]>
Commit | Line | Data |
---|---|---|
1ccea77e | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
bbbe775e NA |
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 | |
bbbe775e NA |
7 | */ |
8 | ||
66620f48 | 9 | #include <linux/export.h> |
1b85270f NA |
10 | #include <linux/bitfield.h> |
11 | ||
12 | #include <drm/drm_fourcc.h> | |
66620f48 | 13 | |
bbbe775e NA |
14 | #include "meson_drv.h" |
15 | #include "meson_viu.h" | |
bbbe775e NA |
16 | #include "meson_registers.h" |
17 | ||
2021d5b7 NA |
18 | /** |
19 | * DOC: Video Input Unit | |
20 | * | |
bbbe775e NA |
21 | * VIU Handles the Pixel scanout and the basic Colorspace conversions |
22 | * We handle the following features : | |
2021d5b7 | 23 | * |
bbbe775e NA |
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 : | |
2021d5b7 | 31 | * |
bbbe775e NA |
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 | ||
2ccb8433 Y |
81 | static void meson_viu_set_g12a_osd1_matrix(struct meson_drm *priv, |
82 | int *m, bool csc_on) | |
72888394 NA |
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)); | |
6463d393 | 97 | writel((m[11] & 0x1fff), |
72888394 NA |
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 | ||
2ccb8433 Y |
109 | static void meson_viu_set_osd_matrix(struct meson_drm *priv, |
110 | enum viu_matrix_sel_e m_select, | |
bbbe775e NA |
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 | ||
2ccb8433 Y |
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) | |
bbbe775e NA |
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 | ||
97b2a318 | 202 | for (i = 0; i < (OSD_OETF_LUT_SIZE / 2); i++) |
bbbe775e NA |
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 | ||
97b2a318 | 209 | for (i = 0; i < (OSD_OETF_LUT_SIZE / 2); i++) |
bbbe775e NA |
210 | writel(g_map[i * 2 + 1] | (g_map[i * 2 + 2] << 16), |
211 | priv->io_base + _REG(data_port)); | |
212 | ||
97b2a318 | 213 | for (i = 0; i < (OSD_OETF_LUT_SIZE / 2); i++) |
bbbe775e NA |
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 | ||
97b2a318 | 229 | for (i = 0; i < (OSD_EOTF_LUT_SIZE / 2); i++) |
bbbe775e NA |
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 | ||
97b2a318 | 236 | for (i = 0; i < (OSD_EOTF_LUT_SIZE / 2); i++) |
bbbe775e NA |
237 | writel(g_map[i * 2 + 1] | (g_map[i * 2 + 2] << 16), |
238 | priv->io_base + _REG(data_port)); | |
239 | ||
97b2a318 | 240 | for (i = 0; i < (OSD_EOTF_LUT_SIZE / 2); i++) |
bbbe775e NA |
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 | ||
3a936bc2 NA |
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 */ | |
147ae1cb | 326 | writel_bits_relaxed(VIU_SW_RESET_OSD1, VIU_SW_RESET_OSD1, |
3a936bc2 | 327 | priv->io_base + _REG(VIU_SW_RESET)); |
147ae1cb | 328 | writel_bits_relaxed(VIU_SW_RESET_OSD1, 0, |
3a936bc2 NA |
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 | ||
1b85270f NA |
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 | ||
bbbe775e NA |
414 | void meson_viu_init(struct meson_drm *priv) |
415 | { | |
416 | uint32_t reg; | |
417 | ||
418 | /* Disable OSDs */ | |
147ae1cb JM |
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)); | |
bbbe775e NA |
423 | |
424 | /* On GXL/GXM, Use the 10bit HDR conversion matrix */ | |
528a25d0 JM |
425 | if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) || |
426 | meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL)) | |
bbbe775e | 427 | meson_viu_load_matrix(priv); |
bf33677a | 428 | else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) { |
72888394 NA |
429 | meson_viu_set_g12a_osd1_matrix(priv, RGB709_to_YUV709l_coeff, |
430 | true); | |
bf33677a CH |
431 | /* fix green/pink color distortion from vendor u-boot */ |
432 | writel_bits_relaxed(OSD1_HDR2_CTRL_REG_ONLY_MAT | | |
433 | OSD1_HDR2_CTRL_VDIN0_HDR2_TOP_EN, 0, | |
434 | priv->io_base + _REG(OSD1_HDR2_CTRL)); | |
435 | } | |
bbbe775e NA |
436 | |
437 | /* Initialize OSD1 fifo control register */ | |
147ae1cb | 438 | reg = VIU_OSD_DDR_PRIORITY_URGENT | |
24e0d405 | 439 | VIU_OSD_HOLD_FIFO_LINES(31) | |
147ae1cb JM |
440 | VIU_OSD_FIFO_DEPTH_VAL(32) | /* fifo_depth_val: 32*8=256 */ |
441 | VIU_OSD_WORDS_PER_BURST(4) | /* 4 words in 1 burst */ | |
442 | VIU_OSD_FIFO_LIMITS(2); /* fifo_lim: 2*16=32 */ | |
443 | ||
528a25d0 | 444 | if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) |
17f64701 | 445 | reg |= VIU_OSD_BURST_LENGTH_32; |
72888394 | 446 | else |
17f64701 | 447 | reg |= VIU_OSD_BURST_LENGTH_64; |
147ae1cb | 448 | |
bbbe775e NA |
449 | writel_relaxed(reg, priv->io_base + _REG(VIU_OSD1_FIFO_CTRL_STAT)); |
450 | writel_relaxed(reg, priv->io_base + _REG(VIU_OSD2_FIFO_CTRL_STAT)); | |
451 | ||
452 | /* Set OSD alpha replace value */ | |
453 | writel_bits_relaxed(0xff << OSD_REPLACE_SHIFT, | |
454 | 0xff << OSD_REPLACE_SHIFT, | |
455 | priv->io_base + _REG(VIU_OSD1_CTRL_STAT2)); | |
456 | writel_bits_relaxed(0xff << OSD_REPLACE_SHIFT, | |
457 | 0xff << OSD_REPLACE_SHIFT, | |
458 | priv->io_base + _REG(VIU_OSD2_CTRL_STAT2)); | |
459 | ||
f9a23481 | 460 | /* Disable VD1 AFBC */ |
147ae1cb JM |
461 | /* di_mif0_en=0 mif0_to_vpp_en=0 di_mad_en=0 and afbc vd1 set=0*/ |
462 | writel_bits_relaxed(VIU_CTRL0_VD1_AFBC_MASK, 0, | |
463 | priv->io_base + _REG(VIU_MISC_CTRL0)); | |
f9a23481 NA |
464 | writel_relaxed(0, priv->io_base + _REG(AFBC_ENABLE)); |
465 | ||
466 | writel_relaxed(0x00FF00C0, | |
467 | priv->io_base + _REG(VD1_IF0_LUMA_FIFO_SIZE)); | |
468 | writel_relaxed(0x00FF00C0, | |
469 | priv->io_base + _REG(VD2_IF0_LUMA_FIFO_SIZE)); | |
470 | ||
528a25d0 | 471 | if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) { |
98692f52 SPR |
472 | u32 val = (u32)VIU_OSD_BLEND_REORDER(0, 1) | |
473 | (u32)VIU_OSD_BLEND_REORDER(1, 0) | | |
474 | (u32)VIU_OSD_BLEND_REORDER(2, 0) | | |
475 | (u32)VIU_OSD_BLEND_REORDER(3, 0) | | |
476 | (u32)VIU_OSD_BLEND_DIN_EN(1) | | |
477 | (u32)VIU_OSD_BLEND1_DIN3_BYPASS_TO_DOUT1 | | |
478 | (u32)VIU_OSD_BLEND1_DOUT_BYPASS_TO_BLEND2 | | |
479 | (u32)VIU_OSD_BLEND_DIN0_BYPASS_TO_DOUT0 | | |
480 | (u32)VIU_OSD_BLEND_BLEN2_PREMULT_EN(1) | | |
481 | (u32)VIU_OSD_BLEND_HOLD_LINES(4); | |
482 | writel_relaxed(val, priv->io_base + _REG(VIU_OSD_BLEND_CTRL)); | |
147ae1cb JM |
483 | |
484 | writel_relaxed(OSD_BLEND_PATH_SEL_ENABLE, | |
485 | priv->io_base + _REG(OSD1_BLEND_SRC_CTRL)); | |
486 | writel_relaxed(OSD_BLEND_PATH_SEL_ENABLE, | |
487 | priv->io_base + _REG(OSD2_BLEND_SRC_CTRL)); | |
72888394 NA |
488 | writel_relaxed(0, priv->io_base + _REG(VD1_BLEND_SRC_CTRL)); |
489 | writel_relaxed(0, priv->io_base + _REG(VD2_BLEND_SRC_CTRL)); | |
490 | writel_relaxed(0, | |
491 | priv->io_base + _REG(VIU_OSD_BLEND_DUMMY_DATA0)); | |
492 | writel_relaxed(0, | |
493 | priv->io_base + _REG(VIU_OSD_BLEND_DUMMY_ALPHA)); | |
147ae1cb JM |
494 | |
495 | writel_bits_relaxed(DOLBY_BYPASS_EN(0xc), DOLBY_BYPASS_EN(0xc), | |
496 | priv->io_base + _REG(DOLBY_PATH_CTRL)); | |
1b85270f NA |
497 | |
498 | meson_viu_g12a_disable_osd1_afbc(priv); | |
72888394 | 499 | } |
f9a23481 | 500 | |
1b85270f NA |
501 | if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM)) |
502 | meson_viu_gxm_disable_osd1_afbc(priv); | |
503 | ||
bbbe775e NA |
504 | priv->viu.osd1_enabled = false; |
505 | priv->viu.osd1_commit = false; | |
506 | priv->viu.osd1_interlace = false; | |
507 | } |