From 04c7f9095057e09da75aa94229bb4886275e48fc Mon Sep 17 00:00:00 2001 From: Evoke Zhang Date: Thu, 22 Feb 2018 18:36:38 +0800 Subject: [PATCH] lcd: add mipi-dsi checking panel state support PD#156734: lcd: add mipi-dsi checking panel state support after config check_state parameters in dts, you can get state by below sysfs node: cat /sys/class/lcd/mpstate Change-Id: I6e1d8452e17166cd9c04c2a4979f42308f995b9a Signed-off-by: Evoke Zhang --- .../boot/dts/amlogic/mesong12a_skt-panel.dtsi | 4 + drivers/amlogic/media/vout/lcd/lcd_debug.c | 22 +++-- .../media/vout/lcd/lcd_tablet/lcd_tablet.c | 20 ++++ .../media/vout/lcd/lcd_tablet/mipi_dsi_util.c | 96 ++++++++++++++++--- .../media/vout/lcd/lcd_tablet/mipi_dsi_util.h | 2 +- drivers/amlogic/media/vout/lcd/lcd_vout.c | 4 + .../linux/amlogic/media/vout/lcd/lcd_vout.h | 5 + 7 files changed, 135 insertions(+), 18 deletions(-) diff --git a/arch/arm64/boot/dts/amlogic/mesong12a_skt-panel.dtsi b/arch/arm64/boot/dts/amlogic/mesong12a_skt-panel.dtsi index 8f6946abbea1..51d938094585 100644 --- a/arch/arm64/boot/dts/amlogic/mesong12a_skt-panel.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesong12a_skt-panel.dtsi @@ -113,6 +113,8 @@ 0 /*clk_ss_level*/ 1 /*clk_auto_generate*/ 44250000>; /*pixel_clk(unit in Hz)*/ + check_state = <0x04 /* check_reg */ + 3>; /* check_cnt */ mipi_attr = <4 /*lane_num*/ 360 /*bit_rate_max(MHz)*/ 0 /*factor(*100, default 0 for auto)*/ @@ -154,6 +156,8 @@ 0 /*clk_ss_level*/ 1 /*clk_auto_generate*/ 48715200>; /*pixel_clk(unit in Hz)*/ + check_state = <0x04 /* check_reg */ + 3>; /* check_cnt */ mipi_attr = <4 /*lane_num*/ 300 /*bit_rate_max(MHz)*/ 0 /*factor(*100, default 0 for auto)*/ diff --git a/drivers/amlogic/media/vout/lcd/lcd_debug.c b/drivers/amlogic/media/vout/lcd/lcd_debug.c index 8bd5de9f320e..5c7142d3f0b7 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_debug.c +++ b/drivers/amlogic/media/vout/lcd/lcd_debug.c @@ -2763,6 +2763,16 @@ static ssize_t lcd_mipi_cmd_debug_store(struct class *class, return count; } +static ssize_t lcd_mipi_state_debug_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); + + return sprintf(buf, "state: %d, check_en: %d\n", + lcd_drv->lcd_config->lcd_control.mipi_config->check_state, + lcd_drv->lcd_config->lcd_control.mipi_config->check_en); +} + static struct class_attribute lcd_interface_debug_class_attrs[] = { __ATTR(ttl, 0644, lcd_ttl_debug_show, lcd_ttl_debug_store), @@ -2781,9 +2791,10 @@ static struct class_attribute lcd_phy_debug_class_attrs[] = { lcd_phy_debug_show, lcd_phy_debug_store), }; -static struct class_attribute lcd_mipi_cmd_debug_class_attrs[] = { +static struct class_attribute lcd_mipi_debug_class_attrs[] = { __ATTR(mpcmd, 0644, lcd_mipi_cmd_debug_show, lcd_mipi_cmd_debug_store), + __ATTR(mpstate, 0644, lcd_mipi_state_debug_show, NULL), }; int lcd_class_creat(void) @@ -2834,12 +2845,11 @@ int lcd_class_creat(void) break; case LCD_MIPI: for (i = 0; i < ARRAY_SIZE - (lcd_mipi_cmd_debug_class_attrs); i++) { + (lcd_mipi_debug_class_attrs); i++) { if (class_create_file(lcd_drv->lcd_debug_class, - &lcd_mipi_cmd_debug_class_attrs[i])) { - LCDERR("create mipi_cmd debug attr %s fail\n", - lcd_mipi_cmd_debug_class_attrs[ - i].attr.name); + &lcd_mipi_debug_class_attrs[i])) { + LCDERR("create mipi debug attr %s fail\n", + lcd_mipi_debug_class_attrs[i].attr.name); } } break; diff --git a/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_tablet.c b/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_tablet.c index 3c2b562803b4..5c30fa0629f4 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_tablet.c +++ b/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_tablet.c @@ -559,6 +559,12 @@ static void lcd_config_print(struct lcd_config_s *pconf) LCDPR("color_fmt = %d\n", pconf->lcd_control.vbyone_config->color_fmt); } else if (pconf->lcd_basic.lcd_type == LCD_MIPI) { + if (pconf->lcd_control.mipi_config->check_en) { + LCDPR("check_reg = 0x%02x\n", + pconf->lcd_control.mipi_config->check_reg); + LCDPR("check_cnt = %d\n", + pconf->lcd_control.mipi_config->check_cnt); + } LCDPR("mipi_lane_num = %d\n", pconf->lcd_control.mipi_config->lane_num); LCDPR("bit_rate_max = %d\n", @@ -813,6 +819,20 @@ static int lcd_config_load_from_dts(struct lcd_config_s *pconf, } break; case LCD_MIPI: + ret = of_property_read_u32_array(child, "check_state", + ¶[0], 2); + if (ret) { + if (lcd_debug_print_flag) + LCDPR("failed to get check_state\n"); + pconf->lcd_control.mipi_config->check_en = 0; + } else { + pconf->lcd_control.mipi_config->check_en = 1; + pconf->lcd_control.mipi_config->check_reg = + (unsigned char)(para[0]); + pconf->lcd_control.mipi_config->check_cnt = + (unsigned char)(para[1]); + } + ret = of_property_read_u32_array(child, "mipi_attr", ¶[0], 8); if (ret) { 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 0b5c49163e08..0b5f5c40422a 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 @@ -212,6 +212,14 @@ static void mipi_dsi_host_print_info(struct lcd_config_s *pconf) factor = dconf->factor_numerator; factor = ((factor * 1000 / dconf->factor_denominator) + 5) / 10; + if (dconf->check_en) { + pr_info("MIPI DSI check state:\n" + " check_reg: 0x%02x\n" + " check_cnt: %d\n" + " check_state %d\n\n", + dconf->check_reg, dconf->check_cnt, dconf->check_state); + } + pr_info("MIPI DSI Config:\n" " lane num: %d\n" " bit rate max: %dMHz\n" @@ -790,9 +798,10 @@ static unsigned int generic_if_wr(unsigned int address, unsigned int data_in) * Function: wait_bta_ack * Poll to check if the BTA ack is finished */ -static void wait_bta_ack(void) +static int wait_bta_ack(void) { - unsigned int phy_status, i; + unsigned int phy_status; + int i; /* Check if phydirection is RX */ i = CMD_TIMEOUT_CNT; @@ -801,8 +810,10 @@ static void wait_bta_ack(void) i--; phy_status = dsi_host_read(MIPI_DSI_DWC_PHY_STATUS_OS); } while ((((phy_status & 0x2) >> BIT_PHY_DIRECTION) == 0x0) && (i > 0)); - if (i == 0) + if (i == 0) { LCDERR("phy direction error: RX\n"); + return -1; + } /* Check if phydirection is return to TX */ i = CMD_TIMEOUT_CNT; @@ -810,9 +821,13 @@ static void wait_bta_ack(void) udelay(10); i--; phy_status = dsi_host_read(MIPI_DSI_DWC_PHY_STATUS_OS); - } while (((phy_status & 0x2) >> BIT_PHY_DIRECTION) == 0x1); - if (i == 0) + } while ((((phy_status & 0x2) >> BIT_PHY_DIRECTION) == 0x1) && (i > 0)); + if (i == 0) { LCDERR("phy direction error: TX\n"); + return -1; + } + + return 0; } /* ************************************************************* @@ -911,6 +926,7 @@ static int dsi_generic_read_packet(struct dsi_cmd_request_s *req, { unsigned int d_para[2], read_data; unsigned int i, j, done; + int ret = 0; switch (req->data_type) { case DT_GEN_RD_1: @@ -938,7 +954,10 @@ static int dsi_generic_read_packet(struct dsi_cmd_request_s *req, (d_para[0] << BIT_GEN_WC_LSBYTE) | (((unsigned int)req->vc_id) << BIT_GEN_VC) | (((unsigned int)req->data_type) << BIT_GEN_DT))); - wait_bta_ack(); + ret = wait_bta_ack(); + if (ret) + return -1; + i = 0; done = 0; while (done == 0) { @@ -965,6 +984,7 @@ static int dsi_dcs_read_packet(struct dsi_cmd_request_s *req, { unsigned int d_command, read_data; unsigned int i, j, done; + int ret = 0; d_command = ((unsigned int)req->payload[2]) & 0xff; @@ -975,7 +995,10 @@ static int dsi_dcs_read_packet(struct dsi_cmd_request_s *req, (d_command << BIT_GEN_WC_LSBYTE) | (((unsigned int)req->vc_id) << BIT_GEN_VC) | (((unsigned int)req->data_type) << BIT_GEN_DT))); - wait_bta_ack(); + ret = wait_bta_ack(); + if (ret) + return -1; + i = 0; done = 0; while (done == 0) { @@ -1276,7 +1299,7 @@ int dsi_write_cmd(unsigned char *payload) * Function: dsi_read_single * Supported Data Type: DT_GEN_RD_0, DT_GEN_RD_1, DT_GEN_RD_2, * DT_DCS_RD_0 - * Return: data count + * Return: data count, -1 for error */ int dsi_read_single(unsigned char *payload, unsigned char *rd_data, unsigned int rd_byte_len) @@ -1322,6 +1345,9 @@ int dsi_read_single(unsigned char *payload, unsigned char *rd_data, break; } + if (num < 0) + LCDERR("mipi-dsi read error\n"); + return num; } #else @@ -1329,7 +1355,7 @@ int dsi_read_single(unsigned char *payload, unsigned char *rd_data, unsigned int rd_byte_len) { LCDPR("Don't support mipi-dsi read command\n"); - return 0; + return -1; } #endif @@ -1590,6 +1616,45 @@ static void mipi_dsi_host_init(struct lcd_config_s *pconf) pconf); } +static void mipi_dsi_check_state(struct dsi_config_s *dconf, + unsigned char reg, int cnt) +{ + int ret = 0, i, len; + unsigned char *rd_data; + unsigned char payload[3] = {DT_GEN_RD_1, 1, 0x04}; + char str[100]; + + LCDPR("%s\n", __func__); + + rd_data = kmalloc_array(cnt, sizeof(unsigned char), GFP_KERNEL); + if (rd_data == NULL) { + LCDERR("%s: rd_data error\n", __func__); + return; + } + + payload[2] = reg; + ret = dsi_read_single(payload, rd_data, cnt); + if (ret < 0) { + dconf->check_state = 0; + lcd_vcbus_setb(L_VCOM_VS_ADDR, 0, 12, 1); + kfree(rd_data); + return; + } + + dconf->check_state = 1; + lcd_vcbus_setb(L_VCOM_VS_ADDR, 1, 12, 1); + len = sprintf(str, "read reg 0x%02x: ", reg); + for (i = 0; i < ret; i++) { + if (i == 0) + len += sprintf(str+len, "0x%02x", rd_data[i]); + else + len += sprintf(str+len, ",0x%02x", rd_data[i]); + } + pr_info("%s\n", str); + + kfree(rd_data); +} + static void mipi_dsi_link_on(struct lcd_config_s *pconf) { unsigned int op_mode_init, op_mode_disp; @@ -1605,6 +1670,9 @@ static void mipi_dsi_link_on(struct lcd_config_s *pconf) op_mode_init = dconf->operation_mode_init; op_mode_disp = dconf->operation_mode_display; + if (dconf->check_en) + mipi_dsi_check_state(dconf, dconf->check_reg, dconf->check_cnt); + #ifdef CONFIG_AMLOGIC_LCD_EXTERN if (dconf->extern_init < LCD_EXTERN_INDEX_INVALID) { lcd_ext = aml_lcd_extern_get_driver(dconf->extern_init); @@ -1616,6 +1684,7 @@ static void mipi_dsi_link_on(struct lcd_config_s *pconf) lcd_ext->config.table_init_on); LCDPR("[extern]%s dsi init on\n", lcd_ext->config.name); + goto mipi_dsi_link_disp; } } } @@ -1626,6 +1695,7 @@ static void mipi_dsi_link_on(struct lcd_config_s *pconf) LCDPR("dsi init on\n"); } +mipi_dsi_link_disp: if (op_mode_disp != op_mode_init) { set_mipi_dsi_host(MIPI_DSI_VIRTUAL_CHAN_ID, 0, /* Chroma sub sample, only for @@ -1787,8 +1857,9 @@ void lcd_mipi_dsi_config_post(struct lcd_config_s *pconf) /* phy config */ mipi_dsi_phy_config(&dsi_phy_config, dconf->bit_rate); - if (lcd_debug_print_flag) - mipi_dsi_host_print_info(pconf); + /* update check_state */ + if (dconf->check_en) + dconf->check_state = lcd_vcbus_getb(L_VCOM_VS_ADDR, 12, 1); } static void mipi_dsi_host_on(struct lcd_config_s *pconf) @@ -1798,6 +1869,9 @@ static void mipi_dsi_host_on(struct lcd_config_s *pconf) dsi_phy_config_set(pconf); mipi_dsi_link_on(pconf); + + if (lcd_debug_print_flag) + mipi_dsi_host_print_info(pconf); } static void mipi_dsi_host_off(void) diff --git a/drivers/amlogic/media/vout/lcd/lcd_tablet/mipi_dsi_util.h b/drivers/amlogic/media/vout/lcd/lcd_tablet/mipi_dsi_util.h index cc80551eefdf..17ae84d2f6cd 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tablet/mipi_dsi_util.h +++ b/drivers/amlogic/media/vout/lcd/lcd_tablet/mipi_dsi_util.h @@ -530,7 +530,7 @@ struct dsi_vid_s { }; #define DSI_CMD_SIZE_MAX 2000 -/* #define DSI_CMD_READ_VALID // DPHY don't support for M8 */ +#define DSI_CMD_READ_VALID extern void mipi_dsi_print_info(struct lcd_config_s *pconf); extern int lcd_mipi_dsi_init_table_detect(struct device_node *m_node, diff --git a/drivers/amlogic/media/vout/lcd/lcd_vout.c b/drivers/amlogic/media/vout/lcd/lcd_vout.c index a2854f104a81..d6f3bd536066 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_vout.c +++ b/drivers/amlogic/media/vout/lcd/lcd_vout.c @@ -128,6 +128,10 @@ static struct dsi_config_s lcd_mipi_config = { /* ext_index if needed, must match ext_config index; * 0xff for invalid */ + .check_en = 0, + .check_reg = 0, + .check_cnt = 0, + .check_state = 0, }; static struct lcd_power_ctrl_s lcd_power_config = { diff --git a/include/linux/amlogic/media/vout/lcd/lcd_vout.h b/include/linux/amlogic/media/vout/lcd/lcd_vout.h index cfdd61ff20ce..7520be140d74 100644 --- a/include/linux/amlogic/media/vout/lcd/lcd_vout.h +++ b/include/linux/amlogic/media/vout/lcd/lcd_vout.h @@ -288,6 +288,11 @@ struct dsi_config_s { unsigned char *dsi_init_on; unsigned char *dsi_init_off; unsigned char extern_init; + + unsigned char check_en; + unsigned char check_reg; + unsigned char check_cnt; + unsigned char check_state; }; struct lcd_control_config_s {