bl_extern: add lp8556 driver

PD#156734: bl_extern: add lp8556 driver

Change-Id: Id38b698cbc87a227abdcd52037c65df87fc8d654
Signed-off-by: weiming.liu <weiming.liu@amlogic.com>
This commit is contained in:
weiming.liu
2018-02-07 14:37:33 +08:00
committed by Yixun Lan
parent d56113f2b7
commit 9fc3e6cb44
9 changed files with 210 additions and 106 deletions

View File

@@ -14360,3 +14360,7 @@ F: drivers/amlogic/thermal/meson_cooldev.c
AMLOGIC G12A Audio DRIVER
M: Xing Wang <xing.wang@amlogic.com>
F: sound/soc/amlogic/auge/*
AMLOGIC G12A BL_EXTERN LP8556 DRIVER
M: Weiming Liu <weiming.liu@amlogic.com>
F: drivers/amlogic/media/vout/backlight/bl_extern/bl_extern_i2c.c

View File

@@ -1351,6 +1351,13 @@
reset_pin = <&gpio GPIOA_5 0>;
};
bl_extern_i2c {
compatible = "amlogic, bl_extern_i2c";
status = "disabled";
reg = <0x2c>; /*reg_address for lp8556*/
dev_name = "lp8556";
};
};
&audiobus {
@@ -1625,12 +1632,6 @@
};
};
bl_pwm_on_pins: bl_pwm_on_pin {
mux {
groups = "pwm_f_h";
function = "pwm_f";
};
};
}; /* end of pinctrl_periphs */
&pinctrl_aobus {

View File

@@ -43,8 +43,9 @@
* power value:(0=output low, 1=output high, 2=input)
* power delay:(unit in ms)
*/
lcd_cpu-gpios = <&gpio GPIOZ_8 GPIO_ACTIVE_HIGH>;
lcd_cpu_gpio_names = "GPIOZ_8";
lcd_cpu-gpios = <&gpio GPIOZ_9 GPIO_ACTIVE_HIGH
&gpio GPIOZ_8 GPIO_ACTIVE_HIGH>;
lcd_cpu_gpio_names = "GPIOZ_9","GPIOZ_8";
lcd_0{
model_name = "B080XAN01";
@@ -86,13 +87,15 @@
/* power step: type, index, value, delay(ms) */
power_on_step = <
0 1 0 100
0 0 0 10
0 0 1 20
2 0 0 0
0xff 0 0 0>; /*ending*/
power_off_step = <
2 0 0 50
0 0 0 100
0 0 0 10
0 1 1 100
0xff 0 0 0>; /*ending*/
backlight_index = <0>;
};
@@ -280,7 +283,7 @@
status = "okay";
key_valid = <0>;
pinctrl-names = "pwm_on";
pinctrl-0 = <&bl_pwm_on_pins>; /*pwm_f_pins2*/
pinctrl-0 = <&pwm_f_pins2>;
pinctrl_version = <2>; /* for uboot */
/* pwm port: PWM_A, PWM_B, PWM_C, PWM_D, PWM_E, PWM_F, PWM_VS*/
/* power index:(point gpios_index, 0xff=invalid)

View File

@@ -1,5 +1,5 @@
obj-$(CONFIG_AMLOGIC_BL_EXTERN) += bl_extern.o
obj-$(CONFIG_AMLOGIC_BL_EXTERN) += bl_extern.o bl_extern_i2c.o
obj-$(CONFIG_AMLOGIC_BL_EXTERN_I2C_LP8556) += i2c_lp8556.o
obj-$(CONFIG_AMLOGIC_BL_EXTERN_MIPI_LT070ME05) += mipi_lt070me05.o

View File

@@ -118,6 +118,7 @@ static unsigned char bl_extern_get_i2c_bus_str(const char *str)
static void bl_extern_config_print(void)
{
struct aml_bl_extern_driver_s *bl_extern = aml_bl_extern_get_driver();
struct aml_bl_extern_i2c_dev_s *i2c_dev = aml_bl_extern_i2c_get_dev();
BLEX("%s:\n", __func__);
switch (bl_extern->config.type) {
@@ -136,6 +137,16 @@ static void bl_extern_config_print(void)
bl_extern->config.i2c_bus,
bl_extern->config.dim_min,
bl_extern->config.dim_max);
if (i2c_dev) {
pr_info("i2c_dev_name: %s\n"
"i2c_client_name: %s\n"
"i2c_client_addr: 0x%02x\n",
i2c_dev->name,
i2c_dev->client->name,
i2c_dev->client->addr);
} else {
pr_info("invalid i2c device\n");
}
break;
case BL_EXTERN_SPI:
break;

View File

@@ -0,0 +1,133 @@
/*
* drivers/amlogic/media/vout/backlight/bl_extern/bl_extern_i2c.c
*
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/slab.h>
#include <linux/amlogic/i2c-amlogic.h>
#include <linux/amlogic/media/vout/lcd/aml_bl_extern.h>
#include "bl_extern.h"
static struct aml_bl_extern_i2c_dev_s *i2c_device;
struct aml_bl_extern_i2c_dev_s *aml_bl_extern_i2c_get_dev(void)
{
return i2c_device;
}
static int bl_extern_i2c_config_from_dts(struct device *dev,
struct aml_bl_extern_i2c_dev_s *i2c_device)
{
int ret;
struct device_node *np = dev->of_node;
const char *str;
ret = of_property_read_string(np, "dev_name", &str);
if (ret) {
BLEXERR("failed to get dev_i2c_name\n");
str = "bl_extern_i2c_name";
}
strcpy(i2c_device->name, str);
return 0;
}
static int aml_bl_extern_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
BLEX("I2C Address: 0x%02x", client->addr);
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
BLEXERR("I2C check functionality failed.");
return -ENODEV;
}
i2c_device = kzalloc(sizeof(struct aml_bl_extern_i2c_dev_s),
GFP_KERNEL);
if (!i2c_device) {
BLEXERR("driver malloc error\n");
return -ENOMEM;
}
i2c_device->client = client;
bl_extern_i2c_config_from_dts(&client->dev, i2c_device);
return 0;
}
static int aml_bl_extern_i2c_remove(struct i2c_client *client)
{
kfree(i2c_device);
i2c_set_clientdata(client, NULL);
return 0;
}
static const struct i2c_device_id aml_bl_extern_i2c_id[] = {
{"bl_extern_i2c", 0},
{}
};
#ifdef CONFIG_OF
static const struct of_device_id aml_bl_extern_i2c_dt_match[] = {
{
.compatible = "amlogic, bl_extern_i2c",
},
{},
};
#endif
static struct i2c_driver aml_bl_extern_i2c_driver = {
.probe = aml_bl_extern_i2c_probe,
.remove = aml_bl_extern_i2c_remove,
.id_table = aml_bl_extern_i2c_id,
.driver = {
.name = "bl_extern_i2c",
.owner = THIS_MODULE,
#ifdef CONFIG_OF
.of_match_table = aml_bl_extern_i2c_dt_match,
#endif
},
};
static int __init aml_bl_extern_i2c_init(void)
{
int ret;
if (lcd_debug_print_flag)
BLEX("%s\n", __func__);
ret = i2c_add_driver(&aml_bl_extern_i2c_driver);
if (ret) {
BLEXERR("driver register failed\n");
return -ENODEV;
}
return ret;
}
static void __exit aml_bl_extern_i2c_exit(void)
{
i2c_del_driver(&aml_bl_extern_i2c_driver);
}
module_init(aml_bl_extern_i2c_init);
module_exit(aml_bl_extern_i2c_exit);
MODULE_AUTHOR("AMLOGIC");
MODULE_DESCRIPTION("bl extern driver");
MODULE_LICENSE("GPL");

View File

@@ -37,17 +37,17 @@
#define BL_EXTERN_CMD_SIZE 4
static unsigned int bl_status;
static struct i2c_client *i2c_lp8556_client;
static unsigned char init_on_table[] = {
0x00, 0xa1, 0x76, 0x00,//hight bit(8~11)(0~0X66e set backlight)
0x00, 0xa0, 0x66, 0x00,//low bit(0~7) 20mA
0x00, 0x16, 0x1F, 0x00,// 5channel LED enable 0x1F
0x00, 0xa9, 0xA0, 0x00,//VBOOST_MAX 25V
0x00, 0x9e, 0x12, 0x00,
0x00, 0xa2, 0x23, 0x00,
/*0x03 pwm+I2c set brightness,0x5 I2c set brightness*/
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
};
@@ -55,22 +55,30 @@ static unsigned char init_off_table[] = {
0xff, 0x00, 0x00, 0x00, //ending
};
static int i2c_lp8556_write(struct i2c_client *i2client,
unsigned char *buff, unsigned int len)
static int i2c_lp8556_write(unsigned char *buff, unsigned int len)
{
int ret = 0;
struct aml_bl_extern_i2c_dev_s *i2c_dev = aml_bl_extern_i2c_get_dev();
struct i2c_msg msg[] = {
{
.addr = i2client->addr,
.addr = i2c_dev->client->addr,
.flags = 0,
.len = len,
.buf = buff,
}
};
BLEX("%s\n", __func__);
ret = i2c_transfer(i2client->adapter, msg, 1);
if (i2c_dev == NULL) {
BLEXERR("invalid i2c device\n");
return -1;
}
ret = i2c_transfer(i2c_dev->client->adapter, msg, 1);
if (ret < 0)
BLEXERR("i2c write failed [addr 0x%02x]\n", i2client->addr);
BLEXERR("i2c write failed [addr 0x%02x]\n",
i2c_dev->client->addr);
return ret;
}
@@ -80,6 +88,7 @@ static int i2c_lp8556_power_cmd(unsigned char *init_table)
int i = 0, len;
int ret = 0;
struct aml_bl_extern_driver_s *bl_extern = aml_bl_extern_get_driver();
BLEX("%s\n", __func__);
len = BL_EXTERN_CMD_SIZE;
while (i <= BL_EXTERN_INIT_TABLE_MAX) {
@@ -88,7 +97,7 @@ static int i2c_lp8556_power_cmd(unsigned char *init_table)
} 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(i2c_lp8556_client,
ret = i2c_lp8556_write(
&init_table[i+1], (len-2));
} else {
BLEXERR("%s(%d: %s): power_type %d is invalid\n",
@@ -107,6 +116,7 @@ static int i2c_lp8556_power_ctrl(int flag)
{
int ret = 0;
struct aml_bl_extern_driver_s *bl_extern = aml_bl_extern_get_driver();
BLEX("%s\n", __func__);
if (flag)
ret = i2c_lp8556_power_cmd(init_on_table);
@@ -122,6 +132,7 @@ static int i2c_lp8556_power_ctrl(int flag)
static int i2c_lp8556_power_on(void)
{
int ret;
BLEX("%s\n", __func__);
bl_status = 1;
ret = i2c_lp8556_power_ctrl(1);
@@ -162,7 +173,7 @@ static int i2c_lp8556_set_level(unsigned int level)
if (bl_status) {
tData[0] = 0x0;
tData[1] = level;
ret = i2c_lp8556_write(i2c_lp8556_client, tData, 2);
ret = i2c_lp8556_write(tData, 2);
}
return ret;
}
@@ -189,83 +200,9 @@ static int i2c_lp8556_update(void)
return 0;
}
static int bl_extern_i2c_lp8556_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
BLEXERR("%s: functionality check failed\n", __func__);
else
i2c_lp8556_client = client;
BLEX("%s OK\n", __func__);
return 0;
}
static int bl_extern_i2c_lp8556_remove(struct i2c_client *client)
{
return 0;
}
static const struct i2c_device_id bl_extern_i2c_lp8556_id[] = {
{BL_EXTERN_NAME, 0},
{ }
};
static struct i2c_driver i2c_lp8556_driver = {
.probe = bl_extern_i2c_lp8556_probe,
.remove = bl_extern_i2c_lp8556_remove,
.id_table = bl_extern_i2c_lp8556_id,
.driver = {
.name = BL_EXTERN_NAME,
.owner = THIS_MODULE,
},
};
int i2c_lp8556_probe(void)
{
int ret = 0;
struct i2c_board_info i2c_info;
struct i2c_adapter *adapter;
struct i2c_client *i2c_client;
struct aml_bl_extern_driver_s *bl_extern = aml_bl_extern_get_driver();
memset(&i2c_info, 0, sizeof(i2c_info));
adapter = i2c_get_adapter(bl_extern->config.i2c_bus);
if (!adapter) {
BLEXERR("%s failed to get i2c adapter\n",
bl_extern->config.name);
return -1;
}
strncpy(i2c_info.type, bl_extern->config.name, I2C_NAME_SIZE);
i2c_info.addr = bl_extern->config.i2c_addr;
i2c_info.platform_data = &bl_extern->config;
i2c_info.flags = 0;
if (i2c_info.addr > 0x7f) {
BLEXERR("%s invalid i2c address: 0x%02x\n",
bl_extern->config.name, bl_extern->config.i2c_addr);
return -1;
}
i2c_client = i2c_new_device(adapter, &i2c_info);
if (!i2c_client) {
BLEXERR("%s failed to new i2c device\n",
bl_extern->config.name);
} else {
if (lcd_debug_print_flag) {
BLEX("%s new i2c device succeed\n",
bl_extern->config.name);
}
}
if (!i2c_lp8556_client) {
ret = i2c_add_driver(&i2c_lp8556_driver);
if (ret) {
BLEXERR("%s add i2c_driver failed\n",
bl_extern->config.name);
return -1;
}
}
ret = i2c_lp8556_update();

View File

@@ -770,7 +770,7 @@ static void lcd_pll_reset_g12a(void)
static void lcd_set_pll_g12a(struct lcd_clk_config_s *cConf)
{
unsigned int pll_ctrl, pll_ctrl1;
unsigned int pll_ctrl, pll_ctrl1, pll_ctrl3, pll_ctrl4, pll_ctrl6;
int ret;
if (lcd_debug_print_flag == 2)
@@ -780,16 +780,25 @@ static void lcd_set_pll_g12a(struct lcd_clk_config_s *cConf)
(cConf->pll_n << LCD_PLL_N_G12A) |
(cConf->pll_m << LCD_PLL_M_G12A) |
(cConf->pll_od1_sel << LCD_PLL_OD_G12A));
pll_ctrl1 = 0x00;
/*pll_ctrl1 |= ((1 << 19) | (cConf->pll_frac << 0));*/
pll_ctrl1 = (cConf->pll_frac << 0);
if (cConf->pll_frac) {
pll_ctrl |= (1 << 27);
pll_ctrl3 = 0x6a295c00;
pll_ctrl4 = 0x65771290;
pll_ctrl6 = 0x54540000;
} else {
pll_ctrl3 = 0x08691c00;
pll_ctrl4 = 0x33771290;
pll_ctrl6 = 0x50540000;
}
lcd_hiu_write(HHI_GP0_PLL_CNTL0_G12A, pll_ctrl);
lcd_hiu_write(HHI_GP0_PLL_CNTL1_G12A, pll_ctrl1);
lcd_hiu_write(HHI_GP0_PLL_CNTL2_G12A, 0x00);
lcd_hiu_write(HHI_GP0_PLL_CNTL3_G12A, 0x08691c00);
lcd_hiu_write(HHI_GP0_PLL_CNTL4_G12A, 0x33771290);
lcd_hiu_write(HHI_GP0_PLL_CNTL3_G12A, pll_ctrl3);
lcd_hiu_write(HHI_GP0_PLL_CNTL4_G12A, pll_ctrl4);
lcd_hiu_write(HHI_GP0_PLL_CNTL5_G12A, 0x39272000);
lcd_hiu_write(HHI_GP0_PLL_CNTL6_G12A, 0x50540000);
lcd_hiu_write(HHI_GP0_PLL_CNTL6_G12A, pll_ctrl6);
lcd_hiu_setb(HHI_GP0_PLL_CNTL0_G12A, 1, LCD_PLL_RST_G12A, 1);
udelay(100);
lcd_hiu_setb(HHI_GP0_PLL_CNTL0_G12A, 0, LCD_PLL_RST_G12A, 1);

View File

@@ -72,6 +72,12 @@ struct aml_bl_extern_driver_s {
struct device *dev;
};
struct aml_bl_extern_i2c_dev_s {
char name[20];
struct i2c_client *client;
};
extern struct aml_bl_extern_i2c_dev_s *aml_bl_extern_i2c_get_dev(void);
extern struct aml_bl_extern_driver_s *aml_bl_extern_get_driver(void);
extern int aml_bl_extern_device_load(int index);