1 /*
2  * Copyright (c) 2006-2023, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2017-10-30     Tanek        the first version
9  * 2018-04-05     Liu2guang    export LCD config parameters.
10  */
11 
12 #include <rtthread.h>
13 
14 #ifdef BSP_USING_LCD
15 
16 #include "drv_lcd.h"
17 #include "fsl_common.h"
18 #include "fsl_iomuxc.h"
19 #include "fsl_elcdif.h"
20 #include "drv_gpio.h"
21 
22 #define LOG_TAG             "drv.lcd"
23 #include <drv_log.h>
24 
25 #if !defined(LCD_WIDTH) || !defined(LCD_HEIGHT)
26 #error "Please config lcd pixel parameters."
27 #endif
28 
29 #if !defined(LCD_HFP) || !defined(LCD_HBP) || !defined(LCD_HSW) || \
30     !defined(LCD_VFP) || !defined(LCD_VBP) || !defined(LCD_VSW)
31 #error "Please config lcd timing parameters."
32 #endif
33 
34 #if !defined(LCD_BL_PIN) || !defined(LCD_RST_PIN)
35 #error "Please config lcd backlight or reset pin."
36 #endif
37 
38 struct imxrt_lcd
39 {
40     struct rt_device device;
41     struct rt_device_graphic_info info;
42 };
43 
44 static struct imxrt_lcd lcd;
45 AT_NONCACHEABLE_SECTION_ALIGN(static uint16_t frame_buffer[LCD_HEIGHT][LCD_WIDTH], 64);
46 
imxrt_lcd_init(rt_device_t device)47 static rt_err_t imxrt_lcd_init(rt_device_t device)
48 {
49     RT_ASSERT(device != RT_NULL);
50 
51     rt_memset(frame_buffer, 0x00, sizeof(frame_buffer));
52     clock_video_pll_config_t pll_config;
53 
54     pll_config.loopDivider = 43;
55     pll_config.postDivider = 4;
56     pll_config.numerator   = 0;
57     pll_config.denominator = 0;
58 
59     CLOCK_InitVideoPll(&pll_config);
60 
61     rt_pin_mode(LCD_RST_PIN, PIN_MODE_OUTPUT); /* LCD_RESET */
62     rt_pin_write(LCD_RST_PIN, PIN_LOW);
63     rt_thread_delay(RT_TICK_PER_SECOND / 100);
64     rt_pin_write(LCD_RST_PIN, PIN_HIGH);
65 
66     rt_pin_mode (LCD_BL_PIN, PIN_MODE_OUTPUT);  /* LCD_BL */
67     rt_pin_write(LCD_BL_PIN, PIN_HIGH);
68 
69     /* LCD */
70     elcdif_rgb_mode_config_t lcd_config;
71 
72     lcd_config.hfp           = LCD_HFP;
73     lcd_config.vfp           = LCD_VFP;
74     lcd_config.hbp           = LCD_HBP;
75     lcd_config.vbp           = LCD_VBP;
76     lcd_config.hsw           = LCD_HSW;
77     lcd_config.vsw           = LCD_VSW;
78 
79     lcd_config.polarityFlags = kELCDIF_DataEnableActiveHigh |
80                                kELCDIF_VsyncActiveHigh      |
81                                kELCDIF_HsyncActiveLow       |
82                                kELCDIF_DriveDataOnRisingClkEdge;
83 
84     lcd_config.panelWidth    = LCD_WIDTH;
85     lcd_config.panelHeight   = LCD_HEIGHT;
86     lcd_config.pixelFormat   = kELCDIF_PixelFormatRGB565;
87     lcd_config.dataBus       = kELCDIF_DataBus16Bit;
88     lcd_config.bufferAddr    = (uint32_t)frame_buffer;
89 
90     ELCDIF_RgbModeInit (LCDIF, &lcd_config);
91     ELCDIF_RgbModeStart(LCDIF);
92 
93     /* LCD DEVICE */
94     lcd.info.width          = LCD_WIDTH;
95     lcd.info.height         = LCD_HEIGHT;
96     lcd.info.pixel_format   = RTGRAPHIC_PIXEL_FORMAT_RGB565;
97     lcd.info.bits_per_pixel = 16;
98     lcd.info.framebuffer    = (void *)frame_buffer;
99 
100     return RT_EOK;
101 }
102 
imxrt_lcd_control(rt_device_t device,int cmd,void * args)103 static rt_err_t imxrt_lcd_control(rt_device_t device, int cmd, void *args)
104 {
105     switch(cmd)
106     {
107     case RTGRAPHIC_CTRL_RECT_UPDATE:
108         break;
109 
110     case RTGRAPHIC_CTRL_POWERON:
111         rt_pin_write(LCD_BL_PIN, PIN_HIGH);
112         break;
113 
114     case RTGRAPHIC_CTRL_POWEROFF:
115         rt_pin_write(LCD_BL_PIN, PIN_LOW);
116         break;
117 
118     case RTGRAPHIC_CTRL_GET_INFO:
119         rt_memcpy(args, &lcd.info, sizeof(lcd.info));
120         break;
121 
122     case RTGRAPHIC_CTRL_SET_MODE:
123         break;
124     }
125 
126     return RT_EOK;
127 }
128 
rt_hw_lcd_init(void)129 int rt_hw_lcd_init(void)
130 {
131     rt_err_t ret;
132 
133     lcd.device.type    = RT_Device_Class_Graphic;
134     lcd.device.init    = imxrt_lcd_init;
135     lcd.device.open    = RT_NULL;
136     lcd.device.close   = RT_NULL;
137     lcd.device.read    = RT_NULL;
138     lcd.device.write   = RT_NULL;
139     lcd.device.control = imxrt_lcd_control;
140 
141     lcd.device.user_data = (void *)&lcd.info;
142 
143     ret = rt_device_register(&lcd.device, "lcd", RT_DEVICE_FLAG_RDWR);
144 
145     return ret;
146 }
147 
148 INIT_DEVICE_EXPORT(rt_hw_lcd_init);
149 
150 #endif /* BSP_USING_LCD */
151