linux/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c
<<
>>
Prefs
   1/*
   2 * Copyright 2011 Advanced Micro Devices, Inc.
   3 *
   4 * Permission is hereby granted, free of charge, to any person obtaining a
   5 * copy of this software and associated documentation files (the "Software"),
   6 * to deal in the Software without restriction, including without limitation
   7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
   8 * and/or sell copies of the Software, and to permit persons to whom the
   9 * Software is furnished to do so, subject to the following conditions:
  10 *
  11 * The above copyright notice and this permission notice shall be included in
  12 * all copies or substantial portions of the Software.
  13 *
  14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
  18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  20 * OTHER DEALINGS IN THE SOFTWARE.
  21 *
  22 * Authors: Alex Deucher
  23 */
  24
  25#include <drm/drmP.h>
  26#include "amdgpu.h"
  27#include "amdgpu_atombios.h"
  28#include "amdgpu_i2c.h"
  29#include "amdgpu_dpm.h"
  30#include "atom.h"
  31#include "amd_pcie.h"
  32
  33void amdgpu_dpm_print_class_info(u32 class, u32 class2)
  34{
  35        const char *s;
  36
  37        switch (class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) {
  38        case ATOM_PPLIB_CLASSIFICATION_UI_NONE:
  39        default:
  40                s = "none";
  41                break;
  42        case ATOM_PPLIB_CLASSIFICATION_UI_BATTERY:
  43                s = "battery";
  44                break;
  45        case ATOM_PPLIB_CLASSIFICATION_UI_BALANCED:
  46                s = "balanced";
  47                break;
  48        case ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE:
  49                s = "performance";
  50                break;
  51        }
  52        printk("\tui class: %s\n", s);
  53        printk("\tinternal class:");
  54        if (((class & ~ATOM_PPLIB_CLASSIFICATION_UI_MASK) == 0) &&
  55            (class2 == 0))
  56                pr_cont(" none");
  57        else {
  58                if (class & ATOM_PPLIB_CLASSIFICATION_BOOT)
  59                        pr_cont(" boot");
  60                if (class & ATOM_PPLIB_CLASSIFICATION_THERMAL)
  61                        pr_cont(" thermal");
  62                if (class & ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE)
  63                        pr_cont(" limited_pwr");
  64                if (class & ATOM_PPLIB_CLASSIFICATION_REST)
  65                        pr_cont(" rest");
  66                if (class & ATOM_PPLIB_CLASSIFICATION_FORCED)
  67                        pr_cont(" forced");
  68                if (class & ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE)
  69                        pr_cont(" 3d_perf");
  70                if (class & ATOM_PPLIB_CLASSIFICATION_OVERDRIVETEMPLATE)
  71                        pr_cont(" ovrdrv");
  72                if (class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE)
  73                        pr_cont(" uvd");
  74                if (class & ATOM_PPLIB_CLASSIFICATION_3DLOW)
  75                        pr_cont(" 3d_low");
  76                if (class & ATOM_PPLIB_CLASSIFICATION_ACPI)
  77                        pr_cont(" acpi");
  78                if (class & ATOM_PPLIB_CLASSIFICATION_HD2STATE)
  79                        pr_cont(" uvd_hd2");
  80                if (class & ATOM_PPLIB_CLASSIFICATION_HDSTATE)
  81                        pr_cont(" uvd_hd");
  82                if (class & ATOM_PPLIB_CLASSIFICATION_SDSTATE)
  83                        pr_cont(" uvd_sd");
  84                if (class2 & ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2)
  85                        pr_cont(" limited_pwr2");
  86                if (class2 & ATOM_PPLIB_CLASSIFICATION2_ULV)
  87                        pr_cont(" ulv");
  88                if (class2 & ATOM_PPLIB_CLASSIFICATION2_MVC)
  89                        pr_cont(" uvd_mvc");
  90        }
  91        pr_cont("\n");
  92}
  93
  94void amdgpu_dpm_print_cap_info(u32 caps)
  95{
  96        printk("\tcaps:");
  97        if (caps & ATOM_PPLIB_SINGLE_DISPLAY_ONLY)
  98                pr_cont(" single_disp");
  99        if (caps & ATOM_PPLIB_SUPPORTS_VIDEO_PLAYBACK)
 100                pr_cont(" video");
 101        if (caps & ATOM_PPLIB_DISALLOW_ON_DC)
 102                pr_cont(" no_dc");
 103        pr_cont("\n");
 104}
 105
 106void amdgpu_dpm_print_ps_status(struct amdgpu_device *adev,
 107                                struct amdgpu_ps *rps)
 108{
 109        printk("\tstatus:");
 110        if (rps == adev->pm.dpm.current_ps)
 111                pr_cont(" c");
 112        if (rps == adev->pm.dpm.requested_ps)
 113                pr_cont(" r");
 114        if (rps == adev->pm.dpm.boot_ps)
 115                pr_cont(" b");
 116        pr_cont("\n");
 117}
 118
 119void amdgpu_dpm_get_active_displays(struct amdgpu_device *adev)
 120{
 121        struct drm_device *ddev = adev->ddev;
 122        struct drm_crtc *crtc;
 123        struct amdgpu_crtc *amdgpu_crtc;
 124
 125        adev->pm.dpm.new_active_crtcs = 0;
 126        adev->pm.dpm.new_active_crtc_count = 0;
 127        if (adev->mode_info.num_crtc && adev->mode_info.mode_config_initialized) {
 128                list_for_each_entry(crtc,
 129                                    &ddev->mode_config.crtc_list, head) {
 130                        amdgpu_crtc = to_amdgpu_crtc(crtc);
 131                        if (amdgpu_crtc->enabled) {
 132                                adev->pm.dpm.new_active_crtcs |= (1 << amdgpu_crtc->crtc_id);
 133                                adev->pm.dpm.new_active_crtc_count++;
 134                        }
 135                }
 136        }
 137}
 138
 139
 140u32 amdgpu_dpm_get_vblank_time(struct amdgpu_device *adev)
 141{
 142        struct drm_device *dev = adev->ddev;
 143        struct drm_crtc *crtc;
 144        struct amdgpu_crtc *amdgpu_crtc;
 145        u32 vblank_in_pixels;
 146        u32 vblank_time_us = 0xffffffff; /* if the displays are off, vblank time is max */
 147
 148        if (adev->mode_info.num_crtc && adev->mode_info.mode_config_initialized) {
 149                list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
 150                        amdgpu_crtc = to_amdgpu_crtc(crtc);
 151                        if (crtc->enabled && amdgpu_crtc->enabled && amdgpu_crtc->hw_mode.clock) {
 152                                vblank_in_pixels =
 153                                        amdgpu_crtc->hw_mode.crtc_htotal *
 154                                        (amdgpu_crtc->hw_mode.crtc_vblank_end -
 155                                        amdgpu_crtc->hw_mode.crtc_vdisplay +
 156                                        (amdgpu_crtc->v_border * 2));
 157
 158                                vblank_time_us = vblank_in_pixels * 1000 / amdgpu_crtc->hw_mode.clock;
 159                                break;
 160                        }
 161                }
 162        }
 163
 164        return vblank_time_us;
 165}
 166
 167u32 amdgpu_dpm_get_vrefresh(struct amdgpu_device *adev)
 168{
 169        struct drm_device *dev = adev->ddev;
 170        struct drm_crtc *crtc;
 171        struct amdgpu_crtc *amdgpu_crtc;
 172        u32 vrefresh = 0;
 173
 174        if (adev->mode_info.num_crtc && adev->mode_info.mode_config_initialized) {
 175                list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
 176                        amdgpu_crtc = to_amdgpu_crtc(crtc);
 177                        if (crtc->enabled && amdgpu_crtc->enabled && amdgpu_crtc->hw_mode.clock) {
 178                                vrefresh = drm_mode_vrefresh(&amdgpu_crtc->hw_mode);
 179                                break;
 180                        }
 181                }
 182        }
 183
 184        return vrefresh;
 185}
 186
 187void amdgpu_calculate_u_and_p(u32 i, u32 r_c, u32 p_b,
 188                              u32 *p, u32 *u)
 189{
 190        u32 b_c = 0;
 191        u32 i_c;
 192        u32 tmp;
 193
 194        i_c = (i * r_c) / 100;
 195        tmp = i_c >> p_b;
 196
 197        while (tmp) {
 198                b_c++;
 199                tmp >>= 1;
 200        }
 201
 202        *u = (b_c + 1) / 2;
 203        *p = i_c / (1 << (2 * (*u)));
 204}
 205
 206int amdgpu_calculate_at(u32 t, u32 h, u32 fh, u32 fl, u32 *tl, u32 *th)
 207{
 208        u32 k, a, ah, al;
 209        u32 t1;
 210
 211        if ((fl == 0) || (fh == 0) || (fl > fh))
 212                return -EINVAL;
 213
 214        k = (100 * fh) / fl;
 215        t1 = (t * (k - 100));
 216        a = (1000 * (100 * h + t1)) / (10000 + (t1 / 100));
 217        a = (a + 5) / 10;
 218        ah = ((a * t) + 5000) / 10000;
 219        al = a - ah;
 220
 221        *th = t - ah;
 222        *tl = t + al;
 223
 224        return 0;
 225}
 226
 227bool amdgpu_is_uvd_state(u32 class, u32 class2)
 228{
 229        if (class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE)
 230                return true;
 231        if (class & ATOM_PPLIB_CLASSIFICATION_HD2STATE)
 232                return true;
 233        if (class & ATOM_PPLIB_CLASSIFICATION_HDSTATE)
 234                return true;
 235        if (class & ATOM_PPLIB_CLASSIFICATION_SDSTATE)
 236                return true;
 237        if (class2 & ATOM_PPLIB_CLASSIFICATION2_MVC)
 238                return true;
 239        return false;
 240}
 241
 242bool amdgpu_is_internal_thermal_sensor(enum amdgpu_int_thermal_type sensor)
 243{
 244        switch (sensor) {
 245        case THERMAL_TYPE_RV6XX:
 246        case THERMAL_TYPE_RV770:
 247        case THERMAL_TYPE_EVERGREEN:
 248        case THERMAL_TYPE_SUMO:
 249        case THERMAL_TYPE_NI:
 250        case THERMAL_TYPE_SI:
 251        case THERMAL_TYPE_CI:
 252        case THERMAL_TYPE_KV:
 253                return true;
 254        case THERMAL_TYPE_ADT7473_WITH_INTERNAL:
 255        case THERMAL_TYPE_EMC2103_WITH_INTERNAL:
 256                return false; /* need special handling */
 257        case THERMAL_TYPE_NONE:
 258        case THERMAL_TYPE_EXTERNAL:
 259        case THERMAL_TYPE_EXTERNAL_GPIO:
 260        default:
 261                return false;
 262        }
 263}
 264
 265union power_info {
 266        struct _ATOM_POWERPLAY_INFO info;
 267        struct _ATOM_POWERPLAY_INFO_V2 info_2;
 268        struct _ATOM_POWERPLAY_INFO_V3 info_3;
 269        struct _ATOM_PPLIB_POWERPLAYTABLE pplib;
 270        struct _ATOM_PPLIB_POWERPLAYTABLE2 pplib2;
 271        struct _ATOM_PPLIB_POWERPLAYTABLE3 pplib3;
 272        struct _ATOM_PPLIB_POWERPLAYTABLE4 pplib4;
 273        struct _ATOM_PPLIB_POWERPLAYTABLE5 pplib5;
 274};
 275
 276union fan_info {
 277        struct _ATOM_PPLIB_FANTABLE fan;
 278        struct _ATOM_PPLIB_FANTABLE2 fan2;
 279        struct _ATOM_PPLIB_FANTABLE3 fan3;
 280};
 281
 282static int amdgpu_parse_clk_voltage_dep_table(struct amdgpu_clock_voltage_dependency_table *amdgpu_table,
 283                                              ATOM_PPLIB_Clock_Voltage_Dependency_Table *atom_table)
 284{
 285        u32 size = atom_table->ucNumEntries *
 286                sizeof(struct amdgpu_clock_voltage_dependency_entry);
 287        int i;
 288        ATOM_PPLIB_Clock_Voltage_Dependency_Record *entry;
 289
 290        amdgpu_table->entries = kzalloc(size, GFP_KERNEL);
 291        if (!amdgpu_table->entries)
 292                return -ENOMEM;
 293
 294        entry = &atom_table->entries[0];
 295        for (i = 0; i < atom_table->ucNumEntries; i++) {
 296                amdgpu_table->entries[i].clk = le16_to_cpu(entry->usClockLow) |
 297                        (entry->ucClockHigh << 16);
 298                amdgpu_table->entries[i].v = le16_to_cpu(entry->usVoltage);
 299                entry = (ATOM_PPLIB_Clock_Voltage_Dependency_Record *)
 300                        ((u8 *)entry + sizeof(ATOM_PPLIB_Clock_Voltage_Dependency_Record));
 301        }
 302        amdgpu_table->count = atom_table->ucNumEntries;
 303
 304        return 0;
 305}
 306
 307int amdgpu_get_platform_caps(struct amdgpu_device *adev)
 308{
 309        struct amdgpu_mode_info *mode_info = &adev->mode_info;
 310        union power_info *power_info;
 311        int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
 312        u16 data_offset;
 313        u8 frev, crev;
 314
 315        if (!amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL,
 316                                   &frev, &crev, &data_offset))
 317                return -EINVAL;
 318        power_info = (union power_info *)(mode_info->atom_context->bios + data_offset);
 319
 320        adev->pm.dpm.platform_caps = le32_to_cpu(power_info->pplib.ulPlatformCaps);
 321        adev->pm.dpm.backbias_response_time = le16_to_cpu(power_info->pplib.usBackbiasTime);
 322        adev->pm.dpm.voltage_response_time = le16_to_cpu(power_info->pplib.usVoltageTime);
 323
 324        return 0;
 325}
 326
 327/* sizeof(ATOM_PPLIB_EXTENDEDHEADER) */
 328#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2 12
 329#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3 14
 330#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4 16
 331#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5 18
 332#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6 20
 333#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7 22
 334#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V8 24
 335#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V9 26
 336
 337int amdgpu_parse_extended_power_table(struct amdgpu_device *adev)
 338{
 339        struct amdgpu_mode_info *mode_info = &adev->mode_info;
 340        union power_info *power_info;
 341        union fan_info *fan_info;
 342        ATOM_PPLIB_Clock_Voltage_Dependency_Table *dep_table;
 343        int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
 344        u16 data_offset;
 345        u8 frev, crev;
 346        int ret, i;
 347
 348        if (!amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL,
 349                                   &frev, &crev, &data_offset))
 350                return -EINVAL;
 351        power_info = (union power_info *)(mode_info->atom_context->bios + data_offset);
 352
 353        /* fan table */
 354        if (le16_to_cpu(power_info->pplib.usTableSize) >=
 355            sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE3)) {
 356                if (power_info->pplib3.usFanTableOffset) {
 357                        fan_info = (union fan_info *)(mode_info->atom_context->bios + data_offset +
 358                                                      le16_to_cpu(power_info->pplib3.usFanTableOffset));
 359                        adev->pm.dpm.fan.t_hyst = fan_info->fan.ucTHyst;
 360                        adev->pm.dpm.fan.t_min = le16_to_cpu(fan_info->fan.usTMin);
 361                        adev->pm.dpm.fan.t_med = le16_to_cpu(fan_info->fan.usTMed);
 362                        adev->pm.dpm.fan.t_high = le16_to_cpu(fan_info->fan.usTHigh);
 363                        adev->pm.dpm.fan.pwm_min = le16_to_cpu(fan_info->fan.usPWMMin);
 364                        adev->pm.dpm.fan.pwm_med = le16_to_cpu(fan_info->fan.usPWMMed);
 365                        adev->pm.dpm.fan.pwm_high = le16_to_cpu(fan_info->fan.usPWMHigh);
 366                        if (fan_info->fan.ucFanTableFormat >= 2)
 367                                adev->pm.dpm.fan.t_max = le16_to_cpu(fan_info->fan2.usTMax);
 368                        else
 369                                adev->pm.dpm.fan.t_max = 10900;
 370                        adev->pm.dpm.fan.cycle_delay = 100000;
 371                        if (fan_info->fan.ucFanTableFormat >= 3) {
 372                                adev->pm.dpm.fan.control_mode = fan_info->fan3.ucFanControlMode;
 373                                adev->pm.dpm.fan.default_max_fan_pwm =
 374                                        le16_to_cpu(fan_info->fan3.usFanPWMMax);
 375                                adev->pm.dpm.fan.default_fan_output_sensitivity = 4836;
 376                                adev->pm.dpm.fan.fan_output_sensitivity =
 377                                        le16_to_cpu(fan_info->fan3.usFanOutputSensitivity);
 378                        }
 379                        adev->pm.dpm.fan.ucode_fan_control = true;
 380                }
 381        }
 382
 383        /* clock dependancy tables, shedding tables */
 384        if (le16_to_cpu(power_info->pplib.usTableSize) >=
 385            sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE4)) {
 386                if (power_info->pplib4.usVddcDependencyOnSCLKOffset) {
 387                        dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
 388                                (mode_info->atom_context->bios + data_offset +
 389                                 le16_to_cpu(power_info->pplib4.usVddcDependencyOnSCLKOffset));
 390                        ret = amdgpu_parse_clk_voltage_dep_table(&adev->pm.dpm.dyn_state.vddc_dependency_on_sclk,
 391                                                                 dep_table);
 392                        if (ret) {
 393                                amdgpu_free_extended_power_table(adev);
 394                                return ret;
 395                        }
 396                }
 397                if (power_info->pplib4.usVddciDependencyOnMCLKOffset) {
 398                        dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
 399                                (mode_info->atom_context->bios + data_offset +
 400                                 le16_to_cpu(power_info->pplib4.usVddciDependencyOnMCLKOffset));
 401                        ret = amdgpu_parse_clk_voltage_dep_table(&adev->pm.dpm.dyn_state.vddci_dependency_on_mclk,
 402                                                                 dep_table);
 403                        if (ret) {
 404                                amdgpu_free_extended_power_table(adev);
 405                                return ret;
 406                        }
 407                }
 408                if (power_info->pplib4.usVddcDependencyOnMCLKOffset) {
 409                        dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
 410                                (mode_info->atom_context->bios + data_offset +
 411                                 le16_to_cpu(power_info->pplib4.usVddcDependencyOnMCLKOffset));
 412                        ret = amdgpu_parse_clk_voltage_dep_table(&adev->pm.dpm.dyn_state.vddc_dependency_on_mclk,
 413                                                                 dep_table);
 414                        if (ret) {
 415                                amdgpu_free_extended_power_table(adev);
 416                                return ret;
 417                        }
 418                }
 419                if (power_info->pplib4.usMvddDependencyOnMCLKOffset) {
 420                        dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
 421                                (mode_info->atom_context->bios + data_offset +
 422                                 le16_to_cpu(power_info->pplib4.usMvddDependencyOnMCLKOffset));
 423                        ret = amdgpu_parse_clk_voltage_dep_table(&adev->pm.dpm.dyn_state.mvdd_dependency_on_mclk,
 424                                                                 dep_table);
 425                        if (ret) {
 426                                amdgpu_free_extended_power_table(adev);
 427                                return ret;
 428                        }
 429                }
 430                if (power_info->pplib4.usMaxClockVoltageOnDCOffset) {
 431                        ATOM_PPLIB_Clock_Voltage_Limit_Table *clk_v =
 432                                (ATOM_PPLIB_Clock_Voltage_Limit_Table *)
 433                                (mode_info->atom_context->bios + data_offset +
 434                                 le16_to_cpu(power_info->pplib4.usMaxClockVoltageOnDCOffset));
 435                        if (clk_v->ucNumEntries) {
 436                                adev->pm.dpm.dyn_state.max_clock_voltage_on_dc.sclk =
 437                                        le16_to_cpu(clk_v->entries[0].usSclkLow) |
 438                                        (clk_v->entries[0].ucSclkHigh << 16);
 439                                adev->pm.dpm.dyn_state.max_clock_voltage_on_dc.mclk =
 440                                        le16_to_cpu(clk_v->entries[0].usMclkLow) |
 441                                        (clk_v->entries[0].ucMclkHigh << 16);
 442                                adev->pm.dpm.dyn_state.max_clock_voltage_on_dc.vddc =
 443                                        le16_to_cpu(clk_v->entries[0].usVddc);
 444                                adev->pm.dpm.dyn_state.max_clock_voltage_on_dc.vddci =
 445                                        le16_to_cpu(clk_v->entries[0].usVddci);
 446                        }
 447                }
 448                if (power_info->pplib4.usVddcPhaseShedLimitsTableOffset) {
 449                        ATOM_PPLIB_PhaseSheddingLimits_Table *psl =
 450                                (ATOM_PPLIB_PhaseSheddingLimits_Table *)
 451                                (mode_info->atom_context->bios + data_offset +
 452                                 le16_to_cpu(power_info->pplib4.usVddcPhaseShedLimitsTableOffset));
 453                        ATOM_PPLIB_PhaseSheddingLimits_Record *entry;
 454
 455                        adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries =
 456                                kcalloc(psl->ucNumEntries,
 457                                        sizeof(struct amdgpu_phase_shedding_limits_entry),
 458                                        GFP_KERNEL);
 459                        if (!adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries) {
 460                                amdgpu_free_extended_power_table(adev);
 461                                return -ENOMEM;
 462                        }
 463
 464                        entry = &psl->entries[0];
 465                        for (i = 0; i < psl->ucNumEntries; i++) {
 466                                adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries[i].sclk =
 467                                        le16_to_cpu(entry->usSclkLow) | (entry->ucSclkHigh << 16);
 468                                adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries[i].mclk =
 469                                        le16_to_cpu(entry->usMclkLow) | (entry->ucMclkHigh << 16);
 470                                adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries[i].voltage =
 471                                        le16_to_cpu(entry->usVoltage);
 472                                entry = (ATOM_PPLIB_PhaseSheddingLimits_Record *)
 473                                        ((u8 *)entry + sizeof(ATOM_PPLIB_PhaseSheddingLimits_Record));
 474                        }
 475                        adev->pm.dpm.dyn_state.phase_shedding_limits_table.count =
 476                                psl->ucNumEntries;
 477                }
 478        }
 479
 480        /* cac data */
 481        if (le16_to_cpu(power_info->pplib.usTableSize) >=
 482            sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE5)) {
 483                adev->pm.dpm.tdp_limit = le32_to_cpu(power_info->pplib5.ulTDPLimit);
 484                adev->pm.dpm.near_tdp_limit = le32_to_cpu(power_info->pplib5.ulNearTDPLimit);
 485                adev->pm.dpm.near_tdp_limit_adjusted = adev->pm.dpm.near_tdp_limit;
 486                adev->pm.dpm.tdp_od_limit = le16_to_cpu(power_info->pplib5.usTDPODLimit);
 487                if (adev->pm.dpm.tdp_od_limit)
 488                        adev->pm.dpm.power_control = true;
 489                else
 490                        adev->pm.dpm.power_control = false;
 491                adev->pm.dpm.tdp_adjustment = 0;
 492                adev->pm.dpm.sq_ramping_threshold = le32_to_cpu(power_info->pplib5.ulSQRampingThreshold);
 493                adev->pm.dpm.cac_leakage = le32_to_cpu(power_info->pplib5.ulCACLeakage);
 494                adev->pm.dpm.load_line_slope = le16_to_cpu(power_info->pplib5.usLoadLineSlope);
 495                if (power_info->pplib5.usCACLeakageTableOffset) {
 496                        ATOM_PPLIB_CAC_Leakage_Table *cac_table =
 497                                (ATOM_PPLIB_CAC_Leakage_Table *)
 498                                (mode_info->atom_context->bios + data_offset +
 499                                 le16_to_cpu(power_info->pplib5.usCACLeakageTableOffset));
 500                        ATOM_PPLIB_CAC_Leakage_Record *entry;
 501                        u32 size = cac_table->ucNumEntries * sizeof(struct amdgpu_cac_leakage_table);
 502                        adev->pm.dpm.dyn_state.cac_leakage_table.entries = kzalloc(size, GFP_KERNEL);
 503                        if (!adev->pm.dpm.dyn_state.cac_leakage_table.entries) {
 504                                amdgpu_free_extended_power_table(adev);
 505                                return -ENOMEM;
 506                        }
 507                        entry = &cac_table->entries[0];
 508                        for (i = 0; i < cac_table->ucNumEntries; i++) {
 509                                if (adev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_EVV) {
 510                                        adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc1 =
 511                                                le16_to_cpu(entry->usVddc1);
 512                                        adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc2 =
 513                                                le16_to_cpu(entry->usVddc2);
 514                                        adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc3 =
 515                                                le16_to_cpu(entry->usVddc3);
 516                                } else {
 517                                        adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc =
 518                                                le16_to_cpu(entry->usVddc);
 519                                        adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].leakage =
 520                                                le32_to_cpu(entry->ulLeakageValue);
 521                                }
 522                                entry = (ATOM_PPLIB_CAC_Leakage_Record *)
 523                                        ((u8 *)entry + sizeof(ATOM_PPLIB_CAC_Leakage_Record));
 524                        }
 525                        adev->pm.dpm.dyn_state.cac_leakage_table.count = cac_table->ucNumEntries;
 526                }
 527        }
 528
 529        /* ext tables */
 530        if (le16_to_cpu(power_info->pplib.usTableSize) >=
 531            sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE3)) {
 532                ATOM_PPLIB_EXTENDEDHEADER *ext_hdr = (ATOM_PPLIB_EXTENDEDHEADER *)
 533                        (mode_info->atom_context->bios + data_offset +
 534                         le16_to_cpu(power_info->pplib3.usExtendendedHeaderOffset));
 535                if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2) &&
 536                        ext_hdr->usVCETableOffset) {
 537                        VCEClockInfoArray *array = (VCEClockInfoArray *)
 538                                (mode_info->atom_context->bios + data_offset +
 539                                 le16_to_cpu(ext_hdr->usVCETableOffset) + 1);
 540                        ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *limits =
 541                                (ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *)
 542                                (mode_info->atom_context->bios + data_offset +
 543                                 le16_to_cpu(ext_hdr->usVCETableOffset) + 1 +
 544                                 1 + array->ucNumEntries * sizeof(VCEClockInfo));
 545                        ATOM_PPLIB_VCE_State_Table *states =
 546                                (ATOM_PPLIB_VCE_State_Table *)
 547                                (mode_info->atom_context->bios + data_offset +
 548                                 le16_to_cpu(ext_hdr->usVCETableOffset) + 1 +
 549                                 1 + (array->ucNumEntries * sizeof (VCEClockInfo)) +
 550                                 1 + (limits->numEntries * sizeof(ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record)));
 551                        ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record *entry;
 552                        ATOM_PPLIB_VCE_State_Record *state_entry;
 553                        VCEClockInfo *vce_clk;
 554                        u32 size = limits->numEntries *
 555                                sizeof(struct amdgpu_vce_clock_voltage_dependency_entry);
 556                        adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries =
 557                                kzalloc(size, GFP_KERNEL);
 558                        if (!adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries) {
 559                                amdgpu_free_extended_power_table(adev);
 560                                return -ENOMEM;
 561                        }
 562                        adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.count =
 563                                limits->numEntries;
 564                        entry = &limits->entries[0];
 565                        state_entry = &states->entries[0];
 566                        for (i = 0; i < limits->numEntries; i++) {
 567                                vce_clk = (VCEClockInfo *)
 568                                        ((u8 *)&array->entries[0] +
 569                                         (entry->ucVCEClockInfoIndex * sizeof(VCEClockInfo)));
 570                                adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries[i].evclk =
 571                                        le16_to_cpu(vce_clk->usEVClkLow) | (vce_clk->ucEVClkHigh << 16);
 572                                adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries[i].ecclk =
 573                                        le16_to_cpu(vce_clk->usECClkLow) | (vce_clk->ucECClkHigh << 16);
 574                                adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries[i].v =
 575                                        le16_to_cpu(entry->usVoltage);
 576                                entry = (ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record *)
 577                                        ((u8 *)entry + sizeof(ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record));
 578                        }
 579                        adev->pm.dpm.num_of_vce_states =
 580                                        states->numEntries > AMD_MAX_VCE_LEVELS ?
 581                                        AMD_MAX_VCE_LEVELS : states->numEntries;
 582                        for (i = 0; i < adev->pm.dpm.num_of_vce_states; i++) {
 583                                vce_clk = (VCEClockInfo *)
 584                                        ((u8 *)&array->entries[0] +
 585                                         (state_entry->ucVCEClockInfoIndex * sizeof(VCEClockInfo)));
 586                                adev->pm.dpm.vce_states[i].evclk =
 587                                        le16_to_cpu(vce_clk->usEVClkLow) | (vce_clk->ucEVClkHigh << 16);
 588                                adev->pm.dpm.vce_states[i].ecclk =
 589                                        le16_to_cpu(vce_clk->usECClkLow) | (vce_clk->ucECClkHigh << 16);
 590                                adev->pm.dpm.vce_states[i].clk_idx =
 591                                        state_entry->ucClockInfoIndex & 0x3f;
 592                                adev->pm.dpm.vce_states[i].pstate =
 593                                        (state_entry->ucClockInfoIndex & 0xc0) >> 6;
 594                                state_entry = (ATOM_PPLIB_VCE_State_Record *)
 595                                        ((u8 *)state_entry + sizeof(ATOM_PPLIB_VCE_State_Record));
 596                        }
 597                }
 598                if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3) &&
 599                        ext_hdr->usUVDTableOffset) {
 600                        UVDClockInfoArray *array = (UVDClockInfoArray *)
 601                                (mode_info->atom_context->bios + data_offset +
 602                                 le16_to_cpu(ext_hdr->usUVDTableOffset) + 1);
 603                        ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *limits =
 604                                (ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *)
 605                                (mode_info->atom_context->bios + data_offset +
 606                                 le16_to_cpu(ext_hdr->usUVDTableOffset) + 1 +
 607                                 1 + (array->ucNumEntries * sizeof (UVDClockInfo)));
 608                        ATOM_PPLIB_UVD_Clock_Voltage_Limit_Record *entry;
 609                        u32 size = limits->numEntries *
 610                                sizeof(struct amdgpu_uvd_clock_voltage_dependency_entry);
 611                        adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries =
 612                                kzalloc(size, GFP_KERNEL);
 613                        if (!adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries) {
 614                                amdgpu_free_extended_power_table(adev);
 615                                return -ENOMEM;
 616                        }
 617                        adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.count =
 618                                limits->numEntries;
 619                        entry = &limits->entries[0];
 620                        for (i = 0; i < limits->numEntries; i++) {
 621                                UVDClockInfo *uvd_clk = (UVDClockInfo *)
 622                                        ((u8 *)&array->entries[0] +
 623                                         (entry->ucUVDClockInfoIndex * sizeof(UVDClockInfo)));
 624                                adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries[i].vclk =
 625                                        le16_to_cpu(uvd_clk->usVClkLow) | (uvd_clk->ucVClkHigh << 16);
 626                                adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries[i].dclk =
 627                                        le16_to_cpu(uvd_clk->usDClkLow) | (uvd_clk->ucDClkHigh << 16);
 628                                adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries[i].v =
 629                                        le16_to_cpu(entry->usVoltage);
 630                                entry = (ATOM_PPLIB_UVD_Clock_Voltage_Limit_Record *)
 631                                        ((u8 *)entry + sizeof(ATOM_PPLIB_UVD_Clock_Voltage_Limit_Record));
 632                        }
 633                }
 634                if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4) &&
 635                        ext_hdr->usSAMUTableOffset) {
 636                        ATOM_PPLIB_SAMClk_Voltage_Limit_Table *limits =
 637                                (ATOM_PPLIB_SAMClk_Voltage_Limit_Table *)
 638                                (mode_info->atom_context->bios + data_offset +
 639                                 le16_to_cpu(ext_hdr->usSAMUTableOffset) + 1);
 640                        ATOM_PPLIB_SAMClk_Voltage_Limit_Record *entry;
 641                        u32 size = limits->numEntries *
 642                                sizeof(struct amdgpu_clock_voltage_dependency_entry);
 643                        adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries =
 644                                kzalloc(size, GFP_KERNEL);
 645                        if (!adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries) {
 646                                amdgpu_free_extended_power_table(adev);
 647                                return -ENOMEM;
 648                        }
 649                        adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.count =
 650                                limits->numEntries;
 651                        entry = &limits->entries[0];
 652                        for (i = 0; i < limits->numEntries; i++) {
 653                                adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries[i].clk =
 654                                        le16_to_cpu(entry->usSAMClockLow) | (entry->ucSAMClockHigh << 16);
 655                                adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries[i].v =
 656                                        le16_to_cpu(entry->usVoltage);
 657                                entry = (ATOM_PPLIB_SAMClk_Voltage_Limit_Record *)
 658                                        ((u8 *)entry + sizeof(ATOM_PPLIB_SAMClk_Voltage_Limit_Record));
 659                        }
 660                }
 661                if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5) &&
 662                    ext_hdr->usPPMTableOffset) {
 663                        ATOM_PPLIB_PPM_Table *ppm = (ATOM_PPLIB_PPM_Table *)
 664                                (mode_info->atom_context->bios + data_offset +
 665                                 le16_to_cpu(ext_hdr->usPPMTableOffset));
 666                        adev->pm.dpm.dyn_state.ppm_table =
 667                                kzalloc(sizeof(struct amdgpu_ppm_table), GFP_KERNEL);
 668                        if (!adev->pm.dpm.dyn_state.ppm_table) {
 669                                amdgpu_free_extended_power_table(adev);
 670                                return -ENOMEM;
 671                        }
 672                        adev->pm.dpm.dyn_state.ppm_table->ppm_design = ppm->ucPpmDesign;
 673                        adev->pm.dpm.dyn_state.ppm_table->cpu_core_number =
 674                                le16_to_cpu(ppm->usCpuCoreNumber);
 675                        adev->pm.dpm.dyn_state.ppm_table->platform_tdp =
 676                                le32_to_cpu(ppm->ulPlatformTDP);
 677                        adev->pm.dpm.dyn_state.ppm_table->small_ac_platform_tdp =
 678                                le32_to_cpu(ppm->ulSmallACPlatformTDP);
 679                        adev->pm.dpm.dyn_state.ppm_table->platform_tdc =
 680                                le32_to_cpu(ppm->ulPlatformTDC);
 681                        adev->pm.dpm.dyn_state.ppm_table->small_ac_platform_tdc =
 682                                le32_to_cpu(ppm->ulSmallACPlatformTDC);
 683                        adev->pm.dpm.dyn_state.ppm_table->apu_tdp =
 684                                le32_to_cpu(ppm->ulApuTDP);
 685                        adev->pm.dpm.dyn_state.ppm_table->dgpu_tdp =
 686                                le32_to_cpu(ppm->ulDGpuTDP);
 687                        adev->pm.dpm.dyn_state.ppm_table->dgpu_ulv_power =
 688                                le32_to_cpu(ppm->ulDGpuUlvPower);
 689                        adev->pm.dpm.dyn_state.ppm_table->tj_max =
 690                                le32_to_cpu(ppm->ulTjmax);
 691                }
 692                if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6) &&
 693                        ext_hdr->usACPTableOffset) {
 694                        ATOM_PPLIB_ACPClk_Voltage_Limit_Table *limits =
 695                                (ATOM_PPLIB_ACPClk_Voltage_Limit_Table *)
 696                                (mode_info->atom_context->bios + data_offset +
 697                                 le16_to_cpu(ext_hdr->usACPTableOffset) + 1);
 698                        ATOM_PPLIB_ACPClk_Voltage_Limit_Record *entry;
 699                        u32 size = limits->numEntries *
 700                                sizeof(struct amdgpu_clock_voltage_dependency_entry);
 701                        adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries =
 702                                kzalloc(size, GFP_KERNEL);
 703                        if (!adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries) {
 704                                amdgpu_free_extended_power_table(adev);
 705                                return -ENOMEM;
 706                        }
 707                        adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.count =
 708                                limits->numEntries;
 709                        entry = &limits->entries[0];
 710                        for (i = 0; i < limits->numEntries; i++) {
 711                                adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries[i].clk =
 712                                        le16_to_cpu(entry->usACPClockLow) | (entry->ucACPClockHigh << 16);
 713                                adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries[i].v =
 714                                        le16_to_cpu(entry->usVoltage);
 715                                entry = (ATOM_PPLIB_ACPClk_Voltage_Limit_Record *)
 716                                        ((u8 *)entry + sizeof(ATOM_PPLIB_ACPClk_Voltage_Limit_Record));
 717                        }
 718                }
 719                if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7) &&
 720                        ext_hdr->usPowerTuneTableOffset) {
 721                        u8 rev = *(u8 *)(mode_info->atom_context->bios + data_offset +
 722                                         le16_to_cpu(ext_hdr->usPowerTuneTableOffset));
 723                        ATOM_PowerTune_Table *pt;
 724                        adev->pm.dpm.dyn_state.cac_tdp_table =
 725                                kzalloc(sizeof(struct amdgpu_cac_tdp_table), GFP_KERNEL);
 726                        if (!adev->pm.dpm.dyn_state.cac_tdp_table) {
 727                                amdgpu_free_extended_power_table(adev);
 728                                return -ENOMEM;
 729                        }
 730                        if (rev > 0) {
 731                                ATOM_PPLIB_POWERTUNE_Table_V1 *ppt = (ATOM_PPLIB_POWERTUNE_Table_V1 *)
 732                                        (mode_info->atom_context->bios + data_offset +
 733                                         le16_to_cpu(ext_hdr->usPowerTuneTableOffset));
 734                                adev->pm.dpm.dyn_state.cac_tdp_table->maximum_power_delivery_limit =
 735                                        ppt->usMaximumPowerDeliveryLimit;
 736                                pt = &ppt->power_tune_table;
 737                        } else {
 738                                ATOM_PPLIB_POWERTUNE_Table *ppt = (ATOM_PPLIB_POWERTUNE_Table *)
 739                                        (mode_info->atom_context->bios + data_offset +
 740                                         le16_to_cpu(ext_hdr->usPowerTuneTableOffset));
 741                                adev->pm.dpm.dyn_state.cac_tdp_table->maximum_power_delivery_limit = 255;
 742                                pt = &ppt->power_tune_table;
 743                        }
 744                        adev->pm.dpm.dyn_state.cac_tdp_table->tdp = le16_to_cpu(pt->usTDP);
 745                        adev->pm.dpm.dyn_state.cac_tdp_table->configurable_tdp =
 746                                le16_to_cpu(pt->usConfigurableTDP);
 747                        adev->pm.dpm.dyn_state.cac_tdp_table->tdc = le16_to_cpu(pt->usTDC);
 748                        adev->pm.dpm.dyn_state.cac_tdp_table->battery_power_limit =
 749                                le16_to_cpu(pt->usBatteryPowerLimit);
 750                        adev->pm.dpm.dyn_state.cac_tdp_table->small_power_limit =
 751                                le16_to_cpu(pt->usSmallPowerLimit);
 752                        adev->pm.dpm.dyn_state.cac_tdp_table->low_cac_leakage =
 753                                le16_to_cpu(pt->usLowCACLeakage);
 754                        adev->pm.dpm.dyn_state.cac_tdp_table->high_cac_leakage =
 755                                le16_to_cpu(pt->usHighCACLeakage);
 756                }
 757                if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V8) &&
 758                                ext_hdr->usSclkVddgfxTableOffset) {
 759                        dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
 760                                (mode_info->atom_context->bios + data_offset +
 761                                 le16_to_cpu(ext_hdr->usSclkVddgfxTableOffset));
 762                        ret = amdgpu_parse_clk_voltage_dep_table(
 763                                        &adev->pm.dpm.dyn_state.vddgfx_dependency_on_sclk,
 764                                        dep_table);
 765                        if (ret) {
 766                                kfree(adev->pm.dpm.dyn_state.vddgfx_dependency_on_sclk.entries);
 767                                return ret;
 768                        }
 769                }
 770        }
 771
 772        return 0;
 773}
 774
 775void amdgpu_free_extended_power_table(struct amdgpu_device *adev)
 776{
 777        struct amdgpu_dpm_dynamic_state *dyn_state = &adev->pm.dpm.dyn_state;
 778
 779        kfree(dyn_state->vddc_dependency_on_sclk.entries);
 780        kfree(dyn_state->vddci_dependency_on_mclk.entries);
 781        kfree(dyn_state->vddc_dependency_on_mclk.entries);
 782        kfree(dyn_state->mvdd_dependency_on_mclk.entries);
 783        kfree(dyn_state->cac_leakage_table.entries);
 784        kfree(dyn_state->phase_shedding_limits_table.entries);
 785        kfree(dyn_state->ppm_table);
 786        kfree(dyn_state->cac_tdp_table);
 787        kfree(dyn_state->vce_clock_voltage_dependency_table.entries);
 788        kfree(dyn_state->uvd_clock_voltage_dependency_table.entries);
 789        kfree(dyn_state->samu_clock_voltage_dependency_table.entries);
 790        kfree(dyn_state->acp_clock_voltage_dependency_table.entries);
 791        kfree(dyn_state->vddgfx_dependency_on_sclk.entries);
 792}
 793
 794static const char *pp_lib_thermal_controller_names[] = {
 795        "NONE",
 796        "lm63",
 797        "adm1032",
 798        "adm1030",
 799        "max6649",
 800        "lm64",
 801        "f75375",
 802        "RV6xx",
 803        "RV770",
 804        "adt7473",
 805        "NONE",
 806        "External GPIO",
 807        "Evergreen",
 808        "emc2103",
 809        "Sumo",
 810        "Northern Islands",
 811        "Southern Islands",
 812        "lm96163",
 813        "Sea Islands",
 814        "Kaveri/Kabini",
 815};
 816
 817void amdgpu_add_thermal_controller(struct amdgpu_device *adev)
 818{
 819        struct amdgpu_mode_info *mode_info = &adev->mode_info;
 820        ATOM_PPLIB_POWERPLAYTABLE *power_table;
 821        int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
 822        ATOM_PPLIB_THERMALCONTROLLER *controller;
 823        struct amdgpu_i2c_bus_rec i2c_bus;
 824        u16 data_offset;
 825        u8 frev, crev;
 826
 827        if (!amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL,
 828                                   &frev, &crev, &data_offset))
 829                return;
 830        power_table = (ATOM_PPLIB_POWERPLAYTABLE *)
 831                (mode_info->atom_context->bios + data_offset);
 832        controller = &power_table->sThermalController;
 833
 834        /* add the i2c bus for thermal/fan chip */
 835        if (controller->ucType > 0) {
 836                if (controller->ucFanParameters & ATOM_PP_FANPARAMETERS_NOFAN)
 837                        adev->pm.no_fan = true;
 838                adev->pm.fan_pulses_per_revolution =
 839                        controller->ucFanParameters & ATOM_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK;
 840                if (adev->pm.fan_pulses_per_revolution) {
 841                        adev->pm.fan_min_rpm = controller->ucFanMinRPM;
 842                        adev->pm.fan_max_rpm = controller->ucFanMaxRPM;
 843                }
 844                if (controller->ucType == ATOM_PP_THERMALCONTROLLER_RV6xx) {
 845                        DRM_INFO("Internal thermal controller %s fan control\n",
 846                                 (controller->ucFanParameters &
 847                                  ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
 848                        adev->pm.int_thermal_type = THERMAL_TYPE_RV6XX;
 849                } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_RV770) {
 850                        DRM_INFO("Internal thermal controller %s fan control\n",
 851                                 (controller->ucFanParameters &
 852                                  ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
 853                        adev->pm.int_thermal_type = THERMAL_TYPE_RV770;
 854                } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_EVERGREEN) {
 855                        DRM_INFO("Internal thermal controller %s fan control\n",
 856                                 (controller->ucFanParameters &
 857                                  ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
 858                        adev->pm.int_thermal_type = THERMAL_TYPE_EVERGREEN;
 859                } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_SUMO) {
 860                        DRM_INFO("Internal thermal controller %s fan control\n",
 861                                 (controller->ucFanParameters &
 862                                  ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
 863                        adev->pm.int_thermal_type = THERMAL_TYPE_SUMO;
 864                } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_NISLANDS) {
 865                        DRM_INFO("Internal thermal controller %s fan control\n",
 866                                 (controller->ucFanParameters &
 867                                  ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
 868                        adev->pm.int_thermal_type = THERMAL_TYPE_NI;
 869                } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_SISLANDS) {
 870                        DRM_INFO("Internal thermal controller %s fan control\n",
 871                                 (controller->ucFanParameters &
 872                                  ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
 873                        adev->pm.int_thermal_type = THERMAL_TYPE_SI;
 874                } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_CISLANDS) {
 875                        DRM_INFO("Internal thermal controller %s fan control\n",
 876                                 (controller->ucFanParameters &
 877                                  ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
 878                        adev->pm.int_thermal_type = THERMAL_TYPE_CI;
 879                } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_KAVERI) {
 880                        DRM_INFO("Internal thermal controller %s fan control\n",
 881                                 (controller->ucFanParameters &
 882                                  ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
 883                        adev->pm.int_thermal_type = THERMAL_TYPE_KV;
 884                } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_EXTERNAL_GPIO) {
 885                        DRM_INFO("External GPIO thermal controller %s fan control\n",
 886                                 (controller->ucFanParameters &
 887                                  ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
 888                        adev->pm.int_thermal_type = THERMAL_TYPE_EXTERNAL_GPIO;
 889                } else if (controller->ucType ==
 890                           ATOM_PP_THERMALCONTROLLER_ADT7473_WITH_INTERNAL) {
 891                        DRM_INFO("ADT7473 with internal thermal controller %s fan control\n",
 892                                 (controller->ucFanParameters &
 893                                  ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
 894                        adev->pm.int_thermal_type = THERMAL_TYPE_ADT7473_WITH_INTERNAL;
 895                } else if (controller->ucType ==
 896                           ATOM_PP_THERMALCONTROLLER_EMC2103_WITH_INTERNAL) {
 897                        DRM_INFO("EMC2103 with internal thermal controller %s fan control\n",
 898                                 (controller->ucFanParameters &
 899                                  ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
 900                        adev->pm.int_thermal_type = THERMAL_TYPE_EMC2103_WITH_INTERNAL;
 901                } else if (controller->ucType < ARRAY_SIZE(pp_lib_thermal_controller_names)) {
 902                        DRM_INFO("Possible %s thermal controller at 0x%02x %s fan control\n",
 903                                 pp_lib_thermal_controller_names[controller->ucType],
 904                                 controller->ucI2cAddress >> 1,
 905                                 (controller->ucFanParameters &
 906                                  ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
 907                        adev->pm.int_thermal_type = THERMAL_TYPE_EXTERNAL;
 908                        i2c_bus = amdgpu_atombios_lookup_i2c_gpio(adev, controller->ucI2cLine);
 909                        adev->pm.i2c_bus = amdgpu_i2c_lookup(adev, &i2c_bus);
 910                        if (adev->pm.i2c_bus) {
 911                                struct i2c_board_info info = { };
 912                                const char *name = pp_lib_thermal_controller_names[controller->ucType];
 913                                info.addr = controller->ucI2cAddress >> 1;
 914                                strlcpy(info.type, name, sizeof(info.type));
 915                                i2c_new_device(&adev->pm.i2c_bus->adapter, &info);
 916                        }
 917                } else {
 918                        DRM_INFO("Unknown thermal controller type %d at 0x%02x %s fan control\n",
 919                                 controller->ucType,
 920                                 controller->ucI2cAddress >> 1,
 921                                 (controller->ucFanParameters &
 922                                  ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
 923                }
 924        }
 925}
 926
 927enum amdgpu_pcie_gen amdgpu_get_pcie_gen_support(struct amdgpu_device *adev,
 928                                                 u32 sys_mask,
 929                                                 enum amdgpu_pcie_gen asic_gen,
 930                                                 enum amdgpu_pcie_gen default_gen)
 931{
 932        switch (asic_gen) {
 933        case AMDGPU_PCIE_GEN1:
 934                return AMDGPU_PCIE_GEN1;
 935        case AMDGPU_PCIE_GEN2:
 936                return AMDGPU_PCIE_GEN2;
 937        case AMDGPU_PCIE_GEN3:
 938                return AMDGPU_PCIE_GEN3;
 939        default:
 940                if ((sys_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3) &&
 941                    (default_gen == AMDGPU_PCIE_GEN3))
 942                        return AMDGPU_PCIE_GEN3;
 943                else if ((sys_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2) &&
 944                         (default_gen == AMDGPU_PCIE_GEN2))
 945                        return AMDGPU_PCIE_GEN2;
 946                else
 947                        return AMDGPU_PCIE_GEN1;
 948        }
 949        return AMDGPU_PCIE_GEN1;
 950}
 951
 952u16 amdgpu_get_pcie_lane_support(struct amdgpu_device *adev,
 953                                 u16 asic_lanes,
 954                                 u16 default_lanes)
 955{
 956        switch (asic_lanes) {
 957        case 0:
 958        default:
 959                return default_lanes;
 960        case 1:
 961                return 1;
 962        case 2:
 963                return 2;
 964        case 4:
 965                return 4;
 966        case 8:
 967                return 8;
 968        case 12:
 969                return 12;
 970        case 16:
 971                return 16;
 972        }
 973}
 974
 975u8 amdgpu_encode_pci_lane_width(u32 lanes)
 976{
 977        u8 encoded_lanes[] = { 0, 1, 2, 0, 3, 0, 0, 0, 4, 0, 0, 0, 5, 0, 0, 0, 6 };
 978
 979        if (lanes > 16)
 980                return 0;
 981
 982        return encoded_lanes[lanes];
 983}
 984
 985struct amd_vce_state*
 986amdgpu_get_vce_clock_state(void *handle, u32 idx)
 987{
 988        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 989
 990        if (idx < adev->pm.dpm.num_of_vce_states)
 991                return &adev->pm.dpm.vce_states[idx];
 992
 993        return NULL;
 994}
 995