mirror of
https://github.com/FEX-Emu/linux.git
synced 2024-12-28 12:25:31 +00:00
drm: handle override and firmware EDID at drm_do_get_edid() level
Handle debugfs override edid and firmware edid at the low level to transparently and completely replace the real edid. Previously, we practically only used the modes from the override EDID, and none of the other data, such as audio parameters. This change also prevents actual EDID reads when the EDID is to be overridden, but retains the DDC probe. This is useful if the reason for preferring override EDID are problems with reading the data, or corruption of the data. Move firmware EDID loading from helper to core, as the functionality moves to lower level as well. This will result in a change of module parameter from drm_kms_helper.edid_firmware to drm.edid_firmware, which arguably makes more sense anyway. Some future work remains related to override and firmware EDID validation. Like before, no validation is done for override EDID. The firmware EDID is validated separately in the loader. Some unification and deduplication would be in order, to validate all of them at the drm_do_get_edid() level, like "real" EDIDs. v2: move firmware loading to core v3: rebase, commit message refresh Cc: Abdiel Janulgue <abdiel.janulgue@linux.intel.com> Cc: Daniel Vetter <daniel.vetter@ffwll.ch> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com> Tested-by: Abdiel Janulgue <abdiel.janulgue@linux.intel.com> Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Acked-by: Dave Airlie <airlied@gmail.com> Signed-off-by: Jani Nikula <jani.nikula@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/1e8a710bcac46e5136c1a7b430074893c81f364a.1505203831.git.jani.nikula@intel.com
This commit is contained in:
parent
c673fe7f0c
commit
53fd40a90f
@ -854,7 +854,7 @@
|
|||||||
The filter can be disabled or changed to another
|
The filter can be disabled or changed to another
|
||||||
driver later using sysfs.
|
driver later using sysfs.
|
||||||
|
|
||||||
drm_kms_helper.edid_firmware=[<connector>:]<file>[,[<connector>:]<file>]
|
drm.edid_firmware=[<connector>:]<file>[,[<connector>:]<file>]
|
||||||
Broken monitors, graphic adapters, KVMs and EDIDless
|
Broken monitors, graphic adapters, KVMs and EDIDless
|
||||||
panels may send no or incorrect EDID data sets.
|
panels may send no or incorrect EDID data sets.
|
||||||
This parameter allows to specify an EDID data sets
|
This parameter allows to specify an EDID data sets
|
||||||
|
@ -110,7 +110,7 @@ config DRM_FBDEV_OVERALLOC
|
|||||||
|
|
||||||
config DRM_LOAD_EDID_FIRMWARE
|
config DRM_LOAD_EDID_FIRMWARE
|
||||||
bool "Allow to specify an EDID data set instead of probing for it"
|
bool "Allow to specify an EDID data set instead of probing for it"
|
||||||
depends on DRM_KMS_HELPER
|
depends on DRM
|
||||||
help
|
help
|
||||||
Say Y here, if you want to use EDID data to be loaded from the
|
Say Y here, if you want to use EDID data to be loaded from the
|
||||||
/lib/firmware directory or one of the provided built-in
|
/lib/firmware directory or one of the provided built-in
|
||||||
|
@ -28,6 +28,7 @@ drm-$(CONFIG_DRM_PANEL) += drm_panel.o
|
|||||||
drm-$(CONFIG_OF) += drm_of.o
|
drm-$(CONFIG_OF) += drm_of.o
|
||||||
drm-$(CONFIG_AGP) += drm_agpsupport.o
|
drm-$(CONFIG_AGP) += drm_agpsupport.o
|
||||||
drm-$(CONFIG_DEBUG_FS) += drm_debugfs.o drm_debugfs_crc.o
|
drm-$(CONFIG_DEBUG_FS) += drm_debugfs.o drm_debugfs_crc.o
|
||||||
|
drm-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o
|
||||||
|
|
||||||
drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o drm_probe_helper.o \
|
drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o drm_probe_helper.o \
|
||||||
drm_plane_helper.o drm_dp_mst_topology.o drm_atomic_helper.o \
|
drm_plane_helper.o drm_dp_mst_topology.o drm_atomic_helper.o \
|
||||||
@ -36,7 +37,6 @@ drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o drm_probe_helper.o \
|
|||||||
drm_scdc_helper.o drm_gem_framebuffer_helper.o
|
drm_scdc_helper.o drm_gem_framebuffer_helper.o
|
||||||
|
|
||||||
drm_kms_helper-$(CONFIG_DRM_PANEL_BRIDGE) += bridge/panel.o
|
drm_kms_helper-$(CONFIG_DRM_PANEL_BRIDGE) += bridge/panel.o
|
||||||
drm_kms_helper-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o
|
|
||||||
drm_kms_helper-$(CONFIG_DRM_FBDEV_EMULATION) += drm_fb_helper.o
|
drm_kms_helper-$(CONFIG_DRM_FBDEV_EMULATION) += drm_fb_helper.o
|
||||||
drm_kms_helper-$(CONFIG_DRM_KMS_CMA_HELPER) += drm_fb_cma_helper.o
|
drm_kms_helper-$(CONFIG_DRM_KMS_CMA_HELPER) += drm_fb_cma_helper.o
|
||||||
drm_kms_helper-$(CONFIG_DRM_DP_AUX_CHARDEV) += drm_dp_aux_dev.o
|
drm_kms_helper-$(CONFIG_DRM_DP_AUX_CHARDEV) += drm_dp_aux_dev.o
|
||||||
|
@ -1533,6 +1533,10 @@ static void connector_bad_edid(struct drm_connector *connector,
|
|||||||
* level, drivers must make all reasonable efforts to expose it as an I2C
|
* level, drivers must make all reasonable efforts to expose it as an I2C
|
||||||
* adapter and use drm_get_edid() instead of abusing this function.
|
* adapter and use drm_get_edid() instead of abusing this function.
|
||||||
*
|
*
|
||||||
|
* The EDID may be overridden using debugfs override_edid or firmare EDID
|
||||||
|
* (drm_load_edid_firmware() and drm.edid_firmware parameter), in this priority
|
||||||
|
* order. Having either of them bypasses actual EDID reads.
|
||||||
|
*
|
||||||
* Return: Pointer to valid EDID or NULL if we couldn't find any.
|
* Return: Pointer to valid EDID or NULL if we couldn't find any.
|
||||||
*/
|
*/
|
||||||
struct edid *drm_do_get_edid(struct drm_connector *connector,
|
struct edid *drm_do_get_edid(struct drm_connector *connector,
|
||||||
@ -1542,6 +1546,17 @@ struct edid *drm_do_get_edid(struct drm_connector *connector,
|
|||||||
{
|
{
|
||||||
int i, j = 0, valid_extensions = 0;
|
int i, j = 0, valid_extensions = 0;
|
||||||
u8 *edid, *new;
|
u8 *edid, *new;
|
||||||
|
struct edid *override = NULL;
|
||||||
|
|
||||||
|
if (connector->override_edid)
|
||||||
|
override = drm_edid_duplicate((const struct edid *)
|
||||||
|
connector->edid_blob_ptr->data);
|
||||||
|
|
||||||
|
if (!override)
|
||||||
|
override = drm_load_edid_firmware(connector);
|
||||||
|
|
||||||
|
if (!IS_ERR_OR_NULL(override))
|
||||||
|
return override;
|
||||||
|
|
||||||
if ((edid = kmalloc(EDID_LENGTH, GFP_KERNEL)) == NULL)
|
if ((edid = kmalloc(EDID_LENGTH, GFP_KERNEL)) == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -353,8 +353,6 @@ EXPORT_SYMBOL(drm_helper_probe_detect);
|
|||||||
* drm_mode_probed_add(). New modes start their life with status as OK.
|
* drm_mode_probed_add(). New modes start their life with status as OK.
|
||||||
* Modes are added from a single source using the following priority order.
|
* Modes are added from a single source using the following priority order.
|
||||||
*
|
*
|
||||||
* - debugfs 'override_edid' (used for testing only)
|
|
||||||
* - firmware EDID (drm_load_edid_firmware())
|
|
||||||
* - &drm_connector_helper_funcs.get_modes vfunc
|
* - &drm_connector_helper_funcs.get_modes vfunc
|
||||||
* - if the connector status is connector_status_connected, standard
|
* - if the connector status is connector_status_connected, standard
|
||||||
* VESA DMT modes up to 1024x768 are automatically added
|
* VESA DMT modes up to 1024x768 are automatically added
|
||||||
@ -483,22 +481,7 @@ retry:
|
|||||||
goto prune;
|
goto prune;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (connector->override_edid) {
|
count = (*connector_funcs->get_modes)(connector);
|
||||||
struct edid *edid = (struct edid *) connector->edid_blob_ptr->data;
|
|
||||||
|
|
||||||
count = drm_add_edid_modes(connector, edid);
|
|
||||||
drm_edid_to_eld(connector, edid);
|
|
||||||
} else {
|
|
||||||
struct edid *edid = drm_load_edid_firmware(connector);
|
|
||||||
if (!IS_ERR_OR_NULL(edid)) {
|
|
||||||
drm_mode_connector_update_edid_property(connector, edid);
|
|
||||||
count = drm_add_edid_modes(connector, edid);
|
|
||||||
drm_edid_to_eld(connector, edid);
|
|
||||||
kfree(edid);
|
|
||||||
}
|
|
||||||
if (count == 0)
|
|
||||||
count = (*connector_funcs->get_modes)(connector);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count == 0 && connector->status == connector_status_connected)
|
if (count == 0 && connector->status == connector_status_connected)
|
||||||
count = drm_add_modes_noedid(connector, 1024, 768);
|
count = drm_add_modes_noedid(connector, 1024, 768);
|
||||||
|
Loading…
Reference in New Issue
Block a user