linux/drivers/video/backlight/qcom-wled.c

// SPDX-License-Identifier: GPL-2.0-only
/* Copyright (c) 2015, Sony Mobile Communications, AB.
 */

#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>

/* From DT binding */
#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

/* WLED3/WLED4 control registers */
#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

/* WLED3/WLED4 sink registers */
#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

/* WLED3 specific per-'string' registers below */
#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

/* WLED4 specific control registers */
#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

/* WLED4 specific sink registers */
#define WLED4_SINK_REG_CURR_SINK
#define WLED4_SINK_REG_CURR_SINK_MASK
#define WLED4_SINK_REG_CURR_SINK_SHFT

/* WLED4 specific per-'string' registers below */
#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)

/* WLED5 specific control registers */
#define WLED5_CTRL_REG_OVP_INT_CTL
#define WLED5_CTRL_REG_OVP_INT_TIMER_MASK

/* WLED5 specific sink registers */
#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

/* WLED5 specific per-'string' registers below */
#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();