Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright 2021 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 "dcn32_dccg.h"
0029 
0030 #define TO_DCN_DCCG(dccg)\
0031     container_of(dccg, struct dcn_dccg, base)
0032 
0033 #define REG(reg) \
0034     (dccg_dcn->regs->reg)
0035 
0036 #undef FN
0037 #define FN(reg_name, field_name) \
0038     dccg_dcn->dccg_shift->field_name, dccg_dcn->dccg_mask->field_name
0039 
0040 #define CTX \
0041     dccg_dcn->base.ctx
0042 #define DC_LOGGER \
0043     dccg->ctx->logger
0044 
0045 static void dccg32_get_pixel_rate_div(
0046         struct dccg *dccg,
0047         uint32_t otg_inst,
0048         enum pixel_rate_div *k1,
0049         enum pixel_rate_div *k2)
0050 {
0051     struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
0052     uint32_t val_k1 = PIXEL_RATE_DIV_NA, val_k2 = PIXEL_RATE_DIV_NA;
0053 
0054     *k1 = PIXEL_RATE_DIV_NA;
0055     *k2 = PIXEL_RATE_DIV_NA;
0056 
0057     switch (otg_inst) {
0058     case 0:
0059         REG_GET_2(OTG_PIXEL_RATE_DIV,
0060             OTG0_PIXEL_RATE_DIVK1, &val_k1,
0061             OTG0_PIXEL_RATE_DIVK2, &val_k2);
0062         break;
0063     case 1:
0064         REG_GET_2(OTG_PIXEL_RATE_DIV,
0065             OTG1_PIXEL_RATE_DIVK1, &val_k1,
0066             OTG1_PIXEL_RATE_DIVK2, &val_k2);
0067         break;
0068     case 2:
0069         REG_GET_2(OTG_PIXEL_RATE_DIV,
0070             OTG2_PIXEL_RATE_DIVK1, &val_k1,
0071             OTG2_PIXEL_RATE_DIVK2, &val_k2);
0072         break;
0073     case 3:
0074         REG_GET_2(OTG_PIXEL_RATE_DIV,
0075             OTG3_PIXEL_RATE_DIVK1, &val_k1,
0076             OTG3_PIXEL_RATE_DIVK2, &val_k2);
0077         break;
0078     default:
0079         BREAK_TO_DEBUGGER();
0080         return;
0081     }
0082 
0083     *k1 = (enum pixel_rate_div)val_k1;
0084     *k2 = (enum pixel_rate_div)val_k2;
0085 }
0086 
0087 static void dccg32_set_pixel_rate_div(
0088         struct dccg *dccg,
0089         uint32_t otg_inst,
0090         enum pixel_rate_div k1,
0091         enum pixel_rate_div k2)
0092 {
0093     struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
0094 
0095     enum pixel_rate_div cur_k1 = PIXEL_RATE_DIV_NA, cur_k2 = PIXEL_RATE_DIV_NA;
0096 
0097     // Don't program 0xF into the register field. Not valid since
0098     // K1 / K2 field is only 1 / 2 bits wide
0099     if (k1 == PIXEL_RATE_DIV_NA || k2 == PIXEL_RATE_DIV_NA)
0100         return;
0101 
0102     dccg32_get_pixel_rate_div(dccg, otg_inst, &cur_k1, &cur_k2);
0103     if (k1 == cur_k1 && k2 == cur_k2)
0104         return;
0105 
0106     switch (otg_inst) {
0107     case 0:
0108         REG_UPDATE_2(OTG_PIXEL_RATE_DIV,
0109                 OTG0_PIXEL_RATE_DIVK1, k1,
0110                 OTG0_PIXEL_RATE_DIVK2, k2);
0111         break;
0112     case 1:
0113         REG_UPDATE_2(OTG_PIXEL_RATE_DIV,
0114                 OTG1_PIXEL_RATE_DIVK1, k1,
0115                 OTG1_PIXEL_RATE_DIVK2, k2);
0116         break;
0117     case 2:
0118         REG_UPDATE_2(OTG_PIXEL_RATE_DIV,
0119                 OTG2_PIXEL_RATE_DIVK1, k1,
0120                 OTG2_PIXEL_RATE_DIVK2, k2);
0121         break;
0122     case 3:
0123         REG_UPDATE_2(OTG_PIXEL_RATE_DIV,
0124                 OTG3_PIXEL_RATE_DIVK1, k1,
0125                 OTG3_PIXEL_RATE_DIVK2, k2);
0126         break;
0127     default:
0128         BREAK_TO_DEBUGGER();
0129         return;
0130     }
0131 }
0132 
0133 static void dccg32_set_dtbclk_p_src(
0134         struct dccg *dccg,
0135         enum streamclk_source src,
0136         uint32_t otg_inst)
0137 {
0138     struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
0139 
0140     uint32_t p_src_sel = 0; /* selects dprefclk */
0141     if (src == DTBCLK0)
0142         p_src_sel = 2;  /* selects dtbclk0 */
0143 
0144     switch (otg_inst) {
0145     case 0:
0146         if (src == REFCLK)
0147             REG_UPDATE(DTBCLK_P_CNTL,
0148                     DTBCLK_P0_EN, 0);
0149         else
0150             REG_UPDATE_2(DTBCLK_P_CNTL,
0151                     DTBCLK_P0_SRC_SEL, p_src_sel,
0152                     DTBCLK_P0_EN, 1);
0153         break;
0154     case 1:
0155         if (src == REFCLK)
0156             REG_UPDATE(DTBCLK_P_CNTL,
0157                     DTBCLK_P1_EN, 0);
0158         else
0159             REG_UPDATE_2(DTBCLK_P_CNTL,
0160                     DTBCLK_P1_SRC_SEL, p_src_sel,
0161                     DTBCLK_P1_EN, 1);
0162         break;
0163     case 2:
0164         if (src == REFCLK)
0165             REG_UPDATE(DTBCLK_P_CNTL,
0166                     DTBCLK_P2_EN, 0);
0167         else
0168             REG_UPDATE_2(DTBCLK_P_CNTL,
0169                     DTBCLK_P2_SRC_SEL, p_src_sel,
0170                     DTBCLK_P2_EN, 1);
0171         break;
0172     case 3:
0173         if (src == REFCLK)
0174             REG_UPDATE(DTBCLK_P_CNTL,
0175                     DTBCLK_P3_EN, 0);
0176         else
0177             REG_UPDATE_2(DTBCLK_P_CNTL,
0178                     DTBCLK_P3_SRC_SEL, p_src_sel,
0179                     DTBCLK_P3_EN, 1);
0180         break;
0181     default:
0182         BREAK_TO_DEBUGGER();
0183         return;
0184     }
0185 
0186 }
0187 
0188 /* Controls the generation of pixel valid for OTG in (OTG -> HPO case) */
0189 void dccg32_set_dtbclk_dto(
0190         struct dccg *dccg,
0191         const struct dtbclk_dto_params *params)
0192 {
0193     struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
0194     /* DTO Output Rate / Pixel Rate = 1/4 */
0195     int req_dtbclk_khz = params->pixclk_khz / 4;
0196 
0197     if (params->ref_dtbclk_khz && req_dtbclk_khz) {
0198         uint32_t modulo, phase;
0199 
0200         // phase / modulo = dtbclk / dtbclk ref
0201         modulo = params->ref_dtbclk_khz * 1000;
0202         phase = req_dtbclk_khz * 1000;
0203 
0204         REG_WRITE(DTBCLK_DTO_MODULO[params->otg_inst], modulo);
0205         REG_WRITE(DTBCLK_DTO_PHASE[params->otg_inst], phase);
0206 
0207         REG_UPDATE(OTG_PIXEL_RATE_CNTL[params->otg_inst],
0208                 DTBCLK_DTO_ENABLE[params->otg_inst], 1);
0209 
0210         REG_WAIT(OTG_PIXEL_RATE_CNTL[params->otg_inst],
0211                 DTBCLKDTO_ENABLE_STATUS[params->otg_inst], 1,
0212                 1, 100);
0213 
0214         /* program OTG_PIXEL_RATE_DIV for DIVK1 and DIVK2 fields */
0215         dccg32_set_pixel_rate_div(dccg, params->otg_inst, PIXEL_RATE_DIV_BY_1, PIXEL_RATE_DIV_BY_1);
0216 
0217         /* The recommended programming sequence to enable DTBCLK DTO to generate
0218          * valid pixel HPO DPSTREAM ENCODER, specifies that DTO source select should
0219          * be set only after DTO is enabled
0220          */
0221         REG_UPDATE(OTG_PIXEL_RATE_CNTL[params->otg_inst],
0222                 PIPE_DTO_SRC_SEL[params->otg_inst], 2);
0223     } else {
0224         REG_UPDATE_2(OTG_PIXEL_RATE_CNTL[params->otg_inst],
0225                 DTBCLK_DTO_ENABLE[params->otg_inst], 0,
0226                 PIPE_DTO_SRC_SEL[params->otg_inst], 1);
0227         if (params->is_hdmi)
0228             REG_UPDATE(OTG_PIXEL_RATE_CNTL[params->otg_inst],
0229                 PIPE_DTO_SRC_SEL[params->otg_inst], 0);
0230 
0231         REG_WRITE(DTBCLK_DTO_MODULO[params->otg_inst], 0);
0232         REG_WRITE(DTBCLK_DTO_PHASE[params->otg_inst], 0);
0233     }
0234 }
0235 
0236 static void dccg32_set_valid_pixel_rate(
0237         struct dccg *dccg,
0238         int ref_dtbclk_khz,
0239         int otg_inst,
0240         int pixclk_khz)
0241 {
0242     struct dtbclk_dto_params dto_params = {0};
0243 
0244     dto_params.ref_dtbclk_khz = ref_dtbclk_khz;
0245     dto_params.otg_inst = otg_inst;
0246     dto_params.pixclk_khz = pixclk_khz;
0247     dto_params.is_hdmi = true;
0248 
0249     dccg32_set_dtbclk_dto(dccg, &dto_params);
0250 }
0251 
0252 static void dccg32_get_dccg_ref_freq(struct dccg *dccg,
0253         unsigned int xtalin_freq_inKhz,
0254         unsigned int *dccg_ref_freq_inKhz)
0255 {
0256     /*
0257      * Assume refclk is sourced from xtalin
0258      * expect 100MHz
0259      */
0260     *dccg_ref_freq_inKhz = xtalin_freq_inKhz;
0261     return;
0262 }
0263 
0264 void dccg32_set_dpstreamclk(
0265         struct dccg *dccg,
0266         enum streamclk_source src,
0267         int otg_inst,
0268         int dp_hpo_inst)
0269 {
0270     struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
0271 
0272     /* set the dtbclk_p source */
0273     dccg32_set_dtbclk_p_src(dccg, src, otg_inst);
0274 
0275     /* enabled to select one of the DTBCLKs for pipe */
0276     switch (otg_inst)
0277     {
0278     case 0:
0279         REG_UPDATE_2(DPSTREAMCLK_CNTL,
0280                  DPSTREAMCLK0_EN,
0281                  (src == REFCLK) ? 0 : 1, DPSTREAMCLK0_SRC_SEL, otg_inst);
0282         break;
0283     case 1:
0284         REG_UPDATE_2(DPSTREAMCLK_CNTL, DPSTREAMCLK1_EN,
0285                  (src == REFCLK) ? 0 : 1, DPSTREAMCLK1_SRC_SEL, otg_inst);
0286         break;
0287     case 2:
0288         REG_UPDATE_2(DPSTREAMCLK_CNTL, DPSTREAMCLK2_EN,
0289                  (src == REFCLK) ? 0 : 1, DPSTREAMCLK2_SRC_SEL, otg_inst);
0290         break;
0291     case 3:
0292         REG_UPDATE_2(DPSTREAMCLK_CNTL, DPSTREAMCLK3_EN,
0293                  (src == REFCLK) ? 0 : 1, DPSTREAMCLK3_SRC_SEL, otg_inst);
0294         break;
0295     default:
0296         BREAK_TO_DEBUGGER();
0297         return;
0298     }
0299 }
0300 
0301 void dccg32_otg_add_pixel(struct dccg *dccg,
0302         uint32_t otg_inst)
0303 {
0304     struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
0305 
0306     REG_UPDATE(OTG_PIXEL_RATE_CNTL[otg_inst],
0307             OTG_ADD_PIXEL[otg_inst], 1);
0308 }
0309 
0310 void dccg32_otg_drop_pixel(struct dccg *dccg,
0311         uint32_t otg_inst)
0312 {
0313     struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
0314 
0315     REG_UPDATE(OTG_PIXEL_RATE_CNTL[otg_inst],
0316             OTG_DROP_PIXEL[otg_inst], 1);
0317 }
0318 
0319 static const struct dccg_funcs dccg32_funcs = {
0320     .update_dpp_dto = dccg2_update_dpp_dto,
0321     .get_dccg_ref_freq = dccg32_get_dccg_ref_freq,
0322     .dccg_init = dccg31_init,
0323     .set_dpstreamclk = dccg32_set_dpstreamclk,
0324     .enable_symclk32_se = dccg31_enable_symclk32_se,
0325     .disable_symclk32_se = dccg31_disable_symclk32_se,
0326     .enable_symclk32_le = dccg31_enable_symclk32_le,
0327     .disable_symclk32_le = dccg31_disable_symclk32_le,
0328     .set_physymclk = dccg31_set_physymclk,
0329     .set_dtbclk_dto = dccg32_set_dtbclk_dto,
0330     .set_valid_pixel_rate = dccg32_set_valid_pixel_rate,
0331     .set_fifo_errdet_ovr_en = dccg2_set_fifo_errdet_ovr_en,
0332     .set_audio_dtbclk_dto = dccg31_set_audio_dtbclk_dto,
0333     .otg_add_pixel = dccg32_otg_add_pixel,
0334     .otg_drop_pixel = dccg32_otg_drop_pixel,
0335     .set_pixel_rate_div = dccg32_set_pixel_rate_div,
0336 };
0337 
0338 struct dccg *dccg32_create(
0339     struct dc_context *ctx,
0340     const struct dccg_registers *regs,
0341     const struct dccg_shift *dccg_shift,
0342     const struct dccg_mask *dccg_mask)
0343 {
0344     struct dcn_dccg *dccg_dcn = kzalloc(sizeof(*dccg_dcn), GFP_KERNEL);
0345     struct dccg *base;
0346 
0347     if (dccg_dcn == NULL) {
0348         BREAK_TO_DEBUGGER();
0349         return NULL;
0350     }
0351 
0352     base = &dccg_dcn->base;
0353     base->ctx = ctx;
0354     base->funcs = &dccg32_funcs;
0355 
0356     dccg_dcn->regs = regs;
0357     dccg_dcn->dccg_shift = dccg_shift;
0358     dccg_dcn->dccg_mask = dccg_mask;
0359 
0360     return &dccg_dcn->base;
0361 }