Home | History | Annotate | Line # | Download | only in hw
      1 /*	$NetBSD: clk_mgr.h,v 1.2 2021/12/18 23:45:05 riastradh Exp $	*/
      2 
      3 /*
      4  * Copyright 2012-16 Advanced Micro Devices, Inc.
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a
      7  * copy of this software and associated documentation files (the "Software"),
      8  * to deal in the Software without restriction, including without limitation
      9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     10  * and/or sell copies of the Software, and to permit persons to whom the
     11  * Software is furnished to do so, subject to the following conditions:
     12  *
     13  * The above copyright notice and this permission notice shall be included in
     14  * all copies or substantial portions of the Software.
     15  *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     19  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
     20  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     21  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     22  * OTHER DEALINGS IN THE SOFTWARE.
     23  *
     24  * Authors: AMD
     25  *
     26  */
     27 
     28 #ifndef __DAL_CLK_MGR_H__
     29 #define __DAL_CLK_MGR_H__
     30 
     31 #include "dc.h"
     32 
     33 #define DCN_MINIMUM_DISPCLK_Khz 100000
     34 #define DCN_MINIMUM_DPPCLK_Khz 100000
     35 
     36 /* Constants */
     37 #define DDR4_DRAM_WIDTH   64
     38 #define WM_A 0
     39 #define WM_B 1
     40 #define WM_C 2
     41 #define WM_D 3
     42 #define WM_SET_COUNT 4
     43 
     44 #define DCN_MINIMUM_DISPCLK_Khz 100000
     45 #define DCN_MINIMUM_DPPCLK_Khz 100000
     46 
     47 /* Will these bw structures be ASIC specific? */
     48 
     49 #define MAX_NUM_DPM_LVL		8
     50 #define WM_SET_COUNT 		4
     51 
     52 
     53 struct clk_limit_table_entry {
     54 	unsigned int voltage; /* milivolts withh 2 fractional bits */
     55 	unsigned int dcfclk_mhz;
     56 	unsigned int fclk_mhz;
     57 	unsigned int memclk_mhz;
     58 	unsigned int socclk_mhz;
     59 };
     60 
     61 /* This table is contiguous */
     62 struct clk_limit_table {
     63 	struct clk_limit_table_entry entries[MAX_NUM_DPM_LVL];
     64 	unsigned int num_entries;
     65 };
     66 
     67 struct wm_range_table_entry {
     68 	unsigned int wm_inst;
     69 	unsigned int wm_type;
     70 	double pstate_latency_us;
     71 	double sr_exit_time_us;
     72 	double sr_enter_plus_exit_time_us;
     73 	bool valid;
     74 };
     75 
     76 
     77 struct clk_log_info {
     78 	bool enabled;
     79 	char *pBuf;
     80 	unsigned int bufSize;
     81 	unsigned int *sum_chars_printed;
     82 };
     83 
     84 struct clk_state_registers_and_bypass {
     85 	uint32_t dcfclk;
     86 	uint32_t dcf_deep_sleep_divider;
     87 	uint32_t dcf_deep_sleep_allow;
     88 	uint32_t dprefclk;
     89 	uint32_t dispclk;
     90 	uint32_t dppclk;
     91 
     92 	uint32_t dppclk_bypass;
     93 	uint32_t dcfclk_bypass;
     94 	uint32_t dprefclk_bypass;
     95 	uint32_t dispclk_bypass;
     96 };
     97 
     98 struct rv1_clk_internal {
     99 	uint32_t CLK0_CLK8_CURRENT_CNT;  //dcfclk
    100 	uint32_t CLK0_CLK8_DS_CNTL;		 //dcf_deep_sleep_divider
    101 	uint32_t CLK0_CLK8_ALLOW_DS;	 //dcf_deep_sleep_allow
    102 	uint32_t CLK0_CLK10_CURRENT_CNT; //dprefclk
    103 	uint32_t CLK0_CLK11_CURRENT_CNT; //dispclk
    104 
    105 	uint32_t CLK0_CLK8_BYPASS_CNTL;  //dcfclk bypass
    106 	uint32_t CLK0_CLK10_BYPASS_CNTL; //dprefclk bypass
    107 	uint32_t CLK0_CLK11_BYPASS_CNTL; //dispclk bypass
    108 };
    109 
    110 struct rn_clk_internal {
    111 	uint32_t CLK1_CLK0_CURRENT_CNT; //dispclk
    112 	uint32_t CLK1_CLK1_CURRENT_CNT; //dppclk
    113 	uint32_t CLK1_CLK2_CURRENT_CNT; //dprefclk
    114 	uint32_t CLK1_CLK3_CURRENT_CNT; //dcfclk
    115 	uint32_t CLK1_CLK3_DS_CNTL;		//dcf_deep_sleep_divider
    116 	uint32_t CLK1_CLK3_ALLOW_DS;	//dcf_deep_sleep_allow
    117 
    118 	uint32_t CLK1_CLK0_BYPASS_CNTL; //dispclk bypass
    119 	uint32_t CLK1_CLK1_BYPASS_CNTL; //dppclk bypass
    120 	uint32_t CLK1_CLK2_BYPASS_CNTL; //dprefclk bypass
    121 	uint32_t CLK1_CLK3_BYPASS_CNTL; //dcfclk bypass
    122 
    123 };
    124 
    125 /* For dtn logging and debugging */
    126 struct clk_state_registers {
    127 		uint32_t CLK0_CLK8_CURRENT_CNT;  //dcfclk
    128 		uint32_t CLK0_CLK8_DS_CNTL;		 //dcf_deep_sleep_divider
    129 		uint32_t CLK0_CLK8_ALLOW_DS;	 //dcf_deep_sleep_allow
    130 		uint32_t CLK0_CLK10_CURRENT_CNT; //dprefclk
    131 		uint32_t CLK0_CLK11_CURRENT_CNT; //dispclk
    132 };
    133 
    134 /* TODO: combine this with the above */
    135 struct clk_bypass {
    136 	uint32_t dcfclk_bypass;
    137 	uint32_t dispclk_pypass;
    138 	uint32_t dprefclk_bypass;
    139 };
    140 /*
    141  * This table is not contiguous, can have holes, each
    142  * entry correspond to one set of WM. For example if
    143  * we have 2 DPM and LPDDR, we will WM set A, B and
    144  * D occupied, C will be emptry.
    145  */
    146 struct wm_table {
    147 	struct wm_range_table_entry entries[WM_SET_COUNT];
    148 };
    149 
    150 struct clk_bw_params {
    151 	unsigned int vram_type;
    152 	unsigned int num_channels;
    153 	struct clk_limit_table clk_table;
    154 	struct wm_table wm_table;
    155 };
    156 /* Public interfaces */
    157 
    158 struct clk_states {
    159 	uint32_t dprefclk_khz;
    160 };
    161 
    162 struct clk_mgr_funcs {
    163 	/*
    164 	 * This function should set new clocks based on the input "safe_to_lower".
    165 	 * If safe_to_lower == false, then only clocks which are to be increased
    166 	 * should changed.
    167 	 * If safe_to_lower == true, then only clocks which are to be decreased
    168 	 * should be changed.
    169 	 */
    170 	void (*update_clocks)(struct clk_mgr *clk_mgr,
    171 			struct dc_state *context,
    172 			bool safe_to_lower);
    173 
    174 	int (*get_dp_ref_clk_frequency)(struct clk_mgr *clk_mgr);
    175 
    176 	void (*init_clocks)(struct clk_mgr *clk_mgr);
    177 
    178 	void (*enable_pme_wa) (struct clk_mgr *clk_mgr);
    179 	void (*get_clock)(struct clk_mgr *clk_mgr,
    180 			struct dc_state *context,
    181 			enum dc_clock_type clock_type,
    182 			struct dc_clock_config *clock_cfg);
    183 
    184 	bool (*are_clock_states_equal) (struct dc_clocks *a,
    185 			struct dc_clocks *b);
    186 	void (*notify_wm_ranges)(struct clk_mgr *clk_mgr);
    187 };
    188 
    189 struct clk_mgr {
    190 	struct dc_context *ctx;
    191 	struct clk_mgr_funcs *funcs;
    192 	struct dc_clocks clks;
    193 	bool psr_allow_active_cache;
    194 	int dprefclk_khz; // Used by program pixel clock in clock source funcs, need to figureout where this goes
    195 	int dentist_vco_freq_khz;
    196 	struct clk_state_registers_and_bypass boot_snapshot;
    197 	struct clk_bw_params *bw_params;
    198 };
    199 
    200 /* forward declarations */
    201 struct dccg;
    202 
    203 struct clk_mgr *dc_clk_mgr_create(struct dc_context *ctx, struct pp_smu_funcs *pp_smu, struct dccg *dccg);
    204 
    205 void dc_destroy_clk_mgr(struct clk_mgr *clk_mgr);
    206 
    207 void clk_mgr_exit_optimized_pwr_state(const struct dc *dc, struct clk_mgr *clk_mgr);
    208 
    209 void clk_mgr_optimize_pwr_state(const struct dc *dc, struct clk_mgr *clk_mgr);
    210 
    211 #endif /* __DAL_CLK_MGR_H__ */
    212