diff --git a/MAINTAINERS b/MAINTAINERS index fddd11e6af54..c04a47906f8b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14360,3 +14360,7 @@ F: drivers/amlogic/thermal/meson_cooldev.c AMLOGIC G12A Audio DRIVER M: Xing Wang F: sound/soc/amlogic/auge/* + +AMLOGIC G12A BL_EXTERN LP8556 DRIVER +M: Weiming Liu +F: drivers/amlogic/media/vout/backlight/bl_extern/bl_extern_i2c.c diff --git a/arch/arm64/boot/dts/amlogic/g12a_skt.dts b/arch/arm64/boot/dts/amlogic/g12a_skt.dts index ac2304a569d2..596f1be31085 100644 --- a/arch/arm64/boot/dts/amlogic/g12a_skt.dts +++ b/arch/arm64/boot/dts/amlogic/g12a_skt.dts @@ -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 { diff --git a/arch/arm64/boot/dts/amlogic/mesong12a_skt-panel.dtsi b/arch/arm64/boot/dts/amlogic/mesong12a_skt-panel.dtsi index c589e0137e8c..8f6946abbea1 100644 --- a/arch/arm64/boot/dts/amlogic/mesong12a_skt-panel.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesong12a_skt-panel.dtsi @@ -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) diff --git a/drivers/amlogic/media/vout/backlight/bl_extern/Makefile b/drivers/amlogic/media/vout/backlight/bl_extern/Makefile index 5f71c1bbb1a0..b386c737ef68 100644 --- a/drivers/amlogic/media/vout/backlight/bl_extern/Makefile +++ b/drivers/amlogic/media/vout/backlight/bl_extern/Makefile @@ -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 diff --git a/drivers/amlogic/media/vout/backlight/bl_extern/bl_extern.c b/drivers/amlogic/media/vout/backlight/bl_extern/bl_extern.c index f3f75ccdf055..4a4e99740ebc 100644 --- a/drivers/amlogic/media/vout/backlight/bl_extern/bl_extern.c +++ b/drivers/amlogic/media/vout/backlight/bl_extern/bl_extern.c @@ -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; diff --git a/drivers/amlogic/media/vout/backlight/bl_extern/bl_extern_i2c.c b/drivers/amlogic/media/vout/backlight/bl_extern/bl_extern_i2c.c new file mode 100644 index 000000000000..e9eb1f06c1b7 --- /dev/null +++ b/drivers/amlogic/media/vout/backlight/bl_extern/bl_extern_i2c.c @@ -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 +#include +#include +#include +#include +#include +#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"); + diff --git a/drivers/amlogic/media/vout/backlight/bl_extern/i2c_lp8556.c b/drivers/amlogic/media/vout/backlight/bl_extern/i2c_lp8556.c index e3b4aedc3cf5..d2141533b2d0 100644 --- a/drivers/amlogic/media/vout/backlight/bl_extern/i2c_lp8556.c +++ b/drivers/amlogic/media/vout/backlight/bl_extern/i2c_lp8556.c @@ -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(); diff --git a/drivers/amlogic/media/vout/lcd/lcd_clk_config.c b/drivers/amlogic/media/vout/lcd/lcd_clk_config.c index 992718fb5cbc..0dc5f7ba6d0b 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_clk_config.c +++ b/drivers/amlogic/media/vout/lcd/lcd_clk_config.c @@ -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); diff --git a/include/linux/amlogic/media/vout/lcd/aml_bl_extern.h b/include/linux/amlogic/media/vout/lcd/aml_bl_extern.h index 8f8fac3c5d9e..5a6b489df529 100644 --- a/include/linux/amlogic/media/vout/lcd/aml_bl_extern.h +++ b/include/linux/amlogic/media/vout/lcd/aml_bl_extern.h @@ -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);