952 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (c) 2022, 2024 Qualcomm Innovation Center, Inc. All rights reserved.4 */5 6#include <linux/bitfield.h>7#include <linux/bits.h>8#include <linux/leds.h>9#include <linux/led-class-flash.h>10#include <linux/module.h>11#include <linux/platform_device.h>12#include <linux/property.h>13#include <linux/regmap.h>14#include <media/v4l2-flash-led-class.h>15 16/* registers definitions */17#define FLASH_REVISION_REG 0x0018#define FLASH_4CH_REVISION_V0P1 0x0119 20#define FLASH_TYPE_REG 0x0421#define FLASH_TYPE_VAL 0x1822 23#define FLASH_SUBTYPE_REG 0x0524#define FLASH_SUBTYPE_3CH_PM8150_VAL 0x0425#define FLASH_SUBTYPE_3CH_PMI8998_VAL 0x0326#define FLASH_SUBTYPE_4CH_VAL 0x0727 28#define FLASH_STS_3CH_OTST1 BIT(0)29#define FLASH_STS_3CH_OTST2 BIT(1)30#define FLASH_STS_3CH_OTST3 BIT(2)31#define FLASH_STS_3CH_BOB_THM_OVERLOAD BIT(3)32#define FLASH_STS_3CH_VPH_DROOP BIT(4)33#define FLASH_STS_3CH_BOB_ILIM_S1 BIT(5)34#define FLASH_STS_3CH_BOB_ILIM_S2 BIT(6)35#define FLASH_STS_3CH_BCL_IBAT BIT(7)36 37#define FLASH_STS_4CH_VPH_LOW BIT(0)38#define FLASH_STS_4CH_BCL_IBAT BIT(1)39#define FLASH_STS_4CH_BOB_ILIM_S1 BIT(2)40#define FLASH_STS_4CH_BOB_ILIM_S2 BIT(3)41#define FLASH_STS_4CH_OTST2 BIT(4)42#define FLASH_STS_4CH_OTST1 BIT(5)43#define FLASH_STS_4CHG_BOB_THM_OVERLOAD BIT(6)44 45#define FLASH_TIMER_EN_BIT BIT(7)46#define FLASH_TIMER_VAL_MASK GENMASK(6, 0)47#define FLASH_TIMER_STEP_MS 1048 49#define FLASH_STROBE_HW_SW_SEL_BIT BIT(2)50#define SW_STROBE_VAL 051#define HW_STROBE_VAL 152#define FLASH_HW_STROBE_TRIGGER_SEL_BIT BIT(1)53#define STROBE_LEVEL_TRIGGER_VAL 054#define STROBE_EDGE_TRIGGER_VAL 155#define FLASH_STROBE_POLARITY_BIT BIT(0)56#define STROBE_ACTIVE_HIGH_VAL 157 58#define FLASH_IRES_MASK_4CH BIT(0)59#define FLASH_IRES_MASK_3CH GENMASK(1, 0)60#define FLASH_IRES_12P5MA_VAL 061#define FLASH_IRES_5MA_VAL_4CH 162#define FLASH_IRES_5MA_VAL_3CH 363 64/* constants */65#define FLASH_CURRENT_MAX_UA 150000066#define TORCH_CURRENT_MAX_UA 50000067#define FLASH_TOTAL_CURRENT_MAX_UA 200000068#define FLASH_CURRENT_DEFAULT_UA 100000069#define TORCH_CURRENT_DEFAULT_UA 20000070 71#define TORCH_IRES_UA 500072#define FLASH_IRES_UA 1250073 74#define FLASH_TIMEOUT_MAX_US 128000075#define FLASH_TIMEOUT_STEP_US 1000076 77#define UA_PER_MA 100078 79/* thermal threshold constants */80#define OTST_3CH_MIN_VAL 381#define OTST1_4CH_MIN_VAL 082#define OTST1_4CH_V0P1_MIN_VAL 383#define OTST2_4CH_MIN_VAL 084 85#define OTST1_MAX_CURRENT_MA 100086#define OTST2_MAX_CURRENT_MA 50087#define OTST3_MAX_CURRENT_MA 20088 89enum hw_type {90 QCOM_MVFLASH_3CH,91 QCOM_MVFLASH_4CH,92};93 94enum led_mode {95 FLASH_MODE,96 TORCH_MODE,97};98 99enum led_strobe {100 SW_STROBE,101 HW_STROBE,102};103 104enum {105 REG_STATUS1,106 REG_STATUS2,107 REG_STATUS3,108 REG_CHAN_TIMER,109 REG_ITARGET,110 REG_MODULE_EN,111 REG_IRESOLUTION,112 REG_CHAN_STROBE,113 REG_CHAN_EN,114 REG_THERM_THRSH1,115 REG_THERM_THRSH2,116 REG_THERM_THRSH3,117 REG_MAX_COUNT,118};119 120static struct reg_field mvflash_3ch_regs[REG_MAX_COUNT] = {121 REG_FIELD(0x08, 0, 7), /* status1 */122 REG_FIELD(0x09, 0, 7), /* status2 */123 REG_FIELD(0x0a, 0, 7), /* status3 */124 REG_FIELD_ID(0x40, 0, 7, 3, 1), /* chan_timer */125 REG_FIELD_ID(0x43, 0, 6, 3, 1), /* itarget */126 REG_FIELD(0x46, 7, 7), /* module_en */127 REG_FIELD(0x47, 0, 5), /* iresolution */128 REG_FIELD_ID(0x49, 0, 2, 3, 1), /* chan_strobe */129 REG_FIELD(0x4c, 0, 2), /* chan_en */130 REG_FIELD(0x56, 0, 2), /* therm_thrsh1 */131 REG_FIELD(0x57, 0, 2), /* therm_thrsh2 */132 REG_FIELD(0x58, 0, 2), /* therm_thrsh3 */133};134 135static struct reg_field mvflash_4ch_regs[REG_MAX_COUNT] = {136 REG_FIELD(0x06, 0, 7), /* status1 */137 REG_FIELD(0x07, 0, 6), /* status2 */138 REG_FIELD(0x09, 0, 7), /* status3 */139 REG_FIELD_ID(0x3e, 0, 7, 4, 1), /* chan_timer */140 REG_FIELD_ID(0x42, 0, 6, 4, 1), /* itarget */141 REG_FIELD(0x46, 7, 7), /* module_en */142 REG_FIELD(0x49, 0, 3), /* iresolution */143 REG_FIELD_ID(0x4a, 0, 6, 4, 1), /* chan_strobe */144 REG_FIELD(0x4e, 0, 3), /* chan_en */145 REG_FIELD(0x7a, 0, 2), /* therm_thrsh1 */146 REG_FIELD(0x78, 0, 2), /* therm_thrsh2 */147};148 149struct qcom_flash_data {150 struct v4l2_flash **v4l2_flash;151 struct regmap_field *r_fields[REG_MAX_COUNT];152 struct mutex lock;153 enum hw_type hw_type;154 u32 total_ma;155 u8 leds_count;156 u8 max_channels;157 u8 chan_en_bits;158 u8 revision;159};160 161struct qcom_flash_led {162 struct qcom_flash_data *flash_data;163 struct led_classdev_flash flash;164 u32 max_flash_current_ma;165 u32 max_torch_current_ma;166 u32 max_timeout_ms;167 u32 flash_current_ma;168 u32 flash_timeout_ms;169 u32 current_in_use_ma;170 u8 *chan_id;171 u8 chan_count;172 bool enabled;173};174 175static int set_flash_module_en(struct qcom_flash_led *led, bool en)176{177 struct qcom_flash_data *flash_data = led->flash_data;178 u8 led_mask = 0, enable;179 int i, rc;180 181 for (i = 0; i < led->chan_count; i++)182 led_mask |= BIT(led->chan_id[i]);183 184 mutex_lock(&flash_data->lock);185 if (en)186 flash_data->chan_en_bits |= led_mask;187 else188 flash_data->chan_en_bits &= ~led_mask;189 190 enable = !!flash_data->chan_en_bits;191 rc = regmap_field_write(flash_data->r_fields[REG_MODULE_EN], enable);192 if (rc)193 dev_err(led->flash.led_cdev.dev, "write module_en failed, rc=%d\n", rc);194 mutex_unlock(&flash_data->lock);195 196 return rc;197}198 199static int update_allowed_flash_current(struct qcom_flash_led *led, u32 *current_ma, bool strobe)200{201 struct qcom_flash_data *flash_data = led->flash_data;202 u32 therm_ma, avail_ma, thrsh[3], min_thrsh, sts;203 int rc = 0;204 205 mutex_lock(&flash_data->lock);206 /*207 * Put previously allocated current into allowed budget in either of these two cases:208 * 1) LED is disabled;209 * 2) LED is enabled repeatedly210 */211 if (!strobe || led->current_in_use_ma != 0) {212 if (flash_data->total_ma >= led->current_in_use_ma)213 flash_data->total_ma -= led->current_in_use_ma;214 else215 flash_data->total_ma = 0;216 217 led->current_in_use_ma = 0;218 if (!strobe)219 goto unlock;220 }221 222 /*223 * Cache the default thermal threshold settings, and set them to the lowest levels before224 * reading over-temp real time status. If over-temp has been triggered at the lowest225 * threshold, it's very likely that it would be triggered at a higher (default) threshold226 * when more flash current is requested. Prevent device from triggering over-temp condition227 * by limiting the flash current for the new request.228 */229 rc = regmap_field_read(flash_data->r_fields[REG_THERM_THRSH1], &thrsh[0]);230 if (rc < 0)231 goto unlock;232 233 rc = regmap_field_read(flash_data->r_fields[REG_THERM_THRSH2], &thrsh[1]);234 if (rc < 0)235 goto unlock;236 237 if (flash_data->hw_type == QCOM_MVFLASH_3CH) {238 rc = regmap_field_read(flash_data->r_fields[REG_THERM_THRSH3], &thrsh[2]);239 if (rc < 0)240 goto unlock;241 }242 243 min_thrsh = OTST_3CH_MIN_VAL;244 if (flash_data->hw_type == QCOM_MVFLASH_4CH)245 min_thrsh = (flash_data->revision == FLASH_4CH_REVISION_V0P1) ?246 OTST1_4CH_V0P1_MIN_VAL : OTST1_4CH_MIN_VAL;247 248 rc = regmap_field_write(flash_data->r_fields[REG_THERM_THRSH1], min_thrsh);249 if (rc < 0)250 goto unlock;251 252 if (flash_data->hw_type == QCOM_MVFLASH_4CH)253 min_thrsh = OTST2_4CH_MIN_VAL;254 255 /*256 * The default thermal threshold settings have been updated hence257 * restore them if any fault happens starting from here.258 */259 rc = regmap_field_write(flash_data->r_fields[REG_THERM_THRSH2], min_thrsh);260 if (rc < 0)261 goto restore;262 263 if (flash_data->hw_type == QCOM_MVFLASH_3CH) {264 rc = regmap_field_write(flash_data->r_fields[REG_THERM_THRSH3], min_thrsh);265 if (rc < 0)266 goto restore;267 }268 269 /* Read thermal level status to get corresponding derating flash current */270 rc = regmap_field_read(flash_data->r_fields[REG_STATUS2], &sts);271 if (rc)272 goto restore;273 274 therm_ma = FLASH_TOTAL_CURRENT_MAX_UA / 1000;275 if (flash_data->hw_type == QCOM_MVFLASH_3CH) {276 if (sts & FLASH_STS_3CH_OTST3)277 therm_ma = OTST3_MAX_CURRENT_MA;278 else if (sts & FLASH_STS_3CH_OTST2)279 therm_ma = OTST2_MAX_CURRENT_MA;280 else if (sts & FLASH_STS_3CH_OTST1)281 therm_ma = OTST1_MAX_CURRENT_MA;282 } else {283 if (sts & FLASH_STS_4CH_OTST2)284 therm_ma = OTST2_MAX_CURRENT_MA;285 else if (sts & FLASH_STS_4CH_OTST1)286 therm_ma = OTST1_MAX_CURRENT_MA;287 }288 289 /* Calculate the allowed flash current for the request */290 if (therm_ma <= flash_data->total_ma)291 avail_ma = 0;292 else293 avail_ma = therm_ma - flash_data->total_ma;294 295 *current_ma = min_t(u32, *current_ma, avail_ma);296 led->current_in_use_ma = *current_ma;297 flash_data->total_ma += led->current_in_use_ma;298 299 dev_dbg(led->flash.led_cdev.dev, "allowed flash current: %dmA, total current: %dmA\n",300 led->current_in_use_ma, flash_data->total_ma);301 302restore:303 /* Restore to default thermal threshold settings */304 rc = regmap_field_write(flash_data->r_fields[REG_THERM_THRSH1], thrsh[0]);305 if (rc < 0)306 goto unlock;307 308 rc = regmap_field_write(flash_data->r_fields[REG_THERM_THRSH2], thrsh[1]);309 if (rc < 0)310 goto unlock;311 312 if (flash_data->hw_type == QCOM_MVFLASH_3CH)313 rc = regmap_field_write(flash_data->r_fields[REG_THERM_THRSH3], thrsh[2]);314 315unlock:316 mutex_unlock(&flash_data->lock);317 return rc;318}319 320static int set_flash_current(struct qcom_flash_led *led, u32 current_ma, enum led_mode mode)321{322 struct qcom_flash_data *flash_data = led->flash_data;323 u32 itarg_ua, ires_ua;324 u8 shift, ires_mask = 0, ires_val = 0, chan_id;325 int i, rc;326 327 /*328 * Split the current across the channels and set the329 * IRESOLUTION and ITARGET registers accordingly.330 */331 itarg_ua = (current_ma * UA_PER_MA) / led->chan_count + 1;332 ires_ua = (mode == FLASH_MODE) ? FLASH_IRES_UA : TORCH_IRES_UA;333 334 for (i = 0; i < led->chan_count; i++) {335 u8 itarget = 0;336 337 if (itarg_ua > ires_ua)338 itarget = itarg_ua / ires_ua - 1;339 340 chan_id = led->chan_id[i];341 342 rc = regmap_fields_write(flash_data->r_fields[REG_ITARGET], chan_id, itarget);343 if (rc)344 return rc;345 346 if (flash_data->hw_type == QCOM_MVFLASH_3CH) {347 shift = chan_id * 2;348 ires_mask |= FLASH_IRES_MASK_3CH << shift;349 ires_val |= ((mode == FLASH_MODE) ?350 (FLASH_IRES_12P5MA_VAL << shift) :351 (FLASH_IRES_5MA_VAL_3CH << shift));352 } else if (flash_data->hw_type == QCOM_MVFLASH_4CH) {353 shift = chan_id;354 ires_mask |= FLASH_IRES_MASK_4CH << shift;355 ires_val |= ((mode == FLASH_MODE) ?356 (FLASH_IRES_12P5MA_VAL << shift) :357 (FLASH_IRES_5MA_VAL_4CH << shift));358 } else {359 dev_err(led->flash.led_cdev.dev,360 "HW type %d is not supported\n", flash_data->hw_type);361 return -EOPNOTSUPP;362 }363 }364 365 return regmap_field_update_bits(flash_data->r_fields[REG_IRESOLUTION], ires_mask, ires_val);366}367 368static int set_flash_timeout(struct qcom_flash_led *led, u32 timeout_ms)369{370 struct qcom_flash_data *flash_data = led->flash_data;371 u8 timer, chan_id;372 int rc, i;373 374 /* set SAFETY_TIMER for all the channels connected to the same LED */375 timeout_ms = min_t(u32, timeout_ms, led->max_timeout_ms);376 377 for (i = 0; i < led->chan_count; i++) {378 chan_id = led->chan_id[i];379 380 timer = timeout_ms / FLASH_TIMER_STEP_MS;381 timer = clamp_t(u8, timer, 0, FLASH_TIMER_VAL_MASK);382 383 if (timeout_ms)384 timer |= FLASH_TIMER_EN_BIT;385 386 rc = regmap_fields_write(flash_data->r_fields[REG_CHAN_TIMER], chan_id, timer);387 if (rc)388 return rc;389 }390 391 return 0;392}393 394static int set_flash_strobe(struct qcom_flash_led *led, enum led_strobe strobe, bool state)395{396 struct qcom_flash_data *flash_data = led->flash_data;397 u8 strobe_sel, chan_en, chan_id, chan_mask = 0;398 int rc, i;399 400 /* Set SW strobe config for all channels connected to the LED */401 for (i = 0; i < led->chan_count; i++) {402 chan_id = led->chan_id[i];403 404 if (strobe == SW_STROBE)405 strobe_sel = FIELD_PREP(FLASH_STROBE_HW_SW_SEL_BIT, SW_STROBE_VAL);406 else407 strobe_sel = FIELD_PREP(FLASH_STROBE_HW_SW_SEL_BIT, HW_STROBE_VAL);408 409 strobe_sel |=410 FIELD_PREP(FLASH_HW_STROBE_TRIGGER_SEL_BIT, STROBE_LEVEL_TRIGGER_VAL) |411 FIELD_PREP(FLASH_STROBE_POLARITY_BIT, STROBE_ACTIVE_HIGH_VAL);412 413 rc = regmap_fields_write(414 flash_data->r_fields[REG_CHAN_STROBE], chan_id, strobe_sel);415 if (rc)416 return rc;417 418 chan_mask |= BIT(chan_id);419 }420 421 /* Enable/disable flash channels */422 chan_en = state ? chan_mask : 0;423 rc = regmap_field_update_bits(flash_data->r_fields[REG_CHAN_EN], chan_mask, chan_en);424 if (rc)425 return rc;426 427 led->enabled = state;428 return 0;429}430 431static inline struct qcom_flash_led *flcdev_to_qcom_fled(struct led_classdev_flash *flcdev)432{433 return container_of(flcdev, struct qcom_flash_led, flash);434}435 436static int qcom_flash_brightness_set(struct led_classdev_flash *fled_cdev, u32 brightness)437{438 struct qcom_flash_led *led = flcdev_to_qcom_fled(fled_cdev);439 440 led->flash_current_ma = min_t(u32, led->max_flash_current_ma, brightness / UA_PER_MA);441 return 0;442}443 444static int qcom_flash_timeout_set(struct led_classdev_flash *fled_cdev, u32 timeout)445{446 struct qcom_flash_led *led = flcdev_to_qcom_fled(fled_cdev);447 448 led->flash_timeout_ms = timeout / USEC_PER_MSEC;449 return 0;450}451 452static int qcom_flash_strobe_set(struct led_classdev_flash *fled_cdev, bool state)453{454 struct qcom_flash_led *led = flcdev_to_qcom_fled(fled_cdev);455 int rc;456 457 rc = set_flash_strobe(led, SW_STROBE, false);458 if (rc)459 return rc;460 461 rc = update_allowed_flash_current(led, &led->flash_current_ma, state);462 if (rc < 0)463 return rc;464 465 rc = set_flash_current(led, led->flash_current_ma, FLASH_MODE);466 if (rc)467 return rc;468 469 rc = set_flash_timeout(led, led->flash_timeout_ms);470 if (rc)471 return rc;472 473 rc = set_flash_module_en(led, state);474 if (rc)475 return rc;476 477 return set_flash_strobe(led, SW_STROBE, state);478}479 480static int qcom_flash_strobe_get(struct led_classdev_flash *fled_cdev, bool *state)481{482 struct qcom_flash_led *led = flcdev_to_qcom_fled(fled_cdev);483 484 *state = led->enabled;485 return 0;486}487 488static int qcom_flash_fault_get(struct led_classdev_flash *fled_cdev, u32 *fault)489{490 struct qcom_flash_led *led = flcdev_to_qcom_fled(fled_cdev);491 struct qcom_flash_data *flash_data = led->flash_data;492 u8 shift, chan_id, chan_mask = 0;493 u8 ot_mask = 0, oc_mask = 0, uv_mask = 0;494 u32 val, fault_sts = 0;495 int i, rc;496 497 rc = regmap_field_read(flash_data->r_fields[REG_STATUS1], &val);498 if (rc)499 return rc;500 501 for (i = 0; i < led->chan_count; i++) {502 chan_id = led->chan_id[i];503 shift = chan_id * 2;504 505 if (val & BIT(shift))506 fault_sts |= LED_FAULT_SHORT_CIRCUIT;507 508 chan_mask |= BIT(chan_id);509 }510 511 rc = regmap_field_read(flash_data->r_fields[REG_STATUS2], &val);512 if (rc)513 return rc;514 515 if (flash_data->hw_type == QCOM_MVFLASH_3CH) {516 ot_mask = FLASH_STS_3CH_OTST1 |517 FLASH_STS_3CH_OTST2 |518 FLASH_STS_3CH_OTST3 |519 FLASH_STS_3CH_BOB_THM_OVERLOAD;520 oc_mask = FLASH_STS_3CH_BOB_ILIM_S1 |521 FLASH_STS_3CH_BOB_ILIM_S2 |522 FLASH_STS_3CH_BCL_IBAT;523 uv_mask = FLASH_STS_3CH_VPH_DROOP;524 } else if (flash_data->hw_type == QCOM_MVFLASH_4CH) {525 ot_mask = FLASH_STS_4CH_OTST2 |526 FLASH_STS_4CH_OTST1 |527 FLASH_STS_4CHG_BOB_THM_OVERLOAD;528 oc_mask = FLASH_STS_4CH_BCL_IBAT |529 FLASH_STS_4CH_BOB_ILIM_S1 |530 FLASH_STS_4CH_BOB_ILIM_S2;531 uv_mask = FLASH_STS_4CH_VPH_LOW;532 }533 534 if (val & ot_mask)535 fault_sts |= LED_FAULT_OVER_TEMPERATURE;536 537 if (val & oc_mask)538 fault_sts |= LED_FAULT_OVER_CURRENT;539 540 if (val & uv_mask)541 fault_sts |= LED_FAULT_INPUT_VOLTAGE;542 543 rc = regmap_field_read(flash_data->r_fields[REG_STATUS3], &val);544 if (rc)545 return rc;546 547 if (flash_data->hw_type == QCOM_MVFLASH_3CH) {548 if (val & chan_mask)549 fault_sts |= LED_FAULT_TIMEOUT;550 } else if (flash_data->hw_type == QCOM_MVFLASH_4CH) {551 for (i = 0; i < led->chan_count; i++) {552 chan_id = led->chan_id[i];553 shift = chan_id * 2;554 555 if (val & BIT(shift))556 fault_sts |= LED_FAULT_TIMEOUT;557 }558 }559 560 *fault = fault_sts;561 return 0;562}563 564static int qcom_flash_led_brightness_set(struct led_classdev *led_cdev,565 enum led_brightness brightness)566{567 struct led_classdev_flash *fled_cdev = lcdev_to_flcdev(led_cdev);568 struct qcom_flash_led *led = flcdev_to_qcom_fled(fled_cdev);569 u32 current_ma = brightness * led->max_torch_current_ma / LED_FULL;570 bool enable = !!brightness;571 int rc;572 573 rc = set_flash_strobe(led, SW_STROBE, false);574 if (rc)575 return rc;576 577 rc = set_flash_module_en(led, false);578 if (rc)579 return rc;580 581 rc = update_allowed_flash_current(led, ¤t_ma, enable);582 if (rc < 0)583 return rc;584 585 rc = set_flash_current(led, current_ma, TORCH_MODE);586 if (rc)587 return rc;588 589 /* Disable flash timeout for torch LED */590 rc = set_flash_timeout(led, 0);591 if (rc)592 return rc;593 594 rc = set_flash_module_en(led, enable);595 if (rc)596 return rc;597 598 return set_flash_strobe(led, SW_STROBE, enable);599}600 601static const struct led_flash_ops qcom_flash_ops = {602 .flash_brightness_set = qcom_flash_brightness_set,603 .strobe_set = qcom_flash_strobe_set,604 .strobe_get = qcom_flash_strobe_get,605 .timeout_set = qcom_flash_timeout_set,606 .fault_get = qcom_flash_fault_get,607};608 609#if IS_ENABLED(CONFIG_V4L2_FLASH_LED_CLASS)610static int qcom_flash_external_strobe_set(struct v4l2_flash *v4l2_flash, bool enable)611{612 struct led_classdev_flash *fled_cdev = v4l2_flash->fled_cdev;613 struct qcom_flash_led *led = flcdev_to_qcom_fled(fled_cdev);614 int rc;615 616 rc = set_flash_module_en(led, enable);617 if (rc)618 return rc;619 620 if (enable)621 return set_flash_strobe(led, HW_STROBE, true);622 else623 return set_flash_strobe(led, SW_STROBE, false);624}625 626static enum led_brightness627qcom_flash_intensity_to_led_brightness(struct v4l2_flash *v4l2_flash, s32 intensity)628{629 struct led_classdev_flash *fled_cdev = v4l2_flash->fled_cdev;630 struct qcom_flash_led *led = flcdev_to_qcom_fled(fled_cdev);631 u32 current_ma = intensity / UA_PER_MA;632 633 current_ma = min_t(u32, current_ma, led->max_torch_current_ma);634 if (!current_ma)635 return LED_OFF;636 637 return (current_ma * LED_FULL) / led->max_torch_current_ma;638}639 640static s32 qcom_flash_brightness_to_led_intensity(struct v4l2_flash *v4l2_flash,641 enum led_brightness brightness)642{643 struct led_classdev_flash *fled_cdev = v4l2_flash->fled_cdev;644 struct qcom_flash_led *led = flcdev_to_qcom_fled(fled_cdev);645 646 return (brightness * led->max_torch_current_ma * UA_PER_MA) / LED_FULL;647}648 649static const struct v4l2_flash_ops qcom_v4l2_flash_ops = {650 .external_strobe_set = qcom_flash_external_strobe_set,651 .intensity_to_led_brightness = qcom_flash_intensity_to_led_brightness,652 .led_brightness_to_intensity = qcom_flash_brightness_to_led_intensity,653};654 655static int656qcom_flash_v4l2_init(struct device *dev, struct qcom_flash_led *led, struct fwnode_handle *fwnode)657{658 struct qcom_flash_data *flash_data = led->flash_data;659 struct v4l2_flash_config v4l2_cfg = { 0 };660 struct led_flash_setting *intensity = &v4l2_cfg.intensity;661 struct v4l2_flash *v4l2_flash;662 663 if (!(led->flash.led_cdev.flags & LED_DEV_CAP_FLASH))664 return 0;665 666 intensity->min = intensity->step = TORCH_IRES_UA * led->chan_count;667 intensity->max = led->max_torch_current_ma * UA_PER_MA;668 intensity->val = min_t(u32, intensity->max, TORCH_CURRENT_DEFAULT_UA);669 670 strscpy(v4l2_cfg.dev_name, led->flash.led_cdev.dev->kobj.name,671 sizeof(v4l2_cfg.dev_name));672 673 v4l2_cfg.has_external_strobe = true;674 v4l2_cfg.flash_faults = LED_FAULT_INPUT_VOLTAGE |675 LED_FAULT_OVER_CURRENT |676 LED_FAULT_SHORT_CIRCUIT |677 LED_FAULT_OVER_TEMPERATURE |678 LED_FAULT_TIMEOUT;679 680 v4l2_flash = v4l2_flash_init(dev, fwnode, &led->flash, &qcom_v4l2_flash_ops, &v4l2_cfg);681 if (IS_ERR(v4l2_flash))682 return PTR_ERR(v4l2_flash);683 684 flash_data->v4l2_flash[flash_data->leds_count] = v4l2_flash;685 return 0;686}687# else688static int689qcom_flash_v4l2_init(struct device *dev, struct qcom_flash_led *led, struct fwnode_handle *fwnode)690{691 return 0;692}693#endif694 695static int qcom_flash_register_led_device(struct device *dev,696 struct fwnode_handle *node, struct qcom_flash_led *led)697{698 struct qcom_flash_data *flash_data = led->flash_data;699 struct led_init_data init_data;700 struct led_classdev_flash *flash = &led->flash;701 struct led_flash_setting *brightness, *timeout;702 u32 current_ua, timeout_us;703 u32 channels[4];704 int i, rc, count;705 706 count = fwnode_property_count_u32(node, "led-sources");707 if (count <= 0) {708 dev_err(dev, "No led-sources specified\n");709 return -ENODEV;710 }711 712 if (count > flash_data->max_channels) {713 dev_err(dev, "led-sources count %u exceeds maximum channel count %u\n",714 count, flash_data->max_channels);715 return -EINVAL;716 }717 718 rc = fwnode_property_read_u32_array(node, "led-sources", channels, count);719 if (rc < 0) {720 dev_err(dev, "Failed to read led-sources property, rc=%d\n", rc);721 return rc;722 }723 724 led->chan_count = count;725 led->chan_id = devm_kcalloc(dev, count, sizeof(u8), GFP_KERNEL);726 if (!led->chan_id)727 return -ENOMEM;728 729 for (i = 0; i < count; i++) {730 if ((channels[i] == 0) || (channels[i] > flash_data->max_channels)) {731 dev_err(dev, "led-source out of HW support range [1-%u]\n",732 flash_data->max_channels);733 return -EINVAL;734 }735 736 /* Make chan_id indexing from 0 */737 led->chan_id[i] = channels[i] - 1;738 }739 740 rc = fwnode_property_read_u32(node, "led-max-microamp", ¤t_ua);741 if (rc < 0) {742 dev_err(dev, "Failed to read led-max-microamp property, rc=%d\n", rc);743 return rc;744 }745 746 if (current_ua == 0) {747 dev_err(dev, "led-max-microamp shouldn't be 0\n");748 return -EINVAL;749 }750 751 current_ua = min_t(u32, current_ua, TORCH_CURRENT_MAX_UA * led->chan_count);752 led->max_torch_current_ma = current_ua / UA_PER_MA;753 754 if (fwnode_property_present(node, "flash-max-microamp")) {755 flash->led_cdev.flags |= LED_DEV_CAP_FLASH;756 757 rc = fwnode_property_read_u32(node, "flash-max-microamp", ¤t_ua);758 if (rc < 0) {759 dev_err(dev, "Failed to read flash-max-microamp property, rc=%d\n",760 rc);761 return rc;762 }763 764 current_ua = min_t(u32, current_ua, FLASH_CURRENT_MAX_UA * led->chan_count);765 current_ua = min_t(u32, current_ua, FLASH_TOTAL_CURRENT_MAX_UA);766 767 /* Initialize flash class LED device brightness settings */768 brightness = &flash->brightness;769 brightness->min = brightness->step = FLASH_IRES_UA * led->chan_count;770 brightness->max = current_ua;771 brightness->val = min_t(u32, current_ua, FLASH_CURRENT_DEFAULT_UA);772 773 led->max_flash_current_ma = current_ua / UA_PER_MA;774 led->flash_current_ma = brightness->val / UA_PER_MA;775 776 rc = fwnode_property_read_u32(node, "flash-max-timeout-us", &timeout_us);777 if (rc < 0) {778 dev_err(dev, "Failed to read flash-max-timeout-us property, rc=%d\n",779 rc);780 return rc;781 }782 783 timeout_us = min_t(u32, timeout_us, FLASH_TIMEOUT_MAX_US);784 785 /* Initialize flash class LED device timeout settings */786 timeout = &flash->timeout;787 timeout->min = timeout->step = FLASH_TIMEOUT_STEP_US;788 timeout->val = timeout->max = timeout_us;789 790 led->max_timeout_ms = led->flash_timeout_ms = timeout_us / USEC_PER_MSEC;791 792 flash->ops = &qcom_flash_ops;793 }794 795 flash->led_cdev.brightness_set_blocking = qcom_flash_led_brightness_set;796 797 init_data.fwnode = node;798 init_data.devicename = NULL;799 init_data.default_label = NULL;800 init_data.devname_mandatory = false;801 802 rc = devm_led_classdev_flash_register_ext(dev, flash, &init_data);803 if (rc < 0) {804 dev_err(dev, "Register flash LED classdev failed, rc=%d\n", rc);805 return rc;806 }807 808 return qcom_flash_v4l2_init(dev, led, node);809}810 811static int qcom_flash_led_probe(struct platform_device *pdev)812{813 struct qcom_flash_data *flash_data;814 struct qcom_flash_led *led;815 struct fwnode_handle *child;816 struct device *dev = &pdev->dev;817 struct regmap *regmap;818 struct reg_field *regs;819 int count, i, rc;820 u32 val, reg_base;821 822 flash_data = devm_kzalloc(dev, sizeof(*flash_data), GFP_KERNEL);823 if (!flash_data)824 return -ENOMEM;825 826 regmap = dev_get_regmap(dev->parent, NULL);827 if (!regmap) {828 dev_err(dev, "Failed to get parent regmap\n");829 return -EINVAL;830 }831 832 rc = fwnode_property_read_u32(dev->fwnode, "reg", ®_base);833 if (rc < 0) {834 dev_err(dev, "Failed to get register base address, rc=%d\n", rc);835 return rc;836 }837 838 rc = regmap_read(regmap, reg_base + FLASH_TYPE_REG, &val);839 if (rc < 0) {840 dev_err(dev, "Read flash LED module type failed, rc=%d\n", rc);841 return rc;842 }843 844 if (val != FLASH_TYPE_VAL) {845 dev_err(dev, "type %#x is not a flash LED module\n", val);846 return -ENODEV;847 }848 849 rc = regmap_read(regmap, reg_base + FLASH_SUBTYPE_REG, &val);850 if (rc < 0) {851 dev_err(dev, "Read flash LED module subtype failed, rc=%d\n", rc);852 return rc;853 }854 855 if (val == FLASH_SUBTYPE_3CH_PM8150_VAL || val == FLASH_SUBTYPE_3CH_PMI8998_VAL) {856 flash_data->hw_type = QCOM_MVFLASH_3CH;857 flash_data->max_channels = 3;858 regs = mvflash_3ch_regs;859 } else if (val == FLASH_SUBTYPE_4CH_VAL) {860 flash_data->hw_type = QCOM_MVFLASH_4CH;861 flash_data->max_channels = 4;862 regs = mvflash_4ch_regs;863 864 rc = regmap_read(regmap, reg_base + FLASH_REVISION_REG, &val);865 if (rc < 0) {866 dev_err(dev, "Failed to read flash LED module revision, rc=%d\n", rc);867 return rc;868 }869 870 flash_data->revision = val;871 } else {872 dev_err(dev, "flash LED subtype %#x is not yet supported\n", val);873 return -ENODEV;874 }875 876 for (i = 0; i < REG_MAX_COUNT; i++)877 regs[i].reg += reg_base;878 879 rc = devm_regmap_field_bulk_alloc(dev, regmap, flash_data->r_fields, regs, REG_MAX_COUNT);880 if (rc < 0) {881 dev_err(dev, "Failed to allocate regmap field, rc=%d\n", rc);882 return rc;883 }884 885 platform_set_drvdata(pdev, flash_data);886 mutex_init(&flash_data->lock);887 888 count = device_get_child_node_count(dev);889 if (count == 0 || count > flash_data->max_channels) {890 dev_err(dev, "No child or child count exceeds %d\n", flash_data->max_channels);891 return -EINVAL;892 }893 894 flash_data->v4l2_flash = devm_kcalloc(dev, count,895 sizeof(*flash_data->v4l2_flash), GFP_KERNEL);896 if (!flash_data->v4l2_flash)897 return -ENOMEM;898 899 device_for_each_child_node(dev, child) {900 led = devm_kzalloc(dev, sizeof(*led), GFP_KERNEL);901 if (!led) {902 rc = -ENOMEM;903 goto release;904 }905 906 led->flash_data = flash_data;907 rc = qcom_flash_register_led_device(dev, child, led);908 if (rc < 0)909 goto release;910 911 flash_data->leds_count++;912 }913 914 return 0;915 916release:917 fwnode_handle_put(child);918 while (flash_data->v4l2_flash[flash_data->leds_count] && flash_data->leds_count)919 v4l2_flash_release(flash_data->v4l2_flash[flash_data->leds_count--]);920 return rc;921}922 923static void qcom_flash_led_remove(struct platform_device *pdev)924{925 struct qcom_flash_data *flash_data = platform_get_drvdata(pdev);926 927 while (flash_data->v4l2_flash[flash_data->leds_count] && flash_data->leds_count)928 v4l2_flash_release(flash_data->v4l2_flash[flash_data->leds_count--]);929 930 mutex_destroy(&flash_data->lock);931}932 933static const struct of_device_id qcom_flash_led_match_table[] = {934 { .compatible = "qcom,spmi-flash-led" },935 { }936};937 938MODULE_DEVICE_TABLE(of, qcom_flash_led_match_table);939static struct platform_driver qcom_flash_led_driver = {940 .driver = {941 .name = "leds-qcom-flash",942 .of_match_table = qcom_flash_led_match_table,943 },944 .probe = qcom_flash_led_probe,945 .remove_new = qcom_flash_led_remove,946};947 948module_platform_driver(qcom_flash_led_driver);949 950MODULE_DESCRIPTION("QCOM Flash LED driver");951MODULE_LICENSE("GPL");952