Commit cbdc80ed authored by Antti Palosaari's avatar Antti Palosaari Committed by Mauro Carvalho Chehab

V4L/DVB (5137): Dvb: add new qt1010 tuner module

QT1010:
- old qt1010-code totally rewritten and put in own kernel module
- same enhancements as my earlier QT1010 125kHz patch
- tuner initialization
- register 1f calculation
- register 20 calculation
- register 25 calculation

m920x: (MSI Megasky)
- use new QT1010 module instead of old code
Signed-off-by: default avatarAntti Palosaari <crope@iki.fi>
Signed-off-by: default avatarMichael Krufky <mkrufky@linuxtv.org>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@infradead.org>
parent 1f61f3ba
......@@ -383,6 +383,17 @@ static int m9206_firmware_download(struct usb_device *udev, const struct firmwar
return ret;
}
static struct qt1010_config megasky_qt1010_config = {
.i2c_address = 0xc4
};
static int megasky_tuner_attach(struct dvb_usb_adapter *adap)
{
return dvb_attach(qt1010_attach,
adap->fe, &adap->dev->i2c_adap,
&megasky_qt1010_config) == NULL ? -ENODEV : 0;
}
/* DVB USB Driver stuff */
static struct dvb_usb_device_properties megasky_properties;
......@@ -442,7 +453,7 @@ static struct dvb_usb_device_properties megasky_properties = {
.pid_filter_ctrl = m9206_pid_filter_ctrl,
.frontend_attach = megasky_frontend_attach,
.tuner_attach = qt1010_tuner_attach,
.tuner_attach = megasky_tuner_attach,
.stream = {
.type = USB_BULK,
......
......@@ -290,6 +290,13 @@ config DVB_TDA826X
help
A DVB-S silicon tuner module. Say Y when you want to support this tuner.
config DVB_TUNER_QT1010
tristate "Quantek QT1010 silicon tuner"
depends on DVB_CORE && I2C
default m if DVB_FE_CUSTOMISE
help
A driver for the silicon tuner QT1010 from Quantek.
config DVB_TUNER_MT2060
tristate "Microtune MT2060 silicon IF tuner"
depends on I2C
......
......@@ -38,5 +38,6 @@ obj-$(CONFIG_DVB_ISL6421) += isl6421.o
obj-$(CONFIG_DVB_TDA10086) += tda10086.o
obj-$(CONFIG_DVB_TDA826X) += tda826x.o
obj-$(CONFIG_DVB_TUNER_MT2060) += mt2060.o
obj-$(CONFIG_DVB_TUNER_QT1010) += qt1010.o
obj-$(CONFIG_DVB_TUA6100) += tua6100.o
obj-$(CONFIG_DVB_TUNER_LGH06XF) += lgh06xf.o
This diff is collapsed.
/*
* qt1010.h - DVB-T Tuner support
* Driver for Quantek QT1010 silicon tuner
*
* Copyright (C) 2006 Antti Palosaari <crope@iki.fi>
* Aapo Tahkola <aet@rasterburn.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
......@@ -16,211 +19,35 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef _QT1010_H_
#define _QT1010_H_
#define QT1010_W 0
#define QT1010_R 1
/* Not actual hw limits. */
#define QT1010_MIN_STEP 2000000
#define QT1010_MIN_FREQ 48000000
static int qt1010_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
{
int i;
int div, mod;
struct {
u8 read, reg, value;
} rd[46] = { { QT1010_W, 0x01, 0x80 },
{ QT1010_W, 0x02, 0x3f },
{ QT1010_W, 0x05, 0xff }, /* c */
{ QT1010_W, 0x06, 0x44 },
{ QT1010_W, 0x07, 0xff }, /* c */
{ QT1010_W, 0x08, 0x08 },
{ QT1010_W, 0x09, 0xff }, /* c */
{ QT1010_W, 0x0a, 0xff }, /* c */
{ QT1010_W, 0x0b, 0xff }, /* c */
{ QT1010_W, 0x0c, 0xe1 },
{ QT1010_W, 0x1a, 0xff }, /* 10 c */
{ QT1010_W, 0x1b, 0x00 },
{ QT1010_W, 0x1c, 0x89 },
{ QT1010_W, 0x11, 0xff }, /* c */
{ QT1010_W, 0x12, 0x91 },
{ QT1010_W, 0x22, 0xff }, /* c */
{ QT1010_W, 0x1e, 0x00 },
{ QT1010_W, 0x1e, 0xd0 },
{ QT1010_R, 0x22, 0xff }, /* c read */
{ QT1010_W, 0x1e, 0x00 },
{ QT1010_R, 0x05, 0xff }, /* 20 c read */
{ QT1010_R, 0x22, 0xff }, /* c read */
{ QT1010_W, 0x23, 0xd0 },
{ QT1010_W, 0x1e, 0x00 },
{ QT1010_W, 0x1e, 0xe0 },
{ QT1010_R, 0x23, 0xff }, /* c read */
{ QT1010_W, 0x1e, 0x00 },
{ QT1010_W, 0x24, 0xd0 },
{ QT1010_W, 0x1e, 0x00 },
{ QT1010_W, 0x1e, 0xf0 },
{ QT1010_R, 0x24, 0xff }, /* 30 c read */
{ QT1010_W, 0x1e, 0x00 },
{ QT1010_W, 0x14, 0x7f },
{ QT1010_W, 0x15, 0x7f },
{ QT1010_W, 0x05, 0xff }, /* c */
{ QT1010_W, 0x06, 0x00 },
{ QT1010_W, 0x15, 0x1f },
{ QT1010_W, 0x16, 0xff },
{ QT1010_W, 0x18, 0xff },
{ QT1010_W, 0x1f, 0xff }, /* c */
{ QT1010_W, 0x20, 0xff }, /* 40 c */
{ QT1010_W, 0x21, 0x53 },
{ QT1010_W, 0x25, 0xbd },
{ QT1010_W, 0x26, 0x15 },
{ QT1010_W, 0x02, 0x00 },
{ QT1010_W, 0x01, 0x00 },
};
struct i2c_msg msg;
struct dvb_usb_adapter *adap = fe->dvb->priv;
unsigned long freq = params->frequency;
if (freq % QT1010_MIN_STEP)
printk("frequency not supported.\n");
div = (freq - QT1010_MIN_FREQ) / QT1010_MIN_STEP;
mod = (div + 16 - 9) % 16;
/* 0x5 */
if (div >= 377)
rd[2].value = 0x74;
else if (div >= 265)
rd[2].value = 0x54;
else if (div >= 121)
rd[2].value = 0x34;
else
rd[2].value = 0x14;
/* 0x7 */
rd[4].value = (((freq - QT1010_MIN_FREQ) / 1000000) * 9975 + 12960000) / 320000;
/* 09 */
if (mod < 4)
rd[6].value = 0x1d;
else
rd[6].value = 0x1c;
/* 0a */
if (mod < 2)
rd[7].value = 0x09;
else if (mod < 4)
rd[7].value = 0x08;
else if (mod < 6)
rd[7].value = 0x0f;
else if (mod < 8)
rd[7].value = 0x0e;
else if (mod < 10)
rd[7].value = 0x0d;
else if (mod < 12)
rd[7].value = 0x0c;
else if (mod < 14)
rd[7].value = 0x0b;
else
rd[7].value = 0x0a;
/* 0b */
if (div & 1)
rd[8].value = 0x45;
else
rd[8].value = 0x44;
/* 1a */
if (div & 1)
rd[10].value = 0x78;
else
rd[10].value = 0xf8;
#ifndef QT1010_H
#define QT1010_H
/* 11 */
if (div >= 265)
rd[13].value = 0xf9;
else if (div >= 121)
rd[13].value = 0xfd;
else
rd[13].value = 0xf9;
#include "dvb_frontend.h"
/* 22 */
if (div < 201)
rd[15].value = 0xd0;
else if (div < 217)
rd[15].value = 0xd3;
else if (div < 233)
rd[15].value = 0xd6;
else if (div < 249)
rd[15].value = 0xd9;
else if (div < 265)
rd[15].value = 0xda;
else
rd[15].value = 0xd0;
struct qt1010_config {
u8 i2c_address;
};
/* 05 */
if (div >= 377)
rd[34].value = 0x70;
else if (div >= 265)
rd[34].value = 0x50;
else if (div >= 121)
rd[34].value = 0x30;
else
rd[34].value = 0x10;
/* 1f */
if (mod < 4)
rd[39].value = 0x64;
else if (mod < 6)
rd[39].value = 0x66;
else if (mod < 8)
rd[39].value = 0x67;
else if (mod < 12)
rd[39].value = 0x68;
else if (mod < 14)
rd[39].value = 0x69;
else
rd[39].value = 0x6a;
/* 20 */
if (mod < 4)
rd[40].value = 0x10;
else if (mod < 6)
rd[40].value = 0x11;
else if (mod < 10)
rd[40].value = 0x12;
else if (mod < 12)
rd[40].value = 0x13;
else if (mod < 14)
rd[40].value = 0x14;
else
rd[40].value = 0x15;
for (i = 0; i < sizeof(rd) / sizeof(*rd); i++) {
if (rd[i].read)
continue;
msg.flags = 0;
msg.len = 2;
msg.addr = adap->dev->adapter[0].pll_addr;
msg.buf = &rd[i].reg;
if (i2c_transfer(&adap->dev->i2c_adap, &msg, 1) != 1) {
printk("tuner write failed\n");
return -EIO;
}
}
return 0;
}
static int qt1010_tuner_attach(struct dvb_usb_adapter *adap)
/**
* Attach a qt1010 tuner to the supplied frontend structure.
*
* @param fe frontend to attach to
* @param i2c i2c adapter to use
* @param cfg tuner hw based configuration
* @return fe pointer on success, NULL on failure
*/
#if defined(CONFIG_DVB_TUNER_QT1010) || (defined(CONFIG_DVB_TUNER_QT1010_MODULE) && defined(MODULE))
extern struct dvb_frontend *qt1010_attach(struct dvb_frontend *fe,
struct i2c_adapter *i2c,
struct qt1010_config *cfg);
#else
static inline struct dvb_frontend *qt1010_attach(struct dvb_frontend *fe,
struct i2c_adapter *i2c,
struct qt1010_config *cfg)
{
adap->pll_addr = 0xc4;
adap->pll_desc = NULL;
adap->fe->ops.tuner_ops.set_params = qt1010_set_params;
return 0;
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
return NULL;
}
#endif // CONFIG_DVB_TUNER_QT1010
#endif
/*
* Driver for Quantek QT1010 silicon tuner
*
* Copyright (C) 2006 Antti Palosaari <crope@iki.fi>
* Aapo Tahkola <aet@rasterburn.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.
*/
#ifndef QT1010_PRIV_H
#define QT1010_PRIV_H
/*
reg def meaning
=== === =======
00 00 ?
01 a0 ? operation start/stop; start=80, stop=00
02 00 ?
03 19 ?
04 00 ?
05 00 ? maybe band selection
06 00 ?
07 2b set frequency: 32 MHz scale, n*32 MHz
08 0b ?
09 10 ? changes every 8/24 MHz; values 1d/1c
0a 08 set frequency: 4 MHz scale, n*4 MHz
0b 41 ? changes every 2/2 MHz; values 45/45
0c e1 ?
0d 94 ?
0e b6 ?
0f 2c ?
10 10 ?
11 f1 ? maybe device specified adjustment
12 11 ? maybe device specified adjustment
13 3f ?
14 1f ?
15 3f ?
16 ff ?
17 ff ?
18 f7 ?
19 80 ?
1a d0 set frequency: 125 kHz scale, n*125 kHz
1b 00 ?
1c 89 ?
1d 00 ?
1e 00 ? looks like operation register; write cmd here, read result from 1f-26
1f 20 ? chip initialization
20 e0 ? chip initialization
21 20 ?
22 d0 ?
23 d0 ?
24 d0 ?
25 40 ? chip initialization
26 08 ?
27 29 ?
28 55 ?
29 39 ?
2a 13 ?
2b 01 ?
2c ea ?
2d 00 ?
2e 00 ? not used?
2f 00 ? not used?
*/
#define QT1010_STEP 125000 /* 125 kHz used by Windows drivers,
hw could be more precise but we don't
know how to use */
#define QT1010_MIN_FREQ 48000000 /* 48 MHz */
#define QT1010_MAX_FREQ 860000000 /* 860 MHz */
#define QT1010_OFFSET 1246000000 /* 1246 MHz */
#define QT1010_WR 0
#define QT1010_RD 1
#define QT1010_M1 3
typedef struct {
u8 oper, reg, val;
} qt1010_i2c_oper_t;
struct qt1010_priv {
struct qt1010_config *cfg;
struct i2c_adapter *i2c;
u8 reg1f_init_val;
u8 reg20_init_val;
u8 reg25_init_val;
u32 frequency;
u32 bandwidth;
};
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment