Merge tag 'soundwire-5.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul...
[linux-2.6-microblaze.git] / drivers / gpu / drm / meson / meson_osd_afbcd.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2019 BayLibre, SAS
4  * Author: Neil Armstrong <narmstrong@baylibre.com>
5  */
6
7 #include <linux/bitfield.h>
8
9 #include <drm/drm_print.h>
10 #include <drm/drm_fourcc.h>
11
12 #include "meson_drv.h"
13 #include "meson_registers.h"
14 #include "meson_viu.h"
15 #include "meson_rdma.h"
16 #include "meson_osd_afbcd.h"
17
18 /*
19  * DOC: Driver for the ARM FrameBuffer Compression Decoders
20  *
21  * The Amlogic GXM and G12A SoC families embeds an AFBC Decoder,
22  * to decode compressed buffers generated by the ARM Mali GPU.
23  *
24  * For the GXM Family, Amlogic designed their own Decoder, named in
25  * the vendor source as "MESON_AFBC", and a single decoder is available
26  * for the 2 OSD planes.
27  * This decoder is compatible with the AFBC 1.0 specifications and the
28  * Mali T820 GPU capabilities.
29  * It supports :
30  * - basic AFBC buffer for RGB32 only, thus YTR feature is mandatory
31  * - SPARSE layout and SPLIT layout
32  * - only 16x16 superblock
33  *
34  * The decoder reads the data from the SDRAM, decodes and sends the
35  * decoded pixel stream to the OSD1 Plane pixel composer.
36  *
37  * For the G12A Family, Amlogic integrated an ARM AFBC Decoder, named
38  * in the vendor source as "MALI_AFBC", and the decoder can decode up
39  * to 4 surfaces, one for each of the 4 available OSDs.
40  * This decoder is compatible with the AFBC 1.2 specifications for the
41  * Mali G31 and G52 GPUs.
42  * Is supports :
43  * - basic AFBC buffer for multiple RGB and YUV pixel formats
44  * - SPARSE layout and SPLIT layout
45  * - 16x16 and 32x8 "wideblk" superblocks
46  * - Tiled header
47  *
48  * The ARM AFBC Decoder independent from the VPU Pixel Pipeline, so
49  * the ARM AFBC Decoder reads the data from the SDRAM then decodes
50  * into a private internal physical address where the OSD1 Plane pixel
51  * composer unpacks the decoded data.
52  */
53
54 /* Amlogic AFBC Decoder for GXM Family */
55
56 #define OSD1_AFBCD_RGB32        0x15
57
58 static int meson_gxm_afbcd_pixel_fmt(u64 modifier, uint32_t format)
59 {
60         switch (format) {
61         case DRM_FORMAT_XBGR8888:
62         case DRM_FORMAT_ABGR8888:
63                 return OSD1_AFBCD_RGB32;
64         /* TOFIX support mode formats */
65         default:
66                 DRM_DEBUG("unsupported afbc format[%08x]\n", format);
67                 return -EINVAL;
68         }
69 }
70
71 static bool meson_gxm_afbcd_supported_fmt(u64 modifier, uint32_t format)
72 {
73         if (modifier & AFBC_FORMAT_MOD_BLOCK_SIZE_32x8)
74                 return false;
75
76         if (!(modifier & AFBC_FORMAT_MOD_YTR))
77                 return false;
78
79         return meson_gxm_afbcd_pixel_fmt(modifier, format) >= 0;
80 }
81
82 static int meson_gxm_afbcd_init(struct meson_drm *priv)
83 {
84         return 0;
85 }
86
87 static int meson_gxm_afbcd_reset(struct meson_drm *priv)
88 {
89         writel_relaxed(VIU_SW_RESET_OSD1_AFBCD,
90                        priv->io_base + _REG(VIU_SW_RESET));
91         writel_relaxed(0, priv->io_base + _REG(VIU_SW_RESET));
92
93         return 0;
94 }
95
96 static int meson_gxm_afbcd_enable(struct meson_drm *priv)
97 {
98         writel_relaxed(FIELD_PREP(OSD1_AFBCD_ID_FIFO_THRD, 0x40) |
99                        OSD1_AFBCD_DEC_ENABLE,
100                        priv->io_base + _REG(OSD1_AFBCD_ENABLE));
101
102         return 0;
103 }
104
105 static int meson_gxm_afbcd_disable(struct meson_drm *priv)
106 {
107         writel_bits_relaxed(OSD1_AFBCD_DEC_ENABLE, 0,
108                             priv->io_base + _REG(OSD1_AFBCD_ENABLE));
109
110         return 0;
111 }
112
113 static int meson_gxm_afbcd_setup(struct meson_drm *priv)
114 {
115         u32 conv_lbuf_len;
116         u32 mode = FIELD_PREP(OSD1_AFBCD_MIF_URGENT, 3) |
117                    FIELD_PREP(OSD1_AFBCD_HOLD_LINE_NUM, 4) |
118                    FIELD_PREP(OSD1_AFBCD_RGBA_EXCHAN_CTRL, 0x34) |
119                    meson_gxm_afbcd_pixel_fmt(priv->afbcd.modifier,
120                                              priv->afbcd.format);
121
122         if (priv->afbcd.modifier & AFBC_FORMAT_MOD_SPARSE)
123                 mode |= OSD1_AFBCD_HREG_HALF_BLOCK;
124
125         if (priv->afbcd.modifier & AFBC_FORMAT_MOD_SPLIT)
126                 mode |= OSD1_AFBCD_HREG_BLOCK_SPLIT;
127
128         writel_relaxed(mode, priv->io_base + _REG(OSD1_AFBCD_MODE));
129
130         writel_relaxed(FIELD_PREP(OSD1_AFBCD_HREG_VSIZE_IN,
131                                   priv->viu.osd1_width) |
132                        FIELD_PREP(OSD1_AFBCD_HREG_HSIZE_IN,
133                                   priv->viu.osd1_height),
134                        priv->io_base + _REG(OSD1_AFBCD_SIZE_IN));
135
136         writel_relaxed(priv->viu.osd1_addr >> 4,
137                        priv->io_base + _REG(OSD1_AFBCD_HDR_PTR));
138         writel_relaxed(priv->viu.osd1_addr >> 4,
139                        priv->io_base + _REG(OSD1_AFBCD_FRAME_PTR));
140         /* TOFIX: bits 31:24 are not documented, nor the meaning of 0xe4 */
141         writel_relaxed((0xe4 << 24) | (priv->viu.osd1_addr & 0xffffff),
142                        priv->io_base + _REG(OSD1_AFBCD_CHROMA_PTR));
143
144         if (priv->viu.osd1_width <= 128)
145                 conv_lbuf_len = 32;
146         else if (priv->viu.osd1_width <= 256)
147                 conv_lbuf_len = 64;
148         else if (priv->viu.osd1_width <= 512)
149                 conv_lbuf_len = 128;
150         else if (priv->viu.osd1_width <= 1024)
151                 conv_lbuf_len = 256;
152         else if (priv->viu.osd1_width <= 2048)
153                 conv_lbuf_len = 512;
154         else
155                 conv_lbuf_len = 1024;
156
157         writel_relaxed(conv_lbuf_len,
158                        priv->io_base + _REG(OSD1_AFBCD_CONV_CTRL));
159
160         writel_relaxed(FIELD_PREP(OSD1_AFBCD_DEC_PIXEL_BGN_H, 0) |
161                        FIELD_PREP(OSD1_AFBCD_DEC_PIXEL_END_H,
162                                   priv->viu.osd1_width - 1),
163                        priv->io_base + _REG(OSD1_AFBCD_PIXEL_HSCOPE));
164
165         writel_relaxed(FIELD_PREP(OSD1_AFBCD_DEC_PIXEL_BGN_V, 0) |
166                        FIELD_PREP(OSD1_AFBCD_DEC_PIXEL_END_V,
167                                   priv->viu.osd1_height - 1),
168                        priv->io_base + _REG(OSD1_AFBCD_PIXEL_VSCOPE));
169
170         return 0;
171 }
172
173 struct meson_afbcd_ops meson_afbcd_gxm_ops = {
174         .init = meson_gxm_afbcd_init,
175         .reset = meson_gxm_afbcd_reset,
176         .enable = meson_gxm_afbcd_enable,
177         .disable = meson_gxm_afbcd_disable,
178         .setup = meson_gxm_afbcd_setup,
179         .supported_fmt = meson_gxm_afbcd_supported_fmt,
180 };
181
182 /* ARM AFBC Decoder for G12A Family */
183
184 /* Amlogic G12A Mali AFBC Decoder supported formats */
185 enum {
186         MAFBC_FMT_RGB565 = 0,
187         MAFBC_FMT_RGBA5551,
188         MAFBC_FMT_RGBA1010102,
189         MAFBC_FMT_YUV420_10B,
190         MAFBC_FMT_RGB888,
191         MAFBC_FMT_RGBA8888,
192         MAFBC_FMT_RGBA4444,
193         MAFBC_FMT_R8,
194         MAFBC_FMT_RG88,
195         MAFBC_FMT_YUV420_8B,
196         MAFBC_FMT_YUV422_8B = 11,
197         MAFBC_FMT_YUV422_10B = 14,
198 };
199
200 static int meson_g12a_afbcd_pixel_fmt(u64 modifier, uint32_t format)
201 {
202         switch (format) {
203         case DRM_FORMAT_XRGB8888:
204         case DRM_FORMAT_ARGB8888:
205                 /* YTR is forbidden for non XBGR formats */
206                 if (modifier & AFBC_FORMAT_MOD_YTR)
207                         return -EINVAL;
208                 fallthrough;
209         case DRM_FORMAT_XBGR8888:
210         case DRM_FORMAT_ABGR8888:
211                 return MAFBC_FMT_RGBA8888;
212         case DRM_FORMAT_RGB888:
213                 /* YTR is forbidden for non XBGR formats */
214                 if (modifier & AFBC_FORMAT_MOD_YTR)
215                         return -EINVAL;
216                 return MAFBC_FMT_RGB888;
217         case DRM_FORMAT_RGB565:
218                 /* YTR is forbidden for non XBGR formats */
219                 if (modifier & AFBC_FORMAT_MOD_YTR)
220                         return -EINVAL;
221                 return MAFBC_FMT_RGB565;
222         /* TOFIX support mode formats */
223         default:
224                 DRM_DEBUG("unsupported afbc format[%08x]\n", format);
225                 return -EINVAL;
226         }
227 }
228
229 static int meson_g12a_afbcd_bpp(uint32_t format)
230 {
231         switch (format) {
232         case DRM_FORMAT_XRGB8888:
233         case DRM_FORMAT_ARGB8888:
234         case DRM_FORMAT_XBGR8888:
235         case DRM_FORMAT_ABGR8888:
236                 return 32;
237         case DRM_FORMAT_RGB888:
238                 return 24;
239         case DRM_FORMAT_RGB565:
240                 return 16;
241         /* TOFIX support mode formats */
242         default:
243                 DRM_ERROR("unsupported afbc format[%08x]\n", format);
244                 return 0;
245         }
246 }
247
248 static int meson_g12a_afbcd_fmt_to_blk_mode(u64 modifier, uint32_t format)
249 {
250         switch (format) {
251         case DRM_FORMAT_XRGB8888:
252         case DRM_FORMAT_ARGB8888:
253         case DRM_FORMAT_XBGR8888:
254         case DRM_FORMAT_ABGR8888:
255                 return OSD_MALI_COLOR_MODE_RGBA8888;
256         case DRM_FORMAT_RGB888:
257                 return OSD_MALI_COLOR_MODE_RGB888;
258         case DRM_FORMAT_RGB565:
259                 return OSD_MALI_COLOR_MODE_RGB565;
260         /* TOFIX support mode formats */
261         default:
262                 DRM_DEBUG("unsupported afbc format[%08x]\n", format);
263                 return -EINVAL;
264         }
265 }
266
267 static bool meson_g12a_afbcd_supported_fmt(u64 modifier, uint32_t format)
268 {
269         return meson_g12a_afbcd_pixel_fmt(modifier, format) >= 0;
270 }
271
272 static int meson_g12a_afbcd_init(struct meson_drm *priv)
273 {
274         int ret;
275
276         ret = meson_rdma_init(priv);
277         if (ret)
278                 return ret;
279
280         meson_rdma_setup(priv);
281
282         /* Handle AFBC Decoder reset manually */
283         writel_bits_relaxed(MALI_AFBCD_MANUAL_RESET, MALI_AFBCD_MANUAL_RESET,
284                             priv->io_base + _REG(MALI_AFBCD_TOP_CTRL));
285
286         return 0;
287 }
288
289 static int meson_g12a_afbcd_reset(struct meson_drm *priv)
290 {
291         meson_rdma_reset(priv);
292
293         meson_rdma_writel_sync(priv, VIU_SW_RESET_G12A_AFBC_ARB |
294                                VIU_SW_RESET_G12A_OSD1_AFBCD,
295                                VIU_SW_RESET);
296         meson_rdma_writel_sync(priv, 0, VIU_SW_RESET);
297
298         return 0;
299 }
300
301 static int meson_g12a_afbcd_enable(struct meson_drm *priv)
302 {
303         meson_rdma_writel_sync(priv, VPU_MAFBC_IRQ_SURFACES_COMPLETED |
304                                VPU_MAFBC_IRQ_CONFIGURATION_SWAPPED |
305                                VPU_MAFBC_IRQ_DECODE_ERROR |
306                                VPU_MAFBC_IRQ_DETILING_ERROR,
307                                VPU_MAFBC_IRQ_MASK);
308
309         meson_rdma_writel_sync(priv, VPU_MAFBC_S0_ENABLE,
310                                VPU_MAFBC_SURFACE_CFG);
311
312         meson_rdma_writel_sync(priv, VPU_MAFBC_DIRECT_SWAP,
313                                VPU_MAFBC_COMMAND);
314
315         /* This will enable the RDMA replaying the register writes on vsync */
316         meson_rdma_flush(priv);
317
318         return 0;
319 }
320
321 static int meson_g12a_afbcd_disable(struct meson_drm *priv)
322 {
323         writel_bits_relaxed(VPU_MAFBC_S0_ENABLE, 0,
324                             priv->io_base + _REG(VPU_MAFBC_SURFACE_CFG));
325
326         return 0;
327 }
328
329 static int meson_g12a_afbcd_setup(struct meson_drm *priv)
330 {
331         u32 format = meson_g12a_afbcd_pixel_fmt(priv->afbcd.modifier,
332                                                 priv->afbcd.format);
333
334         if (priv->afbcd.modifier & AFBC_FORMAT_MOD_YTR)
335                 format |= VPU_MAFBC_YUV_TRANSFORM;
336
337         if (priv->afbcd.modifier & AFBC_FORMAT_MOD_SPLIT)
338                 format |= VPU_MAFBC_BLOCK_SPLIT;
339
340         if (priv->afbcd.modifier & AFBC_FORMAT_MOD_TILED)
341                 format |= VPU_MAFBC_TILED_HEADER_EN;
342
343         if ((priv->afbcd.modifier & AFBC_FORMAT_MOD_BLOCK_SIZE_MASK) ==
344                 AFBC_FORMAT_MOD_BLOCK_SIZE_32x8)
345                 format |= FIELD_PREP(VPU_MAFBC_SUPER_BLOCK_ASPECT, 1);
346
347         meson_rdma_writel_sync(priv, format,
348                                VPU_MAFBC_FORMAT_SPECIFIER_S0);
349
350         meson_rdma_writel_sync(priv, priv->viu.osd1_addr,
351                                VPU_MAFBC_HEADER_BUF_ADDR_LOW_S0);
352         meson_rdma_writel_sync(priv, 0,
353                                VPU_MAFBC_HEADER_BUF_ADDR_HIGH_S0);
354
355         meson_rdma_writel_sync(priv, priv->viu.osd1_width,
356                                VPU_MAFBC_BUFFER_WIDTH_S0);
357         meson_rdma_writel_sync(priv, ALIGN(priv->viu.osd1_height, 32),
358                                VPU_MAFBC_BUFFER_HEIGHT_S0);
359
360         meson_rdma_writel_sync(priv, 0,
361                                VPU_MAFBC_BOUNDING_BOX_X_START_S0);
362         meson_rdma_writel_sync(priv, priv->viu.osd1_width - 1,
363                                VPU_MAFBC_BOUNDING_BOX_X_END_S0);
364         meson_rdma_writel_sync(priv, 0,
365                                VPU_MAFBC_BOUNDING_BOX_Y_START_S0);
366         meson_rdma_writel_sync(priv, priv->viu.osd1_height - 1,
367                                VPU_MAFBC_BOUNDING_BOX_Y_END_S0);
368
369         meson_rdma_writel_sync(priv, MESON_G12A_AFBCD_OUT_ADDR,
370                                VPU_MAFBC_OUTPUT_BUF_ADDR_LOW_S0);
371         meson_rdma_writel_sync(priv, 0,
372                                VPU_MAFBC_OUTPUT_BUF_ADDR_HIGH_S0);
373
374         meson_rdma_writel_sync(priv, priv->viu.osd1_width *
375                                (meson_g12a_afbcd_bpp(priv->afbcd.format) / 8),
376                                VPU_MAFBC_OUTPUT_BUF_STRIDE_S0);
377
378         return 0;
379 }
380
381 struct meson_afbcd_ops meson_afbcd_g12a_ops = {
382         .init = meson_g12a_afbcd_init,
383         .reset = meson_g12a_afbcd_reset,
384         .enable = meson_g12a_afbcd_enable,
385         .disable = meson_g12a_afbcd_disable,
386         .setup = meson_g12a_afbcd_setup,
387         .fmt_to_blk_mode = meson_g12a_afbcd_fmt_to_blk_mode,
388         .supported_fmt = meson_g12a_afbcd_supported_fmt,
389 };