Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright 2018 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 #include "reg_helper.h"
0027 #include "core_types.h"
0028 #include "dcn31_dccg.h"
0029 #include "dal_asic_id.h"
0030 
0031 #define TO_DCN_DCCG(dccg)\
0032     container_of(dccg, struct dcn_dccg, base)
0033 
0034 #define REG(reg) \
0035     (dccg_dcn->regs->reg)
0036 
0037 #undef FN
0038 #define FN(reg_name, field_name) \
0039     dccg_dcn->dccg_shift->field_name, dccg_dcn->dccg_mask->field_name
0040 
0041 #define CTX \
0042     dccg_dcn->base.ctx
0043 #define DC_LOGGER \
0044     dccg->ctx->logger
0045 
0046 void dccg31_update_dpp_dto(struct dccg *dccg, int dpp_inst, int req_dppclk)
0047 {
0048     struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
0049 
0050     if (dccg->ref_dppclk && req_dppclk) {
0051         int ref_dppclk = dccg->ref_dppclk;
0052         int modulo, phase;
0053 
0054         // phase / modulo = dpp pipe clk / dpp global clk
0055         modulo = 0xff;   // use FF at the end
0056         phase = ((modulo * req_dppclk) + ref_dppclk - 1) / ref_dppclk;
0057 
0058         if (phase > 0xff) {
0059             ASSERT(false);
0060             phase = 0xff;
0061         }
0062 
0063         REG_SET_2(DPPCLK_DTO_PARAM[dpp_inst], 0,
0064                 DPPCLK0_DTO_PHASE, phase,
0065                 DPPCLK0_DTO_MODULO, modulo);
0066         REG_UPDATE(DPPCLK_DTO_CTRL,
0067                 DPPCLK_DTO_ENABLE[dpp_inst], 1);
0068     } else {
0069         //DTO must be enabled to generate a 0Hz clock output
0070         if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpp) {
0071             REG_UPDATE(DPPCLK_DTO_CTRL,
0072                     DPPCLK_DTO_ENABLE[dpp_inst], 1);
0073             REG_SET_2(DPPCLK_DTO_PARAM[dpp_inst], 0,
0074                     DPPCLK0_DTO_PHASE, 0,
0075                     DPPCLK0_DTO_MODULO, 1);
0076         } else {
0077             REG_UPDATE(DPPCLK_DTO_CTRL,
0078                     DPPCLK_DTO_ENABLE[dpp_inst], 0);
0079         }
0080     }
0081     dccg->pipe_dppclk_khz[dpp_inst] = req_dppclk;
0082 }
0083 
0084 static enum phyd32clk_clock_source get_phy_mux_symclk(
0085         struct dcn_dccg *dccg_dcn,
0086         enum phyd32clk_clock_source src)
0087 {
0088     if (dccg_dcn->base.ctx->asic_id.hw_internal_rev == YELLOW_CARP_B0) {
0089         if (src == PHYD32CLKC)
0090             src = PHYD32CLKF;
0091         if (src == PHYD32CLKD)
0092             src = PHYD32CLKG;
0093     }
0094     return src;
0095 }
0096 
0097 static void dccg31_enable_dpstreamclk(struct dccg *dccg, int otg_inst)
0098 {
0099     struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
0100 
0101     /* enabled to select one of the DTBCLKs for pipe */
0102     switch (otg_inst) {
0103     case 0:
0104         REG_UPDATE(DPSTREAMCLK_CNTL,
0105                 DPSTREAMCLK_PIPE0_EN, 1);
0106         break;
0107     case 1:
0108         REG_UPDATE(DPSTREAMCLK_CNTL,
0109                 DPSTREAMCLK_PIPE1_EN, 1);
0110         break;
0111     case 2:
0112         REG_UPDATE(DPSTREAMCLK_CNTL,
0113                 DPSTREAMCLK_PIPE2_EN, 1);
0114         break;
0115     case 3:
0116         REG_UPDATE(DPSTREAMCLK_CNTL,
0117                 DPSTREAMCLK_PIPE3_EN, 1);
0118         break;
0119     default:
0120         BREAK_TO_DEBUGGER();
0121         return;
0122     }
0123     if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream)
0124         REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3,
0125             DPSTREAMCLK_GATE_DISABLE, 1,
0126             DPSTREAMCLK_ROOT_GATE_DISABLE, 1);
0127 }
0128 
0129 static void dccg31_disable_dpstreamclk(struct dccg *dccg, int otg_inst)
0130 {
0131     struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
0132 
0133     if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream)
0134         REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3,
0135                 DPSTREAMCLK_ROOT_GATE_DISABLE, 0,
0136                 DPSTREAMCLK_GATE_DISABLE, 0);
0137 
0138     switch (otg_inst) {
0139     case 0:
0140         REG_UPDATE(DPSTREAMCLK_CNTL,
0141                 DPSTREAMCLK_PIPE0_EN, 0);
0142         break;
0143     case 1:
0144         REG_UPDATE(DPSTREAMCLK_CNTL,
0145                 DPSTREAMCLK_PIPE1_EN, 0);
0146         break;
0147     case 2:
0148         REG_UPDATE(DPSTREAMCLK_CNTL,
0149                 DPSTREAMCLK_PIPE2_EN, 0);
0150         break;
0151     case 3:
0152         REG_UPDATE(DPSTREAMCLK_CNTL,
0153                 DPSTREAMCLK_PIPE3_EN, 0);
0154         break;
0155     default:
0156         BREAK_TO_DEBUGGER();
0157         return;
0158     }
0159 }
0160 
0161 void dccg31_set_dpstreamclk(
0162         struct dccg *dccg,
0163         enum streamclk_source src,
0164         int otg_inst,
0165         int dp_hpo_inst)
0166 {
0167     if (src == REFCLK)
0168         dccg31_disable_dpstreamclk(dccg, otg_inst);
0169     else
0170         dccg31_enable_dpstreamclk(dccg, otg_inst);
0171 }
0172 
0173 void dccg31_enable_symclk32_se(
0174         struct dccg *dccg,
0175         int hpo_se_inst,
0176         enum phyd32clk_clock_source phyd32clk)
0177 {
0178     struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
0179 
0180     phyd32clk = get_phy_mux_symclk(dccg_dcn, phyd32clk);
0181 
0182     /* select one of the PHYD32CLKs as the source for symclk32_se */
0183     switch (hpo_se_inst) {
0184     case 0:
0185         if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)
0186             REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3,
0187                     SYMCLK32_SE0_GATE_DISABLE, 1,
0188                     SYMCLK32_ROOT_SE0_GATE_DISABLE, 1);
0189         REG_UPDATE_2(SYMCLK32_SE_CNTL,
0190                 SYMCLK32_SE0_SRC_SEL, phyd32clk,
0191                 SYMCLK32_SE0_EN, 1);
0192         break;
0193     case 1:
0194         if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)
0195             REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3,
0196                     SYMCLK32_SE1_GATE_DISABLE, 1,
0197                     SYMCLK32_ROOT_SE1_GATE_DISABLE, 1);
0198         REG_UPDATE_2(SYMCLK32_SE_CNTL,
0199                 SYMCLK32_SE1_SRC_SEL, phyd32clk,
0200                 SYMCLK32_SE1_EN, 1);
0201         break;
0202     case 2:
0203         if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)
0204             REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3,
0205                     SYMCLK32_SE2_GATE_DISABLE, 1,
0206                     SYMCLK32_ROOT_SE2_GATE_DISABLE, 1);
0207         REG_UPDATE_2(SYMCLK32_SE_CNTL,
0208                 SYMCLK32_SE2_SRC_SEL, phyd32clk,
0209                 SYMCLK32_SE2_EN, 1);
0210         break;
0211     case 3:
0212         if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)
0213             REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3,
0214                     SYMCLK32_SE3_GATE_DISABLE, 1,
0215                     SYMCLK32_ROOT_SE3_GATE_DISABLE, 1);
0216         REG_UPDATE_2(SYMCLK32_SE_CNTL,
0217                 SYMCLK32_SE3_SRC_SEL, phyd32clk,
0218                 SYMCLK32_SE3_EN, 1);
0219         break;
0220     default:
0221         BREAK_TO_DEBUGGER();
0222         return;
0223     }
0224 }
0225 
0226 void dccg31_disable_symclk32_se(
0227         struct dccg *dccg,
0228         int hpo_se_inst)
0229 {
0230     struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
0231 
0232     /* set refclk as the source for symclk32_se */
0233     switch (hpo_se_inst) {
0234     case 0:
0235         REG_UPDATE_2(SYMCLK32_SE_CNTL,
0236                 SYMCLK32_SE0_SRC_SEL, 0,
0237                 SYMCLK32_SE0_EN, 0);
0238         if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)
0239             REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3,
0240                     SYMCLK32_SE0_GATE_DISABLE, 0,
0241                     SYMCLK32_ROOT_SE0_GATE_DISABLE, 0);
0242         break;
0243     case 1:
0244         REG_UPDATE_2(SYMCLK32_SE_CNTL,
0245                 SYMCLK32_SE1_SRC_SEL, 0,
0246                 SYMCLK32_SE1_EN, 0);
0247         if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)
0248             REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3,
0249                     SYMCLK32_SE1_GATE_DISABLE, 0,
0250                     SYMCLK32_ROOT_SE1_GATE_DISABLE, 0);
0251         break;
0252     case 2:
0253         REG_UPDATE_2(SYMCLK32_SE_CNTL,
0254                 SYMCLK32_SE2_SRC_SEL, 0,
0255                 SYMCLK32_SE2_EN, 0);
0256         if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)
0257             REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3,
0258                     SYMCLK32_SE2_GATE_DISABLE, 0,
0259                     SYMCLK32_ROOT_SE2_GATE_DISABLE, 0);
0260         break;
0261     case 3:
0262         REG_UPDATE_2(SYMCLK32_SE_CNTL,
0263                 SYMCLK32_SE3_SRC_SEL, 0,
0264                 SYMCLK32_SE3_EN, 0);
0265         if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)
0266             REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3,
0267                     SYMCLK32_SE3_GATE_DISABLE, 0,
0268                     SYMCLK32_ROOT_SE3_GATE_DISABLE, 0);
0269         break;
0270     default:
0271         BREAK_TO_DEBUGGER();
0272         return;
0273     }
0274 }
0275 
0276 void dccg31_enable_symclk32_le(
0277         struct dccg *dccg,
0278         int hpo_le_inst,
0279         enum phyd32clk_clock_source phyd32clk)
0280 {
0281     struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
0282 
0283     phyd32clk = get_phy_mux_symclk(dccg_dcn, phyd32clk);
0284 
0285     /* select one of the PHYD32CLKs as the source for symclk32_le */
0286     switch (hpo_le_inst) {
0287     case 0:
0288         if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le)
0289             REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3,
0290                     SYMCLK32_LE0_GATE_DISABLE, 1,
0291                     SYMCLK32_ROOT_LE0_GATE_DISABLE, 1);
0292         REG_UPDATE_2(SYMCLK32_LE_CNTL,
0293                 SYMCLK32_LE0_SRC_SEL, phyd32clk,
0294                 SYMCLK32_LE0_EN, 1);
0295         break;
0296     case 1:
0297         if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le)
0298             REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3,
0299                     SYMCLK32_LE1_GATE_DISABLE, 1,
0300                     SYMCLK32_ROOT_LE1_GATE_DISABLE, 1);
0301         REG_UPDATE_2(SYMCLK32_LE_CNTL,
0302                 SYMCLK32_LE1_SRC_SEL, phyd32clk,
0303                 SYMCLK32_LE1_EN, 1);
0304         break;
0305     default:
0306         BREAK_TO_DEBUGGER();
0307         return;
0308     }
0309 }
0310 
0311 void dccg31_disable_symclk32_le(
0312         struct dccg *dccg,
0313         int hpo_le_inst)
0314 {
0315     struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
0316 
0317     /* set refclk as the source for symclk32_le */
0318     switch (hpo_le_inst) {
0319     case 0:
0320         REG_UPDATE_2(SYMCLK32_LE_CNTL,
0321                 SYMCLK32_LE0_SRC_SEL, 0,
0322                 SYMCLK32_LE0_EN, 0);
0323         if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le)
0324             REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3,
0325                     SYMCLK32_LE0_GATE_DISABLE, 0,
0326                     SYMCLK32_ROOT_LE0_GATE_DISABLE, 0);
0327         break;
0328     case 1:
0329         REG_UPDATE_2(SYMCLK32_LE_CNTL,
0330                 SYMCLK32_LE1_SRC_SEL, 0,
0331                 SYMCLK32_LE1_EN, 0);
0332         if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le)
0333             REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3,
0334                     SYMCLK32_LE1_GATE_DISABLE, 0,
0335                     SYMCLK32_ROOT_LE1_GATE_DISABLE, 0);
0336         break;
0337     default:
0338         BREAK_TO_DEBUGGER();
0339         return;
0340     }
0341 }
0342 
0343 void dccg31_disable_dscclk(struct dccg *dccg, int inst)
0344 {
0345     struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
0346 
0347     if (!dccg->ctx->dc->debug.root_clock_optimization.bits.dsc)
0348         return;
0349     //DTO must be enabled to generate a 0 Hz clock output
0350     switch (inst) {
0351     case 0:
0352         REG_UPDATE(DSCCLK_DTO_CTRL,
0353                 DSCCLK0_DTO_ENABLE, 1);
0354         REG_UPDATE_2(DSCCLK0_DTO_PARAM,
0355                 DSCCLK0_DTO_PHASE, 0,
0356                 DSCCLK0_DTO_MODULO, 1);
0357         break;
0358     case 1:
0359         REG_UPDATE(DSCCLK_DTO_CTRL,
0360                 DSCCLK1_DTO_ENABLE, 1);
0361         REG_UPDATE_2(DSCCLK1_DTO_PARAM,
0362                 DSCCLK1_DTO_PHASE, 0,
0363                 DSCCLK1_DTO_MODULO, 1);
0364         break;
0365     case 2:
0366         REG_UPDATE(DSCCLK_DTO_CTRL,
0367                 DSCCLK2_DTO_ENABLE, 1);
0368         REG_UPDATE_2(DSCCLK2_DTO_PARAM,
0369                 DSCCLK2_DTO_PHASE, 0,
0370                 DSCCLK2_DTO_MODULO, 1);
0371         break;
0372     default:
0373         BREAK_TO_DEBUGGER();
0374         return;
0375     }
0376 }
0377 
0378 void dccg31_enable_dscclk(struct dccg *dccg, int inst)
0379 {
0380     struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
0381 
0382     if (!dccg->ctx->dc->debug.root_clock_optimization.bits.dsc)
0383         return;
0384     //Disable DTO
0385     switch (inst) {
0386     case 0:
0387         REG_UPDATE_2(DSCCLK0_DTO_PARAM,
0388                 DSCCLK0_DTO_PHASE, 0,
0389                 DSCCLK0_DTO_MODULO, 0);
0390         REG_UPDATE(DSCCLK_DTO_CTRL,
0391                 DSCCLK0_DTO_ENABLE, 0);
0392         break;
0393     case 1:
0394         REG_UPDATE_2(DSCCLK1_DTO_PARAM,
0395                 DSCCLK1_DTO_PHASE, 0,
0396                 DSCCLK1_DTO_MODULO, 0);
0397         REG_UPDATE(DSCCLK_DTO_CTRL,
0398                 DSCCLK1_DTO_ENABLE, 0);
0399         break;
0400     case 2:
0401         REG_UPDATE_2(DSCCLK2_DTO_PARAM,
0402                 DSCCLK2_DTO_PHASE, 0,
0403                 DSCCLK2_DTO_MODULO, 0);
0404         REG_UPDATE(DSCCLK_DTO_CTRL,
0405                 DSCCLK2_DTO_ENABLE, 0);
0406         break;
0407     default:
0408         BREAK_TO_DEBUGGER();
0409         return;
0410     }
0411 }
0412 
0413 void dccg31_set_physymclk(
0414         struct dccg *dccg,
0415         int phy_inst,
0416         enum physymclk_clock_source clk_src,
0417         bool force_enable)
0418 {
0419     struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
0420 
0421     /* Force PHYSYMCLK on and Select phyd32clk as the source of clock which is output to PHY through DCIO */
0422     switch (phy_inst) {
0423     case 0:
0424         if (force_enable) {
0425             REG_UPDATE_2(PHYASYMCLK_CLOCK_CNTL,
0426                     PHYASYMCLK_FORCE_EN, 1,
0427                     PHYASYMCLK_FORCE_SRC_SEL, clk_src);
0428             if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)
0429                 REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
0430                     PHYASYMCLK_GATE_DISABLE, 1);
0431         } else {
0432             REG_UPDATE_2(PHYASYMCLK_CLOCK_CNTL,
0433                     PHYASYMCLK_FORCE_EN, 0,
0434                     PHYASYMCLK_FORCE_SRC_SEL, 0);
0435             if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)
0436                 REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
0437                     PHYASYMCLK_GATE_DISABLE, 0);
0438         }
0439         break;
0440     case 1:
0441         if (force_enable) {
0442             REG_UPDATE_2(PHYBSYMCLK_CLOCK_CNTL,
0443                     PHYBSYMCLK_FORCE_EN, 1,
0444                     PHYBSYMCLK_FORCE_SRC_SEL, clk_src);
0445             if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)
0446                 REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
0447                     PHYBSYMCLK_GATE_DISABLE, 1);
0448         } else {
0449             REG_UPDATE_2(PHYBSYMCLK_CLOCK_CNTL,
0450                     PHYBSYMCLK_FORCE_EN, 0,
0451                     PHYBSYMCLK_FORCE_SRC_SEL, 0);
0452             if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)
0453                 REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
0454                     PHYBSYMCLK_GATE_DISABLE, 0);
0455         }
0456         break;
0457     case 2:
0458         if (force_enable) {
0459             REG_UPDATE_2(PHYCSYMCLK_CLOCK_CNTL,
0460                     PHYCSYMCLK_FORCE_EN, 1,
0461                     PHYCSYMCLK_FORCE_SRC_SEL, clk_src);
0462             if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)
0463                 REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
0464                     PHYCSYMCLK_GATE_DISABLE, 1);
0465         } else {
0466             REG_UPDATE_2(PHYCSYMCLK_CLOCK_CNTL,
0467                     PHYCSYMCLK_FORCE_EN, 0,
0468                     PHYCSYMCLK_FORCE_SRC_SEL, 0);
0469             if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)
0470                 REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
0471                     PHYCSYMCLK_GATE_DISABLE, 0);
0472         }
0473         break;
0474     case 3:
0475         if (force_enable) {
0476             REG_UPDATE_2(PHYDSYMCLK_CLOCK_CNTL,
0477                     PHYDSYMCLK_FORCE_EN, 1,
0478                     PHYDSYMCLK_FORCE_SRC_SEL, clk_src);
0479             if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)
0480                 REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
0481                     PHYDSYMCLK_GATE_DISABLE, 1);
0482         } else {
0483             REG_UPDATE_2(PHYDSYMCLK_CLOCK_CNTL,
0484                     PHYDSYMCLK_FORCE_EN, 0,
0485                     PHYDSYMCLK_FORCE_SRC_SEL, 0);
0486             if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)
0487                 REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
0488                     PHYDSYMCLK_GATE_DISABLE, 0);
0489         }
0490         break;
0491     case 4:
0492         if (force_enable) {
0493             REG_UPDATE_2(PHYESYMCLK_CLOCK_CNTL,
0494                     PHYESYMCLK_FORCE_EN, 1,
0495                     PHYESYMCLK_FORCE_SRC_SEL, clk_src);
0496             if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)
0497                 REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
0498                     PHYESYMCLK_GATE_DISABLE, 1);
0499         } else {
0500             REG_UPDATE_2(PHYESYMCLK_CLOCK_CNTL,
0501                     PHYESYMCLK_FORCE_EN, 0,
0502                     PHYESYMCLK_FORCE_SRC_SEL, 0);
0503             if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)
0504                 REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
0505                     PHYESYMCLK_GATE_DISABLE, 0);
0506         }
0507         break;
0508     default:
0509         BREAK_TO_DEBUGGER();
0510         return;
0511     }
0512 }
0513 
0514 /* Controls the generation of pixel valid for OTG in (OTG -> HPO case) */
0515 void dccg31_set_dtbclk_dto(
0516         struct dccg *dccg,
0517         const struct dtbclk_dto_params *params)
0518 {
0519     struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
0520     int req_dtbclk_khz = params->pixclk_khz;
0521     uint32_t dtbdto_div;
0522 
0523     /* Mode                 DTBDTO Rate       DTBCLK_DTO<x>_DIV Register
0524      * ODM 4:1 combine      pixel rate/4      2
0525      * ODM 2:1 combine      pixel rate/2      4
0526      * non-DSC 4:2:0 mode   pixel rate/2      4
0527      * DSC native 4:2:0     pixel rate/2      4
0528      * DSC native 4:2:2     pixel rate/2      4
0529      * Other modes          pixel rate        8
0530      */
0531     if (params->num_odm_segments == 4) {
0532         dtbdto_div = 2;
0533         req_dtbclk_khz = params->pixclk_khz / 4;
0534     } else if ((params->num_odm_segments == 2) ||
0535             (params->timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) ||
0536             (params->timing->flags.DSC && params->timing->pixel_encoding == PIXEL_ENCODING_YCBCR422
0537                     && !params->timing->dsc_cfg.ycbcr422_simple)) {
0538         dtbdto_div = 4;
0539         req_dtbclk_khz = params->pixclk_khz / 2;
0540     } else
0541         dtbdto_div = 8;
0542 
0543     if (params->ref_dtbclk_khz && req_dtbclk_khz) {
0544         uint32_t modulo, phase;
0545 
0546         // phase / modulo = dtbclk / dtbclk ref
0547         modulo = params->ref_dtbclk_khz * 1000;
0548         phase = div_u64((((unsigned long long)modulo * req_dtbclk_khz) + params->ref_dtbclk_khz - 1),
0549                 params->ref_dtbclk_khz);
0550 
0551         REG_UPDATE(OTG_PIXEL_RATE_CNTL[params->otg_inst],
0552                 DTBCLK_DTO_DIV[params->otg_inst], dtbdto_div);
0553 
0554         REG_WRITE(DTBCLK_DTO_MODULO[params->otg_inst], modulo);
0555         REG_WRITE(DTBCLK_DTO_PHASE[params->otg_inst], phase);
0556 
0557         REG_UPDATE(OTG_PIXEL_RATE_CNTL[params->otg_inst],
0558                 DTBCLK_DTO_ENABLE[params->otg_inst], 1);
0559 
0560         REG_WAIT(OTG_PIXEL_RATE_CNTL[params->otg_inst],
0561                 DTBCLKDTO_ENABLE_STATUS[params->otg_inst], 1,
0562                 1, 100);
0563 
0564         /* The recommended programming sequence to enable DTBCLK DTO to generate
0565          * valid pixel HPO DPSTREAM ENCODER, specifies that DTO source select should
0566          * be set only after DTO is enabled
0567          */
0568         REG_UPDATE(OTG_PIXEL_RATE_CNTL[params->otg_inst],
0569                 PIPE_DTO_SRC_SEL[params->otg_inst], 1);
0570     } else {
0571         REG_UPDATE_3(OTG_PIXEL_RATE_CNTL[params->otg_inst],
0572                 DTBCLK_DTO_ENABLE[params->otg_inst], 0,
0573                 PIPE_DTO_SRC_SEL[params->otg_inst], 0,
0574                 DTBCLK_DTO_DIV[params->otg_inst], dtbdto_div);
0575 
0576         REG_WRITE(DTBCLK_DTO_MODULO[params->otg_inst], 0);
0577         REG_WRITE(DTBCLK_DTO_PHASE[params->otg_inst], 0);
0578     }
0579 }
0580 
0581 void dccg31_set_audio_dtbclk_dto(
0582         struct dccg *dccg,
0583         const struct dtbclk_dto_params *params)
0584 {
0585     struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
0586 
0587     if (params->ref_dtbclk_khz && params->req_audio_dtbclk_khz) {
0588         uint32_t modulo, phase;
0589 
0590         // phase / modulo = dtbclk / dtbclk ref
0591         modulo = params->ref_dtbclk_khz * 1000;
0592         phase = div_u64((((unsigned long long)modulo * params->req_audio_dtbclk_khz) + params->ref_dtbclk_khz - 1),
0593             params->ref_dtbclk_khz);
0594 
0595 
0596         REG_WRITE(DCCG_AUDIO_DTBCLK_DTO_MODULO, modulo);
0597         REG_WRITE(DCCG_AUDIO_DTBCLK_DTO_PHASE, phase);
0598 
0599         //REG_UPDATE(DCCG_AUDIO_DTO_SOURCE,
0600         //      DCCG_AUDIO_DTBCLK_DTO_USE_512FBR_DTO, 1);
0601 
0602         REG_UPDATE(DCCG_AUDIO_DTO_SOURCE,
0603                 DCCG_AUDIO_DTO_SEL, 4);  //  04 - DCCG_AUDIO_DTO_SEL_AUDIO_DTO_DTBCLK
0604     } else {
0605         REG_WRITE(DCCG_AUDIO_DTBCLK_DTO_PHASE, 0);
0606         REG_WRITE(DCCG_AUDIO_DTBCLK_DTO_MODULO, 0);
0607 
0608         REG_UPDATE(DCCG_AUDIO_DTO_SOURCE,
0609                 DCCG_AUDIO_DTO_SEL, 3);  //  03 - DCCG_AUDIO_DTO_SEL_NO_AUDIO_DTO
0610     }
0611 }
0612 
0613 void dccg31_get_dccg_ref_freq(struct dccg *dccg,
0614         unsigned int xtalin_freq_inKhz,
0615         unsigned int *dccg_ref_freq_inKhz)
0616 {
0617     /*
0618      * Assume refclk is sourced from xtalin
0619      * expect 24MHz
0620      */
0621     *dccg_ref_freq_inKhz = xtalin_freq_inKhz;
0622     return;
0623 }
0624 
0625 void dccg31_set_dispclk_change_mode(
0626     struct dccg *dccg,
0627     enum dentist_dispclk_change_mode change_mode)
0628 {
0629     struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
0630 
0631     REG_UPDATE(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_CHG_MODE,
0632            change_mode == DISPCLK_CHANGE_MODE_RAMPING ? 2 : 0);
0633 }
0634 
0635 void dccg31_init(struct dccg *dccg)
0636 {
0637     /* Set HPO stream encoder to use refclk to avoid case where PHY is
0638      * disabled and SYMCLK32 for HPO SE is sourced from PHYD32CLK which
0639      * will cause DCN to hang.
0640      */
0641     dccg31_disable_symclk32_se(dccg, 0);
0642     dccg31_disable_symclk32_se(dccg, 1);
0643     dccg31_disable_symclk32_se(dccg, 2);
0644     dccg31_disable_symclk32_se(dccg, 3);
0645 
0646     if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le) {
0647         dccg31_disable_symclk32_le(dccg, 0);
0648         dccg31_disable_symclk32_le(dccg, 1);
0649     }
0650 
0651     if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream) {
0652         dccg31_disable_dpstreamclk(dccg, 0);
0653         dccg31_disable_dpstreamclk(dccg, 1);
0654         dccg31_disable_dpstreamclk(dccg, 2);
0655         dccg31_disable_dpstreamclk(dccg, 3);
0656     }
0657 
0658     if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk) {
0659         dccg31_set_physymclk(dccg, 0, PHYSYMCLK_FORCE_SRC_SYMCLK, false);
0660         dccg31_set_physymclk(dccg, 1, PHYSYMCLK_FORCE_SRC_SYMCLK, false);
0661         dccg31_set_physymclk(dccg, 2, PHYSYMCLK_FORCE_SRC_SYMCLK, false);
0662         dccg31_set_physymclk(dccg, 3, PHYSYMCLK_FORCE_SRC_SYMCLK, false);
0663         dccg31_set_physymclk(dccg, 4, PHYSYMCLK_FORCE_SRC_SYMCLK, false);
0664     }
0665 }
0666 
0667 void dccg31_otg_add_pixel(struct dccg *dccg,
0668                  uint32_t otg_inst)
0669 {
0670     struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
0671 
0672     REG_UPDATE(OTG_PIXEL_RATE_CNTL[otg_inst],
0673             OTG_ADD_PIXEL[otg_inst], 1);
0674 }
0675 
0676 void dccg31_otg_drop_pixel(struct dccg *dccg,
0677                   uint32_t otg_inst)
0678 {
0679     struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
0680 
0681     REG_UPDATE(OTG_PIXEL_RATE_CNTL[otg_inst],
0682             OTG_DROP_PIXEL[otg_inst], 1);
0683 }
0684 
0685 static const struct dccg_funcs dccg31_funcs = {
0686     .update_dpp_dto = dccg31_update_dpp_dto,
0687     .get_dccg_ref_freq = dccg31_get_dccg_ref_freq,
0688     .dccg_init = dccg31_init,
0689     .set_dpstreamclk = dccg31_set_dpstreamclk,
0690     .enable_symclk32_se = dccg31_enable_symclk32_se,
0691     .disable_symclk32_se = dccg31_disable_symclk32_se,
0692     .enable_symclk32_le = dccg31_enable_symclk32_le,
0693     .disable_symclk32_le = dccg31_disable_symclk32_le,
0694     .set_physymclk = dccg31_set_physymclk,
0695     .set_dtbclk_dto = dccg31_set_dtbclk_dto,
0696     .set_audio_dtbclk_dto = dccg31_set_audio_dtbclk_dto,
0697     .set_fifo_errdet_ovr_en = dccg2_set_fifo_errdet_ovr_en,
0698     .otg_add_pixel = dccg31_otg_add_pixel,
0699     .otg_drop_pixel = dccg31_otg_drop_pixel,
0700     .set_dispclk_change_mode = dccg31_set_dispclk_change_mode,
0701     .disable_dsc = dccg31_disable_dscclk,
0702     .enable_dsc = dccg31_enable_dscclk,
0703 };
0704 
0705 struct dccg *dccg31_create(
0706     struct dc_context *ctx,
0707     const struct dccg_registers *regs,
0708     const struct dccg_shift *dccg_shift,
0709     const struct dccg_mask *dccg_mask)
0710 {
0711     struct dcn_dccg *dccg_dcn = kzalloc(sizeof(*dccg_dcn), GFP_KERNEL);
0712     struct dccg *base;
0713 
0714     if (dccg_dcn == NULL) {
0715         BREAK_TO_DEBUGGER();
0716         return NULL;
0717     }
0718 
0719     base = &dccg_dcn->base;
0720     base->ctx = ctx;
0721     base->funcs = &dccg31_funcs;
0722 
0723     dccg_dcn->regs = regs;
0724     dccg_dcn->dccg_shift = dccg_shift;
0725     dccg_dcn->dccg_mask = dccg_mask;
0726 
0727     return &dccg_dcn->base;
0728 }