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