drm/radeon/kms/pm: Disable voltage adjust on RS780/RS880
[safe/jmp/linux-2.6] / drivers / gpu / drm / radeon / radeon_atombios.c
index dbfb837..f0fcd6c 100644 (file)
@@ -530,6 +530,8 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
                        }
 
                        /* look up gpio for ddc, hpd */
+                       ddc_bus.valid = false;
+                       hpd.hpd = RADEON_HPD_NONE;
                        if ((le16_to_cpu(path->usDeviceTag) &
                             (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) == 0) {
                                for (j = 0; j < con_obj->ucNumberOfObjects; j++) {
@@ -547,7 +549,6 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
                                                ATOM_I2C_RECORD *i2c_record;
                                                ATOM_HPD_INT_RECORD *hpd_record;
                                                ATOM_I2C_ID_CONFIG_ACCESS *i2c_config;
-                                               hpd.hpd = RADEON_HPD_NONE;
 
                                                while (record->ucRecordType > 0
                                                       && record->
@@ -585,13 +586,10 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
                                                break;
                                        }
                                }
-                       } else {
-                               hpd.hpd = RADEON_HPD_NONE;
-                               ddc_bus.valid = false;
                        }
 
                        /* needed for aux chan transactions */
-                       ddc_bus.hpd_id = hpd.hpd ? (hpd.hpd - 1) : 0;
+                       ddc_bus.hpd = hpd.hpd;
 
                        conn_id = le16_to_cpu(path->usConnObjectId);
 
@@ -682,10 +680,18 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct
        uint8_t dac;
        union atom_supported_devices *supported_devices;
        int i, j, max_device;
-       struct bios_connector bios_connectors[ATOM_MAX_SUPPORTED_DEVICE];
+       struct bios_connector *bios_connectors;
+       size_t bc_size = sizeof(*bios_connectors) * ATOM_MAX_SUPPORTED_DEVICE;
 
-       if (!atom_parse_data_header(ctx, index, &size, &frev, &crev, &data_offset))
+       bios_connectors = kzalloc(bc_size, GFP_KERNEL);
+       if (!bios_connectors)
+               return false;
+
+       if (!atom_parse_data_header(ctx, index, &size, &frev, &crev,
+                                   &data_offset)) {
+               kfree(bios_connectors);
                return false;
+       }
 
        supported_devices =
            (union atom_supported_devices *)(ctx->bios + data_offset);
@@ -853,6 +859,7 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct
 
        radeon_link_encoder_connector(dev);
 
+       kfree(bios_connectors);
        return true;
 }
 
