diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2011-08-04 00:31:28 -0400 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2011-09-20 02:10:35 -0400 |
commit | 52e0d0ecc8f82d4da12c31f0701bf490db5abe72 (patch) | |
tree | f86ed984b946715e172926959886a4c16445529e /drivers/gpu/drm | |
parent | 28e2d12405f1afb34435a23d6bba223ff378de91 (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.c | 46 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_encoder.h | 3 |
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 | ||
163 | static int | ||
164 | auxch_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 | |||
182 | static u32 | 163 | static u32 |
183 | dp_link_bw_get(struct drm_device *dev, int or, int link) | 164 | dp_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 | }; |