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-03-12 ZYH first version
9 */
10
11
12 #include <rtthread.h>
13
14 #ifdef BSP_USING_LCD
15
16 #include <rtdevice.h>
17 #include "drv_lcd.h"
18 #include <board.h>
19 #include <gpiohs.h>
20 #include <drivers/dev_spi.h>
21 #include <spi.h>
22 #include <drv_io_config.h>
23 #include <rthw.h>
24 #include "dmalock.h"
25 #include "sleep.h"
26
27 #define DBG_TAG "LCD"
28 #define DBG_LVL DBG_WARNING
29 #include <rtdbg.h>
30
31 #define NO_OPERATION 0x00
32 #define SOFTWARE_RESET 0x01
33 #define READ_ID 0x04
34 #define READ_STATUS 0x09
35 #define READ_POWER_MODE 0x0A
36 #define READ_MADCTL 0x0B
37 #define READ_PIXEL_FORMAT 0x0C
38 #define READ_IMAGE_FORMAT 0x0D
39 #define READ_SIGNAL_MODE 0x0E
40 #define READ_SELT_DIAG_RESULT 0x0F
41 #define SLEEP_ON 0x10
42 #define SLEEP_OFF 0x11
43 #define PARTIAL_DISPALY_ON 0x12
44 #define NORMAL_DISPALY_ON 0x13
45 #define INVERSION_DISPALY_OFF 0x20
46 #define INVERSION_DISPALY_ON 0x21
47 #define GAMMA_SET 0x26
48 #define DISPALY_OFF 0x28
49 #define DISPALY_ON 0x29
50 #define HORIZONTAL_ADDRESS_SET 0x2A
51 #define VERTICAL_ADDRESS_SET 0x2B
52 #define MEMORY_WRITE 0x2C
53 #define COLOR_SET 0x2D
54 #define MEMORY_READ 0x2E
55 #define PARTIAL_AREA 0x30
56 #define VERTICAL_SCROL_DEFINE 0x33
57 #define TEAR_EFFECT_LINE_OFF 0x34
58 #define TEAR_EFFECT_LINE_ON 0x35
59 #define MEMORY_ACCESS_CTL 0x36
60 #define VERTICAL_SCROL_S_ADD 0x37
61 #define IDLE_MODE_OFF 0x38
62 #define IDLE_MODE_ON 0x39
63 #define PIXEL_FORMAT_SET 0x3A
64 #define WRITE_MEMORY_CONTINUE 0x3C
65 #define READ_MEMORY_CONTINUE 0x3E
66 #define SET_TEAR_SCANLINE 0x44
67 #define GET_SCANLINE 0x45
68 #define WRITE_BRIGHTNESS 0x51
69 #define READ_BRIGHTNESS 0x52
70 #define WRITE_CTRL_DISPALY 0x53
71 #define READ_CTRL_DISPALY 0x54
72 #define WRITE_BRIGHTNESS_CTL 0x55
73 #define READ_BRIGHTNESS_CTL 0x56
74 #define WRITE_MIN_BRIGHTNESS 0x5E
75 #define READ_MIN_BRIGHTNESS 0x5F
76 #define READ_ID1 0xDA
77 #define READ_ID2 0xDB
78 #define READ_ID3 0xDC
79 #define RGB_IF_SIGNAL_CTL 0xB0
80 #define NORMAL_FRAME_CTL 0xB1
81 #define IDLE_FRAME_CTL 0xB2
82 #define PARTIAL_FRAME_CTL 0xB3
83 #define INVERSION_CTL 0xB4
84 #define BLANK_PORCH_CTL 0xB5
85 #define DISPALY_FUNCTION_CTL 0xB6
86 #define ENTRY_MODE_SET 0xB7
87 #define BACKLIGHT_CTL1 0xB8
88 #define BACKLIGHT_CTL2 0xB9
89 #define BACKLIGHT_CTL3 0xBA
90 #define BACKLIGHT_CTL4 0xBB
91 #define BACKLIGHT_CTL5 0xBC
92 #define BACKLIGHT_CTL7 0xBE
93 #define BACKLIGHT_CTL8 0xBF
94 #define POWER_CTL1 0xC0
95 #define POWER_CTL2 0xC1
96 #define VCOM_CTL1 0xC5
97 #define VCOM_CTL2 0xC7
98 #define NV_MEMORY_WRITE 0xD0
99 #define NV_MEMORY_PROTECT_KEY 0xD1
100 #define NV_MEMORY_STATUS_READ 0xD2
101 #define READ_ID4 0xD3
102 #define POSITIVE_GAMMA_CORRECT 0xE0
103 #define NEGATIVE_GAMMA_CORRECT 0xE1
104 #define DIGITAL_GAMMA_CTL1 0xE2
105 #define DIGITAL_GAMMA_CTL2 0xE3
106 #define INTERFACE_CTL 0xF6
107
108 #define LCD_SPI_CHANNEL SPI_DEVICE_0
109 #define LCD_SPI_CHIP_SELECT SPI_CHIP_SELECT_0
110
111 #if defined(BSP_BOARD_K210_OPENMV_TEST)
112 #define LCD_SCAN_DIR DIR_YX_LRUD
113 #elif defined(BSP_BOARD_K210_DRACO)
114 #define LCD_SCAN_DIR DIR_YX_LRUD
115 #elif defined(BSP_BOARD_KD233)
116 #define LCD_SCAN_DIR (DIR_YX_RLUD | 0x08)
117 #elif defined(BSP_BOARD_USER)
118 /*user define.*/
119 #define LCD_SCAN_DIR DIR_YX_RLUD
120 #endif
121
122 typedef struct lcd_8080_device
123 {
124 struct rt_device parent;
125 struct rt_device_graphic_info lcd_info;
126 int spi_channel;
127 int cs;
128 int dc_pin;
129 #if BSP_LCD_RST_PIN >= 0
130 int rst_pin;
131 #endif
132 #if BSP_LCD_BACKLIGHT_PIN >= 0
133 int backlight_pin;
134 #endif
135 int dma_channel;
136 } * lcd_8080_device_t;
137
138 static struct lcd_8080_device _lcddev;
139
drv_lcd_cmd(lcd_8080_device_t lcd,rt_uint8_t cmd)140 static void drv_lcd_cmd(lcd_8080_device_t lcd, rt_uint8_t cmd)
141 {
142 gpiohs_set_pin(lcd->dc_pin, GPIO_PV_LOW);
143 spi_init(lcd->spi_channel, SPI_WORK_MODE_0, SPI_FF_OCTAL, 8, 0);
144 spi_init_non_standard(lcd->spi_channel, 8 /*instrction length*/, 0 /*address length*/, 0 /*wait cycles*/,
145 SPI_AITM_AS_FRAME_FORMAT /*spi address trans mode*/);
146 spi_send_data_normal_dma(lcd->dma_channel, lcd->spi_channel, lcd->cs, &cmd, 1, SPI_TRANS_CHAR);
147 }
148
drv_lcd_data_byte(lcd_8080_device_t lcd,rt_uint8_t * data_buf,rt_uint32_t length)149 static void drv_lcd_data_byte(lcd_8080_device_t lcd, rt_uint8_t *data_buf, rt_uint32_t length)
150 {
151 gpiohs_set_pin(lcd->dc_pin, GPIO_PV_HIGH);
152 spi_init(lcd->spi_channel, SPI_WORK_MODE_0, SPI_FF_OCTAL, 8, 0);
153 spi_init_non_standard(lcd->spi_channel, 8 /*instrction length*/, 0 /*address length*/, 0 /*wait cycles*/,
154 SPI_AITM_AS_FRAME_FORMAT /*spi address trans mode*/);
155 spi_send_data_normal_dma(lcd->dma_channel, lcd->spi_channel, lcd->cs, data_buf, length, SPI_TRANS_CHAR);
156 }
157
drv_lcd_data_half_word(lcd_8080_device_t lcd,rt_uint16_t * data_buf,rt_uint32_t length)158 static void drv_lcd_data_half_word(lcd_8080_device_t lcd, rt_uint16_t *data_buf, rt_uint32_t length)
159 {
160 gpiohs_set_pin(lcd->dc_pin, GPIO_PV_HIGH);
161 spi_init(lcd->spi_channel, SPI_WORK_MODE_0, SPI_FF_OCTAL, 16, 0);
162 spi_init_non_standard(lcd->spi_channel, 16 /*instrction length*/, 0 /*address length*/, 0 /*wait cycles*/,
163 SPI_AITM_AS_FRAME_FORMAT /*spi address trans mode*/);
164 spi_send_data_normal_dma(lcd->dma_channel, lcd->spi_channel, lcd->cs, data_buf, length, SPI_TRANS_SHORT);
165 }
166
drv_lcd_data_word(lcd_8080_device_t lcd,rt_uint32_t * data_buf,rt_uint32_t length)167 static void drv_lcd_data_word(lcd_8080_device_t lcd, rt_uint32_t *data_buf, rt_uint32_t length)
168 {
169 gpiohs_set_pin(lcd->dc_pin, GPIO_PV_HIGH);
170 spi_init(lcd->spi_channel, SPI_WORK_MODE_0, SPI_FF_OCTAL, 32, 0);
171 spi_init_non_standard(lcd->spi_channel, 0 /*instrction length*/, 32 /*address length*/, 0 /*wait cycles*/,
172 SPI_AITM_AS_FRAME_FORMAT /*spi address trans mode*/);
173 spi_send_data_normal_dma(lcd->dma_channel, lcd->spi_channel, lcd->cs, data_buf, length, SPI_TRANS_INT);
174 }
175
drv_lcd_hw_init(lcd_8080_device_t lcd)176 static void drv_lcd_hw_init(lcd_8080_device_t lcd)
177 {
178 #if BSP_LCD_RST_PIN >= 0
179 {
180 gpiohs_set_drive_mode(lcd->rst_pin, GPIO_DM_OUTPUT);
181 gpiohs_set_pin(lcd->rst_pin, GPIO_PV_LOW);
182 msleep(20);
183 gpiohs_set_pin(lcd->rst_pin, GPIO_PV_HIGH);
184 msleep(20);
185 }
186 #endif
187 #if BSP_LCD_BACKLIGHT_PIN >= 0
188 {
189 gpiohs_set_drive_mode(lcd->backlight_pin, GPIO_DM_OUTPUT);
190 #if defined(BSP_LCD_BACKLIGHT_ACTIVE_LOW)
191 gpiohs_set_pin(lcd->backlight_pin, GPIO_PV_LOW);
192 #elif defined(BSP_LCD_BACKLIGHT_ACTIVE_HIGH)
193 gpiohs_set_pin(lcd->backlight_pin, GPIO_PV_HIGH);
194 #else
195 gpiohs_set_pin(lcd->backlight_pin, GPIO_PV_LOW);
196 #endif
197 }
198 #endif
199
200 gpiohs_set_drive_mode(lcd->dc_pin, GPIO_DM_OUTPUT);
201 gpiohs_set_pin(lcd->dc_pin, GPIO_PV_HIGH);
202 spi_init(lcd->spi_channel, SPI_WORK_MODE_0, SPI_FF_OCTAL, 8, 0);
203 spi_set_clk_rate(lcd->spi_channel, BSP_LCD_CLK_FREQ);
204 }
205
drv_lcd_set_direction(lcd_8080_device_t lcd,lcd_dir_t dir)206 static void drv_lcd_set_direction(lcd_8080_device_t lcd, lcd_dir_t dir)
207 {
208 if (dir & DIR_XY_MASK)
209 {
210 lcd->lcd_info.width = BSP_LCD_Y_MAX;
211 lcd->lcd_info.height = BSP_LCD_X_MAX;
212 }
213 else
214 {
215 lcd->lcd_info.width = BSP_LCD_X_MAX;
216 lcd->lcd_info.height = BSP_LCD_Y_MAX;
217 }
218
219 drv_lcd_cmd(lcd, MEMORY_ACCESS_CTL);
220 drv_lcd_data_byte(lcd, (rt_uint8_t *)&dir, 1);
221 }
222
drv_lcd_set_area(lcd_8080_device_t lcd,rt_uint16_t x1,rt_uint16_t y1,rt_uint16_t x2,rt_uint16_t y2)223 static void drv_lcd_set_area(lcd_8080_device_t lcd, rt_uint16_t x1, rt_uint16_t y1, rt_uint16_t x2, rt_uint16_t y2)
224 {
225 rt_uint8_t data[4] = {0};
226
227 data[0] = (rt_uint8_t)(x1 >> 8);
228 data[1] = (rt_uint8_t)(x1);
229 data[2] = (rt_uint8_t)(x2 >> 8);
230 data[3] = (rt_uint8_t)(x2);
231 drv_lcd_cmd(lcd, HORIZONTAL_ADDRESS_SET);
232 drv_lcd_data_byte(lcd, data, 4);
233
234 data[0] = (rt_uint8_t)(y1 >> 8);
235 data[1] = (rt_uint8_t)(y1);
236 data[2] = (rt_uint8_t)(y2 >> 8);
237 data[3] = (rt_uint8_t)(y2);
238 drv_lcd_cmd(lcd, VERTICAL_ADDRESS_SET);
239 drv_lcd_data_byte(lcd, data, 4);
240
241 drv_lcd_cmd(lcd, MEMORY_WRITE);
242 }
243
drv_lcd_set_pixel(lcd_8080_device_t lcd,uint16_t x,uint16_t y,uint16_t color)244 static void drv_lcd_set_pixel(lcd_8080_device_t lcd, uint16_t x, uint16_t y, uint16_t color)
245 {
246 drv_lcd_set_area(lcd, x, y, x, y);
247 drv_lcd_data_half_word(lcd, &color, 1);
248 }
249
drv_lcd_clear(lcd_8080_device_t lcd,uint16_t color)250 static void drv_lcd_clear(lcd_8080_device_t lcd, uint16_t color)
251 {
252 uint32_t data = ((uint32_t)color << 16) | (uint32_t)color;
253
254 drv_lcd_set_area(lcd, 0, 0, lcd->lcd_info.width - 1, lcd->lcd_info.height - 1);
255 gpiohs_set_pin(lcd->dc_pin, GPIO_PV_HIGH);
256 spi_init(lcd->spi_channel, SPI_WORK_MODE_0, SPI_FF_OCTAL, 32, 0);
257 spi_init_non_standard(lcd->spi_channel, 0 /*instrction length*/, 32 /*address length*/, 0 /*wait cycles*/,
258 SPI_AITM_AS_FRAME_FORMAT /*spi address trans mode*/);
259 spi_fill_data_dma(lcd->dma_channel, lcd->spi_channel, lcd->cs, (const uint32_t *)&data, lcd->lcd_info.width * lcd->lcd_info.height / 2);
260 }
261
rt_bitblt(rt_uint16_t * dest,int dest_segment,int dest_common,int dest_x,int dest_y,int width,int height,rt_uint16_t * src,int src_segment,int src_common,int src_x,int src_y)262 static void rt_bitblt(rt_uint16_t * dest, int dest_segment, int dest_common, int dest_x, int dest_y, int width, int height,
263 rt_uint16_t *src, int src_segment, int src_common, int src_x, int src_y)
264 {
265 int sx0, sx1, sy0, sy1;
266 int dx0, dx1, dy0, dy1;
267 rt_uint16_t *buff_src;
268 rt_uint16_t *buff_dest;
269 int x, y;
270
271 if (width <= 0) {
272 return;
273 }
274 if (height <= 0) {
275 return;
276 }
277
278 sx0 = src_x;
279 sy0 = src_y;
280 sx1 = sx0 + width - 1;
281 sy1 = sy0 + height - 1;
282 dx0 = dest_x;
283 dy0 = dest_y;
284 dx1 = dx0 + width - 1;
285 dy1 = dy0 + height - 1;
286
287 if (sx0 < 0) {
288 dx0 -= sx0;
289 sx0 = 0;
290 }
291 if (sy0 < 0) {
292 dy0 -= sy0;
293 sy0 = 0;
294 }
295 if (sx1 >= src_segment) {
296 dx1 -= (sx1 - src_segment + 1);
297 sx1 = src_segment - 1;
298 }
299 if (sy1 >= src_common) {
300 dy1 -= (sy1 - src_common + 1);
301 sy1 = src_common - 1;
302 }
303
304 if (dx0 < 0) {
305 sx0 -= dx0;
306 dx0 = 0;
307 }
308 if (dy0 < 0) {
309 sy0 -= dy0;
310 dy0 = 0;
311 }
312 if (dx1 >= dest_segment) {
313 sx1 -= (dx1 - dest_segment + 1);
314 dx1 = dest_segment - 1;
315 }
316 if (dy1 >= dest_common) {
317 sy1 -= (dy1 - dest_common + 1);
318 dy1 = dest_common - 1;
319 }
320
321 if (sx1 < 0 || sx0 >= src_segment) {
322 return;
323 }
324 if (sy1 < 0 || sy0 >= src_common) {
325 return;
326 }
327 if (dx1 < 0 || dx0 >= dest_segment) {
328 return;
329 }
330 if (dy1 < 0 || dy0 >= dest_common) {
331 return;
332 }
333
334 if ((rt_ubase_t)dest < (rt_ubase_t)src) {
335 buff_src = src + (sy0 * src_segment) + sx0;
336 buff_dest = dest + (dy0 * dest_segment) + dx0;
337 for (y = sy0; y <= sy1; y++) {
338 src = buff_src;
339 dest = buff_dest;
340 for (x = sx0; x <= sx1; x++) {
341 *dest++ = *src++;
342 }
343 buff_src += src_segment;
344 buff_dest += dest_segment;
345 }
346 } else {
347 buff_src = src + (sy1 * src_segment) + sx1;
348 buff_dest = dest + (dy1 * dest_segment) + dx1;
349 for (y = sy1; y >= sy0; y--) {
350 src = buff_src;
351 dest = buff_dest;
352 for (x = sx1; x >= sx0; x--) {
353 *dest-- = *src--;
354 }
355 buff_src -= src_segment;
356 buff_dest -= dest_segment;
357 }
358 }
359 }
360
drv_lcd_rect_update(lcd_8080_device_t lcd,uint16_t x1,uint16_t y1,uint16_t width,uint16_t height)361 static void drv_lcd_rect_update(lcd_8080_device_t lcd, uint16_t x1, uint16_t y1, uint16_t width, uint16_t height)
362 {
363 static rt_uint16_t * rect_buffer = RT_NULL;
364 if(!rect_buffer)
365 {
366 rect_buffer = rt_malloc_align(lcd->lcd_info.height * lcd->lcd_info.width * (lcd->lcd_info.bits_per_pixel / 8), 64);
367 if(!rect_buffer)
368 {
369 return;
370 }
371 }
372 if(x1 == 0 && y1 == 0 && width == lcd->lcd_info.width && height == lcd->lcd_info.height)
373 {
374 drv_lcd_set_area(lcd, x1, y1, x1 + width - 1, y1 + height - 1);
375 drv_lcd_data_half_word(lcd, (rt_uint32_t *)lcd->lcd_info.framebuffer, width * height);
376 }
377 else
378 {
379 rt_bitblt(rect_buffer, width, height, 0, 0, width, height,
380 (rt_uint16_t *)lcd->lcd_info.framebuffer, lcd->lcd_info.width, lcd->lcd_info.height, x1, y1);
381 drv_lcd_set_area(lcd, x1, y1, x1 + width - 1, y1 + height - 1);
382 drv_lcd_data_half_word(lcd, (rt_uint16_t *)rect_buffer, width * height);
383 }
384 }
385
drv_lcd_init(rt_device_t dev)386 static rt_err_t drv_lcd_init(rt_device_t dev)
387 {
388 rt_err_t ret = RT_EOK;
389 lcd_8080_device_t lcd = (lcd_8080_device_t)dev;
390 rt_uint8_t data = 0;
391
392 if(!lcd)
393 {
394 return -RT_ERROR;
395 }
396 drv_lcd_hw_init(lcd);
397 /* reset LCD */
398 drv_lcd_cmd(lcd, SOFTWARE_RESET);
399 rt_thread_mdelay(100);
400
401 /* Enter normal status */
402 drv_lcd_cmd(lcd, SLEEP_OFF);
403 rt_thread_mdelay(100);
404
405 /* pixel format rgb565 */
406 drv_lcd_cmd(lcd, PIXEL_FORMAT_SET);
407 data = 0x55;
408 drv_lcd_data_byte(lcd, &data, 1);
409
410 /* set direction */
411 drv_lcd_set_direction(lcd, LCD_SCAN_DIR);
412
413 lcd->lcd_info.framebuffer = rt_malloc_align(lcd->lcd_info.height * lcd->lcd_info.width * (lcd->lcd_info.bits_per_pixel / 8), 64);
414 RT_ASSERT(lcd->lcd_info.framebuffer);
415
416 uint16_t *framebuffer = (uint16_t *)(lcd->lcd_info.framebuffer);
417 for(uint32_t i=0; i<(lcd->lcd_info.height * lcd->lcd_info.width * (lcd->lcd_info.bits_per_pixel / 8))/2; i++) {
418 framebuffer[i] = BLACK;
419 }
420 /*display on*/
421 #ifdef BSP_BOARD_K210_DRACO
422 drv_lcd_cmd(lcd, INVERSION_DISPALY_ON);
423 #endif
424 drv_lcd_cmd(lcd, DISPALY_ON);
425
426 /* set to black */
427 drv_lcd_clear(lcd, BLACK);
428 return ret;
429 }
430
drv_lcd_open(rt_device_t dev,rt_uint16_t oflag)431 static rt_err_t drv_lcd_open(rt_device_t dev, rt_uint16_t oflag)
432 {
433
434 /* Not need */
435
436 return RT_EOK;
437 }
438
drv_lcd_close(rt_device_t dev)439 static rt_err_t drv_lcd_close(rt_device_t dev)
440 {
441
442 /* Not need */
443
444 return RT_EOK;
445 }
446
drv_lcd_read(rt_device_t dev,rt_off_t pos,void * buffer,rt_size_t size)447 static rt_ssize_t drv_lcd_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
448 {
449
450 /* Not need */
451
452 return 0;
453 }
454
drv_lcd_write(rt_device_t dev,rt_off_t pos,const void * buffer,rt_size_t size)455 static rt_ssize_t drv_lcd_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
456 {
457
458 /* Not need */
459
460 return 0;
461 }
462
drv_lcd_control(rt_device_t dev,int cmd,void * args)463 static rt_err_t drv_lcd_control(rt_device_t dev, int cmd, void *args)
464 {
465 rt_err_t ret = RT_EOK;
466 lcd_8080_device_t lcd = (lcd_8080_device_t)dev;
467 rt_base_t level;
468 struct rt_device_rect_info* rect_info = (struct rt_device_rect_info*)args;
469
470 RT_ASSERT(dev != RT_NULL);
471
472 switch (cmd)
473 {
474 case RTGRAPHIC_CTRL_RECT_UPDATE:
475 if(!rect_info)
476 {
477 LOG_E("RTGRAPHIC_CTRL_RECT_UPDATE error args");
478 return -RT_ERROR;
479 }
480 drv_lcd_rect_update(lcd, rect_info->x, rect_info->y, rect_info->width, rect_info->height);
481 break;
482
483 #if BSP_LCD_BACKLIGHT_PIN >= 0
484 case RTGRAPHIC_CTRL_POWERON:
485 #if defined(BSP_LCD_BACKLIGHT_ACTIVE_LOW)
486 gpiohs_set_pin(lcd->backlight_pin, GPIO_PV_LOW);
487 #elif defined(BSP_LCD_BACKLIGHT_ACTIVE_HIGH)
488 gpiohs_set_pin(lcd->backlight_pin, GPIO_PV_HIGH);
489 #else
490 gpiohs_set_pin(lcd->backlight_pin, GPIO_PV_LOW);
491 #endif
492 break;
493
494 case RTGRAPHIC_CTRL_POWEROFF:
495 #if defined(BSP_LCD_BACKLIGHT_ACTIVE_LOW)
496 gpiohs_set_pin(lcd->backlight_pin, GPIO_PV_HIGH);
497 #elif defined(BSP_LCD_BACKLIGHT_ACTIVE_HIGH)
498 gpiohs_set_pin(lcd->backlight_pin, GPIO_PV_LOW);
499 #else
500 gpiohs_set_pin(lcd->backlight_pin, GPIO_PV_HIGH);
501 #endif
502 break;
503 #endif /* BSP_LCD_BACKLIGHT_PIN >= 0 */
504
505 case RTGRAPHIC_CTRL_GET_INFO:
506 *(struct rt_device_graphic_info *)args = lcd->lcd_info;
507 break;
508
509 case RTGRAPHIC_CTRL_SET_MODE:
510 ret = -RT_ENOSYS;
511 break;
512 case RTGRAPHIC_CTRL_GET_EXT:
513 ret = -RT_ENOSYS;
514 break;
515 default:
516 LOG_E("drv_lcd_control cmd: %d", cmd);
517 break;
518 }
519
520 return ret;
521 }
522
523 #ifdef RT_USING_DEVICE_OPS
524 const static struct rt_device_ops drv_lcd_ops =
525 {
526 drv_lcd_init,
527 drv_lcd_open,
528 drv_lcd_close,
529 drv_lcd_read,
530 drv_lcd_write,
531 drv_lcd_control
532 };
533 #endif
534
535
rt_hw_lcd_init(void)536 int rt_hw_lcd_init(void)
537 {
538 rt_err_t ret = RT_EOK;
539 lcd_8080_device_t lcd_dev = &_lcddev;
540
541 lcd_dev->cs = SPI_CHIP_SELECT_0;
542 lcd_dev->dc_pin = LCD_DC_PIN;
543 #if BSP_LCD_RST_PIN >= 0
544 lcd_dev->rst_pin = LCD_RST_PIN;
545 #endif
546 #if BSP_LCD_BACKLIGHT_PIN >= 0
547 lcd_dev->backlight_pin = LCD_BACKLIGHT_PIN;
548 #endif
549 dmalock_sync_take(&lcd_dev->dma_channel, RT_WAITING_FOREVER);
550 lcd_dev->spi_channel = SPI_DEVICE_0;
551 lcd_dev->lcd_info.bits_per_pixel = 16;
552 lcd_dev->lcd_info.pixel_format = RTGRAPHIC_PIXEL_FORMAT_RGB565;
553
554 lcd_dev->parent.type = RT_Device_Class_Graphic;
555 lcd_dev->parent.rx_indicate = RT_NULL;
556 lcd_dev->parent.tx_complete = RT_NULL;
557
558 #ifdef RT_USING_DEVICE_OPS
559 lcd_dev->parent.ops = &drv_lcd_ops;
560 #else
561 lcd_dev->parent.init = drv_lcd_init;
562 lcd_dev->parent.open = drv_lcd_open;
563 lcd_dev->parent.close = drv_lcd_close;
564 lcd_dev->parent.read = drv_lcd_read;
565 lcd_dev->parent.write = drv_lcd_write;
566 lcd_dev->parent.control = drv_lcd_control;
567 #endif
568
569 lcd_dev->parent.user_data = RT_NULL;
570
571 ret = rt_device_register(&lcd_dev->parent, "lcd", RT_DEVICE_FLAG_RDWR);
572
573 return ret;
574 }
575 INIT_DEVICE_EXPORT(rt_hw_lcd_init);
576
lcd_set_direction(lcd_dir_t dir)577 void lcd_set_direction(lcd_dir_t dir)
578 {
579 drv_lcd_set_direction(&_lcddev, dir);
580 }
581
582 #endif
583