/*
 * Copyright © 2007 Dave Mueller
 *
 * 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 (including the next
 * paragraph) 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 AUTHORS OR COPYRIGHT HOLDERS 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 Mueller <dave.mueller@gmx.ch>
 *
 */

#include "dvo.h"

/* register definitions according to the TFP410 data sheet */
#define TFP410_VID		0x014C
#define TFP410_DID		0x0410

#define TFP410_VID_LO		0x00
#define TFP410_VID_HI		0x01
#define TFP410_DID_LO		0x02
#define TFP410_DID_HI		0x03
#define TFP410_REV		0x04

#define TFP410_CTL_1		0x08
#define TFP410_CTL_1_TDIS	(1<<6)
#define TFP410_CTL_1_VEN	(1<<5)
#define TFP410_CTL_1_HEN	(1<<4)
#define TFP410_CTL_1_DSEL	(1<<3)
#define TFP410_CTL_1_BSEL	(1<<2)
#define TFP410_CTL_1_EDGE	(1<<1)
#define TFP410_CTL_1_PD		(1<<0)

#define TFP410_CTL_2		0x09
#define TFP410_CTL_2_VLOW	(1<<7)
#define TFP410_CTL_2_MSEL_MASK	(0x7<<4)
#define TFP410_CTL_2_MSEL	(1<<4)
#define TFP410_CTL_2_TSEL	(1<<3)
#define TFP410_CTL_2_RSEN	(1<<2)
#define TFP410_CTL_2_HTPLG	(1<<1)
#define TFP410_CTL_2_MDI	(1<<0)

#define TFP410_CTL_3		0x0A
#define TFP410_CTL_3_DK_MASK 	(0x7<<5)
#define TFP410_CTL_3_DK		(1<<5)
#define TFP410_CTL_3_DKEN	(1<<4)
#define TFP410_CTL_3_CTL_MASK	(0x7<<1)
#define TFP410_CTL_3_CTL	(1<<1)

#define TFP410_USERCFG		0x0B

#define TFP410_DE_DLY		0x32

#define TFP410_DE_CTL		0x33
#define TFP410_DE_CTL_DEGEN	(1<<6)
#define TFP410_DE_CTL_VSPOL	(1<<5)
#define TFP410_DE_CTL_HSPOL	(1<<4)
#define TFP410_DE_CTL_DEDLY8	(1<<0)

#define TFP410_DE_TOP		0x34

#define TFP410_DE_CNT_LO	0x36
#define TFP410_DE_CNT_HI	0x37

#define TFP410_DE_LIN_LO	0x38
#define TFP410_DE_LIN_HI	0x39

#define TFP410_H_RES_LO		0x3A
#define TFP410_H_RES_HI		0x3B

#define TFP410_V_RES_LO		0x3C
#define TFP410_V_RES_HI		0x3D

struct tfp410_priv {
	bool quiet;
};

static bool tfp410_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch)
{
	struct tfp410_priv *tfp = dvo->dev_priv;
	struct i2c_adapter *adapter = dvo->i2c_bus;
	u8 out_buf[2];
	u8 in_buf[2];

	struct i2c_msg msgs[] = {
		{
			.addr = dvo->slave_addr,
			.flags = 0,
			.len = 1,
			.buf = out_buf,
		},
		{
			.addr = dvo->slave_addr,
			.flags = I2C_M_RD,
			.len = 1,
			.buf = in_buf,
		}
	};

	out_buf[0] = addr;
	out_buf[1] = 0;

	if (i2c_transfer(adapter, msgs, 2) == 2) {
		*ch = in_buf[0];
		return true;
	};

	if (!tfp->quiet) {
		DRM_DEBUG_KMS("Unable to read register 0x%02x from %s:%02x.\n",
			  addr, adapter->name, dvo->slave_addr);
	}
	return false;
}

static bool tfp410_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch)
{
	struct tfp410_priv *tfp = dvo->dev_priv;
	struct i2c_adapter *adapter = dvo->i2c_bus;
	uint8_t out_buf[2];
	struct i2c_msg msg = {
		.addr = dvo->slave_addr,
		.flags = 0,
		.len = 2,
		.buf = out_buf,
	};

	out_buf[0] = addr;
	out_buf[1] = ch;

	if (i2c_transfer(adapter, &msg, 1) == 1)
		return true;

	if (!tfp->quiet) {
		DRM_DEBUG_KMS("Unable to write register 0x%02x to %s:%d.\n",
			  addr, adapter->name, dvo->slave_addr);
	}

	return false;
}

static int tfp410_getid(struct intel_dvo_device *dvo, int addr)
{
	uint8_t ch1, ch2;

	if (tfp410_readb(dvo, addr+0, &ch1) &&
	    tfp410_readb(dvo, addr+1, &ch2))
		return ((ch2 << 8) & 0xFF00) | (ch1 & 0x00FF);

	return -1;
}

/* Ti TFP410 driver for chip on i2c bus */
static bool tfp410_init(struct intel_dvo_device *dvo,
			struct i2c_adapter *adapter)
{
	/* this will detect the tfp410 chip on the specified i2c bus */
	struct tfp410_priv *tfp;
	int id;

	tfp = kzalloc(sizeof(struct tfp410_priv), GFP_KERNEL);
	if (tfp == NULL)
		return false;

	dvo->i2c_bus = adapter;
	dvo->dev_priv = tfp;
	tfp->quiet = true;

	if ((id = tfp410_getid(dvo, TFP410_VID_LO)) != TFP410_VID) {
		DRM_DEBUG_KMS("tfp410 not detected got VID %X: from %s "
				"Slave %d.\n",
			  id, adapter->name, dvo->slave_addr);
		goto out;
	}

	if ((id = tfp410_getid(dvo, TFP410_DID_LO)) != TFP410_DID) {
		DRM_DEBUG_KMS("tfp410 not detected got DID %X: from %s "
				"Slave %d.\n",
			  id, adapter->name, dvo->slave_addr);
		goto out;
	}
	tfp->quiet = false;
	return true;
out:
	kfree(tfp);
	return false;
}

static enum drm_connector_status tfp410_detect(struct intel_dvo_device *dvo)
{
	enum drm_connector_status ret = connector_status_disconnected;
	uint8_t ctl2;

	if (tfp410_readb(dvo, TFP410_CTL_2, &ctl2)) {
		if (ctl2 & TFP410_CTL_2_RSEN)
			ret = connector_status_connected;
		else
			ret = connector_status_disconnected;
	}

	return ret;
}

static enum drm_mode_status tfp410_mode_valid(struct intel_dvo_device *dvo,
					      struct drm_display_mode *mode)
{
	return MODE_OK;
}

static void tfp410_mode_set(struct intel_dvo_device *dvo,
			    struct drm_display_mode *mode,
			    struct drm_display_mode *adjusted_mode)
{
    /* As long as the basics are set up, since we don't have clock dependencies
     * in the mode setup, we can just leave the registers alone and everything
     * will work fine.
     */
    /* don't do much */
    return;
}

/* set the tfp410 power state */
static void tfp410_dpms(struct intel_dvo_device *dvo, int mode)
{
	uint8_t ctl1;

	if (!tfp410_readb(dvo, TFP410_CTL_1, &ctl1))
		return;

	if (mode == DRM_MODE_DPMS_ON)
		ctl1 |= TFP410_CTL_1_PD;
	else
		ctl1 &= ~TFP410_CTL_1_PD;

	tfp410_writeb(dvo, TFP410_CTL_1, ctl1);
}

static void tfp410_dump_regs(struct intel_dvo_device *dvo)
{
	uint8_t val, val2;

	tfp410_readb(dvo, TFP410_REV, &val);
	DRM_LOG_KMS("TFP410_REV: 0x%02X\n", val);
	tfp410_readb(dvo, TFP410_CTL_1, &val);
	DRM_LOG_KMS("TFP410_CTL1: 0x%02X\n", val);
	tfp410_readb(dvo, TFP410_CTL_2, &val);
	DRM_LOG_KMS("TFP410_CTL2: 0x%02X\n", val);
	tfp410_readb(dvo, TFP410_CTL_3, &val);
	DRM_LOG_KMS("TFP410_CTL3: 0x%02X\n", val);
	tfp410_readb(dvo, TFP410_USERCFG, &val);
	DRM_LOG_KMS("TFP410_USERCFG: 0x%02X\n", val);
	tfp410_readb(dvo, TFP410_DE_DLY, &val);
	DRM_LOG_KMS("TFP410_DE_DLY: 0x%02X\n", val);
	tfp410_readb(dvo, TFP410_DE_CTL, &val);
	DRM_LOG_KMS("TFP410_DE_CTL: 0x%02X\n", val);
	tfp410_readb(dvo, TFP410_DE_TOP, &val);
	DRM_LOG_KMS("TFP410_DE_TOP: 0x%02X\n", val);
	tfp410_readb(dvo, TFP410_DE_CNT_LO, &val);
	tfp410_readb(dvo, TFP410_DE_CNT_HI, &val2);
	DRM_LOG_KMS("TFP410_DE_CNT: 0x%02X%02X\n", val2, val);
	tfp410_readb(dvo, TFP410_DE_LIN_LO, &val);
	tfp410_readb(dvo, TFP410_DE_LIN_HI, &val2);
	DRM_LOG_KMS("TFP410_DE_LIN: 0x%02X%02X\n", val2, val);
	tfp410_readb(dvo, TFP410_H_RES_LO, &val);
	tfp410_readb(dvo, TFP410_H_RES_HI, &val2);
	DRM_LOG_KMS("TFP410_H_RES: 0x%02X%02X\n", val2, val);
	tfp410_readb(dvo, TFP410_V_RES_LO, &val);
	tfp410_readb(dvo, TFP410_V_RES_HI, &val2);
	DRM_LOG_KMS("TFP410_V_RES: 0x%02X%02X\n", val2, val);
}

static void tfp410_destroy(struct intel_dvo_device *dvo)
{
	struct tfp410_priv *tfp = dvo->dev_priv;

	if (tfp) {
		kfree(tfp);
		dvo->dev_priv = NULL;
	}
}

struct intel_dvo_dev_ops tfp410_ops = {
	.init = tfp410_init,
	.detect = tfp410_detect,
	.mode_valid = tfp410_mode_valid,
	.mode_set = tfp410_mode_set,
	.dpms = tfp410_dpms,
	.dump_regs = tfp410_dump_regs,
	.destroy = tfp410_destroy,
};
