Commit a3b08294 authored by Alex Deucher's avatar Alex Deucher Committed by Dave Airlie

drm/radeon/kms: make atombios_dig_transmitter_setup() version based

Use the table version to determine which params to use.
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent 58cdcb8b
...@@ -772,6 +772,11 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t ...@@ -772,6 +772,11 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t
igp_lane_info = dig_connector->igp_lane_info; igp_lane_info = dig_connector->igp_lane_info;
} }
if (encoder->crtc) {
struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
pll_id = radeon_crtc->pll_id;
}
/* no dig encoder assigned */ /* no dig encoder assigned */
if (dig_encoder == -1) if (dig_encoder == -1)
return; return;
...@@ -798,146 +803,240 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t ...@@ -798,146 +803,240 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t
if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
return; return;
args.v1.ucAction = action; switch (frev) {
if (action == ATOM_TRANSMITTER_ACTION_INIT) { case 1:
args.v1.usInitInfo = cpu_to_le16(connector_object_id); switch (crev) {
} else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) { case 1:
args.v1.asMode.ucLaneSel = lane_num; args.v1.ucAction = action;
args.v1.asMode.ucLaneSet = lane_set; if (action == ATOM_TRANSMITTER_ACTION_INIT) {
} else { args.v1.usInitInfo = cpu_to_le16(connector_object_id);
if (is_dp) } else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
args.v1.usPixelClock = args.v1.asMode.ucLaneSel = lane_num;
cpu_to_le16(dp_clock / 10); args.v1.asMode.ucLaneSet = lane_set;
else if (radeon_encoder->pixel_clock > 165000) } else {
args.v1.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10); if (is_dp)
else args.v1.usPixelClock =
args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); cpu_to_le16(dp_clock / 10);
} else if (radeon_encoder->pixel_clock > 165000)
if (ASIC_IS_DCE4(rdev)) { args.v1.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
if (is_dp) else
args.v3.ucLaneNum = dp_lane_count; args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
else if (radeon_encoder->pixel_clock > 165000) }
args.v3.ucLaneNum = 8;
else
args.v3.ucLaneNum = 4;
if (dig->linkb) args.v1.ucConfig = ATOM_TRANSMITTER_CONFIG_CLKSRC_PPLL;
args.v3.acConfig.ucLinkSel = 1;
if (dig_encoder & 1)
args.v3.acConfig.ucEncoderSel = 1;
/* Select the PLL for the PHY if (dig_encoder)
* DP PHY should be clocked from external src if there is args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER;
* one. else
*/ args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER;
if (encoder->crtc) {
struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); if ((rdev->flags & RADEON_IS_IGP) &&
pll_id = radeon_crtc->pll_id; (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_UNIPHY)) {
} if (is_dp || (radeon_encoder->pixel_clock <= 165000)) {
if (igp_lane_info & 0x1)
args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_3;
else if (igp_lane_info & 0x2)
args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_4_7;
else if (igp_lane_info & 0x4)
args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_11;
else if (igp_lane_info & 0x8)
args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_12_15;
} else {
if (igp_lane_info & 0x3)
args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_7;
else if (igp_lane_info & 0xc)
args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_15;
}
}
if (dig->linkb)
args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB;
else
args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA;
if (is_dp)
args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT;
else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
if (dig->coherent_mode)
args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT;
if (radeon_encoder->pixel_clock > 165000)
args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_8LANE_LINK;
}
break;
case 2:
args.v2.ucAction = action;
if (action == ATOM_TRANSMITTER_ACTION_INIT) {
args.v2.usInitInfo = cpu_to_le16(connector_object_id);
} else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
args.v2.asMode.ucLaneSel = lane_num;
args.v2.asMode.ucLaneSet = lane_set;
} else {
if (is_dp)
args.v2.usPixelClock =
cpu_to_le16(dp_clock / 10);
else if (radeon_encoder->pixel_clock > 165000)
args.v2.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
else
args.v2.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
}
args.v2.acConfig.ucEncoderSel = dig_encoder;
if (dig->linkb)
args.v2.acConfig.ucLinkSel = 1;
switch (radeon_encoder->encoder_id) {
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
args.v2.acConfig.ucTransmitterSel = 0;
break;
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
args.v2.acConfig.ucTransmitterSel = 1;
break;
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
args.v2.acConfig.ucTransmitterSel = 2;
break;
}
if (ASIC_IS_DCE5(rdev)) {
/* On DCE5 DCPLL usually generates the DP ref clock */
if (is_dp) { if (is_dp) {
if (rdev->clock.dp_extclk) args.v2.acConfig.fCoherentMode = 1;
args.v4.acConfig.ucRefClkSource = ENCODER_REFCLK_SRC_EXTCLK; args.v2.acConfig.fDPConnector = 1;
} else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
if (dig->coherent_mode)
args.v2.acConfig.fCoherentMode = 1;
if (radeon_encoder->pixel_clock > 165000)
args.v2.acConfig.fDualLinkConnector = 1;
}
break;
case 3:
args.v3.ucAction = action;
if (action == ATOM_TRANSMITTER_ACTION_INIT) {
args.v3.usInitInfo = cpu_to_le16(connector_object_id);
} else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
args.v3.asMode.ucLaneSel = lane_num;
args.v3.asMode.ucLaneSet = lane_set;
} else {
if (is_dp)
args.v3.usPixelClock =
cpu_to_le16(dp_clock / 10);
else if (radeon_encoder->pixel_clock > 165000)
args.v3.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
else else
args.v4.acConfig.ucRefClkSource = ENCODER_REFCLK_SRC_DCPLL; args.v3.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
} else }
args.v4.acConfig.ucRefClkSource = pll_id;
} else { if (is_dp)
args.v3.ucLaneNum = dp_lane_count;
else if (radeon_encoder->pixel_clock > 165000)
args.v3.ucLaneNum = 8;
else
args.v3.ucLaneNum = 4;
if (dig->linkb)
args.v3.acConfig.ucLinkSel = 1;
if (dig_encoder & 1)
args.v3.acConfig.ucEncoderSel = 1;
/* Select the PLL for the PHY
* DP PHY should be clocked from external src if there is
* one.
*/
/* On DCE4, if there is an external clock, it generates the DP ref clock */ /* On DCE4, if there is an external clock, it generates the DP ref clock */
if (is_dp && rdev->clock.dp_extclk) if (is_dp && rdev->clock.dp_extclk)
args.v3.acConfig.ucRefClkSource = 2; /* external src */ args.v3.acConfig.ucRefClkSource = 2; /* external src */
else else
args.v3.acConfig.ucRefClkSource = pll_id; args.v3.acConfig.ucRefClkSource = pll_id;
}
switch (radeon_encoder->encoder_id) { switch (radeon_encoder->encoder_id) {
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
args.v3.acConfig.ucTransmitterSel = 0; args.v3.acConfig.ucTransmitterSel = 0;
break; break;
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
args.v3.acConfig.ucTransmitterSel = 1; args.v3.acConfig.ucTransmitterSel = 1;
break; break;
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
args.v3.acConfig.ucTransmitterSel = 2; args.v3.acConfig.ucTransmitterSel = 2;
break; break;
} }
if (is_dp)
args.v3.acConfig.fCoherentMode = 1; /* DP requires coherent */
else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
if (dig->coherent_mode)
args.v3.acConfig.fCoherentMode = 1;
if (radeon_encoder->pixel_clock > 165000)
args.v3.acConfig.fDualLinkConnector = 1;
}
} else if (ASIC_IS_DCE32(rdev)) {
args.v2.acConfig.ucEncoderSel = dig_encoder;
if (dig->linkb)
args.v2.acConfig.ucLinkSel = 1;
switch (radeon_encoder->encoder_id) { if (is_dp)
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: args.v3.acConfig.fCoherentMode = 1; /* DP requires coherent */
args.v2.acConfig.ucTransmitterSel = 0; else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
break; if (dig->coherent_mode)
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: args.v3.acConfig.fCoherentMode = 1;
args.v2.acConfig.ucTransmitterSel = 1; if (radeon_encoder->pixel_clock > 165000)
break; args.v3.acConfig.fDualLinkConnector = 1;
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: }
args.v2.acConfig.ucTransmitterSel = 2;
break; break;
} case 4:
args.v4.ucAction = action;
if (is_dp) { if (action == ATOM_TRANSMITTER_ACTION_INIT) {
args.v2.acConfig.fCoherentMode = 1; args.v4.usInitInfo = cpu_to_le16(connector_object_id);
args.v2.acConfig.fDPConnector = 1; } else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
} else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { args.v4.asMode.ucLaneSel = lane_num;
if (dig->coherent_mode) args.v4.asMode.ucLaneSet = lane_set;
args.v2.acConfig.fCoherentMode = 1;
if (radeon_encoder->pixel_clock > 165000)
args.v2.acConfig.fDualLinkConnector = 1;
}
} else {
args.v1.ucConfig = ATOM_TRANSMITTER_CONFIG_CLKSRC_PPLL;
if (dig_encoder)
args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER;
else
args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER;
if ((rdev->flags & RADEON_IS_IGP) &&
(radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_UNIPHY)) {
if (is_dp || (radeon_encoder->pixel_clock <= 165000)) {
if (igp_lane_info & 0x1)
args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_3;
else if (igp_lane_info & 0x2)
args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_4_7;
else if (igp_lane_info & 0x4)
args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_11;
else if (igp_lane_info & 0x8)
args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_12_15;
} else { } else {
if (igp_lane_info & 0x3) if (is_dp)
args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_7; args.v4.usPixelClock =
else if (igp_lane_info & 0xc) cpu_to_le16(dp_clock / 10);
args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_15; else if (radeon_encoder->pixel_clock > 165000)
args.v4.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
else
args.v4.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
} }
}
if (dig->linkb) if (is_dp)
args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB; args.v4.ucLaneNum = dp_lane_count;
else else if (radeon_encoder->pixel_clock > 165000)
args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA; args.v4.ucLaneNum = 8;
else
args.v4.ucLaneNum = 4;
if (is_dp) if (dig->linkb)
args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT; args.v4.acConfig.ucLinkSel = 1;
else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { if (dig_encoder & 1)
if (dig->coherent_mode) args.v4.acConfig.ucEncoderSel = 1;
args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT;
if (radeon_encoder->pixel_clock > 165000) /* Select the PLL for the PHY
args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_8LANE_LINK; * DP PHY should be clocked from external src if there is
* one.
*/
/* On DCE5 DCPLL usually generates the DP ref clock */
if (is_dp) {
if (rdev->clock.dp_extclk)
args.v4.acConfig.ucRefClkSource = ENCODER_REFCLK_SRC_EXTCLK;
else
args.v4.acConfig.ucRefClkSource = ENCODER_REFCLK_SRC_DCPLL;
} else
args.v4.acConfig.ucRefClkSource = pll_id;
switch (radeon_encoder->encoder_id) {
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
args.v4.acConfig.ucTransmitterSel = 0;
break;
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
args.v4.acConfig.ucTransmitterSel = 1;
break;
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
args.v4.acConfig.ucTransmitterSel = 2;
break;
}
if (is_dp)
args.v4.acConfig.fCoherentMode = 1; /* DP requires coherent */
else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
if (dig->coherent_mode)
args.v4.acConfig.fCoherentMode = 1;
if (radeon_encoder->pixel_clock > 165000)
args.v4.acConfig.fDualLinkConnector = 1;
}
break;
default:
DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
break;
} }
break;
default:
DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
break;
} }
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment