1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Backlight driver for Analog Devices ADP8870 Backlight Devices 4 * 5 * Copyright 2009-2011 Analog Devices Inc. 6 */ 7 8 #include <linux/module.h> 9 #include <linux/init.h> 10 #include <linux/errno.h> 11 #include <linux/pm.h> 12 #include <linux/platform_device.h> 13 #include <linux/i2c.h> 14 #include <linux/backlight.h> 15 #include <linux/leds.h> 16 #include <linux/workqueue.h> 17 #include <linux/slab.h> 18 19 #include <linux/platform_data/adp8870.h> 20 #define ADP8870_EXT_FEATURES 21 #define ADP8870_USE_LEDS 22 23 24 #define ADP8870_MFDVID 0x00 /* Manufacturer and device ID */ 25 #define ADP8870_MDCR 0x01 /* Device mode and status */ 26 #define ADP8870_INT_STAT 0x02 /* Interrupts status */ 27 #define ADP8870_INT_EN 0x03 /* Interrupts enable */ 28 #define ADP8870_CFGR 0x04 /* Configuration register */ 29 #define ADP8870_BLSEL 0x05 /* Sink enable backlight or independent */ 30 #define ADP8870_PWMLED 0x06 /* PWM Enable Selection Register */ 31 #define ADP8870_BLOFF 0x07 /* Backlight off timeout */ 32 #define ADP8870_BLDIM 0x08 /* Backlight dim timeout */ 33 #define ADP8870_BLFR 0x09 /* Backlight fade in and out rates */ 34 #define ADP8870_BLMX1 0x0A /* Backlight (Brightness Level 1-daylight) maximum current */ 35 #define ADP8870_BLDM1 0x0B /* Backlight (Brightness Level 1-daylight) dim current */ 36 #define ADP8870_BLMX2 0x0C /* Backlight (Brightness Level 2-bright) maximum current */ 37 #define ADP8870_BLDM2 0x0D /* Backlight (Brightness Level 2-bright) dim current */ 38 #define ADP8870_BLMX3 0x0E /* Backlight (Brightness Level 3-office) maximum current */ 39 #define ADP8870_BLDM3 0x0F /* Backlight (Brightness Level 3-office) dim current */ 40 #define ADP8870_BLMX4 0x10 /* Backlight (Brightness Level 4-indoor) maximum current */ 41 #define ADP8870_BLDM4 0x11 /* Backlight (Brightness Level 4-indoor) dim current */ 42 #define ADP8870_BLMX5 0x12 /* Backlight (Brightness Level 5-dark) maximum current */ 43 #define ADP8870_BLDM5 0x13 /* Backlight (Brightness Level 5-dark) dim current */ 44 #define ADP8870_ISCLAW 0x1A /* Independent sink current fade law register */ 45 #define ADP8870_ISCC 0x1B /* Independent sink current control register */ 46 #define ADP8870_ISCT1 0x1C /* Independent Sink Current Timer Register LED[7:5] */ 47 #define ADP8870_ISCT2 0x1D /* Independent Sink Current Timer Register LED[4:1] */ 48 #define ADP8870_ISCF 0x1E /* Independent sink current fade register */ 49 #define ADP8870_ISC1 0x1F /* Independent Sink Current LED1 */ 50 #define ADP8870_ISC2 0x20 /* Independent Sink Current LED2 */ 51 #define ADP8870_ISC3 0x21 /* Independent Sink Current LED3 */ 52 #define ADP8870_ISC4 0x22 /* Independent Sink Current LED4 */ 53 #define ADP8870_ISC5 0x23 /* Independent Sink Current LED5 */ 54 #define ADP8870_ISC6 0x24 /* Independent Sink Current LED6 */ 55 #define ADP8870_ISC7 0x25 /* Independent Sink Current LED7 (Brightness Level 1-daylight) */ 56 #define ADP8870_ISC7_L2 0x26 /* Independent Sink Current LED7 (Brightness Level 2-bright) */ 57 #define ADP8870_ISC7_L3 0x27 /* Independent Sink Current LED7 (Brightness Level 3-office) */ 58 #define ADP8870_ISC7_L4 0x28 /* Independent Sink Current LED7 (Brightness Level 4-indoor) */ 59 #define ADP8870_ISC7_L5 0x29 /* Independent Sink Current LED7 (Brightness Level 5-dark) */ 60 #define ADP8870_CMP_CTL 0x2D /* ALS Comparator Control Register */ 61 #define ADP8870_ALS1_EN 0x2E /* Main ALS comparator level enable */ 62 #define ADP8870_ALS2_EN 0x2F /* Second ALS comparator level enable */ 63 #define ADP8870_ALS1_STAT 0x30 /* Main ALS Comparator Status Register */ 64 #define ADP8870_ALS2_STAT 0x31 /* Second ALS Comparator Status Register */ 65 #define ADP8870_L2TRP 0x32 /* L2 comparator reference */ 66 #define ADP8870_L2HYS 0x33 /* L2 hysteresis */ 67 #define ADP8870_L3TRP 0x34 /* L3 comparator reference */ 68 #define ADP8870_L3HYS 0x35 /* L3 hysteresis */ 69 #define ADP8870_L4TRP 0x36 /* L4 comparator reference */ 70 #define ADP8870_L4HYS 0x37 /* L4 hysteresis */ 71 #define ADP8870_L5TRP 0x38 /* L5 comparator reference */ 72 #define ADP8870_L5HYS 0x39 /* L5 hysteresis */ 73 #define ADP8870_PH1LEVL 0x40 /* First phototransistor ambient light level-low byte register */ 74 #define ADP8870_PH1LEVH 0x41 /* First phototransistor ambient light level-high byte register */ 75 #define ADP8870_PH2LEVL 0x42 /* Second phototransistor ambient light level-low byte register */ 76 #define ADP8870_PH2LEVH 0x43 /* Second phototransistor ambient light level-high byte register */ 77 78 #define ADP8870_MANUFID 0x3 /* Analog Devices AD8870 Manufacturer and device ID */ 79 #define ADP8870_DEVID(x) ((x) & 0xF) 80 #define ADP8870_MANID(x) ((x) >> 4) 81 82 /* MDCR Device mode and status */ 83 #define D7ALSEN (1 << 7) 84 #define INT_CFG (1 << 6) 85 #define NSTBY (1 << 5) 86 #define DIM_EN (1 << 4) 87 #define GDWN_DIS (1 << 3) 88 #define SIS_EN (1 << 2) 89 #define CMP_AUTOEN (1 << 1) 90 #define BLEN (1 << 0) 91 92 /* ADP8870_ALS1_EN Main ALS comparator level enable */ 93 #define L5_EN (1 << 3) 94 #define L4_EN (1 << 2) 95 #define L3_EN (1 << 1) 96 #define L2_EN (1 << 0) 97 98 #define CFGR_BLV_SHIFT 3 99 #define CFGR_BLV_MASK 0x7 100 #define ADP8870_FLAG_LED_MASK 0xFF 101 102 #define FADE_VAL(in, out) ((0xF & (in)) | ((0xF & (out)) << 4)) 103 #define BL_CFGR_VAL(law, blv) ((((blv) & CFGR_BLV_MASK) << CFGR_BLV_SHIFT) | ((0x3 & (law)) << 1)) 104 #define ALS_CMPR_CFG_VAL(filt) ((0x7 & (filt)) << 1) 105 106 struct adp8870_bl { 107 struct i2c_client *client; 108 struct backlight_device *bl; 109 struct adp8870_led *led; 110 struct adp8870_backlight_platform_data *pdata; 111 struct mutex lock; 112 unsigned long cached_daylight_max; 113 int id; 114 int revid; 115 int current_brightness; 116 }; 117 118 struct adp8870_led { 119 struct led_classdev cdev; 120 struct work_struct work; 121 struct i2c_client *client; 122 enum led_brightness new_brightness; 123 int id; 124 int flags; 125 }; 126 127 static int adp8870_read(struct i2c_client *client, int reg, uint8_t *val) 128 { 129 int ret; 130 131 ret = i2c_smbus_read_byte_data(client, reg); 132 if (ret < 0) { 133 dev_err(&client->dev, "failed reading at 0x%02x\n", reg); 134 return ret; 135 } 136 137 *val = ret; 138 return 0; 139 } 140 141 142 static int adp8870_write(struct i2c_client *client, u8 reg, u8 val) 143 { 144 int ret = i2c_smbus_write_byte_data(client, reg, val); 145 146 if (ret) 147 dev_err(&client->dev, "failed to write\n"); 148 149 return ret; 150 } 151 152 static int adp8870_set_bits(struct i2c_client *client, int reg, uint8_t bit_mask) 153 { 154 struct adp8870_bl *data = i2c_get_clientdata(client); 155 uint8_t reg_val; 156 int ret; 157 158 mutex_lock(&data->lock); 159 160 ret = adp8870_read(client, reg, ®_val); 161 162 if (!ret && ((reg_val & bit_mask) != bit_mask)) { 163 reg_val |= bit_mask; 164 ret = adp8870_write(client, reg, reg_val); 165 } 166 167 mutex_unlock(&data->lock); 168 return ret; 169 } 170 171 static int adp8870_clr_bits(struct i2c_client *client, int reg, uint8_t bit_mask) 172 { 173 struct adp8870_bl *data = i2c_get_clientdata(client); 174 uint8_t reg_val; 175 int ret; 176 177 mutex_lock(&data->lock); 178 179 ret = adp8870_read(client, reg, ®_val); 180 181 if (!ret && (reg_val & bit_mask)) { 182 reg_val &= ~bit_mask; 183 ret = adp8870_write(client, reg, reg_val); 184 } 185 186 mutex_unlock(&data->lock); 187 return ret; 188 } 189 190 /* 191 * Independent sink / LED 192 */ 193 #if defined(ADP8870_USE_LEDS) 194 static void adp8870_led_work(struct work_struct *work) 195 { 196 struct adp8870_led *led = container_of(work, struct adp8870_led, work); 197 198 adp8870_write(led->client, ADP8870_ISC1 + led->id - 1, 199 led->new_brightness >> 1); 200 } 201 202 static void adp8870_led_set(struct led_classdev *led_cdev, 203 enum led_brightness value) 204 { 205 struct adp8870_led *led; 206 207 led = container_of(led_cdev, struct adp8870_led, cdev); 208 led->new_brightness = value; 209 /* 210 * Use workqueue for IO since I2C operations can sleep. 211 */ 212 schedule_work(&led->work); 213 } 214 215 static int adp8870_led_setup(struct adp8870_led *led) 216 { 217 struct i2c_client *client = led->client; 218 int ret = 0; 219 220 ret = adp8870_write(client, ADP8870_ISC1 + led->id - 1, 0); 221 if (ret) 222 return ret; 223 224 ret = adp8870_set_bits(client, ADP8870_ISCC, 1 << (led->id - 1)); 225 if (ret) 226 return ret; 227 228 if (led->id > 4) 229 ret = adp8870_set_bits(client, ADP8870_ISCT1, 230 (led->flags & 0x3) << ((led->id - 5) * 2)); 231 else 232 ret = adp8870_set_bits(client, ADP8870_ISCT2, 233 (led->flags & 0x3) << ((led->id - 1) * 2)); 234 235 return ret; 236 } 237 238 static int adp8870_led_probe(struct i2c_client *client) 239 { 240 struct adp8870_backlight_platform_data *pdata = 241 dev_get_platdata(&client->dev); 242 struct adp8870_bl *data = i2c_get_clientdata(client); 243 struct adp8870_led *led, *led_dat; 244 struct led_info *cur_led; 245 int ret, i; 246 247 led = devm_kcalloc(&client->dev, pdata->num_leds, sizeof(*led), 248 GFP_KERNEL); 249 if (led == NULL) 250 return -ENOMEM; 251 252 ret = adp8870_write(client, ADP8870_ISCLAW, pdata->led_fade_law); 253 if (ret) 254 return ret; 255 256 ret = adp8870_write(client, ADP8870_ISCT1, 257 (pdata->led_on_time & 0x3) << 6); 258 if (ret) 259 return ret; 260 261 ret = adp8870_write(client, ADP8870_ISCF, 262 FADE_VAL(pdata->led_fade_in, pdata->led_fade_out)); 263 if (ret) 264 return ret; 265 266 for (i = 0; i < pdata->num_leds; ++i) { 267 cur_led = &pdata->leds[i]; 268 led_dat = &led[i]; 269 270 led_dat->id = cur_led->flags & ADP8870_FLAG_LED_MASK; 271 272 if (led_dat->id > 7 || led_dat->id < 1) { 273 dev_err(&client->dev, "Invalid LED ID %d\n", 274 led_dat->id); 275 ret = -EINVAL; 276 goto err; 277 } 278 279 if (pdata->bl_led_assign & (1 << (led_dat->id - 1))) { 280 dev_err(&client->dev, "LED %d used by Backlight\n", 281 led_dat->id); 282 ret = -EBUSY; 283 goto err; 284 } 285 286 led_dat->cdev.name = cur_led->name; 287 led_dat->cdev.default_trigger = cur_led->default_trigger; 288 led_dat->cdev.brightness_set = adp8870_led_set; 289 led_dat->cdev.brightness = LED_OFF; 290 led_dat->flags = cur_led->flags >> FLAG_OFFT_SHIFT; 291 led_dat->client = client; 292 led_dat->new_brightness = LED_OFF; 293 INIT_WORK(&led_dat->work, adp8870_led_work); 294 295 ret = led_classdev_register(&client->dev, &led_dat->cdev); 296 if (ret) { 297 dev_err(&client->dev, "failed to register LED %d\n", 298 led_dat->id); 299 goto err; 300 } 301 302 ret = adp8870_led_setup(led_dat); 303 if (ret) { 304 dev_err(&client->dev, "failed to write\n"); 305 i++; 306 goto err; 307 } 308 } 309 310 data->led = led; 311 312 return 0; 313 314 err: 315 for (i = i - 1; i >= 0; --i) { 316 led_classdev_unregister(&led[i].cdev); 317 cancel_work_sync(&led[i].work); 318 } 319 320 return ret; 321 } 322 323 static int adp8870_led_remove(struct i2c_client *client) 324 { 325 struct adp8870_backlight_platform_data *pdata = 326 dev_get_platdata(&client->dev); 327 struct adp8870_bl *data = i2c_get_clientdata(client); 328 int i; 329 330 for (i = 0; i < pdata->num_leds; i++) { 331 led_classdev_unregister(&data->led[i].cdev); 332 cancel_work_sync(&data->led[i].work); 333 } 334 335 return 0; 336 } 337 #else 338 static int adp8870_led_probe(struct i2c_client *client) 339 { 340 return 0; 341 } 342 343 static int adp8870_led_remove(struct i2c_client *client) 344 { 345 return 0; 346 } 347 #endif 348 349 static int adp8870_bl_set(struct backlight_device *bl, int brightness) 350 { 351 struct adp8870_bl *data = bl_get_data(bl); 352 struct i2c_client *client = data->client; 353 int ret = 0; 354 355 if (data->pdata->en_ambl_sens) { 356 if ((brightness > 0) && (brightness < ADP8870_MAX_BRIGHTNESS)) { 357 /* Disable Ambient Light auto adjust */ 358 ret = adp8870_clr_bits(client, ADP8870_MDCR, 359 CMP_AUTOEN); 360 if (ret) 361 return ret; 362 ret = adp8870_write(client, ADP8870_BLMX1, brightness); 363 if (ret) 364 return ret; 365 } else { 366 /* 367 * MAX_BRIGHTNESS -> Enable Ambient Light auto adjust 368 * restore daylight l1 sysfs brightness 369 */ 370 ret = adp8870_write(client, ADP8870_BLMX1, 371 data->cached_daylight_max); 372 if (ret) 373 return ret; 374 375 ret = adp8870_set_bits(client, ADP8870_MDCR, 376 CMP_AUTOEN); 377 if (ret) 378 return ret; 379 } 380 } else { 381 ret = adp8870_write(client, ADP8870_BLMX1, brightness); 382 if (ret) 383 return ret; 384 } 385 386 if (data->current_brightness && brightness == 0) 387 ret = adp8870_set_bits(client, 388 ADP8870_MDCR, DIM_EN); 389 else if (data->current_brightness == 0 && brightness) 390 ret = adp8870_clr_bits(client, 391 ADP8870_MDCR, DIM_EN); 392 393 if (!ret) 394 data->current_brightness = brightness; 395 396 return ret; 397 } 398 399 static int adp8870_bl_update_status(struct backlight_device *bl) 400 { 401 return adp8870_bl_set(bl, backlight_get_brightness(bl)); 402 } 403 404 static int adp8870_bl_get_brightness(struct backlight_device *bl) 405 { 406 struct adp8870_bl *data = bl_get_data(bl); 407 408 return data->current_brightness; 409 } 410 411 static const struct backlight_ops adp8870_bl_ops = { 412 .update_status = adp8870_bl_update_status, 413 .get_brightness = adp8870_bl_get_brightness, 414 }; 415 416 static int adp8870_bl_setup(struct backlight_device *bl) 417 { 418 struct adp8870_bl *data = bl_get_data(bl); 419 struct i2c_client *client = data->client; 420 struct adp8870_backlight_platform_data *pdata = data->pdata; 421 int ret = 0; 422 423 ret = adp8870_write(client, ADP8870_BLSEL, ~pdata->bl_led_assign); 424 if (ret) 425 return ret; 426 427 ret = adp8870_write(client, ADP8870_PWMLED, pdata->pwm_assign); 428 if (ret) 429 return ret; 430 431 ret = adp8870_write(client, ADP8870_BLMX1, pdata->l1_daylight_max); 432 if (ret) 433 return ret; 434 435 ret = adp8870_write(client, ADP8870_BLDM1, pdata->l1_daylight_dim); 436 if (ret) 437 return ret; 438 439 if (pdata->en_ambl_sens) { 440 data->cached_daylight_max = pdata->l1_daylight_max; 441 ret = adp8870_write(client, ADP8870_BLMX2, 442 pdata->l2_bright_max); 443 if (ret) 444 return ret; 445 ret = adp8870_write(client, ADP8870_BLDM2, 446 pdata->l2_bright_dim); 447 if (ret) 448 return ret; 449 450 ret = adp8870_write(client, ADP8870_BLMX3, 451 pdata->l3_office_max); 452 if (ret) 453 return ret; 454 ret = adp8870_write(client, ADP8870_BLDM3, 455 pdata->l3_office_dim); 456 if (ret) 457 return ret; 458 459 ret = adp8870_write(client, ADP8870_BLMX4, 460 pdata->l4_indoor_max); 461 if (ret) 462 return ret; 463 464 ret = adp8870_write(client, ADP8870_BLDM4, 465 pdata->l4_indor_dim); 466 if (ret) 467 return ret; 468 469 ret = adp8870_write(client, ADP8870_BLMX5, 470 pdata->l5_dark_max); 471 if (ret) 472 return ret; 473 474 ret = adp8870_write(client, ADP8870_BLDM5, 475 pdata->l5_dark_dim); 476 if (ret) 477 return ret; 478 479 ret = adp8870_write(client, ADP8870_L2TRP, pdata->l2_trip); 480 if (ret) 481 return ret; 482 483 ret = adp8870_write(client, ADP8870_L2HYS, pdata->l2_hyst); 484 if (ret) 485 return ret; 486 487 ret = adp8870_write(client, ADP8870_L3TRP, pdata->l3_trip); 488 if (ret) 489 return ret; 490 491 ret = adp8870_write(client, ADP8870_L3HYS, pdata->l3_hyst); 492 if (ret) 493 return ret; 494 495 ret = adp8870_write(client, ADP8870_L4TRP, pdata->l4_trip); 496 if (ret) 497 return ret; 498 499 ret = adp8870_write(client, ADP8870_L4HYS, pdata->l4_hyst); 500 if (ret) 501 return ret; 502 503 ret = adp8870_write(client, ADP8870_L5TRP, pdata->l5_trip); 504 if (ret) 505 return ret; 506 507 ret = adp8870_write(client, ADP8870_L5HYS, pdata->l5_hyst); 508 if (ret) 509 return ret; 510 511 ret = adp8870_write(client, ADP8870_ALS1_EN, L5_EN | L4_EN | 512 L3_EN | L2_EN); 513 if (ret) 514 return ret; 515 516 ret = adp8870_write(client, ADP8870_CMP_CTL, 517 ALS_CMPR_CFG_VAL(pdata->abml_filt)); 518 if (ret) 519 return ret; 520 } 521 522 ret = adp8870_write(client, ADP8870_CFGR, 523 BL_CFGR_VAL(pdata->bl_fade_law, 0)); 524 if (ret) 525 return ret; 526 527 ret = adp8870_write(client, ADP8870_BLFR, FADE_VAL(pdata->bl_fade_in, 528 pdata->bl_fade_out)); 529 if (ret) 530 return ret; 531 /* 532 * ADP8870 Rev0 requires GDWN_DIS bit set 533 */ 534 535 ret = adp8870_set_bits(client, ADP8870_MDCR, BLEN | DIM_EN | NSTBY | 536 (data->revid == 0 ? GDWN_DIS : 0)); 537 538 return ret; 539 } 540 541 static ssize_t adp8870_show(struct device *dev, char *buf, int reg) 542 { 543 struct adp8870_bl *data = dev_get_drvdata(dev); 544 int error; 545 uint8_t reg_val; 546 547 mutex_lock(&data->lock); 548 error = adp8870_read(data->client, reg, ®_val); 549 mutex_unlock(&data->lock); 550 551 if (error < 0) 552 return error; 553 554 return sprintf(buf, "%u\n", reg_val); 555 } 556 557 static ssize_t adp8870_store(struct device *dev, const char *buf, 558 size_t count, int reg) 559 { 560 struct adp8870_bl *data = dev_get_drvdata(dev); 561 unsigned long val; 562 int ret; 563 564 ret = kstrtoul(buf, 10, &val); 565 if (ret) 566 return ret; 567 568 mutex_lock(&data->lock); 569 adp8870_write(data->client, reg, val); 570 mutex_unlock(&data->lock); 571 572 return count; 573 } 574 575 static ssize_t adp8870_bl_l5_dark_max_show(struct device *dev, 576 struct device_attribute *attr, char *buf) 577 { 578 return adp8870_show(dev, buf, ADP8870_BLMX5); 579 } 580 581 static ssize_t adp8870_bl_l5_dark_max_store(struct device *dev, 582 struct device_attribute *attr, const char *buf, size_t count) 583 { 584 return adp8870_store(dev, buf, count, ADP8870_BLMX5); 585 } 586 static DEVICE_ATTR(l5_dark_max, 0664, adp8870_bl_l5_dark_max_show, 587 adp8870_bl_l5_dark_max_store); 588 589 590 static ssize_t adp8870_bl_l4_indoor_max_show(struct device *dev, 591 struct device_attribute *attr, char *buf) 592 { 593 return adp8870_show(dev, buf, ADP8870_BLMX4); 594 } 595 596 static ssize_t adp8870_bl_l4_indoor_max_store(struct device *dev, 597 struct device_attribute *attr, const char *buf, size_t count) 598 { 599 return adp8870_store(dev, buf, count, ADP8870_BLMX4); 600 } 601 static DEVICE_ATTR(l4_indoor_max, 0664, adp8870_bl_l4_indoor_max_show, 602 adp8870_bl_l4_indoor_max_store); 603 604 605 static ssize_t adp8870_bl_l3_office_max_show(struct device *dev, 606 struct device_attribute *attr, char *buf) 607 { 608 return adp8870_show(dev, buf, ADP8870_BLMX3); 609 } 610 611 static ssize_t adp8870_bl_l3_office_max_store(struct device *dev, 612 struct device_attribute *attr, const char *buf, size_t count) 613 { 614 return adp8870_store(dev, buf, count, ADP8870_BLMX3); 615 } 616 617 static DEVICE_ATTR(l3_office_max, 0664, adp8870_bl_l3_office_max_show, 618 adp8870_bl_l3_office_max_store); 619 620 static ssize_t adp8870_bl_l2_bright_max_show(struct device *dev, 621 struct device_attribute *attr, char *buf) 622 { 623 return adp8870_show(dev, buf, ADP8870_BLMX2); 624 } 625 626 static ssize_t adp8870_bl_l2_bright_max_store(struct device *dev, 627 struct device_attribute *attr, const char *buf, size_t count) 628 { 629 return adp8870_store(dev, buf, count, ADP8870_BLMX2); 630 } 631 static DEVICE_ATTR(l2_bright_max, 0664, adp8870_bl_l2_bright_max_show, 632 adp8870_bl_l2_bright_max_store); 633 634 static ssize_t adp8870_bl_l1_daylight_max_show(struct device *dev, 635 struct device_attribute *attr, char *buf) 636 { 637 return adp8870_show(dev, buf, ADP8870_BLMX1); 638 } 639 640 static ssize_t adp8870_bl_l1_daylight_max_store(struct device *dev, 641 struct device_attribute *attr, const char *buf, size_t count) 642 { 643 struct adp8870_bl *data = dev_get_drvdata(dev); 644 int ret = kstrtoul(buf, 10, &data->cached_daylight_max); 645 646 if (ret) 647 return ret; 648 649 return adp8870_store(dev, buf, count, ADP8870_BLMX1); 650 } 651 static DEVICE_ATTR(l1_daylight_max, 0664, adp8870_bl_l1_daylight_max_show, 652 adp8870_bl_l1_daylight_max_store); 653 654 static ssize_t adp8870_bl_l5_dark_dim_show(struct device *dev, 655 struct device_attribute *attr, char *buf) 656 { 657 return adp8870_show(dev, buf, ADP8870_BLDM5); 658 } 659 660 static ssize_t adp8870_bl_l5_dark_dim_store(struct device *dev, 661 struct device_attribute *attr, 662 const char *buf, size_t count) 663 { 664 return adp8870_store(dev, buf, count, ADP8870_BLDM5); 665 } 666 static DEVICE_ATTR(l5_dark_dim, 0664, adp8870_bl_l5_dark_dim_show, 667 adp8870_bl_l5_dark_dim_store); 668 669 static ssize_t adp8870_bl_l4_indoor_dim_show(struct device *dev, 670 struct device_attribute *attr, char *buf) 671 { 672 return adp8870_show(dev, buf, ADP8870_BLDM4); 673 } 674 675 static ssize_t adp8870_bl_l4_indoor_dim_store(struct device *dev, 676 struct device_attribute *attr, 677 const char *buf, size_t count) 678 { 679 return adp8870_store(dev, buf, count, ADP8870_BLDM4); 680 } 681 static DEVICE_ATTR(l4_indoor_dim, 0664, adp8870_bl_l4_indoor_dim_show, 682 adp8870_bl_l4_indoor_dim_store); 683 684 685 static ssize_t adp8870_bl_l3_office_dim_show(struct device *dev, 686 struct device_attribute *attr, char *buf) 687 { 688 return adp8870_show(dev, buf, ADP8870_BLDM3); 689 } 690 691 static ssize_t adp8870_bl_l3_office_dim_store(struct device *dev, 692 struct device_attribute *attr, 693 const char *buf, size_t count) 694 { 695 return adp8870_store(dev, buf, count, ADP8870_BLDM3); 696 } 697 static DEVICE_ATTR(l3_office_dim, 0664, adp8870_bl_l3_office_dim_show, 698 adp8870_bl_l3_office_dim_store); 699 700 static ssize_t adp8870_bl_l2_bright_dim_show(struct device *dev, 701 struct device_attribute *attr, char *buf) 702 { 703 return adp8870_show(dev, buf, ADP8870_BLDM2); 704 } 705 706 static ssize_t adp8870_bl_l2_bright_dim_store(struct device *dev, 707 struct device_attribute *attr, 708 const char *buf, size_t count) 709 { 710 return adp8870_store(dev, buf, count, ADP8870_BLDM2); 711 } 712 static DEVICE_ATTR(l2_bright_dim, 0664, adp8870_bl_l2_bright_dim_show, 713 adp8870_bl_l2_bright_dim_store); 714 715 static ssize_t adp8870_bl_l1_daylight_dim_show(struct device *dev, 716 struct device_attribute *attr, char *buf) 717 { 718 return adp8870_show(dev, buf, ADP8870_BLDM1); 719 } 720 721 static ssize_t adp8870_bl_l1_daylight_dim_store(struct device *dev, 722 struct device_attribute *attr, 723 const char *buf, size_t count) 724 { 725 return adp8870_store(dev, buf, count, ADP8870_BLDM1); 726 } 727 static DEVICE_ATTR(l1_daylight_dim, 0664, adp8870_bl_l1_daylight_dim_show, 728 adp8870_bl_l1_daylight_dim_store); 729 730 #ifdef ADP8870_EXT_FEATURES 731 static ssize_t adp8870_bl_ambient_light_level_show(struct device *dev, 732 struct device_attribute *attr, char *buf) 733 { 734 struct adp8870_bl *data = dev_get_drvdata(dev); 735 int error; 736 uint8_t reg_val; 737 uint16_t ret_val; 738 739 mutex_lock(&data->lock); 740 error = adp8870_read(data->client, ADP8870_PH1LEVL, ®_val); 741 if (error < 0) { 742 mutex_unlock(&data->lock); 743 return error; 744 } 745 ret_val = reg_val; 746 error = adp8870_read(data->client, ADP8870_PH1LEVH, ®_val); 747 mutex_unlock(&data->lock); 748 749 if (error < 0) 750 return error; 751 752 /* Return 13-bit conversion value for the first light sensor */ 753 ret_val += (reg_val & 0x1F) << 8; 754 755 return sprintf(buf, "%u\n", ret_val); 756 } 757 static DEVICE_ATTR(ambient_light_level, 0444, 758 adp8870_bl_ambient_light_level_show, NULL); 759 760 static ssize_t adp8870_bl_ambient_light_zone_show(struct device *dev, 761 struct device_attribute *attr, char *buf) 762 { 763 struct adp8870_bl *data = dev_get_drvdata(dev); 764 int error; 765 uint8_t reg_val; 766 767 mutex_lock(&data->lock); 768 error = adp8870_read(data->client, ADP8870_CFGR, ®_val); 769 mutex_unlock(&data->lock); 770 771 if (error < 0) 772 return error; 773 774 return sprintf(buf, "%u\n", 775 ((reg_val >> CFGR_BLV_SHIFT) & CFGR_BLV_MASK) + 1); 776 } 777 778 static ssize_t adp8870_bl_ambient_light_zone_store(struct device *dev, 779 struct device_attribute *attr, 780 const char *buf, size_t count) 781 { 782 struct adp8870_bl *data = dev_get_drvdata(dev); 783 unsigned long val; 784 uint8_t reg_val; 785 int ret; 786 787 ret = kstrtoul(buf, 10, &val); 788 if (ret) 789 return ret; 790 791 if (val == 0) { 792 /* Enable automatic ambient light sensing */ 793 adp8870_set_bits(data->client, ADP8870_MDCR, CMP_AUTOEN); 794 } else if ((val > 0) && (val < 6)) { 795 /* Disable automatic ambient light sensing */ 796 adp8870_clr_bits(data->client, ADP8870_MDCR, CMP_AUTOEN); 797 798 /* Set user supplied ambient light zone */ 799 mutex_lock(&data->lock); 800 ret = adp8870_read(data->client, ADP8870_CFGR, ®_val); 801 if (!ret) { 802 reg_val &= ~(CFGR_BLV_MASK << CFGR_BLV_SHIFT); 803 reg_val |= (val - 1) << CFGR_BLV_SHIFT; 804 adp8870_write(data->client, ADP8870_CFGR, reg_val); 805 } 806 mutex_unlock(&data->lock); 807 } 808 809 return count; 810 } 811 static DEVICE_ATTR(ambient_light_zone, 0664, 812 adp8870_bl_ambient_light_zone_show, 813 adp8870_bl_ambient_light_zone_store); 814 #endif 815 816 static struct attribute *adp8870_bl_attributes[] = { 817 &dev_attr_l5_dark_max.attr, 818 &dev_attr_l5_dark_dim.attr, 819 &dev_attr_l4_indoor_max.attr, 820 &dev_attr_l4_indoor_dim.attr, 821 &dev_attr_l3_office_max.attr, 822 &dev_attr_l3_office_dim.attr, 823 &dev_attr_l2_bright_max.attr, 824 &dev_attr_l2_bright_dim.attr, 825 &dev_attr_l1_daylight_max.attr, 826 &dev_attr_l1_daylight_dim.attr, 827 #ifdef ADP8870_EXT_FEATURES 828 &dev_attr_ambient_light_level.attr, 829 &dev_attr_ambient_light_zone.attr, 830 #endif 831 NULL 832 }; 833 834 static const struct attribute_group adp8870_bl_attr_group = { 835 .attrs = adp8870_bl_attributes, 836 }; 837 838 static int adp8870_probe(struct i2c_client *client) 839 { 840 const struct i2c_device_id *id = i2c_client_get_device_id(client); 841 struct backlight_properties props; 842 struct backlight_device *bl; 843 struct adp8870_bl *data; 844 struct adp8870_backlight_platform_data *pdata = 845 dev_get_platdata(&client->dev); 846 uint8_t reg_val; 847 int ret; 848 849 if (!i2c_check_functionality(client->adapter, 850 I2C_FUNC_SMBUS_BYTE_DATA)) { 851 dev_err(&client->dev, "SMBUS Byte Data not Supported\n"); 852 return -EIO; 853 } 854 855 if (!pdata) { 856 dev_err(&client->dev, "no platform data?\n"); 857 return -EINVAL; 858 } 859 860 ret = adp8870_read(client, ADP8870_MFDVID, ®_val); 861 if (ret < 0) 862 return -EIO; 863 864 if (ADP8870_MANID(reg_val) != ADP8870_MANUFID) { 865 dev_err(&client->dev, "failed to probe\n"); 866 return -ENODEV; 867 } 868 869 data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL); 870 if (data == NULL) 871 return -ENOMEM; 872 873 data->revid = ADP8870_DEVID(reg_val); 874 data->client = client; 875 data->pdata = pdata; 876 data->id = id->driver_data; 877 data->current_brightness = 0; 878 i2c_set_clientdata(client, data); 879 880 mutex_init(&data->lock); 881 882 memset(&props, 0, sizeof(props)); 883 props.type = BACKLIGHT_RAW; 884 props.max_brightness = props.brightness = ADP8870_MAX_BRIGHTNESS; 885 bl = devm_backlight_device_register(&client->dev, 886 dev_driver_string(&client->dev), 887 &client->dev, data, &adp8870_bl_ops, &props); 888 if (IS_ERR(bl)) { 889 dev_err(&client->dev, "failed to register backlight\n"); 890 return PTR_ERR(bl); 891 } 892 893 data->bl = bl; 894 895 if (pdata->en_ambl_sens) { 896 ret = sysfs_create_group(&bl->dev.kobj, 897 &adp8870_bl_attr_group); 898 if (ret) { 899 dev_err(&client->dev, "failed to register sysfs\n"); 900 return ret; 901 } 902 } 903 904 ret = adp8870_bl_setup(bl); 905 if (ret) { 906 ret = -EIO; 907 goto out; 908 } 909 910 backlight_update_status(bl); 911 912 dev_info(&client->dev, "Rev.%d Backlight\n", data->revid); 913 914 if (pdata->num_leds) 915 adp8870_led_probe(client); 916 917 return 0; 918 919 out: 920 if (data->pdata->en_ambl_sens) 921 sysfs_remove_group(&data->bl->dev.kobj, 922 &adp8870_bl_attr_group); 923 924 return ret; 925 } 926 927 static void adp8870_remove(struct i2c_client *client) 928 { 929 struct adp8870_bl *data = i2c_get_clientdata(client); 930 931 adp8870_clr_bits(client, ADP8870_MDCR, NSTBY); 932 933 if (data->led) 934 adp8870_led_remove(client); 935 936 if (data->pdata->en_ambl_sens) 937 sysfs_remove_group(&data->bl->dev.kobj, 938 &adp8870_bl_attr_group); 939 } 940 941 #ifdef CONFIG_PM_SLEEP 942 static int adp8870_i2c_suspend(struct device *dev) 943 { 944 struct i2c_client *client = to_i2c_client(dev); 945 946 adp8870_clr_bits(client, ADP8870_MDCR, NSTBY); 947 948 return 0; 949 } 950 951 static int adp8870_i2c_resume(struct device *dev) 952 { 953 struct i2c_client *client = to_i2c_client(dev); 954 955 adp8870_set_bits(client, ADP8870_MDCR, NSTBY | BLEN); 956 957 return 0; 958 } 959 #endif 960 961 static SIMPLE_DEV_PM_OPS(adp8870_i2c_pm_ops, adp8870_i2c_suspend, 962 adp8870_i2c_resume); 963 964 static const struct i2c_device_id adp8870_id[] = { 965 { "adp8870" }, 966 { } 967 }; 968 MODULE_DEVICE_TABLE(i2c, adp8870_id); 969 970 static struct i2c_driver adp8870_driver = { 971 .driver = { 972 .name = KBUILD_MODNAME, 973 .pm = &adp8870_i2c_pm_ops, 974 }, 975 .probe = adp8870_probe, 976 .remove = adp8870_remove, 977 .id_table = adp8870_id, 978 }; 979 980 module_i2c_driver(adp8870_driver); 981 982 MODULE_LICENSE("GPL v2"); 983 MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>"); 984 MODULE_DESCRIPTION("ADP8870 Backlight driver"); 985