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