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