1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26#include "dm_services.h"
27#include "dcn10_opp.h"
28#include "reg_helper.h"
29
30#define REG(reg) \
31 (oppn10->regs->reg)
32
33#undef FN
34#define FN(reg_name, field_name) \
35 oppn10->opp_shift->field_name, oppn10->opp_mask->field_name
36
37#define CTX \
38 oppn10->base.ctx
39
40
41
42
43
44
45
46
47
48
49static void opp1_set_truncation(
50 struct dcn10_opp *oppn10,
51 const struct bit_depth_reduction_params *params)
52{
53 REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
54 FMT_TRUNCATE_EN, params->flags.TRUNCATE_ENABLED,
55 FMT_TRUNCATE_DEPTH, params->flags.TRUNCATE_DEPTH,
56 FMT_TRUNCATE_MODE, params->flags.TRUNCATE_MODE);
57}
58
59static void opp1_set_spatial_dither(
60 struct dcn10_opp *oppn10,
61 const struct bit_depth_reduction_params *params)
62{
63
64 REG_UPDATE_7(FMT_BIT_DEPTH_CONTROL,
65 FMT_SPATIAL_DITHER_EN, 0,
66 FMT_SPATIAL_DITHER_MODE, 0,
67 FMT_SPATIAL_DITHER_DEPTH, 0,
68 FMT_TEMPORAL_DITHER_EN, 0,
69 FMT_HIGHPASS_RANDOM_ENABLE, 0,
70 FMT_FRAME_RANDOM_ENABLE, 0,
71 FMT_RGB_RANDOM_ENABLE, 0);
72
73
74
75 if (params->flags.FRAME_RANDOM == 1) {
76 if (params->flags.SPATIAL_DITHER_DEPTH == 0 || params->flags.SPATIAL_DITHER_DEPTH == 1) {
77 REG_UPDATE_2(FMT_CONTROL,
78 FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, 15,
79 FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, 2);
80 } else if (params->flags.SPATIAL_DITHER_DEPTH == 2) {
81 REG_UPDATE_2(FMT_CONTROL,
82 FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, 3,
83 FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, 1);
84 } else {
85 return;
86 }
87 } else {
88 REG_UPDATE_2(FMT_CONTROL,
89 FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, 0,
90 FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, 0);
91 }
92
93
94
95
96 REG_SET(FMT_DITHER_RAND_R_SEED, 0,
97 FMT_RAND_R_SEED, params->r_seed_value);
98
99 REG_SET(FMT_DITHER_RAND_G_SEED, 0,
100 FMT_RAND_G_SEED, params->g_seed_value);
101
102 REG_SET(FMT_DITHER_RAND_B_SEED, 0,
103 FMT_RAND_B_SEED, params->b_seed_value);
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121 REG_UPDATE_6(FMT_BIT_DEPTH_CONTROL,
122
123 FMT_SPATIAL_DITHER_EN, params->flags.SPATIAL_DITHER_ENABLED,
124
125
126
127 FMT_SPATIAL_DITHER_MODE, params->flags.SPATIAL_DITHER_MODE,
128
129 FMT_SPATIAL_DITHER_DEPTH, params->flags.SPATIAL_DITHER_DEPTH,
130
131 FMT_HIGHPASS_RANDOM_ENABLE, params->flags.HIGHPASS_RANDOM,
132
133 FMT_FRAME_RANDOM_ENABLE, params->flags.FRAME_RANDOM,
134
135 FMT_RGB_RANDOM_ENABLE, params->flags.RGB_RANDOM);
136}
137
138void opp1_program_bit_depth_reduction(
139 struct output_pixel_processor *opp,
140 const struct bit_depth_reduction_params *params)
141{
142 struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp);
143
144 opp1_set_truncation(oppn10, params);
145 opp1_set_spatial_dither(oppn10, params);
146
147
148
149}
150
151
152
153
154
155
156
157
158static void opp1_set_pixel_encoding(
159 struct dcn10_opp *oppn10,
160 const struct clamping_and_pixel_encoding_params *params)
161{
162 switch (params->pixel_encoding) {
163
164 case PIXEL_ENCODING_RGB:
165 case PIXEL_ENCODING_YCBCR444:
166 REG_UPDATE(FMT_CONTROL, FMT_PIXEL_ENCODING, 0);
167 break;
168 case PIXEL_ENCODING_YCBCR422:
169 REG_UPDATE(FMT_CONTROL, FMT_PIXEL_ENCODING, 1);
170 break;
171 case PIXEL_ENCODING_YCBCR420:
172 REG_UPDATE(FMT_CONTROL, FMT_PIXEL_ENCODING, 2);
173 break;
174 default:
175 break;
176 }
177}
178
179
180
181
182
183
184
185
186
187
188static void opp1_set_clamping(
189 struct dcn10_opp *oppn10,
190 const struct clamping_and_pixel_encoding_params *params)
191{
192 REG_UPDATE_2(FMT_CLAMP_CNTL,
193 FMT_CLAMP_DATA_EN, 0,
194 FMT_CLAMP_COLOR_FORMAT, 0);
195
196 switch (params->clamping_level) {
197 case CLAMPING_FULL_RANGE:
198 REG_UPDATE_2(FMT_CLAMP_CNTL,
199 FMT_CLAMP_DATA_EN, 1,
200 FMT_CLAMP_COLOR_FORMAT, 0);
201 break;
202 case CLAMPING_LIMITED_RANGE_8BPC:
203 REG_UPDATE_2(FMT_CLAMP_CNTL,
204 FMT_CLAMP_DATA_EN, 1,
205 FMT_CLAMP_COLOR_FORMAT, 1);
206 break;
207 case CLAMPING_LIMITED_RANGE_10BPC:
208 REG_UPDATE_2(FMT_CLAMP_CNTL,
209 FMT_CLAMP_DATA_EN, 1,
210 FMT_CLAMP_COLOR_FORMAT, 2);
211
212 break;
213 case CLAMPING_LIMITED_RANGE_12BPC:
214 REG_UPDATE_2(FMT_CLAMP_CNTL,
215 FMT_CLAMP_DATA_EN, 1,
216 FMT_CLAMP_COLOR_FORMAT, 3);
217 break;
218 case CLAMPING_LIMITED_RANGE_PROGRAMMABLE:
219
220 default:
221 break;
222 }
223
224}
225
226void opp1_set_dyn_expansion(
227 struct output_pixel_processor *opp,
228 enum dc_color_space color_sp,
229 enum dc_color_depth color_dpth,
230 enum signal_type signal)
231{
232 struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp);
233
234 REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL,
235 FMT_DYNAMIC_EXP_EN, 0,
236 FMT_DYNAMIC_EXP_MODE, 0);
237
238
239
240 if (signal == SIGNAL_TYPE_HDMI_TYPE_A ||
241 signal == SIGNAL_TYPE_DISPLAY_PORT ||
242 signal == SIGNAL_TYPE_DISPLAY_PORT_MST ||
243 signal == SIGNAL_TYPE_VIRTUAL) {
244 switch (color_dpth) {
245 case COLOR_DEPTH_888:
246 REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL,
247 FMT_DYNAMIC_EXP_EN, 1,
248 FMT_DYNAMIC_EXP_MODE, 1);
249 break;
250 case COLOR_DEPTH_101010:
251 REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL,
252 FMT_DYNAMIC_EXP_EN, 1,
253 FMT_DYNAMIC_EXP_MODE, 0);
254 break;
255 case COLOR_DEPTH_121212:
256 REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL,
257 FMT_DYNAMIC_EXP_EN, 1,
258 FMT_DYNAMIC_EXP_MODE, 0);
259 break;
260 default:
261 break;
262 }
263 }
264}
265
266static void opp1_program_clamping_and_pixel_encoding(
267 struct output_pixel_processor *opp,
268 const struct clamping_and_pixel_encoding_params *params)
269{
270 struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp);
271
272 opp1_set_clamping(oppn10, params);
273 opp1_set_pixel_encoding(oppn10, params);
274}
275
276void opp1_program_fmt(
277 struct output_pixel_processor *opp,
278 struct bit_depth_reduction_params *fmt_bit_depth,
279 struct clamping_and_pixel_encoding_params *clamping)
280{
281 struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp);
282
283 if (clamping->pixel_encoding == PIXEL_ENCODING_YCBCR420)
284 REG_UPDATE(FMT_MAP420_MEMORY_CONTROL, FMT_MAP420MEM_PWR_FORCE, 0);
285
286
287
288 opp1_program_bit_depth_reduction(
289 opp,
290 fmt_bit_depth);
291
292 opp1_program_clamping_and_pixel_encoding(
293 opp,
294 clamping);
295
296 return;
297}
298
299void opp1_program_stereo(
300 struct output_pixel_processor *opp,
301 bool enable,
302 const struct dc_crtc_timing *timing)
303{
304 struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp);
305
306 uint32_t active_width = timing->h_addressable - timing->h_border_right - timing->h_border_right;
307 uint32_t space1_size = timing->v_total - timing->v_addressable;
308
309 uint32_t space2_size = timing->v_total - timing->v_addressable;
310
311 if (!enable) {
312 active_width = 0;
313 space1_size = 0;
314 space2_size = 0;
315 }
316
317
318 REG_UPDATE(FMT_CONTROL, FMT_STEREOSYNC_OVERRIDE, 0);
319
320 REG_UPDATE(OPPBUF_CONTROL, OPPBUF_ACTIVE_WIDTH, active_width);
321
322
323
324
325
326
327 if (timing->timing_3d_format == TIMING_3D_FORMAT_FRAME_ALTERNATE)
328 REG_UPDATE(OPPBUF_3D_PARAMETERS_0, OPPBUF_3D_VACT_SPACE2_SIZE, space2_size);
329 else
330 REG_UPDATE(OPPBUF_3D_PARAMETERS_0, OPPBUF_3D_VACT_SPACE1_SIZE, space1_size);
331
332
333
334
335
336
337
338
339
340
341}
342
343void opp1_program_oppbuf(
344 struct output_pixel_processor *opp,
345 struct oppbuf_params *oppbuf)
346{
347 struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp);
348
349
350 REG_UPDATE(OPPBUF_CONTROL, OPPBUF_ACTIVE_WIDTH, oppbuf->active_width);
351
352
353
354
355
356
357
358 REG_UPDATE(OPPBUF_CONTROL, OPPBUF_DISPLAY_SEGMENTATION, oppbuf->mso_segmentation);
359
360
361 REG_UPDATE(OPPBUF_CONTROL, OPPBUF_OVERLAP_PIXEL_NUM, oppbuf->mso_overlap_pixel_num);
362
363
364
365
366 REG_UPDATE(OPPBUF_CONTROL, OPPBUF_PIXEL_REPETITION, oppbuf->pixel_repetition);
367
368}
369
370void opp1_pipe_clock_control(struct output_pixel_processor *opp, bool enable)
371{
372 struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp);
373 uint32_t regval = enable ? 1 : 0;
374
375 REG_UPDATE(OPP_PIPE_CONTROL, OPP_PIPE_CLOCK_EN, regval);
376}
377
378
379
380
381
382void opp1_destroy(struct output_pixel_processor **opp)
383{
384 kfree(TO_DCN10_OPP(*opp));
385 *opp = NULL;
386}
387
388static struct opp_funcs dcn10_opp_funcs = {
389 .opp_set_dyn_expansion = opp1_set_dyn_expansion,
390 .opp_program_fmt = opp1_program_fmt,
391 .opp_program_bit_depth_reduction = opp1_program_bit_depth_reduction,
392 .opp_program_stereo = opp1_program_stereo,
393 .opp_pipe_clock_control = opp1_pipe_clock_control,
394 .opp_destroy = opp1_destroy
395};
396
397void dcn10_opp_construct(struct dcn10_opp *oppn10,
398 struct dc_context *ctx,
399 uint32_t inst,
400 const struct dcn10_opp_registers *regs,
401 const struct dcn10_opp_shift *opp_shift,
402 const struct dcn10_opp_mask *opp_mask)
403{
404
405 oppn10->base.ctx = ctx;
406 oppn10->base.inst = inst;
407 oppn10->base.funcs = &dcn10_opp_funcs;
408
409 oppn10->regs = regs;
410 oppn10->opp_shift = opp_shift;
411 oppn10->opp_mask = opp_mask;
412}
413