/*
 *  Driver for Microtune MT2131 "QAM/8VSB single chip tuner"
 *
 *  Copyright (c) 2006 Steven Toth <stoth@linuxtv.org>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include <linux/module.h>
#include <linux/delay.h>
#include <linux/dvb/frontend.h>
#include <linux/i2c.h>
#include <linux/slab.h>

#include "dvb_frontend.h"

#include "mt2131.h"
#include "mt2131_priv.h"

static int debug;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");

#define dprintk(level,fmt, arg...) if (debug >= level) \
	printk(KERN_INFO "%s: " fmt, "mt2131", ## arg)

static u8 mt2131_config1[] = {
	0x01,
	0x50, 0x00, 0x50, 0x80, 0x00, 0x49, 0xfa, 0x88,
	0x08, 0x77, 0x41, 0x04, 0x00, 0x00, 0x00, 0x32,
	0x7f, 0xda, 0x4c, 0x00, 0x10, 0xaa, 0x78, 0x80,
	0xff, 0x68, 0xa0, 0xff, 0xdd, 0x00, 0x00
};

static u8 mt2131_config2[] = {
	0x10,
	0x7f, 0xc8, 0x0a, 0x5f, 0x00, 0x04
};

static int mt2131_readreg(struct mt2131_priv *priv, u8 reg, u8 *val)
{
	struct i2c_msg msg[2] = {
		{ .addr = priv->cfg->i2c_address, .flags = 0,
		  .buf = &reg, .len = 1 },
		{ .addr = priv->cfg->i2c_address, .flags = I2C_M_RD,
		  .buf = val,  .len = 1 },
	};

	if (i2c_transfer(priv->i2c, msg, 2) != 2) {
		printk(KERN_WARNING "mt2131 I2C read failed\n");
		return -EREMOTEIO;
	}
	return 0;
}

static int mt2131_writereg(struct mt2131_priv *priv, u8 reg, u8 val)
{
	u8 buf[2] = { reg, val };
	struct i2c_msg msg = { .addr = priv->cfg->i2c_address, .flags = 0,
			       .buf = buf, .len = 2 };

	if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
		printk(KERN_WARNING "mt2131 I2C write failed\n");
		return -EREMOTEIO;
	}
	return 0;
}

static int mt2131_writeregs(struct mt2131_priv *priv,u8 *buf, u8 len)
{
	struct i2c_msg msg = { .addr = priv->cfg->i2c_address,
			       .flags = 0, .buf = buf, .len = len };

	if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
		printk(KERN_WARNING "mt2131 I2C write failed (len=%i)\n",
		       (int)len);
		return -EREMOTEIO;
	}
	return 0;
}

static int mt2131_set_params(struct dvb_frontend *fe)
{
	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
	struct mt2131_priv *priv;
	int ret=0, i;
	u32 freq;
	u8  if_band_center;
	u32 f_lo1, f_lo2;
	u32 div1, num1, div2, num2;
	u8  b[8];
	u8 lockval = 0;

	priv = fe->tuner_priv;

	freq = c->frequency / 1000;  /* Hz -> kHz */
	dprintk(1, "%s() freq=%d\n", __func__, freq);

	f_lo1 = freq + MT2131_IF1 * 1000;
	f_lo1 = (f_lo1 / 250) * 250;
	f_lo2 = f_lo1 - freq - MT2131_IF2;

	priv->frequency =  (f_lo1 - f_lo2 - MT2131_IF2) * 1000;

	/* Frequency LO1 = 16MHz * (DIV1 + NUM1/8192 ) */
	num1 = f_lo1 * 64 / (MT2131_FREF / 128);
	div1 = num1 / 8192;
	num1 &= 0x1fff;

	/* Frequency LO2 = 16MHz * (DIV2 + NUM2/8192 ) */
	num2 = f_lo2 * 64 / (MT2131_FREF / 128);
	div2 = num2 / 8192;
	num2 &= 0x1fff;

	if (freq <=   82500) if_band_center = 0x00; else
	if (freq <=  137500) if_band_center = 0x01; else
	if (freq <=  192500) if_band_center = 0x02; else
	if (freq <=  247500) if_band_center = 0x03; else
	if (freq <=  302500) if_band_center = 0x04; else
	if (freq <=  357500) if_band_center = 0x05; else
	if (freq <=  412500) if_band_center = 0x06; else
	if (freq <=  467500) if_band_center = 0x07; else
	if (freq <=  522500) if_band_center = 0x08; else
	if (freq <=  577500) if_band_center = 0x09; else
	if (freq <=  632500) if_band_center = 0x0A; else
	if (freq <=  687500) if_band_center = 0x0B; else
	if (freq <=  742500) if_band_center = 0x0C; else
	if (freq <=  797500) if_band_center = 0x0D; else
	if (freq <=  852500) if_band_center = 0x0E; else
	if (freq <=  907500) if_band_center = 0x0F; else
	if (freq <=  962500) if_band_center = 0x10; else
	if (freq <= 1017500) if_band_center = 0x11; else
	if (freq <= 1072500) if_band_center = 0x12; else if_band_center = 0x13;

	b[0] = 1;
	b[1] = (num1 >> 5) & 0xFF;
	b[2] = (num1 & 0x1F);
	b[3] = div1;
	b[4] = (num2 >> 5) & 0xFF;
	b[5] = num2 & 0x1F;
	b[6] = div2;

	dprintk(1, "IF1: %dMHz IF2: %dMHz\n", MT2131_IF1, MT2131_IF2);
	dprintk(1, "PLL freq=%dkHz  band=%d\n", (int)freq, (int)if_band_center);
	dprintk(1, "PLL f_lo1=%dkHz  f_lo2=%dkHz\n", (int)f_lo1, (int)f_lo2);
	dprintk(1, "PLL div1=%d  num1=%d  div2=%d  num2=%d\n",
		(int)div1, (int)num1, (int)div2, (int)num2);
	dprintk(1, "PLL [1..6]: %2x %2x %2x %2x %2x %2x\n",
		(int)b[1], (int)b[2], (int)b[3], (int)b[4], (int)b[5],
		(int)b[6]);

	ret = mt2131_writeregs(priv,b,7);
	if (ret < 0)
		return ret;

	mt2131_writereg(priv, 0x0b, if_band_center);

	/* Wait for lock */
	i = 0;
	do {
		mt2131_readreg(priv, 0x08, &lockval);
		if ((lockval & 0x88) == 0x88)
			break;
		msleep(4);
		i++;
	} while (i < 10);

	return ret;
}

