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

#include <device/mmio.h>
#include <console/console.h>
#include <edid.h>
#include <timer.h>
#include <types.h>
#include <soc/display/edp_aux.h>
#include <soc/display/edp_reg.h>

#define AUX_CMD_FIFO_LEN		144
#define AUX_CMD_NATIVE_MAX		16
#define AUX_CMD_I2C_MAX			128
#define AUX_INTR_I2C_DONE		BIT(0)
#define AUX_INTR_WRONG_ADDR		BIT(1)
#define AUX_INTR_CONSECUTIVE_TIMEOUT	BIT(2)
#define AUX_INTR_CONSECUTIVE_NACK_DEFER	BIT(3)
#define AUX_INTR_WRONG_RD_DATA_CNT	BIT(4)
#define AUX_INTR_NACK_I2C		BIT(5)
#define AUX_INTR_DEFER_I2C		BIT(6)
#define AUX_INTR_DPPHY_AUX_ERR		BIT(7)
#define EDP_AUX_INTERRUPT		(AUX_INTR_I2C_DONE | AUX_INTR_WRONG_ADDR | \
					AUX_INTR_CONSECUTIVE_TIMEOUT | \
					AUX_INTR_CONSECUTIVE_NACK_DEFER | \
					AUX_INTR_WRONG_RD_DATA_CNT | AUX_INTR_DEFER_I2C | \
					AUX_INTR_NACK_I2C | AUX_INTR_DPPHY_AUX_ERR)

static void edp_wait_for_aux_done(void)
{
	u32 intr_status = 0;

	if (!wait_ms(100, read32(&edp_auxclk->status) & EDP_AUX_INTERRUPT)) {
		printk(BIOS_ERR, "AUX SEND not acknowledged\n");
		return;
	}

	intr_status = read32(&edp_auxclk->status);
	if (!(intr_status & AUX_INTR_I2C_DONE)) {
		printk(BIOS_ERR, "AUX command failed, status = %#x\n", intr_status);
		return;
	}

	write32(&edp_ahbclk->interrupt_status, 0x0);
}

static int edp_msg_fifo_tx(unsigned int address, u8 request, void *buffer, size_t size)
{
	u32 data[4];
	u32 reg, len;
	bool native = (request == DP_AUX_NATIVE_WRITE) || (request == DP_AUX_NATIVE_READ);
	bool read = (request == DP_AUX_I2C_READ) || (request == DP_AUX_NATIVE_READ);
	u8 *msgdata = buffer;
	int i;

	if (read)
		len = 4;
	else
		len = size + 4;

	/*
	 * cmd fifo only has depth of 144 bytes
	 */
	if (len > AUX_CMD_FIFO_LEN)
		return -1;

	/* Pack cmd and write to HW */
	data[0] = (address >> 16) & 0xf;	/* addr[19:16] */
	if (read)
		data[0] |=  AUX_CMD_READ;		/* R/W */

	data[1] = (address >> 8) & 0xff;	/* addr[15:8] */
	data[2] = address & 0xff;		/* addr[7:0] */
	data[3] = (size - 1) & 0xff;		/* len[7:0] */

	for (i = 0; i < len; i++) {
		reg = (i < 4) ? data[i] : msgdata[i - 4];
		reg = EDP_AUX_DATA_DATA(reg); /* index = 0, write */
		if (i == 0)
			reg |= EDP_AUX_DATA_INDEX_WRITE;
		write32(&edp_auxclk->aux_data, reg);
	}

	/* clear old aux transaction control */
	write32(&edp_auxclk->aux_trans_ctrl, 0);
	reg = RX_STOP_ERR | RX_DEC_ERR | RX_SYNC_ERR | RX_ALIGN_ERR | TX_REQ_ERR;
	write32(&edp_phy->aux_interrupt_clr, reg);
	write32(&edp_phy->aux_interrupt_clr, reg | GLOBE_REQ_CLR);
	write32(&edp_phy->aux_interrupt_clr, 0x0);

	reg = 0; /* Transaction number is always 1 */
	if (!native) /* i2c */
		reg |= EDP_AUX_TRANS_CTRL_I2C | EDP_AUX_TRANS_CTRL_NO_SEND_ADDR |
			EDP_AUX_TRANS_CTRL_NO_SEND_STOP;

	reg |= EDP_AUX_TRANS_CTRL_GO;
	write32(&edp_auxclk->aux_trans_ctrl, reg);
	edp_wait_for_aux_done();

	return 0;
}

