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