drm/radeon/kms/atom: rework encoder dpms
authorAlex Deucher <alexander.deucher@amd.com>
Wed, 26 Oct 2011 00:17:45 +0000 (20:17 -0400)
committerDave Airlie <airlied@redhat.com>
Tue, 1 Nov 2011 16:04:53 +0000 (16:04 +0000)
The existing function was getting too big and complex.
Break it down into a more manageable set of functions.

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
drivers/gpu/drm/radeon/radeon_encoders.c

index 9838865e223b623c719a05805441cb831f2df2e0..f01b6b135b992faa3655c12ee19e548909003d6d 100644 (file)
@@ -1356,45 +1356,25 @@ atombios_yuv_setup(struct drm_encoder *encoder, bool enable)
 }
 
 static void
-radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
+radeon_atom_encoder_dpms_avivo(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_atom_get_external_encoder(encoder);
        DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION args;
        int index = 0;
-       bool is_dig = false;
-       bool is_dce5_dac = false;
-       bool is_dce5_dvo = false;
 
        memset(&args, 0, sizeof(args));
 
-       DRM_DEBUG_KMS("encoder dpms %d to mode %d, devices %08x, active_devices %08x\n",
-                 radeon_encoder->encoder_id, mode, radeon_encoder->devices,
-                 radeon_encoder->active_device);
        switch (radeon_encoder->encoder_id) {
        case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
        case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
                index = GetIndexIntoMasterTable(COMMAND, TMDSAOutputControl);
                break;
-       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
-       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
-       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
-       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
-               is_dig = true;
-               break;
        case ENCODER_OBJECT_ID_INTERNAL_DVO1:
        case ENCODER_OBJECT_ID_INTERNAL_DDI:
-               index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl);
-               break;
        case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
-               if (ASIC_IS_DCE5(rdev))
-                       is_dce5_dvo = true;
-               else if (ASIC_IS_DCE3(rdev))
-                       is_dig = true;
-               else
-                       index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl);
+               index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl);
                break;
        case ENCODER_OBJECT_ID_INTERNAL_LVDS:
                index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl);
@@ -1407,16 +1387,12 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
                break;
        case ENCODER_OBJECT_ID_INTERNAL_DAC1:
        case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
-               if (ASIC_IS_DCE5(rdev))
-                       is_dce5_dac = true;
-               else {
-                       if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
-                               index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl);
-                       else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
-                               index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl);
-                       else
-                               index = GetIndexIntoMasterTable(COMMAND, DAC1OutputControl);
-               }
+               if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
+                       index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl);
+               else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
+                       index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl);
+               else
+                       index = GetIndexIntoMasterTable(COMMAND, DAC1OutputControl);
                break;
        case ENCODER_OBJECT_ID_INTERNAL_DAC2:
        case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
@@ -1427,138 +1403,196 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
                else
                        index = GetIndexIntoMasterTable(COMMAND, DAC2OutputControl);
                break;
+       default:
+               return;
        }
 
-       if (is_dig) {
-               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))
-                               atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
-                       else
-                               atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0);
-                       if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP) {
-                               struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
+       switch (mode) {
+       case DRM_MODE_DPMS_ON:
+               args.ucAction = ATOM_ENABLE;
+               /* workaround for DVOOutputControl on some RS690 systems */
+               if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DDI) {
+                       u32 reg = RREG32(RADEON_BIOS_3_SCRATCH);
+                       WREG32(RADEON_BIOS_3_SCRATCH, reg & ~ATOM_S3_DFP2I_ACTIVE);
+                       atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+                       WREG32(RADEON_BIOS_3_SCRATCH, reg);
+               } else
+                       atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+               if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
+                       args.ucAction = ATOM_LCD_BLON;
+                       atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+               }
+               break;
+       case DRM_MODE_DPMS_STANDBY:
+       case DRM_MODE_DPMS_SUSPEND:
+       case DRM_MODE_DPMS_OFF:
+               args.ucAction = ATOM_DISABLE;
+               atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+               if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
+                       args.ucAction = ATOM_LCD_BLOFF;
+                       atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+               }
+               break;
+       }
+}
 
