diff options
-rw-r--r-- | Documentation/gpu/drm-kms.rst | 170 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_connector.c | 33 | ||||
-rw-r--r-- | include/drm/drm_connector.h | 57 |
3 files changed, 94 insertions, 166 deletions
diff --git a/Documentation/gpu/drm-kms.rst b/Documentation/gpu/drm-kms.rst index 6e7ab57924f0..fa948b4e029b 100644 --- a/Documentation/gpu/drm-kms.rst +++ b/Documentation/gpu/drm-kms.rst @@ -110,8 +110,14 @@ Display Modes Function Reference .. kernel-doc:: drivers/gpu/drm/drm_modes.c :export: -Connector Display Sink Abstraction -================================== +Connector Abstraction +===================== + +.. kernel-doc:: drivers/gpu/drm/drm_connector.c + :doc: overview + +Connector Functions Reference +----------------------------- .. kernel-doc:: include/drm/drm_connector.h :internal: @@ -232,166 +238,6 @@ encoders unattached at initialization time. Applications (or the fbdev compatibility layer when implemented) are responsible for attaching the encoders they want to use to a CRTC. -Connectors (:c:type:`struct drm_connector <drm_connector>`) ------------------------------------------------------------ - -A connector is the final destination for pixel data on a device, and -usually connects directly to an external display device like a monitor -or laptop panel. A connector can only be attached to one encoder at a -time. The connector is also the structure where information about the -attached display is kept, so it contains fields for display data, EDID -data, DPMS & connection status, and information about modes supported on -the attached displays. - -Connector Initialization -~~~~~~~~~~~~~~~~~~~~~~~~ - -Finally a KMS driver must create, initialize, register and attach at -least one :c:type:`struct drm_connector <drm_connector>` -instance. The instance is created as other KMS objects and initialized -by setting the following fields. - -interlace_allowed - Whether the connector can handle interlaced modes. - -doublescan_allowed - Whether the connector can handle doublescan. - -display_info - Display information is filled from EDID information when a display - is detected. For non hot-pluggable displays such as flat panels in - embedded systems, the driver should initialize the - display_info.width_mm and display_info.height_mm fields with the - physical size of the display. - -polled - Connector polling mode, a combination of - - DRM_CONNECTOR_POLL_HPD - The connector generates hotplug events and doesn't need to be - periodically polled. The CONNECT and DISCONNECT flags must not - be set together with the HPD flag. - - DRM_CONNECTOR_POLL_CONNECT - Periodically poll the connector for connection. - - DRM_CONNECTOR_POLL_DISCONNECT - Periodically poll the connector for disconnection. - - Set to 0 for connectors that don't support connection status - discovery. - -The connector is then registered with a call to -:c:func:`drm_connector_init()` with a pointer to the connector -functions and a connector type, and exposed through sysfs with a call to -:c:func:`drm_connector_register()`. - -Supported connector types are - -- DRM_MODE_CONNECTOR_VGA -- DRM_MODE_CONNECTOR_DVII -- DRM_MODE_CONNECTOR_DVID -- DRM_MODE_CONNECTOR_DVIA -- DRM_MODE_CONNECTOR_Composite -- DRM_MODE_CONNECTOR_SVIDEO -- DRM_MODE_CONNECTOR_LVDS -- DRM_MODE_CONNECTOR_Component -- DRM_MODE_CONNECTOR_9PinDIN -- DRM_MODE_CONNECTOR_DisplayPort -- DRM_MODE_CONNECTOR_HDMIA -- DRM_MODE_CONNECTOR_HDMIB -- DRM_MODE_CONNECTOR_TV -- DRM_MODE_CONNECTOR_eDP -- DRM_MODE_CONNECTOR_VIRTUAL - -Connectors must be attached to an encoder to be used. For devices that -map connectors to encoders 1:1, the connector should be attached at -initialization time with a call to -:c:func:`drm_mode_connector_attach_encoder()`. The driver must -also set the :c:type:`struct drm_connector <drm_connector>` -encoder field to point to the attached encoder. - -Finally, drivers must initialize the connectors state change detection -with a call to :c:func:`drm_kms_helper_poll_init()`. If at least -one connector is pollable but can't generate hotplug interrupts -(indicated by the DRM_CONNECTOR_POLL_CONNECT and -DRM_CONNECTOR_POLL_DISCONNECT connector flags), a delayed work will -automatically be queued to periodically poll for changes. Connectors -that can generate hotplug interrupts must be marked with the -DRM_CONNECTOR_POLL_HPD flag instead, and their interrupt handler must -call :c:func:`drm_helper_hpd_irq_event()`. The function will -queue a delayed work to check the state of all connectors, but no -periodic polling will be done. - -Connector Operations -~~~~~~~~~~~~~~~~~~~~ - - **Note** - - Unless otherwise state, all operations are mandatory. - -DPMS -'''' - -void (\*dpms)(struct drm_connector \*connector, int mode); -The DPMS operation sets the power state of a connector. The mode -argument is one of - -- DRM_MODE_DPMS_ON - -- DRM_MODE_DPMS_STANDBY - -- DRM_MODE_DPMS_SUSPEND - -- DRM_MODE_DPMS_OFF - -In all but DPMS_ON mode the encoder to which the connector is attached -should put the display in low-power mode by driving its signals -appropriately. If more than one connector is attached to the encoder -care should be taken not to change the power state of other displays as -a side effect. Low-power mode should be propagated to the encoders and -CRTCs when all related connectors are put in low-power mode. - -Modes -''''' - -int (\*fill_modes)(struct drm_connector \*connector, uint32_t -max_width, uint32_t max_height); -Fill the mode list with all supported modes for the connector. If the -``max_width`` and ``max_height`` arguments are non-zero, the -implementation must ignore all modes wider than ``max_width`` or higher -than ``max_height``. - -The connector must also fill in this operation its display_info -width_mm and height_mm fields with the connected display physical size -in millimeters. The fields should be set to 0 if the value isn't known -or is not applicable (for instance for projector devices). - -Connection Status -''''''''''''''''' - -The connection status is updated through polling or hotplug events when -supported (see ?). The status value is reported to userspace through -ioctls and must not be used inside the driver, as it only gets -initialized by a call to :c:func:`drm_mode_getconnector()` from -userspace. - -enum drm_connector_status (\*detect)(struct drm_connector -\*connector, bool force); -Check to see if anything is attached to the connector. The ``force`` -parameter is set to false whilst polling or to true when checking the -connector due to user request. ``force`` can be used by the driver to -avoid expensive, destructive operations during automated probing. - -Return connector_status_connected if something is connected to the -connector, connector_status_disconnected if nothing is connected and -connector_status_unknown if the connection state isn't known. - -Drivers should only return connector_status_connected if the -connection status has really been probed as connected. Connectors that -can't detect the connection status, or failed connection status probes, -should return connector_status_unknown. - Cleanup ------- diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index 99ece6758061..6a0551744d13 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -27,6 +27,37 @@ #include "drm_crtc_internal.h" #include "drm_internal.h" +/** + * DOC: overview + * + * In DRM connectors are the general abstraction for display sinks, and include + * als fixed panels or anything else that can display pixels in some form. As + * opposed to all other KMS objects representing hardware (like CRTC, encoder or + * plane abstractions) connectors can be hotplugged and unplugged at runtime. + * Hence they are reference-counted using drm_connector_reference() and + * drm_connector_unreference(). + * + * KMS driver must create, initialize, register and attach at a struct + * &drm_connector for each such sink. The instance is created as other KMS + * objects and initialized by setting the following fields. + * + * The connector is then registered with a call to drm_connector_init() with a + * pointer to the connector functions and a connector type, and exposed through + * sysfs with a call to drm_connector_register(). + * + * Connectors must be attached to an encoder to be used. For devices that map + * connectors to encoders 1:1, the connector should be attached at + * initialization time with a call to drm_mode_connector_attach_encoder(). The + * driver must also set the struct &drm_connector encoder field to point to the + * attached encoder. + * + * For connectors which are not fixed (like built-in panels) the driver needs to + * support hotplug notifications. The simplest way to do that is by using the + * probe helpers, see drm_kms_helper_poll_init() for connectors which don't have + * hardware support for hotplug interrupts. Connectors with hardware hotplug + * support can instead use e.g. drm_helper_hpd_irq_event(). + */ + struct drm_conn_prop_enum_list { int type; const char *name; @@ -77,7 +108,7 @@ void drm_connector_ida_destroy(void) * drm_connector_get_cmdline_mode - reads the user's cmdline mode * @connector: connector to quwery * - * The kernel supports per-connector configration of its consoles through + * The kernel supports per-connector configuration of its consoles through * use of the video= parameter. This function parses that option and * extracts the user's specified mode (or enable/disable status) for a * particular connector. This is typically only used during the early fbdev diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index ec2bea0b1b38..3537b7d8259b 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -42,9 +42,36 @@ enum drm_connector_force { DRM_FORCE_ON_DIGITAL, /* for DVI-I use digital connector */ }; +/** + * enum drm_connector_status - status for a &drm_connector + * + * This enum is used to track the connector status. There are no separate + * #defines for the uapi! + */ enum drm_connector_status { + /** + * @connector_status_connected: The connector is definitely connected to + * a sink device, and can be enabled. + */ connector_status_connected = 1, + /** + * @connector_status_disconnected: The connector isn't connected to a + * sink device which can be autodetect. For digital outputs like DP or + * HDMI (which can be realiable probed) this means there's really + * nothing there. It is driver-dependent whether a connector with this + * status can be lit up or not. + */ connector_status_disconnected = 2, + /** + * @connector_status_unknown: The connector's status could not be + * reliably detected. This happens when probing would either cause + * flicker (like load-detection when the connector is in use), or when a + * hardware resource isn't available (like when load-detection needs a + * free CRTC). It should be possible to light up the connector with one + * of the listed fallback modes. For default configuration userspace + * should only try to light up connectors with unknown status when + * there's not connector with @connector_status_connected. + */ connector_status_unknown = 3, }; @@ -416,11 +443,9 @@ struct drm_cmdline_mode { * @modes: modes available on this connector (from fill_modes() + user) * @status: one of the drm_connector_status enums (connected, not, or unknown) * @probed_modes: list of modes derived directly from the display - * @display_info: information about attached display (e.g. from EDID) * @funcs: connector control functions * @edid_blob_ptr: DRM property containing EDID if present * @properties: property tracking for this connector - * @polled: a DRM_CONNECTOR_POLL_<foo> value for core driven polling * @dpms: current dpms state * @helper_private: mid-layer private data * @cmdline_mode: mode line parsed from the kernel cmdline for this connector @@ -485,6 +510,13 @@ struct drm_connector { /* these are modes added by probing with DDC or the BIOS */ struct list_head probed_modes; + /** + * @display_info: Display information is filled from EDID information + * when a display is detected. For non hot-pluggable displays such as + * flat panels in embedded systems, the driver should initialize the + * display_info.width_mm and display_info.height_mm fields with the + * physical size of the display. + */ struct drm_display_info display_info; const struct drm_connector_funcs *funcs; @@ -519,7 +551,26 @@ struct drm_connector { /* DACs should rarely do this without a lot of testing */ #define DRM_CONNECTOR_POLL_DISCONNECT (1 << 2) - uint8_t polled; /* DRM_CONNECTOR_POLL_* */ + /** + * @polled: + * + * Connector polling mode, a combination of + * + * DRM_CONNECTOR_POLL_HPD + * The connector generates hotplug events and doesn't need to be + * periodically polled. The CONNECT and DISCONNECT flags must not + * be set together with the HPD flag. + * + * DRM_CONNECTOR_POLL_CONNECT + * Periodically poll the connector for connection. + * + * DRM_CONNECTOR_POLL_DISCONNECT + * Periodically poll the connector for disconnection. + * + * Set to 0 for connectors that don't support connection status + * discovery. + */ + uint8_t polled; /* requested DPMS state */ int dpms; |