lcd: lcd_extern: add two i2c address support
authorEvoke Zhang <evoke.zhang@amlogic.com>
Fri, 10 Aug 2018 05:58:03 +0000 (13:58 +0800)
committerJianxin Pan <jianxin.pan@amlogic.com>
Tue, 21 Aug 2018 11:29:28 +0000 (04:29 -0700)
PD#169249: lcd: lcd_extern: add two i2c address support

Change-Id: Ic67304cd32768f5800b3702c57527e152bb71916
Signed-off-by: Evoke Zhang <evoke.zhang@amlogic.com>
30 files changed:
MAINTAINERS
arch/arm64/boot/dts/amlogic/mesonaxg_s400-panel.dtsi
arch/arm64/boot/dts/amlogic/mesong12a_skt-panel.dtsi
arch/arm64/boot/dts/amlogic/mesong12b_skt-panel.dtsi
arch/arm64/boot/dts/amlogic/mesongxm_q200-panel.dtsi
arch/arm64/boot/dts/amlogic/mesontxlx_r311-panel.dtsi
drivers/amlogic/media/vout/lcd/lcd_common.c
drivers/amlogic/media/vout/lcd/lcd_extern/Makefile
drivers/amlogic/media/vout/lcd/lcd_extern/ext_default.c
drivers/amlogic/media/vout/lcd/lcd_extern/ext_i2c_dev.c [new file with mode: 0644]
drivers/amlogic/media/vout/lcd/lcd_extern/i2c_DLPC3439.c
drivers/amlogic/media/vout/lcd/lcd_extern/i2c_T5800Q.c
drivers/amlogic/media/vout/lcd/lcd_extern/i2c_anx6345.c
drivers/amlogic/media/vout/lcd/lcd_extern/i2c_tc101.c
drivers/amlogic/media/vout/lcd/lcd_extern/lcd_extern.c
drivers/amlogic/media/vout/lcd/lcd_extern/lcd_extern.dts [deleted file]
drivers/amlogic/media/vout/lcd/lcd_extern/lcd_extern.h
drivers/amlogic/media/vout/lcd/lcd_extern/mipi_KD080D13.c
drivers/amlogic/media/vout/lcd/lcd_extern/mipi_N070ICN.c
drivers/amlogic/media/vout/lcd/lcd_extern/mipi_P070ACB.c
drivers/amlogic/media/vout/lcd/lcd_extern/mipi_ST7701.c
drivers/amlogic/media/vout/lcd/lcd_extern/mipi_TL050FHV02CT.c
drivers/amlogic/media/vout/lcd/lcd_extern/mipi_TV070WSM.c
drivers/amlogic/media/vout/lcd/lcd_extern/mipi_default.c
drivers/amlogic/media/vout/lcd/lcd_extern/spi_LD070WS2.c
drivers/amlogic/media/vout/lcd/lcd_tablet/mipi_dsi_util.c
drivers/amlogic/media/vout/lcd/lcd_vout.c
include/linux/amlogic/media/vout/lcd/lcd_extern.h
include/linux/amlogic/media/vout/lcd/lcd_notify.h
include/linux/amlogic/media/vout/lcd/lcd_vout.h

index 44276d6..a84a9f0 100644 (file)
@@ -14596,6 +14596,10 @@ AMLOGIC SOUND ADC3101
 M: Renjun Xu <renjun.xu@amlogic.com>
 F: Documentation/devicetree/bindings/amlogic/axg-sound-adc3010-d608mic-pcm.txt
 
+AMLOGIC LCD EXTERN DRIVER
+M:      evoke zhang <evoke.zhang@amlogic.com>
+F:      drivers/amlogic/media/vout/lcd/lcd_extern/ext_i2c_dev.c
+
 AMLOGIC SYSTEM AS ROOT
 M:     Xindong Xu  <xindong.xu@amlogic.com>
 F:     arch/arm64/boot/dts/amlogic/firmware_avb_system.dtsi
index ac279f9..ae856c7 100644 (file)
                compatible = "amlogic, lcd_extern";
                dev_name = "lcd_extern";
                status = "okay";
