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