mali_dp.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * (C) Copyright 2016-2018 ARM Ltd.
  4. * Author: Liviu Dudau <liviu.dudau@foss.arm.com>
  5. *
  6. */
  7. #define DEBUG
  8. #include <common.h>
  9. #include <video.h>
  10. #include <dm.h>
  11. #ifdef CONFIG_DISPLAY
  12. #include <display.h>
  13. #endif
  14. #include <fdtdec.h>
  15. #include <asm/io.h>
  16. #include <os.h>
  17. #include <fdt_support.h>
  18. #include <clk.h>
  19. #include <linux/sizes.h>
  20. #define MALIDP_CORE_ID 0x0018
  21. #define MALIDP_REG_BG_COLOR 0x0044
  22. #define MALIDP_LAYER_LV1 0x0100
  23. #define MALIDP_DC_STATUS 0xc000
  24. #define MALIDP_DC_CONTROL 0xc010
  25. #define MALIDP_DC_CFG_VALID 0xc014
  26. /* offsets inside the modesetting register block */
  27. #define MALIDP_H_INTERVALS 0x0000
  28. #define MALIDP_V_INTERVALS 0x0004
  29. #define MALIDP_SYNC_CONTROL 0x0008
  30. #define MALIDP_HV_ACTIVESIZE 0x000c
  31. #define MALIDP_OUTPUT_DEPTH 0x001c
  32. /* offsets inside the layer register block */
  33. #define MALIDP_LAYER_FORMAT 0x0000
  34. #define MALIDP_LAYER_CONTROL 0x0004
  35. #define MALIDP_LAYER_IN_SIZE 0x000c
  36. #define MALIDP_LAYER_CMP_SIZE 0x0010
  37. #define MALIDP_LAYER_STRIDE 0x0018
  38. #define MALIDP_LAYER_PTR_LOW 0x0024
  39. #define MALIDP_LAYER_PTR_HIGH 0x0028
  40. /* offsets inside the IRQ control blocks */
  41. #define MALIDP_REG_MASKIRQ 0x0008
  42. #define MALIDP_REG_CLEARIRQ 0x000c
  43. #define M1BITS 0x0001
  44. #define M2BITS 0x0003
  45. #define M4BITS 0x000f
  46. #define M8BITS 0x00ff
  47. #define M10BITS 0x03ff
  48. #define M12BITS 0x0fff
  49. #define M13BITS 0x1fff
  50. #define M16BITS 0xffff
  51. #define M17BITS 0x1ffff
  52. #define MALIDP_H_FRONTPORCH(x) (((x) & M12BITS) << 0)
  53. #define MALIDP_H_BACKPORCH(x) (((x) & M10BITS) << 16)
  54. #define MALIDP_V_FRONTPORCH(x) (((x) & M12BITS) << 0)
  55. #define MALIDP_V_BACKPORCH(x) (((x) & M8BITS) << 16)
  56. #define MALIDP_H_SYNCWIDTH(x) (((x) & M10BITS) << 0)
  57. #define MALIDP_V_SYNCWIDTH(x) (((x) & M8BITS) << 16)
  58. #define MALIDP_H_ACTIVE(x) (((x) & M13BITS) << 0)
  59. #define MALIDP_V_ACTIVE(x) (((x) & M13BITS) << 16)
  60. #define MALIDP_CMP_V_SIZE(x) (((x) & M13BITS) << 16)
  61. #define MALIDP_CMP_H_SIZE(x) (((x) & M13BITS) << 0)
  62. #define MALIDP_IN_V_SIZE(x) (((x) & M13BITS) << 16)
  63. #define MALIDP_IN_H_SIZE(x) (((x) & M13BITS) << 0)
  64. #define MALIDP_DC_CM_CONTROL(x) ((x) & M1BITS) << 16, 1 << 16
  65. #define MALIDP_DC_STATUS_GET_CM(reg) (((reg) >> 16) & M1BITS)
  66. #define MALIDP_FORMAT_ARGB8888 0x08
  67. #define MALIDP_DEFAULT_BG_R 0x0
  68. #define MALIDP_DEFAULT_BG_G 0x0
  69. #define MALIDP_DEFAULT_BG_B 0x0
  70. #define MALIDP_PRODUCT_ID(core_id) ((u32)(core_id) >> 16)
  71. #define MALIDP500 0x500
  72. DECLARE_GLOBAL_DATA_PTR;
  73. struct malidp_priv {
  74. phys_addr_t base_addr;
  75. phys_addr_t dc_status_addr;
  76. phys_addr_t dc_control_addr;
  77. phys_addr_t cval_addr;
  78. struct udevice *display; /* display device attached */
  79. struct clk aclk;
  80. struct clk pxlclk;
  81. u16 modeset_regs_offset;
  82. u8 config_bit_shift;
  83. u8 clear_irq; /* offset for IRQ clear register */
  84. };
  85. static const struct video_ops malidp_ops = {
  86. };
  87. static int malidp_get_hwid(phys_addr_t base_addr)
  88. {
  89. int hwid;
  90. /*
  91. * reading from the old CORE_ID offset will always
  92. * return 0x5000000 on DP500
  93. */
  94. hwid = readl(base_addr + MALIDP_CORE_ID);
  95. if (MALIDP_PRODUCT_ID(hwid) == MALIDP500)
  96. return hwid;
  97. /* otherwise try the other gen CORE_ID offset */
  98. hwid = readl(base_addr + MALIDP_DC_STATUS + MALIDP_CORE_ID);
  99. return hwid;
  100. }
  101. /*
  102. * wait for config mode bit setup to be acted upon by the hardware
  103. */
  104. static int malidp_wait_configdone(struct malidp_priv *malidp)
  105. {
  106. u32 status, tries = 300;
  107. while (tries--) {
  108. status = readl(malidp->dc_status_addr);
  109. if ((status >> malidp->config_bit_shift) & 1)
  110. break;
  111. udelay(500);
  112. }
  113. if (!tries)
  114. return -ETIMEDOUT;
  115. return 0;
  116. }
  117. /*
  118. * signal the hardware to enter configuration mode
  119. */
  120. static int malidp_enter_config(struct malidp_priv *malidp)
  121. {
  122. setbits_le32(malidp->dc_control_addr, 1 << malidp->config_bit_shift);
  123. return malidp_wait_configdone(malidp);
  124. }
  125. /*
  126. * signal the hardware to exit configuration mode
  127. */
  128. static int malidp_leave_config(struct malidp_priv *malidp)
  129. {
  130. clrbits_le32(malidp->dc_control_addr, 1 << malidp->config_bit_shift);
  131. return malidp_wait_configdone(malidp);
  132. }
  133. static void malidp_setup_timings(struct malidp_priv *malidp,
  134. struct display_timing *timings)
  135. {
  136. u32 val = MALIDP_H_SYNCWIDTH(timings->hsync_len.typ) |
  137. MALIDP_V_SYNCWIDTH(timings->vsync_len.typ);
  138. writel(val, malidp->base_addr + malidp->modeset_regs_offset +
  139. MALIDP_SYNC_CONTROL);
  140. val = MALIDP_H_BACKPORCH(timings->hback_porch.typ) |
  141. MALIDP_H_FRONTPORCH(timings->hfront_porch.typ);
  142. writel(val, malidp->base_addr + malidp->modeset_regs_offset +
  143. MALIDP_H_INTERVALS);
  144. val = MALIDP_V_BACKPORCH(timings->vback_porch.typ) |
  145. MALIDP_V_FRONTPORCH(timings->vfront_porch.typ);
  146. writel(val, malidp->base_addr + malidp->modeset_regs_offset +
  147. MALIDP_V_INTERVALS);
  148. val = MALIDP_H_ACTIVE(timings->hactive.typ) |
  149. MALIDP_V_ACTIVE(timings->vactive.typ);
  150. writel(val, malidp->base_addr + malidp->modeset_regs_offset +
  151. MALIDP_HV_ACTIVESIZE);
  152. /* default output bit-depth per colour is 8 bits */
  153. writel(0x080808, malidp->base_addr + malidp->modeset_regs_offset +
  154. MALIDP_OUTPUT_DEPTH);
  155. }
  156. static int malidp_setup_mode(struct malidp_priv *malidp,
  157. struct display_timing *timings)
  158. {
  159. int err;
  160. if (clk_set_rate(&malidp->pxlclk, timings->pixelclock.typ) == 0)
  161. return -EIO;
  162. malidp_setup_timings(malidp, timings);
  163. err = display_enable(malidp->display, 8, timings);
  164. if (err)
  165. printf("display_enable failed with %d\n", err);
  166. return err;
  167. }
  168. static void malidp_setup_layer(struct malidp_priv *malidp,
  169. struct display_timing *timings,
  170. u32 layer_offset, phys_addr_t fb_addr)
  171. {
  172. u32 val;
  173. /* setup the base layer's pixel format to A8R8G8B8 */
  174. writel(MALIDP_FORMAT_ARGB8888, malidp->base_addr + layer_offset +
  175. MALIDP_LAYER_FORMAT);
  176. /* setup layer composition size */
  177. val = MALIDP_CMP_V_SIZE(timings->vactive.typ) |
  178. MALIDP_CMP_H_SIZE(timings->hactive.typ);
  179. writel(val, malidp->base_addr + layer_offset +
  180. MALIDP_LAYER_CMP_SIZE);
  181. /* setup layer input size */
  182. val = MALIDP_IN_V_SIZE(timings->vactive.typ) |
  183. MALIDP_IN_H_SIZE(timings->hactive.typ);
  184. writel(val, malidp->base_addr + layer_offset + MALIDP_LAYER_IN_SIZE);
  185. /* setup layer stride in bytes */
  186. writel(timings->hactive.typ << 2, malidp->base_addr + layer_offset +
  187. MALIDP_LAYER_STRIDE);
  188. /* set framebuffer address */
  189. writel(lower_32_bits(fb_addr), malidp->base_addr + layer_offset +
  190. MALIDP_LAYER_PTR_LOW);
  191. writel(upper_32_bits(fb_addr), malidp->base_addr + layer_offset +
  192. MALIDP_LAYER_PTR_HIGH);
  193. /* enable layer */
  194. setbits_le32(malidp->base_addr + layer_offset +
  195. MALIDP_LAYER_CONTROL, 1);
  196. }
  197. static void malidp_set_configvalid(struct malidp_priv *malidp)
  198. {
  199. setbits_le32(malidp->cval_addr, 1);
  200. }
  201. static int malidp_update_timings_from_edid(struct udevice *dev,
  202. struct display_timing *timings)
  203. {
  204. #ifdef CONFIG_DISPLAY
  205. struct malidp_priv *priv = dev_get_priv(dev);
  206. struct udevice *disp_dev;
  207. int err;
  208. err = uclass_first_device(UCLASS_DISPLAY, &disp_dev);
  209. if (err)
  210. return err;
  211. priv->display = disp_dev;
  212. err = display_read_timing(disp_dev, timings);
  213. if (err)
  214. return err;
  215. #endif
  216. return 0;
  217. }
  218. static int malidp_probe(struct udevice *dev)
  219. {
  220. struct video_priv *uc_priv = dev_get_uclass_priv(dev);
  221. struct video_uc_platdata *uc_plat = dev_get_uclass_platdata(dev);
  222. ofnode framebuffer = ofnode_find_subnode(dev_ofnode(dev), "framebuffer");
  223. struct malidp_priv *priv = dev_get_priv(dev);
  224. struct display_timing timings;
  225. phys_addr_t fb_base, fb_size;
  226. const char *format;
  227. u32 value;
  228. int err;
  229. if (!ofnode_valid(framebuffer))
  230. return -EINVAL;
  231. err = clk_get_by_name(dev, "pxlclk", &priv->pxlclk);
  232. if (err) {
  233. dev_err(dev, "failed to get pixel clock\n");
  234. return err;
  235. }
  236. err = clk_get_by_name(dev, "aclk", &priv->aclk);
  237. if (err) {
  238. dev_err(dev, "failed to get AXI clock\n");
  239. goto fail_aclk;
  240. }
  241. err = ofnode_decode_display_timing(dev_ofnode(dev), 1, &timings);
  242. if (err) {
  243. dev_err(dev, "failed to get any display timings\n");
  244. goto fail_timings;
  245. }
  246. err = malidp_update_timings_from_edid(dev, &timings);
  247. if (err) {
  248. printf("malidp_update_timings_from_edid failed: %d\n", err);
  249. goto fail_timings;
  250. }
  251. fb_base = ofnode_get_addr_size(framebuffer, "reg", &fb_size);
  252. if (fb_base != FDT_ADDR_T_NONE) {
  253. uc_plat->base = fb_base;
  254. uc_plat->size = fb_size;
  255. } else {
  256. printf("cannot get address size for framebuffer\n");
  257. }
  258. err = ofnode_read_u32(framebuffer, "width", &value);
  259. if (err)
  260. goto fail_timings;
  261. uc_priv->xsize = (ushort)value;
  262. err = ofnode_read_u32(framebuffer, "height", &value);
  263. if (err)
  264. goto fail_timings;
  265. uc_priv->ysize = (ushort)value;
  266. format = ofnode_read_string(framebuffer, "format");
  267. if (!format) {
  268. err = -EINVAL;
  269. goto fail_timings;
  270. } else if (!strncmp(format, "a8r8g8b8", 8)) {
  271. uc_priv->bpix = VIDEO_BPP32;
  272. }
  273. uc_priv->rot = 0;
  274. priv->base_addr = (phys_addr_t)dev_read_addr(dev);
  275. clk_enable(&priv->pxlclk);
  276. clk_enable(&priv->aclk);
  277. value = malidp_get_hwid(priv->base_addr);
  278. printf("Display: Arm Mali DP%3x r%dp%d\n", MALIDP_PRODUCT_ID(value),
  279. (value >> 12) & 0xf, (value >> 8) & 0xf);
  280. if (MALIDP_PRODUCT_ID(value) == MALIDP500) {
  281. /* DP500 is special */
  282. priv->modeset_regs_offset = 0x28;
  283. priv->dc_status_addr = priv->base_addr;
  284. priv->dc_control_addr = priv->base_addr + 0xc;
  285. priv->cval_addr = priv->base_addr + 0xf00;
  286. priv->config_bit_shift = 17;
  287. priv->clear_irq = 0;
  288. } else {
  289. priv->modeset_regs_offset = 0x30;
  290. priv->dc_status_addr = priv->base_addr + MALIDP_DC_STATUS;
  291. priv->dc_control_addr = priv->base_addr + MALIDP_DC_CONTROL;
  292. priv->cval_addr = priv->base_addr + MALIDP_DC_CFG_VALID;
  293. priv->config_bit_shift = 16;
  294. priv->clear_irq = MALIDP_REG_CLEARIRQ;
  295. }
  296. /* enter config mode */
  297. err = malidp_enter_config(priv);
  298. if (err)
  299. return err;
  300. /* disable interrupts */
  301. writel(0, priv->dc_status_addr + MALIDP_REG_MASKIRQ);
  302. writel(0xffffffff, priv->dc_status_addr + priv->clear_irq);
  303. err = malidp_setup_mode(priv, &timings);
  304. if (err)
  305. goto fail_timings;
  306. malidp_setup_layer(priv, &timings, MALIDP_LAYER_LV1,
  307. (phys_addr_t)uc_plat->base);
  308. err = malidp_leave_config(priv);
  309. if (err)
  310. goto fail_timings;
  311. malidp_set_configvalid(priv);
  312. return 0;
  313. fail_timings:
  314. clk_free(&priv->aclk);
  315. fail_aclk:
  316. clk_free(&priv->pxlclk);
  317. return err;
  318. }
  319. static int malidp_bind(struct udevice *dev)
  320. {
  321. struct video_uc_platdata *uc_plat = dev_get_uclass_platdata(dev);
  322. /* choose max possible size: 2K x 2K, XRGB888 framebuffer */
  323. uc_plat->size = 4 * 2048 * 2048;
  324. return 0;
  325. }
  326. static const struct udevice_id malidp_ids[] = {
  327. { .compatible = "arm,mali-dp500" },
  328. { .compatible = "arm,mali-dp550" },
  329. { .compatible = "arm,mali-dp650" },
  330. { }
  331. };
  332. U_BOOT_DRIVER(mali_dp) = {
  333. .name = "mali_dp",
  334. .id = UCLASS_VIDEO,
  335. .of_match = malidp_ids,
  336. .bind = malidp_bind,
  337. .probe = malidp_probe,
  338. .priv_auto_alloc_size = sizeof(struct malidp_priv),
  339. .ops = &malidp_ops,
  340. };