drm/radeon/dpm: fetch vce states from the vbios
authorAlex Deucher <alexander.deucher@amd.com>
Wed, 4 Sep 2013 20:13:56 +0000 (16:13 -0400)
committerChristian König <christian.koenig@amd.com>
Tue, 18 Feb 2014 15:11:33 +0000 (16:11 +0100)
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/radeon/r600_dpm.c
drivers/gpu/drm/radeon/radeon.h

index e8b6e4a..cbf7e32 100644 (file)
@@ -1063,7 +1063,15 @@ int r600_parse_extended_power_table(struct radeon_device *rdev)
                                (mode_info->atom_context->bios + data_offset +
                                 le16_to_cpu(ext_hdr->usVCETableOffset) + 1 +
                                 1 + array->ucNumEntries * sizeof(VCEClockInfo));
+                       ATOM_PPLIB_VCE_State_Table *states =
+                               (ATOM_PPLIB_VCE_State_Table *)
+                               (mode_info->atom_context->bios + data_offset +
+                                le16_to_cpu(ext_hdr->usVCETableOffset) + 1 +
+                                1 + (array->ucNumEntries * sizeof (VCEClockInfo)) +
+                                1 + (limits->numEntries * sizeof(ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record)));
                        ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record *entry;
+                       ATOM_PPLIB_VCE_State_Record *state_entry;
+                       VCEClockInfo *vce_clk;
                        u32 size = limits->numEntries *
                                sizeof(struct radeon_vce_clock_voltage_dependency_entry);
                        rdev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries =
@@ -1075,8 +1083,9 @@ int r600_parse_extended_power_table(struct radeon_device *rdev)
                        rdev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.count =
                                limits->numEntries;
                        entry = &limits->entries[0];
+                       state_entry = &states->entries[0];
                        for (i = 0; i < limits->numEntries; i++) {
-                               VCEClockInfo *vce_clk = (VCEClockInfo *)
+                               vce_clk = (VCEClockInfo *)
                                        ((u8 *)&array->entries[0] +
                                         (entry->ucVCEClockInfoIndex * sizeof(VCEClockInfo)));
                                rdev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries[i].evclk =
@@ -1088,6 +1097,23 @@ int r600_parse_extended_power_table(struct radeon_device *rdev)
                                entry = (ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record *)
                                        ((u8 *)entry + sizeof(ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record));
                        }
+                       for (i = 0; i < states->numEntries; i++) {
+                               if (i >= RADEON_MAX_VCE_LEVELS)
+                                       break;
+                               vce_clk = (VCEClockInfo *)
+                                       ((u8 *)&array->entries[0] +
+                                        (state_entry->ucVCEClockInfoIndex * sizeof(VCEClockInfo)));
+                               rdev->pm.dpm.vce_states[i].evclk =
+                                       le16_to_cpu(vce_clk->usEVClkLow) | (vce_clk->ucEVClkHigh << 16);
+                               rdev->pm.dpm.vce_states[i].ecclk =
+                                       le16_to_cpu(vce_clk->usECClkLow) | (vce_clk->ucECClkHigh << 16);
+                               rdev->pm.dpm.vce_states[i].clk_idx =
+                                       state_entry->ucClockInfoIndex & 0x3f;
+                               rdev->pm.dpm.vce_states[i].pstate =
+                                       (state_entry->ucClockInfoIndex & 0xc0) >> 6;
+                               state_entry = (ATOM_PPLIB_VCE_State_Record *)
+                                       ((u8 *)state_entry + sizeof(ATOM_PPLIB_VCE_State_Record));
+                       }
                }
                if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3) &&
                        ext_hdr->usUVDTableOffset) {
index 60c171c..693a8fc 100644 (file)
@@ -1259,6 +1259,8 @@ enum radeon_dpm_event_src {
        RADEON_DPM_EVENT_SRC_DIGIAL_OR_EXTERNAL = 4
 };
 
+#define RADEON_MAX_VCE_LEVELS 6
+
 enum radeon_vce_level {
        RADEON_VCE_LEVEL_AC_ALL = 0,     /* AC, All cases */
        RADEON_VCE_LEVEL_DC_EE = 1,      /* DC, entropy encoding */
@@ -1454,6 +1456,17 @@ enum radeon_dpm_forced_level {
        RADEON_DPM_FORCED_LEVEL_HIGH = 2,
 };
 
+struct radeon_vce_state {
+       /* vce clocks */
+       u32 evclk;
+       u32 ecclk;
+       /* gpu clocks */
+       u32 sclk;
+       u32 mclk;
+       u8 clk_idx;
+       u8 pstate;
+};
+
 struct radeon_dpm {
        struct radeon_ps        *ps;
        /* number of valid power states */
@@ -1466,6 +1479,9 @@ struct radeon_dpm {
        struct radeon_ps        *boot_ps;
        /* default uvd power state */
        struct radeon_ps        *uvd_ps;
+       /* vce requirements */
+       struct radeon_vce_state vce_states[RADEON_MAX_VCE_LEVELS];
+       enum radeon_vce_level vce_level;
        enum radeon_pm_state_type state;
        enum radeon_pm_state_type user_state;
        u32                     platform_caps;