123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247 |
- /*
- * Copyright (c) 2021-2024 HPMicro
- *
- * SPDX-License-Identifier: BSD-3-Clause
- *
- * Change Logs:
- * Date Author Notes
- * 2024-02-20 HPMicro First version
- */
- #include <rtthread.h>
- #ifdef BSP_USING_RTT_LCD_DRIVER
- #include "board.h"
- #include "hpm_l1c_drv.h"
- #include "hpm_lcdc_drv.h"
- #include "hpm_pdma_drv.h"
- #include "hpm_panel.h"
- #define LCD_BITS_PER_PIXEL 16
- #define LCD_PIXEL_FORMAT RTGRAPHIC_PIXEL_FORMAT_RGB565
- #define LCD_LAYER_INDEX (0)
- #define LCD_LAYER_DONE_MASK (1U << LCD_LAYER_INDEX)
- struct hpm_lcd
- {
- LCDC_Type *lcd_base;
- rt_uint8_t lcd_irq;
- struct rt_semaphore lcd_lock;
- char *bus_name;
- struct rt_device parent;
- struct rt_device_graphic_info lcd_info;
- uint32_t lcd_buffer_size;
- };
- static rt_err_t hpm_lcd_init(struct rt_device *device);
- static rt_err_t hpm_lcd_control(struct rt_device *device, int cmd, void *args);
- static int hpm_lcdc_init(struct hpm_lcd *lcd, struct rt_device_graphic_info *info);
- static uint8_t __attribute__((section(".framebuffer"), aligned(HPM_L1C_CACHELINE_SIZE))) lcdc_framebuffer[PANEL_SIZE_WIDTH * PANEL_SIZE_HEIGHT * LCD_BITS_PER_PIXEL / 8];
- #ifdef RT_USING_DEVICE_OPS
- const struct rt_device_ops hpm_lcd_ops = {
- .init = hpm_lcd_init,
- .open = RT_NULL,
- .close = RT_NULL,
- .read = RT_NULL,
- .write = RT_NULL,
- .control = hpm_lcd_control,
- };
- #endif
- static struct hpm_lcd hpm_lcds[] =
- {
- {
- .bus_name = "lcd0",
- .lcd_buffer_size = (PANEL_SIZE_WIDTH * PANEL_SIZE_HEIGHT * LCD_BITS_PER_PIXEL / 8),
- .lcd_base = HPM_LCDC,
- .lcd_irq = BOARD_LCD_IRQ,
- .parent.type = RT_Device_Class_Graphic,
- #ifdef RT_USING_DEVICE_OPS
- .parent.ops = &hpm_lcd_ops,
- #else
- .parent.init = hpm_lcd_init,
- .parent.open = RT_NULL,
- .parent.close = RT_NULL,
- .parent.read = RT_NULL,
- .parent.write = RT_NULL,
- .parent.control = hpm_lcd_control,
- #endif
- },
- };
- void isr_lcd_d0(void)
- {
- lcdc_disable_interrupt(hpm_lcds[0].lcd_base, LCDC_INT_EN_VSYNC_MASK);
- rt_sem_release(&hpm_lcds[0].lcd_lock);
- lcdc_clear_status(hpm_lcds[0].lcd_base, LCDC_ST_VSYNC_MASK);
- }
- SDK_DECLARE_EXT_ISR_M(BOARD_LCD_IRQ, isr_lcd_d0)
- static rt_err_t hpm_lcd_init(struct rt_device *device)
- {
- /* nothing, right now */
- (void *)device;
- return RT_EOK;
- }
- static rt_err_t hpm_lcd_control(struct rt_device *device, int cmd, void *args)
- {
- uint32_t aligned_start, aligned_end, aligned_size;
- struct hpm_lcd *lcd = (struct hpm_lcd *)device->user_data;
- hpm_panel_t *panel = hpm_panel_find_device_default();
- struct rt_device_graphic_info *info = RT_NULL;
- uint32_t buffer;
- switch (cmd)
- {
- case RTGRAPHIC_CTRL_SET_MODE:
- info = (struct rt_device_graphic_info *)args;
- rt_sem_trytake(&lcd->lcd_lock);
- lcdc_disable_interrupt(lcd->lcd_base, LCDC_INT_EN_VSYNC_MASK);
- rt_thread_delay(10);
- hpm_lcdc_init(lcd, info);
- break;
- case RTGRAPHIC_CTRL_RECT_UPDATE:
- if (args != RT_NULL)
- {
- buffer = (uint32_t)args;
- }
- else
- {
- buffer = (uint32_t)lcd->lcd_info.framebuffer;
- }
- if (l1c_dc_is_enabled())
- {
- aligned_start = HPM_L1C_CACHELINE_ALIGN_DOWN(buffer);
- aligned_end = HPM_L1C_CACHELINE_ALIGN_UP(buffer + lcd->lcd_buffer_size);
- aligned_size = aligned_end - aligned_start;
- l1c_dc_writeback(aligned_start, aligned_size);
- }
- if (lcdc_layer_control_shadow_loaded(lcd->lcd_base, 0))
- {
- lcdc_layer_set_next_buffer(lcd->lcd_base, 0, (rt_uint32_t)buffer);
- }
- break;
- case RTGRAPHIC_CTRL_WAIT_VSYNC:
- rt_sem_trytake(&lcd->lcd_lock);
- lcdc_enable_interrupt(lcd->lcd_base, LCDC_INT_EN_VSYNC_MASK);
- rt_sem_take(&lcd->lcd_lock, RT_WAITING_FOREVER);
- break;
- case RTGRAPHIC_CTRL_POWERON:
- hpm_panel_set_backlight(panel, true);
- break;
- case RTGRAPHIC_CTRL_POWEROFF:
- hpm_panel_set_backlight(panel, false);
- break;
- case RTGRAPHIC_CTRL_GET_INFO:
- info = (struct rt_device_graphic_info *)args;
- RT_ASSERT(info != RT_NULL);
- info->pixel_format = lcd->lcd_info.pixel_format;
- info->bits_per_pixel = 16;
- info->width = lcd->lcd_info.width;
- info->height = lcd->lcd_info.height;
- info->framebuffer = lcd->lcd_info.framebuffer;
- break;
- default:
- break;
- }
- }
- static int hpm_lcdc_init(struct hpm_lcd *lcd, struct rt_device_graphic_info *info)
- {
- lcdc_config_t config = {0};
- display_pixel_format_t pixel_format;
- lcdc_get_default_config(lcd->lcd_base, &config);
- board_panel_para_to_lcdc(&config);
- if (info->framebuffer == RT_NULL)
- {
- return -RT_ERROR;
- }
- rt_memcpy(&lcd->lcd_info, info, sizeof(struct rt_device_graphic_info));
- lcd->lcd_info.framebuffer = lcdc_framebuffer;
- if (info->pixel_format == RTGRAPHIC_PIXEL_FORMAT_RGB565)
- {
- pixel_format = display_pixel_format_rgb565;
- }
- else if (info->pixel_format == RTGRAPHIC_PIXEL_FORMAT_ARGB888)
- {
- pixel_format = display_pixel_format_rgb565;
- }
- else {
- return -RT_ERROR;
- }
- lcdc_init(lcd->lcd_base, &config);
- memset(lcd->lcd_info.framebuffer, 0, info->width * info->height * info->bits_per_pixel / 8);
- lcdc_layer_config_t layer;
- lcdc_get_default_layer_config(lcd->lcd_base, &layer, pixel_format, LCD_LAYER_INDEX);
- layer.position_x = 0;
- layer.position_y = 0;
- layer.width = info->width;
- layer.height = info->height;
- layer.buffer = (rt_uint32_t)lcd->lcd_info.framebuffer;
- layer.background.u = 0;
- if (status_success != lcdc_config_layer(lcd->lcd_base, LCD_LAYER_INDEX, &layer, true)) {
- return -RT_ERROR;
- }
- lcdc_turn_on_display(lcd->lcd_base);
- lcdc_enable_interrupt(lcd->lcd_base, LCDC_INT_EN_VSYNC_MASK);
- intc_m_enable_irq_with_priority(lcd->lcd_irq, 7);
- return 0;
- }
- int drv_lcd_hw_init(void)
- {
- rt_err_t result = RT_EOK;
- struct rt_device_graphic_info lcd_info;
- for (uint32_t i = 0; i < sizeof(hpm_lcds) / sizeof(hpm_lcds[0]); i++)
- {
- struct hpm_lcd *lcd = &hpm_lcds[i];
- struct rt_device *device = &lcd->parent;
- lcd->parent.user_data = lcd;
- /* init lcd_lock semaphore */
- result = rt_sem_init(&hpm_lcds[0].lcd_lock, "lcd_lock", 0, RT_IPC_FLAG_FIFO);
- if (result != RT_EOK)
- {
- result = -RT_ENOMEM;
- goto __exit;
- }
- /* config LCD dev info */
- lcd_info.height = PANEL_SIZE_HEIGHT;
- lcd_info.width = PANEL_SIZE_WIDTH;
- lcd_info.bits_per_pixel = LCD_BITS_PER_PIXEL;
- lcd_info.pixel_format = LCD_PIXEL_FORMAT;
- lcd_info.framebuffer = lcdc_framebuffer;
- /* register lcd device */
- rt_device_register(device, hpm_lcds[i].bus_name, RT_DEVICE_FLAG_RDWR);
- board_init_lcd();
- if (hpm_lcdc_init(&hpm_lcds[i], &lcd_info) != RT_EOK)
- {
- result = -RT_ERROR;
- goto __exit;
- }
- __exit:
- if (result != RT_EOK)
- {
- rt_sem_delete(&hpm_lcds[i].lcd_lock);
- }
- return result;
- }
- }
- INIT_BOARD_EXPORT(drv_lcd_hw_init);
- #endif /* BSP_USING_RTT_LCD_DRIVER */
|