linux/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_thermal.c
<<
>>
Prefs
   1/*
   2 * Copyright 2016 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 */
  23
  24#include <asm/div64.h>
  25#include "smu7_thermal.h"
  26#include "smu7_hwmgr.h"
  27#include "smu7_common.h"
  28
  29int smu7_fan_ctrl_get_fan_speed_info(struct pp_hwmgr *hwmgr,
  30                struct phm_fan_speed_info *fan_speed_info)
  31{
  32        if (hwmgr->thermal_controller.fanInfo.bNoFan)
  33                return -ENODEV;
  34
  35        fan_speed_info->supports_percent_read = true;
  36        fan_speed_info->supports_percent_write = true;
  37        fan_speed_info->min_percent = 0;
  38        fan_speed_info->max_percent = 100;
  39
  40        if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
  41                        PHM_PlatformCaps_FanSpeedInTableIsRPM) &&
  42                hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution) {
  43                fan_speed_info->supports_rpm_read = true;
  44                fan_speed_info->supports_rpm_write = true;
  45                fan_speed_info->min_rpm = hwmgr->thermal_controller.fanInfo.ulMinRPM;
  46                fan_speed_info->max_rpm = hwmgr->thermal_controller.fanInfo.ulMaxRPM;
  47        } else {
  48                fan_speed_info->min_rpm = 0;
  49                fan_speed_info->max_rpm = 0;
  50        }
  51
  52        return 0;
  53}
  54
  55int smu7_fan_ctrl_get_fan_speed_percent(struct pp_hwmgr *hwmgr,
  56                uint32_t *speed)
  57{
  58        uint32_t duty100;
  59        uint32_t duty;
  60        uint64_t tmp64;
  61
  62        if (hwmgr->thermal_controller.fanInfo.bNoFan)
  63                return -ENODEV;
  64
  65        duty100 = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
  66                        CG_FDO_CTRL1, FMAX_DUTY100);
  67        duty = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
  68                        CG_THERMAL_STATUS, FDO_PWM_DUTY);
  69
  70        if (duty100 == 0)
  71                return -EINVAL;
  72
  73
  74        tmp64 = (uint64_t)duty * 100;
  75        do_div(tmp64, duty100);
  76        *speed = (uint32_t)tmp64;
  77
  78        if (*speed > 100)
  79                *speed = 100;
  80
  81        return 0;
  82}
  83
  84int smu7_fan_ctrl_get_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t *speed)
  85{
  86        uint32_t tach_period;
  87        uint32_t crystal_clock_freq;
  88
  89        if (hwmgr->thermal_controller.fanInfo.bNoFan ||
  90                        (hwmgr->thermal_controller.fanInfo.
  91                                ucTachometerPulsesPerRevolution == 0))
  92                return -ENODEV;
  93
  94        tach_period = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
  95                        CG_TACH_STATUS, TACH_PERIOD);
  96
  97        if (tach_period == 0)
  98                return -EINVAL;
  99
 100        crystal_clock_freq = smu7_get_xclk(hwmgr);
 101
 102        *speed = 60 * crystal_clock_freq * 10000 / tach_period;
 103
 104        return 0;
 105}
 106
 107/**
 108* Set Fan Speed Control to static mode, so that the user can decide what speed to use.
 109* @param    hwmgr  the address of the powerplay hardware manager.
 110*           mode    the fan control mode, 0 default, 1 by percent, 5, by RPM
 111* @exception Should always succeed.
 112*/
 113int smu7_fan_ctrl_set_static_mode(struct pp_hwmgr *hwmgr, uint32_t mode)
 114{
 115        if (hwmgr->fan_ctrl_is_in_default_mode) {
 116                hwmgr->fan_ctrl_default_mode =
 117                                PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
 118                                                CG_FDO_CTRL2, FDO_PWM_MODE);
 119                hwmgr->tmin =
 120                                PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
 121                                                CG_FDO_CTRL2, TMIN);
 122                hwmgr->fan_ctrl_is_in_default_mode = false;
 123        }
 124
 125        PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
 126                        CG_FDO_CTRL2, TMIN, 0);
 127        PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
 128                        CG_FDO_CTRL2, FDO_PWM_MODE, mode);
 129
 130        return 0;
 131}
 132
 133/**
 134* Reset Fan Speed Control to default mode.
 135* @param    hwmgr  the address of the powerplay hardware manager.
 136* @exception Should always succeed.
 137*/
 138int smu7_fan_ctrl_set_default_mode(struct pp_hwmgr *hwmgr)
 139{
 140        if (!hwmgr->fan_ctrl_is_in_default_mode) {
 141                PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
 142                                CG_FDO_CTRL2, FDO_PWM_MODE, hwmgr->fan_ctrl_default_mode);
 143                PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
 144                                CG_FDO_CTRL2, TMIN, hwmgr->tmin);
 145                hwmgr->fan_ctrl_is_in_default_mode = true;
 146        }
 147
 148        return 0;
 149}
 150
 151int smu7_fan_ctrl_start_smc_fan_control(struct pp_hwmgr *hwmgr)
 152{
 153        int result;
 154
 155        if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
 156                        PHM_PlatformCaps_ODFuzzyFanControlSupport)) {
 157                cgs_write_register(hwmgr->device, mmSMC_MSG_ARG_0, FAN_CONTROL_FUZZY);
 158                result = smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_StartFanControl);
 159
 160                if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
 161                                PHM_PlatformCaps_FanSpeedInTableIsRPM))
 162                        hwmgr->hwmgr_func->set_max_fan_rpm_output(hwmgr,
 163                                        hwmgr->thermal_controller.
 164                                        advanceFanControlParameters.usMaxFanRPM);
 165                else
 166                        hwmgr->hwmgr_func->set_max_fan_pwm_output(hwmgr,
 167                                        hwmgr->thermal_controller.
 168                                        advanceFanControlParameters.usMaxFanPWM);
 169
 170        } else {
 171                cgs_write_register(hwmgr->device, mmSMC_MSG_ARG_0, FAN_CONTROL_TABLE);
 172                result = smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_StartFanControl);
 173        }
 174
 175        if (!result && hwmgr->thermal_controller.
 176                        advanceFanControlParameters.ucTargetTemperature)
 177                result = smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
 178                                PPSMC_MSG_SetFanTemperatureTarget,
 179                                hwmgr->thermal_controller.
 180                                advanceFanControlParameters.ucTargetTemperature);
 181        hwmgr->fan_ctrl_enabled = true;
 182
 183        return result;
 184}
 185
 186
 187int smu7_fan_ctrl_stop_smc_fan_control(struct pp_hwmgr *hwmgr)
 188{
 189        hwmgr->fan_ctrl_enabled = false;
 190        return smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_StopFanControl);
 191}
 192
 193/**
 194* Set Fan Speed in percent.
 195* @param    hwmgr  the address of the powerplay hardware manager.
 196* @param    speed is the percentage value (0% - 100%) to be set.
 197* @exception Fails is the 100% setting appears to be 0.
 198*/
 199int smu7_fan_ctrl_set_fan_speed_percent(struct pp_hwmgr *hwmgr,
 200                uint32_t speed)
 201{
 202        uint32_t duty100;
 203        uint32_t duty;
 204        uint64_t tmp64;
 205
 206        if (hwmgr->thermal_controller.fanInfo.bNoFan)
 207                return 0;
 208
 209        if (speed > 100)
 210                speed = 100;
 211
 212        if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
 213                        PHM_PlatformCaps_MicrocodeFanControl))
 214                smu7_fan_ctrl_stop_smc_fan_control(hwmgr);
 215
 216        duty100 = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
 217                        CG_FDO_CTRL1, FMAX_DUTY100);
 218
 219        if (duty100 == 0)
 220                return -EINVAL;
 221
 222        tmp64 = (uint64_t)speed * duty100;
 223        do_div(tmp64, 100);
 224        duty = (uint32_t)tmp64;
 225
 226        PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
 227                        CG_FDO_CTRL0, FDO_STATIC_DUTY, duty);
 228
 229        return smu7_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC);
 230}
 231
 232/**
 233* Reset Fan Speed to default.
 234* @param    hwmgr  the address of the powerplay hardware manager.
 235* @exception Always succeeds.
 236*/
 237int smu7_fan_ctrl_reset_fan_speed_to_default(struct pp_hwmgr *hwmgr)
 238{
 239        int result;
 240
 241        if (hwmgr->thermal_controller.fanInfo.bNoFan)
 242                return 0;
 243
 244        if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
 245                        PHM_PlatformCaps_MicrocodeFanControl)) {
 246                result = smu7_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC);
 247                if (!result)
 248                        result = smu7_fan_ctrl_start_smc_fan_control(hwmgr);
 249        } else
 250                result = smu7_fan_ctrl_set_default_mode(hwmgr);
 251
 252        return result;
 253}
 254
 255/**
 256* Set Fan Speed in RPM.
 257* @param    hwmgr  the address of the powerplay hardware manager.
 258* @param    speed is the percentage value (min - max) to be set.
 259* @exception Fails is the speed not lie between min and max.
 260*/
 261int smu7_fan_ctrl_set_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t speed)
 262{
 263        uint32_t tach_period;
 264        uint32_t crystal_clock_freq;
 265
 266        if (hwmgr->thermal_controller.fanInfo.bNoFan ||
 267                        (hwmgr->thermal_controller.fanInfo.
 268                        ucTachometerPulsesPerRevolution == 0) ||
 269                        (speed < hwmgr->thermal_controller.fanInfo.ulMinRPM) ||
 270                        (speed > hwmgr->thermal_controller.fanInfo.ulMaxRPM))
 271                return 0;
 272
 273        if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
 274                        PHM_PlatformCaps_MicrocodeFanControl))
 275                smu7_fan_ctrl_stop_smc_fan_control(hwmgr);
 276
 277        crystal_clock_freq = smu7_get_xclk(hwmgr);
 278
 279        tach_period = 60 * crystal_clock_freq * 10000 / (8 * speed);
 280
 281        PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
 282                                CG_TACH_STATUS, TACH_PERIOD, tach_period);
 283
 284        return smu7_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC_RPM);
 285}
 286
 287/**
 288* Reads the remote temperature from the SIslands thermal controller.
 289*
 290* @param    hwmgr The address of the hardware manager.
 291*/
 292int smu7_thermal_get_temperature(struct pp_hwmgr *hwmgr)
 293{
 294        int temp;
 295
 296        temp = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
 297                        CG_MULT_THERMAL_STATUS, CTF_TEMP);
 298
 299        /* Bit 9 means the reading is lower than the lowest usable value. */
 300        if (temp & 0x200)
 301                temp = SMU7_THERMAL_MAXIMUM_TEMP_READING;
 302        else
 303                temp = temp & 0x1ff;
 304
 305        temp *= PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
 306
 307        return temp;
 308}
 309
 310/**
 311* Set the requested temperature range for high and low alert signals
 312*
 313* @param    hwmgr The address of the hardware manager.
 314* @param    range Temperature range to be programmed for high and low alert signals
 315* @exception PP_Result_BadInput if the input data is not valid.
 316*/
 317static int smu7_thermal_set_temperature_range(struct pp_hwmgr *hwmgr,
 318                uint32_t low_temp, uint32_t high_temp)
 319{
 320        uint32_t low = SMU7_THERMAL_MINIMUM_ALERT_TEMP *
 321                        PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
 322        uint32_t high = SMU7_THERMAL_MAXIMUM_ALERT_TEMP *
 323                        PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
 324
 325        if (low < low_temp)
 326                low = low_temp;
 327        if (high > high_temp)
 328                high = high_temp;
 329
 330        if (low > high)
 331                return -EINVAL;
 332
 333        PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
 334                        CG_THERMAL_INT, DIG_THERM_INTH,
 335                        (high / PP_TEMPERATURE_UNITS_PER_CENTIGRADES));
 336        PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
 337                        CG_THERMAL_INT, DIG_THERM_INTL,
 338                        (low / PP_TEMPERATURE_UNITS_PER_CENTIGRADES));
 339        PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
 340                        CG_THERMAL_CTRL, DIG_THERM_DPM,
 341                        (high / PP_TEMPERATURE_UNITS_PER_CENTIGRADES));
 342
 343        return 0;
 344}
 345
 346/**
 347* Programs thermal controller one-time setting registers
 348*
 349* @param    hwmgr The address of the hardware manager.
 350*/
 351static int smu7_thermal_initialize(struct pp_hwmgr *hwmgr)
 352{
 353        if (hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution)
 354                PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
 355                                CG_TACH_CTRL, EDGE_PER_REV,
 356                                hwmgr->thermal_controller.fanInfo.
 357                                ucTachometerPulsesPerRevolution - 1);
 358
 359        PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
 360                        CG_FDO_CTRL2, TACH_PWM_RESP_RATE, 0x28);
 361
 362        return 0;
 363}
 364
 365/**
 366* Enable thermal alerts on the RV770 thermal controller.
 367*
 368* @param    hwmgr The address of the hardware manager.
 369*/
 370int smu7_thermal_enable_alert(struct pp_hwmgr *hwmgr)
 371{
 372        uint32_t alert;
 373
 374        alert = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
 375                        CG_THERMAL_INT, THERM_INT_MASK);
 376        alert &= ~(SMU7_THERMAL_HIGH_ALERT_MASK | SMU7_THERMAL_LOW_ALERT_MASK);
 377        PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
 378                        CG_THERMAL_INT, THERM_INT_MASK, alert);
 379
 380        /* send message to SMU to enable internal thermal interrupts */
 381        return smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_Thermal_Cntl_Enable);
 382}
 383
 384/**
 385* Disable thermal alerts on the RV770 thermal controller.
 386* @param    hwmgr The address of the hardware manager.
 387*/
 388int smu7_thermal_disable_alert(struct pp_hwmgr *hwmgr)
 389{
 390        uint32_t alert;
 391
 392        alert = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
 393                        CG_THERMAL_INT, THERM_INT_MASK);
 394        alert |= (SMU7_THERMAL_HIGH_ALERT_MASK | SMU7_THERMAL_LOW_ALERT_MASK);
 395        PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
 396                        CG_THERMAL_INT, THERM_INT_MASK, alert);
 397
 398        /* send message to SMU to disable internal thermal interrupts */
 399        return smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_Thermal_Cntl_Disable);
 400}
 401
 402/**
 403* Uninitialize the thermal controller.
 404* Currently just disables alerts.
 405* @param    hwmgr The address of the hardware manager.
 406*/
 407int smu7_thermal_stop_thermal_controller(struct pp_hwmgr *hwmgr)
 408{
 409        int result = smu7_thermal_disable_alert(hwmgr);
 410
 411        if (!hwmgr->thermal_controller.fanInfo.bNoFan)
 412                smu7_fan_ctrl_set_default_mode(hwmgr);
 413
 414        return result;
 415}
 416
 417/**
 418* Start the fan control on the SMC.
 419* @param    hwmgr  the address of the powerplay hardware manager.
 420* @param    pInput the pointer to input data
 421* @param    pOutput the pointer to output data
 422* @param    pStorage the pointer to temporary storage
 423* @param    Result the last failure code
 424* @return   result from set temperature range routine
 425*/
 426static int tf_smu7_thermal_start_smc_fan_control(struct pp_hwmgr *hwmgr,
 427                void *input, void *output, void *storage, int result)
 428{
 429/* If the fantable setup has failed we could have disabled
 430 * PHM_PlatformCaps_MicrocodeFanControl even after
 431 * this function was included in the table.
 432 * Make sure that we still think controlling the fan is OK.
 433*/
 434        if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
 435                        PHM_PlatformCaps_MicrocodeFanControl)) {
 436                smu7_fan_ctrl_start_smc_fan_control(hwmgr);
 437                smu7_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC);
 438        }
 439
 440        return 0;
 441}
 442
 443/**
 444* Set temperature range for high and low alerts
 445* @param    hwmgr  the address of the powerplay hardware manager.
 446* @param    pInput the pointer to input data
 447* @param    pOutput the pointer to output data
 448* @param    pStorage the pointer to temporary storage
 449* @param    Result the last failure code
 450* @return   result from set temperature range routine
 451*/
 452static int tf_smu7_thermal_set_temperature_range(struct pp_hwmgr *hwmgr,
 453                void *input, void *output, void *storage, int result)
 454{
 455        struct PP_TemperatureRange *range = (struct PP_TemperatureRange *)input;
 456
 457        if (range == NULL)
 458                return -EINVAL;
 459
 460        return smu7_thermal_set_temperature_range(hwmgr, range->min, range->max);
 461}
 462
 463/**
 464* Programs one-time setting registers
 465* @param    hwmgr  the address of the powerplay hardware manager.
 466* @param    pInput the pointer to input data
 467* @param    pOutput the pointer to output data
 468* @param    pStorage the pointer to temporary storage
 469* @param    Result the last failure code
 470* @return   result from initialize thermal controller routine
 471*/
 472static int tf_smu7_thermal_initialize(struct pp_hwmgr *hwmgr,
 473                void *input, void *output, void *storage, int result)
 474{
 475        return smu7_thermal_initialize(hwmgr);
 476}
 477
 478/**
 479* Enable high and low alerts
 480* @param    hwmgr  the address of the powerplay hardware manager.
 481* @param    pInput the pointer to input data
 482* @param    pOutput the pointer to output data
 483* @param    pStorage the pointer to temporary storage
 484* @param    Result the last failure code
 485* @return   result from enable alert routine
 486*/
 487static int tf_smu7_thermal_enable_alert(struct pp_hwmgr *hwmgr,
 488                void *input, void *output, void *storage, int result)
 489{
 490        return smu7_thermal_enable_alert(hwmgr);
 491}
 492
 493/**
 494* Disable high and low alerts
 495* @param    hwmgr  the address of the powerplay hardware manager.
 496* @param    pInput the pointer to input data
 497* @param    pOutput the pointer to output data
 498* @param    pStorage the pointer to temporary storage
 499* @param    Result the last failure code
 500* @return   result from disable alert routine
 501*/
 502static int tf_smu7_thermal_disable_alert(struct pp_hwmgr *hwmgr,
 503                void *input, void *output, void *storage, int result)
 504{
 505        return smu7_thermal_disable_alert(hwmgr);
 506}
 507
 508static const struct phm_master_table_item
 509phm_thermal_start_thermal_controller_master_list[] = {
 510        { .tableFunction = tf_smu7_thermal_initialize },
 511        { .tableFunction = tf_smu7_thermal_set_temperature_range },
 512        { .tableFunction = tf_smu7_thermal_enable_alert },
 513        { .tableFunction = smum_thermal_avfs_enable },
 514/* We should restrict performance levels to low before we halt the SMC.
 515 * On the other hand we are still in boot state when we do this
 516 * so it would be pointless.
 517 * If this assumption changes we have to revisit this table.
 518 */
 519        { .tableFunction = smum_thermal_setup_fan_table },
 520        { .tableFunction = tf_smu7_thermal_start_smc_fan_control },
 521        { }
 522};
 523
 524static const struct phm_master_table_header
 525phm_thermal_start_thermal_controller_master = {
 526        0,
 527        PHM_MasterTableFlag_None,
 528        phm_thermal_start_thermal_controller_master_list
 529};
 530
 531static const struct phm_master_table_item
 532phm_thermal_set_temperature_range_master_list[] = {
 533        { .tableFunction = tf_smu7_thermal_disable_alert },
 534        { .tableFunction = tf_smu7_thermal_set_temperature_range },
 535        { .tableFunction = tf_smu7_thermal_enable_alert },
 536        { }
 537};
 538
 539static const struct phm_master_table_header
 540phm_thermal_set_temperature_range_master = {
 541        0,
 542        PHM_MasterTableFlag_None,
 543        phm_thermal_set_temperature_range_master_list
 544};
 545
 546int smu7_thermal_ctrl_uninitialize_thermal_controller(struct pp_hwmgr *hwmgr)
 547{
 548        if (!hwmgr->thermal_controller.fanInfo.bNoFan)
 549                smu7_fan_ctrl_set_default_mode(hwmgr);
 550        return 0;
 551}
 552
 553/**
 554* Initializes the thermal controller related functions in the Hardware Manager structure.
 555* @param    hwmgr The address of the hardware manager.
 556* @exception Any error code from the low-level communication.
 557*/
 558int pp_smu7_thermal_initialize(struct pp_hwmgr *hwmgr)
 559{
 560        int result;
 561
 562        result = phm_construct_table(hwmgr,
 563                        &phm_thermal_set_temperature_range_master,
 564                        &(hwmgr->set_temperature_range));
 565
 566        if (!result) {
 567                result = phm_construct_table(hwmgr,
 568                                &phm_thermal_start_thermal_controller_master,
 569                                &(hwmgr->start_thermal_controller));
 570                if (result)
 571                        phm_destroy_table(hwmgr, &(hwmgr->set_temperature_range));
 572        }
 573
 574        if (!result)
 575                hwmgr->fan_ctrl_is_in_default_mode = true;
 576        return result;
 577}
 578
 579void pp_smu7_thermal_fini(struct pp_hwmgr *hwmgr)
 580{
 581        phm_destroy_table(hwmgr, &(hwmgr->set_temperature_range));
 582        phm_destroy_table(hwmgr, &(hwmgr->start_thermal_controller));
 583        return;
 584}