LCOV - code coverage report
Current view: top level - drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314 - dcn314_smu.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 99 0.0 %
Date: 2022-12-09 01:23:36 Functions: 0 17 0.0 %

          Line data    Source code
       1             : // SPDX-License-Identifier: MIT
       2             : /*
       3             :  * Copyright 2022 Advanced Micro Devices, Inc.
       4             :  *
       5             :  * Permission is hereby granted, free of charge, to any person obtaining a
       6             :  * copy of this software and associated documentation files (the "Software"),
       7             :  * to deal in the Software without restriction, including without limitation
       8             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
       9             :  * and/or sell copies of the Software, and to permit persons to whom the
      10             :  * Software is furnished to do so, subject to the following conditions:
      11             :  *
      12             :  * The above copyright notice and this permission notice shall be included in
      13             :  * all copies or substantial portions of the Software.
      14             :  *
      15             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      16             :  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      17             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
      18             :  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
      19             :  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
      20             :  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
      21             :  * OTHER DEALINGS IN THE SOFTWARE.
      22             :  *
      23             :  * Authors: AMD
      24             :  *
      25             :  */
      26             : 
      27             : 
      28             : 
      29             : #include "core_types.h"
      30             : #include "clk_mgr_internal.h"
      31             : #include "reg_helper.h"
      32             : #include "dm_helpers.h"
      33             : #include "dcn314_smu.h"
      34             : 
      35             : #include "mp/mp_13_0_5_offset.h"
      36             : 
      37             : /* TODO: Use the real headers when they're correct */
      38             : #define MP1_BASE__INST0_SEG0                       0x00016000
      39             : #define MP1_BASE__INST0_SEG1                       0x0243FC00
      40             : #define MP1_BASE__INST0_SEG2                       0x00DC0000
      41             : #define MP1_BASE__INST0_SEG3                       0x00E00000
      42             : #define MP1_BASE__INST0_SEG4                       0x00E40000
      43             : #define MP1_BASE__INST0_SEG5                       0
      44             : 
      45             : #ifdef BASE_INNER
      46             : #undef BASE_INNER
      47             : #endif
      48             : 
      49             : #define BASE_INNER(seg) MP1_BASE__INST0_SEG ## seg
      50             : 
      51             : #define BASE(seg) BASE_INNER(seg)
      52             : 
      53             : #define REG(reg_name) (BASE(reg##reg_name##_BASE_IDX) + reg##reg_name)
      54             : 
      55             : #define FN(reg_name, field) \
      56             :         FD(reg_name##__##field)
      57             : 
      58             : #include "logger_types.h"
      59             : #undef DC_LOGGER
      60             : #define DC_LOGGER \
      61             :         CTX->logger
      62             : #define smu_print(str, ...) {DC_LOG_SMU(str, ##__VA_ARGS__); }
      63             : 
      64             : #define VBIOSSMC_MSG_TestMessage                  0x1
      65             : #define VBIOSSMC_MSG_GetSmuVersion                0x2
      66             : #define VBIOSSMC_MSG_PowerUpGfx                   0x3
      67             : #define VBIOSSMC_MSG_SetDispclkFreq               0x4
      68             : #define VBIOSSMC_MSG_SetDprefclkFreq              0x5   //Not used. DPRef is constant
      69             : #define VBIOSSMC_MSG_SetDppclkFreq                0x6
      70             : #define VBIOSSMC_MSG_SetHardMinDcfclkByFreq       0x7
      71             : #define VBIOSSMC_MSG_SetMinDeepSleepDcfclk        0x8
      72             : #define VBIOSSMC_MSG_SetPhyclkVoltageByFreq       0x9   //Keep it in case VMIN dees not support phy clk
      73             : #define VBIOSSMC_MSG_GetFclkFrequency             0xA
      74             : #define VBIOSSMC_MSG_SetDisplayCount              0xB   //Not used anymore
      75             : #define VBIOSSMC_MSG_EnableTmdp48MHzRefclkPwrDown 0xC   //Not used anymore
      76             : #define VBIOSSMC_MSG_UpdatePmeRestore             0xD
      77             : #define VBIOSSMC_MSG_SetVbiosDramAddrHigh         0xE   //Used for WM table txfr
      78             : #define VBIOSSMC_MSG_SetVbiosDramAddrLow          0xF
      79             : #define VBIOSSMC_MSG_TransferTableSmu2Dram        0x10
      80             : #define VBIOSSMC_MSG_TransferTableDram2Smu        0x11
      81             : #define VBIOSSMC_MSG_SetDisplayIdleOptimizations  0x12
      82             : #define VBIOSSMC_MSG_GetDprefclkFreq              0x13
      83             : #define VBIOSSMC_MSG_GetDtbclkFreq                0x14
      84             : #define VBIOSSMC_MSG_AllowZstatesEntry            0x15
      85             : #define VBIOSSMC_MSG_DisallowZstatesEntry         0x16
      86             : #define VBIOSSMC_MSG_SetDtbClk                    0x17
      87             : #define VBIOSSMC_Message_Count                    0x18
      88             : 
      89             : #define VBIOSSMC_Status_BUSY                      0x0
      90             : #define VBIOSSMC_Result_OK                        0x1
      91             : #define VBIOSSMC_Result_Failed                    0xFF
      92             : #define VBIOSSMC_Result_UnknownCmd                0xFE
      93             : #define VBIOSSMC_Result_CmdRejectedPrereq         0xFD
      94             : #define VBIOSSMC_Result_CmdRejectedBusy           0xFC
      95             : 
      96             : /*
      97             :  * Function to be used instead of REG_WAIT macro because the wait ends when
      98             :  * the register is NOT EQUAL to zero, and because the translation in msg_if.h
      99             :  * won't work with REG_WAIT.
     100             :  */
     101           0 : static uint32_t dcn314_smu_wait_for_response(struct clk_mgr_internal *clk_mgr, unsigned int delay_us, unsigned int max_retries)
     102             : {
     103           0 :         uint32_t res_val = VBIOSSMC_Status_BUSY;
     104             : 
     105             :         do {
     106           0 :                 res_val = REG_READ(MP1_SMN_C2PMSG_91);
     107           0 :                 if (res_val != VBIOSSMC_Status_BUSY)
     108             :                         break;
     109             : 
     110           0 :                 if (delay_us >= 1000)
     111           0 :                         msleep(delay_us/1000);
     112           0 :                 else if (delay_us > 0)
     113           0 :                         udelay(delay_us);
     114           0 :         } while (max_retries--);
     115             : 
     116           0 :         return res_val;
     117             : }
     118             : 
     119           0 : static int dcn314_smu_send_msg_with_param(struct clk_mgr_internal *clk_mgr,
     120             :                                          unsigned int msg_id,
     121             :                                          unsigned int param)
     122             : {
     123             :         uint32_t result;
     124             : 
     125           0 :         result = dcn314_smu_wait_for_response(clk_mgr, 10, 200000);
     126           0 :         ASSERT(result == VBIOSSMC_Result_OK);
     127             : 
     128             :         smu_print("SMU response after wait: %d\n", result);
     129             : 
     130           0 :         if (result == VBIOSSMC_Status_BUSY)
     131             :                 return -1;
     132             : 
     133             :         /* First clear response register */
     134           0 :         REG_WRITE(MP1_SMN_C2PMSG_91, VBIOSSMC_Status_BUSY);
     135             : 
     136             :         /* Set the parameter register for the SMU message, unit is Mhz */
     137           0 :         REG_WRITE(MP1_SMN_C2PMSG_83, param);
     138             : 
     139             :         /* Trigger the message transaction by writing the message ID */
     140           0 :         REG_WRITE(MP1_SMN_C2PMSG_67, msg_id);
     141             : 
     142           0 :         result = dcn314_smu_wait_for_response(clk_mgr, 10, 200000);
     143             : 
     144           0 :         if (result == VBIOSSMC_Result_Failed) {
     145           0 :                 if (msg_id == VBIOSSMC_MSG_TransferTableDram2Smu &&
     146           0 :                     param == TABLE_WATERMARKS)
     147           0 :                         DC_LOG_WARNING("Watermarks table not configured properly by SMU");
     148             :                 else
     149           0 :                         ASSERT(0);
     150           0 :                 REG_WRITE(MP1_SMN_C2PMSG_91, VBIOSSMC_Result_OK);
     151           0 :                 return -1;
     152             :         }
     153             : 
     154           0 :         if (IS_SMU_TIMEOUT(result)) {
     155           0 :                 ASSERT(0);
     156           0 :                 dm_helpers_smu_timeout(CTX, msg_id, param, 10 * 200000);
     157             :         }
     158             : 
     159           0 :         return REG_READ(MP1_SMN_C2PMSG_83);
     160             : }
     161             : 
     162           0 : int dcn314_smu_get_smu_version(struct clk_mgr_internal *clk_mgr)
     163             : {
     164           0 :         return dcn314_smu_send_msg_with_param(
     165             :                         clk_mgr,
     166             :                         VBIOSSMC_MSG_GetSmuVersion,
     167             :                         0);
     168             : }
     169             : 
     170             : 
     171           0 : int dcn314_smu_set_dispclk(struct clk_mgr_internal *clk_mgr, int requested_dispclk_khz)
     172             : {
     173           0 :         int actual_dispclk_set_mhz = -1;
     174             : 
     175           0 :         if (!clk_mgr->smu_present)
     176             :                 return requested_dispclk_khz;
     177             : 
     178             :         /*  Unit of SMU msg parameter is Mhz */
     179           0 :         actual_dispclk_set_mhz = dcn314_smu_send_msg_with_param(
     180             :                         clk_mgr,
     181             :                         VBIOSSMC_MSG_SetDispclkFreq,
     182           0 :                         khz_to_mhz_ceil(requested_dispclk_khz));
     183             : 
     184           0 :         return actual_dispclk_set_mhz * 1000;
     185             : }
     186             : 
     187           0 : int dcn314_smu_set_dprefclk(struct clk_mgr_internal *clk_mgr)
     188             : {
     189           0 :         int actual_dprefclk_set_mhz = -1;
     190             : 
     191           0 :         if (!clk_mgr->smu_present)
     192           0 :                 return clk_mgr->base.dprefclk_khz;
     193             : 
     194           0 :         actual_dprefclk_set_mhz = dcn314_smu_send_msg_with_param(
     195             :                         clk_mgr,
     196             :                         VBIOSSMC_MSG_SetDprefclkFreq,
     197           0 :                         khz_to_mhz_ceil(clk_mgr->base.dprefclk_khz));
     198             : 
     199             :         /* TODO: add code for programing DP DTO, currently this is down by command table */
     200             : 
     201           0 :         return actual_dprefclk_set_mhz * 1000;
     202             : }
     203             : 
     204           0 : int dcn314_smu_set_hard_min_dcfclk(struct clk_mgr_internal *clk_mgr, int requested_dcfclk_khz)
     205             : {
     206           0 :         int actual_dcfclk_set_mhz = -1;
     207             : 
     208           0 :         if (!clk_mgr->base.ctx->dc->debug.pstate_enabled)
     209             :                 return -1;
     210             : 
     211           0 :         if (!clk_mgr->smu_present)
     212             :                 return requested_dcfclk_khz;
     213             : 
     214           0 :         actual_dcfclk_set_mhz = dcn314_smu_send_msg_with_param(
     215             :                         clk_mgr,
     216             :                         VBIOSSMC_MSG_SetHardMinDcfclkByFreq,
     217           0 :                         khz_to_mhz_ceil(requested_dcfclk_khz));
     218             : 
     219           0 :         return actual_dcfclk_set_mhz * 1000;
     220             : }
     221             : 
     222           0 : int dcn314_smu_set_min_deep_sleep_dcfclk(struct clk_mgr_internal *clk_mgr, int requested_min_ds_dcfclk_khz)
     223             : {
     224           0 :         int actual_min_ds_dcfclk_mhz = -1;
     225             : 
     226           0 :         if (!clk_mgr->base.ctx->dc->debug.pstate_enabled)
     227             :                 return -1;
     228             : 
     229           0 :         if (!clk_mgr->smu_present)
     230             :                 return requested_min_ds_dcfclk_khz;
     231             : 
     232           0 :         actual_min_ds_dcfclk_mhz = dcn314_smu_send_msg_with_param(
     233             :                         clk_mgr,
     234             :                         VBIOSSMC_MSG_SetMinDeepSleepDcfclk,
     235           0 :                         khz_to_mhz_ceil(requested_min_ds_dcfclk_khz));
     236             : 
     237           0 :         return actual_min_ds_dcfclk_mhz * 1000;
     238             : }
     239             : 
     240           0 : int dcn314_smu_set_dppclk(struct clk_mgr_internal *clk_mgr, int requested_dpp_khz)
     241             : {
     242           0 :         int actual_dppclk_set_mhz = -1;
     243             : 
     244           0 :         if (!clk_mgr->smu_present)
     245             :                 return requested_dpp_khz;
     246             : 
     247           0 :         actual_dppclk_set_mhz = dcn314_smu_send_msg_with_param(
     248             :                         clk_mgr,
     249             :                         VBIOSSMC_MSG_SetDppclkFreq,
     250           0 :                         khz_to_mhz_ceil(requested_dpp_khz));
     251             : 
     252           0 :         return actual_dppclk_set_mhz * 1000;
     253             : }
     254             : 
     255           0 : void dcn314_smu_set_display_idle_optimization(struct clk_mgr_internal *clk_mgr, uint32_t idle_info)
     256             : {
     257           0 :         if (!clk_mgr->base.ctx->dc->debug.pstate_enabled)
     258             :                 return;
     259             : 
     260           0 :         if (!clk_mgr->smu_present)
     261             :                 return;
     262             : 
     263             :         //TODO: Work with smu team to define optimization options.
     264           0 :         dcn314_smu_send_msg_with_param(
     265             :                 clk_mgr,
     266             :                 VBIOSSMC_MSG_SetDisplayIdleOptimizations,
     267             :                 idle_info);
     268             : }
     269             : 
     270           0 : void dcn314_smu_enable_phy_refclk_pwrdwn(struct clk_mgr_internal *clk_mgr, bool enable)
     271             : {
     272           0 :         union display_idle_optimization_u idle_info = { 0 };
     273             : 
     274           0 :         if (!clk_mgr->smu_present)
     275           0 :                 return;
     276             : 
     277           0 :         if (enable) {
     278           0 :                 idle_info.idle_info.df_request_disabled = 1;
     279           0 :                 idle_info.idle_info.phy_ref_clk_off = 1;
     280             :         }
     281             : 
     282           0 :         dcn314_smu_send_msg_with_param(
     283             :                         clk_mgr,
     284             :                         VBIOSSMC_MSG_SetDisplayIdleOptimizations,
     285             :                         idle_info.data);
     286             : }
     287             : 
     288           0 : void dcn314_smu_enable_pme_wa(struct clk_mgr_internal *clk_mgr)
     289             : {
     290           0 :         if (!clk_mgr->smu_present)
     291             :                 return;
     292             : 
     293           0 :         dcn314_smu_send_msg_with_param(
     294             :                         clk_mgr,
     295             :                         VBIOSSMC_MSG_UpdatePmeRestore,
     296             :                         0);
     297             : }
     298             : 
     299           0 : void dcn314_smu_set_dram_addr_high(struct clk_mgr_internal *clk_mgr, uint32_t addr_high)
     300             : {
     301           0 :         if (!clk_mgr->smu_present)
     302             :                 return;
     303             : 
     304           0 :         dcn314_smu_send_msg_with_param(clk_mgr,
     305             :                         VBIOSSMC_MSG_SetVbiosDramAddrHigh, addr_high);
     306             : }
     307             : 
     308           0 : void dcn314_smu_set_dram_addr_low(struct clk_mgr_internal *clk_mgr, uint32_t addr_low)
     309             : {
     310           0 :         if (!clk_mgr->smu_present)
     311             :                 return;
     312             : 
     313           0 :         dcn314_smu_send_msg_with_param(clk_mgr,
     314             :                         VBIOSSMC_MSG_SetVbiosDramAddrLow, addr_low);
     315             : }
     316             : 
     317           0 : void dcn314_smu_transfer_dpm_table_smu_2_dram(struct clk_mgr_internal *clk_mgr)
     318             : {
     319           0 :         if (!clk_mgr->smu_present)
     320             :                 return;
     321             : 
     322           0 :         dcn314_smu_send_msg_with_param(clk_mgr,
     323             :                         VBIOSSMC_MSG_TransferTableSmu2Dram, TABLE_DPMCLOCKS);
     324             : }
     325             : 
     326           0 : void dcn314_smu_transfer_wm_table_dram_2_smu(struct clk_mgr_internal *clk_mgr)
     327             : {
     328           0 :         if (!clk_mgr->smu_present)
     329             :                 return;
     330             : 
     331           0 :         dcn314_smu_send_msg_with_param(clk_mgr,
     332             :                         VBIOSSMC_MSG_TransferTableDram2Smu, TABLE_WATERMARKS);
     333             : }
     334             : 
     335           0 : void dcn314_smu_set_zstate_support(struct clk_mgr_internal *clk_mgr, enum dcn_zstate_support_state support)
     336             : {
     337             :         unsigned int msg_id, param;
     338             : 
     339           0 :         if (!clk_mgr->smu_present)
     340             :                 return;
     341             : 
     342           0 :         if (!clk_mgr->base.ctx->dc->debug.enable_z9_disable_interface &&
     343             :                         (support == DCN_ZSTATE_SUPPORT_ALLOW_Z10_ONLY))
     344           0 :                 support = DCN_ZSTATE_SUPPORT_DISALLOW;
     345             : 
     346             : 
     347             :         // Arg[15:0] = 8/9/0 for Z8/Z9/disallow -> existing bits
     348             :         // Arg[16] = Disallow Z9 -> new bit
     349             :         switch (support) {
     350             : 
     351             :         case DCN_ZSTATE_SUPPORT_ALLOW:
     352             :                 msg_id = VBIOSSMC_MSG_AllowZstatesEntry;
     353             :                 param = 9;
     354             :                 break;
     355             : 
     356             :         case DCN_ZSTATE_SUPPORT_DISALLOW:
     357             :                 msg_id = VBIOSSMC_MSG_AllowZstatesEntry;
     358             :                 param = 8;
     359             :                 break;
     360             : 
     361             : 
     362             :         case DCN_ZSTATE_SUPPORT_ALLOW_Z10_ONLY:
     363             :                 msg_id = VBIOSSMC_MSG_AllowZstatesEntry;
     364             :                 param = 0x00010008;
     365             :                 break;
     366             : 
     367             :         default: //DCN_ZSTATE_SUPPORT_UNKNOWN
     368             :                 msg_id = VBIOSSMC_MSG_AllowZstatesEntry;
     369             :                 param = 0;
     370             :                 break;
     371             :         }
     372             : 
     373             : 
     374           0 :         dcn314_smu_send_msg_with_param(
     375             :                 clk_mgr,
     376             :                 msg_id,
     377             :                 param);
     378             : 
     379             : }
     380             : 
     381             : /* Arg = 1: Turn DTB on; 0: Turn DTB CLK OFF. when it is on, it is 600MHZ */
     382           0 : void dcn314_smu_set_dtbclk(struct clk_mgr_internal *clk_mgr, bool enable)
     383             : {
     384           0 :         if (!clk_mgr->smu_present)
     385             :                 return;
     386             : 
     387           0 :         dcn314_smu_send_msg_with_param(
     388             :                         clk_mgr,
     389             :                         VBIOSSMC_MSG_SetDtbClk,
     390             :                         enable);
     391             : }

Generated by: LCOV version 1.14