1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Amlogic Meson Video Processing Unit driver
4  *
5  * Copyright (c) 2018 BayLibre, SAS.
6  * Author: Neil Armstrong <narmstrong@baylibre.com>
7  */
8 
9 #define DEBUG
10 
11 #include <common.h>
12 #include <dm.h>
13 #include <asm/io.h>
14 #include <linux/bitops.h>
15 
16 #include "meson_vpu.h"
17 
18 /* HHI Registers */
19 #define HHI_VDAC_CNTL0		0x2F4 /* 0xbd offset in data sheet */
20 #define HHI_VDAC_CNTL0_G12A	0x2EC /* 0xbd offset in data sheet */
21 #define HHI_VDAC_CNTL1		0x2F8 /* 0xbe offset in data sheet */
22 #define HHI_VDAC_CNTL1_G12A	0x2F0 /* 0xbe offset in data sheet */
23 #define HHI_HDMI_PHY_CNTL0	0x3a0 /* 0xe8 offset in data sheet */
24 
25 /* OSDx_CTRL_STAT2 */
26 #define OSD_REPLACE_EN		BIT(14)
27 #define OSD_REPLACE_SHIFT	6
28 
meson_vpp_setup_mux(struct meson_vpu_priv * priv,unsigned int mux)29 void meson_vpp_setup_mux(struct meson_vpu_priv *priv, unsigned int mux)
30 {
31 	writel(mux, priv->io_base + _REG(VPU_VIU_VENC_MUX_CTRL));
32 }
33 
34 static unsigned int vpp_filter_coefs_4point_bspline[] = {
35 	0x15561500, 0x14561600, 0x13561700, 0x12561800,
36 	0x11551a00, 0x11541b00, 0x10541c00, 0x0f541d00,
37 	0x0f531e00, 0x0e531f00, 0x0d522100, 0x0c522200,
38 	0x0b522300, 0x0b512400, 0x0a502600, 0x0a4f2700,
39 	0x094e2900, 0x084e2a00, 0x084d2b00, 0x074c2c01,
40 	0x074b2d01, 0x064a2f01, 0x06493001, 0x05483201,
41 	0x05473301, 0x05463401, 0x04453601, 0x04433702,
42 	0x04423802, 0x03413a02, 0x03403b02, 0x033f3c02,
43 	0x033d3d03
44 };
45 
meson_vpp_write_scaling_filter_coefs(struct meson_vpu_priv * priv,const unsigned int * coefs,bool is_horizontal)46 static void meson_vpp_write_scaling_filter_coefs(struct meson_vpu_priv *priv,
47 						 const unsigned int *coefs,
48 						 bool is_horizontal)
49 {
50 	int i;
51 
52 	writel(is_horizontal ? VPP_SCALE_HORIZONTAL_COEF : 0,
53 	       priv->io_base + _REG(VPP_OSD_SCALE_COEF_IDX));
54 	for (i = 0; i < 33; i++)
55 		writel(coefs[i],
56 		       priv->io_base + _REG(VPP_OSD_SCALE_COEF));
57 }
58 
59 static const u32 vpp_filter_coefs_bicubic[] = {
60 	0x00800000, 0x007f0100, 0xff7f0200, 0xfe7f0300,
61 	0xfd7e0500, 0xfc7e0600, 0xfb7d0800, 0xfb7c0900,
62 	0xfa7b0b00, 0xfa7a0dff, 0xf9790fff, 0xf97711ff,
63 	0xf87613ff, 0xf87416fe, 0xf87218fe, 0xf8701afe,
64 	0xf76f1dfd, 0xf76d1ffd, 0xf76b21fd, 0xf76824fd,
65 	0xf76627fc, 0xf76429fc, 0xf7612cfc, 0xf75f2ffb,
66 	0xf75d31fb, 0xf75a34fb, 0xf75837fa, 0xf7553afa,
67 	0xf8523cfa, 0xf8503ff9, 0xf84d42f9, 0xf84a45f9,
68 	0xf84848f8
69 };
70 
meson_vpp_write_vd_scaling_filter_coefs(struct meson_vpu_priv * priv,const unsigned int * coefs,bool is_horizontal)71 static void meson_vpp_write_vd_scaling_filter_coefs(struct meson_vpu_priv *priv,
72 						    const unsigned int *coefs,
73 						    bool is_horizontal)
74 {
75 	int i;
76 
77 	writel(is_horizontal ? VPP_SCALE_HORIZONTAL_COEF : 0,
78 	       priv->io_base + _REG(VPP_SCALE_COEF_IDX));
79 	for (i = 0; i < 33; i++)
80 		writel(coefs[i],
81 		       priv->io_base + _REG(VPP_SCALE_COEF));
82 }
83 
84 /* OSD csc defines */
85 
86 enum viu_matrix_sel_e {
87 	VIU_MATRIX_OSD_EOTF = 0,
88 	VIU_MATRIX_OSD,
89 };
90 
91 enum viu_lut_sel_e {
92 	VIU_LUT_OSD_EOTF = 0,
93 	VIU_LUT_OSD_OETF,
94 };
95 
96 #define COEFF_NORM(a) ((int)((((a) * 2048.0) + 1) / 2))
97 #define MATRIX_5X3_COEF_SIZE 24
98 
99 #define EOTF_COEFF_NORM(a) ((int)((((a) * 4096.0) + 1) / 2))
100 #define EOTF_COEFF_SIZE 10
101 #define EOTF_COEFF_RIGHTSHIFT 1
102 
103 static int RGB709_to_YUV709l_coeff[MATRIX_5X3_COEF_SIZE] = {
104 	0, 0, 0, /* pre offset */
105 	COEFF_NORM(0.181873),	COEFF_NORM(0.611831),	COEFF_NORM(0.061765),
106 	COEFF_NORM(-0.100251),	COEFF_NORM(-0.337249),	COEFF_NORM(0.437500),
107 	COEFF_NORM(0.437500),	COEFF_NORM(-0.397384),	COEFF_NORM(-0.040116),
108 	0, 0, 0, /* 10'/11'/12' */
109 	0, 0, 0, /* 20'/21'/22' */
110 	64, 512, 512, /* offset */
111 	0, 0, 0 /* mode, right_shift, clip_en */
112 };
113 
114 /*  eotf matrix: bypass */
115 static int eotf_bypass_coeff[EOTF_COEFF_SIZE] = {
116 	EOTF_COEFF_NORM(1.0),	EOTF_COEFF_NORM(0.0),	EOTF_COEFF_NORM(0.0),
117 	EOTF_COEFF_NORM(0.0),	EOTF_COEFF_NORM(1.0),	EOTF_COEFF_NORM(0.0),
118 	EOTF_COEFF_NORM(0.0),	EOTF_COEFF_NORM(0.0),	EOTF_COEFF_NORM(1.0),
119 	EOTF_COEFF_RIGHTSHIFT /* right shift */
120 };
121 
meson_viu_set_g12a_osd1_matrix(struct meson_vpu_priv * priv,int * m,bool csc_on)122 static void meson_viu_set_g12a_osd1_matrix(struct meson_vpu_priv *priv,
123 					   int *m, bool csc_on)
124 {
125 	/* VPP WRAP OSD1 matrix */
126 	writel(((m[0] & 0xfff) << 16) | (m[1] & 0xfff),
127 	       priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_PRE_OFFSET0_1));
128 	writel(m[2] & 0xfff,
129 	       priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_PRE_OFFSET2));
130 	writel(((m[3] & 0x1fff) << 16) | (m[4] & 0x1fff),
131 	       priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF00_01));
132 	writel(((m[5] & 0x1fff) << 16) | (m[6] & 0x1fff),
133 	       priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF02_10));
134 	writel(((m[7] & 0x1fff) << 16) | (m[8] & 0x1fff),
135 	       priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF11_12));
136 	writel(((m[9] & 0x1fff) << 16) | (m[10] & 0x1fff),
137 	       priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF20_21));
138 	writel((m[11] & 0x1fff) << 16,
139 	       priv->io_base +	_REG(VPP_WRAP_OSD1_MATRIX_COEF22));
140 
141 	writel(((m[18] & 0xfff) << 16) | (m[19] & 0xfff),
142 	       priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_OFFSET0_1));
143 	writel(m[20] & 0xfff,
144 	       priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_OFFSET2));
145 
146 	writel_bits(BIT(0), csc_on ? BIT(0) : 0,
147 		    priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_EN_CTRL));
148 }
149 
meson_viu_set_osd_matrix(struct meson_vpu_priv * priv,enum viu_matrix_sel_e m_select,int * m,bool csc_on)150 static void meson_viu_set_osd_matrix(struct meson_vpu_priv *priv,
151 				     enum viu_matrix_sel_e m_select,
152 				     int *m, bool csc_on)
153 {
154 	if (m_select == VIU_MATRIX_OSD) {
155 		/* osd matrix, VIU_MATRIX_0 */
156 		writel(((m[0] & 0xfff) << 16) | (m[1] & 0xfff),
157 		       priv->io_base + _REG(VIU_OSD1_MATRIX_PRE_OFFSET0_1));
158 		writel(m[2] & 0xfff,
159 		       priv->io_base + _REG(VIU_OSD1_MATRIX_PRE_OFFSET2));
160 		writel(((m[3] & 0x1fff) << 16) | (m[4] & 0x1fff),
161 		       priv->io_base + _REG(VIU_OSD1_MATRIX_COEF00_01));
162 		writel(((m[5] & 0x1fff) << 16) | (m[6] & 0x1fff),
163 		       priv->io_base + _REG(VIU_OSD1_MATRIX_COEF02_10));
164 		writel(((m[7] & 0x1fff) << 16) | (m[8] & 0x1fff),
165 		       priv->io_base + _REG(VIU_OSD1_MATRIX_COEF11_12));
166 		writel(((m[9] & 0x1fff) << 16) | (m[10] & 0x1fff),
167 		       priv->io_base + _REG(VIU_OSD1_MATRIX_COEF20_21));
168 
169 		if (m[21]) {
170 			writel(((m[11] & 0x1fff) << 16) | (m[12] & 0x1fff),
171 			       priv->io_base +
172 					_REG(VIU_OSD1_MATRIX_COEF22_30));
173 			writel(((m[13] & 0x1fff) << 16) | (m[14] & 0x1fff),
174 			       priv->io_base +
175 					_REG(VIU_OSD1_MATRIX_COEF31_32));
176 			writel(((m[15] & 0x1fff) << 16) | (m[16] & 0x1fff),
177 			       priv->io_base +
178 					_REG(VIU_OSD1_MATRIX_COEF40_41));
179 			writel(m[17] & 0x1fff, priv->io_base +
180 			       _REG(VIU_OSD1_MATRIX_COLMOD_COEF42));
181 		} else {
182 			writel((m[11] & 0x1fff) << 16, priv->io_base +
183 			       _REG(VIU_OSD1_MATRIX_COEF22_30));
184 		}
185 
186 		writel(((m[18] & 0xfff) << 16) | (m[19] & 0xfff),
187 		       priv->io_base + _REG(VIU_OSD1_MATRIX_OFFSET0_1));
188 		writel(m[20] & 0xfff,
189 		       priv->io_base + _REG(VIU_OSD1_MATRIX_OFFSET2));
190 
191 		writel_bits(3 << 30, m[21] << 30,
192 			    priv->io_base +
193 			    _REG(VIU_OSD1_MATRIX_COLMOD_COEF42));
194 		writel_bits(7 << 16, m[22] << 16,
195 			    priv->io_base +
196 			    _REG(VIU_OSD1_MATRIX_COLMOD_COEF42));
197 
198 		/* 23 reserved for clipping control */
199 		writel_bits(BIT(0), csc_on ? BIT(0) : 0,
200 			    priv->io_base + _REG(VIU_OSD1_MATRIX_CTRL));
201 		writel_bits(BIT(1), 0,
202 			    priv->io_base + _REG(VIU_OSD1_MATRIX_CTRL));
203 	} else if (m_select == VIU_MATRIX_OSD_EOTF) {
204 		int i;
205 
206 		/* osd eotf matrix, VIU_MATRIX_OSD_EOTF */
207 		for (i = 0; i < 5; i++)
208 			writel(((m[i * 2] & 0x1fff) << 16) |
209 				(m[i * 2 + 1] & 0x1fff), priv->io_base +
210 				_REG(VIU_OSD1_EOTF_CTL + i + 1));
211 
212 		writel_bits(BIT(30), csc_on ? BIT(30) : 0,
213 			    priv->io_base + _REG(VIU_OSD1_EOTF_CTL));
214 		writel_bits(BIT(31), csc_on ? BIT(31) : 0,
215 			    priv->io_base + _REG(VIU_OSD1_EOTF_CTL));
216 	}
217 }
218 
219 #define OSD_EOTF_LUT_SIZE 33
220 #define OSD_OETF_LUT_SIZE 41
221 
meson_viu_set_osd_lut(struct meson_vpu_priv * priv,enum viu_lut_sel_e lut_sel,unsigned int * r_map,unsigned int * g_map,unsigned int * b_map,bool csc_on)222 static void meson_viu_set_osd_lut(struct meson_vpu_priv *priv,
223 				  enum viu_lut_sel_e lut_sel,
224 				  unsigned int *r_map, unsigned int *g_map,
225 				  unsigned int *b_map,
226 				  bool csc_on)
227 {
228 	unsigned int addr_port;
229 	unsigned int data_port;
230 	unsigned int ctrl_port;
231 	int i;
232 
233 	if (lut_sel == VIU_LUT_OSD_EOTF) {
234 		addr_port = VIU_OSD1_EOTF_LUT_ADDR_PORT;
235 		data_port = VIU_OSD1_EOTF_LUT_DATA_PORT;
236 		ctrl_port = VIU_OSD1_EOTF_CTL;
237 	} else if (lut_sel == VIU_LUT_OSD_OETF) {
238 		addr_port = VIU_OSD1_OETF_LUT_ADDR_PORT;
239 		data_port = VIU_OSD1_OETF_LUT_DATA_PORT;
240 		ctrl_port = VIU_OSD1_OETF_CTL;
241 	} else {
242 		return;
243 	}
244 
245 	if (lut_sel == VIU_LUT_OSD_OETF) {
246 		writel(0, priv->io_base + _REG(addr_port));
247 
248 		for (i = 0; i < 20; i++)
249 			writel(r_map[i * 2] | (r_map[i * 2 + 1] << 16),
250 			       priv->io_base + _REG(data_port));
251 
252 		writel(r_map[OSD_OETF_LUT_SIZE - 1] | (g_map[0] << 16),
253 		       priv->io_base + _REG(data_port));
254 
255 		for (i = 0; i < 20; i++)
256 			writel(g_map[i * 2 + 1] | (g_map[i * 2 + 2] << 16),
257 			       priv->io_base + _REG(data_port));
258 
259 		for (i = 0; i < 20; i++)
260 			writel(b_map[i * 2] | (b_map[i * 2 + 1] << 16),
261 			       priv->io_base + _REG(data_port));
262 
263 		writel(b_map[OSD_OETF_LUT_SIZE - 1],
264 		       priv->io_base + _REG(data_port));
265 
266 		if (csc_on)
267 			writel_bits(0x7 << 29, 7 << 29,
268 				    priv->io_base + _REG(ctrl_port));
269 		else
270 			writel_bits(0x7 << 29, 0,
271 				    priv->io_base + _REG(ctrl_port));
272 	} else if (lut_sel == VIU_LUT_OSD_EOTF) {
273 		writel(0, priv->io_base + _REG(addr_port));
274 
275 		for (i = 0; i < 20; i++)
276 			writel(r_map[i * 2] | (r_map[i * 2 + 1] << 16),
277 			       priv->io_base + _REG(data_port));
278 
279 		writel(r_map[OSD_EOTF_LUT_SIZE - 1] | (g_map[0] << 16),
280 		       priv->io_base + _REG(data_port));
281 
282 		for (i = 0; i < 20; i++)
283 			writel(g_map[i * 2 + 1] | (g_map[i * 2 + 2] << 16),
284 			       priv->io_base + _REG(data_port));
285 
286 		for (i = 0; i < 20; i++)
287 			writel(b_map[i * 2] | (b_map[i * 2 + 1] << 16),
288 			       priv->io_base + _REG(data_port));
289 
290 		writel(b_map[OSD_EOTF_LUT_SIZE - 1],
291 		       priv->io_base + _REG(data_port));
292 
293 		if (csc_on)
294 			writel_bits(7 << 27, 7 << 27,
295 				    priv->io_base + _REG(ctrl_port));
296 		else
297 			writel_bits(7 << 27, 0,
298 				    priv->io_base + _REG(ctrl_port));
299 
300 		writel_bits(BIT(31), BIT(31),
301 			    priv->io_base + _REG(ctrl_port));
302 	}
303 }
304 
305 /* eotf lut: linear */
306 static unsigned int eotf_33_linear_mapping[OSD_EOTF_LUT_SIZE] = {
307 	0x0000,	0x0200,	0x0400, 0x0600,
308 	0x0800, 0x0a00, 0x0c00, 0x0e00,
309 	0x1000, 0x1200, 0x1400, 0x1600,
310 	0x1800, 0x1a00, 0x1c00, 0x1e00,
311 	0x2000, 0x2200, 0x2400, 0x2600,
312 	0x2800, 0x2a00, 0x2c00, 0x2e00,
313 	0x3000, 0x3200, 0x3400, 0x3600,
314 	0x3800, 0x3a00, 0x3c00, 0x3e00,
315 	0x4000
316 };
317 
318 /* osd oetf lut: linear */
319 static unsigned int oetf_41_linear_mapping[OSD_OETF_LUT_SIZE] = {
320 	0, 0, 0, 0,
321 	0, 32, 64, 96,
322 	128, 160, 196, 224,
323 	256, 288, 320, 352,
324 	384, 416, 448, 480,
325 	512, 544, 576, 608,
326 	640, 672, 704, 736,
327 	768, 800, 832, 864,
328 	896, 928, 960, 992,
329 	1023, 1023, 1023, 1023,
330 	1023
331 };
332 
meson_viu_load_matrix(struct meson_vpu_priv * priv)333 static void meson_viu_load_matrix(struct meson_vpu_priv *priv)
334 {
335 	/* eotf lut bypass */
336 	meson_viu_set_osd_lut(priv, VIU_LUT_OSD_EOTF,
337 			      eotf_33_linear_mapping, /* R */
338 			      eotf_33_linear_mapping, /* G */
339 			      eotf_33_linear_mapping, /* B */
340 			      false);
341 
342 	/* eotf matrix bypass */
343 	meson_viu_set_osd_matrix(priv, VIU_MATRIX_OSD_EOTF,
344 				 eotf_bypass_coeff,
345 				 false);
346 
347 	/* oetf lut bypass */
348 	meson_viu_set_osd_lut(priv, VIU_LUT_OSD_OETF,
349 			      oetf_41_linear_mapping, /* R */
350 			      oetf_41_linear_mapping, /* G */
351 			      oetf_41_linear_mapping, /* B */
352 			      false);
353 
354 	/* osd matrix RGB709 to YUV709 limit */
355 	meson_viu_set_osd_matrix(priv, VIU_MATRIX_OSD,
356 				 RGB709_to_YUV709l_coeff,
357 				 true);
358 }
359 
meson_viu_osd_burst_length_reg(uint32_t length)360 static inline uint32_t meson_viu_osd_burst_length_reg(uint32_t length)
361 {
362 	u32 val = (((length & 0x80) % 24) / 12);
363 
364 	return (((val & 0x3) << 10) | (((val & 0x4) >> 2) << 31));
365 }
366 
meson_vpu_init(struct udevice * dev)367 void meson_vpu_init(struct udevice *dev)
368 {
369 	struct meson_vpu_priv *priv = dev_get_priv(dev);
370 	u32 reg;
371 
372 	/*
373 	 * Slave dc0 and dc5 connected to master port 1.
374 	 * By default other slaves are connected to master port 0.
375 	 */
376 	reg = VPU_RDARB_SLAVE_TO_MASTER_PORT(0, 1) |
377 		VPU_RDARB_SLAVE_TO_MASTER_PORT(5, 1);
378 	writel(reg, priv->io_base + _REG(VPU_RDARB_MODE_L1C1));
379 
380 	/* Slave dc0 connected to master port 1 */
381 	reg = VPU_RDARB_SLAVE_TO_MASTER_PORT(0, 1);
382 	writel(reg, priv->io_base + _REG(VPU_RDARB_MODE_L1C2));
383 
384 	/* Slave dc4 and dc7 connected to master port 1 */
385 	reg = VPU_RDARB_SLAVE_TO_MASTER_PORT(4, 1) |
386 		VPU_RDARB_SLAVE_TO_MASTER_PORT(7, 1);
387 	writel(reg, priv->io_base + _REG(VPU_RDARB_MODE_L2C1));
388 
389 	/* Slave dc1 connected to master port 1 */
390 	reg = VPU_RDARB_SLAVE_TO_MASTER_PORT(1, 1);
391 	writel(reg, priv->io_base + _REG(VPU_WRARB_MODE_L2C1));
392 
393 	/* Disable CVBS VDAC */
394 	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
395 		hhi_write(HHI_VDAC_CNTL0_G12A, 0);
396 		hhi_write(HHI_VDAC_CNTL1_G12A, 8);
397 	} else {
398 		hhi_write(HHI_VDAC_CNTL0, 0);
399 		hhi_write(HHI_VDAC_CNTL1, 8);
400 	}
401 
402 	/* Power Down Dacs */
403 	writel(0xff, priv->io_base + _REG(VENC_VDAC_SETTING));
404 
405 	/* Disable HDMI PHY */
406 	hhi_write(HHI_HDMI_PHY_CNTL0, 0);
407 
408 	/* Disable HDMI */
409 	writel_bits(VPU_HDMI_ENCI_DATA_TO_HDMI |
410 		    VPU_HDMI_ENCP_DATA_TO_HDMI, 0,
411 		    priv->io_base + _REG(VPU_HDMI_SETTING));
412 
413 	/* Disable all encoders */
414 	writel(0, priv->io_base + _REG(ENCI_VIDEO_EN));
415 	writel(0, priv->io_base + _REG(ENCP_VIDEO_EN));
416 	writel(0, priv->io_base + _REG(ENCL_VIDEO_EN));
417 
418 	/* Disable VSync IRQ */
419 	writel(0, priv->io_base + _REG(VENC_INTCTRL));
420 
421 	/* set dummy data default YUV black */
422 	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL)) {
423 		writel(0x108080, priv->io_base + _REG(VPP_DUMMY_DATA1));
424 	} else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM)) {
425 		writel_bits(0xff << 16, 0xff << 16,
426 			    priv->io_base + _REG(VIU_MISC_CTRL1));
427 		writel(VPP_PPS_DUMMY_DATA_MODE,
428 		       priv->io_base + _REG(VPP_DOLBY_CTRL));
429 		writel(0x1020080,
430 		       priv->io_base + _REG(VPP_DUMMY_DATA1));
431 	} else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
432 		writel(0xf, priv->io_base + _REG(DOLBY_PATH_CTRL));
433 
434 	/* Initialize vpu fifo control registers */
435 	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
436 		writel(VPP_OFIFO_SIZE_DEFAULT,
437 		       priv->io_base + _REG(VPP_OFIFO_SIZE));
438 	else
439 		writel_bits(VPP_OFIFO_SIZE_MASK, 0x77f,
440 			    priv->io_base + _REG(VPP_OFIFO_SIZE));
441 	writel(VPP_POSTBLEND_HOLD_LINES(4) | VPP_PREBLEND_HOLD_LINES(4),
442 	       priv->io_base + _REG(VPP_HOLD_LINES));
443 
444 	if (!meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
445 		/* Turn off preblend */
446 		writel_bits(VPP_PREBLEND_ENABLE, 0,
447 			    priv->io_base + _REG(VPP_MISC));
448 
449 		/* Turn off POSTBLEND */
450 		writel_bits(VPP_POSTBLEND_ENABLE, 0,
451 			    priv->io_base + _REG(VPP_MISC));
452 
453 		/* Force all planes off */
454 		writel_bits(VPP_OSD1_POSTBLEND | VPP_OSD2_POSTBLEND |
455 			    VPP_VD1_POSTBLEND | VPP_VD2_POSTBLEND |
456 			    VPP_VD1_PREBLEND | VPP_VD2_PREBLEND, 0,
457 			    priv->io_base + _REG(VPP_MISC));
458 
459 		/* Setup default VD settings */
460 		writel(4096,
461 		       priv->io_base + _REG(VPP_PREBLEND_VD1_H_START_END));
462 		writel(4096,
463 		       priv->io_base + _REG(VPP_BLEND_VD2_H_START_END));
464 	}
465 
466 	/* Disable Scalers */
467 	writel(0, priv->io_base + _REG(VPP_OSD_SC_CTRL0));
468 	writel(0, priv->io_base + _REG(VPP_OSD_VSC_CTRL0));
469 	writel(0, priv->io_base + _REG(VPP_OSD_HSC_CTRL0));
470 
471 	writel(VPP_VSC_BANK_LENGTH(4) | VPP_HSC_BANK_LENGTH(4) |
472 	       VPP_SC_VD_EN_ENABLE,
473 	       priv->io_base + _REG(VPP_SC_MISC));
474 
475 	/* Enable minus black level for vadj1 */
476 	writel(VPP_MINUS_BLACK_LVL_VADJ1_ENABLE,
477 	       priv->io_base + _REG(VPP_VADJ_CTRL));
478 
479 	/* Write in the proper filter coefficients. */
480 	meson_vpp_write_scaling_filter_coefs(priv,
481 				vpp_filter_coefs_4point_bspline, false);
482 	meson_vpp_write_scaling_filter_coefs(priv,
483 				vpp_filter_coefs_4point_bspline, true);
484 
485 	/* Write the VD proper filter coefficients. */
486 	meson_vpp_write_vd_scaling_filter_coefs(priv, vpp_filter_coefs_bicubic,
487 						false);
488 	meson_vpp_write_vd_scaling_filter_coefs(priv, vpp_filter_coefs_bicubic,
489 						true);
490 
491 	/* Disable OSDs */
492 	writel_bits(VIU_OSD1_OSD_BLK_ENABLE | VIU_OSD1_OSD_ENABLE, 0,
493 		    priv->io_base + _REG(VIU_OSD1_CTRL_STAT));
494 	writel_bits(VIU_OSD1_OSD_BLK_ENABLE | VIU_OSD1_OSD_ENABLE, 0,
495 		    priv->io_base + _REG(VIU_OSD2_CTRL_STAT));
496 
497 	/* On GXL/GXM, Use the 10bit HDR conversion matrix */
498 	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) ||
499 	    meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL))
500 		meson_viu_load_matrix(priv);
501 	else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
502 		meson_viu_set_g12a_osd1_matrix(priv, RGB709_to_YUV709l_coeff,
503 					       true);
504 
505 	/* Initialize OSD1 fifo control register */
506 	reg = VIU_OSD_DDR_PRIORITY_URGENT |
507 		VIU_OSD_HOLD_FIFO_LINES(4) |
508 		VIU_OSD_FIFO_DEPTH_VAL(32) | /* fifo_depth_val: 32*8=256 */
509 		VIU_OSD_WORDS_PER_BURST(4) | /* 4 words in 1 burst */
510 		VIU_OSD_FIFO_LIMITS(2);      /* fifo_lim: 2*16=32 */
511 
512 	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
513 		reg |= meson_viu_osd_burst_length_reg(32);
514 	else
515 		reg |= meson_viu_osd_burst_length_reg(64);
516 
517 	writel(reg, priv->io_base + _REG(VIU_OSD1_FIFO_CTRL_STAT));
518 	writel(reg, priv->io_base + _REG(VIU_OSD2_FIFO_CTRL_STAT));
519 
520 	/* Set OSD alpha replace value */
521 	writel_bits(0xff << OSD_REPLACE_SHIFT,
522 		    0xff << OSD_REPLACE_SHIFT,
523 		    priv->io_base + _REG(VIU_OSD1_CTRL_STAT2));
524 	writel_bits(0xff << OSD_REPLACE_SHIFT,
525 		    0xff << OSD_REPLACE_SHIFT,
526 		    priv->io_base + _REG(VIU_OSD2_CTRL_STAT2));
527 
528 	/* Disable VD1 AFBC */
529 	/* di_mif0_en=0 mif0_to_vpp_en=0 di_mad_en=0 and afbc vd1 set=0*/
530 	writel_bits(VIU_CTRL0_VD1_AFBC_MASK, 0,
531 		    priv->io_base + _REG(VIU_MISC_CTRL0));
532 	writel(0, priv->io_base + _REG(AFBC_ENABLE));
533 
534 	writel(0x00FF00C0,
535 	       priv->io_base + _REG(VD1_IF0_LUMA_FIFO_SIZE));
536 	writel(0x00FF00C0,
537 	       priv->io_base + _REG(VD2_IF0_LUMA_FIFO_SIZE));
538 
539 	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
540 		writel(VIU_OSD_BLEND_REORDER(0, 1) |
541 		       VIU_OSD_BLEND_REORDER(1, 0) |
542 		       VIU_OSD_BLEND_REORDER(2, 0) |
543 		       VIU_OSD_BLEND_REORDER(3, 0) |
544 		       VIU_OSD_BLEND_DIN_EN(1) |
545 		       VIU_OSD_BLEND1_DIN3_BYPASS_TO_DOUT1 |
546 		       VIU_OSD_BLEND1_DOUT_BYPASS_TO_BLEND2 |
547 		       VIU_OSD_BLEND_DIN0_BYPASS_TO_DOUT0 |
548 		       VIU_OSD_BLEND_BLEN2_PREMULT_EN(1) |
549 		       VIU_OSD_BLEND_HOLD_LINES(4),
550 		       priv->io_base + _REG(VIU_OSD_BLEND_CTRL));
551 		writel(OSD_BLEND_PATH_SEL_ENABLE,
552 		       priv->io_base + _REG(OSD1_BLEND_SRC_CTRL));
553 		writel(OSD_BLEND_PATH_SEL_ENABLE,
554 		       priv->io_base + _REG(OSD2_BLEND_SRC_CTRL));
555 		writel(0, priv->io_base + _REG(VD1_BLEND_SRC_CTRL));
556 		writel(0, priv->io_base + _REG(VD2_BLEND_SRC_CTRL));
557 		writel(0, priv->io_base + _REG(VIU_OSD_BLEND_DUMMY_DATA0));
558 		writel(0, priv->io_base + _REG(VIU_OSD_BLEND_DUMMY_ALPHA));
559 		writel_bits(DOLBY_BYPASS_EN(0xc), DOLBY_BYPASS_EN(0xc),
560 			    priv->io_base + _REG(DOLBY_PATH_CTRL));
561 	}
562 }
563