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