backlight: ldim: add analog pwm support [1/1]
authorEvoke Zhang <evoke.zhang@amlogic.com>
Thu, 3 Jan 2019 11:40:26 +0000 (06:40 -0500)
committerJianxin Pan <jianxin.pan@amlogic.com>
Mon, 7 Jan 2019 11:02:58 +0000 (03:02 -0800)
PD#SWPL-3702

Problem:
local dimming need analog pwm function

Solution:
add analog pwm support

Verify:
x301

Change-Id: I502bb7505947c1f3670f44d0d307f9546f1d57fd
Signed-off-by: Evoke Zhang <evoke.zhang@amlogic.com>
15 files changed:
arch/arm/boot/dts/amlogic/mesontl1_t309-panel.dtsi
arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi
arch/arm/boot/dts/amlogic/mesontxlx_r311-panel.dtsi
arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts
arch/arm64/boot/dts/amlogic/mesontl1_t309-panel.dtsi
arch/arm64/boot/dts/amlogic/mesontl1_x301-panel.dtsi
arch/arm64/boot/dts/amlogic/mesontxlx_r311-panel.dtsi
drivers/amlogic/media/vout/backlight/aml_bl.c
drivers/amlogic/media/vout/backlight/aml_ldim/global_bl.c
drivers/amlogic/media/vout/backlight/aml_ldim/iw7027_bl.c
drivers/amlogic/media/vout/backlight/aml_ldim/ldim_dev_drv.c
drivers/amlogic/media/vout/backlight/aml_ldim/ldim_drv.h
drivers/amlogic/media/vout/backlight/aml_ldim/ob3350_bl.c
include/linux/amlogic/media/vout/lcd/aml_bl.h
include/linux/amlogic/media/vout/lcd/aml_ldim.h

index 79fa79d..7aa829b 100644 (file)
                        bl_level_attr = <255 10 /*max, min*/
                                128 128>; /*mid, mid_mapping*/
                        bl_ctrl_method = <3>; /*1=pwm,2=pwm_combo,3=ldim*/
-                       bl_power_attr = <0 /*en_gpio_index*/
+                       bl_power_attr = <0xff /*en_gpio_index*/
                                1 0  /*on_value, off_value*/
                                200 200>; /*on_delay(ms), off_delay(ms)*/
                        bl_ldim_region_row_col = <1 1>;
                                             */
                        ldim_dev_index = <1>;
                };
+               backlight_5{
+                       index = <5>;
+                       bl_name = "ldim_iw7027";
+                       bl_level_default_uboot_kernel = <100 100>;
+                       bl_level_attr = <255 10 /*max, min*/
+                               128 128>; /*mid, mid_mapping*/
+                       bl_ctrl_method = <3>; /*1=pwm,2=pwm_combo,3=ldim*/
+                       bl_power_attr = <0 /*en_gpio_index*/
+                               1 0  /*on_value, off_value*/
+                               200 200>; /*on_delay(ms), off_delay(ms)*/
+                       bl_ldim_region_row_col = <1 10>;
+                       bl_ldim_mode = <1>; /*0=left/right side
+                                            *1=top/bottom side
+                                            *2=direct
+                                            */
+                       ldim_dev_index = <2>;
+               };
        };
 
        bl_pwm_conf:bl_pwm_conf{
                status = "okay";
                pinctrl-names = "ldim_pwm",
                        "ldim_pwm_vs",
-                       "ldim_pwm_off";
+                       "ldim_pwm_combo",
+                       "ldim_pwm_vs_combo",
+                       "ldim_pwm_off",
+                       "ldim_pwm_combo_off";
                pinctrl-0 = <&pwm_c_pins3>;
                pinctrl-1 = <&bl_pwm_vs_on_pins>;
-               pinctrl-2 = <&bl_pwm_off_pins>;
+               pinctrl-2 = <&pwm_c_pins3 &pwm_d_pins2>;
+               pinctrl-3 = <&bl_pwm_vs_on_pins &pwm_d_pins2>;
+               pinctrl-4 = <&bl_pwm_off_pins>;
+               pinctrl-5 = <&bl_pwm_combo_off_pins>;
                pinctrl_version = <1>; /* for uboot */
                ldim_pwm_config = <&bl_pwm_conf>;
 
                        index = <0>;
                        type = <0>; /*0=normal, 1=spi, 2=i2c*/
                        ldim_dev_name = "ob3350";
-                       ldim_pwm_pinmux_sel = "ldim_pwm";
-                       ldim_pwm_port = "PWM_B";
+                       ldim_pwm_port = "PWM_C";
                        ldim_pwm_attr = <0 /* pol */
                                200 /*freq(pwm:Hz, pwm_vs:multiple of vs)*/
-                               50>;/*duty(%)*/
-                       dim_max_min = <100 20>; /*dim_max, dim_min*/
+                               50>;/*default duty(%)*/
                        en_gpio_on_off = <0 /*ldim_dev-gpios index*/
                                1 0>; /*on_level, off_level*/
+                       dim_max_min = <100 20>; /*dim_max, dim_min*/
                };
                ldim_dev_1 {
                        index = <1>;
                        type = <0>; /*0=normal, 1=spi, 2=i2c*/
                        ldim_dev_name = "global";
-                       ldim_pwm_pinmux_sel = "ldim_pwm";
                        ldim_pwm_port = "PWM_C";
                        ldim_pwm_attr = <1 /* pol */
                                180 /*freq(pwm:Hz, pwm_vs:multiple of vs)*/
-                               50>;/*duty(%)*/
-                       dim_max_min = <100 20>; /*dim_max, dim_min*/
-                       en_gpio_on_off = <2 /*ldim_dev-gpios index*/
+                               50>;/*default duty(%)*/
+                       analog_pwm_port = "PWM_D";
+                       analog_pwm_attr = <1 /*pol(0=negative, 1=positvie)*/
+                               18000 /*freq(pwm:Hz)*/
+                               100 25 /*duty_max(%), duty_min(%)*/
+                               80>;   /*default duty(%)*/
+                       en_gpio_on_off = <0 /*ldim_dev-gpios index*/
                                1 0>; /*on_level, off_level*/
+                       dim_max_min = <100 20>; /*dim_max, dim_min*/
                };
-       };
 
+               ldim_dev_2 {
+                       index = <2>;
+                       type = <1>; /* 0=normal,1=spi,2=i2c */
+                       ldim_dev_name = "iw7027";
+                       ldim_pwm_port = "PWM_VS";
+                       ldim_pwm_attr = <1  /* pol */
+                               2 /*freq(pwm:Hz, pwm_vs:multiple of vs)*/
+                               50>;/*default duty(%)*/
+                       spi_bus_num = <0>;
+                       spi_chip_select = <0>;
+                       spi_max_frequency = <1000000>; /* unit: hz */
+                       spi_mode = <0>; /* mode: 0, 1, 2, 3 */
+                       spi_cs_delay = <10  /* hold_high_delay */
+                               100>; /* clk_cs_delay (unit: us) */
+                       en_gpio_on_off = <0 /* ldim_dev-gpios index */
+                               1 /* on_level */
+                               0>; /* off_level */
+                       lamp_err_gpio = <0xff>;
+                               /* ldim_dev-gpios index, 0xff=invalid */
+                       spi_write_check = <0>; /* 0=disable, 1=enable */
+
+                       dim_max_min = <0xfff 0x7f>; /* dim_max, dim_min */
+                       ldim_region_mapping = <0 1 2 3 4 5 6 7 8 9>;
+
+                       cmd_size = <0xff>;
+                       /* init: (type, data...) */
+                       /*   type: 0x00=cmd with delay,
+                        *         0xc0=cmd,
+                        *         0xfd=delay,
+                        *         0xff=ending
+                        */
+                       /*   data: spi data, fill 0x0 for no use */
+                       /*   delay: unit ms */
+                       init_on = <
+                               0xc0 2 0x23 0x03
+                               0xc0 2 0x24 0xff
+                               0xc0 2 0x25 0x00
+                               0xc0 2 0x26 0x00
+                               0xc0 2 0x27 0x60
+                               0xc0 2 0x29 0x00
+                               0xc0 2 0x2a 0x00
+                               0xc0 2 0x2b 0x00
+                               0xc0 2 0x2c 0x73
+                               0xc0 2 0x2d 0x37
+                               0xc0 2 0x31 0x93
+                               0xc0 2 0x32 0x0f
+                               0xc0 2 0x33 0xff
+                               0xc0 2 0x34 0xc8
+                               0xc0 2 0x35 0xbf
+                               0xff 0>;
+                       init_off = <0xff 0>;
+               };
+       };
 }; /* end of / */
index 15c01c2..80d78cc 100644 (file)
                        bl_level_attr = <255 10 /*max, min*/
                                128 128>; /*mid, mid_mapping*/
                        bl_ctrl_method = <3>; /*1=pwm,2=pwm_combo,3=ldim*/
-                       bl_power_attr = <0 /*en_gpio_index*/
+                       bl_power_attr = <0xff /*en_gpio_index*/
                                1 0  /*on_value, off_value*/
                                200 200>; /*on_delay(ms), off_delay(ms)*/
                        bl_ldim_region_row_col = <1 1>;
                                             */
                        ldim_dev_index = <1>;
                };
