1 /* 2 * Copyright 2018 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 "dcn31_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 void dccg31_set_dpstreamclk( 46 struct dccg *dccg, 47 enum hdmistreamclk_source src, 48 int otg_inst) 49 { 50 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); 51 52 /* enabled to select one of the DTBCLKs for pipe */ 53 switch (otg_inst) { 54 case 0: 55 REG_UPDATE(DPSTREAMCLK_CNTL, 56 DPSTREAMCLK_PIPE0_EN, (src == REFCLK) ? 0 : 1); 57 break; 58 case 1: 59 REG_UPDATE(DPSTREAMCLK_CNTL, 60 DPSTREAMCLK_PIPE1_EN, (src == REFCLK) ? 0 : 1); 61 break; 62 case 2: 63 REG_UPDATE(DPSTREAMCLK_CNTL, 64 DPSTREAMCLK_PIPE2_EN, (src == REFCLK) ? 0 : 1); 65 break; 66 case 3: 67 REG_UPDATE(DPSTREAMCLK_CNTL, 68 DPSTREAMCLK_PIPE3_EN, (src == REFCLK) ? 0 : 1); 69 break; 70 default: 71 BREAK_TO_DEBUGGER(); 72 return; 73 } 74 } 75 76 void dccg31_enable_symclk32_se( 77 struct dccg *dccg, 78 int hpo_se_inst, 79 enum phyd32clk_clock_source phyd32clk) 80 { 81 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); 82 83 /* select one of the PHYD32CLKs as the source for symclk32_se */ 84 switch (hpo_se_inst) { 85 case 0: 86 REG_UPDATE_2(SYMCLK32_SE_CNTL, 87 SYMCLK32_SE0_SRC_SEL, phyd32clk, 88 SYMCLK32_SE0_EN, 1); 89 break; 90 case 1: 91 REG_UPDATE_2(SYMCLK32_SE_CNTL, 92 SYMCLK32_SE1_SRC_SEL, phyd32clk, 93 SYMCLK32_SE1_EN, 1); 94 break; 95 case 2: 96 REG_UPDATE_2(SYMCLK32_SE_CNTL, 97 SYMCLK32_SE2_SRC_SEL, phyd32clk, 98 SYMCLK32_SE2_EN, 1); 99 break; 100 case 3: 101 REG_UPDATE_2(SYMCLK32_SE_CNTL, 102 SYMCLK32_SE3_SRC_SEL, phyd32clk, 103 SYMCLK32_SE3_EN, 1); 104 break; 105 default: 106 BREAK_TO_DEBUGGER(); 107 return; 108 } 109 } 110 111 void dccg31_disable_symclk32_se( 112 struct dccg *dccg, 113 int hpo_se_inst) 114 { 115 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); 116 117 /* set refclk as the source for symclk32_se */ 118 switch (hpo_se_inst) { 119 case 0: 120 REG_UPDATE_2(SYMCLK32_SE_CNTL, 121 SYMCLK32_SE0_SRC_SEL, 0, 122 SYMCLK32_SE0_EN, 0); 123 break; 124 case 1: 125 REG_UPDATE_2(SYMCLK32_SE_CNTL, 126 SYMCLK32_SE1_SRC_SEL, 0, 127 SYMCLK32_SE1_EN, 0); 128 break; 129 case 2: 130 REG_UPDATE_2(SYMCLK32_SE_CNTL, 131 SYMCLK32_SE2_SRC_SEL, 0, 132 SYMCLK32_SE2_EN, 0); 133 break; 134 case 3: 135 REG_UPDATE_2(SYMCLK32_SE_CNTL, 136 SYMCLK32_SE3_SRC_SEL, 0, 137 SYMCLK32_SE3_EN, 0); 138 break; 139 default: 140 BREAK_TO_DEBUGGER(); 141 return; 142 } 143 } 144 145 void dccg31_enable_symclk32_le( 146 struct dccg *dccg, 147 int hpo_le_inst, 148 enum phyd32clk_clock_source phyd32clk) 149 { 150 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); 151 152 /* select one of the PHYD32CLKs as the source for symclk32_le */ 153 switch (hpo_le_inst) { 154 case 0: 155 REG_UPDATE_2(SYMCLK32_LE_CNTL, 156 SYMCLK32_LE0_SRC_SEL, phyd32clk, 157 SYMCLK32_LE0_EN, 1); 158 break; 159 case 1: 160 REG_UPDATE_2(SYMCLK32_LE_CNTL, 161 SYMCLK32_LE1_SRC_SEL, phyd32clk, 162 SYMCLK32_LE1_EN, 1); 163 break; 164 default: 165 BREAK_TO_DEBUGGER(); 166 return; 167 } 168 } 169 170 void dccg31_disable_symclk32_le( 171 struct dccg *dccg, 172 int hpo_le_inst) 173 { 174 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); 175 176 /* set refclk as the source for symclk32_le */ 177 switch (hpo_le_inst) { 178 case 0: 179 REG_UPDATE_2(SYMCLK32_LE_CNTL, 180 SYMCLK32_LE0_SRC_SEL, 0, 181 SYMCLK32_LE0_EN, 0); 182 break; 183 case 1: 184 REG_UPDATE_2(SYMCLK32_LE_CNTL, 185 SYMCLK32_LE1_SRC_SEL, 0, 186 SYMCLK32_LE1_EN, 0); 187 break; 188 default: 189 BREAK_TO_DEBUGGER(); 190 return; 191 } 192 } 193 194 void dccg31_set_physymclk( 195 struct dccg *dccg, 196 int phy_inst, 197 enum physymclk_clock_source clk_src, 198 bool force_enable) 199 { 200 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); 201 202 /* Force PHYSYMCLK on and Select phyd32clk as the source of clock which is output to PHY through DCIO */ 203 switch (phy_inst) { 204 case 0: 205 if (force_enable) 206 REG_UPDATE_2(PHYASYMCLK_CLOCK_CNTL, 207 PHYASYMCLK_FORCE_EN, 1, 208 PHYASYMCLK_FORCE_SRC_SEL, clk_src); 209 else 210 REG_UPDATE_2(PHYASYMCLK_CLOCK_CNTL, 211 PHYASYMCLK_FORCE_EN, 0, 212 PHYASYMCLK_FORCE_SRC_SEL, 0); 213 break; 214 case 1: 215 if (force_enable) 216 REG_UPDATE_2(PHYBSYMCLK_CLOCK_CNTL, 217 PHYBSYMCLK_FORCE_EN, 1, 218 PHYBSYMCLK_FORCE_SRC_SEL, clk_src); 219 else 220 REG_UPDATE_2(PHYBSYMCLK_CLOCK_CNTL, 221 PHYBSYMCLK_FORCE_EN, 0, 222 PHYBSYMCLK_FORCE_SRC_SEL, 0); 223 break; 224 case 2: 225 if (force_enable) 226 REG_UPDATE_2(PHYCSYMCLK_CLOCK_CNTL, 227 PHYCSYMCLK_FORCE_EN, 1, 228 PHYCSYMCLK_FORCE_SRC_SEL, clk_src); 229 else 230 REG_UPDATE_2(PHYCSYMCLK_CLOCK_CNTL, 231 PHYCSYMCLK_FORCE_EN, 0, 232 PHYCSYMCLK_FORCE_SRC_SEL, 0); 233 break; 234 case 3: 235 if (force_enable) 236 REG_UPDATE_2(PHYDSYMCLK_CLOCK_CNTL, 237 PHYDSYMCLK_FORCE_EN, 1, 238 PHYDSYMCLK_FORCE_SRC_SEL, clk_src); 239 else 240 REG_UPDATE_2(PHYDSYMCLK_CLOCK_CNTL, 241 PHYDSYMCLK_FORCE_EN, 0, 242 PHYDSYMCLK_FORCE_SRC_SEL, 0); 243 break; 244 case 4: 245 if (force_enable) 246 REG_UPDATE_2(PHYESYMCLK_CLOCK_CNTL, 247 PHYESYMCLK_FORCE_EN, 1, 248 PHYESYMCLK_FORCE_SRC_SEL, clk_src); 249 else 250 REG_UPDATE_2(PHYESYMCLK_CLOCK_CNTL, 251 PHYESYMCLK_FORCE_EN, 0, 252 PHYESYMCLK_FORCE_SRC_SEL, 0); 253 break; 254 default: 255 BREAK_TO_DEBUGGER(); 256 return; 257 } 258 } 259 260 /* Controls the generation of pixel valid for OTG in (OTG -> HPO case) */ 261 void dccg31_set_dtbclk_dto( 262 struct dccg *dccg, 263 int dtbclk_inst, 264 int req_dtbclk_khz, 265 int num_odm_segments, 266 const struct dc_crtc_timing *timing) 267 { 268 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); 269 uint32_t dtbdto_div; 270 271 /* Mode DTBDTO Rate DTBCLK_DTO<x>_DIV Register 272 * ODM 4:1 combine pixel rate/4 2 273 * ODM 2:1 combine pixel rate/2 4 274 * non-DSC 4:2:0 mode pixel rate/2 4 275 * DSC native 4:2:0 pixel rate/2 4 276 * DSC native 4:2:2 pixel rate/2 4 277 * Other modes pixel rate 8 278 */ 279 if (num_odm_segments == 4) { 280 dtbdto_div = 2; 281 req_dtbclk_khz = req_dtbclk_khz / 4; 282 } else if ((num_odm_segments == 2) || 283 (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) || 284 (timing->flags.DSC && timing->pixel_encoding == PIXEL_ENCODING_YCBCR422 285 && !timing->dsc_cfg.ycbcr422_simple)) { 286 dtbdto_div = 4; 287 req_dtbclk_khz = req_dtbclk_khz / 2; 288 } else 289 dtbdto_div = 8; 290 291 if (dccg->ref_dtbclk_khz && req_dtbclk_khz) { 292 uint32_t modulo, phase; 293 294 // phase / modulo = dtbclk / dtbclk ref 295 modulo = dccg->ref_dtbclk_khz * 1000; 296 phase = div_u64((((unsigned long long)modulo * req_dtbclk_khz) + dccg->ref_dtbclk_khz - 1), 297 dccg->ref_dtbclk_khz); 298 299 REG_UPDATE(OTG_PIXEL_RATE_CNTL[dtbclk_inst], 300 DTBCLK_DTO_DIV[dtbclk_inst], dtbdto_div); 301 302 REG_WRITE(DTBCLK_DTO_MODULO[dtbclk_inst], modulo); 303 REG_WRITE(DTBCLK_DTO_PHASE[dtbclk_inst], phase); 304 305 REG_UPDATE(OTG_PIXEL_RATE_CNTL[dtbclk_inst], 306 DTBCLK_DTO_ENABLE[dtbclk_inst], 1); 307 308 REG_WAIT(OTG_PIXEL_RATE_CNTL[dtbclk_inst], 309 DTBCLKDTO_ENABLE_STATUS[dtbclk_inst], 1, 310 1, 100); 311 312 /* The recommended programming sequence to enable DTBCLK DTO to generate 313 * valid pixel HPO DPSTREAM ENCODER, specifies that DTO source select should 314 * be set only after DTO is enabled 315 */ 316 REG_UPDATE(OTG_PIXEL_RATE_CNTL[dtbclk_inst], 317 PIPE_DTO_SRC_SEL[dtbclk_inst], 1); 318 319 dccg->dtbclk_khz[dtbclk_inst] = req_dtbclk_khz; 320 } else { 321 REG_UPDATE_3(OTG_PIXEL_RATE_CNTL[dtbclk_inst], 322 DTBCLK_DTO_ENABLE[dtbclk_inst], 0, 323 PIPE_DTO_SRC_SEL[dtbclk_inst], 0, 324 DTBCLK_DTO_DIV[dtbclk_inst], dtbdto_div); 325 326 REG_WRITE(DTBCLK_DTO_MODULO[dtbclk_inst], 0); 327 REG_WRITE(DTBCLK_DTO_PHASE[dtbclk_inst], 0); 328 329 dccg->dtbclk_khz[dtbclk_inst] = 0; 330 } 331 } 332 333 void dccg31_set_audio_dtbclk_dto( 334 struct dccg *dccg, 335 uint32_t req_audio_dtbclk_khz) 336 { 337 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); 338 339 if (dccg->ref_dtbclk_khz && req_audio_dtbclk_khz) { 340 uint32_t modulo, phase; 341 342 // phase / modulo = dtbclk / dtbclk ref 343 modulo = dccg->ref_dtbclk_khz * 1000; 344 phase = div_u64((((unsigned long long)modulo * req_audio_dtbclk_khz) + dccg->ref_dtbclk_khz - 1), 345 dccg->ref_dtbclk_khz); 346 347 348 REG_WRITE(DCCG_AUDIO_DTBCLK_DTO_MODULO, modulo); 349 REG_WRITE(DCCG_AUDIO_DTBCLK_DTO_PHASE, phase); 350 351 //REG_UPDATE(DCCG_AUDIO_DTO_SOURCE, 352 // DCCG_AUDIO_DTBCLK_DTO_USE_512FBR_DTO, 1); 353 354 REG_UPDATE(DCCG_AUDIO_DTO_SOURCE, 355 DCCG_AUDIO_DTO_SEL, 4); // 04 - DCCG_AUDIO_DTO_SEL_AUDIO_DTO_DTBCLK 356 357 dccg->audio_dtbclk_khz = req_audio_dtbclk_khz; 358 } else { 359 REG_WRITE(DCCG_AUDIO_DTBCLK_DTO_PHASE, 0); 360 REG_WRITE(DCCG_AUDIO_DTBCLK_DTO_MODULO, 0); 361 362 REG_UPDATE(DCCG_AUDIO_DTO_SOURCE, 363 DCCG_AUDIO_DTO_SEL, 3); // 03 - DCCG_AUDIO_DTO_SEL_NO_AUDIO_DTO 364 365 dccg->audio_dtbclk_khz = 0; 366 } 367 } 368 369 static void dccg31_get_dccg_ref_freq(struct dccg *dccg, 370 unsigned int xtalin_freq_inKhz, 371 unsigned int *dccg_ref_freq_inKhz) 372 { 373 /* 374 * Assume refclk is sourced from xtalin 375 * expect 24MHz 376 */ 377 *dccg_ref_freq_inKhz = xtalin_freq_inKhz; 378 return; 379 } 380 381 static void dccg31_set_dispclk_change_mode( 382 struct dccg *dccg, 383 enum dentist_dispclk_change_mode change_mode) 384 { 385 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); 386 387 REG_UPDATE(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_CHG_MODE, 388 change_mode == DISPCLK_CHANGE_MODE_RAMPING ? 2 : 0); 389 } 390 391 void dccg31_init(struct dccg *dccg) 392 { 393 /* Set HPO stream encoder to use refclk to avoid case where PHY is 394 * disabled and SYMCLK32 for HPO SE is sourced from PHYD32CLK which 395 * will cause DCN to hang. 396 */ 397 dccg31_disable_symclk32_se(dccg, 0); 398 dccg31_disable_symclk32_se(dccg, 1); 399 dccg31_disable_symclk32_se(dccg, 2); 400 dccg31_disable_symclk32_se(dccg, 3); 401 } 402 403 static const struct dccg_funcs dccg31_funcs = { 404 .update_dpp_dto = dccg2_update_dpp_dto, 405 .get_dccg_ref_freq = dccg31_get_dccg_ref_freq, 406 .dccg_init = dccg31_init, 407 .set_dpstreamclk = dccg31_set_dpstreamclk, 408 .enable_symclk32_se = dccg31_enable_symclk32_se, 409 .disable_symclk32_se = dccg31_disable_symclk32_se, 410 .enable_symclk32_le = dccg31_enable_symclk32_le, 411 .disable_symclk32_le = dccg31_disable_symclk32_le, 412 .set_physymclk = dccg31_set_physymclk, 413 .set_dtbclk_dto = dccg31_set_dtbclk_dto, 414 .set_audio_dtbclk_dto = dccg31_set_audio_dtbclk_dto, 415 .set_dispclk_change_mode = dccg31_set_dispclk_change_mode, 416 }; 417 418 struct dccg *dccg31_create( 419 struct dc_context *ctx, 420 const struct dccg_registers *regs, 421 const struct dccg_shift *dccg_shift, 422 const struct dccg_mask *dccg_mask) 423 { 424 struct dcn_dccg *dccg_dcn = kzalloc(sizeof(*dccg_dcn), GFP_KERNEL); 425 struct dccg *base; 426 427 if (dccg_dcn == NULL) { 428 BREAK_TO_DEBUGGER(); 429 return NULL; 430 } 431 432 base = &dccg_dcn->base; 433 base->ctx = ctx; 434 base->funcs = &dccg31_funcs; 435 436 dccg_dcn->regs = regs; 437 dccg_dcn->dccg_shift = dccg_shift; 438 dccg_dcn->dccg_mask = dccg_mask; 439 440 return &dccg_dcn->base; 441 } 442