diff options
Diffstat (limited to 'drivers/media/video/bt8xx/bttv-driver.c')
-rw-r--r-- | drivers/media/video/bt8xx/bttv-driver.c | 2374 |
1 files changed, 993 insertions, 1381 deletions
diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index 581a3c955739..907dc62c1783 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c @@ -9,6 +9,12 @@ some v4l2 code lines are taken from Justin's bttv2 driver which is (c) 2000 Justin Schoeman <justin@suntiger.ee.up.ac.za> + V4L1 removal from: + (c) 2005-2006 Nickolay V. Shmyrev <nshmyrev@yandex.ru> + + Fixes to be fully V4L2 compliant by + (c) 2006 Mauro Carvalho Chehab <mchehab@infradead.org> + Cropping and overscan support Copyright (C) 2005, 2006 Michael H. Schimek <mschimek@gmx.at> Sponsored by OPQ Systems AB @@ -157,7 +163,7 @@ MODULE_LICENSE("GPL"); static ssize_t show_card(struct device *cd, struct device_attribute *attr, char *buf) { - struct video_device *vfd = to_video_device(cd); + struct video_device *vfd = container_of(cd, struct video_device, class_dev); struct bttv *btv = dev_get_drvdata(vfd->dev); return sprintf(buf, "%d\n", btv ? btv->c.type : UNSET); } @@ -470,31 +476,27 @@ static const unsigned int BTTV_TVNORMS = ARRAY_SIZE(bttv_tvnorms); /* ----------------------------------------------------------------------- */ /* bttv format list packed pixel formats must come first */ -static const struct bttv_format bttv_formats[] = { +static const struct bttv_format formats[] = { { .name = "8 bpp, gray", - .palette = VIDEO_PALETTE_GREY, .fourcc = V4L2_PIX_FMT_GREY, .btformat = BT848_COLOR_FMT_Y8, .depth = 8, .flags = FORMAT_FLAGS_PACKED, },{ .name = "8 bpp, dithered color", - .palette = VIDEO_PALETTE_HI240, .fourcc = V4L2_PIX_FMT_HI240, .btformat = BT848_COLOR_FMT_RGB8, .depth = 8, .flags = FORMAT_FLAGS_PACKED | FORMAT_FLAGS_DITHER, },{ .name = "15 bpp RGB, le", - .palette = VIDEO_PALETTE_RGB555, .fourcc = V4L2_PIX_FMT_RGB555, .btformat = BT848_COLOR_FMT_RGB15, .depth = 16, .flags = FORMAT_FLAGS_PACKED, },{ .name = "15 bpp RGB, be", - .palette = -1, .fourcc = V4L2_PIX_FMT_RGB555X, .btformat = BT848_COLOR_FMT_RGB15, .btswap = 0x03, /* byteswap */ @@ -502,14 +504,12 @@ static const struct bttv_format bttv_formats[] = { .flags = FORMAT_FLAGS_PACKED, },{ .name = "16 bpp RGB, le", - .palette = VIDEO_PALETTE_RGB565, .fourcc = V4L2_PIX_FMT_RGB565, .btformat = BT848_COLOR_FMT_RGB16, .depth = 16, .flags = FORMAT_FLAGS_PACKED, },{ .name = "16 bpp RGB, be", - .palette = -1, .fourcc = V4L2_PIX_FMT_RGB565X, .btformat = BT848_COLOR_FMT_RGB16, .btswap = 0x03, /* byteswap */ @@ -517,21 +517,18 @@ static const struct bttv_format bttv_formats[] = { .flags = FORMAT_FLAGS_PACKED, },{ .name = "24 bpp RGB, le", - .palette = VIDEO_PALETTE_RGB24, .fourcc = V4L2_PIX_FMT_BGR24, .btformat = BT848_COLOR_FMT_RGB24, .depth = 24, .flags = FORMAT_FLAGS_PACKED, },{ .name = "32 bpp RGB, le", - .palette = VIDEO_PALETTE_RGB32, .fourcc = V4L2_PIX_FMT_BGR32, .btformat = BT848_COLOR_FMT_RGB32, .depth = 32, .flags = FORMAT_FLAGS_PACKED, },{ .name = "32 bpp RGB, be", - .palette = -1, .fourcc = V4L2_PIX_FMT_RGB32, .btformat = BT848_COLOR_FMT_RGB32, .btswap = 0x0f, /* byte+word swap */ @@ -539,21 +536,18 @@ static const struct bttv_format bttv_formats[] = { .flags = FORMAT_FLAGS_PACKED, },{ .name = "4:2:2, packed, YUYV", - .palette = VIDEO_PALETTE_YUV422, .fourcc = V4L2_PIX_FMT_YUYV, .btformat = BT848_COLOR_FMT_YUY2, .depth = 16, .flags = FORMAT_FLAGS_PACKED, },{ .name = "4:2:2, packed, YUYV", - .palette = VIDEO_PALETTE_YUYV, .fourcc = V4L2_PIX_FMT_YUYV, .btformat = BT848_COLOR_FMT_YUY2, .depth = 16, .flags = FORMAT_FLAGS_PACKED, },{ .name = "4:2:2, packed, UYVY", - .palette = VIDEO_PALETTE_UYVY, .fourcc = V4L2_PIX_FMT_UYVY, .btformat = BT848_COLOR_FMT_YUY2, .btswap = 0x03, /* byteswap */ @@ -561,7 +555,6 @@ static const struct bttv_format bttv_formats[] = { .flags = FORMAT_FLAGS_PACKED, },{ .name = "4:2:2, planar, Y-Cb-Cr", - .palette = VIDEO_PALETTE_YUV422P, .fourcc = V4L2_PIX_FMT_YUV422P, .btformat = BT848_COLOR_FMT_YCrCb422, .depth = 16, @@ -570,7 +563,6 @@ static const struct bttv_format bttv_formats[] = { .vshift = 0, },{ .name = "4:2:0, planar, Y-Cb-Cr", - .palette = VIDEO_PALETTE_YUV420P, .fourcc = V4L2_PIX_FMT_YUV420, .btformat = BT848_COLOR_FMT_YCrCb422, .depth = 12, @@ -579,7 +571,6 @@ static const struct bttv_format bttv_formats[] = { .vshift = 1, },{ .name = "4:2:0, planar, Y-Cr-Cb", - .palette = -1, .fourcc = V4L2_PIX_FMT_YVU420, .btformat = BT848_COLOR_FMT_YCrCb422, .depth = 12, @@ -588,7 +579,6 @@ static const struct bttv_format bttv_formats[] = { .vshift = 1, },{ .name = "4:1:1, planar, Y-Cb-Cr", - .palette = VIDEO_PALETTE_YUV411P, .fourcc = V4L2_PIX_FMT_YUV411P, .btformat = BT848_COLOR_FMT_YCrCb411, .depth = 12, @@ -597,7 +587,6 @@ static const struct bttv_format bttv_formats[] = { .vshift = 0, },{ .name = "4:1:0, planar, Y-Cb-Cr", - .palette = VIDEO_PALETTE_YUV410P, .fourcc = V4L2_PIX_FMT_YUV410, .btformat = BT848_COLOR_FMT_YCrCb411, .depth = 9, @@ -606,7 +595,6 @@ static const struct bttv_format bttv_formats[] = { .vshift = 2, },{ .name = "4:1:0, planar, Y-Cr-Cb", - .palette = -1, .fourcc = V4L2_PIX_FMT_YVU410, .btformat = BT848_COLOR_FMT_YCrCb411, .depth = 9, @@ -615,14 +603,13 @@ static const struct bttv_format bttv_formats[] = { .vshift = 2, },{ .name = "raw scanlines", - .palette = VIDEO_PALETTE_RAW, .fourcc = -1, .btformat = BT848_COLOR_FMT_RAW, .depth = 8, .flags = FORMAT_FLAGS_RAW, } }; -static const unsigned int BTTV_FORMATS = ARRAY_SIZE(bttv_formats); +static const unsigned int FORMATS = ARRAY_SIZE(formats); /* ----------------------------------------------------------------------- */ @@ -798,7 +785,17 @@ static const struct v4l2_queryctrl bttv_ctls[] = { }; -static const int BTTV_CTLS = ARRAY_SIZE(bttv_ctls); + +static const struct v4l2_queryctrl *ctrl_by_id(int id) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(bttv_ctls); i++) + if (bttv_ctls[i].id == id) + return bttv_ctls+i; + + return NULL; +} /* ----------------------------------------------------------------------- */ /* resource management */ @@ -1255,16 +1252,6 @@ audio_input(struct bttv *btv, int input) } static void -i2c_vidiocschan(struct bttv *btv) -{ - v4l2_std_id std = bttv_tvnorms[btv->tvnorm].v4l2_id; - - bttv_call_i2c_clients(btv, VIDIOC_S_STD, &std); - if (btv->c.type == BTTV_BOARD_VOODOOTV_FM || btv->c.type == BTTV_BOARD_VOODOOTV_200) - bttv_tda9880_setnorm(btv,btv->tvnorm); -} - -static void bttv_crop_calc_limits(struct bttv_crop *c) { /* Scale factor min. 1:1, max. 16:1. Min. image size @@ -1298,6 +1285,7 @@ static int set_tvnorm(struct bttv *btv, unsigned int norm) { const struct bttv_tvnorm *tvnorm; + v4l2_std_id id; if (norm < 0 || norm >= BTTV_TVNORMS) return -EINVAL; @@ -1334,6 +1322,9 @@ set_tvnorm(struct bttv *btv, unsigned int norm) bttv_tda9880_setnorm(btv,norm); break; } + id = tvnorm->v4l2_id; + bttv_call_i2c_clients(btv, VIDIOC_S_STD, &id); + return 0; } @@ -1359,7 +1350,6 @@ set_input(struct bttv *btv, unsigned int input, unsigned int norm) audio_input(btv,(input == bttv_tvcards[btv->c.type].tuner ? TVAUDIO_INPUT_TUNER : TVAUDIO_INPUT_EXTERN)); set_tvnorm(btv, norm); - i2c_vidiocschan(btv); } static void init_irqreg(struct bttv *btv) @@ -1452,38 +1442,12 @@ static void bttv_reinit_bt848(struct bttv *btv) set_input(btv, btv->input, btv->tvnorm); } -static int get_control(struct bttv *btv, struct v4l2_control *c) +static int bttv_g_ctrl(struct file *file, void *priv, + struct v4l2_control *c) { - struct video_audio va; - int i; + struct bttv_fh *fh = priv; + struct bttv *btv = fh->btv; - for (i = 0; i < BTTV_CTLS; i++) - if (bttv_ctls[i].id == c->id) - break; - if (i == BTTV_CTLS) - return -EINVAL; - if (btv->audio_hook && i >= 4 && i <= 8) { - memset(&va,0,sizeof(va)); - btv->audio_hook(btv,&va,0); - switch (c->id) { - case V4L2_CID_AUDIO_MUTE: - c->value = (VIDEO_AUDIO_MUTE & va.flags) ? 1 : 0; - break; - case V4L2_CID_AUDIO_VOLUME: - c->value = va.volume; - break; - case V4L2_CID_AUDIO_BALANCE: - c->value = va.balance; - break; - case V4L2_CID_AUDIO_BASS: - c->value = va.bass; - break; - case V4L2_CID_AUDIO_TREBLE: - c->value = va.treble; - break; - } - return 0; - } switch (c->id) { case V4L2_CID_BRIGHTNESS: c->value = btv->bright; @@ -1503,7 +1467,7 @@ static int get_control(struct bttv *btv, struct v4l2_control *c) case V4L2_CID_AUDIO_BALANCE: case V4L2_CID_AUDIO_BASS: case V4L2_CID_AUDIO_TREBLE: - bttv_call_i2c_clients(btv,VIDIOC_G_CTRL,c); + bttv_call_i2c_clients(btv, VIDIOC_G_CTRL, c); break; case V4L2_CID_PRIVATE_CHROMA_AGC: @@ -1545,67 +1509,44 @@ static int get_control(struct bttv *btv, struct v4l2_control *c) return 0; } -static int set_control(struct bttv *btv, struct v4l2_control *c) +static int bttv_s_ctrl(struct file *file, void *f, + struct v4l2_control *c) { - struct video_audio va; - int i,val; + int err; + int val; + struct bttv_fh *fh = f; + struct bttv *btv = fh->btv; - for (i = 0; i < BTTV_CTLS; i++) - if (bttv_ctls[i].id == c->id) - break; - if (i == BTTV_CTLS) - return -EINVAL; - if (btv->audio_hook && i >= 4 && i <= 8) { - memset(&va,0,sizeof(va)); - btv->audio_hook(btv,&va,0); - switch (c->id) { - case V4L2_CID_AUDIO_MUTE: - if (c->value) { - va.flags |= VIDEO_AUDIO_MUTE; - audio_mute(btv, 1); - } else { - va.flags &= ~VIDEO_AUDIO_MUTE; - audio_mute(btv, 0); - } - break; + err = v4l2_prio_check(&btv->prio, &fh->prio); + if (0 != err) + return err; - case V4L2_CID_AUDIO_VOLUME: - va.volume = c->value; - break; - case V4L2_CID_AUDIO_BALANCE: - va.balance = c->value; - break; - case V4L2_CID_AUDIO_BASS: - va.bass = c->value; - break; - case V4L2_CID_AUDIO_TREBLE: - va.treble = c->value; - break; - } - btv->audio_hook(btv,&va,1); - return 0; - } switch (c->id) { case V4L2_CID_BRIGHTNESS: - bt848_bright(btv,c->value); + bt848_bright(btv, c->value); break; case V4L2_CID_HUE: - bt848_hue(btv,c->value); + bt848_hue(btv, c->value); break; case V4L2_CID_CONTRAST: - bt848_contrast(btv,c->value); + bt848_contrast(btv, c->value); break; case V4L2_CID_SATURATION: - bt848_sat(btv,c->value); + bt848_sat(btv, c->value); break; case V4L2_CID_AUDIO_MUTE: audio_mute(btv, c->value); /* fall through */ case V4L2_CID_AUDIO_VOLUME: + if (btv->volume_gpio) + btv->volume_gpio(btv, c->value); + + bttv_call_i2c_clients(btv, VIDIOC_S_CTRL, c); + break; case V4L2_CID_AUDIO_BALANCE: case V4L2_CID_AUDIO_BASS: case V4L2_CID_AUDIO_TREBLE: - bttv_call_i2c_clients(btv,VIDIOC_S_CTRL,c); + bttv_call_i2c_clients(btv, VIDIOC_S_CTRL, c); break; case V4L2_CID_PRIVATE_CHROMA_AGC: @@ -1632,8 +1573,9 @@ static int set_control(struct bttv *btv, struct v4l2_control *c) break; case V4L2_CID_PRIVATE_AGC_CRUSH: btv->opt_adc_crush = c->value; - btwrite(BT848_ADC_RESERVED | (btv->opt_adc_crush ? BT848_ADC_CRUSH : 0), - BT848_ADC); + btwrite(BT848_ADC_RESERVED | + (btv->opt_adc_crush ? BT848_ADC_CRUSH : 0), + BT848_ADC); break; case V4L2_CID_PRIVATE_VCR_HACK: btv->opt_vcr_hack = c->value; @@ -1693,29 +1635,15 @@ static void bttv_field_count(struct bttv *btv) } static const struct bttv_format* -format_by_palette(int palette) -{ - unsigned int i; - - for (i = 0; i < BTTV_FORMATS; i++) { - if (-1 == bttv_formats[i].palette) - continue; - if (bttv_formats[i].palette == palette) - return bttv_formats+i; - } - return NULL; -} - -static const struct bttv_format* format_by_fourcc(int fourcc) { unsigned int i; - for (i = 0; i < BTTV_FORMATS; i++) { - if (-1 == bttv_formats[i].fourcc) + for (i = 0; i < FORMATS; i++) { + if (-1 == formats[i].fourcc) continue; - if (bttv_formats[i].fourcc == fourcc) - return bttv_formats+i; + if (formats[i].fourcc == fourcc) + return formats+i; } return NULL; } @@ -1733,7 +1661,7 @@ bttv_switch_overlay(struct bttv *btv, struct bttv_fh *fh, dprintk("switch_overlay: enter [new=%p]\n",new); if (new) - new->vb.state = STATE_DONE; + new->vb.state = VIDEOBUF_DONE; spin_lock_irqsave(&btv->s_lock,flags); old = btv->screen; btv->screen = new; @@ -1844,7 +1772,7 @@ static int bttv_prepare_buffer(struct videobuf_queue *q,struct bttv *btv, } /* alloc risc memory */ - if (STATE_NEEDS_INIT == buf->vb.state) { + if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { redo_dma_risc = 1; if (0 != (rc = videobuf_iolock(q,&buf->vb,&btv->fbuf))) goto fail; @@ -1854,7 +1782,7 @@ static int bttv_prepare_buffer(struct videobuf_queue *q,struct bttv *btv, if (0 != (rc = bttv_buffer_risc(btv,buf))) goto fail; - buf->vb.state = STATE_PREPARED; + buf->vb.state = VIDEOBUF_PREPARED; return 0; fail: @@ -1893,7 +1821,7 @@ buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb) struct bttv_fh *fh = q->priv_data; struct bttv *btv = fh->btv; - buf->vb.state = STATE_QUEUED; + buf->vb.state = VIDEOBUF_QUEUED; list_add_tail(&buf->vb.queue,&btv->capture); if (!btv->curr.frame_irq) { btv->loop_irq |= 1; @@ -1916,374 +1844,234 @@ static struct videobuf_queue_ops bttv_video_qops = { .buf_release = buffer_release, }; -static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) +static int bttv_s_std(struct file *file, void *priv, v4l2_std_id *id) { - switch (cmd) { - case BTTV_VERSION: - return BTTV_VERSION_CODE; + struct bttv_fh *fh = priv; + struct bttv *btv = fh->btv; + unsigned int i; + int err; - /* *** v4l1 *** ************************************************ */ - case VIDIOCGFREQ: - { - unsigned long *freq = arg; - *freq = btv->freq; - return 0; - } - case VIDIOCSFREQ: - { - struct v4l2_frequency freq; + err = v4l2_prio_check(&btv->prio, &fh->prio); + if (0 != err) + return err; - memset(&freq, 0, sizeof(freq)); - freq.frequency = *(unsigned long *)arg; - mutex_lock(&btv->lock); - freq.type = btv->radio_user ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; - btv->freq = *(unsigned long *)arg; - bttv_call_i2c_clients(btv,VIDIOC_S_FREQUENCY,&freq); - if (btv->has_matchbox && btv->radio_user) - tea5757_set_freq(btv,*(unsigned long *)arg); - mutex_unlock(&btv->lock); - return 0; - } + for (i = 0; i < BTTV_TVNORMS; i++) + if (*id & bttv_tvnorms[i].v4l2_id) + break; + if (i == BTTV_TVNORMS) + return -EINVAL; - case VIDIOCGTUNER: - { - struct video_tuner *v = arg; + mutex_lock(&btv->lock); + set_tvnorm(btv, i); + mutex_unlock(&btv->lock); - if (UNSET == bttv_tvcards[btv->c.type].tuner) - return -EINVAL; - if (v->tuner) /* Only tuner 0 */ - return -EINVAL; - strcpy(v->name, "Television"); - v->rangelow = 0; - v->rangehigh = 0x7FFFFFFF; - v->flags = VIDEO_TUNER_PAL|VIDEO_TUNER_NTSC|VIDEO_TUNER_SECAM; - v->mode = btv->tvnorm; - v->signal = (btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC) ? 0xFFFF : 0; - bttv_call_i2c_clients(btv,cmd,v); - return 0; - } - case VIDIOCSTUNER: - { - struct video_tuner *v = arg; + return 0; +} - if (v->tuner) /* Only tuner 0 */ - return -EINVAL; - if (v->mode >= BTTV_TVNORMS) - return -EINVAL; +static int bttv_querystd(struct file *file, void *f, v4l2_std_id *id) +{ + struct bttv_fh *fh = f; + struct bttv *btv = fh->btv; - mutex_lock(&btv->lock); - set_tvnorm(btv,v->mode); - bttv_call_i2c_clients(btv,cmd,v); - mutex_unlock(&btv->lock); - return 0; - } + if (btread(BT848_DSTATUS) & BT848_DSTATUS_NUML) + *id = V4L2_STD_625_50; + else + *id = V4L2_STD_525_60; + return 0; +} - case VIDIOCGCHAN: - { - struct video_channel *v = arg; - unsigned int channel = v->channel; +static int bttv_enum_input(struct file *file, void *priv, + struct v4l2_input *i) +{ + struct bttv_fh *fh = priv; + struct bttv *btv = fh->btv; + unsigned int n; - if (channel >= bttv_tvcards[btv->c.type].video_inputs) - return -EINVAL; - v->tuners=0; - v->flags = VIDEO_VC_AUDIO; - v->type = VIDEO_TYPE_CAMERA; - v->norm = btv->tvnorm; - if (channel == bttv_tvcards[btv->c.type].tuner) { - strcpy(v->name,"Television"); - v->flags|=VIDEO_VC_TUNER; - v->type=VIDEO_TYPE_TV; - v->tuners=1; - } else if (channel == btv->svhs) { - strcpy(v->name,"S-Video"); - } else { - sprintf(v->name,"Composite%d",channel); - } - return 0; - } - case VIDIOCSCHAN: - { - struct video_channel *v = arg; - unsigned int channel = v->channel; + n = i->index; - if (channel >= bttv_tvcards[btv->c.type].video_inputs) - return -EINVAL; - if (v->norm >= BTTV_TVNORMS) - return -EINVAL; + if (n >= bttv_tvcards[btv->c.type].video_inputs) + return -EINVAL; - mutex_lock(&btv->lock); - if (channel == btv->input && - v->norm == btv->tvnorm) { - /* nothing to do */ - mutex_unlock(&btv->lock); - return 0; - } + memset(i, 0, sizeof(*i)); - set_input(btv, v->channel, v->norm); - mutex_unlock(&btv->lock); - return 0; + i->index = n; + i->type = V4L2_INPUT_TYPE_CAMERA; + i->audioset = 1; + + if (i->index == bttv_tvcards[btv->c.type].tuner) { + sprintf(i->name, "Television"); + i->type = V4L2_INPUT_TYPE_TUNER; + i->tuner = 0; + } else if (i->index == btv->svhs) { + sprintf(i->name, "S-Video"); + } else { + sprintf(i->name, "Composite%d", i->index); } - case VIDIOCGAUDIO: - { - struct video_audio *v = arg; + if (i->index == btv->input) { + __u32 dstatus = btread(BT848_DSTATUS); + if (0 == (dstatus & BT848_DSTATUS_PRES)) + i->status |= V4L2_IN_ST_NO_SIGNAL; + if (0 == (dstatus & BT848_DSTATUS_HLOC)) + i->status |= V4L2_IN_ST_NO_H_LOCK; + } - memset(v,0,sizeof(*v)); - strcpy(v->name,"Television"); - v->flags |= VIDEO_AUDIO_MUTABLE; - v->mode = VIDEO_SOUND_MONO; + for (n = 0; n < BTTV_TVNORMS; n++) + i->std |= bttv_tvnorms[n].v4l2_id; - mutex_lock(&btv->lock); - bttv_call_i2c_clients(btv,cmd,v); + return 0; +} - /* card specific hooks */ - if (btv->audio_hook) - btv->audio_hook(btv,v,0); +static int bttv_g_input(struct file *file, void *priv, unsigned int *i) +{ + struct bttv_fh *fh = priv; + struct bttv *btv = fh->btv; - mutex_unlock(&btv->lock); - return 0; - } - case VIDIOCSAUDIO: - { - struct video_audio *v = arg; - unsigned int audio = v->audio; + *i = btv->input; + return 0; +} - if (audio >= bttv_tvcards[btv->c.type].audio_inputs) - return -EINVAL; +static int bttv_s_input(struct file *file, void *priv, unsigned int i) +{ + struct bttv_fh *fh = priv; + struct bttv *btv = fh->btv; - mutex_lock(&btv->lock); - audio_mute(btv, (v->flags&VIDEO_AUDIO_MUTE) ? 1 : 0); - bttv_call_i2c_clients(btv,cmd,v); + int err; - /* card specific hooks */ - if (btv->audio_hook) - btv->audio_hook(btv,v,1); + err = v4l2_prio_check(&btv->prio, &fh->prio); + if (0 != err) + return err; - mutex_unlock(&btv->lock); - return 0; - } + if (i > bttv_tvcards[btv->c.type].video_inputs) + return -EINVAL; - /* *** v4l2 *** ************************************************ */ - case VIDIOC_ENUMSTD: - { - struct v4l2_standard *e = arg; - unsigned int index = e->index; + mutex_lock(&btv->lock); + set_input(btv, i, btv->tvnorm); + mutex_unlock(&btv->lock); + return 0; +} - if (index >= BTTV_TVNORMS) - return -EINVAL; - v4l2_video_std_construct(e, bttv_tvnorms[e->index].v4l2_id, - bttv_tvnorms[e->index].name); - e->index = index; - return 0; - } - case VIDIOC_G_STD: - { - v4l2_std_id *id = arg; - *id = bttv_tvnorms[btv->tvnorm].v4l2_id; - return 0; - } - case VIDIOC_S_STD: - { - v4l2_std_id *id = arg; - unsigned int i; +static int bttv_s_tuner(struct file *file, void *priv, + struct v4l2_tuner *t) +{ + struct bttv_fh *fh = priv; + struct bttv *btv = fh->btv; + int err; - for (i = 0; i < BTTV_TVNORMS; i++) - if (*id & bttv_tvnorms[i].v4l2_id) - break; - if (i == BTTV_TVNORMS) - return -EINVAL; + err = v4l2_prio_check(&btv->prio, &fh->prio); + if (0 != err) + return err; - mutex_lock(&btv->lock); - set_tvnorm(btv,i); - i2c_vidiocschan(btv); - mutex_unlock(&btv->lock); - return 0; - } - case VIDIOC_QUERYSTD: - { - v4l2_std_id *id = arg; + if (UNSET == bttv_tvcards[btv->c.type].tuner) + return -EINVAL; - if (btread(BT848_DSTATUS) & BT848_DSTATUS_NUML) - *id = V4L2_STD_625_50; - else - *id = V4L2_STD_525_60; - return 0; - } + if (0 != t->index) + return -EINVAL; - case VIDIOC_ENUMINPUT: - { - struct v4l2_input *i = arg; - unsigned int n; + mutex_lock(&btv->lock); + bttv_call_i2c_clients(btv, VIDIOC_S_TUNER, t); - n = i->index; - if (n >= bttv_tvcards[btv->c.type].video_inputs) - return -EINVAL; - memset(i,0,sizeof(*i)); - i->index = n; - i->type = V4L2_INPUT_TYPE_CAMERA; - i->audioset = 1; - if (i->index == bttv_tvcards[btv->c.type].tuner) { - sprintf(i->name, "Television"); - i->type = V4L2_INPUT_TYPE_TUNER; - i->tuner = 0; - } else if (i->index == btv->svhs) { - sprintf(i->name, "S-Video"); - } else { - sprintf(i->name,"Composite%d",i->index); - } - if (i->index == btv->input) { - __u32 dstatus = btread(BT848_DSTATUS); - if (0 == (dstatus & BT848_DSTATUS_PRES)) - i->status |= V4L2_IN_ST_NO_SIGNAL; - if (0 == (dstatus & BT848_DSTATUS_HLOC)) - i->status |= V4L2_IN_ST_NO_H_LOCK; - } - for (n = 0; n < BTTV_TVNORMS; n++) - i->std |= bttv_tvnorms[n].v4l2_id; - return 0; - } - case VIDIOC_G_INPUT: - { - int *i = arg; - *i = btv->input; - return 0; - } - case VIDIOC_S_INPUT: - { - unsigned int *i = arg; + if (btv->audio_mode_gpio) + btv->audio_mode_gpio(btv, t, 1); - if (*i > bttv_tvcards[btv->c.type].video_inputs) - return -EINVAL; - mutex_lock(&btv->lock); - set_input(btv, *i, btv->tvnorm); - mutex_unlock(&btv->lock); - return 0; - } + mutex_unlock(&btv->lock); - case VIDIOC_G_TUNER: - { - struct v4l2_tuner *t = arg; + return 0; +} - if (UNSET == bttv_tvcards[btv->c.type].tuner) - return -EINVAL; - if (0 != t->index) - return -EINVAL; - mutex_lock(&btv->lock); - memset(t,0,sizeof(*t)); - t->rxsubchans = V4L2_TUNER_SUB_MONO; - bttv_call_i2c_clients(btv, VIDIOC_G_TUNER, t); - strcpy(t->name, "Television"); - t->capability = V4L2_TUNER_CAP_NORM; - t->type = V4L2_TUNER_ANALOG_TV; - if (btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC) - t->signal = 0xffff; - - if (btv->audio_hook) { - /* Hmmm ... */ - struct video_audio va; - memset(&va, 0, sizeof(struct video_audio)); - btv->audio_hook(btv,&va,0); - t->audmode = V4L2_TUNER_MODE_MONO; - t->rxsubchans = V4L2_TUNER_SUB_MONO; - if(va.mode & VIDEO_SOUND_STEREO) { - t->audmode = V4L2_TUNER_MODE_STEREO; - t->rxsubchans = V4L2_TUNER_SUB_STEREO; - } - if(va.mode & VIDEO_SOUND_LANG2) { - t->audmode = V4L2_TUNER_MODE_LANG1; - t->rxsubchans = V4L2_TUNER_SUB_LANG1 - | V4L2_TUNER_SUB_LANG2; - } - } - /* FIXME: fill capability+audmode */ - mutex_unlock(&btv->lock); - return 0; - } - case VIDIOC_S_TUNER: - { - struct v4l2_tuner *t = arg; +static int bttv_g_frequency(struct file *file, void *priv, + struct v4l2_frequency *f) +{ + struct bttv_fh *fh = priv; + struct bttv *btv = fh->btv; + int err; - if (UNSET == bttv_tvcards[btv->c.type].tuner) - return -EINVAL; - if (0 != t->index) - return -EINVAL; - mutex_lock(&btv->lock); - bttv_call_i2c_clients(btv, VIDIOC_S_TUNER, t); - if (btv->audio_hook) { - struct video_audio va; - memset(&va, 0, sizeof(struct video_audio)); - if (t->audmode == V4L2_TUNER_MODE_MONO) - va.mode = VIDEO_SOUND_MONO; - else if (t->audmode == V4L2_TUNER_MODE_STEREO || - t->audmode == V4L2_TUNER_MODE_LANG1_LANG2) - va.mode = VIDEO_SOUND_STEREO; - else if (t->audmode == V4L2_TUNER_MODE_LANG1) - va.mode = VIDEO_SOUND_LANG1; - else if (t->audmode == V4L2_TUNER_MODE_LANG2) - va.mode = VIDEO_SOUND_LANG2; - btv->audio_hook(btv,&va,1); - } - mutex_unlock(&btv->lock); - return 0; - } + err = v4l2_prio_check(&btv->prio, &fh->prio); + if (0 != err) + return err; - case VIDIOC_G_FREQUENCY: - { - struct v4l2_frequency *f = arg; + f->type = V4L2_TUNER_ANALOG_TV; + f->frequency = btv->freq; - memset(f,0,sizeof(*f)); - f->type = V4L2_TUNER_ANALOG_TV; - f->frequency = btv->freq; - return 0; - } - case VIDIOC_S_FREQUENCY: - { - struct v4l2_frequency *f = arg; + return 0; +} + +static int bttv_s_frequency(struct file *file, void *priv, + struct v4l2_frequency *f) +{ + struct bttv_fh *fh = priv; + struct bttv *btv = fh->btv; + int err; + + err = v4l2_prio_check(&btv->prio, &fh->prio); + if (0 != err) + return err; + + if (unlikely(f->tuner != 0)) + return -EINVAL; + if (unlikely(f->type != V4L2_TUNER_ANALOG_TV)) + return -EINVAL; + mutex_lock(&btv->lock); + btv->freq = f->frequency; + bttv_call_i2c_clients(btv, VIDIOC_S_FREQUENCY, f); + if (btv->has_matchbox && btv->radio_user) + tea5757_set_freq(btv, btv->freq); + mutex_unlock(&btv->lock); + return 0; +} + +static int bttv_log_status(struct file *file, void *f) +{ + struct bttv_fh *fh = f; + struct bttv *btv = fh->btv; + + printk(KERN_INFO "bttv%d: ======== START STATUS CARD #%d ========\n", + btv->c.nr, btv->c.nr); + bttv_call_i2c_clients(btv, VIDIOC_LOG_STATUS, NULL); + printk(KERN_INFO "bttv%d: ======== END STATUS CARD #%d ========\n", + btv->c.nr, btv->c.nr); + return 0; +} - if (unlikely(f->tuner != 0)) - return -EINVAL; - if (unlikely (f->type != V4L2_TUNER_ANALOG_TV)) - return -EINVAL; - mutex_lock(&btv->lock); - btv->freq = f->frequency; - bttv_call_i2c_clients(btv,VIDIOC_S_FREQUENCY,f); - if (btv->has_matchbox && btv->radio_user) - tea5757_set_freq(btv,btv->freq); - mutex_unlock(&btv->lock); - return 0; - } - case VIDIOC_LOG_STATUS: - { - printk(KERN_INFO "bttv%d: ================= START STATUS CARD #%d =================\n", btv->c.nr, btv->c.nr); - bttv_call_i2c_clients(btv, VIDIOC_LOG_STATUS, NULL); - printk(KERN_INFO "bttv%d: ================== END STATUS CARD #%d ==================\n", btv->c.nr, btv->c.nr); - return 0; - } #ifdef CONFIG_VIDEO_ADV_DEBUG - case VIDIOC_DBG_G_REGISTER: - case VIDIOC_DBG_S_REGISTER: - { - struct v4l2_register *reg = arg; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - if (!v4l2_chip_match_host(reg->match_type, reg->match_chip)) - return -EINVAL; - /* bt848 has a 12-bit register space */ - reg->reg &= 0xfff; - if (cmd == VIDIOC_DBG_G_REGISTER) - reg->val = btread(reg->reg); - else - btwrite(reg->val, reg->reg); - return 0; - } -#endif +static int bttv_g_register(struct file *file, void *f, + struct v4l2_register *reg) +{ + struct bttv_fh *fh = f; + struct bttv *btv = fh->btv; - default: - return -ENOIOCTLCMD; + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + if (!v4l2_chip_match_host(reg->match_type, reg->match_chip)) + return -EINVAL; + + /* bt848 has a 12-bit register space */ + reg->reg &= 0xfff; + reg->val = btread(reg->reg); + + return 0; +} + +static int bttv_s_register(struct file *file, void *f, + struct v4l2_register *reg) +{ + struct bttv_fh *fh = f; + struct bttv *btv = fh->btv; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + if (!v4l2_chip_match_host(reg->match_type, reg->match_chip)) + return -EINVAL; + + /* bt848 has a 12-bit register space */ + reg->reg &= 0xfff; + btwrite(reg->val, reg->reg); - } return 0; } +#endif /* Given cropping boundaries b and the scaled width and height of a single field or frame, which must not exceed hardware limits, this @@ -2659,983 +2447,681 @@ pix_format_set_size (struct v4l2_pix_format * f, } } -static int bttv_g_fmt(struct bttv_fh *fh, struct v4l2_format *f) +static int bttv_g_fmt_cap(struct file *file, void *priv, + struct v4l2_format *f) { - switch (f->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - memset(&f->fmt.pix,0,sizeof(struct v4l2_pix_format)); - pix_format_set_size (&f->fmt.pix, fh->fmt, - fh->width, fh->height); - f->fmt.pix.field = fh->cap.field; - f->fmt.pix.pixelformat = fh->fmt->fourcc; - return 0; - case V4L2_BUF_TYPE_VIDEO_OVERLAY: - memset(&f->fmt.win,0,sizeof(struct v4l2_window)); - f->fmt.win.w = fh->ov.w; - f->fmt.win.field = fh->ov.field; - return 0; - case V4L2_BUF_TYPE_VBI_CAPTURE: - bttv_vbi_get_fmt(fh, &f->fmt.vbi); - return 0; - default: - return -EINVAL; - } + struct bttv_fh *fh = priv; + + pix_format_set_size(&f->fmt.pix, fh->fmt, + fh->width, fh->height); + f->fmt.pix.field = fh->cap.field; + f->fmt.pix.pixelformat = fh->fmt->fourcc; + + return 0; } -static int bttv_try_fmt(struct bttv_fh *fh, struct bttv *btv, - struct v4l2_format *f, int adjust_crop) +static int bttv_g_fmt_overlay(struct file *file, void *priv, + struct v4l2_format *f) { - switch (f->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - { - const struct bttv_format *fmt; - enum v4l2_field field; - __s32 width, height; - int rc; + struct bttv_fh *fh = priv; - fmt = format_by_fourcc(f->fmt.pix.pixelformat); - if (NULL == fmt) - return -EINVAL; + f->fmt.win.w = fh->ov.w; + f->fmt.win.field = fh->ov.field; - field = f->fmt.pix.field; - if (V4L2_FIELD_ANY == field) { - __s32 height2; + return 0; +} - height2 = btv->crop[!!fh->do_crop].rect.height >> 1; - field = (f->fmt.pix.height > height2) - ? V4L2_FIELD_INTERLACED - : V4L2_FIELD_BOTTOM; - } - if (V4L2_FIELD_SEQ_BT == field) - field = V4L2_FIELD_SEQ_TB; - switch (field) { - case V4L2_FIELD_TOP: - case V4L2_FIELD_BOTTOM: - case V4L2_FIELD_ALTERNATE: - case V4L2_FIELD_INTERLACED: - break; - case V4L2_FIELD_SEQ_TB: - if (fmt->flags & FORMAT_FLAGS_PLANAR) - return -EINVAL; - break; - default: - return -EINVAL; - } +static int bttv_try_fmt_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + const struct bttv_format *fmt; + struct bttv_fh *fh = priv; + struct bttv *btv = fh->btv; + enum v4l2_field field; + __s32 width, height; + int rc; - width = f->fmt.pix.width; - height = f->fmt.pix.height; + fmt = format_by_fourcc(f->fmt.pix.pixelformat); + if (NULL == fmt) + return -EINVAL; - rc = limit_scaled_size(fh, &width, &height, field, - /* width_mask: 4 pixels */ ~3, - /* width_bias: nearest */ 2, - /* adjust_size */ 1, - adjust_crop); - if (0 != rc) - return rc; + field = f->fmt.pix.field; - /* update data for the application */ - f->fmt.pix.field = field; - pix_format_set_size(&f->fmt.pix, fmt, width, height); + if (V4L2_FIELD_ANY == field) { + __s32 height2; - return 0; + height2 = btv->crop[!!fh->do_crop].rect.height >> 1; + field = (f->fmt.pix.height > height2) + ? V4L2_FIELD_INTERLACED + : V4L2_FIELD_BOTTOM; } - case V4L2_BUF_TYPE_VIDEO_OVERLAY: - return verify_window(fh, &f->fmt.win, - /* adjust_size */ 1, - /* adjust_crop */ 0); - case V4L2_BUF_TYPE_VBI_CAPTURE: - return bttv_vbi_try_fmt(fh, &f->fmt.vbi); + + if (V4L2_FIELD_SEQ_BT == field) + field = V4L2_FIELD_SEQ_TB; + + switch (field) { + case V4L2_FIELD_TOP: + case V4L2_FIELD_BOTTOM: + case V4L2_FIELD_ALTERNATE: + case V4L2_FIELD_INTERLACED: + break; + case V4L2_FIELD_SEQ_TB: + if (fmt->flags & FORMAT_FLAGS_PLANAR) + return -EINVAL; + break; default: return -EINVAL; } + + width = f->fmt.pix.width; + height = f->fmt.pix.height; + + rc = limit_scaled_size(fh, &width, &height, field, + /* width_mask: 4 pixels */ ~3, + /* width_bias: nearest */ 2, + /* adjust_size */ 1, + /* adjust_crop */ 0); + if (0 != rc) + return rc; + + /* update data for the application */ + f->fmt.pix.field = field; + pix_format_set_size(&f->fmt.pix, fmt, width, height); + + return 0; } -static int bttv_s_fmt(struct bttv_fh *fh, struct bttv *btv, - struct v4l2_format *f) +static int bttv_try_fmt_overlay(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct bttv_fh *fh = priv; + + return verify_window(fh, &f->fmt.win, + /* adjust_size */ 1, + /* adjust_crop */ 0); +} + +static int bttv_s_fmt_cap(struct file *file, void *priv, + struct v4l2_format *f) { int retval; + const struct bttv_format *fmt; + struct bttv_fh *fh = priv; + struct bttv *btv = fh->btv; + __s32 width, height; + enum v4l2_field field; - switch (f->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - { - const struct bttv_format *fmt; + retval = bttv_switch_type(fh, f->type); + if (0 != retval) + return retval; - retval = bttv_switch_type(fh,f->type); - if (0 != retval) - return retval; - retval = bttv_try_fmt(fh,btv,f, /* adjust_crop */ 1); - if (0 != retval) - return retval; - fmt = format_by_fourcc(f->fmt.pix.pixelformat); + retval = bttv_try_fmt_cap(file, priv, f); + if (0 != retval) + return retval; - /* update our state informations */ - mutex_lock(&fh->cap.lock); - fh->fmt = fmt; - fh->cap.field = f->fmt.pix.field; - fh->cap.last = V4L2_FIELD_NONE; - fh->width = f->fmt.pix.width; - fh->height = f->fmt.pix.height; - btv->init.fmt = fmt; - btv->init.width = f->fmt.pix.width; - btv->init.height = f->fmt.pix.height; - mutex_unlock(&fh->cap.lock); + width = f->fmt.pix.width; + height = f->fmt.pix.height; + field = f->fmt.pix.field; - return 0; - } - case V4L2_BUF_TYPE_VIDEO_OVERLAY: - if (no_overlay > 0) { - printk ("V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n"); - return -EINVAL; - } - return setup_window(fh, btv, &f->fmt.win, 1); - case V4L2_BUF_TYPE_VBI_CAPTURE: - retval = bttv_switch_type(fh,f->type); - if (0 != retval) - return retval; - return bttv_vbi_set_fmt(fh, &f->fmt.vbi); - default: - return -EINVAL; - } -} + retval = limit_scaled_size(fh, &width, &height, f->fmt.pix.field, + /* width_mask: 4 pixels */ ~3, + /* width_bias: nearest */ 2, + /* adjust_size */ 1, + /* adjust_crop */ 1); + if (0 != retval) + return retval; -static int bttv_do_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, void *arg) -{ - struct bttv_fh *fh = file->private_data; - struct bttv *btv = fh->btv; - unsigned long flags; - int retval = 0; + f->fmt.pix.field = field; - if (bttv_debug > 1) - v4l_print_ioctl(btv->c.name, cmd); - - if (btv->errors) - bttv_reinit_bt848(btv); - - switch (cmd) { - case VIDIOCSFREQ: - case VIDIOCSTUNER: - case VIDIOCSCHAN: - case VIDIOC_S_CTRL: - case VIDIOC_S_STD: - case VIDIOC_S_INPUT: - case VIDIOC_S_TUNER: - case VIDIOC_S_FREQUENCY: - retval = v4l2_prio_check(&btv->prio,&fh->prio); - if (0 != retval) - return retval; - }; + fmt = format_by_fourcc(f->fmt.pix.pixelformat); - switch (cmd) { + /* update our state informations */ + mutex_lock(&fh->cap.lock); + fh->fmt = fmt; + fh->cap.field = f->fmt.pix.field; + fh->cap.last = V4L2_FIELD_NONE; + fh->width = f->fmt.pix.width; + fh->height = f->fmt.pix.height; + btv->init.fmt = fmt; + btv->init.width = f->fmt.pix.width; + btv->init.height = f->fmt.pix.height; + mutex_unlock(&fh->cap.lock); - /* *** v4l1 *** ************************************************ */ - case VIDIOCGCAP: - { - struct video_capability *cap = arg; + return 0; +} - memset(cap,0,sizeof(*cap)); - strcpy(cap->name,btv->video_dev->name); - if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) { - /* vbi */ - cap->type = VID_TYPE_TUNER|VID_TYPE_TELETEXT; - } else { - /* others */ - cap->type = VID_TYPE_CAPTURE| - VID_TYPE_TUNER| - VID_TYPE_CLIPPING| - VID_TYPE_SCALES; - if (no_overlay <= 0) - cap->type |= VID_TYPE_OVERLAY; - - cap->maxwidth = bttv_tvnorms[btv->tvnorm].swidth; - cap->maxheight = bttv_tvnorms[btv->tvnorm].sheight; - cap->minwidth = 48; - cap->minheight = 32; - } - cap->channels = bttv_tvcards[btv->c.type].video_inputs; - cap->audios = bttv_tvcards[btv->c.type].audio_inputs; - return 0; - } +static int bttv_s_fmt_overlay(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct bttv_fh *fh = priv; + struct bttv *btv = fh->btv; - case VIDIOCGPICT: - { - struct video_picture *pic = arg; - - memset(pic,0,sizeof(*pic)); - pic->brightness = btv->bright; - pic->contrast = btv->contrast; - pic->hue = btv->hue; - pic->colour = btv->saturation; - if (fh->fmt) { - pic->depth = fh->fmt->depth; - pic->palette = fh->fmt->palette; - } - return 0; + if (no_overlay > 0) { + printk(KERN_ERR "V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n"); + return -EINVAL; } - case VIDIOCSPICT: - { - struct video_picture *pic = arg; - const struct bttv_format *fmt; - fmt = format_by_palette(pic->palette); - if (NULL == fmt) - return -EINVAL; - mutex_lock(&fh->cap.lock); - if (fmt->flags & FORMAT_FLAGS_RAW) { - /* VIDIOCMCAPTURE uses gbufsize, not RAW_BPL * - RAW_LINES * 2. F1 is stored at offset 0, F2 - at buffer size / 2. */ - fh->width = RAW_BPL; - fh->height = gbufsize / RAW_BPL; - btv->init.width = RAW_BPL; - btv->init.height = gbufsize / RAW_BPL; - } - fh->ovfmt = fmt; - fh->fmt = fmt; - btv->init.ovfmt = fmt; - btv->init.fmt = fmt; - if (bigendian) { - /* dirty hack time: swap bytes for overlay if the - display adaptor is big endian (insmod option) */ - if (fmt->palette == VIDEO_PALETTE_RGB555 || - fmt->palette == VIDEO_PALETTE_RGB565 || - fmt->palette == VIDEO_PALETTE_RGB32) { - fh->ovfmt = fmt+1; - } - } - bt848_bright(btv,pic->brightness); - bt848_contrast(btv,pic->contrast); - bt848_hue(btv,pic->hue); - bt848_sat(btv,pic->colour); + return setup_window(fh, btv, &f->fmt.win, 1); +} + +#ifdef CONFIG_VIDEO_V4L1_COMPAT +static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf) +{ + int retval; + unsigned int i; + struct bttv_fh *fh = priv; + + mutex_lock(&fh->cap.lock); + retval = videobuf_mmap_setup(&fh->cap, gbuffers, gbufsize, + V4L2_MEMORY_MMAP); + if (retval < 0) { mutex_unlock(&fh->cap.lock); - return 0; + return retval; } - case VIDIOCGWIN: - { - struct video_window *win = arg; + gbuffers = retval; + memset(mbuf, 0, sizeof(*mbuf)); + mbuf->frames = gbuffers; + mbuf->size = gbuffers * gbufsize; - memset(win,0,sizeof(*win)); - win->x = fh->ov.w.left; - win->y = fh->ov.w.top; - win->width = fh->ov.w.width; - win->height = fh->ov.w.height; - return 0; - } - case VIDIOCSWIN: - { - struct video_window *win = arg; - struct v4l2_window w2; + for (i = 0; i < gbuffers; i++) + mbuf->offsets[i] = i * gbufsize; - if (no_overlay > 0) { - printk ("VIDIOCSWIN: no_overlay\n"); - return -EINVAL; - } + mutex_unlock(&fh->cap.lock); + return 0; +} +#endif - w2.field = V4L2_FIELD_ANY; - w2.w.left = win->x; - w2.w.top = win->y; - w2.w.width = win->width; - w2.w.height = win->height; - w2.clipcount = win->clipcount; - 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 */ - fh->width = fh->ov.w.width; - fh->height = fh->ov.w.height; - btv->init.width = fh->ov.w.width; - btv->init.height = fh->ov.w.height; - } - return retval; - } +static int bttv_querycap(struct file *file, void *priv, + struct v4l2_capability *cap) +{ + struct bttv_fh *fh = priv; + struct bttv *btv = fh->btv; - case VIDIOCGFBUF: - { - struct video_buffer *fbuf = arg; - - fbuf->base = btv->fbuf.base; - fbuf->width = btv->fbuf.fmt.width; - fbuf->height = btv->fbuf.fmt.height; - fbuf->bytesperline = btv->fbuf.fmt.bytesperline; - if (fh->ovfmt) - fbuf->depth = fh->ovfmt->depth; - else { - if (fbuf->width) - fbuf->depth = ((fbuf->bytesperline<<3) - + (fbuf->width-1) ) - /fbuf->width; - else - fbuf->depth = 0; - } - return 0; - } - case VIDIOCSFBUF: - { - struct video_buffer *fbuf = arg; - const struct bttv_format *fmt; - unsigned long end; - - if(!capable(CAP_SYS_ADMIN) && - !capable(CAP_SYS_RAWIO)) - return -EPERM; - end = (unsigned long)fbuf->base + - fbuf->height * fbuf->bytesperline; - mutex_lock(&fh->cap.lock); - retval = -EINVAL; + if (0 == v4l2) + return -EINVAL; - switch (fbuf->depth) { - case 8: - fmt = format_by_palette(VIDEO_PALETTE_HI240); - break; - case 16: - fmt = format_by_palette(VIDEO_PALETTE_RGB565); - break; - case 24: - fmt = format_by_palette(VIDEO_PALETTE_RGB24); - break; - case 32: - fmt = format_by_palette(VIDEO_PALETTE_RGB32); - break; - case 15: - fbuf->depth = 16; - fmt = format_by_palette(VIDEO_PALETTE_RGB555); - break; - default: - fmt = NULL; - break; - } - if (NULL == fmt) - goto fh_unlock_and_return; - - fh->ovfmt = fmt; - fh->fmt = fmt; - btv->init.ovfmt = fmt; - btv->init.fmt = fmt; - btv->fbuf.base = fbuf->base; - btv->fbuf.fmt.width = fbuf->width; - btv->fbuf.fmt.height = fbuf->height; - if (fbuf->bytesperline) - btv->fbuf.fmt.bytesperline = fbuf->bytesperline; - else - btv->fbuf.fmt.bytesperline = btv->fbuf.fmt.width*fbuf->depth/8; - mutex_unlock(&fh->cap.lock); - return 0; - } + strlcpy(cap->driver, "bttv", sizeof(cap->driver)); + strlcpy(cap->card, btv->video_dev->name, sizeof(cap->card)); + snprintf(cap->bus_info, sizeof(cap->bus_info), + "PCI:%s", pci_name(btv->c.pci)); + cap->version = BTTV_VERSION_CODE; + cap->capabilities = + V4L2_CAP_VIDEO_CAPTURE | + V4L2_CAP_VBI_CAPTURE | + V4L2_CAP_READWRITE | + V4L2_CAP_STREAMING; + if (no_overlay <= 0) + cap->capabilities |= V4L2_CAP_VIDEO_OVERLAY; + + if (bttv_tvcards[btv->c.type].tuner != UNSET && + bttv_tvcards[btv->c.type].tuner != TUNER_ABSENT) + cap->capabilities |= V4L2_CAP_TUNER; + return 0; +} - case VIDIOCCAPTURE: - case VIDIOC_OVERLAY: - { - struct bttv_buffer *new; - int *on = arg; +static int bttv_enum_fmt_vbi(struct file *file, void *priv, + struct v4l2_fmtdesc *f) +{ + if (0 != f->index) + return -EINVAL; - if (*on) { - /* verify args */ - if (NULL == btv->fbuf.base) - return -EINVAL; - if (!fh->ov.setup_ok) { - dprintk("bttv%d: overlay: !setup_ok\n",btv->c.nr); - return -EINVAL; - } - } + f->pixelformat = V4L2_PIX_FMT_GREY; + strcpy(f->description, "vbi data"); - if (!check_alloc_btres(btv,fh,RESOURCE_OVERLAY)) - return -EBUSY; + return 0; +} - mutex_lock(&fh->cap.lock); - if (*on) { - fh->ov.tvnorm = btv->tvnorm; - new = videobuf_pci_alloc(sizeof(*new)); - new->crop = btv->crop[!!fh->do_crop].rect; - bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new); - } else { - new = NULL; - } +static int bttv_enum_fmt_cap_ovr(struct v4l2_fmtdesc *f) +{ + int index = -1, i; - /* switch over */ - retval = bttv_switch_overlay(btv,fh,new); - mutex_unlock(&fh->cap.lock); - return retval; + for (i = 0; i < FORMATS; i++) { + if (formats[i].fourcc != -1) + index++; + if ((unsigned int)index == f->index) + break; } + if (FORMATS == i) + return -EINVAL; - case VIDIOCGMBUF: - { - struct video_mbuf *mbuf = arg; - unsigned int i; + f->pixelformat = formats[i].fourcc; + strlcpy(f->description, formats[i].name, sizeof(f->description)); - retval = videobuf_mmap_setup(&fh->cap,gbuffers,gbufsize, - V4L2_MEMORY_MMAP); - if (retval < 0) - return retval; + return i; +} - gbuffers = retval; - memset(mbuf,0,sizeof(*mbuf)); - mbuf->frames = gbuffers; - mbuf->size = gbuffers * gbufsize; - for (i = 0; i < gbuffers; i++) - mbuf->offsets[i] = i * gbufsize; - return 0; - } - case VIDIOCMCAPTURE: - { - struct video_mmap *vm = arg; - struct bttv_buffer *buf; - enum v4l2_field field; - __s32 height2; - int res; +static int bttv_enum_fmt_cap(struct file *file, void *priv, + struct v4l2_fmtdesc *f) +{ + int rc = bttv_enum_fmt_cap_ovr(f); - if (vm->frame >= VIDEO_MAX_FRAME) - return -EINVAL; + if (rc < 0) + return rc; - res = bttv_resource(fh); - if (!check_alloc_btres(btv, fh, res)) - return -EBUSY; + return 0; +} - mutex_lock(&fh->cap.lock); - retval = -EINVAL; - buf = (struct bttv_buffer *)fh->cap.bufs[vm->frame]; - if (NULL == buf) - goto fh_unlock_and_return; - if (0 == buf->vb.baddr) - goto fh_unlock_and_return; - if (buf->vb.state == STATE_QUEUED || - buf->vb.state == STATE_ACTIVE) - goto fh_unlock_and_return; +static int bttv_enum_fmt_overlay(struct file *file, void *priv, + struct v4l2_fmtdesc *f) +{ + int rc; - height2 = btv->crop[!!fh->do_crop].rect.height >> 1; - field = (vm->height > height2) - ? V4L2_FIELD_INTERLACED - : V4L2_FIELD_BOTTOM; - retval = bttv_prepare_buffer(&fh->cap,btv,buf, - format_by_palette(vm->format), - vm->width,vm->height,field); - if (0 != retval) - goto fh_unlock_and_return; - btv->init.width = vm->width; - btv->init.height = vm->height; - spin_lock_irqsave(&btv->s_lock,flags); - buffer_queue(&fh->cap,&buf->vb); - spin_unlock_irqrestore(&btv->s_lock,flags); - mutex_unlock(&fh->cap.lock); - return 0; + if (no_overlay > 0) { + printk(KERN_ERR "V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n"); + return -EINVAL; } - case VIDIOCSYNC: - { - int *frame = arg; - struct bttv_buffer *buf; - if (*frame >= VIDEO_MAX_FRAME) - return -EINVAL; + rc = bttv_enum_fmt_cap_ovr(f); - mutex_lock(&fh->cap.lock); - retval = -EINVAL; - buf = (struct bttv_buffer *)fh->cap.bufs[*frame]; - if (NULL == buf) - goto fh_unlock_and_return; - retval = videobuf_waiton(&buf->vb,0,1); - if (0 != retval) - goto fh_unlock_and_return; - switch (buf->vb.state) { - case STATE_ERROR: - retval = -EIO; - /* fall through */ - case STATE_DONE: - { - struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb); - videobuf_dma_sync(&fh->cap,dma); - bttv_dma_free(&fh->cap,btv,buf); - break; - } - default: - retval = -EINVAL; - break; - } - mutex_unlock(&fh->cap.lock); - return retval; - } + if (rc < 0) + return rc; - case VIDIOCGVBIFMT: - if (fh->type != V4L2_BUF_TYPE_VBI_CAPTURE) { - retval = bttv_switch_type(fh,V4L2_BUF_TYPE_VBI_CAPTURE); - if (0 != retval) - return retval; - } + if (!(formats[rc].flags & FORMAT_FLAGS_PACKED)) + return -EINVAL; - /* fall through */ + return 0; +} - case VIDIOCSVBIFMT: - return v4l_compat_translate_ioctl(inode, file, cmd, - arg, bttv_do_ioctl); - - case BTTV_VERSION: - case VIDIOCGFREQ: - case VIDIOCSFREQ: - case VIDIOCGTUNER: - case VIDIOCSTUNER: - case VIDIOCGCHAN: - case VIDIOCSCHAN: - case VIDIOCGAUDIO: - case VIDIOCSAUDIO: - return bttv_common_ioctls(btv,cmd,arg); - - /* *** v4l2 *** ************************************************ */ - case VIDIOC_QUERYCAP: - { - struct v4l2_capability *cap = arg; +static int bttv_g_fbuf(struct file *file, void *f, + struct v4l2_framebuffer *fb) +{ + struct bttv_fh *fh = f; + struct bttv *btv = fh->btv; - if (0 == v4l2) - return -EINVAL; - memset(cap, 0, sizeof (*cap)); - strlcpy(cap->driver, "bttv", sizeof (cap->driver)); - strlcpy(cap->card, btv->video_dev->name, sizeof (cap->card)); - snprintf(cap->bus_info, sizeof (cap->bus_info), - "PCI:%s", pci_name(btv->c.pci)); - cap->version = BTTV_VERSION_CODE; - cap->capabilities = - V4L2_CAP_VIDEO_CAPTURE | - V4L2_CAP_VBI_CAPTURE | - V4L2_CAP_READWRITE | - V4L2_CAP_STREAMING; - if (no_overlay <= 0) - cap->capabilities |= V4L2_CAP_VIDEO_OVERLAY; - - if (bttv_tvcards[btv->c.type].tuner != UNSET && - bttv_tvcards[btv->c.type].tuner != TUNER_ABSENT) - cap->capabilities |= V4L2_CAP_TUNER; - return 0; - } + *fb = btv->fbuf; + fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING; + if (fh->ovfmt) + fb->fmt.pixelformat = fh->ovfmt->fourcc; + return 0; +} - case VIDIOC_ENUM_FMT: - { - struct v4l2_fmtdesc *f = arg; - enum v4l2_buf_type type; - unsigned int i; - int index; - - type = f->type; - if (V4L2_BUF_TYPE_VBI_CAPTURE == type) { - /* vbi */ - index = f->index; - if (0 != index) - return -EINVAL; - memset(f,0,sizeof(*f)); - f->index = index; - f->type = type; - f->pixelformat = V4L2_PIX_FMT_GREY; - strcpy(f->description,"vbi data"); - return 0; - } +static int bttv_overlay(struct file *file, void *f, unsigned int on) +{ + struct bttv_fh *fh = f; + struct bttv *btv = fh->btv; + struct bttv_buffer *new; + int retval; - /* video capture + overlay */ - index = -1; - for (i = 0; i < BTTV_FORMATS; i++) { - if (bttv_formats[i].fourcc != -1) - index++; - if ((unsigned int)index == f->index) - break; - } - if (BTTV_FORMATS == i) + if (on) { + /* verify args */ + if (NULL == btv->fbuf.base) return -EINVAL; - - switch (f->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - break; - case V4L2_BUF_TYPE_VIDEO_OVERLAY: - if (!(bttv_formats[i].flags & FORMAT_FLAGS_PACKED)) - return -EINVAL; - break; - default: + if (!fh->ov.setup_ok) { + dprintk("bttv%d: overlay: !setup_ok\n", btv->c.nr); return -EINVAL; } - memset(f,0,sizeof(*f)); - f->index = index; - f->type = type; - f->pixelformat = bttv_formats[i].fourcc; - strlcpy(f->description,bttv_formats[i].name,sizeof(f->description)); - return 0; } - case VIDIOC_TRY_FMT: - { - struct v4l2_format *f = arg; - return bttv_try_fmt(fh,btv,f, /* adjust_crop */ 0); - } - case VIDIOC_G_FMT: - { - struct v4l2_format *f = arg; - return bttv_g_fmt(fh,f); - } - case VIDIOC_S_FMT: - { - struct v4l2_format *f = arg; - return bttv_s_fmt(fh,btv,f); + if (!check_alloc_btres(btv, fh, RESOURCE_OVERLAY)) + return -EBUSY; + + mutex_lock(&fh->cap.lock); + if (on) { + fh->ov.tvnorm = btv->tvnorm; + new = videobuf_pci_alloc(sizeof(*new)); + bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new); + } else { + new = NULL; } - case VIDIOC_G_FBUF: - { - struct v4l2_framebuffer *fb = arg; + /* switch over */ + retval = bttv_switch_overlay(btv, fh, new); + mutex_unlock(&fh->cap.lock); + return retval; +} - *fb = btv->fbuf; - fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING; - if (fh->ovfmt) - fb->fmt.pixelformat = fh->ovfmt->fourcc; - return 0; - } - case VIDIOC_S_FBUF: - { - struct v4l2_framebuffer *fb = arg; - const struct bttv_format *fmt; +static int bttv_s_fbuf(struct file *file, void *f, + struct v4l2_framebuffer *fb) +{ + struct bttv_fh *fh = f; + struct bttv *btv = fh->btv; + const struct bttv_format *fmt; + int retval; - if(!capable(CAP_SYS_ADMIN) && - !capable(CAP_SYS_RAWIO)) - return -EPERM; + if (!capable(CAP_SYS_ADMIN) && + !capable(CAP_SYS_RAWIO)) + return -EPERM; - /* check args */ - fmt = format_by_fourcc(fb->fmt.pixelformat); - if (NULL == fmt) - return -EINVAL; - if (0 == (fmt->flags & FORMAT_FLAGS_PACKED)) - return -EINVAL; + /* check args */ + fmt = format_by_fourcc(fb->fmt.pixelformat); + if (NULL == fmt) + return -EINVAL; + if (0 == (fmt->flags & FORMAT_FLAGS_PACKED)) + return -EINVAL; - retval = -EINVAL; - if (fb->flags & V4L2_FBUF_FLAG_OVERLAY) { - __s32 width = fb->fmt.width; - __s32 height = fb->fmt.height; - - retval = limit_scaled_size(fh, &width, &height, - V4L2_FIELD_INTERLACED, - /* width_mask */ ~3, - /* width_bias */ 2, - /* adjust_size */ 0, - /* adjust_crop */ 0); - if (0 != retval) - return retval; - } + retval = -EINVAL; + if (fb->flags & V4L2_FBUF_FLAG_OVERLAY) { + __s32 width = fb->fmt.width; + __s32 height = fb->fmt.height; + + retval = limit_scaled_size(fh, &width, &height, + V4L2_FIELD_INTERLACED, + /* width_mask */ ~3, + /* width_bias */ 2, + /* adjust_size */ 0, + /* adjust_crop */ 0); + if (0 != retval) + return retval; + } - /* ok, accept it */ - mutex_lock(&fh->cap.lock); - btv->fbuf.base = fb->base; - btv->fbuf.fmt.width = fb->fmt.width; - btv->fbuf.fmt.height = fb->fmt.height; - if (0 != fb->fmt.bytesperline) - 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 (fb->flags & V4L2_FBUF_FLAG_OVERLAY) { - fh->ov.w.left = 0; - fh->ov.w.top = 0; - fh->ov.w.width = fb->fmt.width; - fh->ov.w.height = fb->fmt.height; - btv->init.ov.w.width = fb->fmt.width; - btv->init.ov.w.height = fb->fmt.height; - kfree(fh->ov.clips); - fh->ov.clips = NULL; - fh->ov.nclips = 0; - - if (check_btres(fh, RESOURCE_OVERLAY)) { - struct bttv_buffer *new; - - new = videobuf_pci_alloc(sizeof(*new)); - new->crop = btv->crop[!!fh->do_crop].rect; - bttv_overlay_risc(btv,&fh->ov,fh->ovfmt,new); - retval = bttv_switch_overlay(btv,fh,new); - } + /* ok, accept it */ + mutex_lock(&fh->cap.lock); + btv->fbuf.base = fb->base; + btv->fbuf.fmt.width = fb->fmt.width; + btv->fbuf.fmt.height = fb->fmt.height; + if (0 != fb->fmt.bytesperline) + 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 (fb->flags & V4L2_FBUF_FLAG_OVERLAY) { + fh->ov.w.left = 0; + fh->ov.w.top = 0; + fh->ov.w.width = fb->fmt.width; + fh->ov.w.height = fb->fmt.height; + btv->init.ov.w.width = fb->fmt.width; + btv->init.ov.w.height = fb->fmt.height; + kfree(fh->ov.clips); + fh->ov.clips = NULL; + fh->ov.nclips = 0; + + if (check_btres(fh, RESOURCE_OVERLAY)) { + struct bttv_buffer *new; + + new = videobuf_pci_alloc(sizeof(*new)); + new->crop = btv->crop[!!fh->do_crop].rect; + bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new); + retval = bttv_switch_overlay(btv, fh, new); } - mutex_unlock(&fh->cap.lock); - return retval; } + mutex_unlock(&fh->cap.lock); + return retval; +} - case VIDIOC_REQBUFS: - return videobuf_reqbufs(bttv_queue(fh),arg); +static int bttv_reqbufs(struct file *file, void *priv, + struct v4l2_requestbuffers *p) +{ + struct bttv_fh *fh = priv; + return videobuf_reqbufs(bttv_queue(fh), p); +} - case VIDIOC_QUERYBUF: - return videobuf_querybuf(bttv_queue(fh),arg); +static int bttv_querybuf(struct file *file, void *priv, + struct v4l2_buffer *b) +{ + struct bttv_fh *fh = priv; + return videobuf_querybuf(bttv_queue(fh), b); +} - case VIDIOC_QBUF: - { - int res = bttv_resource(fh); +static int bttv_qbuf(struct file *file, void *priv, struct v4l2_buffer *b) +{ + struct bttv_fh *fh = priv; + struct bttv *btv = fh->btv; + int res = bttv_resource(fh); - if (!check_alloc_btres(btv, fh, res)) - return -EBUSY; - return videobuf_qbuf(bttv_queue(fh),arg); - } + if (!check_alloc_btres(btv, fh, res)) + return -EBUSY; - case VIDIOC_DQBUF: - return videobuf_dqbuf(bttv_queue(fh),arg, - file->f_flags & O_NONBLOCK); + return videobuf_qbuf(bttv_queue(fh), b); +} - case VIDIOC_STREAMON: - { - int res = bttv_resource(fh); +static int bttv_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b) +{ + struct bttv_fh *fh = priv; + return videobuf_dqbuf(bttv_queue(fh), b, + file->f_flags & O_NONBLOCK); +} - if (!check_alloc_btres(btv,fh,res)) - return -EBUSY; - return videobuf_streamon(bttv_queue(fh)); - } - case VIDIOC_STREAMOFF: - { - int res = bttv_resource(fh); +static int bttv_streamon(struct file *file, void *priv, + enum v4l2_buf_type type) +{ + struct bttv_fh *fh = priv; + struct bttv *btv = fh->btv; + int res = bttv_resource(fh); - retval = videobuf_streamoff(bttv_queue(fh)); - if (retval < 0) - return retval; - free_btres(btv,fh,res); - return 0; - } + if (!check_alloc_btres(btv, fh, res)) + return -EBUSY; + return videobuf_streamon(bttv_queue(fh)); +} - case VIDIOC_QUERYCTRL: - { - struct v4l2_queryctrl *c = arg; - int i; - if ((c->id < V4L2_CID_BASE || - c->id >= V4L2_CID_LASTP1) && - (c->id < V4L2_CID_PRIVATE_BASE || - c->id >= V4L2_CID_PRIVATE_LASTP1)) - return -EINVAL; - for (i = 0; i < BTTV_CTLS; i++) - if (bttv_ctls[i].id == c->id) - break; - if (i == BTTV_CTLS) { - *c = no_ctl; - return 0; - } - *c = bttv_ctls[i]; - if (btv->audio_hook && i >= 4 && i <= 8) { - struct video_audio va; - memset(&va,0,sizeof(va)); - btv->audio_hook(btv,&va,0); - switch (bttv_ctls[i].id) { - case V4L2_CID_AUDIO_VOLUME: - if (!(va.flags & VIDEO_AUDIO_VOLUME)) - *c = no_ctl; - break; - case V4L2_CID_AUDIO_BALANCE: - if (!(va.flags & VIDEO_AUDIO_BALANCE)) - *c = no_ctl; - break; - case V4L2_CID_AUDIO_BASS: - if (!(va.flags & VIDEO_AUDIO_BASS)) - *c = no_ctl; - break; - case V4L2_CID_AUDIO_TREBLE: - if (!(va.flags & VIDEO_AUDIO_TREBLE)) - *c = no_ctl; - break; - } - } - return 0; - } - case VIDIOC_G_CTRL: - return get_control(btv,arg); - case VIDIOC_S_CTRL: - return set_control(btv,arg); - case VIDIOC_G_PARM: - { - struct v4l2_streamparm *parm = arg; - struct v4l2_standard s; - if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - memset(parm,0,sizeof(*parm)); - v4l2_video_std_construct(&s, bttv_tvnorms[btv->tvnorm].v4l2_id, - bttv_tvnorms[btv->tvnorm].name); - parm->parm.capture.timeperframe = s.frameperiod; - return 0; - } +static int bttv_streamoff(struct file *file, void *priv, + enum v4l2_buf_type type) +{ + struct bttv_fh *fh = priv; + struct bttv *btv = fh->btv; + int retval; + int res = bttv_resource(fh); - case VIDIOC_G_PRIORITY: - { - enum v4l2_priority *p = arg; - *p = v4l2_prio_max(&btv->prio); - return 0; - } - case VIDIOC_S_PRIORITY: - { - enum v4l2_priority *prio = arg; + retval = videobuf_streamoff(bttv_queue(fh)); + if (retval < 0) + return retval; + free_btres(btv, fh, res); + return 0; +} - return v4l2_prio_change(&btv->prio, &fh->prio, *prio); - } +static int bttv_queryctrl(struct file *file, void *priv, + struct v4l2_queryctrl *c) +{ + struct bttv_fh *fh = priv; + struct bttv *btv = fh->btv; + const struct v4l2_queryctrl *ctrl; - case VIDIOC_CROPCAP: - { - struct v4l2_cropcap *cap = arg; - enum v4l2_buf_type type; + if ((c->id < V4L2_CID_BASE || + c->id >= V4L2_CID_LASTP1) && + (c->id < V4L2_CID_PRIVATE_BASE || + c->id >= V4L2_CID_PRIVATE_LASTP1)) + return -EINVAL; - type = cap->type; + if (!btv->volume_gpio && (c->id == V4L2_CID_AUDIO_VOLUME)) + *c = no_ctl; + else { + ctrl = ctrl_by_id(c->id); - if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE && - type != V4L2_BUF_TYPE_VIDEO_OVERLAY) - return -EINVAL; + *c = (NULL != ctrl) ? *ctrl : no_ctl; + } - *cap = bttv_tvnorms[btv->tvnorm].cropcap; - cap->type = type; + return 0; +} - return 0; - } - case VIDIOC_G_CROP: - { - struct v4l2_crop * crop = arg; +static int bttv_g_parm(struct file *file, void *f, + struct v4l2_streamparm *parm) +{ + struct bttv_fh *fh = f; + struct bttv *btv = fh->btv; + struct v4l2_standard s; - if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && - crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY) - return -EINVAL; + if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + v4l2_video_std_construct(&s, bttv_tvnorms[btv->tvnorm].v4l2_id, + bttv_tvnorms[btv->tvnorm].name); + parm->parm.capture.timeperframe = s.frameperiod; + return 0; +} - /* No fh->do_crop = 1; because btv->crop[1] may be - inconsistent with fh->width or fh->height and apps - do not expect a change here. */ +static int bttv_g_tuner(struct file *file, void *priv, + struct v4l2_tuner *t) +{ + struct bttv_fh *fh = priv; + struct bttv *btv = fh->btv; - crop->c = btv->crop[!!fh->do_crop].rect; + if (UNSET == bttv_tvcards[btv->c.type].tuner) + return -EINVAL; + if (0 != t->index) + return -EINVAL; - return 0; - } - case VIDIOC_S_CROP: - { - struct v4l2_crop *crop = arg; - const struct v4l2_rect *b; - struct bttv_crop c; - __s32 b_left; - __s32 b_top; - __s32 b_right; - __s32 b_bottom; - - if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && - crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY) - return -EINVAL; + mutex_lock(&btv->lock); + memset(t, 0, sizeof(*t)); + t->rxsubchans = V4L2_TUNER_SUB_MONO; + bttv_call_i2c_clients(btv, VIDIOC_G_TUNER, t); + strcpy(t->name, "Television"); + t->capability = V4L2_TUNER_CAP_NORM; + t->type = V4L2_TUNER_ANALOG_TV; + if (btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC) + t->signal = 0xffff; + + if (btv->audio_mode_gpio) + btv->audio_mode_gpio(btv, t, 0); - retval = v4l2_prio_check(&btv->prio,&fh->prio); - if (0 != retval) - return retval; + mutex_unlock(&btv->lock); + return 0; +} - /* Make sure tvnorm, vbi_end and the current cropping - parameters remain consistent until we're done. Note - read() may change vbi_end in check_alloc_btres(). */ - mutex_lock(&btv->lock); +static int bttv_g_priority(struct file *file, void *f, enum v4l2_priority *p) +{ + struct bttv_fh *fh = f; + struct bttv *btv = fh->btv; - retval = -EBUSY; + *p = v4l2_prio_max(&btv->prio); - if (locked_btres(fh->btv, VIDEO_RESOURCES)) - goto btv_unlock_and_return; + return 0; +} - b = &bttv_tvnorms[btv->tvnorm].cropcap.bounds; +static int bttv_s_priority(struct file *file, void *f, + enum v4l2_priority prio) +{ + struct bttv_fh *fh = f; + struct bttv *btv = fh->btv; - b_left = b->left; - b_right = b_left + b->width; - b_bottom = b->top + b->height; + return v4l2_prio_change(&btv->prio, &fh->prio, prio); +} - b_top = max(b->top, btv->vbi_end); - if (b_top + 32 >= b_bottom) - goto btv_unlock_and_return; +static int bttv_cropcap(struct file *file, void *priv, + struct v4l2_cropcap *cap) +{ + struct bttv_fh *fh = priv; + struct bttv *btv = fh->btv; - /* Min. scaled size 48 x 32. */ - c.rect.left = clamp(crop->c.left, b_left, b_right - 48); - c.rect.left = min(c.rect.left, (__s32) MAX_HDELAY); + if (cap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && + cap->type != V4L2_BUF_TYPE_VIDEO_OVERLAY) + return -EINVAL; - c.rect.width = clamp(crop->c.width, - 48, b_right - c.rect.left); + *cap = bttv_tvnorms[btv->tvnorm].cropcap; - c.rect.top = clamp(crop->c.top, b_top, b_bottom - 32); - /* Top and height must be a multiple of two. */ - c.rect.top = (c.rect.top + 1) & ~1; + return 0; +} - c.rect.height = clamp(crop->c.height, - 32, b_bottom - c.rect.top); - c.rect.height = (c.rect.height + 1) & ~1; +static int bttv_g_crop(struct file *file, void *f, struct v4l2_crop *crop) +{ + struct bttv_fh *fh = f; + struct bttv *btv = fh->btv; - bttv_crop_calc_limits(&c); + if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && + crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY) + return -EINVAL; - btv->crop[1] = c; + /* No fh->do_crop = 1; because btv->crop[1] may be + inconsistent with fh->width or fh->height and apps + do not expect a change here. */ - mutex_unlock(&btv->lock); + crop->c = btv->crop[!!fh->do_crop].rect; - fh->do_crop = 1; + return 0; +} - mutex_lock(&fh->cap.lock); +static int bttv_s_crop(struct file *file, void *f, struct v4l2_crop *crop) +{ + struct bttv_fh *fh = f; + struct bttv *btv = fh->btv; + const struct v4l2_rect *b; + int retval; + struct bttv_crop c; + __s32 b_left; + __s32 b_top; + __s32 b_right; + __s32 b_bottom; - if (fh->width < c.min_scaled_width) { - fh->width = c.min_scaled_width; - btv->init.width = c.min_scaled_width; - } else if (fh->width > c.max_scaled_width) { - fh->width = c.max_scaled_width; - btv->init.width = c.max_scaled_width; - } + if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && + crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY) + return -EINVAL; - if (fh->height < c.min_scaled_height) { - fh->height = c.min_scaled_height; - btv->init.height = c.min_scaled_height; - } else if (fh->height > c.max_scaled_height) { - fh->height = c.max_scaled_height; - btv->init.height = c.max_scaled_height; - } + retval = v4l2_prio_check(&btv->prio, &fh->prio); + if (0 != retval) + return retval; - mutex_unlock(&fh->cap.lock); + /* Make sure tvnorm, vbi_end and the current cropping + parameters remain consistent until we're done. Note + read() may change vbi_end in check_alloc_btres(). */ + mutex_lock(&btv->lock); - return 0; + retval = -EBUSY; + + if (locked_btres(fh->btv, VIDEO_RESOURCES)) { + mutex_unlock(&btv->lock); + return retval; } - case VIDIOC_ENUMSTD: - case VIDIOC_G_STD: - case VIDIOC_S_STD: - case VIDIOC_ENUMINPUT: - case VIDIOC_G_INPUT: - case VIDIOC_S_INPUT: - case VIDIOC_G_TUNER: - case VIDIOC_S_TUNER: - case VIDIOC_G_FREQUENCY: - case VIDIOC_S_FREQUENCY: - case VIDIOC_LOG_STATUS: - case VIDIOC_DBG_G_REGISTER: - case VIDIOC_DBG_S_REGISTER: - return bttv_common_ioctls(btv,cmd,arg); + b = &bttv_tvnorms[btv->tvnorm].cropcap.bounds; - default: - return -ENOIOCTLCMD; + b_left = b->left; + b_right = b_left + b->width; + b_bottom = b->top + b->height; + + b_top = max(b->top, btv->vbi_end); + if (b_top + 32 >= b_bottom) { + mutex_unlock(&btv->lock); + return retval; } - return 0; - fh_unlock_and_return: - mutex_unlock(&fh->cap.lock); - return retval; + /* Min. scaled size 48 x 32. */ + c.rect.left = clamp(crop->c.left, b_left, b_right - 48); + c.rect.left = min(c.rect.left, (__s32) MAX_HDELAY); - btv_unlock_and_return: - mutex_unlock(&btv->lock); - return retval; -} + c.rect.width = clamp(crop->c.width, + 48, b_right - c.rect.left); -static int bttv_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - struct bttv_fh *fh = file->private_data; + c.rect.top = clamp(crop->c.top, b_top, b_bottom - 32); + /* Top and height must be a multiple of two. */ + c.rect.top = (c.rect.top + 1) & ~1; - switch (cmd) { - case BTTV_VBISIZE: - { - const struct bttv_tvnorm *tvnorm; + c.rect.height = clamp(crop->c.height, + 32, b_bottom - c.rect.top); + c.rect.height = (c.rect.height + 1) & ~1; - tvnorm = fh->vbi_fmt.tvnorm; + bttv_crop_calc_limits(&c); - if (fh->vbi_fmt.fmt.start[0] != tvnorm->vbistart[0] || - fh->vbi_fmt.fmt.start[1] != tvnorm->vbistart[1] || - fh->vbi_fmt.fmt.count[0] != fh->vbi_fmt.fmt.count[1]) { - /* BTTV_VBISIZE cannot express these parameters, - however open() resets the paramters to defaults - and apps shouldn't call BTTV_VBISIZE after - VIDIOC_S_FMT. */ - return -EINVAL; - } + btv->crop[1] = c; + + mutex_unlock(&btv->lock); + + fh->do_crop = 1; - bttv_switch_type(fh,V4L2_BUF_TYPE_VBI_CAPTURE); - return (fh->vbi_fmt.fmt.count[0] * 2 - * fh->vbi_fmt.fmt.samples_per_line); + mutex_lock(&fh->cap.lock); + + if (fh->width < c.min_scaled_width) { + fh->width = c.min_scaled_width; + btv->init.width = c.min_scaled_width; + } else if (fh->width > c.max_scaled_width) { + fh->width = c.max_scaled_width; + btv->init.width = c.max_scaled_width; } - default: - return video_usercopy(inode, file, cmd, arg, bttv_do_ioctl); + if (fh->height < c.min_scaled_height) { + fh->height = c.min_scaled_height; + btv->init.height = c.min_scaled_height; + } else if (fh->height > c.max_scaled_height) { + fh->height = c.max_scaled_height; + btv->init.height = c.max_scaled_height; } + + mutex_unlock(&fh->cap.lock); + + return 0; +} + +static int bttv_g_audio(struct file *file, void *priv, struct v4l2_audio *a) +{ + strcpy(a->name, "audio"); + return 0; +} + +static int bttv_s_audio(struct file *file, void *priv, struct v4l2_audio *a) +{ + return 0; } static ssize_t bttv_read(struct file *file, char __user *data, @@ -3719,8 +3205,8 @@ static unsigned int bttv_poll(struct file *file, poll_table *wait) } poll_wait(file, &buf->vb.done, wait); - if (buf->vb.state == STATE_DONE || - buf->vb.state == STATE_ERROR) + if (buf->vb.state == VIDEOBUF_DONE || + buf->vb.state == VIDEOBUF_ERROR) return POLLIN|POLLRDNORM; return 0; } @@ -3777,7 +3263,7 @@ static int bttv_open(struct inode *inode, struct file *file) V4L2_FIELD_SEQ_TB, sizeof(struct bttv_buffer), fh); - i2c_vidiocschan(btv); + set_tvnorm(btv,btv->tvnorm); btv->users++; @@ -3857,7 +3343,7 @@ static const struct file_operations bttv_fops = .owner = THIS_MODULE, .open = bttv_open, .release = bttv_release, - .ioctl = bttv_ioctl, + .ioctl = video_ioctl2, .compat_ioctl = v4l_compat_ioctl32, .llseek = no_llseek, .read = bttv_read, @@ -3867,19 +3353,61 @@ static const struct file_operations bttv_fops = static struct video_device bttv_video_template = { - .name = "UNSET", - .type = VID_TYPE_CAPTURE|VID_TYPE_TUNER| - VID_TYPE_CLIPPING|VID_TYPE_SCALES, - .fops = &bttv_fops, - .minor = -1, -}; - -static struct video_device bttv_vbi_template = -{ - .name = "bt848/878 vbi", - .type = VID_TYPE_TUNER|VID_TYPE_TELETEXT, .fops = &bttv_fops, .minor = -1, + .vidioc_querycap = bttv_querycap, + .vidioc_enum_fmt_cap = bttv_enum_fmt_cap, + .vidioc_g_fmt_cap = bttv_g_fmt_cap, + .vidioc_try_fmt_cap = bttv_try_fmt_cap, + .vidioc_s_fmt_cap = bttv_s_fmt_cap, + .vidioc_enum_fmt_overlay = bttv_enum_fmt_overlay, + .vidioc_g_fmt_overlay = bttv_g_fmt_overlay, + .vidioc_try_fmt_overlay = bttv_try_fmt_overlay, + .vidioc_s_fmt_overlay = bttv_s_fmt_overlay, + .vidioc_enum_fmt_vbi = bttv_enum_fmt_vbi, + .vidioc_g_fmt_vbi = bttv_g_fmt_vbi, + .vidioc_try_fmt_vbi = bttv_try_fmt_vbi, + .vidioc_s_fmt_vbi = bttv_s_fmt_vbi, + .vidioc_g_audio = bttv_g_audio, + .vidioc_s_audio = bttv_s_audio, + .vidioc_cropcap = bttv_cropcap, + .vidioc_reqbufs = bttv_reqbufs, + .vidioc_querybuf = bttv_querybuf, + .vidioc_qbuf = bttv_qbuf, + .vidioc_dqbuf = bttv_dqbuf, + .vidioc_s_std = bttv_s_std, + .vidioc_enum_input = bttv_enum_input, + .vidioc_g_input = bttv_g_input, + .vidioc_s_input = bttv_s_input, + .vidioc_queryctrl = bttv_queryctrl, + .vidioc_g_ctrl = bttv_g_ctrl, + .vidioc_s_ctrl = bttv_s_ctrl, + .vidioc_streamon = bttv_streamon, + .vidioc_streamoff = bttv_streamoff, + .vidioc_g_tuner = bttv_g_tuner, + .vidioc_s_tuner = bttv_s_tuner, +#ifdef CONFIG_VIDEO_V4L1_COMPAT + .vidiocgmbuf = vidiocgmbuf, +#endif + .vidioc_g_crop = bttv_g_crop, + .vidioc_g_crop = bttv_g_crop, + .vidioc_s_crop = bttv_s_crop, + .vidioc_g_fbuf = bttv_g_fbuf, + .vidioc_s_fbuf = bttv_s_fbuf, + .vidioc_overlay = bttv_overlay, + .vidioc_g_priority = bttv_g_priority, + .vidioc_s_priority = bttv_s_priority, + .vidioc_g_parm = bttv_g_parm, + .vidioc_g_frequency = bttv_g_frequency, + .vidioc_s_frequency = bttv_s_frequency, + .vidioc_log_status = bttv_log_status, + .vidioc_querystd = bttv_querystd, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .vidioc_g_register = bttv_g_register, + .vidioc_s_register = bttv_s_register, +#endif + .tvnorms = BTTV_NORMS, + .current_norm = V4L2_STD_PAL, }; /* ----------------------------------------------------------------------- */ @@ -3918,7 +3446,7 @@ static int radio_open(struct inode *inode, struct file *file) static int radio_release(struct inode *inode, struct file *file) { - struct bttv *btv = file->private_data; + struct bttv *btv = file->private_data; struct rds_command cmd; btv->radio_user--; @@ -3928,59 +3456,116 @@ static int radio_release(struct inode *inode, struct file *file) return 0; } -static int radio_do_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, void *arg) +static int radio_querycap(struct file *file, void *priv, + struct v4l2_capability *cap) { - struct bttv *btv = file->private_data; + struct bttv_fh *fh = priv; + struct bttv *btv = fh->btv; - switch (cmd) { - case VIDIOCGCAP: - { - struct video_capability *cap = arg; + strcpy(cap->driver, "bttv"); + strlcpy(cap->card, btv->radio_dev->name, sizeof(cap->card)); + sprintf(cap->bus_info, "PCI:%s", pci_name(btv->c.pci)); + cap->version = BTTV_VERSION_CODE; + cap->capabilities = V4L2_CAP_TUNER; - memset(cap,0,sizeof(*cap)); - strcpy(cap->name,btv->radio_dev->name); - cap->type = VID_TYPE_TUNER; - cap->channels = 1; - cap->audios = 1; - return 0; - } + return 0; +} - case VIDIOCGTUNER: - { - struct video_tuner *v = arg; +static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t) +{ + struct bttv_fh *fh = priv; + struct bttv *btv = fh->btv; - if(v->tuner) - return -EINVAL; - memset(v,0,sizeof(*v)); - strcpy(v->name, "Radio"); - bttv_call_i2c_clients(btv,cmd,v); - return 0; - } - case VIDIOCSTUNER: - /* nothing to do */ - return 0; + if (UNSET == bttv_tvcards[btv->c.type].tuner) + return -EINVAL; + if (0 != t->index) + return -EINVAL; + mutex_lock(&btv->lock); + memset(t, 0, sizeof(*t)); + strcpy(t->name, "Radio"); + t->type = V4L2_TUNER_RADIO; - case BTTV_VERSION: - case VIDIOCGFREQ: - case VIDIOCSFREQ: - case VIDIOCGAUDIO: - case VIDIOCSAUDIO: - case VIDIOC_LOG_STATUS: - case VIDIOC_DBG_G_REGISTER: - case VIDIOC_DBG_S_REGISTER: - return bttv_common_ioctls(btv,cmd,arg); + bttv_call_i2c_clients(btv, VIDIOC_G_TUNER, t); + + if (btv->audio_mode_gpio) + btv->audio_mode_gpio(btv, t, 0); + + mutex_unlock(&btv->lock); + + return 0; +} + +static int radio_enum_input(struct file *file, void *priv, + struct v4l2_input *i) +{ + if (i->index != 0) + return -EINVAL; + + strcpy(i->name, "Radio"); + i->type = V4L2_INPUT_TYPE_TUNER; + + return 0; +} + +static int radio_g_audio(struct file *file, void *priv, + struct v4l2_audio *a) +{ + memset(a, 0, sizeof(*a)); + strcpy(a->name, "Radio"); + return 0; +} + +static int radio_s_tuner(struct file *file, void *priv, + struct v4l2_tuner *t) +{ + struct bttv_fh *fh = priv; + struct bttv *btv = fh->btv; + + if (0 != t->index) + return -EINVAL; + + bttv_call_i2c_clients(btv, VIDIOC_G_TUNER, t); + return 0; +} + +static int radio_s_audio(struct file *file, void *priv, + struct v4l2_audio *a) +{ + return 0; +} + +static int radio_s_input(struct file *filp, void *priv, unsigned int i) +{ + return 0; +} + +static int radio_s_std(struct file *file, void *fh, v4l2_std_id *norm) +{ + return 0; +} + +static int radio_queryctrl(struct file *file, void *priv, + struct v4l2_queryctrl *c) +{ + const struct v4l2_queryctrl *ctrl; + + if (c->id < V4L2_CID_BASE || + c->id >= V4L2_CID_LASTP1) + return -EINVAL; + + if (c->id == V4L2_CID_AUDIO_MUTE) { + ctrl = ctrl_by_id(c->id); + *c = *ctrl; + } else + *c = no_ctl; - default: - return -ENOIOCTLCMD; - } return 0; } -static int radio_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static int radio_g_input(struct file *filp, void *priv, unsigned int *i) { - return video_usercopy(inode, file, cmd, arg, radio_do_ioctl); + *i = 0; + return 0; } static ssize_t radio_read(struct file *file, char __user *data, @@ -4016,17 +3601,29 @@ static const struct file_operations radio_fops = .open = radio_open, .read = radio_read, .release = radio_release, - .ioctl = radio_ioctl, + .ioctl = video_ioctl2, .llseek = no_llseek, .poll = radio_poll, }; static struct video_device radio_template = { - .name = "bt848/878 radio", - .type = VID_TYPE_TUNER, .fops = &radio_fops, .minor = -1, + .vidioc_querycap = radio_querycap, + .vidioc_g_tuner = radio_g_tuner, + .vidioc_enum_input = radio_enum_input, + .vidioc_g_audio = radio_g_audio, + .vidioc_s_tuner = radio_s_tuner, + .vidioc_s_audio = radio_s_audio, + .vidioc_s_input = radio_s_input, + .vidioc_s_std = radio_s_std, + .vidioc_queryctrl = radio_queryctrl, + .vidioc_g_input = radio_g_input, + .vidioc_g_ctrl = bttv_g_ctrl, + .vidioc_s_ctrl = bttv_s_ctrl, + .vidioc_g_frequency = bttv_g_frequency, + .vidioc_s_frequency = bttv_s_frequency, }; /* ----------------------------------------------------------------------- */ @@ -4308,20 +3905,20 @@ static void bttv_irq_timeout(unsigned long data) bttv_set_dma(btv, 0); /* wake up */ - bttv_irq_wakeup_video(btv, &old, &new, STATE_ERROR); - bttv_irq_wakeup_vbi(btv, ovbi, STATE_ERROR); + bttv_irq_wakeup_video(btv, &old, &new, VIDEOBUF_ERROR); + bttv_irq_wakeup_vbi(btv, ovbi, VIDEOBUF_ERROR); /* cancel all outstanding capture / vbi requests */ while (!list_empty(&btv->capture)) { item = list_entry(btv->capture.next, struct bttv_buffer, vb.queue); list_del(&item->vb.queue); - item->vb.state = STATE_ERROR; + item->vb.state = VIDEOBUF_ERROR; wake_up(&item->vb.done); } while (!list_empty(&btv->vcapture)) { item = list_entry(btv->vcapture.next, struct bttv_buffer, vb.queue); list_del(&item->vb.queue); - item->vb.state = STATE_ERROR; + item->vb.state = VIDEOBUF_ERROR; wake_up(&item->vb.done); } @@ -4344,7 +3941,7 @@ bttv_irq_wakeup_top(struct bttv *btv) do_gettimeofday(&wakeup->vb.ts); wakeup->vb.field_count = btv->field_count; - wakeup->vb.state = STATE_DONE; + wakeup->vb.state = VIDEOBUF_DONE; wake_up(&wakeup->vb.done); spin_unlock(&btv->s_lock); } @@ -4393,7 +3990,7 @@ bttv_irq_switch_video(struct bttv *btv) } /* wake up finished buffers */ - bttv_irq_wakeup_video(btv, &old, &new, STATE_DONE); + bttv_irq_wakeup_video(btv, &old, &new, VIDEOBUF_DONE); spin_unlock(&btv->s_lock); } @@ -4426,7 +4023,7 @@ bttv_irq_switch_vbi(struct bttv *btv) bttv_buffer_activate_vbi(btv, new); bttv_set_dma(btv, 0); - bttv_irq_wakeup_vbi(btv, old, STATE_DONE); + bttv_irq_wakeup_vbi(btv, old, VIDEOBUF_DONE); spin_unlock(&btv->s_lock); } @@ -4548,8 +4145,9 @@ static irqreturn_t bttv_irq(int irq, void *dev_id) /* initialitation */ static struct video_device *vdev_init(struct bttv *btv, - struct video_device *template, - char *type) + const struct video_device *template, + const char *type_name, + const int type) { struct video_device *vfd; @@ -4560,9 +4158,10 @@ static struct video_device *vdev_init(struct bttv *btv, vfd->minor = -1; vfd->dev = &btv->c.pci->dev; vfd->release = video_device_release; + vfd->type = type; snprintf(vfd->name, sizeof(vfd->name), "BT%d%s %s (%s)", btv->id, (btv->id==848 && btv->revision==0x12) ? "A" : "", - type, bttv_tvcards[btv->c.type].name); + type_name, bttv_tvcards[btv->c.type].name); return vfd; } @@ -4594,6 +4193,11 @@ static void bttv_unregister_video(struct bttv *btv) /* register video4linux devices */ static int __devinit bttv_register_video(struct bttv *btv) { + int video_type = VID_TYPE_CAPTURE | + VID_TYPE_TUNER | + VID_TYPE_CLIPPING| + VID_TYPE_SCALES; + if (no_overlay <= 0) { bttv_video_template.type |= VID_TYPE_OVERLAY; } else { @@ -4601,7 +4205,9 @@ static int __devinit bttv_register_video(struct bttv *btv) } /* video */ - btv->video_dev = vdev_init(btv, &bttv_video_template, "video"); + btv->video_dev = vdev_init(btv, &bttv_video_template, + "video", video_type); + if (NULL == btv->video_dev) goto err; if (video_register_device(btv->video_dev,VFL_TYPE_GRABBER,video_nr)<0) @@ -4616,7 +4222,9 @@ static int __devinit bttv_register_video(struct bttv *btv) } /* vbi */ - btv->vbi_dev = vdev_init(btv, &bttv_vbi_template, "vbi"); + btv->vbi_dev = vdev_init(btv, &bttv_video_template, + "vbi", VID_TYPE_TUNER | VID_TYPE_TELETEXT); + if (NULL == btv->vbi_dev) goto err; if (video_register_device(btv->vbi_dev,VFL_TYPE_VBI,vbi_nr)<0) @@ -4627,7 +4235,8 @@ static int __devinit bttv_register_video(struct bttv *btv) if (!btv->has_radio) return 0; /* radio */ - btv->radio_dev = vdev_init(btv, &radio_template, "radio"); + btv->radio_dev = vdev_init(btv, &radio_template, + "radio", VID_TYPE_TUNER); if (NULL == btv->radio_dev) goto err; if (video_register_device(btv->radio_dev, VFL_TYPE_RADIO,radio_nr)<0) @@ -4768,7 +4377,7 @@ static int __devinit bttv_probe(struct pci_dev *dev, btv->init.btv = btv; btv->init.ov.w.width = 320; btv->init.ov.w.height = 240; - btv->init.fmt = format_by_palette(VIDEO_PALETTE_RGB24); + btv->init.fmt = format_by_fourcc(V4L2_PIX_FMT_BGR24); btv->init.width = 320; btv->init.height = 240; btv->input = 0; @@ -5013,14 +4622,17 @@ static int __init bttv_init_module(void) printk(KERN_WARNING "bttv: bus_register error: %d\n", ret); return ret; } - return pci_register_driver(&bttv_pci_driver); + ret = pci_register_driver(&bttv_pci_driver); + if (ret < 0) + bus_unregister(&bttv_sub_bus_type); + + return ret; } static void __exit bttv_cleanup_module(void) { pci_unregister_driver(&bttv_pci_driver); bus_unregister(&bttv_sub_bus_type); - return; } module_init(bttv_init_module); |