+               backlight_5{
+                       index = <5>;
+                       bl_name = "ldim_iw7027";
+                       bl_level_default_uboot_kernel = <100 100>;
+                       bl_level_attr = <255 10 /*max, min*/
+                               128 128>; /*mid, mid_mapping*/
+                       bl_ctrl_method = <3>; /*1=pwm,2=pwm_combo,3=ldim*/
+                       bl_power_attr = <0 /*en_gpio_index*/
+                               1 0  /*on_value, off_value*/
+                               200 200>; /*on_delay(ms), off_delay(ms)*/
+                       bl_ldim_region_row_col = <1 10>;
+                       bl_ldim_mode = <1>; /*0=left/right side
+                                            *1=top/bottom side
+                                            *2=direct
+                                            */
+                       ldim_dev_index = <2>;
+               };
        };
 
        bl_pwm_conf:bl_pwm_conf{
                status = "okay";
                pinctrl-names = "ldim_pwm",
                        "ldim_pwm_vs",
-                       "ldim_pwm_off";
+                       "ldim_pwm_combo",
+                       "ldim_pwm_vs_combo",
+                       "ldim_pwm_off",
+                       "ldim_pwm_combo_off";
                pinctrl-0 = <&pwm_c_pins3>;
                pinctrl-1 = <&bl_pwm_vs_on_pins>;
-               pinctrl-2 = <&bl_pwm_off_pins>;
+               pinctrl-2 = <&pwm_c_pins3 &pwm_d_pins2>;
+               pinctrl-3 = <&bl_pwm_vs_on_pins &pwm_d_pins2>;
+               pinctrl-4 = <&bl_pwm_off_pins>;
+               pinctrl-5 = <&bl_pwm_combo_off_pins>;
                pinctrl_version = <1>; /* for uboot */
                ldim_pwm_config = <&bl_pwm_conf>;
 
                        index = <0>;
                        type = <0>; /*0=normal, 1=spi, 2=i2c*/
                        ldim_dev_name = "ob3350";
-                       ldim_pwm_pinmux_sel = "ldim_pwm";
-                       ldim_pwm_port = "PWM_B";
+                       ldim_pwm_port = "PWM_C";
                        ldim_pwm_attr = <0 /* pol */
                                200 /*freq(pwm:Hz, pwm_vs:multiple of vs)*/
-                               50>;/*duty(%)*/
-                       dim_max_min = <100 20>; /*dim_max, dim_min*/
+                               50>;/*default duty(%)*/
                        en_gpio_on_off = <0 /*ldim_dev-gpios index*/
                                1 0>; /*on_level, off_level*/
+                       dim_max_min = <100 20>; /*dim_max, dim_min*/
                };
                ldim_dev_1 {
                        index = <1>;
                        type = <0>; /*0=normal, 1=spi, 2=i2c*/
                        ldim_dev_name = "global";
-                       ldim_pwm_pinmux_sel = "ldim_pwm";
                        ldim_pwm_port = "PWM_C";
                        ldim_pwm_attr = <1 /* pol */
                                180 /*freq(pwm:Hz, pwm_vs:multiple of vs)*/
-                               50>;/*duty(%)*/
-                       dim_max_min = <100 20>; /*dim_max, dim_min*/
-                       en_gpio_on_off = <2 /*ldim_dev-gpios index*/
+                               50>;/*default duty(%)*/
+                       analog_pwm_port = "PWM_D";
+                       analog_pwm_attr = <1 /*pol(0=negative, 1=positvie)*/
+                               18000 /*freq(pwm:Hz)*/
+                               100 25 /*duty_max(%), duty_min(%)*/
+                               80>;   /*default duty(%)*/
+                       en_gpio_on_off = <0 /*ldim_dev-gpios index*/
                                1 0>; /*on_level, off_level*/
+                       dim_max_min = <100 20>; /*dim_max, dim_min*/
+               };
+
+               ldim_dev_2 {
+                       index = <2>;
+                       type = <1>; /* 0=normal,1=spi,2=i2c */
+                       ldim_dev_name = "iw7027";
+                       ldim_pwm_port = "PWM_VS";
+                       ldim_pwm_attr = <1  /* pol */
+                               2 /*freq(pwm:Hz, pwm_vs:multiple of vs)*/
+                               50>;/*default duty(%)*/
+                       spi_bus_num = <0>;
+                       spi_chip_select = <0>;
+                       spi_max_frequency = <1000000>; /* unit: hz */
+                       spi_mode = <0>; /* mode: 0, 1, 2, 3 */
+                       spi_cs_delay = <10  /* hold_high_delay */
+                               100>; /* clk_cs_delay (unit: us) */
+                       en_gpio_on_off = <0 /* ldim_dev-gpios index */
+                               1 /* on_level */
+                               0>; /* off_level */
+                       lamp_err_gpio = <0xff>;
+                               /* ldim_dev-gpios index, 0xff=invalid */
+                       spi_write_check = <0>; /* 0=disable, 1=enable */
+
+                       dim_max_min = <0xfff 0x7f>; /* dim_max, dim_min */
+                       ldim_region_mapping = <0 1 2 3 4 5 6 7 8 9>;
+
+                       cmd_size = <0xff>;
+                       /* init: (type, data...) */
+                       /*   type: 0x00=cmd with delay,
+                        *         0xc0=cmd,
+                        *         0xfd=delay,
+                        *         0xff=ending
+                        */
+                       /*   data: spi data, fill 0x0 for no use */
+                       /*   delay: unit ms */
+                       init_on = <
+                               0xc0 2 0x23 0x03
+                               0xc0 2 0x24 0xff
+                               0xc0 2 0x25 0x00
+                               0xc0 2 0x26 0x00
+                               0xc0 2 0x27 0x60
+                               0xc0 2 0x29 0x00
+                               0xc0 2 0x2a 0x00
+                               0xc0 2 0x2b 0x00
+                               0xc0 2 0x2c 0x73
+                               0xc0 2 0x2d 0x37
+                               0xc0 2 0x31 0x93
+                               0xc0 2 0x32 0x0f
+                               0xc0 2 0x33 0xff
+                               0xc0 2 0x34 0xc8
+                               0xc0 2 0x35 0xbf
+                               0xff 0>;
+                       init_off = <0xff 0>;
                };
        };
 }; /* end of / */
index 73ed979..3e9c828 100644 (file)
                };
                backlight_4{
                        index = <4>;
-                       bl_name = "ldim_iw7027";
+                       bl_name = "ldim_global";
                        bl_level_default_uboot_kernel = <100 100>;
                        bl_level_attr = <255 10 /*max, min*/
                                128 128>; /*mid, mid_mapping*/
                        bl_ctrl_method = <3>; /*1=pwm,2=pwm_combo,3=ldim*/
-                       bl_power_attr = <0 /*en_gpio_index*/
-                               1 0  /*on_value, off_value*/
-                               200 200>; /*on_delay(ms), off_delay(ms)*/
-                       bl_ldim_region_row_col = <1 10>;
+                       bl_power_attr = <0xff /*en_gpio_index*/
+                               1 0 /*on_value, off_value*/
+                               200 200>; /* on_delay(ms), off_delay(ms)*/
+                       bl_ldim_region_row_col = <1 1>;
                        bl_ldim_mode = <1>; /*0=left/right side
                                             *1=top/bottom side
                                             *2=direct
                                             */
-                       ldim_dev_index = <2>;
+                       ldim_dev_index = <1>;
                };
                backlight_5{
                        index = <5>;
-                       bl_name = "ldim_global";
+                       bl_name = "ldim_iw7027";
                        bl_level_default_uboot_kernel = <100 100>;
                        bl_level_attr = <255 10 /*max, min*/
                                128 128>; /*mid, mid_mapping*/
                        bl_ctrl_method = <3>; /*1=pwm,2=pwm_combo,3=ldim*/
                        bl_power_attr = <0 /*en_gpio_index*/
-                               1 0 /*on_value, off_value*/
-                               200 200>; /* on_delay(ms), off_delay(ms)*/
-                       bl_ldim_region_row_col = <1 1>;
+                               1 0  /*on_value, off_value*/
+                               200 200>; /*on_delay(ms), off_delay(ms)*/
+                       bl_ldim_region_row_col = <1 10>;
                        bl_ldim_mode = <1>; /*0=left/right side
                                             *1=top/bottom side
                                             *2=direct
                                             */
-                       ldim_dev_index = <1>;
+                       ldim_dev_index = <2>;
                };
        };
 
                status = "okay";
                pinctrl-names = "ldim_pwm",
                        "ldim_pwm_vs",
-                       "ldim_pwm_off";
+                       "ldim_pwm_combo",
+                       "ldim_pwm_vs_combo",
+                       "ldim_pwm_off",
+                       "ldim_pwm_combo_off";
                pinctrl-0 = <&bl_pwm_on_pins>;
                pinctrl-1 = <&bl_pwm_vs_on_pins>;
-               pinctrl-2 = <&bl_pwm_off_pins>;
+               pinctrl-2 = <&bl_pwm_on_pins &bl_pwm_combo_1_on_pins>;
+               pinctrl-3 = <&bl_pwm_vs_on_pins &bl_pwm_combo_1_on_pins>;
+               pinctrl-4 = <&bl_pwm_off_pins>;
+               pinctrl-5 = <&bl_pwm_combo_off_pins>;
                pinctrl_version = <1>; /* for uboot */
                ldim_pwm_config = <&bl_pwm_conf>;
 
                /* pwm port: PWM_A, PWM_B, PWM_C, PWM_D, PWM_E, PWM_F, PWM_VS*/
                ldim_dev-gpios = <&gpio GPIOZ_12 GPIO_ACTIVE_HIGH
                        &gpio GPIOZ_6 GPIO_ACTIVE_HIGH
-                       &gpio GPIOZ_7 GPIO_ACTIVE_HIGH>;
-               ldim_dev_gpio_names = "GPIOZ_12","GPIOZ_6","GPIOZ_7";
+                       &gpio GPIOZ_7 GPIO_ACTIVE_HIGH
+                       &gpio GPIOZ_4 GPIO_ACTIVE_HIGH>;
+               ldim_dev_gpio_names = "GPIOZ_12","GPIOZ_6","GPIOZ_7","GPIOZ_4";
 
                ldim_dev_0 {
                        index = <0>;
                        type = <0>; /*0=normal, 1=spi, 2=i2c*/
                        ldim_dev_name = "ob3350";
-                       ldim_pwm_pinmux_sel = "ldim_pwm";
                        ldim_pwm_port = "PWM_B";
                        ldim_pwm_attr = <0 /* pol */
                                200 /*freq(pwm:Hz, pwm_vs:multiple of vs)*/
-                               50>;/*duty(%)*/
-                       dim_max_min = <100 20>; /*dim_max, dim_min*/
+                               50>;/*default duty(%)*/
                        en_gpio_on_off = <0 /*ldim_dev-gpios index*/
                                1 0>; /*on_level, off_level*/
+                       dim_max_min = <100 20>; /*dim_max, dim_min*/
                };
                ldim_dev_1 {
                        index = <1>;
                        type = <0>; /*0=normal, 1=spi, 2=i2c*/
                        ldim_dev_name = "global";
-                       ldim_pwm_pinmux_sel = "ldim_pwm";
                        ldim_pwm_port = "PWM_B";
                        ldim_pwm_attr = <1 /* pol */
                                180 /*freq(pwm:Hz, pwm_vs:multiple of vs)*/
-                               50>;/*duty(%)*/
-                       dim_max_min = <100 20>; /*dim_max, dim_min*/
-                       en_gpio_on_off = <2 /*ldim_dev-gpios index*/
+                               50>;/*default duty(%)*/
+                       analog_pwm_port = "PWM_C";
+                       analog_pwm_attr = <1 /*pol(0=negative, 1=positvie)*/
+                               18000 /*freq(pwm:Hz)*/
+                               100 25 /*duty_max(%), duty_min(%)*/
+                               80>;   /*default duty(%)*/
+                       en_gpio_on_off = <3 /*ldim_dev-gpios index*/
                                1 0>; /*on_level, off_level*/
+                       dim_max_min = <100 20>; /*dim_max, dim_min*/
                };
                ldim_dev_2 {
                        index = <2>;
                        type = <1>; /* 0=normal,1=spi,2=i2c */
                        ldim_dev_name = "iw7027";
-                       ldim_pwm_pinmux_sel = "ldim_pwm_vs";
                        ldim_pwm_port = "PWM_VS";
                        ldim_pwm_attr = <1  /* pol */
                                2 /*freq(pwm:Hz, pwm_vs:multiple of vs)*/
-                               50>;/*duty(%)*/
+                               50>;/*default duty(%)*/
                        spi_bus_num = <0>;
                        spi_chip_select = <0>;
                        spi_max_frequency = <1000000>; /* unit: hz */
index 98853d8..ab777dc 100644 (file)
@@ -40,6 +40,8 @@
                i2c2 = &i2c2;
                i2c3 = &i2c3;
                i2c4 = &i2c_AO;
+               spi0 = &spicc0;
+               spi1 = &spicc1;
        };
 
        memory@00000000 {
index 33c1769..1239a61 100644 (file)
                        bl_level_attr = <255 10 /*max, min*/
                                128 128>; /*mid, mid_mapping*/
                        bl_ctrl_method = <3>; /*1=pwm,2=pwm_combo,3=ldim*/
-                       bl_power_attr = <0 /*en_gpio_index*/
+                       bl_power_attr = <0xff /*en_gpio_index*/
                                1 0  /*on_value, off_value*/
                                200 200>; /*on_delay(ms), off_delay(ms)*/
                        bl_ldim_region_row_col = <1 1>;
                                             */
                        ldim_dev_index = <1>;
                };
