// SPDX-License-Identifier: GPL-2.0-only

#include <dt-bindings/leds/rt4831-backlight.h>
#include <linux/backlight.h>
#include <linux/bitops.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/regmap.h>

#define RT4831_REG_BLCFG	0x02
#define RT4831_REG_BLDIML	0x04
#define RT4831_REG_ENABLE	0x08
#define RT4831_REG_BLOPT2	0x11

#define RT4831_BLMAX_BRIGHTNESS	2048

#define RT4831_BLOVP_MASK	GENMASK(7, 5)
#define RT4831_BLOVP_SHIFT	5
#define RT4831_BLPWMEN_MASK	BIT(0)
#define RT4831_BLEN_MASK	BIT(4)
#define RT4831_BLCH_MASK	GENMASK(3, 0)
#define RT4831_BLDIML_MASK	GENMASK(2, 0)
#define RT4831_BLDIMH_MASK	GENMASK(10, 3)
#define RT4831_BLDIMH_SHIFT	3
#define RT4831_BLOCP_MASK	GENMASK(1, 0)

#define RT4831_BLOCP_MINUA	900000
#define RT4831_BLOCP_MAXUA	1800000
#define RT4831_BLOCP_STEPUA	300000

struct rt4831_priv {
	struct device *dev;
	struct regmap *regmap;
	struct backlight_device *bl;
};

static int rt4831_bl_update_status(struct backlight_device *bl_dev)
{
	struct rt4831_priv *priv = bl_get_data(bl_dev);
	int brightness = backlight_get_brightness(bl_dev);
	unsigned int enable = brightness ? RT4831_BLEN_MASK : 0;
	u8 v[2];
	int ret;

	if (brightness) {
		v[0] = (brightness - 1) & RT4831_BLDIML_MASK;
		v[1] = ((brightness - 1) & RT4831_BLDIMH_MASK) >> RT4831_BLDIMH_SHIFT;

		ret = regmap_raw_write(priv->regmap, RT4831_REG_BLDIML, v, sizeof(v));
		if (ret)
			return ret;
	}

	return regmap_update_bits(priv->regmap, RT4831_REG_ENABLE, RT4831_BLEN_MASK, enable);

}

static int rt4831_bl_get_brightness(struct backlight_device *bl_dev)
{
	struct rt4831_priv *priv = bl_get_data(bl_dev);
	unsigned int val;
	u8 v[2];
	int ret;

	ret = regmap_read(priv->regmap, RT4831_REG_ENABLE, &val);
	if (ret)
		return ret;

	if (!(val & RT4831_BLEN_MASK))
		return 0;

	ret = regmap_raw_read(priv->regmap, RT4831_REG_BLDIML, v, sizeof(v));
	if (ret)
		return ret;

	ret = (v[1] << RT4831_BLDIMH_SHIFT) + (v[0] & RT4831_BLDIML_MASK) + 1;

	return ret;
}

static const struct backlight_ops rt4831_bl_ops = {
	.options = BL_CORE_SUSPENDRESUME,
	.update_status = rt4831_bl_update_status,
	.get_brightness = rt4831_bl_get_brightness,
};

static int rt4831_parse_backlight_properties(struct rt4831_priv *priv,
					     struct backlight_properties *bl_props)
{
	struct device *dev = priv->dev;
	u8 propval;
	u32 brightness, ocp_uA;
	unsigned int val = 0;
	int ret;

	/* common properties */
	ret = device_property_read_u32(dev, "max-brightness", &brightness);
	if (ret)
		brightness = RT4831_BLMAX_BRIGHTNESS;

	bl_props->max_brightness = min_t(u32, brightness, RT4831_BLMAX_BRIGHTNESS);

	ret = device_property_read_u32(dev, "default-brightness", &brightness);
	if (ret)
		brightness = bl_props->max_brightness;

	bl_props->brightness = min_t(u32, brightness, bl_props->max_brightness);

	/* vendor properties */
	if (device_property_read_bool(dev, "richtek,pwm-enable"))
		val = RT4831_BLPWMEN_MASK;

	ret = regmap_update_bits(priv->regmap, RT4831_REG_BLCFG, RT4831_BLPWMEN_MASK, val);
	if (ret)
		return ret;

