Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/v4l-dvb
* 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/v4l-dvb: (310 commits) V4L/DVB (6316): Change list_for_each+list_entry to list_for_each_entry V4L/DVB (6315): pvrusb2: Change list_for_each+list_entry to list_for_each_entry V4L/DVB (6314): saa7134: Replace list_for_each+list_entry with list_for_each_entry V4L/DVB (6313): ivtv: Replace list_for_each+list_entry with list_for_each_entry V4L/DVB (6312): cx88: Replace list_for_each+list_entry with list_for_each_entry V4L/DVB (6311): dvb: Replace list_for_each+list_entry with list_for_each_entry V4L/DVB (6308): V4L: zc0301, remove bad usage of ERESTARTSYS V4L/DVB (6307): V4L: w9968cf, remove bad usage of ERESTARTSYS V4L/DVB (6306): Few clenups for saa7134 resume code V4L/DVB (6305): V4L: videobuf-core.c avoid NULL dereferences in videobuf-core V4L/DVB (6301): pvrusb: Update DEBUGIFC sysfs to kernel 2.6.13+ V4L/DVB (6300): CodingStyle cleanup V4L/DVB (6299): dvb: Add dependencies for VIDEOBUF_DVB V4L/DVB (6297): cx23885: remove wrong Kconfig selection of VIDEOBUF V4L/DVB (6296): dib0700: add support for AverMedia DVB-T Express card V4L/DVB (6295): saa7134: add autodetection for KWorld ATSC-115 V4L/DVB (6293): V4L: convert struct class_device to struct device V4L/DVB (6292): videobuf_core init always require callback implementation V4L/DVB (6291): Fix: avoid oops on some SMP machines V4L/DVB (6290): remove videobuf_set_pci_ops ...
This commit is contained in:
commit
c634920aba
|
@ -150,7 +150,7 @@ Some very frequently asked questions about linuxtv-dvb
|
|||
- saa7146_vv: SAA7146 video and vbi functions. These are only needed
|
||||
for full-featured cards.
|
||||
|
||||
- video-buf: capture helper module for the saa7146_vv driver. This
|
||||
- videobuf-dma-sg: capture helper module for the saa7146_vv driver. This
|
||||
one is responsible to handle capture buffers.
|
||||
|
||||
- dvb-ttpci: The main driver for AV7110 based, full-featured
|
||||
|
|
|
@ -147,3 +147,4 @@
|
|||
146 -> SSAI Ultrasound Video Interface [414a:5353]
|
||||
147 -> VoodooTV 200 (USA) [121a:3000]
|
||||
148 -> DViCO FusionHDTV 2 [dbc0:d200]
|
||||
149 -> Typhoon TV-Tuner PCI (50684)
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
0 -> UNKNOWN/GENERIC [0070:3400]
|
||||
1 -> Hauppauge WinTV-HVR1800lp [0070:7600]
|
||||
2 -> Hauppauge WinTV-HVR1800 [0070:7800,0070:7801]
|
||||
3 -> Hauppauge WinTV-HVR1250 [0070:7911]
|
||||
4 -> DViCO FusionHDTV5 Express [18ac:d500]
|
|
@ -88,11 +88,11 @@
|
|||
87 -> ADS Instant TV Duo Cardbus PTV331 [0331:1421]
|
||||
88 -> Tevion/KWorld DVB-T 220RF [17de:7201]
|
||||
89 -> ELSA EX-VISION 700TV [1048:226c]
|
||||
90 -> Kworld ATSC110 [17de:7350]
|
||||
90 -> Kworld ATSC110/115 [17de:7350,17de:7352]
|
||||
91 -> AVerMedia A169 B [1461:7360]
|
||||
92 -> AVerMedia A169 B1 [1461:6360]
|
||||
93 -> Medion 7134 Bridge #2 [16be:0005]
|
||||
94 -> LifeView FlyDVB-T Hybrid Cardbus [5168:3306,5168:3502]
|
||||
94 -> LifeView FlyDVB-T Hybrid Cardbus/MSI TV @nywhere A/D NB [5168:3306,5168:3502,4e42:3502]
|
||||
95 -> LifeView FlyVIDEO3000 (NTSC) [5169:0138]
|
||||
96 -> Medion Md8800 Quadro [16be:0007,16be:0008]
|
||||
97 -> LifeView FlyDVB-S /Acorp TV134DS [5168:0300,4e42:0300]
|
||||
|
@ -115,3 +115,4 @@
|
|||
114 -> KWorld DVB-T 210 [17de:7250]
|
||||
115 -> Sabrent PCMCIA TV-PCB05 [0919:2003]
|
||||
116 -> 10MOONS TM300 TV Card [1131:2304]
|
||||
117 -> Avermedia Super 007 [1461:f01d]
|
||||
|
|
|
@ -69,14 +69,80 @@ source "drivers/media/common/Kconfig"
|
|||
config VIDEO_TUNER
|
||||
tristate
|
||||
depends on I2C
|
||||
select TUNER_MT20XX if !VIDEO_TUNER_CUSTOMIZE
|
||||
select TUNER_TDA8290 if !VIDEO_TUNER_CUSTOMIZE
|
||||
select TUNER_TEA5761 if !VIDEO_TUNER_CUSTOMIZE
|
||||
select TUNER_TEA5767 if !VIDEO_TUNER_CUSTOMIZE
|
||||
select TUNER_SIMPLE if !VIDEO_TUNER_CUSTOMIZE
|
||||
|
||||
config VIDEO_BUF
|
||||
menuconfig VIDEO_TUNER_CUSTOMIZE
|
||||
bool "Customize analog tuner modules to build"
|
||||
depends on VIDEO_TUNER
|
||||
help
|
||||
This allows the user to deselect tuner drivers unnecessary
|
||||
for their hardware from the build. Use this option with care
|
||||
as deselecting tuner drivers which are in fact necessary will
|
||||
result in V4L devices which cannot be tuned due to lack of
|
||||
driver support
|
||||
|
||||
If unsure say N.
|
||||
|
||||
if VIDEO_TUNER_CUSTOMIZE
|
||||
|
||||
config TUNER_MT20XX
|
||||
tristate "Microtune 2032 / 2050 tuners"
|
||||
depends on I2C
|
||||
default m if VIDEO_TUNER_CUSTOMIZE
|
||||
help
|
||||
Say Y here to include support for the MT2032 / MT2050 tuner.
|
||||
|
||||
config TUNER_TDA8290
|
||||
tristate "TDA 8290+8275(a) tuner combo"
|
||||
depends on I2C
|
||||
default m if VIDEO_TUNER_CUSTOMIZE
|
||||
help
|
||||
Say Y here to include support for Philips TDA8290+8275(a) tuner.
|
||||
|
||||
config TUNER_TEA5761
|
||||
tristate "TEA 5761 radio tuner (EXPERIMENTAL)"
|
||||
depends on I2C && EXPERIMENTAL
|
||||
default m if VIDEO_TUNER_CUSTOMIZE
|
||||
help
|
||||
Say Y here to include support for the Philips TEA5761 radio tuner.
|
||||
|
||||
config TUNER_TEA5767
|
||||
tristate "TEA 5767 radio tuner"
|
||||
depends on I2C
|
||||
default m if VIDEO_TUNER_CUSTOMIZE
|
||||
help
|
||||
Say Y here to include support for the Philips TEA5767 radio tuner.
|
||||
|
||||
config TUNER_SIMPLE
|
||||
tristate "Simple tuner support"
|
||||
depends on I2C
|
||||
default m if VIDEO_TUNER_CUSTOMIZE
|
||||
help
|
||||
Say Y here to include support for various simple tuners.
|
||||
|
||||
endif # VIDEO_TUNER_CUSTOMIZE
|
||||
|
||||
config VIDEOBUF_GEN
|
||||
tristate
|
||||
|
||||
config VIDEOBUF_DMA_SG
|
||||
depends on PCI
|
||||
select VIDEOBUF_GEN
|
||||
tristate
|
||||
|
||||
config VIDEO_BUF_DVB
|
||||
config VIDEOBUF_VMALLOC
|
||||
select VIDEOBUF_GEN
|
||||
tristate
|
||||
|
||||
config VIDEOBUF_DVB
|
||||
tristate
|
||||
select VIDEOBUF_GEN
|
||||
select VIDEOBUF_DMA_SG
|
||||
|
||||
config VIDEO_BTCX
|
||||
tristate
|
||||
|
||||
|
|
|
@ -5,5 +5,5 @@ config VIDEO_SAA7146
|
|||
config VIDEO_SAA7146_VV
|
||||
tristate
|
||||
depends on VIDEO_DEV
|
||||
select VIDEO_BUF
|
||||
select VIDEOBUF_DMA_SG
|
||||
select VIDEO_SAA7146
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <media/ir-common.h>
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
|
||||
#include <linux/input.h>
|
||||
#include <media/ir-common.h>
|
||||
|
@ -1783,3 +1782,64 @@ IR_KEYTAB_TYPE ir_codes_tt_1500[IR_KEYTAB_SIZE] = {
|
|||
};
|
||||
|
||||
EXPORT_SYMBOL_GPL(ir_codes_tt_1500);
|
||||
|
||||
/* DViCO FUSION HDTV MCE remote */
|
||||
IR_KEYTAB_TYPE ir_codes_fusionhdtv_mce[IR_KEYTAB_SIZE] = {
|
||||
|
||||
[ 0x0b ] = KEY_1,
|
||||
[ 0x17 ] = KEY_2,
|
||||
[ 0x1b ] = KEY_3,
|
||||
[ 0x07 ] = KEY_4,
|
||||
[ 0x50 ] = KEY_5,
|
||||
[ 0x54 ] = KEY_6,
|
||||
[ 0x48 ] = KEY_7,
|
||||
[ 0x4c ] = KEY_8,
|
||||
[ 0x58 ] = KEY_9,
|
||||
[ 0x03 ] = KEY_0,
|
||||
|
||||
[ 0x5e ] = KEY_OK,
|
||||
[ 0x51 ] = KEY_UP,
|
||||
[ 0x53 ] = KEY_DOWN,
|
||||
[ 0x5b ] = KEY_LEFT,
|
||||
[ 0x5f ] = KEY_RIGHT,
|
||||
|
||||
[ 0x02 ] = KEY_TV, /* Labeled DTV on remote */
|
||||
[ 0x0e ] = KEY_MP3,
|
||||
[ 0x1a ] = KEY_DVD,
|
||||
[ 0x1e ] = KEY_FAVORITES, /* Labeled CPF on remote */
|
||||
[ 0x16 ] = KEY_SETUP,
|
||||
[ 0x46 ] = KEY_POWER2, /* TV On/Off button on remote */
|
||||
[ 0x0a ] = KEY_EPG, /* Labeled Guide on remote */
|
||||
|
||||
[ 0x49 ] = KEY_BACK,
|
||||
[ 0x59 ] = KEY_INFO, /* Labeled MORE on remote */
|
||||
[ 0x4d ] = KEY_MENU, /* Labeled DVDMENU on remote */
|
||||
[ 0x55 ] = KEY_CYCLEWINDOWS, /* Labeled ALT-TAB on remote */
|
||||
|
||||
[ 0x0f ] = KEY_PREVIOUSSONG, /* Labeled |<< REPLAY on remote */
|
||||
[ 0x12 ] = KEY_NEXTSONG, /* Labeled >>| SKIP on remote */
|
||||
[ 0x42 ] = KEY_ENTER, /* Labeled START with a green
|
||||
* MS windows logo on remote */
|
||||
|
||||
[ 0x15 ] = KEY_VOLUMEUP,
|
||||
[ 0x05 ] = KEY_VOLUMEDOWN,
|
||||
[ 0x11 ] = KEY_CHANNELUP,
|
||||
[ 0x09 ] = KEY_CHANNELDOWN,
|
||||
|
||||
[ 0x52 ] = KEY_CAMERA,
|
||||
[ 0x5a ] = KEY_TUNER,
|
||||
[ 0x19 ] = KEY_OPEN,
|
||||
|
||||
[ 0x13 ] = KEY_MODE, /* 4:3 16:9 select */
|
||||
[ 0x1f ] = KEY_ZOOM,
|
||||
|
||||
[ 0x43 ] = KEY_REWIND,
|
||||
[ 0x47 ] = KEY_PLAYPAUSE,
|
||||
[ 0x4f ] = KEY_FASTFORWARD,
|
||||
[ 0x57 ] = KEY_MUTE,
|
||||
[ 0x0d ] = KEY_STOP,
|
||||
[ 0x01 ] = KEY_RECORD,
|
||||
[ 0x4e ] = KEY_POWER,
|
||||
};
|
||||
|
||||
EXPORT_SYMBOL_GPL(ir_codes_fusionhdtv_mce);
|
||||
|
|
|
@ -100,7 +100,7 @@ int saa7146_wait_for_debi_done(struct saa7146_dev *dev, int nobusyloop)
|
|||
* general helper functions
|
||||
****************************************************************************/
|
||||
|
||||
/* this is videobuf_vmalloc_to_sg() from video-buf.c
|
||||
/* this is videobuf_vmalloc_to_sg() from videobuf-dma-sg.c
|
||||
make sure virt has been allocated with vmalloc_32(), otherwise the BUG()
|
||||
may be triggered on highmem machines */
|
||||
static struct scatterlist* vmalloc_to_sg(unsigned char *virt, int nr_pages)
|
||||
|
@ -248,10 +248,11 @@ int saa7146_pgtable_build_single(struct pci_dev *pci, struct saa7146_pgtable *pt
|
|||
static irqreturn_t interrupt_hw(int irq, void *dev_id)
|
||||
{
|
||||
struct saa7146_dev *dev = dev_id;
|
||||
u32 isr = 0;
|
||||
u32 isr;
|
||||
u32 ack_isr;
|
||||
|
||||
/* read out the interrupt status register */
|
||||
isr = saa7146_read(dev, ISR);
|
||||
ack_isr = isr = saa7146_read(dev, ISR);
|
||||
|
||||
/* is this our interrupt? */
|
||||
if ( 0 == isr ) {
|
||||
|
@ -259,8 +260,6 @@ static irqreturn_t interrupt_hw(int irq, void *dev_id)
|
|||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
saa7146_write(dev, ISR, isr);
|
||||
|
||||
if( 0 != (dev->ext)) {
|
||||
if( 0 != (dev->ext->irq_mask & isr )) {
|
||||
if( 0 != dev->ext->irq_func ) {
|
||||
|
@ -283,21 +282,16 @@ static irqreturn_t interrupt_hw(int irq, void *dev_id)
|
|||
isr &= ~MASK_28;
|
||||
}
|
||||
if (0 != (isr & (MASK_16|MASK_17))) {
|
||||
u32 status = saa7146_read(dev, I2C_STATUS);
|
||||
if( (0x3 == (status & 0x3)) || (0 == (status & 0x1)) ) {
|
||||
SAA7146_IER_DISABLE(dev, MASK_16|MASK_17);
|
||||
/* only wake up if we expect something */
|
||||
if( 0 != dev->i2c_op ) {
|
||||
u32 psr = (saa7146_read(dev, PSR) >> 16) & 0x2;
|
||||
u32 ssr = (saa7146_read(dev, SSR) >> 17) & 0x1f;
|
||||
DEB_I2C(("irq: i2c, status: 0x%08x, psr:0x%02x, ssr:0x%02x).\n",status,psr,ssr));
|
||||
dev->i2c_op = 0;
|
||||
wake_up(&dev->i2c_wq);
|
||||
} else {
|
||||
DEB_I2C(("unexpected irq: i2c, status: 0x%08x, isr %#x\n",status, isr));
|
||||
}
|
||||
SAA7146_IER_DISABLE(dev, MASK_16|MASK_17);
|
||||
/* only wake up if we expect something */
|
||||
if (0 != dev->i2c_op) {
|
||||
dev->i2c_op = 0;
|
||||
wake_up(&dev->i2c_wq);
|
||||
} else {
|
||||
DEB_I2C(("unhandled irq: i2c, status: 0x%08x, isr %#x\n",status, isr));
|
||||
u32 psr = saa7146_read(dev, PSR);
|
||||
u32 ssr = saa7146_read(dev, SSR);
|
||||
printk(KERN_WARNING "%s: unexpected i2c irq: isr %08x psr %08x ssr %08x\n",
|
||||
dev->name, isr, psr, ssr);
|
||||
}
|
||||
isr &= ~(MASK_16|MASK_17);
|
||||
}
|
||||
|
@ -306,6 +300,7 @@ static irqreturn_t interrupt_hw(int irq, void *dev_id)
|
|||
ERR(("disabling interrupt source(s)!\n"));
|
||||
SAA7146_IER_DISABLE(dev,isr);
|
||||
}
|
||||
saa7146_write(dev, ISR, ack_isr);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
|
@ -548,7 +543,6 @@ EXPORT_SYMBOL_GPL(saa7146_wait_for_debi_done);
|
|||
|
||||
EXPORT_SYMBOL_GPL(saa7146_setgpio);
|
||||
|
||||
EXPORT_SYMBOL_GPL(saa7146_i2c_transfer);
|
||||
EXPORT_SYMBOL_GPL(saa7146_i2c_adapter_prepare);
|
||||
|
||||
EXPORT_SYMBOL_GPL(saa7146_debug);
|
||||
|
|
|
@ -53,13 +53,14 @@ void saa7146_res_free(struct saa7146_fh *fh, unsigned int bits)
|
|||
void saa7146_dma_free(struct saa7146_dev *dev,struct videobuf_queue *q,
|
||||
struct saa7146_buf *buf)
|
||||
{
|
||||
struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
|
||||
DEB_EE(("dev:%p, buf:%p\n",dev,buf));
|
||||
|
||||
BUG_ON(in_interrupt());
|
||||
|
||||
videobuf_waiton(&buf->vb,0,0);
|
||||
videobuf_dma_unmap(q, &buf->vb.dma);
|
||||
videobuf_dma_free(&buf->vb.dma);
|
||||
videobuf_dma_unmap(q, dma);
|
||||
videobuf_dma_free(dma);
|
||||
buf->vb.state = STATE_NEEDS_INIT;
|
||||
}
|
||||
|
||||
|
|
|
@ -202,7 +202,8 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d
|
|||
/* a signal arrived */
|
||||
return -ERESTARTSYS;
|
||||
|
||||
printk(KERN_WARNING "saa7146_i2c_writeout: timed out waiting for end of xfer\n");
|
||||
printk(KERN_WARNING "%s %s [irq]: timed out waiting for end of xfer\n",
|
||||
dev->name, __FUNCTION__);
|
||||
return -EIO;
|
||||
}
|
||||
status = saa7146_read(dev, I2C_STATUS);
|
||||
|
@ -219,7 +220,8 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d
|
|||
break;
|
||||
}
|
||||
if (time_after(jiffies,timeout)) {
|
||||
printk(KERN_WARNING "saa7146_i2c_writeout: timed out waiting for MC2\n");
|
||||
printk(KERN_WARNING "%s %s: timed out waiting for MC2\n",
|
||||
dev->name, __FUNCTION__);
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
|
@ -235,7 +237,8 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d
|
|||
/* this is normal when probing the bus
|
||||
* (no answer from nonexisistant device...)
|
||||
*/
|
||||
DEB_I2C(("saa7146_i2c_writeout: timed out waiting for end of xfer\n"));
|
||||
printk(KERN_WARNING "%s %s [poll]: timed out waiting for end of xfer\n",
|
||||
dev->name, __FUNCTION__);
|
||||
return -EIO;
|
||||
}
|
||||
if (++trial < 50 && short_delay)
|
||||
|
@ -246,8 +249,16 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d
|
|||
}
|
||||
|
||||
/* give a detailed status report */
|
||||
if ( 0 != (status & SAA7146_I2C_ERR)) {
|
||||
if ( 0 != (status & (SAA7146_I2C_SPERR | SAA7146_I2C_APERR |
|
||||
SAA7146_I2C_DTERR | SAA7146_I2C_DRERR |
|
||||
SAA7146_I2C_AL | SAA7146_I2C_ERR |
|
||||
SAA7146_I2C_BUSY)) ) {
|
||||
|
||||
if ( 0 == (status & SAA7146_I2C_ERR) ||
|
||||
0 == (status & SAA7146_I2C_BUSY) ) {
|
||||
/* it may take some time until ERR goes high - ignore */
|
||||
DEB_I2C(("unexpected i2c status %04x\n", status));
|
||||
}
|
||||
if( 0 != (status & SAA7146_I2C_SPERR) ) {
|
||||
DEB_I2C(("error due to invalid start/stop condition.\n"));
|
||||
}
|
||||
|
@ -277,7 +288,7 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d
|
|||
return 0;
|
||||
}
|
||||
|
||||
int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg *msgs, int num, int retries)
|
||||
static int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg *msgs, int num, int retries)
|
||||
{
|
||||
int i = 0, count = 0;
|
||||
u32* buffer = dev->d_i2c.cpu_addr;
|
||||
|
|
|
@ -165,7 +165,7 @@ static void saa7146_set_vbi_capture(struct saa7146_dev *dev, struct saa7146_buf
|
|||
/* we don't wait here for the first field anymore. this is different from the video
|
||||
capture and might cause that the first buffer is only half filled (with only
|
||||
one field). but since this is some sort of streaming data, this is not that negative.
|
||||
but by doing this, we can use the whole engine from video-buf.c... */
|
||||
but by doing this, we can use the whole engine from videobuf-dma-sg.c... */
|
||||
|
||||
/*
|
||||
WRITE_RPS1(CMD_PAUSE | CMD_OAN | CMD_SIG1 | e_wait);
|
||||
|
@ -239,6 +239,8 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,e
|
|||
saa7146_dma_free(dev,q,buf);
|
||||
|
||||
if (STATE_NEEDS_INIT == buf->vb.state) {
|
||||
struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
|
||||
|
||||
buf->vb.width = llength;
|
||||
buf->vb.height = lines;
|
||||
buf->vb.size = size;
|
||||
|
@ -250,7 +252,8 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,e
|
|||
err = videobuf_iolock(q,&buf->vb, NULL);
|
||||
if (err)
|
||||
goto oops;
|
||||
err = saa7146_pgtable_build_single(dev->pci, &buf->pt[2], buf->vb.dma.sglist, buf->vb.dma.sglen);
|
||||
err = saa7146_pgtable_build_single(dev->pci, &buf->pt[2],
|
||||
dma->sglist, dma->sglen);
|
||||
if (0 != err)
|
||||
return err;
|
||||
}
|
||||
|
@ -404,7 +407,7 @@ static int vbi_open(struct saa7146_dev *dev, struct file *file)
|
|||
fh->vbi_fmt.start[1] = 312;
|
||||
fh->vbi_fmt.count[1] = 16;
|
||||
|
||||
videobuf_queue_init(&fh->vbi_q, &vbi_qops,
|
||||
videobuf_queue_pci_init(&fh->vbi_q, &vbi_qops,
|
||||
dev->pci, &dev->slock,
|
||||
V4L2_BUF_TYPE_VBI_CAPTURE,
|
||||
V4L2_FIELD_SEQ_TB, // FIXME: does this really work?
|
||||
|
|
|
@ -594,8 +594,9 @@ static int set_control(struct saa7146_fh *fh, struct v4l2_control *c)
|
|||
static int saa7146_pgtable_build(struct saa7146_dev *dev, struct saa7146_buf *buf)
|
||||
{
|
||||
struct pci_dev *pci = dev->pci;
|
||||
struct scatterlist *list = buf->vb.dma.sglist;
|
||||
int length = buf->vb.dma.sglen;
|
||||
struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
|
||||
struct scatterlist *list = dma->sglist;
|
||||
int length = dma->sglen;
|
||||
struct saa7146_format *sfmt = format_by_fourcc(dev,buf->fmt->pixelformat);
|
||||
|
||||
DEB_EE(("dev:%p, buf:%p, sg_len:%d\n",dev,buf,length));
|
||||
|
@ -655,7 +656,7 @@ static int saa7146_pgtable_build(struct saa7146_dev *dev, struct saa7146_buf *bu
|
|||
|
||||
/* if we have a user buffer, the first page may not be
|
||||
aligned to a page boundary. */
|
||||
pt1->offset = buf->vb.dma.sglist->offset;
|
||||
pt1->offset = list->offset;
|
||||
pt2->offset = pt1->offset+o1;
|
||||
pt3->offset = pt1->offset+o2;
|
||||
|
||||
|
@ -1211,6 +1212,8 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int
|
|||
mutex_unlock(&q->lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
gbuffers = err;
|
||||
memset(mbuf,0,sizeof(*mbuf));
|
||||
mbuf->frames = gbuffers;
|
||||
mbuf->size = gbuffers * gbufsize;
|
||||
|
@ -1411,7 +1414,7 @@ static int video_open(struct saa7146_dev *dev, struct file *file)
|
|||
sfmt = format_by_fourcc(dev,fh->video_fmt.pixelformat);
|
||||
fh->video_fmt.sizeimage = (fh->video_fmt.width * fh->video_fmt.height * sfmt->depth)/8;
|
||||
|
||||
videobuf_queue_init(&fh->video_q, &video_qops,
|
||||
videobuf_queue_pci_init(&fh->video_q, &video_qops,
|
||||
dev->pci, &dev->slock,
|
||||
V4L2_BUF_TYPE_VIDEO_CAPTURE,
|
||||
V4L2_FIELD_INTERLACED,
|
||||
|
|
|
@ -28,7 +28,6 @@
|
|||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/pci.h>
|
||||
#include <asm/io.h>
|
||||
|
|
|
@ -149,11 +149,10 @@ void bt878_start(struct bt878 *bt, u32 controlreg, u32 op_sync_orin,
|
|||
void bt878_stop(struct bt878 *bt);
|
||||
|
||||
#if defined(__powerpc__) /* big-endian */
|
||||
extern __inline__ void io_st_le32(volatile unsigned __iomem *addr, unsigned val)
|
||||
static inline void io_st_le32(volatile unsigned __iomem *addr, unsigned val)
|
||||
{
|
||||
__asm__ __volatile__("stwbrx %1,0,%2":"=m"(*addr):"r"(val),
|
||||
"r"(addr));
|
||||
__asm__ __volatile__("eieio":::"memory");
|
||||
st_le32(addr, val);
|
||||
eieio();
|
||||
}
|
||||
|
||||
#define bmtwrite(dat,adr) io_st_le32((adr),(dat))
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/device.h>
|
||||
|
|
|
@ -548,19 +548,19 @@ static unsigned int cinergyt2_poll (struct file *file, struct poll_table_struct
|
|||
{
|
||||
struct dvb_device *dvbdev = file->private_data;
|
||||
struct cinergyt2 *cinergyt2 = dvbdev->priv;
|
||||
unsigned int mask = 0;
|
||||
unsigned int mask = 0;
|
||||
|
||||
if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem))
|
||||
return -ERESTARTSYS;
|
||||
|
||||
poll_wait(file, &cinergyt2->poll_wq, wait);
|
||||
|
||||
if (cinergyt2->pending_fe_events != 0)
|
||||
if (cinergyt2->pending_fe_events != 0)
|
||||
mask |= (POLLIN | POLLRDNORM | POLLPRI);
|
||||
|
||||
mutex_unlock(&cinergyt2->sem);
|
||||
|
||||
return mask;
|
||||
return mask;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1008,6 +1008,8 @@ static int cinergyt2_suspend (struct usb_interface *intf, pm_message_t state)
|
|||
cinergyt2_sleep(cinergyt2, 1);
|
||||
mutex_unlock(&cinergyt2->sem);
|
||||
|
||||
mutex_unlock(&cinergyt2->wq_sem);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/poll.h>
|
||||
#include <linux/ioctl.h>
|
||||
#include <linux/wait.h>
|
||||
|
|
|
@ -32,11 +32,11 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/kthread.h>
|
||||
|
||||
#include "dvb_ca_en50221.h"
|
||||
#include "dvb_ringbuffer.h"
|
||||
|
@ -140,13 +140,7 @@ struct dvb_ca_private {
|
|||
wait_queue_head_t wait_queue;
|
||||
|
||||
/* PID of the monitoring thread */
|
||||
pid_t thread_pid;
|
||||
|
||||
/* Wait queue used when shutting thread down */
|
||||
wait_queue_head_t thread_queue;
|
||||
|
||||
/* Flag indicating when thread should exit */
|
||||
unsigned int exit:1;
|
||||
struct task_struct *thread;
|
||||
|
||||
/* Flag indicating if the CA device is open */
|
||||
unsigned int open:1;
|
||||
|
@ -902,27 +896,9 @@ static void dvb_ca_en50221_thread_wakeup(struct dvb_ca_private *ca)
|
|||
|
||||
ca->wakeup = 1;
|
||||
mb();
|
||||
wake_up_interruptible(&ca->thread_queue);
|
||||
wake_up_process(ca->thread);
|
||||
}
|
||||
|
||||
/**
|
||||
* Used by the CA thread to determine if an early wakeup is necessary
|
||||
*
|
||||
* @param ca CA instance.
|
||||
*/
|
||||
static int dvb_ca_en50221_thread_should_wakeup(struct dvb_ca_private *ca)
|
||||
{
|
||||
if (ca->wakeup) {
|
||||
ca->wakeup = 0;
|
||||
return 1;
|
||||
}
|
||||
if (ca->exit)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update the delay used by the thread.
|
||||
*
|
||||
|
@ -982,7 +958,6 @@ static void dvb_ca_en50221_thread_update_delay(struct dvb_ca_private *ca)
|
|||
static int dvb_ca_en50221_thread(void *data)
|
||||
{
|
||||
struct dvb_ca_private *ca = data;
|
||||
char name[15];
|
||||
int slot;
|
||||
int flags;
|
||||
int status;
|
||||
|
@ -991,28 +966,17 @@ static int dvb_ca_en50221_thread(void *data)
|
|||
|
||||
dprintk("%s\n", __FUNCTION__);
|
||||
|
||||
/* setup kernel thread */
|
||||
snprintf(name, sizeof(name), "kdvb-ca-%i:%i", ca->dvbdev->adapter->num, ca->dvbdev->id);
|
||||
|
||||
lock_kernel();
|
||||
daemonize(name);
|
||||
sigfillset(¤t->blocked);
|
||||
unlock_kernel();
|
||||
|
||||
/* choose the correct initial delay */
|
||||
dvb_ca_en50221_thread_update_delay(ca);
|
||||
|
||||
/* main loop */
|
||||
while (!ca->exit) {
|
||||
while (!kthread_should_stop()) {
|
||||
/* sleep for a bit */
|
||||
if (!ca->wakeup) {
|
||||
flags = wait_event_interruptible_timeout(ca->thread_queue,
|
||||
dvb_ca_en50221_thread_should_wakeup(ca),
|
||||
ca->delay);
|
||||
if ((flags == -ERESTARTSYS) || ca->exit) {
|
||||
/* got signal or quitting */
|
||||
break;
|
||||
}
|
||||
while (!ca->wakeup) {
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
schedule_timeout(ca->delay);
|
||||
if (kthread_should_stop())
|
||||
return 0;
|
||||
}
|
||||
ca->wakeup = 0;
|
||||
|
||||
|
@ -1181,10 +1145,6 @@ static int dvb_ca_en50221_thread(void *data)
|
|||
}
|
||||
}
|
||||
|
||||
/* completed */
|
||||
ca->thread_pid = 0;
|
||||
mb();
|
||||
wake_up_interruptible(&ca->thread_queue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1536,8 +1496,10 @@ static int dvb_ca_en50221_io_open(struct inode *inode, struct file *file)
|
|||
return -EIO;
|
||||
|
||||
err = dvb_generic_open(inode, file);
|
||||
if (err < 0)
|
||||
if (err < 0) {
|
||||
module_put(ca->pub->owner);
|
||||
return err;
|
||||
}
|
||||
|
||||
for (i = 0; i < ca->slot_count; i++) {
|
||||
|
||||
|
@ -1570,7 +1532,7 @@ static int dvb_ca_en50221_io_release(struct inode *inode, struct file *file)
|
|||
{
|
||||
struct dvb_device *dvbdev = file->private_data;
|
||||
struct dvb_ca_private *ca = dvbdev->priv;
|
||||
int err = 0;
|
||||
int err;
|
||||
|
||||
dprintk("%s\n", __FUNCTION__);
|
||||
|
||||
|
@ -1582,7 +1544,7 @@ static int dvb_ca_en50221_io_release(struct inode *inode, struct file *file)
|
|||
|
||||
module_put(ca->pub->owner);
|
||||
|
||||
return 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1682,9 +1644,6 @@ int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter,
|
|||
goto error;
|
||||
}
|
||||
init_waitqueue_head(&ca->wait_queue);
|
||||
ca->thread_pid = 0;
|
||||
init_waitqueue_head(&ca->thread_queue);
|
||||
ca->exit = 0;
|
||||
ca->open = 0;
|
||||
ca->wakeup = 0;
|
||||
ca->next_read_slot = 0;
|
||||
|
@ -1710,14 +1669,14 @@ int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter,
|
|||
mb();
|
||||
|
||||
/* create a kthread for monitoring this CA device */
|
||||
|
||||
ret = kernel_thread(dvb_ca_en50221_thread, ca, 0);
|
||||
|
||||
if (ret < 0) {
|
||||
printk("dvb_ca_init: failed to start kernel_thread (%d)\n", ret);
|
||||
ca->thread = kthread_run(dvb_ca_en50221_thread, ca, "kdvb-ca-%i:%i",
|
||||
ca->dvbdev->adapter->num, ca->dvbdev->id);
|
||||
if (IS_ERR(ca->thread)) {
|
||||
ret = PTR_ERR(ca->thread);
|
||||
printk("dvb_ca_init: failed to start kernel_thread (%d)\n",
|
||||
ret);
|
||||
goto error;
|
||||
}
|
||||
ca->thread_pid = ret;
|
||||
return 0;
|
||||
|
||||
error:
|
||||
|
@ -1748,17 +1707,7 @@ void dvb_ca_en50221_release(struct dvb_ca_en50221 *pubca)
|
|||
dprintk("%s\n", __FUNCTION__);
|
||||
|
||||
/* shutdown the thread if there was one */
|
||||
if (ca->thread_pid) {
|
||||
if (kill_proc(ca->thread_pid, 0, 1) == -ESRCH) {
|
||||
printk("dvb_ca_release adapter %d: thread PID %d already died\n",
|
||||
ca->dvbdev->adapter->num, ca->thread_pid);
|
||||
} else {
|
||||
ca->exit = 1;
|
||||
mb();
|
||||
dvb_ca_en50221_thread_wakeup(ca);
|
||||
wait_event_interruptible(ca->thread_queue, ca->thread_pid == 0);
|
||||
}
|
||||
}
|
||||
kthread_stop(ca->thread);
|
||||
|
||||
for (i = 0; i < ca->slot_count; i++) {
|
||||
dvb_ca_en50221_slot_shutdown(ca, i);
|
||||
|
|
|
@ -373,13 +373,10 @@ static inline void dvb_dmx_swfilter_packet_type(struct dvb_demux_feed *feed,
|
|||
static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf)
|
||||
{
|
||||
struct dvb_demux_feed *feed;
|
||||
struct list_head *pos, *head = &demux->feed_list;
|
||||
u16 pid = ts_pid(buf);
|
||||
int dvr_done = 0;
|
||||
|
||||
list_for_each(pos, head) {
|
||||
feed = list_entry(pos, struct dvb_demux_feed, list_head);
|
||||
|
||||
list_for_each_entry(feed, &demux->feed_list, list_head) {
|
||||
if ((feed->pid != pid) && (feed->pid != 0x2000))
|
||||
continue;
|
||||
|
||||
|
|
|
@ -32,7 +32,6 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/poll.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/freezer.h>
|
||||
#include <linux/jiffies.h>
|
||||
|
@ -43,7 +42,7 @@
|
|||
#include "dvbdev.h"
|
||||
|
||||
static int dvb_frontend_debug;
|
||||
static int dvb_shutdown_timeout = 5;
|
||||
static int dvb_shutdown_timeout;
|
||||
static int dvb_force_auto_inversion;
|
||||
static int dvb_override_tune_delay;
|
||||
static int dvb_powerdown_on_sleep = 1;
|
||||
|
@ -138,7 +137,7 @@ static void dvb_frontend_add_event(struct dvb_frontend *fe, fe_status_t status)
|
|||
|
||||
dprintk ("%s\n", __FUNCTION__);
|
||||
|
||||
if (down_interruptible (&events->sem))
|
||||
if (mutex_lock_interruptible (&events->mtx))
|
||||
return;
|
||||
|
||||
wp = (events->eventw + 1) % MAX_EVENT;
|
||||
|
@ -159,7 +158,7 @@ static void dvb_frontend_add_event(struct dvb_frontend *fe, fe_status_t status)
|
|||
|
||||
events->eventw = wp;
|
||||
|
||||
up (&events->sem);
|
||||
mutex_unlock(&events->mtx);
|
||||
|
||||
e->status = status;
|
||||
|
||||
|
@ -197,7 +196,7 @@ static int dvb_frontend_get_event(struct dvb_frontend *fe,
|
|||
return ret;
|
||||
}
|
||||
|
||||
if (down_interruptible (&events->sem))
|
||||
if (mutex_lock_interruptible (&events->mtx))
|
||||
return -ERESTARTSYS;
|
||||
|
||||
memcpy (event, &events->events[events->eventr],
|
||||
|
@ -205,7 +204,7 @@ static int dvb_frontend_get_event(struct dvb_frontend *fe,
|
|||
|
||||
events->eventr = (events->eventr + 1) % MAX_EVENT;
|
||||
|
||||
up (&events->sem);
|
||||
mutex_unlock(&events->mtx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -574,10 +573,9 @@ restart:
|
|||
dvb_frontend_swzigzag(fe);
|
||||
}
|
||||
|
||||
if (dvb_shutdown_timeout) {
|
||||
if (dvb_powerdown_on_sleep)
|
||||
if (fe->ops.set_voltage)
|
||||
fe->ops.set_voltage(fe, SEC_VOLTAGE_OFF);
|
||||
if (dvb_powerdown_on_sleep) {
|
||||
if (fe->ops.set_voltage)
|
||||
fe->ops.set_voltage(fe, SEC_VOLTAGE_OFF);
|
||||
if (fe->ops.tuner_ops.sleep) {
|
||||
fe->ops.tuner_ops.sleep(fe);
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
|
@ -697,6 +695,65 @@ static int dvb_frontend_start(struct dvb_frontend *fe)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void dvb_frontend_get_frequeny_limits(struct dvb_frontend *fe,
|
||||
u32 *freq_min, u32 *freq_max)
|
||||
{
|
||||
*freq_min = max(fe->ops.info.frequency_min, fe->ops.tuner_ops.info.frequency_min);
|
||||
|
||||
if (fe->ops.info.frequency_max == 0)
|
||||
*freq_max = fe->ops.tuner_ops.info.frequency_max;
|
||||
else if (fe->ops.tuner_ops.info.frequency_max == 0)
|
||||
*freq_max = fe->ops.info.frequency_max;
|
||||
else
|
||||
*freq_max = min(fe->ops.info.frequency_max, fe->ops.tuner_ops.info.frequency_max);
|
||||
|
||||
if (*freq_min == 0 || *freq_max == 0)
|
||||
printk(KERN_WARNING "DVB: frontend %u frequency limits undefined - fix the driver\n",
|
||||
fe->dvb->num);
|
||||
}
|
||||
|
||||
static int dvb_frontend_check_parameters(struct dvb_frontend *fe,
|
||||
struct dvb_frontend_parameters *parms)
|
||||
{
|
||||
u32 freq_min;
|
||||
u32 freq_max;
|
||||
|
||||
/* range check: frequency */
|
||||
dvb_frontend_get_frequeny_limits(fe, &freq_min, &freq_max);
|
||||
if ((freq_min && parms->frequency < freq_min) ||
|
||||
(freq_max && parms->frequency > freq_max)) {
|
||||
printk(KERN_WARNING "DVB: frontend %u frequency %u out of range (%u..%u)\n",
|
||||
fe->dvb->num, parms->frequency, freq_min, freq_max);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* range check: symbol rate */
|
||||
if (fe->ops.info.type == FE_QPSK) {
|
||||
if ((fe->ops.info.symbol_rate_min &&
|
||||
parms->u.qpsk.symbol_rate < fe->ops.info.symbol_rate_min) ||
|
||||
(fe->ops.info.symbol_rate_max &&
|
||||
parms->u.qpsk.symbol_rate > fe->ops.info.symbol_rate_max)) {
|
||||
printk(KERN_WARNING "DVB: frontend %u symbol rate %u out of range (%u..%u)\n",
|
||||
fe->dvb->num, parms->u.qpsk.symbol_rate,
|
||||
fe->ops.info.symbol_rate_min, fe->ops.info.symbol_rate_max);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
} else if (fe->ops.info.type == FE_QAM) {
|
||||
if ((fe->ops.info.symbol_rate_min &&
|
||||
parms->u.qam.symbol_rate < fe->ops.info.symbol_rate_min) ||
|
||||
(fe->ops.info.symbol_rate_max &&
|
||||
parms->u.qam.symbol_rate > fe->ops.info.symbol_rate_max)) {
|
||||
printk(KERN_WARNING "DVB: frontend %u symbol rate %u out of range (%u..%u)\n",
|
||||
fe->dvb->num, parms->u.qam.symbol_rate,
|
||||
fe->ops.info.symbol_rate_min, fe->ops.info.symbol_rate_max);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
|
||||
unsigned int cmd, void *parg)
|
||||
{
|
||||
|
@ -707,7 +764,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
|
|||
|
||||
dprintk ("%s\n", __FUNCTION__);
|
||||
|
||||
if (!fe || fepriv->exit)
|
||||
if (fepriv->exit)
|
||||
return -ENODEV;
|
||||
|
||||
if ((file->f_flags & O_ACCMODE) == O_RDONLY &&
|
||||
|
@ -722,6 +779,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
|
|||
case FE_GET_INFO: {
|
||||
struct dvb_frontend_info* info = parg;
|
||||
memcpy(info, &fe->ops.info, sizeof(struct dvb_frontend_info));
|
||||
dvb_frontend_get_frequeny_limits(fe, &info->frequency_min, &info->frequency_max);
|
||||
|
||||
/* Force the CAN_INVERSION_AUTO bit on. If the frontend doesn't
|
||||
* do it, it is done for it. */
|
||||
|
@ -883,6 +941,11 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
|
|||
case FE_SET_FRONTEND: {
|
||||
struct dvb_frontend_tune_settings fetunesettings;
|
||||
|
||||
if (dvb_frontend_check_parameters(fe, parg) < 0) {
|
||||
err = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
memcpy (&fepriv->parameters, parg,
|
||||
sizeof (struct dvb_frontend_parameters));
|
||||
|
||||
|
@ -992,18 +1055,15 @@ static int dvb_frontend_open(struct inode *inode, struct file *file)
|
|||
|
||||
dprintk ("%s\n", __FUNCTION__);
|
||||
|
||||
if ((ret = dvb_generic_open (inode, file)) < 0)
|
||||
return ret;
|
||||
|
||||
if (fe->ops.ts_bus_ctrl) {
|
||||
if ((ret = fe->ops.ts_bus_ctrl (fe, 1)) < 0) {
|
||||
dvb_generic_release (inode, file);
|
||||
if (dvbdev->users == -1 && fe->ops.ts_bus_ctrl) {
|
||||
if ((ret = fe->ops.ts_bus_ctrl(fe, 1)) < 0)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
|
||||
if ((ret = dvb_generic_open (inode, file)) < 0)
|
||||
goto err1;
|
||||
|
||||
if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
|
||||
/* normal tune mode when opened R/W */
|
||||
fepriv->tune_mode_flags &= ~FE_TUNE_MODE_ONESHOT;
|
||||
fepriv->tone = -1;
|
||||
|
@ -1011,13 +1071,20 @@ static int dvb_frontend_open(struct inode *inode, struct file *file)
|
|||
|
||||
ret = dvb_frontend_start (fe);
|
||||
if (ret)
|
||||
dvb_generic_release (inode, file);
|
||||
goto err2;
|
||||
|
||||
/* empty event queue */
|
||||
fepriv->events.eventr = fepriv->events.eventw = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
err2:
|
||||
dvb_generic_release(inode, file);
|
||||
err1:
|
||||
if (dvbdev->users == -1 && fe->ops.ts_bus_ctrl)
|
||||
fe->ops.ts_bus_ctrl(fe, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int dvb_frontend_release(struct inode *inode, struct file *file)
|
||||
|
@ -1032,16 +1099,18 @@ static int dvb_frontend_release(struct inode *inode, struct file *file)
|
|||
if ((file->f_flags & O_ACCMODE) != O_RDONLY)
|
||||
fepriv->release_jiffies = jiffies;
|
||||
|
||||
if (fe->ops.ts_bus_ctrl)
|
||||
fe->ops.ts_bus_ctrl (fe, 0);
|
||||
|
||||
ret = dvb_generic_release (inode, file);
|
||||
|
||||
if (dvbdev->users==-1 && fepriv->exit==1) {
|
||||
fops_put(file->f_op);
|
||||
file->f_op = NULL;
|
||||
wake_up(&dvbdev->wait_queue);
|
||||
if (dvbdev->users == -1) {
|
||||
if (fepriv->exit == 1) {
|
||||
fops_put(file->f_op);
|
||||
file->f_op = NULL;
|
||||
wake_up(&dvbdev->wait_queue);
|
||||
}
|
||||
if (fe->ops.ts_bus_ctrl)
|
||||
fe->ops.ts_bus_ctrl(fe, 0);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1080,7 +1149,7 @@ int dvb_register_frontend(struct dvb_adapter* dvb,
|
|||
init_MUTEX (&fepriv->sem);
|
||||
init_waitqueue_head (&fepriv->wait_queue);
|
||||
init_waitqueue_head (&fepriv->events.wait_queue);
|
||||
init_MUTEX (&fepriv->events.sem);
|
||||
mutex_init(&fepriv->events.mtx);
|
||||
fe->dvb = dvb;
|
||||
fepriv->inversion = INVERSION_OFF;
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/mutex.h>
|
||||
|
||||
#include <linux/dvb/frontend.h>
|
||||
|
||||
|
@ -61,6 +62,13 @@ struct dvb_tuner_info {
|
|||
u32 bandwidth_step;
|
||||
};
|
||||
|
||||
struct analog_parameters {
|
||||
unsigned int frequency;
|
||||
unsigned int mode;
|
||||
unsigned int audmode;
|
||||
u64 std;
|
||||
};
|
||||
|
||||
struct dvb_tuner_ops {
|
||||
|
||||
struct dvb_tuner_info info;
|
||||
|
@ -71,6 +79,7 @@ struct dvb_tuner_ops {
|
|||
|
||||
/** This is for simple PLLs - set all parameters in one go. */
|
||||
int (*set_params)(struct dvb_frontend *fe, struct dvb_frontend_parameters *p);
|
||||
int (*set_analog_params)(struct dvb_frontend *fe, struct analog_parameters *p);
|
||||
|
||||
/** This is support for demods like the mt352 - fills out the supplied buffer with what to write. */
|
||||
int (*calc_regs)(struct dvb_frontend *fe, struct dvb_frontend_parameters *p, u8 *buf, int buf_len);
|
||||
|
@ -79,7 +88,9 @@ struct dvb_tuner_ops {
|
|||
int (*get_bandwidth)(struct dvb_frontend *fe, u32 *bandwidth);
|
||||
|
||||
#define TUNER_STATUS_LOCKED 1
|
||||
#define TUNER_STATUS_STEREO 2
|
||||
int (*get_status)(struct dvb_frontend *fe, u32 *status);
|
||||
int (*get_rf_strength)(struct dvb_frontend *fe, u16 *strength);
|
||||
|
||||
/** These are provided seperately from set_params in order to facilitate silicon
|
||||
* tuners which require sophisticated tuning loops, controlling each parameter seperately. */
|
||||
|
@ -142,7 +153,7 @@ struct dvb_fe_events {
|
|||
int eventr;
|
||||
int overflow;
|
||||
wait_queue_head_t wait_queue;
|
||||
struct semaphore sem;
|
||||
struct mutex mtx;
|
||||
};
|
||||
|
||||
struct dvb_frontend {
|
||||
|
|
|
@ -357,11 +357,6 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
|
|||
static unsigned char *ule_where = ule_hist, ule_dump = 0;
|
||||
#endif
|
||||
|
||||
if (dev == NULL) {
|
||||
printk( KERN_ERR "NO netdev struct!\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
/* For all TS cells in current buffer.
|
||||
* Appearently, we are called for every single TS cell.
|
||||
*/
|
||||
|
@ -800,8 +795,8 @@ static int dvb_net_ts_callback(const u8 *buffer1, size_t buffer1_len,
|
|||
}
|
||||
|
||||
|
||||
static void dvb_net_sec(struct net_device *dev, const u8 *pkt, int
|
||||
pkt_len)
|
||||
static void dvb_net_sec(struct net_device *dev,
|
||||
const u8 *pkt, int pkt_len)
|
||||
{
|
||||
u8 *eth;
|
||||
struct sk_buff *skb;
|
||||
|
@ -1446,18 +1441,9 @@ static int dvb_net_close(struct inode *inode, struct file *file)
|
|||
struct dvb_device *dvbdev = file->private_data;
|
||||
struct dvb_net *dvbnet = dvbdev->priv;
|
||||
|
||||
if (!dvbdev)
|
||||
return -ENODEV;
|
||||
dvb_generic_release(inode, file);
|
||||
|
||||
if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
|
||||
dvbdev->readers++;
|
||||
} else {
|
||||
dvbdev->writers++;
|
||||
}
|
||||
|
||||
dvbdev->users++;
|
||||
|
||||
if(dvbdev->users == 1 && dvbnet->exit==1) {
|
||||
if(dvbdev->users == 1 && dvbnet->exit == 1) {
|
||||
fops_put(file->f_op);
|
||||
file->f_op = NULL;
|
||||
wake_up(&dvbdev->wait_queue);
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
#include <linux/errno.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
|
@ -59,18 +58,13 @@ static struct class *dvb_class;
|
|||
|
||||
static struct dvb_device* dvbdev_find_device (int minor)
|
||||
{
|
||||
struct list_head *entry;
|
||||
struct dvb_adapter *adap;
|
||||
|
||||
list_for_each (entry, &dvb_adapter_list) {
|
||||
struct list_head *entry0;
|
||||
struct dvb_adapter *adap;
|
||||
adap = list_entry (entry, struct dvb_adapter, list_head);
|
||||
list_for_each (entry0, &adap->device_list) {
|
||||
struct dvb_device *dev;
|
||||
dev = list_entry (entry0, struct dvb_device, list_head);
|
||||
list_for_each_entry(adap, &dvb_adapter_list, list_head) {
|
||||
struct dvb_device *dev;
|
||||
list_for_each_entry(dev, &adap->device_list, list_head)
|
||||
if (nums2minor(adap->num, dev->type, dev->id) == minor)
|
||||
return dev;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
@ -180,13 +174,10 @@ static int dvbdev_get_free_id (struct dvb_adapter *adap, int type)
|
|||
u32 id = 0;
|
||||
|
||||
while (id < DVB_MAX_IDS) {
|
||||
struct list_head *entry;
|
||||
list_for_each (entry, &adap->device_list) {
|
||||
struct dvb_device *dev;
|
||||
dev = list_entry (entry, struct dvb_device, list_head);
|
||||
struct dvb_device *dev;
|
||||
list_for_each_entry(dev, &adap->device_list, list_head)
|
||||
if (dev->type == type && dev->id == id)
|
||||
goto skip;
|
||||
}
|
||||
return id;
|
||||
skip:
|
||||
id++;
|
||||
|
@ -200,7 +191,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
|
|||
{
|
||||
struct dvb_device *dvbdev;
|
||||
struct file_operations *dvbdevfops;
|
||||
struct class_device *clsdev;
|
||||
struct device *clsdev;
|
||||
int id;
|
||||
|
||||
mutex_lock(&dvbdev_register_lock);
|
||||
|
@ -242,10 +233,9 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
|
|||
|
||||
mutex_unlock(&dvbdev_register_lock);
|
||||
|
||||
clsdev = class_device_create(dvb_class, NULL, MKDEV(DVB_MAJOR,
|
||||
nums2minor(adap->num, type, id)),
|
||||
adap->device, "dvb%d.%s%d", adap->num,
|
||||
dnames[type], id);
|
||||
clsdev = device_create(dvb_class, adap->device,
|
||||
MKDEV(DVB_MAJOR, nums2minor(adap->num, type, id)),
|
||||
"dvb%d.%s%d", adap->num, dnames[type], id);
|
||||
if (IS_ERR(clsdev)) {
|
||||
printk(KERN_ERR "%s: failed to create device dvb%d.%s%d (%ld)\n",
|
||||
__FUNCTION__, adap->num, dnames[type], id, PTR_ERR(clsdev));
|
||||
|
@ -266,8 +256,8 @@ void dvb_unregister_device(struct dvb_device *dvbdev)
|
|||
if (!dvbdev)
|
||||
return;
|
||||
|
||||
class_device_destroy(dvb_class, MKDEV(DVB_MAJOR, nums2minor(dvbdev->adapter->num,
|
||||
dvbdev->type, dvbdev->id)));
|
||||
device_destroy(dvb_class, MKDEV(DVB_MAJOR, nums2minor(dvbdev->adapter->num,
|
||||
dvbdev->type, dvbdev->id)));
|
||||
|
||||
list_del (&dvbdev->list_head);
|
||||
kfree (dvbdev->fops);
|
||||
|
@ -281,13 +271,10 @@ static int dvbdev_get_free_adapter_num (void)
|
|||
int num = 0;
|
||||
|
||||
while (num < DVB_MAX_ADAPTERS) {
|
||||
struct list_head *entry;
|
||||
list_for_each (entry, &dvb_adapter_list) {
|
||||
struct dvb_adapter *adap;
|
||||
adap = list_entry (entry, struct dvb_adapter, list_head);
|
||||
struct dvb_adapter *adap;
|
||||
list_for_each_entry(adap, &dvb_adapter_list, list_head)
|
||||
if (adap->num == num)
|
||||
goto skip;
|
||||
}
|
||||
return num;
|
||||
skip:
|
||||
num++;
|
||||
|
|
|
@ -74,6 +74,8 @@ config DVB_USB_DIB0700
|
|||
select DVB_DIB7000M
|
||||
select DVB_DIB3000MC
|
||||
select DVB_TUNER_MT2060 if !DVB_FE_CUSTOMISE
|
||||
select DVB_TUNER_MT2266 if !DVB_FE_CUSTOMISE
|
||||
select DVB_TUNER_DIB0070
|
||||
help
|
||||
Support for USB2.0/1.1 DVB receivers based on the DiB0700 USB bridge. The
|
||||
USB bridge is also present in devices having the DiB7700 DVB-T-USB
|
||||
|
|
|
@ -30,17 +30,19 @@ extern int dvb_usb_dib0700_debug;
|
|||
// 1 Byte: 4MSB(1 = enable streaming, 0 = disable streaming) 4LSB(Video Mode: 0 = MPEG2 188Bytes, 1 = Analog)
|
||||
// 2 Byte: MPEG2 mode: 4MSB(1 = Master Mode, 0 = Slave Mode) 4LSB(Channel 1 = bit0, Channel 2 = bit1)
|
||||
// 2 Byte: Analog mode: 4MSB(0 = 625 lines, 1 = 525 lines) 4LSB( " " )
|
||||
#define REQUEST_SET_RC 0x11
|
||||
#define REQUEST_GET_VERSION 0x15
|
||||
|
||||
struct dib0700_state {
|
||||
u8 channel_state;
|
||||
u16 mt2060_if1[2];
|
||||
|
||||
u8 rc_toggle;
|
||||
u8 is_dib7000pc;
|
||||
};
|
||||
|
||||
extern int dib0700_set_gpio(struct dvb_usb_device *, enum dib07x0_gpios gpio, u8 gpio_dir, u8 gpio_val);
|
||||
extern int dib0700_ctrl_clock(struct dvb_usb_device *d, u32 clk_MHz, u8 clock_out_gp3);
|
||||
extern int dib0700_ctrl_rd(struct dvb_usb_device *d, u8 *tx, u8 txlen, u8 *rx, u8 rxlen);
|
||||
extern int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw);
|
||||
extern int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff);
|
||||
extern struct i2c_algorithm dib0700_i2c_algo;
|
||||
|
@ -50,5 +52,4 @@ extern int dib0700_identify_state(struct usb_device *udev, struct dvb_usb_device
|
|||
extern int dib0700_device_count;
|
||||
extern struct dvb_usb_device_properties dib0700_devices[];
|
||||
extern struct usb_device_id dib0700_usb_id_table[];
|
||||
|
||||
#endif
|
||||
|
|
|
@ -13,6 +13,10 @@ int dvb_usb_dib0700_debug;
|
|||
module_param_named(debug,dvb_usb_dib0700_debug, int, 0644);
|
||||
MODULE_PARM_DESC(debug, "set debugging level (1=info,2=fw,4=fwdata,8=data (or-able))." DVB_USB_DEBUG_STATUS);
|
||||
|
||||
static int dvb_usb_dib0700_ir_proto = 1;
|
||||
module_param(dvb_usb_dib0700_ir_proto, int, 0644);
|
||||
MODULE_PARM_DESC(dvb_usb_dib0700_ir_proto, "set ir protocol (0=NEC, 1=RC5 (default), 2=RC6).");
|
||||
|
||||
/* expecting rx buffer: request data[0] data[1] ... data[2] */
|
||||
static int dib0700_ctrl_wr(struct dvb_usb_device *d, u8 *tx, u8 txlen)
|
||||
{
|
||||
|
@ -32,7 +36,7 @@ static int dib0700_ctrl_wr(struct dvb_usb_device *d, u8 *tx, u8 txlen)
|
|||
}
|
||||
|
||||
/* expecting tx buffer: request data[0] ... data[n] (n <= 4) */
|
||||
static int dib0700_ctrl_rd(struct dvb_usb_device *d, u8 *tx, u8 txlen, u8 *rx, u8 rxlen)
|
||||
int dib0700_ctrl_rd(struct dvb_usb_device *d, u8 *tx, u8 txlen, u8 *rx, u8 rxlen)
|
||||
{
|
||||
u16 index, value;
|
||||
int status;
|
||||
|
@ -260,14 +264,29 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
|
|||
return dib0700_ctrl_wr(adap->dev, b, 4);
|
||||
}
|
||||
|
||||
static int dib0700_rc_setup(struct dvb_usb_device *d)
|
||||
{
|
||||
u8 rc_setup[3] = {REQUEST_SET_RC, dvb_usb_dib0700_ir_proto, 0};
|
||||
int i = dib0700_ctrl_wr(d, rc_setup, 3);
|
||||
if (i<0) {
|
||||
err("ir protocol setup failed");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dib0700_probe(struct usb_interface *intf,
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
int i;
|
||||
struct dvb_usb_device *dev;
|
||||
|
||||
for (i = 0; i < dib0700_device_count; i++)
|
||||
if (dvb_usb_device_init(intf, &dib0700_devices[i], THIS_MODULE, NULL) == 0)
|
||||
if (dvb_usb_device_init(intf, &dib0700_devices[i], THIS_MODULE, &dev) == 0)
|
||||
{
|
||||
dib0700_rc_setup(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -ENODEV;
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation, version 2.
|
||||
*
|
||||
* Copyright (C) 2005-6 DiBcom, SA
|
||||
* Copyright (C) 2005-7 DiBcom, SA
|
||||
*/
|
||||
#include "dib0700.h"
|
||||
|
||||
|
@ -12,13 +12,19 @@
|
|||
#include "dib7000m.h"
|
||||
#include "dib7000p.h"
|
||||
#include "mt2060.h"
|
||||
#include "mt2266.h"
|
||||
#include "dib0070.h"
|
||||
|
||||
static int force_lna_activation;
|
||||
module_param(force_lna_activation, int, 0644);
|
||||
MODULE_PARM_DESC(force_lna_activation, "force the activation of Low-Noise-Amplifyer(s) (LNA), "
|
||||
"if applicable for the device (default: 0=automatic/off).");
|
||||
|
||||
/* Hauppauge Nova-T 500
|
||||
struct dib0700_adapter_state {
|
||||
int (*set_param_save) (struct dvb_frontend *, struct dvb_frontend_parameters *);
|
||||
};
|
||||
|
||||
/* Hauppauge Nova-T 500 (aka Bristol)
|
||||
* has a LNA on GPIO0 which is enabled by setting 1 */
|
||||
static struct mt2060_config bristol_mt2060_config[2] = {
|
||||
{
|
||||
|
@ -96,6 +102,321 @@ static int bristol_tuner_attach(struct dvb_usb_adapter *adap)
|
|||
st->mt2060_if1[adap->id]) == NULL ? -ENODEV : 0;
|
||||
}
|
||||
|
||||
/* STK7700D: Pinnacle/Terratec/Hauppauge Dual DVB-T Diversity */
|
||||
|
||||
/* MT226x */
|
||||
static struct dibx000_agc_config stk7700d_7000p_mt2266_agc_config[2] = {
|
||||
{
|
||||
BAND_UHF, // band_caps
|
||||
|
||||
/* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=1, P_agc_inv_pwm1=1, P_agc_inv_pwm2=1,
|
||||
* P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=2, P_agc_write=0 */
|
||||
(0 << 15) | (0 << 14) | (1 << 11) | (1 << 10) | (1 << 9) | (0 << 8) | (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0), // setup
|
||||
|
||||
1130, // inv_gain
|
||||
21, // time_stabiliz
|
||||
|
||||
0, // alpha_level
|
||||
118, // thlock
|
||||
|
||||
0, // wbd_inv
|
||||
3530, // wbd_ref
|
||||
1, // wbd_sel
|
||||
0, // wbd_alpha
|
||||
|
||||
65535, // agc1_max
|
||||
33770, // agc1_min
|
||||
65535, // agc2_max
|
||||
23592, // agc2_min
|
||||
|
||||
0, // agc1_pt1
|
||||
62, // agc1_pt2
|
||||
255, // agc1_pt3
|
||||
64, // agc1_slope1
|
||||
64, // agc1_slope2
|
||||
132, // agc2_pt1
|
||||
192, // agc2_pt2
|
||||
80, // agc2_slope1
|
||||
80, // agc2_slope2
|
||||
|
||||
17, // alpha_mant
|
||||
27, // alpha_exp
|
||||
23, // beta_mant
|
||||
51, // beta_exp
|
||||
|
||||
1, // perform_agc_softsplit
|
||||
}, {
|
||||
BAND_VHF | BAND_LBAND, // band_caps
|
||||
|
||||
/* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=1, P_agc_inv_pwm1=1, P_agc_inv_pwm2=1,
|
||||
* P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=2, P_agc_write=0 */
|
||||
(0 << 15) | (0 << 14) | (1 << 11) | (1 << 10) | (1 << 9) | (0 << 8) | (3 << 5) | (0 << 4) | (2 << 1) | (0 << 0), // setup
|
||||
|
||||
2372, // inv_gain
|
||||
21, // time_stabiliz
|
||||
|
||||
0, // alpha_level
|
||||
118, // thlock
|
||||
|
||||
0, // wbd_inv
|
||||
3530, // wbd_ref
|
||||
1, // wbd_sel
|
||||
0, // wbd_alpha
|
||||
|
||||
65535, // agc1_max
|
||||
0, // agc1_min
|
||||
65535, // agc2_max
|
||||
23592, // agc2_min
|
||||
|
||||
0, // agc1_pt1
|
||||
128, // agc1_pt2
|
||||
128, // agc1_pt3
|
||||
128, // agc1_slope1
|
||||
0, // agc1_slope2
|
||||
128, // agc2_pt1
|
||||
253, // agc2_pt2
|
||||
81, // agc2_slope1
|
||||
0, // agc2_slope2
|
||||
|
||||
17, // alpha_mant
|
||||
27, // alpha_exp
|
||||
23, // beta_mant
|
||||
51, // beta_exp
|
||||
|
||||
1, // perform_agc_softsplit
|
||||
}
|
||||
};
|
||||
|
||||
static struct dibx000_bandwidth_config stk7700d_mt2266_pll_config = {
|
||||
60000, 30000, // internal, sampling
|
||||
1, 8, 3, 1, 0, // pll_cfg: prediv, ratio, range, reset, bypass
|
||||
0, 0, 1, 1, 2, // misc: refdiv, bypclk_div, IO_CLK_en_core, ADClkSrc, modulo
|
||||
(3 << 14) | (1 << 12) | (524 << 0), // sad_cfg: refsel, sel, freq_15k
|
||||
0, // ifreq
|
||||
20452225, // timf
|
||||
};
|
||||
|
||||
static struct dib7000p_config stk7700d_dib7000p_mt2266_config[] = {
|
||||
{ .output_mpeg2_in_188_bytes = 1,
|
||||
.hostbus_diversity = 1,
|
||||
.tuner_is_baseband = 1,
|
||||
|
||||
.agc_config_count = 2,
|
||||
.agc = stk7700d_7000p_mt2266_agc_config,
|
||||
.bw = &stk7700d_mt2266_pll_config,
|
||||
|
||||
.gpio_dir = DIB7000P_GPIO_DEFAULT_DIRECTIONS,
|
||||
.gpio_val = DIB7000P_GPIO_DEFAULT_VALUES,
|
||||
.gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS,
|
||||
},
|
||||
{ .output_mpeg2_in_188_bytes = 1,
|
||||
.hostbus_diversity = 1,
|
||||
.tuner_is_baseband = 1,
|
||||
|
||||
.agc_config_count = 2,
|
||||
.agc = stk7700d_7000p_mt2266_agc_config,
|
||||
.bw = &stk7700d_mt2266_pll_config,
|
||||
|
||||
.gpio_dir = DIB7000P_GPIO_DEFAULT_DIRECTIONS,
|
||||
.gpio_val = DIB7000P_GPIO_DEFAULT_VALUES,
|
||||
.gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS,
|
||||
}
|
||||
};
|
||||
|
||||
static struct mt2266_config stk7700d_mt2266_config[2] = {
|
||||
{ .i2c_address = 0x60
|
||||
},
|
||||
{ .i2c_address = 0x60
|
||||
}
|
||||
};
|
||||
|
||||
static int stk7700d_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
if (adap->id == 0) {
|
||||
dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
|
||||
msleep(10);
|
||||
dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1);
|
||||
dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1);
|
||||
dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1);
|
||||
dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0);
|
||||
msleep(10);
|
||||
dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
|
||||
msleep(10);
|
||||
dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
|
||||
dib7000p_i2c_enumeration(&adap->dev->i2c_adap,2,18,stk7700d_dib7000p_mt2266_config);
|
||||
}
|
||||
|
||||
adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap,0x80+(adap->id << 1),
|
||||
&stk7700d_dib7000p_mt2266_config[adap->id]);
|
||||
|
||||
return adap->fe == NULL ? -ENODEV : 0;
|
||||
}
|
||||
|
||||
static int stk7700d_tuner_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
struct i2c_adapter *tun_i2c;
|
||||
tun_i2c = dib7000p_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1);
|
||||
return dvb_attach(mt2266_attach, adap->fe, tun_i2c,
|
||||
&stk7700d_mt2266_config[adap->id]) == NULL ? -ENODEV : 0;;
|
||||
}
|
||||
|
||||
#define DEFAULT_RC_INTERVAL 150
|
||||
|
||||
static u8 rc_request[] = { REQUEST_POLL_RC, 0 };
|
||||
|
||||
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;
|
||||
i=dib0700_ctrl_rd(d,rc_request,2,key,4);
|
||||
if (i<=0) {
|
||||
err("RC Query Failed");
|
||||
return -1;
|
||||
}
|
||||
if (key[0]==0 && key[1]==0 && key[2]==0 && key[3]==0) return 0;
|
||||
if (key[3-1]!=st->rc_toggle) {
|
||||
for (i=0;i<d->props.rc_key_map_size; i++) {
|
||||
if (keymap[i].custom == key[3-2] && keymap[i].data == key[3-3]) {
|
||||
*event = keymap[i].event;
|
||||
*state = REMOTE_KEY_PRESSED;
|
||||
st->rc_toggle=key[3-1];
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
err("Unknown remote controller key : %2X %2X",(int)key[3-2],(int)key[3-3]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dvb_usb_rc_key dib0700_rc_keys[] = {
|
||||
/* Key codes for the tiny Pinnacle remote*/
|
||||
{ 0x07, 0x00, KEY_MUTE },
|
||||
{ 0x07, 0x01, KEY_MENU }, // Pinnacle logo
|
||||
{ 0x07, 0x39, KEY_POWER },
|
||||
{ 0x07, 0x03, KEY_VOLUMEUP },
|
||||
{ 0x07, 0x09, KEY_VOLUMEDOWN },
|
||||
{ 0x07, 0x06, KEY_CHANNELUP },
|
||||
{ 0x07, 0x0c, KEY_CHANNELDOWN },
|
||||
{ 0x07, 0x0f, KEY_1 },
|
||||
{ 0x07, 0x15, KEY_2 },
|
||||
{ 0x07, 0x10, KEY_3 },
|
||||
{ 0x07, 0x18, KEY_4 },
|
||||
{ 0x07, 0x1b, KEY_5 },
|
||||
{ 0x07, 0x1e, KEY_6 },
|
||||
{ 0x07, 0x11, KEY_7 },
|
||||
{ 0x07, 0x21, KEY_8 },
|
||||
{ 0x07, 0x12, KEY_9 },
|
||||
{ 0x07, 0x27, KEY_0 },
|
||||
{ 0x07, 0x24, KEY_SCREEN }, // 'Square' key
|
||||
{ 0x07, 0x2a, KEY_TEXT }, // 'T' key
|
||||
{ 0x07, 0x2d, KEY_REWIND },
|
||||
{ 0x07, 0x30, KEY_PLAY },
|
||||
{ 0x07, 0x33, KEY_FASTFORWARD },
|
||||
{ 0x07, 0x36, KEY_RECORD },
|
||||
{ 0x07, 0x3c, KEY_STOP },
|
||||
{ 0x07, 0x3f, KEY_CANCEL }, // '?' key
|
||||
/* Key codes for the Terratec Cinergy DT XS Diversity, similar to cinergyT2.c */
|
||||
{ 0xeb, 0x01, KEY_POWER },
|
||||
{ 0xeb, 0x02, KEY_1 },
|
||||
{ 0xeb, 0x03, KEY_2 },
|
||||
{ 0xeb, 0x04, KEY_3 },
|
||||
{ 0xeb, 0x05, KEY_4 },
|
||||
{ 0xeb, 0x06, KEY_5 },
|
||||
{ 0xeb, 0x07, KEY_6 },
|
||||
{ 0xeb, 0x08, KEY_7 },
|
||||
{ 0xeb, 0x09, KEY_8 },
|
||||
{ 0xeb, 0x0a, KEY_9 },
|
||||
{ 0xeb, 0x0b, KEY_VIDEO },
|
||||
{ 0xeb, 0x0c, KEY_0 },
|
||||
{ 0xeb, 0x0d, KEY_REFRESH },
|
||||
{ 0xeb, 0x0f, KEY_EPG },
|
||||
{ 0xeb, 0x10, KEY_UP },
|
||||
{ 0xeb, 0x11, KEY_LEFT },
|
||||
{ 0xeb, 0x12, KEY_OK },
|
||||
{ 0xeb, 0x13, KEY_RIGHT },
|
||||
{ 0xeb, 0x14, KEY_DOWN },
|
||||
{ 0xeb, 0x16, KEY_INFO },
|
||||
{ 0xeb, 0x17, KEY_RED },
|
||||
{ 0xeb, 0x18, KEY_GREEN },
|
||||
{ 0xeb, 0x19, KEY_YELLOW },
|
||||
{ 0xeb, 0x1a, KEY_BLUE },
|
||||
{ 0xeb, 0x1b, KEY_CHANNELUP },
|
||||
{ 0xeb, 0x1c, KEY_VOLUMEUP },
|
||||
{ 0xeb, 0x1d, KEY_MUTE },
|
||||
{ 0xeb, 0x1e, KEY_VOLUMEDOWN },
|
||||
{ 0xeb, 0x1f, KEY_CHANNELDOWN },
|
||||
{ 0xeb, 0x40, KEY_PAUSE },
|
||||
{ 0xeb, 0x41, KEY_HOME },
|
||||
{ 0xeb, 0x42, KEY_MENU }, /* DVD Menu */
|
||||
{ 0xeb, 0x43, KEY_SUBTITLE },
|
||||
{ 0xeb, 0x44, KEY_TEXT }, /* Teletext */
|
||||
{ 0xeb, 0x45, KEY_DELETE },
|
||||
{ 0xeb, 0x46, KEY_TV },
|
||||
{ 0xeb, 0x47, KEY_DVD },
|
||||
{ 0xeb, 0x48, KEY_STOP },
|
||||
{ 0xeb, 0x49, KEY_VIDEO },
|
||||
{ 0xeb, 0x4a, KEY_AUDIO }, /* Music */
|
||||
{ 0xeb, 0x4b, KEY_SCREEN }, /* Pic */
|
||||
{ 0xeb, 0x4c, KEY_PLAY },
|
||||
{ 0xeb, 0x4d, KEY_BACK },
|
||||
{ 0xeb, 0x4e, KEY_REWIND },
|
||||
{ 0xeb, 0x4f, KEY_FASTFORWARD },
|
||||
{ 0xeb, 0x54, KEY_PREVIOUS },
|
||||
{ 0xeb, 0x58, KEY_RECORD },
|
||||
{ 0xeb, 0x5c, KEY_NEXT },
|
||||
|
||||
/* Key codes for the Haupauge WinTV Nova-TD, copied from nova-t-usb2.c (Nova-T USB2) */
|
||||
{ 0x1e, 0x00, KEY_0 },
|
||||
{ 0x1e, 0x01, KEY_1 },
|
||||
{ 0x1e, 0x02, KEY_2 },
|
||||
{ 0x1e, 0x03, KEY_3 },
|
||||
{ 0x1e, 0x04, KEY_4 },
|
||||
{ 0x1e, 0x05, KEY_5 },
|
||||
{ 0x1e, 0x06, KEY_6 },
|
||||
{ 0x1e, 0x07, KEY_7 },
|
||||
{ 0x1e, 0x08, KEY_8 },
|
||||
{ 0x1e, 0x09, KEY_9 },
|
||||
{ 0x1e, 0x0a, KEY_KPASTERISK },
|
||||
{ 0x1e, 0x0b, KEY_RED },
|
||||
{ 0x1e, 0x0c, KEY_RADIO },
|
||||
{ 0x1e, 0x0d, KEY_MENU },
|
||||
{ 0x1e, 0x0e, KEY_GRAVE }, /* # */
|
||||
{ 0x1e, 0x0f, KEY_MUTE },
|
||||
{ 0x1e, 0x10, KEY_VOLUMEUP },
|
||||
{ 0x1e, 0x11, KEY_VOLUMEDOWN },
|
||||
{ 0x1e, 0x12, KEY_CHANNEL },
|
||||
{ 0x1e, 0x14, KEY_UP },
|
||||
{ 0x1e, 0x15, KEY_DOWN },
|
||||
{ 0x1e, 0x16, KEY_LEFT },
|
||||
{ 0x1e, 0x17, KEY_RIGHT },
|
||||
{ 0x1e, 0x18, KEY_VIDEO },
|
||||
{ 0x1e, 0x19, KEY_AUDIO },
|
||||
{ 0x1e, 0x1a, KEY_MEDIA },
|
||||
{ 0x1e, 0x1b, KEY_EPG },
|
||||
{ 0x1e, 0x1c, KEY_TV },
|
||||
{ 0x1e, 0x1e, KEY_NEXT },
|
||||
{ 0x1e, 0x1f, KEY_BACK },
|
||||
{ 0x1e, 0x20, KEY_CHANNELUP },
|
||||
{ 0x1e, 0x21, KEY_CHANNELDOWN },
|
||||
{ 0x1e, 0x24, KEY_LAST }, /* Skip backwards */
|
||||
{ 0x1e, 0x25, KEY_OK },
|
||||
{ 0x1e, 0x29, KEY_BLUE},
|
||||
{ 0x1e, 0x2e, KEY_GREEN },
|
||||
{ 0x1e, 0x30, KEY_PAUSE },
|
||||
{ 0x1e, 0x32, KEY_REWIND },
|
||||
{ 0x1e, 0x34, KEY_FASTFORWARD },
|
||||
{ 0x1e, 0x35, KEY_PLAY },
|
||||
{ 0x1e, 0x36, KEY_STOP },
|
||||
{ 0x1e, 0x37, KEY_RECORD },
|
||||
{ 0x1e, 0x38, KEY_YELLOW },
|
||||
{ 0x1e, 0x3b, KEY_GOTO },
|
||||
{ 0x1e, 0x3d, KEY_POWER },
|
||||
};
|
||||
|
||||
/* STK7700P: Hauppauge Nova-T Stick, AVerMedia Volar */
|
||||
static struct dibx000_agc_config stk7700p_7000m_mt2060_agc_config = {
|
||||
BAND_UHF | BAND_VHF, // band_caps
|
||||
|
@ -194,6 +515,7 @@ static struct dibx000_bandwidth_config stk7700p_pll_config = {
|
|||
(3 << 14) | (1 << 12) | (524 << 0), // sad_cfg: refsel, sel, freq_15k
|
||||
60258167, // ifreq
|
||||
20452225, // timf
|
||||
30000000, // xtal
|
||||
};
|
||||
|
||||
static struct dib7000m_config stk7700p_dib7000m_config = {
|
||||
|
@ -213,6 +535,7 @@ static struct dib7000m_config stk7700p_dib7000m_config = {
|
|||
static struct dib7000p_config stk7700p_dib7000p_config = {
|
||||
.output_mpeg2_in_188_bytes = 1,
|
||||
|
||||
.agc_config_count = 1,
|
||||
.agc = &stk7700p_7000p_mt2060_agc_config,
|
||||
.bw = &stk7700p_pll_config,
|
||||
|
||||
|
@ -267,27 +590,245 @@ static int stk7700p_tuner_attach(struct dvb_usb_adapter *adap)
|
|||
st->mt2060_if1[0]) == NULL ? -ENODEV : 0;
|
||||
}
|
||||
|
||||
/* DIB7070 generic */
|
||||
static struct dibx000_agc_config dib7070_agc_config = {
|
||||
BAND_UHF | BAND_VHF | BAND_LBAND | BAND_SBAND,
|
||||
/* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=5, P_agc_inv_pwm1=0, P_agc_inv_pwm2=0,
|
||||
* P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5, P_agc_write=0 */
|
||||
(0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) | (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0), // setup
|
||||
|
||||
600, // inv_gain
|
||||
10, // time_stabiliz
|
||||
|
||||
0, // alpha_level
|
||||
118, // thlock
|
||||
|
||||
0, // wbd_inv
|
||||
3530, // wbd_ref
|
||||
1, // wbd_sel
|
||||
5, // wbd_alpha
|
||||
|
||||
65535, // agc1_max
|
||||
0, // agc1_min
|
||||
|
||||
65535, // agc2_max
|
||||
0, // agc2_min
|
||||
|
||||
0, // agc1_pt1
|
||||
40, // agc1_pt2
|
||||
183, // agc1_pt3
|
||||
206, // agc1_slope1
|
||||
255, // agc1_slope2
|
||||
72, // agc2_pt1
|
||||
152, // agc2_pt2
|
||||
88, // agc2_slope1
|
||||
90, // agc2_slope2
|
||||
|
||||
17, // alpha_mant
|
||||
27, // alpha_exp
|
||||
23, // beta_mant
|
||||
51, // beta_exp
|
||||
|
||||
0, // perform_agc_softsplit
|
||||
};
|
||||
|
||||
static int dib7070_tuner_reset(struct dvb_frontend *fe, int onoff)
|
||||
{
|
||||
return dib7000p_set_gpio(fe, 8, 0, !onoff);
|
||||
}
|
||||
|
||||
static int dib7070_tuner_sleep(struct dvb_frontend *fe, int onoff)
|
||||
{
|
||||
return dib7000p_set_gpio(fe, 9, 0, onoff);
|
||||
}
|
||||
|
||||
static struct dib0070_config dib7070p_dib0070_config[2] = {
|
||||
{
|
||||
.i2c_address = DEFAULT_DIB0070_I2C_ADDRESS,
|
||||
.reset = dib7070_tuner_reset,
|
||||
.sleep = dib7070_tuner_sleep,
|
||||
.clock_khz = 12000,
|
||||
.clock_pad_drive = 4
|
||||
}, {
|
||||
.i2c_address = DEFAULT_DIB0070_I2C_ADDRESS,
|
||||
.reset = dib7070_tuner_reset,
|
||||
.sleep = dib7070_tuner_sleep,
|
||||
.clock_khz = 12000,
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
static int dib7070_set_param_override(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep)
|
||||
{
|
||||
struct dvb_usb_adapter *adap = fe->dvb->priv;
|
||||
struct dib0700_adapter_state *state = adap->priv;
|
||||
|
||||
u16 offset;
|
||||
u8 band = BAND_OF_FREQUENCY(fep->frequency/1000);
|
||||
switch (band) {
|
||||
case BAND_VHF: offset = 950; break;
|
||||
case BAND_UHF:
|
||||
default: offset = 550; break;
|
||||
}
|
||||
deb_info("WBD for DiB7000P: %d\n", offset + dib0070_wbd_offset(fe));
|
||||
dib7000p_set_wbd_ref(fe, offset + dib0070_wbd_offset(fe));
|
||||
return state->set_param_save(fe, fep);
|
||||
}
|
||||
|
||||
static int dib7070p_tuner_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
struct dib0700_adapter_state *st = adap->priv;
|
||||
struct i2c_adapter *tun_i2c = dib7000p_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1);
|
||||
|
||||
if (adap->id == 0) {
|
||||
if (dvb_attach(dib0070_attach, adap->fe, tun_i2c, &dib7070p_dib0070_config[0]) == NULL)
|
||||
return -ENODEV;
|
||||
} else {
|
||||
if (dvb_attach(dib0070_attach, adap->fe, tun_i2c, &dib7070p_dib0070_config[1]) == NULL)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
st->set_param_save = adap->fe->ops.tuner_ops.set_params;
|
||||
adap->fe->ops.tuner_ops.set_params = dib7070_set_param_override;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dibx000_bandwidth_config dib7070_bw_config_12_mhz = {
|
||||
60000, 15000, // internal, sampling
|
||||
1, 20, 3, 1, 0, // pll_cfg: prediv, ratio, range, reset, bypass
|
||||
0, 0, 1, 1, 2, // misc: refdiv, bypclk_div, IO_CLK_en_core, ADClkSrc, modulo
|
||||
(3 << 14) | (1 << 12) | (524 << 0), // sad_cfg: refsel, sel, freq_15k
|
||||
(0 << 25) | 0, // ifreq = 0.000000 MHz
|
||||
20452225, // timf
|
||||
12000000, // xtal_hz
|
||||
};
|
||||
|
||||
static struct dib7000p_config dib7070p_dib7000p_config = {
|
||||
.output_mpeg2_in_188_bytes = 1,
|
||||
|
||||
.agc_config_count = 1,
|
||||
.agc = &dib7070_agc_config,
|
||||
.bw = &dib7070_bw_config_12_mhz,
|
||||
|
||||
.gpio_dir = DIB7000P_GPIO_DEFAULT_DIRECTIONS,
|
||||
.gpio_val = DIB7000P_GPIO_DEFAULT_VALUES,
|
||||
.gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS,
|
||||
|
||||
.hostbus_diversity = 1,
|
||||
};
|
||||
|
||||
/* STK7070P */
|
||||
static int stk7070p_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
|
||||
msleep(10);
|
||||
dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1);
|
||||
dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1);
|
||||
dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1);
|
||||
dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0);
|
||||
|
||||
dib0700_ctrl_clock(adap->dev, 72, 1);
|
||||
|
||||
msleep(10);
|
||||
dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
|
||||
msleep(10);
|
||||
dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
|
||||
|
||||
dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18, &dib7070p_dib7000p_config);
|
||||
|
||||
adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80, &dib7070p_dib7000p_config);
|
||||
return adap->fe == NULL ? -ENODEV : 0;
|
||||
}
|
||||
|
||||
/* STK7070PD */
|
||||
static struct dib7000p_config stk7070pd_dib7000p_config[2] = {
|
||||
{
|
||||
.output_mpeg2_in_188_bytes = 1,
|
||||
|
||||
.agc_config_count = 1,
|
||||
.agc = &dib7070_agc_config,
|
||||
.bw = &dib7070_bw_config_12_mhz,
|
||||
|
||||
.gpio_dir = DIB7000P_GPIO_DEFAULT_DIRECTIONS,
|
||||
.gpio_val = DIB7000P_GPIO_DEFAULT_VALUES,
|
||||
.gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS,
|
||||
|
||||
.hostbus_diversity = 1,
|
||||
}, {
|
||||
.output_mpeg2_in_188_bytes = 1,
|
||||
|
||||
.agc_config_count = 1,
|
||||
.agc = &dib7070_agc_config,
|
||||
.bw = &dib7070_bw_config_12_mhz,
|
||||
|
||||
.gpio_dir = DIB7000P_GPIO_DEFAULT_DIRECTIONS,
|
||||
.gpio_val = DIB7000P_GPIO_DEFAULT_VALUES,
|
||||
.gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS,
|
||||
|
||||
.hostbus_diversity = 1,
|
||||
}
|
||||
};
|
||||
|
||||
static int stk7070pd_frontend_attach0(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
|
||||
msleep(10);
|
||||
dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1);
|
||||
dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1);
|
||||
dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1);
|
||||
dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0);
|
||||
|
||||
dib0700_ctrl_clock(adap->dev, 72, 1);
|
||||
|
||||
msleep(10);
|
||||
dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
|
||||
msleep(10);
|
||||
dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
|
||||
|
||||
dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 2, 18, stk7070pd_dib7000p_config);
|
||||
|
||||
adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80, &stk7070pd_dib7000p_config[0]);
|
||||
return adap->fe == NULL ? -ENODEV : 0;
|
||||
}
|
||||
|
||||
static int stk7070pd_frontend_attach1(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x82, &stk7070pd_dib7000p_config[1]);
|
||||
return adap->fe == NULL ? -ENODEV : 0;
|
||||
}
|
||||
|
||||
/* DVB-USB and USB stuff follows */
|
||||
struct usb_device_id dib0700_usb_id_table[] = {
|
||||
{ USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7700P) },
|
||||
/* 0 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7700P) },
|
||||
{ USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7700P_PC) },
|
||||
|
||||
{ USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500) },
|
||||
{ USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500_2) },
|
||||
{ USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK) },
|
||||
{ USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR) },
|
||||
/* 5 */ { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR) },
|
||||
{ USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_VIDEOMATE_U500) },
|
||||
{ USB_DEVICE(USB_VID_UNIWILL, USB_PID_UNIWILL_STK7700P) },
|
||||
{ USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_STK7700P) },
|
||||
{ USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK_2) },
|
||||
{ USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_2) },
|
||||
{ } /* Terminating entry */
|
||||
/* 10 */{ USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_2) },
|
||||
{ USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV2000E) },
|
||||
{ USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY) },
|
||||
{ USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_TD_STICK) },
|
||||
{ USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7700D) },
|
||||
/* 15 */{ USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7070P) },
|
||||
{ USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV_DVB_T_FLASH) },
|
||||
{ USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7070PD) },
|
||||
{ USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV_DUAL_DIVERSITY_DVB_T) },
|
||||
{ USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_VIDEOMATE_U500_PC) },
|
||||
/* 20 */{ USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_EXPRESS) },
|
||||
{ 0 } /* Terminating entry */
|
||||
};
|
||||
MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table);
|
||||
|
||||
#define DIB0700_DEFAULT_DEVICE_PROPERTIES \
|
||||
.caps = DVB_USB_IS_AN_I2C_ADAPTER, \
|
||||
.usb_ctrl = DEVICE_SPECIFIC, \
|
||||
.firmware = "dvb-usb-dib0700-01.fw", \
|
||||
.firmware = "dvb-usb-dib0700-03-pre1.fw", \
|
||||
.download_firmware = dib0700_download_firmware, \
|
||||
.no_reconnect = 1, \
|
||||
.size_of_priv = sizeof(struct dib0700_state), \
|
||||
|
@ -321,7 +862,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
|
|||
},
|
||||
},
|
||||
|
||||
.num_device_descs = 6,
|
||||
.num_device_descs = 7,
|
||||
.devices = {
|
||||
{ "DiBcom STK7700P reference design",
|
||||
{ &dib0700_usb_id_table[0], &dib0700_usb_id_table[1] },
|
||||
|
@ -336,7 +877,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
|
|||
{ NULL },
|
||||
},
|
||||
{ "Compro Videomate U500",
|
||||
{ &dib0700_usb_id_table[6], NULL },
|
||||
{ &dib0700_usb_id_table[6], &dib0700_usb_id_table[19] },
|
||||
{ NULL },
|
||||
},
|
||||
{ "Uniwill STK7700P based (Hama and others)",
|
||||
|
@ -346,8 +887,17 @@ struct dvb_usb_device_properties dib0700_devices[] = {
|
|||
{ "Leadtek Winfast DTV Dongle (STK7700P based)",
|
||||
{ &dib0700_usb_id_table[8], NULL },
|
||||
{ NULL },
|
||||
},
|
||||
{ "AVerMedia AVerTV DVB-T Express",
|
||||
{ &dib0700_usb_id_table[20] },
|
||||
{ NULL },
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_key_map = dib0700_rc_keys,
|
||||
.rc_key_map_size = ARRAY_SIZE(dib0700_rc_keys),
|
||||
.rc_query = dib0700_rc_query
|
||||
}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
|
||||
|
||||
.num_adapters = 2,
|
||||
|
@ -371,8 +921,112 @@ struct dvb_usb_device_properties dib0700_devices[] = {
|
|||
{ &dib0700_usb_id_table[2], &dib0700_usb_id_table[3], NULL },
|
||||
{ NULL },
|
||||
},
|
||||
},
|
||||
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_key_map = dib0700_rc_keys,
|
||||
.rc_key_map_size = ARRAY_SIZE(dib0700_rc_keys),
|
||||
.rc_query = dib0700_rc_query
|
||||
}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
|
||||
|
||||
.num_adapters = 2,
|
||||
.adapter = {
|
||||
{
|
||||
.frontend_attach = stk7700d_frontend_attach,
|
||||
.tuner_attach = stk7700d_tuner_attach,
|
||||
|
||||
DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
|
||||
}, {
|
||||
.frontend_attach = stk7700d_frontend_attach,
|
||||
.tuner_attach = stk7700d_tuner_attach,
|
||||
|
||||
DIB0700_DEFAULT_STREAMING_CONFIG(0x03),
|
||||
}
|
||||
},
|
||||
|
||||
.num_device_descs = 4,
|
||||
.devices = {
|
||||
{ "Pinnacle PCTV 2000e",
|
||||
{ &dib0700_usb_id_table[11], NULL },
|
||||
{ NULL },
|
||||
},
|
||||
{ "Terratec Cinergy DT XS Diversity",
|
||||
{ &dib0700_usb_id_table[12], NULL },
|
||||
{ NULL },
|
||||
},
|
||||
{ "Hauppauge Nova-TD Stick/Elgato Eye-TV Diversity",
|
||||
{ &dib0700_usb_id_table[13], NULL },
|
||||
{ NULL },
|
||||
},
|
||||
{ "DiBcom STK7700D reference design",
|
||||
{ &dib0700_usb_id_table[14], NULL },
|
||||
{ NULL },
|
||||
},
|
||||
},
|
||||
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_key_map = dib0700_rc_keys,
|
||||
.rc_key_map_size = ARRAY_SIZE(dib0700_rc_keys),
|
||||
.rc_query = dib0700_rc_query
|
||||
|
||||
}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
|
||||
|
||||
.num_adapters = 1,
|
||||
.adapter = {
|
||||
{
|
||||
.frontend_attach = stk7070p_frontend_attach,
|
||||
.tuner_attach = dib7070p_tuner_attach,
|
||||
|
||||
DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
|
||||
|
||||
.size_of_priv = sizeof(struct dib0700_adapter_state),
|
||||
},
|
||||
},
|
||||
|
||||
.num_device_descs = 2,
|
||||
.devices = {
|
||||
{ "DiBcom STK7070P reference design",
|
||||
{ &dib0700_usb_id_table[15], NULL },
|
||||
{ NULL },
|
||||
},
|
||||
{ "Pinnacle PCTV DVB-T Flash Stick",
|
||||
{ &dib0700_usb_id_table[16], NULL },
|
||||
{ NULL },
|
||||
},
|
||||
}
|
||||
}
|
||||
}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
|
||||
|
||||
.num_adapters = 2,
|
||||
.adapter = {
|
||||
{
|
||||
.frontend_attach = stk7070pd_frontend_attach0,
|
||||
.tuner_attach = dib7070p_tuner_attach,
|
||||
|
||||
DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
|
||||
|
||||
.size_of_priv = sizeof(struct dib0700_adapter_state),
|
||||
}, {
|
||||
.frontend_attach = stk7070pd_frontend_attach1,
|
||||
.tuner_attach = dib7070p_tuner_attach,
|
||||
|
||||
DIB0700_DEFAULT_STREAMING_CONFIG(0x03),
|
||||
|
||||
.size_of_priv = sizeof(struct dib0700_adapter_state),
|
||||
}
|
||||
},
|
||||
|
||||
.num_device_descs = 2,
|
||||
.devices = {
|
||||
{ "DiBcom STK7070PD reference design",
|
||||
{ &dib0700_usb_id_table[17], NULL },
|
||||
{ NULL },
|
||||
},
|
||||
{ "Pinnacle PCTV Dual DVB-T Diversity Stick",
|
||||
{ &dib0700_usb_id_table[18], NULL },
|
||||
{ NULL },
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
int dib0700_device_count = ARRAY_SIZE(dib0700_devices);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* DVB USB library compliant Linux driver for the WideView/ Yakumo/ Hama/
|
||||
* Typhoon/ Yuan DVB-T USB2.0 receiver.
|
||||
* Typhoon/ Yuan/ Miglia DVB-T USB2.0 receiver.
|
||||
*
|
||||
* Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
|
||||
*
|
||||
|
@ -96,6 +96,7 @@ static struct dvb_usb_device_properties dtt200u_properties;
|
|||
static struct dvb_usb_device_properties wt220u_fc_properties;
|
||||
static struct dvb_usb_device_properties wt220u_properties;
|
||||
static struct dvb_usb_device_properties wt220u_zl0353_properties;
|
||||
static struct dvb_usb_device_properties wt220u_miglia_properties;
|
||||
|
||||
static int dtt200u_usb_probe(struct usb_interface *intf,
|
||||
const struct usb_device_id *id)
|
||||
|
@ -103,7 +104,8 @@ static int dtt200u_usb_probe(struct usb_interface *intf,
|
|||
if (dvb_usb_device_init(intf,&dtt200u_properties,THIS_MODULE,NULL) == 0 ||
|
||||
dvb_usb_device_init(intf,&wt220u_properties,THIS_MODULE,NULL) == 0 ||
|
||||
dvb_usb_device_init(intf,&wt220u_fc_properties,THIS_MODULE,NULL) == 0 ||
|
||||
dvb_usb_device_init(intf,&wt220u_zl0353_properties,THIS_MODULE,NULL) == 0)
|
||||
dvb_usb_device_init(intf,&wt220u_zl0353_properties,THIS_MODULE,NULL) == 0 ||
|
||||
dvb_usb_device_init(intf,&wt220u_miglia_properties,THIS_MODULE,NULL) == 0)
|
||||
return 0;
|
||||
|
||||
return -ENODEV;
|
||||
|
@ -119,6 +121,7 @@ static struct usb_device_id dtt200u_usb_table [] = {
|
|||
{ USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_FC_COLD) },
|
||||
{ USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_FC_WARM) },
|
||||
{ USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_ZAP250_COLD) },
|
||||
{ USB_DEVICE(USB_VID_MIGLIA, USB_PID_WT220U_ZAP250_COLD) },
|
||||
{ 0 },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(usb, dtt200u_usb_table);
|
||||
|
@ -303,6 +306,25 @@ static struct dvb_usb_device_properties wt220u_zl0353_properties = {
|
|||
}
|
||||
};
|
||||
|
||||
static struct dvb_usb_device_properties wt220u_miglia_properties = {
|
||||
.usb_ctrl = CYPRESS_FX2,
|
||||
.firmware = "dvb-usb-wt220u-miglia-01.fw",
|
||||
|
||||
.num_adapters = 1,
|
||||
.generic_bulk_ctrl_endpoint = 0x01,
|
||||
|
||||
.num_device_descs = 1,
|
||||
.devices = {
|
||||
{ .name = "WideView WT-220U PenType Receiver (Miglia)",
|
||||
.cold_ids = { &dtt200u_usb_table[9], NULL },
|
||||
/* This device turns into WT220U_ZL0353_WARM when fw
|
||||
has been uploaded */
|
||||
.warm_ids = { NULL },
|
||||
},
|
||||
{ NULL },
|
||||
}
|
||||
};
|
||||
|
||||
/* usb specific object needed to register this driver with the usb subsystem */
|
||||
static struct usb_driver dtt200u_usb_driver = {
|
||||
.name = "dvb_usb_dtt200u",
|
||||
|
@ -333,6 +355,6 @@ module_init(dtt200u_usb_module_init);
|
|||
module_exit(dtt200u_usb_module_exit);
|
||||
|
||||
MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
|
||||
MODULE_DESCRIPTION("Driver for the WideView/Yakumo/Hama/Typhoon/Club3D DVB-T USB2.0 devices");
|
||||
MODULE_DESCRIPTION("Driver for the WideView/Yakumo/Hama/Typhoon/Club3D/Miglia DVB-T USB2.0 devices");
|
||||
MODULE_VERSION("1.0");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
/* Vendor IDs */
|
||||
#define USB_VID_ADSTECH 0x06e1
|
||||
#define USB_VID_AFATECH 0x15a4
|
||||
#define USB_VID_ALCOR_MICRO 0x058f
|
||||
#define USB_VID_ALCOR_MICRO 0x058f
|
||||
#define USB_VID_ALINK 0x05e3
|
||||
#define USB_VID_ANCHOR 0x0547
|
||||
#define USB_VID_ANUBIS_ELECTRONIC 0x10fd
|
||||
|
@ -34,6 +34,7 @@
|
|||
#define USB_VID_LEADTEK 0x0413
|
||||
#define USB_VID_LITEON 0x04ca
|
||||
#define USB_VID_MEDION 0x1660
|
||||
#define USB_VID_MIGLIA 0x18f3
|
||||
#define USB_VID_MSI 0x0db0
|
||||
#define USB_VID_OPERA1 0x695c
|
||||
#define USB_VID_PINNACLE 0x2304
|
||||
|
@ -58,6 +59,7 @@
|
|||
#define USB_PID_COMPRO_DVBU2000_UNK_COLD 0x010c
|
||||
#define USB_PID_COMPRO_DVBU2000_UNK_WARM 0x010d
|
||||
#define USB_PID_COMPRO_VIDEOMATE_U500 0x1e78
|
||||
#define USB_PID_COMPRO_VIDEOMATE_U500_PC 0x1e80
|
||||
#define USB_PID_DIBCOM_HOOK_DEFAULT 0x0064
|
||||
#define USB_PID_DIBCOM_HOOK_DEFAULT_REENUM 0x0065
|
||||
#define USB_PID_DIBCOM_MOD3000_COLD 0x0bb8
|
||||
|
@ -66,6 +68,9 @@
|
|||
#define USB_PID_DIBCOM_MOD3001_WARM 0x0bc7
|
||||
#define USB_PID_DIBCOM_STK7700P 0x1e14
|
||||
#define USB_PID_DIBCOM_STK7700P_PC 0x1e78
|
||||
#define USB_PID_DIBCOM_STK7700D 0x1ef0
|
||||
#define USB_PID_DIBCOM_STK7070P 0x1ebc
|
||||
#define USB_PID_DIBCOM_STK7070PD 0x1ebe
|
||||
#define USB_PID_DIBCOM_ANCHOR_2135_COLD 0x2131
|
||||
#define USB_PID_DPOSH_M9206_COLD 0x9206
|
||||
#define USB_PID_DPOSH_M9206_WARM 0xa090
|
||||
|
@ -115,8 +120,17 @@
|
|||
#define USB_PID_HAUPPAUGE_NOVA_T_500_2 0x9950
|
||||
#define USB_PID_HAUPPAUGE_NOVA_T_STICK 0x7050
|
||||
#define USB_PID_HAUPPAUGE_NOVA_T_STICK_2 0x7060
|
||||
#define USB_PID_HAUPPAUGE_NOVA_TD_STICK 0x9580
|
||||
#define USB_PID_AVERMEDIA_EXPRESS 0xb568
|
||||
#define USB_PID_AVERMEDIA_VOLAR 0xa807
|
||||
#define USB_PID_AVERMEDIA_VOLAR_2 0xb808
|
||||
#define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY 0x005a
|
||||
#define USB_PID_PINNACLE_PCTV2000E 0x022c
|
||||
#define USB_PID_PINNACLE_PCTV_DVB_T_FLASH 0x0228
|
||||
#define USB_PID_PINNACLE_PCTV_DUAL_DIVERSITY_DVB_T 0x0229
|
||||
#define USB_PID_PCTV_200E 0x020e
|
||||
#define USB_PID_PCTV_400E 0x020f
|
||||
#define USB_PID_PCTV_450E 0x0222
|
||||
#define USB_PID_NEBULA_DIGITV 0x0201
|
||||
#define USB_PID_DVICO_BLUEBIRD_LGDT 0xd820
|
||||
#define USB_PID_DVICO_BLUEBIRD_LG064F_COLD 0xd500
|
||||
|
@ -136,9 +150,6 @@
|
|||
#define USB_PID_MSI_MEGASKY580_55801 0x5581
|
||||
#define USB_PID_KYE_DVB_T_COLD 0x701e
|
||||
#define USB_PID_KYE_DVB_T_WARM 0x701f
|
||||
#define USB_PID_PCTV_200E 0x020e
|
||||
#define USB_PID_PCTV_400E 0x020f
|
||||
#define USB_PID_PCTV_450E 0x0222
|
||||
#define USB_PID_LITEON_DVB_T_COLD 0xf000
|
||||
#define USB_PID_LITEON_DVB_T_WARM 0xf001
|
||||
#define USB_PID_DIGIVOX_MINI_SL_COLD 0xe360
|
||||
|
@ -148,8 +159,11 @@
|
|||
#define USB_PID_WINFAST_DTV_DONGLE_COLD 0x6025
|
||||
#define USB_PID_WINFAST_DTV_DONGLE_WARM 0x6026
|
||||
#define USB_PID_WINFAST_DTV_DONGLE_STK7700P 0x6f00
|
||||
#define USB_PID_GENPIX_8PSK_COLD 0x0200
|
||||
#define USB_PID_GENPIX_8PSK_WARM 0x0201
|
||||
#define USB_PID_GENPIX_8PSK_REV_1_COLD 0x0200
|
||||
#define USB_PID_GENPIX_8PSK_REV_1_WARM 0x0201
|
||||
#define USB_PID_GENPIX_8PSK_REV_2 0x0202
|
||||
#define USB_PID_GENPIX_SKYWALKER_1 0x0203
|
||||
#define USB_PID_GENPIX_SKYWALKER_CW3K 0x0204
|
||||
#define USB_PID_SIGMATEK_DVB_110 0x6610
|
||||
#define USB_PID_MSI_DIGI_VOX_MINI_II 0x1513
|
||||
#define USB_PID_OPERA1_COLD 0x2830
|
||||
|
|
|
@ -24,7 +24,7 @@ MODULE_PARM_DESC(disable_rc_polling, "disable remote control polling (default: 0
|
|||
|
||||
static int dvb_usb_force_pid_filter_usage;
|
||||
module_param_named(force_pid_filter_usage, dvb_usb_force_pid_filter_usage, int, 0444);
|
||||
MODULE_PARM_DESC(disable_rc_polling, "force all dvb-usb-devices to use a PID filter, if any (default: 0).");
|
||||
MODULE_PARM_DESC(force_pid_filter_usage, "force all dvb-usb-devices to use a PID filter, if any (default: 0).");
|
||||
|
||||
static int dvb_usb_adapter_init(struct dvb_usb_device *d)
|
||||
{
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
/* DVB USB compliant Linux driver for the
|
||||
* - GENPIX 8pks/qpsk USB2.0 DVB-S module
|
||||
* - GENPIX 8pks/qpsk/DCII USB2.0 DVB-S module
|
||||
*
|
||||
* Copyright (C) 2006 Alan Nisota (alannisota@gmail.com)
|
||||
* Copyright (C) 2006,2007 Alan Nisota (alannisota@gmail.com)
|
||||
* Copyright (C) 2006,2007 Genpix Electronics (genpix@genpix-electronics.com)
|
||||
*
|
||||
* Thanks to GENPIX for the sample code used to implement this module.
|
||||
*
|
||||
|
@ -17,27 +18,39 @@
|
|||
|
||||
struct gp8psk_fe_state {
|
||||
struct dvb_frontend fe;
|
||||
|
||||
struct dvb_usb_device *d;
|
||||
|
||||
u8 lock;
|
||||
u16 snr;
|
||||
|
||||
unsigned long next_snr_check;
|
||||
unsigned long next_status_check;
|
||||
unsigned long status_check_interval;
|
||||
};
|
||||
|
||||
static int gp8psk_fe_update_status(struct gp8psk_fe_state *st)
|
||||
{
|
||||
u8 buf[6];
|
||||
if (time_after(jiffies,st->next_status_check)) {
|
||||
gp8psk_usb_in_op(st->d, GET_SIGNAL_LOCK, 0,0,&st->lock,1);
|
||||
gp8psk_usb_in_op(st->d, GET_SIGNAL_STRENGTH, 0,0,buf,6);
|
||||
st->snr = (buf[1]) << 8 | buf[0];
|
||||
st->next_status_check = jiffies + (st->status_check_interval*HZ)/1000;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gp8psk_fe_read_status(struct dvb_frontend* fe, fe_status_t *status)
|
||||
{
|
||||
struct gp8psk_fe_state *st = fe->demodulator_priv;
|
||||
u8 lock;
|
||||
gp8psk_fe_update_status(st);
|
||||
|
||||
if (gp8psk_usb_in_op(st->d, GET_SIGNAL_LOCK, 0, 0, &lock,1))
|
||||
return -EINVAL;
|
||||
|
||||
if (lock)
|
||||
if (st->lock)
|
||||
*status = FE_HAS_LOCK | FE_HAS_SYNC | FE_HAS_VITERBI | FE_HAS_SIGNAL | FE_HAS_CARRIER;
|
||||
else
|
||||
*status = 0;
|
||||
|
||||
if (*status & FE_HAS_LOCK)
|
||||
st->status_check_interval = 1000;
|
||||
else
|
||||
st->status_check_interval = 100;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -60,33 +73,29 @@ static int gp8psk_fe_read_unc_blocks(struct dvb_frontend* fe, u32 *unc)
|
|||
static int gp8psk_fe_read_snr(struct dvb_frontend* fe, u16 *snr)
|
||||
{
|
||||
struct gp8psk_fe_state *st = fe->demodulator_priv;
|
||||
u8 buf[2];
|
||||
|
||||
if (time_after(jiffies,st->next_snr_check)) {
|
||||
gp8psk_usb_in_op(st->d,GET_SIGNAL_STRENGTH,0,0,buf,2);
|
||||
*snr = (int)(buf[1]) << 8 | buf[0];
|
||||
/* snr is reported in dBu*256 */
|
||||
/* snr / 38.4 ~= 100% strength */
|
||||
/* snr * 17 returns 100% strength as 65535 */
|
||||
if (*snr <= 3855)
|
||||
*snr = (*snr<<4) + *snr; // snr * 17
|
||||
else
|
||||
*snr = 65535;
|
||||
st->next_snr_check = jiffies + (10*HZ)/1000;
|
||||
} else {
|
||||
*snr = st->snr;
|
||||
}
|
||||
gp8psk_fe_update_status(st);
|
||||
/* snr is reported in dBu*256 */
|
||||
*snr = st->snr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gp8psk_fe_read_signal_strength(struct dvb_frontend* fe, u16 *strength)
|
||||
{
|
||||
return gp8psk_fe_read_snr(fe, strength);
|
||||
struct gp8psk_fe_state *st = fe->demodulator_priv;
|
||||
gp8psk_fe_update_status(st);
|
||||
/* snr is reported in dBu*256 */
|
||||
/* snr / 38.4 ~= 100% strength */
|
||||
/* snr * 17 returns 100% strength as 65535 */
|
||||
if (st->snr > 0xf00)
|
||||
*strength = 0xffff;
|
||||
else
|
||||
*strength = (st->snr << 4) + st->snr; /* snr*17 */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gp8psk_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
|
||||
{
|
||||
tune->min_delay_ms = 800;
|
||||
tune->min_delay_ms = 200;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -124,7 +133,9 @@ static int gp8psk_fe_set_frontend(struct dvb_frontend* fe,
|
|||
|
||||
gp8psk_usb_out_op(state->d,TUNE_8PSK,0,0,cmd,10);
|
||||
|
||||
state->next_snr_check = jiffies;
|
||||
state->lock = 0;
|
||||
state->next_status_check = jiffies;
|
||||
state->status_check_interval = 200;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -190,6 +201,12 @@ static int gp8psk_fe_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t volt
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int gp8psk_fe_enable_high_lnb_voltage(struct dvb_frontend* fe, long onoff)
|
||||
{
|
||||
struct gp8psk_fe_state* state = fe->demodulator_priv;
|
||||
return gp8psk_usb_out_op(state->d, USE_EXTRA_VOLT, onoff, 0,NULL,0);
|
||||
}
|
||||
|
||||
static int gp8psk_fe_send_legacy_dish_cmd (struct dvb_frontend* fe, unsigned long sw_cmd)
|
||||
{
|
||||
struct gp8psk_fe_state* state = fe->demodulator_priv;
|
||||
|
@ -235,10 +252,10 @@ success:
|
|||
|
||||
static struct dvb_frontend_ops gp8psk_fe_ops = {
|
||||
.info = {
|
||||
.name = "Genpix 8psk-USB DVB-S",
|
||||
.name = "Genpix 8psk-to-USB2 DVB-S",
|
||||
.type = FE_QPSK,
|
||||
.frequency_min = 950000,
|
||||
.frequency_max = 2150000,
|
||||
.frequency_min = 800000,
|
||||
.frequency_max = 2250000,
|
||||
.frequency_stepsize = 100,
|
||||
.symbol_rate_min = 1000000,
|
||||
.symbol_rate_max = 45000000,
|
||||
|
@ -269,4 +286,5 @@ static struct dvb_frontend_ops gp8psk_fe_ops = {
|
|||
.set_tone = gp8psk_fe_set_tone,
|
||||
.set_voltage = gp8psk_fe_set_voltage,
|
||||
.dishnetwork_send_legacy_command = gp8psk_fe_send_legacy_dish_cmd,
|
||||
.enable_high_lnb_voltage = gp8psk_fe_enable_high_lnb_voltage
|
||||
};
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
/* DVB USB compliant Linux driver for the
|
||||
* - GENPIX 8pks/qpsk USB2.0 DVB-S module
|
||||
* - GENPIX 8pks/qpsk/DCII USB2.0 DVB-S module
|
||||
*
|
||||
* Copyright (C) 2006 Alan Nisota (alannisota@gmail.com)
|
||||
* Copyright (C) 2006,2007 Alan Nisota (alannisota@gmail.com)
|
||||
* Copyright (C) 2006,2007 Genpix Electronics (genpix@genpix-electronics.com)
|
||||
*
|
||||
* Thanks to GENPIX for the sample code used to implement this module.
|
||||
*
|
||||
|
@ -40,7 +41,7 @@ int gp8psk_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8
|
|||
}
|
||||
|
||||
if (ret < 0 || ret != blen) {
|
||||
warn("usb in operation failed.");
|
||||
warn("usb in %d operation failed.", req);
|
||||
ret = -EIO;
|
||||
} else
|
||||
ret = 0;
|
||||
|
@ -97,10 +98,10 @@ static int gp8psk_load_bcm4500fw(struct dvb_usb_device *d)
|
|||
if (gp8psk_usb_out_op(d, LOAD_BCM4500,1,0,NULL, 0))
|
||||
goto out_rel_fw;
|
||||
|
||||
info("downloaidng bcm4500 firmware from file '%s'",bcm4500_firmware);
|
||||
info("downloading bcm4500 firmware from file '%s'",bcm4500_firmware);
|
||||
|
||||
ptr = fw->data;
|
||||
buf = kmalloc(512, GFP_KERNEL | GFP_DMA);
|
||||
buf = kmalloc(64, GFP_KERNEL | GFP_DMA);
|
||||
|
||||
while (ptr[0] != 0xff) {
|
||||
u16 buflen = ptr[0] + 4;
|
||||
|
@ -129,25 +130,34 @@ out_rel_fw:
|
|||
static int gp8psk_power_ctrl(struct dvb_usb_device *d, int onoff)
|
||||
{
|
||||
u8 status, buf;
|
||||
int gp_product_id = le16_to_cpu(d->udev->descriptor.idProduct);
|
||||
|
||||
if (onoff) {
|
||||
gp8psk_usb_in_op(d, GET_8PSK_CONFIG,0,0,&status,1);
|
||||
if (! (status & 0x01)) /* started */
|
||||
if (! (status & bm8pskStarted)) { /* started */
|
||||
if(gp_product_id == USB_PID_GENPIX_SKYWALKER_CW3K)
|
||||
gp8psk_usb_out_op(d, CW3K_INIT, 1, 0, NULL, 0);
|
||||
if (gp8psk_usb_in_op(d, BOOT_8PSK, 1, 0, &buf, 1))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (! (status & 0x02)) /* BCM4500 firmware loaded */
|
||||
if(gp8psk_load_bcm4500fw(d))
|
||||
return EINVAL;
|
||||
if (gp_product_id == USB_PID_GENPIX_8PSK_REV_1_WARM)
|
||||
if (! (status & bm8pskFW_Loaded)) /* BCM4500 firmware loaded */
|
||||
if(gp8psk_load_bcm4500fw(d))
|
||||
return EINVAL;
|
||||
|
||||
if (! (status & 0x04)) /* LNB Power */
|
||||
if (! (status & bmIntersilOn)) /* LNB Power */
|
||||
if (gp8psk_usb_in_op(d, START_INTERSIL, 1, 0,
|
||||
&buf, 1))
|
||||
return EINVAL;
|
||||
|
||||
/* Set DVB mode */
|
||||
if(gp8psk_usb_out_op(d, SET_DVB_MODE, 1, 0, NULL, 0))
|
||||
return -EINVAL;
|
||||
gp8psk_usb_in_op(d, GET_8PSK_CONFIG,0,0,&status,1);
|
||||
/* Set DVB mode to 1 */
|
||||
if (gp_product_id == USB_PID_GENPIX_8PSK_REV_1_WARM)
|
||||
if (gp8psk_usb_out_op(d, SET_DVB_MODE, 1, 0, NULL, 0))
|
||||
return EINVAL;
|
||||
/* Abort possible TS (if previous tune crashed) */
|
||||
if (gp8psk_usb_out_op(d, ARM_TRANSFER, 0, 0, NULL, 0))
|
||||
return EINVAL;
|
||||
} else {
|
||||
/* Turn off LNB power */
|
||||
if (gp8psk_usb_in_op(d, START_INTERSIL, 0, 0, &buf, 1))
|
||||
|
@ -155,11 +165,28 @@ static int gp8psk_power_ctrl(struct dvb_usb_device *d, int onoff)
|
|||
/* Turn off 8psk power */
|
||||
if (gp8psk_usb_in_op(d, BOOT_8PSK, 0, 0, &buf, 1))
|
||||
return -EINVAL;
|
||||
|
||||
if(gp_product_id == USB_PID_GENPIX_SKYWALKER_CW3K)
|
||||
gp8psk_usb_out_op(d, CW3K_INIT, 0, 0, NULL, 0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gp8psk_bcm4500_reload(struct dvb_usb_device *d)
|
||||
{
|
||||
u8 buf;
|
||||
int gp_product_id = le16_to_cpu(d->udev->descriptor.idProduct);
|
||||
/* Turn off 8psk power */
|
||||
if (gp8psk_usb_in_op(d, BOOT_8PSK, 0, 0, &buf, 1))
|
||||
return -EINVAL;
|
||||
/* Turn On 8psk power */
|
||||
if (gp8psk_usb_in_op(d, BOOT_8PSK, 1, 0, &buf, 1))
|
||||
return -EINVAL;
|
||||
/* load BCM4500 firmware */
|
||||
if (gp_product_id == USB_PID_GENPIX_8PSK_REV_1_WARM)
|
||||
if (gp8psk_load_bcm4500fw(d))
|
||||
return EINVAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gp8psk_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
|
||||
{
|
||||
|
@ -177,12 +204,22 @@ static struct dvb_usb_device_properties gp8psk_properties;
|
|||
static int gp8psk_usb_probe(struct usb_interface *intf,
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
return dvb_usb_device_init(intf,&gp8psk_properties,THIS_MODULE,NULL);
|
||||
int ret;
|
||||
struct usb_device *udev = interface_to_usbdev(intf);
|
||||
ret = dvb_usb_device_init(intf,&gp8psk_properties,THIS_MODULE,NULL);
|
||||
if (ret == 0) {
|
||||
info("found Genpix USB device pID = %x (hex)",
|
||||
le16_to_cpu(udev->descriptor.idProduct));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct usb_device_id gp8psk_usb_table [] = {
|
||||
{ USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_8PSK_COLD) },
|
||||
{ USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_8PSK_WARM) },
|
||||
{ USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_8PSK_REV_1_COLD) },
|
||||
{ USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_8PSK_REV_1_WARM) },
|
||||
{ USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_8PSK_REV_2) },
|
||||
{ USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_SKYWALKER_1) },
|
||||
{ USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_SKYWALKER_CW3K) },
|
||||
{ 0 },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(usb, gp8psk_usb_table);
|
||||
|
@ -213,12 +250,24 @@ static struct dvb_usb_device_properties gp8psk_properties = {
|
|||
|
||||
.generic_bulk_ctrl_endpoint = 0x01,
|
||||
|
||||
.num_device_descs = 1,
|
||||
.num_device_descs = 4,
|
||||
.devices = {
|
||||
{ .name = "Genpix 8PSK-USB DVB-S USB2.0 receiver",
|
||||
{ .name = "Genpix 8PSK-to-USB2 Rev.1 DVB-S receiver",
|
||||
.cold_ids = { &gp8psk_usb_table[0], NULL },
|
||||
.warm_ids = { &gp8psk_usb_table[1], NULL },
|
||||
},
|
||||
{ .name = "Genpix 8PSK-to-USB2 Rev.2 DVB-S receiver",
|
||||
.cold_ids = { NULL },
|
||||
.warm_ids = { &gp8psk_usb_table[2], NULL },
|
||||
},
|
||||
{ .name = "Genpix SkyWalker-1 DVB-S receiver",
|
||||
.cold_ids = { NULL },
|
||||
.warm_ids = { &gp8psk_usb_table[3], NULL },
|
||||
},
|
||||
{ .name = "Genpix SkyWalker-CW3K DVB-S receiver",
|
||||
.cold_ids = { NULL },
|
||||
.warm_ids = { &gp8psk_usb_table[4], NULL },
|
||||
},
|
||||
{ NULL },
|
||||
}
|
||||
};
|
||||
|
@ -253,6 +302,6 @@ module_init(gp8psk_usb_module_init);
|
|||
module_exit(gp8psk_usb_module_exit);
|
||||
|
||||
MODULE_AUTHOR("Alan Nisota <alannisota@gamil.com>");
|
||||
MODULE_DESCRIPTION("Driver for Genpix 8psk-USB DVB-S USB2.0");
|
||||
MODULE_VERSION("1.0");
|
||||
MODULE_DESCRIPTION("Driver for Genpix 8psk-to-USB2 DVB-S");
|
||||
MODULE_VERSION("1.1");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
/* DVB USB compliant Linux driver for the
|
||||
* - GENPIX 8pks/qpsk USB2.0 DVB-S module
|
||||
* - GENPIX 8pks/qpsk/DCII USB2.0 DVB-S module
|
||||
*
|
||||
* Copyright (C) 2006 Alan Nisota (alannisota@gmail.com)
|
||||
* Copyright (C) 2006,2007 Alan Nisota (alannisota@gmail.com)
|
||||
*
|
||||
* Thanks to GENPIX for the sample code used to implement this module.
|
||||
*
|
||||
|
@ -30,21 +31,37 @@ extern int dvb_usb_gp8psk_debug;
|
|||
#define TH_COMMAND_IN 0xC0
|
||||
#define TH_COMMAND_OUT 0xC1
|
||||
|
||||
/* command bytes */
|
||||
#define GET_8PSK_CONFIG 0x80
|
||||
/* gp8psk commands */
|
||||
|
||||
#define GET_8PSK_CONFIG 0x80 /* in */
|
||||
#define SET_8PSK_CONFIG 0x81
|
||||
#define I2C_WRITE 0x83
|
||||
#define I2C_READ 0x84
|
||||
#define ARM_TRANSFER 0x85
|
||||
#define TUNE_8PSK 0x86
|
||||
#define GET_SIGNAL_STRENGTH 0x87
|
||||
#define GET_SIGNAL_STRENGTH 0x87 /* in */
|
||||
#define LOAD_BCM4500 0x88
|
||||
#define BOOT_8PSK 0x89
|
||||
#define START_INTERSIL 0x8A
|
||||
#define BOOT_8PSK 0x89 /* in */
|
||||
#define START_INTERSIL 0x8A /* in */
|
||||
#define SET_LNB_VOLTAGE 0x8B
|
||||
#define SET_22KHZ_TONE 0x8C
|
||||
#define SEND_DISEQC_COMMAND 0x8D
|
||||
#define SET_DVB_MODE 0x8E
|
||||
#define SET_DN_SWITCH 0x8F
|
||||
#define GET_SIGNAL_LOCK 0x90
|
||||
#define GET_SIGNAL_LOCK 0x90 /* in */
|
||||
#define GET_SERIAL_NUMBER 0x93 /* in */
|
||||
#define USE_EXTRA_VOLT 0x94
|
||||
#define CW3K_INIT 0x9d
|
||||
|
||||
/* PSK_configuration bits */
|
||||
#define bm8pskStarted 0x01
|
||||
#define bm8pskFW_Loaded 0x02
|
||||
#define bmIntersilOn 0x04
|
||||
#define bmDVBmode 0x08
|
||||
#define bm22kHz 0x10
|
||||
#define bmSEL18V 0x20
|
||||
#define bmDCtuned 0x40
|
||||
#define bmArmed 0x80
|
||||
|
||||
/* Satellite modulation modes */
|
||||
#define ADV_MOD_DVB_QPSK 0 /* DVB-S QPSK */
|
||||
|
@ -75,5 +92,6 @@ extern struct dvb_frontend * gp8psk_fe_attach(struct dvb_usb_device *d);
|
|||
extern int gp8psk_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen);
|
||||
extern int gp8psk_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value,
|
||||
u16 index, u8 *b, int blen);
|
||||
extern int gp8psk_bcm4500_reload(struct dvb_usb_device *d);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -159,7 +159,7 @@ static int vp7045_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
|||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < sizeof(vp7045_rc_keys)/sizeof(struct dvb_usb_rc_key); i++)
|
||||
for (i = 0; i < ARRAY_SIZE(vp7045_rc_keys); i++)
|
||||
if (vp7045_rc_keys[i].data == key) {
|
||||
*state = REMOTE_KEY_PRESSED;
|
||||
*event = vp7045_rc_keys[i].event;
|
||||
|
|
|
@ -283,6 +283,14 @@ config DVB_LGDT330X
|
|||
An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
|
||||
to support this frontend.
|
||||
|
||||
config DVB_S5H1409
|
||||
tristate "Samsung S5H1409 based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if DVB_FE_CUSTOMISE
|
||||
help
|
||||
An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
|
||||
to support this frontend.
|
||||
|
||||
comment "Tuners/PLL support"
|
||||
depends on DVB_CORE
|
||||
|
||||
|
@ -291,7 +299,7 @@ config DVB_PLL
|
|||
depends on DVB_CORE && I2C
|
||||
default m if DVB_FE_CUSTOMISE
|
||||
help
|
||||
This module driver a number of tuners based on PLL chips with a
|
||||
This module drives a number of tuners based on PLL chips with a
|
||||
common I2C interface. Say Y when you want to support these tuners.
|
||||
|
||||
config DVB_TDA826X
|
||||
|
@ -322,6 +330,29 @@ config DVB_TUNER_MT2060
|
|||
help
|
||||
A driver for the silicon IF tuner MT2060 from Microtune.
|
||||
|
||||
config DVB_TUNER_MT2266
|
||||
tristate "Microtune MT2266 silicon tuner"
|
||||
depends on I2C
|
||||
default m if DVB_FE_CUSTOMISE
|
||||
help
|
||||
A driver for the silicon baseband tuner MT2266 from Microtune.
|
||||
|
||||
config DVB_TUNER_MT2131
|
||||
tristate "Microtune MT2131 silicon tuner"
|
||||
depends on I2C
|
||||
default m if DVB_FE_CUSTOMISE
|
||||
help
|
||||
A driver for the silicon baseband tuner MT2131 from Microtune.
|
||||
|
||||
config DVB_TUNER_DIB0070
|
||||
tristate "DiBcom DiB0070 silicon base-band tuner"
|
||||
depends on I2C
|
||||
default m if DVB_FE_CUSTOMISE
|
||||
help
|
||||
A driver for the silicon baseband tuner DiB0070 from DiBcom.
|
||||
This device is only used inside a SiP called togther with a
|
||||
demodulator for now.
|
||||
|
||||
comment "Miscellaneous devices"
|
||||
depends on DVB_CORE
|
||||
|
||||
|
|
|
@ -40,5 +40,9 @@ obj-$(CONFIG_DVB_TDA10086) += tda10086.o
|
|||
obj-$(CONFIG_DVB_TDA826X) += tda826x.o
|
||||
obj-$(CONFIG_DVB_TDA827X) += tda827x.o
|
||||
obj-$(CONFIG_DVB_TUNER_MT2060) += mt2060.o
|
||||
obj-$(CONFIG_DVB_TUNER_MT2266) += mt2266.o
|
||||
obj-$(CONFIG_DVB_TUNER_DIB0070) += dib0070.o
|
||||
obj-$(CONFIG_DVB_TUNER_QT1010) += qt1010.o
|
||||
obj-$(CONFIG_DVB_TUA6100) += tua6100.o
|
||||
obj-$(CONFIG_DVB_TUNER_MT2131) += mt2131.o
|
||||
obj-$(CONFIG_DVB_S5H1409) += s5h1409.o
|
||||
|
|
|
@ -33,7 +33,6 @@
|
|||
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/jiffies.h>
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/slab.h>
|
||||
#include "dvb_frontend.h"
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
#include "dvb_frontend.h"
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
#include "dvb_frontend.h"
|
||||
|
|
|
@ -0,0 +1,580 @@
|
|||
/*
|
||||
* Linux-DVB Driver for DiBcom's DiB0070 base-band RF Tuner.
|
||||
*
|
||||
* Copyright (C) 2005-7 DiBcom (http://www.dibcom.fr/)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation, version 2.
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/i2c.h>
|
||||
|
||||
#include "dvb_frontend.h"
|
||||
|
||||
#include "dib0070.h"
|
||||
#include "dibx000_common.h"
|
||||
|
||||
static int debug;
|
||||
module_param(debug, int, 0644);
|
||||
MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
|
||||
|
||||
#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB0070: "); printk(args); printk("\n"); } } while (0)
|
||||
|
||||
#define DIB0070_P1D 0x00
|
||||
#define DIB0070_P1F 0x01
|
||||
#define DIB0070_P1G 0x03
|
||||
#define DIB0070S_P1A 0x02
|
||||
|
||||
struct dib0070_state {
|
||||
struct i2c_adapter *i2c;
|
||||
struct dvb_frontend *fe;
|
||||
const struct dib0070_config *cfg;
|
||||
u16 wbd_ff_offset;
|
||||
u8 revision;
|
||||
};
|
||||
|
||||
static uint16_t dib0070_read_reg(struct dib0070_state *state, u8 reg)
|
||||
{
|
||||
u8 b[2];
|
||||
struct i2c_msg msg[2] = {
|
||||
{ .addr = state->cfg->i2c_address, .flags = 0, .buf = ®, .len = 1 },
|
||||
{ .addr = state->cfg->i2c_address, .flags = I2C_M_RD, .buf = b, .len = 2 },
|
||||
};
|
||||
if (i2c_transfer(state->i2c, msg, 2) != 2) {
|
||||
printk(KERN_WARNING "DiB0070 I2C read failed\n");
|
||||
return 0;
|
||||
}
|
||||
return (b[0] << 8) | b[1];
|
||||
}
|
||||
|
||||
static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val)
|
||||
{
|
||||
u8 b[3] = { reg, val >> 8, val & 0xff };
|
||||
struct i2c_msg msg = { .addr = state->cfg->i2c_address, .flags = 0, .buf = b, .len = 3 };
|
||||
if (i2c_transfer(state->i2c, &msg, 1) != 1) {
|
||||
printk(KERN_WARNING "DiB0070 I2C write failed\n");
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define HARD_RESET(state) do { if (state->cfg->reset) { state->cfg->reset(state->fe,1); msleep(10); state->cfg->reset(state->fe,0); msleep(10); } } while (0)
|
||||
|
||||
static int dib0070_set_bandwidth(struct dvb_frontend *fe, struct dvb_frontend_parameters *ch)
|
||||
{
|
||||
struct dib0070_state *st = fe->tuner_priv;
|
||||
u16 tmp = 0;
|
||||
tmp = dib0070_read_reg(st, 0x02) & 0x3fff;
|
||||
|
||||
switch(BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth)) {
|
||||
case 8000:
|
||||
tmp |= (0 << 14);
|
||||
break;
|
||||
case 7000:
|
||||
tmp |= (1 << 14);
|
||||
break;
|
||||
case 6000:
|
||||
tmp |= (2 << 14);
|
||||
break;
|
||||
case 5000:
|
||||
default:
|
||||
tmp |= (3 << 14);
|
||||
break;
|
||||
}
|
||||
dib0070_write_reg(st, 0x02, tmp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dib0070_captrim(struct dib0070_state *st, u16 LO4)
|
||||
{
|
||||
int8_t captrim, fcaptrim, step_sign, step;
|
||||
u16 adc, adc_diff = 3000;
|
||||
|
||||
|
||||
|
||||
dib0070_write_reg(st, 0x0f, 0xed10);
|
||||
dib0070_write_reg(st, 0x17, 0x0034);
|
||||
|
||||
dib0070_write_reg(st, 0x18, 0x0032);
|
||||
msleep(2);
|
||||
|
||||
step = captrim = fcaptrim = 64;
|
||||
|
||||
do {
|
||||
step /= 2;
|
||||
dib0070_write_reg(st, 0x14, LO4 | captrim);
|
||||
msleep(1);
|
||||
adc = dib0070_read_reg(st, 0x19);
|
||||
|
||||
dprintk( "CAPTRIM=%hd; ADC = %hd (ADC) & %dmV", captrim, adc, (u32) adc*(u32)1800/(u32)1024);
|
||||
|
||||
if (adc >= 400) {
|
||||
adc -= 400;
|
||||
step_sign = -1;
|
||||
} else {
|
||||
adc = 400 - adc;
|
||||
step_sign = 1;
|
||||
}
|
||||
|
||||
if (adc < adc_diff) {
|
||||
dprintk( "CAPTRIM=%hd is closer to target (%hd/%hd)", captrim, adc, adc_diff);
|
||||
adc_diff = adc;
|
||||
fcaptrim = captrim;
|
||||
|
||||
|
||||
|
||||
}
|
||||
captrim += (step_sign * step);
|
||||
} while (step >= 1);
|
||||
|
||||
dib0070_write_reg(st, 0x14, LO4 | fcaptrim);
|
||||
dib0070_write_reg(st, 0x18, 0x07ff);
|
||||
}
|
||||
|
||||
#define LPF 100 // define for the loop filter 100kHz by default 16-07-06
|
||||
#define LO4_SET_VCO_HFDIV(l, v, h) l |= ((v) << 11) | ((h) << 7)
|
||||
#define LO4_SET_SD(l, s) l |= ((s) << 14) | ((s) << 12)
|
||||
#define LO4_SET_CTRIM(l, c) l |= (c) << 10
|
||||
static int dib0070_tune_digital(struct dvb_frontend *fe, struct dvb_frontend_parameters *ch)
|
||||
{
|
||||
struct dib0070_state *st = fe->tuner_priv;
|
||||
u32 freq = ch->frequency/1000 + (BAND_OF_FREQUENCY(ch->frequency/1000) == BAND_VHF ? st->cfg->freq_offset_khz_vhf : st->cfg->freq_offset_khz_uhf);
|
||||
|
||||
u8 band = BAND_OF_FREQUENCY(freq), c;
|
||||
|
||||
/*******************VCO***********************************/
|
||||
u16 lo4 = 0;
|
||||
|
||||
u8 REFDIV, PRESC = 2;
|
||||
u32 FBDiv, Rest, FREF, VCOF_kHz;
|
||||
u16 Num, Den;
|
||||
/*******************FrontEnd******************************/
|
||||
u16 value = 0;
|
||||
|
||||
dprintk( "Tuning for Band: %hd (%d kHz)", band, freq);
|
||||
|
||||
|
||||
dib0070_write_reg(st, 0x17, 0x30);
|
||||
|
||||
dib0070_set_bandwidth(fe, ch); /* c is used as HF */
|
||||
switch (st->revision) {
|
||||
case DIB0070S_P1A:
|
||||
switch (band) {
|
||||
case BAND_LBAND:
|
||||
LO4_SET_VCO_HFDIV(lo4, 1, 1);
|
||||
c = 2;
|
||||
break;
|
||||
case BAND_SBAND:
|
||||
LO4_SET_VCO_HFDIV(lo4, 0, 0);
|
||||
LO4_SET_CTRIM(lo4, 1);;
|
||||
c = 1;
|
||||
break;
|
||||
case BAND_UHF:
|
||||
default:
|
||||
if (freq < 570000) {
|
||||
LO4_SET_VCO_HFDIV(lo4, 1, 3);
|
||||
PRESC = 6; c = 6;
|
||||
} else if (freq < 680000) {
|
||||
LO4_SET_VCO_HFDIV(lo4, 0, 2);
|
||||
c = 4;
|
||||
} else {
|
||||
LO4_SET_VCO_HFDIV(lo4, 1, 2);
|
||||
c = 4;
|
||||
}
|
||||
break;
|
||||
} break;
|
||||
|
||||
case DIB0070_P1G:
|
||||
case DIB0070_P1F:
|
||||
default:
|
||||
switch (band) {
|
||||
case BAND_FM:
|
||||
LO4_SET_VCO_HFDIV(lo4, 0, 7);
|
||||
c = 24;
|
||||
break;
|
||||
case BAND_LBAND:
|
||||
LO4_SET_VCO_HFDIV(lo4, 1, 0);
|
||||
c = 2;
|
||||
break;
|
||||
case BAND_VHF:
|
||||
if (freq < 180000) {
|
||||
LO4_SET_VCO_HFDIV(lo4, 0, 3);
|
||||
c = 16;
|
||||
} else if (freq < 190000) {
|
||||
LO4_SET_VCO_HFDIV(lo4, 1, 3);
|
||||
c = 16;
|
||||
} else {
|
||||
LO4_SET_VCO_HFDIV(lo4, 0, 6);
|
||||
c = 12;
|
||||
}
|
||||
break;
|
||||
|
||||
case BAND_UHF:
|
||||
default:
|
||||
if (freq < 570000) {
|
||||
LO4_SET_VCO_HFDIV(lo4, 1, 5);
|
||||
c = 6;
|
||||
} else if (freq < 700000) {
|
||||
LO4_SET_VCO_HFDIV(lo4, 0, 1);
|
||||
c = 4;
|
||||
} else {
|
||||
LO4_SET_VCO_HFDIV(lo4, 1, 1);
|
||||
c = 4;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
dprintk( "HFDIV code: %hd", (lo4 >> 7) & 0xf);
|
||||
dprintk( "VCO = %hd", (lo4 >> 11) & 0x3);
|
||||
|
||||
|
||||
VCOF_kHz = (c * freq) * 2;
|
||||
dprintk( "VCOF in kHz: %d ((%hd*%d) << 1))",VCOF_kHz, c, freq);
|
||||
|
||||
switch (band) {
|
||||
case BAND_VHF:
|
||||
REFDIV = (u8) ((st->cfg->clock_khz + 9999) / 10000);
|
||||
break;
|
||||
case BAND_FM:
|
||||
REFDIV = (u8) ((st->cfg->clock_khz) / 1000);
|
||||
break;
|
||||
default:
|
||||
REFDIV = (u8) ( st->cfg->clock_khz / 10000);
|
||||
break;
|
||||
}
|
||||
FREF = st->cfg->clock_khz / REFDIV;
|
||||
|
||||
dprintk( "REFDIV: %hd, FREF: %d", REFDIV, FREF);
|
||||
|
||||
|
||||
|
||||
switch (st->revision) {
|
||||
case DIB0070S_P1A:
|
||||
FBDiv = (VCOF_kHz / PRESC / FREF);
|
||||
Rest = (VCOF_kHz / PRESC) - FBDiv * FREF;
|
||||
break;
|
||||
|
||||
case DIB0070_P1G:
|
||||
case DIB0070_P1F:
|
||||
default:
|
||||
FBDiv = (freq / (FREF / 2));
|
||||
Rest = 2 * freq - FBDiv * FREF;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (Rest < LPF) Rest = 0;
|
||||
else if (Rest < 2 * LPF) Rest = 2 * LPF;
|
||||
else if (Rest > (FREF - LPF)) { Rest = 0 ; FBDiv += 1; }
|
||||
else if (Rest > (FREF - 2 * LPF)) Rest = FREF - 2 * LPF;
|
||||
Rest = (Rest * 6528) / (FREF / 10);
|
||||
dprintk( "FBDIV: %d, Rest: %d", FBDiv, Rest);
|
||||
|
||||
Num = 0;
|
||||
Den = 1;
|
||||
|
||||
if (Rest > 0) {
|
||||
LO4_SET_SD(lo4, 1);
|
||||
Den = 255;
|
||||
Num = (u16)Rest;
|
||||
}
|
||||
dprintk( "Num: %hd, Den: %hd, SD: %hd",Num, Den, (lo4 >> 12) & 0x1);
|
||||
|
||||
|
||||
|
||||
dib0070_write_reg(st, 0x11, (u16)FBDiv);
|
||||
|
||||
|
||||
dib0070_write_reg(st, 0x12, (Den << 8) | REFDIV);
|
||||
|
||||
|
||||
dib0070_write_reg(st, 0x13, Num);
|
||||
|
||||
|
||||
value = 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001;
|
||||
|
||||
switch (band) {
|
||||
case BAND_UHF: value |= 0x4000 | 0x0800; break;
|
||||
case BAND_LBAND: value |= 0x2000 | 0x0400; break;
|
||||
default: value |= 0x8000 | 0x1000; break;
|
||||
}
|
||||
dib0070_write_reg(st, 0x20, value);
|
||||
|
||||
dib0070_captrim(st, lo4);
|
||||
if (st->revision == DIB0070S_P1A) {
|
||||
if (band == BAND_SBAND)
|
||||
dib0070_write_reg(st, 0x15, 0x16e2);
|
||||
else
|
||||
dib0070_write_reg(st, 0x15, 0x56e5);
|
||||
}
|
||||
|
||||
|
||||
|
||||
switch (band) {
|
||||
case BAND_UHF: value = 0x7c82; break;
|
||||
case BAND_LBAND: value = 0x7c84; break;
|
||||
default: value = 0x7c81; break;
|
||||
}
|
||||
dib0070_write_reg(st, 0x0f, value);
|
||||
dib0070_write_reg(st, 0x06, 0x3fff);
|
||||
|
||||
/* Front End */
|
||||
/* c == TUNE, value = SWITCH */
|
||||
c = 0;
|
||||
value = 0;
|
||||
switch (band) {
|
||||
case BAND_FM:
|
||||
c = 0; value = 1;
|
||||
break;
|
||||
|
||||
case BAND_VHF:
|
||||
if (freq <= 180000) c = 0;
|
||||
else if (freq <= 188200) c = 1;
|
||||
else if (freq <= 196400) c = 2;
|
||||
else c = 3;
|
||||
value = 1;
|
||||
break;
|
||||
|
||||
case BAND_LBAND:
|
||||
if (freq <= 1500000) c = 0;
|
||||
else if (freq <= 1600000) c = 1;
|
||||
else c = 3;
|
||||
break;
|
||||
|
||||
case BAND_SBAND:
|
||||
c = 7;
|
||||
dib0070_write_reg(st, 0x1d,0xFFFF);
|
||||
break;
|
||||
|
||||
case BAND_UHF:
|
||||
default:
|
||||
if (st->cfg->flip_chip) {
|
||||
if (freq <= 550000) c = 0;
|
||||
else if (freq <= 590000) c = 1;
|
||||
else if (freq <= 666000) c = 3;
|
||||
else c = 5;
|
||||
} else {
|
||||
if (freq <= 550000) c = 2;
|
||||
else if (freq <= 650000) c = 3;
|
||||
else if (freq <= 750000) c = 5;
|
||||
else if (freq <= 850000) c = 6;
|
||||
else c = 7;
|
||||
}
|
||||
value = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
/* default: LNA_MATCH=7, BIAS=3 */
|
||||
dib0070_write_reg(st, 0x07, (value << 11) | (7 << 8) | (c << 3) | (3 << 0));
|
||||
dib0070_write_reg(st, 0x08, (c << 10) | (3 << 7) | (127));
|
||||
dib0070_write_reg(st, 0x0d, 0x0d80);
|
||||
|
||||
|
||||
dib0070_write_reg(st, 0x18, 0x07ff);
|
||||
dib0070_write_reg(st, 0x17, 0x0033);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dib0070_wakeup(struct dvb_frontend *fe)
|
||||
{
|
||||
struct dib0070_state *st = fe->tuner_priv;
|
||||
if (st->cfg->sleep)
|
||||
st->cfg->sleep(fe, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dib0070_sleep(struct dvb_frontend *fe)
|
||||
{
|
||||
struct dib0070_state *st = fe->tuner_priv;
|
||||
if (st->cfg->sleep)
|
||||
st->cfg->sleep(fe, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u16 dib0070_p1f_defaults[] =
|
||||
|
||||
{
|
||||
7, 0x02,
|
||||
0x0008,
|
||||
0x0000,
|
||||
0x0000,
|
||||
0x0000,
|
||||
0x0000,
|
||||
0x0002,
|
||||
0x0100,
|
||||
|
||||
3, 0x0d,
|
||||
0x0d80,
|
||||
0x0001,
|
||||
0x0000,
|
||||
|
||||
4, 0x11,
|
||||
0x0000,
|
||||
0x0103,
|
||||
0x0000,
|
||||
0x0000,
|
||||
|
||||
3, 0x16,
|
||||
0x0004 | 0x0040,
|
||||
0x0030,
|
||||
0x07ff,
|
||||
|
||||
6, 0x1b,
|
||||
0x4112,
|
||||
0xff00,
|
||||
0xc07f,
|
||||
0x0000,
|
||||
0x0180,
|
||||
0x4000 | 0x0800 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001,
|
||||
|
||||
0,
|
||||
};
|
||||
|
||||
static void dib0070_wbd_calibration(struct dib0070_state *state)
|
||||
{
|
||||
u16 wbd_offs;
|
||||
dib0070_write_reg(state, 0x0f, 0x6d81);
|
||||
dib0070_write_reg(state, 0x20, 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001);
|
||||
msleep(9);
|
||||
wbd_offs = dib0070_read_reg(state, 0x19);
|
||||
dib0070_write_reg(state, 0x20, 0);
|
||||
state->wbd_ff_offset = ((wbd_offs * 8 * 18 / 33 + 1) / 2);
|
||||
dprintk( "WBDStart = %d (Vargen) - FF = %hd", (u32) wbd_offs * 1800/1024, state->wbd_ff_offset);
|
||||
}
|
||||
|
||||
u16 dib0070_wbd_offset(struct dvb_frontend *fe)
|
||||
{
|
||||
struct dib0070_state *st = fe->tuner_priv;
|
||||
return st->wbd_ff_offset;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(dib0070_wbd_offset);
|
||||
static int dib0070_set_ctrl_lo5(struct dvb_frontend *fe, u8 vco_bias_trim, u8 hf_div_trim, u8 cp_current, u8 third_order_filt)
|
||||
{
|
||||
struct dib0070_state *state = fe->tuner_priv;
|
||||
u16 lo5 = (third_order_filt << 14) | (0 << 13) | (1 << 12) | (3 << 9) | (cp_current << 6) | (hf_div_trim << 3) | (vco_bias_trim << 0);
|
||||
dprintk( "CTRL_LO5: 0x%x", lo5);
|
||||
return dib0070_write_reg(state, 0x15, lo5);
|
||||
}
|
||||
|
||||
#define pgm_read_word(w) (*w)
|
||||
static int dib0070_reset(struct dib0070_state *state)
|
||||
{
|
||||
u16 l, r, *n;
|
||||
|
||||
HARD_RESET(state);
|
||||
|
||||
|
||||
#ifndef FORCE_SBAND_TUNER
|
||||
if ((dib0070_read_reg(state, 0x22) >> 9) & 0x1)
|
||||
state->revision = (dib0070_read_reg(state, 0x1f) >> 8) & 0xff;
|
||||
else
|
||||
#endif
|
||||
state->revision = DIB0070S_P1A;
|
||||
|
||||
/* P1F or not */
|
||||
dprintk( "Revision: %x", state->revision);
|
||||
|
||||
if (state->revision == DIB0070_P1D) {
|
||||
dprintk( "Error: this driver is not to be used meant for P1D or earlier");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
n = (u16 *) dib0070_p1f_defaults;
|
||||
l = pgm_read_word(n++);
|
||||
while (l) {
|
||||
r = pgm_read_word(n++);
|
||||
do {
|
||||
dib0070_write_reg(state, (u8)r, pgm_read_word(n++));
|
||||
r++;
|
||||
} while (--l);
|
||||
l = pgm_read_word(n++);
|
||||
}
|
||||
|
||||
if (state->cfg->force_crystal_mode != 0)
|
||||
r = state->cfg->force_crystal_mode;
|
||||
else if (state->cfg->clock_khz >= 24000)
|
||||
r = 1;
|
||||
else
|
||||
r = 2;
|
||||
|
||||
r |= state->cfg->osc_buffer_state << 3;
|
||||
|
||||
dib0070_write_reg(state, 0x10, r);
|
||||
dib0070_write_reg(state, 0x1f, (1 << 8) | ((state->cfg->clock_pad_drive & 0xf) << 4));
|
||||
|
||||
if (state->cfg->invert_iq) {
|
||||
r = dib0070_read_reg(state, 0x02) & 0xffdf;
|
||||
dib0070_write_reg(state, 0x02, r | (1 << 5));
|
||||
}
|
||||
|
||||
|
||||
if (state->revision == DIB0070S_P1A)
|
||||
dib0070_set_ctrl_lo5(state->fe, 4, 7, 3, 1);
|
||||
else
|
||||
dib0070_set_ctrl_lo5(state->fe, 4, 4, 2, 0);
|
||||
|
||||
dib0070_write_reg(state, 0x01, (54 << 9) | 0xc8);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int dib0070_release(struct dvb_frontend *fe)
|
||||
{
|
||||
kfree(fe->tuner_priv);
|
||||
fe->tuner_priv = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dvb_tuner_ops dib0070_ops = {
|
||||
.info = {
|
||||
.name = "DiBcom DiB0070",
|
||||
.frequency_min = 45000000,
|
||||
.frequency_max = 860000000,
|
||||
.frequency_step = 1000,
|
||||
},
|
||||
.release = dib0070_release,
|
||||
|
||||
.init = dib0070_wakeup,
|
||||
.sleep = dib0070_sleep,
|
||||
.set_params = dib0070_tune_digital,
|
||||
// .get_frequency = dib0070_get_frequency,
|
||||
// .get_bandwidth = dib0070_get_bandwidth
|
||||
};
|
||||
|
||||
struct dvb_frontend * dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg)
|
||||
{
|
||||
struct dib0070_state *state = kzalloc(sizeof(struct dib0070_state), GFP_KERNEL);
|
||||
if (state == NULL)
|
||||
return NULL;
|
||||
|
||||
state->cfg = cfg;
|
||||
state->i2c = i2c;
|
||||
state->fe = fe;
|
||||
fe->tuner_priv = state;
|
||||
|
||||
if (dib0070_reset(state) != 0)
|
||||
goto free_mem;
|
||||
|
||||
dib0070_wbd_calibration(state);
|
||||
|
||||
printk(KERN_INFO "DiB0070: successfully identified\n");
|
||||
memcpy(&fe->ops.tuner_ops, &dib0070_ops, sizeof(struct dvb_tuner_ops));
|
||||
|
||||
fe->tuner_priv = state;
|
||||
return fe;
|
||||
|
||||
free_mem:
|
||||
kfree(state);
|
||||
fe->tuner_priv = NULL;
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(dib0070_attach);
|
||||
|
||||
MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
|
||||
MODULE_DESCRIPTION("Driver for the DiBcom 0070 base-band RF Tuner");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Linux-DVB Driver for DiBcom's DiB0070 base-band RF Tuner.
|
||||
*
|
||||
* Copyright (C) 2005-7 DiBcom (http://www.dibcom.fr/)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation, version 2.
|
||||
*/
|
||||
#ifndef DIB0070_H
|
||||
#define DIB0070_H
|
||||
|
||||
struct dvb_frontend;
|
||||
struct i2c_adapter;
|
||||
|
||||
#define DEFAULT_DIB0070_I2C_ADDRESS 0x60
|
||||
|
||||
struct dib0070_config {
|
||||
u8 i2c_address;
|
||||
|
||||
/* tuner pins controlled externally */
|
||||
int (*reset) (struct dvb_frontend *, int);
|
||||
int (*sleep) (struct dvb_frontend *, int);
|
||||
|
||||
/* offset in kHz */
|
||||
int freq_offset_khz_uhf;
|
||||
int freq_offset_khz_vhf;
|
||||
|
||||
u8 osc_buffer_state; /* 0= normal, 1= tri-state */
|
||||
u32 clock_khz;
|
||||
u8 clock_pad_drive; /* (Drive + 1) * 2mA */
|
||||
|
||||
u8 invert_iq; /* invert Q - in case I or Q is inverted on the board */
|
||||
|
||||
u8 force_crystal_mode; /* if == 0 -> decision is made in the driver default: <24 -> 2, >=24 -> 1 */
|
||||
|
||||
u8 flip_chip;
|
||||
};
|
||||
|
||||
extern struct dvb_frontend * dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg);
|
||||
extern void dib0070_ctrl_agc_filter(struct dvb_frontend *, uint8_t open);
|
||||
extern u16 dib0070_wbd_offset(struct dvb_frontend *);
|
||||
|
||||
#endif
|
|
@ -23,7 +23,6 @@
|
|||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/string.h>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Driver for DiBcom DiB3000MC/P-demodulator.
|
||||
*
|
||||
* Copyright (C) 2004-6 DiBcom (http://www.dibcom.fr/)
|
||||
* Copyright (C) 2004-7 DiBcom (http://www.dibcom.fr/)
|
||||
* Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
|
||||
*
|
||||
* This code is partially based on the previous dib3000mc.c .
|
||||
|
@ -13,10 +13,6 @@
|
|||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/i2c.h>
|
||||
//#include <linux/init.h>
|
||||
//#include <linux/delay.h>
|
||||
//#include <linux/string.h>
|
||||
//#include <linux/slab.h>
|
||||
|
||||
#include "dvb_frontend.h"
|
||||
|
||||
|
@ -26,7 +22,11 @@ static int debug;
|
|||
module_param(debug, int, 0644);
|
||||
MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
|
||||
|
||||
#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB3000MC/P:"); printk(args); } } while (0)
|
||||
static int buggy_sfn_workaround;
|
||||
module_param(buggy_sfn_workaround, int, 0644);
|
||||
MODULE_PARM_DESC(buggy_sfn_workaround, "Enable work-around for buggy SFNs (default: 0)");
|
||||
|
||||
#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB3000MC/P:"); printk(args); printk("\n"); } } while (0)
|
||||
|
||||
struct dib3000mc_state {
|
||||
struct dvb_frontend demod;
|
||||
|
@ -42,6 +42,8 @@ struct dib3000mc_state {
|
|||
fe_bandwidth_t current_bandwidth;
|
||||
|
||||
u16 dev_id;
|
||||
|
||||
u8 sfn_workaround_active :1;
|
||||
};
|
||||
|
||||
static u16 dib3000mc_read_word(struct dib3000mc_state *state, u16 reg)
|
||||
|
@ -71,7 +73,6 @@ static int dib3000mc_write_word(struct dib3000mc_state *state, u16 reg, u16 val)
|
|||
return i2c_transfer(state->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
|
||||
}
|
||||
|
||||
|
||||
static int dib3000mc_identify(struct dib3000mc_state *state)
|
||||
{
|
||||
u16 value;
|
||||
|
@ -92,7 +93,7 @@ static int dib3000mc_identify(struct dib3000mc_state *state)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int dib3000mc_set_timing(struct dib3000mc_state *state, s16 nfft, u8 bw, u8 update_offset)
|
||||
static int dib3000mc_set_timing(struct dib3000mc_state *state, s16 nfft, u32 bw, u8 update_offset)
|
||||
{
|
||||
u32 timf;
|
||||
|
||||
|
@ -103,7 +104,7 @@ static int dib3000mc_set_timing(struct dib3000mc_state *state, s16 nfft, u8 bw,
|
|||
} else
|
||||
timf = state->timf;
|
||||
|
||||
timf *= (BW_INDEX_TO_KHZ(bw) / 1000);
|
||||
timf *= (bw / 1000);
|
||||
|
||||
if (update_offset) {
|
||||
s16 tim_offs = dib3000mc_read_word(state, 416);
|
||||
|
@ -111,17 +112,17 @@ static int dib3000mc_set_timing(struct dib3000mc_state *state, s16 nfft, u8 bw,
|
|||
if (tim_offs & 0x2000)
|
||||
tim_offs -= 0x4000;
|
||||
|
||||
if (nfft == 0)
|
||||
if (nfft == TRANSMISSION_MODE_2K)
|
||||
tim_offs *= 4;
|
||||
|
||||
timf += tim_offs;
|
||||
state->timf = timf / (BW_INDEX_TO_KHZ(bw) / 1000);
|
||||
state->timf = timf / (bw / 1000);
|
||||
}
|
||||
|
||||
dprintk("timf: %d\n", timf);
|
||||
|
||||
dib3000mc_write_word(state, 23, timf >> 16);
|
||||
dib3000mc_write_word(state, 24, timf & 0xffff);
|
||||
dib3000mc_write_word(state, 23, (u16) (timf >> 16));
|
||||
dib3000mc_write_word(state, 24, (u16) (timf ) & 0xffff);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -209,31 +210,30 @@ static int dib3000mc_set_output_mode(struct dib3000mc_state *state, int mode)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int dib3000mc_set_bandwidth(struct dvb_frontend *demod, u8 bw)
|
||||
static int dib3000mc_set_bandwidth(struct dib3000mc_state *state, u32 bw)
|
||||
{
|
||||
struct dib3000mc_state *state = demod->demodulator_priv;
|
||||
u16 bw_cfg[6] = { 0 };
|
||||
u16 imp_bw_cfg[3] = { 0 };
|
||||
u16 reg;
|
||||
|
||||
/* settings here are for 27.7MHz */
|
||||
switch (bw) {
|
||||
case BANDWIDTH_8_MHZ:
|
||||
case 8000:
|
||||
bw_cfg[0] = 0x0019; bw_cfg[1] = 0x5c30; bw_cfg[2] = 0x0054; bw_cfg[3] = 0x88a0; bw_cfg[4] = 0x01a6; bw_cfg[5] = 0xab20;
|
||||
imp_bw_cfg[0] = 0x04db; imp_bw_cfg[1] = 0x00db; imp_bw_cfg[2] = 0x00b7;
|
||||
break;
|
||||
|
||||
case BANDWIDTH_7_MHZ:
|
||||
case 7000:
|
||||
bw_cfg[0] = 0x001c; bw_cfg[1] = 0xfba5; bw_cfg[2] = 0x0060; bw_cfg[3] = 0x9c25; bw_cfg[4] = 0x01e3; bw_cfg[5] = 0x0cb7;
|
||||
imp_bw_cfg[0] = 0x04c0; imp_bw_cfg[1] = 0x00c0; imp_bw_cfg[2] = 0x00a0;
|
||||
break;
|
||||
|
||||
case BANDWIDTH_6_MHZ:
|
||||
case 6000:
|
||||
bw_cfg[0] = 0x0021; bw_cfg[1] = 0xd040; bw_cfg[2] = 0x0070; bw_cfg[3] = 0xb62b; bw_cfg[4] = 0x0233; bw_cfg[5] = 0x8ed5;
|
||||
imp_bw_cfg[0] = 0x04a5; imp_bw_cfg[1] = 0x00a5; imp_bw_cfg[2] = 0x0089;
|
||||
break;
|
||||
|
||||
case 255 /* BANDWIDTH_5_MHZ */:
|
||||
case 5000:
|
||||
bw_cfg[0] = 0x0028; bw_cfg[1] = 0x9380; bw_cfg[2] = 0x0087; bw_cfg[3] = 0x4100; bw_cfg[4] = 0x02a4; bw_cfg[5] = 0x4500;
|
||||
imp_bw_cfg[0] = 0x0489; imp_bw_cfg[1] = 0x0089; imp_bw_cfg[2] = 0x0072;
|
||||
break;
|
||||
|
@ -257,7 +257,7 @@ static int dib3000mc_set_bandwidth(struct dvb_frontend *demod, u8 bw)
|
|||
dib3000mc_write_word(state, reg, imp_bw_cfg[reg - 55]);
|
||||
|
||||
// Timing configuration
|
||||
dib3000mc_set_timing(state, 0, bw, 0);
|
||||
dib3000mc_set_timing(state, TRANSMISSION_MODE_2K, bw, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -276,7 +276,7 @@ static void dib3000mc_set_impulse_noise(struct dib3000mc_state *state, u8 mode,
|
|||
for (i = 58; i < 87; i++)
|
||||
dib3000mc_write_word(state, i, impulse_noise_val[i-58]);
|
||||
|
||||
if (nfft == 1) {
|
||||
if (nfft == TRANSMISSION_MODE_8K) {
|
||||
dib3000mc_write_word(state, 58, 0x3b);
|
||||
dib3000mc_write_word(state, 84, 0x00);
|
||||
dib3000mc_write_word(state, 85, 0x8200);
|
||||
|
@ -376,7 +376,7 @@ static int dib3000mc_init(struct dvb_frontend *demod)
|
|||
// P_search_maxtrial=1
|
||||
dib3000mc_write_word(state, 5, 1);
|
||||
|
||||
dib3000mc_set_bandwidth(&state->demod, BANDWIDTH_8_MHZ);
|
||||
dib3000mc_set_bandwidth(state, 8000);
|
||||
|
||||
// div_lock_mask
|
||||
dib3000mc_write_word(state, 4, 0x814);
|
||||
|
@ -397,7 +397,7 @@ static int dib3000mc_init(struct dvb_frontend *demod)
|
|||
dib3000mc_write_word(state, 180, 0x2FF0);
|
||||
|
||||
// Impulse noise configuration
|
||||
dib3000mc_set_impulse_noise(state, 0, 1);
|
||||
dib3000mc_set_impulse_noise(state, 0, TRANSMISSION_MODE_8K);
|
||||
|
||||
// output mode set-up
|
||||
dib3000mc_set_output_mode(state, OUTMODE_HIGH_Z);
|
||||
|
@ -423,13 +423,13 @@ static void dib3000mc_set_adp_cfg(struct dib3000mc_state *state, s16 qam)
|
|||
{
|
||||
u16 cfg[4] = { 0 },reg;
|
||||
switch (qam) {
|
||||
case 0:
|
||||
case QPSK:
|
||||
cfg[0] = 0x099a; cfg[1] = 0x7fae; cfg[2] = 0x0333; cfg[3] = 0x7ff0;
|
||||
break;
|
||||
case 1:
|
||||
case QAM_16:
|
||||
cfg[0] = 0x023d; cfg[1] = 0x7fdf; cfg[2] = 0x00a4; cfg[3] = 0x7ff0;
|
||||
break;
|
||||
case 2:
|
||||
case QAM_64:
|
||||
cfg[0] = 0x0148; cfg[1] = 0x7ff0; cfg[2] = 0x00a4; cfg[3] = 0x7ff8;
|
||||
break;
|
||||
}
|
||||
|
@ -437,11 +437,11 @@ static void dib3000mc_set_adp_cfg(struct dib3000mc_state *state, s16 qam)
|
|||
dib3000mc_write_word(state, reg, cfg[reg - 129]);
|
||||
}
|
||||
|
||||
static void dib3000mc_set_channel_cfg(struct dib3000mc_state *state, struct dibx000_ofdm_channel *chan, u16 seq)
|
||||
static void dib3000mc_set_channel_cfg(struct dib3000mc_state *state, struct dvb_frontend_parameters *ch, u16 seq)
|
||||
{
|
||||
u16 tmp;
|
||||
|
||||
dib3000mc_set_timing(state, chan->nfft, chan->Bw, 0);
|
||||
u16 value;
|
||||
dib3000mc_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth));
|
||||
dib3000mc_set_timing(state, ch->u.ofdm.transmission_mode, BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth), 0);
|
||||
|
||||
// if (boost)
|
||||
// dib3000mc_write_word(state, 100, (11 << 6) + 6);
|
||||
|
@ -455,7 +455,7 @@ static void dib3000mc_set_channel_cfg(struct dib3000mc_state *state, struct dibx
|
|||
dib3000mc_write_word(state, 26, 0x6680);
|
||||
dib3000mc_write_word(state, 29, 0x1273);
|
||||
dib3000mc_write_word(state, 33, 5);
|
||||
dib3000mc_set_adp_cfg(state, 1);
|
||||
dib3000mc_set_adp_cfg(state, QAM_16);
|
||||
dib3000mc_write_word(state, 133, 15564);
|
||||
|
||||
dib3000mc_write_word(state, 12 , 0x0);
|
||||
|
@ -470,52 +470,98 @@ static void dib3000mc_set_channel_cfg(struct dib3000mc_state *state, struct dibx
|
|||
dib3000mc_write_word(state, 97,0);
|
||||
dib3000mc_write_word(state, 98,0);
|
||||
|
||||
dib3000mc_set_impulse_noise(state, 0, chan->nfft);
|
||||
|
||||
tmp = ((chan->nfft & 0x1) << 7) | (chan->guard << 5) | (chan->nqam << 3) | chan->vit_alpha;
|
||||
dib3000mc_write_word(state, 0, tmp);
|
||||
dib3000mc_set_impulse_noise(state, 0, ch->u.ofdm.transmission_mode);
|
||||
|
||||
value = 0;
|
||||
switch (ch->u.ofdm.transmission_mode) {
|
||||
case TRANSMISSION_MODE_2K: value |= (0 << 7); break;
|
||||
default:
|
||||
case TRANSMISSION_MODE_8K: value |= (1 << 7); break;
|
||||
}
|
||||
switch (ch->u.ofdm.guard_interval) {
|
||||
case GUARD_INTERVAL_1_32: value |= (0 << 5); break;
|
||||
case GUARD_INTERVAL_1_16: value |= (1 << 5); break;
|
||||
case GUARD_INTERVAL_1_4: value |= (3 << 5); break;
|
||||
default:
|
||||
case GUARD_INTERVAL_1_8: value |= (2 << 5); break;
|
||||
}
|
||||
switch (ch->u.ofdm.constellation) {
|
||||
case QPSK: value |= (0 << 3); break;
|
||||
case QAM_16: value |= (1 << 3); break;
|
||||
default:
|
||||
case QAM_64: value |= (2 << 3); break;
|
||||
}
|
||||
switch (HIERARCHY_1) {
|
||||
case HIERARCHY_2: value |= 2; break;
|
||||
case HIERARCHY_4: value |= 4; break;
|
||||
default:
|
||||
case HIERARCHY_1: value |= 1; break;
|
||||
}
|
||||
dib3000mc_write_word(state, 0, value);
|
||||
dib3000mc_write_word(state, 5, (1 << 8) | ((seq & 0xf) << 4));
|
||||
|
||||
tmp = (chan->vit_hrch << 4) | (chan->vit_select_hp);
|
||||
if (!chan->vit_hrch || (chan->vit_hrch && chan->vit_select_hp))
|
||||
tmp |= chan->vit_code_rate_hp << 1;
|
||||
else
|
||||
tmp |= chan->vit_code_rate_lp << 1;
|
||||
dib3000mc_write_word(state, 181, tmp);
|
||||
value = 0;
|
||||
if (ch->u.ofdm.hierarchy_information == 1)
|
||||
value |= (1 << 4);
|
||||
if (1 == 1)
|
||||
value |= 1;
|
||||
switch ((ch->u.ofdm.hierarchy_information == 0 || 1 == 1) ? ch->u.ofdm.code_rate_HP : ch->u.ofdm.code_rate_LP) {
|
||||
case FEC_2_3: value |= (2 << 1); break;
|
||||
case FEC_3_4: value |= (3 << 1); break;
|
||||
case FEC_5_6: value |= (5 << 1); break;
|
||||
case FEC_7_8: value |= (7 << 1); break;
|
||||
default:
|
||||
case FEC_1_2: value |= (1 << 1); break;
|
||||
}
|
||||
dib3000mc_write_word(state, 181, value);
|
||||
|
||||
// diversity synchro delay
|
||||
tmp = dib3000mc_read_word(state, 180) & 0x000f;
|
||||
tmp |= ((chan->nfft == 0) ? 64 : 256) * ((1 << (chan->guard)) * 3 / 2) << 4; // add 50% SFN margin
|
||||
dib3000mc_write_word(state, 180, tmp);
|
||||
// diversity synchro delay add 50% SFN margin
|
||||
switch (ch->u.ofdm.transmission_mode) {
|
||||
case TRANSMISSION_MODE_8K: value = 256; break;
|
||||
case TRANSMISSION_MODE_2K:
|
||||
default: value = 64; break;
|
||||
}
|
||||
switch (ch->u.ofdm.guard_interval) {
|
||||
case GUARD_INTERVAL_1_16: value *= 2; break;
|
||||
case GUARD_INTERVAL_1_8: value *= 4; break;
|
||||
case GUARD_INTERVAL_1_4: value *= 8; break;
|
||||
default:
|
||||
case GUARD_INTERVAL_1_32: value *= 1; break;
|
||||
}
|
||||
value <<= 4;
|
||||
value |= dib3000mc_read_word(state, 180) & 0x000f;
|
||||
dib3000mc_write_word(state, 180, value);
|
||||
|
||||
// restart demod
|
||||
tmp = dib3000mc_read_word(state, 0);
|
||||
dib3000mc_write_word(state, 0, tmp | (1 << 9));
|
||||
dib3000mc_write_word(state, 0, tmp);
|
||||
value = dib3000mc_read_word(state, 0);
|
||||
dib3000mc_write_word(state, 0, value | (1 << 9));
|
||||
dib3000mc_write_word(state, 0, value);
|
||||
|
||||
msleep(30);
|
||||
|
||||
dib3000mc_set_impulse_noise(state, state->cfg->impulse_noise_mode, chan->nfft);
|
||||
dib3000mc_set_impulse_noise(state, state->cfg->impulse_noise_mode, ch->u.ofdm.transmission_mode);
|
||||
}
|
||||
|
||||
static int dib3000mc_autosearch_start(struct dvb_frontend *demod, struct dibx000_ofdm_channel *chan)
|
||||
static int dib3000mc_autosearch_start(struct dvb_frontend *demod, struct dvb_frontend_parameters *chan)
|
||||
{
|
||||
struct dib3000mc_state *state = demod->demodulator_priv;
|
||||
u16 reg;
|
||||
// u32 val;
|
||||
struct dibx000_ofdm_channel fchan;
|
||||
struct dvb_frontend_parameters schan;
|
||||
|
||||
INIT_OFDM_CHANNEL(&fchan);
|
||||
fchan = *chan;
|
||||
schan = *chan;
|
||||
|
||||
/* TODO what is that ? */
|
||||
|
||||
/* a channel for autosearch */
|
||||
fchan.nfft = 1; fchan.guard = 0; fchan.nqam = 2;
|
||||
fchan.vit_alpha = 1; fchan.vit_code_rate_hp = 2; fchan.vit_code_rate_lp = 2;
|
||||
fchan.vit_hrch = 0; fchan.vit_select_hp = 1;
|
||||
schan.u.ofdm.transmission_mode = TRANSMISSION_MODE_8K;
|
||||
schan.u.ofdm.guard_interval = GUARD_INTERVAL_1_32;
|
||||
schan.u.ofdm.constellation = QAM_64;
|
||||
schan.u.ofdm.code_rate_HP = FEC_2_3;
|
||||
schan.u.ofdm.code_rate_LP = FEC_2_3;
|
||||
schan.u.ofdm.hierarchy_information = 0;
|
||||
|
||||
dib3000mc_set_channel_cfg(state, &fchan, 11);
|
||||
dib3000mc_set_channel_cfg(state, &schan, 11);
|
||||
|
||||
reg = dib3000mc_read_word(state, 0);
|
||||
dib3000mc_write_word(state, 0, reg | (1 << 8));
|
||||
|
@ -539,7 +585,7 @@ static int dib3000mc_autosearch_is_irq(struct dvb_frontend *demod)
|
|||
return 0; // still pending
|
||||
}
|
||||
|
||||
static int dib3000mc_tune(struct dvb_frontend *demod, struct dibx000_ofdm_channel *ch)
|
||||
static int dib3000mc_tune(struct dvb_frontend *demod, struct dvb_frontend_parameters *ch)
|
||||
{
|
||||
struct dib3000mc_state *state = demod->demodulator_priv;
|
||||
|
||||
|
@ -547,11 +593,17 @@ static int dib3000mc_tune(struct dvb_frontend *demod, struct dibx000_ofdm_channe
|
|||
dib3000mc_set_channel_cfg(state, ch, 0);
|
||||
|
||||
// activates isi
|
||||
dib3000mc_write_word(state, 29, 0x1073);
|
||||
if (state->sfn_workaround_active) {
|
||||
dprintk("SFN workaround is active\n");
|
||||
dib3000mc_write_word(state, 29, 0x1273);
|
||||
dib3000mc_write_word(state, 108, 0x4000); // P_pha3_force_pha_shift
|
||||
} else {
|
||||
dib3000mc_write_word(state, 29, 0x1073);
|
||||
dib3000mc_write_word(state, 108, 0x0000); // P_pha3_force_pha_shift
|
||||
}
|
||||
|
||||
dib3000mc_set_adp_cfg(state, (u8)ch->nqam);
|
||||
|
||||
if (ch->nfft == 1) {
|
||||
dib3000mc_set_adp_cfg(state, (u8)ch->u.ofdm.constellation);
|
||||
if (ch->u.ofdm.transmission_mode == TRANSMISSION_MODE_8K) {
|
||||
dib3000mc_write_word(state, 26, 38528);
|
||||
dib3000mc_write_word(state, 33, 8);
|
||||
} else {
|
||||
|
@ -560,7 +612,7 @@ static int dib3000mc_tune(struct dvb_frontend *demod, struct dibx000_ofdm_channe
|
|||
}
|
||||
|
||||
if (dib3000mc_read_word(state, 509) & 0x80)
|
||||
dib3000mc_set_timing(state, ch->nfft, ch->Bw, 1);
|
||||
dib3000mc_set_timing(state, ch->u.ofdm.transmission_mode, BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth), 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -632,13 +684,12 @@ static int dib3000mc_set_frontend(struct dvb_frontend* fe,
|
|||
struct dvb_frontend_parameters *fep)
|
||||
{
|
||||
struct dib3000mc_state *state = fe->demodulator_priv;
|
||||
struct dibx000_ofdm_channel ch;
|
||||
|
||||
INIT_OFDM_CHANNEL(&ch);
|
||||
FEP2DIB(fep,&ch);
|
||||
|
||||
state->current_bandwidth = fep->u.ofdm.bandwidth;
|
||||
dib3000mc_set_bandwidth(fe, fep->u.ofdm.bandwidth);
|
||||
dib3000mc_set_bandwidth(state, BANDWIDTH_TO_KHZ(fep->u.ofdm.bandwidth));
|
||||
|
||||
/* maybe the parameter has been changed */
|
||||
state->sfn_workaround_active = buggy_sfn_workaround;
|
||||
|
||||
if (fe->ops.tuner_ops.set_params) {
|
||||
fe->ops.tuner_ops.set_params(fe, fep);
|
||||
|
@ -651,7 +702,7 @@ static int dib3000mc_set_frontend(struct dvb_frontend* fe,
|
|||
fep->u.ofdm.code_rate_HP == FEC_AUTO) {
|
||||
int i = 100, found;
|
||||
|
||||
dib3000mc_autosearch_start(fe, &ch);
|
||||
dib3000mc_autosearch_start(fe, fep);
|
||||
do {
|
||||
msleep(1);
|
||||
found = dib3000mc_autosearch_is_irq(fe);
|
||||
|
@ -662,13 +713,12 @@ static int dib3000mc_set_frontend(struct dvb_frontend* fe,
|
|||
return 0; // no channel found
|
||||
|
||||
dib3000mc_get_frontend(fe, fep);
|
||||
FEP2DIB(fep,&ch);
|
||||
}
|
||||
|
||||
/* make this a config parameter */
|
||||
dib3000mc_set_output_mode(state, OUTMODE_MPEG2_FIFO);
|
||||
|
||||
return dib3000mc_tune(fe, &ch);
|
||||
return dib3000mc_tune(fe, fep);
|
||||
}
|
||||
|
||||
static int dib3000mc_read_status(struct dvb_frontend *fe, fe_status_t *stat)
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -9,6 +9,7 @@ struct dib7000p_config {
|
|||
u8 tuner_is_baseband;
|
||||
int (*update_lna) (struct dvb_frontend *, u16 agc_global);
|
||||
|
||||
u8 agc_config_count;
|
||||
struct dibx000_agc_config *agc;
|
||||
struct dibx000_bandwidth_config *bw;
|
||||
|
||||
|
@ -27,20 +28,19 @@ struct dib7000p_config {
|
|||
|
||||
u8 quartz_direct;
|
||||
|
||||
u8 spur_protect;
|
||||
|
||||
int (*agc_control) (struct dvb_frontend *, u8 before);
|
||||
};
|
||||
|
||||
#define DEFAULT_DIB7000P_I2C_ADDRESS 18
|
||||
|
||||
extern struct dvb_frontend * dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg);
|
||||
extern int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000p_config cfg[]);
|
||||
|
||||
extern struct i2c_adapter * dib7000p_get_i2c_master(struct dvb_frontend *, enum dibx000_i2c_interface, int);
|
||||
extern int dib7000pc_detection(struct i2c_adapter *i2c_adap);
|
||||
|
||||
/* TODO
|
||||
extern INT dib7000p_set_gpio(struct dibDemod *demod, UCHAR num, UCHAR dir, UCHAR val);
|
||||
extern INT dib7000p_enable_vbg_voltage(struct dibDemod *demod);
|
||||
extern void dib7000p_set_hostbus_diversity(struct dibDemod *demod, UCHAR onoff);
|
||||
extern USHORT dib7000p_get_current_agc_global(struct dibDemod *demod);
|
||||
*/
|
||||
extern int dib7000p_set_gpio(struct dvb_frontend *, u8 num, u8 dir, u8 val);
|
||||
extern int dib7000p_set_wbd_ref(struct dvb_frontend *, u16 value);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -111,6 +111,8 @@ struct dibx000_bandwidth_config {
|
|||
|
||||
u32 ifreq;
|
||||
u32 timf;
|
||||
|
||||
u32 xtal_hz;
|
||||
};
|
||||
|
||||
enum dibx000_adc_states {
|
||||
|
@ -122,56 +124,17 @@ enum dibx000_adc_states {
|
|||
DIBX000_VBG_DISABLE,
|
||||
};
|
||||
|
||||
#define BW_INDEX_TO_KHZ(v) ( (v) == BANDWIDTH_8_MHZ ? 8000 : \
|
||||
#define BANDWIDTH_TO_KHZ(v) ( (v) == BANDWIDTH_8_MHZ ? 8000 : \
|
||||
(v) == BANDWIDTH_7_MHZ ? 7000 : \
|
||||
(v) == BANDWIDTH_6_MHZ ? 6000 : 8000 )
|
||||
|
||||
/* Chip output mode. */
|
||||
#define OUTMODE_HIGH_Z 0
|
||||
#define OUTMODE_MPEG2_PAR_GATED_CLK 1
|
||||
#define OUTMODE_MPEG2_PAR_CONT_CLK 2
|
||||
#define OUTMODE_MPEG2_SERIAL 7
|
||||
#define OUTMODE_DIVERSITY 4
|
||||
#define OUTMODE_MPEG2_FIFO 5
|
||||
|
||||
/* I hope I can get rid of the following kludge in the near future */
|
||||
struct dibx000_ofdm_channel {
|
||||
u32 RF_kHz;
|
||||
u8 Bw;
|
||||
s16 nfft;
|
||||
s16 guard;
|
||||
s16 nqam;
|
||||
s16 vit_hrch;
|
||||
s16 vit_select_hp;
|
||||
s16 vit_alpha;
|
||||
s16 vit_code_rate_hp;
|
||||
s16 vit_code_rate_lp;
|
||||
u8 intlv_native;
|
||||
};
|
||||
|
||||
#define FEP2DIB(fep,ch) \
|
||||
(ch)->RF_kHz = (fep)->frequency / 1000; \
|
||||
(ch)->Bw = (fep)->u.ofdm.bandwidth; \
|
||||
(ch)->nfft = (fep)->u.ofdm.transmission_mode == TRANSMISSION_MODE_AUTO ? -1 : (fep)->u.ofdm.transmission_mode; \
|
||||
(ch)->guard = (fep)->u.ofdm.guard_interval == GUARD_INTERVAL_AUTO ? -1 : (fep)->u.ofdm.guard_interval; \
|
||||
(ch)->nqam = (fep)->u.ofdm.constellation == QAM_AUTO ? -1 : (fep)->u.ofdm.constellation == QAM_64 ? 2 : (fep)->u.ofdm.constellation; \
|
||||
(ch)->vit_hrch = 0; /* linux-dvb is not prepared for HIERARCHICAL TRANSMISSION */ \
|
||||
(ch)->vit_select_hp = 1; \
|
||||
(ch)->vit_alpha = 1; \
|
||||
(ch)->vit_code_rate_hp = (fep)->u.ofdm.code_rate_HP == FEC_AUTO ? -1 : (fep)->u.ofdm.code_rate_HP; \
|
||||
(ch)->vit_code_rate_lp = (fep)->u.ofdm.code_rate_LP == FEC_AUTO ? -1 : (fep)->u.ofdm.code_rate_LP; \
|
||||
(ch)->intlv_native = 1;
|
||||
|
||||
#define INIT_OFDM_CHANNEL(ch) do {\
|
||||
(ch)->Bw = 0; \
|
||||
(ch)->nfft = -1; \
|
||||
(ch)->guard = -1; \
|
||||
(ch)->nqam = -1; \
|
||||
(ch)->vit_hrch = -1; \
|
||||
(ch)->vit_select_hp = -1; \
|
||||
(ch)->vit_alpha = -1; \
|
||||
(ch)->vit_code_rate_hp = -1; \
|
||||
(ch)->vit_code_rate_lp = -1; \
|
||||
} while (0)
|
||||
#define OUTMODE_HIGH_Z 0
|
||||
#define OUTMODE_MPEG2_PAR_GATED_CLK 1
|
||||
#define OUTMODE_MPEG2_PAR_CONT_CLK 2
|
||||
#define OUTMODE_MPEG2_SERIAL 7
|
||||
#define OUTMODE_DIVERSITY 4
|
||||
#define OUTMODE_MPEG2_FIFO 5
|
||||
#define OUTMODE_ANALOG_ADC 6
|
||||
|
||||
#endif
|
||||
|
|
|
@ -24,12 +24,48 @@
|
|||
|
||||
#include "dvb-pll.h"
|
||||
|
||||
struct dvb_pll_priv {
|
||||
/* pll number */
|
||||
int nr;
|
||||
|
||||
/* i2c details */
|
||||
int pll_i2c_address;
|
||||
struct i2c_adapter *i2c;
|
||||
|
||||
/* the PLL descriptor */
|
||||
struct dvb_pll_desc *pll_desc;
|
||||
|
||||
/* cached frequency/bandwidth */
|
||||
u32 frequency;
|
||||
u32 bandwidth;
|
||||
};
|
||||
|
||||
#define DVB_PLL_MAX 64
|
||||
|
||||
static unsigned int dvb_pll_devcount;
|
||||
|
||||
static int debug = 0;
|
||||
module_param(debug, int, 0644);
|
||||
MODULE_PARM_DESC(debug, "enable verbose debug messages");
|
||||
|
||||
static unsigned int input[DVB_PLL_MAX] = { [ 0 ... (DVB_PLL_MAX-1) ] = 0 };
|
||||
module_param_array(input, int, NULL, 0644);
|
||||
MODULE_PARM_DESC(input,"specify rf input choice, 0 for autoselect (default)");
|
||||
|
||||
static unsigned int id[DVB_PLL_MAX] =
|
||||
{ [ 0 ... (DVB_PLL_MAX-1) ] = DVB_PLL_UNDEFINED };
|
||||
module_param_array(id, int, NULL, 0644);
|
||||
MODULE_PARM_DESC(id, "force pll id to use (DEBUG ONLY)");
|
||||
|
||||
/* ----------------------------------------------------------- */
|
||||
|
||||
struct dvb_pll_desc {
|
||||
char *name;
|
||||
u32 min;
|
||||
u32 max;
|
||||
u32 iffreq;
|
||||
void (*set)(u8 *buf, const struct dvb_frontend_parameters *params);
|
||||
void (*set)(struct dvb_frontend *fe, u8 *buf,
|
||||
const struct dvb_frontend_parameters *params);
|
||||
u8 *initdata;
|
||||
u8 *sleepdata;
|
||||
int count;
|
||||
|
@ -89,7 +125,7 @@ static struct dvb_pll_desc dvb_pll_thomson_dtt7610 = {
|
|||
},
|
||||
};
|
||||
|
||||
static void thomson_dtt759x_bw(u8 *buf,
|
||||
static void thomson_dtt759x_bw(struct dvb_frontend *fe, u8 *buf,
|
||||
const struct dvb_frontend_parameters *params)
|
||||
{
|
||||
if (BANDWIDTH_7_MHZ == params->u.ofdm.bandwidth)
|
||||
|
@ -210,7 +246,8 @@ static struct dvb_pll_desc dvb_pll_env57h1xd5 = {
|
|||
/* Philips TDA6650/TDA6651
|
||||
* used in Panasonic ENV77H11D5
|
||||
*/
|
||||
static void tda665x_bw(u8 *buf, const struct dvb_frontend_parameters *params)
|
||||
static void tda665x_bw(struct dvb_frontend *fe, u8 *buf,
|
||||
const struct dvb_frontend_parameters *params)
|
||||
{
|
||||
if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ)
|
||||
buf[3] |= 0x08;
|
||||
|
@ -243,7 +280,8 @@ static struct dvb_pll_desc dvb_pll_tda665x = {
|
|||
/* Infineon TUA6034
|
||||
* used in LG TDTP E102P
|
||||
*/
|
||||
static void tua6034_bw(u8 *buf, const struct dvb_frontend_parameters *params)
|
||||
static void tua6034_bw(struct dvb_frontend *fe, u8 *buf,
|
||||
const struct dvb_frontend_parameters *params)
|
||||
{
|
||||
if (BANDWIDTH_7_MHZ != params->u.ofdm.bandwidth)
|
||||
buf[3] |= 0x08;
|
||||
|
@ -283,7 +321,8 @@ static struct dvb_pll_desc dvb_pll_lg_tdvs_h06xf = {
|
|||
/* Philips FMD1216ME
|
||||
* used in Medion Hybrid PCMCIA card and USB Box
|
||||
*/
|
||||
static void fmd1216me_bw(u8 *buf, const struct dvb_frontend_parameters *params)
|
||||
static void fmd1216me_bw(struct dvb_frontend *fe, u8 *buf,
|
||||
const struct dvb_frontend_parameters *params)
|
||||
{
|
||||
if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ &&
|
||||
params->frequency >= 158870000)
|
||||
|
@ -313,7 +352,8 @@ static struct dvb_pll_desc dvb_pll_fmd1216me = {
|
|||
/* ALPS TDED4
|
||||
* used in Nebula-Cards and USB boxes
|
||||
*/
|
||||
static void tded4_bw(u8 *buf, const struct dvb_frontend_parameters *params)
|
||||
static void tded4_bw(struct dvb_frontend *fe, u8 *buf,
|
||||
const struct dvb_frontend_parameters *params)
|
||||
{
|
||||
if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ)
|
||||
buf[3] |= 0x04;
|
||||
|
@ -354,16 +394,35 @@ static struct dvb_pll_desc dvb_pll_tdhu2 = {
|
|||
/* Philips TUV1236D
|
||||
* used in ATI HDTV Wonder
|
||||
*/
|
||||
static void tuv1236d_rf(u8 *buf, const struct dvb_frontend_parameters *params)
|
||||
static void tuv1236d_rf(struct dvb_frontend *fe, u8 *buf,
|
||||
const struct dvb_frontend_parameters *params)
|
||||
{
|
||||
switch (params->u.vsb.modulation) {
|
||||
case QAM_64:
|
||||
case QAM_256:
|
||||
struct dvb_pll_priv *priv = fe->tuner_priv;
|
||||
unsigned int new_rf = input[priv->nr];
|
||||
|
||||
if ((new_rf == 0) || (new_rf > 2)) {
|
||||
switch (params->u.vsb.modulation) {
|
||||
case QAM_64:
|
||||
case QAM_256:
|
||||
new_rf = 1;
|
||||
break;
|
||||
case VSB_8:
|
||||
default:
|
||||
new_rf = 2;
|
||||
}
|
||||
}
|
||||
|
||||
switch (new_rf) {
|
||||
case 1:
|
||||
buf[3] |= 0x08;
|
||||
break;
|
||||
case VSB_8:
|
||||
default:
|
||||
case 2:
|
||||
buf[3] &= ~0x08;
|
||||
break;
|
||||
default:
|
||||
printk(KERN_WARNING
|
||||
"%s: unhandled rf input selection: %d",
|
||||
__FUNCTION__, new_rf);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -420,7 +479,8 @@ static struct dvb_pll_desc dvb_pll_philips_sd1878_tda8261 = {
|
|||
/*
|
||||
* Philips TD1316 Tuner.
|
||||
*/
|
||||
static void td1316_bw(u8 *buf, const struct dvb_frontend_parameters *params)
|
||||
static void td1316_bw(struct dvb_frontend *fe, u8 *buf,
|
||||
const struct dvb_frontend_parameters *params)
|
||||
{
|
||||
u8 band;
|
||||
|
||||
|
@ -474,7 +534,8 @@ static struct dvb_pll_desc dvb_pll_thomson_fe6600 = {
|
|||
}
|
||||
};
|
||||
|
||||
static void opera1_bw(u8 *buf, const struct dvb_frontend_parameters *params)
|
||||
static void opera1_bw(struct dvb_frontend *fe, u8 *buf,
|
||||
const struct dvb_frontend_parameters *params)
|
||||
{
|
||||
if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ)
|
||||
buf[2] |= 0x08;
|
||||
|
@ -545,31 +606,14 @@ static struct dvb_pll_desc *pll_list[] = {
|
|||
[DVB_PLL_FCV1236D] = &dvb_pll_fcv1236d,
|
||||
};
|
||||
|
||||
/* ----------------------------------------------------------- */
|
||||
|
||||
struct dvb_pll_priv {
|
||||
/* i2c details */
|
||||
int pll_i2c_address;
|
||||
struct i2c_adapter *i2c;
|
||||
|
||||
/* the PLL descriptor */
|
||||
struct dvb_pll_desc *pll_desc;
|
||||
|
||||
/* cached frequency/bandwidth */
|
||||
u32 frequency;
|
||||
u32 bandwidth;
|
||||
};
|
||||
|
||||
/* ----------------------------------------------------------- */
|
||||
/* code */
|
||||
|
||||
static int debug = 0;
|
||||
module_param(debug, int, 0644);
|
||||
MODULE_PARM_DESC(debug, "enable verbose debug messages");
|
||||
|
||||
static int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf,
|
||||
static int dvb_pll_configure(struct dvb_frontend *fe, u8 *buf,
|
||||
const struct dvb_frontend_parameters *params)
|
||||
{
|
||||
struct dvb_pll_priv *priv = fe->tuner_priv;
|
||||
struct dvb_pll_desc *desc = priv->pll_desc;
|
||||
u32 div;
|
||||
int i;
|
||||
|
||||
|
@ -597,7 +641,7 @@ static int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf,
|
|||
buf[3] = desc->entries[i].cb;
|
||||
|
||||
if (desc->set)
|
||||
desc->set(buf, params);
|
||||
desc->set(fe, buf, params);
|
||||
|
||||
if (debug)
|
||||
printk("pll: %s: div=%d | buf=0x%02x,0x%02x,0x%02x,0x%02x\n",
|
||||
|
@ -654,7 +698,7 @@ static int dvb_pll_set_params(struct dvb_frontend *fe,
|
|||
if (priv->i2c == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
if ((result = dvb_pll_configure(priv->pll_desc, buf, params)) < 0)
|
||||
if ((result = dvb_pll_configure(fe, buf, params)) < 0)
|
||||
return result;
|
||||
else
|
||||
frequency = result;
|
||||
|
@ -682,7 +726,7 @@ static int dvb_pll_calc_regs(struct dvb_frontend *fe,
|
|||
if (buf_len < 5)
|
||||
return -EINVAL;
|
||||
|
||||
if ((result = dvb_pll_configure(priv->pll_desc, buf+1, params)) < 0)
|
||||
if ((result = dvb_pll_configure(fe, buf+1, params)) < 0)
|
||||
return result;
|
||||
else
|
||||
frequency = result;
|
||||
|
@ -755,6 +799,10 @@ struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr,
|
|||
int ret;
|
||||
struct dvb_pll_desc *desc;
|
||||
|
||||
if ((id[dvb_pll_devcount] > DVB_PLL_UNDEFINED) &&
|
||||
(id[dvb_pll_devcount] < ARRAY_SIZE(pll_list)))
|
||||
pll_desc_id = id[dvb_pll_devcount];
|
||||
|
||||
BUG_ON(pll_desc_id < 1 || pll_desc_id >= ARRAY_SIZE(pll_list));
|
||||
|
||||
desc = pll_list[pll_desc_id];
|
||||
|
@ -777,6 +825,7 @@ struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr,
|
|||
priv->pll_i2c_address = pll_addr;
|
||||
priv->i2c = i2c;
|
||||
priv->pll_desc = desc;
|
||||
priv->nr = dvb_pll_devcount++;
|
||||
|
||||
memcpy(&fe->ops.tuner_ops, &dvb_pll_tuner_ops,
|
||||
sizeof(struct dvb_tuner_ops));
|
||||
|
@ -791,6 +840,30 @@ struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr,
|
|||
fe->ops.tuner_ops.sleep = NULL;
|
||||
|
||||
fe->tuner_priv = priv;
|
||||
|
||||
if ((debug) || (id[priv->nr] == pll_desc_id)) {
|
||||
printk("dvb-pll[%d]", priv->nr);
|
||||
if (i2c != NULL)
|
||||
printk(" %d-%04x", i2c_adapter_id(i2c), pll_addr);
|
||||
printk(": id# %d (%s) attached, %s\n", pll_desc_id, desc->name,
|
||||
id[priv->nr] == pll_desc_id ?
|
||||
"insmod option" : "autodetected");
|
||||
}
|
||||
if ((debug) || (input[priv->nr] > 0)) {
|
||||
printk("dvb-pll[%d]", priv->nr);
|
||||
if (i2c != NULL)
|
||||
printk(" %d-%04x", i2c_adapter_id(i2c), pll_addr);
|
||||
printk(": tuner rf input will be ");
|
||||
switch (input[priv->nr]) {
|
||||
case 0:
|
||||
printk("autoselected\n");
|
||||
break;
|
||||
default:
|
||||
printk("set to input %d (insmod option)\n",
|
||||
input[priv->nr]);
|
||||
}
|
||||
}
|
||||
|
||||
return fe;
|
||||
}
|
||||
EXPORT_SYMBOL(dvb_pll_attach);
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/slab.h>
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/slab.h>
|
||||
#include "dvb_frontend.h"
|
||||
|
|
|
@ -35,7 +35,6 @@
|
|||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/string.h>
|
||||
|
|
|
@ -28,7 +28,6 @@
|
|||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
/* In that file, frequencies are expressed in kiloHertz to avoid 32 bits overflows */
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/dvb/frontend.h>
|
||||
#include <linux/i2c.h>
|
||||
|
|
|
@ -0,0 +1,314 @@
|
|||
/*
|
||||
* Driver for Microtune MT2131 "QAM/8VSB single chip tuner"
|
||||
*
|
||||
* Copyright (c) 2006 Steven Toth <stoth@hauppauge.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
*
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/dvb/frontend.h>
|
||||
#include <linux/i2c.h>
|
||||
|
||||
#include "dvb_frontend.h"
|
||||
|
||||
#include "mt2131.h"
|
||||
#include "mt2131_priv.h"
|
||||
|
||||
static int debug;
|
||||
module_param(debug, int, 0644);
|
||||
MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
|
||||
|
||||
#define dprintk(level,fmt, arg...) if (debug >= level) \
|
||||
printk(KERN_INFO "%s: " fmt, "mt2131", ## arg)
|
||||
|
||||
static u8 mt2131_config1[] = {
|
||||
0x01,
|
||||
0x50, 0x00, 0x50, 0x80, 0x00, 0x49, 0xfa, 0x88,
|
||||
0x08, 0x77, 0x41, 0x04, 0x00, 0x00, 0x00, 0x32,
|
||||
0x7f, 0xda, 0x4c, 0x00, 0x10, 0xaa, 0x78, 0x80,
|
||||
0xff, 0x68, 0xa0, 0xff, 0xdd, 0x00, 0x00
|
||||
};
|
||||
|
||||
static u8 mt2131_config2[] = {
|
||||
0x10,
|
||||
0x7f, 0xc8, 0x0a, 0x5f, 0x00, 0x04
|
||||
};
|
||||
|
||||
static int mt2131_readreg(struct mt2131_priv *priv, u8 reg, u8 *val)
|
||||
{
|
||||
struct i2c_msg msg[2] = {
|
||||
{ .addr = priv->cfg->i2c_address, .flags = 0,
|
||||
.buf = ®, .len = 1 },
|
||||
{ .addr = priv->cfg->i2c_address, .flags = I2C_M_RD,
|
||||
.buf = val, .len = 1 },
|
||||
};
|
||||
|
||||
if (i2c_transfer(priv->i2c, msg, 2) != 2) {
|
||||
printk(KERN_WARNING "mt2131 I2C read failed\n");
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mt2131_writereg(struct mt2131_priv *priv, u8 reg, u8 val)
|
||||
{
|
||||
u8 buf[2] = { reg, val };
|
||||
struct i2c_msg msg = { .addr = priv->cfg->i2c_address, .flags = 0,
|
||||
.buf = buf, .len = 2 };
|
||||
|
||||
if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
|
||||
printk(KERN_WARNING "mt2131 I2C write failed\n");
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mt2131_writeregs(struct mt2131_priv *priv,u8 *buf, u8 len)
|
||||
{
|
||||
struct i2c_msg msg = { .addr = priv->cfg->i2c_address,
|
||||
.flags = 0, .buf = buf, .len = len };
|
||||
|
||||
if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
|
||||
printk(KERN_WARNING "mt2131 I2C write failed (len=%i)\n",
|
||||
(int)len);
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mt2131_set_params(struct dvb_frontend *fe,
|
||||
struct dvb_frontend_parameters *params)
|
||||
{
|
||||
struct mt2131_priv *priv;
|
||||
int ret=0, i;
|
||||
u32 freq;
|
||||
u8 if_band_center;
|
||||
u32 f_lo1, f_lo2;
|
||||
u32 div1, num1, div2, num2;
|
||||
u8 b[8];
|
||||
u8 lockval = 0;
|
||||
|
||||
priv = fe->tuner_priv;
|
||||
if (fe->ops.info.type == FE_OFDM)
|
||||
priv->bandwidth = params->u.ofdm.bandwidth;
|
||||
else
|
||||
priv->bandwidth = 0;
|
||||
|
||||
freq = params->frequency / 1000; // Hz -> kHz
|
||||
dprintk(1, "%s() freq=%d\n", __FUNCTION__, freq);
|
||||
|
||||
f_lo1 = freq + MT2131_IF1 * 1000;
|
||||
f_lo1 = (f_lo1 / 250) * 250;
|
||||
f_lo2 = f_lo1 - freq - MT2131_IF2;
|
||||
|
||||
priv->frequency = (f_lo1 - f_lo2 - MT2131_IF2) * 1000,
|
||||
|
||||
/* Frequency LO1 = 16MHz * (DIV1 + NUM1/8192 ) */
|
||||
num1 = f_lo1 * 64 / (MT2131_FREF / 128);
|
||||
div1 = num1 / 8192;
|
||||
num1 &= 0x1fff;
|
||||
|
||||
/* Frequency LO2 = 16MHz * (DIV2 + NUM2/8192 ) */
|
||||
num2 = f_lo2 * 64 / (MT2131_FREF / 128);
|
||||
div2 = num2 / 8192;
|
||||
num2 &= 0x1fff;
|
||||
|
||||
if (freq <= 82500) if_band_center = 0x00; else
|
||||
if (freq <= 137500) if_band_center = 0x01; else
|
||||
if (freq <= 192500) if_band_center = 0x02; else
|
||||
if (freq <= 247500) if_band_center = 0x03; else
|
||||
if (freq <= 302500) if_band_center = 0x04; else
|
||||
if (freq <= 357500) if_band_center = 0x05; else
|
||||
if (freq <= 412500) if_band_center = 0x06; else
|
||||
if (freq <= 467500) if_band_center = 0x07; else
|
||||
if (freq <= 522500) if_band_center = 0x08; else
|
||||
if (freq <= 577500) if_band_center = 0x09; else
|
||||
if (freq <= 632500) if_band_center = 0x0A; else
|
||||
if (freq <= 687500) if_band_center = 0x0B; else
|
||||
if (freq <= 742500) if_band_center = 0x0C; else
|
||||
if (freq <= 797500) if_band_center = 0x0D; else
|
||||
if (freq <= 852500) if_band_center = 0x0E; else
|
||||
if (freq <= 907500) if_band_center = 0x0F; else
|
||||
if (freq <= 962500) if_band_center = 0x10; else
|
||||
if (freq <= 1017500) if_band_center = 0x11; else
|
||||
if (freq <= 1072500) if_band_center = 0x12; else if_band_center = 0x13;
|
||||
|
||||
b[0] = 1;
|
||||
b[1] = (num1 >> 5) & 0xFF;
|
||||
b[2] = (num1 & 0x1F);
|
||||
b[3] = div1;
|
||||
b[4] = (num2 >> 5) & 0xFF;
|
||||
b[5] = num2 & 0x1F;
|
||||
b[6] = div2;
|
||||
|
||||
dprintk(1, "IF1: %dMHz IF2: %dMHz\n", MT2131_IF1, MT2131_IF2);
|
||||
dprintk(1, "PLL freq=%dkHz band=%d\n", (int)freq, (int)if_band_center);
|
||||
dprintk(1, "PLL f_lo1=%dkHz f_lo2=%dkHz\n", (int)f_lo1, (int)f_lo2);
|
||||
dprintk(1, "PLL div1=%d num1=%d div2=%d num2=%d\n",
|
||||
(int)div1, (int)num1, (int)div2, (int)num2);
|
||||
dprintk(1, "PLL [1..6]: %2x %2x %2x %2x %2x %2x\n",
|
||||
(int)b[1], (int)b[2], (int)b[3], (int)b[4], (int)b[5],
|
||||
(int)b[6]);
|
||||
|
||||
ret = mt2131_writeregs(priv,b,7);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
mt2131_writereg(priv, 0x0b, if_band_center);
|
||||
|
||||
/* Wait for lock */
|
||||
i = 0;
|
||||
do {
|
||||
mt2131_readreg(priv, 0x08, &lockval);
|
||||
if ((lockval & 0x88) == 0x88)
|
||||
break;
|
||||
msleep(4);
|
||||
i++;
|
||||
} while (i < 10);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mt2131_get_frequency(struct dvb_frontend *fe, u32 *frequency)
|
||||
{
|
||||
struct mt2131_priv *priv = fe->tuner_priv;
|
||||
dprintk(1, "%s()\n", __FUNCTION__);
|
||||
*frequency = priv->frequency;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mt2131_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
|
||||
{
|
||||
struct mt2131_priv *priv = fe->tuner_priv;
|
||||
dprintk(1, "%s()\n", __FUNCTION__);
|
||||
*bandwidth = priv->bandwidth;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mt2131_get_status(struct dvb_frontend *fe, u32 *status)
|
||||
{
|
||||
struct mt2131_priv *priv = fe->tuner_priv;
|
||||
u8 lock_status = 0;
|
||||
u8 afc_status = 0;
|
||||
|
||||
*status = 0;
|
||||
|
||||
mt2131_readreg(priv, 0x08, &lock_status);
|
||||
if ((lock_status & 0x88) == 0x88)
|
||||
*status = TUNER_STATUS_LOCKED;
|
||||
|
||||
mt2131_readreg(priv, 0x09, &afc_status);
|
||||
dprintk(1, "%s() - LO Status = 0x%x, AFC Status = 0x%x\n",
|
||||
__FUNCTION__, lock_status, afc_status);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mt2131_init(struct dvb_frontend *fe)
|
||||
{
|
||||
struct mt2131_priv *priv = fe->tuner_priv;
|
||||
int ret;
|
||||
dprintk(1, "%s()\n", __FUNCTION__);
|
||||
|
||||
if ((ret = mt2131_writeregs(priv, mt2131_config1,
|
||||
sizeof(mt2131_config1))) < 0)
|
||||
return ret;
|
||||
|
||||
mt2131_writereg(priv, 0x0b, 0x09);
|
||||
mt2131_writereg(priv, 0x15, 0x47);
|
||||
mt2131_writereg(priv, 0x07, 0xf2);
|
||||
mt2131_writereg(priv, 0x0b, 0x01);
|
||||
|
||||
if ((ret = mt2131_writeregs(priv, mt2131_config2,
|
||||
sizeof(mt2131_config2))) < 0)
|
||||
return ret;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mt2131_release(struct dvb_frontend *fe)
|
||||
{
|
||||
dprintk(1, "%s()\n", __FUNCTION__);
|
||||
kfree(fe->tuner_priv);
|
||||
fe->tuner_priv = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dvb_tuner_ops mt2131_tuner_ops = {
|
||||
.info = {
|
||||
.name = "Microtune MT2131",
|
||||
.frequency_min = 48000000,
|
||||
.frequency_max = 860000000,
|
||||
.frequency_step = 50000,
|
||||
},
|
||||
|
||||
.release = mt2131_release,
|
||||
.init = mt2131_init,
|
||||
|
||||
.set_params = mt2131_set_params,
|
||||
.get_frequency = mt2131_get_frequency,
|
||||
.get_bandwidth = mt2131_get_bandwidth,
|
||||
.get_status = mt2131_get_status
|
||||
};
|
||||
|
||||
struct dvb_frontend * mt2131_attach(struct dvb_frontend *fe,
|
||||
struct i2c_adapter *i2c,
|
||||
struct mt2131_config *cfg, u16 if1)
|
||||
{
|
||||
struct mt2131_priv *priv = NULL;
|
||||
u8 id = 0;
|
||||
|
||||
dprintk(1, "%s()\n", __FUNCTION__);
|
||||
|
||||
priv = kzalloc(sizeof(struct mt2131_priv), GFP_KERNEL);
|
||||
if (priv == NULL)
|
||||
return NULL;
|
||||
|
||||
priv->cfg = cfg;
|
||||
priv->bandwidth = 6000000; /* 6MHz */
|
||||
priv->i2c = i2c;
|
||||
|
||||
if (mt2131_readreg(priv, 0, &id) != 0) {
|
||||
kfree(priv);
|
||||
return NULL;
|
||||
}
|
||||
if ( (id != 0x3E) && (id != 0x3F) ) {
|
||||
printk(KERN_ERR "MT2131: Device not found at addr 0x%02x\n",
|
||||
cfg->i2c_address);
|
||||
kfree(priv);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
printk(KERN_INFO "MT2131: successfully identified at address 0x%02x\n",
|
||||
cfg->i2c_address);
|
||||
memcpy(&fe->ops.tuner_ops, &mt2131_tuner_ops,
|
||||
sizeof(struct dvb_tuner_ops));
|
||||
|
||||
fe->tuner_priv = priv;
|
||||
return fe;
|
||||
}
|
||||
EXPORT_SYMBOL(mt2131_attach);
|
||||
|
||||
MODULE_AUTHOR("Steven Toth");
|
||||
MODULE_DESCRIPTION("Microtune MT2131 silicon tuner driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* c-basic-offset: 8
|
||||
*/
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* Driver for Microtune MT2131 "QAM/8VSB single chip tuner"
|
||||
*
|
||||
* Copyright (c) 2006 Steven Toth <stoth@hauppauge.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
*
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef __MT2131_H__
|
||||
#define __MT2131_H__
|
||||
|
||||
struct dvb_frontend;
|
||||
struct i2c_adapter;
|
||||
|
||||
struct mt2131_config {
|
||||
u8 i2c_address;
|
||||
u8 clock_out; /* 0 = off, 1 = CLK/4, 2 = CLK/2, 3 = CLK/1 */
|
||||
};
|
||||
|
||||
#if defined(CONFIG_DVB_TUNER_MT2131) || (defined(CONFIG_DVB_TUNER_MT2131_MODULE) && defined(MODULE))
|
||||
extern struct dvb_frontend* mt2131_attach(struct dvb_frontend *fe,
|
||||
struct i2c_adapter *i2c,
|
||||
struct mt2131_config *cfg,
|
||||
u16 if1);
|
||||
#else
|
||||
static inline struct dvb_frontend* mt2131_attach(struct dvb_frontend *fe,
|
||||
struct i2c_adapter *i2c,
|
||||
struct mt2131_config *cfg,
|
||||
u16 if1)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
#endif /* CONFIG_DVB_TUNER_MT2131 */
|
||||
|
||||
#endif /* __MT2131_H__ */
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* c-basic-offset: 8
|
||||
*/
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Driver for Microtune MT2131 "QAM/8VSB single chip tuner"
|
||||
*
|
||||
* Copyright (c) 2006 Steven Toth <stoth@hauppauge.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
*
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef __MT2131_PRIV_H__
|
||||
#define __MT2131_PRIV_H__
|
||||
|
||||
/* Regs */
|
||||
#define MT2131_PWR 0x07
|
||||
#define MT2131_UPC_1 0x0b
|
||||
#define MT2131_AGC_RL 0x10
|
||||
#define MT2131_MISC_2 0x15
|
||||
|
||||
/* frequency values in KHz */
|
||||
#define MT2131_IF1 1220
|
||||
#define MT2131_IF2 44000
|
||||
#define MT2131_FREF 16000
|
||||
|
||||
struct mt2131_priv {
|
||||
struct mt2131_config *cfg;
|
||||
struct i2c_adapter *i2c;
|
||||
|
||||
u32 frequency;
|
||||
u32 bandwidth;
|
||||
};
|
||||
|
||||
#endif /* __MT2131_PRIV_H__ */
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* c-basic-offset: 8
|
||||
*/
|
|
@ -0,0 +1,287 @@
|
|||
/*
|
||||
* Driver for Microtune MT2266 "Direct conversion low power broadband tuner"
|
||||
*
|
||||
* Copyright (c) 2007 Olivier DANET <odanet@caramail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/dvb/frontend.h>
|
||||
#include <linux/i2c.h>
|
||||
|
||||
#include "dvb_frontend.h"
|
||||
#include "mt2266.h"
|
||||
|
||||
#define I2C_ADDRESS 0x60
|
||||
|
||||
#define REG_PART_REV 0
|
||||
#define REG_TUNE 1
|
||||
#define REG_BAND 6
|
||||
#define REG_BANDWIDTH 8
|
||||
#define REG_LOCK 0x12
|
||||
|
||||
#define PART_REV 0x85
|
||||
|
||||
struct mt2266_priv {
|
||||
struct mt2266_config *cfg;
|
||||
struct i2c_adapter *i2c;
|
||||
|
||||
u32 frequency;
|
||||
u32 bandwidth;
|
||||
};
|
||||
|
||||
/* Here, frequencies are expressed in kiloHertz to avoid 32 bits overflows */
|
||||
|
||||
static int debug;
|
||||
module_param(debug, int, 0644);
|
||||
MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
|
||||
|
||||
#define dprintk(args...) do { if (debug) {printk(KERN_DEBUG "MT2266: " args); printk("\n"); }} while (0)
|
||||
|
||||
// Reads a single register
|
||||
static int mt2266_readreg(struct mt2266_priv *priv, u8 reg, u8 *val)
|
||||
{
|
||||
struct i2c_msg msg[2] = {
|
||||
{ .addr = priv->cfg->i2c_address, .flags = 0, .buf = ®, .len = 1 },
|
||||
{ .addr = priv->cfg->i2c_address, .flags = I2C_M_RD, .buf = val, .len = 1 },
|
||||
};
|
||||
if (i2c_transfer(priv->i2c, msg, 2) != 2) {
|
||||
printk(KERN_WARNING "MT2266 I2C read failed\n");
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Writes a single register
|
||||
static int mt2266_writereg(struct mt2266_priv *priv, u8 reg, u8 val)
|
||||
{
|
||||
u8 buf[2] = { reg, val };
|
||||
struct i2c_msg msg = {
|
||||
.addr = priv->cfg->i2c_address, .flags = 0, .buf = buf, .len = 2
|
||||
};
|
||||
if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
|
||||
printk(KERN_WARNING "MT2266 I2C write failed\n");
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Writes a set of consecutive registers
|
||||
static int mt2266_writeregs(struct mt2266_priv *priv,u8 *buf, u8 len)
|
||||
{
|
||||
struct i2c_msg msg = {
|
||||
.addr = priv->cfg->i2c_address, .flags = 0, .buf = buf, .len = len
|
||||
};
|
||||
if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
|
||||
printk(KERN_WARNING "MT2266 I2C write failed (len=%i)\n",(int)len);
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Initialisation sequences
|
||||
static u8 mt2266_init1[] = {
|
||||
REG_TUNE,
|
||||
0x00, 0x00, 0x28, 0x00, 0x52, 0x99, 0x3f };
|
||||
|
||||
static u8 mt2266_init2[] = {
|
||||
0x17, 0x6d, 0x71, 0x61, 0xc0, 0xbf, 0xff, 0xdc, 0x00, 0x0a,
|
||||
0xd4, 0x03, 0x64, 0x64, 0x64, 0x64, 0x22, 0xaa, 0xf2, 0x1e, 0x80, 0x14, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x7f, 0x5e, 0x3f, 0xff, 0xff, 0xff, 0x00, 0x77, 0x0f, 0x2d };
|
||||
|
||||
static u8 mt2266_init_8mhz[] = {
|
||||
REG_BANDWIDTH,
|
||||
0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 };
|
||||
|
||||
static u8 mt2266_init_7mhz[] = {
|
||||
REG_BANDWIDTH,
|
||||
0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32 };
|
||||
|
||||
static u8 mt2266_init_6mhz[] = {
|
||||
REG_BANDWIDTH,
|
||||
0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7 };
|
||||
|
||||
#define FREF 30000 // Quartz oscillator 30 MHz
|
||||
|
||||
static int mt2266_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
|
||||
{
|
||||
struct mt2266_priv *priv;
|
||||
int ret=0;
|
||||
u32 freq;
|
||||
u32 tune;
|
||||
u8 lnaband;
|
||||
u8 b[10];
|
||||
int i;
|
||||
|
||||
priv = fe->tuner_priv;
|
||||
|
||||
mt2266_writereg(priv,0x17,0x6d);
|
||||
mt2266_writereg(priv,0x1c,0xff);
|
||||
|
||||
freq = params->frequency / 1000; // Hz -> kHz
|
||||
priv->bandwidth = (fe->ops.info.type == FE_OFDM) ? params->u.ofdm.bandwidth : 0;
|
||||
priv->frequency = freq * 1000;
|
||||
tune=2 * freq * (8192/16) / (FREF/16);
|
||||
|
||||
if (freq <= 495000) lnaband = 0xEE; else
|
||||
if (freq <= 525000) lnaband = 0xDD; else
|
||||
if (freq <= 550000) lnaband = 0xCC; else
|
||||
if (freq <= 580000) lnaband = 0xBB; else
|
||||
if (freq <= 605000) lnaband = 0xAA; else
|
||||
if (freq <= 630000) lnaband = 0x99; else
|
||||
if (freq <= 655000) lnaband = 0x88; else
|
||||
if (freq <= 685000) lnaband = 0x77; else
|
||||
if (freq <= 710000) lnaband = 0x66; else
|
||||
if (freq <= 735000) lnaband = 0x55; else
|
||||
if (freq <= 765000) lnaband = 0x44; else
|
||||
if (freq <= 802000) lnaband = 0x33; else
|
||||
if (freq <= 840000) lnaband = 0x22; else lnaband = 0x11;
|
||||
|
||||
msleep(100);
|
||||
mt2266_writeregs(priv,(params->u.ofdm.bandwidth==BANDWIDTH_6_MHZ)?mt2266_init_6mhz:
|
||||
(params->u.ofdm.bandwidth==BANDWIDTH_7_MHZ)?mt2266_init_7mhz:
|
||||
mt2266_init_8mhz,sizeof(mt2266_init_8mhz));
|
||||
|
||||
b[0] = REG_TUNE;
|
||||
b[1] = (tune >> 8) & 0x1F;
|
||||
b[2] = tune & 0xFF;
|
||||
b[3] = tune >> 13;
|
||||
mt2266_writeregs(priv,b,4);
|
||||
|
||||
dprintk("set_parms: tune=%d band=%d",(int)tune,(int)lnaband);
|
||||
dprintk("set_parms: [1..3]: %2x %2x %2x",(int)b[1],(int)b[2],(int)b[3]);
|
||||
|
||||
b[0] = 0x05;
|
||||
b[1] = 0x62;
|
||||
b[2] = lnaband;
|
||||
mt2266_writeregs(priv,b,3);
|
||||
|
||||
//Waits for pll lock or timeout
|
||||
i = 0;
|
||||
do {
|
||||
mt2266_readreg(priv,REG_LOCK,b);
|
||||
if ((b[0] & 0x40)==0x40)
|
||||
break;
|
||||
msleep(10);
|
||||
i++;
|
||||
} while (i<10);
|
||||
dprintk("Lock when i=%i",(int)i);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void mt2266_calibrate(struct mt2266_priv *priv)
|
||||
{
|
||||
mt2266_writereg(priv,0x11,0x03);
|
||||
mt2266_writereg(priv,0x11,0x01);
|
||||
|
||||
mt2266_writeregs(priv,mt2266_init1,sizeof(mt2266_init1));
|
||||
mt2266_writeregs(priv,mt2266_init2,sizeof(mt2266_init2));
|
||||
|
||||
mt2266_writereg(priv,0x33,0x5e);
|
||||
mt2266_writereg(priv,0x10,0x10);
|
||||
mt2266_writereg(priv,0x10,0x00);
|
||||
|
||||
mt2266_writeregs(priv,mt2266_init_8mhz,sizeof(mt2266_init_8mhz));
|
||||
|
||||
msleep(25);
|
||||
mt2266_writereg(priv,0x17,0x6d);
|
||||
mt2266_writereg(priv,0x1c,0x00);
|
||||
msleep(75);
|
||||
mt2266_writereg(priv,0x17,0x6d);
|
||||
mt2266_writereg(priv,0x1c,0xff);
|
||||
}
|
||||
|
||||
static int mt2266_get_frequency(struct dvb_frontend *fe, u32 *frequency)
|
||||
{
|
||||
struct mt2266_priv *priv = fe->tuner_priv;
|
||||
*frequency = priv->frequency;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mt2266_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
|
||||
{
|
||||
struct mt2266_priv *priv = fe->tuner_priv;
|
||||
*bandwidth = priv->bandwidth;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mt2266_init(struct dvb_frontend *fe)
|
||||
{
|
||||
struct mt2266_priv *priv = fe->tuner_priv;
|
||||
mt2266_writereg(priv,0x17,0x6d);
|
||||
mt2266_writereg(priv,0x1c,0xff);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mt2266_sleep(struct dvb_frontend *fe)
|
||||
{
|
||||
struct mt2266_priv *priv = fe->tuner_priv;
|
||||
mt2266_writereg(priv,0x17,0x6d);
|
||||
mt2266_writereg(priv,0x1c,0x00);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mt2266_release(struct dvb_frontend *fe)
|
||||
{
|
||||
kfree(fe->tuner_priv);
|
||||
fe->tuner_priv = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dvb_tuner_ops mt2266_tuner_ops = {
|
||||
.info = {
|
||||
.name = "Microtune MT2266",
|
||||
.frequency_min = 470000000,
|
||||
.frequency_max = 860000000,
|
||||
.frequency_step = 50000,
|
||||
},
|
||||
.release = mt2266_release,
|
||||
.init = mt2266_init,
|
||||
.sleep = mt2266_sleep,
|
||||
.set_params = mt2266_set_params,
|
||||
.get_frequency = mt2266_get_frequency,
|
||||
.get_bandwidth = mt2266_get_bandwidth
|
||||
};
|
||||
|
||||
struct dvb_frontend * mt2266_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct mt2266_config *cfg)
|
||||
{
|
||||
struct mt2266_priv *priv = NULL;
|
||||
u8 id = 0;
|
||||
|
||||
priv = kzalloc(sizeof(struct mt2266_priv), GFP_KERNEL);
|
||||
if (priv == NULL)
|
||||
return NULL;
|
||||
|
||||
priv->cfg = cfg;
|
||||
priv->i2c = i2c;
|
||||
|
||||
if (mt2266_readreg(priv,0,&id) != 0) {
|
||||
kfree(priv);
|
||||
return NULL;
|
||||
}
|
||||
if (id != PART_REV) {
|
||||
kfree(priv);
|
||||
return NULL;
|
||||
}
|
||||
printk(KERN_INFO "MT2266: successfully identified\n");
|
||||
memcpy(&fe->ops.tuner_ops, &mt2266_tuner_ops, sizeof(struct dvb_tuner_ops));
|
||||
|
||||
fe->tuner_priv = priv;
|
||||
mt2266_calibrate(priv);
|
||||
return fe;
|
||||
}
|
||||
EXPORT_SYMBOL(mt2266_attach);
|
||||
|
||||
MODULE_AUTHOR("Olivier DANET");
|
||||
MODULE_DESCRIPTION("Microtune MT2266 silicon tuner driver");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Driver for Microtune MT2266 "Direct conversion low power broadband tuner"
|
||||
*
|
||||
* Copyright (c) 2007 Olivier DANET <odanet@caramail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef MT2266_H
|
||||
#define MT2266_H
|
||||
|
||||
struct dvb_frontend;
|
||||
struct i2c_adapter;
|
||||
|
||||
struct mt2266_config {
|
||||
u8 i2c_address;
|
||||
};
|
||||
|
||||
#if defined(CONFIG_DVB_TUNER_MT2266) || (defined(CONFIG_DVB_TUNER_MT2266_MODULE) && defined(MODULE))
|
||||
extern struct dvb_frontend * mt2266_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct mt2266_config *cfg);
|
||||
#else
|
||||
static inline struct dvb_frontend * mt2266_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct mt2266_config *cfg)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
#endif // CONFIG_DVB_TUNER_MT2266
|
||||
|
||||
#endif
|
|
@ -28,7 +28,6 @@
|
|||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
|
|
|
@ -32,7 +32,6 @@
|
|||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/string.h>
|
||||
|
|
|
@ -44,7 +44,6 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
|
||||
|
|
|
@ -36,7 +36,6 @@
|
|||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/string.h>
|
||||
|
|
|
@ -32,7 +32,6 @@
|
|||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/string.h>
|
||||
|
|
|
@ -0,0 +1,729 @@
|
|||
/*
|
||||
Samsung S5H1409 VSB/QAM demodulator driver
|
||||
|
||||
Copyright (C) 2006 Steven Toth <stoth@hauppauge.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include "dvb_frontend.h"
|
||||
#include "dvb-pll.h"
|
||||
#include "s5h1409.h"
|
||||
|
||||
struct s5h1409_state {
|
||||
|
||||
struct i2c_adapter* i2c;
|
||||
|
||||
/* configuration settings */
|
||||
const struct s5h1409_config* config;
|
||||
|
||||
struct dvb_frontend frontend;
|
||||
|
||||
/* previous uncorrected block counter */
|
||||
fe_modulation_t current_modulation;
|
||||
|
||||
u32 current_frequency;
|
||||
};
|
||||
|
||||
static int debug = 0;
|
||||
#define dprintk if (debug) printk
|
||||
|
||||
/* Register values to initialise the demod, this will set VSB by default */
|
||||
static struct init_tab {
|
||||
u8 reg;
|
||||
u16 data;
|
||||
} init_tab[] = {
|
||||
{ 0x00, 0x0071, },
|
||||
{ 0x01, 0x3213, },
|
||||
{ 0x09, 0x0025, },
|
||||
{ 0x1c, 0x001d, },
|
||||
{ 0x1f, 0x002d, },
|
||||
{ 0x20, 0x001d, },
|
||||
{ 0x22, 0x0022, },
|
||||
{ 0x23, 0x0020, },
|
||||
{ 0x29, 0x110f, },
|
||||
{ 0x2a, 0x10b4, },
|
||||
{ 0x2b, 0x10ae, },
|
||||
{ 0x2c, 0x0031, },
|
||||
{ 0x31, 0x010d, },
|
||||
{ 0x32, 0x0100, },
|
||||
{ 0x44, 0x0510, },
|
||||
{ 0x54, 0x0104, },
|
||||
{ 0x58, 0x2222, },
|
||||
{ 0x59, 0x1162, },
|
||||
{ 0x5a, 0x3211, },
|
||||
{ 0x5d, 0x0370, },
|
||||
{ 0x5e, 0x0296, },
|
||||
{ 0x61, 0x0010, },
|
||||
{ 0x63, 0x4a00, },
|
||||
{ 0x65, 0x0800, },
|
||||
{ 0x71, 0x0003, },
|
||||
{ 0x72, 0x0470, },
|
||||
{ 0x81, 0x0002, },
|
||||
{ 0x82, 0x0600, },
|
||||
{ 0x86, 0x0002, },
|
||||
{ 0x8a, 0x2c38, },
|
||||
{ 0x8b, 0x2a37, },
|
||||
{ 0x92, 0x302f, },
|
||||
{ 0x93, 0x3332, },
|
||||
{ 0x96, 0x000c, },
|
||||
{ 0x99, 0x0101, },
|
||||
{ 0x9c, 0x2e37, },
|
||||
{ 0x9d, 0x2c37, },
|
||||
{ 0x9e, 0x2c37, },
|
||||
{ 0xab, 0x0100, },
|
||||
{ 0xac, 0x1003, },
|
||||
{ 0xad, 0x103f, },
|
||||
{ 0xe2, 0x0100, },
|
||||
{ 0x28, 0x1010, },
|
||||
{ 0xb1, 0x000e, },
|
||||
};
|
||||
|
||||
/* VSB SNR lookup table */
|
||||
static struct vsb_snr_tab {
|
||||
u16 val;
|
||||
u16 data;
|
||||
} vsb_snr_tab[] = {
|
||||
{ 1023, 770, },
|
||||
{ 923, 300, },
|
||||
{ 918, 295, },
|
||||
{ 915, 290, },
|
||||
{ 911, 285, },
|
||||
{ 906, 280, },
|
||||
{ 901, 275, },
|
||||
{ 896, 270, },
|
||||
{ 891, 265, },
|
||||
{ 885, 260, },
|
||||
{ 879, 255, },
|
||||
{ 873, 250, },
|
||||
{ 864, 245, },
|
||||
{ 858, 240, },
|
||||
{ 850, 235, },
|
||||
{ 841, 230, },
|
||||
{ 832, 225, },
|
||||
{ 823, 220, },
|
||||
{ 812, 215, },
|
||||
{ 802, 210, },
|
||||
{ 788, 205, },
|
||||
{ 778, 200, },
|
||||
{ 767, 195, },
|
||||
{ 753, 190, },
|
||||
{ 740, 185, },
|
||||
{ 725, 180, },
|
||||
{ 707, 175, },
|
||||
{ 689, 170, },
|
||||
{ 671, 165, },
|
||||
{ 656, 160, },
|
||||
{ 637, 155, },
|
||||
{ 616, 150, },
|
||||
{ 542, 145, },
|
||||
{ 519, 140, },
|
||||
{ 507, 135, },
|
||||
{ 497, 130, },
|
||||
{ 492, 125, },
|
||||
{ 474, 120, },
|
||||
{ 300, 111, },
|
||||
{ 0, 0, },
|
||||
};
|
||||
|
||||
/* QAM64 SNR lookup table */
|
||||
static struct qam64_snr_tab {
|
||||
u16 val;
|
||||
u16 data;
|
||||
} qam64_snr_tab[] = {
|
||||
{ 12, 300, },
|
||||
{ 15, 290, },
|
||||
{ 18, 280, },
|
||||
{ 22, 270, },
|
||||
{ 23, 268, },
|
||||
{ 24, 266, },
|
||||
{ 25, 264, },
|
||||
{ 27, 262, },
|
||||
{ 28, 260, },
|
||||
{ 29, 258, },
|
||||
{ 30, 256, },
|
||||
{ 32, 254, },
|
||||
{ 33, 252, },
|
||||
{ 34, 250, },
|
||||
{ 35, 249, },
|
||||
{ 36, 248, },
|
||||
{ 37, 247, },
|
||||
{ 38, 246, },
|
||||
{ 39, 245, },
|
||||
{ 40, 244, },
|
||||
{ 41, 243, },
|
||||
{ 42, 241, },
|
||||
{ 43, 240, },
|
||||
{ 44, 239, },
|
||||
{ 45, 238, },
|
||||
{ 46, 237, },
|
||||
{ 47, 236, },
|
||||
{ 48, 235, },
|
||||
{ 49, 234, },
|
||||
{ 50, 233, },
|
||||
{ 51, 232, },
|
||||
{ 52, 231, },
|
||||
{ 53, 230, },
|
||||
{ 55, 229, },
|
||||
{ 56, 228, },
|
||||
{ 57, 227, },
|
||||
{ 58, 226, },
|
||||
{ 59, 225, },
|
||||
{ 60, 224, },
|
||||
{ 62, 223, },
|
||||
{ 63, 222, },
|
||||
{ 65, 221, },
|
||||
{ 66, 220, },
|
||||
{ 68, 219, },
|
||||
{ 69, 218, },
|
||||
{ 70, 217, },
|
||||
{ 72, 216, },
|
||||
{ 73, 215, },
|
||||
{ 75, 214, },
|
||||
{ 76, 213, },
|
||||
{ 78, 212, },
|
||||
{ 80, 211, },
|
||||
{ 81, 210, },
|
||||
{ 83, 209, },
|
||||
{ 84, 208, },
|
||||
{ 85, 207, },
|
||||
{ 87, 206, },
|
||||
{ 89, 205, },
|
||||
{ 91, 204, },
|
||||
{ 93, 203, },
|
||||
{ 95, 202, },
|
||||
{ 96, 201, },
|
||||
{ 104, 200, },
|
||||
};
|
||||
|
||||
/* QAM256 SNR lookup table */
|
||||
static struct qam256_snr_tab {
|
||||
u16 val;
|
||||
u16 data;
|
||||
} qam256_snr_tab[] = {
|
||||
{ 12, 400, },
|
||||
{ 13, 390, },
|
||||
{ 15, 380, },
|
||||
{ 17, 360, },
|
||||
{ 19, 350, },
|
||||
{ 22, 348, },
|
||||
{ 23, 346, },
|
||||
{ 24, 344, },
|
||||
{ 25, 342, },
|
||||
{ 26, 340, },
|
||||
{ 27, 336, },
|
||||
{ 28, 334, },
|
||||
{ 29, 332, },
|
||||
{ 30, 330, },
|
||||
{ 31, 328, },
|
||||
{ 32, 326, },
|
||||
{ 33, 325, },
|
||||
{ 34, 322, },
|
||||
{ 35, 320, },
|
||||
{ 37, 318, },
|
||||
{ 39, 316, },
|
||||
{ 40, 314, },
|
||||
{ 41, 312, },
|
||||
{ 42, 310, },
|
||||
{ 43, 308, },
|
||||
{ 46, 306, },
|
||||
{ 47, 304, },
|
||||
{ 49, 302, },
|
||||
{ 51, 300, },
|
||||
{ 53, 298, },
|
||||
{ 54, 297, },
|
||||
{ 55, 296, },
|
||||
{ 56, 295, },
|
||||
{ 57, 294, },
|
||||
{ 59, 293, },
|
||||
{ 60, 292, },
|
||||
{ 61, 291, },
|
||||
{ 63, 290, },
|
||||
{ 64, 289, },
|
||||
{ 65, 288, },
|
||||
{ 66, 287, },
|
||||
{ 68, 286, },
|
||||
{ 69, 285, },
|
||||
{ 71, 284, },
|
||||
{ 72, 283, },
|
||||
{ 74, 282, },
|
||||
{ 75, 281, },
|
||||
{ 76, 280, },
|
||||
{ 77, 279, },
|
||||
{ 78, 278, },
|
||||
{ 81, 277, },
|
||||
{ 83, 276, },
|
||||
{ 84, 275, },
|
||||
{ 86, 274, },
|
||||
{ 87, 273, },
|
||||
{ 89, 272, },
|
||||
{ 90, 271, },
|
||||
{ 92, 270, },
|
||||
{ 93, 269, },
|
||||
{ 95, 268, },
|
||||
{ 96, 267, },
|
||||
{ 98, 266, },
|
||||
{ 100, 265, },
|
||||
{ 102, 264, },
|
||||
{ 104, 263, },
|
||||
{ 105, 262, },
|
||||
{ 106, 261, },
|
||||
{ 110, 260, },
|
||||
};
|
||||
|
||||
/* 8 bit registers, 16 bit values */
|
||||
static int s5h1409_writereg(struct s5h1409_state* state, u8 reg, u16 data)
|
||||
{
|
||||
int ret;
|
||||
u8 buf [] = { reg, data >> 8, data & 0xff };
|
||||
|
||||
struct i2c_msg msg = { .addr = state->config->demod_address,
|
||||
.flags = 0, .buf = buf, .len = 3 };
|
||||
|
||||
ret = i2c_transfer(state->i2c, &msg, 1);
|
||||
|
||||
if (ret != 1)
|
||||
printk("%s: writereg error (reg == 0x%02x, val == 0x%04x, "
|
||||
"ret == %i)\n", __FUNCTION__, reg, data, ret);
|
||||
|
||||
return (ret != 1) ? -1 : 0;
|
||||
}
|
||||
|
||||
static u16 s5h1409_readreg(struct s5h1409_state* state, u8 reg)
|
||||
{
|
||||
int ret;
|
||||
u8 b0 [] = { reg };
|
||||
u8 b1 [] = { 0, 0 };
|
||||
|
||||
struct i2c_msg msg [] = {
|
||||
{ .addr = state->config->demod_address, .flags = 0,
|
||||
.buf = b0, .len = 1 },
|
||||
{ .addr = state->config->demod_address, .flags = I2C_M_RD,
|
||||
.buf = b1, .len = 2 } };
|
||||
|
||||
ret = i2c_transfer(state->i2c, msg, 2);
|
||||
|
||||
if (ret != 2)
|
||||
printk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret);
|
||||
return (b1[0] << 8) | b1[1];
|
||||
}
|
||||
|
||||
static int s5h1409_softreset(struct dvb_frontend* fe)
|
||||
{
|
||||
struct s5h1409_state* state = fe->demodulator_priv;
|
||||
|
||||
dprintk("%s()\n", __FUNCTION__);
|
||||
|
||||
s5h1409_writereg(state, 0xf5, 0);
|
||||
s5h1409_writereg(state, 0xf5, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int s5h1409_set_if_freq(struct dvb_frontend* fe, int KHz)
|
||||
{
|
||||
struct s5h1409_state* state = fe->demodulator_priv;
|
||||
int ret = 0;
|
||||
|
||||
dprintk("%s(%d KHz)\n", __FUNCTION__, KHz);
|
||||
|
||||
if( (KHz == 44000) || (KHz == 5380) ) {
|
||||
s5h1409_writereg(state, 0x87, 0x01be);
|
||||
s5h1409_writereg(state, 0x88, 0x0436);
|
||||
s5h1409_writereg(state, 0x89, 0x054d);
|
||||
} else {
|
||||
printk("%s() Invalid arg = %d KHz\n", __FUNCTION__, KHz);
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int s5h1409_set_spectralinversion(struct dvb_frontend* fe, int inverted)
|
||||
{
|
||||
struct s5h1409_state* state = fe->demodulator_priv;
|
||||
|
||||
dprintk("%s()\n", __FUNCTION__);
|
||||
|
||||
if(inverted == 1)
|
||||
return s5h1409_writereg(state, 0x1b, 0x1101); /* Inverted */
|
||||
else
|
||||
return s5h1409_writereg(state, 0x1b, 0x0110); /* Normal */
|
||||
}
|
||||
|
||||
static int s5h1409_enable_modulation(struct dvb_frontend* fe,
|
||||
fe_modulation_t m)
|
||||
{
|
||||
struct s5h1409_state* state = fe->demodulator_priv;
|
||||
|
||||
dprintk("%s(0x%08x)\n", __FUNCTION__, m);
|
||||
|
||||
switch(m) {
|
||||
case VSB_8:
|
||||
dprintk("%s() VSB_8\n", __FUNCTION__);
|
||||
s5h1409_writereg(state, 0xf4, 0);
|
||||
break;
|
||||
case QAM_64:
|
||||
dprintk("%s() QAM_64\n", __FUNCTION__);
|
||||
s5h1409_writereg(state, 0xf4, 1);
|
||||
s5h1409_writereg(state, 0x85, 0x100);
|
||||
break;
|
||||
case QAM_256:
|
||||
dprintk("%s() QAM_256\n", __FUNCTION__);
|
||||
s5h1409_writereg(state, 0xf4, 1);
|
||||
s5h1409_writereg(state, 0x85, 0x101);
|
||||
break;
|
||||
default:
|
||||
dprintk("%s() Invalid modulation\n", __FUNCTION__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
state->current_modulation = m;
|
||||
s5h1409_softreset(fe);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int s5h1409_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
|
||||
{
|
||||
struct s5h1409_state* state = fe->demodulator_priv;
|
||||
|
||||
dprintk("%s(%d)\n", __FUNCTION__, enable);
|
||||
|
||||
if (enable)
|
||||
return s5h1409_writereg(state, 0xf3, 1);
|
||||
else
|
||||
return s5h1409_writereg(state, 0xf3, 0);
|
||||
}
|
||||
|
||||
static int s5h1409_set_gpio(struct dvb_frontend* fe, int enable)
|
||||
{
|
||||
struct s5h1409_state* state = fe->demodulator_priv;
|
||||
|
||||
dprintk("%s(%d)\n", __FUNCTION__, enable);
|
||||
|
||||
if (enable)
|
||||
return s5h1409_writereg(state, 0xe3, 0x1100);
|
||||
else
|
||||
return s5h1409_writereg(state, 0xe3, 0);
|
||||
}
|
||||
|
||||
static int s5h1409_sleep(struct dvb_frontend* fe, int enable)
|
||||
{
|
||||
struct s5h1409_state* state = fe->demodulator_priv;
|
||||
|
||||
dprintk("%s(%d)\n", __FUNCTION__, enable);
|
||||
|
||||
return s5h1409_writereg(state, 0xf2, enable);
|
||||
}
|
||||
|
||||
static int s5h1409_register_reset(struct dvb_frontend* fe)
|
||||
{
|
||||
struct s5h1409_state* state = fe->demodulator_priv;
|
||||
|
||||
dprintk("%s()\n", __FUNCTION__);
|
||||
|
||||
return s5h1409_writereg(state, 0xfa, 0);
|
||||
}
|
||||
|
||||
/* Talk to the demod, set the FEC, GUARD, QAM settings etc */
|
||||
static int s5h1409_set_frontend (struct dvb_frontend* fe,
|
||||
struct dvb_frontend_parameters *p)
|
||||
{
|
||||
struct s5h1409_state* state = fe->demodulator_priv;
|
||||
|
||||
dprintk("%s(frequency=%d)\n", __FUNCTION__, p->frequency);
|
||||
|
||||
s5h1409_softreset(fe);
|
||||
|
||||
state->current_frequency = p->frequency;
|
||||
|
||||
s5h1409_enable_modulation(fe, p->u.vsb.modulation);
|
||||
|
||||
if (fe->ops.tuner_ops.set_params) {
|
||||
if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1);
|
||||
fe->ops.tuner_ops.set_params(fe, p);
|
||||
if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Reset the demod hardware and reset all of the configuration registers
|
||||
to a default state. */
|
||||
static int s5h1409_init (struct dvb_frontend* fe)
|
||||
{
|
||||
int i;
|
||||
|
||||
struct s5h1409_state* state = fe->demodulator_priv;
|
||||
dprintk("%s()\n", __FUNCTION__);
|
||||
|
||||
s5h1409_sleep(fe, 0);
|
||||
s5h1409_register_reset(fe);
|
||||
|
||||
for (i=0; i < ARRAY_SIZE(init_tab); i++)
|
||||
s5h1409_writereg(state, init_tab[i].reg, init_tab[i].data);
|
||||
|
||||
/* The datasheet says that after initialisation, VSB is default */
|
||||
state->current_modulation = VSB_8;
|
||||
|
||||
if (state->config->output_mode == S5H1409_SERIAL_OUTPUT)
|
||||
s5h1409_writereg(state, 0xab, 0x100); /* Serial */
|
||||
else
|
||||
s5h1409_writereg(state, 0xab, 0x0); /* Parallel */
|
||||
|
||||
s5h1409_set_spectralinversion(fe, state->config->inversion);
|
||||
s5h1409_set_if_freq(fe, state->config->if_freq);
|
||||
s5h1409_set_gpio(fe, state->config->gpio);
|
||||
s5h1409_softreset(fe);
|
||||
|
||||
/* Note: Leaving the I2C gate open here. */
|
||||
s5h1409_i2c_gate_ctrl(fe, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int s5h1409_read_status(struct dvb_frontend* fe, fe_status_t* status)
|
||||
{
|
||||
struct s5h1409_state* state = fe->demodulator_priv;
|
||||
u16 reg;
|
||||
u32 tuner_status = 0;
|
||||
|
||||
*status = 0;
|
||||
|
||||
/* Get the demodulator status */
|
||||
reg = s5h1409_readreg(state, 0xf1);
|
||||
if(reg & 0x1000)
|
||||
*status |= FE_HAS_VITERBI;
|
||||
if(reg & 0x8000)
|
||||
*status |= FE_HAS_LOCK | FE_HAS_SYNC;
|
||||
|
||||
switch(state->config->status_mode) {
|
||||
case S5H1409_DEMODLOCKING:
|
||||
if (*status & FE_HAS_VITERBI)
|
||||
*status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
|
||||
break;
|
||||
case S5H1409_TUNERLOCKING:
|
||||
/* Get the tuner status */
|
||||
if (fe->ops.tuner_ops.get_status) {
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 1);
|
||||
|
||||
fe->ops.tuner_ops.get_status(fe, &tuner_status);
|
||||
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 0);
|
||||
}
|
||||
if (tuner_status)
|
||||
*status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
|
||||
break;
|
||||
}
|
||||
|
||||
dprintk("%s() status 0x%08x\n", __FUNCTION__, *status);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int s5h1409_qam256_lookup_snr(struct dvb_frontend* fe, u16* snr, u16 v)
|
||||
{
|
||||
int i, ret = -EINVAL;
|
||||
dprintk("%s()\n", __FUNCTION__);
|
||||
|
||||
for (i=0; i < ARRAY_SIZE(qam256_snr_tab); i++) {
|
||||
if (v < qam256_snr_tab[i].val) {
|
||||
*snr = qam256_snr_tab[i].data;
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int s5h1409_qam64_lookup_snr(struct dvb_frontend* fe, u16* snr, u16 v)
|
||||
{
|
||||
int i, ret = -EINVAL;
|
||||
dprintk("%s()\n", __FUNCTION__);
|
||||
|
||||
for (i=0; i < ARRAY_SIZE(qam64_snr_tab); i++) {
|
||||
if (v < qam64_snr_tab[i].val) {
|
||||
*snr = qam64_snr_tab[i].data;
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int s5h1409_vsb_lookup_snr(struct dvb_frontend* fe, u16* snr, u16 v)
|
||||
{
|
||||
int i, ret = -EINVAL;
|
||||
dprintk("%s()\n", __FUNCTION__);
|
||||
|
||||
for (i=0; i < ARRAY_SIZE(vsb_snr_tab); i++) {
|
||||
if (v > vsb_snr_tab[i].val) {
|
||||
*snr = vsb_snr_tab[i].data;
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
dprintk("%s() snr=%d\n", __FUNCTION__, *snr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int s5h1409_read_snr(struct dvb_frontend* fe, u16* snr)
|
||||
{
|
||||
struct s5h1409_state* state = fe->demodulator_priv;
|
||||
u16 reg;
|
||||
dprintk("%s()\n", __FUNCTION__);
|
||||
|
||||
reg = s5h1409_readreg(state, 0xf1) & 0x1ff;
|
||||
|
||||
switch(state->current_modulation) {
|
||||
case QAM_64:
|
||||
return s5h1409_qam64_lookup_snr(fe, snr, reg);
|
||||
case QAM_256:
|
||||
return s5h1409_qam256_lookup_snr(fe, snr, reg);
|
||||
case VSB_8:
|
||||
return s5h1409_vsb_lookup_snr(fe, snr, reg);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int s5h1409_read_signal_strength(struct dvb_frontend* fe,
|
||||
u16* signal_strength)
|
||||
{
|
||||
return s5h1409_read_snr(fe, signal_strength);
|
||||
}
|
||||
|
||||
static int s5h1409_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
|
||||
{
|
||||
struct s5h1409_state* state = fe->demodulator_priv;
|
||||
|
||||
*ucblocks = s5h1409_readreg(state, 0xb5);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int s5h1409_read_ber(struct dvb_frontend* fe, u32* ber)
|
||||
{
|
||||
return s5h1409_read_ucblocks(fe, ber);
|
||||
}
|
||||
|
||||
static int s5h1409_get_frontend(struct dvb_frontend* fe,
|
||||
struct dvb_frontend_parameters *p)
|
||||
{
|
||||
struct s5h1409_state* state = fe->demodulator_priv;
|
||||
|
||||
p->frequency = state->current_frequency;
|
||||
p->u.vsb.modulation = state->current_modulation;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int s5h1409_get_tune_settings(struct dvb_frontend* fe,
|
||||
struct dvb_frontend_tune_settings *tune)
|
||||
{
|
||||
tune->min_delay_ms = 1000;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void s5h1409_release(struct dvb_frontend* fe)
|
||||
{
|
||||
struct s5h1409_state* state = fe->demodulator_priv;
|
||||
kfree(state);
|
||||
}
|
||||
|
||||
static struct dvb_frontend_ops s5h1409_ops;
|
||||
|
||||
struct dvb_frontend* s5h1409_attach(const struct s5h1409_config* config,
|
||||
struct i2c_adapter* i2c)
|
||||
{
|
||||
struct s5h1409_state* state = NULL;
|
||||
|
||||
/* allocate memory for the internal state */
|
||||
state = kmalloc(sizeof(struct s5h1409_state), GFP_KERNEL);
|
||||
if (state == NULL)
|
||||
goto error;
|
||||
|
||||
/* setup the state */
|
||||
state->config = config;
|
||||
state->i2c = i2c;
|
||||
state->current_modulation = 0;
|
||||
|
||||
/* check if the demod exists */
|
||||
if (s5h1409_readreg(state, 0x04) != 0x0066)
|
||||
goto error;
|
||||
|
||||
/* create dvb_frontend */
|
||||
memcpy(&state->frontend.ops, &s5h1409_ops,
|
||||
sizeof(struct dvb_frontend_ops));
|
||||
state->frontend.demodulator_priv = state;
|
||||
|
||||
/* Note: Leaving the I2C gate open here. */
|
||||
s5h1409_writereg(state, 0xf3, 1);
|
||||
|
||||
return &state->frontend;
|
||||
|
||||
error:
|
||||
kfree(state);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct dvb_frontend_ops s5h1409_ops = {
|
||||
|
||||
.info = {
|
||||
.name = "Samsung S5H1409 QAM/8VSB Frontend",
|
||||
.type = FE_ATSC,
|
||||
.frequency_min = 54000000,
|
||||
.frequency_max = 858000000,
|
||||
.frequency_stepsize = 62500,
|
||||
.caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
|
||||
},
|
||||
|
||||
.init = s5h1409_init,
|
||||
.i2c_gate_ctrl = s5h1409_i2c_gate_ctrl,
|
||||
.set_frontend = s5h1409_set_frontend,
|
||||
.get_frontend = s5h1409_get_frontend,
|
||||
.get_tune_settings = s5h1409_get_tune_settings,
|
||||
.read_status = s5h1409_read_status,
|
||||
.read_ber = s5h1409_read_ber,
|
||||
.read_signal_strength = s5h1409_read_signal_strength,
|
||||
.read_snr = s5h1409_read_snr,
|
||||
.read_ucblocks = s5h1409_read_ucblocks,
|
||||
.release = s5h1409_release,
|
||||
};
|
||||
|
||||
module_param(debug, int, 0644);
|
||||
MODULE_PARM_DESC(debug, "Enable verbose debug messages");
|
||||
|
||||
MODULE_DESCRIPTION("Samsung S5H1409 QAM-B/ATSC Demodulator driver");
|
||||
MODULE_AUTHOR("Steven Toth");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
EXPORT_SYMBOL(s5h1409_attach);
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* c-basic-offset: 8
|
||||
*/
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
Samsung S5H1409 VSB/QAM demodulator driver
|
||||
|
||||
Copyright (C) 2006 Steven Toth <stoth@hauppauge.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef __S5H1409_H__
|
||||
#define __S5H1409_H__
|
||||
|
||||
#include <linux/dvb/frontend.h>
|
||||
|
||||
struct s5h1409_config
|
||||
{
|
||||
/* the demodulator's i2c address */
|
||||
u8 demod_address;
|
||||
|
||||
/* serial/parallel output */
|
||||
#define S5H1409_PARALLEL_OUTPUT 0
|
||||
#define S5H1409_SERIAL_OUTPUT 1
|
||||
u8 output_mode;
|
||||
|
||||
/* GPIO Setting */
|
||||
#define S5H1409_GPIO_OFF 0
|
||||
#define S5H1409_GPIO_ON 1
|
||||
u8 gpio;
|
||||
|
||||
/* IF Freq in KHz */
|
||||
u16 if_freq;
|
||||
|
||||
/* Spectral Inversion */
|
||||
#define S5H1409_INVERSION_OFF 0
|
||||
#define S5H1409_INVERSION_ON 1
|
||||
u8 inversion;
|
||||
|
||||
/* Return lock status based on tuner lock, or demod lock */
|
||||
#define S5H1409_TUNERLOCKING 0
|
||||
#define S5H1409_DEMODLOCKING 1
|
||||
u8 status_mode;
|
||||
};
|
||||
|
||||
#if defined(CONFIG_DVB_S5H1409) || (defined(CONFIG_DVB_S5H1409_MODULE) && defined(MODULE))
|
||||
extern struct dvb_frontend* s5h1409_attach(const struct s5h1409_config* config,
|
||||
struct i2c_adapter* i2c);
|
||||
#else
|
||||
static inline struct dvb_frontend* s5h1409_attach(const struct s5h1409_config* config,
|
||||
struct i2c_adapter* i2c)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
#endif /* CONFIG_DVB_S5H1409 */
|
||||
|
||||
#endif /* __S5H1409_H__ */
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* c-basic-offset: 8
|
||||
*/
|
|
@ -29,7 +29,6 @@
|
|||
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/delay.h>
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/string.h>
|
||||
|
|
|
@ -680,8 +680,8 @@ static struct dvb_frontend_ops stv0297_ops = {
|
|||
.info = {
|
||||
.name = "ST STV0297 DVB-C",
|
||||
.type = FE_QAM,
|
||||
.frequency_min = 64000000,
|
||||
.frequency_max = 1300000000,
|
||||
.frequency_min = 47000000,
|
||||
.frequency_max = 862000000,
|
||||
.frequency_stepsize = 62500,
|
||||
.symbol_rate_min = 870000,
|
||||
.symbol_rate_max = 11700000,
|
||||
|
|
|
@ -45,7 +45,6 @@
|
|||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/jiffies.h>
|
||||
|
|
|
@ -439,8 +439,8 @@ static struct dvb_frontend_ops tda10021_ops = {
|
|||
.name = "Philips TDA10021 DVB-C",
|
||||
.type = FE_QAM,
|
||||
.frequency_stepsize = 62500,
|
||||
.frequency_min = 51000000,
|
||||
.frequency_max = 858000000,
|
||||
.frequency_min = 47000000,
|
||||
.frequency_max = 862000000,
|
||||
.symbol_rate_min = (XIN/2)/64, /* SACLK/64 == (XIN/2)/64 */
|
||||
.symbol_rate_max = (XIN/2)/4, /* SACLK/4 */
|
||||
#if 0
|
||||
|
|
|
@ -215,12 +215,6 @@ static int tda10023_set_symbolrate (struct tda10023_state* state, u32 sr)
|
|||
s16 SFIL=0;
|
||||
u16 NDEC = 0;
|
||||
|
||||
if (sr > (SYSCLK/(2*4)))
|
||||
sr=SYSCLK/(2*4);
|
||||
|
||||
if (sr<870000)
|
||||
sr=870000;
|
||||
|
||||
if (sr < (u32)(SYSCLK/98.40)) {
|
||||
NDEC=3;
|
||||
SFIL=1;
|
||||
|
@ -506,8 +500,8 @@ static struct dvb_frontend_ops tda10023_ops = {
|
|||
.name = "Philips TDA10023 DVB-C",
|
||||
.type = FE_QAM,
|
||||
.frequency_stepsize = 62500,
|
||||
.frequency_min = 51000000,
|
||||
.frequency_max = 858000000,
|
||||
.frequency_min = 47000000,
|
||||
.frequency_max = 862000000,
|
||||
.symbol_rate_min = (SYSCLK/2)/64, /* SACLK/64 == (SYSCLK/2)/64 */
|
||||
.symbol_rate_max = (SYSCLK/2)/4, /* SACLK/4 */
|
||||
.caps = 0x400 | //FE_CAN_QAM_4
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/string.h>
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/string.h>
|
||||
|
|
|
@ -27,7 +27,6 @@
|
|||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/jiffies.h>
|
||||
|
@ -443,12 +442,12 @@ static struct dvb_frontend_ops tda8083_ops = {
|
|||
.info = {
|
||||
.name = "Philips TDA8083 DVB-S",
|
||||
.type = FE_QPSK,
|
||||
.frequency_min = 950000, /* FIXME: guessed! */
|
||||
.frequency_max = 1400000, /* FIXME: guessed! */
|
||||
.frequency_min = 920000, /* TDA8060 */
|
||||
.frequency_max = 2200000, /* TDA8060 */
|
||||
.frequency_stepsize = 125, /* kHz for QPSK frontends */
|
||||
/* .frequency_tolerance = ???,*/
|
||||
.symbol_rate_min = 1000000, /* FIXME: guessed! */
|
||||
.symbol_rate_max = 45000000, /* FIXME: guessed! */
|
||||
.symbol_rate_min = 12000000,
|
||||
.symbol_rate_max = 30000000,
|
||||
/* .symbol_rate_tolerance = ???,*/
|
||||
.caps = FE_CAN_INVERSION_AUTO |
|
||||
FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
|
||||
|
|
|
@ -410,8 +410,8 @@ static struct dvb_frontend_ops ves1820_ops = {
|
|||
.name = "VLSI VES1820 DVB-C",
|
||||
.type = FE_QAM,
|
||||
.frequency_stepsize = 62500,
|
||||
.frequency_min = 51000000,
|
||||
.frequency_max = 858000000,
|
||||
.frequency_min = 47000000,
|
||||
.frequency_max = 862000000,
|
||||
.caps = FE_CAN_QAM_16 |
|
||||
FE_CAN_QAM_32 |
|
||||
FE_CAN_QAM_64 |
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/string.h>
|
||||
|
|
|
@ -40,7 +40,6 @@
|
|||
#include <linux/smp_lock.h>
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/fcntl.h>
|
||||
|
@ -1543,7 +1542,7 @@ static int get_firmware(struct av7110* av7110)
|
|||
}
|
||||
|
||||
/* check if the firmware is available */
|
||||
av7110->bin_fw = (unsigned char *) vmalloc(fw->size);
|
||||
av7110->bin_fw = vmalloc(fw->size);
|
||||
if (NULL == av7110->bin_fw) {
|
||||
dprintk(1, "out of memory\n");
|
||||
release_firmware(fw);
|
||||
|
|
|
@ -978,24 +978,24 @@ static int OSDSetColor(struct av7110 *av7110, u8 color, u8 r, u8 g, u8 b, u8 ble
|
|||
|
||||
static int OSDSetPalette(struct av7110 *av7110, u32 __user * colors, u8 first, u8 last)
|
||||
{
|
||||
int i;
|
||||
int length = last - first + 1;
|
||||
int i;
|
||||
int length = last - first + 1;
|
||||
|
||||
if (length * 4 > DATA_BUFF3_SIZE)
|
||||
return -EINVAL;
|
||||
if (length * 4 > DATA_BUFF3_SIZE)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
u32 color, blend, yuv;
|
||||
for (i = 0; i < length; i++) {
|
||||
u32 color, blend, yuv;
|
||||
|
||||
if (get_user(color, colors + i))
|
||||
return -EFAULT;
|
||||
blend = (color & 0xF0000000) >> 4;
|
||||
yuv = blend ? RGB2YUV(color & 0xFF, (color >> 8) & 0xFF,
|
||||
if (get_user(color, colors + i))
|
||||
return -EFAULT;
|
||||
blend = (color & 0xF0000000) >> 4;
|
||||
yuv = blend ? RGB2YUV(color & 0xFF, (color >> 8) & 0xFF,
|
||||
(color >> 16) & 0xFF) | blend : 0;
|
||||
yuv = ((yuv & 0xFFFF0000) >> 16) | ((yuv & 0x0000FFFF) << 16);
|
||||
wdebi(av7110, DEBINOSWAP, DATA_BUFF3_BASE + i * 4, yuv, 4);
|
||||
}
|
||||
return av7110_fw_cmd(av7110, COMTYPE_OSD, Set_Palette, 4,
|
||||
yuv = ((yuv & 0xFFFF0000) >> 16) | ((yuv & 0x0000FFFF) << 16);
|
||||
wdebi(av7110, DEBINOSWAP, DATA_BUFF3_BASE + i * 4, yuv, 4);
|
||||
}
|
||||
return av7110_fw_cmd(av7110, COMTYPE_OSD, Set_Palette, 4,
|
||||
av7110->osdwin,
|
||||
bpp2pal[av7110->osdbpp[av7110->osdwin]],
|
||||
first, last);
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
#include <linux/types.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <asm/bitops.h>
|
||||
|
@ -280,7 +279,7 @@ static int av7110_ir_write_proc(struct file *file, const char __user *buffer,
|
|||
if (count < size)
|
||||
return -EINVAL;
|
||||
|
||||
page = (char *) vmalloc(size);
|
||||
page = vmalloc(size);
|
||||
if (!page)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
|
@ -129,23 +129,25 @@ static struct v4l2_input inputs[4] = {
|
|||
|
||||
static int ves1820_writereg(struct saa7146_dev *dev, u8 addr, u8 reg, u8 data)
|
||||
{
|
||||
struct av7110 *av7110 = dev->ext_priv;
|
||||
u8 buf[] = { 0x00, reg, data };
|
||||
struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = buf, .len = 3 };
|
||||
|
||||
dprintk(4, "dev: %p\n", dev);
|
||||
|
||||
if (1 != saa7146_i2c_transfer(dev, &msg, 1, 1))
|
||||
if (1 != i2c_transfer(&av7110->i2c_adap, &msg, 1))
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tuner_write(struct saa7146_dev *dev, u8 addr, u8 data [4])
|
||||
{
|
||||
struct av7110 *av7110 = dev->ext_priv;
|
||||
struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = data, .len = 4 };
|
||||
|
||||
dprintk(4, "dev: %p\n", dev);
|
||||
|
||||
if (1 != saa7146_i2c_transfer(dev, &msg, 1, 1))
|
||||
if (1 != i2c_transfer(&av7110->i2c_adap, &msg, 1))
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1232,7 +1232,7 @@ static struct saa7146_ext_vv vv_data = {
|
|||
.capabilities = 0, // perhaps later: V4L2_CAP_VBI_CAPTURE, but that need tweaking with the saa7113
|
||||
.flags = 0,
|
||||
.stds = &standard[0],
|
||||
.num_stds = sizeof(standard) / sizeof(struct saa7146_standard),
|
||||
.num_stds = ARRAY_SIZE(standard),
|
||||
.ioctls = &ioctls[0],
|
||||
.ioctl = av_ioctl,
|
||||
};
|
||||
|
|
|
@ -214,7 +214,6 @@ static int msp430_ir_init(struct budget_ci *budget_ci)
|
|||
case 0x100f:
|
||||
case 0x1011:
|
||||
case 0x1012:
|
||||
case 0x1017:
|
||||
/* The hauppauge keymap is a superset of these remotes */
|
||||
ir_input_init(input_dev, &budget_ci->ir.state,
|
||||
IR_TYPE_RC5, ir_codes_hauppauge_new);
|
||||
|
@ -225,6 +224,7 @@ static int msp430_ir_init(struct budget_ci *budget_ci)
|
|||
budget_ci->ir.rc5_device = rc5_device;
|
||||
break;
|
||||
case 0x1010:
|
||||
case 0x1017:
|
||||
/* for the Technotrend 1500 bundled remote */
|
||||
ir_input_init(input_dev, &budget_ci->ir.state,
|
||||
IR_TYPE_RC5, ir_codes_tt_1500);
|
||||
|
|
|
@ -34,7 +34,6 @@
|
|||
* the project's page is at http://www.linuxtv.org/dvb/
|
||||
*/
|
||||
|
||||
#include <linux/moduleparam.h>
|
||||
|
||||
#include "budget.h"
|
||||
#include "ttpci-eeprom.h"
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/usb.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/time.h>
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
|
||||
#include <linux/list.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
|
|
@ -111,11 +111,16 @@ config RADIO_AZTECH_PORT
|
|||
jumper sets the card to 0x358.
|
||||
|
||||
config RADIO_GEMTEK
|
||||
tristate "GemTek Radio Card support"
|
||||
tristate "GemTek Radio card (or compatible) support"
|
||||
depends on ISA && VIDEO_V4L2
|
||||
---help---
|
||||
Choose Y here if you have this FM radio card, and then fill in the
|
||||
port address below.
|
||||
I/O port address and settings below. The following cards either have
|
||||
GemTek Radio tuner or are rebranded GemTek Radio cards:
|
||||
|
||||
- Sound Vision 16 Gold with FM Radio
|
||||
- Typhoon Radio card (some models)
|
||||
- Hama Radio card
|
||||
|
||||
In order to control your radio card, you will need to use programs
|
||||
that are compatible with the Video For Linux API. Information on
|
||||
|
@ -126,14 +131,25 @@ config RADIO_GEMTEK
|
|||
module will be called radio-gemtek.
|
||||
|
||||
config RADIO_GEMTEK_PORT
|
||||
hex "GemTek i/o port (0x20c, 0x30c, 0x24c or 0x34c)"
|
||||
hex "Fixed I/O port (0x20c, 0x30c, 0x24c, 0x34c, 0c24c or 0x28c)"
|
||||
depends on RADIO_GEMTEK=y
|
||||
default "34c"
|
||||
help
|
||||
Enter either 0x20c, 0x30c, 0x24c or 0x34c here. The card default is
|
||||
0x34c, if you haven't changed the jumper setting on the card. On
|
||||
Sound Vision 16 Gold PnP with FM Radio (ESS1869+FM Gemtek), the I/O
|
||||
port is 0x28c.
|
||||
port is 0x20c, 0x248 or 0x28c.
|
||||
If automatic I/O port probing is enabled this port will be used only
|
||||
in case of automatic probing failure, ie. as a fallback.
|
||||
|
||||
config RADIO_GEMTEK_PROBE
|
||||
bool "Automatic I/O port probing"
|
||||
depends on RADIO_GEMTEK=y
|
||||
default y
|
||||
help
|
||||
Say Y here to enable automatic probing for GemTek Radio card. The
|
||||
following ports will be probed: 0x20c, 0x30c, 0x24c, 0x34c, 0x248 and
|
||||
0x28c.
|
||||
|
||||
config RADIO_GEMTEK_PCI
|
||||
tristate "GemTek PCI Radio Card support"
|
||||
|
|
|
@ -26,143 +26,383 @@
|
|||
#include <media/v4l2-common.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#include <linux/version.h> /* for KERNEL_VERSION MACRO */
|
||||
#define RADIO_VERSION KERNEL_VERSION(0,0,2)
|
||||
#include <linux/version.h> /* for KERNEL_VERSION MACRO */
|
||||
#define RADIO_VERSION KERNEL_VERSION(0,0,3)
|
||||
#define RADIO_BANNER "GemTek Radio card driver: v0.0.3"
|
||||
|
||||
static struct v4l2_queryctrl radio_qctrl[] = {
|
||||
{
|
||||
.id = V4L2_CID_AUDIO_MUTE,
|
||||
.name = "Mute",
|
||||
.minimum = 0,
|
||||
.maximum = 1,
|
||||
.default_value = 1,
|
||||
.type = V4L2_CTRL_TYPE_BOOLEAN,
|
||||
},{
|
||||
.id = V4L2_CID_AUDIO_VOLUME,
|
||||
.name = "Volume",
|
||||
.minimum = 0,
|
||||
.maximum = 65535,
|
||||
.step = 65535,
|
||||
.default_value = 0xff,
|
||||
.type = V4L2_CTRL_TYPE_INTEGER,
|
||||
}
|
||||
};
|
||||
/*
|
||||
* Module info.
|
||||
*/
|
||||
|
||||
MODULE_AUTHOR("Jonas Munsin, Pekka Seppänen <pexu@kapsi.fi>");
|
||||
MODULE_DESCRIPTION("A driver for the GemTek Radio card.");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
/*
|
||||
* Module params.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_RADIO_GEMTEK_PORT
|
||||
#define CONFIG_RADIO_GEMTEK_PORT -1
|
||||
#endif
|
||||
#ifndef CONFIG_RADIO_GEMTEK_PROBE
|
||||
#define CONFIG_RADIO_GEMTEK_PROBE 1
|
||||
#endif
|
||||
|
||||
static int io = CONFIG_RADIO_GEMTEK_PORT;
|
||||
static int radio_nr = -1;
|
||||
static spinlock_t lock;
|
||||
static int io = CONFIG_RADIO_GEMTEK_PORT;
|
||||
static int probe = CONFIG_RADIO_GEMTEK_PROBE;
|
||||
static int hardmute;
|
||||
static int shutdown = 1;
|
||||
static int keepmuted = 1;
|
||||
static int initmute = 1;
|
||||
static int radio_nr = -1;
|
||||
|
||||
struct gemtek_device
|
||||
{
|
||||
int port;
|
||||
unsigned long curfreq;
|
||||
module_param(io, int, 0444);
|
||||
MODULE_PARM_DESC(io, "Force I/O port for the GemTek Radio card if automatic"
|
||||
"probing is disabled or fails. The most common I/O ports are: 0x20c "
|
||||
"0x30c, 0x24c or 0x34c (0x20c, 0x248 and 0x28c have been reported to "
|
||||
" work for the combined sound/radiocard).");
|
||||
|
||||
module_param(probe, bool, 0444);
|
||||
MODULE_PARM_DESC(probe, "Enable automatic device probing. Note: only the most "
|
||||
"common I/O ports used by the card are probed.");
|
||||
|
||||
module_param(hardmute, bool, 0644);
|
||||
MODULE_PARM_DESC(hardmute, "Enable `hard muting' by shutting down PLL, may "
|
||||
"reduce static noise.");
|
||||
|
||||
module_param(shutdown, bool, 0644);
|
||||
MODULE_PARM_DESC(shutdown, "Enable shutting down PLL and muting line when "
|
||||
"module is unloaded.");
|
||||
|
||||
module_param(keepmuted, bool, 0644);
|
||||
MODULE_PARM_DESC(keepmuted, "Keep card muted even when frequency is changed.");
|
||||
|
||||
module_param(initmute, bool, 0444);
|
||||
MODULE_PARM_DESC(initmute, "Mute card when module is loaded.");
|
||||
|
||||
module_param(radio_nr, int, 0444);
|
||||
|
||||
/*
|
||||
* Functions for controlling the card.
|
||||
*/
|
||||
#define GEMTEK_LOWFREQ (87*16000)
|
||||
#define GEMTEK_HIGHFREQ (108*16000)
|
||||
|
||||
/*
|
||||
* Frequency calculation constants. Intermediate frequency 10.52 MHz (nominal
|
||||
* value 10.7 MHz), reference divisor 6.39 kHz (nominal 6.25 kHz).
|
||||
*/
|
||||
#define FSCALE 8
|
||||
#define IF_OFFSET ((unsigned int)(10.52 * 16000 * (1<<FSCALE)))
|
||||
#define REF_FREQ ((unsigned int)(6.39 * 16 * (1<<FSCALE)))
|
||||
|
||||
#define GEMTEK_CK 0x01 /* Clock signal */
|
||||
#define GEMTEK_DA 0x02 /* Serial data */
|
||||
#define GEMTEK_CE 0x04 /* Chip enable */
|
||||
#define GEMTEK_NS 0x08 /* No signal */
|
||||
#define GEMTEK_MT 0x10 /* Line mute */
|
||||
#define GEMTEK_STDF_3_125_KHZ 0x01 /* Standard frequency 3.125 kHz */
|
||||
#define GEMTEK_PLL_OFF 0x07 /* PLL off */
|
||||
|
||||
#define BU2614_BUS_SIZE 32 /* BU2614 / BU2614FS bus size */
|
||||
|
||||
#define SHORT_DELAY 5 /* usec */
|
||||
#define LONG_DELAY 75 /* usec */
|
||||
|
||||
struct gemtek_device {
|
||||
unsigned long lastfreq;
|
||||
int muted;
|
||||
u32 bu2614data;
|
||||
};
|
||||
|
||||
#define BU2614_FREQ_BITS 16 /* D0..D15, Frequency data */
|
||||
#define BU2614_PORT_BITS 3 /* P0..P2, Output port control data */
|
||||
#define BU2614_VOID_BITS 4 /* unused */
|
||||
#define BU2614_FMES_BITS 1 /* CT, Frequency measurement beginning data */
|
||||
#define BU2614_STDF_BITS 3 /* R0..R2, Standard frequency data */
|
||||
#define BU2614_SWIN_BITS 1 /* S, Switch between FMIN / AMIN */
|
||||
#define BU2614_SWAL_BITS 1 /* PS, Swallow counter division (AMIN only)*/
|
||||
#define BU2614_VOID2_BITS 1 /* unused */
|
||||
#define BU2614_FMUN_BITS 1 /* GT, Frequency measurement time & unlock */
|
||||
#define BU2614_TEST_BITS 1 /* TS, Test data is input */
|
||||
|
||||
/* local things */
|
||||
#define BU2614_FREQ_SHIFT 0
|
||||
#define BU2614_PORT_SHIFT (BU2614_FREQ_BITS + BU2614_FREQ_SHIFT)
|
||||
#define BU2614_VOID_SHIFT (BU2614_PORT_BITS + BU2614_PORT_SHIFT)
|
||||
#define BU2614_FMES_SHIFT (BU2614_VOID_BITS + BU2614_VOID_SHIFT)
|
||||
#define BU2614_STDF_SHIFT (BU2614_FMES_BITS + BU2614_FMES_SHIFT)
|
||||
#define BU2614_SWIN_SHIFT (BU2614_STDF_BITS + BU2614_STDF_SHIFT)
|
||||
#define BU2614_SWAL_SHIFT (BU2614_SWIN_BITS + BU2614_SWIN_SHIFT)
|
||||
#define BU2614_VOID2_SHIFT (BU2614_SWAL_BITS + BU2614_SWAL_SHIFT)
|
||||
#define BU2614_FMUN_SHIFT (BU2614_VOID2_BITS + BU2614_VOID2_SHIFT)
|
||||
#define BU2614_TEST_SHIFT (BU2614_FMUN_BITS + BU2614_FMUN_SHIFT)
|
||||
|
||||
/* the correct way to mute the gemtek may be to write the last written
|
||||
* frequency || 0x10, but just writing 0x10 once seems to do it as well
|
||||
#define MKMASK(field) (((1<<BU2614_##field##_BITS) - 1) << \
|
||||
BU2614_##field##_SHIFT)
|
||||
#define BU2614_PORT_MASK MKMASK(PORT)
|
||||
#define BU2614_FREQ_MASK MKMASK(FREQ)
|
||||
#define BU2614_VOID_MASK MKMASK(VOID)
|
||||
#define BU2614_FMES_MASK MKMASK(FMES)
|
||||
#define BU2614_STDF_MASK MKMASK(STDF)
|
||||
#define BU2614_SWIN_MASK MKMASK(SWIN)
|
||||
#define BU2614_SWAL_MASK MKMASK(SWAL)
|
||||
#define BU2614_VOID2_MASK MKMASK(VOID2)
|
||||
#define BU2614_FMUN_MASK MKMASK(FMUN)
|
||||
#define BU2614_TEST_MASK MKMASK(TEST)
|
||||
|
||||
static struct gemtek_device gemtek_unit;
|
||||
|
||||
static spinlock_t lock;
|
||||
|
||||
/*
|
||||
* Set data which will be sent to BU2614FS.
|
||||
*/
|
||||
#define gemtek_bu2614_set(dev, field, data) ((dev)->bu2614data = \
|
||||
((dev)->bu2614data & ~field##_MASK) | ((data) << field##_SHIFT))
|
||||
|
||||
/*
|
||||
* Transmit settings to BU2614FS over GemTek IC.
|
||||
*/
|
||||
static void gemtek_bu2614_transmit(struct gemtek_device *dev)
|
||||
{
|
||||
int i, bit, q, mute;
|
||||
|
||||
spin_lock(&lock);
|
||||
|
||||
mute = dev->muted ? GEMTEK_MT : 0x00;
|
||||
|
||||
outb_p(mute | GEMTEK_DA | GEMTEK_CK, io);
|
||||
udelay(SHORT_DELAY);
|
||||
outb_p(mute | GEMTEK_CE | GEMTEK_DA | GEMTEK_CK, io);
|
||||
udelay(LONG_DELAY);
|
||||
|
||||
for (i = 0, q = dev->bu2614data; i < 32; i++, q >>= 1) {
|
||||
bit = (q & 1) ? GEMTEK_DA : 0;
|
||||
outb_p(mute | GEMTEK_CE | bit, io);
|
||||
udelay(SHORT_DELAY);
|
||||
outb_p(mute | GEMTEK_CE | bit | GEMTEK_CK, io);
|
||||
udelay(SHORT_DELAY);
|
||||
}
|
||||
|
||||
outb_p(mute | GEMTEK_DA | GEMTEK_CK, io);
|
||||
udelay(SHORT_DELAY);
|
||||
outb_p(mute | GEMTEK_CE | GEMTEK_DA | GEMTEK_CK, io);
|
||||
udelay(LONG_DELAY);
|
||||
|
||||
spin_unlock(&lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate divisor from FM-frequency for BU2614FS (3.125 KHz STDF expected).
|
||||
*/
|
||||
static unsigned long gemtek_convfreq(unsigned long freq)
|
||||
{
|
||||
return ((freq<<FSCALE) + IF_OFFSET + REF_FREQ/2) / REF_FREQ;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set FM-frequency.
|
||||
*/
|
||||
static void gemtek_setfreq(struct gemtek_device *dev, unsigned long freq)
|
||||
{
|
||||
|
||||
if (keepmuted && hardmute && dev->muted)
|
||||
return;
|
||||
|
||||
if (freq < GEMTEK_LOWFREQ)
|
||||
freq = GEMTEK_LOWFREQ;
|
||||
else if (freq > GEMTEK_HIGHFREQ)
|
||||
freq = GEMTEK_HIGHFREQ;
|
||||
|
||||
dev->lastfreq = freq;
|
||||
dev->muted = 0;
|
||||
|
||||
gemtek_bu2614_set(dev, BU2614_PORT, 0);
|
||||
gemtek_bu2614_set(dev, BU2614_FMES, 0);
|
||||
gemtek_bu2614_set(dev, BU2614_SWIN, 0); /* FM-mode */
|
||||
gemtek_bu2614_set(dev, BU2614_SWAL, 0);
|
||||
gemtek_bu2614_set(dev, BU2614_FMUN, 1); /* GT bit set */
|
||||
gemtek_bu2614_set(dev, BU2614_TEST, 0);
|
||||
|
||||
gemtek_bu2614_set(dev, BU2614_STDF, GEMTEK_STDF_3_125_KHZ);
|
||||
gemtek_bu2614_set(dev, BU2614_FREQ, gemtek_convfreq(freq));
|
||||
|
||||
gemtek_bu2614_transmit(dev);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set mute flag.
|
||||
*/
|
||||
static void gemtek_mute(struct gemtek_device *dev)
|
||||
{
|
||||
if(dev->muted)
|
||||
return;
|
||||
spin_lock(&lock);
|
||||
outb(0x10, io);
|
||||
spin_unlock(&lock);
|
||||
int i;
|
||||
dev->muted = 1;
|
||||
|
||||
if (hardmute) {
|
||||
/* Turn off PLL, disable data output */
|
||||
gemtek_bu2614_set(dev, BU2614_PORT, 0);
|
||||
gemtek_bu2614_set(dev, BU2614_FMES, 0); /* CT bit off */
|
||||
gemtek_bu2614_set(dev, BU2614_SWIN, 0); /* FM-mode */
|
||||
gemtek_bu2614_set(dev, BU2614_SWAL, 0);
|
||||
gemtek_bu2614_set(dev, BU2614_FMUN, 0); /* GT bit off */
|
||||
gemtek_bu2614_set(dev, BU2614_TEST, 0);
|
||||
gemtek_bu2614_set(dev, BU2614_STDF, GEMTEK_PLL_OFF);
|
||||
gemtek_bu2614_set(dev, BU2614_FREQ, 0);
|
||||
gemtek_bu2614_transmit(dev);
|
||||
} else {
|
||||
spin_lock(&lock);
|
||||
|
||||
/* Read bus contents (CE, CK and DA). */
|
||||
i = inb_p(io);
|
||||
/* Write it back with mute flag set. */
|
||||
outb_p((i >> 5) | GEMTEK_MT, io);
|
||||
udelay(SHORT_DELAY);
|
||||
|
||||
spin_unlock(&lock);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Unset mute flag.
|
||||
*/
|
||||
static void gemtek_unmute(struct gemtek_device *dev)
|
||||
{
|
||||
if(dev->muted == 0)
|
||||
return;
|
||||
spin_lock(&lock);
|
||||
outb(0x20, io);
|
||||
spin_unlock(&lock);
|
||||
int i;
|
||||
dev->muted = 0;
|
||||
|
||||
if (hardmute) {
|
||||
/* Turn PLL back on. */
|
||||
gemtek_setfreq(dev, dev->lastfreq);
|
||||
} else {
|
||||
spin_lock(&lock);
|
||||
|
||||
i = inb_p(io);
|
||||
outb_p(i >> 5, io);
|
||||
udelay(SHORT_DELAY);
|
||||
|
||||
spin_unlock(&lock);
|
||||
}
|
||||
}
|
||||
|
||||
static void zero(void)
|
||||
/*
|
||||
* Get signal strength (= stereo status).
|
||||
*/
|
||||
static inline int gemtek_getsigstr(void)
|
||||
{
|
||||
outb_p(0x04, io);
|
||||
udelay(5);
|
||||
outb_p(0x05, io);
|
||||
udelay(5);
|
||||
return inb_p(io) & GEMTEK_NS ? 0 : 1;
|
||||
}
|
||||
|
||||
static void one(void)
|
||||
/*
|
||||
* Check if requested card acts like GemTek Radio card.
|
||||
*/
|
||||
static int gemtek_verify(int port)
|
||||
{
|
||||
outb_p(0x06, io);
|
||||
udelay(5);
|
||||
outb_p(0x07, io);
|
||||
udelay(5);
|
||||
static int verified = -1;
|
||||
int i, q;
|
||||
|
||||
if (verified == port)
|
||||
return 1;
|
||||
|
||||
spin_lock(&lock);
|
||||
|
||||
q = inb_p(port); /* Read bus contents before probing. */
|
||||
/* Try to turn on CE, CK and DA respectively and check if card responds
|
||||
properly. */
|
||||
for (i = 0; i < 3; ++i) {
|
||||
outb_p(1 << i, port);
|
||||
udelay(SHORT_DELAY);
|
||||
|
||||
if ((inb_p(port) & (~GEMTEK_NS)) != (0x17 | (1 << (i + 5)))) {
|
||||
spin_unlock(&lock);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
outb_p(q >> 5, port); /* Write bus contents back. */
|
||||
udelay(SHORT_DELAY);
|
||||
|
||||
spin_unlock(&lock);
|
||||
verified = port;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int gemtek_setfreq(struct gemtek_device *dev, unsigned long freq)
|
||||
/*
|
||||
* Automatic probing for card.
|
||||
*/
|
||||
static int gemtek_probe(void)
|
||||
{
|
||||
int ioports[] = { 0x20c, 0x30c, 0x24c, 0x34c, 0x248, 0x28c };
|
||||
int i;
|
||||
|
||||
/* freq = 78.25*((float)freq/16000.0 + 10.52); */
|
||||
if (!probe) {
|
||||
printk(KERN_INFO "Automatic device probing disabled.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
freq /= 16;
|
||||
freq += 10520;
|
||||
freq *= 7825;
|
||||
freq /= 100000;
|
||||
printk(KERN_INFO "Automatic device probing enabled.\n");
|
||||
|
||||
spin_lock(&lock);
|
||||
for (i = 0; i < ARRAY_SIZE(ioports); ++i) {
|
||||
printk(KERN_INFO "Trying I/O port 0x%x...\n", ioports[i]);
|
||||
|
||||
/* 2 start bits */
|
||||
outb_p(0x03, io);
|
||||
udelay(5);
|
||||
outb_p(0x07, io);
|
||||
udelay(5);
|
||||
if (!request_region(ioports[i], 1, "gemtek-probe")) {
|
||||
printk(KERN_WARNING "I/O port 0x%x busy!\n",
|
||||
ioports[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* 28 frequency bits (lsb first) */
|
||||
for (i = 0; i < 14; i++)
|
||||
if (freq & (1 << i))
|
||||
one();
|
||||
else
|
||||
zero();
|
||||
/* 36 unknown bits */
|
||||
for (i = 0; i < 11; i++)
|
||||
zero();
|
||||
one();
|
||||
for (i = 0; i < 4; i++)
|
||||
zero();
|
||||
one();
|
||||
zero();
|
||||
if (gemtek_verify(ioports[i])) {
|
||||
printk(KERN_INFO "Card found from I/O port "
|
||||
"0x%x!\n", ioports[i]);
|
||||
|
||||
/* 2 end bits */
|
||||
outb_p(0x03, io);
|
||||
udelay(5);
|
||||
outb_p(0x07, io);
|
||||
udelay(5);
|
||||
release_region(ioports[i], 1);
|
||||
|
||||
spin_unlock(&lock);
|
||||
io = ioports[i];
|
||||
return io;
|
||||
}
|
||||
|
||||
return 0;
|
||||
release_region(ioports[i], 1);
|
||||
}
|
||||
|
||||
printk(KERN_ERR "Automatic probing failed!\n");
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int gemtek_getsigstr(struct gemtek_device *dev)
|
||||
{
|
||||
spin_lock(&lock);
|
||||
inb(io);
|
||||
udelay(5);
|
||||
spin_unlock(&lock);
|
||||
if (inb(io) & 8) /* bit set = no signal present */
|
||||
return 0;
|
||||
return 1; /* signal present */
|
||||
}
|
||||
/*
|
||||
* Video 4 Linux stuff.
|
||||
*/
|
||||
|
||||
static int vidioc_querycap(struct file *file, void *priv,
|
||||
struct v4l2_capability *v)
|
||||
static struct v4l2_queryctrl radio_qctrl[] = {
|
||||
{
|
||||
.id = V4L2_CID_AUDIO_MUTE,
|
||||
.name = "Mute",
|
||||
.minimum = 0,
|
||||
.maximum = 1,
|
||||
.default_value = 1,
|
||||
.type = V4L2_CTRL_TYPE_BOOLEAN,
|
||||
}, {
|
||||
.id = V4L2_CID_AUDIO_VOLUME,
|
||||
.name = "Volume",
|
||||
.minimum = 0,
|
||||
.maximum = 65535,
|
||||
.step = 65535,
|
||||
.default_value = 0xff,
|
||||
.type = V4L2_CTRL_TYPE_INTEGER,
|
||||
}
|
||||
};
|
||||
|
||||
static struct file_operations gemtek_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = video_exclusive_open,
|
||||
.release = video_exclusive_release,
|
||||
.ioctl = video_ioctl2,
|
||||
.compat_ioctl = v4l_compat_ioctl32,
|
||||
.llseek = no_llseek
|
||||
};
|
||||
|
||||
static int vidioc_querycap(struct file *file, void *priv,
|
||||
struct v4l2_capability *v)
|
||||
{
|
||||
strlcpy(v->driver, "radio-gemtek", sizeof(v->driver));
|
||||
strlcpy(v->card, "GemTek", sizeof(v->card));
|
||||
|
@ -172,28 +412,29 @@ static int vidioc_querycap(struct file *file, void *priv,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int vidioc_g_tuner(struct file *file, void *priv,
|
||||
struct v4l2_tuner *v)
|
||||
static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v)
|
||||
{
|
||||
struct video_device *dev = video_devdata(file);
|
||||
struct gemtek_device *rt = dev->priv;
|
||||
|
||||
if (v->index > 0)
|
||||
return -EINVAL;
|
||||
|
||||
strcpy(v->name, "FM");
|
||||
v->type = V4L2_TUNER_RADIO;
|
||||
v->rangelow = (87*16000);
|
||||
v->rangehigh = (108*16000);
|
||||
v->rxsubchans = V4L2_TUNER_SUB_MONO;
|
||||
v->capability = V4L2_TUNER_CAP_LOW;
|
||||
v->audmode = V4L2_TUNER_MODE_MONO;
|
||||
v->signal = 0xffff*gemtek_getsigstr(rt);
|
||||
v->rangelow = GEMTEK_LOWFREQ;
|
||||
v->rangehigh = GEMTEK_HIGHFREQ;
|
||||
v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO;
|
||||
v->signal = 0xffff * gemtek_getsigstr();
|
||||
if (v->signal) {
|
||||
v->audmode = V4L2_TUNER_MODE_STEREO;
|
||||
v->rxsubchans = V4L2_TUNER_SUB_STEREO;
|
||||
} else {
|
||||
v->audmode = V4L2_TUNER_MODE_MONO;
|
||||
v->rxsubchans = V4L2_TUNER_SUB_MONO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vidioc_s_tuner(struct file *file, void *priv,
|
||||
struct v4l2_tuner *v)
|
||||
static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *v)
|
||||
{
|
||||
if (v->index > 0)
|
||||
return -EINVAL;
|
||||
|
@ -201,38 +442,35 @@ static int vidioc_s_tuner(struct file *file, void *priv,
|
|||
}
|
||||
|
||||
static int vidioc_s_frequency(struct file *file, void *priv,
|
||||
struct v4l2_frequency *f)
|
||||
struct v4l2_frequency *f)
|
||||
{
|
||||
struct video_device *dev = video_devdata(file);
|
||||
struct gemtek_device *rt = dev->priv;
|
||||
|
||||
rt->curfreq = f->frequency;
|
||||
/* needs to be called twice in order for getsigstr to work */
|
||||
gemtek_setfreq(rt, rt->curfreq);
|
||||
gemtek_setfreq(rt, rt->curfreq);
|
||||
gemtek_setfreq(rt, f->frequency);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vidioc_g_frequency(struct file *file, void *priv,
|
||||
struct v4l2_frequency *f)
|
||||
struct v4l2_frequency *f)
|
||||
{
|
||||
struct video_device *dev = video_devdata(file);
|
||||
struct gemtek_device *rt = dev->priv;
|
||||
|
||||
f->type = V4L2_TUNER_RADIO;
|
||||
f->frequency = rt->curfreq;
|
||||
f->frequency = rt->lastfreq;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vidioc_queryctrl(struct file *file, void *priv,
|
||||
struct v4l2_queryctrl *qc)
|
||||
struct v4l2_queryctrl *qc)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
|
||||
for (i = 0; i < ARRAY_SIZE(radio_qctrl); ++i) {
|
||||
if (qc->id && qc->id == radio_qctrl[i].id) {
|
||||
memcpy(qc, &(radio_qctrl[i]),
|
||||
sizeof(*qc));
|
||||
memcpy(qc, &(radio_qctrl[i]), sizeof(*qc));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -240,7 +478,7 @@ static int vidioc_queryctrl(struct file *file, void *priv,
|
|||
}
|
||||
|
||||
static int vidioc_g_ctrl(struct file *file, void *priv,
|
||||
struct v4l2_control *ctrl)
|
||||
struct v4l2_control *ctrl)
|
||||
{
|
||||
struct video_device *dev = video_devdata(file);
|
||||
struct gemtek_device *rt = dev->priv;
|
||||
|
@ -260,7 +498,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
|
|||
}
|
||||
|
||||
static int vidioc_s_ctrl(struct file *file, void *priv,
|
||||
struct v4l2_control *ctrl)
|
||||
struct v4l2_control *ctrl)
|
||||
{
|
||||
struct video_device *dev = video_devdata(file);
|
||||
struct gemtek_device *rt = dev->priv;
|
||||
|
@ -282,8 +520,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int vidioc_g_audio (struct file *file, void *priv,
|
||||
struct v4l2_audio *a)
|
||||
static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
|
||||
{
|
||||
if (a->index > 1)
|
||||
return -EINVAL;
|
||||
|
@ -306,99 +543,102 @@ static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int vidioc_s_audio(struct file *file, void *priv,
|
||||
struct v4l2_audio *a)
|
||||
static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a)
|
||||
{
|
||||
if (a->index != 0)
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct gemtek_device gemtek_unit;
|
||||
|
||||
static const struct file_operations gemtek_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = video_exclusive_open,
|
||||
.release = video_exclusive_release,
|
||||
.ioctl = video_ioctl2,
|
||||
.compat_ioctl = v4l_compat_ioctl32,
|
||||
.llseek = no_llseek,
|
||||
static struct video_device gemtek_radio = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "GemTek Radio card",
|
||||
.type = VID_TYPE_TUNER,
|
||||
.hardware = VID_HARDWARE_GEMTEK,
|
||||
.fops = &gemtek_fops,
|
||||
.vidioc_querycap = vidioc_querycap,
|
||||
.vidioc_g_tuner = vidioc_g_tuner,
|
||||
.vidioc_s_tuner = vidioc_s_tuner,
|
||||
.vidioc_g_audio = vidioc_g_audio,
|
||||
.vidioc_s_audio = vidioc_s_audio,
|
||||
.vidioc_g_input = vidioc_g_input,
|
||||
.vidioc_s_input = vidioc_s_input,
|
||||
.vidioc_g_frequency = vidioc_g_frequency,
|
||||
.vidioc_s_frequency = vidioc_s_frequency,
|
||||
.vidioc_queryctrl = vidioc_queryctrl,
|
||||
.vidioc_g_ctrl = vidioc_g_ctrl,
|
||||
.vidioc_s_ctrl = vidioc_s_ctrl
|
||||
};
|
||||
|
||||
static struct video_device gemtek_radio=
|
||||
{
|
||||
.owner = THIS_MODULE,
|
||||
.name = "GemTek radio",
|
||||
.type = VID_TYPE_TUNER,
|
||||
.fops = &gemtek_fops,
|
||||
.vidioc_querycap = vidioc_querycap,
|
||||
.vidioc_g_tuner = vidioc_g_tuner,
|
||||
.vidioc_s_tuner = vidioc_s_tuner,
|
||||
.vidioc_g_audio = vidioc_g_audio,
|
||||
.vidioc_s_audio = vidioc_s_audio,
|
||||
.vidioc_g_input = vidioc_g_input,
|
||||
.vidioc_s_input = vidioc_s_input,
|
||||
.vidioc_g_frequency = vidioc_g_frequency,
|
||||
.vidioc_s_frequency = vidioc_s_frequency,
|
||||
.vidioc_queryctrl = vidioc_queryctrl,
|
||||
.vidioc_g_ctrl = vidioc_g_ctrl,
|
||||
.vidioc_s_ctrl = vidioc_s_ctrl,
|
||||
};
|
||||
/*
|
||||
* Initialization / cleanup related stuff.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Initilize card.
|
||||
*/
|
||||
static int __init gemtek_init(void)
|
||||
{
|
||||
if(io==-1)
|
||||
{
|
||||
printk(KERN_ERR "You must set an I/O address with io=0x20c, io=0x30c, io=0x24c or io=0x34c (io=0x020c or io=0x248 for the combined sound/radiocard)\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!request_region(io, 4, "gemtek"))
|
||||
{
|
||||
printk(KERN_ERR "gemtek: port 0x%x already in use\n", io);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
gemtek_radio.priv=&gemtek_unit;
|
||||
|
||||
if(video_register_device(&gemtek_radio, VFL_TYPE_RADIO, radio_nr)==-1)
|
||||
{
|
||||
release_region(io, 4);
|
||||
return -EINVAL;
|
||||
}
|
||||
printk(KERN_INFO "GemTek Radio Card driver.\n");
|
||||
printk(KERN_INFO RADIO_BANNER "\n");
|
||||
|
||||
spin_lock_init(&lock);
|
||||
|
||||
/* this is _maybe_ unnecessary */
|
||||
outb(0x01, io);
|
||||
gemtek_probe();
|
||||
if (io) {
|
||||
if (!request_region(io, 1, "gemtek")) {
|
||||
printk(KERN_ERR "I/O port 0x%x already in use.\n", io);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
/* mute card - prevents noisy bootups */
|
||||
gemtek_unit.muted = 0;
|
||||
gemtek_mute(&gemtek_unit);
|
||||
if (!gemtek_verify(io))
|
||||
printk(KERN_WARNING "Card at I/O port 0x%x does not "
|
||||
"respond properly, check your "
|
||||
"configuration.\n", io);
|
||||
else
|
||||
printk(KERN_INFO "Using I/O port 0x%x.\n", io);
|
||||
} else if (probe) {
|
||||
printk(KERN_ERR "Automatic probing failed and no "
|
||||
"fixed I/O port defined.\n");
|
||||
return -ENODEV;
|
||||
} else {
|
||||
printk(KERN_ERR "Automatic probing disabled but no fixed "
|
||||
"I/O port defined.");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
gemtek_radio.priv = &gemtek_unit;
|
||||
|
||||
if (video_register_device(&gemtek_radio, VFL_TYPE_RADIO,
|
||||
radio_nr) == -1) {
|
||||
release_region(io, 1);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
/* Set defaults */
|
||||
gemtek_unit.lastfreq = GEMTEK_LOWFREQ;
|
||||
gemtek_unit.bu2614data = 0;
|
||||
|
||||
if (initmute)
|
||||
gemtek_mute(&gemtek_unit);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
MODULE_AUTHOR("Jonas Munsin");
|
||||
MODULE_DESCRIPTION("A driver for the GemTek Radio Card");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
module_param(io, int, 0);
|
||||
MODULE_PARM_DESC(io, "I/O address of the GemTek card (0x20c, 0x30c, 0x24c or 0x34c (0x20c or 0x248 have been reported to work for the combined sound/radiocard)).");
|
||||
module_param(radio_nr, int, 0);
|
||||
|
||||
static void __exit gemtek_cleanup(void)
|
||||
/*
|
||||
* Module cleanup
|
||||
*/
|
||||
static void __exit gemtek_exit(void)
|
||||
{
|
||||
if (shutdown) {
|
||||
hardmute = 1; /* Turn off PLL */
|
||||
gemtek_mute(&gemtek_unit);
|
||||
} else {
|
||||
printk(KERN_INFO "Module unloaded but card not muted!\n");
|
||||
}
|
||||
|
||||
video_unregister_device(&gemtek_radio);
|
||||
release_region(io,4);
|
||||
release_region(io, 1);
|
||||
}
|
||||
|
||||
module_init(gemtek_init);
|
||||
module_exit(gemtek_cleanup);
|
||||
|
||||
/*
|
||||
Local variables:
|
||||
compile-command: "gcc -c -DMODVERSIONS -D__KERNEL__ -DMODULE -O6 -Wall -Wstrict-prototypes -I /home/blp/tmp/linux-2.1.111-rtrack/include radio-rtrack2.c"
|
||||
End:
|
||||
*/
|
||||
module_exit(gemtek_exit);
|
||||
|
|
|
@ -173,7 +173,7 @@ static int tt_setfreq(struct tt_device *dev, unsigned long freq1)
|
|||
i--;
|
||||
p--;
|
||||
temp = temp/2;
|
||||
}
|
||||
}
|
||||
|
||||
spin_lock(&lock);
|
||||
|
||||
|
|
|
@ -148,6 +148,15 @@ config VIDEO_WM8739
|
|||
To compile this driver as a module, choose M here: the
|
||||
module will be called wm8739.
|
||||
|
||||
config VIDEO_VP27SMPX
|
||||
tristate "Panasonic VP27s internal MPX"
|
||||
depends on VIDEO_V4L2 && I2C && EXPERIMENTAL
|
||||
---help---
|
||||
Support for the internal MPX of the Panasonic VP27s tuner.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called vp27smpx.
|
||||
|
||||
comment "Video decoders"
|
||||
|
||||
config VIDEO_BT819
|
||||
|
@ -197,6 +206,13 @@ config VIDEO_OV7670
|
|||
OV7670 VGA camera. It currently only works with the M88ALP01
|
||||
controller.
|
||||
|
||||
config VIDEO_TCM825X
|
||||
tristate "TCM825x camera sensor support"
|
||||
depends on I2C && VIDEO_V4L2
|
||||
---help---
|
||||
This is a driver for the Toshiba TCM825x VGA camera sensor.
|
||||
It is used for example in Nokia N800.
|
||||
|
||||
config VIDEO_SAA7110
|
||||
tristate "Philips SAA7110 video decoder"
|
||||
depends on VIDEO_V4L1 && I2C
|
||||
|
@ -348,7 +364,7 @@ endmenu # encoder / decoder chips
|
|||
config VIDEO_VIVI
|
||||
tristate "Virtual Video Driver"
|
||||
depends on VIDEO_V4L2 && !SPARC32 && !SPARC64 && PCI
|
||||
select VIDEO_BUF
|
||||
select VIDEOBUF_VMALLOC
|
||||
default n
|
||||
---help---
|
||||
Enables a virtual video driver. This device shows a color bar
|
||||
|
@ -489,15 +505,6 @@ config TUNER_3036
|
|||
Say Y here to include support for Philips SAB3036 compatible tuners.
|
||||
If in doubt, say N.
|
||||
|
||||
config TUNER_TEA5761
|
||||
bool "TEA 5761 radio tuner (EXPERIMENTAL)"
|
||||
depends on EXPERIMENTAL
|
||||
depends on I2C
|
||||
select VIDEO_TUNER
|
||||
help
|
||||
Say Y here to include support for Philips TEA5761 radio tuner.
|
||||
If in doubt, say N.
|
||||
|
||||
config VIDEO_VINO
|
||||
tristate "SGI Vino Video For Linux (EXPERIMENTAL)"
|
||||
depends on I2C && SGI_IP22 && EXPERIMENTAL && VIDEO_V4L2
|
||||
|
@ -661,6 +668,8 @@ config VIDEO_HEXIUM_GEMINI
|
|||
|
||||
source "drivers/media/video/cx88/Kconfig"
|
||||
|
||||
source "drivers/media/video/cx23885/Kconfig"
|
||||
|
||||
source "drivers/media/video/ivtv/Kconfig"
|
||||
|
||||
config VIDEO_M32R_AR
|
||||
|
|
|
@ -4,14 +4,12 @@
|
|||
|
||||
zr36067-objs := zoran_procfs.o zoran_device.o \
|
||||
zoran_driver.o zoran_card.o
|
||||
tuner-objs := tuner-core.o tuner-types.o tuner-simple.o \
|
||||
mt20xx.o tda8290.o tea5767.o tda9887.o
|
||||
|
||||
tuner-$(CONFIG_TUNER_TEA5761) += tea5761.o
|
||||
tuner-objs := tuner-core.o tuner-types.o tda9887.o
|
||||
|
||||
msp3400-objs := msp3400-driver.o msp3400-kthreads.o
|
||||
|
||||
obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-common.o compat_ioctl32.o
|
||||
obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-common.o compat_ioctl32.o \
|
||||
v4l2-int-device.o
|
||||
|
||||
ifeq ($(CONFIG_VIDEO_V4L1_COMPAT),y)
|
||||
obj-$(CONFIG_VIDEO_DEV) += v4l1-compat.o
|
||||
|
@ -63,7 +61,6 @@ obj-$(CONFIG_VIDEO_CPIA_USB) += cpia_usb.o
|
|||
obj-$(CONFIG_VIDEO_MEYE) += meye.o
|
||||
obj-$(CONFIG_VIDEO_SAA7134) += saa7134/
|
||||
obj-$(CONFIG_VIDEO_CX88) += cx88/
|
||||
obj-$(CONFIG_VIDEO_IVTV) += ivtv/
|
||||
obj-$(CONFIG_VIDEO_EM28XX) += em28xx/
|
||||
obj-$(CONFIG_VIDEO_USBVISION) += usbvision/
|
||||
obj-$(CONFIG_VIDEO_TVP5150) += tvp5150.o
|
||||
|
@ -73,6 +70,7 @@ obj-$(CONFIG_VIDEO_CS53L32A) += cs53l32a.o
|
|||
obj-$(CONFIG_VIDEO_TLV320AIC23B) += tlv320aic23b.o
|
||||
obj-$(CONFIG_VIDEO_WM8775) += wm8775.o
|
||||
obj-$(CONFIG_VIDEO_WM8739) += wm8739.o
|
||||
obj-$(CONFIG_VIDEO_VP27SMPX) += vp27smpx.o
|
||||
obj-$(CONFIG_VIDEO_OVCAMCHIP) += ovcamchip/
|
||||
obj-$(CONFIG_VIDEO_CPIA2) += cpia2/
|
||||
obj-$(CONFIG_VIDEO_MXB) += mxb.o
|
||||
|
@ -82,8 +80,17 @@ obj-$(CONFIG_VIDEO_DPC) += dpc7146.o
|
|||
obj-$(CONFIG_TUNER_3036) += tuner-3036.o
|
||||
|
||||
obj-$(CONFIG_VIDEO_TUNER) += tuner.o
|
||||
obj-$(CONFIG_VIDEO_BUF) += video-buf.o
|
||||
obj-$(CONFIG_VIDEO_BUF_DVB) += video-buf-dvb.o
|
||||
|
||||
obj-$(CONFIG_TUNER_SIMPLE) += tuner-simple.o
|
||||
obj-$(CONFIG_TUNER_MT20XX) += mt20xx.o
|
||||
obj-$(CONFIG_TUNER_TDA8290) += tda8290.o
|
||||
obj-$(CONFIG_TUNER_TEA5767) += tea5767.o
|
||||
obj-$(CONFIG_TUNER_TEA5761) += tea5761.o
|
||||
|
||||
obj-$(CONFIG_VIDEOBUF_GEN) += videobuf-core.o
|
||||
obj-$(CONFIG_VIDEOBUF_DMA_SG) += videobuf-dma-sg.o
|
||||
obj-$(CONFIG_VIDEOBUF_VMALLOC) += videobuf-vmalloc.o
|
||||
obj-$(CONFIG_VIDEOBUF_DVB) += videobuf-dvb.o
|
||||
obj-$(CONFIG_VIDEO_BTCX) += btcx-risc.o
|
||||
obj-$(CONFIG_VIDEO_TVEEPROM) += tveeprom.o
|
||||
|
||||
|
@ -97,6 +104,8 @@ obj-$(CONFIG_VIDEO_CX2341X) += cx2341x.o
|
|||
obj-$(CONFIG_VIDEO_CAFE_CCIC) += cafe_ccic.o
|
||||
obj-$(CONFIG_VIDEO_OV7670) += ov7670.o
|
||||
|
||||
obj-$(CONFIG_VIDEO_TCM825X) += tcm825x.o
|
||||
|
||||
obj-$(CONFIG_USB_DABUSB) += dabusb.o
|
||||
obj-$(CONFIG_USB_OV511) += ov511.o
|
||||
obj-$(CONFIG_USB_SE401) += se401.o
|
||||
|
@ -114,6 +123,9 @@ obj-$(CONFIG_USB_KONICAWC) += usbvideo/
|
|||
obj-$(CONFIG_USB_VICAM) += usbvideo/
|
||||
obj-$(CONFIG_USB_QUICKCAM_MESSENGER) += usbvideo/
|
||||
|
||||
obj-$(CONFIG_VIDEO_IVTV) += ivtv/
|
||||
|
||||
obj-$(CONFIG_VIDEO_VIVI) += vivi.o
|
||||
obj-$(CONFIG_VIDEO_CX23885) += cx23885/
|
||||
|
||||
EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
#include <linux/delay.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/mm.h>
|
||||
|
@ -442,7 +441,7 @@ static int ar_do_ioctl(struct inode *inode, struct file *file,
|
|||
{
|
||||
struct video_window *w = arg;
|
||||
DEBUG(1, "VIDIOCGWIN:\n");
|
||||
memset(w, 0, sizeof(w));
|
||||
memset(w, 0, sizeof(*w));
|
||||
w->width = ar->width;
|
||||
w->height = ar->height;
|
||||
return 0;
|
||||
|
|
|
@ -4,7 +4,7 @@ config VIDEO_BT848
|
|||
select I2C_ALGOBIT
|
||||
select FW_LOADER
|
||||
select VIDEO_BTCX
|
||||
select VIDEO_BUF
|
||||
select VIDEOBUF_DMA_SG
|
||||
select VIDEO_IR
|
||||
select VIDEO_TUNER
|
||||
select VIDEO_TVEEPROM
|
||||
|
|
|
@ -27,7 +27,6 @@
|
|||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/kmod.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/pci.h>
|
||||
|
@ -2989,6 +2988,23 @@ struct tvcard bttv_tvcards[] = {
|
|||
.no_tda9875 = 1,
|
||||
.no_tda7432 = 1,
|
||||
},
|
||||
/* ---- card 0x95---------------------------------- */
|
||||
[BTTV_BOARD_TYPHOON_TVTUNERPCI] = {
|
||||
.name = "Typhoon TV-Tuner PCI (50684)",
|
||||
.video_inputs = 3,
|
||||
.audio_inputs = 1,
|
||||
.tuner = 0,
|
||||
.svhs = 2,
|
||||
.gpiomask = 0x3014f,
|
||||
.muxsel = { 2, 3, 1, 1 },
|
||||
.gpiomux = { 0x20001,0x10001, 0, 0 },
|
||||
.gpiomute = 10,
|
||||
.needs_tvaudio = 1,
|
||||
.pll = PLL_28,
|
||||
.tuner_type = TUNER_PHILIPS_PAL_I,
|
||||
.tuner_addr = ADDR_UNSET,
|
||||
.radio_addr = ADDR_UNSET,
|
||||
},
|
||||
};
|
||||
|
||||
static const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards);
|
||||
|
@ -3276,15 +3292,15 @@ static void eagle_muxsel(struct bttv *btv, unsigned int input)
|
|||
btaor((2)<<5, ~(3<<5), BT848_IFORM);
|
||||
gpio_bits(3,bttv_tvcards[btv->c.type].muxsel[input&7]);
|
||||
|
||||
/* composite */
|
||||
/* set chroma ADC to sleep */
|
||||
btor(BT848_ADC_C_SLEEP, BT848_ADC);
|
||||
/* set to composite video */
|
||||
btand(~BT848_CONTROL_COMP, BT848_E_CONTROL);
|
||||
btand(~BT848_CONTROL_COMP, BT848_O_CONTROL);
|
||||
/* composite */
|
||||
/* set chroma ADC to sleep */
|
||||
btor(BT848_ADC_C_SLEEP, BT848_ADC);
|
||||
/* set to composite video */
|
||||
btand(~BT848_CONTROL_COMP, BT848_E_CONTROL);
|
||||
btand(~BT848_CONTROL_COMP, BT848_O_CONTROL);
|
||||
|
||||
/* switch sync drive off */
|
||||
gpio_bits(LM1882_SYNC_DRIVE,LM1882_SYNC_DRIVE);
|
||||
/* switch sync drive off */
|
||||
gpio_bits(LM1882_SYNC_DRIVE,LM1882_SYNC_DRIVE);
|
||||
}
|
||||
|
||||
static void gvc1100_muxsel(struct bttv *btv, unsigned int input)
|
||||
|
@ -3453,7 +3469,7 @@ void __devinit bttv_init_card2(struct bttv *btv)
|
|||
printk("bttv%d: radio detected by subsystem id (CPH05x)\n",btv->c.nr);
|
||||
}
|
||||
break;
|
||||
case BTTV_BOARD_STB2:
|
||||
case BTTV_BOARD_STB2:
|
||||
if (btv->cardid == 0x3060121a) {
|
||||
/* Fix up entry for 3DFX VoodooTV 100,
|
||||
which is an OEM STB card variant. */
|
||||
|
@ -3784,7 +3800,7 @@ static void __devinit osprey_eeprom(struct bttv *btv, const u8 ee[256])
|
|||
for (i = 12; i < 21; i++)
|
||||
serial *= 10, serial += ee[i] - '0';
|
||||
}
|
||||
} else {
|
||||
} else {
|
||||
unsigned short type;
|
||||
|
||||
for (i = 4*16; i < 8*16; i += 16) {
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/fs.h>
|
||||
|
@ -155,13 +154,14 @@ MODULE_LICENSE("GPL");
|
|||
/* ----------------------------------------------------------------------- */
|
||||
/* sysfs */
|
||||
|
||||
static ssize_t show_card(struct class_device *cd, char *buf)
|
||||
static ssize_t show_card(struct device *cd,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct video_device *vfd = to_video_device(cd);
|
||||
struct bttv *btv = dev_get_drvdata(vfd->dev);
|
||||
return sprintf(buf, "%d\n", btv ? btv->c.type : UNSET);
|
||||
}
|
||||
static CLASS_DEVICE_ATTR(card, S_IRUGO, show_card, NULL);
|
||||
static DEVICE_ATTR(card, S_IRUGO, show_card, NULL);
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
/* dvb auto-load setup */
|
||||
|
@ -2583,7 +2583,7 @@ static int setup_window(struct bttv_fh *fh, struct bttv *btv,
|
|||
if (check_btres(fh, RESOURCE_OVERLAY)) {
|
||||
struct bttv_buffer *new;
|
||||
|
||||
new = videobuf_alloc(sizeof(*new));
|
||||
new = videobuf_pci_alloc(sizeof(*new));
|
||||
new->crop = btv->crop[!!fh->do_crop].rect;
|
||||
bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
|
||||
retval = bttv_switch_overlay(btv,fh,new);
|
||||
|
@ -3049,7 +3049,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
|
|||
mutex_lock(&fh->cap.lock);
|
||||
if (*on) {
|
||||
fh->ov.tvnorm = btv->tvnorm;
|
||||
new = videobuf_alloc(sizeof(*new));
|
||||
new = videobuf_pci_alloc(sizeof(*new));
|
||||
new->crop = btv->crop[!!fh->do_crop].rect;
|
||||
bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
|
||||
} else {
|
||||
|
@ -3072,6 +3072,8 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
|
|||
V4L2_MEMORY_MMAP);
|
||||
if (retval < 0)
|
||||
goto fh_unlock_and_return;
|
||||
|
||||
gbuffers = retval;
|
||||
memset(mbuf,0,sizeof(*mbuf));
|
||||
mbuf->frames = gbuffers;
|
||||
mbuf->size = gbuffers * gbufsize;
|
||||
|
@ -3142,9 +3144,12 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
|
|||
retval = -EIO;
|
||||
/* fall through */
|
||||
case STATE_DONE:
|
||||
videobuf_dma_sync(&fh->cap,&buf->vb.dma);
|
||||
{
|
||||
struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
|
||||
videobuf_dma_sync(&fh->cap,dma);
|
||||
bttv_dma_free(&fh->cap,btv,buf);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
retval = -EINVAL;
|
||||
break;
|
||||
|
@ -3338,7 +3343,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
|
|||
if (check_btres(fh, RESOURCE_OVERLAY)) {
|
||||
struct bttv_buffer *new;
|
||||
|
||||
new = videobuf_alloc(sizeof(*new));
|
||||
new = videobuf_pci_alloc(sizeof(*new));
|
||||
new->crop = btv->crop[!!fh->do_crop].rect;
|
||||
bttv_overlay_risc(btv,&fh->ov,fh->ovfmt,new);
|
||||
retval = bttv_switch_overlay(btv,fh,new);
|
||||
|
@ -3697,7 +3702,7 @@ static unsigned int bttv_poll(struct file *file, poll_table *wait)
|
|||
mutex_unlock(&fh->cap.lock);
|
||||
return POLLERR;
|
||||
}
|
||||
fh->cap.read_buf = videobuf_alloc(fh->cap.msize);
|
||||
fh->cap.read_buf = videobuf_pci_alloc(fh->cap.msize);
|
||||
if (NULL == fh->cap.read_buf) {
|
||||
mutex_unlock(&fh->cap.lock);
|
||||
return POLLERR;
|
||||
|
@ -3764,13 +3769,13 @@ static int bttv_open(struct inode *inode, struct file *file)
|
|||
fh->ov.setup_ok = 0;
|
||||
v4l2_prio_open(&btv->prio,&fh->prio);
|
||||
|
||||
videobuf_queue_init(&fh->cap, &bttv_video_qops,
|
||||
videobuf_queue_pci_init(&fh->cap, &bttv_video_qops,
|
||||
btv->c.pci, &btv->s_lock,
|
||||
V4L2_BUF_TYPE_VIDEO_CAPTURE,
|
||||
V4L2_FIELD_INTERLACED,
|
||||
sizeof(struct bttv_buffer),
|
||||
fh);
|
||||
videobuf_queue_init(&fh->vbi, &bttv_vbi_qops,
|
||||
videobuf_queue_pci_init(&fh->vbi, &bttv_vbi_qops,
|
||||
btv->c.pci, &btv->s_lock,
|
||||
V4L2_BUF_TYPE_VBI_CAPTURE,
|
||||
V4L2_FIELD_SEQ_TB,
|
||||
|
@ -4613,9 +4618,9 @@ static int __devinit bttv_register_video(struct bttv *btv)
|
|||
goto err;
|
||||
printk(KERN_INFO "bttv%d: registered device video%d\n",
|
||||
btv->c.nr,btv->video_dev->minor & 0x1f);
|
||||
if (class_device_create_file(&btv->video_dev->class_dev,
|
||||
&class_device_attr_card)<0) {
|
||||
printk(KERN_ERR "bttv%d: class_device_create_file 'card' "
|
||||
if (device_create_file(&btv->video_dev->class_dev,
|
||||
&dev_attr_card)<0) {
|
||||
printk(KERN_ERR "bttv%d: device_create_file 'card' "
|
||||
"failed\n", btv->c.nr);
|
||||
goto err;
|
||||
}
|
||||
|
|
|
@ -106,11 +106,9 @@ int bttv_sub_add_device(struct bttv_core *core, char *name)
|
|||
|
||||
int bttv_sub_del_devices(struct bttv_core *core)
|
||||
{
|
||||
struct bttv_sub_device *sub;
|
||||
struct list_head *item,*save;
|
||||
struct bttv_sub_device *sub, *save;
|
||||
|
||||
list_for_each_safe(item,save,&core->subs) {
|
||||
sub = list_entry(item,struct bttv_sub_device,list);
|
||||
list_for_each_entry_safe(sub, save, &core->subs, list) {
|
||||
list_del(&sub->list);
|
||||
device_unregister(&sub->dev);
|
||||
}
|
||||
|
|
|
@ -28,7 +28,6 @@
|
|||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue