1f47623a04dab402fb2c18fe516a174bc02005629Steven Toth/*
2f47623a04dab402fb2c18fe516a174bc02005629Steven Toth *  Driver for Microtune MT2131 "QAM/8VSB single chip tuner"
3f47623a04dab402fb2c18fe516a174bc02005629Steven Toth *
46d8976164dd7d10d25fe940b8546265f60ad52cdSteven Toth *  Copyright (c) 2006 Steven Toth <stoth@linuxtv.org>
5f47623a04dab402fb2c18fe516a174bc02005629Steven Toth *
6f47623a04dab402fb2c18fe516a174bc02005629Steven Toth *  This program is free software; you can redistribute it and/or modify
7f47623a04dab402fb2c18fe516a174bc02005629Steven Toth *  it under the terms of the GNU General Public License as published by
8f47623a04dab402fb2c18fe516a174bc02005629Steven Toth *  the Free Software Foundation; either version 2 of the License, or
9f47623a04dab402fb2c18fe516a174bc02005629Steven Toth *  (at your option) any later version.
10f47623a04dab402fb2c18fe516a174bc02005629Steven Toth *
11f47623a04dab402fb2c18fe516a174bc02005629Steven Toth *  This program is distributed in the hope that it will be useful,
12f47623a04dab402fb2c18fe516a174bc02005629Steven Toth *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13f47623a04dab402fb2c18fe516a174bc02005629Steven Toth *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14f47623a04dab402fb2c18fe516a174bc02005629Steven Toth *
15f47623a04dab402fb2c18fe516a174bc02005629Steven Toth *  GNU General Public License for more details.
16f47623a04dab402fb2c18fe516a174bc02005629Steven Toth *
17f47623a04dab402fb2c18fe516a174bc02005629Steven Toth *  You should have received a copy of the GNU General Public License
18f47623a04dab402fb2c18fe516a174bc02005629Steven Toth *  along with this program; if not, write to the Free Software
19f47623a04dab402fb2c18fe516a174bc02005629Steven Toth *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20f47623a04dab402fb2c18fe516a174bc02005629Steven Toth */
21f47623a04dab402fb2c18fe516a174bc02005629Steven Toth
22f47623a04dab402fb2c18fe516a174bc02005629Steven Toth#include <linux/module.h>
23f47623a04dab402fb2c18fe516a174bc02005629Steven Toth#include <linux/delay.h>
24f47623a04dab402fb2c18fe516a174bc02005629Steven Toth#include <linux/dvb/frontend.h>
25f47623a04dab402fb2c18fe516a174bc02005629Steven Toth#include <linux/i2c.h>
265a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
27f47623a04dab402fb2c18fe516a174bc02005629Steven Toth
28f47623a04dab402fb2c18fe516a174bc02005629Steven Toth#include "dvb_frontend.h"
29f47623a04dab402fb2c18fe516a174bc02005629Steven Toth
30f47623a04dab402fb2c18fe516a174bc02005629Steven Toth#include "mt2131.h"
31f47623a04dab402fb2c18fe516a174bc02005629Steven Toth#include "mt2131_priv.h"
32f47623a04dab402fb2c18fe516a174bc02005629Steven Toth
33f47623a04dab402fb2c18fe516a174bc02005629Steven Tothstatic int debug;
34f47623a04dab402fb2c18fe516a174bc02005629Steven Tothmodule_param(debug, int, 0644);
35f47623a04dab402fb2c18fe516a174bc02005629Steven TothMODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
36f47623a04dab402fb2c18fe516a174bc02005629Steven Toth
37f47623a04dab402fb2c18fe516a174bc02005629Steven Toth#define dprintk(level,fmt, arg...) if (debug >= level) \
38f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	printk(KERN_INFO "%s: " fmt, "mt2131", ## arg)
39f47623a04dab402fb2c18fe516a174bc02005629Steven Toth
40f47623a04dab402fb2c18fe516a174bc02005629Steven Tothstatic u8 mt2131_config1[] = {
41f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	0x01,
42f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	0x50, 0x00, 0x50, 0x80, 0x00, 0x49, 0xfa, 0x88,
43f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	0x08, 0x77, 0x41, 0x04, 0x00, 0x00, 0x00, 0x32,
44f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	0x7f, 0xda, 0x4c, 0x00, 0x10, 0xaa, 0x78, 0x80,
45f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	0xff, 0x68, 0xa0, 0xff, 0xdd, 0x00, 0x00
46f47623a04dab402fb2c18fe516a174bc02005629Steven Toth};
47f47623a04dab402fb2c18fe516a174bc02005629Steven Toth
48f47623a04dab402fb2c18fe516a174bc02005629Steven Tothstatic u8 mt2131_config2[] = {
49f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	0x10,
50f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	0x7f, 0xc8, 0x0a, 0x5f, 0x00, 0x04
51f47623a04dab402fb2c18fe516a174bc02005629Steven Toth};
52f47623a04dab402fb2c18fe516a174bc02005629Steven Toth
53f47623a04dab402fb2c18fe516a174bc02005629Steven Tothstatic int mt2131_readreg(struct mt2131_priv *priv, u8 reg, u8 *val)
54f47623a04dab402fb2c18fe516a174bc02005629Steven Toth{
55f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	struct i2c_msg msg[2] = {
563873dd041465799cfdeb642531c0ade4fb6614e5Michael Krufky		{ .addr = priv->cfg->i2c_address, .flags = 0,
573873dd041465799cfdeb642531c0ade4fb6614e5Michael Krufky		  .buf = &reg, .len = 1 },
583873dd041465799cfdeb642531c0ade4fb6614e5Michael Krufky		{ .addr = priv->cfg->i2c_address, .flags = I2C_M_RD,
593873dd041465799cfdeb642531c0ade4fb6614e5Michael Krufky		  .buf = val,  .len = 1 },
60f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	};
61f47623a04dab402fb2c18fe516a174bc02005629Steven Toth
62f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	if (i2c_transfer(priv->i2c, msg, 2) != 2) {
63f47623a04dab402fb2c18fe516a174bc02005629Steven Toth		printk(KERN_WARNING "mt2131 I2C read failed\n");
64f47623a04dab402fb2c18fe516a174bc02005629Steven Toth		return -EREMOTEIO;
65f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	}
66f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	return 0;
67f47623a04dab402fb2c18fe516a174bc02005629Steven Toth}
68f47623a04dab402fb2c18fe516a174bc02005629Steven Toth
69f47623a04dab402fb2c18fe516a174bc02005629Steven Tothstatic int mt2131_writereg(struct mt2131_priv *priv, u8 reg, u8 val)
70f47623a04dab402fb2c18fe516a174bc02005629Steven Toth{
71f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	u8 buf[2] = { reg, val };
723873dd041465799cfdeb642531c0ade4fb6614e5Michael Krufky	struct i2c_msg msg = { .addr = priv->cfg->i2c_address, .flags = 0,
733873dd041465799cfdeb642531c0ade4fb6614e5Michael Krufky			       .buf = buf, .len = 2 };
74f47623a04dab402fb2c18fe516a174bc02005629Steven Toth
75f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
76f47623a04dab402fb2c18fe516a174bc02005629Steven Toth		printk(KERN_WARNING "mt2131 I2C write failed\n");
77f47623a04dab402fb2c18fe516a174bc02005629Steven Toth		return -EREMOTEIO;
78f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	}
79f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	return 0;
80f47623a04dab402fb2c18fe516a174bc02005629Steven Toth}
81f47623a04dab402fb2c18fe516a174bc02005629Steven Toth
82f47623a04dab402fb2c18fe516a174bc02005629Steven Tothstatic int mt2131_writeregs(struct mt2131_priv *priv,u8 *buf, u8 len)
83f47623a04dab402fb2c18fe516a174bc02005629Steven Toth{
843873dd041465799cfdeb642531c0ade4fb6614e5Michael Krufky	struct i2c_msg msg = { .addr = priv->cfg->i2c_address,
853873dd041465799cfdeb642531c0ade4fb6614e5Michael Krufky			       .flags = 0, .buf = buf, .len = len };
86f47623a04dab402fb2c18fe516a174bc02005629Steven Toth
87f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
883873dd041465799cfdeb642531c0ade4fb6614e5Michael Krufky		printk(KERN_WARNING "mt2131 I2C write failed (len=%i)\n",
893873dd041465799cfdeb642531c0ade4fb6614e5Michael Krufky		       (int)len);
90f47623a04dab402fb2c18fe516a174bc02005629Steven Toth		return -EREMOTEIO;
91f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	}
92f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	return 0;
93f47623a04dab402fb2c18fe516a174bc02005629Steven Toth}
94f47623a04dab402fb2c18fe516a174bc02005629Steven Toth
9514d24d148c7521b2b88b396652e36f55d061e195Mauro Carvalho Chehabstatic int mt2131_set_params(struct dvb_frontend *fe)
96f47623a04dab402fb2c18fe516a174bc02005629Steven Toth{
9701ce5a7915932c199c8196347d0469ab2cc0573fMauro Carvalho Chehab	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
98f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	struct mt2131_priv *priv;
99f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	int ret=0, i;
100f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	u32 freq;
101f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	u8  if_band_center;
1023873dd041465799cfdeb642531c0ade4fb6614e5Michael Krufky	u32 f_lo1, f_lo2;
1033873dd041465799cfdeb642531c0ade4fb6614e5Michael Krufky	u32 div1, num1, div2, num2;
104f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	u8  b[8];
105f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	u8 lockval = 0;
106f47623a04dab402fb2c18fe516a174bc02005629Steven Toth
107f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	priv = fe->tuner_priv;
108f47623a04dab402fb2c18fe516a174bc02005629Steven Toth
10901ce5a7915932c199c8196347d0469ab2cc0573fMauro Carvalho Chehab	freq = c->frequency / 1000;  /* Hz -> kHz */
110271ddbf702c3a4e6b18f6464180eda0f62efd9a5Harvey Harrison	dprintk(1, "%s() freq=%d\n", __func__, freq);
111f47623a04dab402fb2c18fe516a174bc02005629Steven Toth
112f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	f_lo1 = freq + MT2131_IF1 * 1000;
113f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	f_lo1 = (f_lo1 / 250) * 250;
114f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	f_lo2 = f_lo1 - freq - MT2131_IF2;
115f47623a04dab402fb2c18fe516a174bc02005629Steven Toth
116195ccf67738f41eae557ba0322b33b15a39fd88fSteven Toth	priv->frequency =  (f_lo1 - f_lo2 - MT2131_IF2) * 1000;
117f47623a04dab402fb2c18fe516a174bc02005629Steven Toth
118f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	/* Frequency LO1 = 16MHz * (DIV1 + NUM1/8192 ) */
119f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	num1 = f_lo1 * 64 / (MT2131_FREF / 128);
120f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	div1 = num1 / 8192;
121f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	num1 &= 0x1fff;
122f47623a04dab402fb2c18fe516a174bc02005629Steven Toth
123f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	/* Frequency LO2 = 16MHz * (DIV2 + NUM2/8192 ) */
124f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	num2 = f_lo2 * 64 / (MT2131_FREF / 128);
125f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	div2 = num2 / 8192;
126f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	num2 &= 0x1fff;
127f47623a04dab402fb2c18fe516a174bc02005629Steven Toth
128f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	if (freq <=   82500) if_band_center = 0x00; else
129f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	if (freq <=  137500) if_band_center = 0x01; else
130f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	if (freq <=  192500) if_band_center = 0x02; else
131f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	if (freq <=  247500) if_band_center = 0x03; else
132f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	if (freq <=  302500) if_band_center = 0x04; else
133f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	if (freq <=  357500) if_band_center = 0x05; else
134f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	if (freq <=  412500) if_band_center = 0x06; else
135f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	if (freq <=  467500) if_band_center = 0x07; else
136f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	if (freq <=  522500) if_band_center = 0x08; else
137f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	if (freq <=  577500) if_band_center = 0x09; else
138f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	if (freq <=  632500) if_band_center = 0x0A; else
139f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	if (freq <=  687500) if_band_center = 0x0B; else
140f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	if (freq <=  742500) if_band_center = 0x0C; else
141f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	if (freq <=  797500) if_band_center = 0x0D; else
142f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	if (freq <=  852500) if_band_center = 0x0E; else
143f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	if (freq <=  907500) if_band_center = 0x0F; else
144f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	if (freq <=  962500) if_band_center = 0x10; else
145f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	if (freq <= 1017500) if_band_center = 0x11; else
146f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	if (freq <= 1072500) if_band_center = 0x12; else if_band_center = 0x13;
147f47623a04dab402fb2c18fe516a174bc02005629Steven Toth
148f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	b[0] = 1;
149f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	b[1] = (num1 >> 5) & 0xFF;
150f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	b[2] = (num1 & 0x1F);
151f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	b[3] = div1;
152f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	b[4] = (num2 >> 5) & 0xFF;
153f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	b[5] = num2 & 0x1F;
154f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	b[6] = div2;
155f47623a04dab402fb2c18fe516a174bc02005629Steven Toth
156f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	dprintk(1, "IF1: %dMHz IF2: %dMHz\n", MT2131_IF1, MT2131_IF2);
157f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	dprintk(1, "PLL freq=%dkHz  band=%d\n", (int)freq, (int)if_band_center);
158f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	dprintk(1, "PLL f_lo1=%dkHz  f_lo2=%dkHz\n", (int)f_lo1, (int)f_lo2);
159f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	dprintk(1, "PLL div1=%d  num1=%d  div2=%d  num2=%d\n",
160f47623a04dab402fb2c18fe516a174bc02005629Steven Toth		(int)div1, (int)num1, (int)div2, (int)num2);
161f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	dprintk(1, "PLL [1..6]: %2x %2x %2x %2x %2x %2x\n",
162f47623a04dab402fb2c18fe516a174bc02005629Steven Toth		(int)b[1], (int)b[2], (int)b[3], (int)b[4], (int)b[5],
163f47623a04dab402fb2c18fe516a174bc02005629Steven Toth		(int)b[6]);
164f47623a04dab402fb2c18fe516a174bc02005629Steven Toth
165f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	ret = mt2131_writeregs(priv,b,7);
166f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	if (ret < 0)
167f47623a04dab402fb2c18fe516a174bc02005629Steven Toth		return ret;
168f47623a04dab402fb2c18fe516a174bc02005629Steven Toth
169f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	mt2131_writereg(priv, 0x0b, if_band_center);
170f47623a04dab402fb2c18fe516a174bc02005629Steven Toth
171f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	/* Wait for lock */
172f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	i = 0;
173f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	do {
174f47623a04dab402fb2c18fe516a174bc02005629Steven Toth		mt2131_readreg(priv, 0x08, &lockval);
175f47623a04dab402fb2c18fe516a174bc02005629Steven Toth		if ((lockval & 0x88) == 0x88)
176f47623a04dab402fb2c18fe516a174bc02005629Steven Toth			break;
177f47623a04dab402fb2c18fe516a174bc02005629Steven Toth		msleep(4);
178f47623a04dab402fb2c18fe516a174bc02005629Steven Toth		i++;
179f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	} while (i < 10);
180f47623a04dab402fb2c18fe516a174bc02005629Steven Toth
181f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	return ret;
182f47623a04dab402fb2c18fe516a174bc02005629Steven Toth}
183f47623a04dab402fb2c18fe516a174bc02005629Steven Toth
184f47623a04dab402fb2c18fe516a174bc02005629Steven Tothstatic int mt2131_get_frequency(struct dvb_frontend *fe, u32 *frequency)
185f47623a04dab402fb2c18fe516a174bc02005629Steven Toth{
186f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	struct mt2131_priv *priv = fe->tuner_priv;
187271ddbf702c3a4e6b18f6464180eda0f62efd9a5Harvey Harrison	dprintk(1, "%s()\n", __func__);
188f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	*frequency = priv->frequency;
189f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	return 0;
190f47623a04dab402fb2c18fe516a174bc02005629Steven Toth}
191f47623a04dab402fb2c18fe516a174bc02005629Steven Toth
192f47623a04dab402fb2c18fe516a174bc02005629Steven Tothstatic int mt2131_get_status(struct dvb_frontend *fe, u32 *status)
193f47623a04dab402fb2c18fe516a174bc02005629Steven Toth{
194f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	struct mt2131_priv *priv = fe->tuner_priv;
195f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	u8 lock_status = 0;
196f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	u8 afc_status = 0;
197f47623a04dab402fb2c18fe516a174bc02005629Steven Toth
198f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	*status = 0;
199f47623a04dab402fb2c18fe516a174bc02005629Steven Toth
200f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	mt2131_readreg(priv, 0x08, &lock_status);
201f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	if ((lock_status & 0x88) == 0x88)
202f47623a04dab402fb2c18fe516a174bc02005629Steven Toth		*status = TUNER_STATUS_LOCKED;
203f47623a04dab402fb2c18fe516a174bc02005629Steven Toth
204f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	mt2131_readreg(priv, 0x09, &afc_status);
205f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	dprintk(1, "%s() - LO Status = 0x%x, AFC Status = 0x%x\n",
206271ddbf702c3a4e6b18f6464180eda0f62efd9a5Harvey Harrison		__func__, lock_status, afc_status);
207f47623a04dab402fb2c18fe516a174bc02005629Steven Toth
208f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	return 0;
209f47623a04dab402fb2c18fe516a174bc02005629Steven Toth}
210f47623a04dab402fb2c18fe516a174bc02005629Steven Toth
211f47623a04dab402fb2c18fe516a174bc02005629Steven Tothstatic int mt2131_init(struct dvb_frontend *fe)
212f47623a04dab402fb2c18fe516a174bc02005629Steven Toth{
213f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	struct mt2131_priv *priv = fe->tuner_priv;
214f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	int ret;
215271ddbf702c3a4e6b18f6464180eda0f62efd9a5Harvey Harrison	dprintk(1, "%s()\n", __func__);
216f47623a04dab402fb2c18fe516a174bc02005629Steven Toth
2173873dd041465799cfdeb642531c0ade4fb6614e5Michael Krufky	if ((ret = mt2131_writeregs(priv, mt2131_config1,
2183873dd041465799cfdeb642531c0ade4fb6614e5Michael Krufky				    sizeof(mt2131_config1))) < 0)
219f47623a04dab402fb2c18fe516a174bc02005629Steven Toth		return ret;
220f47623a04dab402fb2c18fe516a174bc02005629Steven Toth
221f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	mt2131_writereg(priv, 0x0b, 0x09);
222f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	mt2131_writereg(priv, 0x15, 0x47);
223f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	mt2131_writereg(priv, 0x07, 0xf2);
224f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	mt2131_writereg(priv, 0x0b, 0x01);
225f47623a04dab402fb2c18fe516a174bc02005629Steven Toth
2263873dd041465799cfdeb642531c0ade4fb6614e5Michael Krufky	if ((ret = mt2131_writeregs(priv, mt2131_config2,
2273873dd041465799cfdeb642531c0ade4fb6614e5Michael Krufky				    sizeof(mt2131_config2))) < 0)
228f47623a04dab402fb2c18fe516a174bc02005629Steven Toth		return ret;
229f47623a04dab402fb2c18fe516a174bc02005629Steven Toth
230f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	return ret;
231f47623a04dab402fb2c18fe516a174bc02005629Steven Toth}
232f47623a04dab402fb2c18fe516a174bc02005629Steven Toth
233f47623a04dab402fb2c18fe516a174bc02005629Steven Tothstatic int mt2131_release(struct dvb_frontend *fe)
234f47623a04dab402fb2c18fe516a174bc02005629Steven Toth{
235271ddbf702c3a4e6b18f6464180eda0f62efd9a5Harvey Harrison	dprintk(1, "%s()\n", __func__);
236f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	kfree(fe->tuner_priv);
237f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	fe->tuner_priv = NULL;
238f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	return 0;
239f47623a04dab402fb2c18fe516a174bc02005629Steven Toth}
240f47623a04dab402fb2c18fe516a174bc02005629Steven Toth
241f47623a04dab402fb2c18fe516a174bc02005629Steven Tothstatic const struct dvb_tuner_ops mt2131_tuner_ops = {
242f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	.info = {
243f47623a04dab402fb2c18fe516a174bc02005629Steven Toth		.name           = "Microtune MT2131",
244f47623a04dab402fb2c18fe516a174bc02005629Steven Toth		.frequency_min  =  48000000,
245f47623a04dab402fb2c18fe516a174bc02005629Steven Toth		.frequency_max  = 860000000,
246f47623a04dab402fb2c18fe516a174bc02005629Steven Toth		.frequency_step =     50000,
247f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	},
248f47623a04dab402fb2c18fe516a174bc02005629Steven Toth
249f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	.release       = mt2131_release,
250f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	.init          = mt2131_init,
251f47623a04dab402fb2c18fe516a174bc02005629Steven Toth
252f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	.set_params    = mt2131_set_params,
253f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	.get_frequency = mt2131_get_frequency,
254f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	.get_status    = mt2131_get_status
255f47623a04dab402fb2c18fe516a174bc02005629Steven Toth};
256f47623a04dab402fb2c18fe516a174bc02005629Steven Toth
2573873dd041465799cfdeb642531c0ade4fb6614e5Michael Krufkystruct dvb_frontend * mt2131_attach(struct dvb_frontend *fe,
2583873dd041465799cfdeb642531c0ade4fb6614e5Michael Krufky				    struct i2c_adapter *i2c,
2593873dd041465799cfdeb642531c0ade4fb6614e5Michael Krufky				    struct mt2131_config *cfg, u16 if1)
260f47623a04dab402fb2c18fe516a174bc02005629Steven Toth{
261f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	struct mt2131_priv *priv = NULL;
262f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	u8 id = 0;
263f47623a04dab402fb2c18fe516a174bc02005629Steven Toth
264271ddbf702c3a4e6b18f6464180eda0f62efd9a5Harvey Harrison	dprintk(1, "%s()\n", __func__);
265f47623a04dab402fb2c18fe516a174bc02005629Steven Toth
266f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	priv = kzalloc(sizeof(struct mt2131_priv), GFP_KERNEL);
267f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	if (priv == NULL)
268f47623a04dab402fb2c18fe516a174bc02005629Steven Toth		return NULL;
269f47623a04dab402fb2c18fe516a174bc02005629Steven Toth
270f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	priv->cfg = cfg;
271f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	priv->i2c = i2c;
272f47623a04dab402fb2c18fe516a174bc02005629Steven Toth
273f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	if (mt2131_readreg(priv, 0, &id) != 0) {
274f47623a04dab402fb2c18fe516a174bc02005629Steven Toth		kfree(priv);
275f47623a04dab402fb2c18fe516a174bc02005629Steven Toth		return NULL;
276f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	}
277f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	if ( (id != 0x3E) && (id != 0x3F) ) {
2783873dd041465799cfdeb642531c0ade4fb6614e5Michael Krufky		printk(KERN_ERR "MT2131: Device not found at addr 0x%02x\n",
2793873dd041465799cfdeb642531c0ade4fb6614e5Michael Krufky		       cfg->i2c_address);
280f47623a04dab402fb2c18fe516a174bc02005629Steven Toth		kfree(priv);
281f47623a04dab402fb2c18fe516a174bc02005629Steven Toth		return NULL;
282f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	}
283f47623a04dab402fb2c18fe516a174bc02005629Steven Toth
2843873dd041465799cfdeb642531c0ade4fb6614e5Michael Krufky	printk(KERN_INFO "MT2131: successfully identified at address 0x%02x\n",
2853873dd041465799cfdeb642531c0ade4fb6614e5Michael Krufky	       cfg->i2c_address);
2863873dd041465799cfdeb642531c0ade4fb6614e5Michael Krufky	memcpy(&fe->ops.tuner_ops, &mt2131_tuner_ops,
2873873dd041465799cfdeb642531c0ade4fb6614e5Michael Krufky	       sizeof(struct dvb_tuner_ops));
288f47623a04dab402fb2c18fe516a174bc02005629Steven Toth
289f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	fe->tuner_priv = priv;
290f47623a04dab402fb2c18fe516a174bc02005629Steven Toth	return fe;
291f47623a04dab402fb2c18fe516a174bc02005629Steven Toth}
292f47623a04dab402fb2c18fe516a174bc02005629Steven TothEXPORT_SYMBOL(mt2131_attach);
293f47623a04dab402fb2c18fe516a174bc02005629Steven Toth
294f47623a04dab402fb2c18fe516a174bc02005629Steven TothMODULE_AUTHOR("Steven Toth");
295f47623a04dab402fb2c18fe516a174bc02005629Steven TothMODULE_DESCRIPTION("Microtune MT2131 silicon tuner driver");
296f47623a04dab402fb2c18fe516a174bc02005629Steven TothMODULE_LICENSE("GPL");
2973873dd041465799cfdeb642531c0ade4fb6614e5Michael Krufky
2983873dd041465799cfdeb642531c0ade4fb6614e5Michael Krufky/*
2993873dd041465799cfdeb642531c0ade4fb6614e5Michael Krufky * Local variables:
3003873dd041465799cfdeb642531c0ade4fb6614e5Michael Krufky * c-basic-offset: 8
3013873dd041465799cfdeb642531c0ade4fb6614e5Michael Krufky */
302