Line data Source code
1 : /*
2 : * Copyright 2016 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 :
28 : #include "core_types.h"
29 :
30 : #include "reg_helper.h"
31 : #include "dcn10_dpp.h"
32 : #include "basics/conversion.h"
33 :
34 :
35 : #define NUM_PHASES 64
36 : #define HORZ_MAX_TAPS 8
37 : #define VERT_MAX_TAPS 8
38 :
39 : #define BLACK_OFFSET_RGB_Y 0x0
40 : #define BLACK_OFFSET_CBCR 0x8000
41 :
42 : #define VISUAL_CONFIRM_RECT_HEIGHT_DEFAULT 3
43 : #define VISUAL_CONFIRM_RECT_HEIGHT_MIN 1
44 : #define VISUAL_CONFIRM_RECT_HEIGHT_MAX 10
45 :
46 : #define REG(reg)\
47 : dpp->tf_regs->reg
48 :
49 : #define CTX \
50 : dpp->base.ctx
51 :
52 : #undef FN
53 : #define FN(reg_name, field_name) \
54 : dpp->tf_shift->field_name, dpp->tf_mask->field_name
55 :
56 : enum dcn10_coef_filter_type_sel {
57 : SCL_COEF_LUMA_VERT_FILTER = 0,
58 : SCL_COEF_LUMA_HORZ_FILTER = 1,
59 : SCL_COEF_CHROMA_VERT_FILTER = 2,
60 : SCL_COEF_CHROMA_HORZ_FILTER = 3,
61 : SCL_COEF_ALPHA_VERT_FILTER = 4,
62 : SCL_COEF_ALPHA_HORZ_FILTER = 5
63 : };
64 :
65 : enum dscl_autocal_mode {
66 : AUTOCAL_MODE_OFF = 0,
67 :
68 : /* Autocal calculate the scaling ratio and initial phase and the
69 : * DSCL_MODE_SEL must be set to 1
70 : */
71 : AUTOCAL_MODE_AUTOSCALE = 1,
72 : /* Autocal perform auto centering without replication and the
73 : * DSCL_MODE_SEL must be set to 0
74 : */
75 : AUTOCAL_MODE_AUTOCENTER = 2,
76 : /* Autocal perform auto centering and auto replication and the
77 : * DSCL_MODE_SEL must be set to 0
78 : */
79 : AUTOCAL_MODE_AUTOREPLICATE = 3
80 : };
81 :
82 : enum dscl_mode_sel {
83 : DSCL_MODE_SCALING_444_BYPASS = 0,
84 : DSCL_MODE_SCALING_444_RGB_ENABLE = 1,
85 : DSCL_MODE_SCALING_444_YCBCR_ENABLE = 2,
86 : DSCL_MODE_SCALING_420_YCBCR_ENABLE = 3,
87 : DSCL_MODE_SCALING_420_LUMA_BYPASS = 4,
88 : DSCL_MODE_SCALING_420_CHROMA_BYPASS = 5,
89 : DSCL_MODE_DSCL_BYPASS = 6
90 : };
91 :
92 0 : static int dpp1_dscl_get_pixel_depth_val(enum lb_pixel_depth depth)
93 : {
94 0 : if (depth == LB_PIXEL_DEPTH_30BPP)
95 : return 0; /* 10 bpc */
96 0 : else if (depth == LB_PIXEL_DEPTH_24BPP)
97 : return 1; /* 8 bpc */
98 0 : else if (depth == LB_PIXEL_DEPTH_18BPP)
99 : return 2; /* 6 bpc */
100 0 : else if (depth == LB_PIXEL_DEPTH_36BPP)
101 : return 3; /* 12 bpc */
102 : else {
103 0 : ASSERT(0);
104 : return -1; /* Unsupported */
105 : }
106 : }
107 :
108 : static bool dpp1_dscl_is_video_format(enum pixel_format format)
109 : {
110 : if (format >= PIXEL_FORMAT_VIDEO_BEGIN
111 : && format <= PIXEL_FORMAT_VIDEO_END)
112 : return true;
113 : else
114 : return false;
115 : }
116 :
117 : static bool dpp1_dscl_is_420_format(enum pixel_format format)
118 : {
119 0 : if (format == PIXEL_FORMAT_420BPP8 ||
120 : format == PIXEL_FORMAT_420BPP10)
121 : return true;
122 : else
123 : return false;
124 : }
125 :
126 0 : static enum dscl_mode_sel dpp1_dscl_get_dscl_mode(
127 : struct dpp *dpp_base,
128 : const struct scaler_data *data,
129 : bool dbg_always_scale)
130 : {
131 0 : const long long one = dc_fixpt_one.value;
132 :
133 0 : if (dpp_base->caps->dscl_data_proc_format == DSCL_DATA_PRCESSING_FIXED_FORMAT) {
134 : /* DSCL is processing data in fixed format */
135 0 : if (data->format == PIXEL_FORMAT_FP16)
136 : return DSCL_MODE_DSCL_BYPASS;
137 : }
138 :
139 0 : if (data->ratios.horz.value == one
140 0 : && data->ratios.vert.value == one
141 0 : && data->ratios.horz_c.value == one
142 0 : && data->ratios.vert_c.value == one
143 0 : && !dbg_always_scale)
144 : return DSCL_MODE_SCALING_444_BYPASS;
145 :
146 0 : if (!dpp1_dscl_is_420_format(data->format)) {
147 : if (dpp1_dscl_is_video_format(data->format))
148 : return DSCL_MODE_SCALING_444_YCBCR_ENABLE;
149 : else
150 : return DSCL_MODE_SCALING_444_RGB_ENABLE;
151 : }
152 0 : if (data->ratios.horz.value == one && data->ratios.vert.value == one)
153 : return DSCL_MODE_SCALING_420_LUMA_BYPASS;
154 0 : if (data->ratios.horz_c.value == one && data->ratios.vert_c.value == one)
155 : return DSCL_MODE_SCALING_420_CHROMA_BYPASS;
156 :
157 0 : return DSCL_MODE_SCALING_420_YCBCR_ENABLE;
158 : }
159 :
160 0 : static void dpp1_power_on_dscl(
161 : struct dpp *dpp_base,
162 : bool power_on)
163 : {
164 0 : struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base);
165 :
166 0 : if (dpp->tf_regs->DSCL_MEM_PWR_CTRL) {
167 0 : if (power_on) {
168 0 : REG_UPDATE(DSCL_MEM_PWR_CTRL, LUT_MEM_PWR_FORCE, 0);
169 0 : REG_WAIT(DSCL_MEM_PWR_STATUS, LUT_MEM_PWR_STATE, 0, 1, 5);
170 : } else {
171 0 : if (dpp->base.ctx->dc->debug.enable_mem_low_power.bits.dscl) {
172 0 : dpp->base.ctx->dc->optimized_required = true;
173 0 : dpp->base.deferred_reg_writes.bits.disable_dscl = true;
174 : } else {
175 0 : REG_UPDATE(DSCL_MEM_PWR_CTRL, LUT_MEM_PWR_FORCE, 3);
176 : }
177 : }
178 : }
179 0 : }
180 :
181 :
182 0 : static void dpp1_dscl_set_lb(
183 : struct dcn10_dpp *dpp,
184 : const struct line_buffer_params *lb_params,
185 : enum lb_memory_config mem_size_config)
186 : {
187 0 : uint32_t max_partitions = 63; /* Currently hardcoded on all ASICs before DCN 3.2 */
188 :
189 : /* LB */
190 0 : if (dpp->base.caps->dscl_data_proc_format == DSCL_DATA_PRCESSING_FIXED_FORMAT) {
191 : /* DSCL caps: pixel data processed in fixed format */
192 0 : uint32_t pixel_depth = dpp1_dscl_get_pixel_depth_val(lb_params->depth);
193 0 : uint32_t dyn_pix_depth = lb_params->dynamic_pixel_depth;
194 :
195 0 : REG_SET_7(LB_DATA_FORMAT, 0,
196 : PIXEL_DEPTH, pixel_depth, /* Pixel depth stored in LB */
197 : PIXEL_EXPAN_MODE, lb_params->pixel_expan_mode, /* Pixel expansion mode */
198 : PIXEL_REDUCE_MODE, 1, /* Pixel reduction mode: Rounding */
199 : DYNAMIC_PIXEL_DEPTH, dyn_pix_depth, /* Dynamic expansion pixel depth */
200 : DITHER_EN, 0, /* Dithering enable: Disabled */
201 : INTERLEAVE_EN, lb_params->interleave_en, /* Interleave source enable */
202 : LB_DATA_FORMAT__ALPHA_EN, lb_params->alpha_en); /* Alpha enable */
203 : }
204 : else {
205 : /* DSCL caps: pixel data processed in float format */
206 0 : REG_SET_2(LB_DATA_FORMAT, 0,
207 : INTERLEAVE_EN, lb_params->interleave_en, /* Interleave source enable */
208 : LB_DATA_FORMAT__ALPHA_EN, lb_params->alpha_en); /* Alpha enable */
209 : }
210 :
211 0 : if (dpp->base.caps->max_lb_partitions == 31)
212 0 : max_partitions = 31;
213 :
214 0 : REG_SET_2(LB_MEMORY_CTRL, 0,
215 : MEMORY_CONFIG, mem_size_config,
216 : LB_MAX_PARTITIONS, max_partitions);
217 0 : }
218 :
219 0 : static const uint16_t *dpp1_dscl_get_filter_coeffs_64p(int taps, struct fixed31_32 ratio)
220 : {
221 0 : if (taps == 8)
222 0 : return get_filter_8tap_64p(ratio);
223 0 : else if (taps == 7)
224 0 : return get_filter_7tap_64p(ratio);
225 0 : else if (taps == 6)
226 0 : return get_filter_6tap_64p(ratio);
227 0 : else if (taps == 5)
228 0 : return get_filter_5tap_64p(ratio);
229 0 : else if (taps == 4)
230 0 : return get_filter_4tap_64p(ratio);
231 0 : else if (taps == 3)
232 0 : return get_filter_3tap_64p(ratio);
233 0 : else if (taps == 2)
234 0 : return get_filter_2tap_64p();
235 0 : else if (taps == 1)
236 : return NULL;
237 : else {
238 : /* should never happen, bug */
239 0 : BREAK_TO_DEBUGGER();
240 0 : return NULL;
241 : }
242 : }
243 :
244 0 : static void dpp1_dscl_set_scaler_filter(
245 : struct dcn10_dpp *dpp,
246 : uint32_t taps,
247 : enum dcn10_coef_filter_type_sel filter_type,
248 : const uint16_t *filter)
249 : {
250 0 : const int tap_pairs = (taps + 1) / 2;
251 : int phase;
252 : int pair;
253 : uint16_t odd_coef, even_coef;
254 :
255 0 : REG_SET_3(SCL_COEF_RAM_TAP_SELECT, 0,
256 : SCL_COEF_RAM_TAP_PAIR_IDX, 0,
257 : SCL_COEF_RAM_PHASE, 0,
258 : SCL_COEF_RAM_FILTER_TYPE, filter_type);
259 :
260 0 : for (phase = 0; phase < (NUM_PHASES / 2 + 1); phase++) {
261 0 : for (pair = 0; pair < tap_pairs; pair++) {
262 0 : even_coef = filter[phase * taps + 2 * pair];
263 0 : if ((pair * 2 + 1) < taps)
264 0 : odd_coef = filter[phase * taps + 2 * pair + 1];
265 : else
266 : odd_coef = 0;
267 :
268 0 : REG_SET_4(SCL_COEF_RAM_TAP_DATA, 0,
269 : /* Even tap coefficient (bits 1:0 fixed to 0) */
270 : SCL_COEF_RAM_EVEN_TAP_COEF, even_coef,
271 : /* Write/read control for even coefficient */
272 : SCL_COEF_RAM_EVEN_TAP_COEF_EN, 1,
273 : /* Odd tap coefficient (bits 1:0 fixed to 0) */
274 : SCL_COEF_RAM_ODD_TAP_COEF, odd_coef,
275 : /* Write/read control for odd coefficient */
276 : SCL_COEF_RAM_ODD_TAP_COEF_EN, 1);
277 : }
278 : }
279 :
280 0 : }
281 :
282 0 : static void dpp1_dscl_set_scl_filter(
283 : struct dcn10_dpp *dpp,
284 : const struct scaler_data *scl_data,
285 : bool chroma_coef_mode)
286 : {
287 0 : bool h_2tap_hardcode_coef_en = false;
288 0 : bool v_2tap_hardcode_coef_en = false;
289 0 : bool h_2tap_sharp_en = false;
290 0 : bool v_2tap_sharp_en = false;
291 0 : uint32_t h_2tap_sharp_factor = scl_data->sharpness.horz;
292 0 : uint32_t v_2tap_sharp_factor = scl_data->sharpness.vert;
293 : bool coef_ram_current;
294 0 : const uint16_t *filter_h = NULL;
295 0 : const uint16_t *filter_v = NULL;
296 0 : const uint16_t *filter_h_c = NULL;
297 0 : const uint16_t *filter_v_c = NULL;
298 :
299 0 : h_2tap_hardcode_coef_en = scl_data->taps.h_taps < 3
300 0 : && scl_data->taps.h_taps_c < 3
301 0 : && (scl_data->taps.h_taps > 1 && scl_data->taps.h_taps_c > 1);
302 0 : v_2tap_hardcode_coef_en = scl_data->taps.v_taps < 3
303 0 : && scl_data->taps.v_taps_c < 3
304 0 : && (scl_data->taps.v_taps > 1 && scl_data->taps.v_taps_c > 1);
305 :
306 0 : h_2tap_sharp_en = h_2tap_hardcode_coef_en && h_2tap_sharp_factor != 0;
307 0 : v_2tap_sharp_en = v_2tap_hardcode_coef_en && v_2tap_sharp_factor != 0;
308 :
309 0 : REG_UPDATE_6(DSCL_2TAP_CONTROL,
310 : SCL_H_2TAP_HARDCODE_COEF_EN, h_2tap_hardcode_coef_en,
311 : SCL_H_2TAP_SHARP_EN, h_2tap_sharp_en,
312 : SCL_H_2TAP_SHARP_FACTOR, h_2tap_sharp_factor,
313 : SCL_V_2TAP_HARDCODE_COEF_EN, v_2tap_hardcode_coef_en,
314 : SCL_V_2TAP_SHARP_EN, v_2tap_sharp_en,
315 : SCL_V_2TAP_SHARP_FACTOR, v_2tap_sharp_factor);
316 :
317 0 : if (!v_2tap_hardcode_coef_en || !h_2tap_hardcode_coef_en) {
318 0 : bool filter_updated = false;
319 :
320 0 : filter_h = dpp1_dscl_get_filter_coeffs_64p(
321 0 : scl_data->taps.h_taps, scl_data->ratios.horz);
322 0 : filter_v = dpp1_dscl_get_filter_coeffs_64p(
323 0 : scl_data->taps.v_taps, scl_data->ratios.vert);
324 :
325 0 : filter_updated = (filter_h && (filter_h != dpp->filter_h))
326 0 : || (filter_v && (filter_v != dpp->filter_v));
327 :
328 0 : if (chroma_coef_mode) {
329 0 : filter_h_c = dpp1_dscl_get_filter_coeffs_64p(
330 0 : scl_data->taps.h_taps_c, scl_data->ratios.horz_c);
331 0 : filter_v_c = dpp1_dscl_get_filter_coeffs_64p(
332 0 : scl_data->taps.v_taps_c, scl_data->ratios.vert_c);
333 0 : filter_updated = filter_updated || (filter_h_c && (filter_h_c != dpp->filter_h_c))
334 0 : || (filter_v_c && (filter_v_c != dpp->filter_v_c));
335 : }
336 :
337 0 : if (filter_updated) {
338 0 : uint32_t scl_mode = REG_READ(SCL_MODE);
339 :
340 0 : if (!h_2tap_hardcode_coef_en && filter_h) {
341 0 : dpp1_dscl_set_scaler_filter(
342 : dpp, scl_data->taps.h_taps,
343 : SCL_COEF_LUMA_HORZ_FILTER, filter_h);
344 : }
345 0 : dpp->filter_h = filter_h;
346 0 : if (!v_2tap_hardcode_coef_en && filter_v) {
347 0 : dpp1_dscl_set_scaler_filter(
348 : dpp, scl_data->taps.v_taps,
349 : SCL_COEF_LUMA_VERT_FILTER, filter_v);
350 : }
351 0 : dpp->filter_v = filter_v;
352 0 : if (chroma_coef_mode) {
353 0 : if (!h_2tap_hardcode_coef_en && filter_h_c) {
354 0 : dpp1_dscl_set_scaler_filter(
355 : dpp, scl_data->taps.h_taps_c,
356 : SCL_COEF_CHROMA_HORZ_FILTER, filter_h_c);
357 : }
358 0 : if (!v_2tap_hardcode_coef_en && filter_v_c) {
359 0 : dpp1_dscl_set_scaler_filter(
360 : dpp, scl_data->taps.v_taps_c,
361 : SCL_COEF_CHROMA_VERT_FILTER, filter_v_c);
362 : }
363 : }
364 0 : dpp->filter_h_c = filter_h_c;
365 0 : dpp->filter_v_c = filter_v_c;
366 :
367 0 : coef_ram_current = get_reg_field_value_ex(
368 0 : scl_mode, dpp->tf_mask->SCL_COEF_RAM_SELECT_CURRENT,
369 0 : dpp->tf_shift->SCL_COEF_RAM_SELECT_CURRENT);
370 :
371 : /* Swap coefficient RAM and set chroma coefficient mode */
372 0 : REG_SET_2(SCL_MODE, scl_mode,
373 : SCL_COEF_RAM_SELECT, !coef_ram_current,
374 : SCL_CHROMA_COEF_MODE, chroma_coef_mode);
375 : }
376 : }
377 0 : }
378 :
379 0 : static int dpp1_dscl_get_lb_depth_bpc(enum lb_pixel_depth depth)
380 : {
381 0 : if (depth == LB_PIXEL_DEPTH_30BPP)
382 : return 10;
383 0 : else if (depth == LB_PIXEL_DEPTH_24BPP)
384 : return 8;
385 0 : else if (depth == LB_PIXEL_DEPTH_18BPP)
386 : return 6;
387 0 : else if (depth == LB_PIXEL_DEPTH_36BPP)
388 : return 12;
389 : else {
390 0 : BREAK_TO_DEBUGGER();
391 0 : return -1; /* Unsupported */
392 : }
393 : }
394 :
395 0 : void dpp1_dscl_calc_lb_num_partitions(
396 : const struct scaler_data *scl_data,
397 : enum lb_memory_config lb_config,
398 : int *num_part_y,
399 : int *num_part_c)
400 : {
401 : int lb_memory_size, lb_memory_size_c, lb_memory_size_a, num_partitions_a,
402 : lb_bpc, memory_line_size_y, memory_line_size_c, memory_line_size_a;
403 :
404 0 : int line_size = scl_data->viewport.width < scl_data->recout.width ?
405 0 : scl_data->viewport.width : scl_data->recout.width;
406 0 : int line_size_c = scl_data->viewport_c.width < scl_data->recout.width ?
407 0 : scl_data->viewport_c.width : scl_data->recout.width;
408 :
409 0 : if (line_size == 0)
410 0 : line_size = 1;
411 :
412 0 : if (line_size_c == 0)
413 0 : line_size_c = 1;
414 :
415 :
416 0 : lb_bpc = dpp1_dscl_get_lb_depth_bpc(scl_data->lb_params.depth);
417 0 : memory_line_size_y = (line_size * lb_bpc + 71) / 72; /* +71 to ceil */
418 0 : memory_line_size_c = (line_size_c * lb_bpc + 71) / 72; /* +71 to ceil */
419 0 : memory_line_size_a = (line_size + 5) / 6; /* +5 to ceil */
420 :
421 0 : if (lb_config == LB_MEMORY_CONFIG_1) {
422 : lb_memory_size = 816;
423 : lb_memory_size_c = 816;
424 : lb_memory_size_a = 984;
425 0 : } else if (lb_config == LB_MEMORY_CONFIG_2) {
426 : lb_memory_size = 1088;
427 : lb_memory_size_c = 1088;
428 : lb_memory_size_a = 1312;
429 0 : } else if (lb_config == LB_MEMORY_CONFIG_3) {
430 : /* 420 mode: using 3rd mem from Y, Cr and Cb */
431 : lb_memory_size = 816 + 1088 + 848 + 848 + 848;
432 : lb_memory_size_c = 816 + 1088;
433 : lb_memory_size_a = 984 + 1312 + 456;
434 : } else {
435 0 : lb_memory_size = 816 + 1088 + 848;
436 0 : lb_memory_size_c = 816 + 1088 + 848;
437 0 : lb_memory_size_a = 984 + 1312 + 456;
438 : }
439 0 : *num_part_y = lb_memory_size / memory_line_size_y;
440 0 : *num_part_c = lb_memory_size_c / memory_line_size_c;
441 0 : num_partitions_a = lb_memory_size_a / memory_line_size_a;
442 :
443 0 : if (scl_data->lb_params.alpha_en
444 0 : && (num_partitions_a < *num_part_y))
445 0 : *num_part_y = num_partitions_a;
446 :
447 0 : if (*num_part_y > 64)
448 0 : *num_part_y = 64;
449 0 : if (*num_part_c > 64)
450 0 : *num_part_c = 64;
451 :
452 0 : }
453 :
454 0 : bool dpp1_dscl_is_lb_conf_valid(int ceil_vratio, int num_partitions, int vtaps)
455 : {
456 0 : if (ceil_vratio > 2)
457 0 : return vtaps <= (num_partitions - ceil_vratio + 2);
458 : else
459 0 : return vtaps <= num_partitions;
460 : }
461 :
462 : /*find first match configuration which meets the min required lb size*/
463 0 : static enum lb_memory_config dpp1_dscl_find_lb_memory_config(struct dcn10_dpp *dpp,
464 : const struct scaler_data *scl_data)
465 : {
466 : int num_part_y, num_part_c;
467 0 : int vtaps = scl_data->taps.v_taps;
468 0 : int vtaps_c = scl_data->taps.v_taps_c;
469 0 : int ceil_vratio = dc_fixpt_ceil(scl_data->ratios.vert);
470 0 : int ceil_vratio_c = dc_fixpt_ceil(scl_data->ratios.vert_c);
471 :
472 0 : if (dpp->base.ctx->dc->debug.use_max_lb) {
473 0 : if (scl_data->format == PIXEL_FORMAT_420BPP8
474 0 : || scl_data->format == PIXEL_FORMAT_420BPP10)
475 : return LB_MEMORY_CONFIG_3;
476 : return LB_MEMORY_CONFIG_0;
477 : }
478 :
479 0 : dpp->base.caps->dscl_calc_lb_num_partitions(
480 : scl_data, LB_MEMORY_CONFIG_1, &num_part_y, &num_part_c);
481 :
482 0 : if (dpp1_dscl_is_lb_conf_valid(ceil_vratio, num_part_y, vtaps)
483 0 : && dpp1_dscl_is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c))
484 : return LB_MEMORY_CONFIG_1;
485 :
486 0 : dpp->base.caps->dscl_calc_lb_num_partitions(
487 : scl_data, LB_MEMORY_CONFIG_2, &num_part_y, &num_part_c);
488 :
489 0 : if (dpp1_dscl_is_lb_conf_valid(ceil_vratio, num_part_y, vtaps)
490 0 : && dpp1_dscl_is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c))
491 : return LB_MEMORY_CONFIG_2;
492 :
493 0 : if (scl_data->format == PIXEL_FORMAT_420BPP8
494 0 : || scl_data->format == PIXEL_FORMAT_420BPP10) {
495 0 : dpp->base.caps->dscl_calc_lb_num_partitions(
496 : scl_data, LB_MEMORY_CONFIG_3, &num_part_y, &num_part_c);
497 :
498 0 : if (dpp1_dscl_is_lb_conf_valid(ceil_vratio, num_part_y, vtaps)
499 0 : && dpp1_dscl_is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c))
500 : return LB_MEMORY_CONFIG_3;
501 : }
502 :
503 0 : dpp->base.caps->dscl_calc_lb_num_partitions(
504 : scl_data, LB_MEMORY_CONFIG_0, &num_part_y, &num_part_c);
505 :
506 : /*Ensure we can support the requested number of vtaps*/
507 0 : ASSERT(dpp1_dscl_is_lb_conf_valid(ceil_vratio, num_part_y, vtaps)
508 : && dpp1_dscl_is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c));
509 :
510 : return LB_MEMORY_CONFIG_0;
511 : }
512 :
513 :
514 0 : static void dpp1_dscl_set_manual_ratio_init(
515 : struct dcn10_dpp *dpp, const struct scaler_data *data)
516 : {
517 0 : uint32_t init_frac = 0;
518 0 : uint32_t init_int = 0;
519 :
520 0 : REG_SET(SCL_HORZ_FILTER_SCALE_RATIO, 0,
521 : SCL_H_SCALE_RATIO, dc_fixpt_u3d19(data->ratios.horz) << 5);
522 :
523 0 : REG_SET(SCL_VERT_FILTER_SCALE_RATIO, 0,
524 : SCL_V_SCALE_RATIO, dc_fixpt_u3d19(data->ratios.vert) << 5);
525 :
526 0 : REG_SET(SCL_HORZ_FILTER_SCALE_RATIO_C, 0,
527 : SCL_H_SCALE_RATIO_C, dc_fixpt_u3d19(data->ratios.horz_c) << 5);
528 :
529 0 : REG_SET(SCL_VERT_FILTER_SCALE_RATIO_C, 0,
530 : SCL_V_SCALE_RATIO_C, dc_fixpt_u3d19(data->ratios.vert_c) << 5);
531 :
532 : /*
533 : * 0.24 format for fraction, first five bits zeroed
534 : */
535 0 : init_frac = dc_fixpt_u0d19(data->inits.h) << 5;
536 0 : init_int = dc_fixpt_floor(data->inits.h);
537 0 : REG_SET_2(SCL_HORZ_FILTER_INIT, 0,
538 : SCL_H_INIT_FRAC, init_frac,
539 : SCL_H_INIT_INT, init_int);
540 :
541 0 : init_frac = dc_fixpt_u0d19(data->inits.h_c) << 5;
542 0 : init_int = dc_fixpt_floor(data->inits.h_c);
543 0 : REG_SET_2(SCL_HORZ_FILTER_INIT_C, 0,
544 : SCL_H_INIT_FRAC_C, init_frac,
545 : SCL_H_INIT_INT_C, init_int);
546 :
547 0 : init_frac = dc_fixpt_u0d19(data->inits.v) << 5;
548 0 : init_int = dc_fixpt_floor(data->inits.v);
549 0 : REG_SET_2(SCL_VERT_FILTER_INIT, 0,
550 : SCL_V_INIT_FRAC, init_frac,
551 : SCL_V_INIT_INT, init_int);
552 :
553 0 : if (REG(SCL_VERT_FILTER_INIT_BOT)) {
554 0 : struct fixed31_32 bot = dc_fixpt_add(data->inits.v, data->ratios.vert);
555 :
556 0 : init_frac = dc_fixpt_u0d19(bot) << 5;
557 0 : init_int = dc_fixpt_floor(bot);
558 0 : REG_SET_2(SCL_VERT_FILTER_INIT_BOT, 0,
559 : SCL_V_INIT_FRAC_BOT, init_frac,
560 : SCL_V_INIT_INT_BOT, init_int);
561 : }
562 :
563 0 : init_frac = dc_fixpt_u0d19(data->inits.v_c) << 5;
564 0 : init_int = dc_fixpt_floor(data->inits.v_c);
565 0 : REG_SET_2(SCL_VERT_FILTER_INIT_C, 0,
566 : SCL_V_INIT_FRAC_C, init_frac,
567 : SCL_V_INIT_INT_C, init_int);
568 :
569 0 : if (REG(SCL_VERT_FILTER_INIT_BOT_C)) {
570 0 : struct fixed31_32 bot = dc_fixpt_add(data->inits.v_c, data->ratios.vert_c);
571 :
572 0 : init_frac = dc_fixpt_u0d19(bot) << 5;
573 0 : init_int = dc_fixpt_floor(bot);
574 0 : REG_SET_2(SCL_VERT_FILTER_INIT_BOT_C, 0,
575 : SCL_V_INIT_FRAC_BOT_C, init_frac,
576 : SCL_V_INIT_INT_BOT_C, init_int);
577 : }
578 0 : }
579 :
580 : /**
581 : * dpp1_dscl_set_recout - Set the first pixel of RECOUT in the OTG active area
582 : *
583 : * @dpp: DPP data struct
584 : * @recount: Rectangle information
585 : *
586 : * This function sets the MPC RECOUT_START and RECOUT_SIZE registers based on
587 : * the values specified in the recount parameter.
588 : *
589 : * Note: This function only have effect if AutoCal is disabled.
590 : */
591 0 : static void dpp1_dscl_set_recout(struct dcn10_dpp *dpp,
592 : const struct rect *recout)
593 : {
594 0 : int visual_confirm_on = 0;
595 0 : unsigned short visual_confirm_rect_height = VISUAL_CONFIRM_RECT_HEIGHT_DEFAULT;
596 :
597 0 : if (dpp->base.ctx->dc->debug.visual_confirm != VISUAL_CONFIRM_DISABLE)
598 0 : visual_confirm_on = 1;
599 :
600 : /* Check bounds to ensure the VC bar height was set to a sane value */
601 0 : if ((dpp->base.ctx->dc->debug.visual_confirm_rect_height >= VISUAL_CONFIRM_RECT_HEIGHT_MIN) &&
602 : (dpp->base.ctx->dc->debug.visual_confirm_rect_height <= VISUAL_CONFIRM_RECT_HEIGHT_MAX)) {
603 0 : visual_confirm_rect_height = dpp->base.ctx->dc->debug.visual_confirm_rect_height;
604 : }
605 :
606 0 : REG_SET_2(RECOUT_START, 0,
607 : /* First pixel of RECOUT in the active OTG area */
608 : RECOUT_START_X, recout->x,
609 : /* First line of RECOUT in the active OTG area */
610 : RECOUT_START_Y, recout->y);
611 :
612 0 : REG_SET_2(RECOUT_SIZE, 0,
613 : /* Number of RECOUT horizontal pixels */
614 : RECOUT_WIDTH, recout->width,
615 : /* Number of RECOUT vertical lines */
616 : RECOUT_HEIGHT, recout->height
617 : - visual_confirm_on * 2 * (dpp->base.inst + visual_confirm_rect_height));
618 0 : }
619 :
620 : /**
621 : * dpp1_dscl_set_scaler_manual_scale - Manually program scaler and line buffer
622 : *
623 : * @dpp_base: High level DPP struct
624 : * @scl_data: scalaer_data info
625 : *
626 : * This is the primary function to program scaler and line buffer in manual
627 : * scaling mode. To execute the required operations for manual scale, we need
628 : * to disable AutoCal first.
629 : */
630 0 : void dpp1_dscl_set_scaler_manual_scale(struct dpp *dpp_base,
631 : const struct scaler_data *scl_data)
632 : {
633 : enum lb_memory_config lb_config;
634 0 : struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base);
635 0 : enum dscl_mode_sel dscl_mode = dpp1_dscl_get_dscl_mode(
636 0 : dpp_base, scl_data, dpp_base->ctx->dc->debug.always_scale);
637 0 : bool ycbcr = scl_data->format >= PIXEL_FORMAT_VIDEO_BEGIN
638 0 : && scl_data->format <= PIXEL_FORMAT_VIDEO_END;
639 :
640 0 : if (memcmp(&dpp->scl_data, scl_data, sizeof(*scl_data)) == 0)
641 : return;
642 :
643 0 : PERF_TRACE();
644 :
645 0 : dpp->scl_data = *scl_data;
646 :
647 0 : if (dpp_base->ctx->dc->debug.enable_mem_low_power.bits.dscl) {
648 0 : if (dscl_mode != DSCL_MODE_DSCL_BYPASS)
649 0 : dpp1_power_on_dscl(dpp_base, true);
650 : }
651 :
652 : /* Autocal off */
653 0 : REG_SET_3(DSCL_AUTOCAL, 0,
654 : AUTOCAL_MODE, AUTOCAL_MODE_OFF,
655 : AUTOCAL_NUM_PIPE, 0,
656 : AUTOCAL_PIPE_ID, 0);
657 :
658 : /* Recout */
659 0 : dpp1_dscl_set_recout(dpp, &scl_data->recout);
660 :
661 : /* MPC Size */
662 0 : REG_SET_2(MPC_SIZE, 0,
663 : /* Number of horizontal pixels of MPC */
664 : MPC_WIDTH, scl_data->h_active,
665 : /* Number of vertical lines of MPC */
666 : MPC_HEIGHT, scl_data->v_active);
667 :
668 : /* SCL mode */
669 0 : REG_UPDATE(SCL_MODE, DSCL_MODE, dscl_mode);
670 :
671 0 : if (dscl_mode == DSCL_MODE_DSCL_BYPASS) {
672 0 : if (dpp_base->ctx->dc->debug.enable_mem_low_power.bits.dscl)
673 0 : dpp1_power_on_dscl(dpp_base, false);
674 : return;
675 : }
676 :
677 : /* LB */
678 0 : lb_config = dpp1_dscl_find_lb_memory_config(dpp, scl_data);
679 0 : dpp1_dscl_set_lb(dpp, &scl_data->lb_params, lb_config);
680 :
681 0 : if (dscl_mode == DSCL_MODE_SCALING_444_BYPASS)
682 : return;
683 :
684 : /* Black offsets */
685 0 : if (REG(SCL_BLACK_OFFSET)) {
686 0 : if (ycbcr)
687 0 : REG_SET_2(SCL_BLACK_OFFSET, 0,
688 : SCL_BLACK_OFFSET_RGB_Y, BLACK_OFFSET_RGB_Y,
689 : SCL_BLACK_OFFSET_CBCR, BLACK_OFFSET_CBCR);
690 : else
691 :
692 0 : REG_SET_2(SCL_BLACK_OFFSET, 0,
693 : SCL_BLACK_OFFSET_RGB_Y, BLACK_OFFSET_RGB_Y,
694 : SCL_BLACK_OFFSET_CBCR, BLACK_OFFSET_RGB_Y);
695 : }
696 :
697 : /* Manually calculate scale ratio and init values */
698 0 : dpp1_dscl_set_manual_ratio_init(dpp, scl_data);
699 :
700 : /* HTaps/VTaps */
701 0 : REG_SET_4(SCL_TAP_CONTROL, 0,
702 : SCL_V_NUM_TAPS, scl_data->taps.v_taps - 1,
703 : SCL_H_NUM_TAPS, scl_data->taps.h_taps - 1,
704 : SCL_V_NUM_TAPS_C, scl_data->taps.v_taps_c - 1,
705 : SCL_H_NUM_TAPS_C, scl_data->taps.h_taps_c - 1);
706 :
707 0 : dpp1_dscl_set_scl_filter(dpp, scl_data, ycbcr);
708 0 : PERF_TRACE();
709 : }
|