Commit 8bb4a936 authored by Gerd Knorr's avatar Gerd Knorr Committed by Linus Torvalds

[PATCH] v4l: bttv driver update

This is a update of the bttv driver.  Changes:

* some card-specific fixes + new cards.

* separate buffer switching for video frames and vbi data, that should make
  bttv less sensitive to high irq latencies.
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent e6cf179b
...@@ -71,6 +71,9 @@ static void gvc1100_muxsel(struct bttv *btv, unsigned int input); ...@@ -71,6 +71,9 @@ static void gvc1100_muxsel(struct bttv *btv, unsigned int input);
static void PXC200_muxsel(struct bttv *btv, unsigned int input); static void PXC200_muxsel(struct bttv *btv, unsigned int input);
static void picolo_tetra_muxsel(struct bttv *btv, unsigned int input);
static void picolo_tetra_init(struct bttv *btv);
static int terratec_active_radio_upgrade(struct bttv *btv); static int terratec_active_radio_upgrade(struct bttv *btv);
static int tea5757_read(struct bttv *btv); static int tea5757_read(struct bttv *btv);
static int tea5757_write(struct bttv *btv, int value); static int tea5757_write(struct bttv *btv, int value);
...@@ -181,6 +184,7 @@ static struct CARD { ...@@ -181,6 +184,7 @@ static struct CARD {
{ 0xff00bd11, BTTV_PINNACLE, "Pinnacle PCTV [bswap]" }, { 0xff00bd11, BTTV_PINNACLE, "Pinnacle PCTV [bswap]" },
{ 0x3000121a, BTTV_VOODOOTV_FM, "3Dfx VoodooTV FM/ VoodooTV 200" }, { 0x3000121a, BTTV_VOODOOTV_FM, "3Dfx VoodooTV FM/ VoodooTV 200" },
{ 0x263710b4, BTTV_VOODOOTV_FM, "3Dfx VoodooTV FM/ VoodooTV 200" },
{ 0x3060121a, BTTV_STB2, "3Dfx VoodooTV 100/ STB OEM" }, { 0x3060121a, BTTV_STB2, "3Dfx VoodooTV 100/ STB OEM" },
{ 0x3000144f, BTTV_MAGICTVIEW063, "(Askey Magic/others) TView99 CPH06x" }, { 0x3000144f, BTTV_MAGICTVIEW063, "(Askey Magic/others) TView99 CPH06x" },
...@@ -260,12 +264,15 @@ static struct CARD { ...@@ -260,12 +264,15 @@ static struct CARD {
{ 0x41424344, BTTV_GRANDTEC, "GrandTec Multi Capture" }, { 0x41424344, BTTV_GRANDTEC, "GrandTec Multi Capture" },
{ 0x01020304, BTTV_XGUARD, "Grandtec Grand X-Guard" }, { 0x01020304, BTTV_XGUARD, "Grandtec Grand X-Guard" },
{ 0x010115cb, BTTV_GMV1, "AG GMV1" },
{ 0x010114c7, BTTV_MODTEC_205, "Modular Technology MM201/MM202/MM205/MM210/MM215 PCTV" },
{ 0x18501851, BTTV_CHRONOS_VS2, "FlyVideo 98 (LR50)/ Chronos Video Shuttle II" }, { 0x18501851, BTTV_CHRONOS_VS2, "FlyVideo 98 (LR50)/ Chronos Video Shuttle II" },
{ 0x18511851, BTTV_FLYVIDEO98EZ, "FlyVideo 98EZ (LR51)/ CyberMail AV" }, { 0x18511851, BTTV_FLYVIDEO98EZ, "FlyVideo 98EZ (LR51)/ CyberMail AV" },
{ 0x18521852, BTTV_TYPHOON_TVIEW, "FlyVideo 98FM (LR50)/ Typhoon TView TV/FM Tuner" }, { 0x18521852, BTTV_TYPHOON_TVIEW, "FlyVideo 98FM (LR50)/ Typhoon TView TV/FM Tuner" },
{ 0x41a0a051, BTTV_FLYVIDEO_98FM, "Lifeview FlyVideo 98 LR50 Rev Q" }, { 0x41a0a051, BTTV_FLYVIDEO_98FM, "Lifeview FlyVideo 98 LR50 Rev Q" },
{ 0x18501f7f, BTTV_FLYVIDEO_98, "Lifeview Flyvideo 98" },
{ 0x010115cb, BTTV_GMV1, "AG GMV1" },
{ 0x010114c7, BTTV_MODTEC_205, "Modular Technology MM201/MM202/MM205/MM210/MM215 PCTV" },
{ 0x10b42636, BTTV_HAUPPAUGE878, "STB ???" }, { 0x10b42636, BTTV_HAUPPAUGE878, "STB ???" },
{ 0x217d6606, BTTV_WINFAST2000, "Leadtek WinFast TV 2000" }, { 0x217d6606, BTTV_WINFAST2000, "Leadtek WinFast TV 2000" },
{ 0xfff6f6ff, BTTV_WINFAST2000, "Leadtek WinFast TV 2000" }, { 0xfff6f6ff, BTTV_WINFAST2000, "Leadtek WinFast TV 2000" },
...@@ -280,14 +287,21 @@ static struct CARD { ...@@ -280,14 +287,21 @@ static struct CARD {
{ 0x40111554, BTTV_PV_BT878P_9B, "Prolink Pixelview PV-BT" }, { 0x40111554, BTTV_PV_BT878P_9B, "Prolink Pixelview PV-BT" },
{ 0x17de0a01, BTTV_KWORLD, "Mecer TV/FM/Video Tuner" }, { 0x17de0a01, BTTV_KWORLD, "Mecer TV/FM/Video Tuner" },
{ 0x01051805, BTTV_PICOLO_TETRA_CHIP, "Picolo Tetra Chip #1" },
{ 0x01061805, BTTV_PICOLO_TETRA_CHIP, "Picolo Tetra Chip #2" },
{ 0x01071805, BTTV_PICOLO_TETRA_CHIP, "Picolo Tetra Chip #3" },
{ 0x01081805, BTTV_PICOLO_TETRA_CHIP, "Picolo Tetra Chip #4" },
// likely broken, vendor id doesn't match the other magic views ... // likely broken, vendor id doesn't match the other magic views ...
//{ 0xa0fca04f, BTTV_MAGICTVIEW063, "Guillemot Maxi TV Video 3" }, //{ 0xa0fca04f, BTTV_MAGICTVIEW063, "Guillemot Maxi TV Video 3" },
// DVB cards (using pci function .1 for mpeg data xfer) // DVB cards (using pci function .1 for mpeg data xfer)
{ 0x01010071, BTTV_NEBULA_DIGITV, "Nebula Electronics DigiTV" }, { 0x01010071, BTTV_NEBULA_DIGITV, "Nebula Electronics DigiTV" },
{ 0x07611461, BTTV_NEBULA_DIGITV, "AverMedia AverTV DVB-T" },
{ 0x002611bd, BTTV_TWINHAN_DST, "Pinnacle PCTV SAT CI" }, { 0x002611bd, BTTV_TWINHAN_DST, "Pinnacle PCTV SAT CI" },
{ 0x00011822, BTTV_TWINHAN_DST, "Twinhan VisionPlus DVB-T" }, { 0x00011822, BTTV_TWINHAN_DST, "Twinhan VisionPlus DVB-T" },
{ 0xfc00270f, BTTV_TWINHAN_DST, "ChainTech digitop DST-1000 DVB-S" }, { 0xfc00270f, BTTV_TWINHAN_DST, "ChainTech digitop DST-1000 DVB-S" },
{ 0x07711461, BTTV_AVDVBT_771, "AVermedia DVB-T 771" },
{ 0, -1, NULL } { 0, -1, NULL }
}; };
...@@ -835,7 +849,7 @@ struct tvcard bttv_tvcards[] = { ...@@ -835,7 +849,7 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2, .svhs = 2,
.gpiomask = 0x03000F, .gpiomask = 0x03000F,
.muxsel = { 2, 3, 1, 1}, .muxsel = { 2, 3, 1, 1},
.audiomux = { 2, 0, 0, 0, 1}, .audiomux = { 2, 0xd0001, 0, 0, 1},
.needs_tvaudio = 0, .needs_tvaudio = 0,
.pll = PLL_28, .pll = PLL_28,
.tuner_type = -1, .tuner_type = -1,
...@@ -1646,6 +1660,7 @@ struct tvcard bttv_tvcards[] = { ...@@ -1646,6 +1660,7 @@ struct tvcard bttv_tvcards[] = {
.muxsel = { 3, 0, 1, 2}, .muxsel = { 3, 0, 1, 2},
.needs_tvaudio = 0, .needs_tvaudio = 0,
.pll = PLL_28, .pll = PLL_28,
.no_gpioirq = 1,
},{ },{
.name = "Formac ProTV II (bt878)", .name = "Formac ProTV II (bt878)",
.video_inputs = 4, .video_inputs = 4,
...@@ -2012,6 +2027,57 @@ struct tvcard bttv_tvcards[] = { ...@@ -2012,6 +2027,57 @@ struct tvcard bttv_tvcards[] = {
.tuner_type = TUNER_PHILIPS_PAL, .tuner_type = TUNER_PHILIPS_PAL,
.has_remote = 1, .has_remote = 1,
.has_radio = 1, .has_radio = 1,
},{
/*Eric DEBIEF <debief@telemsa.com>*/
/*EURESYS Picolo Tetra : 4 Conexant Fusion 878A, no audio, video input set with analog multiplexers GPIO controled*/
/* adds picolo_tetra_muxsel(), picolo_tetra_init(), the folowing declaration strucure, and #define BTTV_PICOLO_TETRA_CHIP*/
/*0x79 in bttv.h*/
.name = "Euresys Picolo Tetra",
.video_inputs = 4,
.audio_inputs = 0,
.tuner = -1,
.svhs = -1,
.gpiomask = 0,
.gpiomask2 = 0x3C<<16,/*Set the GPIO[18]->GPIO[21] as output pin.==> drive the video inputs through analog multiplexers*/
.no_msp34xx = 1,
.no_tda9875 = 1,
.no_tda7432 = 1,
.muxsel = {2,2,2,2},/*878A input is always MUX0, see above.*/
.audiomux = { 0, 0, 0, 0, 0, 0 }, /* card has no audio */
.pll = PLL_28,
.needs_tvaudio = 0,
.muxsel_hook = picolo_tetra_muxsel,/*Required as it doesn't follow the classic input selection policy*/
},{
/* Spirit TV Tuner from http://spiritmodems.com.au */
/* Stafford Goodsell <surge@goliath.homeunix.org> */
.name = "Spirit TV Tuner",
.video_inputs = 3,
.audio_inputs = 1,
.tuner = 0,
.svhs = 2,
.gpiomask = 0x0000000f,
.muxsel = { 2, 1, 1 },
.audiomux = { 0x02, 0x00, 0x00, 0x00, 0x00},
.tuner_type = TUNER_TEMIC_PAL,
.no_msp34xx = 1,
.no_tda9875 = 1,
},{
/* Wolfram Joost <wojo@frokaschwei.de> */
.name = "AVerMedia AVerTV DVB-T 771",
.video_inputs = 2,
.svhs = 1,
.tuner = -1,
.tuner_type = TUNER_ABSENT,
.muxsel = { 3 , 3 },
.no_msp34xx = 1,
.no_tda9875 = 1,
.no_tda7432 = 1,
.pll = PLL_28,
.has_dvb = 1,
.no_gpioirq = 1,
#if 0 /* untested */
.has_remote = 1,
#endif
}}; }};
const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards); const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards);
...@@ -2381,6 +2447,7 @@ void __devinit bttv_init_card1(struct bttv *btv) ...@@ -2381,6 +2447,7 @@ void __devinit bttv_init_card1(struct bttv *btv)
pvr_boot(btv); pvr_boot(btv);
break; break;
case BTTV_TWINHAN_DST: case BTTV_TWINHAN_DST:
case BTTV_AVDVBT_771:
btv->use_i2c_hw = 1; btv->use_i2c_hw = 1;
break; break;
} }
...@@ -2432,6 +2499,9 @@ void __devinit bttv_init_card2(struct bttv *btv) ...@@ -2432,6 +2499,9 @@ void __devinit bttv_init_card2(struct bttv *btv)
case BTTV_PXC200: case BTTV_PXC200:
init_PXC200(btv); init_PXC200(btv);
break; break;
case BTTV_PICOLO_TETRA_CHIP:
picolo_tetra_init(btv);
break;
case BTTV_VHX: case BTTV_VHX:
btv->has_radio = 1; btv->has_radio = 1;
btv->has_matchbox = 1; btv->has_matchbox = 1;
...@@ -2668,6 +2738,10 @@ static void modtec_eeprom(struct bttv *btv) ...@@ -2668,6 +2738,10 @@ static void modtec_eeprom(struct bttv *btv)
btv->tuner_type=TUNER_ALPS_TSBB5_PAL_I; btv->tuner_type=TUNER_ALPS_TSBB5_PAL_I;
printk("bttv%d: Modtec: Tuner autodetected by eeprom: %s\n", printk("bttv%d: Modtec: Tuner autodetected by eeprom: %s\n",
btv->c.nr,&eeprom_data[0x1e]); btv->c.nr,&eeprom_data[0x1e]);
} else if (strncmp(&(eeprom_data[0x1e]),"Philips FM1246",14) ==0) {
btv->tuner_type=TUNER_PHILIPS_NTSC;
printk("bttv%d: Modtec: Tuner autodetected by eeprom: %s\n",
btv->c.nr,&eeprom_data[0x1e]);
} else { } else {
printk("bttv%d: Modtec: Unknown TunerString: %s\n", printk("bttv%d: Modtec: Unknown TunerString: %s\n",
btv->c.nr,&eeprom_data[0x1e]); btv->c.nr,&eeprom_data[0x1e]);
...@@ -3786,6 +3860,21 @@ static void xguard_muxsel(struct bttv *btv, unsigned int input) ...@@ -3786,6 +3860,21 @@ static void xguard_muxsel(struct bttv *btv, unsigned int input)
}; };
gpio_write(masks[input%16]); gpio_write(masks[input%16]);
} }
static void picolo_tetra_init(struct bttv *btv)
{
/*This is the video input redirection fonctionality : I DID NOT USED IT. */
btwrite (0x08<<16,BT848_GPIO_DATA);/*GPIO[19] [==> 4053 B+C] set to 1 */
btwrite (0x04<<16,BT848_GPIO_DATA);/*GPIO[18] [==> 4053 A] set to 1*/
}
static void picolo_tetra_muxsel (struct bttv* btv, unsigned int input)
{
dprintk (KERN_DEBUG "bttv%d : picolo_tetra_muxsel => input = %d\n",btv->c.nr,input);
/*Just set the right path in the analog multiplexers : channel 1 -> 4 ==> Analog Mux ==> MUX0*/
/*GPIO[20]&GPIO[21] used to choose the right input*/
btwrite (input<<20,BT848_GPIO_DATA);
}
/* /*
* ivc120_muxsel [Added by Alan Garfield <alan@fromorbit.com>] * ivc120_muxsel [Added by Alan Garfield <alan@fromorbit.com>]
......
...@@ -1334,7 +1334,8 @@ bttv_switch_overlay(struct bttv *btv, struct bttv_fh *fh, ...@@ -1334,7 +1334,8 @@ bttv_switch_overlay(struct bttv *btv, struct bttv_fh *fh,
spin_lock_irqsave(&btv->s_lock,flags); spin_lock_irqsave(&btv->s_lock,flags);
old = btv->screen; old = btv->screen;
btv->screen = new; btv->screen = new;
bttv_set_dma(btv, 0x03, 1); btv->curr.irqflags |= 1;
bttv_set_dma(btv, 0x03, btv->curr.irqflags);
spin_unlock_irqrestore(&btv->s_lock,flags); spin_unlock_irqrestore(&btv->s_lock,flags);
if (NULL == new) if (NULL == new)
free_btres(btv,fh,RESOURCE_OVERLAY); free_btres(btv,fh,RESOURCE_OVERLAY);
...@@ -1441,7 +1442,8 @@ buffer_queue(struct file *file, struct videobuf_buffer *vb) ...@@ -1441,7 +1442,8 @@ buffer_queue(struct file *file, struct videobuf_buffer *vb)
buf->vb.state = STATE_QUEUED; buf->vb.state = STATE_QUEUED;
list_add_tail(&buf->vb.queue,&fh->btv->capture); list_add_tail(&buf->vb.queue,&fh->btv->capture);
bttv_set_dma(fh->btv, 0x03, 1); fh->btv->curr.irqflags |= 1;
bttv_set_dma(fh->btv, 0x03, fh->btv->curr.irqflags);
} }
static void buffer_release(struct file *file, struct videobuf_buffer *vb) static void buffer_release(struct file *file, struct videobuf_buffer *vb)
...@@ -3203,8 +3205,8 @@ static void bttv_print_riscaddr(struct bttv *btv) ...@@ -3203,8 +3205,8 @@ static void bttv_print_riscaddr(struct bttv *btv)
printk(" main: %08Lx\n", printk(" main: %08Lx\n",
(unsigned long long)btv->main.dma); (unsigned long long)btv->main.dma);
printk(" vbi : o=%08Lx e=%08Lx\n", printk(" vbi : o=%08Lx e=%08Lx\n",
btv->curr.vbi ? (unsigned long long)btv->curr.vbi->top.dma : 0, btv->cvbi ? (unsigned long long)btv->cvbi->top.dma : 0,
btv->curr.vbi ? (unsigned long long)btv->curr.vbi->bottom.dma : 0); btv->cvbi ? (unsigned long long)btv->cvbi->bottom.dma : 0);
printk(" cap : o=%08Lx e=%08Lx\n", printk(" cap : o=%08Lx e=%08Lx\n",
btv->curr.top ? (unsigned long long)btv->curr.top->top.dma : 0, btv->curr.top ? (unsigned long long)btv->curr.top->top.dma : 0,
btv->curr.bottom ? (unsigned long long)btv->curr.bottom->bottom.dma : 0); btv->curr.bottom ? (unsigned long long)btv->curr.bottom->bottom.dma : 0);
...@@ -3224,7 +3226,7 @@ static void bttv_irq_debug_low_latency(struct bttv *btv, u32 rc) ...@@ -3224,7 +3226,7 @@ static void bttv_irq_debug_low_latency(struct bttv *btv, u32 rc)
if (0 == (btread(BT848_DSTATUS) & BT848_DSTATUS_HLOC)) { if (0 == (btread(BT848_DSTATUS) & BT848_DSTATUS_HLOC)) {
printk("bttv%d: Oh, there (temporarely?) is no input signal. " printk("bttv%d: Oh, there (temporarely?) is no input signal. "
"Ok, then this is harmless, don't worry ;)", "Ok, then this is harmless, don't worry ;)\n",
btv->c.nr); btv->c.nr);
return; return;
} }
...@@ -3236,18 +3238,12 @@ static void bttv_irq_debug_low_latency(struct bttv *btv, u32 rc) ...@@ -3236,18 +3238,12 @@ static void bttv_irq_debug_low_latency(struct bttv *btv, u32 rc)
} }
static int static int
bttv_irq_next_set(struct bttv *btv, struct bttv_buffer_set *set) bttv_irq_next_video(struct bttv *btv, struct bttv_buffer_set *set)
{ {
struct bttv_buffer *item; struct bttv_buffer *item;
memset(set,0,sizeof(*set)); memset(set,0,sizeof(*set));
/* vbi request ? */
if (!list_empty(&btv->vcapture)) {
set->irqflags = 1;
set->vbi = list_entry(btv->vcapture.next, struct bttv_buffer, vb.queue);
}
/* capture request ? */ /* capture request ? */
if (!list_empty(&btv->capture)) { if (!list_empty(&btv->capture)) {
set->irqflags = 1; set->irqflags = 1;
...@@ -3295,27 +3291,20 @@ bttv_irq_next_set(struct bttv *btv, struct bttv_buffer_set *set) ...@@ -3295,27 +3291,20 @@ bttv_irq_next_set(struct bttv *btv, struct bttv_buffer_set *set)
} }
} }
dprintk("bttv%d: next set: top=%p bottom=%p vbi=%p " dprintk("bttv%d: next set: top=%p bottom=%p [screen=%p,irq=%d,%d]\n",
"[screen=%p,irq=%d,%d]\n", btv->c.nr,set->top, set->bottom,
btv->c.nr,set->top, set->bottom, set->vbi,
btv->screen,set->irqflags,set->topirq); btv->screen,set->irqflags,set->topirq);
return 0; return 0;
} }
static void static void
bttv_irq_wakeup_set(struct bttv *btv, struct bttv_buffer_set *wakeup, bttv_irq_wakeup_video(struct bttv *btv, struct bttv_buffer_set *wakeup,
struct bttv_buffer_set *curr, unsigned int state) struct bttv_buffer_set *curr, unsigned int state)
{ {
struct timeval ts; struct timeval ts;
do_gettimeofday(&ts); do_gettimeofday(&ts);
if (NULL != wakeup->vbi) {
wakeup->vbi->vb.ts = ts;
wakeup->vbi->vb.field_count = btv->field_count;
wakeup->vbi->vb.state = state;
wake_up(&wakeup->vbi->vb.done);
}
if (wakeup->top == wakeup->bottom) { if (wakeup->top == wakeup->bottom) {
if (NULL != wakeup->top && curr->top != wakeup->top) { if (NULL != wakeup->top && curr->top != wakeup->top) {
if (irq_debug > 1) if (irq_debug > 1)
...@@ -3345,10 +3334,27 @@ bttv_irq_wakeup_set(struct bttv *btv, struct bttv_buffer_set *wakeup, ...@@ -3345,10 +3334,27 @@ bttv_irq_wakeup_set(struct bttv *btv, struct bttv_buffer_set *wakeup,
} }
} }
static void
bttv_irq_wakeup_vbi(struct bttv *btv, struct bttv_buffer *wakeup,
unsigned int state)
{
struct timeval ts;
if (NULL == wakeup)
return;
do_gettimeofday(&ts);
wakeup->vb.ts = ts;
wakeup->vb.field_count = btv->field_count;
wakeup->vb.state = state;
wake_up(&wakeup->vb.done);
}
static void bttv_irq_timeout(unsigned long data) static void bttv_irq_timeout(unsigned long data)
{ {
struct bttv *btv = (struct bttv *)data; struct bttv *btv = (struct bttv *)data;
struct bttv_buffer_set old,new; struct bttv_buffer_set old,new;
struct bttv_buffer *ovbi;
struct bttv_buffer *item; struct bttv_buffer *item;
unsigned long flags; unsigned long flags;
...@@ -3364,13 +3370,17 @@ static void bttv_irq_timeout(unsigned long data) ...@@ -3364,13 +3370,17 @@ static void bttv_irq_timeout(unsigned long data)
/* deactivate stuff */ /* deactivate stuff */
memset(&new,0,sizeof(new)); memset(&new,0,sizeof(new));
old = btv->curr; old = btv->curr;
ovbi = btv->cvbi;
btv->curr = new; btv->curr = new;
bttv_buffer_set_activate(btv, &new); btv->cvbi = NULL;
bttv_buffer_activate_video(btv, &new);
bttv_buffer_activate_vbi(btv, NULL);
bttv_set_dma(btv, 0, 0); bttv_set_dma(btv, 0, 0);
/* wake up */ /* wake up */
bttv_irq_wakeup_set(btv, &old, &new, STATE_ERROR); bttv_irq_wakeup_video(btv, &old, &new, STATE_ERROR);
bttv_irq_wakeup_vbi(btv, ovbi, STATE_ERROR);
/* cancel all outstanding capture / vbi requests */ /* cancel all outstanding capture / vbi requests */
while (!list_empty(&btv->capture)) { while (!list_empty(&btv->capture)) {
...@@ -3410,8 +3420,17 @@ bttv_irq_wakeup_top(struct bttv *btv) ...@@ -3410,8 +3420,17 @@ bttv_irq_wakeup_top(struct bttv *btv)
spin_unlock(&btv->s_lock); spin_unlock(&btv->s_lock);
} }
static inline int is_active(struct btcx_riscmem *risc, u32 rc)
{
if (rc < risc->dma)
return 0;
if (rc > risc->dma + risc->size)
return 0;
return 1;
}
static void static void
bttv_irq_switch_fields(struct bttv *btv) bttv_irq_switch_video(struct bttv *btv)
{ {
struct bttv_buffer_set new; struct bttv_buffer_set new;
struct bttv_buffer_set old; struct bttv_buffer_set old;
...@@ -3420,9 +3439,10 @@ bttv_irq_switch_fields(struct bttv *btv) ...@@ -3420,9 +3439,10 @@ bttv_irq_switch_fields(struct bttv *btv)
spin_lock(&btv->s_lock); spin_lock(&btv->s_lock);
/* new buffer set */ /* new buffer set */
bttv_irq_next_set(btv, &new); bttv_irq_next_video(btv, &new);
rc = btread(BT848_RISC_COUNT); rc = btread(BT848_RISC_COUNT);
if (rc < btv->main.dma || rc > btv->main.dma + 0x100) { if ((btv->curr.top && is_active(&btv->curr.top->top, rc)) ||
(btv->curr.bottom && is_active(&btv->curr.bottom->bottom, rc))) {
btv->framedrop++; btv->framedrop++;
if (debug_latency) if (debug_latency)
bttv_irq_debug_low_latency(btv, rc); bttv_irq_debug_low_latency(btv, rc);
...@@ -3433,7 +3453,7 @@ bttv_irq_switch_fields(struct bttv *btv) ...@@ -3433,7 +3453,7 @@ bttv_irq_switch_fields(struct bttv *btv)
/* switch over */ /* switch over */
old = btv->curr; old = btv->curr;
btv->curr = new; btv->curr = new;
bttv_buffer_set_activate(btv, &new); bttv_buffer_activate_video(btv, &new);
bttv_set_dma(btv, 0, new.irqflags); bttv_set_dma(btv, 0, new.irqflags);
/* switch input */ /* switch input */
...@@ -3443,7 +3463,39 @@ bttv_irq_switch_fields(struct bttv *btv) ...@@ -3443,7 +3463,39 @@ bttv_irq_switch_fields(struct bttv *btv)
} }
/* wake up finished buffers */ /* wake up finished buffers */
bttv_irq_wakeup_set(btv, &old, &new, STATE_DONE); bttv_irq_wakeup_video(btv, &old, &new, STATE_DONE);
spin_unlock(&btv->s_lock);
}
static void
bttv_irq_switch_vbi(struct bttv *btv)
{
struct bttv_buffer *new = NULL;
struct bttv_buffer *old;
u32 rc;
spin_lock(&btv->s_lock);
if (!list_empty(&btv->vcapture))
new = list_entry(btv->vcapture.next, struct bttv_buffer, vb.queue);
old = btv->cvbi;
rc = btread(BT848_RISC_COUNT);
if (NULL != old && (is_active(&old->top, rc) ||
is_active(&old->bottom, rc))) {
btv->framedrop++;
if (debug_latency)
bttv_irq_debug_low_latency(btv, rc);
spin_unlock(&btv->s_lock);
return;
}
/* switch */
btv->cvbi = new;
bttv_buffer_activate_vbi(btv, new);
bttv_set_dma(btv, 0, btv->curr.irqflags);
bttv_irq_wakeup_vbi(btv, old, STATE_DONE);
spin_unlock(&btv->s_lock); spin_unlock(&btv->s_lock);
} }
...@@ -3500,11 +3552,14 @@ static irqreturn_t bttv_irq(int irq, void *dev_id, struct pt_regs * regs) ...@@ -3500,11 +3552,14 @@ static irqreturn_t bttv_irq(int irq, void *dev_id, struct pt_regs * regs)
wake_up(&btv->i2c_queue); wake_up(&btv->i2c_queue);
} }
if ((astat & BT848_INT_RISCI) && (stat & (4<<28)))
bttv_irq_switch_vbi(btv);
if ((astat & BT848_INT_RISCI) && (stat & (2<<28))) if ((astat & BT848_INT_RISCI) && (stat & (2<<28)))
bttv_irq_wakeup_top(btv); bttv_irq_wakeup_top(btv);
if ((astat & BT848_INT_RISCI) && (stat & (1<<28))) if ((astat & BT848_INT_RISCI) && (stat & (1<<28)))
bttv_irq_switch_fields(btv); bttv_irq_switch_video(btv);
if ((astat & BT848_INT_HLOCK) && btv->opt_automute) if ((astat & BT848_INT_HLOCK) && btv->opt_automute)
audio_mux(btv, -1); audio_mux(btv, -1);
...@@ -3872,9 +3927,11 @@ static int bttv_suspend(struct pci_dev *pci_dev, u32 state) ...@@ -3872,9 +3927,11 @@ static int bttv_suspend(struct pci_dev *pci_dev, u32 state)
/* stop dma + irqs */ /* stop dma + irqs */
spin_lock_irqsave(&btv->s_lock,flags); spin_lock_irqsave(&btv->s_lock,flags);
memset(&idle, 0, sizeof(idle)); memset(&idle, 0, sizeof(idle));
btv->state.set = btv->curr; btv->state.video = btv->curr;
btv->state.vbi = btv->cvbi;
btv->curr = idle; btv->curr = idle;
bttv_buffer_set_activate(btv, &idle); bttv_buffer_activate_video(btv, &idle);
bttv_buffer_activate_vbi(btv, NULL);
bttv_set_dma(btv, 0, 0); bttv_set_dma(btv, 0, 0);
btwrite(0, BT848_INT_MASK); btwrite(0, BT848_INT_MASK);
spin_unlock_irqrestore(&btv->s_lock,flags); spin_unlock_irqrestore(&btv->s_lock,flags);
...@@ -3914,8 +3971,10 @@ static int bttv_resume(struct pci_dev *pci_dev) ...@@ -3914,8 +3971,10 @@ static int bttv_resume(struct pci_dev *pci_dev)
/* restart dma */ /* restart dma */
spin_lock_irqsave(&btv->s_lock,flags); spin_lock_irqsave(&btv->s_lock,flags);
btv->curr = btv->state.set; btv->curr = btv->state.video;
bttv_buffer_set_activate(btv, &btv->curr); btv->cvbi = btv->state.vbi;
bttv_buffer_activate_video(btv, &btv->curr);
bttv_buffer_activate_vbi(btv, btv->cvbi);
bttv_set_dma(btv, 0, btv->curr.irqflags); bttv_set_dma(btv, 0, btv->curr.irqflags);
spin_unlock_irqrestore(&btv->s_lock,flags); spin_unlock_irqrestore(&btv->s_lock,flags);
return 0; return 0;
......
...@@ -379,7 +379,7 @@ bttv_set_dma(struct bttv *btv, int override, int irqflags) ...@@ -379,7 +379,7 @@ bttv_set_dma(struct bttv *btv, int override, int irqflags)
btv->cap_ctl = 0; btv->cap_ctl = 0;
if (NULL != btv->curr.top) btv->cap_ctl |= 0x02; if (NULL != btv->curr.top) btv->cap_ctl |= 0x02;
if (NULL != btv->curr.bottom) btv->cap_ctl |= 0x01; if (NULL != btv->curr.bottom) btv->cap_ctl |= 0x01;
if (NULL != btv->curr.vbi) btv->cap_ctl |= 0x0c; if (NULL != btv->cvbi) btv->cap_ctl |= 0x0c;
capctl = 0; capctl = 0;
capctl |= (btv->cap_ctl & 0x03) ? 0x03 : 0x00; /* capture */ capctl |= (btv->cap_ctl & 0x03) ? 0x03 : 0x00; /* capture */
...@@ -389,9 +389,9 @@ bttv_set_dma(struct bttv *btv, int override, int irqflags) ...@@ -389,9 +389,9 @@ bttv_set_dma(struct bttv *btv, int override, int irqflags)
d2printk(KERN_DEBUG d2printk(KERN_DEBUG
"bttv%d: capctl=%x irq=%d top=%08Lx/%08Lx even=%08Lx/%08Lx\n", "bttv%d: capctl=%x irq=%d top=%08Lx/%08Lx even=%08Lx/%08Lx\n",
btv->c.nr,capctl,irqflags, btv->c.nr,capctl,irqflags,
btv->curr.vbi ? (unsigned long long)btv->curr.vbi->top.dma : 0, btv->cvbi ? (unsigned long long)btv->cvbi->top.dma : 0,
btv->curr.top ? (unsigned long long)btv->curr.top->top.dma : 0, btv->curr.top ? (unsigned long long)btv->curr.top->top.dma : 0,
btv->curr.vbi ? (unsigned long long)btv->curr.vbi->bottom.dma : 0, btv->cvbi ? (unsigned long long)btv->cvbi->bottom.dma : 0,
btv->curr.bottom ? (unsigned long long)btv->curr.bottom->bottom.dma : 0); btv->curr.bottom ? (unsigned long long)btv->curr.bottom->bottom.dma : 0);
cmd = BT848_RISC_JUMP; cmd = BT848_RISC_JUMP;
...@@ -399,6 +399,8 @@ bttv_set_dma(struct bttv *btv, int override, int irqflags) ...@@ -399,6 +399,8 @@ bttv_set_dma(struct bttv *btv, int override, int irqflags)
cmd |= BT848_RISC_IRQ; cmd |= BT848_RISC_IRQ;
cmd |= (irqflags & 0x0f) << 16; cmd |= (irqflags & 0x0f) << 16;
cmd |= (~irqflags & 0x0f) << 20; cmd |= (~irqflags & 0x0f) << 20;
}
if (irqflags || btv->cvbi) {
mod_timer(&btv->timeout, jiffies+BTTV_TIMEOUT); mod_timer(&btv->timeout, jiffies+BTTV_TIMEOUT);
} else { } else {
del_timer(&btv->timeout); del_timer(&btv->timeout);
...@@ -501,20 +503,26 @@ bttv_dma_free(struct bttv *btv, struct bttv_buffer *buf) ...@@ -501,20 +503,26 @@ bttv_dma_free(struct bttv *btv, struct bttv_buffer *buf)
} }
int int
bttv_buffer_set_activate(struct bttv *btv, bttv_buffer_activate_vbi(struct bttv *btv,
struct bttv_buffer_set *set) struct bttv_buffer *vbi)
{ {
/* vbi capture */ /* vbi capture */
if (set->vbi) { if (vbi) {
set->vbi->vb.state = STATE_ACTIVE; vbi->vb.state = STATE_ACTIVE;
list_del(&set->vbi->vb.queue); list_del(&vbi->vb.queue);
bttv_risc_hook(btv, RISC_SLOT_O_VBI, &set->vbi->top, 0); bttv_risc_hook(btv, RISC_SLOT_O_VBI, &vbi->top, 0);
bttv_risc_hook(btv, RISC_SLOT_E_VBI, &set->vbi->bottom, 0); bttv_risc_hook(btv, RISC_SLOT_E_VBI, &vbi->bottom, 4);
} else { } else {
bttv_risc_hook(btv, RISC_SLOT_O_VBI, NULL, 0); bttv_risc_hook(btv, RISC_SLOT_O_VBI, NULL, 0);
bttv_risc_hook(btv, RISC_SLOT_E_VBI, NULL, 0); bttv_risc_hook(btv, RISC_SLOT_E_VBI, NULL, 0);
} }
return 0;
}
int
bttv_buffer_activate_video(struct bttv *btv,
struct bttv_buffer_set *set)
{
/* video capture */ /* video capture */
if (NULL != set->top && NULL != set->bottom) { if (NULL != set->top && NULL != set->bottom) {
if (set->top == set->bottom) { if (set->top == set->bottom) {
......
...@@ -114,7 +114,10 @@ vbi_buffer_queue(struct file *file, struct videobuf_buffer *vb) ...@@ -114,7 +114,10 @@ vbi_buffer_queue(struct file *file, struct videobuf_buffer *vb)
dprintk("queue %p\n",vb); dprintk("queue %p\n",vb);
buf->vb.state = STATE_QUEUED; buf->vb.state = STATE_QUEUED;
list_add_tail(&buf->vb.queue,&btv->vcapture); list_add_tail(&buf->vb.queue,&btv->vcapture);
bttv_set_dma(btv,0x0c,1); if (NULL == btv->cvbi) {
fh->btv->curr.irqflags |= 4;
bttv_set_dma(btv,0x0c,fh->btv->curr.irqflags);
}
} }
static void vbi_buffer_release(struct file *file, struct videobuf_buffer *vb) static void vbi_buffer_release(struct file *file, struct videobuf_buffer *vb)
......
...@@ -124,6 +124,8 @@ ...@@ -124,6 +124,8 @@
#define BTTV_SIMUS_GVC1100 0x74 #define BTTV_SIMUS_GVC1100 0x74
#define BTTV_NGSTV_PLUS 0x75 #define BTTV_NGSTV_PLUS 0x75
#define BTTV_LMLBT4 0x76 #define BTTV_LMLBT4 0x76
#define BTTV_PICOLO_TETRA_CHIP 0x79
#define BTTV_AVDVBT_771 0x7b
/* i2c address list */ /* i2c address list */
#define I2C_TSA5522 0xc2 #define I2C_TSA5522 0xc2
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
#define _BTTVP_H_ #define _BTTVP_H_
#include <linux/version.h> #include <linux/version.h>
#define BTTV_VERSION_CODE KERNEL_VERSION(0,9,14) #define BTTV_VERSION_CODE KERNEL_VERSION(0,9,15)
#include <linux/types.h> #include <linux/types.h>
#include <linux/wait.h> #include <linux/wait.h>
...@@ -127,7 +127,6 @@ struct bttv_buffer { ...@@ -127,7 +127,6 @@ struct bttv_buffer {
struct bttv_buffer_set { struct bttv_buffer_set {
struct bttv_buffer *top; /* top field buffer */ struct bttv_buffer *top; /* top field buffer */
struct bttv_buffer *bottom; /* bottom field buffer */ struct bttv_buffer *bottom; /* bottom field buffer */
struct bttv_buffer *vbi; /* vbi buffer */
unsigned int irqflags; unsigned int irqflags;
unsigned int topirq; unsigned int topirq;
}; };
...@@ -197,8 +196,10 @@ int bttv_risc_hook(struct bttv *btv, int slot, struct btcx_riscmem *risc, ...@@ -197,8 +196,10 @@ int bttv_risc_hook(struct bttv *btv, int slot, struct btcx_riscmem *risc,
/* capture buffer handling */ /* capture buffer handling */
int bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf); int bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf);
int bttv_buffer_set_activate(struct bttv *btv, int bttv_buffer_activate_video(struct bttv *btv,
struct bttv_buffer_set *set); struct bttv_buffer_set *set);
int bttv_buffer_activate_vbi(struct bttv *btv,
struct bttv_buffer *vbi);
void bttv_dma_free(struct bttv *btv, struct bttv_buffer *buf); void bttv_dma_free(struct bttv *btv, struct bttv_buffer *buf);
/* overlay handling */ /* overlay handling */
...@@ -279,7 +280,8 @@ struct bttv_suspend_state { ...@@ -279,7 +280,8 @@ struct bttv_suspend_state {
u32 gpio_enable; u32 gpio_enable;
u32 gpio_data; u32 gpio_data;
int disabled; int disabled;
struct bttv_buffer_set set; struct bttv_buffer_set video;
struct bttv_buffer *vbi;
}; };
struct bttv { struct bttv {
...@@ -377,6 +379,7 @@ struct bttv { ...@@ -377,6 +379,7 @@ struct bttv {
struct list_head capture; /* video capture queue */ struct list_head capture; /* video capture queue */
struct list_head vcapture; /* vbi capture queue */ struct list_head vcapture; /* vbi capture queue */
struct bttv_buffer_set curr; /* active buffers */ struct bttv_buffer_set curr; /* active buffers */
struct bttv_buffer *cvbi; /* active vbi buffer */
int new_input; int new_input;
unsigned long cap_ctl; unsigned long cap_ctl;
......
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