Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright 2012-16 Advanced Micro Devices, Inc.
0003  *
0004  * Permission is hereby granted, free of charge, to any person obtaining a
0005  * copy of this software and associated documentation files (the "Software"),
0006  * to deal in the Software without restriction, including without limitation
0007  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0008  * and/or sell copies of the Software, and to permit persons to whom the
0009  * Software is furnished to do so, subject to the following conditions:
0010  *
0011  * The above copyright notice and this permission notice shall be included in
0012  * all copies or substantial portions of the Software.
0013  *
0014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0017  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
0018  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
0019  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
0020  * OTHER DEALINGS IN THE SOFTWARE.
0021  *
0022  * Authors: AMD
0023  *
0024  */
0025 
0026 #ifndef __DAL_CLK_MGR_H__
0027 #define __DAL_CLK_MGR_H__
0028 
0029 #include "dc.h"
0030 #include "dm_pp_smu.h"
0031 
0032 #define DCN_MINIMUM_DISPCLK_Khz 100000
0033 #define DCN_MINIMUM_DPPCLK_Khz 100000
0034 
0035 /* Constants */
0036 #define DDR4_DRAM_WIDTH   64
0037 #define WM_A 0
0038 #define WM_B 1
0039 #define WM_C 2
0040 #define WM_D 3
0041 #define WM_SET_COUNT 4
0042 
0043 #define DCN_MINIMUM_DISPCLK_Khz 100000
0044 #define DCN_MINIMUM_DPPCLK_Khz 100000
0045 
0046 struct dcn3_clk_internal {
0047     int dummy;
0048     /*TODO:
0049     uint32_t CLK1_CLK0_CURRENT_CNT; //dispclk
0050     uint32_t CLK1_CLK1_CURRENT_CNT; //dppclk
0051     uint32_t CLK1_CLK2_CURRENT_CNT; //dprefclk
0052     uint32_t CLK1_CLK3_CURRENT_CNT; //dcfclk
0053     uint32_t CLK1_CLK3_DS_CNTL; //dcf_deep_sleep_divider
0054     uint32_t CLK1_CLK3_ALLOW_DS;    //dcf_deep_sleep_allow
0055 
0056     uint32_t CLK1_CLK0_BYPASS_CNTL; //dispclk bypass
0057     uint32_t CLK1_CLK1_BYPASS_CNTL; //dppclk bypass
0058     uint32_t CLK1_CLK2_BYPASS_CNTL; //dprefclk bypass
0059     uint32_t CLK1_CLK3_BYPASS_CNTL; //dcfclk bypass
0060     */
0061 };
0062 
0063 struct dcn301_clk_internal {
0064     int dummy;
0065     uint32_t CLK1_CLK0_CURRENT_CNT; //dispclk
0066     uint32_t CLK1_CLK1_CURRENT_CNT; //dppclk
0067     uint32_t CLK1_CLK2_CURRENT_CNT; //dprefclk
0068     uint32_t CLK1_CLK3_CURRENT_CNT; //dcfclk
0069     uint32_t CLK1_CLK3_DS_CNTL; //dcf_deep_sleep_divider
0070     uint32_t CLK1_CLK3_ALLOW_DS;    //dcf_deep_sleep_allow
0071 
0072     uint32_t CLK1_CLK0_BYPASS_CNTL; //dispclk bypass
0073     uint32_t CLK1_CLK1_BYPASS_CNTL; //dppclk bypass
0074     uint32_t CLK1_CLK2_BYPASS_CNTL; //dprefclk bypass
0075     uint32_t CLK1_CLK3_BYPASS_CNTL; //dcfclk bypass
0076 };
0077 
0078 /* Will these bw structures be ASIC specific? */
0079 
0080 #define MAX_NUM_DPM_LVL     8
0081 #define WM_SET_COUNT        4
0082 
0083 
0084 struct clk_limit_table_entry {
0085     unsigned int voltage; /* milivolts withh 2 fractional bits */
0086     unsigned int dcfclk_mhz;
0087     unsigned int fclk_mhz;
0088     unsigned int memclk_mhz;
0089     unsigned int socclk_mhz;
0090     unsigned int dtbclk_mhz;
0091     unsigned int dispclk_mhz;
0092     unsigned int dppclk_mhz;
0093     unsigned int phyclk_mhz;
0094     unsigned int phyclk_d18_mhz;
0095     unsigned int wck_ratio;
0096 };
0097 
0098 /* This table is contiguous */
0099 struct clk_limit_table {
0100     struct clk_limit_table_entry entries[MAX_NUM_DPM_LVL];
0101     unsigned int num_entries;
0102 };
0103 
0104 struct wm_range_table_entry {
0105     unsigned int wm_inst;
0106     unsigned int wm_type;
0107     double pstate_latency_us;
0108     double sr_exit_time_us;
0109     double sr_enter_plus_exit_time_us;
0110     bool valid;
0111 };
0112 
0113 struct nv_wm_range_entry {
0114     bool valid;
0115 
0116     struct {
0117         uint8_t wm_type;
0118         uint16_t min_dcfclk;
0119         uint16_t max_dcfclk;
0120         uint16_t min_uclk;
0121         uint16_t max_uclk;
0122     } pmfw_breakdown;
0123 
0124     struct {
0125         double pstate_latency_us;
0126         double sr_exit_time_us;
0127         double sr_enter_plus_exit_time_us;
0128         double fclk_change_latency_us;
0129     } dml_input;
0130 };
0131 
0132 struct clk_log_info {
0133     bool enabled;
0134     char *pBuf;
0135     unsigned int bufSize;
0136     unsigned int *sum_chars_printed;
0137 };
0138 
0139 struct clk_state_registers_and_bypass {
0140     uint32_t dcfclk;
0141     uint32_t dcf_deep_sleep_divider;
0142     uint32_t dcf_deep_sleep_allow;
0143     uint32_t dprefclk;
0144     uint32_t dispclk;
0145     uint32_t dppclk;
0146     uint32_t dtbclk;
0147 
0148     uint32_t dppclk_bypass;
0149     uint32_t dcfclk_bypass;
0150     uint32_t dprefclk_bypass;
0151     uint32_t dispclk_bypass;
0152 };
0153 
0154 struct rv1_clk_internal {
0155     uint32_t CLK0_CLK8_CURRENT_CNT;  //dcfclk
0156     uint32_t CLK0_CLK8_DS_CNTL;      //dcf_deep_sleep_divider
0157     uint32_t CLK0_CLK8_ALLOW_DS;     //dcf_deep_sleep_allow
0158     uint32_t CLK0_CLK10_CURRENT_CNT; //dprefclk
0159     uint32_t CLK0_CLK11_CURRENT_CNT; //dispclk
0160 
0161     uint32_t CLK0_CLK8_BYPASS_CNTL;  //dcfclk bypass
0162     uint32_t CLK0_CLK10_BYPASS_CNTL; //dprefclk bypass
0163     uint32_t CLK0_CLK11_BYPASS_CNTL; //dispclk bypass
0164 };
0165 
0166 struct rn_clk_internal {
0167     uint32_t CLK1_CLK0_CURRENT_CNT; //dispclk
0168     uint32_t CLK1_CLK1_CURRENT_CNT; //dppclk
0169     uint32_t CLK1_CLK2_CURRENT_CNT; //dprefclk
0170     uint32_t CLK1_CLK3_CURRENT_CNT; //dcfclk
0171     uint32_t CLK1_CLK3_DS_CNTL;     //dcf_deep_sleep_divider
0172     uint32_t CLK1_CLK3_ALLOW_DS;    //dcf_deep_sleep_allow
0173 
0174     uint32_t CLK1_CLK0_BYPASS_CNTL; //dispclk bypass
0175     uint32_t CLK1_CLK1_BYPASS_CNTL; //dppclk bypass
0176     uint32_t CLK1_CLK2_BYPASS_CNTL; //dprefclk bypass
0177     uint32_t CLK1_CLK3_BYPASS_CNTL; //dcfclk bypass
0178 
0179 };
0180 
0181 /* For dtn logging and debugging */
0182 struct clk_state_registers {
0183         uint32_t CLK0_CLK8_CURRENT_CNT;  //dcfclk
0184         uint32_t CLK0_CLK8_DS_CNTL;      //dcf_deep_sleep_divider
0185         uint32_t CLK0_CLK8_ALLOW_DS;     //dcf_deep_sleep_allow
0186         uint32_t CLK0_CLK10_CURRENT_CNT; //dprefclk
0187         uint32_t CLK0_CLK11_CURRENT_CNT; //dispclk
0188 };
0189 
0190 /* TODO: combine this with the above */
0191 struct clk_bypass {
0192     uint32_t dcfclk_bypass;
0193     uint32_t dispclk_pypass;
0194     uint32_t dprefclk_bypass;
0195 };
0196 /*
0197  * This table is not contiguous, can have holes, each
0198  * entry correspond to one set of WM. For example if
0199  * we have 2 DPM and LPDDR, we will WM set A, B and
0200  * D occupied, C will be emptry.
0201  */
0202 struct wm_table {
0203     union {
0204         struct nv_wm_range_entry nv_entries[WM_SET_COUNT];
0205         struct wm_range_table_entry entries[WM_SET_COUNT];
0206     };
0207 };
0208 
0209 struct dummy_pstate_entry {
0210     unsigned int dram_speed_mts;
0211     double dummy_pstate_latency_us;
0212 };
0213 
0214 struct clk_bw_params {
0215     unsigned int vram_type;
0216     unsigned int num_channels;
0217     unsigned int dram_channel_width_bytes;
0218     unsigned int dispclk_vco_khz;
0219     unsigned int dc_mode_softmax_memclk;
0220     struct clk_limit_table clk_table;
0221     struct wm_table wm_table;
0222     struct dummy_pstate_entry dummy_pstate_table[4];
0223 };
0224 /* Public interfaces */
0225 
0226 struct clk_states {
0227     uint32_t dprefclk_khz;
0228 };
0229 
0230 struct clk_mgr_funcs {
0231     /*
0232      * This function should set new clocks based on the input "safe_to_lower".
0233      * If safe_to_lower == false, then only clocks which are to be increased
0234      * should changed.
0235      * If safe_to_lower == true, then only clocks which are to be decreased
0236      * should be changed.
0237      */
0238     void (*update_clocks)(struct clk_mgr *clk_mgr,
0239             struct dc_state *context,
0240             bool safe_to_lower);
0241 
0242     int (*get_dp_ref_clk_frequency)(struct clk_mgr *clk_mgr);
0243     int (*get_dtb_ref_clk_frequency)(struct clk_mgr *clk_mgr);
0244 
0245     void (*set_low_power_state)(struct clk_mgr *clk_mgr);
0246 
0247     void (*init_clocks)(struct clk_mgr *clk_mgr);
0248 
0249     void (*dump_clk_registers)(struct clk_state_registers_and_bypass *regs_and_bypass,
0250             struct clk_mgr *clk_mgr_base, struct clk_log_info *log_info);
0251 
0252     void (*enable_pme_wa) (struct clk_mgr *clk_mgr);
0253     void (*get_clock)(struct clk_mgr *clk_mgr,
0254             struct dc_state *context,
0255             enum dc_clock_type clock_type,
0256             struct dc_clock_config *clock_cfg);
0257 
0258     bool (*are_clock_states_equal) (struct dc_clocks *a,
0259             struct dc_clocks *b);
0260     void (*notify_wm_ranges)(struct clk_mgr *clk_mgr);
0261 
0262     /* Notify clk_mgr of a change in link rate, update phyclk frequency if necessary */
0263     void (*notify_link_rate_change)(struct clk_mgr *clk_mgr, struct dc_link *link);
0264     /*
0265      * Send message to PMFW to set hard min memclk frequency
0266      * When current_mode = false, set DPM0
0267      * When current_mode = true, set required clock for current mode
0268      */
0269     void (*set_hard_min_memclk)(struct clk_mgr *clk_mgr, bool current_mode);
0270 
0271     /* Send message to PMFW to set hard max memclk frequency to highest DPM */
0272     void (*set_hard_max_memclk)(struct clk_mgr *clk_mgr);
0273 
0274     /* Custom set a memclk freq range*/
0275     void (*set_max_memclk)(struct clk_mgr *clk_mgr, unsigned int memclk_mhz);
0276     void (*set_min_memclk)(struct clk_mgr *clk_mgr, unsigned int memclk_mhz);
0277 
0278     /* Get current memclk states from PMFW, update relevant structures */
0279     void (*get_memclk_states_from_smu)(struct clk_mgr *clk_mgr);
0280 
0281     /* Get SMU present */
0282     bool (*is_smu_present)(struct clk_mgr *clk_mgr);
0283 };
0284 
0285 struct clk_mgr {
0286     struct dc_context *ctx;
0287     struct clk_mgr_funcs *funcs;
0288     struct dc_clocks clks;
0289     bool psr_allow_active_cache;
0290     bool force_smu_not_present;
0291     bool dc_mode_softmax_enabled;
0292     int dprefclk_khz; // Used by program pixel clock in clock source funcs, need to figureout where this goes
0293     int dentist_vco_freq_khz;
0294     struct clk_state_registers_and_bypass boot_snapshot;
0295     struct clk_bw_params *bw_params;
0296     struct pp_smu_wm_range_sets ranges;
0297 };
0298 
0299 /* forward declarations */
0300 struct dccg;
0301 
0302 struct clk_mgr *dc_clk_mgr_create(struct dc_context *ctx, struct pp_smu_funcs *pp_smu, struct dccg *dccg);
0303 
0304 void dc_destroy_clk_mgr(struct clk_mgr *clk_mgr);
0305 
0306 void clk_mgr_exit_optimized_pwr_state(const struct dc *dc, struct clk_mgr *clk_mgr);
0307 
0308 void clk_mgr_optimize_pwr_state(const struct dc *dc, struct clk_mgr *clk_mgr);
0309 
0310 #endif /* __DAL_CLK_MGR_H__ */