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

          Line data    Source code
       1             : /*
       2             :  * Copyright 2020 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             : #include "core_types.h"
      27             : #include "clk_mgr_internal.h"
      28             : #include "reg_helper.h"
      29             : #include <linux/delay.h>
      30             : 
      31             : #include "dcn301_smu.h"
      32             : 
      33             : #include "vangogh_ip_offset.h"
      34             : 
      35             : #include "mp/mp_11_5_0_offset.h"
      36             : #include "mp/mp_11_5_0_sh_mask.h"
      37             : 
      38             : #define REG(reg_name) \
      39             :         (MP0_BASE.instance[0].segment[mm ## reg_name ## _BASE_IDX] + mm ## reg_name)
      40             : 
      41             : #define FN(reg_name, field) \
      42             :         FD(reg_name##__##field)
      43             : 
      44             : #include "logger_types.h"
      45             : #undef DC_LOGGER
      46             : #define DC_LOGGER \
      47             :         CTX->logger
      48             : #define smu_print(str, ...) {DC_LOG_SMU(str, ##__VA_ARGS__); }
      49             : 
      50             : #define VBIOSSMC_MSG_GetSmuVersion                0x2
      51             : #define VBIOSSMC_MSG_SetDispclkFreq               0x4
      52             : #define VBIOSSMC_MSG_SetDprefclkFreq              0x5
      53             : #define VBIOSSMC_MSG_SetDppclkFreq                0x6
      54             : #define VBIOSSMC_MSG_SetHardMinDcfclkByFreq       0x7
      55             : #define VBIOSSMC_MSG_SetMinDeepSleepDcfclk        0x8
      56             : //#define VBIOSSMC_MSG_SetPhyclkVoltageByFreq       0xA
      57             : #define VBIOSSMC_MSG_GetFclkFrequency             0xA
      58             : //#define VBIOSSMC_MSG_SetDisplayCount              0xC
      59             : //#define VBIOSSMC_MSG_EnableTmdp48MHzRefclkPwrDown 0xD
      60             : #define VBIOSSMC_MSG_UpdatePmeRestore                     0xD
      61             : #define VBIOSSMC_MSG_SetVbiosDramAddrHigh         0xE   //Used for WM table txfr
      62             : #define VBIOSSMC_MSG_SetVbiosDramAddrLow          0xF
      63             : #define VBIOSSMC_MSG_TransferTableSmu2Dram        0x10
      64             : #define VBIOSSMC_MSG_TransferTableDram2Smu        0x11
      65             : #define VBIOSSMC_MSG_SetDisplayIdleOptimizations  0x12
      66             : 
      67             : #define VBIOSSMC_Status_BUSY                      0x0
      68             : #define VBIOSSMC_Result_OK                        0x1
      69             : #define VBIOSSMC_Result_Failed                    0xFF
      70             : #define VBIOSSMC_Result_UnknownCmd                0xFE
      71             : #define VBIOSSMC_Result_CmdRejectedPrereq         0xFD
      72             : #define VBIOSSMC_Result_CmdRejectedBusy           0xFC
      73             : 
      74             : /*
      75             :  * Function to be used instead of REG_WAIT macro because the wait ends when
      76             :  * the register is NOT EQUAL to zero, and because the translation in msg_if.h
      77             :  * won't work with REG_WAIT.
      78             :  */
      79           0 : static uint32_t dcn301_smu_wait_for_response(struct clk_mgr_internal *clk_mgr, unsigned int delay_us, unsigned int max_retries)
      80             : {
      81           0 :         uint32_t res_val = VBIOSSMC_Status_BUSY;
      82             : 
      83             :         do {
      84           0 :                 res_val = REG_READ(MP1_SMN_C2PMSG_91);
      85           0 :                 if (res_val != VBIOSSMC_Status_BUSY)
      86             :                         break;
      87             : 
      88           0 :                 if (delay_us >= 1000)
      89           0 :                         msleep(delay_us/1000);
      90           0 :                 else if (delay_us > 0)
      91           0 :                         udelay(delay_us);
      92           0 :         } while (max_retries--);
      93             : 
      94           0 :         return res_val;
      95             : }
      96             : 
      97           0 : static int dcn301_smu_send_msg_with_param(struct clk_mgr_internal *clk_mgr,
      98             :                                           unsigned int msg_id,
      99             :                                           unsigned int param)
     100             : {
     101             :         uint32_t result;
     102             : 
     103           0 :         result = dcn301_smu_wait_for_response(clk_mgr, 10, 200000);
     104             : 
     105             :         if (result != VBIOSSMC_Result_OK)
     106             :                 smu_print("SMU Response was not OK. SMU response after wait received is: %d\n", result);
     107             : 
     108           0 :         if (result == VBIOSSMC_Status_BUSY) {
     109             :                 return -1;
     110             :         }
     111             : 
     112             :         /* First clear response register */
     113           0 :         REG_WRITE(MP1_SMN_C2PMSG_91, VBIOSSMC_Status_BUSY);
     114             : 
     115             :         /* Set the parameter register for the SMU message, unit is Mhz */
     116           0 :         REG_WRITE(MP1_SMN_C2PMSG_83, param);
     117             : 
     118             :         /* Trigger the message transaction by writing the message ID */
     119           0 :         REG_WRITE(MP1_SMN_C2PMSG_67, msg_id);
     120             : 
     121           0 :         result = dcn301_smu_wait_for_response(clk_mgr, 10, 200000);
     122             : 
     123           0 :         ASSERT(result == VBIOSSMC_Result_OK);
     124             : 
     125             :         /* Actual dispclk set is returned in the parameter register */
     126           0 :         return REG_READ(MP1_SMN_C2PMSG_83);
     127             : }
     128             : 
     129           0 : int dcn301_smu_get_smu_version(struct clk_mgr_internal *clk_mgr)
     130             : {
     131           0 :         int smu_version = dcn301_smu_send_msg_with_param(clk_mgr,
     132             :                                                          VBIOSSMC_MSG_GetSmuVersion,
     133             :                                                          0);
     134             : 
     135           0 :         DC_LOG_DEBUG("%s %x\n", __func__, smu_version);
     136             : 
     137           0 :         return smu_version;
     138             : }
     139             : 
     140             : 
     141           0 : int dcn301_smu_set_dispclk(struct clk_mgr_internal *clk_mgr, int requested_dispclk_khz)
     142             : {
     143           0 :         int actual_dispclk_set_mhz = -1;
     144             : 
     145           0 :         DC_LOG_DEBUG("%s(%d)\n", __func__, requested_dispclk_khz);
     146             : 
     147             :         /*  Unit of SMU msg parameter is Mhz */
     148           0 :         actual_dispclk_set_mhz = dcn301_smu_send_msg_with_param(
     149             :                         clk_mgr,
     150             :                         VBIOSSMC_MSG_SetDispclkFreq,
     151           0 :                         khz_to_mhz_ceil(requested_dispclk_khz));
     152             : 
     153           0 :         return actual_dispclk_set_mhz * 1000;
     154             : }
     155             : 
     156           0 : int dcn301_smu_set_dprefclk(struct clk_mgr_internal *clk_mgr)
     157             : {
     158           0 :         int actual_dprefclk_set_mhz = -1;
     159             : 
     160           0 :         DC_LOG_DEBUG("%s %d\n", __func__, clk_mgr->base.dprefclk_khz / 1000);
     161             : 
     162           0 :         actual_dprefclk_set_mhz = dcn301_smu_send_msg_with_param(
     163             :                         clk_mgr,
     164             :                         VBIOSSMC_MSG_SetDprefclkFreq,
     165           0 :                         khz_to_mhz_ceil(clk_mgr->base.dprefclk_khz));
     166             : 
     167             :         /* TODO: add code for programing DP DTO, currently this is down by command table */
     168             : 
     169           0 :         return actual_dprefclk_set_mhz * 1000;
     170             : }
     171             : 
     172           0 : int dcn301_smu_set_hard_min_dcfclk(struct clk_mgr_internal *clk_mgr, int requested_dcfclk_khz)
     173             : {
     174           0 :         int actual_dcfclk_set_mhz = -1;
     175             : 
     176           0 :         DC_LOG_DEBUG("%s(%d)\n", __func__, requested_dcfclk_khz);
     177             : 
     178           0 :         actual_dcfclk_set_mhz = dcn301_smu_send_msg_with_param(
     179             :                         clk_mgr,
     180             :                         VBIOSSMC_MSG_SetHardMinDcfclkByFreq,
     181           0 :                         khz_to_mhz_ceil(requested_dcfclk_khz));
     182             : 
     183             : #ifdef DBG
     184             :         smu_print("actual_dcfclk_set_mhz %d is set to : %d\n", actual_dcfclk_set_mhz, actual_dcfclk_set_mhz * 1000);
     185             : #endif
     186             : 
     187           0 :         return actual_dcfclk_set_mhz * 1000;
     188             : }
     189             : 
     190           0 : int dcn301_smu_set_min_deep_sleep_dcfclk(struct clk_mgr_internal *clk_mgr, int requested_min_ds_dcfclk_khz)
     191             : {
     192           0 :         int actual_min_ds_dcfclk_mhz = -1;
     193             : 
     194           0 :         DC_LOG_DEBUG("%s(%d)\n", __func__, requested_min_ds_dcfclk_khz);
     195             : 
     196           0 :         actual_min_ds_dcfclk_mhz = dcn301_smu_send_msg_with_param(
     197             :                         clk_mgr,
     198             :                         VBIOSSMC_MSG_SetMinDeepSleepDcfclk,
     199           0 :                         khz_to_mhz_ceil(requested_min_ds_dcfclk_khz));
     200             : 
     201           0 :         return actual_min_ds_dcfclk_mhz * 1000;
     202             : }
     203             : 
     204           0 : int dcn301_smu_set_dppclk(struct clk_mgr_internal *clk_mgr, int requested_dpp_khz)
     205             : {
     206           0 :         int actual_dppclk_set_mhz = -1;
     207             : 
     208           0 :         DC_LOG_DEBUG("%s(%d)\n", __func__, requested_dpp_khz);
     209             : 
     210           0 :         actual_dppclk_set_mhz = dcn301_smu_send_msg_with_param(
     211             :                         clk_mgr,
     212             :                         VBIOSSMC_MSG_SetDppclkFreq,
     213           0 :                         khz_to_mhz_ceil(requested_dpp_khz));
     214             : 
     215           0 :         return actual_dppclk_set_mhz * 1000;
     216             : }
     217             : 
     218           0 : void dcn301_smu_set_display_idle_optimization(struct clk_mgr_internal *clk_mgr, uint32_t idle_info)
     219             : {
     220             :         //TODO: Work with smu team to define optimization options.
     221             : 
     222           0 :         DC_LOG_DEBUG("%s(%x)\n", __func__, idle_info);
     223             : 
     224           0 :         dcn301_smu_send_msg_with_param(
     225             :                 clk_mgr,
     226             :                 VBIOSSMC_MSG_SetDisplayIdleOptimizations,
     227             :                 idle_info);
     228           0 : }
     229             : 
     230           0 : void dcn301_smu_enable_phy_refclk_pwrdwn(struct clk_mgr_internal *clk_mgr, bool enable)
     231             : {
     232           0 :         union display_idle_optimization_u idle_info = { 0 };
     233             : 
     234           0 :         if (enable) {
     235           0 :                 idle_info.idle_info.df_request_disabled = 1;
     236           0 :                 idle_info.idle_info.phy_ref_clk_off = 1;
     237             :         }
     238             : 
     239           0 :         DC_LOG_DEBUG("%s(%d)\n", __func__, enable);
     240             : 
     241           0 :         dcn301_smu_send_msg_with_param(
     242             :                         clk_mgr,
     243             :                         VBIOSSMC_MSG_SetDisplayIdleOptimizations,
     244             :                         idle_info.data);
     245           0 : }
     246             : 
     247           0 : void dcn301_smu_enable_pme_wa(struct clk_mgr_internal *clk_mgr)
     248             : {
     249           0 :         dcn301_smu_send_msg_with_param(
     250             :                         clk_mgr,
     251             :                         VBIOSSMC_MSG_UpdatePmeRestore,
     252             :                         0);
     253           0 : }
     254             : 
     255           0 : void dcn301_smu_set_dram_addr_high(struct clk_mgr_internal *clk_mgr, uint32_t addr_high)
     256             : {
     257           0 :         DC_LOG_DEBUG("%s(%x)\n", __func__, addr_high);
     258             : 
     259           0 :         dcn301_smu_send_msg_with_param(clk_mgr,
     260             :                         VBIOSSMC_MSG_SetVbiosDramAddrHigh, addr_high);
     261           0 : }
     262             : 
     263           0 : void dcn301_smu_set_dram_addr_low(struct clk_mgr_internal *clk_mgr, uint32_t addr_low)
     264             : {
     265           0 :         DC_LOG_DEBUG("%s(%x)\n", __func__, addr_low);
     266             : 
     267           0 :         dcn301_smu_send_msg_with_param(clk_mgr,
     268             :                         VBIOSSMC_MSG_SetVbiosDramAddrLow, addr_low);
     269           0 : }
     270             : 
     271           0 : void dcn301_smu_transfer_dpm_table_smu_2_dram(struct clk_mgr_internal *clk_mgr)
     272             : {
     273           0 :         dcn301_smu_send_msg_with_param(clk_mgr,
     274             :                         VBIOSSMC_MSG_TransferTableSmu2Dram, TABLE_DPMCLOCKS);
     275           0 : }
     276             : 
     277           0 : void dcn301_smu_transfer_wm_table_dram_2_smu(struct clk_mgr_internal *clk_mgr)
     278             : {
     279           0 :         dcn301_smu_send_msg_with_param(clk_mgr,
     280             :                         VBIOSSMC_MSG_TransferTableDram2Smu, TABLE_WATERMARKS);
     281           0 : }

Generated by: LCOV version 1.14