drm/radeon/kms: properly program vddci on evergreen+
authorAlex Deucher <alexdeucher@gmail.com>
Tue, 12 Apr 2011 18:49:24 +0000 (14:49 -0400)
committerDave Airlie <airlied@redhat.com>
Tue, 12 Apr 2011 23:09:44 +0000 (09:09 +1000)
Change vddci as well as vddc when changing power modes
on evergreen/ni.  Also, properly set vddci on boot up
for ni cards.  The vbios only sets the limited clocks
and voltages on boot until the mc ucode is loaded.  This
should fix stability problems on some btc cards.

Signed-off-by: Alex Deucher <alexdeucher@gmail.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
drivers/gpu/drm/radeon/evergreen.c
drivers/gpu/drm/radeon/radeon.h
drivers/gpu/drm/radeon/radeon_atombios.c
drivers/gpu/drm/radeon/radeon_pm.c

index f2448170086e9a73a0155240c3b984089a5333d4..3453910ee0f383b48049b8f8c5405f11114f9256 100644 (file)
@@ -120,11 +120,16 @@ void evergreen_pm_misc(struct radeon_device *rdev)
        struct radeon_power_state *ps = &rdev->pm.power_state[req_ps_idx];
        struct radeon_voltage *voltage = &ps->clock_info[req_cm_idx].voltage;
 
-       if ((voltage->type == VOLTAGE_SW) && voltage->voltage) {
-               if (voltage->voltage != rdev->pm.current_vddc) {
+       if (voltage->type == VOLTAGE_SW) {
+               if (voltage->voltage && (voltage->voltage != rdev->pm.current_vddc)) {
                        radeon_atom_set_voltage(rdev, voltage->voltage, SET_VOLTAGE_TYPE_ASIC_VDDC);
                        rdev->pm.current_vddc = voltage->voltage;
-                       DRM_DEBUG("Setting: v: %d\n", voltage->voltage);
+                       DRM_DEBUG("Setting: vddc: %d\n", voltage->voltage);
+               }
+               if (voltage->vddci && (voltage->vddci != rdev->pm.current_vddci)) {
+                       radeon_atom_set_voltage(rdev, voltage->vddci, SET_VOLTAGE_TYPE_ASIC_VDDCI);
+                       rdev->pm.current_vddci = voltage->vddci;
+                       DRM_DEBUG("Setting: vddci: %d\n", voltage->vddci);
                }
        }
 }
index 99557407cdcec3e14614d78fb699f9f8d59173fd..ba643b5760542e0e6ad3298464be1e7505995739 100644 (file)
@@ -767,7 +767,9 @@ struct radeon_voltage {
        u8 vddci_id; /* index into vddci voltage table */
        bool vddci_enabled;
        /* r6xx+ sw */
-       u32 voltage;
+       u16 voltage;
+       /* evergreen+ vddci */
+       u16 vddci;
 };
 
 /* clock mode flags */
@@ -835,10 +837,12 @@ struct radeon_pm {
        int                     default_power_state_index;
        u32                     current_sclk;
        u32                     current_mclk;
-       u32                     current_vddc;
+       u16                     current_vddc;
+       u16                     current_vddci;
        u32                     default_sclk;
        u32                     default_mclk;
-       u32                     default_vddc;
+       u16                     default_vddc;
+       u16                     default_vddci;
        struct radeon_i2c_chan *i2c_bus;
        /* selected pm method */
        enum radeon_pm_method     pm_method;
index 330a5b56602b3af47ed5f9dc9d89a4831926e4d9..f5d12fb103fadd982d6b3ae4d2ad5a227ee1f50b 100644 (file)
@@ -2176,24 +2176,27 @@ static void radeon_atombios_add_pplib_thermal_controller(struct radeon_device *r
        }
 }
 
-static u16 radeon_atombios_get_default_vddc(struct radeon_device *rdev)
+static void radeon_atombios_get_default_voltages(struct radeon_device *rdev,
+                                                u16 *vddc, u16 *vddci)
 {
        struct radeon_mode_info *mode_info = &rdev->mode_info;
        int index = GetIndexIntoMasterTable(DATA, FirmwareInfo);
        u8 frev, crev;
        u16 data_offset;
        union firmware_info *firmware_info;
-       u16 vddc = 0;
+
+       *vddc = 0;
+       *vddci = 0;
 
        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);
-               vddc = le16_to_cpu(firmware_info->info_14.usBootUpVDDCVoltage);
+               *vddc = le16_to_cpu(firmware_info->info_14.usBootUpVDDCVoltage);
+               if ((frev == 2) && (crev >= 2))
+                       *vddci = le16_to_cpu(firmware_info->info_22.usBootUpVDDCIVoltage);
        }
