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