2 * Copyright 2016 Advanced Micro Devices, Inc.
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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.
26 #include "dm_services.h"
28 #include "core_types.h"
30 #include "reg_helper.h"
31 #include "dcn20_dpp.h"
32 #include "basics/conversion.h"
35 #define HORZ_MAX_TAPS 8
36 #define VERT_MAX_TAPS 8
38 #define BLACK_OFFSET_RGB_Y 0x0
39 #define BLACK_OFFSET_CBCR 0x8000
48 #define FN(reg_name, field_name) \
49 dpp->tf_shift->field_name, dpp->tf_mask->field_name
51 void dpp20_read_state(struct dpp
*dpp_base
,
52 struct dcn_dpp_state
*s
)
54 struct dcn20_dpp
*dpp
= TO_DCN20_DPP(dpp_base
);
57 DPP_CLOCK_ENABLE
, &s
->is_enabled
);
58 REG_GET(CM_DGAM_CONTROL
,
59 CM_DGAM_LUT_MODE
, &s
->dgam_lut_mode
);
60 // BGAM has no ROM, and definition is different, can't reuse same dump
61 //REG_GET(CM_BLNDGAM_CONTROL,
62 // CM_BLNDGAM_LUT_MODE, &s->rgam_lut_mode);
63 REG_GET(CM_GAMUT_REMAP_CONTROL
,
64 CM_GAMUT_REMAP_MODE
, &s
->gamut_remap_mode
);
65 if (s
->gamut_remap_mode
) {
66 s
->gamut_remap_c11_c12
= REG_READ(CM_GAMUT_REMAP_C11_C12
);
67 s
->gamut_remap_c13_c14
= REG_READ(CM_GAMUT_REMAP_C13_C14
);
68 s
->gamut_remap_c21_c22
= REG_READ(CM_GAMUT_REMAP_C21_C22
);
69 s
->gamut_remap_c23_c24
= REG_READ(CM_GAMUT_REMAP_C23_C24
);
70 s
->gamut_remap_c31_c32
= REG_READ(CM_GAMUT_REMAP_C31_C32
);
71 s
->gamut_remap_c33_c34
= REG_READ(CM_GAMUT_REMAP_C33_C34
);
75 void dpp2_power_on_obuf(
79 struct dcn20_dpp
*dpp
= TO_DCN20_DPP(dpp_base
);
81 REG_UPDATE(CM_MEM_PWR_CTRL
, SHARED_MEM_PWR_DIS
, power_on
== true ? 1:0);
83 REG_UPDATE(OBUF_MEM_PWR_CTRL
,
84 OBUF_MEM_PWR_FORCE
, power_on
== true ? 0:1);
86 REG_UPDATE(DSCL_MEM_PWR_CTRL
,
87 LUT_MEM_PWR_FORCE
, power_on
== true ? 0:1);
90 void dpp2_dummy_program_input_lut(
92 const struct dc_gamma
*gamma
)
95 static void dpp2_cnv_setup (
97 enum surface_pixel_format format
,
98 enum expansion_mode mode
,
99 struct dc_csc_transform input_csc_color_matrix
,
100 enum dc_color_space input_color_space
,
101 struct cnv_alpha_2bit_lut
*alpha_2bit_lut
)
103 struct dcn20_dpp
*dpp
= TO_DCN20_DPP(dpp_base
);
104 uint32_t pixel_format
= 0;
105 uint32_t alpha_en
= 1;
106 enum dc_color_space color_space
= COLOR_SPACE_SRGB
;
107 enum dcn20_input_csc_select select
= DCN2_ICSC_SELECT_BYPASS
;
108 bool force_disable_cursor
= false;
109 struct out_csc_color_matrix tbl_entry
;
110 uint32_t is_2bit
= 0;
113 REG_SET_2(FORMAT_CONTROL
, 0,
115 FORMAT_EXPANSION_MODE
, mode
);
118 //FORMAT_CONTROL. FORMAT_CNV16 default 0: U0.16/S.1.15; 1: U1.15/ S.1.14
119 //FORMAT_CONTROL. CNVC_BYPASS_MSB_ALIGN default 0: disabled 1: enabled
120 //FORMAT_CONTROL. CLAMP_POSITIVE default 0: disabled 1: enabled
121 //FORMAT_CONTROL. CLAMP_POSITIVE_C default 0: disabled 1: enabled
122 REG_UPDATE(FORMAT_CONTROL
, FORMAT_CNV16
, 0);
123 REG_UPDATE(FORMAT_CONTROL
, CNVC_BYPASS_MSB_ALIGN
, 0);
124 REG_UPDATE(FORMAT_CONTROL
, CLAMP_POSITIVE
, 0);
125 REG_UPDATE(FORMAT_CONTROL
, CLAMP_POSITIVE_C
, 0);
128 case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555
:
131 case SURFACE_PIXEL_FORMAT_GRPH_RGB565
:
135 case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888
:
136 case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888
:
139 case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010
:
140 case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010
:
144 case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr
:
145 force_disable_cursor
= false;
147 color_space
= COLOR_SPACE_YCBCR709
;
148 select
= DCN2_ICSC_SELECT_ICSC_A
;
150 case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb
:
151 force_disable_cursor
= true;
153 color_space
= COLOR_SPACE_YCBCR709
;
154 select
= DCN2_ICSC_SELECT_ICSC_A
;
156 case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr
:
157 force_disable_cursor
= true;
159 color_space
= COLOR_SPACE_YCBCR709
;
160 select
= DCN2_ICSC_SELECT_ICSC_A
;
162 case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb
:
163 force_disable_cursor
= true;
165 color_space
= COLOR_SPACE_YCBCR709
;
166 select
= DCN2_ICSC_SELECT_ICSC_A
;
168 case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616
:
171 case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F
:
174 case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F
:
177 case SURFACE_PIXEL_FORMAT_VIDEO_AYCrCb8888
:
179 color_space
= COLOR_SPACE_YCBCR709
;
180 select
= DCN2_ICSC_SELECT_ICSC_A
;
182 case SURFACE_PIXEL_FORMAT_GRPH_RGB111110_FIX
:
185 case SURFACE_PIXEL_FORMAT_GRPH_BGR101111_FIX
:
188 case SURFACE_PIXEL_FORMAT_VIDEO_ACrYCb2101010
:
190 color_space
= COLOR_SPACE_YCBCR709
;
191 select
= DCN2_ICSC_SELECT_ICSC_A
;
194 case SURFACE_PIXEL_FORMAT_VIDEO_CrYCbA1010102
:
196 color_space
= COLOR_SPACE_YCBCR709
;
197 select
= DCN2_ICSC_SELECT_ICSC_A
;
200 case SURFACE_PIXEL_FORMAT_GRPH_RGB111110_FLOAT
:
203 case SURFACE_PIXEL_FORMAT_GRPH_BGR101111_FLOAT
:
210 if (is_2bit
== 1 && alpha_2bit_lut
!= NULL
) {
211 REG_UPDATE(ALPHA_2BIT_LUT
, ALPHA_2BIT_LUT0
, alpha_2bit_lut
->lut0
);
212 REG_UPDATE(ALPHA_2BIT_LUT
, ALPHA_2BIT_LUT1
, alpha_2bit_lut
->lut1
);
213 REG_UPDATE(ALPHA_2BIT_LUT
, ALPHA_2BIT_LUT2
, alpha_2bit_lut
->lut2
);
214 REG_UPDATE(ALPHA_2BIT_LUT
, ALPHA_2BIT_LUT3
, alpha_2bit_lut
->lut3
);
217 REG_SET(CNVC_SURFACE_PIXEL_FORMAT
, 0,
218 CNVC_SURFACE_PIXEL_FORMAT
, pixel_format
);
219 REG_UPDATE(FORMAT_CONTROL
, FORMAT_CONTROL__ALPHA_EN
, alpha_en
);
221 // if input adjustments exist, program icsc with those values
222 if (input_csc_color_matrix
.enable_adjustment
224 for (i
= 0; i
< 12; i
++)
225 tbl_entry
.regval
[i
] = input_csc_color_matrix
.matrix
[i
];
227 tbl_entry
.color_space
= input_color_space
;
229 if (color_space
>= COLOR_SPACE_YCBCR601
)
230 select
= DCN2_ICSC_SELECT_ICSC_A
;
232 select
= DCN2_ICSC_SELECT_BYPASS
;
234 dpp2_program_input_csc(dpp_base
, color_space
, select
, &tbl_entry
);
236 dpp2_program_input_csc(dpp_base
, color_space
, select
, NULL
);
238 if (force_disable_cursor
) {
239 REG_UPDATE(CURSOR_CONTROL
,
241 REG_UPDATE(CURSOR0_CONTROL
,
245 dpp2_power_on_obuf(dpp_base
, true);
249 void dpp2_cnv_set_bias_scale(
250 struct dpp
*dpp_base
,
251 struct dc_bias_and_scale
*bias_and_scale
)
253 struct dcn20_dpp
*dpp
= TO_DCN20_DPP(dpp_base
);
255 REG_UPDATE(FCNV_FP_BIAS_R
, FCNV_FP_BIAS_R
, bias_and_scale
->bias_red
);
256 REG_UPDATE(FCNV_FP_BIAS_G
, FCNV_FP_BIAS_G
, bias_and_scale
->bias_green
);
257 REG_UPDATE(FCNV_FP_BIAS_B
, FCNV_FP_BIAS_B
, bias_and_scale
->bias_blue
);
258 REG_UPDATE(FCNV_FP_SCALE_R
, FCNV_FP_SCALE_R
, bias_and_scale
->scale_red
);
259 REG_UPDATE(FCNV_FP_SCALE_G
, FCNV_FP_SCALE_G
, bias_and_scale
->scale_green
);
260 REG_UPDATE(FCNV_FP_SCALE_B
, FCNV_FP_SCALE_B
, bias_and_scale
->scale_blue
);
263 /*compute the maximum number of lines that we can fit in the line buffer*/
264 void dscl2_calc_lb_num_partitions(
265 const struct scaler_data
*scl_data
,
266 enum lb_memory_config lb_config
,
270 int memory_line_size_y
, memory_line_size_c
, memory_line_size_a
,
271 lb_memory_size
, lb_memory_size_c
, lb_memory_size_a
, num_partitions_a
;
273 int line_size
= scl_data
->viewport
.width
< scl_data
->recout
.width
?
274 scl_data
->viewport
.width
: scl_data
->recout
.width
;
275 int line_size_c
= scl_data
->viewport_c
.width
< scl_data
->recout
.width
?
276 scl_data
->viewport_c
.width
: scl_data
->recout
.width
;
281 if (line_size_c
== 0)
284 memory_line_size_y
= (line_size
+ 5) / 6; /* +5 to ceil */
285 memory_line_size_c
= (line_size_c
+ 5) / 6; /* +5 to ceil */
286 memory_line_size_a
= (line_size
+ 5) / 6; /* +5 to ceil */
288 if (lb_config
== LB_MEMORY_CONFIG_1
) {
289 lb_memory_size
= 970;
290 lb_memory_size_c
= 970;
291 lb_memory_size_a
= 970;
292 } else if (lb_config
== LB_MEMORY_CONFIG_2
) {
293 lb_memory_size
= 1290;
294 lb_memory_size_c
= 1290;
295 lb_memory_size_a
= 1290;
296 } else if (lb_config
== LB_MEMORY_CONFIG_3
) {
297 /* 420 mode: using 3rd mem from Y, Cr and Cb */
298 lb_memory_size
= 970 + 1290 + 484 + 484 + 484;
299 lb_memory_size_c
= 970 + 1290;
300 lb_memory_size_a
= 970 + 1290 + 484;
302 lb_memory_size
= 970 + 1290 + 484;
303 lb_memory_size_c
= 970 + 1290 + 484;
304 lb_memory_size_a
= 970 + 1290 + 484;
306 *num_part_y
= lb_memory_size
/ memory_line_size_y
;
307 *num_part_c
= lb_memory_size_c
/ memory_line_size_c
;
308 num_partitions_a
= lb_memory_size_a
/ memory_line_size_a
;
310 if (scl_data
->lb_params
.alpha_en
311 && (num_partitions_a
< *num_part_y
))
312 *num_part_y
= num_partitions_a
;
314 if (*num_part_y
> 64)
316 if (*num_part_c
> 64)
320 void dpp2_cnv_set_alpha_keyer(
321 struct dpp
*dpp_base
,
322 struct cnv_color_keyer_params
*color_keyer
)
324 struct dcn20_dpp
*dpp
= TO_DCN20_DPP(dpp_base
);
326 REG_UPDATE(COLOR_KEYER_CONTROL
, COLOR_KEYER_EN
, color_keyer
->color_keyer_en
);
328 REG_UPDATE(COLOR_KEYER_CONTROL
, COLOR_KEYER_MODE
, color_keyer
->color_keyer_mode
);
330 REG_UPDATE(COLOR_KEYER_ALPHA
, COLOR_KEYER_ALPHA_LOW
, color_keyer
->color_keyer_alpha_low
);
331 REG_UPDATE(COLOR_KEYER_ALPHA
, COLOR_KEYER_ALPHA_HIGH
, color_keyer
->color_keyer_alpha_high
);
333 REG_UPDATE(COLOR_KEYER_RED
, COLOR_KEYER_RED_LOW
, color_keyer
->color_keyer_red_low
);
334 REG_UPDATE(COLOR_KEYER_RED
, COLOR_KEYER_RED_HIGH
, color_keyer
->color_keyer_red_high
);
336 REG_UPDATE(COLOR_KEYER_GREEN
, COLOR_KEYER_GREEN_LOW
, color_keyer
->color_keyer_green_low
);
337 REG_UPDATE(COLOR_KEYER_GREEN
, COLOR_KEYER_GREEN_HIGH
, color_keyer
->color_keyer_green_high
);
339 REG_UPDATE(COLOR_KEYER_BLUE
, COLOR_KEYER_BLUE_LOW
, color_keyer
->color_keyer_blue_low
);
340 REG_UPDATE(COLOR_KEYER_BLUE
, COLOR_KEYER_BLUE_HIGH
, color_keyer
->color_keyer_blue_high
);
343 void dpp2_set_cursor_attributes(
344 struct dpp
*dpp_base
,
345 struct dc_cursor_attributes
*cursor_attributes
)
347 enum dc_cursor_color_format color_format
= cursor_attributes
->color_format
;
348 struct dcn20_dpp
*dpp
= TO_DCN20_DPP(dpp_base
);
351 if (color_format
== CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA
||
352 color_format
== CURSOR_MODE_COLOR_UN_PRE_MULTIPLIED_ALPHA
) {
353 if (cursor_attributes
->attribute_flags
.bits
.ENABLE_CURSOR_DEGAMMA
) {
358 REG_UPDATE_3(CURSOR0_CONTROL
,
359 CUR0_MODE
, color_format
,
360 CUR0_EXPANSION_MODE
, 0,
361 CUR0_ROM_EN
, cur_rom_en
);
363 if (color_format
== CURSOR_MODE_MONO
) {
364 /* todo: clarify what to program these to */
365 REG_UPDATE(CURSOR0_COLOR0
,
366 CUR0_COLOR0
, 0x00000000);
367 REG_UPDATE(CURSOR0_COLOR1
,
368 CUR0_COLOR1
, 0xFFFFFFFF);
372 #define IDENTITY_RATIO(ratio) (dc_fixpt_u3d19(ratio) == (1 << 19))
374 bool dpp2_get_optimal_number_of_taps(
376 struct scaler_data
*scl_data
,
377 const struct scaling_taps
*in_taps
)
379 /* Some ASICs does not support FP16 scaling, so we reject modes require this*/
380 if (scl_data
->viewport
.width
!= scl_data
->h_active
&&
381 scl_data
->viewport
.height
!= scl_data
->v_active
&&
382 dpp
->caps
->dscl_data_proc_format
== DSCL_DATA_PRCESSING_FIXED_FORMAT
&&
383 scl_data
->format
== PIXEL_FORMAT_FP16
)
386 if (scl_data
->viewport
.width
> scl_data
->h_active
&&
387 dpp
->ctx
->dc
->debug
.max_downscale_src_width
!= 0 &&
388 scl_data
->viewport
.width
> dpp
->ctx
->dc
->debug
.max_downscale_src_width
)
391 /* TODO: add lb check */
393 /* No support for programming ratio of 8, drop to 7.99999.. */
394 if (scl_data
->ratios
.horz
.value
== (8ll << 32))
395 scl_data
->ratios
.horz
.value
--;
396 if (scl_data
->ratios
.vert
.value
== (8ll << 32))
397 scl_data
->ratios
.vert
.value
--;
398 if (scl_data
->ratios
.horz_c
.value
== (8ll << 32))
399 scl_data
->ratios
.horz_c
.value
--;
400 if (scl_data
->ratios
.vert_c
.value
== (8ll << 32))
401 scl_data
->ratios
.vert_c
.value
--;
403 /* Set default taps if none are provided */
404 if (in_taps
->h_taps
== 0) {
405 if (dc_fixpt_ceil(scl_data
->ratios
.horz
) > 4)
406 scl_data
->taps
.h_taps
= 8;
408 scl_data
->taps
.h_taps
= 4;
410 scl_data
->taps
.h_taps
= in_taps
->h_taps
;
411 if (in_taps
->v_taps
== 0) {
412 if (dc_fixpt_ceil(scl_data
->ratios
.vert
) > 4)
413 scl_data
->taps
.v_taps
= 8;
415 scl_data
->taps
.v_taps
= 4;
417 scl_data
->taps
.v_taps
= in_taps
->v_taps
;
418 if (in_taps
->v_taps_c
== 0) {
419 if (dc_fixpt_ceil(scl_data
->ratios
.vert_c
) > 4)
420 scl_data
->taps
.v_taps_c
= 4;
422 scl_data
->taps
.v_taps_c
= 2;
424 scl_data
->taps
.v_taps_c
= in_taps
->v_taps_c
;
425 if (in_taps
->h_taps_c
== 0) {
426 if (dc_fixpt_ceil(scl_data
->ratios
.horz_c
) > 4)
427 scl_data
->taps
.h_taps_c
= 4;
429 scl_data
->taps
.h_taps_c
= 2;
430 } else if ((in_taps
->h_taps_c
% 2) != 0 && in_taps
->h_taps_c
!= 1)
431 /* Only 1 and even h_taps_c are supported by hw */
432 scl_data
->taps
.h_taps_c
= in_taps
->h_taps_c
- 1;
434 scl_data
->taps
.h_taps_c
= in_taps
->h_taps_c
;
436 if (!dpp
->ctx
->dc
->debug
.always_scale
) {
437 if (IDENTITY_RATIO(scl_data
->ratios
.horz
))
438 scl_data
->taps
.h_taps
= 1;
439 if (IDENTITY_RATIO(scl_data
->ratios
.vert
))
440 scl_data
->taps
.v_taps
= 1;
441 if (IDENTITY_RATIO(scl_data
->ratios
.horz_c
))
442 scl_data
->taps
.h_taps_c
= 1;
443 if (IDENTITY_RATIO(scl_data
->ratios
.vert_c
))
444 scl_data
->taps
.v_taps_c
= 1;
450 void oppn20_dummy_program_regamma_pwl(
452 const struct pwl_params
*params
,
453 enum opp_regamma mode
)
456 static struct dpp_funcs dcn20_dpp_funcs
= {
457 .dpp_read_state
= dpp20_read_state
,
458 .dpp_reset
= dpp_reset
,
459 .dpp_set_scaler
= dpp1_dscl_set_scaler_manual_scale
,
460 .dpp_get_optimal_number_of_taps
= dpp1_get_optimal_number_of_taps
,
461 .dpp_set_gamut_remap
= dpp2_cm_set_gamut_remap
,
462 .dpp_set_csc_adjustment
= NULL
,
463 .dpp_set_csc_default
= NULL
,
464 .dpp_program_regamma_pwl
= oppn20_dummy_program_regamma_pwl
,
465 .dpp_set_degamma
= dpp2_set_degamma
,
466 .dpp_program_input_lut
= dpp2_dummy_program_input_lut
,
467 .dpp_full_bypass
= dpp1_full_bypass
,
468 .dpp_setup
= dpp2_cnv_setup
,
469 .dpp_program_degamma_pwl
= dpp2_set_degamma_pwl
,
470 .dpp_program_blnd_lut
= dpp20_program_blnd_lut
,
471 .dpp_program_shaper_lut
= dpp20_program_shaper
,
472 .dpp_program_3dlut
= dpp20_program_3dlut
,
473 .dpp_program_bias_and_scale
= NULL
,
474 .dpp_cnv_set_alpha_keyer
= dpp2_cnv_set_alpha_keyer
,
475 .set_cursor_attributes
= dpp2_set_cursor_attributes
,
476 .set_cursor_position
= dpp1_set_cursor_position
,
477 .set_optional_cursor_attributes
= dpp1_cnv_set_optional_cursor_attributes
,
478 .dpp_dppclk_control
= dpp1_dppclk_control
,
479 .dpp_set_hdr_multiplier
= dpp2_set_hdr_multiplier
,
482 static struct dpp_caps dcn20_dpp_cap
= {
483 .dscl_data_proc_format
= DSCL_DATA_PRCESSING_FLOAT_FORMAT
,
484 .dscl_calc_lb_num_partitions
= dscl2_calc_lb_num_partitions
,
488 struct dcn20_dpp
*dpp
,
489 struct dc_context
*ctx
,
491 const struct dcn2_dpp_registers
*tf_regs
,
492 const struct dcn2_dpp_shift
*tf_shift
,
493 const struct dcn2_dpp_mask
*tf_mask
)
497 dpp
->base
.inst
= inst
;
498 dpp
->base
.funcs
= &dcn20_dpp_funcs
;
499 dpp
->base
.caps
= &dcn20_dpp_cap
;
501 dpp
->tf_regs
= tf_regs
;
502 dpp
->tf_shift
= tf_shift
;
503 dpp
->tf_mask
= tf_mask
;
505 dpp
->lb_pixel_depth_supported
=
506 LB_PIXEL_DEPTH_18BPP
|
507 LB_PIXEL_DEPTH_24BPP
|
508 LB_PIXEL_DEPTH_30BPP
;
510 dpp
->lb_bits_per_entry
= LB_BITS_PER_ENTRY
;
511 dpp
->lb_memory_size
= LB_TOTAL_NUMBER_OF_ENTRIES
; /*0x1404*/