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
36struct 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
47static 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 luma_viewport->x = scl_data->viewport.x - scl_data->viewport.x % 2;
54 luma_viewport->y = scl_data->viewport.y - scl_data->viewport.y % 2;
55 luma_viewport->width =
56 scl_data->viewport.width - scl_data->viewport.width % 2;
57 luma_viewport->height =
58 scl_data->viewport.height - scl_data->viewport.height % 2;
59 chroma_viewport->x = luma_viewport->x;
60 chroma_viewport->y = luma_viewport->y;
61 chroma_viewport->height = luma_viewport->height;
62 chroma_viewport->width = luma_viewport->width;
63
64 if (scl_data->format == PIXEL_FORMAT_420BPP8) {
65 luma_viewport->height += luma_viewport->height % 2;
66 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 chroma_viewport->x = luma_viewport->x / 2;
71 chroma_viewport->y = luma_viewport->y / 2;
72 chroma_viewport->height = luma_viewport->height / 2;
73 chroma_viewport->width = luma_viewport->width / 2;
74 }
75}
76
77static void program_viewport(
78 struct dce_transform *xfm_dce,
79 struct rect *luma_view_port,
80 struct rect *chroma_view_port)
81{
82 struct dc_context *ctx = xfm_dce->base.ctx;
83 uint32_t value = 0;
84 uint32_t addr = 0;
85
86 if (luma_view_port->width != 0 && luma_view_port->height != 0) {
87 addr = mmSCLV_VIEWPORT_START;
88 value = 0;
89 set_reg_field_value(
90 value,
91 luma_view_port->x,
92 SCLV_VIEWPORT_START,
93 VIEWPORT_X_START);
94 set_reg_field_value(
95 value,
96 luma_view_port->y,
97 SCLV_VIEWPORT_START,
98 VIEWPORT_Y_START);
99 dm_write_reg(ctx, addr, value);
100
101 addr = mmSCLV_VIEWPORT_SIZE;
102 value = 0;
103 set_reg_field_value(
104 value,
105 luma_view_port->height,
106 SCLV_VIEWPORT_SIZE,
107 VIEWPORT_HEIGHT);
108 set_reg_field_value(
109 value,
110 luma_view_port->width,
111 SCLV_VIEWPORT_SIZE,
112 VIEWPORT_WIDTH);
113 dm_write_reg(ctx, addr, value);
114 }
115
116 if (chroma_view_port->width != 0 && chroma_view_port->height != 0) {
117 addr = mmSCLV_VIEWPORT_START_C;
118 value = 0;
119 set_reg_field_value(
120 value,
121 chroma_view_port->x,
122 SCLV_VIEWPORT_START_C,
123 VIEWPORT_X_START_C);
124 set_reg_field_value(
125 value,
126 chroma_view_port->y,
127 SCLV_VIEWPORT_START_C,
128 VIEWPORT_Y_START_C);
129 dm_write_reg(ctx, addr, value);
130
131 addr = mmSCLV_VIEWPORT_SIZE_C;
132 value = 0;
133 set_reg_field_value(
134 value,
135 chroma_view_port->height,
136 SCLV_VIEWPORT_SIZE_C,
137 VIEWPORT_HEIGHT_C);
138 set_reg_field_value(
139 value,
140 chroma_view_port->width,
141 SCLV_VIEWPORT_SIZE_C,
142 VIEWPORT_WIDTH_C);
143 dm_write_reg(ctx, addr, value);
144 }
145}
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 */
157static bool setup_scaling_configuration(
158 struct dce_transform *xfm_dce,
159 const struct scaler_data *data)
160{
161 bool is_scaling_needed = false;
162 struct dc_context *ctx = xfm_dce->base.ctx;
163 uint32_t value = 0;
164
165 set_reg_field_value(value, data->taps.h_taps - 1,
166 SCLV_TAP_CONTROL, SCL_H_NUM_OF_TAPS);
167 set_reg_field_value(value, data->taps.v_taps - 1,
168 SCLV_TAP_CONTROL, SCL_V_NUM_OF_TAPS);
169 set_reg_field_value(value, data->taps.h_taps_c - 1,
170 SCLV_TAP_CONTROL, SCL_H_NUM_OF_TAPS_C);
171 set_reg_field_value(value, data->taps.v_taps_c - 1,
172 SCLV_TAP_CONTROL, SCL_V_NUM_OF_TAPS_C);
173 dm_write_reg(ctx, mmSCLV_TAP_CONTROL, value);
174
175 value = 0;
176 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 if (data->taps.h_taps_c + data->taps.v_taps_c > 2) {
186 set_reg_field_value(value, 1, SCLV_MODE, SCL_MODE_C);
187 set_reg_field_value(value, 1, SCLV_MODE, SCL_PSCL_EN_C);
188 is_scaling_needed = true;
189 } else if (data->format != PIXEL_FORMAT_420BPP8) {
190 set_reg_field_value(
191 value,
192 get_reg_field_value(value, SCLV_MODE, SCL_MODE),
193 SCLV_MODE,
194 SCL_MODE_C);
195 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 dm_write_reg(ctx, mmSCLV_MODE, value);
205
206 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 set_reg_field_value(value, 1, SCLV_CONTROL, SCL_BOUNDARY_MODE);
213 dm_write_reg(ctx, mmSCLV_CONTROL, value);
214
215 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 */
227static void program_overscan(
228 struct dce_transform *xfm_dce,
229 const struct scaler_data *data)
230{
231 uint32_t overscan_left_right = 0;
232 uint32_t overscan_top_bottom = 0;
233
234 int overscan_right = data->h_active - data->recout.x - data->recout.width;
235 int overscan_bottom = data->v_active - data->recout.y - data->recout.height;
236
237 if (xfm_dce->base.ctx->dc->debug.visual_confirm != VISUAL_CONFIRM_DISABLE) {
238 overscan_bottom += 2;
239 overscan_right += 2;
240 }
241
242 if (overscan_right < 0) {
243 BREAK_TO_DEBUGGER();
244 overscan_right = 0;
245 }
246 if (overscan_bottom < 0) {
247 BREAK_TO_DEBUGGER();
248 overscan_bottom = 0;
249 }
250
251 set_reg_field_value(overscan_left_right, data->recout.x,
252 EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_LEFT);
253
254 set_reg_field_value(overscan_left_right, overscan_right,
255 EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_RIGHT);
256
257 set_reg_field_value(overscan_top_bottom, data->recout.y,
258 EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_TOP);
259
260 set_reg_field_value(overscan_top_bottom, overscan_bottom,
261 EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_BOTTOM);
262
263 dm_write_reg(xfm_dce->base.ctx,
264 mmSCLV_EXT_OVERSCAN_LEFT_RIGHT,
265 overscan_left_right);
266
267 dm_write_reg(xfm_dce->base.ctx,
268 mmSCLV_EXT_OVERSCAN_TOP_BOTTOM,
269 overscan_top_bottom);
270}
271
272static void set_coeff_update_complete(
273 struct dce_transform *xfm_dce)
274{
275 uint32_t value;
276
277 value = dm_read_reg(xfm_dce->base.ctx, mmSCLV_UPDATE);
278 set_reg_field_value(value, 1, SCLV_UPDATE, SCL_COEF_UPDATE_COMPLETE);
279 dm_write_reg(xfm_dce->base.ctx, mmSCLV_UPDATE, value);
280}
281
282static 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 struct dc_context *ctx = xfm_dce->base.ctx;
289 int i, phase, pair;
290 int array_idx = 0;
291 int taps_pairs = (taps + 1) / 2;
292 int phases_to_program = SCLV_PHASES / 2 + 1;
293
294 uint32_t select = 0;
295 uint32_t power_ctl, power_ctl_off;
296
297 if (!coeffs)
298 return;
299
300 /*We need to disable power gating on coeff memory to do programming*/
301 power_ctl = dm_read_reg(ctx, mmDCFEV_MEM_PWR_CTRL);
302 power_ctl_off = power_ctl;
303 set_reg_field_value(power_ctl_off, 1, DCFEV_MEM_PWR_CTRL, SCLV_COEFF_MEM_PWR_DIS);
304 dm_write_reg(ctx, mmDCFEV_MEM_PWR_CTRL, power_ctl_off);
305
306 /*Wait to disable gating:*/
307 for (i = 0; i < 10; i++) {
308 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 udelay(1);
315 }
316
317 set_reg_field_value(select, filter_type, SCLV_COEF_RAM_SELECT, SCL_C_RAM_FILTER_TYPE);
318
319 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 set_reg_field_value(select, phase, SCLV_COEF_RAM_SELECT, SCL_C_RAM_PHASE);
323 for (pair = 0; pair < taps_pairs; pair++) {
324 uint32_t data = 0;
325
326 set_reg_field_value(select, pair,
327 SCLV_COEF_RAM_SELECT, SCL_C_RAM_TAP_PAIR_IDX);
328
329 dm_write_reg(ctx, mmSCLV_COEF_RAM_SELECT, select);
330
331 set_reg_field_value(
332 data, 1,
333 SCLV_COEF_RAM_TAP_DATA,
334 SCL_C_RAM_EVEN_TAP_COEF_EN);
335 set_reg_field_value(
336 data, coeffs[array_idx],
337 SCLV_COEF_RAM_TAP_DATA,
338 SCL_C_RAM_EVEN_TAP_COEF);
339
340 if (taps % 2 && pair == taps_pairs - 1) {
341 set_reg_field_value(
342 data, 0,
343 SCLV_COEF_RAM_TAP_DATA,
344 SCL_C_RAM_ODD_TAP_COEF_EN);
345 array_idx++;
346 } else {
347 set_reg_field_value(
348 data, 1,
349 SCLV_COEF_RAM_TAP_DATA,
350 SCL_C_RAM_ODD_TAP_COEF_EN);
351 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 array_idx += 2;
357 }
358
359 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 dm_write_reg(ctx, mmDCFEV_MEM_PWR_CTRL, power_ctl);
365}
366
367static 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 inits->h_int_scale_ratio_luma =
375 dc_fixpt_u2d19(arg: data->ratios.horz) << 5;
376 inits->v_int_scale_ratio_luma =
377 dc_fixpt_u2d19(arg: data->ratios.vert) << 5;
378 inits->h_int_scale_ratio_chroma =
379 dc_fixpt_u2d19(arg: data->ratios.horz_c) << 5;
380 inits->v_int_scale_ratio_chroma =
381 dc_fixpt_u2d19(arg: data->ratios.vert_c) << 5;
382
383 inits->h_init_luma.integer = 1;
384 inits->v_init_luma.integer = 1;
385 inits->h_init_chroma.integer = 1;
386 inits->v_init_chroma.integer = 1;
387}
388
389static void program_scl_ratios_inits(
390 struct dce_transform *xfm_dce,
391 struct sclv_ratios_inits *inits)
392{
393 struct dc_context *ctx = xfm_dce->base.ctx;
394 uint32_t addr = mmSCLV_HORZ_FILTER_SCALE_RATIO;
395 uint32_t value = 0;
396
397 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 dm_write_reg(ctx, addr, value);
403
404 addr = mmSCLV_VERT_FILTER_SCALE_RATIO;
405 value = 0;
406 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 dm_write_reg(ctx, addr, value);
412
413 addr = mmSCLV_HORZ_FILTER_SCALE_RATIO_C;
414 value = 0;
415 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 dm_write_reg(ctx, addr, value);
421
422 addr = mmSCLV_VERT_FILTER_SCALE_RATIO_C;
423 value = 0;
424 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 dm_write_reg(ctx, addr, value);
430
431 addr = mmSCLV_HORZ_FILTER_INIT;
432 value = 0;
433 set_reg_field_value(
434 value,
435 inits->h_init_luma.fraction,
436 SCLV_HORZ_FILTER_INIT,
437 SCL_H_INIT_FRAC);
438 set_reg_field_value(
439 value,
440 inits->h_init_luma.integer,
441 SCLV_HORZ_FILTER_INIT,
442 SCL_H_INIT_INT);
443 dm_write_reg(ctx, addr, value);
444
445 addr = mmSCLV_VERT_FILTER_INIT;
446 value = 0;
447 set_reg_field_value(
448 value,
449 inits->v_init_luma.fraction,
450 SCLV_VERT_FILTER_INIT,
451 SCL_V_INIT_FRAC);
452 set_reg_field_value(
453 value,
454 inits->v_init_luma.integer,
455 SCLV_VERT_FILTER_INIT,
456 SCL_V_INIT_INT);
457 dm_write_reg(ctx, addr, value);
458
459 addr = mmSCLV_HORZ_FILTER_INIT_C;
460 value = 0;
461 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 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 dm_write_reg(ctx, addr, value);
472
473 addr = mmSCLV_VERT_FILTER_INIT_C;
474 value = 0;
475 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 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 dm_write_reg(ctx, addr, value);
486}
487
488static const uint16_t *get_filter_coeffs_64p(int taps, struct fixed31_32 ratio)
489{
490 if (taps == 4)
491 return get_filter_4tap_64p(ratio);
492 else if (taps == 2)
493 return get_filter_2tap_64p();
494 else if (taps == 1)
495 return NULL;
496 else {
497 /* should never happen, bug */
498 BREAK_TO_DEBUGGER();
499 return NULL;
500 }
501}
502
503static bool dce110_xfmv_power_up_line_buffer(struct transform *xfm)
504{
505 struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
506 uint32_t value;
507
508 value = dm_read_reg(xfm_dce->base.ctx, mmLBV_MEMORY_CTRL);
509
510 /*Use all three pieces of memory always*/
511 set_reg_field_value(value, 0, LBV_MEMORY_CTRL, LB_MEMORY_CONFIG);
512 /*hard coded number DCE11 1712(0x6B0) Partitions: 720/960/1712*/
513 set_reg_field_value(value, xfm_dce->lb_memory_size, LBV_MEMORY_CTRL,
514 LB_MEMORY_SIZE);
515
516 dm_write_reg(xfm_dce->base.ctx, mmLBV_MEMORY_CTRL, value);
517
518 return true;
519}
520
521static void dce110_xfmv_set_scaler(
522 struct transform *xfm,
523 const struct scaler_data *data)
524{
525 struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
526 bool is_scaling_required = false;
527 bool filter_updated = false;
528 const uint16_t *coeffs_v, *coeffs_h, *coeffs_h_c, *coeffs_v_c;
529 struct rect luma_viewport = {0};
530 struct rect chroma_viewport = {0};
531
532 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 calculate_viewport(scl_data: data, luma_viewport: &luma_viewport, chroma_viewport: &chroma_viewport);
538
539 /* 2. Program overscan */
540 program_overscan(xfm_dce, data);
541
542 /* 3. Program taps and configuration */
543 is_scaling_required = setup_scaling_configuration(xfm_dce, data);
544
545 if (is_scaling_required) {
546 /* 4. Calculate and program ratio, filter initialization */
547
548 struct sclv_ratios_inits inits = { 0 };
549
550 calculate_inits(
551 xfm_dce,
552 data,
553 inits: &inits,
554 luma_viewport: &luma_viewport,
555 chroma_viewport: &chroma_viewport);
556
557 program_scl_ratios_inits(xfm_dce, inits: &inits);
558
559 coeffs_v = get_filter_coeffs_64p(taps: data->taps.v_taps, ratio: data->ratios.vert);
560 coeffs_h = get_filter_coeffs_64p(taps: data->taps.h_taps, ratio: data->ratios.horz);
561 coeffs_v_c = get_filter_coeffs_64p(taps: data->taps.v_taps_c, ratio: data->ratios.vert_c);
562 coeffs_h_c = get_filter_coeffs_64p(taps: data->taps.h_taps_c, ratio: data->ratios.horz_c);
563
564 if (coeffs_v != xfm_dce->filter_v
565 || coeffs_v_c != xfm_dce->filter_v_c
566 || coeffs_h != xfm_dce->filter_h
567 || coeffs_h_c != xfm_dce->filter_h_c) {
568 /* 5. Program vertical filters */
569 program_multi_taps_filter(
570 xfm_dce,
571 taps: data->taps.v_taps,
572 coeffs: coeffs_v,
573 filter_type: FILTER_TYPE_RGB_Y_VERTICAL);
574 program_multi_taps_filter(
575 xfm_dce,
576 taps: data->taps.v_taps_c,
577 coeffs: coeffs_v_c,
578 filter_type: FILTER_TYPE_CBCR_VERTICAL);
579
580 /* 6. Program horizontal filters */
581 program_multi_taps_filter(
582 xfm_dce,
583 taps: data->taps.h_taps,
584 coeffs: coeffs_h,
585 filter_type: FILTER_TYPE_RGB_Y_HORIZONTAL);
586 program_multi_taps_filter(
587 xfm_dce,
588 taps: data->taps.h_taps_c,
589 coeffs: coeffs_h_c,
590 filter_type: FILTER_TYPE_CBCR_HORIZONTAL);
591
592 xfm_dce->filter_v = coeffs_v;
593 xfm_dce->filter_v_c = coeffs_v_c;
594 xfm_dce->filter_h = coeffs_h;
595 xfm_dce->filter_h_c = coeffs_h_c;
596 filter_updated = true;
597 }
598 }
599
600 /* 7. Program the viewport */
601 program_viewport(xfm_dce, luma_view_port: &luma_viewport, chroma_view_port: &chroma_viewport);
602
603 /* 8. Set bit to flip to new coefficient memory */
604 if (filter_updated)
605 set_coeff_update_complete(xfm_dce);
606}
607
608static void dce110_xfmv_reset(struct transform *xfm)
609{
610 struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
611
612 xfm_dce->filter_h = NULL;
613 xfm_dce->filter_v = NULL;
614 xfm_dce->filter_h_c = NULL;
615 xfm_dce->filter_v_c = NULL;
616}
617
618static void dce110_xfmv_set_gamut_remap(
619 struct transform *xfm,
620 const struct xfm_grph_csc_adjustment *adjust)
621{
622 /* DO NOTHING*/
623}
624
625static 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 struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
631 int pixel_depth = 0;
632 int expan_mode = 0;
633 uint32_t reg_data = 0;
634
635 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 pixel_depth = 1;
642 expan_mode = 1;
643 break;
644 case LB_PIXEL_DEPTH_30BPP:
645 pixel_depth = 0;
646 expan_mode = 1;
647 break;
648 case LB_PIXEL_DEPTH_36BPP:
649 pixel_depth = 3;
650 expan_mode = 0;
651 break;
652 default:
653 BREAK_TO_DEBUGGER();
654 break;
655 }
656
657 set_reg_field_value(
658 reg_data,
659 expan_mode,
660 LBV_DATA_FORMAT,
661 PIXEL_EXPAN_MODE);
662
663 set_reg_field_value(
664 reg_data,
665 pixel_depth,
666 LBV_DATA_FORMAT,
667 PIXEL_DEPTH);
668
669 dm_write_reg(xfm->ctx, mmLBV_DATA_FORMAT, reg_data);
670
671 if (!(xfm_dce->lb_pixel_depth_supported & depth)) {
672 /*we should use unsupported capabilities
673 * unless it is required by w/a*/
674 DC_LOG_WARNING("%s: Capability not supported",
675 __func__);
676 }
677}
678
679static 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
698bool dce110_transform_v_construct(
699 struct dce_transform *xfm_dce,
700 struct dc_context *ctx)
701{
702 xfm_dce->base.ctx = ctx;
703
704 xfm_dce->base.funcs = &dce110_xfmv_funcs;
705
706 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 xfm_dce->prescaler_on = true;
713 xfm_dce->lb_bits_per_entry = LB_BITS_PER_ENTRY;
714 xfm_dce->lb_memory_size = LB_TOTAL_NUMBER_OF_ENTRIES; /*0x6B0*/
715
716 return true;
717}
718

source code of linux/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c