drm/radeon/atom: rework encoder enable/disable sequence
authorAlex Deucher <alexdeucher@gmail.com>
Tue, 18 Mar 2014 03:48:16 +0000 (23:48 -0400)
committerChristian König <christian.koenig@amd.com>
Tue, 25 Mar 2014 12:13:17 +0000 (13:13 +0100)
This more closely matches what the vbios does and also
adds a quirk for travis lvds displays and powers down
the sink on DP displays which saves some power and may
fix display issues in some cases.

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Acked-by: Christian König <christian.koenig@amd.com>
drivers/gpu/drm/radeon/atombios_encoders.c

index 607dc14d195e3540f103bf798d2e6f0e10e5634f..e6eb5097597f6088dde34638ee9b94cca5bc8950 100644 (file)
@@ -1633,10 +1633,16 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode)
        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;
+       bool travis_quirk = false;
 
        if (connector) {
                radeon_connector = to_radeon_connector(connector);
                radeon_dig_connector = radeon_connector->con_priv;
+               if ((radeon_connector_encoder_get_dp_bridge_encoder_id(connector) ==
+                    ENCODER_OBJECT_ID_TRAVIS) &&
+                   (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) &&
+                   !ASIC_IS_DCE5(rdev))
+                       travis_quirk = true;
        }
 
        switch (mode) {
@@ -1657,17 +1663,13 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode)
                                        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 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);
                } 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);
                }
                if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) {
                        if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
@@ -1675,68 +1677,56 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode)
                                                             ATOM_TRANSMITTER_ACTION_POWER_ON);
                                radeon_dig_connector->edp_on = true;
                        }
+               }
+               /* enable the transmitter */
+               atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
+               if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) {
+                       /* DP_SET_POWER_D0 is set in radeon_dp_link_train */
                        radeon_dp_link_train(encoder, connector);
                        if (ASIC_IS_DCE4(rdev))
                                atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_ON, 0);
                }
                if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
-                       atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_LCD_BLON, 0, 0);
+                       atombios_dig_transmitter_setup(encoder,
+                                                      ATOM_TRANSMITTER_ACTION_LCD_BLON, 0, 0);
+               if (ext_encoder)
+                       atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE);
                break;
        case DRM_MODE_DPMS_STANDBY:
        case DRM_MODE_DPMS_SUSPEND:
        case DRM_MODE_DPMS_OFF:
+               if (ASIC_IS_DCE4(rdev)) {
+                       if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector)
+                               atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0);
+               }
+               if (ext_encoder)
+                       atombios_external_encoder_setup(encoder, ext_encoder, ATOM_DISABLE);
+               if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
+                       atombios_dig_transmitter_setup(encoder,
+                                                      ATOM_TRANSMITTER_ACTION_LCD_BLOFF, 0, 0);
+
+               if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) &&
+                   connector && !travis_quirk)
+                       radeon_dp_set_rx_power_state(connector, DP_SET_POWER_D3);
                if (ASIC_IS_DCE4(rdev)) {
                        /* disable the transmitter */
-                       atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 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, 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);
+                       if (travis_quirk)
+                               radeon_dp_set_rx_power_state(connector, DP_SET_POWER_D3);
                        if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
                                atombios_set_edp_panel_power(connector,
                                                             ATOM_TRANSMITTER_ACTION_POWER_OFF);
                                radeon_dig_connector->edp_on = false;
                        }
                }
-               if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
-                       atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_LCD_BLOFF, 0, 0);
-               break;
-       }
-}
-
-static void
-radeon_atom_encoder_dpms_ext(struct drm_encoder *encoder,
-                            struct drm_encoder *ext_encoder,
-                            int mode)
-{
-       struct drm_device *dev = encoder->dev;
-       struct radeon_device *rdev = dev->dev_private;
-
-       switch (mode) {
-       case DRM_MODE_DPMS_ON:
-       default:
-               if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(rdev)) {
-                       atombios_external_encoder_setup(encoder, ext_encoder,
-                                                       EXTERNAL_ENCODER_ACTION_V3_ENABLE_OUTPUT);
-                       atombios_external_encoder_setup(encoder, ext_encoder,
-                                                       EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING_OFF);
-               } else
-                       atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE);
-               break;
-       case DRM_MODE_DPMS_STANDBY:
-       case DRM_MODE_DPMS_SUSPEND:
-       case DRM_MODE_DPMS_OFF:
-               if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(rdev)) {
-                       atombios_external_encoder_setup(encoder, ext_encoder,
-                                                       EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING);
-                       atombios_external_encoder_setup(encoder, ext_encoder,
-                                                       EXTERNAL_ENCODER_ACTION_V3_DISABLE_OUTPUT);
-               } else
-                       atombios_external_encoder_setup(encoder, ext_encoder, ATOM_DISABLE);
                break;
        }
 }
@@ -1747,7 +1737,6 @@ radeon_atom_encoder_dpms(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);
 
        DRM_DEBUG_KMS("encoder dpms %d to mode %d, devices %08x, active_devices %08x\n",
                  radeon_encoder->encoder_id, mode, radeon_encoder->devices,
@@ -1807,9 +1796,6 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
                return;
        }
 
-       if (ext_encoder)
-               radeon_atom_encoder_dpms_ext(encoder, ext_encoder, mode);
-
        radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
 
 }