Commit 4edb6fc9 authored by Bhawanpreet Lakha's avatar Bhawanpreet Lakha Committed by Alex Deucher

drm/amd/display: Add Renoir clock manager

Controls display clocks and interfaces with powerplay for
clock and power requirements.
Acked-by: default avatarHarry Wentland <harry.wentland@amd.com>
Signed-off-by: default avatarBhawanpreet Lakha <Bhawanpreet.Lakha@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 6f451b60
...@@ -85,3 +85,13 @@ AMD_DAL_CLK_MGR_DCN20 = $(addprefix $(AMDDALPATH)/dc/clk_mgr/dcn20/,$(CLK_MGR_DC ...@@ -85,3 +85,13 @@ AMD_DAL_CLK_MGR_DCN20 = $(addprefix $(AMDDALPATH)/dc/clk_mgr/dcn20/,$(CLK_MGR_DC
AMD_DISPLAY_FILES += $(AMD_DAL_CLK_MGR_DCN20) AMD_DISPLAY_FILES += $(AMD_DAL_CLK_MGR_DCN20)
endif endif
ifdef CONFIG_DRM_AMD_DC_DCN2_1
###############################################################################
# DCN21
###############################################################################
CLK_MGR_DCN21 = rn_clk_mgr.o rn_clk_mgr_vbios_smu.o
AMD_DAL_CLK_MGR_DCN21 = $(addprefix $(AMDDALPATH)/dc/clk_mgr/dcn21/,$(CLK_MGR_DCN21))
AMD_DISPLAY_FILES += $(AMD_DAL_CLK_MGR_DCN21)
endif
...@@ -37,6 +37,9 @@ ...@@ -37,6 +37,9 @@
#include "dcn10/rv1_clk_mgr.h" #include "dcn10/rv1_clk_mgr.h"
#include "dcn10/rv2_clk_mgr.h" #include "dcn10/rv2_clk_mgr.h"
#include "dcn20/dcn20_clk_mgr.h" #include "dcn20/dcn20_clk_mgr.h"
#if defined(CONFIG_DRM_AMD_DC_DCN2_1)
#include "dcn21/rn_clk_mgr.h"
#endif
int clk_mgr_helper_get_active_display_cnt( int clk_mgr_helper_get_active_display_cnt(
...@@ -117,6 +120,12 @@ struct clk_mgr *dc_clk_mgr_create(struct dc_context *ctx, struct pp_smu_funcs *p ...@@ -117,6 +120,12 @@ struct clk_mgr *dc_clk_mgr_create(struct dc_context *ctx, struct pp_smu_funcs *p
rv1_clk_mgr_construct(ctx, clk_mgr, pp_smu); rv1_clk_mgr_construct(ctx, clk_mgr, pp_smu);
break; break;
} }
#if defined(CONFIG_DRM_AMD_DC_DCN2_1)
if (ASICREV_IS_RENOIR(asic_id.hw_internal_rev)) {
rn_clk_mgr_construct(ctx, clk_mgr, pp_smu, dccg);
break;
}
#endif /* DCN2_1 */
break; break;
#endif /* Family RV */ #endif /* Family RV */
......
This diff is collapsed.
/*
* 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 __RN_CLK_MGR_H__
#define __RN_CLK_MGR_H__
struct rn_clk_registers {
uint32_t CLK1_CLK0_CURRENT_CNT; /* DPREFCLK */
};
void rn_clk_mgr_construct(struct dc_context *ctx,
struct clk_mgr_internal *clk_mgr,
struct pp_smu_funcs *pp_smu,
struct dccg *dccg);
#endif //__RN_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 "core_types.h"
#include "clk_mgr_internal.h"
#include "reg_helper.h"
#include "renoir_ip_offset.h"
#include "mp/mp_12_0_0_offset.h"
#include "mp/mp_12_0_0_sh_mask.h"
#define REG(reg_name) \
(MP1_BASE.instance[0].segment[mm ## reg_name ## _BASE_IDX] + mm ## 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
#define VBIOSSMC_MSG_PowerDownGfx 0x6
#define VBIOSSMC_MSG_SetDppclkFreq 0x7
#define VBIOSSMC_MSG_SetHardMinDcfclkByFreq 0x8
#define VBIOSSMC_MSG_SetMinDeepSleepDcfclk 0x9
#define VBIOSSMC_MSG_SetPhyclkVoltageByFreq 0xA
#define VBIOSSMC_MSG_GetFclkFrequency 0xB
#define VBIOSSMC_MSG_SetDisplayCount 0xC
#define VBIOSSMC_MSG_EnableTmdp48MHzRefclkPwrDown 0xD
#define VBIOSSMC_MSG_UpdatePmeRestore 0xE
int rn_vbios_smu_send_msg_with_param(struct clk_mgr_internal *clk_mgr, unsigned int msg_id, unsigned int param)
{
/* First clear response register */
REG_WRITE(MP1_SMN_C2PMSG_91, 0);
/* 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);
REG_WAIT(MP1_SMN_C2PMSG_91, CONTENT, 1, 10, 200000);
/* Actual dispclk set is returned in the parameter register */
return REG_READ(MP1_SMN_C2PMSG_83);
}
int rn_vbios_smu_get_smu_version(struct clk_mgr_internal *clk_mgr)
{
return rn_vbios_smu_send_msg_with_param(
clk_mgr,
VBIOSSMC_MSG_GetSmuVersion,
0);
}
int rn_vbios_smu_set_dispclk(struct clk_mgr_internal *clk_mgr, int requested_dispclk_khz)
{
int actual_dispclk_set_mhz = -1;
struct dc *core_dc = clk_mgr->base.ctx->dc;
struct dmcu *dmcu = core_dc->res_pool->dmcu;
uint32_t clk = requested_dispclk_khz / 1000;
if (clk <= 100)
clk = 101;
/* Unit of SMU msg parameter is Mhz */
actual_dispclk_set_mhz = rn_vbios_smu_send_msg_with_param(
clk_mgr,
VBIOSSMC_MSG_SetDispclkFreq,
clk);
if (!IS_FPGA_MAXIMUS_DC(core_dc->ctx->dce_environment)) {
if (dmcu && dmcu->funcs->is_dmcu_initialized(dmcu)) {
if (clk_mgr->dfs_bypass_disp_clk != actual_dispclk_set_mhz)
dmcu->funcs->set_psr_wait_loop(dmcu,
actual_dispclk_set_mhz / 7);
}
}
return actual_dispclk_set_mhz * 1000;
}
int rn_vbios_smu_set_dprefclk(struct clk_mgr_internal *clk_mgr)
{
int actual_dprefclk_set_mhz = -1;
actual_dprefclk_set_mhz = rn_vbios_smu_send_msg_with_param(
clk_mgr,
VBIOSSMC_MSG_SetDprefclkFreq,
clk_mgr->base.dprefclk_khz / 1000);
/* TODO: add code for programing DP DTO, currently this is down by command table */
return actual_dprefclk_set_mhz * 1000;
}
int rn_vbios_smu_set_hard_min_dcfclk(struct clk_mgr_internal *clk_mgr, int requested_dcfclk_khz)
{
int actual_dcfclk_set_mhz = -1;
if (clk_mgr->smu_ver < 0xFFFFFFFF)
return actual_dcfclk_set_mhz;
actual_dcfclk_set_mhz = rn_vbios_smu_send_msg_with_param(
clk_mgr,
VBIOSSMC_MSG_SetHardMinDcfclkByFreq,
requested_dcfclk_khz / 1000);
return actual_dcfclk_set_mhz * 1000;
}
int rn_vbios_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->smu_ver < 0xFFFFFFFF)
return actual_min_ds_dcfclk_mhz;
actual_min_ds_dcfclk_mhz = rn_vbios_smu_send_msg_with_param(
clk_mgr,
VBIOSSMC_MSG_SetMinDeepSleepDcfclk,
requested_min_ds_dcfclk_khz / 1000);
return actual_min_ds_dcfclk_mhz * 1000;
}
void rn_vbios_smu_set_phyclk(struct clk_mgr_internal *clk_mgr, int requested_phyclk_khz)
{
rn_vbios_smu_send_msg_with_param(
clk_mgr,
VBIOSSMC_MSG_SetPhyclkVoltageByFreq,
requested_phyclk_khz / 1000);
}
int rn_vbios_smu_set_dppclk(struct clk_mgr_internal *clk_mgr, int requested_dpp_khz)
{
int actual_dppclk_set_mhz = -1;
uint32_t clk = requested_dpp_khz / 1000;
if (clk <= 100)
clk = 101;
actual_dppclk_set_mhz = rn_vbios_smu_send_msg_with_param(
clk_mgr,
VBIOSSMC_MSG_SetDppclkFreq,
clk);
return actual_dppclk_set_mhz * 1000;
}
void rn_vbios_smu_set_display_count(struct clk_mgr_internal *clk_mgr, int display_count)
{
rn_vbios_smu_send_msg_with_param(
clk_mgr,
VBIOSSMC_MSG_SetDisplayCount,
display_count);
}
void rn_vbios_smu_enable_48mhz_tmdp_refclk_pwrdwn(struct clk_mgr_internal *clk_mgr)
{
rn_vbios_smu_send_msg_with_param(
clk_mgr,
VBIOSSMC_MSG_EnableTmdp48MHzRefclkPwrDown,
0);
}
void rn_vbios_smu_enable_pme_wa(struct clk_mgr_internal *clk_mgr)
{
rn_vbios_smu_send_msg_with_param(
clk_mgr,
VBIOSSMC_MSG_UpdatePmeRestore,
0);
}
/*
* 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_RN_CLK_MGR_VBIOS_SMU_H_
#define DAL_DC_RN_CLK_MGR_VBIOS_SMU_H_
int rn_vbios_smu_get_smu_version(struct clk_mgr_internal *clk_mgr);
int rn_vbios_smu_set_dispclk(struct clk_mgr_internal *clk_mgr, int requested_dispclk_khz);
int rn_vbios_smu_set_dprefclk(struct clk_mgr_internal *clk_mgr);
int rn_vbios_smu_set_hard_min_dcfclk(struct clk_mgr_internal *clk_mgr, int requested_dcfclk_khz);
int rn_vbios_smu_set_min_deep_sleep_dcfclk(struct clk_mgr_internal *clk_mgr, int requested_min_ds_dcfclk_khz);
void rn_vbios_smu_set_phyclk(struct clk_mgr_internal *clk_mgr, int requested_phyclk_khz);
int rn_vbios_smu_set_dppclk(struct clk_mgr_internal *clk_mgr, int requested_dpp_khz);
void rn_vbios_smu_set_display_count(struct clk_mgr_internal *clk_mgr, int display_count);
void rn_vbios_smu_enable_48mhz_tmdp_refclk_pwrdwn(struct clk_mgr_internal *clk_mgr);
void rn_vbios_smu_enable_pme_wa(struct clk_mgr_internal *clk_mgr);
#endif /* DAL_DC_DCN10_RV1_CLK_MGR_VBIOS_SMU_H_ */
...@@ -31,6 +31,128 @@ ...@@ -31,6 +31,128 @@
#define DCN_MINIMUM_DISPCLK_Khz 100000 #define DCN_MINIMUM_DISPCLK_Khz 100000
#define DCN_MINIMUM_DPPCLK_Khz 100000 #define DCN_MINIMUM_DPPCLK_Khz 100000
#ifdef CONFIG_DRM_AMD_DC_DCN2_1
/* Constants */
#define DDR4_DRAM_WIDTH 64
#define WM_A 0
#define WM_B 1
#define WM_C 2
#define WM_D 3
#define WM_SET_COUNT 4
#endif
#define DCN_MINIMUM_DISPCLK_Khz 100000
#define DCN_MINIMUM_DPPCLK_Khz 100000
#ifdef CONFIG_DRM_AMD_DC_DCN2_1
/* Will these bw structures be ASIC specific? */
#define MAX_NUM_DPM_LVL 4
#define WM_SET_COUNT 4
struct clk_limit_table_entry {
unsigned int voltage; /* milivolts withh 2 fractional bits */
unsigned int dcfclk_mhz;
unsigned int fclk_mhz;
unsigned int memclk_mhz;
unsigned int socclk_mhz;
};
/* This table is contiguous */
struct clk_limit_table {
struct clk_limit_table_entry entries[MAX_NUM_DPM_LVL];
unsigned int num_entries;
};
struct wm_range_table_entry {
unsigned int wm_inst;
unsigned int wm_type;
double pstate_latency_us;
bool valid;
};
struct clk_log_info {
bool enabled;
char *pBuf;
unsigned int bufSize;
unsigned int *sum_chars_printed;
};
struct clk_state_registers_and_bypass {
uint32_t dcfclk;
uint32_t dcf_deep_sleep_divider;
uint32_t dcf_deep_sleep_allow;
uint32_t dprefclk;
uint32_t dispclk;
uint32_t dppclk;
uint32_t dppclk_bypass;
uint32_t dcfclk_bypass;
uint32_t dprefclk_bypass;
uint32_t dispclk_bypass;
};
struct rv1_clk_internal {
uint32_t CLK0_CLK8_CURRENT_CNT; //dcfclk
uint32_t CLK0_CLK8_DS_CNTL; //dcf_deep_sleep_divider
uint32_t CLK0_CLK8_ALLOW_DS; //dcf_deep_sleep_allow
uint32_t CLK0_CLK10_CURRENT_CNT; //dprefclk
uint32_t CLK0_CLK11_CURRENT_CNT; //dispclk
uint32_t CLK0_CLK8_BYPASS_CNTL; //dcfclk bypass
uint32_t CLK0_CLK10_BYPASS_CNTL; //dprefclk bypass
uint32_t CLK0_CLK11_BYPASS_CNTL; //dispclk bypass
};
struct rn_clk_internal {
uint32_t CLK1_CLK0_CURRENT_CNT; //dispclk
uint32_t CLK1_CLK1_CURRENT_CNT; //dppclk
uint32_t CLK1_CLK2_CURRENT_CNT; //dprefclk
uint32_t CLK1_CLK3_CURRENT_CNT; //dcfclk
uint32_t CLK1_CLK3_DS_CNTL; //dcf_deep_sleep_divider
uint32_t CLK1_CLK3_ALLOW_DS; //dcf_deep_sleep_allow
uint32_t CLK1_CLK0_BYPASS_CNTL; //dispclk bypass
uint32_t CLK1_CLK1_BYPASS_CNTL; //dppclk bypass
uint32_t CLK1_CLK2_BYPASS_CNTL; //dprefclk bypass
uint32_t CLK1_CLK3_BYPASS_CNTL; //dcfclk bypass
};
/* For dtn logging and debugging */
struct clk_state_registers {
uint32_t CLK0_CLK8_CURRENT_CNT; //dcfclk
uint32_t CLK0_CLK8_DS_CNTL; //dcf_deep_sleep_divider
uint32_t CLK0_CLK8_ALLOW_DS; //dcf_deep_sleep_allow
uint32_t CLK0_CLK10_CURRENT_CNT; //dprefclk
uint32_t CLK0_CLK11_CURRENT_CNT; //dispclk
};
/* TODO: combine this with the above */
struct clk_bypass {
uint32_t dcfclk_bypass;
uint32_t dispclk_pypass;
uint32_t dprefclk_bypass;
};
/*
* This table is not contiguous, can have holes, each
* entry correspond to one set of WM. For example if
* we have 2 DPM and LPDDR, we will WM set A, B and
* D occupied, C will be emptry.
*/
struct wm_table {
struct wm_range_table_entry entries[WM_SET_COUNT];
};
struct clk_bw_params {
unsigned int vram_type;
unsigned int num_channels;
struct clk_limit_table clk_table;
struct wm_table wm_table;
};
#endif
/* Public interfaces */ /* Public interfaces */
struct clk_states { struct clk_states {
...@@ -65,6 +187,9 @@ struct clk_mgr { ...@@ -65,6 +187,9 @@ struct clk_mgr {
struct clk_mgr_funcs *funcs; struct clk_mgr_funcs *funcs;
struct dc_clocks clks; struct dc_clocks clks;
int dprefclk_khz; // Used by program pixel clock in clock source funcs, need to figureout where this goes int dprefclk_khz; // Used by program pixel clock in clock source funcs, need to figureout where this goes
#ifdef CONFIG_DRM_AMD_DC_DCN2_1
struct clk_bw_params *bw_params;
#endif
}; };
/* forward declarations */ /* forward declarations */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment