summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/nouveau/nouveau_dp.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/nouveau/nouveau_dp.c')
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_dp.c40
1 files changed, 29 insertions, 11 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c
index 20db8ea1a0ba..e00876f92aee 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/if0011.h>
MODULE_PARM_DESC(mst, "Enable DisplayPort multi-stream (default: enabled)");
static int nouveau_mst = 1;
@@ -140,12 +139,17 @@ nouveau_dp_detect(struct nouveau_connector *nv_connector,
* TODO: look into checking this before probing I2C to detect DVI/HDMI
*/
hpd = nvif_conn_hpd_status(&nv_connector->conn);
- if (hpd == NVIF_CONN_HPD_STATUS_NOT_PRESENT)
+ if (hpd == NVIF_CONN_HPD_STATUS_NOT_PRESENT) {
+ nvif_outp_dp_aux_pwr(&nv_encoder->outp, false);
goto out;
+ }
+ nvif_outp_dp_aux_pwr(&nv_encoder->outp, true);
status = nouveau_dp_probe_dpcd(nv_connector, nv_encoder);
- if (status == connector_status_disconnected)
+ if (status == connector_status_disconnected) {
+ nvif_outp_dp_aux_pwr(&nv_encoder->outp, false);
goto out;
+ }
/* If we're in MST mode, we're done here */
if (mstm && mstm->can_mst && mstm->is_mst) {
@@ -193,6 +197,7 @@ nouveau_dp_detect(struct nouveau_connector *nv_connector,
ret = NOUVEAU_DP_MST;
goto out;
} else if (ret != 0) {
+ nvif_outp_dp_aux_pwr(&nv_encoder->outp, false);
goto out;
}
}
@@ -206,14 +211,28 @@ out:
return ret;
}
-void nouveau_dp_irq(struct nouveau_drm *drm,
- struct nouveau_connector *nv_connector)
+bool
+nouveau_dp_link_check(struct nouveau_connector *nv_connector)
+{
+ struct nouveau_encoder *nv_encoder = find_encoder(&nv_connector->base, DCB_OUTPUT_DP);
+
+ if (!nv_encoder || nv_encoder->outp.or.id < 0)
+ return true;
+
+ return nvif_outp_dp_retrain(&nv_encoder->outp) == 0;
+}
+
+void
+nouveau_dp_irq(struct work_struct *work)
{
+ struct nouveau_connector *nv_connector =
+ container_of(work, typeof(*nv_connector), irq_work);
struct drm_connector *connector = &nv_connector->base;
struct nouveau_encoder *outp = find_encoder(connector, DCB_OUTPUT_DP);
+ struct nouveau_drm *drm = nouveau_drm(outp->base.base.dev);
struct nv50_mstm *mstm;
+ u64 hpd = 0;
int ret;
- bool send_hpd = false;
if (!outp)
return;
@@ -225,14 +244,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_CONN_EVENT_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_CONN_EVENT_V0_PLUG;
if (ret >= 0)
outp->dp.sink_count = ret;
}
@@ -240,8 +259,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_CONN_EVENT_V0_IRQ | hpd);
}
/* TODO: