Line data Source code
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 0 : static void dccg314_set_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 0 : struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
55 :
56 0 : switch (otg_inst) {
57 : case 0:
58 0 : REG_UPDATE_2(OTG_PIXEL_RATE_DIV,
59 : OTG0_PIXEL_RATE_DIVK1, k1,
60 : OTG0_PIXEL_RATE_DIVK2, k2);
61 0 : break;
62 : case 1:
63 0 : REG_UPDATE_2(OTG_PIXEL_RATE_DIV,
64 : OTG1_PIXEL_RATE_DIVK1, k1,
65 : OTG1_PIXEL_RATE_DIVK2, k2);
66 0 : break;
67 : case 2:
68 0 : REG_UPDATE_2(OTG_PIXEL_RATE_DIV,
69 : OTG2_PIXEL_RATE_DIVK1, k1,
70 : OTG2_PIXEL_RATE_DIVK2, k2);
71 0 : break;
72 : case 3:
73 0 : REG_UPDATE_2(OTG_PIXEL_RATE_DIV,
74 : OTG3_PIXEL_RATE_DIVK1, k1,
75 : OTG3_PIXEL_RATE_DIVK2, k2);
76 0 : break;
77 : default:
78 0 : BREAK_TO_DEBUGGER();
79 0 : return;
80 : }
81 : }
82 :
83 0 : static void dccg314_set_dtbclk_p_src(
84 : struct dccg *dccg,
85 : enum streamclk_source src,
86 : uint32_t otg_inst)
87 : {
88 0 : struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
89 :
90 0 : uint32_t p_src_sel = 0; /* selects dprefclk */
91 :
92 0 : if (src == DTBCLK0)
93 0 : p_src_sel = 2; /* selects dtbclk0 */
94 :
95 0 : switch (otg_inst) {
96 : case 0:
97 0 : if (src == REFCLK)
98 0 : REG_UPDATE(DTBCLK_P_CNTL,
99 : DTBCLK_P0_EN, 0);
100 : else
101 0 : REG_UPDATE_2(DTBCLK_P_CNTL,
102 : DTBCLK_P0_SRC_SEL, p_src_sel,
103 : DTBCLK_P0_EN, 1);
104 : break;
105 : case 1:
106 0 : if (src == REFCLK)
107 0 : REG_UPDATE(DTBCLK_P_CNTL,
108 : DTBCLK_P1_EN, 0);
109 : else
110 0 : REG_UPDATE_2(DTBCLK_P_CNTL,
111 : DTBCLK_P1_SRC_SEL, p_src_sel,
112 : DTBCLK_P1_EN, 1);
113 : break;
114 : case 2:
115 0 : if (src == REFCLK)
116 0 : REG_UPDATE(DTBCLK_P_CNTL,
117 : DTBCLK_P2_EN, 0);
118 : else
119 0 : REG_UPDATE_2(DTBCLK_P_CNTL,
120 : DTBCLK_P2_SRC_SEL, p_src_sel,
121 : DTBCLK_P2_EN, 1);
122 : break;
123 : case 3:
124 0 : if (src == REFCLK)
125 0 : REG_UPDATE(DTBCLK_P_CNTL,
126 : DTBCLK_P3_EN, 0);
127 : else
128 0 : REG_UPDATE_2(DTBCLK_P_CNTL,
129 : DTBCLK_P3_SRC_SEL, p_src_sel,
130 : DTBCLK_P3_EN, 1);
131 : break;
132 : default:
133 0 : BREAK_TO_DEBUGGER();
134 0 : return;
135 : }
136 :
137 : }
138 :
139 : /* Controls the generation of pixel valid for OTG in (OTG -> HPO case) */
140 0 : void dccg314_set_dtbclk_dto(
141 : struct dccg *dccg,
142 : const struct dtbclk_dto_params *params)
143 : {
144 0 : struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
145 : /* DTO Output Rate / Pixel Rate = 1/4 */
146 0 : int req_dtbclk_khz = params->pixclk_khz / 4;
147 :
148 0 : if (params->ref_dtbclk_khz && req_dtbclk_khz) {
149 : uint32_t modulo, phase;
150 :
151 : // phase / modulo = dtbclk / dtbclk ref
152 0 : modulo = params->ref_dtbclk_khz * 1000;
153 0 : phase = req_dtbclk_khz * 1000;
154 :
155 0 : REG_WRITE(DTBCLK_DTO_MODULO[params->otg_inst], modulo);
156 0 : REG_WRITE(DTBCLK_DTO_PHASE[params->otg_inst], phase);
157 :
158 0 : REG_UPDATE(OTG_PIXEL_RATE_CNTL[params->otg_inst],
159 : DTBCLK_DTO_ENABLE[params->otg_inst], 1);
160 :
161 0 : REG_WAIT(OTG_PIXEL_RATE_CNTL[params->otg_inst],
162 : DTBCLKDTO_ENABLE_STATUS[params->otg_inst], 1,
163 : 1, 100);
164 :
165 : /* program OTG_PIXEL_RATE_DIV for DIVK1 and DIVK2 fields */
166 0 : dccg314_set_pixel_rate_div(dccg, params->otg_inst, PIXEL_RATE_DIV_BY_1, PIXEL_RATE_DIV_BY_1);
167 :
168 : /* The recommended programming sequence to enable DTBCLK DTO to generate
169 : * valid pixel HPO DPSTREAM ENCODER, specifies that DTO source select should
170 : * be set only after DTO is enabled
171 : */
172 0 : REG_UPDATE(OTG_PIXEL_RATE_CNTL[params->otg_inst],
173 : PIPE_DTO_SRC_SEL[params->otg_inst], 2);
174 : } else {
175 0 : REG_UPDATE_2(OTG_PIXEL_RATE_CNTL[params->otg_inst],
176 : DTBCLK_DTO_ENABLE[params->otg_inst], 0,
177 : PIPE_DTO_SRC_SEL[params->otg_inst], 1);
178 :
179 0 : REG_WRITE(DTBCLK_DTO_MODULO[params->otg_inst], 0);
180 0 : REG_WRITE(DTBCLK_DTO_PHASE[params->otg_inst], 0);
181 : }
182 0 : }
183 :
184 0 : void dccg314_set_dpstreamclk(
185 : struct dccg *dccg,
186 : enum streamclk_source src,
187 : int otg_inst,
188 : int dp_hpo_inst)
189 : {
190 0 : struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
191 :
192 : /* set the dtbclk_p source */
193 0 : dccg314_set_dtbclk_p_src(dccg, src, otg_inst);
194 :
195 : /* enabled to select one of the DTBCLKs for pipe */
196 0 : switch (dp_hpo_inst) {
197 : case 0:
198 0 : REG_UPDATE_2(DPSTREAMCLK_CNTL,
199 : DPSTREAMCLK0_EN, (src == REFCLK) ? 0 : 1,
200 : DPSTREAMCLK0_SRC_SEL, otg_inst);
201 0 : break;
202 : case 1:
203 0 : REG_UPDATE_2(DPSTREAMCLK_CNTL,
204 : DPSTREAMCLK1_EN, (src == REFCLK) ? 0 : 1,
205 : DPSTREAMCLK1_SRC_SEL, otg_inst);
206 0 : break;
207 : case 2:
208 0 : REG_UPDATE_2(DPSTREAMCLK_CNTL,
209 : DPSTREAMCLK2_EN, (src == REFCLK) ? 0 : 1,
210 : DPSTREAMCLK2_SRC_SEL, otg_inst);
211 0 : break;
212 : case 3:
213 0 : REG_UPDATE_2(DPSTREAMCLK_CNTL,
214 : DPSTREAMCLK3_EN, (src == REFCLK) ? 0 : 1,
215 : DPSTREAMCLK3_SRC_SEL, otg_inst);
216 0 : break;
217 : default:
218 0 : BREAK_TO_DEBUGGER();
219 0 : return;
220 : }
221 : }
222 :
223 0 : void dccg314_set_valid_pixel_rate(
224 : struct dccg *dccg,
225 : int ref_dtbclk_khz,
226 : int otg_inst,
227 : int pixclk_khz)
228 : {
229 0 : struct dtbclk_dto_params dto_params = {0};
230 :
231 0 : dto_params.ref_dtbclk_khz = ref_dtbclk_khz;
232 0 : dto_params.otg_inst = otg_inst;
233 0 : dto_params.pixclk_khz = pixclk_khz;
234 :
235 0 : dccg314_set_dtbclk_dto(dccg, &dto_params);
236 0 : }
237 :
238 : static const struct dccg_funcs dccg314_funcs = {
239 : .update_dpp_dto = dccg31_update_dpp_dto,
240 : .get_dccg_ref_freq = dccg31_get_dccg_ref_freq,
241 : .dccg_init = dccg31_init,
242 : .set_dpstreamclk = dccg314_set_dpstreamclk,
243 : .enable_symclk32_se = dccg31_enable_symclk32_se,
244 : .disable_symclk32_se = dccg31_disable_symclk32_se,
245 : .enable_symclk32_le = dccg31_enable_symclk32_le,
246 : .disable_symclk32_le = dccg31_disable_symclk32_le,
247 : .set_physymclk = dccg31_set_physymclk,
248 : .set_dtbclk_dto = dccg314_set_dtbclk_dto,
249 : .set_audio_dtbclk_dto = dccg31_set_audio_dtbclk_dto,
250 : .set_fifo_errdet_ovr_en = dccg2_set_fifo_errdet_ovr_en,
251 : .otg_add_pixel = dccg31_otg_add_pixel,
252 : .otg_drop_pixel = dccg31_otg_drop_pixel,
253 : .set_dispclk_change_mode = dccg31_set_dispclk_change_mode,
254 : .disable_dsc = dccg31_disable_dscclk,
255 : .enable_dsc = dccg31_enable_dscclk,
256 : .set_pixel_rate_div = dccg314_set_pixel_rate_div,
257 : .set_valid_pixel_rate = dccg314_set_valid_pixel_rate,
258 : };
259 :
260 0 : struct dccg *dccg314_create(
261 : struct dc_context *ctx,
262 : const struct dccg_registers *regs,
263 : const struct dccg_shift *dccg_shift,
264 : const struct dccg_mask *dccg_mask)
265 : {
266 0 : struct dcn_dccg *dccg_dcn = kzalloc(sizeof(*dccg_dcn), GFP_KERNEL);
267 : struct dccg *base;
268 :
269 0 : if (dccg_dcn == NULL) {
270 0 : BREAK_TO_DEBUGGER();
271 0 : return NULL;
272 : }
273 :
274 0 : base = &dccg_dcn->base;
275 0 : base->ctx = ctx;
276 0 : base->funcs = &dccg314_funcs;
277 :
278 0 : dccg_dcn->regs = regs;
279 0 : dccg_dcn->dccg_shift = dccg_shift;
280 0 : dccg_dcn->dccg_mask = dccg_mask;
281 :
282 0 : return &dccg_dcn->base;
283 : }
|