bl_extern: add lp8556 driver
authorweiming.liu <weiming.liu@amlogic.com>
Wed, 7 Feb 2018 06:37:33 +0000 (14:37 +0800)
committerYixun Lan <yixun.lan@amlogic.com>
Mon, 5 Mar 2018 07:34:34 +0000 (15:34 +0800)
PD#156734: bl_extern: add lp8556 driver

Change-Id: Id38b698cbc87a227abdcd52037c65df87fc8d654
Signed-off-by: weiming.liu <weiming.liu@amlogic.com>
MAINTAINERS
arch/arm64/boot/dts/amlogic/g12a_skt.dts
arch/arm64/boot/dts/amlogic/mesong12a_skt-panel.dtsi
drivers/amlogic/media/vout/backlight/bl_extern/Makefile
drivers/amlogic/media/vout/backlight/bl_extern/bl_extern.c
drivers/amlogic/media/vout/backlight/bl_extern/bl_extern_i2c.c [new file with mode: 0644]
drivers/amlogic/media/vout/backlight/bl_extern/i2c_lp8556.c
drivers/amlogic/media/vout/lcd/lcd_clk_config.c
include/linux/amlogic/media/vout/lcd/aml_bl_extern.h

index fddd11e..c04a479 100644 (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
index ac2304a..596f1be 100644 (file)
                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 {
                };
        };
 
-       bl_pwm_on_pins: bl_pwm_on_pin {
-               mux {
-                       groups = "pwm_f_h";
-                       function = "pwm_f";
-               };
-       };
 
 }; /* end of pinctrl_periphs */
 &pinctrl_aobus {
index c589e01..8f6946a 100644 (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";
 
                        /* 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>;
                };
                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)
index 5f71c1b..b386c73 100644 (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
 
index f3f75cc..4a4e997 100644 (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;
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 (file)
index 0000000..e9eb1f0
--- /dev/null
@@ -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");
+
index e3b4aed..d214153 100644 (file)
 #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__);
+
+       if (i2c_dev == NULL) {
+               BLEXERR("invalid i2c device\n");
+               return -1;
+       }
 
-       ret = i2c_transfer(i2client->adapter, msg, 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();
 
index 992718f..0dc5f7b 100644 (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);
index 8f8fac3..5a6b489 100644 (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);