/*
 * Copyright 2015 Red Hat Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 *
 * Authors: Dave Airlie
 */

#include <drm/radeon_drm.h>
#include "radeon.h"
#include "nid.h"

#define AUX_RX_ERROR_FLAGS (AUX_SW_RX_OVERFLOW |	     \
			    AUX_SW_RX_HPD_DISCON |	     \
			    AUX_SW_RX_PARTIAL_BYTE |	     \
			    AUX_SW_NON_AUX_MODE |	     \
			    AUX_SW_RX_SYNC_INVALID_L |	     \
			    AUX_SW_RX_SYNC_INVALID_H |	     \
			    AUX_SW_RX_INVALID_START |	     \
			    AUX_SW_RX_RECV_NO_DET |	     \
			    AUX_SW_RX_RECV_INVALID_H |	     \
			    AUX_SW_RX_RECV_INVALID_V)

#define AUX_SW_REPLY_GET_BYTE_COUNT(x) (((x) >> 24) & 0x1f)

#define BARE_ADDRESS_SIZE 3

static const u32 aux_offset[] =
{
	0x6200 - 0x6200,
	0x6250 - 0x6200,
	0x62a0 - 0x6200,
	0x6300 - 0x6200,
	0x6350 - 0x6200,
	0x63a0 - 0x6200,
};

ssize_t
radeon_dp_aux_transfer_native(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
{
	struct radeon_i2c_chan *chan =
		container_of(aux, struct radeon_i2c_chan, aux);
	struct drm_device *dev = chan->dev;
	struct radeon_device *rdev = dev->dev_private;
	int ret = 0, i;
	uint32_t tmp, ack = 0;
	int instance = chan->rec.i2c_id & 0xf;
	u8 byte;
	u8 *buf = msg->buffer;
	int retry_count = 0;
	int bytes;
	int msize;
	bool is_write = false;

	if (WARN_ON(msg->size > 16))
		return -E2BIG;

	switch (msg->request & ~DP_AUX_I2C_MOT) {
	case DP_AUX_NATIVE_WRITE:
	case DP_AUX_I2C_WRITE:
		is_write = true;
		break;
	case DP_AUX_NATIVE_READ:
	case DP_AUX_I2C_READ:
		break;
	default:
		return -EINVAL;
	}

	/* work out two sizes required */
	msize = 0;
	bytes = BARE_ADDRESS_SIZE;
	if (msg->size) {
		msize = msg->size - 1;
		bytes++;
		if (is_write)
			bytes += msg->size;
	}

	mutex_lock(&chan->mutex);

	/* switch the pad to aux mode */
	tmp = RREG32(chan->rec.mask_clk_reg);
	tmp |= (1 << 16);
	WREG32(chan->rec.mask_clk_reg, tmp);

	/* setup AUX control register with correct HPD pin */
	tmp = RREG32(AUX_CONTROL + aux_offset[instance]);

	tmp &= AUX_HPD_SEL(0x7);
	tmp |= AUX_HPD_SEL(chan->rec.hpd);
	tmp |= AUX_EN | AUX_LS_READ_EN;

	WREG32(AUX_CONTROL + aux_offset[instance], tmp);

	/* atombios appears to write this twice lets copy it */
	WREG32(AUX_SW_CONTROL + aux_offset[instance],
	       AUX_SW_WR_BYTES(bytes));
	WREG32(AUX_SW_CONTROL + aux_offset[instance],
	       AUX_SW_WR_BYTES(bytes));

	/* write the data header into the registers */
	/* request, address, msg size */
	byte = (msg->request << 4) | ((msg->address >> 16) & 0xf);
	WREG32(AUX_SW_DATA + aux_offset[instance],
	       AUX_SW_DATA_MASK(byte) | AUX_SW_AUTOINCREMENT_DISABLE);

	byte = (msg->address >> 8) & 0xff;
	WREG32(AUX_SW_DATA + aux_offset[instance],
	       AUX_SW_DATA_MASK(byte));

	byte = msg->address & 0xff;
	WREG32(AUX_SW_DATA + aux_offset[instance],
	       AUX_SW_DATA_MASK(byte));

	byte = msize;
	WREG32(AUX_SW_DATA + aux_offset[instance],
	       AUX_SW_DATA_MASK(byte));

	/* if we are writing - write the msg buffer */
	if (is_write) {
		for (i = 0; i < msg->size; i++) {
			WREG32(AUX_SW_DATA + aux_offset[instance],
			       AUX_SW_DATA_MASK(buf[i]));
		}
	}

	/* clear the ACK */
	WREG32(AUX_SW_INTERRUPT_CONTROL + aux_offset[instance], AUX_SW_DONE_ACK);

	/* write the size and GO bits */
	WREG32(AUX_SW_CONTROL + aux_offset[instance],
	       AUX_SW_WR_BYTES(bytes) | AUX_SW_GO);

	/* poll the status registers - TODO irq support */
	do {
		tmp = RREG32(AUX_SW_STATUS + aux_offset[instance]);
		if (tmp & AUX_SW_DONE) {
			break;
		}
		usleep_range(100, 200);
	} while (retry_count++ < 1000);

	if (retry_count >= 1000) {
		DRM_ERROR("auxch hw never signalled completion, error %08x\n", tmp);
		ret = -EIO;
		goto done;
	}

	if (tmp & AUX_SW_RX_TIMEOUT) {
		ret = -ETIMEDOUT;
		goto done;
	}
	if (tmp & AUX_RX_ERROR_FLAGS) {
		DRM_DEBUG_KMS_RATELIMITED("dp_aux_ch flags not zero: %08x\n",
					  tmp);
		ret = -EIO;
		goto done;
	}

	bytes = AUX_SW_REPLY_GET_BYTE_COUNT(tmp);
	if (bytes) {
		WREG32(AUX_SW_DATA + aux_offset[instance],
		       AUX_SW_DATA_RW | AUX_SW_AUTOINCREMENT_DISABLE);

		tmp = RREG32(AUX_SW_DATA + aux_offset[instance]);
		ack = (tmp >> 8) & 0xff;

		for (i = 0; i < bytes - 1; i++) {
			tmp = RREG32(AUX_SW_DATA + aux_offset[instance]);
			if (buf)
				buf[i] = (tmp >> 8) & 0xff;
		}
		if (buf)
			ret = bytes - 1;
	}

	WREG32(AUX_SW_INTERRUPT_CONTROL + aux_offset[instance], AUX_SW_DONE_ACK);

	if (is_write)
		ret = msg->size;
done:
	mutex_unlock(&chan->mutex);

	if (ret >= 0)
		msg->reply = ack >> 4;
	return ret;
}
