aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Skeggs <[email protected]>2022-06-01 20:46:34 +1000
committerBen Skeggs <[email protected]>2022-11-09 10:43:10 +1000
commit016dacb60e6d4b301c5941a0dedb49d337926832 (patch)
treee1ba6b0ad9521ebea08b39bb1a85d0c7d7b87288
parentd62f8e982cb857f451a9055d8cc446b1212a6500 (diff)
drm/nouveau/kms: pass event mask to hpd handler
Will be moving the DP link status check / re-train here so it's safe from racing with modeset routing changes. MST message handling etc. will remain where it is. Signed-off-by: Ben Skeggs <[email protected]> Reviewed-by: Lyude Paul <[email protected]>
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_connector.c11
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_connector.h3
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_display.c20
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_dp.c12
4 files changed, 29 insertions, 17 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
index c2ff8e91d90d..bbd17ee60853 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
@@ -1162,14 +1162,15 @@ nouveau_connector_funcs_lvds = {
};
void
-nouveau_connector_hpd(struct drm_connector *connector)
+nouveau_connector_hpd(struct nouveau_connector *nv_connector, u64 bits)
{
- struct nouveau_drm *drm = nouveau_drm(connector->dev);
- u32 mask = drm_connector_mask(connector);
+ struct nouveau_drm *drm = nouveau_drm(nv_connector->base.dev);
+ u32 mask = drm_connector_mask(&nv_connector->base);
unsigned long flags;
spin_lock_irqsave(&drm->hpd_lock, flags);
if (!(drm->hpd_pending & mask)) {
+ nv_connector->hpd_pending |= bits;
drm->hpd_pending |= mask;
schedule_work(&drm->hpd_work);
}
@@ -1185,15 +1186,13 @@ nouveau_connector_hotplug(struct nvif_notify *notify)
struct drm_device *dev = connector->dev;
struct nouveau_drm *drm = nouveau_drm(dev);
const struct nvif_notify_conn_rep_v0 *rep = notify->data;
- bool plugged = (rep->mask != NVIF_NOTIFY_CONN_V0_UNPLUG);
if (rep->mask & NVIF_NOTIFY_CONN_V0_IRQ) {
nouveau_dp_irq(drm, nv_connector);
return NVIF_NOTIFY_KEEP;
}
- NV_DEBUG(drm, "%splugged %s\n", plugged ? "" : "un", connector->name);
- nouveau_connector_hpd(connector);
+ nouveau_connector_hpd(nv_connector, rep->mask);
return NVIF_NOTIFY_KEEP;
}
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.h b/drivers/gpu/drm/nouveau/nouveau_connector.h
index f4e17ff68bf9..1bbf8bf6ba44 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.h
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.h
@@ -124,6 +124,7 @@ struct nouveau_connector {
u8 *dcb;
struct nvif_conn conn;
+ u64 hpd_pending;
struct nvif_notify hpd;
struct drm_dp_aux aux;
@@ -198,7 +199,7 @@ nouveau_crtc_connector_get(struct nouveau_crtc *nv_crtc)
struct drm_connector *
nouveau_connector_create(struct drm_device *, const struct dcb_output *);
-void nouveau_connector_hpd(struct drm_connector *connector);
+void nouveau_connector_hpd(struct nouveau_connector *, u64 bits);
extern int nouveau_tv_disable;
extern int nouveau_ignorelid;
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c
index fb22ebed5424..a21dc2a0f92b 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -488,14 +488,28 @@ nouveau_display_hpd_work(struct work_struct *work)
drm_connector_list_iter_begin(dev, &conn_iter);
nouveau_for_each_non_mst_connector_iter(connector, &conn_iter) {
+ struct nouveau_connector *nv_connector = nouveau_connector(connector);
enum drm_connector_status old_status = connector->status;
- u64 old_epoch_counter = connector->epoch_counter;
+ u64 bits, old_epoch_counter = connector->epoch_counter;
if (!(pending & drm_connector_mask(connector)))
continue;
- connector->status = drm_helper_probe_detect(connector, NULL,
- false);
+ spin_lock_irq(&drm->hpd_lock);
+ bits = nv_connector->hpd_pending;
+ nv_connector->hpd_pending = 0;
+ spin_unlock_irq(&drm->hpd_lock);
+
+ drm_dbg_kms(dev, "[CONNECTOR:%d:%s] plug:%d unplug:%d irq:%d\n",
+ connector->base.id, connector->name,
+ !!(bits & NVIF_NOTIFY_CONN_V0_PLUG),
+ !!(bits & NVIF_NOTIFY_CONN_V0_UNPLUG),
+ !!(bits & NVIF_NOTIFY_CONN_V0_IRQ));
+
+ if (bits & NVIF_NOTIFY_CONN_V0_IRQ)
+ continue;
+
+ connector->status = drm_helper_probe_detect(connector, NULL, false);
if (old_epoch_counter == connector->epoch_counter)
continue;
diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c
index b7104e676eb2..d349dc24a003 100644
--- a/drivers/gpu/drm/nouveau/nouveau_dp.c
+++ b/drivers/gpu/drm/nouveau/nouveau_dp.c
@@ -29,8 +29,7 @@
#include "nouveau_encoder.h"
#include "nouveau_crtc.h"
-#include <nvif/class.h>
-#include <nvif/cl5070.h>
+#include <nvif/event.h>
MODULE_PARM_DESC(mst, "Enable DisplayPort multi-stream (default: enabled)");
static int nouveau_mst = 1;
@@ -218,8 +217,8 @@ void nouveau_dp_irq(struct nouveau_drm *drm,
struct drm_connector *connector = &nv_connector->base;
struct nouveau_encoder *outp = find_encoder(connector, DCB_OUTPUT_DP);
struct nv50_mstm *mstm;
+ u64 hpd = 0;
int ret;
- bool send_hpd = false;
if (!outp)
return;
@@ -231,14 +230,14 @@ void nouveau_dp_irq(struct nouveau_drm *drm,
if (mstm && mstm->is_mst) {
if (!nv50_mstm_service(drm, nv_connector, mstm))
- send_hpd = true;
+ hpd |= NVIF_NOTIFY_CONN_V0_UNPLUG;
} else {
drm_dp_cec_irq(&nv_connector->aux);
if (nouveau_dp_has_sink_count(connector, outp)) {
ret = drm_dp_read_sink_count(&nv_connector->aux);
if (ret != outp->dp.sink_count)
- send_hpd = true;
+ hpd |= NVIF_NOTIFY_CONN_V0_PLUG;
if (ret >= 0)
outp->dp.sink_count = ret;
}
@@ -246,8 +245,7 @@ void nouveau_dp_irq(struct nouveau_drm *drm,
mutex_unlock(&outp->dp.hpd_irq_lock);
- if (send_hpd)
- nouveau_connector_hpd(connector);
+ nouveau_connector_hpd(nv_connector, NVIF_NOTIFY_CONN_V0_IRQ | hpd);
}
/* TODO: