Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  * Copyright (C) 2019 BayLibre, SAS
0004  * Author: Neil Armstrong <narmstrong@baylibre.com>
0005  */
0006 
0007 #include <linux/bitfield.h>
0008 
0009 #include <drm/drm_print.h>
0010 #include <drm/drm_fourcc.h>
0011 
0012 #include "meson_drv.h"
0013 #include "meson_registers.h"
0014 #include "meson_viu.h"
0015 #include "meson_rdma.h"
0016 #include "meson_osd_afbcd.h"
0017 
0018 /*
0019  * DOC: Driver for the ARM FrameBuffer Compression Decoders
0020  *
0021  * The Amlogic GXM and G12A SoC families embeds an AFBC Decoder,
0022  * to decode compressed buffers generated by the ARM Mali GPU.
0023  *
0024  * For the GXM Family, Amlogic designed their own Decoder, named in
0025  * the vendor source as "MESON_AFBC", and a single decoder is available
0026  * for the 2 OSD planes.
0027  * This decoder is compatible with the AFBC 1.0 specifications and the
0028  * Mali T820 GPU capabilities.
0029  * It supports :
0030  * - basic AFBC buffer for RGB32 only, thus YTR feature is mandatory
0031  * - SPARSE layout and SPLIT layout
0032  * - only 16x16 superblock
0033  *
0034  * The decoder reads the data from the SDRAM, decodes and sends the
0035  * decoded pixel stream to the OSD1 Plane pixel composer.
0036  *
0037  * For the G12A Family, Amlogic integrated an ARM AFBC Decoder, named
0038  * in the vendor source as "MALI_AFBC", and the decoder can decode up
0039  * to 4 surfaces, one for each of the 4 available OSDs.
0040  * This decoder is compatible with the AFBC 1.2 specifications for the
0041  * Mali G31 and G52 GPUs.
0042  * Is supports :
0043  * - basic AFBC buffer for multiple RGB and YUV pixel formats
0044  * - SPARSE layout and SPLIT layout
0045  * - 16x16 and 32x8 "wideblk" superblocks
0046  * - Tiled header
0047  *
0048  * The ARM AFBC Decoder independent from the VPU Pixel Pipeline, so
0049  * the ARM AFBC Decoder reads the data from the SDRAM then decodes
0050  * into a private internal physical address where the OSD1 Plane pixel
0051  * composer unpacks the decoded data.
0052  */
0053 
0054 /* Amlogic AFBC Decoder for GXM Family */
0055 
0056 #define OSD1_AFBCD_RGB32    0x15
0057 
0058 static int meson_gxm_afbcd_pixel_fmt(u64 modifier, uint32_t format)
0059 {
0060     switch (format) {
0061     case DRM_FORMAT_XBGR8888:
0062     case DRM_FORMAT_ABGR8888:
0063         return OSD1_AFBCD_RGB32;
0064     /* TOFIX support mode formats */
0065     default:
0066         DRM_DEBUG("unsupported afbc format[%08x]\n", format);
0067         return -EINVAL;
0068     }
0069 }
0070 
0071 static bool meson_gxm_afbcd_supported_fmt(u64 modifier, uint32_t format)
0072 {
0073     if (modifier & AFBC_FORMAT_MOD_BLOCK_SIZE_32x8)
0074         return false;
0075 
0076     if (!(modifier & AFBC_FORMAT_MOD_YTR))
0077         return false;
0078 
0079     return meson_gxm_afbcd_pixel_fmt(modifier, format) >= 0;
0080 }
0081 
0082 static int meson_gxm_afbcd_reset(struct meson_drm *priv)
0083 {
0084     writel_relaxed(VIU_SW_RESET_OSD1_AFBCD,
0085                priv->io_base + _REG(VIU_SW_RESET));
0086     writel_relaxed(0, priv->io_base + _REG(VIU_SW_RESET));
0087 
0088     return 0;
0089 }
0090 
0091 static int meson_gxm_afbcd_init(struct meson_drm *priv)
0092 {
0093     return 0;
0094 }
0095 
0096 static void meson_gxm_afbcd_exit(struct meson_drm *priv)
0097 {
0098     meson_gxm_afbcd_reset(priv);
0099 }
0100 
0101 static int meson_gxm_afbcd_enable(struct meson_drm *priv)
0102 {
0103     writel_relaxed(FIELD_PREP(OSD1_AFBCD_ID_FIFO_THRD, 0x40) |
0104                OSD1_AFBCD_DEC_ENABLE,
0105                priv->io_base + _REG(OSD1_AFBCD_ENABLE));
0106 
0107     return 0;
0108 }
0109 
0110 static int meson_gxm_afbcd_disable(struct meson_drm *priv)
0111 {
0112     writel_bits_relaxed(OSD1_AFBCD_DEC_ENABLE, 0,
0113                 priv->io_base + _REG(OSD1_AFBCD_ENABLE));
0114 
0115     return 0;
0116 }
0117 
0118 static int meson_gxm_afbcd_setup(struct meson_drm *priv)
0119 {
0120     u32 conv_lbuf_len;
0121     u32 mode = FIELD_PREP(OSD1_AFBCD_MIF_URGENT, 3) |
0122            FIELD_PREP(OSD1_AFBCD_HOLD_LINE_NUM, 4) |
0123            FIELD_PREP(OSD1_AFBCD_RGBA_EXCHAN_CTRL, 0x34) |
0124            meson_gxm_afbcd_pixel_fmt(priv->afbcd.modifier,
0125                          priv->afbcd.format);
0126 
0127     if (priv->afbcd.modifier & AFBC_FORMAT_MOD_SPARSE)
0128         mode |= OSD1_AFBCD_HREG_HALF_BLOCK;
0129 
0130     if (priv->afbcd.modifier & AFBC_FORMAT_MOD_SPLIT)
0131         mode |= OSD1_AFBCD_HREG_BLOCK_SPLIT;
0132 
0133     writel_relaxed(mode, priv->io_base + _REG(OSD1_AFBCD_MODE));
0134 
0135     writel_relaxed(FIELD_PREP(OSD1_AFBCD_HREG_VSIZE_IN,
0136                   priv->viu.osd1_width) |
0137                FIELD_PREP(OSD1_AFBCD_HREG_HSIZE_IN,
0138                   priv->viu.osd1_height),
0139                priv->io_base + _REG(OSD1_AFBCD_SIZE_IN));
0140 
0141     writel_relaxed(priv->viu.osd1_addr >> 4,
0142                priv->io_base + _REG(OSD1_AFBCD_HDR_PTR));
0143     writel_relaxed(priv->viu.osd1_addr >> 4,
0144                priv->io_base + _REG(OSD1_AFBCD_FRAME_PTR));
0145     /* TOFIX: bits 31:24 are not documented, nor the meaning of 0xe4 */
0146     writel_relaxed((0xe4 << 24) | (priv->viu.osd1_addr & 0xffffff),
0147                priv->io_base + _REG(OSD1_AFBCD_CHROMA_PTR));
0148 
0149     if (priv->viu.osd1_width <= 128)
0150         conv_lbuf_len = 32;
0151     else if (priv->viu.osd1_width <= 256)
0152         conv_lbuf_len = 64;
0153     else if (priv->viu.osd1_width <= 512)
0154         conv_lbuf_len = 128;
0155     else if (priv->viu.osd1_width <= 1024)
0156         conv_lbuf_len = 256;
0157     else if (priv->viu.osd1_width <= 2048)
0158         conv_lbuf_len = 512;
0159     else
0160         conv_lbuf_len = 1024;
0161 
0162     writel_relaxed(conv_lbuf_len,
0163                priv->io_base + _REG(OSD1_AFBCD_CONV_CTRL));
0164 
0165     writel_relaxed(FIELD_PREP(OSD1_AFBCD_DEC_PIXEL_BGN_H, 0) |
0166                FIELD_PREP(OSD1_AFBCD_DEC_PIXEL_END_H,
0167                   priv->viu.osd1_width - 1),
0168                priv->io_base + _REG(OSD1_AFBCD_PIXEL_HSCOPE));
0169 
0170     writel_relaxed(FIELD_PREP(OSD1_AFBCD_DEC_PIXEL_BGN_V, 0) |
0171                FIELD_PREP(OSD1_AFBCD_DEC_PIXEL_END_V,
0172                   priv->viu.osd1_height - 1),
0173                priv->io_base + _REG(OSD1_AFBCD_PIXEL_VSCOPE));
0174 
0175     return 0;
0176 }
0177 
0178 struct meson_afbcd_ops meson_afbcd_gxm_ops = {
0179     .init = meson_gxm_afbcd_init,
0180     .exit = meson_gxm_afbcd_exit,
0181     .reset = meson_gxm_afbcd_reset,
0182     .enable = meson_gxm_afbcd_enable,
0183     .disable = meson_gxm_afbcd_disable,
0184     .setup = meson_gxm_afbcd_setup,
0185     .supported_fmt = meson_gxm_afbcd_supported_fmt,
0186 };
0187 
0188 /* ARM AFBC Decoder for G12A Family */
0189 
0190 /* Amlogic G12A Mali AFBC Decoder supported formats */
0191 enum {
0192     MAFBC_FMT_RGB565 = 0,
0193     MAFBC_FMT_RGBA5551,
0194     MAFBC_FMT_RGBA1010102,
0195     MAFBC_FMT_YUV420_10B,
0196     MAFBC_FMT_RGB888,
0197     MAFBC_FMT_RGBA8888,
0198     MAFBC_FMT_RGBA4444,
0199     MAFBC_FMT_R8,
0200     MAFBC_FMT_RG88,
0201     MAFBC_FMT_YUV420_8B,
0202     MAFBC_FMT_YUV422_8B = 11,
0203     MAFBC_FMT_YUV422_10B = 14,
0204 };
0205 
0206 static int meson_g12a_afbcd_pixel_fmt(u64 modifier, uint32_t format)
0207 {
0208     switch (format) {
0209     case DRM_FORMAT_XRGB8888:
0210     case DRM_FORMAT_ARGB8888:
0211         /* YTR is forbidden for non XBGR formats */
0212         if (modifier & AFBC_FORMAT_MOD_YTR)
0213             return -EINVAL;
0214         fallthrough;
0215     case DRM_FORMAT_XBGR8888:
0216     case DRM_FORMAT_ABGR8888:
0217         return MAFBC_FMT_RGBA8888;
0218     case DRM_FORMAT_RGB888:
0219         /* YTR is forbidden for non XBGR formats */
0220         if (modifier & AFBC_FORMAT_MOD_YTR)
0221             return -EINVAL;
0222         return MAFBC_FMT_RGB888;
0223     case DRM_FORMAT_RGB565:
0224         /* YTR is forbidden for non XBGR formats */
0225         if (modifier & AFBC_FORMAT_MOD_YTR)
0226             return -EINVAL;
0227         return MAFBC_FMT_RGB565;
0228     /* TOFIX support mode formats */
0229     default:
0230         DRM_DEBUG("unsupported afbc format[%08x]\n", format);
0231         return -EINVAL;
0232     }
0233 }
0234 
0235 static int meson_g12a_afbcd_bpp(uint32_t format)
0236 {
0237     switch (format) {
0238     case DRM_FORMAT_XRGB8888:
0239     case DRM_FORMAT_ARGB8888:
0240     case DRM_FORMAT_XBGR8888:
0241     case DRM_FORMAT_ABGR8888:
0242         return 32;
0243     case DRM_FORMAT_RGB888:
0244         return 24;
0245     case DRM_FORMAT_RGB565:
0246         return 16;
0247     /* TOFIX support mode formats */
0248     default:
0249         DRM_ERROR("unsupported afbc format[%08x]\n", format);
0250         return 0;
0251     }
0252 }
0253 
0254 static int meson_g12a_afbcd_fmt_to_blk_mode(u64 modifier, uint32_t format)
0255 {
0256     switch (format) {
0257     case DRM_FORMAT_XRGB8888:
0258     case DRM_FORMAT_ARGB8888:
0259     case DRM_FORMAT_XBGR8888:
0260     case DRM_FORMAT_ABGR8888:
0261         return OSD_MALI_COLOR_MODE_RGBA8888;
0262     case DRM_FORMAT_RGB888:
0263         return OSD_MALI_COLOR_MODE_RGB888;
0264     case DRM_FORMAT_RGB565:
0265         return OSD_MALI_COLOR_MODE_RGB565;
0266     /* TOFIX support mode formats */
0267     default:
0268         DRM_DEBUG("unsupported afbc format[%08x]\n", format);
0269         return -EINVAL;
0270     }
0271 }
0272 
0273 static bool meson_g12a_afbcd_supported_fmt(u64 modifier, uint32_t format)
0274 {
0275     return meson_g12a_afbcd_pixel_fmt(modifier, format) >= 0;
0276 }
0277 
0278 static int meson_g12a_afbcd_reset(struct meson_drm *priv)
0279 {
0280     meson_rdma_reset(priv);
0281 
0282     meson_rdma_writel_sync(priv, VIU_SW_RESET_G12A_AFBC_ARB |
0283                    VIU_SW_RESET_G12A_OSD1_AFBCD,
0284                    VIU_SW_RESET);
0285     meson_rdma_writel_sync(priv, 0, VIU_SW_RESET);
0286 
0287     return 0;
0288 }
0289 
0290 static int meson_g12a_afbcd_init(struct meson_drm *priv)
0291 {
0292     int ret;
0293 
0294     ret = meson_rdma_init(priv);
0295     if (ret)
0296         return ret;
0297 
0298     meson_rdma_setup(priv);
0299 
0300     /* Handle AFBC Decoder reset manually */
0301     writel_bits_relaxed(MALI_AFBCD_MANUAL_RESET, MALI_AFBCD_MANUAL_RESET,
0302                 priv->io_base + _REG(MALI_AFBCD_TOP_CTRL));
0303 
0304     return 0;
0305 }
0306 
0307 static void meson_g12a_afbcd_exit(struct meson_drm *priv)
0308 {
0309     meson_g12a_afbcd_reset(priv);
0310     meson_rdma_free(priv);
0311 }
0312 
0313 static int meson_g12a_afbcd_enable(struct meson_drm *priv)
0314 {
0315     meson_rdma_writel_sync(priv, VPU_MAFBC_IRQ_SURFACES_COMPLETED |
0316                    VPU_MAFBC_IRQ_CONFIGURATION_SWAPPED |
0317                    VPU_MAFBC_IRQ_DECODE_ERROR |
0318                    VPU_MAFBC_IRQ_DETILING_ERROR,
0319                    VPU_MAFBC_IRQ_MASK);
0320 
0321     meson_rdma_writel_sync(priv, VPU_MAFBC_S0_ENABLE,
0322                    VPU_MAFBC_SURFACE_CFG);
0323 
0324     meson_rdma_writel_sync(priv, VPU_MAFBC_DIRECT_SWAP,
0325                    VPU_MAFBC_COMMAND);
0326 
0327     /* This will enable the RDMA replaying the register writes on vsync */
0328     meson_rdma_flush(priv);
0329 
0330     return 0;
0331 }
0332 
0333 static int meson_g12a_afbcd_disable(struct meson_drm *priv)
0334 {
0335     writel_bits_relaxed(VPU_MAFBC_S0_ENABLE, 0,
0336                 priv->io_base + _REG(VPU_MAFBC_SURFACE_CFG));
0337 
0338     return 0;
0339 }
0340 
0341 static int meson_g12a_afbcd_setup(struct meson_drm *priv)
0342 {
0343     u32 format = meson_g12a_afbcd_pixel_fmt(priv->afbcd.modifier,
0344                         priv->afbcd.format);
0345 
0346     if (priv->afbcd.modifier & AFBC_FORMAT_MOD_YTR)
0347         format |= VPU_MAFBC_YUV_TRANSFORM;
0348 
0349     if (priv->afbcd.modifier & AFBC_FORMAT_MOD_SPLIT)
0350         format |= VPU_MAFBC_BLOCK_SPLIT;
0351 
0352     if (priv->afbcd.modifier & AFBC_FORMAT_MOD_TILED)
0353         format |= VPU_MAFBC_TILED_HEADER_EN;
0354 
0355     if ((priv->afbcd.modifier & AFBC_FORMAT_MOD_BLOCK_SIZE_MASK) ==
0356         AFBC_FORMAT_MOD_BLOCK_SIZE_32x8)
0357         format |= FIELD_PREP(VPU_MAFBC_SUPER_BLOCK_ASPECT, 1);
0358 
0359     meson_rdma_writel_sync(priv, format,
0360                    VPU_MAFBC_FORMAT_SPECIFIER_S0);
0361 
0362     meson_rdma_writel_sync(priv, priv->viu.osd1_addr,
0363                    VPU_MAFBC_HEADER_BUF_ADDR_LOW_S0);
0364     meson_rdma_writel_sync(priv, 0,
0365                    VPU_MAFBC_HEADER_BUF_ADDR_HIGH_S0);
0366 
0367     meson_rdma_writel_sync(priv, priv->viu.osd1_width,
0368                    VPU_MAFBC_BUFFER_WIDTH_S0);
0369     meson_rdma_writel_sync(priv, ALIGN(priv->viu.osd1_height, 32),
0370                    VPU_MAFBC_BUFFER_HEIGHT_S0);
0371 
0372     meson_rdma_writel_sync(priv, 0,
0373                    VPU_MAFBC_BOUNDING_BOX_X_START_S0);
0374     meson_rdma_writel_sync(priv, priv->viu.osd1_width - 1,
0375                    VPU_MAFBC_BOUNDING_BOX_X_END_S0);
0376     meson_rdma_writel_sync(priv, 0,
0377                    VPU_MAFBC_BOUNDING_BOX_Y_START_S0);
0378     meson_rdma_writel_sync(priv, priv->viu.osd1_height - 1,
0379                    VPU_MAFBC_BOUNDING_BOX_Y_END_S0);
0380 
0381     meson_rdma_writel_sync(priv, MESON_G12A_AFBCD_OUT_ADDR,
0382                    VPU_MAFBC_OUTPUT_BUF_ADDR_LOW_S0);
0383     meson_rdma_writel_sync(priv, 0,
0384                    VPU_MAFBC_OUTPUT_BUF_ADDR_HIGH_S0);
0385 
0386     meson_rdma_writel_sync(priv, priv->viu.osd1_width *
0387                    (meson_g12a_afbcd_bpp(priv->afbcd.format) / 8),
0388                    VPU_MAFBC_OUTPUT_BUF_STRIDE_S0);
0389 
0390     return 0;
0391 }
0392 
0393 struct meson_afbcd_ops meson_afbcd_g12a_ops = {
0394     .init = meson_g12a_afbcd_init,
0395     .exit = meson_g12a_afbcd_exit,
0396     .reset = meson_g12a_afbcd_reset,
0397     .enable = meson_g12a_afbcd_enable,
0398     .disable = meson_g12a_afbcd_disable,
0399     .setup = meson_g12a_afbcd_setup,
0400     .fmt_to_blk_mode = meson_g12a_afbcd_fmt_to_blk_mode,
0401     .supported_fmt = meson_g12a_afbcd_supported_fmt,
0402 };