drm/radeon/kms/combios: fix typo in voltage fix
[safe/jmp/linux-2.6] / drivers / gpu / drm / radeon / radeon_atombios.c
index 93783b1..4305cd5 100644 (file)
@@ -69,52 +69,54 @@ 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;
 
-       atom_parse_data_header(ctx, index, NULL, NULL, NULL, &data_offset);
-
-       i2c_info = (struct _ATOM_GPIO_I2C_INFO *)(ctx->bios + data_offset);
-
-
-       for (i = 0; i < ATOM_MAX_SUPPORTED_DEVICE; i++) {
-               gpio = &i2c_info->asGPIO_Info[i];
-
-               if (gpio->sucI2cId.ucAccess == id) {
-                       i2c.mask_clk_reg = le16_to_cpu(gpio->usClkMaskRegisterIndex) * 4;
-                       i2c.mask_data_reg = le16_to_cpu(gpio->usDataMaskRegisterIndex) * 4;
-                       i2c.en_clk_reg = le16_to_cpu(gpio->usClkEnRegisterIndex) * 4;
-                       i2c.en_data_reg = le16_to_cpu(gpio->usDataEnRegisterIndex) * 4;
-                       i2c.y_clk_reg = le16_to_cpu(gpio->usClkY_RegisterIndex) * 4;
-                       i2c.y_data_reg = le16_to_cpu(gpio->usDataY_RegisterIndex) * 4;
-                       i2c.a_clk_reg = le16_to_cpu(gpio->usClkA_RegisterIndex) * 4;
-                       i2c.a_data_reg = le16_to_cpu(gpio->usDataA_RegisterIndex) * 4;
-                       i2c.mask_clk_mask = (1 << gpio->ucClkMaskShift);
-                       i2c.mask_data_mask = (1 << gpio->ucDataMaskShift);
-                       i2c.en_clk_mask = (1 << gpio->ucClkEnShift);
-                       i2c.en_data_mask = (1 << gpio->ucDataEnShift);
-                       i2c.y_clk_mask = (1 << gpio->ucClkY_Shift);
-                       i2c.y_data_mask = (1 << gpio->ucDataY_Shift);
-                       i2c.a_clk_mask = (1 << gpio->ucClkA_Shift);
-                       i2c.a_data_mask = (1 << gpio->ucDataA_Shift);
-
-                       if (gpio->sucI2cId.sbfAccess.bfHW_Capable)
-                               i2c.hw_capable = true;
-                       else
-                               i2c.hw_capable = false;
-
-                       if (gpio->sucI2cId.ucAccess == 0xa0)
-                               i2c.mm_i2c = true;
-                       else
-                               i2c.mm_i2c = false;
-
-                       i2c.i2c_id = gpio->sucI2cId.ucAccess;
-
-                       i2c.valid = true;
-                       break;
+       if (atom_parse_data_header(ctx, index, &size, NULL, NULL, &data_offset)) {
+               i2c_info = (struct _ATOM_GPIO_I2C_INFO *)(ctx->bios + data_offset);
+
+               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) {
+                               i2c.mask_clk_reg = le16_to_cpu(gpio->usClkMaskRegisterIndex) * 4;
+                               i2c.mask_data_reg = le16_to_cpu(gpio->usDataMaskRegisterIndex) * 4;
+                               i2c.en_clk_reg = le16_to_cpu(gpio->usClkEnRegisterIndex) * 4;
+                               i2c.en_data_reg = le16_to_cpu(gpio->usDataEnRegisterIndex) * 4;
+                               i2c.y_clk_reg = le16_to_cpu(gpio->usClkY_RegisterIndex) * 4;
+                               i2c.y_data_reg = le16_to_cpu(gpio->usDataY_RegisterIndex) * 4;
+                               i2c.a_clk_reg = le16_to_cpu(gpio->usClkA_RegisterIndex) * 4;
+                               i2c.a_data_reg = le16_to_cpu(gpio->usDataA_RegisterIndex) * 4;
+                               i2c.mask_clk_mask = (1 << gpio->ucClkMaskShift);
+                               i2c.mask_data_mask = (1 << gpio->ucDataMaskShift);
+                               i2c.en_clk_mask = (1 << gpio->ucClkEnShift);
+                               i2c.en_data_mask = (1 << gpio->ucDataEnShift);
+                               i2c.y_clk_mask = (1 << gpio->ucClkY_Shift);
+                               i2c.y_data_mask = (1 << gpio->ucDataY_Shift);
+                               i2c.a_clk_mask = (1 << gpio->ucClkA_Shift);
+                               i2c.a_data_mask = (1 << gpio->ucDataA_Shift);
+
+                               if (gpio->sucI2cId.sbfAccess.bfHW_Capable)
+                                       i2c.hw_capable = true;
+                               else
+                                       i2c.hw_capable = false;
+
+                               if (gpio->sucI2cId.ucAccess == 0xa0)
+                                       i2c.mm_i2c = true;
+                               else
+                                       i2c.mm_i2c = false;
+
+                               i2c.i2c_id = gpio->sucI2cId.ucAccess;
+
+                               i2c.valid = true;
+                               break;
+                       }
                }
        }
 
