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