Commit ce4b50f2 authored by Linus Torvalds's avatar Linus Torvalds

Merge master.kernel.org:/pub/scm/linux/kernel/git/mchehab/v4l-dvb

parents d43da75f 34218e06
...@@ -42,4 +42,4 @@ ...@@ -42,4 +42,4 @@
41 -> Hauppauge WinTV-HVR1100 DVB-T/Hybrid (Low Profile) [0070:9800,0070:9802] 41 -> Hauppauge WinTV-HVR1100 DVB-T/Hybrid (Low Profile) [0070:9800,0070:9802]
42 -> digitalnow DNTV Live! DVB-T Pro [1822:0025] 42 -> digitalnow DNTV Live! DVB-T Pro [1822:0025]
43 -> KWorld/VStream XPert DVB-T with cx22702 [17de:08a1] 43 -> KWorld/VStream XPert DVB-T with cx22702 [17de:08a1]
44 -> DViCO FusionHDTV DVB-T Dual Digital [18ac:db50] 44 -> DViCO FusionHDTV DVB-T Dual Digital [18ac:db50,18ac:db54]
0 -> UNKNOWN/GENERIC 0 -> UNKNOWN/GENERIC
1 -> Proteus Pro [philips reference design] [1131:2001,1131:2001] 1 -> Proteus Pro [philips reference design] [1131:2001,1131:2001]
2 -> LifeView FlyVIDEO3000 [5168:0138,4e42:0138] 2 -> LifeView FlyVIDEO3000 [5168:0138,4e42:0138]
3 -> LifeView FlyVIDEO2000 [5168:0138] 3 -> LifeView/Typhoon FlyVIDEO2000 [5168:0138,4e42:0138]
4 -> EMPRESS [1131:6752] 4 -> EMPRESS [1131:6752]
5 -> SKNet Monster TV [1131:4e85] 5 -> SKNet Monster TV [1131:4e85]
6 -> Tevion MD 9717 6 -> Tevion MD 9717
...@@ -53,12 +53,12 @@ ...@@ -53,12 +53,12 @@
52 -> AverMedia AverTV/305 [1461:2108] 52 -> AverMedia AverTV/305 [1461:2108]
53 -> ASUS TV-FM 7135 [1043:4845] 53 -> ASUS TV-FM 7135 [1043:4845]
54 -> LifeView FlyTV Platinum FM [5168:0214,1489:0214] 54 -> LifeView FlyTV Platinum FM [5168:0214,1489:0214]
55 -> LifeView FlyDVB-T DUO [5168:0502,5168:0306] 55 -> LifeView FlyDVB-T DUO [5168:0306]
56 -> Avermedia AVerTV 307 [1461:a70a] 56 -> Avermedia AVerTV 307 [1461:a70a]
57 -> Avermedia AVerTV GO 007 FM [1461:f31f] 57 -> Avermedia AVerTV GO 007 FM [1461:f31f]
58 -> ADS Tech Instant TV (saa7135) [1421:0350,1421:0351,1421:0370,1421:1370] 58 -> ADS Tech Instant TV (saa7135) [1421:0350,1421:0351,1421:0370,1421:1370]
59 -> Kworld/Tevion V-Stream Xpert TV PVR7134 59 -> Kworld/Tevion V-Stream Xpert TV PVR7134
60 -> Typhoon DVB-T Duo Digital/Analog Cardbus [4e42:0502] 60 -> LifeView/Typhoon FlyDVB-T Duo Cardbus [5168:0502,4e42:0502]
61 -> Philips TOUGH DVB-T reference design [1131:2004] 61 -> Philips TOUGH DVB-T reference design [1131:2004]
62 -> Compro VideoMate TV Gold+II 62 -> Compro VideoMate TV Gold+II
63 -> Kworld Xpert TV PVR7134 63 -> Kworld Xpert TV PVR7134
......
...@@ -540,7 +540,8 @@ S: Supported ...@@ -540,7 +540,8 @@ S: Supported
BTTV VIDEO4LINUX DRIVER BTTV VIDEO4LINUX DRIVER
P: Mauro Carvalho Chehab P: Mauro Carvalho Chehab
M: mchehab@brturbo.com.br M: mchehab@infradead.org
M: v4l-dvb-maintainer@linuxtv.org
L: video4linux-list@redhat.com L: video4linux-list@redhat.com
W: http://linuxtv.org W: http://linuxtv.org
T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/v4l-dvb.git T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/v4l-dvb.git
...@@ -837,11 +838,12 @@ S: Maintained ...@@ -837,11 +838,12 @@ S: Maintained
DVB SUBSYSTEM AND DRIVERS DVB SUBSYSTEM AND DRIVERS
P: LinuxTV.org Project P: LinuxTV.org Project
M: linux-dvb-maintainer@linuxtv.org M: mchehab@infradead.org
M: v4l-dvb-maintainer@linuxtv.org
L: linux-dvb@linuxtv.org (subscription required) L: linux-dvb@linuxtv.org (subscription required)
W: http://linuxtv.org/ W: http://linuxtv.org/
T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/v4l-dvb.git T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/v4l-dvb.git
S: Supported S: Maintained
EATA-DMA SCSI DRIVER EATA-DMA SCSI DRIVER
P: Michael Neuffer P: Michael Neuffer
...@@ -2956,7 +2958,8 @@ S: Maintained ...@@ -2956,7 +2958,8 @@ S: Maintained
VIDEO FOR LINUX VIDEO FOR LINUX
P: Mauro Carvalho Chehab P: Mauro Carvalho Chehab
M: mchehab@brturbo.com.br M: mchehab@infradead.org
M: v4l-dvb-maintainer@linuxtv.org
L: video4linux-list@redhat.com L: video4linux-list@redhat.com
W: http://linuxtv.org W: http://linuxtv.org
T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/v4l-dvb.git T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/v4l-dvb.git
......
...@@ -4,7 +4,7 @@ config DVB_B2C2_FLEXCOP ...@@ -4,7 +4,7 @@ config DVB_B2C2_FLEXCOP
select DVB_STV0299 select DVB_STV0299
select DVB_MT352 select DVB_MT352
select DVB_MT312 select DVB_MT312
select DVB_NXT2002 select DVB_NXT200X
select DVB_STV0297 select DVB_STV0297
select DVB_BCM3510 select DVB_BCM3510
select DVB_LGDT330X select DVB_LGDT330X
......
...@@ -116,11 +116,9 @@ void flexcop_dma_free(struct flexcop_dma *dma); ...@@ -116,11 +116,9 @@ void flexcop_dma_free(struct flexcop_dma *dma);
int flexcop_dma_control_timer_irq(struct flexcop_device *fc, flexcop_dma_index_t no, int onoff); int flexcop_dma_control_timer_irq(struct flexcop_device *fc, flexcop_dma_index_t no, int onoff);
int flexcop_dma_control_size_irq(struct flexcop_device *fc, flexcop_dma_index_t no, int onoff); int flexcop_dma_control_size_irq(struct flexcop_device *fc, flexcop_dma_index_t no, int onoff);
int flexcop_dma_control_packet_irq(struct flexcop_device *fc, flexcop_dma_index_t no, int onoff);
int flexcop_dma_config(struct flexcop_device *fc, struct flexcop_dma *dma, flexcop_dma_index_t dma_idx); int flexcop_dma_config(struct flexcop_device *fc, struct flexcop_dma *dma, flexcop_dma_index_t dma_idx);
int flexcop_dma_xfer_control(struct flexcop_device *fc, flexcop_dma_index_t dma_idx, flexcop_dma_addr_index_t index, int onoff); int flexcop_dma_xfer_control(struct flexcop_device *fc, flexcop_dma_index_t dma_idx, flexcop_dma_addr_index_t index, int onoff);
int flexcop_dma_config_timer(struct flexcop_device *fc, flexcop_dma_index_t dma_idx, u8 cycles); int flexcop_dma_config_timer(struct flexcop_device *fc, flexcop_dma_index_t dma_idx, u8 cycles);
int flexcop_dma_config_packet_count(struct flexcop_device *fc, flexcop_dma_index_t dma_idx, u8 packets);
/* from flexcop-eeprom.c */ /* from flexcop-eeprom.c */
/* the PCI part uses this call to get the MAC address, the USB part has its own */ /* the PCI part uses this call to get the MAC address, the USB part has its own */
......
...@@ -169,38 +169,3 @@ int flexcop_dma_config_timer(struct flexcop_device *fc, ...@@ -169,38 +169,3 @@ int flexcop_dma_config_timer(struct flexcop_device *fc,
} }
EXPORT_SYMBOL(flexcop_dma_config_timer); EXPORT_SYMBOL(flexcop_dma_config_timer);
/* packet IRQ does not exist in FCII or FCIIb - according to data book and tests */
int flexcop_dma_control_packet_irq(struct flexcop_device *fc,
flexcop_dma_index_t no,
int onoff)
{
flexcop_ibi_value v = fc->read_ibi_reg(fc,ctrl_208);
deb_rdump("reg: %03x: %x\n",ctrl_208,v.raw);
if (no & FC_DMA_1)
v.ctrl_208.DMA1_Size_IRQ_Enable_sig = onoff;
if (no & FC_DMA_2)
v.ctrl_208.DMA2_Size_IRQ_Enable_sig = onoff;
fc->write_ibi_reg(fc,ctrl_208,v);
deb_rdump("reg: %03x: %x\n",ctrl_208,v.raw);
return 0;
}
EXPORT_SYMBOL(flexcop_dma_control_packet_irq);
int flexcop_dma_config_packet_count(struct flexcop_device *fc,
flexcop_dma_index_t dma_idx,
u8 packets)
{
flexcop_ibi_register r = (dma_idx & FC_DMA_1) ? dma1_004 : dma2_014;
flexcop_ibi_value v = fc->read_ibi_reg(fc,r);
flexcop_dma_remap(fc,dma_idx,1);
v.dma_0x4_remap.DMA_maxpackets = packets;
fc->write_ibi_reg(fc,r,v);
return 0;
}
EXPORT_SYMBOL(flexcop_dma_config_packet_count);
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
#include "stv0299.h" #include "stv0299.h"
#include "mt352.h" #include "mt352.h"
#include "nxt2002.h" #include "nxt200x.h"
#include "bcm3510.h" #include "bcm3510.h"
#include "stv0297.h" #include "stv0297.h"
#include "mt312.h" #include "mt312.h"
...@@ -343,9 +343,10 @@ static struct lgdt330x_config air2pc_atsc_hd5000_config = { ...@@ -343,9 +343,10 @@ static struct lgdt330x_config air2pc_atsc_hd5000_config = {
.clock_polarity_flip = 1, .clock_polarity_flip = 1,
}; };
static struct nxt2002_config samsung_tbmv_config = { static struct nxt200x_config samsung_tbmv_config = {
.demod_address = 0x0a, .demod_address = 0x0a,
.request_firmware = flexcop_fe_request_firmware, .pll_address = 0xc2,
.pll_desc = &dvb_pll_samsung_tbmv,
}; };
static struct bcm3510_config air2pc_atsc_first_gen_config = { static struct bcm3510_config air2pc_atsc_first_gen_config = {
...@@ -505,7 +506,7 @@ int flexcop_frontend_init(struct flexcop_device *fc) ...@@ -505,7 +506,7 @@ int flexcop_frontend_init(struct flexcop_device *fc)
info("found the mt352 at i2c address: 0x%02x",samsung_tdtc9251dh0_config.demod_address); info("found the mt352 at i2c address: 0x%02x",samsung_tdtc9251dh0_config.demod_address);
} else } else
/* try the air atsc 2nd generation (nxt2002) */ /* try the air atsc 2nd generation (nxt2002) */
if ((fc->fe = nxt2002_attach(&samsung_tbmv_config, &fc->i2c_adap)) != NULL) { if ((fc->fe = nxt200x_attach(&samsung_tbmv_config, &fc->i2c_adap)) != NULL) {
fc->dev_type = FC_AIR_ATSC2; fc->dev_type = FC_AIR_ATSC2;
info("found the nxt2002 at i2c address: 0x%02x",samsung_tbmv_config.demod_address); info("found the nxt2002 at i2c address: 0x%02x",samsung_tbmv_config.demod_address);
} else } else
......
...@@ -36,14 +36,14 @@ void flexcop_determine_revision(struct flexcop_device *fc) ...@@ -36,14 +36,14 @@ void flexcop_determine_revision(struct flexcop_device *fc)
/* bus parts have to decide if hw pid filtering is used or not. */ /* bus parts have to decide if hw pid filtering is used or not. */
} }
const char *flexcop_revision_names[] = { static const char *flexcop_revision_names[] = {
"Unkown chip", "Unkown chip",
"FlexCopII", "FlexCopII",
"FlexCopIIb", "FlexCopIIb",
"FlexCopIII", "FlexCopIII",
}; };
const char *flexcop_device_names[] = { static const char *flexcop_device_names[] = {
"Unkown device", "Unkown device",
"Air2PC/AirStar 2 DVB-T", "Air2PC/AirStar 2 DVB-T",
"Air2PC/AirStar 2 ATSC 1st generation", "Air2PC/AirStar 2 ATSC 1st generation",
...@@ -54,7 +54,7 @@ const char *flexcop_device_names[] = { ...@@ -54,7 +54,7 @@ const char *flexcop_device_names[] = {
"Air2PC/AirStar 2 ATSC 3rd generation (HD5000)", "Air2PC/AirStar 2 ATSC 3rd generation (HD5000)",
}; };
const char *flexcop_bus_names[] = { static const char *flexcop_bus_names[] = {
"USB", "USB",
"PCI", "PCI",
}; };
......
...@@ -161,8 +161,10 @@ static irqreturn_t flexcop_pci_isr(int irq, void *dev_id, struct pt_regs *regs) ...@@ -161,8 +161,10 @@ static irqreturn_t flexcop_pci_isr(int irq, void *dev_id, struct pt_regs *regs)
fc->read_ibi_reg(fc,dma1_008).dma_0x8.dma_cur_addr << 2; fc->read_ibi_reg(fc,dma1_008).dma_0x8.dma_cur_addr << 2;
u32 cur_pos = cur_addr - fc_pci->dma[0].dma_addr0; u32 cur_pos = cur_addr - fc_pci->dma[0].dma_addr0;
deb_irq("%u irq: %08x cur_addr: %08x: cur_pos: %08x, last_cur_pos: %08x ", deb_irq("%u irq: %08x cur_addr: %llx: cur_pos: %08x, last_cur_pos: %08x ",
jiffies_to_usecs(jiffies - fc_pci->last_irq),v.raw,cur_addr,cur_pos,fc_pci->last_dma1_cur_pos); jiffies_to_usecs(jiffies - fc_pci->last_irq),
v.raw, (unsigned long long)cur_addr, cur_pos,
fc_pci->last_dma1_cur_pos);
fc_pci->last_irq = jiffies; fc_pci->last_irq = jiffies;
/* buffer end was reached, restarted from the beginning /* buffer end was reached, restarted from the beginning
......
...@@ -16,8 +16,6 @@ typedef enum { ...@@ -16,8 +16,6 @@ typedef enum {
FLEXCOP_III, FLEXCOP_III,
} flexcop_revision_t; } flexcop_revision_t;
extern const char *flexcop_revision_names[];
typedef enum { typedef enum {
FC_UNK = 0, FC_UNK = 0,
FC_AIR_DVB, FC_AIR_DVB,
...@@ -34,8 +32,6 @@ typedef enum { ...@@ -34,8 +32,6 @@ typedef enum {
FC_PCI, FC_PCI,
} flexcop_bus_t; } flexcop_bus_t;
extern const char *flexcop_device_names[];
/* FlexCop IBI Registers */ /* FlexCop IBI Registers */
#if defined(__LITTLE_ENDIAN) #if defined(__LITTLE_ENDIAN)
#include "flexcop_ibi_value_le.h" #include "flexcop_ibi_value_le.h"
......
...@@ -381,6 +381,23 @@ bt878_device_control(struct bt878 *bt, unsigned int cmd, union dst_gpio_packet * ...@@ -381,6 +381,23 @@ bt878_device_control(struct bt878 *bt, unsigned int cmd, union dst_gpio_packet *
EXPORT_SYMBOL(bt878_device_control); EXPORT_SYMBOL(bt878_device_control);
struct cards card_list[] __devinitdata = {
{ 0x01010071, BTTV_BOARD_NEBULA_DIGITV, "Nebula Electronics DigiTV" },
{ 0x07611461, BTTV_BOARD_AVDVBT_761, "AverMedia AverTV DVB-T 761" },
{ 0x001c11bd, BTTV_BOARD_PINNACLESAT, "Pinnacle PCTV Sat" },
{ 0x002611bd, BTTV_BOARD_TWINHAN_DST, "Pinnacle PCTV SAT CI" },
{ 0x00011822, BTTV_BOARD_TWINHAN_DST, "Twinhan VisionPlus DVB" },
{ 0xfc00270f, BTTV_BOARD_TWINHAN_DST, "ChainTech digitop DST-1000 DVB-S" },
{ 0x07711461, BTTV_BOARD_AVDVBT_771, "AVermedia AverTV DVB-T 771" },
{ 0xdb1018ac, BTTV_BOARD_DVICO_DVBT_LITE, "DViCO FusionHDTV DVB-T Lite" },
{ 0xd50018ac, BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE, "DViCO FusionHDTV 5 Lite" },
{ 0x20007063, BTTV_BOARD_PC_HDTV, "pcHDTV HD-2000 TV"},
{ 0, -1, NULL }
};
/***********************/ /***********************/
/* PCI device handling */ /* PCI device handling */
/***********************/ /***********************/
...@@ -388,18 +405,41 @@ EXPORT_SYMBOL(bt878_device_control); ...@@ -388,18 +405,41 @@ EXPORT_SYMBOL(bt878_device_control);
static int __devinit bt878_probe(struct pci_dev *dev, static int __devinit bt878_probe(struct pci_dev *dev,
const struct pci_device_id *pci_id) const struct pci_device_id *pci_id)
{ {
int result; int result = 0, has_dvb = 0, i;
unsigned char lat; unsigned char lat;
struct bt878 *bt; struct bt878 *bt;
#if defined(__powerpc__) #if defined(__powerpc__)
unsigned int cmd; unsigned int cmd;
#endif #endif
unsigned int cardid;
unsigned short id;
struct cards *dvb_cards;
printk(KERN_INFO "bt878: Bt878 AUDIO function found (%d).\n", printk(KERN_INFO "bt878: Bt878 AUDIO function found (%d).\n",
bt878_num); bt878_num);
if (pci_enable_device(dev)) if (pci_enable_device(dev))
return -EIO; return -EIO;
pci_read_config_word(dev, PCI_SUBSYSTEM_ID, &id);
cardid = id << 16;
pci_read_config_word(dev, PCI_SUBSYSTEM_VENDOR_ID, &id);
cardid |= id;
for (i = 0, dvb_cards = card_list; i < ARRAY_SIZE(card_list); i++, dvb_cards++) {
if (cardid == dvb_cards->pci_id) {
printk("%s: card id=[0x%x],[ %s ] has DVB functions.\n",
__func__, cardid, dvb_cards->name);
has_dvb = 1;
}
}
if (!has_dvb) {
printk("%s: card id=[0x%x], Unknown card.\nExiting..\n", __func__, cardid);
result = -EINVAL;
goto fail0;
}
bt = &bt878[bt878_num]; bt = &bt878[bt878_num];
bt->dev = dev; bt->dev = dev;
bt->nr = bt878_num; bt->nr = bt878_num;
...@@ -416,6 +456,8 @@ static int __devinit bt878_probe(struct pci_dev *dev, ...@@ -416,6 +456,8 @@ static int __devinit bt878_probe(struct pci_dev *dev,
pci_read_config_byte(dev, PCI_CLASS_REVISION, &bt->revision); pci_read_config_byte(dev, PCI_CLASS_REVISION, &bt->revision);
pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat); pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
printk(KERN_INFO "bt878(%d): Bt%x (rev %d) at %02x:%02x.%x, ", printk(KERN_INFO "bt878(%d): Bt%x (rev %d) at %02x:%02x.%x, ",
bt878_num, bt->id, bt->revision, dev->bus->number, bt878_num, bt->id, bt->revision, dev->bus->number,
PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
......
...@@ -88,6 +88,23 @@ ...@@ -88,6 +88,23 @@
#define BT878_RISC_SYNC_MASK (1 << 15) #define BT878_RISC_SYNC_MASK (1 << 15)
#define BTTV_BOARD_UNKNOWN 0x00
#define BTTV_BOARD_PINNACLESAT 0x5e
#define BTTV_BOARD_NEBULA_DIGITV 0x68
#define BTTV_BOARD_PC_HDTV 0x70
#define BTTV_BOARD_TWINHAN_DST 0x71
#define BTTV_BOARD_AVDVBT_771 0x7b
#define BTTV_BOARD_AVDVBT_761 0x7c
#define BTTV_BOARD_DVICO_DVBT_LITE 0x80
#define BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE 0x87
struct cards {
__u32 pci_id;
__u16 card_id;
char *name;
};
extern int bt878_num; extern int bt878_num;
struct bt878 { struct bt878 {
......
...@@ -83,12 +83,18 @@ config DVB_USB_UMT_010 ...@@ -83,12 +83,18 @@ config DVB_USB_UMT_010
Say Y here to support the HanfTek UMT-010 USB2.0 stick-sized DVB-T receiver. Say Y here to support the HanfTek UMT-010 USB2.0 stick-sized DVB-T receiver.
config DVB_USB_CXUSB config DVB_USB_CXUSB
tristate "Medion MD95700 hybrid USB2.0 (Conexant) support" tristate "Conexant USB2.0 hybrid reference design support"
depends on DVB_USB depends on DVB_USB
select DVB_CX22702 select DVB_CX22702
select DVB_LGDT330X
select DVB_MT352
help help
Say Y here to support the Medion MD95700 hybrid USB2.0 device. Currently Say Y here to support the Conexant USB2.0 hybrid reference design.
only the DVB-T part is supported. Currently, only DVB and ATSC modes are supported, analog mode
shall be added in the future. Devices that require this module:
Medion MD95700 hybrid USB2.0 device.
DViCO FusionHDTV (Bluebird) USB2.0 devices
config DVB_USB_DIGITV config DVB_USB_DIGITV
tristate "Nebula Electronics uDigiTV DVB-T USB2.0 support" tristate "Nebula Electronics uDigiTV DVB-T USB2.0 support"
......
...@@ -184,7 +184,7 @@ static int cxusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state) ...@@ -184,7 +184,7 @@ static int cxusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
return 0; return 0;
} }
struct dvb_usb_rc_key dvico_mce_rc_keys[] = { static struct dvb_usb_rc_key dvico_mce_rc_keys[] = {
{ 0xfe, 0x02, KEY_TV }, { 0xfe, 0x02, KEY_TV },
{ 0xfe, 0x0e, KEY_MP3 }, { 0xfe, 0x0e, KEY_MP3 },
{ 0xfe, 0x1a, KEY_DVD }, { 0xfe, 0x1a, KEY_DVD },
...@@ -234,7 +234,7 @@ struct dvb_usb_rc_key dvico_mce_rc_keys[] = { ...@@ -234,7 +234,7 @@ struct dvb_usb_rc_key dvico_mce_rc_keys[] = {
static int cxusb_dee1601_demod_init(struct dvb_frontend* fe) static int cxusb_dee1601_demod_init(struct dvb_frontend* fe)
{ {
static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x38 }; static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x28 };
static u8 reset [] = { RESET, 0x80 }; static u8 reset [] = { RESET, 0x80 };
static u8 adc_ctl_1_cfg [] = { ADC_CTL_1, 0x40 }; static u8 adc_ctl_1_cfg [] = { ADC_CTL_1, 0x40 };
static u8 agc_cfg [] = { AGC_TARGET, 0x28, 0x20 }; static u8 agc_cfg [] = { AGC_TARGET, 0x28, 0x20 };
...@@ -255,7 +255,7 @@ static int cxusb_dee1601_demod_init(struct dvb_frontend* fe) ...@@ -255,7 +255,7 @@ static int cxusb_dee1601_demod_init(struct dvb_frontend* fe)
static int cxusb_mt352_demod_init(struct dvb_frontend* fe) static int cxusb_mt352_demod_init(struct dvb_frontend* fe)
{ /* used in both lgz201 and th7579 */ { /* used in both lgz201 and th7579 */
static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x39 }; static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x29 };
static u8 reset [] = { RESET, 0x80 }; static u8 reset [] = { RESET, 0x80 };
static u8 adc_ctl_1_cfg [] = { ADC_CTL_1, 0x40 }; static u8 adc_ctl_1_cfg [] = { ADC_CTL_1, 0x40 };
static u8 agc_cfg [] = { AGC_TARGET, 0x24, 0x20 }; static u8 agc_cfg [] = { AGC_TARGET, 0x24, 0x20 };
...@@ -273,7 +273,7 @@ static int cxusb_mt352_demod_init(struct dvb_frontend* fe) ...@@ -273,7 +273,7 @@ static int cxusb_mt352_demod_init(struct dvb_frontend* fe)
return 0; return 0;
} }
struct cx22702_config cxusb_cx22702_config = { static struct cx22702_config cxusb_cx22702_config = {
.demod_address = 0x63, .demod_address = 0x63,
.output_mode = CX22702_PARALLEL_OUTPUT, .output_mode = CX22702_PARALLEL_OUTPUT,
...@@ -282,13 +282,13 @@ struct cx22702_config cxusb_cx22702_config = { ...@@ -282,13 +282,13 @@ struct cx22702_config cxusb_cx22702_config = {
.pll_set = dvb_usb_pll_set_i2c, .pll_set = dvb_usb_pll_set_i2c,
}; };
struct lgdt330x_config cxusb_lgdt330x_config = { static struct lgdt330x_config cxusb_lgdt330x_config = {
.demod_address = 0x0e, .demod_address = 0x0e,
.demod_chip = LGDT3303, .demod_chip = LGDT3303,
.pll_set = dvb_usb_pll_set_i2c, .pll_set = dvb_usb_pll_set_i2c,
}; };
struct mt352_config cxusb_dee1601_config = { static struct mt352_config cxusb_dee1601_config = {
.demod_address = 0x0f, .demod_address = 0x0f,
.demod_init = cxusb_dee1601_demod_init, .demod_init = cxusb_dee1601_demod_init,
.pll_set = dvb_usb_pll_set, .pll_set = dvb_usb_pll_set,
......
...@@ -175,12 +175,14 @@ static int digitv_probe(struct usb_interface *intf, ...@@ -175,12 +175,14 @@ static int digitv_probe(struct usb_interface *intf,
if ((ret = dvb_usb_device_init(intf,&digitv_properties,THIS_MODULE,&d)) == 0) { if ((ret = dvb_usb_device_init(intf,&digitv_properties,THIS_MODULE,&d)) == 0) {
u8 b[4] = { 0 }; u8 b[4] = { 0 };
if (d != NULL) { /* do that only when the firmware is loaded */
b[0] = 1; b[0] = 1;
digitv_ctrl_msg(d,USB_WRITE_REMOTE_TYPE,0,b,4,NULL,0); digitv_ctrl_msg(d,USB_WRITE_REMOTE_TYPE,0,b,4,NULL,0);
b[0] = 0; b[0] = 0;
digitv_ctrl_msg(d,USB_WRITE_REMOTE,0,b,4,NULL,0); digitv_ctrl_msg(d,USB_WRITE_REMOTE,0,b,4,NULL,0);
} }
}
return ret; return ret;
} }
...@@ -194,7 +196,7 @@ static struct dvb_usb_properties digitv_properties = { ...@@ -194,7 +196,7 @@ static struct dvb_usb_properties digitv_properties = {
.caps = DVB_USB_IS_AN_I2C_ADAPTER, .caps = DVB_USB_IS_AN_I2C_ADAPTER,
.usb_ctrl = CYPRESS_FX2, .usb_ctrl = CYPRESS_FX2,
.firmware = "dvb-usb-digitv-01.fw", .firmware = "dvb-usb-digitv-02.fw",
.size_of_priv = 0, .size_of_priv = 0,
...@@ -229,6 +231,7 @@ static struct dvb_usb_properties digitv_properties = { ...@@ -229,6 +231,7 @@ static struct dvb_usb_properties digitv_properties = {
{ &digitv_table[0], NULL }, { &digitv_table[0], NULL },
{ NULL }, { NULL },
}, },
{ NULL },
} }
}; };
......
...@@ -24,6 +24,9 @@ static struct usb_cypress_controller cypress[] = { ...@@ -24,6 +24,9 @@ static struct usb_cypress_controller cypress[] = {
{ .id = CYPRESS_FX2, .name = "Cypress FX2", .cpu_cs_register = 0xe600 }, { .id = CYPRESS_FX2, .name = "Cypress FX2", .cpu_cs_register = 0xe600 },
}; };
static int dvb_usb_get_hexline(const struct firmware *fw, struct hexline *hx,
int *pos);
/* /*
* load a firmware packet to the device * load a firmware packet to the device
*/ */
...@@ -112,7 +115,8 @@ int dvb_usb_download_firmware(struct usb_device *udev, struct dvb_usb_properties ...@@ -112,7 +115,8 @@ int dvb_usb_download_firmware(struct usb_device *udev, struct dvb_usb_properties
return ret; return ret;
} }
int dvb_usb_get_hexline(const struct firmware *fw, struct hexline *hx, int *pos) static int dvb_usb_get_hexline(const struct firmware *fw, struct hexline *hx,
int *pos)
{ {
u8 *b = (u8 *) &fw->data[*pos]; u8 *b = (u8 *) &fw->data[*pos];
int data_offs = 4; int data_offs = 4;
...@@ -142,5 +146,3 @@ int dvb_usb_get_hexline(const struct firmware *fw, struct hexline *hx, int *pos) ...@@ -142,5 +146,3 @@ int dvb_usb_get_hexline(const struct firmware *fw, struct hexline *hx, int *pos)
return *pos; return *pos;
} }
EXPORT_SYMBOL(dvb_usb_get_hexline);
...@@ -341,7 +341,6 @@ struct hexline { ...@@ -341,7 +341,6 @@ struct hexline {
u8 data[255]; u8 data[255];
u8 chk; u8 chk;
}; };
extern int dvb_usb_get_hexline(const struct firmware *, struct hexline *, int *);
extern int usb_cypress_load_firmware(struct usb_device *udev, const struct firmware *fw, int type); extern int usb_cypress_load_firmware(struct usb_device *udev, const struct firmware *fw, int type);
#endif #endif
...@@ -53,7 +53,8 @@ int vp702x_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 ...@@ -53,7 +53,8 @@ int vp702x_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8
return ret; return ret;
} }
int vp702x_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen) static int vp702x_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value,
u16 index, u8 *b, int blen)
{ {
deb_xfer("out: req. %x, val: %x, ind: %x, buffer: ",req,value,index); deb_xfer("out: req. %x, val: %x, ind: %x, buffer: ",req,value,index);
debug_dump(b,blen,deb_xfer); debug_dump(b,blen,deb_xfer);
...@@ -88,7 +89,8 @@ int vp702x_usb_inout_op(struct dvb_usb_device *d, u8 *o, int olen, u8 *i, int il ...@@ -88,7 +89,8 @@ int vp702x_usb_inout_op(struct dvb_usb_device *d, u8 *o, int olen, u8 *i, int il
return ret; return ret;
} }
int vp702x_usb_inout_cmd(struct dvb_usb_device *d, u8 cmd, u8 *o, int olen, u8 *i, int ilen, int msec) static int vp702x_usb_inout_cmd(struct dvb_usb_device *d, u8 cmd, u8 *o,
int olen, u8 *i, int ilen, int msec)
{ {
u8 bout[olen+2]; u8 bout[olen+2];
u8 bin[ilen+1]; u8 bin[ilen+1];
......
...@@ -101,8 +101,6 @@ extern int dvb_usb_vp702x_debug; ...@@ -101,8 +101,6 @@ extern int dvb_usb_vp702x_debug;
extern struct dvb_frontend * vp702x_fe_attach(struct dvb_usb_device *d); extern struct dvb_frontend * vp702x_fe_attach(struct dvb_usb_device *d);
extern int vp702x_usb_inout_op(struct dvb_usb_device *d, u8 *o, int olen, u8 *i, int ilen, int msec); extern int vp702x_usb_inout_op(struct dvb_usb_device *d, u8 *o, int olen, u8 *i, int ilen, int msec);
extern int vp702x_usb_inout_cmd(struct dvb_usb_device *d, u8 cmd, u8 *o, int olen, u8 *i, int ilen, int msec);
extern int vp702x_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen); extern int vp702x_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen);
extern int vp702x_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen);
#endif #endif
...@@ -23,10 +23,11 @@ ...@@ -23,10 +23,11 @@
struct vp7045_fe_state { struct vp7045_fe_state {
struct dvb_frontend fe; struct dvb_frontend fe;
struct dvb_frontend_ops ops;
struct dvb_usb_device *d; struct dvb_usb_device *d;
}; };
static int vp7045_fe_read_status(struct dvb_frontend* fe, fe_status_t *status) static int vp7045_fe_read_status(struct dvb_frontend* fe, fe_status_t *status)
{ {
struct vp7045_fe_state *state = fe->demodulator_priv; struct vp7045_fe_state *state = fe->demodulator_priv;
...@@ -150,7 +151,8 @@ struct dvb_frontend * vp7045_fe_attach(struct dvb_usb_device *d) ...@@ -150,7 +151,8 @@ struct dvb_frontend * vp7045_fe_attach(struct dvb_usb_device *d)
goto error; goto error;
s->d = d; s->d = d;
s->fe.ops = &vp7045_fe_ops; memcpy(&s->ops, &vp7045_fe_ops, sizeof(struct dvb_frontend_ops));
s->fe.ops = &s->ops;
s->fe.demodulator_priv = s; s->fe.demodulator_priv = s;
goto success; goto success;
......
...@@ -28,12 +28,6 @@ config DVB_TDA8083 ...@@ -28,12 +28,6 @@ config DVB_TDA8083
help help
A DVB-S tuner module. Say Y when you want to support this frontend. A DVB-S tuner module. Say Y when you want to support this frontend.
config DVB_TDA80XX
tristate "Philips TDA8044 or TDA8083 based"
depends on DVB_CORE
help
A DVB-S tuner module. Say Y when you want to support this frontend.
config DVB_MT312 config DVB_MT312
tristate "Zarlink MT312 based" tristate "Zarlink MT312 based"
depends on DVB_CORE depends on DVB_CORE
...@@ -139,12 +133,6 @@ config DVB_DIB3000MC ...@@ -139,12 +133,6 @@ config DVB_DIB3000MC
comment "DVB-C (cable) frontends" comment "DVB-C (cable) frontends"
depends on DVB_CORE depends on DVB_CORE
config DVB_ATMEL_AT76C651
tristate "Atmel AT76C651 based"
depends on DVB_CORE
help
A DVB-C tuner module. Say Y when you want to support this frontend.
config DVB_VES1820 config DVB_VES1820
tristate "VLSI VES1820 based" tristate "VLSI VES1820 based"
depends on DVB_CORE depends on DVB_CORE
...@@ -166,18 +154,6 @@ config DVB_STV0297 ...@@ -166,18 +154,6 @@ config DVB_STV0297
comment "ATSC (North American/Korean Terresterial DTV) frontends" comment "ATSC (North American/Korean Terresterial DTV) frontends"
depends on DVB_CORE depends on DVB_CORE
config DVB_NXT2002
tristate "Nxt2002 based"
depends on DVB_CORE
select FW_LOADER
help
An ATSC 8VSB tuner module. Say Y when you want to support this frontend.
This driver needs external firmware. Please use the command
"<kerneldir>/Documentation/dvb/get_dvb_firmware nxt2002" to
download/extract it, and then copy it to /usr/lib/hotplug/firmware
or /lib/firmware (depending on configuration of firmware hotplug).
config DVB_NXT200X config DVB_NXT200X
tristate "Nextwave NXT2002/NXT2004 based" tristate "Nextwave NXT2002/NXT2004 based"
depends on DVB_CORE depends on DVB_CORE
......
...@@ -8,7 +8,6 @@ obj-$(CONFIG_DVB_CORE) += dvb-pll.o ...@@ -8,7 +8,6 @@ obj-$(CONFIG_DVB_CORE) += dvb-pll.o
obj-$(CONFIG_DVB_STV0299) += stv0299.o obj-$(CONFIG_DVB_STV0299) += stv0299.o
obj-$(CONFIG_DVB_SP8870) += sp8870.o obj-$(CONFIG_DVB_SP8870) += sp8870.o
obj-$(CONFIG_DVB_CX22700) += cx22700.o obj-$(CONFIG_DVB_CX22700) += cx22700.o
obj-$(CONFIG_DVB_ATMEL_AT76C651) += at76c651.o
obj-$(CONFIG_DVB_CX24110) += cx24110.o obj-$(CONFIG_DVB_CX24110) += cx24110.o
obj-$(CONFIG_DVB_TDA8083) += tda8083.o obj-$(CONFIG_DVB_TDA8083) += tda8083.o
obj-$(CONFIG_DVB_L64781) += l64781.o obj-$(CONFIG_DVB_L64781) += l64781.o
...@@ -22,10 +21,8 @@ obj-$(CONFIG_DVB_SP887X) += sp887x.o ...@@ -22,10 +21,8 @@ obj-$(CONFIG_DVB_SP887X) += sp887x.o
obj-$(CONFIG_DVB_NXT6000) += nxt6000.o obj-$(CONFIG_DVB_NXT6000) += nxt6000.o
obj-$(CONFIG_DVB_MT352) += mt352.o obj-$(CONFIG_DVB_MT352) += mt352.o
obj-$(CONFIG_DVB_CX22702) += cx22702.o obj-$(CONFIG_DVB_CX22702) += cx22702.o
obj-$(CONFIG_DVB_TDA80XX) += tda80xx.o
obj-$(CONFIG_DVB_TDA10021) += tda10021.o obj-$(CONFIG_DVB_TDA10021) += tda10021.o
obj-$(CONFIG_DVB_STV0297) += stv0297.o obj-$(CONFIG_DVB_STV0297) += stv0297.o
obj-$(CONFIG_DVB_NXT2002) += nxt2002.o
obj-$(CONFIG_DVB_NXT200X) += nxt200x.o obj-$(CONFIG_DVB_NXT200X) += nxt200x.o
obj-$(CONFIG_DVB_OR51211) += or51211.o obj-$(CONFIG_DVB_OR51211) += or51211.o
obj-$(CONFIG_DVB_OR51132) += or51132.o obj-$(CONFIG_DVB_OR51132) += or51132.o
......
/*
* at76c651.c
*
* Atmel DVB-C Frontend Driver (at76c651/tua6010xs)
*
* Copyright (C) 2001 fnbrd <fnbrd@gmx.de>
* & 2002-2004 Andreas Oberritter <obi@linuxtv.org>
* & 2003 Wolfram Joost <dbox2@frokaschwei.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; 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.
*
* AT76C651
* http://www.nalanda.nitc.ac.in/industry/datasheets/atmel/acrobat/doc1293.pdf
* http://www.atmel.com/atmel/acrobat/doc1320.pdf
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/bitops.h>
#include "dvb_frontend.h"
#include "at76c651.h"
struct at76c651_state {
struct i2c_adapter* i2c;
struct dvb_frontend_ops ops;
const struct at76c651_config* config;
struct dvb_frontend frontend;
/* revision of the chip */
u8 revision;
/* last QAM value set */
u8 qam;
};
static int debug;
#define dprintk(args...) \
do { \
if (debug) printk(KERN_DEBUG "at76c651: " args); \
} while (0)
#if ! defined(__powerpc__)
static __inline__ int __ilog2(unsigned long x)
{
int i;
if (x == 0)
return -1;
for (i = 0; x != 0; i++)
x >>= 1;
return i - 1;
}
#endif
static int at76c651_writereg(struct at76c651_state* state, u8 reg, u8 data)
{
int ret;
u8 buf[] = { reg, data };
struct i2c_msg msg =
{ .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 };
ret = i2c_transfer(state->i2c, &msg, 1);
if (ret != 1)
dprintk("%s: writereg error "
"(reg == 0x%02x, val == 0x%02x, ret == %i)\n",
__FUNCTION__, reg, data, ret);
msleep(10);
return (ret != 1) ? -EREMOTEIO : 0;
}
static u8 at76c651_readreg(struct at76c651_state* state, u8 reg)
{
int ret;
u8 val;
struct i2c_msg msg[] = {
{ .addr = state->config->demod_address, .flags = 0, .buf = &reg, .len = 1 },
{ .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = &val, .len = 1 }
};
ret = i2c_transfer(state->i2c, msg, 2);
if (ret != 2)
dprintk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret);
return val;
}
static int at76c651_reset(struct at76c651_state* state)
{
return at76c651_writereg(state, 0x07, 0x01);
}
static void at76c651_disable_interrupts(struct at76c651_state* state)
{
at76c651_writereg(state, 0x0b, 0x00);
}
static int at76c651_set_auto_config(struct at76c651_state *state)
{
/*
* Autoconfig
*/
at76c651_writereg(state, 0x06, 0x01);
/*
* Performance optimizations, should be done after autoconfig
*/
at76c651_writereg(state, 0x10, 0x06);
at76c651_writereg(state, 0x11, ((state->qam == 5) || (state->qam == 7)) ? 0x12 : 0x10);
at76c651_writereg(state, 0x15, 0x28);
at76c651_writereg(state, 0x20, 0x09);
at76c651_writereg(state, 0x24, ((state->qam == 5) || (state->qam == 7)) ? 0xC0 : 0x90);
at76c651_writereg(state, 0x30, 0x90);
if (state->qam == 5)
at76c651_writereg(state, 0x35, 0x2A);
/*
* Initialize A/D-converter
*/
if (state->revision == 0x11) {
at76c651_writereg(state, 0x2E, 0x38);
at76c651_writereg(state, 0x2F, 0x13);
}
at76c651_disable_interrupts(state);
/*
* Restart operation
*/
at76c651_reset(state);
return 0;
}
static void at76c651_set_bbfreq(struct at76c651_state* state)
{
at76c651_writereg(state, 0x04, 0x3f);
at76c651_writereg(state, 0x05, 0xee);
}
static int at76c651_set_symbol_rate(struct at76c651_state* state, u32 symbol_rate)
{
u8 exponent;
u32 mantissa;
if (symbol_rate > 9360000)
return -EINVAL;
/*
* FREF = 57800 kHz
* exponent = 10 + floor (log2(symbol_rate / FREF))
* mantissa = (symbol_rate / FREF) * (1 << (30 - exponent))
*/
exponent = __ilog2((symbol_rate << 4) / 903125);
mantissa = ((symbol_rate / 3125) * (1 << (24 - exponent))) / 289;
at76c651_writereg(state, 0x00, mantissa >> 13);
at76c651_writereg(state, 0x01, mantissa >> 5);
at76c651_writereg(state, 0x02, (mantissa << 3) | exponent);
return 0;
}
static int at76c651_set_qam(struct at76c651_state *state, fe_modulation_t qam)
{
switch (qam) {
case QPSK:
state->qam = 0x02;
break;
case QAM_16:
state->qam = 0x04;
break;
case QAM_32:
state->qam = 0x05;
break;
case QAM_64:
state->qam = 0x06;
break;
case QAM_128:
state->qam = 0x07;
break;
case QAM_256:
state->qam = 0x08;
break;
#if 0
case QAM_512:
state->qam = 0x09;
break;
case QAM_1024:
state->qam = 0x0A;
break;
#endif
default:
return -EINVAL;
}
return at76c651_writereg(state, 0x03, state->qam);
}
static int at76c651_set_inversion(struct at76c651_state* state, fe_spectral_inversion_t inversion)
{
u8 feciqinv = at76c651_readreg(state, 0x60);
switch (inversion) {
case INVERSION_OFF:
feciqinv |= 0x02;
feciqinv &= 0xFE;
break;
case INVERSION_ON:
feciqinv |= 0x03;
break;
case INVERSION_AUTO:
feciqinv &= 0xFC;
break;
default:
return -EINVAL;
}
return at76c651_writereg(state, 0x60, feciqinv);
}
static int at76c651_set_parameters(struct dvb_frontend* fe,
struct dvb_frontend_parameters *p)
{
int ret;
struct at76c651_state* state = fe->demodulator_priv;
at76c651_writereg(state, 0x0c, 0xc3);
state->config->pll_set(fe, p);
at76c651_writereg(state, 0x0c, 0xc2);
if ((ret = at76c651_set_symbol_rate(state, p->u.qam.symbol_rate)))
return ret;
if ((ret = at76c651_set_inversion(state, p->inversion)))
return ret;
return at76c651_set_auto_config(state);
}
static int at76c651_set_defaults(struct dvb_frontend* fe)
{
struct at76c651_state* state = fe->demodulator_priv;
at76c651_set_symbol_rate(state, 6900000);
at76c651_set_qam(state, QAM_64);
at76c651_set_bbfreq(state);
at76c651_set_auto_config(state);
if (state->config->pll_init) {
at76c651_writereg(state, 0x0c, 0xc3);
state->config->pll_init(fe);
at76c651_writereg(state, 0x0c, 0xc2);
}
return 0;
}
static int at76c651_read_status(struct dvb_frontend* fe, fe_status_t* status)
{
struct at76c651_state* state = fe->demodulator_priv;
u8 sync;
/*
* Bits: FEC, CAR, EQU, TIM, AGC2, AGC1, ADC, PLL (PLL=0)
*/
sync = at76c651_readreg(state, 0x80);
*status = 0;
if (sync & (0x04 | 0x10)) /* AGC1 || TIM */
*status |= FE_HAS_SIGNAL;
if (sync & 0x10) /* TIM */
*status |= FE_HAS_CARRIER;
if (sync & 0x80) /* FEC */
*status |= FE_HAS_VITERBI;
if (sync & 0x40) /* CAR */
*status |= FE_HAS_SYNC;
if ((sync & 0xF0) == 0xF0) /* TIM && EQU && CAR && FEC */
*status |= FE_HAS_LOCK;
return 0;
}
static int at76c651_read_ber(struct dvb_frontend* fe, u32* ber)
{
struct at76c651_state* state = fe->demodulator_priv;
*ber = (at76c651_readreg(state, 0x81) & 0x0F) << 16;
*ber |= at76c651_readreg(state, 0x82) << 8;
*ber |= at76c651_readreg(state, 0x83);
*ber *= 10;
return 0;
}
static int at76c651_read_signal_strength(struct dvb_frontend* fe, u16* strength)
{
struct at76c651_state* state = fe->demodulator_priv;
u8 gain = ~at76c651_readreg(state, 0x91);
*strength = (gain << 8) | gain;
return 0;
}
static int at76c651_read_snr(struct dvb_frontend* fe, u16* snr)
{
struct at76c651_state* state = fe->demodulator_priv;
*snr = 0xFFFF -
((at76c651_readreg(state, 0x8F) << 8) |
at76c651_readreg(state, 0x90));
return 0;
}
static int at76c651_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
{
struct at76c651_state* state = fe->demodulator_priv;
*ucblocks = at76c651_readreg(state, 0x82);
return 0;
}
static int at76c651_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *fesettings)
{
fesettings->min_delay_ms = 50;
fesettings->step_size = 0;
fesettings->max_drift = 0;
return 0;
}
static void at76c651_release(struct dvb_frontend* fe)
{
struct at76c651_state* state = fe->demodulator_priv;
kfree(state);
}
static struct dvb_frontend_ops at76c651_ops;
struct dvb_frontend* at76c651_attach(const struct at76c651_config* config,
struct i2c_adapter* i2c)
{
struct at76c651_state* state = NULL;
/* allocate memory for the internal state */
state = kmalloc(sizeof(struct at76c651_state), GFP_KERNEL);
if (state == NULL) goto error;
/* setup the state */
state->config = config;
state->qam = 0;
/* check if the demod is there */
if (at76c651_readreg(state, 0x0e) != 0x65) goto error;
/* finalise state setup */
state->i2c = i2c;
state->revision = at76c651_readreg(state, 0x0f) & 0xfe;
memcpy(&state->ops, &at76c651_ops, sizeof(struct dvb_frontend_ops));
/* create dvb_frontend */
state->frontend.ops = &state->ops;
state->frontend.demodulator_priv = state;
return &state->frontend;
error:
kfree(state);
return NULL;
}
static struct dvb_frontend_ops at76c651_ops = {
.info = {
.name = "Atmel AT76C651B DVB-C",
.type = FE_QAM,
.frequency_min = 48250000,
.frequency_max = 863250000,
.frequency_stepsize = 62500,
/*.frequency_tolerance = */ /* FIXME: 12% of SR */
.symbol_rate_min = 0, /* FIXME */
.symbol_rate_max = 9360000, /* FIXME */
.symbol_rate_tolerance = 4000,
.caps = FE_CAN_INVERSION_AUTO |
FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 |
FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO |
FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 | FE_CAN_QAM_128 |
FE_CAN_MUTE_TS | FE_CAN_QAM_256 | FE_CAN_RECOVER
},
.release = at76c651_release,
.init = at76c651_set_defaults,
.set_frontend = at76c651_set_parameters,
.get_tune_settings = at76c651_get_tune_settings,
.read_status = at76c651_read_status,
.read_ber = at76c651_read_ber,
.read_signal_strength = at76c651_read_signal_strength,
.read_snr = at76c651_read_snr,
.read_ucblocks = at76c651_read_ucblocks,
};
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
MODULE_DESCRIPTION("Atmel AT76C651 DVB-C Demodulator Driver");
MODULE_AUTHOR("Andreas Oberritter <obi@linuxtv.org>");
MODULE_LICENSE("GPL");
EXPORT_SYMBOL(at76c651_attach);
/*
* at76c651.c
*
* Atmel DVB-C Frontend Driver (at76c651)
*
* Copyright (C) 2001 fnbrd <fnbrd@gmx.de>
* & 2002-2004 Andreas Oberritter <obi@linuxtv.org>
* & 2003 Wolfram Joost <dbox2@frokaschwei.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; 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.
*
* AT76C651
* http://www.nalanda.nitc.ac.in/industry/datasheets/atmel/acrobat/doc1293.pdf
* http://www.atmel.com/atmel/acrobat/doc1320.pdf
*/
#ifndef AT76C651_H
#define AT76C651_H
#include <linux/dvb/frontend.h>
struct at76c651_config
{
/* the demodulator's i2c address */
u8 demod_address;
/* PLL maintenance */
int (*pll_init)(struct dvb_frontend* fe);
int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
};
extern struct dvb_frontend* at76c651_attach(const struct at76c651_config* config,
struct i2c_adapter* i2c);
#endif // AT76C651_H
...@@ -326,11 +326,11 @@ struct dvb_pll_desc dvb_pll_tuv1236d = { ...@@ -326,11 +326,11 @@ struct dvb_pll_desc dvb_pll_tuv1236d = {
}; };
EXPORT_SYMBOL(dvb_pll_tuv1236d); EXPORT_SYMBOL(dvb_pll_tuv1236d);
/* Samsung TBMV30111IN /* Samsung TBMV30111IN / TBMV30712IN1
* used in Air2PC ATSC - 2nd generation (nxt2002) * used in Air2PC ATSC - 2nd generation (nxt2002)
*/ */
struct dvb_pll_desc dvb_pll_tbmv30111in = { struct dvb_pll_desc dvb_pll_samsung_tbmv = {
.name = "Samsung TBMV30111IN", .name = "Samsung TBMV30111IN / TBMV30712IN1",
.min = 54000000, .min = 54000000,
.max = 860000000, .max = 860000000,
.count = 6, .count = 6,
...@@ -343,7 +343,7 @@ struct dvb_pll_desc dvb_pll_tbmv30111in = { ...@@ -343,7 +343,7 @@ struct dvb_pll_desc dvb_pll_tbmv30111in = {
{ 999999999, 44000000, 166666, 0xfc, 0x02 }, { 999999999, 44000000, 166666, 0xfc, 0x02 },
} }
}; };
EXPORT_SYMBOL(dvb_pll_tbmv30111in); EXPORT_SYMBOL(dvb_pll_samsung_tbmv);
/* /*
* Philips SD1878 Tuner. * Philips SD1878 Tuner.
......
...@@ -38,7 +38,7 @@ extern struct dvb_pll_desc dvb_pll_tded4; ...@@ -38,7 +38,7 @@ extern struct dvb_pll_desc dvb_pll_tded4;
extern struct dvb_pll_desc dvb_pll_tuv1236d; extern struct dvb_pll_desc dvb_pll_tuv1236d;
extern struct dvb_pll_desc dvb_pll_tdhu2; extern struct dvb_pll_desc dvb_pll_tdhu2;
extern struct dvb_pll_desc dvb_pll_tbmv30111in; extern struct dvb_pll_desc dvb_pll_samsung_tbmv;
extern struct dvb_pll_desc dvb_pll_philips_sd1878_tda8261; extern struct dvb_pll_desc dvb_pll_philips_sd1878_tda8261;
int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf, int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf,
......
/*
Support for B2C2/BBTI Technisat Air2PC - ATSC
Copyright (C) 2004 Taylor Jacob <rtjacob@earthlink.net>
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.
*/
/*
* This driver needs external firmware. Please use the command
* "<kerneldir>/Documentation/dvb/get_dvb_firmware nxt2002" to
* download/extract it, and then copy it to /usr/lib/hotplug/firmware
* or /lib/firmware (depending on configuration of firmware hotplug).
*/
#define NXT2002_DEFAULT_FIRMWARE "dvb-fe-nxt2002.fw"
#define CRC_CCIT_MASK 0x1021
#include <linux/init.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/device.h>
#include <linux/firmware.h>
#include <linux/string.h>
#include <linux/slab.h>
#include "dvb_frontend.h"
#include "nxt2002.h"
struct nxt2002_state {
struct i2c_adapter* i2c;
struct dvb_frontend_ops ops;
const struct nxt2002_config* config;
struct dvb_frontend frontend;
/* demodulator private data */
u8 initialised:1;
};
static int debug;
#define dprintk(args...) \
do { \
if (debug) printk(KERN_DEBUG "nxt2002: " args); \
} while (0)
static int i2c_writebytes (struct nxt2002_state* state, u8 reg, u8 *buf, u8 len)
{
/* probbably a much better way or doing this */
u8 buf2 [256],x;
int err;
struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf2, .len = len + 1 };
buf2[0] = reg;
for (x = 0 ; x < len ; x++)
buf2[x+1] = buf[x];
if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
printk ("%s: i2c write error (addr %02x, err == %i)\n",
__FUNCTION__, state->config->demod_address, err);
return -EREMOTEIO;
}
return 0;
}
static u8 i2c_readbytes (struct nxt2002_state* state, u8 reg, u8* buf, u8 len)
{
u8 reg2 [] = { reg };
struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = reg2, .len = 1 },
{ .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = buf, .len = len } };
int err;
if ((err = i2c_transfer (state->i2c, msg, 2)) != 2) {
printk ("%s: i2c read error (addr %02x, err == %i)\n",
__FUNCTION__, state->config->demod_address, err);
return -EREMOTEIO;
}
return 0;
}
static u16 nxt2002_crc(u16 crc, u8 c)
{
u8 i;
u16 input = (u16) c & 0xFF;
input<<=8;
for(i=0 ;i<8 ;i++) {
if((crc ^ input) & 0x8000)
crc=(crc<<1)^CRC_CCIT_MASK;
else
crc<<=1;
input<<=1;
}
return crc;
}
static int nxt2002_writereg_multibyte (struct nxt2002_state* state, u8 reg, u8* data, u8 len)
{
u8 buf;
dprintk("%s\n", __FUNCTION__);
/* set multi register length */
i2c_writebytes(state,0x34,&len,1);
/* set mutli register register */
i2c_writebytes(state,0x35,&reg,1);
/* send the actual data */
i2c_writebytes(state,0x36,data,len);
/* toggle the multireg write bit*/
buf = 0x02;
i2c_writebytes(state,0x21,&buf,1);
i2c_readbytes(state,0x21,&buf,1);
if ((buf & 0x02) == 0)
return 0;
dprintk("Error writing multireg register %02X\n",reg);
return 0;
}
static int nxt2002_readreg_multibyte (struct nxt2002_state* state, u8 reg, u8* data, u8 len)
{
u8 len2;
dprintk("%s\n", __FUNCTION__);
/* set multi register length */
len2 = len & 0x80;
i2c_writebytes(state,0x34,&len2,1);
/* set mutli register register */
i2c_writebytes(state,0x35,&reg,1);
/* send the actual data */
i2c_readbytes(state,reg,data,len);
return 0;
}
static void nxt2002_microcontroller_stop (struct nxt2002_state* state)
{
u8 buf[2],counter = 0;
dprintk("%s\n", __FUNCTION__);
buf[0] = 0x80;
i2c_writebytes(state,0x22,buf,1);
while (counter < 20) {
i2c_readbytes(state,0x31,buf,1);
if (buf[0] & 0x40)
return;
msleep(10);
counter++;
}
dprintk("Timeout waiting for micro to stop.. This is ok after firmware upload\n");
return;
}
static void nxt2002_microcontroller_start (struct nxt2002_state* state)
{
u8 buf;
dprintk("%s\n", __FUNCTION__);
buf = 0x00;
i2c_writebytes(state,0x22,&buf,1);
}
static int nxt2002_writetuner (struct nxt2002_state* state, u8* data)
{
u8 buf,count = 0;
dprintk("Tuner Bytes: %02X %02X %02X %02X\n",data[0],data[1],data[2],data[3]);
dprintk("%s\n", __FUNCTION__);
/* stop the micro first */
nxt2002_microcontroller_stop(state);
/* set the i2c transfer speed to the tuner */
buf = 0x03;
i2c_writebytes(state,0x20,&buf,1);
/* setup to transfer 4 bytes via i2c */
buf = 0x04;
i2c_writebytes(state,0x34,&buf,1);
/* write actual tuner bytes */
i2c_writebytes(state,0x36,data,4);
/* set tuner i2c address */
buf = 0xC2;
i2c_writebytes(state,0x35,&buf,1);
/* write UC Opmode to begin transfer */
buf = 0x80;
i2c_writebytes(state,0x21,&buf,1);
while (count < 20) {
i2c_readbytes(state,0x21,&buf,1);
if ((buf & 0x80)== 0x00)
return 0;
msleep(100);
count++;
}
printk("nxt2002: timeout error writing tuner\n");
return 0;
}
static void nxt2002_agc_reset(struct nxt2002_state* state)
{
u8 buf;
dprintk("%s\n", __FUNCTION__);
buf = 0x08;
i2c_writebytes(state,0x08,&buf,1);
buf = 0x00;
i2c_writebytes(state,0x08,&buf,1);
return;
}
static int nxt2002_load_firmware (struct dvb_frontend* fe, const struct firmware *fw)
{
struct nxt2002_state* state = fe->demodulator_priv;
u8 buf[256],written = 0,chunkpos = 0;
u16 rambase,position,crc = 0;
dprintk("%s\n", __FUNCTION__);
dprintk("Firmware is %zu bytes\n",fw->size);
/* Get the RAM base for this nxt2002 */
i2c_readbytes(state,0x10,buf,1);
if (buf[0] & 0x10)
rambase = 0x1000;
else
rambase = 0x0000;
dprintk("rambase on this nxt2002 is %04X\n",rambase);
/* Hold the micro in reset while loading firmware */
buf[0] = 0x80;
i2c_writebytes(state,0x2B,buf,1);
for (position = 0; position < fw->size ; position++) {
if (written == 0) {
crc = 0;
chunkpos = 0x28;
buf[0] = ((rambase + position) >> 8);
buf[1] = (rambase + position) & 0xFF;
buf[2] = 0x81;
/* write starting address */
i2c_writebytes(state,0x29,buf,3);
}
written++;
chunkpos++;
if ((written % 4) == 0)
i2c_writebytes(state,chunkpos,&fw->data[position-3],4);
crc = nxt2002_crc(crc,fw->data[position]);
if ((written == 255) || (position+1 == fw->size)) {
/* write remaining bytes of firmware */
i2c_writebytes(state, chunkpos+4-(written %4),
&fw->data[position-(written %4) + 1],
written %4);
buf[0] = crc << 8;
buf[1] = crc & 0xFF;
/* write crc */
i2c_writebytes(state,0x2C,buf,2);
/* do a read to stop things */
i2c_readbytes(state,0x2A,buf,1);
/* set transfer mode to complete */
buf[0] = 0x80;
i2c_writebytes(state,0x2B,buf,1);
written = 0;
}
}
printk ("done.\n");
return 0;
};
static int nxt2002_setup_frontend_parameters (struct dvb_frontend* fe,
struct dvb_frontend_parameters *p)
{
struct nxt2002_state* state = fe->demodulator_priv;
u32 freq = 0;
u16 tunerfreq = 0;
u8 buf[4];
freq = 44000 + ( p->frequency / 1000 );
dprintk("freq = %d p->frequency = %d\n",freq,p->frequency);
tunerfreq = freq * 24/4000;
buf[0] = (tunerfreq >> 8) & 0x7F;
buf[1] = (tunerfreq & 0xFF);
if (p->frequency <= 214000000) {
buf[2] = 0x84 + (0x06 << 3);
buf[3] = (p->frequency <= 172000000) ? 0x01 : 0x02;
} else if (p->frequency <= 721000000) {
buf[2] = 0x84 + (0x07 << 3);
buf[3] = (p->frequency <= 467000000) ? 0x02 : 0x08;
} else if (p->frequency <= 841000000) {
buf[2] = 0x84 + (0x0E << 3);
buf[3] = 0x08;
} else {
buf[2] = 0x84 + (0x0F << 3);
buf[3] = 0x02;
}
/* write frequency information */
nxt2002_writetuner(state,buf);
/* reset the agc now that tuning has been completed */
nxt2002_agc_reset(state);
/* set target power level */
switch (p->u.vsb.modulation) {
case QAM_64:
case QAM_256:
buf[0] = 0x74;
break;
case VSB_8:
buf[0] = 0x70;
break;
default:
return -EINVAL;
break;
}
i2c_writebytes(state,0x42,buf,1);
/* configure sdm */
buf[0] = 0x87;
i2c_writebytes(state,0x57,buf,1);
/* write sdm1 input */
buf[0] = 0x10;
buf[1] = 0x00;
nxt2002_writereg_multibyte(state,0x58,buf,2);
/* write sdmx input */
switch (p->u.vsb.modulation) {
case QAM_64:
buf[0] = 0x68;
break;
case QAM_256:
buf[0] = 0x64;
break;
case VSB_8:
buf[0] = 0x60;
break;
default:
return -EINVAL;
break;
}
buf[1] = 0x00;
nxt2002_writereg_multibyte(state,0x5C,buf,2);
/* write adc power lpf fc */
buf[0] = 0x05;
i2c_writebytes(state,0x43,buf,1);
/* write adc power lpf fc */
buf[0] = 0x05;
i2c_writebytes(state,0x43,buf,1);
/* write accumulator2 input */
buf[0] = 0x80;
buf[1] = 0x00;
nxt2002_writereg_multibyte(state,0x4B,buf,2);
/* write kg1 */
buf[0] = 0x00;
i2c_writebytes(state,0x4D,buf,1);
/* write sdm12 lpf fc */
buf[0] = 0x44;
i2c_writebytes(state,0x55,buf,1);
/* write agc control reg */
buf[0] = 0x04;
i2c_writebytes(state,0x41,buf,1);
/* write agc ucgp0 */
switch (p->u.vsb.modulation) {
case QAM_64:
buf[0] = 0x02;
break;
case QAM_256:
buf[0] = 0x03;
break;
case VSB_8:
buf[0] = 0x00;
break;
default:
return -EINVAL;
break;
}
i2c_writebytes(state,0x30,buf,1);
/* write agc control reg */
buf[0] = 0x00;
i2c_writebytes(state,0x41,buf,1);
/* write accumulator2 input */
buf[0] = 0x80;
buf[1] = 0x00;
nxt2002_writereg_multibyte(state,0x49,buf,2);
nxt2002_writereg_multibyte(state,0x4B,buf,2);
/* write agc control reg */
buf[0] = 0x04;
i2c_writebytes(state,0x41,buf,1);
nxt2002_microcontroller_start(state);
/* adjacent channel detection should be done here, but I don't
have any stations with this need so I cannot test it */
return 0;
}
static int nxt2002_read_status(struct dvb_frontend* fe, fe_status_t* status)
{
struct nxt2002_state* state = fe->demodulator_priv;
u8 lock;
i2c_readbytes(state,0x31,&lock,1);
*status = 0;
if (lock & 0x20) {
*status |= FE_HAS_SIGNAL;
*status |= FE_HAS_CARRIER;
*status |= FE_HAS_VITERBI;
*status |= FE_HAS_SYNC;
*status |= FE_HAS_LOCK;
}
return 0;
}
static int nxt2002_read_ber(struct dvb_frontend* fe, u32* ber)
{
struct nxt2002_state* state = fe->demodulator_priv;
u8 b[3];
nxt2002_readreg_multibyte(state,0xE6,b,3);
*ber = ((b[0] << 8) + b[1]) * 8;
return 0;
}
static int nxt2002_read_signal_strength(struct dvb_frontend* fe, u16* strength)
{
struct nxt2002_state* state = fe->demodulator_priv;
u8 b[2];
u16 temp = 0;
/* setup to read cluster variance */
b[0] = 0x00;
i2c_writebytes(state,0xA1,b,1);
/* get multreg val */
nxt2002_readreg_multibyte(state,0xA6,b,2);
temp = (b[0] << 8) | b[1];
*strength = ((0x7FFF - temp) & 0x0FFF) * 16;
return 0;
}
static int nxt2002_read_snr(struct dvb_frontend* fe, u16* snr)
{
struct nxt2002_state* state = fe->demodulator_priv;
u8 b[2];
u16 temp = 0, temp2;
u32 snrdb = 0;
/* setup to read cluster variance */
b[0] = 0x00;
i2c_writebytes(state,0xA1,b,1);
/* get multreg val from 0xA6 */
nxt2002_readreg_multibyte(state,0xA6,b,2);
temp = (b[0] << 8) | b[1];
temp2 = 0x7FFF - temp;
/* snr will be in db */
if (temp2 > 0x7F00)
snrdb = 1000*24 + ( 1000*(30-24) * ( temp2 - 0x7F00 ) / ( 0x7FFF - 0x7F00 ) );
else if (temp2 > 0x7EC0)
snrdb = 1000*18 + ( 1000*(24-18) * ( temp2 - 0x7EC0 ) / ( 0x7F00 - 0x7EC0 ) );
else if (temp2 > 0x7C00)
snrdb = 1000*12 + ( 1000*(18-12) * ( temp2 - 0x7C00 ) / ( 0x7EC0 - 0x7C00 ) );
else
snrdb = 1000*0 + ( 1000*(12-0) * ( temp2 - 0 ) / ( 0x7C00 - 0 ) );
/* the value reported back from the frontend will be FFFF=32db 0000=0db */
*snr = snrdb * (0xFFFF/32000);
return 0;
}
static int nxt2002_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
{
struct nxt2002_state* state = fe->demodulator_priv;
u8 b[3];
nxt2002_readreg_multibyte(state,0xE6,b,3);
*ucblocks = b[2];
return 0;
}
static int nxt2002_sleep(struct dvb_frontend* fe)
{
return 0;
}
static int nxt2002_init(struct dvb_frontend* fe)
{
struct nxt2002_state* state = fe->demodulator_priv;
const struct firmware *fw;
int ret;
u8 buf[2];
if (!state->initialised) {
/* request the firmware, this will block until someone uploads it */
printk("nxt2002: Waiting for firmware upload (%s)...\n", NXT2002_DEFAULT_FIRMWARE);
ret = state->config->request_firmware(fe, &fw, NXT2002_DEFAULT_FIRMWARE);
printk("nxt2002: Waiting for firmware upload(2)...\n");
if (ret) {
printk("nxt2002: no firmware upload (timeout or file not found?)\n");
return ret;
}
ret = nxt2002_load_firmware(fe, fw);
if (ret) {
printk("nxt2002: writing firmware to device failed\n");
release_firmware(fw);
return ret;
}
printk("nxt2002: firmware upload complete\n");
/* Put the micro into reset */
nxt2002_microcontroller_stop(state);
/* ensure transfer is complete */
buf[0]=0;
i2c_writebytes(state,0x2B,buf,1);
/* Put the micro into reset for real this time */
nxt2002_microcontroller_stop(state);
/* soft reset everything (agc,frontend,eq,fec)*/
buf[0] = 0x0F;
i2c_writebytes(state,0x08,buf,1);
buf[0] = 0x00;
i2c_writebytes(state,0x08,buf,1);
/* write agc sdm configure */
buf[0] = 0xF1;
i2c_writebytes(state,0x57,buf,1);
/* write mod output format */
buf[0] = 0x20;
i2c_writebytes(state,0x09,buf,1);
/* write fec mpeg mode */
buf[0] = 0x7E;
buf[1] = 0x00;
i2c_writebytes(state,0xE9,buf,2);
/* write mux selection */
buf[0] = 0x00;
i2c_writebytes(state,0xCC,buf,1);
state->initialised = 1;
}
return 0;
}
static int nxt2002_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings)
{
fesettings->min_delay_ms = 500;
fesettings->step_size = 0;
fesettings->max_drift = 0;
return 0;
}
static void nxt2002_release(struct dvb_frontend* fe)
{
struct nxt2002_state* state = fe->demodulator_priv;
kfree(state);
}
static struct dvb_frontend_ops nxt2002_ops;
struct dvb_frontend* nxt2002_attach(const struct nxt2002_config* config,
struct i2c_adapter* i2c)
{
struct nxt2002_state* state = NULL;
u8 buf [] = {0,0,0,0,0};
/* allocate memory for the internal state */
state = kmalloc(sizeof(struct nxt2002_state), GFP_KERNEL);
if (state == NULL) goto error;
/* setup the state */
state->config = config;
state->i2c = i2c;
memcpy(&state->ops, &nxt2002_ops, sizeof(struct dvb_frontend_ops));
state->initialised = 0;
/* Check the first 5 registers to ensure this a revision we can handle */
i2c_readbytes(state, 0x00, buf, 5);
if (buf[0] != 0x04) goto error; /* device id */
if (buf[1] != 0x02) goto error; /* fab id */
if (buf[2] != 0x11) goto error; /* month */
if (buf[3] != 0x20) goto error; /* year msb */
if (buf[4] != 0x00) goto error; /* year lsb */
/* create dvb_frontend */
state->frontend.ops = &state->ops;
state->frontend.demodulator_priv = state;
return &state->frontend;
error:
kfree(state);
return NULL;
}
static struct dvb_frontend_ops nxt2002_ops = {
.info = {
.name = "Nextwave nxt2002 VSB/QAM frontend",
.type = FE_ATSC,
.frequency_min = 54000000,
.frequency_max = 860000000,
/* stepsize is just a guess */
.frequency_stepsize = 166666,
.caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
FE_CAN_8VSB | FE_CAN_QAM_64 | FE_CAN_QAM_256
},
.release = nxt2002_release,
.init = nxt2002_init,
.sleep = nxt2002_sleep,
.set_frontend = nxt2002_setup_frontend_parameters,
.get_tune_settings = nxt2002_get_tune_settings,
.read_status = nxt2002_read_status,
.read_ber = nxt2002_read_ber,
.read_signal_strength = nxt2002_read_signal_strength,
.read_snr = nxt2002_read_snr,
.read_ucblocks = nxt2002_read_ucblocks,
};
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
MODULE_DESCRIPTION("NXT2002 ATSC (8VSB & ITU J83 AnnexB FEC QAM64/256) demodulator driver");
MODULE_AUTHOR("Taylor Jacob");
MODULE_LICENSE("GPL");
EXPORT_SYMBOL(nxt2002_attach);
/*
Driver for the Nxt2002 demodulator
*/
#ifndef NXT2002_H
#define NXT2002_H
#include <linux/dvb/frontend.h>
#include <linux/firmware.h>
struct nxt2002_config
{
/* the demodulator's i2c address */
u8 demod_address;
/* request firmware for device */
int (*request_firmware)(struct dvb_frontend* fe, const struct firmware **fw, char* name);
};
extern struct dvb_frontend* nxt2002_attach(const struct nxt2002_config* config,
struct i2c_adapter* i2c);
#endif // NXT2002_H
/* /*
* Support for NXT2002 and NXT2004 - VSB/QAM * Support for NXT2002 and NXT2004 - VSB/QAM
* *
* Copyright (C) 2005 Kirk Lapray (kirk.lapray@gmail.com) * Copyright (C) 2005 Kirk Lapray <kirk.lapray@gmail.com>
* Copyright (C) 2006 Michael Krufky <mkrufky@m1k.net>
* based on nxt2002 by Taylor Jacob <rtjacob@earthlink.net> * based on nxt2002 by Taylor Jacob <rtjacob@earthlink.net>
* and nxt2004 by Jean-Francois Thibert (jeanfrancois@sagetv.com) * and nxt2004 by Jean-Francois Thibert <jeanfrancois@sagetv.com>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
...@@ -614,7 +615,17 @@ static int nxt200x_setup_frontend_parameters (struct dvb_frontend* fe, ...@@ -614,7 +615,17 @@ static int nxt200x_setup_frontend_parameters (struct dvb_frontend* fe,
/* write sdm1 input */ /* write sdm1 input */
buf[0] = 0x10; buf[0] = 0x10;
buf[1] = 0x00; buf[1] = 0x00;
switch (state->demod_chip) {
case NXT2002:
nxt200x_writereg_multibyte(state, 0x58, buf, 2);
break;
case NXT2004:
nxt200x_writebytes(state, 0x58, buf, 2); nxt200x_writebytes(state, 0x58, buf, 2);
break;
default:
return -EINVAL;
break;
}
/* write sdmx input */ /* write sdmx input */
switch (p->u.vsb.modulation) { switch (p->u.vsb.modulation) {
...@@ -632,7 +643,17 @@ static int nxt200x_setup_frontend_parameters (struct dvb_frontend* fe, ...@@ -632,7 +643,17 @@ static int nxt200x_setup_frontend_parameters (struct dvb_frontend* fe,
break; break;
} }
buf[1] = 0x00; buf[1] = 0x00;
switch (state->demod_chip) {
case NXT2002:
nxt200x_writereg_multibyte(state, 0x5C, buf, 2);
break;
case NXT2004:
nxt200x_writebytes(state, 0x5C, buf, 2); nxt200x_writebytes(state, 0x5C, buf, 2);
break;
default:
return -EINVAL;
break;
}
/* write adc power lpf fc */ /* write adc power lpf fc */
buf[0] = 0x05; buf[0] = 0x05;
...@@ -648,7 +669,17 @@ static int nxt200x_setup_frontend_parameters (struct dvb_frontend* fe, ...@@ -648,7 +669,17 @@ static int nxt200x_setup_frontend_parameters (struct dvb_frontend* fe,
/* write accumulator2 input */ /* write accumulator2 input */
buf[0] = 0x80; buf[0] = 0x80;
buf[1] = 0x00; buf[1] = 0x00;
switch (state->demod_chip) {
case NXT2002:
nxt200x_writereg_multibyte(state, 0x4B, buf, 2);
break;
case NXT2004:
nxt200x_writebytes(state, 0x4B, buf, 2); nxt200x_writebytes(state, 0x4B, buf, 2);
break;
default:
return -EINVAL;
break;
}
/* write kg1 */ /* write kg1 */
buf[0] = 0x00; buf[0] = 0x00;
...@@ -714,8 +745,19 @@ static int nxt200x_setup_frontend_parameters (struct dvb_frontend* fe, ...@@ -714,8 +745,19 @@ static int nxt200x_setup_frontend_parameters (struct dvb_frontend* fe,
/* write accumulator2 input */ /* write accumulator2 input */
buf[0] = 0x80; buf[0] = 0x80;
buf[1] = 0x00; buf[1] = 0x00;
nxt200x_writebytes(state, 0x49, buf,2); switch (state->demod_chip) {
nxt200x_writebytes(state, 0x4B, buf,2); case NXT2002:
nxt200x_writereg_multibyte(state, 0x49, buf, 2);
nxt200x_writereg_multibyte(state, 0x4B, buf, 2);
break;
case NXT2004:
nxt200x_writebytes(state, 0x49, buf, 2);
nxt200x_writebytes(state, 0x4B, buf, 2);
break;
default:
return -EINVAL;
break;
}
/* write agc control reg */ /* write agc control reg */
buf[0] = 0x04; buf[0] = 0x04;
...@@ -1199,7 +1241,7 @@ module_param(debug, int, 0644); ...@@ -1199,7 +1241,7 @@ module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
MODULE_DESCRIPTION("NXT200X (ATSC 8VSB & ITU-T J.83 AnnexB 64/256 QAM) Demodulator Driver"); MODULE_DESCRIPTION("NXT200X (ATSC 8VSB & ITU-T J.83 AnnexB 64/256 QAM) Demodulator Driver");
MODULE_AUTHOR("Kirk Lapray, Jean-Francois Thibert, and Taylor Jacob"); MODULE_AUTHOR("Kirk Lapray, Michael Krufky, Jean-Francois Thibert, and Taylor Jacob");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
EXPORT_SYMBOL(nxt200x_attach); EXPORT_SYMBOL(nxt200x_attach);
......
/*
* tda80xx.c
*
* Philips TDA8044 / TDA8083 QPSK demodulator driver
*
* Copyright (C) 2001 Felix Domke <tmbinc@elitedvb.net>
* Copyright (C) 2002-2004 Andreas Oberritter <obi@linuxtv.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/config.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/spinlock.h>
#include <linux/threads.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <asm/irq.h>
#include <asm/div64.h>
#include "dvb_frontend.h"
#include "tda80xx.h"
enum {
ID_TDA8044 = 0x04,
ID_TDA8083 = 0x05,
};
struct tda80xx_state {
struct i2c_adapter* i2c;
struct dvb_frontend_ops ops;
/* configuration settings */
const struct tda80xx_config* config;
struct dvb_frontend frontend;
u32 clk;
int afc_loop;
struct work_struct worklet;
fe_code_rate_t code_rate;
fe_spectral_inversion_t spectral_inversion;
fe_status_t status;
u8 id;
};
static int debug = 1;
#define dprintk if (debug) printk
static u8 tda8044_inittab_pre[] = {
0x02, 0x00, 0x6f, 0xb5, 0x86, 0x22, 0x00, 0xea,
0x30, 0x42, 0x98, 0x68, 0x70, 0x42, 0x99, 0x58,
0x95, 0x10, 0xf5, 0xe7, 0x93, 0x0b, 0x15, 0x68,
0x9a, 0x90, 0x61, 0x80, 0x00, 0xe0, 0x40, 0x00,
0x0f, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00
};
static u8 tda8044_inittab_post[] = {
0x04, 0x00, 0x6f, 0xb5, 0x86, 0x22, 0x00, 0xea,
0x30, 0x42, 0x98, 0x68, 0x70, 0x42, 0x99, 0x50,
0x95, 0x10, 0xf5, 0xe7, 0x93, 0x0b, 0x15, 0x68,
0x9a, 0x90, 0x61, 0x80, 0x00, 0xe0, 0x40, 0x6c,
0x0f, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00
};
static u8 tda8083_inittab[] = {
0x04, 0x00, 0x4a, 0x79, 0x04, 0x00, 0xff, 0xea,
0x48, 0x42, 0x79, 0x60, 0x70, 0x52, 0x9a, 0x10,
0x0e, 0x10, 0xf2, 0xa7, 0x93, 0x0b, 0x05, 0xc8,
0x9d, 0x00, 0x42, 0x80, 0x00, 0x60, 0x40, 0x00,
0x00, 0x75, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00
};
static __inline__ u32 tda80xx_div(u32 a, u32 b)
{
return (a + (b / 2)) / b;
}
static __inline__ u32 tda80xx_gcd(u32 a, u32 b)
{
u32 r;
while ((r = a % b)) {
a = b;
b = r;
}
return b;
}
static int tda80xx_read(struct tda80xx_state* state, u8 reg, u8 *buf, u8 len)
{
int ret;
struct i2c_msg msg[] = { { .addr = state->config->demod_address, .flags = 0, .buf = &reg, .len = 1 },
{ .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = buf, .len = len } };
ret = i2c_transfer(state->i2c, msg, 2);
if (ret != 2)
dprintk("%s: readreg error (reg %02x, ret == %i)\n",
__FUNCTION__, reg, ret);
mdelay(10);
return (ret == 2) ? 0 : -EREMOTEIO;
}
static int tda80xx_write(struct tda80xx_state* state, u8 reg, const u8 *buf, u8 len)
{
int ret;
u8 wbuf[len + 1];
struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = wbuf, .len = len + 1 };
wbuf[0] = reg;
memcpy(&wbuf[1], buf, len);
ret = i2c_transfer(state->i2c, &msg, 1);
if (ret != 1)
dprintk("%s: i2c xfer error (ret == %i)\n", __FUNCTION__, ret);
mdelay(10);
return (ret == 1) ? 0 : -EREMOTEIO;
}
static __inline__ u8 tda80xx_readreg(struct tda80xx_state* state, u8 reg)
{
u8 val;
tda80xx_read(state, reg, &val, 1);
return val;
}
static __inline__ int tda80xx_writereg(struct tda80xx_state* state, u8 reg, u8 data)
{
return tda80xx_write(state, reg, &data, 1);
}
static int tda80xx_set_parameters(struct tda80xx_state* state,
fe_spectral_inversion_t inversion,
u32 symbol_rate,
fe_code_rate_t fec_inner)
{
u8 buf[15];
u64 ratio;
u32 clk;
u32 k;
u32 sr = symbol_rate;
u32 gcd;
u8 scd;
if (symbol_rate > (state->clk * 3) / 16)
scd = 0;
else if (symbol_rate > (state->clk * 3) / 32)
scd = 1;
else if (symbol_rate > (state->clk * 3) / 64)
scd = 2;
else
scd = 3;
clk = scd ? (state->clk / (scd * 2)) : state->clk;
/*
* Viterbi decoder:
* Differential decoding off
* Spectral inversion unknown
* QPSK modulation
*/
if (inversion == INVERSION_ON)
buf[0] = 0x60;
else if (inversion == INVERSION_OFF)
buf[0] = 0x20;
else
buf[0] = 0x00;
/*
* CLK ratio:
* system clock frequency is up to 64 or 96 MHz
*
* formula:
* r = k * clk / symbol_rate
*
* k: 2^21 for caa 0..3,
* 2^20 for caa 4..5,
* 2^19 for caa 6..7
*/
if (symbol_rate <= (clk * 3) / 32)
k = (1 << 19);
else if (symbol_rate <= (clk * 3) / 16)
k = (1 << 20);
else
k = (1 << 21);
gcd = tda80xx_gcd(clk, sr);
clk /= gcd;
sr /= gcd;
gcd = tda80xx_gcd(k, sr);
k /= gcd;
sr /= gcd;
ratio = (u64)k * (u64)clk;
do_div(ratio, sr);
buf[1] = ratio >> 16;
buf[2] = ratio >> 8;
buf[3] = ratio;
/* nyquist filter roll-off factor 35% */
buf[4] = 0x20;
clk = scd ? (state->clk / (scd * 2)) : state->clk;
/* Anti Alias Filter */
if (symbol_rate < (clk * 3) / 64)
printk("tda80xx: unsupported symbol rate: %u\n", symbol_rate);
else if (symbol_rate <= clk / 16)
buf[4] |= 0x07;
else if (symbol_rate <= (clk * 3) / 32)
buf[4] |= 0x06;
else if (symbol_rate <= clk / 8)
buf[4] |= 0x05;
else if (symbol_rate <= (clk * 3) / 16)
buf[4] |= 0x04;
else if (symbol_rate <= clk / 4)
buf[4] |= 0x03;
else if (symbol_rate <= (clk * 3) / 8)
buf[4] |= 0x02;
else if (symbol_rate <= clk / 2)
buf[4] |= 0x01;
else
buf[4] |= 0x00;
/* Sigma Delta converter */
buf[5] = 0x00;
/* FEC: Possible puncturing rates */
if (fec_inner == FEC_NONE)
buf[6] = 0x00;
else if ((fec_inner >= FEC_1_2) && (fec_inner <= FEC_8_9))
buf[6] = (1 << (8 - fec_inner));
else if (fec_inner == FEC_AUTO)
buf[6] = 0xff;
else
return -EINVAL;
/* carrier lock detector threshold value */
buf[7] = 0x30;
/* AFC1: proportional part settings */
buf[8] = 0x42;
/* AFC1: integral part settings */
buf[9] = 0x98;
/* PD: Leaky integrator SCPC mode */
buf[10] = 0x28;
/* AFC2, AFC1 controls */
buf[11] = 0x30;
/* PD: proportional part settings */
buf[12] = 0x42;
/* PD: integral part settings */
buf[13] = 0x99;
/* AGC */
buf[14] = 0x50 | scd;
printk("symbol_rate=%u clk=%u\n", symbol_rate, clk);
return tda80xx_write(state, 0x01, buf, sizeof(buf));
}
static int tda80xx_set_clk(struct tda80xx_state* state)
{
u8 buf[2];
/* CLK proportional part */
buf[0] = (0x06 << 5) | 0x08; /* CMP[2:0], CSP[4:0] */
/* CLK integral part */
buf[1] = (0x04 << 5) | 0x1a; /* CMI[2:0], CSI[4:0] */
return tda80xx_write(state, 0x17, buf, sizeof(buf));
}
#if 0
static int tda80xx_set_scpc_freq_offset(struct tda80xx_state* state)
{
/* a constant value is nonsense here imho */
return tda80xx_writereg(state, 0x22, 0xf9);
}
#endif
static int tda80xx_close_loop(struct tda80xx_state* state)
{
u8 buf[2];
/* PD: Loop closed, LD: lock detect enable, SCPC: Sweep mode - AFC1 loop closed */
buf[0] = 0x68;
/* AFC1: Loop closed, CAR Feedback: 8192 */
buf[1] = 0x70;
return tda80xx_write(state, 0x0b, buf, sizeof(buf));
}
static irqreturn_t tda80xx_irq(int irq, void *priv, struct pt_regs *pt)
{
schedule_work(priv);
return IRQ_HANDLED;
}
static void tda80xx_read_status_int(struct tda80xx_state* state)
{
u8 val;
static const fe_spectral_inversion_t inv_tab[] = {
INVERSION_OFF, INVERSION_ON
};
static const fe_code_rate_t fec_tab[] = {
FEC_8_9, FEC_1_2, FEC_2_3, FEC_3_4,
FEC_4_5, FEC_5_6, FEC_6_7, FEC_7_8,
};
val = tda80xx_readreg(state, 0x02);
state->status = 0;
if (val & 0x01) /* demodulator lock */
state->status |= FE_HAS_SIGNAL;
if (val & 0x02) /* clock recovery lock */
state->status |= FE_HAS_CARRIER;
if (val & 0x04) /* viterbi lock */
state->status |= FE_HAS_VITERBI;
if (val & 0x08) /* deinterleaver lock (packet sync) */
state->status |= FE_HAS_SYNC;
if (val & 0x10) /* derandomizer lock (frame sync) */
state->status |= FE_HAS_LOCK;
if (val & 0x20) /* frontend can not lock */
state->status |= FE_TIMEDOUT;
if ((state->status & (FE_HAS_CARRIER)) && (state->afc_loop)) {
printk("tda80xx: closing loop\n");
tda80xx_close_loop(state);
state->afc_loop = 0;
}
if (state->status & (FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK)) {
val = tda80xx_readreg(state, 0x0e);
state->code_rate = fec_tab[val & 0x07];
if (state->status & (FE_HAS_SYNC | FE_HAS_LOCK))
state->spectral_inversion = inv_tab[(val >> 7) & 0x01];
else
state->spectral_inversion = INVERSION_AUTO;
}
else {
state->code_rate = FEC_AUTO;
}
}
static void tda80xx_worklet(void *priv)
{
struct tda80xx_state *state = priv;
tda80xx_writereg(state, 0x00, 0x04);
enable_irq(state->config->irq);
tda80xx_read_status_int(state);
}
static void tda80xx_wait_diseqc_fifo(struct tda80xx_state* state)
{
size_t i;
for (i = 0; i < 100; i++) {
if (tda80xx_readreg(state, 0x02) & 0x80)
break;
msleep(10);
}
}
static int tda8044_init(struct dvb_frontend* fe)
{
struct tda80xx_state* state = fe->demodulator_priv;
int ret;
/*
* this function is a mess...
*/
if ((ret = tda80xx_write(state, 0x00, tda8044_inittab_pre, sizeof(tda8044_inittab_pre))))
return ret;
tda80xx_writereg(state, 0x0f, 0x50);
#if 1
tda80xx_writereg(state, 0x20, 0x8F); /* FIXME */
tda80xx_writereg(state, 0x20, state->config->volt18setting); /* FIXME */
//tda80xx_writereg(state, 0x00, 0x04);
tda80xx_writereg(state, 0x00, 0x0C);
#endif
//tda80xx_writereg(state, 0x00, 0x08); /* Reset AFC1 loop filter */
tda80xx_write(state, 0x00, tda8044_inittab_post, sizeof(tda8044_inittab_post));
if (state->config->pll_init) {
tda80xx_writereg(state, 0x1c, 0x80);
state->config->pll_init(fe);
tda80xx_writereg(state, 0x1c, 0x00);
}
return 0;
}
static int tda8083_init(struct dvb_frontend* fe)
{
struct tda80xx_state* state = fe->demodulator_priv;
tda80xx_write(state, 0x00, tda8083_inittab, sizeof(tda8083_inittab));
if (state->config->pll_init) {
tda80xx_writereg(state, 0x1c, 0x80);
state->config->pll_init(fe);
tda80xx_writereg(state, 0x1c, 0x00);
}
return 0;
}
static int tda80xx_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
{
struct tda80xx_state* state = fe->demodulator_priv;
switch (voltage) {
case SEC_VOLTAGE_13:
return tda80xx_writereg(state, 0x20, state->config->volt13setting);
case SEC_VOLTAGE_18:
return tda80xx_writereg(state, 0x20, state->config->volt18setting);
case SEC_VOLTAGE_OFF:
return tda80xx_writereg(state, 0x20, 0);
default:
return -EINVAL;
}
}
static int tda80xx_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
{
struct tda80xx_state* state = fe->demodulator_priv;
switch (tone) {
case SEC_TONE_OFF:
return tda80xx_writereg(state, 0x29, 0x00);
case SEC_TONE_ON:
return tda80xx_writereg(state, 0x29, 0x80);
default:
return -EINVAL;
}
}
static int tda80xx_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd *cmd)
{
struct tda80xx_state* state = fe->demodulator_priv;
if (cmd->msg_len > 6)
return -EINVAL;
tda80xx_writereg(state, 0x29, 0x08 | (cmd->msg_len - 3));
tda80xx_write(state, 0x23, cmd->msg, cmd->msg_len);
tda80xx_writereg(state, 0x29, 0x0c | (cmd->msg_len - 3));
tda80xx_wait_diseqc_fifo(state);
return 0;
}
static int tda80xx_send_diseqc_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t cmd)
{
struct tda80xx_state* state = fe->demodulator_priv;
switch (cmd) {
case SEC_MINI_A:
tda80xx_writereg(state, 0x29, 0x14);
break;
case SEC_MINI_B:
tda80xx_writereg(state, 0x29, 0x1c);
break;
default:
return -EINVAL;
}
tda80xx_wait_diseqc_fifo(state);
return 0;
}
static int tda80xx_sleep(struct dvb_frontend* fe)
{
struct tda80xx_state* state = fe->demodulator_priv;
tda80xx_writereg(state, 0x00, 0x02); /* enter standby */
return 0;
}
static int tda80xx_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
{
struct tda80xx_state* state = fe->demodulator_priv;
tda80xx_writereg(state, 0x1c, 0x80);
state->config->pll_set(fe, p);
tda80xx_writereg(state, 0x1c, 0x00);
tda80xx_set_parameters(state, p->inversion, p->u.qpsk.symbol_rate, p->u.qpsk.fec_inner);
tda80xx_set_clk(state);
//tda80xx_set_scpc_freq_offset(state);
state->afc_loop = 1;
return 0;
}
static int tda80xx_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
{
struct tda80xx_state* state = fe->demodulator_priv;
if (!state->config->irq)
tda80xx_read_status_int(state);
p->inversion = state->spectral_inversion;
p->u.qpsk.fec_inner = state->code_rate;
return 0;
}
static int tda80xx_read_status(struct dvb_frontend* fe, fe_status_t* status)
{
struct tda80xx_state* state = fe->demodulator_priv;
if (!state->config->irq)
tda80xx_read_status_int(state);
*status = state->status;
return 0;
}
static int tda80xx_read_ber(struct dvb_frontend* fe, u32* ber)
{
struct tda80xx_state* state = fe->demodulator_priv;
int ret;
u8 buf[3];
if ((ret = tda80xx_read(state, 0x0b, buf, sizeof(buf))))
return ret;
*ber = ((buf[0] & 0x1f) << 16) | (buf[1] << 8) | buf[2];
return 0;
}
static int tda80xx_read_signal_strength(struct dvb_frontend* fe, u16* strength)
{
struct tda80xx_state* state = fe->demodulator_priv;
u8 gain = ~tda80xx_readreg(state, 0x01);
*strength = (gain << 8) | gain;
return 0;
}
static int tda80xx_read_snr(struct dvb_frontend* fe, u16* snr)
{
struct tda80xx_state* state = fe->demodulator_priv;
u8 quality = tda80xx_readreg(state, 0x08);
*snr = (quality << 8) | quality;
return 0;
}
static int tda80xx_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
{
struct tda80xx_state* state = fe->demodulator_priv;
*ucblocks = tda80xx_readreg(state, 0x0f);
if (*ucblocks == 0xff)
*ucblocks = 0xffffffff;
return 0;
}
static int tda80xx_init(struct dvb_frontend* fe)
{
struct tda80xx_state* state = fe->demodulator_priv;
switch(state->id) {
case ID_TDA8044:
return tda8044_init(fe);
case ID_TDA8083:
return tda8083_init(fe);
}
return 0;
}
static void tda80xx_release(struct dvb_frontend* fe)
{
struct tda80xx_state* state = fe->demodulator_priv;
if (state->config->irq)
free_irq(state->config->irq, &state->worklet);
kfree(state);
}
static struct dvb_frontend_ops tda80xx_ops;
struct dvb_frontend* tda80xx_attach(const struct tda80xx_config* config,
struct i2c_adapter* i2c)
{
struct tda80xx_state* state = NULL;
int ret;
/* allocate memory for the internal state */
state = kmalloc(sizeof(struct tda80xx_state), GFP_KERNEL);
if (state == NULL) goto error;
/* setup the state */
state->config = config;
state->i2c = i2c;
memcpy(&state->ops, &tda80xx_ops, sizeof(struct dvb_frontend_ops));
state->spectral_inversion = INVERSION_AUTO;
state->code_rate = FEC_AUTO;
state->status = 0;
state->afc_loop = 0;
/* check if the demod is there */
if (tda80xx_writereg(state, 0x89, 0x00) < 0) goto error;
state->id = tda80xx_readreg(state, 0x00);
switch (state->id) {
case ID_TDA8044:
state->clk = 96000000;
printk("tda80xx: Detected tda8044\n");
break;
case ID_TDA8083:
state->clk = 64000000;
printk("tda80xx: Detected tda8083\n");
break;
default:
goto error;
}
/* setup IRQ */
if (state->config->irq) {
INIT_WORK(&state->worklet, tda80xx_worklet, state);
if ((ret = request_irq(state->config->irq, tda80xx_irq, SA_ONESHOT, "tda80xx", &state->worklet)) < 0) {
printk(KERN_ERR "tda80xx: request_irq failed (%d)\n", ret);
goto error;
}
}
/* create dvb_frontend */
state->frontend.ops = &state->ops;
state->frontend.demodulator_priv = state;
return &state->frontend;
error:
kfree(state);
return NULL;
}
static struct dvb_frontend_ops tda80xx_ops = {
.info = {
.name = "Philips TDA80xx DVB-S",
.type = FE_QPSK,
.frequency_min = 500000,
.frequency_max = 2700000,
.frequency_stepsize = 125,
.symbol_rate_min = 4500000,
.symbol_rate_max = 45000000,
.caps = FE_CAN_INVERSION_AUTO |
FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 |
FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO |
FE_CAN_QPSK |
FE_CAN_MUTE_TS
},
.release = tda80xx_release,
.init = tda80xx_init,
.sleep = tda80xx_sleep,
.set_frontend = tda80xx_set_frontend,
.get_frontend = tda80xx_get_frontend,
.read_status = tda80xx_read_status,
.read_ber = tda80xx_read_ber,
.read_signal_strength = tda80xx_read_signal_strength,
.read_snr = tda80xx_read_snr,
.read_ucblocks = tda80xx_read_ucblocks,
.diseqc_send_master_cmd = tda80xx_send_diseqc_msg,
.diseqc_send_burst = tda80xx_send_diseqc_burst,
.set_tone = tda80xx_set_tone,
.set_voltage = tda80xx_set_voltage,
};
module_param(debug, int, 0644);
MODULE_DESCRIPTION("Philips TDA8044 / TDA8083 DVB-S Demodulator driver");
MODULE_AUTHOR("Felix Domke, Andreas Oberritter");
MODULE_LICENSE("GPL");
EXPORT_SYMBOL(tda80xx_attach);
/*
* tda80xx.c
*
* Philips TDA8044 / TDA8083 QPSK demodulator driver
*
* Copyright (C) 2001 Felix Domke <tmbinc@elitedvb.net>
* Copyright (C) 2002-2004 Andreas Oberritter <obi@linuxtv.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef TDA80XX_H
#define TDA80XX_H
#include <linux/dvb/frontend.h>
struct tda80xx_config
{
/* the demodulator's i2c address */
u8 demod_address;
/* IRQ to use (0=>no IRQ used) */
u32 irq;
/* Register setting to use for 13v */
u8 volt13setting;
/* Register setting to use for 18v */
u8 volt18setting;
/* PLL maintenance */
int (*pll_init)(struct dvb_frontend* fe);
int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
};
extern struct dvb_frontend* tda80xx_attach(const struct tda80xx_config* config,
struct i2c_adapter* i2c);
#endif // TDA80XX_H
...@@ -2329,6 +2329,17 @@ static int frontend_init(struct av7110 *av7110) ...@@ -2329,6 +2329,17 @@ static int frontend_init(struct av7110 *av7110)
av7110->fe = ves1820_attach(&alps_tdbe2_config, &av7110->i2c_adap, read_pwm(av7110)); av7110->fe = ves1820_attach(&alps_tdbe2_config, &av7110->i2c_adap, read_pwm(av7110));
break; break;
case 0x0004: // Galaxis DVB-S rev1.3
/* ALPS BSRV2 */
av7110->fe = ves1x93_attach(&alps_bsrv2_config, &av7110->i2c_adap);
if (av7110->fe) {
av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst;
av7110->fe->ops->set_tone = av7110_set_tone;
av7110->recover = dvb_s_recover;
}
break;
case 0x0006: /* Fujitsu-Siemens DVB-S rev 1.6 */ case 0x0006: /* Fujitsu-Siemens DVB-S rev 1.6 */
/* Grundig 29504-451 */ /* Grundig 29504-451 */
av7110->fe = tda8083_attach(&grundig_29504_451_config, &av7110->i2c_adap); av7110->fe = tda8083_attach(&grundig_29504_451_config, &av7110->i2c_adap);
...@@ -2930,6 +2941,7 @@ MAKE_AV7110_INFO(tts_1_3se, "Technotrend/Hauppauge WinTV DVB-S rev1.3 SE"); ...@@ -2930,6 +2941,7 @@ MAKE_AV7110_INFO(tts_1_3se, "Technotrend/Hauppauge WinTV DVB-S rev1.3 SE");
MAKE_AV7110_INFO(ttt, "Technotrend/Hauppauge DVB-T"); MAKE_AV7110_INFO(ttt, "Technotrend/Hauppauge DVB-T");
MAKE_AV7110_INFO(fsc, "Fujitsu Siemens DVB-C"); MAKE_AV7110_INFO(fsc, "Fujitsu Siemens DVB-C");
MAKE_AV7110_INFO(fss, "Fujitsu Siemens DVB-S rev1.6"); MAKE_AV7110_INFO(fss, "Fujitsu Siemens DVB-S rev1.6");
MAKE_AV7110_INFO(gxs_1_3, "Galaxis DVB-S rev1.3");
static struct pci_device_id pci_tbl[] = { static struct pci_device_id pci_tbl[] = {
MAKE_EXTENSION_PCI(fsc, 0x110a, 0x0000), MAKE_EXTENSION_PCI(fsc, 0x110a, 0x0000),
...@@ -2937,13 +2949,13 @@ static struct pci_device_id pci_tbl[] = { ...@@ -2937,13 +2949,13 @@ static struct pci_device_id pci_tbl[] = {
MAKE_EXTENSION_PCI(ttt_1_X, 0x13c2, 0x0001), MAKE_EXTENSION_PCI(ttt_1_X, 0x13c2, 0x0001),
MAKE_EXTENSION_PCI(ttc_2_X, 0x13c2, 0x0002), MAKE_EXTENSION_PCI(ttc_2_X, 0x13c2, 0x0002),
MAKE_EXTENSION_PCI(tts_2_X, 0x13c2, 0x0003), MAKE_EXTENSION_PCI(tts_2_X, 0x13c2, 0x0003),
MAKE_EXTENSION_PCI(gxs_1_3, 0x13c2, 0x0004),
MAKE_EXTENSION_PCI(fss, 0x13c2, 0x0006), MAKE_EXTENSION_PCI(fss, 0x13c2, 0x0006),
MAKE_EXTENSION_PCI(ttt, 0x13c2, 0x0008), MAKE_EXTENSION_PCI(ttt, 0x13c2, 0x0008),
MAKE_EXTENSION_PCI(ttc_1_X, 0x13c2, 0x000a), MAKE_EXTENSION_PCI(ttc_1_X, 0x13c2, 0x000a),
MAKE_EXTENSION_PCI(tts_2_3, 0x13c2, 0x000e), MAKE_EXTENSION_PCI(tts_2_3, 0x13c2, 0x000e),
MAKE_EXTENSION_PCI(tts_1_3se, 0x13c2, 0x1002), MAKE_EXTENSION_PCI(tts_1_3se, 0x13c2, 0x1002),
/* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0004), UNDEFINED CARD */ // Galaxis DVB PC-Sat-Carte
/* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0005), UNDEFINED CARD */ // Technisat SkyStar1 /* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0005), UNDEFINED CARD */ // Technisat SkyStar1
/* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0009), UNDEFINED CARD */ // TT/Hauppauge WinTV Nexus-CA v???? /* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0009), UNDEFINED CARD */ // TT/Hauppauge WinTV Nexus-CA v????
......
...@@ -273,8 +273,6 @@ struct av7110 { ...@@ -273,8 +273,6 @@ struct av7110 {
extern int ChangePIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid, extern int ChangePIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid,
u16 subpid, u16 pcrpid); u16 subpid, u16 pcrpid);
extern int av7110_setup_irc_config (struct av7110 *av7110, u32 ir_config);
extern int av7110_ir_init(struct av7110 *av7110); extern int av7110_ir_init(struct av7110 *av7110);
extern void av7110_ir_exit(struct av7110 *av7110); extern void av7110_ir_exit(struct av7110 *av7110);
......
...@@ -155,6 +155,19 @@ static void input_repeat_key(unsigned long data) ...@@ -155,6 +155,19 @@ static void input_repeat_key(unsigned long data)
} }
static int av7110_setup_irc_config(struct av7110 *av7110, u32 ir_config)
{
int ret = 0;
dprintk(4, "%p\n", av7110);
if (av7110) {
ret = av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, SetIR, 1, ir_config);
av7110->ir_config = ir_config;
}
return ret;
}
static int av7110_ir_write_proc(struct file *file, const char __user *buffer, static int av7110_ir_write_proc(struct file *file, const char __user *buffer,
unsigned long count, void *data) unsigned long count, void *data)
{ {
...@@ -187,19 +200,6 @@ static int av7110_ir_write_proc(struct file *file, const char __user *buffer, ...@@ -187,19 +200,6 @@ static int av7110_ir_write_proc(struct file *file, const char __user *buffer,
} }
int av7110_setup_irc_config(struct av7110 *av7110, u32 ir_config)
{
int ret = 0;
dprintk(4, "%p\n", av7110);
if (av7110) {
ret = av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, SetIR, 1, ir_config);
av7110->ir_config = ir_config;
}
return ret;
}
static void ir_handler(struct av7110 *av7110, u32 ircom) static void ir_handler(struct av7110 *av7110, u32 ircom)
{ {
dprintk(4, "ircommand = %08x\n", ircom); dprintk(4, "ircommand = %08x\n", ircom);
......
...@@ -214,7 +214,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = { ...@@ -214,7 +214,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = {
we can capture, of the first and second field. */ we can capture, of the first and second field. */
.vbistart = { 7,320 }, .vbistart = { 7,320 },
},{ },{
.v4l2_id = V4L2_STD_NTSC_M, .v4l2_id = V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_KR,
.name = "NTSC", .name = "NTSC",
.Fsc = 28636363, .Fsc = 28636363,
.swidth = 768, .swidth = 768,
......
...@@ -220,33 +220,23 @@ static void input_change(struct i2c_client *client) ...@@ -220,33 +220,23 @@ static void input_change(struct i2c_client *client)
cx25840_write(client, 0x808, 0xff); cx25840_write(client, 0x808, 0xff);
cx25840_write(client, 0x80b, 0x10); cx25840_write(client, 0x80b, 0x10);
} else if (std & V4L2_STD_NTSC) { } else if (std & V4L2_STD_NTSC) {
/* NTSC */
if (state->pvr150_workaround) {
/* Certain Hauppauge PVR150 models have a hardware bug /* Certain Hauppauge PVR150 models have a hardware bug
that causes audio to drop out. For these models the that causes audio to drop out. For these models the
audio standard must be set explicitly. audio standard must be set explicitly.
To be precise: it affects cards with tuner models To be precise: it affects cards with tuner models
85, 99 and 112 (model numbers from tveeprom). */ 85, 99 and 112 (model numbers from tveeprom). */
int hw_fix = state->pvr150_workaround;
if (std == V4L2_STD_NTSC_M_JP) { if (std == V4L2_STD_NTSC_M_JP) {
/* Japan uses EIAJ audio standard */ /* Japan uses EIAJ audio standard */
cx25840_write(client, 0x808, 0x2f); cx25840_write(client, 0x808, hw_fix ? 0x2f : 0xf7);
} else { } else if (std == V4L2_STD_NTSC_M_KR) {
/* Others use the BTSC audio standard */ /* South Korea uses A2 audio standard */
cx25840_write(client, 0x808, 0x1f); cx25840_write(client, 0x808, hw_fix ? 0x3f : 0xf8);
}
/* South Korea uses the A2-M (aka Zweiton M) audio
standard, and should set 0x808 to 0x3f, but I don't
know how to detect this. */
} else if (std == V4L2_STD_NTSC_M_JP) {
/* Japan uses EIAJ audio standard */
cx25840_write(client, 0x808, 0xf7);
} else { } else {
/* Others use the BTSC audio standard */ /* Others use the BTSC audio standard */
cx25840_write(client, 0x808, 0xf6); cx25840_write(client, 0x808, hw_fix ? 0x1f : 0xf6);
} }
/* South Korea uses the A2-M (aka Zweiton M) audio standard,
and should set 0x808 to 0xf8, but I don't know how to
detect this. */
cx25840_write(client, 0x80b, 0x00); cx25840_write(client, 0x80b, 0x00);
} }
...@@ -330,17 +320,17 @@ static int set_v4lstd(struct i2c_client *client, v4l2_std_id std) ...@@ -330,17 +320,17 @@ static int set_v4lstd(struct i2c_client *client, v4l2_std_id std)
u8 fmt=0; /* zero is autodetect */ u8 fmt=0; /* zero is autodetect */
/* First tests should be against specific std */ /* First tests should be against specific std */
if (std & V4L2_STD_NTSC_M_JP) { if (std == V4L2_STD_NTSC_M_JP) {
fmt=0x2; fmt=0x2;
} else if (std & V4L2_STD_NTSC_443) { } else if (std == V4L2_STD_NTSC_443) {
fmt=0x3; fmt=0x3;
} else if (std & V4L2_STD_PAL_M) { } else if (std == V4L2_STD_PAL_M) {
fmt=0x5; fmt=0x5;
} else if (std & V4L2_STD_PAL_N) { } else if (std == V4L2_STD_PAL_N) {
fmt=0x6; fmt=0x6;
} else if (std & V4L2_STD_PAL_Nc) { } else if (std == V4L2_STD_PAL_Nc) {
fmt=0x7; fmt=0x7;
} else if (std & V4L2_STD_PAL_60) { } else if (std == V4L2_STD_PAL_60) {
fmt=0x8; fmt=0x8;
} else { } else {
/* Then, test against generic ones */ /* Then, test against generic ones */
...@@ -369,7 +359,7 @@ v4l2_std_id cx25840_get_v4lstd(struct i2c_client * client) ...@@ -369,7 +359,7 @@ v4l2_std_id cx25840_get_v4lstd(struct i2c_client * client)
} }
switch (fmt) { switch (fmt) {
case 0x1: return V4L2_STD_NTSC_M; case 0x1: return V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_KR;
case 0x2: return V4L2_STD_NTSC_M_JP; case 0x2: return V4L2_STD_NTSC_M_JP;
case 0x3: return V4L2_STD_NTSC_443; case 0x3: return V4L2_STD_NTSC_443;
case 0x4: return V4L2_STD_PAL; case 0x4: return V4L2_STD_PAL;
......
...@@ -32,6 +32,7 @@ config VIDEO_CX88_DVB ...@@ -32,6 +32,7 @@ config VIDEO_CX88_DVB
config VIDEO_CX88_ALSA config VIDEO_CX88_ALSA
tristate "ALSA DMA audio support" tristate "ALSA DMA audio support"
depends on VIDEO_CX88 && SND && EXPERIMENTAL depends on VIDEO_CX88 && SND && EXPERIMENTAL
select SND_PCM
---help--- ---help---
This is a video4linux driver for direct (DMA) audio on This is a video4linux driver for direct (DMA) audio on
Conexant 2388x based TV cards. Conexant 2388x based TV cards.
...@@ -48,6 +49,7 @@ config VIDEO_CX88_DVB_ALL_FRONTENDS ...@@ -48,6 +49,7 @@ config VIDEO_CX88_DVB_ALL_FRONTENDS
default y default y
depends on VIDEO_CX88_DVB depends on VIDEO_CX88_DVB
select DVB_MT352 select DVB_MT352
select VIDEO_CX88_VP3054
select DVB_OR51132 select DVB_OR51132
select DVB_CX22702 select DVB_CX22702
select DVB_LGDT330X select DVB_LGDT330X
...@@ -69,6 +71,16 @@ config VIDEO_CX88_DVB_MT352 ...@@ -69,6 +71,16 @@ config VIDEO_CX88_DVB_MT352
This adds DVB-T support for cards based on the This adds DVB-T support for cards based on the
Connexant 2388x chip and the MT352 demodulator. Connexant 2388x chip and the MT352 demodulator.
config VIDEO_CX88_VP3054
tristate "VP-3054 Secondary I2C Bus Support"
default m
depends on DVB_MT352
---help---
This adds DVB-T support for cards based on the
Connexant 2388x chip and the MT352 demodulator,
which also require support for the VP-3054
Secondary I2C bus, such at DNTV Live! DVB-T Pro.
config VIDEO_CX88_DVB_OR51132 config VIDEO_CX88_DVB_OR51132
bool "OR51132 ATSC Support" bool "OR51132 ATSC Support"
default y default y
......
...@@ -4,8 +4,9 @@ cx8800-objs := cx88-video.o cx88-vbi.o ...@@ -4,8 +4,9 @@ cx8800-objs := cx88-video.o cx88-vbi.o
cx8802-objs := cx88-mpeg.o cx8802-objs := cx88-mpeg.o
obj-$(CONFIG_VIDEO_CX88) += cx88xx.o cx8800.o cx8802.o cx88-blackbird.o obj-$(CONFIG_VIDEO_CX88) += cx88xx.o cx8800.o cx8802.o cx88-blackbird.o
obj-$(CONFIG_VIDEO_CX88_DVB) += cx88-dvb.o cx88-vp3054-i2c.o obj-$(CONFIG_VIDEO_CX88_DVB) += cx88-dvb.o
obj-$(CONFIG_VIDEO_CX88_ALSA) += cx88-alsa.o obj-$(CONFIG_VIDEO_CX88_ALSA) += cx88-alsa.o
obj-$(CONFIG_VIDEO_CX88_VP3054) += cx88-vp3054-i2c.o
EXTRA_CFLAGS += -I$(src)/.. EXTRA_CFLAGS += -I$(src)/..
EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/dvb-core EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/dvb-core
...@@ -18,6 +19,6 @@ extra-cflags-$(CONFIG_DVB_LGDT330X) += -DHAVE_LGDT330X=1 ...@@ -18,6 +19,6 @@ extra-cflags-$(CONFIG_DVB_LGDT330X) += -DHAVE_LGDT330X=1
extra-cflags-$(CONFIG_DVB_MT352) += -DHAVE_MT352=1 extra-cflags-$(CONFIG_DVB_MT352) += -DHAVE_MT352=1
extra-cflags-$(CONFIG_DVB_NXT200X) += -DHAVE_NXT200X=1 extra-cflags-$(CONFIG_DVB_NXT200X) += -DHAVE_NXT200X=1
extra-cflags-$(CONFIG_DVB_CX24123) += -DHAVE_CX24123=1 extra-cflags-$(CONFIG_DVB_CX24123) += -DHAVE_CX24123=1
extra-cflags-$(CONFIG_VIDEO_CX88_DVB)+= -DHAVE_VP3054_I2C=1 extra-cflags-$(CONFIG_VIDEO_CX88_VP3054)+= -DHAVE_VP3054_I2C=1
EXTRA_CFLAGS += $(extra-cflags-y) $(extra-cflags-m) EXTRA_CFLAGS += $(extra-cflags-y) $(extra-cflags-m)
...@@ -128,7 +128,7 @@ MODULE_PARM_DESC(debug,"enable debug messages"); ...@@ -128,7 +128,7 @@ MODULE_PARM_DESC(debug,"enable debug messages");
* BOARD Specific: Sets audio DMA * BOARD Specific: Sets audio DMA
*/ */
int _cx88_start_audio_dma(snd_cx88_card_t *chip) static int _cx88_start_audio_dma(snd_cx88_card_t *chip)
{ {
struct cx88_buffer *buf = chip->buf; struct cx88_buffer *buf = chip->buf;
struct cx88_core *core=chip->core; struct cx88_core *core=chip->core;
...@@ -173,7 +173,7 @@ int _cx88_start_audio_dma(snd_cx88_card_t *chip) ...@@ -173,7 +173,7 @@ int _cx88_start_audio_dma(snd_cx88_card_t *chip)
/* /*
* BOARD Specific: Resets audio DMA * BOARD Specific: Resets audio DMA
*/ */
int _cx88_stop_audio_dma(snd_cx88_card_t *chip) static int _cx88_stop_audio_dma(snd_cx88_card_t *chip)
{ {
struct cx88_core *core=chip->core; struct cx88_core *core=chip->core;
dprintk(1, "Stopping audio DMA\n"); dprintk(1, "Stopping audio DMA\n");
...@@ -613,7 +613,7 @@ static snd_kcontrol_new_t snd_cx88_capture_volume = { ...@@ -613,7 +613,7 @@ static snd_kcontrol_new_t snd_cx88_capture_volume = {
* Only boards with eeprom and byte 1 at eeprom=1 have it * Only boards with eeprom and byte 1 at eeprom=1 have it
*/ */
struct pci_device_id cx88_audio_pci_tbl[] = { static struct pci_device_id cx88_audio_pci_tbl[] = {
{0x14f1,0x8801,PCI_ANY_ID,PCI_ANY_ID,0,0,0}, {0x14f1,0x8801,PCI_ANY_ID,PCI_ANY_ID,0,0,0},
{0x14f1,0x8811,PCI_ANY_ID,PCI_ANY_ID,0,0,0}, {0x14f1,0x8811,PCI_ANY_ID,PCI_ANY_ID,0,0,0},
{0, } {0, }
......
...@@ -1244,6 +1244,11 @@ struct cx88_subid cx88_subids[] = { ...@@ -1244,6 +1244,11 @@ struct cx88_subid cx88_subids[] = {
.subvendor = 0x18ac, .subvendor = 0x18ac,
.subdevice = 0xdb50, .subdevice = 0xdb50,
.card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL, .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL,
},{
.subvendor = 0x18ac,
.subdevice = 0xdb54,
.card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL,
/* Re-branded DViCO: DigitalNow DVB-T Dual */
},{ },{
.subvendor = 0x18ac, .subvendor = 0x18ac,
.subdevice = 0xdb11, .subdevice = 0xdb11,
...@@ -1293,6 +1298,7 @@ static void hauppauge_eeprom(struct cx88_core *core, u8 *eeprom_data) ...@@ -1293,6 +1298,7 @@ static void hauppauge_eeprom(struct cx88_core *core, u8 *eeprom_data)
switch (tv.model) switch (tv.model)
{ {
case 28552: /* WinTV-PVR 'Roslyn' (No IR) */ case 28552: /* WinTV-PVR 'Roslyn' (No IR) */
case 34519: /* WinTV-PCI-FM */
case 90002: /* Nova-T-PCI (9002) */ case 90002: /* Nova-T-PCI (9002) */
case 92001: /* Nova-S-Plus (Video and IR) */ case 92001: /* Nova-S-Plus (Video and IR) */
case 92002: /* Nova-S-Plus (Video and IR) */ case 92002: /* Nova-S-Plus (Video and IR) */
......
...@@ -787,12 +787,14 @@ static int set_pll(struct cx88_core *core, int prescale, u32 ofreq) ...@@ -787,12 +787,14 @@ static int set_pll(struct cx88_core *core, int prescale, u32 ofreq)
int cx88_start_audio_dma(struct cx88_core *core) int cx88_start_audio_dma(struct cx88_core *core)
{ {
/* constant 128 made buzz in analog Nicam-stereo for bigger fifo_size */
int bpl = cx88_sram_channels[SRAM_CH25].fifo_size/4;
/* setup fifo + format */ /* setup fifo + format */
cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH25], 128, 0); cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH25], bpl, 0);
cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH26], 128, 0); cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH26], bpl, 0);
cx_write(MO_AUDD_LNGTH, 128); /* fifo bpl size */ cx_write(MO_AUDD_LNGTH, bpl); /* fifo bpl size */
cx_write(MO_AUDR_LNGTH, 128); /* fifo bpl size */ cx_write(MO_AUDR_LNGTH, bpl); /* fifo bpl size */
/* start dma */ /* start dma */
cx_write(MO_AUD_DMACNTRL, 0x0003); /* Up and Down fifo enable */ cx_write(MO_AUD_DMACNTRL, 0x0003); /* Up and Down fifo enable */
......
...@@ -482,6 +482,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) ...@@ -482,6 +482,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
switch (core->board) { switch (core->board) {
case CX88_BOARD_DNTV_LIVE_DVB_T: case CX88_BOARD_DNTV_LIVE_DVB_T:
case CX88_BOARD_KWORLD_DVB_T: case CX88_BOARD_KWORLD_DVB_T:
case CX88_BOARD_KWORLD_DVB_T_CX22702:
ir_codes = ir_codes_dntv_live_dvb_t; ir_codes = ir_codes_dntv_live_dvb_t;
ir->gpio_addr = MO_GP1_IO; ir->gpio_addr = MO_GP1_IO;
ir->mask_keycode = 0x1f; ir->mask_keycode = 0x1f;
......
...@@ -139,6 +139,9 @@ int em28xx_read_reg_req_len(struct em28xx *dev, u8 req, u16 reg, ...@@ -139,6 +139,9 @@ int em28xx_read_reg_req_len(struct em28xx *dev, u8 req, u16 reg,
{ {
int ret, byte; int ret, byte;
if (dev->state & DEV_DISCONNECTED)
return(-ENODEV);
em28xx_regdbg("req=%02x, reg=%02x ", req, reg); em28xx_regdbg("req=%02x, reg=%02x ", req, reg);
ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), req, ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), req,
...@@ -165,6 +168,9 @@ int em28xx_read_reg_req(struct em28xx *dev, u8 req, u16 reg) ...@@ -165,6 +168,9 @@ int em28xx_read_reg_req(struct em28xx *dev, u8 req, u16 reg)
u8 val; u8 val;
int ret; int ret;
if (dev->state & DEV_DISCONNECTED)
return(-ENODEV);
em28xx_regdbg("req=%02x, reg=%02x:", req, reg); em28xx_regdbg("req=%02x, reg=%02x:", req, reg);
ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), req, ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), req,
...@@ -195,7 +201,12 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf, ...@@ -195,7 +201,12 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf,
int ret; int ret;
/*usb_control_msg seems to expect a kmalloced buffer */ /*usb_control_msg seems to expect a kmalloced buffer */
unsigned char *bufs = kmalloc(len, GFP_KERNEL); unsigned char *bufs;
if (dev->state & DEV_DISCONNECTED)
return(-ENODEV);
bufs = kmalloc(len, GFP_KERNEL);
em28xx_regdbg("req=%02x reg=%02x:", req, reg); em28xx_regdbg("req=%02x reg=%02x:", req, reg);
...@@ -212,7 +223,7 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf, ...@@ -212,7 +223,7 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf,
ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), req, ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), req,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0x0000, reg, bufs, len, HZ); 0x0000, reg, bufs, len, HZ);
mdelay(5); /* FIXME: magic number */ msleep(5); /* FIXME: magic number */
kfree(bufs); kfree(bufs);
return ret; return ret;
} }
...@@ -253,7 +264,7 @@ int em28xx_write_ac97(struct em28xx *dev, u8 reg, u8 * val) ...@@ -253,7 +264,7 @@ int em28xx_write_ac97(struct em28xx *dev, u8 reg, u8 * val)
if ((ret = em28xx_read_reg(dev, AC97BUSY_REG)) < 0) if ((ret = em28xx_read_reg(dev, AC97BUSY_REG)) < 0)
return ret; return ret;
else if (((u8) ret) & 0x01) { else if (((u8) ret) & 0x01) {
em28xx_warn ("AC97 command still being exectuted: not handled properly!\n"); em28xx_warn ("AC97 command still being executed: not handled properly!\n");
} }
return 0; return 0;
} }
......
...@@ -78,7 +78,7 @@ static int em2800_i2c_send_max4(struct em28xx *dev, unsigned char addr, ...@@ -78,7 +78,7 @@ static int em2800_i2c_send_max4(struct em28xx *dev, unsigned char addr,
ret = dev->em28xx_read_reg(dev, 0x05); ret = dev->em28xx_read_reg(dev, 0x05);
if (ret == 0x80 + len - 1) if (ret == 0x80 + len - 1)
return len; return len;
mdelay(5); msleep(5);
} }
em28xx_warn("i2c write timed out\n"); em28xx_warn("i2c write timed out\n");
return -EIO; return -EIO;
...@@ -138,7 +138,7 @@ static int em2800_i2c_check_for_device(struct em28xx *dev, unsigned char addr) ...@@ -138,7 +138,7 @@ static int em2800_i2c_check_for_device(struct em28xx *dev, unsigned char addr)
return -ENODEV; return -ENODEV;
else if (msg == 0x84) else if (msg == 0x84)
return 0; return 0;
mdelay(5); msleep(5);
} }
return -ENODEV; return -ENODEV;
} }
...@@ -278,9 +278,9 @@ static int em28xx_i2c_xfer(struct i2c_adapter *i2c_adap, ...@@ -278,9 +278,9 @@ static int em28xx_i2c_xfer(struct i2c_adapter *i2c_adap,
msgs[i].buf, msgs[i].buf,
msgs[i].len, msgs[i].len,
i == num - 1); i == num - 1);
}
if (rc < 0) if (rc < 0)
goto err; goto err;
}
if (i2c_debug>=2) if (i2c_debug>=2)
printk("\n"); printk("\n");
} }
......
...@@ -6,6 +6,9 @@ ...@@ -6,6 +6,9 @@
Mauro Carvalho Chehab <mchehab@brturbo.com.br> Mauro Carvalho Chehab <mchehab@brturbo.com.br>
Sascha Sommer <saschasommer@freenet.de> Sascha Sommer <saschasommer@freenet.de>
Some parts based on SN9C10x PC Camera Controllers GPL driver made
by Luca Risolia <luca.risolia@studio.unibo.it>
This program is free software; you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or the Free Software Foundation; either version 2 of the License, or
......
...@@ -136,7 +136,7 @@ struct saa7134_board saa7134_boards[] = { ...@@ -136,7 +136,7 @@ struct saa7134_board saa7134_boards[] = {
}, },
[SAA7134_BOARD_FLYVIDEO2000] = { [SAA7134_BOARD_FLYVIDEO2000] = {
/* "TC Wan" <tcwan@cs.usm.my> */ /* "TC Wan" <tcwan@cs.usm.my> */
.name = "LifeView FlyVIDEO2000", .name = "LifeView/Typhoon FlyVIDEO2000",
.audio_clock = 0x00200000, .audio_clock = 0x00200000,
.tuner_type = TUNER_LG_PAL_NEW_TAPC, .tuner_type = TUNER_LG_PAL_NEW_TAPC,
.radio_type = UNSET, .radio_type = UNSET,
...@@ -1884,44 +1884,38 @@ struct saa7134_board saa7134_boards[] = { ...@@ -1884,44 +1884,38 @@ struct saa7134_board saa7134_boards[] = {
.gpio = 0x000, .gpio = 0x000,
}, },
}, },
[SAA7134_BOARD_THYPHOON_DVBT_DUO_CARDBUS] = { [SAA7134_BOARD_FLYDVBT_DUO_CARDBUS] = {
.name = "Typhoon DVB-T Duo Digital/Analog Cardbus", .name = "LifeView/Typhoon FlyDVB-T Duo Cardbus",
.audio_clock = 0x00200000, .audio_clock = 0x00200000,
.tuner_type = TUNER_PHILIPS_TDA8290, .tuner_type = TUNER_PHILIPS_TDA8290,
.radio_type = UNSET, .radio_type = UNSET,
.tuner_addr = ADDR_UNSET, .tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET,
.mpeg = SAA7134_MPEG_DVB, .mpeg = SAA7134_MPEG_DVB,
/* .gpiomask = 0xe000, */ .gpiomask = 0x00200000,
.inputs = {{ .inputs = {{
.name = name_tv, .name = name_tv,
.vmux = 1, .vmux = 1,
.amux = TV, .amux = TV,
/* .gpio = 0x0000, */ .gpio = 0x200000, /* GPIO21=High for TV input */
.tv = 1, .tv = 1,
},{
.name = name_svideo, /* S-Video signal on S-Video input */
.vmux = 8,
.amux = LINE2,
},{ },{
.name = name_comp1, /* Composite signal on S-Video input */ .name = name_comp1, /* Composite signal on S-Video input */
.vmux = 0, .vmux = 0,
.amux = LINE2, .amux = LINE2,
/* .gpio = 0x4000, */
},{ },{
.name = name_comp2, /* Composite input */ .name = name_comp2, /* Composite input */
.vmux = 3, .vmux = 3,
.amux = LINE2, .amux = LINE2,
/* .gpio = 0x4000, */
},{
.name = name_svideo, /* S-Video signal on S-Video input */
.vmux = 8,
.amux = LINE2,
/* .gpio = 0x4000, */
}}, }},
.radio = { .radio = {
.name = name_radio, .name = name_radio,
.amux = LINE2, .amux = TV,
}, .gpio = 0x000000, /* GPIO21=Low for FM radio antenna */
.mute = {
.name = name_mute,
.amux = LINE1,
}, },
}, },
[SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII] = { [SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII] = {
...@@ -2699,6 +2693,12 @@ struct pci_device_id saa7134_pci_tbl[] = { ...@@ -2699,6 +2693,12 @@ struct pci_device_id saa7134_pci_tbl[] = {
.subvendor = 0x5168, .subvendor = 0x5168,
.subdevice = 0x0138, .subdevice = 0x0138,
.driver_data = SAA7134_BOARD_FLYVIDEO2000, .driver_data = SAA7134_BOARD_FLYVIDEO2000,
},{
.vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7130,
.subvendor = 0x4e42, /* Typhoon */
.subdevice = 0x0138, /* LifeView FlyTV Prime30 OEM */
.driver_data = SAA7134_BOARD_FLYVIDEO2000,
},{ },{
.vendor = PCI_VENDOR_ID_PHILIPS, .vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7133, .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
...@@ -2935,7 +2935,7 @@ struct pci_device_id saa7134_pci_tbl[] = { ...@@ -2935,7 +2935,7 @@ struct pci_device_id saa7134_pci_tbl[] = {
.device = PCI_DEVICE_ID_PHILIPS_SAA7133, .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
.subvendor = 0x5168, .subvendor = 0x5168,
.subdevice = 0x0502, /* Cardbus version */ .subdevice = 0x0502, /* Cardbus version */
.driver_data = SAA7134_BOARD_FLYDVBTDUO, .driver_data = SAA7134_BOARD_FLYDVBT_DUO_CARDBUS,
},{ },{
.vendor = PCI_VENDOR_ID_PHILIPS, .vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7133, .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
...@@ -2980,12 +2980,12 @@ struct pci_device_id saa7134_pci_tbl[] = { ...@@ -2980,12 +2980,12 @@ struct pci_device_id saa7134_pci_tbl[] = {
.subdevice = 0x1370, /* cardbus version */ .subdevice = 0x1370, /* cardbus version */
.driver_data = SAA7134_BOARD_ADS_INSTANT_TV, .driver_data = SAA7134_BOARD_ADS_INSTANT_TV,
},{ /* Typhoon DVB-T Duo Digital/Analog Cardbus */ },{
.vendor = PCI_VENDOR_ID_PHILIPS, .vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7133, .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
.subvendor = 0x4e42, .subvendor = 0x4e42, /* Typhoon */
.subdevice = 0x0502, .subdevice = 0x0502, /* LifeView LR502 OEM */
.driver_data = SAA7134_BOARD_THYPHOON_DVBT_DUO_CARDBUS, .driver_data = SAA7134_BOARD_FLYDVBT_DUO_CARDBUS,
},{ },{
.vendor = PCI_VENDOR_ID_PHILIPS, .vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7133, .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
...@@ -3206,8 +3206,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) ...@@ -3206,8 +3206,7 @@ int saa7134_board_init1(struct saa7134_dev *dev)
saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x00040000, 0x00040000); saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x00040000, 0x00040000);
saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x00040000, 0x00000004); saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x00040000, 0x00000004);
break; break;
case SAA7134_BOARD_FLYDVBTDUO: case SAA7134_BOARD_FLYDVBT_DUO_CARDBUS:
case SAA7134_BOARD_THYPHOON_DVBT_DUO_CARDBUS:
/* turn the fan on */ /* turn the fan on */
saa_writeb(SAA7134_GPIO_GPMODE3, 0x08); saa_writeb(SAA7134_GPIO_GPMODE3, 0x08);
saa_writeb(SAA7134_GPIO_GPSTATUS3, 0x06); saa_writeb(SAA7134_GPIO_GPSTATUS3, 0x06);
......
...@@ -861,7 +861,7 @@ static int dvb_init(struct saa7134_dev *dev) ...@@ -861,7 +861,7 @@ static int dvb_init(struct saa7134_dev *dev)
dev->dvb.frontend = tda10046_attach(&tda827x_lifeview_config, dev->dvb.frontend = tda10046_attach(&tda827x_lifeview_config,
&dev->i2c_adap); &dev->i2c_adap);
break; break;
case SAA7134_BOARD_THYPHOON_DVBT_DUO_CARDBUS: case SAA7134_BOARD_FLYDVBT_DUO_CARDBUS:
dev->dvb.frontend = tda10046_attach(&tda827x_lifeview_config, dev->dvb.frontend = tda10046_attach(&tda827x_lifeview_config,
&dev->i2c_adap); &dev->i2c_adap);
break; break;
......
...@@ -185,7 +185,7 @@ struct saa7134_format { ...@@ -185,7 +185,7 @@ struct saa7134_format {
#define SAA7134_BOARD_AVERMEDIA_GO_007_FM 57 #define SAA7134_BOARD_AVERMEDIA_GO_007_FM 57
#define SAA7134_BOARD_ADS_INSTANT_TV 58 #define SAA7134_BOARD_ADS_INSTANT_TV 58
#define SAA7134_BOARD_KWORLD_VSTREAM_XPERT 59 #define SAA7134_BOARD_KWORLD_VSTREAM_XPERT 59
#define SAA7134_BOARD_THYPHOON_DVBT_DUO_CARDBUS 60 #define SAA7134_BOARD_FLYDVBT_DUO_CARDBUS 60
#define SAA7134_BOARD_PHILIPS_TOUGH 61 #define SAA7134_BOARD_PHILIPS_TOUGH 61
#define SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII 62 #define SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII 62
#define SAA7134_BOARD_KWORLD_XPERT 63 #define SAA7134_BOARD_KWORLD_XPERT 63
......
...@@ -2012,7 +2012,6 @@ static int __devinit init_saa7146(struct pci_dev *pdev) ...@@ -2012,7 +2012,6 @@ static int __devinit init_saa7146(struct pci_dev *pdev)
{ {
struct saa7146 *saa = pci_get_drvdata(pdev); struct saa7146 *saa = pci_get_drvdata(pdev);
memset(saa, 0, sizeof(*saa));
saa->user = 0; saa->user = 0;
/* reset the saa7146 */ /* reset the saa7146 */
saawrite(0xffff0000, SAA7146_MC1); saawrite(0xffff0000, SAA7146_MC1);
...@@ -2062,16 +2061,16 @@ static int __devinit init_saa7146(struct pci_dev *pdev) ...@@ -2062,16 +2061,16 @@ static int __devinit init_saa7146(struct pci_dev *pdev)
} }
if (saa->audbuf == NULL && (saa->audbuf = vmalloc(65536)) == NULL) { if (saa->audbuf == NULL && (saa->audbuf = vmalloc(65536)) == NULL) {
dev_err(&pdev->dev, "%d: malloc failed\n", saa->nr); dev_err(&pdev->dev, "%d: malloc failed\n", saa->nr);
goto errvid; goto errfree;
} }
if (saa->osdbuf == NULL && (saa->osdbuf = vmalloc(131072)) == NULL) { if (saa->osdbuf == NULL && (saa->osdbuf = vmalloc(131072)) == NULL) {
dev_err(&pdev->dev, "%d: malloc failed\n", saa->nr); dev_err(&pdev->dev, "%d: malloc failed\n", saa->nr);
goto erraud; goto errfree;
} }
/* allocate 81920 byte buffer for clipping */ /* allocate 81920 byte buffer for clipping */
if ((saa->dmavid2 = kzalloc(VIDEO_CLIPMAP_SIZE, GFP_KERNEL)) == NULL) { if ((saa->dmavid2 = kzalloc(VIDEO_CLIPMAP_SIZE, GFP_KERNEL)) == NULL) {
dev_err(&pdev->dev, "%d: clip kmalloc failed\n", saa->nr); dev_err(&pdev->dev, "%d: clip kmalloc failed\n", saa->nr);
goto errosd; goto errfree;
} }
/* setup clipping registers */ /* setup clipping registers */
saawrite(virt_to_bus(saa->dmavid2), SAA7146_BASE_EVEN2); saawrite(virt_to_bus(saa->dmavid2), SAA7146_BASE_EVEN2);
...@@ -2085,15 +2084,11 @@ static int __devinit init_saa7146(struct pci_dev *pdev) ...@@ -2085,15 +2084,11 @@ static int __devinit init_saa7146(struct pci_dev *pdev)
I2CBusScan(saa); I2CBusScan(saa);
return 0; return 0;
errosd: errfree:
vfree(saa->osdbuf); vfree(saa->osdbuf);
saa->osdbuf = NULL;
erraud:
vfree(saa->audbuf); vfree(saa->audbuf);
saa->audbuf = NULL;
errvid:
vfree(saa->vidbuf); vfree(saa->vidbuf);
saa->vidbuf = NULL; saa->audbuf = saa->osdbuf = saa->vidbuf = NULL;
err: err:
return -ENOMEM; return -ENOMEM;
} }
......
...@@ -231,7 +231,7 @@ static struct tvnorm tvnorms[] = { ...@@ -231,7 +231,7 @@ static struct tvnorm tvnorms[] = {
cAudioIF_6_5 | cAudioIF_6_5 |
cVideoIF_38_90 ), cVideoIF_38_90 ),
},{ },{
.std = V4L2_STD_NTSC_M, .std = V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_KR,
.name = "NTSC-M", .name = "NTSC-M",
.b = ( cNegativeFmTV | .b = ( cNegativeFmTV |
cQSS ), cQSS ),
...@@ -619,6 +619,11 @@ static int tda9887_fixup_std(struct tda9887 *t) ...@@ -619,6 +619,11 @@ static int tda9887_fixup_std(struct tda9887 *t)
tda9887_dbg("insmod fixup: NTSC => NTSC_M_JP\n"); tda9887_dbg("insmod fixup: NTSC => NTSC_M_JP\n");
t->std = V4L2_STD_NTSC_M_JP; t->std = V4L2_STD_NTSC_M_JP;
break; break;
case 'k':
case 'K':
tda9887_dbg("insmod fixup: NTSC => NTSC_M_KR\n");
t->std = V4L2_STD_NTSC_M_KR;
break;
case '-': case '-':
/* default parameter, do nothing */ /* default parameter, do nothing */
break; break;
...@@ -876,7 +881,7 @@ static int tda9887_resume(struct device * dev) ...@@ -876,7 +881,7 @@ static int tda9887_resume(struct device * dev)
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
static struct i2c_driver driver = { static struct i2c_driver driver = {
.id = -1, /* FIXME */ .id = I2C_DRIVERID_TDA9887,
.attach_adapter = tda9887_probe, .attach_adapter = tda9887_probe,
.detach_client = tda9887_detach, .detach_client = tda9887_detach,
.command = tda9887_command, .command = tda9887_command,
......
...@@ -216,6 +216,7 @@ static void set_type(struct i2c_client *c, unsigned int type, ...@@ -216,6 +216,7 @@ static void set_type(struct i2c_client *c, unsigned int type,
buffer[3] = 0xa4; buffer[3] = 0xa4;
i2c_master_send(c,buffer,4); i2c_master_send(c,buffer,4);
default_tuner_init(c); default_tuner_init(c);
break;
default: default:
default_tuner_init(c); default_tuner_init(c);
break; break;
...@@ -365,6 +366,11 @@ static int tuner_fixup_std(struct tuner *t) ...@@ -365,6 +366,11 @@ static int tuner_fixup_std(struct tuner *t)
tuner_dbg("insmod fixup: NTSC => NTSC_M_JP\n"); tuner_dbg("insmod fixup: NTSC => NTSC_M_JP\n");
t->std = V4L2_STD_NTSC_M_JP; t->std = V4L2_STD_NTSC_M_JP;
break; break;
case 'k':
case 'K':
tuner_dbg("insmod fixup: NTSC => NTSC_M_KR\n");
t->std = V4L2_STD_NTSC_M_KR;
break;
case '-': case '-':
/* default parameter, do nothing */ /* default parameter, do nothing */
break; break;
...@@ -448,7 +454,7 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind) ...@@ -448,7 +454,7 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind)
printk("%02x ",buffer[i]); printk("%02x ",buffer[i]);
printk("\n"); printk("\n");
} }
/* TEA5767 autodetection code - only for addr = 0xc0 */ /* autodetection code based on the i2c addr */
if (!no_autodetect) { if (!no_autodetect) {
switch (addr) { switch (addr) {
case 0x42: case 0x42:
......
...@@ -390,6 +390,14 @@ static void tda9840_setmode(struct CHIPSTATE *chip, int mode) ...@@ -390,6 +390,14 @@ static void tda9840_setmode(struct CHIPSTATE *chip, int mode)
chip_write(chip, TDA9840_SW, t); chip_write(chip, TDA9840_SW, t);
} }
static int tda9840_checkit(struct CHIPSTATE *chip)
{
int rc;
rc = chip_read(chip);
/* lower 5 bits should be 0 */
return ((rc & 0x1f) == 0) ? 1 : 0;
}
/* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */
/* audio chip descriptions - defines+functions for tda985x */ /* audio chip descriptions - defines+functions for tda985x */
...@@ -1264,6 +1272,7 @@ static struct CHIPDESC chiplist[] = { ...@@ -1264,6 +1272,7 @@ static struct CHIPDESC chiplist[] = {
.addr_hi = I2C_TDA9840 >> 1, .addr_hi = I2C_TDA9840 >> 1,
.registers = 5, .registers = 5,
.checkit = tda9840_checkit,
.getmode = tda9840_getmode, .getmode = tda9840_getmode,
.setmode = tda9840_setmode, .setmode = tda9840_setmode,
.checkmode = generic_checkmode, .checkmode = generic_checkmode,
......
...@@ -746,24 +746,27 @@ static int tvp5150_set_std(struct i2c_client *c, v4l2_std_id std) ...@@ -746,24 +746,27 @@ static int tvp5150_set_std(struct i2c_client *c, v4l2_std_id std)
static inline void tvp5150_reset(struct i2c_client *c) static inline void tvp5150_reset(struct i2c_client *c)
{ {
u8 type, ver_656, msb_id, lsb_id, msb_rom, lsb_rom; u8 msb_id, lsb_id, msb_rom, lsb_rom;
struct tvp5150 *decoder = i2c_get_clientdata(c); struct tvp5150 *decoder = i2c_get_clientdata(c);
type=tvp5150_read(c,TVP5150_AUTOSW_MSK);
msb_id=tvp5150_read(c,TVP5150_MSB_DEV_ID); msb_id=tvp5150_read(c,TVP5150_MSB_DEV_ID);
lsb_id=tvp5150_read(c,TVP5150_LSB_DEV_ID); lsb_id=tvp5150_read(c,TVP5150_LSB_DEV_ID);
msb_rom=tvp5150_read(c,TVP5150_ROM_MAJOR_VER); msb_rom=tvp5150_read(c,TVP5150_ROM_MAJOR_VER);
lsb_rom=tvp5150_read(c,TVP5150_ROM_MINOR_VER); lsb_rom=tvp5150_read(c,TVP5150_ROM_MINOR_VER);
if (type==0xdc) { if ((msb_rom==4)&&(lsb_rom==0)) { /* Is TVP5150AM1 */
ver_656=tvp5150_read(c,TVP5150_REV_SELECT); tvp5150_info("tvp%02x%02xam1 detected.\n",msb_id, lsb_id);
tvp5150_info("tvp%02x%02xam1 detected 656 version is %d.\n",msb_id, lsb_id,ver_656);
} else if (type==0xfc) { /* ITU-T BT.656.4 timing */
tvp5150_write(c,TVP5150_REV_SELECT,0);
} else {
if ((msb_rom==3)||(lsb_rom==0x21)) { /* Is TVP5150A */
tvp5150_info("tvp%02x%02xa detected.\n",msb_id, lsb_id); tvp5150_info("tvp%02x%02xa detected.\n",msb_id, lsb_id);
} else { } else {
tvp5150_info("unknown tvp%02x%02x chip detected(%d).\n",msb_id,lsb_id,type); tvp5150_info("*** unknown tvp%02x%02x chip detected.\n",msb_id,lsb_id);
tvp5150_info("*** Rom ver is %d.%d\n",msb_rom,lsb_rom);
}
} }
tvp5150_info("Rom ver is %d.%d\n",msb_rom,lsb_rom);
/* Initializes TVP5150 to its default values */ /* Initializes TVP5150 to its default values */
tvp5150_write_inittab(c, tvp5150_init_default); tvp5150_write_inittab(c, tvp5150_init_default);
...@@ -893,6 +896,17 @@ static int tvp5150_command(struct i2c_client *c, ...@@ -893,6 +896,17 @@ static int tvp5150_command(struct i2c_client *c,
} }
case DECODER_GET_STATUS: case DECODER_GET_STATUS:
{ {
int *iarg = arg;
int status;
int res=0;
status = tvp5150_read(c, 0x88);
if(status&0x08){
res |= DECODER_STATUS_COLOR;
}
if(status&0x04 && status&0x02){
res |= DECODER_STATUS_GOOD;
}
*iarg=res;
break; break;
} }
......
...@@ -629,6 +629,7 @@ typedef __u64 v4l2_std_id; ...@@ -629,6 +629,7 @@ typedef __u64 v4l2_std_id;
#define V4L2_STD_NTSC_M ((v4l2_std_id)0x00001000) #define V4L2_STD_NTSC_M ((v4l2_std_id)0x00001000)
#define V4L2_STD_NTSC_M_JP ((v4l2_std_id)0x00002000) #define V4L2_STD_NTSC_M_JP ((v4l2_std_id)0x00002000)
#define V4L2_STD_NTSC_443 ((v4l2_std_id)0x00004000) #define V4L2_STD_NTSC_443 ((v4l2_std_id)0x00004000)
#define V4L2_STD_NTSC_M_KR ((v4l2_std_id)0x00008000)
#define V4L2_STD_SECAM_B ((v4l2_std_id)0x00010000) #define V4L2_STD_SECAM_B ((v4l2_std_id)0x00010000)
#define V4L2_STD_SECAM_D ((v4l2_std_id)0x00020000) #define V4L2_STD_SECAM_D ((v4l2_std_id)0x00020000)
...@@ -661,7 +662,8 @@ typedef __u64 v4l2_std_id; ...@@ -661,7 +662,8 @@ typedef __u64 v4l2_std_id;
V4L2_STD_PAL_H |\ V4L2_STD_PAL_H |\
V4L2_STD_PAL_I) V4L2_STD_PAL_I)
#define V4L2_STD_NTSC (V4L2_STD_NTSC_M |\ #define V4L2_STD_NTSC (V4L2_STD_NTSC_M |\
V4L2_STD_NTSC_M_JP) V4L2_STD_NTSC_M_JP |\
V4L2_STD_NTSC_M_KR)
#define V4L2_STD_SECAM_DK (V4L2_STD_SECAM_D |\ #define V4L2_STD_SECAM_DK (V4L2_STD_SECAM_D |\
V4L2_STD_SECAM_K |\ V4L2_STD_SECAM_K |\
V4L2_STD_SECAM_K1) V4L2_STD_SECAM_K1)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment