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