|
@@ -1379,6 +1379,8 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode)
|
|
|
struct drm_device *dev = encoder->dev;
|
|
|
struct radeon_device *rdev = dev->dev_private;
|
|
|
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
|
|
|
+ struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder);
|
|
|
+ struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
|
|
|
struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
|
|
|
struct radeon_connector *radeon_connector = NULL;
|
|
|
struct radeon_connector_atom_dig *radeon_dig_connector = NULL;
|
|
@@ -1390,19 +1392,37 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode)
|
|
|
|
|
|
switch (mode) {
|
|
|
case DRM_MODE_DPMS_ON:
|
|
|
- /* some early dce3.2 boards have a bug in their transmitter control table */
|
|
|
- if ((rdev->family == CHIP_RV710) || (rdev->family == CHIP_RV730) ||
|
|
|
- ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) {
|
|
|
- if (ASIC_IS_DCE6(rdev)) {
|
|
|
- /* It seems we need to call ATOM_ENCODER_CMD_SETUP again
|
|
|
- * before reenabling encoder on DPMS ON, otherwise we never
|
|
|
- * get picture
|
|
|
- */
|
|
|
- atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0);
|
|
|
+ if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) {
|
|
|
+ if (!connector)
|
|
|
+ dig->panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE;
|
|
|
+ else
|
|
|
+ dig->panel_mode = radeon_dp_get_panel_mode(encoder, connector);
|
|
|
+
|
|
|
+ /* setup and enable the encoder */
|
|
|
+ atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0);
|
|
|
+ atombios_dig_encoder_setup(encoder,
|
|
|
+ ATOM_ENCODER_CMD_SETUP_PANEL_MODE,
|
|
|
+ dig->panel_mode);
|
|
|
+ if (ext_encoder) {
|
|
|
+ if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(rdev))
|
|
|
+ atombios_external_encoder_setup(encoder, ext_encoder,
|
|
|
+ EXTERNAL_ENCODER_ACTION_V3_ENCODER_SETUP);
|
|
|
}
|
|
|
atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
|
|
|
- } else {
|
|
|
+ } else if (ASIC_IS_DCE4(rdev)) {
|
|
|
+ /* setup and enable the encoder */
|
|
|
+ atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0);
|
|
|
+ /* enable the transmitter */
|
|
|
+ atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
|
|
|
atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0);
|
|
|
+ } else {
|
|
|
+ /* setup and enable the encoder and transmitter */
|
|
|
+ atombios_dig_encoder_setup(encoder, ATOM_ENABLE, 0);
|
|
|
+ atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0);
|
|
|
+ atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
|
|
|
+ /* some early dce3.2 boards have a bug in their transmitter control table */
|
|
|
+ if ((rdev->family != CHIP_RV710) || (rdev->family != CHIP_RV730))
|
|
|
+ atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0);
|
|
|
}
|
|
|
if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) {
|
|
|
if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
|
|
@@ -1420,10 +1440,19 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode)
|
|
|
case DRM_MODE_DPMS_STANDBY:
|
|
|
case DRM_MODE_DPMS_SUSPEND:
|
|
|
case DRM_MODE_DPMS_OFF:
|
|
|
- if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev))
|
|
|
+ if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) {
|
|
|
+ /* disable the transmitter */
|
|
|
atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
|
|
|
- else
|
|
|
+ } else if (ASIC_IS_DCE4(rdev)) {
|
|
|
+ /* disable the transmitter */
|
|
|
+ atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT, 0, 0);
|
|
|
+ atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
|
|
|
+ } else {
|
|
|
+ /* disable the encoder and transmitter */
|
|
|
atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT, 0, 0);
|
|
|
+ atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
|
|
|
+ atombios_dig_encoder_setup(encoder, ATOM_DISABLE, 0);
|
|
|
+ }
|
|
|
if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) {
|
|
|
if (ASIC_IS_DCE4(rdev))
|
|
|
atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0);
|
|
@@ -1740,13 +1769,34 @@ static int radeon_atom_pick_dig_encoder(struct drm_encoder *encoder)
|
|
|
struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
|
|
|
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
|
|
|
struct drm_encoder *test_encoder;
|
|
|
- struct radeon_encoder_atom_dig *dig;
|
|
|
+ struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
|
|
|
uint32_t dig_enc_in_use = 0;
|
|
|
|
|
|
- /* DCE4/5 */
|
|
|
- if (ASIC_IS_DCE4(rdev)) {
|
|
|
- dig = radeon_encoder->enc_priv;
|
|
|
- if (ASIC_IS_DCE41(rdev)) {
|
|
|
+ if (ASIC_IS_DCE6(rdev)) {
|
|
|
+ /* DCE6 */
|
|
|
+ switch (radeon_encoder->encoder_id) {
|
|
|
+ case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
|
|
|
+ if (dig->linkb)
|
|
|
+ return 1;
|
|
|
+ else
|
|
|
+ return 0;
|
|
|
+ break;
|
|
|
+ case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
|
|
|
+ if (dig->linkb)
|
|
|
+ return 3;
|
|
|
+ else
|
|
|
+ return 2;
|
|
|
+ break;
|
|
|
+ case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
|
|
|
+ if (dig->linkb)
|
|
|
+ return 5;
|
|
|
+ else
|
|
|
+ return 4;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ } else if (ASIC_IS_DCE4(rdev)) {
|
|
|
+ /* DCE4/5 */
|
|
|
+ if (ASIC_IS_DCE41(rdev) && !ASIC_IS_DCE61(rdev)) {
|
|
|
/* ontario follows DCE4 */
|
|
|
if (rdev->family == CHIP_PALM) {
|
|
|
if (dig->linkb)
|
|
@@ -1848,10 +1898,12 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder,
|
|
|
struct drm_device *dev = encoder->dev;
|
|
|
struct radeon_device *rdev = dev->dev_private;
|
|
|
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
|
|
|
- struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder);
|
|
|
|
|
|
radeon_encoder->pixel_clock = adjusted_mode->clock;
|
|
|
|
|
|
+ /* need to call this here rather than in prepare() since we need some crtc info */
|
|
|
+ radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
|
|
|
+
|
|
|
if (ASIC_IS_AVIVO(rdev) && !ASIC_IS_DCE4(rdev)) {
|
|
|
if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT))
|
|
|
atombios_yuv_setup(encoder, true);
|
|
@@ -1870,38 +1922,7 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder,
|
|
|
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
|
|
|
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
|
|
|
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
|
|
|
- if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) {
|
|
|
- struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
|
|
|
- struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
|
|
|
-
|
|
|
- if (!connector)
|
|
|
- dig->panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE;
|
|
|
- else
|
|
|
- dig->panel_mode = radeon_dp_get_panel_mode(encoder, connector);
|
|
|
-
|
|
|
- /* setup and enable the encoder */
|
|
|
- atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0);
|
|
|
- atombios_dig_encoder_setup(encoder,
|
|
|
- ATOM_ENCODER_CMD_SETUP_PANEL_MODE,
|
|
|
- dig->panel_mode);
|
|
|
- } else 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, 0);
|
|
|
-
|
|
|
- /* enable the transmitter */
|
|
|
- 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, 0);
|
|
|
-
|
|
|
- /* setup and enable the encoder and transmitter */
|
|
|
- atombios_dig_encoder_setup(encoder, ATOM_ENABLE, 0);
|
|
|
- atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0);
|
|
|
- atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
|
|
|
- }
|
|
|
+ /* handled in dpms */
|
|
|
break;
|
|
|
case ENCODER_OBJECT_ID_INTERNAL_DDI:
|
|
|
case ENCODER_OBJECT_ID_INTERNAL_DVO1:
|
|
@@ -1922,14 +1943,6 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder,
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
- if (ext_encoder) {
|
|
|
- if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(rdev))
|
|
|
- atombios_external_encoder_setup(encoder, ext_encoder,
|
|
|
- EXTERNAL_ENCODER_ACTION_V3_ENCODER_SETUP);
|
|
|
- else
|
|
|
- atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE);
|
|
|
- }
|
|
|
-
|
|
|
atombios_apply_encoder_quirks(encoder, adjusted_mode);
|
|
|
|
|
|
if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI) {
|
|
@@ -2116,7 +2129,6 @@ static void radeon_atom_encoder_prepare(struct drm_encoder *encoder)
|
|
|
}
|
|
|
|
|
|
radeon_atom_output_lock(encoder, true);
|
|
|
- radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
|
|
|
|
|
|
if (connector) {
|
|
|
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
|
|
@@ -2137,6 +2149,7 @@ static void radeon_atom_encoder_prepare(struct drm_encoder *encoder)
|
|
|
|
|
|
static void radeon_atom_encoder_commit(struct drm_encoder *encoder)
|
|
|
{
|
|
|
+ /* need to call this here as we need the crtc set up */
|
|
|
radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_ON);
|
|
|
radeon_atom_output_lock(encoder, false);
|
|
|
}
|
|
@@ -2177,14 +2190,7 @@ static void radeon_atom_encoder_disable(struct drm_encoder *encoder)
|
|
|
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);
|
|
|
- else {
|
|
|
- /* disable the encoder and transmitter */
|
|
|
- atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
|
|
|
- atombios_dig_encoder_setup(encoder, ATOM_DISABLE, 0);
|
|
|
- }
|
|
|
+ /* handled in dpms */
|
|
|
break;
|
|
|
case ENCODER_OBJECT_ID_INTERNAL_DDI:
|
|
|
case ENCODER_OBJECT_ID_INTERNAL_DVO1:
|