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
dccg32_get_pixel_rate_div(struct dccg * dccg,uint32_t otg_inst,enum pixel_rate_div * k1,enum pixel_rate_div * k2)45 static void dccg32_get_pixel_rate_div(
46 struct dccg *dccg,
47 uint32_t otg_inst,
48 enum pixel_rate_div *k1,
49 enum pixel_rate_div *k2)
50 {
51 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
52 uint32_t val_k1 = PIXEL_RATE_DIV_NA, val_k2 = PIXEL_RATE_DIV_NA;
53
54 *k1 = PIXEL_RATE_DIV_NA;
55 *k2 = PIXEL_RATE_DIV_NA;
56
57 switch (otg_inst) {
58 case 0:
59 REG_GET_2(OTG_PIXEL_RATE_DIV,
60 OTG0_PIXEL_RATE_DIVK1, &val_k1,
61 OTG0_PIXEL_RATE_DIVK2, &val_k2);
62 break;
63 case 1:
64 REG_GET_2(OTG_PIXEL_RATE_DIV,
65 OTG1_PIXEL_RATE_DIVK1, &val_k1,
66 OTG1_PIXEL_RATE_DIVK2, &val_k2);
67 break;
68 case 2:
69 REG_GET_2(OTG_PIXEL_RATE_DIV,
70 OTG2_PIXEL_RATE_DIVK1, &val_k1,
71 OTG2_PIXEL_RATE_DIVK2, &val_k2);
72 break;
73 case 3:
74 REG_GET_2(OTG_PIXEL_RATE_DIV,
75 OTG3_PIXEL_RATE_DIVK1, &val_k1,
76 OTG3_PIXEL_RATE_DIVK2, &val_k2);
77 break;
78 default:
79 BREAK_TO_DEBUGGER();
80 return;
81 }
82
83 *k1 = (enum pixel_rate_div)val_k1;
84 *k2 = (enum pixel_rate_div)val_k2;
85 }
86
dccg32_set_pixel_rate_div(struct dccg * dccg,uint32_t otg_inst,enum pixel_rate_div k1,enum pixel_rate_div k2)87 static void dccg32_set_pixel_rate_div(
88 struct dccg *dccg,
89 uint32_t otg_inst,
90 enum pixel_rate_div k1,
91 enum pixel_rate_div k2)
92 {
93 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
94
95 enum pixel_rate_div cur_k1 = PIXEL_RATE_DIV_NA, cur_k2 = PIXEL_RATE_DIV_NA;
96
97 // Don't program 0xF into the register field. Not valid since
98 // K1 / K2 field is only 1 / 2 bits wide
99 if (k1 == PIXEL_RATE_DIV_NA || k2 == PIXEL_RATE_DIV_NA) {
100 BREAK_TO_DEBUGGER();
101 return;
102 }
103
104 dccg32_get_pixel_rate_div(dccg, otg_inst, &cur_k1, &cur_k2);
105 if (k1 == cur_k1 && k2 == cur_k2)
106 return;
107
108 switch (otg_inst) {
109 case 0:
110 REG_UPDATE_2(OTG_PIXEL_RATE_DIV,
111 OTG0_PIXEL_RATE_DIVK1, k1,
112 OTG0_PIXEL_RATE_DIVK2, k2);
113 break;
114 case 1:
115 REG_UPDATE_2(OTG_PIXEL_RATE_DIV,
116 OTG1_PIXEL_RATE_DIVK1, k1,
117 OTG1_PIXEL_RATE_DIVK2, k2);
118 break;
119 case 2:
120 REG_UPDATE_2(OTG_PIXEL_RATE_DIV,
121 OTG2_PIXEL_RATE_DIVK1, k1,
122 OTG2_PIXEL_RATE_DIVK2, k2);
123 break;
124 case 3:
125 REG_UPDATE_2(OTG_PIXEL_RATE_DIV,
126 OTG3_PIXEL_RATE_DIVK1, k1,
127 OTG3_PIXEL_RATE_DIVK2, k2);
128 break;
129 default:
130 BREAK_TO_DEBUGGER();
131 return;
132 }
133 }
134
dccg32_set_dtbclk_p_src(struct dccg * dccg,enum streamclk_source src,uint32_t otg_inst)135 static void dccg32_set_dtbclk_p_src(
136 struct dccg *dccg,
137 enum streamclk_source src,
138 uint32_t otg_inst)
139 {
140 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
141
142 uint32_t p_src_sel = 0; /* selects dprefclk */
143 if (src == DTBCLK0)
144 p_src_sel = 2; /* selects dtbclk0 */
145
146 switch (otg_inst) {
147 case 0:
148 if (src == REFCLK)
149 REG_UPDATE(DTBCLK_P_CNTL,
150 DTBCLK_P0_EN, 0);
151 else
152 REG_UPDATE_2(DTBCLK_P_CNTL,
153 DTBCLK_P0_SRC_SEL, p_src_sel,
154 DTBCLK_P0_EN, 1);
155 break;
156 case 1:
157 if (src == REFCLK)
158 REG_UPDATE(DTBCLK_P_CNTL,
159 DTBCLK_P1_EN, 0);
160 else
161 REG_UPDATE_2(DTBCLK_P_CNTL,
162 DTBCLK_P1_SRC_SEL, p_src_sel,
163 DTBCLK_P1_EN, 1);
164 break;
165 case 2:
166 if (src == REFCLK)
167 REG_UPDATE(DTBCLK_P_CNTL,
168 DTBCLK_P2_EN, 0);
169 else
170 REG_UPDATE_2(DTBCLK_P_CNTL,
171 DTBCLK_P2_SRC_SEL, p_src_sel,
172 DTBCLK_P2_EN, 1);
173 break;
174 case 3:
175 if (src == REFCLK)
176 REG_UPDATE(DTBCLK_P_CNTL,
177 DTBCLK_P3_EN, 0);
178 else
179 REG_UPDATE_2(DTBCLK_P_CNTL,
180 DTBCLK_P3_SRC_SEL, p_src_sel,
181 DTBCLK_P3_EN, 1);
182 break;
183 default:
184 BREAK_TO_DEBUGGER();
185 return;
186 }
187
188 }
189
190 /* Controls the generation of pixel valid for OTG in (OTG -> HPO case) */
dccg32_set_dtbclk_dto(struct dccg * dccg,const struct dtbclk_dto_params * params)191 static void dccg32_set_dtbclk_dto(
192 struct dccg *dccg,
193 const struct dtbclk_dto_params *params)
194 {
195 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
196 /* DTO Output Rate / Pixel Rate = 1/4 */
197 int req_dtbclk_khz = params->pixclk_khz / 4;
198
199 if (params->ref_dtbclk_khz && req_dtbclk_khz) {
200 uint32_t modulo, phase;
201
202 // phase / modulo = dtbclk / dtbclk ref
203 modulo = params->ref_dtbclk_khz * 1000;
204 phase = req_dtbclk_khz * 1000;
205
206 REG_WRITE(DTBCLK_DTO_MODULO[params->otg_inst], modulo);
207 REG_WRITE(DTBCLK_DTO_PHASE[params->otg_inst], phase);
208
209 REG_UPDATE(OTG_PIXEL_RATE_CNTL[params->otg_inst],
210 DTBCLK_DTO_ENABLE[params->otg_inst], 1);
211
212 REG_WAIT(OTG_PIXEL_RATE_CNTL[params->otg_inst],
213 DTBCLKDTO_ENABLE_STATUS[params->otg_inst], 1,
214 1, 100);
215
216 /* program OTG_PIXEL_RATE_DIV for DIVK1 and DIVK2 fields */
217 dccg32_set_pixel_rate_div(dccg, params->otg_inst, PIXEL_RATE_DIV_BY_1, PIXEL_RATE_DIV_BY_1);
218
219 /* The recommended programming sequence to enable DTBCLK DTO to generate
220 * valid pixel HPO DPSTREAM ENCODER, specifies that DTO source select should
221 * be set only after DTO is enabled
222 */
223 REG_UPDATE(OTG_PIXEL_RATE_CNTL[params->otg_inst],
224 PIPE_DTO_SRC_SEL[params->otg_inst], 2);
225 } else {
226 REG_UPDATE_2(OTG_PIXEL_RATE_CNTL[params->otg_inst],
227 DTBCLK_DTO_ENABLE[params->otg_inst], 0,
228 PIPE_DTO_SRC_SEL[params->otg_inst], params->is_hdmi ? 0 : 1);
229 REG_WRITE(DTBCLK_DTO_MODULO[params->otg_inst], 0);
230 REG_WRITE(DTBCLK_DTO_PHASE[params->otg_inst], 0);
231 }
232 }
233
dccg32_set_valid_pixel_rate(struct dccg * dccg,int ref_dtbclk_khz,int otg_inst,int pixclk_khz)234 static void dccg32_set_valid_pixel_rate(
235 struct dccg *dccg,
236 int ref_dtbclk_khz,
237 int otg_inst,
238 int pixclk_khz)
239 {
240 struct dtbclk_dto_params dto_params = {0};
241
242 dto_params.ref_dtbclk_khz = ref_dtbclk_khz;
243 dto_params.otg_inst = otg_inst;
244 dto_params.pixclk_khz = pixclk_khz;
245 dto_params.is_hdmi = true;
246
247 dccg32_set_dtbclk_dto(dccg, &dto_params);
248 }
249
dccg32_get_dccg_ref_freq(struct dccg * dccg,unsigned int xtalin_freq_inKhz,unsigned int * dccg_ref_freq_inKhz)250 static void dccg32_get_dccg_ref_freq(struct dccg *dccg,
251 unsigned int xtalin_freq_inKhz,
252 unsigned int *dccg_ref_freq_inKhz)
253 {
254 /*
255 * Assume refclk is sourced from xtalin
256 * expect 100MHz
257 */
258 *dccg_ref_freq_inKhz = xtalin_freq_inKhz;
259 return;
260 }
261
dccg32_set_dpstreamclk(struct dccg * dccg,enum streamclk_source src,int otg_inst,int dp_hpo_inst)262 static void dccg32_set_dpstreamclk(
263 struct dccg *dccg,
264 enum streamclk_source src,
265 int otg_inst,
266 int dp_hpo_inst)
267 {
268 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
269
270 /* set the dtbclk_p source */
271 dccg32_set_dtbclk_p_src(dccg, src, otg_inst);
272
273 /* enabled to select one of the DTBCLKs for pipe */
274 switch (otg_inst)
275 {
276 case 0:
277 REG_UPDATE_2(DPSTREAMCLK_CNTL,
278 DPSTREAMCLK0_EN,
279 (src == REFCLK) ? 0 : 1, DPSTREAMCLK0_SRC_SEL, otg_inst);
280 break;
281 case 1:
282 REG_UPDATE_2(DPSTREAMCLK_CNTL, DPSTREAMCLK1_EN,
283 (src == REFCLK) ? 0 : 1, DPSTREAMCLK1_SRC_SEL, otg_inst);
284 break;
285 case 2:
286 REG_UPDATE_2(DPSTREAMCLK_CNTL, DPSTREAMCLK2_EN,
287 (src == REFCLK) ? 0 : 1, DPSTREAMCLK2_SRC_SEL, otg_inst);
288 break;
289 case 3:
290 REG_UPDATE_2(DPSTREAMCLK_CNTL, DPSTREAMCLK3_EN,
291 (src == REFCLK) ? 0 : 1, DPSTREAMCLK3_SRC_SEL, otg_inst);
292 break;
293 default:
294 BREAK_TO_DEBUGGER();
295 return;
296 }
297 }
298
dccg32_otg_add_pixel(struct dccg * dccg,uint32_t otg_inst)299 static void dccg32_otg_add_pixel(struct dccg *dccg,
300 uint32_t otg_inst)
301 {
302 struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
303
304 REG_UPDATE(OTG_PIXEL_RATE_CNTL[otg_inst],
305 OTG_ADD_PIXEL[otg_inst], 1);
306 }
307
dccg32_otg_drop_pixel(struct dccg * dccg,uint32_t otg_inst)308 static void dccg32_otg_drop_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_DROP_PIXEL[otg_inst], 1);
315 }
316
317 static const struct dccg_funcs dccg32_funcs = {
318 .update_dpp_dto = dccg2_update_dpp_dto,
319 .get_dccg_ref_freq = dccg32_get_dccg_ref_freq,
320 .dccg_init = dccg31_init,
321 .set_dpstreamclk = dccg32_set_dpstreamclk,
322 .enable_symclk32_se = dccg31_enable_symclk32_se,
323 .disable_symclk32_se = dccg31_disable_symclk32_se,
324 .enable_symclk32_le = dccg31_enable_symclk32_le,
325 .disable_symclk32_le = dccg31_disable_symclk32_le,
326 .set_physymclk = dccg31_set_physymclk,
327 .set_dtbclk_dto = dccg32_set_dtbclk_dto,
328 .set_valid_pixel_rate = dccg32_set_valid_pixel_rate,
329 .set_fifo_errdet_ovr_en = dccg2_set_fifo_errdet_ovr_en,
330 .set_audio_dtbclk_dto = dccg31_set_audio_dtbclk_dto,
331 .otg_add_pixel = dccg32_otg_add_pixel,
332 .otg_drop_pixel = dccg32_otg_drop_pixel,
333 .set_pixel_rate_div = dccg32_set_pixel_rate_div,
334 };
335
dccg32_create(struct dc_context * ctx,const struct dccg_registers * regs,const struct dccg_shift * dccg_shift,const struct dccg_mask * dccg_mask)336 struct dccg *dccg32_create(
337 struct dc_context *ctx,
338 const struct dccg_registers *regs,
339 const struct dccg_shift *dccg_shift,
340 const struct dccg_mask *dccg_mask)
341 {
342 struct dcn_dccg *dccg_dcn = kzalloc(sizeof(*dccg_dcn), GFP_KERNEL);
343 struct dccg *base;
344
345 if (dccg_dcn == NULL) {
346 BREAK_TO_DEBUGGER();
347 return NULL;
348 }
349
350 base = &dccg_dcn->base;
351 base->ctx = ctx;
352 base->funcs = &dccg32_funcs;
353
354 dccg_dcn->regs = regs;
355 dccg_dcn->dccg_shift = dccg_shift;
356 dccg_dcn->dccg_mask = dccg_mask;
357
358 return &dccg_dcn->base;
359 }
360