Commit 8bb30c88 authored by Ben Skeggs's avatar Ben Skeggs
Browse files

drm/nouveau/disp: add method to trigger DP link retrain



This moves control of link retraining in response to HPD IRQ to the
KMS driver's HPD IRQ handler.

NVKM still handles checking link status for the moment, this can be
moved to the KMS driver when it takes explicit control of link rate
selection.

v2:
- skip source config on retrain (fixes some retrain failures)

Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
Reviewed-by: default avatarLyude Paul <lyude@redhat.com>
parent 016dacb6
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@ union nvif_outp_args {
#define NVIF_OUTP_V0_INFOFRAME   0x03
#define NVIF_OUTP_V0_HDA_ELD     0x04
#define NVIF_OUTP_V0_DP_AUX_PWR  0x05
#define NVIF_OUTP_V0_DP_RETRAIN  0x06

union nvif_outp_load_detect_args {
	struct nvif_outp_load_detect_v0 {
@@ -100,4 +101,9 @@ union nvif_outp_dp_aux_pwr_args {
		__u8 pad02[6];
	} v0;
};

union nvif_outp_dp_retrain_args {
	struct nvif_outp_dp_retrain_vn {
	} vn;
};
#endif
+1 −0
Original line number Diff line number Diff line
@@ -27,4 +27,5 @@ void nvif_outp_release(struct nvif_outp *);
int nvif_outp_infoframe(struct nvif_outp *, u8 type, struct nvif_outp_infoframe_v0 *, u32 size);
int nvif_outp_hda_eld(struct nvif_outp *, int head, void *data, u32 size);
int nvif_outp_dp_aux_pwr(struct nvif_outp *, bool enable);
int nvif_outp_dp_retrain(struct nvif_outp *);
#endif
+4 −2
Original line number Diff line number Diff line
@@ -506,8 +506,10 @@ nouveau_display_hpd_work(struct work_struct *work)
			    !!(bits & NVIF_NOTIFY_CONN_V0_UNPLUG),
			    !!(bits & NVIF_NOTIFY_CONN_V0_IRQ));

		if (bits & NVIF_NOTIFY_CONN_V0_IRQ)
		if (bits & NVIF_NOTIFY_CONN_V0_IRQ) {
			if (nouveau_dp_link_check(nv_connector))
				continue;
		}

		connector->status = drm_helper_probe_detect(connector, NULL, false);
		if (old_epoch_counter == connector->epoch_counter)
+11 −0
Original line number Diff line number Diff line
@@ -211,6 +211,17 @@ nouveau_dp_detect(struct nouveau_connector *nv_connector,
	return ret;
}

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 nouveau_drm *drm,
		    struct nouveau_connector *nv_connector)
{
+1 −0
Original line number Diff line number Diff line
@@ -141,6 +141,7 @@ enum nouveau_dp_status {
};

int nouveau_dp_detect(struct nouveau_connector *, struct nouveau_encoder *);
bool nouveau_dp_link_check(struct nouveau_connector *);
void nouveau_dp_irq(struct nouveau_drm *drm,
		    struct nouveau_connector *nv_connector);
enum drm_mode_status nv50_dp_mode_valid(struct drm_connector *,
Loading