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