mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 11:26:02 +09:00
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:
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
133
drivers/amlogic/media/vout/backlight/bl_extern/bl_extern_i2c.c
Normal file
133
drivers/amlogic/media/vout/backlight/bl_extern/bl_extern_i2c.c
Normal 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");
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user