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