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