]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/gpu/drm/radeon/radeon_atombios.c
drm/radeon/kms: reset ddc_bus in object header parsing
[mv-sheeva.git] / drivers / gpu / drm / radeon / radeon_atombios.c
index 1fff95505cf5fec08f5506c47e26b8e00866632c..8cb4173365c37274d63c00233ff506583710fa71 100644 (file)
@@ -69,16 +69,19 @@ static inline struct radeon_i2c_bus_rec radeon_lookup_i2c_gpio(struct radeon_dev
        struct radeon_i2c_bus_rec i2c;
        int index = GetIndexIntoMasterTable(DATA, GPIO_I2C_Info);
        struct _ATOM_GPIO_I2C_INFO *i2c_info;
-       uint16_t data_offset;
-       int i;
+       uint16_t data_offset, size;
+       int i, num_indices;
 
        memset(&i2c, 0, sizeof(struct radeon_i2c_bus_rec));
        i2c.valid = false;
 
-       if (atom_parse_data_header(ctx, index, NULL, NULL, NULL, &data_offset)) {
+       if (atom_parse_data_header(ctx, index, &size, NULL, NULL, &data_offset)) {
                i2c_info = (struct _ATOM_GPIO_I2C_INFO *)(ctx->bios + data_offset);
 
-               for (i = 0; i < ATOM_MAX_SUPPORTED_DEVICE; i++) {
+               num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) /
+                       sizeof(ATOM_GPIO_I2C_ASSIGMENT);
+
+               for (i = 0; i < num_indices; i++) {
                        gpio = &i2c_info->asGPIO_Info[i];
 
                        if (gpio->sucI2cId.ucAccess == id) {
@@ -527,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++) {
@@ -582,9 +587,6 @@ 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 */
@@ -1171,7 +1173,7 @@ struct radeon_encoder_atom_dig *radeon_atombios_get_lvds_info(struct
                lvds->native_mode.vtotal = lvds->native_mode.vdisplay +
                        le16_to_cpu(lvds_info->info.sLCDTiming.usVBlanking_Time);
                lvds->native_mode.vsync_start = lvds->native_mode.vdisplay +
-                       le16_to_cpu(lvds_info->info.sLCDTiming.usVSyncWidth);
+                       le16_to_cpu(lvds_info->info.sLCDTiming.usVSyncOffset);
                lvds->native_mode.vsync_end = lvds->native_mode.vsync_start +
                        le16_to_cpu(lvds_info->info.sLCDTiming.usVSyncWidth);
                lvds->panel_pwr_delay =
@@ -1261,7 +1263,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);
@@ -1299,7 +1301,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];
@@ -1439,26 +1441,30 @@ 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",
+
 };
 
 union power_info {
@@ -1482,7 +1488,7 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
        int state_index = 0, mode_index = 0;
        struct radeon_i2c_bus_rec i2c_bus;
 
-       rdev->pm.default_power_state = NULL;
+       rdev->pm.default_power_state_index = -1;
 
        if (atom_parse_data_header(mode_info->atom_context, index, NULL,
                                   &frev, &crev, &data_offset)) {
@@ -1495,10 +1501,19 @@ 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)
                                num_modes = ATOM_MAX_NUMBEROF_POWER_BLOCK;
+                       /* last mode is usually default, array is low to high */
                        for (i = 0; i < num_modes; i++) {
                                rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE;
                                switch (frev) {
@@ -1512,13 +1527,7 @@ 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;
-                                       /* skip overclock modes for now */
-                                       if ((rdev->pm.power_state[state_index].clock_info[0].mclk >
-                                            rdev->clock.default_mclk + RADEON_MODE_OVERCLOCK_MARGIN) ||
-                                           (rdev->pm.power_state[state_index].clock_info[0].sclk >
-                                            rdev->clock.default_sclk + RADEON_MODE_OVERCLOCK_MARGIN))
-                                               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) {
@@ -1539,6 +1548,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_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 =
@@ -1552,15 +1563,23 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
                                        if (misc & ATOM_PM_MISCINFO_LOAD_BALANCE_EN)
                                                rdev->pm.power_state[state_index].type =
                                                        POWER_STATE_TYPE_BALANCED;
-                                       if (misc & ATOM_PM_MISCINFO_3D_ACCELERATION_EN)
+                                       if (misc & ATOM_PM_MISCINFO_3D_ACCELERATION_EN) {
                                                rdev->pm.power_state[state_index].type =
                                                        POWER_STATE_TYPE_PERFORMANCE;
+                                               rdev->pm.power_state[state_index].flags &=
+                                                       ~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;
-                                               rdev->pm.default_power_state = &rdev->pm.power_state[state_index];
+                                               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];
+                                               rdev->pm.power_state[state_index].flags &=
+                                                       ~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;
@@ -1574,13 +1593,7 @@ 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;
-                                       /* skip overclock modes for now */
-                                       if ((rdev->pm.power_state[state_index].clock_info[0].mclk >
-                                            rdev->clock.default_mclk + RADEON_MODE_OVERCLOCK_MARGIN) ||
-                                           (rdev->pm.power_state[state_index].clock_info[0].sclk >
-                                            rdev->clock.default_sclk + RADEON_MODE_OVERCLOCK_MARGIN))
-                                               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);
@@ -1602,6 +1615,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_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 =
@@ -1615,18 +1631,29 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
                                        if (misc & ATOM_PM_MISCINFO_LOAD_BALANCE_EN)
                                                rdev->pm.power_state[state_index].type =
                                                        POWER_STATE_TYPE_BALANCED;
-                                       if (misc & ATOM_PM_MISCINFO_3D_ACCELERATION_EN)
+                                       if (misc & ATOM_PM_MISCINFO_3D_ACCELERATION_EN) {
                                                rdev->pm.power_state[state_index].type =
                                                        POWER_STATE_TYPE_PERFORMANCE;
+                                               rdev->pm.power_state[state_index].flags &=
+                                                       ~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_STATE_SINGLE_DISPLAY_ONLY;
                                        if (misc & ATOM_PM_MISCINFO_DRIVER_DEFAULT_MODE) {
                                                rdev->pm.power_state[state_index].type =
                                                        POWER_STATE_TYPE_DEFAULT;
-                                               rdev->pm.default_power_state = &rdev->pm.power_state[state_index];
+                                               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];
+                                               rdev->pm.power_state[state_index].flags &=
+                                                       ~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;
@@ -1640,13 +1667,7 @@ 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;
-                                       /* skip overclock modes for now */
-                                       if ((rdev->pm.power_state[state_index].clock_info[0].mclk >
-                                            rdev->clock.default_mclk + RADEON_MODE_OVERCLOCK_MARGIN) ||
-                                           (rdev->pm.power_state[state_index].clock_info[0].sclk >
-                                            rdev->clock.default_sclk + RADEON_MODE_OVERCLOCK_MARGIN))
-                                               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);
@@ -1674,6 +1695,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_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 =
@@ -1687,42 +1711,76 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
                                        if (misc & ATOM_PM_MISCINFO_LOAD_BALANCE_EN)
                                                rdev->pm.power_state[state_index].type =
                                                        POWER_STATE_TYPE_BALANCED;
-                                       if (misc & ATOM_PM_MISCINFO_3D_ACCELERATION_EN)
+                                       if (misc & ATOM_PM_MISCINFO_3D_ACCELERATION_EN) {
                                                rdev->pm.power_state[state_index].type =
                                                        POWER_STATE_TYPE_PERFORMANCE;
+                                               rdev->pm.power_state[state_index].flags &=
+                                                       ~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 (misc & ATOM_PM_MISCINFO_DRIVER_DEFAULT_MODE) {
                                                rdev->pm.power_state[state_index].type =
                                                        POWER_STATE_TYPE_DEFAULT;
-                                               rdev->pm.default_power_state = &rdev->pm.power_state[state_index];
+                                               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;
                                }
                        }
-               } else if (frev == 4) {
+                       /* last mode is usually default */
+                       if (rdev->pm.default_power_state_index == -1) {
+                               rdev->pm.power_state[state_index - 1].type =
+                                       POWER_STATE_TYPE_DEFAULT;
+                               rdev->pm.default_power_state_index = state_index - 1;
+                               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_STATE_SINGLE_DISPLAY_ONLY;
+                               rdev->pm.power_state[state_index].misc = 0;
+                               rdev->pm.power_state[state_index].misc2 = 0;
+                       }
+               } else {
                        /* 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)) {
+                       ATOM_PPLIB_THERMALCONTROLLER *controller = &power_info->info_4.sThermalController;
+                       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 ((controller->ucType ==
+                                           ATOM_PP_THERMALCONTROLLER_EXTERNAL_GPIO) ||
+                                          (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 */
                        for (i = 0; i < power_info->info_4.ucNumStates; i++) {
                                mode_index = 0;
                                power_state = (struct _ATOM_PPLIB_STATE *)
@@ -1751,14 +1809,34 @@ 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;
-                                               /* skip overclock modes for now */
-                                               if (rdev->pm.power_state[state_index].clock_info[mode_index].sclk >
-                                                   rdev->clock.default_sclk + RADEON_MODE_OVERCLOCK_MARGIN)
+                                               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;
+                                               mode_index++;
+                                       } else if (ASIC_IS_DCE4(rdev)) {
+                                               struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO *clock_info =
+                                                       (struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO *)
+                                                       (mode_info->atom_context->bios +
+                                                        data_offset +
+                                                        le16_to_cpu(power_info->info_4.usClockInfoArrayOffset) +
+                                                        (power_state->ucClockStateIndices[j] *
+                                                         power_info->info_4.ucClockInfoSize));
+                                               sclk = le16_to_cpu(clock_info->usEngineClockLow);
+                                               sclk |= clock_info->ucEngineClockHigh << 16;
+                                               mclk = le16_to_cpu(clock_info->usMemoryClockLow);
+                                               mclk |= clock_info->ucMemoryClockHigh << 16;
+                                               rdev->pm.power_state[state_index].clock_info[mode_index].mclk = mclk;
+                                               rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk;
+                                               /* skip invalid modes */
+                                               if ((rdev->pm.power_state[state_index].clock_info[mode_index].mclk == 0) ||
+                                                   (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;
+                                               /* XXX usVDDCI */
                                                mode_index++;
                                        } else {
                                                struct _ATOM_PPLIB_R600_CLOCK_INFO *clock_info =
@@ -1778,12 +1856,6 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
                                                if ((rdev->pm.power_state[state_index].clock_info[mode_index].mclk == 0) ||
                                                    (rdev->pm.power_state[state_index].clock_info[mode_index].sclk == 0))
                                                        continue;
-                                               /* skip overclock modes for now */
-                                               if ((rdev->pm.power_state[state_index].clock_info[mode_index].mclk >
-                                                    rdev->clock.default_mclk + RADEON_MODE_OVERCLOCK_MARGIN) ||
-                                                   (rdev->pm.power_state[state_index].clock_info[mode_index].sclk >
-                                                    rdev->clock.default_sclk + RADEON_MODE_OVERCLOCK_MARGIN))
-                                                       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 =
@@ -1795,7 +1867,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) {
@@ -1812,22 +1886,36 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
                                                        POWER_STATE_TYPE_PERFORMANCE;
                                                break;
                                        }
+                                       rdev->pm.power_state[state_index].flags = 0;
+                                       if (misc & ATOM_PPLIB_SINGLE_DISPLAY_ONLY)
+                                               rdev->pm.power_state[state_index].flags |=
+                                                       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 = &rdev->pm.power_state[state_index];
+                                               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];
                                        }
                                        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 =
+                                       POWER_STATE_TYPE_DEFAULT;
+                               rdev->pm.default_power_state_index = 0;
+                               rdev->pm.power_state[0].default_clock_mode =
+                                       &rdev->pm.power_state[0].clock_info[0];
+                       }
                }
        } else {
-               /* XXX figure out some good default low power mode for cards w/out power tables */
-       }
-
-       if (rdev->pm.default_power_state == NULL) {
                /* add the default mode */
                rdev->pm.power_state[state_index].type =
                        POWER_STATE_TYPE_DEFAULT;
@@ -1837,18 +1925,16 @@ 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.default_power_state = &rdev->pm.power_state[state_index];
+               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++;
        }
+
        rdev->pm.num_power_states = state_index;
 
-       rdev->pm.current_power_state = rdev->pm.default_power_state;
-       rdev->pm.current_clock_mode =
-               rdev->pm.default_power_state->default_clock_mode;
+       rdev->pm.current_power_state_index = rdev->pm.default_power_state_index;
+       rdev->pm.current_clock_mode_index = 0;
 }
 
 void radeon_atom_set_clock_gating(struct radeon_device *rdev, int enable)