aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2011-08-04 00:31:28 -0400
committerBen Skeggs <bskeggs@redhat.com>2011-09-20 02:10:35 -0400
commit52e0d0ecc8f82d4da12c31f0701bf490db5abe72 (patch)
treef86ed984b946715e172926959886a4c16445529e /drivers/gpu/drm
parent28e2d12405f1afb34435a23d6bba223ff378de91 (diff)
drm/nouveau/dp: enable down-spread if vbios and sink support it
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_dp.c46
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_encoder.h3
2 files changed, 20 insertions, 29 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c
index 3777616cc157..89d5c161c8bd 100644
--- a/drivers/gpu/drm/nouveau/nouveau_dp.c
+++ b/drivers/gpu/drm/nouveau/nouveau_dp.c
@@ -160,25 +160,6 @@ out:
160 return ret; 160 return ret;
161} 161}
162 162
163static int
164auxch_rd(struct drm_encoder *encoder, int address, uint8_t *buf, int size)
165{
166 struct drm_device *dev = encoder->dev;
167 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
168 struct nouveau_i2c_chan *auxch;
169 int ret;
170
171 auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index);
172 if (!auxch)
173 return -ENODEV;
174
175 ret = nouveau_dp_auxch(auxch, 9, address, buf, size);
176 if (ret)
177 return ret;
178
179 return 0;
180}
181
182static u32 163static u32
183dp_link_bw_get(struct drm_device *dev, int or, int link) 164dp_link_bw_get(struct drm_device *dev, int or, int link)
184{ 165{
@@ -298,7 +279,7 @@ struct dp_state {
298 int crtc; 279 int crtc;
299 int or; 280 int or;
300 int link; 281 int link;
301 int enh_frame; 282 u8 *dpcd;
302 int link_nr; 283 int link_nr;
303 u32 link_bw; 284 u32 link_bw;
304 u8 stat[6]; 285 u8 stat[6];
@@ -343,7 +324,7 @@ dp_set_link_config(struct drm_device *dev, struct dp_state *dp)
343 /* configure lane count on the source */ 324 /* configure lane count on the source */
344 dp_ctrl = ((1 << dp->link_nr) - 1) << 16; 325 dp_ctrl = ((1 << dp->link_nr) - 1) << 16;
345 sink[1] = dp->link_nr; 326 sink[1] = dp->link_nr;
346 if (dp->enh_frame) { 327 if (dp->dpcd[2] & DP_ENHANCED_FRAME_CAP) {
347 dp_ctrl |= 0x00004000; 328 dp_ctrl |= 0x00004000;
348 sink[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN; 329 sink[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
349 } 330 }
@@ -505,7 +486,6 @@ nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate)
505 const u32 *link_bw = bw_list; 486 const u32 *link_bw = bw_list;
506 struct dp_state dp; 487 struct dp_state dp;
507 u8 *bios, headerlen; 488 u8 *bios, headerlen;
508 u16 script;
509 489
510 auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index); 490 auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index);
511 if (!auxch) 491 if (!auxch)
@@ -520,7 +500,7 @@ nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate)
520 dp.auxch = auxch->rd; 500 dp.auxch = auxch->rd;
521 dp.or = nv_encoder->or; 501 dp.or = nv_encoder->or;
522 dp.link = !(nv_encoder->dcb->sorconf.link & 1); 502 dp.link = !(nv_encoder->dcb->sorconf.link & 1);
523 dp.enh_frame = nv_encoder->dp.enhanced_frame; 503 dp.dpcd = nv_encoder->dp.dpcd;
524 504
525 /* some sinks toggle hotplug in response to some of the actions 505 /* some sinks toggle hotplug in response to some of the actions
526 * we take during link training (DP_SET_POWER is one), we need 506 * we take during link training (DP_SET_POWER is one), we need
@@ -528,6 +508,15 @@ nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate)
528 */ 508 */
529 pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, false); 509 pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, false);
530 510
511 /* enable down-spreading, if possible */
512 if (headerlen >= 16) {
513 u16 script = ROM16(bios[14]);
514 if (nv_encoder->dp.dpcd[3] & 1)
515 script = ROM16(bios[12]);
516
517 nouveau_bios_run_init_table(dev, script, dp.dcb, dp.crtc);
518 }
519
531 /* execute pre-train script from vbios */ 520 /* execute pre-train script from vbios */
532 nouveau_bios_run_init_table(dev, ROM16(bios[6]), dp.dcb, dp.crtc); 521 nouveau_bios_run_init_table(dev, ROM16(bios[6]), dp.dcb, dp.crtc);
533 522
@@ -575,17 +564,20 @@ nouveau_dp_detect(struct drm_encoder *encoder)
575{ 564{
576 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); 565 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
577 struct drm_device *dev = encoder->dev; 566 struct drm_device *dev = encoder->dev;
578 uint8_t dpcd[4]; 567 struct nouveau_i2c_chan *auxch;
568 u8 *dpcd = nv_encoder->dp.dpcd;
579 int ret; 569 int ret;
580 570
581 ret = auxch_rd(encoder, 0x0000, dpcd, 4); 571 auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index);
572 if (!auxch)
573 return false;
574
575 ret = auxch_tx(dev, auxch->rd, 9, DP_DPCD_REV, dpcd, 8);
582 if (ret) 576 if (ret)
583 return false; 577 return false;
584 578
585 nv_encoder->dp.dpcd_version = dpcd[0];
586 nv_encoder->dp.link_bw = 27000 * dpcd[1]; 579 nv_encoder->dp.link_bw = 27000 * dpcd[1];
587 nv_encoder->dp.link_nr = dpcd[2] & DP_MAX_LANE_COUNT_MASK; 580 nv_encoder->dp.link_nr = dpcd[2] & DP_MAX_LANE_COUNT_MASK;
588 nv_encoder->dp.enhanced_frame = dpcd[2] & DP_ENHANCED_FRAME_CAP;
589 581
590 NV_DEBUG_KMS(dev, "display: %dx%d dpcd 0x%02x\n", 582 NV_DEBUG_KMS(dev, "display: %dx%d dpcd 0x%02x\n",
591 nv_encoder->dp.link_nr, nv_encoder->dp.link_bw, dpcd[0]); 583 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 deafe7b1f524..e5d6e3faff3d 100644
--- a/drivers/gpu/drm/nouveau/nouveau_encoder.h
+++ b/drivers/gpu/drm/nouveau/nouveau_encoder.h
@@ -49,10 +49,9 @@ struct nouveau_encoder {
49 49
50 union { 50 union {
51 struct { 51 struct {
52 int dpcd_version; 52 u8 dpcd[8];
53 int link_nr; 53 int link_nr;
54 int link_bw; 54 int link_bw;
55 bool enhanced_frame;
56 u32 datarate; 55 u32 datarate;
57 } dp; 56 } dp;
58 }; 57 };