Commit 6cd80eb7 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] cx88 update.

From: Gerd Knorr <kraxel@bytesex.org>

This is a update for the cx88 driver.  There are *lots* of changes:

  * vbi support was added.
  * plenty of fixes for audio support (there are still problems
    through).
  * new cards added.
  * serveral minor tweaks.
parent d4953f47
cx88xx-objs := cx88-cards.o cx88-core.o
cx8800-objs := cx88-video.o cx88-tvaudio.o cx88-i2c.o
cx8800-objs := cx88-video.o cx88-tvaudio.o cx88-i2c.o cx88-vbi.o
obj-$(CONFIG_VIDEO_CX88) += cx88xx.o cx8800.o
......
......@@ -52,16 +52,19 @@ struct cx88_board cx88_boards[] = {
.input = {{
.type = CX88_VMUX_TELEVISION,
.vmux = 0,
//.gpio0 = 0xff03,
.gpio0 = 0xff01,
.gpio0 = 0xff00, // internal decoder
},{
.type = CX88_VMUX_DEBUG,
.vmux = 0,
.gpio0 = 0xff00,
.gpio0 = 0xff01, // mono from tuner chip
},{
.type = CX88_VMUX_COMPOSITE1,
.vmux = 1,
.gpio0 = 0xff02,
},{
.type = CX88_VMUX_SVIDEO,
.vmux = 2,
.gpio0 = 0xff02,
}},
.radio = {
.type = CX88_RADIO,
......@@ -92,21 +95,50 @@ struct cx88_board cx88_boards[] = {
},
[CX88_BOARD_ATI_WONDER_PRO] = {
.name = "ATI TV Wonder Pro",
.tuner_type = UNSET,
.tuner_type = 44,
.input = {{
.type = CX88_VMUX_TELEVISION,
.vmux = 0,
},{
.type = CX88_VMUX_COMPOSITE1,
.vmux = 1,
},{
.type = CX88_VMUX_SVIDEO,
.vmux = 2,
}},
},
[CX88_BOARD_WINFAST2000XP] = {
.name = "Leadtek Winfast 2000XP Expert",
.tuner_type = 38,
.tuner_type = 44,
.input = {{
.type = CX88_VMUX_TELEVISION,
.vmux = 0,
.gpio0 = 0x00F5e700,
.gpio1 = 0x00003004,
.gpio2 = 0x00F5e700,
.gpio3 = 0x02000000,
},{
.type = CX88_VMUX_COMPOSITE1,
.vmux = 1,
.gpio0 = 0x00F5c700,
.gpio1 = 0x00003004,
.gpio2 = 0x00F5c700,
.gpio3 = 0x02000000,
},{
.type = CX88_VMUX_SVIDEO,
.vmux = 2,
.gpio0 = 0x00F5c700,
.gpio1 = 0x00003004,
.gpio2 = 0x00F5c700,
.gpio3 = 0x02000000,
}},
.radio = {
.type = CX88_RADIO,
.gpio0 = 0x00F5d700,
.gpio1 = 0x00003004,
.gpio2 = 0x00F5d700,
.gpio3 = 0x02000000,
},
},
[CX88_BOARD_AVERTV_303] = {
......@@ -126,6 +158,10 @@ struct cx88_board cx88_boards[] = {
},{
.type = CX88_VMUX_COMPOSITE1,
.vmux = 1,
},{
// temporarly for testing ...
.type = CX88_VMUX_COMPOSITE2,
.vmux = 2,
},{
.type = CX88_VMUX_SVIDEO,
.vmux = 2,
......@@ -137,15 +173,34 @@ struct cx88_board cx88_boards[] = {
[CX88_BOARD_WINFAST_DV2000] = {
.name = "Leadtek Winfast DV2000",
.tuner_type = 38,
.needs_tda9887 = 1,
.input = {{
.type = CX88_VMUX_TELEVISION,
.vmux = 0,
}},
.radio = {
.type = CX88_RADIO,
},
},
[CX88_BOARD_LEADTEK_PVR2000] = {
.name = "Leadtek PVR 2000",
.tuner_type = 38,
.input = {{
.type = CX88_VMUX_TELEVISION,
.vmux = 0,
},{
.type = CX88_VMUX_COMPOSITE1,
.vmux = 1,
},{
.type = CX88_VMUX_SVIDEO,
.vmux = 2,
}},
.radio = {
.type = CX88_RADIO,
},
},
};
const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards);
......@@ -177,10 +232,18 @@ struct cx88_subid cx88_subids[] = {
.subvendor = 0x107d,
.subdevice = 0x6611,
.card = CX88_BOARD_WINFAST2000XP,
},{
.subvendor = 0x107d,
.subdevice = 0x6613, /* NTSC */
.card = CX88_BOARD_WINFAST2000XP,
},{
.subvendor = 0x107d,
.subdevice = 0x6620,
.card = CX88_BOARD_WINFAST_DV2000,
},{
.subvendor = 0x107d,
.subdevice = 0x663C,
.card = CX88_BOARD_LEADTEK_PVR2000,
},{
.subvendor = 0x1461,
.subdevice = 0x000b,
......@@ -193,6 +256,34 @@ struct cx88_subid cx88_subids[] = {
};
const unsigned int cx88_idcount = ARRAY_SIZE(cx88_subids);
/* ----------------------------------------------------------------------- */
/* some leadtek specific stuff */
static void __devinit leadtek_eeprom(struct cx8800_dev *dev, u8 *eeprom_data)
{
/* This is just for the Winfast 2000 XP board ATM; I don't have data on
* any others.
*
* Byte 0 is 1 on the NTSC board.
*/
if (eeprom_data[4] != 0x7d ||
eeprom_data[5] != 0x10 ||
eeprom_data[7] != 0x66) {
printk(KERN_WARNING "%s Leadtek eeprom invalid.\n", dev->name);
return;
}
dev->has_radio = 1;
dev->tuner_type = (eeprom_data[6] == 0x13) ? 43 : 38;
printk(KERN_INFO "%s: Leadtek Winfast 2000 XP config: "
"tuner=%d, eeprom[0]=0x%02x\n",
dev->name, dev->tuner_type, eeprom_data[0]);
}
/* ----------------------------------------------------------------------- */
/* some hauppauge specific stuff */
......@@ -378,6 +469,11 @@ void __devinit cx88_card_setup(struct cx8800_dev *dev)
i2c_eeprom(&dev->i2c_client,eeprom,sizeof(eeprom));
gdi_eeprom(dev,eeprom);
break;
case CX88_BOARD_WINFAST2000XP:
if (0 == dev->i2c_rc)
i2c_eeprom(&dev->i2c_client,eeprom,sizeof(eeprom));
leadtek_eeprom(dev,eeprom);
break;
}
}
......
......@@ -100,15 +100,6 @@ static const char *v4l2_ioctls[] = {
};
#define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
static const char *osspcm_ioctls[] = {
"RESET", "SYNC", "SPEED", "STEREO", "GETBLKSIZE", "SETFMT",
"CHANNELS", "?", "POST", "SUBDIVIDE", "SETFRAGMENT", "GETFMTS",
"GETOSPACE", "GETISPACE", "NONBLOCK", "GETCAPS", "GET/SETTRIGGER",
"GETIPTR", "GETOPTR", "MAPINBUF", "MAPOUTBUF", "SETSYNCRO",
"SETDUPLEX", "GETODELAY"
};
#define OSSPCM_IOCTLS ARRAY_SIZE(v4l2_ioctls)
void cx88_print_ioctl(char *name, unsigned int cmd)
{
char *dir;
......@@ -131,15 +122,6 @@ void cx88_print_ioctl(char *name, unsigned int cmd)
name, cmd, dir, (_IOC_NR(cmd) < V4L2_IOCTLS) ?
v4l2_ioctls[_IOC_NR(cmd)] : "???");
break;
case 'P':
printk(KERN_DEBUG "%s: ioctl 0x%08x (oss dsp, %s, SNDCTL_DSP_%s)\n",
name, cmd, dir, (_IOC_NR(cmd) < OSSPCM_IOCTLS) ?
osspcm_ioctls[_IOC_NR(cmd)] : "???");
break;
case 'M':
printk(KERN_DEBUG "%s: ioctl 0x%08x (oss mixer, %s, #%d)\n",
name, cmd, dir, _IOC_NR(cmd));
break;
default:
printk(KERN_DEBUG "%s: ioctl 0x%08x (???, %s, #%d)\n",
name, cmd, dir, _IOC_NR(cmd));
......@@ -296,6 +278,7 @@ struct sram_channel cx88_sram_channels[] = {
.name = "video y / packed",
.cmds_start = 0x180040,
.ctrl_start = 0x180400,
.cdt = 0x180400 + 64,
.fifo_start = 0x180c00,
.fifo_size = 0x002800,
.ptr1_reg = MO_DMA21_PTR1,
......@@ -307,6 +290,7 @@ struct sram_channel cx88_sram_channels[] = {
.name = "video u",
.cmds_start = 0x180080,
.ctrl_start = 0x1804a0,
.cdt = 0x1804a0 + 64,
.fifo_start = 0x183400,
.fifo_size = 0x000800,
.ptr1_reg = MO_DMA22_PTR1,
......@@ -318,6 +302,7 @@ struct sram_channel cx88_sram_channels[] = {
.name = "video v",
.cmds_start = 0x1800c0,
.ctrl_start = 0x180540,
.cdt = 0x180540 + 64,
.fifo_start = 0x183c00,
.fifo_size = 0x000800,
.ptr1_reg = MO_DMA23_PTR1,
......@@ -329,6 +314,7 @@ struct sram_channel cx88_sram_channels[] = {
.name = "vbi",
.cmds_start = 0x180100,
.ctrl_start = 0x1805e0,
.cdt = 0x1805e0 + 64,
.fifo_start = 0x184400,
.fifo_size = 0x001000,
.ptr1_reg = MO_DMA24_PTR1,
......@@ -340,6 +326,7 @@ struct sram_channel cx88_sram_channels[] = {
.name = "audio from",
.cmds_start = 0x180140,
.ctrl_start = 0x180680,
.cdt = 0x180680 + 64,
.fifo_start = 0x185400,
.fifo_size = 0x000200,
.ptr1_reg = MO_DMA25_PTR1,
......@@ -351,8 +338,9 @@ struct sram_channel cx88_sram_channels[] = {
.name = "audio to",
.cmds_start = 0x180180,
.ctrl_start = 0x180720,
.fifo_start = 0x185600,
.fifo_size = 0x000200,
.cdt = 0x180680 + 64, /* same as audio IN */
.fifo_start = 0x185400, /* same as audio IN */
.fifo_size = 0x000200, /* same as audio IN */
.ptr1_reg = MO_DMA26_PTR1,
.ptr2_reg = MO_DMA26_PTR2,
.cnt1_reg = MO_DMA26_CNT1,
......@@ -368,7 +356,7 @@ int cx88_sram_channel_setup(struct cx8800_dev *dev,
u32 cdt;
bpl = (bpl + 7) & ~7; /* alignment */
cdt = ch->ctrl_start + 64;
cdt = ch->cdt;
lines = ch->fifo_size / bpl;
if (lines > 6)
lines = 6;
......@@ -429,13 +417,13 @@ int cx88_risc_decode(u32 risc)
};
int i;
printk("0x%08x [ %s", risc, instr[risc >> 28] ?
instr[risc >> 28] : "INVALID");
printk("0x%08x [ %s", risc,
instr[risc >> 28] ? instr[risc >> 28] : "INVALID");
for (i = ARRAY_SIZE(bits)-1; i >= 0; i--)
if (risc & (1 << (i + 12)))
printk(" %s",bits[i]);
printk(" count=%d ]\n", risc & 0xfff);
return incr[risc >> 28] ? 1 : incr[risc >> 28];
return incr[risc >> 28] ? incr[risc >> 28] : 1;
}
void cx88_risc_disasm(struct cx8800_dev *dev,
......
......@@ -152,7 +152,7 @@ int __devinit cx8800_i2c_init(struct cx8800_dev *dev)
sizeof(dev->i2c_client));
dev->i2c_adap.dev.parent = &dev->pci->dev;
strcpy(dev->i2c_adap.name,dev->name);
strlcpy(dev->i2c_adap.name,dev->name,sizeof(dev->i2c_adap.name));
dev->i2c_algo.data = dev;
i2c_set_adapdata(&dev->i2c_adap,dev);
dev->i2c_adap.algo_data = &dev->i2c_algo;
......@@ -162,6 +162,8 @@ int __devinit cx8800_i2c_init(struct cx8800_dev *dev)
cx8800_bit_setsda(dev,1);
dev->i2c_rc = i2c_bit_add_bus(&dev->i2c_adap);
printk("%s: i2c register %s\n", dev->name,
(0 == dev->i2c_rc) ? "ok" : "FAILED");
return dev->i2c_rc;
}
......
......@@ -146,6 +146,8 @@
#define MO_INPUT_FORMAT 0x310104
#define MO_AGC_BURST 0x31010c
#define MO_CONTR_BRIGHT 0x310110
#define MO_UV_SATURATION 0x310114
#define MO_HUE 0x310118
#define MO_HTOTAL 0x310120
#define MO_HDELAY_EVEN 0x310124
#define MO_HDELAY_ODD 0x310128
......@@ -175,6 +177,7 @@
#define MO_VBI_PACKET 0x310188 // vbi packet size / delay
#define MO_FIELD_COUNT 0x310190 // field counter
#define MO_VIP_CONFIG 0x310194
#define MO_VBOS_CONTROL 0x3101a8
#define MO_AGC_BACK_VBI 0x310200
#define MO_AGC_SYNC_TIP1 0x310208
......@@ -406,7 +409,7 @@
#define AUD_PDF_DDS_CNST_BYTE1 0x320d02
#define AUD_PDF_DDS_CNST_BYTE0 0x320d03
#define AUD_PHACC_FREQ_8MSB 0x320d2a
#define AUD_PHACC_FREQ_8LSB 0x320d23
#define AUD_PHACC_FREQ_8LSB 0x320d2b
#define AUD_QAM_MODE 0x320d04
......
This diff is collapsed.
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include "cx88.h"
static unsigned int vbibufs = 4;
MODULE_PARM(vbibufs,"i");
MODULE_PARM_DESC(vbibufs,"number of vbi buffers, range 2-32");
static unsigned int vbi_debug = 0;
MODULE_PARM(vbi_debug,"i");
MODULE_PARM_DESC(vbi_debug,"enable debug messages [video]");
#define dprintk(level,fmt, arg...) if (vbi_debug >= level) \
printk(KERN_DEBUG "%s: " fmt, dev->name , ## arg)
/* ------------------------------------------------------------------ */
void cx8800_vbi_fmt(struct cx8800_dev *dev, struct v4l2_format *f)
{
memset(&f->fmt.vbi,0,sizeof(f->fmt.vbi));
f->fmt.vbi.samples_per_line = VBI_LINE_LENGTH;
f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
f->fmt.vbi.offset = 244;
f->fmt.vbi.count[0] = VBI_LINE_COUNT;
f->fmt.vbi.count[1] = VBI_LINE_COUNT;
switch (dev->tvnorm->id) {
case V4L2_STD_NTSC_M:
case V4L2_STD_NTSC_M_JP:
f->fmt.vbi.sampling_rate = 28636363;
f->fmt.vbi.start[0] = 10 -1;
f->fmt.vbi.start[1] = 273 -1;
break;
case V4L2_STD_PAL_BG:
case V4L2_STD_PAL_DK:
case V4L2_STD_PAL_I:
case V4L2_STD_SECAM:
f->fmt.vbi.sampling_rate = 35468950;
f->fmt.vbi.start[0] = 7 -1;
f->fmt.vbi.start[1] = 319 -1;
}
}
int cx8800_start_vbi_dma(struct cx8800_dev *dev,
struct cx88_dmaqueue *q,
struct cx88_buffer *buf)
{
/* setup fifo + format */
cx88_sram_channel_setup(dev, &cx88_sram_channels[SRAM_CH24],
buf->vb.width, buf->risc.dma);
cx_write(MO_VBOS_CONTROL, ( (1 << 18) | // comb filter delay fixup
(1 << 15) | // enable vbi capture
(1 << 11) ));
/* reset counter */
cx_write(MO_VBI_GPCNTRL,0x3);
q->count = 1;
/* enable irqs */
cx_set(MO_PCI_INTMSK, 0x00fc01);
cx_set(MO_VID_INTMSK, 0x0f0088);
/* enable capture */
cx_set(VID_CAPTURE_CONTROL,0x18);
/* start dma */
cx_set(MO_DEV_CNTRL2, (1<<5));
cx_set(MO_VID_DMACNTRL, 0x88);
return 0;
}
int cx8800_restart_vbi_queue(struct cx8800_dev *dev,
struct cx88_dmaqueue *q)
{
struct cx88_buffer *buf;
struct list_head *item;
if (list_empty(&q->active))
return 0;
buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);
dprintk(2,"restart_queue [%p/%d]: restart dma\n",
buf, buf->vb.i);
cx8800_start_vbi_dma(dev, q, buf);
list_for_each(item,&q->active) {
buf = list_entry(item, struct cx88_buffer, vb.queue);
buf->count = q->count++;
}
mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
return 0;
}
void cx8800_vbi_timeout(unsigned long data)
{
struct cx8800_dev *dev = (struct cx8800_dev*)data;
struct cx88_dmaqueue *q = &dev->vbiq;
struct cx88_buffer *buf;
unsigned long flags;
cx88_sram_channel_dump(dev, &cx88_sram_channels[SRAM_CH24]);
cx_clear(MO_VID_DMACNTRL, 0x88);
cx_clear(VID_CAPTURE_CONTROL, 0x18);
spin_lock_irqsave(&dev->slock,flags);
while (!list_empty(&q->active)) {
buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);
list_del(&buf->vb.queue);
buf->vb.state = STATE_ERROR;
wake_up(&buf->vb.done);
printk("%s: [%p/%d] timeout - dma=0x%08lx\n", dev->name,
buf, buf->vb.i, (unsigned long)buf->risc.dma);
}
cx8800_restart_vbi_queue(dev,q);
spin_unlock_irqrestore(&dev->slock,flags);
}
/* ------------------------------------------------------------------ */
static int
vbi_setup(struct file *file, unsigned int *count, unsigned int *size)
{
*size = VBI_LINE_COUNT * VBI_LINE_LENGTH * 2;
if (0 == *count)
*count = vbibufs;
if (*count < 2)
*count = 2;
if (*count > 32)
*count = 32;
return 0;
}
static int
vbi_prepare(struct file *file, struct videobuf_buffer *vb,
enum v4l2_field field)
{
struct cx8800_fh *fh = file->private_data;
struct cx8800_dev *dev = fh->dev;
struct cx88_buffer *buf = (struct cx88_buffer*)vb;
unsigned int size;
int rc;
size = VBI_LINE_COUNT * VBI_LINE_LENGTH * 2;
if (0 != buf->vb.baddr && buf->vb.bsize < size)
return -EINVAL;
if (STATE_NEEDS_INIT == buf->vb.state) {
buf->vb.width = VBI_LINE_LENGTH;
buf->vb.height = VBI_LINE_COUNT;
buf->vb.size = size;
buf->vb.field = V4L2_FIELD_SEQ_TB;
if (0 != (rc = videobuf_iolock(dev->pci,&buf->vb,NULL)))
goto fail;
cx88_risc_buffer(dev->pci, &buf->risc,
buf->vb.dma.sglist,
0, buf->vb.width * buf->vb.height,
buf->vb.width, 0,
buf->vb.height);
}
buf->vb.state = STATE_PREPARED;
return 0;
fail:
cx88_free_buffer(dev->pci,buf);
return rc;
}
static void
vbi_queue(struct file *file, struct videobuf_buffer *vb)
{
struct cx88_buffer *buf = (struct cx88_buffer*)vb;
struct cx88_buffer *prev;
struct cx8800_fh *fh = file->private_data;
struct cx8800_dev *dev = fh->dev;
struct cx88_dmaqueue *q = &dev->vbiq;
/* add jump to stopper */
buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | 0x10000);
buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma);
if (list_empty(&q->active)) {
list_add_tail(&buf->vb.queue,&q->active);
cx8800_start_vbi_dma(dev, q, buf);
buf->vb.state = STATE_ACTIVE;
buf->count = q->count++;
mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
dprintk(2,"[%p/%d] vbi_queue - first active\n",
buf, buf->vb.i);
} else {
prev = list_entry(q->active.prev, struct cx88_buffer, vb.queue);
list_add_tail(&buf->vb.queue,&q->active);
buf->vb.state = STATE_ACTIVE;
buf->count = q->count++;
prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
dprintk(2,"[%p/%d] buffer_queue - append to active\n",
buf, buf->vb.i);
}
}
static void vbi_release(struct file *file, struct videobuf_buffer *vb)
{
struct cx88_buffer *buf = (struct cx88_buffer*)vb;
struct cx8800_fh *fh = file->private_data;
cx88_free_buffer(fh->dev->pci,buf);
}
struct videobuf_queue_ops cx8800_vbi_qops = {
.buf_setup = vbi_setup,
.buf_prepare = vbi_prepare,
.buf_queue = vbi_queue,
.buf_release = vbi_release,
};
/* ------------------------------------------------------------------ */
/*
* Local variables:
* c-basic-offset: 8
* End:
*/
This diff is collapsed.
/*
* v4l2 device driver for philips saa7134 based TV cards
* v4l2 device driver for cx2388x based TV cards
*
* (c) 2001,02 Gerd Knorr <kraxel@bytesex.org>
* (c) 2003,04 Gerd Knorr <kraxel@bytesex.org> [SUSE Labs]
*
* 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
......@@ -32,7 +32,7 @@
#include "cx88-reg.h"
#include <linux/version.h>
#define CX88_VERSION_CODE KERNEL_VERSION(0,0,1)
#define CX88_VERSION_CODE KERNEL_VERSION(0,0,3)
#ifndef TRUE
# define TRUE (1==1)
......@@ -50,6 +50,14 @@
#define FORMAT_FLAGS_PACKED 0x01
#define FORMAT_FLAGS_PLANAR 0x02
#define VBI_LINE_COUNT 17
#define VBI_LINE_LENGTH 2048
/* need "shadow" registers for some write-only ones ... */
#define SHADOW_AUD_VOL_CTL 1
#define SHADOW_AUD_BAL_CTL 2
#define SHADOW_MAX 2
/* ----------------------------------------------------------- */
/* static data */
......@@ -72,6 +80,7 @@ struct cx88_ctrl {
struct v4l2_queryctrl v;
u32 off;
u32 reg;
u32 sreg;
u32 mask;
u32 shift;
};
......@@ -91,6 +100,7 @@ struct sram_channel {
char *name;
u32 cmds_start;
u32 ctrl_start;
u32 cdt;
u32 fifo_start;
u32 fifo_size;
u32 ptr1_reg;
......@@ -113,6 +123,7 @@ extern struct sram_channel cx88_sram_channels[];
#define CX88_BOARD_AVERTV_303 6
#define CX88_BOARD_MSI_TVANYWHERE 7
#define CX88_BOARD_WINFAST_DV2000 8
#define CX88_BOARD_LEADTEK_PVR2000 9
enum cx88_itype {
......@@ -129,12 +140,13 @@ enum cx88_itype {
struct cx88_input {
enum cx88_itype type;
unsigned int vmux;
u32 gpio0;
u32 gpio0, gpio1, gpio2, gpio3;
};
struct cx88_board {
char *name;
unsigned int tuner_type;
int needs_tda9887:1;
struct cx88_input input[8];
struct cx88_input radio;
};
......@@ -195,6 +207,9 @@ struct cx8800_fh {
struct cx8800_fmt *fmt;
unsigned int width,height;
struct videobuf_queue vidq;
/* vbi capture */
struct videobuf_queue vbiq;
};
struct cx8800_suspend_state {
......@@ -211,6 +226,7 @@ struct cx8800_dev {
/* various device info */
unsigned int resources;
struct video_device *video_dev;
struct video_device *vbi_dev;
struct video_device *radio_dev;
/* pci i/o */
......@@ -218,6 +234,7 @@ struct cx8800_dev {
struct pci_dev *pci;
unsigned char pci_rev,pci_lat;
u32 *lmmio;
u8 *bmmio;
/* config info */
unsigned int board;
......@@ -236,6 +253,7 @@ struct cx8800_dev {
/* capture queues */
struct cx88_dmaqueue vidq;
struct cx88_dmaqueue vbiq;
/* various v4l controls */
struct cx8800_tvnorm *tvnorm;
......@@ -244,6 +262,7 @@ struct cx8800_dev {
u32 freq;
/* other global state info */
u32 shadow[SHADOW_MAX];
struct cx8800_suspend_state state;
};
......@@ -251,6 +270,7 @@ struct cx8800_dev {
#define cx_read(reg) readl(dev->lmmio + ((reg)>>2))
#define cx_write(reg,value) writel((value), dev->lmmio + ((reg)>>2));
#define cx_writeb(reg,value) writeb((value), dev->bmmio + (reg));
#define cx_andor(reg,mask,value) \
writel((readl(dev->lmmio+((reg)>>2)) & ~(mask)) |\
......@@ -258,8 +278,16 @@ struct cx8800_dev {
#define cx_set(reg,bit) cx_andor((reg),(bit),(bit))
#define cx_clear(reg,bit) cx_andor((reg),(bit),0)
#define cx_wait(d) { if (need_resched()) schedule(); else udelay(d);}
#define cx_wait(d) { if (need_resched()) schedule(); else udelay(d); }
/* shadow registers */
#define cx_sread(sreg) (dev->shadow[sreg])
#define cx_swrite(sreg,reg,value) \
(dev->shadow[sreg] = value, \
writel(dev->shadow[sreg], dev->lmmio + ((reg)>>2)))
#define cx_sandor(sreg,reg,mask,value) \
(dev->shadow[sreg] = (dev->shadow[sreg] & ~(mask)) | ((value) & (mask)), \
writel(dev->shadow[sreg], dev->lmmio + ((reg)>>2)))
/* ----------------------------------------------------------- */
/* cx88-core.c */
......@@ -293,6 +321,19 @@ extern void cx88_sram_channel_dump(struct cx8800_dev *dev,
extern int cx88_pci_quirks(char *name, struct pci_dev *pci,
unsigned int *latency);
/* ----------------------------------------------------------- */
/* cx88-vbi.c */
void cx8800_vbi_fmt(struct cx8800_dev *dev, struct v4l2_format *f);
int cx8800_start_vbi_dma(struct cx8800_dev *dev,
struct cx88_dmaqueue *q,
struct cx88_buffer *buf);
int cx8800_restart_vbi_queue(struct cx8800_dev *dev,
struct cx88_dmaqueue *q);
void cx8800_vbi_timeout(unsigned long data);
extern struct videobuf_queue_ops cx8800_vbi_qops;
/* ----------------------------------------------------------- */
/* cx88-i2c.c */
......@@ -310,7 +351,7 @@ extern const unsigned int cx88_bcount;
extern struct cx88_subid cx88_subids[];
extern const unsigned int cx88_idcount;
extern void cx88_card_setup(struct cx8800_dev *dev);
extern void __devinit cx88_card_setup(struct cx8800_dev *dev);
/* ----------------------------------------------------------- */
/* cx88-tvaudio.c */
......
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