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