9 #include <linux/module.h>
11 #include <linux/errno.h>
14 #include <linux/i2c.h>
19 #include <linux/slab.h>
22 #define ADP8870_EXT_FEATURES
23 #define ADP8870_USE_LEDS
26 #define ADP8870_MFDVID 0x00
27 #define ADP8870_MDCR 0x01
28 #define ADP8870_INT_STAT 0x02
29 #define ADP8870_INT_EN 0x03
30 #define ADP8870_CFGR 0x04
31 #define ADP8870_BLSEL 0x05
32 #define ADP8870_PWMLED 0x06
33 #define ADP8870_BLOFF 0x07
34 #define ADP8870_BLDIM 0x08
35 #define ADP8870_BLFR 0x09
36 #define ADP8870_BLMX1 0x0A
37 #define ADP8870_BLDM1 0x0B
38 #define ADP8870_BLMX2 0x0C
39 #define ADP8870_BLDM2 0x0D
40 #define ADP8870_BLMX3 0x0E
41 #define ADP8870_BLDM3 0x0F
42 #define ADP8870_BLMX4 0x10
43 #define ADP8870_BLDM4 0x11
44 #define ADP8870_BLMX5 0x12
45 #define ADP8870_BLDM5 0x13
46 #define ADP8870_ISCLAW 0x1A
47 #define ADP8870_ISCC 0x1B
48 #define ADP8870_ISCT1 0x1C
49 #define ADP8870_ISCT2 0x1D
50 #define ADP8870_ISCF 0x1E
51 #define ADP8870_ISC1 0x1F
52 #define ADP8870_ISC2 0x20
53 #define ADP8870_ISC3 0x21
54 #define ADP8870_ISC4 0x22
55 #define ADP8870_ISC5 0x23
56 #define ADP8870_ISC6 0x24
57 #define ADP8870_ISC7 0x25
58 #define ADP8870_ISC7_L2 0x26
59 #define ADP8870_ISC7_L3 0x27
60 #define ADP8870_ISC7_L4 0x28
61 #define ADP8870_ISC7_L5 0x29
62 #define ADP8870_CMP_CTL 0x2D
63 #define ADP8870_ALS1_EN 0x2E
64 #define ADP8870_ALS2_EN 0x2F
65 #define ADP8870_ALS1_STAT 0x30
66 #define ADP8870_ALS2_STAT 0x31
67 #define ADP8870_L2TRP 0x32
68 #define ADP8870_L2HYS 0x33
69 #define ADP8870_L3TRP 0x34
70 #define ADP8870_L3HYS 0x35
71 #define ADP8870_L4TRP 0x36
72 #define ADP8870_L4HYS 0x37
73 #define ADP8870_L5TRP 0x38
74 #define ADP8870_L5HYS 0x39
75 #define ADP8870_PH1LEVL 0x40
76 #define ADP8870_PH1LEVH 0x41
77 #define ADP8870_PH2LEVL 0x42
78 #define ADP8870_PH2LEVH 0x43
80 #define ADP8870_MANUFID 0x3
81 #define ADP8870_DEVID(x) ((x) & 0xF)
82 #define ADP8870_MANID(x) ((x) >> 4)
85 #define D7ALSEN (1 << 7)
86 #define INT_CFG (1 << 6)
87 #define NSTBY (1 << 5)
88 #define DIM_EN (1 << 4)
89 #define GDWN_DIS (1 << 3)
90 #define SIS_EN (1 << 2)
91 #define CMP_AUTOEN (1 << 1)
95 #define L5_EN (1 << 3)
96 #define L4_EN (1 << 2)
97 #define L3_EN (1 << 1)
98 #define L2_EN (1 << 0)
100 #define CFGR_BLV_SHIFT 3
101 #define CFGR_BLV_MASK 0x7
102 #define ADP8870_FLAG_LED_MASK 0xFF
104 #define FADE_VAL(in, out) ((0xF & (in)) | ((0xF & (out)) << 4))
105 #define BL_CFGR_VAL(law, blv) ((((blv) & CFGR_BLV_MASK) << CFGR_BLV_SHIFT) | ((0x3 & (law)) << 1))
106 #define ALS_CMPR_CFG_VAL(filt) ((0x7 & (filt)) << 1)
135 dev_err(&client->
dev,
"failed reading at 0x%02x\n", reg);
153 static int adp8870_set_bits(
struct i2c_client *client,
int reg,
uint8_t bit_mask)
161 ret = adp8870_read(client, reg, ®_val);
163 if (!ret && ((reg_val & bit_mask) != bit_mask)) {
165 ret = adp8870_write(client, reg, reg_val);
172 static int adp8870_clr_bits(
struct i2c_client *client,
int reg,
uint8_t bit_mask)
174 struct adp8870_bl *data = i2c_get_clientdata(client);
180 ret = adp8870_read(client, reg, ®_val);
182 if (!ret && (reg_val & bit_mask)) {
183 reg_val &= ~bit_mask;
184 ret = adp8870_write(client, reg, reg_val);
194 #if defined(ADP8870_USE_LEDS)
202 static void adp8870_led_set(
struct led_classdev *led_cdev,
230 (led->
flags & 0x3) << ((led->
id - 5) * 2));
233 (led->
flags & 0x3) << ((led->
id - 1) * 2));
241 client->
dev.platform_data;
242 struct adp8870_bl *data = i2c_get_clientdata(client);
250 dev_err(&client->
dev,
"failed to alloc memory\n");
269 cur_led = &pdata->
leds[
i];
274 if (led_dat->
id > 7 || led_dat->
id < 1) {
281 dev_err(&client->
dev,
"LED %d used by Backlight\n",
288 led_dat->
cdev.brightness_set = adp8870_led_set;
297 dev_err(&client->
dev,
"failed to register LED %d\n",
302 ret = adp8870_led_setup(led_dat);
315 for (i = i - 1; i >= 0; --
i) {
326 client->
dev.platform_data;
327 struct adp8870_bl *data = i2c_get_clientdata(client);
330 for (i = 0; i < pdata->
num_leds; i++) {
355 if (data->
pdata->en_ambl_sens) {
387 ret = adp8870_set_bits(client,
390 ret = adp8870_clr_bits(client,
401 int brightness = bl->
props.brightness;
408 return adp8870_bl_set(bl, brightness);
419 .update_status = adp8870_bl_update_status,
420 .get_brightness = adp8870_bl_get_brightness,
555 error = adp8870_read(data->
client, reg, ®_val);
561 return sprintf(buf,
"%u\n", reg_val);
564 static ssize_t adp8870_store(
struct device *dev,
const char *buf,
565 size_t count,
int reg)
571 ret = kstrtoul(buf, 10, &val);
576 adp8870_write(data->
client, reg, val);
582 static ssize_t adp8870_bl_l5_dark_max_show(
struct device *dev,
588 static ssize_t adp8870_bl_l5_dark_max_store(
struct device *dev,
593 static DEVICE_ATTR(l5_dark_max, 0664, adp8870_bl_l5_dark_max_show,
594 adp8870_bl_l5_dark_max_store);
597 static ssize_t adp8870_bl_l4_indoor_max_show(
struct device *dev,
603 static ssize_t adp8870_bl_l4_indoor_max_store(
struct device *dev,
608 static DEVICE_ATTR(l4_indoor_max, 0664, adp8870_bl_l4_indoor_max_show,
609 adp8870_bl_l4_indoor_max_store);
612 static ssize_t adp8870_bl_l3_office_max_show(
struct device *dev,
618 static ssize_t adp8870_bl_l3_office_max_store(
struct device *dev,
624 static DEVICE_ATTR(l3_office_max, 0664, adp8870_bl_l3_office_max_show,
625 adp8870_bl_l3_office_max_store);
627 static ssize_t adp8870_bl_l2_bright_max_show(
struct device *dev,
633 static ssize_t adp8870_bl_l2_bright_max_store(
struct device *dev,
638 static DEVICE_ATTR(l2_bright_max, 0664, adp8870_bl_l2_bright_max_show,
639 adp8870_bl_l2_bright_max_store);
641 static ssize_t adp8870_bl_l1_daylight_max_show(
struct device *dev,
647 static ssize_t adp8870_bl_l1_daylight_max_store(
struct device *dev,
657 static DEVICE_ATTR(l1_daylight_max, 0664, adp8870_bl_l1_daylight_max_show,
658 adp8870_bl_l1_daylight_max_store);
660 static ssize_t adp8870_bl_l5_dark_dim_show(
struct device *dev,
666 static ssize_t adp8870_bl_l5_dark_dim_store(
struct device *dev,
668 const char *buf,
size_t count)
672 static DEVICE_ATTR(l5_dark_dim, 0664, adp8870_bl_l5_dark_dim_show,
673 adp8870_bl_l5_dark_dim_store);
675 static ssize_t adp8870_bl_l4_indoor_dim_show(
struct device *dev,
681 static ssize_t adp8870_bl_l4_indoor_dim_store(
struct device *dev,
683 const char *buf,
size_t count)
687 static DEVICE_ATTR(l4_indoor_dim, 0664, adp8870_bl_l4_indoor_dim_show,
688 adp8870_bl_l4_indoor_dim_store);
691 static ssize_t adp8870_bl_l3_office_dim_show(
struct device *dev,
697 static ssize_t adp8870_bl_l3_office_dim_store(
struct device *dev,
699 const char *buf,
size_t count)
703 static DEVICE_ATTR(l3_office_dim, 0664, adp8870_bl_l3_office_dim_show,
704 adp8870_bl_l3_office_dim_store);
706 static ssize_t adp8870_bl_l2_bright_dim_show(
struct device *dev,
712 static ssize_t adp8870_bl_l2_bright_dim_store(
struct device *dev,
714 const char *buf,
size_t count)
718 static DEVICE_ATTR(l2_bright_dim, 0664, adp8870_bl_l2_bright_dim_show,
719 adp8870_bl_l2_bright_dim_store);
721 static ssize_t adp8870_bl_l1_daylight_dim_show(
struct device *dev,
727 static ssize_t adp8870_bl_l1_daylight_dim_store(
struct device *dev,
729 const char *buf,
size_t count)
733 static DEVICE_ATTR(l1_daylight_dim, 0664, adp8870_bl_l1_daylight_dim_show,
734 adp8870_bl_l1_daylight_dim_store);
736 #ifdef ADP8870_EXT_FEATURES
737 static ssize_t adp8870_bl_ambient_light_level_show(
struct device *dev,
759 ret_val += (reg_val & 0x1F) << 8;
761 return sprintf(buf,
"%u\n", ret_val);
764 adp8870_bl_ambient_light_level_show,
NULL);
766 static ssize_t adp8870_bl_ambient_light_zone_show(
struct device *dev,
784 static ssize_t adp8870_bl_ambient_light_zone_store(
struct device *dev,
786 const char *buf,
size_t count)
793 ret = kstrtoul(buf, 10, &val);
800 }
else if ((val > 0) && (val < 6)) {
816 adp8870_bl_ambient_light_zone_show,
817 adp8870_bl_ambient_light_zone_store);
820 static struct attribute *adp8870_bl_attributes[] = {
821 &dev_attr_l5_dark_max.attr,
822 &dev_attr_l5_dark_dim.attr,
823 &dev_attr_l4_indoor_max.attr,
824 &dev_attr_l4_indoor_dim.attr,
825 &dev_attr_l3_office_max.attr,
826 &dev_attr_l3_office_dim.attr,
827 &dev_attr_l2_bright_max.attr,
828 &dev_attr_l2_bright_dim.attr,
829 &dev_attr_l1_daylight_max.attr,
830 &dev_attr_l1_daylight_dim.attr,
831 #ifdef ADP8870_EXT_FEATURES
832 &dev_attr_ambient_light_level.attr,
833 &dev_attr_ambient_light_zone.attr,
839 .attrs = adp8870_bl_attributes,
849 client->
dev.platform_data;
853 if (!i2c_check_functionality(client->
adapter,
855 dev_err(&client->
dev,
"SMBUS Byte Data not Supported\n");
880 data->
id =
id->driver_data;
882 i2c_set_clientdata(client, data);
886 memset(&props, 0,
sizeof(props));
890 &client->
dev, data, &adp8870_bl_ops, &props);
892 dev_err(&client->
dev,
"failed to register backlight\n");
900 &adp8870_bl_attr_group);
903 dev_err(&client->
dev,
"failed to register sysfs\n");
907 ret = adp8870_bl_setup(bl);
913 backlight_update_status(bl);
918 adp8870_led_probe(client);
923 if (data->
pdata->en_ambl_sens)
925 &adp8870_bl_attr_group);
934 struct adp8870_bl *data = i2c_get_clientdata(client);
939 adp8870_led_remove(client);
941 if (data->
pdata->en_ambl_sens)
943 &adp8870_bl_attr_group);
965 #define adp8870_i2c_suspend NULL
966 #define adp8870_i2c_resume NULL
977 .name = KBUILD_MODNAME,
979 .probe = adp8870_probe,
983 .id_table = adp8870_id,