b59072342cae739b3baa04cdcac36052f4f587ce
[linux-2.6-block.git] / drivers / gpu / drm / meson / meson_viu.c
1 /*
2  * Copyright (C) 2016 BayLibre, SAS
3  * Author: Neil Armstrong <narmstrong@baylibre.com>
4  * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
5  * Copyright (C) 2014 Endless Mobile
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License as
9  * published by the Free Software Foundation; either version 2 of the
10  * License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, see <http://www.gnu.org/licenses/>.
19  */
20
21 #include <linux/kernel.h>
22 #include <linux/module.h>
23 #include <drm/drmP.h>
24 #include "meson_drv.h"
25 #include "meson_viu.h"
26 #include "meson_vpp.h"
27 #include "meson_venc.h"
28 #include "meson_registers.h"
29
30 /**
31  * DOC: Video Input Unit
32  *
33  * VIU Handles the Pixel scanout and the basic Colorspace conversions
34  * We handle the following features :
35  *
36  * - OSD1 RGB565/RGB888/xRGB8888 scanout
37  * - RGB conversion to x/cb/cr
38  * - Progressive or Interlace buffer scanout
39  * - OSD1 Commit on Vsync
40  * - HDR OSD matrix for GXL/GXM
41  *
42  * What is missing :
43  *
44  * - BGR888/xBGR8888/BGRx8888/BGRx8888 modes
45  * - YUV4:2:2 Y0CbY1Cr scanout
46  * - Conversion to YUV 4:4:4 from 4:2:2 input
47  * - Colorkey Alpha matching
48  * - Big endian scanout
49  * - X/Y reverse scanout
50  * - Global alpha setup
51  * - OSD2 support, would need interlace switching on vsync
52  * - OSD1 full scaling to support TV overscan
53  */
54
55 /* OSD csc defines */
56
57 enum viu_matrix_sel_e {
58         VIU_MATRIX_OSD_EOTF = 0,
59         VIU_MATRIX_OSD,
60 };
61
62 enum viu_lut_sel_e {
63         VIU_LUT_OSD_EOTF = 0,
64         VIU_LUT_OSD_OETF,
65 };
66
67 #define COEFF_NORM(a) ((int)((((a) * 2048.0) + 1) / 2))
68 #define MATRIX_5X3_COEF_SIZE 24
69
70 #define EOTF_COEFF_NORM(a) ((int)((((a) * 4096.0) + 1) / 2))
71 #define EOTF_COEFF_SIZE 10
72 #define EOTF_COEFF_RIGHTSHIFT 1
73
74 static int RGB709_to_YUV709l_coeff[MATRIX_5X3_COEF_SIZE] = {
75         0, 0, 0, /* pre offset */
76         COEFF_NORM(0.181873),   COEFF_NORM(0.611831),   COEFF_NORM(0.061765),
77         COEFF_NORM(-0.100251),  COEFF_NORM(-0.337249),  COEFF_NORM(0.437500),
78         COEFF_NORM(0.437500),   COEFF_NORM(-0.397384),  COEFF_NORM(-0.040116),
79         0, 0, 0, /* 10'/11'/12' */
80         0, 0, 0, /* 20'/21'/22' */
81         64, 512, 512, /* offset */
82         0, 0, 0 /* mode, right_shift, clip_en */
83 };
84
85 /*  eotf matrix: bypass */
86 static int eotf_bypass_coeff[EOTF_COEFF_SIZE] = {
87         EOTF_COEFF_NORM(1.0),   EOTF_COEFF_NORM(0.0),   EOTF_COEFF_NORM(0.0),
88         EOTF_COEFF_NORM(0.0),   EOTF_COEFF_NORM(1.0),   EOTF_COEFF_NORM(0.0),
89         EOTF_COEFF_NORM(0.0),   EOTF_COEFF_NORM(0.0),   EOTF_COEFF_NORM(1.0),
90         EOTF_COEFF_RIGHTSHIFT /* right shift */
91 };
92
93 static void meson_viu_set_g12a_osd1_matrix(struct meson_drm *priv,
94                                            int *m, bool csc_on)
95 {
96         /* VPP WRAP OSD1 matrix */
97         writel(((m[0] & 0xfff) << 16) | (m[1] & 0xfff),
98                 priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_PRE_OFFSET0_1));
99         writel(m[2] & 0xfff,
100                 priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_PRE_OFFSET2));
101         writel(((m[3] & 0x1fff) << 16) | (m[4] & 0x1fff),
102                 priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF00_01));
103         writel(((m[5] & 0x1fff) << 16) | (m[6] & 0x1fff),
104                 priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF02_10));
105         writel(((m[7] & 0x1fff) << 16) | (m[8] & 0x1fff),
106                 priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF11_12));
107         writel(((m[9] & 0x1fff) << 16) | (m[10] & 0x1fff),
108                 priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF20_21));
109         writel((m[11] & 0x1fff) << 16,
110                 priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF22));
111
112         writel(((m[18] & 0xfff) << 16) | (m[19] & 0xfff),
113                 priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_OFFSET0_1));
114         writel(m[20] & 0xfff,
115                 priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_OFFSET2));
116
117         writel_bits_relaxed(BIT(0), csc_on ? BIT(0) : 0,
118                 priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_EN_CTRL));
119 }
120
121 static void meson_viu_set_osd_matrix(struct meson_drm *priv,
122                                      enum viu_matrix_sel_e m_select,
123                               int *m, bool csc_on)
124 {
125         if (m_select == VIU_MATRIX_OSD) {
126                 /* osd matrix, VIU_MATRIX_0 */
127                 writel(((m[0] & 0xfff) << 16) | (m[1] & 0xfff),
128                         priv->io_base + _REG(VIU_OSD1_MATRIX_PRE_OFFSET0_1));
129                 writel(m[2] & 0xfff,
130                         priv->io_base + _REG(VIU_OSD1_MATRIX_PRE_OFFSET2));
131                 writel(((m[3] & 0x1fff) << 16) | (m[4] & 0x1fff),
132                         priv->io_base + _REG(VIU_OSD1_MATRIX_COEF00_01));
133                 writel(((m[5] & 0x1fff) << 16) | (m[6] & 0x1fff),
134                         priv->io_base + _REG(VIU_OSD1_MATRIX_COEF02_10));
135                 writel(((m[7] & 0x1fff) << 16) | (m[8] & 0x1fff),
136                         priv->io_base + _REG(VIU_OSD1_MATRIX_COEF11_12));
137                 writel(((m[9] & 0x1fff) << 16) | (m[10] & 0x1fff),
138                         priv->io_base + _REG(VIU_OSD1_MATRIX_COEF20_21));
139
140                 if (m[21]) {
141                         writel(((m[11] & 0x1fff) << 16) | (m[12] & 0x1fff),
142                                 priv->io_base +
143                                         _REG(VIU_OSD1_MATRIX_COEF22_30));
144                         writel(((m[13] & 0x1fff) << 16) | (m[14] & 0x1fff),
145                                 priv->io_base +
146                                         _REG(VIU_OSD1_MATRIX_COEF31_32));
147                         writel(((m[15] & 0x1fff) << 16) | (m[16] & 0x1fff),
148                                 priv->io_base +
149                                         _REG(VIU_OSD1_MATRIX_COEF40_41));
150                         writel(m[17] & 0x1fff, priv->io_base +
151                                 _REG(VIU_OSD1_MATRIX_COLMOD_COEF42));
152                 } else
153                         writel((m[11] & 0x1fff) << 16, priv->io_base +
154                                 _REG(VIU_OSD1_MATRIX_COEF22_30));
155
156                 writel(((m[18] & 0xfff) << 16) | (m[19] & 0xfff),
157                         priv->io_base + _REG(VIU_OSD1_MATRIX_OFFSET0_1));
158                 writel(m[20] & 0xfff,
159                         priv->io_base + _REG(VIU_OSD1_MATRIX_OFFSET2));
160
161                 writel_bits_relaxed(3 << 30, m[21] << 30,
162                         priv->io_base + _REG(VIU_OSD1_MATRIX_COLMOD_COEF42));
163                 writel_bits_relaxed(7 << 16, m[22] << 16,
164                         priv->io_base + _REG(VIU_OSD1_MATRIX_COLMOD_COEF42));
165
166                 /* 23 reserved for clipping control */
167                 writel_bits_relaxed(BIT(0), csc_on ? BIT(0) : 0,
168                         priv->io_base + _REG(VIU_OSD1_MATRIX_CTRL));
169                 writel_bits_relaxed(BIT(1), 0,
170                         priv->io_base + _REG(VIU_OSD1_MATRIX_CTRL));
171         } else if (m_select == VIU_MATRIX_OSD_EOTF) {
172                 int i;
173
174                 /* osd eotf matrix, VIU_MATRIX_OSD_EOTF */
175                 for (i = 0; i < 5; i++)
176                         writel(((m[i * 2] & 0x1fff) << 16) |
177                                 (m[i * 2 + 1] & 0x1fff), priv->io_base +
178                                 _REG(VIU_OSD1_EOTF_CTL + i + 1));
179
180                 writel_bits_relaxed(BIT(30), csc_on ? BIT(30) : 0,
181                         priv->io_base + _REG(VIU_OSD1_EOTF_CTL));
182                 writel_bits_relaxed(BIT(31), csc_on ? BIT(31) : 0,
183                         priv->io_base + _REG(VIU_OSD1_EOTF_CTL));
184         }
185 }
186
187 #define OSD_EOTF_LUT_SIZE 33
188 #define OSD_OETF_LUT_SIZE 41
189
190 static void
191 meson_viu_set_osd_lut(struct meson_drm *priv, enum viu_lut_sel_e lut_sel,
192                       unsigned int *r_map, unsigned int *g_map,
193                       unsigned int *b_map, bool csc_on)
194 {
195         unsigned int addr_port;
196         unsigned int data_port;
197         unsigned int ctrl_port;
198         int i;
199
200         if (lut_sel == VIU_LUT_OSD_EOTF) {
201                 addr_port = VIU_OSD1_EOTF_LUT_ADDR_PORT;
202                 data_port = VIU_OSD1_EOTF_LUT_DATA_PORT;
203                 ctrl_port = VIU_OSD1_EOTF_CTL;
204         } else if (lut_sel == VIU_LUT_OSD_OETF) {
205                 addr_port = VIU_OSD1_OETF_LUT_ADDR_PORT;
206                 data_port = VIU_OSD1_OETF_LUT_DATA_PORT;
207                 ctrl_port = VIU_OSD1_OETF_CTL;
208         } else
209                 return;
210
211         if (lut_sel == VIU_LUT_OSD_OETF) {
212                 writel(0, priv->io_base + _REG(addr_port));
213
214                 for (i = 0; i < (OSD_OETF_LUT_SIZE / 2); i++)
215                         writel(r_map[i * 2] | (r_map[i * 2 + 1] << 16),
216                                 priv->io_base + _REG(data_port));
217
218                 writel(r_map[OSD_OETF_LUT_SIZE - 1] | (g_map[0] << 16),
219                         priv->io_base + _REG(data_port));
220
221                 for (i = 0; i < (OSD_OETF_LUT_SIZE / 2); i++)
222                         writel(g_map[i * 2 + 1] | (g_map[i * 2 + 2] << 16),
223                                 priv->io_base + _REG(data_port));
224
225                 for (i = 0; i < (OSD_OETF_LUT_SIZE / 2); i++)
226                         writel(b_map[i * 2] | (b_map[i * 2 + 1] << 16),
227                                 priv->io_base + _REG(data_port));
228
229                 writel(b_map[OSD_OETF_LUT_SIZE - 1],
230                         priv->io_base + _REG(data_port));
231
232                 if (csc_on)
233                         writel_bits_relaxed(0x7 << 29, 7 << 29,
234                                             priv->io_base + _REG(ctrl_port));
235                 else
236                         writel_bits_relaxed(0x7 << 29, 0,
237                                             priv->io_base + _REG(ctrl_port));
238         } else if (lut_sel == VIU_LUT_OSD_EOTF) {
239                 writel(0, priv->io_base + _REG(addr_port));
240
241                 for (i = 0; i < (OSD_EOTF_LUT_SIZE / 2); i++)
242                         writel(r_map[i * 2] | (r_map[i * 2 + 1] << 16),
243                                 priv->io_base + _REG(data_port));
244
245                 writel(r_map[OSD_EOTF_LUT_SIZE - 1] | (g_map[0] << 16),
246                         priv->io_base + _REG(data_port));
247
248                 for (i = 0; i < (OSD_EOTF_LUT_SIZE / 2); i++)
249                         writel(g_map[i * 2 + 1] | (g_map[i * 2 + 2] << 16),
250                                 priv->io_base + _REG(data_port));
251
252                 for (i = 0; i < (OSD_EOTF_LUT_SIZE / 2); i++)
253                         writel(b_map[i * 2] | (b_map[i * 2 + 1] << 16),
254                                 priv->io_base + _REG(data_port));
255
256                 writel(b_map[OSD_EOTF_LUT_SIZE - 1],
257                         priv->io_base + _REG(data_port));
258
259                 if (csc_on)
260                         writel_bits_relaxed(7 << 27, 7 << 27,
261                                             priv->io_base + _REG(ctrl_port));
262                 else
263                         writel_bits_relaxed(7 << 27, 0,
264                                             priv->io_base + _REG(ctrl_port));
265
266                 writel_bits_relaxed(BIT(31), BIT(31),
267                                     priv->io_base + _REG(ctrl_port));
268         }
269 }
270
271 /* eotf lut: linear */
272 static unsigned int eotf_33_linear_mapping[OSD_EOTF_LUT_SIZE] = {
273         0x0000, 0x0200, 0x0400, 0x0600,
274         0x0800, 0x0a00, 0x0c00, 0x0e00,
275         0x1000, 0x1200, 0x1400, 0x1600,
276         0x1800, 0x1a00, 0x1c00, 0x1e00,
277         0x2000, 0x2200, 0x2400, 0x2600,
278         0x2800, 0x2a00, 0x2c00, 0x2e00,
279         0x3000, 0x3200, 0x3400, 0x3600,
280         0x3800, 0x3a00, 0x3c00, 0x3e00,
281         0x4000
282 };
283
284 /* osd oetf lut: linear */
285 static unsigned int oetf_41_linear_mapping[OSD_OETF_LUT_SIZE] = {
286         0, 0, 0, 0,
287         0, 32, 64, 96,
288         128, 160, 196, 224,
289         256, 288, 320, 352,
290         384, 416, 448, 480,
291         512, 544, 576, 608,
292         640, 672, 704, 736,
293         768, 800, 832, 864,
294         896, 928, 960, 992,
295         1023, 1023, 1023, 1023,
296         1023
297 };
298
299 static void meson_viu_load_matrix(struct meson_drm *priv)
300 {
301         /* eotf lut bypass */
302         meson_viu_set_osd_lut(priv, VIU_LUT_OSD_EOTF,
303                               eotf_33_linear_mapping, /* R */
304                               eotf_33_linear_mapping, /* G */
305                               eotf_33_linear_mapping, /* B */
306                               false);
307
308         /* eotf matrix bypass */
309         meson_viu_set_osd_matrix(priv, VIU_MATRIX_OSD_EOTF,
310                                  eotf_bypass_coeff,
311                                  false);
312
313         /* oetf lut bypass */
314         meson_viu_set_osd_lut(priv, VIU_LUT_OSD_OETF,
315                               oetf_41_linear_mapping, /* R */
316                               oetf_41_linear_mapping, /* G */
317                               oetf_41_linear_mapping, /* B */
318                               false);
319
320         /* osd matrix RGB709 to YUV709 limit */
321         meson_viu_set_osd_matrix(priv, VIU_MATRIX_OSD,
322                                  RGB709_to_YUV709l_coeff,
323                                  true);
324 }
325
326 /* VIU OSD1 Reset as workaround for GXL+ Alpha OSD Bug */
327 void meson_viu_osd1_reset(struct meson_drm *priv)
328 {
329         uint32_t osd1_fifo_ctrl_stat, osd1_ctrl_stat2;
330
331         /* Save these 2 registers state */
332         osd1_fifo_ctrl_stat = readl_relaxed(
333                                 priv->io_base + _REG(VIU_OSD1_FIFO_CTRL_STAT));
334         osd1_ctrl_stat2 = readl_relaxed(
335                                 priv->io_base + _REG(VIU_OSD1_CTRL_STAT2));
336
337         /* Reset OSD1 */
338         writel_bits_relaxed(BIT(0), BIT(0),
339                             priv->io_base + _REG(VIU_SW_RESET));
340         writel_bits_relaxed(BIT(0), 0,
341                             priv->io_base + _REG(VIU_SW_RESET));
342
343         /* Rewrite these registers state lost in the reset */
344         writel_relaxed(osd1_fifo_ctrl_stat,
345                        priv->io_base + _REG(VIU_OSD1_FIFO_CTRL_STAT));
346         writel_relaxed(osd1_ctrl_stat2,
347                        priv->io_base + _REG(VIU_OSD1_CTRL_STAT2));
348
349         /* Reload the conversion matrix */
350         meson_viu_load_matrix(priv);
351 }
352
353 void meson_viu_init(struct meson_drm *priv)
354 {
355         uint32_t reg;
356
357         /* Disable OSDs */
358         writel_bits_relaxed(BIT(0) | BIT(21), 0,
359                         priv->io_base + _REG(VIU_OSD1_CTRL_STAT));
360         writel_bits_relaxed(BIT(0) | BIT(21), 0,
361                         priv->io_base + _REG(VIU_OSD2_CTRL_STAT));
362
363         /* On GXL/GXM, Use the 10bit HDR conversion matrix */
364         if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
365             meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
366                 meson_viu_load_matrix(priv);
367         else if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu"))
368                 meson_viu_set_g12a_osd1_matrix(priv, RGB709_to_YUV709l_coeff,
369                                                true);
370
371         /* Initialize OSD1 fifo control register */
372         reg = BIT(0) |  /* Urgent DDR request priority */
373               (4 << 5); /* hold_fifo_lines */
374         if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu"))
375                 reg |= (1 << 10) | /* burst length 32 */
376                        (32 << 12) | /* fifo_depth_val: 32*8=256 */
377                        (2 << 22) | /* 4 words in 1 burst */
378                        (2 << 24) |
379                        (1 << 31);
380         else
381                 reg |= (3 << 10) | /* burst length 64 */
382                        (32 << 12) | /* fifo_depth_val: 32*8=256 */
383                        (2 << 22) | /* 4 words in 1 burst */
384                        (2 << 24);
385         writel_relaxed(reg, priv->io_base + _REG(VIU_OSD1_FIFO_CTRL_STAT));
386         writel_relaxed(reg, priv->io_base + _REG(VIU_OSD2_FIFO_CTRL_STAT));
387
388         /* Set OSD alpha replace value */
389         writel_bits_relaxed(0xff << OSD_REPLACE_SHIFT,
390                             0xff << OSD_REPLACE_SHIFT,
391                             priv->io_base + _REG(VIU_OSD1_CTRL_STAT2));
392         writel_bits_relaxed(0xff << OSD_REPLACE_SHIFT,
393                             0xff << OSD_REPLACE_SHIFT,
394                             priv->io_base + _REG(VIU_OSD2_CTRL_STAT2));
395
396         /* Disable VD1 AFBC */
397         /* di_mif0_en=0 mif0_to_vpp_en=0 di_mad_en=0 */
398         writel_bits_relaxed(0x7 << 16, 0,
399                         priv->io_base + _REG(VIU_MISC_CTRL0));
400         /* afbc vd1 set=0 */
401         writel_bits_relaxed(BIT(20), 0,
402                         priv->io_base + _REG(VIU_MISC_CTRL0));
403         writel_relaxed(0, priv->io_base + _REG(AFBC_ENABLE));
404
405         writel_relaxed(0x00FF00C0,
406                         priv->io_base + _REG(VD1_IF0_LUMA_FIFO_SIZE));
407         writel_relaxed(0x00FF00C0,
408                         priv->io_base + _REG(VD2_IF0_LUMA_FIFO_SIZE));
409
410         if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu")) {
411                 writel_relaxed(4 << 29 |
412                                 1 << 27 |
413                                 1 << 26 | /* blend_din0 input to blend0 */
414                                 1 << 25 | /* blend1_dout to blend2 */
415                                 1 << 24 | /* blend1_din3 input to blend1 */
416                                 1 << 20 |
417                                 0 << 16 |
418                                 1,
419                                 priv->io_base + _REG(VIU_OSD_BLEND_CTRL));
420                 writel_relaxed(3 << 8 |
421                                 1 << 20,
422                                 priv->io_base + _REG(OSD1_BLEND_SRC_CTRL));
423                 writel_relaxed(1 << 20,
424                                 priv->io_base + _REG(OSD2_BLEND_SRC_CTRL));
425                 writel_relaxed(0, priv->io_base + _REG(VD1_BLEND_SRC_CTRL));
426                 writel_relaxed(0, priv->io_base + _REG(VD2_BLEND_SRC_CTRL));
427                 writel_relaxed(0,
428                                 priv->io_base + _REG(VIU_OSD_BLEND_DUMMY_DATA0));
429                 writel_relaxed(0,
430                                 priv->io_base + _REG(VIU_OSD_BLEND_DUMMY_ALPHA));
431                 writel_bits_relaxed(0x3 << 2, 0x3 << 2,
432                                 priv->io_base + _REG(DOLBY_PATH_CTRL));
433         }
434
435         priv->viu.osd1_enabled = false;
436         priv->viu.osd1_commit = false;
437         priv->viu.osd1_interlace = false;
438 }