Commit f8d1ea42 authored by Nicholas Kazlauskas's avatar Nicholas Kazlauskas Committed by Alex Deucher
Browse files

drm/amd/display: Add DCN3.1 clock manager support



Adds support for clock requests for the various parts of the DCN3.1 IP
and the interfaces and definitions for sending messages to SMU/PMFW.

Includes new support for z9/10, detecting SMU timeout and p-state
support enablement.
Signed-off-by: Nicholas Kazlauskas's avatarNicholas Kazlauskas <nicholas.kazlauskas@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent e14ae4e9
......@@ -655,6 +655,12 @@ void dm_set_dcn_clocks(struct dc_context *ctx, struct dc_clocks *clks)
/* TODO: something */
}
void dm_helpers_smu_timeout(struct dc_context *ctx, unsigned int msg_id, unsigned int param, unsigned int timeout_us)
{
// TODO:
//amdgpu_device_gpu_recover(dc_context->driver-context, NULL);
}
void *dm_helpers_allocate_gpu_mem(
struct dc_context *ctx,
enum dc_gpu_mem_alloc_type type,
......
......@@ -136,3 +136,14 @@ AMD_DAL_CLK_MGR_DCN301 = $(addprefix $(AMDDALPATH)/dc/clk_mgr/dcn301/,$(CLK_MGR_
AMD_DISPLAY_FILES += $(AMD_DAL_CLK_MGR_DCN301)
endif
ifdef CONFIG_DRM_AMD_DC_DCN3_1
###############################################################################
# DCN31
###############################################################################
CLK_MGR_DCN31 = dcn31_smu.o dcn31_clk_mgr.o
AMD_DAL_CLK_MGR_DCN31 = $(addprefix $(AMDDALPATH)/dc/clk_mgr/dcn31/,$(CLK_MGR_DCN31))
AMD_DISPLAY_FILES += $(AMD_DAL_CLK_MGR_DCN31)
endif
......@@ -41,6 +41,9 @@
#include "dcn21/rn_clk_mgr.h"
#include "dcn30/dcn30_clk_mgr.h"
#include "dcn301/vg_clk_mgr.h"
#if defined(CONFIG_DRM_AMD_DC_DCN3_1)
#include "dcn31/dcn31_clk_mgr.h"
#endif
int clk_mgr_helper_get_active_display_cnt(
......@@ -261,6 +264,26 @@ struct clk_mgr *dc_clk_mgr_create(struct dc_context *ctx, struct pp_smu_funcs *p
}
break;
#endif
#if defined(CONFIG_DRM_AMD_DC_DCN3_1)
case FAMILY_YELLOW_CARP: {
struct clk_mgr_dcn31 *clk_mgr = kzalloc(sizeof(*clk_mgr), GFP_KERNEL);
if (clk_mgr == NULL) {
BREAK_TO_DEBUGGER();
return NULL;
}
if (ASICREV_IS_YELLOW_CARP(asic_id.hw_internal_rev)) {
/* TODO: to add DCN31 clk_mgr support, once CLK IP header files are available,
* for now use DCN3.0 clk mgr.
*/
dcn31_clk_mgr_construct(ctx, clk_mgr, pp_smu, dccg);
return &clk_mgr->base.base;
}
return &clk_mgr->base.base;
}
#endif
default:
ASSERT(0); /* Unknown Asic */
break;
......@@ -292,6 +315,13 @@ void dc_destroy_clk_mgr(struct clk_mgr *clk_mgr_base)
vg_clk_mgr_destroy(clk_mgr);
break;
#if defined(CONFIG_DRM_AMD_DC_DCN3_1)
case FAMILY_YELLOW_CARP:
if (ASICREV_IS_YELLOW_CARP(clk_mgr_base->ctx->asic_id.hw_internal_rev))
dcn31_clk_mgr_destroy(clk_mgr);
break;
#endif
default:
break;
}
......
......@@ -324,6 +324,10 @@ void dcn2_update_clocks_fpga(struct clk_mgr *clk_mgr,
// Both fclk and ref_dppclk run on the same scemi clock.
clk_mgr_int->dccg->ref_dppclk = clk_mgr->clks.fclk_khz;
#if defined(CONFIG_DRM_AMD_DC_DCN3_1)
/* TODO: set dtbclk in correct place */
clk_mgr->clks.dtbclk_en = false;
#endif
dm_set_dcn_clocks(clk_mgr->ctx, &clk_mgr->clks);
}
......
This diff is collapsed.
/*
* 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.
*
* Authors: AMD
*
*/
#ifndef __DCN31_CLK_MGR_H__
#define __DCN31_CLK_MGR_H__
#include "clk_mgr_internal.h"
//CLK1_CLK_PLL_REQ
#ifndef CLK11_CLK1_CLK_PLL_REQ__FbMult_int__SHIFT
#define CLK11_CLK1_CLK_PLL_REQ__FbMult_int__SHIFT 0x0
#define CLK11_CLK1_CLK_PLL_REQ__PllSpineDiv__SHIFT 0xc
#define CLK11_CLK1_CLK_PLL_REQ__FbMult_frac__SHIFT 0x10
#define CLK11_CLK1_CLK_PLL_REQ__FbMult_int_MASK 0x000001FFL
#define CLK11_CLK1_CLK_PLL_REQ__PllSpineDiv_MASK 0x0000F000L
#define CLK11_CLK1_CLK_PLL_REQ__FbMult_frac_MASK 0xFFFF0000L
//CLK1_CLK0_DFS_CNTL
#define CLK11_CLK1_CLK0_DFS_CNTL__CLK0_DIVIDER__SHIFT 0x0
#define CLK11_CLK1_CLK0_DFS_CNTL__CLK0_DIVIDER_MASK 0x0000007FL
/*DPREF clock related*/
#define CLK0_CLK3_DFS_CNTL__CLK3_DIVIDER__SHIFT 0x0
#define CLK0_CLK3_DFS_CNTL__CLK3_DIVIDER_MASK 0x0000007FL
#define CLK1_CLK3_DFS_CNTL__CLK3_DIVIDER__SHIFT 0x0
#define CLK1_CLK3_DFS_CNTL__CLK3_DIVIDER_MASK 0x0000007FL
#define CLK2_CLK3_DFS_CNTL__CLK3_DIVIDER__SHIFT 0x0
#define CLK2_CLK3_DFS_CNTL__CLK3_DIVIDER_MASK 0x0000007FL
#define CLK3_CLK3_DFS_CNTL__CLK3_DIVIDER__SHIFT 0x0
#define CLK3_CLK3_DFS_CNTL__CLK3_DIVIDER_MASK 0x0000007FL
//CLK3_0_CLK3_CLK_PLL_REQ
#define CLK3_0_CLK3_CLK_PLL_REQ__FbMult_int__SHIFT 0x0
#define CLK3_0_CLK3_CLK_PLL_REQ__PllSpineDiv__SHIFT 0xc
#define CLK3_0_CLK3_CLK_PLL_REQ__FbMult_frac__SHIFT 0x10
#define CLK3_0_CLK3_CLK_PLL_REQ__FbMult_int_MASK 0x000001FFL
#define CLK3_0_CLK3_CLK_PLL_REQ__PllSpineDiv_MASK 0x0000F000L
#define CLK3_0_CLK3_CLK_PLL_REQ__FbMult_frac_MASK 0xFFFF0000L
#define mmCLK0_CLK3_DFS_CNTL 0x16C60
#define mmCLK00_CLK0_CLK3_DFS_CNTL 0x16C60
#define mmCLK01_CLK0_CLK3_DFS_CNTL 0x16E60
#define mmCLK02_CLK0_CLK3_DFS_CNTL 0x17060
#define mmCLK03_CLK0_CLK3_DFS_CNTL 0x17260
#define mmCLK0_CLK_PLL_REQ 0x16C10
#define mmCLK00_CLK0_CLK_PLL_REQ 0x16C10
#define mmCLK01_CLK0_CLK_PLL_REQ 0x16E10
#define mmCLK02_CLK0_CLK_PLL_REQ 0x17010
#define mmCLK03_CLK0_CLK_PLL_REQ 0x17210
#define mmCLK1_CLK_PLL_REQ 0x1B00D
#define mmCLK10_CLK1_CLK_PLL_REQ 0x1B00D
#define mmCLK11_CLK1_CLK_PLL_REQ 0x1B20D
#define mmCLK12_CLK1_CLK_PLL_REQ 0x1B40D
#define mmCLK13_CLK1_CLK_PLL_REQ 0x1B60D
#define mmCLK2_CLK_PLL_REQ 0x17E0D
/*AMCLK*/
#define mmCLK11_CLK1_CLK0_DFS_CNTL 0x1B23F
#define mmCLK11_CLK1_CLK_PLL_REQ 0x1B20D
#endif
struct dcn31_watermarks;
struct dcn31_smu_watermark_set {
struct dcn31_watermarks *wm_set;
union large_integer mc_address;
};
struct clk_mgr_dcn31 {
struct clk_mgr_internal base;
struct dcn31_smu_watermark_set smu_wm_set;
};
void dcn31_clk_mgr_construct(struct dc_context *ctx,
struct clk_mgr_dcn31 *clk_mgr,
struct pp_smu_funcs *pp_smu,
struct dccg *dccg);
void dcn31_clk_mgr_destroy(struct clk_mgr_internal *clk_mgr_int);
#endif //__DCN31_CLK_MGR_H__
/*
* Copyright 2012-16 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.
*
* Authors: AMD
*
*/
#include <linux/delay.h>
#include "core_types.h"
#include "clk_mgr_internal.h"
#include "reg_helper.h"
#include "dm_helpers.h"
#include "dcn31_smu.h"
#include "yellow_carp_offset.h"
#include "mp/mp_13_0_1_offset.h"
#include "mp/mp_13_0_1_sh_mask.h"
#define REG(reg_name) \
(MP0_BASE.instance[0].segment[reg ## reg_name ## _BASE_IDX] + reg ## reg_name)
#define FN(reg_name, field) \
FD(reg_name##__##field)
#define VBIOSSMC_MSG_TestMessage 0x1
#define VBIOSSMC_MSG_GetSmuVersion 0x2
#define VBIOSSMC_MSG_PowerUpGfx 0x3
#define VBIOSSMC_MSG_SetDispclkFreq 0x4
#define VBIOSSMC_MSG_SetDprefclkFreq 0x5 //Not used. DPRef is constant
#define VBIOSSMC_MSG_SetDppclkFreq 0x6
#define VBIOSSMC_MSG_SetHardMinDcfclkByFreq 0x7
#define VBIOSSMC_MSG_SetMinDeepSleepDcfclk 0x8
#define VBIOSSMC_MSG_SetPhyclkVoltageByFreq 0x9 //Keep it in case VMIN dees not support phy clk
#define VBIOSSMC_MSG_GetFclkFrequency 0xA
#define VBIOSSMC_MSG_SetDisplayCount 0xB //Not used anymore
#define VBIOSSMC_MSG_EnableTmdp48MHzRefclkPwrDown 0xC //Not used anymore
#define VBIOSSMC_MSG_UpdatePmeRestore 0xD
#define VBIOSSMC_MSG_SetVbiosDramAddrHigh 0xE //Used for WM table txfr
#define VBIOSSMC_MSG_SetVbiosDramAddrLow 0xF
#define VBIOSSMC_MSG_TransferTableSmu2Dram 0x10
#define VBIOSSMC_MSG_TransferTableDram2Smu 0x11
#define VBIOSSMC_MSG_SetDisplayIdleOptimizations 0x12
#define VBIOSSMC_MSG_GetDprefclkFreq 0x13
#define VBIOSSMC_MSG_GetDtbclkFreq 0x14
#define VBIOSSMC_MSG_AllowZstatesEntry 0x15
#define VBIOSSMC_MSG_DisallowZstatesEntry 0x16
#define VBIOSSMC_MSG_SetDtbClk 0x17
#define VBIOSSMC_Message_Count 0x18
#define VBIOSSMC_Status_BUSY 0x0
#define VBIOSSMC_Result_OK 0x1
#define VBIOSSMC_Result_Failed 0xFF
#define VBIOSSMC_Result_UnknownCmd 0xFE
#define VBIOSSMC_Result_CmdRejectedPrereq 0xFD
#define VBIOSSMC_Result_CmdRejectedBusy 0xFC
/*
* Function to be used instead of REG_WAIT macro because the wait ends when
* the register is NOT EQUAL to zero, and because the translation in msg_if.h
* won't work with REG_WAIT.
*/
static uint32_t dcn31_smu_wait_for_response(struct clk_mgr_internal *clk_mgr, unsigned int delay_us, unsigned int max_retries)
{
uint32_t res_val = VBIOSSMC_Status_BUSY;
do {
res_val = REG_READ(MP1_SMN_C2PMSG_91);
if (res_val != VBIOSSMC_Status_BUSY)
break;
if (delay_us >= 1000)
msleep(delay_us/1000);
else if (delay_us > 0)
udelay(delay_us);
} while (max_retries--);
return res_val;
}
int dcn31_smu_send_msg_with_param(
struct clk_mgr_internal *clk_mgr,
unsigned int msg_id, unsigned int param)
{
uint32_t result;
result = dcn31_smu_wait_for_response(clk_mgr, 10, 200000);
ASSERT(result == VBIOSSMC_Result_OK);
if (result == VBIOSSMC_Status_BUSY) {
return -1;
}
/* First clear response register */
REG_WRITE(MP1_SMN_C2PMSG_91, VBIOSSMC_Status_BUSY);
/* Set the parameter register for the SMU message, unit is Mhz */
REG_WRITE(MP1_SMN_C2PMSG_83, param);
/* Trigger the message transaction by writing the message ID */
REG_WRITE(MP1_SMN_C2PMSG_67, msg_id);
result = dcn31_smu_wait_for_response(clk_mgr, 10, 200000);
if (IS_SMU_TIMEOUT(result)) {
ASSERT(0);
dm_helpers_smu_timeout(CTX, msg_id, param, 10 * 200000);
}
return REG_READ(MP1_SMN_C2PMSG_83);
}
int dcn31_smu_get_smu_version(struct clk_mgr_internal *clk_mgr)
{
return dcn31_smu_send_msg_with_param(
clk_mgr,
VBIOSSMC_MSG_GetSmuVersion,
0);
}
int dcn31_smu_set_dispclk(struct clk_mgr_internal *clk_mgr, int requested_dispclk_khz)
{
int actual_dispclk_set_mhz = -1;
if (!clk_mgr->smu_present)
return requested_dispclk_khz;
/* Unit of SMU msg parameter is Mhz */
actual_dispclk_set_mhz = dcn31_smu_send_msg_with_param(
clk_mgr,
VBIOSSMC_MSG_SetDispclkFreq,
(requested_dispclk_khz + 999) / 1000);
return actual_dispclk_set_mhz * 1000;
}
int dcn31_smu_set_dprefclk(struct clk_mgr_internal *clk_mgr)
{
int actual_dprefclk_set_mhz = -1;
if (!clk_mgr->smu_present)
return clk_mgr->base.dprefclk_khz;
actual_dprefclk_set_mhz = dcn31_smu_send_msg_with_param(
clk_mgr,
VBIOSSMC_MSG_SetDprefclkFreq,
(clk_mgr->base.dprefclk_khz + 999) / 1000);
/* TODO: add code for programing DP DTO, currently this is down by command table */
return actual_dprefclk_set_mhz * 1000;
}
int dcn31_smu_set_hard_min_dcfclk(struct clk_mgr_internal *clk_mgr, int requested_dcfclk_khz)
{
int actual_dcfclk_set_mhz = -1;
if (!clk_mgr->base.ctx->dc->debug.pstate_enabled)
return -1;
if (!clk_mgr->smu_present)
return requested_dcfclk_khz;
actual_dcfclk_set_mhz = dcn31_smu_send_msg_with_param(
clk_mgr,
VBIOSSMC_MSG_SetHardMinDcfclkByFreq,
(requested_dcfclk_khz + 999) / 1000);
return actual_dcfclk_set_mhz * 1000;
}
int dcn31_smu_set_min_deep_sleep_dcfclk(struct clk_mgr_internal *clk_mgr, int requested_min_ds_dcfclk_khz)
{
int actual_min_ds_dcfclk_mhz = -1;
if (!clk_mgr->base.ctx->dc->debug.pstate_enabled)
return -1;
if (!clk_mgr->smu_present)
return requested_min_ds_dcfclk_khz;
actual_min_ds_dcfclk_mhz = dcn31_smu_send_msg_with_param(
clk_mgr,
VBIOSSMC_MSG_SetMinDeepSleepDcfclk,
(requested_min_ds_dcfclk_khz + 999) / 1000);
return actual_min_ds_dcfclk_mhz * 1000;
}
int dcn31_smu_set_dppclk(struct clk_mgr_internal *clk_mgr, int requested_dpp_khz)
{
int actual_dppclk_set_mhz = -1;
if (!clk_mgr->smu_present)
return requested_dpp_khz;
actual_dppclk_set_mhz = dcn31_smu_send_msg_with_param(
clk_mgr,
VBIOSSMC_MSG_SetDppclkFreq,
(requested_dpp_khz + 999) / 1000);
return actual_dppclk_set_mhz * 1000;
}
void dcn31_smu_set_display_idle_optimization(struct clk_mgr_internal *clk_mgr, uint32_t idle_info)
{
if (!clk_mgr->base.ctx->dc->debug.pstate_enabled)
return;
if (!clk_mgr->smu_present)
return;
//TODO: Work with smu team to define optimization options.
dcn31_smu_send_msg_with_param(
clk_mgr,
VBIOSSMC_MSG_SetDisplayIdleOptimizations,
idle_info);
}
void dcn31_smu_enable_phy_refclk_pwrdwn(struct clk_mgr_internal *clk_mgr, bool enable)
{
union display_idle_optimization_u idle_info = { 0 };
if (!clk_mgr->smu_present)
return;
if (enable) {
idle_info.idle_info.df_request_disabled = 1;
idle_info.idle_info.phy_ref_clk_off = 1;
}
dcn31_smu_send_msg_with_param(
clk_mgr,
VBIOSSMC_MSG_SetDisplayIdleOptimizations,
idle_info.data);
}
void dcn31_smu_enable_pme_wa(struct clk_mgr_internal *clk_mgr)
{
if (!clk_mgr->smu_present)
return;
dcn31_smu_send_msg_with_param(
clk_mgr,
VBIOSSMC_MSG_UpdatePmeRestore,
0);
}
void dcn31_smu_set_dram_addr_high(struct clk_mgr_internal *clk_mgr, uint32_t addr_high)
{
if (!clk_mgr->smu_present)
return;
dcn31_smu_send_msg_with_param(clk_mgr,
VBIOSSMC_MSG_SetVbiosDramAddrHigh, addr_high);
}
void dcn31_smu_set_dram_addr_low(struct clk_mgr_internal *clk_mgr, uint32_t addr_low)
{
if (!clk_mgr->smu_present)
return;
dcn31_smu_send_msg_with_param(clk_mgr,
VBIOSSMC_MSG_SetVbiosDramAddrLow, addr_low);
}
void dcn31_smu_transfer_dpm_table_smu_2_dram(struct clk_mgr_internal *clk_mgr)
{
if (!clk_mgr->smu_present)
return;
dcn31_smu_send_msg_with_param(clk_mgr,
VBIOSSMC_MSG_TransferTableSmu2Dram, TABLE_DPMCLOCKS);
}
void dcn31_smu_transfer_wm_table_dram_2_smu(struct clk_mgr_internal *clk_mgr)
{
if (!clk_mgr->smu_present)
return;
dcn31_smu_send_msg_with_param(clk_mgr,
VBIOSSMC_MSG_TransferTableDram2Smu, TABLE_WATERMARKS);
}
void dcn31_smu_set_Z9_support(struct clk_mgr_internal *clk_mgr, bool support)
{
//TODO: Work with smu team to define optimization options.
unsigned int msg_id;
if (!clk_mgr->smu_present)
return;
if (support)
msg_id = VBIOSSMC_MSG_AllowZstatesEntry;
else
msg_id = VBIOSSMC_MSG_DisallowZstatesEntry;
dcn31_smu_send_msg_with_param(
clk_mgr,
msg_id,
0);
}
/* Arg = 1: Turn DTB on; 0: Turn DTB CLK OFF. when it is on, it is 600MHZ */
void dcn31_smu_set_dtbclk(struct clk_mgr_internal *clk_mgr, bool enable)
{
if (!clk_mgr->smu_present)
return;
dcn31_smu_send_msg_with_param(
clk_mgr,
VBIOSSMC_MSG_SetDtbClk,
enable);
}
/*
* Copyright 2018 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.
*
* Authors: AMD
*
*/
#ifndef DAL_DC_31_SMU_H_
#define DAL_DC_31_SMU_H_
#ifndef PMFW_DRIVER_IF_H
#define PMFW_DRIVER_IF_H
#define PMFW_DRIVER_IF_VERSION 4
typedef struct {
int32_t value;
uint32_t numFractionalBits;
} FloatInIntFormat_t;
typedef enum {
DSPCLK_DCFCLK = 0,
DSPCLK_DISPCLK,
DSPCLK_PIXCLK,
DSPCLK_PHYCLK,
DSPCLK_COUNT,
} DSPCLK_e;
typedef struct {
uint16_t Freq; // in MHz
uint16_t Vid; // min voltage in SVI3 VID
} DisplayClockTable_t;
typedef struct {
uint16_t MinClock; // This is either DCFCLK or SOCCLK (in MHz)
uint16_t MaxClock; // This is either DCFCLK or SOCCLK (in MHz)
uint16_t MinMclk;
uint16_t MaxMclk;
uint8_t WmSetting;
uint8_t WmType; // Used for normal pstate change or memory retraining
uint8_t Padding[2];
} WatermarkRowGeneric_t;
#define NUM_WM_RANGES 4
#define WM_PSTATE_CHG 0
#define WM_RETRAINING 1
typedef enum {
WM_SOCCLK = 0,
WM_DCFCLK,
WM_COUNT,
} WM_CLOCK_e;
typedef struct {
// Watermarks
WatermarkRowGeneric_t WatermarkRow[WM_COUNT][NUM_WM_RANGES];
uint32_t MmHubPadding[7]; // SMU internal use