xref: /netbsd-src/sys/external/bsd/drm2/dist/drm/amd/display/dc/dce110/amdgpu_dce110_transform_v.c (revision 41ec02673d281bbb3d38e6c78504ce6e30c228c1)
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 
calculate_viewport(const struct scaler_data * scl_data,struct rect * luma_viewport,struct rect * chroma_viewport)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 
program_viewport(struct dce_transform * xfm_dce,struct rect * luma_view_port,struct rect * chroma_view_port)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  */
setup_scaling_configuration(struct dce_transform * xfm_dce,const struct scaler_data * data)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 */
program_overscan(struct dce_transform * xfm_dce,const struct scaler_data * data)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 
set_coeff_update_complete(struct dce_transform * xfm_dce)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 
program_multi_taps_filter(struct dce_transform * xfm_dce,int taps,const uint16_t * coeffs,enum ram_filter_type filter_type)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 
calculate_inits(struct dce_transform * xfm_dce,const struct scaler_data * data,struct sclv_ratios_inits * inits,struct rect * luma_viewport,struct rect * chroma_viewport)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 
program_scl_ratios_inits(struct dce_transform * xfm_dce,struct sclv_ratios_inits * inits)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 
get_filter_coeffs_64p(int taps,struct fixed31_32 ratio)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 
dce110_xfmv_power_up_line_buffer(struct transform * xfm)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 
dce110_xfmv_set_scaler(struct transform * xfm,const struct scaler_data * data)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 
dce110_xfmv_reset(struct transform * xfm)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 
dce110_xfmv_set_gamut_remap(struct transform * xfm,const struct xfm_grph_csc_adjustment * adjust)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 
dce110_xfmv_set_pixel_storage_depth(struct transform * xfm,enum lb_pixel_depth depth,const struct bit_depth_reduction_params * bit_depth_params)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 
dce110_transform_v_construct(struct dce_transform * xfm_dce,struct dc_context * ctx)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