Rather than inventing a wrapper to acpi_video_get_edid() use the one provided by drm. This fixes two problems: 1. A memory leak that the memory provided by the ACPI call was never freed. 2. Validation of the BIOS provided blob. Convert the usage in nouveau_connector_detect_lvds() to use struct drm_edid at the same time. Signed-off-by: Mario Limonciello <mario.limonciello@xxxxxxx> --- drivers/gpu/drm/nouveau/nouveau_acpi.c | 27 ---------------- drivers/gpu/drm/nouveau/nouveau_acpi.h | 2 -- drivers/gpu/drm/nouveau/nouveau_connector.c | 35 +++++++++------------ 3 files changed, 14 insertions(+), 50 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c index 8f0c69aad248..de9daafb3fbb 100644 --- a/drivers/gpu/drm/nouveau/nouveau_acpi.c +++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c @@ -360,33 +360,6 @@ void nouveau_unregister_dsm_handler(void) {} void nouveau_switcheroo_optimus_dsm(void) {} #endif -void * -nouveau_acpi_edid(struct drm_device *dev, struct drm_connector *connector) -{ - struct acpi_device *acpidev; - int type, ret; - void *edid; - - switch (connector->connector_type) { - case DRM_MODE_CONNECTOR_LVDS: - case DRM_MODE_CONNECTOR_eDP: - type = ACPI_VIDEO_DISPLAY_LCD; - break; - default: - return NULL; - } - - acpidev = ACPI_COMPANION(dev->dev); - if (!acpidev) - return NULL; - - ret = acpi_video_get_edid(acpidev, type, -1, &edid); - if (ret < 0) - return NULL; - - return kmemdup(edid, EDID_LENGTH, GFP_KERNEL); -} - bool nouveau_acpi_video_backlight_use_native(void) { return acpi_video_backlight_use_native(); diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.h b/drivers/gpu/drm/nouveau/nouveau_acpi.h index e39dd8b94b8b..6a3def8e6cca 100644 --- a/drivers/gpu/drm/nouveau/nouveau_acpi.h +++ b/drivers/gpu/drm/nouveau/nouveau_acpi.h @@ -10,7 +10,6 @@ bool nouveau_is_v1_dsm(void); void nouveau_register_dsm_handler(void); void nouveau_unregister_dsm_handler(void); void nouveau_switcheroo_optimus_dsm(void); -void *nouveau_acpi_edid(struct drm_device *, struct drm_connector *); bool nouveau_acpi_video_backlight_use_native(void); void nouveau_acpi_video_register_backlight(void); #else @@ -19,7 +18,6 @@ static inline bool nouveau_is_v1_dsm(void) { return false; }; static inline void nouveau_register_dsm_handler(void) {} static inline void nouveau_unregister_dsm_handler(void) {} static inline void nouveau_switcheroo_optimus_dsm(void) {} -static inline void *nouveau_acpi_edid(struct drm_device *dev, struct drm_connector *connector) { return NULL; } static inline bool nouveau_acpi_video_backlight_use_native(void) { return true; } static inline void nouveau_acpi_video_register_backlight(void) {} #endif diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index 856b3ef5edb8..492035dc8453 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -687,22 +687,13 @@ nouveau_connector_detect_lvds(struct drm_connector *connector, bool force) struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_connector *nv_connector = nouveau_connector(connector); struct nouveau_encoder *nv_encoder = NULL; - struct edid *edid = NULL; + const struct drm_edid *drm_edid = NULL; enum drm_connector_status status = connector_status_disconnected; nv_encoder = find_encoder(connector, DCB_OUTPUT_LVDS); if (!nv_encoder) goto out; - /* Try retrieving EDID via DDC */ - if (!drm->vbios.fp_no_ddc) { - status = nouveau_connector_detect(connector, force); - if (status == connector_status_connected) { - edid = nv_connector->edid; - goto out; - } - } - /* On some laptops (Sony, i'm looking at you) there appears to * be no direct way of accessing the panel's EDID. The only * option available to us appears to be to ask ACPI for help.. @@ -712,10 +703,14 @@ nouveau_connector_detect_lvds(struct drm_connector *connector, bool force) * the nouveau decides an entry in the VBIOS FP mode table is * valid - it's not (rh#613284) */ - if (nv_encoder->dcb->lvdsconf.use_acpi_for_edid) { - edid = nouveau_acpi_edid(dev, connector); - if (edid) { - status = connector_status_connected; + if (nv_encoder->dcb->lvdsconf.use_acpi_for_edid) + connector->acpi_edid_allowed = true; + + /* Try retrieving EDID via BIOS or DDC */ + if (!drm->vbios.fp_no_ddc || nv_encoder->dcb->lvdsconf.use_acpi_for_edid) { + status = nouveau_connector_detect(connector, force); + if (status == connector_status_connected) { + drm_edid = drm_edid_alloc(nv_connector->edid, EDID_LENGTH); goto out; } } @@ -734,12 +729,9 @@ nouveau_connector_detect_lvds(struct drm_connector *connector, bool force) * stored for the panel stored in them. */ if (!drm->vbios.fp_no_ddc) { - edid = (struct edid *)nouveau_bios_embedded_edid(dev); - if (edid) { - edid = kmemdup(edid, EDID_LENGTH, GFP_KERNEL); - if (edid) - status = connector_status_connected; - } + drm_edid = drm_edid_alloc(nouveau_bios_embedded_edid(dev), EDID_LENGTH); + if (drm_edid) + status = connector_status_connected; } out: @@ -750,7 +742,8 @@ nouveau_connector_detect_lvds(struct drm_connector *connector, bool force) status = connector_status_unknown; #endif - nouveau_connector_set_edid(nv_connector, edid); + drm_edid_connector_update(connector, drm_edid); + drm_edid_free(drm_edid); if (nv_encoder) nouveau_connector_set_encoder(connector, nv_encoder); return status; -- 2.34.1