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