1 // SPDX-License-Identifier: MIT
2 //
3 // Copyright 2024 Advanced Micro Devices, Inc.
4
5 #include "dc_spl_translate.h"
6 #include "dcn20/dcn20_dpp.h"
7 #include "dcn32/dcn32_dpp.h"
8 #include "dcn401/dcn401_dpp.h"
9
10 static struct spl_callbacks dcn2_spl_callbacks = {
11 .spl_calc_lb_num_partitions = dscl2_spl_calc_lb_num_partitions,
12 };
13 static struct spl_callbacks dcn32_spl_callbacks = {
14 .spl_calc_lb_num_partitions = dscl32_spl_calc_lb_num_partitions,
15 };
16 static struct spl_callbacks dcn401_spl_callbacks = {
17 .spl_calc_lb_num_partitions = dscl401_spl_calc_lb_num_partitions,
18 };
populate_splrect_from_rect(struct spl_rect * spl_rect,const struct rect * rect)19 static void populate_splrect_from_rect(struct spl_rect *spl_rect, const struct rect *rect)
20 {
21 spl_rect->x = rect->x;
22 spl_rect->y = rect->y;
23 spl_rect->width = rect->width;
24 spl_rect->height = rect->height;
25 }
populate_rect_from_splrect(struct rect * rect,const struct spl_rect * spl_rect)26 static void populate_rect_from_splrect(struct rect *rect, const struct spl_rect *spl_rect)
27 {
28 rect->x = spl_rect->x;
29 rect->y = spl_rect->y;
30 rect->width = spl_rect->width;
31 rect->height = spl_rect->height;
32 }
populate_spltaps_from_taps(struct spl_taps * spl_scaling_quality,const struct scaling_taps * scaling_quality)33 static void populate_spltaps_from_taps(struct spl_taps *spl_scaling_quality,
34 const struct scaling_taps *scaling_quality)
35 {
36 spl_scaling_quality->h_taps_c = scaling_quality->h_taps_c;
37 spl_scaling_quality->h_taps = scaling_quality->h_taps;
38 spl_scaling_quality->v_taps_c = scaling_quality->v_taps_c;
39 spl_scaling_quality->v_taps = scaling_quality->v_taps;
40 spl_scaling_quality->integer_scaling = scaling_quality->integer_scaling;
41 }
populate_taps_from_spltaps(struct scaling_taps * scaling_quality,const struct spl_taps * spl_scaling_quality)42 static void populate_taps_from_spltaps(struct scaling_taps *scaling_quality,
43 const struct spl_taps *spl_scaling_quality)
44 {
45 scaling_quality->h_taps_c = spl_scaling_quality->h_taps_c + 1;
46 scaling_quality->h_taps = spl_scaling_quality->h_taps + 1;
47 scaling_quality->v_taps_c = spl_scaling_quality->v_taps_c + 1;
48 scaling_quality->v_taps = spl_scaling_quality->v_taps + 1;
49 }
populate_ratios_from_splratios(struct scaling_ratios * ratios,const struct ratio * spl_ratios)50 static void populate_ratios_from_splratios(struct scaling_ratios *ratios,
51 const struct ratio *spl_ratios)
52 {
53 ratios->horz = dc_fixpt_from_ux_dy(spl_ratios->h_scale_ratio >> 5, 3, 19);
54 ratios->vert = dc_fixpt_from_ux_dy(spl_ratios->v_scale_ratio >> 5, 3, 19);
55 ratios->horz_c = dc_fixpt_from_ux_dy(spl_ratios->h_scale_ratio_c >> 5, 3, 19);
56 ratios->vert_c = dc_fixpt_from_ux_dy(spl_ratios->v_scale_ratio_c >> 5, 3, 19);
57 }
populate_inits_from_splinits(struct scl_inits * inits,const struct init * spl_inits)58 static void populate_inits_from_splinits(struct scl_inits *inits,
59 const struct init *spl_inits)
60 {
61 inits->h = dc_fixpt_from_int_dy(spl_inits->h_filter_init_int, spl_inits->h_filter_init_frac >> 5, 0, 19);
62 inits->v = dc_fixpt_from_int_dy(spl_inits->v_filter_init_int, spl_inits->v_filter_init_frac >> 5, 0, 19);
63 inits->h_c = dc_fixpt_from_int_dy(spl_inits->h_filter_init_int_c, spl_inits->h_filter_init_frac_c >> 5, 0, 19);
64 inits->v_c = dc_fixpt_from_int_dy(spl_inits->v_filter_init_int_c, spl_inits->v_filter_init_frac_c >> 5, 0, 19);
65 }
populate_splformat_from_format(enum spl_pixel_format * spl_pixel_format,const enum pixel_format pixel_format)66 static void populate_splformat_from_format(enum spl_pixel_format *spl_pixel_format, const enum pixel_format pixel_format)
67 {
68 if (pixel_format < PIXEL_FORMAT_INVALID)
69 *spl_pixel_format = (enum spl_pixel_format)pixel_format;
70 else
71 *spl_pixel_format = SPL_PIXEL_FORMAT_INVALID;
72 }
73 /// @brief Translate SPL input parameters from pipe context
74 /// @param pipe_ctx
75 /// @param spl_in
translate_SPL_in_params_from_pipe_ctx(struct pipe_ctx * pipe_ctx,struct spl_in * spl_in)76 void translate_SPL_in_params_from_pipe_ctx(struct pipe_ctx *pipe_ctx, struct spl_in *spl_in)
77 {
78 const struct dc_plane_state *plane_state = pipe_ctx->plane_state;
79 const struct dc_stream_state *stream = pipe_ctx->stream;
80 struct rect odm_slice_src = resource_get_odm_slice_src_rect(pipe_ctx);
81
82 // Assign the function to calculate the number of partitions in the line buffer
83 // This is used to determine the vtap support
84 switch (plane_state->ctx->dce_version) {
85 case DCN_VERSION_2_0:
86 spl_in->callbacks = dcn2_spl_callbacks;
87 break;
88 case DCN_VERSION_3_2:
89 spl_in->callbacks = dcn32_spl_callbacks;
90 break;
91 case DCN_VERSION_4_01:
92 spl_in->callbacks = dcn401_spl_callbacks;
93 break;
94 default:
95 spl_in->callbacks = dcn2_spl_callbacks;
96 }
97 // Make format field from spl_in point to plane_res scl_data format
98 populate_splformat_from_format(&spl_in->basic_in.format, pipe_ctx->plane_res.scl_data.format);
99 // Make view_format from basic_out point to view_format from stream
100 spl_in->basic_out.view_format = (enum spl_view_3d)stream->view_format;
101 // Populate spl input basic input clip rect from plane state clip rect
102 populate_splrect_from_rect(&spl_in->basic_in.clip_rect, &plane_state->clip_rect);
103 // Populate spl input basic out src rect from stream src rect
104 populate_splrect_from_rect(&spl_in->basic_out.src_rect, &stream->src);
105 // Populate spl input basic out dst rect from stream dst rect
106 populate_splrect_from_rect(&spl_in->basic_out.dst_rect, &stream->dst);
107 // Make spl input basic input info rotation field point to plane state rotation
108 spl_in->basic_in.rotation = (enum spl_rotation_angle)plane_state->rotation;
109 // Populate spl input basic input src rect from plane state src rect
110 populate_splrect_from_rect(&spl_in->basic_in.src_rect, &plane_state->src_rect);
111 // Populate spl input basic input dst rect from plane state dst rect
112 populate_splrect_from_rect(&spl_in->basic_in.dst_rect, &plane_state->dst_rect);
113 // Make spl input basic input info horiz mirror field point to plane state horz mirror
114 spl_in->basic_in.horizontal_mirror = plane_state->horizontal_mirror;
115
116 // Calculate horizontal splits and split index
117 spl_in->basic_in.num_h_slices_recout_width_align.use_recout_width_aligned = false;
118 spl_in->basic_in.num_h_slices_recout_width_align.num_slices_recout_width.mpc_num_h_slices =
119 resource_get_mpc_slice_count(pipe_ctx);
120
121 if (stream->view_format == VIEW_3D_FORMAT_SIDE_BY_SIDE)
122 spl_in->basic_in.mpc_h_slice_index = 0;
123 else
124 spl_in->basic_in.mpc_h_slice_index = resource_get_mpc_slice_index(pipe_ctx);
125
126 populate_splrect_from_rect(&spl_in->basic_out.odm_slice_rect, &odm_slice_src);
127 spl_in->basic_out.odm_combine_factor = 0;
128 spl_in->odm_slice_index = resource_get_odm_slice_index(pipe_ctx);
129 // Make spl input basic out info output_size width point to stream h active
130 spl_in->basic_out.output_size.width =
131 stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right + pipe_ctx->hblank_borrow;
132 // Make spl input basic out info output_size height point to v active
133 spl_in->basic_out.output_size.height =
134 stream->timing.v_addressable + stream->timing.v_border_bottom + stream->timing.v_border_top;
135 spl_in->basic_out.max_downscale_src_width =
136 pipe_ctx->stream->ctx->dc->debug.max_downscale_src_width;
137 spl_in->basic_out.always_scale = pipe_ctx->stream->ctx->dc->debug.always_scale;
138 // Make spl input basic output info alpha_en field point to plane res scl_data lb_params alpha_en
139 spl_in->basic_out.alpha_en = pipe_ctx->plane_res.scl_data.lb_params.alpha_en;
140 spl_in->basic_out.use_two_pixels_per_container = pipe_ctx->stream_res.tg->funcs->is_two_pixels_per_container(&stream->timing);
141 // Make spl input basic input info scaling quality field point to plane state scaling_quality
142 populate_spltaps_from_taps(&spl_in->scaling_quality, &plane_state->scaling_quality);
143 // Translate edge adaptive scaler preference
144 spl_in->prefer_easf = pipe_ctx->stream->ctx->dc->config.prefer_easf;
145 spl_in->disable_easf = false;
146 if (pipe_ctx->stream->ctx->dc->debug.force_easf == 1)
147 spl_in->prefer_easf = false;
148 else if (pipe_ctx->stream->ctx->dc->debug.force_easf == 2)
149 spl_in->disable_easf = true;
150 /* Translate adaptive sharpening preference */
151 unsigned int sharpness_setting = pipe_ctx->stream->ctx->dc->debug.force_sharpness;
152 unsigned int force_sharpness_level = pipe_ctx->stream->ctx->dc->debug.force_sharpness_level;
153 if (sharpness_setting == SHARPNESS_HW_OFF)
154 spl_in->adaptive_sharpness.enable = false;
155 else if (sharpness_setting == SHARPNESS_ZERO) {
156 spl_in->adaptive_sharpness.enable = true;
157 spl_in->adaptive_sharpness.sharpness_level = 0;
158 } else if (sharpness_setting == SHARPNESS_CUSTOM) {
159 spl_in->adaptive_sharpness.sharpness_range.sdr_rgb_min = 0;
160 spl_in->adaptive_sharpness.sharpness_range.sdr_rgb_max = 1750;
161 spl_in->adaptive_sharpness.sharpness_range.sdr_rgb_mid = 750;
162 spl_in->adaptive_sharpness.sharpness_range.sdr_yuv_min = 0;
163 spl_in->adaptive_sharpness.sharpness_range.sdr_yuv_max = 3500;
164 spl_in->adaptive_sharpness.sharpness_range.sdr_yuv_mid = 1500;
165 spl_in->adaptive_sharpness.sharpness_range.hdr_rgb_min = 0;
166 spl_in->adaptive_sharpness.sharpness_range.hdr_rgb_max = 2750;
167 spl_in->adaptive_sharpness.sharpness_range.hdr_rgb_mid = 1500;
168
169 if (force_sharpness_level > 0) {
170 if (force_sharpness_level > 10)
171 force_sharpness_level = 10;
172 spl_in->adaptive_sharpness.enable = true;
173 spl_in->adaptive_sharpness.sharpness_level = force_sharpness_level;
174 } else if (!plane_state->adaptive_sharpness_en) {
175 spl_in->adaptive_sharpness.enable = false;
176 spl_in->adaptive_sharpness.sharpness_level = 0;
177 } else {
178 spl_in->adaptive_sharpness.enable = true;
179 spl_in->adaptive_sharpness.sharpness_level = plane_state->sharpness_level;
180 }
181 }
182 // Translate linear light scaling preference
183 if (pipe_ctx->stream->ctx->dc->debug.force_lls > 0)
184 spl_in->lls_pref = pipe_ctx->stream->ctx->dc->debug.force_lls;
185 else
186 spl_in->lls_pref = plane_state->linear_light_scaling;
187 /* Translate chroma subsampling offset ( cositing ) */
188 if (pipe_ctx->stream->ctx->dc->debug.force_cositing)
189 spl_in->basic_in.cositing = pipe_ctx->stream->ctx->dc->debug.force_cositing - 1;
190 else
191 spl_in->basic_in.cositing = plane_state->cositing;
192 /* Translate transfer function */
193 spl_in->basic_in.tf_type = (enum spl_transfer_func_type) plane_state->in_transfer_func.type;
194 spl_in->basic_in.tf_predefined_type = (enum spl_transfer_func_predefined) plane_state->in_transfer_func.tf;
195
196 spl_in->h_active = pipe_ctx->plane_res.scl_data.h_active;
197 spl_in->v_active = pipe_ctx->plane_res.scl_data.v_active;
198
199 spl_in->sharpen_policy = (enum sharpen_policy)plane_state->adaptive_sharpness_policy;
200 spl_in->debug.scale_to_sharpness_policy =
201 (enum scale_to_sharpness_policy)pipe_ctx->stream->ctx->dc->debug.scale_to_sharpness_policy;
202
203 /* Check if it is stream is in fullscreen and if its HDR.
204 * Use this to determine sharpness levels
205 */
206 spl_in->is_fullscreen = pipe_ctx->stream->sharpening_required;
207 spl_in->is_hdr_on = dm_helpers_is_hdr_on(pipe_ctx->stream->ctx, pipe_ctx->stream);
208 spl_in->sdr_white_level_nits = plane_state->sdr_white_level_nits;
209 }
210
211 /// @brief Translate SPL output parameters to pipe context
212 /// @param pipe_ctx
213 /// @param spl_out
translate_SPL_out_params_to_pipe_ctx(struct pipe_ctx * pipe_ctx,struct spl_out * spl_out)214 void translate_SPL_out_params_to_pipe_ctx(struct pipe_ctx *pipe_ctx, struct spl_out *spl_out)
215 {
216 // Make scaler data recout point to spl output field recout
217 populate_rect_from_splrect(&pipe_ctx->plane_res.scl_data.recout, &spl_out->dscl_prog_data->recout);
218 // Make scaler data ratios point to spl output field ratios
219 populate_ratios_from_splratios(&pipe_ctx->plane_res.scl_data.ratios, &spl_out->dscl_prog_data->ratios);
220 // Make scaler data viewport point to spl output field viewport
221 populate_rect_from_splrect(&pipe_ctx->plane_res.scl_data.viewport, &spl_out->dscl_prog_data->viewport);
222 // Make scaler data viewport_c point to spl output field viewport_c
223 populate_rect_from_splrect(&pipe_ctx->plane_res.scl_data.viewport_c, &spl_out->dscl_prog_data->viewport_c);
224 // Make scaler data taps point to spl output field scaling taps
225 populate_taps_from_spltaps(&pipe_ctx->plane_res.scl_data.taps, &spl_out->dscl_prog_data->taps);
226 // Make scaler data init point to spl output field init
227 populate_inits_from_splinits(&pipe_ctx->plane_res.scl_data.inits, &spl_out->dscl_prog_data->init);
228 }
229