13515Sache// SPDX-License-Identifier: MIT 23515Sache/* 33515Sache * Copyright 2022 Advanced Micro Devices, Inc. 43515Sache * 53515Sache * Permission is hereby granted, free of charge, to any person obtaining a 612983Sjkh * copy of this software and associated documentation files (the "Software"), 712983Sjkh * to deal in the Software without restriction, including without limitation 83515Sache * the rights to use, copy, modify, merge, publish, distribute, sublicense, 93515Sache * and/or sell copies of the Software, and to permit persons to whom the 103515Sache * Software is furnished to do so, subject to the following conditions: 113515Sache * 123515Sache * The above copyright notice and this permission notice shall be included in 133515Sache * all copies or substantial portions of the Software. 143515Sache * 153515Sache * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 163515Sache * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 173515Sache * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 183515Sache * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 193515Sache * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 203515Sache * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 2154585Sjkh * OTHER DEALINGS IN THE SOFTWARE. 223515Sache * 233515Sache * Authors: AMD 2454585Sjkh * 2554585Sjkh */ 2654585Sjkh 273515Sache#include "reg_helper.h" 283740Sache#include "core_types.h" 293515Sache 303515Sache#include "dcn31/dcn31_dccg.h" 313515Sache#include "dcn314_dccg.h" 3230333Sjkh 333515Sache#define TO_DCN_DCCG(dccg)\ 3412983Sjkh container_of(dccg, struct dcn_dccg, base) 353515Sache 363515Sache#define REG(reg) \ 373515Sache (dccg_dcn->regs->reg) 383515Sache 3913135Sjkh#undef FN 4013135Sjkh#define FN(reg_name, field_name) \ 4115322Sjkh dccg_dcn->dccg_shift->field_name, dccg_dcn->dccg_mask->field_name 423515Sache 4321790Sjkh#define CTX \ 4421790Sjkh dccg_dcn->base.ctx 4515273Sjkh#define DC_LOGGER \ 4621790Sjkh dccg->ctx->logger 4715273Sjkh 4815289Sjkhstatic void dccg314_trigger_dio_fifo_resync( 4915322Sjkh struct dccg *dccg) 5015273Sjkh{ 5130333Sjkh struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); 5230333Sjkh uint32_t dispclk_rdivider_value = 0; 5315273Sjkh 5415376Sjkh REG_GET(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_RDIVIDER, &dispclk_rdivider_value); 5515273Sjkh REG_UPDATE(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_WDIVIDER, dispclk_rdivider_value); 5615273Sjkh} 5715273Sjkh 5815273Sjkhstatic void dccg314_get_pixel_rate_div( 5915273Sjkh struct dccg *dccg, 6015322Sjkh uint32_t otg_inst, 6121790Sjkh enum pixel_rate_div *k1, 6215273Sjkh enum pixel_rate_div *k2) 6315322Sjkh{ 6415273Sjkh struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); 6515273Sjkh uint32_t val_k1 = PIXEL_RATE_DIV_NA, val_k2 = PIXEL_RATE_DIV_NA; 6615322Sjkh 6715273Sjkh *k1 = PIXEL_RATE_DIV_NA; 6815273Sjkh *k2 = PIXEL_RATE_DIV_NA; 6915273Sjkh 7015273Sjkh switch (otg_inst) { 7115273Sjkh case 0: 7215273Sjkh REG_GET_2(OTG_PIXEL_RATE_DIV, 7315322Sjkh OTG0_PIXEL_RATE_DIVK1, &val_k1, 7415273Sjkh OTG0_PIXEL_RATE_DIVK2, &val_k2); 7515322Sjkh break; 7615322Sjkh case 1: 7715273Sjkh REG_GET_2(OTG_PIXEL_RATE_DIV, 7815273Sjkh OTG1_PIXEL_RATE_DIVK1, &val_k1, 7915273Sjkh OTG1_PIXEL_RATE_DIVK2, &val_k2); 8015273Sjkh break; 8115273Sjkh case 2: 8215273Sjkh REG_GET_2(OTG_PIXEL_RATE_DIV, 8315273Sjkh OTG2_PIXEL_RATE_DIVK1, &val_k1, 8415273Sjkh OTG2_PIXEL_RATE_DIVK2, &val_k2); 8515273Sjkh break; 8615273Sjkh case 3: 8715273Sjkh REG_GET_2(OTG_PIXEL_RATE_DIV, 8815273Sjkh OTG3_PIXEL_RATE_DIVK1, &val_k1, 8915273Sjkh OTG3_PIXEL_RATE_DIVK2, &val_k2); 9015273Sjkh break; 9112983Sjkh default: 9215273Sjkh BREAK_TO_DEBUGGER(); 9315273Sjkh return; 9415273Sjkh } 9515273Sjkh 9615273Sjkh *k1 = (enum pixel_rate_div)val_k1; 9715273Sjkh *k2 = (enum pixel_rate_div)val_k2; 9812983Sjkh} 9915273Sjkh 10015273Sjkhstatic void dccg314_set_pixel_rate_div( 10115273Sjkh struct dccg *dccg, 10215273Sjkh uint32_t otg_inst, 10315273Sjkh enum pixel_rate_div k1, 10415273Sjkh enum pixel_rate_div k2) 10515273Sjkh{ 1064565Sache struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); 10715273Sjkh enum pixel_rate_div cur_k1 = PIXEL_RATE_DIV_NA, cur_k2 = PIXEL_RATE_DIV_NA; 10815273Sjkh 10915273Sjkh // Don't program 0xF into the register field. Not valid since 11015273Sjkh // K1 / K2 field is only 1 / 2 bits wide 11115273Sjkh if (k1 == PIXEL_RATE_DIV_NA || k2 == PIXEL_RATE_DIV_NA) { 11215273Sjkh BREAK_TO_DEBUGGER(); 11315273Sjkh return; 11415273Sjkh } 11515273Sjkh 1164527Sache dccg314_get_pixel_rate_div(dccg, otg_inst, &cur_k1, &cur_k2); 1173515Sache if (k1 == cur_k1 && k2 == cur_k2) 11815273Sjkh return; 11915273Sjkh 1203515Sache switch (otg_inst) { 12115273Sjkh case 0: 12215273Sjkh REG_UPDATE_2(OTG_PIXEL_RATE_DIV, 12315273Sjkh OTG0_PIXEL_RATE_DIVK1, k1, 12415273Sjkh OTG0_PIXEL_RATE_DIVK2, k2); 12515273Sjkh break; 12615273Sjkh case 1: 12715273Sjkh REG_UPDATE_2(OTG_PIXEL_RATE_DIV, 12815273Sjkh OTG1_PIXEL_RATE_DIVK1, k1, 12915273Sjkh OTG1_PIXEL_RATE_DIVK2, k2); 13015273Sjkh break; 13115273Sjkh case 2: 13215273Sjkh REG_UPDATE_2(OTG_PIXEL_RATE_DIV, 13315273Sjkh OTG2_PIXEL_RATE_DIVK1, k1, 13415273Sjkh OTG2_PIXEL_RATE_DIVK2, k2); 13515273Sjkh break; 13615273Sjkh case 3: 13715273Sjkh REG_UPDATE_2(OTG_PIXEL_RATE_DIV, 13815273Sjkh OTG3_PIXEL_RATE_DIVK1, k1, 13915273Sjkh OTG3_PIXEL_RATE_DIVK2, k2); 14015273Sjkh break; 14115273Sjkh default: 14215273Sjkh BREAK_TO_DEBUGGER(); 14315273Sjkh return; 14415273Sjkh } 14515273Sjkh} 14615273Sjkh 14715273Sjkhstatic void dccg314_set_dtbclk_p_src( 14815273Sjkh struct dccg *dccg, 14915273Sjkh enum streamclk_source src, 15015273Sjkh uint32_t otg_inst) 15115273Sjkh{ 15215273Sjkh struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); 15315273Sjkh 15415273Sjkh uint32_t p_src_sel = 0; /* selects dprefclk */ 15515273Sjkh 15615273Sjkh if (src == DTBCLK0) 15715273Sjkh p_src_sel = 2; /* selects dtbclk0 */ 15815273Sjkh 15915273Sjkh switch (otg_inst) { 16012983Sjkh case 0: 16115273Sjkh if (src == REFCLK) 16215273Sjkh REG_UPDATE(DTBCLK_P_CNTL, 16315273Sjkh DTBCLK_P0_EN, 0); 16415273Sjkh else 16512983Sjkh REG_UPDATE_2(DTBCLK_P_CNTL, 16615273Sjkh DTBCLK_P0_SRC_SEL, p_src_sel, 16715273Sjkh DTBCLK_P0_EN, 1); 16815273Sjkh break; 16915273Sjkh case 1: 17015273Sjkh if (src == REFCLK) 17115273Sjkh REG_UPDATE(DTBCLK_P_CNTL, 17215273Sjkh DTBCLK_P1_EN, 0); 17315273Sjkh else 17415273Sjkh REG_UPDATE_2(DTBCLK_P_CNTL, 17515273Sjkh DTBCLK_P1_SRC_SEL, p_src_sel, 17630333Sjkh DTBCLK_P1_EN, 1); 17715273Sjkh break; 17815273Sjkh case 2: 17915273Sjkh if (src == REFCLK) 18021790Sjkh REG_UPDATE(DTBCLK_P_CNTL, 18115273Sjkh DTBCLK_P2_EN, 0); 18221790Sjkh else 18321790Sjkh REG_UPDATE_2(DTBCLK_P_CNTL, 18415273Sjkh DTBCLK_P2_SRC_SEL, p_src_sel, 18515273Sjkh DTBCLK_P2_EN, 1); 18615273Sjkh break; 18715273Sjkh case 3: 18815273Sjkh if (src == REFCLK) 18915273Sjkh REG_UPDATE(DTBCLK_P_CNTL, 19015273Sjkh DTBCLK_P3_EN, 0); 19115273Sjkh else 19215273Sjkh REG_UPDATE_2(DTBCLK_P_CNTL, 19315273Sjkh DTBCLK_P3_SRC_SEL, p_src_sel, 19415273Sjkh DTBCLK_P3_EN, 1); 19515273Sjkh break; 19615273Sjkh default: 19715273Sjkh BREAK_TO_DEBUGGER(); 19815273Sjkh return; 19915273Sjkh } 20015273Sjkh 20115273Sjkh} 20215273Sjkh 20315273Sjkh/* Controls the generation of pixel valid for OTG in (OTG -> HPO case) */ 20415273Sjkhstatic void dccg314_set_dtbclk_dto( 20515273Sjkh struct dccg *dccg, 20615273Sjkh const struct dtbclk_dto_params *params) 20715273Sjkh{ 20817092Sjkh struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); 20917092Sjkh /* DTO Output Rate / Pixel Rate = 1/4 */ 21017092Sjkh int req_dtbclk_khz = params->pixclk_khz / 4; 21117092Sjkh 21215289Sjkh if (params->ref_dtbclk_khz && req_dtbclk_khz) { 21317092Sjkh uint32_t modulo, phase; 21417092Sjkh 21517092Sjkh // phase / modulo = dtbclk / dtbclk ref 21617092Sjkh modulo = params->ref_dtbclk_khz * 1000; 21717092Sjkh phase = req_dtbclk_khz * 1000; 21817092Sjkh 21917092Sjkh REG_WRITE(DTBCLK_DTO_MODULO[params->otg_inst], modulo); 22015273Sjkh REG_WRITE(DTBCLK_DTO_PHASE[params->otg_inst], phase); 22115273Sjkh 22215418Sjkh REG_UPDATE(OTG_PIXEL_RATE_CNTL[params->otg_inst], 22315273Sjkh DTBCLK_DTO_ENABLE[params->otg_inst], 1); 22415273Sjkh 22515273Sjkh REG_WAIT(OTG_PIXEL_RATE_CNTL[params->otg_inst], 22615273Sjkh DTBCLKDTO_ENABLE_STATUS[params->otg_inst], 1, 22715273Sjkh 1, 100); 22815273Sjkh 22915273Sjkh /* program OTG_PIXEL_RATE_DIV for DIVK1 and DIVK2 fields */ 23015273Sjkh dccg314_set_pixel_rate_div(dccg, params->otg_inst, PIXEL_RATE_DIV_BY_1, PIXEL_RATE_DIV_BY_1); 23121790Sjkh 23221790Sjkh /* The recommended programming sequence to enable DTBCLK DTO to generate 23321790Sjkh * valid pixel HPO DPSTREAM ENCODER, specifies that DTO source select should 23415142Sjkh * be set only after DTO is enabled 23521790Sjkh */ 23615273Sjkh REG_UPDATE(OTG_PIXEL_RATE_CNTL[params->otg_inst], 23721790Sjkh PIPE_DTO_SRC_SEL[params->otg_inst], 2); 23815273Sjkh } else { 23915273Sjkh REG_UPDATE_2(OTG_PIXEL_RATE_CNTL[params->otg_inst], 24015289Sjkh DTBCLK_DTO_ENABLE[params->otg_inst], 0, 24112983Sjkh PIPE_DTO_SRC_SEL[params->otg_inst], 1); 24215289Sjkh 24315273Sjkh REG_WRITE(DTBCLK_DTO_MODULO[params->otg_inst], 0); 24415289Sjkh REG_WRITE(DTBCLK_DTO_PHASE[params->otg_inst], 0); 24515273Sjkh } 24615273Sjkh} 24715354Sjkh 24815273Sjkhvoid dccg314_set_dpstreamclk( 24915289Sjkh struct dccg *dccg, 25015273Sjkh enum streamclk_source src, 25121790Sjkh int otg_inst, 25221790Sjkh int dp_hpo_inst) 25321790Sjkh{ 25415273Sjkh struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); 25515273Sjkh 25615273Sjkh /* set the dtbclk_p source */ 25715273Sjkh dccg314_set_dtbclk_p_src(dccg, src, otg_inst); 25854720Sjkh 25915273Sjkh /* enabled to select one of the DTBCLKs for pipe */ 26054585Sjkh switch (dp_hpo_inst) { 26121790Sjkh case 0: 26221790Sjkh REG_UPDATE_2(DPSTREAMCLK_CNTL, 26312983Sjkh DPSTREAMCLK0_EN, (src == REFCLK) ? 0 : 1, 26415273Sjkh DPSTREAMCLK0_SRC_SEL, otg_inst); 26515273Sjkh break; 26615273Sjkh case 1: 26721790Sjkh REG_UPDATE_2(DPSTREAMCLK_CNTL, 26815273Sjkh DPSTREAMCLK1_EN, (src == REFCLK) ? 0 : 1, 26915273Sjkh DPSTREAMCLK1_SRC_SEL, otg_inst); 27015273Sjkh break; 27115273Sjkh case 2: 27215273Sjkh REG_UPDATE_2(DPSTREAMCLK_CNTL, 27315273Sjkh DPSTREAMCLK2_EN, (src == REFCLK) ? 0 : 1, 27421790Sjkh DPSTREAMCLK2_SRC_SEL, otg_inst); 27530333Sjkh break; 27615273Sjkh case 3: 27715273Sjkh REG_UPDATE_2(DPSTREAMCLK_CNTL, 27815273Sjkh DPSTREAMCLK3_EN, (src == REFCLK) ? 0 : 1, 27915273Sjkh DPSTREAMCLK3_SRC_SEL, otg_inst); 28015273Sjkh break; 28121790Sjkh default: 28230333Sjkh BREAK_TO_DEBUGGER(); 28315273Sjkh return; 28415273Sjkh } 28515273Sjkh} 28615273Sjkh 28715273Sjkhstatic void dccg314_init(struct dccg *dccg) 28815273Sjkh{ 28915273Sjkh int otg_inst; 29015273Sjkh 29115273Sjkh /* Set HPO stream encoder to use refclk to avoid case where PHY is 29221790Sjkh * disabled and SYMCLK32 for HPO SE is sourced from PHYD32CLK which 29315273Sjkh * will cause DCN to hang. 29421790Sjkh */ 29515273Sjkh for (otg_inst = 0; otg_inst < 4; otg_inst++) 29615273Sjkh dccg31_disable_symclk32_se(dccg, otg_inst); 29715273Sjkh 29815273Sjkh if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le) 29921790Sjkh for (otg_inst = 0; otg_inst < 2; otg_inst++) 30021790Sjkh dccg31_disable_symclk32_le(dccg, otg_inst); 30121790Sjkh 30230333Sjkh if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream) 30315273Sjkh for (otg_inst = 0; otg_inst < 4; otg_inst++) 30415273Sjkh dccg314_set_dpstreamclk(dccg, REFCLK, otg_inst, 30515273Sjkh otg_inst); 30615273Sjkh 30715273Sjkh if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk) 30821790Sjkh for (otg_inst = 0; otg_inst < 5; otg_inst++) 30921790Sjkh dccg31_set_physymclk(dccg, otg_inst, 31021790Sjkh PHYSYMCLK_FORCE_SRC_SYMCLK, false); 31130333Sjkh} 31215273Sjkh 31315273Sjkhstatic void dccg314_set_valid_pixel_rate( 31415273Sjkh struct dccg *dccg, 31515273Sjkh int ref_dtbclk_khz, 31615273Sjkh int otg_inst, 31715273Sjkh int pixclk_khz) 31815273Sjkh{ 31915273Sjkh struct dtbclk_dto_params dto_params = {0}; 32015273Sjkh 32115273Sjkh dto_params.ref_dtbclk_khz = ref_dtbclk_khz; 32215273Sjkh dto_params.otg_inst = otg_inst; 32315273Sjkh dto_params.pixclk_khz = pixclk_khz; 32415273Sjkh 32515289Sjkh dccg314_set_dtbclk_dto(dccg, &dto_params); 32615289Sjkh} 32715289Sjkh 32812983Sjkhstatic void dccg314_dpp_root_clock_control( 32915289Sjkh struct dccg *dccg, 33021790Sjkh unsigned int dpp_inst, 33115380Sjkh bool clock_on) 33215380Sjkh{ 33315380Sjkh struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); 33415380Sjkh 33521790Sjkh if (dccg->dpp_clock_gated[dpp_inst] != clock_on) 33615273Sjkh return; 33721790Sjkh 33815323Sjkh if (clock_on) { 33915323Sjkh /* turn off the DTO and leave phase/modulo at max */ 34015289Sjkh REG_UPDATE(DPPCLK_DTO_CTRL, DPPCLK_DTO_ENABLE[dpp_inst], 0); 34115289Sjkh REG_SET_2(DPPCLK_DTO_PARAM[dpp_inst], 0, 34230333Sjkh DPPCLK0_DTO_PHASE, 0xFF, 34315289Sjkh DPPCLK0_DTO_MODULO, 0xFF); 34415273Sjkh } else { 34515289Sjkh /* turn on the DTO to generate a 0hz clock */ 34615289Sjkh REG_UPDATE(DPPCLK_DTO_CTRL, DPPCLK_DTO_ENABLE[dpp_inst], 1); 34715273Sjkh REG_SET_2(DPPCLK_DTO_PARAM[dpp_inst], 0, 34815273Sjkh DPPCLK0_DTO_PHASE, 0, 34915289Sjkh DPPCLK0_DTO_MODULO, 1); 35015273Sjkh } 35115273Sjkh 35221790Sjkh dccg->dpp_clock_gated[dpp_inst] = !clock_on; 35315273Sjkh} 35415273Sjkh 35515382Sjkhstatic const struct dccg_funcs dccg314_funcs = { 35615382Sjkh .update_dpp_dto = dccg31_update_dpp_dto, 35715382Sjkh .dpp_root_clock_control = dccg314_dpp_root_clock_control, 35816973Sjkh .get_dccg_ref_freq = dccg31_get_dccg_ref_freq, 35915382Sjkh .dccg_init = dccg314_init, 36015382Sjkh .set_dpstreamclk = dccg314_set_dpstreamclk, 36115273Sjkh .enable_symclk32_se = dccg31_enable_symclk32_se, 36215306Sjkh .disable_symclk32_se = dccg31_disable_symclk32_se, 36315306Sjkh .enable_symclk32_le = dccg31_enable_symclk32_le, 36415306Sjkh .disable_symclk32_le = dccg31_disable_symclk32_le, 36515306Sjkh .set_symclk32_le_root_clock_gating = dccg31_set_symclk32_le_root_clock_gating, 36615306Sjkh .set_physymclk = dccg31_set_physymclk, 36715273Sjkh .set_dtbclk_dto = dccg314_set_dtbclk_dto, 36815273Sjkh .set_audio_dtbclk_dto = dccg31_set_audio_dtbclk_dto, 36915306Sjkh .set_fifo_errdet_ovr_en = dccg2_set_fifo_errdet_ovr_en, 37015273Sjkh .otg_add_pixel = dccg31_otg_add_pixel, 37115273Sjkh .otg_drop_pixel = dccg31_otg_drop_pixel, 37215273Sjkh .set_dispclk_change_mode = dccg31_set_dispclk_change_mode, 37315273Sjkh .disable_dsc = dccg31_disable_dscclk, 37415273Sjkh .enable_dsc = dccg31_enable_dscclk, 37515273Sjkh .set_pixel_rate_div = dccg314_set_pixel_rate_div, 37615273Sjkh .trigger_dio_fifo_resync = dccg314_trigger_dio_fifo_resync, 37715273Sjkh .set_valid_pixel_rate = dccg314_set_valid_pixel_rate, 37815273Sjkh .set_dtbclk_p_src = dccg314_set_dtbclk_p_src 37921790Sjkh}; 38015273Sjkh 38115273Sjkhstruct dccg *dccg314_create( 38215273Sjkh struct dc_context *ctx, 38315273Sjkh const struct dccg_registers *regs, 38412983Sjkh const struct dccg_shift *dccg_shift, 38515273Sjkh const struct dccg_mask *dccg_mask) 38615273Sjkh{ 38715273Sjkh struct dcn_dccg *dccg_dcn = kzalloc(sizeof(*dccg_dcn), GFP_KERNEL); 38815273Sjkh struct dccg *base; 38921790Sjkh 39030333Sjkh if (dccg_dcn == NULL) { 39115273Sjkh BREAK_TO_DEBUGGER(); 39215273Sjkh return NULL; 39315273Sjkh } 39430333Sjkh 39515273Sjkh base = &dccg_dcn->base; 39615273Sjkh base->ctx = ctx; 39715273Sjkh base->funcs = &dccg314_funcs; 39815142Sjkh 39915273Sjkh dccg_dcn->regs = regs; 40015273Sjkh dccg_dcn->dccg_shift = dccg_shift; 40115273Sjkh dccg_dcn->dccg_mask = dccg_mask; 40215273Sjkh 40315273Sjkh return &dccg_dcn->base; 40415273Sjkh} 40515273Sjkh