summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Airlie <airlied@linux.ie>2010-01-28 12:58:29 +1000
committerDave Airlie <airlied@redhat.com>2010-01-28 16:06:52 +1000
commitc1a73ff51b371ecc6f57a81a33f644344b4e3f70 (patch)
treea1274797d5438e4bbbb3e8d087196fc09e093db7
parent95b56275d80dcee48a7927df124602c34cd72235 (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>
-rw-r--r--src/atombios_output.c81
-rw-r--r--src/radeon_output.c1
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;