Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
[pandora-kernel.git] / drivers / gpu / drm / radeon / radeon_atombios.c
index 9916d82..24ea683 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,11 +680,19 @@ 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;
 }
 
@@ -1174,7 +1181,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 =
@@ -1442,26 +1449,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 {
@@ -1485,7 +1496,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)) {
@@ -1498,10 +1509,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) {
@@ -1515,13 +1535,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) {
@@ -1542,6 +1556,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 =
@@ -1555,15 +1571,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;
@@ -1577,13 +1601,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);
@@ -1605,6 +1623,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 =
@@ -1618,18 +1639,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;
@@ -1643,13 +1675,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);
@@ -1677,6 +1703,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 =
@@ -1690,42 +1719,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 *)
@@ -1754,14 +1817,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 =
@@ -1781,12 +1864,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 =
@@ -1798,7 +1875,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) {
@@ -1815,22 +1894,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;
@@ -1840,18 +1933,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)