Skip to content

Commit f28e32d

Browse files
committed
drm/nouveau/kms: Don't change EDID when it hasn't actually changed
Currently in nouveau_connector_ddc_detect() and nouveau_connector_detect_lvds(), we start the connector probing process by releasing the previous EDID and informing DRM of the change. However, since commit 5186421 ("drm: Introduce epoch counter to drm_connector") drm_connector_update_edid_property() actually checks whether the new EDID we've specified is different from the previous one, and updates the connector's epoch accordingly if it is. But, because we always set the EDID to NULL first in nouveau_connector_ddc_detect() and nouveau_connector_detect_lvds() we end up making DRM think that the EDID changes every single time we do a connector probe - which isn't needed. So, let's fix this by not clearing the EDID at the start of the connector probing process, and instead simply changing or removing it once near the end of the probing process. This will help prevent us from sending unneeded hotplug events to userspace when nothing has actually changed. Signed-off-by: Lyude Paul <[email protected]> Reviewed-by: Ben Skeggs <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent a4efad3 commit f28e32d

File tree

1 file changed

+27
-27
lines changed

1 file changed

+27
-27
lines changed

drivers/gpu/drm/nouveau/nouveau_connector.c

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -528,6 +528,17 @@ nouveau_connector_set_encoder(struct drm_connector *connector,
528528
}
529529
}
530530

531+
static void
532+
nouveau_connector_set_edid(struct nouveau_connector *nv_connector,
533+
struct edid *edid)
534+
{
535+
struct edid *old_edid = nv_connector->edid;
536+
537+
drm_connector_update_edid_property(&nv_connector->base, edid);
538+
kfree(old_edid);
539+
nv_connector->edid = edid;
540+
}
541+
531542
static enum drm_connector_status
532543
nouveau_connector_detect(struct drm_connector *connector, bool force)
533544
{
@@ -541,13 +552,6 @@ nouveau_connector_detect(struct drm_connector *connector, bool force)
541552
int ret;
542553
enum drm_connector_status conn_status = connector_status_disconnected;
543554

544-
/* Cleanup the previous EDID block. */
545-
if (nv_connector->edid) {
546-
drm_connector_update_edid_property(connector, NULL);
547-
kfree(nv_connector->edid);
548-
nv_connector->edid = NULL;
549-
}
550-
551555
/* Outputs are only polled while runtime active, so resuming the
552556
* device here is unnecessary (and would deadlock upon runtime suspend
553557
* because it waits for polling to finish). We do however, want to
@@ -560,22 +564,23 @@ nouveau_connector_detect(struct drm_connector *connector, bool force)
560564
ret = pm_runtime_get_sync(dev->dev);
561565
if (ret < 0 && ret != -EACCES) {
562566
pm_runtime_put_autosuspend(dev->dev);
567+
nouveau_connector_set_edid(nv_connector, NULL);
563568
return conn_status;
564569
}
565570
}
566571

567572
nv_encoder = nouveau_connector_ddc_detect(connector);
568573
if (nv_encoder && (i2c = nv_encoder->i2c) != NULL) {
574+
struct edid *new_edid;
575+
569576
if ((vga_switcheroo_handler_flags() &
570577
VGA_SWITCHEROO_CAN_SWITCH_DDC) &&
571578
nv_connector->type == DCB_CONNECTOR_LVDS)
572-
nv_connector->edid = drm_get_edid_switcheroo(connector,
573-
i2c);
579+
new_edid = drm_get_edid_switcheroo(connector, i2c);
574580
else
575-
nv_connector->edid = drm_get_edid(connector, i2c);
581+
new_edid = drm_get_edid(connector, i2c);
576582

577-
drm_connector_update_edid_property(connector,
578-
nv_connector->edid);
583+
nouveau_connector_set_edid(nv_connector, new_edid);
579584
if (!nv_connector->edid) {
580585
NV_ERROR(drm, "DDC responded, but no EDID for %s\n",
581586
connector->name);
@@ -609,6 +614,8 @@ nouveau_connector_detect(struct drm_connector *connector, bool force)
609614
conn_status = connector_status_connected;
610615
drm_dp_cec_set_edid(&nv_connector->aux, nv_connector->edid);
611616
goto out;
617+
} else {
618+
nouveau_connector_set_edid(nv_connector, NULL);
612619
}
613620

614621
nv_encoder = nouveau_connector_of_detect(connector);
@@ -652,18 +659,12 @@ nouveau_connector_detect_lvds(struct drm_connector *connector, bool force)
652659
struct nouveau_drm *drm = nouveau_drm(dev);
653660
struct nouveau_connector *nv_connector = nouveau_connector(connector);
654661
struct nouveau_encoder *nv_encoder = NULL;
662+
struct edid *edid = NULL;
655663
enum drm_connector_status status = connector_status_disconnected;
656664

657-
/* Cleanup the previous EDID block. */
658-
if (nv_connector->edid) {
659-
drm_connector_update_edid_property(connector, NULL);
660-
kfree(nv_connector->edid);
661-
nv_connector->edid = NULL;
662-
}
663-
664665
nv_encoder = find_encoder(connector, DCB_OUTPUT_LVDS);
665666
if (!nv_encoder)
666-
return connector_status_disconnected;
667+
goto out;
667668

668669
/* Try retrieving EDID via DDC */
669670
if (!drm->vbios.fp_no_ddc) {
@@ -682,7 +683,8 @@ nouveau_connector_detect_lvds(struct drm_connector *connector, bool force)
682683
* valid - it's not (rh#613284)
683684
*/
684685
if (nv_encoder->dcb->lvdsconf.use_acpi_for_edid) {
685-
if ((nv_connector->edid = nouveau_acpi_edid(dev, connector))) {
686+
edid = nouveau_acpi_edid(dev, connector);
687+
if (edid) {
686688
status = connector_status_connected;
687689
goto out;
688690
}
@@ -702,12 +704,10 @@ nouveau_connector_detect_lvds(struct drm_connector *connector, bool force)
702704
* stored for the panel stored in them.
703705
*/
704706
if (!drm->vbios.fp_no_ddc) {
705-
struct edid *edid =
706-
(struct edid *)nouveau_bios_embedded_edid(dev);
707+
edid = (struct edid *)nouveau_bios_embedded_edid(dev);
707708
if (edid) {
708-
nv_connector->edid =
709-
kmemdup(edid, EDID_LENGTH, GFP_KERNEL);
710-
if (nv_connector->edid)
709+
edid = kmemdup(edid, EDID_LENGTH, GFP_KERNEL);
710+
if (edid)
711711
status = connector_status_connected;
712712
}
713713
}
@@ -720,7 +720,7 @@ nouveau_connector_detect_lvds(struct drm_connector *connector, bool force)
720720
status = connector_status_unknown;
721721
#endif
722722

723-
drm_connector_update_edid_property(connector, nv_connector->edid);
723+
nouveau_connector_set_edid(nv_connector, edid);
724724
nouveau_connector_set_encoder(connector, nv_encoder);
725725
return status;
726726
}

0 commit comments

Comments
 (0)