init_irqreg(btv);
}
-extern void bttv_reinit_bt848(struct bttv *btv)
+void bttv_reinit_bt848(struct bttv *btv)
{
unsigned long flags;
spin_lock_irqsave(&btv->s_lock,flags);
old = btv->screen;
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);
if (NULL == new)
free_btres(btv,fh,RESOURCE_OVERLAY);
buf->vb.state = STATE_QUEUED;
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)
w2.w.width = win->width;
w2.w.height = win->height;
w2.clipcount = win->clipcount;
- w2.clips = (struct v4l2_clip*)win->clips;
+ w2.clips = (struct v4l2_clip __user *)win->clips;
retval = setup_window(fh, btv, &w2, 0);
if (0 == retval) {
/* on v4l1 this ioctl affects the read() size too */
}
}
-static ssize_t bttv_read(struct file *file, char *data,
+static ssize_t bttv_read(struct file *file, char __user *data,
size_t count, loff_t *ppos)
{
struct bttv_fh *fh = file->private_data;
printk(" main: %08Lx\n",
(unsigned long long)btv->main.dma);
printk(" vbi : o=%08Lx e=%08Lx\n",
- btv->curr.vbi ? (unsigned long long)btv->curr.vbi->top.dma : 0,
- btv->curr.vbi ? (unsigned long long)btv->curr.vbi->bottom.dma : 0);
+ btv->cvbi ? (unsigned long long)btv->cvbi->top.dma : 0,
+ btv->cvbi ? (unsigned long long)btv->cvbi->bottom.dma : 0);
printk(" cap : o=%08Lx e=%08Lx\n",
btv->curr.top ? (unsigned long long)btv->curr.top->top.dma : 0,
btv->curr.bottom ? (unsigned long long)btv->curr.bottom->bottom.dma : 0);
if (0 == (btread(BT848_DSTATUS) & BT848_DSTATUS_HLOC)) {
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);
return;
}
}
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;
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 ? */
if (!list_empty(&btv->capture)) {
set->irqflags = 1;
}
}
- dprintk("bttv%d: next set: top=%p bottom=%p vbi=%p "
- "[screen=%p,irq=%d,%d]\n",
- btv->c.nr,set->top, set->bottom, set->vbi,
+ dprintk("bttv%d: next set: top=%p bottom=%p [screen=%p,irq=%d,%d]\n",
+ btv->c.nr,set->top, set->bottom,
btv->screen,set->irqflags,set->topirq);
return 0;
}
static void
-bttv_irq_wakeup_set(struct bttv *btv, struct bttv_buffer_set *wakeup,
- struct bttv_buffer_set *curr, unsigned int state)
+bttv_irq_wakeup_video(struct bttv *btv, struct bttv_buffer_set *wakeup,
+ struct bttv_buffer_set *curr, unsigned int state)
{
struct timeval 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 (NULL != wakeup->top && curr->top != wakeup->top) {
if (irq_debug > 1)
}
}
+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)
{
struct bttv *btv = (struct bttv *)data;
struct bttv_buffer_set old,new;
+ struct bttv_buffer *ovbi;
struct bttv_buffer *item;
unsigned long flags;
/* deactivate stuff */
memset(&new,0,sizeof(new));
- old = btv->curr;
+ old = btv->curr;
+ ovbi = btv->cvbi;
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);
/* 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 */
while (!list_empty(&btv->capture)) {
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
-bttv_irq_switch_fields(struct bttv *btv)
+bttv_irq_switch_video(struct bttv *btv)
{
struct bttv_buffer_set new;
struct bttv_buffer_set old;
spin_lock(&btv->s_lock);
/* new buffer set */
- bttv_irq_next_set(btv, &new);
+ bttv_irq_next_video(btv, &new);
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++;
if (debug_latency)
bttv_irq_debug_low_latency(btv, rc);
/* switch over */
old = btv->curr;
btv->curr = new;
- bttv_buffer_set_activate(btv, &new);
+ bttv_buffer_activate_video(btv, &new);
bttv_set_dma(btv, 0, new.irqflags);
/* switch input */
}
/* 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);
}
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)))
bttv_irq_wakeup_top(btv);
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)
audio_mux(btv, -1);
/* stop dma + irqs */
spin_lock_irqsave(&btv->s_lock,flags);
memset(&idle, 0, sizeof(idle));
- btv->state.set = btv->curr;
+ btv->state.video = btv->curr;
+ btv->state.vbi = btv->cvbi;
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);
btwrite(0, BT848_INT_MASK);
spin_unlock_irqrestore(&btv->s_lock,flags);
/* restart dma */
spin_lock_irqsave(&btv->s_lock,flags);
- btv->curr = btv->state.set;
- bttv_buffer_set_activate(btv, &btv->curr);
+ btv->curr = btv->state.video;
+ 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);
spin_unlock_irqrestore(&btv->s_lock,flags);
return 0;