1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Awinic AW20036/AW20054/AW20072 LED driver 4 * 5 * Copyright (c) 2023, SberDevices. All Rights Reserved. 6 * 7 * Author: Martin Kurbanov <mmkurbanov@sberdevices.ru> 8 */ 9 10 #include <linux/bitfield.h> 11 #include <linux/bits.h> 12 #include <linux/container_of.h> 13 #include <linux/i2c.h> 14 #include <linux/leds.h> 15 #include <linux/mod_devicetable.h> 16 #include <linux/module.h> 17 #include <linux/mutex.h> 18 #include <linux/regmap.h> 19 #include <linux/time.h> 20 #include <linux/units.h> 21 22 #define AW200XX_DIM_MAX (BIT(6) - 1) 23 #define AW200XX_FADE_MAX (BIT(8) - 1) 24 #define AW200XX_IMAX_DEFAULT_uA 60000 25 #define AW200XX_IMAX_MAX_uA 160000 26 #define AW200XX_IMAX_MIN_uA 3300 27 28 /* Page 0 */ 29 #define AW200XX_REG_PAGE0_BASE 0xc000 30 31 /* Select page register */ 32 #define AW200XX_REG_PAGE 0xF0 33 #define AW200XX_PAGE_MASK (GENMASK(7, 6) | GENMASK(2, 0)) 34 #define AW200XX_PAGE_SHIFT 0 35 #define AW200XX_NUM_PAGES 6 36 #define AW200XX_PAGE_SIZE 256 37 #define AW200XX_REG(page, reg) \ 38 (AW200XX_REG_PAGE0_BASE + (page) * AW200XX_PAGE_SIZE + (reg)) 39 #define AW200XX_REG_MAX \ 40 AW200XX_REG(AW200XX_NUM_PAGES - 1, AW200XX_PAGE_SIZE - 1) 41 #define AW200XX_PAGE0 0 42 #define AW200XX_PAGE1 1 43 #define AW200XX_PAGE2 2 44 #define AW200XX_PAGE3 3 45 #define AW200XX_PAGE4 4 46 #define AW200XX_PAGE5 5 47 48 /* Chip ID register */ 49 #define AW200XX_REG_IDR AW200XX_REG(AW200XX_PAGE0, 0x00) 50 #define AW200XX_IDR_CHIPID 0x18 51 52 /* Sleep mode register */ 53 #define AW200XX_REG_SLPCR AW200XX_REG(AW200XX_PAGE0, 0x01) 54 #define AW200XX_SLPCR_ACTIVE 0x00 55 56 /* Reset register */ 57 #define AW200XX_REG_RSTR AW200XX_REG(AW200XX_PAGE0, 0x02) 58 #define AW200XX_RSTR_RESET 0x01 59 60 /* Global current configuration register */ 61 #define AW200XX_REG_GCCR AW200XX_REG(AW200XX_PAGE0, 0x03) 62 #define AW200XX_GCCR_IMAX_MASK GENMASK(7, 4) 63 #define AW200XX_GCCR_IMAX(x) ((x) << 4) 64 #define AW200XX_GCCR_ALLON BIT(3) 65 66 /* Fast clear display control register */ 67 #define AW200XX_REG_FCD AW200XX_REG(AW200XX_PAGE0, 0x04) 68 #define AW200XX_FCD_CLEAR 0x01 69 70 /* Display size configuration */ 71 #define AW200XX_REG_DSIZE AW200XX_REG(AW200XX_PAGE0, 0x80) 72 #define AW200XX_DSIZE_COLUMNS_MAX 12 73 74 #define AW200XX_LED2REG(x, columns) \ 75 ((x) + (((x) / (columns)) * (AW200XX_DSIZE_COLUMNS_MAX - (columns)))) 76 77 /* DIM current configuration register on page 1 */ 78 #define AW200XX_REG_DIM_PAGE1(x, columns) \ 79 AW200XX_REG(AW200XX_PAGE1, AW200XX_LED2REG(x, columns)) 80 81 /* 82 * DIM current configuration register (page 4). 83 * The even address for current DIM configuration. 84 * The odd address for current FADE configuration 85 */ 86 #define AW200XX_REG_DIM(x, columns) \ 87 AW200XX_REG(AW200XX_PAGE4, AW200XX_LED2REG(x, columns) * 2) 88 #define AW200XX_REG_DIM2FADE(x) ((x) + 1) 89 90 /* 91 * Duty ratio of display scan (see p.15 of datasheet for formula): 92 * duty = (592us / 600.5us) * (1 / (display_rows + 1)) 93 * 94 * Multiply to 1000 (MILLI) to improve the accuracy of calculations. 95 */ 96 #define AW200XX_DUTY_RATIO(rows) \ 97 (((592UL * USEC_PER_SEC) / 600500UL) * (MILLI / (rows)) / MILLI) 98 99 struct aw200xx_chipdef { 100 u32 channels; 101 u32 display_size_rows_max; 102 u32 display_size_columns; 103 }; 104 105 struct aw200xx_led { 106 struct led_classdev cdev; 107 struct aw200xx *chip; 108 int dim; 109 u32 num; 110 }; 111 112 struct aw200xx { 113 const struct aw200xx_chipdef *cdef; 114 struct i2c_client *client; 115 struct regmap *regmap; 116 struct mutex mutex; 117 u32 num_leds; 118 u32 display_rows; 119 struct aw200xx_led leds[]; 120 }; 121 122 static ssize_t dim_show(struct device *dev, struct device_attribute *devattr, 123 char *buf) 124 { 125 struct led_classdev *cdev = dev_get_drvdata(dev); 126 struct aw200xx_led *led = container_of(cdev, struct aw200xx_led, cdev); 127 int dim = led->dim; 128 129 if (dim < 0) 130 return sysfs_emit(buf, "auto\n"); 131 132 return sysfs_emit(buf, "%d\n", dim); 133 } 134 135 static ssize_t dim_store(struct device *dev, struct device_attribute *devattr, 136 const char *buf, size_t count) 137 { 138 struct led_classdev *cdev = dev_get_drvdata(dev); 139 struct aw200xx_led *led = container_of(cdev, struct aw200xx_led, cdev); 140 struct aw200xx *chip = led->chip; 141 u32 columns = chip->cdef->display_size_columns; 142 int dim; 143 ssize_t ret; 144 145 if (sysfs_streq(buf, "auto")) { 146 dim = -1; 147 } else { 148 ret = kstrtoint(buf, 0, &dim); 149 if (ret) 150 return ret; 151 152 if (dim > AW200XX_DIM_MAX) 153 return -EINVAL; 154 } 155 156 mutex_lock(&chip->mutex); 157 158 if (dim >= 0) { 159 ret = regmap_write(chip->regmap, 160 AW200XX_REG_DIM_PAGE1(led->num, columns), 161 dim); 162 if (ret) 163 goto out_unlock; 164 } 165 166 led->dim = dim; 167 ret = count; 168 169 out_unlock: 170 mutex_unlock(&chip->mutex); 171 return ret; 172 } 173 static DEVICE_ATTR_RW(dim); 174 175 static struct attribute *dim_attrs[] = { 176 &dev_attr_dim.attr, 177 NULL 178 }; 179 ATTRIBUTE_GROUPS(dim); 180 181 static int aw200xx_brightness_set(struct led_classdev *cdev, 182 enum led_brightness brightness) 183 { 184 struct aw200xx_led *led = container_of(cdev, struct aw200xx_led, cdev); 185 struct aw200xx *chip = led->chip; 186 int dim; 187 u32 reg; 188 int ret; 189 190 mutex_lock(&chip->mutex); 191 192 reg = AW200XX_REG_DIM(led->num, chip->cdef->display_size_columns); 193 194 dim = led->dim; 195 if (dim < 0) 196 dim = max_t(int, 197 brightness / (AW200XX_FADE_MAX / AW200XX_DIM_MAX), 198 1); 199 200 ret = regmap_write(chip->regmap, reg, dim); 201 if (ret) 202 goto out_unlock; 203 204 ret = regmap_write(chip->regmap, 205 AW200XX_REG_DIM2FADE(reg), brightness); 206 207 out_unlock: 208 mutex_unlock(&chip->mutex); 209 210 return ret; 211 } 212 213 static u32 aw200xx_imax_from_global(const struct aw200xx *const chip, 214 u32 global_imax_uA) 215 { 216 u64 led_imax_uA; 217 218 /* 219 * The output current of each LED (see p.14 of datasheet for formula): 220 * Iled = Imax * (dim / 63) * ((fade + 1) / 256) * duty 221 * 222 * The value of duty is determined by the following formula: 223 * duty = (592us / 600.5us) * (1 / (display_rows + 1)) 224 * 225 * Calculated for the maximum values of fade and dim. 226 * We divide by 1000 because we earlier multiplied by 1000 to improve 227 * accuracy when calculating the duty. 228 */ 229 led_imax_uA = global_imax_uA * AW200XX_DUTY_RATIO(chip->display_rows); 230 do_div(led_imax_uA, MILLI); 231 232 return led_imax_uA; 233 } 234 235 static u32 aw200xx_imax_to_global(const struct aw200xx *const chip, 236 u32 led_imax_uA) 237 { 238 u32 duty = AW200XX_DUTY_RATIO(chip->display_rows); 239 240 /* The output current of each LED (see p.14 of datasheet for formula) */ 241 return (led_imax_uA * 1000U) / duty; 242 } 243 244 #define AW200XX_IMAX_MULTIPLIER1 10000 245 #define AW200XX_IMAX_MULTIPLIER2 3333 246 #define AW200XX_IMAX_BASE_VAL1 0 247 #define AW200XX_IMAX_BASE_VAL2 8 248 249 /* 250 * The AW200XX has a 4-bit register (GCCR) to configure the global current, 251 * which ranges from 3.3mA to 160mA. The following table indicates the values 252 * of the global current, divided into two parts: 253 * 254 * +-----------+-----------------+-----------+-----------------+ 255 * | reg value | global max (mA) | reg value | global max (mA) | 256 * +-----------+-----------------+-----------+-----------------+ 257 * | 0 | 10 | 8 | 3.3 | 258 * | 1 | 20 | 9 | 6.7 | 259 * | 2 | 30 | 10 | 10 | 260 * | 3 | 40 | 11 | 13.3 | 261 * | 4 | 60 | 12 | 20 | 262 * | 5 | 80 | 13 | 26.7 | 263 * | 6 | 120 | 14 | 40 | 264 * | 7 | 160 | 15 | 53.3 | 265 * +-----------+-----------------+-----------+-----------------+ 266 * 267 * The left part with a multiplier of 10, and the right part with a multiplier 268 * of 3.3. 269 * So we have two formulas to calculate the global current: 270 * for the left part of the table: 271 * imax = coefficient * 10 272 * 273 * for the right part of the table: 274 * imax = coefficient * 3.3 275 * 276 * The coefficient table consists of the following values: 277 * 1, 2, 3, 4, 6, 8, 12, 16. 278 */ 279 static int aw200xx_set_imax(const struct aw200xx *const chip, 280 u32 led_imax_uA) 281 { 282 u32 g_imax_uA = aw200xx_imax_to_global(chip, led_imax_uA); 283 u32 coeff_table[] = {1, 2, 3, 4, 6, 8, 12, 16}; 284 u32 gccr_imax = UINT_MAX; 285 u32 cur_imax = 0; 286 int i; 287 288 for (i = 0; i < ARRAY_SIZE(coeff_table); i++) { 289 u32 imax; 290 291 /* select closest ones */ 292 imax = coeff_table[i] * AW200XX_IMAX_MULTIPLIER1; 293 if (g_imax_uA >= imax && imax > cur_imax) { 294 cur_imax = imax; 295 gccr_imax = i + AW200XX_IMAX_BASE_VAL1; 296 } 297 298 imax = coeff_table[i] * AW200XX_IMAX_MULTIPLIER2; 299 imax = DIV_ROUND_CLOSEST(imax, 100) * 100; 300 if (g_imax_uA >= imax && imax > cur_imax) { 301 cur_imax = imax; 302 gccr_imax = i + AW200XX_IMAX_BASE_VAL2; 303 } 304 } 305 306 if (gccr_imax == UINT_MAX) 307 return -EINVAL; 308 309 return regmap_update_bits(chip->regmap, AW200XX_REG_GCCR, 310 AW200XX_GCCR_IMAX_MASK, 311 AW200XX_GCCR_IMAX(gccr_imax)); 312 } 313 314 static int aw200xx_chip_reset(const struct aw200xx *const chip) 315 { 316 int ret; 317 318 ret = regmap_write(chip->regmap, AW200XX_REG_RSTR, AW200XX_RSTR_RESET); 319 if (ret) 320 return ret; 321 322 regcache_mark_dirty(chip->regmap); 323 return regmap_write(chip->regmap, AW200XX_REG_FCD, AW200XX_FCD_CLEAR); 324 } 325 326 static int aw200xx_chip_init(const struct aw200xx *const chip) 327 { 328 int ret; 329 330 ret = regmap_write(chip->regmap, AW200XX_REG_DSIZE, 331 chip->display_rows - 1); 332 if (ret) 333 return ret; 334 335 ret = regmap_write(chip->regmap, AW200XX_REG_SLPCR, 336 AW200XX_SLPCR_ACTIVE); 337 if (ret) 338 return ret; 339 340 return regmap_update_bits(chip->regmap, AW200XX_REG_GCCR, 341 AW200XX_GCCR_ALLON, AW200XX_GCCR_ALLON); 342 } 343 344 static int aw200xx_chip_check(const struct aw200xx *const chip) 345 { 346 struct device *dev = &chip->client->dev; 347 u32 chipid; 348 int ret; 349 350 ret = regmap_read(chip->regmap, AW200XX_REG_IDR, &chipid); 351 if (ret) 352 return dev_err_probe(dev, ret, "Failed to read chip ID\n"); 353 354 if (chipid != AW200XX_IDR_CHIPID) 355 return dev_err_probe(dev, -ENODEV, 356 "Chip reported wrong ID: %x\n", chipid); 357 358 return 0; 359 } 360 361 static int aw200xx_probe_fw(struct device *dev, struct aw200xx *chip) 362 { 363 struct fwnode_handle *child; 364 u32 current_min, current_max, min_uA; 365 int ret; 366 int i; 367 368 ret = device_property_read_u32(dev, "awinic,display-rows", 369 &chip->display_rows); 370 if (ret) 371 return dev_err_probe(dev, ret, 372 "Failed to read 'display-rows' property\n"); 373 374 if (!chip->display_rows || 375 chip->display_rows > chip->cdef->display_size_rows_max) { 376 return dev_err_probe(dev, -EINVAL, 377 "Invalid leds display size %u\n", 378 chip->display_rows); 379 } 380 381 current_max = aw200xx_imax_from_global(chip, AW200XX_IMAX_MAX_uA); 382 current_min = aw200xx_imax_from_global(chip, AW200XX_IMAX_MIN_uA); 383 min_uA = UINT_MAX; 384 i = 0; 385 386 device_for_each_child_node(dev, child) { 387 struct led_init_data init_data = {}; 388 struct aw200xx_led *led; 389 u32 source, imax; 390 391 ret = fwnode_property_read_u32(child, "reg", &source); 392 if (ret) { 393 dev_err(dev, "Missing reg property\n"); 394 chip->num_leds--; 395 continue; 396 } 397 398 if (source >= chip->cdef->channels) { 399 dev_err(dev, "LED reg %u out of range (max %u)\n", 400 source, chip->cdef->channels); 401 chip->num_leds--; 402 continue; 403 } 404 405 ret = fwnode_property_read_u32(child, "led-max-microamp", 406 &imax); 407 if (ret) { 408 dev_info(&chip->client->dev, 409 "DT property led-max-microamp is missing\n"); 410 } else if (imax < current_min || imax > current_max) { 411 dev_err(dev, "Invalid value %u for led-max-microamp\n", 412 imax); 413 chip->num_leds--; 414 continue; 415 } else { 416 min_uA = min(min_uA, imax); 417 } 418 419 led = &chip->leds[i]; 420 led->dim = -1; 421 led->num = source; 422 led->chip = chip; 423 led->cdev.brightness_set_blocking = aw200xx_brightness_set; 424 led->cdev.groups = dim_groups; 425 init_data.fwnode = child; 426 427 ret = devm_led_classdev_register_ext(dev, &led->cdev, 428 &init_data); 429 if (ret) { 430 fwnode_handle_put(child); 431 break; 432 } 433 434 i++; 435 } 436 437 if (!chip->num_leds) 438 return -EINVAL; 439 440 if (min_uA == UINT_MAX) { 441 min_uA = aw200xx_imax_from_global(chip, 442 AW200XX_IMAX_DEFAULT_uA); 443 } 444 445 return aw200xx_set_imax(chip, min_uA); 446 } 447 448 static const struct regmap_range_cfg aw200xx_ranges[] = { 449 { 450 .name = "aw200xx", 451 .range_min = 0, 452 .range_max = AW200XX_REG_MAX, 453 .selector_reg = AW200XX_REG_PAGE, 454 .selector_mask = AW200XX_PAGE_MASK, 455 .selector_shift = AW200XX_PAGE_SHIFT, 456 .window_start = 0, 457 .window_len = AW200XX_PAGE_SIZE, 458 }, 459 }; 460 461 static const struct regmap_range aw200xx_writeonly_ranges[] = { 462 regmap_reg_range(AW200XX_REG(AW200XX_PAGE1, 0x00), AW200XX_REG_MAX), 463 }; 464 465 static const struct regmap_access_table aw200xx_readable_table = { 466 .no_ranges = aw200xx_writeonly_ranges, 467 .n_no_ranges = ARRAY_SIZE(aw200xx_writeonly_ranges), 468 }; 469 470 static const struct regmap_range aw200xx_readonly_ranges[] = { 471 regmap_reg_range(AW200XX_REG_IDR, AW200XX_REG_IDR), 472 }; 473 474 static const struct regmap_access_table aw200xx_writeable_table = { 475 .no_ranges = aw200xx_readonly_ranges, 476 .n_no_ranges = ARRAY_SIZE(aw200xx_readonly_ranges), 477 }; 478 479 static const struct regmap_config aw200xx_regmap_config = { 480 .reg_bits = 8, 481 .val_bits = 8, 482 .max_register = AW200XX_REG_MAX, 483 .ranges = aw200xx_ranges, 484 .num_ranges = ARRAY_SIZE(aw200xx_ranges), 485 .rd_table = &aw200xx_readable_table, 486 .wr_table = &aw200xx_writeable_table, 487 .cache_type = REGCACHE_RBTREE, 488 }; 489 490 static int aw200xx_probe(struct i2c_client *client) 491 { 492 const struct aw200xx_chipdef *cdef; 493 struct aw200xx *chip; 494 int count; 495 int ret; 496 497 cdef = device_get_match_data(&client->dev); 498 if (!cdef) 499 return -ENODEV; 500 501 count = device_get_child_node_count(&client->dev); 502 if (!count || count > cdef->channels) 503 return dev_err_probe(&client->dev, -EINVAL, 504 "Incorrect number of leds (%d)", count); 505 506 chip = devm_kzalloc(&client->dev, struct_size(chip, leds, count), 507 GFP_KERNEL); 508 if (!chip) 509 return -ENOMEM; 510 511 chip->cdef = cdef; 512 chip->num_leds = count; 513 chip->client = client; 514 i2c_set_clientdata(client, chip); 515 516 chip->regmap = devm_regmap_init_i2c(client, &aw200xx_regmap_config); 517 if (IS_ERR(chip->regmap)) 518 return PTR_ERR(chip->regmap); 519 520 ret = aw200xx_chip_check(chip); 521 if (ret) 522 return ret; 523 524 mutex_init(&chip->mutex); 525 526 /* Need a lock now since after call aw200xx_probe_fw, sysfs nodes created */ 527 mutex_lock(&chip->mutex); 528 529 ret = aw200xx_chip_reset(chip); 530 if (ret) 531 goto out_unlock; 532 533 ret = aw200xx_probe_fw(&client->dev, chip); 534 if (ret) 535 goto out_unlock; 536 537 ret = aw200xx_chip_init(chip); 538 539 out_unlock: 540 mutex_unlock(&chip->mutex); 541 return ret; 542 } 543 544 static void aw200xx_remove(struct i2c_client *client) 545 { 546 struct aw200xx *chip = i2c_get_clientdata(client); 547 548 aw200xx_chip_reset(chip); 549 mutex_destroy(&chip->mutex); 550 } 551 552 static const struct aw200xx_chipdef aw20036_cdef = { 553 .channels = 36, 554 .display_size_rows_max = 3, 555 .display_size_columns = 12, 556 }; 557 558 static const struct aw200xx_chipdef aw20054_cdef = { 559 .channels = 54, 560 .display_size_rows_max = 6, 561 .display_size_columns = 9, 562 }; 563 564 static const struct aw200xx_chipdef aw20072_cdef = { 565 .channels = 72, 566 .display_size_rows_max = 6, 567 .display_size_columns = 12, 568 }; 569 570 static const struct i2c_device_id aw200xx_id[] = { 571 { "aw20036" }, 572 { "aw20054" }, 573 { "aw20072" }, 574 {} 575 }; 576 MODULE_DEVICE_TABLE(i2c, aw200xx_id); 577 578 static const struct of_device_id aw200xx_match_table[] = { 579 { .compatible = "awinic,aw20036", .data = &aw20036_cdef, }, 580 { .compatible = "awinic,aw20054", .data = &aw20054_cdef, }, 581 { .compatible = "awinic,aw20072", .data = &aw20072_cdef, }, 582 {} 583 }; 584 MODULE_DEVICE_TABLE(of, aw200xx_match_table); 585 586 static struct i2c_driver aw200xx_driver = { 587 .driver = { 588 .name = "aw200xx", 589 .of_match_table = aw200xx_match_table, 590 }, 591 .probe = aw200xx_probe, 592 .remove = aw200xx_remove, 593 .id_table = aw200xx_id, 594 }; 595 module_i2c_driver(aw200xx_driver); 596 597 MODULE_AUTHOR("Martin Kurbanov <mmkurbanov@sberdevices.ru>"); 598 MODULE_DESCRIPTION("AW200XX LED driver"); 599 MODULE_LICENSE("GPL"); 600