cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

dce110_transform_v.c (19246B)


      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			LB_PIXEL_DEPTH_36BPP;
    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}