+               i2c_bus = "i2c_bus_1";
                key_valid = <0>;
 
                extern_0{
index 8a5b9a5..622f5c3 100644 (file)
                compatible = "amlogic, lcd_extern";
                dev_name = "lcd_extern";
                status = "okay";
+               i2c_bus = "i2c_bus_0";
                key_valid = <0>;
 
                extern_0{
index 8caa15d..0ca4d8a 100644 (file)
                compatible = "amlogic, lcd_extern";
                dev_name = "lcd_extern";
                status = "okay";
+               i2c_bus = "i2c_bus_0";
                key_valid = <0>;
 
                extern_0{
index 59fdf06..0251205 100644 (file)
@@ -89,6 +89,7 @@
                compatible = "amlogic, lcd_extern";
                dev_name = "lcd_extern";
                status = "okay";
+               i2c_bus = "i2c_bus_d";
                key_valid = <0>;
 
                extern_0{
@@ -98,7 +99,6 @@
                        type = <0>; /* 0=i2c, 1=spi, 2=mipi */
                        i2c_address = <0x1c>; /* 7bit i2c address */
                        i2c_second_address = <0xff>; /* 0xff for none */
-                       i2c_bus = "i2c_bus_d";
                        cmd_size = <0xff>; /*0xff for dynamic cmd_size*/
 
                        /* init on/off:
index fce0ec3..ca4ef2c 100644 (file)
                        type = <0>; /*0=i2c, 1=spi, 2=mipi*/
                        i2c_address = <0x1c>; /*7bit i2c_addr*/
                        i2c_second_address = <0xff>;
-                       i2c_bus = "i2c_bus_c";
                        cmd_size = <0xff>; /*dynamic cmd_size*/
 
                        /* init on/off:
                        status = "disabled";
                        type = <0>; /* 0=i2c, 1=spi, 2=mipi */
                        i2c_address = <0x1c>; /* 7bit i2c address */
-                       i2c_bus = "i2c_bus_c";
                        cmd_size = <9>;
                };
        };
index 7af5172..e988251 100644 (file)
@@ -471,13 +471,16 @@ int lcd_power_load_from_dts(struct lcd_config_s *pconf,
                                "power_on_step", j, &val);
                        lcd_power->power_on_step[i].delay = val;
 
-                       /* gpio probe */
+                       /* gpio/extern probe */
+                       index = lcd_power->power_on_step[i].index;
                        switch (lcd_power->power_on_step[i].type) {
                        case LCD_POWER_TYPE_CPU:
-                               index = lcd_power->power_on_step[i].index;
                                if (index < LCD_CPU_GPIO_NUM_MAX)
                                        lcd_cpu_gpio_probe(index);
                                break;
+                       case LCD_POWER_TYPE_EXTERN:
+                               pconf->extern_index = index;
+                               break;
                        default:
                                break;
                        }
@@ -522,13 +525,17 @@ int lcd_power_load_from_dts(struct lcd_config_s *pconf,
                                "power_off_step", j, &val);
                        lcd_power->power_off_step[i].delay = val;
 
-                       /* gpio probe */
+                       /* gpio/extern probe */
+                       index = lcd_power->power_off_step[i].index;
                        switch (lcd_power->power_off_step[i].type) {
                        case LCD_POWER_TYPE_CPU:
-                               index = lcd_power->power_off_step[i].index;
                                if (index < LCD_CPU_GPIO_NUM_MAX)
                                        lcd_cpu_gpio_probe(index);
                                break;
+                       case LCD_POWER_TYPE_EXTERN:
+                               if (pconf->extern_index == 0xff)
+                                       pconf->extern_index = index;
+                               break;
                        default:
                                break;
                        }
@@ -591,13 +598,16 @@ int lcd_power_load_from_unifykey(struct lcd_config_s *pconf,
                        (*(p + LCD_UKEY_PWR_DELAY + 5*i) |
                        ((*(p + LCD_UKEY_PWR_DELAY + 5*i + 1)) << 8));
 
-               /* gpio probe */
+               /* gpio/extern probe */
+               index = pconf->lcd_power->power_on_step[i].index;
                switch (pconf->lcd_power->power_on_step[i].type) {
                case LCD_POWER_TYPE_CPU:
-                       index = pconf->lcd_power->power_on_step[i].index;
                        if (index < LCD_CPU_GPIO_NUM_MAX)
                                lcd_cpu_gpio_probe(index);
                        break;
+               case LCD_POWER_TYPE_EXTERN:
+                       pconf->extern_index = index;
+                       break;
                default:
                        break;
                }
@@ -639,13 +649,17 @@ int lcd_power_load_from_unifykey(struct lcd_config_s *pconf,
                                (*(p + LCD_UKEY_PWR_DELAY + 5*j) |
                                ((*(p + LCD_UKEY_PWR_DELAY + 5*j + 1)) << 8));
 
-               /* gpio probe */
+               /* gpio/extern probe */
+               index = pconf->lcd_power->power_off_step[j].index;
                switch (pconf->lcd_power->power_off_step[j].type) {
                case LCD_POWER_TYPE_CPU:
-                       index = pconf->lcd_power->power_off_step[j].index;
                        if (index < LCD_CPU_GPIO_NUM_MAX)
                                lcd_cpu_gpio_probe(index);
                        break;
+               case LCD_POWER_TYPE_EXTERN:
+                       if (pconf->extern_index == 0xff)
+                               pconf->extern_index = index;
+                       break;
                default:
                        break;
                }
index 91bc8b3..fed2ce1 100644 (file)
@@ -1,7 +1,7 @@
-obj-$(CONFIG_AMLOGIC_LCD_EXTERN)                       += lcd_extern.o ext_default.o mipi_default.o
+obj-$(CONFIG_AMLOGIC_LCD_EXTERN)                       += lcd_extern.o ext_default.o mipi_default.o ext_i2c_dev.o
 obj-$(CONFIG_AMLOGIC_LCD_EXTERN_I2C_T5800Q)            += i2c_T5800Q.o
-obj-$(CONFIG_AMLOGIC_LCD_EXTERN_SPI_LD070WS2)          += spi_LD070WS2.o
 obj-$(CONFIG_AMLOGIC_LCD_EXTERN_I2C_DLPC3439)          += i2c_DLPC3439.o
+obj-$(CONFIG_AMLOGIC_LCD_EXTERN_SPI_LD070WS2)          += spi_LD070WS2.o
 obj-$(CONFIG_AMLOGIC_LCD_EXTERN_MIPI_KD080D13)         += mipi_KD080D13.o
 obj-$(CONFIG_AMLOGIC_LCD_EXTERN_MIPI_TV070WSM)         += mipi_TV070WSM.o
 obj-$(CONFIG_AMLOGIC_LCD_EXTERN_MIPI_ST7701)           += mipi_ST7701.o
index a509a08..5821417 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
 #include <linux/i2c.h>
-#include <linux/amlogic/i2c-amlogic.h>
 #include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/amlogic/media/vout/lcd/lcd_extern.h>
 #include "lcd_extern.h"
 
-#define LCD_EXTERN_INDEX          0
 #define LCD_EXTERN_NAME           "ext_default"
 
-#define LCD_EXTERN_TYPE           LCD_EXTERN_I2C
-
-#define LCD_EXTERN_I2C_ADDR       (0x1c) /* 7bit address */
-#define LCD_EXTERN_I2C_ADDR2      (0xff) /* 7bit address */
-#define LCD_EXTERN_I2C_BUS        AML_I2C_MASTER_A
-
-#define SPI_GPIO_CS               0 /* index */
-#define SPI_GPIO_CLK              1 /* index */
-#define SPI_GPIO_DATA             2 /* index */
-#define SPI_CLK_FREQ              10000 /* Hz */
-#define SPI_CLK_POL               1
+#define LCD_EXTERN_TYPE           LCD_EXTERN_MAX
 
 static struct lcd_extern_config_s *ext_config;
-static struct aml_lcd_extern_i2c_dev_s *i2c_device;
-
-#define LCD_EXTERN_CMD_SIZE        9
-static unsigned char init_on_table[] = {
-       0x00, 0x20, 0x01, 0x02, 0x00, 0x40, 0xFF, 0x00, 0x00,
-       0x00, 0x80, 0x02, 0x00, 0x40, 0x62, 0x51, 0x73, 0x00,
-       0x00, 0x61, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0xC1, 0x05, 0x0F, 0x00, 0x08, 0x70, 0x00, 0x00,
-       0x00, 0x13, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x3D, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0xED, 0x0D, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x23, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A,  /* delay 10ms */
-       0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  /* ending */
-};
-
-static unsigned char init_off_table[] = {
-       0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  /* ending */
-};
-
-static int lcd_extern_i2c_write(struct i2c_client *i2client,
-               unsigned char *buff, unsigned int len)
-{
-       int ret = 0;
-       struct i2c_msg msg[] = {
-               {
-                       .addr = i2client->addr,
-                       .flags = 0,
-                       .len = len,
-                       .buf = buff,
-               }
-       };
+static struct aml_lcd_extern_i2c_dev_s *i2c0_dev;
+static struct aml_lcd_extern_i2c_dev_s *i2c1_dev;
 
-       ret = i2c_transfer(i2client->adapter, msg, 1);
-       if (ret < 0)
-               EXTERR("i2c write failed [addr 0x%02x]\n", i2client->addr);
-
-       return ret;
-}
 
 static void set_lcd_csb(unsigned int v)
 {
@@ -154,15 +107,61 @@ static int lcd_extern_spi_write(unsigned char *buf, int len)
 
 static int lcd_extern_reg_read(unsigned char reg, unsigned char *buf)
 {
+       struct aml_lcd_extern_i2c_dev_s *i2c_dev;
+       unsigned char tmp;
        int ret = 0;
 
+       tmp = reg;
+       switch (ext_config->type) {
+       case LCD_EXTERN_I2C:
+               if (ext_config->addr_sel)
+                       i2c_dev = i2c1_dev;
+               else
+                       i2c_dev = i2c0_dev;
+               if (i2c_dev == NULL) {
+                       EXTERR("invalid i2c device\n");
+                       return -1;
+               }
+               lcd_extern_i2c_read(i2c_dev->client, &tmp, 1);
+               buf[0] = tmp;
+               break;
+       case LCD_EXTERN_SPI:
+               EXTPR("not support\n");
+               break;
+       default:
+               break;
+       }
+
        return ret;
 }
 
 static int lcd_extern_reg_write(unsigned char reg, unsigned char value)
 {
+       struct aml_lcd_extern_i2c_dev_s *i2c_dev;
+       unsigned char tmp[2];
        int ret = 0;
 
+       tmp[0] = reg;
+       tmp[1] = value;
+       switch (ext_config->type) {
+       case LCD_EXTERN_I2C:
+               if (ext_config->addr_sel)
+                       i2c_dev = i2c1_dev;
+               else
+                       i2c_dev = i2c0_dev;
+               if (i2c_dev == NULL) {
+                       EXTERR("invalid i2c device\n");
+                       return -1;
+               }
+               lcd_extern_i2c_write(i2c_dev->client, tmp, 2);
+               break;
+       case LCD_EXTERN_SPI:
+               lcd_extern_spi_write(tmp, 2);
+               break;
+       default:
+               break;
+       }
+
        return ret;
 }
 
@@ -219,17 +218,23 @@ static int lcd_extern_power_cmd_dynamic_size(unsigned char *init_table,
                                if (init_table[i+4] > 0)
                                        mdelay(init_table[i+4]);
                        } else if (type == LCD_EXTERN_INIT_CMD) {
-                               if (i2c_device == NULL) {
-                                       EXTERR("invalid i2c device\n");
+                               if (i2c0_dev == NULL) {
+                                       EXTERR("invalid i2c0 device\n");
                                        return -1;
                                }
-                               ret = lcd_extern_i2c_write(
-                                       i2c_device->client,
+                               ret = lcd_extern_i2c_write(i2c0_dev->client,
                                        &init_table[i+2], (cmd_size-1));
                                if (init_table[i+cmd_size+1] > 0)
                                        mdelay(init_table[i+cmd_size+1]);
                        } else if (type == LCD_EXTERN_INIT_CMD2) {
-                               EXTPR("%s not support cmd2\n", __func__);
+                               if (i2c1_dev == NULL) {
+                                       EXTERR("invalid i2c1 device\n");
+                                       return -1;
+                               }
+                               ret = lcd_extern_i2c_write(i2c1_dev->client,
+                                       &init_table[i+2], (cmd_size-1));
+                               if (init_table[i+cmd_size+1] > 0)
+                                       mdelay(init_table[i+cmd_size+1]);
                        } else {
                                EXTERR("%s(%d: %s): type %d invalid\n",
                                        __func__, ext_config->index,
@@ -332,15 +337,19 @@ static int lcd_extern_power_cmd_fixed_size(unsigned char *init_table, int flag)
                                                init_table[i+2]);
                                }
                        } else if (type == LCD_EXTERN_INIT_CMD) {
-                               if (i2c_device == NULL) {
-                                       EXTERR("invalid i2c device\n");
+                               if (i2c0_dev == NULL) {
+                                       EXTERR("invalid i2c0 device\n");
                                        return -1;
                                }
-                               ret = lcd_extern_i2c_write(
-                                       i2c_device->client,
+                               ret = lcd_extern_i2c_write(i2c0_dev->client,
                                        &init_table[i+1], (cmd_size-2));
                        } else if (type == LCD_EXTERN_INIT_CMD2) {
-                               EXTPR("%s not support cmd2\n", __func__);
+                               if (i2c1_dev == NULL) {
+                                       EXTERR("invalid i2c1 device\n");
+                                       return -1;
+                               }
+                               ret = lcd_extern_i2c_write(i2c1_dev->client,
+                                       &init_table[i+1], (cmd_size-2));
                        } else {
                                EXTERR("%s(%d: %s): type %d invalid\n",
                                        __func__, ext_config->index,
@@ -435,21 +444,21 @@ static int lcd_extern_power_ctrl(int flag)
        return ret;
 }
 
-static int lcd_extern_power_on(struct aml_lcd_extern_driver_s *ext_drv)
+static int lcd_extern_power_on(void)
 {
        int ret;
 
-       lcd_extern_pinmux_set(ext_drv, 1);
+       lcd_extern_pinmux_set(1);
        ret = lcd_extern_power_ctrl(1);
        return ret;
 }
 
-static int lcd_extern_power_off(struct aml_lcd_extern_driver_s *ext_drv)
+static int lcd_extern_power_off(void)
 {
        int ret;
 
-       lcd_extern_pinmux_set(ext_drv, 0);
        ret = lcd_extern_power_ctrl(0);
+       lcd_extern_pinmux_set(0);
        return ret;
 }
 
@@ -460,35 +469,9 @@ static int lcd_extern_driver_update(struct aml_lcd_extern_driver_s *ext_drv)
                return -1;
        }
 
-       if (ext_drv->config.type == LCD_EXTERN_MAX) { /* default for no dts */
-               ext_drv->config.index = LCD_EXTERN_INDEX;
-               ext_drv->config.type = LCD_EXTERN_TYPE;
-               strcpy(ext_drv->config.name, LCD_EXTERN_NAME);
-               ext_drv->config.cmd_size = LCD_EXTERN_CMD_SIZE;
-               switch (ext_drv->config.type) {
-               case LCD_EXTERN_I2C:
-                       ext_drv->config.i2c_addr = LCD_EXTERN_I2C_ADDR;
-                       ext_drv->config.i2c_addr2 = LCD_EXTERN_I2C_ADDR2;
-                       ext_drv->config.i2c_bus = LCD_EXTERN_I2C_BUS;
-                       break;
-               case LCD_EXTERN_SPI:
-                       ext_drv->config.spi_gpio_cs = SPI_GPIO_CS;
-                       ext_drv->config.spi_gpio_clk = SPI_GPIO_CLK;
-                       ext_drv->config.spi_gpio_data = SPI_GPIO_DATA;
-                       ext_drv->config.spi_clk_freq = SPI_CLK_FREQ;
-                       ext_drv->config.spi_clk_pol = SPI_CLK_POL;
-                       break;
-               default:
-                       break;
-               }
-       }
-       if (ext_drv->config.table_init_loaded == 0) {
-               ext_drv->config.table_init_on  = init_on_table;
-               ext_drv->config.table_init_off = init_off_table;
-       }
-       if (ext_drv->config.type == LCD_EXTERN_SPI) {
-               ext_drv->config.spi_delay_us =
-                       1000000 / ext_drv->config.spi_clk_freq;
+       if (ext_drv->config->type == LCD_EXTERN_SPI) {
+               ext_drv->config->spi_delay_us =
+                       1000000 / ext_drv->config->spi_clk_freq;
        }
 
        ext_drv->reg_read  = lcd_extern_reg_read;
@@ -503,17 +486,30 @@ int aml_lcd_extern_default_probe(struct aml_lcd_extern_driver_s *ext_drv)
 {
        int ret = 0;
 
-       ext_config = &ext_drv->config;
+       ext_config = ext_drv->config;
 
-       switch (ext_drv->config.type) {
+       switch (ext_config->type) {
        case LCD_EXTERN_I2C:
-               if (i2c_device == NULL) {
-                       EXTERR("invalid i2c device\n");
-                       return -1;
+               if (ext_config->i2c_addr < LCD_EXTERN_I2C_ADDR_INVALID) {
+                       i2c0_dev = lcd_extern_get_i2c_device(
+                                       ext_config->i2c_addr);
+                       if (i2c0_dev == NULL) {
+                               EXTERR("invalid i2c0 device\n");
+                               return -1;
+                       }
+                       EXTPR("get i2c0 device: %s, addr 0x%02x OK\n",
+                               i2c0_dev->name, i2c0_dev->client->addr);
                }
-               if (ext_drv->config.i2c_addr != i2c_device->client->addr) {
-                       EXTERR("invalid i2c addr\n");
-                       return -1;
+               if (ext_config->i2c_addr2 < LCD_EXTERN_I2C_ADDR_INVALID) {
+                       i2c1_dev = lcd_extern_get_i2c_device(
+                                       ext_config->i2c_addr2);
+                       if (i2c1_dev == NULL) {
+                               EXTERR("invalid i2c1 device\n");
+                               i2c0_dev = NULL;
+                               return -1;
+                       }
+                       EXTPR("get i2c1 device: %s, addr 0x%02x OK\n",
+                               i2c1_dev->name, i2c1_dev->client->addr);
                }
                break;
        case LCD_EXTERN_SPI:
@@ -529,83 +525,12 @@ int aml_lcd_extern_default_probe(struct aml_lcd_extern_driver_s *ext_drv)
        return ret;
 }
 
-static int lcd_extern_i2c_config_from_dts(struct device *dev,
-       struct aml_lcd_extern_i2c_dev_s *i2c_device)
+int aml_lcd_extern_default_remove(void)
 {
-       int ret;
-       struct device_node *np = dev->of_node;
-       const char *str;
-
-       ret = of_property_read_string(np, "dev_name", &str);
-       if (ret) {
-               EXTERR("failed to get dev_i2c_name\n");
-               str = "lcd_extern_i2c_default";
-       }
-       strcpy(i2c_device->name, str);
+       i2c0_dev = NULL;
+       i2c1_dev = NULL;
+       ext_config = NULL;
 
        return 0;
 }
 
-static int aml_lcd_extern_i2c_probe(struct i2c_client *client,
-       const struct i2c_device_id *id)
-{
-       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
-               EXTERR("I2C check functionality failed.");
-               return -ENODEV;
-       }
-
-       i2c_device = kzalloc(sizeof(struct aml_lcd_extern_i2c_dev_s),
-               GFP_KERNEL);
-       if (!i2c_device) {
-               EXTERR("driver malloc error\n");
-               return -ENOMEM;
-       }
-       i2c_device->client = client;
-       lcd_extern_i2c_config_from_dts(&client->dev, i2c_device);
-       EXTPR("I2C %s Address: 0x%02x", i2c_device->name,
-               i2c_device->client->addr);
-
-       return 0;
-}
-
-static int aml_lcd_extern_i2c_remove(struct i2c_client *client)
-{
-       kfree(i2c_device);
-       i2c_set_clientdata(client, NULL);
-
-       return 0;
-}
-
-static const struct i2c_device_id aml_lcd_extern_i2c_id[] = {
-       {"ext_default", 0},
-       {}
-};
-
-#ifdef CONFIG_OF
-static const struct of_device_id aml_lcd_extern_i2c_dt_match[] = {
-       {
-               .compatible = "amlogic, lcd_ext_default",
-       },
-       {},
-};
-#endif
-
-static struct i2c_driver aml_lcd_extern_i2c_driver = {
-       .probe  = aml_lcd_extern_i2c_probe,
-       .remove = aml_lcd_extern_i2c_remove,
-       .id_table   = aml_lcd_extern_i2c_id,
-       .driver = {
-               .name  = "ext_default",
-               .owner = THIS_MODULE,
-#ifdef CONFIG_OF
-               .of_match_table = aml_lcd_extern_i2c_dt_match,
-#endif
-       },
-};
-
-module_i2c_driver(aml_lcd_extern_i2c_driver);
-
-MODULE_AUTHOR("AMLOGIC");
-MODULE_DESCRIPTION("lcd extern driver");
-MODULE_LICENSE("GPL");
-
diff --git a/drivers/amlogic/media/vout/lcd/lcd_extern/ext_i2c_dev.c b/drivers/amlogic/media/vout/lcd/lcd_extern/ext_i2c_dev.c
new file mode 100644 (file)
index 0000000..2da1b27
--- /dev/null
@@ -0,0 +1,226 @@
+/*
+ * drivers/amlogic/media/vout/lcd/lcd_extern/ext_i2c_dev.c
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/amlogic/i2c-amlogic.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/amlogic/media/vout/lcd/lcd_extern.h>
+#include "lcd_extern.h"
+
+static struct aml_lcd_extern_i2c_dev_s *i2c_dev[LCD_EXT_I2C_DEV_MAX];
+static unsigned int i2c_dev_cnt;
+
+struct aml_lcd_extern_i2c_dev_s *lcd_extern_get_i2c_device(unsigned char addr)
+{
+       struct aml_lcd_extern_i2c_dev_s *i2c_device = NULL;
+       int i;
+
+       /*pr_info("%s: addr=0x%02x\n", __func__, addr);*/
+       for (i = 0; i < i2c_dev_cnt; i++) {
+               if (i2c_dev[i] == NULL)
+                       break;
+               if (i2c_dev[i]->client->addr == addr) {
+                       i2c_device = i2c_dev[i];
+                       break;
+               }
+       }
+       return i2c_device;
+}
+
+int lcd_extern_i2c_write(struct i2c_client *i2client,
+               unsigned char *buff, unsigned int len)
+{
+       struct i2c_msg msg;
+       int ret = 0;
+
+       if (i2client == NULL) {
+               EXTERR("i2client is null\n");
+               return -1;
+       }
+
+       msg.addr = i2client->addr;
+       msg.flags = 0;
+       msg.len = len;
+       msg.buf = buff;
+
+       ret = i2c_transfer(i2client->adapter, &msg, 1);
+       if (ret < 0)
+               EXTERR("i2c write failed [addr 0x%02x]\n", i2client->addr);
+
+       return ret;
+}
+
+int lcd_extern_i2c_read(struct i2c_client *i2client,
+               unsigned char *buff, unsigned int len)
+{
+       struct i2c_msg msgs[2];
+       int ret = 0;
+
+       if (i2client == NULL) {
+               EXTERR("i2client is null\n");
+               return -1;
+       }
+
+       msgs[0].addr = i2client->addr;
+       msgs[0].flags = 0;
+       msgs[0].len = 1;
+       msgs[0].buf = buff;
+       msgs[1].addr = i2client->addr;
+       msgs[1].flags = I2C_M_RD;
+       msgs[1].len = len;
+       msgs[1].buf = buff;
+
+       ret = i2c_transfer(i2client->adapter, msgs, 2);
+       if (ret < 0) {
+               EXTERR("%s: i2c transfer failed [addr 0x%02x]\n",
+                       __func__, i2client->addr);
+       }
+
+       return ret;
+}
+
+static int lcd_extern_i2c_config_from_dts(struct device *dev,
+               struct aml_lcd_extern_i2c_dev_s *i2c_device)
+{
+       int ret;
+       struct device_node *np = dev->of_node;
+       const char *str;
+
+       ret = of_property_read_string(np, "dev_name", &str);
+       if (ret) {
+               EXTERR("failed to get dev_i2c_name\n");
+               strcpy(i2c_device->name, "lcd_ext_i2c0");
+       } else {
+               strncpy(i2c_device->name, str, 30);
+               i2c_device->name[29] = '\0';
+       }
+
+       return 0;
+}
+
+static int lcd_extern_i2c_dev_probe(struct i2c_client *client,
+       const struct i2c_device_id *id)
+{
+       if (i2c_dev_cnt >= LCD_EXT_I2C_DEV_MAX) {
+               EXTERR("i2c_dev_cnt reach max\n");
+               return -ENODEV;
+       }
+
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+               EXTERR("i2c0_dev check functionality failed");
+               return -ENODEV;
+       }
+
+       i2c_dev[i2c_dev_cnt] = kzalloc(sizeof(struct aml_lcd_extern_i2c_dev_s),
+               GFP_KERNEL);
+       if (!i2c_dev[i2c_dev_cnt]) {
+               EXTERR("i2c0_dev %d driver malloc error\n", i2c_dev_cnt);
+               return -ENOMEM;
+       }
+
+       i2c_dev[i2c_dev_cnt]->client = client;
+       lcd_extern_i2c_config_from_dts(&client->dev, i2c_dev[i2c_dev_cnt]);
+       EXTPR("i2c_dev probe: %s address 0x%02x OK",
+               i2c_dev[i2c_dev_cnt]->name,
+               i2c_dev[i2c_dev_cnt]->client->addr);
+
+       i2c_dev_cnt++;
+
+       return 0;
+}
+
+static int lcd_extern_i2c_dev_remove(struct i2c_client *client)
+{
+       int i;
+
+       if (i2c_dev_cnt == 0)
+               return 0;
+
+       for (i = 0; i < i2c_dev_cnt; i++) {
+               kfree(i2c_dev[i]);
+               i2c_dev[i] = NULL;
+       }
+       i2c_dev_cnt = 0;
+
+       return 0;
+}
+
+static const struct i2c_device_id lcd_extern_i2c_dev_id[] = {
+       {"lcd_ext_i2c", 0},
+       {}
+};
+
+#ifdef CONFIG_OF
+static const struct of_device_id lcd_extern_i2c_dev_dt_match[] = {
+       {
+               .compatible = "lcd_ext, i2c",
+       },
+       {},
+};
+#endif
+
+static struct i2c_driver lcd_extern_i2c_dev_driver = {
+       .probe    = lcd_extern_i2c_dev_probe,
+       .remove   = lcd_extern_i2c_dev_remove,
+       .id_table = lcd_extern_i2c_dev_id,
+       .driver = {
+               .name  = "lcd_ext_i2c",
+               .owner = THIS_MODULE,
+#ifdef CONFIG_OF
+               .of_match_table = lcd_extern_i2c_dev_dt_match,
+#endif
+       },
+};
+
+static int __init aml_lcd_extern_i2c_dev_init(void)
+{
+       int ret;
+
+       if (lcd_debug_print_flag)
+               EXTPR("%s\n", __func__);
+
+       i2c_dev_cnt = 0;
+
+       ret = i2c_add_driver(&lcd_extern_i2c_dev_driver);
+       if (ret) {
+               EXTERR("i2c0_dev driver register failed\n");
+               return -ENODEV;
+       }
+
+       return ret;
+}
+
+static void __exit aml_lcd_extern_i2c_dev_exit(void)
+{
+       i2c_del_driver(&lcd_extern_i2c_dev_driver);
+}
+
+
+module_init(aml_lcd_extern_i2c_dev_init);
+module_exit(aml_lcd_extern_i2c_dev_exit);
+
+MODULE_AUTHOR("AMLOGIC");
+MODULE_DESCRIPTION("lcd extern i2c device driver");
+MODULE_LICENSE("GPL");
+
index 2dd7f86..0f0281e 100644 (file)
 
 #define LCD_EXTERN_NAME                        "i2c_DLPC3439"
 
+#define LCD_EXTERN_I2C_ADDR       (0x1b) /* 7bit address */
+#define LCD_EXTERN_I2C_ADDR2      (0xff) /* 7bit address */
+#define LCD_EXTERN_I2C_BUS        LCD_EXTERN_I2C_BUS_2
+
 static struct lcd_extern_config_s *ext_config;
-static struct aml_lcd_extern_i2c_dev_s *i2c_device;
+static struct aml_lcd_extern_i2c_dev_s *i2c_dev;
 
 
        /* Write: ImageCrop: 1920x1080
@@ -56,51 +60,31 @@ static unsigned char data_4[] = {0x05, 0x00};
         */
 static unsigned char data_5[] = {0x07, 0x43};
 
-static int lcd_extern_i2c_write(struct i2c_client *i2client,
-               unsigned char *buff, unsigned int len)
-{
-       int ret = 0;
-       struct i2c_msg msg[] = {
-               {
-                       .addr = i2client->addr,
-                       .flags = 0,
-                       .len = len,
-                       .buf = buff,
-               }
-       };
-
-       ret = i2c_transfer(i2client->adapter, msg, 1);
-       if (ret < 0)
-               EXTERR("i2c write failed [addr 0x%02x]\n", i2client->addr);
-
-       return ret;
-}
-
-static int lcd_extern_power_on(struct aml_lcd_extern_driver_s *ext_drv)
+static int lcd_extern_power_on(void)
 {
        int ret = 0;
 
-       lcd_extern_pinmux_set(ext_drv, 1);
+       lcd_extern_pinmux_set(1);
 
-       if (i2c_device == NULL) {
+       if (i2c_dev == NULL) {
                EXTERR("invalid i2c device\n");
                return -1;
        }
-       lcd_extern_i2c_write(i2c_device->client, data_1, 9);
-       lcd_extern_i2c_write(i2c_device->client, data_2, 5);
-       lcd_extern_i2c_write(i2c_device->client, data_3, 5);
-       lcd_extern_i2c_write(i2c_device->client, data_4, 2);
-       lcd_extern_i2c_write(i2c_device->client, data_5, 2);
+       lcd_extern_i2c_write(i2c_dev->client, data_1, 9);
+       lcd_extern_i2c_write(i2c_dev->client, data_2, 5);
+       lcd_extern_i2c_write(i2c_dev->client, data_3, 5);
+       lcd_extern_i2c_write(i2c_dev->client, data_4, 2);
+       lcd_extern_i2c_write(i2c_dev->client, data_5, 2);
 
        EXTPR("%s\n", __func__);
        return ret;
 }
 
-static int lcd_extern_power_off(struct aml_lcd_extern_driver_s *ext_drv)
+static int lcd_extern_power_off(void)
 {
        int ret = 0;
 
-       lcd_extern_pinmux_set(ext_drv, 0);
+       lcd_extern_pinmux_set(0);
 
        return ret;
 }
@@ -124,15 +108,15 @@ int aml_lcd_extern_i2c_DLPC3439_probe(struct aml_lcd_extern_driver_s *ext_drv)
 {
        int ret = 0;
 
-       ext_config = &ext_drv->config;
-       if (i2c_device == NULL) {
+       ext_config = ext_drv->config;
+
+       i2c_dev = lcd_extern_get_i2c_device(ext_config->i2c_addr);
+       if (i2c_dev == NULL) {
                EXTERR("invalid i2c device\n");
                return -1;
        }
-       if (ext_drv->config.i2c_addr != i2c_device->client->addr) {
-               EXTERR("invalid i2c addr\n");
-               return -1;
-       }
+       EXTPR("get i2c device: %s, addr 0x%02x OK\n",
+               i2c_dev->name, i2c_dev->client->addr);
 
        ret = lcd_extern_driver_update(ext_drv);
 
@@ -141,83 +125,11 @@ int aml_lcd_extern_i2c_DLPC3439_probe(struct aml_lcd_extern_driver_s *ext_drv)
        return ret;
 }
 
-static int lcd_extern_i2c_config_from_dts(struct device *dev,
-       struct aml_lcd_extern_i2c_dev_s *i2c_device)
+int aml_lcd_extern_i2c_DLPC3439_remove(void)
 {
-       int ret;
-       struct device_node *np = dev->of_node;
-       const char *str;
-
-       ret = of_property_read_string(np, "dev_name", &str);
-       if (ret) {
-               EXTERR("failed to get dev_i2c_name\n");
-               str = "lcd_extern_i2c_DLPC3439";
-       }
-       strcpy(i2c_device->name, str);
+       i2c_dev = NULL;
+       ext_config = NULL;
 
        return 0;
 }
 
-static int aml_lcd_extern_i2c_probe(struct i2c_client *client,
-       const struct i2c_device_id *id)
-{
-       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
-               EXTERR("I2C check functionality failed.");
-               return -ENODEV;
-       }
-
-       i2c_device = kzalloc(sizeof(struct aml_lcd_extern_i2c_dev_s),
-               GFP_KERNEL);
-       if (!i2c_device) {
-               EXTERR("driver malloc error\n");
-               return -ENOMEM;
-       }
-       i2c_device->client = client;
-       lcd_extern_i2c_config_from_dts(&client->dev, i2c_device);
-       EXTPR("I2C %s Address: 0x%02x", i2c_device->name,
-               i2c_device->client->addr);
-
-       return 0;
-}
-
-static int aml_lcd_extern_i2c_remove(struct i2c_client *client)
-{
-       kfree(i2c_device);
-       i2c_set_clientdata(client, NULL);
-
-       return 0;
-}
-
-static const struct i2c_device_id aml_lcd_extern_i2c_id[] = {
-       {"i2c_DLPC3439", 0},
-       {}
-};
-
-#ifdef CONFIG_OF
-static const struct of_device_id aml_lcd_extern_i2c_dt_match[] = {
-       {
-               .compatible = "amlogic, lcd_i2c_DLPC3439",
-       },
-       {},
-};
-#endif
-
-static struct i2c_driver aml_lcd_extern_i2c_driver = {
-       .probe  = aml_lcd_extern_i2c_probe,
-       .remove = aml_lcd_extern_i2c_remove,
-       .id_table   = aml_lcd_extern_i2c_id,
-       .driver = {
-               .name  = "i2c_DLPC3439",
-               .owner = THIS_MODULE,
-#ifdef CONFIG_OF
-               .of_match_table = aml_lcd_extern_i2c_dt_match,
-#endif
-       },
-};
-
-module_i2c_driver(aml_lcd_extern_i2c_driver);
-
-MODULE_AUTHOR("AMLOGIC");
-MODULE_DESCRIPTION("lcd extern driver");
-MODULE_LICENSE("GPL");
-
index 38f8a42..9f86fe7 100644 (file)
 #include <linux/amlogic/media/vout/lcd/lcd_extern.h>
 #include "lcd_extern.h"
 
-#define LCD_EXTERN_NAME                        "i2c_T5800Q"
+#define LCD_EXTERN_NAME           "i2c_T5800Q"
+
+#define LCD_EXTERN_I2C_ADDR       (0x1c) /* 7bit address */
+#define LCD_EXTERN_I2C_ADDR2      (0xff) /* 7bit address */
+#define LCD_EXTERN_I2C_BUS        LCD_EXTERN_I2C_BUS_2
 
 static struct lcd_extern_config_s *ext_config;
-static struct aml_lcd_extern_i2c_dev_s *i2c_device;
+static struct aml_lcd_extern_i2c_dev_s *i2c_dev;
 
 #define LCD_EXTERN_CMD_SIZE        9
 static unsigned char init_on_table[] = {
@@ -50,26 +54,6 @@ static unsigned char init_off_table[] = {
        0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  /* ending */
 };
 
-static int lcd_extern_i2c_write(struct i2c_client *i2client,
-               unsigned char *buff, unsigned int len)
-{
-       int ret = 0;
-       struct i2c_msg msg[] = {
-               {
-                       .addr = i2client->addr,
-                       .flags = 0,
-                       .len = len,
-                       .buf = buff,
-               }
-       };
-
-       ret = i2c_transfer(i2client->adapter, msg, 1);
-       if (ret < 0)
-               EXTERR("i2c write failed [addr 0x%02x]\n", i2client->addr);
-
-       return ret;
-}
-
 static int lcd_extern_power_cmd(unsigned char *init_table, int flag)
 {
        int i = 0, max_len = 0, step = 0;
@@ -110,11 +94,11 @@ static int lcd_extern_power_cmd(unsigned char *init_table, int flag)
                                        init_table[i+2]);
                        }
                } else if (init_table[i] == LCD_EXTERN_INIT_CMD) {
-                       if (i2c_device == NULL) {
+                       if (i2c_dev == NULL) {
                                EXTERR("invalid i2c device\n");
                                return -1;
                        }
-                       ret = lcd_extern_i2c_write(i2c_device->client,
+                       ret = lcd_extern_i2c_write(i2c_dev->client,
                                &init_table[i+1], (cmd_size-2));
                } else {
                        EXTERR("%s(%d: %s): power_type %d is invalid\n",
@@ -144,21 +128,21 @@ static int lcd_extern_power_ctrl(int flag)
        return ret;
 }
 
-static int lcd_extern_power_on(struct aml_lcd_extern_driver_s *ext_drv)
+static int lcd_extern_power_on(void)
 {
        int ret;
 
-       lcd_extern_pinmux_set(ext_drv, 1);
+       lcd_extern_pinmux_set(1);
        ret = lcd_extern_power_ctrl(1);
        return ret;
 }
 
-static int lcd_extern_power_off(struct aml_lcd_extern_driver_s *ext_drv)
+static int lcd_extern_power_off(void)
 {
        int ret;
 
-       lcd_extern_pinmux_set(ext_drv, 0);
        ret = lcd_extern_power_ctrl(0);
+       lcd_extern_pinmux_set(0);
        return ret;
 }
 
@@ -169,9 +153,9 @@ static int lcd_extern_driver_update(struct aml_lcd_extern_driver_s *ext_drv)
                return -1;
        }
 
-       if (ext_drv->config.table_init_loaded == 0) {
-               ext_drv->config.table_init_on = init_on_table;
-               ext_drv->config.table_init_off = init_off_table;
+       if (ext_drv->config->table_init_loaded == 0) {
+               ext_drv->config->table_init_on = init_on_table;
+               ext_drv->config->table_init_off = init_off_table;
        }
        ext_drv->power_on  = lcd_extern_power_on;
        ext_drv->power_off = lcd_extern_power_off;
@@ -183,15 +167,15 @@ int aml_lcd_extern_i2c_T5800Q_probe(struct aml_lcd_extern_driver_s *ext_drv)
 {
        int ret = 0;
 
-       ext_config = &ext_drv->config;
-       if (i2c_device == NULL) {
+       ext_config = ext_drv->config;
+
+       i2c_dev = lcd_extern_get_i2c_device(ext_config->i2c_addr);
+       if (i2c_dev == NULL) {
                EXTERR("invalid i2c device\n");
                return -1;
        }
-       if (ext_drv->config.i2c_addr != i2c_device->client->addr) {
-               EXTERR("invalid i2c addr\n");
-               return -1;
-       }
+       EXTPR("get i2c device: %s, addr 0x%02x OK\n",
+               i2c_dev->name, i2c_dev->client->addr);
 
        ret = lcd_extern_driver_update(ext_drv);
        EXTPR("%s: %d\n", __func__, ret);
@@ -200,111 +184,9 @@ int aml_lcd_extern_i2c_T5800Q_probe(struct aml_lcd_extern_driver_s *ext_drv)
 
 int aml_lcd_extern_i2c_T5800Q_remove(void)
 {
-       return 0;
-}
-
-static int lcd_extern_i2c_config_from_dts(struct device *dev,
-       struct aml_lcd_extern_i2c_dev_s *i2c_device)
-{
-       int ret;
-       struct device_node *np = dev->of_node;
-       const char *str;
-
-       ret = of_property_read_string(np, "dev_name", &str);
-       if (ret) {
-               EXTERR("failed to get dev_i2c_name\n");
-               str = "lcd_extern_i2c_T5800Q";
-       }
-       strcpy(i2c_device->name, str);
-
-       return 0;
-}
-
-static int aml_lcd_extern_i2c_probe(struct i2c_client *client,
-       const struct i2c_device_id *id)
-{
-       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
-               EXTERR("I2C check functionality failed.");
-               return -ENODEV;
-       }
-
-       i2c_device = kzalloc(sizeof(struct aml_lcd_extern_i2c_dev_s),
-               GFP_KERNEL);
-       if (!i2c_device) {
-               EXTERR("driver malloc error\n");
-               return -ENOMEM;
-       }
-
-       i2c_device->client = client;
-       lcd_extern_i2c_config_from_dts(&client->dev, i2c_device);
-       EXTPR("I2C %s Address: 0x%02x", i2c_device->name,
-               i2c_device->client->addr);
-
-       return 0;
-}
-
-static int aml_lcd_extern_i2c_remove(struct i2c_client *client)
-{
-       kfree(i2c_device);
-       //i2c_set_clientdata(client, NULL);
+       i2c_dev = NULL;
+       ext_config = NULL;
 
        return 0;
 }
 
-static const struct i2c_device_id aml_lcd_extern_i2c_id[] = {
-       {"i2c_T5800Q", 0},
-       {}
-};
-
-#ifdef CONFIG_OF
-static const struct of_device_id aml_lcd_extern_i2c_dt_match[] = {
-       {
-               .compatible = "amlogic, lcd_i2c_T5800Q",
-       },
-       {},
-};
-#endif
-
-static struct i2c_driver aml_lcd_extern_i2c_driver = {
-       .probe  = aml_lcd_extern_i2c_probe,
-       .remove = aml_lcd_extern_i2c_remove,
-       .id_table   = aml_lcd_extern_i2c_id,
-       .driver = {
-               .name  = "i2c_T5800Q",
-               .owner = THIS_MODULE,
-#ifdef CONFIG_OF
-               .of_match_table = aml_lcd_extern_i2c_dt_match,
-#endif
-       },
-};
-
-static int __init aml_lcd_extern_i2c_init(void)
-{
-       int ret;
-
-       //if (lcd_debug_print_flag)
-       EXTPR("%s\n", __func__);
-
-       ret = i2c_add_driver(&aml_lcd_extern_i2c_driver);
-       if (ret) {
-               EXTERR("driver register failed\n");
-               return -ENODEV;
-       }
-       return ret;
-}
-
-static void __exit aml_lcd_extern_i2c_exit(void)
-{
-       i2c_del_driver(&aml_lcd_extern_i2c_driver);
-}
-
-
-module_init(aml_lcd_extern_i2c_init);
-module_exit(aml_lcd_extern_i2c_exit);
-
-//module_i2c_driver(aml_lcd_extern_i2c_driver);
-
-MODULE_AUTHOR("AMLOGIC");
-MODULE_DESCRIPTION("lcd extern driver");
-MODULE_LICENSE("GPL");
-
index 40c6388..64e1f0c 100644 (file)
 #include "i2c_anx6345.h"
 
 static struct lcd_extern_config_s *ext_config;
-static struct i2c_client *aml_anx6345_70_client;
-static struct i2c_client *aml_anx6345_72_client;
+static struct aml_lcd_extern_i2c_dev_s *i2c0_dev;
+static struct aml_lcd_extern_i2c_dev_s *i2c1_dev;
 
-const char *anx_addr_name[2] = {"anx6345_70", "anx6345_72"};
 static unsigned int edp_tx_lane = 1;
 
-#define LCD_EXTERN_NAME                        "lcd_anx6345"
+#define LCD_EXTERN_NAME           "lcd_anx6345"
 
-static int aml_i2c_write(struct i2c_client *i2client, unsigned char *buff,
-               unsigned int len)
-{
-       int ret = 0;
-       struct i2c_msg msg[] = {
-               {
-                       .addr = i2client->addr,
-                       .flags = 0,
-                       .len = len,
-                       .buf = buff,
-               },
-       };
-
-       ret = i2c_transfer(i2client->adapter, msg, 1);
-       if (ret < 0) {
-               EXTERR("%s: i2c transfer failed [addr 0x%02x]\n",
-                       __func__, i2client->addr);
-       }
-
-       return ret;
-}
-
-static int aml_i2c_read(struct i2c_client *i2client, unsigned char *buff,
-               unsigned int len)
-{
-       int ret = 0;
-       struct i2c_msg msgs[] = {
-               {
-                       .addr = i2client->addr,
-                       .flags = 0,
-                       .len = 1,
-                       .buf = buff,
-               },
-               {
-                       .addr = i2client->addr,
-                       .flags = I2C_M_RD,
-                       .len = len,
-                       .buf = buff,
-               },
-       };
-
-       ret = i2c_transfer(i2client->adapter, msgs, 2);
-       if (ret < 0) {
-               EXTERR("%s: i2c transfer failed [addr 0x%02x]\n",
-                       __func__, i2client->addr);
-       }
-
-       return ret;
-}
-
-#if 0
-static int i2c_reg_read(unsigned char reg, unsigned char *buf)
-{
-       int ret = 0;
-
-       return ret;
-}
-
-static int i2c_reg_write(unsigned char reg, unsigned char value)
-{
-       int ret = 0;
-
-       return ret;
-}
-#endif
+#define LCD_EXTERN_I2C_ADDR       (0x38) /* 7bit address */
+#define LCD_EXTERN_I2C_ADDR2      (0x39) /* 7bit address */
+#define LCD_EXTERN_I2C_BUS        LCD_EXTERN_I2C_BUS_2
 
 static int SP_TX_Write_Reg(unsigned char addr, unsigned char reg,
                unsigned char data)
@@ -114,15 +51,15 @@ static int SP_TX_Write_Reg(unsigned char addr, unsigned char reg,
        buff[0] = reg;
        buff[1] = data;
        if (addr == 0x70)
-               client = aml_anx6345_70_client;
+               client = i2c0_dev->client;
        else if (addr == 0x72)
-               client = aml_anx6345_72_client;
+               client = i2c1_dev->client;
 
        if (client == NULL) {
                EXTERR("%s: invalid i2c client\n", __func__);
                return -1;
        }
-       ret = aml_i2c_write(client, buff, 1);
+       ret = lcd_extern_i2c_write(client, buff, 1);
        return ret;
 }
 
@@ -134,15 +71,15 @@ static int SP_TX_Read_Reg(unsigned char addr, unsigned char reg,
 
        *data = reg;
        if (addr == 0x70)
-               client = aml_anx6345_70_client;
+               client = i2c0_dev->client;
        else if (addr == 0x72)
-               client = aml_anx6345_72_client;
+               client = i2c1_dev->client;
 
        if (client == NULL) {
                EXTERR("%s: invalid i2c client\n", __func__);
                return -1;
        }
-       ret = aml_i2c_read(client, data, 1);
+       ret = lcd_extern_i2c_read(client, data, 1);
        return ret;
 }
 
@@ -200,7 +137,7 @@ static int SP_TX_AUX_DPCDRead_Bytes(unsigned char addrh, unsigned char addrm,
        return 0; /* aux ok */
 }
 
-static int lcd_extern_power_on(struct aml_lcd_extern_driver_s *ext_drv)
+static int lcd_extern_power_on(void)
 {
        unsigned int lane_num;
        unsigned int link_rate;
@@ -211,7 +148,8 @@ static int lcd_extern_power_on(struct aml_lcd_extern_driver_s *ext_drv)
        unsigned int count = 0;
        unsigned int count1 = 0;
 
-       lcd_extern_pinmux_set(ext_drv, 1);
+       lcd_extern_pinmux_set(1);
+
        lane_num = edp_tx_lane; /* 1 lane */
        link_rate = VAL_EDP_TX_LINK_BW_SET_270; /* 2.7G */
        bits = 0; /* 0x00: 6bit;  0x10:8bit */
@@ -353,11 +291,11 @@ static int lcd_extern_power_on(struct aml_lcd_extern_driver_s *ext_drv)
        return 0;
 }
 
-static int lcd_extern_power_off(struct aml_lcd_extern_driver_s *ext_drv)
+static int lcd_extern_power_off(void)
 {
        int ret = 0;
 
-       lcd_extern_pinmux_set(ext_drv, 0);
+       lcd_extern_pinmux_set(0);
 
        return ret;
 }
@@ -377,131 +315,28 @@ static int lcd_extern_driver_update(struct aml_lcd_extern_driver_s *ext_drv)
        return ret;
 }
 
-static int aml_anx6345_70_probe(struct i2c_client *client,
-               const struct i2c_device_id *id)
-{
-       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
-               EXTERR("%s: functionality check failed\n", __func__);
-       else
-               aml_anx6345_70_client = client;
-
-       EXTPR("%s OK\n", __func__);
-       return 0;
-}
-
-static int aml_anx6345_72_probe(struct i2c_client *client,
-               const struct i2c_device_id *id)
-{
-       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
-               EXTERR("%s: functionality check failed\n", __func__);
-       else
-               aml_anx6345_72_client = client;
-
-       EXTPR("%s OK\n", __func__);
-       return 0;
-}
-
-static int aml_anx6345_70_remove(struct i2c_client *client)
-{
-       return 0;
-}
-static int aml_anx6345_72_remove(struct i2c_client *client)
-{
-       return 0;
-}
-
-static const struct i2c_device_id aml_anx6345_70_id[] = {
-       {"anx6345_70", 0},
-       { }
-};
-static const struct i2c_device_id aml_anx6345_72_id[] = {
-       {"anx6345_72", 0},
-       { }
-};
-
-/* MODULE_DEVICE_TABLE(i2c, aml_tc101_id); */
-
-static struct i2c_driver aml_anx6345_70_driver = {
-       .probe    = aml_anx6345_70_probe,
-       .remove   = aml_anx6345_70_remove,
-       .id_table = aml_anx6345_70_id,
-       .driver = {
-               .name = "anx6345_70",
-               .owner = THIS_MODULE,
-       },
-};
-
-static struct i2c_driver aml_anx6345_72_driver = {
-       .probe    = aml_anx6345_72_probe,
-       .remove   = aml_anx6345_72_remove,
-       .id_table = aml_anx6345_72_id,
-       .driver = {
-               .name = "anx6345_72",
-               .owner = THIS_MODULE,
-       },
-};
-
 int aml_lcd_extern_i2c_anx6345_probe(struct aml_lcd_extern_driver_s *ext_drv)
 {
-       struct i2c_board_info i2c_info[2];
-       struct i2c_adapter *adapter;
-       struct i2c_client *i2c_client;
-       int i = 0;
        int ret = 0;
 
-       ext_config = &ext_drv->config;
-       if (ext_config->i2c_bus == LCD_EXTERN_I2C_BUS_INVALID) {
-               EXTERR("invalid i2c bus\n");
-               return -1;
-       }
-       for (i = 0; i < 2; i++)
-               memset(&i2c_info[i], 0, sizeof(i2c_info[i]));
+       ext_config = ext_drv->config;
 
-       adapter = i2c_get_adapter(ext_config->i2c_bus);
-       if (!adapter) {
-               EXTERR("%s failed to get i2c adapter\n", ext_drv->config.name);
+       i2c0_dev = lcd_extern_get_i2c_device(ext_config->i2c_addr);
+       if (i2c0_dev == NULL) {
+               EXTERR("invalid i2c0 device\n");
                return -1;
        }
+       EXTPR("get i2c0 device: %s, addr 0x%02x OK\n",
+               i2c0_dev->name, i2c0_dev->client->addr);
 
-       i2c_info[0].addr = 0x38; /* 0x70 >> 1; */
-       i2c_info[1].addr = 0x39; /* 0x72 >> 1; */
-       for (i = 0; i < 2; i++) {
-               strncpy(i2c_info[i].type, anx_addr_name[i], I2C_NAME_SIZE);
-               /* i2c_info[i].platform_data = &ext_drv->config; */
-               i2c_info[i].flags = 0;
-               if (i2c_info[i].addr > 0x7f) {
-                       EXTERR("%s invalid i2c address: 0x%02x\n",
-                               ext_drv->config.name, i2c_info[i].addr);
-                       return -1;
-               }
-               i2c_client = i2c_new_device(adapter, &i2c_info[i]);
-               if (!i2c_client) {
-                       EXTERR("%s failed to new i2c device\n",
-                               ext_drv->config.name);
-               } else {
-                       if (lcd_debug_print_flag) {
-                               EXTPR("%s new i2c device succeed\n",
-                                       ext_drv->config.name);
-                       }
-               }
-       }
-
-       if (!aml_anx6345_70_client) {
-               ret = i2c_add_driver(&aml_anx6345_70_driver);
-               if (ret) {
-                       EXTERR("%s add i2c_driver failed\n",
-                               ext_drv->config.name);
-                       return -1;
-               }
-       }
-       if (!aml_anx6345_72_client) {
-               ret = i2c_add_driver(&aml_anx6345_72_driver);
-               if (ret) {
-                       EXTERR("%s add i2c_driver failed\n",
-                               ext_drv->config.name);
-                       return -1;
-               }
+       i2c1_dev = lcd_extern_get_i2c_device(ext_config->i2c_addr2);
+       if (i2c1_dev == NULL) {
+               EXTERR("invalid i2c1 device\n");
+               i2c0_dev = NULL;
+               return -1;
        }
+       EXTPR("get i2c1 device: %s, addr 0x%02x OK\n",
+               i2c1_dev->name, i2c1_dev->client->addr);
 
        ret = lcd_extern_driver_update(ext_drv);
 
@@ -510,3 +345,12 @@ int aml_lcd_extern_i2c_anx6345_probe(struct aml_lcd_extern_driver_s *ext_drv)
        return ret;
 }
 
+int aml_lcd_extern_i2c_anx6345_remove(void)
+{
+       i2c0_dev = NULL;
+       i2c1_dev = NULL;
+       ext_config = NULL;
+
+       return 0;
+}
+
index 09d7bc7..af8d3a5 100644 (file)
 #include <linux/amlogic/media/vout/lcd/lcd_extern.h>
 #include "lcd_extern.h"
 
-#define LCD_EXTERN_NAME                        "i2c_tc101"
+#define LCD_EXTERN_NAME                  "i2c_tc101"
+
+#define LCD_EXTERN_I2C_ADDR       (0x7e) /* 7bit address */
+#define LCD_EXTERN_I2C_ADDR2      (0xff) /* 7bit address */
+#define LCD_EXTERN_I2C_BUS        LCD_EXTERN_I2C_BUS_2
 
 static struct lcd_extern_config_s *ext_config;
-static struct aml_lcd_extern_i2c_dev_s *i2c_device;
+static struct aml_lcd_extern_i2c_dev_s *i2c0_dev;
+static struct aml_lcd_extern_i2c_dev_s *i2c1_dev;
 
 static unsigned char init_on_table[][3] = {
        /* {0xff, 0xff, 20},//delay mark(20ms) */
@@ -63,15 +68,15 @@ static int lcd_extern_i2c_write(struct i2c_client *i2client,
        return ret;
 }
 
-static int lcd_extern_power_on(struct aml_lcd_extern_driver_s *ext_drv)
+static int lcd_extern_power_on(void)
 {
        unsigned char tData[4];
        int i = 0, ending_flag = 0;
        int ret = 0;
 
-       lcd_extern_pinmux_set(ext_drv, 1);
+       lcd_extern_pinmux_set(1);
 
-       if (i2c_device == NULL) {
+       if (i2c0_dev == NULL) {
                EXTERR("invalid i2c device\n");
                return -1;
        }
@@ -86,7 +91,7 @@ static int lcd_extern_power_on(struct aml_lcd_extern_driver_s *ext_drv)
                        tData[0] = init_on_table[i][0];
                        tData[1] = init_on_table[i][1];
                        tData[2] = init_on_table[i][2];
-                       lcd_extern_i2c_write(i2c_device->client, tData, 3);
+                       lcd_extern_i2c_write(i2c0_dev->client, tData, 3);
                }
                i++;
        }
@@ -94,11 +99,11 @@ static int lcd_extern_power_on(struct aml_lcd_extern_driver_s *ext_drv)
        return ret;
 }
 
-static int lcd_extern_power_off(struct aml_lcd_extern_driver_s *ext_drv)
+static int lcd_extern_power_off(void)
 {
        int ret = 0;
 
-       lcd_extern_pinmux_set(ext_drv, 0);
+       lcd_extern_pinmux_set(0);
        return ret;
 }
 
@@ -121,15 +126,24 @@ int aml_lcd_extern_i2c_tc101_probe(struct aml_lcd_extern_driver_s *ext_drv)
 {
        int ret = 0;
 
-       ext_config = &ext_drv->config;
-       if (i2c_device == NULL) {
-               EXTERR("invalid i2c device\n");
+       ext_config = ext_drv->config;
+
+       i2c0_dev = lcd_extern_get_i2c_device(ext_config->i2c_addr);
+       if (i2c0_dev == NULL) {
+               EXTERR("invalid i2c0 device\n");
                return -1;
        }
-       if (ext_drv->config.i2c_addr != i2c_device->client->addr) {
-               EXTERR("invalid i2c addr\n");
+       EXTPR("get i2c0 device: %s, addr 0x%02x OK\n",
+               i2c0_dev->name, i2c0_dev->client->addr);
+
+       i2c1_dev = lcd_extern_get_i2c_device(ext_config->i2c_addr2);
+       if (i2c1_dev == NULL) {
+               EXTERR("invalid i2c1 device\n");
+               i2c0_dev = NULL;
                return -1;
        }
+       EXTPR("get i2c1 device: %s, addr 0x%02x OK\n",
+               i2c1_dev->name, i2c1_dev->client->addr);
 
        ret = lcd_extern_driver_update(ext_drv);
 
@@ -138,83 +152,11 @@ int aml_lcd_extern_i2c_tc101_probe(struct aml_lcd_extern_driver_s *ext_drv)
        return ret;
 }
 
-static int lcd_extern_i2c_config_from_dts(struct device *dev,
-       struct aml_lcd_extern_i2c_dev_s *i2c_device)
-{
-       int ret;
-       struct device_node *np = dev->of_node;
-       const char *str;
-
-       ret = of_property_read_string(np, "dev_name", &str);
-       if (ret) {
-               EXTERR("failed to get dev_i2c_name\n");
-               str = "lcd_extern_i2c_tc101";
-       }
-       strcpy(i2c_device->name, str);
-
-       return 0;
-}
-
-static int aml_lcd_extern_i2c_probe(struct i2c_client *client,
-       const struct i2c_device_id *id)
-{
-       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
-               EXTERR("I2C check functionality failed.");
-               return -ENODEV;
-       }
-
-       i2c_device = kzalloc(sizeof(struct aml_lcd_extern_i2c_dev_s),
-               GFP_KERNEL);
-       if (!i2c_device) {
-               EXTERR("driver malloc error\n");
-               return -ENOMEM;
-       }
-       i2c_device->client = client;
-       lcd_extern_i2c_config_from_dts(&client->dev, i2c_device);
-       EXTPR("I2C %s Address: 0x%02x", i2c_device->name,
-               i2c_device->client->addr);
-
-       return 0;
-}
-
-static int aml_lcd_extern_i2c_remove(struct i2c_client *client)
+int aml_lcd_extern_i2c_tc101_remove(void)
 {
-       kfree(i2c_device);
-       i2c_set_clientdata(client, NULL);
+       i2c0_dev = NULL;
+       i2c1_dev = NULL;
+       ext_config = NULL;
 
        return 0;
 }
-
-static const struct i2c_device_id aml_lcd_extern_i2c_id[] = {
-       {"i2c_tc101", 0},
-       {}
-};
-
-#ifdef CONFIG_OF
-static const struct of_device_id aml_lcd_extern_i2c_dt_match[] = {
-       {
-               .compatible = "amlogic, lcd_i2c_tc101",
-       },
-       {},
-};
-#endif
-
-static struct i2c_driver aml_lcd_extern_i2c_driver = {
-       .probe  = aml_lcd_extern_i2c_probe,
-       .remove = aml_lcd_extern_i2c_remove,
-       .id_table   = aml_lcd_extern_i2c_id,
-       .driver = {
-               .name  = "i2c_tc101",
-               .owner = THIS_MODULE,
-#ifdef CONFIG_OF
-               .of_match_table = aml_lcd_extern_i2c_dt_match,
-#endif
-       },
-};
-
-module_i2c_driver(aml_lcd_extern_i2c_driver);
-
-MODULE_AUTHOR("AMLOGIC");
-MODULE_DESCRIPTION("lcd extern driver");
-MODULE_LICENSE("GPL");
-
index f5db99d..d6e86c7 100644 (file)
 #include <linux/of.h>
 #include <linux/amlogic/media/vout/lcd/lcd_extern.h>
 #include <linux/amlogic/media/vout/lcd/lcd_unifykey.h>
+#include <linux/amlogic/media/vout/lcd/lcd_notify.h>
 #include "lcd_extern.h"
 
 static struct device *lcd_extern_dev;
-static int lcd_ext_driver_num;
-static struct aml_lcd_extern_driver_s *lcd_ext_driver[LCD_EXT_DRIVER_MAX];
+static struct aml_lcd_extern_driver_s *lcd_ext_driver;
 static int lcd_extern_add_driver(struct lcd_extern_config_s *extconf);
 
-static unsigned int lcd_ext_key_valid;
 static unsigned char lcd_ext_config_load;
-static unsigned char lcd_ext_i2c_bus = LCD_EXTERN_I2C_BUS_INVALID;
-static unsigned char lcd_ext_i2c_sck_gpio = LCD_EXTERN_GPIO_NUM_MAX;
-static unsigned char lcd_ext_i2c_sck_gpio_off = 2;
-static unsigned char lcd_ext_i2c_sda_gpio = LCD_EXTERN_GPIO_NUM_MAX;
-static unsigned char lcd_ext_i2c_sda_gpio_off = 2;
 
 struct lcd_ext_gpio_s {
        char name[15];
@@ -58,44 +52,49 @@ static struct lcd_ext_gpio_s lcd_extern_gpio[LCD_EXTERN_GPIO_NUM_MAX] = {
        {.probe_flag = 0, .register_flag = 0,},
 };
 
+static struct lcd_extern_config_s lcd_extern_config = {
+       .index = LCD_EXTERN_INDEX_INVALID,
+       .name = "invalid",
+       .type = LCD_EXTERN_MAX,
+       .status = 0,
+       .pinmux_valid = 0,
+       .key_valid = 0,
+       .addr_sel = 0,
+
+       .i2c_addr = LCD_EXTERN_I2C_ADDR_INVALID,
+       .i2c_addr2 = LCD_EXTERN_I2C_ADDR_INVALID,
+       .i2c_bus = LCD_EXTERN_I2C_BUS_INVALID,
+       .i2c_sck_gpio = LCD_EXTERN_GPIO_NUM_MAX,
+       .i2c_sck_gpio_off = 2,
+       .i2c_sda_gpio = LCD_EXTERN_GPIO_NUM_MAX,
+       .i2c_sda_gpio_off = 2,
+
+       .spi_gpio_cs = LCD_EXTERN_GPIO_NUM_MAX,
+       .spi_gpio_clk = LCD_EXTERN_GPIO_NUM_MAX,
+       .spi_gpio_data = LCD_EXTERN_GPIO_NUM_MAX,
+       .spi_clk_freq = 0,
+       .spi_delay_us = 0,
+       .spi_clk_pol = 1,
+
+       .cmd_size = 0,
+       .table_init_on = NULL,
+       .table_init_off = NULL,
+       .table_init_loaded = 0, /* internal use */
+       .table_init_on_cnt = 0, /* internal use */
+};
+
 struct aml_lcd_extern_driver_s *aml_lcd_extern_get_driver(int index)
 {
-       int i;
-       struct aml_lcd_extern_driver_s *ext_driver = NULL;
-
        if (index >= LCD_EXTERN_INDEX_INVALID) {
                EXTERR("invalid driver index: %d\n", index);
                return NULL;
        }
-       for (i = 0; i < lcd_ext_driver_num; i++) {
-               if (lcd_ext_driver[i]->config.index == index) {
-                       ext_driver = lcd_ext_driver[i];
-                       break;
-               }
-       }
-       if (ext_driver == NULL)
-               EXTERR("invalid driver index: %d\n", index);
-       return ext_driver;
-}
-
-#if 0
-static struct aml_lcd_extern_driver_s
-       *aml_lcd_extern_get_driver_by_name(char *name)
-{
-       int i;
-       struct aml_lcd_extern_driver_s *ext_driver = NULL;
+       if (lcd_ext_driver->config->index == index)
+               return lcd_ext_driver;
 
-       for (i = 0; i < lcd_ext_driver_num; i++) {
-               if (strcmp(lcd_ext_driver[i]->config.name, name) == 0) {
-                       ext_driver = lcd_ext_driver[i];
-                       break;
-               }
-       }
-       if (ext_driver == NULL)
-               EXTERR("invalid driver name: %s\n", name);
-       return ext_driver;
+       EXTERR("invalid driver index: %d\n", index);
+       return NULL;
 }
-#endif
 
 #ifdef CONFIG_OF
 void lcd_extern_gpio_probe(unsigned char index)
@@ -290,71 +289,44 @@ unsigned int lcd_extern_gpio_get(unsigned char index)
        return gpiod_get_value(ext_gpio->gpio);
 }
 
-void lcd_extern_pinmux_set(struct aml_lcd_extern_driver_s *ext_drv, int status)
+void lcd_extern_pinmux_set(int status)
 {
-       struct lcd_ext_gpio_s *ext_gpio_sck;
-       struct lcd_ext_gpio_s *ext_gpio_sda;
+       /* kernel4.9 can't release pins */
+       if (lcd_ext_driver == NULL)
+               return;
 
-       ext_gpio_sck = &lcd_extern_gpio[ext_drv->config.i2c_sck_gpio];
-       ext_gpio_sda = &lcd_extern_gpio[ext_drv->config.i2c_sda_gpio];
+       if (lcd_ext_driver->config->pinmux_valid == 0) {
+               if (lcd_debug_print_flag) {
+                       EXTPR("%s: pinmux_valid %d, bypass\n",
+                               __func__, lcd_ext_driver->config->pinmux_valid);
+               }
+               return;
+       }
 
        if (lcd_debug_print_flag)
                EXTPR("%s: %d\n", __func__, status);
 
        if (status) {
                /* release gpio */
-               if (ext_drv->pinmux_flag) {
+               if (lcd_ext_driver->pinmux_flag) {
                        EXTPR("drv_index %d pinmux is already selected\n",
-                               ext_drv->config.index);
+                               lcd_ext_driver->config->index);
                        return;
                }
-               if (ext_drv->config.type == LCD_EXTERN_I2C) {
-                       if (ext_drv->config.i2c_sck_gpio <
-                               LCD_EXTERN_GPIO_NUM_MAX)
-                               lcd_extern_gpio_unregister(
-                                       ext_drv->config.i2c_sck_gpio);
-                       if (ext_drv->config.i2c_sda_gpio <
-                               LCD_EXTERN_GPIO_NUM_MAX)
-                               lcd_extern_gpio_unregister(
-                                       ext_drv->config.i2c_sda_gpio);
-               }
+
                /* request pinmux */
-               ext_drv->pin = devm_pinctrl_get_select(lcd_extern_dev,
+               lcd_ext_driver->pin = devm_pinctrl_get_select(lcd_extern_dev,
                        "extern_pins");
-               if (IS_ERR(ext_drv->pin)) {
+               if (IS_ERR(lcd_ext_driver->pin)) {
                        EXTERR("set drv_index %d pinmux error\n",
-                               ext_drv->config.index);
+                               lcd_ext_driver->config->index);
                } else {
                        if (lcd_debug_print_flag) {
                                EXTPR("set drv_index %d pinmux ok\n",
-                                       ext_drv->config.index);
-                       }
-               }
-               ext_drv->pinmux_flag = 1;
-       } else {
-               if (ext_drv->pinmux_flag) {
-                       if (lcd_debug_print_flag)
-                               EXTPR("release pinmux: %p\n", ext_drv->pin);
-                        /* release pinmux */
-                       if (!IS_ERR(ext_drv->pin))
-                               devm_pinctrl_put(ext_drv->pin);
-                       ext_drv->pinmux_flag = 0;
-               }
-               /* request gpio &  set gpio */
-               if (ext_drv->config.type == LCD_EXTERN_I2C) {
-                       if (ext_drv->config.i2c_sck_gpio <
-                                       LCD_EXTERN_GPIO_NUM_MAX) {
-                               lcd_extern_gpio_set(
-                                       ext_drv->config.i2c_sck_gpio,
-                                       ext_drv->config.i2c_sck_gpio_off);
-                       }
-                       if (ext_drv->config.i2c_sda_gpio <
-                                       LCD_EXTERN_GPIO_NUM_MAX) {
-                               lcd_extern_gpio_set(
-                                       ext_drv->config.i2c_sda_gpio,
-                                       ext_drv->config.i2c_sda_gpio_off);
+                                       lcd_ext_driver->config->index);
                        }
                }
+               lcd_ext_driver->pinmux_flag = 1;
        }
 }
 
@@ -364,15 +336,25 @@ static unsigned char lcd_extern_get_i2c_bus_str(const char *str)
        unsigned char i2c_bus;
 
        if (strncmp(str, "i2c_bus_ao", 10) == 0)
-               i2c_bus = AML_I2C_MASTER_AO;
+               i2c_bus = LCD_EXTERN_I2C_BUS_4;
        else if (strncmp(str, "i2c_bus_a", 9) == 0)
-               i2c_bus = AML_I2C_MASTER_A;
+               i2c_bus = LCD_EXTERN_I2C_BUS_0;
        else if (strncmp(str, "i2c_bus_b", 9) == 0)
-               i2c_bus = AML_I2C_MASTER_B;
+               i2c_bus = LCD_EXTERN_I2C_BUS_1;
        else if (strncmp(str, "i2c_bus_c", 9) == 0)
-               i2c_bus = AML_I2C_MASTER_C;
+               i2c_bus = LCD_EXTERN_I2C_BUS_2;
        else if (strncmp(str, "i2c_bus_d", 9) == 0)
-               i2c_bus = AML_I2C_MASTER_D;
+               i2c_bus = LCD_EXTERN_I2C_BUS_3;
+       else if (strncmp(str, "i2c_bus_0", 9) == 0)
+               i2c_bus = LCD_EXTERN_I2C_BUS_0;
+       else if (strncmp(str, "i2c_bus_1", 9) == 0)
+               i2c_bus = LCD_EXTERN_I2C_BUS_1;
+       else if (strncmp(str, "i2c_bus_2", 9) == 0)
+               i2c_bus = LCD_EXTERN_I2C_BUS_2;
+       else if (strncmp(str, "i2c_bus_3", 9) == 0)
+               i2c_bus = LCD_EXTERN_I2C_BUS_3;
+       else if (strncmp(str, "i2c_bus_4", 9) == 0)
+               i2c_bus = LCD_EXTERN_I2C_BUS_4;
        else {
                i2c_bus = LCD_EXTERN_I2C_BUS_INVALID;
                EXTERR("invalid i2c_bus: %s\n", str);
@@ -676,10 +658,11 @@ static int lcd_extern_get_config_dts(struct device_node *of_node,
 
        ret = of_property_read_string(of_node, "extern_name", &str);
        if (ret) {
-               str = "none";
                EXTERR("get extern_name failed\n");
+               strncpy(extconf->name, "none", LCD_EXTERN_NAME_LEN_MAX);
+       } else {
+               strncpy(extconf->name, str, LCD_EXTERN_NAME_LEN_MAX);
        }
-       strncpy(extconf->name, str, LCD_EXTERN_NAME_LEN_MAX);
        /* ensure string ending */
        extconf->name[LCD_EXTERN_NAME_LEN_MAX-1] = '\0';
        EXTPR("load config: %s[%d]\n", extconf->name, extconf->index);
@@ -693,17 +676,8 @@ static int lcd_extern_get_config_dts(struct device_node *of_node,
 
        switch (extconf->type) {
        case LCD_EXTERN_I2C:
-               if (lcd_ext_i2c_bus == LCD_EXTERN_I2C_BUS_INVALID) {
-                       ret = of_property_read_string(of_node, "i2c_bus", &str);
-                       if (ret) {
-                               EXTERR("get %s i2c_bus failed, exit\n",
-                                       extconf->name);
-                               extconf->i2c_bus = LCD_EXTERN_I2C_BUS_INVALID;
-                               return -1;
-                       }
-                       extconf->i2c_bus = lcd_extern_get_i2c_bus_str(str);
-               } else
-                       extconf->i2c_bus = lcd_ext_i2c_bus;
+               if (extconf->i2c_bus == LCD_EXTERN_I2C_BUS_INVALID)
+                       EXTERR("get %s i2c_bus failed\n", extconf->name);
                if (lcd_debug_print_flag) {
                        EXTPR("%s i2c_bus=%d\n",
                                extconf->name, extconf->i2c_bus);
@@ -733,17 +707,6 @@ static int lcd_extern_get_config_dts(struct device_node *of_node,
                                extconf->name, extconf->i2c_addr2);
                }
 
-               extconf->i2c_sck_gpio = lcd_ext_i2c_sck_gpio;
-               extconf->i2c_sck_gpio_off = lcd_ext_i2c_sck_gpio_off;
-               extconf->i2c_sda_gpio = lcd_ext_i2c_sda_gpio;
-               extconf->i2c_sda_gpio_off = lcd_ext_i2c_sda_gpio_off;
-               if ((lcd_ext_i2c_sck_gpio < LCD_EXTERN_GPIO_NUM_MAX) ||
-                       (lcd_ext_i2c_sda_gpio < LCD_EXTERN_GPIO_NUM_MAX)) {
-                       EXTPR("find i2c_gpio_off config\n");
-                       lcd_extern_gpio_probe(extconf->i2c_sck_gpio);
-                       lcd_extern_gpio_probe(extconf->i2c_sda_gpio);
-               }
-
                ret = of_property_read_u32(of_node, "cmd_size", &val);
                if (ret) {
                        if (extconf->index == 0) {
@@ -921,17 +884,6 @@ static int lcd_extern_get_config_dts(struct device_node *of_node,
 }
 #endif
 
-
-static unsigned char lcd_extern_get_i2c_bus_unifykey(unsigned char val)
-{
-       if (lcd_ext_i2c_bus == LCD_EXTERN_I2C_BUS_INVALID)
-               EXTERR("get i2c_bus failed\n");
-       if (lcd_debug_print_flag)
-               EXTPR("i2c_bus=%d\n", lcd_ext_i2c_bus);
-
-       return lcd_ext_i2c_bus;
-}
-
 static int lcd_extern_init_table_dynamic_size_load_unifykey(
                struct lcd_extern_config_s *extconf, unsigned char *p,
                int key_len, int len, int flag)
@@ -1273,18 +1225,10 @@ static int lcd_extern_get_config_unifykey(struct lcd_extern_config_s *extconf)
        case LCD_EXTERN_I2C:
                extconf->i2c_addr = *(p + LCD_UKEY_EXT_TYPE_VAL_0);
                extconf->i2c_addr2 = *(p + LCD_UKEY_EXT_TYPE_VAL_1);
-               extconf->i2c_bus = lcd_extern_get_i2c_bus_unifykey(
-                       *(p + LCD_UKEY_EXT_TYPE_VAL_2));
-               extconf->i2c_sck_gpio = lcd_ext_i2c_sck_gpio;
-               extconf->i2c_sck_gpio_off = lcd_ext_i2c_sck_gpio_off;
-               extconf->i2c_sda_gpio = lcd_ext_i2c_sda_gpio;
-               extconf->i2c_sda_gpio_off = lcd_ext_i2c_sda_gpio_off;
-               if ((lcd_ext_i2c_sck_gpio < LCD_EXTERN_GPIO_NUM_MAX) ||
-                       (lcd_ext_i2c_sda_gpio < LCD_EXTERN_GPIO_NUM_MAX)) {
-                       EXTPR("find i2c_gpio_off config\n");
-                       lcd_extern_gpio_probe(extconf->i2c_sck_gpio);
-                       lcd_extern_gpio_probe(extconf->i2c_sda_gpio);
-               }
+               /*extconf->i2c_bus = *(p + LCD_UKEY_EXT_TYPE_VAL_2);*/
+               if (extconf->i2c_bus == LCD_EXTERN_I2C_BUS_INVALID)
+                       EXTERR("get %s i2c_bus failed\n", extconf->name);
+
                extconf->cmd_size = *(p + LCD_UKEY_EXT_TYPE_VAL_3);
 
                /* init */
@@ -1377,9 +1321,8 @@ static int lcd_extern_get_config_unifykey(struct lcd_extern_config_s *extconf)
 static int lcd_extern_get_config(void)
 {
        struct device_node *child;
-       struct lcd_extern_config_s extconf;
-       unsigned char *lcd_ext_init_on_table;
-       unsigned char *lcd_ext_init_off_table;
+       unsigned int ext_index = LCD_EXTERN_INDEX_INVALID;
+       char ext_propname[20];
        unsigned int extern_para[5];
        const char *str;
        int load_id = 0;
@@ -1390,86 +1333,100 @@ static int lcd_extern_get_config(void)
                return -1;
        }
 
-       lcd_ext_init_on_table =
-               kmalloc(sizeof(unsigned char) * LCD_EXTERN_INIT_ON_MAX,
+       lcd_extern_config.table_init_on =
+               kzalloc(sizeof(unsigned char) * LCD_EXTERN_INIT_ON_MAX,
                        GFP_KERNEL);
-       if (lcd_ext_init_on_table == NULL) {
+       if (lcd_extern_config.table_init_on == NULL) {
                EXTERR("failed to alloc default init table\n");
                return -1;
        }
-       lcd_ext_init_off_table =
-               kmalloc(sizeof(unsigned char) * LCD_EXTERN_INIT_OFF_MAX,
+       lcd_extern_config.table_init_off =
+               kzalloc(sizeof(unsigned char) * LCD_EXTERN_INIT_OFF_MAX,
                        GFP_KERNEL);
-       if (lcd_ext_init_off_table == NULL) {
+       if (lcd_extern_config.table_init_off == NULL) {
                EXTERR("failed to alloc default init table\n");
-               kfree(lcd_ext_init_on_table);
+               kfree(lcd_extern_config.table_init_on);
                return -1;
        }
-       lcd_ext_init_on_table[0] = LCD_EXTERN_INIT_END;
-       lcd_ext_init_off_table[0] = LCD_EXTERN_INIT_END;
+       lcd_extern_config.table_init_on[0] = LCD_EXTERN_INIT_END;
+       lcd_extern_config.table_init_off[0] = LCD_EXTERN_INIT_END;
 
-       ret = of_property_read_string(lcd_extern_dev->of_node,
-                       "i2c_bus", &str);
+       ret = of_property_read_string(lcd_extern_dev->of_node, "i2c_bus", &str);
        if (ret)
-               lcd_ext_i2c_bus = LCD_EXTERN_I2C_BUS_INVALID;
+               lcd_extern_config.i2c_bus = LCD_EXTERN_I2C_BUS_INVALID;
        else
-               lcd_ext_i2c_bus = lcd_extern_get_i2c_bus_str(str);
-       if (lcd_debug_print_flag)
-               EXTPR("i2c_bus=%s[%d]\n", str, lcd_ext_i2c_bus);
+               lcd_extern_config.i2c_bus = lcd_extern_get_i2c_bus_str(str);
 
        ret = of_property_read_u32_array(lcd_extern_dev->of_node,
-               "i2c_gpio_off", &extern_para[0], 4);
+                       "i2c_gpio_off", &extern_para[0], 4);
        if (ret) {
-               lcd_ext_i2c_sck_gpio = LCD_EXTERN_GPIO_NUM_MAX;
-               lcd_ext_i2c_sck_gpio_off = 2;
-               lcd_ext_i2c_sda_gpio = LCD_EXTERN_GPIO_NUM_MAX;
-               lcd_ext_i2c_sda_gpio_off = 2;
+               lcd_extern_config.i2c_sck_gpio = LCD_EXTERN_GPIO_NUM_MAX;
+               lcd_extern_config.i2c_sck_gpio_off = 2;
+               lcd_extern_config.i2c_sda_gpio = LCD_EXTERN_GPIO_NUM_MAX;
+               lcd_extern_config.i2c_sda_gpio_off = 2;
        } else {
-               lcd_ext_i2c_sck_gpio = extern_para[0];
-               lcd_ext_i2c_sck_gpio_off = extern_para[1];
-               lcd_ext_i2c_sda_gpio = extern_para[2];
-               lcd_ext_i2c_sda_gpio_off = extern_para[3];
+               lcd_extern_config.i2c_sck_gpio = (unsigned char)extern_para[0];
+               lcd_extern_config.i2c_sck_gpio_off =
+                       (unsigned char) extern_para[1];
+               lcd_extern_config.i2c_sda_gpio = (unsigned char)extern_para[2];
+               lcd_extern_config.i2c_sda_gpio_off =
+                       (unsigned char)extern_para[3];
        }
 
+       ret = of_property_read_string(lcd_extern_dev->of_node,
+                       "pinctrl-names", &str);
+       if (ret)
+               lcd_extern_config.pinmux_valid = 0;
+       else
+               lcd_extern_config.pinmux_valid = 1;
+
        ret = of_property_read_u32(lcd_extern_dev->of_node,
-                       "key_valid", &lcd_ext_key_valid);
+                       "key_valid", &extern_para[0]);
        if (ret) {
                if (lcd_debug_print_flag)
                        EXTPR("failed to get key_valid\n");
-               lcd_ext_key_valid = 0;
+               lcd_extern_config.key_valid = 0;
+       } else {
+               lcd_extern_config.key_valid = (unsigned char)extern_para[0];
        }
-       EXTPR("key_valid: %d\n", lcd_ext_key_valid);
+       EXTPR("key_valid: %d\n", lcd_extern_config.key_valid);
 
-       if (lcd_ext_key_valid) {
+       if (lcd_extern_config.key_valid) {
                ret = lcd_unifykey_check("lcd_extern");
                if (ret < 0)
                        load_id = 0;
                else
                        load_id = 1;
        }
-       memset(&extconf, 0, sizeof(struct lcd_extern_config_s));
-       extconf.table_init_on = lcd_ext_init_on_table;
-       extconf.table_init_off = lcd_ext_init_off_table;
+
        if (load_id) {
                EXTPR("%s from unifykey\n", __func__);
                lcd_ext_config_load = 1;
-               ret = lcd_extern_get_config_unifykey(&extconf);
+               ret = lcd_extern_get_config_unifykey(&lcd_extern_config);
                if (ret == 0)
-                       lcd_extern_add_driver(&extconf);
+                       lcd_extern_add_driver(&lcd_extern_config);
        } else {
 #ifdef CONFIG_OF
-               EXTPR("%s from dts\n", __func__);
+               aml_lcd_notifier_call_chain(LCD_EVENT_EXTERN_SEL, &ext_index);
+               if (ext_index == LCD_EXTERN_INDEX_INVALID) {
+                       EXTERR("%s: invalid index\n", __func__);
+                       return -1;
+               }
+               sprintf(ext_propname, "extern_%d", ext_index);
+               EXTPR("%s %s from dts\n", __func__, ext_propname);
                lcd_ext_config_load = 0;
-               for_each_child_of_node(lcd_extern_dev->of_node, child) {
-                       ret = lcd_extern_get_config_dts(child, &extconf);
-                       if (ret == 0)
-                               lcd_extern_add_driver(&extconf);
+               child = of_get_child_by_name(lcd_extern_dev->of_node,
+                       ext_propname);
+               if (child == NULL) {
+                       EXTERR("failed to get %s\n", ext_propname);
+                       return -1;
                }
+               ret = lcd_extern_get_config_dts(child, &lcd_extern_config);
+               if (ret == 0)
+                       lcd_extern_add_driver(&lcd_extern_config);
 #endif
        }
 
-       kfree(lcd_ext_init_on_table);
-       kfree(lcd_ext_init_off_table);
        return 0;
 }
 
@@ -1477,28 +1434,26 @@ static int lcd_extern_add_i2c(struct aml_lcd_extern_driver_s *ext_drv)
 {
        int ret = 0;
 
-       if (strcmp(ext_drv->config.name, "ext_default") == 0) {
-#ifdef LCD_EXTERN_DEFAULT_ENABLE
+       if (strcmp(ext_drv->config->name, "ext_default") == 0) {
                ret = aml_lcd_extern_default_probe(ext_drv);
-#endif
-       } else if (strcmp(ext_drv->config.name, "i2c_T5800Q") == 0) {
+       } else if (strcmp(ext_drv->config->name, "i2c_T5800Q") == 0) {
 #ifdef CONFIG_AMLOGIC_LCD_EXTERN_I2C_T5800Q
                ret = aml_lcd_extern_i2c_T5800Q_probe(ext_drv);
 #endif
-       } else if (strcmp(ext_drv->config.name, "i2c_tc101") == 0) {
+       } else if (strcmp(ext_drv->config->name, "i2c_tc101") == 0) {
 #ifdef CONFIG_AMLOGIC_LCD_EXTERN_I2C_TC101
                ret = aml_lcd_extern_i2c_tc101_probe(ext_drv);
 #endif
-       } else if (strcmp(ext_drv->config.name, "i2c_anx6345") == 0) {
+       } else if (strcmp(ext_drv->config->name, "i2c_anx6345") == 0) {
 #ifdef CONFIG_AMLOGIC_LCD_EXTERN_I2C_ANX6345
                ret = aml_lcd_extern_i2c_anx6345_probe(ext_drv);
 #endif
-       } else if (strcmp(ext_drv->config.name, "i2c_DLPC3439") == 0) {
+       } else if (strcmp(ext_drv->config->name, "i2c_DLPC3439") == 0) {
 #ifdef CONFIG_AMLOGIC_LCD_EXTERN_I2C_DLPC3439
                ret = aml_lcd_extern_i2c_DLPC3439_probe(ext_drv);
 #endif
        } else {
-               EXTERR("invalid driver name: %s\n", ext_drv->config.name);
+               EXTERR("invalid driver name: %s\n", ext_drv->config->name);
                ret = -1;
        }
        return ret;
@@ -1508,16 +1463,14 @@ static int lcd_extern_add_spi(struct aml_lcd_extern_driver_s *ext_drv)
 {
        int ret = 0;
 
-       if (strcmp(ext_drv->config.name, "ext_default") == 0) {
-#ifdef LCD_EXTERN_DEFAULT_ENABLE
+       if (strcmp(ext_drv->config->name, "ext_default") == 0) {
                ret = aml_lcd_extern_default_probe(ext_drv);
-#endif
-       } else if (strcmp(ext_drv->config.name, "spi_LD070WS2") == 0) {
+       } else if (strcmp(ext_drv->config->name, "spi_LD070WS2") == 0) {
 #ifdef CONFIG_AMLOGIC_LCD_EXTERN_SPI_LD070WS2
                ret = aml_lcd_extern_spi_LD070WS2_probe(ext_drv);
 #endif
        } else {
-               EXTERR("invalid driver name: %s\n", ext_drv->config.name);
+               EXTERR("invalid driver name: %s\n", ext_drv->config->name);
                ret = -1;
        }
        return ret;
@@ -1527,34 +1480,34 @@ static int lcd_extern_add_mipi(struct aml_lcd_extern_driver_s *ext_drv)
 {
        int ret = 0;
 
-       if (strcmp(ext_drv->config.name, "mipi_default") == 0) {
+       if (strcmp(ext_drv->config->name, "mipi_default") == 0) {
                ret = aml_lcd_extern_mipi_default_probe(ext_drv);
-       } else if (strcmp(ext_drv->config.name, "mipi_N070ICN") == 0) {
+       } else if (strcmp(ext_drv->config->name, "mipi_N070ICN") == 0) {
 #ifdef CONFIG_AMLOGIC_LCD_EXTERN_MIPI_N070ICN
                ret = aml_lcd_extern_mipi_N070ICN_probe(ext_drv);
 #endif
-       } else if (strcmp(ext_drv->config.name, "mipi_KD080D13") == 0) {
+       } else if (strcmp(ext_drv->config->name, "mipi_KD080D13") == 0) {
 #ifdef CONFIG_AMLOGIC_LCD_EXTERN_MIPI_KD080D13
                ret = aml_lcd_extern_mipi_KD080D13_probe(ext_drv);
 #endif
-       } else if (strcmp(ext_drv->config.name, "mipi_TV070WSM") == 0) {
+       } else if (strcmp(ext_drv->config->name, "mipi_TV070WSM") == 0) {
 #ifdef CONFIG_AMLOGIC_LCD_EXTERN_MIPI_TV070WSM
                ret = aml_lcd_extern_mipi_TV070WSM_probe(ext_drv);
 #endif
-       } else if (strcmp(ext_drv->config.name, "mipi_ST7701") == 0) {
+       } else if (strcmp(ext_drv->config->name, "mipi_ST7701") == 0) {
 #ifdef CONFIG_AMLOGIC_LCD_EXTERN_MIPI_ST7701
                ret = aml_lcd_extern_mipi_st7701_probe(ext_drv);
 #endif
-       } else if (strcmp(ext_drv->config.name, "mipi_P070ACB") == 0) {
+       } else if (strcmp(ext_drv->config->name, "mipi_P070ACB") == 0) {
 #ifdef CONFIG_AMLOGIC_LCD_EXTERN_MIPI_P070ACB
                ret = aml_lcd_extern_mipi_p070acb_probe(ext_drv);
 #endif
-       } else if (strcmp(ext_drv->config.name, "mipi_TL050FHV02CT") == 0) {
+       } else if (strcmp(ext_drv->config->name, "mipi_TL050FHV02CT") == 0) {
 #ifdef CONFIG_AMLOGIC_LCD_EXTERN_MIPI_TL050FHV02CT
                ret = aml_lcd_extern_mipi_tl050fhv02ct_probe(ext_drv);
 #endif
        } else {
-               EXTERR("invalid driver name: %s\n", ext_drv->config.name);
+               EXTERR("invalid driver name: %s\n", ext_drv->config->name);
                ret = -1;
        }
        return ret;
@@ -1568,80 +1521,31 @@ static int lcd_extern_add_invalid(struct aml_lcd_extern_driver_s *ext_drv)
 static int lcd_extern_add_driver(struct lcd_extern_config_s *extconf)
 {
        struct aml_lcd_extern_driver_s *ext_drv;
-       int i;
        int ret = 0;
 
-       if (lcd_ext_driver_num >= LCD_EXT_DRIVER_MAX) {
-               EXTERR("driver num is out of support\n");
-               return -1;
-       }
        if (extconf->status == 0) {
                EXTERR("driver %s[%d] status is disabled\n",
                        extconf->name, extconf->index);
                return -1;
        }
 
-       i = lcd_ext_driver_num;
-       lcd_ext_driver[i] =
-               kmalloc(sizeof(struct aml_lcd_extern_driver_s), GFP_KERNEL);
-       if (lcd_ext_driver[i] == NULL) {
+       lcd_ext_driver =
+               kzalloc(sizeof(struct aml_lcd_extern_driver_s), GFP_KERNEL);
+       if (lcd_ext_driver == NULL) {
                EXTERR("failed to alloc driver %s[%d], not enough memory\n",
                        extconf->name, extconf->index);
                return -1;
        }
-       lcd_ext_driver[i]->pinmux_flag = 0;
-       ext_drv = lcd_ext_driver[i];
-       /* fill config parameters */
-       ext_drv->config.index = extconf->index;
-       strcpy(ext_drv->config.name, extconf->name);
-       ext_drv->config.type = extconf->type;
-       ext_drv->config.status = extconf->status;
-       ext_drv->config.cmd_size = extconf->cmd_size;
-       ext_drv->config.table_init_on = NULL;
-       ext_drv->config.table_init_off = NULL;
-       ext_drv->config.table_init_loaded = extconf->table_init_loaded;
-       ext_drv->config.table_init_on_cnt = extconf->table_init_on_cnt;
-       if (ext_drv->config.table_init_loaded) {
-               ext_drv->config.table_init_on =
-                       kmalloc(sizeof(unsigned char) * LCD_EXTERN_INIT_ON_MAX,
-                               GFP_KERNEL);
-               if (ext_drv->config.table_init_on == NULL) {
-                       EXTERR("failed to alloc driver %s[%d] init table\n",
-                               extconf->name, extconf->index);
-                       return -1;
-               }
-               ext_drv->config.table_init_off =
-                       kmalloc(sizeof(unsigned char) * LCD_EXTERN_INIT_OFF_MAX,
-                               GFP_KERNEL);
-               if (ext_drv->config.table_init_off == NULL) {
-                       EXTERR("failed to alloc driver %s[%d] init table\n",
-                               extconf->name, extconf->index);
-                       return -1;
-               }
-               memcpy(ext_drv->config.table_init_on, extconf->table_init_on,
-                       LCD_EXTERN_INIT_ON_MAX);
-               memcpy(ext_drv->config.table_init_off, extconf->table_init_off,
-                       LCD_EXTERN_INIT_OFF_MAX);
-       }
+       ext_drv = lcd_ext_driver;
 
-       /* fill config parameters by different type */
-       switch (ext_drv->config.type) {
+       ext_drv->config = extconf;
+       ext_drv->pinmux_flag = 0;
+
+       switch (ext_drv->config->type) {
        case LCD_EXTERN_I2C:
-               ext_drv->config.i2c_addr = extconf->i2c_addr;
-               ext_drv->config.i2c_addr2 = extconf->i2c_addr2;
-               ext_drv->config.i2c_bus = extconf->i2c_bus;
-               ext_drv->config.i2c_sck_gpio = extconf->i2c_sck_gpio;
-               ext_drv->config.i2c_sck_gpio_off = extconf->i2c_sck_gpio_off;
-               ext_drv->config.i2c_sda_gpio = extconf->i2c_sda_gpio;
-               ext_drv->config.i2c_sda_gpio_off = extconf->i2c_sda_gpio_off;
                ret = lcd_extern_add_i2c(ext_drv);
                break;
        case LCD_EXTERN_SPI:
-               ext_drv->config.spi_gpio_cs = extconf->spi_gpio_cs;
-               ext_drv->config.spi_gpio_clk = extconf->spi_gpio_clk;
-               ext_drv->config.spi_gpio_data = extconf->spi_gpio_data;
-               ext_drv->config.spi_clk_freq = extconf->spi_clk_freq;
-               ext_drv->config.spi_clk_pol = extconf->spi_clk_pol;
                ret = lcd_extern_add_spi(ext_drv);
                break;
        case LCD_EXTERN_MIPI:
@@ -1649,20 +1553,22 @@ static int lcd_extern_add_driver(struct lcd_extern_config_s *extconf)
                break;
        default:
                ret = lcd_extern_add_invalid(ext_drv);
-               EXTERR("don't support type %d\n", ext_drv->config.type);
+               EXTERR("don't support type %d\n", ext_drv->config->type);
                break;
        }
        if (ret) {
                EXTERR("add driver failed\n");
-               kfree(lcd_ext_driver[i]->config.table_init_on);
-               kfree(lcd_ext_driver[i]->config.table_init_off);
-               kfree(lcd_ext_driver[i]);
-               lcd_ext_driver[i] = NULL;
+               kfree(lcd_ext_driver->config->table_init_on);
+               kfree(lcd_ext_driver->config->table_init_off);
+               lcd_ext_driver->config->table_init_on = NULL;
+               lcd_ext_driver->config->table_init_off = NULL;
+               kfree(lcd_ext_driver);
+               lcd_ext_driver = NULL;
                return -1;
        }
-       lcd_ext_driver_num++;
+
        EXTPR("add driver %s(%d)\n",
-               ext_drv->config.name, ext_drv->config.index);
+               ext_drv->config->name, ext_drv->config->index);
        return 0;
 }
 
@@ -1670,7 +1576,7 @@ static int lcd_extern_add_driver(struct lcd_extern_config_s *extconf)
  * debug function
  * *********************************************************
  */
-#define EXT_LEN_MAX   2000
+#define EXT_LEN_MAX   300
 static void lcd_extern_init_table_dynamic_size_print(
                struct lcd_extern_config_s *econf, int flag)
 {
@@ -1679,7 +1585,7 @@ static void lcd_extern_init_table_dynamic_size_print(
        char *str;
        unsigned char *init_table;
 
-       str = kmalloc(EXT_LEN_MAX*sizeof(char), GFP_KERNEL);
+       str = kcalloc(EXT_LEN_MAX, sizeof(char), GFP_KERNEL);
        if (str == NULL) {
                EXTERR("lcd_extern_dynamic_size str malloc error\n");
                return;
@@ -1714,11 +1620,13 @@ static void lcd_extern_init_table_dynamic_size_print(
                        k = snprintf(str, EXT_LEN_MAX, "  0x%02x,%d,",
                                init_table[i], cmd_size);
                        if (cmd_size > 0) {
-                               for (j = 0; j < cmd_size; j++) {
+                               for (j = 0; j < (cmd_size - 1); j++) {
                                        k += snprintf(str+k, EXT_LEN_MAX,
                                                "0x%02x,",
                                                init_table[i+2+j]);
                                }
+                               snprintf(str+k, EXT_LEN_MAX,
+                                       "%d,", init_table[i+cmd_size+1]);
                        }
                        pr_info("%s\n", str);
                        i += (cmd_size + 2);
@@ -1776,7 +1684,7 @@ static void lcd_extern_init_table_fixed_size_print(
        char *str;
        unsigned char *init_table;
 
-       str = kmalloc(EXT_LEN_MAX*sizeof(char), GFP_KERNEL);
+       str = kcalloc(EXT_LEN_MAX, sizeof(char), GFP_KERNEL);
        if (str == NULL) {
                EXTERR("lcd_extern_fixed_size str malloc error\n");
                return;
@@ -1800,10 +1708,12 @@ static void lcd_extern_init_table_fixed_size_print(
        i = 0;
        while (i < max_len) {
                k = snprintf(str, EXT_LEN_MAX, " ");
-               for (j = 0; j < cmd_size; j++) {
+               for (j = 0; j < (cmd_size - 1); j++) {
                        k += snprintf(str+k, EXT_LEN_MAX, " 0x%02x",
                                init_table[i+j]);
                }
+               snprintf(str+k, EXT_LEN_MAX, " %d",
+                       init_table[i+cmd_size-1]);
                pr_info("%s\n", str);
 
                if (init_table[i] == LCD_EXTERN_INIT_END)
@@ -1813,15 +1723,16 @@ static void lcd_extern_init_table_fixed_size_print(
        kfree(str);
 }
 
-static void lcd_extern_config_dump(struct aml_lcd_extern_driver_s *ext_drv)
+static ssize_t lcd_extern_info_show(struct class *class,
+               struct class_attribute *attr, char *buf)
 {
        struct lcd_extern_config_s *econf;
 
-       if (ext_drv == NULL)
-               return;
+       if (lcd_ext_driver == NULL)
+               return sprintf(buf, "lcd extern  driver is NULL\n");
 
-       econf = &ext_drv->config;
-       EXTPR("driver %s(%d) info:\n", econf->name, econf->index);
+       econf = lcd_ext_driver->config;
+       pr_info("lcd extern driver %s(%d) info:\n", econf->name, econf->index);
        pr_info("status:          %d\n", econf->status);
        switch (econf->type) {
        case LCD_EXTERN_I2C:
@@ -1880,93 +1791,127 @@ static void lcd_extern_config_dump(struct aml_lcd_extern_driver_s *ext_drv)
                pr_info("not support extern_type\n");
                break;
        }
-       pr_info("\n");
-}
-
-static const char *lcd_extern_debug_usage_str = {
-"Usage:\n"
-"    echo index <n> > info ; dump specified index driver config\n"
-"    echo all > info ; dump all driver config\n"
-};
 
-static ssize_t lcd_extern_debug_help(struct class *class,
-               struct class_attribute *attr, char *buf)
-{
-       return sprintf(buf, "%s\n", lcd_extern_debug_usage_str);
+       return sprintf(buf, "\n");
 }
 
-static ssize_t lcd_extern_info_dump(struct class *class,
-               struct class_attribute *attr, const char *buf, size_t count)
-{
-       unsigned int ret = 0;
-       int i, index;
-       struct aml_lcd_extern_driver_s *ext_drv;
-
-       index = LCD_EXTERN_INDEX_INVALID;
-       switch (buf[0]) {
-       case 'i':
-               ret = sscanf(buf, "index %d", &index);
-               if (ret == 1) {
-                       ext_drv = aml_lcd_extern_get_driver(index);
-                       lcd_extern_config_dump(ext_drv);
-               } else {
-                       EXTERR("invalid parameters\n");
-               }
-               break;
-       case 'a':
-               for (i = 0; i < lcd_ext_driver_num; i++)
-                       lcd_extern_config_dump(lcd_ext_driver[i]);
-               break;
-       default:
-               EXTERR("invalid command\n");
-               break;
-       }
-
-       return count;
-}
-
-static ssize_t lcd_extern_debug_key_valid_show(struct class *class,
+static ssize_t lcd_extern_key_valid_show(struct class *class,
                struct class_attribute *attr, char *buf)
 {
-       return sprintf(buf, "%d\n", lcd_ext_key_valid);
+       return sprintf(buf, "%d\n", lcd_extern_config.key_valid);
 }
 
-static ssize_t lcd_extern_debug_config_load_show(struct class *class,
+static ssize_t lcd_extern_config_load_show(struct class *class,
                struct class_attribute *attr, char *buf)
 {
        return sprintf(buf, "%d\n", lcd_ext_config_load);
 }
 
-static const char *lcd_extern_debug_test_usage_str = {
+static const char *lcd_extern_debug_usage_str = {
 "Usage:\n"
-"    echo <index> <on/off> > test ; test power on/off for index extern device\n"
+"    echo test <on/off> > debug ; test power on/off for extern device\n"
 "        <on/off>: 1 for power on, 0 for power off\n"
+"    echo r <addr_sel> <reg> > debug ; read reg for extern device\n"
+"    echo d <addr_sel> <reg> <cnt> > debug ; dump regs for extern device\n"
+"    echo w <addr_sel> <reg> <value> > debug ; write reg for extern device\n"
 };
 
-static ssize_t lcd_extern_debug_test_show(struct class *class,
+static ssize_t lcd_extern_debug_show(struct class *class,
                struct class_attribute *attr, char *buf)
 {
-       return sprintf(buf, "%s\n", lcd_extern_debug_test_usage_str);
+       return sprintf(buf, "%s\n", lcd_extern_debug_usage_str);
 }
 
-static ssize_t lcd_extern_debug_test_store(struct class *class,
+static ssize_t lcd_extern_debug_store(struct class *class,
                struct class_attribute *attr, const char *buf, size_t count)
 {
        unsigned int ret;
-       int index, flag = 0;
-       struct aml_lcd_extern_driver_s *ext_drv;
+       unsigned int val[3], i;
+       unsigned char reg, value;
 
-       index = LCD_EXTERN_INDEX_INVALID;
-       ret = sscanf(buf, "%d %d", &index, &flag);
-       ext_drv = aml_lcd_extern_get_driver(index);
-       if (ext_drv) {
-               if (flag) {
-                       if (ext_drv->power_on)
-                               ext_drv->power_on(ext_drv);
+       if (lcd_ext_driver == NULL) {
+               pr_info("lcd_extern_driver is null\n");
+               return count;
+       }
+
+       switch (buf[0]) {
+       case 't':
+               ret = sscanf(buf, "test %d", &val[0]);
+               if (ret == 1) {
+                       if (val[0]) {
+                               if (lcd_ext_driver->power_on)
+                                       lcd_ext_driver->power_on();
+                       } else {
+                               if (lcd_ext_driver->power_off)
+                                       lcd_ext_driver->power_off();
+                       }
+               } else {
+                       pr_info("invalid data\n");
+                       return -EINVAL;
+               }
+               break;
+       case 'r':
+               ret = sscanf(buf, "r %d %x", &val[0], &val[1]);
+               if (ret == 2) {
+                       lcd_ext_driver->config->addr_sel =
+                               (unsigned char)val[0];
+                       reg = (unsigned char)val[1];
+                       if (lcd_ext_driver->reg_read) {
+                               lcd_ext_driver->reg_read(reg, &value);
+                               pr_info("reg read: 0x%02x = 0x%02x\n",
+                                       reg, value);
+                       }
                } else {
-                       if (ext_drv->power_off)
-                               ext_drv->power_off(ext_drv);
+                       pr_info("invalid data\n");
+                       return -EINVAL;
                }
+               break;
+       case 'd':
+               ret = sscanf(buf, "d %d %x %d", &val[0], &val[1], &val[2]);
+               if (ret == 3) {
+                       lcd_ext_driver->config->addr_sel =
+                               (unsigned char)val[0];
+                       reg = (unsigned char)val[1];
+                       if (lcd_ext_driver->reg_read) {
+                               pr_info("reg dump:\n");
+                               for (i = 0; i < val[2]; i++) {
+                                       lcd_ext_driver->reg_read(reg+i, &value);
+                                       pr_info("  0x%02x = 0x%02x\n",
+                                               reg, value);
+                               }
+                       }
+               } else {
+                       pr_info("invalid data\n");
+                       return -EINVAL;
+               }
+               break;
+       case 'w':
+               ret = sscanf(buf, "w %d %x %x", &val[0], &val[1], &val[2]);
+               if (ret == 2) {
+                       lcd_ext_driver->config->addr_sel =
+                               (unsigned char)val[0];
+                       reg = (unsigned char)val[1];
+                       value = (unsigned char)val[2];
+                       if (lcd_ext_driver->reg_write) {
+                               lcd_ext_driver->reg_write(reg, value);
+                               if (lcd_ext_driver->reg_read) {
+                                       lcd_ext_driver->reg_read(reg, &value);
+                                       pr_info(
+                               "reg write 0x%02x = 0x%02x, readback: 0x%02x\n",
+                                       reg, val[2], value);
+                               } else {
+                                       pr_info("reg write 0x%02x = 0x%02x\n",
+                                               reg, value);
+                               }
+                       }
+               } else {
+                       pr_info("invalid data\n");
+                       return -EINVAL;
+               }
+               break;
+       default:
+               pr_info("invalid data\n");
+               break;
        }
 
        return count;
@@ -1974,13 +1919,13 @@ static ssize_t lcd_extern_debug_test_store(struct class *class,
 
 static struct class_attribute lcd_extern_class_attrs[] = {
        __ATTR(info, 0644,
-               lcd_extern_debug_help, lcd_extern_info_dump),
+               lcd_extern_info_show, NULL),
        __ATTR(key_valid,   0444,
-                lcd_extern_debug_key_valid_show, NULL),
+                lcd_extern_key_valid_show, NULL),
        __ATTR(config_load, 0444,
-               lcd_extern_debug_config_load_show, NULL),
-       __ATTR(test, 0644,
-               lcd_extern_debug_test_show, lcd_extern_debug_test_store),
+               lcd_extern_config_load_show, NULL),
+       __ATTR(debug, 0644,
+               lcd_extern_debug_show, lcd_extern_debug_store),
 };
 
 static struct class *debug_class;
@@ -2022,7 +1967,7 @@ static int remove_lcd_extern_class(void)
 static int aml_lcd_extern_probe(struct platform_device *pdev)
 {
        lcd_extern_dev = &pdev->dev;
-       lcd_ext_driver_num = 0;
+
        lcd_extern_get_config(); /* also add ext_driver */
 
        creat_lcd_extern_class();
@@ -2033,15 +1978,13 @@ static int aml_lcd_extern_probe(struct platform_device *pdev)
 
 static int aml_lcd_extern_remove(struct platform_device *pdev)
 {
-       int i;
-
        remove_lcd_extern_class();
-       for (i = 0; i < lcd_ext_driver_num; i++) {
-               kfree(lcd_ext_driver[i]->config.table_init_on);
-               kfree(lcd_ext_driver[i]->config.table_init_off);
-               kfree(lcd_ext_driver[i]);
-               lcd_ext_driver[i] = NULL;
-       }
+       kfree(lcd_ext_driver->config->table_init_on);
+       kfree(lcd_ext_driver->config->table_init_off);
+       lcd_ext_driver->config->table_init_on = NULL;
+       lcd_ext_driver->config->table_init_off = NULL;
+       kfree(lcd_ext_driver);
+       lcd_ext_driver = NULL;
        return 0;
 }
 
diff --git a/drivers/amlogic/media/vout/lcd/lcd_extern/lcd_extern.dts b/drivers/amlogic/media/vout/lcd/lcd_extern/lcd_extern.dts
deleted file mode 100644 (file)
index 209b51a..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * drivers/amlogic/media/vout/lcd/lcd_extern/lcd_extern.dts
- *
- * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- */
-
-lcd_extern{
-       compatible = "amlogic, lcd_extern";
-       dev_name = "lcd_extern";
-       status = "okay";
-
-       extern-gpios = <&gpio GPIODV_1 GPIO_ACTIVE_HIGH
-                       &gpio GPIODV_16 GPIO_ACTIVE_HIGH
-                       &gpio GPIODV_17 GPIO_ACTIVE_HIGH>;
-       extern_gpio_names = "GPIODV_1","GPIODV_16","GPIODV_17";
-
-       extern_0{
-               index = <0>;
-               extern_name = "i2c_T5800Q";
-               status = "disabled";
-
-               type = <0>; /** lcd_extern_driver type: 0=i2c, 1=spi, 2=mipi */
-               i2c_address = <0x1c>; /** 7bit i2c address */
-               i2c_bus = "i2c_bus_d";
-       };
-
-       extern_1{
-               index = <1>;
-               extern_name = "i2c_tc101";
-               status = "disabled";
-
-               type = <0>; /** lcd_extern_driver type: 0=i2c, 1=spi, 2=mipi */
-               i2c_address = <0x7e>; /** 7bit i2c address */
-               i2c_bus = "i2c_bus_a";
-       };
-
-       extern_2{
-               index = <2>;
-               extern_name = "i2c_anx6345";
-               status = "disabled";
-
-               type = <0>; /** lcd_extern_driver type: 0=i2c, 1=spi, 2=mipi */
-               i2c_address = <0x38>; /** 7bit i2c address */
-               i2c_bus = "i2c_bus_b";
-               lane_num = <1>; /** edp lane_num: 1/2/4 */
-               bits = <0>;  /** lcd_bits(0=6bit, 1=8bit) */
-               link_rate = <1>; /** edp link rate: (0=1.62G, 1=27G, 2=5.4G) */
-       };
-
-       extern_3{
-               index = <3>;
-               extern_name = "spi_LD070WS2";
-               status = "disabled";
-
-               type = <1>; /** lcd_extern_driver type: 0=i2c, 1=spi, 2=mipi */
-
-               gpio_spi_cs = <0>; /* index in extern-gpios */
-               gpio_spi_clk = <1>; /* index in extern-gpios */
-               gpio_spi_data = <2>; /* index in extern-gpios */
-       };
-
-       extern_4{
-               index = <4>;
-               extern_name = "mipi_N070ICN";
-               status = "disabled";
-
-               type = <2>; /** lcd_extern_driver type: 0=i2c, 1=spi, 2=mipi */
-       };
-
-       extern_5{
-               index = <5>;
-               extern_name = "mipi_KD080D13";
-               status = "disabled";
-
-               type = <2>; /** lcd_extern_driver type: 0=i2c, 1=spi, 2=mipi */
-       };
-
-       extern_6{
-               index = <6>;
-               extern_name = "i2c_DLPC3439";
-               status = "disabled";
-
-               type = <0>; /** lcd_extern_driver type: 0=i2c, 1=spi, 2=mipi */
-               i2c_address = <0x1b>; /** 7bit i2c address */
-               i2c_bus = "i2c_bus_a";
-       };
-};
-
index e7c5672..9fd9212 100644 (file)
@@ -34,15 +34,23 @@ extern struct device_node *aml_lcd_extern_get_dts_child(int index);
 extern void lcd_extern_gpio_probe(unsigned char index);
 extern void lcd_extern_gpio_set(unsigned char index, int value);
 extern unsigned int lcd_extern_gpio_get(unsigned char index);
-extern void lcd_extern_pinmux_set(
-       struct aml_lcd_extern_driver_s *ext_drv, int status);
+extern void lcd_extern_pinmux_set(int status);
 
-#define LCD_EXTERN_DEFAULT_ENABLE
+/* common API */
+extern struct aml_lcd_extern_i2c_dev_s *lcd_extern_get_i2c_device(
+               unsigned char addr);
+extern int lcd_extern_i2c_write(struct i2c_client *i2client,
+               unsigned char *buff, unsigned int len);
+extern int lcd_extern_i2c_read(struct i2c_client *i2client,
+               unsigned char *buff, unsigned int len);
 
-#ifdef LCD_EXTERN_DEFAULT_ENABLE
+
+/* specific API */
 extern int aml_lcd_extern_default_probe(
        struct aml_lcd_extern_driver_s *ext_drv);
-#endif
+extern int aml_lcd_extern_mipi_default_probe(
+       struct aml_lcd_extern_driver_s *ext_drv);
+
 #ifdef CONFIG_AMLOGIC_LCD_EXTERN_I2C_T5800Q
 extern int aml_lcd_extern_i2c_T5800Q_probe(
        struct aml_lcd_extern_driver_s *ext_drv);
@@ -87,8 +95,6 @@ extern int aml_lcd_extern_mipi_p070acb_probe(
 extern int aml_lcd_extern_mipi_tl050fhv02ct_probe(
        struct aml_lcd_extern_driver_s *ext_drv);
 #endif
-extern int aml_lcd_extern_mipi_default_probe(
-       struct aml_lcd_extern_driver_s *ext_drv);
 
 #endif
 
index 80b15c2..36cab44 100644 (file)
@@ -106,8 +106,8 @@ static int lcd_extern_driver_update(struct aml_lcd_extern_driver_s *ext_drv)
        int ret = 0;
 
        if (ext_drv) {
-               ext_drv->config.table_init_on  = &mipi_init_on_table[0];
-               ext_drv->config.table_init_off = &mipi_init_off_table[0];
+               ext_drv->config->table_init_on  = &mipi_init_on_table[0];
+               ext_drv->config->table_init_off = &mipi_init_off_table[0];
        } else {
                EXTERR("%s driver is null\n", LCD_EXTERN_NAME);
                ret = -1;
index 1e7111a..7bb0e75 100644 (file)
@@ -223,8 +223,8 @@ static int lcd_extern_driver_update(struct aml_lcd_extern_driver_s *ext_drv)
        int ret = 0;
 
        if (ext_drv) {
-               ext_drv->config.table_init_on  = &mipi_init_on_table[0];
-               ext_drv->config.table_init_off = &mipi_init_off_table[0];
+               ext_drv->config->table_init_on  = &mipi_init_on_table[0];
+               ext_drv->config->table_init_off = &mipi_init_off_table[0];
        } else {
                EXTERR("%s driver is null\n", LCD_EXTERN_NAME);
                ret = -1;
index 2c6b020..ed09e4d 100644 (file)
@@ -212,8 +212,8 @@ static int lcd_extern_driver_update(struct aml_lcd_extern_driver_s *ext_drv)
        int ret = 0;
 
        if (ext_drv) {
-               ext_drv->config.table_init_on  = &mipi_init_on_table[0];
-               ext_drv->config.table_init_off = &mipi_init_off_table[0];
+               ext_drv->config->table_init_on  = &mipi_init_on_table[0];
+               ext_drv->config->table_init_off = &mipi_init_off_table[0];
        } else {
                EXTERR("%s driver is null\n", LCD_EXTERN_NAME);
                ret = -1;
index e1597d7..e2e8f0c 100644 (file)
@@ -111,8 +111,8 @@ static int lcd_extern_driver_update(struct aml_lcd_extern_driver_s *ext_drv)
        int ret = 0;
 
        if (ext_drv) {
-               ext_drv->config.table_init_on  = &mipi_init_on_table[0];
-               ext_drv->config.table_init_off = &mipi_init_off_table[0];
+               ext_drv->config->table_init_on  = &mipi_init_on_table[0];
+               ext_drv->config->table_init_off = &mipi_init_off_table[0];
        } else {
                EXTERR("%s driver is null\n", LCD_EXTERN_NAME);
                ret = -1;
index 3cf4f5d..457c6fc 100644 (file)
@@ -153,8 +153,8 @@ static int lcd_extern_driver_update(struct aml_lcd_extern_driver_s *ext_drv)
        int ret = 0;
 
        if (ext_drv) {
-               ext_drv->config.table_init_on  = &mipi_init_on_table[0];
-               ext_drv->config.table_init_off = &mipi_init_off_table[0];
+               ext_drv->config->table_init_on  = &mipi_init_on_table[0];
+               ext_drv->config->table_init_off = &mipi_init_off_table[0];
        } else {
                EXTERR("%s driver is null\n", LCD_EXTERN_NAME);
                ret = -1;
index 5559209..903a36b 100644 (file)
@@ -174,8 +174,8 @@ static int lcd_extern_driver_update(struct aml_lcd_extern_driver_s *ext_drv)
        int ret = 0;
 
        if (ext_drv) {
-               ext_drv->config.table_init_on  = &mipi_init_on_table[0];
-               ext_drv->config.table_init_off = &mipi_init_off_table[0];
+               ext_drv->config->table_init_on  = &mipi_init_on_table[0];
+               ext_drv->config->table_init_off = &mipi_init_off_table[0];
        } else {
                EXTERR("%s driver is null\n", LCD_EXTERN_NAME);
                ret = -1;
index 32e339e..6060897 100644 (file)
@@ -57,13 +57,13 @@ static int lcd_extern_driver_update(struct aml_lcd_extern_driver_s *ext_drv)
                return -1;
        }
 
-       if (ext_drv->config.type == LCD_EXTERN_MAX) { //default for no dt
-               ext_drv->config.index = LCD_EXTERN_INDEX;
-               ext_drv->config.type = LCD_EXTERN_TYPE;
-               strcpy(ext_drv->config.name, LCD_EXTERN_NAME);
+       if (ext_drv->config->type == LCD_EXTERN_MAX) { //default for no dt
+               ext_drv->config->index = LCD_EXTERN_INDEX;
+               ext_drv->config->type = LCD_EXTERN_TYPE;
+               strcpy(ext_drv->config->name, LCD_EXTERN_NAME);
 
-               ext_drv->config.table_init_on = &mipi_init_on_table[0];
-               ext_drv->config.table_init_off = &mipi_init_off_table[0];
+               ext_drv->config->table_init_on = &mipi_init_on_table[0];
+               ext_drv->config->table_init_off = &mipi_init_off_table[0];
        }
 
 
index 768a402..a0d025a 100644 (file)
@@ -36,7 +36,12 @@ static struct lcd_extern_config_s *ext_config;
 
 #define LCD_EXTERN_NAME                "lcd_spi_LD070WS2"
 
-#define SPI_DELAY              30 /* unit: us */
+#define SPI_DELAY                 30 /* unit: us */
+#define SPI_GPIO_CS               0 /* index */
+#define SPI_GPIO_CLK              1 /* index */
+#define SPI_GPIO_DATA             2 /* index */
+#define SPI_CLK_FREQ              10000 /* Hz */
+#define SPI_CLK_POL               1
 
 #define LCD_EXTERN_CMD_SIZE        4
 static unsigned char init_on_table[] = {
@@ -228,11 +233,11 @@ static int lcd_extern_driver_update(struct aml_lcd_extern_driver_s *ext_drv)
                return -1;
        }
 
-       if (ext_drv->config.table_init_loaded == 0) {
-               ext_drv->config.table_init_on  = init_on_table;
-               ext_drv->config.table_init_off = init_off_table;
+       if (ext_drv->config->table_init_loaded == 0) {
+               ext_drv->config->table_init_on  = init_on_table;
+               ext_drv->config->table_init_off = init_off_table;
        }
-       ext_drv->config.spi_delay_us = SPI_DELAY;
+       ext_drv->config->spi_delay_us = SPI_DELAY;
 
        ext_drv->power_on  = lcd_extern_power_on;
        ext_drv->power_off = lcd_extern_power_off;
@@ -244,10 +249,17 @@ int aml_lcd_extern_spi_LD070WS2_probe(struct aml_lcd_extern_driver_s *ext_drv)
 {
        int ret = 0;
 
-       ext_config = &ext_drv->config;
+       ext_config = ext_drv->config;
        ret = lcd_extern_driver_update(ext_drv);
 
        if (lcd_debug_print_flag)
                EXTPR("%s: %d\n", __func__, ret);
        return ret;
 }
+
+int aml_lcd_extern_spi_LD070WS2_remove(void)
+{
+       ext_config = NULL;
+
+       return 0;
+}
index 81bee22..1a73779 100644 (file)
@@ -1916,10 +1916,10 @@ static void mipi_dsi_link_on(struct lcd_config_s *pconf)
                if (lcd_ext == NULL) {
                        LCDPR("no lcd_extern driver\n");
                } else {
-                       if (lcd_ext->config.table_init_on) {
-                               dsi_write_cmd(lcd_ext->config.table_init_on);
+                       if (lcd_ext->config->table_init_on) {
+                               dsi_write_cmd(lcd_ext->config->table_init_on);
                                LCDPR("[extern]%s dsi init on\n",
-                                       lcd_ext->config.name);
+                                       lcd_ext->config->name);
                        }
                }
        }
@@ -1965,10 +1965,10 @@ void mipi_dsi_link_off(struct lcd_config_s *pconf)
                if (lcd_ext == NULL) {
                        LCDPR("no lcd_extern driver\n");
                } else {
-                       if (lcd_ext->config.table_init_off) {
-                               dsi_write_cmd(lcd_ext->config.table_init_off);
+                       if (lcd_ext->config->table_init_off) {
+                               dsi_write_cmd(lcd_ext->config->table_init_off);
                                LCDPR("[extern]%s dsi init off\n",
-                                       lcd_ext->config.name);
+                                       lcd_ext->config->name);
                        }
                }
        }
index f2db70b..9d95b9d 100644 (file)
@@ -195,6 +195,9 @@ static struct lcd_config_s lcd_config_dft = {
        .change_flag = 0,
        .retry_enable_flag = 0,
        .retry_enable_cnt = 0,
+
+       .backlight_index = 0xff,
+       .extern_index = 0xff,
 };
 
 static struct vinfo_s lcd_vinfo = {
@@ -259,12 +262,12 @@ static void lcd_power_ctrl(int status)
                        if (ext_drv) {
                                if (status) {
                                        if (ext_drv->power_on)
-                                               ext_drv->power_on(ext_drv);
+                                               ext_drv->power_on();
                                        else
                                                LCDERR("no ext power on\n");
                                } else {
                                        if (ext_drv->power_off)
-                                               ext_drv->power_off(ext_drv);
+                                               ext_drv->power_off();
                                        else
                                                LCDERR("no ext power off\n");
                                }
@@ -567,14 +570,34 @@ static struct notifier_block lcd_bl_select_nb = {
        .notifier_call = lcd_bl_select_notifier,
 };
 
+static int lcd_extern_select_notifier(struct notifier_block *nb,
+               unsigned long event, void *data)
+{
+       unsigned int *index;
+       struct lcd_config_s *pconf = lcd_driver->lcd_config;
+
+       if ((event & LCD_EVENT_EXTERN_SEL) == 0)
+               return NOTIFY_DONE;
+       /* LCDPR("%s: 0x%lx\n", __func__, event); */
+
+       index = (unsigned int *)data;
+       *index = pconf->extern_index;
+       if (pconf->lcd_basic.lcd_type == LCD_MIPI) {
+               if (*index == LCD_EXTERN_INDEX_INVALID)
+                       *index = pconf->lcd_control.mipi_config->extern_init;
+       }
+
+       return NOTIFY_OK;
+}
+
+static struct notifier_block lcd_extern_select_nb = {
+       .notifier_call = lcd_extern_select_notifier,
+};
+
 static int lcd_notifier_register(void)
 {
        int ret = 0;
 
-       ret = aml_lcd_notifier_register(&lcd_bl_select_nb);
-       if (ret)
-               LCDERR("register aml_bl_select_notifier failed\n");
-
        ret = aml_lcd_notifier_register(&lcd_power_encl_on_nb);
        if (ret)
                LCDERR("register lcd_power_encl_on_nb failed\n");
@@ -594,6 +617,13 @@ static int lcd_notifier_register(void)
        if (ret)
                LCDERR("register lcd_power_screen_restore_nb failed\n");
 
+       ret = aml_lcd_notifier_register(&lcd_bl_select_nb);
+       if (ret)
+               LCDERR("register aml_bl_select_notifier failed\n");
+       ret = aml_lcd_notifier_register(&lcd_extern_select_nb);
+       if (ret)
+               LCDERR("register lcd_extern_select_nb failed\n");
+
        return 0;
 }
 
@@ -607,6 +637,7 @@ static void lcd_notifier_unregister(void)
        aml_lcd_notifier_unregister(&lcd_power_encl_on_nb);
 
        aml_lcd_notifier_unregister(&lcd_bl_select_nb);
+       aml_lcd_notifier_unregister(&lcd_extern_select_nb);
 }
 /* **************************************** */
 
index 9037904..c341dff 100644 (file)
@@ -25,15 +25,15 @@ enum lcd_extern_type_e {
        LCD_EXTERN_MAX,
 };
 
-enum lcd_extern_i2c_bus_e {
-       LCD_EXTERN_I2C_BUS_AO = 0,
-       LCD_EXTERN_I2C_BUS_A,
-       LCD_EXTERN_I2C_BUS_B,
-       LCD_EXTERN_I2C_BUS_C,
-       LCD_EXTERN_I2C_BUS_D,
-       LCD_EXTERN_I2C_BUS_MAX,
-};
+#define LCD_EXTERN_I2C_BUS_0          0
+#define LCD_EXTERN_I2C_BUS_1          1
+#define LCD_EXTERN_I2C_BUS_2          2
+#define LCD_EXTERN_I2C_BUS_3          3
+#define LCD_EXTERN_I2C_BUS_4          4
+#define LCD_EXTERN_I2C_BUS_MAX        0xff
+
 #define LCD_EXTERN_I2C_BUS_INVALID    0xff
+#define LCD_EXTERN_I2C_ADDR_INVALID   0xff
 
 #define LCD_EXTERN_SPI_CLK_FREQ_DFT   10000 /* default 10k */
 
@@ -57,6 +57,10 @@ struct lcd_extern_config_s {
        char name[LCD_EXTERN_NAME_LEN_MAX];
        enum lcd_extern_type_e type;
        unsigned char status;
+       unsigned char pinmux_valid;
+       unsigned char key_valid;
+       unsigned char addr_sel; /* internal used */
+
        unsigned char i2c_addr;
        unsigned char i2c_addr2;
        unsigned char i2c_bus;
@@ -64,31 +68,33 @@ struct lcd_extern_config_s {
        unsigned char i2c_sck_gpio_off;
        unsigned char i2c_sda_gpio;
        unsigned char i2c_sda_gpio_off;
+
        unsigned char spi_gpio_cs;
        unsigned char spi_gpio_clk;
        unsigned char spi_gpio_data;
        unsigned int spi_clk_freq;
        unsigned int spi_delay_us;
        unsigned char spi_clk_pol;
+
        unsigned char cmd_size;
-       unsigned char table_init_loaded; /* internal use */
        unsigned char *table_init_on;
        unsigned char *table_init_off;
-       unsigned int table_init_on_cnt;
+       unsigned char table_init_loaded; /* internal use */
+       unsigned int table_init_on_cnt; /* internal use */
 };
 
 /* global API */
-#define LCD_EXT_DRIVER_MAX    10
 struct aml_lcd_extern_driver_s {
-       struct lcd_extern_config_s config;
+       struct lcd_extern_config_s *config;
        int (*reg_read)(unsigned char reg, unsigned char *buf);
        int (*reg_write)(unsigned char reg, unsigned char value);
-       int (*power_on)(struct aml_lcd_extern_driver_s *ext_drv);
-       int (*power_off)(struct aml_lcd_extern_driver_s *ext_drv);
+       int (*power_on)(void);
+       int (*power_off)(void);
        struct pinctrl *pin;
        unsigned int pinmux_flag;
 };
 
+#define LCD_EXT_I2C_DEV_MAX    10
 struct aml_lcd_extern_i2c_dev_s {
        char name[30];
        struct i2c_client *client;
index e76822a..00b7f76 100644 (file)
@@ -66,6 +66,7 @@
 #define LCD_EVENT_BACKLIGHT_UPDATE  (1 << 9)
 
 #define LCD_EVENT_GAMMA_UPDATE      (1 << 10)
+#define LCD_EVENT_EXTERN_SEL        (1 << 11)
 
 /* lcd frame rate change occurred */
 #define LCD_EVENT_FRAME_RATE_ADJUST (1 << 12)
index a8e8565..7a75f18 100644 (file)
@@ -384,6 +384,7 @@ struct lcd_clk_gate_ctrl_s {
 struct lcd_config_s {
        char *lcd_propname;
        unsigned int backlight_index;
+       unsigned int extern_index;
        struct lcd_basic_s lcd_basic;
        struct lcd_timing_s lcd_timing;
        struct lcd_hdr_info_s hdr_info;