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_physymclk( 46 struct dccg *dccg, 47 int phy_inst, 48 enum physymclk_clock_source clk_src, 49 bool force_enable) 50 { 51 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); 52 53 /* Force PHYSYMCLK on and Select phyd32clk as the source of clock which is output to PHY through DCIO */ 54 switch (phy_inst) { 55 case 0: 56 if (force_enable) 57 REG_UPDATE_2(PHYASYMCLK_CLOCK_CNTL, 58 PHYASYMCLK_FORCE_EN, 1, 59 PHYASYMCLK_FORCE_SRC_SEL, clk_src); 60 else 61 REG_UPDATE_2(PHYASYMCLK_CLOCK_CNTL, 62 PHYASYMCLK_FORCE_EN, 0, 63 PHYASYMCLK_FORCE_SRC_SEL, 0); 64 break; 65 case 1: 66 if (force_enable) 67 REG_UPDATE_2(PHYBSYMCLK_CLOCK_CNTL, 68 PHYBSYMCLK_FORCE_EN, 1, 69 PHYBSYMCLK_FORCE_SRC_SEL, clk_src); 70 else 71 REG_UPDATE_2(PHYBSYMCLK_CLOCK_CNTL, 72 PHYBSYMCLK_FORCE_EN, 0, 73 PHYBSYMCLK_FORCE_SRC_SEL, 0); 74 break; 75 case 2: 76 if (force_enable) 77 REG_UPDATE_2(PHYCSYMCLK_CLOCK_CNTL, 78 PHYCSYMCLK_FORCE_EN, 1, 79 PHYCSYMCLK_FORCE_SRC_SEL, clk_src); 80 else 81 REG_UPDATE_2(PHYCSYMCLK_CLOCK_CNTL, 82 PHYCSYMCLK_FORCE_EN, 0, 83 PHYCSYMCLK_FORCE_SRC_SEL, 0); 84 break; 85 case 3: 86 if (force_enable) 87 REG_UPDATE_2(PHYDSYMCLK_CLOCK_CNTL, 88 PHYDSYMCLK_FORCE_EN, 1, 89 PHYDSYMCLK_FORCE_SRC_SEL, clk_src); 90 else 91 REG_UPDATE_2(PHYDSYMCLK_CLOCK_CNTL, 92 PHYDSYMCLK_FORCE_EN, 0, 93 PHYDSYMCLK_FORCE_SRC_SEL, 0); 94 break; 95 case 4: 96 if (force_enable) 97 REG_UPDATE_2(PHYESYMCLK_CLOCK_CNTL, 98 PHYESYMCLK_FORCE_EN, 1, 99 PHYESYMCLK_FORCE_SRC_SEL, clk_src); 100 else 101 REG_UPDATE_2(PHYESYMCLK_CLOCK_CNTL, 102 PHYESYMCLK_FORCE_EN, 0, 103 PHYESYMCLK_FORCE_SRC_SEL, 0); 104 break; 105 default: 106 BREAK_TO_DEBUGGER(); 107 return; 108 } 109 } 110 111 /* Controls the generation of pixel valid for OTG in (OTG -> HPO case) */ 112 void dccg31_set_dtbclk_dto( 113 struct dccg *dccg, 114 int dtbclk_inst, 115 int req_dtbclk_khz, 116 int num_odm_segments, 117 const struct dc_crtc_timing *timing) 118 { 119 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); 120 uint32_t dtbdto_div; 121 122 /* Mode DTBDTO Rate DTBCLK_DTO<x>_DIV Register 123 * ODM 4:1 combine pixel rate/4 2 124 * ODM 2:1 combine pixel rate/2 4 125 * non-DSC 4:2:0 mode pixel rate/2 4 126 * DSC native 4:2:0 pixel rate/2 4 127 * DSC native 4:2:2 pixel rate/2 4 128 * Other modes pixel rate 8 129 */ 130 if (num_odm_segments == 4) { 131 dtbdto_div = 2; 132 req_dtbclk_khz = req_dtbclk_khz / 4; 133 } else if ((num_odm_segments == 2) || 134 (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) || 135 (timing->flags.DSC && timing->pixel_encoding == PIXEL_ENCODING_YCBCR422 136 && !timing->dsc_cfg.ycbcr422_simple)) { 137 dtbdto_div = 4; 138 req_dtbclk_khz = req_dtbclk_khz / 2; 139 } else 140 dtbdto_div = 8; 141 142 if (dccg->ref_dtbclk_khz && req_dtbclk_khz) { 143 uint32_t modulo, phase; 144 145 // phase / modulo = dtbclk / dtbclk ref 146 modulo = dccg->ref_dtbclk_khz * 1000; 147 phase = div_u64((((unsigned long long)modulo * req_dtbclk_khz) + dccg->ref_dtbclk_khz - 1), 148 dccg->ref_dtbclk_khz); 149 150 REG_UPDATE(OTG_PIXEL_RATE_CNTL[dtbclk_inst], 151 DTBCLK_DTO_DIV[dtbclk_inst], dtbdto_div); 152 153 REG_WRITE(DTBCLK_DTO_MODULO[dtbclk_inst], modulo); 154 REG_WRITE(DTBCLK_DTO_PHASE[dtbclk_inst], phase); 155 156 REG_UPDATE(OTG_PIXEL_RATE_CNTL[dtbclk_inst], 157 DTBCLK_DTO_ENABLE[dtbclk_inst], 1); 158 159 REG_WAIT(OTG_PIXEL_RATE_CNTL[dtbclk_inst], 160 DTBCLKDTO_ENABLE_STATUS[dtbclk_inst], 1, 161 1, 100); 162 163 /* The recommended programming sequence to enable DTBCLK DTO to generate 164 * valid pixel HPO DPSTREAM ENCODER, specifies that DTO source select should 165 * be set only after DTO is enabled 166 */ 167 REG_UPDATE(OTG_PIXEL_RATE_CNTL[dtbclk_inst], 168 PIPE_DTO_SRC_SEL[dtbclk_inst], 1); 169 170 dccg->dtbclk_khz[dtbclk_inst] = req_dtbclk_khz; 171 } else { 172 REG_UPDATE_3(OTG_PIXEL_RATE_CNTL[dtbclk_inst], 173 DTBCLK_DTO_ENABLE[dtbclk_inst], 0, 174 PIPE_DTO_SRC_SEL[dtbclk_inst], 0, 175 DTBCLK_DTO_DIV[dtbclk_inst], dtbdto_div); 176 177 REG_WRITE(DTBCLK_DTO_MODULO[dtbclk_inst], 0); 178 REG_WRITE(DTBCLK_DTO_PHASE[dtbclk_inst], 0); 179 180 dccg->dtbclk_khz[dtbclk_inst] = 0; 181 } 182 } 183 184 void dccg31_set_audio_dtbclk_dto( 185 struct dccg *dccg, 186 uint32_t req_audio_dtbclk_khz) 187 { 188 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); 189 190 if (dccg->ref_dtbclk_khz && req_audio_dtbclk_khz) { 191 uint32_t modulo, phase; 192 193 // phase / modulo = dtbclk / dtbclk ref 194 modulo = dccg->ref_dtbclk_khz * 1000; 195 phase = div_u64((((unsigned long long)modulo * req_audio_dtbclk_khz) + dccg->ref_dtbclk_khz - 1), 196 dccg->ref_dtbclk_khz); 197 198 199 REG_WRITE(DCCG_AUDIO_DTBCLK_DTO_MODULO, modulo); 200 REG_WRITE(DCCG_AUDIO_DTBCLK_DTO_PHASE, phase); 201 202 //REG_UPDATE(DCCG_AUDIO_DTO_SOURCE, 203 // DCCG_AUDIO_DTBCLK_DTO_USE_512FBR_DTO, 1); 204 205 REG_UPDATE(DCCG_AUDIO_DTO_SOURCE, 206 DCCG_AUDIO_DTO_SEL, 4); // 04 - DCCG_AUDIO_DTO_SEL_AUDIO_DTO_DTBCLK 207 208 dccg->audio_dtbclk_khz = req_audio_dtbclk_khz; 209 } else { 210 REG_WRITE(DCCG_AUDIO_DTBCLK_DTO_PHASE, 0); 211 REG_WRITE(DCCG_AUDIO_DTBCLK_DTO_MODULO, 0); 212 213 REG_UPDATE(DCCG_AUDIO_DTO_SOURCE, 214 DCCG_AUDIO_DTO_SEL, 3); // 03 - DCCG_AUDIO_DTO_SEL_NO_AUDIO_DTO 215 216 dccg->audio_dtbclk_khz = 0; 217 } 218 } 219 220 static void dccg31_get_dccg_ref_freq(struct dccg *dccg, 221 unsigned int xtalin_freq_inKhz, 222 unsigned int *dccg_ref_freq_inKhz) 223 { 224 /* 225 * Assume refclk is sourced from xtalin 226 * expect 24MHz 227 */ 228 *dccg_ref_freq_inKhz = xtalin_freq_inKhz; 229 return; 230 } 231 232 static void dccg31_set_dispclk_change_mode( 233 struct dccg *dccg, 234 enum dentist_dispclk_change_mode change_mode) 235 { 236 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); 237 238 REG_UPDATE(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_CHG_MODE, 239 change_mode == DISPCLK_CHANGE_MODE_RAMPING ? 2 : 0); 240 } 241 242 void dccg31_init(struct dccg *dccg) 243 { 244 } 245 246 static const struct dccg_funcs dccg31_funcs = { 247 .update_dpp_dto = dccg2_update_dpp_dto, 248 .get_dccg_ref_freq = dccg31_get_dccg_ref_freq, 249 .dccg_init = dccg31_init, 250 .set_physymclk = dccg31_set_physymclk, 251 .set_dtbclk_dto = dccg31_set_dtbclk_dto, 252 .set_audio_dtbclk_dto = dccg31_set_audio_dtbclk_dto, 253 .set_dispclk_change_mode = dccg31_set_dispclk_change_mode, 254 }; 255 256 struct dccg *dccg31_create( 257 struct dc_context *ctx, 258 const struct dccg_registers *regs, 259 const struct dccg_shift *dccg_shift, 260 const struct dccg_mask *dccg_mask) 261 { 262 struct dcn_dccg *dccg_dcn = kzalloc(sizeof(*dccg_dcn), GFP_KERNEL); 263 struct dccg *base; 264 265 if (dccg_dcn == NULL) { 266 BREAK_TO_DEBUGGER(); 267 return NULL; 268 } 269 270 base = &dccg_dcn->base; 271 base->ctx = ctx; 272 base->funcs = &dccg31_funcs; 273 274 dccg_dcn->regs = regs; 275 dccg_dcn->dccg_shift = dccg_shift; 276 dccg_dcn->dccg_mask = dccg_mask; 277 278 return &dccg_dcn->base; 279 } 280