1 // SPDX-License-Identifier: GPL-2.0-only 2 3 #include <linux/bitops.h> 4 #include <linux/delay.h> 5 #include <linux/init.h> 6 #include <linux/interrupt.h> 7 #include <linux/kernel.h> 8 #include <linux/led-class-flash.h> 9 #include <linux/led-class-multicolor.h> 10 #include <linux/module.h> 11 #include <linux/mutex.h> 12 #include <linux/platform_device.h> 13 #include <linux/property.h> 14 #include <linux/regmap.h> 15 #include <media/v4l2-flash-led-class.h> 16 17 enum { 18 MT6360_LED_ISNK1 = 0, 19 MT6360_LED_ISNK2, 20 MT6360_LED_ISNK3, 21 MT6360_LED_ISNKML, 22 MT6360_LED_FLASH1, 23 MT6360_LED_FLASH2, 24 MT6360_MAX_LEDS 25 }; 26 27 #define MT6360_REG_RGBEN 0x380 28 #define MT6360_REG_ISNK(_led_no) (0x381 + (_led_no)) 29 #define MT6360_ISNK_ENMASK(_led_no) BIT(7 - (_led_no)) 30 #define MT6360_ISNK_MASK GENMASK(4, 0) 31 #define MT6360_CHRINDSEL_MASK BIT(3) 32 33 /* Virtual definition for multicolor */ 34 #define MT6360_VIRTUAL_MULTICOLOR (MT6360_MAX_LEDS + 1) 35 #define MULTICOLOR_NUM_CHANNELS 3 36 37 #define MT6360_REG_FLEDEN 0x37E 38 #define MT6360_REG_STRBTO 0x373 39 #define MT6360_REG_FLEDBASE(_id) (0x372 + 4 * (_id - MT6360_LED_FLASH1)) 40 #define MT6360_REG_FLEDISTRB(_id) (MT6360_REG_FLEDBASE(_id) + 2) 41 #define MT6360_REG_FLEDITOR(_id) (MT6360_REG_FLEDBASE(_id) + 3) 42 #define MT6360_REG_CHGSTAT2 0x3E1 43 #define MT6360_REG_FLEDSTAT1 0x3E9 44 #define MT6360_ITORCH_MASK GENMASK(4, 0) 45 #define MT6360_ISTROBE_MASK GENMASK(6, 0) 46 #define MT6360_STRBTO_MASK GENMASK(6, 0) 47 #define MT6360_TORCHEN_MASK BIT(3) 48 #define MT6360_STROBEN_MASK BIT(2) 49 #define MT6360_FLCSEN_MASK(_id) BIT(MT6360_LED_FLASH2 - _id) 50 #define MT6360_FLEDCHGVINOVP_MASK BIT(3) 51 #define MT6360_FLED1STRBTO_MASK BIT(11) 52 #define MT6360_FLED2STRBTO_MASK BIT(10) 53 #define MT6360_FLED1STRB_MASK BIT(9) 54 #define MT6360_FLED2STRB_MASK BIT(8) 55 #define MT6360_FLED1SHORT_MASK BIT(7) 56 #define MT6360_FLED2SHORT_MASK BIT(6) 57 #define MT6360_FLEDLVF_MASK BIT(3) 58 59 #define MT6360_ISNKRGB_STEPUA 2000 60 #define MT6360_ISNKRGB_MAXUA 24000 61 #define MT6360_ISNKML_STEPUA 5000 62 #define MT6360_ISNKML_MAXUA 150000 63 64 #define MT6360_ITORCH_MINUA 25000 65 #define MT6360_ITORCH_STEPUA 12500 66 #define MT6360_ITORCH_MAXUA 400000 67 #define MT6360_ISTRB_MINUA 50000 68 #define MT6360_ISTRB_STEPUA 12500 69 #define MT6360_ISTRB_MAXUA 1500000 70 #define MT6360_STRBTO_MINUS 64000 71 #define MT6360_STRBTO_STEPUS 32000 72 #define MT6360_STRBTO_MAXUS 2432000 73 74 #define STATE_OFF 0 75 #define STATE_KEEP 1 76 #define STATE_ON 2 77 78 struct mt6360_led { 79 union { 80 struct led_classdev isnk; 81 struct led_classdev_mc mc; 82 struct led_classdev_flash flash; 83 }; 84 struct v4l2_flash *v4l2_flash; 85 struct mt6360_priv *priv; 86 u32 led_no; 87 u32 default_state; 88 }; 89 90 struct mt6360_priv { 91 struct device *dev; 92 struct regmap *regmap; 93 struct mutex lock; 94 unsigned int fled_strobe_used; 95 unsigned int fled_torch_used; 96 unsigned int leds_active; 97 unsigned int leds_count; 98 struct mt6360_led leds[]; 99 }; 100 101 static int mt6360_mc_brightness_set(struct led_classdev *lcdev, 102 enum led_brightness level) 103 { 104 struct led_classdev_mc *mccdev = lcdev_to_mccdev(lcdev); 105 struct mt6360_led *led = container_of(mccdev, struct mt6360_led, mc); 106 struct mt6360_priv *priv = led->priv; 107 u32 real_bright, enable_mask = 0, enable = 0; 108 int i, ret; 109 110 mutex_lock(&priv->lock); 111 112 led_mc_calc_color_components(mccdev, level); 113 114 for (i = 0; i < mccdev->num_colors; i++) { 115 struct mc_subled *subled = mccdev->subled_info + i; 116 117 real_bright = min(lcdev->max_brightness, subled->brightness); 118 ret = regmap_update_bits(priv->regmap, MT6360_REG_ISNK(i), 119 MT6360_ISNK_MASK, real_bright); 120 if (ret) 121 goto out; 122 123 enable_mask |= MT6360_ISNK_ENMASK(subled->channel); 124 if (real_bright) 125 enable |= MT6360_ISNK_ENMASK(subled->channel); 126 } 127 128 ret = regmap_update_bits(priv->regmap, MT6360_REG_RGBEN, enable_mask, 129 enable); 130 131 out: 132 mutex_unlock(&priv->lock); 133 return ret; 134 } 135 136 static int mt6360_isnk_brightness_set(struct led_classdev *lcdev, 137 enum led_brightness level) 138 { 139 struct mt6360_led *led = container_of(lcdev, struct mt6360_led, isnk); 140 struct mt6360_priv *priv = led->priv; 141 u32 enable_mask = MT6360_ISNK_ENMASK(led->led_no); 142 u32 val = level ? MT6360_ISNK_ENMASK(led->led_no) : 0; 143 int ret; 144 145 mutex_lock(&priv->lock); 146 147 ret = regmap_update_bits(priv->regmap, MT6360_REG_ISNK(led->led_no), 148 MT6360_ISNK_MASK, level); 149 if (ret) 150 goto out; 151 152 ret = regmap_update_bits(priv->regmap, MT6360_REG_RGBEN, enable_mask, 153 val); 154 155 out: 156 mutex_unlock(&priv->lock); 157 return ret; 158 } 159 160 static int mt6360_torch_brightness_set(struct led_classdev *lcdev, 161 enum led_brightness level) 162 { 163 struct mt6360_led *led = 164 container_of(lcdev, struct mt6360_led, flash.led_cdev); 165 struct mt6360_priv *priv = led->priv; 166 u32 enable_mask = MT6360_TORCHEN_MASK | MT6360_FLCSEN_MASK(led->led_no); 167 u32 val = level ? MT6360_FLCSEN_MASK(led->led_no) : 0; 168 u32 prev = priv->fled_torch_used, curr; 169 int ret; 170 171 mutex_lock(&priv->lock); 172 173 /* 174 * Only one set of flash control logic, use the flag to avoid strobe is 175 * currently used. 176 */ 177 if (priv->fled_strobe_used) { 178 dev_warn(lcdev->dev, "Please disable strobe first [%d]\n", 179 priv->fled_strobe_used); 180 ret = -EBUSY; 181 goto unlock; 182 } 183 184 if (level) 185 curr = prev | BIT(led->led_no); 186 else 187 curr = prev & ~BIT(led->led_no); 188 189 if (curr) 190 val |= MT6360_TORCHEN_MASK; 191 192 if (level) { 193 ret = regmap_update_bits(priv->regmap, 194 MT6360_REG_FLEDITOR(led->led_no), 195 MT6360_ITORCH_MASK, level - 1); 196 if (ret) 197 goto unlock; 198 } 199 200 ret = regmap_update_bits(priv->regmap, MT6360_REG_FLEDEN, enable_mask, 201 val); 202 if (ret) 203 goto unlock; 204 205 priv->fled_torch_used = curr; 206 207 unlock: 208 mutex_unlock(&priv->lock); 209 return ret; 210 } 211 212 static int mt6360_flash_brightness_set(struct led_classdev_flash *fl_cdev, 213 u32 brightness) 214 { 215 /* 216 * Due to the current spike when turning on flash, let brightness to be 217 * kept by framework. 218 * This empty function is used to prevent led_classdev_flash register 219 * ops check failure. 220 */ 221 return 0; 222 } 223 224 static int _mt6360_flash_brightness_set(struct led_classdev_flash *fl_cdev, 225 u32 brightness) 226 { 227 struct mt6360_led *led = 228 container_of(fl_cdev, struct mt6360_led, flash); 229 struct mt6360_priv *priv = led->priv; 230 struct led_flash_setting *s = &fl_cdev->brightness; 231 u32 val = (brightness - s->min) / s->step; 232 233 return regmap_update_bits(priv->regmap, 234 MT6360_REG_FLEDISTRB(led->led_no), 235 MT6360_ISTROBE_MASK, val); 236 } 237 238 static int mt6360_strobe_set(struct led_classdev_flash *fl_cdev, bool state) 239 { 240 struct mt6360_led *led = 241 container_of(fl_cdev, struct mt6360_led, flash); 242 struct mt6360_priv *priv = led->priv; 243 struct led_classdev *lcdev = &fl_cdev->led_cdev; 244 struct led_flash_setting *s = &fl_cdev->brightness; 245 u32 enable_mask = MT6360_STROBEN_MASK | MT6360_FLCSEN_MASK(led->led_no); 246 u32 val = state ? MT6360_FLCSEN_MASK(led->led_no) : 0; 247 u32 prev = priv->fled_strobe_used, curr; 248 int ret; 249 250 mutex_lock(&priv->lock); 251 252 /* 253 * Only one set of flash control logic, use the flag to avoid torch is 254 * currently used 255 */ 256 if (priv->fled_torch_used) { 257 dev_warn(lcdev->dev, "Please disable torch first [0x%x]\n", 258 priv->fled_torch_used); 259 ret = -EBUSY; 260 goto unlock; 261 } 262 263 if (state) 264 curr = prev | BIT(led->led_no); 265 else 266 curr = prev & ~BIT(led->led_no); 267 268 if (curr) 269 val |= MT6360_STROBEN_MASK; 270 271 ret = regmap_update_bits(priv->regmap, MT6360_REG_FLEDEN, enable_mask, 272 val); 273 if (ret) { 274 dev_err(lcdev->dev, "[%d] control current source %d fail\n", 275 led->led_no, state); 276 goto unlock; 277 } 278 279 /* 280 * If the flash need to be on, config the flash current ramping up to 281 * the setting value. 282 * Else, always recover back to the minimum one 283 */ 284 ret = _mt6360_flash_brightness_set(fl_cdev, state ? s->val : s->min); 285 if (ret) 286 goto unlock; 287 288 /* 289 * For the flash turn on/off, HW rampping up/down time is 5ms/500us, 290 * respectively. 291 */ 292 if (!prev && curr) 293 usleep_range(5000, 6000); 294 else if (prev && !curr) 295 udelay(500); 296 297 priv->fled_strobe_used = curr; 298 299 unlock: 300 mutex_unlock(&priv->lock); 301 return ret; 302 } 303 304 static int mt6360_strobe_get(struct led_classdev_flash *fl_cdev, bool *state) 305 { 306 struct mt6360_led *led = 307 container_of(fl_cdev, struct mt6360_led, flash); 308 struct mt6360_priv *priv = led->priv; 309 310 mutex_lock(&priv->lock); 311 *state = !!(priv->fled_strobe_used & BIT(led->led_no)); 312 mutex_unlock(&priv->lock); 313 314 return 0; 315 } 316 317 static int mt6360_timeout_set(struct led_classdev_flash *fl_cdev, u32 timeout) 318 { 319 struct mt6360_led *led = 320 container_of(fl_cdev, struct mt6360_led, flash); 321 struct mt6360_priv *priv = led->priv; 322 struct led_flash_setting *s = &fl_cdev->timeout; 323 u32 val = (timeout - s->min) / s->step; 324 int ret; 325 326 mutex_lock(&priv->lock); 327 ret = regmap_update_bits(priv->regmap, MT6360_REG_STRBTO, 328 MT6360_STRBTO_MASK, val); 329 mutex_unlock(&priv->lock); 330 331 return ret; 332 } 333 334 static int mt6360_fault_get(struct led_classdev_flash *fl_cdev, u32 *fault) 335 { 336 struct mt6360_led *led = 337 container_of(fl_cdev, struct mt6360_led, flash); 338 struct mt6360_priv *priv = led->priv; 339 u16 fled_stat; 340 unsigned int chg_stat, strobe_timeout_mask, fled_short_mask; 341 u32 rfault = 0; 342 int ret; 343 344 mutex_lock(&priv->lock); 345 ret = regmap_read(priv->regmap, MT6360_REG_CHGSTAT2, &chg_stat); 346 if (ret) 347 goto unlock; 348 349 ret = regmap_raw_read(priv->regmap, MT6360_REG_FLEDSTAT1, &fled_stat, 350 sizeof(fled_stat)); 351 if (ret) 352 goto unlock; 353 354 if (led->led_no == MT6360_LED_FLASH1) { 355 strobe_timeout_mask = MT6360_FLED1STRBTO_MASK; 356 fled_short_mask = MT6360_FLED1SHORT_MASK; 357 } else { 358 strobe_timeout_mask = MT6360_FLED2STRBTO_MASK; 359 fled_short_mask = MT6360_FLED2SHORT_MASK; 360 } 361 362 if (chg_stat & MT6360_FLEDCHGVINOVP_MASK) 363 rfault |= LED_FAULT_INPUT_VOLTAGE; 364 365 if (fled_stat & strobe_timeout_mask) 366 rfault |= LED_FAULT_TIMEOUT; 367 368 if (fled_stat & fled_short_mask) 369 rfault |= LED_FAULT_SHORT_CIRCUIT; 370 371 if (fled_stat & MT6360_FLEDLVF_MASK) 372 rfault |= LED_FAULT_UNDER_VOLTAGE; 373 374 *fault = rfault; 375 unlock: 376 mutex_unlock(&priv->lock); 377 return ret; 378 } 379 380 static const struct led_flash_ops mt6360_flash_ops = { 381 .flash_brightness_set = mt6360_flash_brightness_set, 382 .strobe_set = mt6360_strobe_set, 383 .strobe_get = mt6360_strobe_get, 384 .timeout_set = mt6360_timeout_set, 385 .fault_get = mt6360_fault_get, 386 }; 387 388 static int mt6360_isnk_init_default_state(struct mt6360_led *led) 389 { 390 struct mt6360_priv *priv = led->priv; 391 unsigned int regval; 392 u32 level; 393 int ret; 394 395 ret = regmap_read(priv->regmap, MT6360_REG_ISNK(led->led_no), ®val); 396 if (ret) 397 return ret; 398 level = regval & MT6360_ISNK_MASK; 399 400 ret = regmap_read(priv->regmap, MT6360_REG_RGBEN, ®val); 401 if (ret) 402 return ret; 403 404 if (!(regval & MT6360_ISNK_ENMASK(led->led_no))) 405 level = LED_OFF; 406 407 switch (led->default_state) { 408 case STATE_ON: 409 led->isnk.brightness = led->isnk.max_brightness; 410 break; 411 case STATE_KEEP: 412 led->isnk.brightness = min(level, led->isnk.max_brightness); 413 break; 414 default: 415 led->isnk.brightness = LED_OFF; 416 } 417 418 return mt6360_isnk_brightness_set(&led->isnk, led->isnk.brightness); 419 } 420 421 static int mt6360_flash_init_default_state(struct mt6360_led *led) 422 { 423 struct led_classdev_flash *flash = &led->flash; 424 struct mt6360_priv *priv = led->priv; 425 u32 enable_mask = MT6360_TORCHEN_MASK | MT6360_FLCSEN_MASK(led->led_no); 426 u32 level; 427 unsigned int regval; 428 int ret; 429 430 ret = regmap_read(priv->regmap, MT6360_REG_FLEDITOR(led->led_no), 431 ®val); 432 if (ret) 433 return ret; 434 level = regval & MT6360_ITORCH_MASK; 435 436 ret = regmap_read(priv->regmap, MT6360_REG_FLEDEN, ®val); 437 if (ret) 438 return ret; 439 440 if ((regval & enable_mask) == enable_mask) 441 level += 1; 442 else 443 level = LED_OFF; 444 445 switch (led->default_state) { 446 case STATE_ON: 447 flash->led_cdev.brightness = flash->led_cdev.max_brightness; 448 break; 449 case STATE_KEEP: 450 flash->led_cdev.brightness = 451 min(level, flash->led_cdev.max_brightness); 452 break; 453 default: 454 flash->led_cdev.brightness = LED_OFF; 455 } 456 457 return mt6360_torch_brightness_set(&flash->led_cdev, 458 flash->led_cdev.brightness); 459 } 460 461 #if IS_ENABLED(CONFIG_V4L2_FLASH_LED_CLASS) 462 static int mt6360_flash_external_strobe_set(struct v4l2_flash *v4l2_flash, 463 bool enable) 464 { 465 struct led_classdev_flash *flash = v4l2_flash->fled_cdev; 466 struct mt6360_led *led = container_of(flash, struct mt6360_led, flash); 467 struct mt6360_priv *priv = led->priv; 468 u32 mask = MT6360_FLCSEN_MASK(led->led_no); 469 u32 val = enable ? mask : 0; 470 int ret; 471 472 mutex_lock(&priv->lock); 473 474 ret = regmap_update_bits(priv->regmap, MT6360_REG_FLEDEN, mask, val); 475 if (ret) 476 goto unlock; 477 478 if (enable) 479 priv->fled_strobe_used |= BIT(led->led_no); 480 else 481 priv->fled_strobe_used &= ~BIT(led->led_no); 482 483 unlock: 484 mutex_unlock(&priv->lock); 485 return ret; 486 } 487 488 static const struct v4l2_flash_ops v4l2_flash_ops = { 489 .external_strobe_set = mt6360_flash_external_strobe_set, 490 }; 491 492 static void mt6360_init_v4l2_flash_config(struct mt6360_led *led, 493 struct v4l2_flash_config *config) 494 { 495 struct led_classdev *lcdev; 496 struct led_flash_setting *s = &config->intensity; 497 498 lcdev = &led->flash.led_cdev; 499 500 s->min = MT6360_ITORCH_MINUA; 501 s->step = MT6360_ITORCH_STEPUA; 502 s->val = s->max = s->min + (lcdev->max_brightness - 1) * s->step; 503 504 config->has_external_strobe = 1; 505 strscpy(config->dev_name, lcdev->dev->kobj.name, 506 sizeof(config->dev_name)); 507 508 config->flash_faults = LED_FAULT_SHORT_CIRCUIT | LED_FAULT_TIMEOUT | 509 LED_FAULT_INPUT_VOLTAGE | 510 LED_FAULT_UNDER_VOLTAGE; 511 } 512 #else 513 static const struct v4l2_flash_ops v4l2_flash_ops; 514 static void mt6360_init_v4l2_flash_config(struct mt6360_led *led, 515 struct v4l2_flash_config *config) 516 { 517 } 518 #endif 519 520 static int mt6360_led_register(struct device *parent, struct mt6360_led *led, 521 struct led_init_data *init_data) 522 { 523 struct mt6360_priv *priv = led->priv; 524 struct v4l2_flash_config v4l2_config = {0}; 525 int ret; 526 527 if ((led->led_no == MT6360_LED_ISNK1 || 528 led->led_no == MT6360_VIRTUAL_MULTICOLOR) && 529 (priv->leds_active & BIT(MT6360_LED_ISNK1))) { 530 /* 531 * Change isink1 to SW control mode, disconnect it with 532 * charger state 533 */ 534 ret = regmap_update_bits(priv->regmap, MT6360_REG_RGBEN, 535 MT6360_CHRINDSEL_MASK, 536 MT6360_CHRINDSEL_MASK); 537 if (ret) { 538 dev_err(parent, "Failed to config ISNK1 to SW mode\n"); 539 return ret; 540 } 541 } 542 543 switch (led->led_no) { 544 case MT6360_VIRTUAL_MULTICOLOR: 545 ret = mt6360_mc_brightness_set(&led->mc.led_cdev, LED_OFF); 546 if (ret) { 547 dev_err(parent, 548 "Failed to init multicolor brightness\n"); 549 return ret; 550 } 551 552 ret = devm_led_classdev_multicolor_register_ext(parent, 553 &led->mc, init_data); 554 if (ret) { 555 dev_err(parent, "Couldn't register multicolor\n"); 556 return ret; 557 } 558 break; 559 case MT6360_LED_ISNK1 ... MT6360_LED_ISNKML: 560 ret = mt6360_isnk_init_default_state(led); 561 if (ret) { 562 dev_err(parent, "Failed to init %d isnk state\n", 563 led->led_no); 564 return ret; 565 } 566 567 ret = devm_led_classdev_register_ext(parent, &led->isnk, 568 init_data); 569 if (ret) { 570 dev_err(parent, "Couldn't register isink %d\n", 571 led->led_no); 572 return ret; 573 } 574 break; 575 default: 576 ret = mt6360_flash_init_default_state(led); 577 if (ret) { 578 dev_err(parent, "Failed to init %d flash state\n", 579 led->led_no); 580 return ret; 581 } 582 583 ret = devm_led_classdev_flash_register_ext(parent, &led->flash, 584 init_data); 585 if (ret) { 586 dev_err(parent, "Couldn't register flash %d\n", 587 led->led_no); 588 return ret; 589 } 590 591 mt6360_init_v4l2_flash_config(led, &v4l2_config); 592 led->v4l2_flash = v4l2_flash_init(parent, init_data->fwnode, 593 &led->flash, 594 &v4l2_flash_ops, 595 &v4l2_config); 596 if (IS_ERR(led->v4l2_flash)) { 597 dev_err(parent, "Failed to register %d v4l2 sd\n", 598 led->led_no); 599 return PTR_ERR(led->v4l2_flash); 600 } 601 } 602 603 return 0; 604 } 605 606 static u32 clamp_align(u32 val, u32 min, u32 max, u32 step) 607 { 608 u32 retval; 609 610 retval = clamp_val(val, min, max); 611 if (step > 1) 612 retval = rounddown(retval - min, step) + min; 613 614 return retval; 615 } 616 617 static int mt6360_init_isnk_properties(struct mt6360_led *led, 618 struct led_init_data *init_data) 619 { 620 struct led_classdev *lcdev; 621 struct mt6360_priv *priv = led->priv; 622 struct fwnode_handle *child; 623 u32 step_uA = MT6360_ISNKRGB_STEPUA, max_uA = MT6360_ISNKRGB_MAXUA; 624 u32 val; 625 int num_color = 0, ret; 626 627 if (led->led_no == MT6360_VIRTUAL_MULTICOLOR) { 628 struct mc_subled *sub_led; 629 630 sub_led = devm_kzalloc(priv->dev, 631 sizeof(*sub_led) * MULTICOLOR_NUM_CHANNELS, GFP_KERNEL); 632 if (!sub_led) 633 return -ENOMEM; 634 635 fwnode_for_each_child_node(init_data->fwnode, child) { 636 u32 reg, color; 637 638 ret = fwnode_property_read_u32(child, "reg", ®); 639 if (ret || reg > MT6360_LED_ISNK3 || 640 priv->leds_active & BIT(reg)) 641 return -EINVAL; 642 643 ret = fwnode_property_read_u32(child, "color", &color); 644 if (ret) { 645 dev_err(priv->dev, 646 "led %d, no color specified\n", 647 led->led_no); 648 return ret; 649 } 650 651 priv->leds_active |= BIT(reg); 652 sub_led[num_color].color_index = color; 653 sub_led[num_color].channel = reg; 654 num_color++; 655 } 656 657 if (num_color < 2) { 658 dev_err(priv->dev, 659 "Multicolor must include 2 or more led channel\n"); 660 return -EINVAL; 661 } 662 663 led->mc.num_colors = num_color; 664 led->mc.subled_info = sub_led; 665 666 lcdev = &led->mc.led_cdev; 667 lcdev->brightness_set_blocking = mt6360_mc_brightness_set; 668 } else { 669 if (led->led_no == MT6360_LED_ISNKML) { 670 step_uA = MT6360_ISNKML_STEPUA; 671 max_uA = MT6360_ISNKML_MAXUA; 672 } 673 674 lcdev = &led->isnk; 675 lcdev->brightness_set_blocking = mt6360_isnk_brightness_set; 676 } 677 678 ret = fwnode_property_read_u32(init_data->fwnode, "led-max-microamp", 679 &val); 680 if (ret) { 681 dev_warn(priv->dev, 682 "Not specified led-max-microamp, config to the minimum\n"); 683 val = step_uA; 684 } else 685 val = clamp_align(val, 0, max_uA, step_uA); 686 687 lcdev->max_brightness = val / step_uA; 688 689 fwnode_property_read_string(init_data->fwnode, "linux,default-trigger", 690 &lcdev->default_trigger); 691 692 return 0; 693 } 694 695 static int mt6360_init_flash_properties(struct mt6360_led *led, 696 struct led_init_data *init_data) 697 { 698 struct led_classdev_flash *flash = &led->flash; 699 struct led_classdev *lcdev = &flash->led_cdev; 700 struct mt6360_priv *priv = led->priv; 701 struct led_flash_setting *s; 702 u32 val; 703 int ret; 704 705 ret = fwnode_property_read_u32(init_data->fwnode, "led-max-microamp", 706 &val); 707 if (ret) { 708 dev_warn(priv->dev, 709 "Not specified led-max-microamp, config to the minimum\n"); 710 val = MT6360_ITORCH_MINUA; 711 } else 712 val = clamp_align(val, MT6360_ITORCH_MINUA, MT6360_ITORCH_MAXUA, 713 MT6360_ITORCH_STEPUA); 714 715 lcdev->max_brightness = 716 (val - MT6360_ITORCH_MINUA) / MT6360_ITORCH_STEPUA + 1; 717 lcdev->brightness_set_blocking = mt6360_torch_brightness_set; 718 lcdev->flags |= LED_DEV_CAP_FLASH; 719 720 ret = fwnode_property_read_u32(init_data->fwnode, "flash-max-microamp", 721 &val); 722 if (ret) { 723 dev_warn(priv->dev, 724 "Not specified flash-max-microamp, config to the minimum\n"); 725 val = MT6360_ISTRB_MINUA; 726 } else 727 val = clamp_align(val, MT6360_ISTRB_MINUA, MT6360_ISTRB_MAXUA, 728 MT6360_ISTRB_STEPUA); 729 730 s = &flash->brightness; 731 s->min = MT6360_ISTRB_MINUA; 732 s->step = MT6360_ISTRB_STEPUA; 733 s->val = s->max = val; 734 735 /* 736 * Always configure as min level when off to prevent flash current 737 * spike. 738 */ 739 ret = _mt6360_flash_brightness_set(flash, s->min); 740 if (ret) 741 return ret; 742 743 ret = fwnode_property_read_u32(init_data->fwnode, 744 "flash-max-timeout-us", &val); 745 if (ret) { 746 dev_warn(priv->dev, 747 "Not specified flash-max-timeout-us, config to the minimum\n"); 748 val = MT6360_STRBTO_MINUS; 749 } else 750 val = clamp_align(val, MT6360_STRBTO_MINUS, MT6360_STRBTO_MAXUS, 751 MT6360_STRBTO_STEPUS); 752 753 s = &flash->timeout; 754 s->min = MT6360_STRBTO_MINUS; 755 s->step = MT6360_STRBTO_STEPUS; 756 s->val = s->max = val; 757 758 flash->ops = &mt6360_flash_ops; 759 760 return 0; 761 } 762 763 static int mt6360_init_common_properties(struct mt6360_led *led, 764 struct led_init_data *init_data) 765 { 766 const char *const states[] = { "off", "keep", "on" }; 767 const char *str; 768 int ret; 769 770 if (!fwnode_property_read_string(init_data->fwnode, 771 "default-state", &str)) { 772 ret = match_string(states, ARRAY_SIZE(states), str); 773 if (ret < 0) 774 ret = STATE_OFF; 775 776 led->default_state = ret; 777 } 778 779 return 0; 780 } 781 782 static void mt6360_v4l2_flash_release(struct mt6360_priv *priv) 783 { 784 int i; 785 786 for (i = 0; i < priv->leds_count; i++) { 787 struct mt6360_led *led = priv->leds + i; 788 789 if (led->v4l2_flash) 790 v4l2_flash_release(led->v4l2_flash); 791 } 792 } 793 794 static int mt6360_led_probe(struct platform_device *pdev) 795 { 796 struct mt6360_priv *priv; 797 struct fwnode_handle *child; 798 size_t count; 799 int i = 0, ret; 800 801 count = device_get_child_node_count(&pdev->dev); 802 if (!count || count > MT6360_MAX_LEDS) { 803 dev_err(&pdev->dev, 804 "No child node or node count over max led number %zu\n", 805 count); 806 return -EINVAL; 807 } 808 809 priv = devm_kzalloc(&pdev->dev, 810 struct_size(priv, leds, count), GFP_KERNEL); 811 if (!priv) 812 return -ENOMEM; 813 814 priv->leds_count = count; 815 priv->dev = &pdev->dev; 816 mutex_init(&priv->lock); 817 818 priv->regmap = dev_get_regmap(pdev->dev.parent, NULL); 819 if (!priv->regmap) { 820 dev_err(&pdev->dev, "Failed to get parent regmap\n"); 821 return -ENODEV; 822 } 823 824 device_for_each_child_node(&pdev->dev, child) { 825 struct mt6360_led *led = priv->leds + i; 826 struct led_init_data init_data = { .fwnode = child, }; 827 u32 reg, led_color; 828 829 ret = fwnode_property_read_u32(child, "color", &led_color); 830 if (ret) 831 goto out_flash_release; 832 833 if (led_color == LED_COLOR_ID_RGB || 834 led_color == LED_COLOR_ID_MULTI) 835 reg = MT6360_VIRTUAL_MULTICOLOR; 836 else { 837 ret = fwnode_property_read_u32(child, "reg", ®); 838 if (ret) 839 goto out_flash_release; 840 841 if (reg >= MT6360_MAX_LEDS) { 842 ret = -EINVAL; 843 goto out_flash_release; 844 } 845 } 846 847 if (priv->leds_active & BIT(reg)) { 848 ret = -EINVAL; 849 goto out_flash_release; 850 } 851 priv->leds_active |= BIT(reg); 852 853 led->led_no = reg; 854 led->priv = priv; 855 856 ret = mt6360_init_common_properties(led, &init_data); 857 if (ret) 858 goto out_flash_release; 859 860 if (reg == MT6360_VIRTUAL_MULTICOLOR || 861 reg <= MT6360_LED_ISNKML) 862 ret = mt6360_init_isnk_properties(led, &init_data); 863 else 864 ret = mt6360_init_flash_properties(led, &init_data); 865 866 if (ret) 867 goto out_flash_release; 868 869 ret = mt6360_led_register(&pdev->dev, led, &init_data); 870 if (ret) 871 goto out_flash_release; 872 873 i++; 874 } 875 876 platform_set_drvdata(pdev, priv); 877 return 0; 878 879 out_flash_release: 880 mt6360_v4l2_flash_release(priv); 881 return ret; 882 } 883 884 static int mt6360_led_remove(struct platform_device *pdev) 885 { 886 struct mt6360_priv *priv = platform_get_drvdata(pdev); 887 888 mt6360_v4l2_flash_release(priv); 889 return 0; 890 } 891 892 static const struct of_device_id __maybe_unused mt6360_led_of_id[] = { 893 { .compatible = "mediatek,mt6360-led", }, 894 {} 895 }; 896 MODULE_DEVICE_TABLE(of, mt6360_led_of_id); 897 898 static struct platform_driver mt6360_led_driver = { 899 .driver = { 900 .name = "mt6360-led", 901 .of_match_table = mt6360_led_of_id, 902 }, 903 .probe = mt6360_led_probe, 904 .remove = mt6360_led_remove, 905 }; 906 module_platform_driver(mt6360_led_driver); 907 908 MODULE_AUTHOR("Gene Chen <gene_chen@richtek.com>"); 909 MODULE_DESCRIPTION("MT6360 LED Driver"); 910 MODULE_LICENSE("GPL v2"); 911