drv_slcdc.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496
  1. /*
  2. * File : drv_slcd_new.c
  3. * COPYRIGHT (C) 2008 - 2016, RT-Thread Development Team
  4. *
  5. * Change Logs:
  6. * Date Author Notes
  7. * 2017Äê4ÔÂ10ÈÕ Urey the first version
  8. */
  9. #include <rthw.h>
  10. #include <rtthread.h>
  11. #include <rtdevice.h>
  12. #include <cache.h>
  13. #include "board.h"
  14. #include "drv_slcdc.h"
  15. #include "drv_clock.h"
  16. #include "drv_gpio.h"
  17. static struct slcdc_dev_s *_slcd_device;
  18. static void _slcd_enable(struct slcdc_dev_s *lcd_dev);
  19. static void _slcd_disable(struct slcdc_dev_s *lcd_dev);
  20. static void udelay(uint32_t x)
  21. {
  22. volatile uint32_t n ;
  23. while(x--)
  24. {
  25. for (n = 0; n < 200; ++n);
  26. }
  27. }
  28. static int _slcd_convert_bpp(uint32_t bpp)
  29. {
  30. switch (bpp)
  31. {
  32. case 18:
  33. case 24:
  34. return 32;
  35. case 15:
  36. return 16;
  37. default:
  38. return bpp;
  39. }
  40. }
  41. static uint32_t refresh_pixclock_auto_adapt(struct slcdc_dev_s *lcd_dev)
  42. {
  43. uint32_t pixclk = 0;
  44. if((lcd_dev->cfg->refresh < 10) || (lcd_dev->cfg->refresh > 100))
  45. lcd_dev->cfg->refresh = 60;
  46. pixclk = lcd_dev->fb_size * lcd_dev->cfg->refresh * 9;// Range 7 to 10
  47. return pixclk;
  48. }
  49. static void _slcd_wait_busy(void)
  50. {
  51. int count = 10000;
  52. while ((slcd_reg_read(SLCDC_STATE) & SLCDC_STATE_BUSY) && count--);
  53. }
  54. /* Sent a command without data (18-bit bus, 16-bit index) */
  55. static void _slcd_mcu_send_command(struct slcdc_dev_s *lcd_dev,uint16_t cmd)
  56. {
  57. _slcd_wait_busy();
  58. cmd &= 0xffffff;
  59. slcd_reg_write(SLCDC_DATA, SLCDC_DATA_RS_COMMAND | cmd);
  60. }
  61. static void _slcd_mcu_send_data(struct slcdc_dev_s *lcd_dev,uint16_t data)
  62. {
  63. _slcd_wait_busy();
  64. data &= 0xffffff;
  65. slcd_reg_write(SLCDC_DATA, SLCDC_DATA_RS_DATA | data);
  66. }
  67. /* Sent a command with data (18-bit bus, 16-bit index, 16-bit register value) */
  68. static void _slcd_mcu_set_register(struct slcdc_dev_s *lcd_dev,uint16_t cmd, uint16_t data)
  69. {
  70. _slcd_mcu_send_command(lcd_dev,cmd);
  71. _slcd_mcu_send_data(lcd_dev,data);
  72. }
  73. static void _slcd_init_mcu(struct slcdc_dev_s *lcd_dev)
  74. {
  75. struct slcd_configure *cfg = lcd_dev->cfg;
  76. uint32_t index,j;
  77. uint32_t reg_width = lcd_dev->cfg->reg_width;
  78. uint32_t bus_width = lcd_dev->cfg->bus_width;
  79. if(reg_width < bus_width)
  80. reg_width = bus_width;
  81. if (cfg->data_table_num && cfg->data_table)
  82. {
  83. for (index = 0; index < cfg->data_table_num; index ++)
  84. {
  85. uint32_t value = cfg->data_table[index].value;
  86. switch (cfg->data_table[index].type)
  87. {
  88. case SMART_CONFIG_CMD:
  89. for (j = reg_width / bus_width; j > 0; j--)
  90. _slcd_mcu_send_command(lcd_dev, ((value << (32 - bus_width * j)) >> (32 - bus_width)));
  91. break;
  92. case SMART_CONFIG_DATA:
  93. for (j = reg_width / bus_width; j > 0; j--)
  94. _slcd_mcu_send_data(lcd_dev,((value << (32 - bus_width * j))>> (32 - bus_width)));
  95. break;
  96. case SMART_CONFIG_UDELAY:
  97. udelay(cfg->data_table[index].value);
  98. break;
  99. }
  100. }
  101. _slcd_wait_busy();
  102. }
  103. if (cfg->bpp / cfg->bus_width != 1)
  104. {
  105. int tmp = slcd_reg_read(SLCDC_CFG_NEW);
  106. tmp &= ~(SMART_LCD_DWIDTH_MASK); //mask the 8~9bit
  107. tmp |= (cfg->bpp / cfg->bus_width) == 2 ? SMART_LCD_NEW_DTIMES_TWICE : SMART_LCD_NEW_DTIMES_THICE ;
  108. slcd_reg_write(SLCDC_CFG_NEW, tmp);
  109. }
  110. }
  111. static void _slcd_init_mem(struct slcdc_dev_s *lcd_dev)
  112. {
  113. struct slcd_configure *cfg = lcd_dev->cfg;
  114. int i;
  115. uint32_t bypes_per_panel = (((cfg->width * _slcd_convert_bpp(cfg->bpp) / 8 + 3) >> 2 << 2) * cfg->height);
  116. #ifdef FB_BASE
  117. lcd_dev->fb_base = FB_BASE;
  118. #else
  119. #ifdef SLCDC_USING_DUAL_BUFFER
  120. lcd_dev->fb_base = (rt_uint32_t)rt_malloc_align((bypes_per_panel + FB_PAGE_SIZE) * 2, 32);
  121. #else
  122. lcd_dev->fb_base = (rt_uint32_t)rt_malloc_align((bypes_per_panel + FB_PAGE_SIZE) * 1, 32);
  123. #endif
  124. #endif
  125. lcd_dev->desc_cmd = (struct slcdc_dma_descriptor *)(lcd_dev->fb_base + 0 * sizeof(struct slcdc_dma_descriptor));
  126. lcd_dev->desc_tmp = (struct slcdc_dma_descriptor *)(lcd_dev->fb_base + 1 * sizeof(struct slcdc_dma_descriptor));
  127. lcd_dev->desc_dat = (struct slcdc_dma_descriptor *)(lcd_dev->fb_base + 2 * sizeof(struct slcdc_dma_descriptor));
  128. //nop
  129. lcd_dev->fb_cmd = (rt_uint32_t)lcd_dev->fb_base + 4 * sizeof(struct slcdc_dma_descriptor);
  130. lcd_dev->fb_screen= (rt_uint32_t)lcd_dev->fb_base + FB_PAGE_SIZE;
  131. rt_memset((void *) lcd_dev->fb_screen, 0, bypes_per_panel);
  132. #ifdef SLCDC_USING_DUAL_BUFFER
  133. lcd_dev->fb_dual = (lcd_dev->fb_screen + bypes_per_panel + FB_PAGE_SIZE) & ~(FB_PAGE_SIZE - 1);
  134. rt_memset((void *)lcd_dev->fb_dual,0,bypes_per_panel);
  135. #endif
  136. lcd_dev->fb_size = bypes_per_panel;
  137. /* copy command tbl */
  138. {
  139. uint32_t* cmd_ptr = (uint32_t*) lcd_dev->fb_cmd;
  140. for (i = 0; i < cfg->cmd_table_num; ++i)
  141. {
  142. cmd_ptr[i] = cfg->cmd_table[i];
  143. }
  144. }
  145. }
  146. static void _slcd_init_dma_desc(struct slcdc_dev_s *lcd_dev)
  147. {
  148. struct slcd_configure *cfg = lcd_dev->cfg;
  149. uint32_t bypes_per_panel = (((cfg->width * _slcd_convert_bpp(cfg->bpp) / 8 + 3) >> 2 << 2) * cfg->height);
  150. //dmadesc_tmp used to start DMA
  151. lcd_dev->desc_tmp->fdadr = virt_to_phys((void *)lcd_dev->desc_dat);
  152. lcd_dev->desc_tmp->fsadr = 0;
  153. lcd_dev->desc_tmp->fidr = 0xda0c0;
  154. lcd_dev->desc_tmp->ldcmd = LCDC_CMD_CMD | LCDC_CMD_FRM_EN | 0;
  155. lcd_dev->desc_tmp->offsize = 0;
  156. lcd_dev->desc_tmp->page_width = 0;
  157. lcd_dev->desc_tmp->cmd_num = 0;
  158. lcd_dev->desc_tmp->desc_size = 0;
  159. //dmadesc_cmd used to write CMD
  160. lcd_dev->desc_cmd->fdadr = virt_to_phys((void *)lcd_dev->desc_dat);
  161. lcd_dev->desc_cmd->fsadr = virt_to_phys((void *)lcd_dev->fb_cmd);
  162. lcd_dev->desc_cmd->fidr = 0xda0c1;
  163. lcd_dev->desc_cmd->offsize = 0;
  164. lcd_dev->desc_cmd->page_width = 0;
  165. lcd_dev->desc_cmd->desc_size = 0;
  166. /* if connect mipi smart lcd, do not sent command by slcdc, send command by mipi dsi controller. */
  167. switch (cfg->bus_width)
  168. {
  169. case 8:
  170. lcd_dev->desc_cmd->ldcmd = LCDC_CMD_CMD | LCDC_CMD_FRM_EN | 1;
  171. lcd_dev->desc_cmd->cmd_num = 4;
  172. break;
  173. case 9:
  174. case 16:
  175. lcd_dev->desc_cmd->ldcmd = LCDC_CMD_CMD | LCDC_CMD_FRM_EN | 1;
  176. lcd_dev->desc_cmd->cmd_num = 2;
  177. break;
  178. default:
  179. lcd_dev->desc_cmd->ldcmd = LCDC_CMD_CMD | LCDC_CMD_FRM_EN | 1;
  180. lcd_dev->desc_cmd->cmd_num = 1;
  181. break;
  182. }
  183. //frame_desc[1] used to update GRAM
  184. lcd_dev->desc_dat->fdadr = virt_to_phys((void *)lcd_dev->desc_cmd);
  185. lcd_dev->desc_dat->fsadr = virt_to_phys((void *)lcd_dev->fb_screen);
  186. lcd_dev->desc_dat->fidr = 0xda0d0;
  187. lcd_dev->desc_dat->ldcmd = LCDC_CMD_EOFINT | LCDC_CMD_FRM_EN | (bypes_per_panel / 4);
  188. lcd_dev->desc_dat->offsize = 0;
  189. lcd_dev->desc_dat->page_width = 0;
  190. switch(_slcd_convert_bpp(cfg->bpp))
  191. {
  192. case 16 :
  193. lcd_dev->desc_dat->cmd_num = LCDC_CPOS_RGB_RGB565 | LCDC_CPOS_BPP_16;;
  194. break;
  195. case 30 :
  196. lcd_dev->desc_dat->cmd_num = LCDC_CPOS_BPP_30;
  197. break;
  198. default:
  199. lcd_dev->desc_dat->cmd_num = LCDC_CPOS_BPP_18_24;
  200. break;
  201. }
  202. /* data has not been premultied */
  203. lcd_dev->desc_dat->cmd_num |= LCDC_CPOS_PREMULTI;
  204. /* coef_sle 0 use 1 */
  205. lcd_dev->desc_dat->cmd_num |= LCDC_CPOS_COEF_SLE_1;
  206. lcd_dev->desc_dat->desc_size = (((cfg->height - 1) << LCDC_DESSIZE_HEIGHT_BIT) | ((cfg->width - 1) << LCDC_DESSIZE_WIDTH_BIT));
  207. slcd_reg_write(LCDC_DA0, virt_to_phys(lcd_dev->desc_cmd));
  208. //desc self
  209. rt_hw_flush_cache_all();
  210. }
  211. static void _slcd_init_ctrl(struct slcdc_dev_s *lcd_dev)
  212. {
  213. struct slcd_configure *lcd_cfg = lcd_dev->cfg;
  214. struct clk *clk,*gate_clk;
  215. uint32_t ctrl;
  216. uint32_t size0;
  217. uint32_t smart_cfg = 0, smart_ctrl = 0;
  218. uint32_t pcfg;
  219. uint32_t smart_new_cfg = 0;
  220. uint32_t smart_wtime = 0, smart_tas = 0;
  221. /* clear all registers*/
  222. _slcd_disable(lcd_dev);
  223. slcd_reg_write(SLCDC_CTRL,0);
  224. /*The SLCD rd and ce function only can be used by set PB16/PB18 as normal GPIO function
  225. * SLCS_D00 PA00
  226. * ...
  227. * SLCS_D07 PA07
  228. *
  229. * slcd_rd PB16 (not use,must set high)
  230. * slcd_wr PB17
  231. * slcd_ce PB18
  232. * slcd_te PB19 (not use)
  233. * slcd_dc PB20
  234. * 2. setup SLCD for register mode
  235. * */
  236. gpio_set_func(GPIO_PORT_A, 0x000000FF, GPIO_FUNC_1);
  237. gpio_set_func(GPIO_PORT_B, (GPIO_Pin_17 | GPIO_Pin_18 | GPIO_Pin_20), GPIO_FUNC_1);
  238. #ifdef CONFIG_SLCDC_USE_TE
  239. gpio_set_func(GPIO_PORT_B, (GPIO_Pin_19), GPIO_FUNC_1);
  240. #endif
  241. gpio_set_func(GPIO_PORT_B, GPIO_Pin_16, GPIO_OUTPUT1);
  242. /* set clock */
  243. gate_clk = clk_get("lcd");
  244. clk = clk_get("cgu_lcd");
  245. clk_disable(clk);
  246. clk_set_rate(clk, refresh_pixclock_auto_adapt(lcd_dev));
  247. clk_enable(clk);
  248. clk_enable(gate_clk);
  249. ctrl = LCDC_CTRL_BST_64 | LCDC_CTRL_OFUM;
  250. if(lcd_cfg->pinmd)
  251. ctrl |= LCDC_CTRL_PINMD;
  252. smart_cfg = SMART_LCD_DWIDTH_24_BIT_ONCE_PARALLEL;
  253. switch (lcd_cfg->bus_width)
  254. {
  255. case 8:
  256. smart_cfg |= SMART_LCD_CWIDTH_8_BIT_ONCE;
  257. smart_new_cfg |= SMART_LCD_NEW_DWIDTH_8_BIT;
  258. break;
  259. case 9:
  260. smart_cfg |= SMART_LCD_CWIDTH_9_BIT_ONCE;
  261. smart_new_cfg |= SMART_LCD_NEW_DWIDTH_9_BIT;
  262. break;
  263. case 16:
  264. smart_cfg |= SMART_LCD_CWIDTH_16_BIT_ONCE;
  265. smart_new_cfg |= SMART_LCD_NEW_DWIDTH_16_BIT;
  266. break;
  267. case 18:
  268. smart_cfg |= SMART_LCD_CWIDTH_18_BIT_ONCE;
  269. smart_new_cfg |= SMART_LCD_NEW_DWIDTH_18_BIT;
  270. break;
  271. case 24:
  272. smart_cfg |= SMART_LCD_CWIDTH_24_BIT_ONCE;
  273. smart_new_cfg |= SMART_LCD_NEW_DWIDTH_24_BIT;
  274. break;
  275. default:
  276. rt_kprintf("ERR: please check out your bus width config\n");
  277. break;
  278. }
  279. if (lcd_cfg->clkply_active_rising)
  280. smart_cfg |= SLCDC_CFG_CLK_ACTIVE_RISING;
  281. if (lcd_cfg->rsply_cmd_high)
  282. smart_cfg |= SLCDC_CFG_RS_CMD_HIGH;
  283. if (lcd_cfg->csply_active_high)
  284. smart_cfg |= SLCDC_CFG_CS_ACTIVE_HIGH;
  285. /* SLCD DMA mode select 0 */
  286. smart_ctrl = SLCDC_CTRL_DMA_MODE;
  287. smart_ctrl &= ~SLCDC_CTRL_GATE_MASK;
  288. smart_ctrl |= (SLCDC_CTRL_NEW_MODE | SLCDC_CTRL_NOT_USE_TE | SLCDC_CTRL_FAST_MODE); //new slcd mode
  289. smart_ctrl &= ~SLCDC_CTRL_MIPI_MODE;
  290. smart_new_cfg |= SMART_LCD_NEW_DTIMES_ONCE;
  291. if (lcd_cfg->newcfg_6800_md)
  292. smart_new_cfg |= SLCDC_NEW_CFG_6800_MD;
  293. if (lcd_cfg->newcfg_cmd_9bit)
  294. smart_new_cfg |= SLCDC_NEW_CFG_CMD_9BIT;
  295. slcd_reg_write(LCDC_VAT, (lcd_cfg->width << 16) | lcd_cfg->height);
  296. slcd_reg_write(LCDC_DAH, lcd_cfg->width);
  297. slcd_reg_write(LCDC_DAV, lcd_cfg->height);
  298. slcd_reg_write(SLCDC_CFG, smart_cfg);
  299. slcd_reg_write(SLCDC_CTRL, smart_ctrl);
  300. slcd_reg_write(SLCDC_CFG_NEW, smart_new_cfg);
  301. slcd_reg_write(SLCDC_WTIME, smart_wtime);
  302. slcd_reg_write(SLCDC_TAS, smart_tas);
  303. slcd_reg_write(SLCDC_SLOW_TIME, 0x0000FFFF);
  304. slcd_reg_write(LCDC_CTRL, ctrl);
  305. pcfg = 0xC0000000 | (511 << 18) | (400 << 9) | (256 << 0);
  306. slcd_reg_write(LCDC_PCFG, pcfg);
  307. size0 = (lcd_cfg->width << LCDC_SIZE_WIDTH_BIT) & LCDC_SIZE_WIDTH_MASK;
  308. size0 |= (lcd_cfg->height << LCDC_SIZE_HEIGHT_BIT) & LCDC_SIZE_HEIGHT_MASK;
  309. slcd_reg_write(LCDC_SIZE0, size0);
  310. slcd_reg_write(LCDC_CTRL,slcd_reg_read(LCDC_CTRL) | LCDC_CTRL_ENA);
  311. _slcd_init_dma_desc(lcd_dev);
  312. _slcd_init_mcu(lcd_dev);
  313. _slcd_enable(lcd_dev);
  314. if (lcd_cfg->newcfg_fmt_conv)
  315. {
  316. smart_new_cfg = slcd_reg_read(SLCDC_CFG_NEW);
  317. smart_new_cfg |= SLCDC_NEW_CFG_FMT_CONV_EN;
  318. slcd_reg_write(SLCDC_CFG_NEW, smart_new_cfg);
  319. }
  320. #ifdef CONFIG_SLCDC_CONTINUA
  321. smart_ctrl &= ~SLCDC_CTRL_DMA_MODE;
  322. #else
  323. smart_ctrl |= SLCDC_CTRL_DMA_START;
  324. #endif
  325. smart_ctrl |= SLCDC_CTRL_DMA_EN;
  326. #ifdef CONFIG_SLCDC_USE_TE
  327. smart_ctrl &= ~SLCDC_CTRL_NOT_USE_TE;
  328. //smart_ctrl |= SLCDC_CTRL_TE_INV;
  329. smart_ctrl &= ~SLCDC_CTRL_TE_INV;
  330. #endif
  331. slcd_reg_write(SLCDC_CTRL, smart_ctrl);
  332. }
  333. static void _slcd_enable(struct slcdc_dev_s *lcd_dev)
  334. {
  335. uint32_t ctrl,state;
  336. int count = 2000;
  337. while ((slcd_reg_read(SLCDC_STATE) & SLCDC_STATE_BUSY) && count--)
  338. {
  339. udelay(10);
  340. }
  341. slcd_reg_write(LCDC_STATE, 0);
  342. slcd_reg_write(LCDC_CTRL,slcd_reg_read(LCDC_CTRL) | LCDC_CTRL_ENA);
  343. }
  344. static void _slcd_disable(struct slcdc_dev_s *lcd_dev)
  345. {
  346. /* SLCD and TVE only support quick disable */
  347. slcd_reg_write(LCDC_CTRL, slcd_reg_read(LCDC_CTRL) & ~LCDC_CTRL_ENA);
  348. }
  349. /* common device interface */
  350. static rt_err_t _slcd_device_control(rt_device_t dev, int cmd, void *args)
  351. {
  352. struct slcdc_dev_s *slcd;
  353. uint32_t smart_ctrl = 0;
  354. slcd = (struct slcdc_dev_s *)dev;
  355. RT_ASSERT(slcd != RT_NULL);
  356. rt_mutex_take(&(slcd->lock), RT_WAITING_FOREVER);
  357. switch (cmd)
  358. {
  359. case RTGRAPHIC_CTRL_GET_INFO:
  360. {
  361. struct rt_device_graphic_info *info = (struct rt_device_graphic_info *) args;
  362. info->bits_per_pixel = slcd->cfg->bpp;
  363. info->pixel_format = slcd->cfg->fmt;
  364. #ifdef SLCDC_USING_DUAL_BUFFER
  365. info->framebuffer = (rt_uint8_t *)(KSEG1ADDR(slcd->fb_dual));
  366. #else
  367. info->framebuffer = (rt_uint8_t *)(KSEG1ADDR(slcd->fb_screen));
  368. #endif
  369. info->width = slcd->cfg->width;
  370. info->height = slcd->cfg->height;
  371. break;
  372. }
  373. case RTGRAPHIC_CTRL_RECT_UPDATE:
  374. {
  375. #ifdef SLCDC_USING_DUAL_BUFFER
  376. rt_memcpy((void *)(slcd->fb_screen), (void *)(slcd->fb_dual), slcd->fb_size);
  377. #endif
  378. rt_hw_dcache_flush_range((rt_uint32_t)slcd->fb_screen,slcd->fb_size);
  379. smart_ctrl = slcd_reg_read(SLCDC_CTRL);
  380. smart_ctrl |= SLCDC_CTRL_DMA_START;
  381. slcd_reg_write(SLCDC_CTRL, smart_ctrl);
  382. while (slcd_reg_read(SLCDC_STATE) & SLCDC_STATE_BUSY);
  383. break;
  384. }
  385. case RTGRAPHIC_CTRL_SET_MODE:
  386. break;
  387. }
  388. rt_mutex_release(&(slcd->lock));
  389. return RT_EOK;
  390. }
  391. int rt_hw_slcd_init(struct slcd_configure *cfg)
  392. {
  393. struct slcdc_dev_s *slcd;
  394. slcd = (struct slcdc_dev_s *)rt_malloc(sizeof(struct slcdc_dev_s));
  395. if(slcd == RT_NULL)
  396. {
  397. rt_kprintf("error no memory!\n");
  398. return -RT_ENOMEM;
  399. }
  400. _slcd_device = slcd;
  401. slcd->cfg = cfg;
  402. rt_mutex_init(&slcd->lock, "lcdfb", RT_IPC_FLAG_FIFO);
  403. _slcd_disable(slcd);
  404. _slcd_init_mem(slcd);
  405. _slcd_init_ctrl(slcd);
  406. _slcd_enable(slcd);
  407. /* device support */
  408. slcd->parent.type = RT_Device_Class_Graphic;
  409. slcd->parent.init = RT_NULL;
  410. slcd->parent.open = RT_NULL;
  411. slcd->parent.close = RT_NULL;
  412. slcd->parent.read = RT_NULL;
  413. slcd->parent.write = RT_NULL;
  414. slcd->parent.control = _slcd_device_control;
  415. rt_device_register(&slcd->parent, "lcd", RT_DEVICE_FLAG_RDWR);
  416. return RT_EOK;
  417. }