xref: /openbmc/linux/drivers/gpu/drm/meson/meson_viu.c (revision 3b754ed6)
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>
101b85270fSNeil Armstrong #include <linux/bitfield.h>
111b85270fSNeil Armstrong 
121b85270fSNeil Armstrong #include <drm/drm_fourcc.h>
1366620f48SSam Ravnborg 
14bbbe775eSNeil Armstrong #include "meson_drv.h"
15bbbe775eSNeil Armstrong #include "meson_viu.h"
16bbbe775eSNeil Armstrong #include "meson_registers.h"
17bbbe775eSNeil Armstrong 
182021d5b7SNeil Armstrong /**
192021d5b7SNeil Armstrong  * DOC: Video Input Unit
202021d5b7SNeil Armstrong  *
21bbbe775eSNeil Armstrong  * VIU Handles the Pixel scanout and the basic Colorspace conversions
22bbbe775eSNeil Armstrong  * We handle the following features :
232021d5b7SNeil Armstrong  *
24bbbe775eSNeil Armstrong  * - OSD1 RGB565/RGB888/xRGB8888 scanout
25bbbe775eSNeil Armstrong  * - RGB conversion to x/cb/cr
26bbbe775eSNeil Armstrong  * - Progressive or Interlace buffer scanout
27bbbe775eSNeil Armstrong  * - OSD1 Commit on Vsync
28bbbe775eSNeil Armstrong  * - HDR OSD matrix for GXL/GXM
29bbbe775eSNeil Armstrong  *
30bbbe775eSNeil Armstrong  * What is missing :
312021d5b7SNeil Armstrong  *
32bbbe775eSNeil Armstrong  * - BGR888/xBGR8888/BGRx8888/BGRx8888 modes
33bbbe775eSNeil Armstrong  * - YUV4:2:2 Y0CbY1Cr scanout
34bbbe775eSNeil Armstrong  * - Conversion to YUV 4:4:4 from 4:2:2 input
35bbbe775eSNeil Armstrong  * - Colorkey Alpha matching
36bbbe775eSNeil Armstrong  * - Big endian scanout
37bbbe775eSNeil Armstrong  * - X/Y reverse scanout
38bbbe775eSNeil Armstrong  * - Global alpha setup
39bbbe775eSNeil Armstrong  * - OSD2 support, would need interlace switching on vsync
40bbbe775eSNeil Armstrong  * - OSD1 full scaling to support TV overscan
41bbbe775eSNeil Armstrong  */
42bbbe775eSNeil Armstrong 
43bbbe775eSNeil Armstrong /* OSD csc defines */
44bbbe775eSNeil Armstrong 
45bbbe775eSNeil Armstrong enum viu_matrix_sel_e {
46bbbe775eSNeil Armstrong 	VIU_MATRIX_OSD_EOTF = 0,
47bbbe775eSNeil Armstrong 	VIU_MATRIX_OSD,
48bbbe775eSNeil Armstrong };
49bbbe775eSNeil Armstrong 
50bbbe775eSNeil Armstrong enum viu_lut_sel_e {
51bbbe775eSNeil Armstrong 	VIU_LUT_OSD_EOTF = 0,
52bbbe775eSNeil Armstrong 	VIU_LUT_OSD_OETF,
53bbbe775eSNeil Armstrong };
54bbbe775eSNeil Armstrong 
55bbbe775eSNeil Armstrong #define COEFF_NORM(a) ((int)((((a) * 2048.0) + 1) / 2))
56bbbe775eSNeil Armstrong #define MATRIX_5X3_COEF_SIZE 24
57bbbe775eSNeil Armstrong 
58bbbe775eSNeil Armstrong #define EOTF_COEFF_NORM(a) ((int)((((a) * 4096.0) + 1) / 2))
59bbbe775eSNeil Armstrong #define EOTF_COEFF_SIZE 10
60bbbe775eSNeil Armstrong #define EOTF_COEFF_RIGHTSHIFT 1
61bbbe775eSNeil Armstrong 
62bbbe775eSNeil Armstrong static int RGB709_to_YUV709l_coeff[MATRIX_5X3_COEF_SIZE] = {
63bbbe775eSNeil Armstrong 	0, 0, 0, /* pre offset */
64bbbe775eSNeil Armstrong 	COEFF_NORM(0.181873),	COEFF_NORM(0.611831),	COEFF_NORM(0.061765),
65bbbe775eSNeil Armstrong 	COEFF_NORM(-0.100251),	COEFF_NORM(-0.337249),	COEFF_NORM(0.437500),
66bbbe775eSNeil Armstrong 	COEFF_NORM(0.437500),	COEFF_NORM(-0.397384),	COEFF_NORM(-0.040116),
67bbbe775eSNeil Armstrong 	0, 0, 0, /* 10'/11'/12' */
68bbbe775eSNeil Armstrong 	0, 0, 0, /* 20'/21'/22' */
69bbbe775eSNeil Armstrong 	64, 512, 512, /* offset */
70bbbe775eSNeil Armstrong 	0, 0, 0 /* mode, right_shift, clip_en */
71bbbe775eSNeil Armstrong };
72bbbe775eSNeil Armstrong 
73bbbe775eSNeil Armstrong /*  eotf matrix: bypass */
74bbbe775eSNeil Armstrong static int eotf_bypass_coeff[EOTF_COEFF_SIZE] = {
75bbbe775eSNeil Armstrong 	EOTF_COEFF_NORM(1.0),	EOTF_COEFF_NORM(0.0),	EOTF_COEFF_NORM(0.0),
76bbbe775eSNeil Armstrong 	EOTF_COEFF_NORM(0.0),	EOTF_COEFF_NORM(1.0),	EOTF_COEFF_NORM(0.0),
77bbbe775eSNeil Armstrong 	EOTF_COEFF_NORM(0.0),	EOTF_COEFF_NORM(0.0),	EOTF_COEFF_NORM(1.0),
78bbbe775eSNeil Armstrong 	EOTF_COEFF_RIGHTSHIFT /* right shift */
79bbbe775eSNeil Armstrong };
80bbbe775eSNeil Armstrong 
meson_viu_set_g12a_osd1_matrix(struct meson_drm * priv,int * m,bool csc_on)812ccb8433SYueHaibing static void meson_viu_set_g12a_osd1_matrix(struct meson_drm *priv,
822ccb8433SYueHaibing 					   int *m, bool csc_on)
8372888394SNeil Armstrong {
8472888394SNeil Armstrong 	/* VPP WRAP OSD1 matrix */
8572888394SNeil Armstrong 	writel(((m[0] & 0xfff) << 16) | (m[1] & 0xfff),
8672888394SNeil Armstrong 		priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_PRE_OFFSET0_1));
8772888394SNeil Armstrong 	writel(m[2] & 0xfff,
8872888394SNeil Armstrong 		priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_PRE_OFFSET2));
8972888394SNeil Armstrong 	writel(((m[3] & 0x1fff) << 16) | (m[4] & 0x1fff),
9072888394SNeil Armstrong 		priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF00_01));
9172888394SNeil Armstrong 	writel(((m[5] & 0x1fff) << 16) | (m[6] & 0x1fff),
9272888394SNeil Armstrong 		priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF02_10));
9372888394SNeil Armstrong 	writel(((m[7] & 0x1fff) << 16) | (m[8] & 0x1fff),
9472888394SNeil Armstrong 		priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF11_12));
9572888394SNeil Armstrong 	writel(((m[9] & 0x1fff) << 16) | (m[10] & 0x1fff),
9672888394SNeil Armstrong 		priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF20_21));
976463d393SStuart Menefy 	writel((m[11] & 0x1fff),
9872888394SNeil Armstrong 		priv->io_base +	_REG(VPP_WRAP_OSD1_MATRIX_COEF22));
9972888394SNeil Armstrong 
10072888394SNeil Armstrong 	writel(((m[18] & 0xfff) << 16) | (m[19] & 0xfff),
10172888394SNeil Armstrong 		priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_OFFSET0_1));
10272888394SNeil Armstrong 	writel(m[20] & 0xfff,
10372888394SNeil Armstrong 		priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_OFFSET2));
10472888394SNeil Armstrong 
10572888394SNeil Armstrong 	writel_bits_relaxed(BIT(0), csc_on ? BIT(0) : 0,
10672888394SNeil Armstrong 		priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_EN_CTRL));
10772888394SNeil Armstrong }
10872888394SNeil Armstrong 
meson_viu_set_osd_matrix(struct meson_drm * priv,enum viu_matrix_sel_e m_select,int * m,bool csc_on)1092ccb8433SYueHaibing static void meson_viu_set_osd_matrix(struct meson_drm *priv,
110bbbe775eSNeil Armstrong 				     enum viu_matrix_sel_e m_select,
111bbbe775eSNeil Armstrong 			      int *m, bool csc_on)
112bbbe775eSNeil Armstrong {
113bbbe775eSNeil Armstrong 	if (m_select == VIU_MATRIX_OSD) {
114bbbe775eSNeil Armstrong 		/* osd matrix, VIU_MATRIX_0 */
115bbbe775eSNeil Armstrong 		writel(((m[0] & 0xfff) << 16) | (m[1] & 0xfff),
116bbbe775eSNeil Armstrong 			priv->io_base + _REG(VIU_OSD1_MATRIX_PRE_OFFSET0_1));
117bbbe775eSNeil Armstrong 		writel(m[2] & 0xfff,
118bbbe775eSNeil Armstrong 			priv->io_base + _REG(VIU_OSD1_MATRIX_PRE_OFFSET2));
119bbbe775eSNeil Armstrong 		writel(((m[3] & 0x1fff) << 16) | (m[4] & 0x1fff),
120bbbe775eSNeil Armstrong 			priv->io_base + _REG(VIU_OSD1_MATRIX_COEF00_01));
121bbbe775eSNeil Armstrong 		writel(((m[5] & 0x1fff) << 16) | (m[6] & 0x1fff),
122bbbe775eSNeil Armstrong 			priv->io_base + _REG(VIU_OSD1_MATRIX_COEF02_10));
123bbbe775eSNeil Armstrong 		writel(((m[7] & 0x1fff) << 16) | (m[8] & 0x1fff),
124bbbe775eSNeil Armstrong 			priv->io_base + _REG(VIU_OSD1_MATRIX_COEF11_12));
125bbbe775eSNeil Armstrong 		writel(((m[9] & 0x1fff) << 16) | (m[10] & 0x1fff),
126bbbe775eSNeil Armstrong 			priv->io_base + _REG(VIU_OSD1_MATRIX_COEF20_21));
127bbbe775eSNeil Armstrong 
128bbbe775eSNeil Armstrong 		if (m[21]) {
129bbbe775eSNeil Armstrong 			writel(((m[11] & 0x1fff) << 16) | (m[12] & 0x1fff),
130bbbe775eSNeil Armstrong 				priv->io_base +
131bbbe775eSNeil Armstrong 					_REG(VIU_OSD1_MATRIX_COEF22_30));
132bbbe775eSNeil Armstrong 			writel(((m[13] & 0x1fff) << 16) | (m[14] & 0x1fff),
133bbbe775eSNeil Armstrong 				priv->io_base +
134bbbe775eSNeil Armstrong 					_REG(VIU_OSD1_MATRIX_COEF31_32));
135bbbe775eSNeil Armstrong 			writel(((m[15] & 0x1fff) << 16) | (m[16] & 0x1fff),
136bbbe775eSNeil Armstrong 				priv->io_base +
137bbbe775eSNeil Armstrong 					_REG(VIU_OSD1_MATRIX_COEF40_41));
138bbbe775eSNeil Armstrong 			writel(m[17] & 0x1fff, priv->io_base +
139bbbe775eSNeil Armstrong 				_REG(VIU_OSD1_MATRIX_COLMOD_COEF42));
140bbbe775eSNeil Armstrong 		} else
141bbbe775eSNeil Armstrong 			writel((m[11] & 0x1fff) << 16, priv->io_base +
142bbbe775eSNeil Armstrong 				_REG(VIU_OSD1_MATRIX_COEF22_30));
143bbbe775eSNeil Armstrong 
144bbbe775eSNeil Armstrong 		writel(((m[18] & 0xfff) << 16) | (m[19] & 0xfff),
145bbbe775eSNeil Armstrong 			priv->io_base + _REG(VIU_OSD1_MATRIX_OFFSET0_1));
146bbbe775eSNeil Armstrong 		writel(m[20] & 0xfff,
147bbbe775eSNeil Armstrong 			priv->io_base + _REG(VIU_OSD1_MATRIX_OFFSET2));
148bbbe775eSNeil Armstrong 
149bbbe775eSNeil Armstrong 		writel_bits_relaxed(3 << 30, m[21] << 30,
150bbbe775eSNeil Armstrong 			priv->io_base + _REG(VIU_OSD1_MATRIX_COLMOD_COEF42));
151bbbe775eSNeil Armstrong 		writel_bits_relaxed(7 << 16, m[22] << 16,
152bbbe775eSNeil Armstrong 			priv->io_base + _REG(VIU_OSD1_MATRIX_COLMOD_COEF42));
153bbbe775eSNeil Armstrong 
154bbbe775eSNeil Armstrong 		/* 23 reserved for clipping control */
155bbbe775eSNeil Armstrong 		writel_bits_relaxed(BIT(0), csc_on ? BIT(0) : 0,
156bbbe775eSNeil Armstrong 			priv->io_base + _REG(VIU_OSD1_MATRIX_CTRL));
157bbbe775eSNeil Armstrong 		writel_bits_relaxed(BIT(1), 0,
158bbbe775eSNeil Armstrong 			priv->io_base + _REG(VIU_OSD1_MATRIX_CTRL));
159bbbe775eSNeil Armstrong 	} else if (m_select == VIU_MATRIX_OSD_EOTF) {
160bbbe775eSNeil Armstrong 		int i;
161bbbe775eSNeil Armstrong 
162bbbe775eSNeil Armstrong 		/* osd eotf matrix, VIU_MATRIX_OSD_EOTF */
163bbbe775eSNeil Armstrong 		for (i = 0; i < 5; i++)
164bbbe775eSNeil Armstrong 			writel(((m[i * 2] & 0x1fff) << 16) |
165bbbe775eSNeil Armstrong 				(m[i * 2 + 1] & 0x1fff), priv->io_base +
166bbbe775eSNeil Armstrong 				_REG(VIU_OSD1_EOTF_CTL + i + 1));
167bbbe775eSNeil Armstrong 
168bbbe775eSNeil Armstrong 		writel_bits_relaxed(BIT(30), csc_on ? BIT(30) : 0,
169bbbe775eSNeil Armstrong 			priv->io_base + _REG(VIU_OSD1_EOTF_CTL));
170bbbe775eSNeil Armstrong 		writel_bits_relaxed(BIT(31), csc_on ? BIT(31) : 0,
171bbbe775eSNeil Armstrong 			priv->io_base + _REG(VIU_OSD1_EOTF_CTL));
172bbbe775eSNeil Armstrong 	}
173bbbe775eSNeil Armstrong }
174bbbe775eSNeil Armstrong 
175bbbe775eSNeil Armstrong #define OSD_EOTF_LUT_SIZE 33
176bbbe775eSNeil Armstrong #define OSD_OETF_LUT_SIZE 41
177bbbe775eSNeil Armstrong 
1782ccb8433SYueHaibing static void
meson_viu_set_osd_lut(struct meson_drm * priv,enum viu_lut_sel_e lut_sel,unsigned int * r_map,unsigned int * g_map,unsigned int * b_map,bool csc_on)1792ccb8433SYueHaibing meson_viu_set_osd_lut(struct meson_drm *priv, enum viu_lut_sel_e lut_sel,
180bbbe775eSNeil Armstrong 		      unsigned int *r_map, unsigned int *g_map,
1812ccb8433SYueHaibing 		      unsigned int *b_map, bool csc_on)
182bbbe775eSNeil Armstrong {
183bbbe775eSNeil Armstrong 	unsigned int addr_port;
184bbbe775eSNeil Armstrong 	unsigned int data_port;
185bbbe775eSNeil Armstrong 	unsigned int ctrl_port;
186bbbe775eSNeil Armstrong 	int i;
187bbbe775eSNeil Armstrong 
188bbbe775eSNeil Armstrong 	if (lut_sel == VIU_LUT_OSD_EOTF) {
189bbbe775eSNeil Armstrong 		addr_port = VIU_OSD1_EOTF_LUT_ADDR_PORT;
190bbbe775eSNeil Armstrong 		data_port = VIU_OSD1_EOTF_LUT_DATA_PORT;
191bbbe775eSNeil Armstrong 		ctrl_port = VIU_OSD1_EOTF_CTL;
192bbbe775eSNeil Armstrong 	} else if (lut_sel == VIU_LUT_OSD_OETF) {
193bbbe775eSNeil Armstrong 		addr_port = VIU_OSD1_OETF_LUT_ADDR_PORT;
194bbbe775eSNeil Armstrong 		data_port = VIU_OSD1_OETF_LUT_DATA_PORT;
195bbbe775eSNeil Armstrong 		ctrl_port = VIU_OSD1_OETF_CTL;
196bbbe775eSNeil Armstrong 	} else
197bbbe775eSNeil Armstrong 		return;
198bbbe775eSNeil Armstrong 
199bbbe775eSNeil Armstrong 	if (lut_sel == VIU_LUT_OSD_OETF) {
200bbbe775eSNeil Armstrong 		writel(0, priv->io_base + _REG(addr_port));
201bbbe775eSNeil Armstrong 
20297b2a318SLyude Paul 		for (i = 0; i < (OSD_OETF_LUT_SIZE / 2); i++)
203bbbe775eSNeil Armstrong 			writel(r_map[i * 2] | (r_map[i * 2 + 1] << 16),
204bbbe775eSNeil Armstrong 				priv->io_base + _REG(data_port));
205bbbe775eSNeil Armstrong 
206bbbe775eSNeil Armstrong 		writel(r_map[OSD_OETF_LUT_SIZE - 1] | (g_map[0] << 16),
207bbbe775eSNeil Armstrong 			priv->io_base + _REG(data_port));
208bbbe775eSNeil Armstrong 
20997b2a318SLyude Paul 		for (i = 0; i < (OSD_OETF_LUT_SIZE / 2); i++)
210bbbe775eSNeil Armstrong 			writel(g_map[i * 2 + 1] | (g_map[i * 2 + 2] << 16),
211bbbe775eSNeil Armstrong 				priv->io_base + _REG(data_port));
212bbbe775eSNeil Armstrong 
21397b2a318SLyude Paul 		for (i = 0; i < (OSD_OETF_LUT_SIZE / 2); i++)
214bbbe775eSNeil Armstrong 			writel(b_map[i * 2] | (b_map[i * 2 + 1] << 16),
215bbbe775eSNeil Armstrong 				priv->io_base + _REG(data_port));
216bbbe775eSNeil Armstrong 
217bbbe775eSNeil Armstrong 		writel(b_map[OSD_OETF_LUT_SIZE - 1],
218bbbe775eSNeil Armstrong 			priv->io_base + _REG(data_port));
219bbbe775eSNeil Armstrong 
220bbbe775eSNeil Armstrong 		if (csc_on)
221bbbe775eSNeil Armstrong 			writel_bits_relaxed(0x7 << 29, 7 << 29,
222bbbe775eSNeil Armstrong 					    priv->io_base + _REG(ctrl_port));
223bbbe775eSNeil Armstrong 		else
224bbbe775eSNeil Armstrong 			writel_bits_relaxed(0x7 << 29, 0,
225bbbe775eSNeil Armstrong 					    priv->io_base + _REG(ctrl_port));
226bbbe775eSNeil Armstrong 	} else if (lut_sel == VIU_LUT_OSD_EOTF) {
227bbbe775eSNeil Armstrong 		writel(0, priv->io_base + _REG(addr_port));
228bbbe775eSNeil Armstrong 
22997b2a318SLyude Paul 		for (i = 0; i < (OSD_EOTF_LUT_SIZE / 2); i++)
230bbbe775eSNeil Armstrong 			writel(r_map[i * 2] | (r_map[i * 2 + 1] << 16),
231bbbe775eSNeil Armstrong 				priv->io_base + _REG(data_port));
232bbbe775eSNeil Armstrong 
233bbbe775eSNeil Armstrong 		writel(r_map[OSD_EOTF_LUT_SIZE - 1] | (g_map[0] << 16),
234bbbe775eSNeil Armstrong 			priv->io_base + _REG(data_port));
235bbbe775eSNeil Armstrong 
23697b2a318SLyude Paul 		for (i = 0; i < (OSD_EOTF_LUT_SIZE / 2); i++)
237bbbe775eSNeil Armstrong 			writel(g_map[i * 2 + 1] | (g_map[i * 2 + 2] << 16),
238bbbe775eSNeil Armstrong 				priv->io_base + _REG(data_port));
239bbbe775eSNeil Armstrong 
24097b2a318SLyude Paul 		for (i = 0; i < (OSD_EOTF_LUT_SIZE / 2); i++)
241bbbe775eSNeil Armstrong 			writel(b_map[i * 2] | (b_map[i * 2 + 1] << 16),
242bbbe775eSNeil Armstrong 				priv->io_base + _REG(data_port));
243bbbe775eSNeil Armstrong 
244bbbe775eSNeil Armstrong 		writel(b_map[OSD_EOTF_LUT_SIZE - 1],
245bbbe775eSNeil Armstrong 			priv->io_base + _REG(data_port));
246bbbe775eSNeil Armstrong 
247bbbe775eSNeil Armstrong 		if (csc_on)
248bbbe775eSNeil Armstrong 			writel_bits_relaxed(7 << 27, 7 << 27,
249bbbe775eSNeil Armstrong 					    priv->io_base + _REG(ctrl_port));
250bbbe775eSNeil Armstrong 		else
251bbbe775eSNeil Armstrong 			writel_bits_relaxed(7 << 27, 0,
252bbbe775eSNeil Armstrong 					    priv->io_base + _REG(ctrl_port));
253bbbe775eSNeil Armstrong 
254bbbe775eSNeil Armstrong 		writel_bits_relaxed(BIT(31), BIT(31),
255bbbe775eSNeil Armstrong 				    priv->io_base + _REG(ctrl_port));
256bbbe775eSNeil Armstrong 	}
257bbbe775eSNeil Armstrong }
258bbbe775eSNeil Armstrong 
259bbbe775eSNeil Armstrong /* eotf lut: linear */
260bbbe775eSNeil Armstrong static unsigned int eotf_33_linear_mapping[OSD_EOTF_LUT_SIZE] = {
261bbbe775eSNeil Armstrong 	0x0000,	0x0200,	0x0400, 0x0600,
262bbbe775eSNeil Armstrong 	0x0800, 0x0a00, 0x0c00, 0x0e00,
263bbbe775eSNeil Armstrong 	0x1000, 0x1200, 0x1400, 0x1600,
264bbbe775eSNeil Armstrong 	0x1800, 0x1a00, 0x1c00, 0x1e00,
265bbbe775eSNeil Armstrong 	0x2000, 0x2200, 0x2400, 0x2600,
266bbbe775eSNeil Armstrong 	0x2800, 0x2a00, 0x2c00, 0x2e00,
267bbbe775eSNeil Armstrong 	0x3000, 0x3200, 0x3400, 0x3600,
268bbbe775eSNeil Armstrong 	0x3800, 0x3a00, 0x3c00, 0x3e00,
269bbbe775eSNeil Armstrong 	0x4000
270bbbe775eSNeil Armstrong };
271bbbe775eSNeil Armstrong 
272bbbe775eSNeil Armstrong /* osd oetf lut: linear */
273bbbe775eSNeil Armstrong static unsigned int oetf_41_linear_mapping[OSD_OETF_LUT_SIZE] = {
274bbbe775eSNeil Armstrong 	0, 0, 0, 0,
275bbbe775eSNeil Armstrong 	0, 32, 64, 96,
276bbbe775eSNeil Armstrong 	128, 160, 196, 224,
277bbbe775eSNeil Armstrong 	256, 288, 320, 352,
278bbbe775eSNeil Armstrong 	384, 416, 448, 480,
279bbbe775eSNeil Armstrong 	512, 544, 576, 608,
280bbbe775eSNeil Armstrong 	640, 672, 704, 736,
281bbbe775eSNeil Armstrong 	768, 800, 832, 864,
282bbbe775eSNeil Armstrong 	896, 928, 960, 992,
283bbbe775eSNeil Armstrong 	1023, 1023, 1023, 1023,
284bbbe775eSNeil Armstrong 	1023
285bbbe775eSNeil Armstrong };
286bbbe775eSNeil Armstrong 
meson_viu_load_matrix(struct meson_drm * priv)287bbbe775eSNeil Armstrong static void meson_viu_load_matrix(struct meson_drm *priv)
288bbbe775eSNeil Armstrong {
289bbbe775eSNeil Armstrong 	/* eotf lut bypass */
290bbbe775eSNeil Armstrong 	meson_viu_set_osd_lut(priv, VIU_LUT_OSD_EOTF,
291bbbe775eSNeil Armstrong 			      eotf_33_linear_mapping, /* R */
292bbbe775eSNeil Armstrong 			      eotf_33_linear_mapping, /* G */
293bbbe775eSNeil Armstrong 			      eotf_33_linear_mapping, /* B */
294bbbe775eSNeil Armstrong 			      false);
295bbbe775eSNeil Armstrong 
296bbbe775eSNeil Armstrong 	/* eotf matrix bypass */
297bbbe775eSNeil Armstrong 	meson_viu_set_osd_matrix(priv, VIU_MATRIX_OSD_EOTF,
298bbbe775eSNeil Armstrong 				 eotf_bypass_coeff,
299bbbe775eSNeil Armstrong 				 false);
300bbbe775eSNeil Armstrong 
301bbbe775eSNeil Armstrong 	/* oetf lut bypass */
302bbbe775eSNeil Armstrong 	meson_viu_set_osd_lut(priv, VIU_LUT_OSD_OETF,
303bbbe775eSNeil Armstrong 			      oetf_41_linear_mapping, /* R */
304bbbe775eSNeil Armstrong 			      oetf_41_linear_mapping, /* G */
305bbbe775eSNeil Armstrong 			      oetf_41_linear_mapping, /* B */
306bbbe775eSNeil Armstrong 			      false);
307bbbe775eSNeil Armstrong 
308bbbe775eSNeil Armstrong 	/* osd matrix RGB709 to YUV709 limit */
309bbbe775eSNeil Armstrong 	meson_viu_set_osd_matrix(priv, VIU_MATRIX_OSD,
310bbbe775eSNeil Armstrong 				 RGB709_to_YUV709l_coeff,
311bbbe775eSNeil Armstrong 				 true);
312bbbe775eSNeil Armstrong }
313bbbe775eSNeil Armstrong 
3143a936bc2SNeil Armstrong /* VIU OSD1 Reset as workaround for GXL+ Alpha OSD Bug */
meson_viu_osd1_reset(struct meson_drm * priv)3153a936bc2SNeil Armstrong void meson_viu_osd1_reset(struct meson_drm *priv)
3163a936bc2SNeil Armstrong {
3173a936bc2SNeil Armstrong 	uint32_t osd1_fifo_ctrl_stat, osd1_ctrl_stat2;
3183a936bc2SNeil Armstrong 
3193a936bc2SNeil Armstrong 	/* Save these 2 registers state */
3203a936bc2SNeil Armstrong 	osd1_fifo_ctrl_stat = readl_relaxed(
3213a936bc2SNeil Armstrong 				priv->io_base + _REG(VIU_OSD1_FIFO_CTRL_STAT));
3223a936bc2SNeil Armstrong 	osd1_ctrl_stat2 = readl_relaxed(
3233a936bc2SNeil Armstrong 				priv->io_base + _REG(VIU_OSD1_CTRL_STAT2));
3243a936bc2SNeil Armstrong 
3253a936bc2SNeil Armstrong 	/* Reset OSD1 */
326147ae1cbSJulien Masson 	writel_bits_relaxed(VIU_SW_RESET_OSD1, VIU_SW_RESET_OSD1,
3273a936bc2SNeil Armstrong 			    priv->io_base + _REG(VIU_SW_RESET));
328147ae1cbSJulien Masson 	writel_bits_relaxed(VIU_SW_RESET_OSD1, 0,
3293a936bc2SNeil Armstrong 			    priv->io_base + _REG(VIU_SW_RESET));
3303a936bc2SNeil Armstrong 
3313a936bc2SNeil Armstrong 	/* Rewrite these registers state lost in the reset */
3323a936bc2SNeil Armstrong 	writel_relaxed(osd1_fifo_ctrl_stat,
3333a936bc2SNeil Armstrong 		       priv->io_base + _REG(VIU_OSD1_FIFO_CTRL_STAT));
3343a936bc2SNeil Armstrong 	writel_relaxed(osd1_ctrl_stat2,
3353a936bc2SNeil Armstrong 		       priv->io_base + _REG(VIU_OSD1_CTRL_STAT2));
3363a936bc2SNeil Armstrong 
3373a936bc2SNeil Armstrong 	/* Reload the conversion matrix */
3383a936bc2SNeil Armstrong 	meson_viu_load_matrix(priv);
3393a936bc2SNeil Armstrong }
3403a936bc2SNeil Armstrong 
3411b85270fSNeil Armstrong #define OSD1_MALI_ORDER_ABGR				\
3421b85270fSNeil Armstrong 	(FIELD_PREP(VIU_OSD1_MALI_AFBCD_A_REORDER,	\
3431b85270fSNeil Armstrong 		    VIU_OSD1_MALI_REORDER_A) |		\
3441b85270fSNeil Armstrong 	 FIELD_PREP(VIU_OSD1_MALI_AFBCD_B_REORDER,	\
3451b85270fSNeil Armstrong 		    VIU_OSD1_MALI_REORDER_B) |		\
3461b85270fSNeil Armstrong 	 FIELD_PREP(VIU_OSD1_MALI_AFBCD_G_REORDER,	\
3471b85270fSNeil Armstrong 		    VIU_OSD1_MALI_REORDER_G) |		\
3481b85270fSNeil Armstrong 	 FIELD_PREP(VIU_OSD1_MALI_AFBCD_R_REORDER,	\
3491b85270fSNeil Armstrong 		    VIU_OSD1_MALI_REORDER_R))
3501b85270fSNeil Armstrong 
3511b85270fSNeil Armstrong #define OSD1_MALI_ORDER_ARGB				\
3521b85270fSNeil Armstrong 	(FIELD_PREP(VIU_OSD1_MALI_AFBCD_A_REORDER,	\
3531b85270fSNeil Armstrong 		    VIU_OSD1_MALI_REORDER_A) |		\
3541b85270fSNeil Armstrong 	 FIELD_PREP(VIU_OSD1_MALI_AFBCD_B_REORDER,	\
3551b85270fSNeil Armstrong 		    VIU_OSD1_MALI_REORDER_R) |		\
3561b85270fSNeil Armstrong 	 FIELD_PREP(VIU_OSD1_MALI_AFBCD_G_REORDER,	\
3571b85270fSNeil Armstrong 		    VIU_OSD1_MALI_REORDER_G) |		\
3581b85270fSNeil Armstrong 	 FIELD_PREP(VIU_OSD1_MALI_AFBCD_R_REORDER,	\
3591b85270fSNeil Armstrong 		    VIU_OSD1_MALI_REORDER_B))
3601b85270fSNeil Armstrong 
meson_viu_g12a_enable_osd1_afbc(struct meson_drm * priv)3611b85270fSNeil Armstrong void meson_viu_g12a_enable_osd1_afbc(struct meson_drm *priv)
3621b85270fSNeil Armstrong {
3631b85270fSNeil Armstrong 	u32 afbc_order = OSD1_MALI_ORDER_ARGB;
3641b85270fSNeil Armstrong 
3651b85270fSNeil Armstrong 	/* Enable Mali AFBC Unpack */
3661b85270fSNeil Armstrong 	writel_bits_relaxed(VIU_OSD1_MALI_UNPACK_EN,
3671b85270fSNeil Armstrong 			    VIU_OSD1_MALI_UNPACK_EN,
3681b85270fSNeil Armstrong 			    priv->io_base + _REG(VIU_OSD1_MALI_UNPACK_CTRL));
3691b85270fSNeil Armstrong 
3701b85270fSNeil Armstrong 	switch (priv->afbcd.format) {
3711b85270fSNeil Armstrong 	case DRM_FORMAT_XBGR8888:
3721b85270fSNeil Armstrong 	case DRM_FORMAT_ABGR8888:
3731b85270fSNeil Armstrong 		afbc_order = OSD1_MALI_ORDER_ABGR;
3741b85270fSNeil Armstrong 		break;
3751b85270fSNeil Armstrong 	}
3761b85270fSNeil Armstrong 
3771b85270fSNeil Armstrong 	/* Setup RGBA Reordering */
3781b85270fSNeil Armstrong 	writel_bits_relaxed(VIU_OSD1_MALI_AFBCD_A_REORDER |
3791b85270fSNeil Armstrong 			    VIU_OSD1_MALI_AFBCD_B_REORDER |
3801b85270fSNeil Armstrong 			    VIU_OSD1_MALI_AFBCD_G_REORDER |
3811b85270fSNeil Armstrong 			    VIU_OSD1_MALI_AFBCD_R_REORDER,
3821b85270fSNeil Armstrong 			    afbc_order,
3831b85270fSNeil Armstrong 			    priv->io_base + _REG(VIU_OSD1_MALI_UNPACK_CTRL));
3841b85270fSNeil Armstrong 
3851b85270fSNeil Armstrong 	/* Select AFBCD path for OSD1 */
3861b85270fSNeil Armstrong 	writel_bits_relaxed(OSD_PATH_OSD_AXI_SEL_OSD1_AFBCD,
3871b85270fSNeil Armstrong 			    OSD_PATH_OSD_AXI_SEL_OSD1_AFBCD,
3881b85270fSNeil Armstrong 			    priv->io_base + _REG(OSD_PATH_MISC_CTRL));
3891b85270fSNeil Armstrong }
3901b85270fSNeil Armstrong 
meson_viu_g12a_disable_osd1_afbc(struct meson_drm * priv)3911b85270fSNeil Armstrong void meson_viu_g12a_disable_osd1_afbc(struct meson_drm *priv)
3921b85270fSNeil Armstrong {
3931b85270fSNeil Armstrong 	/* Disable AFBCD path for OSD1 */
3941b85270fSNeil Armstrong 	writel_bits_relaxed(OSD_PATH_OSD_AXI_SEL_OSD1_AFBCD, 0,
3951b85270fSNeil Armstrong 			    priv->io_base + _REG(OSD_PATH_MISC_CTRL));
3961b85270fSNeil Armstrong 
3971b85270fSNeil Armstrong 	/* Disable AFBCD unpack */
3981b85270fSNeil Armstrong 	writel_bits_relaxed(VIU_OSD1_MALI_UNPACK_EN, 0,
3991b85270fSNeil Armstrong 			    priv->io_base + _REG(VIU_OSD1_MALI_UNPACK_CTRL));
4001b85270fSNeil Armstrong }
4011b85270fSNeil Armstrong 
meson_viu_gxm_enable_osd1_afbc(struct meson_drm * priv)4021b85270fSNeil Armstrong void meson_viu_gxm_enable_osd1_afbc(struct meson_drm *priv)
4031b85270fSNeil Armstrong {
4041b85270fSNeil Armstrong 	writel_bits_relaxed(MALI_AFBC_MISC, FIELD_PREP(MALI_AFBC_MISC, 0x90),
4051b85270fSNeil Armstrong 			    priv->io_base + _REG(VIU_MISC_CTRL1));
4061b85270fSNeil Armstrong }
4071b85270fSNeil Armstrong 
meson_viu_gxm_disable_osd1_afbc(struct meson_drm * priv)4081b85270fSNeil Armstrong void meson_viu_gxm_disable_osd1_afbc(struct meson_drm *priv)
4091b85270fSNeil Armstrong {
4101b85270fSNeil Armstrong 	writel_bits_relaxed(MALI_AFBC_MISC, FIELD_PREP(MALI_AFBC_MISC, 0x00),
4111b85270fSNeil Armstrong 			    priv->io_base + _REG(VIU_MISC_CTRL1));
4121b85270fSNeil Armstrong }
4131b85270fSNeil Armstrong 
meson_viu_init(struct meson_drm * priv)414bbbe775eSNeil Armstrong void meson_viu_init(struct meson_drm *priv)
415bbbe775eSNeil Armstrong {
416bbbe775eSNeil Armstrong 	uint32_t reg;
417bbbe775eSNeil Armstrong 
418bbbe775eSNeil Armstrong 	/* Disable OSDs */
419147ae1cbSJulien Masson 	writel_bits_relaxed(VIU_OSD1_OSD_BLK_ENABLE | VIU_OSD1_OSD_ENABLE, 0,
420bbbe775eSNeil Armstrong 			    priv->io_base + _REG(VIU_OSD1_CTRL_STAT));
421147ae1cbSJulien Masson 	writel_bits_relaxed(VIU_OSD1_OSD_BLK_ENABLE | VIU_OSD1_OSD_ENABLE, 0,
422bbbe775eSNeil Armstrong 			    priv->io_base + _REG(VIU_OSD2_CTRL_STAT));
423bbbe775eSNeil Armstrong 
424bbbe775eSNeil Armstrong 	/* On GXL/GXM, Use the 10bit HDR conversion matrix */
425528a25d0SJulien Masson 	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) ||
426528a25d0SJulien Masson 	    meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL))
427bbbe775eSNeil Armstrong 		meson_viu_load_matrix(priv);
428bf33677aSChristian Hewitt 	else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
42972888394SNeil Armstrong 		meson_viu_set_g12a_osd1_matrix(priv, RGB709_to_YUV709l_coeff,
43072888394SNeil Armstrong 					       true);
431bf33677aSChristian Hewitt 		/* fix green/pink color distortion from vendor u-boot */
432bf33677aSChristian Hewitt 		writel_bits_relaxed(OSD1_HDR2_CTRL_REG_ONLY_MAT |
433bf33677aSChristian Hewitt 				OSD1_HDR2_CTRL_VDIN0_HDR2_TOP_EN, 0,
434bf33677aSChristian Hewitt 				priv->io_base + _REG(OSD1_HDR2_CTRL));
435bf33677aSChristian Hewitt 	}
436bbbe775eSNeil Armstrong 
437bbbe775eSNeil Armstrong 	/* Initialize OSD1 fifo control register */
438147ae1cbSJulien Masson 	reg = VIU_OSD_DDR_PRIORITY_URGENT |
439147ae1cbSJulien Masson 		VIU_OSD_FIFO_DEPTH_VAL(32) | /* fifo_depth_val: 32*8=256 */
440147ae1cbSJulien Masson 		VIU_OSD_WORDS_PER_BURST(4) | /* 4 words in 1 burst */
441147ae1cbSJulien Masson 		VIU_OSD_FIFO_LIMITS(2);      /* fifo_lim: 2*16=32 */
442147ae1cbSJulien Masson 
443528a25d0SJulien Masson 	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
444*3b754ed6SCarlo Caione 		reg |= (VIU_OSD_BURST_LENGTH_32 | VIU_OSD_HOLD_FIFO_LINES(31));
44572888394SNeil Armstrong 	else
446*3b754ed6SCarlo Caione 		reg |= (VIU_OSD_BURST_LENGTH_64 | VIU_OSD_HOLD_FIFO_LINES(4));
447147ae1cbSJulien Masson 
448bbbe775eSNeil Armstrong 	writel_relaxed(reg, priv->io_base + _REG(VIU_OSD1_FIFO_CTRL_STAT));
449bbbe775eSNeil Armstrong 	writel_relaxed(reg, priv->io_base + _REG(VIU_OSD2_FIFO_CTRL_STAT));
450bbbe775eSNeil Armstrong 
451bbbe775eSNeil Armstrong 	/* Set OSD alpha replace value */
452bbbe775eSNeil Armstrong 	writel_bits_relaxed(0xff << OSD_REPLACE_SHIFT,
453bbbe775eSNeil Armstrong 			    0xff << OSD_REPLACE_SHIFT,
454bbbe775eSNeil Armstrong 			    priv->io_base + _REG(VIU_OSD1_CTRL_STAT2));
455bbbe775eSNeil Armstrong 	writel_bits_relaxed(0xff << OSD_REPLACE_SHIFT,
456bbbe775eSNeil Armstrong 			    0xff << OSD_REPLACE_SHIFT,
457bbbe775eSNeil Armstrong 			    priv->io_base + _REG(VIU_OSD2_CTRL_STAT2));
458bbbe775eSNeil Armstrong 
459f9a23481SNeil Armstrong 	/* Disable VD1 AFBC */
460147ae1cbSJulien Masson 	/* di_mif0_en=0 mif0_to_vpp_en=0 di_mad_en=0 and afbc vd1 set=0*/
461147ae1cbSJulien Masson 	writel_bits_relaxed(VIU_CTRL0_VD1_AFBC_MASK, 0,
462f9a23481SNeil Armstrong 			    priv->io_base + _REG(VIU_MISC_CTRL0));
463f9a23481SNeil Armstrong 	writel_relaxed(0, priv->io_base + _REG(AFBC_ENABLE));
464f9a23481SNeil Armstrong 
465f9a23481SNeil Armstrong 	writel_relaxed(0x00FF00C0,
466f9a23481SNeil Armstrong 			priv->io_base + _REG(VD1_IF0_LUMA_FIFO_SIZE));
467f9a23481SNeil Armstrong 	writel_relaxed(0x00FF00C0,
468f9a23481SNeil Armstrong 			priv->io_base + _REG(VD2_IF0_LUMA_FIFO_SIZE));
469f9a23481SNeil Armstrong 
470528a25d0SJulien Masson 	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
47198692f52SSai Prakash Ranjan 		u32 val = (u32)VIU_OSD_BLEND_REORDER(0, 1) |
47298692f52SSai Prakash Ranjan 			  (u32)VIU_OSD_BLEND_REORDER(1, 0) |
47398692f52SSai Prakash Ranjan 			  (u32)VIU_OSD_BLEND_REORDER(2, 0) |
47498692f52SSai Prakash Ranjan 			  (u32)VIU_OSD_BLEND_REORDER(3, 0) |
47598692f52SSai Prakash Ranjan 			  (u32)VIU_OSD_BLEND_DIN_EN(1) |
47698692f52SSai Prakash Ranjan 			  (u32)VIU_OSD_BLEND1_DIN3_BYPASS_TO_DOUT1 |
47798692f52SSai Prakash Ranjan 			  (u32)VIU_OSD_BLEND1_DOUT_BYPASS_TO_BLEND2 |
47898692f52SSai Prakash Ranjan 			  (u32)VIU_OSD_BLEND_DIN0_BYPASS_TO_DOUT0 |
47998692f52SSai Prakash Ranjan 			  (u32)VIU_OSD_BLEND_BLEN2_PREMULT_EN(1) |
48098692f52SSai Prakash Ranjan 			  (u32)VIU_OSD_BLEND_HOLD_LINES(4);
48198692f52SSai Prakash Ranjan 		writel_relaxed(val, priv->io_base + _REG(VIU_OSD_BLEND_CTRL));
482147ae1cbSJulien Masson 
483147ae1cbSJulien Masson 		writel_relaxed(OSD_BLEND_PATH_SEL_ENABLE,
48472888394SNeil Armstrong 			       priv->io_base + _REG(OSD1_BLEND_SRC_CTRL));
485147ae1cbSJulien Masson 		writel_relaxed(OSD_BLEND_PATH_SEL_ENABLE,
48672888394SNeil Armstrong 			       priv->io_base + _REG(OSD2_BLEND_SRC_CTRL));
48772888394SNeil Armstrong 		writel_relaxed(0, priv->io_base + _REG(VD1_BLEND_SRC_CTRL));
48872888394SNeil Armstrong 		writel_relaxed(0, priv->io_base + _REG(VD2_BLEND_SRC_CTRL));
48972888394SNeil Armstrong 		writel_relaxed(0,
49072888394SNeil Armstrong 				priv->io_base + _REG(VIU_OSD_BLEND_DUMMY_DATA0));
49172888394SNeil Armstrong 		writel_relaxed(0,
49272888394SNeil Armstrong 				priv->io_base + _REG(VIU_OSD_BLEND_DUMMY_ALPHA));
493147ae1cbSJulien Masson 
494147ae1cbSJulien Masson 		writel_bits_relaxed(DOLBY_BYPASS_EN(0xc), DOLBY_BYPASS_EN(0xc),
49572888394SNeil Armstrong 				    priv->io_base + _REG(DOLBY_PATH_CTRL));
4961b85270fSNeil Armstrong 
4971b85270fSNeil Armstrong 		meson_viu_g12a_disable_osd1_afbc(priv);
49872888394SNeil Armstrong 	}
499f9a23481SNeil Armstrong 
5001b85270fSNeil Armstrong 	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM))
5011b85270fSNeil Armstrong 		meson_viu_gxm_disable_osd1_afbc(priv);
5021b85270fSNeil Armstrong 
503bbbe775eSNeil Armstrong 	priv->viu.osd1_enabled = false;
504bbbe775eSNeil Armstrong 	priv->viu.osd1_commit = false;
505bbbe775eSNeil Armstrong 	priv->viu.osd1_interlace = false;
506bbbe775eSNeil Armstrong }
507