1 // Copyright (C) 2022 Beken Corporation
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include <stdlib.h>
16 #include <common/bk_include.h>
17 #include <os/mem.h>
18 #include "arch_interrupt.h"
19 #include "lcd_disp_hal.h"
20 #include <driver/lcd.h>
21 #include "gpio_map.h"
22 #include "gpio_driver.h"
23 #include <driver/gpio.h>
24 #include "gpio_map.h"
25 #include <driver/int.h>
26 #include "sys_driver.h"
27 #include <modules/pm.h>
28 #include <driver/hal/hal_gpio_types.h>
29 #include <driver/hal/hal_lcd_types.h>
30 #include "lcd_disp_ll_macro_def_mp2.h"
31 #include <driver/dma2d.h>
32 #include <./lcd/lcd_devices.h>
33
34 #if CONFIG_PWM
35 #include <driver/pwm.h>
36 #endif
37
38 #include "lcd_devices.h"
39
40 #define TAG "lcd_drv"
41
42 #define IO_FUNCTION_ENABLE(pin, func) \
43 do { \
44 gpio_dev_unmap(pin); \
45 gpio_dev_map(pin, func); \
46 } while (0)
47
48
49 #define LOGI(...) BK_LOGI(TAG, ##__VA_ARGS__)
50 #define LOGW(...) BK_LOGW(TAG, ##__VA_ARGS__)
51 #define LOGE(...) BK_LOGE(TAG, ##__VA_ARGS__)
52 #define LOGD(...) BK_LOGD(TAG, ##__VA_ARGS__)
53
54 typedef struct
55 {
56 #if (USE_LCD_REGISTER_CALLBACKS == 1) //register callback
57 lcd_isr_t lcd_8080_frame_start_handler;
58 lcd_isr_t lcd_8080_frame_end_handler;
59 lcd_isr_t lcd_rgb_frame_end_handler;
60 lcd_isr_t lcd_rgb_frame_start_handler;
61 #endif
62 #if CONFIG_PWM
63 pwm_id_t pwm_id;
64 #endif
65 lcd_config_t config;
66 } lcd_driver_t;
67
68
69 extern bk_err_t bk_lcd_set_yuv_mode(lcd_data_format_t input_data_format);
70
71 const lcd_device_t *lcd_devices[] =
72 {
73 &lcd_device_st7282,
74 &lcd_device_hx8282,
75 &lcd_device_st7796s,
76 &lcd_device_gc9503v,
77 };
78
79 static lcd_driver_t s_lcd = {0};
80
get_lcd_device_by_id(lcd_device_id_t id)81 const lcd_device_t *get_lcd_device_by_id(lcd_device_id_t id)
82 {
83 uint32_t i, size = sizeof(lcd_devices) / sizeof(lcd_device_t *);
84
85 for (i = 0; i < size; i++)
86 {
87 if (lcd_devices[i]->id == id)
88 {
89 return lcd_devices[i];
90 }
91 }
92
93 return NULL;
94 }
95
lcd_mcu_gpio_init(void)96 bk_err_t lcd_mcu_gpio_init(void)
97 {
98 LOGI("%s\n", __func__);
99
100 IO_FUNCTION_ENABLE(LCD_MCU_D0_PIN, LCD_MCU_D0_FUNC);
101 IO_FUNCTION_ENABLE(LCD_MCU_D1_PIN, LCD_MCU_D1_FUNC);
102 IO_FUNCTION_ENABLE(LCD_MCU_D2_PIN, LCD_MCU_D2_FUNC);
103 IO_FUNCTION_ENABLE(LCD_MCU_D3_PIN, LCD_MCU_D3_FUNC);
104 IO_FUNCTION_ENABLE(LCD_MCU_D4_PIN, LCD_MCU_D4_FUNC);
105 IO_FUNCTION_ENABLE(LCD_MCU_D5_PIN, LCD_MCU_D5_FUNC);
106 IO_FUNCTION_ENABLE(LCD_MCU_D6_PIN, LCD_MCU_D6_FUNC);
107 IO_FUNCTION_ENABLE(LCD_MCU_D7_PIN, LCD_MCU_D7_FUNC);
108
109 IO_FUNCTION_ENABLE(LCD_MCU_RDX_PIN, LCD_MCU_RDX_FUNC);
110 IO_FUNCTION_ENABLE(LCD_MCU_WRX_PIN, LCD_MCU_WRX_FUNC);
111 IO_FUNCTION_ENABLE(LCD_MCU_RSX_PIN, LCD_MCU_RSX_FUNC);
112 IO_FUNCTION_ENABLE(LCD_MCU_RESET_PIN, LCD_MCU_RESET_FUNC);
113 IO_FUNCTION_ENABLE(LCD_MCU_CSX_PIN, LCD_MCU_CSX_FUNC);
114
115 return BK_OK;
116 }
117
lcd_rgb_gpio_init(void)118 static bk_err_t lcd_rgb_gpio_init(void)
119 {
120 LOGI("%s\n", __func__);
121
122 IO_FUNCTION_ENABLE(LCD_RGB_R0_PIN, LCD_RGB_R0_FUNC);
123 IO_FUNCTION_ENABLE(LCD_RGB_R1_PIN, LCD_RGB_R1_FUNC);
124 IO_FUNCTION_ENABLE(LCD_RGB_R2_PIN, LCD_RGB_R2_FUNC);
125 IO_FUNCTION_ENABLE(LCD_RGB_R3_PIN, LCD_RGB_R3_FUNC);
126 IO_FUNCTION_ENABLE(LCD_RGB_R4_PIN, LCD_RGB_R4_FUNC);
127 IO_FUNCTION_ENABLE(LCD_RGB_G0_PIN, LCD_RGB_G0_FUNC);
128 IO_FUNCTION_ENABLE(LCD_RGB_G1_PIN, LCD_RGB_G1_FUNC);
129 IO_FUNCTION_ENABLE(LCD_RGB_G2_PIN, LCD_RGB_G2_FUNC);
130 IO_FUNCTION_ENABLE(LCD_RGB_G3_PIN, LCD_RGB_G3_FUNC);
131 IO_FUNCTION_ENABLE(LCD_RGB_G4_PIN, LCD_RGB_G4_FUNC);
132 IO_FUNCTION_ENABLE(LCD_RGB_G5_PIN, LCD_RGB_G5_FUNC);
133 IO_FUNCTION_ENABLE(LCD_RGB_B0_PIN, LCD_RGB_B0_FUNC);
134 IO_FUNCTION_ENABLE(LCD_RGB_B1_PIN, LCD_RGB_B1_FUNC);
135 IO_FUNCTION_ENABLE(LCD_RGB_B2_PIN, LCD_RGB_B2_FUNC);
136 IO_FUNCTION_ENABLE(LCD_RGB_B3_PIN, LCD_RGB_B3_FUNC);
137 IO_FUNCTION_ENABLE(LCD_RGB_B4_PIN, LCD_RGB_B4_FUNC);
138
139 IO_FUNCTION_ENABLE(LCD_RGB_CLK_PIN, LCD_RGB_CLK_FUNC);
140 IO_FUNCTION_ENABLE(LCD_RGB_DISP_PIN, LCD_RGB_DISP_FUNC);
141 IO_FUNCTION_ENABLE(LCD_RGB_HSYNC_PIN, LCD_RGB_HSYNC_FUNC);
142 IO_FUNCTION_ENABLE(LCD_RGB_VSYNC_PIN, LCD_RGB_VSYNC_FUNC);
143 IO_FUNCTION_ENABLE(LCD_RGB_DE_PIN, LCD_RGB_DE_FUNC);
144
145 return BK_OK;
146 }
147
148
149 #if (USE_LCD_REGISTER_CALLBACKS == 1)
150 static void lcd_isr(void);
151
bk_lcd_isr_register(lcd_int_type_t int_type,lcd_isr_t isr)152 bk_err_t bk_lcd_isr_register(lcd_int_type_t int_type, lcd_isr_t isr)
153 {
154 if(int_type == I8080_OUTPUT_SOF) {
155 s_lcd.lcd_8080_frame_start_handler = isr;
156 }
157 if(int_type == I8080_OUTPUT_EOF) {
158 s_lcd.lcd_8080_frame_end_handler = isr;
159 }
160 if(int_type == RGB_OUTPUT_SOF) {
161 s_lcd.lcd_rgb_frame_start_handler= isr;
162 }
163 if(int_type == RGB_OUTPUT_EOF) {
164 s_lcd.lcd_rgb_frame_end_handler= isr;
165 }
166 return BK_OK;
167 }
168
lcd_isr(void)169 static void lcd_isr(void)
170 {
171 uint32_t int_status = lcd_hal_int_status_get();
172
173 if (int_status & RGB_OUTPUT_SOF)
174 {
175 if (s_lcd.lcd_rgb_frame_start_handler)
176 {
177 s_lcd.lcd_rgb_frame_start_handler();
178 }
179 lcd_hal_rgb_sof_int_status_clear();
180 }
181 if (int_status & RGB_OUTPUT_EOF)
182 {
183 if (s_lcd.lcd_rgb_frame_end_handler)
184 {
185 s_lcd.lcd_rgb_frame_end_handler();
186 }
187 lcd_hal_rgb_eof_int_status_clear();
188 }
189 if (int_status & I8080_OUTPUT_SOF)
190 {
191 if (s_lcd.lcd_8080_frame_start_handler)
192 {
193 s_lcd.lcd_8080_frame_start_handler();
194 }
195 lcd_hal_eof_int_status_clear();
196 }
197
198 if (int_status & I8080_OUTPUT_EOF)
199 {
200 if (s_lcd.lcd_8080_frame_end_handler)
201 {
202 s_lcd.lcd_8080_frame_end_handler();
203 }
204 lcd_hal_eof_int_status_clear();
205 }
206 }
207 #else
bk_lcd_isr_register(lcd_isr_t lcd_isr)208 bk_err_t bk_lcd_isr_register(lcd_isr_t lcd_isr)
209 {
210 bk_int_isr_register(INT_SRC_LCD, lcd_isr, NULL);
211 return BK_OK;
212 }
213
214
bk_lcd_int_status_get(void)215 uint32_t bk_lcd_int_status_get(void)
216 {
217 return reg_DISP_INT_CONFIG;
218 }
219
220
bk_lcd_int_status_clear(lcd_int_type_t int_type)221 bk_err_t bk_lcd_int_status_clear(lcd_int_type_t int_type)
222 {
223 switch (int_type)
224 {
225 case RGB_OUTPUT_SOF:
226 lcd_hal_rgb_sof_int_status_clear();
227 break;
228 case RGB_OUTPUT_EOF:
229 lcd_hal_rgb_eof_int_status_clear();
230 break;
231 case I8080_OUTPUT_SOF:
232 lcd_hal_eof_int_status_clear();
233 break;
234 case I8080_OUTPUT_EOF:
235 lcd_hal_eof_int_status_clear();
236 break;
237 default:
238 reg_DISP_INT_CONFIG = 0;
239 break;
240 }
241 return BK_OK;
242 }
243 #endif
244
bk_lcd_8080_int_enable(bool is_sof_en,bool is_eof_en)245 bk_err_t bk_lcd_8080_int_enable(bool is_sof_en, bool is_eof_en)
246 {
247 lcd_hal_8080_int_enable(is_sof_en, is_eof_en);
248 return BK_OK;
249 }
250
bk_lcd_rgb_int_enable(bool is_sof_en,bool is_eof_en)251 bk_err_t bk_lcd_rgb_int_enable(bool is_sof_en, bool is_eof_en)
252 {
253 lcd_hal_rgb_int_enable(is_sof_en, is_eof_en);
254 return BK_OK;
255 }
256
257
bk_lcd_driver_init(lcd_clk_t clk)258 bk_err_t bk_lcd_driver_init(lcd_clk_t clk)
259 {
260 bk_err_t ret = BK_OK;
261 bk_pm_module_vote_power_ctrl(PM_POWER_SUB_MODULE_NAME_VIDP_LCD, PM_POWER_MODULE_STATE_ON);
262 bk_pm_clock_ctrl(PM_CLK_ID_DISP, CLK_PWR_CTRL_PWR_UP);
263 switch (clk)
264 {
265 case LCD_320M:
266 ret = sys_drv_lcd_set(DISP_CLK_320M, DISP_DIV_L_0, DISP_DIV_H_0, DISP_INT_EN, DSIP_DISCLK_ALWAYS_ON);
267 break;
268 case LCD_160M:
269 ret = sys_drv_lcd_set(DISP_CLK_320M, DISP_DIV_L_1, DISP_DIV_H_0, DISP_INT_EN, DSIP_DISCLK_ALWAYS_ON);
270 break;
271 case LCD_120M:
272 ret = sys_drv_lcd_set(DISP_CLK_120M, DISP_DIV_L_0, DISP_DIV_H_0, DISP_INT_EN, DSIP_DISCLK_ALWAYS_ON);
273 break;
274 case LCD_40M:
275 ret = sys_drv_lcd_set(DISP_CLK_120M, DISP_DIV_L_0, DISP_DIV_H_1, DISP_INT_EN, DSIP_DISCLK_ALWAYS_ON);
276 //ret = sys_drv_lcd_set(DISP_CLK_320M, DISP_DIV_L_1, DISP_DIV_H_3, DISP_INT_EN, DSIP_DISCLK_ALWAYS_ON);
277 break;
278 case LCD_20M:
279 ret = sys_drv_lcd_set(DISP_CLK_320M, DISP_DIV_L_1, DISP_DIV_H_7, DISP_INT_EN, DSIP_DISCLK_ALWAYS_ON);
280 //ret = sys_drv_lcd_set(DISP_CLK_120M, DISP_DIV_L_1, DISP_DIV_H_2, DISP_INT_EN, DSIP_DISCLK_ALWAYS_ON);
281 break;
282 case LCD_60M:
283 ret = sys_drv_lcd_set(DISP_CLK_120M, DISP_DIV_L_1, DISP_DIV_H_0, DISP_INT_EN, DSIP_DISCLK_ALWAYS_ON);
284 break;
285 case LCD_80M:
286 ret = sys_drv_lcd_set(DISP_CLK_320M, DISP_DIV_L_1, DISP_DIV_H_1, DISP_INT_EN, DSIP_DISCLK_ALWAYS_ON);
287 break;
288 case LCD_54M:
289 ret = sys_drv_lcd_set(DISP_CLK_320M, DISP_DIV_L_1, DISP_DIV_H_2, DISP_INT_EN, DSIP_DISCLK_ALWAYS_ON);
290 break;
291 case LCD_32M:
292 ret = sys_drv_lcd_set(DISP_CLK_320M, DISP_DIV_L_1, DISP_DIV_H_4, DISP_INT_EN, DSIP_DISCLK_ALWAYS_ON);
293 break;
294 case LCD_12M:
295 ret = sys_drv_lcd_set(DISP_CLK_120M, DISP_DIV_L_1, DISP_DIV_H_4, DISP_INT_EN, DSIP_DISCLK_ALWAYS_ON);
296 break;
297 case LCD_10M:
298 ret = sys_drv_lcd_set(DISP_CLK_120M, DISP_DIV_L_1, DISP_DIV_H_5, DISP_INT_EN, DSIP_DISCLK_ALWAYS_ON);
299 break;
300 case LCD_26M:
301 ret = sys_drv_lcd_set(DISP_CLK_320M, DISP_DIV_L_1, DISP_DIV_H_5, DISP_INT_EN, DSIP_DISCLK_ALWAYS_ON);
302 break;
303 case LCD_8M:
304 ret = sys_drv_lcd_set(DISP_CLK_120M, DISP_DIV_L_1, DISP_DIV_H_7, DISP_INT_EN, DSIP_DISCLK_ALWAYS_ON);
305 break;
306 default:
307 break;
308 }
309
310 #if (USE_LCD_REGISTER_CALLBACKS == 1)
311 bk_int_isr_register(INT_SRC_LCD, lcd_isr, NULL);
312 #endif
313
314 return ret;
315 }
316 /**
317 * @brief This API config lcd display x size and y size
318
319 * @param
320 * - width lcd display width
321 * - height lcd display height
322 *
323 * attention 1. int the next version, the width and height deside the transfer number of lcd display.
324 * will config with another two register x offset and y offset
325 *
326 * attention 2. in this sdk version width/height only set once in 8080_init,if you want set twice,should
327 set bk_lcd_8080_display_enable(0)
328 */
bk_lcd_pixel_config(uint16_t x_pixel,uint16_t y_pixel)329 bk_err_t bk_lcd_pixel_config(uint16_t x_pixel, uint16_t y_pixel)
330 {
331 lcd_hal_pixel_config(x_pixel, y_pixel);
332 return BK_OK;
333 }
334
335
bk_lcd_8080_send_cmd(uint8_t param_count,uint32_t command,uint32_t * param)336 bk_err_t bk_lcd_8080_send_cmd(uint8_t param_count, uint32_t command, uint32_t *param)
337 {
338 lcd_hal_8080_cmd_send(param_count, command, param);
339 return BK_OK;
340 }
341
342
bk_lcd_8080_ram_write(uint32_t command)343 bk_err_t bk_lcd_8080_ram_write(uint32_t command)
344 {
345 lcd_hal_8080_cmd_param_count(1);
346 lcd_hal_8080_write_cmd(command);
347 return BK_OK;
348 }
349
bk_lcd_set_yuv_mode(lcd_data_format_t input_data_format)350 bk_err_t bk_lcd_set_yuv_mode(lcd_data_format_t input_data_format)
351 {
352 switch (input_data_format)
353 {
354 case LCD_FMT_RGB565:
355 lcd_hal_display_yuv_sel(0);
356 break;
357 case LCD_FMT_ORGINAL_YUYV:
358 lcd_hal_display_yuv_sel(1);
359 break;
360 case LCD_FMT_UYVY:
361 lcd_hal_display_yuv_sel(2);
362 break;
363 case LCD_FMT_YYUV:
364 lcd_hal_display_yuv_sel(3);
365 break;
366 case LCD_FMT_UVYY:
367 lcd_hal_display_yuv_sel(4);
368 break;
369 case LCD_FMT_VUYY:
370 lcd_hal_display_yuv_sel(5);
371 break;
372 case LCD_FMT_YVYU:
373 lcd_hal_display_yuv_sel(1);
374 lcd_hal_set_pixel_reverse(1);
375 break;
376 case LCD_FMT_VYUY:
377 lcd_hal_display_yuv_sel(2);
378 lcd_hal_set_pixel_reverse(1);
379 break;
380 case LCD_FMT_YYVU:
381 lcd_hal_display_yuv_sel(5);
382 lcd_hal_set_pixel_reverse(1);
383 break;
384 default:
385 break;
386 }
387 return BK_OK;
388 }
389
bk_lcd_rgb_init(lcd_device_id_t id,uint16_t x_pixel,uint16_t y_pixel,lcd_data_format_t input_data_format)390 bk_err_t bk_lcd_rgb_init(lcd_device_id_t id, uint16_t x_pixel, uint16_t y_pixel, lcd_data_format_t input_data_format)
391 {
392 lcd_rgb_gpio_init();
393 lcd_hal_rgb_int_enable(0, 1);
394 lcd_hal_rgb_display_sel(1); //RGB display enable, and select rgb module
395 lcd_hal_set_sync_low(HSYNC_BACK_LOW, VSYNC_BACK_LOW);
396 switch (id)
397 {
398 case LCD_DEVICE_ST7282:
399 lcd_hal_rgb_sync_config(RGB_HSYNC_BACK_PORCH, RGB_HSYNC_FRONT_PORCH, RGB_VSYNC_BACK_PORCH, RGB_VSYNC_FRONT_PORCH);
400 lcd_hal_set_rgb_clk_rev_edge(POSEDGE_OUTPUT);
401 break;
402 case LCD_DEVICE_HX8282:
403 lcd_hal_rgb_sync_config(RGB_720P_HSYNC_BACK_PORCH, RGB_720P_HSYNC_FRONT_PORCH,RGB_720P_VSYNC_BACK_PORCH, RGB_720P_VSYNC_FRONT_PORCH);
404 lcd_hal_set_rgb_clk_rev_edge(POSEDGE_OUTPUT);
405 break;
406 case LCD_DEVICE_GC9503V:
407 lcd_hal_rgb_sync_config(RGB_HSYNC_BACK_PORCH, RGB_HSYNC_FRONT_PORCH, RGB_VSYNC_BACK_PORCH, RGB_VSYNC_FRONT_PORCH);
408 lcd_hal_set_rgb_clk_rev_edge(NEGEDGE_OUTPUT); //output data is in clk doen edge or up adge
409 break;
410 default:
411 lcd_hal_rgb_sync_config(RGB_HSYNC_BACK_PORCH, RGB_HSYNC_FRONT_PORCH, RGB_VSYNC_BACK_PORCH, RGB_VSYNC_FRONT_PORCH);
412 lcd_hal_set_rgb_clk_rev_edge(POSEDGE_OUTPUT);
413 break;
414 }
415
416 lcd_hal_disconti_mode(DISCONTINUE_MODE);
417 bk_lcd_pixel_config(x_pixel, y_pixel);
418 bk_lcd_set_yuv_mode(input_data_format);
419 lcd_hal_set_data_fifo_thrd(DATA_FIFO_WR_THRD, DATA_FIFO_RD_THRD);
420 return BK_OK;
421 }
422
423
424
bk_lcd_8080_init(uint16_t x_pixel,uint16_t y_pixel,lcd_data_format_t input_data_format)425 bk_err_t bk_lcd_8080_init(uint16_t x_pixel, uint16_t y_pixel,lcd_data_format_t input_data_format)
426 {
427 lcd_mcu_gpio_init();
428 lcd_hal_rgb_display_sel(0); //25bit - rgb_on = 0 select 8080 mode
429 lcd_hal_disconti_mode(DISCONTINUE_MODE);
430 lcd_hal_8080_verify_1ms_count(VERIFY_1MS_COUNT);
431 lcd_hal_8080_set_tik(TIK_CNT);
432 lcd_hal_set_data_fifo_thrd(DATA_FIFO_WR_THRD, DATA_FIFO_RD_THRD);
433 lcd_hal_8080_set_fifo_data_thrd(CMD_FIFO_WR_THRD,CMD_FIFO_RD_THRD);
434 bk_lcd_pixel_config(x_pixel, y_pixel);
435 lcd_hal_8080_display_enable(1);
436 lcd_hal_8080_int_enable(0, 1); //set eof int enable
437 bk_lcd_set_yuv_mode(input_data_format);
438 lcd_hal_8080_sleep_in(1);
439 //delay(7017857); //reset need 131ms.
440 return BK_OK;
441 }
442
443
bk_lcd_8080_deinit(void)444 bk_err_t bk_lcd_8080_deinit(void)
445 {
446
447 bk_int_isr_unregister(INT_SRC_LCD);
448 lcd_hal_8080_sleep_in(1);
449 lcd_hal_8080_int_enable(0, 0);
450 lcd_hal_8080_display_enable(0);
451 lcd_hal_8080_start_transfer(0);
452 bk_pm_clock_ctrl(PM_CLK_ID_DISP, CLK_PWR_CTRL_PWR_DOWN);
453 bk_pm_module_vote_power_ctrl(PM_POWER_SUB_MODULE_NAME_VIDP_LCD, PM_POWER_MODULE_STATE_OFF);
454 if (sys_drv_lcd_close() != 0)
455 {
456 os_printf("lcd system deinit 8080 config error \r\n");
457 return BK_FAIL;
458 }
459
460 lcd_hal_soft_reset(1);
461 rtos_delay_milliseconds(1);
462
463 return BK_OK;
464 }
465
466
bk_lcd_rgb_display_en(bool en)467 bk_err_t bk_lcd_rgb_display_en(bool en)
468 {
469 lcd_hal_rgb_display_en(en);
470 return BK_OK;
471 }
472
bk_lcd_rgb_deinit(void)473 bk_err_t bk_lcd_rgb_deinit(void)
474 {
475 lcd_hal_rgb_int_enable(0, 0);
476 lcd_hal_rgb_display_en(0);
477 lcd_hal_rgb_display_sel(0);
478 bk_int_isr_unregister(INT_SRC_LCD);
479 bk_pm_clock_ctrl(PM_CLK_ID_DISP, CLK_PWR_CTRL_PWR_DOWN);
480 bk_pm_module_vote_power_ctrl(PM_POWER_SUB_MODULE_NAME_VIDP_LCD, PM_POWER_MODULE_STATE_OFF);
481 if(sys_drv_lcd_close() != 0) {
482 os_printf("lcd system deinit reg config error \r\n");
483 return BK_FAIL;
484 }
485 lcd_hal_soft_reset(1);
486 rtos_delay_milliseconds(1);
487 return BK_OK;
488 }
489
bk_lcd_8080_start_transfer(bool start)490 bk_err_t bk_lcd_8080_start_transfer(bool start)
491 {
492 lcd_hal_8080_start_transfer(start);
493 return BK_OK;
494 }
495
lcd_driver_rgb_init(const lcd_config_t * config)496 bk_err_t lcd_driver_rgb_init(const lcd_config_t *config)
497 {
498 const lcd_rgb_t *rgb = config->device->rgb;
499 uint16_t x = ppi_to_pixel_x(config->device->ppi); //lcd size x
500 uint16_t y = ppi_to_pixel_y(config->device->ppi); //lcd size y
501
502 LOGI("%s\n", __func__);
503
504 lcd_hal_set_rgb_clk_rev_edge(0); //output data is in clk doen edge or up adge
505 lcd_hal_rgb_display_sel(1); //RGB display enable, and select rgb module
506 lcd_hal_set_sync_low(HSYNC_BACK_LOW, VSYNC_BACK_LOW);
507
508 lcd_hal_rgb_sync_config(rgb->hsync_back_porch,
509 rgb->hsync_front_porch,
510 rgb->vsync_back_porch,
511 rgb->vsync_front_porch);
512
513 lcd_hal_set_rgb_clk_rev_edge(rgb->data_out_clk_edge);
514
515 lcd_hal_disconti_mode(DISCONTINUE_MODE);
516
517 bk_lcd_pixel_config(config->pixel_x, config->pixel_y); //image xpixel ypixel
518
519 bk_lcd_set_yuv_mode(config->fmt);
520 lcd_hal_set_data_fifo_thrd(DATA_FIFO_WR_THRD, DATA_FIFO_RD_THRD);
521
522 if (x < config->pixel_x || y < config->pixel_y)
523 {
524 uint16_t start_x, end_x, start_y, end_y;
525
526 start_x = (config->pixel_x - x) / 2 + 1;
527 end_x = start_x + x - 1;
528
529 start_y = (config->pixel_y - y) / 2 + 1;
530 end_y = start_y + y - 1;
531
532 LOGI("%s, offset %d, %d, %d, %d\n", __func__, start_x, end_x, start_y, end_y);
533
534 bk_lcd_set_partical_display(1, start_x, end_x, start_y, end_y);
535 }
536
537 return BK_OK;
538 }
539
bk_lcd_set_partical_display(bool en,uint16_t partial_clum_l,uint16_t partial_clum_r,uint16_t partial_line_l,uint16_t partial_line_r)540 bk_err_t bk_lcd_set_partical_display(bool en, uint16_t partial_clum_l, uint16_t partial_clum_r, uint16_t partial_line_l, uint16_t partial_line_r)
541 {
542 lcd_hal_set_partical_display(en, partial_clum_l, partial_clum_r, partial_line_l, partial_line_r);
543 return BK_OK;
544 }
545
546
lcd_driver_mcu_init(const lcd_config_t * config)547 bk_err_t lcd_driver_mcu_init(const lcd_config_t *config)
548 {
549 uint16_t x = ppi_to_pixel_x(config->device->ppi);
550 uint16_t y = ppi_to_pixel_y(config->device->ppi);
551
552 LOGI("%s\n", __func__);
553
554 lcd_hal_rgb_display_sel(0); //25bit - rgb_on = 0 select 8080 mode
555 lcd_hal_disconti_mode(DISCONTINUE_MODE);
556 lcd_hal_8080_verify_1ms_count(VERIFY_1MS_COUNT);
557 lcd_hal_8080_set_tik(TIK_CNT);
558 lcd_hal_set_data_fifo_thrd(DATA_FIFO_WR_THRD, DATA_FIFO_RD_THRD);
559 lcd_hal_8080_set_fifo_data_thrd(CMD_FIFO_WR_THRD, CMD_FIFO_RD_THRD);
560 lcd_hal_pixel_config(config->pixel_x, config->pixel_y);
561 lcd_hal_8080_display_enable(1);
562 lcd_hal_8080_int_enable(0, 1); //set eof int enable
563 bk_lcd_set_yuv_mode(config->fmt);
564 lcd_hal_8080_sleep_in(1);
565
566 if (x < config->pixel_x || y < config->pixel_y)
567 {
568 uint16_t start_x, end_x, start_y, end_y;
569
570 start_x = (config->pixel_x - x) / 2 + 1;
571 end_x = start_x + x - 1;
572
573 start_y = (config->pixel_y - y) / 2 + 1;
574 end_y = start_y + y - 1;
575
576 LOGI("%s, offset %d, %d, %d, %d\n", __func__, start_x, end_x, start_y, end_y);
577
578 bk_lcd_set_partical_display(1,start_x, end_x, start_y, end_y);
579 }
580
581 return BK_OK;
582 }
583
584 #if CONFIG_PWM
lcd_driver_backlight_init(uint8_t pwm_id,uint8_t percent)585 bk_err_t lcd_driver_backlight_init(uint8_t pwm_id, uint8_t percent)
586 {
587 pwm_init_config_t config = {0};
588 BK_LOG_ON_ERR(bk_pwm_driver_init());
589
590 if (percent > 100)
591 {
592 percent = 100;
593 }
594
595 config.period_cycle = 100;
596 config.duty_cycle = percent;
597 BK_LOG_ON_ERR(bk_pwm_init(pwm_id, &config));
598 BK_LOG_ON_ERR(bk_pwm_start(pwm_id));
599
600 return BK_OK;
601 }
602
lcd_driver_backlight_deinit(uint8_t pwm_id)603 bk_err_t lcd_driver_backlight_deinit(uint8_t pwm_id)
604 {
605 BK_LOG_ON_ERR(bk_pwm_stop(pwm_id));
606 BK_LOG_ON_ERR(bk_pwm_deinit(pwm_id));
607 return BK_OK;
608 }
609
lcd_driver_set_backlight(uint8_t percent)610 bk_err_t lcd_driver_set_backlight(uint8_t percent)
611 {
612 pwm_period_duty_config_t config = {0};
613
614 if (percent > 100)
615 {
616 percent = 100;
617 }
618
619 config.period_cycle = 100;
620 config.duty_cycle = percent;
621
622 bk_pwm_set_period_duty(s_lcd.pwm_id, &config);
623
624 return BK_OK;
625 }
626 #endif
627
lcd_driver_display_enable(void)628 bk_err_t lcd_driver_display_enable(void)
629 {
630 lcd_type_t type;
631
632 type = s_lcd.config.device->type;
633
634 if (type == LCD_TYPE_RGB565)
635 {
636 lcd_hal_rgb_display_en(1);
637 }
638 else if (type == LCD_TYPE_MCU8080)
639 {
640 lcd_hal_8080_start_transfer(1);
641 lcd_hal_8080_cmd_param_count(1);
642 lcd_hal_8080_write_cmd(0x2c);
643 }
644
645 return BK_OK;
646 }
lcd_driver_display_continue(void)647 bk_err_t lcd_driver_display_continue(void)
648 {
649 lcd_type_t type;
650 type = s_lcd.config.device->type;
651 if (type == LCD_TYPE_RGB565)
652 {
653 // lcd_hal_rgb_eof_int_status_clear();
654 }
655
656 if (type == LCD_TYPE_MCU8080)
657 {
658 lcd_hal_8080_write_cmd(0x3c);
659 // lcd_hal_eof_int_status_clear();
660 }
661 return BK_OK;
662 }
663
lcd_driver_set_display_base_addr(uint32_t disp_base_addr)664 bk_err_t lcd_driver_set_display_base_addr(uint32_t disp_base_addr)
665 {
666 lcd_hal_set_display_read_base_addr(disp_base_addr);
667
668 return BK_OK;
669 }
bk_lcd_get_display_base_addr(void)670 uint32_t bk_lcd_get_display_base_addr(void)
671 {
672 return lcd_disp_ll_get_mater_rd_base_addr();
673 }
674
675
lcd_driver_init(const lcd_config_t * config)676 bk_err_t lcd_driver_init(const lcd_config_t *config)
677 {
678 int ret = BK_FAIL;
679 lcd_clk_t clk = 0;
680 const lcd_device_t *device = config->device;
681
682 if (device == NULL)
683 {
684 LOGE("%s, device need to be set\n", __func__);
685 goto error;
686 }
687
688 os_memset(&s_lcd, 0, sizeof(s_lcd));
689 os_memcpy(&s_lcd.config, config, sizeof(lcd_config_t));
690
691
692 if (device->type == LCD_TYPE_RGB565)
693 {
694 clk = device->rgb->clk;
695 #if CONFIG_PWM
696 s_lcd.pwm_id = LCD_PWM_BACKLIGHT;
697 #endif
698 }
699 else if (device->type == LCD_TYPE_MCU8080)
700 {
701 clk = device->mcu->clk;
702 #if CONFIG_PWM
703 s_lcd.pwm_id = LCD_PWM_BACKLIGHT;
704 #endif
705 }
706
707 #if CONFIG_PWM
708 lcd_driver_backlight_init(s_lcd.pwm_id, 90);
709 #endif
710 LOGI("%s, LCD clk set: %d\n", __func__, clk);
711
712 ret = bk_lcd_driver_init(clk);
713
714 if (ret != BK_OK)
715 {
716 LOGE("%s, device clk set error\n", __func__);
717 goto error;
718 }
719
720 if (device->type == LCD_TYPE_RGB565)
721 {
722
723 #if (USE_LCD_REGISTER_CALLBACKS == 1)
724 lcd_hal_rgb_int_enable(0, 1);
725 if (config->complete_callback)
726 {
727 LOGI("%s, rgb eof register\n", __func__);
728 s_lcd.lcd_rgb_frame_end_handler = config->complete_callback;
729 }
730 #endif
731
732 lcd_rgb_gpio_init();
733 lcd_driver_rgb_init(config);
734 }
735 else if (device->type == LCD_TYPE_MCU8080)
736 {
737
738 #if (USE_LCD_REGISTER_CALLBACKS == 1)
739 lcd_hal_8080_int_enable(0, 1);
740 if (config->complete_callback)
741 {
742 LOGI("%s, mcu eof register\n", __func__);
743 s_lcd.lcd_8080_frame_end_handler = config->complete_callback;
744 }
745 #endif
746
747 lcd_mcu_gpio_init();
748 lcd_driver_mcu_init(config);
749 }
750
751 if (device->init)
752 {
753 device->init();
754 }
755
756 return ret;
757
758 error:
759
760 return ret;
761 }
762
lcd_driver_deinit(void)763 bk_err_t lcd_driver_deinit(void)
764 {
765 lcd_type_t type;
766
767 type = s_lcd.config.device->type;
768
769 if (type == LCD_TYPE_RGB565)
770 {
771 lcd_hal_rgb_int_enable(0, 0);
772 lcd_hal_rgb_display_en(0);
773 lcd_hal_rgb_display_sel(0);
774 bk_int_isr_unregister(INT_SRC_LCD);
775 bk_pm_clock_ctrl(PM_CLK_ID_DISP, CLK_PWR_CTRL_PWR_DOWN);
776 bk_pm_module_vote_power_ctrl(PM_POWER_SUB_MODULE_NAME_VIDP_LCD, PM_POWER_MODULE_STATE_OFF);
777 if (sys_drv_lcd_close() != 0)
778 {
779 LOGE("lcd system deinit reg config error \r\n");
780 return BK_FAIL;
781 }
782 }
783 else if (type == LCD_TYPE_MCU8080)
784 {
785 bk_int_isr_unregister(INT_SRC_LCD);
786 lcd_hal_8080_sleep_in(1);
787 lcd_hal_8080_int_enable(0, 0);
788 lcd_hal_8080_display_enable(0);
789 lcd_hal_8080_start_transfer(0);
790 bk_pm_clock_ctrl(PM_CLK_ID_DISP, CLK_PWR_CTRL_PWR_DOWN);
791 bk_pm_module_vote_power_ctrl(PM_POWER_SUB_MODULE_NAME_VIDP_LCD, PM_POWER_MODULE_STATE_OFF);
792 if (sys_drv_lcd_close() != 0)
793 {
794 LOGE("lcd system deinit reg config error \r\n");
795 return BK_FAIL;
796 }
797 }
798
799 lcd_hal_soft_reset(1);
800 rtos_delay_milliseconds(1);
801
802 #if CONFIG_PWM
803 lcd_driver_backlight_deinit(s_lcd.pwm_id);
804 #endif
805
806 return BK_OK;
807 }
808
dma2d_lcd_fill(uint32_t frameaddr,uint16_t width,uint16_t height,uint32_t color)809 static void dma2d_lcd_fill(uint32_t frameaddr, uint16_t width, uint16_t height, uint32_t color)
810 {
811 uint32_t color_temp = (color << 16) | color;
812 // os_printf("displat color :%x\r\n", color_temp);
813 dma2d_config_t dma2d_config = {0};
814
815 dma2d_config.init.mode = DMA2D_R2M; /**< Mode Register to Memory */
816 dma2d_config.init.color_mode = DMA2D_OUTPUT_ARGB8888; /**< DMA2D Output color mode is ARGB4444 (16 bpp) */
817 dma2d_config.init.output_offset = 0; /**< offset in output */
818 dma2d_config.init.red_blue_swap = DMA2D_RB_REGULAR; /**< No R&B swap for the output image */
819 dma2d_config.init.alpha_inverted = DMA2D_REGULAR_ALPHA; /**< No alpha inversion for the output image */
820 bk_dma2d_driver_init(&dma2d_config);
821
822 if (width == 0 && height == 0)
823 {
824 }
825 else if (width == 0)
826 {
827 height = height/2;
828 }
829 else if(height == 0)
830 {
831 width = width/2;
832 }
833 else
834 {
835 width = width/2;
836 }
837 bk_dma2d_start_transfer(&dma2d_config, color_temp, (uint32_t)frameaddr, width, height);
838 while (bk_dma2d_is_transfer_busy()) {
839 }
840 }
841
bk_lcd_fill_color(lcd_device_id_t id,lcd_disp_framebuf_t * lcd_disp,uint32_t color)842 bk_err_t bk_lcd_fill_color(lcd_device_id_t id, lcd_disp_framebuf_t *lcd_disp, uint32_t color)
843 {
844 if((lcd_disp->rect.x > PIXEL_320-1) || (lcd_disp->rect.x + lcd_disp->rect.width > PIXEL_320-1)) return 0;
845 if((lcd_disp->rect.y > PIXEL_480-1) || (lcd_disp->rect.y + lcd_disp->rect.height > PIXEL_480-1)) return 0;
846
847 dma2d_lcd_fill((uint32_t)lcd_disp->buffer, lcd_disp->rect.width, lcd_disp->rect.height, color);
848 lcd_hal_pixel_config(lcd_disp->rect.width, lcd_disp->rect.height);
849 //os_printf("displat partical (%d, %d)\r\n", lcd_disp->rect.width, lcd_disp->rect.height);
850 lcd_hal_8080_start_transfer(1);
851 switch (id)
852 {
853 case LCD_DEVICE_ST7796S:
854 lcd_st7796s_set_display_mem_area(lcd_disp->rect.x, lcd_disp->rect.x + lcd_disp->rect.width, lcd_disp->rect.y, lcd_disp->rect.y + lcd_disp->rect.height);
855 // os_printf("lcd partical (xs, xe ,ys, ye) = (%d, %d,%d, %d)\r\n", lcd_disp->rect.x, lcd_disp->rect.x + lcd_disp->rect.width, lcd_disp->rect.y, lcd_disp->rect.y + lcd_disp->rect.height);
856 break;
857 default:
858 break;
859 }
860 lcd_driver_set_display_base_addr((uint32_t)lcd_disp->buffer);
861 return BK_OK;
862 }
863
bk_lcd_fill_data(lcd_device_id_t id,lcd_disp_framebuf_t * lcd_disp)864 bk_err_t bk_lcd_fill_data(lcd_device_id_t id, lcd_disp_framebuf_t *lcd_disp)
865 {
866 lcd_hal_pixel_config(lcd_disp->rect.width, lcd_disp->rect.height);
867 lcd_hal_8080_start_transfer(1);
868 switch (id)
869 {
870 case LCD_DEVICE_ST7796S:
871 lcd_st7796s_set_display_mem_area(lcd_disp->rect.x, lcd_disp->rect.x + lcd_disp->rect.width, lcd_disp->rect.y, lcd_disp->rect.y + lcd_disp->rect.height);
872 break;
873 default:
874 break;
875 }
876 lcd_driver_set_display_base_addr((uint32_t)lcd_disp->buffer);
877 return BK_OK;
878 }
879
bk_lcd_draw_point(lcd_device_id_t id,uint16_t x,uint16_t y,uint16_t pixel)880 bk_err_t bk_lcd_draw_point(lcd_device_id_t id, uint16_t x, uint16_t y, uint16_t pixel)
881 {
882 uint16 pixel_l, pixel_h;
883
884 pixel_l = pixel >> 8;
885 pixel_h = pixel & 0xff;
886 uint32_t param_clumn[2] = {pixel_l, pixel_h};
887
888 switch (id)
889 {
890 case LCD_DEVICE_ST7796S:
891 if(x>=320||y>=480)return 0;
892 lcd_st7796s_set_display_mem_area(x, x+1, y, y+1);
893 break;
894 default:
895 break;
896 }
897 lcd_hal_8080_cmd_send(2, 0x2c, param_clumn);
898 return BK_OK;
899 }
900
901
902