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 uint32_t pixel_width
;
139 if (scl_data
->viewport
.width
> scl_data
->recout
.width
)
140 pixel_width
= scl_data
->recout
.width
;
142 pixel_width
= scl_data
->viewport
.width
;
144 /* Some ASICs does not support FP16 scaling, so we reject modes require this*/
145 if (scl_data
->format
== PIXEL_FORMAT_FP16
&&
146 dpp
->caps
->dscl_data_proc_format
== DSCL_DATA_PRCESSING_FIXED_FORMAT
&&
147 scl_data
->ratios
.horz
.value
!= dc_fixpt_one
.value
&&
148 scl_data
->ratios
.vert
.value
!= dc_fixpt_one
.value
)
151 if (scl_data
->viewport
.width
> scl_data
->h_active
&&
152 dpp
->ctx
->dc
->debug
.max_downscale_src_width
!= 0 &&
153 scl_data
->viewport
.width
> dpp
->ctx
->dc
->debug
.max_downscale_src_width
)
156 /* TODO: add lb check */
158 /* No support for programming ratio of 4, drop to 3.99999.. */
159 if (scl_data
->ratios
.horz
.value
== (4ll << 32))
160 scl_data
->ratios
.horz
.value
--;
161 if (scl_data
->ratios
.vert
.value
== (4ll << 32))
162 scl_data
->ratios
.vert
.value
--;
163 if (scl_data
->ratios
.horz_c
.value
== (4ll << 32))
164 scl_data
->ratios
.horz_c
.value
--;
165 if (scl_data
->ratios
.vert_c
.value
== (4ll << 32))
166 scl_data
->ratios
.vert_c
.value
--;
168 /* Set default taps if none are provided */
169 if (in_taps
->h_taps
== 0)
170 scl_data
->taps
.h_taps
= 4;
172 scl_data
->taps
.h_taps
= in_taps
->h_taps
;
173 if (in_taps
->v_taps
== 0)
174 scl_data
->taps
.v_taps
= 4;
176 scl_data
->taps
.v_taps
= in_taps
->v_taps
;
177 if (in_taps
->v_taps_c
== 0)
178 scl_data
->taps
.v_taps_c
= 2;
180 scl_data
->taps
.v_taps_c
= in_taps
->v_taps_c
;
181 if (in_taps
->h_taps_c
== 0)
182 scl_data
->taps
.h_taps_c
= 2;
183 /* Only 1 and even h_taps_c are supported by hw */
184 else if ((in_taps
->h_taps_c
% 2) != 0 && in_taps
->h_taps_c
!= 1)
185 scl_data
->taps
.h_taps_c
= in_taps
->h_taps_c
- 1;
187 scl_data
->taps
.h_taps_c
= in_taps
->h_taps_c
;
189 if (!dpp
->ctx
->dc
->debug
.always_scale
) {
190 if (IDENTITY_RATIO(scl_data
->ratios
.horz
))
191 scl_data
->taps
.h_taps
= 1;
192 if (IDENTITY_RATIO(scl_data
->ratios
.vert
))
193 scl_data
->taps
.v_taps
= 1;
194 if (IDENTITY_RATIO(scl_data
->ratios
.horz_c
))
195 scl_data
->taps
.h_taps_c
= 1;
196 if (IDENTITY_RATIO(scl_data
->ratios
.vert_c
))
197 scl_data
->taps
.v_taps_c
= 1;
203 void dpp_reset(struct dpp
*dpp_base
)
205 struct dcn10_dpp
*dpp
= TO_DCN10_DPP(dpp_base
);
207 dpp
->filter_h_c
= NULL
;
208 dpp
->filter_v_c
= NULL
;
209 dpp
->filter_h
= NULL
;
210 dpp
->filter_v
= NULL
;
212 memset(&dpp
->scl_data
, 0, sizeof(dpp
->scl_data
));
213 memset(&dpp
->pwl_data
, 0, sizeof(dpp
->pwl_data
));
218 static void dpp1_cm_set_regamma_pwl(
219 struct dpp
*dpp_base
, const struct pwl_params
*params
, enum opp_regamma mode
)
221 struct dcn10_dpp
*dpp
= TO_DCN10_DPP(dpp_base
);
222 uint32_t re_mode
= 0;
225 case OPP_REGAMMA_BYPASS
:
228 case OPP_REGAMMA_SRGB
:
231 case OPP_REGAMMA_XVYCC
:
234 case OPP_REGAMMA_USER
:
235 re_mode
= dpp
->is_write_to_ram_a_safe
? 4 : 3;
236 if (memcmp(&dpp
->pwl_data
, params
, sizeof(*params
)) == 0)
239 dpp1_cm_power_on_regamma_lut(dpp_base
, true);
240 dpp1_cm_configure_regamma_lut(dpp_base
, dpp
->is_write_to_ram_a_safe
);
242 if (dpp
->is_write_to_ram_a_safe
)
243 dpp1_cm_program_regamma_luta_settings(dpp_base
, params
);
245 dpp1_cm_program_regamma_lutb_settings(dpp_base
, params
);
247 dpp1_cm_program_regamma_lut(dpp_base
, params
->rgb_resulted
,
248 params
->hw_points_num
);
249 dpp
->pwl_data
= *params
;
251 re_mode
= dpp
->is_write_to_ram_a_safe
? 3 : 4;
252 dpp
->is_write_to_ram_a_safe
= !dpp
->is_write_to_ram_a_safe
;
257 REG_SET(CM_RGAM_CONTROL
, 0, CM_RGAM_LUT_MODE
, re_mode
);
260 static void dpp1_setup_format_flags(enum surface_pixel_format input_format
,\
261 enum pixel_format_description
*fmt
)
264 if (input_format
== SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F
||
265 input_format
== SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F
)
266 *fmt
= PIXEL_FORMAT_FLOAT
;
267 else if (input_format
== SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616
)
268 *fmt
= PIXEL_FORMAT_FIXED16
;
270 *fmt
= PIXEL_FORMAT_FIXED
;
273 static void dpp1_set_degamma_format_float(
274 struct dpp
*dpp_base
,
277 struct dcn10_dpp
*dpp
= TO_DCN10_DPP(dpp_base
);
280 REG_UPDATE(CM_IGAM_CONTROL
, CM_IGAM_INPUT_FORMAT
, 3);
281 REG_UPDATE(CM_IGAM_CONTROL
, CM_IGAM_LUT_MODE
, 1);
283 REG_UPDATE(CM_IGAM_CONTROL
, CM_IGAM_INPUT_FORMAT
, 2);
284 REG_UPDATE(CM_IGAM_CONTROL
, CM_IGAM_LUT_MODE
, 0);
288 void dpp1_cnv_setup (
289 struct dpp
*dpp_base
,
290 enum surface_pixel_format format
,
291 enum expansion_mode mode
,
292 struct dc_csc_transform input_csc_color_matrix
,
293 enum dc_color_space input_color_space
,
294 struct cnv_alpha_2bit_lut
*alpha_2bit_lut
)
296 uint32_t pixel_format
;
298 enum pixel_format_description fmt
;
299 enum dc_color_space color_space
;
300 enum dcn10_input_csc_select select
;
302 struct dcn10_dpp
*dpp
= TO_DCN10_DPP(dpp_base
);
303 bool force_disable_cursor
= false;
304 struct out_csc_color_matrix tbl_entry
;
307 dpp1_setup_format_flags(format
, &fmt
);
310 color_space
= COLOR_SPACE_SRGB
;
311 select
= INPUT_CSC_SELECT_BYPASS
;
315 case PIXEL_FORMAT_FIXED
:
316 case PIXEL_FORMAT_FIXED16
:
317 /*when output is float then FORMAT_CONTROL__OUTPUT_FP=1*/
318 REG_SET_3(FORMAT_CONTROL
, 0,
320 FORMAT_EXPANSION_MODE
, mode
,
323 case PIXEL_FORMAT_FLOAT
:
324 REG_SET_3(FORMAT_CONTROL
, 0,
326 FORMAT_EXPANSION_MODE
, mode
,
335 dpp1_set_degamma_format_float(dpp_base
, is_float
);
338 case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555
:
341 case SURFACE_PIXEL_FORMAT_GRPH_RGB565
:
345 case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888
:
346 case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888
:
349 case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010
:
350 case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010
:
353 case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr
:
354 force_disable_cursor
= false;
356 color_space
= COLOR_SPACE_YCBCR709
;
357 select
= INPUT_CSC_SELECT_ICSC
;
359 case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb
:
360 force_disable_cursor
= true;
362 color_space
= COLOR_SPACE_YCBCR709
;
363 select
= INPUT_CSC_SELECT_ICSC
;
365 case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr
:
366 force_disable_cursor
= true;
368 color_space
= COLOR_SPACE_YCBCR709
;
369 select
= INPUT_CSC_SELECT_ICSC
;
371 case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb
:
372 force_disable_cursor
= true;
374 color_space
= COLOR_SPACE_YCBCR709
;
375 select
= INPUT_CSC_SELECT_ICSC
;
377 case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616
:
380 case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F
:
383 case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F
:
390 /* Set default color space based on format if none is given. */
391 color_space
= input_color_space
? input_color_space
: color_space
;
393 REG_SET(CNVC_SURFACE_PIXEL_FORMAT
, 0,
394 CNVC_SURFACE_PIXEL_FORMAT
, pixel_format
);
395 REG_UPDATE(FORMAT_CONTROL
, FORMAT_CONTROL__ALPHA_EN
, alpha_en
);
397 // if input adjustments exist, program icsc with those values
399 if (input_csc_color_matrix
.enable_adjustment
401 for (i
= 0; i
< 12; i
++)
402 tbl_entry
.regval
[i
] = input_csc_color_matrix
.matrix
[i
];
404 tbl_entry
.color_space
= color_space
;
406 if (color_space
>= COLOR_SPACE_YCBCR601
)
407 select
= INPUT_CSC_SELECT_ICSC
;
409 select
= INPUT_CSC_SELECT_BYPASS
;
411 dpp1_program_input_csc(dpp_base
, color_space
, select
, &tbl_entry
);
413 dpp1_program_input_csc(dpp_base
, color_space
, select
, NULL
);
415 if (force_disable_cursor
) {
416 REG_UPDATE(CURSOR_CONTROL
,
418 REG_UPDATE(CURSOR0_CONTROL
,
423 void dpp1_set_cursor_attributes(
424 struct dpp
*dpp_base
,
425 struct dc_cursor_attributes
*cursor_attributes
)
427 enum dc_cursor_color_format color_format
= cursor_attributes
->color_format
;
428 struct dcn10_dpp
*dpp
= TO_DCN10_DPP(dpp_base
);
430 REG_UPDATE_2(CURSOR0_CONTROL
,
431 CUR0_MODE
, color_format
,
432 CUR0_EXPANSION_MODE
, 0);
434 if (color_format
== CURSOR_MODE_MONO
) {
435 /* todo: clarify what to program these to */
436 REG_UPDATE(CURSOR0_COLOR0
,
437 CUR0_COLOR0
, 0x00000000);
438 REG_UPDATE(CURSOR0_COLOR1
,
439 CUR0_COLOR1
, 0xFFFFFFFF);
444 void dpp1_set_cursor_position(
445 struct dpp
*dpp_base
,
446 const struct dc_cursor_position
*pos
,
447 const struct dc_cursor_mi_param
*param
,
451 struct dcn10_dpp
*dpp
= TO_DCN10_DPP(dpp_base
);
452 int src_x_offset
= pos
->x
- pos
->x_hotspot
- param
->viewport
.x
;
453 int src_y_offset
= pos
->y
- pos
->y_hotspot
- param
->viewport
.y
;
454 uint32_t cur_en
= pos
->enable
? 1 : 0;
456 // Cursor width/height and hotspots need to be rotated for offset calculation
457 if (param
->rotation
== ROTATION_ANGLE_90
|| param
->rotation
== ROTATION_ANGLE_270
) {
459 if (param
->rotation
== ROTATION_ANGLE_90
) {
460 src_x_offset
= pos
->x
- pos
->y_hotspot
- param
->viewport
.x
;
461 src_y_offset
= pos
->y
- pos
->x_hotspot
- param
->viewport
.y
;
463 } else if (param
->rotation
== ROTATION_ANGLE_180
) {
464 src_x_offset
= pos
->x
- param
->viewport
.x
;
465 src_y_offset
= pos
->y
- param
->viewport
.y
;
469 if (src_x_offset
>= (int)param
->viewport
.width
)
470 cur_en
= 0; /* not visible beyond right edge*/
472 if (src_x_offset
+ (int)width
<= 0)
473 cur_en
= 0; /* not visible beyond left edge*/
475 if (src_y_offset
>= (int)param
->viewport
.height
)
476 cur_en
= 0; /* not visible beyond bottom edge*/
478 if (src_y_offset
+ (int)height
<= 0)
479 cur_en
= 0; /* not visible beyond top edge*/
481 REG_UPDATE(CURSOR0_CONTROL
,
482 CUR0_ENABLE
, cur_en
);
486 void dpp1_cnv_set_optional_cursor_attributes(
487 struct dpp
*dpp_base
,
488 struct dpp_cursor_attributes
*attr
)
490 struct dcn10_dpp
*dpp
= TO_DCN10_DPP(dpp_base
);
493 REG_UPDATE(CURSOR0_FP_SCALE_BIAS
, CUR0_FP_BIAS
, attr
->bias
);
494 REG_UPDATE(CURSOR0_FP_SCALE_BIAS
, CUR0_FP_SCALE
, attr
->scale
);
498 void dpp1_dppclk_control(
499 struct dpp
*dpp_base
,
503 struct dcn10_dpp
*dpp
= TO_DCN10_DPP(dpp_base
);
506 if (dpp
->tf_mask
->DPPCLK_RATE_CONTROL
)
507 REG_UPDATE_2(DPP_CONTROL
,
508 DPPCLK_RATE_CONTROL
, dppclk_div
,
509 DPP_CLOCK_ENABLE
, 1);
511 REG_UPDATE(DPP_CONTROL
, DPP_CLOCK_ENABLE
, 1);
513 REG_UPDATE(DPP_CONTROL
, DPP_CLOCK_ENABLE
, 0);
516 static const struct dpp_funcs dcn10_dpp_funcs
= {
517 .dpp_read_state
= dpp_read_state
,
518 .dpp_reset
= dpp_reset
,
519 .dpp_set_scaler
= dpp1_dscl_set_scaler_manual_scale
,
520 .dpp_get_optimal_number_of_taps
= dpp1_get_optimal_number_of_taps
,
521 .dpp_set_gamut_remap
= dpp1_cm_set_gamut_remap
,
522 .dpp_set_csc_adjustment
= dpp1_cm_set_output_csc_adjustment
,
523 .dpp_set_csc_default
= dpp1_cm_set_output_csc_default
,
524 .dpp_power_on_regamma_lut
= dpp1_cm_power_on_regamma_lut
,
525 .dpp_program_regamma_lut
= dpp1_cm_program_regamma_lut
,
526 .dpp_configure_regamma_lut
= dpp1_cm_configure_regamma_lut
,
527 .dpp_program_regamma_lutb_settings
= dpp1_cm_program_regamma_lutb_settings
,
528 .dpp_program_regamma_luta_settings
= dpp1_cm_program_regamma_luta_settings
,
529 .dpp_program_regamma_pwl
= dpp1_cm_set_regamma_pwl
,
530 .dpp_program_bias_and_scale
= dpp1_program_bias_and_scale
,
531 .dpp_set_degamma
= dpp1_set_degamma
,
532 .dpp_program_input_lut
= dpp1_program_input_lut
,
533 .dpp_program_degamma_pwl
= dpp1_set_degamma_pwl
,
534 .dpp_setup
= dpp1_cnv_setup
,
535 .dpp_full_bypass
= dpp1_full_bypass
,
536 .set_cursor_attributes
= dpp1_set_cursor_attributes
,
537 .set_cursor_position
= dpp1_set_cursor_position
,
538 .set_optional_cursor_attributes
= dpp1_cnv_set_optional_cursor_attributes
,
539 .dpp_dppclk_control
= dpp1_dppclk_control
,
540 .dpp_set_hdr_multiplier
= dpp1_set_hdr_multiplier
,
541 .dpp_program_blnd_lut
= NULL
,
542 .dpp_program_shaper_lut
= NULL
,
543 .dpp_program_3dlut
= NULL
546 static struct dpp_caps dcn10_dpp_cap
= {
547 .dscl_data_proc_format
= DSCL_DATA_PRCESSING_FIXED_FORMAT
,
548 .dscl_calc_lb_num_partitions
= dpp1_dscl_calc_lb_num_partitions
,
551 /*****************************************/
552 /* Constructor, Destructor */
553 /*****************************************/
556 struct dcn10_dpp
*dpp
,
557 struct dc_context
*ctx
,
559 const struct dcn_dpp_registers
*tf_regs
,
560 const struct dcn_dpp_shift
*tf_shift
,
561 const struct dcn_dpp_mask
*tf_mask
)
565 dpp
->base
.inst
= inst
;
566 dpp
->base
.funcs
= &dcn10_dpp_funcs
;
567 dpp
->base
.caps
= &dcn10_dpp_cap
;
569 dpp
->tf_regs
= tf_regs
;
570 dpp
->tf_shift
= tf_shift
;
571 dpp
->tf_mask
= tf_mask
;
573 dpp
->lb_pixel_depth_supported
=
574 LB_PIXEL_DEPTH_18BPP
|
575 LB_PIXEL_DEPTH_24BPP
|
576 LB_PIXEL_DEPTH_30BPP
;
578 dpp
->lb_bits_per_entry
= LB_BITS_PER_ENTRY
;
579 dpp
->lb_memory_size
= LB_TOTAL_NUMBER_OF_ENTRIES
; /*0x1404*/