diff options
author | Dave Airlie <airlied@linux.ie> | 2010-01-28 12:58:29 +1000 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2010-01-28 16:06:52 +1000 |
commit | c1a73ff51b371ecc6f57a81a33f644344b4e3f70 (patch) | |
tree | a1274797d5438e4bbbb3e8d087196fc09e093db7 /src | |
parent | 95b56275d80dcee48a7927df124602c34cd72235 (diff) |
radeon: add support for picking the digitial encoder
Testing on a W500 laptop found the LVDS + DisplayPort would conflict
over the choice of digital encoder, and only one would work.
This patch fixes the DCE3 case where LVTMA requires the second digital
encoder and lets DP/DVI use the first in most cases.
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/atombios_output.c | 81 | ||||
-rw-r--r-- | src/radeon_output.c | 1 |
2 files changed, 61 insertions, 21 deletions
diff --git a/src/atombios_output.c b/src/atombios_output.c index 024fa4c5..fc6c1ec1 100644 --- a/src/atombios_output.c +++ b/src/atombios_output.c @@ -595,7 +595,7 @@ atombios_output_dig_encoder_setup(xf86OutputPtr output, int action) /* doesn't really matter which dig encoder we pick as long as it's * not already in use */ - if (radeon_output->linkb) + if (dig_block) index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl); else index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl); @@ -779,7 +779,7 @@ atombios_output_dig_transmitter_setup(xf86OutputPtr output, int action, uint8_t /* doesn't really matter which dig encoder we pick as long as it's * not already in use */ - if (radeon_output->linkb) + if (radeon_output->dig_block) disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER; else disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER; @@ -1489,7 +1489,7 @@ atombios_set_output_crtc_source(xf86OutputPtr output) /* doesn't really matter which dig encoder we pick as long as it's * not already in use */ - if (radeon_output->linkb) + if (radeon_output->dig_block) crtc_src_param2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID; else crtc_src_param2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID; @@ -1581,20 +1581,67 @@ atombios_apply_output_quirks(xf86OutputPtr output, DisplayModePtr mode) } } +static void +atombios_pick_dig_block(xf86OutputPtr output) +{ + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(output->scrn); + RADEONOutputPrivatePtr radeon_output = output->driver_private; + RADEONInfoPtr info = RADEONPTR(output->scrn); + Bool is_lvtma = FALSE; + int i, mode; + uint32_t dig_enc_use_mask = 0; + + /* non digital encoders don't need a dig block */ + mode = atombios_get_encoder_mode(output); + if (mode == ATOM_ENCODER_MODE_CRT || + mode == ATOM_ENCODER_MODE_TV || + mode == ATOM_ENCODER_MODE_CV) + return; + + if (IS_DCE32_VARIANT) { + RADEONCrtcPrivatePtr radeon_crtc = output->crtc->driver_private; + radeon_output->dig_block = radeon_crtc->crtc_id; + return; + } + + for (i = 0; i < xf86_config->num_output; i++) { + xf86OutputPtr test = xf86_config->output[i]; + radeon_encoder_ptr radeon_encoder = radeon_get_encoder(test); + RADEONOutputPrivatePtr radeon_test = test->driver_private; + + if (!radeon_encoder || !test->crtc) + continue; + + if (output == test && radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA) + is_lvtma = TRUE; + if (output != test && (radeon_test->dig_block >= 0)) + dig_enc_use_mask |= (1 << radeon_test->dig_block); + + } + if (is_lvtma) { + if (dig_enc_use_mask & 0x2) + ErrorF("Need digital encoder 2 for LVTMA and it isn't free - stealing\n"); + radeon_output->dig_block = 1; + return; + } + if (!(dig_enc_use_mask & 1)) + radeon_output->dig_block = 0; + else + radeon_output->dig_block = 1; +} void atombios_output_mode_set(xf86OutputPtr output, DisplayModePtr mode, DisplayModePtr adjusted_mode) { RADEONOutputPrivatePtr radeon_output = output->driver_private; - RADEONCrtcPrivatePtr radeon_crtc = output->crtc->driver_private; radeon_encoder_ptr radeon_encoder = radeon_get_encoder(output); RADEONInfoPtr info = RADEONPTR(output->scrn); if (radeon_encoder == NULL) return; radeon_output->pixel_clock = adjusted_mode->Clock; - radeon_output->dig_block = radeon_crtc->crtc_id; + atombios_pick_dig_block(output); atombios_output_overscan_setup(output, mode, adjusted_mode); atombios_output_scaler_setup(output); atombios_set_output_crtc_source(output); @@ -1869,24 +1916,16 @@ atombios_dac_detect(xf86OutputPtr output) static inline int atom_dp_get_encoder_id(xf86OutputPtr output) { - RADEONInfoPtr info = RADEONPTR(output->scrn); RADEONOutputPrivatePtr radeon_output = output->driver_private; int ret = 0; - if (IS_DCE32_VARIANT) { - if (radeon_output->dig_block) - ret |= ATOM_DP_CONFIG_DIG2_ENCODER; - else - ret |= ATOM_DP_CONFIG_DIG1_ENCODER; - if (radeon_output->linkb) - ret |= ATOM_DP_CONFIG_LINK_B; - else - ret |= ATOM_DP_CONFIG_LINK_A; - } else { - if (radeon_output->linkb) - ret |= ATOM_DP_CONFIG_DIG2_ENCODER | ATOM_DP_CONFIG_LINK_B; - else - ret |= ATOM_DP_CONFIG_DIG1_ENCODER | ATOM_DP_CONFIG_LINK_A; - } + if (radeon_output->dig_block) + ret |= ATOM_DP_CONFIG_DIG2_ENCODER; + else + ret |= ATOM_DP_CONFIG_DIG1_ENCODER; + if (radeon_output->linkb) + ret |= ATOM_DP_CONFIG_LINK_B; + else + ret |= ATOM_DP_CONFIG_LINK_A; return ret; } diff --git a/src/radeon_output.c b/src/radeon_output.c index 04817e30..d2795fe2 100644 --- a/src/radeon_output.c +++ b/src/radeon_output.c @@ -2961,6 +2961,7 @@ Bool RADEONSetupConnectors(ScrnInfoPtr pScrn) radeon_output->shared_ddc = info->BiosConnector[i].shared_ddc; radeon_output->load_detection = info->BiosConnector[i].load_detection; radeon_output->linkb = info->BiosConnector[i].linkb; + radeon_output->dig_block = -1; radeon_output->connector_id = info->BiosConnector[i].connector_object; radeon_output->connector_object_id = info->BiosConnector[i].connector_object_id; radeon_output->ucI2cId = info->BiosConnector[i].ucI2cId; |