-
-       return vddc;
 }
 
 static void radeon_atombios_parse_pplib_non_clock_info(struct radeon_device *rdev,
@@ -2203,7 +2206,9 @@ static void radeon_atombios_parse_pplib_non_clock_info(struct radeon_device *rde
        int j;
        u32 misc = le32_to_cpu(non_clock_info->ulCapsAndSettings);
        u32 misc2 = le16_to_cpu(non_clock_info->usClassification);
-       u16 vddc = radeon_atombios_get_default_vddc(rdev);
+       u16 vddc, vddci;
+
+       radeon_atombios_get_default_voltages(rdev, &vddc, &vddci);
 
        rdev->pm.power_state[state_index].misc = misc;
        rdev->pm.power_state[state_index].misc2 = misc2;
@@ -2244,6 +2249,7 @@ static void radeon_atombios_parse_pplib_non_clock_info(struct radeon_device *rde
                        rdev->pm.default_sclk = rdev->pm.power_state[state_index].clock_info[0].sclk;
                        rdev->pm.default_mclk = rdev->pm.power_state[state_index].clock_info[0].mclk;
                        rdev->pm.default_vddc = rdev->pm.power_state[state_index].clock_info[0].voltage.voltage;
+                       rdev->pm.default_vddci = rdev->pm.power_state[state_index].clock_info[0].voltage.vddci;
                } else {
                        /* patch the table values with the default slck/mclk from firmware info */
                        for (j = 0; j < mode_index; j++) {
@@ -2286,6 +2292,8 @@ static bool radeon_atombios_parse_pplib_clock_info(struct radeon_device *rdev,
                        VOLTAGE_SW;
                rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage =
                        le16_to_cpu(clock_info->evergreen.usVDDC);
+               rdev->pm.power_state[state_index].clock_info[mode_index].voltage.vddci =
+                       le16_to_cpu(clock_info->evergreen.usVDDCI);
        } else {
                sclk = le16_to_cpu(clock_info->r600.usEngineClockLow);
                sclk |= clock_info->r600.ucEngineClockHigh << 16;
index 4010571def3aff813e37a11b14d31d6a71071be9..86eda1ea94dfc7a250d7add83ad2b25b8ae0dd76 100644 (file)
@@ -538,6 +538,9 @@ void radeon_pm_resume(struct radeon_device *rdev)
                if (rdev->pm.default_vddc)
                        radeon_atom_set_voltage(rdev, rdev->pm.default_vddc,
                                                SET_VOLTAGE_TYPE_ASIC_VDDC);
+               if (rdev->pm.default_vddci)
+                       radeon_atom_set_voltage(rdev, rdev->pm.default_vddci,
+                                               SET_VOLTAGE_TYPE_ASIC_VDDCI);
                if (rdev->pm.default_sclk)
                        radeon_set_engine_clock(rdev, rdev->pm.default_sclk);
                if (rdev->pm.default_mclk)
@@ -550,6 +553,7 @@ void radeon_pm_resume(struct radeon_device *rdev)
        rdev->pm.current_sclk = rdev->pm.default_sclk;
        rdev->pm.current_mclk = rdev->pm.default_mclk;
        rdev->pm.current_vddc = rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.voltage;
+       rdev->pm.current_vddci = rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.vddci;
        if (rdev->pm.pm_method == PM_METHOD_DYNPM
            && rdev->pm.dynpm_state == DYNPM_STATE_SUSPENDED) {
                rdev->pm.dynpm_state = DYNPM_STATE_ACTIVE;