1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Copyright (C) 2023 Richtek Technology Corp. 4 * 5 * Authors: 6 * Alice Chen <alice_chen@richtek.com> 7 * ChiYuan Huang <cy_huang@richtek.com> 8 */ 9 10#include <linux/bitops.h> 11#include <linux/delay.h> 12#include <linux/init.h> 13#include <linux/interrupt.h> 14#include <linux/kernel.h> 15#include <linux/led-class-flash.h> 16#include <linux/module.h> 17#include <linux/mutex.h> 18#include <linux/platform_device.h> 19#include <linux/property.h> 20#include <linux/regmap.h> 21 22#include <media/v4l2-flash-led-class.h> 23 24enum { 25 MT6370_LED_FLASH1 = 0, 26 MT6370_LED_FLASH2, 27 MT6370_MAX_LEDS 28}; 29 30/* Virtual definition for multicolor */ 31 32#define MT6370_REG_FLEDEN 0x17E 33#define MT6370_REG_STRBTO 0x173 34#define MT6370_REG_CHGSTAT2 0x1D1 35#define MT6370_REG_FLEDSTAT1 0x1D9 36#define MT6370_REG_FLEDISTRB(_id) (0x174 + 4 * (_id)) 37#define MT6370_REG_FLEDITOR(_id) (0x175 + 4 * (_id)) 38#define MT6370_ITORCH_MASK GENMASK(4, 0) 39#define MT6370_ISTROBE_MASK GENMASK(6, 0) 40#define MT6370_STRBTO_MASK GENMASK(6, 0) 41#define MT6370_TORCHEN_MASK BIT(3) 42#define MT6370_STROBEN_MASK BIT(2) 43#define MT6370_FLCSEN_MASK(_id) BIT(MT6370_LED_FLASH2 - (_id)) 44#define MT6370_FLCSEN_MASK_ALL GENMASK(1, 0) 45#define MT6370_FLEDCHGVINOVP_MASK BIT(3) 46#define MT6370_FLED1STRBTO_MASK BIT(11) 47#define MT6370_FLED2STRBTO_MASK BIT(10) 48#define MT6370_FLED1STRB_MASK BIT(9) 49#define MT6370_FLED2STRB_MASK BIT(8) 50#define MT6370_FLED1SHORT_MASK BIT(7) 51#define MT6370_FLED2SHORT_MASK BIT(6) 52#define MT6370_FLEDLVF_MASK BIT(3) 53 54#define MT6370_LED_JOINT 2 55#define MT6370_RANGE_FLED_REG 4 56#define MT6370_ITORCH_MIN_uA 25000 57#define MT6370_ITORCH_STEP_uA 12500 58#define MT6370_ITORCH_MAX_uA 400000 59#define MT6370_ITORCH_DOUBLE_MAX_uA 800000 60#define MT6370_ISTRB_MIN_uA 50000 61#define MT6370_ISTRB_STEP_uA 12500 62#define MT6370_ISTRB_MAX_uA 1500000 63#define MT6370_ISTRB_DOUBLE_MAX_uA 3000000 64#define MT6370_STRBTO_MIN_US 64000 65#define MT6370_STRBTO_STEP_US 32000 66#define MT6370_STRBTO_MAX_US 2432000 67 68#define to_mt6370_led(ptr, member) container_of(ptr, struct mt6370_led, member) 69 70struct mt6370_led { 71 struct led_classdev_flash flash; 72 struct v4l2_flash *v4l2_flash; 73 struct mt6370_priv *priv; 74 u8 led_no; 75}; 76 77struct mt6370_priv { 78 struct regmap *regmap; 79 struct mutex lock; 80 unsigned int fled_strobe_used; 81 unsigned int fled_torch_used; 82 unsigned int leds_active; 83 unsigned int leds_count; 84 struct mt6370_led leds[] __counted_by(leds_count); 85}; 86 87static int mt6370_torch_brightness_set(struct led_classdev *lcdev, enum led_brightness level) 88{ 89 struct mt6370_led *led = to_mt6370_led(lcdev, flash.led_cdev); 90 struct mt6370_priv *priv = led->priv; 91 u32 led_enable_mask = led->led_no == MT6370_LED_JOINT ? MT6370_FLCSEN_MASK_ALL : 92 MT6370_FLCSEN_MASK(led->led_no); 93 u32 enable_mask = MT6370_TORCHEN_MASK | led_enable_mask; 94 u32 val = level ? led_enable_mask : 0; 95 u32 curr; 96 int ret, i; 97 98 mutex_lock(&priv->lock); 99 100 /* 101 * There is only one set of flash control logic, and this flag is used to check if 'strobe' 102 * is currently being used. 103 */ 104 if (priv->fled_strobe_used) { 105 dev_warn(lcdev->dev, "Please disable strobe first [%d]\n", priv->fled_strobe_used); 106 ret = -EBUSY; 107 goto unlock; 108 } 109 110 if (level) 111 curr = priv->fled_torch_used | BIT(led->led_no); 112 else 113 curr = priv->fled_torch_used & ~BIT(led->led_no); 114 115 if (curr) 116 val |= MT6370_TORCHEN_MASK; 117 118 if (level) { 119 level -= 1; 120 if (led->led_no == MT6370_LED_JOINT) { 121 u32 flevel[MT6370_MAX_LEDS]; 122 123 /* 124 * There're two flash channels in MT6370. If joint flash output is used, 125 * torch current will be averaged output from both channels. 126 */ 127 flevel[0] = level / 2; 128 flevel[1] = level - flevel[0]; 129 for (i = 0; i < MT6370_MAX_LEDS; i++) { 130 ret = regmap_update_bits(priv->regmap, MT6370_REG_FLEDITOR(i), 131 MT6370_ITORCH_MASK, flevel[i]); 132 if (ret) 133 goto unlock; 134 } 135 } else { 136 ret = regmap_update_bits(priv->regmap, MT6370_REG_FLEDITOR(led->led_no), 137 MT6370_ITORCH_MASK, level); 138 if (ret) 139 goto unlock; 140 } 141 } 142 143 ret = regmap_update_bits(priv->regmap, MT6370_REG_FLEDEN, enable_mask, val); 144 if (ret) 145 goto unlock; 146 147 priv->fled_torch_used = curr; 148 149unlock: 150 mutex_unlock(&priv->lock); 151 return ret; 152} 153 154static int mt6370_flash_brightness_set(struct led_classdev_flash *fl_cdev, u32 brightness) 155{ 156 /* 157 * Because of the current spikes when turning on the flash, the brightness should be kept 158 * by the LED framework. This empty function is used to prevent checking failure when 159 * led_classdev_flash registers ops. 160 */ 161 return 0; 162} 163 164static int _mt6370_flash_brightness_set(struct led_classdev_flash *fl_cdev, u32 brightness) 165{ 166 struct mt6370_led *led = to_mt6370_led(fl_cdev, flash); 167 struct mt6370_priv *priv = led->priv; 168 struct led_flash_setting *setting = &fl_cdev->brightness; 169 u32 val = (brightness - setting->min) / setting->step; 170 int ret, i; 171 172 if (led->led_no == MT6370_LED_JOINT) { 173 u32 flevel[MT6370_MAX_LEDS]; 174 175 /* 176 * There're two flash channels in MT6370. If joint flash output is used, storbe 177 * current will be averaged output from both channels. 178 */ 179 flevel[0] = val / 2; 180 flevel[1] = val - flevel[0]; 181 for (i = 0; i < MT6370_MAX_LEDS; i++) { 182 ret = regmap_update_bits(priv->regmap, MT6370_REG_FLEDISTRB(i), 183 MT6370_ISTROBE_MASK, flevel[i]); 184 if (ret) 185 break; 186 } 187 } else { 188 ret = regmap_update_bits(priv->regmap, MT6370_REG_FLEDISTRB(led->led_no), 189 MT6370_ISTROBE_MASK, val); 190 } 191 192 return ret; 193} 194 195static int mt6370_strobe_set(struct led_classdev_flash *fl_cdev, bool state) 196{ 197 struct mt6370_led *led = to_mt6370_led(fl_cdev, flash); 198 struct mt6370_priv *priv = led->priv; 199 struct led_classdev *lcdev = &fl_cdev->led_cdev; 200 struct led_flash_setting *s = &fl_cdev->brightness; 201 u32 led_enable_mask = led->led_no == MT6370_LED_JOINT ? MT6370_FLCSEN_MASK_ALL : 202 MT6370_FLCSEN_MASK(led->led_no); 203 u32 enable_mask = MT6370_STROBEN_MASK | led_enable_mask; 204 u32 val = state ? led_enable_mask : 0; 205 u32 curr; 206 int ret; 207 208 mutex_lock(&priv->lock); 209 210 /* 211 * There is only one set of flash control logic, and this flag is used to check if 'torch' 212 * is currently being used. 213 */ 214 if (priv->fled_torch_used) { 215 dev_warn(lcdev->dev, "Please disable torch first [0x%x]\n", priv->fled_torch_used); 216 ret = -EBUSY; 217 goto unlock; 218 } 219 220 if (state) 221 curr = priv->fled_strobe_used | BIT(led->led_no); 222 else 223 curr = priv->fled_strobe_used & ~BIT(led->led_no); 224 225 if (curr) 226 val |= MT6370_STROBEN_MASK; 227 228 ret = regmap_update_bits(priv->regmap, MT6370_REG_FLEDEN, enable_mask, val); 229 if (ret) { 230 dev_err(lcdev->dev, "[%d] control current source %d fail\n", led->led_no, state); 231 goto unlock; 232 } 233 234 /* 235 * If the flash needs to turn on, configure the flash current to ramp up to the setting 236 * value. Otherwise, always revert to the minimum one. 237 */ 238 ret = _mt6370_flash_brightness_set(fl_cdev, state ? s->val : s->min); 239 if (ret) { 240 dev_err(lcdev->dev, "[%d] Failed to set brightness\n", led->led_no); 241 goto unlock; 242 } 243 244 /* 245 * For the flash to turn on/off, we must wait for HW ramping up/down time 5ms/500us to 246 * prevent the unexpected problem. 247 */ 248 if (!priv->fled_strobe_used && curr) 249 usleep_range(5000, 6000); 250 else if (priv->fled_strobe_used && !curr) 251 usleep_range(500, 600); 252 253 priv->fled_strobe_used = curr; 254 255unlock: 256 mutex_unlock(&priv->lock); 257 return ret; 258} 259 260static int mt6370_strobe_get(struct led_classdev_flash *fl_cdev, bool *state) 261{ 262 struct mt6370_led *led = to_mt6370_led(fl_cdev, flash); 263 struct mt6370_priv *priv = led->priv; 264 265 mutex_lock(&priv->lock); 266 *state = !!(priv->fled_strobe_used & BIT(led->led_no)); 267 mutex_unlock(&priv->lock); 268 269 return 0; 270} 271 272static int mt6370_timeout_set(struct led_classdev_flash *fl_cdev, u32 timeout) 273{ 274 struct mt6370_led *led = to_mt6370_led(fl_cdev, flash); 275 struct mt6370_priv *priv = led->priv; 276 struct led_flash_setting *s = &fl_cdev->timeout; 277 u32 val = (timeout - s->min) / s->step; 278 279 return regmap_update_bits(priv->regmap, MT6370_REG_STRBTO, MT6370_STRBTO_MASK, val); 280} 281 282static int mt6370_fault_get(struct led_classdev_flash *fl_cdev, u32 *fault) 283{ 284 struct mt6370_led *led = to_mt6370_led(fl_cdev, flash); 285 struct mt6370_priv *priv = led->priv; 286 u16 fled_stat; 287 unsigned int chg_stat, strobe_timeout_mask, fled_short_mask; 288 u32 rfault = 0; 289 int ret; 290 291 ret = regmap_read(priv->regmap, MT6370_REG_CHGSTAT2, &chg_stat); 292 if (ret) 293 return ret; 294 295 ret = regmap_raw_read(priv->regmap, MT6370_REG_FLEDSTAT1, &fled_stat, sizeof(fled_stat)); 296 if (ret) 297 return ret; 298 299 switch (led->led_no) { 300 case MT6370_LED_FLASH1: 301 strobe_timeout_mask = MT6370_FLED1STRBTO_MASK; 302 fled_short_mask = MT6370_FLED1SHORT_MASK; 303 break; 304 305 case MT6370_LED_FLASH2: 306 strobe_timeout_mask = MT6370_FLED2STRBTO_MASK; 307 fled_short_mask = MT6370_FLED2SHORT_MASK; 308 break; 309 310 case MT6370_LED_JOINT: 311 strobe_timeout_mask = MT6370_FLED1STRBTO_MASK | MT6370_FLED2STRBTO_MASK; 312 fled_short_mask = MT6370_FLED1SHORT_MASK | MT6370_FLED2SHORT_MASK; 313 break; 314 default: 315 return -EINVAL; 316 } 317 318 if (chg_stat & MT6370_FLEDCHGVINOVP_MASK) 319 rfault |= LED_FAULT_INPUT_VOLTAGE; 320 321 if (fled_stat & strobe_timeout_mask) 322 rfault |= LED_FAULT_TIMEOUT; 323 324 if (fled_stat & fled_short_mask) 325 rfault |= LED_FAULT_SHORT_CIRCUIT; 326 327 if (fled_stat & MT6370_FLEDLVF_MASK) 328 rfault |= LED_FAULT_UNDER_VOLTAGE; 329 330 *fault = rfault; 331 return ret; 332} 333 334static const struct led_flash_ops mt6370_flash_ops = { 335 .flash_brightness_set = mt6370_flash_brightness_set, 336 .strobe_set = mt6370_strobe_set, 337 .strobe_get = mt6370_strobe_get, 338 .timeout_set = mt6370_timeout_set, 339 .fault_get = mt6370_fault_get, 340}; 341 342#if IS_ENABLED(CONFIG_V4L2_FLASH_LED_CLASS) 343static int mt6370_flash_external_strobe_set(struct v4l2_flash *v4l2_flash, 344 bool enable) 345{ 346 struct led_classdev_flash *flash = v4l2_flash->fled_cdev; 347 struct mt6370_led *led = to_mt6370_led(flash, flash); 348 struct mt6370_priv *priv = led->priv; 349 u32 mask = led->led_no == MT6370_LED_JOINT ? MT6370_FLCSEN_MASK_ALL : 350 MT6370_FLCSEN_MASK(led->led_no); 351 u32 val = enable ? mask : 0; 352 int ret; 353 354 mutex_lock(&priv->lock); 355 356 ret = regmap_update_bits(priv->regmap, MT6370_REG_FLEDEN, mask, val); 357 if (ret) 358 goto unlock; 359 360 if (enable) 361 priv->fled_strobe_used |= BIT(led->led_no); 362 else 363 priv->fled_strobe_used &= ~BIT(led->led_no); 364 365unlock: 366 mutex_unlock(&priv->lock); 367 return ret; 368} 369 370static const struct v4l2_flash_ops v4l2_flash_ops = { 371 .external_strobe_set = mt6370_flash_external_strobe_set, 372}; 373 374static void mt6370_init_v4l2_flash_config(struct mt6370_led *led, struct v4l2_flash_config *cfg) 375{ 376 struct led_classdev *lcdev; 377 struct led_flash_setting *s = &cfg->intensity; 378 379 lcdev = &led->flash.led_cdev; 380 381 s->min = MT6370_ITORCH_MIN_uA; 382 s->step = MT6370_ITORCH_STEP_uA; 383 s->val = s->max = s->min + (lcdev->max_brightness - 1) * s->step; 384 385 cfg->has_external_strobe = 1; 386 strscpy(cfg->dev_name, dev_name(lcdev->dev), sizeof(cfg->dev_name)); 387 388 cfg->flash_faults = LED_FAULT_SHORT_CIRCUIT | LED_FAULT_TIMEOUT | 389 LED_FAULT_INPUT_VOLTAGE | LED_FAULT_UNDER_VOLTAGE; 390} 391#else 392static const struct v4l2_flash_ops v4l2_flash_ops; 393static void mt6370_init_v4l2_flash_config(struct mt6370_led *led, struct v4l2_flash_config *cfg) 394{ 395} 396#endif 397 398static void mt6370_v4l2_flash_release(void *v4l2_flash) 399{ 400 v4l2_flash_release(v4l2_flash); 401} 402 403static int mt6370_led_register(struct device *parent, struct mt6370_led *led, 404 struct fwnode_handle *fwnode) 405{ 406 struct led_init_data init_data = { .fwnode = fwnode }; 407 struct v4l2_flash_config v4l2_config = {}; 408 int ret; 409 410 ret = devm_led_classdev_flash_register_ext(parent, &led->flash, &init_data); 411 if (ret) 412 return dev_err_probe(parent, ret, "Couldn't register flash %d\n", led->led_no); 413 414 mt6370_init_v4l2_flash_config(led, &v4l2_config); 415 led->v4l2_flash = v4l2_flash_init(parent, fwnode, &led->flash, &v4l2_flash_ops, 416 &v4l2_config); 417 if (IS_ERR(led->v4l2_flash)) 418 return dev_err_probe(parent, PTR_ERR(led->v4l2_flash), 419 "Failed to register %d v4l2 sd\n", led->led_no); 420 421 return devm_add_action_or_reset(parent, mt6370_v4l2_flash_release, led->v4l2_flash); 422} 423 424static u32 mt6370_clamp(u32 val, u32 min, u32 max, u32 step) 425{ 426 u32 retval; 427 428 retval = clamp_val(val, min, max); 429 if (step > 1) 430 retval = rounddown(retval - min, step) + min; 431 432 return retval; 433} 434 435static int mt6370_init_flash_properties(struct device *dev, struct mt6370_led *led, 436 struct fwnode_handle *fwnode) 437{ 438 struct led_classdev_flash *flash = &led->flash; 439 struct led_classdev *lcdev = &flash->led_cdev; 440 struct mt6370_priv *priv = led->priv; 441 struct led_flash_setting *s; 442 u32 sources[MT6370_MAX_LEDS]; 443 u32 max_ua, val; 444 int i, ret, num; 445 446 num = fwnode_property_count_u32(fwnode, "led-sources"); 447 if (num < 1) 448 return dev_err_probe(dev, -EINVAL, 449 "Not specified or wrong number of led-sources\n"); 450 451 ret = fwnode_property_read_u32_array(fwnode, "led-sources", sources, num); 452 if (ret) 453 return ret; 454 455 for (i = 0; i < num; i++) { 456 if (sources[i] >= MT6370_MAX_LEDS) 457 return -EINVAL; 458 if (priv->leds_active & BIT(sources[i])) 459 return -EINVAL; 460 priv->leds_active |= BIT(sources[i]); 461 } 462 463 /* If both channels are specified in 'led-sources', joint flash output mode is used */ 464 led->led_no = num == 2 ? MT6370_LED_JOINT : sources[0]; 465 466 max_ua = num == 2 ? MT6370_ITORCH_DOUBLE_MAX_uA : MT6370_ITORCH_MAX_uA; 467 val = MT6370_ITORCH_MIN_uA; 468 ret = fwnode_property_read_u32(fwnode, "led-max-microamp", &val); 469 if (!ret) 470 val = mt6370_clamp(val, MT6370_ITORCH_MIN_uA, max_ua, MT6370_ITORCH_STEP_uA); 471 472 lcdev->max_brightness = (val - MT6370_ITORCH_MIN_uA) / MT6370_ITORCH_STEP_uA + 1; 473 lcdev->brightness_set_blocking = mt6370_torch_brightness_set; 474 lcdev->flags |= LED_DEV_CAP_FLASH; 475 476 max_ua = num == 2 ? MT6370_ISTRB_DOUBLE_MAX_uA : MT6370_ISTRB_MAX_uA; 477 val = MT6370_ISTRB_MIN_uA; 478 ret = fwnode_property_read_u32(fwnode, "flash-max-microamp", &val); 479 if (!ret) 480 val = mt6370_clamp(val, MT6370_ISTRB_MIN_uA, max_ua, MT6370_ISTRB_STEP_uA); 481 482 s = &flash->brightness; 483 s->min = MT6370_ISTRB_MIN_uA; 484 s->step = MT6370_ISTRB_STEP_uA; 485 s->val = s->max = val; 486 487 /* Always configure to the minimum level when off to prevent flash current spikes. */ 488 ret = _mt6370_flash_brightness_set(flash, s->min); 489 if (ret) 490 return ret; 491 492 val = MT6370_STRBTO_MIN_US; 493 ret = fwnode_property_read_u32(fwnode, "flash-max-timeout-us", &val); 494 if (!ret) 495 val = mt6370_clamp(val, MT6370_STRBTO_MIN_US, MT6370_STRBTO_MAX_US, 496 MT6370_STRBTO_STEP_US); 497 498 s = &flash->timeout; 499 s->min = MT6370_STRBTO_MIN_US; 500 s->step = MT6370_STRBTO_STEP_US; 501 s->val = s->max = val; 502 503 flash->ops = &mt6370_flash_ops; 504 505 return 0; 506} 507 508static int mt6370_led_probe(struct platform_device *pdev) 509{ 510 struct device *dev = &pdev->dev; 511 struct mt6370_priv *priv; 512 struct fwnode_handle *child; 513 size_t count; 514 int i = 0, ret; 515 516 count = device_get_child_node_count(dev); 517 if (!count || count > MT6370_MAX_LEDS) 518 return dev_err_probe(dev, -EINVAL, 519 "No child node or node count over max led number %zu\n", count); 520 521 priv = devm_kzalloc(dev, struct_size(priv, leds, count), GFP_KERNEL); 522 if (!priv) 523 return -ENOMEM; 524 525 priv->leds_count = count; 526 mutex_init(&priv->lock); 527 528 priv->regmap = dev_get_regmap(dev->parent, NULL); 529 if (!priv->regmap) 530 return dev_err_probe(dev, -ENODEV, "Failed to get parent regmap\n"); 531 532 device_for_each_child_node(dev, child) { 533 struct mt6370_led *led = priv->leds + i; 534 535 led->priv = priv; 536 537 ret = mt6370_init_flash_properties(dev, led, child); 538 if (ret) { 539 fwnode_handle_put(child); 540 return ret; 541 } 542 543 ret = mt6370_led_register(dev, led, child); 544 if (ret) { 545 fwnode_handle_put(child); 546 return ret; 547 } 548 549 i++; 550 } 551 552 return 0; 553} 554 555static const struct of_device_id mt6370_led_of_id[] = { 556 { .compatible = "mediatek,mt6370-flashlight" }, 557 {} 558}; 559MODULE_DEVICE_TABLE(of, mt6370_led_of_id); 560 561static struct platform_driver mt6370_led_driver = { 562 .driver = { 563 .name = "mt6370-flashlight", 564 .of_match_table = mt6370_led_of_id, 565 }, 566 .probe = mt6370_led_probe, 567}; 568module_platform_driver(mt6370_led_driver); 569 570MODULE_AUTHOR("Alice Chen <alice_chen@richtek.com>"); 571MODULE_AUTHOR("ChiYuan Huang <cy_huang@richtek.com>"); 572MODULE_DESCRIPTION("MT6370 FLASH LED Driver"); 573MODULE_LICENSE("GPL"); 574