diff options
author | Alex Deucher <alexander.deucher@amd.com> | 2013-06-24 10:50:34 -0400 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2013-06-27 10:49:19 -0400 |
commit | ae5b0abbb6f7478688ac2846b82c9dcc17718daa (patch) | |
tree | 973bbd0ec1ae6f5d7e0f8e22b32eb204aadb6159 /drivers/gpu/drm | |
parent | 2948f5e6c211eccd58b81c15a410d9f3d9cda657 (diff) |
drm/radeon/kms: add atom helper functions for dpm (v3)
dpm needs access to atombios data and command tables
for setup and calculation of a number of parameters.
v2: endian fix
v3: fix mc reg table bug
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r-- | drivers/gpu/drm/radeon/radeon.h | 33 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_atombios.c | 660 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_mode.h | 57 |
3 files changed, 743 insertions, 7 deletions
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index f904ded90e0c..aeec346c8d31 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h | |||
@@ -219,6 +219,39 @@ int radeon_atom_get_clock_dividers(struct radeon_device *rdev, | |||
219 | bool strobe_mode, | 219 | bool strobe_mode, |
220 | struct atom_clock_dividers *dividers); | 220 | struct atom_clock_dividers *dividers); |
221 | void radeon_atom_set_voltage(struct radeon_device *rdev, u16 voltage_level, u8 voltage_type); | 221 | void radeon_atom_set_voltage(struct radeon_device *rdev, u16 voltage_level, u8 voltage_type); |
222 | int radeon_atom_get_voltage_gpio_settings(struct radeon_device *rdev, | ||
223 | u16 voltage_level, u8 voltage_type, | ||
224 | u32 *gpio_value, u32 *gpio_mask); | ||
225 | void radeon_atom_set_engine_dram_timings(struct radeon_device *rdev, | ||
226 | u32 eng_clock, u32 mem_clock); | ||
227 | int radeon_atom_get_voltage_step(struct radeon_device *rdev, | ||
228 | u8 voltage_type, u16 *voltage_step); | ||
229 | int radeon_atom_round_to_true_voltage(struct radeon_device *rdev, | ||
230 | u8 voltage_type, | ||
231 | u16 nominal_voltage, | ||
232 | u16 *true_voltage); | ||
233 | int radeon_atom_get_min_voltage(struct radeon_device *rdev, | ||
234 | u8 voltage_type, u16 *min_voltage); | ||
235 | int radeon_atom_get_max_voltage(struct radeon_device *rdev, | ||
236 | u8 voltage_type, u16 *max_voltage); | ||
237 | int radeon_atom_get_voltage_table(struct radeon_device *rdev, | ||
238 | u8 voltage_type, | ||
239 | struct atom_voltage_table *voltage_table); | ||
240 | bool radeon_atom_is_voltage_gpio(struct radeon_device *rdev, u8 voltage_type); | ||
241 | void radeon_atom_update_memory_dll(struct radeon_device *rdev, | ||
242 | u32 mem_clock); | ||
243 | void radeon_atom_set_ac_timing(struct radeon_device *rdev, | ||
244 | u32 mem_clock); | ||
245 | int radeon_atom_init_mc_reg_table(struct radeon_device *rdev, | ||
246 | u8 module_index, | ||
247 | struct atom_mc_reg_table *reg_table); | ||
248 | int radeon_atom_get_memory_info(struct radeon_device *rdev, | ||
249 | u8 module_index, struct atom_memory_info *mem_info); | ||
250 | int radeon_atom_get_mclk_range_table(struct radeon_device *rdev, | ||
251 | bool gddr5, u8 module_index, | ||
252 | struct atom_memory_clock_range_table *mclk_range_table); | ||
253 | int radeon_atom_get_max_vddc(struct radeon_device *rdev, u8 voltage_type, | ||
254 | u16 voltage_id, u16 *voltage); | ||
222 | void rs690_pm_info(struct radeon_device *rdev); | 255 | void rs690_pm_info(struct radeon_device *rdev); |
223 | extern void evergreen_tiling_fields(unsigned tiling_flags, unsigned *bankw, | 256 | extern void evergreen_tiling_fields(unsigned tiling_flags, unsigned *bankw, |
224 | unsigned *bankh, unsigned *mtaspect, | 257 | unsigned *bankh, unsigned *mtaspect, |
diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index bf3b92442f6c..90401fdc937c 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c | |||
@@ -56,10 +56,6 @@ extern void | |||
56 | radeon_add_legacy_encoder(struct drm_device *dev, uint32_t encoder_enum, | 56 | radeon_add_legacy_encoder(struct drm_device *dev, uint32_t encoder_enum, |
57 | uint32_t supported_device); | 57 | uint32_t supported_device); |
58 | 58 | ||
59 | /* local */ | ||
60 | static int radeon_atom_get_max_vddc(struct radeon_device *rdev, u8 voltage_type, | ||
61 | u16 voltage_id, u16 *voltage); | ||
62 | |||
63 | union atom_supported_devices { | 59 | union atom_supported_devices { |
64 | struct _ATOM_SUPPORTED_DEVICES_INFO info; | 60 | struct _ATOM_SUPPORTED_DEVICES_INFO info; |
65 | struct _ATOM_SUPPORTED_DEVICES_INFO_2 info_2; | 61 | struct _ATOM_SUPPORTED_DEVICES_INFO_2 info_2; |
@@ -1516,6 +1512,10 @@ bool radeon_atombios_get_asic_ss_info(struct radeon_device *rdev, | |||
1516 | le16_to_cpu(ss_info->info_2.asSpreadSpectrum[i].usSpreadSpectrumPercentage); | 1512 | le16_to_cpu(ss_info->info_2.asSpreadSpectrum[i].usSpreadSpectrumPercentage); |
1517 | ss->type = ss_info->info_2.asSpreadSpectrum[i].ucSpreadSpectrumMode; | 1513 | ss->type = ss_info->info_2.asSpreadSpectrum[i].ucSpreadSpectrumMode; |
1518 | ss->rate = le16_to_cpu(ss_info->info_2.asSpreadSpectrum[i].usSpreadRateIn10Hz); | 1514 | ss->rate = le16_to_cpu(ss_info->info_2.asSpreadSpectrum[i].usSpreadRateIn10Hz); |
1515 | if ((crev == 2) && | ||
1516 | ((id == ASIC_INTERNAL_ENGINE_SS) || | ||
1517 | (id == ASIC_INTERNAL_MEMORY_SS))) | ||
1518 | ss->rate /= 100; | ||
1519 | return true; | 1519 | return true; |
1520 | } | 1520 | } |
1521 | } | 1521 | } |
@@ -1530,6 +1530,9 @@ bool radeon_atombios_get_asic_ss_info(struct radeon_device *rdev, | |||
1530 | le16_to_cpu(ss_info->info_3.asSpreadSpectrum[i].usSpreadSpectrumPercentage); | 1530 | le16_to_cpu(ss_info->info_3.asSpreadSpectrum[i].usSpreadSpectrumPercentage); |
1531 | ss->type = ss_info->info_3.asSpreadSpectrum[i].ucSpreadSpectrumMode; | 1531 | ss->type = ss_info->info_3.asSpreadSpectrum[i].ucSpreadSpectrumMode; |
1532 | ss->rate = le16_to_cpu(ss_info->info_3.asSpreadSpectrum[i].usSpreadRateIn10Hz); | 1532 | ss->rate = le16_to_cpu(ss_info->info_3.asSpreadSpectrum[i].usSpreadRateIn10Hz); |
1533 | if ((id == ASIC_INTERNAL_ENGINE_SS) || | ||
1534 | (id == ASIC_INTERNAL_MEMORY_SS)) | ||
1535 | ss->rate /= 100; | ||
1533 | if (rdev->flags & RADEON_IS_IGP) | 1536 | if (rdev->flags & RADEON_IS_IGP) |
1534 | radeon_atombios_get_igp_ss_overrides(rdev, ss, id); | 1537 | radeon_atombios_get_igp_ss_overrides(rdev, ss, id); |
1535 | return true; | 1538 | return true; |
@@ -2340,7 +2343,13 @@ static void radeon_atombios_parse_pplib_non_clock_info(struct radeon_device *rde | |||
2340 | rdev->pm.default_vddc = rdev->pm.power_state[state_index].clock_info[0].voltage.voltage; | 2343 | rdev->pm.default_vddc = rdev->pm.power_state[state_index].clock_info[0].voltage.voltage; |
2341 | rdev->pm.default_vddci = rdev->pm.power_state[state_index].clock_info[0].voltage.vddci; | 2344 | rdev->pm.default_vddci = rdev->pm.power_state[state_index].clock_info[0].voltage.vddci; |
2342 | } else { | 2345 | } else { |
2343 | /* patch the table values with the default slck/mclk from firmware info */ | 2346 | u16 max_vddci = 0; |
2347 | |||
2348 | if (ASIC_IS_DCE4(rdev)) | ||
2349 | radeon_atom_get_max_voltage(rdev, | ||
2350 | SET_VOLTAGE_TYPE_ASIC_VDDCI, | ||
2351 | &max_vddci); | ||
2352 | /* patch the table values with the default sclk/mclk from firmware info */ | ||
2344 | for (j = 0; j < mode_index; j++) { | 2353 | for (j = 0; j < mode_index; j++) { |
2345 | rdev->pm.power_state[state_index].clock_info[j].mclk = | 2354 | rdev->pm.power_state[state_index].clock_info[j].mclk = |
2346 | rdev->clock.default_mclk; | 2355 | rdev->clock.default_mclk; |
@@ -2349,6 +2358,9 @@ static void radeon_atombios_parse_pplib_non_clock_info(struct radeon_device *rde | |||
2349 | if (vddc) | 2358 | if (vddc) |
2350 | rdev->pm.power_state[state_index].clock_info[j].voltage.voltage = | 2359 | rdev->pm.power_state[state_index].clock_info[j].voltage.voltage = |
2351 | vddc; | 2360 | vddc; |
2361 | if (max_vddci) | ||
2362 | rdev->pm.power_state[state_index].clock_info[j].voltage.vddci = | ||
2363 | max_vddci; | ||
2352 | } | 2364 | } |
2353 | } | 2365 | } |
2354 | } | 2366 | } |
@@ -2874,6 +2886,48 @@ void radeon_atom_set_memory_clock(struct radeon_device *rdev, | |||
2874 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | 2886 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); |
2875 | } | 2887 | } |
2876 | 2888 | ||
2889 | void radeon_atom_set_engine_dram_timings(struct radeon_device *rdev, | ||
2890 | u32 eng_clock, u32 mem_clock) | ||
2891 | { | ||
2892 | SET_ENGINE_CLOCK_PS_ALLOCATION args; | ||
2893 | int index = GetIndexIntoMasterTable(COMMAND, DynamicMemorySettings); | ||
2894 | u32 tmp; | ||
2895 | |||
2896 | memset(&args, 0, sizeof(args)); | ||
2897 | |||
2898 | tmp = eng_clock & SET_CLOCK_FREQ_MASK; | ||
2899 | tmp |= (COMPUTE_ENGINE_PLL_PARAM << 24); | ||
2900 | |||
2901 | args.ulTargetEngineClock = cpu_to_le32(tmp); | ||
2902 | if (mem_clock) | ||
2903 | args.sReserved.ulClock = cpu_to_le32(mem_clock & SET_CLOCK_FREQ_MASK); | ||
2904 | |||
2905 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | ||
2906 | } | ||
2907 | |||
2908 | void radeon_atom_update_memory_dll(struct radeon_device *rdev, | ||
2909 | u32 mem_clock) | ||
2910 | { | ||
2911 | u32 args; | ||
2912 | int index = GetIndexIntoMasterTable(COMMAND, DynamicMemorySettings); | ||
2913 | |||
2914 | args = cpu_to_le32(mem_clock); /* 10 khz */ | ||
2915 | |||
2916 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | ||
2917 | } | ||
2918 | |||
2919 | void radeon_atom_set_ac_timing(struct radeon_device *rdev, | ||
2920 | u32 mem_clock) | ||
2921 | { | ||
2922 | SET_MEMORY_CLOCK_PS_ALLOCATION args; | ||
2923 | int index = GetIndexIntoMasterTable(COMMAND, DynamicMemorySettings); | ||
2924 | u32 tmp = mem_clock | (COMPUTE_MEMORY_PLL_PARAM << 24); | ||
2925 | |||
2926 | args.ulTargetMemoryClock = cpu_to_le32(tmp); /* 10 khz */ | ||
2927 | |||
2928 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | ||
2929 | } | ||
2930 | |||
2877 | union set_voltage { | 2931 | union set_voltage { |
2878 | struct _SET_VOLTAGE_PS_ALLOCATION alloc; | 2932 | struct _SET_VOLTAGE_PS_ALLOCATION alloc; |
2879 | struct _SET_VOLTAGE_PARAMETERS v1; | 2933 | struct _SET_VOLTAGE_PARAMETERS v1; |
@@ -2918,8 +2972,8 @@ void radeon_atom_set_voltage(struct radeon_device *rdev, u16 voltage_level, u8 v | |||
2918 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | 2972 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); |
2919 | } | 2973 | } |
2920 | 2974 | ||
2921 | static int radeon_atom_get_max_vddc(struct radeon_device *rdev, u8 voltage_type, | 2975 | int radeon_atom_get_max_vddc(struct radeon_device *rdev, u8 voltage_type, |
2922 | u16 voltage_id, u16 *voltage) | 2976 | u16 voltage_id, u16 *voltage) |
2923 | { | 2977 | { |
2924 | union set_voltage args; | 2978 | union set_voltage args; |
2925 | int index = GetIndexIntoMasterTable(COMMAND, SetVoltage); | 2979 | int index = GetIndexIntoMasterTable(COMMAND, SetVoltage); |
@@ -2957,6 +3011,598 @@ static int radeon_atom_get_max_vddc(struct radeon_device *rdev, u8 voltage_type, | |||
2957 | return 0; | 3011 | return 0; |
2958 | } | 3012 | } |
2959 | 3013 | ||
3014 | int radeon_atom_get_voltage_gpio_settings(struct radeon_device *rdev, | ||
3015 | u16 voltage_level, u8 voltage_type, | ||
3016 | u32 *gpio_value, u32 *gpio_mask) | ||
3017 | { | ||
3018 | union set_voltage args; | ||
3019 | int index = GetIndexIntoMasterTable(COMMAND, SetVoltage); | ||
3020 | u8 frev, crev; | ||
3021 | |||
3022 | if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) | ||
3023 | return -EINVAL; | ||
3024 | |||
3025 | switch (crev) { | ||
3026 | case 1: | ||
3027 | return -EINVAL; | ||
3028 | case 2: | ||
3029 | args.v2.ucVoltageType = voltage_type; | ||
3030 | args.v2.ucVoltageMode = SET_ASIC_VOLTAGE_MODE_GET_GPIOMASK; | ||
3031 | args.v2.usVoltageLevel = cpu_to_le16(voltage_level); | ||
3032 | |||
3033 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | ||
3034 | |||
3035 | *gpio_mask = le32_to_cpu(*(u32 *)&args.v2); | ||
3036 | |||
3037 | args.v2.ucVoltageType = voltage_type; | ||
3038 | args.v2.ucVoltageMode = SET_ASIC_VOLTAGE_MODE_GET_GPIOVAL; | ||
3039 | args.v2.usVoltageLevel = cpu_to_le16(voltage_level); | ||
3040 | |||
3041 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | ||
3042 | |||
3043 | *gpio_value = le32_to_cpu(*(u32 *)&args.v2); | ||
3044 | break; | ||
3045 | default: | ||
3046 | DRM_ERROR("Unknown table version %d, %d\n", frev, crev); | ||
3047 | return -EINVAL; | ||
3048 | } | ||
3049 | |||
3050 | return 0; | ||
3051 | } | ||
3052 | |||
3053 | union voltage_object_info { | ||
3054 | struct _ATOM_VOLTAGE_OBJECT_INFO v1; | ||
3055 | struct _ATOM_VOLTAGE_OBJECT_INFO_V2 v2; | ||
3056 | }; | ||
3057 | |||
3058 | bool | ||
3059 | radeon_atom_is_voltage_gpio(struct radeon_device *rdev, u8 voltage_type) | ||
3060 | { | ||
3061 | int index = GetIndexIntoMasterTable(DATA, VoltageObjectInfo); | ||
3062 | u8 frev, crev; | ||
3063 | u16 data_offset, size; | ||
3064 | int num_indices, i; | ||
3065 | union voltage_object_info *voltage_info; | ||
3066 | |||
3067 | if (atom_parse_data_header(rdev->mode_info.atom_context, index, &size, | ||
3068 | &frev, &crev, &data_offset)) { | ||
3069 | voltage_info = (union voltage_object_info *) | ||
3070 | (rdev->mode_info.atom_context->bios + data_offset); | ||
3071 | |||
3072 | switch (crev) { | ||
3073 | case 1: | ||
3074 | num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) / | ||
3075 | sizeof(ATOM_VOLTAGE_OBJECT); | ||
3076 | |||
3077 | for (i = 0; i < num_indices; i++) { | ||
3078 | if ((voltage_info->v1.asVoltageObj[i].ucVoltageType == voltage_type) && | ||
3079 | (voltage_info->v1.asVoltageObj[i].asControl.ucVoltageControlId == | ||
3080 | VOLTAGE_CONTROLLED_BY_GPIO)) | ||
3081 | return true; | ||
3082 | } | ||
3083 | break; | ||
3084 | case 2: | ||
3085 | num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) / | ||
3086 | sizeof(ATOM_VOLTAGE_OBJECT_INFO_V2); | ||
3087 | |||
3088 | for (i = 0; i < num_indices; i++) { | ||
3089 | if ((voltage_info->v2.asVoltageObj[i].ucVoltageType == voltage_type) && | ||
3090 | (voltage_info->v2.asVoltageObj[i].asControl.ucVoltageControlId == | ||
3091 | VOLTAGE_CONTROLLED_BY_GPIO)) | ||
3092 | return true; | ||
3093 | } | ||
3094 | break; | ||
3095 | default: | ||
3096 | DRM_ERROR("unknown voltage object table\n"); | ||
3097 | return false; | ||
3098 | } | ||
3099 | |||
3100 | } | ||
3101 | return false; | ||
3102 | } | ||
3103 | |||
3104 | int radeon_atom_get_max_voltage(struct radeon_device *rdev, | ||
3105 | u8 voltage_type, u16 *max_voltage) | ||
3106 | { | ||
3107 | int index = GetIndexIntoMasterTable(DATA, VoltageObjectInfo); | ||
3108 | u8 frev, crev; | ||
3109 | u16 data_offset, size; | ||
3110 | int num_indices, i; | ||
3111 | union voltage_object_info *voltage_info; | ||
3112 | |||
3113 | if (atom_parse_data_header(rdev->mode_info.atom_context, index, &size, | ||
3114 | &frev, &crev, &data_offset)) { | ||
3115 | voltage_info = (union voltage_object_info *) | ||
3116 | (rdev->mode_info.atom_context->bios + data_offset); | ||
3117 | |||
3118 | switch (crev) { | ||
3119 | case 1: | ||
3120 | num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) / | ||
3121 | sizeof(ATOM_VOLTAGE_OBJECT); | ||
3122 | |||
3123 | for (i = 0; i < num_indices; i++) { | ||
3124 | if (voltage_info->v1.asVoltageObj[i].ucVoltageType == voltage_type) { | ||
3125 | ATOM_VOLTAGE_FORMULA *formula = | ||
3126 | &voltage_info->v1.asVoltageObj[i].asFormula; | ||
3127 | if (formula->ucFlag & 1) | ||
3128 | *max_voltage = | ||
3129 | le16_to_cpu(formula->usVoltageBaseLevel) + | ||
3130 | formula->ucNumOfVoltageEntries / 2 * | ||
3131 | le16_to_cpu(formula->usVoltageStep); | ||
3132 | else | ||
3133 | *max_voltage = | ||
3134 | le16_to_cpu(formula->usVoltageBaseLevel) + | ||
3135 | (formula->ucNumOfVoltageEntries - 1) * | ||
3136 | le16_to_cpu(formula->usVoltageStep); | ||
3137 | return 0; | ||
3138 | } | ||
3139 | } | ||
3140 | break; | ||
3141 | case 2: | ||
3142 | num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) / | ||
3143 | sizeof(ATOM_VOLTAGE_OBJECT_INFO_V2); | ||
3144 | |||
3145 | for (i = 0; i < num_indices; i++) { | ||
3146 | if (voltage_info->v2.asVoltageObj[i].ucVoltageType == voltage_type) { | ||
3147 | ATOM_VOLTAGE_FORMULA_V2 *formula = | ||
3148 | &voltage_info->v2.asVoltageObj[i].asFormula; | ||
3149 | if (formula->ucNumOfVoltageEntries) { | ||
3150 | *max_voltage = | ||
3151 | le16_to_cpu(formula->asVIDAdjustEntries[ | ||
3152 | formula->ucNumOfVoltageEntries - 1 | ||
3153 | ].usVoltageValue); | ||
3154 | return 0; | ||
3155 | } | ||
3156 | } | ||
3157 | } | ||
3158 | break; | ||
3159 | default: | ||
3160 | DRM_ERROR("unknown voltage object table\n"); | ||
3161 | return -EINVAL; | ||
3162 | } | ||
3163 | |||
3164 | } | ||
3165 | return -EINVAL; | ||
3166 | } | ||
3167 | |||
3168 | int radeon_atom_get_min_voltage(struct radeon_device *rdev, | ||
3169 | u8 voltage_type, u16 *min_voltage) | ||
3170 | { | ||
3171 | int index = GetIndexIntoMasterTable(DATA, VoltageObjectInfo); | ||
3172 | u8 frev, crev; | ||
3173 | u16 data_offset, size; | ||
3174 | int num_indices, i; | ||
3175 | union voltage_object_info *voltage_info; | ||
3176 | |||
3177 | if (atom_parse_data_header(rdev->mode_info.atom_context, index, &size, | ||
3178 | &frev, &crev, &data_offset)) { | ||
3179 | voltage_info = (union voltage_object_info *) | ||
3180 | (rdev->mode_info.atom_context->bios + data_offset); | ||
3181 | |||
3182 | switch (crev) { | ||
3183 | case 1: | ||
3184 | num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) / | ||
3185 | sizeof(ATOM_VOLTAGE_OBJECT); | ||
3186 | |||
3187 | for (i = 0; i < num_indices; i++) { | ||
3188 | if (voltage_info->v1.asVoltageObj[i].ucVoltageType == voltage_type) { | ||
3189 | ATOM_VOLTAGE_FORMULA *formula = | ||
3190 | &voltage_info->v1.asVoltageObj[i].asFormula; | ||
3191 | *min_voltage = | ||
3192 | le16_to_cpu(formula->usVoltageBaseLevel); | ||
3193 | return 0; | ||
3194 | } | ||
3195 | } | ||
3196 | break; | ||
3197 | case 2: | ||
3198 | num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) / | ||
3199 | sizeof(ATOM_VOLTAGE_OBJECT_INFO_V2); | ||
3200 | |||
3201 | for (i = 0; i < num_indices; i++) { | ||
3202 | if (voltage_info->v2.asVoltageObj[i].ucVoltageType == voltage_type) { | ||
3203 | ATOM_VOLTAGE_FORMULA_V2 *formula = | ||
3204 | &voltage_info->v2.asVoltageObj[i].asFormula; | ||
3205 | if (formula->ucNumOfVoltageEntries) { | ||
3206 | *min_voltage = | ||
3207 | le16_to_cpu(formula->asVIDAdjustEntries[ | ||
3208 | 0 | ||
3209 | ].usVoltageValue); | ||
3210 | return 0; | ||
3211 | } | ||
3212 | } | ||
3213 | } | ||
3214 | break; | ||
3215 | default: | ||
3216 | DRM_ERROR("unknown voltage object table\n"); | ||
3217 | return -EINVAL; | ||
3218 | } | ||
3219 | |||
3220 | } | ||
3221 | return -EINVAL; | ||
3222 | } | ||
3223 | |||
3224 | int radeon_atom_get_voltage_step(struct radeon_device *rdev, | ||
3225 | u8 voltage_type, u16 *voltage_step) | ||
3226 | { | ||
3227 | int index = GetIndexIntoMasterTable(DATA, VoltageObjectInfo); | ||
3228 | u8 frev, crev; | ||
3229 | u16 data_offset, size; | ||
3230 | int num_indices, i; | ||
3231 | union voltage_object_info *voltage_info; | ||
3232 | |||
3233 | if (atom_parse_data_header(rdev->mode_info.atom_context, index, &size, | ||
3234 | &frev, &crev, &data_offset)) { | ||
3235 | voltage_info = (union voltage_object_info *) | ||
3236 | (rdev->mode_info.atom_context->bios + data_offset); | ||
3237 | |||
3238 | switch (crev) { | ||
3239 | case 1: | ||
3240 | num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) / | ||
3241 | sizeof(ATOM_VOLTAGE_OBJECT); | ||
3242 | |||
3243 | for (i = 0; i < num_indices; i++) { | ||
3244 | if (voltage_info->v1.asVoltageObj[i].ucVoltageType == voltage_type) { | ||
3245 | ATOM_VOLTAGE_FORMULA *formula = | ||
3246 | &voltage_info->v1.asVoltageObj[i].asFormula; | ||
3247 | if (formula->ucFlag & 1) | ||
3248 | *voltage_step = | ||
3249 | (le16_to_cpu(formula->usVoltageStep) + 1) / 2; | ||
3250 | else | ||
3251 | *voltage_step = | ||
3252 | le16_to_cpu(formula->usVoltageStep); | ||
3253 | return 0; | ||
3254 | } | ||
3255 | } | ||
3256 | break; | ||
3257 | case 2: | ||
3258 | return -EINVAL; | ||
3259 | default: | ||
3260 | DRM_ERROR("unknown voltage object table\n"); | ||
3261 | return -EINVAL; | ||
3262 | } | ||
3263 | |||
3264 | } | ||
3265 | return -EINVAL; | ||
3266 | } | ||
3267 | |||
3268 | int radeon_atom_round_to_true_voltage(struct radeon_device *rdev, | ||
3269 | u8 voltage_type, | ||
3270 | u16 nominal_voltage, | ||
3271 | u16 *true_voltage) | ||
3272 | { | ||
3273 | u16 min_voltage, max_voltage, voltage_step; | ||
3274 | |||
3275 | if (radeon_atom_get_max_voltage(rdev, voltage_type, &max_voltage)) | ||
3276 | return -EINVAL; | ||
3277 | if (radeon_atom_get_min_voltage(rdev, voltage_type, &min_voltage)) | ||
3278 | return -EINVAL; | ||
3279 | if (radeon_atom_get_voltage_step(rdev, voltage_type, &voltage_step)) | ||
3280 | return -EINVAL; | ||
3281 | |||
3282 | if (nominal_voltage <= min_voltage) | ||
3283 | *true_voltage = min_voltage; | ||
3284 | else if (nominal_voltage >= max_voltage) | ||
3285 | *true_voltage = max_voltage; | ||
3286 | else | ||
3287 | *true_voltage = min_voltage + | ||
3288 | ((nominal_voltage - min_voltage) / voltage_step) * | ||
3289 | voltage_step; | ||
3290 | |||
3291 | return 0; | ||
3292 | } | ||
3293 | |||
3294 | int radeon_atom_get_voltage_table(struct radeon_device *rdev, | ||
3295 | u8 voltage_type, | ||
3296 | struct atom_voltage_table *voltage_table) | ||
3297 | { | ||
3298 | int index = GetIndexIntoMasterTable(DATA, VoltageObjectInfo); | ||
3299 | u8 frev, crev; | ||
3300 | u16 data_offset, size; | ||
3301 | int num_indices, i, j, ret; | ||
3302 | union voltage_object_info *voltage_info; | ||
3303 | |||
3304 | if (atom_parse_data_header(rdev->mode_info.atom_context, index, &size, | ||
3305 | &frev, &crev, &data_offset)) { | ||
3306 | voltage_info = (union voltage_object_info *) | ||
3307 | (rdev->mode_info.atom_context->bios + data_offset); | ||
3308 | |||
3309 | switch (crev) { | ||
3310 | case 1: | ||
3311 | DRM_ERROR("old table version %d, %d\n", frev, crev); | ||
3312 | return -EINVAL; | ||
3313 | case 2: | ||
3314 | num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) / | ||
3315 | sizeof(ATOM_VOLTAGE_OBJECT_INFO_V2); | ||
3316 | |||
3317 | for (i = 0; i < num_indices; i++) { | ||
3318 | if (voltage_info->v2.asVoltageObj[i].ucVoltageType == voltage_type) { | ||
3319 | ATOM_VOLTAGE_FORMULA_V2 *formula = | ||
3320 | &voltage_info->v2.asVoltageObj[i].asFormula; | ||
3321 | if (formula->ucNumOfVoltageEntries > MAX_VOLTAGE_ENTRIES) | ||
3322 | return -EINVAL; | ||
3323 | for (j = 0; j < formula->ucNumOfVoltageEntries; j++) { | ||
3324 | voltage_table->entries[j].value = | ||
3325 | le16_to_cpu(formula->asVIDAdjustEntries[j].usVoltageValue); | ||
3326 | ret = radeon_atom_get_voltage_gpio_settings(rdev, | ||
3327 | voltage_table->entries[j].value, | ||
3328 | voltage_type, | ||
3329 | &voltage_table->entries[j].smio_low, | ||
3330 | &voltage_table->mask_low); | ||
3331 | if (ret) | ||
3332 | return ret; | ||
3333 | } | ||
3334 | voltage_table->count = formula->ucNumOfVoltageEntries; | ||
3335 | return 0; | ||
3336 | } | ||
3337 | } | ||
3338 | break; | ||
3339 | default: | ||
3340 | DRM_ERROR("unknown voltage object table\n"); | ||
3341 | return -EINVAL; | ||
3342 | } | ||
3343 | |||
3344 | } | ||
3345 | return -EINVAL; | ||
3346 | } | ||
3347 | |||
3348 | union vram_info { | ||
3349 | struct _ATOM_VRAM_INFO_V3 v1_3; | ||
3350 | struct _ATOM_VRAM_INFO_V4 v1_4; | ||
3351 | struct _ATOM_VRAM_INFO_HEADER_V2_1 v2_1; | ||
3352 | }; | ||
3353 | |||
3354 | int radeon_atom_get_memory_info(struct radeon_device *rdev, | ||
3355 | u8 module_index, struct atom_memory_info *mem_info) | ||
3356 | { | ||
3357 | int index = GetIndexIntoMasterTable(DATA, VRAM_Info); | ||
3358 | u8 frev, crev, i; | ||
3359 | u16 data_offset, size; | ||
3360 | union vram_info *vram_info; | ||
3361 | u8 *p; | ||
3362 | |||
3363 | memset(mem_info, 0, sizeof(struct atom_memory_info)); | ||
3364 | |||
3365 | if (atom_parse_data_header(rdev->mode_info.atom_context, index, &size, | ||
3366 | &frev, &crev, &data_offset)) { | ||
3367 | vram_info = (union vram_info *) | ||
3368 | (rdev->mode_info.atom_context->bios + data_offset); | ||
3369 | switch (frev) { | ||
3370 | case 1: | ||
3371 | switch (crev) { | ||
3372 | case 3: | ||
3373 | /* r6xx */ | ||
3374 | if (module_index < vram_info->v1_3.ucNumOfVRAMModule) { | ||
3375 | ATOM_VRAM_MODULE_V3 *vram_module = | ||
3376 | (ATOM_VRAM_MODULE_V3 *)vram_info->v1_3.aVramInfo; | ||
3377 | p = (u8 *)vram_info->v1_3.aVramInfo; | ||
3378 | |||
3379 | for (i = 0; i < module_index; i++) { | ||
3380 | vram_module = (ATOM_VRAM_MODULE_V3 *)p; | ||
3381 | if (le16_to_cpu(vram_module->usSize) == 0) | ||
3382 | return -EINVAL; | ||
3383 | p += le16_to_cpu(vram_module->usSize); | ||
3384 | } | ||
3385 | mem_info->mem_vendor = vram_module->asMemory.ucMemoryVenderID & 0xf; | ||
3386 | mem_info->mem_type = vram_module->asMemory.ucMemoryType & 0xf0; | ||
3387 | } else | ||
3388 | return -EINVAL; | ||
3389 | break; | ||
3390 | case 4: | ||
3391 | /* r7xx, evergreen */ | ||
3392 | if (module_index < vram_info->v1_4.ucNumOfVRAMModule) { | ||
3393 | ATOM_VRAM_MODULE_V4 *vram_module = | ||
3394 | (ATOM_VRAM_MODULE_V4 *)vram_info->v1_4.aVramInfo; | ||
3395 | p = (u8 *)vram_info->v1_4.aVramInfo; | ||
3396 | |||
3397 | for (i = 0; i < module_index; i++) { | ||
3398 | vram_module = (ATOM_VRAM_MODULE_V4 *)p; | ||
3399 | if (le16_to_cpu(vram_module->usModuleSize) == 0) | ||
3400 | return -EINVAL; | ||
3401 | p += le16_to_cpu(vram_module->usModuleSize); | ||
3402 | } | ||
3403 | mem_info->mem_vendor = vram_module->ucMemoryVenderID & 0xf; | ||
3404 | mem_info->mem_type = vram_module->ucMemoryType & 0xf0; | ||
3405 | } else | ||
3406 | return -EINVAL; | ||
3407 | break; | ||
3408 | default: | ||
3409 | DRM_ERROR("Unknown table version %d, %d\n", frev, crev); | ||
3410 | return -EINVAL; | ||
3411 | } | ||
3412 | break; | ||
3413 | case 2: | ||
3414 | switch (crev) { | ||
3415 | case 1: | ||
3416 | /* ni */ | ||
3417 | if (module_index < vram_info->v2_1.ucNumOfVRAMModule) { | ||
3418 | ATOM_VRAM_MODULE_V7 *vram_module = | ||
3419 | (ATOM_VRAM_MODULE_V7 *)vram_info->v2_1.aVramInfo; | ||
3420 | p = (u8 *)vram_info->v2_1.aVramInfo; | ||
3421 | |||
3422 | for (i = 0; i < module_index; i++) { | ||
3423 | vram_module = (ATOM_VRAM_MODULE_V7 *)p; | ||
3424 | if (le16_to_cpu(vram_module->usModuleSize) == 0) | ||
3425 | return -EINVAL; | ||
3426 | p += le16_to_cpu(vram_module->usModuleSize); | ||
3427 | } | ||
3428 | mem_info->mem_vendor = vram_module->ucMemoryVenderID & 0xf; | ||
3429 | mem_info->mem_type = vram_module->ucMemoryType & 0xf0; | ||
3430 | } else | ||
3431 | return -EINVAL; | ||
3432 | break; | ||
3433 | default: | ||
3434 | DRM_ERROR("Unknown table version %d, %d\n", frev, crev); | ||
3435 | return -EINVAL; | ||
3436 | } | ||
3437 | break; | ||
3438 | default: | ||
3439 | DRM_ERROR("Unknown table version %d, %d\n", frev, crev); | ||
3440 | return -EINVAL; | ||
3441 | } | ||
3442 | return 0; | ||
3443 | } | ||
3444 | return -EINVAL; | ||
3445 | } | ||
3446 | |||
3447 | int radeon_atom_get_mclk_range_table(struct radeon_device *rdev, | ||
3448 | bool gddr5, u8 module_index, | ||
3449 | struct atom_memory_clock_range_table *mclk_range_table) | ||
3450 | { | ||
3451 | int index = GetIndexIntoMasterTable(DATA, VRAM_Info); | ||
3452 | u8 frev, crev, i; | ||
3453 | u16 data_offset, size; | ||
3454 | union vram_info *vram_info; | ||
3455 | u32 mem_timing_size = gddr5 ? | ||
3456 | sizeof(ATOM_MEMORY_TIMING_FORMAT_V2) : sizeof(ATOM_MEMORY_TIMING_FORMAT); | ||
3457 | u8 *p; | ||
3458 | |||
3459 | memset(mclk_range_table, 0, sizeof(struct atom_memory_clock_range_table)); | ||
3460 | |||
3461 | if (atom_parse_data_header(rdev->mode_info.atom_context, index, &size, | ||
3462 | &frev, &crev, &data_offset)) { | ||
3463 | vram_info = (union vram_info *) | ||
3464 | (rdev->mode_info.atom_context->bios + data_offset); | ||
3465 | switch (frev) { | ||
3466 | case 1: | ||
3467 | switch (crev) { | ||
3468 | case 3: | ||
3469 | DRM_ERROR("old table version %d, %d\n", frev, crev); | ||
3470 | return -EINVAL; | ||
3471 | case 4: | ||
3472 | /* r7xx, evergreen */ | ||
3473 | if (module_index < vram_info->v1_4.ucNumOfVRAMModule) { | ||
3474 | ATOM_VRAM_MODULE_V4 *vram_module = | ||
3475 | (ATOM_VRAM_MODULE_V4 *)vram_info->v1_4.aVramInfo; | ||
3476 | ATOM_MEMORY_TIMING_FORMAT *format; | ||
3477 | p = (u8 *)vram_info->v1_4.aVramInfo; | ||
3478 | |||
3479 | for (i = 0; i < module_index; i++) { | ||
3480 | vram_module = (ATOM_VRAM_MODULE_V4 *)p; | ||
3481 | if (le16_to_cpu(vram_module->usModuleSize) == 0) | ||
3482 | return -EINVAL; | ||
3483 | p += le16_to_cpu(vram_module->usModuleSize); | ||
3484 | } | ||
3485 | mclk_range_table->num_entries = (u8) | ||
3486 | ((vram_module->usModuleSize - offsetof(ATOM_VRAM_MODULE_V4, asMemTiming)) / | ||
3487 | mem_timing_size); | ||
3488 | p = (u8 *)vram_module->asMemTiming; | ||
3489 | for (i = 0; i < mclk_range_table->num_entries; i++) { | ||
3490 | format = (ATOM_MEMORY_TIMING_FORMAT *)p; | ||
3491 | mclk_range_table->mclk[i] = format->ulClkRange; | ||
3492 | p += mem_timing_size; | ||
3493 | } | ||
3494 | } else | ||
3495 | return -EINVAL; | ||
3496 | break; | ||
3497 | default: | ||
3498 | DRM_ERROR("Unknown table version %d, %d\n", frev, crev); | ||
3499 | return -EINVAL; | ||
3500 | } | ||
3501 | break; | ||
3502 | case 2: | ||
3503 | DRM_ERROR("new table version %d, %d\n", frev, crev); | ||
3504 | return -EINVAL; | ||
3505 | default: | ||
3506 | DRM_ERROR("Unknown table version %d, %d\n", frev, crev); | ||
3507 | return -EINVAL; | ||
3508 | } | ||
3509 | return 0; | ||
3510 | } | ||
3511 | return -EINVAL; | ||
3512 | } | ||
3513 | |||
3514 | #define MEM_ID_MASK 0xff000000 | ||
3515 | #define MEM_ID_SHIFT 24 | ||
3516 | #define CLOCK_RANGE_MASK 0x00ffffff | ||
3517 | #define CLOCK_RANGE_SHIFT 0 | ||
3518 | #define LOW_NIBBLE_MASK 0xf | ||
3519 | #define DATA_EQU_PREV 0 | ||
3520 | #define DATA_FROM_TABLE 4 | ||
3521 | |||
3522 | int radeon_atom_init_mc_reg_table(struct radeon_device *rdev, | ||
3523 | u8 module_index, | ||
3524 | struct atom_mc_reg_table *reg_table) | ||
3525 | { | ||
3526 | int index = GetIndexIntoMasterTable(DATA, VRAM_Info); | ||
3527 | u8 frev, crev, num_entries, t_mem_id, num_ranges = 0; | ||
3528 | u32 i = 0, j; | ||
3529 | u16 data_offset, size; | ||
3530 | union vram_info *vram_info; | ||
3531 | |||
3532 | memset(reg_table, 0, sizeof(struct atom_mc_reg_table)); | ||
3533 | |||
3534 | if (atom_parse_data_header(rdev->mode_info.atom_context, index, &size, | ||
3535 | &frev, &crev, &data_offset)) { | ||
3536 | vram_info = (union vram_info *) | ||
3537 | (rdev->mode_info.atom_context->bios + data_offset); | ||
3538 | switch (frev) { | ||
3539 | case 1: | ||
3540 | DRM_ERROR("old table version %d, %d\n", frev, crev); | ||
3541 | return -EINVAL; | ||
3542 | case 2: | ||
3543 | switch (crev) { | ||
3544 | case 1: | ||
3545 | if (module_index < vram_info->v2_1.ucNumOfVRAMModule) { | ||
3546 | ATOM_INIT_REG_BLOCK *reg_block = | ||
3547 | (ATOM_INIT_REG_BLOCK *) | ||
3548 | ((u8 *)vram_info + le16_to_cpu(vram_info->v2_1.usMemClkPatchTblOffset)); | ||
3549 | ATOM_MEMORY_SETTING_DATA_BLOCK *reg_data = | ||
3550 | (ATOM_MEMORY_SETTING_DATA_BLOCK *) | ||
3551 | ((u8 *)reg_block + (2 * sizeof(u16)) + | ||
3552 | le16_to_cpu(reg_block->usRegIndexTblSize)); | ||
3553 | num_entries = (u8)((le16_to_cpu(reg_block->usRegIndexTblSize)) / | ||
3554 | sizeof(ATOM_INIT_REG_INDEX_FORMAT)) - 1; | ||
3555 | if (num_entries > VBIOS_MC_REGISTER_ARRAY_SIZE) | ||
3556 | return -EINVAL; | ||
3557 | while (!(reg_block->asRegIndexBuf[i].ucPreRegDataLength & ACCESS_PLACEHOLDER) && | ||
3558 | (i < num_entries)) { | ||
3559 | reg_table->mc_reg_address[i].s1 = | ||
3560 | (u16)(reg_block->asRegIndexBuf[i].usRegIndex); | ||
3561 | reg_table->mc_reg_address[i].pre_reg_data = | ||
3562 | (u8)(reg_block->asRegIndexBuf[i].ucPreRegDataLength); | ||
3563 | i++; | ||
3564 | } | ||
3565 | reg_table->last = i; | ||
3566 | while ((*(u32 *)reg_data != END_OF_REG_DATA_BLOCK) && | ||
3567 | (num_ranges < VBIOS_MAX_AC_TIMING_ENTRIES)) { | ||
3568 | t_mem_id = (u8)((*(u32 *)reg_data & MEM_ID_MASK) >> MEM_ID_SHIFT); | ||
3569 | if (module_index == t_mem_id) { | ||
3570 | reg_table->mc_reg_table_entry[num_ranges].mclk_max = | ||
3571 | (u32)((*(u32 *)reg_data & CLOCK_RANGE_MASK) >> CLOCK_RANGE_SHIFT); | ||
3572 | for (i = 0, j = 1; i < reg_table->last; i++) { | ||
3573 | if ((reg_table->mc_reg_address[i].pre_reg_data & LOW_NIBBLE_MASK) == DATA_FROM_TABLE) { | ||
3574 | reg_table->mc_reg_table_entry[num_ranges].mc_data[i] = | ||
3575 | (u32)*((u32 *)reg_data + j); | ||
3576 | j++; | ||
3577 | } else if ((reg_table->mc_reg_address[i].pre_reg_data & LOW_NIBBLE_MASK) == DATA_EQU_PREV) { | ||
3578 | reg_table->mc_reg_table_entry[num_ranges].mc_data[i] = | ||
3579 | reg_table->mc_reg_table_entry[num_ranges].mc_data[i - 1]; | ||
3580 | } | ||
3581 | } | ||
3582 | num_ranges++; | ||
3583 | } | ||
3584 | reg_data += reg_block->usRegDataBlkSize; | ||
3585 | } | ||
3586 | if (*(u32 *)reg_data != END_OF_REG_DATA_BLOCK) | ||
3587 | return -EINVAL; | ||
3588 | reg_table->num_entries = num_ranges; | ||
3589 | } else | ||
3590 | return -EINVAL; | ||
3591 | break; | ||
3592 | default: | ||
3593 | DRM_ERROR("Unknown table version %d, %d\n", frev, crev); | ||
3594 | return -EINVAL; | ||
3595 | } | ||
3596 | break; | ||
3597 | default: | ||
3598 | DRM_ERROR("Unknown table version %d, %d\n", frev, crev); | ||
3599 | return -EINVAL; | ||
3600 | } | ||
3601 | return 0; | ||
3602 | } | ||
3603 | return -EINVAL; | ||
3604 | } | ||
3605 | |||
2960 | void radeon_atom_initialize_bios_scratch_regs(struct drm_device *dev) | 3606 | void radeon_atom_initialize_bios_scratch_regs(struct drm_device *dev) |
2961 | { | 3607 | { |
2962 | struct radeon_device *rdev = dev->dev_private; | 3608 | struct radeon_device *rdev = dev->dev_private; |
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 576511f46c9d..5a1c69ec6a41 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h | |||
@@ -519,6 +519,63 @@ struct atom_clock_dividers { | |||
519 | u32 flags; | 519 | u32 flags; |
520 | }; | 520 | }; |
521 | 521 | ||
522 | #define MEM_TYPE_GDDR5 0x50 | ||
523 | #define MEM_TYPE_GDDR4 0x40 | ||
524 | #define MEM_TYPE_GDDR3 0x30 | ||
525 | #define MEM_TYPE_DDR2 0x20 | ||
526 | #define MEM_TYPE_GDDR1 0x10 | ||
527 | #define MEM_TYPE_DDR3 0xb0 | ||
528 | #define MEM_TYPE_MASK 0xf0 | ||
529 | |||
530 | struct atom_memory_info { | ||
531 | u8 mem_vendor; | ||
532 | u8 mem_type; | ||
533 | }; | ||
534 | |||
535 | #define MAX_AC_TIMING_ENTRIES 16 | ||
536 | |||
537 | struct atom_memory_clock_range_table | ||
538 | { | ||
539 | u8 num_entries; | ||
540 | u8 rsv[3]; | ||
541 | u32 mclk[MAX_AC_TIMING_ENTRIES]; | ||
542 | }; | ||
543 | |||
544 | #define VBIOS_MC_REGISTER_ARRAY_SIZE 32 | ||
545 | #define VBIOS_MAX_AC_TIMING_ENTRIES 20 | ||
546 | |||
547 | struct atom_mc_reg_entry { | ||
548 | u32 mclk_max; | ||
549 | u32 mc_data[VBIOS_MC_REGISTER_ARRAY_SIZE]; | ||
550 | }; | ||
551 | |||
552 | struct atom_mc_register_address { | ||
553 | u16 s1; | ||
554 | u8 pre_reg_data; | ||
555 | }; | ||
556 | |||
557 | struct atom_mc_reg_table { | ||
558 | u8 last; | ||
559 | u8 num_entries; | ||
560 | struct atom_mc_reg_entry mc_reg_table_entry[VBIOS_MAX_AC_TIMING_ENTRIES]; | ||
561 | struct atom_mc_register_address mc_reg_address[VBIOS_MC_REGISTER_ARRAY_SIZE]; | ||
562 | }; | ||
563 | |||
564 | #define MAX_VOLTAGE_ENTRIES 32 | ||
565 | |||
566 | struct atom_voltage_table_entry | ||
567 | { | ||
568 | u16 value; | ||
569 | u32 smio_low; | ||
570 | }; | ||
571 | |||
572 | struct atom_voltage_table | ||
573 | { | ||
574 | u32 count; | ||
575 | u32 mask_low; | ||
576 | struct atom_voltage_table_entry entries[MAX_VOLTAGE_ENTRIES]; | ||
577 | }; | ||
578 | |||
522 | extern enum radeon_tv_std | 579 | extern enum radeon_tv_std |
523 | radeon_combios_get_tv_info(struct radeon_device *rdev); | 580 | radeon_combios_get_tv_info(struct radeon_device *rdev); |
524 | extern enum radeon_tv_std | 581 | extern enum radeon_tv_std |