-                               if (connector &&
-                                   (connector->connector_type == DRM_MODE_CONNECTOR_eDP)) {
-                                       struct radeon_connector *radeon_connector = to_radeon_connector(connector);
-                                       struct radeon_connector_atom_dig *radeon_dig_connector =
-                                               radeon_connector->con_priv;
-                                       atombios_set_edp_panel_power(connector,
-                                                                    ATOM_TRANSMITTER_ACTION_POWER_ON);
-                                       radeon_dig_connector->edp_on = true;
-                               }
-                               if (ASIC_IS_DCE4(rdev))
-                                       atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0);
-                               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);
-                       break;
-               case DRM_MODE_DPMS_STANDBY:
-               case DRM_MODE_DPMS_SUSPEND:
-               case DRM_MODE_DPMS_OFF:
-                       atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT, 0, 0);
-                       if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP) {
-                               struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
+static void
+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_connector *connector = radeon_get_connector_for_encoder(encoder);
+       struct radeon_connector *radeon_connector = NULL;
+       struct radeon_connector_atom_dig *radeon_dig_connector = NULL;
 
-                               if (ASIC_IS_DCE4(rdev))
-                                       atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0);
-                               if (connector &&
-                                   (connector->connector_type == DRM_MODE_CONNECTOR_eDP)) {
-                                       struct radeon_connector *radeon_connector = to_radeon_connector(connector);
-                                       struct radeon_connector_atom_dig *radeon_dig_connector =
-                                               radeon_connector->con_priv;
-                                       atombios_set_edp_panel_power(connector,
-                                                                    ATOM_TRANSMITTER_ACTION_POWER_OFF);
-                                       radeon_dig_connector->edp_on = false;
-                               }
+       if (connector) {
+               radeon_connector = to_radeon_connector(connector);
+               radeon_dig_connector = radeon_connector->con_priv;
+       }
+
+       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))
+                       atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
+               else
+                       atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0);
+               if ((atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP) && connector) {
+                       if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
+                               atombios_set_edp_panel_power(connector,
+                                                            ATOM_TRANSMITTER_ACTION_POWER_ON);
+                               radeon_dig_connector->edp_on = true;
                        }
-                       if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
-                               atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_LCD_BLOFF, 0, 0);
-                       break;
-               }
-       } else if (is_dce5_dac) {
-               switch (mode) {
-               case DRM_MODE_DPMS_ON:
-                       atombios_dac_setup(encoder, ATOM_ENABLE);
-                       break;
-               case DRM_MODE_DPMS_STANDBY:
-               case DRM_MODE_DPMS_SUSPEND:
-               case DRM_MODE_DPMS_OFF:
-                       atombios_dac_setup(encoder, ATOM_DISABLE);
-                       break;
-               }
-       } else if (is_dce5_dvo) {
-               switch (mode) {
-               case DRM_MODE_DPMS_ON:
-                       atombios_dvo_setup(encoder, ATOM_ENABLE);
-                       break;
-               case DRM_MODE_DPMS_STANDBY:
-               case DRM_MODE_DPMS_SUSPEND:
-               case DRM_MODE_DPMS_OFF:
-                       atombios_dvo_setup(encoder, ATOM_DISABLE);
-                       break;
+                       if (ASIC_IS_DCE4(rdev))
+                               atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0);
+                       radeon_dp_link_train(encoder, connector);
+                       if (ASIC_IS_DCE4(rdev))
+                               atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_ON, 0);
                }
