Line data Source code
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 0 : static void set_truncation(
105 : struct dce110_opp *opp110,
106 : const struct bit_depth_reduction_params *params)
107 : {
108 : /*Disable truncation*/
109 0 : 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 0 : if (params->pixel_encoding == PIXEL_ENCODING_YCBCR422) {
116 : /* 8bpc trunc on YCbCr422*/
117 0 : if (params->flags.TRUNCATE_DEPTH == 1)
118 0 : REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
119 : FMT_TRUNCATE_EN, 1,
120 : FMT_TRUNCATE_DEPTH, 1,
121 : FMT_TRUNCATE_MODE, 0);
122 0 : else if (params->flags.TRUNCATE_DEPTH == 2)
123 : /* 10bpc trunc on YCbCr422*/
124 0 : 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 0 : if (params->flags.TRUNCATE_ENABLED == 0)
132 : return;
133 : /*Set truncation depth and Enable truncation*/
134 0 : REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
135 : FMT_TRUNCATE_EN, 1,
136 : FMT_TRUNCATE_DEPTH,
137 : params->flags.TRUNCATE_DEPTH,
138 : FMT_TRUNCATE_MODE,
139 : params->flags.TRUNCATE_MODE);
140 : }
141 :
142 : #if defined(CONFIG_DRM_AMD_DC_SI)
143 : /*
144 : * dce60_set_truncation
145 : * 1) set truncation depth: 0 for 18 bpp or 1 for 24 bpp
146 : * 2) enable truncation
147 : * 3) HW remove 12bit FMT support for DCE11 power saving reason.
148 : */
149 : static void dce60_set_truncation(
150 : struct dce110_opp *opp110,
151 : const struct bit_depth_reduction_params *params)
152 : {
153 : /* DCE6 has no FMT_TRUNCATE_MODE bit in FMT_BIT_DEPTH_CONTROL reg */
154 :
155 : /*Disable truncation*/
156 : REG_UPDATE_2(FMT_BIT_DEPTH_CONTROL,
157 : FMT_TRUNCATE_EN, 0,
158 : FMT_TRUNCATE_DEPTH, 0);
159 :
160 : if (params->pixel_encoding == PIXEL_ENCODING_YCBCR422) {
161 : /* 8bpc trunc on YCbCr422*/
162 : if (params->flags.TRUNCATE_DEPTH == 1)
163 : REG_UPDATE_2(FMT_BIT_DEPTH_CONTROL,
164 : FMT_TRUNCATE_EN, 1,
165 : FMT_TRUNCATE_DEPTH, 1);
166 : else if (params->flags.TRUNCATE_DEPTH == 2)
167 : /* 10bpc trunc on YCbCr422*/
168 : REG_UPDATE_2(FMT_BIT_DEPTH_CONTROL,
169 : FMT_TRUNCATE_EN, 1,
170 : FMT_TRUNCATE_DEPTH, 2);
171 : return;
172 : }
173 : /* on other format-to do */
174 : if (params->flags.TRUNCATE_ENABLED == 0)
175 : return;
176 : /*Set truncation depth and Enable truncation*/
177 : REG_UPDATE_2(FMT_BIT_DEPTH_CONTROL,
178 : FMT_TRUNCATE_EN, 1,
179 : FMT_TRUNCATE_DEPTH,
180 : params->flags.TRUNCATE_DEPTH);
181 : }
182 : #endif
183 :
184 : /*
185 : * set_spatial_dither
186 : * 1) set spatial dithering mode: pattern of seed
187 : * 2) set spatial dithering depth: 0 for 18bpp or 1 for 24bpp
188 : * 3) set random seed
189 : * 4) set random mode
190 : * lfsr is reset every frame or not reset
191 : * RGB dithering method
192 : * 0: RGB data are all dithered with x^28+x^3+1
193 : * 1: R data is dithered with x^28+x^3+1
194 : * G data is dithered with x^28+X^9+1
195 : * B data is dithered with x^28+x^13+1
196 : * enable high pass filter or not
197 : * 5) enable spatical dithering
198 : */
199 0 : static void set_spatial_dither(
200 : struct dce110_opp *opp110,
201 : const struct bit_depth_reduction_params *params)
202 : {
203 : /*Disable spatial (random) dithering*/
204 0 : REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
205 : FMT_SPATIAL_DITHER_EN, 0,
206 : FMT_SPATIAL_DITHER_DEPTH, 0,
207 : FMT_SPATIAL_DITHER_MODE, 0);
208 :
209 0 : REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
210 : FMT_HIGHPASS_RANDOM_ENABLE, 0,
211 : FMT_FRAME_RANDOM_ENABLE, 0,
212 : FMT_RGB_RANDOM_ENABLE, 0);
213 :
214 0 : REG_UPDATE(FMT_BIT_DEPTH_CONTROL,
215 : FMT_TEMPORAL_DITHER_EN, 0);
216 :
217 0 : if (params->flags.SPATIAL_DITHER_ENABLED == 0)
218 : return;
219 :
220 : /* only use FRAME_COUNTER_MAX if frameRandom == 1*/
221 :
222 0 : if (opp110->opp_mask->FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX &&
223 0 : opp110->opp_mask->FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP) {
224 0 : if (params->flags.FRAME_RANDOM == 1) {
225 0 : if (params->flags.SPATIAL_DITHER_DEPTH == 0 ||
226 : params->flags.SPATIAL_DITHER_DEPTH == 1) {
227 0 : REG_UPDATE_2(FMT_CONTROL,
228 : FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, 15,
229 : FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, 2);
230 0 : } else if (params->flags.SPATIAL_DITHER_DEPTH == 2) {
231 0 : REG_UPDATE_2(FMT_CONTROL,
232 : FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, 3,
233 : FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, 1);
234 : } else
235 : return;
236 : } else {
237 0 : REG_UPDATE_2(FMT_CONTROL,
238 : FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, 0,
239 : FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, 0);
240 : }
241 : }
242 : /* Set seed for random values for
243 : * spatial dithering for R,G,B channels
244 : */
245 0 : REG_UPDATE(FMT_DITHER_RAND_R_SEED,
246 : FMT_RAND_R_SEED, params->r_seed_value);
247 :
248 0 : REG_UPDATE(FMT_DITHER_RAND_G_SEED,
249 : FMT_RAND_G_SEED, params->g_seed_value);
250 :
251 0 : REG_UPDATE(FMT_DITHER_RAND_B_SEED,
252 : FMT_RAND_B_SEED, params->b_seed_value);
253 :
254 : /* FMT_OFFSET_R_Cr 31:16 0x0 Setting the zero
255 : * offset for the R/Cr channel, lower 4LSB
256 : * is forced to zeros. Typically set to 0
257 : * RGB and 0x80000 YCbCr.
258 : */
259 : /* FMT_OFFSET_G_Y 31:16 0x0 Setting the zero
260 : * offset for the G/Y channel, lower 4LSB is
261 : * forced to zeros. Typically set to 0 RGB
262 : * and 0x80000 YCbCr.
263 : */
264 : /* FMT_OFFSET_B_Cb 31:16 0x0 Setting the zero
265 : * offset for the B/Cb channel, lower 4LSB is
266 : * forced to zeros. Typically set to 0 RGB and
267 : * 0x80000 YCbCr.
268 : */
269 :
270 : /* Disable High pass filter
271 : * Reset only at startup
272 : * Set RGB data dithered with x^28+x^3+1
273 : */
274 0 : REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
275 : FMT_HIGHPASS_RANDOM_ENABLE, params->flags.HIGHPASS_RANDOM,
276 : FMT_FRAME_RANDOM_ENABLE, params->flags.FRAME_RANDOM,
277 : FMT_RGB_RANDOM_ENABLE, params->flags.RGB_RANDOM);
278 :
279 : /* Set spatial dithering bit depth
280 : * Set spatial dithering mode
281 : * (default is Seed patterrn AAAA...)
282 : * Enable spatial dithering
283 : */
284 0 : REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
285 : FMT_SPATIAL_DITHER_DEPTH, params->flags.SPATIAL_DITHER_DEPTH,
286 : FMT_SPATIAL_DITHER_MODE, params->flags.SPATIAL_DITHER_MODE,
287 : FMT_SPATIAL_DITHER_EN, 1);
288 : }
289 :
290 : /*
291 : * SetTemporalDither (Frame Modulation)
292 : * 1) set temporal dither depth
293 : * 2) select pattern: from hard-coded pattern or programmable pattern
294 : * 3) select optimized strips for BGR or RGB LCD sub-pixel
295 : * 4) set s matrix
296 : * 5) set t matrix
297 : * 6) set grey level for 0.25, 0.5, 0.75
298 : * 7) enable temporal dithering
299 : */
300 :
301 0 : static void set_temporal_dither(
302 : struct dce110_opp *opp110,
303 : const struct bit_depth_reduction_params *params)
304 : {
305 : /*Disable temporal (frame modulation) dithering first*/
306 0 : REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
307 : FMT_TEMPORAL_DITHER_EN, 0,
308 : FMT_TEMPORAL_DITHER_RESET, 0,
309 : FMT_TEMPORAL_DITHER_OFFSET, 0);
310 :
311 0 : REG_UPDATE_2(FMT_BIT_DEPTH_CONTROL,
312 : FMT_TEMPORAL_DITHER_DEPTH, 0,
313 : FMT_TEMPORAL_LEVEL, 0);
314 :
315 0 : REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
316 : FMT_25FRC_SEL, 0,
317 : FMT_50FRC_SEL, 0,
318 : FMT_75FRC_SEL, 0);
319 :
320 : /* no 10bpc dither on DCE11*/
321 0 : if (params->flags.FRAME_MODULATION_ENABLED == 0 ||
322 0 : params->flags.FRAME_MODULATION_DEPTH == 2)
323 : return;
324 :
325 : /* Set temporal dithering depth*/
326 0 : REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
327 : FMT_TEMPORAL_DITHER_DEPTH, params->flags.FRAME_MODULATION_DEPTH,
328 : FMT_TEMPORAL_DITHER_RESET, 0,
329 : FMT_TEMPORAL_DITHER_OFFSET, 0);
330 :
331 : /*Select legacy pattern based on FRC and Temporal level*/
332 0 : if (REG(FMT_TEMPORAL_DITHER_PATTERN_CONTROL)) {
333 0 : REG_WRITE(FMT_TEMPORAL_DITHER_PATTERN_CONTROL, 0);
334 : /*Set s matrix*/
335 0 : REG_WRITE(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX, 0);
336 : /*Set t matrix*/
337 0 : REG_WRITE(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX, 0);
338 : }
339 :
340 : /*Select patterns for 0.25, 0.5 and 0.75 grey level*/
341 0 : REG_UPDATE(FMT_BIT_DEPTH_CONTROL,
342 : FMT_TEMPORAL_LEVEL, params->flags.TEMPORAL_LEVEL);
343 :
344 0 : REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
345 : FMT_25FRC_SEL, params->flags.FRC25,
346 : FMT_50FRC_SEL, params->flags.FRC50,
347 : FMT_75FRC_SEL, params->flags.FRC75);
348 :
349 : /*Enable bit reduction by temporal (frame modulation) dithering*/
350 0 : REG_UPDATE(FMT_BIT_DEPTH_CONTROL,
351 : FMT_TEMPORAL_DITHER_EN, 1);
352 : }
353 :
354 : /*
355 : * Set Clamping
356 : * 1) Set clamping format based on bpc - 0 for 6bpc (No clamping)
357 : * 1 for 8 bpc
358 : * 2 for 10 bpc
359 : * 3 for 12 bpc
360 : * 7 for programable
361 : * 2) Enable clamp if Limited range requested
362 : */
363 0 : void dce110_opp_set_clamping(
364 : struct dce110_opp *opp110,
365 : const struct clamping_and_pixel_encoding_params *params)
366 : {
367 0 : REG_SET_2(FMT_CLAMP_CNTL, 0,
368 : FMT_CLAMP_DATA_EN, 0,
369 : FMT_CLAMP_COLOR_FORMAT, 0);
370 :
371 0 : switch (params->clamping_level) {
372 : case CLAMPING_FULL_RANGE:
373 : break;
374 : case CLAMPING_LIMITED_RANGE_8BPC:
375 0 : REG_SET_2(FMT_CLAMP_CNTL, 0,
376 : FMT_CLAMP_DATA_EN, 1,
377 : FMT_CLAMP_COLOR_FORMAT, 1);
378 0 : break;
379 : case CLAMPING_LIMITED_RANGE_10BPC:
380 0 : REG_SET_2(FMT_CLAMP_CNTL, 0,
381 : FMT_CLAMP_DATA_EN, 1,
382 : FMT_CLAMP_COLOR_FORMAT, 2);
383 0 : break;
384 : case CLAMPING_LIMITED_RANGE_12BPC:
385 0 : REG_SET_2(FMT_CLAMP_CNTL, 0,
386 : FMT_CLAMP_DATA_EN, 1,
387 : FMT_CLAMP_COLOR_FORMAT, 3);
388 0 : break;
389 : case CLAMPING_LIMITED_RANGE_PROGRAMMABLE:
390 : /*Set clamp control*/
391 0 : REG_SET_2(FMT_CLAMP_CNTL, 0,
392 : FMT_CLAMP_DATA_EN, 1,
393 : FMT_CLAMP_COLOR_FORMAT, 7);
394 :
395 : /*set the defaults*/
396 0 : REG_SET_2(FMT_CLAMP_COMPONENT_R, 0,
397 : FMT_CLAMP_LOWER_R, 0x10,
398 : FMT_CLAMP_UPPER_R, 0xFEF);
399 :
400 0 : REG_SET_2(FMT_CLAMP_COMPONENT_G, 0,
401 : FMT_CLAMP_LOWER_G, 0x10,
402 : FMT_CLAMP_UPPER_G, 0xFEF);
403 :
404 0 : REG_SET_2(FMT_CLAMP_COMPONENT_B, 0,
405 : FMT_CLAMP_LOWER_B, 0x10,
406 : FMT_CLAMP_UPPER_B, 0xFEF);
407 0 : break;
408 : default:
409 : break;
410 : }
411 0 : }
412 :
413 : #if defined(CONFIG_DRM_AMD_DC_SI)
414 : /*
415 : * Set Clamping for DCE6 parts
416 : * 1) Set clamping format based on bpc - 0 for 6bpc (No clamping)
417 : * 1 for 8 bpc
418 : * 2 for 10 bpc
419 : * 3 for 12 bpc
420 : * 7 for programable
421 : * 2) Enable clamp if Limited range requested
422 : */
423 : static void dce60_opp_set_clamping(
424 : struct dce110_opp *opp110,
425 : const struct clamping_and_pixel_encoding_params *params)
426 : {
427 : REG_SET_2(FMT_CLAMP_CNTL, 0,
428 : FMT_CLAMP_DATA_EN, 0,
429 : FMT_CLAMP_COLOR_FORMAT, 0);
430 :
431 : switch (params->clamping_level) {
432 : case CLAMPING_FULL_RANGE:
433 : break;
434 : case CLAMPING_LIMITED_RANGE_8BPC:
435 : REG_SET_2(FMT_CLAMP_CNTL, 0,
436 : FMT_CLAMP_DATA_EN, 1,
437 : FMT_CLAMP_COLOR_FORMAT, 1);
438 : break;
439 : case CLAMPING_LIMITED_RANGE_10BPC:
440 : REG_SET_2(FMT_CLAMP_CNTL, 0,
441 : FMT_CLAMP_DATA_EN, 1,
442 : FMT_CLAMP_COLOR_FORMAT, 2);
443 : break;
444 : case CLAMPING_LIMITED_RANGE_12BPC:
445 : REG_SET_2(FMT_CLAMP_CNTL, 0,
446 : FMT_CLAMP_DATA_EN, 1,
447 : FMT_CLAMP_COLOR_FORMAT, 3);
448 : break;
449 : case CLAMPING_LIMITED_RANGE_PROGRAMMABLE:
450 : /*Set clamp control*/
451 : REG_SET_2(FMT_CLAMP_CNTL, 0,
452 : FMT_CLAMP_DATA_EN, 1,
453 : FMT_CLAMP_COLOR_FORMAT, 7);
454 :
455 : /* DCE6 does have FMT_CLAMP_COMPONENT_{R,G,B} registers */
456 :
457 : break;
458 : default:
459 : break;
460 : }
461 : }
462 : #endif
463 :
464 : /*
465 : * set_pixel_encoding
466 : *
467 : * Set Pixel Encoding
468 : * 0: RGB 4:4:4 or YCbCr 4:4:4 or YOnly
469 : * 1: YCbCr 4:2:2
470 : */
471 0 : static void set_pixel_encoding(
472 : struct dce110_opp *opp110,
473 : const struct clamping_and_pixel_encoding_params *params)
474 : {
475 0 : if (opp110->opp_mask->FMT_CBCR_BIT_REDUCTION_BYPASS)
476 0 : REG_UPDATE_3(FMT_CONTROL,
477 : FMT_PIXEL_ENCODING, 0,
478 : FMT_SUBSAMPLING_MODE, 0,
479 : FMT_CBCR_BIT_REDUCTION_BYPASS, 0);
480 : else
481 0 : REG_UPDATE_2(FMT_CONTROL,
482 : FMT_PIXEL_ENCODING, 0,
483 : FMT_SUBSAMPLING_MODE, 0);
484 :
485 0 : if (params->pixel_encoding == PIXEL_ENCODING_YCBCR422) {
486 0 : REG_UPDATE_2(FMT_CONTROL,
487 : FMT_PIXEL_ENCODING, 1,
488 : FMT_SUBSAMPLING_ORDER, 0);
489 : }
490 0 : if (params->pixel_encoding == PIXEL_ENCODING_YCBCR420) {
491 0 : REG_UPDATE_3(FMT_CONTROL,
492 : FMT_PIXEL_ENCODING, 2,
493 : FMT_SUBSAMPLING_MODE, 2,
494 : FMT_CBCR_BIT_REDUCTION_BYPASS, 1);
495 : }
496 :
497 0 : }
498 :
499 : #if defined(CONFIG_DRM_AMD_DC_SI)
500 : /*
501 : * dce60_set_pixel_encoding
502 : * DCE6 has no FMT_SUBSAMPLING_{MODE,ORDER} bits in FMT_CONTROL reg
503 : * Set Pixel Encoding
504 : * 0: RGB 4:4:4 or YCbCr 4:4:4 or YOnly
505 : * 1: YCbCr 4:2:2
506 : */
507 : static void dce60_set_pixel_encoding(
508 : struct dce110_opp *opp110,
509 : const struct clamping_and_pixel_encoding_params *params)
510 : {
511 : if (opp110->opp_mask->FMT_CBCR_BIT_REDUCTION_BYPASS)
512 : REG_UPDATE_2(FMT_CONTROL,
513 : FMT_PIXEL_ENCODING, 0,
514 : FMT_CBCR_BIT_REDUCTION_BYPASS, 0);
515 : else
516 : REG_UPDATE(FMT_CONTROL,
517 : FMT_PIXEL_ENCODING, 0);
518 :
519 : if (params->pixel_encoding == PIXEL_ENCODING_YCBCR422) {
520 : REG_UPDATE(FMT_CONTROL,
521 : FMT_PIXEL_ENCODING, 1);
522 : }
523 : if (params->pixel_encoding == PIXEL_ENCODING_YCBCR420) {
524 : REG_UPDATE_2(FMT_CONTROL,
525 : FMT_PIXEL_ENCODING, 2,
526 : FMT_CBCR_BIT_REDUCTION_BYPASS, 1);
527 : }
528 :
529 : }
530 : #endif
531 :
532 0 : void dce110_opp_program_bit_depth_reduction(
533 : struct output_pixel_processor *opp,
534 : const struct bit_depth_reduction_params *params)
535 : {
536 0 : struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
537 :
538 0 : set_truncation(opp110, params);
539 0 : set_spatial_dither(opp110, params);
540 0 : set_temporal_dither(opp110, params);
541 0 : }
542 :
543 : #if defined(CONFIG_DRM_AMD_DC_SI)
544 : static void dce60_opp_program_bit_depth_reduction(
545 : struct output_pixel_processor *opp,
546 : const struct bit_depth_reduction_params *params)
547 : {
548 : struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
549 :
550 : dce60_set_truncation(opp110, params);
551 : set_spatial_dither(opp110, params);
552 : set_temporal_dither(opp110, params);
553 : }
554 : #endif
555 :
556 0 : void dce110_opp_program_clamping_and_pixel_encoding(
557 : struct output_pixel_processor *opp,
558 : const struct clamping_and_pixel_encoding_params *params)
559 : {
560 0 : struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
561 :
562 0 : dce110_opp_set_clamping(opp110, params);
563 0 : set_pixel_encoding(opp110, params);
564 0 : }
565 :
566 : #if defined(CONFIG_DRM_AMD_DC_SI)
567 : static void dce60_opp_program_clamping_and_pixel_encoding(
568 : struct output_pixel_processor *opp,
569 : const struct clamping_and_pixel_encoding_params *params)
570 : {
571 : struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
572 :
573 : dce60_opp_set_clamping(opp110, params);
574 : dce60_set_pixel_encoding(opp110, params);
575 : }
576 : #endif
577 :
578 :
579 0 : static void program_formatter_420_memory(struct output_pixel_processor *opp)
580 : {
581 0 : struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
582 : uint32_t fmt_mem_cntl_value;
583 :
584 : /* Program source select*/
585 : /* Use HW default source select for FMT_MEMORYx_CONTROL */
586 : /* Use that value for FMT_SRC_SELECT as well*/
587 0 : REG_GET(CONTROL,
588 : FMT420_MEM0_SOURCE_SEL, &fmt_mem_cntl_value);
589 :
590 0 : REG_UPDATE(FMT_CONTROL,
591 : FMT_SRC_SELECT, fmt_mem_cntl_value);
592 :
593 : /* Turn on the memory */
594 0 : REG_UPDATE(CONTROL,
595 : FMT420_MEM0_PWR_FORCE, 0);
596 0 : }
597 :
598 0 : void dce110_opp_set_dyn_expansion(
599 : struct output_pixel_processor *opp,
600 : enum dc_color_space color_sp,
601 : enum dc_color_depth color_dpth,
602 : enum signal_type signal)
603 : {
604 0 : struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
605 :
606 0 : REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL,
607 : FMT_DYNAMIC_EXP_EN, 0,
608 : FMT_DYNAMIC_EXP_MODE, 0);
609 :
610 : /*00 - 10-bit -> 12-bit dynamic expansion*/
611 : /*01 - 8-bit -> 12-bit dynamic expansion*/
612 0 : if (signal == SIGNAL_TYPE_HDMI_TYPE_A ||
613 0 : signal == SIGNAL_TYPE_DISPLAY_PORT ||
614 : signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
615 0 : switch (color_dpth) {
616 : case COLOR_DEPTH_888:
617 0 : REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL,
618 : FMT_DYNAMIC_EXP_EN, 1,
619 : FMT_DYNAMIC_EXP_MODE, 1);
620 0 : break;
621 : case COLOR_DEPTH_101010:
622 0 : REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL,
623 : FMT_DYNAMIC_EXP_EN, 1,
624 : FMT_DYNAMIC_EXP_MODE, 0);
625 0 : break;
626 : case COLOR_DEPTH_121212:
627 0 : REG_UPDATE_2(
628 : FMT_DYNAMIC_EXP_CNTL,
629 : FMT_DYNAMIC_EXP_EN, 1,/*otherwise last two bits are zero*/
630 : FMT_DYNAMIC_EXP_MODE, 0);
631 0 : break;
632 : default:
633 : break;
634 : }
635 : }
636 0 : }
637 :
638 0 : static void program_formatter_reset_dig_resync_fifo(struct output_pixel_processor *opp)
639 : {
640 0 : struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
641 :
642 : /* clear previous phase lock status*/
643 0 : REG_UPDATE(FMT_CONTROL,
644 : FMT_420_PIXEL_PHASE_LOCKED_CLEAR, 1);
645 :
646 : /* poll until FMT_420_PIXEL_PHASE_LOCKED become 1*/
647 0 : REG_WAIT(FMT_CONTROL, FMT_420_PIXEL_PHASE_LOCKED, 1, 10, 10);
648 :
649 0 : }
650 :
651 0 : void dce110_opp_program_fmt(
652 : struct output_pixel_processor *opp,
653 : struct bit_depth_reduction_params *fmt_bit_depth,
654 : struct clamping_and_pixel_encoding_params *clamping)
655 : {
656 : /* dithering is affected by <CrtcSourceSelect>, hence should be
657 : * programmed afterwards */
658 :
659 0 : if (clamping->pixel_encoding == PIXEL_ENCODING_YCBCR420)
660 0 : program_formatter_420_memory(opp);
661 :
662 0 : dce110_opp_program_bit_depth_reduction(
663 : opp,
664 : fmt_bit_depth);
665 :
666 0 : dce110_opp_program_clamping_and_pixel_encoding(
667 : opp,
668 : clamping);
669 :
670 0 : if (clamping->pixel_encoding == PIXEL_ENCODING_YCBCR420)
671 0 : program_formatter_reset_dig_resync_fifo(opp);
672 :
673 0 : return;
674 : }
675 :
676 : #if defined(CONFIG_DRM_AMD_DC_SI)
677 : static void dce60_opp_program_fmt(
678 : struct output_pixel_processor *opp,
679 : struct bit_depth_reduction_params *fmt_bit_depth,
680 : struct clamping_and_pixel_encoding_params *clamping)
681 : {
682 : /* dithering is affected by <CrtcSourceSelect>, hence should be
683 : * programmed afterwards */
684 :
685 : if (clamping->pixel_encoding == PIXEL_ENCODING_YCBCR420)
686 : program_formatter_420_memory(opp);
687 :
688 : dce60_opp_program_bit_depth_reduction(
689 : opp,
690 : fmt_bit_depth);
691 :
692 : dce60_opp_program_clamping_and_pixel_encoding(
693 : opp,
694 : clamping);
695 :
696 : if (clamping->pixel_encoding == PIXEL_ENCODING_YCBCR420)
697 : program_formatter_reset_dig_resync_fifo(opp);
698 :
699 : return;
700 : }
701 : #endif
702 :
703 :
704 :
705 : /*****************************************/
706 : /* Constructor, Destructor */
707 : /*****************************************/
708 :
709 : static const struct opp_funcs funcs = {
710 : .opp_set_dyn_expansion = dce110_opp_set_dyn_expansion,
711 : .opp_destroy = dce110_opp_destroy,
712 : .opp_program_fmt = dce110_opp_program_fmt,
713 : .opp_program_bit_depth_reduction = dce110_opp_program_bit_depth_reduction
714 : };
715 :
716 : #if defined(CONFIG_DRM_AMD_DC_SI)
717 : static const struct opp_funcs dce60_opp_funcs = {
718 : .opp_set_dyn_expansion = dce110_opp_set_dyn_expansion,
719 : .opp_destroy = dce110_opp_destroy,
720 : .opp_program_fmt = dce60_opp_program_fmt,
721 : .opp_program_bit_depth_reduction = dce60_opp_program_bit_depth_reduction
722 : };
723 : #endif
724 :
725 0 : void dce110_opp_construct(struct dce110_opp *opp110,
726 : struct dc_context *ctx,
727 : uint32_t inst,
728 : const struct dce_opp_registers *regs,
729 : const struct dce_opp_shift *opp_shift,
730 : const struct dce_opp_mask *opp_mask)
731 : {
732 0 : opp110->base.funcs = &funcs;
733 :
734 0 : opp110->base.ctx = ctx;
735 :
736 0 : opp110->base.inst = inst;
737 :
738 0 : opp110->regs = regs;
739 0 : opp110->opp_shift = opp_shift;
740 0 : opp110->opp_mask = opp_mask;
741 0 : }
742 :
743 : #if defined(CONFIG_DRM_AMD_DC_SI)
744 : void dce60_opp_construct(struct dce110_opp *opp110,
745 : struct dc_context *ctx,
746 : uint32_t inst,
747 : const struct dce_opp_registers *regs,
748 : const struct dce_opp_shift *opp_shift,
749 : const struct dce_opp_mask *opp_mask)
750 : {
751 : opp110->base.funcs = &dce60_opp_funcs;
752 :
753 : opp110->base.ctx = ctx;
754 :
755 : opp110->base.inst = inst;
756 :
757 : opp110->regs = regs;
758 : opp110->opp_shift = opp_shift;
759 : opp110->opp_mask = opp_mask;
760 : }
761 : #endif
762 :
763 0 : void dce110_opp_destroy(struct output_pixel_processor **opp)
764 : {
765 0 : if (*opp)
766 0 : kfree(FROM_DCE11_OPP(*opp));
767 0 : *opp = NULL;
768 0 : }
769 :
|