brintos

brintos / linux-shallow public Read only

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