	ret = device_property_read_u8(dev, "richtek,bled-ovp-sel", &propval);
	if (ret)
		propval = RT4831_BLOVPLVL_21V;

	propval = min_t(u8, propval, RT4831_BLOVPLVL_29V);
	ret = regmap_update_bits(priv->regmap, RT4831_REG_BLCFG, RT4831_BLOVP_MASK,
				 propval << RT4831_BLOVP_SHIFT);
	if (ret)
		return ret;

	/*
	 * This OCP level is used to protect and limit the inductor current.
	 * If inductor peak current reach the level, low-side MOSFET will be
	 * turned off. Meanwhile, the output channel current may be limited.
	 * To match the configured channel current, the inductor chosen must
	 * be higher than the OCP level.
	 *
	 * Not like the OVP level, the default 21V can be used in the most
	 * application. But if the chosen OCP level is smaller than needed,
	 * it will also affect the backlight channel output current to be
	 * smaller than the register setting.
	 */
	ret = device_property_read_u32(dev, "richtek,bled-ocp-microamp",
				       &ocp_uA);
	if (!ret) {
		ocp_uA = clamp_val(ocp_uA, RT4831_BLOCP_MINUA,
				   RT4831_BLOCP_MAXUA);
		val = DIV_ROUND_UP(ocp_uA - RT4831_BLOCP_MINUA,
				   RT4831_BLOCP_STEPUA);
		ret = regmap_update_bits(priv->regmap, RT4831_REG_BLOPT2,
					 RT4831_BLOCP_MASK, val);
		if (ret)
			return ret;
	}

	ret = device_property_read_u8(dev, "richtek,channel-use", &propval);
	if (ret) {
		dev_err(dev, "richtek,channel-use DT property missing\n");
		return ret;
	}

	if (!(propval & RT4831_BLCH_MASK)) {
		dev_err(dev, "No channel specified\n");
		return -EINVAL;
	}

	return regmap_update_bits(priv->regmap, RT4831_REG_ENABLE, RT4831_BLCH_MASK, propval);
}

static int rt4831_bl_probe(struct platform_device *pdev)
{
	struct rt4831_priv *priv;
	struct backlight_properties bl_props = { .type = BACKLIGHT_RAW,
						 .scale = BACKLIGHT_SCALE_LINEAR };
	int ret;

	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
	if (!priv)
		return -ENOMEM;

	priv->dev = &pdev->dev;

	priv->regmap = dev_get_regmap(pdev->dev.parent, NULL);
	if (!priv->regmap) {
		dev_err(&pdev->dev, "Failed to init regmap\n");
		return -ENODEV;
	}

	ret = rt4831_parse_backlight_properties(priv, &bl_props);
	if (ret) {
		dev_err(&pdev->dev, "Failed to parse backlight properties\n");
		return ret;
	}

	priv->bl = devm_backlight_device_register(&pdev->dev, pdev->name, &pdev->dev, priv,
						  &rt4831_bl_ops, &bl_props);
	if (IS_ERR(priv->bl)) {
		dev_err(&pdev->dev, "Failed to register backlight\n");
		return PTR_ERR(priv->bl);
	}

	backlight_update_status(priv->bl);
	platform_set_drvdata(pdev, priv);

	return 0;
}

static int rt4831_bl_remove(struct platform_device *pdev)
{
	struct rt4831_priv *priv = platform_get_drvdata(pdev);
	struct backlight_device *bl_dev = priv->bl;

	bl_dev->props.brightness = 0;
	backlight_update_status(priv->bl);

	return 0;
}

static const struct of_device_id __maybe_unused rt4831_bl_of_match[] = {
	{ .compatible = "richtek,rt4831-backlight", },
	{}
};
MODULE_DEVICE_TABLE(of, rt4831_bl_of_match);

static struct platform_driver rt4831_bl_driver = {
	.driver = {
		.name = "rt4831-backlight",
		.of_match_table = rt4831_bl_of_match,
	},
	.probe = rt4831_bl_probe,
	.remove = rt4831_bl_remove,
};
module_platform_driver(rt4831_bl_driver);

MODULE_AUTHOR("ChiYuan Huang <cy_huang@richtek.com>");
MODULE_LICENSE("GPL v2");
