Home | History | Annotate | Line # | Download | only in dce110
      1 /*	$NetBSD: amdgpu_dce110_transform_v.c,v 1.2 2021/12/18 23:45:02 riastradh Exp $	*/
      2 
      3 /*
      4  * Copyright 2012-15 Advanced Micro Devices, Inc.
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a
      7  * copy of this software and associated documentation files (the "Software"),
      8  * to deal in the Software without restriction, including without limitation
      9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     10  * and/or sell copies of the Software, and to permit persons to whom the
     11  * Software is furnished to do so, subject to the following conditions:
     12  *
     13  * The above copyright notice and this permission notice shall be included in
     14  * all copies or substantial portions of the Software.
     15  *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     19  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
     20  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     21  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     22  * OTHER DEALINGS IN THE SOFTWARE.
     23  *
     24  * Authors: AMD
     25  *
     26  */
     27 
     28 #include <sys/cdefs.h>
     29 __KERNEL_RCSID(0, "$NetBSD: amdgpu_dce110_transform_v.c,v 1.2 2021/12/18 23:45:02 riastradh Exp $");
     30 
     31 #include <linux/delay.h>
     32 
     33 #include "dce110_transform_v.h"
     34 #include "dm_services.h"
     35 #include "dc.h"
     36 #include "dce/dce_11_0_d.h"
     37 #include "dce/dce_11_0_sh_mask.h"
     38 
     39 #define SCLV_PHASES 64
     40 #define DC_LOGGER \
     41 	xfm->ctx->logger
     42 
     43 struct sclv_ratios_inits {
     44 	uint32_t h_int_scale_ratio_luma;
     45 	uint32_t h_int_scale_ratio_chroma;
     46 	uint32_t v_int_scale_ratio_luma;
     47 	uint32_t v_int_scale_ratio_chroma;
     48 	struct init_int_and_frac h_init_luma;
     49 	struct init_int_and_frac h_init_chroma;
     50 	struct init_int_and_frac v_init_luma;
     51 	struct init_int_and_frac v_init_chroma;
     52 };
     53 
     54 static void calculate_viewport(
     55 		const struct scaler_data *scl_data,
     56 		struct rect *luma_viewport,
     57 		struct rect *chroma_viewport)
     58 {
     59 	/*Do not set chroma vp for rgb444 pixel format*/
     60 	luma_viewport->x = scl_data->viewport.x - scl_data->viewport.x % 2;
     61 	luma_viewport->y = scl_data->viewport.y - scl_data->viewport.y % 2;
     62 	luma_viewport->width =
     63 		scl_data->viewport.width - scl_data->viewport.width % 2;
     64 	luma_viewport->height =
     65 		scl_data->viewport.height - scl_data->viewport.height % 2;
     66 	chroma_viewport->x = luma_viewport->x;
     67 	chroma_viewport->y = luma_viewport->y;
     68 	chroma_viewport->height = luma_viewport->height;
     69 	chroma_viewport->width = luma_viewport->width;
     70 
     71 	if (scl_data->format == PIXEL_FORMAT_420BPP8) {
     72 		luma_viewport->height += luma_viewport->height % 2;
     73 		luma_viewport->width += luma_viewport->width % 2;
     74 		/*for 420 video chroma is 1/4 the area of luma, scaled
     75 		 *vertically and horizontally
     76 		 */
     77 		chroma_viewport->x = luma_viewport->x / 2;
     78 		chroma_viewport->y = luma_viewport->y / 2;
     79 		chroma_viewport->height = luma_viewport->height / 2;
     80 		chroma_viewport->width = luma_viewport->width / 2;
     81 	}
     82 }
     83 
     84 static void program_viewport(
     85 	struct dce_transform *xfm_dce,
     86 	struct rect *luma_view_port,
     87 	struct rect *chroma_view_port)
     88 {
     89 	struct dc_context *ctx = xfm_dce->base.ctx;
     90 	uint32_t value = 0;
     91 	uint32_t addr = 0;
     92 
     93 	if (luma_view_port->width != 0 && luma_view_port->height != 0) {
     94 		addr = mmSCLV_VIEWPORT_START;
     95 		value = 0;
     96 		set_reg_field_value(
     97 			value,
     98 			luma_view_port->x,
     99 			SCLV_VIEWPORT_START,
    100 			VIEWPORT_X_START);
    101 		set_reg_field_value(
    102 			value,
    103 			luma_view_port->y,
    104 			SCLV_VIEWPORT_START,
    105 			VIEWPORT_Y_START);
    106 		dm_write_reg(ctx, addr, value);
    107 
    108 		addr = mmSCLV_VIEWPORT_SIZE;
    109 		value = 0;
    110 		set_reg_field_value(
    111 			value,
    112 			luma_view_port->height,
    113 			SCLV_VIEWPORT_SIZE,
    114 			VIEWPORT_HEIGHT);
    115 		set_reg_field_value(
    116 			value,
    117 			luma_view_port->width,
    118 			SCLV_VIEWPORT_SIZE,
    119 			VIEWPORT_WIDTH);
    120 		dm_write_reg(ctx, addr, value);
    121 	}
    122 
    123 	if (chroma_view_port->width != 0 && chroma_view_port->height != 0) {
    124 		addr = mmSCLV_VIEWPORT_START_C;
    125 		value = 0;
    126 		set_reg_field_value(
    127 			value,
    128 			chroma_view_port->x,
    129 			SCLV_VIEWPORT_START_C,
    130 			VIEWPORT_X_START_C);
    131 		set_reg_field_value(
    132 			value,
    133 			chroma_view_port->y,
    134 			SCLV_VIEWPORT_START_C,
    135 			VIEWPORT_Y_START_C);
    136 		dm_write_reg(ctx, addr, value);
    137 
    138 		addr = mmSCLV_VIEWPORT_SIZE_C;
    139 		value = 0;
    140 		set_reg_field_value(
    141 			value,
    142 			chroma_view_port->height,
    143 			SCLV_VIEWPORT_SIZE_C,
    144 			VIEWPORT_HEIGHT_C);
    145 		set_reg_field_value(
    146 			value,
    147 			chroma_view_port->width,
    148 			SCLV_VIEWPORT_SIZE_C,
    149 			VIEWPORT_WIDTH_C);
    150 		dm_write_reg(ctx, addr, value);
    151 	}
    152 }
    153 
    154 /*
    155  * Function:
    156  * void setup_scaling_configuration
    157  *
    158  * Purpose: setup scaling mode : bypass, RGb, YCbCr and nummber of taps
    159  * Input:   data
    160  *
    161  * Output:
    162  *  void
    163  */
    164 static bool setup_scaling_configuration(
    165 	struct dce_transform *xfm_dce,
    166 	const struct scaler_data *data)
    167 {
    168 	bool is_scaling_needed = false;
    169 	struct dc_context *ctx = xfm_dce->base.ctx;
    170 	uint32_t value = 0;
    171 
    172 	set_reg_field_value(value, data->taps.h_taps - 1,
    173 			SCLV_TAP_CONTROL, SCL_H_NUM_OF_TAPS);
    174 	set_reg_field_value(value, data->taps.v_taps - 1,
    175 			SCLV_TAP_CONTROL, SCL_V_NUM_OF_TAPS);
    176 	set_reg_field_value(value, data->taps.h_taps_c - 1,
    177 			SCLV_TAP_CONTROL, SCL_H_NUM_OF_TAPS_C);
    178 	set_reg_field_value(value, data->taps.v_taps_c - 1,
    179 			SCLV_TAP_CONTROL, SCL_V_NUM_OF_TAPS_C);
    180 	dm_write_reg(ctx, mmSCLV_TAP_CONTROL, value);
    181 
    182 	value = 0;
    183 	if (data->taps.h_taps + data->taps.v_taps > 2) {
    184 		set_reg_field_value(value, 1, SCLV_MODE, SCL_MODE);
    185 		set_reg_field_value(value, 1, SCLV_MODE, SCL_PSCL_EN);
    186 		is_scaling_needed = true;
    187 	} else {
    188 		set_reg_field_value(value, 0, SCLV_MODE, SCL_MODE);
    189 		set_reg_field_value(value, 0, SCLV_MODE, SCL_PSCL_EN);
    190 	}
    191 
    192 	if (data->taps.h_taps_c + data->taps.v_taps_c > 2) {
    193 		set_reg_field_value(value, 1, SCLV_MODE, SCL_MODE_C);
    194 		set_reg_field_value(value, 1, SCLV_MODE, SCL_PSCL_EN_C);
    195 		is_scaling_needed = true;
    196 	} else if (data->format != PIXEL_FORMAT_420BPP8) {
    197 		set_reg_field_value(
    198 			value,
    199 			get_reg_field_value(value, SCLV_MODE, SCL_MODE),
    200 			SCLV_MODE,
    201 			SCL_MODE_C);
    202 		set_reg_field_value(
    203 			value,
    204 			get_reg_field_value(value, SCLV_MODE, SCL_PSCL_EN),
    205 			SCLV_MODE,
    206 			SCL_PSCL_EN_C);
    207 	} else {
    208 		set_reg_field_value(value, 0, SCLV_MODE, SCL_MODE_C);
    209 		set_reg_field_value(value, 0, SCLV_MODE, SCL_PSCL_EN_C);
    210 	}
    211 	dm_write_reg(ctx, mmSCLV_MODE, value);
    212 
    213 	value = 0;
    214 	/*
    215 	 * 0 - Replaced out of bound pixels with black pixel
    216 	 * (or any other required color)
    217 	 * 1 - Replaced out of bound pixels with the edge pixel
    218 	 */
    219 	set_reg_field_value(value, 1, SCLV_CONTROL, SCL_BOUNDARY_MODE);
    220 	dm_write_reg(ctx, mmSCLV_CONTROL, value);
    221 
    222 	return is_scaling_needed;
    223 }
    224 
    225 /**
    226 * Function:
    227 * void program_overscan
    228 *
    229 * Purpose: Programs overscan border
    230 * Input:   overscan
    231 *
    232 * Output:
    233    void
    234 */
    235 static void program_overscan(
    236 		struct dce_transform *xfm_dce,
    237 		const struct scaler_data *data)
    238 {
    239 	uint32_t overscan_left_right = 0;
    240 	uint32_t overscan_top_bottom = 0;
    241 
    242 	int overscan_right = data->h_active - data->recout.x - data->recout.width;
    243 	int overscan_bottom = data->v_active - data->recout.y - data->recout.height;
    244 
    245 	if (xfm_dce->base.ctx->dc->debug.visual_confirm != VISUAL_CONFIRM_DISABLE) {
    246 		overscan_bottom += 2;
    247 		overscan_right += 2;
    248 	}
    249 
    250 	if (overscan_right < 0) {
    251 		BREAK_TO_DEBUGGER();
    252 		overscan_right = 0;
    253 	}
    254 	if (overscan_bottom < 0) {
    255 		BREAK_TO_DEBUGGER();
    256 		overscan_bottom = 0;
    257 	}
    258 
    259 	set_reg_field_value(overscan_left_right, data->recout.x,
    260 			EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_LEFT);
    261 
    262 	set_reg_field_value(overscan_left_right, overscan_right,
    263 			EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_RIGHT);
    264 
    265 	set_reg_field_value(overscan_top_bottom, data->recout.y,
    266 			EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_TOP);
    267 
    268 	set_reg_field_value(overscan_top_bottom, overscan_bottom,
    269 			EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_BOTTOM);
    270 
    271 	dm_write_reg(xfm_dce->base.ctx,
    272 			mmSCLV_EXT_OVERSCAN_LEFT_RIGHT,
    273 			overscan_left_right);
    274 
    275 	dm_write_reg(xfm_dce->base.ctx,
    276 			mmSCLV_EXT_OVERSCAN_TOP_BOTTOM,
    277 			overscan_top_bottom);
    278 }
    279 
    280 static void set_coeff_update_complete(
    281 		struct dce_transform *xfm_dce)
    282 {
    283 	uint32_t value;
    284 
    285 	value = dm_read_reg(xfm_dce->base.ctx, mmSCLV_UPDATE);
    286 	set_reg_field_value(value, 1, SCLV_UPDATE, SCL_COEF_UPDATE_COMPLETE);
    287 	dm_write_reg(xfm_dce->base.ctx, mmSCLV_UPDATE, value);
    288 }
    289 
    290 static void program_multi_taps_filter(
    291 	struct dce_transform *xfm_dce,
    292 	int taps,
    293 	const uint16_t *coeffs,
    294 	enum ram_filter_type filter_type)
    295 {
    296 	struct dc_context *ctx = xfm_dce->base.ctx;
    297 	int i, phase, pair;
    298 	int array_idx = 0;
    299 	int taps_pairs = (taps + 1) / 2;
    300 	int phases_to_program = SCLV_PHASES / 2 + 1;
    301 
    302 	uint32_t select = 0;
    303 	uint32_t power_ctl, power_ctl_off;
    304 
    305 	if (!coeffs)
    306 		return;
    307 
    308 	/*We need to disable power gating on coeff memory to do programming*/
    309 	power_ctl = dm_read_reg(ctx, mmDCFEV_MEM_PWR_CTRL);
    310 	power_ctl_off = power_ctl;
    311 	set_reg_field_value(power_ctl_off, 1, DCFEV_MEM_PWR_CTRL, SCLV_COEFF_MEM_PWR_DIS);
    312 	dm_write_reg(ctx, mmDCFEV_MEM_PWR_CTRL, power_ctl_off);
    313 
    314 	/*Wait to disable gating:*/
    315 	for (i = 0; i < 10; i++) {
    316 		if (get_reg_field_value(
    317 				dm_read_reg(ctx, mmDCFEV_MEM_PWR_STATUS),
    318 				DCFEV_MEM_PWR_STATUS,
    319 				SCLV_COEFF_MEM_PWR_STATE) == 0)
    320 			break;
    321 
    322 		udelay(1);
    323 	}
    324 
    325 	set_reg_field_value(select, filter_type, SCLV_COEF_RAM_SELECT, SCL_C_RAM_FILTER_TYPE);
    326 
    327 	for (phase = 0; phase < phases_to_program; phase++) {
    328 		/*we always program N/2 + 1 phases, total phases N, but N/2-1 are just mirror
    329 		phase 0 is unique and phase N/2 is unique if N is even*/
    330 		set_reg_field_value(select, phase, SCLV_COEF_RAM_SELECT, SCL_C_RAM_PHASE);
    331 		for (pair = 0; pair < taps_pairs; pair++) {
    332 			uint32_t data = 0;
    333 
    334 			set_reg_field_value(select, pair,
    335 					SCLV_COEF_RAM_SELECT, SCL_C_RAM_TAP_PAIR_IDX);
    336 
    337 			dm_write_reg(ctx, mmSCLV_COEF_RAM_SELECT, select);
    338 
    339 			set_reg_field_value(
    340 					data, 1,
    341 					SCLV_COEF_RAM_TAP_DATA,
    342 					SCL_C_RAM_EVEN_TAP_COEF_EN);
    343 			set_reg_field_value(
    344 					data, coeffs[array_idx],
    345 					SCLV_COEF_RAM_TAP_DATA,
    346 					SCL_C_RAM_EVEN_TAP_COEF);
    347 
    348 			if (taps % 2 && pair == taps_pairs - 1) {
    349 				set_reg_field_value(
    350 						data, 0,
    351 						SCLV_COEF_RAM_TAP_DATA,
    352 						SCL_C_RAM_ODD_TAP_COEF_EN);
    353 				array_idx++;
    354 			} else {
    355 				set_reg_field_value(
    356 						data, 1,
    357 						SCLV_COEF_RAM_TAP_DATA,
    358 						SCL_C_RAM_ODD_TAP_COEF_EN);
    359 				set_reg_field_value(
    360 						data, coeffs[array_idx + 1],
    361 						SCLV_COEF_RAM_TAP_DATA,
    362 						SCL_C_RAM_ODD_TAP_COEF);
    363 
    364 				array_idx += 2;
    365 			}
    366 
    367 			dm_write_reg(ctx, mmSCLV_COEF_RAM_TAP_DATA, data);
    368 		}
    369 	}
    370 
    371 	/*We need to restore power gating on coeff memory to initial state*/
    372 	dm_write_reg(ctx, mmDCFEV_MEM_PWR_CTRL, power_ctl);
    373 }
    374 
    375 static void calculate_inits(
    376 	struct dce_transform *xfm_dce,
    377 	const struct scaler_data *data,
    378 	struct sclv_ratios_inits *inits,
    379 	struct rect *luma_viewport,
    380 	struct rect *chroma_viewport)
    381 {
    382 	inits->h_int_scale_ratio_luma =
    383 		dc_fixpt_u2d19(data->ratios.horz) << 5;
    384 	inits->v_int_scale_ratio_luma =
    385 		dc_fixpt_u2d19(data->ratios.vert) << 5;
    386 	inits->h_int_scale_ratio_chroma =
    387 		dc_fixpt_u2d19(data->ratios.horz_c) << 5;
    388 	inits->v_int_scale_ratio_chroma =
    389 		dc_fixpt_u2d19(data->ratios.vert_c) << 5;
    390 
    391 	inits->h_init_luma.integer = 1;
    392 	inits->v_init_luma.integer = 1;
    393 	inits->h_init_chroma.integer = 1;
    394 	inits->v_init_chroma.integer = 1;
    395 }
    396 
    397 static void program_scl_ratios_inits(
    398 	struct dce_transform *xfm_dce,
    399 	struct sclv_ratios_inits *inits)
    400 {
    401 	struct dc_context *ctx = xfm_dce->base.ctx;
    402 	uint32_t addr = mmSCLV_HORZ_FILTER_SCALE_RATIO;
    403 	uint32_t value = 0;
    404 
    405 	set_reg_field_value(
    406 		value,
    407 		inits->h_int_scale_ratio_luma,
    408 		SCLV_HORZ_FILTER_SCALE_RATIO,
    409 		SCL_H_SCALE_RATIO);
    410 	dm_write_reg(ctx, addr, value);
    411 
    412 	addr = mmSCLV_VERT_FILTER_SCALE_RATIO;
    413 	value = 0;
    414 	set_reg_field_value(
    415 		value,
    416 		inits->v_int_scale_ratio_luma,
    417 		SCLV_VERT_FILTER_SCALE_RATIO,
    418 		SCL_V_SCALE_RATIO);
    419 	dm_write_reg(ctx, addr, value);
    420 
    421 	addr = mmSCLV_HORZ_FILTER_SCALE_RATIO_C;
    422 	value = 0;
    423 	set_reg_field_value(
    424 		value,
    425 		inits->h_int_scale_ratio_chroma,
    426 		SCLV_HORZ_FILTER_SCALE_RATIO_C,
    427 		SCL_H_SCALE_RATIO_C);
    428 	dm_write_reg(ctx, addr, value);
    429 
    430 	addr = mmSCLV_VERT_FILTER_SCALE_RATIO_C;
    431 	value = 0;
    432 	set_reg_field_value(
    433 		value,
    434 		inits->v_int_scale_ratio_chroma,
    435 		SCLV_VERT_FILTER_SCALE_RATIO_C,
    436 		SCL_V_SCALE_RATIO_C);
    437 	dm_write_reg(ctx, addr, value);
    438 
    439 	addr = mmSCLV_HORZ_FILTER_INIT;
    440 	value = 0;
    441 	set_reg_field_value(
    442 		value,
    443 		inits->h_init_luma.fraction,
    444 		SCLV_HORZ_FILTER_INIT,
    445 		SCL_H_INIT_FRAC);
    446 	set_reg_field_value(
    447 		value,
    448 		inits->h_init_luma.integer,
    449 		SCLV_HORZ_FILTER_INIT,
    450 		SCL_H_INIT_INT);
    451 	dm_write_reg(ctx, addr, value);
    452 
    453 	addr = mmSCLV_VERT_FILTER_INIT;
    454 	value = 0;
    455 	set_reg_field_value(
    456 		value,
    457 		inits->v_init_luma.fraction,
    458 		SCLV_VERT_FILTER_INIT,
    459 		SCL_V_INIT_FRAC);
    460 	set_reg_field_value(
    461 		value,
    462 		inits->v_init_luma.integer,
    463 		SCLV_VERT_FILTER_INIT,
    464 		SCL_V_INIT_INT);
    465 	dm_write_reg(ctx, addr, value);
    466 
    467 	addr = mmSCLV_HORZ_FILTER_INIT_C;
    468 	value = 0;
    469 	set_reg_field_value(
    470 		value,
    471 		inits->h_init_chroma.fraction,
    472 		SCLV_HORZ_FILTER_INIT_C,
    473 		SCL_H_INIT_FRAC_C);
    474 	set_reg_field_value(
    475 		value,
    476 		inits->h_init_chroma.integer,
    477 		SCLV_HORZ_FILTER_INIT_C,
    478 		SCL_H_INIT_INT_C);
    479 	dm_write_reg(ctx, addr, value);
    480 
    481 	addr = mmSCLV_VERT_FILTER_INIT_C;
    482 	value = 0;
    483 	set_reg_field_value(
    484 		value,
    485 		inits->v_init_chroma.fraction,
    486 		SCLV_VERT_FILTER_INIT_C,
    487 		SCL_V_INIT_FRAC_C);
    488 	set_reg_field_value(
    489 		value,
    490 		inits->v_init_chroma.integer,
    491 		SCLV_VERT_FILTER_INIT_C,
    492 		SCL_V_INIT_INT_C);
    493 	dm_write_reg(ctx, addr, value);
    494 }
    495 
    496 static const uint16_t *get_filter_coeffs_64p(int taps, struct fixed31_32 ratio)
    497 {
    498 	if (taps == 4)
    499 		return get_filter_4tap_64p(ratio);
    500 	else if (taps == 2)
    501 		return get_filter_2tap_64p();
    502 	else if (taps == 1)
    503 		return NULL;
    504 	else {
    505 		/* should never happen, bug */
    506 		BREAK_TO_DEBUGGER();
    507 		return NULL;
    508 	}
    509 }
    510 
    511 static bool dce110_xfmv_power_up_line_buffer(struct transform *xfm)
    512 {
    513 	struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
    514 	uint32_t value;
    515 
    516 	value = dm_read_reg(xfm_dce->base.ctx, mmLBV_MEMORY_CTRL);
    517 
    518 	/*Use all three pieces of memory always*/
    519 	set_reg_field_value(value, 0, LBV_MEMORY_CTRL, LB_MEMORY_CONFIG);
    520 	/*hard coded number DCE11 1712(0x6B0) Partitions: 720/960/1712*/
    521 	set_reg_field_value(value, xfm_dce->lb_memory_size, LBV_MEMORY_CTRL,
    522 			LB_MEMORY_SIZE);
    523 
    524 	dm_write_reg(xfm_dce->base.ctx, mmLBV_MEMORY_CTRL, value);
    525 
    526 	return true;
    527 }
    528 
    529 static void dce110_xfmv_set_scaler(
    530 	struct transform *xfm,
    531 	const struct scaler_data *data)
    532 {
    533 	struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
    534 	bool is_scaling_required = false;
    535 	bool filter_updated = false;
    536 	const uint16_t *coeffs_v, *coeffs_h, *coeffs_h_c, *coeffs_v_c;
    537 	struct rect luma_viewport = {0};
    538 	struct rect chroma_viewport = {0};
    539 
    540 	dce110_xfmv_power_up_line_buffer(xfm);
    541 	/* 1. Calculate viewport, viewport programming should happen after init
    542 	 * calculations as they may require an adjustment in the viewport.
    543 	 */
    544 
    545 	calculate_viewport(data, &luma_viewport, &chroma_viewport);
    546 
    547 	/* 2. Program overscan */
    548 	program_overscan(xfm_dce, data);
    549 
    550 	/* 3. Program taps and configuration */
    551 	is_scaling_required = setup_scaling_configuration(xfm_dce, data);
    552 
    553 	if (is_scaling_required) {
    554 		/* 4. Calculate and program ratio, filter initialization */
    555 
    556 		struct sclv_ratios_inits inits = { 0 };
    557 
    558 		calculate_inits(
    559 			xfm_dce,
    560 			data,
    561 			&inits,
    562 			&luma_viewport,
    563 			&chroma_viewport);
    564 
    565 		program_scl_ratios_inits(xfm_dce, &inits);
    566 
    567 		coeffs_v = get_filter_coeffs_64p(data->taps.v_taps, data->ratios.vert);
    568 		coeffs_h = get_filter_coeffs_64p(data->taps.h_taps, data->ratios.horz);
    569 		coeffs_v_c = get_filter_coeffs_64p(data->taps.v_taps_c, data->ratios.vert_c);
    570 		coeffs_h_c = get_filter_coeffs_64p(data->taps.h_taps_c, data->ratios.horz_c);
    571 
    572 		if (coeffs_v != xfm_dce->filter_v
    573 				|| coeffs_v_c != xfm_dce->filter_v_c
    574 				|| coeffs_h != xfm_dce->filter_h
    575 				|| coeffs_h_c != xfm_dce->filter_h_c) {
    576 		/* 5. Program vertical filters */
    577 			program_multi_taps_filter(
    578 					xfm_dce,
    579 					data->taps.v_taps,
    580 					coeffs_v,
    581 					FILTER_TYPE_RGB_Y_VERTICAL);
    582 			program_multi_taps_filter(
    583 					xfm_dce,
    584 					data->taps.v_taps_c,
    585 					coeffs_v_c,
    586 					FILTER_TYPE_CBCR_VERTICAL);
    587 
    588 		/* 6. Program horizontal filters */
    589 			program_multi_taps_filter(
    590 					xfm_dce,
    591 					data->taps.h_taps,
    592 					coeffs_h,
    593 					FILTER_TYPE_RGB_Y_HORIZONTAL);
    594 			program_multi_taps_filter(
    595 					xfm_dce,
    596 					data->taps.h_taps_c,
    597 					coeffs_h_c,
    598 					FILTER_TYPE_CBCR_HORIZONTAL);
    599 
    600 			xfm_dce->filter_v = coeffs_v;
    601 			xfm_dce->filter_v_c = coeffs_v_c;
    602 			xfm_dce->filter_h = coeffs_h;
    603 			xfm_dce->filter_h_c = coeffs_h_c;
    604 			filter_updated = true;
    605 		}
    606 	}
    607 
    608 	/* 7. Program the viewport */
    609 	program_viewport(xfm_dce, &luma_viewport, &chroma_viewport);
    610 
    611 	/* 8. Set bit to flip to new coefficient memory */
    612 	if (filter_updated)
    613 		set_coeff_update_complete(xfm_dce);
    614 }
    615 
    616 static void dce110_xfmv_reset(struct transform *xfm)
    617 {
    618 	struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
    619 
    620 	xfm_dce->filter_h = NULL;
    621 	xfm_dce->filter_v = NULL;
    622 	xfm_dce->filter_h_c = NULL;
    623 	xfm_dce->filter_v_c = NULL;
    624 }
    625 
    626 static void dce110_xfmv_set_gamut_remap(
    627 	struct transform *xfm,
    628 	const struct xfm_grph_csc_adjustment *adjust)
    629 {
    630 	/* DO NOTHING*/
    631 }
    632 
    633 static void dce110_xfmv_set_pixel_storage_depth(
    634 	struct transform *xfm,
    635 	enum lb_pixel_depth depth,
    636 	const struct bit_depth_reduction_params *bit_depth_params)
    637 {
    638 	struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
    639 	int pixel_depth = 0;
    640 	int expan_mode = 0;
    641 	uint32_t reg_data = 0;
    642 
    643 	switch (depth) {
    644 	case LB_PIXEL_DEPTH_18BPP:
    645 		pixel_depth = 2;
    646 		expan_mode  = 1;
    647 		break;
    648 	case LB_PIXEL_DEPTH_24BPP:
    649 		pixel_depth = 1;
    650 		expan_mode  = 1;
    651 		break;
    652 	case LB_PIXEL_DEPTH_30BPP:
    653 		pixel_depth = 0;
    654 		expan_mode  = 1;
    655 		break;
    656 	case LB_PIXEL_DEPTH_36BPP:
    657 		pixel_depth = 3;
    658 		expan_mode  = 0;
    659 		break;
    660 	default:
    661 		BREAK_TO_DEBUGGER();
    662 		break;
    663 	}
    664 
    665 	set_reg_field_value(
    666 		reg_data,
    667 		expan_mode,
    668 		LBV_DATA_FORMAT,
    669 		PIXEL_EXPAN_MODE);
    670 
    671 	set_reg_field_value(
    672 		reg_data,
    673 		pixel_depth,
    674 		LBV_DATA_FORMAT,
    675 		PIXEL_DEPTH);
    676 
    677 	dm_write_reg(xfm->ctx, mmLBV_DATA_FORMAT, reg_data);
    678 
    679 	if (!(xfm_dce->lb_pixel_depth_supported & depth)) {
    680 		/*we should use unsupported capabilities
    681 		 *  unless it is required by w/a*/
    682 		DC_LOG_WARNING("%s: Capability not supported",
    683 			__func__);
    684 	}
    685 }
    686 
    687 static const struct transform_funcs dce110_xfmv_funcs = {
    688 	.transform_reset = dce110_xfmv_reset,
    689 	.transform_set_scaler = dce110_xfmv_set_scaler,
    690 	.transform_set_gamut_remap =
    691 		dce110_xfmv_set_gamut_remap,
    692 	.opp_set_csc_default = dce110_opp_v_set_csc_default,
    693 	.opp_set_csc_adjustment = dce110_opp_v_set_csc_adjustment,
    694 	.opp_power_on_regamma_lut = dce110_opp_power_on_regamma_lut_v,
    695 	.opp_program_regamma_pwl = dce110_opp_program_regamma_pwl_v,
    696 	.opp_set_regamma_mode = dce110_opp_set_regamma_mode_v,
    697 	.transform_set_pixel_storage_depth =
    698 			dce110_xfmv_set_pixel_storage_depth,
    699 	.transform_get_optimal_number_of_taps =
    700 		dce_transform_get_optimal_number_of_taps
    701 };
    702 /*****************************************/
    703 /* Constructor, Destructor               */
    704 /*****************************************/
    705 
    706 bool dce110_transform_v_construct(
    707 	struct dce_transform *xfm_dce,
    708 	struct dc_context *ctx)
    709 {
    710 	xfm_dce->base.ctx = ctx;
    711 
    712 	xfm_dce->base.funcs = &dce110_xfmv_funcs;
    713 
    714 	xfm_dce->lb_pixel_depth_supported =
    715 			LB_PIXEL_DEPTH_18BPP |
    716 			LB_PIXEL_DEPTH_24BPP |
    717 			LB_PIXEL_DEPTH_30BPP;
    718 
    719 	xfm_dce->prescaler_on = true;
    720 	xfm_dce->lb_bits_per_entry = LB_BITS_PER_ENTRY;
    721 	xfm_dce->lb_memory_size = LB_TOTAL_NUMBER_OF_ENTRIES; /*0x6B0*/
    722 
    723 	return true;
    724 }
    725