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  * 2018-04-12     RT-Thread    the first version
9  * 2023-09-02     zbtrs        support sdl2
10  */
11 
12 #include "rtthread.h"
13 #include <rthw.h>
14 #include <string.h>
15 #include <stdatomic.h>
16 
17 #include "interrupt.h"
18 #include "mmu.h"
19 #include "cache.h"
20 
21 #ifdef BSP_USING_LCD
22 
23 #include "drv_lcd.h"
24 #include "lcd_cfg.h"
25 
26 #ifdef RT_USING_SMART
27 #include <page.h>
28 #include <lwp_user_mm.h>
29 #endif
30 
31 #include <video/sunxi_display2.h>
32 #include <dfs_file.h>
33 #include "dev_disp.h"
34 
35 #define DEFAULT_SCREEN (0)
36 
37 #define LCD_DRV_FB_SZ (lcd_drv->lcd_info.width * lcd_drv->lcd_info.height * sizeof(rt_uint32_t))
38 
39 
40 enum state_buff
41 {
42     EMPTY,
43     FULL
44 };
45 
46 enum lcd_evt
47 {
48     LCD_EVT_VSYNC = 1,
49 };
50 
51 struct buff_info
52 {
53     rt_uint32_t *buff;
54     rt_uint32_t *buff_phy;
55     enum state_buff status;
56 };
57 
58 /* kind of a candidate for the official lcd driver framework */
59 struct lcd_device
60 {
61     struct rt_device lcd;
62     struct rt_device fb;
63     struct rt_device_graphic_info lcd_info; /* rtdef.h */
64     struct rt_event lcd_evt;
65     int use_screen; /* screen index */
66     void *framebuffer;
67     void *framebuffer_phy;
68 
69     atomic_uint refresh_flag;        /* atom flag,  0: nothing. 1:framebuffer ==> front_buf. 2:back_buf ==> front_buf.  */
70     struct buff_info front_buf_info; /* TCON hardware framebuffer */
71     struct buff_info back_buf_info;  /* rotate swap framebuffer */
72 
73     const struct lcd_cfg_panel_info *panel;
74 };
75 typedef struct lcd_device *lcd_device_t;
76 
77 static struct disp_layer_config layer_cfg;
78 static struct lcd_device _lcd_device;
79 static const struct lcd_cfg_panel_info *_panel;
80 static int lcd_status = 0;
81 static rt_uint8_t lcd_bn = 80;
82 #define LCD_PWM_DEV_CHANNEL 1
83 
84 extern void rt_hw_cpu_dcache_clean(void *addr, int size);
85 extern int disp_ioctl(int cmd, void *arg);
86 extern int disp_probe(void);
87 
88 struct lcd_device *g_lcd = RT_NULL;
89 
90 /* set up the lcd pin function */
lcd_gpio_config(void)91 static void lcd_gpio_config(void)
92 {
93     int i;
94     gpio_pin_t pin;
95     gpio_muxsel_t function_index;
96     gpio_driving_level_t level;
97 
98     if (_panel->bl_pin >= 0)
99     {
100         hal_gpio_set_direction(_panel->bl_pin, GPIO_DIRECTION_OUTPUT); // bl_pin
101         hal_gpio_set_driving_level(_panel->bl_pin, 3);
102         hal_gpio_set_data(_panel->bl_pin, _panel->bl_level);
103     }
104 
105     if (_panel->pwr_pin >= 0)
106     {
107         hal_gpio_set_direction(_panel->pwr_pin, GPIO_DIRECTION_OUTPUT); // pwr_pin
108         hal_gpio_set_driving_level(_panel->pwr_pin, 3);
109         hal_gpio_set_data(_panel->pwr_pin, 0);
110         rt_thread_delay(10);
111         hal_gpio_set_data(_panel->pwr_pin, _panel->pwr_level);
112         rt_thread_delay(10);
113         lcd_status = _panel->pwr_level;
114     }
115 
116     if (_panel->bl_mode == 0)
117     {
118         hal_gpio_set_direction(_panel->bl_gpio_pin, GPIO_DIRECTION_OUTPUT);
119         hal_gpio_set_driving_level(_panel->bl_gpio_pin, 3);
120         hal_gpio_set_data(_panel->bl_gpio_pin, _panel->bl_gpio_level);
121     }
122     else
123     {
124         lcd_bn = _panel->bl_pwm_val;
125         set_lcd_backlight(lcd_bn);
126     }
127 }
128 
lcd_get_framebuffer(void * dev)129 void *lcd_get_framebuffer(void *dev)
130 {
131     return ((struct lcd_device *)dev)->framebuffer;
132 }
133 
lcd_vsync_event_process(u32 sel)134 s32 lcd_vsync_event_process(u32 sel)
135 {
136     lcd_device_t lcd_drv = &_lcd_device;
137     uint32_t refresh_flag = atomic_exchange(&lcd_drv->refresh_flag, 0); // read-modify-write, read & clean.
138 
139     if (refresh_flag != 0)
140     {
141         uint32_t len = (uint32_t)lcd_drv->lcd_info.width * lcd_drv->lcd_info.height * (lcd_drv->lcd_info.bits_per_pixel / 8);
142         uint32_t len_stage1 = 1024;
143         void *dst = lcd_drv->front_buf_info.buff;
144         const void *src = lcd_drv->framebuffer;
145 
146         if (refresh_flag == 1)
147         {
148             src = lcd_drv->framebuffer;
149         }
150         else if (refresh_flag == 2)
151         {
152             src = lcd_drv->back_buf_info.buff;
153         }
154         else
155         {
156             // TODO: error
157         }
158 
159         memcpy((uint32_t *)dst, (uint32_t *)src, len_stage1);
160         rt_hw_cpu_dcache_clean(dst, len_stage1);
161 
162         memcpy((uint32_t *)(dst + len_stage1), (uint32_t *)(src + len_stage1), len - len_stage1);
163         rt_hw_cpu_dcache_clean((uint32_t *)(dst + len_stage1), len - len_stage1);
164 
165         rt_event_send(&lcd_drv->lcd_evt, LCD_EVT_VSYNC);
166     }
167 
168     rt_event_send(&lcd_drv->lcd_evt, LCD_EVT_VSYNC);
169 }
170 
_framebuffer_rotate_mirror(void * src_buf,void * dst_buf,const struct rt_device_graphic_info * lcd_info,const struct lcd_cfg_panel_info * _panel_info)171 static void _framebuffer_rotate_mirror(void *src_buf, void *dst_buf,
172                                        const struct rt_device_graphic_info *lcd_info, const struct lcd_cfg_panel_info *_panel_info)
173 {
174     lcd_device_t lcd_drv = &_lcd_device;
175     memcpy(dst_buf, src_buf, LCD_DRV_FB_SZ);
176 }
177 
178 /* Multi-layer is not supported now. */
179 #ifdef GUIENGINE_USING_MULTI_LAYER
180 #include <rtgui/rtgui_layer.h>
181 struct debe_info
182 {
183     int index;
184     void *buffer;
185     rt_uint32_t bf_size;
186 };
187 static struct debe_info _debe_use[3];
188 #endif
189 
190 /* pixel format, only 565 (2 bytes) or 666 (4 bytes) are supported */
_lcd_format_get(rt_uint8_t pixel_format)191 static inline int _lcd_format_get(rt_uint8_t pixel_format)
192 {
193     switch (pixel_format)
194     {
195     case RTGRAPHIC_PIXEL_FORMAT_RGB565:
196         return DISP_FORMAT_RGB_565;
197     case RTGRAPHIC_PIXEL_FORMAT_ARGB888:
198         return DISP_FORMAT_ARGB_8888;
199     default:
200         return -1;
201     }
202 }
203 
_lcd_drv_init(lcd_device_t lcd_drv)204 static int _lcd_drv_init(lcd_device_t lcd_drv)
205 {
206     unsigned long arg[6] = {0};
207     void *framebuffer = RT_NULL;
208     void *frontbuf = RT_NULL;
209     void *backbuf = RT_NULL;
210 
211     /*
212      * The event is used for the synchronization between updating the
213      * framebuffer and flushing the screen.
214      */
215     rt_event_init(&lcd_drv->lcd_evt, "lcd_evt", RT_IPC_FLAG_FIFO);
216 
217     /* the lcd device information defined by RT-Thread */
218     arg[0] = lcd_drv->use_screen;
219     lcd_drv->lcd_info.width = (rt_uint16_t)disp_ioctl(DISP_GET_SCN_WIDTH, arg);
220     lcd_drv->lcd_info.height = (rt_uint16_t)disp_ioctl(DISP_GET_SCN_HEIGHT, arg);
221     lcd_drv->lcd_info.bits_per_pixel = 32;
222     lcd_drv->lcd_info.pixel_format = RTGRAPHIC_PIXEL_FORMAT_ARGB888; /* should be coherent to adding layers */
223 
224     /* allocate the framebuffer, the front buffer and the back buffer */
225     /* framebuffer */
226 #ifdef RT_USING_SMART
227     framebuffer = rt_pages_alloc(rt_page_bits(LCD_DRV_FB_SZ));
228 #else
229     framebuffer = rt_malloc(LCD_DRV_FB_SZ);
230 #endif
231     if (!framebuffer)
232     {
233         rt_kprintf("malloc framebuffer fail\n");
234         goto out;
235     }
236     lcd_drv->lcd_info.framebuffer = framebuffer;
237     lcd_drv->framebuffer = framebuffer;
238     lcd_drv->framebuffer_phy = (void *)((size_t)framebuffer + PV_OFFSET);
239     memset(framebuffer, 0, LCD_DRV_FB_SZ);
240     rt_hw_cpu_dcache_clean(lcd_drv->framebuffer, LCD_DRV_FB_SZ);
241 #ifdef RT_USING_SMART
242     frontbuf = rt_pages_alloc(rt_page_bits(LCD_DRV_FB_SZ));
243 #else
244     frontbuf = rt_malloc(LCD_DRV_FB_SZ);
245 #endif
246     if (!frontbuf)
247     {
248         rt_kprintf("malloc frontbuf fail\n");
249         goto out;
250     }
251     lcd_drv->front_buf_info.buff = frontbuf;
252     lcd_drv->front_buf_info.buff_phy = (void *)((size_t)frontbuf + PV_OFFSET);
253     memset(frontbuf, 0, LCD_DRV_FB_SZ);
254     rt_hw_cpu_dcache_clean(lcd_drv->front_buf_info.buff, LCD_DRV_FB_SZ);
255 
256     if ((lcd_drv->panel) && (lcd_drv->panel->swap_flag != 0))
257     {
258         /* backbuf */
259 #ifdef RT_USING_SMART
260         backbuf = rt_pages_alloc(rt_page_bits(LCD_DRV_FB_SZ));
261 #else
262         backbuf = rt_malloc(LCD_DRV_FB_SZ);
263 #endif
264         if (!backbuf)
265         {
266             rt_kprintf("malloc backbuf fail\n");
267             goto out;
268         }
269         lcd_drv->back_buf_info.buff = backbuf;
270         lcd_drv->back_buf_info.buff_phy = (void *)((size_t)backbuf + PV_OFFSET);
271         memset(backbuf, 0, LCD_DRV_FB_SZ);
272         rt_hw_cpu_dcache_clean(lcd_drv->back_buf_info.buff, LCD_DRV_FB_SZ);
273     }
274 
275     return RT_EOK;
276 out:
277     if (framebuffer)
278     {
279 #ifdef RT_USING_SMART
280         rt_free_align(framebuffer);
281 #else
282         rt_free(framebuffer);
283 #endif
284     }
285 
286     if (frontbuf)
287     {
288 #ifdef RT_USING_SMART
289         rt_free_align(frontbuf);
290 #else
291         rt_free(frontbuf);
292 #endif
293     }
294 
295     if (backbuf)
296     {
297 #ifdef RT_USING_SMART
298         rt_free_align(backbuf);
299 #else
300         rt_free(backbuf);
301 #endif
302     }
303 
304     return -RT_ERROR;
305 }
306 
_lcd_layer_init(lcd_device_t lcd_drv)307 static int _lcd_layer_init(lcd_device_t lcd_drv)
308 {
309     int format;
310     int ret;
311     unsigned long arg[6] = {0};
312 
313     format = _lcd_format_get(lcd_drv->lcd_info.pixel_format);
314     if (format < 0)
315     {
316         rt_kprintf("lcd init faile pixel_format:%d\n", lcd_drv->lcd_info.pixel_format);
317         return -RT_ERROR;
318     }
319 
320     // config layer info
321     memset(&layer_cfg, 0, sizeof(layer_cfg));
322     layer_cfg.info.b_trd_out = 0;
323     layer_cfg.channel = de_feat_get_num_vi_chns(lcd_drv->use_screen); // skip vi channel
324     layer_cfg.layer_id = 0;
325     layer_cfg.info.fb.format = format;
326     layer_cfg.info.fb.crop.x = 0;
327     layer_cfg.info.fb.crop.y = 0;
328     layer_cfg.info.fb.crop.width = lcd_drv->lcd_info.width;
329     layer_cfg.info.fb.crop.height = lcd_drv->lcd_info.height;
330     layer_cfg.info.fb.crop.width = layer_cfg.info.fb.crop.width << 32;
331     layer_cfg.info.fb.crop.height = layer_cfg.info.fb.crop.height << 32;
332     layer_cfg.info.fb.align[0] = 4;
333     layer_cfg.info.mode = 0; // LAYER_MODE_BUFFER
334     layer_cfg.info.alpha_mode = 1;
335     layer_cfg.info.alpha_value = 255;
336     layer_cfg.info.zorder = 0;
337     layer_cfg.info.screen_win.x = 0;
338     layer_cfg.info.screen_win.y = 0;
339     layer_cfg.info.screen_win.width = lcd_drv->lcd_info.width;
340     layer_cfg.info.screen_win.height = lcd_drv->lcd_info.height;
341 
342     layer_cfg.info.fb.size[0].width = lcd_drv->lcd_info.width;
343     layer_cfg.info.fb.size[0].height = lcd_drv->lcd_info.height;
344     layer_cfg.info.fb.size[1].width = lcd_drv->lcd_info.width;
345     layer_cfg.info.fb.size[1].height = lcd_drv->lcd_info.height;
346     layer_cfg.info.fb.size[2].width = lcd_drv->lcd_info.width;
347     layer_cfg.info.fb.size[2].height = lcd_drv->lcd_info.height;
348 
349     layer_cfg.info.fb.addr[0] = (size_t)lcd_drv->front_buf_info.buff_phy;
350 
351     /* INTERLEAVED */
352     layer_cfg.info.fb.addr[0] = (unsigned long long)(layer_cfg.info.fb.addr[0] + lcd_drv->lcd_info.width * lcd_drv->lcd_info.height / 3 * 0);
353     layer_cfg.info.fb.addr[1] = (unsigned long long)(layer_cfg.info.fb.addr[0] + lcd_drv->lcd_info.width * lcd_drv->lcd_info.height / 3 * 1);
354     layer_cfg.info.fb.addr[2] = (unsigned long long)(layer_cfg.info.fb.addr[0] + lcd_drv->lcd_info.width * lcd_drv->lcd_info.height / 3 * 2);
355     layer_cfg.info.fb.trd_right_addr[0] = (unsigned int)(layer_cfg.info.fb.addr[0] + lcd_drv->lcd_info.width * lcd_drv->lcd_info.height * 3 / 2);
356     layer_cfg.info.fb.trd_right_addr[1] = (unsigned int)(layer_cfg.info.fb.trd_right_addr[0] + lcd_drv->lcd_info.width * lcd_drv->lcd_info.height);
357     layer_cfg.info.fb.trd_right_addr[2] = (unsigned int)(layer_cfg.info.fb.trd_right_addr[0] + lcd_drv->lcd_info.width * lcd_drv->lcd_info.height * 3 / 2);
358 
359     layer_cfg.enable = 1;
360 
361     arg[0] = lcd_drv->use_screen;
362     arg[1] = (unsigned long)&layer_cfg;
363     arg[2] = 1;
364     arg[3] = 0;
365     ret = disp_ioctl(DISP_LAYER_SET_CONFIG, (void *)arg);
366     if (0 != ret)
367     {
368         rt_kprintf("fail to set layer cfg %d\n", ret);
369         return -RT_ERROR;
370     }
371 
372     arg[0] = lcd_drv->use_screen;
373     arg[1] = 1; // enable
374     arg[2] = 0;
375     ret = disp_ioctl(DISP_VSYNC_EVENT_EN, (void *)arg);
376     if (0 != ret)
377     {
378         rt_kprintf("fail to set vsync enable %d\n", ret);
379         return -RT_ERROR;
380     }
381 
382     return RT_EOK;
383 }
384 
385 /* Add the first layer, then enable the interrupt */
rt_lcd_init(rt_device_t dev)386 static rt_err_t rt_lcd_init(rt_device_t dev)
387 {
388     lcd_device_t lcd_drv = (lcd_device_t)dev;
389 
390     RT_ASSERT(lcd_drv != RT_NULL);
391 
392     static int lcd_init = 0;
393 
394     if (lcd_init)
395     {
396         return RT_EOK;
397     }
398     lcd_init = 1;
399 
400     _panel = load_lcd_config_from_xml();
401     lcd_drv->panel = _panel;
402 
403     if (disp_probe() != 0)
404     {
405         rt_kprintf("lcd disp probe failure\n");
406         return -RT_ERROR;
407     }
408 
409     lcd_gpio_config();
410 
411     if (_lcd_drv_init(lcd_drv) != RT_EOK)
412     {
413         rt_kprintf("lcd drv init failure\n");
414         return -RT_ERROR;
415     }
416 
417     if (_lcd_layer_init(lcd_drv) != RT_EOK)
418     {
419         rt_kprintf("disp layer init failure\n");
420         return -RT_ERROR;
421     }
422 
423     return RT_EOK;
424 }
425 
turn_on_lcd_backlight(void)426 void turn_on_lcd_backlight(void)
427 {
428     if (_panel->bl_pin >= 0)
429     {
430         hal_gpio_set_direction(_panel->bl_pin, GPIO_DIRECTION_OUTPUT); // bl_pin
431         hal_gpio_set_driving_level(_panel->bl_pin, 3);
432         hal_gpio_set_data(_panel->bl_pin, 1);
433     }
434 
435     if (_panel->pwr_pin >= 0)
436     {
437         hal_gpio_set_direction(_panel->pwr_pin, GPIO_DIRECTION_OUTPUT); // pwr_pin
438         hal_gpio_set_driving_level(_panel->pwr_pin, 3);
439         hal_gpio_set_data(_panel->pwr_pin, 1);
440     }
441     if (_panel->bl_mode == 0)
442     {
443         hal_gpio_set_direction(_panel->bl_gpio_pin, GPIO_DIRECTION_OUTPUT);
444         hal_gpio_set_driving_level(_panel->bl_gpio_pin, 3);
445         hal_gpio_set_data(_panel->bl_gpio_pin, 1);
446     }
447     else
448     {
449         struct rt_device_pwm *pwm_dev;
450         pwm_dev = (struct rt_device_pwm *)rt_device_find(_panel->bl_pwm_name);
451         if (pwm_dev == RT_NULL)
452         {
453             rt_kprintf("%s open fail\n", _panel->bl_pwm_name);
454             return;
455         }
456         rt_pwm_set(pwm_dev, LCD_PWM_DEV_CHANNEL, 1000000000 / _panel->bl_pwm_hz, lcd_bn * (10000000 / _panel->bl_pwm_hz));
457         rt_pwm_enable(pwm_dev, LCD_PWM_DEV_CHANNEL);
458     }
459     lcd_status = 1;
460 }
461 
turn_down_lcd_backlight(void)462 void turn_down_lcd_backlight(void)
463 {
464 
465     if (_panel->bl_pin >= 0)
466     {
467         hal_gpio_set_direction(_panel->bl_pin, GPIO_DIRECTION_OUTPUT); // bl_pin
468         hal_gpio_set_driving_level(_panel->bl_pin, 3);
469         hal_gpio_set_data(_panel->bl_pin, 0);
470     }
471 
472     if (_panel->pwr_pin >= 0)
473     {
474         hal_gpio_set_direction(_panel->pwr_pin, GPIO_DIRECTION_OUTPUT); // pwr_pin
475         hal_gpio_set_driving_level(_panel->pwr_pin, 3);
476         hal_gpio_set_data(_panel->pwr_pin, 0);
477     }
478     if (_panel->bl_mode == 0)
479     {
480         hal_gpio_set_direction(_panel->bl_gpio_pin, GPIO_DIRECTION_OUTPUT);
481         hal_gpio_set_driving_level(_panel->bl_gpio_pin, 3);
482         hal_gpio_set_data(_panel->bl_gpio_pin, 0);
483     }
484     else
485     {
486         struct rt_device_pwm *pwm_dev;
487         pwm_dev = (struct rt_device_pwm *)rt_device_find(_panel->bl_pwm_name);
488         if (pwm_dev == RT_NULL)
489         {
490             rt_kprintf("%s open fail\n", _panel->bl_pwm_name);
491             return;
492         }
493         rt_pwm_set(pwm_dev, LCD_PWM_DEV_CHANNEL, 1000000000 / _panel->bl_pwm_hz, 0 * (10000000 / _panel->bl_pwm_hz));
494         rt_pwm_enable(pwm_dev, LCD_PWM_DEV_CHANNEL);
495     }
496     lcd_status = 0;
497     return;
498 }
499 
set_lcd_backlight(rt_uint8_t value)500 void set_lcd_backlight(rt_uint8_t value)
501 {
502     struct rt_device_pwm *pwm_dev;
503     pwm_dev = (struct rt_device_pwm *)rt_device_find(_panel->bl_pwm_name);
504     if (pwm_dev == RT_NULL)
505     {
506         rt_kprintf("%s open fail\n", _panel->bl_pwm_name);
507         return;
508     }
509     rt_pwm_set(pwm_dev, LCD_PWM_DEV_CHANNEL, 1000000000 / _panel->bl_pwm_hz, value * (10000000 / _panel->bl_pwm_hz));
510     rt_pwm_enable(pwm_dev, LCD_PWM_DEV_CHANNEL);
511 }
512 
get_lcd_backlight(void)513 rt_uint8_t get_lcd_backlight(void)
514 {
515     int result = 0;
516     struct rt_device_pwm *pwm_dev;
517     struct rt_pwm_configuration cfg = {0};
518 
519     pwm_dev = (struct rt_device_pwm *)rt_device_find(_panel->bl_pwm_name);
520     cfg.channel = LCD_PWM_DEV_CHANNEL;
521     rt_pwm_get(pwm_dev, LCD_PWM_DEV_CHANNEL);
522 
523     return cfg.pulse / (10000000 / _panel->bl_pwm_hz);
524 }
525 
rt_lcd_control(rt_device_t dev,int cmd,void * args)526 static rt_err_t rt_lcd_control(rt_device_t dev, int cmd, void *args)
527 {
528     struct lcd_device *lcd_drv = (struct lcd_device *)dev;
529 
530     switch (cmd)
531     {
532     case RTGRAPHIC_CTRL_RECT_UPDATE:
533     {
534         unsigned long arg[6] = {0};
535         int ret;
536 
537         // clean event.
538         rt_event_recv(&lcd_drv->lcd_evt, LCD_EVT_VSYNC, RT_EVENT_FLAG_CLEAR | RT_EVENT_FLAG_OR, 0, NULL);
539 
540         // rotate and set refresh_flag
541         if ((lcd_drv->panel) && (lcd_drv->panel->swap_flag != 0))
542         {
543             _framebuffer_rotate_mirror(lcd_drv->framebuffer, lcd_drv->back_buf_info.buff, &lcd_drv->lcd_info, _panel);
544             rt_hw_cpu_dcache_clean(lcd_drv->back_buf_info.buff, LCD_DRV_FB_SZ);
545             atomic_store(&lcd_drv->refresh_flag, 2); // lcd_drv->refresh_flag = 2;
546         }
547         else
548         {
549             atomic_store(&lcd_drv->refresh_flag, 1); // lcd_drv->refresh_flag = 1;
550         }
551 
552         // wait irq
553         rt_err_t result = rt_event_recv(&lcd_drv->lcd_evt, LCD_EVT_VSYNC, RT_EVENT_FLAG_CLEAR | RT_EVENT_FLAG_OR, RT_TICK_PER_SECOND / 20, NULL);
554         if (result != RT_EOK)
555         {
556             rt_kprintf("RTGRAPHIC_CTRL_RECT_UPDATE wait LCD_EVT_VSYNC:%d\n", result);
557         }
558 
559         break;
560     }
561     case RTGRAPHIC_CTRL_POWERON:
562         if (lcd_status == 0)
563         {
564 #ifdef WATCH_APP_FWK_USING_SCREEN_MGT
565             extern void watch_screen_time_update(void);
566             watch_screen_time_update();
567 #endif
568             turn_on_lcd_backlight();
569             rt_kprintf("lcd driver control power on.\n");
570             lcd_status = 1;
571         }
572         break;
573     case RTGRAPHIC_CTRL_POWEROFF:
574         if (lcd_status == 1)
575         {
576             lcd_status = 0;
577             turn_down_lcd_backlight();
578             rt_kprintf("lcd driver control power off.\n");
579         }
580         break;
581     case RTGRAPHIC_CTRL_SET_BRIGHTNESS:
582         lcd_bn = *((rt_uint8_t *)args);
583         // TODO::if can SET_BRIGHTNESS
584         set_lcd_backlight(lcd_bn);
585         rt_kprintf("lcd driver control set brightness: %d.\n", lcd_bn);
586         break;
587 
588     case RTGRAPHIC_CTRL_GET_BRIGHTNESS:
589         lcd_bn = get_lcd_backlight();
590         *((rt_uint8_t *)args) = lcd_bn;
591         // TODO::if can GET_BRIGHTNESS
592         rt_kprintf("lcd driver control get brightness: %d.\n", lcd_bn);
593         break;
594     case RTGRAPHIC_CTRL_GET_INFO:
595         memcpy(args, &lcd_drv->lcd_info, sizeof(struct rt_device_graphic_info));
596         break;
597     case FBIOGET_FSCREENINFO:
598     {
599         struct fb_fix_screeninfo *info = (struct fb_fix_screeninfo *)args;
600         strncpy(info->id, "lcd", sizeof(info->id));
601         info->smem_len = LCD_DRV_FB_SZ;
602 #ifdef RT_USING_SMART
603         info->smem_start = (size_t)lwp_map_user_phy(lwp_self(), RT_NULL, lcd_drv->framebuffer_phy, info->smem_len, 1);
604 #else
605         info->smem_start = (size_t)lcd_drv->framebuffer_phy;
606 #endif
607         info->line_length = lcd_drv->lcd_info.width * sizeof(rt_uint32_t);
608         memset((void *)info->smem_start, 0, info->smem_len);
609     }
610     case RTGRAPHIC_CTRL_SET_MODE:
611         break;
612     }
613     return RT_EOK;
614 }
615 
fb_open(rt_device_t dev,rt_uint16_t oflag)616 static rt_err_t fb_open(rt_device_t dev,rt_uint16_t oflag)
617 {
618     return RT_EOK;
619 }
620 
fb_close(rt_device_t dev)621 static rt_err_t fb_close(rt_device_t dev)
622 {
623     return RT_EOK;
624 }
625 
fb_control(rt_device_t dev,int cmd,void * args)626 static rt_err_t fb_control(rt_device_t dev, int cmd, void *args)
627 {
628     switch(cmd) {
629         case FBIOGET_PIXELINFO:
630         {
631             int *fmt = (int *)args;
632             *fmt = RTGRAPHIC_PIXEL_FORMAT_ARGB888;
633             break;
634         }
635         case FBIOPAN_DISPLAY:
636         {
637             struct lcd_device *lcd_drv = g_lcd;
638             rt_hw_cpu_dcache_clean(lcd_drv->framebuffer, LCD_DRV_FB_SZ);
639             rt_lcd_control((rt_device_t)g_lcd, RTGRAPHIC_CTRL_RECT_UPDATE, RT_NULL);
640             break;
641         }
642         case FBIOGET_FSCREENINFO:
643         {
644             rt_lcd_control((rt_device_t)g_lcd,FBIOGET_FSCREENINFO,args);
645             break;
646         }
647         case FBIOGET_VSCREENINFO:
648         {
649             struct lcd_device *lcd_drv = g_lcd;
650             struct fb_var_screeninfo *info = (struct fb_var_screeninfo *)args;
651             info->xres = lcd_drv->lcd_info.width;
652             info->yres = lcd_drv->lcd_info.height;
653             break;
654         }
655         case RT_FIOMMAP2:
656         {
657             struct dfs_mmap2_args *mmap2 = (struct dfs_mmap2_args *)args;
658             if (mmap2)
659             {
660                 mmap2->ret = lwp_map_user_phy(lwp_self(),RT_NULL,g_lcd->framebuffer,mmap2->length,1);
661             }
662             else
663             {
664                 return -EIO;
665             }
666 
667             break;
668         }
669         default:
670             break;
671     }
672 
673     return RT_EOK;
674 }
675 
676 #ifdef RT_USING_DEVICE_OPS
677 const static struct rt_device_ops fb_ops =
678 {
679     RT_NULL,
680     fb_open,
681     fb_close,
682     RT_NULL,
683     RT_NULL,
684     fb_control
685 };
686 #endif
687 
688 /* register framebuffer device */
fb_init(rt_device_t fb)689 static int fb_init(rt_device_t fb)
690 {
691     static rt_bool_t fb_init_ok = RT_FALSE;
692 
693     if (fb_init_ok)
694     {
695         return 0;
696     }
697     RT_ASSERT(!rt_device_find("fb0"));
698     fb->type    = RT_Device_Class_Miscellaneous;
699 
700 #ifdef RT_USING_DEVICE_OPS
701     fb->ops     = &fb_ops;
702 #else
703 
704     fb->init    = RT_NULL;
705     fb->open    = fb_open;
706     fb->close   = fb_close;
707     fb->read    = RT_NULL;
708     fb->write   = RT_NULL;
709     fb->control = fb_control;
710     fb->user_data = RT_NULL;
711 #endif
712 
713     rt_device_register(fb,"fb0",RT_DEVICE_FLAG_RDWR);
714 
715     fb_init_ok = RT_TRUE;
716 
717     return RT_EOK;
718 }
719 
720 /* set up the 'lcd_device' and register it */
rt_hw_lcd_init(void)721 int rt_hw_lcd_init(void)
722 {
723     struct lcd_device *lcd_drv = &_lcd_device;
724 
725     g_lcd = lcd_drv;
726     /* the content of tcon control registers can be loaded from a xml file ? */
727     // _panel = load_config_from_xml();
728     memset(lcd_drv, 0, sizeof(struct lcd_device));
729 
730     lcd_drv->use_screen = DEFAULT_SCREEN;
731 
732     /* initialize device structure, the type of 'lcd' is 'rt_device' */
733     lcd_drv->lcd.type = RT_Device_Class_Graphic;
734     lcd_drv->lcd.init = rt_lcd_init;
735     lcd_drv->lcd.open = RT_NULL;
736     lcd_drv->lcd.close = RT_NULL;
737     lcd_drv->lcd.control = rt_lcd_control;
738     lcd_drv->lcd.user_data = (void *)&lcd_drv->lcd_info;
739 
740     /* register lcd device to RT-Thread */
741     rt_device_register(&lcd_drv->lcd, "lcd", RT_DEVICE_FLAG_RDWR);
742 
743     rt_lcd_init((rt_device_t)lcd_drv);
744 
745     if (fb_init(&(lcd_drv->fb)) != RT_EOK)
746     {
747         rt_kprintf("fb device init failure\n");
748         return -RT_ERROR;
749     }
750 
751     return RT_EOK;
752 }
753 // INIT_DEVICE_EXPORT(rt_hw_lcd_init);
754 
lcd_draw_point(int args,char * argv[])755 static int lcd_draw_point(int args, char *argv[])
756 {
757     struct lcd_device *lcd_drv = g_lcd;
758     int x = 0;
759     int y = 0;
760     int i, k;
761 
762     rt_kprintf("lcd_draw_point\n");
763 
764     x = atoi(argv[1]);
765     y = atoi(argv[2]);
766 
767     if (x >= lcd_drv->lcd_info.width)
768         x = lcd_drv->lcd_info.width - 1;
769     if (y >= lcd_drv->lcd_info.height)
770         y = lcd_drv->lcd_info.height - 1;
771     if (x < 0)
772         x = 0;
773     if (y < 0)
774         y = 0;
775 
776     rt_kprintf("Darw point is x:%d,y:%d\n", x, y);
777 
778     // memset(lcd->framebuffer, 0, sizeof(rt_uint32_t) * lcd_drv->lcd_info.width * lcd_drv->lcd_info.height);
779 
780     for (i = y - 100; i < y + 100; i++)
781     {
782         if (i < 0)
783             continue;
784         if (i >= lcd_drv->lcd_info.height)
785             break;
786         for (k = x - 100; k < x + 100; k++)
787         {
788             if (k < 0)
789                 continue;
790             if (k >= lcd_drv->lcd_info.width)
791                 break;
792 
793             *((uint32_t *)lcd_drv->framebuffer + lcd_drv->lcd_info.width * i + k) = 0xff00ff00;
794         }
795     }
796 
797     *((uint32_t *)lcd_drv->framebuffer + lcd_drv->lcd_info.width * y + x) = 0xffff0000;
798     // *((uint32_t *)lcd->framebuffer + lcd_drv->lcd_info.width * y + x + 2) = 0xff00ff00;
799 
800     rt_hw_cpu_dcache_clean(lcd_drv->framebuffer, LCD_DRV_FB_SZ);
801     rt_lcd_control((rt_device_t)g_lcd, RTGRAPHIC_CTRL_RECT_UPDATE, RT_NULL);
802 
803     return 0;
804 }
805 MSH_CMD_EXPORT(lcd_draw_point, draw a point on lcd);
806 
lcd_pwm_test(int argc,char ** argv)807 void lcd_pwm_test(int argc, char **argv)
808 {
809     set_lcd_backlight(atoi(argv[1]));
810 }
811 
812 MSH_CMD_EXPORT(lcd_pwm_test, set pwm);
813 #endif
814