From cfc3eabe2fa78a11d6e99e94e616d363bb5b4b76 Mon Sep 17 00:00:00 2001 From: Weiming Liu Date: Fri, 18 Aug 2017 15:47:39 +0800 Subject: [PATCH] lcd_extern: fix i2c address mistake for dts config PD#149233: lcd: add lcd_extern driver za7783 1.add lcd_extern driver za7783 2.modify the axg pll parameters 3.read under the dts lcd_extern i2c address errors Change-Id: Ib059805a6a82d7896b2394d451d5aedb3f10ecb9 Signed-off-by: Weiming Liu --- .../boot/dts/amlogic/mesonaxg_s400-panel.dtsi | 71 ++ drivers/amlogic/media/vout/lcd/lcd_clk_config.c | 2 +- drivers/amlogic/media/vout/lcd/lcd_clk_config.h | 6 +- .../media/vout/lcd/lcd_extern/ext_default.c | 476 ++++++++---- .../amlogic/media/vout/lcd/lcd_extern/i2c_T5800Q.c | 47 +- .../amlogic/media/vout/lcd/lcd_extern/lcd_extern.c | 859 +++++++++++++-------- .../media/vout/lcd/lcd_extern/spi_LD070WS2.c | 64 +- include/linux/amlogic/media/vout/lcd/lcd_extern.h | 29 +- 8 files changed, 998 insertions(+), 556 deletions(-) diff --git a/arch/arm64/boot/dts/amlogic/mesonaxg_s400-panel.dtsi b/arch/arm64/boot/dts/amlogic/mesonaxg_s400-panel.dtsi index 7e547ed..ce1ff28 100644 --- a/arch/arm64/boot/dts/amlogic/mesonaxg_s400-panel.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesonaxg_s400-panel.dtsi @@ -106,6 +106,77 @@ status = "okay"; key_valid = <0>; + extern_0{ + index = <0>; + extern_name = "ext_default"; + status = "disabled"; + type = <0>; /* 0=i2c, 1=spi, 2=mipi */ + i2c_address = <0x37>; /* 7bit i2c address */ + /* 7bit i2c address, 0xff for none */ + i2c_second_address = <0xff>; + i2c_bus = "i2c_bus_c"; + cmd_size = <4>; + /* init on/off: (type, value..., delay), + * must match cmd_size for every group + * type: 0x00=cmd(bit[3:0]=1 for second_addr), + * 0x10=gpio, 0xff=ending + * value: i2c or spi cmd, or gpio index & level, + * fill 0x0 for no use + * delay: unit ms + */ + init_on = <0x00 0x00 0x00 0x00 + 0x00 0x08 0x01 0x00 + 0x00 0x10 0x3F 0x00 + 0x00 0x11 0x00 0x00 + 0x00 0x12 0x00 0x00 + 0x00 0x13 0xE4 0x00 + 0x00 0x14 0x02 0x00 + 0x00 0x15 0x02 0x00 + 0x00 0x16 0x24 0x00 + 0x00 0x17 0x00 0x00 + 0x00 0x18 0x21 0x00 + 0x00 0x20 0x3F 0x00 + 0x00 0x21 0xFF 0x00 + 0x00 0x22 0x00 0x00 + 0x00 0x23 0x00 0x00 + 0x00 0x24 0x00 0x00 + 0x00 0x25 0x00 0x00 + 0x00 0x26 0xE4 0x00 + 0x00 0x27 0x00 0x00 + 0x00 0x28 0x28 0x00 + 0x00 0x29 0x01 0x00 + 0x00 0x2A 0x00 0x00 + 0x00 0x2B 0x01 0x00 + 0x00 0x2C 0x0E 0x00 + 0x00 0x2D 0x00 0x00 + 0x00 0x2E 0x18 0x00 + 0x00 0x2F 0x02 0x00 + 0x00 0x30 0x02 0x00 + 0x00 0x31 0x00 0x00 + 0x00 0x32 0x63 0x00 + 0x00 0x40 0x00 0x00 + 0x00 0x41 0x00 0x00 + 0x00 0x42 0x00 0x00 + 0x00 0x12 0x00 0x00 + 0x00 0x13 0xE4 0x00 + 0x00 0x14 0x02 0x00 + 0x00 0x15 0x00 0x00 + 0x00 0x16 0x0D 0x00 + 0x00 0x17 0x00 0x00 + 0x00 0x18 0x21 0x00 + 0x00 0x41 0x06 0x00 + 0x00 0x00 0x01 0x00 + 0x00 0x08 0x00 0x00 + 0x00 0x10 0x00 0x00 + 0x00 0x11 0x0F 0x00 + 0xff 0x00 0x00 0x00>; + init_off = <0x00 0x00 0x01 0x00 + 0x00 0x08 0x00 0x00 + 0x00 0x10 0x00 0x00 + 0x00 0x11 0x0F 0x00 + 0xff 0x00 0x00 0x00>; + }; + extern_1{ index = <1>; extern_name = "mipi_KD080D13"; diff --git a/drivers/amlogic/media/vout/lcd/lcd_clk_config.c b/drivers/amlogic/media/vout/lcd/lcd_clk_config.c index a8f8282..a69e6f0e 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_clk_config.c +++ b/drivers/amlogic/media/vout/lcd/lcd_clk_config.c @@ -1646,7 +1646,7 @@ static void lcd_set_pll_axg(struct lcd_clk_config_s *cConf) lcd_hiu_write(HHI_GP0_PLL_CNTL2, pll_ctrl2); lcd_hiu_write(HHI_GP0_PLL_CNTL3, 0x0a59a288); lcd_hiu_write(HHI_GP0_PLL_CNTL4, 0xc000004d); - lcd_hiu_write(HHI_GP0_PLL_CNTL5, 0x00058000); + lcd_hiu_write(HHI_GP0_PLL_CNTL5, 0x00078000); lcd_hiu_setb(HHI_GP0_PLL_CNTL, 1, LCD_PLL_RST_AXG, 1); lcd_hiu_setb(HHI_GP0_PLL_CNTL, 0, LCD_PLL_RST_AXG, 1); diff --git a/drivers/amlogic/media/vout/lcd/lcd_clk_config.h b/drivers/amlogic/media/vout/lcd/lcd_clk_config.h index 1db5e45..911a843 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_clk_config.h +++ b/drivers/amlogic/media/vout/lcd/lcd_clk_config.h @@ -297,11 +297,11 @@ enum div_sel_e { #define PLL_OD_SEL_MAX_AXG 3 #define PLL_FREF_MIN_AXG (5 * 1000) #define PLL_FREF_MAX_AXG (25 * 1000) -#define PLL_VCO_MIN_AXG (1500 * 1000) -#define PLL_VCO_MAX_AXG (3000 * 1000) +#define PLL_VCO_MIN_AXG (960 * 1000) +#define PLL_VCO_MAX_AXG (1632 * 1000) /* video */ -#define CRT_VID_CLK_IN_MAX_AXG (3000 * 1000) +#define CRT_VID_CLK_IN_MAX_AXG (1632 * 1000) #define ENCL_CLK_IN_MAX_AXG (200 * 1000) diff --git a/drivers/amlogic/media/vout/lcd/lcd_extern/ext_default.c b/drivers/amlogic/media/vout/lcd/lcd_extern/ext_default.c index 7c74074..5ef6b507 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_extern/ext_default.c +++ b/drivers/amlogic/media/vout/lcd/lcd_extern/ext_default.c @@ -84,6 +84,75 @@ static int lcd_extern_i2c_write(struct i2c_client *i2client, return ret; } +static void set_lcd_csb(unsigned int v) +{ + lcd_extern_gpio_set(ext_config->spi_gpio_cs, v); + udelay(ext_config->spi_delay_us); +} + +static void set_lcd_scl(unsigned int v) +{ + lcd_extern_gpio_set(ext_config->spi_gpio_clk, v); + udelay(ext_config->spi_delay_us); +} + +static void set_lcd_sda(unsigned int v) +{ + lcd_extern_gpio_set(ext_config->spi_gpio_data, v); + udelay(ext_config->spi_delay_us); +} + +static void spi_gpio_init(void) +{ + set_lcd_csb(1); + set_lcd_scl(1); + set_lcd_sda(1); +} + +static void spi_gpio_off(void) +{ + set_lcd_sda(0); + set_lcd_scl(0); + set_lcd_csb(0); +} + +static void spi_write_byte(unsigned char data) +{ + int i; + + for (i = 0; i < 8; i++) { + set_lcd_scl(0); + if (data & 0x80) + set_lcd_sda(1); + else + set_lcd_sda(0); + data <<= 1; + set_lcd_scl(1); + } +} + +static int lcd_extern_spi_write(unsigned char *buf, int len) +{ + int i; + + if (len < 2) { + EXTERR("%s: len %d error\n", __func__, len); + return -1; + } + + set_lcd_csb(0); + + for (i = 0; i < len; i++) + spi_write_byte(buf[i]); + + set_lcd_csb(1); + set_lcd_scl(1); + set_lcd_sda(1); + udelay(ext_config->spi_delay_us); + + return 0; +} + static int lcd_extern_reg_read(unsigned char reg, unsigned char *buf) { int ret = 0; @@ -98,188 +167,244 @@ static int lcd_extern_reg_write(unsigned char reg, unsigned char value) return ret; } -static int lcd_extern_spi_write(unsigned char *buf, int len) +static int lcd_extern_power_cmd_dynamic_size(unsigned char *init_table, + int flag) { - EXTPR("to do\n"); - return 0; + int i = 0, step = 0, max_len = 0; + unsigned char type, cmd_size; + int ret = 0; + + if (flag) + max_len = LCD_EXTERN_INIT_ON_MAX; + else + max_len = LCD_EXTERN_INIT_OFF_MAX; + + switch (ext_config->type) { + case LCD_EXTERN_I2C: + while (i <= max_len) { + type = init_table[i]; + if (type == LCD_EXTERN_INIT_END) + break; + if (lcd_debug_print_flag) { + EXTPR("%s: step %d: type=0x%02x, cmd_size=%d\n", + __func__, step, + init_table[i], init_table[i+1]); + } + cmd_size = init_table[i+1]; + if (type == LCD_EXTERN_INIT_NONE) { + if (cmd_size < 1) { + EXTERR("step %d: invalid cmd_size %d\n", + step, cmd_size); + i += (cmd_size + 2); + step++; + continue; + } + /* do nothing, only for delay */ + if (init_table[i+2] > 0) + mdelay(init_table[i+2]); + } else if (type == LCD_EXTERN_INIT_GPIO) { + if (cmd_size < 3) { + EXTERR("step %d: invalid cmd_size %d\n", + step, cmd_size); + i += (cmd_size + 2); + step++; + continue; + } + if (init_table[i+2] < LCD_GPIO_MAX) { + lcd_extern_gpio_set(init_table[i+2], + init_table[i+3]); + } + if (init_table[i+4] > 0) + mdelay(init_table[i+3]); + } else if (type == LCD_EXTERN_INIT_CMD) { + ret = lcd_extern_i2c_write( + aml_default_i2c_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) { + ret = lcd_extern_i2c_write( + aml_default_i2c2_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, + ext_config->name, ext_config->type); + } + i += (cmd_size + 2); + step++; + } + break; + case LCD_EXTERN_SPI: + while (i <= max_len) { + type = init_table[i]; + if (type == LCD_EXTERN_INIT_END) + break; + if (lcd_debug_print_flag) { + EXTPR("%s: step %d: type=0x%02x, cmd_size=%d\n", + __func__, step, + init_table[i], init_table[i+1]); + } + cmd_size = init_table[i+1]; + if (type == LCD_EXTERN_INIT_NONE) { + if (cmd_size < 1) { + EXTERR("step %d: invalid cmd_size %d\n", + step, cmd_size); + i += (cmd_size + 2); + step++; + continue; + } + /* do nothing, only for delay */ + if (init_table[i+2] > 0) + mdelay(init_table[i+2]); + } else if (type == LCD_EXTERN_INIT_GPIO) { + if (cmd_size < 3) { + EXTERR("step %d: invalid cmd_size %d\n", + step, cmd_size); + i += (cmd_size + 2); + step++; + continue; + } + if (init_table[i+2] < LCD_GPIO_MAX) { + lcd_extern_gpio_set(init_table[i+2], + init_table[i+3]); + } + if (init_table[i+4] > 0) + mdelay(init_table[i+4]); + } else if (type == LCD_EXTERN_INIT_CMD) { + ret = lcd_extern_spi_write( + &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, + ext_config->name, ext_config->type); + } + i += (cmd_size + 2); + step++; + } + break; + default: + EXTERR("%s(%d: %s): extern_type %d is not support\n", + __func__, ext_config->index, + ext_config->name, ext_config->type); + break; + } + + return ret; } -static int lcd_extern_power_cmd(unsigned char *init_table) +static int lcd_extern_power_cmd_fixed_size(unsigned char *init_table, int flag) { - int i = 0, len; + int i = 0, step = 0, max_len = 0; + unsigned char type, cmd_size; int ret = 0; - len = ext_config->cmd_size; - if (len < 1) { - EXTERR("%s: cmd_size %d is invalid\n", __func__, len); - return -1; - } - if (len == LCD_EXTERN_DYNAMIC_LEN) { - switch (ext_config->type) { - case LCD_EXTERN_I2C: - while (i <= LCD_EXTERN_INIT_TABLE_MAX) { - if (init_table[i] == LCD_EXTERN_INIT_END) { - break; - } else if (init_table[i] == - LCD_EXTERN_INIT_NONE) { - /* do nothing, only for delay */ - if (init_table[i+1] > 0) - mdelay(init_table[i+1]); - i += 2; - } else if (init_table[i] == - LCD_EXTERN_INIT_GPIO) { - if (init_table[i+1] < LCD_GPIO_MAX) { - lcd_extern_gpio_set( - init_table[i+1], - init_table[i+2]); - } - if (init_table[i+3] > 0) - mdelay(init_table[i+3]); - i += 4; - } else if (init_table[i] == - LCD_EXTERN_INIT_CMD) { - ret = lcd_extern_i2c_write( - aml_default_i2c_client, - &init_table[i+2], - init_table[i+1]-1); - if (init_table[i+init_table[i+1]+1] > 0) - mdelay(init_table[i+ - init_table[i+1]+1]); - i += (init_table[i+1] + 2); - } else if (init_table[i] == - LCD_EXTERN_INIT_CMD2) { - ret = lcd_extern_i2c_write( - aml_default_i2c2_client, - &init_table[i+2], - init_table[i+1]-1); - if (init_table[i+init_table[i+1]+1] > 0) - mdelay(init_table[i+ - init_table[i+1]+1]); - i += (init_table[i+1] + 2); - } else { - EXTERR("%s(%d: %s): type %d invalid\n", - __func__, ext_config->index, - ext_config->name, - ext_config->type); - } + if (flag) + max_len = LCD_EXTERN_INIT_ON_MAX; + else + max_len = LCD_EXTERN_INIT_OFF_MAX; + + cmd_size = ext_config->cmd_size; + switch (ext_config->type) { + case LCD_EXTERN_I2C: + while (i <= max_len) { + type = init_table[i]; + if (type == LCD_EXTERN_INIT_END) + break; + if (lcd_debug_print_flag) { + EXTPR("%s: step %d: type=0x%02x, cmd_size=%d\n", + __func__, step, type, cmd_size); } - break; - case LCD_EXTERN_SPI: - while (i <= LCD_EXTERN_INIT_TABLE_MAX) { - if (init_table[i] == LCD_EXTERN_INIT_END) { - break; - } else if (init_table[i] == - LCD_EXTERN_INIT_NONE) { - /* do nothing, only for delay */ - if (init_table[i+1] > 0) - mdelay(init_table[i+1]); - i += 2; - } else if (init_table[i] == - LCD_EXTERN_INIT_GPIO) { - if (init_table[i+1] < LCD_GPIO_MAX) { - lcd_extern_gpio_set( - init_table[i+1], - init_table[i+2]); - } - if (init_table[i+3] > 0) - mdelay(init_table[i+3]); - i += 4; - } else if (init_table[i] == - LCD_EXTERN_INIT_CMD) { - ret = lcd_extern_spi_write( - &init_table[i+2], - init_table[i+1]-1); - if (init_table[i+init_table[i+1]+1] > 0) - mdelay(init_table[i+ - init_table[i+1]+1]); - i += (init_table[i+1] + 2); - } else { - EXTERR("%s(%d: %s): type %d invalid\n", - __func__, ext_config->index, - ext_config->name, - ext_config->type); + if (type == LCD_EXTERN_INIT_NONE) { + /* do nothing, only for delay */ + } else if (type == LCD_EXTERN_INIT_GPIO) { + if (init_table[i+1] < LCD_GPIO_MAX) { + lcd_extern_gpio_set(init_table[i+1], + init_table[i+2]); } + } else if (type == LCD_EXTERN_INIT_CMD) { + ret = lcd_extern_i2c_write( + aml_default_i2c_client, + &init_table[i+1], (cmd_size-2)); + } else if (type == LCD_EXTERN_INIT_CMD2) { + ret = lcd_extern_i2c_write( + aml_default_i2c2_client, + &init_table[i+1], (cmd_size-2)); + } else { + EXTERR("%s(%d: %s): type %d invalid\n", + __func__, ext_config->index, + ext_config->name, ext_config->type); } - break; - default: - EXTERR("%s(%d: %s): extern_type %d is not support\n", - __func__, ext_config->index, - ext_config->name, ext_config->type); - break; + if (init_table[i+cmd_size-1] > 0) + mdelay(init_table[i+cmd_size-1]); + i += cmd_size; + step++; } - } else { - switch (ext_config->type) { - case LCD_EXTERN_I2C: - while (i <= LCD_EXTERN_INIT_TABLE_MAX) { - if (init_table[i] == LCD_EXTERN_INIT_END) { - break; - } else if (init_table[i] == - LCD_EXTERN_INIT_NONE) { - /* do nothing, only for delay */ - } else if (init_table[i] == - LCD_EXTERN_INIT_GPIO) { - if (init_table[i+1] < LCD_GPIO_MAX) { - lcd_extern_gpio_set( - init_table[i+1], - init_table[i+2]); - } - } else if (init_table[i] == - LCD_EXTERN_INIT_CMD) { - ret = lcd_extern_i2c_write( - aml_default_i2c_client, - &init_table[i+1], (len-2)); - } else if (init_table[i] == - LCD_EXTERN_INIT_CMD2) { - ret = lcd_extern_i2c_write( - aml_default_i2c2_client, - &init_table[i+1], (len-2)); - } else { - EXTERR("%s(%d: %s): type %d invalid\n", - __func__, ext_config->index, - ext_config->name, - ext_config->type); - } - if (init_table[i+len-1] > 0) - mdelay(init_table[i+len-1]); - i += len; + break; + case LCD_EXTERN_SPI: + while (i <= max_len) { + type = init_table[i]; + if (type == LCD_EXTERN_INIT_END) + break; + if (lcd_debug_print_flag) { + EXTPR("%s: step %d: type=0x%02x, cmd_size=%d\n", + __func__, step, type, cmd_size); } - break; - case LCD_EXTERN_SPI: - while (i <= LCD_EXTERN_INIT_TABLE_MAX) { - if (init_table[i] == LCD_EXTERN_INIT_END) { - break; - } else if (init_table[i] == - LCD_EXTERN_INIT_NONE) { - /* do nothing, only for delay */ - } else if (init_table[i] == - LCD_EXTERN_INIT_GPIO) { - if (init_table[i+1] < LCD_GPIO_MAX) { - lcd_extern_gpio_set( - init_table[i+1], - init_table[i+2]); - } - } else if (init_table[i] == - LCD_EXTERN_INIT_CMD) { - ret = lcd_extern_spi_write( - &init_table[i+1], (len-1)); - } else { - EXTERR("%s(%d: %s): type %d invalid\n", - __func__, ext_config->index, - ext_config->name, - ext_config->type); + if (type == LCD_EXTERN_INIT_NONE) { + /* do nothing, only for delay */ + } else if (type == LCD_EXTERN_INIT_GPIO) { + if (init_table[i+1] < LCD_GPIO_MAX) { + lcd_extern_gpio_set(init_table[i+1], + init_table[i+2]); } - if (init_table[i+len-1] > 0) - mdelay(init_table[i+len-1]); - i += len; + } else if (type == LCD_EXTERN_INIT_CMD) { + ret = lcd_extern_spi_write(&init_table[i+1], + (cmd_size-2)); + } else { + EXTERR("%s(%d: %s): type %d invalid\n", + __func__, ext_config->index, + ext_config->name, ext_config->type); } - break; - default: - EXTERR("%s(%d: %s): extern_type %d is not support\n", - __func__, ext_config->index, - ext_config->name, ext_config->type); - break; - } + if (init_table[i+cmd_size-1] > 0) + mdelay(init_table[i+cmd_size-1]); + i += cmd_size; + step++; } + break; + default: + EXTERR("%s(%d: %s): extern_type %d is not support\n", + __func__, ext_config->index, + ext_config->name, ext_config->type); + break; + } + + return ret; +} + +static int lcd_extern_power_cmd(unsigned char *init_table, int flag) +{ + unsigned char cmd_size; + int ret = 0; + + cmd_size = ext_config->cmd_size; + if (cmd_size < 1) { + EXTERR("%s: cmd_size %d is invalid\n", __func__, cmd_size); + return -1; + } + if (init_table == NULL) { + EXTERR("%s: init_table %d is NULL\n", __func__, flag); + return -1; + } + + if (cmd_size == LCD_EXTERN_CMD_SIZE_DYNAMIC) + ret = lcd_extern_power_cmd_dynamic_size(init_table, flag); + else + ret = lcd_extern_power_cmd_fixed_size(init_table, flag); + return ret; } @@ -287,10 +412,16 @@ static int lcd_extern_power_ctrl(int flag) { int ret = 0; + if (ext_config->type == LCD_EXTERN_SPI) + spi_gpio_init(); + if (flag) - ret = lcd_extern_power_cmd(ext_config->table_init_on); + ret = lcd_extern_power_cmd(ext_config->table_init_on, 1); else - ret = lcd_extern_power_cmd(ext_config->table_init_off); + ret = lcd_extern_power_cmd(ext_config->table_init_off, 0); + + if (ext_config->type == LCD_EXTERN_SPI) + spi_gpio_off(); EXTPR("%s(%d: %s): %d\n", __func__, ext_config->index, ext_config->name, flag); @@ -346,6 +477,11 @@ static int lcd_extern_driver_update(struct aml_lcd_extern_driver_s *ext_drv) 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; + } + ext_drv->reg_read = lcd_extern_reg_read; ext_drv->reg_write = lcd_extern_reg_write; ext_drv->power_on = lcd_extern_power_on; diff --git a/drivers/amlogic/media/vout/lcd/lcd_extern/i2c_T5800Q.c b/drivers/amlogic/media/vout/lcd/lcd_extern/i2c_T5800Q.c index 66d337b..b8f6648 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_extern/i2c_T5800Q.c +++ b/drivers/amlogic/media/vout/lcd/lcd_extern/i2c_T5800Q.c @@ -111,21 +111,39 @@ static int lcd_extern_reg_write(unsigned char reg, unsigned char value) return ret; } -static int lcd_extern_power_cmd(unsigned char *init_table) +static int lcd_extern_power_cmd(unsigned char *init_table, int flag) { - int i = 0, len; + int i = 0, max_len = 0, step = 0; + unsigned char cmd_size; int ret = 0; - len = ext_config->cmd_size; - if (len < 1) { - EXTERR("%s: cmd_size %d is invalid\n", __func__, len); + cmd_size = ext_config->cmd_size; + if (cmd_size < 1) { + EXTERR("%s: cmd_size %d is invalid\n", __func__, cmd_size); + return -1; + } + if (cmd_size == LCD_EXTERN_CMD_SIZE_DYNAMIC) { + EXTPR("%s: cmd_size dynamic length is not support\n", __func__); + return -1; + } + if (init_table == NULL) { + EXTERR("%s: init_table %d is NULL\n", __func__, flag); return -1; } - while (i <= LCD_EXTERN_INIT_TABLE_MAX) { - if (init_table[i] == LCD_EXTERN_INIT_END) { + if (flag) + max_len = LCD_EXTERN_INIT_ON_MAX; + else + max_len = LCD_EXTERN_INIT_OFF_MAX; + + while (i <= max_len) { + if (init_table[i] == LCD_EXTERN_INIT_END) break; - } else if (init_table[i] == LCD_EXTERN_INIT_NONE) { + if (lcd_debug_print_flag) { + EXTPR("%s: step %d: type=0x%02x, cmd_size=%d\n", + __func__, step, init_table[i], cmd_size); + } + if (init_table[i] == LCD_EXTERN_INIT_NONE) { /* do nothing, only for delay */ } else if (init_table[i] == LCD_EXTERN_INIT_GPIO) { if (init_table[i+1] < LCD_GPIO_MAX) { @@ -134,15 +152,16 @@ static int lcd_extern_power_cmd(unsigned char *init_table) } } else if (init_table[i] == LCD_EXTERN_INIT_CMD) { ret = lcd_extern_i2c_write(aml_T5800Q_i2c_client, - &init_table[i+1], (len-2)); + &init_table[i+1], (cmd_size-2)); } else { EXTERR("%s(%d: %s): power_type %d is invalid\n", __func__, ext_config->index, ext_config->name, ext_config->type); } - if (init_table[i+len-1] > 0) - mdelay(init_table[i+len-1]); - i += len; + if (init_table[i+cmd_size-1] > 0) + mdelay(init_table[i+cmd_size-1]); + step++; + i += cmd_size; } return ret; @@ -153,9 +172,9 @@ static int lcd_extern_power_ctrl(int flag) int ret = 0; if (flag) - ret = lcd_extern_power_cmd(ext_config->table_init_on); + ret = lcd_extern_power_cmd(ext_config->table_init_on, 1); else - ret = lcd_extern_power_cmd(ext_config->table_init_off); + ret = lcd_extern_power_cmd(ext_config->table_init_off, 0); EXTPR("%s(%d: %s): %d\n", __func__, ext_config->index, ext_config->name, flag); diff --git a/drivers/amlogic/media/vout/lcd/lcd_extern/lcd_extern.c b/drivers/amlogic/media/vout/lcd/lcd_extern/lcd_extern.c index 6615564..2490664 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_extern/lcd_extern.c +++ b/drivers/amlogic/media/vout/lcd/lcd_extern/lcd_extern.c @@ -37,14 +37,6 @@ 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_extern_init_on_table[LCD_EXTERN_INIT_TABLE_MAX] = { - 0xff, -}; - -static unsigned char lcd_extern_init_off_table[LCD_EXTERN_INIT_TABLE_MAX] = { - 0xff, -}; - struct lcd_ext_gpio_s { char name[15]; struct gpio_desc *gpio; @@ -237,20 +229,137 @@ struct device_node *aml_lcd_extern_get_dts_child(int index) return child; } +static int lcd_extern_init_table_dynamic_size_load_dts( + struct device_node *of_node, + struct lcd_extern_config_s *extconf, int flag) +{ + unsigned char cmd_size, index, type; + int i, j, val, max_len, step = 0, ret = 0; + unsigned char *init_table; + char propname[20]; + + if (flag) { + init_table = extconf->table_init_on; + max_len = LCD_EXTERN_INIT_ON_MAX; + sprintf(propname, "init_on"); + } else { + init_table = extconf->table_init_off; + max_len = LCD_EXTERN_INIT_OFF_MAX; + sprintf(propname, "init_off"); + } + + i = 0; + while (i < max_len) { + /* step1: type */ + ret = of_property_read_u32_index(of_node, propname, i, &val); + if (ret) { + EXTERR("get %s %s type failed, step %d\n", + extconf->name, propname, step); + init_table[i] = LCD_EXTERN_INIT_END; + return -1; + } + init_table[i] = (unsigned char)val; + type = init_table[i]; + if (type == LCD_EXTERN_INIT_END) + break; + /* step2: cmd_size */ + ret = of_property_read_u32_index( + of_node, propname, (i+1), &val); + if (ret) { + EXTERR("get %s %s cmd_size failed, step %d\n", + extconf->name, propname, step); + init_table[i] = LCD_EXTERN_INIT_END; + return -1; + } + init_table[i+1] = (unsigned char)val; + cmd_size = init_table[i+1]; + if (cmd_size == 0) { + i += 2; + continue; + } + /* step3: data */ + for (j = 0; j < cmd_size; j++) { + ret = of_property_read_u32_index( + of_node, propname, (i+2+j), &val); + if (ret) { + EXTERR("get %s %s data failed, step %d\n", + extconf->name, propname, step); + init_table[i] = LCD_EXTERN_INIT_END; + return -1; + } + init_table[i+2+j] = (unsigned char)val; + } + if (type == LCD_EXTERN_INIT_GPIO) { + /* gpio request */ + index = init_table[i+2]; + if (index < LCD_EXTERN_GPIO_NUM_MAX) + lcd_extern_gpio_register(index); + } + step++; + i += (cmd_size + 2); + } + + return 0; +} + +static int lcd_extern_init_table_fixed_size_load_dts( + struct device_node *of_node, + struct lcd_extern_config_s *extconf, int flag) +{ + unsigned char cmd_size, index; + int i, j, val, max_len, step = 0, ret = 0; + unsigned char *init_table; + char propname[20]; + + cmd_size = extconf->cmd_size; + if (flag) { + init_table = extconf->table_init_on; + max_len = LCD_EXTERN_INIT_ON_MAX; + sprintf(propname, "init_on"); + } else { + init_table = extconf->table_init_off; + max_len = LCD_EXTERN_INIT_OFF_MAX; + sprintf(propname, "init_off"); + } + + i = 0; + while (i < max_len) { + for (j = 0; j < cmd_size; j++) { + ret = of_property_read_u32_index( + of_node, propname, (i+j), &val); + if (ret) { + EXTERR("get %s %s failed, step %d\n", + extconf->name, propname, step); + init_table[i] = LCD_EXTERN_INIT_END; + return -1; + } + init_table[i+j] = (unsigned char)val; + } + if (init_table[i] == LCD_EXTERN_INIT_END) { + break; + } else if (init_table[i] == LCD_EXTERN_INIT_GPIO) { + /* gpio request */ + index = init_table[i+1]; + if (index < LCD_EXTERN_GPIO_NUM_MAX) + lcd_extern_gpio_register(index); + } + step++; + i += cmd_size; + } + + return 0; +} + static int lcd_extern_get_config_dts(struct device_node *of_node, struct lcd_extern_config_s *extconf) { int ret; int val; const char *str; - unsigned char cmd_size, index; - int i, j; extconf->index = LCD_EXTERN_INDEX_INVALID; extconf->type = LCD_EXTERN_MAX; extconf->table_init_loaded = 0; - extconf->table_init_on = lcd_extern_init_on_table; - extconf->table_init_off = lcd_extern_init_off_table; ret = of_property_read_u32(of_node, "index", &val); if (ret) @@ -305,7 +414,7 @@ static int lcd_extern_get_config_dts(struct device_node *of_node, extconf->name); extconf->i2c_addr2 = 0xff; } else { - extconf->i2c_addr = (unsigned char)val; + extconf->i2c_addr2 = (unsigned char)val; } if (lcd_debug_print_flag) { EXTPR("%s i2c_second_address=0x%02x\n", @@ -335,66 +444,28 @@ static int lcd_extern_get_config_dts(struct device_node *of_node, EXTPR("%s cmd_size=%d\n", extconf->name, extconf->cmd_size); } - cmd_size = extconf->cmd_size; - if (cmd_size > 1) { - i = 0; - while (i < LCD_EXTERN_INIT_TABLE_MAX) { - for (j = 0; j < cmd_size; j++) { - ret = of_property_read_u32_index( - of_node, "init_on", - (i + j), &val); - if (ret) { - EXTERR("get init_on failed\n"); - extconf->table_init_on[i] = - LCD_EXTERN_INIT_END; - goto i2c_get_init_on_dts; - } - extconf->table_init_on[i + j] = - (unsigned char)val; - } - if (extconf->table_init_on[i] == - LCD_EXTERN_INIT_END) { - break; - } else if (extconf->table_init_on[i] == - LCD_EXTERN_INIT_GPIO) { - /* gpio request */ - index = extconf->table_init_on[i+1]; - if (index < LCD_EXTERN_GPIO_NUM_MAX) - lcd_extern_gpio_register(index); - } - i += cmd_size; - } - extconf->table_init_loaded = 1; -i2c_get_init_on_dts: - i = 0; - while (i < LCD_EXTERN_INIT_TABLE_MAX) { - for (j = 0; j < cmd_size; j++) { - ret = of_property_read_u32_index( - of_node, "init_off", - (i + j), &val); - if (ret) { - EXTERR("get init_off failed\n"); - extconf->table_init_off[i] = - LCD_EXTERN_INIT_END; - goto i2c_get_init_off_dts; - } - extconf->table_init_off[i + j] = - (unsigned char)val; - } - if (extconf->table_init_off[i] == - LCD_EXTERN_INIT_END) { - break; - } else if (extconf->table_init_off[i] == - LCD_EXTERN_INIT_GPIO) { - /* gpio request */ - index = extconf->table_init_off[i+1]; - if (index < LCD_EXTERN_GPIO_NUM_MAX) - lcd_extern_gpio_register(index); - } - i += cmd_size; - } + if (extconf->cmd_size <= 1) { + EXTERR("cmd_size %d is invalid\n", extconf->cmd_size); + break; } -i2c_get_init_off_dts: + + if (extconf->cmd_size == LCD_EXTERN_CMD_SIZE_DYNAMIC) { + ret = lcd_extern_init_table_dynamic_size_load_dts( + of_node, extconf, 1); + if (ret) + break; + ret = lcd_extern_init_table_dynamic_size_load_dts( + of_node, extconf, 0); + } else { + ret = lcd_extern_init_table_fixed_size_load_dts( + of_node, extconf, 1); + if (ret) + break; + ret = lcd_extern_init_table_fixed_size_load_dts( + of_node, extconf, 0); + } + if (ret == 0) + extconf->table_init_loaded = 1; break; case LCD_EXTERN_SPI: ret = of_property_read_u32(of_node, "gpio_spi_cs", &val); @@ -471,66 +542,28 @@ i2c_get_init_off_dts: EXTPR("%s cmd_size=%d\n", extconf->name, extconf->cmd_size); } - cmd_size = extconf->cmd_size; - if (cmd_size > 1) { - i = 0; - while (i < LCD_EXTERN_INIT_TABLE_MAX) { - for (j = 0; j < cmd_size; j++) { - ret = of_property_read_u32_index( - of_node, "init_on", - (i + j), &val); - if (ret) { - EXTERR("get init_on failed\n"); - extconf->table_init_on[i] = - LCD_EXTERN_INIT_END; - goto spi_get_init_on_dts; - } - extconf->table_init_on[i + j] = - (unsigned char)val; - } - if (extconf->table_init_on[i] == - LCD_EXTERN_INIT_END) { - break; - } else if (extconf->table_init_on[i] == - LCD_EXTERN_INIT_GPIO) { - /* gpio request */ - index = extconf->table_init_on[i+1]; - if (index < LCD_EXTERN_GPIO_NUM_MAX) - lcd_extern_gpio_register(index); - } - i += cmd_size; - } - extconf->table_init_loaded = 1; -spi_get_init_on_dts: - i = 0; - while (i < LCD_EXTERN_INIT_TABLE_MAX) { - for (j = 0; j < cmd_size; j++) { - ret = of_property_read_u32_index( - of_node, "init_off", - (i + j), &val); - if (ret) { - EXTERR("get init_off failed\n"); - extconf->table_init_off[i] = - LCD_EXTERN_INIT_END; - goto spi_get_init_off_dts; - } - extconf->table_init_off[i + j] = - (unsigned char)val; - } - if (extconf->table_init_off[i] == - LCD_EXTERN_INIT_END) { - break; - } else if (extconf->table_init_off[i] == - LCD_EXTERN_INIT_GPIO) { - /* gpio request */ - index = extconf->table_init_off[i+1]; - if (index < LCD_EXTERN_GPIO_NUM_MAX) - lcd_extern_gpio_register(index); - } - i += cmd_size; - } + if (extconf->cmd_size <= 1) { + EXTERR("cmd_size %d is invalid\n", extconf->cmd_size); + break; } -spi_get_init_off_dts: + + if (extconf->cmd_size == LCD_EXTERN_CMD_SIZE_DYNAMIC) { + ret = lcd_extern_init_table_dynamic_size_load_dts( + of_node, extconf, 1); + if (ret) + break; + ret = lcd_extern_init_table_dynamic_size_load_dts( + of_node, extconf, 0); + } else { + ret = lcd_extern_init_table_fixed_size_load_dts( + of_node, extconf, 1); + if (ret) + break; + ret = lcd_extern_init_table_fixed_size_load_dts( + of_node, extconf, 0); + } + if (ret == 0) + extconf->table_init_loaded = 1; break; case LCD_EXTERN_MIPI: break; @@ -565,22 +598,150 @@ static unsigned char lcd_extern_get_i2c_bus_unifykey(unsigned char val) return i2c_bus; } -static int lcd_extern_get_config_unifykey(struct lcd_extern_config_s *extconf) +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) { - unsigned char *para; - int i, j, key_len, len; unsigned char cmd_size; - unsigned char *p; + unsigned char index; + int i, j, max_len, step = 0, ret = 0; + unsigned char *init_table; + char propname[20]; + + if (flag) { + init_table = extconf->table_init_on; + max_len = LCD_EXTERN_INIT_ON_MAX; + sprintf(propname, "init_on"); + } else { + init_table = extconf->table_init_off; + max_len = LCD_EXTERN_INIT_OFF_MAX; + sprintf(propname, "init_off"); + } + + i = 0; + while (i < max_len) { + /* step1: type */ + len += 1; + ret = lcd_unifykey_len_check(key_len, len); + if (ret) { + EXTERR("get %s %s type failed, step %d\n", + extconf->name, propname, step); + init_table[i] = LCD_EXTERN_INIT_END; + return -1; + } + init_table[i] = *p; + p++; + if (init_table[i] == LCD_EXTERN_INIT_END) + break; + + /* step2: cmd_size */ + len += 1; + ret = lcd_unifykey_len_check(key_len, len); + if (ret) { + EXTERR("get %s %s cmd_size failed, step %d\n", + extconf->name, propname, step); + init_table[i] = LCD_EXTERN_INIT_END; + return -1; + } + init_table[i+1] = *p; + cmd_size = init_table[i+1]; + p++; + if (cmd_size == 0) { + i += 2; + continue; + } + + /* step3: data */ + len += cmd_size; + ret = lcd_unifykey_len_check(key_len, len); + if (ret) { + EXTERR("get %s %s data failed, step %d\n", + extconf->name, propname, step); + init_table[i] = LCD_EXTERN_INIT_END; + for (j = 0; j < cmd_size; j++) + init_table[i+2+j] = 0x0; + return -1; + } + for (j = 0; j < cmd_size; j++) { + init_table[i+2+j] = *p; + p++; + } + if (init_table[i] == LCD_EXTERN_INIT_END) { + break; + } else if (init_table[i] == LCD_EXTERN_INIT_GPIO) { + /* gpio request */ + index = init_table[i+1]; + if (index < LCD_EXTERN_GPIO_NUM_MAX) + lcd_extern_gpio_register(index); + } + step++; + i += (cmd_size + 2); + } + + return 0; +} + +static int lcd_extern_init_table_fixed_size_load_unifykey( + struct lcd_extern_config_s *extconf, unsigned char *p, + int key_len, int len, int flag) +{ + unsigned char cmd_size; + unsigned char index; + int i, j, max_len, step = 0, ret = 0; + unsigned char *init_table; + char propname[20]; + + cmd_size = extconf->cmd_size; + if (flag) { + init_table = extconf->table_init_on; + max_len = LCD_EXTERN_INIT_ON_MAX; + sprintf(propname, "init_on"); + } else { + init_table = extconf->table_init_off; + max_len = LCD_EXTERN_INIT_OFF_MAX; + sprintf(propname, "init_off"); + } + + i = 0; + while (i < max_len) { + len += cmd_size; + ret = lcd_unifykey_len_check(key_len, len); + if (ret) { + EXTERR("get %s %s failed, step %d\n", + extconf->name, propname, step); + init_table[i] = LCD_EXTERN_INIT_END; + return -1; + } + for (j = 0; j < cmd_size; j++) { + init_table[i+j] = *p; + p++; + } + if (init_table[i] == LCD_EXTERN_INIT_END) { + break; + } else if (init_table[i] == LCD_EXTERN_INIT_GPIO) { + /* gpio request */ + index = init_table[i+1]; + if (index < LCD_EXTERN_GPIO_NUM_MAX) + lcd_extern_gpio_register(index); + } + step++; + i += cmd_size; + } + + return 0; +} + +static int lcd_extern_get_config_unifykey(struct lcd_extern_config_s *extconf) +{ + unsigned char *para, *p; + int key_len, len; const char *str; struct aml_lcd_unifykey_header_s ext_header; - unsigned char index; int ret; extconf->index = LCD_EXTERN_INDEX_INVALID; extconf->type = LCD_EXTERN_MAX; extconf->table_init_loaded = 0; - extconf->table_init_on = lcd_extern_init_on_table; - extconf->table_init_off = lcd_extern_init_off_table; para = kmalloc((sizeof(unsigned char) * LCD_UKEY_LCD_EXT_SIZE), GFP_KERNEL); @@ -647,72 +808,28 @@ static int lcd_extern_get_config_unifykey(struct lcd_extern_config_s *extconf) p += LCD_UKEY_EXT_TYPE_VAL_8; p += LCD_UKEY_EXT_TYPE_VAL_9; - /* power */ - cmd_size = extconf->cmd_size; - if (cmd_size >= 1) { - i = 0; - while (i < LCD_EXTERN_INIT_TABLE_MAX) { - len += cmd_size; - ret = lcd_unifykey_len_check(key_len, len); - if (ret) { - extconf->table_init_on[i] = - LCD_EXTERN_INIT_END; - for (j = 1; j < cmd_size; j++) { - extconf->table_init_on[i+j] = - 0x0; - } - kfree(para); - return -1; - } - for (j = 0; j < cmd_size; j++) { - extconf->table_init_on[i+j] = *p; - p++; - } - if (extconf->table_init_on[i] == - LCD_EXTERN_INIT_END) { - break; - } else if (extconf->table_init_on[i] == - LCD_EXTERN_INIT_GPIO) { - /* gpio request */ - index = extconf->table_init_on[i+1]; - if (index < LCD_EXTERN_GPIO_NUM_MAX) - lcd_extern_gpio_register(index); - } - i += cmd_size; - } - extconf->table_init_loaded = 1; - i = 0; - while (i < LCD_EXTERN_INIT_TABLE_MAX) { - len += cmd_size; - ret = lcd_unifykey_len_check(key_len, len); - if (ret) { - extconf->table_init_off[i] = - LCD_EXTERN_INIT_END; - for (j = 1; j < cmd_size; j++) { - extconf->table_init_off[i+j] = - 0x0; - } - kfree(para); - return -1; - } - for (j = 0; j < cmd_size; j++) { - extconf->table_init_off[i+j] = *p; - p++; - } - if (extconf->table_init_off[i] == - LCD_EXTERN_INIT_END) { - break; - } else if (extconf->table_init_off[i] == - LCD_EXTERN_INIT_GPIO) { - /* gpio request */ - index = extconf->table_init_off[i+1]; - if (index < LCD_EXTERN_GPIO_NUM_MAX) - lcd_extern_gpio_register(index); - } else { - i += cmd_size; - } - } + /* init */ + if (extconf->cmd_size <= 1) { + EXTERR("cmd_size %d is invalid\n", extconf->cmd_size); + break; } + if (extconf->cmd_size == LCD_EXTERN_CMD_SIZE_DYNAMIC) { + ret = lcd_extern_init_table_dynamic_size_load_unifykey( + extconf, p, key_len, len, 1); + if (ret) + break; + ret = lcd_extern_init_table_dynamic_size_load_unifykey( + extconf, p, key_len, len, 0); + } else { + ret = lcd_extern_init_table_fixed_size_load_unifykey( + extconf, p, key_len, len, 1); + if (ret) + break; + ret = lcd_extern_init_table_fixed_size_load_unifykey( + extconf, p, key_len, len, 0); + } + if (ret == 0) + extconf->table_init_loaded = 1; break; case LCD_EXTERN_SPI: extconf->spi_gpio_cs = *p; @@ -739,72 +856,27 @@ static int lcd_extern_get_config_unifykey(struct lcd_extern_config_s *extconf) p += LCD_UKEY_EXT_TYPE_VAL_9; /* init */ - cmd_size = extconf->cmd_size; - if (cmd_size >= 1) { - i = 0; - while (i < LCD_EXTERN_INIT_TABLE_MAX) { - len += cmd_size; - ret = lcd_unifykey_len_check(key_len, len); - if (ret) { - extconf->table_init_on[i] = - LCD_EXTERN_INIT_END; - for (j = 1; j < cmd_size; j++) { - extconf->table_init_on[i+j] = - 0x0; - } - kfree(para); - return -1; - } - for (j = 0; j < cmd_size; j++) { - extconf->table_init_on[i+j] = *p; - p++; - } - if (extconf->table_init_on[i] == - LCD_EXTERN_INIT_END) { - break; - } else if (extconf->table_init_on[i] == - LCD_EXTERN_INIT_GPIO) { - /* gpio request */ - index = extconf->table_init_on[i+1]; - if (index < LCD_EXTERN_GPIO_NUM_MAX) - lcd_extern_gpio_register(index); - } else { - i += cmd_size; - } - } - extconf->table_init_loaded = 1; - i = 0; - while (i < LCD_EXTERN_INIT_TABLE_MAX) { - len += cmd_size; - ret = lcd_unifykey_len_check(key_len, len); - if (ret) { - extconf->table_init_off[i] = - LCD_EXTERN_INIT_END; - for (j = 1; j < cmd_size; j++) { - extconf->table_init_off[i+j] = - 0x0; - } - kfree(para); - return -1; - } - for (j = 0; j < cmd_size; j++) { - extconf->table_init_off[i+j] = *p; - p++; - } - if (extconf->table_init_off[i] == - LCD_EXTERN_INIT_END) { - break; - } else if (extconf->table_init_off[i] == - LCD_EXTERN_INIT_GPIO) { - /* gpio request */ - index = extconf->table_init_off[i+1]; - if (index < LCD_EXTERN_GPIO_NUM_MAX) - lcd_extern_gpio_register(index); - } else { - i += cmd_size; - } - } + if (extconf->cmd_size <= 1) { + EXTERR("cmd_size %d is invalid\n", extconf->cmd_size); + break; + } + if (extconf->cmd_size == LCD_EXTERN_CMD_SIZE_DYNAMIC) { + ret = lcd_extern_init_table_dynamic_size_load_unifykey( + extconf, p, key_len, len, 1); + if (ret) + break; + ret = lcd_extern_init_table_dynamic_size_load_unifykey( + extconf, p, key_len, len, 0); + } else { + ret = lcd_extern_init_table_fixed_size_load_unifykey( + extconf, p, key_len, len, 1); + if (ret) + break; + ret = lcd_extern_init_table_fixed_size_load_unifykey( + extconf, p, key_len, len, 0); } + if (ret == 0) + extconf->table_init_loaded = 1; break; case LCD_EXTERN_MIPI: /* dummy pointer */ @@ -834,6 +906,8 @@ 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; int load_id = 0; int ret; @@ -841,6 +915,24 @@ static int lcd_extern_get_config(void) EXTERR("no lcd_extern of_node exist\n"); return -1; } + + lcd_ext_init_on_table = + kmalloc(sizeof(unsigned char) * LCD_EXTERN_INIT_ON_MAX, + GFP_KERNEL); + if (lcd_ext_init_on_table == 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, + GFP_KERNEL); + if (lcd_ext_init_off_table == NULL) { + EXTERR("failed to alloc default init table\n"); + return -1; + } + lcd_ext_init_on_table[0] = LCD_EXTERN_INIT_END; + lcd_ext_init_off_table[0] = LCD_EXTERN_INIT_END; + ret = of_property_read_u32(lcd_extern_dev->of_node, "key_valid", &lcd_ext_key_valid); if (ret) { @@ -857,10 +949,12 @@ static int lcd_extern_get_config(void) 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; - memset(&extconf, 0, sizeof(struct lcd_extern_config_s)); ret = lcd_extern_get_config_unifykey(&extconf); if (ret == 0) lcd_extern_add_driver(&extconf); @@ -869,13 +963,15 @@ static int lcd_extern_get_config(void) EXTPR("%s from dts\n", __func__); lcd_ext_config_load = 0; for_each_child_of_node(lcd_extern_dev->of_node, child) { - memset(&extconf, 0, sizeof(struct lcd_extern_config_s)); ret = lcd_extern_get_config_dts(child, &extconf); if (ret == 0) lcd_extern_add_driver(&extconf); } #endif } + + kfree(lcd_ext_init_on_table); + kfree(lcd_ext_init_off_table); return 0; } @@ -997,9 +1093,31 @@ static int lcd_extern_add_driver(struct lcd_extern_config_s *extconf) strcpy(ext_drv->config.name, extconf->name); ext_drv->config.type = extconf->type; ext_drv->config.status = extconf->status; + 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 = lcd_extern_init_on_table; - ext_drv->config.table_init_off = lcd_extern_init_off_table; + 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); + } /* fill config parameters by different type */ switch (ext_drv->config.type) { @@ -1029,6 +1147,8 @@ static int lcd_extern_add_driver(struct lcd_extern_config_s *extconf) } 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; return -1; @@ -1039,10 +1159,88 @@ static int lcd_extern_add_driver(struct lcd_extern_config_s *extconf) return 0; } -/* debug function */ +#define EXT_LEN_MAX 200 +static void lcd_extern_init_table_dynamic_size_print( + struct lcd_extern_config_s *econf, int flag) +{ + int i, j, k, max_len; + unsigned char cmd_size; + char str[EXT_LEN_MAX]; + unsigned char *init_table; + + if (flag) { + pr_info("power on:\n"); + init_table = econf->table_init_on; + max_len = LCD_EXTERN_INIT_ON_MAX; + } else { + pr_info("power off:\n"); + init_table = econf->table_init_off; + max_len = LCD_EXTERN_INIT_OFF_MAX; + } + if (init_table == NULL) { + EXTERR("init_table %d is NULL\n", flag); + return; + } + + i = 0; + while (i < max_len) { + if (init_table[i] == LCD_EXTERN_INIT_END) + break; + + cmd_size = init_table[i+1]; + 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++) { + k += snprintf(str+k, EXT_LEN_MAX, " 0x%02x", + init_table[i+2+j]); + } + } + pr_info("%s\n", str); + i += (cmd_size + 2); + } +} + +static void lcd_extern_init_table_fixed_size_print( + struct lcd_extern_config_s *econf, int flag) +{ + int i, j, k, max_len; + unsigned char cmd_size; + char str[EXT_LEN_MAX]; + unsigned char *init_table; + + cmd_size = econf->cmd_size; + if (flag) { + pr_info("power on:\n"); + init_table = econf->table_init_on; + max_len = LCD_EXTERN_INIT_ON_MAX; + } else { + pr_info("power off:\n"); + init_table = econf->table_init_off; + max_len = LCD_EXTERN_INIT_OFF_MAX; + } + if (init_table == NULL) { + EXTERR("init_table %d is NULL\n", flag); + return; + } + + i = 0; + while (i < max_len) { + if (init_table[i] == LCD_EXTERN_INIT_END) + break; + + k = snprintf(str, EXT_LEN_MAX, " "); + for (j = 0; j < cmd_size; j++) { + k += snprintf(str+k, EXT_LEN_MAX, " 0x%02x", + init_table[i+j]); + } + pr_info("%s\n", str); + i += cmd_size; + } +} + static void lcd_extern_config_dump(struct aml_lcd_extern_driver_s *ext_drv) { - int i, j, len; struct lcd_extern_config_s *econf; if (ext_drv == NULL) @@ -1062,34 +1260,12 @@ static void lcd_extern_config_dump(struct aml_lcd_extern_driver_s *ext_drv) econf->cmd_size, econf->i2c_addr, econf->i2c_addr2, econf->i2c_bus, econf->table_init_loaded); - len = econf->cmd_size; - pr_info("power on:\n"); - i = 0; - while (i < LCD_EXTERN_INIT_TABLE_MAX) { - if (econf->table_init_on[i] == LCD_EXTERN_INIT_END) { - pr_info("\n"); - } else { - for (j = 0; j < len; j++) { - pr_info("0x%02x ", - econf->table_init_on[i+j]); - } - pr_info("\n"); - } - i += len; - } - pr_info("power off:\n"); - i = 0; - while (i < LCD_EXTERN_INIT_TABLE_MAX) { - if (econf->table_init_off[i] == LCD_EXTERN_INIT_END) { - pr_info("\n"); - } else { - for (j = 0; j < len; j++) { - pr_info("0x%02x ", - econf->table_init_off[i+j]); - } - pr_info("\n"); - } - i += len; + if (econf->cmd_size == LCD_EXTERN_CMD_SIZE_DYNAMIC) { + lcd_extern_init_table_dynamic_size_print(econf, 1); + lcd_extern_init_table_dynamic_size_print(econf, 0); + } else { + lcd_extern_init_table_fixed_size_print(econf, 1); + lcd_extern_init_table_fixed_size_print(econf, 0); } break; case LCD_EXTERN_SPI: @@ -1099,38 +1275,19 @@ static void lcd_extern_config_dump(struct aml_lcd_extern_driver_s *ext_drv) "spi_gpio_clk: %d\n" "spi_gpio_data: %d\n" "spi_clk_freq: %dHz\n" + "spi_delay_us: %d\n" "spi_clk_pol: %d\n" "table_loaded: %d\n", econf->cmd_size, econf->spi_gpio_cs, econf->spi_gpio_clk, econf->spi_gpio_data, - econf->spi_clk_freq, econf->spi_clk_pol, - econf->table_init_loaded); - len = econf->cmd_size; - i = 0; - while (i < LCD_EXTERN_INIT_TABLE_MAX) { - if (econf->table_init_on[i] == LCD_EXTERN_INIT_END) { - pr_info("\n"); - } else { - for (j = 0; j < len; j++) { - pr_info("0x%02x ", - econf->table_init_on[i+j]); - } - pr_info("\n"); - } - i += len; - } - i = 0; - while (i < LCD_EXTERN_INIT_TABLE_MAX) { - if (econf->table_init_off[i] == LCD_EXTERN_INIT_END) { - pr_info("\n"); - } else { - for (j = 0; j < len; j++) { - pr_info("0x%02x ", - econf->table_init_off[i+j]); - } - pr_info("\n"); - } - i += len; + econf->spi_clk_freq, econf->spi_delay_us, + econf->spi_clk_pol, econf->table_init_loaded); + if (econf->cmd_size == LCD_EXTERN_CMD_SIZE_DYNAMIC) { + lcd_extern_init_table_dynamic_size_print(econf, 1); + lcd_extern_init_table_dynamic_size_print(econf, 0); + } else { + lcd_extern_init_table_fixed_size_print(econf, 1); + lcd_extern_init_table_fixed_size_print(econf, 0); } break; case LCD_EXTERN_MIPI: @@ -1178,9 +1335,6 @@ static ssize_t lcd_extern_info_dump(struct class *class, break; } - if (ret != 1 || ret != 2) - return -EINVAL; - return count; } @@ -1196,6 +1350,41 @@ static ssize_t lcd_extern_debug_config_load_show(struct class *class, return sprintf(buf, "%d\n", lcd_ext_config_load); } +static const char *lcd_extern_debug_test_usage_str = { +"Usage:\n" +" echo > test ; test power on/off for index extern device\n" +" : 1 for power on, 0 for power off\n" +}; + +static ssize_t lcd_extern_debug_test_show(struct class *class, + struct class_attribute *attr, char *buf) +{ + return sprintf(buf, "%s\n", lcd_extern_debug_test_usage_str); +} + +static ssize_t lcd_extern_debug_test_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; + + 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(); + } else { + if (ext_drv->power_off) + ext_drv->power_off(); + } + } + + return count; +} + static struct class_attribute lcd_extern_class_attrs[] = { __ATTR(info, 0644, lcd_extern_debug_help, lcd_extern_info_dump), @@ -1203,6 +1392,8 @@ static struct class_attribute lcd_extern_class_attrs[] = { lcd_extern_debug_key_valid_show, NULL), __ATTR(config_load, 0644, lcd_extern_debug_config_load_show, NULL), + __ATTR(test, 0644, + lcd_extern_debug_test_show, lcd_extern_debug_test_store), }; static struct class *debug_class; @@ -1259,6 +1450,8 @@ static int aml_lcd_extern_remove(struct platform_device *pdev) 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; } diff --git a/drivers/amlogic/media/vout/lcd/lcd_extern/spi_LD070WS2.c b/drivers/amlogic/media/vout/lcd/lcd_extern/spi_LD070WS2.c index 7c2678c..768a402 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_extern/spi_LD070WS2.c +++ b/drivers/amlogic/media/vout/lcd/lcd_extern/spi_LD070WS2.c @@ -61,20 +61,20 @@ static unsigned char init_off_table[] = { static void set_lcd_csb(unsigned int v) { - lcd_extern_gpio_set(ext_config->spi_cs, v); - udelay(SPI_DELAY); + lcd_extern_gpio_set(ext_config->spi_gpio_cs, v); + udelay(ext_config->spi_delay_us); } static void set_lcd_scl(unsigned int v) { - lcd_extern_gpio_set(ext_config->spi_clk, v); - udelay(SPI_DELAY); + lcd_extern_gpio_set(ext_config->spi_gpio_clk, v); + udelay(ext_config->spi_delay_us); } static void set_lcd_sda(unsigned int v) { - lcd_extern_gpio_set(ext_config->spi_data, v); - udelay(SPI_DELAY); + lcd_extern_gpio_set(ext_config->spi_gpio_data, v); + udelay(ext_config->spi_delay_us); } static void spi_gpio_init(void) @@ -119,7 +119,7 @@ static void spi_write_8(unsigned char addr, unsigned char data) set_lcd_csb(1); set_lcd_scl(1); set_lcd_sda(1); - udelay(SPI_DELAY); + udelay(ext_config->spi_delay_us); } static int lcd_extern_spi_write(unsigned char *buf, int len) @@ -132,21 +132,39 @@ static int lcd_extern_spi_write(unsigned char *buf, int len) return 0; } -static int lcd_extern_power_cmd(unsigned char *init_table) +static int lcd_extern_power_cmd(unsigned char *init_table, int flag) { - int i = 0, len; + int i = 0, max_len, step = 0; + unsigned char cmd_size; int ret = 0; - len = ext_config->cmd_size; - if (len < 1) { - EXTERR("%s: cmd_size %d is invalid\n", __func__, len); + cmd_size = ext_config->cmd_size; + if (cmd_size < 1) { + EXTERR("%s: cmd_size %d is invalid\n", __func__, cmd_size); + return -1; + } + if (cmd_size == LCD_EXTERN_CMD_SIZE_DYNAMIC) { + EXTPR("%s: cmd_size dynamic length to do\n", __func__); + return -1; + } + if (init_table == NULL) { + EXTERR("%s: init_table %d is NULL\n", __func__, flag); return -1; } - while (i <= LCD_EXTERN_INIT_TABLE_MAX) { - if (init_table[i] == LCD_EXTERN_INIT_END) { + if (flag) + max_len = LCD_EXTERN_INIT_ON_MAX; + else + max_len = LCD_EXTERN_INIT_OFF_MAX; + + while (i <= max_len) { + if (init_table[i] == LCD_EXTERN_INIT_END) break; - } else if (init_table[i] == LCD_EXTERN_INIT_NONE) { + if (lcd_debug_print_flag) { + EXTPR("%s: step %d: type=0x%02x, cmd_size=%d\n", + __func__, step, init_table[i], cmd_size); + } + if (init_table[i] == LCD_EXTERN_INIT_NONE) { /* do nothing, only for delay */ } else if (init_table[i] == LCD_EXTERN_INIT_GPIO) { if (init_table[i+1] < LCD_GPIO_MAX) { @@ -154,15 +172,17 @@ static int lcd_extern_power_cmd(unsigned char *init_table) init_table[i+2]); } } else if (init_table[i] == LCD_EXTERN_INIT_CMD) { - ret = lcd_extern_spi_write(&init_table[i+1], (len-2)); + ret = lcd_extern_spi_write(&init_table[i+1], + (cmd_size-2)); } else { EXTERR("%s(%d: %s): power_type %d is invalid\n", __func__, ext_config->index, ext_config->name, ext_config->type); } - if (init_table[i+len-1] > 0) - mdelay(init_table[i+len-1]); - i += len; + if (init_table[i+cmd_size-1] > 0) + mdelay(init_table[i+cmd_size-1]); + step++; + i += cmd_size; } return ret; @@ -174,9 +194,9 @@ static int lcd_extern_power_ctrl(int flag) spi_gpio_init(); if (flag) - ret = lcd_extern_power_cmd(ext_config->table_init_on); + ret = lcd_extern_power_cmd(ext_config->table_init_on, 1); else - ret = lcd_extern_power_cmd(ext_config->table_init_off); + ret = lcd_extern_power_cmd(ext_config->table_init_off, 0); mdelay(10); spi_gpio_off(); @@ -212,6 +232,8 @@ static int lcd_extern_driver_update(struct aml_lcd_extern_driver_s *ext_drv) 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->power_on = lcd_extern_power_on; ext_drv->power_off = lcd_extern_power_off; diff --git a/include/linux/amlogic/media/vout/lcd/lcd_extern.h b/include/linux/amlogic/media/vout/lcd/lcd_extern.h index 6c18502..5d3b676 100644 --- a/include/linux/amlogic/media/vout/lcd/lcd_extern.h +++ b/include/linux/amlogic/media/vout/lcd/lcd_extern.h @@ -33,25 +33,25 @@ enum lcd_extern_i2c_bus_e { LCD_EXTERN_I2C_BUS_D, LCD_EXTERN_I2C_BUS_MAX, }; -#define LCD_EXTERN_I2C_BUS_INVALID 0xff +#define LCD_EXTERN_I2C_BUS_INVALID 0xff -#define LCD_EXTERN_SPI_CLK_FREQ_DFT 10000 /* default 10k */ +#define LCD_EXTERN_SPI_CLK_FREQ_DFT 10000 /* default 10k */ -#define LCD_EXTERN_INIT_TABLE_MAX 500 +#define LCD_EXTERN_INIT_ON_MAX 500 +#define LCD_EXTERN_INIT_OFF_MAX 100 -#define LCD_EXTERN_INIT_CMD 0x00 -#define LCD_EXTERN_INIT_CMD2 0x01 /* only for special i2c device */ -#define LCD_EXTERN_INIT_GPIO 0x10 -#define LCD_EXTERN_INIT_NONE 0xf0 -#define LCD_EXTERN_INIT_END 0xff +#define LCD_EXTERN_INIT_CMD 0x00 +#define LCD_EXTERN_INIT_CMD2 0x01 /* only for special i2c device */ +#define LCD_EXTERN_INIT_GPIO 0x10 +#define LCD_EXTERN_INIT_NONE 0xf0 +#define LCD_EXTERN_INIT_END 0xff +#define LCD_EXTERN_CMD_SIZE_DYNAMIC 0xff +#define LCD_EXTERN_DYNAMIC_SIZE_INDEX 1 -#define LCD_EXTERN_DYNAMIC_LEN 0xff - - -#define LCD_EXTERN_GPIO_NUM_MAX 6 -#define LCD_EXTERN_INDEX_INVALID 0xff -#define LCD_EXTERN_NAME_LEN_MAX 30 +#define LCD_EXTERN_GPIO_NUM_MAX 6 +#define LCD_EXTERN_INDEX_INVALID 0xff +#define LCD_EXTERN_NAME_LEN_MAX 30 struct lcd_extern_config_s { unsigned char index; char name[LCD_EXTERN_NAME_LEN_MAX]; @@ -64,6 +64,7 @@ struct lcd_extern_config_s { 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 */ -- 2.7.4