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

#include <linux/bitfield.h>
#include <linux/cleanup.h>
#include <linux/dev_printk.h>
#include <linux/string.h>
#include <linux/string_choices.h>
#include <linux/types.h>

#include "core.h"
#include "out.h"

/**
 * zl3073x_out_state_fetch - fetch output state from hardware
 * @zldev: pointer to zl3073x_dev structure
 * @index: output index to fetch state for
 *
 * Function fetches state of the given output from hardware and stores it
 * for later use.
 *
 * Return: 0 on success, <0 on error
 */
int zl3073x_out_state_fetch(struct zl3073x_dev *zldev, u8 index)
{
	struct zl3073x_out *out = &zldev->out[index];
	int rc;

	/* Read output configuration */
	rc = zl3073x_read_u8(zldev, ZL_REG_OUTPUT_CTRL(index), &out->ctrl);
	if (rc)
		return rc;

	dev_dbg(zldev->dev, "OUT%u is %s and connected to SYNTH%u\n", index,
		str_enabled_disabled(zl3073x_out_is_enabled(out)),
		zl3073x_out_synth_get(out));

	guard(mutex)(&zldev->multiop_lock);

	/* Read output configuration */
	rc = zl3073x_mb_op(zldev, ZL_REG_OUTPUT_MB_SEM, ZL_OUTPUT_MB_SEM_RD,
			   ZL_REG_OUTPUT_MB_MASK, BIT(index));
	if (rc)
		return rc;

	/* Read output mode */
	rc = zl3073x_read_u8(zldev, ZL_REG_OUTPUT_MODE, &out->mode);
	if (rc)
		return rc;

	dev_dbg(zldev->dev, "OUT%u has signal format 0x%02x\n", index,
		zl3073x_out_signal_format_get(out));

	/* Read output divisor */
	rc = zl3073x_read_u32(zldev, ZL_REG_OUTPUT_DIV, &out->div);
	if (rc)
		return rc;

	if (!out->div) {
		dev_err(zldev->dev, "Zero divisor for OUT%u got from device\n",
			index);
		return -EINVAL;
	}

	dev_dbg(zldev->dev, "OUT%u divisor: %u\n", index, out->div);

	/* Read output width */
	rc = zl3073x_read_u32(zldev, ZL_REG_OUTPUT_WIDTH, &out->width);
	if (rc)
		return rc;

	rc = zl3073x_read_u32(zldev, ZL_REG_OUTPUT_ESYNC_PERIOD,
			      &out->esync_n_period);
	if (rc)
		return rc;

	if (!out->esync_n_period) {
		dev_err(zldev->dev,
			"Zero esync divisor for OUT%u got from device\n",
			index);
		return -EINVAL;
	}

	rc = zl3073x_read_u32(zldev, ZL_REG_OUTPUT_ESYNC_WIDTH,
			      &out->esync_n_width);
	if (rc)
		return rc;

	rc = zl3073x_read_u32(zldev, ZL_REG_OUTPUT_PHASE_COMP,
			      &out->phase_comp);
	if (rc)
		return rc;

	return rc;
}

/**
 * zl3073x_out_state_get - get current output state
 * @zldev: pointer to zl3073x_dev structure
 * @index: output index to get state for
 *
 * Return: pointer to given output state
 */
const struct zl3073x_out *zl3073x_out_state_get(struct zl3073x_dev *zldev,
						u8 index)
{
	return &zldev->out[index];
}

/**
 * zl3073x_out_state_set - commit output state changes to hardware
 * @zldev: pointer to zl3073x_dev structure
 * @index: output index to set state for
 * @out: desired output state
 *
 * Validates that invariant fields have not been modified, skips the HW
 * write if the mutable configuration is unchanged, and otherwise writes
 * only the changed cfg fields to hardware via the mailbox interface.
 *
 * Return: 0 on success, -EINVAL if invariants changed, <0 on HW error
 */
int zl3073x_out_state_set(struct zl3073x_dev *zldev, u8 index,
			  const struct zl3073x_out *out)
{
	struct zl3073x_out *dout = &zldev->out[index];
	int rc;

	/* Reject attempts to change invariant fields (set at fetch only) */
	if (WARN_ON(memcmp(&dout->inv, &out->inv, sizeof(out->inv))))
		return -EINVAL;

	/* Skip HW write if configuration hasn't changed */
	if (!memcmp(&dout->cfg, &out->cfg, sizeof(out->cfg)))
		return 0;

	guard(mutex)(&zldev->multiop_lock);

	/* Read output configuration into mailbox */
	rc = zl3073x_mb_op(zldev, ZL_REG_OUTPUT_MB_SEM, ZL_OUTPUT_MB_SEM_RD,
			   ZL_REG_OUTPUT_MB_MASK, BIT(index));
	if (rc)
		return rc;

	/* Update mailbox with changed values */
	if (dout->div != out->div)
		rc = zl3073x_write_u32(zldev, ZL_REG_OUTPUT_DIV, out->div);
	if (!rc && dout->width != out->width)
		rc = zl3073x_write_u32(zldev, ZL_REG_OUTPUT_WIDTH, out->width);
	if (!rc && dout->esync_n_period != out->esync_n_period)
		rc = zl3073x_write_u32(zldev, ZL_REG_OUTPUT_ESYNC_PERIOD,
				       out->esync_n_period);
	if (!rc && dout->esync_n_width != out->esync_n_width)
		rc = zl3073x_write_u32(zldev, ZL_REG_OUTPUT_ESYNC_WIDTH,
				       out->esync_n_width);
	if (!rc && dout->mode != out->mode)
		rc = zl3073x_write_u8(zldev, ZL_REG_OUTPUT_MODE, out->mode);
	if (!rc && dout->phase_comp != out->phase_comp)
		rc = zl3073x_write_u32(zldev, ZL_REG_OUTPUT_PHASE_COMP,
				       out->phase_comp);
	if (rc)
		return rc;

	/* Commit output configuration */
	rc = zl3073x_mb_op(zldev, ZL_REG_OUTPUT_MB_SEM, ZL_OUTPUT_MB_SEM_WR,
			   ZL_REG_OUTPUT_MB_MASK, BIT(index));
	if (rc)
		return rc;

	/* After successful commit store new state */
	dout->cfg = out->cfg;

	return 0;
}
