/*
+ $Id: bttv-driver.c,v 1.34 2005/01/07 13:11:19 kraxel Exp $
+
bttv - Bt848 frame grabber driver
-
+
Copyright (C) 1996,97,98 Ralph Metzler <rjkm@thp.uni-koeln.de>
& Marcus Metzler <mocm@thp.uni-koeln.de>
(c) 1999-2002 Gerd Knorr <kraxel@bytesex.org>
-
+
some v4l2 code lines are taken from Justin's bttv2 driver which is
(c) 2000 Justin Schoeman <justin@suntiger.ee.up.ac.za>
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#include <linux/init.h>
#include <linux/module.h>
+#include <linux/moduleparam.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/fs.h>
static unsigned int irq_iswitch = 0;
/* API features (turn on/off stuff for testing) */
-static unsigned int v4l2 = 1;
+static unsigned int v4l2 = 1;
/* insmod args */
-MODULE_PARM(radio,"1-" __stringify(BTTV_MAX) "i");
+module_param(bttv_verbose, int, 0644);
+module_param(bttv_gpio, int, 0644);
+module_param(bttv_debug, int, 0644);
+module_param(irq_debug, int, 0644);
+module_param(debug_latency, int, 0644);
+
+module_param(fdsr, int, 0444);
+module_param(video_nr, int, 0444);
+module_param(radio_nr, int, 0444);
+module_param(vbi_nr, int, 0444);
+module_param(gbuffers, int, 0444);
+module_param(gbufsize, int, 0444);
+
+module_param(v4l2, int, 0644);
+module_param(bigendian, int, 0644);
+module_param(irq_iswitch, int, 0644);
+module_param(combfilter, int, 0444);
+module_param(lumafilter, int, 0444);
+module_param(automute, int, 0444);
+module_param(chroma_agc, int, 0444);
+module_param(adc_crush, int, 0444);
+module_param(whitecrush_upper, int, 0444);
+module_param(whitecrush_lower, int, 0444);
+module_param(vcr_hack, int, 0444);
+
+module_param_array(radio, int, NULL, 0444);
+
MODULE_PARM_DESC(radio,"The TV card supports radio, default is 0 (no)");
-MODULE_PARM(bigendian,"i");
MODULE_PARM_DESC(bigendian,"byte order of the framebuffer, default is native endian");
-MODULE_PARM(bttv_verbose,"i");
MODULE_PARM_DESC(bttv_verbose,"verbose startup messages, default is 1 (yes)");
-MODULE_PARM(bttv_gpio,"i");
MODULE_PARM_DESC(bttv_gpio,"log gpio changes, default is 0 (no)");
-MODULE_PARM(bttv_debug,"i");
MODULE_PARM_DESC(bttv_debug,"debug messages, default is 0 (no)");
-MODULE_PARM(irq_debug,"i");
MODULE_PARM_DESC(irq_debug,"irq handler debug messages, default is 0 (no)");
-MODULE_PARM(gbuffers,"i");
MODULE_PARM_DESC(gbuffers,"number of capture buffers. range 2-32, default 8");
-MODULE_PARM(gbufsize,"i");
MODULE_PARM_DESC(gbufsize,"size of the capture buffers, default is 0x208000");
-
-MODULE_PARM(video_nr,"i");
-MODULE_PARM(radio_nr,"i");
-MODULE_PARM(vbi_nr,"i");
-MODULE_PARM(debug_latency,"i");
-
-MODULE_PARM(fdsr,"i");
-
-MODULE_PARM(combfilter,"i");
-MODULE_PARM(lumafilter,"i");
-MODULE_PARM(automute,"i");
MODULE_PARM_DESC(automute,"mute audio on bad/missing video signal, default is 1 (yes)");
-MODULE_PARM(chroma_agc,"i");
MODULE_PARM_DESC(chroma_agc,"enables the AGC of chroma signal, default is 0 (no)");
-MODULE_PARM(adc_crush,"i");
MODULE_PARM_DESC(adc_crush,"enables the luminance ADC crush, default is 1 (yes)");
-MODULE_PARM(whitecrush_upper,"i");
MODULE_PARM_DESC(whitecrush_upper,"sets the white crush upper value, default is 207");
-MODULE_PARM(whitecrush_lower,"i");
MODULE_PARM_DESC(whitecrush_lower,"sets the white crush lower value, default is 127");
-MODULE_PARM(vcr_hack,"i");
MODULE_PARM_DESC(vcr_hack,"enables the VCR hack (improves synch on poor VCR tapes), default is 0 (no)");
-MODULE_PARM(irq_iswitch,"i");
MODULE_PARM_DESC(irq_iswitch,"switch inputs in irq handler");
-MODULE_PARM(v4l2,"i");
-
MODULE_DESCRIPTION("bttv - v4l/v4l2 driver module for bt848/878 based cards");
MODULE_AUTHOR("Ralph Metzler & Marcus Metzler & Gerd Knorr");
MODULE_LICENSE("GPL");
-/* kernel args */
-#ifndef MODULE
-static int __init p_radio(char *str) { return bttv_parse(str,BTTV_MAX,radio); }
-__setup("bttv.radio=", p_radio);
-#endif
-
/* ----------------------------------------------------------------------- */
/* sysfs */
.sheight = 576,
.totalwidth = 1135,
.adelay = 0x7f,
- .bdelay = 0x72,
+ .bdelay = 0x72,
.iform = (BT848_IFORM_PAL_BDGHI|BT848_IFORM_XT1),
.scaledtwidth = 1135,
.hdelayx1 = 186,
.sram = -1,
}
};
-const unsigned int BTTV_TVNORMS = ARRAY_SIZE(bttv_tvnorms);
+static const unsigned int BTTV_TVNORMS = ARRAY_SIZE(bttv_tvnorms);
/* ----------------------------------------------------------------------- */
/* bttv format list
packed pixel formats must come first */
-const struct bttv_format bttv_formats[] = {
+static const struct bttv_format bttv_formats[] = {
{
.name = "8 bpp, gray",
.palette = VIDEO_PALETTE_GREY,
.flags = FORMAT_FLAGS_RAW,
}
};
-const unsigned int BTTV_FORMATS = ARRAY_SIZE(bttv_formats);
+static const unsigned int BTTV_FORMATS = ARRAY_SIZE(bttv_formats);
/* ----------------------------------------------------------------------- */
}
};
-const int BTTV_CTLS = ARRAY_SIZE(bttv_ctls);
+static const int BTTV_CTLS = ARRAY_SIZE(bttv_ctls);
/* ----------------------------------------------------------------------- */
/* resource management */
/* ----------------------------------------------------------------------- */
/* If Bt848a or Bt849, use PLL for PAL/SECAM and crystal for NTSC */
-/* Frequency = (F_input / PLL_X) * PLL_I.PLL_F/PLL_C
- PLL_X = Reference pre-divider (0=1, 1=2)
+/* Frequency = (F_input / PLL_X) * PLL_I.PLL_F/PLL_C
+ PLL_X = Reference pre-divider (0=1, 1=2)
PLL_C = Post divider (0=6, 1=4)
- PLL_I = Integer input
- PLL_F = Fractional input
-
- F_input = 28.636363 MHz:
+ PLL_I = Integer input
+ PLL_F = Fractional input
+
+ F_input = 28.636363 MHz:
PAL (CLKx2 = 35.46895 MHz): PLL_X = 1, PLL_I = 0x0E, PLL_F = 0xDCF9, PLL_C = 0
*/
static void set_pll_freq(struct bttv *btv, unsigned int fin, unsigned int fout)
{
unsigned char fl, fh, fi;
-
+
/* prevent overflows */
fin/=4;
fout/=4;
for (i=0; i<10; i++) {
/* Let other people run while the PLL stabilizes */
vprintk(".");
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(HZ/50);
-
+ msleep(10);
+
if (btread(BT848_DSTATUS) & BT848_DSTATUS_PLOCK) {
btwrite(0,BT848_DSTATUS);
} else {
}
/* used to switch between the bt848's analog/digital video capture modes */
-void bt848A_set_timing(struct bttv *btv)
+static void bt848A_set_timing(struct bttv *btv)
{
int i, len;
int table_idx = bttv_tvnorms[btv->tvnorm].sram;
static void bt848_hue(struct bttv *btv, int hue)
{
int value;
-
+
btv->hue = hue;
/* -128 to 127 */
static void bt848_contrast(struct bttv *btv, int cont)
{
int value,hibit;
-
+
btv->contrast = cont;
-
+
/* 0-511 */
value = (cont >> 7);
hibit = (value >> 6) & 4;
static void bt848_sat(struct bttv *btv, int color)
{
int val_u,val_v,hibits;
-
+
btv->saturation = color;
/* 0-511 for the color */
set_input(struct bttv *btv, unsigned int input)
{
unsigned long flags;
-
+
btv->input = input;
if (irq_iswitch) {
spin_lock_irqsave(&btv->s_lock,flags);
- if (btv->curr.irqflags) {
+ if (btv->curr.frame_irq) {
/* active capture -> delayed input switch */
btv->new_input = input;
} else {
audio_mux(btv,(input == bttv_tvcards[btv->c.type].tuner ?
AUDIO_TUNER : AUDIO_EXTERN));
set_tvnorm(btv,btv->tvnorm);
+ i2c_vidiocschan(btv);
}
static void init_irqreg(struct bttv *btv)
static void init_bt848(struct bttv *btv)
{
int val;
-
+
if (bttv_tvcards[btv->c.type].no_video) {
/* very basic init only */
init_irqreg(btv);
BT848_GPIO_DMA_CTL_PLTP1_16|
BT848_GPIO_DMA_CTL_PLTP23_16|
BT848_GPIO_DMA_CTL_GPINTC|
- BT848_GPIO_DMA_CTL_GPINTI,
+ BT848_GPIO_DMA_CTL_GPINTI,
BT848_GPIO_DMA_CTL);
val = btv->opt_chroma_agc ? BT848_SCLOOP_CAGC : 0;
init_irqreg(btv);
}
-void bttv_reinit_bt848(struct bttv *btv)
+static void bttv_reinit_bt848(struct bttv *btv)
{
unsigned long flags;
printk(KERN_INFO "bttv%d: reset, reinitialize\n",btv->c.nr);
spin_lock_irqsave(&btv->s_lock,flags);
btv->errors=0;
- bttv_set_dma(btv,0,0);
+ bttv_set_dma(btv,0);
spin_unlock_irqrestore(&btv->s_lock,flags);
init_bt848(btv);
{
struct video_audio va;
int i;
-
+
for (i = 0; i < BTTV_CTLS; i++)
if (bttv_ctls[i].id == c->id)
break;
btv->c.nr,outbits,data & outbits, data & ~outbits, comment);
}
-void bttv_field_count(struct bttv *btv)
+static void bttv_field_count(struct bttv *btv)
{
int need_count = 0;
spin_lock_irqsave(&btv->s_lock,flags);
old = btv->screen;
btv->screen = new;
- btv->curr.irqflags |= 1;
- bttv_set_dma(btv, 0x03, btv->curr.irqflags);
+ btv->loop_irq |= 1;
+ bttv_set_dma(btv, 0x03);
spin_unlock_irqrestore(&btv->s_lock,flags);
if (NULL == new)
free_btres(btv,fh,RESOURCE_OVERLAY);
{
int redo_dma_risc = 0;
int rc;
-
+
/* check settings */
if (NULL == fmt)
return -EINVAL;
if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size)
return -EINVAL;
}
-
+
/* alloc + fill struct bttv_buffer (if changed) */
if (buf->vb.width != width || buf->vb.height != height ||
buf->vb.field != field ||
}
static int
-buffer_setup(struct file *file, unsigned int *count, unsigned int *size)
+buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
{
- struct bttv_fh *fh = file->private_data;
-
+ struct bttv_fh *fh = q->priv_data;
+
*size = fh->fmt->depth*fh->width*fh->height >> 3;
if (0 == *count)
*count = gbuffers;
}
static int
-buffer_prepare(struct file *file, struct videobuf_buffer *vb,
+buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
enum v4l2_field field)
{
- struct bttv_buffer *buf = (struct bttv_buffer*)vb;
- struct bttv_fh *fh = file->private_data;
+ struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
+ struct bttv_fh *fh = q->priv_data;
return bttv_prepare_buffer(fh->btv, buf, fh->fmt,
fh->width, fh->height, field);
}
static void
-buffer_queue(struct file *file, struct videobuf_buffer *vb)
+buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
{
- struct bttv_buffer *buf = (struct bttv_buffer*)vb;
- struct bttv_fh *fh = file->private_data;
+ struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
+ struct bttv_fh *fh = q->priv_data;
+ struct bttv *btv = fh->btv;
buf->vb.state = STATE_QUEUED;
- list_add_tail(&buf->vb.queue,&fh->btv->capture);
- fh->btv->curr.irqflags |= 1;
- bttv_set_dma(fh->btv, 0x03, fh->btv->curr.irqflags);
+ list_add_tail(&buf->vb.queue,&btv->capture);
+ if (!btv->curr.frame_irq) {
+ btv->loop_irq |= 1;
+ bttv_set_dma(btv, 0x03);
+ }
}
-static void buffer_release(struct file *file, struct videobuf_buffer *vb)
+static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
{
- struct bttv_buffer *buf = (struct bttv_buffer*)vb;
- struct bttv_fh *fh = file->private_data;
+ struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
+ struct bttv_fh *fh = q->priv_data;
bttv_dma_free(fh->btv,buf);
}
"SMICROCODE", "GVBIFMT", "SVBIFMT" };
#define V4L1_IOCTLS ARRAY_SIZE(v4l1_ioctls)
-int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
+static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
{
switch (cmd) {
case BTTV_VERSION:
case VIDIOCGTUNER:
{
struct video_tuner *v = arg;
-
+
if (UNSET == bttv_tvcards[btv->c.type].tuner)
return -EINVAL;
if (v->tuner) /* Only tuner 0 */
up(&btv->lock);
return 0;
}
-
+
case VIDIOCGCHAN:
{
struct video_channel *v = arg;
/* card specific hooks */
if (btv->audio_hook)
btv->audio_hook(btv,v,1);
-
+
up(&btv->lock);
return 0;
}
{
struct v4l2_standard *e = arg;
unsigned int index = e->index;
-
+
if (index >= BTTV_TVNORMS)
return -EINVAL;
v4l2_video_std_construct(e, bttv_tvnorms[e->index].v4l2_id,
case VIDIOC_QUERYSTD:
{
v4l2_std_id *id = arg;
-
+
if (btread(BT848_DSTATUS) & BT848_DSTATUS_NUML)
*id = V4L2_STD_625_50;
else
{
struct v4l2_input *i = arg;
unsigned int n;
-
+
n = i->index;
if (n >= bttv_tvcards[btv->c.type].video_inputs)
return -EINVAL;
case VIDIOC_S_INPUT:
{
unsigned int *i = arg;
-
+
if (*i > bttv_tvcards[btv->c.type].video_inputs)
return -EINVAL;
down(&btv->lock);
set_input(btv,*i);
- i2c_vidiocschan(btv);
up(&btv->lock);
return 0;
}
-
+
case VIDIOC_G_TUNER:
{
struct v4l2_tuner *t = arg;
default:
return -ENOIOCTLCMD;
-
+
}
return 0;
}
default:
BUG();
}
-
+
down(&fh->cap.lock);
if (fh->ov.clips)
kfree(fh->ov.clips);
fh->ov.clips = clips;
fh->ov.nclips = n;
-
+
fh->ov.w = win->w;
fh->ov.field = win->field;
fh->ov.setup_ok = 1;
btv->init.ov.w.width = win->w.width;
btv->init.ov.w.height = win->w.height;
btv->init.ov.field = win->field;
-
+
/* update overlay if needed */
retval = 0;
if (check_btres(fh, RESOURCE_OVERLAY)) {
struct bttv_buffer *new;
-
+
new = videobuf_alloc(sizeof(*new));
bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
retval = bttv_switch_overlay(btv,fh,new);
static struct videobuf_queue* bttv_queue(struct bttv_fh *fh)
{
struct videobuf_queue* q = NULL;
-
+
switch (fh->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
q = &fh->cap;
static int bttv_resource(struct bttv_fh *fh)
{
int res = 0;
-
+
switch (fh->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
res = RESOURCE_VIDEO;
(f->fmt.pix.width * fmt->depth) >> 3;
f->fmt.pix.sizeimage =
f->fmt.pix.height * f->fmt.pix.bytesperline;
-
+
return 0;
}
case V4L2_BUF_TYPE_VIDEO_OVERLAY:
struct v4l2_format *f)
{
int retval;
-
+
switch (f->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
{
if (0 != retval)
return retval;
fmt = format_by_fourcc(f->fmt.pix.pixelformat);
-
+
/* update our state informations */
down(&fh->cap.lock);
fh->fmt = fmt;
btv->init.width = f->fmt.pix.width;
btv->init.height = f->fmt.pix.height;
up(&fh->cap.lock);
-
+
return 0;
}
case V4L2_BUF_TYPE_VIDEO_OVERLAY:
if (btv->errors)
bttv_reinit_bt848(btv);
-#ifdef VIDIOC_G_PRIORITY
switch (cmd) {
case VIDIOCSFREQ:
case VIDIOCSTUNER:
if (0 != retval)
return retval;
};
-#endif
+
switch (cmd) {
/* *** v4l1 *** ************************************************ */
{
struct video_picture *pic = arg;
const struct bttv_format *fmt;
-
+
fmt = format_by_palette(pic->palette);
if (NULL == fmt)
return -EINVAL;
if (!check_alloc_btres(btv,fh,RESOURCE_OVERLAY))
return -EBUSY;
-
+
down(&fh->cap.lock);
if (*on) {
fh->ov.tvnorm = btv->tvnorm;
unsigned int i;
down(&fh->cap.lock);
- retval = videobuf_mmap_setup(file,&fh->cap,gbuffers,gbufsize,
+ retval = videobuf_mmap_setup(&fh->cap,gbuffers,gbufsize,
V4L2_MEMORY_MMAP);
if (retval < 0)
goto fh_unlock_and_return;
if (buf->vb.state == STATE_QUEUED ||
buf->vb.state == STATE_ACTIVE)
goto fh_unlock_and_return;
-
+
field = (vm->height > bttv_tvnorms[btv->tvnorm].sheight/2)
? V4L2_FIELD_INTERLACED
: V4L2_FIELD_BOTTOM;
if (0 != retval)
goto fh_unlock_and_return;
spin_lock_irqsave(&btv->s_lock,flags);
- buffer_queue(file,&buf->vb);
+ buffer_queue(&fh->cap,&buf->vb);
spin_unlock_irqrestore(&btv->s_lock,flags);
up(&fh->cap.lock);
return 0;
V4L2_CAP_VIDEO_CAPTURE |
V4L2_CAP_VIDEO_OVERLAY |
V4L2_CAP_VBI_CAPTURE |
- V4L2_CAP_TUNER |
- V4L2_CAP_READWRITE |
+ V4L2_CAP_READWRITE |
V4L2_CAP_STREAMING;
+ if (bttv_tvcards[btv->c.type].tuner != UNSET &&
+ bttv_tvcards[btv->c.type].tuner != TUNER_ABSENT)
+ cap->capabilities |= V4L2_CAP_TUNER;
return 0;
}
{
struct v4l2_framebuffer *fb = arg;
const struct bttv_format *fmt;
-
+
if(!capable(CAP_SYS_ADMIN) &&
!capable(CAP_SYS_RAWIO))
return -EPERM;
btv->fbuf.fmt.bytesperline = fb->fmt.bytesperline;
else
btv->fbuf.fmt.bytesperline = btv->fbuf.fmt.width*fmt->depth/8;
-
+
retval = 0;
fh->ovfmt = fmt;
btv->init.ovfmt = fmt;
if (check_btres(fh, RESOURCE_OVERLAY)) {
struct bttv_buffer *new;
-
+
new = videobuf_alloc(sizeof(*new));
bttv_overlay_risc(btv,&fh->ov,fh->ovfmt,new);
retval = bttv_switch_overlay(btv,fh,new);
}
case VIDIOC_REQBUFS:
- return videobuf_reqbufs(file,bttv_queue(fh),arg);
+ return videobuf_reqbufs(bttv_queue(fh),arg);
case VIDIOC_QUERYBUF:
return videobuf_querybuf(bttv_queue(fh),arg);
case VIDIOC_QBUF:
- return videobuf_qbuf(file,bttv_queue(fh),arg);
+ return videobuf_qbuf(bttv_queue(fh),arg);
case VIDIOC_DQBUF:
- return videobuf_dqbuf(file,bttv_queue(fh),arg);
+ return videobuf_dqbuf(bttv_queue(fh),arg,
+ file->f_flags & O_NONBLOCK);
case VIDIOC_STREAMON:
{
if (!check_alloc_btres(btv,fh,res))
return -EBUSY;
- return videobuf_streamon(file,bttv_queue(fh));
+ return videobuf_streamon(bttv_queue(fh));
}
case VIDIOC_STREAMOFF:
{
int res = bttv_resource(fh);
- retval = videobuf_streamoff(file,bttv_queue(fh));
+ retval = videobuf_streamoff(bttv_queue(fh));
if (retval < 0)
return retval;
free_btres(btv,fh,res);
return 0;
}
-#ifdef VIDIOC_G_PRIORITY
case VIDIOC_G_PRIORITY:
{
enum v4l2_priority *p = arg;
return v4l2_prio_change(&btv->prio, &fh->prio, *prio);
}
-#endif
-
case VIDIOC_ENUMSTD:
case VIDIOC_G_STD:
case VIDIOC_S_STD:
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
if (locked_btres(fh->btv,RESOURCE_VIDEO))
return -EBUSY;
- retval = videobuf_read_one(file, &fh->cap, data, count, ppos);
+ retval = videobuf_read_one(&fh->cap, data, count, ppos,
+ file->f_flags & O_NONBLOCK);
break;
case V4L2_BUF_TYPE_VBI_CAPTURE:
if (!check_alloc_btres(fh->btv,fh,RESOURCE_VBI))
return -EBUSY;
- retval = videobuf_read_stream(file, &fh->vbi, data, count, ppos, 1);
+ retval = videobuf_read_stream(&fh->vbi, data, count, ppos, 1,
+ file->f_flags & O_NONBLOCK);
break;
default:
BUG();
if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) {
if (!check_alloc_btres(fh->btv,fh,RESOURCE_VBI))
- return -EBUSY;
+ return POLLERR;
return videobuf_poll_stream(file, &fh->vbi, wait);
}
}
fh->cap.read_buf->memory = V4L2_MEMORY_USERPTR;
field = videobuf_next_field(&fh->cap);
- if (0 != fh->cap.ops->buf_prepare(file,fh->cap.read_buf,field)) {
+ if (0 != fh->cap.ops->buf_prepare(&fh->cap,fh->cap.read_buf,field)) {
up(&fh->cap.lock);
return POLLERR;
}
- fh->cap.ops->buf_queue(file,fh->cap.read_buf);
+ fh->cap.ops->buf_queue(&fh->cap,fh->cap.read_buf);
fh->cap.read_off = 0;
}
up(&fh->cap.lock);
buf = (struct bttv_buffer*)fh->cap.read_buf;
}
-
+
poll_wait(file, &buf->vb.done, wait);
if (buf->vb.state == STATE_DONE ||
buf->vb.state == STATE_ERROR)
*fh = btv->init;
fh->type = type;
fh->ov.setup_ok = 0;
-#ifdef VIDIOC_G_PRIORITY
v4l2_prio_open(&btv->prio,&fh->prio);
-#endif
videobuf_queue_init(&fh->cap, &bttv_video_qops,
btv->c.pci, &btv->s_lock,
V4L2_BUF_TYPE_VIDEO_CAPTURE,
V4L2_FIELD_INTERLACED,
- sizeof(struct bttv_buffer));
+ sizeof(struct bttv_buffer),
+ fh);
videobuf_queue_init(&fh->vbi, &bttv_vbi_qops,
btv->c.pci, &btv->s_lock,
V4L2_BUF_TYPE_VBI_CAPTURE,
V4L2_FIELD_SEQ_TB,
- sizeof(struct bttv_buffer));
+ sizeof(struct bttv_buffer),
+ fh);
i2c_vidiocschan(btv);
btv->users++;
/* turn off overlay */
if (check_btres(fh, RESOURCE_OVERLAY))
bttv_switch_overlay(btv,fh,NULL);
-
+
/* stop video capture */
if (check_btres(fh, RESOURCE_VIDEO)) {
- videobuf_streamoff(file,&fh->cap);
+ videobuf_streamoff(&fh->cap);
free_btres(btv,fh,RESOURCE_VIDEO);
}
if (fh->cap.read_buf) {
- buffer_release(file,fh->cap.read_buf);
+ buffer_release(&fh->cap,fh->cap.read_buf);
kfree(fh->cap.read_buf);
}
/* stop vbi capture */
if (check_btres(fh, RESOURCE_VBI)) {
if (fh->vbi.streaming)
- videobuf_streamoff(file,&fh->vbi);
+ videobuf_streamoff(&fh->vbi);
if (fh->vbi.reading)
- videobuf_read_stop(file,&fh->vbi);
+ videobuf_read_stop(&fh->vbi);
free_btres(btv,fh,RESOURCE_VBI);
}
-#ifdef VIDIOC_G_PRIORITY
+ /* free stuff */
+ videobuf_mmap_free(&fh->cap);
+ videobuf_mmap_free(&fh->vbi);
v4l2_prio_close(&btv->prio,&fh->prio);
-#endif
file->private_data = NULL;
kfree(fh);
dprintk("bttv%d: mmap type=%s 0x%lx+%ld\n",
fh->btv->c.nr, v4l2_type_names[fh->type],
vma->vm_start, vma->vm_end - vma->vm_start);
- return videobuf_mmap_mapper(vma,bttv_queue(fh));
+ return videobuf_mmap_mapper(bttv_queue(fh),vma);
}
static struct file_operations bttv_fops =
.minor = -1,
};
-struct video_device bttv_vbi_template =
+static struct video_device bttv_vbi_template =
{
.name = "bt848/878 vbi",
.type = VID_TYPE_TUNER|VID_TYPE_TELETEXT,
case VIDIOCSTUNER:
/* nothing to do */
return 0;
-
+
case BTTV_VERSION:
case VIDIOCGFREQ:
case VIDIOCSFREQ:
static void bttv_print_irqbits(u32 print, u32 mark)
{
unsigned int i;
-
+
printk("bits:");
for (i = 0; i < ARRAY_SIZE(irq_name); i++) {
if (print & (1 << i))
/* capture request ? */
if (!list_empty(&btv->capture)) {
- set->irqflags = 1;
+ set->frame_irq = 1;
item = list_entry(btv->capture.next, struct bttv_buffer, vb.queue);
if (V4L2_FIELD_HAS_TOP(item->vb.field))
set->top = item;
set->bottom = item;
}
if (NULL != set->top && NULL != set->bottom)
- set->topirq = 2;
+ set->top_irq = 2;
}
}
}
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);
+ btv->screen,set->frame_irq,set->top_irq);
return 0;
}
struct bttv_buffer *ovbi;
struct bttv_buffer *item;
unsigned long flags;
-
+
if (bttv_verbose) {
printk(KERN_INFO "bttv%d: timeout: drop=%d irq=%d/%d, risc=%08x, ",
btv->c.nr, btv->framedrop, btv->irq_me, btv->irq_total,
}
spin_lock_irqsave(&btv->s_lock,flags);
-
+
/* deactivate stuff */
memset(&new,0,sizeof(new));
old = btv->curr;
ovbi = btv->cvbi;
btv->curr = new;
btv->cvbi = NULL;
+ btv->loop_irq = 0;
bttv_buffer_activate_video(btv, &new);
bttv_buffer_activate_vbi(btv, NULL);
- bttv_set_dma(btv, 0, 0);
+ bttv_set_dma(btv, 0);
/* wake up */
bttv_irq_wakeup_video(btv, &old, &new, STATE_ERROR);
item->vb.state = STATE_ERROR;
wake_up(&item->vb.done);
}
-
+
btv->errors++;
spin_unlock_irqrestore(&btv->s_lock,flags);
}
return;
spin_lock(&btv->s_lock);
- btv->curr.topirq = 0;
+ btv->curr.top_irq = 0;
btv->curr.top = NULL;
bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);
spin_unlock(&btv->s_lock);
return;
}
-
+
/* switch over */
old = btv->curr;
btv->curr = new;
+ btv->loop_irq &= ~1;
bttv_buffer_activate_video(btv, &new);
- bttv_set_dma(btv, 0, new.irqflags);
+ bttv_set_dma(btv, 0);
/* switch input */
if (UNSET != btv->new_input) {
/* switch */
btv->cvbi = new;
+ btv->loop_irq &= ~4;
bttv_buffer_activate_vbi(btv, new);
- bttv_set_dma(btv, 0, btv->curr.irqflags);
+ bttv_set_dma(btv, 0);
bttv_irq_wakeup_vbi(btv, old, STATE_DONE);
spin_unlock(&btv->s_lock);
printk("\n");
}
- if (astat&BT848_INT_VSYNC)
+ if (astat&BT848_INT_VSYNC)
btv->field_count++;
if (astat & BT848_INT_GPINT) {
count++;
if (count > 4) {
btwrite(0, BT848_INT_MASK);
- printk(KERN_ERR
+ printk(KERN_ERR
"bttv%d: IRQ lockup, cleared int mask [", btv->c.nr);
bttv_print_irqbits(stat,astat);
printk("]\n");
{
#if defined(__powerpc__)
unsigned int cmd;
-
+
pci_read_config_dword(dev, PCI_COMMAND, &cmd);
- cmd = (cmd | PCI_COMMAND_MEMORY );
+ cmd = (cmd | PCI_COMMAND_MEMORY );
pci_write_config_dword(dev, PCI_COMMAND, cmd);
#endif
}
/* initialize structs / fill in defaults */
init_MUTEX(&btv->lock);
init_MUTEX(&btv->reslock);
- btv->s_lock = SPIN_LOCK_UNLOCKED;
- btv->gpio_lock = SPIN_LOCK_UNLOCKED;
+ spin_lock_init(&btv->s_lock);
+ spin_lock_init(&btv->gpio_lock);
init_waitqueue_head(&btv->gpioq);
init_waitqueue_head(&btv->i2c_queue);
INIT_LIST_HEAD(&btv->c.subs);
INIT_LIST_HEAD(&btv->capture);
INIT_LIST_HEAD(&btv->vcapture);
-#ifdef VIDIOC_G_PRIORITY
v4l2_prio_init(&btv->prio);
-#endif
init_timer(&btv->timeout);
btv->timeout.function = bttv_irq_timeout;
btv->timeout.data = (unsigned long)btv;
-
+
btv->i2c_rc = -1;
btv->tuner_type = UNSET;
btv->pinnacle_id = UNSET;
btv->new_input = UNSET;
btv->gpioirq = 1;
btv->has_radio=radio[btv->c.nr];
-
+
/* pci stuff (init, get irq/mmio, ... */
btv->c.pci = dev;
btv->id = dev->device;
printk("irq: %d, latency: %d, mmio: 0x%lx\n",
btv->c.pci->irq, lat, pci_resource_start(dev,0));
schedule();
-
+
btv->bt848_mmio=ioremap(pci_resource_start(dev,0), 0x1000);
if (NULL == ioremap(pci_resource_start(dev,0), 0x1000)) {
printk("bttv%d: ioremap() failed\n", btv->c.nr);
btv->opt_vcr_hack = vcr_hack;
btv->opt_whitecrush_upper = whitecrush_upper;
btv->opt_whitecrush_lower = whitecrush_lower;
-
+
/* fill struct bttv with some useful defaults */
btv->init.btv = btv;
btv->init.ov.w.width = 320;
fail2:
free_irq(btv->c.pci->irq,btv);
-
+
fail1:
if (btv->bt848_mmio)
iounmap(btv->bt848_mmio);
btv->shutdown=1;
wake_up(&btv->gpioq);
bttv_sub_del_devices(&btv->c);
-
+
/* unregister i2c_bus + input */
fini_bttv_i2c(btv);
struct bttv_buffer_set idle;
unsigned long flags;
- printk("bttv%d: suspend %d\n", btv->c.nr, state);
+ dprintk("bttv%d: suspend %d\n", btv->c.nr, state);
/* stop dma + irqs */
spin_lock_irqsave(&btv->s_lock,flags);
memset(&idle, 0, sizeof(idle));
btv->state.video = btv->curr;
btv->state.vbi = btv->cvbi;
+ btv->state.loop_irq = btv->loop_irq;
btv->curr = idle;
+ btv->loop_irq = 0;
bttv_buffer_activate_video(btv, &idle);
bttv_buffer_activate_vbi(btv, NULL);
- bttv_set_dma(btv, 0, 0);
+ bttv_set_dma(btv, 0);
btwrite(0, BT848_INT_MASK);
spin_unlock_irqrestore(&btv->s_lock,flags);
btv->state.gpio_data = gpio_read();
/* save pci state */
- pci_save_state(pci_dev, btv->state.pci_cfg);
- if (0 != pci_set_power_state(pci_dev, state)) {
+ pci_save_state(pci_dev);
+ if (0 != pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state))) {
pci_disable_device(pci_dev);
btv->state.disabled = 1;
}
struct bttv *btv = pci_get_drvdata(pci_dev);
unsigned long flags;
- printk("bttv%d: resume\n", btv->c.nr);
+ dprintk("bttv%d: resume\n", btv->c.nr);
/* restore pci state */
if (btv->state.disabled) {
pci_enable_device(pci_dev);
btv->state.disabled = 0;
}
- pci_set_power_state(pci_dev, 0);
- pci_restore_state(pci_dev, btv->state.pci_cfg);
+ pci_set_power_state(pci_dev, PCI_D0);
+ pci_restore_state(pci_dev);
/* restore bt878 state */
bttv_reinit_bt848(btv);
spin_lock_irqsave(&btv->s_lock,flags);
btv->curr = btv->state.video;
btv->cvbi = btv->state.vbi;
+ btv->loop_irq = btv->state.loop_irq;
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);
spin_unlock_irqrestore(&btv->s_lock,flags);
return 0;
}
.id_table = bttv_pci_tbl,
.probe = bttv_probe,
.remove = __devexit_p(bttv_remove),
-
- .suspend = bttv_suspend,
- .resume = bttv_resume,
+ .suspend = bttv_suspend,
+ .resume = bttv_resume,
};
static int bttv_init_module(void)
{
- int rc;
bttv_num = 0;
printk(KERN_INFO "bttv: driver version %d.%d.%d loaded\n",
bttv_check_chipset();
bus_register(&bttv_sub_bus_type);
- rc = pci_module_init(&bttv_pci_driver);
- if (-ENODEV == rc) {
- /* plenty of people trying to use bttv for the cx2388x ... */
- if (NULL != pci_find_device(0x14f1, 0x8800, NULL))
- printk("bttv doesn't support your Conexant 2388x card.\n");
- }
- return rc;
+ return pci_module_init(&bttv_pci_driver);
}
static void bttv_cleanup_module(void)