-       } else {
-               switch (mode) {
-               case DRM_MODE_DPMS_ON:
-                       args.ucAction = ATOM_ENABLE;
-                       /* workaround for DVOOutputControl on some RS690 systems */
-                       if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DDI) {
-                               u32 reg = RREG32(RADEON_BIOS_3_SCRATCH);
-                               WREG32(RADEON_BIOS_3_SCRATCH, reg & ~ATOM_S3_DFP2I_ACTIVE);
-                               atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
-                               WREG32(RADEON_BIOS_3_SCRATCH, reg);
-                       } else
-                               atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
-                       if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
-                               args.ucAction = ATOM_LCD_BLON;
-                               atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
-                       }
-                       break;
-               case DRM_MODE_DPMS_STANDBY:
-               case DRM_MODE_DPMS_SUSPEND:
-               case DRM_MODE_DPMS_OFF:
-                       args.ucAction = ATOM_DISABLE;
-                       atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
-                       if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
-                               args.ucAction = ATOM_LCD_BLOFF;
-                               atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+               if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
+                       atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_LCD_BLON, 0, 0);
+               break;
+       case DRM_MODE_DPMS_STANDBY:
+       case DRM_MODE_DPMS_SUSPEND:
+       case DRM_MODE_DPMS_OFF:
+               atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT, 0, 0);
+               if ((atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP) && connector) {
+                       if (ASIC_IS_DCE4(rdev))
+                               atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0);
+                       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;
                        }
-                       break;
                }
+               if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
+                       atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_LCD_BLOFF, 0, 0);
+               break;
        }
+}
 
-       if (ext_encoder) {
-               switch (mode) {
-               case DRM_MODE_DPMS_ON:
-               default:
-                       if (ASIC_IS_DCE41(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)) {
-                               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;
-               }
+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)) {
+                       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)) {
+                       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;
+       }
+}
+
+static void
+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_atom_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,
+                 radeon_encoder->active_device);
+       switch (radeon_encoder->encoder_id) {
+       case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
+       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
+       case ENCODER_OBJECT_ID_INTERNAL_LVDS:
+       case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
+       case ENCODER_OBJECT_ID_INTERNAL_DVO1:
+       case ENCODER_OBJECT_ID_INTERNAL_DDI:
+       case ENCODER_OBJECT_ID_INTERNAL_DAC2:
+       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
+               radeon_atom_encoder_dpms_avivo(encoder, mode);
+               break;
+       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
+       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
+       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
+               radeon_atom_encoder_dpms_dig(encoder, mode);
+               break;
+       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
+               if (ASIC_IS_DCE5(rdev)) {
+                       switch (mode) {
+                       case DRM_MODE_DPMS_ON:
+                               atombios_dvo_setup(encoder, ATOM_ENABLE);
+                               break;
+                       case DRM_MODE_DPMS_STANDBY:
+                       case DRM_MODE_DPMS_SUSPEND:
+                       case DRM_MODE_DPMS_OFF:
+                               atombios_dvo_setup(encoder, ATOM_DISABLE);
+                               break;
+                       }
+               } else if (ASIC_IS_DCE3(rdev))
+                       radeon_atom_encoder_dpms_dig(encoder, mode);
+               else
+                       radeon_atom_encoder_dpms_avivo(encoder, mode);
+               break;
+       case ENCODER_OBJECT_ID_INTERNAL_DAC1:
+       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
+               if (ASIC_IS_DCE5(rdev)) {
+                       switch (mode) {
+                       case DRM_MODE_DPMS_ON:
+                               atombios_dac_setup(encoder, ATOM_ENABLE);
+                               break;
+                       case DRM_MODE_DPMS_STANDBY:
+                       case DRM_MODE_DPMS_SUSPEND:
+                       case DRM_MODE_DPMS_OFF:
+                               atombios_dac_setup(encoder, ATOM_DISABLE);
+                               break;
+                       }
+               } else
+                       radeon_atom_encoder_dpms_avivo(encoder, mode);
+               break;
+       default:
+               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);
 
 }