mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-03 08:46:41 +07:00
drm/nv30: Workaround dual TMDS brain damage.
Signed-off-by: Francisco Jerez <currojerez@riseup.net> Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
This commit is contained in:
parent
bfe9dbcfc6
commit
2d14e35c95
@ -146,6 +146,36 @@ void nv04_dfp_update_fp_control(struct drm_encoder *encoder, int mode)
|
||||
}
|
||||
}
|
||||
|
||||
static struct drm_encoder *get_tmds_slave(struct drm_encoder *encoder)
|
||||
{
|
||||
struct drm_device *dev = encoder->dev;
|
||||
struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb;
|
||||
struct drm_encoder *slave;
|
||||
|
||||
if (dcb->type != OUTPUT_TMDS || dcb->location == DCB_LOC_ON_CHIP)
|
||||
return NULL;
|
||||
|
||||
/* Some BIOSes (e.g. the one in a Quadro FX1000) report several
|
||||
* TMDS transmitters at the same I2C address, in the same I2C
|
||||
* bus. This can still work because in that case one of them is
|
||||
* always hard-wired to a reasonable configuration using straps,
|
||||
* and the other one needs to be programmed.
|
||||
*
|
||||
* I don't think there's a way to know which is which, even the
|
||||
* blob programs the one exposed via I2C for *both* heads, so
|
||||
* let's do the same.
|
||||
*/
|
||||
list_for_each_entry(slave, &dev->mode_config.encoder_list, head) {
|
||||
struct dcb_entry *slave_dcb = nouveau_encoder(slave)->dcb;
|
||||
|
||||
if (slave_dcb->type == OUTPUT_TMDS && get_slave_funcs(slave) &&
|
||||
slave_dcb->tmdsconf.slave_addr == dcb->tmdsconf.slave_addr)
|
||||
return slave;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool nv04_dfp_mode_fixup(struct drm_encoder *encoder,
|
||||
struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode)
|
||||
@ -432,9 +462,9 @@ static void nv04_dfp_commit(struct drm_encoder *encoder)
|
||||
NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + nv04_dac_output_offset(encoder), 0x00100000);
|
||||
|
||||
/* Init external transmitters */
|
||||
if (get_slave_funcs(encoder))
|
||||
get_slave_funcs(encoder)->mode_set(encoder, &nv_encoder->mode,
|
||||
&nv_encoder->mode);
|
||||
if (get_tmds_slave(encoder))
|
||||
get_slave_funcs(get_tmds_slave(encoder))->mode_set(
|
||||
encoder, &nv_encoder->mode, &nv_encoder->mode);
|
||||
|
||||
helper->dpms(encoder, DRM_MODE_DPMS_ON);
|
||||
|
||||
@ -581,7 +611,8 @@ static void nv04_tmds_slave_init(struct drm_encoder *encoder)
|
||||
};
|
||||
int type;
|
||||
|
||||
if (!nv_gf4_disp_arch(dev) || !i2c)
|
||||
if (!nv_gf4_disp_arch(dev) || !i2c ||
|
||||
get_tmds_slave(encoder))
|
||||
return;
|
||||
|
||||
type = nouveau_i2c_identify(dev, "TMDS transmitter", info, 2);
|
||||
|
Loading…
Reference in New Issue
Block a user