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 "dcn10_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 enum pixel_format_description
{
52 PIXEL_FORMAT_FIXED
= 0,
58 enum dcn10_coef_filter_type_sel
{
59 SCL_COEF_LUMA_VERT_FILTER
= 0,
60 SCL_COEF_LUMA_HORZ_FILTER
= 1,
61 SCL_COEF_CHROMA_VERT_FILTER
= 2,
62 SCL_COEF_CHROMA_HORZ_FILTER
= 3,
63 SCL_COEF_ALPHA_VERT_FILTER
= 4,
64 SCL_COEF_ALPHA_HORZ_FILTER
= 5
67 enum dscl_autocal_mode
{
70 /* Autocal calculate the scaling ratio and initial phase and the
71 * DSCL_MODE_SEL must be set to 1
73 AUTOCAL_MODE_AUTOSCALE
= 1,
74 /* Autocal perform auto centering without replication and the
75 * DSCL_MODE_SEL must be set to 0
77 AUTOCAL_MODE_AUTOCENTER
= 2,
78 /* Autocal perform auto centering and auto replication and the
79 * DSCL_MODE_SEL must be set to 0
81 AUTOCAL_MODE_AUTOREPLICATE
= 3
85 DSCL_MODE_SCALING_444_BYPASS
= 0,
86 DSCL_MODE_SCALING_444_RGB_ENABLE
= 1,
87 DSCL_MODE_SCALING_444_YCBCR_ENABLE
= 2,
88 DSCL_MODE_SCALING_420_YCBCR_ENABLE
= 3,
89 DSCL_MODE_SCALING_420_LUMA_BYPASS
= 4,
90 DSCL_MODE_SCALING_420_CHROMA_BYPASS
= 5,
91 DSCL_MODE_DSCL_BYPASS
= 6
94 void dpp_read_state(struct dpp
*dpp_base
,
95 struct dcn_dpp_state
*s
)
97 struct dcn10_dpp
*dpp
= TO_DCN10_DPP(dpp_base
);
100 DPP_CLOCK_ENABLE
, &s
->is_enabled
);
101 REG_GET(CM_IGAM_CONTROL
,
102 CM_IGAM_LUT_MODE
, &s
->igam_lut_mode
);
103 REG_GET(CM_IGAM_CONTROL
,
104 CM_IGAM_INPUT_FORMAT
, &s
->igam_input_format
);
105 REG_GET(CM_DGAM_CONTROL
,
106 CM_DGAM_LUT_MODE
, &s
->dgam_lut_mode
);
107 REG_GET(CM_RGAM_CONTROL
,
108 CM_RGAM_LUT_MODE
, &s
->rgam_lut_mode
);
109 REG_GET(CM_GAMUT_REMAP_CONTROL
,
110 CM_GAMUT_REMAP_MODE
, &s
->gamut_remap_mode
);
112 if (s
->gamut_remap_mode
) {
113 s
->gamut_remap_c11_c12
= REG_READ(CM_GAMUT_REMAP_C11_C12
);
114 s
->gamut_remap_c13_c14
= REG_READ(CM_GAMUT_REMAP_C13_C14
);
115 s
->gamut_remap_c21_c22
= REG_READ(CM_GAMUT_REMAP_C21_C22
);
116 s
->gamut_remap_c23_c24
= REG_READ(CM_GAMUT_REMAP_C23_C24
);
117 s
->gamut_remap_c31_c32
= REG_READ(CM_GAMUT_REMAP_C31_C32
);
118 s
->gamut_remap_c33_c34
= REG_READ(CM_GAMUT_REMAP_C33_C34
);
122 /* Program gamut remap in bypass mode */
123 void dpp_set_gamut_remap_bypass(struct dcn10_dpp
*dpp
)
125 REG_SET(CM_GAMUT_REMAP_CONTROL
, 0,
126 CM_GAMUT_REMAP_MODE
, 0);
127 /* Gamut remap in bypass */
130 #define IDENTITY_RATIO(ratio) (dc_fixpt_u2d19(ratio) == (1 << 19))
132 bool dpp1_get_optimal_number_of_taps(
134 struct scaler_data
*scl_data
,
135 const struct scaling_taps
*in_taps
)
137 /* Some ASICs does not support FP16 scaling, so we reject modes require this*/
138 if (scl_data
->format
== PIXEL_FORMAT_FP16
&&
139 dpp
->caps
->dscl_data_proc_format
== DSCL_DATA_PRCESSING_FIXED_FORMAT
&&
140 scl_data
->ratios
.horz
.value
!= dc_fixpt_one
.value
&&
141 scl_data
->ratios
.vert
.value
!= dc_fixpt_one
.value
)
144 if (scl_data
->viewport
.width
> scl_data
->h_active
&&
145 dpp
->ctx
->dc
->debug
.max_downscale_src_width
!= 0 &&
146 scl_data
->viewport
.width
> dpp
->ctx
->dc
->debug
.max_downscale_src_width
)
149 /* TODO: add lb check */
151 /* No support for programming ratio of 4, drop to 3.99999.. */
152 if (scl_data
->ratios
.horz
.value
== (4ll << 32))
153 scl_data
->ratios
.horz
.value
--;
154 if (scl_data
->ratios
.vert
.value
== (4ll << 32))
155 scl_data
->ratios
.vert
.value
--;
156 if (scl_data
->ratios
.horz_c
.value
== (4ll << 32))
157 scl_data
->ratios
.horz_c
.value
--;
158 if (scl_data
->ratios
.vert_c
.value
== (4ll << 32))
159 scl_data
->ratios
.vert_c
.value
--;
161 /* Set default taps if none are provided */
162 if (in_taps
->h_taps
== 0)
163 scl_data
->taps
.h_taps
= 4;
165 scl_data
->taps
.h_taps
= in_taps
->h_taps
;
166 if (in_taps
->v_taps
== 0)
167 scl_data
->taps
.v_taps
= 4;
169 scl_data
->taps
.v_taps
= in_taps
->v_taps
;
170 if (in_taps
->v_taps_c
== 0)
171 scl_data
->taps
.v_taps_c
= 2;
173 scl_data
->taps
.v_taps_c
= in_taps
->v_taps_c
;
174 if (in_taps
->h_taps_c
== 0)
175 scl_data
->taps
.h_taps_c
= 2;
176 /* Only 1 and even h_taps_c are supported by hw */
177 else if ((in_taps
->h_taps_c
% 2) != 0 && in_taps
->h_taps_c
!= 1)
178 scl_data
->taps
.h_taps_c
= in_taps
->h_taps_c
- 1;
180 scl_data
->taps
.h_taps_c
= in_taps
->h_taps_c
;
182 if (!dpp
->ctx
->dc
->debug
.always_scale
) {
183 if (IDENTITY_RATIO(scl_data
->ratios
.horz
))
184 scl_data
->taps
.h_taps
= 1;
185 if (IDENTITY_RATIO(scl_data
->ratios
.vert
))
186 scl_data
->taps
.v_taps
= 1;
187 if (IDENTITY_RATIO(scl_data
->ratios
.horz_c
))
188 scl_data
->taps
.h_taps_c
= 1;
189 if (IDENTITY_RATIO(scl_data
->ratios
.vert_c
))
190 scl_data
->taps
.v_taps_c
= 1;
196 void dpp_reset(struct dpp
*dpp_base
)
198 struct dcn10_dpp
*dpp
= TO_DCN10_DPP(dpp_base
);
200 dpp
->filter_h_c
= NULL
;
201 dpp
->filter_v_c
= NULL
;
202 dpp
->filter_h
= NULL
;
203 dpp
->filter_v
= NULL
;
205 memset(&dpp
->scl_data
, 0, sizeof(dpp
->scl_data
));
206 memset(&dpp
->pwl_data
, 0, sizeof(dpp
->pwl_data
));
211 static void dpp1_cm_set_regamma_pwl(
212 struct dpp
*dpp_base
, const struct pwl_params
*params
, enum opp_regamma mode
)
214 struct dcn10_dpp
*dpp
= TO_DCN10_DPP(dpp_base
);
215 uint32_t re_mode
= 0;
218 case OPP_REGAMMA_BYPASS
:
221 case OPP_REGAMMA_SRGB
:
224 case OPP_REGAMMA_XVYCC
:
227 case OPP_REGAMMA_USER
:
228 re_mode
= dpp
->is_write_to_ram_a_safe
? 4 : 3;
229 if (memcmp(&dpp
->pwl_data
, params
, sizeof(*params
)) == 0)
232 dpp1_cm_power_on_regamma_lut(dpp_base
, true);
233 dpp1_cm_configure_regamma_lut(dpp_base
, dpp
->is_write_to_ram_a_safe
);
235 if (dpp
->is_write_to_ram_a_safe
)
236 dpp1_cm_program_regamma_luta_settings(dpp_base
, params
);
238 dpp1_cm_program_regamma_lutb_settings(dpp_base
, params
);
240 dpp1_cm_program_regamma_lut(dpp_base
, params
->rgb_resulted
,
241 params
->hw_points_num
);
242 dpp
->pwl_data
= *params
;
244 re_mode
= dpp
->is_write_to_ram_a_safe
? 3 : 4;
245 dpp
->is_write_to_ram_a_safe
= !dpp
->is_write_to_ram_a_safe
;
250 REG_SET(CM_RGAM_CONTROL
, 0, CM_RGAM_LUT_MODE
, re_mode
);
253 static void dpp1_setup_format_flags(enum surface_pixel_format input_format
,\
254 enum pixel_format_description
*fmt
)
257 if (input_format
== SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F
||
258 input_format
== SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F
)
259 *fmt
= PIXEL_FORMAT_FLOAT
;
260 else if (input_format
== SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616
)
261 *fmt
= PIXEL_FORMAT_FIXED16
;
263 *fmt
= PIXEL_FORMAT_FIXED
;
266 static void dpp1_set_degamma_format_float(
267 struct dpp
*dpp_base
,
270 struct dcn10_dpp
*dpp
= TO_DCN10_DPP(dpp_base
);
273 REG_UPDATE(CM_IGAM_CONTROL
, CM_IGAM_INPUT_FORMAT
, 3);
274 REG_UPDATE(CM_IGAM_CONTROL
, CM_IGAM_LUT_MODE
, 1);
276 REG_UPDATE(CM_IGAM_CONTROL
, CM_IGAM_INPUT_FORMAT
, 2);
277 REG_UPDATE(CM_IGAM_CONTROL
, CM_IGAM_LUT_MODE
, 0);
281 void dpp1_cnv_setup (
282 struct dpp
*dpp_base
,
283 enum surface_pixel_format format
,
284 enum expansion_mode mode
,
285 struct dc_csc_transform input_csc_color_matrix
,
286 enum dc_color_space input_color_space
,
287 struct cnv_alpha_2bit_lut
*alpha_2bit_lut
)
289 uint32_t pixel_format
;
291 enum pixel_format_description fmt
;
292 enum dc_color_space color_space
;
293 enum dcn10_input_csc_select select
;
295 struct dcn10_dpp
*dpp
= TO_DCN10_DPP(dpp_base
);
296 bool force_disable_cursor
= false;
297 struct out_csc_color_matrix tbl_entry
;
300 dpp1_setup_format_flags(format
, &fmt
);
303 color_space
= COLOR_SPACE_SRGB
;
304 select
= INPUT_CSC_SELECT_BYPASS
;
308 case PIXEL_FORMAT_FIXED
:
309 case PIXEL_FORMAT_FIXED16
:
310 /*when output is float then FORMAT_CONTROL__OUTPUT_FP=1*/
311 REG_SET_3(FORMAT_CONTROL
, 0,
313 FORMAT_EXPANSION_MODE
, mode
,
316 case PIXEL_FORMAT_FLOAT
:
317 REG_SET_3(FORMAT_CONTROL
, 0,
319 FORMAT_EXPANSION_MODE
, mode
,
328 dpp1_set_degamma_format_float(dpp_base
, is_float
);
331 case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555
:
334 case SURFACE_PIXEL_FORMAT_GRPH_RGB565
:
338 case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888
:
339 case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888
:
342 case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010
:
343 case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010
:
346 case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr
:
347 force_disable_cursor
= false;
349 color_space
= COLOR_SPACE_YCBCR709
;
350 select
= INPUT_CSC_SELECT_ICSC
;
352 case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb
:
353 force_disable_cursor
= true;
355 color_space
= COLOR_SPACE_YCBCR709
;
356 select
= INPUT_CSC_SELECT_ICSC
;
358 case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr
:
359 force_disable_cursor
= true;
361 color_space
= COLOR_SPACE_YCBCR709
;
362 select
= INPUT_CSC_SELECT_ICSC
;
364 case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb
:
365 force_disable_cursor
= true;
367 color_space
= COLOR_SPACE_YCBCR709
;
368 select
= INPUT_CSC_SELECT_ICSC
;
370 case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616
:
373 case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F
:
376 case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F
:
383 /* Set default color space based on format if none is given. */
384 color_space
= input_color_space
? input_color_space
: color_space
;
386 REG_SET(CNVC_SURFACE_PIXEL_FORMAT
, 0,
387 CNVC_SURFACE_PIXEL_FORMAT
, pixel_format
);
388 REG_UPDATE(FORMAT_CONTROL
, FORMAT_CONTROL__ALPHA_EN
, alpha_en
);
390 // if input adjustments exist, program icsc with those values
392 if (input_csc_color_matrix
.enable_adjustment
394 for (i
= 0; i
< 12; i
++)
395 tbl_entry
.regval
[i
] = input_csc_color_matrix
.matrix
[i
];
397 tbl_entry
.color_space
= color_space
;
399 if (color_space
>= COLOR_SPACE_YCBCR601
)
400 select
= INPUT_CSC_SELECT_ICSC
;
402 select
= INPUT_CSC_SELECT_BYPASS
;
404 dpp1_program_input_csc(dpp_base
, color_space
, select
, &tbl_entry
);
406 dpp1_program_input_csc(dpp_base
, color_space
, select
, NULL
);
408 if (force_disable_cursor
) {
409 REG_UPDATE(CURSOR_CONTROL
,
411 REG_UPDATE(CURSOR0_CONTROL
,
416 void dpp1_set_cursor_attributes(
417 struct dpp
*dpp_base
,
418 struct dc_cursor_attributes
*cursor_attributes
)
420 enum dc_cursor_color_format color_format
= cursor_attributes
->color_format
;
421 struct dcn10_dpp
*dpp
= TO_DCN10_DPP(dpp_base
);
423 REG_UPDATE_2(CURSOR0_CONTROL
,
424 CUR0_MODE
, color_format
,
425 CUR0_EXPANSION_MODE
, 0);
427 if (color_format
== CURSOR_MODE_MONO
) {
428 /* todo: clarify what to program these to */
429 REG_UPDATE(CURSOR0_COLOR0
,
430 CUR0_COLOR0
, 0x00000000);
431 REG_UPDATE(CURSOR0_COLOR1
,
432 CUR0_COLOR1
, 0xFFFFFFFF);
437 void dpp1_set_cursor_position(
438 struct dpp
*dpp_base
,
439 const struct dc_cursor_position
*pos
,
440 const struct dc_cursor_mi_param
*param
,
444 struct dcn10_dpp
*dpp
= TO_DCN10_DPP(dpp_base
);
445 int src_x_offset
= pos
->x
- pos
->x_hotspot
- param
->viewport
.x
;
446 int src_y_offset
= pos
->y
- pos
->y_hotspot
- param
->viewport
.y
;
447 uint32_t cur_en
= pos
->enable
? 1 : 0;
449 // Cursor width/height and hotspots need to be rotated for offset calculation
450 if (param
->rotation
== ROTATION_ANGLE_90
|| param
->rotation
== ROTATION_ANGLE_270
) {
452 if (param
->rotation
== ROTATION_ANGLE_90
) {
453 src_x_offset
= pos
->x
- pos
->y_hotspot
- param
->viewport
.x
;
454 src_y_offset
= pos
->y
- pos
->x_hotspot
- param
->viewport
.y
;
456 } else if (param
->rotation
== ROTATION_ANGLE_180
) {
457 src_x_offset
= pos
->x
- param
->viewport
.x
;
458 src_y_offset
= pos
->y
- param
->viewport
.y
;
462 if (src_x_offset
>= (int)param
->viewport
.width
)
463 cur_en
= 0; /* not visible beyond right edge*/
465 if (src_x_offset
+ (int)width
<= 0)
466 cur_en
= 0; /* not visible beyond left edge*/
468 if (src_y_offset
>= (int)param
->viewport
.height
)
469 cur_en
= 0; /* not visible beyond bottom edge*/
471 if (src_y_offset
+ (int)height
<= 0)
472 cur_en
= 0; /* not visible beyond top edge*/
474 REG_UPDATE(CURSOR0_CONTROL
,
475 CUR0_ENABLE
, cur_en
);
479 void dpp1_cnv_set_optional_cursor_attributes(
480 struct dpp
*dpp_base
,
481 struct dpp_cursor_attributes
*attr
)
483 struct dcn10_dpp
*dpp
= TO_DCN10_DPP(dpp_base
);
486 REG_UPDATE(CURSOR0_FP_SCALE_BIAS
, CUR0_FP_BIAS
, attr
->bias
);
487 REG_UPDATE(CURSOR0_FP_SCALE_BIAS
, CUR0_FP_SCALE
, attr
->scale
);
491 void dpp1_dppclk_control(
492 struct dpp
*dpp_base
,
496 struct dcn10_dpp
*dpp
= TO_DCN10_DPP(dpp_base
);
499 if (dpp
->tf_mask
->DPPCLK_RATE_CONTROL
)
500 REG_UPDATE_2(DPP_CONTROL
,
501 DPPCLK_RATE_CONTROL
, dppclk_div
,
502 DPP_CLOCK_ENABLE
, 1);
504 REG_UPDATE(DPP_CONTROL
, DPP_CLOCK_ENABLE
, 1);
506 REG_UPDATE(DPP_CONTROL
, DPP_CLOCK_ENABLE
, 0);
509 static const struct dpp_funcs dcn10_dpp_funcs
= {
510 .dpp_read_state
= dpp_read_state
,
511 .dpp_reset
= dpp_reset
,
512 .dpp_set_scaler
= dpp1_dscl_set_scaler_manual_scale
,
513 .dpp_get_optimal_number_of_taps
= dpp1_get_optimal_number_of_taps
,
514 .dpp_set_gamut_remap
= dpp1_cm_set_gamut_remap
,
515 .dpp_set_csc_adjustment
= dpp1_cm_set_output_csc_adjustment
,
516 .dpp_set_csc_default
= dpp1_cm_set_output_csc_default
,
517 .dpp_power_on_regamma_lut
= dpp1_cm_power_on_regamma_lut
,
518 .dpp_program_regamma_lut
= dpp1_cm_program_regamma_lut
,
519 .dpp_configure_regamma_lut
= dpp1_cm_configure_regamma_lut
,
520 .dpp_program_regamma_lutb_settings
= dpp1_cm_program_regamma_lutb_settings
,
521 .dpp_program_regamma_luta_settings
= dpp1_cm_program_regamma_luta_settings
,
522 .dpp_program_regamma_pwl
= dpp1_cm_set_regamma_pwl
,
523 .dpp_program_bias_and_scale
= dpp1_program_bias_and_scale
,
524 .dpp_set_degamma
= dpp1_set_degamma
,
525 .dpp_program_input_lut
= dpp1_program_input_lut
,
526 .dpp_program_degamma_pwl
= dpp1_set_degamma_pwl
,
527 .dpp_setup
= dpp1_cnv_setup
,
528 .dpp_full_bypass
= dpp1_full_bypass
,
529 .set_cursor_attributes
= dpp1_set_cursor_attributes
,
530 .set_cursor_position
= dpp1_set_cursor_position
,
531 .set_optional_cursor_attributes
= dpp1_cnv_set_optional_cursor_attributes
,
532 .dpp_dppclk_control
= dpp1_dppclk_control
,
533 .dpp_set_hdr_multiplier
= dpp1_set_hdr_multiplier
,
534 .dpp_program_blnd_lut
= NULL
,
535 .dpp_program_shaper_lut
= NULL
,
536 .dpp_program_3dlut
= NULL
539 static struct dpp_caps dcn10_dpp_cap
= {
540 .dscl_data_proc_format
= DSCL_DATA_PRCESSING_FIXED_FORMAT
,
541 .dscl_calc_lb_num_partitions
= dpp1_dscl_calc_lb_num_partitions
,
544 /*****************************************/
545 /* Constructor, Destructor */
546 /*****************************************/
549 struct dcn10_dpp
*dpp
,
550 struct dc_context
*ctx
,
552 const struct dcn_dpp_registers
*tf_regs
,
553 const struct dcn_dpp_shift
*tf_shift
,
554 const struct dcn_dpp_mask
*tf_mask
)
558 dpp
->base
.inst
= inst
;
559 dpp
->base
.funcs
= &dcn10_dpp_funcs
;
560 dpp
->base
.caps
= &dcn10_dpp_cap
;
562 dpp
->tf_regs
= tf_regs
;
563 dpp
->tf_shift
= tf_shift
;
564 dpp
->tf_mask
= tf_mask
;
566 dpp
->lb_pixel_depth_supported
=
567 LB_PIXEL_DEPTH_18BPP
|
568 LB_PIXEL_DEPTH_24BPP
|
569 LB_PIXEL_DEPTH_30BPP
;
571 dpp
->lb_bits_per_entry
= LB_BITS_PER_ENTRY
;
572 dpp
->lb_memory_size
= LB_TOTAL_NUMBER_OF_ENTRIES
; /*0x1404*/