meson_osd_afbcd.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (C) 2019 BayLibre, SAS
  4. * Author: Neil Armstrong <narmstrong@baylibre.com>
  5. */
  6. #include <linux/bitfield.h>
  7. #include <drm/drm_print.h>
  8. #include <drm/drm_fourcc.h>
  9. #include "meson_drv.h"
  10. #include "meson_registers.h"
  11. #include "meson_viu.h"
  12. #include "meson_rdma.h"
  13. #include "meson_osd_afbcd.h"
  14. /*
  15. * DOC: Driver for the ARM FrameBuffer Compression Decoders
  16. *
  17. * The Amlogic GXM and G12A SoC families embeds an AFBC Decoder,
  18. * to decode compressed buffers generated by the ARM Mali GPU.
  19. *
  20. * For the GXM Family, Amlogic designed their own Decoder, named in
  21. * the vendor source as "MESON_AFBC", and a single decoder is available
  22. * for the 2 OSD planes.
  23. * This decoder is compatible with the AFBC 1.0 specifications and the
  24. * Mali T820 GPU capabilities.
  25. * It supports :
  26. * - basic AFBC buffer for RGB32 only, thus YTR feature is mandatory
  27. * - SPARSE layout and SPLIT layout
  28. * - only 16x16 superblock
  29. *
  30. * The decoder reads the data from the SDRAM, decodes and sends the
  31. * decoded pixel stream to the OSD1 Plane pixel composer.
  32. *
  33. * For the G12A Family, Amlogic integrated an ARM AFBC Decoder, named
  34. * in the vendor source as "MALI_AFBC", and the decoder can decode up
  35. * to 4 surfaces, one for each of the 4 available OSDs.
  36. * This decoder is compatible with the AFBC 1.2 specifications for the
  37. * Mali G31 and G52 GPUs.
  38. * Is supports :
  39. * - basic AFBC buffer for multiple RGB and YUV pixel formats
  40. * - SPARSE layout and SPLIT layout
  41. * - 16x16 and 32x8 "wideblk" superblocks
  42. * - Tiled header
  43. *
  44. * The ARM AFBC Decoder independent from the VPU Pixel Pipeline, so
  45. * the ARM AFBC Decoder reads the data from the SDRAM then decodes
  46. * into a private internal physical address where the OSD1 Plane pixel
  47. * composer unpacks the decoded data.
  48. */
  49. /* Amlogic AFBC Decoder for GXM Family */
  50. #define OSD1_AFBCD_RGB32 0x15
  51. static int meson_gxm_afbcd_pixel_fmt(u64 modifier, uint32_t format)
  52. {
  53. switch (format) {
  54. case DRM_FORMAT_XBGR8888:
  55. case DRM_FORMAT_ABGR8888:
  56. return OSD1_AFBCD_RGB32;
  57. /* TOFIX support mode formats */
  58. default:
  59. DRM_DEBUG("unsupported afbc format[%08x]\n", format);
  60. return -EINVAL;
  61. }
  62. }
  63. static bool meson_gxm_afbcd_supported_fmt(u64 modifier, uint32_t format)
  64. {
  65. if (modifier & AFBC_FORMAT_MOD_BLOCK_SIZE_32x8)
  66. return false;
  67. if (!(modifier & AFBC_FORMAT_MOD_YTR))
  68. return false;
  69. return meson_gxm_afbcd_pixel_fmt(modifier, format) >= 0;
  70. }
  71. static int meson_gxm_afbcd_reset(struct meson_drm *priv)
  72. {
  73. writel_relaxed(VIU_SW_RESET_OSD1_AFBCD,
  74. priv->io_base + _REG(VIU_SW_RESET));
  75. writel_relaxed(0, priv->io_base + _REG(VIU_SW_RESET));
  76. return 0;
  77. }
  78. static int meson_gxm_afbcd_init(struct meson_drm *priv)
  79. {
  80. return 0;
  81. }
  82. static void meson_gxm_afbcd_exit(struct meson_drm *priv)
  83. {
  84. meson_gxm_afbcd_reset(priv);
  85. }
  86. static int meson_gxm_afbcd_enable(struct meson_drm *priv)
  87. {
  88. writel_relaxed(FIELD_PREP(OSD1_AFBCD_ID_FIFO_THRD, 0x40) |
  89. OSD1_AFBCD_DEC_ENABLE,
  90. priv->io_base + _REG(OSD1_AFBCD_ENABLE));
  91. return 0;
  92. }
  93. static int meson_gxm_afbcd_disable(struct meson_drm *priv)
  94. {
  95. writel_bits_relaxed(OSD1_AFBCD_DEC_ENABLE, 0,
  96. priv->io_base + _REG(OSD1_AFBCD_ENABLE));
  97. return 0;
  98. }
  99. static int meson_gxm_afbcd_setup(struct meson_drm *priv)
  100. {
  101. u32 conv_lbuf_len;
  102. u32 mode = FIELD_PREP(OSD1_AFBCD_MIF_URGENT, 3) |
  103. FIELD_PREP(OSD1_AFBCD_HOLD_LINE_NUM, 4) |
  104. FIELD_PREP(OSD1_AFBCD_RGBA_EXCHAN_CTRL, 0x34) |
  105. meson_gxm_afbcd_pixel_fmt(priv->afbcd.modifier,
  106. priv->afbcd.format);
  107. if (priv->afbcd.modifier & AFBC_FORMAT_MOD_SPARSE)
  108. mode |= OSD1_AFBCD_HREG_HALF_BLOCK;
  109. if (priv->afbcd.modifier & AFBC_FORMAT_MOD_SPLIT)
  110. mode |= OSD1_AFBCD_HREG_BLOCK_SPLIT;
  111. writel_relaxed(mode, priv->io_base + _REG(OSD1_AFBCD_MODE));
  112. writel_relaxed(FIELD_PREP(OSD1_AFBCD_HREG_VSIZE_IN,
  113. priv->viu.osd1_width) |
  114. FIELD_PREP(OSD1_AFBCD_HREG_HSIZE_IN,
  115. priv->viu.osd1_height),
  116. priv->io_base + _REG(OSD1_AFBCD_SIZE_IN));
  117. writel_relaxed(priv->viu.osd1_addr >> 4,
  118. priv->io_base + _REG(OSD1_AFBCD_HDR_PTR));
  119. writel_relaxed(priv->viu.osd1_addr >> 4,
  120. priv->io_base + _REG(OSD1_AFBCD_FRAME_PTR));
  121. /* TOFIX: bits 31:24 are not documented, nor the meaning of 0xe4 */
  122. writel_relaxed((0xe4 << 24) | (priv->viu.osd1_addr & 0xffffff),
  123. priv->io_base + _REG(OSD1_AFBCD_CHROMA_PTR));
  124. if (priv->viu.osd1_width <= 128)
  125. conv_lbuf_len = 32;
  126. else if (priv->viu.osd1_width <= 256)
  127. conv_lbuf_len = 64;
  128. else if (priv->viu.osd1_width <= 512)
  129. conv_lbuf_len = 128;
  130. else if (priv->viu.osd1_width <= 1024)
  131. conv_lbuf_len = 256;
  132. else if (priv->viu.osd1_width <= 2048)
  133. conv_lbuf_len = 512;
  134. else
  135. conv_lbuf_len = 1024;
  136. writel_relaxed(conv_lbuf_len,
  137. priv->io_base + _REG(OSD1_AFBCD_CONV_CTRL));
  138. writel_relaxed(FIELD_PREP(OSD1_AFBCD_DEC_PIXEL_BGN_H, 0) |
  139. FIELD_PREP(OSD1_AFBCD_DEC_PIXEL_END_H,
  140. priv->viu.osd1_width - 1),
  141. priv->io_base + _REG(OSD1_AFBCD_PIXEL_HSCOPE));
  142. writel_relaxed(FIELD_PREP(OSD1_AFBCD_DEC_PIXEL_BGN_V, 0) |
  143. FIELD_PREP(OSD1_AFBCD_DEC_PIXEL_END_V,
  144. priv->viu.osd1_height - 1),
  145. priv->io_base + _REG(OSD1_AFBCD_PIXEL_VSCOPE));
  146. return 0;
  147. }
  148. struct meson_afbcd_ops meson_afbcd_gxm_ops = {
  149. .init = meson_gxm_afbcd_init,
  150. .exit = meson_gxm_afbcd_exit,
  151. .reset = meson_gxm_afbcd_reset,
  152. .enable = meson_gxm_afbcd_enable,
  153. .disable = meson_gxm_afbcd_disable,
  154. .setup = meson_gxm_afbcd_setup,
  155. .supported_fmt = meson_gxm_afbcd_supported_fmt,
  156. };
  157. /* ARM AFBC Decoder for G12A Family */
  158. /* Amlogic G12A Mali AFBC Decoder supported formats */
  159. enum {
  160. MAFBC_FMT_RGB565 = 0,
  161. MAFBC_FMT_RGBA5551,
  162. MAFBC_FMT_RGBA1010102,
  163. MAFBC_FMT_YUV420_10B,
  164. MAFBC_FMT_RGB888,
  165. MAFBC_FMT_RGBA8888,
  166. MAFBC_FMT_RGBA4444,
  167. MAFBC_FMT_R8,
  168. MAFBC_FMT_RG88,
  169. MAFBC_FMT_YUV420_8B,
  170. MAFBC_FMT_YUV422_8B = 11,
  171. MAFBC_FMT_YUV422_10B = 14,
  172. };
  173. static int meson_g12a_afbcd_pixel_fmt(u64 modifier, uint32_t format)
  174. {
  175. switch (format) {
  176. case DRM_FORMAT_XRGB8888:
  177. case DRM_FORMAT_ARGB8888:
  178. /* YTR is forbidden for non XBGR formats */
  179. if (modifier & AFBC_FORMAT_MOD_YTR)
  180. return -EINVAL;
  181. fallthrough;
  182. case DRM_FORMAT_XBGR8888:
  183. case DRM_FORMAT_ABGR8888:
  184. return MAFBC_FMT_RGBA8888;
  185. case DRM_FORMAT_RGB888:
  186. /* YTR is forbidden for non XBGR formats */
  187. if (modifier & AFBC_FORMAT_MOD_YTR)
  188. return -EINVAL;
  189. return MAFBC_FMT_RGB888;
  190. case DRM_FORMAT_RGB565:
  191. /* YTR is forbidden for non XBGR formats */
  192. if (modifier & AFBC_FORMAT_MOD_YTR)
  193. return -EINVAL;
  194. return MAFBC_FMT_RGB565;
  195. /* TOFIX support mode formats */
  196. default:
  197. DRM_DEBUG("unsupported afbc format[%08x]\n", format);
  198. return -EINVAL;
  199. }
  200. }
  201. static int meson_g12a_afbcd_bpp(uint32_t format)
  202. {
  203. switch (format) {
  204. case DRM_FORMAT_XRGB8888:
  205. case DRM_FORMAT_ARGB8888:
  206. case DRM_FORMAT_XBGR8888:
  207. case DRM_FORMAT_ABGR8888:
  208. return 32;
  209. case DRM_FORMAT_RGB888:
  210. return 24;
  211. case DRM_FORMAT_RGB565:
  212. return 16;
  213. /* TOFIX support mode formats */
  214. default:
  215. DRM_ERROR("unsupported afbc format[%08x]\n", format);
  216. return 0;
  217. }
  218. }
  219. static int meson_g12a_afbcd_fmt_to_blk_mode(u64 modifier, uint32_t format)
  220. {
  221. switch (format) {
  222. case DRM_FORMAT_XRGB8888:
  223. case DRM_FORMAT_ARGB8888:
  224. case DRM_FORMAT_XBGR8888:
  225. case DRM_FORMAT_ABGR8888:
  226. return OSD_MALI_COLOR_MODE_RGBA8888;
  227. case DRM_FORMAT_RGB888:
  228. return OSD_MALI_COLOR_MODE_RGB888;
  229. case DRM_FORMAT_RGB565:
  230. return OSD_MALI_COLOR_MODE_RGB565;
  231. /* TOFIX support mode formats */
  232. default:
  233. DRM_DEBUG("unsupported afbc format[%08x]\n", format);
  234. return -EINVAL;
  235. }
  236. }
  237. static bool meson_g12a_afbcd_supported_fmt(u64 modifier, uint32_t format)
  238. {
  239. return meson_g12a_afbcd_pixel_fmt(modifier, format) >= 0;
  240. }
  241. static int meson_g12a_afbcd_reset(struct meson_drm *priv)
  242. {
  243. meson_rdma_reset(priv);
  244. meson_rdma_writel_sync(priv, VIU_SW_RESET_G12A_AFBC_ARB |
  245. VIU_SW_RESET_G12A_OSD1_AFBCD,
  246. VIU_SW_RESET);
  247. meson_rdma_writel_sync(priv, 0, VIU_SW_RESET);
  248. return 0;
  249. }
  250. static int meson_g12a_afbcd_init(struct meson_drm *priv)
  251. {
  252. int ret;
  253. ret = meson_rdma_init(priv);
  254. if (ret)
  255. return ret;
  256. meson_rdma_setup(priv);
  257. /* Handle AFBC Decoder reset manually */
  258. writel_bits_relaxed(MALI_AFBCD_MANUAL_RESET, MALI_AFBCD_MANUAL_RESET,
  259. priv->io_base + _REG(MALI_AFBCD_TOP_CTRL));
  260. return 0;
  261. }
  262. static void meson_g12a_afbcd_exit(struct meson_drm *priv)
  263. {
  264. meson_g12a_afbcd_reset(priv);
  265. meson_rdma_free(priv);
  266. }
  267. static int meson_g12a_afbcd_enable(struct meson_drm *priv)
  268. {
  269. meson_rdma_writel_sync(priv, VPU_MAFBC_IRQ_SURFACES_COMPLETED |
  270. VPU_MAFBC_IRQ_CONFIGURATION_SWAPPED |
  271. VPU_MAFBC_IRQ_DECODE_ERROR |
  272. VPU_MAFBC_IRQ_DETILING_ERROR,
  273. VPU_MAFBC_IRQ_MASK);
  274. meson_rdma_writel_sync(priv, VPU_MAFBC_S0_ENABLE,
  275. VPU_MAFBC_SURFACE_CFG);
  276. meson_rdma_writel_sync(priv, VPU_MAFBC_DIRECT_SWAP,
  277. VPU_MAFBC_COMMAND);
  278. /* This will enable the RDMA replaying the register writes on vsync */
  279. meson_rdma_flush(priv);
  280. return 0;
  281. }
  282. static int meson_g12a_afbcd_disable(struct meson_drm *priv)
  283. {
  284. writel_bits_relaxed(VPU_MAFBC_S0_ENABLE, 0,
  285. priv->io_base + _REG(VPU_MAFBC_SURFACE_CFG));
  286. return 0;
  287. }
  288. static int meson_g12a_afbcd_setup(struct meson_drm *priv)
  289. {
  290. u32 format = meson_g12a_afbcd_pixel_fmt(priv->afbcd.modifier,
  291. priv->afbcd.format);
  292. if (priv->afbcd.modifier & AFBC_FORMAT_MOD_YTR)
  293. format |= VPU_MAFBC_YUV_TRANSFORM;
  294. if (priv->afbcd.modifier & AFBC_FORMAT_MOD_SPLIT)
  295. format |= VPU_MAFBC_BLOCK_SPLIT;
  296. if (priv->afbcd.modifier & AFBC_FORMAT_MOD_TILED)
  297. format |= VPU_MAFBC_TILED_HEADER_EN;
  298. if ((priv->afbcd.modifier & AFBC_FORMAT_MOD_BLOCK_SIZE_MASK) ==
  299. AFBC_FORMAT_MOD_BLOCK_SIZE_32x8)
  300. format |= FIELD_PREP(VPU_MAFBC_SUPER_BLOCK_ASPECT, 1);
  301. meson_rdma_writel_sync(priv, format,
  302. VPU_MAFBC_FORMAT_SPECIFIER_S0);
  303. meson_rdma_writel_sync(priv, priv->viu.osd1_addr,
  304. VPU_MAFBC_HEADER_BUF_ADDR_LOW_S0);
  305. meson_rdma_writel_sync(priv, 0,
  306. VPU_MAFBC_HEADER_BUF_ADDR_HIGH_S0);
  307. meson_rdma_writel_sync(priv, priv->viu.osd1_width,
  308. VPU_MAFBC_BUFFER_WIDTH_S0);
  309. meson_rdma_writel_sync(priv, ALIGN(priv->viu.osd1_height, 32),
  310. VPU_MAFBC_BUFFER_HEIGHT_S0);
  311. meson_rdma_writel_sync(priv, 0,
  312. VPU_MAFBC_BOUNDING_BOX_X_START_S0);
  313. meson_rdma_writel_sync(priv, priv->viu.osd1_width - 1,
  314. VPU_MAFBC_BOUNDING_BOX_X_END_S0);
  315. meson_rdma_writel_sync(priv, 0,
  316. VPU_MAFBC_BOUNDING_BOX_Y_START_S0);
  317. meson_rdma_writel_sync(priv, priv->viu.osd1_height - 1,
  318. VPU_MAFBC_BOUNDING_BOX_Y_END_S0);
  319. meson_rdma_writel_sync(priv, MESON_G12A_AFBCD_OUT_ADDR,
  320. VPU_MAFBC_OUTPUT_BUF_ADDR_LOW_S0);
  321. meson_rdma_writel_sync(priv, 0,
  322. VPU_MAFBC_OUTPUT_BUF_ADDR_HIGH_S0);
  323. meson_rdma_writel_sync(priv, priv->viu.osd1_width *
  324. (meson_g12a_afbcd_bpp(priv->afbcd.format) / 8),
  325. VPU_MAFBC_OUTPUT_BUF_STRIDE_S0);
  326. return 0;
  327. }
  328. struct meson_afbcd_ops meson_afbcd_g12a_ops = {
  329. .init = meson_g12a_afbcd_init,
  330. .exit = meson_g12a_afbcd_exit,
  331. .reset = meson_g12a_afbcd_reset,
  332. .enable = meson_g12a_afbcd_enable,
  333. .disable = meson_g12a_afbcd_disable,
  334. .setup = meson_g12a_afbcd_setup,
  335. .fmt_to_blk_mode = meson_g12a_afbcd_fmt_to_blk_mode,
  336. .supported_fmt = meson_g12a_afbcd_supported_fmt,
  337. };