+               backlight_5{
+                       index = <5>;
+                       bl_name = "ldim_iw7027";
+                       bl_level_default_uboot_kernel = <100 100>;
+                       bl_level_attr = <255 10 /*max, min*/
+                               128 128>; /*mid, mid_mapping*/
+                       bl_ctrl_method = <3>; /*1=pwm,2=pwm_combo,3=ldim*/
+                       bl_power_attr = <0 /*en_gpio_index*/
+                               1 0  /*on_value, off_value*/
+                               200 200>; /*on_delay(ms), off_delay(ms)*/
+                       bl_ldim_region_row_col = <1 10>;
+                       bl_ldim_mode = <1>; /*0=left/right side
+                                            *1=top/bottom side
+                                            *2=direct
+                                            */
+                       ldim_dev_index = <2>;
+               };
        };
 
        bl_pwm_conf:bl_pwm_conf{
                status = "okay";
                pinctrl-names = "ldim_pwm",
                        "ldim_pwm_vs",
-                       "ldim_pwm_off";
+                       "ldim_pwm_combo",
+                       "ldim_pwm_vs_combo",
+                       "ldim_pwm_off",
+                       "ldim_pwm_combo_off";
                pinctrl-0 = <&pwm_c_pins3>;
                pinctrl-1 = <&bl_pwm_vs_on_pins>;
-               pinctrl-2 = <&bl_pwm_off_pins>;
+               pinctrl-2 = <&pwm_c_pins3 &pwm_d_pins2>;
+               pinctrl-3 = <&bl_pwm_vs_on_pins &pwm_d_pins2>;
+               pinctrl-4 = <&bl_pwm_off_pins>;
+               pinctrl-5 = <&bl_pwm_combo_off_pins>;
                pinctrl_version = <1>; /* for uboot */
                ldim_pwm_config = <&bl_pwm_conf>;
 
                        index = <0>;
                        type = <0>; /*0=normal, 1=spi, 2=i2c*/
                        ldim_dev_name = "ob3350";
-                       ldim_pwm_pinmux_sel = "ldim_pwm";
-                       ldim_pwm_port = "PWM_B";
+                       ldim_pwm_port = "PWM_C";
                        ldim_pwm_attr = <0 /* pol */
                                200 /*freq(pwm:Hz, pwm_vs:multiple of vs)*/
-                               50>;/*duty(%)*/
-                       dim_max_min = <100 20>; /*dim_max, dim_min*/
+                               50>;/*default duty(%)*/
                        en_gpio_on_off = <0 /*ldim_dev-gpios index*/
                                1 0>; /*on_level, off_level*/
+                       dim_max_min = <100 20>; /*dim_max, dim_min*/
                };
                ldim_dev_1 {
                        index = <1>;
                        type = <0>; /*0=normal, 1=spi, 2=i2c*/
                        ldim_dev_name = "global";
-                       ldim_pwm_pinmux_sel = "ldim_pwm";
                        ldim_pwm_port = "PWM_C";
                        ldim_pwm_attr = <1 /* pol */
                                180 /*freq(pwm:Hz, pwm_vs:multiple of vs)*/
-                               50>;/*duty(%)*/
-                       dim_max_min = <100 20>; /*dim_max, dim_min*/
-                       en_gpio_on_off = <2 /*ldim_dev-gpios index*/
+                               50>;/*default duty(%)*/
+                       analog_pwm_port = "PWM_D";
+                       analog_pwm_attr = <1 /*pol(0=negative, 1=positvie)*/
+                               18000 /*freq(pwm:Hz)*/
+                               100 25 /*duty_max(%), duty_min(%)*/
+                               80>;   /*default duty(%)*/
+                       en_gpio_on_off = <0 /*ldim_dev-gpios index*/
                                1 0>; /*on_level, off_level*/
+                       dim_max_min = <100 20>; /*dim_max, dim_min*/
                };
-       };
 
+               ldim_dev_2 {
+                       index = <2>;
+                       type = <1>; /* 0=normal,1=spi,2=i2c */
+                       ldim_dev_name = "iw7027";
+                       ldim_pwm_port = "PWM_VS";
+                       ldim_pwm_attr = <1  /* pol */
+                               2 /*freq(pwm:Hz, pwm_vs:multiple of vs)*/
+                               50>;/*default duty(%)*/
+                       spi_bus_num = <0>;
+                       spi_chip_select = <0>;
+                       spi_max_frequency = <1000000>; /* unit: hz */
+                       spi_mode = <0>; /* mode: 0, 1, 2, 3 */
+                       spi_cs_delay = <10  /* hold_high_delay */
+                               100>; /* clk_cs_delay (unit: us) */
+                       en_gpio_on_off = <0 /* ldim_dev-gpios index */
+                               1 /* on_level */
+                               0>; /* off_level */
+                       lamp_err_gpio = <0xff>;
+                               /* ldim_dev-gpios index, 0xff=invalid */
+                       spi_write_check = <0>; /* 0=disable, 1=enable */
+
+                       dim_max_min = <0xfff 0x7f>; /* dim_max, dim_min */
+                       ldim_region_mapping = <0 1 2 3 4 5 6 7 8 9>;
+
+                       cmd_size = <0xff>;
+                       /* init: (type, data...) */
+                       /*   type: 0x00=cmd with delay,
+                        *         0xc0=cmd,
+                        *         0xfd=delay,
+                        *         0xff=ending
+                        */
+                       /*   data: spi data, fill 0x0 for no use */
+                       /*   delay: unit ms */
+                       init_on = <
+                               0xc0 2 0x23 0x03
+                               0xc0 2 0x24 0xff
+                               0xc0 2 0x25 0x00
+                               0xc0 2 0x26 0x00
+                               0xc0 2 0x27 0x60
+                               0xc0 2 0x29 0x00
+                               0xc0 2 0x2a 0x00
+                               0xc0 2 0x2b 0x00
+                               0xc0 2 0x2c 0x73
+                               0xc0 2 0x2d 0x37
+                               0xc0 2 0x31 0x93
+                               0xc0 2 0x32 0x0f
+                               0xc0 2 0x33 0xff
+                               0xc0 2 0x34 0xc8
+                               0xc0 2 0x35 0xbf
+                               0xff 0>;
+                       init_off = <0xff 0>;
+               };
+       };
 }; /* end of / */
index 95d59da..3d018ed 100644 (file)
                        bl_level_attr = <255 10 /*max, min*/
                                128 128>; /*mid, mid_mapping*/
                        bl_ctrl_method = <3>; /*1=pwm,2=pwm_combo,3=ldim*/
-                       bl_power_attr = <0 /*en_gpio_index*/
+                       bl_power_attr = <0xff /*en_gpio_index*/
                                1 0  /*on_value, off_value*/
                                200 200>; /*on_delay(ms), off_delay(ms)*/
                        bl_ldim_region_row_col = <1 1>;
                                             */
                        ldim_dev_index = <1>;
                };
