// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2022, 2024-2025 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/bitfield.h>
#include <linux/bits.h>
#include <linux/leds.h>
#include <linux/led-class-flash.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/regmap.h>
#include <media/v4l2-flash-led-class.h>
/* registers definitions */
#define FLASH_REVISION_REG 0x00
#define FLASH_4CH_REVISION_V0P1 0x01
#define FLASH_TYPE_REG 0x04
#define FLASH_TYPE_VAL 0x18
#define FLASH_SUBTYPE_REG 0x05
#define FLASH_SUBTYPE_3CH_PM8150_VAL 0x04
#define FLASH_SUBTYPE_3CH_PMI8998_VAL 0x03
#define FLASH_SUBTYPE_4CH_VAL 0x07
#define FLASH_STS_3CH_OTST1 BIT(0)
#define FLASH_STS_3CH_OTST2 BIT(1)
#define FLASH_STS_3CH_OTST3 BIT(2)
#define FLASH_STS_3CH_BOB_THM_OVERLOAD BIT(3)
#define FLASH_STS_3CH_VPH_DROOP BIT(4)
#define FLASH_STS_3CH_BOB_ILIM_S1 BIT(5)
#define FLASH_STS_3CH_BOB_ILIM_S2 BIT(6)
#define FLASH_STS_3CH_BCL_IBAT BIT(7)
#define FLASH_STS_4CH_VPH_LOW BIT(0)
#define FLASH_STS_4CH_BCL_IBAT BIT(1)
#define FLASH_STS_4CH_BOB_ILIM_S1 BIT(2)
#define FLASH_STS_4CH_BOB_ILIM_S2 BIT(3)
#define FLASH_STS_4CH_OTST2 BIT(4)
#define FLASH_STS_4CH_OTST1 BIT(5)
#define FLASH_STS_4CHG_BOB_THM_OVERLOAD BIT(6)
#define FLASH_TIMER_EN_BIT BIT(7)
#define FLASH_TIMER_VAL_MASK GENMASK(6, 0)
#define FLASH_TIMER_STEP_MS 10
#define FLASH_STROBE_HW_SW_SEL_BIT BIT(2)
#define SW_STROBE_VAL 0
#define HW_STROBE_VAL 1
#define FLASH_HW_STROBE_TRIGGER_SEL_BIT BIT(1)
#define STROBE_LEVEL_TRIGGER_VAL 0
#define STROBE_EDGE_TRIGGER_VAL 1
#define FLASH_STROBE_POLARITY_BIT BIT(0)
#define STROBE_ACTIVE_HIGH_VAL 1
#define FLASH_IRES_MASK_4CH BIT(0)
#define FLASH_IRES_MASK_3CH GENMASK(1, 0)
#define FLASH_IRES_12P5MA_VAL 0
#define FLASH_IRES_5MA_VAL_4CH 1
#define FLASH_IRES_5MA_VAL_3CH 3
/* constants */
#define FLASH_CURRENT_MAX_UA 1500000
#define TORCH_CURRENT_MAX_UA 500000
#define FLASH_TOTAL_CURRENT_MAX_UA 2000000
#define FLASH_CURRENT_DEFAULT_UA 1000000
#define TORCH_CURRENT_DEFAULT_UA 200000
#define TORCH_IRES_UA 5000
#define FLASH_IRES_UA 12500
#define FLASH_TIMEOUT_MAX_US 1280000
#define FLASH_TIMEOUT_STEP_US 10000
#define UA_PER_MA 1000
/* thermal threshold constants */
#define OTST_3CH_MIN_VAL 3
#define OTST1_4CH_MIN_VAL 0
#define OTST1_4CH_V0P1_MIN_VAL 3
#define OTST2_4CH_MIN_VAL 0
#define OTST1_MAX_CURRENT_MA 1000
#define OTST2_MAX_CURRENT_MA 500
#define OTST3_MAX_CURRENT_MA 200
enum hw_type {
QCOM_MVFLASH_3CH,
QCOM_MVFLASH_4CH,
};
enum led_mode {
FLASH_MODE,
TORCH_MODE,
};
enum led_strobe {
SW_STROBE,
HW_STROBE,
};
enum {
REG_STATUS1,
REG_STATUS2,
REG_STATUS3,
REG_CHAN_TIMER,
REG_ITARGET,
REG_MODULE_EN,
REG_IRESOLUTION,
REG_CHAN_STROBE,
REG_CHAN_EN,
REG_THERM_THRSH1,
REG_THERM_THRSH2,
REG_THERM_THRSH3,
REG_TORCH_CLAMP,
REG_MAX_COUNT,
};
static const struct reg_field mvflash_3ch_pmi8998_regs[REG_MAX_COUNT] = {
[REG_STATUS1] = REG_FIELD(0x08, 0, 5),
[REG_STATUS2] = REG_FIELD(0x09, 0, 7),
[REG_STATUS3] = REG_FIELD(0x0a, 0, 7),
[REG_CHAN_TIMER] = REG_FIELD_ID(0x40, 0, 7, 3, 1),
[REG_ITARGET] = REG_FIELD_ID(0x43, 0, 6, 3, 1),
[REG_MODULE_EN] = REG_FIELD(0x46, 7, 7),
[REG_IRESOLUTION] = REG_FIELD(0x47, 0, 5),
[REG_CHAN_STROBE] = REG_FIELD_ID(0x49, 0, 2, 3, 1),
[REG_CHAN_EN] = REG_FIELD(0x4c, 0, 2),
[REG_THERM_THRSH1] = REG_FIELD(0x56, 0, 2),
[REG_THERM_THRSH2] = REG_FIELD(0x57, 0, 2),
[REG_THERM_THRSH3] = REG_FIELD(0x58, 0, 2),
[REG_TORCH_CLAMP] = REG_FIELD(0xea, 0, 6),
};
static const struct reg_field mvflash_3ch_regs[REG_MAX_COUNT] = {
[REG_STATUS1] = REG_FIELD(0x08, 0, 7),
[REG_STATUS2] = REG_FIELD(0x09, 0, 7),
[REG_STATUS3] = REG_FIELD(0x0a, 0, 7),
[REG_CHAN_TIMER] = REG_FIELD_ID(0x40, 0, 7, 3, 1),
[REG_ITARGET] = REG_FIELD_ID(0x43, 0, 6, 3, 1),
[REG_MODULE_EN] = REG_FIELD(0x46, 7, 7),
[REG_IRESOLUTION] = REG_FIELD(0x47, 0, 5),
[REG_CHAN_STROBE] = REG_FIELD_ID(0x49, 0, 2, 3, 1),
[REG_CHAN_EN] = REG_FIELD(0x4c, 0, 2),
[REG_THERM_THRSH1] = REG_FIELD(0x56, 0, 2),
[REG_THERM_THRSH2] = REG_FIELD(0x57, 0, 2),
[REG_THERM_THRSH3] = REG_FIELD(0x58, 0, 2),
[REG_TORCH_CLAMP] = REG_FIELD(0xec, 0, 6),
};
static const struct reg_field mvflash_4ch_regs[REG_MAX_COUNT] = {
[REG_STATUS1] = REG_FIELD(0x06, 0, 7),
[REG_STATUS2] = REG_FIELD(0x07, 0, 6),
[REG_STATUS3] = REG_FIELD(0x09, 0, 7),
[REG_CHAN_TIMER] = REG_FIELD_ID(0x3e, 0, 7, 4, 1),
[REG_ITARGET]<