summaryrefslogtreecommitdiff
path: root/linux/drivers/media/dvb/frontends
diff options
context:
space:
mode:
Diffstat (limited to 'linux/drivers/media/dvb/frontends')
-rw-r--r--linux/drivers/media/dvb/frontends/Kconfig45
-rw-r--r--linux/drivers/media/dvb/frontends/Makefile5
-rw-r--r--linux/drivers/media/dvb/frontends/at76c651.h9
-rw-r--r--linux/drivers/media/dvb/frontends/bcm3510.h9
-rw-r--r--linux/drivers/media/dvb/frontends/cx22700.h9
-rw-r--r--linux/drivers/media/dvb/frontends/cx22702.h9
-rw-r--r--linux/drivers/media/dvb/frontends/cx24110.c17
-rw-r--r--linux/drivers/media/dvb/frontends/cx24110.h19
-rw-r--r--linux/drivers/media/dvb/frontends/cx24123.h9
-rw-r--r--linux/drivers/media/dvb/frontends/dib3000-common.c83
-rw-r--r--linux/drivers/media/dvb/frontends/dib3000-common.h135
-rw-r--r--linux/drivers/media/dvb/frontends/dib3000.h11
-rw-r--r--linux/drivers/media/dvb/frontends/dib3000mb.c77
-rw-r--r--linux/drivers/media/dvb/frontends/dib3000mb_priv.h93
-rw-r--r--linux/drivers/media/dvb/frontends/dib3000mc.c1464
-rw-r--r--linux/drivers/media/dvb/frontends/dib3000mc_priv.h428
-rw-r--r--linux/drivers/media/dvb/frontends/dvb-pll.c25
-rw-r--r--linux/drivers/media/dvb/frontends/dvb-pll.h4
-rw-r--r--linux/drivers/media/dvb/frontends/isl6421.c28
-rw-r--r--linux/drivers/media/dvb/frontends/isl6421.h11
-rw-r--r--linux/drivers/media/dvb/frontends/l64781.h10
-rw-r--r--linux/drivers/media/dvb/frontends/lgdt330x.c2
-rw-r--r--linux/drivers/media/dvb/frontends/lgdt330x.h9
-rw-r--r--linux/drivers/media/dvb/frontends/lnbp21.c28
-rw-r--r--linux/drivers/media/dvb/frontends/lnbp21.h12
-rw-r--r--linux/drivers/media/dvb/frontends/mt2060.c372
-rw-r--r--linux/drivers/media/dvb/frontends/mt2060.h35
-rw-r--r--linux/drivers/media/dvb/frontends/mt2060_priv.h105
-rw-r--r--linux/drivers/media/dvb/frontends/mt312.h10
-rw-r--r--linux/drivers/media/dvb/frontends/mt352.c16
-rw-r--r--linux/drivers/media/dvb/frontends/mt352.h16
-rw-r--r--linux/drivers/media/dvb/frontends/nxt200x.c4
-rw-r--r--linux/drivers/media/dvb/frontends/nxt200x.h9
-rw-r--r--linux/drivers/media/dvb/frontends/nxt6000.h9
-rw-r--r--linux/drivers/media/dvb/frontends/or51132.h9
-rw-r--r--linux/drivers/media/dvb/frontends/or51211.c2
-rw-r--r--linux/drivers/media/dvb/frontends/or51211.h9
-rw-r--r--linux/drivers/media/dvb/frontends/s5h1420.h9
-rw-r--r--linux/drivers/media/dvb/frontends/sp8870.c2
-rw-r--r--linux/drivers/media/dvb/frontends/sp8870.h9
-rw-r--r--linux/drivers/media/dvb/frontends/sp887x.c2
-rw-r--r--linux/drivers/media/dvb/frontends/sp887x.h9
-rw-r--r--linux/drivers/media/dvb/frontends/stv0297.h9
-rw-r--r--linux/drivers/media/dvb/frontends/stv0299.c9
-rw-r--r--linux/drivers/media/dvb/frontends/stv0299.h19
-rw-r--r--linux/drivers/media/dvb/frontends/tda10021.c64
-rw-r--r--linux/drivers/media/dvb/frontends/tda10021.h19
-rw-r--r--linux/drivers/media/dvb/frontends/tda1004x.c10
-rw-r--r--linux/drivers/media/dvb/frontends/tda1004x.h25
-rw-r--r--linux/drivers/media/dvb/frontends/tda8083.h9
-rw-r--r--linux/drivers/media/dvb/frontends/tda80xx.c1
-rw-r--r--linux/drivers/media/dvb/frontends/tda80xx.h9
-rw-r--r--linux/drivers/media/dvb/frontends/ves1820.c1
-rw-r--r--linux/drivers/media/dvb/frontends/ves1820.h9
-rw-r--r--linux/drivers/media/dvb/frontends/ves1x93.h9
-rw-r--r--linux/drivers/media/dvb/frontends/zl10353.c3
-rw-r--r--linux/drivers/media/dvb/frontends/zl10353.h11
57 files changed, 1890 insertions, 1495 deletions
diff --git a/linux/drivers/media/dvb/frontends/Kconfig b/linux/drivers/media/dvb/frontends/Kconfig
index 0ef361f03..191fa4de7 100644
--- a/linux/drivers/media/dvb/frontends/Kconfig
+++ b/linux/drivers/media/dvb/frontends/Kconfig
@@ -1,48 +1,66 @@
menu "Customise DVB Frontends"
depends on DVB_CORE
+config DVB_FE_CUSTOMISE
+ bool "Customise the frontend modules to build"
+ default N
+ help
+ This allows the user to deselect frontend drivers unnecessary
+ for their hardware from the build. Use this option with care
+ as deselecting frontends which are in fact necessary will result
+ in DVB devices which cannot be tuned due to lack of driver support.
+
+ If unsure say N.
+
comment "DVB-S (satellite) frontends"
depends on DVB_CORE
config DVB_STV0299
tristate "ST STV0299 based"
depends on DVB_CORE
+ default m if DVB_FE_CUSTOMISE
help
A DVB-S tuner module. Say Y when you want to support this frontend.
config DVB_CX24110
tristate "Conexant CX24110 based"
depends on DVB_CORE
+ default m if DVB_FE_CUSTOMISE
help
A DVB-S tuner module. Say Y when you want to support this frontend.
config DVB_CX24123
tristate "Conexant CX24123 based"
depends on DVB_CORE
+ default m if DVB_FE_CUSTOMISE
help
A DVB-S tuner module. Say Y when you want to support this frontend.
config DVB_TDA8083
tristate "Philips TDA8083 based"
depends on DVB_CORE
+ default m if DVB_FE_CUSTOMISE
help
A DVB-S tuner module. Say Y when you want to support this frontend.
config DVB_MT312
tristate "Zarlink VP310/MT312 based"
depends on DVB_CORE
+ default m if DVB_FE_CUSTOMISE
help
A DVB-S tuner module. Say Y when you want to support this frontend.
config DVB_VES1X93
tristate "VLSI VES1893 or VES1993 based"
depends on DVB_CORE
+ default m if DVB_FE_CUSTOMISE
help
A DVB-S tuner module. Say Y when you want to support this frontend.
config DVB_S5H1420
tristate "Samsung S5H1420 based"
depends on DVB_CORE
+ default m if DVB_FE_CUSTOMISE
help
A DVB-S tuner module. Say Y when you want to support this frontend.
@@ -52,6 +70,7 @@ comment "DVB-T (terrestrial) frontends"
config DVB_SP8870
tristate "Spase sp8870 based"
depends on DVB_CORE
+ default m if DVB_FE_CUSTOMISE
select FW_LOADER
help
A DVB-T tuner module. Say Y when you want to support this frontend.
@@ -64,6 +83,7 @@ config DVB_SP8870
config DVB_SP887X
tristate "Spase sp887x based"
depends on DVB_CORE
+ default m if DVB_FE_CUSTOMISE
select FW_LOADER
help
A DVB-T tuner module. Say Y when you want to support this frontend.
@@ -76,24 +96,28 @@ config DVB_SP887X
config DVB_CX22700
tristate "Conexant CX22700 based"
depends on DVB_CORE
+ default m if DVB_FE_CUSTOMISE
help
A DVB-T tuner module. Say Y when you want to support this frontend.
config DVB_CX22702
tristate "Conexant cx22702 demodulator (OFDM)"
depends on DVB_CORE
+ default m if DVB_FE_CUSTOMISE
help
A DVB-T tuner module. Say Y when you want to support this frontend.
config DVB_L64781
tristate "LSI L64781"
depends on DVB_CORE
+ default m if DVB_FE_CUSTOMISE
help
A DVB-T tuner module. Say Y when you want to support this frontend.
config DVB_TDA1004X
tristate "Philips TDA10045H/TDA10046H based"
depends on DVB_CORE
+ default m if DVB_FE_CUSTOMISE
select FW_LOADER
help
A DVB-T tuner module. Say Y when you want to support this frontend.
@@ -107,24 +131,28 @@ config DVB_TDA1004X
config DVB_NXT6000
tristate "NxtWave Communications NXT6000 based"
depends on DVB_CORE
+ default m if DVB_FE_CUSTOMISE
help
A DVB-T tuner module. Say Y when you want to support this frontend.
config DVB_MT352
tristate "Zarlink MT352 based"
depends on DVB_CORE
+ default m if DVB_FE_CUSTOMISE
help
A DVB-T tuner module. Say Y when you want to support this frontend.
config DVB_ZL10353
tristate "Zarlink ZL10353 based"
depends on DVB_CORE
+ default m if DVB_FE_CUSTOMISE
help
A DVB-T tuner module. Say Y when you want to support this frontend.
config DVB_DIB3000MB
tristate "DiBcom 3000M-B"
depends on DVB_CORE
+ default m if DVB_FE_CUSTOMISE
help
A DVB-T tuner module. Designed for mobile usage. Say Y when you want
to support this frontend.
@@ -132,6 +160,7 @@ config DVB_DIB3000MB
config DVB_DIB3000MC
tristate "DiBcom 3000P/M-C"
depends on DVB_CORE
+ default m if DVB_FE_CUSTOMISE
help
A DVB-T tuner module. Designed for mobile usage. Say Y when you want
to support this frontend.
@@ -142,18 +171,21 @@ comment "DVB-C (cable) frontends"
config DVB_VES1820
tristate "VLSI VES1820 based"
depends on DVB_CORE
+ default m if DVB_FE_CUSTOMISE
help
A DVB-C tuner module. Say Y when you want to support this frontend.
config DVB_TDA10021
tristate "Philips TDA10021 based"
depends on DVB_CORE
+ default m if DVB_FE_CUSTOMISE
help
A DVB-C tuner module. Say Y when you want to support this frontend.
config DVB_STV0297
tristate "ST STV0297 based"
depends on DVB_CORE
+ default m if DVB_FE_CUSTOMISE
help
A DVB-C tuner module. Say Y when you want to support this frontend.
@@ -163,6 +195,7 @@ comment "ATSC (North American/Korean Terrestrial/Cable DTV) frontends"
config DVB_NXT200X
tristate "NxtWave Communications NXT2002/NXT2004 based"
depends on DVB_CORE
+ default m if DVB_FE_CUSTOMISE
select FW_LOADER
help
An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
@@ -177,6 +210,7 @@ config DVB_NXT200X
config DVB_OR51211
tristate "Oren OR51211 based"
depends on DVB_CORE
+ default m if DVB_FE_CUSTOMISE
select FW_LOADER
help
An ATSC 8VSB tuner module. Say Y when you want to support this frontend.
@@ -189,6 +223,7 @@ config DVB_OR51211
config DVB_OR51132
tristate "Oren OR51132 based"
depends on DVB_CORE
+ default m if DVB_FE_CUSTOMISE
select FW_LOADER
help
An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
@@ -204,6 +239,7 @@ config DVB_OR51132
config DVB_BCM3510
tristate "Broadcom BCM3510"
depends on DVB_CORE
+ default m if DVB_FE_CUSTOMISE
select FW_LOADER
help
An ATSC 8VSB/16VSB and QAM64/256 tuner module. Say Y when you want to
@@ -212,24 +248,31 @@ config DVB_BCM3510
config DVB_LGDT330X
tristate "LG Electronics LGDT3302/LGDT3303 based"
depends on DVB_CORE
+ default m if DVB_FE_CUSTOMISE
help
An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
to support this frontend.
-
comment "Miscellaneous devices"
depends on DVB_CORE
config DVB_LNBP21
tristate "LNBP21 SEC controller"
depends on DVB_CORE
+ default m if DVB_FE_CUSTOMISE
help
An SEC control chip.
config DVB_ISL6421
tristate "ISL6421 SEC controller"
depends on DVB_CORE
+ default m if DVB_FE_CUSTOMISE
help
An SEC control chip.
+config DVB_TUNER_MT2060
+ tristate "Microtune MT2060 silicon IF tuner"
+ help
+ A driver for the silicon IF tuner MT2060 from Microtune.
+
endmenu
diff --git a/linux/drivers/media/dvb/frontends/Makefile b/linux/drivers/media/dvb/frontends/Makefile
index 5222245c7..a7fbd0fab 100644
--- a/linux/drivers/media/dvb/frontends/Makefile
+++ b/linux/drivers/media/dvb/frontends/Makefile
@@ -11,8 +11,8 @@ obj-$(CONFIG_DVB_CX22700) += cx22700.o
obj-$(CONFIG_DVB_CX24110) += cx24110.o
obj-$(CONFIG_DVB_TDA8083) += tda8083.o
obj-$(CONFIG_DVB_L64781) += l64781.o
-obj-$(CONFIG_DVB_DIB3000MB) += dib3000mb.o dib3000-common.o
-obj-$(CONFIG_DVB_DIB3000MC) += dib3000mc.o dib3000-common.o
+obj-$(CONFIG_DVB_DIB3000MB) += dib3000mb.o
+obj-$(CONFIG_DVB_DIB3000MC) += dib3000mc.o dibx000_common.o
obj-$(CONFIG_DVB_MT312) += mt312.o
obj-$(CONFIG_DVB_VES1820) += ves1820.o
obj-$(CONFIG_DVB_VES1X93) += ves1x93.o
@@ -33,3 +33,4 @@ obj-$(CONFIG_DVB_LGDT330X) += lgdt330x.o
obj-$(CONFIG_DVB_CX24123) += cx24123.o
obj-$(CONFIG_DVB_LNBP21) += lnbp21.o
obj-$(CONFIG_DVB_ISL6421) += isl6421.o
+obj-$(CONFIG_DVB_TUNER_MT2060) += mt2060.o
diff --git a/linux/drivers/media/dvb/frontends/at76c651.h b/linux/drivers/media/dvb/frontends/at76c651.h
index c31db11a2..32b26e368 100644
--- a/linux/drivers/media/dvb/frontends/at76c651.h
+++ b/linux/drivers/media/dvb/frontends/at76c651.h
@@ -37,7 +37,16 @@ struct at76c651_config
u8 demod_address;
};
+#if defined(CONFIG_DVB_AT76C651) || defined(CONFIG_DVB_AT76C651_MODULE)
extern struct dvb_frontend* at76c651_attach(const struct at76c651_config* config,
struct i2c_adapter* i2c);
+#else
+static inline struct dvb_frontend* at76c651_attach(const struct at76c651_config* config,
+ struct i2c_adapter* i2c)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ return NULL;
+}
+#endif // CONFIG_DVB_AT76C651
#endif // AT76C651_H
diff --git a/linux/drivers/media/dvb/frontends/bcm3510.h b/linux/drivers/media/dvb/frontends/bcm3510.h
index 80f5d0953..6dfa839a7 100644
--- a/linux/drivers/media/dvb/frontends/bcm3510.h
+++ b/linux/drivers/media/dvb/frontends/bcm3510.h
@@ -34,7 +34,16 @@ struct bcm3510_config
int (*request_firmware)(struct dvb_frontend* fe, const struct firmware **fw, char* name);
};
+#if defined(CONFIG_DVB_BCM3510) || defined(CONFIG_DVB_BCM3510_MODULE)
extern struct dvb_frontend* bcm3510_attach(const struct bcm3510_config* config,
struct i2c_adapter* i2c);
+#else
+static inline struct dvb_frontend* bcm3510_attach(const struct bcm3510_config* config,
+ struct i2c_adapter* i2c)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ return NULL;
+}
+#endif // CONFIG_DVB_BCM3510
#endif
diff --git a/linux/drivers/media/dvb/frontends/cx22700.h b/linux/drivers/media/dvb/frontends/cx22700.h
index dcd8979c1..10286cc29 100644
--- a/linux/drivers/media/dvb/frontends/cx22700.h
+++ b/linux/drivers/media/dvb/frontends/cx22700.h
@@ -31,7 +31,16 @@ struct cx22700_config
u8 demod_address;
};
+#if defined(CONFIG_DVB_CX22700) || defined(CONFIG_DVB_CX22700_MODULE)
extern struct dvb_frontend* cx22700_attach(const struct cx22700_config* config,
struct i2c_adapter* i2c);
+#else
+static inline struct dvb_frontend* cx22700_attach(const struct cx22700_config* config,
+ struct i2c_adapter* i2c)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ return NULL;
+}
+#endif // CONFIG_DVB_CX22700
#endif // CX22700_H
diff --git a/linux/drivers/media/dvb/frontends/cx22702.h b/linux/drivers/media/dvb/frontends/cx22702.h
index 7f2f241e5..bc217ddf0 100644
--- a/linux/drivers/media/dvb/frontends/cx22702.h
+++ b/linux/drivers/media/dvb/frontends/cx22702.h
@@ -41,7 +41,16 @@ struct cx22702_config
u8 output_mode;
};
+#if defined(CONFIG_DVB_CX22702) || defined(CONFIG_DVB_CX22702_MODULE)
extern struct dvb_frontend* cx22702_attach(const struct cx22702_config* config,
struct i2c_adapter* i2c);
+#else
+static inline struct dvb_frontend* cx22702_attach(const struct cx22702_config* config,
+ struct i2c_adapter* i2c)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ return NULL;
+}
+#endif // CONFIG_DVB_CX22702
#endif // CX22702_H
diff --git a/linux/drivers/media/dvb/frontends/cx24110.c b/linux/drivers/media/dvb/frontends/cx24110.c
index ce3c7398b..ae9639521 100644
--- a/linux/drivers/media/dvb/frontends/cx24110.c
+++ b/linux/drivers/media/dvb/frontends/cx24110.c
@@ -1,4 +1,4 @@
-/*
+ /*
cx24110 - Single Chip Satellite Channel Receiver driver module
Copyright (C) 2002 Peter Hettkamp <peter.hettkamp@htp-tel.de> based on
@@ -311,16 +311,17 @@ static int cx24110_set_symbolrate (struct cx24110_state* state, u32 srate)
}
-int cx24110_pll_write (struct dvb_frontend* fe, u32 data)
+static int _cx24110_pll_write (struct dvb_frontend* fe, u8 *buf, int len)
{
struct cx24110_state *state = fe->demodulator_priv;
+ if (len != 3)
+ return -EINVAL;
+
/* tuner data is 21 bits long, must be left-aligned in data */
/* tuner cx24108 is written through a dedicated 3wire interface on the demod chip */
/* FIXME (low): add error handling, avoid infinite loops if HW fails... */
- dprintk("cx24110 debug: cx24108_write(%8.8x)\n",data);
-
cx24110_writereg(state,0x6d,0x30); /* auto mode at 62kHz */
cx24110_writereg(state,0x70,0x15); /* auto mode 21 bits */
@@ -329,19 +330,19 @@ int cx24110_pll_write (struct dvb_frontend* fe, u32 data)
cx24110_writereg(state,0x72,0);
/* write the topmost 8 bits */
- cx24110_writereg(state,0x72,(data>>24)&0xff);
+ cx24110_writereg(state,0x72,buf[0]);
/* wait for the send to be completed */
while ((cx24110_readreg(state,0x6d)&0xc0)==0x80)
;
/* send another 8 bytes */
- cx24110_writereg(state,0x72,(data>>16)&0xff);
+ cx24110_writereg(state,0x72,buf[1]);
while ((cx24110_readreg(state,0x6d)&0xc0)==0x80)
;
/* and the topmost 5 bits of this byte */
- cx24110_writereg(state,0x72,(data>>8)&0xff);
+ cx24110_writereg(state,0x72,buf[2]);
while ((cx24110_readreg(state,0x6d)&0xc0)==0x80)
;
@@ -642,6 +643,7 @@ static struct dvb_frontend_ops cx24110_ops = {
.release = cx24110_release,
.init = cx24110_initfe,
+ .write = _cx24110_pll_write,
.set_frontend = cx24110_set_frontend,
.get_frontend = cx24110_get_frontend,
.read_status = cx24110_read_status,
@@ -664,4 +666,3 @@ MODULE_AUTHOR("Peter Hettkamp");
MODULE_LICENSE("GPL");
EXPORT_SYMBOL(cx24110_attach);
-EXPORT_SYMBOL(cx24110_pll_write);
diff --git a/linux/drivers/media/dvb/frontends/cx24110.h b/linux/drivers/media/dvb/frontends/cx24110.h
index b354a64e0..c9d5ae250 100644
--- a/linux/drivers/media/dvb/frontends/cx24110.h
+++ b/linux/drivers/media/dvb/frontends/cx24110.h
@@ -33,9 +33,24 @@ struct cx24110_config
u8 demod_address;
};
+static inline int cx24110_pll_write(struct dvb_frontend *fe, u32 val) {
+ int r = 0;
+ u8 buf[] = {(u8) (val>>24), (u8) (val>>16), (u8) (val>>8)};
+ if (fe->ops.write)
+ r = fe->ops.write(fe, buf, 3);
+ return r;
+}
+
+#if defined(CONFIG_DVB_CX24110) || defined(CONFIG_DVB_CX24110_MODULE)
extern struct dvb_frontend* cx24110_attach(const struct cx24110_config* config,
struct i2c_adapter* i2c);
-
-extern int cx24110_pll_write(struct dvb_frontend* fe, u32 data);
+#else
+static inline struct dvb_frontend* cx24110_attach(const struct cx24110_config* config,
+ struct i2c_adapter* i2c)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ return NULL;
+}
+#endif // CONFIG_DVB_CX24110
#endif // CX24110_H
diff --git a/linux/drivers/media/dvb/frontends/cx24123.h b/linux/drivers/media/dvb/frontends/cx24123.h
index 9606f8259..6a8cb4c41 100644
--- a/linux/drivers/media/dvb/frontends/cx24123.h
+++ b/linux/drivers/media/dvb/frontends/cx24123.h
@@ -32,7 +32,16 @@ struct cx24123_config
int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured);
};
+#if defined(CONFIG_DVB_CX24123) || defined(CONFIG_DVB_CX24123_MODULE)
extern struct dvb_frontend* cx24123_attach(const struct cx24123_config* config,
struct i2c_adapter* i2c);
+#else
+static inline struct dvb_frontend* cx24123_attach(const struct cx24123_config* config,
+ struct i2c_adapter* i2c)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ return NULL;
+}
+#endif // CONFIG_DVB_CX24123
#endif /* CX24123_H */
diff --git a/linux/drivers/media/dvb/frontends/dib3000-common.c b/linux/drivers/media/dvb/frontends/dib3000-common.c
deleted file mode 100644
index 1a4f1f7c2..000000000
--- a/linux/drivers/media/dvb/frontends/dib3000-common.c
+++ /dev/null
@@ -1,83 +0,0 @@
-#include "dib3000-common.h"
-
-#ifdef CONFIG_DVB_DIBCOM_DEBUG
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debugging level (1=info,2=i2c,4=srch (|-able)).");
-#endif
-#define deb_info(args...) dprintk(0x01,args)
-#define deb_i2c(args...) dprintk(0x02,args)
-#define deb_srch(args...) dprintk(0x04,args)
-
-
-int dib3000_read_reg(struct dib3000_state *state, u16 reg)
-{
- u8 wb[] = { ((reg >> 8) | 0x80) & 0xff, reg & 0xff };
- u8 rb[2];
- struct i2c_msg msg[] = {
- { .addr = state->config.demod_address, .flags = 0, .buf = wb, .len = 2 },
- { .addr = state->config.demod_address, .flags = I2C_M_RD, .buf = rb, .len = 2 },
- };
-
- if (i2c_transfer(state->i2c, msg, 2) != 2)
- deb_i2c("i2c read error\n");
-
- deb_i2c("reading i2c bus (reg: %5d 0x%04x, val: %5d 0x%04x)\n",reg,reg,
- (rb[0] << 8) | rb[1],(rb[0] << 8) | rb[1]);
-
- return (rb[0] << 8) | rb[1];
-}
-
-int dib3000_write_reg(struct dib3000_state *state, u16 reg, u16 val)
-{
- u8 b[] = {
- (reg >> 8) & 0xff, reg & 0xff,
- (val >> 8) & 0xff, val & 0xff,
- };
- struct i2c_msg msg[] = {
- { .addr = state->config.demod_address, .flags = 0, .buf = b, .len = 4 }
- };
- deb_i2c("writing i2c bus (reg: %5d 0x%04x, val: %5d 0x%04x)\n",reg,reg,val,val);
-
- return i2c_transfer(state->i2c,msg, 1) != 1 ? -EREMOTEIO : 0;
-}
-
-int dib3000_search_status(u16 irq,u16 lock)
-{
- if (irq & 0x02) {
- if (lock & 0x01) {
- deb_srch("auto search succeeded\n");
- return 1; // auto search succeeded
- } else {
- deb_srch("auto search not successful\n");
- return 0; // auto search failed
- }
- } else if (irq & 0x01) {
- deb_srch("auto search failed\n");
- return 0; // auto search failed
- }
- return -1; // try again
-}
-
-/* for auto search */
-u16 dib3000_seq[2][2][2] = /* fft,gua, inv */
- { /* fft */
- { /* gua */
- { 0, 1 }, /* 0 0 { 0,1 } */
- { 3, 9 }, /* 0 1 { 0,1 } */
- },
- {
- { 2, 5 }, /* 1 0 { 0,1 } */
- { 6, 11 }, /* 1 1 { 0,1 } */
- }
- };
-
-MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de");
-MODULE_DESCRIPTION("Common functions for the dib3000mb/dib3000mc dvb frontend drivers");
-MODULE_LICENSE("GPL");
-
-EXPORT_SYMBOL(dib3000_seq);
-
-EXPORT_SYMBOL(dib3000_read_reg);
-EXPORT_SYMBOL(dib3000_write_reg);
-EXPORT_SYMBOL(dib3000_search_status);
diff --git a/linux/drivers/media/dvb/frontends/dib3000-common.h b/linux/drivers/media/dvb/frontends/dib3000-common.h
deleted file mode 100644
index be1c0d3e1..000000000
--- a/linux/drivers/media/dvb/frontends/dib3000-common.h
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * .h-files for the common use of the frontend drivers made by DiBcom
- * DiBcom 3000M-B/C, 3000P
- *
- * DiBcom (http://www.dibcom.fr/)
- *
- * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
- *
- * based on GPL code from DibCom, which has
- *
- * Copyright (C) 2004 Amaury Demol for DiBcom (ademol@dibcom.fr)
- *
- * 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, version 2.
- *
- * Acknowledgements
- *
- * Amaury Demol (ademol@dibcom.fr) from DiBcom for providing specs and driver
- * sources, on which this driver (and the dvb-dibusb) are based.
- *
- * see Documentation/dvb/README.dibusb for more information
- *
- */
-
-#ifndef DIB3000_COMMON_H
-#define DIB3000_COMMON_H
-
-#include "dvb_frontend.h"
-#include "dib3000.h"
-
-/* info and err, taken from usb.h, if there is anything available like by default. */
-#define err(format, arg...) printk(KERN_ERR "dib3000: " format "\n" , ## arg)
-#define info(format, arg...) printk(KERN_INFO "dib3000: " format "\n" , ## arg)
-#define warn(format, arg...) printk(KERN_WARNING "dib3000: " format "\n" , ## arg)
-
-/* frontend state */
-struct dib3000_state {
- struct i2c_adapter* i2c;
-
-/* configuration settings */
- struct dib3000_config config;
-
- struct dvb_frontend frontend;
- int timing_offset;
- int timing_offset_comp_done;
-
- fe_bandwidth_t last_tuned_bw;
- u32 last_tuned_freq;
-};
-
-/* commonly used methods by the dib3000mb/mc/p frontend */
-extern int dib3000_read_reg(struct dib3000_state *state, u16 reg);
-extern int dib3000_write_reg(struct dib3000_state *state, u16 reg, u16 val);
-
-extern int dib3000_search_status(u16 irq,u16 lock);
-
-/* handy shortcuts */
-#define rd(reg) dib3000_read_reg(state,reg)
-
-#define wr(reg,val) if (dib3000_write_reg(state,reg,val)) \
- { err("while sending 0x%04x to 0x%04x.",val,reg); return -EREMOTEIO; }
-
-#define wr_foreach(a,v) { int i; \
- if (sizeof(a) != sizeof(v)) \
- err("sizeof: %zu %zu is different",sizeof(a),sizeof(v));\
- for (i=0; i < sizeof(a)/sizeof(u16); i++) \
- wr(a[i],v[i]); \
- }
-
-#define set_or(reg,val) wr(reg,rd(reg) | val)
-
-#define set_and(reg,val) wr(reg,rd(reg) & val)
-
-
-/* debug */
-
-#ifdef CONFIG_DVB_DIBCOM_DEBUG
-#define dprintk(level,args...) \
- do { if ((debug & level)) { printk(args); } } while (0)
-#else
-#define dprintk(args...) do { } while (0)
-#endif
-
-/* mask for enabling a specific pid for the pid_filter */
-#define DIB3000_ACTIVATE_PID_FILTERING (0x2000)
-
-/* common values for tuning */
-#define DIB3000_ALPHA_0 ( 0)
-#define DIB3000_ALPHA_1 ( 1)
-#define DIB3000_ALPHA_2 ( 2)
-#define DIB3000_ALPHA_4 ( 4)
-
-#define DIB3000_CONSTELLATION_QPSK ( 0)
-#define DIB3000_CONSTELLATION_16QAM ( 1)
-#define DIB3000_CONSTELLATION_64QAM ( 2)
-
-#define DIB3000_GUARD_TIME_1_32 ( 0)
-#define DIB3000_GUARD_TIME_1_16 ( 1)
-#define DIB3000_GUARD_TIME_1_8 ( 2)
-#define DIB3000_GUARD_TIME_1_4 ( 3)
-
-#define DIB3000_TRANSMISSION_MODE_2K ( 0)
-#define DIB3000_TRANSMISSION_MODE_8K ( 1)
-
-#define DIB3000_SELECT_LP ( 0)
-#define DIB3000_SELECT_HP ( 1)
-
-#define DIB3000_FEC_1_2 ( 1)
-#define DIB3000_FEC_2_3 ( 2)
-#define DIB3000_FEC_3_4 ( 3)
-#define DIB3000_FEC_5_6 ( 5)
-#define DIB3000_FEC_7_8 ( 7)
-
-#define DIB3000_HRCH_OFF ( 0)
-#define DIB3000_HRCH_ON ( 1)
-
-#define DIB3000_DDS_INVERSION_OFF ( 0)
-#define DIB3000_DDS_INVERSION_ON ( 1)
-
-#define DIB3000_TUNER_WRITE_ENABLE(a) (0xffff & (a << 8))
-#define DIB3000_TUNER_WRITE_DISABLE(a) (0xffff & ((a << 8) | (1 << 7)))
-
-/* for auto search */
-extern u16 dib3000_seq[2][2][2];
-
-#define DIB3000_REG_MANUFACTOR_ID ( 1025)
-#define DIB3000_I2C_ID_DIBCOM (0x01b3)
-
-#define DIB3000_REG_DEVICE_ID ( 1026)
-#define DIB3000MB_DEVICE_ID (0x3000)
-#define DIB3000MC_DEVICE_ID (0x3001)
-#define DIB3000P_DEVICE_ID (0x3002)
-
-#endif // DIB3000_COMMON_H
diff --git a/linux/drivers/media/dvb/frontends/dib3000.h b/linux/drivers/media/dvb/frontends/dib3000.h
index ec927628d..0caac3f0f 100644
--- a/linux/drivers/media/dvb/frontends/dib3000.h
+++ b/linux/drivers/media/dvb/frontends/dib3000.h
@@ -41,9 +41,16 @@ struct dib_fe_xfer_ops
int (*tuner_pass_ctrl)(struct dvb_frontend *fe, int onoff, u8 pll_ctrl);
};
+#if defined(CONFIG_DVB_DIB3000MB) || defined(CONFIG_DVB_DIB3000MB_MODULE)
extern struct dvb_frontend* dib3000mb_attach(const struct dib3000_config* config,
struct i2c_adapter* i2c, struct dib_fe_xfer_ops *xfer_ops);
+#else
+static inline struct dvb_frontend* dib3000mb_attach(const struct dib3000_config* config,
+ struct i2c_adapter* i2c, struct dib_fe_xfer_ops *xfer_ops)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ return NULL;
+}
+#endif // CONFIG_DVB_DIB3000MB
-extern struct dvb_frontend* dib3000mc_attach(const struct dib3000_config* config,
- struct i2c_adapter* i2c, struct dib_fe_xfer_ops *xfer_ops);
#endif // DIB3000_H
diff --git a/linux/drivers/media/dvb/frontends/dib3000mb.c b/linux/drivers/media/dvb/frontends/dib3000mb.c
index 7c6dc7e30..adbabfdb0 100644
--- a/linux/drivers/media/dvb/frontends/dib3000mb.c
+++ b/linux/drivers/media/dvb/frontends/dib3000mb.c
@@ -21,7 +21,6 @@
*
*/
-#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
@@ -30,9 +29,10 @@
#include <linux/string.h>
#include <linux/slab.h>
-#include "dib3000-common.h"
-#include "dib3000mb_priv.h"
+#include "dvb_frontend.h"
+
#include "dib3000.h"
+#include "dib3000mb_priv.h"
/* Version information */
#define DRIVER_VERSION "0.1"
@@ -45,10 +45,81 @@ module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "set debugging level (1=info,2=xfer,4=setfe,8=getfe (|-able)).");
#endif
#define deb_info(args...) dprintk(0x01,args)
+#define deb_i2c(args...) dprintk(0x02,args)
+#define deb_srch(args...) dprintk(0x04,args)
+#define deb_info(args...) dprintk(0x01,args)
#define deb_xfer(args...) dprintk(0x02,args)
#define deb_setf(args...) dprintk(0x04,args)
#define deb_getf(args...) dprintk(0x08,args)
+#ifdef CONFIG_DVB_DIBCOM_DEBUG
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level (1=info,2=i2c,4=srch (|-able)).");
+#endif
+
+static int dib3000_read_reg(struct dib3000_state *state, u16 reg)
+{
+ u8 wb[] = { ((reg >> 8) | 0x80) & 0xff, reg & 0xff };
+ u8 rb[2];
+ struct i2c_msg msg[] = {
+ { .addr = state->config.demod_address, .flags = 0, .buf = wb, .len = 2 },
+ { .addr = state->config.demod_address, .flags = I2C_M_RD, .buf = rb, .len = 2 },
+ };
+
+ if (i2c_transfer(state->i2c, msg, 2) != 2)
+ deb_i2c("i2c read error\n");
+
+ deb_i2c("reading i2c bus (reg: %5d 0x%04x, val: %5d 0x%04x)\n",reg,reg,
+ (rb[0] << 8) | rb[1],(rb[0] << 8) | rb[1]);
+
+ return (rb[0] << 8) | rb[1];
+}
+
+static int dib3000_write_reg(struct dib3000_state *state, u16 reg, u16 val)
+{
+ u8 b[] = {
+ (reg >> 8) & 0xff, reg & 0xff,
+ (val >> 8) & 0xff, val & 0xff,
+ };
+ struct i2c_msg msg[] = {
+ { .addr = state->config.demod_address, .flags = 0, .buf = b, .len = 4 }
+ };
+ deb_i2c("writing i2c bus (reg: %5d 0x%04x, val: %5d 0x%04x)\n",reg,reg,val,val);
+
+ return i2c_transfer(state->i2c,msg, 1) != 1 ? -EREMOTEIO : 0;
+}
+
+static int dib3000_search_status(u16 irq,u16 lock)
+{
+ if (irq & 0x02) {
+ if (lock & 0x01) {
+ deb_srch("auto search succeeded\n");
+ return 1; // auto search succeeded
+ } else {
+ deb_srch("auto search not successful\n");
+ return 0; // auto search failed
+ }
+ } else if (irq & 0x01) {
+ deb_srch("auto search failed\n");
+ return 0; // auto search failed
+ }
+ return -1; // try again
+}
+
+/* for auto search */
+static u16 dib3000_seq[2][2][2] = /* fft,gua, inv */
+ { /* fft */
+ { /* gua */
+ { 0, 1 }, /* 0 0 { 0,1 } */
+ { 3, 9 }, /* 0 1 { 0,1 } */
+ },
+ {
+ { 2, 5 }, /* 1 0 { 0,1 } */
+ { 6, 11 }, /* 1 1 { 0,1 } */
+ }
+ };
+
static int dib3000mb_get_frontend(struct dvb_frontend* fe,
struct dvb_frontend_parameters *fep);
diff --git a/linux/drivers/media/dvb/frontends/dib3000mb_priv.h b/linux/drivers/media/dvb/frontends/dib3000mb_priv.h
index 999b19047..1a12747fd 100644
--- a/linux/drivers/media/dvb/frontends/dib3000mb_priv.h
+++ b/linux/drivers/media/dvb/frontends/dib3000mb_priv.h
@@ -13,6 +13,99 @@
#ifndef __DIB3000MB_PRIV_H_INCLUDED__
#define __DIB3000MB_PRIV_H_INCLUDED__
+/* info and err, taken from usb.h, if there is anything available like by default. */
+#define err(format, arg...) printk(KERN_ERR "dib3000: " format "\n" , ## arg)
+#define info(format, arg...) printk(KERN_INFO "dib3000: " format "\n" , ## arg)
+#define warn(format, arg...) printk(KERN_WARNING "dib3000: " format "\n" , ## arg)
+
+/* handy shortcuts */
+#define rd(reg) dib3000_read_reg(state,reg)
+
+#define wr(reg,val) if (dib3000_write_reg(state,reg,val)) \
+ { err("while sending 0x%04x to 0x%04x.",val,reg); return -EREMOTEIO; }
+
+#define wr_foreach(a,v) { int i; \
+ if (sizeof(a) != sizeof(v)) \
+ err("sizeof: %zu %zu is different",sizeof(a),sizeof(v));\
+ for (i=0; i < sizeof(a)/sizeof(u16); i++) \
+ wr(a[i],v[i]); \
+ }
+
+#define set_or(reg,val) wr(reg,rd(reg) | val)
+
+#define set_and(reg,val) wr(reg,rd(reg) & val)
+
+/* debug */
+
+#ifdef CONFIG_DVB_DIBCOM_DEBUG
+#define dprintk(level,args...) \
+ do { if ((debug & level)) { printk(args); } } while (0)
+#else
+#define dprintk(args...) do { } while (0)
+#endif
+
+/* mask for enabling a specific pid for the pid_filter */
+#define DIB3000_ACTIVATE_PID_FILTERING (0x2000)
+
+/* common values for tuning */
+#define DIB3000_ALPHA_0 ( 0)
+#define DIB3000_ALPHA_1 ( 1)
+#define DIB3000_ALPHA_2 ( 2)
+#define DIB3000_ALPHA_4 ( 4)
+
+#define DIB3000_CONSTELLATION_QPSK ( 0)
+#define DIB3000_CONSTELLATION_16QAM ( 1)
+#define DIB3000_CONSTELLATION_64QAM ( 2)
+
+#define DIB3000_GUARD_TIME_1_32 ( 0)
+#define DIB3000_GUARD_TIME_1_16 ( 1)
+#define DIB3000_GUARD_TIME_1_8 ( 2)
+#define DIB3000_GUARD_TIME_1_4 ( 3)
+
+#define DIB3000_TRANSMISSION_MODE_2K ( 0)
+#define DIB3000_TRANSMISSION_MODE_8K ( 1)
+
+#define DIB3000_SELECT_LP ( 0)
+#define DIB3000_SELECT_HP ( 1)
+
+#define DIB3000_FEC_1_2 ( 1)
+#define DIB3000_FEC_2_3 ( 2)
+#define DIB3000_FEC_3_4 ( 3)
+#define DIB3000_FEC_5_6 ( 5)
+#define DIB3000_FEC_7_8 ( 7)
+
+#define DIB3000_HRCH_OFF ( 0)
+#define DIB3000_HRCH_ON ( 1)
+
+#define DIB3000_DDS_INVERSION_OFF ( 0)
+#define DIB3000_DDS_INVERSION_ON ( 1)
+
+#define DIB3000_TUNER_WRITE_ENABLE(a) (0xffff & (a << 8))
+#define DIB3000_TUNER_WRITE_DISABLE(a) (0xffff & ((a << 8) | (1 << 7)))
+
+#define DIB3000_REG_MANUFACTOR_ID ( 1025)
+#define DIB3000_I2C_ID_DIBCOM (0x01b3)
+
+#define DIB3000_REG_DEVICE_ID ( 1026)
+#define DIB3000MB_DEVICE_ID (0x3000)
+#define DIB3000MC_DEVICE_ID (0x3001)
+#define DIB3000P_DEVICE_ID (0x3002)
+
+/* frontend state */
+struct dib3000_state {
+ struct i2c_adapter* i2c;
+
+/* configuration settings */
+ struct dib3000_config config;
+
+ struct dvb_frontend frontend;
+ int timing_offset;
+ int timing_offset_comp_done;
+
+ fe_bandwidth_t last_tuned_bw;
+ u32 last_tuned_freq;
+};
+
/* register addresses and some of their default values */
/* restart subsystems */
diff --git a/linux/drivers/media/dvb/frontends/dib3000mc.c b/linux/drivers/media/dvb/frontends/dib3000mc.c
index 6c3be2529..3e68fd8e3 100644
--- a/linux/drivers/media/dvb/frontends/dib3000mc.c
+++ b/linux/drivers/media/dvb/frontends/dib3000mc.c
@@ -1,914 +1,954 @@
/*
- * Frontend driver for mobile DVB-T demodulator DiBcom 3000P/M-C
- * DiBcom (http://www.dibcom.fr/)
+ * Driver for DiBcom DiB3000MC/P-demodulator.
*
+ * Copyright (C) 2004-6 DiBcom (http://www.dibcom.fr/)
* Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
*
- * based on GPL code from DiBCom, which has
+ * This code is partially based on the previous dib3000mc.c .
*
- * Copyright (C) 2004 Amaury Demol for DiBcom (ademol@dibcom.fr)
- *
- * This program is free software; you can redistribute it and/or
+ * 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, version 2.
- *
- * Acknowledgements
- *
- * Amaury Demol (ademol@dibcom.fr) from DiBcom for providing specs and driver
- * sources, on which this driver (and the dvb-dibusb) are based.
- *
- * see Documentation/dvb/README.dibusb for more information
- *
*/
-#include <linux/config.h>
+
#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-
-#include "dib3000-common.h"
-#include "dib3000mc_priv.h"
-#include "dib3000.h"
-
-/* Version information */
-#define DRIVER_VERSION "0.1"
-#define DRIVER_DESC "DiBcom 3000M-C DVB-T demodulator"
-#define DRIVER_AUTHOR "Patrick Boettcher, patrick.boettcher@desy.de"
-
-#ifdef CONFIG_DVB_DIBCOM_DEBUG
+#include <linux/i2c.h>
+//#include <linux/init.h>
+//#include <linux/delay.h>
+//#include <linux/string.h>
+//#include <linux/slab.h>
+
+#include "dvb_frontend.h"
+
+#include "dib3000mc.h"
+
static int debug;
module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debugging level (1=info,2=xfer,4=setfe,8=getfe,16=stat (|-able)).");
-#endif
-#define deb_info(args...) dprintk(0x01,args)
-#define deb_xfer(args...) dprintk(0x02,args)
-#define deb_setf(args...) dprintk(0x04,args)
-#define deb_getf(args...) dprintk(0x08,args)
-#define deb_stat(args...) dprintk(0x10,args)
-
-static int dib3000mc_set_impulse_noise(struct dib3000_state * state, int mode,
- fe_transmit_mode_t transmission_mode, fe_bandwidth_t bandwidth)
-{
- switch (transmission_mode) {
- case TRANSMISSION_MODE_2K:
- wr_foreach(dib3000mc_reg_fft,dib3000mc_fft_modes[0]);
- break;
- case TRANSMISSION_MODE_8K:
- wr_foreach(dib3000mc_reg_fft,dib3000mc_fft_modes[1]);
- break;
- default:
- break;
- }
+MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
- switch (bandwidth) {
-/* case BANDWIDTH_5_MHZ:
- wr_foreach(dib3000mc_reg_impulse_noise,dib3000mc_impluse_noise[0]);
- break; */
- case BANDWIDTH_6_MHZ:
- wr_foreach(dib3000mc_reg_impulse_noise,dib3000mc_impluse_noise[1]);
- break;
- case BANDWIDTH_7_MHZ:
- wr_foreach(dib3000mc_reg_impulse_noise,dib3000mc_impluse_noise[2]);
- break;
- case BANDWIDTH_8_MHZ:
- wr_foreach(dib3000mc_reg_impulse_noise,dib3000mc_impluse_noise[3]);
- break;
- default:
- break;
+#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB3000MC/P:"); printk(args); } } while (0)
+
+struct dib3000mc_state {
+ struct dvb_frontend demod;
+ struct dib3000mc_config *cfg;
+
+ u8 i2c_addr;
+ struct i2c_adapter *i2c_adap;
+
+ struct dibx000_i2c_master i2c_master;
+
+ fe_bandwidth_t current_bandwidth;
+
+ u16 dev_id;
+};
+
+static u16 dib3000mc_read_word(struct dib3000mc_state *state, u16 reg)
+{
+ u8 wb[2] = { (reg >> 8) | 0x80, reg & 0xff };
+ u8 rb[2];
+ struct i2c_msg msg[2] = {
+ { .addr = state->i2c_addr >> 1, .flags = 0, .buf = wb, .len = 2 },
+ { .addr = state->i2c_addr >> 1, .flags = I2C_M_RD, .buf = rb, .len = 2 },
+ };
+
+ if (i2c_transfer(state->i2c_adap, msg, 2) != 2)
+ dprintk("i2c read error on %d\n",reg);
+
+ return (rb[0] << 8) | rb[1];
+}
+
+static int dib3000mc_write_word(struct dib3000mc_state *state, u16 reg, u16 val)
+{
+ u8 b[4] = {
+ (reg >> 8) & 0xff, reg & 0xff,
+ (val >> 8) & 0xff, val & 0xff,
+ };
+ struct i2c_msg msg = {
+ .addr = state->i2c_addr >> 1, .flags = 0, .buf = b, .len = 4
+ };
+ return i2c_transfer(state->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
+}
+
+static void dump_fep(struct dibx000_ofdm_channel *cd)
+{
+ printk(KERN_DEBUG "DiB3000MC: ");
+ switch (cd->nfft) {
+ case 1: printk("8K "); break;
+ case 2: printk("4K "); break;
+ case 0: printk("2K "); break;
+ default: printk("FFT_UNK "); break;
}
- switch (mode) {
- case 0: /* no impulse */ /* fall through */
- wr_foreach(dib3000mc_reg_imp_noise_ctl,dib3000mc_imp_noise_ctl[0]);
- break;
- case 1: /* new algo */
- wr_foreach(dib3000mc_reg_imp_noise_ctl,dib3000mc_imp_noise_ctl[1]);
- set_or(DIB3000MC_REG_IMP_NOISE_55,DIB3000MC_IMP_NEW_ALGO(0)); /* gives 1<<10 */
- break;
- default: /* old algo */
- wr_foreach(dib3000mc_reg_imp_noise_ctl,dib3000mc_imp_noise_ctl[3]);
- break;
+ printk("1/%i ", 32 / (1 << cd->guard));
+ switch (cd->nqam) {
+ case 0: printk("QPSK "); break;
+ case 1: printk("16QAM "); break;
+ case 2: printk("64QAM "); break;
+ default: printk("QAM_UNK "); break;
}
- return 0;
+ printk("ALPHA %i ", cd->vit_alpha);
+ printk("Code Rate HP %i/%i ", cd->vit_code_rate_hp, cd->vit_code_rate_hp + 1);
+ printk("Code Rate LP %i/%i ", cd->vit_code_rate_lp, cd->vit_code_rate_lp + 1);
+ printk("HRCH %i\n", cd->vit_hrch);
}
-static int dib3000mc_set_timing(struct dib3000_state *state, int upd_offset,
- fe_transmit_mode_t fft, fe_bandwidth_t bw)
+
+static int dib3000mc_identify(struct dib3000mc_state *state)
{
- u16 timf_msb,timf_lsb;
- s32 tim_offset,tim_sgn;
- u64 comp1,comp2,comp=0;
+ u16 value;
+ if ((value = dib3000mc_read_word(state, 1025)) != 0x01b3) {
+ dprintk("-E- DiB3000MC/P: wrong Vendor ID (read=0x%x)\n",value);
+ return -EREMOTEIO;
+ }
- switch (bw) {
- case BANDWIDTH_8_MHZ: comp = DIB3000MC_CLOCK_REF*8; break;
- case BANDWIDTH_7_MHZ: comp = DIB3000MC_CLOCK_REF*7; break;
- case BANDWIDTH_6_MHZ: comp = DIB3000MC_CLOCK_REF*6; break;
- default: err("unknown bandwidth (%d)",bw); break;
+ value = dib3000mc_read_word(state, 1026);
+ if (value != 0x3001 && value != 0x3002) {
+ dprintk("-E- DiB3000MC/P: wrong Device ID (%x)\n",value);
+ return -EREMOTEIO;
}
- timf_msb = (comp >> 16) & 0xff;
- timf_lsb = (comp & 0xffff);
+ state->dev_id = value;
+
+ dprintk("-I- found DiB3000MC/P: %x\n",state->dev_id);
+
+ return 0;
+}
+
+static int dib3000mc_set_timing(struct dib3000mc_state *state, s16 nfft, u8 bw, u8 update_offset)
+{
+/*
+ u32 timf_msb, timf_lsb, i;
+ int tim_sgn ;
+ LUInt comp1, comp2, comp ;
+// u32 tim_offset ;
+ comp = 27700 * BW_INDEX_TO_KHZ(bw) / 1000;
+ timf_msb = (comp >> 16) & 0x00FF;
+ timf_lsb = comp & 0xFFFF;
// Update the timing offset ;
- if (upd_offset > 0) {
- if (!state->timing_offset_comp_done) {
- msleep(200);
+ if (update_offset) {
+ if (state->timing_offset_comp_done == 0) {
+ usleep(200000);
state->timing_offset_comp_done = 1;
}
- tim_offset = rd(DIB3000MC_REG_TIMING_OFFS_MSB);
+ tim_offset = dib3000mc_read_word(state, 416);
if ((tim_offset & 0x2000) == 0x2000)
- tim_offset |= 0xC000;
- if (fft == TRANSMISSION_MODE_2K)
- tim_offset <<= 2;
+ tim_offset |= 0xC000; // PB: This only works if tim_offset is s16 - weird
+
+ if (nfft == 0)
+ tim_offset = tim_offset << 2; // PB: Do not store the offset for different things in one variable
state->timing_offset += tim_offset;
}
-
tim_offset = state->timing_offset;
+
if (tim_offset < 0) {
tim_sgn = 1;
tim_offset = -tim_offset;
} else
tim_sgn = 0;
- comp1 = (u32)tim_offset * (u32)timf_lsb ;
- comp2 = (u32)tim_offset * (u32)timf_msb ;
+ comp1 = tim_offset * timf_lsb;
+ comp2 = tim_offset * timf_msb;
comp = ((comp1 >> 16) + comp2) >> 7;
if (tim_sgn == 0)
- comp = (u32)(timf_msb << 16) + (u32) timf_lsb + comp;
+ comp = timf_msb * (1<<16) + timf_lsb + comp;
else
- comp = (u32)(timf_msb << 16) + (u32) timf_lsb - comp ;
+ comp = timf_msb * (1<<16) + timf_lsb - comp;
- timf_msb = (comp >> 16) & 0xff;
- timf_lsb = comp & 0xffff;
+ timf_msb = (comp>>16)&0xFF ;
+ timf_lsb = comp&0xFFFF;
+*/
+ u32 timf = 1384402 * (BW_INDEX_TO_KHZ(bw) / 1000);
+
+ dib3000mc_write_word(state, 23, timf >> 16);
+ dib3000mc_write_word(state, 24, timf & 0xffff);
- wr(DIB3000MC_REG_TIMING_FREQ_MSB,timf_msb);
- wr(DIB3000MC_REG_TIMING_FREQ_LSB,timf_lsb);
return 0;
}
-static int dib3000mc_init_auto_scan(struct dib3000_state *state, fe_bandwidth_t bw, int boost)
+static int dib3000mc_setup_pwm3_state(struct dib3000mc_state *state)
{
- if (boost) {
- wr(DIB3000MC_REG_SCAN_BOOST,DIB3000MC_SCAN_BOOST_ON);
+ if (state->cfg->pwm3_inversion) {
+ dib3000mc_write_word(state, 51, (2 << 14) | (0 << 10) | (7 << 6) | (2 << 2) | (2 << 0));
+ dib3000mc_write_word(state, 52, (0 << 8) | (5 << 5) | (1 << 4) | (1 << 3) | (1 << 2) | (2 << 0));
} else {
- wr(DIB3000MC_REG_SCAN_BOOST,DIB3000MC_SCAN_BOOST_OFF);
- }
- switch (bw) {
- case BANDWIDTH_8_MHZ:
- wr_foreach(dib3000mc_reg_bandwidth,dib3000mc_bandwidth_8mhz);
- break;
- case BANDWIDTH_7_MHZ:
- wr_foreach(dib3000mc_reg_bandwidth,dib3000mc_bandwidth_7mhz);
- break;
- case BANDWIDTH_6_MHZ:
- wr_foreach(dib3000mc_reg_bandwidth,dib3000mc_bandwidth_6mhz);
- break;
-/* case BANDWIDTH_5_MHZ:
- wr_foreach(dib3000mc_reg_bandwidth,dib3000mc_bandwidth_5mhz);
- break;*/
- case BANDWIDTH_AUTO:
- return -EOPNOTSUPP;
- default:
- err("unknown bandwidth value (%d).",bw);
- return -EINVAL;
- }
- if (boost) {
- u32 timeout = (rd(DIB3000MC_REG_BW_TIMOUT_MSB) << 16) +
- rd(DIB3000MC_REG_BW_TIMOUT_LSB);
- timeout *= 85; timeout >>= 7;
- wr(DIB3000MC_REG_BW_TIMOUT_MSB,(timeout >> 16) & 0xffff);
- wr(DIB3000MC_REG_BW_TIMOUT_LSB,timeout & 0xffff);
+ dib3000mc_write_word(state, 51, (2 << 14) | (4 << 10) | (7 << 6) | (2 << 2) | (2 << 0));
+ dib3000mc_write_word(state, 52, (1 << 8) | (5 << 5) | (1 << 4) | (1 << 3) | (0 << 2) | (2 << 0));
}
+
+ if (state->cfg->use_pwm3)
+ dib3000mc_write_word(state, 245, (1 << 3) | (1 << 0));
+ else
+ dib3000mc_write_word(state, 245, 0);
+
+ dib3000mc_write_word(state, 1040, 0x3);
return 0;
}
-static int dib3000mc_set_adp_cfg(struct dib3000_state *state, fe_modulation_t con)
+static int dib3000mc_set_output_mode(struct dib3000mc_state *state, int mode)
{
- switch (con) {
- case QAM_64:
- wr_foreach(dib3000mc_reg_adp_cfg,dib3000mc_adp_cfg[2]);
- break;
- case QAM_16:
- wr_foreach(dib3000mc_reg_adp_cfg,dib3000mc_adp_cfg[1]);
- break;
- case QPSK:
- wr_foreach(dib3000mc_reg_adp_cfg,dib3000mc_adp_cfg[0]);
- break;
- case QAM_AUTO:
+ int ret = 0;
+ u16 fifo_threshold = 1792;
+ u16 outreg = 0;
+ u16 outmode = 0;
+ u16 elecout = 1;
+ u16 smo_reg = (0 << 6) | (0 << 5) | (0 << 4) | (0 << 3) | (1 << 1) | 0 ; //smo_mode = 1
+
+ dprintk("-I- Setting output mode for demod %p to %d\n",
+ &state->demod, mode);
+
+ switch (mode) {
+ case OUTMODE_HIGH_Z: // disable
+ elecout = 0;
+ break;
+ case OUTMODE_MPEG2_PAR_GATED_CLK: // STBs with parallel gated clock
+ outmode = 0;
+ break;
+ case OUTMODE_MPEG2_PAR_CONT_CLK: // STBs with parallel continues clock
+ outmode = 1;
+ break;
+ case OUTMODE_MPEG2_SERIAL: // STBs with serial input
+ outmode = 2;
+ break;
+ case OUTMODE_MPEG2_FIFO: // e.g. USB feeding
+ elecout = 3;
+ /*ADDR @ 206 :
+ P_smo_error_discard [1;6:6] = 0
+ P_smo_rs_discard [1;5:5] = 0
+ P_smo_pid_parse [1;4:4] = 0
+ P_smo_fifo_flush [1;3:3] = 0
+ P_smo_mode [2;2:1] = 11
+ P_smo_ovf_prot [1;0:0] = 0
+ */
+ smo_reg = (0 << 6) | (0 << 5) | (0 << 4) | (0 << 3) |(3 << 1) | 0;
+ fifo_threshold = 512;
+ outmode = 5;
+ break;
+ case OUTMODE_DIVERSITY:
+ outmode = 4;
+ elecout = 1;
break;
default:
- warn("unkown constellation.");
+ dprintk("Unhandled output_mode passed to be set for demod %p\n",&state->demod);
+ outmode = 0;
break;
}
- return 0;
+
+ if ((state->cfg->output_mpeg2_in_188_bytes))
+ smo_reg |= (1 << 5) ; //P_smo_rs_discard [1;5:5] = 1
+
+ outreg = dib3000mc_read_word(state, 244) & 0x07FF;
+ outreg |= (outmode << 11);
+ ret |= dib3000mc_write_word(state, 244, outreg);
+ ret |= dib3000mc_write_word(state, 206, smo_reg); /*smo_ mode*/
+ ret |= dib3000mc_write_word(state, 207, fifo_threshold); /* synchronous fread */
+ ret |= dib3000mc_write_word(state, 1040, elecout); /* P_out_cfg */
+ return ret;
}
-static int dib3000mc_set_general_cfg(struct dib3000_state *state, struct dvb_frontend_parameters *fep, int *auto_val)
+static int dib3000mc_set_bandwidth(struct dvb_frontend *demod, u8 bw)
{
- struct dvb_ofdm_parameters *ofdm = &fep->u.ofdm;
- fe_code_rate_t fe_cr = FEC_NONE;
- u8 fft=0, guard=0, qam=0, alpha=0, sel_hp=0, cr=0, hrch=0;
- int seq;
+ struct dib3000mc_state *state = demod->demodulator_priv;
+ u16 bw_cfg[6] = { 0 };
+ u16 imp_bw_cfg[3] = { 0 };
+ u16 reg;
- switch (ofdm->transmission_mode) {
- case TRANSMISSION_MODE_2K: fft = DIB3000_TRANSMISSION_MODE_2K; break;
- case TRANSMISSION_MODE_8K: fft = DIB3000_TRANSMISSION_MODE_8K; break;
- case TRANSMISSION_MODE_AUTO: break;
- default: return -EINVAL;
- }
- switch (ofdm->guard_interval) {
- case GUARD_INTERVAL_1_32: guard = DIB3000_GUARD_TIME_1_32; break;
- case GUARD_INTERVAL_1_16: guard = DIB3000_GUARD_TIME_1_16; break;
- case GUARD_INTERVAL_1_8: guard = DIB3000_GUARD_TIME_1_8; break;
- case GUARD_INTERVAL_1_4: guard = DIB3000_GUARD_TIME_1_4; break;
- case GUARD_INTERVAL_AUTO: break;
- default: return -EINVAL;
- }
- switch (ofdm->constellation) {
- case QPSK: qam = DIB3000_CONSTELLATION_QPSK; break;
- case QAM_16: qam = DIB3000_CONSTELLATION_16QAM; break;
- case QAM_64: qam = DIB3000_CONSTELLATION_64QAM; break;
- case QAM_AUTO: break;
- default: return -EINVAL;
- }
- switch (ofdm->hierarchy_information) {
- case HIERARCHY_NONE: /* fall through */
- case HIERARCHY_1: alpha = DIB3000_ALPHA_1; break;
- case HIERARCHY_2: alpha = DIB3000_ALPHA_2; break;
- case HIERARCHY_4: alpha = DIB3000_ALPHA_4; break;
- case HIERARCHY_AUTO: break;
- default: return -EINVAL;
- }
- if (ofdm->hierarchy_information == HIERARCHY_NONE) {
- hrch = DIB3000_HRCH_OFF;
- sel_hp = DIB3000_SELECT_HP;
- fe_cr = ofdm->code_rate_HP;
- } else if (ofdm->hierarchy_information != HIERARCHY_AUTO) {
- hrch = DIB3000_HRCH_ON;
- sel_hp = DIB3000_SELECT_LP;
- fe_cr = ofdm->code_rate_LP;
- }
- switch (fe_cr) {
- case FEC_1_2: cr = DIB3000_FEC_1_2; break;
- case FEC_2_3: cr = DIB3000_FEC_2_3; break;
- case FEC_3_4: cr = DIB3000_FEC_3_4; break;
- case FEC_5_6: cr = DIB3000_FEC_5_6; break;
- case FEC_7_8: cr = DIB3000_FEC_7_8; break;
- case FEC_NONE: break;
- case FEC_AUTO: break;
- default: return -EINVAL;
- }
+/* settings here are for 27.7MHz */
+ switch (bw) {
+ case BANDWIDTH_8_MHZ:
+ bw_cfg[0] = 0x0019; bw_cfg[1] = 0x5c30; bw_cfg[2] = 0x0054; bw_cfg[3] = 0x88a0; bw_cfg[4] = 0x01a6; bw_cfg[5] = 0xab20;
+ imp_bw_cfg[0] = 0x04db; imp_bw_cfg[1] = 0x00db; imp_bw_cfg[2] = 0x00b7;
+ break;
- wr(DIB3000MC_REG_DEMOD_PARM,DIB3000MC_DEMOD_PARM(alpha,qam,guard,fft));
- wr(DIB3000MC_REG_HRCH_PARM,DIB3000MC_HRCH_PARM(sel_hp,cr,hrch));
+ case BANDWIDTH_7_MHZ:
+ bw_cfg[0] = 0x001c; bw_cfg[1] = 0xfba5; bw_cfg[2] = 0x0060; bw_cfg[3] = 0x9c25; bw_cfg[4] = 0x01e3; bw_cfg[5] = 0x0cb7;
+ imp_bw_cfg[0] = 0x04c0; imp_bw_cfg[1] = 0x00c0; imp_bw_cfg[2] = 0x00a0;
+ break;
- switch (fep->inversion) {
- case INVERSION_OFF:
- wr(DIB3000MC_REG_SET_DDS_FREQ_MSB,DIB3000MC_DDS_FREQ_MSB_INV_OFF);
+ case BANDWIDTH_6_MHZ:
+ bw_cfg[0] = 0x0021; bw_cfg[1] = 0xd040; bw_cfg[2] = 0x0070; bw_cfg[3] = 0xb62b; bw_cfg[4] = 0x0233; bw_cfg[5] = 0x8ed5;
+ imp_bw_cfg[0] = 0x04a5; imp_bw_cfg[1] = 0x00a5; imp_bw_cfg[2] = 0x0089;
break;
- case INVERSION_AUTO: /* fall through */
- case INVERSION_ON:
- wr(DIB3000MC_REG_SET_DDS_FREQ_MSB,DIB3000MC_DDS_FREQ_MSB_INV_ON);
+
+ case 255 /* BANDWIDTH_5_MHZ */:
+ bw_cfg[0] = 0x0028; bw_cfg[1] = 0x9380; bw_cfg[2] = 0x0087; bw_cfg[3] = 0x4100; bw_cfg[4] = 0x02a4; bw_cfg[5] = 0x4500;
+ imp_bw_cfg[0] = 0x0489; imp_bw_cfg[1] = 0x0089; imp_bw_cfg[2] = 0x0072;
break;
- default:
- return -EINVAL;
+
+ default: return -EINVAL;
}
- seq = dib3000_seq
- [ofdm->transmission_mode == TRANSMISSION_MODE_AUTO]
- [ofdm->guard_interval == GUARD_INTERVAL_AUTO]
- [fep->inversion == INVERSION_AUTO];
-
- deb_setf("seq? %d\n", seq);
- wr(DIB3000MC_REG_SEQ_TPS,DIB3000MC_SEQ_TPS(seq,1));
- *auto_val = ofdm->constellation == QAM_AUTO ||
- ofdm->hierarchy_information == HIERARCHY_AUTO ||
- ofdm->guard_interval == GUARD_INTERVAL_AUTO ||
- ofdm->transmission_mode == TRANSMISSION_MODE_AUTO ||
- fe_cr == FEC_AUTO ||
- fep->inversion == INVERSION_AUTO;
- return 0;
-}
+ for (reg = 6; reg < 12; reg++)
+ dib3000mc_write_word(state, reg, bw_cfg[reg - 6]);
+ dib3000mc_write_word(state, 12, 0x0000);
+ dib3000mc_write_word(state, 13, 0x03e8);
+ dib3000mc_write_word(state, 14, 0x0000);
+ dib3000mc_write_word(state, 15, 0x03f2);
+ dib3000mc_write_word(state, 16, 0x0001);
+ dib3000mc_write_word(state, 17, 0xb0d0);
+ // P_sec_len
+ dib3000mc_write_word(state, 18, 0x0393);
+ dib3000mc_write_word(state, 19, 0x8700);
-static int dib3000mc_get_frontend(struct dvb_frontend* fe,
- struct dvb_frontend_parameters *fep)
-{
- struct dib3000_state* state = fe->demodulator_priv;
- struct dvb_ofdm_parameters *ofdm = &fep->u.ofdm;
- fe_code_rate_t *cr;
- u16 tps_val,cr_val;
- int inv_test1,inv_test2;
- u32 dds_val, threshold = 0x1000000;
-
- if (!(rd(DIB3000MC_REG_LOCK_507) & DIB3000MC_LOCK_507))
- return 0;
-
- dds_val = (rd(DIB3000MC_REG_DDS_FREQ_MSB) << 16) + rd(DIB3000MC_REG_DDS_FREQ_LSB);
- deb_getf("DDS_FREQ: %6x\n",dds_val);
- if (dds_val < threshold)
- inv_test1 = 0;
- else if (dds_val == threshold)
- inv_test1 = 1;
- else
- inv_test1 = 2;
-
- dds_val = (rd(DIB3000MC_REG_SET_DDS_FREQ_MSB) << 16) + rd(DIB3000MC_REG_SET_DDS_FREQ_LSB);
- deb_getf("DDS_SET_FREQ: %6x\n",dds_val);
- if (dds_val < threshold)
- inv_test2 = 0;
- else if (dds_val == threshold)
- inv_test2 = 1;
- else
- inv_test2 = 2;
+ for (reg = 55; reg < 58; reg++)
+ dib3000mc_write_word(state, reg, imp_bw_cfg[reg - 55]);
- fep->inversion =
- ((inv_test2 == 2) && (inv_test1==1 || inv_test1==0)) ||
- ((inv_test2 == 0) && (inv_test1==1 || inv_test1==2)) ?
- INVERSION_ON : INVERSION_OFF;
+ // Timing configuration
+ dib3000mc_set_timing(state, 0, bw, 0);
- deb_getf("inversion %d %d, %d\n", inv_test2, inv_test1, fep->inversion);
+ return 0;
+}
- fep->frequency = state->last_tuned_freq;
- fep->u.ofdm.bandwidth= state->last_tuned_bw;
+static u16 impulse_noise_val[29] =
- tps_val = rd(DIB3000MC_REG_TUNING_PARM);
+{
+ 0x38, 0x6d9, 0x3f28, 0x7a7, 0x3a74, 0x196, 0x32a, 0x48c, 0x3ffe, 0x7f3,
+ 0x2d94, 0x76, 0x53d, 0x3ff8, 0x7e3, 0x3320, 0x76, 0x5b3, 0x3feb, 0x7d2,
+ 0x365e, 0x76, 0x48c, 0x3ffe, 0x5b3, 0x3feb, 0x76, 0x0000, 0xd
+};
- switch (DIB3000MC_TP_QAM(tps_val)) {
- case DIB3000_CONSTELLATION_QPSK:
- deb_getf("QPSK ");
- ofdm->constellation = QPSK;
- break;
- case DIB3000_CONSTELLATION_16QAM:
- deb_getf("QAM16 ");
- ofdm->constellation = QAM_16;
- break;
- case DIB3000_CONSTELLATION_64QAM:
- deb_getf("QAM64 ");
- ofdm->constellation = QAM_64;
- break;
- default:
- err("Unexpected constellation returned by TPS (%d)", tps_val);
- break;
+static void dib3000mc_set_impulse_noise(struct dib3000mc_state *state, u8 mode, s16 nfft)
+{
+ u16 i;
+ for (i = 58; i < 87; i++)
+ dib3000mc_write_word(state, i, impulse_noise_val[i-58]);
+
+ if (nfft == 1) {
+ dib3000mc_write_word(state, 58, 0x3b);
+ dib3000mc_write_word(state, 84, 0x00);
+ dib3000mc_write_word(state, 85, 0x8200);
}
- if (DIB3000MC_TP_HRCH(tps_val)) {
- deb_getf("HRCH ON ");
- cr = &ofdm->code_rate_LP;
- ofdm->code_rate_HP = FEC_NONE;
- switch (DIB3000MC_TP_ALPHA(tps_val)) {
- case DIB3000_ALPHA_0:
- deb_getf("HIERARCHY_NONE ");
- ofdm->hierarchy_information = HIERARCHY_NONE;
- break;
- case DIB3000_ALPHA_1:
- deb_getf("HIERARCHY_1 ");
- ofdm->hierarchy_information = HIERARCHY_1;
- break;
- case DIB3000_ALPHA_2:
- deb_getf("HIERARCHY_2 ");
- ofdm->hierarchy_information = HIERARCHY_2;
- break;
- case DIB3000_ALPHA_4:
- deb_getf("HIERARCHY_4 ");
- ofdm->hierarchy_information = HIERARCHY_4;
- break;
- default:
- err("Unexpected ALPHA value returned by TPS (%d)", tps_val);
- break;
- }
- cr_val = DIB3000MC_TP_FEC_CR_LP(tps_val);
+ dib3000mc_write_word(state, 34, 0x1294);
+ dib3000mc_write_word(state, 35, 0x1ff8);
+ if (mode == 1)
+ dib3000mc_write_word(state, 55, dib3000mc_read_word(state, 55) | (1 << 10));
+}
+
+static int dib3000mc_init(struct dvb_frontend *demod)
+{
+ struct dib3000mc_state *state = demod->demodulator_priv;
+ struct dibx000_agc_config *agc = state->cfg->agc;
+
+ // Restart Configuration
+ dib3000mc_write_word(state, 1027, 0x8000);
+ dib3000mc_write_word(state, 1027, 0x0000);
+
+ // power up the demod + mobility configuration
+ dib3000mc_write_word(state, 140, 0x0000);
+ dib3000mc_write_word(state, 1031, 0);
+
+ if (state->cfg->mobile_mode) {
+ dib3000mc_write_word(state, 139, 0x0000);
+ dib3000mc_write_word(state, 141, 0x0000);
+ dib3000mc_write_word(state, 175, 0x0002);
+ dib3000mc_write_word(state, 1032, 0x0000);
} else {
- deb_getf("HRCH OFF ");
- cr = &ofdm->code_rate_HP;
- ofdm->code_rate_LP = FEC_NONE;
- ofdm->hierarchy_information = HIERARCHY_NONE;
- cr_val = DIB3000MC_TP_FEC_CR_HP(tps_val);
+ dib3000mc_write_word(state, 139, 0x0001);
+ dib3000mc_write_word(state, 141, 0x0000);
+ dib3000mc_write_word(state, 175, 0x0000);
+ dib3000mc_write_word(state, 1032, 0x012C);
}
+ dib3000mc_write_word(state, 1033, 0);
- switch (cr_val) {
- case DIB3000_FEC_1_2:
- deb_getf("FEC_1_2 ");
- *cr = FEC_1_2;
- break;
- case DIB3000_FEC_2_3:
- deb_getf("FEC_2_3 ");
- *cr = FEC_2_3;
- break;
- case DIB3000_FEC_3_4:
- deb_getf("FEC_3_4 ");
- *cr = FEC_3_4;
- break;
- case DIB3000_FEC_5_6:
- deb_getf("FEC_5_6 ");
- *cr = FEC_4_5;
- break;
- case DIB3000_FEC_7_8:
- deb_getf("FEC_7_8 ");
- *cr = FEC_7_8;
- break;
- default:
- err("Unexpected FEC returned by TPS (%d)", tps_val);
- break;
- }
+ // P_clk_cfg
+ dib3000mc_write_word(state, 1037, 12592);
- switch (DIB3000MC_TP_GUARD(tps_val)) {
- case DIB3000_GUARD_TIME_1_32:
- deb_getf("GUARD_INTERVAL_1_32 ");
- ofdm->guard_interval = GUARD_INTERVAL_1_32;
- break;
- case DIB3000_GUARD_TIME_1_16:
- deb_getf("GUARD_INTERVAL_1_16 ");
- ofdm->guard_interval = GUARD_INTERVAL_1_16;
- break;
- case DIB3000_GUARD_TIME_1_8:
- deb_getf("GUARD_INTERVAL_1_8 ");
- ofdm->guard_interval = GUARD_INTERVAL_1_8;
- break;
- case DIB3000_GUARD_TIME_1_4:
- deb_getf("GUARD_INTERVAL_1_4 ");
- ofdm->guard_interval = GUARD_INTERVAL_1_4;
- break;
- default:
- err("Unexpected Guard Time returned by TPS (%d)", tps_val);
- break;
- }
+ // other configurations
- switch (DIB3000MC_TP_FFT(tps_val)) {
- case DIB3000_TRANSMISSION_MODE_2K:
- deb_getf("TRANSMISSION_MODE_2K ");
- ofdm->transmission_mode = TRANSMISSION_MODE_2K;
- break;
- case DIB3000_TRANSMISSION_MODE_8K:
- deb_getf("TRANSMISSION_MODE_8K ");
- ofdm->transmission_mode = TRANSMISSION_MODE_8K;
- break;
- default:
- err("unexpected transmission mode return by TPS (%d)", tps_val);
- break;
- }
- deb_getf("\n");
+ // P_ctrl_sfreq
+ dib3000mc_write_word(state, 33, (5 << 0));
+ dib3000mc_write_word(state, 88, (1 << 10) | (0x10 << 0));
+
+ // Phase noise control
+ // P_fft_phacor_inh, P_fft_phacor_cpe, P_fft_powrange
+ dib3000mc_write_word(state, 99, (1 << 9) | (0x20 << 0));
+
+ if (state->cfg->phase_noise_mode == 0)
+ dib3000mc_write_word(state, 111, 0x00);
+ else
+ dib3000mc_write_word(state, 111, 0x02);
+
+ // P_agc_global
+ dib3000mc_write_word(state, 50, 0x8000);
+
+ // agc setup misc
+ dib3000mc_setup_pwm3_state(state);
+
+ // P_agc_counter_lock
+ dib3000mc_write_word(state, 53, 0x87);
+ // P_agc_counter_unlock
+ dib3000mc_write_word(state, 54, 0x87);
+
+ /* agc */
+ dib3000mc_write_word(state, 36, state->cfg->max_time);
+ dib3000mc_write_word(state, 37, agc->setup);
+ dib3000mc_write_word(state, 38, state->cfg->pwm3_value);
+ dib3000mc_write_word(state, 39, state->cfg->ln_adc_level);
+
+ // set_agc_loop_Bw
+ dib3000mc_write_word(state, 40, 0x0179);
+ dib3000mc_write_word(state, 41, 0x03f0);
+
+ dib3000mc_write_word(state, 42, agc->agc1_max);
+ dib3000mc_write_word(state, 43, agc->agc1_min);
+ dib3000mc_write_word(state, 44, agc->agc2_max);
+ dib3000mc_write_word(state, 45, agc->agc2_min);
+ dib3000mc_write_word(state, 46, (agc->agc1_pt1 << 8) | agc->agc1_pt2);
+ dib3000mc_write_word(state, 47, (agc->agc1_slope1 << 8) | agc->agc1_slope2);
+ dib3000mc_write_word(state, 48, (agc->agc2_pt1 << 8) | agc->agc2_pt2);
+ dib3000mc_write_word(state, 49, (agc->agc2_slope1 << 8) | agc->agc2_slope2);
+
+// Begin: TimeOut registers
+ // P_pha3_thres
+ dib3000mc_write_word(state, 110, 3277);
+ // P_timf_alpha = 6, P_corm_alpha = 6, P_corm_thres = 0x80
+ dib3000mc_write_word(state, 26, 0x6680);
+ // lock_mask0
+ dib3000mc_write_word(state, 1, 4);
+ // lock_mask1
+ dib3000mc_write_word(state, 2, 4);
+ // lock_mask2
+ dib3000mc_write_word(state, 3, 0x1000);
+ // P_search_maxtrial=1
+ dib3000mc_write_word(state, 5, 1);
+
+ dib3000mc_set_bandwidth(&state->demod, BANDWIDTH_8_MHZ);
+
+ // div_lock_mask
+ dib3000mc_write_word(state, 4, 0x814);
+
+ dib3000mc_write_word(state, 21, (1 << 9) | 0x164);
+ dib3000mc_write_word(state, 22, 0x463d);
+
+ // Spurious rm cfg
+ // P_cspu_regul, P_cspu_win_cut
+ dib3000mc_write_word(state, 120, 0x200f);
+ // P_adp_selec_monit
+ dib3000mc_write_word(state, 134, 0);
+
+ // Fec cfg
+ dib3000mc_write_word(state, 195, 0x10);
+
+ // diversity register: P_dvsy_sync_wait..
+ dib3000mc_write_word(state, 180, 0x2FF0);
+
+ // Impulse noise configuration
+ dib3000mc_set_impulse_noise(state, 0, 1);
+
+ // output mode set-up
+ dib3000mc_set_output_mode(state, OUTMODE_HIGH_Z);
+
+ /* close the i2c-gate */
+ dib3000mc_write_word(state, 769, (1 << 7) );
return 0;
}
-static int dib3000mc_set_frontend(struct dvb_frontend* fe,
- struct dvb_frontend_parameters *fep, int tuner)
+static int dib3000mc_sleep(struct dvb_frontend *demod)
{
- struct dib3000_state* state = fe->demodulator_priv;
- struct dvb_ofdm_parameters *ofdm = &fep->u.ofdm;
- int search_state,auto_val;
- u16 val;
-
- if (tuner && fe->ops.tuner_ops.set_params) { /* initial call from dvb */
- fe->ops.tuner_ops.set_params(fe, fep);
- if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
-
- state->last_tuned_freq = fep->frequency;
- // if (!scanboost) {
- dib3000mc_set_timing(state,0,ofdm->transmission_mode,ofdm->bandwidth);
- dib3000mc_init_auto_scan(state, ofdm->bandwidth, 0);
- state->last_tuned_bw = ofdm->bandwidth;
-
- wr_foreach(dib3000mc_reg_agc_bandwidth,dib3000mc_agc_bandwidth);
- wr(DIB3000MC_REG_RESTART,DIB3000MC_RESTART_AGC);
- wr(DIB3000MC_REG_RESTART,DIB3000MC_RESTART_OFF);
-
- /* Default cfg isi offset adp */
- wr_foreach(dib3000mc_reg_offset,dib3000mc_offset[0]);
-
- wr(DIB3000MC_REG_ISI,DIB3000MC_ISI_DEFAULT | DIB3000MC_ISI_INHIBIT);
- dib3000mc_set_adp_cfg(state,ofdm->constellation);
- wr(DIB3000MC_REG_UNK_133,DIB3000MC_UNK_133);
-
- wr_foreach(dib3000mc_reg_bandwidth_general,dib3000mc_bandwidth_general);
- /* power smoothing */
- if (ofdm->bandwidth != BANDWIDTH_8_MHZ) {
- wr_foreach(dib3000mc_reg_bw,dib3000mc_bw[0]);
- } else {
- wr_foreach(dib3000mc_reg_bw,dib3000mc_bw[3]);
- }
- auto_val = 0;
- dib3000mc_set_general_cfg(state,fep,&auto_val);
- dib3000mc_set_impulse_noise(state,0,ofdm->constellation,ofdm->bandwidth);
-
- val = rd(DIB3000MC_REG_DEMOD_PARM);
- wr(DIB3000MC_REG_DEMOD_PARM,val|DIB3000MC_DEMOD_RST_DEMOD_ON);
- wr(DIB3000MC_REG_DEMOD_PARM,val);
- // }
- msleep(70);
-
- /* something has to be auto searched */
- if (auto_val) {
- int as_count=0;
-
- deb_setf("autosearch enabled.\n");
-
- val = rd(DIB3000MC_REG_DEMOD_PARM);
- wr(DIB3000MC_REG_DEMOD_PARM,val | DIB3000MC_DEMOD_RST_AUTO_SRCH_ON);
- wr(DIB3000MC_REG_DEMOD_PARM,val);
-
- while ((search_state = dib3000_search_status(
- rd(DIB3000MC_REG_AS_IRQ),1)) < 0 && as_count++ < 100)
- msleep(10);
-
- deb_info("search_state after autosearch %d after %d checks\n",search_state,as_count);
-
- if (search_state == 1) {
- struct dvb_frontend_parameters feps;
- if (dib3000mc_get_frontend(fe, &feps) == 0) {
- deb_setf("reading tuning data from frontend succeeded.\n");
- return dib3000mc_set_frontend(fe, &feps, 0);
- }
- }
- } else {
- dib3000mc_set_impulse_noise(state,0,ofdm->transmission_mode,ofdm->bandwidth);
- wr(DIB3000MC_REG_ISI,DIB3000MC_ISI_DEFAULT|DIB3000MC_ISI_ACTIVATE);
- dib3000mc_set_adp_cfg(state,ofdm->constellation);
-
- /* set_offset_cfg */
- wr_foreach(dib3000mc_reg_offset,
- dib3000mc_offset[(ofdm->transmission_mode == TRANSMISSION_MODE_8K)+1]);
- }
- } else { /* second call, after autosearch (fka: set_WithKnownParams) */
-// dib3000mc_set_timing(state,1,ofdm->transmission_mode,ofdm->bandwidth);
-
- auto_val = 0;
- dib3000mc_set_general_cfg(state,fep,&auto_val);
- if (auto_val)
- deb_info("auto_val is true, even though an auto search was already performed.\n");
+ struct dib3000mc_state *state = demod->demodulator_priv;
- dib3000mc_set_impulse_noise(state,0,ofdm->constellation,ofdm->bandwidth);
+ dib3000mc_write_word(state, 1037, dib3000mc_read_word(state, 1037) | 0x0003);
+ dib3000mc_write_word(state, 1031, 0xFFFF);
+ dib3000mc_write_word(state, 1032, 0xFFFF);
+ dib3000mc_write_word(state, 1033, 0xFFF4); // **** Bin2
- val = rd(DIB3000MC_REG_DEMOD_PARM);
- wr(DIB3000MC_REG_DEMOD_PARM,val | DIB3000MC_DEMOD_RST_AUTO_SRCH_ON);
- wr(DIB3000MC_REG_DEMOD_PARM,val);
-
- msleep(30);
+ return 0;
+}
- wr(DIB3000MC_REG_ISI,DIB3000MC_ISI_DEFAULT|DIB3000MC_ISI_ACTIVATE);
- dib3000mc_set_adp_cfg(state,ofdm->constellation);
- wr_foreach(dib3000mc_reg_offset,
- dib3000mc_offset[(ofdm->transmission_mode == TRANSMISSION_MODE_8K)+1]);
+static void dib3000mc_set_adp_cfg(struct dib3000mc_state *state, s16 qam)
+{
+ u16 cfg[4] = { 0 },reg;
+ switch (qam) {
+ case 0:
+ cfg[0] = 0x099a; cfg[1] = 0x7fae; cfg[2] = 0x0333; cfg[3] = 0x7ff0;
+ break;
+ case 1:
+ cfg[0] = 0x023d; cfg[1] = 0x7fdf; cfg[2] = 0x00a4; cfg[3] = 0x7ff0;
+ break;
+ case 2:
+ cfg[0] = 0x0148; cfg[1] = 0x7ff0; cfg[2] = 0x00a4; cfg[3] = 0x7ff8;
+ break;
}
- return 0;
+ for (reg = 129; reg < 133; reg++)
+ dib3000mc_write_word(state, reg, cfg[reg - 129]);
}
-static int dib3000mc_fe_init(struct dvb_frontend* fe, int mobile_mode)
+static void dib3000mc_set_channel_cfg(struct dib3000mc_state *state, struct dibx000_ofdm_channel *chan, u16 seq)
{
- struct dib3000_state *state = fe->demodulator_priv;
- deb_info("init start\n");
+ u16 tmp;
- state->timing_offset = 0;
- state->timing_offset_comp_done = 0;
+ dib3000mc_set_timing(state, chan->nfft, chan->Bw, 0);
- wr(DIB3000MC_REG_RESTART,DIB3000MC_RESTART_CONFIG);
- wr(DIB3000MC_REG_RESTART,DIB3000MC_RESTART_OFF);
- wr(DIB3000MC_REG_CLK_CFG_1,DIB3000MC_CLK_CFG_1_POWER_UP);
- wr(DIB3000MC_REG_CLK_CFG_2,DIB3000MC_CLK_CFG_2_PUP_MOBILE);
- wr(DIB3000MC_REG_CLK_CFG_3,DIB3000MC_CLK_CFG_3_POWER_UP);
- wr(DIB3000MC_REG_CLK_CFG_7,DIB3000MC_CLK_CFG_7_INIT);
+// if (boost)
+// dib3000mc_write_word(state, 100, (11 << 6) + 6);
+// else
+ dib3000mc_write_word(state, 100, (16 << 6) + 9);
- wr(DIB3000MC_REG_RST_UNC,DIB3000MC_RST_UNC_OFF);
- wr(DIB3000MC_REG_UNK_19,DIB3000MC_UNK_19);
+ dib3000mc_write_word(state, 1027, 0x0800);
+ dib3000mc_write_word(state, 1027, 0x0000);
- wr(33,5);
- wr(36,81);
- wr(DIB3000MC_REG_UNK_88,DIB3000MC_UNK_88);
+ //Default cfg isi offset adp
+ dib3000mc_write_word(state, 26, 0x6680);
+ dib3000mc_write_word(state, 29, 0x1273);
+ dib3000mc_write_word(state, 33, 5);
+ dib3000mc_set_adp_cfg(state, 1);
+ dib3000mc_write_word(state, 133, 15564);
- wr(DIB3000MC_REG_UNK_99,DIB3000MC_UNK_99);
- wr(DIB3000MC_REG_UNK_111,DIB3000MC_UNK_111_PH_N_MODE_0); /* phase noise algo off */
+ dib3000mc_write_word(state, 12 , 0x0);
+ dib3000mc_write_word(state, 13 , 0x3e8);
+ dib3000mc_write_word(state, 14 , 0x0);
+ dib3000mc_write_word(state, 15 , 0x3f2);
- /* mobile mode - portable reception */
- wr_foreach(dib3000mc_reg_mobile_mode,dib3000mc_mobile_mode[1]);
+ dib3000mc_write_word(state, 93,0);
+ dib3000mc_write_word(state, 94,0);
+ dib3000mc_write_word(state, 95,0);
+ dib3000mc_write_word(state, 96,0);
+ dib3000mc_write_word(state, 97,0);
+ dib3000mc_write_word(state, 98,0);
-/* TUNER_PANASONIC_ENV57H12D5: */
- wr_foreach(dib3000mc_reg_agc_bandwidth,dib3000mc_agc_bandwidth);
- wr_foreach(dib3000mc_reg_agc_bandwidth_general,dib3000mc_agc_bandwidth_general);
- wr_foreach(dib3000mc_reg_agc,dib3000mc_agc_tuner[1]);
+ dib3000mc_set_impulse_noise(state, 0, chan->nfft);
- wr(DIB3000MC_REG_UNK_110,DIB3000MC_UNK_110);
- wr(26,0x6680);
- wr(DIB3000MC_REG_UNK_1,DIB3000MC_UNK_1);
- wr(DIB3000MC_REG_UNK_2,DIB3000MC_UNK_2);
- wr(DIB3000MC_REG_UNK_3,DIB3000MC_UNK_3);
- wr(DIB3000MC_REG_SEQ_TPS,DIB3000MC_SEQ_TPS_DEFAULT);
+ tmp = ((chan->nfft & 0x1) << 7) | (chan->guard << 5) | (chan->nqam << 3) | chan->vit_alpha;
+ dib3000mc_write_word(state, 0, tmp);
- wr_foreach(dib3000mc_reg_bandwidth,dib3000mc_bandwidth_8mhz);
- wr_foreach(dib3000mc_reg_bandwidth_general,dib3000mc_bandwidth_general);
+ dib3000mc_write_word(state, 5, seq);
- wr(DIB3000MC_REG_UNK_4,DIB3000MC_UNK_4);
-
- wr(DIB3000MC_REG_SET_DDS_FREQ_MSB,DIB3000MC_DDS_FREQ_MSB_INV_OFF);
- wr(DIB3000MC_REG_SET_DDS_FREQ_LSB,DIB3000MC_DDS_FREQ_LSB);
+ tmp = (chan->vit_hrch << 4) | (chan->vit_select_hp);
+ if (!chan->vit_hrch || (chan->vit_hrch && chan->vit_select_hp))
+ tmp |= chan->vit_code_rate_hp << 1;
+ else
+ tmp |= chan->vit_code_rate_lp << 1;
+ dib3000mc_write_word(state, 181, tmp);
- dib3000mc_set_timing(state,0,TRANSMISSION_MODE_8K,BANDWIDTH_8_MHZ);
-// wr_foreach(dib3000mc_reg_timing_freq,dib3000mc_timing_freq[3]);
+ // diversity synchro delay
+ tmp = dib3000mc_read_word(state, 180) & 0x000f;
+ tmp |= ((chan->nfft == 0) ? 64 : 256) * ((1 << (chan->guard)) * 3 / 2) << 4; // add 50% SFN margin
+ dib3000mc_write_word(state, 180, tmp);
- wr(DIB3000MC_REG_UNK_120,DIB3000MC_UNK_120);
- wr(DIB3000MC_REG_UNK_134,DIB3000MC_UNK_134);
- wr(DIB3000MC_REG_FEC_CFG,DIB3000MC_FEC_CFG);
+ // restart demod
+ tmp = dib3000mc_read_word(state, 0);
+ dib3000mc_write_word(state, 0, tmp | (1 << 9));
+ dib3000mc_write_word(state, 0, tmp);
- wr(DIB3000MC_REG_DIVERSITY3,DIB3000MC_DIVERSITY3_IN_OFF);
+ msleep(30);
- dib3000mc_set_impulse_noise(state,0,TRANSMISSION_MODE_8K,BANDWIDTH_8_MHZ);
+ dib3000mc_set_impulse_noise(state, state->cfg->impulse_noise_mode, chan->nfft);
+}
-/* output mode control, just the MPEG2_SLAVE */
-// set_or(DIB3000MC_REG_OUTMODE,DIB3000MC_OM_SLAVE);
- wr(DIB3000MC_REG_OUTMODE,DIB3000MC_OM_SLAVE);
- wr(DIB3000MC_REG_SMO_MODE,DIB3000MC_SMO_MODE_SLAVE);
- wr(DIB3000MC_REG_FIFO_THRESHOLD,DIB3000MC_FIFO_THRESHOLD_SLAVE);
- wr(DIB3000MC_REG_ELEC_OUT,DIB3000MC_ELEC_OUT_SLAVE);
+static int dib3000mc_autosearch_start(struct dvb_frontend *demod, struct dibx000_ofdm_channel *chan)
+{
+ struct dib3000mc_state *state = demod->demodulator_priv;
+ u16 reg;
+// u32 val;
+ struct dibx000_ofdm_channel fchan;
-/* MPEG2_PARALLEL_CONTINUOUS_CLOCK
- wr(DIB3000MC_REG_OUTMODE,
- DIB3000MC_SET_OUTMODE(DIB3000MC_OM_PAR_CONT_CLK,
- rd(DIB3000MC_REG_OUTMODE)));
+ INIT_OFDM_CHANNEL(&fchan);
+ fchan = *chan;
- wr(DIB3000MC_REG_SMO_MODE,
- DIB3000MC_SMO_MODE_DEFAULT |
- DIB3000MC_SMO_MODE_188);
+#if 0
+ if (boost) {
+ val = (dib3000mc_read_word(state, 6) << 16) | dib3000mc_read_word(state, 7);
+ val *= 85;
+ val >>= 7;
+ dib3000mc_write_word(state, 6, (val >> 16) & 0xffff);
+ dib3000mc_write_word(state, 7, (val ) & 0xffff);
+ }
+#endif
- wr(DIB3000MC_REG_FIFO_THRESHOLD,DIB3000MC_FIFO_THRESHOLD_DEFAULT);
- wr(DIB3000MC_REG_ELEC_OUT,DIB3000MC_ELEC_OUT_DIV_OUT_ON);
-*/
+ /* a channel for autosearch */
+ reg = 0;
+ if (chan->nfft == -1 && chan->guard == -1) reg = 7;
+ if (chan->nfft == -1 && chan->guard != -1) reg = 2;
+ if (chan->nfft != -1 && chan->guard == -1) reg = 3;
-/* diversity */
- wr(DIB3000MC_REG_DIVERSITY1,DIB3000MC_DIVERSITY1_DEFAULT);
- wr(DIB3000MC_REG_DIVERSITY2,DIB3000MC_DIVERSITY2_DEFAULT);
+ fchan.nfft = 1; fchan.guard = 0; fchan.nqam = 2;
+ fchan.vit_alpha = 1; fchan.vit_code_rate_hp = 2; fchan.vit_code_rate_lp = 2;
+ fchan.vit_hrch = 0; fchan.vit_select_hp = 1;
- set_and(DIB3000MC_REG_DIVERSITY3,DIB3000MC_DIVERSITY3_IN_OFF);
+ dib3000mc_set_channel_cfg(state, &fchan, reg);
- set_or(DIB3000MC_REG_CLK_CFG_7,DIB3000MC_CLK_CFG_7_DIV_IN_OFF);
+ reg = dib3000mc_read_word(state, 0);
+ dib3000mc_write_word(state, 0, reg | (1 << 8));
+ dib3000mc_write_word(state, 0, reg);
- deb_info("init end\n");
return 0;
}
-static int dib3000mc_read_status(struct dvb_frontend* fe, fe_status_t *stat)
+
+static int dib3000mc_autosearch_is_irq(struct dvb_frontend *demod)
{
- struct dib3000_state* state = fe->demodulator_priv;
- u16 lock = rd(DIB3000MC_REG_LOCKING);
+ struct dib3000mc_state *state = demod->demodulator_priv;
+ u16 irq_pending = dib3000mc_read_word(state, 511);
- *stat = 0;
- if (DIB3000MC_AGC_LOCK(lock))
- *stat |= FE_HAS_SIGNAL;
- if (DIB3000MC_CARRIER_LOCK(lock))
- *stat |= FE_HAS_CARRIER;
- if (DIB3000MC_TPS_LOCK(lock))
- *stat |= FE_HAS_VITERBI;
- if (DIB3000MC_MPEG_SYNC_LOCK(lock))
- *stat |= (FE_HAS_SYNC | FE_HAS_LOCK);
+ if (irq_pending & 0x1) // failed
+ return 1;
- deb_stat("actual status is %2x fifo_level: %x,244: %x, 206: %x, 207: %x, 1040: %x\n",*stat,rd(510),rd(244),rd(206),rd(207),rd(1040));
+ if (irq_pending & 0x2) // succeeded
+ return 2;
- return 0;
+ return 0; // still pending
}
-static int dib3000mc_read_ber(struct dvb_frontend* fe, u32 *ber)
+static int dib3000mc_tune(struct dvb_frontend *demod, struct dibx000_ofdm_channel *ch)
{
- struct dib3000_state* state = fe->demodulator_priv;
- *ber = ((rd(DIB3000MC_REG_BER_MSB) << 16) | rd(DIB3000MC_REG_BER_LSB));
+ struct dib3000mc_state *state = demod->demodulator_priv;
+
+ // ** configure demod **
+ dib3000mc_set_channel_cfg(state, ch, 0);
+
+ // activates isi
+ dib3000mc_write_word(state, 29, 0x1073);
+
+ dib3000mc_set_adp_cfg(state, (u8)ch->nqam);
+
+ if (ch->nfft == 1) {
+ dib3000mc_write_word(state, 26, 38528);
+ dib3000mc_write_word(state, 33, 8);
+ } else {
+ dib3000mc_write_word(state, 26, 30336);
+ dib3000mc_write_word(state, 33, 6);
+ }
+
+ // if (lock)
+ // dib3000mc_set_timing(state, ch->nfft, ch->Bw, 1);
+
return 0;
}
-static int dib3000mc_read_unc_blocks(struct dvb_frontend* fe, u32 *unc)
+static int dib3000mc_demod_output_mode(struct dvb_frontend *demod, int mode)
{
- struct dib3000_state* state = fe->demodulator_priv;
-
- *unc = rd(DIB3000MC_REG_PACKET_ERRORS);
- return 0;
+ struct dib3000mc_state *state = demod->demodulator_priv;
+ return dib3000mc_set_output_mode(state, mode);
}
-/* see dib3000mb.c for calculation comments */
-static int dib3000mc_read_signal_strength(struct dvb_frontend* fe, u16 *strength)
+static int dib3000mc_i2c_enumeration(struct dvb_frontend *demod[], int no_of_demods, u8 default_addr)
{
- struct dib3000_state* state = fe->demodulator_priv;
- u16 val = rd(DIB3000MC_REG_SIGNAL_NOISE_LSB);
- *strength = (((val >> 6) & 0xff) << 8) + (val & 0x3f);
+ struct dib3000mc_state *st;
+ int k,ret=0;
+ u8 new_addr;
+
+ static u8 DIB3000MC_I2C_ADDRESS[] = {20,22,24,26};
+
+ for (k = no_of_demods-1; k >= 0; k--) {
+ st = demod[k]->demodulator_priv;
- deb_stat("signal: mantisse = %d, exponent = %d\n",(*strength >> 8) & 0xff, *strength & 0xff);
+ /* designated i2c address */
+ new_addr = DIB3000MC_I2C_ADDRESS[k];
+
+ st->i2c_addr = new_addr;
+ if (dib3000mc_identify(st) != 0) {
+ st->i2c_addr = default_addr;
+ if (dib3000mc_identify(st) != 0) {
+ dprintk("-E- DiB3000P/MC #%d: not identified\n", k);
+ return -EINVAL;
+ }
+ }
+
+ /* turn on div_out */
+ dib3000mc_demod_output_mode(demod[k], OUTMODE_MPEG2_PAR_CONT_CLK);
+
+ // set new i2c address and force divstr (Bit 1) to value 0 (Bit 0)
+ ret |= dib3000mc_write_word(st, 1024, (new_addr << 3) | 0x1);
+ st->i2c_addr = new_addr;
+ }
+
+ for (k = 0; k < no_of_demods; k++) {
+ st = demod[k]->demodulator_priv;
+
+ ret |= dib3000mc_write_word(st, 1024, st->i2c_addr << 3);
+
+ /* turn off data output */
+ dib3000mc_demod_output_mode(demod[k],OUTMODE_HIGH_Z);
+ dib3000mc_write_word(st, 769, (1 << 7) );
+
+ }
return 0;
}
-/* see dib3000mb.c for calculation comments */
-static int dib3000mc_read_snr(struct dvb_frontend* fe, u16 *snr)
+struct i2c_adapter * dib3000mc_get_tuner_i2c_master(struct dvb_frontend *demod, int gating)
{
- struct dib3000_state* state = fe->demodulator_priv;
- u16 val = rd(DIB3000MC_REG_SIGNAL_NOISE_LSB),
- val2 = rd(DIB3000MC_REG_SIGNAL_NOISE_MSB);
- u16 sig,noise;
+ struct dib3000mc_state *st = demod->demodulator_priv;
+ return dibx000_get_i2c_adapter(&st->i2c_master, DIBX000_I2C_INTERFACE_TUNER, gating);
+}
- sig = (((val >> 6) & 0xff) << 8) + (val & 0x3f);
- noise = (((val >> 4) & 0xff) << 8) + ((val & 0xf) << 2) + ((val2 >> 14) & 0x3);
- if (noise == 0)
- *snr = 0xffff;
- else
- *snr = (u16) sig/noise;
+EXPORT_SYMBOL(dib3000mc_get_tuner_i2c_master);
+
+static int dib3000mc_get_frontend(struct dvb_frontend* fe,
+ struct dvb_frontend_parameters *fep)
+{
+ struct dib3000mc_state *state = fe->demodulator_priv;
+ u16 tps = dib3000mc_read_word(state,458);
+
+ fep->inversion = INVERSION_AUTO;
+
+ fep->u.ofdm.bandwidth = state->current_bandwidth;
+
+ switch ((tps >> 8) & 0x1) {
+ case 0: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_2K; break;
+ case 1: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_8K; break;
+ }
+
+ switch (tps & 0x3) {
+ case 0: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_32; break;
+ case 1: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_16; break;
+ case 2: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_8; break;
+ case 3: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_4; break;
+ }
+
+ switch ((tps >> 13) & 0x3) {
+ case 0: fep->u.ofdm.constellation = QPSK; break;
+ case 1: fep->u.ofdm.constellation = QAM_16; break;
+ case 2:
+ default: fep->u.ofdm.constellation = QAM_64; break;
+ }
+
+ /* as long as the frontend_param structure is fixed for hierarchical transmission I refuse to use it */
+ /* (tps >> 12) & 0x1 == hrch is used, (tps >> 9) & 0x7 == alpha */
+
+ fep->u.ofdm.hierarchy_information = HIERARCHY_NONE;
+ switch ((tps >> 5) & 0x7) {
+ case 1: fep->u.ofdm.code_rate_HP = FEC_1_2; break;
+ case 2: fep->u.ofdm.code_rate_HP = FEC_2_3; break;
+ case 3: fep->u.ofdm.code_rate_HP = FEC_3_4; break;
+ case 5: fep->u.ofdm.code_rate_HP = FEC_5_6; break;
+ case 7:
+ default: fep->u.ofdm.code_rate_HP = FEC_7_8; break;
+
+ }
+
+ switch ((tps >> 2) & 0x7) {
+ case 1: fep->u.ofdm.code_rate_LP = FEC_1_2; break;
+ case 2: fep->u.ofdm.code_rate_LP = FEC_2_3; break;
+ case 3: fep->u.ofdm.code_rate_LP = FEC_3_4; break;
+ case 5: fep->u.ofdm.code_rate_LP = FEC_5_6; break;
+ case 7:
+ default: fep->u.ofdm.code_rate_LP = FEC_7_8; break;
+ }
- deb_stat("signal: mantisse = %d, exponent = %d\n",(sig >> 8) & 0xff, sig & 0xff);
- deb_stat("noise: mantisse = %d, exponent = %d\n",(noise >> 8) & 0xff, noise & 0xff);
- deb_stat("snr: %d\n",*snr);
return 0;
}
-static int dib3000mc_sleep(struct dvb_frontend* fe)
+static int dib3000mc_set_frontend(struct dvb_frontend* fe,
+ struct dvb_frontend_parameters *fep)
{
- struct dib3000_state* state = fe->demodulator_priv;
+ struct dib3000mc_state *state = fe->demodulator_priv;
+ struct dibx000_ofdm_channel ch;
- set_or(DIB3000MC_REG_CLK_CFG_7,DIB3000MC_CLK_CFG_7_PWR_DOWN);
- wr(DIB3000MC_REG_CLK_CFG_1,DIB3000MC_CLK_CFG_1_POWER_DOWN);
- wr(DIB3000MC_REG_CLK_CFG_2,DIB3000MC_CLK_CFG_2_POWER_DOWN);
- wr(DIB3000MC_REG_CLK_CFG_3,DIB3000MC_CLK_CFG_3_POWER_DOWN);
- return 0;
+ INIT_OFDM_CHANNEL(&ch);
+ FEP2DIB(fep,&ch);
+
+ dump_fep(&ch);
+
+ state->current_bandwidth = fep->u.ofdm.bandwidth;
+ dib3000mc_set_bandwidth(fe, fep->u.ofdm.bandwidth);
+
+ if (fe->ops.tuner_ops.set_params) {
+ fe->ops.tuner_ops.set_params(fe, fep);
+ msleep(100);
+ }
+
+ if (fep->u.ofdm.transmission_mode == TRANSMISSION_MODE_AUTO ||
+ fep->u.ofdm.guard_interval == GUARD_INTERVAL_AUTO ||
+ fep->u.ofdm.constellation == QAM_AUTO ||
+ fep->u.ofdm.code_rate_HP == FEC_AUTO) {
+ int i = 100, found;
+
+ dib3000mc_autosearch_start(fe, &ch);
+ do {
+ msleep(1);
+ found = dib3000mc_autosearch_is_irq(fe);
+ } while (found == 0 && i--);
+
+ dprintk("autosearch returns: %d\n",found);
+ if (found == 0 || found == 1)
+ return 0; // no channel found
+
+ dib3000mc_get_frontend(fe, fep);
+ FEP2DIB(fep,&ch);
+ }
+
+ /* make this a config parameter */
+ dib3000mc_set_output_mode(state, OUTMODE_MPEG2_FIFO);
+
+ return dib3000mc_tune(fe, &ch);
}
-static int dib3000mc_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
+static int dib3000mc_read_status(struct dvb_frontend *fe, fe_status_t *stat)
{
- tune->min_delay_ms = 1000;
+ struct dib3000mc_state *state = fe->demodulator_priv;
+ u16 lock = dib3000mc_read_word(state, 509);
+
+ *stat = 0;
+
+ if (lock & 0x8000)
+ *stat |= FE_HAS_SIGNAL;
+ if (lock & 0x3000)
+ *stat |= FE_HAS_CARRIER;
+ if (lock & 0x0100)
+ *stat |= FE_HAS_VITERBI;
+ if (lock & 0x0010)
+ *stat |= FE_HAS_SYNC;
+ if (lock & 0x0008)
+ *stat |= FE_HAS_LOCK;
+
return 0;
}
-static int dib3000mc_fe_init_nonmobile(struct dvb_frontend* fe)
+static int dib3000mc_read_ber(struct dvb_frontend *fe, u32 *ber)
{
- return dib3000mc_fe_init(fe, 0);
+ struct dib3000mc_state *state = fe->demodulator_priv;
+ *ber = (dib3000mc_read_word(state, 500) << 16) | dib3000mc_read_word(state, 501);
+ return 0;
}
-static int dib3000mc_set_frontend_and_tuner(struct dvb_frontend* fe, struct dvb_frontend_parameters *fep)
+static int dib3000mc_read_unc_blocks(struct dvb_frontend *fe, u32 *unc)
{
- return dib3000mc_set_frontend(fe, fep, 1);
+ struct dib3000mc_state *state = fe->demodulator_priv;
+ *unc = dib3000mc_read_word(state, 508);
+ return 0;
}
-static void dib3000mc_release(struct dvb_frontend* fe)
+static int dib3000mc_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
{
- struct dib3000_state *state = fe->demodulator_priv;
- kfree(state);
+ struct dib3000mc_state *state = fe->demodulator_priv;
+ u16 val = dib3000mc_read_word(state, 392);
+ *strength = 65535 - val;
+ return 0;
}
-/* pid filter and transfer stuff */
-static int dib3000mc_pid_control(struct dvb_frontend *fe,int index, int pid,int onoff)
+static int dib3000mc_read_snr(struct dvb_frontend* fe, u16 *snr)
{
- struct dib3000_state *state = fe->demodulator_priv;
- pid = (onoff ? pid | DIB3000_ACTIVATE_PID_FILTERING : 0);
- wr(index+DIB3000MC_REG_FIRST_PID,pid);
+ *snr = 0x0000;
return 0;
}
-static int dib3000mc_fifo_control(struct dvb_frontend *fe, int onoff)
+static int dib3000mc_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
{
- struct dib3000_state *state = fe->demodulator_priv;
- u16 tmp = rd(DIB3000MC_REG_SMO_MODE);
-
- deb_xfer("%s fifo\n",onoff ? "enabling" : "disabling");
-
- if (onoff) {
- deb_xfer("%d %x\n",tmp & DIB3000MC_SMO_MODE_FIFO_UNFLUSH,tmp & DIB3000MC_SMO_MODE_FIFO_UNFLUSH);
- wr(DIB3000MC_REG_SMO_MODE,tmp & DIB3000MC_SMO_MODE_FIFO_UNFLUSH);
- } else {
- deb_xfer("%d %x\n",tmp | DIB3000MC_SMO_MODE_FIFO_FLUSH,tmp | DIB3000MC_SMO_MODE_FIFO_FLUSH);
- wr(DIB3000MC_REG_SMO_MODE,tmp | DIB3000MC_SMO_MODE_FIFO_FLUSH);
- }
+ tune->min_delay_ms = 1000;
return 0;
}
-static int dib3000mc_pid_parse(struct dvb_frontend *fe, int onoff)
+static void dib3000mc_release(struct dvb_frontend *fe)
{
- struct dib3000_state *state = fe->demodulator_priv;
- u16 tmp = rd(DIB3000MC_REG_SMO_MODE);
-
- deb_xfer("%s pid parsing\n",onoff ? "enabling" : "disabling");
-
- if (onoff) {
- wr(DIB3000MC_REG_SMO_MODE,tmp | DIB3000MC_SMO_MODE_PID_PARSE);
- } else {
- wr(DIB3000MC_REG_SMO_MODE,tmp & DIB3000MC_SMO_MODE_NO_PID_PARSE);
- }
- return 0;
+ struct dib3000mc_state *state = fe->demodulator_priv;
+ dibx000_exit_i2c_master(&state->i2c_master);
+ kfree(state);
}
-static int dib3000mc_tuner_pass_ctrl(struct dvb_frontend *fe, int onoff, u8 pll_addr)
+int dib3000mc_pid_control(struct dvb_frontend *fe, int index, int pid,int onoff)
{
- struct dib3000_state *state = fe->demodulator_priv;
- if (onoff) {
- wr(DIB3000MC_REG_TUNER, DIB3000_TUNER_WRITE_ENABLE(pll_addr));
- } else {
- wr(DIB3000MC_REG_TUNER, DIB3000_TUNER_WRITE_DISABLE(pll_addr));
- }
+ struct dib3000mc_state *state = fe->demodulator_priv;
+ dib3000mc_write_word(state, 212 + index, onoff ? (1 << 13) | pid : 0);
return 0;
}
+EXPORT_SYMBOL(dib3000mc_pid_control);
-static int dib3000mc_demod_init(struct dib3000_state *state)
+int dib3000mc_pid_parse(struct dvb_frontend *fe, int onoff)
{
- u16 default_addr = 0x0a;
- /* first init */
- if (state->config.demod_address != default_addr) {
- deb_info("initializing the demod the first time. Setting demod addr to 0x%x\n",default_addr);
- wr(DIB3000MC_REG_ELEC_OUT,DIB3000MC_ELEC_OUT_DIV_OUT_ON);
- wr(DIB3000MC_REG_OUTMODE,DIB3000MC_OM_PAR_CONT_CLK);
-
- wr(DIB3000MC_REG_RST_I2C_ADDR,
- DIB3000MC_DEMOD_ADDR(default_addr) |
- DIB3000MC_DEMOD_ADDR_ON);
-
- state->config.demod_address = default_addr;
-
- wr(DIB3000MC_REG_RST_I2C_ADDR,
- DIB3000MC_DEMOD_ADDR(default_addr));
- } else
- deb_info("demod is already initialized. Demod addr: 0x%x\n",state->config.demod_address);
- return 0;
+ struct dib3000mc_state *state = fe->demodulator_priv;
+ u16 tmp = dib3000mc_read_word(state, 206) & ~(1 << 4);
+ tmp |= (onoff << 4);
+ return dib3000mc_write_word(state, 206, tmp);
}
+EXPORT_SYMBOL(dib3000mc_pid_parse);
+void dib3000mc_set_config(struct dvb_frontend *fe, struct dib3000mc_config *cfg)
+{
+ struct dib3000mc_state *state = fe->demodulator_priv;
+ state->cfg = cfg;
+}
+EXPORT_SYMBOL(dib3000mc_set_config);
static struct dvb_frontend_ops dib3000mc_ops;
-struct dvb_frontend* dib3000mc_attach(const struct dib3000_config* config,
- struct i2c_adapter* i2c, struct dib_fe_xfer_ops *xfer_ops)
+int dib3000mc_attach(struct i2c_adapter *i2c_adap, int no_of_demods, u8 default_addr, u8 do_i2c_enum, struct dib3000mc_config cfg[], struct dvb_frontend *demod[])
{
- struct dib3000_state* state = NULL;
- u16 devid;
+ struct dib3000mc_state *st;
+ int k, num=0;
- /* allocate memory for the internal state */
- state = kzalloc(sizeof(struct dib3000_state), GFP_KERNEL);
- if (state == NULL)
- goto error;
+ if (no_of_demods < 1)
+ return -EINVAL;
- /* setup the state */
- state->i2c = i2c;
- memcpy(&state->config,config,sizeof(struct dib3000_config));
+ for (k = 0; k < no_of_demods; k++) {
+ st = kzalloc(sizeof(struct dib3000mc_state), GFP_KERNEL);
+ if (st == NULL)
+ goto error;
- /* check for the correct demod */
- if (rd(DIB3000_REG_MANUFACTOR_ID) != DIB3000_I2C_ID_DIBCOM)
- goto error;
+ num++;
- devid = rd(DIB3000_REG_DEVICE_ID);
- if (devid != DIB3000MC_DEVICE_ID && devid != DIB3000P_DEVICE_ID)
- goto error;
+ st->cfg = &cfg[k];
+ // st->gpio_val = cfg[k].gpio_val;
+ // st->gpio_dir = cfg[k].gpio_dir;
+ st->i2c_adap = i2c_adap;
- switch (devid) {
- case DIB3000MC_DEVICE_ID:
- info("Found a DiBcom 3000M-C, interesting...");
- break;
- case DIB3000P_DEVICE_ID:
- info("Found a DiBcom 3000P.");
- break;
- }
+ demod[k] = &st->demod;
+ demod[k]->demodulator_priv = st;
+ memcpy(&st->demod.ops, &dib3000mc_ops, sizeof(struct dvb_frontend_ops));
- /* create dvb_frontend */
- memcpy(&state->frontend.ops, &dib3000mc_ops, sizeof(struct dvb_frontend_ops));
- state->frontend.demodulator_priv = state;
+// INIT_COMPONENT_REGISTER_ACCESS(&st->register_access, 12, 16, dib7000p_register_read, dib7000p_register_write, st);
+// demod[k]->register_access = &st->register_access;
+ }
- /* set the xfer operations */
- xfer_ops->pid_parse = dib3000mc_pid_parse;
- xfer_ops->fifo_ctrl = dib3000mc_fifo_control;
- xfer_ops->pid_ctrl = dib3000mc_pid_control;
- xfer_ops->tuner_pass_ctrl = dib3000mc_tuner_pass_ctrl;
+ if (do_i2c_enum) {
+ if (dib3000mc_i2c_enumeration(demod,no_of_demods,default_addr) != 0)
+ goto error;
+ } else {
+ st = demod[0]->demodulator_priv;
+ st->i2c_addr = default_addr;
+ if (dib3000mc_identify(st) != 0)
+ goto error;
+ }
- dib3000mc_demod_init(state);
+ for (k = 0; k < num; k++) {
+ st = demod[k]->demodulator_priv;
+ dibx000_init_i2c_master(&st->i2c_master, DIB3000MC, st->i2c_adap, st->i2c_addr);
+ }
- return &state->frontend;
+ return 0;
error:
- kfree(state);
- return NULL;
+ for (k = 0; k < num; k++)
+ kfree(demod[k]->demodulator_priv);
+
+ return -EINVAL;
}
+
EXPORT_SYMBOL(dib3000mc_attach);
static struct dvb_frontend_ops dib3000mc_ops = {
-
.info = {
- .name = "DiBcom 3000P/M-C DVB-T",
- .type = FE_OFDM,
- .frequency_min = 44250000,
- .frequency_max = 867250000,
- .frequency_stepsize = 62500,
+ .name = "DiBcom 3000MC/P",
+ .type = FE_OFDM,
+ .frequency_min = 44250000,
+ .frequency_max = 867250000,
+ .frequency_stepsize = 62500,
.caps = FE_CAN_INVERSION_AUTO |
- FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
- FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
- FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
- FE_CAN_TRANSMISSION_MODE_AUTO |
- FE_CAN_GUARD_INTERVAL_AUTO |
- FE_CAN_RECOVER |
- FE_CAN_HIERARCHY_AUTO,
+ FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
+ FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
+ FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
+ FE_CAN_TRANSMISSION_MODE_AUTO |
+ FE_CAN_GUARD_INTERVAL_AUTO |
+ FE_CAN_RECOVER |
+ FE_CAN_HIERARCHY_AUTO,
},
- .release = dib3000mc_release,
+ .release = dib3000mc_release,
- .init = dib3000mc_fe_init_nonmobile,
- .sleep = dib3000mc_sleep,
+ .init = dib3000mc_init,
+ .sleep = dib3000mc_sleep,
- .set_frontend = dib3000mc_set_frontend_and_tuner,
- .get_frontend = dib3000mc_get_frontend,
- .get_tune_settings = dib3000mc_fe_get_tune_settings,
+ .set_frontend = dib3000mc_set_frontend,
+ .get_tune_settings = dib3000mc_fe_get_tune_settings,
+ .get_frontend = dib3000mc_get_frontend,
- .read_status = dib3000mc_read_status,
- .read_ber = dib3000mc_read_ber,
+ .read_status = dib3000mc_read_status,
+ .read_ber = dib3000mc_read_ber,
.read_signal_strength = dib3000mc_read_signal_strength,
- .read_snr = dib3000mc_read_snr,
- .read_ucblocks = dib3000mc_read_unc_blocks,
+ .read_snr = dib3000mc_read_snr,
+ .read_ucblocks = dib3000mc_read_unc_blocks,
};
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
+MODULE_DESCRIPTION("Driver for the DiBcom 3000MC/P COFDM demodulator");
MODULE_LICENSE("GPL");
diff --git a/linux/drivers/media/dvb/frontends/dib3000mc_priv.h b/linux/drivers/media/dvb/frontends/dib3000mc_priv.h
deleted file mode 100644
index 2930aac75..000000000
--- a/linux/drivers/media/dvb/frontends/dib3000mc_priv.h
+++ /dev/null
@@ -1,428 +0,0 @@
-/*
- * dib3000mc_priv.h
- *
- * Copyright (C) 2004 Patrick Boettcher (patrick.boettcher@desy.de)
- *
- * 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, version 2.
- *
- * for more information see dib3000mc.c .
- */
-
-#ifndef __DIB3000MC_PRIV_H__
-#define __DIB3000MC_PRIV_H__
-
-/*
- * Demodulator parameters
- * reg: 0 1 1 1 11 11 111
- * | | | | | |
- * | | | | | +-- alpha (000=0, 001=1, 010=2, 100=4)
- * | | | | +----- constellation (00=QPSK, 01=16QAM, 10=64QAM)
- * | | | +-------- guard (00=1/32, 01=1/16, 10=1/8, 11=1/4)
- * | | +----------- transmission mode (0=2k, 1=8k)
- * | |
- * | +-------------- restart autosearch for parameters
- * +---------------- restart the demodulator
- * reg: 181 1 111 1
- * | | |
- * | | +- FEC applies for HP or LP (0=LP, 1=HP)
- * | +---- FEC rate (001=1/2, 010=2/3, 011=3/4, 101=5/6, 111=7/8)
- * +------- hierarchy on (0=no, 1=yes)
- */
-
-/* demodulator tuning parameter and restart options */
-#define DIB3000MC_REG_DEMOD_PARM ( 0)
-#define DIB3000MC_DEMOD_PARM(a,c,g,t) ( \
- (0x7 & a) | \
- ((0x3 & c) << 3) | \
- ((0x3 & g) << 5) | \
- ((0x1 & t) << 7) )
-#define DIB3000MC_DEMOD_RST_AUTO_SRCH_ON (1 << 8)
-#define DIB3000MC_DEMOD_RST_AUTO_SRCH_OFF (0 << 8)
-#define DIB3000MC_DEMOD_RST_DEMOD_ON (1 << 9)
-#define DIB3000MC_DEMOD_RST_DEMOD_OFF (0 << 9)
-
-/* register for hierarchy parameters */
-#define DIB3000MC_REG_HRCH_PARM ( 181)
-#define DIB3000MC_HRCH_PARM(s,f,h) ( \
- (0x1 & s) | \
- ((0x7 & f) << 1) | \
- ((0x1 & h) << 4) )
-
-/* timeout ??? */
-#define DIB3000MC_REG_UNK_1 ( 1)
-#define DIB3000MC_UNK_1 ( 0x04)
-
-/* timeout ??? */
-#define DIB3000MC_REG_UNK_2 ( 2)
-#define DIB3000MC_UNK_2 ( 0x04)
-
-/* timeout ??? */
-#define DIB3000MC_REG_UNK_3 ( 3)
-#define DIB3000MC_UNK_3 (0x1000)
-
-#define DIB3000MC_REG_UNK_4 ( 4)
-#define DIB3000MC_UNK_4 (0x0814)
-
-/* timeout ??? */
-#define DIB3000MC_REG_SEQ_TPS ( 5)
-#define DIB3000MC_SEQ_TPS_DEFAULT ( 1)
-#define DIB3000MC_SEQ_TPS(s,t) ( \
- ((s & 0x0f) << 4) | \
- ((t & 0x01) << 8) )
-#define DIB3000MC_IS_TPS(v) ((v << 8) & 0x1)
-#define DIB3000MC_IS_AS(v) ((v >> 4) & 0xf)
-
-/* parameters for the bandwidth */
-#define DIB3000MC_REG_BW_TIMOUT_MSB ( 6)
-#define DIB3000MC_REG_BW_TIMOUT_LSB ( 7)
-
-static u16 dib3000mc_reg_bandwidth[] = { 6,7,8,9,10,11,16,17 };
-
-/*static u16 dib3000mc_bandwidth_5mhz[] =
- { 0x28, 0x9380, 0x87, 0x4100, 0x2a4, 0x4500, 0x1, 0xb0d0 };*/
-
-static u16 dib3000mc_bandwidth_6mhz[] =
- { 0x21, 0xd040, 0x70, 0xb62b, 0x233, 0x8ed5, 0x1, 0xb0d0 };
-
-static u16 dib3000mc_bandwidth_7mhz[] =
- { 0x1c, 0xfba5, 0x60, 0x9c25, 0x1e3, 0x0cb7, 0x1, 0xb0d0 };
-
-static u16 dib3000mc_bandwidth_8mhz[] =
- { 0x19, 0x5c30, 0x54, 0x88a0, 0x1a6, 0xab20, 0x1, 0xb0d0 };
-
-static u16 dib3000mc_reg_bandwidth_general[] = { 12,13,14,15 };
-static u16 dib3000mc_bandwidth_general[] = { 0x0000, 0x03e8, 0x0000, 0x03f2 };
-
-/* lock mask */
-#define DIB3000MC_REG_LOCK_MASK ( 15)
-#define DIB3000MC_ACTIVATE_LOCK_MASK (0x0800)
-
-/* reset the uncorrected packet count (??? do it 5 times) */
-#define DIB3000MC_REG_RST_UNC ( 18)
-#define DIB3000MC_RST_UNC_ON ( 1)
-#define DIB3000MC_RST_UNC_OFF ( 0)
-
-#define DIB3000MC_REG_UNK_19 ( 19)
-#define DIB3000MC_UNK_19 ( 0)
-
-/* DDS frequency value (IF position) and inversion bit */
-#define DIB3000MC_REG_INVERSION ( 21)
-#define DIB3000MC_REG_SET_DDS_FREQ_MSB ( 21)
-#define DIB3000MC_DDS_FREQ_MSB_INV_OFF (0x0164)
-#define DIB3000MC_DDS_FREQ_MSB_INV_ON (0x0364)
-
-#define DIB3000MC_REG_SET_DDS_FREQ_LSB ( 22)
-#define DIB3000MC_DDS_FREQ_LSB (0x463d)
-
-/* timing frequencies setting */
-#define DIB3000MC_REG_TIMING_FREQ_MSB ( 23)
-#define DIB3000MC_REG_TIMING_FREQ_LSB ( 24)
-#define DIB3000MC_CLOCK_REF (0x151fd1)
-
-//static u16 dib3000mc_reg_timing_freq[] = { 23,24 };
-
-//static u16 dib3000mc_timing_freq[][2] = {
-// { 0x69, 0x9f18 }, /* 5 MHz */
-// { 0x7e ,0xbee9 }, /* 6 MHz */
-// { 0x93 ,0xdebb }, /* 7 MHz */
-// { 0xa8 ,0xfe8c }, /* 8 MHz */
-//};
-
-/* timeout ??? */
-static u16 dib3000mc_reg_offset[] = { 26,33 };
-
-static u16 dib3000mc_offset[][2] = {
- { 26240, 5 }, /* default */
- { 30336, 6 }, /* 8K */
- { 38528, 8 }, /* 2K */
-};
-
-#define DIB3000MC_REG_ISI ( 29)
-#define DIB3000MC_ISI_DEFAULT (0x1073)
-#define DIB3000MC_ISI_ACTIVATE (0x0000)
-#define DIB3000MC_ISI_INHIBIT (0x0200)
-
-/* impulse noise control */
-static u16 dib3000mc_reg_imp_noise_ctl[] = { 34,35 };
-
-static u16 dib3000mc_imp_noise_ctl[][2] = {
- { 0x1294, 0x1ff8 }, /* mode 0 */
- { 0x1294, 0x1ff8 }, /* mode 1 */
- { 0x1294, 0x1ff8 }, /* mode 2 */
- { 0x1294, 0x1ff8 }, /* mode 3 */
- { 0x1294, 0x1ff8 }, /* mode 4 */
-};
-
-/* AGC registers */
-static u16 dib3000mc_reg_agc[] = {
- 36,37,38,39,42,43,44,45,46,47,48,49
-};
-
-static u16 dib3000mc_agc_tuner[][12] = {
- { 0x0051, 0x301d, 0x0000, 0x1cc7, 0xcf5c, 0x6666,
- 0xbae1, 0xa148, 0x3b5e, 0x3c1c, 0x001a, 0x2019
- }, /* TUNER_PANASONIC_ENV77H04D5, */
-
- { 0x0051, 0x301d, 0x0000, 0x1cc7, 0xdc29, 0x570a,
- 0xbae1, 0x8ccd, 0x3b6d, 0x551d, 0x000a, 0x951e
- }, /* TUNER_PANASONIC_ENV57H13D5, TUNER_PANASONIC_ENV57H12D5 */
-
- { 0x0051, 0x301d, 0x0000, 0x1cc7, 0xffff, 0xffff,
- 0xffff, 0x0000, 0xfdfd, 0x4040, 0x00fd, 0x4040
- }, /* TUNER_SAMSUNG_DTOS333IH102, TUNER_RFAGCIN_UNKNOWN */
-
- { 0x0196, 0x301d, 0x0000, 0x1cc7, 0xbd71, 0x5c29,
- 0xb5c3, 0x6148, 0x6569, 0x5127, 0x0033, 0x3537
- }, /* TUNER_PROVIDER_X */
- /* TODO TUNER_PANASONIC_ENV57H10D8, TUNER_PANASONIC_ENV57H11D8 */
-};
-
-/* AGC loop bandwidth */
-static u16 dib3000mc_reg_agc_bandwidth[] = { 40,41 };
-static u16 dib3000mc_agc_bandwidth[] = { 0x119,0x330 };
-
-static u16 dib3000mc_reg_agc_bandwidth_general[] = { 50,51,52,53,54 };
-static u16 dib3000mc_agc_bandwidth_general[] =
- { 0x8000, 0x91ca, 0x01ba, 0x0087, 0x0087 };
-
-#define DIB3000MC_REG_IMP_NOISE_55 ( 55)
-#define DIB3000MC_IMP_NEW_ALGO(w) (w | (1<<10))
-
-/* Impulse noise params */
-static u16 dib3000mc_reg_impulse_noise[] = { 55,56,57 };
-static u16 dib3000mc_impluse_noise[][3] = {
- { 0x489, 0x89, 0x72 }, /* 5 MHz */
- { 0x4a5, 0xa5, 0x89 }, /* 6 MHz */
- { 0x4c0, 0xc0, 0xa0 }, /* 7 MHz */
- { 0x4db, 0xdb, 0xb7 }, /* 8 Mhz */
-};
-
-static u16 dib3000mc_reg_fft[] = {
- 58,59,60,61,62,63,64,65,66,67,68,69,
- 70,71,72,73,74,75,76,77,78,79,80,81,
- 82,83,84,85,86
-};
-
-static u16 dib3000mc_fft_modes[][29] = {
- { 0x38, 0x6d9, 0x3f28, 0x7a7, 0x3a74, 0x196, 0x32a, 0x48c,
- 0x3ffe, 0x7f3, 0x2d94, 0x76, 0x53d,
- 0x3ff8, 0x7e3, 0x3320, 0x76, 0x5b3,
- 0x3feb, 0x7d2, 0x365e, 0x76, 0x48c,
- 0x3ffe, 0x5b3, 0x3feb, 0x76, 0x0, 0xd
- }, /* fft mode 0 */
- { 0x3b, 0x6d9, 0x3f28, 0x7a7, 0x3a74, 0x196, 0x32a, 0x48c,
- 0x3ffe, 0x7f3, 0x2d94, 0x76, 0x53d,
- 0x3ff8, 0x7e3, 0x3320, 0x76, 0x5b3,
- 0x3feb, 0x7d2, 0x365e, 0x76, 0x48c,
- 0x3ffe, 0x5b3, 0x3feb, 0x0, 0x8200, 0xd
- }, /* fft mode 1 */
-};
-
-#define DIB3000MC_REG_UNK_88 ( 88)
-#define DIB3000MC_UNK_88 (0x0410)
-
-static u16 dib3000mc_reg_bw[] = { 93,94,95,96,97,98 };
-static u16 dib3000mc_bw[][6] = {
- { 0,0,0,0,0,0 }, /* 5 MHz */
- { 0,0,0,0,0,0 }, /* 6 MHz */
- { 0,0,0,0,0,0 }, /* 7 MHz */
- { 0x20, 0x21, 0x20, 0x23, 0x20, 0x27 }, /* 8 MHz */
-};
-
-
-/* phase noise control */
-#define DIB3000MC_REG_UNK_99 ( 99)
-#define DIB3000MC_UNK_99 (0x0220)
-
-#define DIB3000MC_REG_SCAN_BOOST ( 100)
-#define DIB3000MC_SCAN_BOOST_ON ((11 << 6) + 6)
-#define DIB3000MC_SCAN_BOOST_OFF ((16 << 6) + 9)
-
-/* timeout ??? */
-#define DIB3000MC_REG_UNK_110 ( 110)
-#define DIB3000MC_UNK_110 ( 3277)
-
-#define DIB3000MC_REG_UNK_111 ( 111)
-#define DIB3000MC_UNK_111_PH_N_MODE_0 ( 0)
-#define DIB3000MC_UNK_111_PH_N_MODE_1 (1 << 1)
-
-/* superious rm config */
-#define DIB3000MC_REG_UNK_120 ( 120)
-#define DIB3000MC_UNK_120 ( 8207)
-
-#define DIB3000MC_REG_UNK_133 ( 133)
-#define DIB3000MC_UNK_133 ( 15564)
-
-#define DIB3000MC_REG_UNK_134 ( 134)
-#define DIB3000MC_UNK_134 ( 0)
-
-/* adapter config for constellation */
-static u16 dib3000mc_reg_adp_cfg[] = { 129, 130, 131, 132 };
-
-static u16 dib3000mc_adp_cfg[][4] = {
- { 0x99a, 0x7fae, 0x333, 0x7ff0 }, /* QPSK */
- { 0x23d, 0x7fdf, 0x0a4, 0x7ff0 }, /* 16-QAM */
- { 0x148, 0x7ff0, 0x0a4, 0x7ff8 }, /* 64-QAM */
-};
-
-static u16 dib3000mc_reg_mobile_mode[] = { 139, 140, 141, 175, 1032 };
-
-static u16 dib3000mc_mobile_mode[][5] = {
- { 0x01, 0x0, 0x0, 0x00, 0x12c }, /* fixed */
- { 0x01, 0x0, 0x0, 0x00, 0x12c }, /* portable */
- { 0x00, 0x0, 0x0, 0x02, 0x000 }, /* mobile */
- { 0x00, 0x0, 0x0, 0x02, 0x000 }, /* auto */
-};
-
-#define DIB3000MC_REG_DIVERSITY1 ( 177)
-#define DIB3000MC_DIVERSITY1_DEFAULT ( 1)
-
-#define DIB3000MC_REG_DIVERSITY2 ( 178)
-#define DIB3000MC_DIVERSITY2_DEFAULT ( 1)
-
-#define DIB3000MC_REG_DIVERSITY3 ( 180)
-#define DIB3000MC_DIVERSITY3_IN_OFF (0xfff0)
-#define DIB3000MC_DIVERSITY3_IN_ON (0xfff6)
-
-#define DIB3000MC_REG_FEC_CFG ( 195)
-#define DIB3000MC_FEC_CFG ( 0x10)
-
-/*
- * reg 206, output mode
- * 1111 1111
- * |||| ||||
- * |||| |||+- unk
- * |||| ||+-- unk
- * |||| |+--- unk (on by default)
- * |||| +---- fifo_ctrl (1 = inhibit (flushed), 0 = active (unflushed))
- * |||+------ pid_parse (1 = enabled, 0 = disabled)
- * ||+------- outp_188 (1 = TS packet size 188, 0 = packet size 204)
- * |+-------- unk
- * +--------- unk
- */
-
-#define DIB3000MC_REG_SMO_MODE ( 206)
-#define DIB3000MC_SMO_MODE_DEFAULT (1 << 2)
-#define DIB3000MC_SMO_MODE_FIFO_FLUSH (1 << 3)
-#define DIB3000MC_SMO_MODE_FIFO_UNFLUSH (0xfff7)
-#define DIB3000MC_SMO_MODE_PID_PARSE (1 << 4)
-#define DIB3000MC_SMO_MODE_NO_PID_PARSE (0xffef)
-#define DIB3000MC_SMO_MODE_188 (1 << 5)
-#define DIB3000MC_SMO_MODE_SLAVE (DIB3000MC_SMO_MODE_DEFAULT | \
- DIB3000MC_SMO_MODE_188 | DIB3000MC_SMO_MODE_PID_PARSE | (1<<1))
-
-#define DIB3000MC_REG_FIFO_THRESHOLD ( 207)
-#define DIB3000MC_FIFO_THRESHOLD_DEFAULT ( 1792)
-#define DIB3000MC_FIFO_THRESHOLD_SLAVE ( 512)
-/*
- * pidfilter
- * it is not a hardware pidfilter but a filter which drops all pids
- * except the ones set. When connected to USB1.1 bandwidth this is important.
- * DiB3000P/M-C can filter up to 32 PIDs
- */
-#define DIB3000MC_REG_FIRST_PID ( 212)
-#define DIB3000MC_NUM_PIDS ( 32)
-
-#define DIB3000MC_REG_OUTMODE ( 244)
-#define DIB3000MC_OM_PARALLEL_GATED_CLK ( 0)
-#define DIB3000MC_OM_PAR_CONT_CLK (1 << 11)
-#define DIB3000MC_OM_SERIAL (2 << 11)
-#define DIB3000MC_OM_DIVOUT_ON (4 << 11)
-#define DIB3000MC_OM_SLAVE (DIB3000MC_OM_DIVOUT_ON | DIB3000MC_OM_PAR_CONT_CLK)
-
-#define DIB3000MC_REG_RF_POWER ( 392)
-
-#define DIB3000MC_REG_FFT_POSITION ( 407)
-
-#define DIB3000MC_REG_DDS_FREQ_MSB ( 414)
-#define DIB3000MC_REG_DDS_FREQ_LSB ( 415)
-
-#define DIB3000MC_REG_TIMING_OFFS_MSB ( 416)
-#define DIB3000MC_REG_TIMING_OFFS_LSB ( 417)
-
-#define DIB3000MC_REG_TUNING_PARM ( 458)
-#define DIB3000MC_TP_QAM(v) ((v >> 13) & 0x03)
-#define DIB3000MC_TP_HRCH(v) ((v >> 12) & 0x01)
-#define DIB3000MC_TP_ALPHA(v) ((v >> 9) & 0x07)
-#define DIB3000MC_TP_FFT(v) ((v >> 8) & 0x01)
-#define DIB3000MC_TP_FEC_CR_HP(v) ((v >> 5) & 0x07)
-#define DIB3000MC_TP_FEC_CR_LP(v) ((v >> 2) & 0x07)
-#define DIB3000MC_TP_GUARD(v) (v & 0x03)
-
-#define DIB3000MC_REG_SIGNAL_NOISE_MSB ( 483)
-#define DIB3000MC_REG_SIGNAL_NOISE_LSB ( 484)
-
-#define DIB3000MC_REG_MER ( 485)
-
-#define DIB3000MC_REG_BER_MSB ( 500)
-#define DIB3000MC_REG_BER_LSB ( 501)
-
-#define DIB3000MC_REG_PACKET_ERRORS ( 503)
-
-#define DIB3000MC_REG_PACKET_ERROR_COUNT ( 506)
-
-#define DIB3000MC_REG_LOCK_507 ( 507)
-#define DIB3000MC_LOCK_507 (0x0002) // ? name correct ?
-
-#define DIB3000MC_REG_LOCKING ( 509)
-#define DIB3000MC_AGC_LOCK(v) (v & 0x8000)
-#define DIB3000MC_CARRIER_LOCK(v) (v & 0x2000)
-#define DIB3000MC_MPEG_SYNC_LOCK(v) (v & 0x0080)
-#define DIB3000MC_MPEG_DATA_LOCK(v) (v & 0x0040)
-#define DIB3000MC_TPS_LOCK(v) (v & 0x0004)
-
-#define DIB3000MC_REG_AS_IRQ ( 511)
-#define DIB3000MC_AS_IRQ_SUCCESS (1 << 1)
-#define DIB3000MC_AS_IRQ_FAIL ( 1)
-
-#define DIB3000MC_REG_TUNER ( 769)
-
-#define DIB3000MC_REG_RST_I2C_ADDR ( 1024)
-#define DIB3000MC_DEMOD_ADDR_ON ( 1)
-#define DIB3000MC_DEMOD_ADDR(a) ((a << 4) & 0x03F0)
-
-#define DIB3000MC_REG_RESTART ( 1027)
-#define DIB3000MC_RESTART_OFF (0x0000)
-#define DIB3000MC_RESTART_AGC (0x0800)
-#define DIB3000MC_RESTART_CONFIG (0x8000)
-
-#define DIB3000MC_REG_RESTART_VIT ( 1028)
-#define DIB3000MC_RESTART_VIT_OFF ( 0)
-#define DIB3000MC_RESTART_VIT_ON ( 1)
-
-#define DIB3000MC_REG_CLK_CFG_1 ( 1031)
-#define DIB3000MC_CLK_CFG_1_POWER_UP ( 0)
-#define DIB3000MC_CLK_CFG_1_POWER_DOWN (0xffff)
-
-#define DIB3000MC_REG_CLK_CFG_2 ( 1032)
-#define DIB3000MC_CLK_CFG_2_PUP_FIXED (0x012c)
-#define DIB3000MC_CLK_CFG_2_PUP_PORT (0x0104)
-#define DIB3000MC_CLK_CFG_2_PUP_MOBILE (0x0000)
-#define DIB3000MC_CLK_CFG_2_POWER_DOWN (0xffff)
-
-#define DIB3000MC_REG_CLK_CFG_3 ( 1033)
-#define DIB3000MC_CLK_CFG_3_POWER_UP ( 0)
-#define DIB3000MC_CLK_CFG_3_POWER_DOWN (0xfff5)
-
-#define DIB3000MC_REG_CLK_CFG_7 ( 1037)
-#define DIB3000MC_CLK_CFG_7_INIT ( 12592)
-#define DIB3000MC_CLK_CFG_7_POWER_UP (~0x0003)
-#define DIB3000MC_CLK_CFG_7_PWR_DOWN (0x0003)
-#define DIB3000MC_CLK_CFG_7_DIV_IN_OFF (1 << 8)
-
-/* was commented out ??? */
-#define DIB3000MC_REG_CLK_CFG_8 ( 1038)
-#define DIB3000MC_CLK_CFG_8_POWER_UP (0x160c)
-
-#define DIB3000MC_REG_CLK_CFG_9 ( 1039)
-#define DIB3000MC_CLK_CFG_9_POWER_UP ( 0)
-
-/* also clock ??? */
-#define DIB3000MC_REG_ELEC_OUT ( 1040)
-#define DIB3000MC_ELEC_OUT_HIGH_Z ( 0)
-#define DIB3000MC_ELEC_OUT_DIV_OUT_ON ( 1)
-#define DIB3000MC_ELEC_OUT_SLAVE ( 3)
-
-#endif
diff --git a/linux/drivers/media/dvb/frontends/dvb-pll.c b/linux/drivers/media/dvb/frontends/dvb-pll.c
index fce5c4252..c92877baa 100644
--- a/linux/drivers/media/dvb/frontends/dvb-pll.c
+++ b/linux/drivers/media/dvb/frontends/dvb-pll.c
@@ -611,26 +611,27 @@ static struct dvb_tuner_ops dvb_pll_tuner_ops = {
.get_bandwidth = dvb_pll_get_bandwidth,
};
-int dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, struct i2c_adapter *i2c, struct dvb_pll_desc *desc)
+struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, struct i2c_adapter *i2c, struct dvb_pll_desc *desc)
{
u8 b1 [] = { 0 };
- struct i2c_msg msg [] = { { .addr = pll_addr, .flags = 0, .buf = NULL, .len = 0 },
- { .addr = pll_addr, .flags = I2C_M_RD, .buf = b1, .len = 1 } };
+ struct i2c_msg msg = { .addr = pll_addr, .flags = I2C_M_RD, .buf = b1, .len = 1 };
struct dvb_pll_priv *priv = NULL;
int ret;
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 1);
+ if (i2c != NULL) {
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
- ret = i2c_transfer (i2c, msg, 2);
- if (ret != 2)
- return -1;
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 0);
+ ret = i2c_transfer (i2c, &msg, 1);
+ if (ret != 1)
+ return NULL;
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 0);
+ }
priv = kzalloc(sizeof(struct dvb_pll_priv), GFP_KERNEL);
if (priv == NULL)
- return -ENOMEM;
+ return NULL;
priv->pll_i2c_address = pll_addr;
priv->i2c = i2c;
@@ -642,7 +643,7 @@ int dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, struct i2c_adapter *i2
fe->ops.tuner_ops.info.frequency_min = desc->max;
fe->tuner_priv = priv;
- return 0;
+ return fe;
}
EXPORT_SYMBOL(dvb_pll_attach);
diff --git a/linux/drivers/media/dvb/frontends/dvb-pll.h b/linux/drivers/media/dvb/frontends/dvb-pll.h
index 66361cd18..ed5ac5a36 100644
--- a/linux/drivers/media/dvb/frontends/dvb-pll.h
+++ b/linux/drivers/media/dvb/frontends/dvb-pll.h
@@ -57,8 +57,8 @@ extern int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf,
* @param pll_addr i2c address of the PLL (if used).
* @param i2c i2c adapter to use (set to NULL if not used).
* @param desc dvb_pll_desc to use.
- * @return 0 on success, nonzero on failure.
+ * @return Frontend pointer on success, NULL on failure
*/
-extern int dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, struct i2c_adapter *i2c, struct dvb_pll_desc *desc);
+extern struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, struct i2c_adapter *i2c, struct dvb_pll_desc *desc);
#endif
diff --git a/linux/drivers/media/dvb/frontends/isl6421.c b/linux/drivers/media/dvb/frontends/isl6421.c
index 58c34db31..0fc18f5a7 100644
--- a/linux/drivers/media/dvb/frontends/isl6421.c
+++ b/linux/drivers/media/dvb/frontends/isl6421.c
@@ -42,12 +42,11 @@ struct isl6421 {
u8 override_and;
struct i2c_adapter *i2c;
u8 i2c_addr;
- void (*release_chain)(struct dvb_frontend* fe);
};
static int isl6421_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
{
- struct isl6421 *isl6421 = (struct isl6421 *) fe->misc_priv;
+ struct isl6421 *isl6421 = (struct isl6421 *) fe->sec_priv;
struct i2c_msg msg = { .addr = isl6421->i2c_addr, .flags = 0,
.buf = &isl6421->config,
.len = sizeof(isl6421->config) };
@@ -75,7 +74,7 @@ static int isl6421_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage
static int isl6421_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
{
- struct isl6421 *isl6421 = (struct isl6421 *) fe->misc_priv;
+ struct isl6421 *isl6421 = (struct isl6421 *) fe->sec_priv;
struct i2c_msg msg = { .addr = isl6421->i2c_addr, .flags = 0,
.buf = &isl6421->config,
.len = sizeof(isl6421->config) };
@@ -93,31 +92,26 @@ static int isl6421_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
static void isl6421_release(struct dvb_frontend *fe)
{
- struct isl6421 *isl6421 = (struct isl6421 *) fe->misc_priv;
-
/* power off */
isl6421_set_voltage(fe, SEC_VOLTAGE_OFF);
- /* free data & call next release routine */
- fe->ops.release = isl6421->release_chain;
- kfree(fe->misc_priv);
- fe->misc_priv = NULL;
- if (fe->ops.release)
- fe->ops.release(fe);
+ /* free */
+ kfree(fe->sec_priv);
+ fe->sec_priv = NULL;
}
-int isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr,
+struct dvb_frontend *isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr,
u8 override_set, u8 override_clear)
{
struct isl6421 *isl6421 = kmalloc(sizeof(struct isl6421), GFP_KERNEL);
if (!isl6421)
- return -ENOMEM;
+ return NULL;
/* default configuration */
isl6421->config = ISL6421_ISEL1;
isl6421->i2c = i2c;
isl6421->i2c_addr = i2c_addr;
- fe->misc_priv = isl6421;
+ fe->sec_priv = isl6421;
/* bits which should be forced to '1' */
isl6421->override_or = override_set;
@@ -128,19 +122,17 @@ int isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr
/* detect if it is present or not */
if (isl6421_set_voltage(fe, SEC_VOLTAGE_OFF)) {
kfree(isl6421);
- fe->misc_priv = NULL;
- return -EIO;
+ return NULL;
}
/* install release callback */
- isl6421->release_chain = fe->ops.release;
fe->ops.release = isl6421_release;
/* override frontend ops */
fe->ops.set_voltage = isl6421_set_voltage;
fe->ops.enable_high_lnb_voltage = isl6421_enable_high_lnb_voltage;
- return 0;
+ return fe;
}
EXPORT_SYMBOL(isl6421_attach);
diff --git a/linux/drivers/media/dvb/frontends/isl6421.h b/linux/drivers/media/dvb/frontends/isl6421.h
index 675f80a19..1916e3eb2 100644
--- a/linux/drivers/media/dvb/frontends/isl6421.h
+++ b/linux/drivers/media/dvb/frontends/isl6421.h
@@ -39,8 +39,17 @@
#define ISL6421_ISEL1 0x20
#define ISL6421_DCL 0x40
+#if defined(CONFIG_DVB_ISL6421) || defined(CONFIG_DVB_ISL6421_MODULE)
/* override_set and override_clear control which system register bits (above) to always set & clear */
-extern int isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr,
+extern struct dvb_frontend *isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr,
u8 override_set, u8 override_clear);
+#else
+static inline struct dvb_frontend *isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr,
+ u8 override_set, u8 override_clear)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ return NULL;
+}
+#endif // CONFIG_DVB_ISL6421
#endif
diff --git a/linux/drivers/media/dvb/frontends/l64781.h b/linux/drivers/media/dvb/frontends/l64781.h
index 83b8bc210..21ba4a230 100644
--- a/linux/drivers/media/dvb/frontends/l64781.h
+++ b/linux/drivers/media/dvb/frontends/l64781.h
@@ -31,8 +31,16 @@ struct l64781_config
u8 demod_address;
};
-
+#if defined(CONFIG_DVB_L64781) || defined(CONFIG_DVB_L64781_MODULE)
extern struct dvb_frontend* l64781_attach(const struct l64781_config* config,
struct i2c_adapter* i2c);
+#else
+static inline struct dvb_frontend* l64781_attach(const struct l64781_config* config,
+ struct i2c_adapter* i2c)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ return NULL;
+}
+#endif // CONFIG_DVB_L64781
#endif // L64781_H
diff --git a/linux/drivers/media/dvb/frontends/lgdt330x.c b/linux/drivers/media/dvb/frontends/lgdt330x.c
index b48b82b11..a1152c69c 100644
--- a/linux/drivers/media/dvb/frontends/lgdt330x.c
+++ b/linux/drivers/media/dvb/frontends/lgdt330x.c
@@ -216,7 +216,7 @@ static int lgdt330x_init(struct dvb_frontend* fe)
AGC_DELAY0, 0x07,
AGC_DELAY2, 0xfe,
/* Change the value of IAGCBW[15:8]
- of inner AGC loop filter bandwith */
+ of inner AGC loop filter bandwidth */
AGC_LOOP_BANDWIDTH0, 0x08,
AGC_LOOP_BANDWIDTH1, 0x9a
};
diff --git a/linux/drivers/media/dvb/frontends/lgdt330x.h b/linux/drivers/media/dvb/frontends/lgdt330x.h
index bad903c6f..3f96b4855 100644
--- a/linux/drivers/media/dvb/frontends/lgdt330x.h
+++ b/linux/drivers/media/dvb/frontends/lgdt330x.h
@@ -52,8 +52,17 @@ struct lgdt330x_config
int clock_polarity_flip;
};
+#if defined(CONFIG_DVB_LGDT330X) || defined(CONFIG_DVB_LGDT330X_MODULE)
extern struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config,
struct i2c_adapter* i2c);
+#else
+static inline struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config,
+ struct i2c_adapter* i2c)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ return NULL;
+}
+#endif // CONFIG_DVB_LGDT330X
#endif /* LGDT330X_H */
diff --git a/linux/drivers/media/dvb/frontends/lnbp21.c b/linux/drivers/media/dvb/frontends/lnbp21.c
index e933edc8d..37bba32f2 100644
--- a/linux/drivers/media/dvb/frontends/lnbp21.c
+++ b/linux/drivers/media/dvb/frontends/lnbp21.c
@@ -40,12 +40,11 @@ struct lnbp21 {
u8 override_or;
u8 override_and;
struct i2c_adapter *i2c;
- void (*release_chain)(struct dvb_frontend* fe);
};
static int lnbp21_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
{
- struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->misc_priv;
+ struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->sec_priv;
struct i2c_msg msg = { .addr = 0x08, .flags = 0,
.buf = &lnbp21->config,
.len = sizeof(lnbp21->config) };
@@ -73,7 +72,7 @@ static int lnbp21_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
static int lnbp21_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
{
- struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->misc_priv;
+ struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->sec_priv;
struct i2c_msg msg = { .addr = 0x08, .flags = 0,
.buf = &lnbp21->config,
.len = sizeof(lnbp21->config) };
@@ -91,29 +90,24 @@ static int lnbp21_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
static void lnbp21_release(struct dvb_frontend *fe)
{
- struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->misc_priv;
-
/* LNBP power off */
lnbp21_set_voltage(fe, SEC_VOLTAGE_OFF);
- /* free data & call next release routine */
- fe->ops.release = lnbp21->release_chain;
- kfree(fe->misc_priv);
- fe->misc_priv = NULL;
- if (fe->ops.release)
- fe->ops.release(fe);
+ /* free data */
+ kfree(fe->sec_priv);
+ fe->sec_priv = NULL;
}
-int lnbp21_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 override_set, u8 override_clear)
+struct dvb_frontend *lnbp21_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 override_set, u8 override_clear)
{
struct lnbp21 *lnbp21 = kmalloc(sizeof(struct lnbp21), GFP_KERNEL);
if (!lnbp21)
- return -ENOMEM;
+ return NULL;
/* default configuration */
lnbp21->config = LNBP21_ISEL;
lnbp21->i2c = i2c;
- fe->misc_priv = lnbp21;
+ fe->sec_priv = lnbp21;
/* bits which should be forced to '1' */
lnbp21->override_or = override_set;
@@ -124,19 +118,17 @@ int lnbp21_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 override_
/* detect if it is present or not */
if (lnbp21_set_voltage(fe, SEC_VOLTAGE_OFF)) {
kfree(lnbp21);
- fe->misc_priv = NULL;
- return -EIO;
+ return NULL;
}
/* install release callback */
- lnbp21->release_chain = fe->ops.release;
fe->ops.release = lnbp21_release;
/* override frontend ops */
fe->ops.set_voltage = lnbp21_set_voltage;
fe->ops.enable_high_lnb_voltage = lnbp21_enable_high_lnb_voltage;
- return 0;
+ return fe;
}
EXPORT_SYMBOL(lnbp21_attach);
diff --git a/linux/drivers/media/dvb/frontends/lnbp21.h b/linux/drivers/media/dvb/frontends/lnbp21.h
index 047a4ab68..1fe1dd179 100644
--- a/linux/drivers/media/dvb/frontends/lnbp21.h
+++ b/linux/drivers/media/dvb/frontends/lnbp21.h
@@ -39,7 +39,15 @@
#include <linux/dvb/frontend.h>
+#if defined(CONFIG_DVB_LNBP21) || defined(CONFIG_DVB_LNBP21_MODULE)
/* override_set and override_clear control which system register bits (above) to always set & clear */
-extern int lnbp21_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 override_set, u8 override_clear);
+extern struct dvb_frontend *lnbp21_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 override_set, u8 override_clear);
+#else
+static inline struct dvb_frontend *lnbp21_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 override_set, u8 override_clear)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ return NULL;
+}
+#endif // CONFIG_DVB_LNBP21
-#endif
+#endif // _LNBP21_H
diff --git a/linux/drivers/media/dvb/frontends/mt2060.c b/linux/drivers/media/dvb/frontends/mt2060.c
new file mode 100644
index 000000000..39b32de2c
--- /dev/null
+++ b/linux/drivers/media/dvb/frontends/mt2060.c
@@ -0,0 +1,372 @@
+/*
+ * Driver for Microtune MT2060 "Single chip dual conversion broadband tuner"
+ *
+ * Copyright (c) 2006 Olivier DANET <odanet@caramail.com>
+ *
+ * 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.=
+ */
+
+/* In that file, frequencies are expressed in kiloHertz to avoid 32 bits overflows */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/delay.h>
+#include <linux/dvb/frontend.h>
+#include <linux/i2c.h>
+
+#include "dvb_frontend.h"
+
+#include "mt2060.h"
+#include "mt2060_priv.h"
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
+
+#define dprintk(args...) do { if (debug) {printk(KERN_DEBUG "MT2060: " args); printk("\n"); }} while (0)
+
+// Reads a single register
+static int mt2060_readreg(struct mt2060_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 "mt2060 I2C read failed\n");
+ return -EREMOTEIO;
+ }
+ return 0;
+}
+
+// Writes a single register
+static int mt2060_writereg(struct mt2060_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 "mt2060 I2C write failed\n");
+ return -EREMOTEIO;
+ }
+ return 0;
+}
+
+// Writes a set of consecutive registers
+static int mt2060_writeregs(struct mt2060_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 "mt2060 I2C write failed (len=%i)\n",(int)len);
+ return -EREMOTEIO;
+ }
+ return 0;
+}
+
+// Initialisation sequences
+// LNABAND=3, NUM1=0x3C, DIV1=0x74, NUM2=0x1080, DIV2=0x49
+static u8 mt2060_config1[] = {
+ REG_LO1C1,
+ 0x3F, 0x74, 0x00, 0x08, 0x93
+};
+
+// FMCG=2, GP2=0, GP1=0
+static u8 mt2060_config2[] = {
+ REG_MISC_CTRL,
+ 0x20, 0x1E, 0x30, 0xff, 0x80, 0xff, 0x00, 0x2c, 0x42
+};
+
+// VGAG=3, V1CSE=1
+#if 0
+static u8 mt2060_config3[] = {
+ REG_VGAG,
+ 0x33
+};
+#endif
+
+#ifdef MT2060_SPURCHECK
+/* The function below calculates the frequency offset between the output frequency if2
+ and the closer cross modulation subcarrier between lo1 and lo2 up to the tenth harmonic */
+static int mt2060_spurcalc(u32 lo1,u32 lo2,u32 if2)
+{
+ int I,J;
+ int dia,diamin,diff;
+ diamin=1000000;
+ for (I = 1; I < 10; I++) {
+ J = ((2*I*lo1)/lo2+1)/2;
+ diff = I*(int)lo1-J*(int)lo2;
+ if (diff < 0) diff=-diff;
+ dia = (diff-(int)if2);
+ if (dia < 0) dia=-dia;
+ if (diamin > dia) diamin=dia;
+ }
+ return diamin;
+}
+
+#define BANDWIDTH 4000 // kHz
+
+/* Calculates the frequency offset to add to avoid spurs. Returns 0 if no offset is needed */
+static int mt2060_spurcheck(u32 lo1,u32 lo2,u32 if2)
+{
+ u32 Spur,Sp1,Sp2;
+ int I,J;
+ I=0;
+ J=1000;
+
+ Spur=mt2060_spurcalc(lo1,lo2,if2);
+ if (Spur < BANDWIDTH) {
+ /* Potential spurs detected */
+ dprintk("Spurs before : f_lo1: %d f_lo2: %d (kHz)",
+ (int)lo1,(int)lo2);
+ I=1000;
+ Sp1 = mt2060_spurcalc(lo1+I,lo2+I,if2);
+ Sp2 = mt2060_spurcalc(lo1-I,lo2-I,if2);
+
+ if (Sp1 < Sp2) {
+ J=-J; I=-I; Spur=Sp2;
+ } else
+ Spur=Sp1;
+
+ while (Spur < BANDWIDTH) {
+ I += J;
+ Spur = mt2060_spurcalc(lo1+I,lo2+I,if2);
+ }
+ dprintk("Spurs after : f_lo1: %d f_lo2: %d (kHz)",
+ (int)(lo1+I),(int)(lo2+I));
+ }
+ return I;
+}
+#endif
+
+#define IF2 36150 // IF2 frequency = 36.150 MHz
+#define FREF 16000 // Quartz oscillator 16 MHz
+
+static int mt2060_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+{
+ struct mt2060_priv *priv;
+ int ret=0;
+ int i=0;
+ u32 freq;
+ u8 lnaband;
+ u32 f_lo1,f_lo2;
+ u32 div1,num1,div2,num2;
+ u8 b[8];
+ u32 if1;
+
+ priv = fe->tuner_priv;
+
+ if1 = priv->if1_freq;
+ b[0] = REG_LO1B1;
+ b[1] = 0xFF;
+
+ mt2060_writeregs(priv,b,2);
+
+ freq = params->frequency / 1000; // Hz -> kHz
+ priv->bandwidth = (fe->ops.info.type == FE_OFDM) ? params->u.ofdm.bandwidth : 0;
+
+ f_lo1 = freq + if1 * 1000;
+ f_lo1 = (f_lo1 / 250) * 250;
+ f_lo2 = f_lo1 - freq - IF2;
+ // From the Comtech datasheet, the step used is 50kHz. The tuner chip could be more precise
+ f_lo2 = ((f_lo2 + 25) / 50) * 50;
+ priv->frequency = (f_lo1 - f_lo2 - IF2) * 1000,
+
+#ifdef MT2060_SPURCHECK
+ // LO-related spurs detection and correction
+ num1 = mt2060_spurcheck(f_lo1,f_lo2,IF2);
+ f_lo1 += num1;
+ f_lo2 += num1;
+#endif
+ //Frequency LO1 = 16MHz * (DIV1 + NUM1/64 )
+ num1 = f_lo1 / (FREF / 64);
+ div1 = num1 / 64;
+ num1 &= 0x3f;
+
+ // Frequency LO2 = 16MHz * (DIV2 + NUM2/8192 )
+ num2 = f_lo2 * 64 / (FREF / 128);
+ div2 = num2 / 8192;
+ num2 &= 0x1fff;
+
+ if (freq <= 95000) lnaband = 0xB0; else
+ if (freq <= 180000) lnaband = 0xA0; else
+ if (freq <= 260000) lnaband = 0x90; else
+ if (freq <= 335000) lnaband = 0x80; else
+ if (freq <= 425000) lnaband = 0x70; else
+ if (freq <= 480000) lnaband = 0x60; else
+ if (freq <= 570000) lnaband = 0x50; else
+ if (freq <= 645000) lnaband = 0x40; else
+ if (freq <= 730000) lnaband = 0x30; else
+ if (freq <= 810000) lnaband = 0x20; else lnaband = 0x10;
+
+ b[0] = REG_LO1C1;
+ b[1] = lnaband | ((num1 >>2) & 0x0F);
+ b[2] = div1;
+ b[3] = (num2 & 0x0F) | ((num1 & 3) << 4);
+ b[4] = num2 >> 4;
+ b[5] = ((num2 >>12) & 1) | (div2 << 1);
+
+ dprintk("IF1: %dMHz",(int)if1);
+ dprintk("PLL freq=%dkHz f_lo1=%dkHz f_lo2=%dkHz",(int)freq,(int)f_lo1,(int)f_lo2);
+ dprintk("PLL div1=%d num1=%d div2=%d num2=%d",(int)div1,(int)num1,(int)div2,(int)num2);
+ dprintk("PLL [1..5]: %2x %2x %2x %2x %2x",(int)b[1],(int)b[2],(int)b[3],(int)b[4],(int)b[5]);
+
+ mt2060_writeregs(priv,b,6);
+
+ //Waits for pll lock or timeout
+ i = 0;
+ do {
+ mt2060_readreg(priv,REG_LO_STATUS,b);
+ if ((b[0] & 0x88)==0x88)
+ break;
+ msleep(4);
+ i++;
+ } while (i<10);
+
+ return ret;
+}
+
+static void mt2060_calibrate(struct mt2060_priv *priv)
+{
+ u8 b = 0;
+ int i = 0;
+
+ if (mt2060_writeregs(priv,mt2060_config1,sizeof(mt2060_config1)))
+ return;
+ if (mt2060_writeregs(priv,mt2060_config2,sizeof(mt2060_config2)))
+ return;
+
+ do {
+ b |= (1 << 6); // FM1SS;
+ mt2060_writereg(priv, REG_LO2C1,b);
+ msleep(20);
+
+ if (i == 0) {
+ b |= (1 << 7); // FM1CA;
+ mt2060_writereg(priv, REG_LO2C1,b);
+ b &= ~(1 << 7); // FM1CA;
+ msleep(20);
+ }
+
+ b &= ~(1 << 6); // FM1SS
+ mt2060_writereg(priv, REG_LO2C1,b);
+
+ msleep(20);
+ i++;
+ } while (i < 9);
+
+ i = 0;
+ while (i++ < 10 && mt2060_readreg(priv, REG_MISC_STAT, &b) == 0 && (b & (1 << 6)) == 0)
+ msleep(20);
+
+ if (i < 10) {
+ mt2060_readreg(priv, REG_FM_FREQ, &priv->fmfreq); // now find out, what is fmreq used for :)
+ dprintk("calibration was successful: %d", (int)priv->fmfreq);
+ } else
+ dprintk("FMCAL timed out");
+}
+
+static int mt2060_calc_regs(struct dvb_frontend *fe, struct dvb_frontend_parameters *params, u8 *buf, int buf_len)
+{
+ return -ENODEV;
+}
+
+static int mt2060_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+ struct mt2060_priv *priv = fe->tuner_priv;
+ *frequency = priv->frequency;
+ return 0;
+}
+
+static int mt2060_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
+{
+ struct mt2060_priv *priv = fe->tuner_priv;
+ *bandwidth = priv->bandwidth;
+ return 0;
+}
+
+static int mt2060_sleep(struct dvb_frontend *fe)
+{
+ struct mt2060_priv *priv = fe->tuner_priv;
+ return mt2060_writereg(priv, REG_VGAG,0x30);
+}
+
+static int mt2060_release(struct dvb_frontend *fe)
+{
+ kfree(fe->tuner_priv);
+ fe->tuner_priv = NULL;
+ return 0;
+}
+
+static const struct dvb_tuner_ops mt2060_tuner_ops = {
+ .info = {
+ .name = "Microtune MT2060",
+ .frequency_min = 48000000,
+ .frequency_max = 860000000,
+ .frequency_step = 50000,
+ },
+
+ .release = mt2060_release,
+
+ .sleep = mt2060_sleep,
+
+ .set_params = mt2060_set_params,
+ .calc_regs = mt2060_calc_regs,
+ .get_frequency = mt2060_get_frequency,
+ .get_bandwidth = mt2060_get_bandwidth
+};
+
+/* This functions tries to identify a MT2060 tuner by reading the PART/REV register. This is hasty. */
+int mt2060_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct mt2060_config *cfg, u16 if1)
+{
+ struct mt2060_priv *priv = NULL;
+ u8 id = 0;
+
+ priv = kzalloc(sizeof(struct mt2060_priv), GFP_KERNEL);
+ if (priv == NULL)
+ return -ENOMEM;
+
+ priv->cfg = cfg;
+ priv->i2c = i2c;
+ priv->if1_freq = if1;
+
+ if (mt2060_readreg(priv,REG_PART_REV,&id) != 0) {
+ kfree(priv);
+ return -ENODEV;
+ }
+
+ if (id != PART_REV) {
+ kfree(priv);
+ return -ENODEV;
+ }
+ printk(KERN_INFO "MT2060: successfully identified (IF1 = %d)\n", if1);
+ memcpy(&fe->ops.tuner_ops, &mt2060_tuner_ops, sizeof(struct dvb_tuner_ops));
+
+ fe->tuner_priv = priv;
+
+ mt2060_calibrate(priv);
+
+ return 0;
+}
+EXPORT_SYMBOL(mt2060_attach);
+
+MODULE_AUTHOR("Olivier DANET");
+MODULE_DESCRIPTION("Microtune MT2060 silicon tuner driver");
+MODULE_LICENSE("GPL");
diff --git a/linux/drivers/media/dvb/frontends/mt2060.h b/linux/drivers/media/dvb/frontends/mt2060.h
new file mode 100644
index 000000000..c58b03e82
--- /dev/null
+++ b/linux/drivers/media/dvb/frontends/mt2060.h
@@ -0,0 +1,35 @@
+/*
+ * Driver for Microtune MT2060 "Single chip dual conversion broadband tuner"
+ *
+ * Copyright (c) 2006 Olivier DANET <odanet@caramail.com>
+ *
+ * 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 MT2060_H
+#define MT2060_H
+
+struct dvb_frontend;
+struct i2c_adapter;
+
+struct mt2060_config {
+ u8 i2c_address;
+ /* Shall we add settings for the discrete outputs ? */
+};
+
+extern int mt2060_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct mt2060_config *cfg, u16 if1);
+
+#endif
diff --git a/linux/drivers/media/dvb/frontends/mt2060_priv.h b/linux/drivers/media/dvb/frontends/mt2060_priv.h
new file mode 100644
index 000000000..5eaccdefd
--- /dev/null
+++ b/linux/drivers/media/dvb/frontends/mt2060_priv.h
@@ -0,0 +1,105 @@
+/*
+ * Driver for Microtune MT2060 "Single chip dual conversion broadband tuner"
+ *
+ * Copyright (c) 2006 Olivier DANET <odanet@caramail.com>
+ *
+ * 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 MT2060_PRIV_H
+#define MT2060_PRIV_H
+
+// Uncomment the #define below to enable spurs checking. The results where quite unconvincing.
+// #define MT2060_SPURCHECK
+
+/* This driver is based on the information available in the datasheet of the
+ "Comtech SDVBT-3K6M" tuner ( K1000737843.pdf ) which features the MT2060 register map :
+
+ I2C Address : 0x60
+
+ Reg.No | B7 | B6 | B5 | B4 | B3 | B2 | B1 | B0 | ( defaults )
+ --------------------------------------------------------------------------------
+ 00 | [ PART ] | [ REV ] | R = 0x63
+ 01 | [ LNABAND ] | [ NUM1(5:2) ] | RW = 0x3F
+ 02 | [ DIV1 ] | RW = 0x74
+ 03 | FM1CA | FM1SS | [ NUM1(1:0) ] | [ NUM2(3:0) ] | RW = 0x00
+ 04 | NUM2(11:4) ] | RW = 0x08
+ 05 | [ DIV2 ] |NUM2(12)| RW = 0x93
+ 06 | L1LK | [ TAD1 ] | L2LK | [ TAD2 ] | R
+ 07 | [ FMF ] | R
+ 08 | ? | FMCAL | ? | ? | ? | ? | ? | TEMP | R
+ 09 | 0 | 0 | [ FMGC ] | 0 | GP02 | GP01 | 0 | RW = 0x20
+ 0A | ??
+ 0B | 0 | 0 | 1 | 1 | 0 | 0 | [ VGAG ] | RW = 0x30
+ 0C | V1CSE | 1 | 1 | 1 | 1 | 1 | 1 | 1 | RW = 0xFF
+ 0D | 1 | 0 | [ V1CS ] | RW = 0xB0
+ 0E | ??
+ 0F | ??
+ 10 | ??
+ 11 | [ LOTO ] | 0 | 0 | 1 | 0 | RW = 0x42
+
+ PART : Part code : 6 for MT2060
+ REV : Revision code : 3 for current revision
+ LNABAND : Input frequency range : ( See code for details )
+ NUM1 / DIV1 / NUM2 / DIV2 : Frequencies programming ( See code for details )
+ FM1CA : Calibration Start Bit
+ FM1SS : Calibration Single Step bit
+ L1LK : LO1 Lock Detect
+ TAD1 : Tune Line ADC ( ? )
+ L2LK : LO2 Lock Detect
+ TAD2 : Tune Line ADC ( ? )
+ FMF : Estimated first IF Center frequency Offset ( ? )
+ FM1CAL : Calibration done bit
+ TEMP : On chip temperature sensor
+ FMCG : Mixer 1 Cap Gain ( ? )
+ GP01 / GP02 : Programmable digital outputs. Unconnected pins ?
+ V1CSE : LO1 VCO Automatic Capacitor Select Enable ( ? )
+ V1CS : LO1 Capacitor Selection Value ( ? )
+ LOTO : LO Timeout ( ? )
+ VGAG : Tuner Output gain
+*/
+
+#define I2C_ADDRESS 0x60
+
+#define REG_PART_REV 0
+#define REG_LO1C1 1
+#define REG_LO1C2 2
+#define REG_LO2C1 3
+#define REG_LO2C2 4
+#define REG_LO2C3 5
+#define REG_LO_STATUS 6
+#define REG_FM_FREQ 7
+#define REG_MISC_STAT 8
+#define REG_MISC_CTRL 9
+#define REG_RESERVED_A 0x0A
+#define REG_VGAG 0x0B
+#define REG_LO1B1 0x0C
+#define REG_LO1B2 0x0D
+#define REG_LOTO 0x11
+
+#define PART_REV 0x63 // The current driver works only with PART=6 and REV=3 chips
+
+struct mt2060_priv {
+ struct mt2060_config *cfg;
+ struct i2c_adapter *i2c;
+
+ u32 frequency;
+ u32 bandwidth;
+ u16 if1_freq;
+ u8 fmfreq;
+};
+
+#endif
diff --git a/linux/drivers/media/dvb/frontends/mt312.h b/linux/drivers/media/dvb/frontends/mt312.h
index 666a1bd1c..7112fb4d5 100644
--- a/linux/drivers/media/dvb/frontends/mt312.h
+++ b/linux/drivers/media/dvb/frontends/mt312.h
@@ -34,8 +34,16 @@ struct mt312_config
u8 demod_address;
};
+#if defined(CONFIG_DVB_MT312) || defined(CONFIG_DVB_MT312_MODULE)
struct dvb_frontend* vp310_mt312_attach(const struct mt312_config* config,
struct i2c_adapter* i2c);
-
+#else
+static inline struct dvb_frontend* vp310_mt312_attach(const struct mt312_config* config,
+ struct i2c_adapter* i2c)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ return NULL;
+}
+#endif // CONFIG_DVB_MT312
#endif // MT312_H
diff --git a/linux/drivers/media/dvb/frontends/mt352.c b/linux/drivers/media/dvb/frontends/mt352.c
index 5de7376c9..87e31ca7e 100644
--- a/linux/drivers/media/dvb/frontends/mt352.c
+++ b/linux/drivers/media/dvb/frontends/mt352.c
@@ -70,7 +70,7 @@ static int mt352_single_write(struct dvb_frontend *fe, u8 reg, u8 val)
return 0;
}
-int mt352_write(struct dvb_frontend* fe, u8* ibuf, int ilen)
+static int _mt352_write(struct dvb_frontend* fe, u8* ibuf, int ilen)
{
int err,i;
for (i=0; i < ilen-1; i++)
@@ -107,7 +107,7 @@ static int mt352_sleep(struct dvb_frontend* fe)
{
static u8 mt352_softdown[] = { CLOCK_CTL, 0x20, 0x08 };
- mt352_write(fe, mt352_softdown, sizeof(mt352_softdown));
+ _mt352_write(fe, mt352_softdown, sizeof(mt352_softdown));
return 0;
}
@@ -293,14 +293,14 @@ static int mt352_set_parameters(struct dvb_frontend* fe,
fe->ops.i2c_gate_ctrl(fe, 0);
}
- mt352_write(fe, buf, 8);
- mt352_write(fe, fsm_go, 2);
+ _mt352_write(fe, buf, 8);
+ _mt352_write(fe, fsm_go, 2);
} else {
if (fe->ops.tuner_ops.calc_regs) {
fe->ops.tuner_ops.calc_regs(fe, param, buf+8, 5);
buf[8] <<= 1;
- mt352_write(fe, buf, sizeof(buf));
- mt352_write(fe, tuner_go, 2);
+ _mt352_write(fe, buf, sizeof(buf));
+ _mt352_write(fe, tuner_go, 2);
}
}
@@ -522,7 +522,7 @@ static int mt352_init(struct dvb_frontend* fe)
(mt352_read_register(state, CONFIG) & 0x20) == 0) {
/* Do a "hard" reset */
- mt352_write(fe, mt352_reset_attach, sizeof(mt352_reset_attach));
+ _mt352_write(fe, mt352_reset_attach, sizeof(mt352_reset_attach));
return state->config.demod_init(fe);
}
@@ -585,6 +585,7 @@ static struct dvb_frontend_ops mt352_ops = {
.init = mt352_init,
.sleep = mt352_sleep,
+ .write = _mt352_write,
.set_frontend = mt352_set_parameters,
.get_frontend = mt352_get_parameters,
@@ -605,4 +606,3 @@ MODULE_AUTHOR("Holger Waechtler, Daniel Mack, Antonio Mancuso");
MODULE_LICENSE("GPL");
EXPORT_SYMBOL(mt352_attach);
-EXPORT_SYMBOL(mt352_write);
diff --git a/linux/drivers/media/dvb/frontends/mt352.h b/linux/drivers/media/dvb/frontends/mt352.h
index 9e7ff4b8f..0035c2e2d 100644
--- a/linux/drivers/media/dvb/frontends/mt352.h
+++ b/linux/drivers/media/dvb/frontends/mt352.h
@@ -51,9 +51,23 @@ struct mt352_config
int (*demod_init)(struct dvb_frontend* fe);
};
+#if defined(CONFIG_DVB_MT352) || defined(CONFIG_DVB_MT352_MODULE)
extern struct dvb_frontend* mt352_attach(const struct mt352_config* config,
struct i2c_adapter* i2c);
+#else
+static inline struct dvb_frontend* mt352_attach(const struct mt352_config* config,
+ struct i2c_adapter* i2c)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ return NULL;
+}
+#endif // CONFIG_DVB_MT352
-extern int mt352_write(struct dvb_frontend* fe, u8* ibuf, int ilen);
+static inline int mt352_write(struct dvb_frontend *fe, u8 *buf, int len) {
+ int r = 0;
+ if (fe->ops.write)
+ r = fe->ops.write(fe, buf, len);
+ return r;
+}
#endif // MT352_H
diff --git a/linux/drivers/media/dvb/frontends/nxt200x.c b/linux/drivers/media/dvb/frontends/nxt200x.c
index 55671cb52..87c286ee6 100644
--- a/linux/drivers/media/dvb/frontends/nxt200x.c
+++ b/linux/drivers/media/dvb/frontends/nxt200x.c
@@ -896,9 +896,9 @@ static int nxt2002_init(struct dvb_frontend* fe)
}
ret = nxt2002_load_firmware(fe, fw);
+ release_firmware(fw);
if (ret) {
printk("nxt2002: Writing firmware to device failed\n");
- release_firmware(fw);
return ret;
}
printk("nxt2002: Firmware upload complete\n");
@@ -960,9 +960,9 @@ static int nxt2004_init(struct dvb_frontend* fe)
}
ret = nxt2004_load_firmware(fe, fw);
+ release_firmware(fw);
if (ret) {
printk("nxt2004: Writing firmware to device failed\n");
- release_firmware(fw);
return ret;
}
printk("nxt2004: Firmware upload complete\n");
diff --git a/linux/drivers/media/dvb/frontends/nxt200x.h b/linux/drivers/media/dvb/frontends/nxt200x.h
index 34d617358..2eb220e98 100644
--- a/linux/drivers/media/dvb/frontends/nxt200x.h
+++ b/linux/drivers/media/dvb/frontends/nxt200x.h
@@ -45,8 +45,17 @@ struct nxt200x_config
int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured);
};
+#if defined(CONFIG_DVB_NXT200X) || defined(CONFIG_DVB_NXT200X_MODULE)
extern struct dvb_frontend* nxt200x_attach(const struct nxt200x_config* config,
struct i2c_adapter* i2c);
+#else
+static inline struct dvb_frontend* nxt200x_attach(const struct nxt200x_config* config,
+ struct i2c_adapter* i2c)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ return NULL;
+}
+#endif // CONFIG_DVB_NXT200X
#endif /* NXT200X_H */
diff --git a/linux/drivers/media/dvb/frontends/nxt6000.h b/linux/drivers/media/dvb/frontends/nxt6000.h
index 117031d11..9397393a6 100644
--- a/linux/drivers/media/dvb/frontends/nxt6000.h
+++ b/linux/drivers/media/dvb/frontends/nxt6000.h
@@ -33,7 +33,16 @@ struct nxt6000_config
u8 clock_inversion:1;
};
+#if defined(CONFIG_DVB_NXT6000) || defined(CONFIG_DVB_NXT6000_MODULE)
extern struct dvb_frontend* nxt6000_attach(const struct nxt6000_config* config,
struct i2c_adapter* i2c);
+#else
+static inline struct dvb_frontend* nxt6000_attach(const struct nxt6000_config* config,
+ struct i2c_adapter* i2c)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ return NULL;
+}
+#endif // CONFIG_DVB_NXT6000
#endif // NXT6000_H
diff --git a/linux/drivers/media/dvb/frontends/or51132.h b/linux/drivers/media/dvb/frontends/or51132.h
index 89658883a..9718be4fb 100644
--- a/linux/drivers/media/dvb/frontends/or51132.h
+++ b/linux/drivers/media/dvb/frontends/or51132.h
@@ -34,8 +34,17 @@ struct or51132_config
int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured);
};
+#if defined(CONFIG_DVB_OR51132) || defined(CONFIG_DVB_OR51132_MODULE)
extern struct dvb_frontend* or51132_attach(const struct or51132_config* config,
struct i2c_adapter* i2c);
+#else
+static inline struct dvb_frontend* or51132_attach(const struct or51132_config* config,
+ struct i2c_adapter* i2c)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ return NULL;
+}
+#endif // CONFIG_DVB_OR51132
#endif // OR51132_H
diff --git a/linux/drivers/media/dvb/frontends/or51211.c b/linux/drivers/media/dvb/frontends/or51211.c
index 26bed616f..2bf124b53 100644
--- a/linux/drivers/media/dvb/frontends/or51211.c
+++ b/linux/drivers/media/dvb/frontends/or51211.c
@@ -437,10 +437,10 @@ static int or51211_init(struct dvb_frontend* fe)
}
ret = or51211_load_firmware(fe, fw);
+ release_firmware(fw);
if (ret) {
printk(KERN_WARNING "or51211: Writing firmware to "
"device failed!\n");
- release_firmware(fw);
return ret;
}
printk(KERN_INFO "or51211: Firmware upload complete.\n");
diff --git a/linux/drivers/media/dvb/frontends/or51211.h b/linux/drivers/media/dvb/frontends/or51211.h
index 13a5a3afb..10a5419f9 100644
--- a/linux/drivers/media/dvb/frontends/or51211.h
+++ b/linux/drivers/media/dvb/frontends/or51211.h
@@ -37,8 +37,17 @@ struct or51211_config
void (*sleep)(struct dvb_frontend * fe);
};
+#if defined(CONFIG_DVB_OR51211) || defined(CONFIG_DVB_OR51211_MODULE)
extern struct dvb_frontend* or51211_attach(const struct or51211_config* config,
struct i2c_adapter* i2c);
+#else
+static inline struct dvb_frontend* or51211_attach(const struct or51211_config* config,
+ struct i2c_adapter* i2c)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ return NULL;
+}
+#endif // CONFIG_DVB_OR51211
#endif // OR51211_H
diff --git a/linux/drivers/media/dvb/frontends/s5h1420.h b/linux/drivers/media/dvb/frontends/s5h1420.h
index 4e39015fa..efc54d7f3 100644
--- a/linux/drivers/media/dvb/frontends/s5h1420.h
+++ b/linux/drivers/media/dvb/frontends/s5h1420.h
@@ -34,7 +34,16 @@ struct s5h1420_config
u8 invert:1;
};
+#if defined(CONFIG_DVB_S5H1420) || defined(CONFIG_DVB_S5H1420_MODULE)
extern struct dvb_frontend* s5h1420_attach(const struct s5h1420_config* config,
struct i2c_adapter* i2c);
+#else
+static inline struct dvb_frontend* s5h1420_attach(const struct s5h1420_config* config,
+ struct i2c_adapter* i2c)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ return NULL;
+}
+#endif // CONFIG_DVB_S5H1420
#endif // S5H1420_H
diff --git a/linux/drivers/media/dvb/frontends/sp8870.c b/linux/drivers/media/dvb/frontends/sp8870.c
index 44ec5b9a4..d98fd5c2e 100644
--- a/linux/drivers/media/dvb/frontends/sp8870.c
+++ b/linux/drivers/media/dvb/frontends/sp8870.c
@@ -318,7 +318,6 @@ static int sp8870_init (struct dvb_frontend* fe)
printk("sp8870: waiting for firmware upload (%s)...\n", SP8870_DEFAULT_FIRMWARE);
if (state->config->request_firmware(fe, &fw, SP8870_DEFAULT_FIRMWARE)) {
printk("sp8870: no firmware upload (timeout or file not found?)\n");
- release_firmware(fw);
return -EIO;
}
@@ -327,6 +326,7 @@ static int sp8870_init (struct dvb_frontend* fe)
release_firmware(fw);
return -EIO;
}
+ release_firmware(fw);
printk("sp8870: firmware upload complete\n");
/* enable TS output and interface pins */
diff --git a/linux/drivers/media/dvb/frontends/sp8870.h b/linux/drivers/media/dvb/frontends/sp8870.h
index 93afbb969..4cf27d3b1 100644
--- a/linux/drivers/media/dvb/frontends/sp8870.h
+++ b/linux/drivers/media/dvb/frontends/sp8870.h
@@ -35,7 +35,16 @@ struct sp8870_config
int (*request_firmware)(struct dvb_frontend* fe, const struct firmware **fw, char* name);
};
+#if defined(CONFIG_DVB_SP8870) || defined(CONFIG_DVB_SP8870_MODULE)
extern struct dvb_frontend* sp8870_attach(const struct sp8870_config* config,
struct i2c_adapter* i2c);
+#else
+static inline struct dvb_frontend* sp8870_attach(const struct sp8870_config* config,
+ struct i2c_adapter* i2c)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ return NULL;
+}
+#endif // CONFIG_DVB_SP8870
#endif // SP8870_H
diff --git a/linux/drivers/media/dvb/frontends/sp887x.c b/linux/drivers/media/dvb/frontends/sp887x.c
index b0a2b02f6..5c2f8f4e0 100644
--- a/linux/drivers/media/dvb/frontends/sp887x.c
+++ b/linux/drivers/media/dvb/frontends/sp887x.c
@@ -520,9 +520,9 @@ static int sp887x_init(struct dvb_frontend* fe)
}
ret = sp887x_initial_setup(fe, fw);
+ release_firmware(fw);
if (ret) {
printk("sp887x: writing firmware to device failed\n");
- release_firmware(fw);
return ret;
}
printk("sp887x: firmware upload complete\n");
diff --git a/linux/drivers/media/dvb/frontends/sp887x.h b/linux/drivers/media/dvb/frontends/sp887x.h
index c44b0ebdf..cab7ea644 100644
--- a/linux/drivers/media/dvb/frontends/sp887x.h
+++ b/linux/drivers/media/dvb/frontends/sp887x.h
@@ -17,7 +17,16 @@ struct sp887x_config
int (*request_firmware)(struct dvb_frontend* fe, const struct firmware **fw, char* name);
};
+#if defined(CONFIG_DVB_SP887X) || defined(CONFIG_DVB_SP887X_MODULE)
extern struct dvb_frontend* sp887x_attach(const struct sp887x_config* config,
struct i2c_adapter* i2c);
+#else
+static inline struct dvb_frontend* sp887x_attach(const struct sp887x_config* config,
+ struct i2c_adapter* i2c)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ return NULL;
+}
+#endif // CONFIG_DVB_SP887X
#endif // SP887X_H
diff --git a/linux/drivers/media/dvb/frontends/stv0297.h b/linux/drivers/media/dvb/frontends/stv0297.h
index 1da5384fb..760b80db4 100644
--- a/linux/drivers/media/dvb/frontends/stv0297.h
+++ b/linux/drivers/media/dvb/frontends/stv0297.h
@@ -42,7 +42,16 @@ struct stv0297_config
u8 stop_during_read:1;
};
+#if defined(CONFIG_DVB_STV0297) || defined(CONFIG_DVB_STV0297_MODULE)
extern struct dvb_frontend* stv0297_attach(const struct stv0297_config* config,
struct i2c_adapter* i2c);
+#else
+static inline struct dvb_frontend* stv0297_attach(const struct stv0297_config* config,
+ struct i2c_adapter* i2c)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ return NULL;
+}
+#endif // CONFIG_DVB_STV0297
#endif // STV0297_H
diff --git a/linux/drivers/media/dvb/frontends/stv0299.c b/linux/drivers/media/dvb/frontends/stv0299.c
index 96648a754..93483769e 100644
--- a/linux/drivers/media/dvb/frontends/stv0299.c
+++ b/linux/drivers/media/dvb/frontends/stv0299.c
@@ -92,11 +92,14 @@ static int stv0299_writeregI (struct stv0299_state* state, u8 reg, u8 data)
return (ret != 1) ? -EREMOTEIO : 0;
}
-int stv0299_writereg (struct dvb_frontend* fe, u8 reg, u8 data)
+int stv0299_write(struct dvb_frontend* fe, u8 *buf, int len)
{
struct stv0299_state* state = fe->demodulator_priv;
- return stv0299_writeregI(state, reg, data);
+ if (len != 2)
+ return -EINVAL;
+
+ return stv0299_writeregI(state, buf[0], buf[1]);
}
static u8 stv0299_readreg (struct stv0299_state* state, u8 reg)
@@ -694,6 +697,7 @@ static struct dvb_frontend_ops stv0299_ops = {
.init = stv0299_init,
.sleep = stv0299_sleep,
+ .write = stv0299_write,
.i2c_gate_ctrl = stv0299_i2c_gate_ctrl,
.set_frontend = stv0299_set_frontend,
@@ -724,5 +728,4 @@ MODULE_AUTHOR("Ralph Metzler, Holger Waechtler, Peter Schildmann, Felix Domke, "
"Andreas Oberritter, Andrew de Quincey, Kenneth Aafly");
MODULE_LICENSE("GPL");
-EXPORT_SYMBOL(stv0299_writereg);
EXPORT_SYMBOL(stv0299_attach);
diff --git a/linux/drivers/media/dvb/frontends/stv0299.h b/linux/drivers/media/dvb/frontends/stv0299.h
index 1504828e4..7ef252070 100644
--- a/linux/drivers/media/dvb/frontends/stv0299.h
+++ b/linux/drivers/media/dvb/frontends/stv0299.h
@@ -89,9 +89,24 @@ struct stv0299_config
int (*set_symbol_rate)(struct dvb_frontend* fe, u32 srate, u32 ratio);
};
-extern int stv0299_writereg (struct dvb_frontend* fe, u8 reg, u8 data);
-
+#if defined(CONFIG_DVB_STV0299) || defined(CONFIG_DVB_STV0299_MODULE)
extern struct dvb_frontend* stv0299_attach(const struct stv0299_config* config,
struct i2c_adapter* i2c);
+#else
+static inline struct dvb_frontend* stv0299_attach(const struct stv0299_config* config,
+ struct i2c_adapter* i2c)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ return NULL;
+}
+#endif // CONFIG_DVB_STV0299
+
+static inline int stv0299_writereg(struct dvb_frontend *fe, u8 reg, u8 val) {
+ int r = 0;
+ u8 buf[] = {reg, val};
+ if (fe->ops.write)
+ r = fe->ops.write(fe, buf, 2);
+ return r;
+}
#endif // STV0299_H
diff --git a/linux/drivers/media/dvb/frontends/tda10021.c b/linux/drivers/media/dvb/frontends/tda10021.c
index 48b02abd0..8b7bbdf2e 100644
--- a/linux/drivers/media/dvb/frontends/tda10021.c
+++ b/linux/drivers/media/dvb/frontends/tda10021.c
@@ -21,7 +21,6 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include <linux/config.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/init.h>
@@ -73,7 +72,7 @@ static u8 tda10021_inittab[0x40]=
0x04, 0x2d, 0x2f, 0xff, 0x00, 0x00, 0x00, 0x00,
};
-static int tda10021_writereg (struct tda10021_state* state, u8 reg, u8 data)
+static int _tda10021_writereg (struct tda10021_state* state, u8 reg, u8 data)
{
u8 buf[] = { reg, data };
struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 };
@@ -89,14 +88,6 @@ static int tda10021_writereg (struct tda10021_state* state, u8 reg, u8 data)
return (ret != 1) ? -EREMOTEIO : 0;
}
-int tda10021_write_byte(struct dvb_frontend* fe, int reg, int data)
-{
- struct tda10021_state* state = fe->demodulator_priv;
-
- return tda10021_writereg(state, reg, data);
-}
-EXPORT_SYMBOL(tda10021_write_byte);
-
static u8 tda10021_readreg (struct tda10021_state* state, u8 reg)
{
u8 b0 [] = { reg };
@@ -150,8 +141,8 @@ static int tda10021_setup_reg0 (struct tda10021_state* state, u8 reg0,
else if (INVERSION_OFF == inversion)
DISABLE_INVERSION(reg0);
- tda10021_writereg (state, 0x00, reg0 & 0xfe);
- tda10021_writereg (state, 0x00, reg0 | 0x01);
+ _tda10021_writereg (state, 0x00, reg0 & 0xfe);
+ _tda10021_writereg (state, 0x00, reg0 | 0x01);
state->reg0 = reg0;
return 0;
@@ -199,17 +190,27 @@ static int tda10021_set_symbolrate (struct tda10021_state* state, u32 symbolrate
NDEC = (NDEC << 6) | tda10021_inittab[0x03];
- tda10021_writereg (state, 0x03, NDEC);
- tda10021_writereg (state, 0x0a, BDR&0xff);
- tda10021_writereg (state, 0x0b, (BDR>> 8)&0xff);
- tda10021_writereg (state, 0x0c, (BDR>>16)&0x3f);
+ _tda10021_writereg (state, 0x03, NDEC);
+ _tda10021_writereg (state, 0x0a, BDR&0xff);
+ _tda10021_writereg (state, 0x0b, (BDR>> 8)&0xff);
+ _tda10021_writereg (state, 0x0c, (BDR>>16)&0x3f);
- tda10021_writereg (state, 0x0d, BDRI);
- tda10021_writereg (state, 0x0e, SFIL);
+ _tda10021_writereg (state, 0x0d, BDRI);
+ _tda10021_writereg (state, 0x0e, SFIL);
return 0;
}
+int tda10021_write(struct dvb_frontend* fe, u8 *buf, int len)
+{
+ struct tda10021_state* state = fe->demodulator_priv;
+
+ if (len != 2)
+ return -EINVAL;
+
+ return _tda10021_writereg(state, buf[0], buf[1]);
+}
+
static int tda10021_init (struct dvb_frontend *fe)
{
struct tda10021_state* state = fe->demodulator_priv;
@@ -217,12 +218,12 @@ static int tda10021_init (struct dvb_frontend *fe)
dprintk("DVB: TDA10021(%d): init chip\n", fe->adapter->num);
- //tda10021_writereg (fe, 0, 0);
+ //_tda10021_writereg (fe, 0, 0);
for (i=0; i<tda10021_inittab_size; i++)
- tda10021_writereg (state, i, tda10021_inittab[i]);
+ _tda10021_writereg (state, i, tda10021_inittab[i]);
- tda10021_writereg (state, 0x34, state->pwm);
+ _tda10021_writereg (state, 0x34, state->pwm);
//Comment by markus
//0x2A[3-0] == PDIV -> P multiplaying factor (P=PDIV+1)(default 0)
@@ -231,7 +232,7 @@ static int tda10021_init (struct dvb_frontend *fe)
//0x2A[6] == POLAXIN -> Polarity of the input reference clock (default 0)
//Activate PLL
- tda10021_writereg(state, 0x2a, tda10021_inittab[0x2a] & 0xef);
+ _tda10021_writereg(state, 0x2a, tda10021_inittab[0x2a] & 0xef);
return 0;
}
@@ -265,12 +266,12 @@ static int tda10021_set_parameters (struct dvb_frontend *fe,
}
tda10021_set_symbolrate (state, p->u.qam.symbol_rate);
- tda10021_writereg (state, 0x34, state->pwm);
+ _tda10021_writereg (state, 0x34, state->pwm);
- tda10021_writereg (state, 0x01, reg0x01[qam]);
- tda10021_writereg (state, 0x05, reg0x05[qam]);
- tda10021_writereg (state, 0x08, reg0x08[qam]);
- tda10021_writereg (state, 0x09, reg0x09[qam]);
+ _tda10021_writereg (state, 0x01, reg0x01[qam]);
+ _tda10021_writereg (state, 0x05, reg0x05[qam]);
+ _tda10021_writereg (state, 0x08, reg0x08[qam]);
+ _tda10021_writereg (state, 0x09, reg0x09[qam]);
tda10021_setup_reg0 (state, reg0x00[qam], p->inversion);
@@ -343,8 +344,8 @@ static int tda10021_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
*ucblocks = 0xffffffff;
/* reset uncorrected block counter */
- tda10021_writereg (state, 0x10, tda10021_inittab[0x10] & 0xdf);
- tda10021_writereg (state, 0x10, tda10021_inittab[0x10]);
+ _tda10021_writereg (state, 0x10, tda10021_inittab[0x10] & 0xdf);
+ _tda10021_writereg (state, 0x10, tda10021_inittab[0x10]);
return 0;
}
@@ -393,8 +394,8 @@ static int tda10021_sleep(struct dvb_frontend* fe)
{
struct tda10021_state* state = fe->demodulator_priv;
- tda10021_writereg (state, 0x1b, 0x02); /* pdown ADC */
- tda10021_writereg (state, 0x00, 0x80); /* standby */
+ _tda10021_writereg (state, 0x1b, 0x02); /* pdown ADC */
+ _tda10021_writereg (state, 0x00, 0x80); /* standby */
return 0;
}
@@ -460,6 +461,7 @@ static struct dvb_frontend_ops tda10021_ops = {
.init = tda10021_init,
.sleep = tda10021_sleep,
+ .write = tda10021_write,
.i2c_gate_ctrl = tda10021_i2c_gate_ctrl,
.set_frontend = tda10021_set_parameters,
diff --git a/linux/drivers/media/dvb/frontends/tda10021.h b/linux/drivers/media/dvb/frontends/tda10021.h
index b1df4259b..d68ae20c8 100644
--- a/linux/drivers/media/dvb/frontends/tda10021.h
+++ b/linux/drivers/media/dvb/frontends/tda10021.h
@@ -32,9 +32,24 @@ struct tda10021_config
u8 demod_address;
};
+#if defined(CONFIG_DVB_TDA10021) || defined(CONFIG_DVB_TDA10021_MODULE)
extern struct dvb_frontend* tda10021_attach(const struct tda10021_config* config,
struct i2c_adapter* i2c, u8 pwm);
-
-extern int tda10021_write_byte(struct dvb_frontend* fe, int reg, int data);
+#else
+static inline struct dvb_frontend* tda10021_attach(const struct tda10021_config* config,
+ struct i2c_adapter* i2c, u8 pwm)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ return NULL;
+}
+#endif // CONFIG_DVB_TDA10021
+
+static inline int tda10021_writereg(struct dvb_frontend *fe, u8 reg, u8 val) {
+ int r = 0;
+ u8 buf[] = {reg, val};
+ if (fe->ops.write)
+ r = fe->ops.write(fe, buf, 2);
+ return r;
+}
#endif // TDA10021_H
diff --git a/linux/drivers/media/dvb/frontends/tda1004x.c b/linux/drivers/media/dvb/frontends/tda1004x.c
index 59a2ed614..11e0dca9a 100644
--- a/linux/drivers/media/dvb/frontends/tda1004x.c
+++ b/linux/drivers/media/dvb/frontends/tda1004x.c
@@ -579,11 +579,14 @@ static int tda1004x_decode_fec(int tdafec)
return -1;
}
-int tda1004x_write_byte(struct dvb_frontend* fe, int reg, int data)
+int tda1004x_write(struct dvb_frontend* fe, u8 *buf, int len)
{
struct tda1004x_state* state = fe->demodulator_priv;
- return tda1004x_write_byteI(state, reg, data);
+ if (len != 2)
+ return -EINVAL;
+
+ return tda1004x_write_byteI(state, buf[0], buf[1]);
}
static int tda10045_init(struct dvb_frontend* fe)
@@ -1216,6 +1219,7 @@ static struct dvb_frontend_ops tda10045_ops = {
.init = tda10045_init,
.sleep = tda1004x_sleep,
+ .write = tda1004x_write,
.i2c_gate_ctrl = tda1004x_i2c_gate_ctrl,
.set_frontend = tda1004x_set_fe,
@@ -1274,6 +1278,7 @@ static struct dvb_frontend_ops tda10046_ops = {
.init = tda10046_init,
.sleep = tda1004x_sleep,
+ .write = tda1004x_write,
.i2c_gate_ctrl = tda1004x_i2c_gate_ctrl,
.set_frontend = tda1004x_set_fe,
@@ -1323,4 +1328,3 @@ MODULE_LICENSE("GPL");
EXPORT_SYMBOL(tda10045_attach);
EXPORT_SYMBOL(tda10046_attach);
-EXPORT_SYMBOL(tda1004x_write_byte);
diff --git a/linux/drivers/media/dvb/frontends/tda1004x.h b/linux/drivers/media/dvb/frontends/tda1004x.h
index b877b23ed..e28fca057 100644
--- a/linux/drivers/media/dvb/frontends/tda1004x.h
+++ b/linux/drivers/media/dvb/frontends/tda1004x.h
@@ -71,12 +71,33 @@ struct tda1004x_config
int (*request_firmware)(struct dvb_frontend* fe, const struct firmware **fw, char* name);
};
+#if defined(CONFIG_DVB_TDA1004X) || defined(CONFIG_DVB_TDA1004X_MODULE)
extern struct dvb_frontend* tda10045_attach(const struct tda1004x_config* config,
struct i2c_adapter* i2c);
extern struct dvb_frontend* tda10046_attach(const struct tda1004x_config* config,
struct i2c_adapter* i2c);
-
-extern int tda1004x_write_byte(struct dvb_frontend* fe, int reg, int data);
+#else
+static inline struct dvb_frontend* tda10045_attach(const struct tda1004x_config* config,
+ struct i2c_adapter* i2c)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ return NULL;
+}
+static inline struct dvb_frontend* tda10046_attach(const struct tda1004x_config* config,
+ struct i2c_adapter* i2c)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ return NULL;
+}
+#endif // CONFIG_DVB_TDA1004X
+
+static inline int tda1004x_writereg(struct dvb_frontend *fe, u8 reg, u8 val) {
+ int r = 0;
+ u8 buf[] = {reg, val};
+ if (fe->ops.write)
+ r = fe->ops.write(fe, buf, 2);
+ return r;
+}
#endif // TDA1004X_H
diff --git a/linux/drivers/media/dvb/frontends/tda8083.h b/linux/drivers/media/dvb/frontends/tda8083.h
index e7a48f61e..aae15bdce 100644
--- a/linux/drivers/media/dvb/frontends/tda8083.h
+++ b/linux/drivers/media/dvb/frontends/tda8083.h
@@ -35,7 +35,16 @@ struct tda8083_config
u8 demod_address;
};
+#if defined(CONFIG_DVB_TDA8083) || defined(CONFIG_DVB_TDA8083_MODULE)
extern struct dvb_frontend* tda8083_attach(const struct tda8083_config* config,
struct i2c_adapter* i2c);
+#else
+static inline struct dvb_frontend* tda8083_attach(const struct tda8083_config* config,
+ struct i2c_adapter* i2c)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ return NULL;
+}
+#endif // CONFIG_DVB_TDA8083
#endif // TDA8083_H
diff --git a/linux/drivers/media/dvb/frontends/tda80xx.c b/linux/drivers/media/dvb/frontends/tda80xx.c
index 996fd4beb..83fc57a22 100644
--- a/linux/drivers/media/dvb/frontends/tda80xx.c
+++ b/linux/drivers/media/dvb/frontends/tda80xx.c
@@ -21,7 +21,6 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include <linux/config.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/spinlock.h>
diff --git a/linux/drivers/media/dvb/frontends/tda80xx.h b/linux/drivers/media/dvb/frontends/tda80xx.h
index 435dd9477..ce472b3fb 100644
--- a/linux/drivers/media/dvb/frontends/tda80xx.h
+++ b/linux/drivers/media/dvb/frontends/tda80xx.h
@@ -41,7 +41,16 @@ struct tda80xx_config
u8 volt18setting;
};
+#if defined(CONFIG_DVB_TDA80XX) || defined(CONFIG_DVB_TDA80XX_MODULE)
extern struct dvb_frontend* tda80xx_attach(const struct tda80xx_config* config,
struct i2c_adapter* i2c);
+#else
+static inline struct dvb_frontend* tda80xx_attach(const struct tda80xx_config* config,
+ struct i2c_adapter* i2c)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ return NULL;
+}
+#endif // CONFIG_DVB_TDA80XX
#endif // TDA80XX_H
diff --git a/linux/drivers/media/dvb/frontends/ves1820.c b/linux/drivers/media/dvb/frontends/ves1820.c
index 6bffe85c1..9b57576bf 100644
--- a/linux/drivers/media/dvb/frontends/ves1820.c
+++ b/linux/drivers/media/dvb/frontends/ves1820.c
@@ -18,7 +18,6 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include <linux/config.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/init.h>
diff --git a/linux/drivers/media/dvb/frontends/ves1820.h b/linux/drivers/media/dvb/frontends/ves1820.h
index 520f09522..f0c9dded3 100644
--- a/linux/drivers/media/dvb/frontends/ves1820.h
+++ b/linux/drivers/media/dvb/frontends/ves1820.h
@@ -41,7 +41,16 @@ struct ves1820_config
u8 selagc:1;
};
+#if defined(CONFIG_DVB_VES1820) || defined(CONFIG_DVB_VES1820_MODULE)
extern struct dvb_frontend* ves1820_attach(const struct ves1820_config* config,
struct i2c_adapter* i2c, u8 pwm);
+#else
+static inline struct dvb_frontend* ves1820_attach(const struct ves1820_config* config,
+ struct i2c_adapter* i2c, u8 pwm)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ return NULL;
+}
+#endif // CONFIG_DVB_VES1820
#endif // VES1820_H
diff --git a/linux/drivers/media/dvb/frontends/ves1x93.h b/linux/drivers/media/dvb/frontends/ves1x93.h
index ba88ae085..395fed39b 100644
--- a/linux/drivers/media/dvb/frontends/ves1x93.h
+++ b/linux/drivers/media/dvb/frontends/ves1x93.h
@@ -40,7 +40,16 @@ struct ves1x93_config
u8 invert_pwm:1;
};
+#if defined(CONFIG_DVB_VES1X93) || defined(CONFIG_DVB_VES1X93_MODULE)
extern struct dvb_frontend* ves1x93_attach(const struct ves1x93_config* config,
struct i2c_adapter* i2c);
+#else
+static inline struct dvb_frontend* ves1x93_attach(const struct ves1x93_config* config,
+ struct i2c_adapter* i2c)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ return NULL;
+}
+#endif // CONFIG_DVB_VES1X93
#endif // VES1X93_H
diff --git a/linux/drivers/media/dvb/frontends/zl10353.c b/linux/drivers/media/dvb/frontends/zl10353.c
index 27001b453..1d22d53dc 100644
--- a/linux/drivers/media/dvb/frontends/zl10353.c
+++ b/linux/drivers/media/dvb/frontends/zl10353.c
@@ -268,7 +268,6 @@ static int zl10353_init(struct dvb_frontend *fe)
static void zl10353_release(struct dvb_frontend *fe)
{
struct zl10353_state *state = fe->demodulator_priv;
-
kfree(state);
}
@@ -324,6 +323,7 @@ static struct dvb_frontend_ops zl10353_ops = {
.init = zl10353_init,
.sleep = zl10353_sleep,
+ .write = zl10353_write,
.set_frontend = zl10353_set_parameters,
.get_tune_settings = zl10353_get_tune_settings,
@@ -342,4 +342,3 @@ MODULE_AUTHOR("Chris Pascoe");
MODULE_LICENSE("GPL");
EXPORT_SYMBOL(zl10353_attach);
-EXPORT_SYMBOL(zl10353_write);
diff --git a/linux/drivers/media/dvb/frontends/zl10353.h b/linux/drivers/media/dvb/frontends/zl10353.h
index 9770cb840..6aec655d8 100644
--- a/linux/drivers/media/dvb/frontends/zl10353.h
+++ b/linux/drivers/media/dvb/frontends/zl10353.h
@@ -33,9 +33,16 @@ struct zl10353_config
int no_tuner;
};
+#if defined(CONFIG_DVB_ZL10353) || defined(CONFIG_DVB_ZL10353_MODULE)
extern struct dvb_frontend* zl10353_attach(const struct zl10353_config *config,
struct i2c_adapter *i2c);
-
-extern int zl10353_write(struct dvb_frontend *fe, u8 *ibuf, int ilen);
+#else
+static inline struct dvb_frontend* zl10353_attach(const struct zl10353_config *config,
+ struct i2c_adapter *i2c)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ return NULL;
+}
+#endif // CONFIG_DVB_ZL10353
#endif /* ZL10353_H */