cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

meson_osd_afbcd.c (11217B)


      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_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	else
    160		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};