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