drv_lcd.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. /*
  2. * Copyright (c) 2006-2021, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2021-01-11 Lyons first version
  9. * 2021-06-24 RiceChen refactor
  10. * 2021-07-28 songchao add cmd
  11. */
  12. #include <rthw.h>
  13. #include <rtdevice.h>
  14. #ifdef BSP_USING_LCD
  15. #define LOG_TAG "drv.lcd"
  16. #include <drv_log.h>
  17. #include "fsl_iomuxc.h"
  18. #include "drv_lcd.h"
  19. #include <lwp_user_mm.h>
  20. static struct imx6ull_lcd_config _lcd_config = LCD_BUS_CONFIG;
  21. static struct imx6ull_lcd_bus _lcd_obj;
  22. static rt_err_t imx6ull_elcd_init(rt_device_t device)
  23. {
  24. struct imx6ull_lcd_bus *elcd_dev = RT_NULL;
  25. clock_video_pll_config_t pll_config;
  26. elcdif_rgb_mode_config_t lcd_config;
  27. RT_ASSERT(device != RT_NULL);
  28. elcd_dev = (struct imx6ull_lcd_bus *)device;
  29. ELCDIF_Reset(elcd_dev->config->ELCDIF);
  30. pll_config.loopDivider = 32;
  31. pll_config.postDivider = LCD_PLL_DIV;
  32. pll_config.numerator = 0;
  33. pll_config.denominator = 0;
  34. CLOCK_InitVideoPll(&pll_config);
  35. lcd_config.hfp = LCD_HFP;
  36. lcd_config.vfp = LCD_VFP;
  37. lcd_config.hbp = LCD_HBP;
  38. lcd_config.vbp = LCD_VBP;
  39. lcd_config.hsw = LCD_HSW;
  40. lcd_config.vsw = LCD_VSW;
  41. lcd_config.polarityFlags = kELCDIF_DataEnableActiveHigh |
  42. kELCDIF_VsyncActiveLow |
  43. kELCDIF_HsyncActiveLow |
  44. kELCDIF_DriveDataOnRisingClkEdge;
  45. switch(elcd_dev->info.pixel_format)
  46. {
  47. case RTGRAPHIC_PIXEL_FORMAT_RGB888:
  48. lcd_config.pixelFormat = kELCDIF_PixelFormatRGB888;
  49. break;
  50. case RTGRAPHIC_PIXEL_FORMAT_RGB565:
  51. lcd_config.pixelFormat = kELCDIF_PixelFormatRGB565;
  52. break;
  53. default:
  54. LOG_E("not support this pixel_format %d\n",elcd_dev->info.pixel_format);
  55. return RT_ERROR;
  56. }
  57. lcd_config.panelWidth = elcd_dev->info.width;
  58. lcd_config.panelHeight = elcd_dev->info.height;
  59. lcd_config.bufferAddr = (uint32_t)elcd_dev->fb_phy;
  60. lcd_config.dataBus = kELCDIF_DataBus24Bit;
  61. ELCDIF_RgbModeInit(elcd_dev->config->ELCDIF, &lcd_config);
  62. ELCDIF_RgbModeStart(elcd_dev->config->ELCDIF);
  63. return RT_EOK;
  64. }
  65. static rt_err_t imx6ull_elcd_control(rt_device_t device, int cmd, void *args)
  66. {
  67. struct imx6ull_lcd_bus *elcd_dev = RT_NULL;
  68. int mem_size = 0;
  69. RT_ASSERT(device != RT_NULL);
  70. elcd_dev = (struct imx6ull_lcd_bus *)device;
  71. switch(cmd)
  72. {
  73. case RTGRAPHIC_CTRL_RECT_UPDATE:
  74. {
  75. mem_size = elcd_dev->info.width * elcd_dev->info.height * elcd_dev->info.bits_per_pixel / 8;
  76. rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, (void *)(_lcd_obj.info.framebuffer), mem_size);
  77. break;
  78. }
  79. case RTGRAPHIC_CTRL_POWERON:
  80. {
  81. rt_pin_write(IMX6ULL_LCD_BL_PIN, PIN_HIGH);
  82. break;
  83. }
  84. case RTGRAPHIC_CTRL_POWEROFF:
  85. {
  86. rt_pin_write(IMX6ULL_LCD_BL_PIN, PIN_LOW);
  87. break;
  88. }
  89. case RTGRAPHIC_CTRL_GET_INFO:
  90. {
  91. struct lcd_info *info = (struct lcd_info *)args;
  92. RT_ASSERT(info != RT_NULL);
  93. rt_memcpy(&info->graphic, &elcd_dev->info, sizeof(struct rt_device_graphic_info));
  94. info->screen.shamem_len = elcd_dev->info.width * elcd_dev->info.height * elcd_dev->info.bits_per_pixel / 8;
  95. info->screen.shamem_start = (rt_uint32_t)lwp_map_user_phy(lwp_self(), RT_NULL,
  96. elcd_dev->fb_phy,
  97. info->screen.shamem_len, 1);
  98. break;
  99. }
  100. case RTGRAPHIC_CTRL_SET_MODE:
  101. {
  102. break;
  103. }
  104. case FBIOGET_FSCREENINFO:
  105. {
  106. struct fb_fix_screeninfo *info = (struct fb_fix_screeninfo *)args;
  107. rt_memcpy(info->id, elcd_dev->config->name, (strlen(elcd_dev->config->name)+1));
  108. info->smem_len = elcd_dev->info.width * elcd_dev->info.height * elcd_dev->info.bits_per_pixel / 8;
  109. info->smem_start = (rt_uint32_t)lwp_map_user_phy(lwp_self(), RT_NULL,
  110. elcd_dev->fb_phy,
  111. info->smem_len, 1);
  112. info->line_length = elcd_dev->info.width * 2;
  113. break;
  114. }
  115. case FBIOGET_VSCREENINFO:
  116. {
  117. struct fb_var_screeninfo *info = (struct fb_var_screeninfo *)args;
  118. info->bits_per_pixel = elcd_dev->info.bits_per_pixel;
  119. info->xres = elcd_dev->info.width;
  120. info->yres = elcd_dev->info.height;
  121. break;
  122. }
  123. }
  124. return RT_EOK;
  125. }
  126. #ifdef RT_USING_DEVICE_OPS
  127. const static struct rt_device_ops elcd_ops =
  128. {
  129. imx6ull_elcd_init,
  130. RT_NULL,
  131. RT_NULL,
  132. RT_NULL,
  133. RT_NULL,
  134. imx6ull_elcd_control,
  135. };
  136. #endif
  137. int rt_hw_elcd_init(void)
  138. {
  139. rt_err_t ret = 0;
  140. _lcd_config.ELCDIF = (LCDIF_Type *)imx6ull_get_periph_vaddr((rt_uint32_t)(_lcd_config.ELCDIF));
  141. _lcd_config.lcd_mux_base = (rt_uint32_t)imx6ull_get_periph_vaddr((rt_uint32_t)(_lcd_config.lcd_mux_base));
  142. _lcd_config.lcd_cfg_base = (rt_uint32_t)imx6ull_get_periph_vaddr((rt_uint32_t)(_lcd_config.lcd_cfg_base));
  143. for(int i = 0; i < LCD_GPIO_MAX; i++)
  144. {
  145. IOMUXC_SetPinMux((_lcd_config.lcd_mux_base + i * 4),
  146. 0x0U, 0x0U, 0x0U, (_lcd_config.lcd_cfg_base + i * 4), 0);
  147. IOMUXC_SetPinConfig((_lcd_config.lcd_mux_base + i * 4),
  148. 0x0U, 0x0U, 0x0U, (_lcd_config.lcd_cfg_base + i * 4), 0xB9);
  149. }
  150. CLOCK_EnableClock(_lcd_config.apd_clk_name);
  151. CLOCK_EnableClock(_lcd_config.pix_clk_name);
  152. _lcd_obj.config = &_lcd_config;
  153. _lcd_obj.fb_virt = rt_pages_alloc(rt_page_bits(LCD_BUF_SIZE));
  154. _lcd_obj.fb_phy = _lcd_obj.fb_virt + PV_OFFSET;
  155. LOG_D("fb address => 0x%08x\n", _lcd_obj.fb_phy);
  156. if(_lcd_obj.fb_phy == RT_NULL)
  157. {
  158. LOG_E("initialize frame buffer failed!\n");
  159. return -RT_ERROR;
  160. }
  161. _lcd_obj.info.width = LCD_WIDTH;
  162. _lcd_obj.info.height = LCD_HEIGHT;
  163. _lcd_obj.info.pixel_format = RTGRAPHIC_PIXEL_FORMAT_RGB888;
  164. _lcd_obj.info.bits_per_pixel = LCD_BITS_PER_PIXEL;
  165. _lcd_obj.info.framebuffer = (void *)_lcd_obj.fb_virt;
  166. _lcd_obj.parent.type = RT_Device_Class_Graphic;
  167. #ifdef RT_USING_DEVICE_OPS
  168. _lcd_obj.parent.ops = &elcd_ops;
  169. #else
  170. _lcd_obj.parent.init = imx6ull_elcd_init;
  171. _lcd_obj.parent.open = RT_NULL;
  172. _lcd_obj.parent.close = RT_NULL;
  173. _lcd_obj.parent.read = RT_NULL;
  174. _lcd_obj.parent.write = RT_NULL;
  175. _lcd_obj.parent.control = imx6ull_elcd_control;
  176. #endif
  177. _lcd_obj.parent.user_data = (void *)&_lcd_obj.info;
  178. ret = rt_device_register(&_lcd_obj.parent, _lcd_obj.config->name, RT_DEVICE_FLAG_RDWR);
  179. /* LCD_BL */
  180. rt_pin_mode(IMX6ULL_LCD_BL_PIN, PIN_MODE_OUTPUT);
  181. rt_pin_write(IMX6ULL_LCD_BL_PIN, PIN_HIGH);
  182. rt_memset((rt_uint8_t *)_lcd_obj.fb_virt, 0xff, LCD_BUF_SIZE);
  183. return ret;
  184. }
  185. INIT_DEVICE_EXPORT(rt_hw_elcd_init);
  186. #endif