blob: fe8d49875275a17ebab49d80a98b6b09fab2e762 [file] [log] [blame]
/*
* drivers/display/lcd/bl_extern/i2c_lp8556.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_bl_extern.h>
#include "bl_extern.h"
#include "../aml_lcd_common.h"
#include "../aml_lcd_reg.h"
//#define BL_EXT_I2C_PORT_INIT /* no need init i2c port here */
//#define BL_EXT_DEBUG_INFO
#ifdef CONFIG_SYS_I2C_AML
#define BL_EXTERN_INDEX 1
#define BL_EXTERN_NAME "i2c_lp8556"
#define BL_EXTERN_TYPE BL_EXTERN_I2C
#define BL_EXTERN_I2C_ADDR (0x58 >> 1) //7bit address
#define BL_EXTERN_I2C_BUS AML_I2C_MASTER_C
#ifdef BL_EXT_I2C_PORT_INIT
static unsigned aml_i2c_bus_tmp;
#endif
static unsigned int bl_status = 0;
#define BL_EXTERN_CMD_SIZE 4
static unsigned char init_on_table[] = {
0x00, 0xa2, 0x20, 0x00,
0x00, 0xa5, 0x54, 0x00,
0x00, 0x00, 0xff, 0x00,
0x00, 0x01, 0x05, 0x00,
0x00, 0xa2, 0x20, 0x00,
0x00, 0xa5, 0x54, 0x00,
0x00, 0xa1, 0xb7, 0x00,
0x00, 0xa0, 0xff, 0x00,
0x00, 0x00, 0x80, 0x00,
0xff, 0x00, 0x00, 0x00, //ending
};
static unsigned char init_off_table[] = {
0xFF, 0x00, 0x00, 0x00, //ending
};
static int i2c_lp8556_write(unsigned i2caddr, unsigned char *buff, unsigned len)
{
int ret = 0;
#ifdef BL_EXT_DEBUG_INFO
int i;
#endif
struct i2c_msg msg;
msg.addr = i2caddr;
msg.flags = 0;
msg.len = len;
msg.buf = buff;
#ifdef BL_EXT_DEBUG_INFO
printf("%s:", __func__);
for (i = 0; i < len; i++) {
printf(" 0x%02x", buff[i]);
}
printf(" [addr 0x%02x]\n", i2caddr);
#endif
ret = aml_i2c_xfer(&msg, 1);
//ret = aml_i2c_xfer_slow(&msg, 1);
if (ret < 0)
BLEXERR("i2c write failed [addr 0x%02x]\n", i2caddr);
return ret;
}
static int i2c_lp8556_power_cmd(unsigned char *init_table)
{
int len;
int i = 0;
int ret = 0;
struct aml_bl_extern_driver_s *bl_extern = aml_bl_extern_get_driver();
len = BL_EXTERN_CMD_SIZE;
while (i <= BL_EXTERN_INIT_TABLE_MAX) {
if (init_table[i] == BL_EXTERN_INIT_END) {
break;
} else if (init_table[i] == BL_EXTERN_INIT_NONE) {
//do nothing, only for delay
} else if (init_table[i] == BL_EXTERN_INIT_CMD) {
ret = i2c_lp8556_write(bl_extern->config->i2c_addr,
&init_table[i+1], (len-2));
} else {
BLEXERR("%s(%d: %s): pwoer_type %d is invalid\n",
__func__, bl_extern->config->index,
bl_extern->config->name, bl_extern->config->type);
}
if (init_table[i+len-1] > 0)
mdelay(init_table[i+len-1]);
i += len;
}
return ret;
}
#ifdef BL_EXT_I2C_PORT_INIT
static int bl_extern_change_i2c_bus(unsigned aml_i2c_bus)
{
int ret = 0;
extern struct aml_i2c_platform g_aml_i2c_plat;
if (aml_i2c_bus == BL_EXTERN_I2C_BUS_INVALID) {
BLEXERR("%s: invalid i2c_bus\n", __func__);
return -1;
}
g_aml_i2c_plat.master_no = aml_i2c_bus;
ret = aml_i2c_init();
return ret;
}
#endif
static int i2c_lp8556_power_ctrl(int flag)
{
#ifdef BL_EXT_I2C_PORT_INIT
extern struct aml_i2c_platform g_aml_i2c_plat;
aml_i2c_bus_tmp = g_aml_i2c_plat.master_no;
#endif
struct aml_bl_extern_driver_s *bl_extern = aml_bl_extern_get_driver();
int ret = 0;
if (bl_status) {
/* step 1: power prepare */
#ifdef BL_EXT_I2C_PORT_INIT
bl_extern_change_i2c_bus(bl_extern->i2c_bus);
#endif
/* step 2: power cmd */
if (flag)
ret = i2c_lp8556_power_cmd(init_on_table);
else
ret = i2c_lp8556_power_cmd(init_off_table);
/* step 3: power finish */
#ifdef BL_EXT_I2C_PORT_INIT
bl_extern_change_i2c_bus(aml_i2c_bus_tmp);
#endif
}
BLEX("%s(%d: %s): %d\n",
__func__, bl_extern->config->index,
bl_extern->config->name, flag);
return ret;
}
static int i2c_lp8556_power_on(void)
{
int ret;
bl_status = 1;
ret = i2c_lp8556_power_ctrl(1);
return ret;
}
static int i2c_lp8556_power_off(void)
{
int ret;
bl_status = 0;
ret = i2c_lp8556_power_ctrl(0);
return ret;
}
static int i2c_lp8556_set_level(unsigned int level)
{
unsigned char tData[3];
int ret = 0;
struct aml_lcd_drv_s *bl_drv = aml_lcd_get_driver();
struct aml_bl_extern_driver_s *bl_extern = aml_bl_extern_get_driver();
unsigned int level_max, level_min;
unsigned int dim_max, dim_min;
if (bl_drv == NULL)
return -1;
level_max = bl_drv->bl_config->level_max;
level_min = bl_drv->bl_config->level_min;
dim_max = bl_extern->config->dim_max;
dim_min = bl_extern->config->dim_min;
level = dim_min - ((level - level_min) * (dim_min - dim_max)) /
(level_max - level_min);
level &= 0xff;
if (bl_status) {
tData[0] = 0x0;
tData[1] = level;
ret = i2c_lp8556_write(bl_extern->config->i2c_addr,
tData, 2);
}
return ret;
}
static int i2c_lp8556_update(void)
{
struct aml_bl_extern_driver_s *bl_extern = aml_bl_extern_get_driver();
if (bl_extern == NULL) {
BLEXERR("%s driver is null\n", BL_EXTERN_NAME);
return -1;
}
if (bl_extern->config->type == BL_EXTERN_MAX) {
bl_extern->config->index = BL_EXTERN_INDEX;
bl_extern->config->type = BL_EXTERN_TYPE;
strcpy(bl_extern->config->name, BL_EXTERN_NAME);
bl_extern->config->i2c_addr = BL_EXTERN_I2C_ADDR;
bl_extern->config->i2c_bus = BL_EXTERN_I2C_BUS;
}
bl_extern->device_power_on = i2c_lp8556_power_on;
bl_extern->device_power_off = i2c_lp8556_power_off;
bl_extern->device_bri_update = i2c_lp8556_set_level;
return 0;
}
int i2c_lp8556_probe(void)
{
int ret = 0;
ret = i2c_lp8556_update();
if (lcd_debug_print_flag)
BLEX("%s: %d\n", __func__, ret);
return ret;
}
#endif