170ccab60SHarry Wentland /*
270ccab60SHarry Wentland  * Copyright 2017 Advanced Micro Devices, Inc.
370ccab60SHarry Wentland  *
470ccab60SHarry Wentland  * Permission is hereby granted, free of charge, to any person obtaining a
570ccab60SHarry Wentland  * copy of this software and associated documentation files (the "Software"),
670ccab60SHarry Wentland  * to deal in the Software without restriction, including without limitation
770ccab60SHarry Wentland  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
870ccab60SHarry Wentland  * and/or sell copies of the Software, and to permit persons to whom the
970ccab60SHarry Wentland  * Software is furnished to do so, subject to the following conditions:
1070ccab60SHarry Wentland  *
1170ccab60SHarry Wentland  * The above copyright notice and this permission notice shall be included in
1270ccab60SHarry Wentland  * all copies or substantial portions of the Software.
1370ccab60SHarry Wentland  *
1470ccab60SHarry Wentland  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1570ccab60SHarry Wentland  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1670ccab60SHarry Wentland  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1770ccab60SHarry Wentland  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
1870ccab60SHarry Wentland  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
1970ccab60SHarry Wentland  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
2070ccab60SHarry Wentland  * OTHER DEALINGS IN THE SOFTWARE.
2170ccab60SHarry Wentland  *
2270ccab60SHarry Wentland  * Authors: AMD
2370ccab60SHarry Wentland  *
2470ccab60SHarry Wentland  */
2570ccab60SHarry Wentland 
2670ccab60SHarry Wentland #include "dm_services.h"
2770ccab60SHarry Wentland #include "dcn10_ipp.h"
2870ccab60SHarry Wentland #include "reg_helper.h"
2970ccab60SHarry Wentland 
3070ccab60SHarry Wentland #define REG(reg) \
3170ccab60SHarry Wentland 	(ippn10->regs->reg)
3270ccab60SHarry Wentland 
3370ccab60SHarry Wentland #undef FN
3470ccab60SHarry Wentland #define FN(reg_name, field_name) \
3570ccab60SHarry Wentland 	ippn10->ipp_shift->field_name, ippn10->ipp_mask->field_name
3670ccab60SHarry Wentland 
3770ccab60SHarry Wentland #define CTX \
3870ccab60SHarry Wentland 	ippn10->base.ctx
3970ccab60SHarry Wentland 
4070ccab60SHarry Wentland 
4170ccab60SHarry Wentland struct dcn10_input_csc_matrix {
4270ccab60SHarry Wentland 	enum dc_color_space color_space;
4370ccab60SHarry Wentland 	uint32_t regval[12];
4470ccab60SHarry Wentland };
4570ccab60SHarry Wentland 
4670ccab60SHarry Wentland static const struct dcn10_input_csc_matrix dcn10_input_csc_matrix[] = {
4770ccab60SHarry Wentland 	{COLOR_SPACE_SRGB,
4870ccab60SHarry Wentland 		{0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} },
4970ccab60SHarry Wentland 	{COLOR_SPACE_SRGB_LIMITED,
5070ccab60SHarry Wentland 		{0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} },
5170ccab60SHarry Wentland 	{COLOR_SPACE_YCBCR601,
5270ccab60SHarry Wentland 		{0x2cdd, 0x2000, 0, 0xe991, 0xe926, 0x2000, 0xf4fd, 0x10ef,
5370ccab60SHarry Wentland 						0, 0x2000, 0x38b4, 0xe3a6} },
5470ccab60SHarry Wentland 	{COLOR_SPACE_YCBCR601_LIMITED,
5570ccab60SHarry Wentland 		{0x3353, 0x2568, 0, 0xe400, 0xe5dc, 0x2568, 0xf367, 0x1108,
5670ccab60SHarry Wentland 						0, 0x2568, 0x40de, 0xdd3a} },
5770ccab60SHarry Wentland 	{COLOR_SPACE_YCBCR709,
5870ccab60SHarry Wentland 		{0x3265, 0x2000, 0, 0xe6ce, 0xf105, 0x2000, 0xfa01, 0xa7d, 0,
5970ccab60SHarry Wentland 						0x2000, 0x3b61, 0xe24f} },
6070ccab60SHarry Wentland 
6170ccab60SHarry Wentland 	{COLOR_SPACE_YCBCR709_LIMITED,
6270ccab60SHarry Wentland 		{0x39a6, 0x2568, 0, 0xe0d6, 0xeedd, 0x2568, 0xf925, 0x9a8, 0,
6370ccab60SHarry Wentland 						0x2568, 0x43ee, 0xdbb2} }
6470ccab60SHarry Wentland };
6570ccab60SHarry Wentland 
6670ccab60SHarry Wentland enum dcn10_input_csc_select {
6770ccab60SHarry Wentland 	INPUT_CSC_SELECT_BYPASS = 0,
6870ccab60SHarry Wentland 	INPUT_CSC_SELECT_ICSC,
6970ccab60SHarry Wentland 	INPUT_CSC_SELECT_COMA
7070ccab60SHarry Wentland };
7170ccab60SHarry Wentland 
7270ccab60SHarry Wentland 
7370ccab60SHarry Wentland 
74a3ac9dadSDmytro Laktyushkin static bool ippn10_cursor_program_control(
7570ccab60SHarry Wentland 		struct dcn10_ipp *ippn10,
7670ccab60SHarry Wentland 		bool pixel_data_invert,
7770ccab60SHarry Wentland 		enum dc_cursor_color_format color_format)
7870ccab60SHarry Wentland {
7951666631SDmytro Laktyushkin 	if (REG(CURSOR_SETTINS))
8070ccab60SHarry Wentland 		REG_SET_2(CURSOR_SETTINS, 0,
8170ccab60SHarry Wentland 				/* no shift of the cursor HDL schedule */
8270ccab60SHarry Wentland 				CURSOR0_DST_Y_OFFSET, 0,
8370ccab60SHarry Wentland 				 /* used to shift the cursor chunk request deadline */
8470ccab60SHarry Wentland 				CURSOR0_CHUNK_HDL_ADJUST, 3);
8551666631SDmytro Laktyushkin 	else
8651666631SDmytro Laktyushkin 		REG_SET_2(CURSOR_SETTINGS, 0,
8751666631SDmytro Laktyushkin 				/* no shift of the cursor HDL schedule */
8851666631SDmytro Laktyushkin 				CURSOR0_DST_Y_OFFSET, 0,
8951666631SDmytro Laktyushkin 				 /* used to shift the cursor chunk request deadline */
9051666631SDmytro Laktyushkin 				CURSOR0_CHUNK_HDL_ADJUST, 3);
9170ccab60SHarry Wentland 
9270ccab60SHarry Wentland 	REG_UPDATE_2(CURSOR0_CONTROL,
9370ccab60SHarry Wentland 			CUR0_MODE, color_format,
9435ce37d6SDmytro Laktyushkin 			CUR0_EXPANSION_MODE, 0);
9570ccab60SHarry Wentland 
9670ccab60SHarry Wentland 	if (color_format == CURSOR_MODE_MONO) {
9770ccab60SHarry Wentland 		/* todo: clarify what to program these to */
9870ccab60SHarry Wentland 		REG_UPDATE(CURSOR0_COLOR0,
9970ccab60SHarry Wentland 				CUR0_COLOR0, 0x00000000);
10070ccab60SHarry Wentland 		REG_UPDATE(CURSOR0_COLOR1,
10170ccab60SHarry Wentland 				CUR0_COLOR1, 0xFFFFFFFF);
10270ccab60SHarry Wentland 	}
10370ccab60SHarry Wentland 
10470ccab60SHarry Wentland 	/* TODO: Fixed vs float */
10570ccab60SHarry Wentland 
10670ccab60SHarry Wentland 	REG_UPDATE_3(FORMAT_CONTROL,
10770ccab60SHarry Wentland 				CNVC_BYPASS, 0,
10870ccab60SHarry Wentland 				ALPHA_EN, 1,
10970ccab60SHarry Wentland 				FORMAT_EXPANSION_MODE, 0);
11070ccab60SHarry Wentland 
11170ccab60SHarry Wentland 	return true;
11270ccab60SHarry Wentland }
11370ccab60SHarry Wentland 
11470ccab60SHarry Wentland enum cursor_pitch {
11570ccab60SHarry Wentland 	CURSOR_PITCH_64_PIXELS = 0,
11670ccab60SHarry Wentland 	CURSOR_PITCH_128_PIXELS,
11770ccab60SHarry Wentland 	CURSOR_PITCH_256_PIXELS
11870ccab60SHarry Wentland };
11970ccab60SHarry Wentland 
12070ccab60SHarry Wentland enum cursor_lines_per_chunk {
12170ccab60SHarry Wentland 	CURSOR_LINE_PER_CHUNK_2 = 1,
12270ccab60SHarry Wentland 	CURSOR_LINE_PER_CHUNK_4,
12370ccab60SHarry Wentland 	CURSOR_LINE_PER_CHUNK_8,
12470ccab60SHarry Wentland 	CURSOR_LINE_PER_CHUNK_16
12570ccab60SHarry Wentland };
12670ccab60SHarry Wentland 
127a3ac9dadSDmytro Laktyushkin static enum cursor_pitch ippn10_get_cursor_pitch(
12870ccab60SHarry Wentland 		unsigned int pitch)
12970ccab60SHarry Wentland {
13070ccab60SHarry Wentland 	enum cursor_pitch hw_pitch;
13170ccab60SHarry Wentland 
13270ccab60SHarry Wentland 	switch (pitch) {
13370ccab60SHarry Wentland 	case 64:
13470ccab60SHarry Wentland 		hw_pitch = CURSOR_PITCH_64_PIXELS;
13570ccab60SHarry Wentland 		break;
13670ccab60SHarry Wentland 	case 128:
13770ccab60SHarry Wentland 		hw_pitch = CURSOR_PITCH_128_PIXELS;
13870ccab60SHarry Wentland 		break;
13970ccab60SHarry Wentland 	case 256:
14070ccab60SHarry Wentland 		hw_pitch = CURSOR_PITCH_256_PIXELS;
14170ccab60SHarry Wentland 		break;
14270ccab60SHarry Wentland 	default:
14370ccab60SHarry Wentland 		DC_ERR("Invalid cursor pitch of %d. "
14470ccab60SHarry Wentland 				"Only 64/128/256 is supported on DCN.\n", pitch);
14570ccab60SHarry Wentland 		hw_pitch = CURSOR_PITCH_64_PIXELS;
14670ccab60SHarry Wentland 		break;
14770ccab60SHarry Wentland 	}
14870ccab60SHarry Wentland 	return hw_pitch;
14970ccab60SHarry Wentland }
15070ccab60SHarry Wentland 
151a3ac9dadSDmytro Laktyushkin static enum cursor_lines_per_chunk ippn10_get_lines_per_chunk(
15270ccab60SHarry Wentland 		unsigned int cur_width,
15370ccab60SHarry Wentland 		enum dc_cursor_color_format format)
15470ccab60SHarry Wentland {
15570ccab60SHarry Wentland 	enum cursor_lines_per_chunk line_per_chunk;
15670ccab60SHarry Wentland 
15770ccab60SHarry Wentland 	if (format == CURSOR_MODE_MONO)
15870ccab60SHarry Wentland 		/* impl B. expansion in CUR Buffer reader */
15970ccab60SHarry Wentland 		line_per_chunk = CURSOR_LINE_PER_CHUNK_16;
16070ccab60SHarry Wentland 	else if (cur_width <= 32)
16170ccab60SHarry Wentland 		line_per_chunk = CURSOR_LINE_PER_CHUNK_16;
16270ccab60SHarry Wentland 	else if (cur_width <= 64)
16370ccab60SHarry Wentland 		line_per_chunk = CURSOR_LINE_PER_CHUNK_8;
16470ccab60SHarry Wentland 	else if (cur_width <= 128)
16570ccab60SHarry Wentland 		line_per_chunk = CURSOR_LINE_PER_CHUNK_4;
16670ccab60SHarry Wentland 	else
16770ccab60SHarry Wentland 		line_per_chunk = CURSOR_LINE_PER_CHUNK_2;
16870ccab60SHarry Wentland 
16970ccab60SHarry Wentland 	return line_per_chunk;
17070ccab60SHarry Wentland }
17170ccab60SHarry Wentland 
172a3ac9dadSDmytro Laktyushkin static void ippn10_cursor_set_attributes(
17370ccab60SHarry Wentland 		struct input_pixel_processor *ipp,
17470ccab60SHarry Wentland 		const struct dc_cursor_attributes *attr)
17570ccab60SHarry Wentland {
17670ccab60SHarry Wentland 	struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp);
177a3ac9dadSDmytro Laktyushkin 	enum cursor_pitch hw_pitch = ippn10_get_cursor_pitch(attr->pitch);
178a3ac9dadSDmytro Laktyushkin 	enum cursor_lines_per_chunk lpc = ippn10_get_lines_per_chunk(
17970ccab60SHarry Wentland 			attr->width, attr->color_format);
18070ccab60SHarry Wentland 
18170ccab60SHarry Wentland 	ippn10->curs_attr = *attr;
18270ccab60SHarry Wentland 
18370ccab60SHarry Wentland 	REG_UPDATE(CURSOR_SURFACE_ADDRESS_HIGH,
18470ccab60SHarry Wentland 			CURSOR_SURFACE_ADDRESS_HIGH, attr->address.high_part);
18570ccab60SHarry Wentland 	REG_UPDATE(CURSOR_SURFACE_ADDRESS,
18670ccab60SHarry Wentland 			CURSOR_SURFACE_ADDRESS, attr->address.low_part);
18770ccab60SHarry Wentland 
18870ccab60SHarry Wentland 	REG_UPDATE_2(CURSOR_SIZE,
18970ccab60SHarry Wentland 			CURSOR_WIDTH, attr->width,
19070ccab60SHarry Wentland 			CURSOR_HEIGHT, attr->height);
19170ccab60SHarry Wentland 
19270ccab60SHarry Wentland 	REG_UPDATE_3(CURSOR_CONTROL,
19370ccab60SHarry Wentland 			CURSOR_MODE, attr->color_format,
19470ccab60SHarry Wentland 			CURSOR_PITCH, hw_pitch,
19570ccab60SHarry Wentland 			CURSOR_LINES_PER_CHUNK, lpc);
19670ccab60SHarry Wentland 
197a3ac9dadSDmytro Laktyushkin 	ippn10_cursor_program_control(ippn10,
19870ccab60SHarry Wentland 			attr->attribute_flags.bits.INVERT_PIXEL_DATA,
19970ccab60SHarry Wentland 			attr->color_format);
20070ccab60SHarry Wentland }
20170ccab60SHarry Wentland 
202a3ac9dadSDmytro Laktyushkin static void ippn10_cursor_set_position(
20370ccab60SHarry Wentland 		struct input_pixel_processor *ipp,
20470ccab60SHarry Wentland 		const struct dc_cursor_position *pos,
20570ccab60SHarry Wentland 		const struct dc_cursor_mi_param *param)
20670ccab60SHarry Wentland {
20770ccab60SHarry Wentland 	struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp);
20870ccab60SHarry Wentland 	int src_x_offset = pos->x - pos->x_hotspot - param->viewport_x_start;
20970ccab60SHarry Wentland 	uint32_t cur_en = pos->enable ? 1 : 0;
21070ccab60SHarry Wentland 	uint32_t dst_x_offset = (src_x_offset >= 0) ? src_x_offset : 0;
21170ccab60SHarry Wentland 
212d3ec0562SLeo (Sunpeng) Li 	/*
213d3ec0562SLeo (Sunpeng) Li 	 * Guard aganst cursor_set_position() from being called with invalid
214d3ec0562SLeo (Sunpeng) Li 	 * attributes
215d3ec0562SLeo (Sunpeng) Li 	 *
216d3ec0562SLeo (Sunpeng) Li 	 * TODO: Look at combining cursor_set_position() and
217d3ec0562SLeo (Sunpeng) Li 	 * cursor_set_attributes() into cursor_update()
218d3ec0562SLeo (Sunpeng) Li 	 */
219d3ec0562SLeo (Sunpeng) Li 	if (ippn10->curs_attr.address.quad_part == 0)
220d3ec0562SLeo (Sunpeng) Li 		return;
221d3ec0562SLeo (Sunpeng) Li 
22270ccab60SHarry Wentland 	dst_x_offset *= param->ref_clk_khz;
22370ccab60SHarry Wentland 	dst_x_offset /= param->pixel_clk_khz;
22470ccab60SHarry Wentland 
22570ccab60SHarry Wentland 	ASSERT(param->h_scale_ratio.value);
22670ccab60SHarry Wentland 
22770ccab60SHarry Wentland 	if (param->h_scale_ratio.value)
22870ccab60SHarry Wentland 		dst_x_offset = dal_fixed31_32_floor(dal_fixed31_32_div(
22970ccab60SHarry Wentland 				dal_fixed31_32_from_int(dst_x_offset),
23070ccab60SHarry Wentland 				param->h_scale_ratio));
23170ccab60SHarry Wentland 
23270ccab60SHarry Wentland 	if (src_x_offset >= (int)param->viewport_width)
23370ccab60SHarry Wentland 		cur_en = 0;  /* not visible beyond right edge*/
23470ccab60SHarry Wentland 
23570ccab60SHarry Wentland 	if (src_x_offset + (int)ippn10->curs_attr.width < 0)
23670ccab60SHarry Wentland 		cur_en = 0;  /* not visible beyond left edge*/
23770ccab60SHarry Wentland 
23870ccab60SHarry Wentland 	if (cur_en && REG_READ(CURSOR_SURFACE_ADDRESS) == 0)
239a3ac9dadSDmytro Laktyushkin 		ippn10_cursor_set_attributes(ipp, &ippn10->curs_attr);
24070ccab60SHarry Wentland 	REG_UPDATE(CURSOR_CONTROL,
24170ccab60SHarry Wentland 			CURSOR_ENABLE, cur_en);
24270ccab60SHarry Wentland 	REG_UPDATE(CURSOR0_CONTROL,
24370ccab60SHarry Wentland 			CUR0_ENABLE, cur_en);
24470ccab60SHarry Wentland 
24570ccab60SHarry Wentland 	REG_SET_2(CURSOR_POSITION, 0,
24670ccab60SHarry Wentland 			CURSOR_X_POSITION, pos->x,
24770ccab60SHarry Wentland 			CURSOR_Y_POSITION, pos->y);
24870ccab60SHarry Wentland 
24970ccab60SHarry Wentland 	REG_SET_2(CURSOR_HOT_SPOT, 0,
25070ccab60SHarry Wentland 			CURSOR_HOT_SPOT_X, pos->x_hotspot,
25170ccab60SHarry Wentland 			CURSOR_HOT_SPOT_Y, pos->y_hotspot);
25270ccab60SHarry Wentland 
25370ccab60SHarry Wentland 	REG_SET(CURSOR_DST_OFFSET, 0,
25470ccab60SHarry Wentland 			CURSOR_DST_X_OFFSET, dst_x_offset);
25570ccab60SHarry Wentland 	/* TODO Handle surface pixel formats other than 4:4:4 */
25670ccab60SHarry Wentland }
25770ccab60SHarry Wentland 
25870ccab60SHarry Wentland enum pixel_format_description {
25970ccab60SHarry Wentland 	PIXEL_FORMAT_FIXED = 0,
26070ccab60SHarry Wentland 	PIXEL_FORMAT_FIXED16,
26170ccab60SHarry Wentland 	PIXEL_FORMAT_FLOAT
26270ccab60SHarry Wentland 
26370ccab60SHarry Wentland };
26470ccab60SHarry Wentland 
26570ccab60SHarry Wentland /*****************************************/
26670ccab60SHarry Wentland /* Constructor, Destructor               */
26770ccab60SHarry Wentland /*****************************************/
26870ccab60SHarry Wentland 
26970ccab60SHarry Wentland static void dcn10_ipp_destroy(struct input_pixel_processor **ipp)
27070ccab60SHarry Wentland {
27170ccab60SHarry Wentland 	dm_free(TO_DCN10_IPP(*ipp));
27270ccab60SHarry Wentland 	*ipp = NULL;
27370ccab60SHarry Wentland }
27470ccab60SHarry Wentland 
27570ccab60SHarry Wentland static const struct ipp_funcs dcn10_ipp_funcs = {
276a3ac9dadSDmytro Laktyushkin 	.ipp_cursor_set_attributes	= ippn10_cursor_set_attributes,
277a3ac9dadSDmytro Laktyushkin 	.ipp_cursor_set_position	= ippn10_cursor_set_position,
278b3c340faSYue Hin Lau 	.ipp_set_degamma		= NULL,
279b3c340faSYue Hin Lau 	.ipp_program_input_lut		= NULL,
280b3c340faSYue Hin Lau 	.ipp_full_bypass		= NULL,
281b3c340faSYue Hin Lau 	.ipp_setup			= NULL,
282b3c340faSYue Hin Lau 	.ipp_program_degamma_pwl	= NULL,
28370ccab60SHarry Wentland 	.ipp_destroy			= dcn10_ipp_destroy
28470ccab60SHarry Wentland };
28570ccab60SHarry Wentland 
28670ccab60SHarry Wentland void dcn10_ipp_construct(
28770ccab60SHarry Wentland 	struct dcn10_ipp *ippn10,
28870ccab60SHarry Wentland 	struct dc_context *ctx,
28970ccab60SHarry Wentland 	int inst,
29070ccab60SHarry Wentland 	const struct dcn10_ipp_registers *regs,
29170ccab60SHarry Wentland 	const struct dcn10_ipp_shift *ipp_shift,
29270ccab60SHarry Wentland 	const struct dcn10_ipp_mask *ipp_mask)
29370ccab60SHarry Wentland {
29470ccab60SHarry Wentland 	ippn10->base.ctx = ctx;
29570ccab60SHarry Wentland 	ippn10->base.inst = inst;
29670ccab60SHarry Wentland 	ippn10->base.funcs = &dcn10_ipp_funcs;
29770ccab60SHarry Wentland 
29870ccab60SHarry Wentland 	ippn10->regs = regs;
29970ccab60SHarry Wentland 	ippn10->ipp_shift = ipp_shift;
30070ccab60SHarry Wentland 	ippn10->ipp_mask = ipp_mask;
30170ccab60SHarry Wentland }
302a3ac9dadSDmytro Laktyushkin 
303