#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/ktime.h>
#include <linux/kernel.h>
#include <linux/backlight.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#define WLED_MAX_STRINGS …
#define MOD_A …
#define MOD_B …
#define WLED_DEFAULT_BRIGHTNESS …
#define WLED_SOFT_START_DLY_US …
#define WLED3_SINK_REG_BRIGHT_MAX …
#define WLED5_SINK_REG_BRIGHT_MAX_12B …
#define WLED5_SINK_REG_BRIGHT_MAX_15B …
#define WLED3_CTRL_REG_FAULT_STATUS …
#define WLED3_CTRL_REG_ILIM_FAULT_BIT …
#define WLED3_CTRL_REG_OVP_FAULT_BIT …
#define WLED4_CTRL_REG_SC_FAULT_BIT …
#define WLED5_CTRL_REG_OVP_PRE_ALARM_BIT …
#define WLED3_CTRL_REG_INT_RT_STS …
#define WLED3_CTRL_REG_OVP_FAULT_STATUS …
#define WLED3_CTRL_REG_MOD_EN …
#define WLED3_CTRL_REG_MOD_EN_MASK …
#define WLED3_CTRL_REG_MOD_EN_SHIFT …
#define WLED3_CTRL_REG_FEEDBACK_CONTROL …
#define WLED3_CTRL_REG_FREQ …
#define WLED3_CTRL_REG_FREQ_MASK …
#define WLED3_CTRL_REG_OVP …
#define WLED3_CTRL_REG_OVP_MASK …
#define WLED5_CTRL_REG_OVP_MASK …
#define WLED3_CTRL_REG_ILIMIT …
#define WLED3_CTRL_REG_ILIMIT_MASK …
#define WLED3_SINK_REG_SYNC …
#define WLED3_SINK_REG_SYNC_CLEAR …
#define WLED3_SINK_REG_CURR_SINK …
#define WLED3_SINK_REG_CURR_SINK_MASK …
#define WLED3_SINK_REG_CURR_SINK_SHFT …
#define WLED3_SINK_REG_BRIGHT(n) …
#define WLED3_SINK_REG_STR_MOD_EN(n) …
#define WLED3_SINK_REG_STR_MOD_MASK …
#define WLED3_SINK_REG_STR_FULL_SCALE_CURR(n) …
#define WLED3_SINK_REG_STR_FULL_SCALE_CURR_MASK …
#define WLED3_SINK_REG_STR_MOD_SRC(n) …
#define WLED3_SINK_REG_STR_MOD_SRC_MASK …
#define WLED3_SINK_REG_STR_MOD_SRC_INT …
#define WLED3_SINK_REG_STR_MOD_SRC_EXT …
#define WLED3_SINK_REG_STR_CABC(n) …
#define WLED3_SINK_REG_STR_CABC_MASK …
#define WLED4_CTRL_REG_SHORT_PROTECT …
#define WLED4_CTRL_REG_SHORT_EN_MASK …
#define WLED4_CTRL_REG_SEC_ACCESS …
#define WLED4_CTRL_REG_SEC_UNLOCK …
#define WLED4_CTRL_REG_TEST1 …
#define WLED4_CTRL_REG_TEST1_EXT_FET_DTEST2 …
#define WLED4_SINK_REG_CURR_SINK …
#define WLED4_SINK_REG_CURR_SINK_MASK …
#define WLED4_SINK_REG_CURR_SINK_SHFT …
#define WLED4_SINK_REG_STR_MOD_EN(n) …
#define WLED4_SINK_REG_STR_MOD_MASK …
#define WLED4_SINK_REG_STR_FULL_SCALE_CURR(n) …
#define WLED4_SINK_REG_STR_FULL_SCALE_CURR_MASK …
#define WLED4_SINK_REG_STR_MOD_SRC(n) …
#define WLED4_SINK_REG_STR_MOD_SRC_MASK …
#define WLED4_SINK_REG_STR_MOD_SRC_INT …
#define WLED4_SINK_REG_STR_MOD_SRC_EXT …
#define WLED4_SINK_REG_STR_CABC(n) …
#define WLED4_SINK_REG_STR_CABC_MASK …
#define WLED4_SINK_REG_BRIGHT(n) …
#define WLED5_CTRL_REG_OVP_INT_CTL …
#define WLED5_CTRL_REG_OVP_INT_TIMER_MASK …
#define WLED5_SINK_REG_MOD_A_EN …
#define WLED5_SINK_REG_MOD_B_EN …
#define WLED5_SINK_REG_MOD_EN_MASK …
#define WLED5_SINK_REG_MOD_A_SRC_SEL …
#define WLED5_SINK_REG_MOD_B_SRC_SEL …
#define WLED5_SINK_REG_MOD_SRC_SEL_HIGH …
#define WLED5_SINK_REG_MOD_SRC_SEL_EXT …
#define WLED5_SINK_REG_MOD_SRC_SEL_MASK …
#define WLED5_SINK_REG_MOD_A_BRIGHTNESS_WIDTH_SEL …
#define WLED5_SINK_REG_MOD_B_BRIGHTNESS_WIDTH_SEL …
#define WLED5_SINK_REG_BRIGHTNESS_WIDTH_12B …
#define WLED5_SINK_REG_BRIGHTNESS_WIDTH_15B …
#define WLED5_SINK_REG_MOD_A_BRIGHTNESS_LSB …
#define WLED5_SINK_REG_MOD_A_BRIGHTNESS_MSB …
#define WLED5_SINK_REG_MOD_B_BRIGHTNESS_LSB …
#define WLED5_SINK_REG_MOD_B_BRIGHTNESS_MSB …
#define WLED5_SINK_REG_MOD_SYNC_BIT …
#define WLED5_SINK_REG_SYNC_MOD_A_BIT …
#define WLED5_SINK_REG_SYNC_MOD_B_BIT …
#define WLED5_SINK_REG_SYNC_MASK …
#define WLED5_SINK_REG_STR_FULL_SCALE_CURR(n) …
#define WLED5_SINK_REG_STR_SRC_SEL(n) …
#define WLED5_SINK_REG_SRC_SEL_MOD_A …
#define WLED5_SINK_REG_SRC_SEL_MOD_B …
#define WLED5_SINK_REG_SRC_SEL_MASK …
struct wled_var_cfg { … };
struct wled_u32_opts { … };
struct wled_bool_opts { … };
struct wled_config { … };
struct wled { … };
static int wled3_set_brightness(struct wled *wled, u16 brightness)
{ … }
static int wled4_set_brightness(struct wled *wled, u16 brightness)
{ … }
static int wled5_set_brightness(struct wled *wled, u16 brightness)
{ … }
static void wled_ovp_work(struct work_struct *work)
{ … }
static int wled_module_enable(struct wled *wled, int val)
{ … }
static int wled3_sync_toggle(struct wled *wled)
{ … }
static int wled5_mod_sync_toggle(struct wled *wled)
{ … }
static int wled_ovp_fault_status(struct wled *wled, bool *fault_set)
{ … }
static int wled4_ovp_delay(struct wled *wled)
{ … }
static int wled5_ovp_delay(struct wled *wled)
{ … }
static int wled_update_status(struct backlight_device *bl)
{ … }
static int wled4_cabc_config(struct wled *wled, bool enable)
{ … }
static int wled5_cabc_config(struct wled *wled, bool enable)
{ … }
#define WLED_SHORT_DLY_MS …
#define WLED_SHORT_CNT_MAX …
#define WLED_SHORT_RESET_CNT_DLY_US …
static irqreturn_t wled_short_irq_handler(int irq, void *_wled)
{ … }
#define AUTO_DETECT_BRIGHTNESS …
static void wled_auto_string_detection(struct wled *wled)
{ … }
#define WLED_AUTO_DETECT_OVP_COUNT …
#define WLED_AUTO_DETECT_CNT_DLY_US …
static bool wled4_auto_detection_required(struct wled *wled)
{ … }
static bool wled5_auto_detection_required(struct wled *wled)
{ … }
static int wled_auto_detection_at_init(struct wled *wled)
{ … }
static irqreturn_t wled_ovp_irq_handler(int irq, void *_wled)
{ … }
static int wled3_setup(struct wled *wled)
{ … }
static const struct wled_config wled3_config_defaults = …;
static int wled4_setup(struct wled *wled)
{ … }
static const struct wled_config wled4_config_defaults = …;
static int wled5_setup(struct wled *wled)
{ … }
static const struct wled_config wled5_config_defaults = …;
static const u32 wled3_boost_i_limit_values[] = …;
static const struct wled_var_cfg wled3_boost_i_limit_cfg = …;
static const u32 wled4_boost_i_limit_values[] = …;
static const struct wled_var_cfg wled4_boost_i_limit_cfg = …;
static inline u32 wled5_boost_i_limit_values_fn(u32 idx)
{ … }
static const struct wled_var_cfg wled5_boost_i_limit_cfg = …;
static const u32 wled3_ovp_values[] = …;
static const struct wled_var_cfg wled3_ovp_cfg = …;
static const u32 wled4_ovp_values[] = …;
static const struct wled_var_cfg wled4_ovp_cfg = …;
static inline u32 wled5_ovp_values_fn(u32 idx)
{ … }
static const struct wled_var_cfg wled5_ovp_cfg = …;
static u32 wled3_switch_freq_values_fn(u32 idx)
{ … }
static const struct wled_var_cfg wled3_switch_freq_cfg = …;
static const struct wled_var_cfg wled3_string_i_limit_cfg = …;
static const u32 wled4_string_i_limit_values[] = …;
static const struct wled_var_cfg wled4_string_i_limit_cfg = …;
static const struct wled_var_cfg wled5_mod_sel_cfg = …;
static const struct wled_var_cfg wled5_cabc_sel_cfg = …;
static u32 wled_values(const struct wled_var_cfg *cfg, u32 idx)
{ … }
static int wled_configure(struct wled *wled)
{ … }
static int wled_configure_short_irq(struct wled *wled,
struct platform_device *pdev)
{ … }
static int wled_configure_ovp_irq(struct wled *wled,
struct platform_device *pdev)
{ … }
static const struct backlight_ops wled_ops = …;
static int wled_probe(struct platform_device *pdev)
{
struct backlight_properties props;
struct backlight_device *bl;
struct wled *wled;
struct regmap *regmap;
u32 val;
int rc;
regmap = dev_get_regmap(pdev->dev.parent, NULL);
if (!regmap) {
dev_err(&pdev->dev, "Unable to get regmap\n");
return -EINVAL;
}
wled = devm_kzalloc(&pdev->dev, sizeof(*wled), GFP_KERNEL);
if (!wled)
return -ENOMEM;
wled->regmap = regmap;
wled->dev = &pdev->dev;
wled->version = (uintptr_t)of_device_get_match_data(&pdev->dev);
if (!wled->version) {
dev_err(&pdev->dev, "Unknown device version\n");
return -ENODEV;
}
mutex_init(&wled->lock);
rc = wled_configure(wled);
if (rc)
return rc;
val = WLED3_SINK_REG_BRIGHT_MAX;
of_property_read_u32(pdev->dev.of_node, "max-brightness", &val);
wled->max_brightness = val;
switch (wled->version) {
case 3:
wled->cfg.auto_detection_enabled = false;
rc = wled3_setup(wled);
if (rc) {
dev_err(&pdev->dev, "wled3_setup failed\n");
return rc;
}
break;
case 4:
wled->has_short_detect = true;
rc = wled4_setup(wled);
if (rc) {
dev_err(&pdev->dev, "wled4_setup failed\n");
return rc;
}
break;
case 5:
wled->has_short_detect = true;
if (wled->cfg.cabc_sel)
wled->max_brightness = WLED5_SINK_REG_BRIGHT_MAX_12B;
rc = wled5_setup(wled);
if (rc) {
dev_err(&pdev->dev, "wled5_setup failed\n");
return rc;
}
break;
default:
dev_err(wled->dev, "Invalid WLED version\n");
break;
}
INIT_DELAYED_WORK(&wled->ovp_work, wled_ovp_work);
rc = wled_configure_short_irq(wled, pdev);
if (rc < 0)
return rc;
rc = wled_configure_ovp_irq(wled, pdev);
if (rc < 0)
return rc;
val = WLED_DEFAULT_BRIGHTNESS;
of_property_read_u32(pdev->dev.of_node, "default-brightness", &val);
memset(&props, 0, sizeof(struct backlight_properties));
props.type = BACKLIGHT_RAW;
props.brightness = val;
props.max_brightness = wled->max_brightness;
bl = devm_backlight_device_register(&pdev->dev, wled->name,
&pdev->dev, wled,
&wled_ops, &props);
return PTR_ERR_OR_ZERO(bl);
};
static void wled_remove(struct platform_device *pdev)
{ … }
static const struct of_device_id wled_match_table[] = …;
MODULE_DEVICE_TABLE(of, wled_match_table);
static struct platform_driver wled_driver = …;
module_platform_driver(…) …;
MODULE_DESCRIPTION(…) …;
MODULE_LICENSE(…) …;