diff options
author | Dave Airlie <airlied@redhat.com> | 2020-02-28 16:21:14 +1000 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2020-02-28 16:22:41 +1000 |
commit | 60347451ddb0646c1a9cc5b9581e5bcf648ad1aa (patch) | |
tree | 73cd9298b66b4a84b0e3f02346202f905f5840bd /include/drm | |
parent | a2ae604da74dcf9ae674d3c03efad80574952800 (diff) | |
parent | 18b39fb975b79d6526449ca7c8ab504bc92e2825 (diff) | |
download | linux-60347451ddb0646c1a9cc5b9581e5bcf648ad1aa.tar.gz linux-60347451ddb0646c1a9cc5b9581e5bcf648ad1aa.tar.bz2 linux-60347451ddb0646c1a9cc5b9581e5bcf648ad1aa.zip |
Merge tag 'drm-misc-next-2020-02-27' of git://anongit.freedesktop.org/drm/drm-misc into drm-next
drm-misc-next for 5.7
UAPI Changes:
Cross-subsystem Changes:
Core Changes:
- bridge: huge rework to get rid of omap_dss custom display drivers
Driver Changes:
- hisilicon: some fixes related to modes it can deal with / default to
- virtio: shmem and gpu context fixes and enhancements
- sun4i: Support for LVDS on the A33
Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Maxime Ripard <maxime@cerno.tech>
Link: https://patchwork.freedesktop.org/patch/msgid/20200227113222.cdwzy4cvcqjtbmou@gilmour.lan
Diffstat (limited to 'include/drm')
-rw-r--r-- | include/drm/drm_bridge.h | 237 | ||||
-rw-r--r-- | include/drm/drm_bridge_connector.h | 18 | ||||
-rw-r--r-- | include/drm/drm_connector.h | 9 | ||||
-rw-r--r-- | include/drm/drm_encoder.h | 3 |
4 files changed, 256 insertions, 11 deletions
diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h index 999faaaab9a1..ea2aa5ebae34 100644 --- a/include/drm/drm_bridge.h +++ b/include/drm/drm_bridge.h @@ -23,8 +23,9 @@ #ifndef __DRM_BRIDGE_H__ #define __DRM_BRIDGE_H__ -#include <linux/list.h> #include <linux/ctype.h> +#include <linux/list.h> +#include <linux/mutex.h> #include <drm/drm_atomic.h> #include <drm/drm_encoder.h> @@ -33,7 +34,21 @@ struct drm_bridge; struct drm_bridge_timings; +struct drm_connector; struct drm_panel; +struct edid; +struct i2c_adapter; + +/** + * enum drm_bridge_attach_flags - Flags for &drm_bridge_funcs.attach + */ +enum drm_bridge_attach_flags { + /** + * @DRM_BRIDGE_ATTACH_NO_CONNECTOR: When this flag is set the bridge + * shall not create a drm_connector. + */ + DRM_BRIDGE_ATTACH_NO_CONNECTOR = BIT(0), +}; /** * struct drm_bridge_funcs - drm_bridge control functions @@ -43,7 +58,8 @@ struct drm_bridge_funcs { * @attach: * * This callback is invoked whenever our bridge is being attached to a - * &drm_encoder. + * &drm_encoder. The flags argument tunes the behaviour of the attach + * operation (see DRM_BRIDGE_ATTACH_*). * * The @attach callback is optional. * @@ -51,7 +67,8 @@ struct drm_bridge_funcs { * * Zero on success, error code on failure. */ - int (*attach)(struct drm_bridge *bridge); + int (*attach)(struct drm_bridge *bridge, + enum drm_bridge_attach_flags flags); /** * @detach: @@ -349,9 +366,11 @@ struct drm_bridge_funcs { * Duplicate the current bridge state object (which is guaranteed to be * non-NULL). * - * The atomic_duplicate_state() hook is optional. When not implemented - * the core allocates a drm_bridge_state object and calls - * __drm_atomic_helper_bridge_duplicate_state() to initialize it. + * The atomic_duplicate_state hook is mandatory if the bridge + * implements any of the atomic hooks, and should be left unassigned + * otherwise. For bridges that don't subclass &drm_bridge_state, the + * drm_atomic_helper_bridge_duplicate_state() helper function shall be + * used to implement this hook. * * RETURNS: * A valid drm_bridge_state object or NULL if the allocation fails. @@ -364,8 +383,11 @@ struct drm_bridge_funcs { * Destroy a bridge state object previously allocated by * &drm_bridge_funcs.atomic_duplicate_state(). * - * The atomic_destroy_state hook is optional. When not implemented the - * core calls kfree() on the state. + * The atomic_destroy_state hook is mandatory if the bridge implements + * any of the atomic hooks, and should be left unassigned otherwise. + * For bridges that don't subclass &drm_bridge_state, the + * drm_atomic_helper_bridge_destroy_state() helper function shall be + * used to implement this hook. */ void (*atomic_destroy_state)(struct drm_bridge *bridge, struct drm_bridge_state *state); @@ -474,7 +496,10 @@ struct drm_bridge_funcs { * This function is called at attach time. * * The atomic_reset hook is mandatory if the bridge implements any of - * the atomic hooks, and should be left unassigned otherwise. + * the atomic hooks, and should be left unassigned otherwise. For + * bridges that don't subclass &drm_bridge_state, the + * drm_atomic_helper_bridge_reset() helper function shall be used to + * implement this hook. * * Note that the atomic_reset() semantics is not exactly matching the * reset() semantics found on other components (connector, plane, ...). @@ -489,6 +514,119 @@ struct drm_bridge_funcs { * giving the reason of the failure otherwise. */ struct drm_bridge_state *(*atomic_reset)(struct drm_bridge *bridge); + + /** + * @detect: + * + * Check if anything is attached to the bridge output. + * + * This callback is optional, if not implemented the bridge will be + * considered as always having a component attached to its output. + * Bridges that implement this callback shall set the + * DRM_BRIDGE_OP_DETECT flag in their &drm_bridge->ops. + * + * RETURNS: + * + * drm_connector_status indicating the bridge output status. + */ + enum drm_connector_status (*detect)(struct drm_bridge *bridge); + + /** + * @get_modes: + * + * Fill all modes currently valid for the sink into the &drm_connector + * with drm_mode_probed_add(). + * + * The @get_modes callback is mostly intended to support non-probeable + * displays such as many fixed panels. Bridges that support reading + * EDID shall leave @get_modes unimplemented and implement the + * &drm_bridge_funcs->get_edid callback instead. + * + * This callback is optional. Bridges that implement it shall set the + * DRM_BRIDGE_OP_MODES flag in their &drm_bridge->ops. + * + * The connector parameter shall be used for the sole purpose of + * filling modes, and shall not be stored internally by bridge drivers + * for future usage. + * + * RETURNS: + * + * The number of modes added by calling drm_mode_probed_add(). + */ + int (*get_modes)(struct drm_bridge *bridge, + struct drm_connector *connector); + + /** + * @get_edid: + * + * Read and parse the EDID data of the connected display. + * + * The @get_edid callback is the preferred way of reporting mode + * information for a display connected to the bridge output. Bridges + * that support reading EDID shall implement this callback and leave + * the @get_modes callback unimplemented. + * + * The caller of this operation shall first verify the output + * connection status and refrain from reading EDID from a disconnected + * output. + * + * This callback is optional. Bridges that implement it shall set the + * DRM_BRIDGE_OP_EDID flag in their &drm_bridge->ops. + * + * The connector parameter shall be used for the sole purpose of EDID + * retrieval and parsing, and shall not be stored internally by bridge + * drivers for future usage. + * + * RETURNS: + * + * An edid structure newly allocated with kmalloc() (or similar) on + * success, or NULL otherwise. The caller is responsible for freeing + * the returned edid structure with kfree(). + */ + struct edid *(*get_edid)(struct drm_bridge *bridge, + struct drm_connector *connector); + + /** + * @hpd_notify: + * + * Notify the bridge of hot plug detection. + * + * This callback is optional, it may be implemented by bridges that + * need to be notified of display connection or disconnection for + * internal reasons. One use case is to reset the internal state of CEC + * controllers for HDMI bridges. + */ + void (*hpd_notify)(struct drm_bridge *bridge, + enum drm_connector_status status); + + /** + * @hpd_enable: + * + * Enable hot plug detection. From now on the bridge shall call + * drm_bridge_hpd_notify() each time a change is detected in the output + * connection status, until hot plug detection gets disabled with + * @hpd_disable. + * + * This callback is optional and shall only be implemented by bridges + * that support hot-plug notification without polling. Bridges that + * implement it shall also implement the @hpd_disable callback and set + * the DRM_BRIDGE_OP_HPD flag in their &drm_bridge->ops. + */ + void (*hpd_enable)(struct drm_bridge *bridge); + + /** + * @hpd_disable: + * + * Disable hot plug detection. Once this function returns the bridge + * shall not call drm_bridge_hpd_notify() when a change in the output + * connection status occurs. + * + * This callback is optional and shall only be implemented by bridges + * that support hot-plug notification without polling. Bridges that + * implement it shall also implement the @hpd_enable callback and set + * the DRM_BRIDGE_OP_HPD flag in their &drm_bridge->ops. + */ + void (*hpd_disable)(struct drm_bridge *bridge); }; /** @@ -528,6 +666,39 @@ struct drm_bridge_timings { }; /** + * enum drm_bridge_ops - Bitmask of operations supported by the bridge + */ +enum drm_bridge_ops { + /** + * @DRM_BRIDGE_OP_DETECT: The bridge can detect displays connected to + * its output. Bridges that set this flag shall implement the + * &drm_bridge_funcs->detect callback. + */ + DRM_BRIDGE_OP_DETECT = BIT(0), + /** + * @DRM_BRIDGE_OP_EDID: The bridge can retrieve the EDID of the display + * connected to its output. Bridges that set this flag shall implement + * the &drm_bridge_funcs->get_edid callback. + */ + DRM_BRIDGE_OP_EDID = BIT(1), + /** + * @DRM_BRIDGE_OP_HPD: The bridge can detect hot-plug and hot-unplug + * without requiring polling. Bridges that set this flag shall + * implement the &drm_bridge_funcs->hpd_enable and + * &drm_bridge_funcs->hpd_disable callbacks if they support enabling + * and disabling hot-plug detection dynamically. + */ + DRM_BRIDGE_OP_HPD = BIT(2), + /** + * @DRM_BRIDGE_OP_MODES: The bridge can retrieve the modes supported + * by the display at its output. This does not include reading EDID + * which is separately covered by @DRM_BRIDGE_OP_EDID. Bridges that set + * this flag shall implement the &drm_bridge_funcs->get_modes callback. + */ + DRM_BRIDGE_OP_MODES = BIT(3), +}; + +/** * struct drm_bridge - central DRM bridge control structure */ struct drm_bridge { @@ -555,6 +726,38 @@ struct drm_bridge { const struct drm_bridge_funcs *funcs; /** @driver_private: pointer to the bridge driver's internal context */ void *driver_private; + /** @ops: bitmask of operations supported by the bridge */ + enum drm_bridge_ops ops; + /** + * @type: Type of the connection at the bridge output + * (DRM_MODE_CONNECTOR_*). For bridges at the end of this chain this + * identifies the type of connected display. + */ + int type; + /** + * @interlace_allowed: Indicate that the bridge can handle interlaced + * modes. + */ + bool interlace_allowed; + /** + * @ddc: Associated I2C adapter for DDC access, if any. + */ + struct i2c_adapter *ddc; + /** private: */ + /** + * @hpd_mutex: Protects the @hpd_cb and @hpd_data fields. + */ + struct mutex hpd_mutex; + /** + * @hpd_cb: Hot plug detection callback, registered with + * drm_bridge_hpd_enable(). + */ + void (*hpd_cb)(void *data, enum drm_connector_status status); + /** + * @hpd_data: Private data passed to the Hot plug detection callback + * @hpd_cb. + */ + void *hpd_data; }; static inline struct drm_bridge * @@ -567,7 +770,8 @@ void drm_bridge_add(struct drm_bridge *bridge); void drm_bridge_remove(struct drm_bridge *bridge); struct drm_bridge *of_drm_find_bridge(struct device_node *np); int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge *bridge, - struct drm_bridge *previous); + struct drm_bridge *previous, + enum drm_bridge_attach_flags flags); /** * drm_bridge_get_next_bridge() - Get the next bridge in the chain @@ -661,6 +865,19 @@ drm_atomic_helper_bridge_propagate_bus_fmt(struct drm_bridge *bridge, u32 output_fmt, unsigned int *num_input_fmts); +enum drm_connector_status drm_bridge_detect(struct drm_bridge *bridge); +int drm_bridge_get_modes(struct drm_bridge *bridge, + struct drm_connector *connector); +struct edid *drm_bridge_get_edid(struct drm_bridge *bridge, + struct drm_connector *connector); +void drm_bridge_hpd_enable(struct drm_bridge *bridge, + void (*cb)(void *data, + enum drm_connector_status status), + void *data); +void drm_bridge_hpd_disable(struct drm_bridge *bridge); +void drm_bridge_hpd_notify(struct drm_bridge *bridge, + enum drm_connector_status status); + #ifdef CONFIG_DRM_PANEL_BRIDGE struct drm_bridge *drm_panel_bridge_add(struct drm_panel *panel); struct drm_bridge *drm_panel_bridge_add_typed(struct drm_panel *panel, diff --git a/include/drm/drm_bridge_connector.h b/include/drm/drm_bridge_connector.h new file mode 100644 index 000000000000..33f6c3bbdb4a --- /dev/null +++ b/include/drm/drm_bridge_connector.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2019 Laurent Pinchart <laurent.pinchart@ideasonboard.com> + */ + +#ifndef __DRM_BRIDGE_CONNECTOR_H__ +#define __DRM_BRIDGE_CONNECTOR_H__ + +struct drm_connector; +struct drm_device; +struct drm_encoder; + +void drm_bridge_connector_enable_hpd(struct drm_connector *connector); +void drm_bridge_connector_disable_hpd(struct drm_connector *connector); +struct drm_connector *drm_bridge_connector_init(struct drm_device *drm, + struct drm_encoder *encoder); + +#endif /* __DRM_BRIDGE_CONNECTOR_H__ */ diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index b3815371c271..0df7a95ca5d9 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -435,6 +435,14 @@ struct drm_display_info { bool dvi_dual; /** + * @is_hdmi: True if the sink is an HDMI device. + * + * This field shall be used instead of calling + * drm_detect_hdmi_monitor() when possible. + */ + bool is_hdmi; + + /** * @has_hdmi_infoframe: Does the sink support the HDMI infoframe? */ bool has_hdmi_infoframe; @@ -1518,6 +1526,7 @@ drm_connector_is_unregistered(struct drm_connector *connector) DRM_CONNECTOR_UNREGISTERED; } +const char *drm_get_connector_type_name(unsigned int connector_type); const char *drm_get_connector_status_name(enum drm_connector_status status); const char *drm_get_subpixel_order_name(enum subpixel_order order); const char *drm_get_dpms_name(int val); diff --git a/include/drm/drm_encoder.h b/include/drm/drm_encoder.h index 5623994b6e9e..4370e039c015 100644 --- a/include/drm/drm_encoder.h +++ b/include/drm/drm_encoder.h @@ -174,7 +174,8 @@ struct drm_encoder { struct drm_crtc *crtc; /** - * @bridge_chain: Bridges attached to this encoder. + * @bridge_chain: Bridges attached to this encoder. Drivers shall not + * access this field directly. */ struct list_head bridge_chain; |