linux/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c
<<
>>
Prefs
   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
  38struct 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
  49static 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
  79static 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 */
 159static 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*/
 230static 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
 275static 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
 285static 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
 370static 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
 392static 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
 491static 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
 506static 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
 524static 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
 611static 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
 621static void dce110_xfmv_set_gamut_remap(
 622        struct transform *xfm,
 623        const struct xfm_grph_csc_adjustment *adjust)
 624{
 625        /* DO NOTHING*/
 626}
 627
 628static 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
 682static 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
 701bool 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}
 720