diff --git a/drivers/amlogic/media/vout/lcd/lcd_common.h b/drivers/amlogic/media/vout/lcd/lcd_common.h index 61a9a8fdc32f..9eda786c3df7 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_common.h +++ b/drivers/amlogic/media/vout/lcd/lcd_common.h @@ -114,6 +114,7 @@ extern int lcd_tv_probe(struct device *dev); extern int lcd_tv_remove(struct device *dev); #endif #ifdef CONFIG_AMLOGIC_LCD_TABLET +int lcd_mipi_test_read(struct dsi_read_s *dread); extern void lcd_tablet_vout_server_init(void); extern void lcd_tablet_vout_server_remove(void); extern void lcd_tablet_clk_config_change(struct lcd_config_s *pconf); diff --git a/drivers/amlogic/media/vout/lcd/lcd_debug.c b/drivers/amlogic/media/vout/lcd/lcd_debug.c index ffae26961e38..d488117b0b54 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_debug.c +++ b/drivers/amlogic/media/vout/lcd/lcd_debug.c @@ -1054,7 +1054,7 @@ static void lcd_screen_restore(void) struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); unsigned int num; - num = lcd_drv->lcd_test_flag; + num = lcd_drv->lcd_test_state; num = (num >= LCD_ENC_TST_NUM_MAX) ? 0 : num; if (lcd_drv->workqueue) @@ -2902,76 +2902,110 @@ static ssize_t lcd_mipi_cmd_debug_store(struct class *class, return count; } -/* [0]=reg_addr, [1]=read_cnt */ -static unsigned char lcd_mipi_read_buf[2] = {0xff, 0}; +#define MIPI_RD_RET_CODE_MAX 5 +static char *mipi_read_ret_code_table[] = { + "success", + "read null", + "read error", + "read back cnt is wrong", + "timeout", + "unknown error", +}; + +static struct dsi_read_s dread = { + .flag = 0, + .reg = 0xff, + .cnt = 0, + .value = NULL, + .ret_code = 4, + + .line_start = 0x1fff, + .line_end = 0x1fff, +}; + static ssize_t lcd_mipi_read_debug_show(struct class *class, struct class_attribute *attr, char *buf) { struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); - int ret = 0, i, len; - unsigned char reg, cnt, *rd_data; - unsigned char payload[3] = {DT_GEN_RD_1, 1, 0x04}; + unsigned int i = 0, len; if ((lcd_drv->lcd_status & LCD_STATUS_IF_ON) == 0) return sprintf(buf, "error: panel is disabled\n"); - reg = lcd_mipi_read_buf[0]; - cnt = lcd_mipi_read_buf[1]; - if (reg == 0xff) - return sprintf(buf, "reg address is invalid\n"); - if (cnt == 0) - return sprintf(buf, "read count is invalid\n"); + if (dread.reg == 0xff) + return sprintf(buf, "error: reg address is invalid\n"); + if (dread.cnt == 0) + return sprintf(buf, "error: read count is invalid\n"); - rd_data = kcalloc(cnt, sizeof(unsigned char), GFP_KERNEL); - if (rd_data == NULL) - return sprintf(buf, "rd_data buf error\n"); + if (dread.cnt > DSI_READ_CNT_MAX) + return sprintf(buf, "error: mipi read cnt is out of support\n"); + if (dread.value == NULL) + return sprintf(buf, "error: mipi read return value is null\n"); + + dread.line_start = 0x1fff; + dread.line_end = 0x1fff; + dread.ret_code = 4; - payload[2] = reg; #ifdef CONFIG_AMLOGIC_LCD_TABLET - ret = dsi_read_single(payload, rd_data, cnt); - if (ret < 0) { - kfree(rd_data); - return sprintf(buf, "mipi-dsi read error\n"); - } - if (ret > cnt) { - kfree(rd_data); - return sprintf(buf, "mipi-dsi read 0x%02x back cnt is wrong\n", - reg); + if (lcd_drv->lcd_config->lcd_control.mipi_config->current_mode == 0) { + dread.flag = 1; + while (i++ < 5000) { + if (dread.flag == 0) + break; + udelay(20); + } + } else { + lcd_mipi_test_read(&dread); } #endif - len = sprintf(buf, "read reg 0x%02x: ", reg); - for (i = 0; i < ret; i++) { - if (i == 0) - len += sprintf(buf+len, "0x%02x", rd_data[i]); - else - len += sprintf(buf+len, ",0x%02x", rd_data[i]); + if (dread.ret_code) { + dread.ret_code = (dread.ret_code >= MIPI_RD_RET_CODE_MAX) ? + MIPI_RD_RET_CODE_MAX : dread.ret_code; + return sprintf(buf, "read error: %s(%d)\n", + mipi_read_ret_code_table[dread.ret_code], + dread.ret_code); } - len += sprintf(buf+len, "\n"); - kfree(rd_data); + len = sprintf(buf, "read reg 0x%02x: ", dread.reg); + for (i = 0; i < dread.cnt; i++) { + if (i == 0) + len += sprintf(buf+len, "0x%02x", dread.value[i]); + else + len += sprintf(buf+len, ",0x%02x", dread.value[i]); + } + + len += sprintf(buf+len, "\nread line start=%d, end=%d\n", + dread.line_start, dread.line_end); + return len; } static ssize_t lcd_mipi_read_debug_store(struct class *class, struct class_attribute *attr, const char *buf, size_t count) { - struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); unsigned int para[2]; int ret = 0; - if ((lcd_drv->lcd_status & LCD_STATUS_IF_ON) == 0) { - LCDERR("panel is disabled\n"); - return count; - } - ret = sscanf(buf, "%x %d", ¶[0], ¶[1]); if (ret < 2) { + dread.reg = 0xff; + dread.cnt = 0; pr_info("invalid data\n"); return count; } - lcd_mipi_read_buf[0] = (unsigned char)para[0]; - lcd_mipi_read_buf[1] = (unsigned char)para[1]; + dread.reg = (unsigned char)para[0]; + dread.cnt = (unsigned char)para[1]; + if (dread.cnt > DSI_READ_CNT_MAX) { + LCDERR("mipi read cnt is out of support\n"); + return count; + } + if (dread.value == NULL) { + LCDERR("mipi read return value is null\n"); + return count; + } + + pr_info("set mipi read reg: 0x%02x, cnt: %d\n", dread.reg, dread.cnt); return count; } @@ -3107,6 +3141,9 @@ int lcd_class_creat(void) } break; case LCD_MIPI: + dread.value = kcalloc(DSI_READ_CNT_MAX, sizeof(unsigned char), + GFP_KERNEL); + lcd_drv->lcd_config->lcd_control.mipi_config->dread = &dread; for (i = 0; i < ARRAY_SIZE (lcd_mipi_debug_class_attrs); i++) { if (class_create_file(lcd_drv->lcd_debug_class, diff --git a/drivers/amlogic/media/vout/lcd/lcd_reg.h b/drivers/amlogic/media/vout/lcd/lcd_reg.h index 7a5c8d58e07b..29f5d7a6d4a3 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_reg.h +++ b/drivers/amlogic/media/vout/lcd/lcd_reg.h @@ -1119,6 +1119,7 @@ * 0=ENCL, 1=ENCI, 2=ENCP, 3=ENCT. */ #define VPU_VIU_VENC_MUX_CTRL 0x271a +#define ENCL_INFO_READ 0x271f /* Bit 6 RW, gclk_mpeg_vpu_misc * Bit 5 RW, gclk_mpeg_venc_l_top diff --git a/drivers/amlogic/media/vout/lcd/lcd_tablet/mipi_dsi_util.c b/drivers/amlogic/media/vout/lcd/lcd_tablet/mipi_dsi_util.c index 175a3a3edb57..81bee22c22a2 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tablet/mipi_dsi_util.c +++ b/drivers/amlogic/media/vout/lcd/lcd_tablet/mipi_dsi_util.c @@ -2169,3 +2169,29 @@ void lcd_mipi_control_set(struct lcd_config_s *pconf, int status) mipi_dsi_host_off(); } +int lcd_mipi_test_read(struct dsi_read_s *dread) +{ + int ret = 0; + unsigned char payload[3] = {DT_GEN_RD_1, 1, 0x04}; + + if (dread == NULL) + return 1; + + dread->line_start = lcd_vcbus_getb(ENCL_INFO_READ, 16, 13); + + payload[2] = dread->reg; + ret = dsi_read_single(payload, dread->value, dread->cnt); + if (ret < 0) { + dread->ret_code = 2; + return 2; + } + if (ret > dread->cnt) { + dread->ret_code = 3; + return 3; + } + + dread->line_end = lcd_vcbus_getb(ENCL_INFO_READ, 16, 13); + + dread->ret_code = 0; + return 0; +} diff --git a/drivers/amlogic/media/vout/lcd/lcd_vout.c b/drivers/amlogic/media/vout/lcd/lcd_vout.c index 7d21061a1643..9cc196b08391 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_vout.c +++ b/drivers/amlogic/media/vout/lcd/lcd_vout.c @@ -373,10 +373,23 @@ static void lcd_resume_work(struct work_struct *p_work) static irqreturn_t lcd_vsync_isr(int irq, void *dev_id) { int flag; +#ifdef CONFIG_AMLOGIC_LCD_TABLET + struct lcd_config_s *pconf = lcd_driver->lcd_config; +#endif if ((lcd_driver->lcd_status & LCD_STATUS_ENCL_ON) == 0) return IRQ_HANDLED; +#ifdef CONFIG_AMLOGIC_LCD_TABLET + if (pconf->lcd_control.mipi_config->dread) { + if (pconf->lcd_control.mipi_config->dread->flag) { + lcd_mipi_test_read( + pconf->lcd_control.mipi_config->dread); + pconf->lcd_control.mipi_config->dread->flag = 0; + } + } +#endif + if (lcd_driver->lcd_mute_flag & LCD_MUTE_UPDATE) { flag = lcd_driver->lcd_mute_flag & 0x1; if (flag) { diff --git a/include/linux/amlogic/media/vout/lcd/lcd_vout.h b/include/linux/amlogic/media/vout/lcd/lcd_vout.h index 6b8cc4b34a44..ccf8a91ce624 100644 --- a/include/linux/amlogic/media/vout/lcd/lcd_vout.h +++ b/include/linux/amlogic/media/vout/lcd/lcd_vout.h @@ -267,6 +267,18 @@ struct vbyone_config_s { #define DSI_INIT_ON_MAX 100 #define DSI_INIT_OFF_MAX 30 +#define DSI_READ_CNT_MAX 30 +struct dsi_read_s { + unsigned char flag; + unsigned char reg; + unsigned char cnt; + unsigned char *value; + unsigned char ret_code; + + unsigned int line_start; + unsigned int line_end; +}; + struct dsi_config_s { unsigned char lane_num; unsigned int bit_rate_max; /* MHz */ @@ -294,6 +306,8 @@ struct dsi_config_s { unsigned char check_state; unsigned char current_mode; + + struct dsi_read_s *dread; }; struct lcd_control_config_s {