376 lines · c
1/*2 * Copyright 2021 Advanced Micro Devices, Inc.3 *4 * Permission is hereby granted, free of charge, to any person obtaining a5 * copy of this software and associated documentation files (the "Software"),6 * to deal in the Software without restriction, including without limitation7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,8 * and/or sell copies of the Software, and to permit persons to whom the9 * Software is furnished to do so, subject to the following conditions:10 *11 * The above copyright notice and this permission notice shall be included in12 * all copies or substantial portions of the Software.13 *14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR18 * 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 OR20 * OTHER DEALINGS IN THE SOFTWARE.21 *22 * Authors: AMD23 *24 */25 26#include "reg_helper.h"27#include "core_types.h"28#include "dcn32_dccg.h"29 30#define TO_DCN_DCCG(dccg)\31 container_of(dccg, struct dcn_dccg, base)32 33#define REG(reg) \34 (dccg_dcn->regs->reg)35 36#undef FN37#define FN(reg_name, field_name) \38 dccg_dcn->dccg_shift->field_name, dccg_dcn->dccg_mask->field_name39 40#define CTX \41 dccg_dcn->base.ctx42#define DC_LOGGER \43 dccg->ctx->logger44 45static void dccg32_trigger_dio_fifo_resync(46 struct dccg *dccg)47{48 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);49 uint32_t dispclk_rdivider_value = 0;50 51 REG_GET(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_RDIVIDER, &dispclk_rdivider_value);52 53 /* Not valid for the WDIVIDER to be set to 0 */54 if (dispclk_rdivider_value != 0)55 REG_UPDATE(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_WDIVIDER, dispclk_rdivider_value);56}57 58static void dccg32_get_pixel_rate_div(59 struct dccg *dccg,60 uint32_t otg_inst,61 uint32_t *k1,62 uint32_t *k2)63{64 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);65 uint32_t val_k1 = PIXEL_RATE_DIV_NA, val_k2 = PIXEL_RATE_DIV_NA;66 67 *k1 = PIXEL_RATE_DIV_NA;68 *k2 = PIXEL_RATE_DIV_NA;69 70 switch (otg_inst) {71 case 0:72 REG_GET_2(OTG_PIXEL_RATE_DIV,73 OTG0_PIXEL_RATE_DIVK1, &val_k1,74 OTG0_PIXEL_RATE_DIVK2, &val_k2);75 break;76 case 1:77 REG_GET_2(OTG_PIXEL_RATE_DIV,78 OTG1_PIXEL_RATE_DIVK1, &val_k1,79 OTG1_PIXEL_RATE_DIVK2, &val_k2);80 break;81 case 2:82 REG_GET_2(OTG_PIXEL_RATE_DIV,83 OTG2_PIXEL_RATE_DIVK1, &val_k1,84 OTG2_PIXEL_RATE_DIVK2, &val_k2);85 break;86 case 3:87 REG_GET_2(OTG_PIXEL_RATE_DIV,88 OTG3_PIXEL_RATE_DIVK1, &val_k1,89 OTG3_PIXEL_RATE_DIVK2, &val_k2);90 break;91 default:92 BREAK_TO_DEBUGGER();93 return;94 }95 96 *k1 = val_k1;97 *k2 = val_k2;98}99 100static void dccg32_set_pixel_rate_div(101 struct dccg *dccg,102 uint32_t otg_inst,103 enum pixel_rate_div k1,104 enum pixel_rate_div k2)105{106 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);107 uint32_t cur_k1 = PIXEL_RATE_DIV_NA;108 uint32_t cur_k2 = PIXEL_RATE_DIV_NA;109 110 // Don't program 0xF into the register field. Not valid since111 // K1 / K2 field is only 1 / 2 bits wide112 if (k1 == PIXEL_RATE_DIV_NA || k2 == PIXEL_RATE_DIV_NA) {113 BREAK_TO_DEBUGGER();114 return;115 }116 117 dccg32_get_pixel_rate_div(dccg, otg_inst, &cur_k1, &cur_k2);118 if (k1 == cur_k1 && k2 == cur_k2)119 return;120 121 switch (otg_inst) {122 case 0:123 REG_UPDATE_2(OTG_PIXEL_RATE_DIV,124 OTG0_PIXEL_RATE_DIVK1, k1,125 OTG0_PIXEL_RATE_DIVK2, k2);126 break;127 case 1:128 REG_UPDATE_2(OTG_PIXEL_RATE_DIV,129 OTG1_PIXEL_RATE_DIVK1, k1,130 OTG1_PIXEL_RATE_DIVK2, k2);131 break;132 case 2:133 REG_UPDATE_2(OTG_PIXEL_RATE_DIV,134 OTG2_PIXEL_RATE_DIVK1, k1,135 OTG2_PIXEL_RATE_DIVK2, k2);136 break;137 case 3:138 REG_UPDATE_2(OTG_PIXEL_RATE_DIV,139 OTG3_PIXEL_RATE_DIVK1, k1,140 OTG3_PIXEL_RATE_DIVK2, k2);141 break;142 default:143 BREAK_TO_DEBUGGER();144 return;145 }146}147 148static void dccg32_set_dtbclk_p_src(149 struct dccg *dccg,150 enum streamclk_source src,151 uint32_t otg_inst)152{153 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);154 155 uint32_t p_src_sel = 0; /* selects dprefclk */156 if (src == DTBCLK0)157 p_src_sel = 2; /* selects dtbclk0 */158 159 switch (otg_inst) {160 case 0:161 if (src == REFCLK)162 REG_UPDATE(DTBCLK_P_CNTL,163 DTBCLK_P0_EN, 0);164 else165 REG_UPDATE_2(DTBCLK_P_CNTL,166 DTBCLK_P0_SRC_SEL, p_src_sel,167 DTBCLK_P0_EN, 1);168 break;169 case 1:170 if (src == REFCLK)171 REG_UPDATE(DTBCLK_P_CNTL,172 DTBCLK_P1_EN, 0);173 else174 REG_UPDATE_2(DTBCLK_P_CNTL,175 DTBCLK_P1_SRC_SEL, p_src_sel,176 DTBCLK_P1_EN, 1);177 break;178 case 2:179 if (src == REFCLK)180 REG_UPDATE(DTBCLK_P_CNTL,181 DTBCLK_P2_EN, 0);182 else183 REG_UPDATE_2(DTBCLK_P_CNTL,184 DTBCLK_P2_SRC_SEL, p_src_sel,185 DTBCLK_P2_EN, 1);186 break;187 case 3:188 if (src == REFCLK)189 REG_UPDATE(DTBCLK_P_CNTL,190 DTBCLK_P3_EN, 0);191 else192 REG_UPDATE_2(DTBCLK_P_CNTL,193 DTBCLK_P3_SRC_SEL, p_src_sel,194 DTBCLK_P3_EN, 1);195 break;196 default:197 BREAK_TO_DEBUGGER();198 return;199 }200 201}202 203/* Controls the generation of pixel valid for OTG in (OTG -> HPO case) */204static void dccg32_set_dtbclk_dto(205 struct dccg *dccg,206 const struct dtbclk_dto_params *params)207{208 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);209 /* DTO Output Rate / Pixel Rate = 1/4 */210 int req_dtbclk_khz = params->pixclk_khz / 4;211 212 if (params->ref_dtbclk_khz && req_dtbclk_khz) {213 uint32_t modulo, phase;214 215 // phase / modulo = dtbclk / dtbclk ref216 modulo = params->ref_dtbclk_khz * 1000;217 phase = req_dtbclk_khz * 1000;218 219 REG_WRITE(DTBCLK_DTO_MODULO[params->otg_inst], modulo);220 REG_WRITE(DTBCLK_DTO_PHASE[params->otg_inst], phase);221 222 REG_UPDATE(OTG_PIXEL_RATE_CNTL[params->otg_inst],223 DTBCLK_DTO_ENABLE[params->otg_inst], 1);224 225 REG_WAIT(OTG_PIXEL_RATE_CNTL[params->otg_inst],226 DTBCLKDTO_ENABLE_STATUS[params->otg_inst], 1,227 1, 100);228 229 /* program OTG_PIXEL_RATE_DIV for DIVK1 and DIVK2 fields */230 dccg32_set_pixel_rate_div(dccg, params->otg_inst, PIXEL_RATE_DIV_BY_1, PIXEL_RATE_DIV_BY_1);231 232 /* The recommended programming sequence to enable DTBCLK DTO to generate233 * valid pixel HPO DPSTREAM ENCODER, specifies that DTO source select should234 * be set only after DTO is enabled235 */236 REG_UPDATE(OTG_PIXEL_RATE_CNTL[params->otg_inst],237 PIPE_DTO_SRC_SEL[params->otg_inst], 2);238 } else {239 REG_UPDATE_2(OTG_PIXEL_RATE_CNTL[params->otg_inst],240 DTBCLK_DTO_ENABLE[params->otg_inst], 0,241 PIPE_DTO_SRC_SEL[params->otg_inst], params->is_hdmi ? 0 : 1);242 REG_WRITE(DTBCLK_DTO_MODULO[params->otg_inst], 0);243 REG_WRITE(DTBCLK_DTO_PHASE[params->otg_inst], 0);244 }245}246 247static void dccg32_set_valid_pixel_rate(248 struct dccg *dccg,249 int ref_dtbclk_khz,250 int otg_inst,251 int pixclk_khz)252{253 struct dtbclk_dto_params dto_params = {0};254 255 dto_params.ref_dtbclk_khz = ref_dtbclk_khz;256 dto_params.otg_inst = otg_inst;257 dto_params.pixclk_khz = pixclk_khz;258 dto_params.is_hdmi = true;259 260 dccg32_set_dtbclk_dto(dccg, &dto_params);261}262 263static void dccg32_get_dccg_ref_freq(struct dccg *dccg,264 unsigned int xtalin_freq_inKhz,265 unsigned int *dccg_ref_freq_inKhz)266{267 /*268 * Assume refclk is sourced from xtalin269 * expect 100MHz270 */271 *dccg_ref_freq_inKhz = xtalin_freq_inKhz;272 return;273}274 275static void dccg32_set_dpstreamclk(276 struct dccg *dccg,277 enum streamclk_source src,278 int otg_inst,279 int dp_hpo_inst)280{281 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);282 283 /* set the dtbclk_p source */284 /* always program refclk as DTBCLK. No use-case expected to require DPREFCLK as refclk */285 dccg32_set_dtbclk_p_src(dccg, DTBCLK0, otg_inst);286 287 /* enabled to select one of the DTBCLKs for pipe */288 switch (dp_hpo_inst) {289 case 0:290 REG_UPDATE_2(DPSTREAMCLK_CNTL,291 DPSTREAMCLK0_EN,292 (src == REFCLK) ? 0 : 1, DPSTREAMCLK0_SRC_SEL, otg_inst);293 break;294 case 1:295 REG_UPDATE_2(DPSTREAMCLK_CNTL, DPSTREAMCLK1_EN,296 (src == REFCLK) ? 0 : 1, DPSTREAMCLK1_SRC_SEL, otg_inst);297 break;298 case 2:299 REG_UPDATE_2(DPSTREAMCLK_CNTL, DPSTREAMCLK2_EN,300 (src == REFCLK) ? 0 : 1, DPSTREAMCLK2_SRC_SEL, otg_inst);301 break;302 case 3:303 REG_UPDATE_2(DPSTREAMCLK_CNTL, DPSTREAMCLK3_EN,304 (src == REFCLK) ? 0 : 1, DPSTREAMCLK3_SRC_SEL, otg_inst);305 break;306 default:307 BREAK_TO_DEBUGGER();308 return;309 }310}311 312static void dccg32_otg_add_pixel(struct dccg *dccg,313 uint32_t otg_inst)314{315 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);316 317 REG_UPDATE(OTG_PIXEL_RATE_CNTL[otg_inst],318 OTG_ADD_PIXEL[otg_inst], 1);319}320 321static void dccg32_otg_drop_pixel(struct dccg *dccg,322 uint32_t otg_inst)323{324 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);325 326 REG_UPDATE(OTG_PIXEL_RATE_CNTL[otg_inst],327 OTG_DROP_PIXEL[otg_inst], 1);328}329 330static const struct dccg_funcs dccg32_funcs = {331 .update_dpp_dto = dccg2_update_dpp_dto,332 .get_dccg_ref_freq = dccg32_get_dccg_ref_freq,333 .dccg_init = dccg31_init,334 .set_dpstreamclk = dccg32_set_dpstreamclk,335 .enable_symclk32_se = dccg31_enable_symclk32_se,336 .disable_symclk32_se = dccg31_disable_symclk32_se,337 .enable_symclk32_le = dccg31_enable_symclk32_le,338 .disable_symclk32_le = dccg31_disable_symclk32_le,339 .set_physymclk = dccg31_set_physymclk,340 .set_dtbclk_dto = dccg32_set_dtbclk_dto,341 .set_valid_pixel_rate = dccg32_set_valid_pixel_rate,342 .set_fifo_errdet_ovr_en = dccg2_set_fifo_errdet_ovr_en,343 .set_audio_dtbclk_dto = dccg31_set_audio_dtbclk_dto,344 .otg_add_pixel = dccg32_otg_add_pixel,345 .otg_drop_pixel = dccg32_otg_drop_pixel,346 .set_pixel_rate_div = dccg32_set_pixel_rate_div,347 .get_pixel_rate_div = dccg32_get_pixel_rate_div,348 .trigger_dio_fifo_resync = dccg32_trigger_dio_fifo_resync,349 .set_dtbclk_p_src = dccg32_set_dtbclk_p_src,350};351 352struct dccg *dccg32_create(353 struct dc_context *ctx,354 const struct dccg_registers *regs,355 const struct dccg_shift *dccg_shift,356 const struct dccg_mask *dccg_mask)357{358 struct dcn_dccg *dccg_dcn = kzalloc(sizeof(*dccg_dcn), GFP_KERNEL);359 struct dccg *base;360 361 if (dccg_dcn == NULL) {362 BREAK_TO_DEBUGGER();363 return NULL;364 }365 366 base = &dccg_dcn->base;367 base->ctx = ctx;368 base->funcs = &dccg32_funcs;369 370 dccg_dcn->regs = regs;371 dccg_dcn->dccg_shift = dccg_shift;372 dccg_dcn->dccg_mask = dccg_mask;373 374 return &dccg_dcn->base;375}376