@@ -1264,7 +1271,7 @@ bool radeon_atom_get_tv_timings(struct radeon_device *rdev, int index,
        switch (crev) {
        case 1:
                tv_info = (ATOM_ANALOG_TV_INFO *)(mode_info->atom_context->bios + data_offset);
-               if (index > MAX_SUPPORTED_TV_TIMING)
+               if (index >= MAX_SUPPORTED_TV_TIMING)
                        return false;
 
                mode->crtc_htotal = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_Total);
@@ -1302,7 +1309,7 @@ bool radeon_atom_get_tv_timings(struct radeon_device *rdev, int index,
                break;
        case 2:
                tv_info_v1_2 = (ATOM_ANALOG_TV_INFO_V1_2 *)(mode_info->atom_context->bios + data_offset);
-               if (index > MAX_SUPPORTED_TV_TIMING_V1_2)
+               if (index >= MAX_SUPPORTED_TV_TIMING_V1_2)
                        return false;
 
                dtd_timings = &tv_info_v1_2->aModeTimings[index];
@@ -1442,29 +1449,29 @@ radeon_atombios_get_tv_dac_info(struct radeon_encoder *encoder)
 
 static const char *thermal_controller_names[] = {
        "NONE",
-       "LM63",
-       "ADM1032",
-       "ADM1030",
-       "MUA6649",
-       "LM64",
-       "F75375",
-       "ASC7512",
+       "lm63",
+       "adm1032",
+       "adm1030",
+       "max6649",
+       "lm64",
+       "f75375",
+       "asc7xxx",
 };
 
 static const char *pp_lib_thermal_controller_names[] = {
        "NONE",
-       "LM63",
-       "ADM1032",
-       "ADM1030",
-       "MUA6649",
-       "LM64",
-       "F75375",
+       "lm63",
+       "adm1032",
+       "adm1030",
+       "max6649",
+       "lm64",
+       "f75375",
        "RV6xx",
        "RV770",
-       "ADT7473",
+       "adt7473",
        "External GPIO",
        "Evergreen",
-       "ADT7473 with internal",
+       "adt7473 with internal",
 
 };
 
@@ -1502,6 +1509,14 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
                                         power_info->info.ucOverdriveControllerAddress >> 1);
                                i2c_bus = radeon_lookup_i2c_gpio(rdev, power_info->info.ucOverdriveI2cLine);
                                rdev->pm.i2c_bus = radeon_i2c_create(rdev->ddev, &i2c_bus, "Thermal");
+                               if (rdev->pm.i2c_bus) {
+                                       struct i2c_board_info info = { };
+                                       const char *name = thermal_controller_names[power_info->info.
+                                                                                   ucOverdriveThermalController];
+                                       info.addr = power_info->info.ucOverdriveControllerAddress >> 1;
+                                       strlcpy(info.type, name, sizeof(info.type));
+                                       i2c_new_device(&rdev->pm.i2c_bus->adapter, &info);
+                               }
                        }
                        num_modes = power_info->info.ucNumOfPowerModeEntries;
                        if (num_modes > ATOM_MAX_NUMBEROF_POWER_BLOCK)
@@ -1520,10 +1535,11 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
                                        if ((rdev->pm.power_state[state_index].clock_info[0].mclk == 0) ||
                                            (rdev->pm.power_state[state_index].clock_info[0].sclk == 0))
                                                continue;
-                                       rdev->pm.power_state[state_index].non_clock_info.pcie_lanes =
+                                       rdev->pm.power_state[state_index].pcie_lanes =
                                                power_info->info.asPowerPlayInfo[i].ucNumPciELanes;
                                        misc = le32_to_cpu(power_info->info.asPowerPlayInfo[i].ulMiscInfo);
-                                       if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) {
+                                       if ((misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) ||
+                                           (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)) {
                                                rdev->pm.power_state[state_index].clock_info[0].voltage.type =
                                                        VOLTAGE_GPIO;
                                                rdev->pm.power_state[state_index].clock_info[0].voltage.gpio =
@@ -1541,7 +1557,8 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
                                                rdev->pm.power_state[state_index].clock_info[0].voltage.vddc_id =
                                                        power_info->info.asPowerPlayInfo[i].ucVoltageDropIndex;
                                        }
-                                       rdev->pm.power_state[state_index].flags = RADEON_PM_SINGLE_DISPLAY_ONLY;
+                                       rdev->pm.power_state[state_index].flags = RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
+                                       rdev->pm.power_state[state_index].misc = misc;
                                        /* order matters! */
                                        if (misc & ATOM_PM_MISCINFO_POWER_SAVING_MODE)
                                                rdev->pm.power_state[state_index].type =
@@ -1559,7 +1576,7 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
                                                rdev->pm.power_state[state_index].type =
                                                        POWER_STATE_TYPE_PERFORMANCE;
                                                rdev->pm.power_state[state_index].flags &=
-                                                       ~RADEON_PM_SINGLE_DISPLAY_ONLY;
+                                                       ~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
                                        }
                                        if (misc & ATOM_PM_MISCINFO_DRIVER_DEFAULT_MODE) {
                                                rdev->pm.power_state[state_index].type =
@@ -1568,7 +1585,10 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
                                                rdev->pm.power_state[state_index].default_clock_mode =
                                                        &rdev->pm.power_state[state_index].clock_info[0];
                                                rdev->pm.power_state[state_index].flags &=
-                                                       ~RADEON_PM_SINGLE_DISPLAY_ONLY;
+                                                       ~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
+                                       } else if (state_index == 0) {
+                                               rdev->pm.power_state[state_index].clock_info[0].flags |=
+                                                       RADEON_PM_MODE_NO_DISPLAY;
                                        }
                                        state_index++;
                                        break;
