228,32 → 228,6 |
return NULL; |
} |
|
static struct radeon_connector_atom_dig * |
radeon_get_atom_connector_priv_from_encoder(struct drm_encoder *encoder) |
{ |
struct drm_device *dev = encoder->dev; |
struct radeon_device *rdev = dev->dev_private; |
struct drm_connector *connector; |
struct radeon_connector *radeon_connector; |
struct radeon_connector_atom_dig *dig_connector; |
|
if (!rdev->is_atom_bios) |
return NULL; |
|
connector = radeon_get_connector_for_encoder(encoder); |
if (!connector) |
return NULL; |
|
radeon_connector = to_radeon_connector(connector); |
|
if (!radeon_connector->con_priv) |
return NULL; |
|
dig_connector = radeon_connector->con_priv; |
|
return dig_connector; |
} |
|
static bool radeon_atom_mode_fixup(struct drm_encoder *encoder, |
struct drm_display_mode *mode, |
struct drm_display_mode *adjusted_mode) |
262,9 → 236,6 |
struct drm_device *dev = encoder->dev; |
struct radeon_device *rdev = dev->dev_private; |
|
/* adjust pm to upcoming mode change */ |
radeon_pm_compute_clocks(rdev); |
|
/* set the active encoder to connector routing */ |
radeon_encoder_set_active_device(encoder); |
drm_mode_set_crtcinfo(adjusted_mode, 0); |
487,20 → 458,34 |
struct drm_device *dev = encoder->dev; |
struct radeon_device *rdev = dev->dev_private; |
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; |
struct radeon_connector_atom_dig *dig_connector = |
radeon_get_atom_connector_priv_from_encoder(encoder); |
union lvds_encoder_control args; |
int index = 0; |
int hdmi_detected = 0; |
uint8_t frev, crev; |
struct radeon_encoder_atom_dig *dig; |
struct drm_connector *connector; |
struct radeon_connector *radeon_connector; |
struct radeon_connector_atom_dig *dig_connector; |
|
if (!dig || !dig_connector) |
connector = radeon_get_connector_for_encoder(encoder); |
if (!connector) |
return; |
|
if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI) |
radeon_connector = to_radeon_connector(connector); |
|
if (!radeon_encoder->enc_priv) |
return; |
|
dig = radeon_encoder->enc_priv; |
|
if (!radeon_connector->con_priv) |
return; |
|
if (drm_detect_hdmi_monitor(radeon_connector->edid)) |
hdmi_detected = 1; |
|
dig_connector = radeon_connector->con_priv; |
|
memset(&args, 0, sizeof(args)); |
|
switch (radeon_encoder->encoder_id) { |
601,7 → 586,7 |
{ |
struct drm_connector *connector; |
struct radeon_connector *radeon_connector; |
struct radeon_connector_atom_dig *dig_connector; |
struct radeon_connector_atom_dig *radeon_dig_connector; |
|
connector = radeon_get_connector_for_encoder(encoder); |
if (!connector) |
632,9 → 617,9 |
break; |
case DRM_MODE_CONNECTOR_DisplayPort: |
case DRM_MODE_CONNECTOR_eDP: |
dig_connector = radeon_connector->con_priv; |
if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) || |
(dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) |
radeon_dig_connector = radeon_connector->con_priv; |
if ((radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) || |
(radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) |
return ATOM_ENCODER_MODE_DP; |
else if (drm_detect_hdmi_monitor(radeon_connector->edid)) |
return ATOM_ENCODER_MODE_HDMI; |
671,18 → 656,6 |
* - 2 DIG encoder blocks. |
* DIG1/2 can drive UNIPHY0/1/2 link A or link B |
* |
* DCE 4.0 |
* - 3 DIG transmitter blocks UNPHY0/1/2 (links A and B). |
* Supports up to 6 digital outputs |
* - 6 DIG encoder blocks. |
* - DIG to PHY mapping is hardcoded |
* DIG1 drives UNIPHY0 link A, A+B |
* DIG2 drives UNIPHY0 link B |
* DIG3 drives UNIPHY1 link A, A+B |
* DIG4 drives UNIPHY1 link B |
* DIG5 drives UNIPHY2 link A, A+B |
* DIG6 drives UNIPHY2 link B |
* |
* Routing |
* crtc -> dig encoder -> UNIPHY/LVTMA (1 or 2 links) |
* Examples: |
691,77 → 664,87 |
* crtc0 -> dig1 -> UNIPHY2 link A -> LVDS |
* crtc1 -> dig2 -> UNIPHY1 link B+A -> TMDS/HDMI |
*/ |
|
union dig_encoder_control { |
DIG_ENCODER_CONTROL_PS_ALLOCATION v1; |
DIG_ENCODER_CONTROL_PARAMETERS_V2 v2; |
DIG_ENCODER_CONTROL_PARAMETERS_V3 v3; |
}; |
|
void |
static void |
atombios_dig_encoder_setup(struct drm_encoder *encoder, int action) |
{ |
struct drm_device *dev = encoder->dev; |
struct radeon_device *rdev = dev->dev_private; |
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; |
struct radeon_connector_atom_dig *dig_connector = |
radeon_get_atom_connector_priv_from_encoder(encoder); |
union dig_encoder_control args; |
DIG_ENCODER_CONTROL_PS_ALLOCATION args; |
int index = 0, num = 0; |
uint8_t frev, crev; |
struct radeon_encoder_atom_dig *dig; |
struct drm_connector *connector; |
struct radeon_connector *radeon_connector; |
struct radeon_connector_atom_dig *dig_connector; |
|
if (!dig || !dig_connector) |
connector = radeon_get_connector_for_encoder(encoder); |
if (!connector) |
return; |
|
radeon_connector = to_radeon_connector(connector); |
|
if (!radeon_connector->con_priv) |
return; |
|
dig_connector = radeon_connector->con_priv; |
|
if (!radeon_encoder->enc_priv) |
return; |
|
dig = radeon_encoder->enc_priv; |
|
memset(&args, 0, sizeof(args)); |
|
if (ASIC_IS_DCE4(rdev)) |
index = GetIndexIntoMasterTable(COMMAND, DIGxEncoderControl); |
else { |
if (dig->dig_encoder) |
index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl); |
else |
index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl); |
} |
num = dig->dig_encoder + 1; |
|
atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev); |
|
args.v1.ucAction = action; |
args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); |
args.v1.ucEncoderMode = atombios_get_encoder_mode(encoder); |
args.ucAction = action; |
args.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); |
|
if (args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP) { |
if (dig_connector->dp_clock == 270000) |
args.v1.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ; |
args.v1.ucLaneNum = dig_connector->dp_lane_count; |
} else if (radeon_encoder->pixel_clock > 165000) |
args.v1.ucLaneNum = 8; |
else |
args.v1.ucLaneNum = 4; |
|
if (ASIC_IS_DCE4(rdev)) { |
args.v3.acConfig.ucDigSel = dig->dig_encoder; |
args.v3.ucBitPerColor = PANEL_8BIT_PER_COLOR; |
} else { |
if (ASIC_IS_DCE32(rdev)) { |
switch (radeon_encoder->encoder_id) { |
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: |
args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER1; |
args.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER1; |
break; |
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: |
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: |
args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER2; |
args.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER2; |
break; |
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: |
args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER3; |
args.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER3; |
break; |
} |
} else { |
switch (radeon_encoder->encoder_id) { |
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: |
args.ucConfig = ATOM_ENCODER_CONFIG_TRANSMITTER1; |
break; |
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: |
args.ucConfig = ATOM_ENCODER_CONFIG_TRANSMITTER2; |
break; |
} |
} |
|
args.ucEncoderMode = atombios_get_encoder_mode(encoder); |
|
if (args.ucEncoderMode == ATOM_ENCODER_MODE_DP) { |
if (dig_connector->dp_clock == 270000) |
args.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ; |
args.ucLaneNum = dig_connector->dp_lane_count; |
} else if (radeon_encoder->pixel_clock > 165000) |
args.ucLaneNum = 8; |
else |
args.ucLaneNum = 4; |
|
if (dig_connector->linkb) |
args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKB; |
args.ucConfig |= ATOM_ENCODER_CONFIG_LINKB; |
else |
args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKA; |
} |
args.ucConfig |= ATOM_ENCODER_CONFIG_LINKA; |
|
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); |
|
770,7 → 753,6 |
union dig_transmitter_control { |
DIG_TRANSMITTER_CONTROL_PS_ALLOCATION v1; |
DIG_TRANSMITTER_CONTROL_PARAMETERS_V2 v2; |
DIG_TRANSMITTER_CONTROL_PARAMETERS_V3 v3; |
}; |
|
void |
779,29 → 761,37 |
struct drm_device *dev = encoder->dev; |
struct radeon_device *rdev = dev->dev_private; |
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; |
struct radeon_connector_atom_dig *dig_connector = |
radeon_get_atom_connector_priv_from_encoder(encoder); |
struct drm_connector *connector; |
struct radeon_connector *radeon_connector; |
union dig_transmitter_control args; |
int index = 0, num = 0; |
uint8_t frev, crev; |
struct radeon_encoder_atom_dig *dig; |
struct drm_connector *connector; |
struct radeon_connector *radeon_connector; |
struct radeon_connector_atom_dig *dig_connector; |
bool is_dp = false; |
int pll_id = 0; |
|
if (!dig || !dig_connector) |
connector = radeon_get_connector_for_encoder(encoder); |
if (!connector) |
return; |
|
connector = radeon_get_connector_for_encoder(encoder); |
radeon_connector = to_radeon_connector(connector); |
|
if (!radeon_encoder->enc_priv) |
return; |
|
dig = radeon_encoder->enc_priv; |
|
if (!radeon_connector->con_priv) |
return; |
|
dig_connector = radeon_connector->con_priv; |
|
if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP) |
is_dp = true; |
|
memset(&args, 0, sizeof(args)); |
|
if (ASIC_IS_DCE32(rdev) || ASIC_IS_DCE4(rdev)) |
if (ASIC_IS_DCE32(rdev)) |
index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl); |
else { |
switch (radeon_encoder->encoder_id) { |
831,54 → 821,7 |
else |
args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); |
} |
if (ASIC_IS_DCE4(rdev)) { |
if (is_dp) |
args.v3.ucLaneNum = dig_connector->dp_lane_count; |
else if (radeon_encoder->pixel_clock > 165000) |
args.v3.ucLaneNum = 8; |
else |
args.v3.ucLaneNum = 4; |
|
if (dig_connector->linkb) { |
args.v3.acConfig.ucLinkSel = 1; |
args.v3.acConfig.ucEncoderSel = 1; |
} |
|
/* Select the PLL for the PHY |
* DP PHY should be clocked from external src if there is |
* one. |
*/ |
if (encoder->crtc) { |
struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); |
pll_id = radeon_crtc->pll_id; |
} |
if (is_dp && rdev->clock.dp_extclk) |
args.v3.acConfig.ucRefClkSource = 2; /* external src */ |
else |
args.v3.acConfig.ucRefClkSource = pll_id; |
|
switch (radeon_encoder->encoder_id) { |
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: |
args.v3.acConfig.ucTransmitterSel = 0; |
num = 0; |
break; |
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: |
args.v3.acConfig.ucTransmitterSel = 1; |
num = 1; |
break; |
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: |
args.v3.acConfig.ucTransmitterSel = 2; |
num = 2; |
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; |
} |
} else if (ASIC_IS_DCE32(rdev)) { |
if (ASIC_IS_DCE32(rdev)) { |
if (dig->dig_encoder == 1) |
args.v2.acConfig.ucEncoderSel = 1; |
if (dig_connector->linkb) |
906,6 → 849,7 |
args.v2.acConfig.fCoherentMode = 1; |
} |
} else { |
|
args.v1.ucConfig = ATOM_TRANSMITTER_CONFIG_CLKSRC_PPLL; |
|
if (dig->dig_encoder) |
1080,12 → 1024,9 |
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); |
} |
radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false); |
|
/* adjust pm to dpms change */ |
radeon_pm_compute_clocks(rdev); |
} |
|
union crtc_source_param { |
union crtc_sourc_param { |
SELECT_CRTC_SOURCE_PS_ALLOCATION v1; |
SELECT_CRTC_SOURCE_PARAMETERS_V2 v2; |
}; |
1097,7 → 1038,7 |
struct radeon_device *rdev = dev->dev_private; |
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); |
union crtc_source_param args; |
union crtc_sourc_param args; |
int index = GetIndexIntoMasterTable(COMMAND, SelectCRTC_Source); |
uint8_t frev, crev; |
struct radeon_encoder_atom_dig *dig; |
1166,27 → 1107,11 |
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: |
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: |
dig = radeon_encoder->enc_priv; |
switch (dig->dig_encoder) { |
case 0: |
if (dig->dig_encoder) |
args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID; |
else |
args.v2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID; |
break; |
case 1: |
args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID; |
break; |
case 2: |
args.v2.ucEncoderID = ASIC_INT_DIG3_ENCODER_ID; |
break; |
case 3: |
args.v2.ucEncoderID = ASIC_INT_DIG4_ENCODER_ID; |
break; |
case 4: |
args.v2.ucEncoderID = ASIC_INT_DIG5_ENCODER_ID; |
break; |
case 5: |
args.v2.ucEncoderID = ASIC_INT_DIG6_ENCODER_ID; |
break; |
} |
break; |
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: |
args.v2.ucEncoderID = ASIC_INT_DVO_ENCODER_ID; |
break; |
1242,7 → 1167,6 |
} |
|
/* set scaler clears this on some chips */ |
/* XXX check DCE4 */ |
if (!(radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))) { |
if (ASIC_IS_AVIVO(rdev) && (mode->flags & DRM_MODE_FLAG_INTERLACE)) |
WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset, |
1259,33 → 1183,6 |
struct drm_encoder *test_encoder; |
struct radeon_encoder_atom_dig *dig; |
uint32_t dig_enc_in_use = 0; |
|
if (ASIC_IS_DCE4(rdev)) { |
struct radeon_connector_atom_dig *dig_connector = |
radeon_get_atom_connector_priv_from_encoder(encoder); |
|
switch (radeon_encoder->encoder_id) { |
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: |
if (dig_connector->linkb) |
return 1; |
else |
return 0; |
break; |
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: |
if (dig_connector->linkb) |
return 3; |
else |
return 2; |
break; |
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: |
if (dig_connector->linkb) |
return 5; |
else |
return 4; |
break; |
} |
} |
|
/* on DCE32 and encoder can driver any block so just crtc id */ |
if (ASIC_IS_DCE32(rdev)) { |
return radeon_crtc->crtc_id; |
1357,16 → 1254,6 |
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: |
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: |
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: |
if (ASIC_IS_DCE4(rdev)) { |
/* disable the transmitter */ |
atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); |
/* setup and enable the encoder */ |
atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP); |
|
/* init and enable the transmitter */ |
atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_INIT, 0, 0); |
atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); |
} else { |
/* disable the encoder and transmitter */ |
atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); |
atombios_dig_encoder_setup(encoder, ATOM_DISABLE); |
1376,7 → 1263,6 |
atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_INIT, 0, 0); |
atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0); |
atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); |
} |
break; |
case ENCODER_OBJECT_ID_INTERNAL_DDI: |
atombios_ddia_setup(encoder, ATOM_ENABLE); |
1396,8 → 1282,6 |
} |
atombios_apply_encoder_quirks(encoder, adjusted_mode); |
|
/* XXX */ |
if (!ASIC_IS_DCE4(rdev)) |
r600_hdmi_setmode(encoder, adjusted_mode); |
} |
|
1596,18 → 1480,10 |
return; |
|
encoder = &radeon_encoder->base; |
switch (rdev->num_crtc) { |
case 1: |
if (rdev->flags & RADEON_SINGLE_CRTC) |
encoder->possible_crtcs = 0x1; |
break; |
case 2: |
default: |
else |
encoder->possible_crtcs = 0x3; |
break; |
case 6: |
encoder->possible_crtcs = 0x3f; |
break; |
} |
|
radeon_encoder->enc_priv = NULL; |
|