]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blob - drivers/gpu/drm/amd/display/dc/dce/dce_opp.c
Merge remote-tracking branches 'asoc/topic/tscs42xx', 'asoc/topic/twl4030', 'asoc...
[mirror_ubuntu-hirsute-kernel.git] / drivers / gpu / drm / amd / display / dc / dce / dce_opp.c
1 /*
2 * Copyright 2012-15 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 "dm_services.h"
27 #include "basics/conversion.h"
28
29 #include "dce_opp.h"
30
31 #include "reg_helper.h"
32
33 #define REG(reg)\
34 (opp110->regs->reg)
35
36 #undef FN
37 #define FN(reg_name, field_name) \
38 opp110->opp_shift->field_name, opp110->opp_mask->field_name
39
40 #define CTX \
41 opp110->base.ctx
42
43 enum {
44 MAX_PWL_ENTRY = 128,
45 MAX_REGIONS_NUMBER = 16
46 };
47
48 enum {
49 MAX_LUT_ENTRY = 256,
50 MAX_NUMBER_OF_ENTRIES = 256
51 };
52
53
54 enum {
55 OUTPUT_CSC_MATRIX_SIZE = 12
56 };
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79 /*
80 *****************************************************************************
81 * Function: regamma_config_regions_and_segments
82 *
83 * build regamma curve by using predefined hw points
84 * uses interface parameters ,like EDID coeff.
85 *
86 * @param : parameters interface parameters
87 * @return void
88 *
89 * @note
90 *
91 * @see
92 *
93 *****************************************************************************
94 */
95
96
97
98 /**
99 * set_truncation
100 * 1) set truncation depth: 0 for 18 bpp or 1 for 24 bpp
101 * 2) enable truncation
102 * 3) HW remove 12bit FMT support for DCE11 power saving reason.
103 */
104 static void set_truncation(
105 struct dce110_opp *opp110,
106 const struct bit_depth_reduction_params *params)
107 {
108 /*Disable truncation*/
109 REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
110 FMT_TRUNCATE_EN, 0,
111 FMT_TRUNCATE_DEPTH, 0,
112 FMT_TRUNCATE_MODE, 0);
113
114
115 if (params->pixel_encoding == PIXEL_ENCODING_YCBCR422) {
116 /* 8bpc trunc on YCbCr422*/
117 if (params->flags.TRUNCATE_DEPTH == 1)
118 REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
119 FMT_TRUNCATE_EN, 1,
120 FMT_TRUNCATE_DEPTH, 1,
121 FMT_TRUNCATE_MODE, 0);
122 else if (params->flags.TRUNCATE_DEPTH == 2)
123 /* 10bpc trunc on YCbCr422*/
124 REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
125 FMT_TRUNCATE_EN, 1,
126 FMT_TRUNCATE_DEPTH, 2,
127 FMT_TRUNCATE_MODE, 0);
128 return;
129 }
130 /* on other format-to do */
131 if (params->flags.TRUNCATE_ENABLED == 0 ||
132 params->flags.TRUNCATE_DEPTH == 2)
133 return;
134 /*Set truncation depth and Enable truncation*/
135 REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
136 FMT_TRUNCATE_EN, 1,
137 FMT_TRUNCATE_DEPTH,
138 params->flags.TRUNCATE_MODE,
139 FMT_TRUNCATE_MODE,
140 params->flags.TRUNCATE_DEPTH);
141 }
142
143
144 /**
145 * set_spatial_dither
146 * 1) set spatial dithering mode: pattern of seed
147 * 2) set spatical dithering depth: 0 for 18bpp or 1 for 24bpp
148 * 3) set random seed
149 * 4) set random mode
150 * lfsr is reset every frame or not reset
151 * RGB dithering method
152 * 0: RGB data are all dithered with x^28+x^3+1
153 * 1: R data is dithered with x^28+x^3+1
154 * G data is dithered with x^28+X^9+1
155 * B data is dithered with x^28+x^13+1
156 * enable high pass filter or not
157 * 5) enable spatical dithering
158 */
159 static void set_spatial_dither(
160 struct dce110_opp *opp110,
161 const struct bit_depth_reduction_params *params)
162 {
163 /*Disable spatial (random) dithering*/
164 REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
165 FMT_SPATIAL_DITHER_EN, 0,
166 FMT_SPATIAL_DITHER_DEPTH, 0,
167 FMT_SPATIAL_DITHER_MODE, 0);
168
169 REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
170 FMT_HIGHPASS_RANDOM_ENABLE, 0,
171 FMT_FRAME_RANDOM_ENABLE, 0,
172 FMT_RGB_RANDOM_ENABLE, 0);
173
174 REG_UPDATE(FMT_BIT_DEPTH_CONTROL,
175 FMT_TEMPORAL_DITHER_EN, 0);
176
177 /* no 10bpc on DCE11*/
178 if (params->flags.SPATIAL_DITHER_ENABLED == 0 ||
179 params->flags.SPATIAL_DITHER_DEPTH == 2)
180 return;
181
182 /* only use FRAME_COUNTER_MAX if frameRandom == 1*/
183
184 if (opp110->opp_mask->FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX &&
185 opp110->opp_mask->FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP) {
186 if (params->flags.FRAME_RANDOM == 1) {
187 if (params->flags.SPATIAL_DITHER_DEPTH == 0 ||
188 params->flags.SPATIAL_DITHER_DEPTH == 1) {
189 REG_UPDATE_2(FMT_CONTROL,
190 FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, 15,
191 FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, 2);
192 } else if (params->flags.SPATIAL_DITHER_DEPTH == 2) {
193 REG_UPDATE_2(FMT_CONTROL,
194 FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, 3,
195 FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, 1);
196 } else
197 return;
198 } else {
199 REG_UPDATE_2(FMT_CONTROL,
200 FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, 0,
201 FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, 0);
202 }
203 }
204 /* Set seed for random values for
205 * spatial dithering for R,G,B channels
206 */
207 REG_UPDATE(FMT_DITHER_RAND_R_SEED,
208 FMT_RAND_R_SEED, params->r_seed_value);
209
210 REG_UPDATE(FMT_DITHER_RAND_G_SEED,
211 FMT_RAND_G_SEED, params->g_seed_value);
212
213 REG_UPDATE(FMT_DITHER_RAND_B_SEED,
214 FMT_RAND_B_SEED, params->b_seed_value);
215
216 /* FMT_OFFSET_R_Cr 31:16 0x0 Setting the zero
217 * offset for the R/Cr channel, lower 4LSB
218 * is forced to zeros. Typically set to 0
219 * RGB and 0x80000 YCbCr.
220 */
221 /* FMT_OFFSET_G_Y 31:16 0x0 Setting the zero
222 * offset for the G/Y channel, lower 4LSB is
223 * forced to zeros. Typically set to 0 RGB
224 * and 0x80000 YCbCr.
225 */
226 /* FMT_OFFSET_B_Cb 31:16 0x0 Setting the zero
227 * offset for the B/Cb channel, lower 4LSB is
228 * forced to zeros. Typically set to 0 RGB and
229 * 0x80000 YCbCr.
230 */
231
232 /* Disable High pass filter
233 * Reset only at startup
234 * Set RGB data dithered with x^28+x^3+1
235 */
236 REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
237 FMT_HIGHPASS_RANDOM_ENABLE, params->flags.HIGHPASS_RANDOM,
238 FMT_FRAME_RANDOM_ENABLE, params->flags.FRAME_RANDOM,
239 FMT_RGB_RANDOM_ENABLE, params->flags.RGB_RANDOM);
240
241 /* Set spatial dithering bit depth
242 * Set spatial dithering mode
243 * (default is Seed patterrn AAAA...)
244 * Enable spatial dithering
245 */
246 REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
247 FMT_SPATIAL_DITHER_DEPTH, params->flags.SPATIAL_DITHER_DEPTH,
248 FMT_SPATIAL_DITHER_MODE, params->flags.SPATIAL_DITHER_MODE,
249 FMT_SPATIAL_DITHER_EN, 1);
250 }
251
252 /**
253 * SetTemporalDither (Frame Modulation)
254 * 1) set temporal dither depth
255 * 2) select pattern: from hard-coded pattern or programmable pattern
256 * 3) select optimized strips for BGR or RGB LCD sub-pixel
257 * 4) set s matrix
258 * 5) set t matrix
259 * 6) set grey level for 0.25, 0.5, 0.75
260 * 7) enable temporal dithering
261 */
262
263 static void set_temporal_dither(
264 struct dce110_opp *opp110,
265 const struct bit_depth_reduction_params *params)
266 {
267 /*Disable temporal (frame modulation) dithering first*/
268 REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
269 FMT_TEMPORAL_DITHER_EN, 0,
270 FMT_TEMPORAL_DITHER_RESET, 0,
271 FMT_TEMPORAL_DITHER_OFFSET, 0);
272
273 REG_UPDATE_2(FMT_BIT_DEPTH_CONTROL,
274 FMT_TEMPORAL_DITHER_DEPTH, 0,
275 FMT_TEMPORAL_LEVEL, 0);
276
277 REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
278 FMT_25FRC_SEL, 0,
279 FMT_50FRC_SEL, 0,
280 FMT_75FRC_SEL, 0);
281
282 /* no 10bpc dither on DCE11*/
283 if (params->flags.FRAME_MODULATION_ENABLED == 0 ||
284 params->flags.FRAME_MODULATION_DEPTH == 2)
285 return;
286
287 /* Set temporal dithering depth*/
288 REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
289 FMT_TEMPORAL_DITHER_DEPTH, params->flags.FRAME_MODULATION_DEPTH,
290 FMT_TEMPORAL_DITHER_RESET, 0,
291 FMT_TEMPORAL_DITHER_OFFSET, 0);
292
293 /*Select legacy pattern based on FRC and Temporal level*/
294 if (REG(FMT_TEMPORAL_DITHER_PATTERN_CONTROL)) {
295 REG_WRITE(FMT_TEMPORAL_DITHER_PATTERN_CONTROL, 0);
296 /*Set s matrix*/
297 REG_WRITE(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX, 0);
298 /*Set t matrix*/
299 REG_WRITE(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX, 0);
300 }
301
302 /*Select patterns for 0.25, 0.5 and 0.75 grey level*/
303 REG_UPDATE(FMT_BIT_DEPTH_CONTROL,
304 FMT_TEMPORAL_LEVEL, params->flags.TEMPORAL_LEVEL);
305
306 REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
307 FMT_25FRC_SEL, params->flags.FRC25,
308 FMT_50FRC_SEL, params->flags.FRC50,
309 FMT_75FRC_SEL, params->flags.FRC75);
310
311 /*Enable bit reduction by temporal (frame modulation) dithering*/
312 REG_UPDATE(FMT_BIT_DEPTH_CONTROL,
313 FMT_TEMPORAL_DITHER_EN, 1);
314 }
315
316 /**
317 * Set Clamping
318 * 1) Set clamping format based on bpc - 0 for 6bpc (No clamping)
319 * 1 for 8 bpc
320 * 2 for 10 bpc
321 * 3 for 12 bpc
322 * 7 for programable
323 * 2) Enable clamp if Limited range requested
324 */
325 void dce110_opp_set_clamping(
326 struct dce110_opp *opp110,
327 const struct clamping_and_pixel_encoding_params *params)
328 {
329 REG_SET_2(FMT_CLAMP_CNTL, 0,
330 FMT_CLAMP_DATA_EN, 0,
331 FMT_CLAMP_COLOR_FORMAT, 0);
332
333 switch (params->clamping_level) {
334 case CLAMPING_FULL_RANGE:
335 break;
336 case CLAMPING_LIMITED_RANGE_8BPC:
337 REG_SET_2(FMT_CLAMP_CNTL, 0,
338 FMT_CLAMP_DATA_EN, 1,
339 FMT_CLAMP_COLOR_FORMAT, 1);
340 break;
341 case CLAMPING_LIMITED_RANGE_10BPC:
342 REG_SET_2(FMT_CLAMP_CNTL, 0,
343 FMT_CLAMP_DATA_EN, 1,
344 FMT_CLAMP_COLOR_FORMAT, 2);
345 break;
346 case CLAMPING_LIMITED_RANGE_12BPC:
347 REG_SET_2(FMT_CLAMP_CNTL, 0,
348 FMT_CLAMP_DATA_EN, 1,
349 FMT_CLAMP_COLOR_FORMAT, 3);
350 break;
351 case CLAMPING_LIMITED_RANGE_PROGRAMMABLE:
352 /*Set clamp control*/
353 REG_SET_2(FMT_CLAMP_CNTL, 0,
354 FMT_CLAMP_DATA_EN, 1,
355 FMT_CLAMP_COLOR_FORMAT, 7);
356
357 /*set the defaults*/
358 REG_SET_2(FMT_CLAMP_COMPONENT_R, 0,
359 FMT_CLAMP_LOWER_R, 0x10,
360 FMT_CLAMP_UPPER_R, 0xFEF);
361
362 REG_SET_2(FMT_CLAMP_COMPONENT_G, 0,
363 FMT_CLAMP_LOWER_G, 0x10,
364 FMT_CLAMP_UPPER_G, 0xFEF);
365
366 REG_SET_2(FMT_CLAMP_COMPONENT_B, 0,
367 FMT_CLAMP_LOWER_B, 0x10,
368 FMT_CLAMP_UPPER_B, 0xFEF);
369 break;
370 default:
371 break;
372 }
373 }
374
375 /**
376 * set_pixel_encoding
377 *
378 * Set Pixel Encoding
379 * 0: RGB 4:4:4 or YCbCr 4:4:4 or YOnly
380 * 1: YCbCr 4:2:2
381 */
382 static void set_pixel_encoding(
383 struct dce110_opp *opp110,
384 const struct clamping_and_pixel_encoding_params *params)
385 {
386 if (opp110->opp_mask->FMT_CBCR_BIT_REDUCTION_BYPASS)
387 REG_UPDATE_3(FMT_CONTROL,
388 FMT_PIXEL_ENCODING, 0,
389 FMT_SUBSAMPLING_MODE, 0,
390 FMT_CBCR_BIT_REDUCTION_BYPASS, 0);
391 else
392 REG_UPDATE_2(FMT_CONTROL,
393 FMT_PIXEL_ENCODING, 0,
394 FMT_SUBSAMPLING_MODE, 0);
395
396 if (params->pixel_encoding == PIXEL_ENCODING_YCBCR422) {
397 REG_UPDATE_2(FMT_CONTROL,
398 FMT_PIXEL_ENCODING, 1,
399 FMT_SUBSAMPLING_ORDER, 0);
400 }
401 if (params->pixel_encoding == PIXEL_ENCODING_YCBCR420) {
402 REG_UPDATE_3(FMT_CONTROL,
403 FMT_PIXEL_ENCODING, 2,
404 FMT_SUBSAMPLING_MODE, 2,
405 FMT_CBCR_BIT_REDUCTION_BYPASS, 1);
406 }
407
408 }
409
410 void dce110_opp_program_bit_depth_reduction(
411 struct output_pixel_processor *opp,
412 const struct bit_depth_reduction_params *params)
413 {
414 struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
415
416 set_truncation(opp110, params);
417 set_spatial_dither(opp110, params);
418 set_temporal_dither(opp110, params);
419 }
420
421 void dce110_opp_program_clamping_and_pixel_encoding(
422 struct output_pixel_processor *opp,
423 const struct clamping_and_pixel_encoding_params *params)
424 {
425 struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
426
427 dce110_opp_set_clamping(opp110, params);
428 set_pixel_encoding(opp110, params);
429 }
430
431 static void program_formatter_420_memory(struct output_pixel_processor *opp)
432 {
433 struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
434 uint32_t fmt_mem_cntl_value;
435
436 /* Program source select*/
437 /* Use HW default source select for FMT_MEMORYx_CONTROL */
438 /* Use that value for FMT_SRC_SELECT as well*/
439 REG_GET(CONTROL,
440 FMT420_MEM0_SOURCE_SEL, &fmt_mem_cntl_value);
441
442 REG_UPDATE(FMT_CONTROL,
443 FMT_SRC_SELECT, fmt_mem_cntl_value);
444
445 /* Turn on the memory */
446 REG_UPDATE(CONTROL,
447 FMT420_MEM0_PWR_FORCE, 0);
448 }
449
450 void dce110_opp_set_dyn_expansion(
451 struct output_pixel_processor *opp,
452 enum dc_color_space color_sp,
453 enum dc_color_depth color_dpth,
454 enum signal_type signal)
455 {
456 struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
457
458 REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL,
459 FMT_DYNAMIC_EXP_EN, 0,
460 FMT_DYNAMIC_EXP_MODE, 0);
461
462 /*00 - 10-bit -> 12-bit dynamic expansion*/
463 /*01 - 8-bit -> 12-bit dynamic expansion*/
464 if (signal == SIGNAL_TYPE_HDMI_TYPE_A ||
465 signal == SIGNAL_TYPE_DISPLAY_PORT ||
466 signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
467 switch (color_dpth) {
468 case COLOR_DEPTH_888:
469 REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL,
470 FMT_DYNAMIC_EXP_EN, 1,
471 FMT_DYNAMIC_EXP_MODE, 1);
472 break;
473 case COLOR_DEPTH_101010:
474 REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL,
475 FMT_DYNAMIC_EXP_EN, 1,
476 FMT_DYNAMIC_EXP_MODE, 0);
477 break;
478 case COLOR_DEPTH_121212:
479 REG_UPDATE_2(
480 FMT_DYNAMIC_EXP_CNTL,
481 FMT_DYNAMIC_EXP_EN, 1,/*otherwise last two bits are zero*/
482 FMT_DYNAMIC_EXP_MODE, 0);
483 break;
484 default:
485 break;
486 }
487 }
488 }
489
490 static void program_formatter_reset_dig_resync_fifo(struct output_pixel_processor *opp)
491 {
492 struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
493
494 /* clear previous phase lock status*/
495 REG_UPDATE(FMT_CONTROL,
496 FMT_420_PIXEL_PHASE_LOCKED_CLEAR, 1);
497
498 /* poll until FMT_420_PIXEL_PHASE_LOCKED become 1*/
499 REG_WAIT(FMT_CONTROL, FMT_420_PIXEL_PHASE_LOCKED, 1, 10, 10);
500
501 }
502
503 void dce110_opp_program_fmt(
504 struct output_pixel_processor *opp,
505 struct bit_depth_reduction_params *fmt_bit_depth,
506 struct clamping_and_pixel_encoding_params *clamping)
507 {
508 /* dithering is affected by <CrtcSourceSelect>, hence should be
509 * programmed afterwards */
510
511 if (clamping->pixel_encoding == PIXEL_ENCODING_YCBCR420)
512 program_formatter_420_memory(opp);
513
514 dce110_opp_program_bit_depth_reduction(
515 opp,
516 fmt_bit_depth);
517
518 dce110_opp_program_clamping_and_pixel_encoding(
519 opp,
520 clamping);
521
522 if (clamping->pixel_encoding == PIXEL_ENCODING_YCBCR420)
523 program_formatter_reset_dig_resync_fifo(opp);
524
525 return;
526 }
527
528
529
530
531
532 /*****************************************/
533 /* Constructor, Destructor */
534 /*****************************************/
535
536 static const struct opp_funcs funcs = {
537 .opp_set_dyn_expansion = dce110_opp_set_dyn_expansion,
538 .opp_destroy = dce110_opp_destroy,
539 .opp_program_fmt = dce110_opp_program_fmt,
540 .opp_program_bit_depth_reduction = dce110_opp_program_bit_depth_reduction
541 };
542
543 void dce110_opp_construct(struct dce110_opp *opp110,
544 struct dc_context *ctx,
545 uint32_t inst,
546 const struct dce_opp_registers *regs,
547 const struct dce_opp_shift *opp_shift,
548 const struct dce_opp_mask *opp_mask)
549 {
550 opp110->base.funcs = &funcs;
551
552 opp110->base.ctx = ctx;
553
554 opp110->base.inst = inst;
555
556 opp110->regs = regs;
557 opp110->opp_shift = opp_shift;
558 opp110->opp_mask = opp_mask;
559 }
560
561 void dce110_opp_destroy(struct output_pixel_processor **opp)
562 {
563 if (*opp)
564 kfree(FROM_DCE11_OPP(*opp));
565 *opp = NULL;
566 }
567