Commit e44d520e authored by Gerd Knorr's avatar Gerd Knorr Committed by Linus Torvalds

[PATCH] v4l: cx88 driver update

Finally the big cx88 driver update which makes the cx88-dvb driver compile and
work for some cards.  A number of changes accumulated over time ...

 * various new tv cards added / fixed.
 * added support for infrared remote controls.
 * some fixes in the blackbird (mpeg encoder) driver,
   starts working now.
 * configurarion for analog hauppauge cards now uses
   the tveeprom module.
 * kconfig fixups.
 * powermanagement fixups.
 * lot of tweaks for tv audio (make NICAM decoding work).
 * lot of changes in the dvb driver, still not working
   for all cards though as some more changes in the dvb
   subsystem are needed.
Signed-off-by: default avatarGerd Knorr <kraxel@bytesex.org>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 0d3430ba
......@@ -307,11 +307,14 @@ config VIDEO_HEXIUM_GEMINI
config VIDEO_CX88
tristate "Conexant 2388x (bt878 successor) support"
depends on VIDEO_DEV && PCI && EXPERIMENTAL
depends on VIDEO_DEV && PCI && I2C && EXPERIMENTAL
select I2C_ALGOBIT
select FW_LOADER
select VIDEO_BTCX
select VIDEO_BUF
select VIDEO_TUNER
select VIDEO_TVEEPROM
select VIDEO_IR
---help---
This is a video4linux driver for Conexant 2388x based
TV cards.
......@@ -321,10 +324,11 @@ config VIDEO_CX88
config VIDEO_CX88_DVB
tristate "DVB Support for cx2388x based TV cards"
depends on VIDEO_CX88 && DVB_CORE && BROKEN
depends on VIDEO_CX88 && DVB_CORE
select VIDEO_BUF_DVB
select DVB_MT352
---help---
This adds support for DVB cards based on the
This adds support for DVB/ATSC cards based on the
Connexant 2388x chip.
config VIDEO_OVCAMCHIP
......
cx88xx-objs := cx88-cards.o cx88-core.o cx88-i2c.o cx88-tvaudio.o
cx88xx-objs := cx88-cards.o cx88-core.o cx88-i2c.o cx88-tvaudio.o \
cx88-input.o
cx8800-objs := cx88-video.o cx88-vbi.o
cx8802-objs := cx88-mpeg.o
......
/*
* $Id: cx88-blackbird.c,v 1.17 2004/11/07 13:17:15 kraxel Exp $
* $Id: cx88-blackbird.c,v 1.26 2005/03/07 15:58:05 kraxel Exp $
*
* Support for a cx23416 mpeg encoder via cx2388x host port.
* "blackbird" reference design.
......@@ -25,6 +25,7 @@
*/
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/delay.h>
......@@ -207,10 +208,6 @@ static int register_write(struct cx88_core *core, u32 address, u32 value)
cx_read(P1_RADDR0);
return wait_ready_gpio0_bit1(core,1);
#if 0
udelay(1000); /* without this, things don't go right (subsequent memory_write()'s don't get through */
/* ? would this be safe here? set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(1); */
#endif
}
......@@ -283,7 +280,7 @@ static int blackbird_api_cmd(struct cx8802_dev *dev, u32 command,
timeout = jiffies + msecs_to_jiffies(10);
for (;;) {
memory_read(dev->core, dev->mailbox, &flag);
if (0 == (flag & 4))
if (0 != (flag & 4))
break;
if (time_after(jiffies,timeout)) {
dprintk(0, "ERROR: API Mailbox timeout\n");
......@@ -324,7 +321,7 @@ static int blackbird_find_mailbox(struct cx8802_dev *dev)
signaturecnt = 0;
if (4 == signaturecnt) {
dprintk(1, "Mailbox signature found\n");
return i;
return i+1;
}
}
dprintk(0, "Mailbox signature values not found!\n");
......@@ -427,7 +424,8 @@ static void blackbird_codec_settings(struct cx8802_dev *dev)
blackbird_api_cmd(dev, IVTV_API_ASSIGN_FRAMERATE, 1, 0, 0);
/* assign frame size */
blackbird_api_cmd(dev, IVTV_API_ASSIGN_FRAME_SIZE, 2, 0, 480, 720);
blackbird_api_cmd(dev, IVTV_API_ASSIGN_FRAME_SIZE, 2, 0,
dev->height, dev->width);
/* assign aspect ratio */
blackbird_api_cmd(dev, IVTV_API_ASSIGN_ASPECT_RATIO, 1, 0, 2);
......@@ -629,8 +627,8 @@ static int mpeg_do_ioctl(struct inode *inode, struct file *file,
memset(f,0,sizeof(*f));
f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
f->fmt.pix.width = 720;
f->fmt.pix.height = 576;
f->fmt.pix.width = dev->width;
f->fmt.pix.height = dev->height;
f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
f->fmt.pix.sizeimage = 1024 * 512 /* FIXME: BUFFER_SIZE */;
}
......@@ -694,6 +692,10 @@ static int mpeg_open(struct inode *inode, struct file *file)
file->private_data = fh;
fh->dev = dev;
/* FIXME: locking against other video device */
cx88_set_scale(dev->core, dev->width, dev->height,
V4L2_FIELD_INTERLACED);
videobuf_queue_init(&fh->mpegq, &blackbird_qops,
dev->pci, &dev->slock,
V4L2_BUF_TYPE_VIDEO_CAPTURE,
......@@ -715,6 +717,7 @@ static int mpeg_release(struct inode *inode, struct file *file)
if (fh->mpegq.reading)
videobuf_read_stop(&fh->mpegq);
videobuf_mmap_free(&fh->mpegq);
file->private_data = NULL;
kfree(fh);
return 0;
......@@ -821,6 +824,8 @@ static int __devinit blackbird_probe(struct pci_dev *pci_dev,
memset(dev,0,sizeof(*dev));
dev->pci = pci_dev;
dev->core = core;
dev->width = 720;
dev->height = 480;
err = cx8802_init_common(dev);
if (0 != err)
......@@ -852,6 +857,8 @@ static void __devexit blackbird_remove(struct pci_dev *pci_dev)
/* common */
cx8802_fini_common(dev);
cx88_core_put(dev->core,dev->pci);
kfree(dev);
}
static struct pci_device_id cx8802_pci_tbl[] = {
......
/*
* $Id: cx88-cards.c,v 1.47 2004/11/03 09:04:50 kraxel Exp $
* $Id: cx88-cards.c,v 1.66 2005/03/04 09:12:23 kraxel Exp $
*
* device driver for Conexant 2388x based TV cards
* card-specific stuff.
......@@ -26,14 +26,7 @@
#include <linux/pci.h>
#include <linux/delay.h>
#if defined(CONFIG_VIDEO_CX88_DVB) || defined(CONFIG_VIDEO_CX88_DVB_MODULE)
# define WITH_DVB 1
#endif
#include "cx88.h"
#ifdef WITH_DVB
#include "cx22702.h"
#endif
/* ------------------------------------------------------------------ */
/* board config info */
......@@ -59,6 +52,7 @@ struct cx88_board cx88_boards[] = {
[CX88_BOARD_HAUPPAUGE] = {
.name = "Hauppauge WinTV 34xxx models",
.tuner_type = UNSET,
.tda9887_conf = TDA9887_PRESENT,
.input = {{
.type = CX88_VMUX_TELEVISION,
.vmux = 0,
......@@ -91,7 +85,7 @@ struct cx88_board cx88_boards[] = {
},
[CX88_BOARD_PIXELVIEW] = {
.name = "PixelView",
.tuner_type = UNSET,
.tuner_type = 5,
.input = {{
.type = CX88_VMUX_TELEVISION,
.vmux = 0,
......@@ -126,7 +120,7 @@ struct cx88_board cx88_boards[] = {
.gpio0 = 0x03fe,
}},
},
[CX88_BOARD_WINFAST2000XP] = {
[CX88_BOARD_WINFAST2000XP_EXPERT] = {
.name = "Leadtek Winfast 2000XP Expert",
.tuner_type = 44,
.tda9887_conf = TDA9887_PRESENT,
......@@ -217,26 +211,55 @@ struct cx88_board cx88_boards[] = {
.input = {{
.type = CX88_VMUX_TELEVISION,
.vmux = 0,
}},
.gpio0 = 0x0035e700,
.gpio1 = 0x00003004,
.gpio2 = 0x0035e700,
.gpio3 = 0x02000000,
},{
.type = CX88_VMUX_COMPOSITE1,
.vmux = 1,
.gpio0 = 0x0035c700,
.gpio1 = 0x00003004,
.gpio2 = 0x0035c700,
.gpio3 = 0x02000000,
},{
.type = CX88_VMUX_SVIDEO,
.vmux = 2,
.gpio0 = 0x0035c700,
.gpio1 = 0x0035c700,
.gpio2 = 0x02000000,
.gpio3 = 0x02000000,
}},
.radio = {
.type = CX88_RADIO,
},
.type = CX88_RADIO,
.gpio0 = 0x0035d700,
.gpio1 = 0x00007004,
.gpio2 = 0x0035d700,
.gpio3 = 0x02000000,
},
},
[CX88_BOARD_LEADTEK_PVR2000] = {
// gpio values for PAL version from regspy by DScaler
.name = "Leadtek PVR 2000",
.tuner_type = 38,
.tda9887_conf = TDA9887_PRESENT,
.input = {{
.type = CX88_VMUX_TELEVISION,
.vmux = 0,
.gpio0 = 0x0000bde6,
},{
.type = CX88_VMUX_COMPOSITE1,
.vmux = 1,
.gpio0 = 0x0000bde6,
},{
.type = CX88_VMUX_SVIDEO,
.vmux = 2,
.gpio0 = 0x0000bde6,
}},
.radio = {
.type = CX88_RADIO,
.gpio0 = 0x0000bd62,
},
.blackbird = 1,
},
......@@ -320,14 +343,15 @@ struct cx88_board cx88_boards[] = {
.name = "KWorld/VStream XPert DVB-T",
.tuner_type = TUNER_ABSENT,
.input = {{
.type = CX88_VMUX_DVB,
.vmux = 0,
},{
.type = CX88_VMUX_COMPOSITE1,
.vmux = 1,
.gpio0 = 0x0700,
.gpio2 = 0x0101,
},{
.type = CX88_VMUX_SVIDEO,
.vmux = 2,
.gpio0 = 0x0700,
.gpio2 = 0x0101,
}},
.dvb = 1,
},
......@@ -452,6 +476,131 @@ struct cx88_board cx88_boards[] = {
}},
.dvb = 1,
},
[CX88_BOARD_DNTV_LIVE_DVB_T] = {
.name = "digitalnow DNTV Live! DVB-T",
.tuner_type = TUNER_ABSENT,
.input = {{
.type = CX88_VMUX_COMPOSITE1,
.vmux = 1,
.gpio0 = 0x00000700,
.gpio2 = 0x00000101,
},{
.type = CX88_VMUX_SVIDEO,
.vmux = 2,
.gpio0 = 0x00000700,
.gpio2 = 0x00000101,
}},
.dvb = 1,
},
[CX88_BOARD_PCHDTV_HD3000] = {
.name = "pcHDTV HD3000 HDTV",
.tuner_type = TUNER_THOMSON_DTT7610,
.input = {{
.type = CX88_VMUX_TELEVISION,
.vmux = 0,
.gpio0 = 0x00008484,
.gpio1 = 0x00000000,
.gpio2 = 0x00000000,
.gpio3 = 0x00000000,
},{
.type = CX88_VMUX_COMPOSITE1,
.vmux = 1,
.gpio0 = 0x00008400,
.gpio1 = 0x00000000,
.gpio2 = 0x00000000,
.gpio3 = 0x00000000,
},{
.type = CX88_VMUX_SVIDEO,
.vmux = 2,
.gpio0 = 0x00008400,
.gpio1 = 0x00000000,
.gpio2 = 0x00000000,
.gpio3 = 0x00000000,
}},
.radio = {
.type = CX88_RADIO,
.vmux = 2,
.gpio0 = 0x00008400,
.gpio1 = 0x00000000,
.gpio2 = 0x00000000,
.gpio3 = 0x00000000,
},
.dvb = 1,
},
[CX88_BOARD_HAUPPAUGE_ROSLYN] = {
// entry added by Kaustubh D. Bhalerao <bhalerao.1@osu.edu>
// GPIO values obtained from regspy, courtesy Sean Covel
.name = "Hauppauge WinTV 28xxx (Roslyn) models",
.tuner_type = UNSET,
.input = {{
.type = CX88_VMUX_TELEVISION,
.vmux = 0,
.gpio0 = 0xed12, // internal decoder
.gpio2 = 0x00ff,
},{
.type = CX88_VMUX_DEBUG,
.vmux = 0,
.gpio0 = 0xff01, // mono from tuner chip
},{
.type = CX88_VMUX_COMPOSITE1,
.vmux = 1,
.gpio0 = 0xff02,
},{
.type = CX88_VMUX_SVIDEO,
.vmux = 2,
.gpio0 = 0xed92,
.gpio2 = 0x00ff,
}},
.radio = {
.type = CX88_RADIO,
.gpio0 = 0xed96,
.gpio2 = 0x00ff,
},
.blackbird = 1,
},
[CX88_BOARD_DIGITALLOGIC_MEC] = {
/* params copied over from Leadtek PVR 2000 */
.name = "Digital-Logic MICROSPACE Entertainment Center (MEC)",
/* not sure yet about the tuner type */
.tuner_type = 38,
.tda9887_conf = TDA9887_PRESENT,
.input = {{
.type = CX88_VMUX_TELEVISION,
.vmux = 0,
.gpio0 = 0x0000bde6,
},{
.type = CX88_VMUX_COMPOSITE1,
.vmux = 1,
.gpio0 = 0x0000bde6,
},{
.type = CX88_VMUX_SVIDEO,
.vmux = 2,
.gpio0 = 0x0000bde6,
}},
.radio = {
.type = CX88_RADIO,
.gpio0 = 0x0000bd62,
},
.blackbird = 1,
},
[CX88_BOARD_IODATA_GVBCTV7E] = {
.name = "IODATA GV/BCTV7E",
.tuner_type = TUNER_PHILIPS_FQ1286,
.tda9887_conf = TDA9887_PRESENT,
.input = {{
.type = CX88_VMUX_TELEVISION,
.vmux = 1,
.gpio1 = 0x0000e03f,
},{
.type = CX88_VMUX_COMPOSITE1,
.vmux = 2,
.gpio1 = 0x0000e07f,
},{
.type = CX88_VMUX_SVIDEO,
.vmux = 3,
.gpio1 = 0x0000e07f,
}}
},
};
const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards);
......@@ -482,11 +631,11 @@ struct cx88_subid cx88_subids[] = {
},{
.subvendor = 0x107d,
.subdevice = 0x6611,
.card = CX88_BOARD_WINFAST2000XP,
.card = CX88_BOARD_WINFAST2000XP_EXPERT,
},{
.subvendor = 0x107d,
.subdevice = 0x6613, /* NTSC */
.card = CX88_BOARD_WINFAST2000XP,
.card = CX88_BOARD_WINFAST2000XP_EXPERT,
},{
.subvendor = 0x107d,
.subdevice = 0x6620,
......@@ -543,6 +692,30 @@ struct cx88_subid cx88_subids[] = {
.subvendor = 0x18AC,
.subdevice = 0xDB10,
.card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS,
},{
.subvendor = 0x1554,
.subdevice = 0x4811,
.card = CX88_BOARD_PIXELVIEW,
},{
.subvendor = 0x7063,
.subdevice = 0x3000, /* HD-3000 card */
.card = CX88_BOARD_PCHDTV_HD3000,
},{
.subvendor = 0x17DE,
.subdevice = 0xA8A6,
.card = CX88_BOARD_DNTV_LIVE_DVB_T,
},{
.subvendor = 0x0070,
.subdevice = 0x2801,
.card = CX88_BOARD_HAUPPAUGE_ROSLYN,
},{
.subvendor = 0x14F1,
.subdevice = 0x0342,
.card = CX88_BOARD_DIGITALLOGIC_MEC,
},{
.subvendor = 0x10fc,
.subdevice = 0xd035,
.card = CX88_BOARD_IODATA_GVBCTV7E,
}
};
const unsigned int cx88_idcount = ARRAY_SIZE(cx88_subids);
......@@ -552,7 +725,7 @@ const unsigned int cx88_idcount = ARRAY_SIZE(cx88_subids);
static void __devinit leadtek_eeprom(struct cx88_core *core, u8 *eeprom_data)
{
/* This is just for the Winfast 2000 XP board ATM; I don't have data on
/* This is just for the "Winfast 2000XP Expert" board ATM; I don't have data on
* any others.
*
* Byte 0 is 1 on the NTSC board.
......@@ -569,108 +742,27 @@ static void __devinit leadtek_eeprom(struct cx88_core *core, u8 *eeprom_data)
core->has_radio = 1;
core->tuner_type = (eeprom_data[6] == 0x13) ? 43 : 38;
printk(KERN_INFO "%s: Leadtek Winfast 2000 XP config: "
printk(KERN_INFO "%s: Leadtek Winfast 2000XP Expert config: "
"tuner=%d, eeprom[0]=0x%02x\n",
core->name, core->tuner_type, eeprom_data[0]);
}
/* ----------------------------------------------------------------------- */
/* some hauppauge specific stuff */
static struct {
int id;
char *name;
} hauppauge_tuner[] __devinitdata = {
{ TUNER_ABSENT, "" },
{ TUNER_ABSENT, "External" },
{ TUNER_ABSENT, "Unspecified" },
{ TUNER_PHILIPS_PAL, "Philips FI1216" },
{ TUNER_PHILIPS_SECAM, "Philips FI1216MF" },
{ TUNER_PHILIPS_NTSC, "Philips FI1236" },
{ TUNER_PHILIPS_PAL_I, "Philips FI1246" },
{ TUNER_PHILIPS_PAL_DK,"Philips FI1256" },
{ TUNER_PHILIPS_PAL, "Philips FI1216 MK2" },
{ TUNER_PHILIPS_SECAM, "Philips FI1216MF MK2" },
{ TUNER_PHILIPS_NTSC, "Philips FI1236 MK2" },
{ TUNER_PHILIPS_PAL_I, "Philips FI1246 MK2" },
{ TUNER_PHILIPS_PAL_DK,"Philips FI1256 MK2" },
{ TUNER_TEMIC_NTSC, "Temic 4032FY5" },
{ TUNER_TEMIC_PAL, "Temic 4002FH5" },
{ TUNER_TEMIC_PAL_I, "Temic 4062FY5" },
{ TUNER_PHILIPS_PAL, "Philips FR1216 MK2" },
{ TUNER_PHILIPS_SECAM, "Philips FR1216MF MK2" },
{ TUNER_PHILIPS_NTSC, "Philips FR1236 MK2" },
{ TUNER_PHILIPS_PAL_I, "Philips FR1246 MK2" },
{ TUNER_PHILIPS_PAL_DK,"Philips FR1256 MK2" },
{ TUNER_PHILIPS_PAL, "Philips FM1216" },
{ TUNER_PHILIPS_SECAM, "Philips FM1216MF" },
{ TUNER_PHILIPS_NTSC, "Philips FM1236" },
{ TUNER_PHILIPS_PAL_I, "Philips FM1246" },
{ TUNER_PHILIPS_PAL_DK,"Philips FM1256" },
{ TUNER_TEMIC_4036FY5_NTSC, "Temic 4036FY5" },
{ TUNER_ABSENT, "Samsung TCPN9082D" },
{ TUNER_ABSENT, "Samsung TCPM9092P" },
{ TUNER_TEMIC_4006FH5_PAL, "Temic 4006FH5" },
{ TUNER_ABSENT, "Samsung TCPN9085D" },
{ TUNER_ABSENT, "Samsung TCPB9085P" },
{ TUNER_ABSENT, "Samsung TCPL9091P" },
{ TUNER_TEMIC_4039FR5_NTSC, "Temic 4039FR5" },
{ TUNER_PHILIPS_FQ1216ME, "Philips FQ1216 ME" },
{ TUNER_TEMIC_4066FY5_PAL_I, "Temic 4066FY5" },
{ TUNER_PHILIPS_NTSC, "Philips TD1536" },
{ TUNER_PHILIPS_NTSC, "Philips TD1536D" },
{ TUNER_PHILIPS_NTSC, "Philips FMR1236" }, /* mono radio */
{ TUNER_ABSENT, "Philips FI1256MP" },
{ TUNER_ABSENT, "Samsung TCPQ9091P" },
{ TUNER_TEMIC_4006FN5_MULTI_PAL, "Temic 4006FN5" },
{ TUNER_TEMIC_4009FR5_PAL, "Temic 4009FR5" },
{ TUNER_TEMIC_4046FM5, "Temic 4046FM5" },
{ TUNER_TEMIC_4009FN5_MULTI_PAL_FM, "Temic 4009FN5" },
{ TUNER_ABSENT, "Philips TD1536D_FH_44"},
{ TUNER_LG_NTSC_FM, "LG TPI8NSR01F"},
{ TUNER_LG_PAL_FM, "LG TPI8PSB01D"},
{ TUNER_LG_PAL, "LG TPI8PSB11D"},
{ TUNER_LG_PAL_I_FM, "LG TAPC-I001D"},
{ TUNER_LG_PAL_I, "LG TAPC-I701D"}
};
static void hauppauge_eeprom(struct cx88_core *core, u8 *eeprom_data)
{
unsigned int blk2,tuner,radio,model;
if (eeprom_data[0] != 0x84 || eeprom_data[2] != 0) {
printk(KERN_WARNING "%s: Hauppauge eeprom: invalid\n",
core->name);
return;
}
/* Block 2 starts after len+3 bytes header */
blk2 = eeprom_data[1] + 3;
struct tveeprom tv;
/* decode + use some config infos */
model = eeprom_data[12] << 8 | eeprom_data[11];
tuner = eeprom_data[9];
radio = eeprom_data[blk2-1] & 0x01;
if (tuner < ARRAY_SIZE(hauppauge_tuner))
core->tuner_type = hauppauge_tuner[tuner].id;
if (radio)
core->has_radio = 1;
printk(KERN_INFO "%s: hauppauge eeprom: model=%d, "
"tuner=%s (%d), radio=%s\n",
core->name, model, (tuner < ARRAY_SIZE(hauppauge_tuner)
? hauppauge_tuner[tuner].name : "?"),
core->tuner_type, radio ? "yes" : "no");
tveeprom_hauppauge_analog(&tv, eeprom_data);
core->tuner_type = tv.tuner_type;
core->has_radio = tv.has_radio;
}
#ifdef WITH_DVB
static int hauppauge_eeprom_dvb(struct cx88_core *core, u8 *ee)
{
int model;
int tuner;
char *tname;
/* Make sure we support the board model */
model = ee[0x1f] << 24 | ee[0x1e] << 16 | ee[0x1d] << 8 | ee[0x1c];
......@@ -689,26 +781,18 @@ static int hauppauge_eeprom_dvb(struct cx88_core *core, u8 *ee)
/* Make sure we support the tuner */
tuner = ee[0x2d];
switch(tuner) {
case 0x4B:
tname = "Thomson DTT 7595";
core->pll_type = PLLTYPE_DTT7595;
break;
case 0x4C:
tname = "Thomson DTT 7592";
core->pll_type = PLLTYPE_DTT7592;
case 0x4B: /* dtt 7595 */
case 0x4C: /* dtt 7592 */
break;
default:
printk("%s: error: unknown hauppauge tuner 0x%02x\n",
core->name, tuner);
return -ENODEV;
}
printk(KERN_INFO "%s: hauppauge eeprom: model=%d, tuner=%s (%d)\n",
core->name, model, tname, tuner);
core->pll_addr = 0x61;
core->demod_addr = 0x43;
printk(KERN_INFO "%s: hauppauge eeprom: model=%d, tuner=%d\n",
core->name, model, tuner);
return 0;
}
#endif
/* ----------------------------------------------------------------------- */
/* some GDI (was: Modular Technology) specific stuff */
......@@ -763,36 +847,6 @@ static void gdi_eeprom(struct cx88_core *core, u8 *eeprom_data)
/* ----------------------------------------------------------------------- */
static int
i2c_eeprom(struct i2c_client *c, unsigned char *eedata, int len)
{
unsigned char buf;
int err;
c->addr = 0xa0 >> 1;
buf = 0;
if (1 != (err = i2c_master_send(c,&buf,1))) {
printk(KERN_INFO "cx88: Huh, no eeprom present (err=%d)?\n",
err);
return -1;
}
if (len != (err = i2c_master_recv(c,eedata,len))) {
printk(KERN_WARNING "cx88: i2c eeprom read error (err=%d)\n",
err);
return -1;
}
#if 0
for (i = 0; i < len; i++) {
if (0 == (i % 16))
printk(KERN_INFO "cx88 ee: %02x:",i);
printk(" %02x",eedata[i]);
if (15 == (i % 16))
printk("\n");
}
#endif
return 0;
}
void cx88_card_list(struct cx88_core *core, struct pci_dev *pci)
{
int i;
......@@ -823,41 +877,46 @@ void cx88_card_setup(struct cx88_core *core)
{
static u8 eeprom[128];
if (0 == core->i2c_rc) {
core->i2c_client.addr = 0xa0 >> 1;
tveeprom_read(&core->i2c_client,eeprom,sizeof(eeprom));
}
switch (core->board) {
case CX88_BOARD_HAUPPAUGE:
case CX88_BOARD_HAUPPAUGE_ROSLYN:
if (0 == core->i2c_rc)
i2c_eeprom(&core->i2c_client,eeprom,sizeof(eeprom));
hauppauge_eeprom(core,eeprom+8);
hauppauge_eeprom(core,eeprom+8);
break;
case CX88_BOARD_GDI:
if (0 == core->i2c_rc)
i2c_eeprom(&core->i2c_client,eeprom,sizeof(eeprom));
gdi_eeprom(core,eeprom);
gdi_eeprom(core,eeprom);
break;
case CX88_BOARD_WINFAST2000XP:
case CX88_BOARD_WINFAST2000XP_EXPERT:
if (0 == core->i2c_rc)
i2c_eeprom(&core->i2c_client,eeprom,sizeof(eeprom));
leadtek_eeprom(core,eeprom);
leadtek_eeprom(core,eeprom);
break;
case CX88_BOARD_HAUPPAUGE_DVB_T1:
if (0 == core->i2c_rc)
hauppauge_eeprom_dvb(core,eeprom);
break;
case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1:
/* Tuner reset is hooked to the tuner out of reset */
case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS:
/* GPIO0:0 is hooked to mt352 reset pin */
cx_set(MO_GP0_IO, 0x00000101);
cx_clear(MO_GP0_IO, 0x00000001);
msleep(1);
cx_set(MO_GP0_IO, 0x00000101);
break;
#ifdef WITH_DVB
case CX88_BOARD_HAUPPAUGE_DVB_T1:
if (0 == core->i2c_rc)
i2c_eeprom(&core->i2c_client,eeprom,sizeof(eeprom));
hauppauge_eeprom_dvb(core,eeprom);
break;
case CX88_BOARD_CONEXANT_DVB_T1:
core->pll_type = PLLTYPE_DTT7579;
core->pll_addr = 0x60;
core->demod_addr = 0x43;
case CX88_BOARD_KWORLD_DVB_T:
case CX88_BOARD_DNTV_LIVE_DVB_T:
cx_set(MO_GP0_IO, 0x00000707);
cx_set(MO_GP2_IO, 0x00000101);
cx_clear(MO_GP2_IO, 0x00000001);
msleep(1);
cx_clear(MO_GP0_IO, 0x00000007);
cx_set(MO_GP2_IO, 0x00000101);
break;
#endif
}
if (cx88_boards[core->board].radio.type == CX88_RADIO)
core->has_radio = 1;
......
/*
* $Id: cx88-core.c,v 1.15 2004/10/25 11:26:36 kraxel Exp $
* $Id: cx88-core.c,v 1.24 2005/01/19 12:01:55 kraxel Exp $
*
* device driver for Conexant 2388x based TV cards
* driver core
......@@ -24,6 +24,7 @@
#include <linux/init.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/kmod.h>
......@@ -62,6 +63,10 @@ static unsigned int nicam = 0;
module_param(nicam,int,0644);
MODULE_PARM_DESC(nicam,"tv audio is nicam");
static unsigned int nocomb = 0;
module_param(nocomb,int,0644);
MODULE_PARM_DESC(nocomb,"disable comb filter");
#define dprintk(level,fmt, arg...) if (core_debug >= level) \
printk(KERN_DEBUG "%s: " fmt, core->name , ## arg)
......@@ -462,6 +467,7 @@ int cx88_risc_decode(u32 risc)
return incr[risc >> 28] ? incr[risc >> 28] : 1;
}
#if 0 /* currently unused, but useful for debugging */
void cx88_risc_disasm(struct cx88_core *core,
struct btcx_riscmem *risc)
{
......@@ -479,6 +485,7 @@ void cx88_risc_disasm(struct cx88_core *core,
break;
}
}
#endif
void cx88_sram_channel_dump(struct cx88_core *core,
struct sram_channel *ch)
......@@ -579,10 +586,19 @@ void cx88_print_irqbits(char *name, char *tag, char **strings,
/* ------------------------------------------------------------------ */
void cx88_irq(struct cx88_core *core, u32 status, u32 mask)
int cx88_core_irq(struct cx88_core *core, u32 status)
{
cx88_print_irqbits(core->name, "irq pci",
cx88_pci_irqs, status, mask);
int handled = 0;
if (status & (1<<18)) {
cx88_ir_irq(core);
handled++;
}
if (!handled)
cx88_print_irqbits(core->name, "irq pci",
cx88_pci_irqs, status,
core->pci_irqmask);
return handled;
}
void cx88_wakeup(struct cx88_core *core,
......@@ -800,6 +816,8 @@ int cx88_set_scale(struct cx88_core *core, unsigned int width, unsigned int heig
value |= (1 << 0); // 3-tap interpolation
if (width < 193)
value |= (1 << 1); // 5-tap interpolation
if (nocomb)
value |= (3 << 5); // disable comb filter
cx_write(MO_FILTER_EVEN, value);
cx_write(MO_FILTER_ODD, value);
......@@ -887,8 +905,8 @@ static int set_tvaudio(struct cx88_core *core)
cx88_set_tvaudio(core);
// cx88_set_stereo(dev,V4L2_TUNER_MODE_STEREO);
cx_write(MO_AUDD_LNGTH, 128/8); /* fifo size */
cx_write(MO_AUDR_LNGTH, 128/8); /* fifo size */
cx_write(MO_AUDD_LNGTH, 128); /* fifo size */
cx_write(MO_AUDR_LNGTH, 128); /* fifo size */
cx_write(MO_AUD_DMACNTRL, 0x03); /* need audio fifo */
return 0;
}
......@@ -969,6 +987,9 @@ int cx88_set_tvnorm(struct cx88_core *core, struct cx88_tvnorm *norm)
cx_write(MO_VBI_PACKET, ((1 << 11) | /* (norm_vdelay(norm) << 11) | */
norm_vbipack(norm)));
// this is needed as well to set all tvnorm parameter
cx88_set_scale(core, 320, 240, V4L2_FIELD_INTERLACED);
// audio
set_tvaudio(core);
......@@ -1105,9 +1126,10 @@ struct cx88_core* cx88_core_get(struct pci_dev *pci)
goto fail_unlock;
memset(core,0,sizeof(*core));
atomic_inc(&core->refcount);
core->pci_bus = pci->bus->number;
core->pci_slot = PCI_SLOT(pci->devfn);
atomic_inc(&core->refcount);
core->pci_irqmask = 0x00fc00;
core->nr = cx88_devcount++;
sprintf(core->name,"cx88[%d]",core->nr);
......@@ -1150,6 +1172,7 @@ struct cx88_core* cx88_core_get(struct pci_dev *pci)
cx88_reset(core);
cx88_i2c_init(core,pci);
cx88_card_setup(core);
cx88_ir_init(core,pci);
up(&devlist);
return core;
......@@ -1170,6 +1193,7 @@ void cx88_core_put(struct cx88_core *core, struct pci_dev *pci)
return;
down(&devlist);
cx88_ir_fini(core);
if (0 == core->i2c_rc)
i2c_bit_del_bus(&core->i2c_adap);
list_del(&core->devlist);
......@@ -1187,7 +1211,7 @@ EXPORT_SYMBOL(cx88_vid_irqs);
EXPORT_SYMBOL(cx88_mpeg_irqs);
EXPORT_SYMBOL(cx88_print_irqbits);
EXPORT_SYMBOL(cx88_irq);
EXPORT_SYMBOL(cx88_core_irq);
EXPORT_SYMBOL(cx88_wakeup);
EXPORT_SYMBOL(cx88_reset);
EXPORT_SYMBOL(cx88_shutdown);
......@@ -1197,8 +1221,6 @@ EXPORT_SYMBOL(cx88_risc_databuffer);
EXPORT_SYMBOL(cx88_risc_stopper);
EXPORT_SYMBOL(cx88_free_buffer);
EXPORT_SYMBOL(cx88_risc_disasm);
EXPORT_SYMBOL(cx88_sram_channels);
EXPORT_SYMBOL(cx88_sram_channel_setup);
EXPORT_SYMBOL(cx88_sram_channel_dump);
......
/*
* $Id: cx88-dvb.c,v 1.19 2004/11/07 14:44:59 kraxel Exp $
* $Id: cx88-dvb.c,v 1.31 2005/03/07 15:58:05 kraxel Exp $
*
* device driver for Conexant 2388x based TV cards
* MPEG Transport Stream (DVB) routines
......@@ -30,10 +30,20 @@
#include <linux/file.h>
#include <linux/suspend.h>
/* those two frontends need merging via linuxtv cvs ... */
#define HAVE_CX22702 0
#define HAVE_OR51132 0
#include "cx88.h"
#include "cx22702.h"
#include "dvb-pll.h"
#include "mt352.h"
#include "mt352_priv.h" /* FIXME */
#include "mt352_priv.h"
#if HAVE_CX22702
# include "cx22702.h"
#endif
#if HAVE_OR51132
# include "or51132.h"
#endif
MODULE_DESCRIPTION("driver for cx2388x based DVB cards");
MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>");
......@@ -110,111 +120,144 @@ static int dvico_fusionhdtv_demod_init(struct dvb_frontend* fe)
return 0;
}
#define IF_FREQUENCYx6 217 /* 6 * 36.16666666667MHz */
static int lg_z201_pll_set(struct dvb_frontend* fe,
struct dvb_frontend_parameters* params, u8* pllbuf)
static int dntv_live_dvbt_demod_init(struct dvb_frontend* fe)
{
u32 div;
unsigned char cp = 0;
unsigned char bs = 0;
div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
static u8 clock_config [] = { 0x89, 0x38, 0x39 };
static u8 reset [] = { 0x50, 0x80 };
static u8 adc_ctl_1_cfg [] = { 0x8E, 0x40 };
static u8 agc_cfg [] = { 0x67, 0x10, 0x23, 0x00, 0xFF, 0xFF,
0x00, 0xFF, 0x00, 0x40, 0x40 };
static u8 dntv_extra[] = { 0xB5, 0x7A };
static u8 capt_range_cfg[] = { 0x75, 0x32 };
if (params->frequency < 542000000) cp = 0xbc;
else if (params->frequency < 830000000) cp = 0xf4;
else cp = 0xfc;
if (params->frequency == 0) bs = 0x03;
else if (params->frequency < 157500000) bs = 0x01;
else if (params->frequency < 443250000) bs = 0x02;
else bs = 0x04;
mt352_write(fe, clock_config, sizeof(clock_config));
udelay(2000);
mt352_write(fe, reset, sizeof(reset));
mt352_write(fe, adc_ctl_1_cfg, sizeof(adc_ctl_1_cfg));
pllbuf[0] = 0xC2; /* Note: non-linux standard PLL I2C address */
pllbuf[1] = div >> 8;
pllbuf[2] = div & 0xff;
pllbuf[3] = cp;
pllbuf[4] = bs;
mt352_write(fe, agc_cfg, sizeof(agc_cfg));
udelay(2000);
mt352_write(fe, dntv_extra, sizeof(dntv_extra));
mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg));
return 0;
}
static int thomson_dtt7579_pll_set(struct dvb_frontend* fe,
struct dvb_frontend_parameters* params,
u8* pllbuf)
static int mt352_pll_set(struct dvb_frontend* fe,
struct dvb_frontend_parameters* params,
u8* pllbuf)
{
u32 div;
unsigned char cp = 0;
unsigned char bs = 0;
div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
if (params->frequency < 542000000) cp = 0xb4;
else if (params->frequency < 771000000) cp = 0xbc;
else cp = 0xf4;
if (params->frequency == 0) bs = 0x03;
else if (params->frequency < 443250000) bs = 0x02;
else bs = 0x08;
pllbuf[0] = 0xc0; // Note: non-linux standard PLL i2c address
pllbuf[1] = div >> 8;
pllbuf[2] = div & 0xff;
pllbuf[3] = cp;
pllbuf[4] = bs;
struct cx8802_dev *dev= fe->dvb->priv;
pllbuf[0] = dev->core->pll_addr << 1;
dvb_pll_configure(dev->core->pll_desc, pllbuf+1,
params->frequency,
params->u.ofdm.bandwidth);
return 0;
}
struct mt352_config dvico_fusionhdtv_dvbt1 = {
static struct mt352_config dvico_fusionhdtv = {
.demod_address = 0x0F,
.demod_init = dvico_fusionhdtv_demod_init,
.pll_set = lg_z201_pll_set,
.pll_set = mt352_pll_set,
};
struct mt352_config dvico_fusionhdtv_dvbt_plus = {
.demod_address = 0x0F,
.demod_init = dvico_fusionhdtv_demod_init,
.pll_set = thomson_dtt7579_pll_set,
static struct mt352_config dntv_live_dvbt_config = {
.demod_address = 0x0f,
.demod_init = dntv_live_dvbt_demod_init,
.pll_set = mt352_pll_set,
};
#if HAVE_CX22702
static struct cx22702_config connexant_refboard_config = {
.demod_address = 0x43,
.pll_address = 0x60,
.pll_desc = &dvb_pll_thomson_dtt7579,
};
static struct cx22702_config hauppauge_novat_config = {
.demod_address = 0x43,
.pll_address = 0x61,
.pll_desc = &dvb_pll_thomson_dtt759x,
};
#endif
#if HAVE_OR51132
static int or51132_set_ts_param(struct dvb_frontend* fe,
int is_punctured)
{
struct cx8802_dev *dev= fe->dvb->priv;
dev->ts_gen_cntrl = is_punctured ? 0x04 : 0x00;
return 0;
}
struct or51132_config pchdtv_hd3000 = {
.demod_address = 0x15,
.pll_address = 0x61,
.pll_desc = &dvb_pll_thomson_dtt7610,
.set_ts_params = or51132_set_ts_param,
};
#endif
static int dvb_register(struct cx8802_dev *dev)
{
/* init struct videobuf_dvb */
dev->dvb.name = dev->core->name;
dev->ts_gen_cntrl = 0x0c;
/* init frontend */
switch (dev->core->board) {
#if HAVE_CX22702
case CX88_BOARD_HAUPPAUGE_DVB_T1:
dev->dvb.frontend = cx22702_attach(&hauppauge_novat_config,
&dev->core->i2c_adap);
break;
case CX88_BOARD_CONEXANT_DVB_T1:
dev->dvb.frontend = cx22702_create(&dev->core->i2c_adap,
dev->core->pll_addr,
dev->core->pll_type,
dev->core->demod_addr);
dev->dvb.frontend = cx22702_attach(&connexant_refboard_config,
&dev->core->i2c_adap);
break;
#endif
case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1:
dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv_dvbt1,
dev->core->pll_addr = 0x61;
dev->core->pll_desc = &dvb_pll_lg_z201;
dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv,
&dev->core->i2c_adap);
if (dev->dvb.frontend) {
dev->dvb.frontend->ops->info.frequency_min = 174000000;
dev->dvb.frontend->ops->info.frequency_max = 862000000;
}
break;
case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS:
dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv_dvbt_plus,
dev->core->pll_addr = 0x60;
dev->core->pll_desc = &dvb_pll_thomson_dtt7579;
dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv,
&dev->core->i2c_adap);
break;
case CX88_BOARD_KWORLD_DVB_T:
case CX88_BOARD_DNTV_LIVE_DVB_T:
dev->core->pll_addr = 0x61;
dev->core->pll_desc = &dvb_pll_unknown_1;
dev->dvb.frontend = mt352_attach(&dntv_live_dvbt_config,
&dev->core->i2c_adap);
break;
#if HAVE_OR51132
case CX88_BOARD_PCHDTV_HD3000:
dev->dvb.frontend = or51132_attach(&pchdtv_hd3000,
&dev->core->i2c_adap);
if (dev->dvb.frontend) {
dev->dvb.frontend->ops->info.frequency_min = 174000000;
dev->dvb.frontend->ops->info.frequency_max = 862000000;
}
break;
#endif
default:
printk("%s: FIXME: frontend handling not here yet ...\n",
dev->core->name);
printk("%s: The frontend of your DVB/ATSC card isn't supported yet\n"
"%s: you might want to look out for patches here:\n"
"%s: http://dl.bytesex.org/patches/\n",
dev->core->name, dev->core->name, dev->core->name);
break;
}
if (NULL == dev->dvb.frontend)
if (NULL == dev->dvb.frontend) {
printk("%s: frontend initialization failed\n",dev->core->name);
return -1;
}
if (dev->core->pll_desc) {
dev->dvb.frontend->ops->info.frequency_min = dev->core->pll_desc->min;
dev->dvb.frontend->ops->info.frequency_max = dev->core->pll_desc->max;
}
/* Copy the board name into the DVB structure */
strlcpy(dev->dvb.frontend->ops->info.name,
......@@ -222,7 +265,7 @@ static int dvb_register(struct cx8802_dev *dev)
sizeof(dev->dvb.frontend->ops->info.name));
/* register everything */
return videobuf_dvb_register(&dev->dvb);
return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev);
}
/* ----------------------------------------------------------- */
......
/*
$Id: cx88-i2c.c,v 1.18 2004/10/13 10:39:00 kraxel Exp $
$Id: cx88-i2c.c,v 1.20 2005/02/15 15:59:35 kraxel Exp $
cx88-i2c.c -- all the i2c code is here
......@@ -25,6 +25,7 @@
*/
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <asm/io.h>
......
/*
* $Id: cx88-input.c,v 1.9 2005/03/04 09:12:23 kraxel Exp $
*
* Device driver for GPIO attached remote control interfaces
* on Conexant 2388x based TV/DVB cards.
*
* Copyright (c) 2003 Pavel Machek
* Copyright (c) 2004 Gerd Knorr
* Copyright (c) 2004 Chris Pascoe
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/input.h>
#include <linux/pci.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <media/ir-common.h>
#include "cx88.h"
/* ---------------------------------------------------------------------- */
/* DigitalNow DNTV Live DVB-T Remote */
static IR_KEYTAB_TYPE ir_codes_dntv_live_dvb_t[IR_KEYTAB_SIZE] = {
[ 0x00 ] = KEY_ESC, // 'go up a level?'
[ 0x01 ] = KEY_KP1, // '1'
[ 0x02 ] = KEY_KP2, // '2'
[ 0x03 ] = KEY_KP3, // '3'
[ 0x04 ] = KEY_KP4, // '4'
[ 0x05 ] = KEY_KP5, // '5'
[ 0x06 ] = KEY_KP6, // '6'
[ 0x07 ] = KEY_KP7, // '7'
[ 0x08 ] = KEY_KP8, // '8'
[ 0x09 ] = KEY_KP9, // '9'
[ 0x0a ] = KEY_KP0, // '0'
[ 0x0b ] = KEY_TUNER, // 'tv/fm'
[ 0x0c ] = KEY_SEARCH, // 'scan'
[ 0x0d ] = KEY_STOP, // 'stop'
[ 0x0e ] = KEY_PAUSE, // 'pause'
[ 0x0f ] = KEY_LIST, // 'source'
[ 0x10 ] = KEY_MUTE, // 'mute'
[ 0x11 ] = KEY_REWIND, // 'backward <<'
[ 0x12 ] = KEY_POWER, // 'power'
[ 0x13 ] = KEY_S, // 'snap'
[ 0x14 ] = KEY_AUDIO, // 'stereo'
[ 0x15 ] = KEY_CLEAR, // 'reset'
[ 0x16 ] = KEY_PLAY, // 'play'
[ 0x17 ] = KEY_ENTER, // 'enter'
[ 0x18 ] = KEY_ZOOM, // 'full screen'
[ 0x19 ] = KEY_FASTFORWARD, // 'forward >>'
[ 0x1a ] = KEY_CHANNELUP, // 'channel +'
[ 0x1b ] = KEY_VOLUMEUP, // 'volume +'
[ 0x1c ] = KEY_INFO, // 'preview'
[ 0x1d ] = KEY_RECORD, // 'record'
[ 0x1e ] = KEY_CHANNELDOWN, // 'channel -'
[ 0x1f ] = KEY_VOLUMEDOWN, // 'volume -'
};
/* ---------------------------------------------------------------------- */
/* IO-DATA BCTV7E Remote */
static IR_KEYTAB_TYPE ir_codes_iodata_bctv7e[IR_KEYTAB_SIZE] = {
[ 0x40 ] = KEY_TV, // TV
[ 0x20 ] = KEY_RADIO, // FM
[ 0x60 ] = KEY_EPG, // EPG
[ 0x00 ] = KEY_POWER, // power
[ 0x50 ] = KEY_KP1, // 1
[ 0x30 ] = KEY_KP2, // 2
[ 0x70 ] = KEY_KP3, // 3
[ 0x10 ] = KEY_L, // Live
[ 0x48 ] = KEY_KP4, // 4
[ 0x28 ] = KEY_KP5, // 5
[ 0x68 ] = KEY_KP6, // 6
[ 0x08 ] = KEY_T, // Time Shift
[ 0x58 ] = KEY_KP7, // 7
[ 0x38 ] = KEY_KP8, // 8
[ 0x78 ] = KEY_KP9, // 9
[ 0x18 ] = KEY_PLAYPAUSE, // Play
[ 0x44 ] = KEY_KP0, // 10
[ 0x24 ] = KEY_ENTER, // 11
[ 0x64 ] = KEY_ESC, // 12
[ 0x04 ] = KEY_M, // Multi
[ 0x54 ] = KEY_VIDEO, // VIDEO
[ 0x34 ] = KEY_CHANNELUP, // channel +
[ 0x74 ] = KEY_VOLUMEUP, // volume +
[ 0x14 ] = KEY_MUTE, // Mute
[ 0x4c ] = KEY_S, // SVIDEO
[ 0x2c ] = KEY_CHANNELDOWN, // channel -
[ 0x6c ] = KEY_VOLUMEDOWN, // volume -
[ 0x0c ] = KEY_ZOOM, // Zoom
[ 0x5c ] = KEY_PAUSE, // pause
[ 0x3c ] = KEY_C, // || (red)
[ 0x7c ] = KEY_RECORD, // recording
[ 0x1c ] = KEY_STOP, // stop
[ 0x41 ] = KEY_REWIND, // backward <<
[ 0x21 ] = KEY_PLAY, // play
[ 0x61 ] = KEY_FASTFORWARD, // forward >>
[ 0x01 ] = KEY_NEXT, // skip >|
};
/* ---------------------------------------------------------------------- */
struct cx88_IR {
struct cx88_core *core;
struct input_dev input;
struct ir_input_state ir;
char name[32];
char phys[32];
/* sample from gpio pin 16 */
int sampling;
u32 samples[16];
int scount;
unsigned long release;
/* poll external decoder */
int polling;
struct work_struct work;
struct timer_list timer;
u32 gpio_addr;
u32 last_gpio;
u32 mask_keycode;
u32 mask_keydown;
u32 mask_keyup;
};
static int ir_debug = 0;
module_param(ir_debug, int, 0644); /* debug level [IR] */
MODULE_PARM_DESC(ir_debug, "enable debug messages [IR]");
#define ir_dprintk(fmt, arg...) if (ir_debug) \
printk(KERN_DEBUG "%s IR: " fmt , ir->core->name, ## arg)
/* ---------------------------------------------------------------------- */
static void cx88_ir_handle_key(struct cx88_IR *ir)
{
struct cx88_core *core = ir->core;
u32 gpio, data;
/* read gpio value */
gpio = cx_read(ir->gpio_addr);
if (ir->polling) {
if (ir->last_gpio == gpio)
return;
ir->last_gpio = gpio;
}
/* extract data */
data = ir_extract_bits(gpio, ir->mask_keycode);
ir_dprintk("irq gpio=0x%x code=%d | %s%s%s\n",
gpio, data,
ir->polling ? "poll" : "irq",
(gpio & ir->mask_keydown) ? " down" : "",
(gpio & ir->mask_keyup) ? " up" : "");
if (ir->mask_keydown) {
/* bit set on keydown */
if (gpio & ir->mask_keydown) {
ir_input_keydown(&ir->input,&ir->ir,data,data);
} else {
ir_input_nokey(&ir->input,&ir->ir);
}
} else if (ir->mask_keyup) {
/* bit cleared on keydown */
if (0 == (gpio & ir->mask_keyup)) {
ir_input_keydown(&ir->input,&ir->ir,data,data);
} else {
ir_input_nokey(&ir->input,&ir->ir);
}
} else {
/* can't distinguish keydown/up :-/ */
ir_input_keydown(&ir->input,&ir->ir,data,data);
ir_input_nokey(&ir->input,&ir->ir);
}
}
static void ir_timer(unsigned long data)
{
struct cx88_IR *ir = (struct cx88_IR*)data;
schedule_work(&ir->work);
}
static void cx88_ir_work(void *data)
{
struct cx88_IR *ir = data;
unsigned long timeout;
cx88_ir_handle_key(ir);
timeout = jiffies + (ir->polling * HZ / 1000);
mod_timer(&ir->timer, timeout);
}
/* ---------------------------------------------------------------------- */
int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
{
struct cx88_IR *ir;
IR_KEYTAB_TYPE *ir_codes = NULL;
int ir_type = IR_TYPE_OTHER;
ir = kmalloc(sizeof(*ir),GFP_KERNEL);
if (NULL == ir)
return -ENOMEM;
memset(ir,0,sizeof(*ir));
/* detect & configure */
switch (core->board) {
case CX88_BOARD_DNTV_LIVE_DVB_T:
ir_codes = ir_codes_dntv_live_dvb_t;
ir->gpio_addr = MO_GP1_IO;
ir->mask_keycode = 0x1f;
ir->mask_keyup = 0x60;
ir->polling = 50; // ms
break;
case CX88_BOARD_HAUPPAUGE:
case CX88_BOARD_HAUPPAUGE_DVB_T1:
ir_codes = ir_codes_hauppauge_new;
ir_type = IR_TYPE_RC5;
ir->sampling = 1;
break;
case CX88_BOARD_WINFAST2000XP_EXPERT:
ir_codes = ir_codes_winfast;
ir->gpio_addr = MO_GP0_IO;
ir->mask_keycode = 0x8f8;
ir->mask_keyup = 0x100;
ir->polling = 1; // ms
break;
case CX88_BOARD_IODATA_GVBCTV7E:
ir_codes = ir_codes_iodata_bctv7e;
ir->gpio_addr = MO_GP0_IO;
ir->mask_keycode = 0xfd;
ir->mask_keydown = 0x02;
ir->polling = 5; // ms
break;
}
if (NULL == ir_codes) {
kfree(ir);
return -ENODEV;
}
/* init input device */
snprintf(ir->name, sizeof(ir->name), "cx88 IR (%s)",
cx88_boards[core->board].name);
snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0",
pci_name(pci));
ir_input_init(&ir->input, &ir->ir, ir_type, ir_codes);
ir->input.name = ir->name;
ir->input.phys = ir->phys;
ir->input.id.bustype = BUS_PCI;
ir->input.id.version = 1;
if (pci->subsystem_vendor) {
ir->input.id.vendor = pci->subsystem_vendor;
ir->input.id.product = pci->subsystem_device;
} else {
ir->input.id.vendor = pci->vendor;
ir->input.id.product = pci->device;
}
/* record handles to ourself */
ir->core = core;
core->ir = ir;
if (ir->polling) {
INIT_WORK(&ir->work, cx88_ir_work, ir);
init_timer(&ir->timer);
ir->timer.function = ir_timer;
ir->timer.data = (unsigned long)ir;
schedule_work(&ir->work);
}
if (ir->sampling) {
core->pci_irqmask |= (1<<18); // IR_SMP_INT
cx_write(MO_DDS_IO, 0xa80a80); // 4 kHz sample rate
cx_write(MO_DDSCFG_IO, 0x5); // enable
}
/* all done */
input_register_device(&ir->input);
printk("%s: registered IR remote control\n", core->name);
return 0;
}
int cx88_ir_fini(struct cx88_core *core)
{
struct cx88_IR *ir = core->ir;
/* skip detach on non attached boards */
if (NULL == ir)
return 0;
if (ir->polling) {
del_timer(&ir->timer);
flush_scheduled_work();
}
input_unregister_device(&ir->input);
kfree(ir);
/* done */
core->ir = NULL;
return 0;
}
/* ---------------------------------------------------------------------- */
void cx88_ir_irq(struct cx88_core *core)
{
struct cx88_IR *ir = core->ir;
u32 samples,rc5;
int i;
if (NULL == ir)
return;
if (!ir->sampling)
return;
samples = cx_read(MO_SAMPLE_IO);
if (0 != samples && 0xffffffff != samples) {
/* record sample data */
if (ir->scount < ARRAY_SIZE(ir->samples))
ir->samples[ir->scount++] = samples;
return;
}
if (!ir->scount) {
/* nothing to sample */
if (ir->ir.keypressed && time_after(jiffies,ir->release))
ir_input_nokey(&ir->input,&ir->ir);
return;
}
/* have a complete sample */
if (ir->scount < ARRAY_SIZE(ir->samples))
ir->samples[ir->scount++] = samples;
for (i = 0; i < ir->scount; i++)
ir->samples[i] = ~ir->samples[i];
if (ir_debug)
ir_dump_samples(ir->samples,ir->scount);
/* decode it */
switch (core->board) {
case CX88_BOARD_HAUPPAUGE:
case CX88_BOARD_HAUPPAUGE_DVB_T1:
rc5 = ir_decode_biphase(ir->samples,ir->scount,5,7);
ir_dprintk("biphase decoded: %x\n",rc5);
if ((rc5 & 0xfffff000) != 0x3000)
break;
ir_input_keydown(&ir->input, &ir->ir, rc5 & 0x3f, rc5);
ir->release = jiffies + msecs_to_jiffies(120);
break;
}
ir->scount = 0;
return;
}
/* ---------------------------------------------------------------------- */
MODULE_AUTHOR("Gerd Knorr, Pavel Machek, Chris Pascoe");
MODULE_DESCRIPTION("input driver for cx88 GPIO-based IR remote controls");
MODULE_LICENSE("GPL");
/*
* Local variables:
* c-basic-offset: 8
* End:
*/
/*
* $Id: cx88-mpeg.c,v 1.14 2004/10/25 11:26:36 kraxel Exp $
* $Id: cx88-mpeg.c,v 1.25 2005/03/07 14:18:00 kraxel Exp $
*
* Support for the mpeg transport stream transfers
* PCI function #2 of the cx2388x.
......@@ -24,6 +24,7 @@
*/
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/interrupt.h>
......@@ -68,8 +69,14 @@ static int cx8802_start_dma(struct cx8802_dev *dev,
* also: move to cx88-blackbird + cx88-dvb source files? */
if (cx88_boards[core->board].dvb) {
/* Setup TS portion of chip */
cx_write(TS_GEN_CNTRL, 0x0c);
/* negedge driven & software reset */
cx_write(TS_GEN_CNTRL, 0x40);
udelay(100);
cx_write(MO_PINMUX_IO, 0x00);
cx_write(TS_HW_SOP_CNTRL,47<<16|188<<4|0x00);
cx_write(TS_SOP_STAT,0x00);
cx_write(TS_GEN_CNTRL, dev->ts_gen_cntrl);
udelay(100);
}
if (cx88_boards[core->board].blackbird) {
......@@ -93,7 +100,7 @@ static int cx8802_start_dma(struct cx8802_dev *dev,
q->count = 1;
/* enable irqs */
cx_set(MO_PCI_INTMSK, 0x00fc04);
cx_set(MO_PCI_INTMSK, core->pci_irqmask | 0x04);
cx_write(MO_TS_INTMSK, 0x1f0011);
/* start dma */
......@@ -292,19 +299,18 @@ static irqreturn_t cx8802_irq(int irq, void *dev_id, struct pt_regs *regs)
{
struct cx8802_dev *dev = dev_id;
struct cx88_core *core = dev->core;
u32 status, mask;
u32 status;
int loop, handled = 0;
for (loop = 0; loop < 10; loop++) {
status = cx_read(MO_PCI_INTSTAT) & (~0x1f | 0x04);
mask = cx_read(MO_PCI_INTMSK);
if (0 == (status & mask))
status = cx_read(MO_PCI_INTSTAT) & (core->pci_irqmask | 0x04);
if (0 == status)
goto out;
handled = 1;
cx_write(MO_PCI_INTSTAT, status);
if (status & mask & ~0x1f)
cx88_irq(core,status,mask);
if (status & core->pci_irqmask)
cx88_core_irq(core,status);
if (status & 0x04)
cx8802_mpeg_irq(dev);
};
......@@ -323,6 +329,7 @@ static irqreturn_t cx8802_irq(int irq, void *dev_id, struct pt_regs *regs)
int cx8802_init_common(struct cx8802_dev *dev)
{
struct cx88_core *core = dev->core;
int err;
/* pci init */
......@@ -354,11 +361,6 @@ int cx8802_init_common(struct cx8802_dev *dev)
cx88_risc_stopper(dev->pci,&dev->mpegq.stopper,
MO_TS_DMACNTRL,0x11,0x00);
#if 0 /* FIXME */
/* initialize hardware */
cx8802_reset(dev);
#endif
/* get irq */
err = request_irq(dev->pci->irq, cx8802_irq,
SA_SHIRQ | SA_INTERRUPT, dev->core->name, dev);
......@@ -367,11 +369,7 @@ int cx8802_init_common(struct cx8802_dev *dev)
dev->core->name, dev->pci->irq);
return err;
}
#if 0 /* FIXME */
/* register i2c bus + load i2c helpers */
cx88_card_setup(dev);
#endif
cx_set(MO_PCI_INTMSK, core->pci_irqmask);
/* everything worked */
pci_set_drvdata(dev->pci,dev);
......@@ -393,7 +391,7 @@ void cx8802_fini_common(struct cx8802_dev *dev)
/* ----------------------------------------------------------- */
int cx8802_suspend_common(struct pci_dev *pci_dev, u32 state)
int cx8802_suspend_common(struct pci_dev *pci_dev, pm_message_t state)
{
struct cx8802_dev *dev = pci_get_drvdata(pci_dev);
struct cx88_core *core = dev->core;
......@@ -413,7 +411,7 @@ int cx8802_suspend_common(struct pci_dev *pci_dev, u32 state)
#endif
pci_save_state(pci_dev);
if (0 != pci_set_power_state(pci_dev, state)) {
if (0 != pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state))) {
pci_disable_device(pci_dev);
dev->state.disabled = 1;
}
......@@ -429,7 +427,7 @@ int cx8802_resume_common(struct pci_dev *pci_dev)
pci_enable_device(pci_dev);
dev->state.disabled = 0;
}
pci_set_power_state(pci_dev, 0);
pci_set_power_state(pci_dev, PCI_D0);
pci_restore_state(pci_dev);
#if 1
......
/*
$Id: cx88-tvaudio.c,v 1.24 2004/10/25 11:51:00 kraxel Exp $
$Id: cx88-tvaudio.c,v 1.34 2005/03/07 16:10:51 kraxel Exp $
cx88x-audio.c - Conexant CX23880/23881 audio downstream driver driver
......@@ -37,6 +37,7 @@
*/
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/slab.h>
......@@ -56,7 +57,7 @@
#include "cx88.h"
static unsigned int audio_debug = 1;
static unsigned int audio_debug = 0;
module_param(audio_debug,int,0644);
MODULE_PARM_DESC(audio_debug,"enable debug messages [audio]");
......@@ -141,6 +142,13 @@ static void set_audio_finish(struct cx88_core *core)
{
u32 volume;
if (cx88_boards[core->board].blackbird) {
// 'pass-thru mode': this enables the i2s output to the mpeg encoder
cx_set(AUD_CTL, 0x2000);
cx_write(AUD_I2SOUTPUTCNTL, 1);
//cx_write(AUD_APB_IN_RATE_ADJ, 0);
}
// finish programming
cx_write(AUD_SOFT_RESET, 0x0000);
......@@ -263,6 +271,7 @@ static void set_audio_standard_BTSC(struct cx88_core *core, unsigned int sap)
set_audio_finish(core);
}
#if 0
static void set_audio_standard_NICAM(struct cx88_core *core)
{
static const struct rlist nicam_common[] = {
......@@ -335,128 +344,243 @@ static void set_audio_standard_NICAM(struct cx88_core *core)
};
set_audio_finish(core);
}
#endif
static void set_audio_standard_NICAM_L(struct cx88_core *core)
static void set_audio_standard_NICAM_L(struct cx88_core *core, int stereo)
{
/* This is officially weird.. register dumps indicate windows
* uses audio mode 4.. A2. Let's operate and find out. */
/* This is probably weird..
* Let's operate and find out. */
static const struct rlist nicam_l_mono[] = {
{ AUD_ERRLOGPERIOD_R, 0x00000064 },
{ AUD_ERRINTRPTTHSHLD1_R, 0x00000FFF },
{ AUD_ERRINTRPTTHSHLD2_R, 0x0000001F },
{ AUD_ERRINTRPTTHSHLD3_R, 0x0000000F },
{ AUD_PDF_DDS_CNST_BYTE2, 0x48 },
{ AUD_PDF_DDS_CNST_BYTE1, 0x3D },
{ AUD_QAM_MODE, 0x00 },
{ AUD_PDF_DDS_CNST_BYTE0, 0xf5 },
{ AUD_PHACC_FREQ_8MSB, 0x3a },
{ AUD_PHACC_FREQ_8LSB, 0x4a },
{ AUD_DEEMPHGAIN_R, 0x6680 },
{ AUD_DEEMPHNUMER1_R, 0x353DE },
{ AUD_DEEMPHNUMER2_R, 0x1B1 },
{ AUD_DEEMPHDENOM1_R, 0x0F3D0 },
{ AUD_DEEMPHDENOM2_R, 0x0 },
{ AUD_FM_MODE_ENABLE, 0x7 },
{ AUD_POLYPH80SCALEFAC, 0x3 },
{ AUD_AFE_12DB_EN, 0x1 },
{ AAGC_GAIN, 0x0 },
{ AAGC_HYST, 0x18 },
{ AAGC_DEF, 0x20 },
{ AUD_DN0_FREQ, 0x0 },
{ AUD_POLY0_DDS_CONSTANT, 0x0E4DB2 },
{ AUD_DCOC_0_SRC, 0x21 },
{ AUD_IIR1_0_SEL, 0x0 },
{ AUD_IIR1_0_SHIFT, 0x7 },
{ AUD_IIR1_1_SEL, 0x2 },
{ AUD_IIR1_1_SHIFT, 0x0 },
{ AUD_DCOC_1_SRC, 0x3 },
{ AUD_DCOC1_SHIFT, 0x0 },
{ AUD_DCOC_PASS_IN, 0x0 },
{ AUD_IIR1_2_SEL, 0x23 },
{ AUD_IIR1_2_SHIFT, 0x0 },
{ AUD_IIR1_3_SEL, 0x4 },
{ AUD_IIR1_3_SHIFT, 0x7 },
{ AUD_IIR1_4_SEL, 0x5 },
{ AUD_IIR1_4_SHIFT, 0x7 },
{ AUD_IIR3_0_SEL, 0x7 },
{ AUD_IIR3_0_SHIFT, 0x0 },
{ AUD_DEEMPH0_SRC_SEL, 0x11 },
{ AUD_DEEMPH0_SHIFT, 0x0 },
{ AUD_DEEMPH0_G0, 0x7000 },
{ AUD_DEEMPH0_A0, 0x0 },
{ AUD_DEEMPH0_B0, 0x0 },
{ AUD_DEEMPH0_A1, 0x0 },
{ AUD_DEEMPH0_B1, 0x0 },
{ AUD_DEEMPH1_SRC_SEL, 0x11 },
{ AUD_DEEMPH1_SHIFT, 0x0 },
{ AUD_DEEMPH1_G0, 0x7000 },
{ AUD_DEEMPH1_A0, 0x0 },
{ AUD_DEEMPH1_B0, 0x0 },
{ AUD_DEEMPH1_A1, 0x0 },
{ AUD_DEEMPH1_B1, 0x0 },
{ AUD_OUT0_SEL, 0x3F },
{ AUD_OUT1_SEL, 0x3F },
{ AUD_DMD_RA_DDS, 0x0F5C285 },
{ AUD_PLL_INT, 0x1E },
{ AUD_PLL_DDS, 0x0 },
{ AUD_PLL_FRAC, 0x0E542 },
// setup QAM registers
{ AUD_RATE_ADJ1, 0x00000100 },
{ AUD_RATE_ADJ2, 0x00000200 },
{ AUD_RATE_ADJ3, 0x00000300 },
{ AUD_RATE_ADJ4, 0x00000400 },
{ AUD_RATE_ADJ5, 0x00000500 },
{ AUD_RATE_THRES_DMD, 0x000000C0 },
{ /* end of list */ },
};
static const struct rlist nicam_l[] = {
// setup QAM registers
{ AUD_PDF_DDS_CNST_BYTE2, 0x48 },
{ AUD_PDF_DDS_CNST_BYTE1, 0x3d },
{ AUD_PDF_DDS_CNST_BYTE0, 0xf5 },
{ AUD_QAM_MODE, 0x00 },
{ AUD_PHACC_FREQ_8MSB, 0x3a },
{ AUD_PHACC_FREQ_8LSB, 0x4a },
{ AUD_POLY0_DDS_CONSTANT, 0x000e4db2 },
{ AUD_IIR1_0_SEL, 0x00000000 },
{ AUD_IIR1_1_SEL, 0x00000002 },
{ AUD_IIR1_2_SEL, 0x00000023 },
{ AUD_IIR1_3_SEL, 0x00000004 },
{ AUD_IIR1_4_SEL, 0x00000005 },
{ AUD_IIR1_5_SEL, 0x00000007 },
{ AUD_IIR1_0_SHIFT, 0x00000007 },
{ AUD_IIR1_1_SHIFT, 0x00000000 },
{ AUD_IIR1_2_SHIFT, 0x00000000 },
{ AUD_IIR1_3_SHIFT, 0x00000007 },
{ AUD_IIR1_4_SHIFT, 0x00000007 },
{ AUD_IIR1_5_SHIFT, 0x00000007 },
{ AUD_IIR2_0_SEL, 0x00000002 },
{ AUD_IIR2_1_SEL, 0x00000003 },
{ AUD_IIR2_2_SEL, 0x00000004 },
{ AUD_IIR2_3_SEL, 0x00000005 },
{ AUD_IIR3_0_SEL, 0x00000007 },
{ AUD_IIR3_1_SEL, 0x00000023 },
{ AUD_IIR3_2_SEL, 0x00000016 },
{ AUD_IIR4_0_SHIFT, 0x00000000 },
{ AUD_IIR4_1_SHIFT, 0x00000000 },
{ AUD_IIR3_2_SHIFT, 0x00000002 },
{ AUD_IIR4_0_SEL, 0x0000001d },
{ AUD_IIR4_1_SEL, 0x00000019 },
{ AUD_IIR4_2_SEL, 0x00000008 },
{ AUD_IIR4_0_SHIFT, 0x00000000 },
{ AUD_IIR4_1_SHIFT, 0x00000007 },
{ AUD_IIR4_2_SHIFT, 0x00000007 },
{ AUD_IIR4_0_CA0, 0x0003e57e },
{ AUD_IIR4_0_CA1, 0x00005e11 },
{ AUD_IIR4_0_CA2, 0x0003a7cf },
{ AUD_IIR4_0_CB0, 0x00002368 },
{ AUD_IIR4_0_CB1, 0x0003bf1b },
{ AUD_IIR4_1_CA0, 0x00006349 },
{ AUD_IIR4_1_CA1, 0x00006f27 },
{ AUD_IIR4_1_CA2, 0x0000e7a3 },
{ AUD_IIR4_1_CB0, 0x00005653 },
{ AUD_IIR4_1_CB1, 0x0000cf97 },
{ AUD_IIR4_2_CA0, 0x00006349 },
{ AUD_IIR4_2_CA1, 0x00006f27 },
{ AUD_IIR4_2_CA2, 0x0000e7a3 },
{ AUD_IIR4_2_CB0, 0x00005653 },
{ AUD_IIR4_2_CB1, 0x0000cf97 },
{ AUD_HP_MD_IIR4_1, 0x00000001 },
{ AUD_HP_PROG_IIR4_1, 0x0000001a },
{ AUD_DN0_FREQ, 0x00000000 },
{ AUD_DN1_FREQ, 0x00003318 },
{ AUD_DN1_SRC_SEL, 0x00000017 },
{ AUD_DN1_SHFT, 0x00000007 },
{ AUD_DN1_AFC, 0x00000000 },
{ AUD_DN1_FREQ_SHIFT, 0x00000000 },
{ AUD_DN2_FREQ, 0x00003551 },
{ AUD_DN2_SRC_SEL, 0x00000001 },
{ AUD_DN2_SHFT, 0x00000000 },
{ AUD_DN2_AFC, 0x00000002 },
{ AUD_DN2_FREQ_SHIFT, 0x00000000 },
{ AUD_PDET_SRC, 0x00000014 },
{ AUD_PDET_SHIFT, 0x00000000 },
{ AUD_DEEMPH0_SRC_SEL, 0x00000011 },
{ AUD_DEEMPH1_SRC_SEL, 0x00000011 },
{ AUD_DEEMPH0_SHIFT, 0x00000000 },
{ AUD_DEEMPH1_SHIFT, 0x00000000 },
{ AUD_DEEMPH0_G0, 0x00007000 },
{ AUD_DEEMPH0_A0, 0x00000000 },
{ AUD_DEEMPH0_B0, 0x00000000 },
{ AUD_DEEMPH0_A1, 0x00000000 },
{ AUD_DEEMPH0_B1, 0x00000000 },
{ AUD_DEEMPH1_G0, 0x00007000 },
{ AUD_DEEMPH1_A0, 0x00000000 },
{ AUD_DEEMPH1_B0, 0x00000000 },
{ AUD_DEEMPH1_A1, 0x00000000 },
{ AUD_DEEMPH1_B1, 0x00000000 },
{ AUD_DMD_RA_DDS, 0x00f5c285 },
{ AUD_RATE_ADJ1, 0x00000100 },
{ AUD_RATE_ADJ2, 0x00000200 },
{ AUD_RATE_ADJ3, 0x00000300 },
{ AUD_RATE_ADJ4, 0x00000400 },
{ AUD_RATE_ADJ5, 0x00000500 },
{ AUD_C2_UP_THR, 0x00005400 },
{ AUD_C2_LO_THR, 0x00003000 },
{ AUD_C1_UP_THR, 0x00007000 },
{ AUD_C2_LO_THR, 0x00005400 },
{ AUD_CTL, 0x0000100c },
{ AUD_DCOC_0_SRC, 0x00000021 },
{ AUD_DCOC_1_SRC, 0x00000003 },
{ AUD_DCOC1_SHIFT, 0x00000000 },
{ AUD_DCOC_1_SHIFT_IN0, 0x0000000a },
{ AUD_DCOC_1_SHIFT_IN1, 0x00000008 },
{ AUD_DCOC_PASS_IN, 0x00000000 },
{ AUD_DCOC_2_SRC, 0x0000001b },
{ AUD_IIR4_0_SEL, 0x0000001d },
{ AUD_POLY0_DDS_CONSTANT, 0x000e4db2 },
{ AUD_PHASE_FIX_CTL, 0x00000000 },
{ AUD_CORDIC_SHIFT_1, 0x00000007 },
{ AUD_PLL_EN, 0x00000000 },
{ AUD_PLL_PRESCALE, 0x00000002 },
{ AUD_PLL_INT, 0x0000001e },
{ AUD_OUT1_SHIFT, 0x00000000 },
static const struct rlist nicam_l[] = {
// setup QAM registers
{ AUD_RATE_ADJ1, 0x00000060 },
{ AUD_RATE_ADJ2, 0x000000F9 },
{ AUD_RATE_ADJ3, 0x000001CC },
{ AUD_RATE_ADJ4, 0x000002B3 },
{ AUD_RATE_ADJ5, 0x00000726 },
{ AUD_DEEMPHDENOM1_R, 0x0000F3D0 },
{ AUD_DEEMPHDENOM2_R, 0x00000000 },
{ AUD_ERRLOGPERIOD_R, 0x00000064 },
{ AUD_ERRINTRPTTHSHLD1_R, 0x00000FFF },
{ AUD_ERRINTRPTTHSHLD2_R, 0x0000001F },
{ AUD_ERRINTRPTTHSHLD3_R, 0x0000000F },
{ AUD_POLYPH80SCALEFAC, 0x00000003 },
{ AUD_DMD_RA_DDS, 0x00C00000 },
{ AUD_PLL_INT, 0x0000001E },
{ AUD_PLL_DDS, 0x00000000 },
{ AUD_PLL_FRAC, 0x0000E542 },
{ AUD_START_TIMER, 0x00000000 },
{ AUD_DEEMPHNUMER1_R, 0x000353DE },
{ AUD_DEEMPHNUMER2_R, 0x000001B1 },
{ AUD_PDF_DDS_CNST_BYTE2, 0x06 },
{ AUD_PDF_DDS_CNST_BYTE1, 0x82 },
{ AUD_QAM_MODE, 0x05 },
{ AUD_PDF_DDS_CNST_BYTE0, 0x12 },
{ AUD_PHACC_FREQ_8MSB, 0x34 },
{ AUD_PHACC_FREQ_8LSB, 0x4C },
{ AUD_DEEMPHGAIN_R, 0x00006680 },
{ AUD_RATE_THRES_DMD, 0x000000C0 },
{ /* end of list */ },
} ;
dprintk("%s (status: devel), stereo : %d\n",__FUNCTION__,stereo);
if (!stereo) {
/* AM mono sound */
set_audio_start(core, 0x0004,
0x100c /* FIXME again */);
set_audio_registers(core, nicam_l_mono);
} else {
set_audio_start(core, 0x0010,
0x1924 /* FIXME again */);
set_audio_registers(core, nicam_l);
}
set_audio_finish(core);
{ /* end of list */ },
};
}
dprintk("%s (status: unknown)\n",__FUNCTION__);
set_audio_start(core, 0x0004,
0 /* FIXME */);
set_audio_registers(core, nicam_l);
static void set_audio_standard_PAL_I(struct cx88_core *core, int stereo)
{
static const struct rlist pal_i_fm_mono[] = {
{AUD_ERRLOGPERIOD_R, 0x00000064},
{AUD_ERRINTRPTTHSHLD1_R, 0x00000fff},
{AUD_ERRINTRPTTHSHLD2_R, 0x0000001f},
{AUD_ERRINTRPTTHSHLD3_R, 0x0000000f},
{AUD_PDF_DDS_CNST_BYTE2, 0x06},
{AUD_PDF_DDS_CNST_BYTE1, 0x82},
{AUD_PDF_DDS_CNST_BYTE0, 0x12},
{AUD_QAM_MODE, 0x05},
{AUD_PHACC_FREQ_8MSB, 0x3a},
{AUD_PHACC_FREQ_8LSB, 0x93},
{AUD_DMD_RA_DDS, 0x002a4f2f},
{AUD_PLL_INT, 0x0000001e},
{AUD_PLL_DDS, 0x00000004},
{AUD_PLL_FRAC, 0x0000e542},
{AUD_RATE_ADJ1, 0x00000100},
{AUD_RATE_ADJ2, 0x00000200},
{AUD_RATE_ADJ3, 0x00000300},
{AUD_RATE_ADJ4, 0x00000400},
{AUD_RATE_ADJ5, 0x00000500},
{AUD_THR_FR, 0x00000000},
{AUD_PILOT_BQD_1_K0, 0x0000755b},
{AUD_PILOT_BQD_1_K1, 0x00551340},
{AUD_PILOT_BQD_1_K2, 0x006d30be},
{AUD_PILOT_BQD_1_K3, 0xffd394af},
{AUD_PILOT_BQD_1_K4, 0x00400000},
{AUD_PILOT_BQD_2_K0, 0x00040000},
{AUD_PILOT_BQD_2_K1, 0x002a4841},
{AUD_PILOT_BQD_2_K2, 0x00400000},
{AUD_PILOT_BQD_2_K3, 0x00000000},
{AUD_PILOT_BQD_2_K4, 0x00000000},
{AUD_MODE_CHG_TIMER, 0x00000060},
{AUD_AFE_12DB_EN, 0x00000001},
{AAGC_HYST, 0x0000000a},
{AUD_CORDIC_SHIFT_0, 0x00000007},
{AUD_CORDIC_SHIFT_1, 0x00000007},
{AUD_C1_UP_THR, 0x00007000},
{AUD_C1_LO_THR, 0x00005400},
{AUD_C2_UP_THR, 0x00005400},
{AUD_C2_LO_THR, 0x00003000},
{AUD_DCOC_0_SRC, 0x0000001a},
{AUD_DCOC0_SHIFT, 0x00000000},
{AUD_DCOC_0_SHIFT_IN0, 0x0000000a},
{AUD_DCOC_0_SHIFT_IN1, 0x00000008},
{AUD_DCOC_PASS_IN, 0x00000003},
{AUD_IIR3_0_SEL, 0x00000021},
{AUD_DN2_AFC, 0x00000002},
{AUD_DCOC_1_SRC, 0x0000001b},
{AUD_DCOC1_SHIFT, 0x00000000},
{AUD_DCOC_1_SHIFT_IN0, 0x0000000a},
{AUD_DCOC_1_SHIFT_IN1, 0x00000008},
{AUD_IIR3_1_SEL, 0x00000023},
{AUD_DN0_FREQ, 0x000035a3},
{AUD_DN2_FREQ, 0x000029c7},
{AUD_CRDC0_SRC_SEL, 0x00000511},
{AUD_IIR1_0_SEL, 0x00000001},
{AUD_IIR1_1_SEL, 0x00000000},
{AUD_IIR3_2_SEL, 0x00000003},
{AUD_IIR3_2_SHIFT, 0x00000000},
{AUD_IIR3_0_SEL, 0x00000002},
{AUD_IIR2_0_SEL, 0x00000021},
{AUD_IIR2_0_SHIFT, 0x00000002},
{AUD_DEEMPH0_SRC_SEL, 0x0000000b},
{AUD_DEEMPH1_SRC_SEL, 0x0000000b},
{AUD_POLYPH80SCALEFAC, 0x00000001},
{AUD_START_TIMER, 0x00000000},
{ /* end of list */ },
};
static const struct rlist pal_i_nicam[] = {
{ AUD_RATE_ADJ1, 0x00000010 },
{ AUD_RATE_ADJ2, 0x00000040 },
{ AUD_RATE_ADJ3, 0x00000100 },
{ AUD_RATE_ADJ4, 0x00000400 },
{ AUD_RATE_ADJ5, 0x00001000 },
// { AUD_DMD_RA_DDS, 0x00c0d5ce },
{ AUD_DEEMPHGAIN_R, 0x000023c2 },
{ AUD_DEEMPHNUMER1_R, 0x0002a7bc },
{ AUD_DEEMPHNUMER2_R, 0x0003023e },
{ AUD_DEEMPHDENOM1_R, 0x0000f3d0 },
{ AUD_DEEMPHDENOM2_R, 0x00000000 },
{ AUD_DEEMPHDENOM2_R, 0x00000000 },
{ AUD_ERRLOGPERIOD_R, 0x00000fff },
{ AUD_ERRINTRPTTHSHLD1_R, 0x000003ff },
{ AUD_ERRINTRPTTHSHLD2_R, 0x000000ff },
{ AUD_ERRINTRPTTHSHLD3_R, 0x0000003f },
{ AUD_POLYPH80SCALEFAC, 0x00000003 },
{ AUD_PDF_DDS_CNST_BYTE2, 0x06 },
{ AUD_PDF_DDS_CNST_BYTE1, 0x82 },
{ AUD_PDF_DDS_CNST_BYTE0, 0x16 },
{ AUD_QAM_MODE, 0x05 },
{ AUD_PDF_DDS_CNST_BYTE0, 0x12 },
{ AUD_PHACC_FREQ_8MSB, 0x3a },
{ AUD_PHACC_FREQ_8LSB, 0x93 },
{ /* end of list */ },
};
dprintk("%s (status: devel), stereo : %d\n",__FUNCTION__,stereo);
if (!stereo) {
// FM mono
set_audio_start(core, 0x0004, EN_DMTRX_SUMDIFF | EN_A2_FORCE_MONO1);
set_audio_registers(core, pal_i_fm_mono);
} else {
// Nicam Stereo
set_audio_start(core, 0x0010, EN_DMTRX_LR | EN_DMTRX_BYPASS | EN_NICAM_AUTO_STEREO);
set_audio_registers(core, pal_i_nicam);
}
set_audio_finish(core);
}
......@@ -553,13 +677,6 @@ static void set_audio_standard_A2(struct cx88_core *core)
set_audio_start(core, 0x0004, EN_DMTRX_SUMDIFF | EN_A2_AUTO_STEREO);
set_audio_registers(core, a2_common);
switch (core->tvaudio) {
case WW_NICAM_I:
/* gives at least mono according to the dscaler guys */
/* so use use that while nicam is broken ... */
dprintk("%s PAL-I mono (status: unknown)\n",__FUNCTION__);
set_audio_registers(core, a2_table1);
cx_write(AUD_CTL, EN_A2_FORCE_MONO1);
break;
case WW_A2_BG:
dprintk("%s PAL-BG A2 (status: known-good)\n",__FUNCTION__);
set_audio_registers(core, a2_table1);
......@@ -646,11 +763,12 @@ void cx88_set_tvaudio(struct cx88_core *core)
case WW_BTSC:
set_audio_standard_BTSC(core,0);
break;
// case WW_NICAM_I:
case WW_NICAM_BGDKL:
set_audio_standard_NICAM(core);
set_audio_standard_NICAM_L(core,0);
break;
case WW_NICAM_I:
set_audio_standard_PAL_I(core,0);
break;
case WW_A2_BG:
case WW_A2_DK:
case WW_A2_M:
......@@ -663,7 +781,7 @@ void cx88_set_tvaudio(struct cx88_core *core)
set_audio_standard_FM(core);
break;
case WW_SYSTEM_L_AM:
set_audio_standard_NICAM_L(core);
set_audio_standard_NICAM_L(core, 1);
break;
case WW_NONE:
default:
......@@ -674,6 +792,19 @@ void cx88_set_tvaudio(struct cx88_core *core)
return;
}
void cx88_newstation(struct cx88_core *core)
{
core->audiomode_manual = UNSET;
switch (core->tvaudio) {
case WW_SYSTEM_L_AM:
/* try nicam ... */
core->audiomode_current = V4L2_TUNER_MODE_STEREO;
set_audio_standard_NICAM_L(core, 1);
break;
}
}
void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t)
{
static char *m[] = {"stereo", "dual mono", "mono", "sap"};
......@@ -721,22 +852,37 @@ void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t)
}
break;
case WW_NICAM_BGDKL:
if (0 == mode)
if (0 == mode) {
t->audmode = V4L2_TUNER_MODE_STEREO;
t->rxsubchans |= V4L2_TUNER_SUB_STEREO;
}
break;
case WW_SYSTEM_L_AM:
if (0x0 == mode && !(cx_read(AUD_INIT) & 0x04)) {
t->audmode = V4L2_TUNER_MODE_STEREO;
t->rxsubchans |= V4L2_TUNER_SUB_STEREO;
}
break ;
default:
t->rxsubchans = V4L2_TUNER_SUB_MONO;
t->audmode = V4L2_TUNER_MODE_MONO;
/* nothing */
break;
}
return;
}
void cx88_set_stereo(struct cx88_core *core, u32 mode)
void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual)
{
u32 ctl = UNSET;
u32 mask = UNSET;
if (manual) {
core->audiomode_manual = mode;
} else {
if (UNSET != core->audiomode_manual)
return;
}
core->audiomode_current = mode;
switch (core->tvaudio) {
case WW_BTSC:
switch (mode) {
......@@ -789,6 +935,28 @@ void cx88_set_stereo(struct cx88_core *core, u32 mode)
break;
}
break;
case WW_SYSTEM_L_AM:
switch (mode) {
case V4L2_TUNER_MODE_MONO:
case V4L2_TUNER_MODE_LANG1: /* FIXME */
set_audio_standard_NICAM_L(core, 0);
break;
case V4L2_TUNER_MODE_STEREO:
set_audio_standard_NICAM_L(core, 1);
break;
}
break;
case WW_NICAM_I:
switch (mode) {
case V4L2_TUNER_MODE_MONO:
case V4L2_TUNER_MODE_LANG1:
set_audio_standard_PAL_I(core, 0);
break;
case V4L2_TUNER_MODE_STEREO:
set_audio_standard_PAL_I(core, 1);
break;
}
break;
case WW_FM:
switch (mode) {
case V4L2_TUNER_MODE_MONO:
......@@ -804,13 +972,11 @@ void cx88_set_stereo(struct cx88_core *core, u32 mode)
}
if (UNSET != ctl) {
cx_write(AUD_SOFT_RESET, 0x0001);
cx_andor(AUD_CTL, mask, ctl);
cx_write(AUD_SOFT_RESET, 0x0000);
dprintk("cx88_set_stereo: mask 0x%x, ctl 0x%x "
"[status=0x%x,ctl=0x%x,vol=0x%x]\n",
mask, ctl, cx_read(AUD_STATUS),
cx_read(AUD_CTL), cx_sread(SHADOW_AUD_VOL_CTL));
cx_andor(AUD_CTL, mask, ctl);
}
return;
}
......@@ -819,16 +985,32 @@ int cx88_audio_thread(void *data)
{
struct cx88_core *core = data;
struct v4l2_tuner t;
u32 mode = 0;
dprintk("cx88: tvaudio thread started\n");
for (;;) {
msleep_interruptible(1000);
if (kthread_should_stop())
break;
/* just monitor the audio status for now ... */
memset(&t,0,sizeof(t));
cx88_get_stereo(core,&t);
msleep_interruptible(1000);
if (UNSET != core->audiomode_manual)
/* manually set, don't do anything. */
continue;
/* monitor signal */
if (t.rxsubchans & V4L2_TUNER_SUB_STEREO)
mode = V4L2_TUNER_MODE_STEREO;
else
mode = V4L2_TUNER_MODE_MONO;
if (mode == core->audiomode_current)
continue;
/* automatically switch to best available mode */
cx88_set_stereo(core, mode, 0);
}
dprintk("cx88: tvaudio thread exiting\n");
......@@ -838,6 +1020,7 @@ int cx88_audio_thread(void *data)
/* ----------------------------------------------------------- */
EXPORT_SYMBOL(cx88_set_tvaudio);
EXPORT_SYMBOL(cx88_newstation);
EXPORT_SYMBOL(cx88_set_stereo);
EXPORT_SYMBOL(cx88_get_stereo);
EXPORT_SYMBOL(cx88_audio_thread);
......
/*
* $Id: cx88-vbi.c,v 1.14 2004/11/07 13:17:15 kraxel Exp $
* $Id: cx88-vbi.c,v 1.16 2004/12/10 12:33:39 kraxel Exp $
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/slab.h>
......@@ -64,7 +65,7 @@ int cx8800_start_vbi_dma(struct cx8800_dev *dev,
q->count = 1;
/* enable irqs */
cx_set(MO_PCI_INTMSK, 0x00fc01);
cx_set(MO_PCI_INTMSK, core->pci_irqmask | 0x01);
cx_set(MO_VID_INTMSK, 0x0f0088);
/* enable capture */
......
/*
* $Id: cx88-video.c,v 1.46 2004/11/07 14:44:59 kraxel Exp $
* $Id: cx88-video.c,v 1.58 2005/03/07 15:58:05 kraxel Exp $
*
* device driver for Conexant 2388x based TV cards
* video4linux video interface
......@@ -24,6 +24,7 @@
#include <linux/init.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kmod.h>
#include <linux/kernel.h>
#include <linux/slab.h>
......@@ -428,7 +429,7 @@ static int start_video_dma(struct cx8800_dev *dev,
q->count = 1;
/* enable irqs */
cx_set(MO_PCI_INTMSK, 0x00fc01);
cx_set(MO_PCI_INTMSK, core->pci_irqmask | 0x01);
cx_set(MO_VID_INTMSK, 0x0f0011);
/* enable capture */
......@@ -994,7 +995,7 @@ static int video_open(struct inode *inode, struct file *file)
cx_write(MO_GP3_IO, cx88_boards[board].radio.gpio3);
dev->core->tvaudio = WW_FM;
cx88_set_tvaudio(core);
cx88_set_stereo(core,V4L2_TUNER_MODE_STEREO);
cx88_set_stereo(core,V4L2_TUNER_MODE_STEREO,1);
cx88_call_i2c_clients(dev->core,AUDC_SET_RADIO,NULL);
}
......@@ -1002,7 +1003,7 @@ static int video_open(struct inode *inode, struct file *file)
}
static ssize_t
video_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
video_read(struct file *file, char *data, size_t count, loff_t *ppos)
{
struct cx8800_fh *fh = file->private_data;
......@@ -1083,6 +1084,8 @@ static int video_release(struct inode *inode, struct file *file)
res_free(dev,fh,RESOURCE_VBI);
}
videobuf_mmap_free(&fh->vidq);
videobuf_mmap_free(&fh->vbiq);
file->private_data = NULL;
kfree(fh);
return 0;
......@@ -1338,7 +1341,6 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
0;
if (UNSET != core->tuner_type)
cap->capabilities |= V4L2_CAP_TUNER;
return 0;
}
......@@ -1429,6 +1431,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
if (*i >= 4)
return -EINVAL;
down(&dev->lock);
cx88_newstation(core);
video_mux(dev,*i);
up(&dev->lock);
return 0;
......@@ -1560,7 +1563,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
return -EINVAL;
if (0 != t->index)
return -EINVAL;
cx88_set_stereo(core, t->audmode);
cx88_set_stereo(core, t->audmode, 1);
return 0;
}
case VIDIOC_G_FREQUENCY:
......@@ -1590,6 +1593,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
return -EINVAL;
down(&dev->lock);
dev->freq = f->frequency;
cx88_newstation(core);
#ifdef V4L2_I2C_CLIENTS
cx88_call_i2c_clients(dev->core,VIDIOC_S_FREQUENCY,f);
#else
......@@ -1880,19 +1884,18 @@ static irqreturn_t cx8800_irq(int irq, void *dev_id, struct pt_regs *regs)
{
struct cx8800_dev *dev = dev_id;
struct cx88_core *core = dev->core;
u32 status, mask;
u32 status;
int loop, handled = 0;
for (loop = 0; loop < 10; loop++) {
status = cx_read(MO_PCI_INTSTAT) & (~0x1f | 0x01);
mask = cx_read(MO_PCI_INTMSK);
if (0 == (status & mask))
status = cx_read(MO_PCI_INTSTAT) & (core->pci_irqmask | 0x01);
if (0 == status)
goto out;
cx_write(MO_PCI_INTSTAT, status);
handled = 1;
if (status & mask & ~0x1f)
cx88_irq(core,status,mask);
if (status & core->pci_irqmask)
cx88_core_irq(core,status);
if (status & 0x01)
cx8800_vid_irq(dev);
};
......@@ -2055,6 +2058,7 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev,
core->name,pci_dev->irq);
goto fail_core;
}
cx_set(MO_PCI_INTMSK, core->pci_irqmask);
/* load and configure helper modules */
if (TUNER_ABSENT != core->tuner_type)
......@@ -2156,7 +2160,7 @@ static void __devexit cx8800_finidev(struct pci_dev *pci_dev)
kfree(dev);
}
static int cx8800_suspend(struct pci_dev *pci_dev, u32 state)
static int cx8800_suspend(struct pci_dev *pci_dev, pm_message_t state)
{
struct cx8800_dev *dev = pci_get_drvdata(pci_dev);
struct cx88_core *core = dev->core;
......@@ -2181,7 +2185,7 @@ static int cx8800_suspend(struct pci_dev *pci_dev, u32 state)
#endif
pci_save_state(pci_dev);
if (0 != pci_set_power_state(pci_dev, state)) {
if (0 != pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state))) {
pci_disable_device(pci_dev);
dev->state.disabled = 1;
}
......@@ -2197,7 +2201,7 @@ static int cx8800_resume(struct pci_dev *pci_dev)
pci_enable_device(pci_dev);
dev->state.disabled = 0;
}
pci_set_power_state(pci_dev, 0);
pci_set_power_state(pci_dev, PCI_D0);
pci_restore_state(pci_dev);
#if 1
......
/*
* $Id: cx88.h,v 1.40 2004/11/03 09:04:51 kraxel Exp $
* $Id: cx88.h,v 1.56 2005/03/04 09:12:23 kraxel Exp $
*
* v4l2 device driver for cx2388x based TV cards
*
......@@ -27,6 +27,7 @@
#include <linux/kdev_t.h>
#include <media/tuner.h>
#include <media/tveeprom.h>
#include <media/audiochip.h>
#include <media/video-buf.h>
#include <media/video-buf-dvb.h>
......@@ -139,7 +140,7 @@ extern struct sram_channel cx88_sram_channels[];
#define CX88_BOARD_GDI 2
#define CX88_BOARD_PIXELVIEW 3
#define CX88_BOARD_ATI_WONDER_PRO 4
#define CX88_BOARD_WINFAST2000XP 5
#define CX88_BOARD_WINFAST2000XP_EXPERT 5
#define CX88_BOARD_AVERTV_303 6
#define CX88_BOARD_MSI_TVANYWHERE_MASTER 7
#define CX88_BOARD_WINFAST_DV2000 8
......@@ -156,6 +157,11 @@ extern struct sram_channel cx88_sram_channels[];
#define CX88_BOARD_CONEXANT_DVB_T1 19
#define CX88_BOARD_PROVIDEO_PV259 20
#define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS 21
#define CX88_BOARD_PCHDTV_HD3000 22
#define CX88_BOARD_DNTV_LIVE_DVB_T 23
#define CX88_BOARD_HAUPPAUGE_ROSLYN 24
#define CX88_BOARD_DIGITALLOGIC_MEC 25
#define CX88_BOARD_IODATA_GVBCTV7E 26
enum cx88_itype {
CX88_VMUX_COMPOSITE1 = 1,
......@@ -238,6 +244,7 @@ struct cx88_core {
u32 __iomem *lmmio;
u8 __iomem *bmmio;
u32 shadow[SHADOW_MAX];
int pci_irqmask;
/* i2c i/o */
struct i2c_adapter i2c_adap;
......@@ -252,16 +259,20 @@ struct cx88_core {
unsigned int has_radio;
/* config info -- dvb */
unsigned int pll_type;
struct dvb_pll_desc *pll_desc;
unsigned int pll_addr;
unsigned int demod_addr;
/* state info */
struct task_struct *kthread;
struct cx88_tvnorm *tvnorm;
u32 tvaudio;
u32 audiomode_manual;
u32 audiomode_current;
u32 input;
u32 astat;
/* IR remote control state */
struct cx88_IR *ir;
};
struct cx8800_dev;
......@@ -371,11 +382,16 @@ struct cx8802_dev {
struct list_head devlist;
struct video_device *mpeg_dev;
u32 mailbox;
int width;
int height;
/* for dvb only */
struct videobuf_dvb dvb;
void* fe_handle;
int (*fe_release)(void *handle);
/* for switching modulation types */
unsigned char ts_gen_cntrl;
};
/* ----------------------------------------------------------- */
......@@ -411,7 +427,7 @@ extern void cx88_print_irqbits(char *name, char *tag, char **strings,
u32 bits, u32 mask);
extern void cx88_print_ioctl(char *name, unsigned int cmd);
extern void cx88_irq(struct cx88_core *core, u32 status, u32 mask);
extern int cx88_core_irq(struct cx88_core *core, u32 status);
extern void cx88_wakeup(struct cx88_core *core,
struct cx88_dmaqueue *q, u32 count);
extern void cx88_shutdown(struct cx88_core *core);
......@@ -503,10 +519,18 @@ extern void cx88_card_setup(struct cx88_core *core);
#define WW_FM 12
void cx88_set_tvaudio(struct cx88_core *core);
void cx88_newstation(struct cx88_core *core);
void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t);
void cx88_set_stereo(struct cx88_core *core, u32 mode);
void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual);
int cx88_audio_thread(void *data);
/* ----------------------------------------------------------- */
/* cx88-input.c */
int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci);
int cx88_ir_fini(struct cx88_core *core);
void cx88_ir_irq(struct cx88_core *core);
/* ----------------------------------------------------------- */
/* cx88-mpeg.c */
......@@ -517,7 +541,7 @@ void cx8802_cancel_buffers(struct cx8802_dev *dev);
int cx8802_init_common(struct cx8802_dev *dev);
void cx8802_fini_common(struct cx8802_dev *dev);
int cx8802_suspend_common(struct pci_dev *pci_dev, u32 state);
int cx8802_suspend_common(struct pci_dev *pci_dev, pm_message_t state);
int cx8802_resume_common(struct pci_dev *pci_dev);
/*
......
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