@@ -1582,11 +1602,12 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
                                        if ((rdev->pm.power_state[state_index].clock_info[0].mclk == 0) ||
                                            (rdev->pm.power_state[state_index].clock_info[0].sclk == 0))
                                                continue;
-                                       rdev->pm.power_state[state_index].non_clock_info.pcie_lanes =
+                                       rdev->pm.power_state[state_index].pcie_lanes =
                                                power_info->info_2.asPowerPlayInfo[i].ucNumPciELanes;
                                        misc = le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMiscInfo);
                                        misc2 = le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMiscInfo2);
-                                       if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) {
+                                       if ((misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) ||
+                                           (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)) {
                                                rdev->pm.power_state[state_index].clock_info[0].voltage.type =
                                                        VOLTAGE_GPIO;
                                                rdev->pm.power_state[state_index].clock_info[0].voltage.gpio =
@@ -1604,7 +1625,9 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
                                                rdev->pm.power_state[state_index].clock_info[0].voltage.vddc_id =
                                                        power_info->info_2.asPowerPlayInfo[i].ucVoltageDropIndex;
                                        }
-                                       rdev->pm.power_state[state_index].flags = RADEON_PM_SINGLE_DISPLAY_ONLY;
+                                       rdev->pm.power_state[state_index].flags = RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
+                                       rdev->pm.power_state[state_index].misc = misc;
+                                       rdev->pm.power_state[state_index].misc2 = misc2;
                                        /* order matters! */
                                        if (misc & ATOM_PM_MISCINFO_POWER_SAVING_MODE)
                                                rdev->pm.power_state[state_index].type =
@@ -1622,14 +1645,14 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
                                                rdev->pm.power_state[state_index].type =
                                                        POWER_STATE_TYPE_PERFORMANCE;
                                                rdev->pm.power_state[state_index].flags &=
-                                                       ~RADEON_PM_SINGLE_DISPLAY_ONLY;
+                                                       ~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
                                        }
                                        if (misc2 & ATOM_PM_MISCINFO2_SYSTEM_AC_LITE_MODE)
                                                rdev->pm.power_state[state_index].type =
                                                        POWER_STATE_TYPE_BALANCED;
                                        if (misc2 & ATOM_PM_MISCINFO2_MULTI_DISPLAY_SUPPORT)
                                                rdev->pm.power_state[state_index].flags &=
-                                                       ~RADEON_PM_SINGLE_DISPLAY_ONLY;
+                                                       ~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
                                        if (misc & ATOM_PM_MISCINFO_DRIVER_DEFAULT_MODE) {
                                                rdev->pm.power_state[state_index].type =
                                                        POWER_STATE_TYPE_DEFAULT;
@@ -1637,7 +1660,10 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
                                                rdev->pm.power_state[state_index].default_clock_mode =
                                                        &rdev->pm.power_state[state_index].clock_info[0];
                                                rdev->pm.power_state[state_index].flags &=
-                                                       ~RADEON_PM_SINGLE_DISPLAY_ONLY;
+                                                       ~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
+                                       } else if (state_index == 0) {
+                                               rdev->pm.power_state[state_index].clock_info[0].flags |=
+                                                       RADEON_PM_MODE_NO_DISPLAY;
                                        }
                                        state_index++;
                                        break;
@@ -1651,11 +1677,12 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
                                        if ((rdev->pm.power_state[state_index].clock_info[0].mclk == 0) ||
                                            (rdev->pm.power_state[state_index].clock_info[0].sclk == 0))
                                                continue;
-                                       rdev->pm.power_state[state_index].non_clock_info.pcie_lanes =
+                                       rdev->pm.power_state[state_index].pcie_lanes =
                                                power_info->info_3.asPowerPlayInfo[i].ucNumPciELanes;
                                        misc = le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMiscInfo);
                                        misc2 = le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMiscInfo2);
-                                       if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) {
+                                       if ((misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) ||
+                                           (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)) {
                                                rdev->pm.power_state[state_index].clock_info[0].voltage.type =
                                                        VOLTAGE_GPIO;
                                                rdev->pm.power_state[state_index].clock_info[0].voltage.gpio =
@@ -1679,7 +1706,9 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
                                                        power_info->info_3.asPowerPlayInfo[i].ucVDDCI_VoltageDropIndex;
                                                }
                                        }
-                                       rdev->pm.power_state[state_index].flags = RADEON_PM_SINGLE_DISPLAY_ONLY;
+                                       rdev->pm.power_state[state_index].flags = RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
+                                       rdev->pm.power_state[state_index].misc = misc;
+                                       rdev->pm.power_state[state_index].misc2 = misc2;
                                        /* order matters! */
                                        if (misc & ATOM_PM_MISCINFO_POWER_SAVING_MODE)
                                                rdev->pm.power_state[state_index].type =
@@ -1697,7 +1726,7 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
                                                rdev->pm.power_state[state_index].type =
                                                        POWER_STATE_TYPE_PERFORMANCE;
                                                rdev->pm.power_state[state_index].flags &=
-                                                       ~RADEON_PM_SINGLE_DISPLAY_ONLY;
+                                                       ~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
                                        }
                                        if (misc2 & ATOM_PM_MISCINFO2_SYSTEM_AC_LITE_MODE)
                                                rdev->pm.power_state[state_index].type =
@@ -1708,6 +1737,9 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
                                                rdev->pm.default_power_state_index = state_index;
                                                rdev->pm.power_state[state_index].default_clock_mode =
                                                        &rdev->pm.power_state[state_index].clock_info[0];
+                                       } else if (state_index == 0) {
+                                               rdev->pm.power_state[state_index].clock_info[0].flags |=
+                                                       RADEON_PM_MODE_NO_DISPLAY;
                                        }
                                        state_index++;
                                        break;
@@ -1721,31 +1753,55 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
                                rdev->pm.power_state[state_index - 1].default_clock_mode =
                                        &rdev->pm.power_state[state_index - 1].clock_info[0];
                                rdev->pm.power_state[state_index].flags &=
-                                       ~RADEON_PM_SINGLE_DISPLAY_ONLY;
+                                       ~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
+                               rdev->pm.power_state[state_index].misc = 0;
+                               rdev->pm.power_state[state_index].misc2 = 0;
                        }
                } else {
+                       int fw_index = GetIndexIntoMasterTable(DATA, FirmwareInfo);
+                       uint8_t fw_frev, fw_crev;
+                       uint16_t fw_data_offset, vddc = 0;
+                       union firmware_info *firmware_info;
+                       ATOM_PPLIB_THERMALCONTROLLER *controller = &power_info->info_4.sThermalController;
+
+                       if (atom_parse_data_header(mode_info->atom_context, fw_index, NULL,
+                                                  &fw_frev, &fw_crev, &fw_data_offset)) {
+                               firmware_info =
+                                       (union firmware_info *)(mode_info->atom_context->bios +
+                                                               fw_data_offset);
+                               vddc = firmware_info->info_14.usBootUpVDDCVoltage;
+                       }
+
                        /* add the i2c bus for thermal/fan chip */
                        /* no support for internal controller yet */
-                       if (power_info->info_4.sThermalController.ucType > 0) {
-                               if ((power_info->info_4.sThermalController.ucType == ATOM_PP_THERMALCONTROLLER_RV6xx) ||
-                                   (power_info->info_4.sThermalController.ucType == ATOM_PP_THERMALCONTROLLER_RV770) ||
-                                   (power_info->info_4.sThermalController.ucType == ATOM_PP_THERMALCONTROLLER_EVERGREEN)) {
+                       if (controller->ucType > 0) {
+                               if ((controller->ucType == ATOM_PP_THERMALCONTROLLER_RV6xx) ||
+                                   (controller->ucType == ATOM_PP_THERMALCONTROLLER_RV770) ||
+                                   (controller->ucType == ATOM_PP_THERMALCONTROLLER_EVERGREEN)) {
                                        DRM_INFO("Internal thermal controller %s fan control\n",
-                                                (power_info->info_4.sThermalController.ucFanParameters &
+                                                (controller->ucFanParameters &
                                                  ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
-                               } else if ((power_info->info_4.sThermalController.ucType ==
+                               } else if ((controller->ucType ==
                                            ATOM_PP_THERMALCONTROLLER_EXTERNAL_GPIO) ||
-                                          (power_info->info_4.sThermalController.ucType ==
+                                          (controller->ucType ==
                                            ATOM_PP_THERMALCONTROLLER_ADT7473_WITH_INTERNAL)) {
                                        DRM_INFO("Special thermal controller config\n");
                                } else {
                                        DRM_INFO("Possible %s thermal controller at 0x%02x %s fan control\n",
-                                                pp_lib_thermal_controller_names[power_info->info_4.sThermalController.ucType],
-                                                power_info->info_4.sThermalController.ucI2cAddress >> 1,
-                                                (power_info->info_4.sThermalController.ucFanParameters &
+                                                pp_lib_thermal_controller_names[controller->ucType],
+                                                controller->ucI2cAddress >> 1,
+                                                (controller->ucFanParameters &
                                                  ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
-                                       i2c_bus = radeon_lookup_i2c_gpio(rdev, power_info->info_4.sThermalController.ucI2cLine);
+                                       i2c_bus = radeon_lookup_i2c_gpio(rdev, controller->ucI2cLine);
                                        rdev->pm.i2c_bus = radeon_i2c_create(rdev->ddev, &i2c_bus, "Thermal");
+                                       if (rdev->pm.i2c_bus) {
+                                               struct i2c_board_info info = { };
+                                               const char *name = pp_lib_thermal_controller_names[controller->ucType];
+                                               info.addr = controller->ucI2cAddress >> 1;
+                                               strlcpy(info.type, name, sizeof(info.type));
+                                               i2c_new_device(&rdev->pm.i2c_bus->adapter, &info);
+                                       }
+
                                }
                        }
                        /* first mode is usually default, followed by low to high */
@@ -1777,10 +1833,7 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
                                                /* skip invalid modes */
                                                if (rdev->pm.power_state[state_index].clock_info[mode_index].sclk == 0)
                                                        continue;
-                                               rdev->pm.power_state[state_index].clock_info[mode_index].voltage.type =
-                                                       VOLTAGE_SW;
-                                               rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage =
-                                                       clock_info->usVDDC;
+                                               /* voltage works differently on IGPs */
                                                mode_index++;
                                        } else if (ASIC_IS_DCE4(rdev)) {
                                                struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO *clock_info =
@@ -1835,7 +1888,9 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
                                if (mode_index) {
                                        misc = le32_to_cpu(non_clock_info->ulCapsAndSettings);
                                        misc2 = le16_to_cpu(non_clock_info->usClassification);
-                                       rdev->pm.power_state[state_index].non_clock_info.pcie_lanes =
+                                       rdev->pm.power_state[state_index].misc = misc;
+                                       rdev->pm.power_state[state_index].misc2 = misc2;
+                                       rdev->pm.power_state[state_index].pcie_lanes =
                                                ((misc & ATOM_PPLIB_PCIE_LINK_WIDTH_MASK) >>
                                                ATOM_PPLIB_PCIE_LINK_WIDTH_SHIFT) + 1;
                                        switch (misc2 & ATOM_PPLIB_CLASSIFICATION_UI_MASK) {
@@ -1855,17 +1910,33 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
                                        rdev->pm.power_state[state_index].flags = 0;
                                        if (misc & ATOM_PPLIB_SINGLE_DISPLAY_ONLY)
                                                rdev->pm.power_state[state_index].flags |=
-                                                       RADEON_PM_SINGLE_DISPLAY_ONLY;
+                                                       RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
                                        if (misc2 & ATOM_PPLIB_CLASSIFICATION_BOOT) {
                                                rdev->pm.power_state[state_index].type =
                                                        POWER_STATE_TYPE_DEFAULT;
                                                rdev->pm.default_power_state_index = state_index;
                                                rdev->pm.power_state[state_index].default_clock_mode =
                                                        &rdev->pm.power_state[state_index].clock_info[mode_index - 1];
+                                               /* patch the table values with the default slck/mclk from firmware info */
+                                               for (j = 0; j < mode_index; j++) {
+                                                       rdev->pm.power_state[state_index].clock_info[j].mclk =
+                                                               rdev->clock.default_mclk;
+                                                       rdev->pm.power_state[state_index].clock_info[j].sclk =
+                                                               rdev->clock.default_sclk;
+                                                       if (vddc)
+                                                               rdev->pm.power_state[state_index].clock_info[j].voltage.voltage =
+                                                                       vddc;
+                                               }
                                        }
                                        state_index++;
                                }
                        }
+                       /* if multiple clock modes, mark the lowest as no display */
+                       for (i = 0; i < state_index; i++) {
+                               if (rdev->pm.power_state[i].num_clock_modes > 1)
+                                       rdev->pm.power_state[i].clock_info[0].flags |=
+                                               RADEON_PM_MODE_NO_DISPLAY;
+                       }
                        /* first mode is usually default */
                        if (rdev->pm.default_power_state_index == -1) {
                                rdev->pm.power_state[0].type =
@@ -1885,10 +1956,7 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
                rdev->pm.power_state[state_index].default_clock_mode =
                        &rdev->pm.power_state[state_index].clock_info[0];
                rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE;
-               if (rdev->asic->get_pcie_lanes)
-                       rdev->pm.power_state[state_index].non_clock_info.pcie_lanes = radeon_get_pcie_lanes(rdev);
-               else
-                       rdev->pm.power_state[state_index].non_clock_info.pcie_lanes = 16;
+               rdev->pm.power_state[state_index].pcie_lanes = 16;
                rdev->pm.default_power_state_index = state_index;
                rdev->pm.power_state[state_index].flags = 0;
                state_index++;
@@ -1953,6 +2021,42 @@ void radeon_atom_set_memory_clock(struct radeon_device *rdev,
        atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
 }
 
+union set_voltage {
+       struct _SET_VOLTAGE_PS_ALLOCATION alloc;
+       struct _SET_VOLTAGE_PARAMETERS v1;
+       struct _SET_VOLTAGE_PARAMETERS_V2 v2;
+};
+
+void radeon_atom_set_voltage(struct radeon_device *rdev, u16 level)
+{
+       union set_voltage args;
+       int index = GetIndexIntoMasterTable(COMMAND, SetVoltage);
+       u8 frev, crev, volt_index = level;
+
+       if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
+               return;
+
+       switch (crev) {
+       case 1:
+               args.v1.ucVoltageType = SET_VOLTAGE_TYPE_ASIC_VDDC;
+               args.v1.ucVoltageMode = SET_ASIC_VOLTAGE_MODE_ALL_SOURCE;
+               args.v1.ucVoltageIndex = volt_index;
+               break;
+       case 2:
+               args.v2.ucVoltageType = SET_VOLTAGE_TYPE_ASIC_VDDC;
+               args.v2.ucVoltageMode = SET_ASIC_VOLTAGE_MODE_SET_VOLTAGE;
+               args.v2.usVoltageLevel = cpu_to_le16(level);
+               break;
+       default:
+               DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
+               return;
+       }
+
+       atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+}
+
+
+
 void radeon_atom_initialize_bios_scratch_regs(struct drm_device *dev)
 {
        struct radeon_device *rdev = dev->dev_private;