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