1 /* 2 * Copyright 2017 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 DM_PP_SMU_IF__H 27 #define DM_PP_SMU_IF__H 28 29 /* 30 * interface to PPLIB/SMU to setup clocks and pstate requirements on SoC 31 */ 32 33 typedef bool BOOLEAN; 34 35 enum pp_smu_ver { 36 /* 37 * PP_SMU_INTERFACE_X should be interpreted as the interface defined 38 * starting from X, where X is some family of ASICs. This is as 39 * opposed to interfaces used only for X. There will be some degree 40 * of interface sharing between families of ASIcs. 41 */ 42 PP_SMU_UNSUPPORTED, 43 PP_SMU_VER_RV, 44 PP_SMU_VER_NV, 45 PP_SMU_VER_RN, 46 47 PP_SMU_VER_MAX 48 }; 49 50 struct pp_smu { 51 enum pp_smu_ver ver; 52 const void *pp; 53 54 /* 55 * interim extra handle for backwards compatibility 56 * as some existing functionality not yet implemented 57 * by ppsmu 58 */ 59 const void *dm; 60 }; 61 62 enum pp_smu_status { 63 PP_SMU_RESULT_UNDEFINED = 0, 64 PP_SMU_RESULT_OK = 1, 65 PP_SMU_RESULT_FAIL, 66 PP_SMU_RESULT_UNSUPPORTED 67 }; 68 69 #define PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN 0x0 70 #define PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX 0xFFFF 71 72 enum wm_type { 73 WM_TYPE_PSTATE_CHG = 0, 74 WM_TYPE_RETRAINING = 1, 75 }; 76 77 /* This structure is a copy of WatermarkRowGeneric_t defined by smuxx_driver_if.h*/ 78 struct pp_smu_wm_set_range { 79 uint16_t min_fill_clk_mhz; 80 uint16_t max_fill_clk_mhz; 81 uint16_t min_drain_clk_mhz; 82 uint16_t max_drain_clk_mhz; 83 84 uint8_t wm_inst; 85 uint8_t wm_type; 86 }; 87 88 #define MAX_WATERMARK_SETS 4 89 90 struct pp_smu_wm_range_sets { 91 unsigned int num_reader_wm_sets; 92 struct pp_smu_wm_set_range reader_wm_sets[MAX_WATERMARK_SETS]; 93 94 unsigned int num_writer_wm_sets; 95 struct pp_smu_wm_set_range writer_wm_sets[MAX_WATERMARK_SETS]; 96 }; 97 98 struct pp_smu_funcs_rv { 99 struct pp_smu pp_smu; 100 101 /* PPSMC_MSG_SetDisplayCount 102 * 0 triggers S0i2 optimization 103 */ 104 105 void (*set_display_count)(struct pp_smu *pp, int count); 106 107 /* reader and writer WM's are sent together as part of one table*/ 108 /* 109 * PPSMC_MSG_SetDriverDramAddrHigh 110 * PPSMC_MSG_SetDriverDramAddrLow 111 * PPSMC_MSG_TransferTableDram2Smu 112 * 113 * */ 114 void (*set_wm_ranges)(struct pp_smu *pp, 115 struct pp_smu_wm_range_sets *ranges); 116 117 /* PPSMC_MSG_SetHardMinDcfclkByFreq 118 * fixed clock at requested freq, either from FCH bypass or DFS 119 */ 120 void (*set_hard_min_dcfclk_by_freq)(struct pp_smu *pp, int mhz); 121 122 /* PPSMC_MSG_SetMinDeepSleepDcfclk 123 * when DF is in cstate, dcf clock is further divided down 124 * to just above given frequency 125 */ 126 void (*set_min_deep_sleep_dcfclk)(struct pp_smu *pp, int mhz); 127 128 /* PPSMC_MSG_SetHardMinFclkByFreq 129 * FCLK will vary with DPM, but never below requested hard min 130 */ 131 void (*set_hard_min_fclk_by_freq)(struct pp_smu *pp, int mhz); 132 133 /* PPSMC_MSG_SetHardMinSocclkByFreq 134 * Needed for DWB support 135 */ 136 void (*set_hard_min_socclk_by_freq)(struct pp_smu *pp, int mhz); 137 138 /* PME w/a */ 139 void (*set_pme_wa_enable)(struct pp_smu *pp); 140 }; 141 142 /* Used by pp_smu_funcs_nv.set_voltage_by_freq 143 * 144 */ 145 enum pp_smu_nv_clock_id { 146 PP_SMU_NV_DISPCLK, 147 PP_SMU_NV_PHYCLK, 148 PP_SMU_NV_PIXELCLK 149 }; 150 151 /* 152 * Used by pp_smu_funcs_nv.get_maximum_sustainable_clocks 153 */ 154 struct pp_smu_nv_clock_table { 155 // voltage managed SMU, freq set by driver 156 unsigned int displayClockInKhz; 157 unsigned int dppClockInKhz; 158 unsigned int phyClockInKhz; 159 unsigned int pixelClockInKhz; 160 unsigned int dscClockInKhz; 161 162 // freq/voltage managed by SMU 163 unsigned int fabricClockInKhz; 164 unsigned int socClockInKhz; 165 unsigned int dcfClockInKhz; 166 unsigned int uClockInKhz; 167 }; 168 169 struct pp_smu_funcs_nv { 170 struct pp_smu pp_smu; 171 172 /* PPSMC_MSG_SetDisplayCount 173 * 0 triggers S0i2 optimization 174 */ 175 enum pp_smu_status (*set_display_count)(struct pp_smu *pp, int count); 176 177 /* PPSMC_MSG_SetHardMinDcfclkByFreq 178 * fixed clock at requested freq, either from FCH bypass or DFS 179 */ 180 enum pp_smu_status (*set_hard_min_dcfclk_by_freq)(struct pp_smu *pp, int Mhz); 181 182 /* PPSMC_MSG_SetMinDeepSleepDcfclk 183 * when DF is in cstate, dcf clock is further divided down 184 * to just above given frequency 185 */ 186 enum pp_smu_status (*set_min_deep_sleep_dcfclk)(struct pp_smu *pp, int Mhz); 187 188 /* PPSMC_MSG_SetHardMinUclkByFreq 189 * UCLK will vary with DPM, but never below requested hard min 190 */ 191 enum pp_smu_status (*set_hard_min_uclk_by_freq)(struct pp_smu *pp, int Mhz); 192 193 /* PPSMC_MSG_SetHardMinSocclkByFreq 194 * Needed for DWB support 195 */ 196 enum pp_smu_status (*set_hard_min_socclk_by_freq)(struct pp_smu *pp, int Mhz); 197 198 /* PME w/a */ 199 enum pp_smu_status (*set_pme_wa_enable)(struct pp_smu *pp); 200 201 /* PPSMC_MSG_SetHardMinByFreq 202 * Needed to set ASIC voltages for clocks programmed by DAL 203 */ 204 enum pp_smu_status (*set_voltage_by_freq)(struct pp_smu *pp, 205 enum pp_smu_nv_clock_id clock_id, int Mhz); 206 207 /* reader and writer WM's are sent together as part of one table*/ 208 /* 209 * PPSMC_MSG_SetDriverDramAddrHigh 210 * PPSMC_MSG_SetDriverDramAddrLow 211 * PPSMC_MSG_TransferTableDram2Smu 212 * 213 * on DCN20: 214 * reader fill clk = uclk 215 * reader drain clk = dcfclk 216 * writer fill clk = socclk 217 * writer drain clk = uclk 218 * */ 219 enum pp_smu_status (*set_wm_ranges)(struct pp_smu *pp, 220 struct pp_smu_wm_range_sets *ranges); 221 222 /* Not a single SMU message. This call should return maximum sustainable limit for all 223 * clocks that DC depends on. These will be used as basis for mode enumeration. 224 */ 225 enum pp_smu_status (*get_maximum_sustainable_clocks)(struct pp_smu *pp, 226 struct pp_smu_nv_clock_table *max_clocks); 227 228 /* This call should return the discrete uclk DPM states available 229 */ 230 enum pp_smu_status (*get_uclk_dpm_states)(struct pp_smu *pp, 231 unsigned int *clock_values_in_khz, unsigned int *num_states); 232 233 /* Not a single SMU message. This call informs PPLIB that display will not be able 234 * to perform pstate handshaking in its current state. Typically this handshake 235 * is used to perform uCLK switching, so disabling pstate disables uCLK switching. 236 * 237 * Note that when setting handshake to unsupported, the call is pre-emptive. That means 238 * DC will make the call BEFORE setting up the display state which would cause pstate 239 * request to go un-acked. Only when the call completes should such a state be applied to 240 * DC hardware 241 */ 242 enum pp_smu_status (*set_pstate_handshake_support)(struct pp_smu *pp, 243 BOOLEAN pstate_handshake_supported); 244 }; 245 246 #define PP_SMU_NUM_SOCCLK_DPM_LEVELS 8 247 #define PP_SMU_NUM_DCFCLK_DPM_LEVELS 8 248 #define PP_SMU_NUM_FCLK_DPM_LEVELS 4 249 #define PP_SMU_NUM_MEMCLK_DPM_LEVELS 4 250 251 struct dpm_clock { 252 uint32_t Freq; // In MHz 253 uint32_t Vol; // Millivolts with 2 fractional bits 254 }; 255 256 257 /* this is a copy of the structure defined in smuxx_driver_if.h*/ 258 struct dpm_clocks { 259 struct dpm_clock DcfClocks[PP_SMU_NUM_DCFCLK_DPM_LEVELS]; 260 struct dpm_clock SocClocks[PP_SMU_NUM_SOCCLK_DPM_LEVELS]; 261 struct dpm_clock FClocks[PP_SMU_NUM_FCLK_DPM_LEVELS]; 262 struct dpm_clock MemClocks[PP_SMU_NUM_MEMCLK_DPM_LEVELS]; 263 }; 264 265 266 struct pp_smu_funcs_rn { 267 struct pp_smu pp_smu; 268 269 /* 270 * reader and writer WM's are sent together as part of one table 271 * 272 * PPSMC_MSG_SetDriverDramAddrHigh 273 * PPSMC_MSG_SetDriverDramAddrLow 274 * PPSMC_MSG_TransferTableDram2Smu 275 * 276 */ 277 enum pp_smu_status (*set_wm_ranges)(struct pp_smu *pp, 278 struct pp_smu_wm_range_sets *ranges); 279 280 enum pp_smu_status (*get_dpm_clock_table) (struct pp_smu *pp, 281 struct dpm_clocks *clock_table); 282 }; 283 284 struct pp_smu_funcs { 285 struct pp_smu ctx; 286 union { 287 struct pp_smu_funcs_rv rv_funcs; 288 struct pp_smu_funcs_nv nv_funcs; 289 struct pp_smu_funcs_rn rn_funcs; 290 291 }; 292 }; 293 294 #endif /* DM_PP_SMU_IF__H */ 295