mcde_simple.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /* Copyright (C) 2019 Stephan Gerhold */
  3. #include <common.h>
  4. #include <dm.h>
  5. #include <log.h>
  6. #include <video.h>
  7. #include <asm/io.h>
  8. #include <linux/bitfield.h>
  9. #include <linux/iopoll.h>
  10. #define MCDE_EXTSRC0A0 0x200
  11. #define MCDE_EXTSRC0CONF 0x20C
  12. #define MCDE_EXTSRC0CONF_BPP GENMASK(11, 8)
  13. #define MCDE_OVL0CONF 0x404
  14. #define MCDE_OVL0CONF_PPL GENMASK(10, 0)
  15. #define MCDE_OVL0CONF_LPF GENMASK(26, 16)
  16. #define MCDE_CHNL0SYNCHMOD 0x608
  17. #define MCDE_CHNL0SYNCHMOD_SRC_SYNCH GENMASK(1, 0)
  18. #define MCDE_CHNL0SYNCHSW 0x60C
  19. #define MCDE_CHNL0SYNCHSW_SW_TRIG BIT(0)
  20. #define MCDE_CRA0 0x800
  21. #define MCDE_CRA0_FLOEN BIT(0)
  22. #define MCDE_FLOW_COMPLETION_TIMEOUT 200000 /* us */
  23. enum mcde_bpp {
  24. MCDE_EXTSRC0CONF_BPP_1BPP_PAL,
  25. MCDE_EXTSRC0CONF_BPP_2BPP_PAL,
  26. MCDE_EXTSRC0CONF_BPP_4BPP_PAL,
  27. MCDE_EXTSRC0CONF_BPP_8BPP_PAL,
  28. MCDE_EXTSRC0CONF_BPP_RGB444,
  29. MCDE_EXTSRC0CONF_BPP_ARGB4444,
  30. MCDE_EXTSRC0CONF_BPP_IRGB1555,
  31. MCDE_EXTSRC0CONF_BPP_RGB565,
  32. MCDE_EXTSRC0CONF_BPP_RGB888,
  33. MCDE_EXTSRC0CONF_BPP_XRGB8888,
  34. MCDE_EXTSRC0CONF_BPP_ARGB8888,
  35. MCDE_EXTSRC0CONF_BPP_YCBCR422,
  36. };
  37. enum mcde_src_synch {
  38. MCDE_CHNL0SYNCHMOD_SRC_SYNCH_HARDWARE,
  39. MCDE_CHNL0SYNCHMOD_SRC_SYNCH_NO_SYNCH,
  40. MCDE_CHNL0SYNCHMOD_SRC_SYNCH_SOFTWARE,
  41. };
  42. struct mcde_simple_priv {
  43. fdt_addr_t base;
  44. enum mcde_src_synch src_synch;
  45. };
  46. static int mcde_simple_probe(struct udevice *dev)
  47. {
  48. struct mcde_simple_priv *priv = dev_get_priv(dev);
  49. struct video_uc_plat *plat = dev_get_uclass_plat(dev);
  50. struct video_priv *uc_priv = dev_get_uclass_priv(dev);
  51. u32 val;
  52. priv->base = dev_read_addr(dev);
  53. if (priv->base == FDT_ADDR_T_NONE)
  54. return -EINVAL;
  55. plat->base = readl(priv->base + MCDE_EXTSRC0A0);
  56. if (!plat->base)
  57. return -ENODEV;
  58. val = readl(priv->base + MCDE_OVL0CONF);
  59. uc_priv->xsize = FIELD_GET(MCDE_OVL0CONF_PPL, val);
  60. uc_priv->ysize = FIELD_GET(MCDE_OVL0CONF_LPF, val);
  61. uc_priv->rot = 0;
  62. val = readl(priv->base + MCDE_EXTSRC0CONF);
  63. switch (FIELD_GET(MCDE_EXTSRC0CONF_BPP, val)) {
  64. case MCDE_EXTSRC0CONF_BPP_RGB565:
  65. uc_priv->bpix = VIDEO_BPP16;
  66. break;
  67. case MCDE_EXTSRC0CONF_BPP_XRGB8888:
  68. case MCDE_EXTSRC0CONF_BPP_ARGB8888:
  69. uc_priv->bpix = VIDEO_BPP32;
  70. break;
  71. default:
  72. printf("unsupported format: %#x\n", val);
  73. return -EINVAL;
  74. }
  75. val = readl(priv->base + MCDE_CHNL0SYNCHMOD);
  76. priv->src_synch = FIELD_GET(MCDE_CHNL0SYNCHMOD_SRC_SYNCH, val);
  77. plat->size = uc_priv->xsize * uc_priv->ysize * VNBYTES(uc_priv->bpix);
  78. debug("MCDE base: %#lx, xsize: %d, ysize: %d, bpp: %d\n",
  79. plat->base, uc_priv->xsize, uc_priv->ysize, VNBITS(uc_priv->bpix));
  80. video_set_flush_dcache(dev, true);
  81. return 0;
  82. }
  83. static int mcde_simple_video_sync(struct udevice *dev)
  84. {
  85. struct mcde_simple_priv *priv = dev_get_priv(dev);
  86. unsigned int val;
  87. if (priv->src_synch != MCDE_CHNL0SYNCHMOD_SRC_SYNCH_SOFTWARE)
  88. return 0;
  89. /* Enable flow */
  90. val = readl(priv->base + MCDE_CRA0);
  91. val |= MCDE_CRA0_FLOEN;
  92. writel(val, priv->base + MCDE_CRA0);
  93. /* Trigger a software sync */
  94. writel(MCDE_CHNL0SYNCHSW_SW_TRIG, priv->base + MCDE_CHNL0SYNCHSW);
  95. /* Disable flow */
  96. val = readl(priv->base + MCDE_CRA0);
  97. val &= ~MCDE_CRA0_FLOEN;
  98. writel(val, priv->base + MCDE_CRA0);
  99. /* Wait for completion */
  100. return readl_poll_timeout(priv->base + MCDE_CRA0, val,
  101. !(val & MCDE_CRA0_FLOEN),
  102. MCDE_FLOW_COMPLETION_TIMEOUT);
  103. }
  104. static struct video_ops mcde_simple_ops = {
  105. .video_sync = mcde_simple_video_sync,
  106. };
  107. static const struct udevice_id mcde_simple_ids[] = {
  108. { .compatible = "ste,mcde" },
  109. { }
  110. };
  111. U_BOOT_DRIVER(mcde_simple) = {
  112. .name = "mcde_simple",
  113. .id = UCLASS_VIDEO,
  114. .ops = &mcde_simple_ops,
  115. .of_match = mcde_simple_ids,
  116. .probe = mcde_simple_probe,
  117. .priv_auto = sizeof(struct mcde_simple_priv),
  118. };