blob: acfba981f0956ada17374b52d2b4c40b16e32872 [file] [log] [blame]
/*
* drivers/amlogic/media/vout/lcd/lcd_extern/lcd_extern.c
*
* Copyright (C) 2015 Amlogic, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <common.h>
#include <malloc.h>
#include <dm.h>
#include <asm/gpio.h>
#include <fdtdec.h>
#include <amlogic/media/vout/lcd/aml_lcd.h>
#include <amlogic/media/vout/lcd/lcd_extern.h>
#include "lcd_extern.h"
#include "../lcd_common.h"
#include "../lcd_reg.h"
static const void *ext_dt_blob = NULL;
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 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 *table;
if (flag) {
printf("power on:\n");
table = econf->table_init_on;
max_len = econf->table_init_on_cnt;
} else {
printf("power off:\n");
table = econf->table_init_off;
max_len = econf->table_init_off_cnt;
}
if (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 (table[i] == LCD_EXT_CMD_TYPE_END) {
printf(" 0x%02x,%d,\n", table[i], table[i+1]);
break;
}
cmd_size = table[i+1];
printf(" 0x%02x,%d,", table[i], cmd_size);
if (cmd_size == 0)
goto init_table_dynamic_print_i2c_spi_next;
if (i + 2 + cmd_size > max_len) {
printf("cmd_size out of support\n");
break;
}
if ((table[i] == LCD_EXT_CMD_TYPE_GPIO) ||
(table[i] == LCD_EXT_CMD_TYPE_DELAY)) {
for (j = 0; j < cmd_size; j++)
printf("%d,", table[i+2+j]);
} else if ((table[i] == LCD_EXT_CMD_TYPE_CMD) ||
(table[i] == LCD_EXT_CMD_TYPE_CMD2)) {
for (j = 0; j < cmd_size; j++)
printf("0x%02x,", table[i+2+j]);
} else if ((table[i] == LCD_EXT_CMD_TYPE_CMD_DELAY) ||
(table[i] == LCD_EXT_CMD_TYPE_CMD2_DELAY)) {
for (j = 0; j < (cmd_size - 1); j++)
printf("0x%02x,", table[i+2+j]);
printf("%d,", table[i+cmd_size+1]);
} else {
for (j = 0; j < cmd_size; j++)
printf("0x%02x,", table[i+2+j]);
}
init_table_dynamic_print_i2c_spi_next:
printf("\n");
i += (cmd_size + 2);
}
break;
case LCD_EXTERN_MIPI:
while ((i + 1) < max_len) {
cmd_size = table[i+1];
if (table[i] == LCD_EXT_CMD_TYPE_END) {
if (cmd_size == 0xff) {
printf(" 0x%02x,0x%02x,\n",
table[i], table[i+1]);
break;
}
if (cmd_size == 0) {
printf(" 0x%02x,%d,\n",
table[i], table[i+1]);
break;
}
cmd_size = 0;
}
printf(" 0x%02x,%d,", table[i], table[i+1]);
if (cmd_size == 0)
goto init_table_dynamic_print_mipi_next;
if (i + 2 + cmd_size > max_len) {
printf("cmd_size out of support\n");
break;
}
if ((table[i] == LCD_EXT_CMD_TYPE_GPIO) ||
(table[i] == LCD_EXT_CMD_TYPE_DELAY)) {
for (j = 0; j < cmd_size; j++)
printf("%d,", table[i+2+j]);
} else if ((table[i] & 0xf) == 0x0) {
printf(" init_%s wrong data_type: 0x%02x\n",
flag ? "on" : "off", table[i]);
break;
} else {
for (j = 0; j < cmd_size; j++)
printf("0x%02x,", table[i+2+j]);
}
init_table_dynamic_print_mipi_next:
printf("\n");
i += (cmd_size + 2);
}
break;
default:
break;
}
}
static void 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 *table;
cmd_size = econf->cmd_size;
if (flag) {
printf("power on:\n");
table = econf->table_init_on;
max_len = econf->table_init_on_cnt;
} else {
printf("power off:\n");
table = econf->table_init_off;
max_len = econf->table_init_off_cnt;
}
if (table == NULL) {
EXTERR("init_table %d is NULL\n", flag);
return;
}
i = 0;
while ((i + cmd_size) <= max_len) {
printf(" ");
for (j = 0; j < cmd_size; j++)
printf("0x%02x,", table[i+j]);
printf("\n");
if (table[i] == LCD_EXT_CMD_TYPE_END)
break;
i += cmd_size;
}
}
static void 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",
econf->name, econf->index,
econf->type, econf->status);
switch (econf->type) {
case LCD_EXTERN_I2C:
printf("i2c_addr: 0x%02x\n"
"i2c_addr2: 0x%02x\n"
"i2c_bus: %d\n"
"i2c_gpio_sck: %d\n"
"i2c_gpio_sda: %d\n"
"table_loaded: %d\n",
econf->i2c_addr, econf->i2c_addr2,
ecommon->i2c_bus,
ecommon->i2c_gpio_sck,
ecommon->i2c_gpio_sda,
econf->table_init_loaded);
if (econf->cmd_size == 0)
break;
printf("init_loaded = %d\n"
"cmd_size = %d\n"
"table_init_on_cnt: = %d\n"
"table_init_off_cnt: = %d\n",
econf->table_init_loaded,
econf->cmd_size,
econf->table_init_on_cnt,
econf->table_init_off_cnt);
if (econf->cmd_size == LCD_EXT_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:
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",
ecommon->spi_gpio_cs,
ecommon->spi_gpio_clk, ecommon->spi_gpio_data,
econf->spi_clk_freq, econf->spi_clk_pol,
econf->table_init_loaded);
if (econf->cmd_size == 0)
break;
printf("init_loaded = %d\n"
"cmd_size = %d\n"
"table_init_on_cnt: = %d\n"
"table_init_off_cnt: = %d\n",
econf->table_init_loaded,
econf->cmd_size,
econf->table_init_on_cnt,
econf->table_init_off_cnt);
if (econf->cmd_size == LCD_EXT_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:
if (econf->cmd_size != LCD_EXT_CMD_SIZE_DYNAMIC)
break;
printf("init_loaded = %d\n"
"cmd_size = %d\n"
"table_init_on_cnt: = %d\n"
"table_init_off_cnt: = %d\n",
econf->table_init_loaded,
econf->cmd_size,
econf->table_init_on_cnt,
econf->table_init_off_cnt);
lcd_extern_init_table_dynamic_size_print(econf, 1);
lcd_extern_init_table_dynamic_size_print(econf, 0);
break;
default:
printf("not support extern_type\n");
break;
}
}
/* ***************************************
* lcd_extern gpio
* *************************************** */
static struct lcd_cpu_gpio_s lcd_ext_gpio[LCD_EXTERN_GPIO_NUM_MAX] = {
{.name = "invalid", .probe_flag = 0, .register_flag = 0,},
{.name = "invalid", .probe_flag = 0, .register_flag = 0,},
{.name = "invalid", .probe_flag = 0, .register_flag = 0,},
{.name = "invalid", .probe_flag = 0, .register_flag = 0,},
{.name = "invalid", .probe_flag = 0, .register_flag = 0,},
{.name = "invalid", .probe_flag = 0, .register_flag = 0,},
};
static int lcd_ext_gpio_probe(const char *name, unsigned char index)
{
if (name == NULL) {
LCDERR("bl: %s: gpio name is null\n", __func__);
return -1;
}
if (index >= LCD_EXTERN_GPIO_NUM_MAX) {
LCDERR("bl: %s: invalid gpio: %d\n", __func__, index);
return -1;
}
if (lcd_ext_gpio[index].probe_flag == 1) {
if (lcd_debug_print_flag) {
LCDPR("bl: gpio %s(%d) is already probed\n",
lcd_ext_gpio[index].name, index);
}
return 0;
}
if (lcd_debug_print_flag)
LCDPR("bl: probe gpio: %s(%d)\n", name, index);
strcpy(lcd_ext_gpio[index].name, name);
/* init gpio flag */
lcd_ext_gpio[index].probe_flag = 1;
lcd_ext_gpio[index].register_flag = 0;
return 0;
}
static int lcd_ext_gpio_request(unsigned char index)
{
int ret = 0;
if (index >= LCD_EXTERN_GPIO_NUM_MAX) {
LCDERR("bl: %s: invalid gpio: %d\n", __func__, index);
return -1;
}
if (lcd_ext_gpio[index].probe_flag == 0) {
LCDERR("bl: gpio %d is not probed\n", index);
return -1;
}
if (lcd_ext_gpio[index].register_flag == 1) {
if (lcd_debug_print_flag) {
LCDPR("bl: gpio %s(%d) is already registered\n",
lcd_ext_gpio[index].name, index);
}
return 0;
}
ret = dm_gpio_lookup_name(lcd_ext_gpio[index].name, &lcd_ext_gpio[index].gpio);
if (ret) {
LCDERR("bl: lookup gpio: wrong name %s\n", lcd_ext_gpio[index].name);
return -1;
}
ret = dm_gpio_request(&lcd_ext_gpio[index].gpio, "aml_lcd_bl");
if (ret) {
LCDERR("bl: request gpio %s(%d) failed\n", lcd_ext_gpio[index].name, index);
return -1;
}
if (lcd_debug_print_flag)
LCDPR("bl: request gpio: %s(%d)\n", lcd_ext_gpio[index].name, index);
lcd_ext_gpio[index].register_flag = 1;
return 0;
}
int lcd_ext_gpio_set(unsigned char index, int value)
{
int ret = 0;
if (index >= LCD_EXTERN_GPIO_NUM_MAX) {
LCDERR("bl: %s: invalid gpio: %d\n", __func__, index);
return -1;
}
if (lcd_ext_gpio[index].register_flag == 0) {
ret = lcd_ext_gpio_request(index);
if (ret)
return -1;
}
switch (value) {
case LCD_GPIO_OUTPUT_LOW:
ret = dm_gpio_set_dir_flags(&lcd_ext_gpio[index].gpio, GPIOD_IS_OUT);
if (ret) {
LCDERR("bl: set gpio %s(%d) direction failed\n",
lcd_ext_gpio[index].name, index);
return ret;
}
dm_gpio_set_value(&lcd_ext_gpio[index].gpio, 0);
break;
case LCD_GPIO_OUTPUT_HIGH:
ret = dm_gpio_set_dir_flags(&lcd_ext_gpio[index].gpio, GPIOD_IS_OUT);
if (ret) {
LCDERR("bl: set gpio %s(%d) direction failed\n",
lcd_ext_gpio[index].name, index);
return ret;
}
dm_gpio_set_value(&lcd_ext_gpio[index].gpio, 1);
break;
case LCD_GPIO_INPUT:
default:
ret = dm_gpio_set_dir_flags(&lcd_ext_gpio[index].gpio, GPIOD_IS_IN);
if (ret) {
LCDERR("bl: set gpio %s(%d) direction failed\n",
lcd_ext_gpio[index].name, index);
return ret;
}
break;
}
if (lcd_debug_print_flag) {
LCDPR("bl: gpio: %s(%d), value: %d\n",
lcd_ext_gpio[index].name, index, value);
}
return 0;
}
unsigned int lcd_ext_gpio_input_get(unsigned char index)
{
int ret;
unsigned int value;
if (index >= LCD_EXTERN_GPIO_NUM_MAX) {
LCDERR("%s: invalid gpio: %d\n", __func__, index);
return 0;
}
if (lcd_ext_gpio[index].register_flag == 0) {
ret = lcd_ext_gpio_request(index);
if (ret)
return 0;
}
value = dm_gpio_get_value(&lcd_ext_gpio[index].gpio);
return value;
}
/* *************************************** */
void lcd_extern_pinmux_set(int status)
{
int i;
struct lcd_extern_common_s *extcommon = lcd_ext_driver->common;
if (extcommon->pinmux_valid == 0)
return;
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 */
switch (lcd_ext_driver->config->type) {
case LCD_EXTERN_I2C:
if (extcommon->i2c_gpio_sck < LCD_EXTERN_GPIO_NUM_MAX) {
lcd_ext_gpio_set(extcommon->i2c_gpio_sck,
extcommon->pinmux_gpio_off);
}
if (extcommon->i2c_gpio_sda < LCD_EXTERN_GPIO_NUM_MAX) {
lcd_ext_gpio_set(extcommon->i2c_gpio_sda,
extcommon->pinmux_gpio_off);
}
break;
case LCD_EXTERN_SPI:
if (extcommon->spi_gpio_cs < LCD_EXTERN_GPIO_NUM_MAX) {
lcd_ext_gpio_set(extcommon->spi_gpio_cs,
extcommon->pinmux_gpio_off);
}
if (extcommon->spi_gpio_clk < LCD_EXTERN_GPIO_NUM_MAX) {
lcd_ext_gpio_set(extcommon->spi_gpio_clk,
extcommon->pinmux_gpio_off);
}
if (extcommon->spi_gpio_data < LCD_EXTERN_GPIO_NUM_MAX) {
lcd_ext_gpio_set(extcommon->spi_gpio_data,
extcommon->pinmux_gpio_off);
}
break;
default:
break;
}
}
}
static unsigned char lcd_extern_get_i2c_bus_str(const char *str)
{
unsigned char i2c_bus;
if (strncmp(str, "i2c_bus_ao", 10) == 0)
i2c_bus = LCD_EXTERN_I2C_BUS_4;
else if (strncmp(str, "i2c_bus_a", 9) == 0)
i2c_bus = LCD_EXTERN_I2C_BUS_0;
else if (strncmp(str, "i2c_bus_b", 9) == 0)
i2c_bus = LCD_EXTERN_I2C_BUS_1;
else if (strncmp(str, "i2c_bus_c", 9) == 0)
i2c_bus = LCD_EXTERN_I2C_BUS_2;
else if (strncmp(str, "i2c_bus_d", 9) == 0)
i2c_bus = LCD_EXTERN_I2C_BUS_3;
else if (strncmp(str, "i2c_bus_0", 9) == 0)
i2c_bus = LCD_EXTERN_I2C_BUS_0;
else if (strncmp(str, "i2c_bus_1", 9) == 0)
i2c_bus = LCD_EXTERN_I2C_BUS_1;
else if (strncmp(str, "i2c_bus_2", 9) == 0)
i2c_bus = LCD_EXTERN_I2C_BUS_2;
else if (strncmp(str, "i2c_bus_3", 9) == 0)
i2c_bus = LCD_EXTERN_I2C_BUS_3;
else if (strncmp(str, "i2c_bus_4", 9) == 0)
i2c_bus = LCD_EXTERN_I2C_BUS_4;
else {
i2c_bus = LCD_EXTERN_I2C_BUS_MAX;
EXTERR("invalid i2c_bus: %s\n", str);
}
return i2c_bus;
}
char *lcd_extern_get_dts_prop(int nodeoffset, char *propname)
{
char *propdata;
propdata = (char *)fdt_getprop(ext_dt_blob, nodeoffset, propname, NULL);
return propdata;
}
int 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(ext_dt_blob, chlid_node);
if (nodeoffset < 0) {
EXTERR("dts: not find node %s\n", chlid_node);
return nodeoffset;
}
propdata = (char *)fdt_getprop(ext_dt_blob, 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 lcd_extern_pinmux_load_from_bsp(struct lcd_extern_common_s *extcommon)
{
struct lcd_pinmux_ctrl_s *pinmux;
unsigned int i, j;
int set_cnt = 0, clr_cnt = 0;
if (lcd_debug_print_flag)
EXTPR("%s\n", __func__);
extcommon->pinmux_valid = 0;
if (extcommon->lcd_ext_pinmux == NULL) {
if (lcd_debug_print_flag)
LCDPR("%s: lcd_ext_pinmux is NULL for lcd.c\n", __func__);
return -1;
}
pinmux = extcommon->lcd_ext_pinmux;
for (i = 0; i < LCD_PINMX_MAX; i++) {
pinmux += i;
if (strcmp(pinmux->name, "invalid") == 0)
break;
if (strcmp(pinmux->name, "extern_on") == 0) {
for (j = 0; j < LCD_PINMUX_NUM; j++ ) {
if (pinmux->pinmux_set[j][0] == LCD_PINMUX_END)
break;
extcommon->pinmux_set[j][0] = pinmux->pinmux_set[j][0];
extcommon->pinmux_set[j][1] = pinmux->pinmux_set[j][1];
set_cnt++;
}
for (j = 0; j < LCD_PINMUX_NUM; j++ ) {
if (pinmux->pinmux_clr[j][0] == LCD_PINMUX_END)
break;
extcommon->pinmux_clr[j][0] = pinmux->pinmux_clr[j][0];
extcommon->pinmux_clr[j][1] = pinmux->pinmux_clr[j][1];
clr_cnt++;
}
if (set_cnt < LCD_PINMUX_NUM) {
extcommon->pinmux_set[set_cnt][0] = LCD_PINMUX_END;
extcommon->pinmux_set[set_cnt][1] = 0x0;
}
if (clr_cnt < LCD_PINMUX_NUM) {
extcommon->pinmux_clr[clr_cnt][0] = LCD_PINMUX_END;
extcommon->pinmux_clr[clr_cnt][1] = 0x0;
}
extcommon->pinmux_valid = 1;
break;
}
}
return 0;
}
static int lcd_extern_get_init_dts(const void *dt_blob, struct lcd_extern_common_s *extcommon)
{
int parent_offset;
char *propdata, *p;
const char *str;
int i;
parent_offset = fdt_path_offset(dt_blob, "/lcd_extern");
if (parent_offset < 0) {
EXTERR("not find /lcd_extern node: %s\n", fdt_strerror(parent_offset));
return -1;
}
propdata = (char *)fdt_getprop(dt_blob, 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(dt_blob, parent_offset, "i2c_bus", NULL);
if (propdata == NULL)
extcommon->i2c_bus = LCD_EXTERN_I2C_BUS_MAX;
else
extcommon->i2c_bus = lcd_extern_get_i2c_bus_str(propdata);
i = 0;
propdata = (char *)fdt_getprop(dt_blob, 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;
lcd_ext_gpio_probe(str, i);
i++;
}
}
propdata = (char *)fdt_getprop(dt_blob, parent_offset, "i2c_gpio", NULL);
if (propdata == NULL) {
extcommon->i2c_gpio_sck = LCD_EXT_GPIO_INVALID;
extcommon->i2c_gpio_sda = LCD_EXT_GPIO_INVALID;
} else {
extcommon->i2c_gpio_sck = (unsigned char)be32_to_cpup((u32*)propdata);
extcommon->i2c_gpio_sda = (unsigned char)be32_to_cpup((((u32*)propdata)+1));
}
propdata = (char *)fdt_getprop(dt_blob, parent_offset, "spi_gpio", NULL);
if (propdata == NULL) {
extcommon->spi_gpio_cs = LCD_EXT_GPIO_INVALID;
extcommon->spi_gpio_clk = LCD_EXT_GPIO_INVALID;
extcommon->spi_gpio_data = LCD_EXT_GPIO_INVALID;
} else {
extcommon->spi_gpio_cs = (unsigned char)be32_to_cpup((u32*)propdata);
extcommon->spi_gpio_clk = (unsigned char)be32_to_cpup((((u32*)propdata)+1));
extcommon->spi_gpio_data = (unsigned char)be32_to_cpup((((u32*)propdata)+2));
}
propdata = (char *)fdt_getprop(dt_blob, parent_offset, "pinmux_gpio_off", NULL);
if (propdata == NULL)
extcommon->pinmux_gpio_off = 2;
else
extcommon->pinmux_gpio_off = be32_to_cpup((u32*)propdata);
lcd_extern_pinmux_load_from_bsp(extcommon);
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 lcd_extern_init_table_dynamic_size_load_dts(const void *dt_blob,
int nodeoffset, struct lcd_extern_config_s *extconf, int flag)
{
unsigned char cmd_size, type;
int i = 0, j, max_len;
unsigned char *table;
char propname[20];
char *propdata;
if (flag) {
table = extconf->table_init_on;
max_len = LCD_EXTERN_INIT_ON_MAX;
sprintf(propname, "init_on");
} else {
table = extconf->table_init_off;
max_len = LCD_EXTERN_INIT_OFF_MAX;
sprintf(propname, "init_off");
}
if (table == NULL) {
EXTERR("%s init_table is null\n", propname);
return 0;
}
propdata = (char *)fdt_getprop(dt_blob, nodeoffset, propname, NULL);
if (propdata == NULL) {
EXTERR("%s: get %s failed\n", extconf->name, propname);
table[0] = LCD_EXT_CMD_TYPE_END;
table[1] = 0;
return -1;
}
switch (extconf->type) {
case LCD_EXTERN_I2C:
case LCD_EXTERN_SPI:
while ((i + 1) < max_len) {
table[i] = (unsigned char)(be32_to_cpup((((u32*)propdata)+i)));
table[i+1] = (unsigned char)(be32_to_cpup((((u32*)propdata)+i+1)));
type = table[i];
cmd_size = table[i+1];
if (type == LCD_EXT_CMD_TYPE_END)
break;
if (cmd_size == 0)
goto init_table_dynamic_i2c_spi_dts_next;
if ((i + 2 + cmd_size) > max_len) {
EXTERR("%s: %s cmd_size out of support\n", extconf->name, propname);
table[i] = LCD_EXT_CMD_TYPE_END;
table[i+1] = 0;
return -1;
}
for (j = 0; j < cmd_size; j++)
table[i+2+j] = (unsigned char)(be32_to_cpup((((u32*)propdata)+i+2+j)));
init_table_dynamic_i2c_spi_dts_next:
i += (cmd_size + 2);
}
if (flag)
extconf->table_init_on_cnt = i + 2;
else
extconf->table_init_off_cnt = i + 2;
break;
case LCD_EXTERN_MIPI:
while ((i + 1) < max_len) {
table[i] = (unsigned char)(be32_to_cpup((((u32*)propdata)+i)));
table[i+1] = (unsigned char)(be32_to_cpup((((u32*)propdata)+i+1)));
type = table[i];
cmd_size = table[i+1];
if (type == LCD_EXT_CMD_TYPE_END) {
if ((cmd_size == 0xff) || (cmd_size == 0))
break;
cmd_size = 0;
}
if (cmd_size == 0)
goto init_table_dynamic_mipi_dts_next;
if ((i + 2 + cmd_size) > max_len) {
EXTERR("%s: %s cmd_size out of support\n", extconf->name, propname);
table[i] = LCD_EXT_CMD_TYPE_END;
table[i+1] = 0;
return -1;
}
for (j = 0; j < cmd_size; j++)
table[i+2+j] = (unsigned char)(be32_to_cpup((((u32*)propdata)+i+2+j)));
init_table_dynamic_mipi_dts_next:
i += (cmd_size + 2);
}
if (flag)
extconf->table_init_on_cnt = i + 2;
else
extconf->table_init_off_cnt = i + 2;
break;
default:
break;
}
return 0;
}
static int lcd_extern_init_table_fixed_size_load_dts(const void *dt_blob,
int nodeoffset, struct lcd_extern_config_s *extconf, int flag)
{
unsigned char cmd_size;
int i = 0, j, max_len;
unsigned char *table;
char propname[20];
char *propdata;
cmd_size = extconf->cmd_size;
if (flag) {
table = extconf->table_init_on;
max_len = LCD_EXTERN_INIT_ON_MAX;
sprintf(propname, "init_on");
} else {
table = extconf->table_init_off;
max_len = LCD_EXTERN_INIT_OFF_MAX;
sprintf(propname, "init_off");
}
if (table == NULL) {
EXTPR("%s init_table is null\n", propname);
return 0;
}
propdata = (char *)fdt_getprop(dt_blob, nodeoffset, propname, NULL);
if (propdata == NULL) {
EXTERR("%s: get %s failed\n", extconf->name, propname);
table[0] = LCD_EXT_CMD_TYPE_END;
table[1] = 0;
return -1;
}
while (i < max_len) {
if ((i + cmd_size) > max_len) {
EXTERR("%s: %s cmd_size out of support\n", extconf->name, propname);
table[i] = LCD_EXT_CMD_TYPE_END;
return -1;
}
for (j = 0; j < cmd_size; j++)
table[i+j] = (unsigned char)(be32_to_cpup((((u32*)propdata)+i+j)));
if (table[i] == LCD_EXT_CMD_TYPE_END)
break;
i += cmd_size;
}
if (flag)
extconf->table_init_on_cnt = i + cmd_size;
else
extconf->table_init_off_cnt = i + cmd_size;
return 0;
}
static int lcd_extern_get_config_dts(const void *dt_blob, 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 = lcd_extern_get_dts_child(index);
if (nodeoffset < 0)
return -1;
propdata = (char *)fdt_getprop(dt_blob, 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(dt_blob, 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(dt_blob, 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(dt_blob, 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:
propdata = (char *)fdt_getprop(dt_blob, nodeoffset, "i2c_address", NULL);
if (propdata == NULL) {
EXTERR("%s: get 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(dt_blob, nodeoffset, "i2c_address2", NULL);
if (propdata == NULL) {
propdata = (char *)fdt_getprop(dt_blob, nodeoffset, "i2c_second_address", NULL);
if (propdata == NULL) {
if (lcd_debug_print_flag)
EXTPR("%s no i2c_address2 exist\n", extconf->name);
extconf->i2c_addr2 = 0xff;
} else {
extconf->i2c_addr2 = (unsigned char)(be32_to_cpup((u32*)propdata));
}
} else {
extconf->i2c_addr2 = (unsigned char)(be32_to_cpup((u32*)propdata));
}
if (lcd_debug_print_flag)
EXTPR("%s: i2c_address2=0x%02x\n", extconf->name, extconf->i2c_addr2);
extconf->i2c_bus = extcommon->i2c_bus;
if (lcd_debug_print_flag)
lcd_extern_i2c_bus_print(extconf->i2c_bus);
if ((extcommon->i2c_gpio_sck < LCD_EXTERN_GPIO_NUM_MAX) &&
(extcommon->i2c_gpio_sda < LCD_EXTERN_GPIO_NUM_MAX)) {
EXTPR("%s: find spi_gpio config: sck=%d, sda=%d\n",
extconf->name,
extcommon->i2c_gpio_sck, extcommon->i2c_gpio_sda);
}
propdata = (char *)fdt_getprop(dt_blob, nodeoffset, "cmd_size", NULL);
if (propdata == NULL) {
EXTPR("%s: no cmd_size\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 == 0)
break;
if (extconf->cmd_size == LCD_EXT_CMD_SIZE_DYNAMIC) {
ret = lcd_extern_init_table_dynamic_size_load_dts(
dt_blob, nodeoffset, extconf, 1);
if (ret)
break;
ret = lcd_extern_init_table_dynamic_size_load_dts(
dt_blob, nodeoffset, extconf, 0);
} else {
ret = lcd_extern_init_table_fixed_size_load_dts(
dt_blob, nodeoffset, extconf, 1);
if (ret)
break;
ret = lcd_extern_init_table_fixed_size_load_dts(
dt_blob, nodeoffset, extconf, 0);
}
if (ret == 0)
extconf->table_init_loaded = 1;
break;
case LCD_EXTERN_SPI:
if ((extcommon->spi_gpio_cs < LCD_EXTERN_GPIO_NUM_MAX) &&
(extcommon->spi_gpio_clk < LCD_EXTERN_GPIO_NUM_MAX) &&
(extcommon->spi_gpio_data < LCD_EXTERN_GPIO_NUM_MAX)) {
EXTPR("%s: find spi_gpio config: cs=%d, clk=%d, data=%d\n",
extconf->name, extcommon->spi_gpio_cs,
extcommon->spi_gpio_clk, extcommon->spi_gpio_data);
} else {
EXTERR("%s: get spi_gpio failed\n", extconf->name);
}
propdata = (char *)fdt_getprop(dt_blob, nodeoffset, "spi_clk_freq", NULL);
if (propdata == NULL) {
EXTERR("%s: get spi_clk_freq failed, default to %dKHz\n",
extconf->name, LCD_EXT_SPI_CLK_FREQ_DFT);
extconf->spi_clk_freq = LCD_EXT_SPI_CLK_FREQ_DFT;
} else {
extconf->spi_clk_freq = be32_to_cpup((u32*)propdata);
}
propdata = (char *)fdt_getprop(dt_blob, nodeoffset, "spi_clk_pol", NULL);
if (propdata == NULL) {
EXTERR("%s: get 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=%dKHz, clk_pol=%d\n",
extconf->name, extconf->spi_clk_freq, extconf->spi_clk_pol);
}
propdata = (char *)fdt_getprop(dt_blob, nodeoffset, "cmd_size", NULL);
if (propdata == NULL) {
EXTPR("%s: no cmd_size\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 == 0)
break;
if (extconf->cmd_size == LCD_EXT_CMD_SIZE_DYNAMIC) {
ret = lcd_extern_init_table_dynamic_size_load_dts(
dt_blob, nodeoffset, extconf, 1);
if (ret)
break;
ret = lcd_extern_init_table_dynamic_size_load_dts(
dt_blob, nodeoffset, extconf, 0);
} else {
ret = lcd_extern_init_table_fixed_size_load_dts(
dt_blob, nodeoffset, extconf, 1);
if (ret)
break;
ret = lcd_extern_init_table_fixed_size_load_dts(
dt_blob, nodeoffset, extconf, 0);
}
if (ret == 0)
extconf->table_init_loaded = 1;
break;
case LCD_EXTERN_MIPI:
propdata = (char *)fdt_getprop(dt_blob, nodeoffset, "cmd_size", NULL);
if (propdata == NULL) {
EXTPR("%s: no cmd_size\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 == 0)
break;
if (extconf->cmd_size == LCD_EXT_CMD_SIZE_DYNAMIC) {
ret = lcd_extern_init_table_dynamic_size_load_dts(
dt_blob, nodeoffset, extconf, 1);
if (ret)
break;
ret = lcd_extern_init_table_dynamic_size_load_dts(
dt_blob, nodeoffset, extconf, 0);
if (ret == 0)
extconf->table_init_loaded = 1;
}
break;
default:
break;
}
return 0;
}
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 cmd_size = 0;
int i = 0, j, max_len, ret = 0;
unsigned char *table, *buf;
char propname[20];
if (flag) {
table = extconf->table_init_on;
max_len = LCD_EXTERN_INIT_ON_MAX;
sprintf(propname, "init_on");
buf = p;
} else {
table = extconf->table_init_off;
max_len = LCD_EXTERN_INIT_OFF_MAX;
sprintf(propname, "init_off");
buf = p + extconf->table_init_on_cnt;
}
if (table == NULL) {
EXTPR("%s init_table is null\n", propname);
return 0;
}
switch (extconf->type) {
case LCD_EXTERN_I2C:
case LCD_EXTERN_SPI:
while ((i + 1) < max_len) {
/* type */
len += 1;
ret = aml_lcd_unifykey_len_check(key_len, len);
if (ret) {
EXTERR("%s: get %s failed\n", extconf->name, propname);
table[i] = LCD_EXT_CMD_TYPE_END;
table[i+1] = 0;
return -1;
}
table[i] = *(buf + LCD_UKEY_EXT_INIT + i);
/* cmd_size */
len += 1;
ret = aml_lcd_unifykey_len_check(key_len, len);
if (ret) {
EXTERR("%s: get %s failed\n", extconf->name, propname);
table[i] = LCD_EXT_CMD_TYPE_END;
table[i+1] = 0;
return -1;
}
table[i+1] = *(buf + LCD_UKEY_EXT_INIT + i + 1);
cmd_size = table[i+1];
if (table[i] == LCD_EXT_CMD_TYPE_END)
break;
if (cmd_size == 0)
goto init_table_dynamic_i2c_spi_ukey_next;
if ((i + 2 + cmd_size) > max_len) {
EXTERR("%s: %s cmd_size out of support\n", extconf->name, propname);
table[i] = LCD_EXT_CMD_TYPE_END;
table[i+1] = 0;
return -1;
}
/* data */
len += cmd_size;
ret = aml_lcd_unifykey_len_check(key_len, len);
if (ret) {
EXTERR("%s: get %s failed\n", extconf->name, propname);
table[i] = LCD_EXT_CMD_TYPE_END;
table[i+1] = 0;
return -1;
}
for (j = 0; j < cmd_size; j++)
table[i+2+j] = *(buf + LCD_UKEY_EXT_INIT + i + 2 + j);
init_table_dynamic_i2c_spi_ukey_next:
i += (cmd_size + 2);
}
if (flag)
extconf->table_init_on_cnt = i + 2;
else
extconf->table_init_off_cnt = i + 2;
break;
case LCD_EXTERN_MIPI:
while ((i + 1) < max_len) { /* type & cmd_size detect */
/* type */
len += 1;
ret = aml_lcd_unifykey_len_check(key_len, len);
if (ret) {
EXTERR("%s: get %s failed\n", extconf->name, propname);
table[i] = LCD_EXT_CMD_TYPE_END;
table[i+1] = 0;
return -1;
}
table[i] = *(buf + LCD_UKEY_EXT_INIT + i);
/* type */
len += 1;
ret = aml_lcd_unifykey_len_check(key_len, len);
if (ret) {
EXTERR("%s: get %s failed\n", extconf->name, propname);
table[i] = LCD_EXT_CMD_TYPE_END;
table[i+1] = 0;
return -1;
}
table[i+1] = *(buf + LCD_UKEY_EXT_INIT + i + 1);
cmd_size = table[i+1];
if (table[i] == LCD_EXT_CMD_TYPE_END) {
if ((cmd_size == 0xff) || (cmd_size == 0))
break;
cmd_size = 0;
}
if (cmd_size == 0)
goto init_table_dynamic_mipi_ukey_next;
if ((i + 2 + cmd_size) > max_len) {
EXTERR("%s: %s cmd_size out of support\n", extconf->name, propname);
table[i] = LCD_EXT_CMD_TYPE_END;
table[i+1] = 0;
break;
}
len += cmd_size;
ret = aml_lcd_unifykey_len_check(key_len, len);
if (ret) {
EXTERR("%s: get %s failed\n", extconf->name, propname);
table[i] = LCD_EXT_CMD_TYPE_END;
table[i+1] = 0;
return -1;
}
for (j = 0; j < cmd_size; j++)
table[i+2+j] = *(buf + LCD_UKEY_EXT_INIT + i + 2 + j);
init_table_dynamic_mipi_ukey_next:
i += (cmd_size + 2);
}
if (flag)
extconf->table_init_on_cnt = i + 2;
else
extconf->table_init_off_cnt = i + 2;
break;
default:
break;
}
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;
int i = 0, j, max_len, ret = 0;
unsigned char *table, *buf;
char propname[20];
cmd_size = extconf->cmd_size;
if (flag) {
table = extconf->table_init_on;
max_len = LCD_EXTERN_INIT_ON_MAX;
sprintf(propname, "init_on");
buf = p;
} else {
table = extconf->table_init_off;
max_len = LCD_EXTERN_INIT_OFF_MAX;
sprintf(propname, "init_off");
buf = p + extconf->table_init_on_cnt;
}
if (table == NULL) {
EXTPR("%s init_table is null\n", propname);
return 0;
}
while (i < max_len) {
if ((i + cmd_size) > max_len) {
EXTERR("%s: %s cmd_size out of support\n", extconf->name, propname);
table[i] = LCD_EXT_CMD_TYPE_END;
return -1;
}
len += cmd_size;
ret = aml_lcd_unifykey_len_check(key_len, len);
if (ret) {
EXTERR("%s: get %s failed\n", extconf->name, propname);
table[i] = LCD_EXT_CMD_TYPE_END;
return -1;
}
for (j = 0; j < cmd_size; j++)
table[i+j] = *(buf + LCD_UKEY_EXT_INIT + i + j);
if (table[i] == LCD_EXT_CMD_TYPE_END)
break;
i += cmd_size;
}
if (flag)
extconf->table_init_on_cnt = i + cmd_size;
else
extconf->table_init_off_cnt = i + cmd_size;
return 0;
}
static int 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 = extcommon->i2c_bus;
if (lcd_debug_print_flag)
lcd_extern_i2c_bus_print(extconf->i2c_bus);
if ((extcommon->i2c_gpio_sck < LCD_EXTERN_GPIO_NUM_MAX) &&
(extcommon->i2c_gpio_sda < LCD_EXTERN_GPIO_NUM_MAX)) {
EXTPR("%s: find spi_gpio config: sck=%d, sda=%d\n",
extconf->name,
extcommon->i2c_gpio_sck, extcommon->i2c_gpio_sda);
}
extconf->cmd_size = *(p + LCD_UKEY_EXT_TYPE_VAL_3);
if (lcd_debug_print_flag) {
EXTPR("%s: cmd_size = %d\n",
extconf->name, extconf->cmd_size);
}
/* init */
if (extconf->cmd_size == 0)
break;
if (extconf->cmd_size == LCD_EXT_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:
if ((extcommon->spi_gpio_cs < LCD_EXTERN_GPIO_NUM_MAX) &&
(extcommon->spi_gpio_clk < LCD_EXTERN_GPIO_NUM_MAX) &&
(extcommon->spi_gpio_data < LCD_EXTERN_GPIO_NUM_MAX)) {
EXTPR("%s: find spi_gpio config: cs=%d, clk=%d, data=%d\n",
extconf->name, extcommon->spi_gpio_cs,
extcommon->spi_gpio_clk, extcommon->spi_gpio_data);
} else {
EXTERR("%s: get spi_gpio failed\n", extconf->name);
}
extconf->spi_clk_freq = (*(p + LCD_UKEY_EXT_TYPE_VAL_3) |
((*(p + LCD_UKEY_EXT_TYPE_VAL_4)) << 8));
extconf->spi_clk_pol = *(p + LCD_UKEY_EXT_TYPE_VAL_5);
extconf->cmd_size = *(p + LCD_UKEY_EXT_TYPE_VAL_6);
if (lcd_debug_print_flag) {
EXTPR("%s: cmd_size = %d\n",
extconf->name, extconf->cmd_size);
}
/* init */
if (extconf->cmd_size == 0)
break;
if (extconf->cmd_size == LCD_EXT_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:
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 == 0)
break;
if (extconf->cmd_size == LCD_EXT_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);
}
if (ret == 0)
extconf->table_init_loaded = 1;
break;
default:
break;
}
free(para);
return 0;
}
static int lcd_extern_get_init_default(const void *dt_blob,
struct lcd_extern_common_s *extcommon)
{
int i = 0;
while (i < LCD_EXTERN_GPIO_NUM_MAX) {
if (strcmp(extcommon->gpio_name[i], "invalid") == 0)
break;
lcd_ext_gpio_probe(extcommon->gpio_name[i], i);
i++;
}
return 0;
}
static int lcd_extern_add_i2c(struct aml_lcd_extern_driver_s *ext_drv)
{
int ret = -1;
if (strcmp(ext_drv->config->name, "ext_default") == 0) {
if (ext_drv->config->cmd_size < 2) {
EXTERR("%s: cmd_size %d is invalid\n",
ext_drv->config->name, ext_drv->config->cmd_size);
} else {
ret = lcd_extern_default_probe(ext_drv);
}
} else if (strcmp(ext_drv->config->name, "i2c_T5800Q") == 0) {
#ifdef CONFIG_AML_LCD_EXTERN_I2C_T5800Q
ret = lcd_extern_i2c_T5800Q_probe(ext_drv);
#endif
} else if (strcmp(ext_drv->config->name, "i2c_DLPC3439") == 0) {
#ifdef CONFIG_AML_LCD_EXTERN_I2C_DLPC3439
ret = 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 = lcd_extern_i2c_RT6947_probe(ext_drv);
#endif
} else if (strcmp(ext_drv->config->name, "i2c_ANX6862_7911") == 0) {
#ifdef CONFIG_AML_LCD_EXTERN_I2C_ANX6862_7911
ret = lcd_extern_i2c_ANX6862_7911_probe(ext_drv);
#endif
} else {
EXTERR("invalid driver name: %s\n", ext_drv->config->name);
}
return ret;
}
static int lcd_extern_add_spi(struct aml_lcd_extern_driver_s *ext_drv)
{
int ret = -1;
if (strcmp(ext_drv->config->name, "ext_default") == 0) {
if (ext_drv->config->cmd_size < 2) {
EXTERR("%s: cmd_size %d is invalid\n",
ext_drv->config->name, ext_drv->config->cmd_size);
} else {
ret = lcd_extern_default_probe(ext_drv);
}
} else if (strcmp(ext_drv->config->name, "spi_LD070WS2") == 0) {
#ifdef CONFIG_AML_LCD_EXTERN_SPI_LD070WS2
ret = lcd_extern_spi_LD070WS2_probe(ext_drv);
#endif
} else {
EXTERR("invalid driver name: %s\n", ext_drv->config->name);
}
return ret;
}
static int lcd_extern_add_mipi(struct aml_lcd_extern_driver_s *ext_drv)
{
int ret = -1;
if ((strcmp(ext_drv->config->name, "mipi_default") == 0) ||
strcmp(ext_drv->config->name, "ext_default") == 0) {
if (ext_drv->config->cmd_size != LCD_EXT_CMD_SIZE_DYNAMIC) {
EXTERR("%s: cmd_size %d is invalid\n",
ext_drv->config->name, ext_drv->config->cmd_size);
} else {
ret = lcd_extern_mipi_default_probe(ext_drv);
}
} else if (strcmp(ext_drv->config->name, "mipi_TV070WSM") == 0) {
#ifdef CONFIG_AML_LCD_EXTERN_MIPI_TV070WSM
ret = lcd_extern_mipi_TV070WSM_probe(ext_drv);
#endif
} else if (strcmp(ext_drv->config->name, "mipi_P070ACB") == 0) {
#ifdef CONFIG_AML_LCD_EXTERN_MIPI_P070ACB
ret = lcd_extern_mipi_p070acb_probe(ext_drv);
#endif
} else if (strcmp(ext_drv->config->name, "mipi_ST7701") == 0) {
#ifdef CONFIG_AML_LCD_EXTERN_MIPI_ST7701
ret = lcd_extern_mipi_st7701_probe(ext_drv);
#endif
} else if (strcmp(ext_drv->config->name, "mipi_TL050FHV02CT") == 0) {
#ifdef CONFIG_AML_LCD_EXTERN_MIPI_TL050FHV02CT
ret = lcd_extern_mipi_tl050fhv02ct_probe(ext_drv);
#endif
} else {
EXTERR("invalid driver name: %s\n", ext_drv->config->name);
}
return ret;
}
static int 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 = lcd_extern_info_print;
ext_drv->reg_read = NULL;
ext_drv->reg_write = NULL;
ext_drv->power_on = NULL;
ext_drv->power_off = NULL;
/* fill config parameters by different type */
switch (ext_drv->config->type) {
case LCD_EXTERN_I2C:
ret = lcd_extern_add_i2c(ext_drv);
break;
case LCD_EXTERN_SPI:
ret = lcd_extern_add_spi(ext_drv);
break;
case LCD_EXTERN_MIPI:
ret = lcd_extern_add_mipi(ext_drv);
break;
default:
ret = -1;
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;
}
#ifdef BL33_DEBUG_PRINT
EXTPR("add driver %s(%d)\n", ext_drv->config->name, ext_drv->config->index);
#endif
return ret;
}
static int 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 = lcd_extern_info_print;
ext_drv->reg_read = NULL;
ext_drv->reg_write = NULL;
ext_drv->power_on = NULL;
ext_drv->power_off = NULL;
/* add ext_default driver */
if (strcmp(ext_drv->config->name, "ext_default") == 0) {
ret = lcd_extern_default_probe(ext_drv);
} else if ((strcmp(ext_drv->config->name, "mipi_default") == 0) ||
(strcmp(ext_drv->config->name, "ext_default") == 0)) {
ret = lcd_extern_mipi_default_probe(ext_drv);
} else if (strcmp(ext_drv->config->name, "i2c_T5800Q") == 0) {
#ifdef CONFIG_AML_LCD_EXTERN_I2C_T5800Q
ret = lcd_extern_i2c_T5800Q_probe(ext_drv);
#endif
} else if (strcmp(ext_drv->config->name, "i2c_DLPC3439") == 0) {
#ifdef CONFIG_AML_LCD_EXTERN_I2C_DLPC3439
ret = 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 = lcd_extern_i2c_RT6947_probe(ext_drv);
#endif
} else if (strcmp(ext_drv->config->name, "i2c_ANX6862_7911") == 0) {
#ifdef CONFIG_AML_LCD_EXTERN_I2C_ANX6862_7911
ret = lcd_extern_i2c_ANX6862_7911_probe(ext_drv);
#endif
} else if (strcmp(ext_drv->config->name, "spi_LD070WS2") == 0) {
#ifdef CONFIG_AML_LCD_EXTERN_SPI_LD070WS2
ret = lcd_extern_spi_LD070WS2_probe(ext_drv);
#endif
} else if (strcmp(ext_drv->config->name, "mipi_TV070WSM") == 0) {
#ifdef CONFIG_AML_LCD_EXTERN_MIPI_TV070WSM
ret = lcd_extern_mipi_TV070WSM_probe(ext_drv);
#endif
} else if (strcmp(ext_drv->config->name, "mipi_P070ACB") == 0) {
#ifdef CONFIG_AML_LCD_EXTERN_MIPI_P070ACB
ret = lcd_extern_mipi_p070acb_probe(ext_drv);
#endif
} else if (strcmp(ext_drv->config->name, "mipi_ST7701") == 0) {
#ifdef CONFIG_AML_LCD_EXTERN_MIPI_ST7701
ret = lcd_extern_mipi_st7701_probe(ext_drv);
#endif
} else if (strcmp(ext_drv->config->name, "mipi_TL050FHV02CT") == 0) {
#ifdef CONFIG_AML_LCD_EXTERN_MIPI_TL050FHV02CT
ret = lcd_extern_mipi_tl050fhv02ct_probe(ext_drv);
#endif
} else {
EXTERR("invalid driver name: %s\n", ext_drv->config->name);
}
if (ret) {
EXTERR("add default driver failed: %s(%d)\n", ext_drv->config->name, index);
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(const void *dt_blob, 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;
}
ext_dt_blob = NULL;
ext_common = &ext_common_dft;
ext_config = &ext_config_dtf;
/* check dts config */
if (dt_blob)
ext_dt_blob = dt_blob;
ret = fdt_check_header(ext_dt_blob);
if (ret) {
EXTERR("check dts: %s, use default parameters\n",
fdt_strerror(ret));
} else {
load_id = 1;
}
if (lcd_debug_load_flag)
load_id = 0;
switch (load_id) {
case 1: /* dts */
ext_config->table_init_on_cnt = 0;
ext_config->table_init_off_cnt = 0;
ext_config->table_init_loaded = 0;
lcd_extern_get_init_dts(ext_dt_blob, 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 = lcd_extern_get_config_unifykey(index,
ext_config, ext_common);
}
} else {
#ifdef BL33_DEBUG_PRINT
EXTPR("load config from dts\n");
#endif
ret = lcd_extern_get_config_dts(ext_dt_blob, index,
ext_config, ext_common);
}
if (ret == 0)
ret = lcd_extern_add_driver(ext_config, ext_common);
break;
default: /* default */
ext_config->table_init_loaded = 0;
ext_config->i2c_bus = ext_common->i2c_bus;
lcd_extern_get_init_default(ext_dt_blob, ext_common);
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 = lcd_extern_get_config_unifykey(index,
ext_config, ext_common);
if (ret == 0)
ret = lcd_extern_add_driver(ext_config, ext_common);
}
} else {
EXTPR("load config from bsp\n");
ret = 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;
}