Line data Source code
1 : /*
2 : * Copyright 2012-15 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 "dce110_transform_v.h"
27 : #include "dm_services.h"
28 : #include "dc.h"
29 : #include "dce/dce_11_0_d.h"
30 : #include "dce/dce_11_0_sh_mask.h"
31 :
32 : #define SCLV_PHASES 64
33 : #define DC_LOGGER \
34 : xfm->ctx->logger
35 :
36 : struct sclv_ratios_inits {
37 : uint32_t h_int_scale_ratio_luma;
38 : uint32_t h_int_scale_ratio_chroma;
39 : uint32_t v_int_scale_ratio_luma;
40 : uint32_t v_int_scale_ratio_chroma;
41 : struct init_int_and_frac h_init_luma;
42 : struct init_int_and_frac h_init_chroma;
43 : struct init_int_and_frac v_init_luma;
44 : struct init_int_and_frac v_init_chroma;
45 : };
46 :
47 0 : static void calculate_viewport(
48 : const struct scaler_data *scl_data,
49 : struct rect *luma_viewport,
50 : struct rect *chroma_viewport)
51 : {
52 : /*Do not set chroma vp for rgb444 pixel format*/
53 0 : luma_viewport->x = scl_data->viewport.x - scl_data->viewport.x % 2;
54 0 : luma_viewport->y = scl_data->viewport.y - scl_data->viewport.y % 2;
55 0 : luma_viewport->width =
56 0 : scl_data->viewport.width - scl_data->viewport.width % 2;
57 0 : luma_viewport->height =
58 0 : scl_data->viewport.height - scl_data->viewport.height % 2;
59 0 : chroma_viewport->x = luma_viewport->x;
60 0 : chroma_viewport->y = luma_viewport->y;
61 0 : chroma_viewport->height = luma_viewport->height;
62 0 : chroma_viewport->width = luma_viewport->width;
63 :
64 0 : if (scl_data->format == PIXEL_FORMAT_420BPP8) {
65 0 : luma_viewport->height += luma_viewport->height % 2;
66 0 : luma_viewport->width += luma_viewport->width % 2;
67 : /*for 420 video chroma is 1/4 the area of luma, scaled
68 : *vertically and horizontally
69 : */
70 0 : chroma_viewport->x = luma_viewport->x / 2;
71 0 : chroma_viewport->y = luma_viewport->y / 2;
72 0 : chroma_viewport->height = luma_viewport->height / 2;
73 0 : chroma_viewport->width = luma_viewport->width / 2;
74 : }
75 0 : }
76 :
77 0 : static void program_viewport(
78 : struct dce_transform *xfm_dce,
79 : struct rect *luma_view_port,
80 : struct rect *chroma_view_port)
81 : {
82 0 : struct dc_context *ctx = xfm_dce->base.ctx;
83 0 : uint32_t value = 0;
84 0 : uint32_t addr = 0;
85 :
86 0 : if (luma_view_port->width != 0 && luma_view_port->height != 0) {
87 0 : addr = mmSCLV_VIEWPORT_START;
88 0 : value = 0;
89 0 : set_reg_field_value(
90 : value,
91 : luma_view_port->x,
92 : SCLV_VIEWPORT_START,
93 : VIEWPORT_X_START);
94 0 : set_reg_field_value(
95 : value,
96 : luma_view_port->y,
97 : SCLV_VIEWPORT_START,
98 : VIEWPORT_Y_START);
99 0 : dm_write_reg(ctx, addr, value);
100 :
101 0 : addr = mmSCLV_VIEWPORT_SIZE;
102 0 : value = 0;
103 0 : set_reg_field_value(
104 : value,
105 : luma_view_port->height,
106 : SCLV_VIEWPORT_SIZE,
107 : VIEWPORT_HEIGHT);
108 0 : set_reg_field_value(
109 : value,
110 : luma_view_port->width,
111 : SCLV_VIEWPORT_SIZE,
112 : VIEWPORT_WIDTH);
113 0 : dm_write_reg(ctx, addr, value);
114 : }
115 :
116 0 : if (chroma_view_port->width != 0 && chroma_view_port->height != 0) {
117 0 : addr = mmSCLV_VIEWPORT_START_C;
118 0 : value = 0;
119 0 : set_reg_field_value(
120 : value,
121 : chroma_view_port->x,
122 : SCLV_VIEWPORT_START_C,
123 : VIEWPORT_X_START_C);
124 0 : set_reg_field_value(
125 : value,
126 : chroma_view_port->y,
127 : SCLV_VIEWPORT_START_C,
128 : VIEWPORT_Y_START_C);
129 0 : dm_write_reg(ctx, addr, value);
130 :
131 0 : addr = mmSCLV_VIEWPORT_SIZE_C;
132 0 : value = 0;
133 0 : set_reg_field_value(
134 : value,
135 : chroma_view_port->height,
136 : SCLV_VIEWPORT_SIZE_C,
137 : VIEWPORT_HEIGHT_C);
138 0 : set_reg_field_value(
139 : value,
140 : chroma_view_port->width,
141 : SCLV_VIEWPORT_SIZE_C,
142 : VIEWPORT_WIDTH_C);
143 0 : dm_write_reg(ctx, addr, value);
144 : }
145 0 : }
146 :
147 : /*
148 : * Function:
149 : * void setup_scaling_configuration
150 : *
151 : * Purpose: setup scaling mode : bypass, RGb, YCbCr and nummber of taps
152 : * Input: data
153 : *
154 : * Output:
155 : * void
156 : */
157 0 : static bool setup_scaling_configuration(
158 : struct dce_transform *xfm_dce,
159 : const struct scaler_data *data)
160 : {
161 0 : bool is_scaling_needed = false;
162 0 : struct dc_context *ctx = xfm_dce->base.ctx;
163 0 : uint32_t value = 0;
164 :
165 0 : set_reg_field_value(value, data->taps.h_taps - 1,
166 : SCLV_TAP_CONTROL, SCL_H_NUM_OF_TAPS);
167 0 : set_reg_field_value(value, data->taps.v_taps - 1,
168 : SCLV_TAP_CONTROL, SCL_V_NUM_OF_TAPS);
169 0 : set_reg_field_value(value, data->taps.h_taps_c - 1,
170 : SCLV_TAP_CONTROL, SCL_H_NUM_OF_TAPS_C);
171 0 : set_reg_field_value(value, data->taps.v_taps_c - 1,
172 : SCLV_TAP_CONTROL, SCL_V_NUM_OF_TAPS_C);
173 0 : dm_write_reg(ctx, mmSCLV_TAP_CONTROL, value);
174 :
175 0 : value = 0;
176 0 : if (data->taps.h_taps + data->taps.v_taps > 2) {
177 : set_reg_field_value(value, 1, SCLV_MODE, SCL_MODE);
178 : set_reg_field_value(value, 1, SCLV_MODE, SCL_PSCL_EN);
179 : is_scaling_needed = true;
180 : } else {
181 : set_reg_field_value(value, 0, SCLV_MODE, SCL_MODE);
182 : set_reg_field_value(value, 0, SCLV_MODE, SCL_PSCL_EN);
183 : }
184 :
185 0 : if (data->taps.h_taps_c + data->taps.v_taps_c > 2) {
186 0 : set_reg_field_value(value, 1, SCLV_MODE, SCL_MODE_C);
187 0 : set_reg_field_value(value, 1, SCLV_MODE, SCL_PSCL_EN_C);
188 0 : is_scaling_needed = true;
189 0 : } else if (data->format != PIXEL_FORMAT_420BPP8) {
190 0 : set_reg_field_value(
191 : value,
192 : get_reg_field_value(value, SCLV_MODE, SCL_MODE),
193 : SCLV_MODE,
194 : SCL_MODE_C);
195 0 : set_reg_field_value(
196 : value,
197 : get_reg_field_value(value, SCLV_MODE, SCL_PSCL_EN),
198 : SCLV_MODE,
199 : SCL_PSCL_EN_C);
200 : } else {
201 : set_reg_field_value(value, 0, SCLV_MODE, SCL_MODE_C);
202 : set_reg_field_value(value, 0, SCLV_MODE, SCL_PSCL_EN_C);
203 : }
204 0 : dm_write_reg(ctx, mmSCLV_MODE, value);
205 :
206 0 : value = 0;
207 : /*
208 : * 0 - Replaced out of bound pixels with black pixel
209 : * (or any other required color)
210 : * 1 - Replaced out of bound pixels with the edge pixel
211 : */
212 0 : set_reg_field_value(value, 1, SCLV_CONTROL, SCL_BOUNDARY_MODE);
213 0 : dm_write_reg(ctx, mmSCLV_CONTROL, value);
214 :
215 0 : return is_scaling_needed;
216 : }
217 :
218 : /*
219 : * Function:
220 : * void program_overscan
221 : *
222 : * Purpose: Programs overscan border
223 : * Input: overscan
224 : *
225 : * Output: void
226 : */
227 0 : static void program_overscan(
228 : struct dce_transform *xfm_dce,
229 : const struct scaler_data *data)
230 : {
231 0 : uint32_t overscan_left_right = 0;
232 0 : uint32_t overscan_top_bottom = 0;
233 :
234 0 : int overscan_right = data->h_active - data->recout.x - data->recout.width;
235 0 : int overscan_bottom = data->v_active - data->recout.y - data->recout.height;
236 :
237 0 : if (xfm_dce->base.ctx->dc->debug.visual_confirm != VISUAL_CONFIRM_DISABLE) {
238 0 : overscan_bottom += 2;
239 0 : overscan_right += 2;
240 : }
241 :
242 0 : if (overscan_right < 0) {
243 0 : BREAK_TO_DEBUGGER();
244 0 : overscan_right = 0;
245 : }
246 0 : if (overscan_bottom < 0) {
247 0 : BREAK_TO_DEBUGGER();
248 0 : overscan_bottom = 0;
249 : }
250 :
251 0 : set_reg_field_value(overscan_left_right, data->recout.x,
252 : EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_LEFT);
253 :
254 0 : set_reg_field_value(overscan_left_right, overscan_right,
255 : EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_RIGHT);
256 :
257 0 : set_reg_field_value(overscan_top_bottom, data->recout.y,
258 : EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_TOP);
259 :
260 0 : set_reg_field_value(overscan_top_bottom, overscan_bottom,
261 : EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_BOTTOM);
262 :
263 0 : dm_write_reg(xfm_dce->base.ctx,
264 : mmSCLV_EXT_OVERSCAN_LEFT_RIGHT,
265 : overscan_left_right);
266 :
267 0 : dm_write_reg(xfm_dce->base.ctx,
268 : mmSCLV_EXT_OVERSCAN_TOP_BOTTOM,
269 : overscan_top_bottom);
270 0 : }
271 :
272 0 : static void set_coeff_update_complete(
273 : struct dce_transform *xfm_dce)
274 : {
275 : uint32_t value;
276 :
277 0 : value = dm_read_reg(xfm_dce->base.ctx, mmSCLV_UPDATE);
278 0 : set_reg_field_value(value, 1, SCLV_UPDATE, SCL_COEF_UPDATE_COMPLETE);
279 0 : dm_write_reg(xfm_dce->base.ctx, mmSCLV_UPDATE, value);
280 0 : }
281 :
282 0 : static void program_multi_taps_filter(
283 : struct dce_transform *xfm_dce,
284 : int taps,
285 : const uint16_t *coeffs,
286 : enum ram_filter_type filter_type)
287 : {
288 0 : struct dc_context *ctx = xfm_dce->base.ctx;
289 : int i, phase, pair;
290 0 : int array_idx = 0;
291 0 : int taps_pairs = (taps + 1) / 2;
292 0 : int phases_to_program = SCLV_PHASES / 2 + 1;
293 :
294 0 : uint32_t select = 0;
295 : uint32_t power_ctl, power_ctl_off;
296 :
297 0 : if (!coeffs)
298 : return;
299 :
300 : /*We need to disable power gating on coeff memory to do programming*/
301 0 : power_ctl = dm_read_reg(ctx, mmDCFEV_MEM_PWR_CTRL);
302 0 : power_ctl_off = power_ctl;
303 0 : set_reg_field_value(power_ctl_off, 1, DCFEV_MEM_PWR_CTRL, SCLV_COEFF_MEM_PWR_DIS);
304 0 : dm_write_reg(ctx, mmDCFEV_MEM_PWR_CTRL, power_ctl_off);
305 :
306 : /*Wait to disable gating:*/
307 0 : for (i = 0; i < 10; i++) {
308 0 : if (get_reg_field_value(
309 : dm_read_reg(ctx, mmDCFEV_MEM_PWR_STATUS),
310 : DCFEV_MEM_PWR_STATUS,
311 : SCLV_COEFF_MEM_PWR_STATE) == 0)
312 : break;
313 :
314 0 : udelay(1);
315 : }
316 :
317 0 : set_reg_field_value(select, filter_type, SCLV_COEF_RAM_SELECT, SCL_C_RAM_FILTER_TYPE);
318 :
319 0 : for (phase = 0; phase < phases_to_program; phase++) {
320 : /*we always program N/2 + 1 phases, total phases N, but N/2-1 are just mirror
321 : phase 0 is unique and phase N/2 is unique if N is even*/
322 0 : set_reg_field_value(select, phase, SCLV_COEF_RAM_SELECT, SCL_C_RAM_PHASE);
323 0 : for (pair = 0; pair < taps_pairs; pair++) {
324 0 : uint32_t data = 0;
325 :
326 0 : set_reg_field_value(select, pair,
327 : SCLV_COEF_RAM_SELECT, SCL_C_RAM_TAP_PAIR_IDX);
328 :
329 0 : dm_write_reg(ctx, mmSCLV_COEF_RAM_SELECT, select);
330 :
331 0 : set_reg_field_value(
332 : data, 1,
333 : SCLV_COEF_RAM_TAP_DATA,
334 : SCL_C_RAM_EVEN_TAP_COEF_EN);
335 0 : set_reg_field_value(
336 : data, coeffs[array_idx],
337 : SCLV_COEF_RAM_TAP_DATA,
338 : SCL_C_RAM_EVEN_TAP_COEF);
339 :
340 0 : if (taps % 2 && pair == taps_pairs - 1) {
341 0 : set_reg_field_value(
342 : data, 0,
343 : SCLV_COEF_RAM_TAP_DATA,
344 : SCL_C_RAM_ODD_TAP_COEF_EN);
345 0 : array_idx++;
346 : } else {
347 0 : set_reg_field_value(
348 : data, 1,
349 : SCLV_COEF_RAM_TAP_DATA,
350 : SCL_C_RAM_ODD_TAP_COEF_EN);
351 0 : set_reg_field_value(
352 : data, coeffs[array_idx + 1],
353 : SCLV_COEF_RAM_TAP_DATA,
354 : SCL_C_RAM_ODD_TAP_COEF);
355 :
356 0 : array_idx += 2;
357 : }
358 :
359 0 : dm_write_reg(ctx, mmSCLV_COEF_RAM_TAP_DATA, data);
360 : }
361 : }
362 :
363 : /*We need to restore power gating on coeff memory to initial state*/
364 0 : dm_write_reg(ctx, mmDCFEV_MEM_PWR_CTRL, power_ctl);
365 : }
366 :
367 0 : static void calculate_inits(
368 : struct dce_transform *xfm_dce,
369 : const struct scaler_data *data,
370 : struct sclv_ratios_inits *inits,
371 : struct rect *luma_viewport,
372 : struct rect *chroma_viewport)
373 : {
374 0 : inits->h_int_scale_ratio_luma =
375 0 : dc_fixpt_u2d19(data->ratios.horz) << 5;
376 0 : inits->v_int_scale_ratio_luma =
377 0 : dc_fixpt_u2d19(data->ratios.vert) << 5;
378 0 : inits->h_int_scale_ratio_chroma =
379 0 : dc_fixpt_u2d19(data->ratios.horz_c) << 5;
380 0 : inits->v_int_scale_ratio_chroma =
381 0 : dc_fixpt_u2d19(data->ratios.vert_c) << 5;
382 :
383 0 : inits->h_init_luma.integer = 1;
384 0 : inits->v_init_luma.integer = 1;
385 0 : inits->h_init_chroma.integer = 1;
386 0 : inits->v_init_chroma.integer = 1;
387 0 : }
388 :
389 0 : static void program_scl_ratios_inits(
390 : struct dce_transform *xfm_dce,
391 : struct sclv_ratios_inits *inits)
392 : {
393 0 : struct dc_context *ctx = xfm_dce->base.ctx;
394 0 : uint32_t addr = mmSCLV_HORZ_FILTER_SCALE_RATIO;
395 0 : uint32_t value = 0;
396 :
397 0 : set_reg_field_value(
398 : value,
399 : inits->h_int_scale_ratio_luma,
400 : SCLV_HORZ_FILTER_SCALE_RATIO,
401 : SCL_H_SCALE_RATIO);
402 0 : dm_write_reg(ctx, addr, value);
403 :
404 0 : addr = mmSCLV_VERT_FILTER_SCALE_RATIO;
405 0 : value = 0;
406 0 : set_reg_field_value(
407 : value,
408 : inits->v_int_scale_ratio_luma,
409 : SCLV_VERT_FILTER_SCALE_RATIO,
410 : SCL_V_SCALE_RATIO);
411 0 : dm_write_reg(ctx, addr, value);
412 :
413 0 : addr = mmSCLV_HORZ_FILTER_SCALE_RATIO_C;
414 0 : value = 0;
415 0 : set_reg_field_value(
416 : value,
417 : inits->h_int_scale_ratio_chroma,
418 : SCLV_HORZ_FILTER_SCALE_RATIO_C,
419 : SCL_H_SCALE_RATIO_C);
420 0 : dm_write_reg(ctx, addr, value);
421 :
422 0 : addr = mmSCLV_VERT_FILTER_SCALE_RATIO_C;
423 0 : value = 0;
424 0 : set_reg_field_value(
425 : value,
426 : inits->v_int_scale_ratio_chroma,
427 : SCLV_VERT_FILTER_SCALE_RATIO_C,
428 : SCL_V_SCALE_RATIO_C);
429 0 : dm_write_reg(ctx, addr, value);
430 :
431 0 : addr = mmSCLV_HORZ_FILTER_INIT;
432 0 : value = 0;
433 0 : set_reg_field_value(
434 : value,
435 : inits->h_init_luma.fraction,
436 : SCLV_HORZ_FILTER_INIT,
437 : SCL_H_INIT_FRAC);
438 0 : set_reg_field_value(
439 : value,
440 : inits->h_init_luma.integer,
441 : SCLV_HORZ_FILTER_INIT,
442 : SCL_H_INIT_INT);
443 0 : dm_write_reg(ctx, addr, value);
444 :
445 0 : addr = mmSCLV_VERT_FILTER_INIT;
446 0 : value = 0;
447 0 : set_reg_field_value(
448 : value,
449 : inits->v_init_luma.fraction,
450 : SCLV_VERT_FILTER_INIT,
451 : SCL_V_INIT_FRAC);
452 0 : set_reg_field_value(
453 : value,
454 : inits->v_init_luma.integer,
455 : SCLV_VERT_FILTER_INIT,
456 : SCL_V_INIT_INT);
457 0 : dm_write_reg(ctx, addr, value);
458 :
459 0 : addr = mmSCLV_HORZ_FILTER_INIT_C;
460 0 : value = 0;
461 0 : set_reg_field_value(
462 : value,
463 : inits->h_init_chroma.fraction,
464 : SCLV_HORZ_FILTER_INIT_C,
465 : SCL_H_INIT_FRAC_C);
466 0 : set_reg_field_value(
467 : value,
468 : inits->h_init_chroma.integer,
469 : SCLV_HORZ_FILTER_INIT_C,
470 : SCL_H_INIT_INT_C);
471 0 : dm_write_reg(ctx, addr, value);
472 :
473 0 : addr = mmSCLV_VERT_FILTER_INIT_C;
474 0 : value = 0;
475 0 : set_reg_field_value(
476 : value,
477 : inits->v_init_chroma.fraction,
478 : SCLV_VERT_FILTER_INIT_C,
479 : SCL_V_INIT_FRAC_C);
480 0 : set_reg_field_value(
481 : value,
482 : inits->v_init_chroma.integer,
483 : SCLV_VERT_FILTER_INIT_C,
484 : SCL_V_INIT_INT_C);
485 0 : dm_write_reg(ctx, addr, value);
486 0 : }
487 :
488 0 : static const uint16_t *get_filter_coeffs_64p(int taps, struct fixed31_32 ratio)
489 : {
490 0 : if (taps == 4)
491 0 : return get_filter_4tap_64p(ratio);
492 0 : else if (taps == 2)
493 0 : return get_filter_2tap_64p();
494 0 : else if (taps == 1)
495 : return NULL;
496 : else {
497 : /* should never happen, bug */
498 0 : BREAK_TO_DEBUGGER();
499 0 : return NULL;
500 : }
501 : }
502 :
503 0 : static bool dce110_xfmv_power_up_line_buffer(struct transform *xfm)
504 : {
505 0 : struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
506 : uint32_t value;
507 :
508 0 : value = dm_read_reg(xfm_dce->base.ctx, mmLBV_MEMORY_CTRL);
509 :
510 : /*Use all three pieces of memory always*/
511 0 : set_reg_field_value(value, 0, LBV_MEMORY_CTRL, LB_MEMORY_CONFIG);
512 : /*hard coded number DCE11 1712(0x6B0) Partitions: 720/960/1712*/
513 0 : set_reg_field_value(value, xfm_dce->lb_memory_size, LBV_MEMORY_CTRL,
514 : LB_MEMORY_SIZE);
515 :
516 0 : dm_write_reg(xfm_dce->base.ctx, mmLBV_MEMORY_CTRL, value);
517 :
518 0 : return true;
519 : }
520 :
521 0 : static void dce110_xfmv_set_scaler(
522 : struct transform *xfm,
523 : const struct scaler_data *data)
524 : {
525 0 : struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
526 0 : bool is_scaling_required = false;
527 0 : bool filter_updated = false;
528 : const uint16_t *coeffs_v, *coeffs_h, *coeffs_h_c, *coeffs_v_c;
529 0 : struct rect luma_viewport = {0};
530 0 : struct rect chroma_viewport = {0};
531 :
532 0 : dce110_xfmv_power_up_line_buffer(xfm);
533 : /* 1. Calculate viewport, viewport programming should happen after init
534 : * calculations as they may require an adjustment in the viewport.
535 : */
536 :
537 0 : calculate_viewport(data, &luma_viewport, &chroma_viewport);
538 :
539 : /* 2. Program overscan */
540 0 : program_overscan(xfm_dce, data);
541 :
542 : /* 3. Program taps and configuration */
543 0 : is_scaling_required = setup_scaling_configuration(xfm_dce, data);
544 :
545 0 : if (is_scaling_required) {
546 : /* 4. Calculate and program ratio, filter initialization */
547 :
548 0 : struct sclv_ratios_inits inits = { 0 };
549 :
550 0 : calculate_inits(
551 : xfm_dce,
552 : data,
553 : &inits,
554 : &luma_viewport,
555 : &chroma_viewport);
556 :
557 0 : program_scl_ratios_inits(xfm_dce, &inits);
558 :
559 0 : coeffs_v = get_filter_coeffs_64p(data->taps.v_taps, data->ratios.vert);
560 0 : coeffs_h = get_filter_coeffs_64p(data->taps.h_taps, data->ratios.horz);
561 0 : coeffs_v_c = get_filter_coeffs_64p(data->taps.v_taps_c, data->ratios.vert_c);
562 0 : coeffs_h_c = get_filter_coeffs_64p(data->taps.h_taps_c, data->ratios.horz_c);
563 :
564 0 : if (coeffs_v != xfm_dce->filter_v
565 0 : || coeffs_v_c != xfm_dce->filter_v_c
566 0 : || coeffs_h != xfm_dce->filter_h
567 0 : || coeffs_h_c != xfm_dce->filter_h_c) {
568 : /* 5. Program vertical filters */
569 0 : program_multi_taps_filter(
570 : xfm_dce,
571 0 : data->taps.v_taps,
572 : coeffs_v,
573 : FILTER_TYPE_RGB_Y_VERTICAL);
574 0 : program_multi_taps_filter(
575 : xfm_dce,
576 0 : data->taps.v_taps_c,
577 : coeffs_v_c,
578 : FILTER_TYPE_CBCR_VERTICAL);
579 :
580 : /* 6. Program horizontal filters */
581 0 : program_multi_taps_filter(
582 : xfm_dce,
583 0 : data->taps.h_taps,
584 : coeffs_h,
585 : FILTER_TYPE_RGB_Y_HORIZONTAL);
586 0 : program_multi_taps_filter(
587 : xfm_dce,
588 0 : data->taps.h_taps_c,
589 : coeffs_h_c,
590 : FILTER_TYPE_CBCR_HORIZONTAL);
591 :
592 0 : xfm_dce->filter_v = coeffs_v;
593 0 : xfm_dce->filter_v_c = coeffs_v_c;
594 0 : xfm_dce->filter_h = coeffs_h;
595 0 : xfm_dce->filter_h_c = coeffs_h_c;
596 0 : filter_updated = true;
597 : }
598 : }
599 :
600 : /* 7. Program the viewport */
601 0 : program_viewport(xfm_dce, &luma_viewport, &chroma_viewport);
602 :
603 : /* 8. Set bit to flip to new coefficient memory */
604 0 : if (filter_updated)
605 0 : set_coeff_update_complete(xfm_dce);
606 0 : }
607 :
608 0 : static void dce110_xfmv_reset(struct transform *xfm)
609 : {
610 0 : struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
611 :
612 0 : xfm_dce->filter_h = NULL;
613 0 : xfm_dce->filter_v = NULL;
614 0 : xfm_dce->filter_h_c = NULL;
615 0 : xfm_dce->filter_v_c = NULL;
616 0 : }
617 :
618 0 : static void dce110_xfmv_set_gamut_remap(
619 : struct transform *xfm,
620 : const struct xfm_grph_csc_adjustment *adjust)
621 : {
622 : /* DO NOTHING*/
623 0 : }
624 :
625 0 : static void dce110_xfmv_set_pixel_storage_depth(
626 : struct transform *xfm,
627 : enum lb_pixel_depth depth,
628 : const struct bit_depth_reduction_params *bit_depth_params)
629 : {
630 0 : struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
631 0 : int pixel_depth = 0;
632 0 : int expan_mode = 0;
633 0 : uint32_t reg_data = 0;
634 :
635 0 : switch (depth) {
636 : case LB_PIXEL_DEPTH_18BPP:
637 : pixel_depth = 2;
638 : expan_mode = 1;
639 : break;
640 : case LB_PIXEL_DEPTH_24BPP:
641 0 : pixel_depth = 1;
642 0 : expan_mode = 1;
643 0 : break;
644 : case LB_PIXEL_DEPTH_30BPP:
645 0 : pixel_depth = 0;
646 0 : expan_mode = 1;
647 0 : break;
648 : case LB_PIXEL_DEPTH_36BPP:
649 0 : pixel_depth = 3;
650 0 : expan_mode = 0;
651 0 : break;
652 : default:
653 0 : BREAK_TO_DEBUGGER();
654 0 : break;
655 : }
656 :
657 0 : set_reg_field_value(
658 : reg_data,
659 : expan_mode,
660 : LBV_DATA_FORMAT,
661 : PIXEL_EXPAN_MODE);
662 :
663 0 : set_reg_field_value(
664 : reg_data,
665 : pixel_depth,
666 : LBV_DATA_FORMAT,
667 : PIXEL_DEPTH);
668 :
669 0 : dm_write_reg(xfm->ctx, mmLBV_DATA_FORMAT, reg_data);
670 :
671 0 : if (!(xfm_dce->lb_pixel_depth_supported & depth)) {
672 : /*we should use unsupported capabilities
673 : * unless it is required by w/a*/
674 0 : DC_LOG_WARNING("%s: Capability not supported",
675 : __func__);
676 : }
677 0 : }
678 :
679 : static const struct transform_funcs dce110_xfmv_funcs = {
680 : .transform_reset = dce110_xfmv_reset,
681 : .transform_set_scaler = dce110_xfmv_set_scaler,
682 : .transform_set_gamut_remap =
683 : dce110_xfmv_set_gamut_remap,
684 : .opp_set_csc_default = dce110_opp_v_set_csc_default,
685 : .opp_set_csc_adjustment = dce110_opp_v_set_csc_adjustment,
686 : .opp_power_on_regamma_lut = dce110_opp_power_on_regamma_lut_v,
687 : .opp_program_regamma_pwl = dce110_opp_program_regamma_pwl_v,
688 : .opp_set_regamma_mode = dce110_opp_set_regamma_mode_v,
689 : .transform_set_pixel_storage_depth =
690 : dce110_xfmv_set_pixel_storage_depth,
691 : .transform_get_optimal_number_of_taps =
692 : dce_transform_get_optimal_number_of_taps
693 : };
694 : /*****************************************/
695 : /* Constructor, Destructor */
696 : /*****************************************/
697 :
698 0 : bool dce110_transform_v_construct(
699 : struct dce_transform *xfm_dce,
700 : struct dc_context *ctx)
701 : {
702 0 : xfm_dce->base.ctx = ctx;
703 :
704 0 : xfm_dce->base.funcs = &dce110_xfmv_funcs;
705 :
706 0 : xfm_dce->lb_pixel_depth_supported =
707 : LB_PIXEL_DEPTH_18BPP |
708 : LB_PIXEL_DEPTH_24BPP |
709 : LB_PIXEL_DEPTH_30BPP |
710 : LB_PIXEL_DEPTH_36BPP;
711 :
712 0 : xfm_dce->prescaler_on = true;
713 0 : xfm_dce->lb_bits_per_entry = LB_BITS_PER_ENTRY;
714 0 : xfm_dce->lb_memory_size = LB_TOTAL_NUMBER_OF_ENTRIES; /*0x6B0*/
715 :
716 0 : return true;
717 : }
|