/*
 * Copyright (c) 2021 Sky Hero SA
 * Copyright (c) 2018 Linaro Limited
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#define DT_DRV_COMPAT ti_tlc59108

/**
 * @file
 * @brief LED driver for the TLC59108 I2C LED driver
 */

#include <zephyr/drivers/i2c.h>
#include <zephyr/drivers/led.h>
#include <zephyr/sys/util.h>
#include <zephyr/kernel.h>
#include <zephyr/logging/log.h>

LOG_MODULE_REGISTER(tlc59108, CONFIG_LED_LOG_LEVEL);

/* TLC59108 max supported LED id */
#define TLC59108_MAX_LED 7

/* TLC59108 select registers determine the source that drives LED outputs */
#define TLC59108_LED_OFF         0x0     /* LED driver off */
#define TLC59108_LED_ON          0x1     /* LED driver on */
#define TLC59108_LED_PWM         0x2     /* Controlled through PWM */
#define TLC59108_LED_GRP_PWM     0x3     /* Controlled through PWM/GRPPWM */

/* TLC59108 control register */
#define TLC59108_MODE1           0x00
#define TLC59108_MODE2           0x01
#define TLC59108_PWM_BASE        0x02
#define TLC59108_GRPPWM          0x0A
#define TLC59108_GRPFREQ         0x0B
#define TLC59108_LEDOUT0         0x0C
#define TLC59108_LEDOUT1         0x0D

/* TLC59108 mode register 1 */
#define TLC59108_MODE1_OSC       0x10

/* TLC59108 mode register 2 */
#define TLC59108_MODE2_DMBLNK    0x20    /* Enable blinking */

#define TLC59108_MASK            0x03

#define TLC59108_MIN_PERIOD      41U
#define TLC59108_MAX_PERIOD      10730U

struct tlc59108_cfg {
	struct i2c_dt_spec i2c;
};

static int tlc59108_set_ledout(const struct device *dev, uint32_t led,
		uint8_t val)
{
	const struct tlc59108_cfg *config = dev->config;

	if (led < 4) {
		if (i2c_reg_update_byte_dt(&config->i2c, TLC59108_LEDOUT0,
					   TLC59108_MASK << (led << 1), val << (led << 1))) {
			LOG_ERR("LED reg 0x%x update failed", TLC59108_LEDOUT0);
			return -EIO;
		}
	} else {
		if (i2c_reg_update_byte_dt(&config->i2c, TLC59108_LEDOUT1,
					   TLC59108_MASK << ((led - 4) << 1),
					   val << ((led - 4) << 1))) {
			LOG_ERR("LED reg 0x%x update failed", TLC59108_LEDOUT1);
			return -EIO;
		}
	}

	return 0;
}

static int tlc59108_led_blink(const struct device *dev, uint32_t led,
		uint32_t delay_on, uint32_t delay_off)
{
	const struct tlc59108_cfg *config = dev->config;
	uint8_t gdc, gfrq;
	uint32_t period;

	period = delay_on + delay_off;

	if (led > TLC59108_MAX_LED) {
		return -EINVAL;
	}

	if (period < TLC59108_MIN_PERIOD || period > TLC59108_MAX_PERIOD) {
		return -EINVAL;
	}

	/*
	 * From manual:
	 * duty cycle = (GDC / 256) ->
	 *	(time_on / period) = (GDC / 256) ->
	 *		GDC = ((time_on * 256) / period)
	 */
	gdc = delay_on * 256U / period;
	if (i2c_reg_write_byte_dt(&config->i2c, TLC59108_GRPPWM, gdc)) {
		LOG_ERR("LED reg 0x%x write failed", TLC59108_GRPPWM);
		return -EIO;
	}

	/*
	 * From manual:
	 * period = ((GFRQ + 1) / 24) in seconds.
	 * So, period (in ms) = (((GFRQ + 1) / 24) * 1000) ->
	 *		GFRQ = ((period * 24 / 1000) - 1)
	 */
	gfrq = (period * 24U / 1000) - 1;
	if (i2c_reg_write_byte_dt(&config->i2c, TLC59108_GRPFREQ, gfrq)) {
		LOG_ERR("LED reg 0x%x write failed", TLC59108_GRPFREQ);
		return -EIO;
	}

	/* Enable blinking mode */
	if (i2c_reg_update_byte_dt(&config->i2c, TLC59108_MODE2, TLC59108_MODE2_DMBLNK,
				   TLC59108_MODE2_DMBLNK)) {
		LOG_ERR("LED reg 0x%x update failed", TLC59108_MODE2);
		return -EIO;
	}

	/* Select the GRPPWM source to drive the LED output */
	return tlc59108_set_ledout(dev, led, TLC59108_LED_GRP_PWM);
}

static int tlc59108_led_set_brightness(const struct device *dev, uint32_t led,
		uint8_t value)
{
	const struct tlc59108_cfg *config = dev->config;
	uint8_t val;

	if (led > TLC59108_MAX_LED) {
		return -EINVAL;
	}

	/* Set the LED brightness value */
	val = (value * 255U) / LED_BRIGHTNESS_MAX;
	if (i2c_reg_write_byte_dt(&config->i2c, TLC59108_PWM_BASE + led, val)) {
		LOG_ERR("LED 0x%x reg write failed", TLC59108_PWM_BASE + led);
		return -EIO;
	}

	/* Set the LED driver to be controlled through its PWMx register. */
	return tlc59108_set_ledout(dev, led, TLC59108_LED_PWM);
}

static inline int tlc59108_led_on(const struct device *dev, uint32_t led)
{
	if (led > TLC59108_MAX_LED) {
		return -EINVAL;
	}

	/* Set LED state to ON */
	return tlc59108_set_ledout(dev, led, TLC59108_LED_ON);
}

static inline int tlc59108_led_off(const struct device *dev, uint32_t led)
{
	if (led > TLC59108_MAX_LED) {
		return -EINVAL;
	}

	/* Set LED state to OFF */
	return tlc59108_set_ledout(dev, led, TLC59108_LED_OFF);
}

static int tlc59108_led_init(const struct device *dev)
{
	const struct tlc59108_cfg *config = dev->config;

	if (!device_is_ready(config->i2c.bus)) {
		LOG_ERR("I2C bus device %s is not ready", config->i2c.bus->name);
		return -ENODEV;
	}

	/* Wake up from sleep mode */
	if (i2c_reg_update_byte_dt(&config->i2c, TLC59108_MODE1, TLC59108_MODE1_OSC, 0)) {
		LOG_ERR("LED reg 0x%x update failed", TLC59108_MODE1);
		return -EIO;
	}

	return 0;
}

static DEVICE_API(led, tlc59108_led_api) = {
	.blink = tlc59108_led_blink,
	.set_brightness = tlc59108_led_set_brightness,
	.on = tlc59108_led_on,
	.off = tlc59108_led_off,
};

#define TLC59108_DEVICE(id) \
	static const struct tlc59108_cfg tlc59108_##id##_cfg = {	\
		.i2c = I2C_DT_SPEC_INST_GET(id),			\
	};								\
									\
	DEVICE_DT_INST_DEFINE(id, &tlc59108_led_init, NULL,		\
			NULL,						\
			&tlc59108_##id##_cfg, POST_KERNEL,		\
			CONFIG_LED_INIT_PRIORITY,			\
			&tlc59108_led_api);

DT_INST_FOREACH_STATUS_OKAY(TLC59108_DEVICE)
