/*======================================================================================================================== Copyright (c) 2022 Quectel Wireless Solution, Co., Ltd. All Rights Reserved. Quectel Wireless Solution Proprietary and Confidential. ========================================================================================================================*/ /*================================================================= EDIT HISTORY FOR MODULE This section contains comments describing changes made to the module. Notice that changes are listed in reverse chronological order. WHEN WHO WHAT, WHERE, WHY ------------ ------- ------------------------------------------------------------------------------- 2022/04/26 Fias.fan 此文件用于LCD的主要驱动文件,---客户可根据硬件设计更改此文件的部分引脚 ==========================================================================================================================*/ #include "common.h" #include "bsp.h" #include #include "quec_spi_drv.h" #include "plat_types.h" #include "quec_ssp_lcd.h" struct panel_spec *g_ppanel = NULL; int g_lcd_status = LCD_STATUS_POWEROFF; //Todo..........需要客户根据硬件设计自行实现 //LCD电源域控制 void quec_lcd_power_ctrl(bool onoff) { LCDLOGD("quec_lcd_power_ctrl(%d) ++\r\n",onoff); //2>电源VDD&IOVDD上电,供电 if (PMIC_IS_PM803()) //ASR-1606-QUECTEL-ECxxxM系列 { if(onoff) { //GuilinLite_Ldo_6_set_2_8(); //GuilinLite_Ldo_6_set(1); } else { //GuilinLite_Ldo_6_set(0); } } LCDLOGD("quec_lcd_power_on --\r\n"); } //此延时函数,用于LCD-spi相关的延时 static __inline void uudelay(int us) { volatile uint32_t i; for(i=0; iinfo; quec_lcd_brightness_init(LCD_BACK_LIGHT);//背光初始化 quec_lcd_rst_init(LCD_RST_PIN);//复位引脚初始化 if(spi->line_num == 4)//如果是4线LCD,需要进行RS引脚初始化 { quec_lcd_rs_init(LCD_SPI_RS); } spi_ctx = spi_init(sclk, spi, work_mode); if (NULL == spi_ctx){ LCDLOGE("ERROR: panel_interface_init, spi init fail!\r\n"); return -1; } self->panel_if = (void*)spi_ctx; quec_lcd_power_ctrl(1); g_lcd_status = LCD_STATUS_HWON; return 0; } int quec_lcd_panel_spi_uninit(struct panel_spec *self) { struct s_spi_ctx *spi_ctx = NULL; LCDLOGD("DBG: lcd_panel_interface_uninit, spi+++\r\n"); if(CHIP_IS_CRANEM) { if(NULL == self){ LCDLOGE("ERROR: lcd_panel_interface_uninit, Invalid param\r\n"); return -1; } spi_ctx = (struct s_spi_ctx*)self->panel_if; spi_uninit(spi_ctx); self->panel_if = NULL; } quec_lcd_power_ctrl(0); g_lcd_status = LCD_STATUS_POWEROFF; LCDLOGD("DBG: lcd_panel_interface_uninit, spi---\r\n"); return 0; } static int quec_lcd_panel_spi_update(struct panel_spec *self, int32_t work_mode) { int ret=0; struct s_spi_ctx* spi_ctx = NULL; if (NULL == self || NULL == self->panel_if) { LCDLOGE("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; } //刷屏函数 void quec_lcd_panel_refresh(struct panel_spec *self,struct asrlcdd_framebuffer_window *frame_window,uint16_t startX, uint16_t startY) { struct s_spi_ctx* spi_ctx = NULL; struct spi_info * spi = NULL; 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 == self->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); spi_ctx = (struct s_spi_ctx*)self->panel_if; spi = (struct spi_info *)self->info; size = (src_roi_info->height)*(src_roi_info->width); addr = (unsigned short *)src_frame_buffer->pbuffer; if(self->ops->panel_invalid) //pony add 2021-2-7 刷图位置,,设置LCD的起始坐标和结束坐标 self->ops->panel_invalid(self,startX,startY,src_roi_info->width+startX-1,src_roi_info->height+startY-1); else printf("panel_invalid not init\r\n"); if(spi->line_num ==4) { quec_gpio_set_output(LCD_SPI_RS); quec_gpio_set_value(LCD_SPI_RS, 1); } spi_set_clk_rate(SPI_26M); quec_gpio_set_output(LCD_SPI_CS); //cs quec_gpio_set_value(LCD_SPI_CS, 0); ssp_write_data_to_LCD_Gram(addr,size,16,spi->line_num);// wait_ssp_write_data_to_LCD_complete();//等待spi tx fifo 为空 quec_gpio_set_value(LCD_SPI_CS, 1); //LCDLOGD("------\r\n"); } //读取ID static unsigned int quec_lcd_panel_readid(struct panel_spec *self) { struct s_spi_ctx* spi_ctx = NULL; uint32_t read_id = 0; if (NULL == self){ LCDLOGE("ERROR: panel_readid, Invalid param\r\n"); return 0; } if (NULL == self->panel_if) { LCDLOGE("ERROR: panel_readid, spi has not been inited!\r\n"); //return 0; } spi_ctx = (struct s_spi_ctx*)self->panel_if; if(CHIP_IS_CRANEM || CHIP_IS_CRANEL||CHIP_IS_CRANELRH)//ASR-1606&1603 { quec_gpio_set_output(LCD_RST_PIN); //rst mdelay(20); quec_gpio_set_value(LCD_RST_PIN, 0); mdelay(20); quec_gpio_set_value(LCD_RST_PIN, 1); mdelay(120); } spi_read_data(spi_ctx, 0xDA, 8, &read_id, 8); LCDLOGI("INFO: panel_readid, read 0xDA receive 0x%x!\r\n",read_id); spi_read_data(spi_ctx, 0xDB, 8, &read_id, 8); LCDLOGI("INFO: panel_readid, read 0xDB receive 0x%x!\r\n",read_id); spi_read_data(spi_ctx, 0xDC, 8, &read_id, 8); LCDLOGI("INFO: panel_readid, read 0xDC receive 0x%x!\r\n",read_id); spi_read_data(spi_ctx, 0x04, 8, &read_id, 24); /*read status*/ //spi_read_data(spi_ctx, 0x09, 8, &read_id, 32); //LCDLOGI("INFO: panel_readid, read 0x09 receive 0x%x!\r\n", read_id); return read_id; } static int quec_lcd_panel_display_on(struct panel_spec *self) { struct s_spi_ctx* spi_ctx = NULL; LCDLOGI("INFO: lcd_panel_display_on +++\r\n"); if (NULL == self ){ LCDLOGE("ERROR: lcd_panel_display_on, Invalid param\r\n"); return -1; } if (NULL == self->panel_if) { LCDLOGE("ERROR: lcd_panel_display_on, mcu has not been inited!\r\n"); return -1; } spi_ctx = (struct s_spi_ctx*)self->panel_if; spi_write_cmd(spi_ctx, 0x11, 8); mdelay(120); spi_write_cmd(spi_ctx, 0x29, 8); mdelay(20); return 0; } static int quec_lcd_panel_display_off(struct panel_spec *self) { struct s_spi_ctx* spi_ctx = NULL; LCDLOGI("INFO: lcd_panel_display_off +++\r\n"); if (NULL == self ){ LCDLOGE("ERROR: lcd_panel_display_off, Invalid param\r\n"); return -1; } if (NULL == self->panel_if) { LCDLOGE("ERROR: lcd_panel_display_off, mcu has not been inited!\r\n"); return -1; } spi_ctx = (struct s_spi_ctx*)self->panel_if; spi_write_cmd(spi_ctx, 0x28, 8); mdelay(20); spi_write_cmd(spi_ctx, 0x10, 8); mdelay(120); return 0; } static int quec_lcd_panel_invalid(struct panel_spec *self, uint32_t start_x, uint32_t start_y, uint32_t end_x, uint32_t end_y) { struct s_spi_ctx* spi_ctx = NULL; if (NULL == self){ LCDLOGE("ERROR: panel_init, Invalid param\r\n"); return -1; } if (NULL == self->panel_if){ LCDLOGE("ERROR: panel_init, 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; } static struct panel_operations quec_spi_ops = { quec_lcd_panel_spi_init, quec_lcd_panel_spi_update, NULL, quec_lcd_panel_invalid, quec_lcd_panel_display_off, quec_lcd_panel_display_on, quec_lcd_panel_readid, }; void lcd_7789v_lcd_panel_init(struct panel_spec *self) { struct s_spi_ctx* spi_ctx = NULL; LCDLOGE("lcd_panel_init_for_7789v\r\n"); if (NULL == self) { LCDLOGE("ERROR: panel_init, Invalid param\r\n"); return -1; } if (NULL == self->panel_if) { LCDLOGE("ERROR: panel_init, mcu has not been inited!\r\n"); return -1; } spi_ctx = (struct s_spi_ctx*)self->panel_if; //mdelay(120); spi_write_cmd(spi_ctx, 0x11, 8); mdelay(120); spi_write_cmd(spi_ctx,0x3A, 8); spi_write_data(spi_ctx,0x05, 8); spi_write_cmd(spi_ctx,0x35, 8); spi_write_data(spi_ctx,0x00, 8); spi_write_cmd(spi_ctx,0x36, 8); //此处放的太靠前会导致横竖屏设置失败 pony add 2021-06-02 #if 1 //横屏 spi_write_data(spi_ctx,0xa0, 8); #else spi_write_data(spi_ctx,0x00, 8); #endif spi_write_cmd(spi_ctx,0x44, 8); spi_write_data(spi_ctx,0x00, 8); spi_write_data(spi_ctx,0x1f, 8); spi_write_cmd(spi_ctx,0xB2, 8); spi_write_data(spi_ctx,0x0c, 8); spi_write_data(spi_ctx,0x0c, 8); spi_write_data(spi_ctx,0x00, 8); spi_write_data(spi_ctx,0x33, 8); spi_write_data(spi_ctx,0x33, 8); spi_write_cmd(spi_ctx,0xB7, 8); spi_write_data(spi_ctx,0x30, 8); spi_write_cmd(spi_ctx,0xBB, 8); spi_write_data(spi_ctx,0x34, 8); spi_write_cmd(spi_ctx,0xC0, 8); spi_write_data(spi_ctx,0x2C, 8); spi_write_cmd(spi_ctx,0xC2, 8); spi_write_data(spi_ctx,0x01, 8); spi_write_cmd(spi_ctx,0xC3, 8); spi_write_data(spi_ctx,0x17, 8); spi_write_cmd(spi_ctx,0xC4, 8); spi_write_data(spi_ctx,0x20, 8); spi_write_cmd(spi_ctx,0xC6, 8); //spi_write_data(spi_ctx,0x18, 8); spi_write_data(spi_ctx,0x0F, 8); spi_write_cmd(spi_ctx,0xD0, 8); spi_write_data(spi_ctx,0xA4, 8); spi_write_data(spi_ctx,0xA1, 8); spi_write_cmd(spi_ctx,0xE9, 8); spi_write_data(spi_ctx,0x0E, 8); spi_write_data(spi_ctx,0x0E, 8); spi_write_data(spi_ctx,0x04, 8); spi_write_cmd(spi_ctx,0xE0, 8); spi_write_data(spi_ctx,0xD0, 8); spi_write_data(spi_ctx,0x01, 8); spi_write_data(spi_ctx,0x09, 8); spi_write_data(spi_ctx,0x10, 8); spi_write_data(spi_ctx,0x11, 8); spi_write_data(spi_ctx,0x0B, 8); spi_write_data(spi_ctx,0x39, 8); spi_write_data(spi_ctx,0x54, 8); spi_write_data(spi_ctx,0x47, 8); spi_write_data(spi_ctx,0x3A, 8); spi_write_data(spi_ctx,0x17, 8); spi_write_data(spi_ctx,0x11, 8); spi_write_data(spi_ctx,0x20, 8); spi_write_data(spi_ctx,0x23, 8); spi_write_cmd(spi_ctx,0xE1, 8); spi_write_data(spi_ctx,0xD0, 8); spi_write_data(spi_ctx,0x01, 8); spi_write_data(spi_ctx,0x04, 8); spi_write_data(spi_ctx,0x0B, 8); spi_write_data(spi_ctx,0x0D, 8); spi_write_data(spi_ctx,0x18, 8); spi_write_data(spi_ctx,0x35, 8); spi_write_data(spi_ctx,0x44, 8); spi_write_data(spi_ctx,0x49, 8); spi_write_data(spi_ctx,0x2B, 8); spi_write_data(spi_ctx,0x15, 8); spi_write_data(spi_ctx,0x19, 8); spi_write_data(spi_ctx,0x14, 8); spi_write_data(spi_ctx,0x17, 8); spi_write_cmd(spi_ctx,0xE2, 8); spi_write_data(spi_ctx,0x00, 8); spi_write_data(spi_ctx,0x04, 8); spi_write_data(spi_ctx,0x08, 8); spi_write_data(spi_ctx,0x0C, 8); spi_write_data(spi_ctx,0x10, 8); spi_write_data(spi_ctx,0x14, 8); spi_write_data(spi_ctx,0x18, 8); spi_write_data(spi_ctx,0x1C, 8); spi_write_data(spi_ctx,0x20, 8); spi_write_data(spi_ctx,0x24, 8); spi_write_data(spi_ctx,0x28, 8); spi_write_data(spi_ctx,0x2C, 8); spi_write_data(spi_ctx,0x30, 8); spi_write_data(spi_ctx,0x34, 8); spi_write_data(spi_ctx,0x38, 8); spi_write_data(spi_ctx,0x3C, 8); spi_write_data(spi_ctx,0x40, 8); spi_write_data(spi_ctx,0x44, 8); spi_write_data(spi_ctx,0x48, 8); spi_write_data(spi_ctx,0x4C, 8); spi_write_data(spi_ctx,0x50, 8); spi_write_data(spi_ctx,0x54, 8); spi_write_data(spi_ctx,0x58, 8); spi_write_data(spi_ctx,0x5C, 8); spi_write_data(spi_ctx,0x60, 8); spi_write_data(spi_ctx,0x64, 8); spi_write_data(spi_ctx,0x68, 8); spi_write_data(spi_ctx,0x6C, 8); spi_write_data(spi_ctx,0x70, 8); spi_write_data(spi_ctx,0x74, 8); spi_write_data(spi_ctx,0x78, 8); spi_write_data(spi_ctx,0x7C, 8); spi_write_data(spi_ctx,0x80, 8); spi_write_data(spi_ctx,0x84, 8); spi_write_data(spi_ctx,0x88, 8); spi_write_data(spi_ctx,0x8C, 8); spi_write_data(spi_ctx,0x90, 8); spi_write_data(spi_ctx,0x94, 8); spi_write_data(spi_ctx,0x98, 8); spi_write_data(spi_ctx,0x9C, 8); spi_write_data(spi_ctx,0xA0, 8); spi_write_data(spi_ctx,0xA4, 8); spi_write_data(spi_ctx,0xA8, 8); spi_write_data(spi_ctx,0xAC, 8); spi_write_data(spi_ctx,0xB0, 8); spi_write_data(spi_ctx,0xB4, 8); spi_write_data(spi_ctx,0xB8, 8); spi_write_data(spi_ctx,0xBC, 8); spi_write_data(spi_ctx,0xC0, 8); spi_write_data(spi_ctx,0xC4, 8); spi_write_data(spi_ctx,0xC8, 8); spi_write_data(spi_ctx,0xCC, 8); spi_write_data(spi_ctx,0xD0, 8); spi_write_data(spi_ctx,0xD4, 8); spi_write_data(spi_ctx,0xD8, 8); spi_write_data(spi_ctx,0xDC, 8); spi_write_data(spi_ctx,0xE0, 8); spi_write_data(spi_ctx,0xE4, 8); spi_write_data(spi_ctx,0xE8, 8); spi_write_data(spi_ctx,0xEC, 8); spi_write_data(spi_ctx,0xF0, 8); spi_write_data(spi_ctx,0xF4, 8); spi_write_data(spi_ctx,0xF8, 8); spi_write_data(spi_ctx,0xFC, 8); spi_write_cmd(spi_ctx,0xE3, 8); spi_write_data(spi_ctx,0x00, 8); spi_write_data(spi_ctx,0x04, 8); spi_write_data(spi_ctx,0x07, 8); spi_write_data(spi_ctx,0x0A, 8); spi_write_data(spi_ctx,0x0E, 8); spi_write_data(spi_ctx,0x12, 8); spi_write_data(spi_ctx,0x16, 8); spi_write_data(spi_ctx,0x19, 8); spi_write_data(spi_ctx,0x1C, 8); spi_write_data(spi_ctx,0x1F, 8); spi_write_data(spi_ctx,0x23, 8); spi_write_data(spi_ctx,0x27, 8); spi_write_data(spi_ctx,0x2A, 8); spi_write_data(spi_ctx,0x2C, 8); spi_write_data(spi_ctx,0x30, 8); spi_write_data(spi_ctx,0x34, 8); spi_write_data(spi_ctx,0x38, 8); spi_write_data(spi_ctx,0x3C, 8); spi_write_data(spi_ctx,0x40, 8); spi_write_data(spi_ctx,0x44, 8); spi_write_data(spi_ctx,0x48, 8); spi_write_data(spi_ctx,0x4B, 8); spi_write_data(spi_ctx,0x4E, 8); spi_write_data(spi_ctx,0x51, 8); spi_write_data(spi_ctx,0x54, 8); spi_write_data(spi_ctx,0x58, 8); spi_write_data(spi_ctx,0x5C, 8); spi_write_data(spi_ctx,0x60, 8); spi_write_data(spi_ctx,0x64, 8); spi_write_data(spi_ctx,0x68, 8); spi_write_data(spi_ctx,0x6C, 8); spi_write_data(spi_ctx,0x70, 8); spi_write_data(spi_ctx,0x74, 8); spi_write_data(spi_ctx,0x78, 8); spi_write_data(spi_ctx,0x7C, 8); spi_write_data(spi_ctx,0x80, 8); spi_write_data(spi_ctx,0x84, 8); spi_write_data(spi_ctx,0x88, 8); spi_write_data(spi_ctx,0x8C, 8); spi_write_data(spi_ctx,0x91, 8); spi_write_data(spi_ctx,0x96, 8); spi_write_data(spi_ctx,0x9B, 8); spi_write_data(spi_ctx,0xA0, 8); spi_write_data(spi_ctx,0xA4, 8); spi_write_data(spi_ctx,0xA8, 8); spi_write_data(spi_ctx,0xAC, 8); spi_write_data(spi_ctx,0xB0, 8); spi_write_data(spi_ctx,0xB4, 8); spi_write_data(spi_ctx,0xB8, 8); spi_write_data(spi_ctx,0xBC, 8); spi_write_data(spi_ctx,0xC0, 8); spi_write_data(spi_ctx,0xC4, 8); spi_write_data(spi_ctx,0xC8, 8); spi_write_data(spi_ctx,0xCC, 8); spi_write_data(spi_ctx,0xD0, 8); spi_write_data(spi_ctx,0xD4, 8); spi_write_data(spi_ctx,0xDA, 8); spi_write_data(spi_ctx,0xE0, 8); spi_write_data(spi_ctx,0xE6, 8); spi_write_data(spi_ctx,0xEA, 8); spi_write_data(spi_ctx,0xF0, 8); spi_write_data(spi_ctx,0xF4, 8); spi_write_data(spi_ctx,0xF8, 8); spi_write_data(spi_ctx,0xFC, 8); spi_write_cmd(spi_ctx,0xBA, 8); spi_write_data(spi_ctx,0x04, 8); spi_write_cmd(spi_ctx,0x3A, 8); // 65k mode spi_write_data(spi_ctx,0x55, 8); spi_write_cmd(spi_ctx,0x2C, 8); spi_write_cmd(spi_ctx,0x29, 8); // display on return 0; } void ST7735s_lcd_panel_init(struct panel_spec *self) { struct s_spi_ctx* spi_ctx = NULL; LCDLOGE("lcd_panel_init_for_BOARD_CRANE_EVB ++\r\n"); if (NULL == self) { LCDLOGE("ERROR: panel_init, Invalid param\r\n"); return -1; } if (NULL == self->panel_if) { LCDLOGE("ERROR: panel_init, mcu has not been inited!\r\n"); return -1; } spi_ctx = (struct s_spi_ctx*)self->panel_if; spi_write_cmd(spi_ctx, 0x11, 8); mdelay(120); spi_write_cmd(spi_ctx, 0xB1, 8); spi_write_data(spi_ctx, 0x01, 8); spi_write_data(spi_ctx, 0x08, 8); spi_write_data(spi_ctx, 0x05, 8); spi_write_cmd(spi_ctx, 0xB2, 8); spi_write_data(spi_ctx, 0x05, 8); spi_write_data(spi_ctx, 0x3C, 8); spi_write_data(spi_ctx, 0x3C, 8); spi_write_cmd(spi_ctx, 0xB3, 8); spi_write_data(spi_ctx, 0x05, 8); spi_write_data(spi_ctx, 0x3C, 8); spi_write_data(spi_ctx, 0x3C, 8); spi_write_data(spi_ctx, 0x05, 8); spi_write_data(spi_ctx, 0x3C, 8); spi_write_data(spi_ctx, 0x3C, 8); spi_write_cmd(spi_ctx, 0xB4, 8); spi_write_data(spi_ctx, 0x03, 8); spi_write_cmd(spi_ctx, 0xC0, 8); spi_write_data(spi_ctx, 0x28, 8); spi_write_data(spi_ctx, 0x08, 8); spi_write_data(spi_ctx, 0x04, 8); spi_write_cmd(spi_ctx, 0xC1, 8); spi_write_data(spi_ctx, 0xC0, 8); spi_write_cmd(spi_ctx, 0xC2, 8); spi_write_data(spi_ctx, 0x0D, 8); spi_write_data(spi_ctx, 0x00, 8); spi_write_cmd(spi_ctx, 0xC3, 8); spi_write_data(spi_ctx, 0x8D, 8); spi_write_data(spi_ctx, 0x2A, 8); spi_write_cmd(spi_ctx, 0xC4, 8); spi_write_data(spi_ctx, 0x8D, 8); spi_write_data(spi_ctx, 0xEE, 8); spi_write_cmd(spi_ctx, 0xC5, 8); spi_write_data(spi_ctx, 0x12, 8); spi_write_cmd(spi_ctx, 0x36, 8); spi_write_data(spi_ctx, 0x00, 8); mdelay(120); spi_write_cmd(spi_ctx, 0xE0, 8); spi_write_data(spi_ctx, 0x04, 8); spi_write_data(spi_ctx, 0x22, 8); spi_write_data(spi_ctx, 0x07, 8); spi_write_data(spi_ctx, 0x0A, 8); spi_write_data(spi_ctx, 0x2E, 8); spi_write_data(spi_ctx, 0x30, 8); spi_write_data(spi_ctx, 0x25, 8); spi_write_data(spi_ctx, 0x2A, 8); spi_write_data(spi_ctx, 0x28, 8); spi_write_data(spi_ctx, 0x26, 8); spi_write_data(spi_ctx, 0x2E, 8); spi_write_data(spi_ctx, 0x3A, 8); spi_write_data(spi_ctx, 0x00, 8); spi_write_data(spi_ctx, 0x01, 8); spi_write_data(spi_ctx, 0x03, 8); spi_write_data(spi_ctx, 0x13, 8); spi_write_cmd(spi_ctx, 0xE1, 8); spi_write_data(spi_ctx, 0x04, 8); spi_write_data(spi_ctx, 0x16, 8); spi_write_data(spi_ctx, 0x06, 8); spi_write_data(spi_ctx, 0x0D, 8); spi_write_data(spi_ctx, 0x2D, 8); spi_write_data(spi_ctx, 0x26, 8); spi_write_data(spi_ctx, 0x23, 8); spi_write_data(spi_ctx, 0x27, 8); spi_write_data(spi_ctx, 0x27, 8); spi_write_data(spi_ctx, 0x25, 8); spi_write_data(spi_ctx, 0x2D, 8); spi_write_data(spi_ctx, 0x3B, 8); spi_write_data(spi_ctx, 0x00, 8); spi_write_data(spi_ctx, 0x01, 8); spi_write_data(spi_ctx, 0x04, 8); spi_write_data(spi_ctx, 0x13, 8); spi_write_cmd(spi_ctx, 0x3A, 8); spi_write_data(spi_ctx, 0x05, 8); /* Format is RGB565, if for RGB666, 0x05 -> 0x06 */ spi_write_cmd (spi_ctx, 0x35, 8); spi_write_data(spi_ctx, 0x00, 8); spi_write_cmd (spi_ctx, 0x29, 8); //display on spi_write_cmd (spi_ctx, 0x2C, 8); //mdelay(120); LCDLOGE("lcd_panel_init, spi has been inited!\r\n"); return 0; } static int st7735_lcd_panel_init(struct panel_spec *self) { struct s_spi_ctx* spi_ctx = NULL; struct spi_info * spi = NULL; if (NULL == self) { LCDLOGE("ERROR: panel_init, Invalid param\r\n"); return -1; } if (NULL == self->panel_if) { LCDLOGE("ERROR: panel_init, mcu has not been inited!\r\n"); return -1; } spi_ctx = (struct s_spi_ctx*)self->panel_if; spi = (struct spi_info *)self->info; spi_write_cmd(spi_ctx, 0x11, 8); mdelay(120); spi_write_cmd(spi_ctx, 0xB1, 8); spi_write_data(spi_ctx, 0x05, 8); spi_write_data(spi_ctx, 0x3A, 8); spi_write_data(spi_ctx, 0x3A, 8); spi_write_cmd(spi_ctx, 0xB2, 8); spi_write_data(spi_ctx, 0x05, 8); spi_write_data(spi_ctx, 0x3A, 8); spi_write_data(spi_ctx, 0x3A, 8); spi_write_cmd(spi_ctx, 0xB3, 8); spi_write_data(spi_ctx, 0x05, 8); spi_write_data(spi_ctx, 0x3A, 8); spi_write_data(spi_ctx, 0x3A, 8); spi_write_data(spi_ctx, 0x05, 8); spi_write_data(spi_ctx, 0x3A, 8); spi_write_data(spi_ctx, 0x3A, 8); spi_write_cmd(spi_ctx, 0xB4, 8); spi_write_data(spi_ctx, 0x03, 8); spi_write_cmd(spi_ctx, 0xC0, 8); spi_write_data(spi_ctx, 0x62, 8); spi_write_data(spi_ctx, 0x02, 8); spi_write_data(spi_ctx, 0x04, 8); spi_write_cmd(spi_ctx, 0xC1, 8); spi_write_data(spi_ctx, 0xC0, 8); spi_write_cmd(spi_ctx, 0xC2, 8); spi_write_data(spi_ctx, 0x0D, 8); spi_write_data(spi_ctx, 0x00, 8); spi_write_cmd(spi_ctx, 0xC3, 8); spi_write_data(spi_ctx, 0x8D, 8); spi_write_data(spi_ctx, 0x6A, 8); spi_write_cmd(spi_ctx, 0xC4, 8); spi_write_data(spi_ctx, 0x8D, 8); spi_write_data(spi_ctx, 0xEE, 8); spi_write_cmd(spi_ctx, 0xC5, 8); spi_write_data(spi_ctx, 0x12, 8); spi_write_cmd(spi_ctx, 0x36, 8); spi_write_data(spi_ctx, 0xC8, 8); mdelay(120); spi_write_cmd(spi_ctx, 0xE0, 8); spi_write_data(spi_ctx, 0x03, 8); spi_write_data(spi_ctx, 0x1B, 8); spi_write_data(spi_ctx, 0x12, 8); spi_write_data(spi_ctx, 0x11, 8); spi_write_data(spi_ctx, 0x3F, 8); spi_write_data(spi_ctx, 0x3A, 8); spi_write_data(spi_ctx, 0x32, 8); spi_write_data(spi_ctx, 0x34, 8); spi_write_data(spi_ctx, 0x2F, 8); spi_write_data(spi_ctx, 0x2B, 8); spi_write_data(spi_ctx, 0x30, 8); spi_write_data(spi_ctx, 0x3A, 8); spi_write_data(spi_ctx, 0x00, 8); spi_write_data(spi_ctx, 0x01, 8); spi_write_data(spi_ctx, 0x02, 8); spi_write_data(spi_ctx, 0x05, 8); spi_write_cmd(spi_ctx, 0xE1, 8); spi_write_data(spi_ctx, 0x03, 8); spi_write_data(spi_ctx, 0x1B, 8); spi_write_data(spi_ctx, 0x12, 8); spi_write_data(spi_ctx, 0x11, 8); spi_write_data(spi_ctx, 0x32, 8); spi_write_data(spi_ctx, 0x2F, 8); spi_write_data(spi_ctx, 0x2A, 8); spi_write_data(spi_ctx, 0x2F, 8); spi_write_data(spi_ctx, 0x2E, 8); spi_write_data(spi_ctx, 0x2C, 8); spi_write_data(spi_ctx, 0x35, 8); spi_write_data(spi_ctx, 0x3F, 8); spi_write_data(spi_ctx, 0x00, 8); spi_write_data(spi_ctx, 0x00, 8); spi_write_data(spi_ctx, 0x01, 8); spi_write_data(spi_ctx, 0x05, 8); spi_write_cmd(spi_ctx, 0x3A, 8); spi_write_data(spi_ctx, 0x05, 8); /* Format is RGB565, if for RGB666, 0x05 -> 0x06 */ #if 0 spi_write_cmd (spi_ctx, 0x35, 8); spi_write_data(spi_ctx, 0x00, 8); spi_write_cmd (spi_ctx, 0x29, 8); //display on //spi_write_cmd (spi_ctx, 0x2C, 8); mdelay(120); spi_write_cmd(spi_ctx, 0x2A, 8); spi_write_data(spi_ctx, 0, 8); spi_write_data(spi_ctx, 2, 8); spi_write_data(spi_ctx, 0, 8); spi_write_data(spi_ctx, 129, 8); spi_write_cmd(spi_ctx, 0x2B, 8); spi_write_data(spi_ctx, 0, 8); spi_write_data(spi_ctx, 3, 8); spi_write_data(spi_ctx, 0, 8); spi_write_data(spi_ctx, 130, 8); #endif spi_write_cmd(spi_ctx, 0x29, 8); //mdelay(120); LCDLOGE("lcd_panel_init, spi has been inited!\r\n"); return 0; } /* Note: this timing is not used in CraneM */ static struct timing_spi quec_spi_timing = { 13000, /*kHz wclk*/ 5000, /*kHz rckl*/ }; //note:choose 3_line or4_line static struct spi_info quec_lcd_info = { LCD_SPI_CONTROLLER_LINE, // 1, LCD_SPI_CONTROLLER_DATA_LINE, //数据线的个数 SPI_FORMAT_RGB565, 0, SPI_EDGE_RISING, 0, SPI_ENDIAN_MSB, 0, &quec_spi_timing, }; struct panel_spec quec_st7735_lcd_spec = { "st7735_spi_3w_1l_1i", 0x7c89f0, LCD_CAP_NOTE, 128, 128, LCD_MODE_SPI, LCD_POLARITY_POS, (&quec_lcd_info), NULL, &quec_spi_ops, }; struct panel_spec quec_st7735S_lcd_spec = { "st7735S_spi_4w_1l_1i", 0x7c89f0, LCD_CAP_NOTE, 128, 160, LCD_MODE_SPI, LCD_POLARITY_POS, (&quec_lcd_info), NULL, &quec_spi_ops, }; struct panel_spec quec_st7789v_lcd_spec = { "st7789v_spi_4w_1l_1i", 0x858552, LCD_CAP_NOTE, 320, 240, LCD_MODE_SPI, LCD_POLARITY_POS, (&quec_lcd_info), NULL, &quec_spi_ops, }; //驱动实例st7735 128*128 struct quec_lcd_driver quec_st7735_lcd_driver ={ &quec_st7735_lcd_spec, st7735_lcd_panel_init, }; //驱动实例st7735S 128*160 struct quec_lcd_driver quec_st7735S_lcd_driver ={ &quec_st7735S_lcd_spec, ST7735s_lcd_panel_init, }; //驱动实例st7789v struct quec_lcd_driver quec_st7789v_lcd_driver ={ &quec_st7789v_lcd_spec, lcd_7789v_lcd_panel_init, }; //新建驱动请放入此数组 struct quec_lcd_driver *quec_panel_list[]={ //&quec_st7735_lcd_driver, &quec_st7789v_lcd_driver, //&quec_st7735S_lcd_driver, }; struct panel_spec *quec_detect_lcd(void) { int i=0; unsigned int lcd_id = 0; struct panel_spec *panel=NULL; LCDLOGI("quec_detect_lcd +++\r\n"); for(i=0;i<(sizeof(quec_panel_list)/sizeof(quec_panel_list[0]));i++) { //初始化LCD的SPI和相关Pin quec_lcd_panel_spi_init(quec_panel_list[i]->quec_panel_spec ,LCD_SCLK_FREQ,LCD_WORK_MODE_POLLING); lcd_id =quec_lcd_panel_readid(quec_panel_list[i]->quec_panel_spec); LCDLOGI("+++++++read_lcd_id=%x,lcd_real_id=%x+++++++ line_num=%d\r\n",lcd_id,quec_panel_list[i]->quec_panel_spec->panel_id,quec_panel_list[i]->quec_panel_spec->info->line_num); if(quec_panel_list[i]->quec_panel_spec->panel_id == lcd_id) { panel = quec_panel_list[i]->quec_panel_spec; quec_panel_list[i]->lcd_panel_init(panel);//初始化外挂的LCD LCDLOGI("=================lcd_id=%x===================\r\n",lcd_id); return panel; }; } LCDLOGE("do not support this lcd\r\n"); return NULL; } int quec_lcd_close(void) { int i = 0; LCDLOGE("quec_lcd_close +++!\r\n"); if(CHIP_IS_CRANE)//ASR 1601&3601 { //ToDo... } else //ASR 1603&1606 { quec_gpio_set_output(LCD_SPI_CS); //cs quec_gpio_set_value(LCD_SPI_CS, 1);//cs默认拉高 g_lcd_status = LCD_STATUS_POWEROFF; } LCDLOGI("quec_lcd_close---\n"); return 0; } //LCD初始化接口 int quec_lcd_init(void) { int ret = -1; unsigned int lcd_id = 0; struct panel_spec *panel = NULL; LCDLOGI("Info: quec_lcd_init +++\r\n"); if((g_lcd_status != LCD_STATUS_POWEROFF) && (g_lcd_status != LCD_STATUS_HWON)) { LCDLOGE("Info: quec_lcd_init: asrlcd has been opened!\r\n"); return 0; } panel=quec_detect_lcd();//查找驱动初始化lcd if(panel == NULL) { quec_lcd_close(); LCDLOGE("lcd init failed"); ret = -1; return ret; } g_ppanel = panel; LCDLOGI("Info: quec_lcd_init ---\r\n"); return 0; } // //buffer:要写入到LCD的数据的起始地址 void quec_lcd_block_write_sync(UINT16* buffer, UINT16 startx,UINT16 starty,UINT16 endx,UINT16 endy) { struct asrlcdd_framebuffer_window frameBufferWin; UINT32 attempts = 0; LCDLOGI("quec_lcd_block_write_Sync +++\r\n"); unsigned short height = endy - starty + 1;// unsigned short width = endx - startx + 1;// frameBufferWin.frame_info.pbuffer = buffer; frameBufferWin.frame_info.stride = width*2;// frameBufferWin.frame_info.height = height; frameBufferWin.frame_info.bitdepth = 16;//RGB565 /*pony 2021-01-06注1:此处是画布大小应定义为屏幕大小所以图层刷图的起始地址是x,y而非0,0此处区别kernel侧*/ /*pony 2021-01-06注2:部分客户需求显示logo同时刷背景色,故此处画布大小在ASRLCDD_Logo_Blit16_sync调整为整屏大小,图层起始地址是相对画布而言的*/ frameBufferWin.roi_info.startX = 0; frameBufferWin.roi_info.startY = 0; frameBufferWin.roi_info.width = width; frameBufferWin.roi_info.height = height; CacheCleanMemory( (void *)buffer, width*height*2);//cache LCDLOGI("quec_lcd_block_write_Sync %d %d %d %d\r\n",startx, starty, endx, endy); if(CHIP_IS_CRANEM || CHIP_IS_CRANEL||CHIP_IS_CRANELRH) { frameBufferWin.roi_info.startX = 0; frameBufferWin.roi_info.startY = 0; quec_lcd_panel_refresh(g_ppanel,&frameBufferWin,startx,starty); LCDLOGI("quec_lcd_block_write_Sync ---\r\n"); return ; } } //清屏接口 //RGB565 --#define RED 0xF800 // 红色 // R G B int quec_lcd_clear_screen(unsigned int bg_color) { unsigned char *pbuffer = NULL; int i, j; #if 1 pbuffer = malloc(g_ppanel->width*g_ppanel->height*2); if (NULL == pbuffer) { uart_printf("malloc pbuffer failed! \n"); return -1; } #else //temp@20220427 logo阶段,直接使用mem,好危险 //pbuffer = (unsigned char *) (0x7E0E0010);//最大320*240*2=150Kb 不用这里,这里仅仅测试 #endif memset(pbuffer, 0, g_ppanel->width*g_ppanel->height*2); for(j=0; jheight; j++) { for(i=0; iwidth; i++) { *((UINT16*)(pbuffer+i*2+j*g_ppanel->width*2)) = bg_color; } } quec_lcd_block_write_sync((unsigned short *)pbuffer, 0, 0, g_ppanel->width-1, g_ppanel->height-1); free(pbuffer); return 0; } int quec_lcd_brightness_init(GPIO_PIN_NUMBER_E gpio_pin) { if(CHIP_IS_CRANEM || CHIP_IS_CRANEL||CHIP_IS_CRANELRH) { quec_gpio_set_output(gpio_pin); LCDLOGI("quec_lcd_brightness_init GPIO(%d)\r\n",gpio_pin); return 0; } //使用PWM的方式控制背光 //ToDo } int quec_lcd_rst_init(GPIO_PIN_NUMBER_E gpio_pin) { if(CHIP_IS_CRANEM || CHIP_IS_CRANEL||CHIP_IS_CRANELRH) { ql_gpio_init(gpio_pin,PIN_DIRECTION_OUT,PIN_PULL_DISABLE,PIN_LEVEL_HIGH); //rst--默认状态为高 LCDLOGI("quec_lcd_rst_init GPIO(%d)\r\n",gpio_pin); return 0; } //使用LCD控制器控制rst引脚 //ToDo } //命令&数据选择引脚,4line的LCD支持此引脚 int quec_lcd_rs_init(GPIO_PIN_NUMBER_E gpio_pin) { if(CHIP_IS_CRANEM || CHIP_IS_CRANEL||CHIP_IS_CRANELRH) { ql_gpio_init(gpio_pin,PIN_DIRECTION_OUT,PIN_PULL_DISABLE,PIN_LEVEL_HIGH); //rs--默认状态为高 LCDLOGI("quec_lcd_rst_init GPIO(%d)\r\n",gpio_pin); return 0; } } /*********************************************************************** * * Name: * * Description: 设置LCD背光等级 * * Parameters:level:0-5 * * Returns: * * Notes: * 如果使用GPIO作为背光引脚,那么只有关闭和打开; * 只有使用PWM方式才可以设置等级 ***********************************************************************/ int ql_lcd_set_brightness(unsigned int level) { //GPIO的方式 if(level == 0) { quec_gpio_set_value(LCD_BACK_LIGHT, 0); } else { quec_gpio_set_value(LCD_BACK_LIGHT, 1); } //PWM的方式 //ToDo return 0; } void ql_lcd_set_rts(unsigned int level) { quec_gpio_set_value(LCD_RST_PIN, level); //通过LCD的控制器控制 }