+               backlight_5{
+                       index = <5>;
+                       bl_name = "ldim_iw7027";
+                       bl_level_default_uboot_kernel = <100 100>;
+                       bl_level_attr = <255 10 /*max, min*/
+                               128 128>; /*mid, mid_mapping*/
+                       bl_ctrl_method = <3>; /*1=pwm,2=pwm_combo,3=ldim*/
+                       bl_power_attr = <0 /*en_gpio_index*/
+                               1 0  /*on_value, off_value*/
+                               200 200>; /*on_delay(ms), off_delay(ms)*/
+                       bl_ldim_region_row_col = <1 10>;
+                       bl_ldim_mode = <1>; /*0=left/right side
+                                            *1=top/bottom side
+                                            *2=direct
+                                            */
+                       ldim_dev_index = <2>;
+               };
        };
 
        bl_pwm_conf:bl_pwm_conf{
                status = "okay";
                pinctrl-names = "ldim_pwm",
                        "ldim_pwm_vs",
-                       "ldim_pwm_off";
+                       "ldim_pwm_combo",
+                       "ldim_pwm_vs_combo",
+                       "ldim_pwm_off",
+                       "ldim_pwm_combo_off";
                pinctrl-0 = <&pwm_c_pins3>;
                pinctrl-1 = <&bl_pwm_vs_on_pins>;
-               pinctrl-2 = <&bl_pwm_off_pins>;
+               pinctrl-2 = <&pwm_c_pins3 &pwm_d_pins2>;
+               pinctrl-3 = <&bl_pwm_vs_on_pins &pwm_d_pins2>;
+               pinctrl-4 = <&bl_pwm_off_pins>;
+               pinctrl-5 = <&bl_pwm_combo_off_pins>;
                pinctrl_version = <1>; /* for uboot */
                ldim_pwm_config = <&bl_pwm_conf>;
 
                        index = <0>;
                        type = <0>; /*0=normal, 1=spi, 2=i2c*/
                        ldim_dev_name = "ob3350";
-                       ldim_pwm_pinmux_sel = "ldim_pwm";
-                       ldim_pwm_port = "PWM_B";
+                       ldim_pwm_port = "PWM_C";
                        ldim_pwm_attr = <0 /* pol */
                                200 /*freq(pwm:Hz, pwm_vs:multiple of vs)*/
-                               50>;/*duty(%)*/
-                       dim_max_min = <100 20>; /*dim_max, dim_min*/
+                               50>;/*default duty(%)*/
                        en_gpio_on_off = <0 /*ldim_dev-gpios index*/
                                1 0>; /*on_level, off_level*/
+                       dim_max_min = <100 20>; /*dim_max, dim_min*/
                };
                ldim_dev_1 {
                        index = <1>;
                        type = <0>; /*0=normal, 1=spi, 2=i2c*/
                        ldim_dev_name = "global";
-                       ldim_pwm_pinmux_sel = "ldim_pwm";
                        ldim_pwm_port = "PWM_C";
                        ldim_pwm_attr = <1 /* pol */
                                180 /*freq(pwm:Hz, pwm_vs:multiple of vs)*/
-                               50>;/*duty(%)*/
-                       dim_max_min = <100 20>; /*dim_max, dim_min*/
-                       en_gpio_on_off = <2 /*ldim_dev-gpios index*/
+                               50>;/*default duty(%)*/
+                       analog_pwm_port = "PWM_D";
+                       analog_pwm_attr = <1 /*pol(0=negative, 1=positvie)*/
+                               18000 /*freq(pwm:Hz)*/
+                               100 25 /*duty_max(%), duty_min(%)*/
+                               80>;   /*default duty(%)*/
+                       en_gpio_on_off = <0 /*ldim_dev-gpios index*/
                                1 0>; /*on_level, off_level*/
+                       dim_max_min = <100 20>; /*dim_max, dim_min*/
+               };
+
+               ldim_dev_2 {
+                       index = <2>;
+                       type = <1>; /* 0=normal,1=spi,2=i2c */
+                       ldim_dev_name = "iw7027";
+                       ldim_pwm_port = "PWM_VS";
+                       ldim_pwm_attr = <1  /* pol */
+                               2 /*freq(pwm:Hz, pwm_vs:multiple of vs)*/
+                               50>;/*default duty(%)*/
+                       spi_bus_num = <0>;
+                       spi_chip_select = <0>;
+                       spi_max_frequency = <1000000>; /* unit: hz */
+                       spi_mode = <0>; /* mode: 0, 1, 2, 3 */
+                       spi_cs_delay = <10  /* hold_high_delay */
+                               100>; /* clk_cs_delay (unit: us) */
+                       en_gpio_on_off = <0 /* ldim_dev-gpios index */
+                               1 /* on_level */
+                               0>; /* off_level */
+                       lamp_err_gpio = <0xff>;
+                               /* ldim_dev-gpios index, 0xff=invalid */
+                       spi_write_check = <0>; /* 0=disable, 1=enable */
+
+                       dim_max_min = <0xfff 0x7f>; /* dim_max, dim_min */
+                       ldim_region_mapping = <0 1 2 3 4 5 6 7 8 9>;
+
+                       cmd_size = <0xff>;
+                       /* init: (type, data...) */
+                       /*   type: 0x00=cmd with delay,
+                        *         0xc0=cmd,
+                        *         0xfd=delay,
+                        *         0xff=ending
+                        */
+                       /*   data: spi data, fill 0x0 for no use */
+                       /*   delay: unit ms */
+                       init_on = <
+                               0xc0 2 0x23 0x03
+                               0xc0 2 0x24 0xff
+                               0xc0 2 0x25 0x00
+                               0xc0 2 0x26 0x00
+                               0xc0 2 0x27 0x60
+                               0xc0 2 0x29 0x00
+                               0xc0 2 0x2a 0x00
+                               0xc0 2 0x2b 0x00
+                               0xc0 2 0x2c 0x73
+                               0xc0 2 0x2d 0x37
+                               0xc0 2 0x31 0x93
+                               0xc0 2 0x32 0x0f
+                               0xc0 2 0x33 0xff
+                               0xc0 2 0x34 0xc8
+                               0xc0 2 0x35 0xbf
+                               0xff 0>;
+                       init_off = <0xff 0>;
                };
        };
 }; /* end of / */
index 99c8c93..610a57d 100644 (file)
                };
                backlight_4{
                        index = <4>;
-                       bl_name = "ldim_iw7027";
+                       bl_name = "ldim_global";
                        bl_level_default_uboot_kernel = <100 100>;
                        bl_level_attr = <255 10 /*max, min*/
                                128 128>; /*mid, mid_mapping*/
                        bl_ctrl_method = <3>; /*1=pwm,2=pwm_combo,3=ldim*/
-                       bl_power_attr = <0 /*en_gpio_index*/
-                               1 0  /*on_value, off_value*/
-                               200 200>; /*on_delay(ms), off_delay(ms)*/
-                       bl_ldim_region_row_col = <1 10>;
+                       bl_power_attr = <0xff /*en_gpio_index*/
+                               1 0 /*on_value, off_value*/
+                               200 200>; /* on_delay(ms), off_delay(ms)*/
+                       bl_ldim_region_row_col = <1 1>;
                        bl_ldim_mode = <1>; /*0=left/right side
                                             *1=top/bottom side
                                             *2=direct
                                             */
-                       ldim_dev_index = <2>;
+                       ldim_dev_index = <1>;
                };
                backlight_5{
                        index = <5>;
-                       bl_name = "ldim_global";
+                       bl_name = "ldim_iw7027";
                        bl_level_default_uboot_kernel = <100 100>;
                        bl_level_attr = <255 10 /*max, min*/
                                128 128>; /*mid, mid_mapping*/
                        bl_ctrl_method = <3>; /*1=pwm,2=pwm_combo,3=ldim*/
                        bl_power_attr = <0 /*en_gpio_index*/
-                               1 0 /*on_value, off_value*/
-                               200 200>; /* on_delay(ms), off_delay(ms)*/
-                       bl_ldim_region_row_col = <1 1>;
+                               1 0  /*on_value, off_value*/
+                               200 200>; /*on_delay(ms), off_delay(ms)*/
+                       bl_ldim_region_row_col = <1 10>;
                        bl_ldim_mode = <1>; /*0=left/right side
                                             *1=top/bottom side
                                             *2=direct
                                             */
-                       ldim_dev_index = <1>;
+                       ldim_dev_index = <2>;
                };
        };
 
                status = "okay";
                pinctrl-names = "ldim_pwm",
                        "ldim_pwm_vs",
-                       "ldim_pwm_off";
+                       "ldim_pwm_combo",
+                       "ldim_pwm_vs_combo",
+                       "ldim_pwm_off",
+                       "ldim_pwm_combo_off";
                pinctrl-0 = <&bl_pwm_on_pins>;
                pinctrl-1 = <&bl_pwm_vs_on_pins>;
-               pinctrl-2 = <&bl_pwm_off_pins>;
+               pinctrl-2 = <&bl_pwm_on_pins &bl_pwm_combo_1_on_pins>;
+               pinctrl-3 = <&bl_pwm_vs_on_pins &bl_pwm_combo_1_on_pins>;
+               pinctrl-4 = <&bl_pwm_off_pins>;
+               pinctrl-5 = <&bl_pwm_combo_off_pins>;
                pinctrl_version = <1>; /* for uboot */
                ldim_pwm_config = <&bl_pwm_conf>;
 
                /* pwm port: PWM_A, PWM_B, PWM_C, PWM_D, PWM_E, PWM_F, PWM_VS*/
                ldim_dev-gpios = <&gpio GPIOZ_12 GPIO_ACTIVE_HIGH
                        &gpio GPIOZ_6 GPIO_ACTIVE_HIGH
-                       &gpio GPIOZ_7 GPIO_ACTIVE_HIGH>;
-               ldim_dev_gpio_names = "GPIOZ_12","GPIOZ_6","GPIOZ_7";
+                       &gpio GPIOZ_7 GPIO_ACTIVE_HIGH
+                       &gpio GPIOZ_4 GPIO_ACTIVE_HIGH>;
+               ldim_dev_gpio_names = "GPIOZ_12","GPIOZ_6","GPIOZ_7","GPIOZ_4";
 
                ldim_dev_0 {
                        index = <0>;
                        type = <0>; /*0=normal, 1=spi, 2=i2c*/
                        ldim_dev_name = "ob3350";
-                       ldim_pwm_pinmux_sel = "ldim_pwm";
                        ldim_pwm_port = "PWM_B";
                        ldim_pwm_attr = <0 /* pol */
                                200 /*freq(pwm:Hz, pwm_vs:multiple of vs)*/
-                               50>;/*duty(%)*/
-                       dim_max_min = <100 20>; /*dim_max, dim_min*/
+                               50>;/*default duty(%)*/
                        en_gpio_on_off = <0 /*ldim_dev-gpios index*/
                                1 0>; /*on_level, off_level*/
+                       dim_max_min = <100 20>; /*dim_max, dim_min*/
                };
                ldim_dev_1 {
                        index = <1>;
                        type = <0>; /*0=normal, 1=spi, 2=i2c*/
                        ldim_dev_name = "global";
-                       ldim_pwm_pinmux_sel = "ldim_pwm";
                        ldim_pwm_port = "PWM_B";
                        ldim_pwm_attr = <1 /* pol */
                                180 /*freq(pwm:Hz, pwm_vs:multiple of vs)*/
-                               50>;/*duty(%)*/
-                       dim_max_min = <100 20>; /*dim_max, dim_min*/
-                       en_gpio_on_off = <2 /*ldim_dev-gpios index*/
+                               50>;/*default duty(%)*/
+                       analog_pwm_port = "PWM_C";
+                       analog_pwm_attr = <1 /*pol(0=negative, 1=positvie)*/
+                               18000 /*freq(pwm:Hz)*/
+                               100 25 /*duty_max(%), duty_min(%)*/
+                               80>;   /*default duty(%)*/
+                       en_gpio_on_off = <3 /*ldim_dev-gpios index*/
                                1 0>; /*on_level, off_level*/
+                       dim_max_min = <100 20>; /*dim_max, dim_min*/
                };
                ldim_dev_2 {
                        index = <2>;
                        type = <1>; /* 0=normal,1=spi,2=i2c */
                        ldim_dev_name = "iw7027";
-                       ldim_pwm_pinmux_sel = "ldim_pwm_vs";
                        ldim_pwm_port = "PWM_VS";
                        ldim_pwm_attr = <1  /* pol */
                                2 /*freq(pwm:Hz, pwm_vs:multiple of vs)*/
-                               50>;/*duty(%)*/
+                               50>;/*default duty(%)*/
                        spi_bus_num = <0>;
                        spi_chip_select = <0>;
                        spi_max_frequency = <1000000>; /* unit: hz */
                                0xc0 2 0x34 0xc8
                                0xc0 2 0x35 0xbf
                                0xff 0>;
+                       init_off = <0xff 0>;
                };
        };
 
