Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright 2017 Advanced Micro Devices, Inc.
0003  *
0004  * Permission is hereby granted, free of charge, to any person obtaining a
0005  * copy of this software and associated documentation files (the "Software"),
0006  * to deal in the Software without restriction, including without limitation
0007  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0008  * and/or sell copies of the Software, and to permit persons to whom the
0009  * Software is furnished to do so, subject to the following conditions:
0010  *
0011  * The above copyright notice and this permission notice shall be included in
0012  * all copies or substantial portions of the Software.
0013  *
0014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0017  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
0018  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
0019  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
0020  * OTHER DEALINGS IN THE SOFTWARE.
0021  *
0022  * Authors: AMD
0023  *
0024  */
0025 
0026 #ifndef DM_PP_SMU_IF__H
0027 #define DM_PP_SMU_IF__H
0028 
0029 /*
0030  * interface to PPLIB/SMU to setup clocks and pstate requirements on SoC
0031  */
0032 
0033 enum pp_smu_ver {
0034     /*
0035      * PP_SMU_INTERFACE_X should be interpreted as the interface defined
0036      * starting from X, where X is some family of ASICs.  This is as
0037      * opposed to interfaces used only for X.  There will be some degree
0038      * of interface sharing between families of ASIcs.
0039      */
0040     PP_SMU_UNSUPPORTED,
0041     PP_SMU_VER_RV,
0042     PP_SMU_VER_NV,
0043     PP_SMU_VER_RN,
0044 
0045     PP_SMU_VER_MAX
0046 };
0047 
0048 struct pp_smu {
0049     enum pp_smu_ver ver;
0050     const void *pp;
0051 
0052     /*
0053      * interim extra handle for backwards compatibility
0054      * as some existing functionality not yet implemented
0055      * by ppsmu
0056      */
0057     const void *dm;
0058 };
0059 
0060 enum pp_smu_status {
0061     PP_SMU_RESULT_UNDEFINED = 0,
0062     PP_SMU_RESULT_OK = 1,
0063     PP_SMU_RESULT_FAIL,
0064     PP_SMU_RESULT_UNSUPPORTED
0065 };
0066 
0067 #define PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN 0x0
0068 #define PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX 0xFFFF
0069 
0070 enum wm_type {
0071     WM_TYPE_PSTATE_CHG = 0,
0072     WM_TYPE_RETRAINING = 1,
0073 };
0074 
0075 /* This structure is a copy of WatermarkRowGeneric_t defined by smuxx_driver_if.h*/
0076 struct pp_smu_wm_set_range {
0077     uint16_t min_fill_clk_mhz;
0078     uint16_t max_fill_clk_mhz;
0079     uint16_t min_drain_clk_mhz;
0080     uint16_t max_drain_clk_mhz;
0081 
0082     uint8_t wm_inst;
0083     uint8_t wm_type;
0084 };
0085 
0086 #define MAX_WATERMARK_SETS 4
0087 
0088 struct pp_smu_wm_range_sets {
0089     unsigned int num_reader_wm_sets;
0090     struct pp_smu_wm_set_range reader_wm_sets[MAX_WATERMARK_SETS];
0091 
0092     unsigned int num_writer_wm_sets;
0093     struct pp_smu_wm_set_range writer_wm_sets[MAX_WATERMARK_SETS];
0094 };
0095 
0096 struct pp_smu_funcs_rv {
0097     struct pp_smu pp_smu;
0098 
0099     /* PPSMC_MSG_SetDisplayCount
0100      * 0 triggers S0i2 optimization
0101      */
0102 
0103     void (*set_display_count)(struct pp_smu *pp, int count);
0104 
0105     /* reader and writer WM's are sent together as part of one table*/
0106     /*
0107      * PPSMC_MSG_SetDriverDramAddrHigh
0108      * PPSMC_MSG_SetDriverDramAddrLow
0109      * PPSMC_MSG_TransferTableDram2Smu
0110      *
0111      * */
0112     void (*set_wm_ranges)(struct pp_smu *pp,
0113             struct pp_smu_wm_range_sets *ranges);
0114 
0115     /* PPSMC_MSG_SetHardMinDcfclkByFreq
0116      * fixed clock at requested freq, either from FCH bypass or DFS
0117      */
0118     void (*set_hard_min_dcfclk_by_freq)(struct pp_smu *pp, int mhz);
0119 
0120     /* PPSMC_MSG_SetMinDeepSleepDcfclk
0121      * when DF is in cstate, dcf clock is further divided down
0122      * to just above given frequency
0123      */
0124     void (*set_min_deep_sleep_dcfclk)(struct pp_smu *pp, int mhz);
0125 
0126     /* PPSMC_MSG_SetHardMinFclkByFreq
0127      * FCLK will vary with DPM, but never below requested hard min
0128      */
0129     void (*set_hard_min_fclk_by_freq)(struct pp_smu *pp, int mhz);
0130 
0131     /* PPSMC_MSG_SetHardMinSocclkByFreq
0132      * Needed for DWB support
0133      */
0134     void (*set_hard_min_socclk_by_freq)(struct pp_smu *pp, int mhz);
0135 
0136     /* PME w/a */
0137     void (*set_pme_wa_enable)(struct pp_smu *pp);
0138 };
0139 
0140 /* Used by pp_smu_funcs_nv.set_voltage_by_freq
0141  *
0142  */
0143 enum pp_smu_nv_clock_id {
0144     PP_SMU_NV_DISPCLK,
0145     PP_SMU_NV_PHYCLK,
0146     PP_SMU_NV_PIXELCLK
0147 };
0148 
0149 /*
0150  * Used by pp_smu_funcs_nv.get_maximum_sustainable_clocks
0151  */
0152 struct pp_smu_nv_clock_table {
0153     // voltage managed SMU, freq set by driver
0154     unsigned int    displayClockInKhz;
0155     unsigned int    dppClockInKhz;
0156     unsigned int    phyClockInKhz;
0157     unsigned int    pixelClockInKhz;
0158     unsigned int    dscClockInKhz;
0159 
0160     // freq/voltage managed by SMU
0161     unsigned int    fabricClockInKhz;
0162     unsigned int    socClockInKhz;
0163     unsigned int    dcfClockInKhz;
0164     unsigned int    uClockInKhz;
0165 };
0166 
0167 struct pp_smu_funcs_nv {
0168     struct pp_smu pp_smu;
0169 
0170     /* PPSMC_MSG_SetDisplayCount
0171      * 0 triggers S0i2 optimization
0172      */
0173     enum pp_smu_status (*set_display_count)(struct pp_smu *pp, int count);
0174 
0175     /* PPSMC_MSG_SetHardMinDcfclkByFreq
0176      * fixed clock at requested freq, either from FCH bypass or DFS
0177      */
0178     enum pp_smu_status (*set_hard_min_dcfclk_by_freq)(struct pp_smu *pp, int Mhz);
0179 
0180     /* PPSMC_MSG_SetMinDeepSleepDcfclk
0181      * when DF is in cstate, dcf clock is further divided down
0182      * to just above given frequency
0183      */
0184     enum pp_smu_status (*set_min_deep_sleep_dcfclk)(struct pp_smu *pp, int Mhz);
0185 
0186     /* PPSMC_MSG_SetHardMinUclkByFreq
0187      * UCLK will vary with DPM, but never below requested hard min
0188      */
0189     enum pp_smu_status (*set_hard_min_uclk_by_freq)(struct pp_smu *pp, int Mhz);
0190 
0191     /* PPSMC_MSG_SetHardMinSocclkByFreq
0192      * Needed for DWB support
0193      */
0194     enum pp_smu_status (*set_hard_min_socclk_by_freq)(struct pp_smu *pp, int Mhz);
0195 
0196     /* PME w/a */
0197     enum pp_smu_status (*set_pme_wa_enable)(struct pp_smu *pp);
0198 
0199     /* PPSMC_MSG_SetHardMinByFreq
0200      * Needed to set ASIC voltages for clocks programmed by DAL
0201      */
0202     enum pp_smu_status (*set_voltage_by_freq)(struct pp_smu *pp,
0203             enum pp_smu_nv_clock_id clock_id, int Mhz);
0204 
0205     /* reader and writer WM's are sent together as part of one table*/
0206     /*
0207      * PPSMC_MSG_SetDriverDramAddrHigh
0208      * PPSMC_MSG_SetDriverDramAddrLow
0209      * PPSMC_MSG_TransferTableDram2Smu
0210      *
0211      * on DCN20:
0212      *  reader fill clk = uclk
0213      *  reader drain clk = dcfclk
0214      *  writer fill clk = socclk
0215      *  writer drain clk = uclk
0216      * */
0217     enum pp_smu_status (*set_wm_ranges)(struct pp_smu *pp,
0218             struct pp_smu_wm_range_sets *ranges);
0219 
0220     /* Not a single SMU message.  This call should return maximum sustainable limit for all
0221      * clocks that DC depends on.  These will be used as basis for mode enumeration.
0222      */
0223     enum pp_smu_status (*get_maximum_sustainable_clocks)(struct pp_smu *pp,
0224             struct pp_smu_nv_clock_table *max_clocks);
0225 
0226     /* This call should return the discrete uclk DPM states available
0227      */
0228     enum pp_smu_status (*get_uclk_dpm_states)(struct pp_smu *pp,
0229             unsigned int *clock_values_in_khz, unsigned int *num_states);
0230 
0231     /* Not a single SMU message.  This call informs PPLIB that display will not be able
0232      * to perform pstate handshaking in its current state.  Typically this handshake
0233      * is used to perform uCLK switching, so disabling pstate disables uCLK switching.
0234      *
0235      * Note that when setting handshake to unsupported, the call is pre-emptive.  That means
0236      * DC will make the call BEFORE setting up the display state which would cause pstate
0237      * request to go un-acked.  Only when the call completes should such a state be applied to
0238      * DC hardware
0239      */
0240     enum pp_smu_status (*set_pstate_handshake_support)(struct pp_smu *pp,
0241             bool pstate_handshake_supported);
0242 };
0243 
0244 #define PP_SMU_NUM_SOCCLK_DPM_LEVELS  8
0245 #define PP_SMU_NUM_DCFCLK_DPM_LEVELS  8
0246 #define PP_SMU_NUM_FCLK_DPM_LEVELS    4
0247 #define PP_SMU_NUM_MEMCLK_DPM_LEVELS  4
0248 #define PP_SMU_NUM_DCLK_DPM_LEVELS    8
0249 #define PP_SMU_NUM_VCLK_DPM_LEVELS    8
0250 
0251 struct dpm_clock {
0252   uint32_t  Freq;    // In MHz
0253   uint32_t  Vol;     // Millivolts with 2 fractional bits
0254 };
0255 
0256 
0257 /* this is a copy of the structure defined in smuxx_driver_if.h*/
0258 struct dpm_clocks {
0259     struct dpm_clock DcfClocks[PP_SMU_NUM_DCFCLK_DPM_LEVELS];
0260     struct dpm_clock SocClocks[PP_SMU_NUM_SOCCLK_DPM_LEVELS];
0261     struct dpm_clock FClocks[PP_SMU_NUM_FCLK_DPM_LEVELS];
0262     struct dpm_clock MemClocks[PP_SMU_NUM_MEMCLK_DPM_LEVELS];
0263     struct dpm_clock VClocks[PP_SMU_NUM_VCLK_DPM_LEVELS];
0264     struct dpm_clock DClocks[PP_SMU_NUM_DCLK_DPM_LEVELS];
0265 };
0266 
0267 
0268 struct pp_smu_funcs_rn {
0269     struct pp_smu pp_smu;
0270 
0271     /*
0272      * reader and writer WM's are sent together as part of one table
0273      *
0274      * PPSMC_MSG_SetDriverDramAddrHigh
0275      * PPSMC_MSG_SetDriverDramAddrLow
0276      * PPSMC_MSG_TransferTableDram2Smu
0277      *
0278      */
0279     enum pp_smu_status (*set_wm_ranges)(struct pp_smu *pp,
0280             struct pp_smu_wm_range_sets *ranges);
0281 
0282     enum pp_smu_status (*get_dpm_clock_table) (struct pp_smu *pp,
0283             struct dpm_clocks *clock_table);
0284 };
0285 
0286 struct pp_smu_funcs_vgh {
0287     struct pp_smu pp_smu;
0288 
0289     /*
0290      * reader and writer WM's are sent together as part of one table
0291      *
0292      * PPSMC_MSG_SetDriverDramAddrHigh
0293      * PPSMC_MSG_SetDriverDramAddrLow
0294      * PPSMC_MSG_TransferTableDram2Smu
0295      *
0296      */
0297     // TODO: Check whether this is moved to DAL, and remove as needed
0298     enum pp_smu_status (*set_wm_ranges)(struct pp_smu *pp,
0299             struct pp_smu_wm_range_sets *ranges);
0300 
0301     // TODO: Check whether this is moved to DAL, and remove as needed
0302     enum pp_smu_status (*get_dpm_clock_table) (struct pp_smu *pp,
0303             struct dpm_clocks *clock_table);
0304 
0305     enum pp_smu_status (*notify_smu_timeout) (struct pp_smu *pp);
0306 };
0307 
0308 struct pp_smu_funcs {
0309     struct pp_smu ctx;
0310     union {
0311         struct pp_smu_funcs_rv rv_funcs;
0312         struct pp_smu_funcs_nv nv_funcs;
0313         struct pp_smu_funcs_rn rn_funcs;
0314         struct pp_smu_funcs_vgh vgh_funcs;
0315     };
0316 };
0317 
0318 #endif /* DM_PP_SMU_IF__H */