| /* |
| * drivers/display/lcd/lcd_extern/lcd_extern.c |
| * |
| * 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 named License, |
| * or 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 <common.h> |
| #include <malloc.h> |
| #include <asm/arch/gpio.h> |
| #ifdef CONFIG_OF_LIBFDT |
| #include <libfdt.h> |
| #endif |
| #ifdef CONFIG_SYS_I2C_AML |
| #include <aml_i2c.h> |
| #endif |
| #include <amlogic/aml_lcd.h> |
| #include <amlogic/aml_lcd_extern.h> |
| #include "lcd_extern.h" |
| #include "../aml_lcd_common.h" |
| #include "../aml_lcd_reg.h" |
| |
| |
| static char *dt_addr = NULL; |
| 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; |
| |
| /* only probe one extern driver for uboot */ |
| static struct aml_lcd_extern_driver_s *lcd_ext_driver; |
| |
| struct aml_lcd_extern_driver_s *aml_lcd_extern_get_driver(void) |
| { |
| if (lcd_ext_driver == NULL) |
| EXTERR("invalid driver\n"); |
| return lcd_ext_driver; |
| } |
| |
| static void aml_lcd_extern_init_table_dynamic_size_print( |
| struct lcd_extern_config_s *econf, int flag) |
| { |
| int i, j, max_len; |
| unsigned char cmd_size; |
| unsigned char *init_table; |
| |
| if (flag) { |
| printf("power on:\n"); |
| init_table = econf->table_init_on; |
| max_len = LCD_EXTERN_INIT_ON_MAX; |
| } else { |
| printf("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; |
| switch (econf->type) { |
| case LCD_EXTERN_I2C: |
| case LCD_EXTERN_SPI: |
| while ((i + 1) < max_len) { |
| if (init_table[i] == LCD_EXTERN_INIT_END) { |
| printf(" 0x%02x,%d,\n", |
| init_table[i], init_table[i+1]); |
| break; |
| } |
| |
| cmd_size = init_table[i+1]; |
| printf(" 0x%02x,%d,", init_table[i], cmd_size); |
| if (cmd_size > 0) { |
| for (j = 0; j < cmd_size; j++) |
| printf("0x%02x,", init_table[i+2+j]); |
| } |
| printf("\n"); |
| i += (cmd_size + 2); |
| } |
| break; |
| case LCD_EXTERN_MIPI: |
| while ((i + 1) < max_len) { |
| if (init_table[i] == 0xff) { /* ctrl flag */ |
| cmd_size = 0; |
| if (init_table[i+1] == 0xff) { |
| printf(" 0x%02x,0x%02x,\n", |
| init_table[i], init_table[i+1]); |
| break; |
| } else { |
| printf(" 0x%02x,%d,\n", |
| init_table[i], init_table[i+1]); |
| } |
| } else if (init_table[i] == 0xf0) { /* gpio */ |
| cmd_size = init_table[i+DSI_CMD_SIZE_INDEX]; |
| printf(" 0x%02x,%d,", init_table[i], cmd_size); |
| for (j = 0; j < cmd_size; j++) |
| printf("%d,", init_table[i+2+j]); |
| printf("\n"); |
| } else if ((init_table[i] & 0xf) == 0x0) { |
| printf(" init_%s wrong data_type: 0x%02x\n", |
| flag ? "on" : "off", init_table[i]); |
| break; |
| } else { |
| cmd_size = init_table[i+DSI_CMD_SIZE_INDEX]; |
| printf(" 0x%02x,%d,", init_table[i], cmd_size); |
| for (j = 0; j < cmd_size; j++) |
| printf("0x%02x,", init_table[i+2+j]); |
| printf("\n"); |
| } |
| i += (cmd_size + 2); |
| } |
| break; |
| default: |
| break; |
| } |
| } |
| |
| static void aml_lcd_extern_init_table_fixed_size_print( |
| struct lcd_extern_config_s *econf, int flag) |
| { |
| int i, j, max_len; |
| unsigned char cmd_size; |
| unsigned char *init_table; |
| |
| cmd_size = econf->cmd_size; |
| if (flag) { |
| printf("power on:\n"); |
| init_table = econf->table_init_on; |
| max_len = LCD_EXTERN_INIT_ON_MAX; |
| } else { |
| printf("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) { |
| printf(" "); |
| for (j = 0; j < cmd_size; j++) { |
| printf("0x%02x,", init_table[i+j]); |
| } |
| printf("\n"); |
| |
| if (init_table[i] == LCD_EXTERN_INIT_END) |
| break; |
| i += cmd_size; |
| } |
| } |
| |
| static void aml_lcd_extern_info_print(void) |
| { |
| struct lcd_extern_config_s *econf; |
| struct lcd_extern_common_s *ecommon; |
| |
| if (lcd_ext_driver == NULL) { |
| EXTERR("no lcd_extern driver\n"); |
| return; |
| } |
| econf = lcd_ext_driver->config; |
| ecommon = lcd_ext_driver->common; |
| |
| LCDPR("lcd_extern info:\n"); |
| printf("name: %s\n" |
| "index: %d\n" |
| "type: %d\n" |
| "status: %d\n" |
| "cmd_size: %d\n", |
| econf->name, econf->index, |
| econf->type, econf->status, |
| econf->cmd_size); |
| |
| switch (econf->type) { |
| case LCD_EXTERN_I2C: |
| printf("i2c_addr: 0x%02x\n" |
| "i2c_addr2: 0x%02x\n" |
| "i2c_bus: %d\n" |
| "i2c_sck_gpio: %d\n" |
| "i2c_sck_gpio_off: %d\n" |
| "i2c_sda_gpio: %d\n" |
| "i2c_sda_gpio_off: %d\n" |
| "table_loaded: %d\n", |
| econf->i2c_addr, econf->i2c_addr2, |
| econf->i2c_bus, |
| ecommon->i2c_sck_gpio, |
| ecommon->i2c_sck_gpio_off, |
| ecommon->i2c_sda_gpio, |
| ecommon->i2c_sda_gpio_off, |
| econf->table_init_loaded); |
| if (econf->cmd_size == 0) |
| break; |
| if (econf->cmd_size == LCD_EXTERN_CMD_SIZE_DYNAMIC) { |
| aml_lcd_extern_init_table_dynamic_size_print(econf, 1); |
| aml_lcd_extern_init_table_dynamic_size_print(econf, 0); |
| } else { |
| aml_lcd_extern_init_table_fixed_size_print(econf, 1); |
| aml_lcd_extern_init_table_fixed_size_print(econf, 0); |
| } |
| break; |
| case LCD_EXTERN_SPI: |
| printf("spi_gpio_cs: %d\n" |
| "spi_gpio_clk: %d\n" |
| "spi_gpio_data: %d\n" |
| "spi_clk_freq: %d\n" |
| "spi_clk_pol: %d\n" |
| "table_loaded: %d\n", |
| econf->spi_gpio_cs, |
| econf->spi_gpio_clk, econf->spi_gpio_data, |
| econf->spi_clk_freq, econf->spi_clk_pol, |
| econf->table_init_loaded); |
| if (econf->cmd_size == 0) |
| break; |
| if (econf->cmd_size == LCD_EXTERN_CMD_SIZE_DYNAMIC) { |
| aml_lcd_extern_init_table_dynamic_size_print(econf, 1); |
| aml_lcd_extern_init_table_dynamic_size_print(econf, 0); |
| } else { |
| aml_lcd_extern_init_table_fixed_size_print(econf, 1); |
| aml_lcd_extern_init_table_fixed_size_print(econf, 0); |
| } |
| break; |
| case LCD_EXTERN_MIPI: |
| if (econf->cmd_size != LCD_EXTERN_CMD_SIZE_DYNAMIC) |
| break; |
| aml_lcd_extern_init_table_dynamic_size_print(econf, 1); |
| aml_lcd_extern_init_table_dynamic_size_print(econf, 0); |
| break; |
| default: |
| printf("not support extern_type\n"); |
| break; |
| } |
| } |
| |
| int aml_lcd_extern_get_gpio(unsigned char index) |
| { |
| int gpio; |
| char *str; |
| |
| if (lcd_ext_driver == NULL) { |
| EXTERR("no lcd_extern driver\n"); |
| return LCD_GPIO_MAX; |
| } |
| |
| if (index >= LCD_EXTERN_GPIO_NUM_MAX) { |
| return LCD_GPIO_MAX; |
| } |
| str = lcd_ext_driver->common->gpio_name[index]; |
| gpio = aml_lcd_gpio_name_map_num(str); |
| return gpio; |
| } |
| |
| int aml_lcd_extern_set_gpio(unsigned char index, int value) |
| { |
| int gpio; |
| int ret; |
| |
| gpio = aml_lcd_extern_get_gpio(index); |
| ret = aml_lcd_gpio_set(gpio, value); |
| return ret; |
| } |
| |
| void lcd_extern_pinmux_set(int status) |
| { |
| int i; |
| struct lcd_extern_config_s *extconf = lcd_ext_driver->config; |
| struct lcd_extern_common_s *extcommon = lcd_ext_driver->common; |
| |
| if (lcd_debug_print_flag) |
| EXTPR("%s: %d\n", __func__, status); |
| |
| if (status) { |
| i = 0; |
| while (i < LCD_PINMUX_NUM) { |
| if (extcommon->pinmux_clr[i][0] == LCD_PINMUX_END) |
| break; |
| if (lcd_debug_print_flag) { |
| EXTPR("pinmux_clr: %d, 0x%08x\n", |
| extcommon->pinmux_clr[i][0], |
| extcommon->pinmux_clr[i][1]); |
| } |
| lcd_pinmux_clr_mask(extcommon->pinmux_clr[i][0], |
| extcommon->pinmux_clr[i][1]); |
| i++; |
| } |
| i = 0; |
| while (i < LCD_PINMUX_NUM) { |
| if (extcommon->pinmux_set[i][0] == LCD_PINMUX_END) |
| break; |
| if (lcd_debug_print_flag) { |
| EXTPR("pinmux_set: %d, 0x%08x\n", |
| extcommon->pinmux_set[i][0], |
| extcommon->pinmux_set[i][1]); |
| } |
| lcd_pinmux_set_mask(extcommon->pinmux_set[i][0], |
| extcommon->pinmux_set[i][1]); |
| i++; |
| } |
| } else { |
| i = 0; |
| while (i < LCD_PINMUX_NUM) { |
| if (extcommon->pinmux_set[i][0] == LCD_PINMUX_END) |
| break; |
| if (lcd_debug_print_flag) { |
| EXTPR("pinmux_clr: %d, 0x%08x\n", |
| extcommon->pinmux_set[i][0], |
| extcommon->pinmux_set[i][1]); |
| } |
| lcd_pinmux_clr_mask(extcommon->pinmux_set[i][0], |
| extcommon->pinmux_set[i][1]); |
| i++; |
| } |
| /* set gpio */ |
| if (extconf->type == LCD_EXTERN_I2C) { |
| if (extcommon->i2c_sck_gpio != LCD_EXTERN_GPIO_NUM_MAX) |
| aml_lcd_extern_set_gpio(extcommon->i2c_sck_gpio, extcommon->i2c_sck_gpio_off); |
| if (extcommon->i2c_sda_gpio != LCD_EXTERN_GPIO_NUM_MAX) |
| aml_lcd_extern_set_gpio(extcommon->i2c_sda_gpio, extcommon->i2c_sda_gpio_off); |
| } |
| } |
| } |
| |
| #ifdef CONFIG_OF_LIBFDT |
| #ifdef CONFIG_SYS_I2C_AML |
| static unsigned char aml_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; |
| else if (strncmp(str, "i2c_bus_a", 9) == 0) |
| i2c_bus = AML_I2C_MASTER_A; |
| else if (strncmp(str, "i2c_bus_b", 9) == 0) |
| i2c_bus = AML_I2C_MASTER_B; |
| else if (strncmp(str, "i2c_bus_c", 9) == 0) |
| i2c_bus = AML_I2C_MASTER_C; |
| else if (strncmp(str, "i2c_bus_d", 9) == 0) |
| i2c_bus = AML_I2C_MASTER_D; |
| else { |
| i2c_bus = LCD_EXTERN_I2C_BUS_INVALID; |
| EXTERR("invalid i2c_bus: %s\n", str); |
| } |
| |
| return i2c_bus; |
| } |
| #endif |
| |
| char *aml_lcd_extern_get_dts_prop(int nodeoffset, char *propname) |
| { |
| char *propdata; |
| |
| propdata = (char *)fdt_getprop(dt_addr, nodeoffset, propname, NULL); |
| return propdata; |
| } |
| |
| int aml_lcd_extern_get_dts_child(int index) |
| { |
| int nodeoffset; |
| char chlid_node[30]; |
| char *propdata; |
| |
| sprintf(chlid_node, "/lcd_extern/extern_%d", index); |
| nodeoffset = fdt_path_offset(dt_addr, chlid_node); |
| if (nodeoffset < 0) { |
| EXTERR("dts: not find node %s\n", chlid_node); |
| return nodeoffset; |
| } |
| |
| propdata = (char *)fdt_getprop(dt_addr, nodeoffset, "index", NULL); |
| if (propdata == NULL) { |
| EXTERR("get index failed, exit\n"); |
| return -1; |
| } else { |
| if (be32_to_cpup((u32*)propdata) != index) { |
| EXTERR("index not match, exit\n"); |
| return -1; |
| } |
| } |
| return nodeoffset; |
| } |
| |
| static int aml_lcd_extern_get_init_dts(char *dtaddr, struct lcd_extern_common_s *extcommon) |
| { |
| int parent_offset; |
| char *propdata, *p; |
| const char *str; |
| char propname[30]; |
| int lcd_ext_pinctrl_ver = 0; |
| int temp, len = 0; |
| int i; |
| |
| parent_offset = fdt_path_offset(dtaddr, "/lcd_extern"); |
| if (parent_offset < 0) { |
| EXTERR("not find /lcd_extern node: %s\n", fdt_strerror(parent_offset)); |
| return -1; |
| } |
| |
| propdata = (char *)fdt_getprop(dtaddr, parent_offset, "key_valid", NULL); |
| if (propdata == NULL) { |
| if (lcd_debug_print_flag) |
| EXTPR("failed to get key_valid\n"); |
| extcommon->lcd_ext_key_valid = 0; |
| } else { |
| extcommon->lcd_ext_key_valid = (unsigned char)(be32_to_cpup((u32*)propdata)); |
| } |
| |
| propdata = (char *)fdt_getprop(dtaddr, parent_offset, "i2c_bus", NULL); |
| if (propdata == NULL) |
| lcd_ext_i2c_bus = LCD_EXTERN_I2C_BUS_INVALID; |
| else |
| lcd_ext_i2c_bus = aml_lcd_extern_get_i2c_bus_str(propdata); |
| |
| i = 0; |
| propdata = (char *)fdt_getprop(dtaddr, parent_offset, "extern_gpio_names", NULL); |
| if (propdata == NULL) { |
| if (lcd_debug_print_flag) |
| EXTPR("failed to get extern_gpio_names\n"); |
| } else { |
| p = propdata; |
| while (i < LCD_EXTERN_GPIO_NUM_MAX) { |
| if (i > 0) |
| p += strlen(p) + 1; |
| str = p; |
| if (strlen(str) == 0) |
| break; |
| strcpy(extcommon->gpio_name[i], str); |
| if (lcd_debug_print_flag) { |
| EXTPR("i=%d, gpio=%s\n", i, extcommon->gpio_name[i]); |
| } |
| i++; |
| } |
| } |
| if (i < LCD_EXTERN_GPIO_NUM_MAX) |
| strcpy(extcommon->gpio_name[i], "invalid"); |
| |
| propdata = (char *)fdt_getprop(dtaddr, parent_offset, "i2c_gpio_off", NULL); |
| if (propdata == NULL) { |
| 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; |
| } else { |
| lcd_ext_i2c_sck_gpio = be32_to_cpup((u32*)propdata); |
| lcd_ext_i2c_sck_gpio_off = be32_to_cpup((((u32*)propdata)+1)); |
| lcd_ext_i2c_sda_gpio = be32_to_cpup((((u32*)propdata)+2)); |
| lcd_ext_i2c_sda_gpio_off = be32_to_cpup((((u32*)propdata)+3)); |
| } |
| |
| /* pinmux version*/ |
| /* new kernel dts pinctrl detect */ |
| propdata = (char *)fdt_getprop(dtaddr, parent_offset, "pinctrl_version", NULL); |
| if (propdata) { |
| lcd_ext_pinctrl_ver = (unsigned char)(be32_to_cpup((u32*)propdata)); |
| EXTPR("pinctrl_version: %d\n", lcd_ext_pinctrl_ver); |
| } |
| if (lcd_ext_pinctrl_ver) /*use lcd.c config, not read dts*/ |
| return 0; |
| |
| /* get pinmux */ |
| propdata = (char *)fdt_getprop(dtaddr, parent_offset, "pinctrl_names_uboot", NULL); |
| if (propdata == NULL) |
| return 0; |
| |
| sprintf(propname, "/pinmux/%s", propdata); |
| EXTPR("find pinctrl_names_uboot: %s\n", propname); |
| parent_offset = fdt_path_offset(dt_addr, propname); |
| if (parent_offset < 0) { |
| EXTPR("no pinmux extern_pins\n"); |
| extcommon->pinmux_set[0][0] = LCD_PINMUX_END; |
| extcommon->pinmux_set[0][1] = 0x0; |
| extcommon->pinmux_clr[0][0] = LCD_PINMUX_END; |
| extcommon->pinmux_clr[0][1] = 0x0; |
| return -1; |
| } else { |
| propdata = (char *)fdt_getprop(dt_addr, parent_offset, "amlogic,setmask", &len); |
| if (propdata == NULL) { |
| EXTERR("failed to get amlogic,setmask\n"); |
| extcommon->pinmux_set[0][0] = LCD_PINMUX_END; |
| extcommon->pinmux_set[0][1] = 0x0; |
| } else { |
| temp = len / 8; |
| for (i = 0; i < temp; i++) { |
| extcommon->pinmux_set[i][0] = be32_to_cpup((((u32*)propdata)+2*i)); |
| extcommon->pinmux_set[i][1] = be32_to_cpup((((u32*)propdata)+2*i+1)); |
| } |
| if (temp < (LCD_PINMUX_NUM - 1)) { |
| extcommon->pinmux_set[temp][0] = LCD_PINMUX_END; |
| extcommon->pinmux_set[temp][1] = 0x0; |
| } |
| } |
| |
| propdata = (char *)fdt_getprop(dt_addr, parent_offset, "amlogic,clrmask", &len); |
| if (propdata == NULL) { |
| EXTERR("failed to get amlogic,clrmask\n"); |
| extcommon->pinmux_clr[0][0] = LCD_PINMUX_END; |
| extcommon->pinmux_clr[0][1] = 0x0; |
| } else { |
| temp = len / 8; |
| for (i = 0; i < temp; i++) { |
| extcommon->pinmux_clr[i][0] = be32_to_cpup((((u32*)propdata)+2*i)); |
| extcommon->pinmux_clr[i][1] = be32_to_cpup((((u32*)propdata)+2*i+1)); |
| } |
| if (temp < (LCD_PINMUX_NUM - 1)) { |
| extcommon->pinmux_clr[temp][0] = LCD_PINMUX_END; |
| extcommon->pinmux_clr[temp][1] = 0x0; |
| } |
| } |
| if (lcd_debug_print_flag) { |
| i = 0; |
| while (i < LCD_PINMUX_NUM) { |
| if (extcommon->pinmux_set[i][0] == LCD_PINMUX_END) |
| break; |
| EXTPR("pinmux set: %d, 0x%08x\n", |
| extcommon->pinmux_set[i][0], extcommon->pinmux_set[i][1]); |
| i++; |
| } |
| i = 0; |
| while (i < LCD_PINMUX_NUM) { |
| if (extcommon->pinmux_clr[i][0] == LCD_PINMUX_END) |
| break; |
| EXTPR("pinmux clr: %d, 0x%08x\n", |
| extcommon->pinmux_clr[i][0], extcommon->pinmux_clr[i][1]); |
| i++; |
| } |
| } |
| } |
| |
| return 0; |
| } |
| |
| static int aml_lcd_extern_init_table_dynamic_size_load_dts( |
| char *dtaddr, int nodeoffset, |
| struct lcd_extern_config_s *extconf, int flag) |
| { |
| unsigned char cmd_size, type; |
| int i, j, max_len; |
| unsigned char *init_table; |
| char propname[20]; |
| char *propdata; |
| |
| 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"); |
| } |
| if (init_table == NULL) { |
| EXTPR("%s table is null\n", propname); |
| return 0; |
| } |
| |
| i = 0; |
| propdata = (char *)fdt_getprop(dtaddr, nodeoffset, propname, NULL); |
| if (propdata == NULL) { |
| EXTERR("get %s %s failed\n", extconf->name, propname); |
| init_table[0] = LCD_EXTERN_INIT_END; |
| return -1; |
| } |
| |
| switch (extconf->type) { |
| case LCD_EXTERN_I2C: |
| case LCD_EXTERN_SPI: |
| while ((i + 1) < max_len) { |
| /* step1: type */ |
| init_table[i] = (unsigned char)(be32_to_cpup((((u32*)propdata)+i))); |
| type = init_table[i]; |
| if (type == LCD_EXTERN_INIT_END) |
| break; |
| /* step2: cmd_size */ |
| init_table[i+1] = (unsigned char)(be32_to_cpup((((u32*)propdata)+i+1))); |
| cmd_size = init_table[i+1]; |
| if (cmd_size == 0) { |
| i += 2; |
| continue; |
| } |
| if ((i + 2 + cmd_size) >= max_len) { |
| EXTERR("%s %s cmd_size out of max\n", extconf->name, propname); |
| init_table[i] = LCD_EXTERN_INIT_END; |
| init_table[i+1] = 0; |
| break; |
| } |
| /* step3: data */ |
| for (j = 0; j < cmd_size; j++) |
| init_table[i+2+j] = (unsigned char)(be32_to_cpup((((u32*)propdata)+i+2+j))); |
| |
| i += (cmd_size + 2); |
| } |
| break; |
| case LCD_EXTERN_MIPI: |
| while ((i + 1) < max_len) { |
| init_table[i] = (unsigned char)(be32_to_cpup((((u32*)propdata)+i))); |
| type = init_table[i]; |
| if (type == 0xff) { |
| init_table[i+1] = (unsigned char)(be32_to_cpup((((u32*)propdata)+i+1))); |
| cmd_size = init_table[i+1]; |
| if (cmd_size == 0xff) |
| break; |
| i += 2; |
| } else if (type == 0xf0) { |
| init_table[i+1] = (unsigned char)(be32_to_cpup((((u32*)propdata)+i+1))); |
| cmd_size = init_table[i+1]; |
| if (cmd_size < 3) { |
| EXTERR("%s %s invalid cmd_size for gpio\n", extconf->name, propname); |
| break; |
| } |
| if ((i + 2 + cmd_size) >= max_len) { |
| EXTERR("%s %s cmd_size out of max\n", extconf->name, propname); |
| init_table[i] = 0xff; |
| init_table[i+1] = 0xff; |
| break; |
| } |
| for (j = 0; j < cmd_size; j++) |
| init_table[i+2+j] = (unsigned char)(be32_to_cpup((((u32*)propdata)+i+2+j))); |
| |
| i += (cmd_size + 2); |
| } else { |
| init_table[i+1] = (unsigned char)(be32_to_cpup((((u32*)propdata)+i+1))); |
| cmd_size = init_table[i+1]; |
| if (cmd_size == 0) { |
| i += 2; |
| continue; |
| } |
| if ((i + 2 + cmd_size) >= max_len) { |
| EXTERR("%s %s cmd_size out of max\n", extconf->name, propname); |
| init_table[i] = 0xff; |
| init_table[i+1] = 0xff; |
| break; |
| } |
| for (j = 0; j < cmd_size; j++) |
| init_table[i+2+j] = (unsigned char)(be32_to_cpup((((u32*)propdata)+i+2+j))); |
| |
| i += (cmd_size + 2); |
| } |
| } |
| break; |
| default: |
| break; |
| } |
| |
| return 0; |
| } |
| |
| static int aml_lcd_extern_init_table_fixed_size_load_dts( |
| char *dtaddr, int nodeoffset, |
| struct lcd_extern_config_s *extconf, int flag) |
| { |
| unsigned char cmd_size; |
| int i, j, max_len; |
| unsigned char *init_table; |
| char propname[20]; |
| char *propdata; |
| |
| 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"); |
| } |
| if (init_table == NULL) { |
| EXTPR("%s table is null\n", propname); |
| return 0; |
| } |
| |
| i = 0; |
| propdata = (char *)fdt_getprop(dtaddr, nodeoffset, propname, NULL); |
| if (propdata == NULL) { |
| EXTERR("get %s %s failed\n", extconf->name, propname); |
| init_table[0] = LCD_EXTERN_INIT_END; |
| return -1; |
| } |
| while (i < max_len) { |
| if ((i + cmd_size) >= max_len) { |
| EXTERR("%s %s cmd_size out of max\n", extconf->name, propname); |
| init_table[i] = LCD_EXTERN_INIT_END; |
| break; |
| } |
| for (j = 0; j < cmd_size; j++) |
| init_table[i+j] = (unsigned char)(be32_to_cpup((((u32*)propdata)+i+j))); |
| |
| if (extconf->table_init_on[i] == LCD_EXTERN_INIT_END) |
| break; |
| |
| i += cmd_size; |
| } |
| |
| return 0; |
| } |
| |
| static int aml_lcd_extern_get_config_dts(char *dtaddr, int index, |
| struct lcd_extern_config_s *extconf, |
| struct lcd_extern_common_s *extcommon) |
| { |
| int nodeoffset; |
| char *propdata; |
| const char *str; |
| int ret = 0; |
| |
| extconf->table_init_loaded = 0; |
| nodeoffset = aml_lcd_extern_get_dts_child(index); |
| if (nodeoffset < 0) |
| return -1; |
| |
| propdata = (char *)fdt_getprop(dtaddr, nodeoffset, "index", NULL); |
| if (propdata == NULL) { |
| extconf->index = LCD_EXTERN_INDEX_INVALID; |
| EXTERR("get index failed, exit\n"); |
| return -1; |
| } else { |
| extconf->index = (unsigned char)(be32_to_cpup((u32*)propdata)); |
| } |
| if (lcd_debug_print_flag) |
| EXTPR("index = %d\n", extconf->index); |
| |
| propdata = (char *)fdt_getprop(dtaddr, nodeoffset, "extern_name", NULL); |
| if (propdata == NULL) { |
| str = "invalid_name"; |
| strcpy(extconf->name, str); |
| EXTERR("get extern_name failed\n"); |
| } else { |
| memset(extconf->name, 0, LCD_EXTERN_NAME_LEN_MAX); |
| strcpy(extconf->name, propdata); |
| } |
| |
| propdata = (char *)fdt_getprop(dtaddr, nodeoffset, "status", NULL); |
| if (propdata == NULL) { |
| EXTERR("get status failed, default to disabled\n"); |
| extconf->status = 0; |
| } else { |
| if (strncmp(propdata, "okay", 2) == 0) |
| extconf->status = 1; |
| else |
| extconf->status = 0; |
| } |
| if (lcd_debug_print_flag) |
| EXTPR("%s: status = %d\n", extconf->name, extconf->status); |
| |
| propdata = (char *)fdt_getprop(dtaddr, nodeoffset, "type", NULL); |
| if (propdata == NULL) { |
| extconf->type = LCD_EXTERN_MAX; |
| EXTERR("get type failed, exit\n"); |
| return -1; |
| } else { |
| extconf->type = be32_to_cpup((u32*)propdata); |
| } |
| if (lcd_debug_print_flag) |
| EXTPR("%s: type = %d\n", extconf->name, extconf->type); |
| |
| switch (extconf->type) { |
| case LCD_EXTERN_I2C: |
| #ifdef CONFIG_SYS_I2C_AML |
| propdata = (char *)fdt_getprop(dtaddr, nodeoffset, "i2c_address", NULL); |
| if (propdata == NULL) { |
| EXTERR("get %s i2c_address failed, exit\n", extconf->name); |
| extconf->i2c_addr = 0xff; |
| return -1; |
| } else { |
| extconf->i2c_addr = (unsigned char)(be32_to_cpup((u32*)propdata)); |
| } |
| if (lcd_debug_print_flag) |
| EXTPR("%s: i2c_address=0x%02x\n", extconf->name, extconf->i2c_addr); |
| propdata = (char *)fdt_getprop(dtaddr, nodeoffset, "i2c_second_address", NULL); |
| if (propdata == NULL) { |
| if (lcd_debug_print_flag) |
| EXTPR("get %s i2c_second_address failed, exit\n", extconf->name); |
| extconf->i2c_addr2 = 0xff; |
| } else { |
| extconf->i2c_addr2 = (unsigned char)(be32_to_cpup((u32*)propdata)); |
| } |
| if (lcd_debug_print_flag) |
| EXTPR("%s: i2c_second_address=0x%02x\n", extconf->name, extconf->i2c_addr2); |
| |
| if (lcd_ext_i2c_bus == LCD_EXTERN_I2C_BUS_INVALID) { /* compatible for kernel3.14 */ |
| propdata = (char *)fdt_getprop(dtaddr, nodeoffset, "i2c_bus", NULL); |
| if (propdata == NULL) { |
| EXTERR("get %s i2c_bus failed, exit\n", extconf->name); |
| extconf->i2c_bus = LCD_EXTERN_I2C_BUS_INVALID; |
| return -1; |
| } else { |
| extconf->i2c_bus = aml_lcd_extern_get_i2c_bus_str(propdata); |
| } |
| } else { |
| extconf->i2c_bus = lcd_ext_i2c_bus; |
| } |
| if (lcd_debug_print_flag) |
| EXTPR("%s: i2c_bus= %d\n", extconf->name, extconf->i2c_bus); |
| |
| extcommon->i2c_sck_gpio = lcd_ext_i2c_sck_gpio; |
| extcommon->i2c_sck_gpio_off = lcd_ext_i2c_sck_gpio_off; |
| extcommon->i2c_sda_gpio = lcd_ext_i2c_sda_gpio; |
| extcommon->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"); |
| |
| propdata = (char *)fdt_getprop(dtaddr, nodeoffset, "cmd_size", NULL); |
| if (propdata == NULL) { |
| EXTERR("get %s cmd_size failed\n", extconf->name); |
| extconf->cmd_size = 0; |
| } else { |
| extconf->cmd_size = (unsigned char)(be32_to_cpup((u32*)propdata)); |
| } |
| if (lcd_debug_print_flag) |
| EXTPR("%s: cmd_size=%d\n", extconf->name, extconf->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 = aml_lcd_extern_init_table_dynamic_size_load_dts( |
| dtaddr, nodeoffset, extconf, 1); |
| if (ret) |
| break; |
| ret = aml_lcd_extern_init_table_dynamic_size_load_dts( |
| dtaddr, nodeoffset, extconf, 0); |
| } else { |
| ret = aml_lcd_extern_init_table_fixed_size_load_dts( |
| dtaddr, nodeoffset, extconf, 1); |
| if (ret) |
| break; |
| ret = aml_lcd_extern_init_table_fixed_size_load_dts( |
| dtaddr, nodeoffset, extconf, 0); |
| } |
| if (ret == 0) |
| extconf->table_init_loaded = 1; |
| #else |
| EXTERR("system has no i2c support\n"); |
| #endif |
| break; |
| case LCD_EXTERN_SPI: |
| propdata = (char *)fdt_getprop(dtaddr, nodeoffset, "gpio_spi_cs", NULL); |
| if (propdata == NULL) { |
| EXTERR("get %s gpio_spi_cs failed, exit\n", extconf->name); |
| extconf->spi_gpio_cs = LCD_EXTERN_GPIO_NUM_MAX; |
| return -1; |
| } else { |
| extconf->spi_gpio_cs = (unsigned char)(be32_to_cpup((u32*)propdata)); |
| } |
| propdata = (char *)fdt_getprop(dtaddr, nodeoffset, "gpio_spi_clk", NULL); |
| if (propdata == NULL) { |
| EXTERR("get %s gpio_spi_clk failed, exit\n", extconf->name); |
| extconf->spi_gpio_clk = LCD_EXTERN_GPIO_NUM_MAX; |
| return -1; |
| } else { |
| extconf->spi_gpio_clk = (unsigned char)(be32_to_cpup((u32*)propdata)); |
| } |
| propdata = (char *)fdt_getprop(dtaddr, nodeoffset, "gpio_spi_data", NULL); |
| if (propdata == NULL) { |
| EXTERR("get %s gpio_spi_data failed, exit\n", extconf->name); |
| extconf->spi_gpio_data = LCD_EXTERN_GPIO_NUM_MAX; |
| return -1; |
| } else { |
| extconf->spi_gpio_data = (unsigned char)(be32_to_cpup((u32*)propdata)); |
| } |
| if (lcd_debug_print_flag) { |
| EXTPR("%s: gpio_spi cs=%d, clk=%d, data=%d\n", |
| extconf->name, extconf->spi_gpio_cs, |
| extconf->spi_gpio_clk, extconf->spi_gpio_data); |
| } |
| propdata = (char *)fdt_getprop(dtaddr, nodeoffset, "spi_clk_freq", NULL); |
| if (propdata == NULL) { |
| EXTERR("get %s spi_clk_freq failed, default to %dHz\n", |
| extconf->name, LCD_EXTERN_SPI_CLK_FREQ_DFT); |
| extconf->spi_clk_freq = LCD_EXTERN_SPI_CLK_FREQ_DFT; |
| } else { |
| extconf->spi_clk_freq = be32_to_cpup((u32*)propdata); |
| } |
| propdata = (char *)fdt_getprop(dtaddr, nodeoffset, "spi_clk_pol", NULL); |
| if (propdata == NULL) { |
| EXTERR("get %s spi_clk_pol failed, default to 1\n", extconf->name); |
| extconf->spi_clk_pol = 1; |
| } else { |
| extconf->spi_clk_pol = (unsigned char)(be32_to_cpup((u32*)propdata)); |
| } |
| if (lcd_debug_print_flag) { |
| EXTPR("%s: spi clk=%dHz, clk_pol=%d\n", |
| extconf->name, extconf->spi_clk_freq, extconf->spi_clk_pol); |
| } |
| propdata = (char *)fdt_getprop(dtaddr, nodeoffset, "cmd_size", NULL); |
| if (propdata == NULL) { |
| EXTERR("get %s cmd_size failed\n", extconf->name); |
| extconf->cmd_size = 0; |
| return -1; |
| } else { |
| extconf->cmd_size = (unsigned char)(be32_to_cpup((u32*)propdata)); |
| } |
| if (lcd_debug_print_flag) |
| EXTPR("%s: cmd_size=%d\n", extconf->name, extconf->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 = aml_lcd_extern_init_table_dynamic_size_load_dts( |
| dtaddr, nodeoffset, extconf, 1); |
| if (ret) |
| break; |
| ret = aml_lcd_extern_init_table_dynamic_size_load_dts( |
| dtaddr, nodeoffset, extconf, 0); |
| } else { |
| ret = aml_lcd_extern_init_table_fixed_size_load_dts( |
| dtaddr, nodeoffset, extconf, 1); |
| if (ret) |
| break; |
| ret = aml_lcd_extern_init_table_fixed_size_load_dts( |
| dtaddr, nodeoffset, extconf, 0); |
| } |
| if (ret == 0) |
| extconf->table_init_loaded = 1; |
| break; |
| case LCD_EXTERN_MIPI: |
| propdata = (char *)fdt_getprop(dtaddr, nodeoffset, "cmd_size", NULL); |
| if (propdata == NULL) { |
| EXTERR("get %s cmd_size failed\n", extconf->name); |
| extconf->cmd_size = 0; |
| return -1; |
| } else { |
| extconf->cmd_size = (unsigned char)(be32_to_cpup((u32*)propdata)); |
| } |
| if (lcd_debug_print_flag) |
| EXTPR("%s: cmd_size=%d\n", extconf->name, extconf->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 = aml_lcd_extern_init_table_dynamic_size_load_dts( |
| dtaddr, nodeoffset, extconf, 1); |
| if (ret) |
| break; |
| ret = aml_lcd_extern_init_table_dynamic_size_load_dts( |
| dtaddr, nodeoffset, extconf, 0); |
| } |
| if (ret == 0) |
| extconf->table_init_loaded = 1; |
| break; |
| default: |
| break; |
| } |
| |
| return 0; |
| } |
| #endif |
| |
| static unsigned char aml_lcd_extern_i2c_bus_table[][2] = { |
| {LCD_EXTERN_I2C_BUS_AO, AML_I2C_MASTER_AO}, |
| {LCD_EXTERN_I2C_BUS_A, AML_I2C_MASTER_A}, |
| {LCD_EXTERN_I2C_BUS_B, AML_I2C_MASTER_B}, |
| {LCD_EXTERN_I2C_BUS_C, AML_I2C_MASTER_C}, |
| {LCD_EXTERN_I2C_BUS_D, AML_I2C_MASTER_D}, |
| }; |
| |
| static unsigned char aml_lcd_extern_get_i2c_bus_unifykey(unsigned char val) |
| { |
| unsigned char i2c_bus = LCD_EXTERN_I2C_BUS_INVALID; |
| int i; |
| |
| if (lcd_ext_i2c_bus == LCD_EXTERN_I2C_BUS_INVALID) { /* compatible for kernel3.14 */ |
| for (i = 0; i < ARRAY_SIZE(aml_lcd_extern_i2c_bus_table); i++) { |
| if (aml_lcd_extern_i2c_bus_table[i][0] == val) { |
| i2c_bus = aml_lcd_extern_i2c_bus_table[i][1]; |
| break; |
| } |
| } |
| } else { |
| i2c_bus = lcd_ext_i2c_bus; |
| } |
| if (lcd_debug_print_flag) |
| EXTPR("i2c_bus= %d\n", i2c_bus); |
| |
| return i2c_bus; |
| } |
| |
| static int aml_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 cmd_size = 0; |
| int i, j, max_len, ret = 0; |
| unsigned char *init_table, *buf; |
| char propname[20]; |
| |
| if (flag) { |
| init_table = extconf->table_init_on; |
| max_len = LCD_EXTERN_INIT_ON_MAX; |
| sprintf(propname, "init_on"); |
| buf = p; |
| } else { |
| init_table = extconf->table_init_off; |
| max_len = LCD_EXTERN_INIT_OFF_MAX; |
| sprintf(propname, "init_off"); |
| buf = p + extconf->table_init_on_cnt; |
| } |
| if (init_table == NULL) { |
| EXTPR("%s table is null\n", propname); |
| return 0; |
| } |
| |
| switch (extconf->type) { |
| case LCD_EXTERN_I2C: |
| case LCD_EXTERN_SPI: |
| i = 0; |
| while ((i + 1) < max_len) { |
| /* step1: type */ |
| len += 1; |
| ret = aml_lcd_unifykey_len_check(key_len, len); |
| if (ret) { |
| EXTERR("get %s %s failed\n", extconf->name, propname); |
| init_table[i] = LCD_EXTERN_INIT_END; |
| return -1; |
| } |
| init_table[i] = *(buf + LCD_UKEY_EXT_INIT + i); |
| if (init_table[i] == LCD_EXTERN_INIT_END) |
| break; |
| |
| /* step2: cmd_size */ |
| len += 1; |
| ret = aml_lcd_unifykey_len_check(key_len, len); |
| if (ret) { |
| EXTERR("get %s %s failed\n", extconf->name, propname); |
| init_table[i] = LCD_EXTERN_INIT_END; |
| return -1; |
| } |
| init_table[i+1] = *(buf + LCD_UKEY_EXT_INIT + i + 1); |
| cmd_size = init_table[i+1]; |
| if (cmd_size == 0) { |
| i += 2; |
| continue; |
| } |
| if ((i + 2 + cmd_size) >= max_len) { |
| EXTERR("%s %s cmd_size out of max\n", extconf->name, propname); |
| init_table[i] = LCD_EXTERN_INIT_END; |
| init_table[i+1] = 0; |
| return -1; |
| } |
| |
| /* step3: data */ |
| len += cmd_size; |
| ret = aml_lcd_unifykey_len_check(key_len, len); |
| if (ret) { |
| EXTERR("get %s %s failed\n", extconf->name, propname); |
| 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] = *(buf + LCD_UKEY_EXT_INIT + i + 2 + j); |
| |
| i += (cmd_size + 2); |
| } |
| if (flag) |
| extconf->table_init_on_cnt = i + 2; |
| |
| break; |
| case LCD_EXTERN_MIPI: |
| i = 0; |
| while ((i + 1) < max_len) { /* type & cmd_size detect */ |
| len += 1; |
| ret = aml_lcd_unifykey_len_check(key_len, len); |
| if (ret) { |
| EXTERR("get %s %s failed\n", extconf->name, propname); |
| init_table[i] = 0xff; |
| return -1; |
| } |
| init_table[i] = *(buf + LCD_UKEY_EXT_INIT + i); |
| if (init_table[i] == 0xff) { |
| len += 1; |
| ret = aml_lcd_unifykey_len_check(key_len, len); |
| if (ret) { |
| EXTERR("get %s %s failed\n", extconf->name, propname); |
| init_table[i+1] = 0xff; |
| return -1; |
| } |
| init_table[i+1] = *(buf + LCD_UKEY_EXT_INIT + i + 1); |
| cmd_size = init_table[i+1]; |
| if (cmd_size == 0xff) |
| break; |
| i += 2; |
| } else if (init_table[i] == 0xf0) { |
| len += 1; |
| ret = aml_lcd_unifykey_len_check(key_len, len); |
| if (ret) { |
| EXTERR("get %s %s failed\n", extconf->name, propname); |
| init_table[i+1] = 0xff; |
| return -1; |
| } |
| init_table[i+1] = *(buf + LCD_UKEY_EXT_INIT + i + 1); |
| cmd_size = *(buf + LCD_UKEY_EXT_INIT + i + 1); |
| if (cmd_size < 3) { |
| EXTERR("%s %s wrong cmd_size %d for gpio\n", extconf->name, propname, cmd_size); |
| return -1; |
| } |
| if ((i + 2 + cmd_size) >= max_len) { |
| EXTERR("%s %s cmd_size out of max\n", extconf->name, propname); |
| init_table[i] = 0xff; |
| init_table[i+1] = 0xff; |
| return -1; |
| } |
| len += cmd_size; |
| ret = aml_lcd_unifykey_len_check(key_len, len); |
| if (ret) { |
| EXTERR("get %s %s failed\n", extconf->name, propname); |
| 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] = *(buf + LCD_UKEY_EXT_INIT + i + 2 + j); |
| |
| i += (cmd_size + 2); |
| } else { |
| len += 1; |
| ret = aml_lcd_unifykey_len_check(key_len, len); |
| if (ret) { |
| EXTERR("get %s %s failed\n", extconf->name, propname); |
| init_table[i+1] = 0xff; |
| return -1; |
| } |
| init_table[i+1] = *(buf + LCD_UKEY_EXT_INIT + i + 1); |
| cmd_size = *(buf + LCD_UKEY_EXT_INIT + i + 1); |
| if (cmd_size == 0) { |
| i += 2; |
| continue; |
| } |
| if ((i + 2 + cmd_size) >= max_len) { |
| EXTERR("%s %s cmd_size out of max\n", extconf->name, propname); |
| init_table[i] = 0xff; |
| init_table[i+1] = 0xff; |
| return -1; |
| } |
| len += cmd_size; |
| ret = aml_lcd_unifykey_len_check(key_len, len); |
| if (ret) { |
| EXTERR("get %s %s failed\n", extconf->name, propname); |
| init_table[i] = LCD_EXTERN_INIT_END; |
| for (j = 0; j < cmd_size; j++) |
| init_table[i+2+j] = 0xff; |
| return -1; |
| } |
| for (j = 0; j < cmd_size; j++) |
| init_table[i+2+j] = *(buf + LCD_UKEY_EXT_INIT + i + 2 + j); |
| |
| i += (cmd_size + 2); |
| } |
| } |
| if (flag) |
| extconf->table_init_on_cnt = i + 2; |
| |
| break; |
| default: |
| break; |
| } |
| |
| return 0; |
| } |
| |
| static int aml_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; |
| int i, j, max_len, ret = 0; |
| unsigned char *init_table, *buf; |
| 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"); |
| buf = p; |
| } else { |
| init_table = extconf->table_init_off; |
| max_len = LCD_EXTERN_INIT_OFF_MAX; |
| sprintf(propname, "init_off"); |
| buf = p + extconf->table_init_on_cnt; |
| } |
| if (init_table == NULL) { |
| EXTPR("%s table is null\n", propname); |
| return 0; |
| } |
| |
| i = 0; |
| while (i < max_len) { |
| if ((i + cmd_size) >= max_len) { |
| EXTERR("%s %s cmd_size out of max\n", extconf->name, propname); |
| init_table[i] = LCD_EXTERN_INIT_END; |
| return -1; |
| } |
| len += cmd_size; |
| ret = aml_lcd_unifykey_len_check(key_len, len); |
| if (ret) { |
| EXTERR("get %s %s failed\n", extconf->name, propname); |
| init_table[i] = LCD_EXTERN_INIT_END; |
| return -1; |
| } |
| for (j = 0; j < cmd_size; j++) |
| init_table[i+j] = *(buf + LCD_UKEY_EXT_INIT + i + j); |
| if (init_table[i] == LCD_EXTERN_INIT_END) |
| break; |
| |
| i += cmd_size; |
| } |
| |
| if (flag) |
| extconf->table_init_on_cnt = i + cmd_size; |
| |
| return 0; |
| } |
| |
| static int aml_lcd_extern_get_config_unifykey(int index, |
| struct lcd_extern_config_s *extconf, |
| struct lcd_extern_common_s *extcommon) |
| { |
| unsigned char *para, *p; |
| int key_len, len; |
| const char *str; |
| struct aml_lcd_unifykey_header_s ext_header; |
| int ret; |
| |
| extconf->table_init_loaded = 0; |
| para = (unsigned char *)malloc(sizeof(unsigned char) * LCD_UKEY_LCD_EXT_SIZE); |
| if (!para) { |
| EXTERR("%s: Not enough memory\n", __func__); |
| return -1; |
| } |
| key_len = LCD_UKEY_LCD_EXT_SIZE; |
| memset(para, 0, (sizeof(unsigned char) * key_len)); |
| ret = aml_lcd_unifykey_get("lcd_extern", para, &key_len); |
| if (ret) { |
| free(para); |
| return -1; |
| } |
| |
| /* check lcd_extern unifykey length */ |
| len = 10 + 33 + 10; |
| ret = aml_lcd_unifykey_len_check(key_len, len); |
| if (ret) { |
| EXTERR("unifykey length is not correct\n"); |
| free(para); |
| return -1; |
| } |
| |
| /* header: 10byte */ |
| aml_lcd_unifykey_header_check(para, &ext_header); |
| if (lcd_debug_print_flag) { |
| EXTPR("unifykey header:\n"); |
| EXTPR("crc32 = 0x%08x\n", ext_header.crc32); |
| EXTPR("data_len = %d\n", ext_header.data_len); |
| EXTPR("version = 0x%04x\n", ext_header.version); |
| EXTPR("reserved = 0x%04x\n", ext_header.reserved); |
| } |
| |
| /* basic: 33byte */ |
| p = para; |
| *(p + LCD_UKEY_EXT_NAME - 1) = '\0'; /* ensure string ending */ |
| str = (const char *)(p + LCD_UKEY_HEAD_SIZE); |
| strcpy(extconf->name, str); |
| extconf->index = *(p + LCD_UKEY_EXT_INDEX); |
| extconf->type = *(p + LCD_UKEY_EXT_TYPE); |
| extconf->status = *(p + LCD_UKEY_EXT_STATUS); |
| |
| if (index != extconf->index) { |
| EXTERR("index %d err, unifykey config index %d\n", index, extconf->index); |
| free(para); |
| return -1; |
| } |
| |
| /* type: 10byte */ |
| switch (extconf->type) { |
| 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 = aml_lcd_extern_get_i2c_bus_unifykey(*(p + LCD_UKEY_EXT_TYPE_VAL_2)); |
| extcommon->i2c_sck_gpio = lcd_ext_i2c_sck_gpio; |
| extcommon->i2c_sck_gpio_off = lcd_ext_i2c_sck_gpio_off; |
| extcommon->i2c_sda_gpio = lcd_ext_i2c_sda_gpio; |
| extcommon->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"); |
| extconf->cmd_size = *(p + LCD_UKEY_EXT_TYPE_VAL_3); |
| |
| /* 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 = aml_lcd_extern_init_table_dynamic_size_load_unifykey( |
| extconf, p, key_len, len, 1); |
| if (ret) |
| break; |
| ret = aml_lcd_extern_init_table_dynamic_size_load_unifykey( |
| extconf, p, key_len, len, 0); |
| } else { |
| ret = aml_lcd_extern_init_table_fixed_size_load_unifykey( |
| extconf, p, key_len, len, 1); |
| if (ret) |
| break; |
| ret = aml_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 + LCD_UKEY_EXT_TYPE_VAL_0); |
| extconf->spi_gpio_clk = *(p + LCD_UKEY_EXT_TYPE_VAL_1); |
| extconf->spi_gpio_data = *(p + LCD_UKEY_EXT_TYPE_VAL_2); |
| extconf->spi_clk_freq = (*(p + LCD_UKEY_EXT_TYPE_VAL_3) | |
| ((*(p + LCD_UKEY_EXT_TYPE_VAL_3 + 1)) << 8) | |
| ((*(p + LCD_UKEY_EXT_TYPE_VAL_3 + 2)) << 16) | |
| ((*(p + LCD_UKEY_EXT_TYPE_VAL_3 + 3)) << 24)); |
| extconf->spi_clk_pol = *(p + LCD_UKEY_EXT_TYPE_VAL_7); |
| extconf->cmd_size = *(p + LCD_UKEY_EXT_TYPE_VAL_8); |
| |
| /* 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 = aml_lcd_extern_init_table_dynamic_size_load_unifykey( |
| extconf, p, key_len, len, 1); |
| if (ret) |
| break; |
| ret = aml_lcd_extern_init_table_dynamic_size_load_unifykey( |
| extconf, p, key_len, len, 0); |
| } else { |
| ret = aml_lcd_extern_init_table_fixed_size_load_unifykey( |
| extconf, p, key_len, len, 1); |
| if (ret) |
| break; |
| ret = aml_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: |
| extconf->cmd_size = *(p + LCD_UKEY_EXT_TYPE_VAL_0); |
| if (lcd_debug_print_flag) { |
| EXTPR("%s cmd_size=%d\n", |
| extconf->name, extconf->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 = aml_lcd_extern_init_table_dynamic_size_load_unifykey( |
| extconf, p, key_len, len, 1); |
| if (ret) |
| break; |
| ret = aml_lcd_extern_init_table_dynamic_size_load_unifykey( |
| extconf, p, key_len, len, 0); |
| } |
| if (ret == 0) |
| extconf->table_init_loaded = 1; |
| |
| break; |
| default: |
| break; |
| } |
| |
| free(para); |
| return 0; |
| } |
| |
| #ifdef CONFIG_SYS_I2C_AML |
| static int aml_lcd_extern_add_i2c(struct aml_lcd_extern_driver_s *ext_drv) |
| { |
| int ret = 0; |
| |
| if (strcmp(ext_drv->config->name, "ext_default") == 0) { |
| ret = aml_lcd_extern_default_probe(ext_drv); |
| } else if (strcmp(ext_drv->config->name, "i2c_T5800Q") == 0) { |
| #ifdef CONFIG_AML_LCD_EXTERN_I2C_T5800Q |
| ret = aml_lcd_extern_i2c_T5800Q_probe(ext_drv); |
| #endif |
| } else if (strcmp(ext_drv->config->name, "i2c_tc101") == 0) { |
| #ifdef CONFIG_AML_LCD_EXTERN_I2C_TC101 |
| ret = aml_lcd_extern_i2c_tc101_probe(ext_drv); |
| #endif |
| } else if (strcmp(ext_drv->config->name, "i2c_anx6345") == 0) { |
| #ifdef CONFIG_AML_LCD_EXTERN_I2C_ANX6345 |
| ret = aml_lcd_extern_i2c_anx6345_probe(ext_drv); |
| #endif |
| } else if (strcmp(ext_drv->config->name, "i2c_DLPC3439") == 0) { |
| #ifdef CONFIG_AML_LCD_EXTERN_I2C_DLPC3439 |
| ret = aml_lcd_extern_i2c_DLPC3439_probe(ext_drv); |
| #endif |
| } else if (strcmp(ext_drv->config->name, "i2c_RT6947") == 0) { |
| #ifdef CONFIG_AML_LCD_EXTERN_I2C_RT6947 |
| ret = aml_lcd_extern_i2c_RT6947_probe(ext_drv); |
| #endif |
| } else { |
| EXTERR("invalid driver name: %s\n", ext_drv->config->name); |
| ret = -1; |
| } |
| return ret; |
| } |
| #endif |
| |
| static int aml_lcd_extern_add_spi(struct aml_lcd_extern_driver_s *ext_drv) |
| { |
| int ret = 0; |
| |
| if (strcmp(ext_drv->config->name, "ext_default") == 0) { |
| ret = aml_lcd_extern_default_probe(ext_drv); |
| } else if (strcmp(ext_drv->config->name, "spi_LD070WS2") == 0) { |
| #ifdef CONFIG_AML_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); |
| ret = -1; |
| } |
| return ret; |
| } |
| |
| static int aml_lcd_extern_add_mipi(struct aml_lcd_extern_driver_s *ext_drv) |
| { |
| int ret = 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) { |
| #ifdef CONFIG_AML_LCD_EXTERN_MIPI_N070ICN |
| ret = aml_lcd_extern_mipi_N070ICN_probe(ext_drv); |
| #endif |
| } else if (strcmp(ext_drv->config->name, "mipi_KD080D13") == 0) { |
| #ifdef CONFIG_AML_LCD_EXTERN_MIPI_KD080D13 |
| ret = aml_lcd_extern_mipi_KD080D13_probe(ext_drv); |
| #endif |
| } else if (strcmp(ext_drv->config->name, "mipi_TV070WSM") == 0) { |
| #ifdef CONFIG_AML_LCD_EXTERN_MIPI_TV070WSM |
| ret = aml_lcd_extern_mipi_TV070WSM_probe(ext_drv); |
| #endif |
| } else if (strcmp(ext_drv->config->name, "mipi_ST7701") == 0) { |
| #ifdef CONFIG_AML_LCD_EXTERN_MIPI_ST7701 |
| ret = aml_lcd_extern_mipi_st7701_probe(ext_drv); |
| #endif |
| } else if (strcmp(ext_drv->config->name, "mipi_P070ACB") == 0) { |
| #ifdef CONFIG_AML_LCD_EXTERN_MIPI_P070ACB |
| ret = aml_lcd_extern_mipi_p070acb_probe(ext_drv); |
| #endif |
| } else if (strcmp(ext_drv->config->name, "mipi_TV070WSM_FT") == 0) { |
| #ifdef CONFIG_AML_LCD_EXTERN_MIPI_TV070WSM_FT |
| ret = aml_lcd_extern_mipi_TV070WSM_ft_probe(ext_drv); |
| #endif |
| } else if (strcmp(ext_drv->config->name, "mipi_P070ACB_FT") == 0) { |
| #ifdef CONFIG_AML_LCD_EXTERN_MIPI_P070ACB_FT |
| ret = aml_lcd_extern_mipi_p070acb_ft_probe(ext_drv); |
| #endif |
| } else if (strcmp(ext_drv->config->name, "mipi_TL050FHV02CT") == 0) { |
| #ifdef CONFIG_AML_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); |
| ret = -1; |
| } |
| return ret; |
| } |
| |
| static int aml_lcd_extern_add_invalid(struct aml_lcd_extern_driver_s *ext_drv) |
| { |
| return -1; |
| } |
| |
| static int aml_lcd_extern_add_driver(struct lcd_extern_config_s *extconf, struct lcd_extern_common_s *extcommon) |
| { |
| struct aml_lcd_extern_driver_s *ext_drv; |
| int ret = -1; |
| |
| if (extconf->status == 0) { |
| EXTERR("%s(%d) is disabled\n", extconf->name, extconf->index); |
| return -1; |
| } |
| lcd_ext_driver = (struct aml_lcd_extern_driver_s *)malloc(sizeof(struct aml_lcd_extern_driver_s)); |
| if (lcd_ext_driver == NULL) { |
| EXTERR("failed to alloc driver %s[%d], not enough memory\n", extconf->name, extconf->index); |
| return -1; |
| } |
| |
| /* fill config parameters */ |
| ext_drv = lcd_ext_driver; |
| ext_drv->config = extconf; |
| ext_drv->common = extcommon; |
| ext_drv->info_print = aml_lcd_extern_info_print; |
| |
| /* fill config parameters by different type */ |
| switch (ext_drv->config->type) { |
| case LCD_EXTERN_I2C: |
| #ifdef CONFIG_SYS_I2C_AML |
| ret = aml_lcd_extern_add_i2c(ext_drv); |
| #else |
| EXTERR("system has no i2c support\n"); |
| #endif |
| break; |
| case LCD_EXTERN_SPI: |
| ret = aml_lcd_extern_add_spi(ext_drv); |
| break; |
| case LCD_EXTERN_MIPI: |
| ret = aml_lcd_extern_add_mipi(ext_drv); |
| break; |
| default: |
| ret = aml_lcd_extern_add_invalid(ext_drv); |
| EXTERR("don't support type %d\n", ext_drv->config->type); |
| break; |
| } |
| if (ret) { |
| EXTERR("add driver failed\n"); |
| free(lcd_ext_driver); |
| lcd_ext_driver = NULL; |
| return -1; |
| } |
| |
| EXTPR("add driver %s(%d)\n", ext_drv->config->name, ext_drv->config->index); |
| return ret; |
| } |
| |
| static int aml_lcd_extern_add_driver_default(int index, struct lcd_extern_config_s *extconf, |
| struct lcd_extern_common_s *extcommon) |
| { |
| int drv_index = extconf->index; |
| int ret = -1; |
| struct aml_lcd_extern_driver_s *ext_drv; |
| |
| if (index != drv_index) { |
| EXTERR("index %d err, default config index %d\n", index, drv_index); |
| return -1; |
| } |
| |
| if (extconf->status == 0) { |
| EXTERR("%s(%d) is disabled\n", extconf->name, drv_index); |
| return -1; |
| } |
| |
| lcd_ext_driver = (struct aml_lcd_extern_driver_s *)malloc(sizeof(struct aml_lcd_extern_driver_s)); |
| if (lcd_ext_driver == NULL) { |
| EXTERR("failed to alloc driver %d, not enough memory\n", index); |
| return -1; |
| } |
| |
| ext_drv = lcd_ext_driver; |
| ext_drv->config = extconf; |
| ext_drv->common = extcommon; |
| ext_drv->config->table_init_loaded = 1; |
| ext_drv->info_print = aml_lcd_extern_info_print; |
| |
| /* add ext_default driver */ |
| if (strcmp(ext_drv->config->name, "ext_default") == 0) { |
| ret = aml_lcd_extern_default_probe(ext_drv); |
| goto add_driver_default_end; |
| } |
| if (strcmp(ext_drv->config->name, "mipi_default") == 0) { |
| ret = aml_lcd_extern_mipi_default_probe(ext_drv); |
| goto add_driver_default_end; |
| } |
| #ifdef CONFIG_SYS_I2C_AML |
| #ifdef CONFIG_AML_LCD_EXTERN_I2C_T5800Q |
| if (strcmp(ext_drv->config->name, "i2c_T5800Q") == 0) { |
| ret = aml_lcd_extern_i2c_T5800Q_probe(ext_drv); |
| goto add_driver_default_end; |
| } |
| #endif |
| #ifdef CONFIG_AML_LCD_EXTERN_I2C_TC101 |
| if (strcmp(ext_drv->config->name, "i2c_tc101") == 0) { |
| ret = aml_lcd_extern_i2c_tc101_probe(ext_drv); |
| goto add_driver_default_end; |
| } |
| #endif |
| #ifdef CONFIG_AML_LCD_EXTERN_I2C_ANX6345 |
| if (strcmp(ext_drv->config->name, "i2c_anx6345") == 0) { |
| ret = aml_lcd_extern_i2c_anx6345_probe(ext_drv); |
| goto add_driver_default_end; |
| } |
| #endif |
| #ifdef CONFIG_AML_LCD_EXTERN_I2C_DLPC3439 |
| if (strcmp(ext_drv->config->name, "i2c_DLPC3439") == 0) { |
| ret = aml_lcd_extern_i2c_DLPC3439_probe(ext_drv); |
| goto add_driver_default_end; |
| } |
| #endif |
| #ifdef CONFIG_AML_LCD_EXTERN_I2C_RT6947 |
| if (strcmp(ext_drv->config->name, "i2c_RT6947") == 0) { |
| ret = aml_lcd_extern_i2c_RT6947_probe(ext_drv); |
| goto add_driver_default_end; |
| } |
| #endif |
| #endif |
| #ifdef CONFIG_AML_LCD_EXTERN_SPI_LD070WS2 |
| if (strcmp(ext_drv->config->name, "spi_LD070WS2") == 0) { |
| ret = aml_lcd_extern_spi_LD070WS2_probe(ext_drv); |
| goto add_driver_default_end; |
| } |
| #endif |
| #ifdef CONFIG_AML_LCD_EXTERN_MIPI_N070ICN |
| if (strcmp(ext_drv->config->name, "mipi_N070ICN") == 0) { |
| ret = aml_lcd_extern_mipi_N070ICN_probe(ext_drv); |
| goto add_driver_default_end; |
| } |
| #endif |
| #ifdef CONFIG_AML_LCD_EXTERN_MIPI_KD080D13 |
| if (strcmp(ext_drv->config->name, "mipi_KD080D13") == 0) { |
| ret = aml_lcd_extern_mipi_KD080D13_probe(ext_drv); |
| goto add_driver_default_end; |
| } |
| #endif |
| #ifdef CONFIG_AML_LCD_EXTERN_MIPI_TV070WSM |
| if (strcmp(ext_drv->config->name, "mipi_TV070WSM") == 0) { |
| ret = aml_lcd_extern_mipi_TV070WSM_probe(ext_drv); |
| goto add_driver_default_end; |
| } |
| #endif |
| #ifdef CONFIG_AML_LCD_EXTERN_MIPI_ST7701 |
| if (strcmp(ext_drv->config->name, "mipi_ST7701") == 0) { |
| ret = aml_lcd_extern_mipi_st7701_probe(ext_drv); |
| goto add_driver_default_end; |
| } |
| #endif |
| #ifdef CONFIG_AML_LCD_EXTERN_MIPI_P070ACB |
| if (strcmp(ext_drv->config->name, "mipi_P070ACB") == 0) { |
| ret = aml_lcd_extern_mipi_p070acb_probe(ext_drv); |
| goto add_driver_default_end; |
| } |
| #endif |
| #ifdef CONFIG_AML_LCD_EXTERN_MIPI_TV070WSM_FT |
| if (strcmp(ext_drv->config->name, "mipi_TV070WSM_FT") == 0) { |
| ret = aml_lcd_extern_mipi_TV070WSM_ft_probe(ext_drv); |
| goto add_driver_default_end; |
| } |
| #endif |
| #ifdef CONFIG_AML_LCD_EXTERN_MIPI_P070ACB_FT |
| if (strcmp(ext_drv->config->name, "mipi_P070ACB_FT") == 0) { |
| ret = aml_lcd_extern_mipi_p070acb_ft_probe(ext_drv); |
| goto add_driver_default_end; |
| } |
| #endif |
| #ifdef CONFIG_AML_LCD_EXTERN_MIPI_TL050FHV02CT |
| if (strcmp(ext_drv->config->name, "mipi_TL050FHV02CT") == 0) { |
| ret = aml_lcd_extern_mipi_tl050fhv02ct_probe(ext_drv); |
| goto add_driver_default_end; |
| } |
| #endif |
| |
| add_driver_default_end: |
| if (ret) { |
| EXTERR("add driver failed\n"); |
| free(lcd_ext_driver); |
| lcd_ext_driver = NULL; |
| return -1; |
| } |
| EXTPR("add default driver: %s(%d)\n", ext_drv->config->name, index); |
| return ret; |
| } |
| |
| int aml_lcd_extern_probe(char *dtaddr, int index) |
| { |
| struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver(); |
| struct lcd_extern_config_s *ext_config; |
| struct lcd_extern_common_s *ext_common; |
| int ret, load_id = 0; |
| |
| if (index >= LCD_EXTERN_INDEX_INVALID) { |
| EXTERR("invalid index, %s exit\n", __func__); |
| return -1; |
| } |
| |
| dt_addr = NULL; |
| ext_common = &ext_common_dft; |
| |
| /* check dts config */ |
| #ifdef CONFIG_OF_LIBFDT |
| if (dtaddr) |
| dt_addr = dtaddr; |
| if (fdt_check_header(dtaddr) < 0) { |
| EXTERR("check dts: %s, use default parameters\n", |
| fdt_strerror(fdt_check_header(dt_addr))); |
| } else { |
| load_id = 1; |
| } |
| #endif |
| |
| if (lcd_debug_test) |
| load_id = 0; |
| |
| switch (load_id) { |
| case 1: /* dts */ |
| ext_config = &ext_config_dtf[0]; |
| ext_config->table_init_loaded = 0; |
| |
| aml_lcd_extern_get_init_dts(dtaddr, ext_common); |
| if (lcd_drv->unifykey_test_flag) { |
| ext_common->lcd_ext_key_valid = 1; |
| LCDPR("force lcd_ext_key_valid to 1\n"); |
| } |
| /* check unifykey config */ |
| if (ext_common->lcd_ext_key_valid) { |
| ret = aml_lcd_unifykey_check("lcd_extern"); |
| if (ret == 0) { |
| EXTPR("load config from unifykey\n"); |
| ret = aml_lcd_extern_get_config_unifykey(index, ext_config, ext_common); |
| if (ret == 0) |
| ret = aml_lcd_extern_add_driver(ext_config, ext_common); |
| } |
| } else { |
| EXTPR("load config from dts\n"); |
| ret = aml_lcd_extern_get_config_dts(dtaddr, index, ext_config, ext_common); |
| if (ret == 0) |
| ret = aml_lcd_extern_add_driver(ext_config, ext_common); |
| } |
| break; |
| default: /* default */ |
| if (index >= ext_common_dft.lcd_ext_num) { |
| EXTERR("invalid index %d, %s exit\n", index, __func__); |
| return -1; |
| } |
| ext_config = &ext_config_dtf[index]; |
| ext_config->table_init_loaded = 0; |
| |
| if (lcd_drv->unifykey_test_flag) { |
| ext_common->lcd_ext_key_valid = 1; |
| LCDPR("force lcd_ext_key_valid to 1\n"); |
| } |
| if (ext_common->lcd_ext_key_valid) { |
| ret = aml_lcd_unifykey_check("lcd_extern"); |
| if (ret == 0) { |
| EXTPR("load config from unifykey\n"); |
| ret = aml_lcd_extern_get_config_unifykey(index, ext_config, ext_common); |
| if (ret == 0) |
| ret = aml_lcd_extern_add_driver(ext_config, ext_common); |
| } |
| } else { |
| EXTPR("load config from bsp\n"); |
| ret = aml_lcd_extern_add_driver_default(index, ext_config, ext_common); |
| } |
| break; |
| } |
| |
| EXTPR("%s %s\n", __func__, (ret ? "failed" : "ok")); |
| return ret; |
| } |
| |
| int aml_lcd_extern_remove(void) |
| { |
| if (lcd_ext_driver) |
| free(lcd_ext_driver); |
| lcd_ext_driver = NULL; |
| return 0; |
| } |
| |