summaryrefslogtreecommitdiff
path: root/drivers/media/dvb
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-02-27 04:16:20 +0300
committerLinus Torvalds <torvalds@linux-foundation.org>2010-02-27 04:16:20 +0300
commit2b8c70b2174402ca3dec13310ce56597233392d7 (patch)
tree0aed464521a2a671cbb7b4302b55fe72abc95d3d /drivers/media/dvb
parent29e1fa3565a7951cc415c634eb2b78dbdbee151d (diff)
parent3621263a4d9679726b7bc1e2546c1c03941a59b4 (diff)
downloadlinux-2b8c70b2174402ca3dec13310ce56597233392d7.tar.xz
Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6
* 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6: (362 commits) V4L-DVB: cx88-dvb: remove extra attribution for core V4L/DVB: v4l: soc_camera: fix bound checking of mbus_fmt[] index V4L/DVB: Add support for SMT7020 to cx88 V4L/DVB: radio-si470x: Use UTF-8 encoding on a comment V4L/DVB: MAINTAINERS: Telegent tlg2300 section fix V4L/DVB: gspca_stv06xx: Add support for camera button V4L/DVB: gspca_ov519: add support for the button on ov511 based cams V4L/DVB: gspca_ov519: Add support for the button on ov518 based cams V4L/DVB: gspca_ov519: add support for the button on ov519 based cams V4L/DVB: gspca_main: Fix a compile error when CONFIG_INPUT is not set V4L/DVB: gspca_main: some input error handling fixes V4L/DVB: gspca_main: Allow use of input device creation code for non int. inputs V4L/DVB: gspca_pac7302: much improved exposure control V4L/DVB: gspca_sonixb: Make sonixb driver handle pas106 and pas202 cameras V4L/DVB: gspca_sonixb: pas106: fixup bright ctrl and add gain and exposure ctrls V4L/DVB: Documentation: gspca.txt: update known mr97310a cams V4L/DVB: gspca_mr97310a: add support for the Sakar 1638x CyberPix V4L/DVB: gscpa_sonixb: limit ov7630 max framerate at 640x480 V4L/DVB: gspca_sonixb: pas202: fixup brightness ctrl and add gain and exposure ctrls V4L/DVB: gscpa_sonixb: Differentiate between sensors with a coarse and fine expo ctrl ...
Diffstat (limited to 'drivers/media/dvb')
-rw-r--r--drivers/media/dvb/Kconfig4
-rw-r--r--drivers/media/dvb/Makefile3
-rw-r--r--drivers/media/dvb/bt8xx/bt878.c21
-rw-r--r--drivers/media/dvb/bt8xx/dst.c12
-rw-r--r--drivers/media/dvb/dm1105/Kconfig1
-rw-r--r--drivers/media/dvb/dm1105/dm1105.c505
-rw-r--r--drivers/media/dvb/dvb-core/dvb_frontend.c12
-rw-r--r--drivers/media/dvb/dvb-core/dvb_ringbuffer.c1
-rw-r--r--drivers/media/dvb/dvb-usb/Kconfig8
-rw-r--r--drivers/media/dvb/dvb-usb/Makefile3
-rw-r--r--drivers/media/dvb/dvb-usb/af9015.c351
-rw-r--r--drivers/media/dvb/dvb-usb/af9015.h1
-rw-r--r--drivers/media/dvb/dvb-usb/az6027.c1151
-rw-r--r--drivers/media/dvb/dvb-usb/az6027.h14
-rw-r--r--drivers/media/dvb/dvb-usb/cxusb.c3
-rw-r--r--drivers/media/dvb/dvb-usb/dib0700.h1
-rw-r--r--drivers/media/dvb/dvb-usb/dib0700_core.c197
-rw-r--r--drivers/media/dvb/dvb-usb/dib0700_devices.c160
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-ids.h9
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-init.c2
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-remote.c1
-rw-r--r--drivers/media/dvb/dvb-usb/dw2102.c95
-rw-r--r--drivers/media/dvb/dvb-usb/friio-fe.c2
-rw-r--r--drivers/media/dvb/dvb-usb/m920x.c141
-rw-r--r--drivers/media/dvb/dvb-usb/m920x.h2
-rw-r--r--drivers/media/dvb/dvb-usb/opera1.c2
-rw-r--r--drivers/media/dvb/firewire/firedtv-1394.c19
-rw-r--r--drivers/media/dvb/firewire/firedtv-avc.c514
-rw-r--r--drivers/media/dvb/firewire/firedtv-dvb.c1
-rw-r--r--drivers/media/dvb/firewire/firedtv-fw.c2
-rw-r--r--drivers/media/dvb/firewire/firedtv.h6
-rw-r--r--drivers/media/dvb/frontends/af9013.h1
-rw-r--r--drivers/media/dvb/frontends/atbm8830.c16
-rw-r--r--drivers/media/dvb/frontends/dib0090.c2
-rw-r--r--drivers/media/dvb/frontends/dib8000.c2
-rw-r--r--drivers/media/dvb/frontends/dibx000_common.c2
-rw-r--r--drivers/media/dvb/frontends/lnbp21.c3
-rw-r--r--drivers/media/dvb/frontends/si21xx.c38
-rw-r--r--drivers/media/dvb/frontends/stv0900.h2
-rw-r--r--drivers/media/dvb/frontends/stv0900_core.c109
-rw-r--r--drivers/media/dvb/frontends/stv0900_priv.h11
-rw-r--r--drivers/media/dvb/frontends/stv0900_reg.h6
-rw-r--r--drivers/media/dvb/frontends/stv0900_sw.c54
-rw-r--r--drivers/media/dvb/frontends/stv090x.c486
-rw-r--r--drivers/media/dvb/frontends/stv090x.h13
-rw-r--r--drivers/media/dvb/frontends/stv090x_priv.h17
-rw-r--r--drivers/media/dvb/frontends/stv6110x.c188
-rw-r--r--drivers/media/dvb/frontends/stv6110x.h1
-rw-r--r--drivers/media/dvb/frontends/stv6110x_priv.h1
-rw-r--r--drivers/media/dvb/frontends/tda665x.c2
-rw-r--r--drivers/media/dvb/frontends/tda8261.c2
-rw-r--r--drivers/media/dvb/frontends/zl10036.c2
-rw-r--r--drivers/media/dvb/frontends/zl10039.c1
-rw-r--r--drivers/media/dvb/mantis/mantis_hif.c2
-rw-r--r--drivers/media/dvb/mantis/mantis_input.c2
-rw-r--r--drivers/media/dvb/mantis/mantis_pci.c5
-rw-r--r--drivers/media/dvb/ngene/Kconfig9
-rw-r--r--drivers/media/dvb/ngene/Makefile11
-rw-r--r--drivers/media/dvb/ngene/ngene-core.c2024
-rw-r--r--drivers/media/dvb/ngene/ngene.h859
-rw-r--r--drivers/media/dvb/siano/sms-cards.c1
-rw-r--r--drivers/media/dvb/siano/smscoreapi.c7
-rw-r--r--drivers/media/dvb/siano/smscoreapi.h77
-rw-r--r--drivers/media/dvb/siano/smsdvb.c318
-rw-r--r--drivers/media/dvb/siano/smsir.c6
-rw-r--r--drivers/media/dvb/ttpci/av7110_ir.c14
-rw-r--r--drivers/media/dvb/ttpci/budget-ci.c2
-rw-r--r--drivers/media/dvb/ttpci/budget.c4
68 files changed, 6393 insertions, 1151 deletions
diff --git a/drivers/media/dvb/Kconfig b/drivers/media/dvb/Kconfig
index cf8f65f309da..161ccfd471cb 100644
--- a/drivers/media/dvb/Kconfig
+++ b/drivers/media/dvb/Kconfig
@@ -76,6 +76,10 @@ comment "Supported Mantis Adapters"
depends on DVB_CORE && PCI && I2C
source "drivers/media/dvb/mantis/Kconfig"
+comment "Supported nGene Adapters"
+ depends on DVB_CORE && PCI && I2C
+ source "drivers/media/dvb/ngene/Kconfig"
+
comment "Supported DVB Frontends"
depends on DVB_CORE
source "drivers/media/dvb/frontends/Kconfig"
diff --git a/drivers/media/dvb/Makefile b/drivers/media/dvb/Makefile
index c12922c3659b..a1a08758a6f2 100644
--- a/drivers/media/dvb/Makefile
+++ b/drivers/media/dvb/Makefile
@@ -14,6 +14,7 @@ obj-y := dvb-core/ \
siano/ \
dm1105/ \
pt1/ \
- mantis/
+ mantis/ \
+ ngene/
obj-$(CONFIG_DVB_FIREDTV) += firewire/
diff --git a/drivers/media/dvb/bt8xx/bt878.c b/drivers/media/dvb/bt8xx/bt878.c
index a24c125331f0..99d62094f908 100644
--- a/drivers/media/dvb/bt8xx/bt878.c
+++ b/drivers/media/dvb/bt8xx/bt878.c
@@ -576,43 +576,30 @@ static struct pci_driver bt878_pci_driver = {
.remove = __devexit_p(bt878_remove),
};
-static int bt878_pci_driver_registered;
-
/*******************************/
/* Module management functions */
/*******************************/
-static int bt878_init_module(void)
+static int __init bt878_init_module(void)
{
bt878_num = 0;
- bt878_pci_driver_registered = 0;
printk(KERN_INFO "bt878: AUDIO driver version %d.%d.%d loaded\n",
(BT878_VERSION_CODE >> 16) & 0xff,
(BT878_VERSION_CODE >> 8) & 0xff,
BT878_VERSION_CODE & 0xff);
-/*
- bt878_check_chipset();
-*/
- /* later we register inside of bt878_find_audio_dma()
- * because we may want to ignore certain cards */
- bt878_pci_driver_registered = 1;
+
return pci_register_driver(&bt878_pci_driver);
}
-static void bt878_cleanup_module(void)
+static void __exit bt878_cleanup_module(void)
{
- if (bt878_pci_driver_registered) {
- bt878_pci_driver_registered = 0;
- pci_unregister_driver(&bt878_pci_driver);
- }
- return;
+ pci_unregister_driver(&bt878_pci_driver);
}
module_init(bt878_init_module);
module_exit(bt878_cleanup_module);
-//MODULE_AUTHOR("XXX");
MODULE_LICENSE("GPL");
/*
diff --git a/drivers/media/dvb/bt8xx/dst.c b/drivers/media/dvb/bt8xx/dst.c
index 91353a6faf1d..8b0cde38984d 100644
--- a/drivers/media/dvb/bt8xx/dst.c
+++ b/drivers/media/dvb/bt8xx/dst.c
@@ -1352,8 +1352,7 @@ static int dst_get_tuna(struct dst_state *state)
return retval;
}
if ((state->type_flags & DST_TYPE_HAS_VLF) &&
- !(state->dst_type == DST_TYPE_IS_CABLE) &&
- !(state->dst_type == DST_TYPE_IS_ATSC)) {
+ !(state->dst_type == DST_TYPE_IS_ATSC)) {
if (state->rx_tuna[9] != dst_check_sum(&state->rx_tuna[0], 9)) {
dprintk(verbose, DST_INFO, 1, "checksum failure ? ");
@@ -1820,8 +1819,13 @@ static struct dvb_frontend_ops dst_dvbc_ops = {
.frequency_max = 858000000,
.symbol_rate_min = 1000000,
.symbol_rate_max = 45000000,
- /* . symbol_rate_tolerance = ???,*/
- .caps = FE_CAN_FEC_AUTO | FE_CAN_QAM_AUTO
+ .caps = FE_CAN_FEC_AUTO |
+ FE_CAN_QAM_AUTO |
+ FE_CAN_QAM_16 |
+ FE_CAN_QAM_32 |
+ FE_CAN_QAM_64 |
+ FE_CAN_QAM_128 |
+ FE_CAN_QAM_256
},
.release = dst_release,
diff --git a/drivers/media/dvb/dm1105/Kconfig b/drivers/media/dvb/dm1105/Kconfig
index de3eeb0a8d6e..695239227cb7 100644
--- a/drivers/media/dvb/dm1105/Kconfig
+++ b/drivers/media/dvb/dm1105/Kconfig
@@ -8,6 +8,7 @@ config DVB_DM1105
select DVB_STB6000 if !DVB_FE_CUSTOMISE
select DVB_CX24116 if !DVB_FE_CUSTOMISE
select DVB_SI21XX if !DVB_FE_CUSTOMISE
+ select DVB_DS3000 if !DVB_FE_CUSTOMISE
select VIDEO_IR
help
Support for cards based on the SDMC DM1105 PCI chip like
diff --git a/drivers/media/dvb/dm1105/dm1105.c b/drivers/media/dvb/dm1105/dm1105.c
index f0f483ac8b89..383cca378b8c 100644
--- a/drivers/media/dvb/dm1105/dm1105.c
+++ b/drivers/media/dvb/dm1105/dm1105.c
@@ -43,6 +43,7 @@
#include "si21xx.h"
#include "cx24116.h"
#include "z0194a.h"
+#include "ds3000.h"
#define UNSET (-1U)
@@ -269,7 +270,7 @@ struct infrared {
u32 ir_command;
};
-struct dm1105dvb {
+struct dm1105_dev {
/* pci */
struct pci_dev *pdev;
u8 __iomem *io_mem;
@@ -308,31 +309,47 @@ struct dm1105dvb {
spinlock_t lock;
};
-#define dm_io_mem(reg) ((unsigned long)(&dm1105dvb->io_mem[reg]))
+#define dm_io_mem(reg) ((unsigned long)(&dev->io_mem[reg]))
+
+#define dm_readb(reg) inb(dm_io_mem(reg))
+#define dm_writeb(reg, value) outb((value), (dm_io_mem(reg)))
+
+#define dm_readw(reg) inw(dm_io_mem(reg))
+#define dm_writew(reg, value) outw((value), (dm_io_mem(reg)))
+
+#define dm_readl(reg) inl(dm_io_mem(reg))
+#define dm_writel(reg, value) outl((value), (dm_io_mem(reg)))
+
+#define dm_andorl(reg, mask, value) \
+ outl((inl(dm_io_mem(reg)) & ~(mask)) |\
+ ((value) & (mask)), (dm_io_mem(reg)))
+
+#define dm_setl(reg, bit) dm_andorl((reg), (bit), (bit))
+#define dm_clearl(reg, bit) dm_andorl((reg), (bit), 0)
static int dm1105_i2c_xfer(struct i2c_adapter *i2c_adap,
struct i2c_msg *msgs, int num)
{
- struct dm1105dvb *dm1105dvb ;
+ struct dm1105_dev *dev ;
int addr, rc, i, j, k, len, byte, data;
u8 status;
- dm1105dvb = i2c_adap->algo_data;
+ dev = i2c_adap->algo_data;
for (i = 0; i < num; i++) {
- outb(0x00, dm_io_mem(DM1105_I2CCTR));
+ dm_writeb(DM1105_I2CCTR, 0x00);
if (msgs[i].flags & I2C_M_RD) {
/* read bytes */
addr = msgs[i].addr << 1;
addr |= 1;
- outb(addr, dm_io_mem(DM1105_I2CDAT));
+ dm_writeb(DM1105_I2CDAT, addr);
for (byte = 0; byte < msgs[i].len; byte++)
- outb(0, dm_io_mem(DM1105_I2CDAT + byte + 1));
+ dm_writeb(DM1105_I2CDAT + byte + 1, 0);
- outb(0x81 + msgs[i].len, dm_io_mem(DM1105_I2CCTR));
+ dm_writeb(DM1105_I2CCTR, 0x81 + msgs[i].len);
for (j = 0; j < 55; j++) {
mdelay(10);
- status = inb(dm_io_mem(DM1105_I2CSTS));
+ status = dm_readb(DM1105_I2CSTS);
if ((status & 0xc0) == 0x40)
break;
}
@@ -340,56 +357,54 @@ static int dm1105_i2c_xfer(struct i2c_adapter *i2c_adap,
return -1;
for (byte = 0; byte < msgs[i].len; byte++) {
- rc = inb(dm_io_mem(DM1105_I2CDAT + byte + 1));
+ rc = dm_readb(DM1105_I2CDAT + byte + 1);
if (rc < 0)
goto err;
msgs[i].buf[byte] = rc;
}
- } else {
- if ((msgs[i].buf[0] == 0xf7) && (msgs[i].addr == 0x55)) {
- /* prepaired for cx24116 firmware */
- /* Write in small blocks */
- len = msgs[i].len - 1;
- k = 1;
- do {
- outb(msgs[i].addr << 1, dm_io_mem(DM1105_I2CDAT));
- outb(0xf7, dm_io_mem(DM1105_I2CDAT + 1));
- for (byte = 0; byte < (len > 48 ? 48 : len); byte++) {
- data = msgs[i].buf[k+byte];
- outb(data, dm_io_mem(DM1105_I2CDAT + byte + 2));
- }
- outb(0x82 + (len > 48 ? 48 : len), dm_io_mem(DM1105_I2CCTR));
- for (j = 0; j < 25; j++) {
- mdelay(10);
- status = inb(dm_io_mem(DM1105_I2CSTS));
- if ((status & 0xc0) == 0x40)
- break;
- }
-
- if (j >= 25)
- return -1;
-
- k += 48;
- len -= 48;
- } while (len > 0);
- } else {
- /* write bytes */
- outb(msgs[i].addr<<1, dm_io_mem(DM1105_I2CDAT));
- for (byte = 0; byte < msgs[i].len; byte++) {
- data = msgs[i].buf[byte];
- outb(data, dm_io_mem(DM1105_I2CDAT + byte + 1));
+ } else if ((msgs[i].buf[0] == 0xf7) && (msgs[i].addr == 0x55)) {
+ /* prepaired for cx24116 firmware */
+ /* Write in small blocks */
+ len = msgs[i].len - 1;
+ k = 1;
+ do {
+ dm_writeb(DM1105_I2CDAT, msgs[i].addr << 1);
+ dm_writeb(DM1105_I2CDAT + 1, 0xf7);
+ for (byte = 0; byte < (len > 48 ? 48 : len); byte++) {
+ data = msgs[i].buf[k + byte];
+ dm_writeb(DM1105_I2CDAT + byte + 2, data);
}
- outb(0x81 + msgs[i].len, dm_io_mem(DM1105_I2CCTR));
+ dm_writeb(DM1105_I2CCTR, 0x82 + (len > 48 ? 48 : len));
for (j = 0; j < 25; j++) {
mdelay(10);
- status = inb(dm_io_mem(DM1105_I2CSTS));
+ status = dm_readb(DM1105_I2CSTS);
if ((status & 0xc0) == 0x40)
break;
}
if (j >= 25)
return -1;
+
+ k += 48;
+ len -= 48;
+ } while (len > 0);
+ } else {
+ /* write bytes */
+ dm_writeb(DM1105_I2CDAT, msgs[i].addr << 1);
+ for (byte = 0; byte < msgs[i].len; byte++) {
+ data = msgs[i].buf[byte];
+ dm_writeb(DM1105_I2CDAT + byte + 1, data);
}
+ dm_writeb(DM1105_I2CCTR, 0x81 + msgs[i].len);
+ for (j = 0; j < 25; j++) {
+ mdelay(10);
+ status = dm_readb(DM1105_I2CSTS);
+ if ((status & 0xc0) == 0x40)
+ break;
+ }
+
+ if (j >= 25)
+ return -1;
}
}
return num;
@@ -407,22 +422,22 @@ static struct i2c_algorithm dm1105_algo = {
.functionality = functionality,
};
-static inline struct dm1105dvb *feed_to_dm1105dvb(struct dvb_demux_feed *feed)
+static inline struct dm1105_dev *feed_to_dm1105_dev(struct dvb_demux_feed *feed)
{
- return container_of(feed->demux, struct dm1105dvb, demux);
+ return container_of(feed->demux, struct dm1105_dev, demux);
}
-static inline struct dm1105dvb *frontend_to_dm1105dvb(struct dvb_frontend *fe)
+static inline struct dm1105_dev *frontend_to_dm1105_dev(struct dvb_frontend *fe)
{
- return container_of(fe->dvb, struct dm1105dvb, dvb_adapter);
+ return container_of(fe->dvb, struct dm1105_dev, dvb_adapter);
}
-static int dm1105dvb_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
+static int dm1105_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
{
- struct dm1105dvb *dm1105dvb = frontend_to_dm1105dvb(fe);
+ struct dm1105_dev *dev = frontend_to_dm1105_dev(fe);
u32 lnb_mask, lnb_13v, lnb_18v, lnb_off;
- switch (dm1105dvb->boardnr) {
+ switch (dev->boardnr) {
case DM1105_BOARD_AXESS_DM05:
lnb_mask = DM05_LNB_MASK;
lnb_off = DM05_LNB_OFF;
@@ -438,62 +453,67 @@ static int dm1105dvb_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t volta
lnb_18v = DM1105_LNB_18V;
}
- outl(lnb_mask, dm_io_mem(DM1105_GPIOCTR));
+ dm_writel(DM1105_GPIOCTR, lnb_mask);
if (voltage == SEC_VOLTAGE_18)
- outl(lnb_18v , dm_io_mem(DM1105_GPIOVAL));
+ dm_writel(DM1105_GPIOVAL, lnb_18v);
else if (voltage == SEC_VOLTAGE_13)
- outl(lnb_13v, dm_io_mem(DM1105_GPIOVAL));
+ dm_writel(DM1105_GPIOVAL, lnb_13v);
else
- outl(lnb_off, dm_io_mem(DM1105_GPIOVAL));
+ dm_writel(DM1105_GPIOVAL, lnb_off);
return 0;
}
-static void dm1105dvb_set_dma_addr(struct dm1105dvb *dm1105dvb)
+static void dm1105_set_dma_addr(struct dm1105_dev *dev)
{
- outl(cpu_to_le32(dm1105dvb->dma_addr), dm_io_mem(DM1105_STADR));
+ dm_writel(DM1105_STADR, cpu_to_le32(dev->dma_addr));
}
-static int __devinit dm1105dvb_dma_map(struct dm1105dvb *dm1105dvb)
+static int __devinit dm1105_dma_map(struct dm1105_dev *dev)
{
- dm1105dvb->ts_buf = pci_alloc_consistent(dm1105dvb->pdev, 6*DM1105_DMA_BYTES, &dm1105dvb->dma_addr);
+ dev->ts_buf = pci_alloc_consistent(dev->pdev,
+ 6 * DM1105_DMA_BYTES,
+ &dev->dma_addr);
- return !dm1105dvb->ts_buf;
+ return !dev->ts_buf;
}
-static void dm1105dvb_dma_unmap(struct dm1105dvb *dm1105dvb)
+static void dm1105_dma_unmap(struct dm1105_dev *dev)
{
- pci_free_consistent(dm1105dvb->pdev, 6*DM1105_DMA_BYTES, dm1105dvb->ts_buf, dm1105dvb->dma_addr);
+ pci_free_consistent(dev->pdev,
+ 6 * DM1105_DMA_BYTES,
+ dev->ts_buf,
+ dev->dma_addr);
}
-static void dm1105dvb_enable_irqs(struct dm1105dvb *dm1105dvb)
+static void dm1105_enable_irqs(struct dm1105_dev *dev)
{
- outb(INTMAK_ALLMASK, dm_io_mem(DM1105_INTMAK));
- outb(1, dm_io_mem(DM1105_CR));
+ dm_writeb(DM1105_INTMAK, INTMAK_ALLMASK);
+ dm_writeb(DM1105_CR, 1);
}
-static void dm1105dvb_disable_irqs(struct dm1105dvb *dm1105dvb)
+static void dm1105_disable_irqs(struct dm1105_dev *dev)
{
- outb(INTMAK_IRM, dm_io_mem(DM1105_INTMAK));
- outb(0, dm_io_mem(DM1105_CR));
+ dm_writeb(DM1105_INTMAK, INTMAK_IRM);
+ dm_writeb(DM1105_CR, 0);
}
-static int dm1105dvb_start_feed(struct dvb_demux_feed *f)
+static int dm1105_start_feed(struct dvb_demux_feed *f)
{
- struct dm1105dvb *dm1105dvb = feed_to_dm1105dvb(f);
+ struct dm1105_dev *dev = feed_to_dm1105_dev(f);
- if (dm1105dvb->full_ts_users++ == 0)
- dm1105dvb_enable_irqs(dm1105dvb);
+ if (dev->full_ts_users++ == 0)
+ dm1105_enable_irqs(dev);
return 0;
}
-static int dm1105dvb_stop_feed(struct dvb_demux_feed *f)
+static int dm1105_stop_feed(struct dvb_demux_feed *f)
{
- struct dm1105dvb *dm1105dvb = feed_to_dm1105dvb(f);
+ struct dm1105_dev *dev = feed_to_dm1105_dev(f);
- if (--dm1105dvb->full_ts_users == 0)
- dm1105dvb_disable_irqs(dm1105dvb);
+ if (--dev->full_ts_users == 0)
+ dm1105_disable_irqs(dev);
return 0;
}
@@ -517,68 +537,64 @@ static void dm1105_emit_key(struct work_struct *work)
/* work handler */
static void dm1105_dmx_buffer(struct work_struct *work)
{
- struct dm1105dvb *dm1105dvb =
- container_of(work, struct dm1105dvb, work);
+ struct dm1105_dev *dev = container_of(work, struct dm1105_dev, work);
unsigned int nbpackets;
- u32 oldwrp = dm1105dvb->wrp;
- u32 nextwrp = dm1105dvb->nextwrp;
+ u32 oldwrp = dev->wrp;
+ u32 nextwrp = dev->nextwrp;
- if (!((dm1105dvb->ts_buf[oldwrp] == 0x47) &&
- (dm1105dvb->ts_buf[oldwrp + 188] == 0x47) &&
- (dm1105dvb->ts_buf[oldwrp + 188 * 2] == 0x47))) {
- dm1105dvb->PacketErrorCount++;
+ if (!((dev->ts_buf[oldwrp] == 0x47) &&
+ (dev->ts_buf[oldwrp + 188] == 0x47) &&
+ (dev->ts_buf[oldwrp + 188 * 2] == 0x47))) {
+ dev->PacketErrorCount++;
/* bad packet found */
- if ((dm1105dvb->PacketErrorCount >= 2) &&
- (dm1105dvb->dmarst == 0)) {
- outb(1, dm_io_mem(DM1105_RST));
- dm1105dvb->wrp = 0;
- dm1105dvb->PacketErrorCount = 0;
- dm1105dvb->dmarst = 0;
+ if ((dev->PacketErrorCount >= 2) &&
+ (dev->dmarst == 0)) {
+ dm_writeb(DM1105_RST, 1);
+ dev->wrp = 0;
+ dev->PacketErrorCount = 0;
+ dev->dmarst = 0;
return;
}
}
if (nextwrp < oldwrp) {
- memcpy(dm1105dvb->ts_buf + dm1105dvb->buffer_size,
- dm1105dvb->ts_buf, nextwrp);
- nbpackets = ((dm1105dvb->buffer_size - oldwrp) + nextwrp) / 188;
+ memcpy(dev->ts_buf + dev->buffer_size, dev->ts_buf, nextwrp);
+ nbpackets = ((dev->buffer_size - oldwrp) + nextwrp) / 188;
} else
nbpackets = (nextwrp - oldwrp) / 188;
- dm1105dvb->wrp = nextwrp;
- dvb_dmx_swfilter_packets(&dm1105dvb->demux,
- &dm1105dvb->ts_buf[oldwrp], nbpackets);
+ dev->wrp = nextwrp;
+ dvb_dmx_swfilter_packets(&dev->demux, &dev->ts_buf[oldwrp], nbpackets);
}
-static irqreturn_t dm1105dvb_irq(int irq, void *dev_id)
+static irqreturn_t dm1105_irq(int irq, void *dev_id)
{
- struct dm1105dvb *dm1105dvb = dev_id;
+ struct dm1105_dev *dev = dev_id;
/* Read-Write INSTS Ack's Interrupt for DM1105 chip 16.03.2008 */
- unsigned int intsts = inb(dm_io_mem(DM1105_INTSTS));
- outb(intsts, dm_io_mem(DM1105_INTSTS));
+ unsigned int intsts = dm_readb(DM1105_INTSTS);
+ dm_writeb(DM1105_INTSTS, intsts);
switch (intsts) {
case INTSTS_TSIRQ:
case (INTSTS_TSIRQ | INTSTS_IR):
- dm1105dvb->nextwrp = inl(dm_io_mem(DM1105_WRP)) -
- inl(dm_io_mem(DM1105_STADR));
- queue_work(dm1105dvb->wq, &dm1105dvb->work);
+ dev->nextwrp = dm_readl(DM1105_WRP) - dm_readl(DM1105_STADR);
+ queue_work(dev->wq, &dev->work);
break;
case INTSTS_IR:
- dm1105dvb->ir.ir_command = inl(dm_io_mem(DM1105_IRCODE));
- schedule_work(&dm1105dvb->ir.work);
+ dev->ir.ir_command = dm_readl(DM1105_IRCODE);
+ schedule_work(&dev->ir.work);
break;
}
return IRQ_HANDLED;
}
-int __devinit dm1105_ir_init(struct dm1105dvb *dm1105)
+int __devinit dm1105_ir_init(struct dm1105_dev *dm1105)
{
struct input_dev *input_dev;
struct ir_scancode_table *ir_codes = &ir_codes_dm1105_nec_table;
- int ir_type = IR_TYPE_OTHER;
+ u64 ir_type = IR_TYPE_OTHER;
int err = -ENOMEM;
input_dev = input_allocate_device();
@@ -611,51 +627,51 @@ int __devinit dm1105_ir_init(struct dm1105dvb *dm1105)
INIT_WORK(&dm1105->ir.work, dm1105_emit_key);
- err = ir_input_register(input_dev, ir_codes);
+ err = ir_input_register(input_dev, ir_codes, NULL);
return err;
}
-void __devexit dm1105_ir_exit(struct dm1105dvb *dm1105)
+void __devexit dm1105_ir_exit(struct dm1105_dev *dm1105)
{
ir_input_unregister(dm1105->ir.input_dev);
}
-static int __devinit dm1105dvb_hw_init(struct dm1105dvb *dm1105dvb)
+static int __devinit dm1105_hw_init(struct dm1105_dev *dev)
{
- dm1105dvb_disable_irqs(dm1105dvb);
+ dm1105_disable_irqs(dev);
- outb(0, dm_io_mem(DM1105_HOST_CTR));
+ dm_writeb(DM1105_HOST_CTR, 0);
/*DATALEN 188,*/
- outb(188, dm_io_mem(DM1105_DTALENTH));
+ dm_writeb(DM1105_DTALENTH, 188);
/*TS_STRT TS_VALP MSBFIRST TS_MODE ALPAS TSPES*/
- outw(0xc10a, dm_io_mem(DM1105_TSCTR));
+ dm_writew(DM1105_TSCTR, 0xc10a);
/* map DMA and set address */
- dm1105dvb_dma_map(dm1105dvb);
- dm1105dvb_set_dma_addr(dm1105dvb);
+ dm1105_dma_map(dev);
+ dm1105_set_dma_addr(dev);
/* big buffer */
- outl(5*DM1105_DMA_BYTES, dm_io_mem(DM1105_RLEN));
- outb(47, dm_io_mem(DM1105_INTCNT));
+ dm_writel(DM1105_RLEN, 5 * DM1105_DMA_BYTES);
+ dm_writeb(DM1105_INTCNT, 47);
/* IR NEC mode enable */
- outb((DM1105_IR_EN | DM1105_SYS_CHK), dm_io_mem(DM1105_IRCTR));
- outb(0, dm_io_mem(DM1105_IRMODE));
- outw(0, dm_io_mem(DM1105_SYSTEMCODE));
+ dm_writeb(DM1105_IRCTR, (DM1105_IR_EN | DM1105_SYS_CHK));
+ dm_writeb(DM1105_IRMODE, 0);
+ dm_writew(DM1105_SYSTEMCODE, 0);
return 0;
}
-static void dm1105dvb_hw_exit(struct dm1105dvb *dm1105dvb)
+static void dm1105_hw_exit(struct dm1105_dev *dev)
{
- dm1105dvb_disable_irqs(dm1105dvb);
+ dm1105_disable_irqs(dev);
/* IR disable */
- outb(0, dm_io_mem(DM1105_IRCTR));
- outb(INTMAK_NONEMASK, dm_io_mem(DM1105_INTMAK));
+ dm_writeb(DM1105_IRCTR, 0);
+ dm_writeb(DM1105_INTMAK, INTMAK_NONEMASK);
- dm1105dvb_dma_unmap(dm1105dvb);
+ dm1105_dma_unmap(dev);
}
static struct stv0299_config sharp_z0194a_config = {
@@ -685,70 +701,79 @@ static struct cx24116_config serit_sp2633_config = {
.demod_address = 0x55,
};
-static int __devinit frontend_init(struct dm1105dvb *dm1105dvb)
+static struct ds3000_config dvbworld_ds3000_config = {
+ .demod_address = 0x68,
+};
+
+static int __devinit frontend_init(struct dm1105_dev *dev)
{
int ret;
- switch (dm1105dvb->boardnr) {
+ switch (dev->boardnr) {
case DM1105_BOARD_DVBWORLD_2004:
- dm1105dvb->fe = dvb_attach(
+ dev->fe = dvb_attach(
cx24116_attach, &serit_sp2633_config,
- &dm1105dvb->i2c_adap);
- if (dm1105dvb->fe)
- dm1105dvb->fe->ops.set_voltage = dm1105dvb_set_voltage;
+ &dev->i2c_adap);
+ if (dev->fe) {
+ dev->fe->ops.set_voltage = dm1105_set_voltage;
+ break;
+ }
+
+ dev->fe = dvb_attach(
+ ds3000_attach, &dvbworld_ds3000_config,
+ &dev->i2c_adap);
+ if (dev->fe)
+ dev->fe->ops.set_voltage = dm1105_set_voltage;
break;
case DM1105_BOARD_DVBWORLD_2002:
case DM1105_BOARD_AXESS_DM05:
default:
- dm1105dvb->fe = dvb_attach(
+ dev->fe = dvb_attach(
stv0299_attach, &sharp_z0194a_config,
- &dm1105dvb->i2c_adap);
- if (dm1105dvb->fe) {
- dm1105dvb->fe->ops.set_voltage =
- dm1105dvb_set_voltage;
- dvb_attach(dvb_pll_attach, dm1105dvb->fe, 0x60,
- &dm1105dvb->i2c_adap, DVB_PLL_OPERA1);
+ &dev->i2c_adap);
+ if (dev->fe) {
+ dev->fe->ops.set_voltage = dm1105_set_voltage;
+ dvb_attach(dvb_pll_attach, dev->fe, 0x60,
+ &dev->i2c_adap, DVB_PLL_OPERA1);
break;
}
- dm1105dvb->fe = dvb_attach(
+ dev->fe = dvb_attach(
stv0288_attach, &earda_config,
- &dm1105dvb->i2c_adap);
- if (dm1105dvb->fe) {
- dm1105dvb->fe->ops.set_voltage =
- dm1105dvb_set_voltage;
- dvb_attach(stb6000_attach, dm1105dvb->fe, 0x61,
- &dm1105dvb->i2c_adap);
+ &dev->i2c_adap);
+ if (dev->fe) {
+ dev->fe->ops.set_voltage = dm1105_set_voltage;
+ dvb_attach(stb6000_attach, dev->fe, 0x61,
+ &dev->i2c_adap);
break;
}
- dm1105dvb->fe = dvb_attach(
+ dev->fe = dvb_attach(
si21xx_attach, &serit_config,
- &dm1105dvb->i2c_adap);
- if (dm1105dvb->fe)
- dm1105dvb->fe->ops.set_voltage =
- dm1105dvb_set_voltage;
+ &dev->i2c_adap);
+ if (dev->fe)
+ dev->fe->ops.set_voltage = dm1105_set_voltage;
}
- if (!dm1105dvb->fe) {
- dev_err(&dm1105dvb->pdev->dev, "could not attach frontend\n");
+ if (!dev->fe) {
+ dev_err(&dev->pdev->dev, "could not attach frontend\n");
return -ENODEV;
}
- ret = dvb_register_frontend(&dm1105dvb->dvb_adapter, dm1105dvb->fe);
+ ret = dvb_register_frontend(&dev->dvb_adapter, dev->fe);
if (ret < 0) {
- if (dm1105dvb->fe->ops.release)
- dm1105dvb->fe->ops.release(dm1105dvb->fe);
- dm1105dvb->fe = NULL;
+ if (dev->fe->ops.release)
+ dev->fe->ops.release(dev->fe);
+ dev->fe = NULL;
return ret;
}
return 0;
}
-static void __devinit dm1105dvb_read_mac(struct dm1105dvb *dm1105dvb, u8 *mac)
+static void __devinit dm1105_read_mac(struct dm1105_dev *dev, u8 *mac)
{
static u8 command[1] = { 0x28 };
@@ -766,47 +791,47 @@ static void __devinit dm1105dvb_read_mac(struct dm1105dvb *dm1105dvb, u8 *mac)
},
};
- dm1105_i2c_xfer(&dm1105dvb->i2c_adap, msg , 2);
- dev_info(&dm1105dvb->pdev->dev, "MAC %pM\n", mac);
+ dm1105_i2c_xfer(&dev->i2c_adap, msg , 2);
+ dev_info(&dev->pdev->dev, "MAC %pM\n", mac);
}
static int __devinit dm1105_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
- struct dm1105dvb *dm1105dvb;
+ struct dm1105_dev *dev;
struct dvb_adapter *dvb_adapter;
struct dvb_demux *dvbdemux;
struct dmx_demux *dmx;
int ret = -ENOMEM;
int i;
- dm1105dvb = kzalloc(sizeof(struct dm1105dvb), GFP_KERNEL);
- if (!dm1105dvb)
+ dev = kzalloc(sizeof(struct dm1105_dev), GFP_KERNEL);
+ if (!dev)
return -ENOMEM;
/* board config */
- dm1105dvb->nr = dm1105_devcount;
- dm1105dvb->boardnr = UNSET;
- if (card[dm1105dvb->nr] < ARRAY_SIZE(dm1105_boards))
- dm1105dvb->boardnr = card[dm1105dvb->nr];
- for (i = 0; UNSET == dm1105dvb->boardnr &&
+ dev->nr = dm1105_devcount;
+ dev->boardnr = UNSET;
+ if (card[dev->nr] < ARRAY_SIZE(dm1105_boards))
+ dev->boardnr = card[dev->nr];
+ for (i = 0; UNSET == dev->boardnr &&
i < ARRAY_SIZE(dm1105_subids); i++)
if (pdev->subsystem_vendor ==
dm1105_subids[i].subvendor &&
pdev->subsystem_device ==
dm1105_subids[i].subdevice)
- dm1105dvb->boardnr = dm1105_subids[i].card;
+ dev->boardnr = dm1105_subids[i].card;
- if (UNSET == dm1105dvb->boardnr) {
- dm1105dvb->boardnr = DM1105_BOARD_UNKNOWN;
+ if (UNSET == dev->boardnr) {
+ dev->boardnr = DM1105_BOARD_UNKNOWN;
dm1105_card_list(pdev);
}
dm1105_devcount++;
- dm1105dvb->pdev = pdev;
- dm1105dvb->buffer_size = 5 * DM1105_DMA_BYTES;
- dm1105dvb->PacketErrorCount = 0;
- dm1105dvb->dmarst = 0;
+ dev->pdev = pdev;
+ dev->buffer_size = 5 * DM1105_DMA_BYTES;
+ dev->PacketErrorCount = 0;
+ dev->dmarst = 0;
ret = pci_enable_device(pdev);
if (ret < 0)
@@ -822,47 +847,47 @@ static int __devinit dm1105_probe(struct pci_dev *pdev,
if (ret < 0)
goto err_pci_disable_device;
- dm1105dvb->io_mem = pci_iomap(pdev, 0, pci_resource_len(pdev, 0));
- if (!dm1105dvb->io_mem) {
+ dev->io_mem = pci_iomap(pdev, 0, pci_resource_len(pdev, 0));
+ if (!dev->io_mem) {
ret = -EIO;
goto err_pci_release_regions;
}
- spin_lock_init(&dm1105dvb->lock);
- pci_set_drvdata(pdev, dm1105dvb);
+ spin_lock_init(&dev->lock);
+ pci_set_drvdata(pdev, dev);
- ret = dm1105dvb_hw_init(dm1105dvb);
+ ret = dm1105_hw_init(dev);
if (ret < 0)
goto err_pci_iounmap;
/* i2c */
- i2c_set_adapdata(&dm1105dvb->i2c_adap, dm1105dvb);
- strcpy(dm1105dvb->i2c_adap.name, DRIVER_NAME);
- dm1105dvb->i2c_adap.owner = THIS_MODULE;
- dm1105dvb->i2c_adap.class = I2C_CLASS_TV_DIGITAL;
- dm1105dvb->i2c_adap.dev.parent = &pdev->dev;
- dm1105dvb->i2c_adap.algo = &dm1105_algo;
- dm1105dvb->i2c_adap.algo_data = dm1105dvb;
- ret = i2c_add_adapter(&dm1105dvb->i2c_adap);
+ i2c_set_adapdata(&dev->i2c_adap, dev);
+ strcpy(dev->i2c_adap.name, DRIVER_NAME);
+ dev->i2c_adap.owner = THIS_MODULE;
+ dev->i2c_adap.class = I2C_CLASS_TV_DIGITAL;
+ dev->i2c_adap.dev.parent = &pdev->dev;
+ dev->i2c_adap.algo = &dm1105_algo;
+ dev->i2c_adap.algo_data = dev;
+ ret = i2c_add_adapter(&dev->i2c_adap);
if (ret < 0)
- goto err_dm1105dvb_hw_exit;
+ goto err_dm1105_hw_exit;
/* dvb */
- ret = dvb_register_adapter(&dm1105dvb->dvb_adapter, DRIVER_NAME,
+ ret = dvb_register_adapter(&dev->dvb_adapter, DRIVER_NAME,
THIS_MODULE, &pdev->dev, adapter_nr);
if (ret < 0)
goto err_i2c_del_adapter;
- dvb_adapter = &dm1105dvb->dvb_adapter;
+ dvb_adapter = &dev->dvb_adapter;
- dm1105dvb_read_mac(dm1105dvb, dvb_adapter->proposed_mac);
+ dm1105_read_mac(dev, dvb_adapter->proposed_mac);
- dvbdemux = &dm1105dvb->demux;
+ dvbdemux = &dev->demux;
dvbdemux->filternum = 256;
dvbdemux->feednum = 256;
- dvbdemux->start_feed = dm1105dvb_start_feed;
- dvbdemux->stop_feed = dm1105dvb_stop_feed;
+ dvbdemux->start_feed = dm1105_start_feed;
+ dvbdemux->stop_feed = dm1105_stop_feed;
dvbdemux->dmx.capabilities = (DMX_TS_FILTERING |
DMX_SECTION_FILTERING | DMX_MEMORY_BASED_FILTERING);
ret = dvb_dmx_init(dvbdemux);
@@ -870,113 +895,113 @@ static int __devinit dm1105_probe(struct pci_dev *pdev,
goto err_dvb_unregister_adapter;
dmx = &dvbdemux->dmx;
- dm1105dvb->dmxdev.filternum = 256;
- dm1105dvb->dmxdev.demux = dmx;
- dm1105dvb->dmxdev.capabilities = 0;
+ dev->dmxdev.filternum = 256;
+ dev->dmxdev.demux = dmx;
+ dev->dmxdev.capabilities = 0;
- ret = dvb_dmxdev_init(&dm1105dvb->dmxdev, dvb_adapter);
+ ret = dvb_dmxdev_init(&dev->dmxdev, dvb_adapter);
if (ret < 0)
goto err_dvb_dmx_release;
- dm1105dvb->hw_frontend.source = DMX_FRONTEND_0;
+ dev->hw_frontend.source = DMX_FRONTEND_0;
- ret = dmx->add_frontend(dmx, &dm1105dvb->hw_frontend);
+ ret = dmx->add_frontend(dmx, &dev->hw_frontend);
if (ret < 0)
goto err_dvb_dmxdev_release;
- dm1105dvb->mem_frontend.source = DMX_MEMORY_FE;
+ dev->mem_frontend.source = DMX_MEMORY_FE;
- ret = dmx->add_frontend(dmx, &dm1105dvb->mem_frontend);
+ ret = dmx->add_frontend(dmx, &dev->mem_frontend);
if (ret < 0)
goto err_remove_hw_frontend;
- ret = dmx->connect_frontend(dmx, &dm1105dvb->hw_frontend);
+ ret = dmx->connect_frontend(dmx, &dev->hw_frontend);
if (ret < 0)
goto err_remove_mem_frontend;
- ret = frontend_init(dm1105dvb);
+ ret = frontend_init(dev);
if (ret < 0)
goto err_disconnect_frontend;
- dvb_net_init(dvb_adapter, &dm1105dvb->dvbnet, dmx);
- dm1105_ir_init(dm1105dvb);
+ dvb_net_init(dvb_adapter, &dev->dvbnet, dmx);
+ dm1105_ir_init(dev);
- INIT_WORK(&dm1105dvb->work, dm1105_dmx_buffer);
- sprintf(dm1105dvb->wqn, "%s/%d", dvb_adapter->name, dvb_adapter->num);
- dm1105dvb->wq = create_singlethread_workqueue(dm1105dvb->wqn);
- if (!dm1105dvb->wq)
+ INIT_WORK(&dev->work, dm1105_dmx_buffer);
+ sprintf(dev->wqn, "%s/%d", dvb_adapter->name, dvb_adapter->num);
+ dev->wq = create_singlethread_workqueue(dev->wqn);
+ if (!dev->wq)
goto err_dvb_net;
- ret = request_irq(pdev->irq, dm1105dvb_irq, IRQF_SHARED,
- DRIVER_NAME, dm1105dvb);
+ ret = request_irq(pdev->irq, dm1105_irq, IRQF_SHARED,
+ DRIVER_NAME, dev);
if (ret < 0)
goto err_workqueue;
return 0;
err_workqueue:
- destroy_workqueue(dm1105dvb->wq);
+ destroy_workqueue(dev->wq);
err_dvb_net:
- dvb_net_release(&dm1105dvb->dvbnet);
+ dvb_net_release(&dev->dvbnet);
err_disconnect_frontend:
dmx->disconnect_frontend(dmx);
err_remove_mem_frontend:
- dmx->remove_frontend(dmx, &dm1105dvb->mem_frontend);
+ dmx->remove_frontend(dmx, &dev->mem_frontend);
err_remove_hw_frontend:
- dmx->remove_frontend(dmx, &dm1105dvb->hw_frontend);
+ dmx->remove_frontend(dmx, &dev->hw_frontend);
err_dvb_dmxdev_release:
- dvb_dmxdev_release(&dm1105dvb->dmxdev);
+ dvb_dmxdev_release(&dev->dmxdev);
err_dvb_dmx_release:
dvb_dmx_release(dvbdemux);
err_dvb_unregister_adapter:
dvb_unregister_adapter(dvb_adapter);
err_i2c_del_adapter:
- i2c_del_adapter(&dm1105dvb->i2c_adap);
-err_dm1105dvb_hw_exit:
- dm1105dvb_hw_exit(dm1105dvb);
+ i2c_del_adapter(&dev->i2c_adap);
+err_dm1105_hw_exit:
+ dm1105_hw_exit(dev);
err_pci_iounmap:
- pci_iounmap(pdev, dm1105dvb->io_mem);
+ pci_iounmap(pdev, dev->io_mem);
err_pci_release_regions:
pci_release_regions(pdev);
err_pci_disable_device:
pci_disable_device(pdev);
err_kfree:
pci_set_drvdata(pdev, NULL);
- kfree(dm1105dvb);
+ kfree(dev);
return ret;
}
static void __devexit dm1105_remove(struct pci_dev *pdev)
{
- struct dm1105dvb *dm1105dvb = pci_get_drvdata(pdev);
- struct dvb_adapter *dvb_adapter = &dm1105dvb->dvb_adapter;
- struct dvb_demux *dvbdemux = &dm1105dvb->demux;
+ struct dm1105_dev *dev = pci_get_drvdata(pdev);
+ struct dvb_adapter *dvb_adapter = &dev->dvb_adapter;
+ struct dvb_demux *dvbdemux = &dev->demux;
struct dmx_demux *dmx = &dvbdemux->dmx;
- dm1105_ir_exit(dm1105dvb);
+ dm1105_ir_exit(dev);
dmx->close(dmx);
- dvb_net_release(&dm1105dvb->dvbnet);
- if (dm1105dvb->fe)
- dvb_unregister_frontend(dm1105dvb->fe);
+ dvb_net_release(&dev->dvbnet);
+ if (dev->fe)
+ dvb_unregister_frontend(dev->fe);
dmx->disconnect_frontend(dmx);
- dmx->remove_frontend(dmx, &dm1105dvb->mem_frontend);
- dmx->remove_frontend(dmx, &dm1105dvb->hw_frontend);
- dvb_dmxdev_release(&dm1105dvb->dmxdev);
+ dmx->remove_frontend(dmx, &dev->mem_frontend);
+ dmx->remove_frontend(dmx, &dev->hw_frontend);
+ dvb_dmxdev_release(&dev->dmxdev);
dvb_dmx_release(dvbdemux);
dvb_unregister_adapter(dvb_adapter);
- if (&dm1105dvb->i2c_adap)
- i2c_del_adapter(&dm1105dvb->i2c_adap);
+ if (&dev->i2c_adap)
+ i2c_del_adapter(&dev->i2c_adap);
- dm1105dvb_hw_exit(dm1105dvb);
+ dm1105_hw_exit(dev);
synchronize_irq(pdev->irq);
- free_irq(pdev->irq, dm1105dvb);
- pci_iounmap(pdev, dm1105dvb->io_mem);
+ free_irq(pdev->irq, dev);
+ pci_iounmap(pdev, dev->io_mem);
pci_release_regions(pdev);
pci_disable_device(pdev);
pci_set_drvdata(pdev, NULL);
dm1105_devcount--;
- kfree(dm1105dvb);
+ kfree(dev);
}
static struct pci_device_id dm1105_id_table[] __devinitdata = {
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c
index 07461222a7f5..55ea260572bf 100644
--- a/drivers/media/dvb/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb/dvb-core/dvb_frontend.c
@@ -1199,8 +1199,6 @@ static int dtv_property_process_get(struct dvb_frontend *fe,
{
int r = 0;
- dtv_property_dump(tvp);
-
/* Allow the frontend to validate incoming properties */
if (fe->ops.get_property)
r = fe->ops.get_property(fe, tvp);
@@ -1323,6 +1321,8 @@ static int dtv_property_process_get(struct dvb_frontend *fe,
r = -1;
}
+ dtv_property_dump(tvp);
+
return r;
}
@@ -1488,7 +1488,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
struct dvb_frontend_private *fepriv = fe->frontend_priv;
int err = -EOPNOTSUPP;
- dprintk ("%s\n", __func__);
+ dprintk("%s (%d)\n", __func__, _IOC_NR(cmd));
if (fepriv->exit)
return -ENODEV;
@@ -1536,8 +1536,7 @@ static int dvb_frontend_ioctl_properties(struct inode *inode, struct file *file,
if ((tvps->num == 0) || (tvps->num > DTV_IOCTL_MAX_MSGS))
return -EINVAL;
- tvp = (struct dtv_property *) kmalloc(tvps->num *
- sizeof(struct dtv_property), GFP_KERNEL);
+ tvp = kmalloc(tvps->num * sizeof(struct dtv_property), GFP_KERNEL);
if (!tvp) {
err = -ENOMEM;
goto out;
@@ -1569,8 +1568,7 @@ static int dvb_frontend_ioctl_properties(struct inode *inode, struct file *file,
if ((tvps->num == 0) || (tvps->num > DTV_IOCTL_MAX_MSGS))
return -EINVAL;
- tvp = (struct dtv_property *) kmalloc(tvps->num *
- sizeof(struct dtv_property), GFP_KERNEL);
+ tvp = kmalloc(tvps->num * sizeof(struct dtv_property), GFP_KERNEL);
if (!tvp) {
err = -ENOMEM;
goto out;
diff --git a/drivers/media/dvb/dvb-core/dvb_ringbuffer.c b/drivers/media/dvb/dvb-core/dvb_ringbuffer.c
index 584bbd194dc8..a5712cd7c65f 100644
--- a/drivers/media/dvb/dvb-core/dvb_ringbuffer.c
+++ b/drivers/media/dvb/dvb-core/dvb_ringbuffer.c
@@ -89,6 +89,7 @@ void dvb_ringbuffer_flush(struct dvb_ringbuffer *rbuf)
rbuf->pread = rbuf->pwrite;
rbuf->error = 0;
}
+EXPORT_SYMBOL(dvb_ringbuffer_flush);
void dvb_ringbuffer_reset(struct dvb_ringbuffer *rbuf)
{
diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig
index 465295b1d14b..e5f91f16ffa4 100644
--- a/drivers/media/dvb/dvb-usb/Kconfig
+++ b/drivers/media/dvb/dvb-usb/Kconfig
@@ -336,3 +336,11 @@ config DVB_USB_EC168
select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE
help
Say Y here to support the E3C EC168 DVB-T USB2.0 receiver.
+
+config DVB_USB_AZ6027
+ tristate "Azurewave DVB-S/S2 USB2.0 AZ6027 support"
+ depends on DVB_USB
+ select DVB_STB0899 if !DVB_FE_CUSTOMISE
+ select DVB_STB6100 if !DVB_FE_CUSTOMISE
+ help
+ Say Y here to support the AZ6027 device
diff --git a/drivers/media/dvb/dvb-usb/Makefile b/drivers/media/dvb/dvb-usb/Makefile
index 72c92cb69a22..1a192453b0e7 100644
--- a/drivers/media/dvb/dvb-usb/Makefile
+++ b/drivers/media/dvb/dvb-usb/Makefile
@@ -85,6 +85,9 @@ obj-$(CONFIG_DVB_USB_FRIIO) += dvb-usb-friio.o
dvb-usb-ec168-objs = ec168.o
obj-$(CONFIG_DVB_USB_EC168) += dvb-usb-ec168.o
+dvb-usb-az6027-objs = az6027.o
+obj-$(CONFIG_DVB_USB_AZ6027) += dvb-usb-az6027.o
+
EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
# due to tuner-xc3028
EXTRA_CFLAGS += -Idrivers/media/common/tuners
diff --git a/drivers/media/dvb/dvb-usb/af9015.c b/drivers/media/dvb/dvb-usb/af9015.c
index 8b60a601fb82..d7975383d31b 100644
--- a/drivers/media/dvb/dvb-usb/af9015.c
+++ b/drivers/media/dvb/dvb-usb/af9015.c
@@ -21,6 +21,8 @@
*
*/
+#include <linux/hash.h>
+
#include "af9015.h"
#include "af9013.h"
#include "mt2060.h"
@@ -553,26 +555,45 @@ exit:
return ret;
}
-/* dump eeprom */
-static int af9015_eeprom_dump(struct dvb_usb_device *d)
+/* hash (and dump) eeprom */
+static int af9015_eeprom_hash(struct usb_device *udev)
{
- u8 reg, val;
+ static const unsigned int eeprom_size = 256;
+ unsigned int reg;
+ int ret;
+ u8 val, *eeprom;
+ struct req_t req = {READ_I2C, AF9015_I2C_EEPROM, 0, 0, 1, 1, &val};
- for (reg = 0; ; reg++) {
- if (reg % 16 == 0) {
- if (reg)
- deb_info(KERN_CONT "\n");
- deb_info(KERN_DEBUG "%02x:", reg);
- }
- if (af9015_read_reg_i2c(d, AF9015_I2C_EEPROM, reg, &val) == 0)
- deb_info(KERN_CONT " %02x", val);
- else
- deb_info(KERN_CONT " --");
- if (reg == 0xff)
- break;
+ eeprom = kmalloc(eeprom_size, GFP_KERNEL);
+ if (eeprom == NULL)
+ return -ENOMEM;
+
+ for (reg = 0; reg < eeprom_size; reg++) {
+ req.addr = reg;
+ ret = af9015_rw_udev(udev, &req);
+ if (ret)
+ goto free;
+ eeprom[reg] = val;
}
- deb_info(KERN_CONT "\n");
- return 0;
+
+ if (dvb_usb_af9015_debug & 0x01)
+ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, eeprom,
+ eeprom_size);
+
+ BUG_ON(eeprom_size % 4);
+
+ af9015_config.eeprom_sum = 0;
+ for (reg = 0; reg < eeprom_size / sizeof(u32); reg++) {
+ af9015_config.eeprom_sum *= GOLDEN_RATIO_PRIME_32;
+ af9015_config.eeprom_sum += le32_to_cpu(((u32 *)eeprom)[reg]);
+ }
+
+ deb_info("%s: eeprom sum=%.8x\n", __func__, af9015_config.eeprom_sum);
+
+ ret = 0;
+free:
+ kfree(eeprom);
+ return ret;
}
static int af9015_download_ir_table(struct dvb_usb_device *d)
@@ -711,12 +732,132 @@ error:
return ret;
}
+struct af9015_setup {
+ unsigned int id;
+ struct dvb_usb_rc_key *rc_key_map;
+ unsigned int rc_key_map_size;
+ u8 *ir_table;
+ unsigned int ir_table_size;
+};
+
+static const struct af9015_setup *af9015_setup_match(unsigned int id,
+ const struct af9015_setup *table)
+{
+ for (; table->rc_key_map; table++)
+ if (table->id == id)
+ return table;
+ return NULL;
+}
+
+static const struct af9015_setup af9015_setup_modparam[] = {
+ { AF9015_REMOTE_A_LINK_DTU_M,
+ af9015_rc_keys_a_link, ARRAY_SIZE(af9015_rc_keys_a_link),
+ af9015_ir_table_a_link, ARRAY_SIZE(af9015_ir_table_a_link) },
+ { AF9015_REMOTE_MSI_DIGIVOX_MINI_II_V3,
+ af9015_rc_keys_msi, ARRAY_SIZE(af9015_rc_keys_msi),
+ af9015_ir_table_msi, ARRAY_SIZE(af9015_ir_table_msi) },
+ { AF9015_REMOTE_MYGICTV_U718,
+ af9015_rc_keys_mygictv, ARRAY_SIZE(af9015_rc_keys_mygictv),
+ af9015_ir_table_mygictv, ARRAY_SIZE(af9015_ir_table_mygictv) },
+ { AF9015_REMOTE_DIGITTRADE_DVB_T,
+ af9015_rc_keys_digittrade, ARRAY_SIZE(af9015_rc_keys_digittrade),
+ af9015_ir_table_digittrade, ARRAY_SIZE(af9015_ir_table_digittrade) },
+ { AF9015_REMOTE_AVERMEDIA_KS,
+ af9015_rc_keys_avermedia, ARRAY_SIZE(af9015_rc_keys_avermedia),
+ af9015_ir_table_avermedia_ks, ARRAY_SIZE(af9015_ir_table_avermedia_ks) },
+ { }
+};
+
+/* don't add new entries here anymore, use hashes instead */
+static const struct af9015_setup af9015_setup_usbids[] = {
+ { USB_VID_LEADTEK,
+ af9015_rc_keys_leadtek, ARRAY_SIZE(af9015_rc_keys_leadtek),
+ af9015_ir_table_leadtek, ARRAY_SIZE(af9015_ir_table_leadtek) },
+ { USB_VID_VISIONPLUS,
+ af9015_rc_keys_twinhan, ARRAY_SIZE(af9015_rc_keys_twinhan),
+ af9015_ir_table_twinhan, ARRAY_SIZE(af9015_ir_table_twinhan) },
+ { USB_VID_KWORLD_2, /* TODO: use correct rc keys */
+ af9015_rc_keys_twinhan, ARRAY_SIZE(af9015_rc_keys_twinhan),
+ af9015_ir_table_kworld, ARRAY_SIZE(af9015_ir_table_kworld) },
+ { USB_VID_AVERMEDIA,
+ af9015_rc_keys_avermedia, ARRAY_SIZE(af9015_rc_keys_avermedia),
+ af9015_ir_table_avermedia, ARRAY_SIZE(af9015_ir_table_avermedia) },
+ { USB_VID_MSI_2,
+ af9015_rc_keys_msi_digivox_iii, ARRAY_SIZE(af9015_rc_keys_msi_digivox_iii),
+ af9015_ir_table_msi_digivox_iii, ARRAY_SIZE(af9015_ir_table_msi_digivox_iii) },
+ { }
+};
+
+static const struct af9015_setup af9015_setup_hashes[] = {
+ { 0xb8feb708,
+ af9015_rc_keys_msi, ARRAY_SIZE(af9015_rc_keys_msi),
+ af9015_ir_table_msi, ARRAY_SIZE(af9015_ir_table_msi) },
+ { 0xa3703d00,
+ af9015_rc_keys_a_link, ARRAY_SIZE(af9015_rc_keys_a_link),
+ af9015_ir_table_a_link, ARRAY_SIZE(af9015_ir_table_a_link) },
+ { 0x9b7dc64e,
+ af9015_rc_keys_mygictv, ARRAY_SIZE(af9015_rc_keys_mygictv),
+ af9015_ir_table_mygictv, ARRAY_SIZE(af9015_ir_table_mygictv) },
+ { }
+};
+
+static void af9015_set_remote_config(struct usb_device *udev,
+ struct dvb_usb_device_properties *props)
+{
+ const struct af9015_setup *table = NULL;
+
+ if (dvb_usb_af9015_remote) {
+ /* load remote defined as module param */
+ table = af9015_setup_match(dvb_usb_af9015_remote,
+ af9015_setup_modparam);
+ } else {
+ u16 vendor = le16_to_cpu(udev->descriptor.idVendor);
+
+ table = af9015_setup_match(af9015_config.eeprom_sum,
+ af9015_setup_hashes);
+
+ if (!table && vendor == USB_VID_AFATECH) {
+ /* Check USB manufacturer and product strings and try
+ to determine correct remote in case of chip vendor
+ reference IDs are used.
+ DO NOT ADD ANYTHING NEW HERE. Use hashes instead.
+ */
+ char manufacturer[10];
+ memset(manufacturer, 0, sizeof(manufacturer));
+ usb_string(udev, udev->descriptor.iManufacturer,
+ manufacturer, sizeof(manufacturer));
+ if (!strcmp("MSI", manufacturer)) {
+ /* iManufacturer 1 MSI
+ iProduct 2 MSI K-VOX */
+ table = af9015_setup_match(
+ AF9015_REMOTE_MSI_DIGIVOX_MINI_II_V3,
+ af9015_setup_modparam);
+ } else if (udev->descriptor.idProduct ==
+ cpu_to_le16(USB_PID_TREKSTOR_DVBT)) {
+ table = &(const struct af9015_setup){ 0,
+ af9015_rc_keys_trekstor,
+ ARRAY_SIZE(af9015_rc_keys_trekstor),
+ af9015_ir_table_trekstor,
+ ARRAY_SIZE(af9015_ir_table_trekstor)
+ };
+ }
+ } else if (!table)
+ table = af9015_setup_match(vendor, af9015_setup_usbids);
+ }
+
+ if (table) {
+ props->rc_key_map = table->rc_key_map;
+ props->rc_key_map_size = table->rc_key_map_size;
+ af9015_config.ir_table = table->ir_table;
+ af9015_config.ir_table_size = table->ir_table_size;
+ }
+}
+
static int af9015_read_config(struct usb_device *udev)
{
int ret;
u8 val, i, offset = 0;
struct req_t req = {READ_I2C, AF9015_I2C_EEPROM, 0, 0, 1, 1, &val};
- char manufacturer[10];
/* IR remote controller */
req.addr = AF9015_EEPROM_IR_MODE;
@@ -728,158 +869,18 @@ static int af9015_read_config(struct usb_device *udev)
}
if (ret)
goto error;
+
+ ret = af9015_eeprom_hash(udev);
+ if (ret)
+ goto error;
+
deb_info("%s: IR mode:%d\n", __func__, val);
for (i = 0; i < af9015_properties_count; i++) {
if (val == AF9015_IR_MODE_DISABLED) {
af9015_properties[i].rc_key_map = NULL;
af9015_properties[i].rc_key_map_size = 0;
- } else if (dvb_usb_af9015_remote) {
- /* load remote defined as module param */
- switch (dvb_usb_af9015_remote) {
- case AF9015_REMOTE_A_LINK_DTU_M:
- af9015_properties[i].rc_key_map =
- af9015_rc_keys_a_link;
- af9015_properties[i].rc_key_map_size =
- ARRAY_SIZE(af9015_rc_keys_a_link);
- af9015_config.ir_table = af9015_ir_table_a_link;
- af9015_config.ir_table_size =
- ARRAY_SIZE(af9015_ir_table_a_link);
- break;
- case AF9015_REMOTE_MSI_DIGIVOX_MINI_II_V3:
- af9015_properties[i].rc_key_map =
- af9015_rc_keys_msi;
- af9015_properties[i].rc_key_map_size =
- ARRAY_SIZE(af9015_rc_keys_msi);
- af9015_config.ir_table = af9015_ir_table_msi;
- af9015_config.ir_table_size =
- ARRAY_SIZE(af9015_ir_table_msi);
- break;
- case AF9015_REMOTE_MYGICTV_U718:
- af9015_properties[i].rc_key_map =
- af9015_rc_keys_mygictv;
- af9015_properties[i].rc_key_map_size =
- ARRAY_SIZE(af9015_rc_keys_mygictv);
- af9015_config.ir_table =
- af9015_ir_table_mygictv;
- af9015_config.ir_table_size =
- ARRAY_SIZE(af9015_ir_table_mygictv);
- break;
- case AF9015_REMOTE_DIGITTRADE_DVB_T:
- af9015_properties[i].rc_key_map =
- af9015_rc_keys_digittrade;
- af9015_properties[i].rc_key_map_size =
- ARRAY_SIZE(af9015_rc_keys_digittrade);
- af9015_config.ir_table =
- af9015_ir_table_digittrade;
- af9015_config.ir_table_size =
- ARRAY_SIZE(af9015_ir_table_digittrade);
- break;
- case AF9015_REMOTE_AVERMEDIA_KS:
- af9015_properties[i].rc_key_map =
- af9015_rc_keys_avermedia;
- af9015_properties[i].rc_key_map_size =
- ARRAY_SIZE(af9015_rc_keys_avermedia);
- af9015_config.ir_table =
- af9015_ir_table_avermedia_ks;
- af9015_config.ir_table_size =
- ARRAY_SIZE(af9015_ir_table_avermedia_ks);
- break;
- }
- } else {
- switch (le16_to_cpu(udev->descriptor.idVendor)) {
- case USB_VID_LEADTEK:
- af9015_properties[i].rc_key_map =
- af9015_rc_keys_leadtek;
- af9015_properties[i].rc_key_map_size =
- ARRAY_SIZE(af9015_rc_keys_leadtek);
- af9015_config.ir_table =
- af9015_ir_table_leadtek;
- af9015_config.ir_table_size =
- ARRAY_SIZE(af9015_ir_table_leadtek);
- break;
- case USB_VID_VISIONPLUS:
- af9015_properties[i].rc_key_map =
- af9015_rc_keys_twinhan;
- af9015_properties[i].rc_key_map_size =
- ARRAY_SIZE(af9015_rc_keys_twinhan);
- af9015_config.ir_table =
- af9015_ir_table_twinhan;
- af9015_config.ir_table_size =
- ARRAY_SIZE(af9015_ir_table_twinhan);
- break;
- case USB_VID_KWORLD_2:
- /* TODO: use correct rc keys */
- af9015_properties[i].rc_key_map =
- af9015_rc_keys_twinhan;
- af9015_properties[i].rc_key_map_size =
- ARRAY_SIZE(af9015_rc_keys_twinhan);
- af9015_config.ir_table = af9015_ir_table_kworld;
- af9015_config.ir_table_size =
- ARRAY_SIZE(af9015_ir_table_kworld);
- break;
- /* Check USB manufacturer and product strings and try
- to determine correct remote in case of chip vendor
- reference IDs are used. */
- case USB_VID_AFATECH:
- memset(manufacturer, 0, sizeof(manufacturer));
- usb_string(udev, udev->descriptor.iManufacturer,
- manufacturer, sizeof(manufacturer));
- if (!strcmp("Geniatech", manufacturer)) {
- /* iManufacturer 1 Geniatech
- iProduct 2 AF9015 */
- af9015_properties[i].rc_key_map =
- af9015_rc_keys_mygictv;
- af9015_properties[i].rc_key_map_size =
- ARRAY_SIZE(af9015_rc_keys_mygictv);
- af9015_config.ir_table =
- af9015_ir_table_mygictv;
- af9015_config.ir_table_size =
- ARRAY_SIZE(af9015_ir_table_mygictv);
- } else if (!strcmp("MSI", manufacturer)) {
- /* iManufacturer 1 MSI
- iProduct 2 MSI K-VOX */
- af9015_properties[i].rc_key_map =
- af9015_rc_keys_msi;
- af9015_properties[i].rc_key_map_size =
- ARRAY_SIZE(af9015_rc_keys_msi);
- af9015_config.ir_table =
- af9015_ir_table_msi;
- af9015_config.ir_table_size =
- ARRAY_SIZE(af9015_ir_table_msi);
- } else if (udev->descriptor.idProduct ==
- cpu_to_le16(USB_PID_TREKSTOR_DVBT)) {
- af9015_properties[i].rc_key_map =
- af9015_rc_keys_trekstor;
- af9015_properties[i].rc_key_map_size =
- ARRAY_SIZE(af9015_rc_keys_trekstor);
- af9015_config.ir_table =
- af9015_ir_table_trekstor;
- af9015_config.ir_table_size =
- ARRAY_SIZE(af9015_ir_table_trekstor);
- }
- break;
- case USB_VID_AVERMEDIA:
- af9015_properties[i].rc_key_map =
- af9015_rc_keys_avermedia;
- af9015_properties[i].rc_key_map_size =
- ARRAY_SIZE(af9015_rc_keys_avermedia);
- af9015_config.ir_table =
- af9015_ir_table_avermedia;
- af9015_config.ir_table_size =
- ARRAY_SIZE(af9015_ir_table_avermedia);
- break;
- case USB_VID_MSI_2:
- af9015_properties[i].rc_key_map =
- af9015_rc_keys_msi_digivox_iii;
- af9015_properties[i].rc_key_map_size =
- ARRAY_SIZE(af9015_rc_keys_msi_digivox_iii);
- af9015_config.ir_table =
- af9015_ir_table_msi_digivox_iii;
- af9015_config.ir_table_size =
- ARRAY_SIZE(af9015_ir_table_msi_digivox_iii);
- break;
- }
- }
+ } else
+ af9015_set_remote_config(udev, &af9015_properties[i]);
}
/* TS mode - one or two receivers */
@@ -1001,6 +1002,9 @@ static int af9015_read_config(struct usb_device *udev)
af9015_af9013_config[i].gpio[1] = AF9013_GPIO_LO;
af9015_af9013_config[i].rf_spec_inv = 1;
break;
+ case AF9013_TUNER_TDA18218:
+ warn("tuner NXP TDA18218 not supported yet");
+ return -ENODEV;
default:
warn("tuner id:%d not supported, please report!", val);
return -ENODEV;
@@ -1125,11 +1129,6 @@ static int af9015_af9013_frontend_attach(struct dvb_usb_adapter *adap)
deb_info("%s: init I2C\n", __func__);
ret = af9015_i2c_init(adap->dev);
-
- /* dump eeprom (debug) */
- ret = af9015_eeprom_dump(adap->dev);
- if (ret)
- return ret;
} else {
/* select I2C adapter */
i2c_adap = &state->i2c_adap;
@@ -1295,6 +1294,8 @@ static struct usb_device_id af9015_usb_table[] = {
/* 25 */{USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_399U_2)},
{USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_PC160_T)},
{USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV20)},
+ {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_TINYTWIN_2)},
+ {USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV2000DS)},
{0},
};
MODULE_DEVICE_TABLE(usb, af9015_usb_table);
@@ -1381,7 +1382,8 @@ static struct dvb_usb_device_properties af9015_properties[] = {
},
{
.name = "DigitalNow TinyTwin DVB-T Receiver",
- .cold_ids = {&af9015_usb_table[5], NULL},
+ .cold_ids = {&af9015_usb_table[5],
+ &af9015_usb_table[28], NULL},
.warm_ids = {NULL},
},
{
@@ -1566,7 +1568,7 @@ static struct dvb_usb_device_properties af9015_properties[] = {
.i2c_algo = &af9015_i2c_algo,
- .num_device_descs = 6, /* max 9 */
+ .num_device_descs = 7, /* max 9 */
.devices = {
{
.name = "AverMedia AVerTV Volar GPS 805 (A805)",
@@ -1600,6 +1602,11 @@ static struct dvb_usb_device_properties af9015_properties[] = {
.cold_ids = {&af9015_usb_table[27], NULL},
.warm_ids = {NULL},
},
+ {
+ .name = "Leadtek WinFast DTV2000DS",
+ .cold_ids = {&af9015_usb_table[29], NULL},
+ .warm_ids = {NULL},
+ },
}
},
};
diff --git a/drivers/media/dvb/dvb-usb/af9015.h b/drivers/media/dvb/dvb-usb/af9015.h
index 931c8515830d..ef36b1831490 100644
--- a/drivers/media/dvb/dvb-usb/af9015.h
+++ b/drivers/media/dvb/dvb-usb/af9015.h
@@ -107,6 +107,7 @@ struct af9015_config {
u16 mt2060_if1[2];
u16 firmware_size;
u16 firmware_checksum;
+ u32 eeprom_sum;
u8 *ir_table;
u16 ir_table_size;
};
diff --git a/drivers/media/dvb/dvb-usb/az6027.c b/drivers/media/dvb/dvb-usb/az6027.c
new file mode 100644
index 000000000000..d7290b2c0913
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/az6027.c
@@ -0,0 +1,1151 @@
+/* DVB USB compliant Linux driver for the AZUREWAVE DVB-S/S2 USB2.0 (AZ6027)
+ * receiver.
+ *
+ * Copyright (C) 2009 Adams.Xu <adams.xu@azwave.com.cn>
+ *
+ * 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.
+ *
+ * see Documentation/dvb/README.dvb-usb for more information
+ */
+#include "az6027.h"
+
+#include "stb0899_drv.h"
+#include "stb0899_reg.h"
+#include "stb0899_cfg.h"
+
+#include "stb6100.h"
+#include "stb6100_cfg.h"
+#include "dvb_ca_en50221.h"
+
+int dvb_usb_az6027_debug;
+module_param_named(debug, dvb_usb_az6027_debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DVB_USB_DEBUG_STATUS);
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+struct az6027_device_state {
+ struct dvb_ca_en50221 ca;
+ struct mutex ca_mutex;
+ u8 power_state;
+};
+
+static const struct stb0899_s1_reg az6027_stb0899_s1_init_1[] = {
+
+ /* 0x0000000b, SYSREG */
+ { STB0899_DEV_ID , 0x30 },
+ { STB0899_DISCNTRL1 , 0x32 },
+ { STB0899_DISCNTRL2 , 0x80 },
+ { STB0899_DISRX_ST0 , 0x04 },
+ { STB0899_DISRX_ST1 , 0x00 },
+ { STB0899_DISPARITY , 0x00 },
+ { STB0899_DISFIFO , 0x00 },
+ { STB0899_DISSTATUS , 0x20 },
+ { STB0899_DISF22 , 0x99 },
+ { STB0899_DISF22RX , 0xa8 },
+ /* SYSREG ? */
+ { STB0899_ACRPRESC , 0x11 },
+ { STB0899_ACRDIV1 , 0x0a },
+ { STB0899_ACRDIV2 , 0x05 },
+ { STB0899_DACR1 , 0x00 },
+ { STB0899_DACR2 , 0x00 },
+ { STB0899_OUTCFG , 0x00 },
+ { STB0899_MODECFG , 0x00 },
+ { STB0899_IRQSTATUS_3 , 0xfe },
+ { STB0899_IRQSTATUS_2 , 0x03 },
+ { STB0899_IRQSTATUS_1 , 0x7c },
+ { STB0899_IRQSTATUS_0 , 0xf4 },
+ { STB0899_IRQMSK_3 , 0xf3 },
+ { STB0899_IRQMSK_2 , 0xfc },
+ { STB0899_IRQMSK_1 , 0xff },
+ { STB0899_IRQMSK_0 , 0xff },
+ { STB0899_IRQCFG , 0x00 },
+ { STB0899_I2CCFG , 0x88 },
+ { STB0899_I2CRPT , 0x58 },
+ { STB0899_IOPVALUE5 , 0x00 },
+ { STB0899_IOPVALUE4 , 0x33 },
+ { STB0899_IOPVALUE3 , 0x6d },
+ { STB0899_IOPVALUE2 , 0x90 },
+ { STB0899_IOPVALUE1 , 0x60 },
+ { STB0899_IOPVALUE0 , 0x00 },
+ { STB0899_GPIO00CFG , 0x82 },
+ { STB0899_GPIO01CFG , 0x82 },
+ { STB0899_GPIO02CFG , 0x82 },
+ { STB0899_GPIO03CFG , 0x82 },
+ { STB0899_GPIO04CFG , 0x82 },
+ { STB0899_GPIO05CFG , 0x82 },
+ { STB0899_GPIO06CFG , 0x82 },
+ { STB0899_GPIO07CFG , 0x82 },
+ { STB0899_GPIO08CFG , 0x82 },
+ { STB0899_GPIO09CFG , 0x82 },
+ { STB0899_GPIO10CFG , 0x82 },
+ { STB0899_GPIO11CFG , 0x82 },
+ { STB0899_GPIO12CFG , 0x82 },
+ { STB0899_GPIO13CFG , 0x82 },
+ { STB0899_GPIO14CFG , 0x82 },
+ { STB0899_GPIO15CFG , 0x82 },
+ { STB0899_GPIO16CFG , 0x82 },
+ { STB0899_GPIO17CFG , 0x82 },
+ { STB0899_GPIO18CFG , 0x82 },
+ { STB0899_GPIO19CFG , 0x82 },
+ { STB0899_GPIO20CFG , 0x82 },
+ { STB0899_SDATCFG , 0xb8 },
+ { STB0899_SCLTCFG , 0xba },
+ { STB0899_AGCRFCFG , 0x1c }, /* 0x11 */
+ { STB0899_GPIO22 , 0x82 }, /* AGCBB2CFG */
+ { STB0899_GPIO21 , 0x91 }, /* AGCBB1CFG */
+ { STB0899_DIRCLKCFG , 0x82 },
+ { STB0899_CLKOUT27CFG , 0x7e },
+ { STB0899_STDBYCFG , 0x82 },
+ { STB0899_CS0CFG , 0x82 },
+ { STB0899_CS1CFG , 0x82 },
+ { STB0899_DISEQCOCFG , 0x20 },
+ { STB0899_GPIO32CFG , 0x82 },
+ { STB0899_GPIO33CFG , 0x82 },
+ { STB0899_GPIO34CFG , 0x82 },
+ { STB0899_GPIO35CFG , 0x82 },
+ { STB0899_GPIO36CFG , 0x82 },
+ { STB0899_GPIO37CFG , 0x82 },
+ { STB0899_GPIO38CFG , 0x82 },
+ { STB0899_GPIO39CFG , 0x82 },
+ { STB0899_NCOARSE , 0x17 }, /* 0x15 = 27 Mhz Clock, F/3 = 198MHz, F/6 = 99MHz */
+ { STB0899_SYNTCTRL , 0x02 }, /* 0x00 = CLK from CLKI, 0x02 = CLK from XTALI */
+ { STB0899_FILTCTRL , 0x00 },
+ { STB0899_SYSCTRL , 0x01 },
+ { STB0899_STOPCLK1 , 0x20 },
+ { STB0899_STOPCLK2 , 0x00 },
+ { STB0899_INTBUFSTATUS , 0x00 },
+ { STB0899_INTBUFCTRL , 0x0a },
+ { 0xffff , 0xff },
+};
+
+static const struct stb0899_s1_reg az6027_stb0899_s1_init_3[] = {
+ { STB0899_DEMOD , 0x00 },
+ { STB0899_RCOMPC , 0xc9 },
+ { STB0899_AGC1CN , 0x01 },
+ { STB0899_AGC1REF , 0x10 },
+ { STB0899_RTC , 0x23 },
+ { STB0899_TMGCFG , 0x4e },
+ { STB0899_AGC2REF , 0x34 },
+ { STB0899_TLSR , 0x84 },
+ { STB0899_CFD , 0xf7 },
+ { STB0899_ACLC , 0x87 },
+ { STB0899_BCLC , 0x94 },
+ { STB0899_EQON , 0x41 },
+ { STB0899_LDT , 0xf1 },
+ { STB0899_LDT2 , 0xe3 },
+ { STB0899_EQUALREF , 0xb4 },
+ { STB0899_TMGRAMP , 0x10 },
+ { STB0899_TMGTHD , 0x30 },
+ { STB0899_IDCCOMP , 0xfd },
+ { STB0899_QDCCOMP , 0xff },
+ { STB0899_POWERI , 0x0c },
+ { STB0899_POWERQ , 0x0f },
+ { STB0899_RCOMP , 0x6c },
+ { STB0899_AGCIQIN , 0x80 },
+ { STB0899_AGC2I1 , 0x06 },
+ { STB0899_AGC2I2 , 0x00 },
+ { STB0899_TLIR , 0x30 },
+ { STB0899_RTF , 0x7f },
+ { STB0899_DSTATUS , 0x00 },
+ { STB0899_LDI , 0xbc },
+ { STB0899_CFRM , 0xea },
+ { STB0899_CFRL , 0x31 },
+ { STB0899_NIRM , 0x2b },
+ { STB0899_NIRL , 0x80 },
+ { STB0899_ISYMB , 0x1d },
+ { STB0899_QSYMB , 0xa6 },
+ { STB0899_SFRH , 0x2f },
+ { STB0899_SFRM , 0x68 },
+ { STB0899_SFRL , 0x40 },
+ { STB0899_SFRUPH , 0x2f },
+ { STB0899_SFRUPM , 0x68 },
+ { STB0899_SFRUPL , 0x40 },
+ { STB0899_EQUAI1 , 0x02 },
+ { STB0899_EQUAQ1 , 0xff },
+ { STB0899_EQUAI2 , 0x04 },
+ { STB0899_EQUAQ2 , 0x05 },
+ { STB0899_EQUAI3 , 0x02 },
+ { STB0899_EQUAQ3 , 0xfd },
+ { STB0899_EQUAI4 , 0x03 },
+ { STB0899_EQUAQ4 , 0x07 },
+ { STB0899_EQUAI5 , 0x08 },
+ { STB0899_EQUAQ5 , 0xf5 },
+ { STB0899_DSTATUS2 , 0x00 },
+ { STB0899_VSTATUS , 0x00 },
+ { STB0899_VERROR , 0x86 },
+ { STB0899_IQSWAP , 0x2a },
+ { STB0899_ECNT1M , 0x00 },
+ { STB0899_ECNT1L , 0x00 },
+ { STB0899_ECNT2M , 0x00 },
+ { STB0899_ECNT2L , 0x00 },
+ { STB0899_ECNT3M , 0x0a },
+ { STB0899_ECNT3L , 0xad },
+ { STB0899_FECAUTO1 , 0x06 },
+ { STB0899_FECM , 0x01 },
+ { STB0899_VTH12 , 0xb0 },
+ { STB0899_VTH23 , 0x7a },
+ { STB0899_VTH34 , 0x58 },
+ { STB0899_VTH56 , 0x38 },
+ { STB0899_VTH67 , 0x34 },
+ { STB0899_VTH78 , 0x24 },
+ { STB0899_PRVIT , 0xff },
+ { STB0899_VITSYNC , 0x19 },
+ { STB0899_RSULC , 0xb1 }, /* DVB = 0xb1, DSS = 0xa1 */
+ { STB0899_TSULC , 0x42 },
+ { STB0899_RSLLC , 0x41 },
+ { STB0899_TSLPL , 0x12 },
+ { STB0899_TSCFGH , 0x0c },
+ { STB0899_TSCFGM , 0x00 },
+ { STB0899_TSCFGL , 0x00 },
+ { STB0899_TSOUT , 0x69 }, /* 0x0d for CAM */
+ { STB0899_RSSYNCDEL , 0x00 },
+ { STB0899_TSINHDELH , 0x02 },
+ { STB0899_TSINHDELM , 0x00 },
+ { STB0899_TSINHDELL , 0x00 },
+ { STB0899_TSLLSTKM , 0x1b },
+ { STB0899_TSLLSTKL , 0xb3 },
+ { STB0899_TSULSTKM , 0x00 },
+ { STB0899_TSULSTKL , 0x00 },
+ { STB0899_PCKLENUL , 0xbc },
+ { STB0899_PCKLENLL , 0xcc },
+ { STB0899_RSPCKLEN , 0xbd },
+ { STB0899_TSSTATUS , 0x90 },
+ { STB0899_ERRCTRL1 , 0xb6 },
+ { STB0899_ERRCTRL2 , 0x95 },
+ { STB0899_ERRCTRL3 , 0x8d },
+ { STB0899_DMONMSK1 , 0x27 },
+ { STB0899_DMONMSK0 , 0x03 },
+ { STB0899_DEMAPVIT , 0x5c },
+ { STB0899_PLPARM , 0x19 },
+ { STB0899_PDELCTRL , 0x48 },
+ { STB0899_PDELCTRL2 , 0x00 },
+ { STB0899_BBHCTRL1 , 0x00 },
+ { STB0899_BBHCTRL2 , 0x00 },
+ { STB0899_HYSTTHRESH , 0x77 },
+ { STB0899_MATCSTM , 0x00 },
+ { STB0899_MATCSTL , 0x00 },
+ { STB0899_UPLCSTM , 0x00 },
+ { STB0899_UPLCSTL , 0x00 },
+ { STB0899_DFLCSTM , 0x00 },
+ { STB0899_DFLCSTL , 0x00 },
+ { STB0899_SYNCCST , 0x00 },
+ { STB0899_SYNCDCSTM , 0x00 },
+ { STB0899_SYNCDCSTL , 0x00 },
+ { STB0899_ISI_ENTRY , 0x00 },
+ { STB0899_ISI_BIT_EN , 0x00 },
+ { STB0899_MATSTRM , 0xf0 },
+ { STB0899_MATSTRL , 0x02 },
+ { STB0899_UPLSTRM , 0x45 },
+ { STB0899_UPLSTRL , 0x60 },
+ { STB0899_DFLSTRM , 0xe3 },
+ { STB0899_DFLSTRL , 0x00 },
+ { STB0899_SYNCSTR , 0x47 },
+ { STB0899_SYNCDSTRM , 0x05 },
+ { STB0899_SYNCDSTRL , 0x18 },
+ { STB0899_CFGPDELSTATUS1 , 0x19 },
+ { STB0899_CFGPDELSTATUS2 , 0x2b },
+ { STB0899_BBFERRORM , 0x00 },
+ { STB0899_BBFERRORL , 0x01 },
+ { STB0899_UPKTERRORM , 0x00 },
+ { STB0899_UPKTERRORL , 0x00 },
+ { 0xffff , 0xff },
+};
+
+
+
+struct stb0899_config az6027_stb0899_config = {
+ .init_dev = az6027_stb0899_s1_init_1,
+ .init_s2_demod = stb0899_s2_init_2,
+ .init_s1_demod = az6027_stb0899_s1_init_3,
+ .init_s2_fec = stb0899_s2_init_4,
+ .init_tst = stb0899_s1_init_5,
+
+ .demod_address = 0xd0, /* 0x68, 0xd0 >> 1 */
+
+ .xtal_freq = 27000000,
+ .inversion = IQ_SWAP_ON, /* 1 */
+
+ .lo_clk = 76500000,
+ .hi_clk = 99000000,
+
+ .esno_ave = STB0899_DVBS2_ESNO_AVE,
+ .esno_quant = STB0899_DVBS2_ESNO_QUANT,
+ .avframes_coarse = STB0899_DVBS2_AVFRAMES_COARSE,
+ .avframes_fine = STB0899_DVBS2_AVFRAMES_FINE,
+ .miss_threshold = STB0899_DVBS2_MISS_THRESHOLD,
+ .uwp_threshold_acq = STB0899_DVBS2_UWP_THRESHOLD_ACQ,
+ .uwp_threshold_track = STB0899_DVBS2_UWP_THRESHOLD_TRACK,
+ .uwp_threshold_sof = STB0899_DVBS2_UWP_THRESHOLD_SOF,
+ .sof_search_timeout = STB0899_DVBS2_SOF_SEARCH_TIMEOUT,
+
+ .btr_nco_bits = STB0899_DVBS2_BTR_NCO_BITS,
+ .btr_gain_shift_offset = STB0899_DVBS2_BTR_GAIN_SHIFT_OFFSET,
+ .crl_nco_bits = STB0899_DVBS2_CRL_NCO_BITS,
+ .ldpc_max_iter = STB0899_DVBS2_LDPC_MAX_ITER,
+
+ .tuner_get_frequency = stb6100_get_frequency,
+ .tuner_set_frequency = stb6100_set_frequency,
+ .tuner_set_bandwidth = stb6100_set_bandwidth,
+ .tuner_get_bandwidth = stb6100_get_bandwidth,
+ .tuner_set_rfsiggain = NULL,
+};
+
+struct stb6100_config az6027_stb6100_config = {
+ .tuner_address = 0xc0,
+ .refclock = 27000000,
+};
+
+
+/* check for mutex FIXME */
+int az6027_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen)
+{
+ int ret = -1;
+ if (mutex_lock_interruptible(&d->usb_mutex))
+ return -EAGAIN;
+
+ ret = usb_control_msg(d->udev,
+ usb_rcvctrlpipe(d->udev, 0),
+ req,
+ USB_TYPE_VENDOR | USB_DIR_IN,
+ value,
+ index,
+ b,
+ blen,
+ 2000);
+
+ if (ret < 0) {
+ warn("usb in operation failed. (%d)", ret);
+ ret = -EIO;
+ } else
+ ret = 0;
+
+ deb_xfer("in: req. %02x, val: %04x, ind: %04x, buffer: ", req, value, index);
+ debug_dump(b, blen, deb_xfer);
+
+ mutex_unlock(&d->usb_mutex);
+ return ret;
+}
+
+static int az6027_usb_out_op(struct dvb_usb_device *d,
+ u8 req,
+ u16 value,
+ u16 index,
+ u8 *b,
+ int blen)
+{
+ int ret;
+
+ deb_xfer("out: req. %02x, val: %04x, ind: %04x, buffer: ", req, value, index);
+ debug_dump(b, blen, deb_xfer);
+
+ if (mutex_lock_interruptible(&d->usb_mutex))
+ return -EAGAIN;
+
+ ret = usb_control_msg(d->udev,
+ usb_sndctrlpipe(d->udev, 0),
+ req,
+ USB_TYPE_VENDOR | USB_DIR_OUT,
+ value,
+ index,
+ b,
+ blen,
+ 2000);
+
+ if (ret != blen) {
+ warn("usb out operation failed. (%d)", ret);
+ mutex_unlock(&d->usb_mutex);
+ return -EIO;
+ } else{
+ mutex_unlock(&d->usb_mutex);
+ return 0;
+ }
+}
+
+static int az6027_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
+{
+ int ret;
+ u8 req;
+ u16 value;
+ u16 index;
+ int blen;
+
+ deb_info("%s %d", __func__, onoff);
+
+ req = 0xBC;
+ value = onoff;
+ index = 0;
+ blen = 0;
+
+ ret = az6027_usb_out_op(adap->dev, req, value, index, NULL, blen);
+ if (ret != 0)
+ warn("usb out operation failed. (%d)", ret);
+
+ return ret;
+}
+
+/* keys for the enclosed remote control */
+static struct dvb_usb_rc_key az6027_rc_keys[] = {
+ { 0x01, KEY_1 },
+ { 0x02, KEY_2 },
+};
+
+/* remote control stuff (does not work with my box) */
+static int az6027_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
+{
+ return 0;
+}
+
+/*
+int az6027_power_ctrl(struct dvb_usb_device *d, int onoff)
+{
+ u8 v = onoff;
+ return az6027_usb_out_op(d,0xBC,v,3,NULL,1);
+}
+*/
+
+static int az6027_ci_read_attribute_mem(struct dvb_ca_en50221 *ca,
+ int slot,
+ int address)
+{
+ struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
+ struct az6027_device_state *state = (struct az6027_device_state *)d->priv;
+
+ int ret;
+ u8 req;
+ u16 value;
+ u16 index;
+ int blen;
+ u8 b[12];
+
+ if (slot != 0)
+ return -EINVAL;
+
+ mutex_lock(&state->ca_mutex);
+
+ req = 0xC1;
+ value = address;
+ index = 0;
+ blen = 1;
+
+ ret = az6027_usb_in_op(d, req, value, index, b, blen);
+ if (ret < 0) {
+ warn("usb in operation failed. (%d)", ret);
+ ret = -EINVAL;
+ } else {
+ ret = b[0];
+ }
+
+ mutex_unlock(&state->ca_mutex);
+ return ret;
+}
+
+static int az6027_ci_write_attribute_mem(struct dvb_ca_en50221 *ca,
+ int slot,
+ int address,
+ u8 value)
+{
+ struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
+ struct az6027_device_state *state = (struct az6027_device_state *)d->priv;
+
+ int ret;
+ u8 req;
+ u16 value1;
+ u16 index;
+ int blen;
+
+ deb_info("%s %d", __func__, slot);
+ if (slot != 0)
+ return -EINVAL;
+
+ mutex_lock(&state->ca_mutex);
+ req = 0xC2;
+ value1 = address;
+ index = value;
+ blen = 0;
+
+ ret = az6027_usb_out_op(d, req, value1, index, NULL, blen);
+ if (ret != 0)
+ warn("usb out operation failed. (%d)", ret);
+
+ mutex_unlock(&state->ca_mutex);
+ return ret;
+}
+
+static int az6027_ci_read_cam_control(struct dvb_ca_en50221 *ca,
+ int slot,
+ u8 address)
+{
+ struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
+ struct az6027_device_state *state = (struct az6027_device_state *)d->priv;
+
+ int ret;
+ u8 req;
+ u16 value;
+ u16 index;
+ int blen;
+ u8 b[12];
+
+ if (slot != 0)
+ return -EINVAL;
+
+ mutex_lock(&state->ca_mutex);
+
+ req = 0xC3;
+ value = address;
+ index = 0;
+ blen = 2;
+
+ ret = az6027_usb_in_op(d, req, value, index, b, blen);
+ if (ret < 0) {
+ warn("usb in operation failed. (%d)", ret);
+ ret = -EINVAL;
+ } else {
+ if (b[0] == 0)
+ warn("Read CI IO error");
+
+ ret = b[1];
+ deb_info("read cam data = %x from 0x%x", b[1], value);
+ }
+
+ mutex_unlock(&state->ca_mutex);
+ return ret;
+}
+
+static int az6027_ci_write_cam_control(struct dvb_ca_en50221 *ca,
+ int slot,
+ u8 address,
+ u8 value)
+{
+ struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
+ struct az6027_device_state *state = (struct az6027_device_state *)d->priv;
+
+ int ret;
+ u8 req;
+ u16 value1;
+ u16 index;
+ int blen;
+
+ if (slot != 0)
+ return -EINVAL;
+
+ mutex_lock(&state->ca_mutex);
+ req = 0xC4;
+ value1 = address;
+ index = value;
+ blen = 0;
+
+ ret = az6027_usb_out_op(d, req, value1, index, NULL, blen);
+ if (ret != 0) {
+ warn("usb out operation failed. (%d)", ret);
+ goto failed;
+ }
+
+failed:
+ mutex_unlock(&state->ca_mutex);
+ return ret;
+}
+
+static int CI_CamReady(struct dvb_ca_en50221 *ca, int slot)
+{
+ struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
+
+ int ret;
+ u8 req;
+ u16 value;
+ u16 index;
+ int blen;
+ u8 b[12];
+
+ req = 0xC8;
+ value = 0;
+ index = 0;
+ blen = 1;
+
+ ret = az6027_usb_in_op(d, req, value, index, b, blen);
+ if (ret < 0) {
+ warn("usb in operation failed. (%d)", ret);
+ ret = -EIO;
+ } else{
+ ret = b[0];
+ }
+ return ret;
+}
+
+static int az6027_ci_slot_reset(struct dvb_ca_en50221 *ca, int slot)
+{
+ struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
+ struct az6027_device_state *state = (struct az6027_device_state *)d->priv;
+
+ int ret, i;
+ u8 req;
+ u16 value;
+ u16 index;
+ int blen;
+
+ mutex_lock(&state->ca_mutex);
+
+ req = 0xC6;
+ value = 1;
+ index = 0;
+ blen = 0;
+
+ ret = az6027_usb_out_op(d, req, value, index, NULL, blen);
+ if (ret != 0) {
+ warn("usb out operation failed. (%d)", ret);
+ goto failed;
+ }
+
+ msleep(500);
+ req = 0xC6;
+ value = 0;
+ index = 0;
+ blen = 0;
+
+ ret = az6027_usb_out_op(d, req, value, index, NULL, blen);
+ if (ret != 0) {
+ warn("usb out operation failed. (%d)", ret);
+ goto failed;
+ }
+
+ for (i = 0; i < 15; i++) {
+ msleep(100);
+
+ if (CI_CamReady(ca, slot)) {
+ deb_info("CAM Ready");
+ break;
+ }
+ }
+ msleep(5000);
+
+failed:
+ mutex_unlock(&state->ca_mutex);
+ return ret;
+}
+
+static int az6027_ci_slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
+{
+ return 0;
+}
+
+static int az6027_ci_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
+{
+ struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
+ struct az6027_device_state *state = (struct az6027_device_state *)d->priv;
+
+ int ret;
+ u8 req;
+ u16 value;
+ u16 index;
+ int blen;
+
+ deb_info("%s", __func__);
+ mutex_lock(&state->ca_mutex);
+ req = 0xC7;
+ value = 1;
+ index = 0;
+ blen = 0;
+
+ ret = az6027_usb_out_op(d, req, value, index, NULL, blen);
+ if (ret != 0) {
+ warn("usb out operation failed. (%d)", ret);
+ goto failed;
+ }
+
+failed:
+ mutex_unlock(&state->ca_mutex);
+ return ret;
+}
+
+static int az6027_ci_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open)
+{
+ struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
+ struct az6027_device_state *state = (struct az6027_device_state *)d->priv;
+ int ret;
+ u8 req;
+ u16 value;
+ u16 index;
+ int blen;
+ u8 b[12];
+
+ mutex_lock(&state->ca_mutex);
+
+ req = 0xC5;
+ value = 0;
+ index = 0;
+ blen = 1;
+
+ ret = az6027_usb_in_op(d, req, value, index, b, blen);
+ if (ret < 0) {
+ warn("usb in operation failed. (%d)", ret);
+ ret = -EIO;
+ } else
+ ret = 0;
+
+ if (b[0] == 0) {
+ ret = 0;
+
+ } else if (b[0] == 1) {
+ ret = DVB_CA_EN50221_POLL_CAM_PRESENT |
+ DVB_CA_EN50221_POLL_CAM_READY;
+ }
+
+ mutex_unlock(&state->ca_mutex);
+ return ret;
+}
+
+
+static void az6027_ci_uninit(struct dvb_usb_device *d)
+{
+ struct az6027_device_state *state;
+
+ deb_info("%s", __func__);
+
+ if (NULL == d)
+ return;
+
+ state = (struct az6027_device_state *)d->priv;
+ if (NULL == state)
+ return;
+
+ if (NULL == state->ca.data)
+ return;
+
+ dvb_ca_en50221_release(&state->ca);
+
+ memset(&state->ca, 0, sizeof(state->ca));
+}
+
+
+static int az6027_ci_init(struct dvb_usb_adapter *a)
+{
+ struct dvb_usb_device *d = a->dev;
+ struct az6027_device_state *state = (struct az6027_device_state *)d->priv;
+ int ret;
+
+ deb_info("%s", __func__);
+
+ mutex_init(&state->ca_mutex);
+
+ state->ca.owner = THIS_MODULE;
+ state->ca.read_attribute_mem = az6027_ci_read_attribute_mem;
+ state->ca.write_attribute_mem = az6027_ci_write_attribute_mem;
+ state->ca.read_cam_control = az6027_ci_read_cam_control;
+ state->ca.write_cam_control = az6027_ci_write_cam_control;
+ state->ca.slot_reset = az6027_ci_slot_reset;
+ state->ca.slot_shutdown = az6027_ci_slot_shutdown;
+ state->ca.slot_ts_enable = az6027_ci_slot_ts_enable;
+ state->ca.poll_slot_status = az6027_ci_poll_slot_status;
+ state->ca.data = d;
+
+ ret = dvb_ca_en50221_init(&a->dvb_adap,
+ &state->ca,
+ 0, /* flags */
+ 1);/* n_slots */
+ if (ret != 0) {
+ err("Cannot initialize CI: Error %d.", ret);
+ memset(&state->ca, 0, sizeof(state->ca));
+ return ret;
+ }
+
+ deb_info("CI initialized.");
+
+ return 0;
+}
+
+/*
+static int az6027_read_mac_addr(struct dvb_usb_device *d, u8 mac[6])
+{
+ az6027_usb_in_op(d, 0xb7, 6, 0, &mac[0], 6);
+ return 0;
+}
+*/
+
+static int az6027_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
+{
+
+ u8 buf;
+ int ret;
+ struct dvb_usb_adapter *adap = fe->dvb->priv;
+
+ struct i2c_msg i2c_msg = {
+ .addr = 0x99,
+ .flags = 0,
+ .buf = &buf,
+ .len = 1
+ };
+
+ /*
+ * 2 --18v
+ * 1 --13v
+ * 0 --off
+ */
+ switch (voltage) {
+ case SEC_VOLTAGE_13:
+ buf = 1;
+ ret = i2c_transfer(&adap->dev->i2c_adap, &i2c_msg, 1);
+ break;
+
+ case SEC_VOLTAGE_18:
+ buf = 2;
+ ret = i2c_transfer(&adap->dev->i2c_adap, &i2c_msg, 1);
+ break;
+
+ case SEC_VOLTAGE_OFF:
+ buf = 0;
+ ret = i2c_transfer(&adap->dev->i2c_adap, &i2c_msg, 1);
+ break;
+
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+
+static int az6027_frontend_poweron(struct dvb_usb_adapter *adap)
+{
+ int ret;
+ u8 req;
+ u16 value;
+ u16 index;
+ int blen;
+
+ req = 0xBC;
+ value = 1; /* power on */
+ index = 3;
+ blen = 0;
+
+ ret = az6027_usb_out_op(adap->dev, req, value, index, NULL, blen);
+ if (ret != 0)
+ return -EIO;
+
+ return 0;
+}
+static int az6027_frontend_reset(struct dvb_usb_adapter *adap)
+{
+ int ret;
+ u8 req;
+ u16 value;
+ u16 index;
+ int blen;
+
+ /* reset demodulator */
+ req = 0xC0;
+ value = 1; /* high */
+ index = 3;
+ blen = 0;
+
+ ret = az6027_usb_out_op(adap->dev, req, value, index, NULL, blen);
+ if (ret != 0)
+ return -EIO;
+
+ req = 0xC0;
+ value = 0; /* low */
+ index = 3;
+ blen = 0;
+ msleep_interruptible(200);
+
+ ret = az6027_usb_out_op(adap->dev, req, value, index, NULL, blen);
+ if (ret != 0)
+ return -EIO;
+
+ msleep_interruptible(200);
+
+ req = 0xC0;
+ value = 1; /*high */
+ index = 3;
+ blen = 0;
+
+ ret = az6027_usb_out_op(adap->dev, req, value, index, NULL, blen);
+ if (ret != 0)
+ return -EIO;
+
+ msleep_interruptible(200);
+ return 0;
+}
+
+static int az6027_frontend_tsbypass(struct dvb_usb_adapter *adap, int onoff)
+{
+ int ret;
+ u8 req;
+ u16 value;
+ u16 index;
+ int blen;
+
+ /* TS passthrough */
+ req = 0xC7;
+ value = onoff;
+ index = 0;
+ blen = 0;
+
+ ret = az6027_usb_out_op(adap->dev, req, value, index, NULL, blen);
+ if (ret != 0)
+ return -EIO;
+
+ return 0;
+}
+
+static int az6027_frontend_attach(struct dvb_usb_adapter *adap)
+{
+
+ az6027_frontend_poweron(adap);
+ az6027_frontend_reset(adap);
+
+ deb_info("adap = %p, dev = %p\n", adap, adap->dev);
+ adap->fe = stb0899_attach(&az6027_stb0899_config, &adap->dev->i2c_adap);
+
+ if (adap->fe) {
+ deb_info("found STB0899 DVB-S/DVB-S2 frontend @0x%02x", az6027_stb0899_config.demod_address);
+ if (stb6100_attach(adap->fe, &az6027_stb6100_config, &adap->dev->i2c_adap)) {
+ deb_info("found STB6100 DVB-S/DVB-S2 frontend @0x%02x", az6027_stb6100_config.tuner_address);
+ adap->fe->ops.set_voltage = az6027_set_voltage;
+ az6027_ci_init(adap);
+ } else {
+ adap->fe = NULL;
+ }
+ } else
+ warn("no front-end attached\n");
+
+ az6027_frontend_tsbypass(adap, 0);
+
+ return 0;
+}
+
+static struct dvb_usb_device_properties az6027_properties;
+
+static void az6027_usb_disconnect(struct usb_interface *intf)
+{
+ struct dvb_usb_device *d = usb_get_intfdata(intf);
+ az6027_ci_uninit(d);
+ dvb_usb_device_exit(intf);
+}
+
+
+static int az6027_usb_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ return dvb_usb_device_init(intf,
+ &az6027_properties,
+ THIS_MODULE,
+ NULL,
+ adapter_nr);
+}
+
+/* I2C */
+static int az6027_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num)
+{
+ struct dvb_usb_device *d = i2c_get_adapdata(adap);
+ int i = 0, j = 0, len = 0;
+ int ret;
+ u16 index;
+ u16 value;
+ int length;
+ u8 req;
+ u8 data[256];
+
+ if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
+ return -EAGAIN;
+
+ if (num > 2)
+ warn("more than 2 i2c messages at a time is not handled yet. TODO.");
+
+ for (i = 0; i < num; i++) {
+
+ if (msg[i].addr == 0x99) {
+ req = 0xBE;
+ index = 0;
+ value = msg[i].buf[0] & 0x00ff;
+ length = 1;
+ az6027_usb_out_op(d, req, value, index, data, length);
+ }
+
+ if (msg[i].addr == 0xd0) {
+ /* write/read request */
+ if (i + 1 < num && (msg[i + 1].flags & I2C_M_RD)) {
+ req = 0xB9;
+ index = (((msg[i].buf[0] << 8) & 0xff00) | (msg[i].buf[1] & 0x00ff));
+ value = msg[i].addr + (msg[i].len << 8);
+ length = msg[i + 1].len + 6;
+ ret = az6027_usb_in_op(d, req, value, index, data, length);
+ len = msg[i + 1].len;
+ for (j = 0; j < len; j++)
+ msg[i + 1].buf[j] = data[j + 5];
+
+ i++;
+ } else {
+
+ if (msg[i].addr == 0xd0) {
+ /* demod 16bit addr */
+ req = 0xBD;
+ index = (((msg[i].buf[0] << 8) & 0xff00) | (msg[i].buf[1] & 0x00ff));
+ value = msg[i].addr + (2 << 8);
+ length = msg[i].len - 2;
+ len = msg[i].len - 2;
+ for (j = 0; j < len; j++)
+ data[j] = msg[i].buf[j + 2];
+
+ }
+ az6027_usb_out_op(d, req, value, index, data, length);
+ }
+ }
+
+ if (msg[i].addr == 0xc0) {
+ if (msg[i].flags & I2C_M_RD) {
+
+ req = 0xB9;
+ index = 0x0;
+ value = msg[i].addr;
+ length = msg[i].len + 6;
+ ret = az6027_usb_in_op(d, req, value, index, data, length);
+ len = msg[i].len;
+ for (j = 0; j < len; j++)
+ msg[i].buf[j] = data[j + 5];
+
+ } else {
+
+ req = 0xBD;
+ index = msg[i].buf[0] & 0x00FF;
+ value = msg[i].addr + (1 << 8);
+ length = msg[i].len - 1;
+ len = msg[i].len - 1;
+
+ for (j = 0; j < len; j++)
+ data[j] = msg[i].buf[j + 1];
+
+ az6027_usb_out_op(d, req, value, index, data, length);
+ }
+ }
+ }
+ mutex_unlock(&d->i2c_mutex);
+
+ return i;
+}
+
+
+static u32 az6027_i2c_func(struct i2c_adapter *adapter)
+{
+ return I2C_FUNC_I2C;
+}
+
+static struct i2c_algorithm az6027_i2c_algo = {
+ .master_xfer = az6027_i2c_xfer,
+ .functionality = az6027_i2c_func,
+};
+
+int az6027_identify_state(struct usb_device *udev,
+ struct dvb_usb_device_properties *props,
+ struct dvb_usb_device_description **desc,
+ int *cold)
+{
+ u8 b[16];
+ s16 ret = usb_control_msg(udev,
+ usb_rcvctrlpipe(udev, 0),
+ 0xb7,
+ USB_TYPE_VENDOR | USB_DIR_IN,
+ 6,
+ 0,
+ b,
+ 6,
+ USB_CTRL_GET_TIMEOUT);
+
+ *cold = ret <= 0;
+
+ deb_info("cold: %d\n", *cold);
+ return 0;
+}
+
+
+static struct usb_device_id az6027_usb_table[] = {
+ { USB_DEVICE(USB_VID_AZUREWAVE, USB_PID_AZUREWAVE_AZ6027) },
+ { USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_DVBS2CI) },
+ { USB_DEVICE(USB_VID_TECHNISAT, USB_PID_TECHNISAT_USB2_HDCI) },
+ { },
+};
+
+MODULE_DEVICE_TABLE(usb, az6027_usb_table);
+
+static struct dvb_usb_device_properties az6027_properties = {
+ .caps = DVB_USB_IS_AN_I2C_ADAPTER,
+ .usb_ctrl = CYPRESS_FX2,
+ .firmware = "dvb-usb-az6027-03.fw",
+ .no_reconnect = 1,
+
+ .size_of_priv = sizeof(struct az6027_device_state),
+ .identify_state = az6027_identify_state,
+ .num_adapters = 1,
+ .adapter = {
+ {
+ .streaming_ctrl = az6027_streaming_ctrl,
+ .frontend_attach = az6027_frontend_attach,
+
+ /* parameter for the MPEG2-data transfer */
+ .stream = {
+ .type = USB_BULK,
+ .count = 10,
+ .endpoint = 0x02,
+ .u = {
+ .bulk = {
+ .buffersize = 4096,
+ }
+ }
+ },
+ }
+ },
+/*
+ .power_ctrl = az6027_power_ctrl,
+ .read_mac_address = az6027_read_mac_addr,
+ */
+ .rc_key_map = az6027_rc_keys,
+ .rc_key_map_size = ARRAY_SIZE(az6027_rc_keys),
+ .rc_interval = 400,
+ .rc_query = az6027_rc_query,
+ .i2c_algo = &az6027_i2c_algo,
+
+ .num_device_descs = 1,
+ .devices = {
+ {
+ .name = "AZUREWAVE DVB-S/S2 USB2.0 (AZ6027)",
+ .cold_ids = { &az6027_usb_table[0], NULL },
+ .warm_ids = { NULL },
+ },
+ { NULL },
+ }
+};
+
+/* usb specific object needed to register this driver with the usb subsystem */
+static struct usb_driver az6027_usb_driver = {
+ .name = "dvb_usb_az6027",
+ .probe = az6027_usb_probe,
+ .disconnect = az6027_usb_disconnect,
+ .id_table = az6027_usb_table,
+};
+
+/* module stuff */
+static int __init az6027_usb_module_init(void)
+{
+ int result;
+
+ result = usb_register(&az6027_usb_driver);
+ if (result) {
+ err("usb_register failed. (%d)", result);
+ return result;
+ }
+
+ return 0;
+}
+
+static void __exit az6027_usb_module_exit(void)
+{
+ /* deregister this driver from the USB subsystem */
+ usb_deregister(&az6027_usb_driver);
+}
+
+module_init(az6027_usb_module_init);
+module_exit(az6027_usb_module_exit);
+
+MODULE_AUTHOR("Adams Xu <Adams.xu@azwave.com.cn>");
+MODULE_DESCRIPTION("Driver for AZUREWAVE DVB-S/S2 USB2.0 (AZ6027)");
+MODULE_VERSION("1.0");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/az6027.h b/drivers/media/dvb/dvb-usb/az6027.h
new file mode 100644
index 000000000000..f3afe17f3f3d
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/az6027.h
@@ -0,0 +1,14 @@
+#ifndef _DVB_USB_VP6027_H_
+#define _DVB_USB_VP6027_H_
+
+#define DVB_USB_LOG_PREFIX "az6027"
+#include "dvb-usb.h"
+
+
+extern int dvb_usb_az6027_debug;
+#define deb_info(args...) dprintk(dvb_usb_az6027_debug, 0x01, args)
+#define deb_xfer(args...) dprintk(dvb_usb_az6027_debug, 0x02, args)
+#define deb_rc(args...) dprintk(dvb_usb_az6027_debug, 0x04, args)
+#define deb_fe(args...) dprintk(dvb_usb_az6027_debug, 0x08, args)
+
+#endif
diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c
index 05fb28e9c69e..a7b8405c291e 100644
--- a/drivers/media/dvb/dvb-usb/cxusb.c
+++ b/drivers/media/dvb/dvb-usb/cxusb.c
@@ -1184,6 +1184,9 @@ static struct atbm8830_config mygica_d689_atbm8830_cfg = {
.osc_clk_freq = 30400, /* in kHz */
.if_freq = 0, /* zero IF */
.zif_swap_iq = 1,
+ .agc_min = 0x2E,
+ .agc_max = 0x90,
+ .agc_hold_loop = 0,
};
static int cxusb_mygica_d689_frontend_attach(struct dvb_usb_adapter *adap)
diff --git a/drivers/media/dvb/dvb-usb/dib0700.h b/drivers/media/dvb/dvb-usb/dib0700.h
index 495a90577c5f..83fc24a6c31a 100644
--- a/drivers/media/dvb/dvb-usb/dib0700.h
+++ b/drivers/media/dvb/dvb-usb/dib0700.h
@@ -42,7 +42,6 @@ struct dib0700_state {
u16 mt2060_if1[2];
u8 rc_toggle;
u8 rc_counter;
- u8 rc_func_version;
u8 is_dib7000pc;
u8 fw_use_new_i2c_api;
u8 disable_streaming_master_mode;
diff --git a/drivers/media/dvb/dvb-usb/dib0700_core.c b/drivers/media/dvb/dvb-usb/dib0700_core.c
index 0d3c9a9a33be..4f961d2d1817 100644
--- a/drivers/media/dvb/dvb-usb/dib0700_core.c
+++ b/drivers/media/dvb/dvb-usb/dib0700_core.c
@@ -471,14 +471,209 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
return dib0700_ctrl_wr(adap->dev, b, 4);
}
+/* Number of keypresses to ignore before start repeating */
+#define RC_REPEAT_DELAY_V1_20 10
+
+/* This is the structure of the RC response packet starting in firmware 1.20 */
+struct dib0700_rc_response {
+ u8 report_id;
+ u8 data_state;
+ u16 system;
+ u8 data;
+ u8 not_data;
+};
+#define RC_MSG_SIZE_V1_20 6
+
+static void dib0700_rc_urb_completion(struct urb *purb)
+{
+ struct dvb_usb_device *d = purb->context;
+ struct dvb_usb_rc_key *keymap;
+ struct dib0700_state *st;
+ struct dib0700_rc_response poll_reply;
+ u8 *buf;
+ int found = 0;
+ u32 event;
+ int state;
+ int i;
+
+ deb_info("%s()\n", __func__);
+ if (d == NULL)
+ return;
+
+ if (d->rc_input_dev == NULL) {
+ /* This will occur if disable_rc_polling=1 */
+ usb_free_urb(purb);
+ return;
+ }
+
+ keymap = d->props.rc_key_map;
+ st = d->priv;
+ buf = (u8 *)purb->transfer_buffer;
+
+ if (purb->status < 0) {
+ deb_info("discontinuing polling\n");
+ usb_free_urb(purb);
+ return;
+ }
+
+ if (purb->actual_length != RC_MSG_SIZE_V1_20) {
+ deb_info("malformed rc msg size=%d\n", purb->actual_length);
+ goto resubmit;
+ }
+
+ /* Set initial results in case we exit the function early */
+ event = 0;
+ state = REMOTE_NO_KEY_PRESSED;
+
+ deb_data("IR raw %02X %02X %02X %02X %02X %02X (len %d)\n", buf[0],
+ buf[1], buf[2], buf[3], buf[4], buf[5], purb->actual_length);
+
+ switch (dvb_usb_dib0700_ir_proto) {
+ case 0:
+ /* NEC Protocol */
+ poll_reply.report_id = 0;
+ poll_reply.data_state = 1;
+ poll_reply.system = buf[2];
+ poll_reply.data = buf[4];
+ poll_reply.not_data = buf[5];
+
+ /* NEC protocol sends repeat code as 0 0 0 FF */
+ if ((poll_reply.system == 0x00) && (poll_reply.data == 0x00)
+ && (poll_reply.not_data == 0xff)) {
+ poll_reply.data_state = 2;
+ break;
+ }
+ break;
+ default:
+ /* RC5 Protocol */
+ poll_reply.report_id = buf[0];
+ poll_reply.data_state = buf[1];
+ poll_reply.system = (buf[2] << 8) | buf[3];
+ poll_reply.data = buf[4];
+ poll_reply.not_data = buf[5];
+ break;
+ }
+
+ if ((poll_reply.data + poll_reply.not_data) != 0xff) {
+ /* Key failed integrity check */
+ err("key failed integrity check: %04x %02x %02x",
+ poll_reply.system,
+ poll_reply.data, poll_reply.not_data);
+ goto resubmit;
+ }
+
+ deb_data("rid=%02x ds=%02x sm=%04x d=%02x nd=%02x\n",
+ poll_reply.report_id, poll_reply.data_state,
+ poll_reply.system, poll_reply.data, poll_reply.not_data);
+
+ /* Find the key in the map */
+ for (i = 0; i < d->props.rc_key_map_size; i++) {
+ if (rc5_custom(&keymap[i]) == (poll_reply.system & 0xff) &&
+ rc5_data(&keymap[i]) == poll_reply.data) {
+ event = keymap[i].event;
+ found = 1;
+ break;
+ }
+ }
+
+ if (found == 0) {
+ err("Unknown remote controller key: %04x %02x %02x",
+ poll_reply.system, poll_reply.data, poll_reply.not_data);
+ d->last_event = 0;
+ goto resubmit;
+ }
+
+ if (poll_reply.data_state == 1) {
+ /* New key hit */
+ st->rc_counter = 0;
+ event = keymap[i].event;
+ state = REMOTE_KEY_PRESSED;
+ d->last_event = keymap[i].event;
+ } else if (poll_reply.data_state == 2) {
+ /* Key repeated */
+ st->rc_counter++;
+
+ /* prevents unwanted double hits */
+ if (st->rc_counter > RC_REPEAT_DELAY_V1_20) {
+ event = d->last_event;
+ state = REMOTE_KEY_PRESSED;
+ st->rc_counter = RC_REPEAT_DELAY_V1_20;
+ }
+ } else {
+ err("Unknown data state [%d]", poll_reply.data_state);
+ }
+
+ switch (state) {
+ case REMOTE_NO_KEY_PRESSED:
+ break;
+ case REMOTE_KEY_PRESSED:
+ deb_info("key pressed\n");
+ d->last_event = event;
+ case REMOTE_KEY_REPEAT:
+ deb_info("key repeated\n");
+ input_event(d->rc_input_dev, EV_KEY, event, 1);
+ input_sync(d->rc_input_dev);
+ input_event(d->rc_input_dev, EV_KEY, d->last_event, 0);
+ input_sync(d->rc_input_dev);
+ break;
+ default:
+ break;
+ }
+
+resubmit:
+ /* Clean the buffer before we requeue */
+ memset(purb->transfer_buffer, 0, RC_MSG_SIZE_V1_20);
+
+ /* Requeue URB */
+ usb_submit_urb(purb, GFP_ATOMIC);
+}
+
int dib0700_rc_setup(struct dvb_usb_device *d)
{
+ struct dib0700_state *st = d->priv;
u8 rc_setup[3] = {REQUEST_SET_RC, dvb_usb_dib0700_ir_proto, 0};
- int i = dib0700_ctrl_wr(d, rc_setup, 3);
+ struct urb *purb;
+ int ret;
+ int i;
+
+ if (d->props.rc_key_map == NULL)
+ return 0;
+
+ /* Set the IR mode */
+ i = dib0700_ctrl_wr(d, rc_setup, 3);
if (i<0) {
err("ir protocol setup failed");
return -1;
}
+
+ if (st->fw_version < 0x10200)
+ return 0;
+
+ /* Starting in firmware 1.20, the RC info is provided on a bulk pipe */
+ purb = usb_alloc_urb(0, GFP_KERNEL);
+ if (purb == NULL) {
+ err("rc usb alloc urb failed\n");
+ return -1;
+ }
+
+ purb->transfer_buffer = kzalloc(RC_MSG_SIZE_V1_20, GFP_KERNEL);
+ if (purb->transfer_buffer == NULL) {
+ err("rc kzalloc failed\n");
+ usb_free_urb(purb);
+ return -1;
+ }
+
+ purb->status = -EINPROGRESS;
+ usb_fill_bulk_urb(purb, d->udev, usb_rcvbulkpipe(d->udev, 1),
+ purb->transfer_buffer, RC_MSG_SIZE_V1_20,
+ dib0700_rc_urb_completion, d);
+
+ ret = usb_submit_urb(purb, GFP_ATOMIC);
+ if (ret != 0) {
+ err("rc submit urb failed\n");
+ return -1;
+ }
+
return 0;
}
diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c
index 44972d01bbd0..34eab05afc6c 100644
--- a/drivers/media/dvb/dvb-usb/dib0700_devices.c
+++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c
@@ -472,20 +472,25 @@ static u8 rc_request[] = { REQUEST_POLL_RC, 0 };
/* Number of keypresses to ignore before start repeating */
#define RC_REPEAT_DELAY 6
-#define RC_REPEAT_DELAY_V1_20 10
-
-
-/* Used by firmware versions < 1.20 (deprecated) */
-static int dib0700_rc_query_legacy(struct dvb_usb_device *d, u32 *event,
- int *state)
+static int dib0700_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
{
u8 key[4];
int i;
struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
struct dib0700_state *st = d->priv;
+
*event = 0;
*state = REMOTE_NO_KEY_PRESSED;
+
+ if (st->fw_version >= 0x10200) {
+ /* For 1.20 firmware , We need to keep the RC polling
+ callback so we can reuse the input device setup in
+ dvb-usb-remote.c. However, the actual work is being done
+ in the bulk URB completion handler. */
+ return 0;
+ }
+
i=dib0700_ctrl_rd(d,rc_request,2,key,4);
if (i<=0) {
err("RC Query Failed");
@@ -557,149 +562,6 @@ static int dib0700_rc_query_legacy(struct dvb_usb_device *d, u32 *event,
return 0;
}
-/* This is the structure of the RC response packet starting in firmware 1.20 */
-struct dib0700_rc_response {
- u8 report_id;
- u8 data_state;
- u16 system;
- u8 data;
- u8 not_data;
-};
-
-/* This supports the new IR response format for firmware v1.20 */
-static int dib0700_rc_query_v1_20(struct dvb_usb_device *d, u32 *event,
- int *state)
-{
- struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
- struct dib0700_state *st = d->priv;
- struct dib0700_rc_response poll_reply;
- u8 buf[6];
- int i;
- int status;
- int actlen;
- int found = 0;
-
- /* Set initial results in case we exit the function early */
- *event = 0;
- *state = REMOTE_NO_KEY_PRESSED;
-
- /* Firmware v1.20 provides RC data via bulk endpoint 1 */
- status = usb_bulk_msg(d->udev, usb_rcvbulkpipe(d->udev, 1), buf,
- sizeof(buf), &actlen, 50);
- if (status < 0) {
- /* No data available (meaning no key press) */
- return 0;
- }
-
-
- switch (dvb_usb_dib0700_ir_proto) {
- case 0:
- poll_reply.report_id = 0;
- poll_reply.data_state = 1;
- poll_reply.system = buf[2];
- poll_reply.data = buf[4];
- poll_reply.not_data = buf[5];
-
- /* NEC protocol sends repeat code as 0 0 0 FF */
- if ((poll_reply.system == 0x00) && (poll_reply.data == 0x00)
- && (poll_reply.not_data == 0xff)) {
- poll_reply.data_state = 2;
- break;
- }
- break;
- default:
- if (actlen != sizeof(buf)) {
- /* We didn't get back the 6 byte message we expected */
- err("Unexpected RC response size [%d]", actlen);
- return -1;
- }
-
- poll_reply.report_id = buf[0];
- poll_reply.data_state = buf[1];
- poll_reply.system = (buf[2] << 8) | buf[3];
- poll_reply.data = buf[4];
- poll_reply.not_data = buf[5];
-
- break;
- }
-
- if ((poll_reply.data + poll_reply.not_data) != 0xff) {
- /* Key failed integrity check */
- err("key failed integrity check: %04x %02x %02x",
- poll_reply.system,
- poll_reply.data, poll_reply.not_data);
- return -1;
- }
-
-
- /* Find the key in the map */
- for (i = 0; i < d->props.rc_key_map_size; i++) {
- if (rc5_custom(&keymap[i]) == (poll_reply.system & 0xff) &&
- rc5_data(&keymap[i]) == poll_reply.data) {
- *event = keymap[i].event;
- found = 1;
- break;
- }
- }
-
- if (found == 0) {
- err("Unknown remote controller key: %04x %02x %02x",
- poll_reply.system,
- poll_reply.data, poll_reply.not_data);
- d->last_event = 0;
- return 0;
- }
-
- if (poll_reply.data_state == 1) {
- /* New key hit */
- st->rc_counter = 0;
- *event = keymap[i].event;
- *state = REMOTE_KEY_PRESSED;
- d->last_event = keymap[i].event;
- } else if (poll_reply.data_state == 2) {
- /* Key repeated */
- st->rc_counter++;
-
- /* prevents unwanted double hits */
- if (st->rc_counter > RC_REPEAT_DELAY_V1_20) {
- *event = d->last_event;
- *state = REMOTE_KEY_PRESSED;
- st->rc_counter = RC_REPEAT_DELAY_V1_20;
- }
- } else {
- err("Unknown data state [%d]", poll_reply.data_state);
- }
-
- return 0;
-}
-
-static int dib0700_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
-{
- struct dib0700_state *st = d->priv;
-
- /* Because some people may have improperly named firmware files,
- let's figure out whether to use the new firmware call or the legacy
- call based on the firmware version embedded in the file */
- if (st->rc_func_version == 0) {
- u32 hwver, romver, ramver, fwtype;
- int ret = dib0700_get_version(d, &hwver, &romver, &ramver,
- &fwtype);
- if (ret < 0) {
- err("Could not determine version info");
- return -1;
- }
- if (ramver < 0x10200)
- st->rc_func_version = 1;
- else
- st->rc_func_version = 2;
- }
-
- if (st->rc_func_version == 2)
- return dib0700_rc_query_v1_20(d, event, state);
- else
- return dib0700_rc_query_legacy(d, event, state);
-}
-
static struct dvb_usb_rc_key dib0700_rc_keys[] = {
/* Key codes for the tiny Pinnacle remote*/
{ 0x0700, KEY_MUTE },
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
index bc3581d58ced..ae8b57acfe05 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
@@ -64,6 +64,8 @@
#define USB_VID_HUMAX_COEX 0x10b9
#define USB_VID_774 0x7a69
#define USB_VID_EVOLUTEPC 0x1e59
+#define USB_VID_AZUREWAVE 0x13d3
+#define USB_VID_TECHNISAT 0x14f7
/* Product IDs */
#define USB_PID_ADSTECH_USB2_COLD 0xa333
@@ -138,6 +140,7 @@
#define USB_PID_TWINHAN_VP7021_COLD 0x3207
#define USB_PID_TWINHAN_VP7021_WARM 0x3208
#define USB_PID_TINYTWIN 0x3226
+#define USB_PID_TINYTWIN_2 0xe402
#define USB_PID_DNTV_TINYUSB2_COLD 0x3223
#define USB_PID_DNTV_TINYUSB2_WARM 0x3224
#define USB_PID_ULTIMA_TVBOX_COLD 0x8105
@@ -209,6 +212,7 @@
#define USB_PID_PINNACLE_PCTV71E 0x022b
#define USB_PID_PINNACLE_PCTV72E 0x0236
#define USB_PID_PINNACLE_PCTV73E 0x0237
+#define USB_PID_PINNACLE_PCTV310E 0x3211
#define USB_PID_PINNACLE_PCTV801E 0x023a
#define USB_PID_PINNACLE_PCTV801E_SE 0x023b
#define USB_PID_PINNACLE_PCTV73A 0x0243
@@ -248,6 +252,7 @@
#define USB_PID_DIGIVOX_MINI_SL_WARM 0xe361
#define USB_PID_GRANDTEC_DVBT_USB2_COLD 0x0bc6
#define USB_PID_GRANDTEC_DVBT_USB2_WARM 0x0bc7
+#define USB_PID_WINFAST_DTV2000DS 0x6a04
#define USB_PID_WINFAST_DTV_DONGLE_COLD 0x6025
#define USB_PID_WINFAST_DTV_DONGLE_WARM 0x6026
#define USB_PID_WINFAST_DTV_DONGLE_STK7700P 0x6f00
@@ -290,5 +295,7 @@
#define USB_PID_FRIIO_WHITE 0x0001
#define USB_PID_TVWAY_PLUS 0x0002
#define USB_PID_SVEON_STV20 0xe39d
-
+#define USB_PID_AZUREWAVE_AZ6027 0x3275
+#define USB_PID_TERRATEC_DVBS2CI 0x3275
+#define USB_PID_TECHNISAT_USB2_HDCI 0x0002
#endif
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-init.c b/drivers/media/dvb/dvb-usb/dvb-usb-init.c
index e331db8c77b2..5d91f70d2d2d 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-init.c
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-init.c
@@ -243,7 +243,7 @@ int dvb_usb_device_init(struct usb_interface *intf,
d = kzalloc(sizeof(struct dvb_usb_device),GFP_KERNEL);
if (d == NULL) {
err("no memory for 'struct dvb_usb_device'");
- return ret;
+ return -ENOMEM;
}
d->udev = udev;
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c
index 6b5ded9e7d5d..a03ef7efec9a 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c
@@ -107,6 +107,7 @@ static void dvb_usb_read_remote_control(struct work_struct *work)
case REMOTE_KEY_REPEAT:
deb_rc("key repeated\n");
input_event(d->rc_input_dev, EV_KEY, event, 1);
+ input_sync(d->rc_input_dev);
input_event(d->rc_input_dev, EV_KEY, d->last_event, 0);
input_sync(d->rc_input_dev);
break;
diff --git a/drivers/media/dvb/dvb-usb/dw2102.c b/drivers/media/dvb/dvb-usb/dw2102.c
index 64132c0cf80d..accc65509b07 100644
--- a/drivers/media/dvb/dvb-usb/dw2102.c
+++ b/drivers/media/dvb/dvb-usb/dw2102.c
@@ -1,6 +1,7 @@
/* DVB USB framework compliant Linux driver for the
* DVBWorld DVB-S 2101, 2102, DVB-S2 2104, DVB-C 3101,
-* TeVii S600, S630, S650 Cards
+* TeVii S600, S630, S650,
+* Prof 1100, 7500 Cards
* Copyright (C) 2008,2009 Igor M. Liplianin (liplianin@me.by)
*
* This program is free software; you can redistribute it and/or modify it
@@ -469,11 +470,13 @@ static int s6x0_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
int num)
{
struct dvb_usb_device *d = i2c_get_adapdata(adap);
+ struct usb_device *udev;
int ret = 0;
int len, i, j;
if (!d)
return -ENODEV;
+ udev = d->udev;
if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
return -EAGAIN;
@@ -488,8 +491,13 @@ static int s6x0_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
}
case (DW2102_VOLTAGE_CTRL): {
u8 obuf[2];
+
+ obuf[0] = 1;
+ obuf[1] = msg[j].buf[1];/* off-on */
+ ret = dw210x_op_rw(d->udev, 0x8a, 0, 0,
+ obuf, 2, DW210X_WRITE_MSG);
obuf[0] = 3;
- obuf[1] = msg[j].buf[0];
+ obuf[1] = msg[j].buf[0];/* 13v-18v */
ret = dw210x_op_rw(d->udev, 0x8a, 0, 0,
obuf, 2, DW210X_WRITE_MSG);
break;
@@ -527,6 +535,17 @@ static int s6x0_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
i += 16;
len -= 16;
} while (len > 0);
+ } else if ((udev->descriptor.idProduct == 0x7500)
+ && (j < (num - 1))) {
+ /* write register addr before read */
+ u8 obuf[msg[j].len + 2];
+ obuf[0] = msg[j + 1].len;
+ obuf[1] = (msg[j].addr << 1);
+ memcpy(obuf + 2, msg[j].buf, msg[j].len);
+ ret = dw210x_op_rw(d->udev, 0x92, 0, 0,
+ obuf, msg[j].len + 2,
+ DW210X_WRITE_MSG);
+ break;
} else {
/* write registers */
u8 obuf[msg[j].len + 2];
@@ -651,18 +670,25 @@ static int s6x0_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
static int dw210x_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
{
- static u8 command_13v[1] = {0x00};
- static u8 command_18v[1] = {0x01};
- struct i2c_msg msg[] = {
- {.addr = DW2102_VOLTAGE_CTRL, .flags = 0,
- .buf = command_13v, .len = 1},
+ static u8 command_13v[] = {0x00, 0x01};
+ static u8 command_18v[] = {0x01, 0x01};
+ static u8 command_off[] = {0x00, 0x00};
+ struct i2c_msg msg = {
+ .addr = DW2102_VOLTAGE_CTRL,
+ .flags = 0,
+ .buf = command_off,
+ .len = 2,
};
struct dvb_usb_adapter *udev_adap =
(struct dvb_usb_adapter *)(fe->dvb->priv);
if (voltage == SEC_VOLTAGE_18)
- msg[0].buf = command_18v;
- i2c_transfer(&udev_adap->dev->i2c_adap, msg, 1);
+ msg.buf = command_18v;
+ else if (voltage == SEC_VOLTAGE_13)
+ msg.buf = command_13v;
+
+ i2c_transfer(&udev_adap->dev->i2c_adap, &msg, 1);
+
return 0;
}
@@ -735,6 +761,18 @@ static struct stv6110_config dw2104_stv6110_config = {
.clk_div = 1,
};
+static struct stv0900_config prof_7500_stv0900_config = {
+ .demod_address = 0x6a,
+ .demod_mode = 0,
+ .xtal = 27000000,
+ .clkmode = 3,/* 0-CLKI, 2-XTALI, else AUTO */
+ .diseqc_mode = 2,/* 2/3 PWM */
+ .tun1_maddress = 0,/* 0x60 */
+ .tun1_adc = 0,/* 2 Vpp */
+ .path1_mode = 3,
+ .tun1_type = 3,
+};
+
static int dw2104_frontend_attach(struct dvb_usb_adapter *d)
{
struct dvb_tuner_ops *tuner_ops = NULL;
@@ -882,6 +920,19 @@ static int s6x0_frontend_attach(struct dvb_usb_adapter *d)
return -EIO;
}
+static int prof_7500_frontend_attach(struct dvb_usb_adapter *d)
+{
+ d->fe = dvb_attach(stv0900_attach, &prof_7500_stv0900_config,
+ &d->dev->i2c_adap, 0);
+ if (d->fe == NULL)
+ return -EIO;
+ d->fe->ops.set_voltage = dw210x_set_voltage;
+
+ info("Attached STV0900+STB6100A!\n");
+
+ return 0;
+}
+
static int dw2102_tuner_attach(struct dvb_usb_adapter *adap)
{
dvb_attach(dvb_pll_attach, adap->fe, 0x60,
@@ -1073,6 +1124,7 @@ static struct usb_device_id dw2102_table[] = {
{USB_DEVICE(0x9022, USB_PID_TEVII_S630)},
{USB_DEVICE(0x3011, USB_PID_PROF_1100)},
{USB_DEVICE(0x9022, USB_PID_TEVII_S660)},
+ {USB_DEVICE(0x3034, 0x7500)},
{ }
};
@@ -1387,9 +1439,30 @@ static struct dvb_usb_device_properties s6x0_properties = {
}
};
+struct dvb_usb_device_properties *p7500;
+static struct dvb_usb_device_description d7500 = {
+ "Prof 7500 USB DVB-S2",
+ {&dw2102_table[9], NULL},
+ {NULL},
+};
+
static int dw2102_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
+
+ p7500 = kzalloc(sizeof(struct dvb_usb_device_properties), GFP_KERNEL);
+ if (!p7500)
+ return -ENOMEM;
+ /* copy default structure */
+ memcpy(p7500, &s6x0_properties,
+ sizeof(struct dvb_usb_device_properties));
+ /* fill only different fields */
+ p7500->firmware = "dvb-usb-p7500.fw";
+ p7500->devices[0] = d7500;
+ p7500->rc_key_map = tbs_rc_keys;
+ p7500->rc_key_map_size = ARRAY_SIZE(tbs_rc_keys);
+ p7500->adapter->frontend_attach = prof_7500_frontend_attach;
+
if (0 == dvb_usb_device_init(intf, &dw2102_properties,
THIS_MODULE, NULL, adapter_nr) ||
0 == dvb_usb_device_init(intf, &dw2104_properties,
@@ -1397,6 +1470,8 @@ static int dw2102_probe(struct usb_interface *intf,
0 == dvb_usb_device_init(intf, &dw3101_properties,
THIS_MODULE, NULL, adapter_nr) ||
0 == dvb_usb_device_init(intf, &s6x0_properties,
+ THIS_MODULE, NULL, adapter_nr) ||
+ 0 == dvb_usb_device_init(intf, p7500,
THIS_MODULE, NULL, adapter_nr))
return 0;
@@ -1431,6 +1506,6 @@ MODULE_AUTHOR("Igor M. Liplianin (c) liplianin@me.by");
MODULE_DESCRIPTION("Driver for DVBWorld DVB-S 2101, 2102, DVB-S2 2104,"
" DVB-C 3101 USB2.0,"
" TeVii S600, S630, S650, S660 USB2.0,"
- " Prof 1100 USB2.0 devices");
+ " Prof 1100, 7500 USB2.0 devices");
MODULE_VERSION("0.1");
MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/friio-fe.c b/drivers/media/dvb/dvb-usb/friio-fe.c
index ebb7b9fd115b..d14bd227b502 100644
--- a/drivers/media/dvb/dvb-usb/friio-fe.c
+++ b/drivers/media/dvb/dvb-usb/friio-fe.c
@@ -366,7 +366,7 @@ static u8 init_code[][2] = {
{0x76, 0x0C},
};
-const static int init_code_len = sizeof(init_code) / sizeof(u8[2]);
+static const int init_code_len = sizeof(init_code) / sizeof(u8[2]);
static int jdvbt90502_init(struct dvb_frontend *fe)
{
diff --git a/drivers/media/dvb/dvb-usb/m920x.c b/drivers/media/dvb/dvb-usb/m920x.c
index ef9b7bed13ff..737ffa36ac9c 100644
--- a/drivers/media/dvb/dvb-usb/m920x.c
+++ b/drivers/media/dvb/dvb-usb/m920x.c
@@ -16,6 +16,9 @@
#include "qt1010.h"
#include "tda1004x.h"
#include "tda827x.h"
+
+#include <media/tuner.h>
+#include "tuner-simple.h"
#include <asm/unaligned.h>
/* debug */
@@ -158,11 +161,14 @@ static int m920x_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
case 0x93:
case 0x92:
+ case 0x83: /* pinnacle PCTV310e */
+ case 0x82:
m->rep_count = 0;
*state = REMOTE_KEY_PRESSED;
goto unlock;
case 0x91:
+ case 0x81: /* pinnacle PCTV310e */
/* prevent immediate auto-repeat */
if (++m->rep_count > 2)
*state = REMOTE_KEY_REPEAT;
@@ -546,6 +552,14 @@ static int m920x_tda8275_61_tuner_attach(struct dvb_usb_adapter *adap)
return 0;
}
+static int m920x_fmd1216me_tuner_attach(struct dvb_usb_adapter *adap)
+{
+ dvb_attach(simple_tuner_attach, adap->fe,
+ &adap->dev->i2c_adap, 0x61,
+ TUNER_PHILIPS_FMD1216ME_MK3);
+ return 0;
+}
+
/* device-specific initialization */
static struct m920x_inits megasky_rc_init [] = {
{ M9206_RC_INIT2, 0xa8 },
@@ -562,6 +576,18 @@ static struct m920x_inits tvwalkertwin_rc_init [] = {
{ } /* terminating entry */
};
+static struct m920x_inits pinnacle310e_init[] = {
+ /* without these the tuner don't work */
+ { 0xff20, 0x9b },
+ { 0xff22, 0x70 },
+
+ /* rc settings */
+ { 0xff50, 0x80 },
+ { M9206_RC_INIT1, 0x00 },
+ { M9206_RC_INIT2, 0xff },
+ { } /* terminating entry */
+};
+
/* ir keymaps */
static struct dvb_usb_rc_key megasky_rc_keys [] = {
{ 0x0012, KEY_POWER },
@@ -602,11 +628,68 @@ static struct dvb_usb_rc_key tvwalkertwin_rc_keys [] = {
{ 0x001e, KEY_VOLUMEUP },
};
+static struct dvb_usb_rc_key pinnacle310e_rc_keys[] = {
+ { 0x16, KEY_POWER },
+ { 0x17, KEY_FAVORITES },
+ { 0x0f, KEY_TEXT },
+ { 0x48, KEY_MEDIA }, /* preview */
+ { 0x1c, KEY_EPG },
+ { 0x04, KEY_LIST }, /* record list */
+ { 0x03, KEY_1 },
+ { 0x01, KEY_2 },
+ { 0x06, KEY_3 },
+ { 0x09, KEY_4 },
+ { 0x1d, KEY_5 },
+ { 0x1f, KEY_6 },
+ { 0x0d, KEY_7 },
+ { 0x19, KEY_8 },
+ { 0x1b, KEY_9 },
+ { 0x15, KEY_0 },
+ { 0x0c, KEY_CANCEL },
+ { 0x4a, KEY_CLEAR },
+ { 0x13, KEY_BACK },
+ { 0x00, KEY_TAB },
+ { 0x4b, KEY_UP },
+ { 0x4e, KEY_LEFT },
+ { 0x52, KEY_RIGHT },
+ { 0x51, KEY_DOWN },
+ { 0x4f, KEY_ENTER }, /* could also be KEY_OK */
+ { 0x1e, KEY_VOLUMEUP },
+ { 0x0a, KEY_VOLUMEDOWN },
+ { 0x05, KEY_CHANNELUP },
+ { 0x02, KEY_CHANNELDOWN },
+ { 0x11, KEY_RECORD },
+ { 0x14, KEY_PLAY },
+ { 0x4c, KEY_PAUSE },
+ { 0x1a, KEY_STOP },
+ { 0x40, KEY_REWIND },
+ { 0x12, KEY_FASTFORWARD },
+ { 0x41, KEY_PREVIOUSSONG }, /* Replay */
+ { 0x42, KEY_NEXTSONG }, /* Skip */
+ { 0x54, KEY_CAMERA }, /* Capture */
+/* { 0x50, KEY_SAP }, */ /* Sap */
+ { 0x47, KEY_CYCLEWINDOWS }, /* Pip */
+ { 0x4d, KEY_SCREEN }, /* FullScreen */
+ { 0x08, KEY_SUBTITLE },
+ { 0x0e, KEY_MUTE },
+/* { 0x49, KEY_LR }, */ /* L/R */
+ { 0x07, KEY_SLEEP }, /* Hibernate */
+ { 0x08, KEY_MEDIA }, /* A/V */
+ { 0x0e, KEY_MENU }, /* Recall */
+ { 0x45, KEY_ZOOMIN },
+ { 0x46, KEY_ZOOMOUT },
+ { 0x18, KEY_TV }, /* Red */
+ { 0x53, KEY_VCR }, /* Green */
+ { 0x5e, KEY_SAT }, /* Yellow */
+ { 0x5f, KEY_PLAYER }, /* Blue */
+};
+
/* DVB USB Driver stuff */
static struct dvb_usb_device_properties megasky_properties;
static struct dvb_usb_device_properties digivox_mini_ii_properties;
static struct dvb_usb_device_properties tvwalkertwin_properties;
static struct dvb_usb_device_properties dposh_properties;
+static struct dvb_usb_device_properties pinnacle_pctv310e_properties;
static int m920x_probe(struct usb_interface *intf,
const struct usb_device_id *id)
@@ -652,6 +735,13 @@ static int m920x_probe(struct usb_interface *intf,
goto found;
}
+ ret = dvb_usb_device_init(intf, &pinnacle_pctv310e_properties,
+ THIS_MODULE, &d, adapter_nr);
+ if (ret == 0) {
+ rc_init_seq = pinnacle310e_init;
+ goto found;
+ }
+
return ret;
} else {
/* Another interface on a multi-tuner device */
@@ -682,6 +772,7 @@ static struct usb_device_id m920x_table [] = {
USB_PID_LIFEVIEW_TV_WALKER_TWIN_WARM) },
{ USB_DEVICE(USB_VID_DPOSH, USB_PID_DPOSH_M9206_COLD) },
{ USB_DEVICE(USB_VID_DPOSH, USB_PID_DPOSH_M9206_WARM) },
+ { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_PINNACLE_PCTV310E) },
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE (usb, m920x_table);
@@ -895,6 +986,56 @@ static struct dvb_usb_device_properties dposh_properties = {
}
};
+static struct dvb_usb_device_properties pinnacle_pctv310e_properties = {
+ .caps = DVB_USB_IS_AN_I2C_ADAPTER,
+
+ .usb_ctrl = DEVICE_SPECIFIC,
+ .download_firmware = NULL,
+
+ .rc_interval = 100,
+ .rc_key_map = pinnacle310e_rc_keys,
+ .rc_key_map_size = ARRAY_SIZE(pinnacle310e_rc_keys),
+ .rc_query = m920x_rc_query,
+
+ .size_of_priv = sizeof(struct m920x_state),
+
+ .identify_state = m920x_identify_state,
+ .num_adapters = 1,
+ .adapter = {{
+ .caps = DVB_USB_ADAP_HAS_PID_FILTER |
+ DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
+
+ .pid_filter_count = 8,
+ .pid_filter = m920x_pid_filter,
+ .pid_filter_ctrl = m920x_pid_filter_ctrl,
+
+ .frontend_attach = m920x_mt352_frontend_attach,
+ .tuner_attach = m920x_fmd1216me_tuner_attach,
+
+ .stream = {
+ .type = USB_ISOC,
+ .count = 5,
+ .endpoint = 0x84,
+ .u = {
+ .isoc = {
+ .framesperurb = 128,
+ .framesize = 564,
+ .interval = 1,
+ }
+ }
+ },
+ } },
+ .i2c_algo = &m920x_i2c_algo,
+
+ .num_device_descs = 1,
+ .devices = {
+ { "Pinnacle PCTV 310e",
+ { &m920x_table[6], NULL },
+ { NULL },
+ }
+ }
+};
+
static struct usb_driver m920x_driver = {
.name = "dvb_usb_m920x",
.probe = m920x_probe,
diff --git a/drivers/media/dvb/dvb-usb/m920x.h b/drivers/media/dvb/dvb-usb/m920x.h
index 37532890accd..3c061518ffc1 100644
--- a/drivers/media/dvb/dvb-usb/m920x.h
+++ b/drivers/media/dvb/dvb-usb/m920x.h
@@ -18,7 +18,7 @@
#define M9206_FW 0x30
#define M9206_MAX_FILTERS 8
-#define M9206_MAX_ADAPTERS 2
+#define M9206_MAX_ADAPTERS 4
/*
sequences found in logs:
diff --git a/drivers/media/dvb/dvb-usb/opera1.c b/drivers/media/dvb/dvb-usb/opera1.c
index d4e230941679..830557696ae6 100644
--- a/drivers/media/dvb/dvb-usb/opera1.c
+++ b/drivers/media/dvb/dvb-usb/opera1.c
@@ -138,7 +138,7 @@ static int opera1_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
(msg[i].addr<<1)|(msg[i].flags&I2C_M_RD?0x01:0),
msg[i].buf,
msg[i].len
- )!= msg[i].len)) {
+ )) != msg[i].len) {
break;
}
if (dvb_usb_opera1_debug & 0x10)
diff --git a/drivers/media/dvb/firewire/firedtv-1394.c b/drivers/media/dvb/firewire/firedtv-1394.c
index 7c5459c27b75..c3e0ec2dcfca 100644
--- a/drivers/media/dvb/firewire/firedtv-1394.c
+++ b/drivers/media/dvb/firewire/firedtv-1394.c
@@ -90,13 +90,14 @@ static inline struct node_entry *node_of(struct firedtv *fdtv)
return container_of(fdtv->device, struct unit_directory, device)->ne;
}
-static int node_lock(struct firedtv *fdtv, u64 addr, __be32 data[])
+static int node_lock(struct firedtv *fdtv, u64 addr, void *data)
{
+ quadlet_t *d = data;
int ret;
- ret = hpsb_node_lock(node_of(fdtv), addr, EXTCODE_COMPARE_SWAP,
- (__force quadlet_t *)&data[1], (__force quadlet_t)data[0]);
- data[0] = data[1];
+ ret = hpsb_node_lock(node_of(fdtv), addr,
+ EXTCODE_COMPARE_SWAP, &d[1], d[0]);
+ d[0] = d[1];
return ret;
}
@@ -192,9 +193,13 @@ static int node_probe(struct device *dev)
int kv_len, err;
void *kv_str;
- kv_len = (ud->model_name_kv->value.leaf.len - 2) * sizeof(quadlet_t);
- kv_str = CSR1212_TEXTUAL_DESCRIPTOR_LEAF_DATA(ud->model_name_kv);
-
+ if (ud->model_name_kv) {
+ kv_len = (ud->model_name_kv->value.leaf.len - 2) * 4;
+ kv_str = CSR1212_TEXTUAL_DESCRIPTOR_LEAF_DATA(ud->model_name_kv);
+ } else {
+ kv_len = 0;
+ kv_str = NULL;
+ }
fdtv = fdtv_alloc(dev, &fdtv_1394_backend, kv_str, kv_len);
if (!fdtv)
return -ENOMEM;
diff --git a/drivers/media/dvb/firewire/firedtv-avc.c b/drivers/media/dvb/firewire/firedtv-avc.c
index 50c42a4b972b..1b31bebc27d6 100644
--- a/drivers/media/dvb/firewire/firedtv-avc.c
+++ b/drivers/media/dvb/firewire/firedtv-avc.c
@@ -74,7 +74,6 @@
#define EN50221_TAG_CA_INFO 0x9f8031
struct avc_command_frame {
- int length;
u8 ctype;
u8 subunit;
u8 opcode;
@@ -82,13 +81,27 @@ struct avc_command_frame {
};
struct avc_response_frame {
- int length;
u8 response;
u8 subunit;
u8 opcode;
u8 operand[509];
};
+#define LAST_OPERAND (509 - 1)
+
+static inline void clear_operands(struct avc_command_frame *c, int from, int to)
+{
+ memset(&c->operand[from], 0, to - from + 1);
+}
+
+static void pad_operands(struct avc_command_frame *c, int from)
+{
+ int to = ALIGN(from, 4);
+
+ if (from <= to && to <= LAST_OPERAND)
+ clear_operands(c, from, to);
+}
+
#define AVC_DEBUG_READ_DESCRIPTOR 0x0001
#define AVC_DEBUG_DSIT 0x0002
#define AVC_DEBUG_DSD 0x0004
@@ -202,78 +215,65 @@ static void debug_pmt(char *msg, int length)
16, 1, msg, length, false);
}
-static int __avc_write(struct firedtv *fdtv,
- const struct avc_command_frame *c, struct avc_response_frame *r)
+static int avc_write(struct firedtv *fdtv)
{
int err, retry;
- if (r)
- fdtv->avc_reply_received = false;
+ fdtv->avc_reply_received = false;
for (retry = 0; retry < 6; retry++) {
if (unlikely(avc_debug))
- debug_fcp(&c->ctype, c->length);
+ debug_fcp(fdtv->avc_data, fdtv->avc_data_length);
err = fdtv->backend->write(fdtv, FCP_COMMAND_REGISTER,
- (void *)&c->ctype, c->length);
+ fdtv->avc_data, fdtv->avc_data_length);
if (err) {
- fdtv->avc_reply_received = true;
dev_err(fdtv->device, "FCP command write failed\n");
+
return err;
}
- if (!r)
- return 0;
-
/*
* AV/C specs say that answers should be sent within 150 ms.
* Time out after 200 ms.
*/
if (wait_event_timeout(fdtv->avc_wait,
fdtv->avc_reply_received,
- msecs_to_jiffies(200)) != 0) {
- r->length = fdtv->response_length;
- memcpy(&r->response, fdtv->response, r->length);
-
+ msecs_to_jiffies(200)) != 0)
return 0;
- }
}
dev_err(fdtv->device, "FCP response timed out\n");
+
return -ETIMEDOUT;
}
-static int avc_write(struct firedtv *fdtv,
- const struct avc_command_frame *c, struct avc_response_frame *r)
+static bool is_register_rc(struct avc_response_frame *r)
{
- int ret;
-
- if (mutex_lock_interruptible(&fdtv->avc_mutex))
- return -EINTR;
-
- ret = __avc_write(fdtv, c, r);
-
- mutex_unlock(&fdtv->avc_mutex);
- return ret;
+ return r->opcode == AVC_OPCODE_VENDOR &&
+ r->operand[0] == SFE_VENDOR_DE_COMPANYID_0 &&
+ r->operand[1] == SFE_VENDOR_DE_COMPANYID_1 &&
+ r->operand[2] == SFE_VENDOR_DE_COMPANYID_2 &&
+ r->operand[3] == SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL;
}
int avc_recv(struct firedtv *fdtv, void *data, size_t length)
{
- struct avc_response_frame *r =
- data - offsetof(struct avc_response_frame, response);
+ struct avc_response_frame *r = data;
if (unlikely(avc_debug))
debug_fcp(data, length);
- if (length >= 8 &&
- r->operand[0] == SFE_VENDOR_DE_COMPANYID_0 &&
- r->operand[1] == SFE_VENDOR_DE_COMPANYID_1 &&
- r->operand[2] == SFE_VENDOR_DE_COMPANYID_2 &&
- r->operand[3] == SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL) {
- if (r->response == AVC_RESPONSE_CHANGED) {
- fdtv_handle_rc(fdtv,
- r->operand[4] << 8 | r->operand[5]);
+ if (length >= 8 && is_register_rc(r)) {
+ switch (r->response) {
+ case AVC_RESPONSE_CHANGED:
+ fdtv_handle_rc(fdtv, r->operand[4] << 8 | r->operand[5]);
schedule_work(&fdtv->remote_ctrl_work);
- } else if (r->response != AVC_RESPONSE_INTERIM) {
+ break;
+ case AVC_RESPONSE_INTERIM:
+ if (is_register_rc((void *)fdtv->avc_data))
+ goto wake;
+ break;
+ default:
dev_info(fdtv->device,
"remote control result = %d\n", r->response);
}
@@ -285,9 +285,9 @@ int avc_recv(struct firedtv *fdtv, void *data, size_t length)
return -EIO;
}
- memcpy(fdtv->response, data, length);
- fdtv->response_length = length;
-
+ memcpy(fdtv->avc_data, data, length);
+ fdtv->avc_data_length = length;
+wake:
fdtv->avc_reply_received = true;
wake_up(&fdtv->avc_wait);
@@ -318,10 +318,11 @@ static int add_pid_filter(struct firedtv *fdtv, u8 *operand)
* tuning command for setting the relative LNB frequency
* (not supported by the AVC standard)
*/
-static void avc_tuner_tuneqpsk(struct firedtv *fdtv,
- struct dvb_frontend_parameters *params,
- struct avc_command_frame *c)
+static int avc_tuner_tuneqpsk(struct firedtv *fdtv,
+ struct dvb_frontend_parameters *params)
{
+ struct avc_command_frame *c = (void *)fdtv->avc_data;
+
c->opcode = AVC_OPCODE_VENDOR;
c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
@@ -370,16 +371,18 @@ static void avc_tuner_tuneqpsk(struct firedtv *fdtv,
c->operand[13] = 0x1;
c->operand[14] = 0xff;
c->operand[15] = 0xff;
- c->length = 20;
+
+ return 16;
} else {
- c->length = 16;
+ return 13;
}
}
-static void avc_tuner_dsd_dvb_c(struct firedtv *fdtv,
- struct dvb_frontend_parameters *params,
- struct avc_command_frame *c)
+static int avc_tuner_dsd_dvb_c(struct firedtv *fdtv,
+ struct dvb_frontend_parameters *params)
{
+ struct avc_command_frame *c = (void *)fdtv->avc_data;
+
c->opcode = AVC_OPCODE_DSD;
c->operand[0] = 0; /* source plug */
@@ -440,15 +443,14 @@ static void avc_tuner_dsd_dvb_c(struct firedtv *fdtv,
c->operand[20] = 0x00;
c->operand[21] = 0x00;
- /* Add PIDs to filter */
- c->length = ALIGN(22 + add_pid_filter(fdtv, &c->operand[22]) + 3, 4);
+ return 22 + add_pid_filter(fdtv, &c->operand[22]);
}
-static void avc_tuner_dsd_dvb_t(struct firedtv *fdtv,
- struct dvb_frontend_parameters *params,
- struct avc_command_frame *c)
+static int avc_tuner_dsd_dvb_t(struct firedtv *fdtv,
+ struct dvb_frontend_parameters *params)
{
struct dvb_ofdm_parameters *ofdm = &params->u.ofdm;
+ struct avc_command_frame *c = (void *)fdtv->avc_data;
c->opcode = AVC_OPCODE_DSD;
@@ -543,55 +545,58 @@ static void avc_tuner_dsd_dvb_t(struct firedtv *fdtv,
c->operand[15] = 0x00; /* network_ID[0] */
c->operand[16] = 0x00; /* network_ID[1] */
- /* Add PIDs to filter */
- c->length = ALIGN(17 + add_pid_filter(fdtv, &c->operand[17]) + 3, 4);
+ return 17 + add_pid_filter(fdtv, &c->operand[17]);
}
int avc_tuner_dsd(struct firedtv *fdtv,
struct dvb_frontend_parameters *params)
{
- char buffer[sizeof(struct avc_command_frame)];
- struct avc_command_frame *c = (void *)buffer;
- struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */
+ struct avc_command_frame *c = (void *)fdtv->avc_data;
+ int pos, ret;
- memset(c, 0, sizeof(*c));
+ mutex_lock(&fdtv->avc_mutex);
c->ctype = AVC_CTYPE_CONTROL;
c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
switch (fdtv->type) {
case FIREDTV_DVB_S:
- case FIREDTV_DVB_S2: avc_tuner_tuneqpsk(fdtv, params, c); break;
- case FIREDTV_DVB_C: avc_tuner_dsd_dvb_c(fdtv, params, c); break;
- case FIREDTV_DVB_T: avc_tuner_dsd_dvb_t(fdtv, params, c); break;
+ case FIREDTV_DVB_S2: pos = avc_tuner_tuneqpsk(fdtv, params); break;
+ case FIREDTV_DVB_C: pos = avc_tuner_dsd_dvb_c(fdtv, params); break;
+ case FIREDTV_DVB_T: pos = avc_tuner_dsd_dvb_t(fdtv, params); break;
default:
BUG();
}
+ pad_operands(c, pos);
- if (avc_write(fdtv, c, r) < 0)
- return -EIO;
-
- msleep(500);
+ fdtv->avc_data_length = ALIGN(3 + pos, 4);
+ ret = avc_write(fdtv);
#if 0
- /* FIXME: */
- /* u8 *status was an out-parameter of avc_tuner_dsd, unused by caller */
+ /*
+ * FIXME:
+ * u8 *status was an out-parameter of avc_tuner_dsd, unused by caller.
+ * Check for AVC_RESPONSE_ACCEPTED here instead?
+ */
if (status)
*status = r->operand[2];
#endif
- return 0;
+ mutex_unlock(&fdtv->avc_mutex);
+
+ if (ret == 0)
+ msleep(500);
+
+ return ret;
}
int avc_tuner_set_pids(struct firedtv *fdtv, unsigned char pidc, u16 pid[])
{
- char buffer[sizeof(struct avc_command_frame)];
- struct avc_command_frame *c = (void *)buffer;
- struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */
- int pos, k;
+ struct avc_command_frame *c = (void *)fdtv->avc_data;
+ int ret, pos, k;
if (pidc > 16 && pidc != 0xff)
return -EINVAL;
- memset(c, 0, sizeof(*c));
+ mutex_lock(&fdtv->avc_mutex);
c->ctype = AVC_CTYPE_CONTROL;
c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
@@ -614,24 +619,27 @@ int avc_tuner_set_pids(struct firedtv *fdtv, unsigned char pidc, u16 pid[])
c->operand[pos++] = 0x00; /* tableID */
c->operand[pos++] = 0x00; /* filter_length */
}
+ pad_operands(c, pos);
- c->length = ALIGN(3 + pos, 4);
+ fdtv->avc_data_length = ALIGN(3 + pos, 4);
+ ret = avc_write(fdtv);
- if (avc_write(fdtv, c, r) < 0)
- return -EIO;
+ /* FIXME: check response code? */
- msleep(50);
- return 0;
+ mutex_unlock(&fdtv->avc_mutex);
+
+ if (ret == 0)
+ msleep(50);
+
+ return ret;
}
int avc_tuner_get_ts(struct firedtv *fdtv)
{
- char buffer[sizeof(struct avc_command_frame)];
- struct avc_command_frame *c = (void *)buffer;
- struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */
- int sl;
+ struct avc_command_frame *c = (void *)fdtv->avc_data;
+ int ret, sl;
- memset(c, 0, sizeof(*c));
+ mutex_lock(&fdtv->avc_mutex);
c->ctype = AVC_CTYPE_CONTROL;
c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
@@ -646,26 +654,33 @@ int avc_tuner_get_ts(struct firedtv *fdtv)
c->operand[4] = 0x00; /* antenna number */
c->operand[5] = 0x0; /* system_specific_search_flags */
c->operand[6] = sl; /* system_specific_multiplex selection_length */
- c->operand[7] = 0x00; /* valid_flags [0] */
- c->operand[8] = 0x00; /* valid_flags [1] */
- c->operand[7 + sl] = 0x00; /* nr_of_dsit_sel_specs (always 0) */
+ /*
+ * operand[7]: valid_flags[0]
+ * operand[8]: valid_flags[1]
+ * operand[7 + sl]: nr_of_dsit_sel_specs (always 0)
+ */
+ clear_operands(c, 7, 24);
- c->length = fdtv->type == FIREDTV_DVB_T ? 24 : 28;
+ fdtv->avc_data_length = fdtv->type == FIREDTV_DVB_T ? 24 : 28;
+ ret = avc_write(fdtv);
- if (avc_write(fdtv, c, r) < 0)
- return -EIO;
+ /* FIXME: check response code? */
- msleep(250);
- return 0;
+ mutex_unlock(&fdtv->avc_mutex);
+
+ if (ret == 0)
+ msleep(250);
+
+ return ret;
}
int avc_identify_subunit(struct firedtv *fdtv)
{
- char buffer[sizeof(struct avc_command_frame)];
- struct avc_command_frame *c = (void *)buffer;
- struct avc_response_frame *r = (void *)buffer;
+ struct avc_command_frame *c = (void *)fdtv->avc_data;
+ struct avc_response_frame *r = (void *)fdtv->avc_data;
+ int ret;
- memset(c, 0, sizeof(*c));
+ mutex_lock(&fdtv->avc_mutex);
c->ctype = AVC_CTYPE_CONTROL;
c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
@@ -678,31 +693,34 @@ int avc_identify_subunit(struct firedtv *fdtv)
c->operand[4] = 0x08; /* length lowbyte */
c->operand[5] = 0x00; /* offset highbyte */
c->operand[6] = 0x0d; /* offset lowbyte */
+ clear_operands(c, 7, 8); /* padding */
- c->length = 12;
-
- if (avc_write(fdtv, c, r) < 0)
- return -EIO;
+ fdtv->avc_data_length = 12;
+ ret = avc_write(fdtv);
+ if (ret < 0)
+ goto out;
if ((r->response != AVC_RESPONSE_STABLE &&
r->response != AVC_RESPONSE_ACCEPTED) ||
(r->operand[3] << 8) + r->operand[4] != 8) {
dev_err(fdtv->device, "cannot read subunit identifier\n");
- return -EINVAL;
+ ret = -EINVAL;
}
- return 0;
+out:
+ mutex_unlock(&fdtv->avc_mutex);
+
+ return ret;
}
#define SIZEOF_ANTENNA_INPUT_INFO 22
int avc_tuner_status(struct firedtv *fdtv, struct firedtv_tuner_status *stat)
{
- char buffer[sizeof(struct avc_command_frame)];
- struct avc_command_frame *c = (void *)buffer;
- struct avc_response_frame *r = (void *)buffer;
- int length;
+ struct avc_command_frame *c = (void *)fdtv->avc_data;
+ struct avc_response_frame *r = (void *)fdtv->avc_data;
+ int length, ret;
- memset(c, 0, sizeof(*c));
+ mutex_lock(&fdtv->avc_mutex);
c->ctype = AVC_CTYPE_CONTROL;
c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
@@ -710,27 +728,30 @@ int avc_tuner_status(struct firedtv *fdtv, struct firedtv_tuner_status *stat)
c->operand[0] = DESCRIPTOR_TUNER_STATUS;
c->operand[1] = 0xff; /* read_result_status */
- c->operand[2] = 0x00; /* reserved */
- c->operand[3] = 0; /* SIZEOF_ANTENNA_INPUT_INFO >> 8; */
- c->operand[4] = 0; /* SIZEOF_ANTENNA_INPUT_INFO & 0xff; */
- c->operand[5] = 0x00;
- c->operand[6] = 0x00;
-
- c->length = 12;
-
- if (avc_write(fdtv, c, r) < 0)
- return -EIO;
+ /*
+ * operand[2]: reserved
+ * operand[3]: SIZEOF_ANTENNA_INPUT_INFO >> 8
+ * operand[4]: SIZEOF_ANTENNA_INPUT_INFO & 0xff
+ */
+ clear_operands(c, 2, 31);
+
+ fdtv->avc_data_length = 12;
+ ret = avc_write(fdtv);
+ if (ret < 0)
+ goto out;
if (r->response != AVC_RESPONSE_STABLE &&
r->response != AVC_RESPONSE_ACCEPTED) {
dev_err(fdtv->device, "cannot read tuner status\n");
- return -EINVAL;
+ ret = -EINVAL;
+ goto out;
}
length = r->operand[9];
if (r->operand[1] != 0x10 || length != SIZEOF_ANTENNA_INPUT_INFO) {
dev_err(fdtv->device, "got invalid tuner status\n");
- return -EINVAL;
+ ret = -EINVAL;
+ goto out;
}
stat->active_system = r->operand[10];
@@ -766,20 +787,21 @@ int avc_tuner_status(struct firedtv *fdtv, struct firedtv_tuner_status *stat)
stat->ca_dvb_flag = r->operand[31] >> 3 & 1;
stat->ca_error_flag = r->operand[31] >> 2 & 1;
stat->ca_initialization_status = r->operand[31] >> 1 & 1;
+out:
+ mutex_unlock(&fdtv->avc_mutex);
- return 0;
+ return ret;
}
int avc_lnb_control(struct firedtv *fdtv, char voltage, char burst,
char conttone, char nrdiseq,
struct dvb_diseqc_master_cmd *diseqcmd)
{
- char buffer[sizeof(struct avc_command_frame)];
- struct avc_command_frame *c = (void *)buffer;
- struct avc_response_frame *r = (void *)buffer;
- int i, j, k;
+ struct avc_command_frame *c = (void *)fdtv->avc_data;
+ struct avc_response_frame *r = (void *)fdtv->avc_data;
+ int pos, j, k, ret;
- memset(c, 0, sizeof(*c));
+ mutex_lock(&fdtv->avc_mutex);
c->ctype = AVC_CTYPE_CONTROL;
c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
@@ -789,41 +811,41 @@ int avc_lnb_control(struct firedtv *fdtv, char voltage, char burst,
c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
c->operand[3] = SFE_VENDOR_OPCODE_LNB_CONTROL;
-
c->operand[4] = voltage;
c->operand[5] = nrdiseq;
- i = 6;
-
+ pos = 6;
for (j = 0; j < nrdiseq; j++) {
- c->operand[i++] = diseqcmd[j].msg_len;
+ c->operand[pos++] = diseqcmd[j].msg_len;
for (k = 0; k < diseqcmd[j].msg_len; k++)
- c->operand[i++] = diseqcmd[j].msg[k];
+ c->operand[pos++] = diseqcmd[j].msg[k];
}
+ c->operand[pos++] = burst;
+ c->operand[pos++] = conttone;
+ pad_operands(c, pos);
- c->operand[i++] = burst;
- c->operand[i++] = conttone;
-
- c->length = ALIGN(3 + i, 4);
-
- if (avc_write(fdtv, c, r) < 0)
- return -EIO;
+ fdtv->avc_data_length = ALIGN(3 + pos, 4);
+ ret = avc_write(fdtv);
+ if (ret < 0)
+ goto out;
if (r->response != AVC_RESPONSE_ACCEPTED) {
dev_err(fdtv->device, "LNB control failed\n");
- return -EINVAL;
+ ret = -EINVAL;
}
+out:
+ mutex_unlock(&fdtv->avc_mutex);
- return 0;
+ return ret;
}
int avc_register_remote_control(struct firedtv *fdtv)
{
- char buffer[sizeof(struct avc_command_frame)];
- struct avc_command_frame *c = (void *)buffer;
+ struct avc_command_frame *c = (void *)fdtv->avc_data;
+ int ret;
- memset(c, 0, sizeof(*c));
+ mutex_lock(&fdtv->avc_mutex);
c->ctype = AVC_CTYPE_NOTIFY;
c->subunit = AVC_SUBUNIT_TYPE_UNIT | 7;
@@ -833,10 +855,16 @@ int avc_register_remote_control(struct firedtv *fdtv)
c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
c->operand[3] = SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL;
+ c->operand[4] = 0; /* padding */
+
+ fdtv->avc_data_length = 8;
+ ret = avc_write(fdtv);
- c->length = 8;
+ /* FIXME: check response code? */
- return avc_write(fdtv, c, NULL);
+ mutex_unlock(&fdtv->avc_mutex);
+
+ return ret;
}
void avc_remote_ctrl_work(struct work_struct *work)
@@ -851,11 +879,10 @@ void avc_remote_ctrl_work(struct work_struct *work)
#if 0 /* FIXME: unused */
int avc_tuner_host2ca(struct firedtv *fdtv)
{
- char buffer[sizeof(struct avc_command_frame)];
- struct avc_command_frame *c = (void *)buffer;
- struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */
+ struct avc_command_frame *c = (void *)fdtv->avc_data;
+ int ret;
- memset(c, 0, sizeof(*c));
+ mutex_lock(&fdtv->avc_mutex);
c->ctype = AVC_CTYPE_CONTROL;
c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
@@ -867,15 +894,16 @@ int avc_tuner_host2ca(struct firedtv *fdtv)
c->operand[3] = SFE_VENDOR_OPCODE_HOST2CA;
c->operand[4] = 0; /* slot */
c->operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; /* ca tag */
- c->operand[6] = 0; /* more/last */
- c->operand[7] = 0; /* length */
+ clear_operands(c, 6, 8);
- c->length = 12;
+ fdtv->avc_data_length = 12;
+ ret = avc_write(fdtv);
- if (avc_write(fdtv, c, r) < 0)
- return -EIO;
+ /* FIXME: check response code? */
- return 0;
+ mutex_unlock(&fdtv->avc_mutex);
+
+ return ret;
}
#endif
@@ -906,12 +934,11 @@ static int get_ca_object_length(struct avc_response_frame *r)
int avc_ca_app_info(struct firedtv *fdtv, char *app_info, unsigned int *len)
{
- char buffer[sizeof(struct avc_command_frame)];
- struct avc_command_frame *c = (void *)buffer;
- struct avc_response_frame *r = (void *)buffer;
- int pos;
+ struct avc_command_frame *c = (void *)fdtv->avc_data;
+ struct avc_response_frame *r = (void *)fdtv->avc_data;
+ int pos, ret;
- memset(c, 0, sizeof(*c));
+ mutex_lock(&fdtv->avc_mutex);
c->ctype = AVC_CTYPE_STATUS;
c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
@@ -923,11 +950,12 @@ int avc_ca_app_info(struct firedtv *fdtv, char *app_info, unsigned int *len)
c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST;
c->operand[4] = 0; /* slot */
c->operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; /* ca tag */
+ clear_operands(c, 6, LAST_OPERAND);
- c->length = 12;
-
- if (avc_write(fdtv, c, r) < 0)
- return -EIO;
+ fdtv->avc_data_length = 12;
+ ret = avc_write(fdtv);
+ if (ret < 0)
+ goto out;
/* FIXME: check response code and validate response data */
@@ -939,18 +967,19 @@ int avc_ca_app_info(struct firedtv *fdtv, char *app_info, unsigned int *len)
app_info[4] = 0x01;
memcpy(&app_info[5], &r->operand[pos], 5 + r->operand[pos + 4]);
*len = app_info[3] + 4;
+out:
+ mutex_unlock(&fdtv->avc_mutex);
- return 0;
+ return ret;
}
int avc_ca_info(struct firedtv *fdtv, char *app_info, unsigned int *len)
{
- char buffer[sizeof(struct avc_command_frame)];
- struct avc_command_frame *c = (void *)buffer;
- struct avc_response_frame *r = (void *)buffer;
- int pos;
+ struct avc_command_frame *c = (void *)fdtv->avc_data;
+ struct avc_response_frame *r = (void *)fdtv->avc_data;
+ int pos, ret;
- memset(c, 0, sizeof(*c));
+ mutex_lock(&fdtv->avc_mutex);
c->ctype = AVC_CTYPE_STATUS;
c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
@@ -962,11 +991,14 @@ int avc_ca_info(struct firedtv *fdtv, char *app_info, unsigned int *len)
c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST;
c->operand[4] = 0; /* slot */
c->operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; /* ca tag */
+ clear_operands(c, 6, LAST_OPERAND);
- c->length = 12;
+ fdtv->avc_data_length = 12;
+ ret = avc_write(fdtv);
+ if (ret < 0)
+ goto out;
- if (avc_write(fdtv, c, r) < 0)
- return -EIO;
+ /* FIXME: check response code and validate response data */
pos = get_ca_object_pos(r);
app_info[0] = (EN50221_TAG_CA_INFO >> 16) & 0xff;
@@ -976,17 +1008,18 @@ int avc_ca_info(struct firedtv *fdtv, char *app_info, unsigned int *len)
app_info[4] = r->operand[pos + 0];
app_info[5] = r->operand[pos + 1];
*len = app_info[3] + 4;
+out:
+ mutex_unlock(&fdtv->avc_mutex);
- return 0;
+ return ret;
}
int avc_ca_reset(struct firedtv *fdtv)
{
- char buffer[sizeof(struct avc_command_frame)];
- struct avc_command_frame *c = (void *)buffer;
- struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */
+ struct avc_command_frame *c = (void *)fdtv->avc_data;
+ int ret;
- memset(c, 0, sizeof(*c));
+ mutex_lock(&fdtv->avc_mutex);
c->ctype = AVC_CTYPE_CONTROL;
c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
@@ -1002,19 +1035,20 @@ int avc_ca_reset(struct firedtv *fdtv)
c->operand[7] = 1; /* length */
c->operand[8] = 0; /* force hardware reset */
- c->length = 12;
+ fdtv->avc_data_length = 12;
+ ret = avc_write(fdtv);
- if (avc_write(fdtv, c, r) < 0)
- return -EIO;
+ /* FIXME: check response code? */
- return 0;
+ mutex_unlock(&fdtv->avc_mutex);
+
+ return ret;
}
int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length)
{
- char buffer[sizeof(struct avc_command_frame)];
- struct avc_command_frame *c = (void *)buffer;
- struct avc_response_frame *r = (void *)buffer;
+ struct avc_command_frame *c = (void *)fdtv->avc_data;
+ struct avc_response_frame *r = (void *)fdtv->avc_data;
int list_management;
int program_info_length;
int pmt_cmd_id;
@@ -1022,11 +1056,12 @@ int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length)
int write_pos;
int es_info_length;
int crc32_csum;
+ int ret;
if (unlikely(avc_debug & AVC_DEBUG_APPLICATION_PMT))
debug_pmt(msg, length);
- memset(c, 0, sizeof(*c));
+ mutex_lock(&fdtv->avc_mutex);
c->ctype = AVC_CTYPE_CONTROL;
c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
@@ -1058,7 +1093,7 @@ int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length)
c->operand[12] = 0x02; /* Table id=2 */
c->operand[13] = 0x80; /* Section syntax + length */
- /* c->operand[14] = XXXprogram_info_length + 12; */
+
c->operand[15] = msg[1]; /* Program number */
c->operand[16] = msg[2];
c->operand[17] = 0x01; /* Version number=0 + current/next=1 */
@@ -1106,12 +1141,7 @@ int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length)
write_pos += es_info_length;
}
}
-
- /* CRC */
- c->operand[write_pos++] = 0x00;
- c->operand[write_pos++] = 0x00;
- c->operand[write_pos++] = 0x00;
- c->operand[write_pos++] = 0x00;
+ write_pos += 4; /* CRC */
c->operand[7] = 0x82;
c->operand[8] = (write_pos - 10) >> 8;
@@ -1123,28 +1153,31 @@ int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length)
c->operand[write_pos - 3] = (crc32_csum >> 16) & 0xff;
c->operand[write_pos - 2] = (crc32_csum >> 8) & 0xff;
c->operand[write_pos - 1] = (crc32_csum >> 0) & 0xff;
+ pad_operands(c, write_pos);
- c->length = ALIGN(3 + write_pos, 4);
-
- if (avc_write(fdtv, c, r) < 0)
- return -EIO;
+ fdtv->avc_data_length = ALIGN(3 + write_pos, 4);
+ ret = avc_write(fdtv);
+ if (ret < 0)
+ goto out;
if (r->response != AVC_RESPONSE_ACCEPTED) {
dev_err(fdtv->device,
"CA PMT failed with response 0x%x\n", r->response);
- return -EFAULT;
+ ret = -EFAULT;
}
+out:
+ mutex_unlock(&fdtv->avc_mutex);
- return 0;
+ return ret;
}
int avc_ca_get_time_date(struct firedtv *fdtv, int *interval)
{
- char buffer[sizeof(struct avc_command_frame)];
- struct avc_command_frame *c = (void *)buffer;
- struct avc_response_frame *r = (void *)buffer;
+ struct avc_command_frame *c = (void *)fdtv->avc_data;
+ struct avc_response_frame *r = (void *)fdtv->avc_data;
+ int ret;
- memset(c, 0, sizeof(*c));
+ mutex_lock(&fdtv->avc_mutex);
c->ctype = AVC_CTYPE_STATUS;
c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
@@ -1156,28 +1189,28 @@ int avc_ca_get_time_date(struct firedtv *fdtv, int *interval)
c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST;
c->operand[4] = 0; /* slot */
c->operand[5] = SFE_VENDOR_TAG_CA_DATE_TIME; /* ca tag */
- c->operand[6] = 0; /* more/last */
- c->operand[7] = 0; /* length */
+ clear_operands(c, 6, LAST_OPERAND);
- c->length = 12;
-
- if (avc_write(fdtv, c, r) < 0)
- return -EIO;
+ fdtv->avc_data_length = 12;
+ ret = avc_write(fdtv);
+ if (ret < 0)
+ goto out;
/* FIXME: check response code and validate response data */
*interval = r->operand[get_ca_object_pos(r)];
+out:
+ mutex_unlock(&fdtv->avc_mutex);
- return 0;
+ return ret;
}
int avc_ca_enter_menu(struct firedtv *fdtv)
{
- char buffer[sizeof(struct avc_command_frame)];
- struct avc_command_frame *c = (void *)buffer;
- struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */
+ struct avc_command_frame *c = (void *)fdtv->avc_data;
+ int ret;
- memset(c, 0, sizeof(*c));
+ mutex_lock(&fdtv->avc_mutex);
c->ctype = AVC_CTYPE_STATUS;
c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
@@ -1189,24 +1222,25 @@ int avc_ca_enter_menu(struct firedtv *fdtv)
c->operand[3] = SFE_VENDOR_OPCODE_HOST2CA;
c->operand[4] = 0; /* slot */
c->operand[5] = SFE_VENDOR_TAG_CA_ENTER_MENU;
- c->operand[6] = 0; /* more/last */
- c->operand[7] = 0; /* length */
+ clear_operands(c, 6, 8);
- c->length = 12;
+ fdtv->avc_data_length = 12;
+ ret = avc_write(fdtv);
- if (avc_write(fdtv, c, r) < 0)
- return -EIO;
+ /* FIXME: check response code? */
- return 0;
+ mutex_unlock(&fdtv->avc_mutex);
+
+ return ret;
}
int avc_ca_get_mmi(struct firedtv *fdtv, char *mmi_object, unsigned int *len)
{
- char buffer[sizeof(struct avc_command_frame)];
- struct avc_command_frame *c = (void *)buffer;
- struct avc_response_frame *r = (void *)buffer;
+ struct avc_command_frame *c = (void *)fdtv->avc_data;
+ struct avc_response_frame *r = (void *)fdtv->avc_data;
+ int ret;
- memset(c, 0, sizeof(*c));
+ mutex_lock(&fdtv->avc_mutex);
c->ctype = AVC_CTYPE_STATUS;
c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
@@ -1218,20 +1252,21 @@ int avc_ca_get_mmi(struct firedtv *fdtv, char *mmi_object, unsigned int *len)
c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST;
c->operand[4] = 0; /* slot */
c->operand[5] = SFE_VENDOR_TAG_CA_MMI;
- c->operand[6] = 0; /* more/last */
- c->operand[7] = 0; /* length */
+ clear_operands(c, 6, LAST_OPERAND);
- c->length = 12;
-
- if (avc_write(fdtv, c, r) < 0)
- return -EIO;
+ fdtv->avc_data_length = 12;
+ ret = avc_write(fdtv);
+ if (ret < 0)
+ goto out;
/* FIXME: check response code and validate response data */
*len = get_ca_object_length(r);
memcpy(mmi_object, &r->operand[get_ca_object_pos(r)], *len);
+out:
+ mutex_unlock(&fdtv->avc_mutex);
- return 0;
+ return ret;
}
#define CMP_OUTPUT_PLUG_CONTROL_REG_0 0xfffff0000904ULL
@@ -1240,14 +1275,14 @@ static int cmp_read(struct firedtv *fdtv, u64 addr, __be32 *data)
{
int ret;
- if (mutex_lock_interruptible(&fdtv->avc_mutex))
- return -EINTR;
+ mutex_lock(&fdtv->avc_mutex);
ret = fdtv->backend->read(fdtv, addr, data);
if (ret < 0)
dev_err(fdtv->device, "CMP: read I/O error\n");
mutex_unlock(&fdtv->avc_mutex);
+
return ret;
}
@@ -1255,14 +1290,19 @@ static int cmp_lock(struct firedtv *fdtv, u64 addr, __be32 data[])
{
int ret;
- if (mutex_lock_interruptible(&fdtv->avc_mutex))
- return -EINTR;
+ mutex_lock(&fdtv->avc_mutex);
+
+ /* data[] is stack-allocated and should not be DMA-mapped. */
+ memcpy(fdtv->avc_data, data, 8);
- ret = fdtv->backend->lock(fdtv, addr, data);
+ ret = fdtv->backend->lock(fdtv, addr, fdtv->avc_data);
if (ret < 0)
dev_err(fdtv->device, "CMP: lock I/O error\n");
+ else
+ memcpy(data, fdtv->avc_data, 8);
mutex_unlock(&fdtv->avc_mutex);
+
return ret;
}
diff --git a/drivers/media/dvb/firewire/firedtv-dvb.c b/drivers/media/dvb/firewire/firedtv-dvb.c
index fc9996c13e13..079e8c5b0475 100644
--- a/drivers/media/dvb/firewire/firedtv-dvb.c
+++ b/drivers/media/dvb/firewire/firedtv-dvb.c
@@ -277,7 +277,6 @@ struct firedtv *fdtv_alloc(struct device *dev,
mutex_init(&fdtv->avc_mutex);
init_waitqueue_head(&fdtv->avc_wait);
- fdtv->avc_reply_received = true;
mutex_init(&fdtv->demux_mutex);
INIT_WORK(&fdtv->remote_ctrl_work, avc_remote_ctrl_work);
diff --git a/drivers/media/dvb/firewire/firedtv-fw.c b/drivers/media/dvb/firewire/firedtv-fw.c
index 6223bf01efe9..7a3de16fba06 100644
--- a/drivers/media/dvb/firewire/firedtv-fw.c
+++ b/drivers/media/dvb/firewire/firedtv-fw.c
@@ -41,7 +41,7 @@ static int node_req(struct firedtv *fdtv, u64 addr, void *data, size_t len,
return rcode != RCODE_COMPLETE ? -EIO : 0;
}
-static int node_lock(struct firedtv *fdtv, u64 addr, __be32 data[])
+static int node_lock(struct firedtv *fdtv, u64 addr, void *data)
{
return node_req(fdtv, addr, data, 8, TCODE_LOCK_COMPARE_SWAP);
}
diff --git a/drivers/media/dvb/firewire/firedtv.h b/drivers/media/dvb/firewire/firedtv.h
index 35080dbb3c66..78cc28f36914 100644
--- a/drivers/media/dvb/firewire/firedtv.h
+++ b/drivers/media/dvb/firewire/firedtv.h
@@ -73,7 +73,7 @@ struct input_dev;
struct firedtv;
struct firedtv_backend {
- int (*lock)(struct firedtv *fdtv, u64 addr, __be32 data[]);
+ int (*lock)(struct firedtv *fdtv, u64 addr, void *data);
int (*read)(struct firedtv *fdtv, u64 addr, void *data);
int (*write)(struct firedtv *fdtv, u64 addr, void *data, size_t len);
int (*start_iso)(struct firedtv *fdtv);
@@ -114,8 +114,8 @@ struct firedtv {
unsigned long channel_active;
u16 channel_pid[16];
- size_t response_length;
- u8 response[512];
+ int avc_data_length;
+ u8 avc_data[512];
};
/* firedtv-1394.c */
diff --git a/drivers/media/dvb/frontends/af9013.h b/drivers/media/dvb/frontends/af9013.h
index 28b90c91c766..e90fa92b1c1d 100644
--- a/drivers/media/dvb/frontends/af9013.h
+++ b/drivers/media/dvb/frontends/af9013.h
@@ -44,6 +44,7 @@ enum af9013_tuner {
AF9013_TUNER_MT2060_2 = 147, /* Microtune */
AF9013_TUNER_TDA18271 = 156, /* NXP */
AF9013_TUNER_QT1010A = 162, /* Quantek */
+ AF9013_TUNER_TDA18218 = 179, /* NXP */
};
/* AF9013/5 GPIOs (mostly guessed)
diff --git a/drivers/media/dvb/frontends/atbm8830.c b/drivers/media/dvb/frontends/atbm8830.c
index 59881a5944eb..43aac2f85c2e 100644
--- a/drivers/media/dvb/frontends/atbm8830.c
+++ b/drivers/media/dvb/frontends/atbm8830.c
@@ -170,6 +170,19 @@ static int is_locked(struct atbm_state *priv, u8 *locked)
return 0;
}
+static int set_agc_config(struct atbm_state *priv,
+ u8 min, u8 max, u8 hold_loop)
+{
+ /* no effect if both min and max are zero */
+ if (!min && !max)
+ return 0;
+
+ atbm8830_write_reg(priv, REG_AGC_MIN, min);
+ atbm8830_write_reg(priv, REG_AGC_MAX, max);
+ atbm8830_write_reg(priv, REG_AGC_HOLD_LOOP, hold_loop);
+
+ return 0;
+}
static int set_static_channel_mode(struct atbm_state *priv)
{
@@ -227,6 +240,9 @@ static int atbm8830_init(struct dvb_frontend *fe)
/*Set IF frequency*/
set_if_freq(priv, cfg->if_freq);
+ /*Set AGC Config*/
+ set_agc_config(priv, cfg->agc_min, cfg->agc_max,
+ cfg->agc_hold_loop);
/*Set static channel mode*/
set_static_channel_mode(priv);
diff --git a/drivers/media/dvb/frontends/dib0090.c b/drivers/media/dvb/frontends/dib0090.c
index 614552709a6f..7eac178f57b2 100644
--- a/drivers/media/dvb/frontends/dib0090.c
+++ b/drivers/media/dvb/frontends/dib0090.c
@@ -283,7 +283,7 @@ static int dib0090_sleep(struct dvb_frontend *fe)
return 0;
}
-extern void dib0090_dcc_freq(struct dvb_frontend *fe, u8 fast)
+void dib0090_dcc_freq(struct dvb_frontend *fe, u8 fast)
{
struct dib0090_state *state = fe->tuner_priv;
if (fast)
diff --git a/drivers/media/dvb/frontends/dib8000.c b/drivers/media/dvb/frontends/dib8000.c
index 6f6fa29d9ea4..2aa97dd6a8af 100644
--- a/drivers/media/dvb/frontends/dib8000.c
+++ b/drivers/media/dvb/frontends/dib8000.c
@@ -1999,6 +1999,8 @@ static int dib8000_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_par
struct dib8000_state *state = fe->demodulator_priv;
int time, ret;
+ fe->dtv_property_cache.delivery_system = SYS_ISDBT;
+
dib8000_set_output_mode(state, OUTMODE_HIGH_Z);
if (fe->ops.tuner_ops.set_params)
diff --git a/drivers/media/dvb/frontends/dibx000_common.c b/drivers/media/dvb/frontends/dibx000_common.c
index e6f3d73db9d3..980e02f1575e 100644
--- a/drivers/media/dvb/frontends/dibx000_common.c
+++ b/drivers/media/dvb/frontends/dibx000_common.c
@@ -174,7 +174,7 @@ void dibx000_exit_i2c_master(struct dibx000_i2c_master *mst)
EXPORT_SYMBOL(dibx000_exit_i2c_master);
-u32 systime()
+u32 systime(void)
{
struct timespec t;
diff --git a/drivers/media/dvb/frontends/lnbp21.c b/drivers/media/dvb/frontends/lnbp21.c
index b181bf023ada..13437259eeac 100644
--- a/drivers/media/dvb/frontends/lnbp21.c
+++ b/drivers/media/dvb/frontends/lnbp21.c
@@ -158,7 +158,8 @@ static struct dvb_frontend *lnbx2x_attach(struct dvb_frontend *fe,
/* override frontend ops */
fe->ops.set_voltage = lnbp21_set_voltage;
fe->ops.enable_high_lnb_voltage = lnbp21_enable_high_lnb_voltage;
- fe->ops.set_tone = lnbp21_set_tone;
+ if (!(override_clear & LNBH24_TEN)) /*22kHz logic controlled by demod*/
+ fe->ops.set_tone = lnbp21_set_tone;
printk(KERN_INFO "LNBx2x attached on addr=%x\n", lnbp21->i2c_addr);
return fe;
diff --git a/drivers/media/dvb/frontends/si21xx.c b/drivers/media/dvb/frontends/si21xx.c
index 9552a22ccffb..d21a327db629 100644
--- a/drivers/media/dvb/frontends/si21xx.c
+++ b/drivers/media/dvb/frontends/si21xx.c
@@ -97,8 +97,6 @@
#define LNB_SUPPLY_CTRL_REG_4 0xce
#define LNB_SUPPLY_STATUS_REG 0xcf
-#define FALSE 0
-#define TRUE 1
#define FAIL -1
#define PASS 0
@@ -718,7 +716,7 @@ static int si21xx_set_frontend(struct dvb_frontend *fe,
int fine_tune_freq;
unsigned char sample_rate = 0;
/* boolean */
- unsigned int inband_interferer_ind;
+ bool inband_interferer_ind;
/* INTERMEDIATE VALUES */
int icoarse_tune_freq; /* MHz */
@@ -728,15 +726,8 @@ static int si21xx_set_frontend(struct dvb_frontend *fe,
unsigned int x1;
unsigned int x2;
int i;
- unsigned int inband_interferer_div2[ALLOWABLE_FS_COUNT] = {
- FALSE, FALSE, FALSE, FALSE, FALSE,
- FALSE, FALSE, FALSE, FALSE, FALSE
- };
- unsigned int inband_interferer_div4[ALLOWABLE_FS_COUNT] = {
- FALSE, FALSE, FALSE, FALSE, FALSE,
- FALSE, FALSE, FALSE, FALSE, FALSE
- };
-
+ bool inband_interferer_div2[ALLOWABLE_FS_COUNT];
+ bool inband_interferer_div4[ALLOWABLE_FS_COUNT];
int status;
/* allowable sample rates for ADC in MHz */
@@ -762,7 +753,7 @@ static int si21xx_set_frontend(struct dvb_frontend *fe,
}
for (i = 0; i < ALLOWABLE_FS_COUNT; ++i)
- inband_interferer_div2[i] = inband_interferer_div4[i] = FALSE;
+ inband_interferer_div2[i] = inband_interferer_div4[i] = false;
if_limit_high = -700000;
if_limit_low = -100000;
@@ -798,7 +789,7 @@ static int si21xx_set_frontend(struct dvb_frontend *fe,
if (((band_low < x1) && (x1 < band_high)) ||
((band_low < x2) && (x2 < band_high)))
- inband_interferer_div4[i] = TRUE;
+ inband_interferer_div4[i] = true;
}
@@ -811,25 +802,28 @@ static int si21xx_set_frontend(struct dvb_frontend *fe,
if (((band_low < x1) && (x1 < band_high)) ||
((band_low < x2) && (x2 < band_high)))
- inband_interferer_div2[i] = TRUE;
+ inband_interferer_div2[i] = true;
}
- inband_interferer_ind = TRUE;
- for (i = 0; i < ALLOWABLE_FS_COUNT; ++i)
- inband_interferer_ind &= inband_interferer_div2[i] |
- inband_interferer_div4[i];
+ inband_interferer_ind = true;
+ for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) {
+ if (inband_interferer_div2[i] || inband_interferer_div4[i]) {
+ inband_interferer_ind = false;
+ break;
+ }
+ }
if (inband_interferer_ind) {
for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) {
- if (inband_interferer_div2[i] == FALSE) {
+ if (!inband_interferer_div2[i]) {
sample_rate = (u8) afs[i];
break;
}
}
} else {
for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) {
- if ((inband_interferer_div2[i] |
- inband_interferer_div4[i]) == FALSE) {
+ if ((inband_interferer_div2[i] ||
+ !inband_interferer_div4[i])) {
sample_rate = (u8) afs[i];
break;
}
diff --git a/drivers/media/dvb/frontends/stv0900.h b/drivers/media/dvb/frontends/stv0900.h
index 29c3fa85c227..e3e35d1ce838 100644
--- a/drivers/media/dvb/frontends/stv0900.h
+++ b/drivers/media/dvb/frontends/stv0900.h
@@ -49,6 +49,8 @@ struct stv0900_config {
u8 tun2_maddress;
u8 tun1_adc;/* 1 for stv6110, 2 for stb6100 */
u8 tun2_adc;
+ u8 tun1_type;/* for now 3 for stb6100 auto, else - software */
+ u8 tun2_type;
/* Set device param to start dma */
int (*set_ts_params)(struct dvb_frontend *fe, int is_punctured);
};
diff --git a/drivers/media/dvb/frontends/stv0900_core.c b/drivers/media/dvb/frontends/stv0900_core.c
index 8762c86044a5..01f8f1f802fd 100644
--- a/drivers/media/dvb/frontends/stv0900_core.c
+++ b/drivers/media/dvb/frontends/stv0900_core.c
@@ -177,7 +177,7 @@ u8 stv0900_read_reg(struct stv0900_internal *intp, u16 reg)
return buf;
}
-void extract_mask_pos(u32 label, u8 *mask, u8 *pos)
+static void extract_mask_pos(u32 label, u8 *mask, u8 *pos)
{
u8 position = 0, i = 0;
@@ -218,7 +218,7 @@ u8 stv0900_get_bits(struct stv0900_internal *intp, u32 label)
return val;
}
-enum fe_stv0900_error stv0900_initialize(struct stv0900_internal *intp)
+static enum fe_stv0900_error stv0900_initialize(struct stv0900_internal *intp)
{
s32 i;
@@ -282,7 +282,7 @@ enum fe_stv0900_error stv0900_initialize(struct stv0900_internal *intp)
return STV0900_NO_ERROR;
}
-u32 stv0900_get_mclk_freq(struct stv0900_internal *intp, u32 ext_clk)
+static u32 stv0900_get_mclk_freq(struct stv0900_internal *intp, u32 ext_clk)
{
u32 mclk = 90000000, div = 0, ad_div = 0;
@@ -296,7 +296,7 @@ u32 stv0900_get_mclk_freq(struct stv0900_internal *intp, u32 ext_clk)
return mclk;
}
-enum fe_stv0900_error stv0900_set_mclk(struct stv0900_internal *intp, u32 mclk)
+static enum fe_stv0900_error stv0900_set_mclk(struct stv0900_internal *intp, u32 mclk)
{
u32 m_div, clk_sel;
@@ -334,7 +334,7 @@ enum fe_stv0900_error stv0900_set_mclk(struct stv0900_internal *intp, u32 mclk)
return STV0900_NO_ERROR;
}
-u32 stv0900_get_err_count(struct stv0900_internal *intp, int cntr,
+static u32 stv0900_get_err_count(struct stv0900_internal *intp, int cntr,
enum fe_stv0900_demod_num demod)
{
u32 lsb, msb, hsb, err_val;
@@ -567,6 +567,46 @@ void stv0900_set_bandwidth(struct dvb_frontend *fe, u32 bandwidth)
}
}
+u32 stv0900_get_freq_auto(struct stv0900_internal *intp, int demod)
+{
+ u32 freq, round;
+ /* Formulat :
+ Tuner_Frequency(MHz) = Regs / 64
+ Tuner_granularity(MHz) = Regs / 2048
+ real_Tuner_Frequency = Tuner_Frequency(MHz) - Tuner_granularity(MHz)
+ */
+ freq = (stv0900_get_bits(intp, TUN_RFFREQ2) << 10) +
+ (stv0900_get_bits(intp, TUN_RFFREQ1) << 2) +
+ stv0900_get_bits(intp, TUN_RFFREQ0);
+
+ freq = (freq * 1000) / 64;
+
+ round = (stv0900_get_bits(intp, TUN_RFRESTE1) >> 2) +
+ stv0900_get_bits(intp, TUN_RFRESTE0);
+
+ round = (round * 1000) / 2048;
+
+ return freq + round;
+}
+
+void stv0900_set_tuner_auto(struct stv0900_internal *intp, u32 Frequency,
+ u32 Bandwidth, int demod)
+{
+ u32 tunerFrequency;
+ /* Formulat:
+ Tuner_frequency_reg= Frequency(MHz)*64
+ */
+ tunerFrequency = (Frequency * 64) / 1000;
+
+ stv0900_write_bits(intp, TUN_RFFREQ2, (tunerFrequency >> 10));
+ stv0900_write_bits(intp, TUN_RFFREQ1, (tunerFrequency >> 2) & 0xff);
+ stv0900_write_bits(intp, TUN_RFFREQ0, (tunerFrequency & 0x03));
+ /* Low Pass Filter = BW /2 (MHz)*/
+ stv0900_write_bits(intp, TUN_BW, Bandwidth / 2000000);
+ /* Tuner Write trig */
+ stv0900_write_reg(intp, TNRLD, 1);
+}
+
static s32 stv0900_get_rf_level(struct stv0900_internal *intp,
const struct stv0900_table *lookup,
enum fe_stv0900_demod_num demod)
@@ -1329,7 +1369,6 @@ static enum fe_stv0900_error stv0900_init_internal(struct dvb_frontend *fe,
enum fe_stv0900_error error = STV0900_NO_ERROR;
enum fe_stv0900_error demodError = STV0900_NO_ERROR;
struct stv0900_internal *intp = NULL;
-
int selosci, i;
struct stv0900_inode *temp_int = find_inode(state->i2c_adap,
@@ -1345,7 +1384,14 @@ static enum fe_stv0900_error stv0900_init_internal(struct dvb_frontend *fe,
} else {
state->internal = kmalloc(sizeof(struct stv0900_internal),
GFP_KERNEL);
+ if (state->internal == NULL)
+ return STV0900_INVALID_HANDLE;
temp_int = append_internal(state->internal);
+ if (temp_int == NULL) {
+ kfree(state->internal);
+ state->internal = NULL;
+ return STV0900_INVALID_HANDLE;
+ }
state->internal->dmds_used = 1;
state->internal->i2c_adap = state->i2c_adap;
state->internal->i2c_addr = state->config->demod_address;
@@ -1371,11 +1417,6 @@ static enum fe_stv0900_error stv0900_init_internal(struct dvb_frontend *fe,
return error;
}
- if (state->internal == NULL) {
- error = STV0900_INVALID_HANDLE;
- return error;
- }
-
intp = state->internal;
intp->demod_mode = p_init->demod_mode;
@@ -1404,6 +1445,27 @@ static enum fe_stv0900_error stv0900_init_internal(struct dvb_frontend *fe,
stv0900_write_bits(intp, F0900_P1_RST_HWARE, 0);
}
+ intp->tuner_type[0] = p_init->tuner1_type;
+ intp->tuner_type[1] = p_init->tuner2_type;
+ /* tuner init */
+ switch (p_init->tuner1_type) {
+ case 3: /*FE_AUTO_STB6100:*/
+ stv0900_write_reg(intp, R0900_P1_TNRCFG, 0x3c);
+ stv0900_write_reg(intp, R0900_P1_TNRCFG2, 0x86);
+ stv0900_write_reg(intp, R0900_P1_TNRCFG3, 0x18);
+ stv0900_write_reg(intp, R0900_P1_TNRXTAL, 27); /* 27MHz */
+ stv0900_write_reg(intp, R0900_P1_TNRSTEPS, 0x05);
+ stv0900_write_reg(intp, R0900_P1_TNRGAIN, 0x17);
+ stv0900_write_reg(intp, R0900_P1_TNRADJ, 0x1f);
+ stv0900_write_reg(intp, R0900_P1_TNRCTL2, 0x0);
+ stv0900_write_bits(intp, F0900_P1_TUN_TYPE, 3);
+ break;
+ /* case FE_SW_TUNER: */
+ default:
+ stv0900_write_bits(intp, F0900_P1_TUN_TYPE, 6);
+ break;
+ }
+
stv0900_write_bits(intp, F0900_P1_TUN_MADDRESS, p_init->tun1_maddress);
switch (p_init->tuner1_adc) {
case 1:
@@ -1413,6 +1475,27 @@ static enum fe_stv0900_error stv0900_init_internal(struct dvb_frontend *fe,
break;
}
+ stv0900_write_reg(intp, R0900_P1_TNRLD, 1); /* hw tuner */
+
+ /* tuner init */
+ switch (p_init->tuner2_type) {
+ case 3: /*FE_AUTO_STB6100:*/
+ stv0900_write_reg(intp, R0900_P2_TNRCFG, 0x3c);
+ stv0900_write_reg(intp, R0900_P2_TNRCFG2, 0x86);
+ stv0900_write_reg(intp, R0900_P2_TNRCFG3, 0x18);
+ stv0900_write_reg(intp, R0900_P2_TNRXTAL, 27); /* 27MHz */
+ stv0900_write_reg(intp, R0900_P2_TNRSTEPS, 0x05);
+ stv0900_write_reg(intp, R0900_P2_TNRGAIN, 0x17);
+ stv0900_write_reg(intp, R0900_P2_TNRADJ, 0x1f);
+ stv0900_write_reg(intp, R0900_P2_TNRCTL2, 0x0);
+ stv0900_write_bits(intp, F0900_P2_TUN_TYPE, 3);
+ break;
+ /* case FE_SW_TUNER: */
+ default:
+ stv0900_write_bits(intp, F0900_P2_TUN_TYPE, 6);
+ break;
+ }
+
stv0900_write_bits(intp, F0900_P2_TUN_MADDRESS, p_init->tun2_maddress);
switch (p_init->tuner2_adc) {
case 1:
@@ -1422,6 +1505,8 @@ static enum fe_stv0900_error stv0900_init_internal(struct dvb_frontend *fe,
break;
}
+ stv0900_write_reg(intp, R0900_P2_TNRLD, 1); /* hw tuner */
+
stv0900_write_bits(intp, F0900_P1_TUN_IQSWAP, p_init->tun1_iq_inv);
stv0900_write_bits(intp, F0900_P2_TUN_IQSWAP, p_init->tun2_iq_inv);
stv0900_set_mclk(intp, 135000000);
@@ -1824,10 +1909,12 @@ struct dvb_frontend *stv0900_attach(const struct stv0900_config *config,
init_params.tun1_maddress = config->tun1_maddress;
init_params.tun1_iq_inv = STV0900_IQ_NORMAL;
init_params.tuner1_adc = config->tun1_adc;
+ init_params.tuner1_type = config->tun1_type;
init_params.path2_ts_clock = config->path2_mode;
init_params.ts_config = config->ts_config_regs;
init_params.tun2_maddress = config->tun2_maddress;
init_params.tuner2_adc = config->tun2_adc;
+ init_params.tuner2_type = config->tun2_type;
init_params.tun2_iq_inv = STV0900_IQ_SWAPPED;
err_stv0900 = stv0900_init_internal(&state->frontend,
diff --git a/drivers/media/dvb/frontends/stv0900_priv.h b/drivers/media/dvb/frontends/stv0900_priv.h
index d8ba8a984abe..b62b0f0a4fef 100644
--- a/drivers/media/dvb/frontends/stv0900_priv.h
+++ b/drivers/media/dvb/frontends/stv0900_priv.h
@@ -247,6 +247,7 @@ struct stv0900_init_params{
u8 tun1_maddress;
int tuner1_adc;
+ int tuner1_type;
/* IQ from the tuner1 to the demod */
enum stv0900_iq_inversion tun1_iq_inv;
@@ -254,6 +255,7 @@ struct stv0900_init_params{
u8 tun2_maddress;
int tuner2_adc;
+ int tuner2_type;
/* IQ from the tuner2 to the demod */
enum stv0900_iq_inversion tun2_iq_inv;
@@ -309,6 +311,8 @@ struct stv0900_internal{
s32 bw[2];
s32 symbol_rate[2];
s32 srch_range[2];
+ /* for software/auto tuner */
+ int tuner_type[2];
/* algorithm for search Blind, Cold or Warm*/
enum fe_stv0900_search_algo srch_algo[2];
@@ -394,4 +398,11 @@ extern enum
fe_stv0900_tracking_standard stv0900_get_standard(struct dvb_frontend *fe,
enum fe_stv0900_demod_num demod);
+extern u32
+stv0900_get_freq_auto(struct stv0900_internal *intp, int demod);
+
+extern void
+stv0900_set_tuner_auto(struct stv0900_internal *intp, u32 Frequency,
+ u32 Bandwidth, int demod);
+
#endif
diff --git a/drivers/media/dvb/frontends/stv0900_reg.h b/drivers/media/dvb/frontends/stv0900_reg.h
index 7b8edf192e97..731afe93a823 100644
--- a/drivers/media/dvb/frontends/stv0900_reg.h
+++ b/drivers/media/dvb/frontends/stv0900_reg.h
@@ -3174,17 +3174,21 @@ extern s32 shiftx(s32 x, int demod, s32 shift);
#define R0900_P1_TNRRF1 0xf4e9
#define TNRRF1 REGx(R0900_P1_TNRRF1)
#define F0900_P1_TUN_RFFREQ2 0xf4e900ff
+#define TUN_RFFREQ2 FLDx(F0900_P1_TUN_RFFREQ2)
/*P1_TNRRF0*/
#define R0900_P1_TNRRF0 0xf4ea
#define TNRRF0 REGx(R0900_P1_TNRRF0)
#define F0900_P1_TUN_RFFREQ1 0xf4ea00ff
+#define TUN_RFFREQ1 FLDx(F0900_P1_TUN_RFFREQ1)
/*P1_TNRBW*/
#define R0900_P1_TNRBW 0xf4eb
#define TNRBW REGx(R0900_P1_TNRBW)
#define F0900_P1_TUN_RFFREQ0 0xf4eb00c0
+#define TUN_RFFREQ0 FLDx(F0900_P1_TUN_RFFREQ0)
#define F0900_P1_TUN_BW 0xf4eb003f
+#define TUN_BW FLDx(F0900_P1_TUN_BW)
/*P1_TNRADJ*/
#define R0900_P1_TNRADJ 0xf4ec
@@ -3234,11 +3238,13 @@ extern s32 shiftx(s32 x, int demod, s32 shift);
#define F0900_P1_TUN_I2CLOCKED 0xf4f60010
#define F0900_P1_TUN_PROGDONE 0xf4f6000c
#define F0900_P1_TUN_RFRESTE1 0xf4f60003
+#define TUN_RFRESTE1 FLDx(F0900_P1_TUN_RFRESTE1)
/*P1_TNRRESTE*/
#define R0900_P1_TNRRESTE 0xf4f7
#define TNRRESTE REGx(R0900_P1_TNRRESTE)
#define F0900_P1_TUN_RFRESTE0 0xf4f700ff
+#define TUN_RFRESTE0 FLDx(F0900_P1_TUN_RFRESTE0)
/*P1_SMAPCOEF7*/
#define R0900_P1_SMAPCOEF7 0xf500
diff --git a/drivers/media/dvb/frontends/stv0900_sw.c b/drivers/media/dvb/frontends/stv0900_sw.c
index b8da87fa637f..ba0709b2d433 100644
--- a/drivers/media/dvb/frontends/stv0900_sw.c
+++ b/drivers/media/dvb/frontends/stv0900_sw.c
@@ -193,7 +193,7 @@ static int stv0900_search_carr_sw_loop(struct stv0900_internal *intp,
return lock;
}
-int stv0900_sw_algo(struct stv0900_internal *intp,
+static int stv0900_sw_algo(struct stv0900_internal *intp,
enum fe_stv0900_demod_num demod)
{
int lock = FALSE,
@@ -606,7 +606,12 @@ static int stv0900_get_demod_cold_lock(struct dvb_frontend *fe,
tuner_freq -= (current_step * currier_step);
if (intp->chip_id <= 0x20) {
- stv0900_set_tuner(fe, tuner_freq, intp->bw[d]);
+ if (intp->tuner_type[d] == 3)
+ stv0900_set_tuner_auto(intp, tuner_freq,
+ intp->bw[d], demod);
+ else
+ stv0900_set_tuner(fe, tuner_freq, intp->bw[d]);
+
stv0900_write_reg(intp, DMDISTATE, 0x1c);
stv0900_write_reg(intp, CFRINIT1, 0);
stv0900_write_reg(intp, CFRINIT0, 0);
@@ -790,7 +795,7 @@ static enum fe_stv0900_fec stv0900_get_vit_fec(struct stv0900_internal *intp,
return prate;
}
-void stv0900_set_dvbs1_track_car_loop(struct stv0900_internal *intp,
+static void stv0900_set_dvbs1_track_car_loop(struct stv0900_internal *intp,
enum fe_stv0900_demod_num demod,
u32 srate)
{
@@ -976,8 +981,16 @@ static void stv0900_track_optimization(struct dvb_frontend *fe)
intp->rolloff) + 10000000;
if ((intp->chip_id >= 0x20) || (blind_tun_sw == 1)) {
- if (intp->srch_algo[demod] != STV0900_WARM_START)
- stv0900_set_bandwidth(fe, intp->bw[demod]);
+ if (intp->srch_algo[demod] != STV0900_WARM_START) {
+ if (intp->tuner_type[demod] == 3)
+ stv0900_set_tuner_auto(intp,
+ intp->freq[demod],
+ intp->bw[demod],
+ demod);
+ else
+ stv0900_set_bandwidth(fe,
+ intp->bw[demod]);
+ }
}
if ((intp->srch_algo[demod] == STV0900_BLIND_SEARCH) ||
@@ -1202,7 +1215,11 @@ fe_stv0900_signal_type stv0900_get_signal_params(struct dvb_frontend *fe)
}
result->standard = stv0900_get_standard(fe, d);
- result->frequency = stv0900_get_tuner_freq(fe);
+ if (intp->tuner_type[demod] == 3)
+ result->frequency = stv0900_get_freq_auto(intp, d);
+ else
+ result->frequency = stv0900_get_tuner_freq(fe);
+
offsetFreq = stv0900_get_carr_freq(intp, intp->mclk, d) / 1000;
result->frequency += offsetFreq;
result->symbol_rate = stv0900_get_symbol_rate(intp, intp->mclk, d);
@@ -1213,6 +1230,9 @@ fe_stv0900_signal_type stv0900_get_signal_params(struct dvb_frontend *fe)
result->pilot = stv0900_get_bits(intp, DEMOD_TYPE) & 0x01;
result->frame_len = ((u32)stv0900_get_bits(intp, DEMOD_TYPE)) >> 1;
result->rolloff = stv0900_get_bits(intp, ROLLOFF_STATUS);
+
+ dprintk("%s: modcode=0x%x \n", __func__, result->modcode);
+
switch (result->standard) {
case STV0900_DVBS2_STANDARD:
result->spectrum = stv0900_get_bits(intp, SPECINV_DEMOD);
@@ -1239,7 +1259,11 @@ fe_stv0900_signal_type stv0900_get_signal_params(struct dvb_frontend *fe)
if ((intp->srch_algo[d] == STV0900_BLIND_SEARCH) ||
(intp->symbol_rate[d] < 10000000)) {
offsetFreq = result->frequency - intp->freq[d];
- intp->freq[d] = stv0900_get_tuner_freq(fe);
+ if (intp->tuner_type[demod] == 3)
+ intp->freq[d] = stv0900_get_freq_auto(intp, d);
+ else
+ intp->freq[d] = stv0900_get_tuner_freq(fe);
+
if (ABS(offsetFreq) <= ((intp->srch_range[d] / 2000) + 500))
range = STV0900_RANGEOK;
else if (ABS(offsetFreq) <=
@@ -1481,7 +1505,12 @@ static u32 stv0900_search_srate_coarse(struct dvb_frontend *fe)
else
tuner_freq -= (current_step * currier_step);
- stv0900_set_tuner(fe, tuner_freq, intp->bw[demod]);
+ if (intp->tuner_type[demod] == 3)
+ stv0900_set_tuner_auto(intp, tuner_freq,
+ intp->bw[demod], demod);
+ else
+ stv0900_set_tuner(fe, tuner_freq,
+ intp->bw[demod]);
}
}
@@ -1608,7 +1637,8 @@ static int stv0900_blind_search_algo(struct dvb_frontend *fe)
agc2_int = stv0900_blind_check_agc2_min_level(intp, demod);
- if (agc2_int > STV0900_BLIND_SEARCH_AGC2_TH)
+ dprintk("%s agc2_int=%d agc2_th=%d \n", __func__, agc2_int, agc2_th);
+ if (agc2_int > agc2_th)
return FALSE;
if (intp->chip_id == 0x10)
@@ -1875,7 +1905,11 @@ enum fe_stv0900_signal_type stv0900_algo(struct dvb_frontend *fe)
}
- stv0900_set_tuner(fe, intp->freq[demod], intp->bw[demod]);
+ if (intp->tuner_type[demod] == 3)
+ stv0900_set_tuner_auto(intp, intp->freq[demod],
+ intp->bw[demod], demod);
+ else
+ stv0900_set_tuner(fe, intp->freq[demod], intp->bw[demod]);
agc1_power = MAKEWORD(stv0900_get_bits(intp, AGCIQ_VALUE1),
stv0900_get_bits(intp, AGCIQ_VALUE0));
diff --git a/drivers/media/dvb/frontends/stv090x.c b/drivers/media/dvb/frontends/stv090x.c
index 1573466a5c74..c52c3357dc54 100644
--- a/drivers/media/dvb/frontends/stv090x.c
+++ b/drivers/media/dvb/frontends/stv090x.c
@@ -37,7 +37,82 @@
static unsigned int verbose;
module_param(verbose, int, 0644);
-struct mutex demod_lock;
+/* internal params node */
+struct stv090x_dev {
+ /* pointer for internal params, one for each pair of demods */
+ struct stv090x_internal *internal;
+ struct stv090x_dev *next_dev;
+};
+
+/* first internal params */
+static struct stv090x_dev *stv090x_first_dev;
+
+/* find chip by i2c adapter and i2c address */
+static struct stv090x_dev *find_dev(struct i2c_adapter *i2c_adap,
+ u8 i2c_addr)
+{
+ struct stv090x_dev *temp_dev = stv090x_first_dev;
+
+ /*
+ Search of the last stv0900 chip or
+ find it by i2c adapter and i2c address */
+ while ((temp_dev != NULL) &&
+ ((temp_dev->internal->i2c_adap != i2c_adap) ||
+ (temp_dev->internal->i2c_addr != i2c_addr))) {
+
+ temp_dev = temp_dev->next_dev;
+ }
+
+ return temp_dev;
+}
+
+/* deallocating chip */
+static void remove_dev(struct stv090x_internal *internal)
+{
+ struct stv090x_dev *prev_dev = stv090x_first_dev;
+ struct stv090x_dev *del_dev = find_dev(internal->i2c_adap,
+ internal->i2c_addr);
+
+ if (del_dev != NULL) {
+ if (del_dev == stv090x_first_dev) {
+ stv090x_first_dev = del_dev->next_dev;
+ } else {
+ while (prev_dev->next_dev != del_dev)
+ prev_dev = prev_dev->next_dev;
+
+ prev_dev->next_dev = del_dev->next_dev;
+ }
+
+ kfree(del_dev);
+ }
+}
+
+/* allocating new chip */
+static struct stv090x_dev *append_internal(struct stv090x_internal *internal)
+{
+ struct stv090x_dev *new_dev;
+ struct stv090x_dev *temp_dev;
+
+ new_dev = kmalloc(sizeof(struct stv090x_dev), GFP_KERNEL);
+ if (new_dev != NULL) {
+ new_dev->internal = internal;
+ new_dev->next_dev = NULL;
+
+ /* append to list */
+ if (stv090x_first_dev == NULL) {
+ stv090x_first_dev = new_dev;
+ } else {
+ temp_dev = stv090x_first_dev;
+ while (temp_dev->next_dev != NULL)
+ temp_dev = temp_dev->next_dev;
+
+ temp_dev->next_dev = new_dev;
+ }
+ }
+
+ return new_dev;
+}
+
/* DVBS1 and DSS C/N Lookup table */
static const struct stv090x_tab stv090x_s1cn_tab[] = {
@@ -683,6 +758,9 @@ static int stv090x_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
struct stv090x_state *state = fe->demodulator_priv;
u32 reg;
+ if (enable)
+ mutex_lock(&state->internal->tuner_lock);
+
reg = STV090x_READ_DEMOD(state, I2CRPT);
if (enable) {
dprintk(FE_DEBUG, 1, "Enable Gate");
@@ -696,9 +774,14 @@ static int stv090x_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
if ((STV090x_WRITE_DEMOD(state, I2CRPT, reg)) < 0)
goto err;
}
+
+ if (!enable)
+ mutex_unlock(&state->internal->tuner_lock);
+
return 0;
err:
dprintk(FE_ERROR, 1, "I/O error");
+ mutex_unlock(&state->internal->tuner_lock);
return -1;
}
@@ -755,13 +838,13 @@ static int stv090x_set_srate(struct stv090x_state *state, u32 srate)
if (srate > 60000000) {
sym = (srate << 4); /* SR * 2^16 / master_clk */
- sym /= (state->mclk >> 12);
+ sym /= (state->internal->mclk >> 12);
} else if (srate > 6000000) {
sym = (srate << 6);
- sym /= (state->mclk >> 10);
+ sym /= (state->internal->mclk >> 10);
} else {
sym = (srate << 9);
- sym /= (state->mclk >> 7);
+ sym /= (state->internal->mclk >> 7);
}
if (STV090x_WRITE_DEMOD(state, SFRINIT1, (sym >> 8) & 0x7f) < 0) /* MSB */
@@ -782,13 +865,13 @@ static int stv090x_set_max_srate(struct stv090x_state *state, u32 clk, u32 srate
srate = 105 * (srate / 100);
if (srate > 60000000) {
sym = (srate << 4); /* SR * 2^16 / master_clk */
- sym /= (state->mclk >> 12);
+ sym /= (state->internal->mclk >> 12);
} else if (srate > 6000000) {
sym = (srate << 6);
- sym /= (state->mclk >> 10);
+ sym /= (state->internal->mclk >> 10);
} else {
sym = (srate << 9);
- sym /= (state->mclk >> 7);
+ sym /= (state->internal->mclk >> 7);
}
if (sym < 0x7fff) {
@@ -816,13 +899,13 @@ static int stv090x_set_min_srate(struct stv090x_state *state, u32 clk, u32 srate
srate = 95 * (srate / 100);
if (srate > 60000000) {
sym = (srate << 4); /* SR * 2^16 / master_clk */
- sym /= (state->mclk >> 12);
+ sym /= (state->internal->mclk >> 12);
} else if (srate > 6000000) {
sym = (srate << 6);
- sym /= (state->mclk >> 10);
+ sym /= (state->internal->mclk >> 10);
} else {
sym = (srate << 9);
- sym /= (state->mclk >> 7);
+ sym /= (state->internal->mclk >> 7);
}
if (STV090x_WRITE_DEMOD(state, SFRLOW1, ((sym >> 8) & 0x7f)) < 0) /* MSB */
@@ -1103,21 +1186,21 @@ static int stv090x_vitclk_ctl(struct stv090x_state *state, int enable)
switch (state->demod) {
case STV090x_DEMODULATOR_0:
- mutex_lock(&demod_lock);
+ mutex_lock(&state->internal->demod_lock);
reg = stv090x_read_reg(state, STV090x_STOPCLK2);
STV090x_SETFIELD(reg, STOP_CLKVIT1_FIELD, enable);
if (stv090x_write_reg(state, STV090x_STOPCLK2, reg) < 0)
goto err;
- mutex_unlock(&demod_lock);
+ mutex_unlock(&state->internal->demod_lock);
break;
case STV090x_DEMODULATOR_1:
- mutex_lock(&demod_lock);
+ mutex_lock(&state->internal->demod_lock);
reg = stv090x_read_reg(state, STV090x_STOPCLK2);
STV090x_SETFIELD(reg, STOP_CLKVIT2_FIELD, enable);
if (stv090x_write_reg(state, STV090x_STOPCLK2, reg) < 0)
goto err;
- mutex_unlock(&demod_lock);
+ mutex_unlock(&state->internal->demod_lock);
break;
default:
@@ -1126,14 +1209,14 @@ static int stv090x_vitclk_ctl(struct stv090x_state *state, int enable)
}
return 0;
err:
- mutex_unlock(&demod_lock);
+ mutex_unlock(&state->internal->demod_lock);
dprintk(FE_ERROR, 1, "I/O error");
return -1;
}
static int stv090x_dvbs_track_crl(struct stv090x_state *state)
{
- if (state->dev_ver >= 0x30) {
+ if (state->internal->dev_ver >= 0x30) {
/* Set ACLC BCLC optimised value vs SR */
if (state->srate >= 15000000) {
if (STV090x_WRITE_DEMOD(state, ACLC, 0x2b) < 0)
@@ -1215,7 +1298,7 @@ static int stv090x_delivery_search(struct stv090x_state *state)
if (STV090x_WRITE_DEMOD(state, BCLC, 0x09) < 0)
goto err;
- if (state->dev_ver <= 0x20) {
+ if (state->internal->dev_ver <= 0x20) {
/* enable S2 carrier loop */
if (STV090x_WRITE_DEMOD(state, CAR2CFG, 0x26) < 0)
goto err;
@@ -1246,6 +1329,10 @@ static int stv090x_delivery_search(struct stv090x_state *state)
default:
/* enable DVB-S2 and DVB-S2 in Auto MODE */
reg = STV090x_READ_DEMOD(state, DMDCFGMD);
+ STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 0);
+ STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 0);
+ if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
+ goto err;
STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 1);
STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 1);
if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
@@ -1257,7 +1344,7 @@ static int stv090x_delivery_search(struct stv090x_state *state)
if (stv090x_dvbs_track_crl(state) < 0)
goto err;
- if (state->dev_ver <= 0x20) {
+ if (state->internal->dev_ver <= 0x20) {
/* enable S2 carrier loop */
if (STV090x_WRITE_DEMOD(state, CAR2CFG, 0x26) < 0)
goto err;
@@ -1304,7 +1391,7 @@ static int stv090x_start_search(struct stv090x_state *state)
if (STV090x_WRITE_DEMOD(state, DMDISTATE, reg) < 0)
goto err;
- if (state->dev_ver <= 0x20) {
+ if (state->internal->dev_ver <= 0x20) {
if (state->srate <= 5000000) {
if (STV090x_WRITE_DEMOD(state, CARCFG, 0x44) < 0)
goto err;
@@ -1348,7 +1435,7 @@ static int stv090x_start_search(struct stv090x_state *state)
* CFR max = +1MHz
*/
freq_abs = 1000 << 16;
- freq_abs /= (state->mclk / 1000);
+ freq_abs /= (state->internal->mclk / 1000);
freq = (s16) freq_abs;
} else {
/* COLD Start
@@ -1358,7 +1445,7 @@ static int stv090x_start_search(struct stv090x_state *state)
*/
freq_abs = (state->search_range / 2000) + 600;
freq_abs = freq_abs << 16;
- freq_abs /= (state->mclk / 1000);
+ freq_abs /= (state->internal->mclk / 1000);
freq = (s16) freq_abs;
}
@@ -1381,7 +1468,7 @@ static int stv090x_start_search(struct stv090x_state *state)
if (STV090x_WRITE_DEMOD(state, CFRINIT0, 0) < 0)
goto err;
- if (state->dev_ver >= 0x20) {
+ if (state->internal->dev_ver >= 0x20) {
if (STV090x_WRITE_DEMOD(state, EQUALCFG, 0x41) < 0)
goto err;
if (STV090x_WRITE_DEMOD(state, FFECFG, 0x41) < 0)
@@ -1418,10 +1505,10 @@ static int stv090x_start_search(struct stv090x_state *state)
if (STV090x_WRITE_DEMOD(state, RTC, 0x88) < 0)
goto err;
- if (state->dev_ver >= 0x20) {
+ if (state->internal->dev_ver >= 0x20) {
/*Frequency offset detector setting*/
if (state->srate < 2000000) {
- if (state->dev_ver <= 0x20) {
+ if (state->internal->dev_ver <= 0x20) {
/* Cut 2 */
if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x39) < 0)
goto err;
@@ -1512,7 +1599,7 @@ static int stv090x_get_agc2_min_level(struct stv090x_state *state)
steps = 1;
dir = 1;
- freq_step = (1000000 * 256) / (state->mclk / 256);
+ freq_step = (1000000 * 256) / (state->internal->mclk / 256);
freq_init = 0;
for (i = 0; i < steps; i++) {
@@ -1583,7 +1670,7 @@ static u32 stv090x_srate_srch_coarse(struct stv090x_state *state)
u32 srate_coarse = 0, agc2 = 0, car_step = 1200, reg;
u32 agc2th;
- if (state->dev_ver >= 0x30)
+ if (state->internal->dev_ver >= 0x30)
agc2th = 0x2e00;
else
agc2th = 0x1f00;
@@ -1619,13 +1706,13 @@ static u32 stv090x_srate_srch_coarse(struct stv090x_state *state)
if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x50) < 0)
goto err;
- if (state->dev_ver >= 0x30) {
+ if (state->internal->dev_ver >= 0x30) {
if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x99) < 0)
goto err;
if (STV090x_WRITE_DEMOD(state, SFRSTEP, 0x98) < 0)
goto err;
- } else if (state->dev_ver >= 0x20) {
+ } else if (state->internal->dev_ver >= 0x20) {
if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x6a) < 0)
goto err;
if (STV090x_WRITE_DEMOD(state, SFRSTEP, 0x95) < 0)
@@ -1677,7 +1764,7 @@ static u32 stv090x_srate_srch_coarse(struct stv090x_state *state)
STV090x_READ_DEMOD(state, AGC2I0);
}
agc2 /= 10;
- srate_coarse = stv090x_get_srate(state, state->mclk);
+ srate_coarse = stv090x_get_srate(state, state->internal->mclk);
cur_step++;
dir *= -1;
if ((tmg_cpt >= 5) && (agc2 < agc2th) &&
@@ -1695,12 +1782,12 @@ static u32 stv090x_srate_srch_coarse(struct stv090x_state *state)
if (state->config->tuner_set_frequency) {
if (state->config->tuner_set_frequency(fe, freq) < 0)
- goto err;
+ goto err_gateoff;
}
if (state->config->tuner_set_bandwidth) {
if (state->config->tuner_set_bandwidth(fe, state->tuner_bw) < 0)
- goto err;
+ goto err_gateoff;
}
if (stv090x_i2c_gate_ctrl(fe, 0) < 0)
@@ -1713,7 +1800,7 @@ static u32 stv090x_srate_srch_coarse(struct stv090x_state *state)
if (state->config->tuner_get_status) {
if (state->config->tuner_get_status(fe, &reg) < 0)
- goto err;
+ goto err_gateoff;
}
if (reg)
@@ -1729,9 +1816,12 @@ static u32 stv090x_srate_srch_coarse(struct stv090x_state *state)
if (!tmg_lock)
srate_coarse = 0;
else
- srate_coarse = stv090x_get_srate(state, state->mclk);
+ srate_coarse = stv090x_get_srate(state, state->internal->mclk);
return srate_coarse;
+
+err_gateoff:
+ stv090x_i2c_gate_ctrl(fe, 0);
err:
dprintk(FE_ERROR, 1, "I/O error");
return -1;
@@ -1741,7 +1831,7 @@ static u32 stv090x_srate_srch_fine(struct stv090x_state *state)
{
u32 srate_coarse, freq_coarse, sym, reg;
- srate_coarse = stv090x_get_srate(state, state->mclk);
+ srate_coarse = stv090x_get_srate(state, state->internal->mclk);
freq_coarse = STV090x_READ_DEMOD(state, CFR2) << 8;
freq_coarse |= STV090x_READ_DEMOD(state, CFR1);
sym = 13 * (srate_coarse / 10); /* SFRUP = SFR + 30% */
@@ -1767,10 +1857,10 @@ static u32 stv090x_srate_srch_fine(struct stv090x_state *state)
if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x38) < 0)
goto err;
- if (state->dev_ver >= 0x30) {
+ if (state->internal->dev_ver >= 0x30) {
if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x79) < 0)
goto err;
- } else if (state->dev_ver >= 0x20) {
+ } else if (state->internal->dev_ver >= 0x20) {
if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x49) < 0)
goto err;
}
@@ -1778,20 +1868,20 @@ static u32 stv090x_srate_srch_fine(struct stv090x_state *state)
if (srate_coarse > 3000000) {
sym = 13 * (srate_coarse / 10); /* SFRUP = SFR + 30% */
sym = (sym / 1000) * 65536;
- sym /= (state->mclk / 1000);
+ sym /= (state->internal->mclk / 1000);
if (STV090x_WRITE_DEMOD(state, SFRUP1, (sym >> 8) & 0x7f) < 0)
goto err;
if (STV090x_WRITE_DEMOD(state, SFRUP0, sym & 0xff) < 0)
goto err;
sym = 10 * (srate_coarse / 13); /* SFRLOW = SFR - 30% */
sym = (sym / 1000) * 65536;
- sym /= (state->mclk / 1000);
+ sym /= (state->internal->mclk / 1000);
if (STV090x_WRITE_DEMOD(state, SFRLOW1, (sym >> 8) & 0x7f) < 0)
goto err;
if (STV090x_WRITE_DEMOD(state, SFRLOW0, sym & 0xff) < 0)
goto err;
sym = (srate_coarse / 1000) * 65536;
- sym /= (state->mclk / 1000);
+ sym /= (state->internal->mclk / 1000);
if (STV090x_WRITE_DEMOD(state, SFRINIT1, (sym >> 8) & 0xff) < 0)
goto err;
if (STV090x_WRITE_DEMOD(state, SFRINIT0, sym & 0xff) < 0)
@@ -1799,20 +1889,20 @@ static u32 stv090x_srate_srch_fine(struct stv090x_state *state)
} else {
sym = 13 * (srate_coarse / 10); /* SFRUP = SFR + 30% */
sym = (sym / 100) * 65536;
- sym /= (state->mclk / 100);
+ sym /= (state->internal->mclk / 100);
if (STV090x_WRITE_DEMOD(state, SFRUP1, (sym >> 8) & 0x7f) < 0)
goto err;
if (STV090x_WRITE_DEMOD(state, SFRUP0, sym & 0xff) < 0)
goto err;
sym = 10 * (srate_coarse / 14); /* SFRLOW = SFR - 30% */
sym = (sym / 100) * 65536;
- sym /= (state->mclk / 100);
+ sym /= (state->internal->mclk / 100);
if (STV090x_WRITE_DEMOD(state, SFRLOW1, (sym >> 8) & 0x7f) < 0)
goto err;
if (STV090x_WRITE_DEMOD(state, SFRLOW0, sym & 0xff) < 0)
goto err;
sym = (srate_coarse / 100) * 65536;
- sym /= (state->mclk / 100);
+ sym /= (state->internal->mclk / 100);
if (STV090x_WRITE_DEMOD(state, SFRINIT1, (sym >> 8) & 0xff) < 0)
goto err;
if (STV090x_WRITE_DEMOD(state, SFRINIT0, sym & 0xff) < 0)
@@ -1874,18 +1964,19 @@ static int stv090x_blind_search(struct stv090x_state *state)
u32 agc2, reg, srate_coarse;
s32 cpt_fail, agc2_ovflw, i;
u8 k_ref, k_max, k_min;
- int coarse_fail, lock;
+ int coarse_fail = 0;
+ int lock;
k_max = 110;
k_min = 10;
agc2 = stv090x_get_agc2_min_level(state);
- if (agc2 > STV090x_SEARCH_AGC2_TH(state->dev_ver)) {
+ if (agc2 > STV090x_SEARCH_AGC2_TH(state->internal->dev_ver)) {
lock = 0;
} else {
- if (state->dev_ver <= 0x20) {
+ if (state->internal->dev_ver <= 0x20) {
if (STV090x_WRITE_DEMOD(state, CARCFG, 0xc4) < 0)
goto err;
} else {
@@ -1897,7 +1988,7 @@ static int stv090x_blind_search(struct stv090x_state *state)
if (STV090x_WRITE_DEMOD(state, RTCS2, 0x44) < 0)
goto err;
- if (state->dev_ver >= 0x20) {
+ if (state->internal->dev_ver >= 0x20) {
if (STV090x_WRITE_DEMOD(state, EQUALCFG, 0x41) < 0)
goto err;
if (STV090x_WRITE_DEMOD(state, FFECFG, 0x41) < 0)
@@ -1956,7 +2047,7 @@ static int stv090x_chk_tmg(struct stv090x_state *state)
u32 reg;
s32 tmg_cpt = 0, i;
u8 freq, tmg_thh, tmg_thl;
- int tmg_lock;
+ int tmg_lock = 0;
freq = STV090x_READ_DEMOD(state, CARFREQ);
tmg_thh = STV090x_READ_DEMOD(state, TMGTHRISE);
@@ -2080,12 +2171,12 @@ static int stv090x_get_coldlock(struct stv090x_state *state, s32 timeout_dmd)
if (state->config->tuner_set_frequency) {
if (state->config->tuner_set_frequency(fe, freq) < 0)
- goto err;
+ goto err_gateoff;
}
if (state->config->tuner_set_bandwidth) {
if (state->config->tuner_set_bandwidth(fe, state->tuner_bw) < 0)
- goto err;
+ goto err_gateoff;
}
if (stv090x_i2c_gate_ctrl(fe, 0) < 0)
@@ -2098,7 +2189,7 @@ static int stv090x_get_coldlock(struct stv090x_state *state, s32 timeout_dmd)
if (state->config->tuner_get_status) {
if (state->config->tuner_get_status(fe, &reg) < 0)
- goto err;
+ goto err_gateoff;
}
if (reg)
@@ -2129,6 +2220,8 @@ static int stv090x_get_coldlock(struct stv090x_state *state, s32 timeout_dmd)
return lock;
+err_gateoff:
+ stv090x_i2c_gate_ctrl(fe, 0);
err:
dprintk(FE_ERROR, 1, "I/O error");
return -1;
@@ -2142,13 +2235,13 @@ static int stv090x_get_loop_params(struct stv090x_state *state, s32 *freq_inc, s
car_max = state->search_range / 1000;
car_max += car_max / 10;
car_max = 65536 * (car_max / 2);
- car_max /= (state->mclk / 1000);
+ car_max /= (state->internal->mclk / 1000);
if (car_max > 0x4000)
car_max = 0x4000 ; /* maxcarrier should be<= +-1/4 Mclk */
inc = srate;
- inc /= state->mclk / 1000;
+ inc /= state->internal->mclk / 1000;
inc *= 256;
inc *= 256;
inc /= 1000;
@@ -2209,7 +2302,7 @@ static int stv090x_chk_signal(struct stv090x_state *state)
car_max += (car_max / 10); /* 10% margin */
car_max = (65536 * car_max / 2);
- car_max /= state->mclk / 1000;
+ car_max /= state->internal->mclk / 1000;
if (car_max > 0x4000)
car_max = 0x4000;
@@ -2234,7 +2327,7 @@ static int stv090x_search_car_loop(struct stv090x_state *state, s32 inc, s32 tim
car_max = state->search_range / 1000;
car_max += (car_max / 10);
car_max = (65536 * car_max / 2);
- car_max /= (state->mclk / 1000);
+ car_max /= (state->internal->mclk / 1000);
if (car_max > 0x4000)
car_max = 0x4000;
@@ -2304,7 +2397,7 @@ static int stv090x_sw_algo(struct stv090x_state *state)
case STV090x_SEARCH_DVBS1:
case STV090x_SEARCH_DSS:
/* accelerate the frequency detector */
- if (state->dev_ver >= 0x20) {
+ if (state->internal->dev_ver >= 0x20) {
if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x3B) < 0)
goto err;
}
@@ -2315,7 +2408,7 @@ static int stv090x_sw_algo(struct stv090x_state *state)
break;
case STV090x_SEARCH_DVBS2:
- if (state->dev_ver >= 0x20) {
+ if (state->internal->dev_ver >= 0x20) {
if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x79) < 0)
goto err;
}
@@ -2328,7 +2421,7 @@ static int stv090x_sw_algo(struct stv090x_state *state)
case STV090x_SEARCH_AUTO:
default:
/* accelerate the frequency detector */
- if (state->dev_ver >= 0x20) {
+ if (state->internal->dev_ver >= 0x20) {
if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x3b) < 0)
goto err;
if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x79) < 0)
@@ -2350,7 +2443,7 @@ static int stv090x_sw_algo(struct stv090x_state *state)
/*run the SW search 2 times maximum*/
if (lock || no_signal || (trials == 2)) {
/*Check if the demod is not losing lock in DVBS2*/
- if (state->dev_ver >= 0x20) {
+ if (state->internal->dev_ver >= 0x20) {
if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x49) < 0)
goto err;
if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x9e) < 0)
@@ -2372,7 +2465,7 @@ static int stv090x_sw_algo(struct stv090x_state *state)
/*FALSE lock, The demod is loosing lock */
lock = 0;
if (trials < 2) {
- if (state->dev_ver >= 0x20) {
+ if (state->internal->dev_ver >= 0x20) {
if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x79) < 0)
goto err;
}
@@ -2422,11 +2515,11 @@ static s32 stv090x_get_car_freq(struct stv090x_state *state, u32 mclk)
derot |= STV090x_READ_DEMOD(state, CFR0);
derot = comp2(derot, 24);
- int_1 = state->mclk >> 12;
+ int_1 = mclk >> 12;
int_2 = derot >> 12;
/* carrier_frequency = MasterClock * Reg / 2^24 */
- tmp_1 = state->mclk % 0x1000;
+ tmp_1 = mclk % 0x1000;
tmp_2 = derot % 0x1000;
derot = (int_1 * int_2) +
@@ -2502,13 +2595,13 @@ static enum stv090x_signal_state stv090x_get_sig_params(struct stv090x_state *st
if (state->config->tuner_get_frequency) {
if (state->config->tuner_get_frequency(fe, &state->frequency) < 0)
- goto err;
+ goto err_gateoff;
}
if (stv090x_i2c_gate_ctrl(fe, 0) < 0)
goto err;
- offst_freq = stv090x_get_car_freq(state, state->mclk) / 1000;
+ offst_freq = stv090x_get_car_freq(state, state->internal->mclk) / 1000;
state->frequency += offst_freq;
if (stv090x_get_viterbi(state) < 0)
@@ -2530,7 +2623,7 @@ static enum stv090x_signal_state stv090x_get_sig_params(struct stv090x_state *st
if (state->config->tuner_get_frequency) {
if (state->config->tuner_get_frequency(fe, &state->frequency) < 0)
- goto err;
+ goto err_gateoff;
}
if (stv090x_i2c_gate_ctrl(fe, 0) < 0)
@@ -2550,6 +2643,9 @@ static enum stv090x_signal_state stv090x_get_sig_params(struct stv090x_state *st
}
return STV090x_OUTOFRANGE;
+
+err_gateoff:
+ stv090x_i2c_gate_ctrl(fe, 0);
err:
dprintk(FE_ERROR, 1, "I/O error");
return -1;
@@ -2579,7 +2675,7 @@ static u8 stv090x_optimize_carloop(struct stv090x_state *state, enum stv090x_mod
s32 i;
struct stv090x_long_frame_crloop *car_loop, *car_loop_qpsk_low, *car_loop_apsk_low;
- if (state->dev_ver == 0x20) {
+ if (state->internal->dev_ver == 0x20) {
car_loop = stv090x_s2_crl_cut20;
car_loop_qpsk_low = stv090x_s2_lowqpsk_crl_cut20;
car_loop_apsk_low = stv090x_s2_apsk_crl_cut20;
@@ -2700,7 +2796,7 @@ static u8 stv090x_optimize_carloop_short(struct stv090x_state *state)
break;
}
- if (state->dev_ver >= 0x30) {
+ if (state->internal->dev_ver >= 0x30) {
/* Cut 3.0 and up */
short_crl = stv090x_s2_short_crl_cut30;
} else {
@@ -2732,7 +2828,7 @@ static int stv090x_optimize_track(struct stv090x_state *state)
s32 srate, pilots, aclc, f_1, f_0, i = 0, blind_tune = 0;
u32 reg;
- srate = stv090x_get_srate(state, state->mclk);
+ srate = stv090x_get_srate(state, state->internal->mclk);
srate += stv090x_get_tmgoffst(state, srate);
switch (state->delsys) {
@@ -2751,7 +2847,7 @@ static int stv090x_optimize_track(struct stv090x_state *state)
if (STV090x_WRITE_DEMOD(state, DEMOD, reg) < 0)
goto err;
- if (state->dev_ver >= 0x30) {
+ if (state->internal->dev_ver >= 0x30) {
if (stv090x_get_viterbi(state) < 0)
goto err;
@@ -2868,7 +2964,7 @@ static int stv090x_optimize_track(struct stv090x_state *state)
goto err;
}
- if (state->dev_ver >= 0x20) {
+ if (state->internal->dev_ver >= 0x20) {
if ((state->search_mode == STV090x_SEARCH_DVBS1) ||
(state->search_mode == STV090x_SEARCH_DSS) ||
(state->search_mode == STV090x_SEARCH_AUTO)) {
@@ -2890,7 +2986,8 @@ static int stv090x_optimize_track(struct stv090x_state *state)
if (STV090x_WRITE_DEMOD(state, SFRLOW1, 0x80) < 0)
goto err;
- if ((state->dev_ver >= 0x20) || (blind_tune == 1) || (state->srate < 10000000)) {
+ if ((state->internal->dev_ver >= 0x20) || (blind_tune == 1) ||
+ (state->srate < 10000000)) {
/* update initial carrier freq with the found freq offset */
if (STV090x_WRITE_DEMOD(state, CFRINIT1, f_1) < 0)
goto err;
@@ -2898,7 +2995,7 @@ static int stv090x_optimize_track(struct stv090x_state *state)
goto err;
state->tuner_bw = stv090x_car_width(srate, state->rolloff) + 10000000;
- if ((state->dev_ver >= 0x20) || (blind_tune == 1)) {
+ if ((state->internal->dev_ver >= 0x20) || (blind_tune == 1)) {
if (state->algo != STV090x_WARM_SEARCH) {
@@ -2907,7 +3004,7 @@ static int stv090x_optimize_track(struct stv090x_state *state)
if (state->config->tuner_set_bandwidth) {
if (state->config->tuner_set_bandwidth(fe, state->tuner_bw) < 0)
- goto err;
+ goto err_gateoff;
}
if (stv090x_i2c_gate_ctrl(fe, 0) < 0)
@@ -2950,7 +3047,7 @@ static int stv090x_optimize_track(struct stv090x_state *state)
}
- if (state->dev_ver >= 0x20) {
+ if (state->internal->dev_ver >= 0x20) {
if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x49) < 0)
goto err;
}
@@ -2959,6 +3056,9 @@ static int stv090x_optimize_track(struct stv090x_state *state)
stv090x_set_vit_thtracq(state);
return 0;
+
+err_gateoff:
+ stv090x_i2c_gate_ctrl(fe, 0);
err:
dprintk(FE_ERROR, 1, "I/O error");
return -1;
@@ -3026,7 +3126,7 @@ static int stv090x_set_s2rolloff(struct stv090x_state *state)
{
u32 reg;
- if (state->dev_ver <= 0x20) {
+ if (state->internal->dev_ver <= 0x20) {
/* rolloff to auto mode if DVBS2 */
reg = STV090x_READ_DEMOD(state, DEMOD);
STV090x_SETFIELD_Px(reg, MANUAL_SXROLLOFF_FIELD, 0x00);
@@ -3062,7 +3162,7 @@ static enum stv090x_signal_state stv090x_algo(struct stv090x_state *state)
if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x5c) < 0) /* Demod stop */
goto err;
- if (state->dev_ver >= 0x20) {
+ if (state->internal->dev_ver >= 0x20) {
if (state->srate > 5000000) {
if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x9e) < 0)
goto err;
@@ -3102,7 +3202,7 @@ static enum stv090x_signal_state stv090x_algo(struct stv090x_state *state)
if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x38) < 0)
goto err;
- if (state->dev_ver >= 0x20) {
+ if (state->internal->dev_ver >= 0x20) {
if (STV090x_WRITE_DEMOD(state, KREFTMG, 0x5a) < 0)
goto err;
if (state->algo == STV090x_COLD_SEARCH)
@@ -3120,9 +3220,11 @@ static enum stv090x_signal_state stv090x_algo(struct stv090x_state *state)
if (stv090x_set_srate(state, state->srate) < 0)
goto err;
- if (stv090x_set_max_srate(state, state->mclk, state->srate) < 0)
+ if (stv090x_set_max_srate(state, state->internal->mclk,
+ state->srate) < 0)
goto err;
- if (stv090x_set_min_srate(state, state->mclk, state->srate) < 0)
+ if (stv090x_set_min_srate(state, state->internal->mclk,
+ state->srate) < 0)
goto err;
if (state->srate >= 10000000)
@@ -3136,18 +3238,21 @@ static enum stv090x_signal_state stv090x_algo(struct stv090x_state *state)
goto err;
if (state->config->tuner_set_bbgain) {
- if (state->config->tuner_set_bbgain(fe, 10) < 0) /* 10dB */
- goto err;
+ reg = state->config->tuner_bbgain;
+ if (reg == 0)
+ reg = 10; /* default: 10dB */
+ if (state->config->tuner_set_bbgain(fe, reg) < 0)
+ goto err_gateoff;
}
if (state->config->tuner_set_frequency) {
if (state->config->tuner_set_frequency(fe, state->frequency) < 0)
- goto err;
+ goto err_gateoff;
}
if (state->config->tuner_set_bandwidth) {
if (state->config->tuner_set_bandwidth(fe, state->tuner_bw) < 0)
- goto err;
+ goto err_gateoff;
}
if (stv090x_i2c_gate_ctrl(fe, 0) < 0)
@@ -3155,21 +3260,21 @@ static enum stv090x_signal_state stv090x_algo(struct stv090x_state *state)
msleep(50);
- if (stv090x_i2c_gate_ctrl(fe, 1) < 0)
- goto err;
-
if (state->config->tuner_get_status) {
+ if (stv090x_i2c_gate_ctrl(fe, 1) < 0)
+ goto err;
if (state->config->tuner_get_status(fe, &reg) < 0)
+ goto err_gateoff;
+ if (stv090x_i2c_gate_ctrl(fe, 0) < 0)
goto err;
- }
- if (reg)
- dprintk(FE_DEBUG, 1, "Tuner phase locked");
- else
- dprintk(FE_DEBUG, 1, "Tuner unlocked");
-
- if (stv090x_i2c_gate_ctrl(fe, 0) < 0)
- goto err;
+ if (reg)
+ dprintk(FE_DEBUG, 1, "Tuner phase locked");
+ else {
+ dprintk(FE_DEBUG, 1, "Tuner unlocked");
+ return STV090x_NOCARRIER;
+ }
+ }
msleep(10);
agc1_power = MAKEWORD16(STV090x_READ_DEMOD(state, AGCIQIN1),
@@ -3194,7 +3299,7 @@ static enum stv090x_signal_state stv090x_algo(struct stv090x_state *state)
reg = STV090x_READ_DEMOD(state, DEMOD);
STV090x_SETFIELD_Px(reg, SPECINV_CONTROL_FIELD, state->inversion);
- if (state->dev_ver <= 0x20) {
+ if (state->internal->dev_ver <= 0x20) {
/* rolloff to auto mode if DVBS2 */
STV090x_SETFIELD_Px(reg, MANUAL_SXROLLOFF_FIELD, 1);
} else {
@@ -3238,7 +3343,7 @@ static enum stv090x_signal_state stv090x_algo(struct stv090x_state *state)
if ((lock) && (signal_state == STV090x_RANGEOK)) { /* signal within Range */
stv090x_optimize_track(state);
- if (state->dev_ver >= 0x20) {
+ if (state->internal->dev_ver >= 0x20) {
/* >= Cut 2.0 :release TS reset after
* demod lock and optimized Tracking
*/
@@ -3293,6 +3398,8 @@ static enum stv090x_signal_state stv090x_algo(struct stv090x_state *state)
}
return signal_state;
+err_gateoff:
+ stv090x_i2c_gate_ctrl(fe, 0);
err:
dprintk(FE_ERROR, 1, "I/O error");
return -1;
@@ -3303,6 +3410,9 @@ static enum dvbfe_search stv090x_search(struct dvb_frontend *fe, struct dvb_fron
struct stv090x_state *state = fe->demodulator_priv;
struct dtv_frontend_properties *props = &fe->dtv_property_cache;
+ if (p->frequency == 0)
+ return DVBFE_ALGO_SEARCH_INVALID;
+
state->delsys = props->delivery_system;
state->frequency = p->frequency;
state->srate = p->u.qpsk.symbol_rate;
@@ -3353,7 +3463,8 @@ static int stv090x_read_status(struct dvb_frontend *fe, enum fe_status *status)
if (STV090x_GETFIELD_Px(reg, PKTDELIN_LOCK_FIELD)) {
reg = STV090x_READ_DEMOD(state, TSSTATUS);
if (STV090x_GETFIELD_Px(reg, TSFIFO_LINEOK_FIELD)) {
- *status = FE_HAS_CARRIER |
+ *status = FE_HAS_SIGNAL |
+ FE_HAS_CARRIER |
FE_HAS_VITERBI |
FE_HAS_SYNC |
FE_HAS_LOCK;
@@ -3370,7 +3481,11 @@ static int stv090x_read_status(struct dvb_frontend *fe, enum fe_status *status)
if (STV090x_GETFIELD_Px(reg, LOCKEDVIT_FIELD)) {
reg = STV090x_READ_DEMOD(state, TSSTATUS);
if (STV090x_GETFIELD_Px(reg, TSFIFO_LINEOK_FIELD)) {
- *status = FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
+ *status = FE_HAS_SIGNAL |
+ FE_HAS_CARRIER |
+ FE_HAS_VITERBI |
+ FE_HAS_SYNC |
+ FE_HAS_LOCK;
}
}
}
@@ -3770,6 +3885,15 @@ static void stv090x_release(struct dvb_frontend *fe)
{
struct stv090x_state *state = fe->demodulator_priv;
+ state->internal->num_used--;
+ if (state->internal->num_used <= 0) {
+
+ dprintk(FE_ERROR, 1, "Actually removing");
+
+ remove_dev(state->internal);
+ kfree(state->internal);
+ }
+
kfree(state);
}
@@ -3901,10 +4025,10 @@ static int stv090x_set_mclk(struct stv090x_state *state, u32 mclk, u32 clk)
if (stv090x_write_reg(state, STV090x_NCOARSE, reg) < 0)
goto err;
- state->mclk = stv090x_get_mclk(state);
+ state->internal->mclk = stv090x_get_mclk(state);
/*Set the DiseqC frequency to 22KHz */
- div = state->mclk / 704000;
+ div = state->internal->mclk / 704000;
if (STV090x_WRITE_DEMOD(state, F22TX, div) < 0)
goto err;
if (STV090x_WRITE_DEMOD(state, F22RX, div) < 0)
@@ -3920,7 +4044,7 @@ static int stv090x_set_tspath(struct stv090x_state *state)
{
u32 reg;
- if (state->dev_ver >= 0x20) {
+ if (state->internal->dev_ver >= 0x20) {
switch (state->config->ts1_mode) {
case STV090x_TSMODE_PARALLEL_PUNCTURED:
case STV090x_TSMODE_DVBCI:
@@ -4092,6 +4216,71 @@ static int stv090x_set_tspath(struct stv090x_state *state)
default:
break;
}
+
+ if (state->config->ts1_clk > 0) {
+ u32 speed;
+
+ switch (state->config->ts1_mode) {
+ case STV090x_TSMODE_PARALLEL_PUNCTURED:
+ case STV090x_TSMODE_DVBCI:
+ default:
+ speed = state->internal->mclk /
+ (state->config->ts1_clk / 4);
+ if (speed < 0x08)
+ speed = 0x08;
+ if (speed > 0xFF)
+ speed = 0xFF;
+ break;
+ case STV090x_TSMODE_SERIAL_PUNCTURED:
+ case STV090x_TSMODE_SERIAL_CONTINUOUS:
+ speed = state->internal->mclk /
+ (state->config->ts1_clk / 32);
+ if (speed < 0x20)
+ speed = 0x20;
+ if (speed > 0xFF)
+ speed = 0xFF;
+ break;
+ }
+ reg = stv090x_read_reg(state, STV090x_P1_TSCFGM);
+ STV090x_SETFIELD_Px(reg, TSFIFO_MANSPEED_FIELD, 3);
+ if (stv090x_write_reg(state, STV090x_P1_TSCFGM, reg) < 0)
+ goto err;
+ if (stv090x_write_reg(state, STV090x_P1_TSSPEED, speed) < 0)
+ goto err;
+ }
+
+ if (state->config->ts2_clk > 0) {
+ u32 speed;
+
+ switch (state->config->ts2_mode) {
+ case STV090x_TSMODE_PARALLEL_PUNCTURED:
+ case STV090x_TSMODE_DVBCI:
+ default:
+ speed = state->internal->mclk /
+ (state->config->ts2_clk / 4);
+ if (speed < 0x08)
+ speed = 0x08;
+ if (speed > 0xFF)
+ speed = 0xFF;
+ break;
+ case STV090x_TSMODE_SERIAL_PUNCTURED:
+ case STV090x_TSMODE_SERIAL_CONTINUOUS:
+ speed = state->internal->mclk /
+ (state->config->ts2_clk / 32);
+ if (speed < 0x20)
+ speed = 0x20;
+ if (speed > 0xFF)
+ speed = 0xFF;
+ break;
+ }
+ reg = stv090x_read_reg(state, STV090x_P2_TSCFGM);
+ STV090x_SETFIELD_Px(reg, TSFIFO_MANSPEED_FIELD, 3);
+ if (stv090x_write_reg(state, STV090x_P2_TSCFGM, reg) < 0)
+ goto err;
+ if (stv090x_write_reg(state, STV090x_P2_TSSPEED, speed) < 0)
+ goto err;
+ }
+
reg = stv090x_read_reg(state, STV090x_P2_TSCFGH);
STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0x01);
if (stv090x_write_reg(state, STV090x_P2_TSCFGH, reg) < 0)
@@ -4120,6 +4309,15 @@ static int stv090x_init(struct dvb_frontend *fe)
const struct stv090x_config *config = state->config;
u32 reg;
+ if (state->internal->mclk == 0) {
+ stv090x_set_mclk(state, 135000000, config->xtal); /* 135 Mhz */
+ msleep(5);
+ if (stv090x_write_reg(state, STV090x_SYNTCTRL,
+ 0x20 | config->clk_mode) < 0)
+ goto err;
+ stv090x_get_mclk(state);
+ }
+
if (stv090x_wakeup(fe) < 0) {
dprintk(FE_ERROR, 1, "Error waking device");
goto err;
@@ -4142,12 +4340,12 @@ static int stv090x_init(struct dvb_frontend *fe)
if (config->tuner_set_mode) {
if (config->tuner_set_mode(fe, TUNER_WAKE) < 0)
- goto err;
+ goto err_gateoff;
}
if (config->tuner_init) {
if (config->tuner_init(fe) < 0)
- goto err;
+ goto err_gateoff;
}
if (stv090x_i2c_gate_ctrl(fe, 0) < 0)
@@ -4157,6 +4355,9 @@ static int stv090x_init(struct dvb_frontend *fe)
goto err;
return 0;
+
+err_gateoff:
+ stv090x_i2c_gate_ctrl(fe, 0);
err:
dprintk(FE_ERROR, 1, "I/O error");
return -1;
@@ -4188,16 +4389,26 @@ static int stv090x_setup(struct dvb_frontend *fe)
}
/* STV090x init */
- if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x5c) < 0) /* Stop Demod */
+
+ /* Stop Demod */
+ if (stv090x_write_reg(state, STV090x_P1_DMDISTATE, 0x5c) < 0)
+ goto err;
+ if (stv090x_write_reg(state, STV090x_P2_DMDISTATE, 0x5c) < 0)
goto err;
msleep(5);
- if (STV090x_WRITE_DEMOD(state, TNRCFG, 0x6c) < 0) /* check register ! (No Tuner Mode) */
+ /* Set No Tuner Mode */
+ if (stv090x_write_reg(state, STV090x_P1_TNRCFG, 0x6c) < 0)
+ goto err;
+ if (stv090x_write_reg(state, STV090x_P2_TNRCFG, 0x6c) < 0)
goto err;
+ /* I2C repeater OFF */
STV090x_SETFIELD_Px(reg, ENARPT_LEVEL_FIELD, config->repeater_level);
- if (STV090x_WRITE_DEMOD(state, I2CRPT, reg) < 0) /* repeater OFF */
+ if (stv090x_write_reg(state, STV090x_P1_I2CRPT, reg) < 0)
+ goto err;
+ if (stv090x_write_reg(state, STV090x_P2_I2CRPT, reg) < 0)
goto err;
if (stv090x_write_reg(state, STV090x_NCOARSE, 0x13) < 0) /* set PLL divider */
@@ -4216,8 +4427,8 @@ static int stv090x_setup(struct dvb_frontend *fe)
goto err;
}
- state->dev_ver = stv090x_read_reg(state, STV090x_MID);
- if (state->dev_ver >= 0x20) {
+ state->internal->dev_ver = stv090x_read_reg(state, STV090x_MID);
+ if (state->internal->dev_ver >= 0x20) {
if (stv090x_write_reg(state, STV090x_TSGENERAL, 0x0c) < 0)
goto err;
@@ -4228,27 +4439,35 @@ static int stv090x_setup(struct dvb_frontend *fe)
goto err;
}
- } else if (state->dev_ver < 0x20) {
+ } else if (state->internal->dev_ver < 0x20) {
dprintk(FE_ERROR, 1, "ERROR: Unsupported Cut: 0x%02x!",
- state->dev_ver);
+ state->internal->dev_ver);
goto err;
- } else if (state->dev_ver > 0x30) {
+ } else if (state->internal->dev_ver > 0x30) {
/* we shouldn't bail out from here */
dprintk(FE_ERROR, 1, "INFO: Cut: 0x%02x probably incomplete support!",
- state->dev_ver);
+ state->internal->dev_ver);
}
- if (stv090x_write_reg(state, STV090x_TSTRES0, 0x80) < 0)
+ /* ADC1 range */
+ reg = stv090x_read_reg(state, STV090x_TSTTNR1);
+ STV090x_SETFIELD(reg, ADC1_INMODE_FIELD,
+ (config->adc1_range == STV090x_ADC_1Vpp) ? 0 : 1);
+ if (stv090x_write_reg(state, STV090x_TSTTNR1, reg) < 0)
goto err;
- if (stv090x_write_reg(state, STV090x_TSTRES0, 0x00) < 0)
+
+ /* ADC2 range */
+ reg = stv090x_read_reg(state, STV090x_TSTTNR3);
+ STV090x_SETFIELD(reg, ADC2_INMODE_FIELD,
+ (config->adc2_range == STV090x_ADC_1Vpp) ? 0 : 1);
+ if (stv090x_write_reg(state, STV090x_TSTTNR3, reg) < 0)
goto err;
- stv090x_set_mclk(state, 135000000, config->xtal); /* 135 Mhz */
- msleep(5);
- if (stv090x_write_reg(state, STV090x_SYNTCTRL, 0x20 | config->clk_mode) < 0)
+ if (stv090x_write_reg(state, STV090x_TSTRES0, 0x80) < 0)
+ goto err;
+ if (stv090x_write_reg(state, STV090x_TSTRES0, 0x00) < 0)
goto err;
- stv090x_get_mclk(state);
return 0;
err:
@@ -4299,6 +4518,7 @@ struct dvb_frontend *stv090x_attach(const struct stv090x_config *config,
enum stv090x_demodulator demod)
{
struct stv090x_state *state = NULL;
+ struct stv090x_dev *temp_int;
state = kzalloc(sizeof (struct stv090x_state), GFP_KERNEL);
if (state == NULL)
@@ -4314,8 +4534,32 @@ struct dvb_frontend *stv090x_attach(const struct stv090x_config *config,
state->device = config->device;
state->rolloff = STV090x_RO_35; /* default */
- if (state->demod == STV090x_DEMODULATOR_0)
- mutex_init(&demod_lock);
+ temp_int = find_dev(state->i2c,
+ state->config->address);
+
+ if ((temp_int != NULL) && (state->demod_mode == STV090x_DUAL)) {
+ state->internal = temp_int->internal;
+ state->internal->num_used++;
+ dprintk(FE_INFO, 1, "Found Internal Structure!");
+ dprintk(FE_ERROR, 1, "Attaching %s demodulator(%d) Cut=0x%02x",
+ state->device == STV0900 ? "STV0900" : "STV0903",
+ demod,
+ state->internal->dev_ver);
+ return &state->frontend;
+ } else {
+ state->internal = kmalloc(sizeof(struct stv090x_internal),
+ GFP_KERNEL);
+ temp_int = append_internal(state->internal);
+ state->internal->num_used = 1;
+ state->internal->mclk = 0;
+ state->internal->dev_ver = 0;
+ state->internal->i2c_adap = state->i2c;
+ state->internal->i2c_addr = state->config->address;
+ dprintk(FE_INFO, 1, "Create New Internal Structure!");
+ }
+
+ mutex_init(&state->internal->demod_lock);
+ mutex_init(&state->internal->tuner_lock);
if (stv090x_sleep(&state->frontend) < 0) {
dprintk(FE_ERROR, 1, "Error putting device to sleep");
@@ -4331,10 +4575,10 @@ struct dvb_frontend *stv090x_attach(const struct stv090x_config *config,
goto error;
}
- dprintk(FE_ERROR, 1, "Attaching %s demodulator(%d) Cut=0x%02x\n",
+ dprintk(FE_ERROR, 1, "Attaching %s demodulator(%d) Cut=0x%02x",
state->device == STV0900 ? "STV0900" : "STV0903",
demod,
- state->dev_ver);
+ state->internal->dev_ver);
return &state->frontend;
diff --git a/drivers/media/dvb/frontends/stv090x.h b/drivers/media/dvb/frontends/stv090x.h
index b133807663ea..30f01a6902ac 100644
--- a/drivers/media/dvb/frontends/stv090x.h
+++ b/drivers/media/dvb/frontends/stv090x.h
@@ -60,6 +60,11 @@ enum stv090x_i2crpt {
STV090x_RPTLEVEL_2 = 7,
};
+enum stv090x_adc_range {
+ STV090x_ADC_2Vpp = 0,
+ STV090x_ADC_1Vpp = 1
+};
+
struct stv090x_config {
enum stv090x_device device;
enum stv090x_mode demod_mode;
@@ -68,13 +73,17 @@ struct stv090x_config {
u32 xtal; /* default: 8000000 */
u8 address; /* default: 0x68 */
- u32 ref_clk; /* default: 16000000 FIXME to tuner config */
-
u8 ts1_mode;
u8 ts2_mode;
+ u32 ts1_clk;
+ u32 ts2_clk;
enum stv090x_i2crpt repeater_level;
+ u8 tuner_bbgain; /* default: 10db */
+ enum stv090x_adc_range adc1_range; /* default: 2Vpp */
+ enum stv090x_adc_range adc2_range; /* default: 2Vpp */
+
bool diseqc_envelope_mode;
int (*tuner_init) (struct dvb_frontend *fe);
diff --git a/drivers/media/dvb/frontends/stv090x_priv.h b/drivers/media/dvb/frontends/stv090x_priv.h
index 5921a8d6c89f..5b780c80d496 100644
--- a/drivers/media/dvb/frontends/stv090x_priv.h
+++ b/drivers/media/dvb/frontends/stv090x_priv.h
@@ -230,11 +230,23 @@ struct stv090x_tab {
s32 read;
};
+struct stv090x_internal {
+ struct i2c_adapter *i2c_adap;
+ u8 i2c_addr;
+
+ struct mutex demod_lock; /* Lock access to shared register */
+ struct mutex tuner_lock; /* Lock access to tuners */
+ s32 mclk; /* Masterclock Divider factor */
+ u32 dev_ver;
+
+ int num_used;
+};
+
struct stv090x_state {
enum stv090x_device device;
enum stv090x_demodulator demod;
enum stv090x_mode demod_mode;
- u32 dev_ver;
+ struct stv090x_internal *internal;
struct i2c_adapter *i2c;
const struct stv090x_config *config;
@@ -256,11 +268,8 @@ struct stv090x_state {
u32 frequency;
u32 srate;
- s32 mclk; /* Masterclock Divider factor */
s32 tuner_bw;
- u32 tuner_refclk;
-
s32 search_range;
s32 DemodTimeout;
diff --git a/drivers/media/dvb/frontends/stv6110x.c b/drivers/media/dvb/frontends/stv6110x.c
index bcfcb652464c..f931ed07e92d 100644
--- a/drivers/media/dvb/frontends/stv6110x.c
+++ b/drivers/media/dvb/frontends/stv6110x.c
@@ -35,8 +35,6 @@ static unsigned int verbose;
module_param(verbose, int, 0644);
MODULE_PARM_DESC(verbose, "Set Verbosity level");
-static u8 stv6110x_regs[] = {0x07, 0x11, 0xdc, 0x85, 0x17, 0x01, 0xe6, 0x1e};
-
static int stv6110x_read_reg(struct stv6110x_state *stv6110x, u8 reg, u8 *data)
{
int ret;
@@ -58,12 +56,23 @@ static int stv6110x_read_reg(struct stv6110x_state *stv6110x, u8 reg, u8 *data)
return 0;
}
-static int stv6110x_write_reg(struct stv6110x_state *stv6110x, u8 reg, u8 data)
+static int stv6110x_write_regs(struct stv6110x_state *stv6110x, int start, u8 data[], int len)
{
int ret;
const struct stv6110x_config *config = stv6110x->config;
- u8 buf[] = { reg, data };
- struct i2c_msg msg = { .addr = config->addr, .flags = 0, . buf = buf, .len = 2 };
+ u8 buf[len + 1];
+ struct i2c_msg msg = {
+ .addr = config->addr,
+ .flags = 0,
+ .buf = buf,
+ .len = len + 1
+ };
+
+ if (start + len > 8)
+ return -EINVAL;
+
+ buf[0] = start;
+ memcpy(&buf[1], data, len);
ret = i2c_transfer(stv6110x->i2c, &msg, 1);
if (ret != 1) {
@@ -74,18 +83,21 @@ static int stv6110x_write_reg(struct stv6110x_state *stv6110x, u8 reg, u8 data)
return 0;
}
+static int stv6110x_write_reg(struct stv6110x_state *stv6110x, u8 reg, u8 data)
+{
+ return stv6110x_write_regs(stv6110x, reg, &data, 1);
+}
+
static int stv6110x_init(struct dvb_frontend *fe)
{
struct stv6110x_state *stv6110x = fe->tuner_priv;
int ret;
- u8 i;
- for (i = 0; i < ARRAY_SIZE(stv6110x_regs); i++) {
- ret = stv6110x_write_reg(stv6110x, i, stv6110x_regs[i]);
- if (ret < 0) {
- dprintk(FE_ERROR, 1, "Initialization failed");
- return -1;
- }
+ ret = stv6110x_write_regs(stv6110x, 0, stv6110x->regs,
+ ARRAY_SIZE(stv6110x->regs));
+ if (ret < 0) {
+ dprintk(FE_ERROR, 1, "Initialization failed");
+ return -1;
}
return 0;
@@ -98,23 +110,23 @@ static int stv6110x_set_frequency(struct dvb_frontend *fe, u32 frequency)
s32 pVal, pCalc, rDivOpt = 0, pCalcOpt = 1000;
u8 i;
- STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL1], CTRL1_K, (REFCLOCK_MHz - 16));
+ STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL1], CTRL1_K, (REFCLOCK_MHz - 16));
if (frequency <= 1023000) {
- STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_DIV4SEL, 1);
- STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_PRESC32_ON, 0);
+ STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_DIV4SEL, 1);
+ STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_PRESC32_ON, 0);
pVal = 40;
} else if (frequency <= 1300000) {
- STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_DIV4SEL, 1);
- STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_PRESC32_ON, 1);
+ STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_DIV4SEL, 1);
+ STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_PRESC32_ON, 1);
pVal = 40;
} else if (frequency <= 2046000) {
- STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_DIV4SEL, 0);
- STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_PRESC32_ON, 0);
+ STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_DIV4SEL, 0);
+ STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_PRESC32_ON, 0);
pVal = 20;
} else {
- STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_DIV4SEL, 0);
- STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_PRESC32_ON, 1);
+ STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_DIV4SEL, 0);
+ STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_PRESC32_ON, 1);
pVal = 20;
}
@@ -130,21 +142,21 @@ static int stv6110x_set_frequency(struct dvb_frontend *fe, u32 frequency)
divider = (frequency * R_DIV(rDivOpt) * pVal) / REFCLOCK_kHz;
divider = (divider + 5) / 10;
- STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_R_DIV, rDivOpt);
- STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_N_DIV_11_8, MSB(divider));
- STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG0], TNG0_N_DIV_7_0, LSB(divider));
+ STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_R_DIV, rDivOpt);
+ STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_N_DIV_11_8, MSB(divider));
+ STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG0], TNG0_N_DIV_7_0, LSB(divider));
/* VCO Auto calibration */
- STV6110x_SETFIELD(stv6110x_regs[STV6110x_STAT1], STAT1_CALVCO_STRT, 1);
+ STV6110x_SETFIELD(stv6110x->regs[STV6110x_STAT1], STAT1_CALVCO_STRT, 1);
- stv6110x_write_reg(stv6110x, STV6110x_CTRL1, stv6110x_regs[STV6110x_CTRL1]);
- stv6110x_write_reg(stv6110x, STV6110x_TNG1, stv6110x_regs[STV6110x_TNG1]);
- stv6110x_write_reg(stv6110x, STV6110x_TNG0, stv6110x_regs[STV6110x_TNG0]);
- stv6110x_write_reg(stv6110x, STV6110x_STAT1, stv6110x_regs[STV6110x_STAT1]);
+ stv6110x_write_reg(stv6110x, STV6110x_CTRL1, stv6110x->regs[STV6110x_CTRL1]);
+ stv6110x_write_reg(stv6110x, STV6110x_TNG1, stv6110x->regs[STV6110x_TNG1]);
+ stv6110x_write_reg(stv6110x, STV6110x_TNG0, stv6110x->regs[STV6110x_TNG0]);
+ stv6110x_write_reg(stv6110x, STV6110x_STAT1, stv6110x->regs[STV6110x_STAT1]);
for (i = 0; i < TRIALS; i++) {
- stv6110x_read_reg(stv6110x, STV6110x_STAT1, &stv6110x_regs[STV6110x_STAT1]);
- if (!STV6110x_GETFIELD(STAT1_CALVCO_STRT, stv6110x_regs[STV6110x_STAT1]))
+ stv6110x_read_reg(stv6110x, STV6110x_STAT1, &stv6110x->regs[STV6110x_STAT1]);
+ if (!STV6110x_GETFIELD(STAT1_CALVCO_STRT, stv6110x->regs[STV6110x_STAT1]))
break;
msleep(1);
}
@@ -156,14 +168,14 @@ static int stv6110x_get_frequency(struct dvb_frontend *fe, u32 *frequency)
{
struct stv6110x_state *stv6110x = fe->tuner_priv;
- stv6110x_read_reg(stv6110x, STV6110x_TNG1, &stv6110x_regs[STV6110x_TNG1]);
- stv6110x_read_reg(stv6110x, STV6110x_TNG0, &stv6110x_regs[STV6110x_TNG0]);
+ stv6110x_read_reg(stv6110x, STV6110x_TNG1, &stv6110x->regs[STV6110x_TNG1]);
+ stv6110x_read_reg(stv6110x, STV6110x_TNG0, &stv6110x->regs[STV6110x_TNG0]);
- *frequency = (MAKEWORD16(STV6110x_GETFIELD(TNG1_N_DIV_11_8, stv6110x_regs[STV6110x_TNG1]),
- STV6110x_GETFIELD(TNG0_N_DIV_7_0, stv6110x_regs[STV6110x_TNG0]))) * REFCLOCK_kHz;
+ *frequency = (MAKEWORD16(STV6110x_GETFIELD(TNG1_N_DIV_11_8, stv6110x->regs[STV6110x_TNG1]),
+ STV6110x_GETFIELD(TNG0_N_DIV_7_0, stv6110x->regs[STV6110x_TNG0]))) * REFCLOCK_kHz;
- *frequency /= (1 << (STV6110x_GETFIELD(TNG1_R_DIV, stv6110x_regs[STV6110x_TNG1]) +
- STV6110x_GETFIELD(TNG1_DIV4SEL, stv6110x_regs[STV6110x_TNG1])));
+ *frequency /= (1 << (STV6110x_GETFIELD(TNG1_R_DIV, stv6110x->regs[STV6110x_TNG1]) +
+ STV6110x_GETFIELD(TNG1_DIV4SEL, stv6110x->regs[STV6110x_TNG1])));
*frequency >>= 2;
@@ -179,27 +191,27 @@ static int stv6110x_set_bandwidth(struct dvb_frontend *fe, u32 bandwidth)
halfbw = bandwidth >> 1;
if (halfbw > 36000000)
- STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL3], CTRL3_CF, 31); /* LPF */
+ STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL3], CTRL3_CF, 31); /* LPF */
else if (halfbw < 5000000)
- STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL3], CTRL3_CF, 0); /* LPF */
+ STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL3], CTRL3_CF, 0); /* LPF */
else
- STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL3], CTRL3_CF, ((halfbw / 1000000) - 5)); /* LPF */
+ STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL3], CTRL3_CF, ((halfbw / 1000000) - 5)); /* LPF */
- STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL3], CTRL3_RCCLK_OFF, 0x0); /* cal. clk activated */
- STV6110x_SETFIELD(stv6110x_regs[STV6110x_STAT1], STAT1_CALRC_STRT, 0x1); /* LPF auto cal */
+ STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL3], CTRL3_RCCLK_OFF, 0x0); /* cal. clk activated */
+ STV6110x_SETFIELD(stv6110x->regs[STV6110x_STAT1], STAT1_CALRC_STRT, 0x1); /* LPF auto cal */
- stv6110x_write_reg(stv6110x, STV6110x_CTRL3, stv6110x_regs[STV6110x_CTRL3]);
- stv6110x_write_reg(stv6110x, STV6110x_STAT1, stv6110x_regs[STV6110x_STAT1]);
+ stv6110x_write_reg(stv6110x, STV6110x_CTRL3, stv6110x->regs[STV6110x_CTRL3]);
+ stv6110x_write_reg(stv6110x, STV6110x_STAT1, stv6110x->regs[STV6110x_STAT1]);
for (i = 0; i < TRIALS; i++) {
- stv6110x_read_reg(stv6110x, STV6110x_STAT1, &stv6110x_regs[STV6110x_STAT1]);
- if (!STV6110x_GETFIELD(STAT1_CALRC_STRT, stv6110x_regs[STV6110x_STAT1]))
+ stv6110x_read_reg(stv6110x, STV6110x_STAT1, &stv6110x->regs[STV6110x_STAT1]);
+ if (!STV6110x_GETFIELD(STAT1_CALRC_STRT, stv6110x->regs[STV6110x_STAT1]))
break;
msleep(1);
}
- STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL3], CTRL3_RCCLK_OFF, 0x1); /* cal. done */
- stv6110x_write_reg(stv6110x, STV6110x_CTRL3, stv6110x_regs[STV6110x_CTRL3]);
+ STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL3], CTRL3_RCCLK_OFF, 0x1); /* cal. done */
+ stv6110x_write_reg(stv6110x, STV6110x_CTRL3, stv6110x->regs[STV6110x_CTRL3]);
return 0;
}
@@ -208,8 +220,8 @@ static int stv6110x_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
{
struct stv6110x_state *stv6110x = fe->tuner_priv;
- stv6110x_read_reg(stv6110x, STV6110x_CTRL3, &stv6110x_regs[STV6110x_CTRL3]);
- *bandwidth = (STV6110x_GETFIELD(CTRL3_CF, stv6110x_regs[STV6110x_CTRL3]) + 5) * 2000000;
+ stv6110x_read_reg(stv6110x, STV6110x_CTRL3, &stv6110x->regs[STV6110x_CTRL3]);
+ *bandwidth = (STV6110x_GETFIELD(CTRL3_CF, stv6110x->regs[STV6110x_CTRL3]) + 5) * 2000000;
return 0;
}
@@ -222,20 +234,20 @@ static int stv6110x_set_refclock(struct dvb_frontend *fe, u32 refclock)
switch (refclock) {
default:
case 1:
- STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL2], CTRL2_CO_DIV, 0);
+ STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 0);
break;
case 2:
- STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL2], CTRL2_CO_DIV, 1);
+ STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 1);
break;
case 4:
- STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL2], CTRL2_CO_DIV, 2);
+ STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 2);
break;
case 8:
case 0:
- STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL2], CTRL2_CO_DIV, 3);
+ STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 3);
break;
}
- stv6110x_write_reg(stv6110x, STV6110x_CTRL2, stv6110x_regs[STV6110x_CTRL2]);
+ stv6110x_write_reg(stv6110x, STV6110x_CTRL2, stv6110x->regs[STV6110x_CTRL2]);
return 0;
}
@@ -244,8 +256,8 @@ static int stv6110x_get_bbgain(struct dvb_frontend *fe, u32 *gain)
{
struct stv6110x_state *stv6110x = fe->tuner_priv;
- stv6110x_read_reg(stv6110x, STV6110x_CTRL2, &stv6110x_regs[STV6110x_CTRL2]);
- *gain = 2 * STV6110x_GETFIELD(CTRL2_BBGAIN, stv6110x_regs[STV6110x_CTRL2]);
+ stv6110x_read_reg(stv6110x, STV6110x_CTRL2, &stv6110x->regs[STV6110x_CTRL2]);
+ *gain = 2 * STV6110x_GETFIELD(CTRL2_BBGAIN, stv6110x->regs[STV6110x_CTRL2]);
return 0;
}
@@ -254,8 +266,8 @@ static int stv6110x_set_bbgain(struct dvb_frontend *fe, u32 gain)
{
struct stv6110x_state *stv6110x = fe->tuner_priv;
- STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL2], CTRL2_BBGAIN, gain / 2);
- stv6110x_write_reg(stv6110x, STV6110x_CTRL2, stv6110x_regs[STV6110x_CTRL2]);
+ STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_BBGAIN, gain / 2);
+ stv6110x_write_reg(stv6110x, STV6110x_CTRL2, stv6110x->regs[STV6110x_CTRL2]);
return 0;
}
@@ -267,19 +279,19 @@ static int stv6110x_set_mode(struct dvb_frontend *fe, enum tuner_mode mode)
switch (mode) {
case TUNER_SLEEP:
- STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL1], CTRL1_SYN, 0);
- STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL1], CTRL1_RX, 0);
- STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL1], CTRL1_LPT, 0);
+ STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL1], CTRL1_SYN, 0);
+ STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL1], CTRL1_RX, 0);
+ STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL1], CTRL1_LPT, 0);
break;
case TUNER_WAKE:
- STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL1], CTRL1_SYN, 1);
- STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL1], CTRL1_RX, 1);
- STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL1], CTRL1_LPT, 1);
+ STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL1], CTRL1_SYN, 1);
+ STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL1], CTRL1_RX, 1);
+ STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL1], CTRL1_LPT, 1);
break;
}
- ret = stv6110x_write_reg(stv6110x, STV6110x_CTRL1, stv6110x_regs[STV6110x_CTRL1]);
+ ret = stv6110x_write_reg(stv6110x, STV6110x_CTRL1, stv6110x->regs[STV6110x_CTRL1]);
if (ret < 0) {
dprintk(FE_ERROR, 1, "I/O Error");
return -EIO;
@@ -297,9 +309,9 @@ static int stv6110x_get_status(struct dvb_frontend *fe, u32 *status)
{
struct stv6110x_state *stv6110x = fe->tuner_priv;
- stv6110x_read_reg(stv6110x, STV6110x_STAT1, &stv6110x_regs[STV6110x_STAT1]);
+ stv6110x_read_reg(stv6110x, STV6110x_STAT1, &stv6110x->regs[STV6110x_STAT1]);
- if (STV6110x_GETFIELD(STAT1_LOCK, stv6110x_regs[STV6110x_STAT1]))
+ if (STV6110x_GETFIELD(STAT1_LOCK, stv6110x->regs[STV6110x_STAT1]))
*status = TUNER_PHASELOCKED;
else
*status = 0;
@@ -349,6 +361,8 @@ struct stv6110x_devctl *stv6110x_attach(struct dvb_frontend *fe,
struct i2c_adapter *i2c)
{
struct stv6110x_state *stv6110x;
+ u8 default_regs[] = {0x07, 0x11, 0xdc, 0x85, 0x17, 0x01, 0xe6, 0x1e};
+ int ret;
stv6110x = kzalloc(sizeof (struct stv6110x_state), GFP_KERNEL);
if (stv6110x == NULL)
@@ -357,6 +371,44 @@ struct stv6110x_devctl *stv6110x_attach(struct dvb_frontend *fe,
stv6110x->i2c = i2c;
stv6110x->config = config;
stv6110x->devctl = &stv6110x_ctl;
+ memcpy(stv6110x->regs, default_regs, 8);
+
+ /* setup divider */
+ switch (stv6110x->config->clk_div) {
+ default:
+ case 1:
+ STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 0);
+ break;
+ case 2:
+ STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 1);
+ break;
+ case 4:
+ STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 2);
+ break;
+ case 8:
+ case 0:
+ STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 3);
+ break;
+ }
+
+ if (fe->ops.i2c_gate_ctrl) {
+ ret = fe->ops.i2c_gate_ctrl(fe, 1);
+ if (ret < 0)
+ goto error;
+ }
+
+ ret = stv6110x_write_regs(stv6110x, 0, stv6110x->regs,
+ ARRAY_SIZE(stv6110x->regs));
+ if (ret < 0) {
+ dprintk(FE_ERROR, 1, "Initialization failed");
+ goto error;
+ }
+
+ if (fe->ops.i2c_gate_ctrl) {
+ ret = fe->ops.i2c_gate_ctrl(fe, 0);
+ if (ret < 0)
+ goto error;
+ }
fe->tuner_priv = stv6110x;
fe->ops.tuner_ops = stv6110x_ops;
diff --git a/drivers/media/dvb/frontends/stv6110x.h b/drivers/media/dvb/frontends/stv6110x.h
index a38257080e01..2429ae6d7847 100644
--- a/drivers/media/dvb/frontends/stv6110x.h
+++ b/drivers/media/dvb/frontends/stv6110x.h
@@ -26,6 +26,7 @@
struct stv6110x_config {
u8 addr;
u32 refclk;
+ u8 clk_div; /* divisor value for the output clock */
};
enum tuner_mode {
diff --git a/drivers/media/dvb/frontends/stv6110x_priv.h b/drivers/media/dvb/frontends/stv6110x_priv.h
index 7260da633d49..0ec936a660a7 100644
--- a/drivers/media/dvb/frontends/stv6110x_priv.h
+++ b/drivers/media/dvb/frontends/stv6110x_priv.h
@@ -68,6 +68,7 @@
struct stv6110x_state {
struct i2c_adapter *i2c;
const struct stv6110x_config *config;
+ u8 regs[8];
struct stv6110x_devctl *devctl;
};
diff --git a/drivers/media/dvb/frontends/tda665x.c b/drivers/media/dvb/frontends/tda665x.c
index 87d52739c828..c44fefe92d97 100644
--- a/drivers/media/dvb/frontends/tda665x.c
+++ b/drivers/media/dvb/frontends/tda665x.c
@@ -133,7 +133,7 @@ static int tda665x_set_state(struct dvb_frontend *fe,
frequency += config->ref_divider >> 1;
frequency /= config->ref_divider;
- buf[0] = (u8) (frequency & 0x7f00) >> 8;
+ buf[0] = (u8) ((frequency & 0x7f00) >> 8);
buf[1] = (u8) (frequency & 0x00ff) >> 0;
buf[2] = 0x80 | 0x40 | 0x02;
buf[3] = 0x00;
diff --git a/drivers/media/dvb/frontends/tda8261.c b/drivers/media/dvb/frontends/tda8261.c
index 320c3c36d8b2..614afcec05f1 100644
--- a/drivers/media/dvb/frontends/tda8261.c
+++ b/drivers/media/dvb/frontends/tda8261.c
@@ -39,7 +39,7 @@ static int tda8261_read(struct tda8261_state *state, u8 *buf)
{
const struct tda8261_config *config = state->config;
int err = 0;
- struct i2c_msg msg = { .addr = config->addr, .flags = I2C_M_RD,.buf = buf, .len = 2 };
+ struct i2c_msg msg = { .addr = config->addr, .flags = I2C_M_RD,.buf = buf, .len = 1 };
if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1)
printk("%s: read error, err=%d\n", __func__, err);
diff --git a/drivers/media/dvb/frontends/zl10036.c b/drivers/media/dvb/frontends/zl10036.c
index 4e814ff22b23..34c5de491d2b 100644
--- a/drivers/media/dvb/frontends/zl10036.c
+++ b/drivers/media/dvb/frontends/zl10036.c
@@ -411,7 +411,7 @@ static int zl10036_init_regs(struct zl10036_state *state)
state->bf = 0xff;
if (!state->config->rf_loop_enable)
- zl10036_init_tab[1][2] |= 0x01;
+ zl10036_init_tab[1][0] |= 0x01;
deb_info("%s\n", __func__);
diff --git a/drivers/media/dvb/frontends/zl10039.c b/drivers/media/dvb/frontends/zl10039.c
index 11b29cb883e6..c085e58a94bf 100644
--- a/drivers/media/dvb/frontends/zl10039.c
+++ b/drivers/media/dvb/frontends/zl10039.c
@@ -287,7 +287,6 @@ struct dvb_frontend *zl10039_attach(struct dvb_frontend *fe,
break;
default:
dprintk("Chip ID=%x does not match a known type\n", state->id);
- break;
goto error;
}
diff --git a/drivers/media/dvb/mantis/mantis_hif.c b/drivers/media/dvb/mantis/mantis_hif.c
index 7477dac628b4..5772ebb3a69e 100644
--- a/drivers/media/dvb/mantis/mantis_hif.c
+++ b/drivers/media/dvb/mantis/mantis_hif.c
@@ -22,8 +22,6 @@
#include <linux/signal.h>
#include <linux/sched.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
#include <linux/interrupt.h>
#include "dmxdev.h"
diff --git a/drivers/media/dvb/mantis/mantis_input.c b/drivers/media/dvb/mantis/mantis_input.c
index 6a9df779441f..4675a3b53c7d 100644
--- a/drivers/media/dvb/mantis/mantis_input.c
+++ b/drivers/media/dvb/mantis/mantis_input.c
@@ -126,7 +126,7 @@ int mantis_input_init(struct mantis_pci *mantis)
rc->id.version = 1;
rc->dev = mantis->pdev->dev;
- err = ir_input_register(rc, &ir_mantis);
+ err = ir_input_register(rc, &ir_mantis, NULL);
if (err) {
dprintk(MANTIS_ERROR, 1, "IR device registration failed, ret = %d", err);
input_free_device(rc);
diff --git a/drivers/media/dvb/mantis/mantis_pci.c b/drivers/media/dvb/mantis/mantis_pci.c
index 6c7534af6b44..59feeb84aec7 100644
--- a/drivers/media/dvb/mantis/mantis_pci.c
+++ b/drivers/media/dvb/mantis/mantis_pci.c
@@ -41,11 +41,6 @@
#include "dvb_frontend.h"
#include "dvb_net.h"
-#include <asm/irq.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-
#include "mantis_common.h"
#include "mantis_reg.h"
#include "mantis_pci.h"
diff --git a/drivers/media/dvb/ngene/Kconfig b/drivers/media/dvb/ngene/Kconfig
new file mode 100644
index 000000000000..3ec8e6fcbb1d
--- /dev/null
+++ b/drivers/media/dvb/ngene/Kconfig
@@ -0,0 +1,9 @@
+config DVB_NGENE
+ tristate "Micronas nGene support"
+ depends on DVB_CORE && PCI && I2C
+ select DVB_LNBP21 if !DVB_FE_CUSTOMISE
+ select DVB_STV6110x if !DVB_FE_CUSTOMISE
+ select DVB_STV090x if !DVB_FE_CUSTOMISE
+ ---help---
+ Support for Micronas PCI express cards with nGene bridge.
+
diff --git a/drivers/media/dvb/ngene/Makefile b/drivers/media/dvb/ngene/Makefile
new file mode 100644
index 000000000000..40435cad4819
--- /dev/null
+++ b/drivers/media/dvb/ngene/Makefile
@@ -0,0 +1,11 @@
+#
+# Makefile for the nGene device driver
+#
+
+ngene-objs := ngene-core.o
+
+obj-$(CONFIG_DVB_NGENE) += ngene.o
+
+EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/
+EXTRA_CFLAGS += -Idrivers/media/dvb/frontends/
+
diff --git a/drivers/media/dvb/ngene/ngene-core.c b/drivers/media/dvb/ngene/ngene-core.c
new file mode 100644
index 000000000000..0150dfe7cfbb
--- /dev/null
+++ b/drivers/media/dvb/ngene/ngene-core.c
@@ -0,0 +1,2024 @@
+/*
+ * ngene.c: nGene PCIe bridge driver
+ *
+ * Copyright (C) 2005-2007 Micronas
+ *
+ * Copyright (C) 2008-2009 Ralph Metzler <rjkm@metzlerbros.de>
+ * Modifications for new nGene firmware,
+ * support for EEPROM-copying,
+ * support for new dual DVB-S2 card prototype
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 only, as published by the Free Software Foundation.
+ *
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/poll.h>
+#include <linux/io.h>
+#include <asm/div64.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/smp_lock.h>
+#include <linux/timer.h>
+#include <linux/version.h>
+#include <linux/byteorder/generic.h>
+#include <linux/firmware.h>
+#include <linux/vmalloc.h>
+
+#include "ngene.h"
+
+#include "stv6110x.h"
+#include "stv090x.h"
+#include "lnbh24.h"
+
+static int one_adapter = 1;
+module_param(one_adapter, int, 0444);
+MODULE_PARM_DESC(one_adapter, "Use only one adapter.");
+
+
+static int debug;
+module_param(debug, int, 0444);
+MODULE_PARM_DESC(debug, "Print debugging information.");
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+#define COMMAND_TIMEOUT_WORKAROUND
+
+#define dprintk if (debug) printk
+
+#define DEVICE_NAME "ngene"
+
+#define ngwriteb(dat, adr) writeb((dat), (char *)(dev->iomem + (adr)))
+#define ngwritel(dat, adr) writel((dat), (char *)(dev->iomem + (adr)))
+#define ngwriteb(dat, adr) writeb((dat), (char *)(dev->iomem + (adr)))
+#define ngreadl(adr) readl(dev->iomem + (adr))
+#define ngreadb(adr) readb(dev->iomem + (adr))
+#define ngcpyto(adr, src, count) memcpy_toio((char *) \
+ (dev->iomem + (adr)), (src), (count))
+#define ngcpyfrom(dst, adr, count) memcpy_fromio((dst), (char *) \
+ (dev->iomem + (adr)), (count))
+
+/****************************************************************************/
+/* nGene interrupt handler **************************************************/
+/****************************************************************************/
+
+static void event_tasklet(unsigned long data)
+{
+ struct ngene *dev = (struct ngene *)data;
+
+ while (dev->EventQueueReadIndex != dev->EventQueueWriteIndex) {
+ struct EVENT_BUFFER Event =
+ dev->EventQueue[dev->EventQueueReadIndex];
+ dev->EventQueueReadIndex =
+ (dev->EventQueueReadIndex + 1) & (EVENT_QUEUE_SIZE - 1);
+
+ if ((Event.UARTStatus & 0x01) && (dev->TxEventNotify))
+ dev->TxEventNotify(dev, Event.TimeStamp);
+ if ((Event.UARTStatus & 0x02) && (dev->RxEventNotify))
+ dev->RxEventNotify(dev, Event.TimeStamp,
+ Event.RXCharacter);
+ }
+}
+
+static void demux_tasklet(unsigned long data)
+{
+ struct ngene_channel *chan = (struct ngene_channel *)data;
+ struct SBufferHeader *Cur = chan->nextBuffer;
+
+ spin_lock_irq(&chan->state_lock);
+
+ while (Cur->ngeneBuffer.SR.Flags & 0x80) {
+ if (chan->mode & NGENE_IO_TSOUT) {
+ u32 Flags = chan->DataFormatFlags;
+ if (Cur->ngeneBuffer.SR.Flags & 0x20)
+ Flags |= BEF_OVERFLOW;
+ if (chan->pBufferExchange) {
+ if (!chan->pBufferExchange(chan,
+ Cur->Buffer1,
+ chan->Capture1Length,
+ Cur->ngeneBuffer.SR.
+ Clock, Flags)) {
+ /*
+ We didn't get data
+ Clear in service flag to make sure we
+ get called on next interrupt again.
+ leave fill/empty (0x80) flag alone
+ to avoid hardware running out of
+ buffers during startup, we hold only
+ in run state ( the source may be late
+ delivering data )
+ */
+
+ if (chan->HWState == HWSTATE_RUN) {
+ Cur->ngeneBuffer.SR.Flags &=
+ ~0x40;
+ break;
+ /* Stop proccessing stream */
+ }
+ } else {
+ /* We got a valid buffer,
+ so switch to run state */
+ chan->HWState = HWSTATE_RUN;
+ }
+ } else {
+ printk(KERN_ERR DEVICE_NAME ": OOPS\n");
+ if (chan->HWState == HWSTATE_RUN) {
+ Cur->ngeneBuffer.SR.Flags &= ~0x40;
+ break; /* Stop proccessing stream */
+ }
+ }
+ if (chan->AudioDTOUpdated) {
+ printk(KERN_INFO DEVICE_NAME
+ ": Update AudioDTO = %d\n",
+ chan->AudioDTOValue);
+ Cur->ngeneBuffer.SR.DTOUpdate =
+ chan->AudioDTOValue;
+ chan->AudioDTOUpdated = 0;
+ }
+ } else {
+ if (chan->HWState == HWSTATE_RUN) {
+ u32 Flags = 0;
+ if (Cur->ngeneBuffer.SR.Flags & 0x01)
+ Flags |= BEF_EVEN_FIELD;
+ if (Cur->ngeneBuffer.SR.Flags & 0x20)
+ Flags |= BEF_OVERFLOW;
+ if (chan->pBufferExchange)
+ chan->pBufferExchange(chan,
+ Cur->Buffer1,
+ chan->
+ Capture1Length,
+ Cur->ngeneBuffer.
+ SR.Clock, Flags);
+ if (chan->pBufferExchange2)
+ chan->pBufferExchange2(chan,
+ Cur->Buffer2,
+ chan->
+ Capture2Length,
+ Cur->ngeneBuffer.
+ SR.Clock, Flags);
+ } else if (chan->HWState != HWSTATE_STOP)
+ chan->HWState = HWSTATE_RUN;
+ }
+ Cur->ngeneBuffer.SR.Flags = 0x00;
+ Cur = Cur->Next;
+ }
+ chan->nextBuffer = Cur;
+
+ spin_unlock_irq(&chan->state_lock);
+}
+
+static irqreturn_t irq_handler(int irq, void *dev_id)
+{
+ struct ngene *dev = (struct ngene *)dev_id;
+ u32 icounts = 0;
+ irqreturn_t rc = IRQ_NONE;
+ u32 i = MAX_STREAM;
+ u8 *tmpCmdDoneByte;
+
+ if (dev->BootFirmware) {
+ icounts = ngreadl(NGENE_INT_COUNTS);
+ if (icounts != dev->icounts) {
+ ngwritel(0, FORCE_NMI);
+ dev->cmd_done = 1;
+ wake_up(&dev->cmd_wq);
+ dev->icounts = icounts;
+ rc = IRQ_HANDLED;
+ }
+ return rc;
+ }
+
+ ngwritel(0, FORCE_NMI);
+
+ spin_lock(&dev->cmd_lock);
+ tmpCmdDoneByte = dev->CmdDoneByte;
+ if (tmpCmdDoneByte &&
+ (*tmpCmdDoneByte ||
+ (dev->ngenetohost[0] == 1 && dev->ngenetohost[1] != 0))) {
+ dev->CmdDoneByte = NULL;
+ dev->cmd_done = 1;
+ wake_up(&dev->cmd_wq);
+ rc = IRQ_HANDLED;
+ }
+ spin_unlock(&dev->cmd_lock);
+
+ if (dev->EventBuffer->EventStatus & 0x80) {
+ u8 nextWriteIndex =
+ (dev->EventQueueWriteIndex + 1) &
+ (EVENT_QUEUE_SIZE - 1);
+ if (nextWriteIndex != dev->EventQueueReadIndex) {
+ dev->EventQueue[dev->EventQueueWriteIndex] =
+ *(dev->EventBuffer);
+ dev->EventQueueWriteIndex = nextWriteIndex;
+ } else {
+ printk(KERN_ERR DEVICE_NAME ": event overflow\n");
+ dev->EventQueueOverflowCount += 1;
+ dev->EventQueueOverflowFlag = 1;
+ }
+ dev->EventBuffer->EventStatus &= ~0x80;
+ tasklet_schedule(&dev->event_tasklet);
+ rc = IRQ_HANDLED;
+ }
+
+ while (i > 0) {
+ i--;
+ spin_lock(&dev->channel[i].state_lock);
+ /* if (dev->channel[i].State>=KSSTATE_RUN) { */
+ if (dev->channel[i].nextBuffer) {
+ if ((dev->channel[i].nextBuffer->
+ ngeneBuffer.SR.Flags & 0xC0) == 0x80) {
+ dev->channel[i].nextBuffer->
+ ngeneBuffer.SR.Flags |= 0x40;
+ tasklet_schedule(
+ &dev->channel[i].demux_tasklet);
+ rc = IRQ_HANDLED;
+ }
+ }
+ spin_unlock(&dev->channel[i].state_lock);
+ }
+
+ /* Request might have been processed by a previous call. */
+ return IRQ_HANDLED;
+}
+
+/****************************************************************************/
+/* nGene command interface **************************************************/
+/****************************************************************************/
+
+static void dump_command_io(struct ngene *dev)
+{
+ u8 buf[8], *b;
+
+ ngcpyfrom(buf, HOST_TO_NGENE, 8);
+ printk(KERN_ERR "host_to_ngene (%04x): %02x %02x %02x %02x %02x %02x %02x %02x\n",
+ HOST_TO_NGENE, buf[0], buf[1], buf[2], buf[3],
+ buf[4], buf[5], buf[6], buf[7]);
+
+ ngcpyfrom(buf, NGENE_TO_HOST, 8);
+ printk(KERN_ERR "ngene_to_host (%04x): %02x %02x %02x %02x %02x %02x %02x %02x\n",
+ NGENE_TO_HOST, buf[0], buf[1], buf[2], buf[3],
+ buf[4], buf[5], buf[6], buf[7]);
+
+ b = dev->hosttongene;
+ printk(KERN_ERR "dev->hosttongene (%p): %02x %02x %02x %02x %02x %02x %02x %02x\n",
+ b, b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]);
+
+ b = dev->ngenetohost;
+ printk(KERN_ERR "dev->ngenetohost (%p): %02x %02x %02x %02x %02x %02x %02x %02x\n",
+ b, b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]);
+}
+
+static int ngene_command_mutex(struct ngene *dev, struct ngene_command *com)
+{
+ int ret;
+ u8 *tmpCmdDoneByte;
+
+ dev->cmd_done = 0;
+
+ if (com->cmd.hdr.Opcode == CMD_FWLOAD_PREPARE) {
+ dev->BootFirmware = 1;
+ dev->icounts = ngreadl(NGENE_INT_COUNTS);
+ ngwritel(0, NGENE_COMMAND);
+ ngwritel(0, NGENE_COMMAND_HI);
+ ngwritel(0, NGENE_STATUS);
+ ngwritel(0, NGENE_STATUS_HI);
+ ngwritel(0, NGENE_EVENT);
+ ngwritel(0, NGENE_EVENT_HI);
+ } else if (com->cmd.hdr.Opcode == CMD_FWLOAD_FINISH) {
+ u64 fwio = dev->PAFWInterfaceBuffer;
+
+ ngwritel(fwio & 0xffffffff, NGENE_COMMAND);
+ ngwritel(fwio >> 32, NGENE_COMMAND_HI);
+ ngwritel((fwio + 256) & 0xffffffff, NGENE_STATUS);
+ ngwritel((fwio + 256) >> 32, NGENE_STATUS_HI);
+ ngwritel((fwio + 512) & 0xffffffff, NGENE_EVENT);
+ ngwritel((fwio + 512) >> 32, NGENE_EVENT_HI);
+ }
+
+ memcpy(dev->FWInterfaceBuffer, com->cmd.raw8, com->in_len + 2);
+
+ if (dev->BootFirmware)
+ ngcpyto(HOST_TO_NGENE, com->cmd.raw8, com->in_len + 2);
+
+ spin_lock_irq(&dev->cmd_lock);
+ tmpCmdDoneByte = dev->ngenetohost + com->out_len;
+ if (!com->out_len)
+ tmpCmdDoneByte++;
+ *tmpCmdDoneByte = 0;
+ dev->ngenetohost[0] = 0;
+ dev->ngenetohost[1] = 0;
+ dev->CmdDoneByte = tmpCmdDoneByte;
+ spin_unlock_irq(&dev->cmd_lock);
+
+ /* Notify 8051. */
+ ngwritel(1, FORCE_INT);
+
+ ret = wait_event_timeout(dev->cmd_wq, dev->cmd_done == 1, 2 * HZ);
+ if (!ret) {
+ /*ngwritel(0, FORCE_NMI);*/
+
+ printk(KERN_ERR DEVICE_NAME
+ ": Command timeout cmd=%02x prev=%02x\n",
+ com->cmd.hdr.Opcode, dev->prev_cmd);
+ dump_command_io(dev);
+ return -1;
+ }
+ if (com->cmd.hdr.Opcode == CMD_FWLOAD_FINISH)
+ dev->BootFirmware = 0;
+
+ dev->prev_cmd = com->cmd.hdr.Opcode;
+
+ if (!com->out_len)
+ return 0;
+
+ memcpy(com->cmd.raw8, dev->ngenetohost, com->out_len);
+
+ return 0;
+}
+
+static int ngene_command(struct ngene *dev, struct ngene_command *com)
+{
+ int result;
+
+ down(&dev->cmd_mutex);
+ result = ngene_command_mutex(dev, com);
+ up(&dev->cmd_mutex);
+ return result;
+}
+
+
+static int ngene_command_i2c_read(struct ngene *dev, u8 adr,
+ u8 *out, u8 outlen, u8 *in, u8 inlen, int flag)
+{
+ struct ngene_command com;
+
+ com.cmd.hdr.Opcode = CMD_I2C_READ;
+ com.cmd.hdr.Length = outlen + 3;
+ com.cmd.I2CRead.Device = adr << 1;
+ memcpy(com.cmd.I2CRead.Data, out, outlen);
+ com.cmd.I2CRead.Data[outlen] = inlen;
+ com.cmd.I2CRead.Data[outlen + 1] = 0;
+ com.in_len = outlen + 3;
+ com.out_len = inlen + 1;
+
+ if (ngene_command(dev, &com) < 0)
+ return -EIO;
+
+ if ((com.cmd.raw8[0] >> 1) != adr)
+ return -EIO;
+
+ if (flag)
+ memcpy(in, com.cmd.raw8, inlen + 1);
+ else
+ memcpy(in, com.cmd.raw8 + 1, inlen);
+ return 0;
+}
+
+static int ngene_command_i2c_write(struct ngene *dev, u8 adr,
+ u8 *out, u8 outlen)
+{
+ struct ngene_command com;
+
+
+ com.cmd.hdr.Opcode = CMD_I2C_WRITE;
+ com.cmd.hdr.Length = outlen + 1;
+ com.cmd.I2CRead.Device = adr << 1;
+ memcpy(com.cmd.I2CRead.Data, out, outlen);
+ com.in_len = outlen + 1;
+ com.out_len = 1;
+
+ if (ngene_command(dev, &com) < 0)
+ return -EIO;
+
+ if (com.cmd.raw8[0] == 1)
+ return -EIO;
+
+ return 0;
+}
+
+static int ngene_command_load_firmware(struct ngene *dev,
+ u8 *ngene_fw, u32 size)
+{
+#define FIRSTCHUNK (1024)
+ u32 cleft;
+ struct ngene_command com;
+
+ com.cmd.hdr.Opcode = CMD_FWLOAD_PREPARE;
+ com.cmd.hdr.Length = 0;
+ com.in_len = 0;
+ com.out_len = 0;
+
+ ngene_command(dev, &com);
+
+ cleft = (size + 3) & ~3;
+ if (cleft > FIRSTCHUNK) {
+ ngcpyto(PROGRAM_SRAM + FIRSTCHUNK, ngene_fw + FIRSTCHUNK,
+ cleft - FIRSTCHUNK);
+ cleft = FIRSTCHUNK;
+ }
+ ngcpyto(DATA_FIFO_AREA, ngene_fw, cleft);
+
+ memset(&com, 0, sizeof(struct ngene_command));
+ com.cmd.hdr.Opcode = CMD_FWLOAD_FINISH;
+ com.cmd.hdr.Length = 4;
+ com.cmd.FWLoadFinish.Address = DATA_FIFO_AREA;
+ com.cmd.FWLoadFinish.Length = (unsigned short)cleft;
+ com.in_len = 4;
+ com.out_len = 0;
+
+ return ngene_command(dev, &com);
+}
+
+
+static int ngene_command_config_buf(struct ngene *dev, u8 config)
+{
+ struct ngene_command com;
+
+ com.cmd.hdr.Opcode = CMD_CONFIGURE_BUFFER;
+ com.cmd.hdr.Length = 1;
+ com.cmd.ConfigureBuffers.config = config;
+ com.in_len = 1;
+ com.out_len = 0;
+
+ if (ngene_command(dev, &com) < 0)
+ return -EIO;
+ return 0;
+}
+
+static int ngene_command_config_free_buf(struct ngene *dev, u8 *config)
+{
+ struct ngene_command com;
+
+ com.cmd.hdr.Opcode = CMD_CONFIGURE_FREE_BUFFER;
+ com.cmd.hdr.Length = 6;
+ memcpy(&com.cmd.ConfigureBuffers.config, config, 6);
+ com.in_len = 6;
+ com.out_len = 0;
+
+ if (ngene_command(dev, &com) < 0)
+ return -EIO;
+
+ return 0;
+}
+
+static int ngene_command_gpio_set(struct ngene *dev, u8 select, u8 level)
+{
+ struct ngene_command com;
+
+ com.cmd.hdr.Opcode = CMD_SET_GPIO_PIN;
+ com.cmd.hdr.Length = 1;
+ com.cmd.SetGpioPin.select = select | (level << 7);
+ com.in_len = 1;
+ com.out_len = 0;
+
+ return ngene_command(dev, &com);
+}
+
+
+/*
+ 02000640 is sample on rising edge.
+ 02000740 is sample on falling edge.
+ 02000040 is ignore "valid" signal
+
+ 0: FD_CTL1 Bit 7,6 must be 0,1
+ 7 disable(fw controlled)
+ 6 0-AUX,1-TS
+ 5 0-par,1-ser
+ 4 0-lsb/1-msb
+ 3,2 reserved
+ 1,0 0-no sync, 1-use ext. start, 2-use 0x47, 3-both
+ 1: FD_CTL2 has 3-valid must be hi, 2-use valid, 1-edge
+ 2: FD_STA is read-only. 0-sync
+ 3: FD_INSYNC is number of 47s to trigger "in sync".
+ 4: FD_OUTSYNC is number of 47s to trigger "out of sync".
+ 5: FD_MAXBYTE1 is low-order of bytes per packet.
+ 6: FD_MAXBYTE2 is high-order of bytes per packet.
+ 7: Top byte is unused.
+*/
+
+/****************************************************************************/
+
+static u8 TSFeatureDecoderSetup[8 * 4] = {
+ 0x42, 0x00, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00,
+ 0x40, 0x06, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00, /* DRXH */
+ 0x71, 0x07, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00, /* DRXHser */
+ 0x72, 0x06, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00, /* S2ser */
+};
+
+/* Set NGENE I2S Config to 16 bit packed */
+static u8 I2SConfiguration[] = {
+ 0x00, 0x10, 0x00, 0x00,
+ 0x80, 0x10, 0x00, 0x00,
+};
+
+static u8 SPDIFConfiguration[10] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+/* Set NGENE I2S Config to transport stream compatible mode */
+
+static u8 TS_I2SConfiguration[4] = { 0x3E, 0x1A, 0x00, 0x00 }; /*3e 18 00 00 ?*/
+
+static u8 TS_I2SOutConfiguration[4] = { 0x80, 0x20, 0x00, 0x00 };
+
+static u8 ITUDecoderSetup[4][16] = {
+ {0x1c, 0x13, 0x01, 0x68, 0x3d, 0x90, 0x14, 0x20, /* SDTV */
+ 0x00, 0x00, 0x01, 0xb0, 0x9c, 0x00, 0x00, 0x00},
+ {0x9c, 0x03, 0x23, 0xC0, 0x60, 0x0E, 0x13, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0xB0, 0x00, 0x00, 0x00},
+ {0x9f, 0x00, 0x23, 0xC0, 0x60, 0x0F, 0x13, 0x00, /* HDTV 1080i50 */
+ 0x00, 0x00, 0x00, 0x01, 0xB0, 0x00, 0x00, 0x00},
+ {0x9c, 0x01, 0x23, 0xC0, 0x60, 0x0E, 0x13, 0x00, /* HDTV 1080i60 */
+ 0x00, 0x00, 0x00, 0x01, 0xB0, 0x00, 0x00, 0x00},
+};
+
+/*
+ * 50 48 60 gleich
+ * 27p50 9f 00 22 80 42 69 18 ...
+ * 27p60 93 00 22 80 82 69 1c ...
+ */
+
+/* Maxbyte to 1144 (for raw data) */
+static u8 ITUFeatureDecoderSetup[8] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x04, 0x00
+};
+
+static void FillTSBuffer(void *Buffer, int Length, u32 Flags)
+{
+ u32 *ptr = Buffer;
+
+ memset(Buffer, 0xff, Length);
+ while (Length > 0) {
+ if (Flags & DF_SWAP32)
+ *ptr = 0x471FFF10;
+ else
+ *ptr = 0x10FF1F47;
+ ptr += (188 / 4);
+ Length -= 188;
+ }
+}
+
+
+static void flush_buffers(struct ngene_channel *chan)
+{
+ u8 val;
+
+ do {
+ msleep(1);
+ spin_lock_irq(&chan->state_lock);
+ val = chan->nextBuffer->ngeneBuffer.SR.Flags & 0x80;
+ spin_unlock_irq(&chan->state_lock);
+ } while (val);
+}
+
+static void clear_buffers(struct ngene_channel *chan)
+{
+ struct SBufferHeader *Cur = chan->nextBuffer;
+
+ do {
+ memset(&Cur->ngeneBuffer.SR, 0, sizeof(Cur->ngeneBuffer.SR));
+ if (chan->mode & NGENE_IO_TSOUT)
+ FillTSBuffer(Cur->Buffer1,
+ chan->Capture1Length,
+ chan->DataFormatFlags);
+ Cur = Cur->Next;
+ } while (Cur != chan->nextBuffer);
+
+ if (chan->mode & NGENE_IO_TSOUT) {
+ chan->nextBuffer->ngeneBuffer.SR.DTOUpdate =
+ chan->AudioDTOValue;
+ chan->AudioDTOUpdated = 0;
+
+ Cur = chan->TSIdleBuffer.Head;
+
+ do {
+ memset(&Cur->ngeneBuffer.SR, 0,
+ sizeof(Cur->ngeneBuffer.SR));
+ FillTSBuffer(Cur->Buffer1,
+ chan->Capture1Length,
+ chan->DataFormatFlags);
+ Cur = Cur->Next;
+ } while (Cur != chan->TSIdleBuffer.Head);
+ }
+}
+
+static int ngene_command_stream_control(struct ngene *dev, u8 stream,
+ u8 control, u8 mode, u8 flags)
+{
+ struct ngene_channel *chan = &dev->channel[stream];
+ struct ngene_command com;
+ u16 BsUVI = ((stream & 1) ? 0x9400 : 0x9300);
+ u16 BsSDI = ((stream & 1) ? 0x9600 : 0x9500);
+ u16 BsSPI = ((stream & 1) ? 0x9800 : 0x9700);
+ u16 BsSDO = 0x9B00;
+
+ /* down(&dev->stream_mutex); */
+ while (down_trylock(&dev->stream_mutex)) {
+ printk(KERN_INFO DEVICE_NAME ": SC locked\n");
+ msleep(1);
+ }
+ memset(&com, 0, sizeof(com));
+ com.cmd.hdr.Opcode = CMD_CONTROL;
+ com.cmd.hdr.Length = sizeof(struct FW_STREAM_CONTROL) - 2;
+ com.cmd.StreamControl.Stream = stream | (control ? 8 : 0);
+ if (chan->mode & NGENE_IO_TSOUT)
+ com.cmd.StreamControl.Stream |= 0x07;
+ com.cmd.StreamControl.Control = control |
+ (flags & SFLAG_ORDER_LUMA_CHROMA);
+ com.cmd.StreamControl.Mode = mode;
+ com.in_len = sizeof(struct FW_STREAM_CONTROL);
+ com.out_len = 0;
+
+ dprintk(KERN_INFO DEVICE_NAME
+ ": Stream=%02x, Control=%02x, Mode=%02x\n",
+ com.cmd.StreamControl.Stream, com.cmd.StreamControl.Control,
+ com.cmd.StreamControl.Mode);
+
+ chan->Mode = mode;
+
+ if (!(control & 0x80)) {
+ spin_lock_irq(&chan->state_lock);
+ if (chan->State == KSSTATE_RUN) {
+ chan->State = KSSTATE_ACQUIRE;
+ chan->HWState = HWSTATE_STOP;
+ spin_unlock_irq(&chan->state_lock);
+ if (ngene_command(dev, &com) < 0) {
+ up(&dev->stream_mutex);
+ return -1;
+ }
+ /* clear_buffers(chan); */
+ flush_buffers(chan);
+ up(&dev->stream_mutex);
+ return 0;
+ }
+ spin_unlock_irq(&chan->state_lock);
+ up(&dev->stream_mutex);
+ return 0;
+ }
+
+ if (mode & SMODE_AUDIO_CAPTURE) {
+ com.cmd.StreamControl.CaptureBlockCount =
+ chan->Capture1Length / AUDIO_BLOCK_SIZE;
+ com.cmd.StreamControl.Buffer_Address = chan->RingBuffer.PAHead;
+ } else if (mode & SMODE_TRANSPORT_STREAM) {
+ com.cmd.StreamControl.CaptureBlockCount =
+ chan->Capture1Length / TS_BLOCK_SIZE;
+ com.cmd.StreamControl.MaxLinesPerField =
+ chan->Capture1Length / TS_BLOCK_SIZE;
+ com.cmd.StreamControl.Buffer_Address =
+ chan->TSRingBuffer.PAHead;
+ if (chan->mode & NGENE_IO_TSOUT) {
+ com.cmd.StreamControl.BytesPerVBILine =
+ chan->Capture1Length / TS_BLOCK_SIZE;
+ com.cmd.StreamControl.Stream |= 0x07;
+ }
+ } else {
+ com.cmd.StreamControl.BytesPerVideoLine = chan->nBytesPerLine;
+ com.cmd.StreamControl.MaxLinesPerField = chan->nLines;
+ com.cmd.StreamControl.MinLinesPerField = 100;
+ com.cmd.StreamControl.Buffer_Address = chan->RingBuffer.PAHead;
+
+ if (mode & SMODE_VBI_CAPTURE) {
+ com.cmd.StreamControl.MaxVBILinesPerField =
+ chan->nVBILines;
+ com.cmd.StreamControl.MinVBILinesPerField = 0;
+ com.cmd.StreamControl.BytesPerVBILine =
+ chan->nBytesPerVBILine;
+ }
+ if (flags & SFLAG_COLORBAR)
+ com.cmd.StreamControl.Stream |= 0x04;
+ }
+
+ spin_lock_irq(&chan->state_lock);
+ if (mode & SMODE_AUDIO_CAPTURE) {
+ chan->nextBuffer = chan->RingBuffer.Head;
+ if (mode & SMODE_AUDIO_SPDIF) {
+ com.cmd.StreamControl.SetupDataLen =
+ sizeof(SPDIFConfiguration);
+ com.cmd.StreamControl.SetupDataAddr = BsSPI;
+ memcpy(com.cmd.StreamControl.SetupData,
+ SPDIFConfiguration, sizeof(SPDIFConfiguration));
+ } else {
+ com.cmd.StreamControl.SetupDataLen = 4;
+ com.cmd.StreamControl.SetupDataAddr = BsSDI;
+ memcpy(com.cmd.StreamControl.SetupData,
+ I2SConfiguration +
+ 4 * dev->card_info->i2s[stream], 4);
+ }
+ } else if (mode & SMODE_TRANSPORT_STREAM) {
+ chan->nextBuffer = chan->TSRingBuffer.Head;
+ if (stream >= STREAM_AUDIOIN1) {
+ if (chan->mode & NGENE_IO_TSOUT) {
+ com.cmd.StreamControl.SetupDataLen =
+ sizeof(TS_I2SOutConfiguration);
+ com.cmd.StreamControl.SetupDataAddr = BsSDO;
+ memcpy(com.cmd.StreamControl.SetupData,
+ TS_I2SOutConfiguration,
+ sizeof(TS_I2SOutConfiguration));
+ } else {
+ com.cmd.StreamControl.SetupDataLen =
+ sizeof(TS_I2SConfiguration);
+ com.cmd.StreamControl.SetupDataAddr = BsSDI;
+ memcpy(com.cmd.StreamControl.SetupData,
+ TS_I2SConfiguration,
+ sizeof(TS_I2SConfiguration));
+ }
+ } else {
+ com.cmd.StreamControl.SetupDataLen = 8;
+ com.cmd.StreamControl.SetupDataAddr = BsUVI + 0x10;
+ memcpy(com.cmd.StreamControl.SetupData,
+ TSFeatureDecoderSetup +
+ 8 * dev->card_info->tsf[stream], 8);
+ }
+ } else {
+ chan->nextBuffer = chan->RingBuffer.Head;
+ com.cmd.StreamControl.SetupDataLen =
+ 16 + sizeof(ITUFeatureDecoderSetup);
+ com.cmd.StreamControl.SetupDataAddr = BsUVI;
+ memcpy(com.cmd.StreamControl.SetupData,
+ ITUDecoderSetup[chan->itumode], 16);
+ memcpy(com.cmd.StreamControl.SetupData + 16,
+ ITUFeatureDecoderSetup, sizeof(ITUFeatureDecoderSetup));
+ }
+ clear_buffers(chan);
+ chan->State = KSSTATE_RUN;
+ if (mode & SMODE_TRANSPORT_STREAM)
+ chan->HWState = HWSTATE_RUN;
+ else
+ chan->HWState = HWSTATE_STARTUP;
+ spin_unlock_irq(&chan->state_lock);
+
+ if (ngene_command(dev, &com) < 0) {
+ up(&dev->stream_mutex);
+ return -1;
+ }
+ up(&dev->stream_mutex);
+ return 0;
+}
+
+
+/****************************************************************************/
+/* I2C **********************************************************************/
+/****************************************************************************/
+
+static void ngene_i2c_set_bus(struct ngene *dev, int bus)
+{
+ if (!(dev->card_info->i2c_access & 2))
+ return;
+ if (dev->i2c_current_bus == bus)
+ return;
+
+ switch (bus) {
+ case 0:
+ ngene_command_gpio_set(dev, 3, 0);
+ ngene_command_gpio_set(dev, 2, 1);
+ break;
+
+ case 1:
+ ngene_command_gpio_set(dev, 2, 0);
+ ngene_command_gpio_set(dev, 3, 1);
+ break;
+ }
+ dev->i2c_current_bus = bus;
+}
+
+static int ngene_i2c_master_xfer(struct i2c_adapter *adapter,
+ struct i2c_msg msg[], int num)
+{
+ struct ngene_channel *chan =
+ (struct ngene_channel *)i2c_get_adapdata(adapter);
+ struct ngene *dev = chan->dev;
+
+ down(&dev->i2c_switch_mutex);
+ ngene_i2c_set_bus(dev, chan->number);
+
+ if (num == 2 && msg[1].flags & I2C_M_RD && !(msg[0].flags & I2C_M_RD))
+ if (!ngene_command_i2c_read(dev, msg[0].addr,
+ msg[0].buf, msg[0].len,
+ msg[1].buf, msg[1].len, 0))
+ goto done;
+
+ if (num == 1 && !(msg[0].flags & I2C_M_RD))
+ if (!ngene_command_i2c_write(dev, msg[0].addr,
+ msg[0].buf, msg[0].len))
+ goto done;
+ if (num == 1 && (msg[0].flags & I2C_M_RD))
+ if (!ngene_command_i2c_read(dev, msg[0].addr, 0, 0,
+ msg[0].buf, msg[0].len, 0))
+ goto done;
+
+ up(&dev->i2c_switch_mutex);
+ return -EIO;
+
+done:
+ up(&dev->i2c_switch_mutex);
+ return num;
+}
+
+
+static u32 ngene_i2c_functionality(struct i2c_adapter *adap)
+{
+ return I2C_FUNC_SMBUS_EMUL;
+}
+
+static struct i2c_algorithm ngene_i2c_algo = {
+ .master_xfer = ngene_i2c_master_xfer,
+ .functionality = ngene_i2c_functionality,
+};
+
+static int ngene_i2c_init(struct ngene *dev, int dev_nr)
+{
+ struct i2c_adapter *adap = &(dev->channel[dev_nr].i2c_adapter);
+
+ i2c_set_adapdata(adap, &(dev->channel[dev_nr]));
+ adap->class = I2C_CLASS_TV_DIGITAL | I2C_CLASS_TV_ANALOG;
+
+ strcpy(adap->name, "nGene");
+
+ adap->algo = &ngene_i2c_algo;
+ adap->algo_data = (void *)&(dev->channel[dev_nr]);
+ adap->dev.parent = &dev->pci_dev->dev;
+
+ return i2c_add_adapter(adap);
+}
+
+
+/****************************************************************************/
+/* DVB functions and API interface ******************************************/
+/****************************************************************************/
+
+static void swap_buffer(u32 *p, u32 len)
+{
+ while (len) {
+ *p = swab32(*p);
+ p++;
+ len -= 4;
+ }
+}
+
+
+static void *tsin_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags)
+{
+ struct ngene_channel *chan = priv;
+
+
+#ifdef COMMAND_TIMEOUT_WORKAROUND
+ if (chan->users > 0)
+#endif
+ dvb_dmx_swfilter(&chan->demux, buf, len);
+ return 0;
+}
+
+u8 fill_ts[188] = { 0x47, 0x1f, 0xff, 0x10 };
+
+static void *tsout_exchange(void *priv, void *buf, u32 len,
+ u32 clock, u32 flags)
+{
+ struct ngene_channel *chan = priv;
+ struct ngene *dev = chan->dev;
+ u32 alen;
+
+ alen = dvb_ringbuffer_avail(&dev->tsout_rbuf);
+ alen -= alen % 188;
+
+ if (alen < len)
+ FillTSBuffer(buf + alen, len - alen, flags);
+ else
+ alen = len;
+ dvb_ringbuffer_read(&dev->tsout_rbuf, buf, alen);
+ if (flags & DF_SWAP32)
+ swap_buffer((u32 *)buf, alen);
+ wake_up_interruptible(&dev->tsout_rbuf.queue);
+ return buf;
+}
+
+
+static void set_transfer(struct ngene_channel *chan, int state)
+{
+ u8 control = 0, mode = 0, flags = 0;
+ struct ngene *dev = chan->dev;
+ int ret;
+
+ /*
+ printk(KERN_INFO DEVICE_NAME ": st %d\n", state);
+ msleep(100);
+ */
+
+ if (state) {
+ if (chan->running) {
+ printk(KERN_INFO DEVICE_NAME ": already running\n");
+ return;
+ }
+ } else {
+ if (!chan->running) {
+ printk(KERN_INFO DEVICE_NAME ": already stopped\n");
+ return;
+ }
+ }
+
+ if (dev->card_info->switch_ctrl)
+ dev->card_info->switch_ctrl(chan, 1, state ^ 1);
+
+ if (state) {
+ spin_lock_irq(&chan->state_lock);
+
+ /* printk(KERN_INFO DEVICE_NAME ": lock=%08x\n",
+ ngreadl(0x9310)); */
+ dvb_ringbuffer_flush(&dev->tsout_rbuf);
+ control = 0x80;
+ if (chan->mode & (NGENE_IO_TSIN | NGENE_IO_TSOUT)) {
+ chan->Capture1Length = 512 * 188;
+ mode = SMODE_TRANSPORT_STREAM;
+ }
+ if (chan->mode & NGENE_IO_TSOUT) {
+ chan->pBufferExchange = tsout_exchange;
+ /* 0x66666666 = 50MHz *2^33 /250MHz */
+ chan->AudioDTOValue = 0x66666666;
+ /* set_dto(chan, 38810700+1000); */
+ /* set_dto(chan, 19392658); */
+ }
+ if (chan->mode & NGENE_IO_TSIN)
+ chan->pBufferExchange = tsin_exchange;
+ /* ngwritel(0, 0x9310); */
+ spin_unlock_irq(&chan->state_lock);
+ } else
+ ;/* printk(KERN_INFO DEVICE_NAME ": lock=%08x\n",
+ ngreadl(0x9310)); */
+
+ ret = ngene_command_stream_control(dev, chan->number,
+ control, mode, flags);
+ if (!ret)
+ chan->running = state;
+ else
+ printk(KERN_ERR DEVICE_NAME ": set_transfer %d failed\n",
+ state);
+ if (!state) {
+ spin_lock_irq(&chan->state_lock);
+ chan->pBufferExchange = 0;
+ dvb_ringbuffer_flush(&dev->tsout_rbuf);
+ spin_unlock_irq(&chan->state_lock);
+ }
+}
+
+static int ngene_start_feed(struct dvb_demux_feed *dvbdmxfeed)
+{
+ struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
+ struct ngene_channel *chan = dvbdmx->priv;
+
+ if (chan->users == 0) {
+#ifdef COMMAND_TIMEOUT_WORKAROUND
+ if (!chan->running)
+#endif
+ set_transfer(chan, 1);
+ /* msleep(10); */
+ }
+
+ return ++chan->users;
+}
+
+static int ngene_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
+{
+ struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
+ struct ngene_channel *chan = dvbdmx->priv;
+
+ if (--chan->users)
+ return chan->users;
+
+#ifndef COMMAND_TIMEOUT_WORKAROUND
+ set_transfer(chan, 0);
+#endif
+
+ return 0;
+}
+
+
+
+static int my_dvb_dmx_ts_card_init(struct dvb_demux *dvbdemux, char *id,
+ int (*start_feed)(struct dvb_demux_feed *),
+ int (*stop_feed)(struct dvb_demux_feed *),
+ void *priv)
+{
+ dvbdemux->priv = priv;
+
+ dvbdemux->filternum = 256;
+ dvbdemux->feednum = 256;
+ dvbdemux->start_feed = start_feed;
+ dvbdemux->stop_feed = stop_feed;
+ dvbdemux->write_to_decoder = 0;
+ dvbdemux->dmx.capabilities = (DMX_TS_FILTERING |
+ DMX_SECTION_FILTERING |
+ DMX_MEMORY_BASED_FILTERING);
+ return dvb_dmx_init(dvbdemux);
+}
+
+static int my_dvb_dmxdev_ts_card_init(struct dmxdev *dmxdev,
+ struct dvb_demux *dvbdemux,
+ struct dmx_frontend *hw_frontend,
+ struct dmx_frontend *mem_frontend,
+ struct dvb_adapter *dvb_adapter)
+{
+ int ret;
+
+ dmxdev->filternum = 256;
+ dmxdev->demux = &dvbdemux->dmx;
+ dmxdev->capabilities = 0;
+ ret = dvb_dmxdev_init(dmxdev, dvb_adapter);
+ if (ret < 0)
+ return ret;
+
+ hw_frontend->source = DMX_FRONTEND_0;
+ dvbdemux->dmx.add_frontend(&dvbdemux->dmx, hw_frontend);
+ mem_frontend->source = DMX_MEMORY_FE;
+ dvbdemux->dmx.add_frontend(&dvbdemux->dmx, mem_frontend);
+ return dvbdemux->dmx.connect_frontend(&dvbdemux->dmx, hw_frontend);
+}
+
+
+/****************************************************************************/
+/* nGene hardware init and release functions ********************************/
+/****************************************************************************/
+
+static void free_ringbuffer(struct ngene *dev, struct SRingBufferDescriptor *rb)
+{
+ struct SBufferHeader *Cur = rb->Head;
+ u32 j;
+
+ if (!Cur)
+ return;
+
+ for (j = 0; j < rb->NumBuffers; j++, Cur = Cur->Next) {
+ if (Cur->Buffer1)
+ pci_free_consistent(dev->pci_dev,
+ rb->Buffer1Length,
+ Cur->Buffer1,
+ Cur->scList1->Address);
+
+ if (Cur->Buffer2)
+ pci_free_consistent(dev->pci_dev,
+ rb->Buffer2Length,
+ Cur->Buffer2,
+ Cur->scList2->Address);
+ }
+
+ if (rb->SCListMem)
+ pci_free_consistent(dev->pci_dev, rb->SCListMemSize,
+ rb->SCListMem, rb->PASCListMem);
+
+ pci_free_consistent(dev->pci_dev, rb->MemSize, rb->Head, rb->PAHead);
+}
+
+static void free_idlebuffer(struct ngene *dev,
+ struct SRingBufferDescriptor *rb,
+ struct SRingBufferDescriptor *tb)
+{
+ int j;
+ struct SBufferHeader *Cur = tb->Head;
+
+ if (!rb->Head)
+ return;
+ free_ringbuffer(dev, rb);
+ for (j = 0; j < tb->NumBuffers; j++, Cur = Cur->Next) {
+ Cur->Buffer2 = 0;
+ Cur->scList2 = 0;
+ Cur->ngeneBuffer.Address_of_first_entry_2 = 0;
+ Cur->ngeneBuffer.Number_of_entries_2 = 0;
+ }
+}
+
+static void free_common_buffers(struct ngene *dev)
+{
+ u32 i;
+ struct ngene_channel *chan;
+
+ for (i = STREAM_VIDEOIN1; i < MAX_STREAM; i++) {
+ chan = &dev->channel[i];
+ free_idlebuffer(dev, &chan->TSIdleBuffer, &chan->TSRingBuffer);
+ free_ringbuffer(dev, &chan->RingBuffer);
+ free_ringbuffer(dev, &chan->TSRingBuffer);
+ }
+
+ if (dev->OverflowBuffer)
+ pci_free_consistent(dev->pci_dev,
+ OVERFLOW_BUFFER_SIZE,
+ dev->OverflowBuffer, dev->PAOverflowBuffer);
+
+ if (dev->FWInterfaceBuffer)
+ pci_free_consistent(dev->pci_dev,
+ 4096,
+ dev->FWInterfaceBuffer,
+ dev->PAFWInterfaceBuffer);
+}
+
+/****************************************************************************/
+/* Ring buffer handling *****************************************************/
+/****************************************************************************/
+
+static int create_ring_buffer(struct pci_dev *pci_dev,
+ struct SRingBufferDescriptor *descr, u32 NumBuffers)
+{
+ dma_addr_t tmp;
+ struct SBufferHeader *Head;
+ u32 i;
+ u32 MemSize = SIZEOF_SBufferHeader * NumBuffers;
+ u64 PARingBufferHead;
+ u64 PARingBufferCur;
+ u64 PARingBufferNext;
+ struct SBufferHeader *Cur, *Next;
+
+ descr->Head = 0;
+ descr->MemSize = 0;
+ descr->PAHead = 0;
+ descr->NumBuffers = 0;
+
+ if (MemSize < 4096)
+ MemSize = 4096;
+
+ Head = pci_alloc_consistent(pci_dev, MemSize, &tmp);
+ PARingBufferHead = tmp;
+
+ if (!Head)
+ return -ENOMEM;
+
+ memset(Head, 0, MemSize);
+
+ PARingBufferCur = PARingBufferHead;
+ Cur = Head;
+
+ for (i = 0; i < NumBuffers - 1; i++) {
+ Next = (struct SBufferHeader *)
+ (((u8 *) Cur) + SIZEOF_SBufferHeader);
+ PARingBufferNext = PARingBufferCur + SIZEOF_SBufferHeader;
+ Cur->Next = Next;
+ Cur->ngeneBuffer.Next = PARingBufferNext;
+ Cur = Next;
+ PARingBufferCur = PARingBufferNext;
+ }
+ /* Last Buffer points back to first one */
+ Cur->Next = Head;
+ Cur->ngeneBuffer.Next = PARingBufferHead;
+
+ descr->Head = Head;
+ descr->MemSize = MemSize;
+ descr->PAHead = PARingBufferHead;
+ descr->NumBuffers = NumBuffers;
+
+ return 0;
+}
+
+static int AllocateRingBuffers(struct pci_dev *pci_dev,
+ dma_addr_t of,
+ struct SRingBufferDescriptor *pRingBuffer,
+ u32 Buffer1Length, u32 Buffer2Length)
+{
+ dma_addr_t tmp;
+ u32 i, j;
+ int status = 0;
+ u32 SCListMemSize = pRingBuffer->NumBuffers
+ * ((Buffer2Length != 0) ? (NUM_SCATTER_GATHER_ENTRIES * 2) :
+ NUM_SCATTER_GATHER_ENTRIES)
+ * sizeof(struct HW_SCATTER_GATHER_ELEMENT);
+
+ u64 PASCListMem;
+ struct HW_SCATTER_GATHER_ELEMENT *SCListEntry;
+ u64 PASCListEntry;
+ struct SBufferHeader *Cur;
+ void *SCListMem;
+
+ if (SCListMemSize < 4096)
+ SCListMemSize = 4096;
+
+ SCListMem = pci_alloc_consistent(pci_dev, SCListMemSize, &tmp);
+
+ PASCListMem = tmp;
+ if (SCListMem == NULL)
+ return -ENOMEM;
+
+ memset(SCListMem, 0, SCListMemSize);
+
+ pRingBuffer->SCListMem = SCListMem;
+ pRingBuffer->PASCListMem = PASCListMem;
+ pRingBuffer->SCListMemSize = SCListMemSize;
+ pRingBuffer->Buffer1Length = Buffer1Length;
+ pRingBuffer->Buffer2Length = Buffer2Length;
+
+ SCListEntry = SCListMem;
+ PASCListEntry = PASCListMem;
+ Cur = pRingBuffer->Head;
+
+ for (i = 0; i < pRingBuffer->NumBuffers; i += 1, Cur = Cur->Next) {
+ u64 PABuffer;
+
+ void *Buffer = pci_alloc_consistent(pci_dev, Buffer1Length,
+ &tmp);
+ PABuffer = tmp;
+
+ if (Buffer == NULL)
+ return -ENOMEM;
+
+ Cur->Buffer1 = Buffer;
+
+ SCListEntry->Address = PABuffer;
+ SCListEntry->Length = Buffer1Length;
+
+ Cur->scList1 = SCListEntry;
+ Cur->ngeneBuffer.Address_of_first_entry_1 = PASCListEntry;
+ Cur->ngeneBuffer.Number_of_entries_1 =
+ NUM_SCATTER_GATHER_ENTRIES;
+
+ SCListEntry += 1;
+ PASCListEntry += sizeof(struct HW_SCATTER_GATHER_ELEMENT);
+
+#if NUM_SCATTER_GATHER_ENTRIES > 1
+ for (j = 0; j < NUM_SCATTER_GATHER_ENTRIES - 1; j += 1) {
+ SCListEntry->Address = of;
+ SCListEntry->Length = OVERFLOW_BUFFER_SIZE;
+ SCListEntry += 1;
+ PASCListEntry +=
+ sizeof(struct HW_SCATTER_GATHER_ELEMENT);
+ }
+#endif
+
+ if (!Buffer2Length)
+ continue;
+
+ Buffer = pci_alloc_consistent(pci_dev, Buffer2Length, &tmp);
+ PABuffer = tmp;
+
+ if (Buffer == NULL)
+ return -ENOMEM;
+
+ Cur->Buffer2 = Buffer;
+
+ SCListEntry->Address = PABuffer;
+ SCListEntry->Length = Buffer2Length;
+
+ Cur->scList2 = SCListEntry;
+ Cur->ngeneBuffer.Address_of_first_entry_2 = PASCListEntry;
+ Cur->ngeneBuffer.Number_of_entries_2 =
+ NUM_SCATTER_GATHER_ENTRIES;
+
+ SCListEntry += 1;
+ PASCListEntry += sizeof(struct HW_SCATTER_GATHER_ELEMENT);
+
+#if NUM_SCATTER_GATHER_ENTRIES > 1
+ for (j = 0; j < NUM_SCATTER_GATHER_ENTRIES - 1; j++) {
+ SCListEntry->Address = of;
+ SCListEntry->Length = OVERFLOW_BUFFER_SIZE;
+ SCListEntry += 1;
+ PASCListEntry +=
+ sizeof(struct HW_SCATTER_GATHER_ELEMENT);
+ }
+#endif
+
+ }
+
+ return status;
+}
+
+static int FillTSIdleBuffer(struct SRingBufferDescriptor *pIdleBuffer,
+ struct SRingBufferDescriptor *pRingBuffer)
+{
+ int status = 0;
+
+ /* Copy pointer to scatter gather list in TSRingbuffer
+ structure for buffer 2
+ Load number of buffer
+ */
+ u32 n = pRingBuffer->NumBuffers;
+
+ /* Point to first buffer entry */
+ struct SBufferHeader *Cur = pRingBuffer->Head;
+ int i;
+ /* Loop thru all buffer and set Buffer 2 pointers to TSIdlebuffer */
+ for (i = 0; i < n; i++) {
+ Cur->Buffer2 = pIdleBuffer->Head->Buffer1;
+ Cur->scList2 = pIdleBuffer->Head->scList1;
+ Cur->ngeneBuffer.Address_of_first_entry_2 =
+ pIdleBuffer->Head->ngeneBuffer.
+ Address_of_first_entry_1;
+ Cur->ngeneBuffer.Number_of_entries_2 =
+ pIdleBuffer->Head->ngeneBuffer.Number_of_entries_1;
+ Cur = Cur->Next;
+ }
+ return status;
+}
+
+static u32 RingBufferSizes[MAX_STREAM] = {
+ RING_SIZE_VIDEO,
+ RING_SIZE_VIDEO,
+ RING_SIZE_AUDIO,
+ RING_SIZE_AUDIO,
+ RING_SIZE_AUDIO,
+};
+
+static u32 Buffer1Sizes[MAX_STREAM] = {
+ MAX_VIDEO_BUFFER_SIZE,
+ MAX_VIDEO_BUFFER_SIZE,
+ MAX_AUDIO_BUFFER_SIZE,
+ MAX_AUDIO_BUFFER_SIZE,
+ MAX_AUDIO_BUFFER_SIZE
+};
+
+static u32 Buffer2Sizes[MAX_STREAM] = {
+ MAX_VBI_BUFFER_SIZE,
+ MAX_VBI_BUFFER_SIZE,
+ 0,
+ 0,
+ 0
+};
+
+
+static int AllocCommonBuffers(struct ngene *dev)
+{
+ int status = 0, i;
+
+ dev->FWInterfaceBuffer = pci_alloc_consistent(dev->pci_dev, 4096,
+ &dev->PAFWInterfaceBuffer);
+ if (!dev->FWInterfaceBuffer)
+ return -ENOMEM;
+ dev->hosttongene = dev->FWInterfaceBuffer;
+ dev->ngenetohost = dev->FWInterfaceBuffer + 256;
+ dev->EventBuffer = dev->FWInterfaceBuffer + 512;
+
+ dev->OverflowBuffer = pci_alloc_consistent(dev->pci_dev,
+ OVERFLOW_BUFFER_SIZE,
+ &dev->PAOverflowBuffer);
+ if (!dev->OverflowBuffer)
+ return -ENOMEM;
+ memset(dev->OverflowBuffer, 0, OVERFLOW_BUFFER_SIZE);
+
+ for (i = STREAM_VIDEOIN1; i < MAX_STREAM; i++) {
+ int type = dev->card_info->io_type[i];
+
+ dev->channel[i].State = KSSTATE_STOP;
+
+ if (type & (NGENE_IO_TV | NGENE_IO_HDTV | NGENE_IO_AIN)) {
+ status = create_ring_buffer(dev->pci_dev,
+ &dev->channel[i].RingBuffer,
+ RingBufferSizes[i]);
+ if (status < 0)
+ break;
+
+ if (type & (NGENE_IO_TV | NGENE_IO_AIN)) {
+ status = AllocateRingBuffers(dev->pci_dev,
+ dev->
+ PAOverflowBuffer,
+ &dev->channel[i].
+ RingBuffer,
+ Buffer1Sizes[i],
+ Buffer2Sizes[i]);
+ if (status < 0)
+ break;
+ } else if (type & NGENE_IO_HDTV) {
+ status = AllocateRingBuffers(dev->pci_dev,
+ dev->
+ PAOverflowBuffer,
+ &dev->channel[i].
+ RingBuffer,
+ MAX_HDTV_BUFFER_SIZE,
+ 0);
+ if (status < 0)
+ break;
+ }
+ }
+
+ if (type & (NGENE_IO_TSIN | NGENE_IO_TSOUT)) {
+
+ status = create_ring_buffer(dev->pci_dev,
+ &dev->channel[i].
+ TSRingBuffer, RING_SIZE_TS);
+ if (status < 0)
+ break;
+
+ status = AllocateRingBuffers(dev->pci_dev,
+ dev->PAOverflowBuffer,
+ &dev->channel[i].
+ TSRingBuffer,
+ MAX_TS_BUFFER_SIZE, 0);
+ if (status)
+ break;
+ }
+
+ if (type & NGENE_IO_TSOUT) {
+ status = create_ring_buffer(dev->pci_dev,
+ &dev->channel[i].
+ TSIdleBuffer, 1);
+ if (status < 0)
+ break;
+ status = AllocateRingBuffers(dev->pci_dev,
+ dev->PAOverflowBuffer,
+ &dev->channel[i].
+ TSIdleBuffer,
+ MAX_TS_BUFFER_SIZE, 0);
+ if (status)
+ break;
+ FillTSIdleBuffer(&dev->channel[i].TSIdleBuffer,
+ &dev->channel[i].TSRingBuffer);
+ }
+ }
+ return status;
+}
+
+static void ngene_release_buffers(struct ngene *dev)
+{
+ if (dev->iomem)
+ iounmap(dev->iomem);
+ free_common_buffers(dev);
+ vfree(dev->tsout_buf);
+ vfree(dev->ain_buf);
+ vfree(dev->vin_buf);
+ vfree(dev);
+}
+
+static int ngene_get_buffers(struct ngene *dev)
+{
+ if (AllocCommonBuffers(dev))
+ return -ENOMEM;
+ if (dev->card_info->io_type[4] & NGENE_IO_TSOUT) {
+ dev->tsout_buf = vmalloc(TSOUT_BUF_SIZE);
+ if (!dev->tsout_buf)
+ return -ENOMEM;
+ dvb_ringbuffer_init(&dev->tsout_rbuf,
+ dev->tsout_buf, TSOUT_BUF_SIZE);
+ }
+ if (dev->card_info->io_type[2] & NGENE_IO_AIN) {
+ dev->ain_buf = vmalloc(AIN_BUF_SIZE);
+ if (!dev->ain_buf)
+ return -ENOMEM;
+ dvb_ringbuffer_init(&dev->ain_rbuf, dev->ain_buf, AIN_BUF_SIZE);
+ }
+ if (dev->card_info->io_type[0] & NGENE_IO_HDTV) {
+ dev->vin_buf = vmalloc(VIN_BUF_SIZE);
+ if (!dev->vin_buf)
+ return -ENOMEM;
+ dvb_ringbuffer_init(&dev->vin_rbuf, dev->vin_buf, VIN_BUF_SIZE);
+ }
+ dev->iomem = ioremap(pci_resource_start(dev->pci_dev, 0),
+ pci_resource_len(dev->pci_dev, 0));
+ if (!dev->iomem)
+ return -ENOMEM;
+
+ return 0;
+}
+
+static void ngene_init(struct ngene *dev)
+{
+ int i;
+
+ tasklet_init(&dev->event_tasklet, event_tasklet, (unsigned long)dev);
+
+ memset_io(dev->iomem + 0xc000, 0x00, 0x220);
+ memset_io(dev->iomem + 0xc400, 0x00, 0x100);
+
+ for (i = 0; i < MAX_STREAM; i++) {
+ dev->channel[i].dev = dev;
+ dev->channel[i].number = i;
+ }
+
+ dev->fw_interface_version = 0;
+
+ ngwritel(0, NGENE_INT_ENABLE);
+
+ dev->icounts = ngreadl(NGENE_INT_COUNTS);
+
+ dev->device_version = ngreadl(DEV_VER) & 0x0f;
+ printk(KERN_INFO DEVICE_NAME ": Device version %d\n",
+ dev->device_version);
+}
+
+static int ngene_load_firm(struct ngene *dev)
+{
+ u32 size;
+ const struct firmware *fw = NULL;
+ u8 *ngene_fw;
+ char *fw_name;
+ int err, version;
+
+ version = dev->card_info->fw_version;
+
+ switch (version) {
+ default:
+ case 15:
+ version = 15;
+ size = 23466;
+ fw_name = "ngene_15.fw";
+ break;
+ case 16:
+ size = 23498;
+ fw_name = "ngene_16.fw";
+ break;
+ case 17:
+ size = 24446;
+ fw_name = "ngene_17.fw";
+ break;
+ }
+
+ if (request_firmware(&fw, fw_name, &dev->pci_dev->dev) < 0) {
+ printk(KERN_ERR DEVICE_NAME
+ ": Could not load firmware file %s.\n", fw_name);
+ printk(KERN_INFO DEVICE_NAME
+ ": Copy %s to your hotplug directory!\n", fw_name);
+ return -1;
+ }
+ if (size != fw->size) {
+ printk(KERN_ERR DEVICE_NAME
+ ": Firmware %s has invalid size!", fw_name);
+ err = -1;
+ } else {
+ printk(KERN_INFO DEVICE_NAME
+ ": Loading firmware file %s.\n", fw_name);
+ ngene_fw = (u8 *) fw->data;
+ err = ngene_command_load_firmware(dev, ngene_fw, size);
+ }
+
+ release_firmware(fw);
+
+ return err;
+}
+
+static void ngene_stop(struct ngene *dev)
+{
+ down(&dev->cmd_mutex);
+ i2c_del_adapter(&(dev->channel[0].i2c_adapter));
+ i2c_del_adapter(&(dev->channel[1].i2c_adapter));
+ ngwritel(0, NGENE_INT_ENABLE);
+ ngwritel(0, NGENE_COMMAND);
+ ngwritel(0, NGENE_COMMAND_HI);
+ ngwritel(0, NGENE_STATUS);
+ ngwritel(0, NGENE_STATUS_HI);
+ ngwritel(0, NGENE_EVENT);
+ ngwritel(0, NGENE_EVENT_HI);
+ free_irq(dev->pci_dev->irq, dev);
+}
+
+static int ngene_start(struct ngene *dev)
+{
+ int stat;
+ int i;
+
+ pci_set_master(dev->pci_dev);
+ ngene_init(dev);
+
+ stat = request_irq(dev->pci_dev->irq, irq_handler,
+ IRQF_SHARED, "nGene",
+ (void *)dev);
+ if (stat < 0)
+ return stat;
+
+ init_waitqueue_head(&dev->cmd_wq);
+ init_waitqueue_head(&dev->tx_wq);
+ init_waitqueue_head(&dev->rx_wq);
+ sema_init(&dev->cmd_mutex, 1);
+ sema_init(&dev->stream_mutex, 1);
+ sema_init(&dev->pll_mutex, 1);
+ sema_init(&dev->i2c_switch_mutex, 1);
+ spin_lock_init(&dev->cmd_lock);
+ for (i = 0; i < MAX_STREAM; i++)
+ spin_lock_init(&dev->channel[i].state_lock);
+ ngwritel(1, TIMESTAMPS);
+
+ ngwritel(1, NGENE_INT_ENABLE);
+
+ stat = ngene_load_firm(dev);
+ if (stat < 0)
+ goto fail;
+
+ stat = ngene_i2c_init(dev, 0);
+ if (stat < 0)
+ goto fail;
+
+ stat = ngene_i2c_init(dev, 1);
+ if (stat < 0)
+ goto fail;
+
+ if (dev->card_info->fw_version == 17) {
+ u8 tsin4_config[6] = {
+ 3072 / 64, 3072 / 64, 0, 3072 / 64, 3072 / 64, 0};
+ u8 default_config[6] = {
+ 4096 / 64, 4096 / 64, 0, 2048 / 64, 2048 / 64, 0};
+ u8 *bconf = default_config;
+
+ if (dev->card_info->io_type[3] == NGENE_IO_TSIN)
+ bconf = tsin4_config;
+ dprintk(KERN_DEBUG DEVICE_NAME ": FW 17 buffer config\n");
+ stat = ngene_command_config_free_buf(dev, bconf);
+ } else {
+ int bconf = BUFFER_CONFIG_4422;
+ if (dev->card_info->io_type[3] == NGENE_IO_TSIN)
+ bconf = BUFFER_CONFIG_3333;
+ stat = ngene_command_config_buf(dev, bconf);
+ }
+ return stat;
+fail:
+ ngwritel(0, NGENE_INT_ENABLE);
+ free_irq(dev->pci_dev->irq, dev);
+ return stat;
+}
+
+
+
+/****************************************************************************/
+/* Switch control (I2C gates, etc.) *****************************************/
+/****************************************************************************/
+
+
+/****************************************************************************/
+/* Demod/tuner attachment ***************************************************/
+/****************************************************************************/
+
+static int tuner_attach_stv6110(struct ngene_channel *chan)
+{
+ struct stv090x_config *feconf = (struct stv090x_config *)
+ chan->dev->card_info->fe_config[chan->number];
+ struct stv6110x_config *tunerconf = (struct stv6110x_config *)
+ chan->dev->card_info->tuner_config[chan->number];
+ struct stv6110x_devctl *ctl;
+
+ ctl = dvb_attach(stv6110x_attach, chan->fe, tunerconf,
+ &chan->i2c_adapter);
+ if (ctl == NULL) {
+ printk(KERN_ERR DEVICE_NAME ": No STV6110X found!\n");
+ return -ENODEV;
+ }
+
+ feconf->tuner_init = ctl->tuner_init;
+ feconf->tuner_set_mode = ctl->tuner_set_mode;
+ feconf->tuner_set_frequency = ctl->tuner_set_frequency;
+ feconf->tuner_get_frequency = ctl->tuner_get_frequency;
+ feconf->tuner_set_bandwidth = ctl->tuner_set_bandwidth;
+ feconf->tuner_get_bandwidth = ctl->tuner_get_bandwidth;
+ feconf->tuner_set_bbgain = ctl->tuner_set_bbgain;
+ feconf->tuner_get_bbgain = ctl->tuner_get_bbgain;
+ feconf->tuner_set_refclk = ctl->tuner_set_refclk;
+ feconf->tuner_get_status = ctl->tuner_get_status;
+
+ return 0;
+}
+
+
+static int demod_attach_stv0900(struct ngene_channel *chan)
+{
+ struct stv090x_config *feconf = (struct stv090x_config *)
+ chan->dev->card_info->fe_config[chan->number];
+
+ chan->fe = dvb_attach(stv090x_attach,
+ feconf,
+ &chan->i2c_adapter,
+ chan->number == 0 ? STV090x_DEMODULATOR_0 :
+ STV090x_DEMODULATOR_1);
+ if (chan->fe == NULL) {
+ printk(KERN_ERR DEVICE_NAME ": No STV0900 found!\n");
+ return -ENODEV;
+ }
+
+ if (!dvb_attach(lnbh24_attach, chan->fe, &chan->i2c_adapter, 0,
+ 0, chan->dev->card_info->lnb[chan->number])) {
+ printk(KERN_ERR DEVICE_NAME ": No LNBH24 found!\n");
+ dvb_frontend_detach(chan->fe);
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+/****************************************************************************/
+/****************************************************************************/
+/****************************************************************************/
+
+static void release_channel(struct ngene_channel *chan)
+{
+ struct dvb_demux *dvbdemux = &chan->demux;
+ struct ngene *dev = chan->dev;
+ struct ngene_info *ni = dev->card_info;
+ int io = ni->io_type[chan->number];
+
+#ifdef COMMAND_TIMEOUT_WORKAROUND
+ if (chan->running)
+ set_transfer(chan, 0);
+#endif
+
+ tasklet_kill(&chan->demux_tasklet);
+
+ if (io & (NGENE_IO_TSIN | NGENE_IO_TSOUT)) {
+ if (chan->fe) {
+ dvb_unregister_frontend(chan->fe);
+ dvb_frontend_detach(chan->fe);
+ chan->fe = 0;
+ }
+ dvbdemux->dmx.close(&dvbdemux->dmx);
+ dvbdemux->dmx.remove_frontend(&dvbdemux->dmx,
+ &chan->hw_frontend);
+ dvbdemux->dmx.remove_frontend(&dvbdemux->dmx,
+ &chan->mem_frontend);
+ dvb_dmxdev_release(&chan->dmxdev);
+ dvb_dmx_release(&chan->demux);
+
+ if (chan->number == 0 || !one_adapter)
+ dvb_unregister_adapter(&dev->adapter[chan->number]);
+ }
+}
+
+static int init_channel(struct ngene_channel *chan)
+{
+ int ret = 0, nr = chan->number;
+ struct dvb_adapter *adapter = NULL;
+ struct dvb_demux *dvbdemux = &chan->demux;
+ struct ngene *dev = chan->dev;
+ struct ngene_info *ni = dev->card_info;
+ int io = ni->io_type[nr];
+
+ tasklet_init(&chan->demux_tasklet, demux_tasklet, (unsigned long)chan);
+ chan->users = 0;
+ chan->type = io;
+ chan->mode = chan->type; /* for now only one mode */
+
+ if (io & (NGENE_IO_TSIN | NGENE_IO_TSOUT)) {
+ if (nr >= STREAM_AUDIOIN1)
+ chan->DataFormatFlags = DF_SWAP32;
+ if (nr == 0 || !one_adapter) {
+ adapter = &dev->adapter[nr];
+ ret = dvb_register_adapter(adapter, "nGene",
+ THIS_MODULE,
+ &chan->dev->pci_dev->dev,
+ adapter_nr);
+ if (ret < 0)
+ return ret;
+ } else {
+ adapter = &dev->adapter[0];
+ }
+
+ ret = my_dvb_dmx_ts_card_init(dvbdemux, "SW demux",
+ ngene_start_feed,
+ ngene_stop_feed, chan);
+ ret = my_dvb_dmxdev_ts_card_init(&chan->dmxdev, &chan->demux,
+ &chan->hw_frontend,
+ &chan->mem_frontend, adapter);
+ }
+
+ if (io & NGENE_IO_TSIN) {
+ chan->fe = NULL;
+ if (ni->demod_attach[nr])
+ ni->demod_attach[nr](chan);
+ if (chan->fe) {
+ if (dvb_register_frontend(adapter, chan->fe) < 0) {
+ if (chan->fe->ops.release)
+ chan->fe->ops.release(chan->fe);
+ chan->fe = NULL;
+ }
+ }
+ if (chan->fe && ni->tuner_attach[nr])
+ if (ni->tuner_attach[nr] (chan) < 0) {
+ printk(KERN_ERR DEVICE_NAME
+ ": Tuner attach failed on channel %d!\n",
+ nr);
+ }
+ }
+ return ret;
+}
+
+static int init_channels(struct ngene *dev)
+{
+ int i, j;
+
+ for (i = 0; i < MAX_STREAM; i++) {
+ if (init_channel(&dev->channel[i]) < 0) {
+ for (j = i - 1; j >= 0; j--)
+ release_channel(&dev->channel[j]);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+/****************************************************************************/
+/* device probe/remove calls ************************************************/
+/****************************************************************************/
+
+static void __devexit ngene_remove(struct pci_dev *pdev)
+{
+ struct ngene *dev = (struct ngene *)pci_get_drvdata(pdev);
+ int i;
+
+ tasklet_kill(&dev->event_tasklet);
+ for (i = MAX_STREAM - 1; i >= 0; i--)
+ release_channel(&dev->channel[i]);
+ ngene_stop(dev);
+ ngene_release_buffers(dev);
+ pci_set_drvdata(pdev, 0);
+ pci_disable_device(pdev);
+}
+
+static int __devinit ngene_probe(struct pci_dev *pci_dev,
+ const struct pci_device_id *id)
+{
+ struct ngene *dev;
+ int stat = 0;
+
+ if (pci_enable_device(pci_dev) < 0)
+ return -ENODEV;
+
+ dev = vmalloc(sizeof(struct ngene));
+ if (dev == NULL) {
+ stat = -ENOMEM;
+ goto fail0;
+ }
+ memset(dev, 0, sizeof(struct ngene));
+
+ dev->pci_dev = pci_dev;
+ dev->card_info = (struct ngene_info *)id->driver_data;
+ printk(KERN_INFO DEVICE_NAME ": Found %s\n", dev->card_info->name);
+
+ pci_set_drvdata(pci_dev, dev);
+
+ /* Alloc buffers and start nGene */
+ stat = ngene_get_buffers(dev);
+ if (stat < 0)
+ goto fail1;
+ stat = ngene_start(dev);
+ if (stat < 0)
+ goto fail1;
+
+ dev->i2c_current_bus = -1;
+
+ /* Register DVB adapters and devices for both channels */
+ if (init_channels(dev) < 0)
+ goto fail2;
+
+ return 0;
+
+fail2:
+ ngene_stop(dev);
+fail1:
+ ngene_release_buffers(dev);
+fail0:
+ pci_disable_device(pci_dev);
+ pci_set_drvdata(pci_dev, 0);
+ return stat;
+}
+
+/****************************************************************************/
+/* Card configs *************************************************************/
+/****************************************************************************/
+
+static struct stv090x_config fe_cineS2 = {
+ .device = STV0900,
+ .demod_mode = STV090x_DUAL,
+ .clk_mode = STV090x_CLK_EXT,
+
+ .xtal = 27000000,
+ .address = 0x68,
+
+ .ts1_mode = STV090x_TSMODE_SERIAL_PUNCTURED,
+ .ts2_mode = STV090x_TSMODE_SERIAL_PUNCTURED,
+
+ .repeater_level = STV090x_RPTLEVEL_16,
+
+ .adc1_range = STV090x_ADC_1Vpp,
+ .adc2_range = STV090x_ADC_1Vpp,
+
+ .diseqc_envelope_mode = true,
+};
+
+static struct stv6110x_config tuner_cineS2_0 = {
+ .addr = 0x60,
+ .refclk = 27000000,
+ .clk_div = 1,
+};
+
+static struct stv6110x_config tuner_cineS2_1 = {
+ .addr = 0x63,
+ .refclk = 27000000,
+ .clk_div = 1,
+};
+
+static struct ngene_info ngene_info_cineS2 = {
+ .type = NGENE_SIDEWINDER,
+ .name = "Linux4Media cineS2 DVB-S2 Twin Tuner",
+ .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN},
+ .demod_attach = {demod_attach_stv0900, demod_attach_stv0900},
+ .tuner_attach = {tuner_attach_stv6110, tuner_attach_stv6110},
+ .fe_config = {&fe_cineS2, &fe_cineS2},
+ .tuner_config = {&tuner_cineS2_0, &tuner_cineS2_1},
+ .lnb = {0x0b, 0x08},
+ .tsf = {3, 3},
+ .fw_version = 15,
+};
+
+static struct ngene_info ngene_info_satixs2 = {
+ .type = NGENE_SIDEWINDER,
+ .name = "Mystique SaTiX-S2 Dual",
+ .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN},
+ .demod_attach = {demod_attach_stv0900, demod_attach_stv0900},
+ .tuner_attach = {tuner_attach_stv6110, tuner_attach_stv6110},
+ .fe_config = {&fe_cineS2, &fe_cineS2},
+ .tuner_config = {&tuner_cineS2_0, &tuner_cineS2_1},
+ .lnb = {0x0b, 0x08},
+ .tsf = {3, 3},
+ .fw_version = 15,
+};
+
+/****************************************************************************/
+
+
+
+/****************************************************************************/
+/* PCI Subsystem ID *********************************************************/
+/****************************************************************************/
+
+#define NGENE_ID(_subvend, _subdev, _driverdata) { \
+ .vendor = NGENE_VID, .device = NGENE_PID, \
+ .subvendor = _subvend, .subdevice = _subdev, \
+ .driver_data = (unsigned long) &_driverdata }
+
+/****************************************************************************/
+
+static const struct pci_device_id ngene_id_tbl[] __devinitdata = {
+ NGENE_ID(0x18c3, 0xabc3, ngene_info_cineS2),
+ NGENE_ID(0x18c3, 0xabc4, ngene_info_cineS2),
+ NGENE_ID(0x18c3, 0xdb01, ngene_info_satixs2),
+ {0}
+};
+MODULE_DEVICE_TABLE(pci, ngene_id_tbl);
+
+/****************************************************************************/
+/* Init/Exit ****************************************************************/
+/****************************************************************************/
+
+static pci_ers_result_t ngene_error_detected(struct pci_dev *dev,
+ enum pci_channel_state state)
+{
+ printk(KERN_ERR DEVICE_NAME ": PCI error\n");
+ if (state == pci_channel_io_perm_failure)
+ return PCI_ERS_RESULT_DISCONNECT;
+ if (state == pci_channel_io_frozen)
+ return PCI_ERS_RESULT_NEED_RESET;
+ return PCI_ERS_RESULT_CAN_RECOVER;
+}
+
+static pci_ers_result_t ngene_link_reset(struct pci_dev *dev)
+{
+ printk(KERN_INFO DEVICE_NAME ": link reset\n");
+ return 0;
+}
+
+static pci_ers_result_t ngene_slot_reset(struct pci_dev *dev)
+{
+ printk(KERN_INFO DEVICE_NAME ": slot reset\n");
+ return 0;
+}
+
+static void ngene_resume(struct pci_dev *dev)
+{
+ printk(KERN_INFO DEVICE_NAME ": resume\n");
+}
+
+static struct pci_error_handlers ngene_errors = {
+ .error_detected = ngene_error_detected,
+ .link_reset = ngene_link_reset,
+ .slot_reset = ngene_slot_reset,
+ .resume = ngene_resume,
+};
+
+static struct pci_driver ngene_pci_driver = {
+ .name = "ngene",
+ .id_table = ngene_id_tbl,
+ .probe = ngene_probe,
+ .remove = __devexit_p(ngene_remove),
+ .err_handler = &ngene_errors,
+};
+
+static __init int module_init_ngene(void)
+{
+ printk(KERN_INFO
+ "nGene PCIE bridge driver, Copyright (C) 2005-2007 Micronas\n");
+ return pci_register_driver(&ngene_pci_driver);
+}
+
+static __exit void module_exit_ngene(void)
+{
+ pci_unregister_driver(&ngene_pci_driver);
+}
+
+module_init(module_init_ngene);
+module_exit(module_exit_ngene);
+
+MODULE_DESCRIPTION("nGene");
+MODULE_AUTHOR("Micronas, Ralph Metzler, Manfred Voelkel");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/ngene/ngene.h b/drivers/media/dvb/ngene/ngene.h
new file mode 100644
index 000000000000..a7eb29846310
--- /dev/null
+++ b/drivers/media/dvb/ngene/ngene.h
@@ -0,0 +1,859 @@
+/*
+ * ngene.h: nGene PCIe bridge driver
+ *
+ * Copyright (C) 2005-2007 Micronas
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 only, as published by the Free Software Foundation.
+ *
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ */
+
+#ifndef _NGENE_H_
+#define _NGENE_H_
+
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <asm/dma.h>
+#include <linux/scatterlist.h>
+
+#include <linux/dvb/frontend.h>
+
+#include "dmxdev.h"
+#include "dvbdev.h"
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+#include "dvb_ringbuffer.h"
+
+#define NGENE_VID 0x18c3
+#define NGENE_PID 0x0720
+
+#ifndef VIDEO_CAP_VC1
+#define VIDEO_CAP_AVC 128
+#define VIDEO_CAP_H264 128
+#define VIDEO_CAP_VC1 256
+#define VIDEO_CAP_WMV9 256
+#define VIDEO_CAP_MPEG4 512
+#endif
+
+enum STREAM {
+ STREAM_VIDEOIN1 = 0, /* ITU656 or TS Input */
+ STREAM_VIDEOIN2,
+ STREAM_AUDIOIN1, /* I2S or SPI Input */
+ STREAM_AUDIOIN2,
+ STREAM_AUDIOOUT,
+ MAX_STREAM
+};
+
+enum SMODE_BITS {
+ SMODE_AUDIO_SPDIF = 0x20,
+ SMODE_AVSYNC = 0x10,
+ SMODE_TRANSPORT_STREAM = 0x08,
+ SMODE_AUDIO_CAPTURE = 0x04,
+ SMODE_VBI_CAPTURE = 0x02,
+ SMODE_VIDEO_CAPTURE = 0x01
+};
+
+enum STREAM_FLAG_BITS {
+ SFLAG_CHROMA_FORMAT_2COMP = 0x01, /* Chroma Format : 2's complement */
+ SFLAG_CHROMA_FORMAT_OFFSET = 0x00, /* Chroma Format : Binary offset */
+ SFLAG_ORDER_LUMA_CHROMA = 0x02, /* Byte order: Y,Cb,Y,Cr */
+ SFLAG_ORDER_CHROMA_LUMA = 0x00, /* Byte order: Cb,Y,Cr,Y */
+ SFLAG_COLORBAR = 0x04, /* Select colorbar */
+};
+
+#define PROGRAM_ROM 0x0000
+#define PROGRAM_SRAM 0x1000
+#define PERIPHERALS0 0x8000
+#define PERIPHERALS1 0x9000
+#define SHARED_BUFFER 0xC000
+
+#define HOST_TO_NGENE (SHARED_BUFFER+0x0000)
+#define NGENE_TO_HOST (SHARED_BUFFER+0x0100)
+#define NGENE_COMMAND (SHARED_BUFFER+0x0200)
+#define NGENE_COMMAND_HI (SHARED_BUFFER+0x0204)
+#define NGENE_STATUS (SHARED_BUFFER+0x0208)
+#define NGENE_STATUS_HI (SHARED_BUFFER+0x020C)
+#define NGENE_EVENT (SHARED_BUFFER+0x0210)
+#define NGENE_EVENT_HI (SHARED_BUFFER+0x0214)
+#define VARIABLES (SHARED_BUFFER+0x0210)
+
+#define NGENE_INT_COUNTS (SHARED_BUFFER+0x0260)
+#define NGENE_INT_ENABLE (SHARED_BUFFER+0x0264)
+#define NGENE_VBI_LINE_COUNT (SHARED_BUFFER+0x0268)
+
+#define BUFFER_GP_XMIT (SHARED_BUFFER+0x0800)
+#define BUFFER_GP_RECV (SHARED_BUFFER+0x0900)
+#define EEPROM_AREA (SHARED_BUFFER+0x0A00)
+
+#define SG_V_IN_1 (SHARED_BUFFER+0x0A80)
+#define SG_VBI_1 (SHARED_BUFFER+0x0B00)
+#define SG_A_IN_1 (SHARED_BUFFER+0x0B80)
+#define SG_V_IN_2 (SHARED_BUFFER+0x0C00)
+#define SG_VBI_2 (SHARED_BUFFER+0x0C80)
+#define SG_A_IN_2 (SHARED_BUFFER+0x0D00)
+#define SG_V_OUT (SHARED_BUFFER+0x0D80)
+#define SG_A_OUT2 (SHARED_BUFFER+0x0E00)
+
+#define DATA_A_IN_1 (SHARED_BUFFER+0x0E80)
+#define DATA_A_IN_2 (SHARED_BUFFER+0x0F00)
+#define DATA_A_OUT (SHARED_BUFFER+0x0F80)
+#define DATA_V_IN_1 (SHARED_BUFFER+0x1000)
+#define DATA_V_IN_2 (SHARED_BUFFER+0x2000)
+#define DATA_V_OUT (SHARED_BUFFER+0x3000)
+
+#define DATA_FIFO_AREA (SHARED_BUFFER+0x1000)
+
+#define TIMESTAMPS 0xA000
+#define SCRATCHPAD 0xA080
+#define FORCE_INT 0xA088
+#define FORCE_NMI 0xA090
+#define INT_STATUS 0xA0A0
+
+#define DEV_VER 0x9004
+
+#define FW_DEBUG_DEFAULT (PROGRAM_SRAM+0x00FF)
+
+struct SG_ADDR {
+ u64 start;
+ u64 curr;
+ u16 curr_ptr;
+ u16 elements;
+ u32 pad[3];
+} __attribute__ ((__packed__));
+
+struct SHARED_MEMORY {
+ /* C000 */
+ u32 HostToNgene[64];
+
+ /* C100 */
+ u32 NgeneToHost[64];
+
+ /* C200 */
+ u64 NgeneCommand;
+ u64 NgeneStatus;
+ u64 NgeneEvent;
+
+ /* C210 */
+ u8 pad1[0xc260 - 0xc218];
+
+ /* C260 */
+ u32 IntCounts;
+ u32 IntEnable;
+
+ /* C268 */
+ u8 pad2[0xd000 - 0xc268];
+
+} __attribute__ ((__packed__));
+
+struct BUFFER_STREAM_RESULTS {
+ u32 Clock; /* Stream time in 100ns units */
+ u16 RemainingLines; /* Remaining lines in this field.
+ 0 for complete field */
+ u8 FieldCount; /* Video field number */
+ u8 Flags; /* Bit 7 = Done, Bit 6 = seen, Bit 5 = overflow,
+ Bit 0 = FieldID */
+ u16 BlockCount; /* Audio block count (unused) */
+ u8 Reserved[2];
+ u32 DTOUpdate;
+} __attribute__ ((__packed__));
+
+struct HW_SCATTER_GATHER_ELEMENT {
+ u64 Address;
+ u32 Length;
+ u32 Reserved;
+} __attribute__ ((__packed__));
+
+struct BUFFER_HEADER {
+ u64 Next;
+ struct BUFFER_STREAM_RESULTS SR;
+
+ u32 Number_of_entries_1;
+ u32 Reserved5;
+ u64 Address_of_first_entry_1;
+
+ u32 Number_of_entries_2;
+ u32 Reserved7;
+ u64 Address_of_first_entry_2;
+} __attribute__ ((__packed__));
+
+struct EVENT_BUFFER {
+ u32 TimeStamp;
+ u8 GPIOStatus;
+ u8 UARTStatus;
+ u8 RXCharacter;
+ u8 EventStatus;
+ u32 Reserved[2];
+} __attribute__ ((__packed__));
+
+/* Firmware commands. */
+
+enum OPCODES {
+ CMD_NOP = 0,
+ CMD_FWLOAD_PREPARE = 0x01,
+ CMD_FWLOAD_FINISH = 0x02,
+ CMD_I2C_READ = 0x03,
+ CMD_I2C_WRITE = 0x04,
+
+ CMD_I2C_WRITE_NOSTOP = 0x05,
+ CMD_I2C_CONTINUE_WRITE = 0x06,
+ CMD_I2C_CONTINUE_WRITE_NOSTOP = 0x07,
+
+ CMD_DEBUG_OUTPUT = 0x09,
+
+ CMD_CONTROL = 0x10,
+ CMD_CONFIGURE_BUFFER = 0x11,
+ CMD_CONFIGURE_FREE_BUFFER = 0x12,
+
+ CMD_SPI_READ = 0x13,
+ CMD_SPI_WRITE = 0x14,
+
+ CMD_MEM_READ = 0x20,
+ CMD_MEM_WRITE = 0x21,
+ CMD_SFR_READ = 0x22,
+ CMD_SFR_WRITE = 0x23,
+ CMD_IRAM_READ = 0x24,
+ CMD_IRAM_WRITE = 0x25,
+ CMD_SET_GPIO_PIN = 0x26,
+ CMD_SET_GPIO_INT = 0x27,
+ CMD_CONFIGURE_UART = 0x28,
+ CMD_WRITE_UART = 0x29,
+ MAX_CMD
+};
+
+enum RESPONSES {
+ OK = 0,
+ ERROR = 1
+};
+
+struct FW_HEADER {
+ u8 Opcode;
+ u8 Length;
+} __attribute__ ((__packed__));
+
+struct FW_I2C_WRITE {
+ struct FW_HEADER hdr;
+ u8 Device;
+ u8 Data[250];
+} __attribute__ ((__packed__));
+
+struct FW_I2C_CONTINUE_WRITE {
+ struct FW_HEADER hdr;
+ u8 Data[250];
+} __attribute__ ((__packed__));
+
+struct FW_I2C_READ {
+ struct FW_HEADER hdr;
+ u8 Device;
+ u8 Data[252]; /* followed by two bytes of read data count */
+} __attribute__ ((__packed__));
+
+struct FW_SPI_WRITE {
+ struct FW_HEADER hdr;
+ u8 ModeSelect;
+ u8 Data[250];
+} __attribute__ ((__packed__));
+
+struct FW_SPI_READ {
+ struct FW_HEADER hdr;
+ u8 ModeSelect;
+ u8 Data[252]; /* followed by two bytes of read data count */
+} __attribute__ ((__packed__));
+
+struct FW_FWLOAD_PREPARE {
+ struct FW_HEADER hdr;
+} __attribute__ ((__packed__));
+
+struct FW_FWLOAD_FINISH {
+ struct FW_HEADER hdr;
+ u16 Address; /* address of final block */
+ u16 Length;
+} __attribute__ ((__packed__));
+
+/*
+ * Meaning of FW_STREAM_CONTROL::Mode bits:
+ * Bit 7: Loopback PEXin to PEXout using TVOut channel
+ * Bit 6: AVLOOP
+ * Bit 5: Audio select; 0=I2S, 1=SPDIF
+ * Bit 4: AVSYNC
+ * Bit 3: Enable transport stream
+ * Bit 2: Enable audio capture
+ * Bit 1: Enable ITU-Video VBI capture
+ * Bit 0: Enable ITU-Video capture
+ *
+ * Meaning of FW_STREAM_CONTROL::Control bits (see UVI1_CTL)
+ * Bit 7: continuous capture
+ * Bit 6: capture one field
+ * Bit 5: capture one frame
+ * Bit 4: unused
+ * Bit 3: starting field; 0=odd, 1=even
+ * Bit 2: sample size; 0=8-bit, 1=10-bit
+ * Bit 1: data format; 0=UYVY, 1=YUY2
+ * Bit 0: resets buffer pointers
+*/
+
+enum FSC_MODE_BITS {
+ SMODE_LOOPBACK = 0x80,
+ SMODE_AVLOOP = 0x40,
+ _SMODE_AUDIO_SPDIF = 0x20,
+ _SMODE_AVSYNC = 0x10,
+ _SMODE_TRANSPORT_STREAM = 0x08,
+ _SMODE_AUDIO_CAPTURE = 0x04,
+ _SMODE_VBI_CAPTURE = 0x02,
+ _SMODE_VIDEO_CAPTURE = 0x01
+};
+
+
+/* Meaning of FW_STREAM_CONTROL::Stream bits:
+ * Bit 3: Audio sample count: 0 = relative, 1 = absolute
+ * Bit 2: color bar select; 1=color bars, 0=CV3 decoder
+ * Bits 1-0: stream select, UVI1, UVI2, TVOUT
+ */
+
+struct FW_STREAM_CONTROL {
+ struct FW_HEADER hdr;
+ u8 Stream; /* Stream number (UVI1, UVI2, TVOUT) */
+ u8 Control; /* Value written to UVI1_CTL */
+ u8 Mode; /* Controls clock source */
+ u8 SetupDataLen; /* Length of setup data, MSB=1 write
+ backwards */
+ u16 CaptureBlockCount; /* Blocks (a 256 Bytes) to capture per buffer
+ for TS and Audio */
+ u64 Buffer_Address; /* Address of first buffer header */
+ u16 BytesPerVideoLine;
+ u16 MaxLinesPerField;
+ u16 MinLinesPerField;
+ u16 Reserved_1;
+ u16 BytesPerVBILine;
+ u16 MaxVBILinesPerField;
+ u16 MinVBILinesPerField;
+ u16 SetupDataAddr; /* ngene relative address of setup data */
+ u8 SetupData[32]; /* setup data */
+} __attribute__((__packed__));
+
+#define AUDIO_BLOCK_SIZE 256
+#define TS_BLOCK_SIZE 256
+
+struct FW_MEM_READ {
+ struct FW_HEADER hdr;
+ u16 address;
+} __attribute__ ((__packed__));
+
+struct FW_MEM_WRITE {
+ struct FW_HEADER hdr;
+ u16 address;
+ u8 data;
+} __attribute__ ((__packed__));
+
+struct FW_SFR_IRAM_READ {
+ struct FW_HEADER hdr;
+ u8 address;
+} __attribute__ ((__packed__));
+
+struct FW_SFR_IRAM_WRITE {
+ struct FW_HEADER hdr;
+ u8 address;
+ u8 data;
+} __attribute__ ((__packed__));
+
+struct FW_SET_GPIO_PIN {
+ struct FW_HEADER hdr;
+ u8 select;
+} __attribute__ ((__packed__));
+
+struct FW_SET_GPIO_INT {
+ struct FW_HEADER hdr;
+ u8 select;
+} __attribute__ ((__packed__));
+
+struct FW_SET_DEBUGMODE {
+ struct FW_HEADER hdr;
+ u8 debug_flags;
+} __attribute__ ((__packed__));
+
+struct FW_CONFIGURE_BUFFERS {
+ struct FW_HEADER hdr;
+ u8 config;
+} __attribute__ ((__packed__));
+
+enum _BUFFER_CONFIGS {
+ /* 4k UVI1, 4k UVI2, 2k AUD1, 2k AUD2 (standard usage) */
+ BUFFER_CONFIG_4422 = 0,
+ /* 3k UVI1, 3k UVI2, 3k AUD1, 3k AUD2 (4x TS input usage) */
+ BUFFER_CONFIG_3333 = 1,
+ /* 8k UVI1, 0k UVI2, 2k AUD1, 2k I2SOut (HDTV decoder usage) */
+ BUFFER_CONFIG_8022 = 2,
+ BUFFER_CONFIG_FW17 = 255, /* Use new FW 17 command */
+};
+
+struct FW_CONFIGURE_FREE_BUFFERS {
+ struct FW_HEADER hdr;
+ u8 UVI1_BufferLength;
+ u8 UVI2_BufferLength;
+ u8 TVO_BufferLength;
+ u8 AUD1_BufferLength;
+ u8 AUD2_BufferLength;
+ u8 TVA_BufferLength;
+} __attribute__ ((__packed__));
+
+struct FW_CONFIGURE_UART {
+ struct FW_HEADER hdr;
+ u8 UartControl;
+} __attribute__ ((__packed__));
+
+enum _UART_CONFIG {
+ _UART_BAUDRATE_19200 = 0,
+ _UART_BAUDRATE_9600 = 1,
+ _UART_BAUDRATE_4800 = 2,
+ _UART_BAUDRATE_2400 = 3,
+ _UART_RX_ENABLE = 0x40,
+ _UART_TX_ENABLE = 0x80,
+};
+
+struct FW_WRITE_UART {
+ struct FW_HEADER hdr;
+ u8 Data[252];
+} __attribute__ ((__packed__));
+
+
+struct ngene_command {
+ u32 in_len;
+ u32 out_len;
+ union {
+ u32 raw[64];
+ u8 raw8[256];
+ struct FW_HEADER hdr;
+ struct FW_I2C_WRITE I2CWrite;
+ struct FW_I2C_CONTINUE_WRITE I2CContinueWrite;
+ struct FW_I2C_READ I2CRead;
+ struct FW_STREAM_CONTROL StreamControl;
+ struct FW_FWLOAD_PREPARE FWLoadPrepare;
+ struct FW_FWLOAD_FINISH FWLoadFinish;
+ struct FW_MEM_READ MemoryRead;
+ struct FW_MEM_WRITE MemoryWrite;
+ struct FW_SFR_IRAM_READ SfrIramRead;
+ struct FW_SFR_IRAM_WRITE SfrIramWrite;
+ struct FW_SPI_WRITE SPIWrite;
+ struct FW_SPI_READ SPIRead;
+ struct FW_SET_GPIO_PIN SetGpioPin;
+ struct FW_SET_GPIO_INT SetGpioInt;
+ struct FW_SET_DEBUGMODE SetDebugMode;
+ struct FW_CONFIGURE_BUFFERS ConfigureBuffers;
+ struct FW_CONFIGURE_FREE_BUFFERS ConfigureFreeBuffers;
+ struct FW_CONFIGURE_UART ConfigureUart;
+ struct FW_WRITE_UART WriteUart;
+ } cmd;
+} __attribute__ ((__packed__));
+
+#define NGENE_INTERFACE_VERSION 0x103
+#define MAX_VIDEO_BUFFER_SIZE (417792) /* 288*1440 rounded up to next page */
+#define MAX_AUDIO_BUFFER_SIZE (8192) /* Gives room for about 23msec@48KHz */
+#define MAX_VBI_BUFFER_SIZE (28672) /* 1144*18 rounded up to next page */
+#define MAX_TS_BUFFER_SIZE (98304) /* 512*188 rounded up to next page */
+#define MAX_HDTV_BUFFER_SIZE (2080768) /* 541*1920*2 rounded up to next page
+ Max: (1920x1080i60) */
+
+#define OVERFLOW_BUFFER_SIZE (8192)
+
+#define RING_SIZE_VIDEO 4
+#define RING_SIZE_AUDIO 8
+#define RING_SIZE_TS 8
+
+#define NUM_SCATTER_GATHER_ENTRIES 8
+
+#define MAX_DMA_LENGTH (((MAX_VIDEO_BUFFER_SIZE + MAX_VBI_BUFFER_SIZE) * \
+ RING_SIZE_VIDEO * 2) + \
+ (MAX_AUDIO_BUFFER_SIZE * RING_SIZE_AUDIO * 2) + \
+ (MAX_TS_BUFFER_SIZE * RING_SIZE_TS * 4) + \
+ (RING_SIZE_VIDEO * PAGE_SIZE * 2) + \
+ (RING_SIZE_AUDIO * PAGE_SIZE * 2) + \
+ (RING_SIZE_TS * PAGE_SIZE * 4) + \
+ 8 * PAGE_SIZE + OVERFLOW_BUFFER_SIZE + PAGE_SIZE)
+
+#define EVENT_QUEUE_SIZE 16
+
+/* Gathers the current state of a single channel. */
+
+struct SBufferHeader {
+ struct BUFFER_HEADER ngeneBuffer; /* Physical descriptor */
+ struct SBufferHeader *Next;
+ void *Buffer1;
+ struct HW_SCATTER_GATHER_ELEMENT *scList1;
+ void *Buffer2;
+ struct HW_SCATTER_GATHER_ELEMENT *scList2;
+};
+
+/* Sizeof SBufferHeader aligned to next 64 Bit boundary (hw restriction) */
+#define SIZEOF_SBufferHeader ((sizeof(struct SBufferHeader) + 63) & ~63)
+
+enum HWSTATE {
+ HWSTATE_STOP,
+ HWSTATE_STARTUP,
+ HWSTATE_RUN,
+ HWSTATE_PAUSE,
+};
+
+enum KSSTATE {
+ KSSTATE_STOP,
+ KSSTATE_ACQUIRE,
+ KSSTATE_PAUSE,
+ KSSTATE_RUN,
+};
+
+struct SRingBufferDescriptor {
+ struct SBufferHeader *Head; /* Points to first buffer in ring buffer
+ structure*/
+ u64 PAHead; /* Physical address of first buffer */
+ u32 MemSize; /* Memory size of allocated ring buffers
+ (needed for freeing) */
+ u32 NumBuffers; /* Number of buffers in the ring */
+ u32 Buffer1Length; /* Allocated length of Buffer 1 */
+ u32 Buffer2Length; /* Allocated length of Buffer 2 */
+ void *SCListMem; /* Memory to hold scatter gather lists for this
+ ring */
+ u64 PASCListMem; /* Physical address .. */
+ u32 SCListMemSize; /* Size of this memory */
+};
+
+enum STREAMMODEFLAGS {
+ StreamMode_NONE = 0, /* Stream not used */
+ StreamMode_ANALOG = 1, /* Analog: Stream 0,1 = Video, 2,3 = Audio */
+ StreamMode_TSIN = 2, /* Transport stream input (all) */
+ StreamMode_HDTV = 4, /* HDTV: Maximum 1920x1080p30,1920x1080i60
+ (only stream 0) */
+ StreamMode_TSOUT = 8, /* Transport stream output (only stream 3) */
+};
+
+
+enum BufferExchangeFlags {
+ BEF_EVEN_FIELD = 0x00000001,
+ BEF_CONTINUATION = 0x00000002,
+ BEF_MORE_DATA = 0x00000004,
+ BEF_OVERFLOW = 0x00000008,
+ DF_SWAP32 = 0x00010000,
+};
+
+typedef void *(IBufferExchange)(void *, void *, u32, u32, u32);
+
+struct MICI_STREAMINFO {
+ IBufferExchange *pExchange;
+ IBufferExchange *pExchangeVBI; /* Secondary (VBI, ancillary) */
+ u8 Stream;
+ u8 Flags;
+ u8 Mode;
+ u8 Reserved;
+ u16 nLinesVideo;
+ u16 nBytesPerLineVideo;
+ u16 nLinesVBI;
+ u16 nBytesPerLineVBI;
+ u32 CaptureLength; /* Used for audio and transport stream */
+};
+
+/****************************************************************************/
+/* STRUCTS ******************************************************************/
+/****************************************************************************/
+
+/* sound hardware definition */
+#define MIXER_ADDR_TVTUNER 0
+#define MIXER_ADDR_LAST 0
+
+struct ngene_channel;
+
+/*struct sound chip*/
+
+struct mychip {
+ struct ngene_channel *chan;
+ struct snd_card *card;
+ struct pci_dev *pci;
+ struct snd_pcm_substream *substream;
+ struct snd_pcm *pcm;
+ unsigned long port;
+ int irq;
+ spinlock_t mixer_lock;
+ spinlock_t lock;
+ int mixer_volume[MIXER_ADDR_LAST + 1][2];
+ int capture_source[MIXER_ADDR_LAST + 1][2];
+};
+
+#ifdef NGENE_V4L
+struct ngene_overlay {
+ int tvnorm;
+ struct v4l2_rect w;
+ enum v4l2_field field;
+ struct v4l2_clip *clips;
+ int nclips;
+ int setup_ok;
+};
+
+struct ngene_tvnorm {
+ int v4l2_id;
+ char *name;
+ u16 swidth, sheight; /* scaled standard width, height */
+ int tuner_norm;
+ int soundstd;
+};
+
+struct ngene_vopen {
+ struct ngene_channel *ch;
+ enum v4l2_priority prio;
+ int width;
+ int height;
+ int depth;
+ struct videobuf_queue vbuf_q;
+ struct videobuf_queue vbi;
+ int fourcc;
+ int picxcount;
+ int resources;
+ enum v4l2_buf_type type;
+ const struct ngene_format *fmt;
+
+ const struct ngene_format *ovfmt;
+ struct ngene_overlay ov;
+};
+#endif
+
+struct ngene_channel {
+ struct device device;
+ struct i2c_adapter i2c_adapter;
+
+ struct ngene *dev;
+ int number;
+ int type;
+ int mode;
+
+ struct dvb_frontend *fe;
+ struct dmxdev dmxdev;
+ struct dvb_demux demux;
+ struct dmx_frontend hw_frontend;
+ struct dmx_frontend mem_frontend;
+ int users;
+ struct video_device *v4l_dev;
+ struct tasklet_struct demux_tasklet;
+
+ struct SBufferHeader *nextBuffer;
+ enum KSSTATE State;
+ enum HWSTATE HWState;
+ u8 Stream;
+ u8 Flags;
+ u8 Mode;
+ IBufferExchange *pBufferExchange;
+ IBufferExchange *pBufferExchange2;
+
+ spinlock_t state_lock;
+ u16 nLines;
+ u16 nBytesPerLine;
+ u16 nVBILines;
+ u16 nBytesPerVBILine;
+ u16 itumode;
+ u32 Capture1Length;
+ u32 Capture2Length;
+ struct SRingBufferDescriptor RingBuffer;
+ struct SRingBufferDescriptor TSRingBuffer;
+ struct SRingBufferDescriptor TSIdleBuffer;
+
+ u32 DataFormatFlags;
+
+ int AudioDTOUpdated;
+ u32 AudioDTOValue;
+
+ int (*set_tone)(struct dvb_frontend *, fe_sec_tone_mode_t);
+ u8 lnbh;
+
+ /* stuff from analog driver */
+
+ int minor;
+ struct mychip *mychip;
+ struct snd_card *soundcard;
+ u8 *evenbuffer;
+ u8 dma_on;
+ int soundstreamon;
+ int audiomute;
+ int soundbuffisallocated;
+ int sndbuffflag;
+ int tun_rdy;
+ int dec_rdy;
+ int tun_dec_rdy;
+ int lastbufferflag;
+
+ struct ngene_tvnorm *tvnorms;
+ int tvnorm_num;
+ int tvnorm;
+
+#ifdef NGENE_V4L
+ int videousers;
+ struct v4l2_prio_state prio;
+ struct ngene_vopen init;
+ int resources;
+ struct v4l2_framebuffer fbuf;
+ struct ngene_buffer *screen; /* overlay */
+ struct list_head capture; /* video capture queue */
+ spinlock_t s_lock;
+ struct semaphore reslock;
+#endif
+
+ int running;
+};
+
+struct ngene;
+
+typedef void (rx_cb_t)(struct ngene *, u32, u8);
+typedef void (tx_cb_t)(struct ngene *, u32);
+
+struct ngene {
+ int nr;
+ struct pci_dev *pci_dev;
+ unsigned char *iomem;
+
+ /*struct i2c_adapter i2c_adapter;*/
+
+ u32 device_version;
+ u32 fw_interface_version;
+ u32 icounts;
+
+ u8 *CmdDoneByte;
+ int BootFirmware;
+ void *OverflowBuffer;
+ dma_addr_t PAOverflowBuffer;
+ void *FWInterfaceBuffer;
+ dma_addr_t PAFWInterfaceBuffer;
+ u8 *ngenetohost;
+ u8 *hosttongene;
+
+ struct EVENT_BUFFER EventQueue[EVENT_QUEUE_SIZE];
+ int EventQueueOverflowCount;
+ int EventQueueOverflowFlag;
+ struct tasklet_struct event_tasklet;
+ struct EVENT_BUFFER *EventBuffer;
+ int EventQueueWriteIndex;
+ int EventQueueReadIndex;
+
+ wait_queue_head_t cmd_wq;
+ int cmd_done;
+ struct semaphore cmd_mutex;
+ struct semaphore stream_mutex;
+ struct semaphore pll_mutex;
+ struct semaphore i2c_switch_mutex;
+ int i2c_current_channel;
+ int i2c_current_bus;
+ spinlock_t cmd_lock;
+
+ struct dvb_adapter adapter[MAX_STREAM];
+ struct ngene_channel channel[MAX_STREAM];
+
+ struct ngene_info *card_info;
+
+ tx_cb_t *TxEventNotify;
+ rx_cb_t *RxEventNotify;
+ int tx_busy;
+ wait_queue_head_t tx_wq;
+ wait_queue_head_t rx_wq;
+#define UART_RBUF_LEN 4096
+ u8 uart_rbuf[UART_RBUF_LEN];
+ int uart_rp, uart_wp;
+
+ u8 *tsout_buf;
+#define TSOUT_BUF_SIZE (512*188*8)
+ struct dvb_ringbuffer tsout_rbuf;
+
+ u8 *ain_buf;
+#define AIN_BUF_SIZE (128*1024)
+ struct dvb_ringbuffer ain_rbuf;
+
+
+ u8 *vin_buf;
+#define VIN_BUF_SIZE (4*1920*1080)
+ struct dvb_ringbuffer vin_rbuf;
+
+ unsigned long exp_val;
+ int prev_cmd;
+};
+
+struct ngene_info {
+ int type;
+#define NGENE_APP 0
+#define NGENE_TERRATEC 1
+#define NGENE_SIDEWINDER 2
+#define NGENE_RACER 3
+#define NGENE_VIPER 4
+#define NGENE_PYTHON 5
+#define NGENE_VBOX_V1 6
+#define NGENE_VBOX_V2 7
+
+ int fw_version;
+ char *name;
+
+ int io_type[MAX_STREAM];
+#define NGENE_IO_NONE 0
+#define NGENE_IO_TV 1
+#define NGENE_IO_HDTV 2
+#define NGENE_IO_TSIN 4
+#define NGENE_IO_TSOUT 8
+#define NGENE_IO_AIN 16
+
+ void *fe_config[4];
+ void *tuner_config[4];
+
+ int (*demod_attach[4])(struct ngene_channel *);
+ int (*tuner_attach[4])(struct ngene_channel *);
+
+ u8 avf[4];
+ u8 msp[4];
+ u8 demoda[4];
+ u8 lnb[4];
+ int i2c_access;
+ u8 ntsc;
+ u8 tsf[4];
+ u8 i2s[4];
+
+ int (*gate_ctrl)(struct dvb_frontend *, int);
+ int (*switch_ctrl)(struct ngene_channel *, int, int);
+};
+
+#ifdef NGENE_V4L
+struct ngene_format{
+ char *name;
+ int fourcc; /* video4linux 2 */
+ int btformat; /* BT848_COLOR_FMT_* */
+ int format;
+ int btswap; /* BT848_COLOR_CTL_* */
+ int depth; /* bit/pixel */
+ int flags;
+ int hshift, vshift; /* for planar modes */
+ int palette;
+};
+
+#define RESOURCE_OVERLAY 1
+#define RESOURCE_VIDEO 2
+#define RESOURCE_VBI 4
+
+struct ngene_buffer {
+ /* common v4l buffer stuff -- must be first */
+ struct videobuf_buffer vb;
+
+ /* ngene specific */
+ const struct ngene_format *fmt;
+ int tvnorm;
+ int btformat;
+ int btswap;
+};
+#endif
+
+
+#endif
+
+/* LocalWords: Endif
+ */
diff --git a/drivers/media/dvb/siano/sms-cards.c b/drivers/media/dvb/siano/sms-cards.c
index 1067b22eb0c6..cff77e2eb557 100644
--- a/drivers/media/dvb/siano/sms-cards.c
+++ b/drivers/media/dvb/siano/sms-cards.c
@@ -62,6 +62,7 @@ static struct sms_board sms_boards[] = {
[SMS1XXX_BOARD_HAUPPAUGE_WINDHAM] = {
.name = "Hauppauge WinTV MiniStick",
.type = SMS_NOVA_B0,
+ .fw[DEVICE_MODE_ISDBT_BDA] = "sms1xxx-hcw-55xxx-isdbt-02.fw",
.fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-02.fw",
.board_cfg.leds_power = 26,
.board_cfg.led0 = 27,
diff --git a/drivers/media/dvb/siano/smscoreapi.c b/drivers/media/dvb/siano/smscoreapi.c
index ca758bcb48c9..4bfd3451b568 100644
--- a/drivers/media/dvb/siano/smscoreapi.c
+++ b/drivers/media/dvb/siano/smscoreapi.c
@@ -1459,8 +1459,10 @@ int smscore_gpio_configure(struct smscore_device_t *coredev, u8 PinNum,
if (!(coredev->device_flags & SMS_DEVICE_FAMILY2)) {
pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_CONFIG_REQ;
if (GetGpioPinParams(PinNum, &TranslatedPinNum, &GroupNum,
- &groupCfg) != 0)
- return -EINVAL;
+ &groupCfg) != 0) {
+ rc = -EINVAL;
+ goto free;
+ }
pMsg->msgData[1] = TranslatedPinNum;
pMsg->msgData[2] = GroupNum;
@@ -1490,6 +1492,7 @@ int smscore_gpio_configure(struct smscore_device_t *coredev, u8 PinNum,
else
sms_err("smscore_gpio_configure error");
}
+free:
kfree(buffer);
return rc;
diff --git a/drivers/media/dvb/siano/smscoreapi.h b/drivers/media/dvb/siano/smscoreapi.h
index eec18aaf5512..8ecadecaa9d0 100644
--- a/drivers/media/dvb/siano/smscoreapi.h
+++ b/drivers/media/dvb/siano/smscoreapi.h
@@ -212,6 +212,8 @@ struct smscore_device_t {
#define MSG_SMS_DAB_CHANNEL 607
#define MSG_SMS_GET_PID_FILTER_LIST_REQ 608
#define MSG_SMS_GET_PID_FILTER_LIST_RES 609
+#define MSG_SMS_GET_STATISTICS_RES 616
+#define MSG_SMS_GET_STATISTICS_REQ 615
#define MSG_SMS_HO_PER_SLICES_IND 630
#define MSG_SMS_SET_ANTENNA_CONFIG_REQ 651
#define MSG_SMS_SET_ANTENNA_CONFIG_RES 652
@@ -339,7 +341,7 @@ struct SmsFirmware_ST {
/* Statistics information returned as response for
* SmsHostApiGetStatistics_Req */
-struct SMSHOSTLIB_STATISTICS_S {
+struct SMSHOSTLIB_STATISTICS_ST {
u32 Reserved; /* Reserved */
/* Common parameters */
@@ -424,6 +426,79 @@ struct SMSHOSTLIB_STATISTICS_S {
u32 ReservedFields[10]; /* Reserved */
};
+struct SmsMsgStatisticsInfo_ST {
+ u32 RequestResult;
+
+ struct SMSHOSTLIB_STATISTICS_ST Stat;
+
+ /* Split the calc of the SNR in DAB */
+ u32 Signal; /* dB */
+ u32 Noise; /* dB */
+
+};
+
+struct SMSHOSTLIB_ISDBT_LAYER_STAT_ST {
+ /* Per-layer information */
+ u32 CodeRate; /* Code Rate from SMSHOSTLIB_CODE_RATE_ET,
+ * 255 means layer does not exist */
+ u32 Constellation; /* Constellation from SMSHOSTLIB_CONSTELLATION_ET,
+ * 255 means layer does not exist */
+ u32 BER; /* Post Viterbi BER [1E-5], 0xFFFFFFFF indicate N/A */
+ u32 BERErrorCount; /* Post Viterbi Error Bits Count */
+ u32 BERBitCount; /* Post Viterbi Total Bits Count */
+ u32 PreBER; /* Pre Viterbi BER [1E-5], 0xFFFFFFFF indicate N/A */
+ u32 TS_PER; /* Transport stream PER [%], 0xFFFFFFFF indicate N/A */
+ u32 ErrorTSPackets; /* Number of erroneous transport-stream packets */
+ u32 TotalTSPackets; /* Total number of transport-stream packets */
+ u32 TILdepthI; /* Time interleaver depth I parameter,
+ * 255 means layer does not exist */
+ u32 NumberOfSegments; /* Number of segments in layer A,
+ * 255 means layer does not exist */
+ u32 TMCCErrors; /* TMCC errors */
+};
+
+struct SMSHOSTLIB_STATISTICS_ISDBT_ST {
+ u32 StatisticsType; /* Enumerator identifying the type of the
+ * structure. Values are the same as
+ * SMSHOSTLIB_DEVICE_MODES_E
+ *
+ * This field MUST always be first in any
+ * statistics structure */
+
+ u32 FullSize; /* Total size of the structure returned by the modem.
+ * If the size requested by the host is smaller than
+ * FullSize, the struct will be truncated */
+
+ /* Common parameters */
+ u32 IsRfLocked; /* 0 - not locked, 1 - locked */
+ u32 IsDemodLocked; /* 0 - not locked, 1 - locked */
+ u32 IsExternalLNAOn; /* 0 - external LNA off, 1 - external LNA on */
+
+ /* Reception quality */
+ s32 SNR; /* dB */
+ s32 RSSI; /* dBm */
+ s32 InBandPwr; /* In band power in dBM */
+ s32 CarrierOffset; /* Carrier Offset in Hz */
+
+ /* Transmission parameters */
+ u32 Frequency; /* Frequency in Hz */
+ u32 Bandwidth; /* Bandwidth in MHz */
+ u32 TransmissionMode; /* ISDB-T transmission mode */
+ u32 ModemState; /* 0 - Acquisition, 1 - Locked */
+ u32 GuardInterval; /* Guard Interval, 1 divided by value */
+ u32 SystemType; /* ISDB-T system type (ISDB-T / ISDB-Tsb) */
+ u32 PartialReception; /* TRUE - partial reception, FALSE otherwise */
+ u32 NumOfLayers; /* Number of ISDB-T layers in the network */
+
+ /* Per-layer information */
+ /* Layers A, B and C */
+ struct SMSHOSTLIB_ISDBT_LAYER_STAT_ST LayerInfo[3];
+ /* Per-layer statistics, see SMSHOSTLIB_ISDBT_LAYER_STAT_ST */
+
+ /* Interface information */
+ u32 SmsToHostTxErrors; /* Total number of transmission errors. */
+};
+
struct PID_STATISTICS_DATA_S {
struct PID_BURST_S {
u32 size;
diff --git a/drivers/media/dvb/siano/smsdvb.c b/drivers/media/dvb/siano/smsdvb.c
index 68bf9fbd8fed..5f3939821ca3 100644
--- a/drivers/media/dvb/siano/smsdvb.c
+++ b/drivers/media/dvb/siano/smsdvb.c
@@ -116,6 +116,118 @@ static void sms_board_dvb3_event(struct smsdvb_client_t *client,
}
}
+
+static void smsdvb_update_dvb_stats(struct RECEPTION_STATISTICS_S *pReceptionData,
+ struct SMSHOSTLIB_STATISTICS_ST *p)
+{
+ if (sms_dbg & 2) {
+ printk(KERN_DEBUG "Reserved = %d", p->Reserved);
+ printk(KERN_DEBUG "IsRfLocked = %d", p->IsRfLocked);
+ printk(KERN_DEBUG "IsDemodLocked = %d", p->IsDemodLocked);
+ printk(KERN_DEBUG "IsExternalLNAOn = %d", p->IsExternalLNAOn);
+ printk(KERN_DEBUG "SNR = %d", p->SNR);
+ printk(KERN_DEBUG "BER = %d", p->BER);
+ printk(KERN_DEBUG "FIB_CRC = %d", p->FIB_CRC);
+ printk(KERN_DEBUG "TS_PER = %d", p->TS_PER);
+ printk(KERN_DEBUG "MFER = %d", p->MFER);
+ printk(KERN_DEBUG "RSSI = %d", p->RSSI);
+ printk(KERN_DEBUG "InBandPwr = %d", p->InBandPwr);
+ printk(KERN_DEBUG "CarrierOffset = %d", p->CarrierOffset);
+ printk(KERN_DEBUG "Frequency = %d", p->Frequency);
+ printk(KERN_DEBUG "Bandwidth = %d", p->Bandwidth);
+ printk(KERN_DEBUG "TransmissionMode = %d", p->TransmissionMode);
+ printk(KERN_DEBUG "ModemState = %d", p->ModemState);
+ printk(KERN_DEBUG "GuardInterval = %d", p->GuardInterval);
+ printk(KERN_DEBUG "CodeRate = %d", p->CodeRate);
+ printk(KERN_DEBUG "LPCodeRate = %d", p->LPCodeRate);
+ printk(KERN_DEBUG "Hierarchy = %d", p->Hierarchy);
+ printk(KERN_DEBUG "Constellation = %d", p->Constellation);
+ printk(KERN_DEBUG "BurstSize = %d", p->BurstSize);
+ printk(KERN_DEBUG "BurstDuration = %d", p->BurstDuration);
+ printk(KERN_DEBUG "BurstCycleTime = %d", p->BurstCycleTime);
+ printk(KERN_DEBUG "CalculatedBurstCycleTime = %d", p->CalculatedBurstCycleTime);
+ printk(KERN_DEBUG "NumOfRows = %d", p->NumOfRows);
+ printk(KERN_DEBUG "NumOfPaddCols = %d", p->NumOfPaddCols);
+ printk(KERN_DEBUG "NumOfPunctCols = %d", p->NumOfPunctCols);
+ printk(KERN_DEBUG "ErrorTSPackets = %d", p->ErrorTSPackets);
+ printk(KERN_DEBUG "TotalTSPackets = %d", p->TotalTSPackets);
+ printk(KERN_DEBUG "NumOfValidMpeTlbs = %d", p->NumOfValidMpeTlbs);
+ printk(KERN_DEBUG "NumOfInvalidMpeTlbs = %d", p->NumOfInvalidMpeTlbs);
+ printk(KERN_DEBUG "NumOfCorrectedMpeTlbs = %d", p->NumOfCorrectedMpeTlbs);
+ printk(KERN_DEBUG "BERErrorCount = %d", p->BERErrorCount);
+ printk(KERN_DEBUG "BERBitCount = %d", p->BERBitCount);
+ printk(KERN_DEBUG "SmsToHostTxErrors = %d", p->SmsToHostTxErrors);
+ printk(KERN_DEBUG "PreBER = %d", p->PreBER);
+ printk(KERN_DEBUG "CellId = %d", p->CellId);
+ printk(KERN_DEBUG "DvbhSrvIndHP = %d", p->DvbhSrvIndHP);
+ printk(KERN_DEBUG "DvbhSrvIndLP = %d", p->DvbhSrvIndLP);
+ printk(KERN_DEBUG "NumMPEReceived = %d", p->NumMPEReceived);
+ }
+
+ pReceptionData->IsDemodLocked = p->IsDemodLocked;
+
+ pReceptionData->SNR = p->SNR;
+ pReceptionData->BER = p->BER;
+ pReceptionData->BERErrorCount = p->BERErrorCount;
+ pReceptionData->InBandPwr = p->InBandPwr;
+ pReceptionData->ErrorTSPackets = p->ErrorTSPackets;
+};
+
+
+static void smsdvb_update_isdbt_stats(struct RECEPTION_STATISTICS_S *pReceptionData,
+ struct SMSHOSTLIB_STATISTICS_ISDBT_ST *p)
+{
+ int i;
+
+ if (sms_dbg & 2) {
+ printk(KERN_DEBUG "IsRfLocked = %d", p->IsRfLocked);
+ printk(KERN_DEBUG "IsDemodLocked = %d", p->IsDemodLocked);
+ printk(KERN_DEBUG "IsExternalLNAOn = %d", p->IsExternalLNAOn);
+ printk(KERN_DEBUG "SNR = %d", p->SNR);
+ printk(KERN_DEBUG "RSSI = %d", p->RSSI);
+ printk(KERN_DEBUG "InBandPwr = %d", p->InBandPwr);
+ printk(KERN_DEBUG "CarrierOffset = %d", p->CarrierOffset);
+ printk(KERN_DEBUG "Frequency = %d", p->Frequency);
+ printk(KERN_DEBUG "Bandwidth = %d", p->Bandwidth);
+ printk(KERN_DEBUG "TransmissionMode = %d", p->TransmissionMode);
+ printk(KERN_DEBUG "ModemState = %d", p->ModemState);
+ printk(KERN_DEBUG "GuardInterval = %d", p->GuardInterval);
+ printk(KERN_DEBUG "SystemType = %d", p->SystemType);
+ printk(KERN_DEBUG "PartialReception = %d", p->PartialReception);
+ printk(KERN_DEBUG "NumOfLayers = %d", p->NumOfLayers);
+ printk(KERN_DEBUG "SmsToHostTxErrors = %d", p->SmsToHostTxErrors);
+
+ for (i = 0; i < 3; i++) {
+ printk(KERN_DEBUG "%d: CodeRate = %d", i, p->LayerInfo[i].CodeRate);
+ printk(KERN_DEBUG "%d: Constellation = %d", i, p->LayerInfo[i].Constellation);
+ printk(KERN_DEBUG "%d: BER = %d", i, p->LayerInfo[i].BER);
+ printk(KERN_DEBUG "%d: BERErrorCount = %d", i, p->LayerInfo[i].BERErrorCount);
+ printk(KERN_DEBUG "%d: BERBitCount = %d", i, p->LayerInfo[i].BERBitCount);
+ printk(KERN_DEBUG "%d: PreBER = %d", i, p->LayerInfo[i].PreBER);
+ printk(KERN_DEBUG "%d: TS_PER = %d", i, p->LayerInfo[i].TS_PER);
+ printk(KERN_DEBUG "%d: ErrorTSPackets = %d", i, p->LayerInfo[i].ErrorTSPackets);
+ printk(KERN_DEBUG "%d: TotalTSPackets = %d", i, p->LayerInfo[i].TotalTSPackets);
+ printk(KERN_DEBUG "%d: TILdepthI = %d", i, p->LayerInfo[i].TILdepthI);
+ printk(KERN_DEBUG "%d: NumberOfSegments = %d", i, p->LayerInfo[i].NumberOfSegments);
+ printk(KERN_DEBUG "%d: TMCCErrors = %d", i, p->LayerInfo[i].TMCCErrors);
+ }
+ }
+
+ pReceptionData->IsDemodLocked = p->IsDemodLocked;
+
+ pReceptionData->SNR = p->SNR;
+ pReceptionData->InBandPwr = p->InBandPwr;
+
+ pReceptionData->ErrorTSPackets = 0;
+ pReceptionData->BER = 0;
+ pReceptionData->BERErrorCount = 0;
+ for (i = 0; i < 3; i++) {
+ pReceptionData->BER += p->LayerInfo[i].BER;
+ pReceptionData->BERErrorCount += p->LayerInfo[i].BERErrorCount;
+ pReceptionData->ErrorTSPackets += p->LayerInfo[i].ErrorTSPackets;
+ }
+}
+
static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb)
{
struct smsdvb_client_t *client = (struct smsdvb_client_t *) context;
@@ -134,6 +246,7 @@ static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb)
break;
case MSG_SMS_RF_TUNE_RES:
+ case MSG_SMS_ISDBT_TUNE_RES:
complete(&client->tune_done);
break;
@@ -217,6 +330,40 @@ static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb)
is_status_update = true;
break;
}
+ case MSG_SMS_GET_STATISTICS_RES: {
+ union {
+ struct SMSHOSTLIB_STATISTICS_ISDBT_ST isdbt;
+ struct SmsMsgStatisticsInfo_ST dvb;
+ } *p = (void *) (phdr + 1);
+ struct RECEPTION_STATISTICS_S *pReceptionData =
+ &client->sms_stat_dvb.ReceptionData;
+
+ sms_info("MSG_SMS_GET_STATISTICS_RES");
+
+ is_status_update = true;
+
+ switch (smscore_get_device_mode(client->coredev)) {
+ case DEVICE_MODE_ISDBT:
+ case DEVICE_MODE_ISDBT_BDA:
+ smsdvb_update_isdbt_stats(pReceptionData, &p->isdbt);
+ break;
+ default:
+ smsdvb_update_dvb_stats(pReceptionData, &p->dvb.Stat);
+ }
+ if (!pReceptionData->IsDemodLocked) {
+ pReceptionData->SNR = 0;
+ pReceptionData->BER = 0;
+ pReceptionData->BERErrorCount = 0;
+ pReceptionData->InBandPwr = 0;
+ pReceptionData->ErrorTSPackets = 0;
+ }
+
+ complete(&client->tune_done);
+ break;
+ }
+ default:
+ sms_info("Unhandled message %d", phdr->msgType);
+
}
smscore_putbuffer(client->coredev, cb);
@@ -233,10 +380,10 @@ static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb)
DVB3_EVENT_UNC_ERR);
} else {
- /*client->fe_status =
- (phdr->msgType == MSG_SMS_NO_SIGNAL_IND) ?
- 0 : FE_HAS_SIGNAL;*/
- client->fe_status = 0;
+ if (client->sms_stat_dvb.ReceptionData.IsRfLocked)
+ client->fe_status = FE_HAS_SIGNAL | FE_HAS_CARRIER;
+ else
+ client->fe_status = 0;
sms_board_dvb3_event(client, DVB3_EVENT_FE_UNLOCK);
}
}
@@ -325,6 +472,20 @@ static int smsdvb_sendrequest_and_wait(struct smsdvb_client_t *client,
0 : -ETIME;
}
+static int smsdvb_send_statistics_request(struct smsdvb_client_t *client)
+{
+ int rc;
+ struct SmsMsgHdr_ST Msg = { MSG_SMS_GET_STATISTICS_REQ,
+ DVBT_BDA_CONTROL_MSG_ID,
+ HIF_TASK,
+ sizeof(struct SmsMsgHdr_ST), 0 };
+
+ rc = smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg),
+ &client->tune_done);
+
+ return rc;
+}
+
static inline int led_feedback(struct smsdvb_client_t *client)
{
if (client->fe_status & FE_HAS_LOCK)
@@ -337,33 +498,43 @@ static inline int led_feedback(struct smsdvb_client_t *client)
static int smsdvb_read_status(struct dvb_frontend *fe, fe_status_t *stat)
{
+ int rc;
struct smsdvb_client_t *client;
client = container_of(fe, struct smsdvb_client_t, frontend);
+ rc = smsdvb_send_statistics_request(client);
+
*stat = client->fe_status;
led_feedback(client);
- return 0;
+ return rc;
}
static int smsdvb_read_ber(struct dvb_frontend *fe, u32 *ber)
{
+ int rc;
struct smsdvb_client_t *client;
client = container_of(fe, struct smsdvb_client_t, frontend);
+ rc = smsdvb_send_statistics_request(client);
+
*ber = client->sms_stat_dvb.ReceptionData.BER;
led_feedback(client);
- return 0;
+ return rc;
}
static int smsdvb_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
{
+ int rc;
+
struct smsdvb_client_t *client;
client = container_of(fe, struct smsdvb_client_t, frontend);
+ rc = smsdvb_send_statistics_request(client);
+
if (client->sms_stat_dvb.ReceptionData.InBandPwr < -95)
*strength = 0;
else if (client->sms_stat_dvb.ReceptionData.InBandPwr > -29)
@@ -375,31 +546,37 @@ static int smsdvb_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
led_feedback(client);
- return 0;
+ return rc;
}
static int smsdvb_read_snr(struct dvb_frontend *fe, u16 *snr)
{
+ int rc;
struct smsdvb_client_t *client;
client = container_of(fe, struct smsdvb_client_t, frontend);
+ rc = smsdvb_send_statistics_request(client);
+
*snr = client->sms_stat_dvb.ReceptionData.SNR;
led_feedback(client);
- return 0;
+ return rc;
}
static int smsdvb_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
{
+ int rc;
struct smsdvb_client_t *client;
client = container_of(fe, struct smsdvb_client_t, frontend);
+ rc = smsdvb_send_statistics_request(client);
+
*ucblocks = client->sms_stat_dvb.ReceptionData.ErrorTSPackets;
led_feedback(client);
- return 0;
+ return rc;
}
static int smsdvb_get_tune_settings(struct dvb_frontend *fe,
@@ -413,9 +590,10 @@ static int smsdvb_get_tune_settings(struct dvb_frontend *fe,
return 0;
}
-static int smsdvb_set_frontend(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *fep)
+static int smsdvb_dvbt_set_frontend(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *p)
{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct smsdvb_client_t *client =
container_of(fe, struct smsdvb_client_t, frontend);
@@ -429,24 +607,33 @@ static int smsdvb_set_frontend(struct dvb_frontend *fe,
client->fe_status = FE_HAS_SIGNAL;
client->event_fe_state = -1;
client->event_unc_state = -1;
+ fe->dtv_property_cache.delivery_system = SYS_DVBT;
Msg.Msg.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
Msg.Msg.msgDstId = HIF_TASK;
Msg.Msg.msgFlags = 0;
Msg.Msg.msgType = MSG_SMS_RF_TUNE_REQ;
Msg.Msg.msgLength = sizeof(Msg);
- Msg.Data[0] = fep->frequency;
+ Msg.Data[0] = c->frequency;
Msg.Data[2] = 12000000;
- sms_debug("freq %d band %d",
- fep->frequency, fep->u.ofdm.bandwidth);
+ sms_info("%s: freq %d band %d", __func__, c->frequency,
+ c->bandwidth_hz);
- switch (fep->u.ofdm.bandwidth) {
- case BANDWIDTH_8_MHZ: Msg.Data[1] = BW_8_MHZ; break;
- case BANDWIDTH_7_MHZ: Msg.Data[1] = BW_7_MHZ; break;
- case BANDWIDTH_6_MHZ: Msg.Data[1] = BW_6_MHZ; break;
- case BANDWIDTH_AUTO: return -EOPNOTSUPP;
- default: return -EINVAL;
+ switch (c->bandwidth_hz / 1000000) {
+ case 8:
+ Msg.Data[1] = BW_8_MHZ;
+ break;
+ case 7:
+ Msg.Data[1] = BW_7_MHZ;
+ break;
+ case 6:
+ Msg.Data[1] = BW_6_MHZ;
+ break;
+ case 0:
+ return -EOPNOTSUPP;
+ default:
+ return -EINVAL;
}
/* Disable LNA, if any. An error is returned if no LNA is present */
ret = sms_board_lna_control(client->coredev, 0);
@@ -470,6 +657,90 @@ static int smsdvb_set_frontend(struct dvb_frontend *fe,
&client->tune_done);
}
+static int smsdvb_isdbt_set_frontend(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *p)
+{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+ struct smsdvb_client_t *client =
+ container_of(fe, struct smsdvb_client_t, frontend);
+
+ struct {
+ struct SmsMsgHdr_ST Msg;
+ u32 Data[4];
+ } Msg;
+
+ fe->dtv_property_cache.delivery_system = SYS_ISDBT;
+
+ Msg.Msg.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
+ Msg.Msg.msgDstId = HIF_TASK;
+ Msg.Msg.msgFlags = 0;
+ Msg.Msg.msgType = MSG_SMS_ISDBT_TUNE_REQ;
+ Msg.Msg.msgLength = sizeof(Msg);
+
+ if (c->isdbt_sb_segment_idx == -1)
+ c->isdbt_sb_segment_idx = 0;
+
+ switch (c->isdbt_sb_segment_count) {
+ case 3:
+ Msg.Data[1] = BW_ISDBT_3SEG;
+ break;
+ case 1:
+ Msg.Data[1] = BW_ISDBT_1SEG;
+ break;
+ case 0: /* AUTO */
+ switch (c->bandwidth_hz / 1000000) {
+ case 8:
+ case 7:
+ c->isdbt_sb_segment_count = 3;
+ Msg.Data[1] = BW_ISDBT_3SEG;
+ break;
+ case 6:
+ c->isdbt_sb_segment_count = 1;
+ Msg.Data[1] = BW_ISDBT_1SEG;
+ break;
+ default: /* Assumes 6 MHZ bw */
+ c->isdbt_sb_segment_count = 1;
+ c->bandwidth_hz = 6000;
+ Msg.Data[1] = BW_ISDBT_1SEG;
+ break;
+ }
+ break;
+ default:
+ sms_info("Segment count %d not supported", c->isdbt_sb_segment_count);
+ return -EINVAL;
+ }
+
+ Msg.Data[0] = c->frequency;
+ Msg.Data[2] = 12000000;
+ Msg.Data[3] = c->isdbt_sb_segment_idx;
+
+ sms_info("%s: freq %d segwidth %d segindex %d\n", __func__,
+ c->frequency, c->isdbt_sb_segment_count,
+ c->isdbt_sb_segment_idx);
+
+ return smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg),
+ &client->tune_done);
+}
+
+static int smsdvb_set_frontend(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *fep)
+{
+ struct smsdvb_client_t *client =
+ container_of(fe, struct smsdvb_client_t, frontend);
+ struct smscore_device_t *coredev = client->coredev;
+
+ switch (smscore_get_device_mode(coredev)) {
+ case DEVICE_MODE_DVBT:
+ case DEVICE_MODE_DVBT_BDA:
+ return smsdvb_dvbt_set_frontend(fe, fep);
+ case DEVICE_MODE_ISDBT:
+ case DEVICE_MODE_ISDBT_BDA:
+ return smsdvb_isdbt_set_frontend(fe, fep);
+ default:
+ return -EINVAL;
+ }
+}
+
static int smsdvb_get_frontend(struct dvb_frontend *fe,
struct dvb_frontend_parameters *fep)
{
@@ -557,13 +828,6 @@ static int smsdvb_hotplug(struct smscore_device_t *coredev,
/* device removal handled by onremove callback */
if (!arrival)
return 0;
-
- if (smscore_get_device_mode(coredev) != DEVICE_MODE_DVBT_BDA) {
- sms_err("SMS Device mode is not set for "
- "DVB operation.");
- return 0;
- }
-
client = kzalloc(sizeof(struct smsdvb_client_t), GFP_KERNEL);
if (!client) {
sms_err("kmalloc() failed");
diff --git a/drivers/media/dvb/siano/smsir.c b/drivers/media/dvb/siano/smsir.c
index e3d776feeaca..a56eac76e0f0 100644
--- a/drivers/media/dvb/siano/smsir.c
+++ b/drivers/media/dvb/siano/smsir.c
@@ -85,9 +85,9 @@ static struct keyboard_layout_map_t keyboard_layout_maps[] = {
{ } /* Terminating entry */
};
-u32 ir_pos;
-u32 ir_word;
-u32 ir_toggle;
+static u32 ir_pos;
+static u32 ir_word;
+static u32 ir_toggle;
#define RC5_PUSH_BIT(dst, bit, pos) \
{ dst <<= 1; dst |= bit; pos++; }
diff --git a/drivers/media/dvb/ttpci/av7110_ir.c b/drivers/media/dvb/ttpci/av7110_ir.c
index 23a1c6380d3f..b070e88d8c6b 100644
--- a/drivers/media/dvb/ttpci/av7110_ir.c
+++ b/drivers/media/dvb/ttpci/av7110_ir.c
@@ -268,8 +268,8 @@ int av7110_check_ir_config(struct av7110 *av7110, int force)
/* /proc/av7110_ir interface */
-static int av7110_ir_write_proc(struct file *file, const char __user *buffer,
- unsigned long count, void *data)
+static ssize_t av7110_ir_proc_write(struct file *file, const char __user *buffer,
+ size_t count, loff_t *pos)
{
char *page;
u32 ir_config;
@@ -309,6 +309,10 @@ static int av7110_ir_write_proc(struct file *file, const char __user *buffer,
return count;
}
+static const struct file_operations av7110_ir_proc_fops = {
+ .owner = THIS_MODULE,
+ .write = av7110_ir_proc_write,
+};
/* interrupt handler */
static void ir_handler(struct av7110 *av7110, u32 ircom)
@@ -368,11 +372,9 @@ int __devinit av7110_ir_init(struct av7110 *av7110)
input_dev->timer.data = (unsigned long) &av7110->ir;
if (av_cnt == 1) {
- e = create_proc_entry("av7110_ir", S_IFREG | S_IRUGO | S_IWUSR, NULL);
- if (e) {
- e->write_proc = av7110_ir_write_proc;
+ e = proc_create("av7110_ir", S_IWUSR, NULL, &av7110_ir_proc_fops);
+ if (e)
e->size = 4 + 256 * sizeof(u16);
- }
}
tasklet_init(&av7110->ir.ir_tasklet, av7110_emit_key, (unsigned long) &av7110->ir);
diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c
index 9782e0593733..49c2a817a06f 100644
--- a/drivers/media/dvb/ttpci/budget-ci.c
+++ b/drivers/media/dvb/ttpci/budget-ci.c
@@ -254,7 +254,7 @@ static int msp430_ir_init(struct budget_ci *budget_ci)
budget_ci->ir.timer_keyup.function = msp430_ir_keyup;
budget_ci->ir.timer_keyup.data = (unsigned long) &budget_ci->ir;
budget_ci->ir.last_raw = 0xffff; /* An impossible value */
- error = ir_input_register(input_dev, ir_codes);
+ error = ir_input_register(input_dev, ir_codes, NULL);
if (error) {
printk(KERN_ERR "budget_ci: could not init driver for IR device (code %d)\n", error);
return error;
diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c
index e48380c48990..9fdf26cc6998 100644
--- a/drivers/media/dvb/ttpci/budget.c
+++ b/drivers/media/dvb/ttpci/budget.c
@@ -433,9 +433,8 @@ static struct stv090x_config tt1600_stv090x_config = {
.demod_mode = STV090x_SINGLE,
.clk_mode = STV090x_CLK_EXT,
- .xtal = 27000000,
+ .xtal = 13500000,
.address = 0x68,
- .ref_clk = 27000000,
.ts1_mode = STV090x_TSMODE_DVBCI,
.ts2_mode = STV090x_TSMODE_SERIAL_CONTINUOUS,
@@ -457,6 +456,7 @@ static struct stv090x_config tt1600_stv090x_config = {
static struct stv6110x_config tt1600_stv6110x_config = {
.addr = 0x60,
.refclk = 27000000,
+ .clk_div = 2,
};
static struct isl6423_config tt1600_isl6423_config = {