drm/nouveau/dp: enable down-spread if vbios and sink support it

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c
index 3777616..89d5c16 100644
--- a/drivers/gpu/drm/nouveau/nouveau_dp.c
+++ b/drivers/gpu/drm/nouveau/nouveau_dp.c
@@ -160,25 +160,6 @@
 	return ret;
 }
 
-static int
-auxch_rd(struct drm_encoder *encoder, int address, uint8_t *buf, int size)
-{
-	struct drm_device *dev = encoder->dev;
-	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
-	struct nouveau_i2c_chan *auxch;
-	int ret;
-
-	auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index);
-	if (!auxch)
-		return -ENODEV;
-
-	ret = nouveau_dp_auxch(auxch, 9, address, buf, size);
-	if (ret)
-		return ret;
-
-	return 0;
-}
-
 static u32
 dp_link_bw_get(struct drm_device *dev, int or, int link)
 {
@@ -298,7 +279,7 @@
 	int crtc;
 	int or;
 	int link;
-	int enh_frame;
+	u8 *dpcd;
 	int link_nr;
 	u32 link_bw;
 	u8  stat[6];
@@ -343,7 +324,7 @@
 	/* configure lane count on the source */
 	dp_ctrl = ((1 << dp->link_nr) - 1) << 16;
 	sink[1] = dp->link_nr;
-	if (dp->enh_frame) {
+	if (dp->dpcd[2] & DP_ENHANCED_FRAME_CAP) {
 		dp_ctrl |= 0x00004000;
 		sink[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
 	}
@@ -505,7 +486,6 @@
 	const u32 *link_bw = bw_list;
 	struct dp_state dp;
 	u8 *bios, headerlen;
-	u16 script;
 
 	auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index);
 	if (!auxch)
@@ -520,7 +500,7 @@
 	dp.auxch = auxch->rd;
 	dp.or = nv_encoder->or;
 	dp.link = !(nv_encoder->dcb->sorconf.link & 1);
-	dp.enh_frame = nv_encoder->dp.enhanced_frame;
+	dp.dpcd = nv_encoder->dp.dpcd;
 
 	/* some sinks toggle hotplug in response to some of the actions
 	 * we take during link training (DP_SET_POWER is one), we need
@@ -528,6 +508,15 @@
 	 */
 	pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, false);
 
+	/* enable down-spreading, if possible */
+	if (headerlen >= 16) {
+		u16 script = ROM16(bios[14]);
+		if (nv_encoder->dp.dpcd[3] & 1)
+			script = ROM16(bios[12]);
+
+		nouveau_bios_run_init_table(dev, script, dp.dcb, dp.crtc);
+	}
+
 	/* execute pre-train script from vbios */
 	nouveau_bios_run_init_table(dev, ROM16(bios[6]), dp.dcb, dp.crtc);
 
@@ -575,17 +564,20 @@
 {
 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
 	struct drm_device *dev = encoder->dev;
-	uint8_t dpcd[4];
+	struct nouveau_i2c_chan *auxch;
+	u8 *dpcd = nv_encoder->dp.dpcd;
 	int ret;
 
-	ret = auxch_rd(encoder, 0x0000, dpcd, 4);
+	auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index);
+	if (!auxch)
+		return false;
+
+	ret = auxch_tx(dev, auxch->rd, 9, DP_DPCD_REV, dpcd, 8);
 	if (ret)
 		return false;
 
-	nv_encoder->dp.dpcd_version = dpcd[0];
 	nv_encoder->dp.link_bw = 27000 * dpcd[1];
 	nv_encoder->dp.link_nr = dpcd[2] & DP_MAX_LANE_COUNT_MASK;
-	nv_encoder->dp.enhanced_frame = dpcd[2] & DP_ENHANCED_FRAME_CAP;
 
 	NV_DEBUG_KMS(dev, "display: %dx%d dpcd 0x%02x\n",
 		     nv_encoder->dp.link_nr, nv_encoder->dp.link_bw, dpcd[0]);
diff --git a/drivers/gpu/drm/nouveau/nouveau_encoder.h b/drivers/gpu/drm/nouveau/nouveau_encoder.h
index deafe7b..e5d6e3f 100644
--- a/drivers/gpu/drm/nouveau/nouveau_encoder.h
+++ b/drivers/gpu/drm/nouveau/nouveau_encoder.h
@@ -49,10 +49,9 @@
 
 	union {
 		struct {
-			int dpcd_version;
+			u8  dpcd[8];
 			int link_nr;
 			int link_bw;
-			bool enhanced_frame;
 			u32 datarate;
 		} dp;
 	};