/*
* Copyright 2019 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include "pp_debug.h"
#include <linux/firmware.h>
#include <drm/drmP.h>
#include "amdgpu.h"
#include "amdgpu_smu.h"
#include "soc15_common.h"
#include "smu_v11_0.h"
#include "atom.h"
#include "amd_pcie.h"
int smu_dpm_set_power_gate(struct smu_context *smu, uint32_t block_type,
bool gate)
{
int ret = 0;
switch (block_type) {
case AMD_IP_BLOCK_TYPE_UVD:
ret = smu_dpm_set_uvd_enable(smu, gate);
break;
case AMD_IP_BLOCK_TYPE_VCE:
ret = smu_dpm_set_vce_enable(smu, gate);
break;
default:
break;
}
return ret;
}
enum amd_pm_state_type smu_get_current_power_state(struct smu_context *smu)
{
/* not support power state */
return POWER_STATE_TYPE_DEFAULT;
}
int smu_get_power_num_states(struct smu_context *smu,
struct pp_states_info *state_info)
{
if (!state_info)
return -EINVAL;
/* not support power state */
memset(state_info, 0, sizeof(struct pp_states_info));
state_info->nums = 0;
return 0;
}
int smu_common_read_sensor(struct smu_context *smu, enum amd_pp_sensors sensor,
void *data, uint32_t *size)
{
int ret = 0;
switch (sensor) {
case AMDGPU_PP_SENSOR_STABLE_PSTATE_SCLK:
*((uint32_t *)data) = smu->pstate_sclk;
*size = 4;
break;
case AMDGPU_PP_SENSOR_STABLE_PSTATE_MCLK:
*((uint32_t *)data) = smu->pstate_mclk;
*size = 4;
break;
case AMDGPU_PP_SENSOR_ENABLED_SMC_FEATURES_MASK:
ret = smu_feature_get_enabled_mask(smu, (uint32_t *)data, 2);
*size = 8;
break;
default:
ret = -EINVAL;
break;
}
if (ret)
*size = 0;
return ret;
}
int smu_update_table_with_arg(struct smu_context *smu, uint16_t table_id, uint16_t exarg,
void *table_data, bool drv2smu)
{
struct smu_table_context *smu_table = &smu->smu_table;
struct smu_table *table = NULL;
int ret = 0;
uint32_t table_index;
if (!table_data || table_id >= smu_table->table_count)
return -EINVAL;
table_index = (exarg << 16) | table_id;
table = &smu_table->tables[table_id];
if (drv2smu)
memcpy(table->cpu_addr, table_data, table->size);
ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetDriverDramAddrHigh,
upper_32_bits(table->mc_address));