static int mt2131_get_frequency(struct dvb_frontend *fe, u32 *frequency)
{
	struct mt2131_priv *priv = fe->tuner_priv;
	dprintk(1, "%s()\n", __func__);
	*frequency = priv->frequency;
	return 0;
}

static int mt2131_get_status(struct dvb_frontend *fe, u32 *status)
{
	struct mt2131_priv *priv = fe->tuner_priv;
	u8 lock_status = 0;
	u8 afc_status = 0;

	*status = 0;

	mt2131_readreg(priv, 0x08, &lock_status);
	if ((lock_status & 0x88) == 0x88)
		*status = TUNER_STATUS_LOCKED;

	mt2131_readreg(priv, 0x09, &afc_status);
	dprintk(1, "%s() - LO Status = 0x%x, AFC Status = 0x%x\n",
		__func__, lock_status, afc_status);

	return 0;
}

static int mt2131_init(struct dvb_frontend *fe)
{
	struct mt2131_priv *priv = fe->tuner_priv;
	int ret;
	dprintk(1, "%s()\n", __func__);

	if ((ret = mt2131_writeregs(priv, mt2131_config1,
				    sizeof(mt2131_config1))) < 0)
		return ret;

	mt2131_writereg(priv, 0x0b, 0x09);
	mt2131_writereg(priv, 0x15, 0x47);
	mt2131_writereg(priv, 0x07, 0xf2);
	mt2131_writereg(priv, 0x0b, 0x01);

	if ((ret = mt2131_writeregs(priv, mt2131_config2,
				    sizeof(mt2131_config2))) < 0)
		return ret;

	return ret;
}

static void mt2131_release(struct dvb_frontend *fe)
{
	dprintk(1, "%s()\n", __func__);
	kfree(fe->tuner_priv);
	fe->tuner_priv = NULL;
}

static const struct dvb_tuner_ops mt2131_tuner_ops = {
	.info = {
		.name           = "Microtune MT2131",
		.frequency_min  =  48000000,
		.frequency_max  = 860000000,
		.frequency_step =     50000,
	},

	.release       = mt2131_release,
	.init          = mt2131_init,

	.set_params    = mt2131_set_params,
	.get_frequency = mt2131_get_frequency,
	.get_status    = mt2131_get_status
};

struct dvb_frontend * mt2131_attach(struct dvb_frontend *fe,
				    struct i2c_adapter *i2c,
				    struct mt2131_config *cfg, u16 if1)
{
	struct mt2131_priv *priv = NULL;
	u8 id = 0;

	dprintk(1, "%s()\n", __func__);

	priv = kzalloc(sizeof(struct mt2131_priv), GFP_KERNEL);
	if (priv == NULL)
		return NULL;

	priv->cfg = cfg;
	priv->i2c = i2c;

	if (mt2131_readreg(priv, 0, &id) != 0) {
		kfree(priv);
		return NULL;
	}
	if ( (id != 0x3E) && (id != 0x3F) ) {
		printk(KERN_ERR "MT2131: Device not found at addr 0x%02x\n",
		       cfg->i2c_address);
		kfree(priv);
		return NULL;
	}

	printk(KERN_INFO "MT2131: successfully identified at address 0x%02x\n",
	       cfg->i2c_address);
	memcpy(&fe->ops.tuner_ops, &mt2131_tuner_ops,
	       sizeof(struct dvb_tuner_ops));

	fe->tuner_priv = priv;
	return fe;
}
EXPORT_SYMBOL(mt2131_attach);

MODULE_AUTHOR("Steven Toth");
MODULE_DESCRIPTION("Microtune MT2131 silicon tuner driver");
MODULE_LICENSE("GPL");
