/*
 * Copyright (c) 2021 BrainCo Inc.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#define DT_DRV_COMPAT gd_gd32_dac

#include <errno.h>

#include <zephyr/drivers/clock_control.h>
#include <zephyr/drivers/clock_control/gd32.h>
#include <zephyr/drivers/pinctrl.h>
#include <zephyr/drivers/reset.h>
#include <zephyr/drivers/dac.h>

#include <gd32_dac.h>

#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(dac_gd32, CONFIG_DAC_LOG_LEVEL);

/**
 * GD32 DAC HAL use different DAC0 interface for 2 or 1 output channels SoCs.
 * Unify the DAC0 interface to DAC0_xx.
 */
#if DT_INST_PROP(0, num_channels) == 1
#define DAC_CTL_DEN0 DAC_CTL_DEN
#define DAC0_R8DH    DAC_R8DH
#define DAC0_R12DH   DAC_R12DH
#endif

struct dac_gd32_config {
	uint32_t reg;
	uint16_t clkid;
	struct reset_dt_spec reset;
	const struct pinctrl_dev_config *pcfg;
	uint32_t num_channels;
	uint32_t reset_val;
};

struct dac_gd32_data {
	uint8_t resolutions[2];
};

static void dac_gd32_enable(uint8_t dacx)
{
	switch (dacx) {
	case 0U:
		DAC_CTL |= DAC_CTL_DEN0;
		break;
#if DT_INST_PROP(0, num_channels) == 2
	case 1U:
		DAC_CTL |= DAC_CTL_DEN1;
		break;
#endif
	}
}

static void dac_gd32_disable(uint8_t dacx)
{
	switch (dacx) {
	case 0U:
		DAC_CTL &= ~DAC_CTL_DEN0;
		break;
#if DT_INST_PROP(0, num_channels) == 2
	case 1U:
		DAC_CTL &= ~DAC_CTL_DEN1;
		break;
#endif
	}
}

static void dac_gd32_write(struct dac_gd32_data *data,
			   uint8_t dacx, uint32_t value)
{
	switch (dacx) {
	case 0U:
		if (data->resolutions[dacx] == 8U) {
			DAC0_R8DH = value;
		} else {
			DAC0_R12DH = value;
		}
		break;
#if DT_INST_PROP(0, num_channels) == 2
	case 1U:
		if (data->resolutions[dacx] == 8U) {
			DAC1_R8DH = value;
		} else {
			DAC1_R12DH = value;
		}
		break;
#endif
	}
}

static int dac_gd32_channel_setup(const struct device *dev,
				  const struct dac_channel_cfg *channel_cfg)
{
	struct dac_gd32_data *data = dev->data;
	const struct dac_gd32_config *config = dev->config;
	uint8_t dacx = channel_cfg->channel_id;

	if (dacx >= config->num_channels) {
		return -ENOTSUP;
	}

	/* GD32 DAC only support 8 or 12 bits resolution */
	if ((channel_cfg->resolution != 8U) &&
	    (channel_cfg->resolution != 12U)) {
		LOG_ERR("Only 8 and 12 bits resolutions are supported!");
		return -ENOTSUP;
	}

	data->resolutions[dacx] = channel_cfg->resolution;

	dac_gd32_disable(dacx);
	dac_gd32_write(data, dacx, config->reset_val);
	dac_gd32_enable(dacx);

	return 0;
}

static int dac_gd32_write_value(const struct device *dev,
				uint8_t dacx, uint32_t value)
{
	struct dac_gd32_data *data = dev->data;
	const struct dac_gd32_config *config = dev->config;

	if (dacx >= config->num_channels) {
		return -ENOTSUP;
	}

	dac_gd32_write(data, dacx, value);

	return 0;
}

struct dac_driver_api dac_gd32_driver_api = {
	.channel_setup = dac_gd32_channel_setup,
	.write_value = dac_gd32_write_value
};

static int dac_gd32_init(const struct device *dev)
{
	const struct dac_gd32_config *cfg = dev->config;
	int ret;

	ret = pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_DEFAULT);
	if (ret < 0) {
		LOG_ERR("Failed to apply pinctrl state");
		return ret;
	}

	(void)clock_control_on(GD32_CLOCK_CONTROLLER,
			       (clock_control_subsys_t *)&cfg->clkid);

	(void)reset_line_toggle_dt(&cfg->reset);

	return 0;
}

PINCTRL_DT_INST_DEFINE(0);

static struct dac_gd32_data dac_gd32_data_0;

static const struct dac_gd32_config dac_gd32_cfg_0 = {
	.reg = DT_INST_REG_ADDR(0),
	.clkid = DT_INST_CLOCKS_CELL(0, id),
	.reset = RESET_DT_SPEC_INST_GET(0),
	.pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(0),
	.num_channels = DT_INST_PROP(0, num_channels),
	.reset_val = DT_INST_PROP(0, reset_val),
};

DEVICE_DT_INST_DEFINE(0, &dac_gd32_init, NULL, &dac_gd32_data_0,
		      &dac_gd32_cfg_0, POST_KERNEL, CONFIG_DAC_INIT_PRIORITY,
		      &dac_gd32_driver_api);
