Linux-libre 5.3.12-gnu
[librecmc/linux-libre.git] / drivers / gpu / drm / amd / display / dc / dce110 / dce110_transform_v.c
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
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
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  */
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:
228    void
229 */
230 static void program_overscan(
231                 struct dce_transform *xfm_dce,
232                 const struct scaler_data *data)
233 {
234         uint32_t overscan_left_right = 0;
235         uint32_t overscan_top_bottom = 0;
236
237         int overscan_right = data->h_active - data->recout.x - data->recout.width;
238         int overscan_bottom = data->v_active - data->recout.y - data->recout.height;
239
240         if (xfm_dce->base.ctx->dc->debug.visual_confirm != VISUAL_CONFIRM_DISABLE) {
241                 overscan_bottom += 2;
242                 overscan_right += 2;
243         }
244
245         if (overscan_right < 0) {
246                 BREAK_TO_DEBUGGER();
247                 overscan_right = 0;
248         }
249         if (overscan_bottom < 0) {
250                 BREAK_TO_DEBUGGER();
251                 overscan_bottom = 0;
252         }
253
254         set_reg_field_value(overscan_left_right, data->recout.x,
255                         EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_LEFT);
256
257         set_reg_field_value(overscan_left_right, overscan_right,
258                         EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_RIGHT);
259
260         set_reg_field_value(overscan_top_bottom, data->recout.y,
261                         EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_TOP);
262
263         set_reg_field_value(overscan_top_bottom, overscan_bottom,
264                         EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_BOTTOM);
265
266         dm_write_reg(xfm_dce->base.ctx,
267                         mmSCLV_EXT_OVERSCAN_LEFT_RIGHT,
268                         overscan_left_right);
269
270         dm_write_reg(xfm_dce->base.ctx,
271                         mmSCLV_EXT_OVERSCAN_TOP_BOTTOM,
272                         overscan_top_bottom);
273 }
274
275 static void set_coeff_update_complete(
276                 struct dce_transform *xfm_dce)
277 {
278         uint32_t value;
279
280         value = dm_read_reg(xfm_dce->base.ctx, mmSCLV_UPDATE);
281         set_reg_field_value(value, 1, SCLV_UPDATE, SCL_COEF_UPDATE_COMPLETE);
282         dm_write_reg(xfm_dce->base.ctx, mmSCLV_UPDATE, value);
283 }
284
285 static void program_multi_taps_filter(
286         struct dce_transform *xfm_dce,
287         int taps,
288         const uint16_t *coeffs,
289         enum ram_filter_type filter_type)
290 {
291         struct dc_context *ctx = xfm_dce->base.ctx;
292         int i, phase, pair;
293         int array_idx = 0;
294         int taps_pairs = (taps + 1) / 2;
295         int phases_to_program = SCLV_PHASES / 2 + 1;
296
297         uint32_t select = 0;
298         uint32_t power_ctl, power_ctl_off;
299
300         if (!coeffs)
301                 return;
302
303         /*We need to disable power gating on coeff memory to do programming*/
304         power_ctl = dm_read_reg(ctx, mmDCFEV_MEM_PWR_CTRL);
305         power_ctl_off = power_ctl;
306         set_reg_field_value(power_ctl_off, 1, DCFEV_MEM_PWR_CTRL, SCLV_COEFF_MEM_PWR_DIS);
307         dm_write_reg(ctx, mmDCFEV_MEM_PWR_CTRL, power_ctl_off);
308
309         /*Wait to disable gating:*/
310         for (i = 0; i < 10; i++) {
311                 if (get_reg_field_value(
312                                 dm_read_reg(ctx, mmDCFEV_MEM_PWR_STATUS),
313                                 DCFEV_MEM_PWR_STATUS,
314                                 SCLV_COEFF_MEM_PWR_STATE) == 0)
315                         break;
316
317                 udelay(1);
318         }
319
320         set_reg_field_value(select, filter_type, SCLV_COEF_RAM_SELECT, SCL_C_RAM_FILTER_TYPE);
321
322         for (phase = 0; phase < phases_to_program; phase++) {
323                 /*we always program N/2 + 1 phases, total phases N, but N/2-1 are just mirror
324                 phase 0 is unique and phase N/2 is unique if N is even*/
325                 set_reg_field_value(select, phase, SCLV_COEF_RAM_SELECT, SCL_C_RAM_PHASE);
326                 for (pair = 0; pair < taps_pairs; pair++) {
327                         uint32_t data = 0;
328
329                         set_reg_field_value(select, pair,
330                                         SCLV_COEF_RAM_SELECT, SCL_C_RAM_TAP_PAIR_IDX);
331
332                         dm_write_reg(ctx, mmSCLV_COEF_RAM_SELECT, select);
333
334                         set_reg_field_value(
335                                         data, 1,
336                                         SCLV_COEF_RAM_TAP_DATA,
337                                         SCL_C_RAM_EVEN_TAP_COEF_EN);
338                         set_reg_field_value(
339                                         data, coeffs[array_idx],
340                                         SCLV_COEF_RAM_TAP_DATA,
341                                         SCL_C_RAM_EVEN_TAP_COEF);
342
343                         if (taps % 2 && pair == taps_pairs - 1) {
344                                 set_reg_field_value(
345                                                 data, 0,
346                                                 SCLV_COEF_RAM_TAP_DATA,
347                                                 SCL_C_RAM_ODD_TAP_COEF_EN);
348                                 array_idx++;
349                         } else {
350                                 set_reg_field_value(
351                                                 data, 1,
352                                                 SCLV_COEF_RAM_TAP_DATA,
353                                                 SCL_C_RAM_ODD_TAP_COEF_EN);
354                                 set_reg_field_value(
355                                                 data, coeffs[array_idx + 1],
356                                                 SCLV_COEF_RAM_TAP_DATA,
357                                                 SCL_C_RAM_ODD_TAP_COEF);
358
359                                 array_idx += 2;
360                         }
361
362                         dm_write_reg(ctx, mmSCLV_COEF_RAM_TAP_DATA, data);
363                 }
364         }
365
366         /*We need to restore power gating on coeff memory to initial state*/
367         dm_write_reg(ctx, mmDCFEV_MEM_PWR_CTRL, power_ctl);
368 }
369
370 static void calculate_inits(
371         struct dce_transform *xfm_dce,
372         const struct scaler_data *data,
373         struct sclv_ratios_inits *inits,
374         struct rect *luma_viewport,
375         struct rect *chroma_viewport)
376 {
377         inits->h_int_scale_ratio_luma =
378                 dc_fixpt_u2d19(data->ratios.horz) << 5;
379         inits->v_int_scale_ratio_luma =
380                 dc_fixpt_u2d19(data->ratios.vert) << 5;
381         inits->h_int_scale_ratio_chroma =
382                 dc_fixpt_u2d19(data->ratios.horz_c) << 5;
383         inits->v_int_scale_ratio_chroma =
384                 dc_fixpt_u2d19(data->ratios.vert_c) << 5;
385
386         inits->h_init_luma.integer = 1;
387         inits->v_init_luma.integer = 1;
388         inits->h_init_chroma.integer = 1;
389         inits->v_init_chroma.integer = 1;
390 }
391
392 static void program_scl_ratios_inits(
393         struct dce_transform *xfm_dce,
394         struct sclv_ratios_inits *inits)
395 {
396         struct dc_context *ctx = xfm_dce->base.ctx;
397         uint32_t addr = mmSCLV_HORZ_FILTER_SCALE_RATIO;
398         uint32_t value = 0;
399
400         set_reg_field_value(
401                 value,
402                 inits->h_int_scale_ratio_luma,
403                 SCLV_HORZ_FILTER_SCALE_RATIO,
404                 SCL_H_SCALE_RATIO);
405         dm_write_reg(ctx, addr, value);
406
407         addr = mmSCLV_VERT_FILTER_SCALE_RATIO;
408         value = 0;
409         set_reg_field_value(
410                 value,
411                 inits->v_int_scale_ratio_luma,
412                 SCLV_VERT_FILTER_SCALE_RATIO,
413                 SCL_V_SCALE_RATIO);
414         dm_write_reg(ctx, addr, value);
415
416         addr = mmSCLV_HORZ_FILTER_SCALE_RATIO_C;
417         value = 0;
418         set_reg_field_value(
419                 value,
420                 inits->h_int_scale_ratio_chroma,
421                 SCLV_HORZ_FILTER_SCALE_RATIO_C,
422                 SCL_H_SCALE_RATIO_C);
423         dm_write_reg(ctx, addr, value);
424
425         addr = mmSCLV_VERT_FILTER_SCALE_RATIO_C;
426         value = 0;
427         set_reg_field_value(
428                 value,
429                 inits->v_int_scale_ratio_chroma,
430                 SCLV_VERT_FILTER_SCALE_RATIO_C,
431                 SCL_V_SCALE_RATIO_C);
432         dm_write_reg(ctx, addr, value);
433
434         addr = mmSCLV_HORZ_FILTER_INIT;
435         value = 0;
436         set_reg_field_value(
437                 value,
438                 inits->h_init_luma.fraction,
439                 SCLV_HORZ_FILTER_INIT,
440                 SCL_H_INIT_FRAC);
441         set_reg_field_value(
442                 value,
443                 inits->h_init_luma.integer,
444                 SCLV_HORZ_FILTER_INIT,
445                 SCL_H_INIT_INT);
446         dm_write_reg(ctx, addr, value);
447
448         addr = mmSCLV_VERT_FILTER_INIT;
449         value = 0;
450         set_reg_field_value(
451                 value,
452                 inits->v_init_luma.fraction,
453                 SCLV_VERT_FILTER_INIT,
454                 SCL_V_INIT_FRAC);
455         set_reg_field_value(
456                 value,
457                 inits->v_init_luma.integer,
458                 SCLV_VERT_FILTER_INIT,
459                 SCL_V_INIT_INT);
460         dm_write_reg(ctx, addr, value);
461
462         addr = mmSCLV_HORZ_FILTER_INIT_C;
463         value = 0;
464         set_reg_field_value(
465                 value,
466                 inits->h_init_chroma.fraction,
467                 SCLV_HORZ_FILTER_INIT_C,
468                 SCL_H_INIT_FRAC_C);
469         set_reg_field_value(
470                 value,
471                 inits->h_init_chroma.integer,
472                 SCLV_HORZ_FILTER_INIT_C,
473                 SCL_H_INIT_INT_C);
474         dm_write_reg(ctx, addr, value);
475
476         addr = mmSCLV_VERT_FILTER_INIT_C;
477         value = 0;
478         set_reg_field_value(
479                 value,
480                 inits->v_init_chroma.fraction,
481                 SCLV_VERT_FILTER_INIT_C,
482                 SCL_V_INIT_FRAC_C);
483         set_reg_field_value(
484                 value,
485                 inits->v_init_chroma.integer,
486                 SCLV_VERT_FILTER_INIT_C,
487                 SCL_V_INIT_INT_C);
488         dm_write_reg(ctx, addr, value);
489 }
490
491 static const uint16_t *get_filter_coeffs_64p(int taps, struct fixed31_32 ratio)
492 {
493         if (taps == 4)
494                 return get_filter_4tap_64p(ratio);
495         else if (taps == 2)
496                 return get_filter_2tap_64p();
497         else if (taps == 1)
498                 return NULL;
499         else {
500                 /* should never happen, bug */
501                 BREAK_TO_DEBUGGER();
502                 return NULL;
503         }
504 }
505
506 static bool dce110_xfmv_power_up_line_buffer(struct transform *xfm)
507 {
508         struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
509         uint32_t value;
510
511         value = dm_read_reg(xfm_dce->base.ctx, mmLBV_MEMORY_CTRL);
512
513         /*Use all three pieces of memory always*/
514         set_reg_field_value(value, 0, LBV_MEMORY_CTRL, LB_MEMORY_CONFIG);
515         /*hard coded number DCE11 1712(0x6B0) Partitions: 720/960/1712*/
516         set_reg_field_value(value, xfm_dce->lb_memory_size, LBV_MEMORY_CTRL,
517                         LB_MEMORY_SIZE);
518
519         dm_write_reg(xfm_dce->base.ctx, mmLBV_MEMORY_CTRL, value);
520
521         return true;
522 }
523
524 static void dce110_xfmv_set_scaler(
525         struct transform *xfm,
526         const struct scaler_data *data)
527 {
528         struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
529         bool is_scaling_required = false;
530         bool filter_updated = false;
531         const uint16_t *coeffs_v, *coeffs_h, *coeffs_h_c, *coeffs_v_c;
532         struct rect luma_viewport = {0};
533         struct rect chroma_viewport = {0};
534
535         dce110_xfmv_power_up_line_buffer(xfm);
536         /* 1. Calculate viewport, viewport programming should happen after init
537          * calculations as they may require an adjustment in the viewport.
538          */
539
540         calculate_viewport(data, &luma_viewport, &chroma_viewport);
541
542         /* 2. Program overscan */
543         program_overscan(xfm_dce, data);
544
545         /* 3. Program taps and configuration */
546         is_scaling_required = setup_scaling_configuration(xfm_dce, data);
547
548         if (is_scaling_required) {
549                 /* 4. Calculate and program ratio, filter initialization */
550
551                 struct sclv_ratios_inits inits = { 0 };
552
553                 calculate_inits(
554                         xfm_dce,
555                         data,
556                         &inits,
557                         &luma_viewport,
558                         &chroma_viewport);
559
560                 program_scl_ratios_inits(xfm_dce, &inits);
561
562                 coeffs_v = get_filter_coeffs_64p(data->taps.v_taps, data->ratios.vert);
563                 coeffs_h = get_filter_coeffs_64p(data->taps.h_taps, data->ratios.horz);
564                 coeffs_v_c = get_filter_coeffs_64p(data->taps.v_taps_c, data->ratios.vert_c);
565                 coeffs_h_c = get_filter_coeffs_64p(data->taps.h_taps_c, data->ratios.horz_c);
566
567                 if (coeffs_v != xfm_dce->filter_v
568                                 || coeffs_v_c != xfm_dce->filter_v_c
569                                 || coeffs_h != xfm_dce->filter_h
570                                 || coeffs_h_c != xfm_dce->filter_h_c) {
571                 /* 5. Program vertical filters */
572                         program_multi_taps_filter(
573                                         xfm_dce,
574                                         data->taps.v_taps,
575                                         coeffs_v,
576                                         FILTER_TYPE_RGB_Y_VERTICAL);
577                         program_multi_taps_filter(
578                                         xfm_dce,
579                                         data->taps.v_taps_c,
580                                         coeffs_v_c,
581                                         FILTER_TYPE_CBCR_VERTICAL);
582
583                 /* 6. Program horizontal filters */
584                         program_multi_taps_filter(
585                                         xfm_dce,
586                                         data->taps.h_taps,
587                                         coeffs_h,
588                                         FILTER_TYPE_RGB_Y_HORIZONTAL);
589                         program_multi_taps_filter(
590                                         xfm_dce,
591                                         data->taps.h_taps_c,
592                                         coeffs_h_c,
593                                         FILTER_TYPE_CBCR_HORIZONTAL);
594
595                         xfm_dce->filter_v = coeffs_v;
596                         xfm_dce->filter_v_c = coeffs_v_c;
597                         xfm_dce->filter_h = coeffs_h;
598                         xfm_dce->filter_h_c = coeffs_h_c;
599                         filter_updated = true;
600                 }
601         }
602
603         /* 7. Program the viewport */
604         program_viewport(xfm_dce, &luma_viewport, &chroma_viewport);
605
606         /* 8. Set bit to flip to new coefficient memory */
607         if (filter_updated)
608                 set_coeff_update_complete(xfm_dce);
609 }
610
611 static void dce110_xfmv_reset(struct transform *xfm)
612 {
613         struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
614
615         xfm_dce->filter_h = NULL;
616         xfm_dce->filter_v = NULL;
617         xfm_dce->filter_h_c = NULL;
618         xfm_dce->filter_v_c = NULL;
619 }
620
621 static void dce110_xfmv_set_gamut_remap(
622         struct transform *xfm,
623         const struct xfm_grph_csc_adjustment *adjust)
624 {
625         /* DO NOTHING*/
626 }
627
628 static void dce110_xfmv_set_pixel_storage_depth(
629         struct transform *xfm,
630         enum lb_pixel_depth depth,
631         const struct bit_depth_reduction_params *bit_depth_params)
632 {
633         struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
634         int pixel_depth = 0;
635         int expan_mode = 0;
636         uint32_t reg_data = 0;
637
638         switch (depth) {
639         case LB_PIXEL_DEPTH_18BPP:
640                 pixel_depth = 2;
641                 expan_mode  = 1;
642                 break;
643         case LB_PIXEL_DEPTH_24BPP:
644                 pixel_depth = 1;
645                 expan_mode  = 1;
646                 break;
647         case LB_PIXEL_DEPTH_30BPP:
648                 pixel_depth = 0;
649                 expan_mode  = 1;
650                 break;
651         case LB_PIXEL_DEPTH_36BPP:
652                 pixel_depth = 3;
653                 expan_mode  = 0;
654                 break;
655         default:
656                 BREAK_TO_DEBUGGER();
657                 break;
658         }
659
660         set_reg_field_value(
661                 reg_data,
662                 expan_mode,
663                 LBV_DATA_FORMAT,
664                 PIXEL_EXPAN_MODE);
665
666         set_reg_field_value(
667                 reg_data,
668                 pixel_depth,
669                 LBV_DATA_FORMAT,
670                 PIXEL_DEPTH);
671
672         dm_write_reg(xfm->ctx, mmLBV_DATA_FORMAT, reg_data);
673
674         if (!(xfm_dce->lb_pixel_depth_supported & depth)) {
675                 /*we should use unsupported capabilities
676                  *  unless it is required by w/a*/
677                 DC_LOG_WARNING("%s: Capability not supported",
678                         __func__);
679         }
680 }
681
682 static const struct transform_funcs dce110_xfmv_funcs = {
683         .transform_reset = dce110_xfmv_reset,
684         .transform_set_scaler = dce110_xfmv_set_scaler,
685         .transform_set_gamut_remap =
686                 dce110_xfmv_set_gamut_remap,
687         .opp_set_csc_default = dce110_opp_v_set_csc_default,
688         .opp_set_csc_adjustment = dce110_opp_v_set_csc_adjustment,
689         .opp_power_on_regamma_lut = dce110_opp_power_on_regamma_lut_v,
690         .opp_program_regamma_pwl = dce110_opp_program_regamma_pwl_v,
691         .opp_set_regamma_mode = dce110_opp_set_regamma_mode_v,
692         .transform_set_pixel_storage_depth =
693                         dce110_xfmv_set_pixel_storage_depth,
694         .transform_get_optimal_number_of_taps =
695                 dce_transform_get_optimal_number_of_taps
696 };
697 /*****************************************/
698 /* Constructor, Destructor               */
699 /*****************************************/
700
701 bool dce110_transform_v_construct(
702         struct dce_transform *xfm_dce,
703         struct dc_context *ctx)
704 {
705         xfm_dce->base.ctx = ctx;
706
707         xfm_dce->base.funcs = &dce110_xfmv_funcs;
708
709         xfm_dce->lb_pixel_depth_supported =
710                         LB_PIXEL_DEPTH_18BPP |
711                         LB_PIXEL_DEPTH_24BPP |
712                         LB_PIXEL_DEPTH_30BPP;
713
714         xfm_dce->prescaler_on = true;
715         xfm_dce->lb_bits_per_entry = LB_BITS_PER_ENTRY;
716         xfm_dce->lb_memory_size = LB_TOTAL_NUMBER_OF_ENTRIES; /*0x6B0*/
717
718         return true;
719 }