aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau
diff options
context:
space:
mode:
authorFrancisco Jerez <currojerez@riseup.net>2010-07-25 13:13:43 -0400
committerBen Skeggs <bskeggs@redhat.com>2010-08-05 18:35:11 -0400
commit2d14e35c950b00bddeba770278f2fe4dfd4355b2 (patch)
tree572d2d0c02629cb5ed0d8dacc42503f282bba4a6 /drivers/gpu/drm/nouveau
parentbfe9dbcfc67e14eb679869afbc8ada2c4bcc4440 (diff)
drm/nv30: Workaround dual TMDS brain damage.
Signed-off-by: Francisco Jerez <currojerez@riseup.net> Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau')
-rw-r--r--drivers/gpu/drm/nouveau/nv04_dfp.c39
1 files changed, 35 insertions, 4 deletions
diff --git a/drivers/gpu/drm/nouveau/nv04_dfp.c b/drivers/gpu/drm/nouveau/nv04_dfp.c
index 9871570d2ff..a5dcf768580 100644
--- a/drivers/gpu/drm/nouveau/nv04_dfp.c
+++ b/drivers/gpu/drm/nouveau/nv04_dfp.c
@@ -146,6 +146,36 @@ void nv04_dfp_update_fp_control(struct drm_encoder *encoder, int mode)
146 } 146 }
147} 147}
148 148
149static struct drm_encoder *get_tmds_slave(struct drm_encoder *encoder)
150{
151 struct drm_device *dev = encoder->dev;
152 struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb;
153 struct drm_encoder *slave;
154
155 if (dcb->type != OUTPUT_TMDS || dcb->location == DCB_LOC_ON_CHIP)
156 return NULL;
157
158 /* Some BIOSes (e.g. the one in a Quadro FX1000) report several
159 * TMDS transmitters at the same I2C address, in the same I2C
160 * bus. This can still work because in that case one of them is
161 * always hard-wired to a reasonable configuration using straps,
162 * and the other one needs to be programmed.
163 *
164 * I don't think there's a way to know which is which, even the
165 * blob programs the one exposed via I2C for *both* heads, so
166 * let's do the same.
167 */
168 list_for_each_entry(slave, &dev->mode_config.encoder_list, head) {
169 struct dcb_entry *slave_dcb = nouveau_encoder(slave)->dcb;
170
171 if (slave_dcb->type == OUTPUT_TMDS && get_slave_funcs(slave) &&
172 slave_dcb->tmdsconf.slave_addr == dcb->tmdsconf.slave_addr)
173 return slave;
174 }
175
176 return NULL;
177}
178
149static bool nv04_dfp_mode_fixup(struct drm_encoder *encoder, 179static bool nv04_dfp_mode_fixup(struct drm_encoder *encoder,
150 struct drm_display_mode *mode, 180 struct drm_display_mode *mode,
151 struct drm_display_mode *adjusted_mode) 181 struct drm_display_mode *adjusted_mode)
@@ -432,9 +462,9 @@ static void nv04_dfp_commit(struct drm_encoder *encoder)
432 NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + nv04_dac_output_offset(encoder), 0x00100000); 462 NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + nv04_dac_output_offset(encoder), 0x00100000);
433 463
434 /* Init external transmitters */ 464 /* Init external transmitters */
435 if (get_slave_funcs(encoder)) 465 if (get_tmds_slave(encoder))
436 get_slave_funcs(encoder)->mode_set(encoder, &nv_encoder->mode, 466 get_slave_funcs(get_tmds_slave(encoder))->mode_set(
437 &nv_encoder->mode); 467 encoder, &nv_encoder->mode, &nv_encoder->mode);
438 468
439 helper->dpms(encoder, DRM_MODE_DPMS_ON); 469 helper->dpms(encoder, DRM_MODE_DPMS_ON);
440 470
@@ -581,7 +611,8 @@ static void nv04_tmds_slave_init(struct drm_encoder *encoder)
581 }; 611 };
582 int type; 612 int type;
583 613
584 if (!nv_gf4_disp_arch(dev) || !i2c) 614 if (!nv_gf4_disp_arch(dev) || !i2c ||
615 get_tmds_slave(encoder))
585 return; 616 return;
586 617
587 type = nouveau_i2c_identify(dev, "TMDS transmitter", info, 2); 618 type = nouveau_i2c_identify(dev, "TMDS transmitter", info, 2);