Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  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
 58static 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
 71static 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
 82static int meson_gxm_afbcd_init(struct meson_drm *priv)
 83{
 84	return 0;
 85}
 86
 87static 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
 96static 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
105static 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
113static 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
173struct 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 */
185enum {
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
200static 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
229static 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
248static 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
267static bool meson_g12a_afbcd_supported_fmt(u64 modifier, uint32_t format)
268{
269	return meson_g12a_afbcd_pixel_fmt(modifier, format) >= 0;
270}
271
272static 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
289static 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
301static 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
321static 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
329static 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
381struct 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};