mali_dp.c 11 KB

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