@@ -135,20 +137,21 @@ static inline struct radeon_gpio_rec radeon_lookup_gpio(struct radeon_device *rd
        memset(&gpio, 0, sizeof(struct radeon_gpio_rec));
        gpio.valid = false;
 
-       atom_parse_data_header(ctx, index, &size, NULL, NULL, &data_offset);
-
-       gpio_info = (struct _ATOM_GPIO_PIN_LUT *)(ctx->bios + data_offset);
+       if (atom_parse_data_header(ctx, index, &size, NULL, NULL, &data_offset)) {
+               gpio_info = (struct _ATOM_GPIO_PIN_LUT *)(ctx->bios + data_offset);
 
-       num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) / sizeof(ATOM_GPIO_PIN_ASSIGNMENT);
+               num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) /
+                       sizeof(ATOM_GPIO_PIN_ASSIGNMENT);
 
-       for (i = 0; i < num_indices; i++) {
-               pin = &gpio_info->asGPIO_Pin[i];
-               if (id == pin->ucGPIO_ID) {
-                       gpio.id = pin->ucGPIO_ID;
-                       gpio.reg = pin->usGpioPin_AIndex * 4;
-                       gpio.mask = (1 << pin->ucGpioPinBitShift);
-                       gpio.valid = true;
-                       break;
+               for (i = 0; i < num_indices; i++) {
+                       pin = &gpio_info->asGPIO_Pin[i];
+                       if (id == pin->ucGPIO_ID) {
+                               gpio.id = pin->ucGPIO_ID;
+                               gpio.reg = pin->usGpioPin_AIndex * 4;
+                               gpio.mask = (1 << pin->ucGpioPinBitShift);
+                               gpio.valid = true;
+                               break;
+                       }
                }
        }
 
@@ -264,6 +267,8 @@ static bool radeon_atom_apply_quirks(struct drm_device *dev,
                if ((supported_device == ATOM_DEVICE_CRT1_SUPPORT) ||
                    (supported_device == ATOM_DEVICE_DFP2_SUPPORT))
                        return false;
+               if (supported_device == ATOM_DEVICE_CRT2_SUPPORT)
+                       *line_mux = 0x90;
        }
 
        /* ASUS HD 3600 XT board lists the DVI port as HDMI */
@@ -395,9 +400,7 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
        struct radeon_gpio_rec gpio;
        struct radeon_hpd hpd;
 
-       atom_parse_data_header(ctx, index, &size, &frev, &crev, &data_offset);
-
-       if (data_offset == 0)
+       if (!atom_parse_data_header(ctx, index, &size, &frev, &crev, &data_offset))
                return false;
 
        if (crev < 2)
@@ -449,37 +452,43 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
                                    GetIndexIntoMasterTable(DATA,
                                                            IntegratedSystemInfo);
 
-                               atom_parse_data_header(ctx, index, &size, &frev,
-                                                      &crev, &igp_offset);
-
-                               if (crev >= 2) {
-                                       igp_obj =
-                                           (ATOM_INTEGRATED_SYSTEM_INFO_V2
-                                            *) (ctx->bios + igp_offset);
-
-                                       if (igp_obj) {
-                                               uint32_t slot_config, ct;
-
-                                               if (con_obj_num == 1)
-                                                       slot_config =
-                                                           igp_obj->
-                                                           ulDDISlot1Config;
-                                               else
-                                                       slot_config =
-                                                           igp_obj->
-                                                           ulDDISlot2Config;
-
-                                               ct = (slot_config >> 16) & 0xff;
-                                               connector_type =
-                                                   object_connector_convert
-                                                   [ct];
-                                               connector_object_id = ct;
-                                               igp_lane_info =
-                                                   slot_config & 0xffff;
+                               if (atom_parse_data_header(ctx, index, &size, &frev,
+                                                          &crev, &igp_offset)) {
+
+                                       if (crev >= 2) {
+                                               igp_obj =
+                                                       (ATOM_INTEGRATED_SYSTEM_INFO_V2
+                                                        *) (ctx->bios + igp_offset);
+
+                                               if (igp_obj) {
+                                                       uint32_t slot_config, ct;
+
+                                                       if (con_obj_num == 1)
+                                                               slot_config =
+                                                                       igp_obj->
+                                                                       ulDDISlot1Config;
+                                                       else
+                                                               slot_config =
+                                                                       igp_obj->
+                                                                       ulDDISlot2Config;
+
+                                                       ct = (slot_config >> 16) & 0xff;
+                                                       connector_type =
+                                                               object_connector_convert
+                                                               [ct];
+                                                       connector_object_id = ct;
+                                                       igp_lane_info =
+                                                               slot_config & 0xffff;
+                                               } else
+                                                       continue;
                                        } else
                                                continue;
-                               } else
-                                       continue;
+                               } else {
+                                       igp_lane_info = 0;
+                                       connector_type =
+                                               object_connector_convert[con_obj_id];
+                                       connector_object_id = con_obj_id;
+                               }
                        } else {
                                igp_lane_info = 0;
                                connector_type =
@@ -521,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++) {
@@ -538,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->
@@ -576,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);
 
@@ -627,20 +634,23 @@ static uint16_t atombios_get_connector_object_id(struct drm_device *dev,
                uint8_t frev, crev;
                ATOM_XTMDS_INFO *xtmds;
 
-               atom_parse_data_header(ctx, index, &size, &frev, &crev, &data_offset);
-               xtmds = (ATOM_XTMDS_INFO *)(ctx->bios + data_offset);
+               if (atom_parse_data_header(ctx, index, &size, &frev, &crev, &data_offset)) {
+                       xtmds = (ATOM_XTMDS_INFO *)(ctx->bios + data_offset);
 
-               if (xtmds->ucSupportedLink & ATOM_XTMDS_SUPPORTED_DUALLINK) {
-                       if (connector_type == DRM_MODE_CONNECTOR_DVII)
-                               return CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I;
-                       else
-                               return CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D;
-               } else {
-                       if (connector_type == DRM_MODE_CONNECTOR_DVII)
-                               return CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I;
-                       else
-                               return CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D;
-               }
+                       if (xtmds->ucSupportedLink & ATOM_XTMDS_SUPPORTED_DUALLINK) {
+                               if (connector_type == DRM_MODE_CONNECTOR_DVII)
+                                       return CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I;
+                               else
+                                       return CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D;
+                       } else {
+                               if (connector_type == DRM_MODE_CONNECTOR_DVII)
+                                       return CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I;
+                               else
+                                       return CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D;
+                       }
+               } else
+                       return supported_devices_connector_object_id_convert
+                               [connector_type];
        } else {
                return supported_devices_connector_object_id_convert
                        [connector_type];
@@ -670,9 +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;
 
-       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);
@@ -840,6 +859,7 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct
 
        radeon_link_encoder_connector(dev);
 
+       kfree(bios_connectors);
        return true;
 }
 