static int edp_msg_fifo_rx(void *buffer, size_t size)
{
	u32 data;
	u8 *dp;
	int i;
	u32 len = size;

	clrbits32(&edp_auxclk->aux_trans_ctrl, EDP_AUX_TRANS_CTRL_GO);
	write32(&edp_auxclk->aux_data,
		EDP_AUX_DATA_INDEX_WRITE | EDP_AUX_DATA_READ); /* index = 0 */

	dp = buffer;

	/* discard first byte */
	data = read32(&edp_auxclk->aux_data);
	for (i = 0; i < len; i++) {
		data = read32(&edp_auxclk->aux_data);
		dp[i] = (u8)((data >> 8) & 0xff);
	}

	return 0;
}

ssize_t edp_aux_transfer(unsigned int address, u8 request, void *buffer, size_t size)
{
	ssize_t ret;
	bool native = (request == DP_AUX_NATIVE_WRITE) || (request == DP_AUX_NATIVE_READ);
	bool read = (request == DP_AUX_I2C_READ) || (request == DP_AUX_NATIVE_READ);

	/* Ignore address only message */
	if ((size == 0) || (buffer == NULL)) {
		printk(BIOS_ERR, "%s: invalid size or buffer\n", __func__);
		return size;
	}

	/* msg sanity check */
	if ((native && (size > AUX_CMD_NATIVE_MAX)) ||
		(size > AUX_CMD_I2C_MAX)) {
		printk(BIOS_ERR, "%s: invalid msg: size(%zu), request(%x)\n",
		       __func__, size, request);
		return -1;
	}

	ret = edp_msg_fifo_tx(address, request, buffer, size);
	if (ret < 0) {
		printk(BIOS_ERR, "edp aux transfer tx failed\n");
		return ret;
	}

	if (read) {
		ret = edp_msg_fifo_rx(buffer, size);
		if (ret < 0) {
			printk(BIOS_ERR, "edp aux transfer rx failed\n");
			return ret;
		}
	}

	/* Return requested size for success or retry */
	ret = size;

	return ret;
}

int edp_read_edid(struct edid *out)
{
	int err;
	u8 edid[EDID_LENGTH * 2];
	int edid_size = EDID_LENGTH;

	uint8_t reg_addr = 0;
	err = edp_aux_transfer(EDID_I2C_ADDR, DP_AUX_I2C_WRITE, &reg_addr, 1);
	if (err > 0)
		err = edp_aux_transfer(EDID_I2C_ADDR, DP_AUX_I2C_READ, edid, EDID_LENGTH);

	if (err < EDID_LENGTH) {
		printk(BIOS_ERR, "Failed to read EDID. :%d\n", err);
		return err;
	}

	if (edid[EDID_EXTENSION_FLAG]) {
		printk(BIOS_ERR, " read EDID ext block.\n");
		edid_size += EDID_LENGTH;
		reg_addr = EDID_LENGTH;
		err = edp_aux_transfer(EDID_I2C_ADDR, DP_AUX_I2C_WRITE, &reg_addr, 1);
		if (err > 0)
			err = edp_aux_transfer(EDID_I2C_ADDR, DP_AUX_I2C_READ,
					       &edid[EDID_LENGTH], EDID_LENGTH);

		if (err < EDID_LENGTH) {
			printk(BIOS_ERR, "Failed to read EDID ext block.\n");
			return err;
		}
	}

	if (decode_edid(edid, edid_size, out) != EDID_CONFORMANT) {
		printk(BIOS_ERR, "Failed to decode EDID.\n");
		return CB_ERR;
	}


	return CB_SUCCESS;
}

void edp_aux_ctrl(int enable)
{
	u32 data;
	data = read32(&edp_auxclk->aux_ctrl);

	if (!enable) {
		data &= ~EDP_AUX_CTRL_ENABLE;
		write32(&edp_auxclk->aux_ctrl, data);
		return;
	}

	data |= EDP_AUX_CTRL_RESET;
	write32(&edp_auxclk->aux_ctrl, data);

	data &= ~EDP_AUX_CTRL_RESET;
	write32(&edp_auxclk->aux_ctrl, data);

	write32(&edp_auxclk->timeout_count, 0xffff);
	write32(&edp_auxclk->aux_limits, 0xffff);

	data |= EDP_AUX_CTRL_ENABLE;
	write32(&edp_auxclk->aux_ctrl, data);
}
