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 | return; |
133 | /*Set truncation depth and Enable truncation*/ |
134 | 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 | 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 | 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 | 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 | REG_UPDATE(FMT_BIT_DEPTH_CONTROL, |
215 | FMT_TEMPORAL_DITHER_EN, 0); |
216 | |
217 | if (params->flags.SPATIAL_DITHER_ENABLED == 0) |
218 | return; |
219 | |
220 | /* only use FRAME_COUNTER_MAX if frameRandom == 1*/ |
221 | |
222 | if (opp110->opp_mask->FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX && |
223 | opp110->opp_mask->FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP) { |
224 | if (params->flags.FRAME_RANDOM == 1) { |
225 | if (params->flags.SPATIAL_DITHER_DEPTH == 0 || |
226 | params->flags.SPATIAL_DITHER_DEPTH == 1) { |
227 | REG_UPDATE_2(FMT_CONTROL, |
228 | FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, 15, |
229 | FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, 2); |
230 | } else if (params->flags.SPATIAL_DITHER_DEPTH == 2) { |
231 | 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 | 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 | REG_UPDATE(FMT_DITHER_RAND_R_SEED, |
246 | FMT_RAND_R_SEED, params->r_seed_value); |
247 | |
248 | REG_UPDATE(FMT_DITHER_RAND_G_SEED, |
249 | FMT_RAND_G_SEED, params->g_seed_value); |
250 | |
251 | 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 | 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 | 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 | 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 | 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 | REG_UPDATE_2(FMT_BIT_DEPTH_CONTROL, |
312 | FMT_TEMPORAL_DITHER_DEPTH, 0, |
313 | FMT_TEMPORAL_LEVEL, 0); |
314 | |
315 | 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 | if (params->flags.FRAME_MODULATION_ENABLED == 0 || |
322 | params->flags.FRAME_MODULATION_DEPTH == 2) |
323 | return; |
324 | |
325 | /* Set temporal dithering depth*/ |
326 | 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 | if (REG(FMT_TEMPORAL_DITHER_PATTERN_CONTROL)) { |
333 | REG_WRITE(FMT_TEMPORAL_DITHER_PATTERN_CONTROL, 0); |
334 | /*Set s matrix*/ |
335 | REG_WRITE(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX, 0); |
336 | /*Set t matrix*/ |
337 | 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 | REG_UPDATE(FMT_BIT_DEPTH_CONTROL, |
342 | FMT_TEMPORAL_LEVEL, params->flags.TEMPORAL_LEVEL); |
343 | |
344 | 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 | 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 | void dce110_opp_set_clamping( |
364 | struct dce110_opp *opp110, |
365 | const struct clamping_and_pixel_encoding_params *params) |
366 | { |
367 | REG_SET_2(FMT_CLAMP_CNTL, 0, |
368 | FMT_CLAMP_DATA_EN, 0, |
369 | FMT_CLAMP_COLOR_FORMAT, 0); |
370 | |
371 | switch (params->clamping_level) { |
372 | case CLAMPING_FULL_RANGE: |
373 | break; |
374 | case CLAMPING_LIMITED_RANGE_8BPC: |
375 | REG_SET_2(FMT_CLAMP_CNTL, 0, |
376 | FMT_CLAMP_DATA_EN, 1, |
377 | FMT_CLAMP_COLOR_FORMAT, 1); |
378 | break; |
379 | case CLAMPING_LIMITED_RANGE_10BPC: |
380 | REG_SET_2(FMT_CLAMP_CNTL, 0, |
381 | FMT_CLAMP_DATA_EN, 1, |
382 | FMT_CLAMP_COLOR_FORMAT, 2); |
383 | break; |
384 | case CLAMPING_LIMITED_RANGE_12BPC: |
385 | REG_SET_2(FMT_CLAMP_CNTL, 0, |
386 | FMT_CLAMP_DATA_EN, 1, |
387 | FMT_CLAMP_COLOR_FORMAT, 3); |
388 | break; |
389 | case CLAMPING_LIMITED_RANGE_PROGRAMMABLE: |
390 | /*Set clamp control*/ |
391 | 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 | REG_SET_2(FMT_CLAMP_COMPONENT_R, 0, |
397 | FMT_CLAMP_LOWER_R, 0x10, |
398 | FMT_CLAMP_UPPER_R, 0xFEF); |
399 | |
400 | REG_SET_2(FMT_CLAMP_COMPONENT_G, 0, |
401 | FMT_CLAMP_LOWER_G, 0x10, |
402 | FMT_CLAMP_UPPER_G, 0xFEF); |
403 | |
404 | REG_SET_2(FMT_CLAMP_COMPONENT_B, 0, |
405 | FMT_CLAMP_LOWER_B, 0x10, |
406 | FMT_CLAMP_UPPER_B, 0xFEF); |
407 | break; |
408 | default: |
409 | break; |
410 | } |
411 | } |
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 | static void set_pixel_encoding( |
472 | struct dce110_opp *opp110, |
473 | const struct clamping_and_pixel_encoding_params *params) |
474 | { |
475 | if (opp110->opp_mask->FMT_CBCR_BIT_REDUCTION_BYPASS) |
476 | 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 | REG_UPDATE_2(FMT_CONTROL, |
482 | FMT_PIXEL_ENCODING, 0, |
483 | FMT_SUBSAMPLING_MODE, 0); |
484 | |
485 | if (params->pixel_encoding == PIXEL_ENCODING_YCBCR422) { |
486 | REG_UPDATE_2(FMT_CONTROL, |
487 | FMT_PIXEL_ENCODING, 1, |
488 | FMT_SUBSAMPLING_ORDER, 0); |
489 | } |
490 | if (params->pixel_encoding == PIXEL_ENCODING_YCBCR420) { |
491 | 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 | } |
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 | void dce110_opp_program_bit_depth_reduction( |
533 | struct output_pixel_processor *opp, |
534 | const struct bit_depth_reduction_params *params) |
535 | { |
536 | struct dce110_opp *opp110 = TO_DCE110_OPP(opp); |
537 | |
538 | set_truncation(opp110, params); |
539 | set_spatial_dither(opp110, params); |
540 | set_temporal_dither(opp110, params); |
541 | } |
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 | 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 | struct dce110_opp *opp110 = TO_DCE110_OPP(opp); |
561 | |
562 | dce110_opp_set_clamping(opp110, params); |
563 | set_pixel_encoding(opp110, params); |
564 | } |
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 | static void program_formatter_420_memory(struct output_pixel_processor *opp) |
580 | { |
581 | 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 | REG_GET(CONTROL, |
588 | FMT420_MEM0_SOURCE_SEL, &fmt_mem_cntl_value); |
589 | |
590 | REG_UPDATE(FMT_CONTROL, |
591 | FMT_SRC_SELECT, fmt_mem_cntl_value); |
592 | |
593 | /* Turn on the memory */ |
594 | REG_UPDATE(CONTROL, |
595 | FMT420_MEM0_PWR_FORCE, 0); |
596 | } |
597 | |
598 | 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 | struct dce110_opp *opp110 = TO_DCE110_OPP(opp); |
605 | |
606 | 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 | if (signal == SIGNAL_TYPE_HDMI_TYPE_A || |
613 | signal == SIGNAL_TYPE_DISPLAY_PORT || |
614 | signal == SIGNAL_TYPE_DISPLAY_PORT_MST) { |
615 | switch (color_dpth) { |
616 | case COLOR_DEPTH_888: |
617 | REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL, |
618 | FMT_DYNAMIC_EXP_EN, 1, |
619 | FMT_DYNAMIC_EXP_MODE, 1); |
620 | break; |
621 | case COLOR_DEPTH_101010: |
622 | REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL, |
623 | FMT_DYNAMIC_EXP_EN, 1, |
624 | FMT_DYNAMIC_EXP_MODE, 0); |
625 | break; |
626 | case COLOR_DEPTH_121212: |
627 | 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 | break; |
632 | default: |
633 | break; |
634 | } |
635 | } |
636 | } |
637 | |
638 | static void program_formatter_reset_dig_resync_fifo(struct output_pixel_processor *opp) |
639 | { |
640 | struct dce110_opp *opp110 = TO_DCE110_OPP(opp); |
641 | |
642 | /* clear previous phase lock status*/ |
643 | REG_UPDATE(FMT_CONTROL, |
644 | FMT_420_PIXEL_PHASE_LOCKED_CLEAR, 1); |
645 | |
646 | /* poll until FMT_420_PIXEL_PHASE_LOCKED become 1*/ |
647 | REG_WAIT(FMT_CONTROL, FMT_420_PIXEL_PHASE_LOCKED, 1, 10, 10); |
648 | |
649 | } |
650 | |
651 | 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 | if (clamping->pixel_encoding == PIXEL_ENCODING_YCBCR420) |
660 | program_formatter_420_memory(opp); |
661 | |
662 | dce110_opp_program_bit_depth_reduction( |
663 | opp, |
664 | params: fmt_bit_depth); |
665 | |
666 | dce110_opp_program_clamping_and_pixel_encoding( |
667 | opp, |
668 | params: clamping); |
669 | |
670 | if (clamping->pixel_encoding == PIXEL_ENCODING_YCBCR420) |
671 | program_formatter_reset_dig_resync_fifo(opp); |
672 | |
673 | 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 | params: fmt_bit_depth); |
691 | |
692 | dce60_opp_program_clamping_and_pixel_encoding( |
693 | opp, |
694 | params: 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 | 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 | opp110->base.funcs = &funcs; |
733 | |
734 | opp110->base.ctx = ctx; |
735 | |
736 | opp110->base.inst = inst; |
737 | |
738 | opp110->regs = regs; |
739 | opp110->opp_shift = opp_shift; |
740 | opp110->opp_mask = opp_mask; |
741 | } |
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 | void dce110_opp_destroy(struct output_pixel_processor **opp) |
764 | { |
765 | if (*opp) |
766 | kfree(FROM_DCE11_OPP(*opp)); |
767 | *opp = NULL; |
768 | } |
769 | |
770 | |