diff options
Diffstat (limited to 'drivers/gpu/drm/drm_connector.c')
-rw-r--r-- | drivers/gpu/drm/drm_connector.c | 69 |
1 files changed, 56 insertions, 13 deletions
diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index d877ddc6dc57..00e40a26a800 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -38,7 +38,7 @@ * 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 + * also 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_get() and @@ -129,7 +129,7 @@ EXPORT_SYMBOL(drm_get_connector_type_name); /** * drm_connector_get_cmdline_mode - reads the user's cmdline mode - * @connector: connector to quwery + * @connector: connector to query * * The kernel supports per-connector configuration of its consoles through * use of the video= parameter. This function parses that option and @@ -269,6 +269,7 @@ int drm_connector_init(struct drm_device *dev, INIT_LIST_HEAD(&connector->modes); mutex_init(&connector->mutex); connector->edid_blob_ptr = NULL; + connector->epoch_counter = 0; connector->tile_blob_ptr = NULL; connector->status = connector_status_unknown; connector->display_info.panel_orientation = @@ -953,8 +954,7 @@ static const struct drm_prop_enum_list dp_colorspaces[] = { * connector is linked to. Drivers should never set this property directly, * it is handled by the DRM core by calling the &drm_connector_funcs.dpms * callback. For atomic drivers the remapping to the "ACTIVE" property is - * implemented in the DRM core. This is the only standard connector - * property that userspace can change. + * implemented in the DRM core. * * Note that this property cannot be set through the MODE_ATOMIC ioctl, * userspace must use "ACTIVE" on the CRTC instead. @@ -991,7 +991,7 @@ static const struct drm_prop_enum_list dp_colorspaces[] = { * DP MST sinks), or high-res integrated panels (like dual-link DSI) which * are not gen-locked. Note that for tiled panels which are genlocked, like * dual-link LVDS or dual-link DSI, the driver should try to not expose the - * tiling and virtualize both &drm_crtc and &drm_plane if needed. Drivers + * tiling and virtualise both &drm_crtc and &drm_plane if needed. Drivers * should update this value using drm_connector_set_tile_property(). * Userspace cannot change this property. * link-status: @@ -1000,6 +1000,32 @@ static const struct drm_prop_enum_list dp_colorspaces[] = { * after modeset, the kernel driver may set this to "BAD" and issue a * hotplug uevent. Drivers should update this value using * drm_connector_set_link_status_property(). + * + * When user-space receives the hotplug uevent and detects a "BAD" + * link-status, the sink doesn't receive pixels anymore (e.g. the screen + * becomes completely black). The list of available modes may have + * changed. User-space is expected to pick a new mode if the current one + * has disappeared and perform a new modeset with link-status set to + * "GOOD" to re-enable the connector. + * + * If multiple connectors share the same CRTC and one of them gets a "BAD" + * link-status, the other are unaffected (ie. the sinks still continue to + * receive pixels). + * + * When user-space performs an atomic commit on a connector with a "BAD" + * link-status without resetting the property to "GOOD", the sink may + * still not receive pixels. When user-space performs an atomic commit + * which resets the link-status property to "GOOD" without the + * ALLOW_MODESET flag set, it might fail because a modeset is required. + * + * User-space can only change link-status to "GOOD", changing it to "BAD" + * is a no-op. + * + * For backwards compatibility with non-atomic userspace the kernel + * tries to automatically set the link-status back to "GOOD" in the + * SETCRTC IOCTL. This might fail if the mode is no longer valid, similar + * to how it might fail if a different screen has been connected in the + * interim. * non_desktop: * Indicates the output should be ignored for purposes of displaying a * standard desktop environment or console. This is most likely because @@ -1131,7 +1157,7 @@ static const struct drm_prop_enum_list dp_colorspaces[] = { * * It will even need to do colorspace conversion and get all layers * to one common colorspace for blending. It can use either GL, Media - * or display engine to get this done based on the capabilties of the + * or display engine to get this done based on the capabilities of the * associated hardware. * * Driver expects metadata to be put in &struct hdr_output_metadata @@ -1614,7 +1640,7 @@ EXPORT_SYMBOL(drm_mode_create_scaling_mode_property); * variable refresh rate capability for a connector. * * Returns: - * Zero on success, negative errono on failure. + * Zero on success, negative errno on failure. */ int drm_connector_attach_vrr_capable_property( struct drm_connector *connector) @@ -1759,7 +1785,7 @@ EXPORT_SYMBOL(drm_mode_create_aspect_ratio_property); * HDMI connectors. * * Returns: - * Zero on success, negative errono on failure. + * Zero on success, negative errno on failure. */ int drm_mode_create_hdmi_colorspace_property(struct drm_connector *connector) { @@ -1788,7 +1814,7 @@ EXPORT_SYMBOL(drm_mode_create_hdmi_colorspace_property); * DP connectors. * * Returns: - * Zero on success, negative errono on failure. + * Zero on success, negative errno on failure. */ int drm_mode_create_dp_colorspace_property(struct drm_connector *connector) { @@ -1840,7 +1866,7 @@ EXPORT_SYMBOL(drm_mode_create_content_type_property); * drm_mode_create_suggested_offset_properties - create suggests offset properties * @dev: DRM device * - * Create the the suggested x/y offset property for connectors. + * Create the suggested x/y offset property for connectors. */ int drm_mode_create_suggested_offset_properties(struct drm_device *dev) { @@ -1954,6 +1980,7 @@ int drm_connector_update_edid_property(struct drm_connector *connector, struct drm_device *dev = connector->dev; size_t size = 0; int ret; + const struct edid *old_edid; /* ignore requests to set edid when overridden */ if (connector->override_edid) @@ -1963,7 +1990,7 @@ int drm_connector_update_edid_property(struct drm_connector *connector, size = EDID_LENGTH * (1 + edid->extensions); /* Set the display info, using edid if available, otherwise - * reseting the values to defaults. This duplicates the work + * resetting the values to defaults. This duplicates the work * done in drm_add_edid_modes, but that function is not * consistently called before this one in all drivers and the * computation is cheap enough that it seems better to @@ -1977,6 +2004,20 @@ int drm_connector_update_edid_property(struct drm_connector *connector, drm_update_tile_info(connector, edid); + if (connector->edid_blob_ptr) { + old_edid = (const struct edid *)connector->edid_blob_ptr->data; + if (old_edid) { + if (!drm_edid_are_equal(edid, old_edid)) { + DRM_DEBUG_KMS("[CONNECTOR:%d:%s] Edid was changed.\n", + connector->base.id, connector->name); + + connector->epoch_counter += 1; + DRM_DEBUG_KMS("Updating change counter to %llu\n", + connector->epoch_counter); + } + } + } + drm_object_property_set_value(&connector->base, dev->mode_config.non_desktop_property, connector->display_info.non_desktop); @@ -2076,7 +2117,7 @@ void drm_connector_set_vrr_capable_property( EXPORT_SYMBOL(drm_connector_set_vrr_capable_property); /** - * drm_connector_set_panel_orientation - sets the connecter's panel_orientation + * drm_connector_set_panel_orientation - sets the connector's panel_orientation * @connector: connector for which to set the panel-orientation property. * @panel_orientation: drm_panel_orientation value to set * @@ -2131,7 +2172,7 @@ EXPORT_SYMBOL(drm_connector_set_panel_orientation); /** * drm_connector_set_panel_orientation_with_quirk - - * set the connecter's panel_orientation after checking for quirks + * set the connector's panel_orientation after checking for quirks * @connector: connector for which to init the panel-orientation property. * @panel_orientation: drm_panel_orientation value to set * @width: width in pixels of the panel, used for panel quirk detection @@ -2368,6 +2409,7 @@ static void drm_tile_group_free(struct kref *kref) { struct drm_tile_group *tg = container_of(kref, struct drm_tile_group, refcount); struct drm_device *dev = tg->dev; + mutex_lock(&dev->mode_config.idr_mutex); idr_remove(&dev->mode_config.tile_idr, tg->id); mutex_unlock(&dev->mode_config.idr_mutex); @@ -2403,6 +2445,7 @@ struct drm_tile_group *drm_mode_get_tile_group(struct drm_device *dev, { struct drm_tile_group *tg; int id; + mutex_lock(&dev->mode_config.idr_mutex); idr_for_each_entry(&dev->mode_config.tile_idr, tg, id) { if (!memcmp(tg->group_data, topology, 8)) { |