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_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 91 static int meson_gxm_afbcd_init(struct meson_drm *priv) 92 { 93 return 0; 94 } 95 96 static void meson_gxm_afbcd_exit(struct meson_drm *priv) 97 { 98 meson_gxm_afbcd_reset(priv); 99 } 100 101 static 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 110 static 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 118 static 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 178 struct 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 */ 191 enum { 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 206 static 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 235 static 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 254 static 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 273 static bool meson_g12a_afbcd_supported_fmt(u64 modifier, uint32_t format) 274 { 275 return meson_g12a_afbcd_pixel_fmt(modifier, format) >= 0; 276 } 277 278 static 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 290 static 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 307 static void meson_g12a_afbcd_exit(struct meson_drm *priv) 308 { 309 meson_g12a_afbcd_reset(priv); 310 meson_rdma_free(priv); 311 } 312 313 static 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 333 static 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 341 static 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 393 struct 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