Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

backlight: adp8860: add support for ADP8861 & ADP8863

Signed-off-by: Michael Hennerich <michael.hennerich@analog.com>
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Signed-off-by: Richard Purdie <rpurdie@linux.intel.com>

authored by

Michael Hennerich and committed by
Richard Purdie
c7c06d8a ed601fa4

+63 -22
+3 -3
drivers/video/backlight/Kconfig
··· 275 275 be called adp5520_bl. 276 276 277 277 config BACKLIGHT_ADP8860 278 - tristate "Backlight Driver for ADP8860 using WLED" 278 + tristate "Backlight Driver for ADP8860/ADP8861/ADP8863 using WLED" 279 279 depends on BACKLIGHT_CLASS_DEVICE && I2C 280 280 select NEW_LEDS 281 281 select LEDS_CLASS 282 282 help 283 - If you have a LCD backlight connected to the ADP8860, 284 - say Y here to enable this driver. 283 + If you have a LCD backlight connected to the ADP8860, ADP8861 or 284 + ADP8863 say Y here to enable this driver. 285 285 286 286 To compile this driver as a module, choose M here: the module will 287 287 be called adp8860_bl.
+43 -19
drivers/video/backlight/adp8860_bl.c
··· 62 62 #define ADP8860_PH2LEVH 0x24 /* Second phototransistor ambient light level-high byte register */ 63 63 64 64 #define ADP8860_MANUFID 0x0 /* Analog Devices ADP8860 Manufacturer ID */ 65 - #define ADP8860_DEVICEID 0x7 /* Analog Devices ADP8860 Device ID */ 65 + #define ADP8861_MANUFID 0x4 /* Analog Devices ADP8861 Manufacturer ID */ 66 + #define ADP8863_MANUFID 0x2 /* Analog Devices ADP8863 Manufacturer ID */ 67 + 66 68 #define ADP8860_DEVID(x) ((x) & 0xF) 67 69 #define ADP8860_MANID(x) ((x) >> 4) 68 70 ··· 72 70 #define INT_CFG (1 << 6) 73 71 #define NSTBY (1 << 5) 74 72 #define DIM_EN (1 << 4) 73 + #define GDWN_DIS (1 << 3) 75 74 #define SIS_EN (1 << 2) 76 75 #define CMP_AUTOEN (1 << 1) 77 76 #define BLEN (1 << 0) ··· 88 85 #define FADE_VAL(in, out) ((0xF & (in)) | ((0xF & (out)) << 4)) 89 86 #define BL_CFGR_VAL(law, blv) ((((blv) & CFGR_BLV_MASK) << CFGR_BLV_SHIFT) | ((0x3 & (law)) << 1)) 90 87 #define ALS_CCFG_VAL(filt) ((0x7 & filt) << 5) 88 + 89 + enum { 90 + adp8860, 91 + adp8861, 92 + adp8863 93 + }; 91 94 92 95 struct adp8860_led { 93 96 struct led_classdev cdev; ··· 114 105 int id; 115 106 int revid; 116 107 int current_brightness; 108 + unsigned en_ambl_sens:1; 109 + unsigned gdwn_dis:1; 117 110 }; 118 111 119 112 static int adp8860_read(struct i2c_client *client, int reg, uint8_t *val) ··· 131 120 *val = (uint8_t)ret; 132 121 return 0; 133 122 } 134 - 135 123 136 124 static int adp8860_write(struct i2c_client *client, u8 reg, u8 val) 137 125 { ··· 331 321 struct i2c_client *client = data->client; 332 322 int ret = 0; 333 323 334 - if (data->pdata->en_ambl_sens) { 324 + if (data->en_ambl_sens) { 335 325 if ((brightness > 0) && (brightness < ADP8860_MAX_BRIGHTNESS)) { 336 326 /* Disable Ambient Light auto adjust */ 337 327 ret |= adp8860_clr_bits(client, ADP8860_MDCR, ··· 398 388 ret |= adp8860_write(client, ADP8860_BLMX1, pdata->l1_daylight_max); 399 389 ret |= adp8860_write(client, ADP8860_BLDM1, pdata->l1_daylight_dim); 400 390 401 - if (pdata->en_ambl_sens) { 391 + if (data->en_ambl_sens) { 402 392 data->cached_daylight_max = pdata->l1_daylight_max; 403 393 ret |= adp8860_write(client, ADP8860_BLMX2, 404 394 pdata->l2_office_max); ··· 423 413 ret |= adp8860_write(client, ADP8860_BLFR, FADE_VAL(pdata->bl_fade_in, 424 414 pdata->bl_fade_out)); 425 415 426 - ret |= adp8860_set_bits(client, ADP8860_MDCR, BLEN | DIM_EN | NSTBY); 416 + ret |= adp8860_set_bits(client, ADP8860_MDCR, BLEN | DIM_EN | NSTBY | 417 + (data->gdwn_dis ? GDWN_DIS : 0)); 427 418 428 419 return ret; 429 420 } ··· 674 663 return -EINVAL; 675 664 } 676 665 677 - ret = adp8860_read(client, ADP8860_MFDVID, &reg_val); 678 - if (ret < 0) 679 - return -EIO; 680 - 681 - if (ADP8860_MANID(reg_val) != ADP8860_MANUFID) { 682 - dev_err(&client->dev, "failed to probe\n"); 683 - return -ENODEV; 684 - } 685 - 686 666 data = kzalloc(sizeof(*data), GFP_KERNEL); 687 667 if (data == NULL) 688 668 return -ENOMEM; 669 + 670 + ret = adp8860_read(client, ADP8860_MFDVID, &reg_val); 671 + if (ret < 0) 672 + goto out2; 673 + 674 + switch (ADP8860_MANID(reg_val)) { 675 + case ADP8863_MANUFID: 676 + data->gdwn_dis = !!pdata->gdwn_dis; 677 + case ADP8860_MANUFID: 678 + data->en_ambl_sens = !!pdata->en_ambl_sens; 679 + break; 680 + case ADP8861_MANUFID: 681 + data->gdwn_dis = !!pdata->gdwn_dis; 682 + break; 683 + default: 684 + dev_err(&client->dev, "failed to probe\n"); 685 + ret = -ENODEV; 686 + goto out2; 687 + } 689 688 690 689 /* It's confirmed that the DEVID field is actually a REVID */ 691 690 ··· 724 703 725 704 data->bl = bl; 726 705 727 - if (pdata->en_ambl_sens) 706 + if (data->en_ambl_sens) 728 707 ret = sysfs_create_group(&bl->dev.kobj, 729 708 &adp8860_bl_attr_group); 730 709 ··· 741 720 742 721 backlight_update_status(bl); 743 722 744 - dev_info(&client->dev, "Rev.%d Backlight\n", data->revid); 723 + dev_info(&client->dev, "%s Rev.%d Backlight\n", 724 + client->name, data->revid); 745 725 746 726 if (pdata->num_leds) 747 727 adp8860_led_probe(client); ··· 750 728 return 0; 751 729 752 730 out: 753 - if (data->pdata->en_ambl_sens) 731 + if (data->en_ambl_sens) 754 732 sysfs_remove_group(&data->bl->dev.kobj, 755 733 &adp8860_bl_attr_group); 756 734 out1: ··· 771 749 if (data->led) 772 750 adp8860_led_remove(client); 773 751 774 - if (data->pdata->en_ambl_sens) 752 + if (data->en_ambl_sens) 775 753 sysfs_remove_group(&data->bl->dev.kobj, 776 754 &adp8860_bl_attr_group); 777 755 ··· 802 780 #endif 803 781 804 782 static const struct i2c_device_id adp8860_id[] = { 805 - { "adp8860", 0 }, 783 + { "adp8860", adp8860 }, 784 + { "adp8861", adp8861 }, 785 + { "adp8863", adp8863 }, 806 786 { } 807 787 }; 808 788 MODULE_DEVICE_TABLE(i2c, adp8860_id);
+17
include/linux/i2c/adp8860.h
··· 132 132 u8 led_fade_out; /* LED Fade-Out Timer */ 133 133 u8 led_fade_law; /* fade-on/fade-off transfer characteristic */ 134 134 u8 led_on_time; 135 + 136 + /** 137 + * Gain down disable. Setting this option does not allow the 138 + * charge pump to switch to lower gains. NOT AVAILABLE on ADP8860 139 + * 1 = the charge pump doesn't switch down in gain until all LEDs are 0. 140 + * The charge pump switches up in gain as needed. This feature is 141 + * useful if the ADP8863 charge pump is used to drive an external load. 142 + * This feature must be used when utilizing small fly capacitors 143 + * (0402 or smaller). 144 + * 0 = the charge pump automatically switches up and down in gain. 145 + * This provides optimal efficiency, but is not suitable for driving 146 + * loads that are not connected through the ADP8863 diode drivers. 147 + * Additionally, the charge pump fly capacitors should be low ESR 148 + * and sized 0603 or greater. 149 + */ 150 + 151 + u8 gdwn_dis; 135 152 }; 136 153 137 154 #endif /* __LINUX_I2C_ADP8860_H */