lcd: add mipi-dsi checking panel state support
authorEvoke Zhang <evoke.zhang@amlogic.com>
Thu, 22 Feb 2018 10:36:38 +0000 (18:36 +0800)
committerYixun Lan <yixun.lan@amlogic.com>
Mon, 5 Mar 2018 07:34:34 +0000 (15:34 +0800)
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 <evoke.zhang@amlogic.com>
arch/arm64/boot/dts/amlogic/mesong12a_skt-panel.dtsi
drivers/amlogic/media/vout/lcd/lcd_debug.c
drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_tablet.c
drivers/amlogic/media/vout/lcd/lcd_tablet/mipi_dsi_util.c
drivers/amlogic/media/vout/lcd/lcd_tablet/mipi_dsi_util.h
drivers/amlogic/media/vout/lcd/lcd_vout.c
include/linux/amlogic/media/vout/lcd/lcd_vout.h

index 8f6946a..51d9380 100644 (file)
                                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)*/
                                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)*/
index 8bd5de9..5c7142d 100644 (file)
@@ -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;
index 3c2b562..5c30fa0 100644 (file)
@@ -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",
+                       &para[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",
                        &para[0], 8);
                if (ret) {
index 0b5c491..0b5f5c4 100644 (file)
@@ -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)
index cc80551..17ae84d 100644 (file)
@@ -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,
index a2854f1..d6f3bd5 100644 (file)
@@ -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 = {
index cfdd61f..7520be1 100644 (file)
@@ -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 {