mipi_dsi_host.c 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  1. /*
  2. * Copyright 2016-2019 NXP
  3. *
  4. * SPDX-License-Identifier: GPL-2.0+
  5. */
  6. #include <asm/io.h>
  7. #include <common.h>
  8. #include <div64.h>
  9. #include <dm.h>
  10. #include <dm/device-internal.h>
  11. #include <dsi_host.h>
  12. #include <linux/err.h>
  13. #include <linux/string.h>
  14. #include <malloc.h>
  15. #include <panel.h>
  16. #include <regmap.h>
  17. #include <syscon.h>
  18. #include <video_bridge.h>
  19. #include "sf_mipi.h"
  20. #include "mipi_dsi_northwest_regs.h"
  21. #define MIPI_LCD_SLEEP_MODE_DELAY (120)
  22. #define MIPI_FIFO_TIMEOUT 250000 /* 250ms */
  23. #define PS2KHZ(ps) (1000000000UL / (ps))
  24. #define MSEC_PER_SEC 1000
  25. #define DIV_ROUND_CLOSEST_ULL(x, divisor)( \
  26. { \
  27. typeof(divisor) __d = divisor; \
  28. unsigned long long _tmp = (x) + (__d) / 2; \
  29. do_div(_tmp, __d); \
  30. _tmp; \
  31. } \
  32. )
  33. enum mipi_dsi_mode {
  34. DSI_COMMAND_MODE,
  35. DSI_VIDEO_MODE
  36. };
  37. #define DSI_LP_MODE 0
  38. #define DSI_HS_MODE 1
  39. enum mipi_dsi_payload {
  40. DSI_PAYLOAD_CMD,
  41. DSI_PAYLOAD_VIDEO,
  42. };
  43. /*
  44. * mipi-dsi northwest driver information structure, holds useful data for the driver.
  45. */
  46. struct mipi_dsi_northwest_info {
  47. void __iomem *dsi_base;
  48. void __iomem *phy_base;
  49. void __iomem *mmio_base;
  50. struct mipi_dsi_device *device;
  51. struct mipi_dsi_host dsi_host;
  52. struct display_timing timings;
  53. struct regmap *sim;
  54. const struct mipi_dsi_phy_ops *phy_ops;
  55. uint32_t max_data_lanes;
  56. uint32_t max_data_rate;
  57. uint32_t pll_ref;
  58. bool link_initialized;
  59. };
  60. static void cdns_dsi_init_link(struct mipi_dsi_northwest_info *mipi_dsi, struct mipi_dsi_device *device)
  61. {
  62. unsigned long ulpout;
  63. u32 val;
  64. int i;
  65. struct udevice *dev = device->dev;
  66. struct dsi_sf_priv *priv = dev_get_priv(dev);
  67. if (mipi_dsi->link_initialized)
  68. return;
  69. val = WAIT_BURST_TIME(0xf);
  70. for (i = 1; i < mipi_dsi->max_data_lanes; i++)
  71. val |= DATA_LANE_EN(i);
  72. debug("%s,device->mode_flags = 0x%ld,mipi_dsi->max_data_lanes = %d\n", __func__,device->mode_flags,mipi_dsi->max_data_lanes);
  73. if (!(device->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS))
  74. val |= CLK_CONTINUOUS;
  75. writel(val, mipi_dsi->dsi_base + MCTL_MAIN_PHY_CTL);
  76. ulpout = DIV_ROUND_UP(clk_get_rate(&priv->dsi_sys_clk), MSEC_PER_SEC);
  77. debug("%s ulpout: 0x%ld\n", __func__, ulpout);
  78. writel(CLK_LANE_ULPOUT_TIME(ulpout) | DATA_LANE_ULPOUT_TIME(ulpout),
  79. mipi_dsi->dsi_base + MCTL_ULPOUT_TIME);
  80. writel(LINK_EN, mipi_dsi->dsi_base + MCTL_MAIN_DATA_CTL);
  81. val = CLK_LANE_EN | PLL_START ; // | PLL_START; unused bit
  82. for (i = 0; i < mipi_dsi->max_data_lanes; i++)
  83. val |= DATA_LANE_START(i);
  84. writel(val, mipi_dsi->dsi_base + MCTL_MAIN_EN);
  85. udelay(20);
  86. mipi_dsi->link_initialized = true;
  87. }
  88. static inline struct mipi_dsi_northwest_info *host_to_dsi(struct mipi_dsi_host *host)
  89. {
  90. return container_of(host, struct mipi_dsi_northwest_info, dsi_host);
  91. }
  92. static int mipi_dsi_northwest_host_attach(struct mipi_dsi_host *host,
  93. struct mipi_dsi_device *device)
  94. {
  95. return 0;
  96. }
  97. static int wait_for_send_done(struct mipi_dsi_northwest_info *mipi_dsi, unsigned long timeout)
  98. {
  99. uint32_t irq_status;
  100. uint32_t ctl;
  101. do {
  102. irq_status = readl(mipi_dsi->dsi_base + DIRECT_CMD_STS_FLAG);
  103. if (irq_status)
  104. {
  105. ctl = readl(mipi_dsi->dsi_base + DIRECT_CMD_STS_CTL);
  106. ctl &= ~irq_status;
  107. writel(ctl, mipi_dsi->dsi_base + DIRECT_CMD_STS_CTL);
  108. return timeout;
  109. }
  110. udelay(1);
  111. } while (--timeout);
  112. return 0;
  113. }
  114. static ssize_t cdns_dsi_transfer(struct mipi_dsi_host *host,
  115. const struct mipi_dsi_msg *msg)
  116. {
  117. struct mipi_dsi_northwest_info *dsi = host_to_dsi(host);
  118. u32 cmd, sts, val, wait = WRITE_COMPLETED, ctl = 0;
  119. struct mipi_dsi_packet packet;
  120. int ret, i, tx_len, rx_len;
  121. struct udevice *dev = dsi->device->dev;
  122. struct dsi_sf_priv *priv = dev_get_priv(dev);
  123. cdns_dsi_init_link(dsi, dsi->device);
  124. ret = mipi_dsi_create_packet(&packet, msg);
  125. if (ret)
  126. goto out;
  127. tx_len = msg->tx_buf ? msg->tx_len : 0;
  128. rx_len = msg->rx_buf ? msg->rx_len : 0;
  129. /* For read operations, the maximum TX len is 2. */
  130. if (rx_len && tx_len > 2) {
  131. ret = -ENOTSUPP;
  132. goto out;
  133. }
  134. /* TX len is limited by the CMD FIFO depth. */
  135. if (tx_len > priv->direct_cmd_fifo_depth) {
  136. ret = -ENOTSUPP;
  137. goto out;
  138. }
  139. /* RX len is limited by the RX FIFO depth. */
  140. if (rx_len > priv->rx_fifo_depth) {
  141. ret = -ENOTSUPP;
  142. goto out;
  143. }
  144. cmd = CMD_SIZE(tx_len) | CMD_VCHAN_ID(msg->channel) |
  145. CMD_DATATYPE(msg->type);
  146. if (msg->flags & MIPI_DSI_MSG_USE_LPM)
  147. cmd |= CMD_LP_EN;
  148. if (mipi_dsi_packet_format_is_long(msg->type))
  149. cmd |= CMD_LONG;
  150. if (rx_len) {
  151. cmd |= READ_CMD;
  152. wait = READ_COMPLETED_WITH_ERR | READ_COMPLETED;
  153. ctl = READ_EN | BTA_EN;
  154. } else if (msg->flags & MIPI_DSI_MSG_REQ_ACK) {
  155. cmd |= BTA_REQ;
  156. wait = ACK_WITH_ERR_RCVD | ACK_RCVD;
  157. ctl = BTA_EN;
  158. }
  159. udelay(10);
  160. writel(readl(dsi->dsi_base + MCTL_MAIN_DATA_CTL) | ctl,
  161. dsi->dsi_base + MCTL_MAIN_DATA_CTL);
  162. writel(cmd, dsi->dsi_base + DIRECT_CMD_MAIN_SETTINGS);
  163. for (i = 0; i < tx_len; i += 4) {
  164. const u8 *buf = msg->tx_buf;
  165. int j;
  166. val = 0;
  167. for (j = 0; j < 4 && j + i < tx_len; j++)
  168. val |= (u32)buf[i + j] << (8 * j);
  169. writel(val, dsi->dsi_base + DIRECT_CMD_WRDATA);
  170. }
  171. /* Clear status flags before sending the command. */
  172. writel(wait, dsi->dsi_base + DIRECT_CMD_STS_CLR);
  173. writel(wait, dsi->dsi_base + DIRECT_CMD_STS_CTL);
  174. writel(0, dsi->dsi_base + DIRECT_CMD_SEND);
  175. ret = wait_for_send_done(dsi, MIPI_FIFO_TIMEOUT);
  176. if (!ret) {
  177. debug("wait tx done timeout!\n");
  178. return -ETIMEDOUT;
  179. }
  180. udelay(10);
  181. sts = readl(dsi->dsi_base + DIRECT_CMD_STS);
  182. writel(wait, dsi->dsi_base + DIRECT_CMD_STS_CLR);
  183. writel(0, dsi->dsi_base + DIRECT_CMD_STS_CTL);
  184. writel(readl(dsi->dsi_base + MCTL_MAIN_DATA_CTL) & ~ctl,
  185. dsi->dsi_base + MCTL_MAIN_DATA_CTL);
  186. /* We did not receive the events we were waiting for. */
  187. if (!(sts & wait)) {
  188. ret = -ETIMEDOUT;
  189. goto out;
  190. }
  191. /* 'READ' or 'WRITE with ACK' failed. */
  192. if (sts & (READ_COMPLETED_WITH_ERR | ACK_WITH_ERR_RCVD)) {
  193. ret = -EIO;
  194. goto out;
  195. }
  196. for (i = 0; i < rx_len; i += 4) {
  197. u8 *buf = msg->rx_buf;
  198. int j;
  199. val = readl(dsi->dsi_base + DIRECT_CMD_RDDATA);
  200. for (j = 0; j < 4 && j + i < rx_len; j++)
  201. buf[i + j] = val >> (8 * j);
  202. }
  203. out:
  204. return ret;
  205. }
  206. static const struct mipi_dsi_host_ops mipi_dsi_northwest_host_ops = {
  207. .attach = mipi_dsi_northwest_host_attach,
  208. .transfer = cdns_dsi_transfer,
  209. };
  210. static int mipi_dsi_northwest_init(struct udevice *dev,
  211. struct mipi_dsi_device *device,
  212. struct display_timing *timings,
  213. unsigned int max_data_lanes,
  214. const struct mipi_dsi_phy_ops *phy_ops)
  215. {
  216. struct mipi_dsi_northwest_info *priv = dev_get_priv(dev);
  217. if (!phy_ops->init || !phy_ops->get_lane_mbps ||
  218. !phy_ops->post_set_mode)
  219. return -5;
  220. priv->max_data_lanes = max_data_lanes;
  221. priv->device = device;
  222. priv->dsi_host.ops = &mipi_dsi_northwest_host_ops;
  223. device->host = &priv->dsi_host;
  224. priv->timings = *timings;
  225. priv->phy_ops = phy_ops;
  226. priv->dsi_base = (void *)dev_read_addr_name(device->dev, "dsi");
  227. priv->phy_base = (void *)dev_read_addr_name(device->dev, "phy");
  228. if ((fdt_addr_t)priv->dsi_base == FDT_ADDR_T_NONE || (fdt_addr_t)priv->phy_base == FDT_ADDR_T_NONE) {
  229. debug("dsi dt register address error\n");
  230. return -EINVAL;
  231. }
  232. priv->link_initialized = false;
  233. return 0;
  234. }
  235. static int mipi_dsi_enable(struct udevice *dev)
  236. {
  237. struct mipi_dsi_northwest_info *priv = dev_get_priv(dev);
  238. priv->phy_ops->init(priv->device);
  239. priv->phy_ops->post_set_mode(priv->device, MIPI_DSI_MODE_VIDEO);
  240. cdns_dsi_init_link(priv, priv->device);
  241. debug("priv->timings.hactive.typ %d----\n",priv->timings.hactive.typ);
  242. debug("priv->timings.vactive.typ %d----\n",priv->timings.vactive.typ);
  243. if (priv->timings.hactive.typ == 800)
  244. {
  245. writel(0x00670067, priv->dsi_base + 0x000000c0);
  246. writel(0x00cb0960, priv->dsi_base + 0x000000c4);
  247. writel(0x0003b145, priv->dsi_base + 0x000000b4);
  248. writel(0x000001e0, priv->dsi_base + 0x000000b8);
  249. writel(0x00000a9e, priv->dsi_base + 0x000000d0);
  250. writel(0x0a980000, priv->dsi_base + 0x000000f8);
  251. writel(0x00000b0f, priv->dsi_base + 0x000000cc);
  252. writel(0x7c3c0aae, priv->dsi_base + 0x000000dc);
  253. writel(0x0032dcd3, priv->dsi_base + 0x00000014);
  254. writel(0x00032dcd, priv->dsi_base + 0x00000018);
  255. writel(0x80b8fe00, priv->dsi_base + 0x000000b0);
  256. writel(0x00020027, priv->dsi_base + 0x00000004);
  257. writel(0x00004018, priv->dsi_base + 0x0000000c);
  258. }else if (priv->timings.hactive.typ == 1920){
  259. writel(0x01d30081, priv->dsi_base + 0x000000c0);
  260. writel(0x01171680, priv->dsi_base + 0x000000c4);
  261. writel(0x00003905, priv->dsi_base + 0x000000b4);
  262. writel(0x00000438, priv->dsi_base + 0x000000b8);
  263. writel(0x00001976, priv->dsi_base + 0x000000d0);
  264. writel(0x19700000, priv->dsi_base + 0x000000f8);
  265. writel(0x00001a01, priv->dsi_base + 0x000000cc);
  266. writel(0x98900661, priv->dsi_base + 0x000000dc);
  267. writel(0x003f9403, priv->dsi_base + 0x00000014);
  268. writel(0x0003f940, priv->dsi_base + 0x00000018);
  269. writel(0x80b8fe00, priv->dsi_base + 0x000000b0);
  270. writel(0x00020027, priv->dsi_base + 0x00000004);
  271. writel(0x000040f8, priv->dsi_base + 0x0000000c);
  272. }
  273. return 0;
  274. }
  275. static int mipi_dsi_northwest_disable(struct udevice *dev)
  276. {
  277. return 0;
  278. }
  279. struct dsi_host_ops mipi_dsi_northwest_ops = {
  280. .init = mipi_dsi_northwest_init,
  281. .enable = mipi_dsi_enable,
  282. .disable = mipi_dsi_northwest_disable,
  283. };
  284. static int mipi_dsi_northwest_probe(struct udevice *dev)
  285. {
  286. return 0;
  287. }
  288. static const struct udevice_id mipi_dsi_northwest_ids[] = {
  289. { .compatible = "starfive,mipi-dsi" },
  290. { }
  291. };
  292. U_BOOT_DRIVER(mipi_dsi_host) = {
  293. .name = "mipi_dsi_host",
  294. .id = UCLASS_DSI_HOST,
  295. .of_match = mipi_dsi_northwest_ids,
  296. .probe = mipi_dsi_northwest_probe,
  297. .remove = mipi_dsi_northwest_disable,
  298. .ops = &mipi_dsi_northwest_ops,
  299. .priv_auto = sizeof(struct mipi_dsi_northwest_info),
  300. };