1 // SPDX-License-Identifier: MIT 2 /* 3 * Copyright 2022 Advanced Micro Devices, Inc. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 * and/or sell copies of the Software, and to permit persons to whom the 10 * Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be included in 13 * all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 19 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 20 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 21 * OTHER DEALINGS IN THE SOFTWARE. 22 * 23 * Authors: AMD 24 * 25 */ 26 27 #include "reg_helper.h" 28 #include "core_types.h" 29 30 #include "dcn31/dcn31_dccg.h" 31 #include "dcn314_dccg.h" 32 33 #define TO_DCN_DCCG(dccg)\ 34 container_of(dccg, struct dcn_dccg, base) 35 36 #define REG(reg) \ 37 (dccg_dcn->regs->reg) 38 39 #undef FN 40 #define FN(reg_name, field_name) \ 41 dccg_dcn->dccg_shift->field_name, dccg_dcn->dccg_mask->field_name 42 43 #define CTX \ 44 dccg_dcn->base.ctx 45 #define DC_LOGGER \ 46 dccg->ctx->logger 47 48 static void dccg314_get_pixel_rate_div( 49 struct dccg *dccg, 50 uint32_t otg_inst, 51 enum pixel_rate_div *k1, 52 enum pixel_rate_div *k2) 53 { 54 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); 55 uint32_t val_k1 = PIXEL_RATE_DIV_NA, val_k2 = PIXEL_RATE_DIV_NA; 56 57 *k1 = PIXEL_RATE_DIV_NA; 58 *k2 = PIXEL_RATE_DIV_NA; 59 60 switch (otg_inst) { 61 case 0: 62 REG_GET_2(OTG_PIXEL_RATE_DIV, 63 OTG0_PIXEL_RATE_DIVK1, &val_k1, 64 OTG0_PIXEL_RATE_DIVK2, &val_k2); 65 break; 66 case 1: 67 REG_GET_2(OTG_PIXEL_RATE_DIV, 68 OTG1_PIXEL_RATE_DIVK1, &val_k1, 69 OTG1_PIXEL_RATE_DIVK2, &val_k2); 70 break; 71 case 2: 72 REG_GET_2(OTG_PIXEL_RATE_DIV, 73 OTG2_PIXEL_RATE_DIVK1, &val_k1, 74 OTG2_PIXEL_RATE_DIVK2, &val_k2); 75 break; 76 case 3: 77 REG_GET_2(OTG_PIXEL_RATE_DIV, 78 OTG3_PIXEL_RATE_DIVK1, &val_k1, 79 OTG3_PIXEL_RATE_DIVK2, &val_k2); 80 break; 81 default: 82 BREAK_TO_DEBUGGER(); 83 return; 84 } 85 86 *k1 = (enum pixel_rate_div)val_k1; 87 *k2 = (enum pixel_rate_div)val_k2; 88 } 89 90 static void dccg314_set_pixel_rate_div( 91 struct dccg *dccg, 92 uint32_t otg_inst, 93 enum pixel_rate_div k1, 94 enum pixel_rate_div k2) 95 { 96 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); 97 enum pixel_rate_div cur_k1 = PIXEL_RATE_DIV_NA, cur_k2 = PIXEL_RATE_DIV_NA; 98 99 dccg314_get_pixel_rate_div(dccg, otg_inst, &cur_k1, &cur_k2); 100 if (k1 == PIXEL_RATE_DIV_NA || k2 == PIXEL_RATE_DIV_NA || (k1 == cur_k1 && k2 == cur_k2)) 101 return; 102 103 switch (otg_inst) { 104 case 0: 105 REG_UPDATE_2(OTG_PIXEL_RATE_DIV, 106 OTG0_PIXEL_RATE_DIVK1, k1, 107 OTG0_PIXEL_RATE_DIVK2, k2); 108 break; 109 case 1: 110 REG_UPDATE_2(OTG_PIXEL_RATE_DIV, 111 OTG1_PIXEL_RATE_DIVK1, k1, 112 OTG1_PIXEL_RATE_DIVK2, k2); 113 break; 114 case 2: 115 REG_UPDATE_2(OTG_PIXEL_RATE_DIV, 116 OTG2_PIXEL_RATE_DIVK1, k1, 117 OTG2_PIXEL_RATE_DIVK2, k2); 118 break; 119 case 3: 120 REG_UPDATE_2(OTG_PIXEL_RATE_DIV, 121 OTG3_PIXEL_RATE_DIVK1, k1, 122 OTG3_PIXEL_RATE_DIVK2, k2); 123 break; 124 default: 125 BREAK_TO_DEBUGGER(); 126 return; 127 } 128 } 129 130 static void dccg314_set_dtbclk_p_src( 131 struct dccg *dccg, 132 enum streamclk_source src, 133 uint32_t otg_inst) 134 { 135 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); 136 137 uint32_t p_src_sel = 0; /* selects dprefclk */ 138 139 if (src == DTBCLK0) 140 p_src_sel = 2; /* selects dtbclk0 */ 141 142 switch (otg_inst) { 143 case 0: 144 if (src == REFCLK) 145 REG_UPDATE(DTBCLK_P_CNTL, 146 DTBCLK_P0_EN, 0); 147 else 148 REG_UPDATE_2(DTBCLK_P_CNTL, 149 DTBCLK_P0_SRC_SEL, p_src_sel, 150 DTBCLK_P0_EN, 1); 151 break; 152 case 1: 153 if (src == REFCLK) 154 REG_UPDATE(DTBCLK_P_CNTL, 155 DTBCLK_P1_EN, 0); 156 else 157 REG_UPDATE_2(DTBCLK_P_CNTL, 158 DTBCLK_P1_SRC_SEL, p_src_sel, 159 DTBCLK_P1_EN, 1); 160 break; 161 case 2: 162 if (src == REFCLK) 163 REG_UPDATE(DTBCLK_P_CNTL, 164 DTBCLK_P2_EN, 0); 165 else 166 REG_UPDATE_2(DTBCLK_P_CNTL, 167 DTBCLK_P2_SRC_SEL, p_src_sel, 168 DTBCLK_P2_EN, 1); 169 break; 170 case 3: 171 if (src == REFCLK) 172 REG_UPDATE(DTBCLK_P_CNTL, 173 DTBCLK_P3_EN, 0); 174 else 175 REG_UPDATE_2(DTBCLK_P_CNTL, 176 DTBCLK_P3_SRC_SEL, p_src_sel, 177 DTBCLK_P3_EN, 1); 178 break; 179 default: 180 BREAK_TO_DEBUGGER(); 181 return; 182 } 183 184 } 185 186 /* Controls the generation of pixel valid for OTG in (OTG -> HPO case) */ 187 static void dccg314_set_dtbclk_dto( 188 struct dccg *dccg, 189 const struct dtbclk_dto_params *params) 190 { 191 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); 192 /* DTO Output Rate / Pixel Rate = 1/4 */ 193 int req_dtbclk_khz = params->pixclk_khz / 4; 194 195 if (params->ref_dtbclk_khz && req_dtbclk_khz) { 196 uint32_t modulo, phase; 197 198 // phase / modulo = dtbclk / dtbclk ref 199 modulo = params->ref_dtbclk_khz * 1000; 200 phase = req_dtbclk_khz * 1000; 201 202 REG_WRITE(DTBCLK_DTO_MODULO[params->otg_inst], modulo); 203 REG_WRITE(DTBCLK_DTO_PHASE[params->otg_inst], phase); 204 205 REG_UPDATE(OTG_PIXEL_RATE_CNTL[params->otg_inst], 206 DTBCLK_DTO_ENABLE[params->otg_inst], 1); 207 208 REG_WAIT(OTG_PIXEL_RATE_CNTL[params->otg_inst], 209 DTBCLKDTO_ENABLE_STATUS[params->otg_inst], 1, 210 1, 100); 211 212 /* program OTG_PIXEL_RATE_DIV for DIVK1 and DIVK2 fields */ 213 dccg314_set_pixel_rate_div(dccg, params->otg_inst, PIXEL_RATE_DIV_BY_1, PIXEL_RATE_DIV_BY_1); 214 215 /* The recommended programming sequence to enable DTBCLK DTO to generate 216 * valid pixel HPO DPSTREAM ENCODER, specifies that DTO source select should 217 * be set only after DTO is enabled 218 */ 219 REG_UPDATE(OTG_PIXEL_RATE_CNTL[params->otg_inst], 220 PIPE_DTO_SRC_SEL[params->otg_inst], 2); 221 } else { 222 REG_UPDATE_2(OTG_PIXEL_RATE_CNTL[params->otg_inst], 223 DTBCLK_DTO_ENABLE[params->otg_inst], 0, 224 PIPE_DTO_SRC_SEL[params->otg_inst], 1); 225 226 REG_WRITE(DTBCLK_DTO_MODULO[params->otg_inst], 0); 227 REG_WRITE(DTBCLK_DTO_PHASE[params->otg_inst], 0); 228 } 229 } 230 231 static void dccg314_set_dpstreamclk( 232 struct dccg *dccg, 233 enum streamclk_source src, 234 int otg_inst, 235 int dp_hpo_inst) 236 { 237 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); 238 239 /* set the dtbclk_p source */ 240 dccg314_set_dtbclk_p_src(dccg, src, otg_inst); 241 242 /* enabled to select one of the DTBCLKs for pipe */ 243 switch (dp_hpo_inst) { 244 case 0: 245 REG_UPDATE_2(DPSTREAMCLK_CNTL, 246 DPSTREAMCLK0_EN, (src == REFCLK) ? 0 : 1, 247 DPSTREAMCLK0_SRC_SEL, otg_inst); 248 break; 249 case 1: 250 REG_UPDATE_2(DPSTREAMCLK_CNTL, 251 DPSTREAMCLK1_EN, (src == REFCLK) ? 0 : 1, 252 DPSTREAMCLK1_SRC_SEL, otg_inst); 253 break; 254 case 2: 255 REG_UPDATE_2(DPSTREAMCLK_CNTL, 256 DPSTREAMCLK2_EN, (src == REFCLK) ? 0 : 1, 257 DPSTREAMCLK2_SRC_SEL, otg_inst); 258 break; 259 case 3: 260 REG_UPDATE_2(DPSTREAMCLK_CNTL, 261 DPSTREAMCLK3_EN, (src == REFCLK) ? 0 : 1, 262 DPSTREAMCLK3_SRC_SEL, otg_inst); 263 break; 264 default: 265 BREAK_TO_DEBUGGER(); 266 return; 267 } 268 } 269 270 static void dccg314_set_valid_pixel_rate( 271 struct dccg *dccg, 272 int ref_dtbclk_khz, 273 int otg_inst, 274 int pixclk_khz) 275 { 276 struct dtbclk_dto_params dto_params = {0}; 277 278 dto_params.ref_dtbclk_khz = ref_dtbclk_khz; 279 dto_params.otg_inst = otg_inst; 280 dto_params.pixclk_khz = pixclk_khz; 281 282 dccg314_set_dtbclk_dto(dccg, &dto_params); 283 } 284 285 static const struct dccg_funcs dccg314_funcs = { 286 .update_dpp_dto = dccg31_update_dpp_dto, 287 .get_dccg_ref_freq = dccg31_get_dccg_ref_freq, 288 .dccg_init = dccg31_init, 289 .set_dpstreamclk = dccg314_set_dpstreamclk, 290 .enable_symclk32_se = dccg31_enable_symclk32_se, 291 .disable_symclk32_se = dccg31_disable_symclk32_se, 292 .enable_symclk32_le = dccg31_enable_symclk32_le, 293 .disable_symclk32_le = dccg31_disable_symclk32_le, 294 .set_physymclk = dccg31_set_physymclk, 295 .set_dtbclk_dto = dccg314_set_dtbclk_dto, 296 .set_audio_dtbclk_dto = dccg31_set_audio_dtbclk_dto, 297 .set_fifo_errdet_ovr_en = dccg2_set_fifo_errdet_ovr_en, 298 .otg_add_pixel = dccg31_otg_add_pixel, 299 .otg_drop_pixel = dccg31_otg_drop_pixel, 300 .set_dispclk_change_mode = dccg31_set_dispclk_change_mode, 301 .disable_dsc = dccg31_disable_dscclk, 302 .enable_dsc = dccg31_enable_dscclk, 303 .set_pixel_rate_div = dccg314_set_pixel_rate_div, 304 .set_valid_pixel_rate = dccg314_set_valid_pixel_rate, 305 }; 306 307 struct dccg *dccg314_create( 308 struct dc_context *ctx, 309 const struct dccg_registers *regs, 310 const struct dccg_shift *dccg_shift, 311 const struct dccg_mask *dccg_mask) 312 { 313 struct dcn_dccg *dccg_dcn = kzalloc(sizeof(*dccg_dcn), GFP_KERNEL); 314 struct dccg *base; 315 316 if (dccg_dcn == NULL) { 317 BREAK_TO_DEBUGGER(); 318 return NULL; 319 } 320 321 base = &dccg_dcn->base; 322 base->ctx = ctx; 323 base->funcs = &dccg314_funcs; 324 325 dccg_dcn->regs = regs; 326 dccg_dcn->dccg_shift = dccg_shift; 327 dccg_dcn->dccg_mask = dccg_mask; 328 329 return &dccg_dcn->base; 330 } 331