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  * 2019-01-10     zylx         first version
9  */
10 
11 #include <rtthread.h>
12 #include <rtdevice.h>
13 #include <board.h>
14 
15 #ifdef BSP_USING_DSI
16 #include <lcd_port_dsi.h>
17 #include <string.h>
18 #include "drv_gpio.h"
19 #include "gfxmmu_lut_390x390_24bpp.h"
20 
21 #define DRV_DEBUG
22 #define LOG_TAG             "drv.lcd"
23 #include <drv_log.h>
24 
25 static DSI_HandleTypeDef    DsiHandle;
26 
27 struct drv_lcd_dsi_device
28 {
29     struct rt_device parent;
30 
31     struct rt_device_graphic_info lcd_info;
32 
33     struct rt_semaphore lcd_lock;
34 
35     rt_uint8_t *front_buf;
36 };
37 
38 struct drv_lcd_dsi_device _lcd;
39 
40 static DMA2D_HandleTypeDef   Dma2dHandle;
CopyInVirtualBuffer(uint32_t * pSrc,uint32_t * pDst,uint16_t x,uint16_t y,uint16_t xsize,uint16_t ysize)41 static void CopyInVirtualBuffer(uint32_t *pSrc, uint32_t *pDst, uint16_t x, uint16_t y, uint16_t xsize, uint16_t ysize)
42 {
43     uint32_t destination = (uint32_t)pDst + (y * 390 + x) * 4;
44     uint32_t source      = (uint32_t)pSrc;
45 
46     Dma2dHandle.Instance          = DMA2D;
47 
48     /*##-1- Configure the DMA2D Mode, Color Mode and output offset #############*/
49     Dma2dHandle.Init.Mode           = DMA2D_M2M_PFC;
50     Dma2dHandle.Init.ColorMode      = DMA2D_OUTPUT_RGB888;
51     Dma2dHandle.Init.OutputOffset   = 1024 - 390;
52     /* No Output Alpha Inversion */
53     Dma2dHandle.Init.AlphaInverted  = DMA2D_REGULAR_ALPHA;
54     /* No Output Red & Blue swap */
55     Dma2dHandle.Init.RedBlueSwap    = DMA2D_RB_REGULAR;
56     /* Regular output byte order */
57     Dma2dHandle.Init.BytesSwap      = DMA2D_BYTES_REGULAR;
58     /* Pixel mode */
59     Dma2dHandle.Init.LineOffsetMode = DMA2D_LOM_PIXELS;
60 
61     /*##-2- Foreground Configuration ###########################################*/
62     Dma2dHandle.LayerCfg[1].InputColorMode = DMA2D_INPUT_ARGB8888;
63     Dma2dHandle.LayerCfg[1].InputOffset    = 0;
64     Dma2dHandle.LayerCfg[1].AlphaMode      = DMA2D_NO_MODIF_ALPHA;
65     /* Not used */
66     Dma2dHandle.LayerCfg[1].InputAlpha     = 0xFF;
67     /* No ForeGround Red/Blue swap */
68     Dma2dHandle.LayerCfg[1].RedBlueSwap    = DMA2D_RB_REGULAR;
69     /* No ForeGround Alpha inversion */
70     Dma2dHandle.LayerCfg[1].AlphaInverted  = DMA2D_REGULAR_ALPHA;
71 
72     /* DMA2D Initialization */
73     if (HAL_DMA2D_Init(&Dma2dHandle) == HAL_OK)
74     {
75         if (HAL_DMA2D_ConfigLayer(&Dma2dHandle, 1) == HAL_OK)
76         {
77             if (HAL_DMA2D_Start(&Dma2dHandle, source, destination, xsize, ysize) == HAL_OK)
78             {
79                 /* Polling For DMA transfer */
80                 HAL_DMA2D_PollForTransfer(&Dma2dHandle, 100);
81             }
82         }
83     }
84 }
85 
drv_lcd_init(struct rt_device * device)86 static rt_err_t drv_lcd_init(struct rt_device *device)
87 {
88     struct drv_lcd_dsi_device *lcd = (struct drv_lcd_dsi_device *)device;
89     /* nothing, right now */
90     lcd = lcd;
91     return RT_EOK;
92 }
93 
drv_lcd_control(struct rt_device * device,int cmd,void * args)94 static rt_err_t drv_lcd_control(struct rt_device *device, int cmd, void *args)
95 {
96     struct drv_lcd_dsi_device *lcd = (struct drv_lcd_dsi_device *)device;
97     rt_uint8_t color = 0;
98     switch (cmd)
99     {
100     case RTGRAPHIC_CTRL_RECT_UPDATE:
101     {
102         /* update */
103         rt_sem_take(&_lcd.lcd_lock, RT_TICK_PER_SECOND / 20);
104         CopyInVirtualBuffer((uint32_t *)_lcd.lcd_info.framebuffer, (uint32_t *)LAYER_ADDRESS, 0, 0, 390, 390);
105         HAL_DSI_Refresh(&DsiHandle);
106     }
107     break;
108 
109     case RTGRAPHIC_CTRL_GET_INFO:
110     {
111         struct rt_device_graphic_info *info = (struct rt_device_graphic_info *)args;
112 
113         RT_ASSERT(info != RT_NULL);
114         info->pixel_format  = lcd->lcd_info.pixel_format;
115         info->bits_per_pixel = 32;
116         info->width         = lcd->lcd_info.width;
117         info->height        = lcd->lcd_info.height;
118         info->framebuffer   = lcd->lcd_info.framebuffer;
119     }
120     break;
121     }
122 
123     return RT_EOK;
124 }
125 
126 LTDC_HandleTypeDef   LtdcHandle;
stm32_lcd_init(struct drv_lcd_dsi_device * lcd)127 rt_err_t stm32_lcd_init(struct drv_lcd_dsi_device *lcd)
128 {
129     DSI_PLLInitTypeDef      dsiPllInit = {0};
130     DSI_PHY_TimerTypeDef    PhyTimings = {0};
131     DSI_HOST_TimeoutTypeDef HostTimeouts = {0};
132     DSI_LPCmdTypeDef        LPCmd = {0};
133     DSI_CmdCfgTypeDef       CmdCfg = {0};
134     GFXMMU_HandleTypeDef GfxmmuHandle = {0};
135     LTDC_LayerCfgTypeDef    LayerCfg = {0};
136 
137     /* GFXMMU CONFIGURATION */
138     __HAL_GFXMMU_RESET_HANDLE_STATE(&GfxmmuHandle);
139     GfxmmuHandle.Instance = GFXMMU;
140     GfxmmuHandle.Init.BlocksPerLine                     = GFXMMU_192BLOCKS;
141     GfxmmuHandle.Init.DefaultValue                      = 0xFFFFFFFF;
142     GfxmmuHandle.Init.Buffers.Buf0Address               = (uint32_t)lcd->front_buf;
143     GfxmmuHandle.Init.Buffers.Buf1Address               = 0;
144     GfxmmuHandle.Init.Buffers.Buf2Address               = 0;
145     GfxmmuHandle.Init.Buffers.Buf3Address               = 0;
146     GfxmmuHandle.Init.Interrupts.Activation             = DISABLE;
147     GfxmmuHandle.Init.Interrupts.UsedInterrupts         = GFXMMU_AHB_MASTER_ERROR_IT;
148     if (HAL_OK != HAL_GFXMMU_Init(&GfxmmuHandle))
149     {
150         return -RT_ERROR;
151     }
152 
153     /* Initialize LUT */
154     if (HAL_OK != HAL_GFXMMU_ConfigLut(&GfxmmuHandle, 0, 390, (uint32_t) gfxmmu_lut_config_rgb888))
155     {
156         return -RT_ERROR;
157     }
158 
159     /* Disable non visible lines : from line 390 to 1023 (634 lines) */
160     if (HAL_OK != HAL_GFXMMU_DisableLutLines(&GfxmmuHandle, 390, 634))
161     {
162         return -RT_ERROR;
163     }
164 
165     /**********************/
166     /* LTDC CONFIGURATION */
167     /**********************/
168     /* LTDC initialization */
169     __HAL_LTDC_RESET_HANDLE_STATE(&LtdcHandle);
170     LtdcHandle.Instance = LTDC;
171     LtdcHandle.Init.HSPolarity         = LTDC_HSPOLARITY_AL;
172     LtdcHandle.Init.VSPolarity         = LTDC_VSPOLARITY_AL;
173     LtdcHandle.Init.DEPolarity         = LTDC_DEPOLARITY_AL;
174     LtdcHandle.Init.PCPolarity         = LTDC_PCPOLARITY_IPC;
175     /* HSYNC width - 1 */
176     LtdcHandle.Init.HorizontalSync     = 0;
177     /* VSYNC width - 1 */
178     LtdcHandle.Init.VerticalSync       = 0;
179     /* HSYNC width + HBP - 1 */
180     LtdcHandle.Init.AccumulatedHBP     = 1;
181     /* VSYNC width + VBP - 1 */
182     LtdcHandle.Init.AccumulatedVBP     = 1;
183     /* HSYNC width + HBP + Active width - 1 */
184     LtdcHandle.Init.AccumulatedActiveW = 391;
185     /* VSYNC width + VBP + Active height - 1 */
186     LtdcHandle.Init.AccumulatedActiveH = 391;
187     /* HSYNC width + HBP + Active width + HFP - 1 */
188     LtdcHandle.Init.TotalWidth         = 392;
189     /* VSYNC width + VBP + Active height + VFP - 1 */
190     LtdcHandle.Init.TotalHeigh         = 392;
191     LtdcHandle.Init.Backcolor.Red      = 0;
192     LtdcHandle.Init.Backcolor.Green    = 0;
193     LtdcHandle.Init.Backcolor.Blue     = 0;
194     LtdcHandle.Init.Backcolor.Reserved = 0xFF;
195     if (HAL_LTDC_Init(&LtdcHandle) != HAL_OK)
196     {
197         return -RT_ERROR;
198     }
199 
200     /* LTDC layer 1 configuration */
201     LayerCfg.WindowX0        = 0;
202     LayerCfg.WindowX1        = 390;
203     LayerCfg.WindowY0        = 0;
204     LayerCfg.WindowY1        = 390;
205     LayerCfg.PixelFormat     = LTDC_PIXEL_FORMAT_RGB888;
206     LayerCfg.Alpha           = 0xFF;
207     LayerCfg.Alpha0          = 0;
208     LayerCfg.BlendingFactor1 = LTDC_BLENDING_FACTOR1_PAxCA;
209     LayerCfg.BlendingFactor2 = LTDC_BLENDING_FACTOR2_PAxCA;
210     LayerCfg.FBStartAdress   = LAYER_ADDRESS;
211     /* virtual frame buffer contains 768 pixels per line for 24bpp */
212     /* (192 blocs * 16) / (24bpp/3) = 1024 pixels per ligne        */
213     LayerCfg.ImageWidth      = 1024;
214     LayerCfg.ImageHeight     = 390;
215     LayerCfg.Backcolor.Red   = 0;
216     LayerCfg.Backcolor.Green = 0;
217     LayerCfg.Backcolor.Blue  = 0;
218     LayerCfg.Backcolor.Reserved = 0xFF;
219     if (HAL_LTDC_ConfigLayer(&LtdcHandle, &LayerCfg, LTDC_LAYER_1) != HAL_OK)
220     {
221         return -RT_ERROR;
222     }
223 
224     /*********************/
225     /* DSI CONFIGURATION */
226     /*********************/
227 
228     /* DSI initialization */
229     __HAL_DSI_RESET_HANDLE_STATE(&DsiHandle);
230     DsiHandle.Instance = DSI;
231     DsiHandle.Init.AutomaticClockLaneControl = DSI_AUTO_CLK_LANE_CTRL_DISABLE;
232     /* We have 1 data lane at 500Mbps => lane byte clock at 500/8 = 62,5 MHZ */
233     /* We want TX escape clock at arround 20MHz and under 20MHz so clock division is set to 4 */
234     DsiHandle.Init.TXEscapeCkdiv             = 4;
235     DsiHandle.Init.NumberOfLanes             = DSI_ONE_DATA_LANE;
236     /* We have HSE value at 16 Mhz and we want data lane at 500Mbps */
237     dsiPllInit.PLLNDIV = 20;
238     dsiPllInit.PLLIDF  = DSI_PLL_IN_DIV1;
239     dsiPllInit.PLLODF  = DSI_PLL_OUT_DIV2;
240     if (HAL_DSI_Init(&DsiHandle, &dsiPllInit) != HAL_OK)
241     {
242         return -RT_ERROR;
243     }
244     /* Tclk-post + Tclk-trail + Ths-exit = [(60ns + 52xUI) + (60ns) + (300ns)]/16ns */
245     PhyTimings.ClockLaneHS2LPTime  = 33;
246     /* Tlpx + (Tclk-prepare + Tclk-zero) + Tclk-pre = [150ns + 300ns + 8xUI]/16ns */
247     PhyTimings.ClockLaneLP2HSTime  = 30;
248     /* Ths-trail + Ths-exit = [(60ns + 4xUI) + 100ns]/16ns */
249     PhyTimings.DataLaneHS2LPTime   = 11;
250     /* Tlpx + (Ths-prepare + Ths-zero) + Ths-sync = [150ns + (145ns + 10xUI) + 8xUI]/16ns */
251     PhyTimings.DataLaneLP2HSTime   = 21;
252     PhyTimings.DataLaneMaxReadTime = 0;
253     PhyTimings.StopWaitTime        = 7;
254     if (HAL_DSI_ConfigPhyTimer(&DsiHandle, &PhyTimings) != HAL_OK)
255     {
256         return -RT_ERROR;
257     }
258 
259     HostTimeouts.TimeoutCkdiv                 = 1;
260     HostTimeouts.HighSpeedTransmissionTimeout = 0;
261     HostTimeouts.LowPowerReceptionTimeout     = 0;
262     HostTimeouts.HighSpeedReadTimeout         = 0;
263     HostTimeouts.LowPowerReadTimeout          = 0;
264     HostTimeouts.HighSpeedWriteTimeout        = 0;
265     HostTimeouts.HighSpeedWritePrespMode      = 0;
266     HostTimeouts.LowPowerWriteTimeout         = 0;
267     HostTimeouts.BTATimeout                   = 0;
268     if (HAL_DSI_ConfigHostTimeouts(&DsiHandle, &HostTimeouts) != HAL_OK)
269     {
270         return -RT_ERROR;
271     }
272 
273     LPCmd.LPGenShortWriteNoP  = DSI_LP_GSW0P_ENABLE;
274     LPCmd.LPGenShortWriteOneP = DSI_LP_GSW1P_ENABLE;
275     LPCmd.LPGenShortWriteTwoP = DSI_LP_GSW2P_ENABLE;
276     LPCmd.LPGenShortReadNoP   = DSI_LP_GSR0P_ENABLE;
277     LPCmd.LPGenShortReadOneP  = DSI_LP_GSR1P_ENABLE;
278     LPCmd.LPGenShortReadTwoP  = DSI_LP_GSR2P_ENABLE;
279     LPCmd.LPGenLongWrite      = DSI_LP_GLW_DISABLE;
280     LPCmd.LPDcsShortWriteNoP  = DSI_LP_DSW0P_ENABLE;
281     LPCmd.LPDcsShortWriteOneP = DSI_LP_DSW1P_ENABLE;
282     LPCmd.LPDcsShortReadNoP   = DSI_LP_DSR0P_ENABLE;
283     LPCmd.LPDcsLongWrite      = DSI_LP_DLW_DISABLE;
284     LPCmd.LPMaxReadPacket     = DSI_LP_MRDP_DISABLE;
285     LPCmd.AcknowledgeRequest  = DSI_ACKNOWLEDGE_DISABLE;
286     if (HAL_DSI_ConfigCommand(&DsiHandle, &LPCmd) != HAL_OK)
287     {
288         return -RT_ERROR;
289     }
290 
291     CmdCfg.VirtualChannelID      = 0;
292 #if LCD_BITS_PER_PIXEL == 16
293     CmdCfg.ColorCoding           = DSI_RGB565;
294 #else
295     CmdCfg.ColorCoding           = DSI_RGB888;
296 #endif
297     CmdCfg.CommandSize           = 390;
298     CmdCfg.TearingEffectSource   = DSI_TE_DSILINK;
299     CmdCfg.TearingEffectPolarity = DSI_TE_FALLING_EDGE;
300     CmdCfg.HSPolarity            = DSI_HSYNC_ACTIVE_LOW;
301     CmdCfg.VSPolarity            = DSI_VSYNC_ACTIVE_LOW;
302     CmdCfg.DEPolarity            = DSI_DATA_ENABLE_ACTIVE_HIGH;
303     CmdCfg.VSyncPol              = DSI_VSYNC_FALLING;
304     CmdCfg.AutomaticRefresh      = DSI_AR_ENABLE;
305     CmdCfg.TEAcknowledgeRequest  = DSI_TE_ACKNOWLEDGE_ENABLE;
306     if (HAL_DSI_ConfigAdaptedCommandMode(&DsiHandle, &CmdCfg) != HAL_OK)
307     {
308         return -RT_ERROR;
309     }
310 
311     /* Disable the Tearing Effect interrupt activated by default on previous function */
312     __HAL_DSI_DISABLE_IT(&DsiHandle, DSI_IT_TE);
313 
314     if (HAL_DSI_ConfigFlowControl(&DsiHandle, DSI_FLOW_CONTROL_BTA) != HAL_OK)
315     {
316         return -RT_ERROR;
317     }
318 
319     /* Enable DSI */
320     __HAL_DSI_ENABLE(&DsiHandle);
321 
322     /*************************/
323     /* LCD POWER ON SEQUENCE */
324     /*************************/
325     /* Step 1 */
326     /* Go to command 2 */
327     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0xFE, 0x01);
328     /* IC Frame rate control, set power, sw mapping, mux swithc timing command */
329     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x06, 0x62);
330     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x0E, 0x80);
331     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x0F, 0x80);
332     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x10, 0x71);
333     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x13, 0x81);
334     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x14, 0x81);
335     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x15, 0x82);
336     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x16, 0x82);
337     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x18, 0x88);
338     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x19, 0x55);
339     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x1A, 0x10);
340     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x1C, 0x99);
341     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x1D, 0x03);
342     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x1E, 0x03);
343     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x1F, 0x03);
344     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x20, 0x03);
345     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x25, 0x03);
346     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x26, 0x8D);
347     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x2A, 0x03);
348     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x2B, 0x8D);
349     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x36, 0x00);
350     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x37, 0x10);
351     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x3A, 0x00);
352     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x3B, 0x00);
353     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x3D, 0x20);
354     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x3F, 0x3A);
355     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x40, 0x30);
356     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x41, 0x1A);
357     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x42, 0x33);
358     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x43, 0x22);
359     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x44, 0x11);
360     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x45, 0x66);
361     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x46, 0x55);
362     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x47, 0x44);
363     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x4C, 0x33);
364     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x4D, 0x22);
365     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x4E, 0x11);
366     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x4F, 0x66);
367     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x50, 0x55);
368     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x51, 0x44);
369     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x57, 0x33);
370     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x6B, 0x1B);
371     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x70, 0x55);
372     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x74, 0x0C);
373 
374     /* Go to command 3 */
375     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0xFE, 0x02);
376     /* Set the VGMP/VGSP coltage control */
377     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x9B, 0x40);
378     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x9C, 0x00);
379     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x9D, 0x20);
380 
381     /* Go to command 4 */
382     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0xFE, 0x03);
383     /* Set the VGMP/VGSP coltage control */
384     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x9B, 0x40);
385     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x9C, 0x00);
386     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x9D, 0x20);
387 
388     /* Go to command 5 */
389     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0xFE, 0x04);
390     /* VSR command */
391     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x5D, 0x10);
392     /* VSR1 timing set */
393     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x00, 0x8D);
394     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x01, 0x00);
395     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x02, 0x01);
396     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x03, 0x01);
397     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x04, 0x10);
398     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x05, 0x01);
399     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x06, 0xA7);
400     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x07, 0x20);
401     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x08, 0x00);
402     /* VSR2 timing set */
403     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x09, 0xC2);
404     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x0A, 0x00);
405     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x0B, 0x02);
406     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x0C, 0x01);
407     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x0D, 0x40);
408     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x0E, 0x06);
409     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x0F, 0x01);
410     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x10, 0xA7);
411     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x11, 0x00);
412     /* VSR3 timing set */
413     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x12, 0xC2);
414     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x13, 0x00);
415     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x14, 0x02);
416     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x15, 0x01);
417     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x16, 0x40);
418     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x17, 0x07);
419     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x18, 0x01);
420     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x19, 0xA7);
421     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x1A, 0x00);
422     /* VSR4 timing set */
423     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x1B, 0x82);
424     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x1C, 0x00);
425     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x1D, 0xFF);
426     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x1E, 0x05);
427     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x1F, 0x60);
428     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x20, 0x02);
429     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x21, 0x01);
430     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x22, 0x7C);
431     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x23, 0x00);
432     /* VSR5 timing set */
433     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x24, 0xC2);
434     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x25, 0x00);
435     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x26, 0x04);
436     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x27, 0x02);
437     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x28, 0x70);
438     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x29, 0x05);
439     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x2A, 0x74);
440     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x2B, 0x8D);
441     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x2D, 0x00);
442     /* VSR6 timing set */
443     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x2F, 0xC2);
444     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x30, 0x00);
445     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x31, 0x04);
446     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x32, 0x02);
447     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x33, 0x70);
448     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x34, 0x07);
449     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x35, 0x74);
450     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x36, 0x8D);
451     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x37, 0x00);
452     /* VSR marping command */
453     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x5E, 0x20);
454     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x5F, 0x31);
455     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x60, 0x54);
456     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x61, 0x76);
457     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x62, 0x98);
458 
459     /* Go to command 6 */
460     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0xFE, 0x05);
461     /* Set the ELVSS voltage */
462     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x05, 0x17);
463     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x2A, 0x04);
464     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x91, 0x00);
465 
466     /* Go back in standard commands */
467     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0xFE, 0x00);
468 
469     /* Set the Pixel format */
470     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x3A, 0x07);
471 
472     /* Set tear off */
473     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, DSI_SET_TEAR_OFF, 0x0);
474 
475     /* Set DSI mode to internal timing added vs ORIGINAL for Command mode */
476     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0xC2, 0x0);
477 
478     /* Set memory address MODIFIED vs ORIGINAL */
479     {
480         uint8_t InitParam1[4] = {0x00, 0x04, 0x01, 0x89};
481         uint8_t InitParam2[4] = {0x00, 0x00, 0x01, 0x85};
482 
483         HAL_DSI_LongWrite(&DsiHandle, 0, DSI_DCS_LONG_PKT_WRITE, 4, DSI_SET_COLUMN_ADDRESS, InitParam1);
484         HAL_DSI_LongWrite(&DsiHandle, 0, DSI_DCS_LONG_PKT_WRITE, 4, DSI_SET_PAGE_ADDRESS, InitParam2);
485     }
486 
487     /* Sleep out */
488     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P0, DSI_EXIT_SLEEP_MODE, 0x0);
489 
490     HAL_Delay(120);
491 
492     /* Set default Brightness */
493     HAL_DSI_ShortWrite(&DsiHandle, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x51, BRIGHTNESS_NORMAL);
494 
495     /* Set display on */
496     if (HAL_DSI_ShortWrite(&DsiHandle,
497                            0,
498                            DSI_DCS_SHORT_PKT_WRITE_P0,
499                            DSI_SET_DISPLAY_ON,
500                            0x0) != HAL_OK)
501     {
502         LOG_E("set display on failed");
503         return -RT_ERROR;
504     }
505 
506     /* Enable DSI Wrapper */
507     __HAL_DSI_WRAPPER_ENABLE(&DsiHandle);
508 
509     /* NVIC configuration for DSI interrupt that is now enabled */
510     HAL_NVIC_SetPriority(DSI_IRQn, 3, 0);
511     HAL_NVIC_EnableIRQ(DSI_IRQn);
512 
513     HAL_DSI_Refresh(&DsiHandle);
514     LOG_D("LCD init success");
515 
516     return RT_EOK;
517 }
518 
519 #if defined(LCD_BACKLIGHT_USING_PWM)
turn_on_lcd_backlight(void)520 void turn_on_lcd_backlight(void)
521 {
522     struct rt_device_pwm *pwm_dev;
523 
524     /* turn on the LCD backlight */
525     pwm_dev = (struct rt_device_pwm *)rt_device_find(PWM_DEV_NAME);
526     /* pwm frequency:100K = 10000ns */
527     rt_pwm_set(pwm_dev, PWM_DEV_CHANNEL, 10000, 10000);
528     rt_pwm_enable(pwm_dev, PWM_DEV_CHANNEL);
529 }
530 #elif defined(LCD_BACKLIGHT_USING_GPIO)
turn_on_lcd_backlight(void)531 void turn_on_lcd_backlight(void)
532 {
533     rt_pin_mode(LCD_BL_GPIO_NUM, PIN_MODE_OUTPUT);
534 
535     rt_pin_write(LCD_BL_GPIO_NUM, PIN_HIGH);
536 }
537 #endif
538 
DSI_IRQHandler(void)539 void DSI_IRQHandler(void)
540 {
541     HAL_DSI_IRQHandler(&DsiHandle);
542 }
543 
HAL_DSI_EndOfRefreshCallback(DSI_HandleTypeDef * hdsi)544 void HAL_DSI_EndOfRefreshCallback(DSI_HandleTypeDef *hdsi)
545 {
546     rt_sem_release(&_lcd.lcd_lock);
547 }
548 
549 #ifdef RT_USING_DEVICE_OPS
550 const static struct rt_device_ops lcd_ops =
551 {
552     drv_lcd_init,
553     RT_NULL,
554     RT_NULL,
555     RT_NULL,
556     RT_NULL,
557     drv_lcd_control
558 };
559 #endif
560 
drv_lcd_hw_init(void)561 int drv_lcd_hw_init(void)
562 {
563     rt_err_t result = RT_EOK;
564     struct rt_device *device = &_lcd.parent;
565 
566     /* memset _lcd to zero */
567     memset(&_lcd, 0x00, sizeof(_lcd));
568 
569     /* init lcd_lock semaphore */
570     result = rt_sem_init(&_lcd.lcd_lock, "lcd_lock", 0, RT_IPC_FLAG_FIFO);
571     if (result != RT_EOK)
572     {
573         LOG_E("init semaphore failed!\n");
574         result = -RT_ENOMEM;
575         goto __exit;
576     }
577 
578     /* config LCD dev info */
579     _lcd.lcd_info.height = LCD_HEIGHT;
580     _lcd.lcd_info.width = LCD_WIDTH;
581     _lcd.lcd_info.bits_per_pixel = LCD_BITS_PER_PIXEL;
582     _lcd.lcd_info.pixel_format = LCD_PIXEL_FORMAT;
583 
584     /* malloc memory */
585     _lcd.lcd_info.framebuffer = rt_malloc_align(LCD_DSI_BUF_SIZE, 16);
586     _lcd.front_buf = rt_malloc_align(LCD_DSI_BUF_SIZE_ROUND, 16);
587     if (_lcd.lcd_info.framebuffer == RT_NULL || _lcd.front_buf == RT_NULL)
588     {
589         LOG_E("init frame buffer failed!\n");
590         result = -RT_ENOMEM;
591         goto __exit;
592     }
593 
594     /* memset buff to 0xFF */
595     memset(_lcd.lcd_info.framebuffer, 0xFF, LCD_DSI_BUF_SIZE);
596     memset(_lcd.front_buf, 0xFF, LCD_DSI_BUF_SIZE_ROUND);
597 
598     device->type    = RT_Device_Class_Graphic;
599 #ifdef RT_USING_DEVICE_OPS
600     device->ops     = &lcd_ops;
601 #else
602     device->init    = drv_lcd_init;
603     device->control = drv_lcd_control;
604 #endif
605 
606     /* register lcd device */
607     rt_device_register(device, "lcd_dsi", RT_DEVICE_FLAG_RDWR);
608 
609     /* init stm32 LTDC */
610     if (stm32_lcd_init(&_lcd) != RT_EOK)
611     {
612         result = -RT_ERROR;
613         goto __exit;
614     }
615     else
616     {
617         turn_on_lcd_backlight();
618     }
619 
620 __exit:
621     if (result != RT_EOK)
622     {
623         rt_sem_delete(&_lcd.lcd_lock);
624 
625         if (_lcd.lcd_info.framebuffer)
626         {
627             rt_free(_lcd.lcd_info.framebuffer);
628         }
629 
630         if (_lcd.front_buf)
631         {
632 
633             rt_free(_lcd.front_buf);
634         }
635     }
636     return result;
637 }
638 INIT_DEVICE_EXPORT(drv_lcd_hw_init);
639 
640 #if defined(PKG_USING_GUIENGINE)
641 
642 #include <rtgui/driver.h>
graphic_device_init(void)643 int graphic_device_init(void)
644 {
645     struct rt_device *device;
646     device = rt_device_find("lcd_dsi");
647     if (device)
648     {
649         rtgui_graphic_set_device(device);
650     }
651 
652     return 0;
653 }
654 INIT_ENV_EXPORT(graphic_device_init);
655 #endif
656 
657 #ifdef DRV_DEBUG
658 #ifdef FINSH_USING_MSH
lcd_dsi_test()659 int lcd_dsi_test()
660 {
661     struct drv_lcd_dsi_device *lcd;
662     lcd = (struct drv_lcd_dsi_device *)rt_device_find("lcd_dsi");
663     rt_uint8_t *ptr = lcd->lcd_info.framebuffer;
664     while (1)
665     {
666         /* red */
667         for (unsigned long long i = 0; i < LCD_DSI_BUF_SIZE/4; i++)
668         {
669             ptr[4 * i] = 0x00;
670             ptr[4 * i + 1] = 0x00;
671             ptr[4 * i + 2] = 0xFF;
672             ptr[4 * i + 3] = 0xFF;
673         }
674         rt_device_control(&lcd->parent, RTGRAPHIC_CTRL_RECT_UPDATE, RT_NULL);
675         rt_thread_mdelay(1000);
676 
677         /* green */
678         for (int i = 0; i < LCD_DSI_BUF_SIZE/4; i++)
679         {
680             ptr[4 * i] = 0x00;
681             ptr[4 * i + 1] = 0xFF;
682             ptr[4 * i + 2] = 0x00;
683             ptr[4 * i + 3] = 0xFF;
684         }
685         rt_device_control(&lcd->parent, RTGRAPHIC_CTRL_RECT_UPDATE, RT_NULL);
686         rt_thread_mdelay(1000);
687 
688         /* blue */
689         for (int i = 0; i < LCD_DSI_BUF_SIZE/4; i++)
690         {
691             ptr[4 * i] = 0xFF;
692             ptr[4 * i + 1] = 0x00;
693             ptr[4 * i + 2] = 0x00;
694             ptr[4 * i + 3] = 0xFF;
695         }
696         rt_device_control(&lcd->parent, RTGRAPHIC_CTRL_RECT_UPDATE, RT_NULL);
697         rt_thread_mdelay(1000);
698     }
699 }
700 MSH_CMD_EXPORT(lcd_dsi_test, lcd_dsi_test);
701 
702 //draw a line in screen
line()703 void line()
704 {
705     struct drv_lcd_dsi_device *lcd;
706     lcd = (struct drv_lcd_dsi_device *)rt_device_find("lcd_dsi");
707     rt_uint8_t *ptr = lcd->lcd_info.framebuffer;
708 
709         /* red */
710         for (unsigned long long i = LCD_DSI_BUF_SIZE/4/2; i <LCD_DSI_BUF_SIZE/4/2+390; i++)
711         {
712                 ptr[4 * i] = 0x00;
713                 ptr[4 * i + 1] = 0x00;
714                 ptr[4 * i + 2] = 0xFF;
715                 ptr[4 * i + 3] = 0xFF;
716         }
717         rt_device_control(&lcd->parent, RTGRAPHIC_CTRL_RECT_UPDATE, RT_NULL);
718 
719 
720 }
721 MSH_CMD_EXPORT(line, line);
722 
723 #endif /* FINSH_USING_MSH */
724 #endif /* DRV_DEBUG */
725 #endif /* BSP_USING_LCD */
726