1 /*
2  * Copyright 2016 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 "dm_services.h"
27 
28 #include "core_types.h"
29 
30 #include "reg_helper.h"
31 #include "dcn10_dpp.h"
32 #include "basics/conversion.h"
33 
34 #define NUM_PHASES    64
35 #define HORZ_MAX_TAPS 8
36 #define VERT_MAX_TAPS 8
37 
38 #define BLACK_OFFSET_RGB_Y 0x0
39 #define BLACK_OFFSET_CBCR  0x8000
40 
41 #define REG(reg)\
42 	xfm->tf_regs->reg
43 
44 #define CTX \
45 	xfm->base.ctx
46 
47 #undef FN
48 #define FN(reg_name, field_name) \
49 	xfm->tf_shift->field_name, xfm->tf_mask->field_name
50 
51 enum pixel_format_description {
52 	PIXEL_FORMAT_FIXED = 0,
53 	PIXEL_FORMAT_FIXED16,
54 	PIXEL_FORMAT_FLOAT
55 
56 };
57 
58 enum dcn10_coef_filter_type_sel {
59 	SCL_COEF_LUMA_VERT_FILTER = 0,
60 	SCL_COEF_LUMA_HORZ_FILTER = 1,
61 	SCL_COEF_CHROMA_VERT_FILTER = 2,
62 	SCL_COEF_CHROMA_HORZ_FILTER = 3,
63 	SCL_COEF_ALPHA_VERT_FILTER = 4,
64 	SCL_COEF_ALPHA_HORZ_FILTER = 5
65 };
66 
67 enum dscl_autocal_mode {
68 	AUTOCAL_MODE_OFF = 0,
69 
70 	/* Autocal calculate the scaling ratio and initial phase and the
71 	 * DSCL_MODE_SEL must be set to 1
72 	 */
73 	AUTOCAL_MODE_AUTOSCALE = 1,
74 	/* Autocal perform auto centering without replication and the
75 	 * DSCL_MODE_SEL must be set to 0
76 	 */
77 	AUTOCAL_MODE_AUTOCENTER = 2,
78 	/* Autocal perform auto centering and auto replication and the
79 	 * DSCL_MODE_SEL must be set to 0
80 	 */
81 	AUTOCAL_MODE_AUTOREPLICATE = 3
82 };
83 
84 enum dscl_mode_sel {
85 	DSCL_MODE_SCALING_444_BYPASS = 0,
86 	DSCL_MODE_SCALING_444_RGB_ENABLE = 1,
87 	DSCL_MODE_SCALING_444_YCBCR_ENABLE = 2,
88 	DSCL_MODE_SCALING_420_YCBCR_ENABLE = 3,
89 	DSCL_MODE_SCALING_420_LUMA_BYPASS = 4,
90 	DSCL_MODE_SCALING_420_CHROMA_BYPASS = 5,
91 	DSCL_MODE_DSCL_BYPASS = 6
92 };
93 
94 enum gamut_remap_select {
95 	GAMUT_REMAP_BYPASS = 0,
96 	GAMUT_REMAP_COEFF,
97 	GAMUT_REMAP_COMA_COEFF,
98 	GAMUT_REMAP_COMB_COEFF
99 };
100 
101 /* Program gamut remap in bypass mode */
102 void dpp_set_gamut_remap_bypass(struct dcn10_dpp *xfm)
103 {
104 	REG_SET(CM_GAMUT_REMAP_CONTROL, 0,
105 			CM_GAMUT_REMAP_MODE, 0);
106 	/* Gamut remap in bypass */
107 }
108 
109 #define IDENTITY_RATIO(ratio) (dal_fixed31_32_u2d19(ratio) == (1 << 19))
110 
111 
112 bool dpp_get_optimal_number_of_taps(
113 		struct transform *xfm,
114 		struct scaler_data *scl_data,
115 		const struct scaling_taps *in_taps)
116 {
117 	uint32_t pixel_width;
118 
119 	if (scl_data->viewport.width > scl_data->recout.width)
120 		pixel_width = scl_data->recout.width;
121 	else
122 		pixel_width = scl_data->viewport.width;
123 
124 	/* TODO: add lb check */
125 
126 	/* No support for programming ratio of 4, drop to 3.99999.. */
127 	if (scl_data->ratios.horz.value == (4ll << 32))
128 		scl_data->ratios.horz.value--;
129 	if (scl_data->ratios.vert.value == (4ll << 32))
130 		scl_data->ratios.vert.value--;
131 	if (scl_data->ratios.horz_c.value == (4ll << 32))
132 		scl_data->ratios.horz_c.value--;
133 	if (scl_data->ratios.vert_c.value == (4ll << 32))
134 		scl_data->ratios.vert_c.value--;
135 
136 	/* Set default taps if none are provided */
137 	if (in_taps->h_taps == 0)
138 		scl_data->taps.h_taps = 4;
139 	else
140 		scl_data->taps.h_taps = in_taps->h_taps;
141 	if (in_taps->v_taps == 0)
142 		scl_data->taps.v_taps = 4;
143 	else
144 		scl_data->taps.v_taps = in_taps->v_taps;
145 	if (in_taps->v_taps_c == 0)
146 		scl_data->taps.v_taps_c = 2;
147 	else
148 		scl_data->taps.v_taps_c = in_taps->v_taps_c;
149 	if (in_taps->h_taps_c == 0)
150 		scl_data->taps.h_taps_c = 2;
151 	/* Only 1 and even h_taps_c are supported by hw */
152 	else if ((in_taps->h_taps_c % 2) != 0 && in_taps->h_taps_c != 1)
153 		scl_data->taps.h_taps_c = in_taps->h_taps_c - 1;
154 	else
155 		scl_data->taps.h_taps_c = in_taps->h_taps_c;
156 
157 	if (!xfm->ctx->dc->debug.always_scale) {
158 		if (IDENTITY_RATIO(scl_data->ratios.horz))
159 			scl_data->taps.h_taps = 1;
160 		if (IDENTITY_RATIO(scl_data->ratios.vert))
161 			scl_data->taps.v_taps = 1;
162 		if (IDENTITY_RATIO(scl_data->ratios.horz_c))
163 			scl_data->taps.h_taps_c = 1;
164 		if (IDENTITY_RATIO(scl_data->ratios.vert_c))
165 			scl_data->taps.v_taps_c = 1;
166 	}
167 
168 	return true;
169 }
170 
171 void dpp_reset(struct transform *xfm_base)
172 {
173 	struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base);
174 
175 	xfm->filter_h_c = NULL;
176 	xfm->filter_v_c = NULL;
177 	xfm->filter_h = NULL;
178 	xfm->filter_v = NULL;
179 
180 	/* set boundary mode to 0 */
181 	REG_SET(DSCL_CONTROL, 0, SCL_BOUNDARY_MODE, 0);
182 }
183 
184 
185 
186 static bool dcn10_dpp_cm_set_regamma_pwl(
187 	struct transform *xfm_base, const struct pwl_params *params)
188 {
189 	struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base);
190 
191 	dcn10_dpp_cm_power_on_regamma_lut(xfm_base, true);
192 	dcn10_dpp_cm_configure_regamma_lut(xfm_base, xfm->is_write_to_ram_a_safe);
193 
194 	if (xfm->is_write_to_ram_a_safe)
195 		dcn10_dpp_cm_program_regamma_luta_settings(xfm_base, params);
196 	else
197 		dcn10_dpp_cm_program_regamma_lutb_settings(xfm_base, params);
198 
199 	dcn10_dpp_cm_program_regamma_lut(
200 			xfm_base, params->rgb_resulted, params->hw_points_num);
201 
202 	return true;
203 }
204 
205 static void dcn10_dpp_cm_set_regamma_mode(
206 	struct transform *xfm_base,
207 	enum opp_regamma mode)
208 {
209 	struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base);
210 	uint32_t re_mode = 0;
211 	uint32_t obuf_bypass = 0; /* need for pipe split */
212 	uint32_t obuf_hupscale = 0;
213 
214 	switch (mode) {
215 	case OPP_REGAMMA_BYPASS:
216 		re_mode = 0;
217 		break;
218 	case OPP_REGAMMA_SRGB:
219 		re_mode = 1;
220 		break;
221 	case OPP_REGAMMA_3_6:
222 		re_mode = 2;
223 		break;
224 	case OPP_REGAMMA_USER:
225 		re_mode = xfm->is_write_to_ram_a_safe ? 3 : 4;
226 		xfm->is_write_to_ram_a_safe = !xfm->is_write_to_ram_a_safe;
227 		break;
228 	default:
229 		break;
230 	}
231 
232 	REG_SET(CM_RGAM_CONTROL, 0, CM_RGAM_LUT_MODE, re_mode);
233 	REG_UPDATE_2(OBUF_CONTROL,
234 			OBUF_BYPASS, obuf_bypass,
235 			OBUF_H_2X_UPSCALE_EN, obuf_hupscale);
236 }
237 
238 static void ippn10_setup_format_flags(enum surface_pixel_format input_format,\
239 						enum pixel_format_description *fmt)
240 {
241 
242 	if (input_format == SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F ||
243 		input_format == SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F)
244 		*fmt = PIXEL_FORMAT_FLOAT;
245 	else if (input_format == SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616)
246 		*fmt = PIXEL_FORMAT_FIXED16;
247 	else
248 		*fmt = PIXEL_FORMAT_FIXED;
249 }
250 
251 static void ippn10_set_degamma_format_float(
252 		struct transform *xfm_base,
253 		bool is_float)
254 {
255 	struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base);
256 
257 	if (is_float) {
258 		REG_UPDATE(CM_IGAM_CONTROL, CM_IGAM_INPUT_FORMAT, 3);
259 		REG_UPDATE(CM_IGAM_CONTROL, CM_IGAM_LUT_MODE, 1);
260 	} else {
261 		REG_UPDATE(CM_IGAM_CONTROL, CM_IGAM_INPUT_FORMAT, 2);
262 		REG_UPDATE(CM_IGAM_CONTROL, CM_IGAM_LUT_MODE, 0);
263 	}
264 }
265 
266 void ippn10_cnv_setup (
267 		struct transform *xfm_base,
268 		enum surface_pixel_format input_format,
269 		enum expansion_mode mode)
270 {
271 	uint32_t pixel_format;
272 	uint32_t alpha_en;
273 	enum pixel_format_description fmt ;
274 	enum dc_color_space color_space;
275 	enum dcn10_input_csc_select select;
276 	bool is_float;
277 	struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base);
278 	bool force_disable_cursor = false;
279 
280 	ippn10_setup_format_flags(input_format, &fmt);
281 	alpha_en = 1;
282 	pixel_format = 0;
283 	color_space = COLOR_SPACE_SRGB;
284 	select = INPUT_CSC_SELECT_BYPASS;
285 	is_float = false;
286 
287 	switch (fmt) {
288 	case PIXEL_FORMAT_FIXED:
289 	case PIXEL_FORMAT_FIXED16:
290 	/*when output is float then FORMAT_CONTROL__OUTPUT_FP=1*/
291 		REG_SET_3(FORMAT_CONTROL, 0,
292 			CNVC_BYPASS, 0,
293 			FORMAT_EXPANSION_MODE, mode,
294 			OUTPUT_FP, 0);
295 		break;
296 	case PIXEL_FORMAT_FLOAT:
297 		REG_SET_3(FORMAT_CONTROL, 0,
298 			CNVC_BYPASS, 0,
299 			FORMAT_EXPANSION_MODE, mode,
300 			OUTPUT_FP, 1);
301 		is_float = true;
302 		break;
303 	default:
304 
305 		break;
306 	}
307 
308 	ippn10_set_degamma_format_float(xfm_base, is_float);
309 
310 	switch (input_format) {
311 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555:
312 		pixel_format = 1;
313 		break;
314 	case SURFACE_PIXEL_FORMAT_GRPH_RGB565:
315 		pixel_format = 3;
316 		alpha_en = 0;
317 		break;
318 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:
319 	case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888:
320 		pixel_format = 8;
321 		break;
322 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010:
323 	case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010:
324 		pixel_format = 10;
325 		break;
326 	case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr:
327 		force_disable_cursor = false;
328 		pixel_format = 65;
329 		color_space = COLOR_SPACE_YCBCR709;
330 		select = INPUT_CSC_SELECT_ICSC;
331 		break;
332 	case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb:
333 		force_disable_cursor = true;
334 		pixel_format = 64;
335 		color_space = COLOR_SPACE_YCBCR709;
336 		select = INPUT_CSC_SELECT_ICSC;
337 		break;
338 	case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr:
339 		force_disable_cursor = true;
340 		pixel_format = 67;
341 		color_space = COLOR_SPACE_YCBCR709;
342 		select = INPUT_CSC_SELECT_ICSC;
343 		break;
344 	case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb:
345 		force_disable_cursor = true;
346 		pixel_format = 66;
347 		color_space = COLOR_SPACE_YCBCR709;
348 		select = INPUT_CSC_SELECT_ICSC;
349 		break;
350 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
351 		pixel_format = 22;
352 		break;
353 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F:
354 		pixel_format = 24;
355 		break;
356 	case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
357 		pixel_format = 25;
358 		break;
359 	default:
360 		break;
361 	}
362 	REG_SET(CNVC_SURFACE_PIXEL_FORMAT, 0,
363 			CNVC_SURFACE_PIXEL_FORMAT, pixel_format);
364 	REG_UPDATE(FORMAT_CONTROL, FORMAT_CONTROL__ALPHA_EN, alpha_en);
365 
366 	ippn10_program_input_csc(xfm_base, color_space, select);
367 
368 	if (force_disable_cursor) {
369 		REG_UPDATE(CURSOR_CONTROL,
370 				CURSOR_ENABLE, 0);
371 		REG_UPDATE(CURSOR0_CONTROL,
372 				CUR0_ENABLE, 0);
373 	}
374 }
375 
376 static struct transform_funcs dcn10_dpp_funcs = {
377 		.transform_reset = dpp_reset,
378 		.transform_set_scaler = dcn10_dpp_dscl_set_scaler_manual_scale,
379 		.transform_get_optimal_number_of_taps = dpp_get_optimal_number_of_taps,
380 		.transform_set_gamut_remap = dcn10_dpp_cm_set_gamut_remap,
381 		.opp_set_csc_adjustment = dcn10_dpp_cm_set_output_csc_adjustment,
382 		.opp_set_csc_default = dcn10_dpp_cm_set_output_csc_default,
383 		.opp_power_on_regamma_lut = dcn10_dpp_cm_power_on_regamma_lut,
384 		.opp_program_regamma_lut = dcn10_dpp_cm_program_regamma_lut,
385 		.opp_configure_regamma_lut = dcn10_dpp_cm_configure_regamma_lut,
386 		.opp_program_regamma_lutb_settings = dcn10_dpp_cm_program_regamma_lutb_settings,
387 		.opp_program_regamma_luta_settings = dcn10_dpp_cm_program_regamma_luta_settings,
388 		.opp_program_regamma_pwl = dcn10_dpp_cm_set_regamma_pwl,
389 		.opp_set_regamma_mode = dcn10_dpp_cm_set_regamma_mode,
390 		.ipp_set_degamma = ippn10_set_degamma,
391 		.ipp_program_input_lut		= ippn10_program_input_lut,
392 		.ipp_program_degamma_pwl	= ippn10_set_degamma_pwl,
393 		.ipp_setup			= ippn10_cnv_setup,
394 		.ipp_full_bypass		= ippn10_full_bypass,
395 };
396 
397 
398 /*****************************************/
399 /* Constructor, Destructor               */
400 /*****************************************/
401 
402 bool dcn10_dpp_construct(
403 	struct dcn10_dpp *xfm,
404 	struct dc_context *ctx,
405 	uint32_t inst,
406 	const struct dcn_dpp_registers *tf_regs,
407 	const struct dcn_dpp_shift *tf_shift,
408 	const struct dcn_dpp_mask *tf_mask)
409 {
410 	xfm->base.ctx = ctx;
411 
412 	xfm->base.inst = inst;
413 	xfm->base.funcs = &dcn10_dpp_funcs;
414 
415 	xfm->tf_regs = tf_regs;
416 	xfm->tf_shift = tf_shift;
417 	xfm->tf_mask = tf_mask;
418 
419 	xfm->lb_pixel_depth_supported =
420 		LB_PIXEL_DEPTH_18BPP |
421 		LB_PIXEL_DEPTH_24BPP |
422 		LB_PIXEL_DEPTH_30BPP;
423 
424 	xfm->lb_bits_per_entry = LB_BITS_PER_ENTRY;
425 	xfm->lb_memory_size = LB_TOTAL_NUMBER_OF_ENTRIES; /*0x1404*/
426 
427 	return true;
428 }
429