xref: /openbmc/linux/drivers/gpu/drm/meson/meson_viu.c (revision dfc53baa)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (C) 2016 BayLibre, SAS
4  * Author: Neil Armstrong <narmstrong@baylibre.com>
5  * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
6  * Copyright (C) 2014 Endless Mobile
7  */
8 
9 #include <linux/export.h>
10 #include <linux/bitfield.h>
11 
12 #include <drm/drm_fourcc.h>
13 
14 #include "meson_drv.h"
15 #include "meson_viu.h"
16 #include "meson_registers.h"
17 
18 /**
19  * DOC: Video Input Unit
20  *
21  * VIU Handles the Pixel scanout and the basic Colorspace conversions
22  * We handle the following features :
23  *
24  * - OSD1 RGB565/RGB888/xRGB8888 scanout
25  * - RGB conversion to x/cb/cr
26  * - Progressive or Interlace buffer scanout
27  * - OSD1 Commit on Vsync
28  * - HDR OSD matrix for GXL/GXM
29  *
30  * What is missing :
31  *
32  * - BGR888/xBGR8888/BGRx8888/BGRx8888 modes
33  * - YUV4:2:2 Y0CbY1Cr scanout
34  * - Conversion to YUV 4:4:4 from 4:2:2 input
35  * - Colorkey Alpha matching
36  * - Big endian scanout
37  * - X/Y reverse scanout
38  * - Global alpha setup
39  * - OSD2 support, would need interlace switching on vsync
40  * - OSD1 full scaling to support TV overscan
41  */
42 
43 /* OSD csc defines */
44 
45 enum viu_matrix_sel_e {
46 	VIU_MATRIX_OSD_EOTF = 0,
47 	VIU_MATRIX_OSD,
48 };
49 
50 enum viu_lut_sel_e {
51 	VIU_LUT_OSD_EOTF = 0,
52 	VIU_LUT_OSD_OETF,
53 };
54 
55 #define COEFF_NORM(a) ((int)((((a) * 2048.0) + 1) / 2))
56 #define MATRIX_5X3_COEF_SIZE 24
57 
58 #define EOTF_COEFF_NORM(a) ((int)((((a) * 4096.0) + 1) / 2))
59 #define EOTF_COEFF_SIZE 10
60 #define EOTF_COEFF_RIGHTSHIFT 1
61 
62 static int RGB709_to_YUV709l_coeff[MATRIX_5X3_COEF_SIZE] = {
63 	0, 0, 0, /* pre offset */
64 	COEFF_NORM(0.181873),	COEFF_NORM(0.611831),	COEFF_NORM(0.061765),
65 	COEFF_NORM(-0.100251),	COEFF_NORM(-0.337249),	COEFF_NORM(0.437500),
66 	COEFF_NORM(0.437500),	COEFF_NORM(-0.397384),	COEFF_NORM(-0.040116),
67 	0, 0, 0, /* 10'/11'/12' */
68 	0, 0, 0, /* 20'/21'/22' */
69 	64, 512, 512, /* offset */
70 	0, 0, 0 /* mode, right_shift, clip_en */
71 };
72 
73 /*  eotf matrix: bypass */
74 static int eotf_bypass_coeff[EOTF_COEFF_SIZE] = {
75 	EOTF_COEFF_NORM(1.0),	EOTF_COEFF_NORM(0.0),	EOTF_COEFF_NORM(0.0),
76 	EOTF_COEFF_NORM(0.0),	EOTF_COEFF_NORM(1.0),	EOTF_COEFF_NORM(0.0),
77 	EOTF_COEFF_NORM(0.0),	EOTF_COEFF_NORM(0.0),	EOTF_COEFF_NORM(1.0),
78 	EOTF_COEFF_RIGHTSHIFT /* right shift */
79 };
80 
81 static void meson_viu_set_g12a_osd1_matrix(struct meson_drm *priv,
82 					   int *m, bool csc_on)
83 {
84 	/* VPP WRAP OSD1 matrix */
85 	writel(((m[0] & 0xfff) << 16) | (m[1] & 0xfff),
86 		priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_PRE_OFFSET0_1));
87 	writel(m[2] & 0xfff,
88 		priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_PRE_OFFSET2));
89 	writel(((m[3] & 0x1fff) << 16) | (m[4] & 0x1fff),
90 		priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF00_01));
91 	writel(((m[5] & 0x1fff) << 16) | (m[6] & 0x1fff),
92 		priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF02_10));
93 	writel(((m[7] & 0x1fff) << 16) | (m[8] & 0x1fff),
94 		priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF11_12));
95 	writel(((m[9] & 0x1fff) << 16) | (m[10] & 0x1fff),
96 		priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF20_21));
97 	writel((m[11] & 0x1fff) << 16,
98 		priv->io_base +	_REG(VPP_WRAP_OSD1_MATRIX_COEF22));
99 
100 	writel(((m[18] & 0xfff) << 16) | (m[19] & 0xfff),
101 		priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_OFFSET0_1));
102 	writel(m[20] & 0xfff,
103 		priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_OFFSET2));
104 
105 	writel_bits_relaxed(BIT(0), csc_on ? BIT(0) : 0,
106 		priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_EN_CTRL));
107 }
108 
109 static void meson_viu_set_osd_matrix(struct meson_drm *priv,
110 				     enum viu_matrix_sel_e m_select,
111 			      int *m, bool csc_on)
112 {
113 	if (m_select == VIU_MATRIX_OSD) {
114 		/* osd matrix, VIU_MATRIX_0 */
115 		writel(((m[0] & 0xfff) << 16) | (m[1] & 0xfff),
116 			priv->io_base + _REG(VIU_OSD1_MATRIX_PRE_OFFSET0_1));
117 		writel(m[2] & 0xfff,
118 			priv->io_base + _REG(VIU_OSD1_MATRIX_PRE_OFFSET2));
119 		writel(((m[3] & 0x1fff) << 16) | (m[4] & 0x1fff),
120 			priv->io_base + _REG(VIU_OSD1_MATRIX_COEF00_01));
121 		writel(((m[5] & 0x1fff) << 16) | (m[6] & 0x1fff),
122 			priv->io_base + _REG(VIU_OSD1_MATRIX_COEF02_10));
123 		writel(((m[7] & 0x1fff) << 16) | (m[8] & 0x1fff),
124 			priv->io_base + _REG(VIU_OSD1_MATRIX_COEF11_12));
125 		writel(((m[9] & 0x1fff) << 16) | (m[10] & 0x1fff),
126 			priv->io_base + _REG(VIU_OSD1_MATRIX_COEF20_21));
127 
128 		if (m[21]) {
129 			writel(((m[11] & 0x1fff) << 16) | (m[12] & 0x1fff),
130 				priv->io_base +
131 					_REG(VIU_OSD1_MATRIX_COEF22_30));
132 			writel(((m[13] & 0x1fff) << 16) | (m[14] & 0x1fff),
133 				priv->io_base +
134 					_REG(VIU_OSD1_MATRIX_COEF31_32));
135 			writel(((m[15] & 0x1fff) << 16) | (m[16] & 0x1fff),
136 				priv->io_base +
137 					_REG(VIU_OSD1_MATRIX_COEF40_41));
138 			writel(m[17] & 0x1fff, priv->io_base +
139 				_REG(VIU_OSD1_MATRIX_COLMOD_COEF42));
140 		} else
141 			writel((m[11] & 0x1fff) << 16, priv->io_base +
142 				_REG(VIU_OSD1_MATRIX_COEF22_30));
143 
144 		writel(((m[18] & 0xfff) << 16) | (m[19] & 0xfff),
145 			priv->io_base + _REG(VIU_OSD1_MATRIX_OFFSET0_1));
146 		writel(m[20] & 0xfff,
147 			priv->io_base + _REG(VIU_OSD1_MATRIX_OFFSET2));
148 
149 		writel_bits_relaxed(3 << 30, m[21] << 30,
150 			priv->io_base + _REG(VIU_OSD1_MATRIX_COLMOD_COEF42));
151 		writel_bits_relaxed(7 << 16, m[22] << 16,
152 			priv->io_base + _REG(VIU_OSD1_MATRIX_COLMOD_COEF42));
153 
154 		/* 23 reserved for clipping control */
155 		writel_bits_relaxed(BIT(0), csc_on ? BIT(0) : 0,
156 			priv->io_base + _REG(VIU_OSD1_MATRIX_CTRL));
157 		writel_bits_relaxed(BIT(1), 0,
158 			priv->io_base + _REG(VIU_OSD1_MATRIX_CTRL));
159 	} else if (m_select == VIU_MATRIX_OSD_EOTF) {
160 		int i;
161 
162 		/* osd eotf matrix, VIU_MATRIX_OSD_EOTF */
163 		for (i = 0; i < 5; i++)
164 			writel(((m[i * 2] & 0x1fff) << 16) |
165 				(m[i * 2 + 1] & 0x1fff), priv->io_base +
166 				_REG(VIU_OSD1_EOTF_CTL + i + 1));
167 
168 		writel_bits_relaxed(BIT(30), csc_on ? BIT(30) : 0,
169 			priv->io_base + _REG(VIU_OSD1_EOTF_CTL));
170 		writel_bits_relaxed(BIT(31), csc_on ? BIT(31) : 0,
171 			priv->io_base + _REG(VIU_OSD1_EOTF_CTL));
172 	}
173 }
174 
175 #define OSD_EOTF_LUT_SIZE 33
176 #define OSD_OETF_LUT_SIZE 41
177 
178 static void
179 meson_viu_set_osd_lut(struct meson_drm *priv, enum viu_lut_sel_e lut_sel,
180 		      unsigned int *r_map, unsigned int *g_map,
181 		      unsigned int *b_map, bool csc_on)
182 {
183 	unsigned int addr_port;
184 	unsigned int data_port;
185 	unsigned int ctrl_port;
186 	int i;
187 
188 	if (lut_sel == VIU_LUT_OSD_EOTF) {
189 		addr_port = VIU_OSD1_EOTF_LUT_ADDR_PORT;
190 		data_port = VIU_OSD1_EOTF_LUT_DATA_PORT;
191 		ctrl_port = VIU_OSD1_EOTF_CTL;
192 	} else if (lut_sel == VIU_LUT_OSD_OETF) {
193 		addr_port = VIU_OSD1_OETF_LUT_ADDR_PORT;
194 		data_port = VIU_OSD1_OETF_LUT_DATA_PORT;
195 		ctrl_port = VIU_OSD1_OETF_CTL;
196 	} else
197 		return;
198 
199 	if (lut_sel == VIU_LUT_OSD_OETF) {
200 		writel(0, priv->io_base + _REG(addr_port));
201 
202 		for (i = 0; i < (OSD_OETF_LUT_SIZE / 2); i++)
203 			writel(r_map[i * 2] | (r_map[i * 2 + 1] << 16),
204 				priv->io_base + _REG(data_port));
205 
206 		writel(r_map[OSD_OETF_LUT_SIZE - 1] | (g_map[0] << 16),
207 			priv->io_base + _REG(data_port));
208 
209 		for (i = 0; i < (OSD_OETF_LUT_SIZE / 2); i++)
210 			writel(g_map[i * 2 + 1] | (g_map[i * 2 + 2] << 16),
211 				priv->io_base + _REG(data_port));
212 
213 		for (i = 0; i < (OSD_OETF_LUT_SIZE / 2); i++)
214 			writel(b_map[i * 2] | (b_map[i * 2 + 1] << 16),
215 				priv->io_base + _REG(data_port));
216 
217 		writel(b_map[OSD_OETF_LUT_SIZE - 1],
218 			priv->io_base + _REG(data_port));
219 
220 		if (csc_on)
221 			writel_bits_relaxed(0x7 << 29, 7 << 29,
222 					    priv->io_base + _REG(ctrl_port));
223 		else
224 			writel_bits_relaxed(0x7 << 29, 0,
225 					    priv->io_base + _REG(ctrl_port));
226 	} else if (lut_sel == VIU_LUT_OSD_EOTF) {
227 		writel(0, priv->io_base + _REG(addr_port));
228 
229 		for (i = 0; i < (OSD_EOTF_LUT_SIZE / 2); i++)
230 			writel(r_map[i * 2] | (r_map[i * 2 + 1] << 16),
231 				priv->io_base + _REG(data_port));
232 
233 		writel(r_map[OSD_EOTF_LUT_SIZE - 1] | (g_map[0] << 16),
234 			priv->io_base + _REG(data_port));
235 
236 		for (i = 0; i < (OSD_EOTF_LUT_SIZE / 2); i++)
237 			writel(g_map[i * 2 + 1] | (g_map[i * 2 + 2] << 16),
238 				priv->io_base + _REG(data_port));
239 
240 		for (i = 0; i < (OSD_EOTF_LUT_SIZE / 2); i++)
241 			writel(b_map[i * 2] | (b_map[i * 2 + 1] << 16),
242 				priv->io_base + _REG(data_port));
243 
244 		writel(b_map[OSD_EOTF_LUT_SIZE - 1],
245 			priv->io_base + _REG(data_port));
246 
247 		if (csc_on)
248 			writel_bits_relaxed(7 << 27, 7 << 27,
249 					    priv->io_base + _REG(ctrl_port));
250 		else
251 			writel_bits_relaxed(7 << 27, 0,
252 					    priv->io_base + _REG(ctrl_port));
253 
254 		writel_bits_relaxed(BIT(31), BIT(31),
255 				    priv->io_base + _REG(ctrl_port));
256 	}
257 }
258 
259 /* eotf lut: linear */
260 static unsigned int eotf_33_linear_mapping[OSD_EOTF_LUT_SIZE] = {
261 	0x0000,	0x0200,	0x0400, 0x0600,
262 	0x0800, 0x0a00, 0x0c00, 0x0e00,
263 	0x1000, 0x1200, 0x1400, 0x1600,
264 	0x1800, 0x1a00, 0x1c00, 0x1e00,
265 	0x2000, 0x2200, 0x2400, 0x2600,
266 	0x2800, 0x2a00, 0x2c00, 0x2e00,
267 	0x3000, 0x3200, 0x3400, 0x3600,
268 	0x3800, 0x3a00, 0x3c00, 0x3e00,
269 	0x4000
270 };
271 
272 /* osd oetf lut: linear */
273 static unsigned int oetf_41_linear_mapping[OSD_OETF_LUT_SIZE] = {
274 	0, 0, 0, 0,
275 	0, 32, 64, 96,
276 	128, 160, 196, 224,
277 	256, 288, 320, 352,
278 	384, 416, 448, 480,
279 	512, 544, 576, 608,
280 	640, 672, 704, 736,
281 	768, 800, 832, 864,
282 	896, 928, 960, 992,
283 	1023, 1023, 1023, 1023,
284 	1023
285 };
286 
287 static void meson_viu_load_matrix(struct meson_drm *priv)
288 {
289 	/* eotf lut bypass */
290 	meson_viu_set_osd_lut(priv, VIU_LUT_OSD_EOTF,
291 			      eotf_33_linear_mapping, /* R */
292 			      eotf_33_linear_mapping, /* G */
293 			      eotf_33_linear_mapping, /* B */
294 			      false);
295 
296 	/* eotf matrix bypass */
297 	meson_viu_set_osd_matrix(priv, VIU_MATRIX_OSD_EOTF,
298 				 eotf_bypass_coeff,
299 				 false);
300 
301 	/* oetf lut bypass */
302 	meson_viu_set_osd_lut(priv, VIU_LUT_OSD_OETF,
303 			      oetf_41_linear_mapping, /* R */
304 			      oetf_41_linear_mapping, /* G */
305 			      oetf_41_linear_mapping, /* B */
306 			      false);
307 
308 	/* osd matrix RGB709 to YUV709 limit */
309 	meson_viu_set_osd_matrix(priv, VIU_MATRIX_OSD,
310 				 RGB709_to_YUV709l_coeff,
311 				 true);
312 }
313 
314 /* VIU OSD1 Reset as workaround for GXL+ Alpha OSD Bug */
315 void meson_viu_osd1_reset(struct meson_drm *priv)
316 {
317 	uint32_t osd1_fifo_ctrl_stat, osd1_ctrl_stat2;
318 
319 	/* Save these 2 registers state */
320 	osd1_fifo_ctrl_stat = readl_relaxed(
321 				priv->io_base + _REG(VIU_OSD1_FIFO_CTRL_STAT));
322 	osd1_ctrl_stat2 = readl_relaxed(
323 				priv->io_base + _REG(VIU_OSD1_CTRL_STAT2));
324 
325 	/* Reset OSD1 */
326 	writel_bits_relaxed(VIU_SW_RESET_OSD1, VIU_SW_RESET_OSD1,
327 			    priv->io_base + _REG(VIU_SW_RESET));
328 	writel_bits_relaxed(VIU_SW_RESET_OSD1, 0,
329 			    priv->io_base + _REG(VIU_SW_RESET));
330 
331 	/* Rewrite these registers state lost in the reset */
332 	writel_relaxed(osd1_fifo_ctrl_stat,
333 		       priv->io_base + _REG(VIU_OSD1_FIFO_CTRL_STAT));
334 	writel_relaxed(osd1_ctrl_stat2,
335 		       priv->io_base + _REG(VIU_OSD1_CTRL_STAT2));
336 
337 	/* Reload the conversion matrix */
338 	meson_viu_load_matrix(priv);
339 }
340 
341 #define OSD1_MALI_ORDER_ABGR				\
342 	(FIELD_PREP(VIU_OSD1_MALI_AFBCD_A_REORDER,	\
343 		    VIU_OSD1_MALI_REORDER_A) |		\
344 	 FIELD_PREP(VIU_OSD1_MALI_AFBCD_B_REORDER,	\
345 		    VIU_OSD1_MALI_REORDER_B) |		\
346 	 FIELD_PREP(VIU_OSD1_MALI_AFBCD_G_REORDER,	\
347 		    VIU_OSD1_MALI_REORDER_G) |		\
348 	 FIELD_PREP(VIU_OSD1_MALI_AFBCD_R_REORDER,	\
349 		    VIU_OSD1_MALI_REORDER_R))
350 
351 #define OSD1_MALI_ORDER_ARGB				\
352 	(FIELD_PREP(VIU_OSD1_MALI_AFBCD_A_REORDER,	\
353 		    VIU_OSD1_MALI_REORDER_A) |		\
354 	 FIELD_PREP(VIU_OSD1_MALI_AFBCD_B_REORDER,	\
355 		    VIU_OSD1_MALI_REORDER_R) |		\
356 	 FIELD_PREP(VIU_OSD1_MALI_AFBCD_G_REORDER,	\
357 		    VIU_OSD1_MALI_REORDER_G) |		\
358 	 FIELD_PREP(VIU_OSD1_MALI_AFBCD_R_REORDER,	\
359 		    VIU_OSD1_MALI_REORDER_B))
360 
361 void meson_viu_g12a_enable_osd1_afbc(struct meson_drm *priv)
362 {
363 	u32 afbc_order = OSD1_MALI_ORDER_ARGB;
364 
365 	/* Enable Mali AFBC Unpack */
366 	writel_bits_relaxed(VIU_OSD1_MALI_UNPACK_EN,
367 			    VIU_OSD1_MALI_UNPACK_EN,
368 			    priv->io_base + _REG(VIU_OSD1_MALI_UNPACK_CTRL));
369 
370 	switch (priv->afbcd.format) {
371 	case DRM_FORMAT_XBGR8888:
372 	case DRM_FORMAT_ABGR8888:
373 		afbc_order = OSD1_MALI_ORDER_ABGR;
374 		break;
375 	}
376 
377 	/* Setup RGBA Reordering */
378 	writel_bits_relaxed(VIU_OSD1_MALI_AFBCD_A_REORDER |
379 			    VIU_OSD1_MALI_AFBCD_B_REORDER |
380 			    VIU_OSD1_MALI_AFBCD_G_REORDER |
381 			    VIU_OSD1_MALI_AFBCD_R_REORDER,
382 			    afbc_order,
383 			    priv->io_base + _REG(VIU_OSD1_MALI_UNPACK_CTRL));
384 
385 	/* Select AFBCD path for OSD1 */
386 	writel_bits_relaxed(OSD_PATH_OSD_AXI_SEL_OSD1_AFBCD,
387 			    OSD_PATH_OSD_AXI_SEL_OSD1_AFBCD,
388 			    priv->io_base + _REG(OSD_PATH_MISC_CTRL));
389 }
390 
391 void meson_viu_g12a_disable_osd1_afbc(struct meson_drm *priv)
392 {
393 	/* Disable AFBCD path for OSD1 */
394 	writel_bits_relaxed(OSD_PATH_OSD_AXI_SEL_OSD1_AFBCD, 0,
395 			    priv->io_base + _REG(OSD_PATH_MISC_CTRL));
396 
397 	/* Disable AFBCD unpack */
398 	writel_bits_relaxed(VIU_OSD1_MALI_UNPACK_EN, 0,
399 			    priv->io_base + _REG(VIU_OSD1_MALI_UNPACK_CTRL));
400 }
401 
402 void meson_viu_gxm_enable_osd1_afbc(struct meson_drm *priv)
403 {
404 	writel_bits_relaxed(MALI_AFBC_MISC, FIELD_PREP(MALI_AFBC_MISC, 0x90),
405 			    priv->io_base + _REG(VIU_MISC_CTRL1));
406 }
407 
408 void meson_viu_gxm_disable_osd1_afbc(struct meson_drm *priv)
409 {
410 	writel_bits_relaxed(MALI_AFBC_MISC, FIELD_PREP(MALI_AFBC_MISC, 0x00),
411 			    priv->io_base + _REG(VIU_MISC_CTRL1));
412 }
413 
414 void meson_viu_init(struct meson_drm *priv)
415 {
416 	uint32_t reg;
417 
418 	/* Disable OSDs */
419 	writel_bits_relaxed(VIU_OSD1_OSD_BLK_ENABLE | VIU_OSD1_OSD_ENABLE, 0,
420 			    priv->io_base + _REG(VIU_OSD1_CTRL_STAT));
421 	writel_bits_relaxed(VIU_OSD1_OSD_BLK_ENABLE | VIU_OSD1_OSD_ENABLE, 0,
422 			    priv->io_base + _REG(VIU_OSD2_CTRL_STAT));
423 
424 	/* On GXL/GXM, Use the 10bit HDR conversion matrix */
425 	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) ||
426 	    meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL))
427 		meson_viu_load_matrix(priv);
428 	else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
429 		meson_viu_set_g12a_osd1_matrix(priv, RGB709_to_YUV709l_coeff,
430 					       true);
431 
432 	/* Initialize OSD1 fifo control register */
433 	reg = VIU_OSD_DDR_PRIORITY_URGENT |
434 		VIU_OSD_HOLD_FIFO_LINES(31) |
435 		VIU_OSD_FIFO_DEPTH_VAL(32) | /* fifo_depth_val: 32*8=256 */
436 		VIU_OSD_WORDS_PER_BURST(4) | /* 4 words in 1 burst */
437 		VIU_OSD_FIFO_LIMITS(2);      /* fifo_lim: 2*16=32 */
438 
439 	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
440 		reg |= VIU_OSD_BURST_LENGTH_32;
441 	else
442 		reg |= VIU_OSD_BURST_LENGTH_64;
443 
444 	writel_relaxed(reg, priv->io_base + _REG(VIU_OSD1_FIFO_CTRL_STAT));
445 	writel_relaxed(reg, priv->io_base + _REG(VIU_OSD2_FIFO_CTRL_STAT));
446 
447 	/* Set OSD alpha replace value */
448 	writel_bits_relaxed(0xff << OSD_REPLACE_SHIFT,
449 			    0xff << OSD_REPLACE_SHIFT,
450 			    priv->io_base + _REG(VIU_OSD1_CTRL_STAT2));
451 	writel_bits_relaxed(0xff << OSD_REPLACE_SHIFT,
452 			    0xff << OSD_REPLACE_SHIFT,
453 			    priv->io_base + _REG(VIU_OSD2_CTRL_STAT2));
454 
455 	/* Disable VD1 AFBC */
456 	/* di_mif0_en=0 mif0_to_vpp_en=0 di_mad_en=0 and afbc vd1 set=0*/
457 	writel_bits_relaxed(VIU_CTRL0_VD1_AFBC_MASK, 0,
458 			    priv->io_base + _REG(VIU_MISC_CTRL0));
459 	writel_relaxed(0, priv->io_base + _REG(AFBC_ENABLE));
460 
461 	writel_relaxed(0x00FF00C0,
462 			priv->io_base + _REG(VD1_IF0_LUMA_FIFO_SIZE));
463 	writel_relaxed(0x00FF00C0,
464 			priv->io_base + _REG(VD2_IF0_LUMA_FIFO_SIZE));
465 
466 	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
467 		writel_relaxed(VIU_OSD_BLEND_REORDER(0, 1) |
468 			       VIU_OSD_BLEND_REORDER(1, 0) |
469 			       VIU_OSD_BLEND_REORDER(2, 0) |
470 			       VIU_OSD_BLEND_REORDER(3, 0) |
471 			       VIU_OSD_BLEND_DIN_EN(1) |
472 			       VIU_OSD_BLEND1_DIN3_BYPASS_TO_DOUT1 |
473 			       VIU_OSD_BLEND1_DOUT_BYPASS_TO_BLEND2 |
474 			       VIU_OSD_BLEND_DIN0_BYPASS_TO_DOUT0 |
475 			       VIU_OSD_BLEND_BLEN2_PREMULT_EN(1) |
476 			       VIU_OSD_BLEND_HOLD_LINES(4),
477 			       priv->io_base + _REG(VIU_OSD_BLEND_CTRL));
478 
479 		writel_relaxed(OSD_BLEND_PATH_SEL_ENABLE,
480 			       priv->io_base + _REG(OSD1_BLEND_SRC_CTRL));
481 		writel_relaxed(OSD_BLEND_PATH_SEL_ENABLE,
482 			       priv->io_base + _REG(OSD2_BLEND_SRC_CTRL));
483 		writel_relaxed(0, priv->io_base + _REG(VD1_BLEND_SRC_CTRL));
484 		writel_relaxed(0, priv->io_base + _REG(VD2_BLEND_SRC_CTRL));
485 		writel_relaxed(0,
486 				priv->io_base + _REG(VIU_OSD_BLEND_DUMMY_DATA0));
487 		writel_relaxed(0,
488 				priv->io_base + _REG(VIU_OSD_BLEND_DUMMY_ALPHA));
489 
490 		writel_bits_relaxed(DOLBY_BYPASS_EN(0xc), DOLBY_BYPASS_EN(0xc),
491 				    priv->io_base + _REG(DOLBY_PATH_CTRL));
492 
493 		meson_viu_g12a_disable_osd1_afbc(priv);
494 	}
495 
496 	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM))
497 		meson_viu_gxm_disable_osd1_afbc(priv);
498 
499 	priv->viu.osd1_enabled = false;
500 	priv->viu.osd1_commit = false;
501 	priv->viu.osd1_interlace = false;
502 }
503