@@ -865,14 +885,11 @@ bool radeon_atom_get_clock_info(struct drm_device *dev)
        struct radeon_pll *mpll = &rdev->clock.mpll;
        uint16_t data_offset;
 
-       atom_parse_data_header(mode_info->atom_context, index, NULL, &frev,
-                              &crev, &data_offset);
-
-       firmware_info =
-           (union firmware_info *)(mode_info->atom_context->bios +
-                                   data_offset);
-
-       if (firmware_info) {
+       if (atom_parse_data_header(mode_info->atom_context, index, NULL,
+                                  &frev, &crev, &data_offset)) {
+               firmware_info =
+                       (union firmware_info *)(mode_info->atom_context->bios +
+                                               data_offset);
                /* pixel clocks */
                p1pll->reference_freq =
                    le16_to_cpu(firmware_info->info.usReferenceClock);
@@ -887,6 +904,20 @@ bool radeon_atom_get_clock_info(struct drm_device *dev)
                p1pll->pll_out_max =
                    le32_to_cpu(firmware_info->info.ulMaxPixelClockPLL_Output);
 
+               if (crev >= 4) {
+                       p1pll->lcd_pll_out_min =
+                               le16_to_cpu(firmware_info->info_14.usLcdMinPixelClockPLL_Output) * 100;
+                       if (p1pll->lcd_pll_out_min == 0)
+                               p1pll->lcd_pll_out_min = p1pll->pll_out_min;
+                       p1pll->lcd_pll_out_max =
+                               le16_to_cpu(firmware_info->info_14.usLcdMaxPixelClockPLL_Output) * 100;
+                       if (p1pll->lcd_pll_out_max == 0)
+                               p1pll->lcd_pll_out_max = p1pll->pll_out_max;
+               } else {
+                       p1pll->lcd_pll_out_min = p1pll->pll_out_min;
+                       p1pll->lcd_pll_out_max = p1pll->pll_out_max;
+               }
+
                if (p1pll->pll_out_min == 0) {
                        if (ASIC_IS_AVIVO(rdev))
                                p1pll->pll_out_min = 64800;
@@ -992,13 +1023,10 @@ bool radeon_atombios_sideport_present(struct radeon_device *rdev)
        u8 frev, crev;
        u16 data_offset;
 
-       atom_parse_data_header(mode_info->atom_context, index, NULL, &frev,
-                              &crev, &data_offset);
-
-       igp_info = (union igp_info *)(mode_info->atom_context->bios +
+       if (atom_parse_data_header(mode_info->atom_context, index, NULL,
+                                  &frev, &crev, &data_offset)) {
+               igp_info = (union igp_info *)(mode_info->atom_context->bios +
                                      data_offset);
-
-       if (igp_info) {
                switch (crev) {
                case 1:
                        if (igp_info->info.ucMemoryType & 0xf0)
@@ -1029,14 +1057,12 @@ bool radeon_atombios_get_tmds_info(struct radeon_encoder *encoder,
        uint16_t maxfreq;
        int i;
 
-       atom_parse_data_header(mode_info->atom_context, index, NULL, &frev,
-                              &crev, &data_offset);
-
-       tmds_info =
-           (struct _ATOM_TMDS_INFO *)(mode_info->atom_context->bios +
-                                      data_offset);
+       if (atom_parse_data_header(mode_info->atom_context, index, NULL,
+                                  &frev, &crev, &data_offset)) {
+               tmds_info =
+                       (struct _ATOM_TMDS_INFO *)(mode_info->atom_context->bios +
+                                                  data_offset);
 
-       if (tmds_info) {
                maxfreq = le16_to_cpu(tmds_info->usMaxFrequency);
                for (i = 0; i < 4; i++) {
                        tmds->tmds_pll[i].freq =
@@ -1085,13 +1111,11 @@ static struct radeon_atom_ss *radeon_atombios_get_ss_info(struct
        if (id > ATOM_MAX_SS_ENTRY)
                return NULL;
 
-       atom_parse_data_header(mode_info->atom_context, index, NULL, &frev,
-                              &crev, &data_offset);
+       if (atom_parse_data_header(mode_info->atom_context, index, NULL,
+                                  &frev, &crev, &data_offset)) {
+               ss_info =
+                       (struct _ATOM_SPREAD_SPECTRUM_INFO *)(mode_info->atom_context->bios + data_offset);
 
-       ss_info =
-           (struct _ATOM_SPREAD_SPECTRUM_INFO *)(mode_info->atom_context->bios + data_offset);
-
-       if (ss_info) {
                ss =
                    kzalloc(sizeof(struct radeon_atom_ss), GFP_KERNEL);
 
@@ -1114,30 +1138,6 @@ static struct radeon_atom_ss *radeon_atombios_get_ss_info(struct
        return ss;
 }
 
-static void radeon_atom_apply_lvds_quirks(struct drm_device *dev,
-                                         struct radeon_encoder_atom_dig *lvds)
-{
-
-       /* Toshiba A300-1BU laptop panel doesn't like new pll divider algo */
-       if ((dev->pdev->device == 0x95c4) &&
-           (dev->pdev->subsystem_vendor == 0x1179) &&
-           (dev->pdev->subsystem_device == 0xff50)) {
-               if ((lvds->native_mode.hdisplay == 1280) &&
-                   (lvds->native_mode.vdisplay == 800))
-                       lvds->pll_algo = PLL_ALGO_LEGACY;
-       }
-
-       /* Dell Studio 15 laptop panel doesn't like new pll divider algo */
-       if ((dev->pdev->device == 0x95c4) &&
-           (dev->pdev->subsystem_vendor == 0x1028) &&
-           (dev->pdev->subsystem_device == 0x029f)) {
-               if ((lvds->native_mode.hdisplay == 1280) &&
-                   (lvds->native_mode.vdisplay == 800))
-                       lvds->pll_algo = PLL_ALGO_LEGACY;
-       }
-
-}
-
 union lvds_info {
        struct _ATOM_LVDS_INFO info;
        struct _ATOM_LVDS_INFO_V12 info_12;
@@ -1156,13 +1156,10 @@ struct radeon_encoder_atom_dig *radeon_atombios_get_lvds_info(struct
        uint8_t frev, crev;
        struct radeon_encoder_atom_dig *lvds = NULL;
 
-       atom_parse_data_header(mode_info->atom_context, index, NULL, &frev,
-                              &crev, &data_offset);
-
-       lvds_info =
-           (union lvds_info *)(mode_info->atom_context->bios + data_offset);
-
-       if (lvds_info) {
+       if (atom_parse_data_header(mode_info->atom_context, index, NULL,
+                                  &frev, &crev, &data_offset)) {
+               lvds_info =
+                       (union lvds_info *)(mode_info->atom_context->bios + data_offset);
                lvds =
                    kzalloc(sizeof(struct radeon_encoder_atom_dig), GFP_KERNEL);
 
@@ -1184,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 =
@@ -1220,9 +1217,6 @@ struct radeon_encoder_atom_dig *radeon_atombios_get_lvds_info(struct
                                lvds->pll_algo = PLL_ALGO_LEGACY;
                }
 
-               /* LVDS quirks */
-               radeon_atom_apply_lvds_quirks(dev, lvds);
-
                encoder->native_mode = lvds->native_mode;
        }
        return lvds;
@@ -1241,11 +1235,11 @@ radeon_atombios_get_primary_dac_info(struct radeon_encoder *encoder)
        uint8_t bg, dac;
        struct radeon_encoder_primary_dac *p_dac = NULL;
 
-       atom_parse_data_header(mode_info->atom_context, index, NULL, &frev, &crev, &data_offset);
-
-       dac_info = (struct _COMPASSIONATE_DATA *)(mode_info->atom_context->bios + data_offset);
+       if (atom_parse_data_header(mode_info->atom_context, index, NULL,
+                                  &frev, &crev, &data_offset)) {
+               dac_info = (struct _COMPASSIONATE_DATA *)
+                       (mode_info->atom_context->bios + data_offset);
 
-       if (dac_info) {
                p_dac = kzalloc(sizeof(struct radeon_encoder_primary_dac), GFP_KERNEL);
 
                if (!p_dac)
@@ -1270,12 +1264,14 @@ bool radeon_atom_get_tv_timings(struct radeon_device *rdev, int index,
        u8 frev, crev;
        u16 data_offset, misc;
 
-       atom_parse_data_header(mode_info->atom_context, data_index, NULL, &frev, &crev, &data_offset);
+       if (!atom_parse_data_header(mode_info->atom_context, data_index, NULL,
+                                   &frev, &crev, &data_offset))
+               return false;
 
        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);
@@ -1313,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];
@@ -1362,47 +1358,50 @@ radeon_atombios_get_tv_info(struct radeon_device *rdev)
        struct _ATOM_ANALOG_TV_INFO *tv_info;
        enum radeon_tv_std tv_std = TV_STD_NTSC;
 
-       atom_parse_data_header(mode_info->atom_context, index, NULL, &frev, &crev, &data_offset);
+       if (atom_parse_data_header(mode_info->atom_context, index, NULL,
+                                  &frev, &crev, &data_offset)) {
 
-       tv_info = (struct _ATOM_ANALOG_TV_INFO *)(mode_info->atom_context->bios + data_offset);
+               tv_info = (struct _ATOM_ANALOG_TV_INFO *)
+                       (mode_info->atom_context->bios + data_offset);
 
-       switch (tv_info->ucTV_BootUpDefaultStandard) {
-       case ATOM_TV_NTSC:
-               tv_std = TV_STD_NTSC;
-               DRM_INFO("Default TV standard: NTSC\n");
-               break;
-       case ATOM_TV_NTSCJ:
-               tv_std = TV_STD_NTSC_J;
-               DRM_INFO("Default TV standard: NTSC-J\n");
-               break;
-       case ATOM_TV_PAL:
-               tv_std = TV_STD_PAL;
-               DRM_INFO("Default TV standard: PAL\n");
-               break;
-       case ATOM_TV_PALM:
-               tv_std = TV_STD_PAL_M;
-               DRM_INFO("Default TV standard: PAL-M\n");
-               break;
-       case ATOM_TV_PALN:
-               tv_std = TV_STD_PAL_N;
-               DRM_INFO("Default TV standard: PAL-N\n");
-               break;
-       case ATOM_TV_PALCN:
-               tv_std = TV_STD_PAL_CN;
-               DRM_INFO("Default TV standard: PAL-CN\n");
-               break;
-       case ATOM_TV_PAL60:
-               tv_std = TV_STD_PAL_60;
-               DRM_INFO("Default TV standard: PAL-60\n");
-               break;
-       case ATOM_TV_SECAM:
-               tv_std = TV_STD_SECAM;
-               DRM_INFO("Default TV standard: SECAM\n");
-               break;
-       default:
-               tv_std = TV_STD_NTSC;
-               DRM_INFO("Unknown TV standard; defaulting to NTSC\n");
-               break;
+               switch (tv_info->ucTV_BootUpDefaultStandard) {
+               case ATOM_TV_NTSC:
+                       tv_std = TV_STD_NTSC;
+                       DRM_INFO("Default TV standard: NTSC\n");
+                       break;
+               case ATOM_TV_NTSCJ:
+                       tv_std = TV_STD_NTSC_J;
+                       DRM_INFO("Default TV standard: NTSC-J\n");
+                       break;
+               case ATOM_TV_PAL:
+                       tv_std = TV_STD_PAL;
+                       DRM_INFO("Default TV standard: PAL\n");
+                       break;
+               case ATOM_TV_PALM:
+                       tv_std = TV_STD_PAL_M;
+                       DRM_INFO("Default TV standard: PAL-M\n");
+                       break;
+               case ATOM_TV_PALN:
+                       tv_std = TV_STD_PAL_N;
+                       DRM_INFO("Default TV standard: PAL-N\n");
+                       break;
+               case ATOM_TV_PALCN:
+                       tv_std = TV_STD_PAL_CN;
+                       DRM_INFO("Default TV standard: PAL-CN\n");
+                       break;
+               case ATOM_TV_PAL60:
+                       tv_std = TV_STD_PAL_60;
+                       DRM_INFO("Default TV standard: PAL-60\n");
+                       break;
+               case ATOM_TV_SECAM:
+                       tv_std = TV_STD_SECAM;
+                       DRM_INFO("Default TV standard: SECAM\n");
+                       break;
+               default:
+                       tv_std = TV_STD_NTSC;
+                       DRM_INFO("Unknown TV standard; defaulting to NTSC\n");
+                       break;
+               }
        }
        return tv_std;
 }
@@ -1420,11 +1419,12 @@ radeon_atombios_get_tv_dac_info(struct radeon_encoder *encoder)
        uint8_t bg, dac;
        struct radeon_encoder_tv_dac *tv_dac = NULL;
 
-       atom_parse_data_header(mode_info->atom_context, index, NULL, &frev, &crev, &data_offset);
+       if (atom_parse_data_header(mode_info->atom_context, index, NULL,
+                                  &frev, &crev, &data_offset)) {
 
-       dac_info = (struct _COMPASSIONATE_DATA *)(mode_info->atom_context->bios + data_offset);
+               dac_info = (struct _COMPASSIONATE_DATA *)
+                       (mode_info->atom_context->bios + data_offset);
 
-       if (dac_info) {
                tv_dac = kzalloc(sizeof(struct radeon_encoder_tv_dac), GFP_KERNEL);
 
                if (!tv_dac)
@@ -1447,6 +1447,34 @@ radeon_atombios_get_tv_dac_info(struct radeon_encoder *encoder)
        return tv_dac;
 }
 
+static const char *thermal_controller_names[] = {
+       "NONE",
+       "lm63",
+       "adm1032",
+       "adm1030",
+       "max6649",
+       "lm64",
+       "f75375",
+       "asc7xxx",
+};
+
+static const char *pp_lib_thermal_controller_names[] = {
+       "NONE",
+       "lm63",
+       "adm1032",
+       "adm1030",
+       "max6649",
+       "lm64",
+       "f75375",
+       "RV6xx",
+       "RV770",
+       "adt7473",
+       "External GPIO",
+       "Evergreen",
+       "adt7473 with internal",
+
+};
+
 union power_info {
        struct _ATOM_POWERPLAY_INFO info;
        struct _ATOM_POWERPLAY_INFO_V2 info_2;
@@ -1466,18 +1494,34 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
        struct _ATOM_PPLIB_STATE *power_state;
        int num_modes = 0, i, j;
        int state_index = 0, mode_index = 0;
+       struct radeon_i2c_bus_rec i2c_bus;
 
-       atom_parse_data_header(mode_info->atom_context, index, NULL, &frev, &crev, &data_offset);
+       rdev->pm.default_power_state_index = -1;
 
-       power_info = (union power_info *)(mode_info->atom_context->bios + data_offset);
-
-       rdev->pm.default_power_state = NULL;
-
-       if (power_info) {
+       if (atom_parse_data_header(mode_info->atom_context, index, NULL,
+                                  &frev, &crev, &data_offset)) {
+               power_info = (union power_info *)(mode_info->atom_context->bios + data_offset);
                if (frev < 4) {
+                       /* add the i2c bus for thermal/fan chip */
+                       if (power_info->info.ucOverdriveThermalController > 0) {
+                               DRM_INFO("Possible %s thermal controller at 0x%02x\n",
+                                        thermal_controller_names[power_info->info.ucOverdriveThermalController],
+                                        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) {
@@ -1491,16 +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;
-                                       /* 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) {
+                                       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 =
@@ -1518,6 +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_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 =
@@ -1531,15 +1572,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;
@@ -1553,17 +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;
-                                       /* 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);
-                                       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 =
@@ -1581,6 +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_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 =
@@ -1594,18 +1641,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;
@@ -1619,17 +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;
-                                       /* 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);
-                                       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 =
@@ -1653,6 +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_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 =
@@ -1666,24 +1722,89 @@ 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 {
+                       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 (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",
+                                                (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[controller->ucType],
+                                                controller->ucI2cAddress >> 1,
+                                                (controller->ucFanParameters &
+                                                 ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
+                                       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 *)
@@ -1712,14 +1833,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 =
@@ -1739,12 +1880,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 =
@@ -1756,7 +1891,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) {
@@ -1773,22 +1910,46 @@ 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];
+                                               /* 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 =
+                                       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;
@@ -1798,18 +1959,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)
@@ -1865,6 +2024,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;