Files
banban/ql-kernel/threadx/lcd/src/panel_drv.c
T

634 lines
16 KiB
C

#include "panel_drv.h"
#include "lcd_log.h"
#include "spi_drv.h"
#include "quec_lcd.h"
int g_panel_mode = PANEL_MODE_NORMAL;
#define MAX_PANEL_COUNT 1
int g_panel_status[MAX_PANEL_COUNT] = {
PANEL_STATUS_POWEROFF
};
extern quec_mutex_t g_cramem_mutex;
extern void CacheCleanMemory( void *pMem ,UINT32 size);
static int quec_lcd_panel_interface_init(struct panel_spec *self, unsigned int sclk, int work_mode);
static int quec_lcd_panel_interface_update(struct panel_spec *self, int work_mode);
static int quec_lcd_panel_init(struct panel_spec *self);
static int quec_lcd_panel_invalid(struct panel_spec *self, unsigned int start_x, unsigned int start_y, unsigned int end_x, unsigned int end_y);
static unsigned int quec_lcd_panel_readid(struct panel_spec *self);
static int quec_lcd_panel_display_on(struct panel_spec *self);
static int quec_lcd_panel_display_off(struct panel_spec *self);
static void quec_lcd_panel_refresh(struct panel_spec *self,struct asrlcdd_framebuffer_window *frame_window,unsigned short startX, unsigned short startY);
static int lcd_panel_spi_uninit(struct panel_spec *self);
static int lcd_panel_spi_reset(struct panel_spec *self);
/********************lcd设备描述***************************/
const static struct panel_operations lcd_spi_ops = {
quec_lcd_panel_interface_init,
lcd_panel_spi_reset,
lcd_panel_spi_uninit,
quec_lcd_panel_interface_update,
quec_lcd_panel_init,
quec_lcd_panel_invalid,
quec_lcd_panel_display_off,
quec_lcd_panel_display_on,
quec_lcd_panel_readid,
quec_lcd_panel_refresh
};
static struct timing_spi lcd_spi_timing = {
SPI_6_5M,//62500, //31200, //26000, // /*kHz*/
SPI_3_25M, /*kHz*/
};
static struct spi_info lcd_spi_info_customer = {
4,
1,
1,
SPI_FORMAT_RGB565,
#ifdef SPI_CONETROLER_0_ENABLE
0,
#else
1,
#endif
SPI_EDGE_RISING,
0,
SPI_ENDIAN_MSB,
0,
(struct timing_spi*)&lcd_spi_timing,
};
struct panel_spec lcd_spi_spec_customer = {
"quec_Lcd",
0x7c89f0,
QUEC_LCD_CAP_NOTE,
128,
128,
LCD_INTERFACE_SPI,
LCD_TYPE_RGB,
LCD_POLARITY_POS,
(void*)&lcd_spi_info_customer,
NULL,
(struct panel_operations*)&lcd_spi_ops,
};
struct panel_spec* lcd_get_panel(void)
{
return &lcd_spi_spec_customer;
}
void lcd_msleep(unsigned int ms)
{
quec_rtos_task_sleep_ms(ms);
}
void lcd_udelay(int us)
{
volatile unsigned int i;
for(i=0; i<us*100;i++)
i = i+1;
}
void lcd_mdelay(unsigned int ms)
{
volatile unsigned int i;
for(i=0; i<ms;i++)
lcd_udelay(100);
}
void lcd_pin_cfg(struct panel_spec* panel)
{
struct spi_info *spi = NULL;
if(panel->interf == LCD_INTERFACE_SPI){
spi = (struct spi_info*)panel->info;
if(spi->line_num == 3){
if(spi->data_lane_num == 1){
if(spi->interface_id == 1){
LCD_Pinmuxcfg(LCM_INTERFACE_SPI_3W_1L_1IF);
} else{
LCD_Pinmuxcfg(LCM_INTERFACE_SPI_3W_1L_2IF);
}
} else{
if(spi->interface_id == 1){
LCD_Pinmuxcfg(LCM_INTERFACE_SPI_3W_2L_1IF);
} else{
LCD_Pinmuxcfg(LCM_INTERFACE_SPI_3W_2L_2IF);
}
}
} else { /*4 wire spi*/
if(spi->interface_id == 1){
LCD_Pinmuxcfg(LCM_INTERFACE_SPI_4W_1L_1IF);
} else{
LCD_Pinmuxcfg(LCM_INTERFACE_SPI_4W_1L_2IF);
}
}
}
}
int panel_pin_cfg(void)
{
struct panel_spec* panel=lcd_get_panel();
if (panel == NULL)
{
LCDLOGE("quec_lcd_init failed, para invalid!!! \r\n");
return -1;
}
lcd_pin_cfg(panel);
return 0;
}
int panel_sleep(struct panel_spec* panel)
{
LCDLOGD("+++");
if(panel->ops->panel_suspend){
return panel->ops->panel_suspend(panel);
}
LCDLOGD("---");
return -1;
}
int panel_wakeup(struct panel_spec* panel)
{
LCDLOGD("+++");
if(panel->ops->panel_resume){
return panel->ops->panel_resume(panel);
}
LCDLOGD("---");
return -1;
}
int panel_reset(struct panel_spec* panel)
{
if(NULL != panel->ops->panel_interface_reset){
panel->ops->panel_interface_reset(panel);
}
return -1;
}
int panel_write_cmd(struct panel_spec *self, unsigned int cmd, unsigned int bits)
{
struct s_spi_ctx* spi_ctx = self->panel_if;
return spi_write_cmd(spi_ctx, cmd, bits);
}
int panel_write_data(struct panel_spec *self, unsigned int data, unsigned int bits)
{
struct s_spi_ctx* spi_ctx = self->panel_if;
return spi_write_data(spi_ctx, data, bits);
}
unsigned int panel_read_id(struct panel_spec* panel)
{
if(NULL != panel->ops->panel_readid){
return panel->ops->panel_readid(panel);
}
return 0;
}
int panel_refresh_lcd(struct panel_spec* panel,struct asrlcdd_framebuffer_window *frame_window,unsigned short startX, unsigned short startY)
{
if(NULL != panel->ops->panel_refresh){
panel->ops->panel_refresh(panel,frame_window,startX,startY);
return 0;
}
return -1;
}
void panel_uninit(struct panel_spec *panel, int lcd_id)
{
int* p_panel_status;
if(NULL == panel){
LCDLOGE("Invalid param");
return;
}
if(lcd_id >= MAX_PANEL_COUNT){
LCDLOGE("Invalid lcd_id (%d)", lcd_id);
return;
}
if (NULL != panel->ops->panel_interface_uninit){
if (panel->ops->panel_interface_uninit(panel) != 0){
LCDLOGE("ERROR: panel_uninit: lcd interface uninit fail\r\n");
}
}
p_panel_status = &g_panel_status[lcd_id];
*p_panel_status = PANEL_STATUS_POWEROFF;
}
void panel_delay(int ms)
{
if(PANEL_MODE_ASSERT == g_panel_mode)
lcd_mdelay(ms);
else
lcd_msleep(ms);
}
void panel_cs_control(unsigned char val)
{
if(val == PANEL_CS_SET_HIGH)
spi_set_cs_high();
else
spi_set_cs_low();
}
int panel_init(struct panel_spec* panel, unsigned int sclk, int32_t work_mode, int panel_is_ready, int lcd_id)
{
//extern struct s_lcd_ctx *g_plcd;
int* p_panel_status;
int ret = 0;
LCDLOGD("INFO: panel_init (ready: %d) +++\r\n", panel_is_ready);
if(NULL == panel){
LCDLOGE("ERROR: panel_init, Invalid param\r\n");
return -1;
}
if(lcd_id >= MAX_PANEL_COUNT){
LCDLOGE("ERROR: panel_init, Invalid lcd_id (%d)\r\n", lcd_id);
return -1;
}
if(LCD_WORK_MODE_POLLING == work_mode)
g_panel_mode = PANEL_MODE_ASSERT;
else
g_panel_mode = PANEL_MODE_NORMAL;
p_panel_status = &g_panel_status[lcd_id];
if(*p_panel_status == PANEL_STATUS_POWERON){
if(NULL != panel->ops->panel_interface_update){
panel->ops->panel_interface_update(panel, work_mode);
}
else
return -1;
}
if(NULL != panel->ops->panel_interface_init){
panel->ops->panel_interface_init(panel, sclk, work_mode);
}
else
return -1;
if(NULL != panel->ops->panel_init){
panel->ops->panel_init(panel);
}
else
return -1;
*p_panel_status = PANEL_STATUS_POWERON;
LCDLOGD("INFO: panel_init ---\r\n");
return 0;
}
/***********************************************************************
*
* Name: quec_lcd_panel_interface_init
*
* Description: 1601的lcd控制器或者1603的spi总线初始化
*
* Parameters:
*
* Returns:
*
* Notes:
*
***********************************************************************/
static int quec_lcd_panel_interface_init(struct panel_spec *self, unsigned int sclk, int work_mode)
{
struct s_spi_ctx *spi_ctx = NULL;
struct spi_info * spi = NULL;
LCDLOGD(" panel_interface_init, spi+++\r\n");
if(NULL == self){
LCDLOGD(" panel_interface_init, Invalid param\r\n");
return -1;
}
spi = (struct spi_info *)self->info;
spi_ctx = spi_init(sclk, spi, work_mode);
if(NULL == spi_ctx){
LCDLOGD(" panel_interface_init, spi init fail!\r\n");
return -1;
}
self->panel_if = (void*)spi_ctx;
return 0;
}
/***********************************************************************
*
* Name: quec_lcd_panel_interface_update
*
* Description: 切换lcd的工作模式
*
* Parameters:
*
* Returns:
*
* Notes:
*
***********************************************************************/
static int quec_lcd_panel_interface_update(struct panel_spec *self, int work_mode)
{
int ret;
if(NULL == self || NULL == self->panel_if){
LCDLOGD("ERROR: lcd_panel_interface_update, Invalid param\r\n");
return -1;
}
ret = spi_update((struct s_spi_ctx *)self->panel_if, work_mode);
return ret;
}
/***********************************************************************
*
* Name: quec_lcd_panel_init
*
* Description: 预留接口,可以设置lcd角度
*
* Parameters:
*
* Returns:
*
* Notes:
*
***********************************************************************/
static int quec_lcd_panel_init(struct panel_spec *self)
{
if(NULL == self){
LCDLOGD("ERROR: panel_init, Invalid param\r\n");
return -1;
}
if(NULL == self->panel_if){
LCDLOGD("ERROR: panel_init, mcu has not been inited!\r\n");
return -1;
}
return 0;
}
/***********************************************************************
*
* Name: quec_lcd_panel_invalid
*
* Description: 向lcd发送显示范围指令
*
* Parameters:
*
* Returns:
*
* Notes:
*
***********************************************************************/
static int quec_lcd_panel_invalid(struct panel_spec *self, unsigned int start_x, unsigned int start_y, unsigned int end_x, unsigned int end_y)
{
struct s_spi_ctx* spi_ctx = NULL;
if(NULL == self){
LCDLOGD("ERROR: lcd_panel_invalid, Invalid param\r\n");
return -1;
}
if(NULL == self->panel_if){
LCDLOGD("ERROR: lcd_panel_invalid, mcu has not been inited!\r\n");
return -1;
}
spi_ctx = (struct s_spi_ctx*)self->panel_if;
spi_write_cmd(spi_ctx, 0x2A, 8);
spi_write_data(spi_ctx, ((start_x >> 8) & 0xFF), 8);
spi_write_data(spi_ctx, (start_x & 0xFF), 8);
spi_write_data(spi_ctx, ((end_x >> 8) & 0xFF), 8);
spi_write_data(spi_ctx, (end_x & 0xFF), 8);
spi_write_cmd(spi_ctx, 0x2B, 8);
spi_write_data(spi_ctx, ((start_y >> 8) & 0xFF), 8);
spi_write_data(spi_ctx, (start_y & 0xFF), 8);
spi_write_data(spi_ctx, ((end_y >> 8) & 0xFF), 8);
spi_write_data(spi_ctx, (end_y & 0xFF), 8);
spi_write_cmd(spi_ctx, 0x2C, 8);
return 0;
}
/***********************************************************************
*
* Name: quec_lcd_panel_readid
*
* Description: 获取lcd的id号
*
* Parameters:
*
* Returns:
*
* Notes:
*
***********************************************************************/
static unsigned int quec_lcd_panel_readid(struct panel_spec *self)
{
struct s_spi_ctx* spi_ctx = NULL;
unsigned int read_id = 0;
if(NULL == self){
LCDLOGD("ERROR: panel_readid, Invalid param\r\n");
return 0;
}
if(NULL == self->panel_if){
LCDLOGD("ERROR: panel_readid, spi has not been inited!\r\n");
return 0;
}
spi_ctx = (struct s_spi_ctx*)self->panel_if;
spi_read_data(spi_ctx, 0xDA, 8, &read_id, 8);
LCDLOGD("INFO: panel_readid, read 0xDA receive 0x%x!\r\n",read_id);
spi_read_data(spi_ctx, 0xDB, 8, &read_id, 8);
LCDLOGD("INFO: panel_readid, read 0xDB receive 0x%x!\r\n",read_id);
spi_read_data(spi_ctx, 0xDC, 8, &read_id, 8);
LCDLOGD("INFO: panel_readid, read 0xDC receive 0x%x!\r\n",read_id);
spi_read_data(spi_ctx, 0x04, 8, &read_id, 24);
LCDLOGD("INFO: panel_readid, read 0x04 receive 0x%x!\r\n",read_id);
return read_id;
}
/***********************************************************************
*
* Name:
*
* Description:
*
* Parameters:
*
* Returns:
*
* Notes:
*
***********************************************************************/
static int quec_lcd_panel_display_on(struct panel_spec *self)
{
struct s_spi_ctx* spi_ctx = NULL;
if(NULL == self){
LCDLOGD("ERROR: lcd_panel_display_on, Invalid param\r\n");
return -1;
}
if(NULL == self->panel_if){
LCDLOGD("ERROR: lcd_panel_display_on, mcu has not been inited!\r\n");
return -1;
}
spi_ctx = (struct s_spi_ctx*)self->panel_if;
quec_rtos_mutex_lock(g_cramem_mutex,QUEC_WAIT_FOREVER);
spi_write_cmd(spi_ctx, 0x11, 8);
panel_delay(120);
spi_write_cmd(spi_ctx, 0x29, 8);
panel_delay(20);
quec_rtos_mutex_unlock(g_cramem_mutex);
return 0;
}
/***********************************************************************
*
* Name:
*
* Description:
*
* Parameters:
*
* Returns:
*
* Notes:
*
***********************************************************************/
static int quec_lcd_panel_display_off(struct panel_spec *self)
{
struct s_spi_ctx* spi_ctx = NULL;
if(NULL == self){
LCDLOGD("ERROR: lcd_panel_display_off, Invalid param\r\n");
return -1;
}
if(NULL == self->panel_if){
LCDLOGD("ERROR: lcd_panel_display_off, mcu has not been inited!\r\n");
return -1;
}
spi_ctx = (struct s_spi_ctx*)self->panel_if;
quec_rtos_mutex_lock(g_cramem_mutex,QUEC_WAIT_FOREVER);
spi_write_cmd(spi_ctx, 0x28, 8);
panel_delay(20);
spi_write_cmd(spi_ctx, 0x10, 8);
panel_delay(120);
quec_rtos_mutex_unlock(g_cramem_mutex);
return 0;
}
/***********************************************************************
*
* Name:
*
* Description:
*
* Parameters:
*
* Returns:
*
* Notes:
*
***********************************************************************/
static void quec_lcd_panel_refresh(struct panel_spec *self,struct asrlcdd_framebuffer_window *frame_window,unsigned short startX, unsigned short startY)
{
struct s_spi_ctx* panel_if = (struct s_spi_ctx *)self->panel_if;
struct spi_info * spi = &(panel_if->info);
unsigned int size = 0;
unsigned short *addr = NULL;
struct asrlcdd_roi_info *src_roi_info = NULL;
struct asrlcdd_framebuffer_info *src_frame_buffer = NULL;
LCDLOGD("++++++\r\n");
if (NULL == self) {
LCDLOGE("ERROR: panel_init, Invalid param\r\n");
return;
}
if (NULL == panel_if) {
LCDLOGE("ERROR: panel_init, mcu has not been inited!\r\n");
return;
}
src_roi_info = &(frame_window->roi_info);
src_frame_buffer = &(frame_window->frame_info);
size = (src_roi_info->height)*(src_roi_info->width);
addr = (unsigned short *)src_frame_buffer->pbuffer;
if(self->ops->panel_invalid) //Set up LCD area pony add 2021-2-7
self->ops->panel_invalid(self,startX,startY,src_roi_info->width+startX-1,src_roi_info->height+startY-1);
else
LCDLOGE("panel_invalid not init\r\n");
if(spi->line_num ==4)
{
lcd_spi_set_data_mode();
}
spi_set_clk_rate(spi->timing->wclk);
panel_cs_control(PANEL_CS_SET_LOW);
if(spi->line_num==4)//只有4线lcd才支持dma pony add 2021-06-23
{
if(panel_if->work_mode == SPI_WORK_MODE_DMA)
{
CacheCleanMemory((void *)addr, src_roi_info->height*src_roi_info->width*2);
spi_write_data_dma(addr,size*2,16,spi->line_num);
}
else
ssp_write_data_to_LCD_Gram(addr,size,16,spi->line_num);//ssp_write_data_to_LCD_Gram(image,128*128,16,spi->line_num);
}
else
{
ssp_write_data_to_LCD_Gram(addr,size,16,spi->line_num);
}
wait_ssp_write_data_to_LCD_complete();
panel_cs_control(PANEL_CS_SET_HIGH);
}
static int lcd_panel_spi_uninit(struct panel_spec *self)
{
struct s_spi_ctx *spi_ctx = NULL;
LCDLOGD("+++");
if(NULL == self){
LCDLOGE("Invalid param");
return -1;
}
spi_ctx = (struct s_spi_ctx*)self->panel_if;
spi_uninit(spi_ctx); /*此接口未实现*/
self->panel_if = NULL;
LCDLOGD("---");
return 0;
}
static int lcd_panel_spi_reset(struct panel_spec *self)
{
struct s_spi_ctx *spi_ctx = NULL;
LCDLOGD("spi+++");
if(NULL == self){
LCDLOGE("Invalid param");
return -1;
}
spi_ctx = (struct s_spi_ctx*)self->panel_if;
spi_reset(spi_ctx);/*此接口未实现*/
LCDLOGD("spi---");
return 0;
}