Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright 2012-15 Advanced Micro Devices, Inc.
0003  *
0004  * Permission is hereby granted, free of charge, to any person obtaining a
0005  * copy of this software and associated documentation files (the "Software"),
0006  * to deal in the Software without restriction, including without limitation
0007  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0008  * and/or sell copies of the Software, and to permit persons to whom the
0009  * Software is furnished to do so, subject to the following conditions:
0010  *
0011  * The above copyright notice and this permission notice shall be included in
0012  * all copies or substantial portions of the Software.
0013  *
0014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0017  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
0018  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
0019  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
0020  * OTHER DEALINGS IN THE SOFTWARE.
0021  *
0022  * Authors: AMD
0023  *
0024  */
0025 
0026 #include "dce110_transform_v.h"
0027 #include "dm_services.h"
0028 #include "dc.h"
0029 #include "dce/dce_11_0_d.h"
0030 #include "dce/dce_11_0_sh_mask.h"
0031 
0032 #define SCLV_PHASES 64
0033 #define DC_LOGGER \
0034     xfm->ctx->logger
0035 
0036 struct sclv_ratios_inits {
0037     uint32_t h_int_scale_ratio_luma;
0038     uint32_t h_int_scale_ratio_chroma;
0039     uint32_t v_int_scale_ratio_luma;
0040     uint32_t v_int_scale_ratio_chroma;
0041     struct init_int_and_frac h_init_luma;
0042     struct init_int_and_frac h_init_chroma;
0043     struct init_int_and_frac v_init_luma;
0044     struct init_int_and_frac v_init_chroma;
0045 };
0046 
0047 static void calculate_viewport(
0048         const struct scaler_data *scl_data,
0049         struct rect *luma_viewport,
0050         struct rect *chroma_viewport)
0051 {
0052     /*Do not set chroma vp for rgb444 pixel format*/
0053     luma_viewport->x = scl_data->viewport.x - scl_data->viewport.x % 2;
0054     luma_viewport->y = scl_data->viewport.y - scl_data->viewport.y % 2;
0055     luma_viewport->width =
0056         scl_data->viewport.width - scl_data->viewport.width % 2;
0057     luma_viewport->height =
0058         scl_data->viewport.height - scl_data->viewport.height % 2;
0059     chroma_viewport->x = luma_viewport->x;
0060     chroma_viewport->y = luma_viewport->y;
0061     chroma_viewport->height = luma_viewport->height;
0062     chroma_viewport->width = luma_viewport->width;
0063 
0064     if (scl_data->format == PIXEL_FORMAT_420BPP8) {
0065         luma_viewport->height += luma_viewport->height % 2;
0066         luma_viewport->width += luma_viewport->width % 2;
0067         /*for 420 video chroma is 1/4 the area of luma, scaled
0068          *vertically and horizontally
0069          */
0070         chroma_viewport->x = luma_viewport->x / 2;
0071         chroma_viewport->y = luma_viewport->y / 2;
0072         chroma_viewport->height = luma_viewport->height / 2;
0073         chroma_viewport->width = luma_viewport->width / 2;
0074     }
0075 }
0076 
0077 static void program_viewport(
0078     struct dce_transform *xfm_dce,
0079     struct rect *luma_view_port,
0080     struct rect *chroma_view_port)
0081 {
0082     struct dc_context *ctx = xfm_dce->base.ctx;
0083     uint32_t value = 0;
0084     uint32_t addr = 0;
0085 
0086     if (luma_view_port->width != 0 && luma_view_port->height != 0) {
0087         addr = mmSCLV_VIEWPORT_START;
0088         value = 0;
0089         set_reg_field_value(
0090             value,
0091             luma_view_port->x,
0092             SCLV_VIEWPORT_START,
0093             VIEWPORT_X_START);
0094         set_reg_field_value(
0095             value,
0096             luma_view_port->y,
0097             SCLV_VIEWPORT_START,
0098             VIEWPORT_Y_START);
0099         dm_write_reg(ctx, addr, value);
0100 
0101         addr = mmSCLV_VIEWPORT_SIZE;
0102         value = 0;
0103         set_reg_field_value(
0104             value,
0105             luma_view_port->height,
0106             SCLV_VIEWPORT_SIZE,
0107             VIEWPORT_HEIGHT);
0108         set_reg_field_value(
0109             value,
0110             luma_view_port->width,
0111             SCLV_VIEWPORT_SIZE,
0112             VIEWPORT_WIDTH);
0113         dm_write_reg(ctx, addr, value);
0114     }
0115 
0116     if (chroma_view_port->width != 0 && chroma_view_port->height != 0) {
0117         addr = mmSCLV_VIEWPORT_START_C;
0118         value = 0;
0119         set_reg_field_value(
0120             value,
0121             chroma_view_port->x,
0122             SCLV_VIEWPORT_START_C,
0123             VIEWPORT_X_START_C);
0124         set_reg_field_value(
0125             value,
0126             chroma_view_port->y,
0127             SCLV_VIEWPORT_START_C,
0128             VIEWPORT_Y_START_C);
0129         dm_write_reg(ctx, addr, value);
0130 
0131         addr = mmSCLV_VIEWPORT_SIZE_C;
0132         value = 0;
0133         set_reg_field_value(
0134             value,
0135             chroma_view_port->height,
0136             SCLV_VIEWPORT_SIZE_C,
0137             VIEWPORT_HEIGHT_C);
0138         set_reg_field_value(
0139             value,
0140             chroma_view_port->width,
0141             SCLV_VIEWPORT_SIZE_C,
0142             VIEWPORT_WIDTH_C);
0143         dm_write_reg(ctx, addr, value);
0144     }
0145 }
0146 
0147 /*
0148  * Function:
0149  * void setup_scaling_configuration
0150  *
0151  * Purpose: setup scaling mode : bypass, RGb, YCbCr and nummber of taps
0152  * Input:   data
0153  *
0154  * Output:
0155  *  void
0156  */
0157 static bool setup_scaling_configuration(
0158     struct dce_transform *xfm_dce,
0159     const struct scaler_data *data)
0160 {
0161     bool is_scaling_needed = false;
0162     struct dc_context *ctx = xfm_dce->base.ctx;
0163     uint32_t value = 0;
0164 
0165     set_reg_field_value(value, data->taps.h_taps - 1,
0166             SCLV_TAP_CONTROL, SCL_H_NUM_OF_TAPS);
0167     set_reg_field_value(value, data->taps.v_taps - 1,
0168             SCLV_TAP_CONTROL, SCL_V_NUM_OF_TAPS);
0169     set_reg_field_value(value, data->taps.h_taps_c - 1,
0170             SCLV_TAP_CONTROL, SCL_H_NUM_OF_TAPS_C);
0171     set_reg_field_value(value, data->taps.v_taps_c - 1,
0172             SCLV_TAP_CONTROL, SCL_V_NUM_OF_TAPS_C);
0173     dm_write_reg(ctx, mmSCLV_TAP_CONTROL, value);
0174 
0175     value = 0;
0176     if (data->taps.h_taps + data->taps.v_taps > 2) {
0177         set_reg_field_value(value, 1, SCLV_MODE, SCL_MODE);
0178         set_reg_field_value(value, 1, SCLV_MODE, SCL_PSCL_EN);
0179         is_scaling_needed = true;
0180     } else {
0181         set_reg_field_value(value, 0, SCLV_MODE, SCL_MODE);
0182         set_reg_field_value(value, 0, SCLV_MODE, SCL_PSCL_EN);
0183     }
0184 
0185     if (data->taps.h_taps_c + data->taps.v_taps_c > 2) {
0186         set_reg_field_value(value, 1, SCLV_MODE, SCL_MODE_C);
0187         set_reg_field_value(value, 1, SCLV_MODE, SCL_PSCL_EN_C);
0188         is_scaling_needed = true;
0189     } else if (data->format != PIXEL_FORMAT_420BPP8) {
0190         set_reg_field_value(
0191             value,
0192             get_reg_field_value(value, SCLV_MODE, SCL_MODE),
0193             SCLV_MODE,
0194             SCL_MODE_C);
0195         set_reg_field_value(
0196             value,
0197             get_reg_field_value(value, SCLV_MODE, SCL_PSCL_EN),
0198             SCLV_MODE,
0199             SCL_PSCL_EN_C);
0200     } else {
0201         set_reg_field_value(value, 0, SCLV_MODE, SCL_MODE_C);
0202         set_reg_field_value(value, 0, SCLV_MODE, SCL_PSCL_EN_C);
0203     }
0204     dm_write_reg(ctx, mmSCLV_MODE, value);
0205 
0206     value = 0;
0207     /*
0208      * 0 - Replaced out of bound pixels with black pixel
0209      * (or any other required color)
0210      * 1 - Replaced out of bound pixels with the edge pixel
0211      */
0212     set_reg_field_value(value, 1, SCLV_CONTROL, SCL_BOUNDARY_MODE);
0213     dm_write_reg(ctx, mmSCLV_CONTROL, value);
0214 
0215     return is_scaling_needed;
0216 }
0217 
0218 /*
0219  * Function:
0220  * void program_overscan
0221  *
0222  * Purpose: Programs overscan border
0223  * Input:   overscan
0224  *
0225  * Output: void
0226  */
0227 static void program_overscan(
0228         struct dce_transform *xfm_dce,
0229         const struct scaler_data *data)
0230 {
0231     uint32_t overscan_left_right = 0;
0232     uint32_t overscan_top_bottom = 0;
0233 
0234     int overscan_right = data->h_active - data->recout.x - data->recout.width;
0235     int overscan_bottom = data->v_active - data->recout.y - data->recout.height;
0236 
0237     if (xfm_dce->base.ctx->dc->debug.visual_confirm != VISUAL_CONFIRM_DISABLE) {
0238         overscan_bottom += 2;
0239         overscan_right += 2;
0240     }
0241 
0242     if (overscan_right < 0) {
0243         BREAK_TO_DEBUGGER();
0244         overscan_right = 0;
0245     }
0246     if (overscan_bottom < 0) {
0247         BREAK_TO_DEBUGGER();
0248         overscan_bottom = 0;
0249     }
0250 
0251     set_reg_field_value(overscan_left_right, data->recout.x,
0252             EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_LEFT);
0253 
0254     set_reg_field_value(overscan_left_right, overscan_right,
0255             EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_RIGHT);
0256 
0257     set_reg_field_value(overscan_top_bottom, data->recout.y,
0258             EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_TOP);
0259 
0260     set_reg_field_value(overscan_top_bottom, overscan_bottom,
0261             EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_BOTTOM);
0262 
0263     dm_write_reg(xfm_dce->base.ctx,
0264             mmSCLV_EXT_OVERSCAN_LEFT_RIGHT,
0265             overscan_left_right);
0266 
0267     dm_write_reg(xfm_dce->base.ctx,
0268             mmSCLV_EXT_OVERSCAN_TOP_BOTTOM,
0269             overscan_top_bottom);
0270 }
0271 
0272 static void set_coeff_update_complete(
0273         struct dce_transform *xfm_dce)
0274 {
0275     uint32_t value;
0276 
0277     value = dm_read_reg(xfm_dce->base.ctx, mmSCLV_UPDATE);
0278     set_reg_field_value(value, 1, SCLV_UPDATE, SCL_COEF_UPDATE_COMPLETE);
0279     dm_write_reg(xfm_dce->base.ctx, mmSCLV_UPDATE, value);
0280 }
0281 
0282 static void program_multi_taps_filter(
0283     struct dce_transform *xfm_dce,
0284     int taps,
0285     const uint16_t *coeffs,
0286     enum ram_filter_type filter_type)
0287 {
0288     struct dc_context *ctx = xfm_dce->base.ctx;
0289     int i, phase, pair;
0290     int array_idx = 0;
0291     int taps_pairs = (taps + 1) / 2;
0292     int phases_to_program = SCLV_PHASES / 2 + 1;
0293 
0294     uint32_t select = 0;
0295     uint32_t power_ctl, power_ctl_off;
0296 
0297     if (!coeffs)
0298         return;
0299 
0300     /*We need to disable power gating on coeff memory to do programming*/
0301     power_ctl = dm_read_reg(ctx, mmDCFEV_MEM_PWR_CTRL);
0302     power_ctl_off = power_ctl;
0303     set_reg_field_value(power_ctl_off, 1, DCFEV_MEM_PWR_CTRL, SCLV_COEFF_MEM_PWR_DIS);
0304     dm_write_reg(ctx, mmDCFEV_MEM_PWR_CTRL, power_ctl_off);
0305 
0306     /*Wait to disable gating:*/
0307     for (i = 0; i < 10; i++) {
0308         if (get_reg_field_value(
0309                 dm_read_reg(ctx, mmDCFEV_MEM_PWR_STATUS),
0310                 DCFEV_MEM_PWR_STATUS,
0311                 SCLV_COEFF_MEM_PWR_STATE) == 0)
0312             break;
0313 
0314         udelay(1);
0315     }
0316 
0317     set_reg_field_value(select, filter_type, SCLV_COEF_RAM_SELECT, SCL_C_RAM_FILTER_TYPE);
0318 
0319     for (phase = 0; phase < phases_to_program; phase++) {
0320         /*we always program N/2 + 1 phases, total phases N, but N/2-1 are just mirror
0321         phase 0 is unique and phase N/2 is unique if N is even*/
0322         set_reg_field_value(select, phase, SCLV_COEF_RAM_SELECT, SCL_C_RAM_PHASE);
0323         for (pair = 0; pair < taps_pairs; pair++) {
0324             uint32_t data = 0;
0325 
0326             set_reg_field_value(select, pair,
0327                     SCLV_COEF_RAM_SELECT, SCL_C_RAM_TAP_PAIR_IDX);
0328 
0329             dm_write_reg(ctx, mmSCLV_COEF_RAM_SELECT, select);
0330 
0331             set_reg_field_value(
0332                     data, 1,
0333                     SCLV_COEF_RAM_TAP_DATA,
0334                     SCL_C_RAM_EVEN_TAP_COEF_EN);
0335             set_reg_field_value(
0336                     data, coeffs[array_idx],
0337                     SCLV_COEF_RAM_TAP_DATA,
0338                     SCL_C_RAM_EVEN_TAP_COEF);
0339 
0340             if (taps % 2 && pair == taps_pairs - 1) {
0341                 set_reg_field_value(
0342                         data, 0,
0343                         SCLV_COEF_RAM_TAP_DATA,
0344                         SCL_C_RAM_ODD_TAP_COEF_EN);
0345                 array_idx++;
0346             } else {
0347                 set_reg_field_value(
0348                         data, 1,
0349                         SCLV_COEF_RAM_TAP_DATA,
0350                         SCL_C_RAM_ODD_TAP_COEF_EN);
0351                 set_reg_field_value(
0352                         data, coeffs[array_idx + 1],
0353                         SCLV_COEF_RAM_TAP_DATA,
0354                         SCL_C_RAM_ODD_TAP_COEF);
0355 
0356                 array_idx += 2;
0357             }
0358 
0359             dm_write_reg(ctx, mmSCLV_COEF_RAM_TAP_DATA, data);
0360         }
0361     }
0362 
0363     /*We need to restore power gating on coeff memory to initial state*/
0364     dm_write_reg(ctx, mmDCFEV_MEM_PWR_CTRL, power_ctl);
0365 }
0366 
0367 static void calculate_inits(
0368     struct dce_transform *xfm_dce,
0369     const struct scaler_data *data,
0370     struct sclv_ratios_inits *inits,
0371     struct rect *luma_viewport,
0372     struct rect *chroma_viewport)
0373 {
0374     inits->h_int_scale_ratio_luma =
0375         dc_fixpt_u2d19(data->ratios.horz) << 5;
0376     inits->v_int_scale_ratio_luma =
0377         dc_fixpt_u2d19(data->ratios.vert) << 5;
0378     inits->h_int_scale_ratio_chroma =
0379         dc_fixpt_u2d19(data->ratios.horz_c) << 5;
0380     inits->v_int_scale_ratio_chroma =
0381         dc_fixpt_u2d19(data->ratios.vert_c) << 5;
0382 
0383     inits->h_init_luma.integer = 1;
0384     inits->v_init_luma.integer = 1;
0385     inits->h_init_chroma.integer = 1;
0386     inits->v_init_chroma.integer = 1;
0387 }
0388 
0389 static void program_scl_ratios_inits(
0390     struct dce_transform *xfm_dce,
0391     struct sclv_ratios_inits *inits)
0392 {
0393     struct dc_context *ctx = xfm_dce->base.ctx;
0394     uint32_t addr = mmSCLV_HORZ_FILTER_SCALE_RATIO;
0395     uint32_t value = 0;
0396 
0397     set_reg_field_value(
0398         value,
0399         inits->h_int_scale_ratio_luma,
0400         SCLV_HORZ_FILTER_SCALE_RATIO,
0401         SCL_H_SCALE_RATIO);
0402     dm_write_reg(ctx, addr, value);
0403 
0404     addr = mmSCLV_VERT_FILTER_SCALE_RATIO;
0405     value = 0;
0406     set_reg_field_value(
0407         value,
0408         inits->v_int_scale_ratio_luma,
0409         SCLV_VERT_FILTER_SCALE_RATIO,
0410         SCL_V_SCALE_RATIO);
0411     dm_write_reg(ctx, addr, value);
0412 
0413     addr = mmSCLV_HORZ_FILTER_SCALE_RATIO_C;
0414     value = 0;
0415     set_reg_field_value(
0416         value,
0417         inits->h_int_scale_ratio_chroma,
0418         SCLV_HORZ_FILTER_SCALE_RATIO_C,
0419         SCL_H_SCALE_RATIO_C);
0420     dm_write_reg(ctx, addr, value);
0421 
0422     addr = mmSCLV_VERT_FILTER_SCALE_RATIO_C;
0423     value = 0;
0424     set_reg_field_value(
0425         value,
0426         inits->v_int_scale_ratio_chroma,
0427         SCLV_VERT_FILTER_SCALE_RATIO_C,
0428         SCL_V_SCALE_RATIO_C);
0429     dm_write_reg(ctx, addr, value);
0430 
0431     addr = mmSCLV_HORZ_FILTER_INIT;
0432     value = 0;
0433     set_reg_field_value(
0434         value,
0435         inits->h_init_luma.fraction,
0436         SCLV_HORZ_FILTER_INIT,
0437         SCL_H_INIT_FRAC);
0438     set_reg_field_value(
0439         value,
0440         inits->h_init_luma.integer,
0441         SCLV_HORZ_FILTER_INIT,
0442         SCL_H_INIT_INT);
0443     dm_write_reg(ctx, addr, value);
0444 
0445     addr = mmSCLV_VERT_FILTER_INIT;
0446     value = 0;
0447     set_reg_field_value(
0448         value,
0449         inits->v_init_luma.fraction,
0450         SCLV_VERT_FILTER_INIT,
0451         SCL_V_INIT_FRAC);
0452     set_reg_field_value(
0453         value,
0454         inits->v_init_luma.integer,
0455         SCLV_VERT_FILTER_INIT,
0456         SCL_V_INIT_INT);
0457     dm_write_reg(ctx, addr, value);
0458 
0459     addr = mmSCLV_HORZ_FILTER_INIT_C;
0460     value = 0;
0461     set_reg_field_value(
0462         value,
0463         inits->h_init_chroma.fraction,
0464         SCLV_HORZ_FILTER_INIT_C,
0465         SCL_H_INIT_FRAC_C);
0466     set_reg_field_value(
0467         value,
0468         inits->h_init_chroma.integer,
0469         SCLV_HORZ_FILTER_INIT_C,
0470         SCL_H_INIT_INT_C);
0471     dm_write_reg(ctx, addr, value);
0472 
0473     addr = mmSCLV_VERT_FILTER_INIT_C;
0474     value = 0;
0475     set_reg_field_value(
0476         value,
0477         inits->v_init_chroma.fraction,
0478         SCLV_VERT_FILTER_INIT_C,
0479         SCL_V_INIT_FRAC_C);
0480     set_reg_field_value(
0481         value,
0482         inits->v_init_chroma.integer,
0483         SCLV_VERT_FILTER_INIT_C,
0484         SCL_V_INIT_INT_C);
0485     dm_write_reg(ctx, addr, value);
0486 }
0487 
0488 static const uint16_t *get_filter_coeffs_64p(int taps, struct fixed31_32 ratio)
0489 {
0490     if (taps == 4)
0491         return get_filter_4tap_64p(ratio);
0492     else if (taps == 2)
0493         return get_filter_2tap_64p();
0494     else if (taps == 1)
0495         return NULL;
0496     else {
0497         /* should never happen, bug */
0498         BREAK_TO_DEBUGGER();
0499         return NULL;
0500     }
0501 }
0502 
0503 static bool dce110_xfmv_power_up_line_buffer(struct transform *xfm)
0504 {
0505     struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
0506     uint32_t value;
0507 
0508     value = dm_read_reg(xfm_dce->base.ctx, mmLBV_MEMORY_CTRL);
0509 
0510     /*Use all three pieces of memory always*/
0511     set_reg_field_value(value, 0, LBV_MEMORY_CTRL, LB_MEMORY_CONFIG);
0512     /*hard coded number DCE11 1712(0x6B0) Partitions: 720/960/1712*/
0513     set_reg_field_value(value, xfm_dce->lb_memory_size, LBV_MEMORY_CTRL,
0514             LB_MEMORY_SIZE);
0515 
0516     dm_write_reg(xfm_dce->base.ctx, mmLBV_MEMORY_CTRL, value);
0517 
0518     return true;
0519 }
0520 
0521 static void dce110_xfmv_set_scaler(
0522     struct transform *xfm,
0523     const struct scaler_data *data)
0524 {
0525     struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
0526     bool is_scaling_required = false;
0527     bool filter_updated = false;
0528     const uint16_t *coeffs_v, *coeffs_h, *coeffs_h_c, *coeffs_v_c;
0529     struct rect luma_viewport = {0};
0530     struct rect chroma_viewport = {0};
0531 
0532     dce110_xfmv_power_up_line_buffer(xfm);
0533     /* 1. Calculate viewport, viewport programming should happen after init
0534      * calculations as they may require an adjustment in the viewport.
0535      */
0536 
0537     calculate_viewport(data, &luma_viewport, &chroma_viewport);
0538 
0539     /* 2. Program overscan */
0540     program_overscan(xfm_dce, data);
0541 
0542     /* 3. Program taps and configuration */
0543     is_scaling_required = setup_scaling_configuration(xfm_dce, data);
0544 
0545     if (is_scaling_required) {
0546         /* 4. Calculate and program ratio, filter initialization */
0547 
0548         struct sclv_ratios_inits inits = { 0 };
0549 
0550         calculate_inits(
0551             xfm_dce,
0552             data,
0553             &inits,
0554             &luma_viewport,
0555             &chroma_viewport);
0556 
0557         program_scl_ratios_inits(xfm_dce, &inits);
0558 
0559         coeffs_v = get_filter_coeffs_64p(data->taps.v_taps, data->ratios.vert);
0560         coeffs_h = get_filter_coeffs_64p(data->taps.h_taps, data->ratios.horz);
0561         coeffs_v_c = get_filter_coeffs_64p(data->taps.v_taps_c, data->ratios.vert_c);
0562         coeffs_h_c = get_filter_coeffs_64p(data->taps.h_taps_c, data->ratios.horz_c);
0563 
0564         if (coeffs_v != xfm_dce->filter_v
0565                 || coeffs_v_c != xfm_dce->filter_v_c
0566                 || coeffs_h != xfm_dce->filter_h
0567                 || coeffs_h_c != xfm_dce->filter_h_c) {
0568         /* 5. Program vertical filters */
0569             program_multi_taps_filter(
0570                     xfm_dce,
0571                     data->taps.v_taps,
0572                     coeffs_v,
0573                     FILTER_TYPE_RGB_Y_VERTICAL);
0574             program_multi_taps_filter(
0575                     xfm_dce,
0576                     data->taps.v_taps_c,
0577                     coeffs_v_c,
0578                     FILTER_TYPE_CBCR_VERTICAL);
0579 
0580         /* 6. Program horizontal filters */
0581             program_multi_taps_filter(
0582                     xfm_dce,
0583                     data->taps.h_taps,
0584                     coeffs_h,
0585                     FILTER_TYPE_RGB_Y_HORIZONTAL);
0586             program_multi_taps_filter(
0587                     xfm_dce,
0588                     data->taps.h_taps_c,
0589                     coeffs_h_c,
0590                     FILTER_TYPE_CBCR_HORIZONTAL);
0591 
0592             xfm_dce->filter_v = coeffs_v;
0593             xfm_dce->filter_v_c = coeffs_v_c;
0594             xfm_dce->filter_h = coeffs_h;
0595             xfm_dce->filter_h_c = coeffs_h_c;
0596             filter_updated = true;
0597         }
0598     }
0599 
0600     /* 7. Program the viewport */
0601     program_viewport(xfm_dce, &luma_viewport, &chroma_viewport);
0602 
0603     /* 8. Set bit to flip to new coefficient memory */
0604     if (filter_updated)
0605         set_coeff_update_complete(xfm_dce);
0606 }
0607 
0608 static void dce110_xfmv_reset(struct transform *xfm)
0609 {
0610     struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
0611 
0612     xfm_dce->filter_h = NULL;
0613     xfm_dce->filter_v = NULL;
0614     xfm_dce->filter_h_c = NULL;
0615     xfm_dce->filter_v_c = NULL;
0616 }
0617 
0618 static void dce110_xfmv_set_gamut_remap(
0619     struct transform *xfm,
0620     const struct xfm_grph_csc_adjustment *adjust)
0621 {
0622     /* DO NOTHING*/
0623 }
0624 
0625 static void dce110_xfmv_set_pixel_storage_depth(
0626     struct transform *xfm,
0627     enum lb_pixel_depth depth,
0628     const struct bit_depth_reduction_params *bit_depth_params)
0629 {
0630     struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
0631     int pixel_depth = 0;
0632     int expan_mode = 0;
0633     uint32_t reg_data = 0;
0634 
0635     switch (depth) {
0636     case LB_PIXEL_DEPTH_18BPP:
0637         pixel_depth = 2;
0638         expan_mode  = 1;
0639         break;
0640     case LB_PIXEL_DEPTH_24BPP:
0641         pixel_depth = 1;
0642         expan_mode  = 1;
0643         break;
0644     case LB_PIXEL_DEPTH_30BPP:
0645         pixel_depth = 0;
0646         expan_mode  = 1;
0647         break;
0648     case LB_PIXEL_DEPTH_36BPP:
0649         pixel_depth = 3;
0650         expan_mode  = 0;
0651         break;
0652     default:
0653         BREAK_TO_DEBUGGER();
0654         break;
0655     }
0656 
0657     set_reg_field_value(
0658         reg_data,
0659         expan_mode,
0660         LBV_DATA_FORMAT,
0661         PIXEL_EXPAN_MODE);
0662 
0663     set_reg_field_value(
0664         reg_data,
0665         pixel_depth,
0666         LBV_DATA_FORMAT,
0667         PIXEL_DEPTH);
0668 
0669     dm_write_reg(xfm->ctx, mmLBV_DATA_FORMAT, reg_data);
0670 
0671     if (!(xfm_dce->lb_pixel_depth_supported & depth)) {
0672         /*we should use unsupported capabilities
0673          *  unless it is required by w/a*/
0674         DC_LOG_WARNING("%s: Capability not supported",
0675             __func__);
0676     }
0677 }
0678 
0679 static const struct transform_funcs dce110_xfmv_funcs = {
0680     .transform_reset = dce110_xfmv_reset,
0681     .transform_set_scaler = dce110_xfmv_set_scaler,
0682     .transform_set_gamut_remap =
0683         dce110_xfmv_set_gamut_remap,
0684     .opp_set_csc_default = dce110_opp_v_set_csc_default,
0685     .opp_set_csc_adjustment = dce110_opp_v_set_csc_adjustment,
0686     .opp_power_on_regamma_lut = dce110_opp_power_on_regamma_lut_v,
0687     .opp_program_regamma_pwl = dce110_opp_program_regamma_pwl_v,
0688     .opp_set_regamma_mode = dce110_opp_set_regamma_mode_v,
0689     .transform_set_pixel_storage_depth =
0690             dce110_xfmv_set_pixel_storage_depth,
0691     .transform_get_optimal_number_of_taps =
0692         dce_transform_get_optimal_number_of_taps
0693 };
0694 /*****************************************/
0695 /* Constructor, Destructor               */
0696 /*****************************************/
0697 
0698 bool dce110_transform_v_construct(
0699     struct dce_transform *xfm_dce,
0700     struct dc_context *ctx)
0701 {
0702     xfm_dce->base.ctx = ctx;
0703 
0704     xfm_dce->base.funcs = &dce110_xfmv_funcs;
0705 
0706     xfm_dce->lb_pixel_depth_supported =
0707             LB_PIXEL_DEPTH_18BPP |
0708             LB_PIXEL_DEPTH_24BPP |
0709             LB_PIXEL_DEPTH_30BPP |
0710             LB_PIXEL_DEPTH_36BPP;
0711 
0712     xfm_dce->prescaler_on = true;
0713     xfm_dce->lb_bits_per_entry = LB_BITS_PER_ENTRY;
0714     xfm_dce->lb_memory_size = LB_TOTAL_NUMBER_OF_ENTRIES; /*0x6B0*/
0715 
0716     return true;
0717 }