index 7e8e52e..4e13b6f 100644 (file)
@@ -330,15 +330,6 @@ static void bl_gpio_set(int index, int value)
        }
 }
 
-static inline unsigned int bl_do_div(unsigned long long num, unsigned int den)
-{
-       unsigned long long ret = num;
-
-       do_div(ret, den);
-
-       return (unsigned int)ret;
-}
-
 /* ****************************************************** */
 #define BL_PINMUX_MAX    8
 static char *bl_pinmux_str[BL_PINMUX_MAX] = {
@@ -2868,11 +2859,11 @@ static ssize_t bl_debug_pwm_show(struct class *class,
        return len;
 }
 
-#define BL_DEBUG_PWM_FREQ    0
-#define BL_DEBUG_PWM_DUTY    1
-#define BL_DEBUG_PWM_POL     2
-#define BL_DEBUG_PWM_DUTY_MAX 3
-#define BL_DEBUG_PWM_DUTY_MIN 4
+#define BL_DEBUG_PWM_FREQ       0
+#define BL_DEBUG_PWM_DUTY       1
+#define BL_DEBUG_PWM_POL        2
+#define BL_DEBUG_PWM_DUTY_MAX   3
+#define BL_DEBUG_PWM_DUTY_MIN   4
 static void bl_debug_pwm_set(unsigned int index, unsigned int value, int state)
 {
        struct bl_config_s *bconf = bl_drv->bconf;
index d2dcd99..1a1856c 100644 (file)
@@ -44,7 +44,8 @@ static int global_hw_init_on(void)
 {
        struct aml_ldim_driver_s *ldim_drv = aml_ldim_get_driver();
 
-       ldim_set_duty_pwm(&(ldim_drv->ldev_conf->pwm_config));
+       ldim_set_duty_pwm(&(ldim_drv->ldev_conf->ldim_pwm_config));
+       ldim_set_duty_pwm(&(ldim_drv->ldev_conf->analog_pwm_config));
        ldim_drv->pinmux_ctrl(1);
        mdelay(2);
        ldim_gpio_set(ldim_drv->ldev_conf->en_gpio,
@@ -61,7 +62,8 @@ static int global_hw_init_off(void)
        ldim_gpio_set(ldim_drv->ldev_conf->en_gpio,
                ldim_drv->ldev_conf->en_gpio_off);
        ldim_drv->pinmux_ctrl(0);
-       ldim_pwm_off(&(ldim_drv->ldev_conf->pwm_config));
+       ldim_pwm_off(&(ldim_drv->ldev_conf->ldim_pwm_config));
+       ldim_pwm_off(&(ldim_drv->ldev_conf->analog_pwm_config));
 
        return 0;
 }
@@ -88,12 +90,22 @@ static int global_smr(unsigned short *buf, unsigned char len)
        level = buf[0];
        val = dim_min + ((level * (dim_max - dim_min)) / LD_DATA_MAX);
 
-       ldim_drv->ldev_conf->pwm_config.pwm_duty = val;
-       ldim_set_duty_pwm(&(ldim_drv->ldev_conf->pwm_config));
+       ldim_drv->ldev_conf->ldim_pwm_config.pwm_duty = val;
+       ldim_set_duty_pwm(&(ldim_drv->ldev_conf->ldim_pwm_config));
 
        return 0;
 }
 
+static void global_dim_range_update(void)
+{
+       struct aml_ldim_driver_s *ldim_drv = aml_ldim_get_driver();
+       struct ldim_dev_config_s *ldim_dev;
+
+       ldim_dev = ldim_drv->ldev_conf;
+       ldim_dev->dim_max = ldim_dev->ldim_pwm_config.pwm_duty_max;
+       ldim_dev->dim_min = ldim_dev->ldim_pwm_config.pwm_duty_min;
+}
+
 static int global_power_on(void)
 {
        if (global_on_flag) {
@@ -137,7 +149,7 @@ static ssize_t global_show(struct class *class,
                                ldim_drv->ldev_conf->en_gpio_off,
                                ldim_drv->ldev_conf->dim_max,
                                ldim_drv->ldev_conf->dim_min,
-                               ldim_drv->ldev_conf->pwm_config.pwm_duty);
+                               ldim_drv->ldev_conf->ldim_pwm_config.pwm_duty);
        }
 
        return ret;
@@ -150,6 +162,12 @@ static struct class_attribute global_class_attrs[] = {
 
 static int global_ldim_driver_update(struct aml_ldim_driver_s *ldim_drv)
 {
+       struct ldim_dev_config_s *ldim_dev = ldim_drv->ldev_conf;
+
+       ldim_dev->ldim_pwm_config.pwm_duty_max = ldim_dev->dim_max;
+       ldim_dev->ldim_pwm_config.pwm_duty_min = ldim_dev->dim_min;
+       ldim_dev->dim_range_update = global_dim_range_update;
+
        ldim_drv->device_power_on = global_power_on;
        ldim_drv->device_power_off = global_power_off;
        ldim_drv->device_bri_update = global_smr;
index 6c123d1..054f3d2 100644 (file)
@@ -273,7 +273,8 @@ static int iw7027_hw_init_on(void)
        iw7027_power_on_init();
 
        /* step 5: supply stable vsync */
-       ldim_set_duty_pwm(&(ldim_drv->ldev_conf->pwm_config));
+       ldim_set_duty_pwm(&(ldim_drv->ldev_conf->ldim_pwm_config));
+       ldim_set_duty_pwm(&(ldim_drv->ldev_conf->analog_pwm_config));
        ldim_drv->pinmux_ctrl(1);
 
        /* step 6: delay for system clock and light bar PSU stable */
@@ -305,7 +306,8 @@ static int iw7027_hw_init_off(void)
        ldim_gpio_set(ldim_drv->ldev_conf->en_gpio,
                ldim_drv->ldev_conf->en_gpio_off);
        ldim_drv->pinmux_ctrl(0);
-       ldim_pwm_off(&(ldim_drv->ldev_conf->pwm_config));
+       ldim_pwm_off(&(ldim_drv->ldev_conf->ldim_pwm_config));
+       ldim_pwm_off(&(ldim_drv->ldev_conf->analog_pwm_config));
 
        return 0;
 }
@@ -617,7 +619,7 @@ static ssize_t iw7027_store(struct class *class,
        struct aml_ldim_driver_s *ldim_drv = aml_ldim_get_driver();
        struct iw7027_s *bl = container_of(class, struct iw7027_s, cls);
        unsigned int val, val2;
-       unsigned char reg_addr, reg_val;
+       unsigned char reg_addr, reg_val, temp;
        int i;
 
        if (!strcmp(attr->attr.name, "init")) {
@@ -632,6 +634,10 @@ static ssize_t iw7027_store(struct class *class,
                                reg_addr = (unsigned char)val;
                                reg_val = (unsigned char)val2;
                                iw7027_wreg(bl->spi, reg_addr, reg_val);
+                               iw7027_rreg(bl->spi, reg_addr, &temp);
+                               pr_info(
+                               "reg 0x%02x = 0x%02x, readback 0x%02x\n",
+                                       reg_addr, reg_val, temp);
                                mutex_unlock(&iw7027_spi_mutex);
                        } else {
                                LDIMERR("%s: invalid args\n", __func__);
index 6ed4519..db5a10a 100644 (file)
@@ -58,6 +58,7 @@ static struct spi_board_info ldim_spi_info = {
 static unsigned char *table_init_on_dft;
 static unsigned char *table_init_off_dft;
 static int ldim_dev_probe_flag;
+static struct class ldim_dev_class;
 
 struct ldim_dev_config_s ldim_dev_config = {
        .type = LDIM_DEV_TYPE_NORMAL,
@@ -77,12 +78,20 @@ struct ldim_dev_config_s ldim_dev_config = {
        .init_off = NULL,
        .init_on_cnt = 0,
        .init_off_cnt = 0,
-       .pwm_config = {
+       .ldim_pwm_config = {
                .pwm_method = BL_PWM_POSITIVE,
                .pwm_port = BL_PWM_MAX,
                .pwm_duty_max = 100,
-               .pwm_duty_min = 1,
+               .pwm_duty_min = 0,
        },
+       .analog_pwm_config = {
+               .pwm_method = BL_PWM_POSITIVE,
+               .pwm_port = BL_PWM_MAX,
+               .pwm_freq = 1000,
+               .pwm_duty_max = 100,
+               .pwm_duty_min = 10,
+       },
+       .dim_range_update = NULL,
 
        .bl_regnum = 0,
 };
@@ -246,14 +255,13 @@ unsigned int ldim_gpio_get(int index)
 
 void ldim_set_duty_pwm(struct bl_pwm_config_s *bl_pwm)
 {
-       unsigned long temp;
+       unsigned long long temp;
 
        if (bl_pwm->pwm_port >= BL_PWM_MAX)
                return;
 
        temp = bl_pwm->pwm_cnt;
-       temp = (((temp * bl_pwm->pwm_duty) + 50) / 100);
-       bl_pwm->pwm_level = (unsigned int)temp;
+       bl_pwm->pwm_level = bl_do_div(((temp * bl_pwm->pwm_duty) + 50), 100);
 
        if (ldim_debug_print == 2) {
                LDIMPR(
@@ -277,42 +285,53 @@ void ldim_pwm_off(struct bl_pwm_config_s *bl_pwm)
 static char *ldim_pinmux_str[] = {
        "ldim_pwm",               /* 0 */
        "ldim_pwm_vs",            /* 1 */
-       "ldim_pwm_off",            /* 1 */
-       "none",
+       "ldim_pwm_combo",         /* 2 */
+       "ldim_pwm_vs_combo",      /* 3 */
+       "ldim_pwm_off",           /* 4 */
+       "ldim_pwm_combo_off",     /* 5 */
+       "custome",
 };
 
 static int ldim_pwm_pinmux_ctrl(int status)
 {
        struct aml_ldim_driver_s *ldim_drv = aml_ldim_get_driver();
        struct bl_pwm_config_s *bl_pwm;
+       char *str;
        int ret = 0, index = 0xff;
 
-       if (strcmp(ldim_drv->ldev_conf->pinmux_name, "invalid") == 0)
+       if (ldim_drv->ldev_conf->ldim_pwm_config.pwm_port >= BL_PWM_MAX)
                return 0;
 
-       bl_pwm = &ldim_drv->ldev_conf->pwm_config;
-       if (bl_pwm->pwm_port >= BL_PWM_MAX)
-               return 0;
-
-       if (bl_pwm->pwm_port == BL_PWM_VS)
-               index = (status) ? 1 : 2;
-       else
-               index = (status) ? 0 : 2;
+       if (status) {
+               bl_pwm = &ldim_drv->ldev_conf->ldim_pwm_config;
+               if (bl_pwm->pwm_port == BL_PWM_VS)
+                       index = 1;
+               else
+                       index = 0;
+               bl_pwm = &ldim_drv->ldev_conf->analog_pwm_config;
+               if (bl_pwm->pwm_port < BL_PWM_VS)
+                       index += 2;
+       } else {
+               bl_pwm = &ldim_drv->ldev_conf->analog_pwm_config;
+               if (bl_pwm->pwm_port < BL_PWM_VS)
+                       index = 5;
+               else
+                       index = 4;
+       }
 
+       str = ldim_pinmux_str[index];
        if (ldim_drv->pinmux_flag == index) {
-               LDIMPR("pinmux %s is already selected\n",
-                       ldim_pinmux_str[index]);
+               LDIMPR("pinmux %s is already selected\n", str);
                return 0;
        }
 
        /* request pwm pinmux */
-       ldim_drv->pin = devm_pinctrl_get_select(ldim_drv->dev,
-               ldim_pinmux_str[index]);
+       ldim_drv->pin = devm_pinctrl_get_select(ldim_drv->dev, str);
        if (IS_ERR(ldim_drv->pin)) {
-               LDIMERR("set pinmux %s error\n", ldim_pinmux_str[index]);
+               LDIMERR("set pinmux %s error\n", str);
+               ret = -1;
        } else {
-               LDIMPR("set pinmux %s: 0x%p\n",
-                       ldim_pinmux_str[index], ldim_drv->pin);
+               LDIMPR("set pinmux %s: 0x%p\n", str, ldim_drv->pin);
        }
        ldim_drv->pinmux_flag = index;
 
@@ -321,7 +340,7 @@ static int ldim_pwm_pinmux_ctrl(int status)
 
 static int ldim_pwm_vs_update(void)
 {
-       struct bl_pwm_config_s *bl_pwm = &ldim_dev_config.pwm_config;
+       struct bl_pwm_config_s *bl_pwm = &ldim_dev_config.ldim_pwm_config;
        unsigned int cnt;
        int ret = 0;
 
@@ -363,6 +382,10 @@ static void ldim_dev_init_table_dynamic_size_print(
                table = econf->init_off;
                max_len = econf->init_off_cnt;
        }
+       if (max_len == 0) {
+               kfree(str);
+               return;
+       }
        if (table == NULL) {
                LDIMERR("init_table %d is NULL\n", flag);
                kfree(str);
@@ -440,6 +463,10 @@ static void ldim_dev_init_table_fixed_size_print(
                table = econf->init_off;
                max_len = econf->init_off_cnt;
        }
+       if (max_len == 0) {
+               kfree(str);
+               return;
+       }
        if (table == NULL) {
                LDIMERR("init_table %d is NULL\n", flag);
                kfree(str);
@@ -476,7 +503,7 @@ static void ldim_dev_config_print(void)
 
        pr_info("valid_flag            = %d\n"
                "dev_index             = %d\n"
-               "vsync_change_flag     = %d\n",
+               "vsync_change_flag     = %d\n\n",
                ldim_drv->valid_flag,
                ldim_drv->dev_index,
                ldim_drv->vsync_change_flag);
@@ -485,7 +512,6 @@ static void ldim_dev_config_print(void)
                return;
        }
 
-       bl_pwm = &ldim_drv->ldev_conf->pwm_config;
        pr_info("dev_name              = %s\n"
                "type                  = %d\n"
                "en_gpio               = %d\n"
@@ -548,13 +574,14 @@ static void ldim_dev_config_print(void)
        default:
                break;
        }
+       bl_pwm = &ldim_drv->ldev_conf->ldim_pwm_config;
        if (bl_pwm->pwm_port < BL_PWM_MAX) {
-               pr_info("pwm_port:           %d\n"
-                       "pwm_pol:            %d\n"
-                       "pwm_freq:           %d\n"
-                       "pwm_cnt:            %d\n"
-                       "pwm_level:          %d\n"
-                       "pwm_duty:           %d%%\n",
+               pr_info("lidm_pwm_port:       %d\n"
+                       "lidm_pwm_pol:        %d\n"
+                       "lidm_pwm_freq:       %d\n"
+                       "lidm_pwm_cnt:        %d\n"
+                       "lidm_pwm_level:      %d\n"
+                       "lidm_pwm_duty:       %d%%\n",
                        bl_pwm->pwm_port, bl_pwm->pwm_method,
                        bl_pwm->pwm_freq, bl_pwm->pwm_cnt,
                        bl_pwm->pwm_level, bl_pwm->pwm_duty);
@@ -566,28 +593,28 @@ static void ldim_dev_config_print(void)
                case BL_PWM_E:
                case BL_PWM_F:
                        if (IS_ERR_OR_NULL(bl_pwm->pwm_data.pwm)) {
-                               pr_info("pwm invalid\n");
+                               pr_info("lidm_pwm invalid\n");
                                break;
                        }
-                       pr_info("pwm_pointer:        %p\n",
+                       pr_info("lidm_pwm_pointer:    0x%p\n",
                                bl_pwm->pwm_data.pwm);
                        pwm_get_state(bl_pwm->pwm_data.pwm, &pstate);
-                       pr_info("pwm state:\n"
-                               "  period:           %d\n"
-                               "  duty_cycle:       %d\n"
-                               "  polarity:         %d\n"
-                               "  enabled:          %d\n",
+                       pr_info("lidm_pwm state:\n"
+                               "  period:            %d\n"
+                               "  duty_cycle:        %d\n"
+                               "  polarity:          %d\n"
+                               "  enabled:           %d\n",
                                pstate.period, pstate.duty_cycle,
                                pstate.polarity, pstate.enabled);
                        value = bl_cbus_read(
                                bl_drv->data->pwm_reg[bl_pwm->pwm_port]);
-                       pr_info("pwm_reg:            0x%08x\n", value);
+                       pr_info("lidm_pwm_reg:        0x%08x\n", value);
                        break;
                case BL_PWM_VS:
-                       pr_info("pwm_reg0:           0x%08x\n"
-                               "pwm_reg1:           0x%08x\n"
-                               "pwm_reg2:           0x%08x\n"
-                               "pwm_reg3:           0x%08x\n",
+                       pr_info("lidm_pwm_reg0:       0x%08x\n"
+                               "lidm_pwm_reg1:       0x%08x\n"
+                               "lidm_pwm_reg2:       0x%08x\n"
+                               "lidm_pwm_reg3:       0x%08x\n",
                                bl_vcbus_read(VPU_VPU_PWM_V0),
                                bl_vcbus_read(VPU_VPU_PWM_V1),
                                bl_vcbus_read(VPU_VPU_PWM_V2),
@@ -597,16 +624,59 @@ static void ldim_dev_config_print(void)
                        break;
                }
        }
-       pr_info("pinmux_flag:        %d\n"
-               "pinmux_pointer:     0x%p\n\n",
+       bl_pwm = &ldim_drv->ldev_conf->analog_pwm_config;
+       if (bl_pwm->pwm_port < BL_PWM_MAX) {
+               pr_info("\nanalog_pwm_port:     %d\n"
+                       "analog_pwm_pol:      %d\n"
+                       "analog_pwm_freq:     %d\n"
+                       "analog_pwm_cnt:      %d\n"
+                       "analog_pwm_level:    %d\n"
+                       "analog_pwm_duty:     %d%%\n"
+                       "analog_pwm_duty_max: %d%%\n"
+                       "analog_pwm_duty_min: %d%%\n",
+                       bl_pwm->pwm_port, bl_pwm->pwm_method,
+                       bl_pwm->pwm_freq, bl_pwm->pwm_cnt,
+                       bl_pwm->pwm_level, bl_pwm->pwm_duty,
+                       bl_pwm->pwm_duty_max, bl_pwm->pwm_duty_min);
+               switch (bl_pwm->pwm_port) {
+               case BL_PWM_A:
+               case BL_PWM_B:
+               case BL_PWM_C:
+               case BL_PWM_D:
+               case BL_PWM_E:
+               case BL_PWM_F:
+                       if (IS_ERR_OR_NULL(bl_pwm->pwm_data.pwm)) {
+                               pr_info("analog_pwm invalid\n");
+                               break;
+                       }
+                       pr_info("analog_pwm_pointer:  0x%p\n",
+                               bl_pwm->pwm_data.pwm);
+                       pwm_get_state(bl_pwm->pwm_data.pwm, &pstate);
+                       pr_info("analog_pwm state:\n"
+                               "  period:            %d\n"
+                               "  duty_cycle:        %d\n"
+                               "  polarity:          %d\n"
+                               "  enabled:           %d\n",
+                               pstate.period, pstate.duty_cycle,
+                               pstate.polarity, pstate.enabled);
+                       value = bl_cbus_read(
+                               bl_drv->data->pwm_reg[bl_pwm->pwm_port]);
+                       pr_info("analog_pwm_reg:      0x%08x\n", value);
+                       break;
+               default:
+                       break;
+               }
+       }
+       pr_info("\npinmux_flag:         %d\n"
+               "pinmux_pointer:      0x%p\n\n",
                ldim_drv->pinmux_flag,
                ldim_drv->pin);
 
        if (ldim_drv->ldev_conf->cmd_size > 0) {
-               pr_info("table_loaded:       %d\n"
-                       "cmd_size:           %d\n"
-                       "init_on_cnt:        %d\n"
-                       "init_off_cnt:       %d\n",
+               pr_info("table_loaded:        %d\n"
+                       "cmd_size:            %d\n"
+                       "init_on_cnt:         %d\n"
+                       "init_off_cnt:        %d\n",
                        ldim_drv->ldev_conf->init_loaded,
                        ldim_drv->ldev_conf->cmd_size,
                        ldim_drv->ldev_conf->init_on_cnt,
@@ -892,6 +962,7 @@ static int ldim_dev_get_config_from_dts(struct device_node *np, int index)
        int i;
        int ret = 0;
        struct aml_ldim_driver_s *ldim_drv = aml_ldim_get_driver();
+       struct bl_pwm_config_s *bl_pwm;
 
        temp = kcalloc(LD_BLKREGNUM, sizeof(unsigned int), GFP_KERNEL);
        if (temp == NULL) {
@@ -917,48 +988,77 @@ static int ldim_dev_get_config_from_dts(struct device_node *np, int index)
 
        ret = of_property_read_string(child, "ldim_pwm_pinmux_sel", &str);
        if (ret) {
-               LDIMERR("failed to get ldim_pwm_name\n");
                strcpy(ldim_dev_config.pinmux_name, "invalid");
        } else {
+               LDIMPR("find custome ldim_pwm_pinmux_sel: %s\n", str);
                strcpy(ldim_dev_config.pinmux_name, str);
        }
 
+       /* ldim pwm config */
+       bl_pwm = &ldim_dev_config.ldim_pwm_config;
        ret = of_property_read_string(child, "ldim_pwm_port", &str);
        if (ret) {
                LDIMERR("failed to get ldim_pwm_port\n");
-               ldim_dev_config.pwm_config.pwm_port = BL_PWM_MAX;
        } else {
-               ldim_dev_config.pwm_config.pwm_port = bl_pwm_str_to_pwm(str);
+               bl_pwm->pwm_port = bl_pwm_str_to_pwm(str);
+               LDIMPR("ldim_pwm_port: %s(%u)\n", str, bl_pwm->pwm_port);
        }
-       LDIMPR("pwm_port: %s(%u)\n", str, ldim_dev_config.pwm_config.pwm_port);
-
-       if (ldim_dev_config.pwm_config.pwm_port < BL_PWM_MAX) {
+       if (bl_pwm->pwm_port < BL_PWM_MAX) {
                ret = of_property_read_u32_array(child, "ldim_pwm_attr",
                        temp, 3);
                if (ret) {
                        LDIMERR("failed to get ldim_pwm_attr\n");
-                       ldim_dev_config.pwm_config.pwm_method = BL_PWM_POSITIVE;
-                       if (ldim_dev_config.pwm_config.pwm_port == BL_PWM_VS)
-                               ldim_dev_config.pwm_config.pwm_freq = 1;
+                       bl_pwm->pwm_method = BL_PWM_POSITIVE;
+                       if (bl_pwm->pwm_port == BL_PWM_VS)
+                               bl_pwm->pwm_freq = 1;
                        else
-                               ldim_dev_config.pwm_config.pwm_freq = 60;
-                       ldim_dev_config.pwm_config.pwm_duty = 50;
+                               bl_pwm->pwm_freq = 60;
+                       bl_pwm->pwm_duty = 50;
                } else {
-                       ldim_dev_config.pwm_config.pwm_method = temp[0];
-                       ldim_dev_config.pwm_config.pwm_freq = temp[1];
-                       ldim_dev_config.pwm_config.pwm_duty = temp[2];
+                       bl_pwm->pwm_method = temp[0];
+                       bl_pwm->pwm_freq = temp[1];
+                       bl_pwm->pwm_duty = temp[2];
                }
-               LDIMPR("get pwm pol = %d, freq = %d, duty = %d%%\n",
-                       ldim_dev_config.pwm_config.pwm_method,
-                       ldim_dev_config.pwm_config.pwm_freq,
-                       ldim_dev_config.pwm_config.pwm_duty);
+               LDIMPR(
+               "get ldim_pwm pol = %d, freq = %d, default duty = %d%%\n",
+                       bl_pwm->pwm_method, bl_pwm->pwm_freq,
+                       bl_pwm->pwm_duty);
 
-               bl_pwm_config_init(&ldim_dev_config.pwm_config);
+               bl_pwm_config_init(bl_pwm);
 
-               if (ldim_dev_config.pwm_config.pwm_port < BL_PWM_VS) {
-                       ldim_dev_pwm_channel_register(
-                               &ldim_dev_config.pwm_config, np);
+               if (bl_pwm->pwm_port < BL_PWM_VS)
+                       ldim_dev_pwm_channel_register(bl_pwm, np);
+       }
+
+       /* analog pwm config */
+       bl_pwm = &ldim_dev_config.analog_pwm_config;
+       ret = of_property_read_string(child, "analog_pwm_port", &str);
+       if (ret)
+               bl_pwm->pwm_port = BL_PWM_MAX;
+       else
+               bl_pwm->pwm_port = bl_pwm_str_to_pwm(str);
+       if (bl_pwm->pwm_port < BL_PWM_VS) {
+               LDIMPR("find analog_pwm_port: %s(%u)\n", str, bl_pwm->pwm_port);
+               ret = of_property_read_u32_array(child, "analog_pwm_attr",
+                       temp, 5);
+               if (ret) {
+                       LDIMERR("failed to get analog_pwm_attr\n");
+               } else {
+                       bl_pwm->pwm_method = temp[0];
+                       bl_pwm->pwm_freq = temp[1];
+                       bl_pwm->pwm_duty_max = temp[2];
+                       bl_pwm->pwm_duty_min = temp[3];
+                       bl_pwm->pwm_duty = temp[4];
                }
+               LDIMPR(
+"get analog_pwm pol = %d, freq = %d, duty_max = %d%%, duty_min = %d%%, default duty = %d%%\n",
+                       bl_pwm->pwm_method, bl_pwm->pwm_freq,
+                       bl_pwm->pwm_duty_max, bl_pwm->pwm_duty_min,
+                       bl_pwm->pwm_duty);
+
+               bl_pwm_config_init(bl_pwm);
+
+               ldim_dev_pwm_channel_register(bl_pwm, np);
        }
 
        ret = of_property_read_u32_array(child, "en_gpio_on_off", temp, 3);
@@ -1160,6 +1260,268 @@ ldim_get_config_err:
        return -1;
 }
 
+static ssize_t ldim_dev_show(struct class *class,
+               struct class_attribute *attr, char *buf)
+{
+       int ret = 0;
+
+       ldim_dev_config_print();
+
+       return ret;
+}
+
+static ssize_t ldim_dev_pwm_ldim_show(struct class *class,
+               struct class_attribute *attr, char *buf)
+{
+       struct bl_pwm_config_s *bl_pwm;
+       ssize_t len = 0;
+
+       bl_pwm = &ldim_dev_config.ldim_pwm_config;
+       if (bl_pwm->pwm_port < BL_PWM_MAX) {
+               len += sprintf(buf+len,
+                       "ldim_pwm: freq=%d, pol=%d, duty_max=%d, duty_min=%d,",
+                       bl_pwm->pwm_freq, bl_pwm->pwm_method,
+                       bl_pwm->pwm_duty_max, bl_pwm->pwm_duty_min);
+               len += sprintf(buf+len, " duty_value=%d%%\n", bl_pwm->pwm_duty);
+       }
+
+       return len;
+}
+
+static ssize_t ldim_dev_pwm_ldim_store(struct class *class,
+       struct class_attribute *attr, const char *buf, size_t count)
+{
+       unsigned int ret;
+       unsigned int val = 0;
+       struct bl_pwm_config_s *bl_pwm;
+
+       bl_pwm = &ldim_dev_config.ldim_pwm_config;
+       if (bl_pwm->pwm_port >= BL_PWM_MAX)
+               return count;
+
+       switch (buf[0]) {
+       case 'f': /* frequency */
+               ret = sscanf(buf, "freq %d", &val);
+               if (ret == 1) {
+                       bl_pwm->pwm_freq = val;
+                       bl_pwm_config_init(bl_pwm);
+                       ldim_set_duty_pwm(bl_pwm);
+                       if (ldim_debug_print) {
+                               LDIMPR("set ldim_pwm (port %d): freq = %dHz\n",
+                                       bl_pwm->pwm_port, bl_pwm->pwm_freq);
+                       }
+               } else {
+                       LDIMERR("invalid parameters\n");
+               }
+               break;
+       case 'd': /* duty */
+               ret = sscanf(buf, "duty %d", &val);
+               if (ret == 1) {
+                       bl_pwm->pwm_duty = val;
+                       ldim_set_duty_pwm(bl_pwm);
+                       if (ldim_debug_print) {
+                               LDIMPR("set ldim_pwm (port %d): duty = %d%%\n",
+                                       bl_pwm->pwm_port, bl_pwm->pwm_duty);
+                       }
+               } else {
+                       LDIMERR("invalid parameters\n");
+               }
+               break;
+       case 'p': /* polarity */
+               ret = sscanf(buf, "pol %d", &val);
+               if (ret == 1) {
+                       bl_pwm->pwm_method = val;
+                       bl_pwm_config_init(bl_pwm);
+                       ldim_set_duty_pwm(bl_pwm);
+                       if (ldim_debug_print) {
+                               LDIMPR("set ldim_pwm (port %d): method = %d\n",
+                                       bl_pwm->pwm_port, bl_pwm->pwm_method);
+                       }
+               } else {
+                       LDIMERR("invalid parameters\n");
+               }
+               break;
+       case 'm':
+               if (buf[1] == 'a') { /* max */
+                       ret = sscanf(buf, "max %d", &val);
+                       if (ret == 1) {
+                               bl_pwm->pwm_duty_max = val;
+                               if (ldim_dev_config.dim_range_update)
+                                       ldim_dev_config.dim_range_update();
+                               bl_pwm_config_init(bl_pwm);
+                               ldim_set_duty_pwm(bl_pwm);
+                               if (ldim_debug_print) {
+                                       LDIMPR(
+                               "set ldim_pwm (port %d): duty_max = %d%%\n",
+                                               bl_pwm->pwm_port,
+                                               bl_pwm->pwm_duty_max);
+                               }
+                       } else {
+                               LDIMERR("invalid parameters\n");
+                       }
+               } else if (buf[1] == 'i') { /* min */
+                       ret = sscanf(buf, "min %d", &val);
+                       if (ret == 1) {
+                               bl_pwm->pwm_duty_min = val;
+                               if (ldim_dev_config.dim_range_update)
+                                       ldim_dev_config.dim_range_update();
+                               bl_pwm_config_init(bl_pwm);
+                               ldim_set_duty_pwm(bl_pwm);
+                               if (ldim_debug_print) {
+                                       LDIMPR(
+                               "set ldim_pwm (port %d): duty_min = %d%%\n",
+                                               bl_pwm->pwm_port,
+                                               bl_pwm->pwm_duty_min);
+                               }
+                       } else {
+                               LDIMERR("invalid parameters\n");
+                       }
+               }
+               break;
+       default:
+               LDIMERR("wrong command\n");
+               break;
+       }
+
+       return count;
+}
+
+static ssize_t ldim_dev_pwm_analog_show(struct class *class,
+               struct class_attribute *attr, char *buf)
+{
+       struct bl_pwm_config_s *bl_pwm;
+       ssize_t len = 0;
+
+       bl_pwm = &ldim_dev_config.analog_pwm_config;
+       if (bl_pwm->pwm_port < BL_PWM_VS) {
+               len += sprintf(buf+len,
+                       "analog_pwm: freq=%d, pol=%d, duty_max=%d, duty_min=%d,",
+                       bl_pwm->pwm_freq, bl_pwm->pwm_method,
+                       bl_pwm->pwm_duty_max, bl_pwm->pwm_duty_min);
+               len += sprintf(buf+len, " duty_value=%d%%\n", bl_pwm->pwm_duty);
+       }
+
+       return len;
+}
+
+static ssize_t ldim_dev_pwm_analog_store(struct class *class,
+       struct class_attribute *attr, const char *buf, size_t count)
+{
+       unsigned int ret;
+       unsigned int val = 0;
+       struct bl_pwm_config_s *bl_pwm;
+
+       bl_pwm = &ldim_dev_config.analog_pwm_config;
+       if (bl_pwm->pwm_port >= BL_PWM_VS)
+               return count;
+
+       switch (buf[0]) {
+       case 'f': /* frequency */
+               ret = sscanf(buf, "freq %d", &val);
+               if (ret == 1) {
+                       bl_pwm->pwm_freq = val;
+                       bl_pwm_config_init(bl_pwm);
+                       ldim_set_duty_pwm(bl_pwm);
+                       if (ldim_debug_print) {
+                               LDIMPR("set ldim_pwm (port %d): freq = %dHz\n",
+                                       bl_pwm->pwm_port, bl_pwm->pwm_freq);
+                       }
+               } else {
+                       LDIMERR("invalid parameters\n");
+               }
+               break;
+       case 'd': /* duty */
+               ret = sscanf(buf, "duty %d", &val);
+               if (ret == 1) {
+                       bl_pwm->pwm_duty = val;
+                       ldim_set_duty_pwm(bl_pwm);
+                       if (ldim_debug_print) {
+                               LDIMPR("set ldim_pwm (port %d): duty = %d%%\n",
+                                       bl_pwm->pwm_port, bl_pwm->pwm_duty);
+                       }
+               } else {
+                       LDIMERR("invalid parameters\n");
+               }
+               break;
+       case 'p': /* polarity */
+               ret = sscanf(buf, "pol %d", &val);
+               if (ret == 1) {
+                       bl_pwm->pwm_method = val;
+                       bl_pwm_config_init(bl_pwm);
+                       ldim_set_duty_pwm(bl_pwm);
+                       if (ldim_debug_print) {
+                               LDIMPR("set ldim_pwm (port %d): method = %d\n",
+                                       bl_pwm->pwm_port, bl_pwm->pwm_method);
+                       }
+               } else {
+                       LDIMERR("invalid parameters\n");
+               }
+               break;
+       case 'm':
+               if (buf[1] == 'a') { /* max */
+                       ret = sscanf(buf, "max %d", &val);
+                       if (ret == 1) {
+                               bl_pwm->pwm_duty_max = val;
+                               bl_pwm_config_init(bl_pwm);
+                               ldim_set_duty_pwm(bl_pwm);
+                               if (ldim_debug_print) {
+                                       LDIMPR(
+                               "set ldim_pwm (port %d): duty_max = %d%%\n",
+                                               bl_pwm->pwm_port,
+                                               bl_pwm->pwm_duty_max);
+                               }
+                       } else {
+                               LDIMERR("invalid parameters\n");
+                       }
+               } else if (buf[1] == 'i') { /* min */
+                       ret = sscanf(buf, "min %d", &val);
+                       if (ret == 1) {
+                               bl_pwm->pwm_duty_min = val;
+                               bl_pwm_config_init(bl_pwm);
+                               ldim_set_duty_pwm(bl_pwm);
+                               if (ldim_debug_print) {
+                                       LDIMPR(
+                               "set ldim_pwm (port %d): duty_min = %d%%\n",
+                                               bl_pwm->pwm_port,
+                                               bl_pwm->pwm_duty_min);
+                               }
+                       } else {
+                               LDIMERR("invalid parameters\n");
+                       }
+               }
+               break;
+       default:
+               LDIMERR("wrong command\n");
+               break;
+       }
+
+       return count;
+}
+
+static struct class_attribute ldim_dev_class_attrs[] = {
+       __ATTR(status, 0644, ldim_dev_show, NULL),
+       __ATTR(pwm_ldim, 0644, ldim_dev_pwm_ldim_show, ldim_dev_pwm_ldim_store),
+       __ATTR(pwm_analog, 0644, ldim_dev_pwm_analog_show,
+               ldim_dev_pwm_analog_store),
+       __ATTR_NULL
+};
+
+static void ldim_dev_class_create(void)
+{
+       int ret;
+
+       ldim_dev_class.name = kzalloc(10, GFP_KERNEL);
+       if (ldim_dev_class.name == NULL) {
+               LDIMERR("%s: malloc failed\n", __func__);
+               return;
+       }
+       sprintf((char *)ldim_dev_class.name, "ldim_dev");
+       ldim_dev_class.class_attrs = ldim_dev_class_attrs;
+       ret = class_register(&ldim_dev_class);
+       if (ret < 0)
+               LDIMERR("register ldim_dev_class failed\n");
+}
+
 static int ldim_dev_add_driver(struct aml_ldim_driver_s *ldim_drv)
 {
        struct ldim_dev_config_s *ldev_conf = ldim_drv->ldev_conf;
@@ -1255,6 +1617,7 @@ static int ldim_dev_probe(struct platform_device *pdev)
                ldim_dev_get_config_from_dts(pdev->dev.of_node,
                        ldim_drv->dev_index);
 
+               ldim_dev_class_create();
                ldim_dev_add_driver(ldim_drv);
 
                /* init ldim function */
index d186f59..76c23ce 100644 (file)
@@ -26,7 +26,8 @@
 /*20181101: fix ldim_op_func null mistake, add new spi api support */
 /*20181203: add 50/60hz change & iw7027 error handle support */
 /*20181220: add tl1 support*/
-#define LDIM_DRV_VER    "20181220"
+/*20190103: add analog pwm support*/
+#define LDIM_DRV_VER    "20190103"
 
 extern unsigned char ldim_debug_print;
 
index 4348321..8efef8b 100644 (file)
@@ -48,7 +48,8 @@ static int ob3350_hw_init_on(void)
                ldim_drv->ldev_conf->en_gpio_on);
        mdelay(2);
 
-       ldim_set_duty_pwm(&(ldim_drv->ldev_conf->pwm_config));
+       ldim_set_duty_pwm(&(ldim_drv->ldev_conf->ldim_pwm_config));
+       ldim_set_duty_pwm(&(ldim_drv->ldev_conf->analog_pwm_config));
        ldim_drv->pinmux_ctrl(1);
        mdelay(20);
 
@@ -62,7 +63,8 @@ static int ob3350_hw_init_off(void)
        ldim_gpio_set(ldim_drv->ldev_conf->en_gpio,
                ldim_drv->ldev_conf->en_gpio_off);
        ldim_drv->pinmux_ctrl(0);
-       ldim_pwm_off(&(ldim_drv->ldev_conf->pwm_config));
+       ldim_pwm_off(&(ldim_drv->ldev_conf->ldim_pwm_config));
+       ldim_pwm_off(&(ldim_drv->ldev_conf->analog_pwm_config));
 
        return 0;
 }
@@ -89,12 +91,22 @@ static int ob3350_smr(unsigned short *buf, unsigned char len)
        level = buf[0];
        val = dim_min + ((level * (dim_max - dim_min)) / LD_DATA_MAX);
 
-       ldim_drv->ldev_conf->pwm_config.pwm_duty = val;
-       ldim_set_duty_pwm(&(ldim_drv->ldev_conf->pwm_config));
+       ldim_drv->ldev_conf->ldim_pwm_config.pwm_duty = val;
+       ldim_set_duty_pwm(&(ldim_drv->ldev_conf->ldim_pwm_config));
 
        return 0;
 }
 
+static void ob3350_dim_range_update(void)
+{
+       struct aml_ldim_driver_s *ldim_drv = aml_ldim_get_driver();
+       struct ldim_dev_config_s *ldim_dev;
+
+       ldim_dev = ldim_drv->ldev_conf;
+       ldim_dev->dim_max = ldim_dev->ldim_pwm_config.pwm_duty_max;
+       ldim_dev->dim_min = ldim_dev->ldim_pwm_config.pwm_duty_min;
+}
+
 static int ob3350_power_on(void)
 {
        if (ob3350_on_flag) {
@@ -138,7 +150,7 @@ static ssize_t ob3350_show(struct class *class,
                                ldim_drv->ldev_conf->en_gpio_off,
                                ldim_drv->ldev_conf->dim_max,
                                ldim_drv->ldev_conf->dim_min,
-                               ldim_drv->ldev_conf->pwm_config.pwm_duty);
+                               ldim_drv->ldev_conf->ldim_pwm_config.pwm_duty);
        }
 
        return ret;
@@ -151,6 +163,12 @@ static struct class_attribute ob3350_class_attrs[] = {
 
 static int ob3350_ldim_driver_update(struct aml_ldim_driver_s *ldim_drv)
 {
+       struct ldim_dev_config_s *ldim_dev = ldim_drv->ldev_conf;
+
+       ldim_dev->ldim_pwm_config.pwm_duty_max = ldim_dev->dim_max;
+       ldim_dev->ldim_pwm_config.pwm_duty_min = ldim_dev->dim_min;
+       ldim_dev->dim_range_update = ob3350_dim_range_update;
+
        ldim_drv->device_power_on = ob3350_power_on;
        ldim_drv->device_power_off = ob3350_power_off;
        ldim_drv->device_bri_update = ob3350_smr;
index 67b65e1..8e13c11 100644 (file)
@@ -196,5 +196,14 @@ extern void bl_pwm_ctrl(struct bl_pwm_config_s *bl_pwm, int status);
 #define BL_GPIO_OUTPUT_HIGH            1
 #define BL_GPIO_INPUT                  2
 
+static inline unsigned int bl_do_div(unsigned long long num, unsigned int den)
+{
+       unsigned long long ret = num;
+
+       do_div(ret, den);
+
+       return (unsigned int)ret;
+}
+
 #endif
 
index 6638083..c7578e9 100644 (file)
@@ -81,7 +81,9 @@ struct ldim_dev_config_s {
        unsigned int init_on_cnt;
        unsigned int init_off_cnt;
 
-       struct bl_pwm_config_s pwm_config;
+       struct bl_pwm_config_s ldim_pwm_config;
+       struct bl_pwm_config_s analog_pwm_config;
+       void (*dim_range_update)(void);
 
        unsigned short bl_regnum;
        unsigned short bl_mapping[LD_BLKREGNUM];