// SPDX-License-Identifier: GPL-2.0-only
/*
 * PWM-based multi-color LED control
 *
 * Copyright 2022 Sven Schwermer <sven.schwermer@disruptive-technologies.com>
 */

#include <linux/err.h>
#include <linux/kernel.h>
#include <linux/led-class-multicolor.h>
#include <linux/leds.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/pwm.h>

struct pwm_led {
	struct pwm_device *pwm;
	struct pwm_state state;
	bool active_low;
};

struct pwm_mc_led {
	struct led_classdev_mc mc_cdev;
	struct mutex lock;
	struct pwm_led leds[];
};

static int led_pwm_mc_set(struct led_classdev *cdev,
			  enum led_brightness brightness)
{
	struct led_classdev_mc *mc_cdev = lcdev_to_mccdev(cdev);
	struct pwm_mc_led *priv = container_of(mc_cdev, struct pwm_mc_led, mc_cdev);
	unsigned long long duty;
	int ret = 0;
	int i;

	led_mc_calc_color_components(mc_cdev, brightness);

	mutex_lock(&priv->lock);

	for (i = 0; i < mc_cdev->num_colors; i++) {
		duty = priv->leds[i].state.period;
		duty *= mc_cdev->subled_info[i].brightness;
		do_div(duty, cdev->max_brightness);

		if (priv->leds[i].active_low)
			duty = priv->leds[i].state.period - duty;

		priv->leds[i].state.duty_cycle = duty;
		priv->leds[i].state.enabled = duty > 0;
		ret = pwm_apply_might_sleep(priv->leds[i].pwm,
					    &priv->leds[i].state);
		if (ret)
			break;
	}

	mutex_unlock(&priv->lock);

	return ret;
}

static int iterate_subleds(struct device *dev, struct pwm_mc_led *priv,
			   struct fwnode_handle *mcnode)
{
	struct mc_subled *subled = priv->mc_cdev.subled_info;
	struct fwnode_handle *fwnode;
	struct pwm_led *pwmled;
	u32 color;
	int ret;

	/* iterate over the nodes inside the multi-led node */
	fwnode_for_each_child_node(mcnode, fwnode) {
		pwmled = &priv->leds[priv->mc_cdev.num_colors];
		pwmled->pwm = devm_fwnode_pwm_get(dev, fwnode, NULL);
		if (IS_ERR(pwmled->pwm)) {
			ret = dev_err_probe(dev, PTR_ERR(pwmled->pwm), "unable to request PWM\n");
			goto release_fwnode;
		}
		pwm_init_state(pwmled->pwm, &pwmled->state);
		pwmled->active_low = fwnode_property_read_bool(fwnode, "active-low");

		ret = fwnode_property_read_u32(fwnode, "color", &color);
		if (ret) {
			dev_err(dev, "cannot read color: %d\n", ret);
			goto release_fwnode;
		}

		subled[priv->mc_cdev.num_colors].color_index = color;
		priv->mc_cdev.num_colors++;
	}

	return 0;

release_fwnode:
	fwnode_handle_put(fwnode);
	return ret;
}

static int led_pwm_mc_probe(struct platform_device *pdev)
{
	struct fwnode_handle *mcnode, *fwnode;
	struct led_init_data init_data = {};
	struct led_classdev *cdev;
	struct mc_subled *subled;
	struct pwm_mc_led *priv;
	int count = 0;
	int ret = 0;

	mcnode = device_get_named_child_node(&pdev->dev, "multi-led");
	if (!mcnode)
		return dev_err_probe(&pdev->dev, -ENODEV,
				     "expected multi-led node\n");

	/* count the nodes inside the multi-led node */
	fwnode_for_each_child_node(mcnode, fwnode)
		count++;

	priv = devm_kzalloc(&pdev->dev, struct_size(priv, leds, count),
			    GFP_KERNEL);
	if (!priv) {
		ret = -ENOMEM;
		goto release_mcnode;
	}
	mutex_init(&priv->lock);

	subled = devm_kcalloc(&pdev->dev, count, sizeof(*subled), GFP_KERNEL);
	if (!subled) {
		ret = -ENOMEM;
		goto release_mcnode;
	}
	priv->mc_cdev.subled_info = subled;

	/* init the multicolor's LED class device */
	cdev = &priv->mc_cdev.led_cdev;
	fwnode_property_read_u32(mcnode, "max-brightness",
				 &cdev->max_brightness);
	cdev->flags = LED_CORE_SUSPENDRESUME;
	cdev->brightness_set_blocking = led_pwm_mc_set;

	ret = iterate_subleds(&pdev->dev, priv, mcnode);
	if (ret)
		goto release_mcnode;

	init_data.fwnode = mcnode;
	ret = devm_led_classdev_multicolor_register_ext(&pdev->dev,
							&priv->mc_cdev,
							&init_data);
	if (ret) {
		dev_err(&pdev->dev,
			"failed to register multicolor PWM led for %s: %d\n",
			cdev->name, ret);
		goto release_mcnode;
	}

	ret = led_pwm_mc_set(cdev, cdev->brightness);
	if (ret)
		return dev_err_probe(&pdev->dev, ret,
				     "failed to set led PWM value for %s\n",
				     cdev->name);

	platform_set_drvdata(pdev, priv);
	return 0;

release_mcnode:
	fwnode_handle_put(mcnode);
	return ret;
}

static const struct of_device_id of_pwm_leds_mc_match[] = {
	{ .compatible = "pwm-leds-multicolor", },
	{}
};
MODULE_DEVICE_TABLE(of, of_pwm_leds_mc_match);

static struct platform_driver led_pwm_mc_driver = {
	.probe		= led_pwm_mc_probe,
	.driver		= {
		.name	= "leds_pwm_multicolor",
		.of_match_table = of_pwm_leds_mc_match,
	},
};
module_platform_driver(led_pwm_mc_driver);

MODULE_AUTHOR("Sven Schwermer <sven.schwermer@disruptive-technologies.com>");
MODULE_DESCRIPTION("multi-color PWM LED driver");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:leds-pwm-multicolor");
