xref: /openbmc/linux/drivers/gpu/drm/meson/meson_viu.c (revision 66620f48)
11ccea77eSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2bbbe775eSNeil Armstrong /*
3bbbe775eSNeil Armstrong  * Copyright (C) 2016 BayLibre, SAS
4bbbe775eSNeil Armstrong  * Author: Neil Armstrong <narmstrong@baylibre.com>
5bbbe775eSNeil Armstrong  * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
6bbbe775eSNeil Armstrong  * Copyright (C) 2014 Endless Mobile
7bbbe775eSNeil Armstrong  */
8bbbe775eSNeil Armstrong 
966620f48SSam Ravnborg #include <linux/export.h>
1066620f48SSam Ravnborg 
11bbbe775eSNeil Armstrong #include "meson_drv.h"
12bbbe775eSNeil Armstrong #include "meson_viu.h"
13bbbe775eSNeil Armstrong #include "meson_registers.h"
14bbbe775eSNeil Armstrong 
152021d5b7SNeil Armstrong /**
162021d5b7SNeil Armstrong  * DOC: Video Input Unit
172021d5b7SNeil Armstrong  *
18bbbe775eSNeil Armstrong  * VIU Handles the Pixel scanout and the basic Colorspace conversions
19bbbe775eSNeil Armstrong  * We handle the following features :
202021d5b7SNeil Armstrong  *
21bbbe775eSNeil Armstrong  * - OSD1 RGB565/RGB888/xRGB8888 scanout
22bbbe775eSNeil Armstrong  * - RGB conversion to x/cb/cr
23bbbe775eSNeil Armstrong  * - Progressive or Interlace buffer scanout
24bbbe775eSNeil Armstrong  * - OSD1 Commit on Vsync
25bbbe775eSNeil Armstrong  * - HDR OSD matrix for GXL/GXM
26bbbe775eSNeil Armstrong  *
27bbbe775eSNeil Armstrong  * What is missing :
282021d5b7SNeil Armstrong  *
29bbbe775eSNeil Armstrong  * - BGR888/xBGR8888/BGRx8888/BGRx8888 modes
30bbbe775eSNeil Armstrong  * - YUV4:2:2 Y0CbY1Cr scanout
31bbbe775eSNeil Armstrong  * - Conversion to YUV 4:4:4 from 4:2:2 input
32bbbe775eSNeil Armstrong  * - Colorkey Alpha matching
33bbbe775eSNeil Armstrong  * - Big endian scanout
34bbbe775eSNeil Armstrong  * - X/Y reverse scanout
35bbbe775eSNeil Armstrong  * - Global alpha setup
36bbbe775eSNeil Armstrong  * - OSD2 support, would need interlace switching on vsync
37bbbe775eSNeil Armstrong  * - OSD1 full scaling to support TV overscan
38bbbe775eSNeil Armstrong  */
39bbbe775eSNeil Armstrong 
40bbbe775eSNeil Armstrong /* OSD csc defines */
41bbbe775eSNeil Armstrong 
42bbbe775eSNeil Armstrong enum viu_matrix_sel_e {
43bbbe775eSNeil Armstrong 	VIU_MATRIX_OSD_EOTF = 0,
44bbbe775eSNeil Armstrong 	VIU_MATRIX_OSD,
45bbbe775eSNeil Armstrong };
46bbbe775eSNeil Armstrong 
47bbbe775eSNeil Armstrong enum viu_lut_sel_e {
48bbbe775eSNeil Armstrong 	VIU_LUT_OSD_EOTF = 0,
49bbbe775eSNeil Armstrong 	VIU_LUT_OSD_OETF,
50bbbe775eSNeil Armstrong };
51bbbe775eSNeil Armstrong 
52bbbe775eSNeil Armstrong #define COEFF_NORM(a) ((int)((((a) * 2048.0) + 1) / 2))
53bbbe775eSNeil Armstrong #define MATRIX_5X3_COEF_SIZE 24
54bbbe775eSNeil Armstrong 
55bbbe775eSNeil Armstrong #define EOTF_COEFF_NORM(a) ((int)((((a) * 4096.0) + 1) / 2))
56bbbe775eSNeil Armstrong #define EOTF_COEFF_SIZE 10
57bbbe775eSNeil Armstrong #define EOTF_COEFF_RIGHTSHIFT 1
58bbbe775eSNeil Armstrong 
59bbbe775eSNeil Armstrong static int RGB709_to_YUV709l_coeff[MATRIX_5X3_COEF_SIZE] = {
60bbbe775eSNeil Armstrong 	0, 0, 0, /* pre offset */
61bbbe775eSNeil Armstrong 	COEFF_NORM(0.181873),	COEFF_NORM(0.611831),	COEFF_NORM(0.061765),
62bbbe775eSNeil Armstrong 	COEFF_NORM(-0.100251),	COEFF_NORM(-0.337249),	COEFF_NORM(0.437500),
63bbbe775eSNeil Armstrong 	COEFF_NORM(0.437500),	COEFF_NORM(-0.397384),	COEFF_NORM(-0.040116),
64bbbe775eSNeil Armstrong 	0, 0, 0, /* 10'/11'/12' */
65bbbe775eSNeil Armstrong 	0, 0, 0, /* 20'/21'/22' */
66bbbe775eSNeil Armstrong 	64, 512, 512, /* offset */
67bbbe775eSNeil Armstrong 	0, 0, 0 /* mode, right_shift, clip_en */
68bbbe775eSNeil Armstrong };
69bbbe775eSNeil Armstrong 
70bbbe775eSNeil Armstrong /*  eotf matrix: bypass */
71bbbe775eSNeil Armstrong static int eotf_bypass_coeff[EOTF_COEFF_SIZE] = {
72bbbe775eSNeil Armstrong 	EOTF_COEFF_NORM(1.0),	EOTF_COEFF_NORM(0.0),	EOTF_COEFF_NORM(0.0),
73bbbe775eSNeil Armstrong 	EOTF_COEFF_NORM(0.0),	EOTF_COEFF_NORM(1.0),	EOTF_COEFF_NORM(0.0),
74bbbe775eSNeil Armstrong 	EOTF_COEFF_NORM(0.0),	EOTF_COEFF_NORM(0.0),	EOTF_COEFF_NORM(1.0),
75bbbe775eSNeil Armstrong 	EOTF_COEFF_RIGHTSHIFT /* right shift */
76bbbe775eSNeil Armstrong };
77bbbe775eSNeil Armstrong 
782ccb8433SYueHaibing static void meson_viu_set_g12a_osd1_matrix(struct meson_drm *priv,
792ccb8433SYueHaibing 					   int *m, bool csc_on)
8072888394SNeil Armstrong {
8172888394SNeil Armstrong 	/* VPP WRAP OSD1 matrix */
8272888394SNeil Armstrong 	writel(((m[0] & 0xfff) << 16) | (m[1] & 0xfff),
8372888394SNeil Armstrong 		priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_PRE_OFFSET0_1));
8472888394SNeil Armstrong 	writel(m[2] & 0xfff,
8572888394SNeil Armstrong 		priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_PRE_OFFSET2));
8672888394SNeil Armstrong 	writel(((m[3] & 0x1fff) << 16) | (m[4] & 0x1fff),
8772888394SNeil Armstrong 		priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF00_01));
8872888394SNeil Armstrong 	writel(((m[5] & 0x1fff) << 16) | (m[6] & 0x1fff),
8972888394SNeil Armstrong 		priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF02_10));
9072888394SNeil Armstrong 	writel(((m[7] & 0x1fff) << 16) | (m[8] & 0x1fff),
9172888394SNeil Armstrong 		priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF11_12));
9272888394SNeil Armstrong 	writel(((m[9] & 0x1fff) << 16) | (m[10] & 0x1fff),
9372888394SNeil Armstrong 		priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF20_21));
9472888394SNeil Armstrong 	writel((m[11] & 0x1fff) << 16,
9572888394SNeil Armstrong 		priv->io_base +	_REG(VPP_WRAP_OSD1_MATRIX_COEF22));
9672888394SNeil Armstrong 
9772888394SNeil Armstrong 	writel(((m[18] & 0xfff) << 16) | (m[19] & 0xfff),
9872888394SNeil Armstrong 		priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_OFFSET0_1));
9972888394SNeil Armstrong 	writel(m[20] & 0xfff,
10072888394SNeil Armstrong 		priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_OFFSET2));
10172888394SNeil Armstrong 
10272888394SNeil Armstrong 	writel_bits_relaxed(BIT(0), csc_on ? BIT(0) : 0,
10372888394SNeil Armstrong 		priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_EN_CTRL));
10472888394SNeil Armstrong }
10572888394SNeil Armstrong 
1062ccb8433SYueHaibing static void meson_viu_set_osd_matrix(struct meson_drm *priv,
107bbbe775eSNeil Armstrong 				     enum viu_matrix_sel_e m_select,
108bbbe775eSNeil Armstrong 			      int *m, bool csc_on)
109bbbe775eSNeil Armstrong {
110bbbe775eSNeil Armstrong 	if (m_select == VIU_MATRIX_OSD) {
111bbbe775eSNeil Armstrong 		/* osd matrix, VIU_MATRIX_0 */
112bbbe775eSNeil Armstrong 		writel(((m[0] & 0xfff) << 16) | (m[1] & 0xfff),
113bbbe775eSNeil Armstrong 			priv->io_base + _REG(VIU_OSD1_MATRIX_PRE_OFFSET0_1));
114bbbe775eSNeil Armstrong 		writel(m[2] & 0xfff,
115bbbe775eSNeil Armstrong 			priv->io_base + _REG(VIU_OSD1_MATRIX_PRE_OFFSET2));
116bbbe775eSNeil Armstrong 		writel(((m[3] & 0x1fff) << 16) | (m[4] & 0x1fff),
117bbbe775eSNeil Armstrong 			priv->io_base + _REG(VIU_OSD1_MATRIX_COEF00_01));
118bbbe775eSNeil Armstrong 		writel(((m[5] & 0x1fff) << 16) | (m[6] & 0x1fff),
119bbbe775eSNeil Armstrong 			priv->io_base + _REG(VIU_OSD1_MATRIX_COEF02_10));
120bbbe775eSNeil Armstrong 		writel(((m[7] & 0x1fff) << 16) | (m[8] & 0x1fff),
121bbbe775eSNeil Armstrong 			priv->io_base + _REG(VIU_OSD1_MATRIX_COEF11_12));
122bbbe775eSNeil Armstrong 		writel(((m[9] & 0x1fff) << 16) | (m[10] & 0x1fff),
123bbbe775eSNeil Armstrong 			priv->io_base + _REG(VIU_OSD1_MATRIX_COEF20_21));
124bbbe775eSNeil Armstrong 
125bbbe775eSNeil Armstrong 		if (m[21]) {
126bbbe775eSNeil Armstrong 			writel(((m[11] & 0x1fff) << 16) | (m[12] & 0x1fff),
127bbbe775eSNeil Armstrong 				priv->io_base +
128bbbe775eSNeil Armstrong 					_REG(VIU_OSD1_MATRIX_COEF22_30));
129bbbe775eSNeil Armstrong 			writel(((m[13] & 0x1fff) << 16) | (m[14] & 0x1fff),
130bbbe775eSNeil Armstrong 				priv->io_base +
131bbbe775eSNeil Armstrong 					_REG(VIU_OSD1_MATRIX_COEF31_32));
132bbbe775eSNeil Armstrong 			writel(((m[15] & 0x1fff) << 16) | (m[16] & 0x1fff),
133bbbe775eSNeil Armstrong 				priv->io_base +
134bbbe775eSNeil Armstrong 					_REG(VIU_OSD1_MATRIX_COEF40_41));
135bbbe775eSNeil Armstrong 			writel(m[17] & 0x1fff, priv->io_base +
136bbbe775eSNeil Armstrong 				_REG(VIU_OSD1_MATRIX_COLMOD_COEF42));
137bbbe775eSNeil Armstrong 		} else
138bbbe775eSNeil Armstrong 			writel((m[11] & 0x1fff) << 16, priv->io_base +
139bbbe775eSNeil Armstrong 				_REG(VIU_OSD1_MATRIX_COEF22_30));
140bbbe775eSNeil Armstrong 
141bbbe775eSNeil Armstrong 		writel(((m[18] & 0xfff) << 16) | (m[19] & 0xfff),
142bbbe775eSNeil Armstrong 			priv->io_base + _REG(VIU_OSD1_MATRIX_OFFSET0_1));
143bbbe775eSNeil Armstrong 		writel(m[20] & 0xfff,
144bbbe775eSNeil Armstrong 			priv->io_base + _REG(VIU_OSD1_MATRIX_OFFSET2));
145bbbe775eSNeil Armstrong 
146bbbe775eSNeil Armstrong 		writel_bits_relaxed(3 << 30, m[21] << 30,
147bbbe775eSNeil Armstrong 			priv->io_base + _REG(VIU_OSD1_MATRIX_COLMOD_COEF42));
148bbbe775eSNeil Armstrong 		writel_bits_relaxed(7 << 16, m[22] << 16,
149bbbe775eSNeil Armstrong 			priv->io_base + _REG(VIU_OSD1_MATRIX_COLMOD_COEF42));
150bbbe775eSNeil Armstrong 
151bbbe775eSNeil Armstrong 		/* 23 reserved for clipping control */
152bbbe775eSNeil Armstrong 		writel_bits_relaxed(BIT(0), csc_on ? BIT(0) : 0,
153bbbe775eSNeil Armstrong 			priv->io_base + _REG(VIU_OSD1_MATRIX_CTRL));
154bbbe775eSNeil Armstrong 		writel_bits_relaxed(BIT(1), 0,
155bbbe775eSNeil Armstrong 			priv->io_base + _REG(VIU_OSD1_MATRIX_CTRL));
156bbbe775eSNeil Armstrong 	} else if (m_select == VIU_MATRIX_OSD_EOTF) {
157bbbe775eSNeil Armstrong 		int i;
158bbbe775eSNeil Armstrong 
159bbbe775eSNeil Armstrong 		/* osd eotf matrix, VIU_MATRIX_OSD_EOTF */
160bbbe775eSNeil Armstrong 		for (i = 0; i < 5; i++)
161bbbe775eSNeil Armstrong 			writel(((m[i * 2] & 0x1fff) << 16) |
162bbbe775eSNeil Armstrong 				(m[i * 2 + 1] & 0x1fff), priv->io_base +
163bbbe775eSNeil Armstrong 				_REG(VIU_OSD1_EOTF_CTL + i + 1));
164bbbe775eSNeil Armstrong 
165bbbe775eSNeil Armstrong 		writel_bits_relaxed(BIT(30), csc_on ? BIT(30) : 0,
166bbbe775eSNeil Armstrong 			priv->io_base + _REG(VIU_OSD1_EOTF_CTL));
167bbbe775eSNeil Armstrong 		writel_bits_relaxed(BIT(31), csc_on ? BIT(31) : 0,
168bbbe775eSNeil Armstrong 			priv->io_base + _REG(VIU_OSD1_EOTF_CTL));
169bbbe775eSNeil Armstrong 	}
170bbbe775eSNeil Armstrong }
171bbbe775eSNeil Armstrong 
172bbbe775eSNeil Armstrong #define OSD_EOTF_LUT_SIZE 33
173bbbe775eSNeil Armstrong #define OSD_OETF_LUT_SIZE 41
174bbbe775eSNeil Armstrong 
1752ccb8433SYueHaibing static void
1762ccb8433SYueHaibing meson_viu_set_osd_lut(struct meson_drm *priv, enum viu_lut_sel_e lut_sel,
177bbbe775eSNeil Armstrong 		      unsigned int *r_map, unsigned int *g_map,
1782ccb8433SYueHaibing 		      unsigned int *b_map, bool csc_on)
179bbbe775eSNeil Armstrong {
180bbbe775eSNeil Armstrong 	unsigned int addr_port;
181bbbe775eSNeil Armstrong 	unsigned int data_port;
182bbbe775eSNeil Armstrong 	unsigned int ctrl_port;
183bbbe775eSNeil Armstrong 	int i;
184bbbe775eSNeil Armstrong 
185bbbe775eSNeil Armstrong 	if (lut_sel == VIU_LUT_OSD_EOTF) {
186bbbe775eSNeil Armstrong 		addr_port = VIU_OSD1_EOTF_LUT_ADDR_PORT;
187bbbe775eSNeil Armstrong 		data_port = VIU_OSD1_EOTF_LUT_DATA_PORT;
188bbbe775eSNeil Armstrong 		ctrl_port = VIU_OSD1_EOTF_CTL;
189bbbe775eSNeil Armstrong 	} else if (lut_sel == VIU_LUT_OSD_OETF) {
190bbbe775eSNeil Armstrong 		addr_port = VIU_OSD1_OETF_LUT_ADDR_PORT;
191bbbe775eSNeil Armstrong 		data_port = VIU_OSD1_OETF_LUT_DATA_PORT;
192bbbe775eSNeil Armstrong 		ctrl_port = VIU_OSD1_OETF_CTL;
193bbbe775eSNeil Armstrong 	} else
194bbbe775eSNeil Armstrong 		return;
195bbbe775eSNeil Armstrong 
196bbbe775eSNeil Armstrong 	if (lut_sel == VIU_LUT_OSD_OETF) {
197bbbe775eSNeil Armstrong 		writel(0, priv->io_base + _REG(addr_port));
198bbbe775eSNeil Armstrong 
19997b2a318SLyude Paul 		for (i = 0; i < (OSD_OETF_LUT_SIZE / 2); i++)
200bbbe775eSNeil Armstrong 			writel(r_map[i * 2] | (r_map[i * 2 + 1] << 16),
201bbbe775eSNeil Armstrong 				priv->io_base + _REG(data_port));
202bbbe775eSNeil Armstrong 
203bbbe775eSNeil Armstrong 		writel(r_map[OSD_OETF_LUT_SIZE - 1] | (g_map[0] << 16),
204bbbe775eSNeil Armstrong 			priv->io_base + _REG(data_port));
205bbbe775eSNeil Armstrong 
20697b2a318SLyude Paul 		for (i = 0; i < (OSD_OETF_LUT_SIZE / 2); i++)
207bbbe775eSNeil Armstrong 			writel(g_map[i * 2 + 1] | (g_map[i * 2 + 2] << 16),
208bbbe775eSNeil Armstrong 				priv->io_base + _REG(data_port));
209bbbe775eSNeil Armstrong 
21097b2a318SLyude Paul 		for (i = 0; i < (OSD_OETF_LUT_SIZE / 2); i++)
211bbbe775eSNeil Armstrong 			writel(b_map[i * 2] | (b_map[i * 2 + 1] << 16),
212bbbe775eSNeil Armstrong 				priv->io_base + _REG(data_port));
213bbbe775eSNeil Armstrong 
214bbbe775eSNeil Armstrong 		writel(b_map[OSD_OETF_LUT_SIZE - 1],
215bbbe775eSNeil Armstrong 			priv->io_base + _REG(data_port));
216bbbe775eSNeil Armstrong 
217bbbe775eSNeil Armstrong 		if (csc_on)
218bbbe775eSNeil Armstrong 			writel_bits_relaxed(0x7 << 29, 7 << 29,
219bbbe775eSNeil Armstrong 					    priv->io_base + _REG(ctrl_port));
220bbbe775eSNeil Armstrong 		else
221bbbe775eSNeil Armstrong 			writel_bits_relaxed(0x7 << 29, 0,
222bbbe775eSNeil Armstrong 					    priv->io_base + _REG(ctrl_port));
223bbbe775eSNeil Armstrong 	} else if (lut_sel == VIU_LUT_OSD_EOTF) {
224bbbe775eSNeil Armstrong 		writel(0, priv->io_base + _REG(addr_port));
225bbbe775eSNeil Armstrong 
22697b2a318SLyude Paul 		for (i = 0; i < (OSD_EOTF_LUT_SIZE / 2); i++)
227bbbe775eSNeil Armstrong 			writel(r_map[i * 2] | (r_map[i * 2 + 1] << 16),
228bbbe775eSNeil Armstrong 				priv->io_base + _REG(data_port));
229bbbe775eSNeil Armstrong 
230bbbe775eSNeil Armstrong 		writel(r_map[OSD_EOTF_LUT_SIZE - 1] | (g_map[0] << 16),
231bbbe775eSNeil Armstrong 			priv->io_base + _REG(data_port));
232bbbe775eSNeil Armstrong 
23397b2a318SLyude Paul 		for (i = 0; i < (OSD_EOTF_LUT_SIZE / 2); i++)
234bbbe775eSNeil Armstrong 			writel(g_map[i * 2 + 1] | (g_map[i * 2 + 2] << 16),
235bbbe775eSNeil Armstrong 				priv->io_base + _REG(data_port));
236bbbe775eSNeil Armstrong 
23797b2a318SLyude Paul 		for (i = 0; i < (OSD_EOTF_LUT_SIZE / 2); i++)
238bbbe775eSNeil Armstrong 			writel(b_map[i * 2] | (b_map[i * 2 + 1] << 16),
239bbbe775eSNeil Armstrong 				priv->io_base + _REG(data_port));
240bbbe775eSNeil Armstrong 
241bbbe775eSNeil Armstrong 		writel(b_map[OSD_EOTF_LUT_SIZE - 1],
242bbbe775eSNeil Armstrong 			priv->io_base + _REG(data_port));
243bbbe775eSNeil Armstrong 
244bbbe775eSNeil Armstrong 		if (csc_on)
245bbbe775eSNeil Armstrong 			writel_bits_relaxed(7 << 27, 7 << 27,
246bbbe775eSNeil Armstrong 					    priv->io_base + _REG(ctrl_port));
247bbbe775eSNeil Armstrong 		else
248bbbe775eSNeil Armstrong 			writel_bits_relaxed(7 << 27, 0,
249bbbe775eSNeil Armstrong 					    priv->io_base + _REG(ctrl_port));
250bbbe775eSNeil Armstrong 
251bbbe775eSNeil Armstrong 		writel_bits_relaxed(BIT(31), BIT(31),
252bbbe775eSNeil Armstrong 				    priv->io_base + _REG(ctrl_port));
253bbbe775eSNeil Armstrong 	}
254bbbe775eSNeil Armstrong }
255bbbe775eSNeil Armstrong 
256bbbe775eSNeil Armstrong /* eotf lut: linear */
257bbbe775eSNeil Armstrong static unsigned int eotf_33_linear_mapping[OSD_EOTF_LUT_SIZE] = {
258bbbe775eSNeil Armstrong 	0x0000,	0x0200,	0x0400, 0x0600,
259bbbe775eSNeil Armstrong 	0x0800, 0x0a00, 0x0c00, 0x0e00,
260bbbe775eSNeil Armstrong 	0x1000, 0x1200, 0x1400, 0x1600,
261bbbe775eSNeil Armstrong 	0x1800, 0x1a00, 0x1c00, 0x1e00,
262bbbe775eSNeil Armstrong 	0x2000, 0x2200, 0x2400, 0x2600,
263bbbe775eSNeil Armstrong 	0x2800, 0x2a00, 0x2c00, 0x2e00,
264bbbe775eSNeil Armstrong 	0x3000, 0x3200, 0x3400, 0x3600,
265bbbe775eSNeil Armstrong 	0x3800, 0x3a00, 0x3c00, 0x3e00,
266bbbe775eSNeil Armstrong 	0x4000
267bbbe775eSNeil Armstrong };
268bbbe775eSNeil Armstrong 
269bbbe775eSNeil Armstrong /* osd oetf lut: linear */
270bbbe775eSNeil Armstrong static unsigned int oetf_41_linear_mapping[OSD_OETF_LUT_SIZE] = {
271bbbe775eSNeil Armstrong 	0, 0, 0, 0,
272bbbe775eSNeil Armstrong 	0, 32, 64, 96,
273bbbe775eSNeil Armstrong 	128, 160, 196, 224,
274bbbe775eSNeil Armstrong 	256, 288, 320, 352,
275bbbe775eSNeil Armstrong 	384, 416, 448, 480,
276bbbe775eSNeil Armstrong 	512, 544, 576, 608,
277bbbe775eSNeil Armstrong 	640, 672, 704, 736,
278bbbe775eSNeil Armstrong 	768, 800, 832, 864,
279bbbe775eSNeil Armstrong 	896, 928, 960, 992,
280bbbe775eSNeil Armstrong 	1023, 1023, 1023, 1023,
281bbbe775eSNeil Armstrong 	1023
282bbbe775eSNeil Armstrong };
283bbbe775eSNeil Armstrong 
284bbbe775eSNeil Armstrong static void meson_viu_load_matrix(struct meson_drm *priv)
285bbbe775eSNeil Armstrong {
286bbbe775eSNeil Armstrong 	/* eotf lut bypass */
287bbbe775eSNeil Armstrong 	meson_viu_set_osd_lut(priv, VIU_LUT_OSD_EOTF,
288bbbe775eSNeil Armstrong 			      eotf_33_linear_mapping, /* R */
289bbbe775eSNeil Armstrong 			      eotf_33_linear_mapping, /* G */
290bbbe775eSNeil Armstrong 			      eotf_33_linear_mapping, /* B */
291bbbe775eSNeil Armstrong 			      false);
292bbbe775eSNeil Armstrong 
293bbbe775eSNeil Armstrong 	/* eotf matrix bypass */
294bbbe775eSNeil Armstrong 	meson_viu_set_osd_matrix(priv, VIU_MATRIX_OSD_EOTF,
295bbbe775eSNeil Armstrong 				 eotf_bypass_coeff,
296bbbe775eSNeil Armstrong 				 false);
297bbbe775eSNeil Armstrong 
298bbbe775eSNeil Armstrong 	/* oetf lut bypass */
299bbbe775eSNeil Armstrong 	meson_viu_set_osd_lut(priv, VIU_LUT_OSD_OETF,
300bbbe775eSNeil Armstrong 			      oetf_41_linear_mapping, /* R */
301bbbe775eSNeil Armstrong 			      oetf_41_linear_mapping, /* G */
302bbbe775eSNeil Armstrong 			      oetf_41_linear_mapping, /* B */
303bbbe775eSNeil Armstrong 			      false);
304bbbe775eSNeil Armstrong 
305bbbe775eSNeil Armstrong 	/* osd matrix RGB709 to YUV709 limit */
306bbbe775eSNeil Armstrong 	meson_viu_set_osd_matrix(priv, VIU_MATRIX_OSD,
307bbbe775eSNeil Armstrong 				 RGB709_to_YUV709l_coeff,
308bbbe775eSNeil Armstrong 				 true);
309bbbe775eSNeil Armstrong }
310bbbe775eSNeil Armstrong 
3113a936bc2SNeil Armstrong /* VIU OSD1 Reset as workaround for GXL+ Alpha OSD Bug */
3123a936bc2SNeil Armstrong void meson_viu_osd1_reset(struct meson_drm *priv)
3133a936bc2SNeil Armstrong {
3143a936bc2SNeil Armstrong 	uint32_t osd1_fifo_ctrl_stat, osd1_ctrl_stat2;
3153a936bc2SNeil Armstrong 
3163a936bc2SNeil Armstrong 	/* Save these 2 registers state */
3173a936bc2SNeil Armstrong 	osd1_fifo_ctrl_stat = readl_relaxed(
3183a936bc2SNeil Armstrong 				priv->io_base + _REG(VIU_OSD1_FIFO_CTRL_STAT));
3193a936bc2SNeil Armstrong 	osd1_ctrl_stat2 = readl_relaxed(
3203a936bc2SNeil Armstrong 				priv->io_base + _REG(VIU_OSD1_CTRL_STAT2));
3213a936bc2SNeil Armstrong 
3223a936bc2SNeil Armstrong 	/* Reset OSD1 */
3233a936bc2SNeil Armstrong 	writel_bits_relaxed(BIT(0), BIT(0),
3243a936bc2SNeil Armstrong 			    priv->io_base + _REG(VIU_SW_RESET));
3253a936bc2SNeil Armstrong 	writel_bits_relaxed(BIT(0), 0,
3263a936bc2SNeil Armstrong 			    priv->io_base + _REG(VIU_SW_RESET));
3273a936bc2SNeil Armstrong 
3283a936bc2SNeil Armstrong 	/* Rewrite these registers state lost in the reset */
3293a936bc2SNeil Armstrong 	writel_relaxed(osd1_fifo_ctrl_stat,
3303a936bc2SNeil Armstrong 		       priv->io_base + _REG(VIU_OSD1_FIFO_CTRL_STAT));
3313a936bc2SNeil Armstrong 	writel_relaxed(osd1_ctrl_stat2,
3323a936bc2SNeil Armstrong 		       priv->io_base + _REG(VIU_OSD1_CTRL_STAT2));
3333a936bc2SNeil Armstrong 
3343a936bc2SNeil Armstrong 	/* Reload the conversion matrix */
3353a936bc2SNeil Armstrong 	meson_viu_load_matrix(priv);
3363a936bc2SNeil Armstrong }
3373a936bc2SNeil Armstrong 
338bbbe775eSNeil Armstrong void meson_viu_init(struct meson_drm *priv)
339bbbe775eSNeil Armstrong {
340bbbe775eSNeil Armstrong 	uint32_t reg;
341bbbe775eSNeil Armstrong 
342bbbe775eSNeil Armstrong 	/* Disable OSDs */
343bbbe775eSNeil Armstrong 	writel_bits_relaxed(BIT(0) | BIT(21), 0,
344bbbe775eSNeil Armstrong 			priv->io_base + _REG(VIU_OSD1_CTRL_STAT));
345bbbe775eSNeil Armstrong 	writel_bits_relaxed(BIT(0) | BIT(21), 0,
346bbbe775eSNeil Armstrong 			priv->io_base + _REG(VIU_OSD2_CTRL_STAT));
347bbbe775eSNeil Armstrong 
348bbbe775eSNeil Armstrong 	/* On GXL/GXM, Use the 10bit HDR conversion matrix */
349bbbe775eSNeil Armstrong 	if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
350bbbe775eSNeil Armstrong 	    meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
351bbbe775eSNeil Armstrong 		meson_viu_load_matrix(priv);
35272888394SNeil Armstrong 	else if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu"))
35372888394SNeil Armstrong 		meson_viu_set_g12a_osd1_matrix(priv, RGB709_to_YUV709l_coeff,
35472888394SNeil Armstrong 					       true);
355bbbe775eSNeil Armstrong 
356bbbe775eSNeil Armstrong 	/* Initialize OSD1 fifo control register */
357bbbe775eSNeil Armstrong 	reg = BIT(0) |	/* Urgent DDR request priority */
35872888394SNeil Armstrong 	      (4 << 5); /* hold_fifo_lines */
35972888394SNeil Armstrong 	if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu"))
36072888394SNeil Armstrong 		reg |= (1 << 10) | /* burst length 32 */
36172888394SNeil Armstrong 		       (32 << 12) | /* fifo_depth_val: 32*8=256 */
36272888394SNeil Armstrong 		       (2 << 22) | /* 4 words in 1 burst */
36372888394SNeil Armstrong 		       (2 << 24) |
36472888394SNeil Armstrong 		       (1 << 31);
36572888394SNeil Armstrong 	else
36672888394SNeil Armstrong 		reg |= (3 << 10) | /* burst length 64 */
367bbbe775eSNeil Armstrong 		       (32 << 12) | /* fifo_depth_val: 32*8=256 */
368bbbe775eSNeil Armstrong 		       (2 << 22) | /* 4 words in 1 burst */
369bbbe775eSNeil Armstrong 		       (2 << 24);
370bbbe775eSNeil Armstrong 	writel_relaxed(reg, priv->io_base + _REG(VIU_OSD1_FIFO_CTRL_STAT));
371bbbe775eSNeil Armstrong 	writel_relaxed(reg, priv->io_base + _REG(VIU_OSD2_FIFO_CTRL_STAT));
372bbbe775eSNeil Armstrong 
373bbbe775eSNeil Armstrong 	/* Set OSD alpha replace value */
374bbbe775eSNeil Armstrong 	writel_bits_relaxed(0xff << OSD_REPLACE_SHIFT,
375bbbe775eSNeil Armstrong 			    0xff << OSD_REPLACE_SHIFT,
376bbbe775eSNeil Armstrong 			    priv->io_base + _REG(VIU_OSD1_CTRL_STAT2));
377bbbe775eSNeil Armstrong 	writel_bits_relaxed(0xff << OSD_REPLACE_SHIFT,
378bbbe775eSNeil Armstrong 			    0xff << OSD_REPLACE_SHIFT,
379bbbe775eSNeil Armstrong 			    priv->io_base + _REG(VIU_OSD2_CTRL_STAT2));
380bbbe775eSNeil Armstrong 
381f9a23481SNeil Armstrong 	/* Disable VD1 AFBC */
382f9a23481SNeil Armstrong 	/* di_mif0_en=0 mif0_to_vpp_en=0 di_mad_en=0 */
383f9a23481SNeil Armstrong 	writel_bits_relaxed(0x7 << 16, 0,
384f9a23481SNeil Armstrong 			priv->io_base + _REG(VIU_MISC_CTRL0));
385f9a23481SNeil Armstrong 	/* afbc vd1 set=0 */
386f9a23481SNeil Armstrong 	writel_bits_relaxed(BIT(20), 0,
387f9a23481SNeil Armstrong 			priv->io_base + _REG(VIU_MISC_CTRL0));
388f9a23481SNeil Armstrong 	writel_relaxed(0, priv->io_base + _REG(AFBC_ENABLE));
389f9a23481SNeil Armstrong 
390f9a23481SNeil Armstrong 	writel_relaxed(0x00FF00C0,
391f9a23481SNeil Armstrong 			priv->io_base + _REG(VD1_IF0_LUMA_FIFO_SIZE));
392f9a23481SNeil Armstrong 	writel_relaxed(0x00FF00C0,
393f9a23481SNeil Armstrong 			priv->io_base + _REG(VD2_IF0_LUMA_FIFO_SIZE));
394f9a23481SNeil Armstrong 
39572888394SNeil Armstrong 	if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu")) {
39672888394SNeil Armstrong 		writel_relaxed(4 << 29 |
39772888394SNeil Armstrong 				1 << 27 |
39872888394SNeil Armstrong 				1 << 26 | /* blend_din0 input to blend0 */
39972888394SNeil Armstrong 				1 << 25 | /* blend1_dout to blend2 */
40072888394SNeil Armstrong 				1 << 24 | /* blend1_din3 input to blend1 */
40172888394SNeil Armstrong 				1 << 20 |
40272888394SNeil Armstrong 				0 << 16 |
40372888394SNeil Armstrong 				1,
40472888394SNeil Armstrong 				priv->io_base + _REG(VIU_OSD_BLEND_CTRL));
4050b84933dSNeil Armstrong 		writel_relaxed(1 << 20,
40672888394SNeil Armstrong 				priv->io_base + _REG(OSD1_BLEND_SRC_CTRL));
40772888394SNeil Armstrong 		writel_relaxed(1 << 20,
40872888394SNeil Armstrong 				priv->io_base + _REG(OSD2_BLEND_SRC_CTRL));
40972888394SNeil Armstrong 		writel_relaxed(0, priv->io_base + _REG(VD1_BLEND_SRC_CTRL));
41072888394SNeil Armstrong 		writel_relaxed(0, priv->io_base + _REG(VD2_BLEND_SRC_CTRL));
41172888394SNeil Armstrong 		writel_relaxed(0,
41272888394SNeil Armstrong 				priv->io_base + _REG(VIU_OSD_BLEND_DUMMY_DATA0));
41372888394SNeil Armstrong 		writel_relaxed(0,
41472888394SNeil Armstrong 				priv->io_base + _REG(VIU_OSD_BLEND_DUMMY_ALPHA));
41572888394SNeil Armstrong 		writel_bits_relaxed(0x3 << 2, 0x3 << 2,
41672888394SNeil Armstrong 				priv->io_base + _REG(DOLBY_PATH_CTRL));
41772888394SNeil Armstrong 	}
418f9a23481SNeil Armstrong 
419bbbe775eSNeil Armstrong 	priv->viu.osd1_enabled = false;
420bbbe775eSNeil Armstrong 	priv->viu.osd1_commit = false;
421bbbe775eSNeil Armstrong 	priv->viu.osd1_interlace = false;
422bbbe775eSNeil Armstrong }
423