aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
authorAlex Deucher <alexander.deucher@amd.com>2013-06-24 10:50:34 -0400
committerAlex Deucher <alexander.deucher@amd.com>2013-06-27 10:49:19 -0400
commitae5b0abbb6f7478688ac2846b82c9dcc17718daa (patch)
tree973bbd0ec1ae6f5d7e0f8e22b32eb204aadb6159 /drivers/gpu/drm
parent2948f5e6c211eccd58b81c15a410d9f3d9cda657 (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.h33
-rw-r--r--drivers/gpu/drm/radeon/radeon_atombios.c660
-rw-r--r--drivers/gpu/drm/radeon/radeon_mode.h57
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);
221void radeon_atom_set_voltage(struct radeon_device *rdev, u16 voltage_level, u8 voltage_type); 221void radeon_atom_set_voltage(struct radeon_device *rdev, u16 voltage_level, u8 voltage_type);
222int radeon_atom_get_voltage_gpio_settings(struct radeon_device *rdev,
223 u16 voltage_level, u8 voltage_type,
224 u32 *gpio_value, u32 *gpio_mask);
225void radeon_atom_set_engine_dram_timings(struct radeon_device *rdev,
226 u32 eng_clock, u32 mem_clock);
227int radeon_atom_get_voltage_step(struct radeon_device *rdev,
228 u8 voltage_type, u16 *voltage_step);
229int radeon_atom_round_to_true_voltage(struct radeon_device *rdev,
230 u8 voltage_type,
231 u16 nominal_voltage,
232 u16 *true_voltage);
233int radeon_atom_get_min_voltage(struct radeon_device *rdev,
234 u8 voltage_type, u16 *min_voltage);
235int radeon_atom_get_max_voltage(struct radeon_device *rdev,
236 u8 voltage_type, u16 *max_voltage);
237int radeon_atom_get_voltage_table(struct radeon_device *rdev,
238 u8 voltage_type,
239 struct atom_voltage_table *voltage_table);
240bool radeon_atom_is_voltage_gpio(struct radeon_device *rdev, u8 voltage_type);
241void radeon_atom_update_memory_dll(struct radeon_device *rdev,
242 u32 mem_clock);
243void radeon_atom_set_ac_timing(struct radeon_device *rdev,
244 u32 mem_clock);
245int radeon_atom_init_mc_reg_table(struct radeon_device *rdev,
246 u8 module_index,
247 struct atom_mc_reg_table *reg_table);
248int radeon_atom_get_memory_info(struct radeon_device *rdev,
249 u8 module_index, struct atom_memory_info *mem_info);
250int 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);
253int radeon_atom_get_max_vddc(struct radeon_device *rdev, u8 voltage_type,
254 u16 voltage_id, u16 *voltage);
222void rs690_pm_info(struct radeon_device *rdev); 255void rs690_pm_info(struct radeon_device *rdev);
223extern void evergreen_tiling_fields(unsigned tiling_flags, unsigned *bankw, 256extern 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
56radeon_add_legacy_encoder(struct drm_device *dev, uint32_t encoder_enum, 56radeon_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 */
60static int radeon_atom_get_max_vddc(struct radeon_device *rdev, u8 voltage_type,
61 u16 voltage_id, u16 *voltage);
62
63union atom_supported_devices { 59union 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
2889void 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
2908void 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
2919void 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
2877union set_voltage { 2931union 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
2921static int radeon_atom_get_max_vddc(struct radeon_device *rdev, u8 voltage_type, 2975int 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
3014int 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
3053union voltage_object_info {
3054 struct _ATOM_VOLTAGE_OBJECT_INFO v1;
3055 struct _ATOM_VOLTAGE_OBJECT_INFO_V2 v2;
3056};
3057
3058bool
3059radeon_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
3104int 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
3168int 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
3224int 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
3268int 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
3294int 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
3348union 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
3354int 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
3447int 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
3522int 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
2960void radeon_atom_initialize_bios_scratch_regs(struct drm_device *dev) 3606void 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
530struct atom_memory_info {
531 u8 mem_vendor;
532 u8 mem_type;
533};
534
535#define MAX_AC_TIMING_ENTRIES 16
536
537struct 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
547struct atom_mc_reg_entry {
548 u32 mclk_max;
549 u32 mc_data[VBIOS_MC_REGISTER_ARRAY_SIZE];
550};
551
552struct atom_mc_register_address {
553 u16 s1;
554 u8 pre_reg_data;
555};
556
557struct 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
566struct atom_voltage_table_entry
567{
568 u16 value;
569 u32 smio_low;
570};
571
572struct atom_voltage_table
573{
574 u32 count;
575 u32 mask_low;
576 struct atom_voltage_table_entry entries[MAX_VOLTAGE_ENTRIES];
577};
578
522extern enum radeon_tv_std 579extern enum radeon_tv_std
523radeon_combios_get_tv_info(struct radeon_device *rdev); 580radeon_combios_get_tv_info(struct radeon_device *rdev);
524extern enum radeon_tv_std 581extern enum radeon_tv_std