mali_dp.c 11 KB

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