|
@@ -9,6 +9,12 @@
|
|
|
some v4l2 code lines are taken from Justin's bttv2 driver which is
|
|
some v4l2 code lines are taken from Justin's bttv2 driver which is
|
|
|
(c) 2000 Justin Schoeman <justin@suntiger.ee.up.ac.za>
|
|
(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
|
|
Cropping and overscan support
|
|
|
Copyright (C) 2005, 2006 Michael H. Schimek <mschimek@gmx.at>
|
|
Copyright (C) 2005, 2006 Michael H. Schimek <mschimek@gmx.at>
|
|
|
Sponsored by OPQ Systems AB
|
|
Sponsored by OPQ Systems AB
|
|
@@ -157,7 +163,7 @@ MODULE_LICENSE("GPL");
|
|
|
static ssize_t show_card(struct device *cd,
|
|
static ssize_t show_card(struct device *cd,
|
|
|
struct device_attribute *attr, char *buf)
|
|
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);
|
|
struct bttv *btv = dev_get_drvdata(vfd->dev);
|
|
|
return sprintf(buf, "%d\n", btv ? btv->c.type : UNSET);
|
|
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
|
|
/* bttv format list
|
|
|
packed pixel formats must come first */
|
|
packed pixel formats must come first */
|
|
|
-static const struct bttv_format bttv_formats[] = {
|
|
|
|
|
|
|
+static const struct bttv_format formats[] = {
|
|
|
{
|
|
{
|
|
|
.name = "8 bpp, gray",
|
|
.name = "8 bpp, gray",
|
|
|
- .palette = VIDEO_PALETTE_GREY,
|
|
|
|
|
.fourcc = V4L2_PIX_FMT_GREY,
|
|
.fourcc = V4L2_PIX_FMT_GREY,
|
|
|
.btformat = BT848_COLOR_FMT_Y8,
|
|
.btformat = BT848_COLOR_FMT_Y8,
|
|
|
.depth = 8,
|
|
.depth = 8,
|
|
|
.flags = FORMAT_FLAGS_PACKED,
|
|
.flags = FORMAT_FLAGS_PACKED,
|
|
|
},{
|
|
},{
|
|
|
.name = "8 bpp, dithered color",
|
|
.name = "8 bpp, dithered color",
|
|
|
- .palette = VIDEO_PALETTE_HI240,
|
|
|
|
|
.fourcc = V4L2_PIX_FMT_HI240,
|
|
.fourcc = V4L2_PIX_FMT_HI240,
|
|
|
.btformat = BT848_COLOR_FMT_RGB8,
|
|
.btformat = BT848_COLOR_FMT_RGB8,
|
|
|
.depth = 8,
|
|
.depth = 8,
|
|
|
.flags = FORMAT_FLAGS_PACKED | FORMAT_FLAGS_DITHER,
|
|
.flags = FORMAT_FLAGS_PACKED | FORMAT_FLAGS_DITHER,
|
|
|
},{
|
|
},{
|
|
|
.name = "15 bpp RGB, le",
|
|
.name = "15 bpp RGB, le",
|
|
|
- .palette = VIDEO_PALETTE_RGB555,
|
|
|
|
|
.fourcc = V4L2_PIX_FMT_RGB555,
|
|
.fourcc = V4L2_PIX_FMT_RGB555,
|
|
|
.btformat = BT848_COLOR_FMT_RGB15,
|
|
.btformat = BT848_COLOR_FMT_RGB15,
|
|
|
.depth = 16,
|
|
.depth = 16,
|
|
|
.flags = FORMAT_FLAGS_PACKED,
|
|
.flags = FORMAT_FLAGS_PACKED,
|
|
|
},{
|
|
},{
|
|
|
.name = "15 bpp RGB, be",
|
|
.name = "15 bpp RGB, be",
|
|
|
- .palette = -1,
|
|
|
|
|
.fourcc = V4L2_PIX_FMT_RGB555X,
|
|
.fourcc = V4L2_PIX_FMT_RGB555X,
|
|
|
.btformat = BT848_COLOR_FMT_RGB15,
|
|
.btformat = BT848_COLOR_FMT_RGB15,
|
|
|
.btswap = 0x03, /* byteswap */
|
|
.btswap = 0x03, /* byteswap */
|
|
@@ -502,14 +504,12 @@ static const struct bttv_format bttv_formats[] = {
|
|
|
.flags = FORMAT_FLAGS_PACKED,
|
|
.flags = FORMAT_FLAGS_PACKED,
|
|
|
},{
|
|
},{
|
|
|
.name = "16 bpp RGB, le",
|
|
.name = "16 bpp RGB, le",
|
|
|
- .palette = VIDEO_PALETTE_RGB565,
|
|
|
|
|
.fourcc = V4L2_PIX_FMT_RGB565,
|
|
.fourcc = V4L2_PIX_FMT_RGB565,
|
|
|
.btformat = BT848_COLOR_FMT_RGB16,
|
|
.btformat = BT848_COLOR_FMT_RGB16,
|
|
|
.depth = 16,
|
|
.depth = 16,
|
|
|
.flags = FORMAT_FLAGS_PACKED,
|
|
.flags = FORMAT_FLAGS_PACKED,
|
|
|
},{
|
|
},{
|
|
|
.name = "16 bpp RGB, be",
|
|
.name = "16 bpp RGB, be",
|
|
|
- .palette = -1,
|
|
|
|
|
.fourcc = V4L2_PIX_FMT_RGB565X,
|
|
.fourcc = V4L2_PIX_FMT_RGB565X,
|
|
|
.btformat = BT848_COLOR_FMT_RGB16,
|
|
.btformat = BT848_COLOR_FMT_RGB16,
|
|
|
.btswap = 0x03, /* byteswap */
|
|
.btswap = 0x03, /* byteswap */
|
|
@@ -517,21 +517,18 @@ static const struct bttv_format bttv_formats[] = {
|
|
|
.flags = FORMAT_FLAGS_PACKED,
|
|
.flags = FORMAT_FLAGS_PACKED,
|
|
|
},{
|
|
},{
|
|
|
.name = "24 bpp RGB, le",
|
|
.name = "24 bpp RGB, le",
|
|
|
- .palette = VIDEO_PALETTE_RGB24,
|
|
|
|
|
.fourcc = V4L2_PIX_FMT_BGR24,
|
|
.fourcc = V4L2_PIX_FMT_BGR24,
|
|
|
.btformat = BT848_COLOR_FMT_RGB24,
|
|
.btformat = BT848_COLOR_FMT_RGB24,
|
|
|
.depth = 24,
|
|
.depth = 24,
|
|
|
.flags = FORMAT_FLAGS_PACKED,
|
|
.flags = FORMAT_FLAGS_PACKED,
|
|
|
},{
|
|
},{
|
|
|
.name = "32 bpp RGB, le",
|
|
.name = "32 bpp RGB, le",
|
|
|
- .palette = VIDEO_PALETTE_RGB32,
|
|
|
|
|
.fourcc = V4L2_PIX_FMT_BGR32,
|
|
.fourcc = V4L2_PIX_FMT_BGR32,
|
|
|
.btformat = BT848_COLOR_FMT_RGB32,
|
|
.btformat = BT848_COLOR_FMT_RGB32,
|
|
|
.depth = 32,
|
|
.depth = 32,
|
|
|
.flags = FORMAT_FLAGS_PACKED,
|
|
.flags = FORMAT_FLAGS_PACKED,
|
|
|
},{
|
|
},{
|
|
|
.name = "32 bpp RGB, be",
|
|
.name = "32 bpp RGB, be",
|
|
|
- .palette = -1,
|
|
|
|
|
.fourcc = V4L2_PIX_FMT_RGB32,
|
|
.fourcc = V4L2_PIX_FMT_RGB32,
|
|
|
.btformat = BT848_COLOR_FMT_RGB32,
|
|
.btformat = BT848_COLOR_FMT_RGB32,
|
|
|
.btswap = 0x0f, /* byte+word swap */
|
|
.btswap = 0x0f, /* byte+word swap */
|
|
@@ -539,21 +536,18 @@ static const struct bttv_format bttv_formats[] = {
|
|
|
.flags = FORMAT_FLAGS_PACKED,
|
|
.flags = FORMAT_FLAGS_PACKED,
|
|
|
},{
|
|
},{
|
|
|
.name = "4:2:2, packed, YUYV",
|
|
.name = "4:2:2, packed, YUYV",
|
|
|
- .palette = VIDEO_PALETTE_YUV422,
|
|
|
|
|
.fourcc = V4L2_PIX_FMT_YUYV,
|
|
.fourcc = V4L2_PIX_FMT_YUYV,
|
|
|
.btformat = BT848_COLOR_FMT_YUY2,
|
|
.btformat = BT848_COLOR_FMT_YUY2,
|
|
|
.depth = 16,
|
|
.depth = 16,
|
|
|
.flags = FORMAT_FLAGS_PACKED,
|
|
.flags = FORMAT_FLAGS_PACKED,
|
|
|
},{
|
|
},{
|
|
|
.name = "4:2:2, packed, YUYV",
|
|
.name = "4:2:2, packed, YUYV",
|
|
|
- .palette = VIDEO_PALETTE_YUYV,
|
|
|
|
|
.fourcc = V4L2_PIX_FMT_YUYV,
|
|
.fourcc = V4L2_PIX_FMT_YUYV,
|
|
|
.btformat = BT848_COLOR_FMT_YUY2,
|
|
.btformat = BT848_COLOR_FMT_YUY2,
|
|
|
.depth = 16,
|
|
.depth = 16,
|
|
|
.flags = FORMAT_FLAGS_PACKED,
|
|
.flags = FORMAT_FLAGS_PACKED,
|
|
|
},{
|
|
},{
|
|
|
.name = "4:2:2, packed, UYVY",
|
|
.name = "4:2:2, packed, UYVY",
|
|
|
- .palette = VIDEO_PALETTE_UYVY,
|
|
|
|
|
.fourcc = V4L2_PIX_FMT_UYVY,
|
|
.fourcc = V4L2_PIX_FMT_UYVY,
|
|
|
.btformat = BT848_COLOR_FMT_YUY2,
|
|
.btformat = BT848_COLOR_FMT_YUY2,
|
|
|
.btswap = 0x03, /* byteswap */
|
|
.btswap = 0x03, /* byteswap */
|
|
@@ -561,7 +555,6 @@ static const struct bttv_format bttv_formats[] = {
|
|
|
.flags = FORMAT_FLAGS_PACKED,
|
|
.flags = FORMAT_FLAGS_PACKED,
|
|
|
},{
|
|
},{
|
|
|
.name = "4:2:2, planar, Y-Cb-Cr",
|
|
.name = "4:2:2, planar, Y-Cb-Cr",
|
|
|
- .palette = VIDEO_PALETTE_YUV422P,
|
|
|
|
|
.fourcc = V4L2_PIX_FMT_YUV422P,
|
|
.fourcc = V4L2_PIX_FMT_YUV422P,
|
|
|
.btformat = BT848_COLOR_FMT_YCrCb422,
|
|
.btformat = BT848_COLOR_FMT_YCrCb422,
|
|
|
.depth = 16,
|
|
.depth = 16,
|
|
@@ -570,7 +563,6 @@ static const struct bttv_format bttv_formats[] = {
|
|
|
.vshift = 0,
|
|
.vshift = 0,
|
|
|
},{
|
|
},{
|
|
|
.name = "4:2:0, planar, Y-Cb-Cr",
|
|
.name = "4:2:0, planar, Y-Cb-Cr",
|
|
|
- .palette = VIDEO_PALETTE_YUV420P,
|
|
|
|
|
.fourcc = V4L2_PIX_FMT_YUV420,
|
|
.fourcc = V4L2_PIX_FMT_YUV420,
|
|
|
.btformat = BT848_COLOR_FMT_YCrCb422,
|
|
.btformat = BT848_COLOR_FMT_YCrCb422,
|
|
|
.depth = 12,
|
|
.depth = 12,
|
|
@@ -579,7 +571,6 @@ static const struct bttv_format bttv_formats[] = {
|
|
|
.vshift = 1,
|
|
.vshift = 1,
|
|
|
},{
|
|
},{
|
|
|
.name = "4:2:0, planar, Y-Cr-Cb",
|
|
.name = "4:2:0, planar, Y-Cr-Cb",
|
|
|
- .palette = -1,
|
|
|
|
|
.fourcc = V4L2_PIX_FMT_YVU420,
|
|
.fourcc = V4L2_PIX_FMT_YVU420,
|
|
|
.btformat = BT848_COLOR_FMT_YCrCb422,
|
|
.btformat = BT848_COLOR_FMT_YCrCb422,
|
|
|
.depth = 12,
|
|
.depth = 12,
|
|
@@ -588,7 +579,6 @@ static const struct bttv_format bttv_formats[] = {
|
|
|
.vshift = 1,
|
|
.vshift = 1,
|
|
|
},{
|
|
},{
|
|
|
.name = "4:1:1, planar, Y-Cb-Cr",
|
|
.name = "4:1:1, planar, Y-Cb-Cr",
|
|
|
- .palette = VIDEO_PALETTE_YUV411P,
|
|
|
|
|
.fourcc = V4L2_PIX_FMT_YUV411P,
|
|
.fourcc = V4L2_PIX_FMT_YUV411P,
|
|
|
.btformat = BT848_COLOR_FMT_YCrCb411,
|
|
.btformat = BT848_COLOR_FMT_YCrCb411,
|
|
|
.depth = 12,
|
|
.depth = 12,
|
|
@@ -597,7 +587,6 @@ static const struct bttv_format bttv_formats[] = {
|
|
|
.vshift = 0,
|
|
.vshift = 0,
|
|
|
},{
|
|
},{
|
|
|
.name = "4:1:0, planar, Y-Cb-Cr",
|
|
.name = "4:1:0, planar, Y-Cb-Cr",
|
|
|
- .palette = VIDEO_PALETTE_YUV410P,
|
|
|
|
|
.fourcc = V4L2_PIX_FMT_YUV410,
|
|
.fourcc = V4L2_PIX_FMT_YUV410,
|
|
|
.btformat = BT848_COLOR_FMT_YCrCb411,
|
|
.btformat = BT848_COLOR_FMT_YCrCb411,
|
|
|
.depth = 9,
|
|
.depth = 9,
|
|
@@ -606,7 +595,6 @@ static const struct bttv_format bttv_formats[] = {
|
|
|
.vshift = 2,
|
|
.vshift = 2,
|
|
|
},{
|
|
},{
|
|
|
.name = "4:1:0, planar, Y-Cr-Cb",
|
|
.name = "4:1:0, planar, Y-Cr-Cb",
|
|
|
- .palette = -1,
|
|
|
|
|
.fourcc = V4L2_PIX_FMT_YVU410,
|
|
.fourcc = V4L2_PIX_FMT_YVU410,
|
|
|
.btformat = BT848_COLOR_FMT_YCrCb411,
|
|
.btformat = BT848_COLOR_FMT_YCrCb411,
|
|
|
.depth = 9,
|
|
.depth = 9,
|
|
@@ -615,14 +603,13 @@ static const struct bttv_format bttv_formats[] = {
|
|
|
.vshift = 2,
|
|
.vshift = 2,
|
|
|
},{
|
|
},{
|
|
|
.name = "raw scanlines",
|
|
.name = "raw scanlines",
|
|
|
- .palette = VIDEO_PALETTE_RAW,
|
|
|
|
|
.fourcc = -1,
|
|
.fourcc = -1,
|
|
|
.btformat = BT848_COLOR_FMT_RAW,
|
|
.btformat = BT848_COLOR_FMT_RAW,
|
|
|
.depth = 8,
|
|
.depth = 8,
|
|
|
.flags = FORMAT_FLAGS_RAW,
|
|
.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 */
|
|
/* resource management */
|
|
@@ -1254,16 +1251,6 @@ audio_input(struct bttv *btv, int input)
|
|
|
return audio_mux(btv, input, btv->mute);
|
|
return audio_mux(btv, input, btv->mute);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-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
|
|
static void
|
|
|
bttv_crop_calc_limits(struct bttv_crop *c)
|
|
bttv_crop_calc_limits(struct bttv_crop *c)
|
|
|
{
|
|
{
|
|
@@ -1298,6 +1285,7 @@ static int
|
|
|
set_tvnorm(struct bttv *btv, unsigned int norm)
|
|
set_tvnorm(struct bttv *btv, unsigned int norm)
|
|
|
{
|
|
{
|
|
|
const struct bttv_tvnorm *tvnorm;
|
|
const struct bttv_tvnorm *tvnorm;
|
|
|
|
|
+ v4l2_std_id id;
|
|
|
|
|
|
|
|
if (norm < 0 || norm >= BTTV_TVNORMS)
|
|
if (norm < 0 || norm >= BTTV_TVNORMS)
|
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
@@ -1334,6 +1322,9 @@ set_tvnorm(struct bttv *btv, unsigned int norm)
|
|
|
bttv_tda9880_setnorm(btv,norm);
|
|
bttv_tda9880_setnorm(btv,norm);
|
|
|
break;
|
|
break;
|
|
|
}
|
|
}
|
|
|
|
|
+ id = tvnorm->v4l2_id;
|
|
|
|
|
+ bttv_call_i2c_clients(btv, VIDIOC_S_STD, &id);
|
|
|
|
|
+
|
|
|
return 0;
|
|
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 ?
|
|
audio_input(btv,(input == bttv_tvcards[btv->c.type].tuner ?
|
|
|
TVAUDIO_INPUT_TUNER : TVAUDIO_INPUT_EXTERN));
|
|
TVAUDIO_INPUT_TUNER : TVAUDIO_INPUT_EXTERN));
|
|
|
set_tvnorm(btv, norm);
|
|
set_tvnorm(btv, norm);
|
|
|
- i2c_vidiocschan(btv);
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
static void init_irqreg(struct bttv *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);
|
|
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) {
|
|
switch (c->id) {
|
|
|
case V4L2_CID_BRIGHTNESS:
|
|
case V4L2_CID_BRIGHTNESS:
|
|
|
c->value = btv->bright;
|
|
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_BALANCE:
|
|
|
case V4L2_CID_AUDIO_BASS:
|
|
case V4L2_CID_AUDIO_BASS:
|
|
|
case V4L2_CID_AUDIO_TREBLE:
|
|
case V4L2_CID_AUDIO_TREBLE:
|
|
|
- bttv_call_i2c_clients(btv,VIDIOC_G_CTRL,c);
|
|
|
|
|
|
|
+ bttv_call_i2c_clients(btv, VIDIOC_G_CTRL, c);
|
|
|
break;
|
|
break;
|
|
|
|
|
|
|
|
case V4L2_CID_PRIVATE_CHROMA_AGC:
|
|
case V4L2_CID_PRIVATE_CHROMA_AGC:
|
|
@@ -1545,67 +1509,44 @@ static int get_control(struct bttv *btv, struct v4l2_control *c)
|
|
|
return 0;
|
|
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) {
|
|
switch (c->id) {
|
|
|
case V4L2_CID_BRIGHTNESS:
|
|
case V4L2_CID_BRIGHTNESS:
|
|
|
- bt848_bright(btv,c->value);
|
|
|
|
|
|
|
+ bt848_bright(btv, c->value);
|
|
|
break;
|
|
break;
|
|
|
case V4L2_CID_HUE:
|
|
case V4L2_CID_HUE:
|
|
|
- bt848_hue(btv,c->value);
|
|
|
|
|
|
|
+ bt848_hue(btv, c->value);
|
|
|
break;
|
|
break;
|
|
|
case V4L2_CID_CONTRAST:
|
|
case V4L2_CID_CONTRAST:
|
|
|
- bt848_contrast(btv,c->value);
|
|
|
|
|
|
|
+ bt848_contrast(btv, c->value);
|
|
|
break;
|
|
break;
|
|
|
case V4L2_CID_SATURATION:
|
|
case V4L2_CID_SATURATION:
|
|
|
- bt848_sat(btv,c->value);
|
|
|
|
|
|
|
+ bt848_sat(btv, c->value);
|
|
|
break;
|
|
break;
|
|
|
case V4L2_CID_AUDIO_MUTE:
|
|
case V4L2_CID_AUDIO_MUTE:
|
|
|
audio_mute(btv, c->value);
|
|
audio_mute(btv, c->value);
|
|
|
/* fall through */
|
|
/* fall through */
|
|
|
case V4L2_CID_AUDIO_VOLUME:
|
|
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_BALANCE:
|
|
|
case V4L2_CID_AUDIO_BASS:
|
|
case V4L2_CID_AUDIO_BASS:
|
|
|
case V4L2_CID_AUDIO_TREBLE:
|
|
case V4L2_CID_AUDIO_TREBLE:
|
|
|
- bttv_call_i2c_clients(btv,VIDIOC_S_CTRL,c);
|
|
|
|
|
|
|
+ bttv_call_i2c_clients(btv, VIDIOC_S_CTRL, c);
|
|
|
break;
|
|
break;
|
|
|
|
|
|
|
|
case V4L2_CID_PRIVATE_CHROMA_AGC:
|
|
case V4L2_CID_PRIVATE_CHROMA_AGC:
|
|
@@ -1632,8 +1573,9 @@ static int set_control(struct bttv *btv, struct v4l2_control *c)
|
|
|
break;
|
|
break;
|
|
|
case V4L2_CID_PRIVATE_AGC_CRUSH:
|
|
case V4L2_CID_PRIVATE_AGC_CRUSH:
|
|
|
btv->opt_adc_crush = c->value;
|
|
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;
|
|
break;
|
|
|
case V4L2_CID_PRIVATE_VCR_HACK:
|
|
case V4L2_CID_PRIVATE_VCR_HACK:
|
|
|
btv->opt_vcr_hack = c->value;
|
|
btv->opt_vcr_hack = c->value;
|
|
@@ -1692,30 +1634,16 @@ 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*
|
|
static const struct bttv_format*
|
|
|
format_by_fourcc(int fourcc)
|
|
format_by_fourcc(int fourcc)
|
|
|
{
|
|
{
|
|
|
unsigned int i;
|
|
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;
|
|
continue;
|
|
|
- if (bttv_formats[i].fourcc == fourcc)
|
|
|
|
|
- return bttv_formats+i;
|
|
|
|
|
|
|
+ if (formats[i].fourcc == fourcc)
|
|
|
|
|
+ return formats+i;
|
|
|
}
|
|
}
|
|
|
return NULL;
|
|
return NULL;
|
|
|
}
|
|
}
|
|
@@ -1733,7 +1661,7 @@ bttv_switch_overlay(struct bttv *btv, struct bttv_fh *fh,
|
|
|
|
|
|
|
|
dprintk("switch_overlay: enter [new=%p]\n",new);
|
|
dprintk("switch_overlay: enter [new=%p]\n",new);
|
|
|
if (new)
|
|
if (new)
|
|
|
- new->vb.state = STATE_DONE;
|
|
|
|
|
|
|
+ new->vb.state = VIDEOBUF_DONE;
|
|
|
spin_lock_irqsave(&btv->s_lock,flags);
|
|
spin_lock_irqsave(&btv->s_lock,flags);
|
|
|
old = btv->screen;
|
|
old = btv->screen;
|
|
|
btv->screen = new;
|
|
btv->screen = new;
|
|
@@ -1844,7 +1772,7 @@ static int bttv_prepare_buffer(struct videobuf_queue *q,struct bttv *btv,
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/* alloc risc memory */
|
|
/* alloc risc memory */
|
|
|
- if (STATE_NEEDS_INIT == buf->vb.state) {
|
|
|
|
|
|
|
+ if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
|
|
|
redo_dma_risc = 1;
|
|
redo_dma_risc = 1;
|
|
|
if (0 != (rc = videobuf_iolock(q,&buf->vb,&btv->fbuf)))
|
|
if (0 != (rc = videobuf_iolock(q,&buf->vb,&btv->fbuf)))
|
|
|
goto fail;
|
|
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)))
|
|
if (0 != (rc = bttv_buffer_risc(btv,buf)))
|
|
|
goto fail;
|
|
goto fail;
|
|
|
|
|
|
|
|
- buf->vb.state = STATE_PREPARED;
|
|
|
|
|
|
|
+ buf->vb.state = VIDEOBUF_PREPARED;
|
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
|
|
fail:
|
|
fail:
|
|
@@ -1893,7 +1821,7 @@ buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
|
|
|
struct bttv_fh *fh = q->priv_data;
|
|
struct bttv_fh *fh = q->priv_data;
|
|
|
struct bttv *btv = fh->btv;
|
|
struct bttv *btv = fh->btv;
|
|
|
|
|
|
|
|
- buf->vb.state = STATE_QUEUED;
|
|
|
|
|
|
|
+ buf->vb.state = VIDEOBUF_QUEUED;
|
|
|
list_add_tail(&buf->vb.queue,&btv->capture);
|
|
list_add_tail(&buf->vb.queue,&btv->capture);
|
|
|
if (!btv->curr.frame_irq) {
|
|
if (!btv->curr.frame_irq) {
|
|
|
btv->loop_irq |= 1;
|
|
btv->loop_irq |= 1;
|
|
@@ -1916,399 +1844,259 @@ static struct videobuf_queue_ops bttv_video_qops = {
|
|
|
.buf_release = buffer_release,
|
|
.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;
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
- 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_s_frequency(struct file *file, void *priv,
|
|
|
|
|
+ struct v4l2_frequency *f)
|
|
|
|
|
+{
|
|
|
|
|
+ struct bttv_fh *fh = priv;
|
|
|
|
|
+ struct bttv *btv = fh->btv;
|
|
|
|
|
+ int err;
|
|
|
|
|
|
|
|
- default:
|
|
|
|
|
- return -ENOIOCTLCMD;
|
|
|
|
|
|
|
+ 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;
|
|
return 0;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-/* Given cropping boundaries b and the scaled width and height of a
|
|
|
|
|
- single field or frame, which must not exceed hardware limits, this
|
|
|
|
|
- function adjusts the cropping parameters c. */
|
|
|
|
|
-static void
|
|
|
|
|
-bttv_crop_adjust (struct bttv_crop * c,
|
|
|
|
|
- const struct v4l2_rect * b,
|
|
|
|
|
- __s32 width,
|
|
|
|
|
- __s32 height,
|
|
|
|
|
- enum v4l2_field field)
|
|
|
|
|
|
|
+static int bttv_log_status(struct file *file, void *f)
|
|
|
{
|
|
{
|
|
|
- __s32 frame_height = height << !V4L2_FIELD_HAS_BOTH(field);
|
|
|
|
|
- __s32 max_left;
|
|
|
|
|
- __s32 max_top;
|
|
|
|
|
|
|
+ struct bttv_fh *fh = f;
|
|
|
|
|
+ struct bttv *btv = fh->btv;
|
|
|
|
|
|
|
|
- if (width < c->min_scaled_width) {
|
|
|
|
|
- /* Max. hor. scale factor 16:1. */
|
|
|
|
|
- c->rect.width = width * 16;
|
|
|
|
|
- } else if (width > c->max_scaled_width) {
|
|
|
|
|
- /* Min. hor. scale factor 1:1. */
|
|
|
|
|
- c->rect.width = width;
|
|
|
|
|
|
|
+ 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;
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
- max_left = b->left + b->width - width;
|
|
|
|
|
- max_left = min(max_left, (__s32) MAX_HDELAY);
|
|
|
|
|
- if (c->rect.left > max_left)
|
|
|
|
|
|
|
+#ifdef CONFIG_VIDEO_ADV_DEBUG
|
|
|
|
|
+static int bttv_g_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;
|
|
|
|
|
+ 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
|
|
|
|
|
+ function adjusts the cropping parameters c. */
|
|
|
|
|
+static void
|
|
|
|
|
+bttv_crop_adjust (struct bttv_crop * c,
|
|
|
|
|
+ const struct v4l2_rect * b,
|
|
|
|
|
+ __s32 width,
|
|
|
|
|
+ __s32 height,
|
|
|
|
|
+ enum v4l2_field field)
|
|
|
|
|
+{
|
|
|
|
|
+ __s32 frame_height = height << !V4L2_FIELD_HAS_BOTH(field);
|
|
|
|
|
+ __s32 max_left;
|
|
|
|
|
+ __s32 max_top;
|
|
|
|
|
+
|
|
|
|
|
+ if (width < c->min_scaled_width) {
|
|
|
|
|
+ /* Max. hor. scale factor 16:1. */
|
|
|
|
|
+ c->rect.width = width * 16;
|
|
|
|
|
+ } else if (width > c->max_scaled_width) {
|
|
|
|
|
+ /* Min. hor. scale factor 1:1. */
|
|
|
|
|
+ c->rect.width = width;
|
|
|
|
|
+
|
|
|
|
|
+ max_left = b->left + b->width - width;
|
|
|
|
|
+ max_left = min(max_left, (__s32) MAX_HDELAY);
|
|
|
|
|
+ if (c->rect.left > max_left)
|
|
|
c->rect.left = max_left;
|
|
c->rect.left = max_left;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -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:
|
|
default:
|
|
|
return -EINVAL;
|
|
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_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(struct bttv_fh *fh, struct bttv *btv,
|
|
|
|
|
- struct v4l2_format *f)
|
|
|
|
|
|
|
+static int bttv_s_fmt_cap(struct file *file, void *priv,
|
|
|
|
|
+ struct v4l2_format *f)
|
|
|
{
|
|
{
|
|
|
int retval;
|
|
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:
|
|
|
|
|
|
|
+ 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;
|
|
|
|
|
+
|
|
|
|
|
+ f->fmt.pix.field = field;
|
|
|
|
|
+
|
|
|
|
|
+ fmt = format_by_fourcc(f->fmt.pix.pixelformat);
|
|
|
|
|
+
|
|
|
|
|
+ /* 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);
|
|
|
|
|
+
|
|
|
|
|
+ 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;
|
|
|
|
|
+
|
|
|
|
|
+ if (no_overlay > 0) {
|
|
|
|
|
+ printk(KERN_ERR "V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
|
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ return setup_window(fh, btv, &f->fmt.win, 1);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-static int bttv_do_ioctl(struct inode *inode, struct file *file,
|
|
|
|
|
- unsigned int cmd, void *arg)
|
|
|
|
|
|
|
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
|
|
|
|
|
+static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf)
|
|
|
{
|
|
{
|
|
|
- struct bttv_fh *fh = file->private_data;
|
|
|
|
|
- struct bttv *btv = fh->btv;
|
|
|
|
|
- unsigned long flags;
|
|
|
|
|
- int retval = 0;
|
|
|
|
|
|
|
+ int retval;
|
|
|
|
|
+ unsigned int i;
|
|
|
|
|
+ struct bttv_fh *fh = priv;
|
|
|
|
|
|
|
|
- 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;
|
|
|
|
|
- };
|
|
|
|
|
|
|
+ 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 retval;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- switch (cmd) {
|
|
|
|
|
|
|
+ gbuffers = retval;
|
|
|
|
|
+ memset(mbuf, 0, sizeof(*mbuf));
|
|
|
|
|
+ mbuf->frames = gbuffers;
|
|
|
|
|
+ mbuf->size = gbuffers * gbufsize;
|
|
|
|
|
|
|
|
- /* *** v4l1 *** ************************************************ */
|
|
|
|
|
- case VIDIOCGCAP:
|
|
|
|
|
- {
|
|
|
|
|
- struct video_capability *cap = arg;
|
|
|
|
|
|
|
+ for (i = 0; i < gbuffers; i++)
|
|
|
|
|
+ mbuf->offsets[i] = i * gbufsize;
|
|
|
|
|
|
|
|
- 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;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ mutex_unlock(&fh->cap.lock);
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
|
|
|
|
+#endif
|
|
|
|
|
|
|
|
- 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;
|
|
|
|
|
- }
|
|
|
|
|
- case VIDIOCSPICT:
|
|
|
|
|
- {
|
|
|
|
|
- struct video_picture *pic = arg;
|
|
|
|
|
- const struct bttv_format *fmt;
|
|
|
|
|
|
|
+static int bttv_querycap(struct file *file, void *priv,
|
|
|
|
|
+ struct v4l2_capability *cap)
|
|
|
|
|
+{
|
|
|
|
|
+ struct bttv_fh *fh = priv;
|
|
|
|
|
+ struct bttv *btv = fh->btv;
|
|
|
|
|
|
|
|
- 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);
|
|
|
|
|
- mutex_unlock(&fh->cap.lock);
|
|
|
|
|
- return 0;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ if (0 == v4l2)
|
|
|
|
|
+ return -EINVAL;
|
|
|
|
|
|
|
|
- case VIDIOCGWIN:
|
|
|
|
|
- {
|
|
|
|
|
- struct video_window *win = arg;
|
|
|
|
|
|
|
+ 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;
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
- 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;
|
|
|
|
|
|
|
+static int bttv_enum_fmt_vbi(struct file *file, void *priv,
|
|
|
|
|
+ struct v4l2_fmtdesc *f)
|
|
|
|
|
+{
|
|
|
|
|
+ if (0 != f->index)
|
|
|
|
|
+ return -EINVAL;
|
|
|
|
|
|
|
|
- if (no_overlay > 0) {
|
|
|
|
|
- printk ("VIDIOCSWIN: no_overlay\n");
|
|
|
|
|
- return -EINVAL;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ f->pixelformat = V4L2_PIX_FMT_GREY;
|
|
|
|
|
+ strcpy(f->description, "vbi data");
|
|
|
|
|
|
|
|
- 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;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
- 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;
|
|
|
|
|
|
|
+static int bttv_enum_fmt_cap_ovr(struct v4l2_fmtdesc *f)
|
|
|
|
|
+{
|
|
|
|
|
+ int index = -1, i;
|
|
|
|
|
|
|
|
- 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;
|
|
|
|
|
|
|
+ for (i = 0; i < FORMATS; i++) {
|
|
|
|
|
+ if (formats[i].fourcc != -1)
|
|
|
|
|
+ index++;
|
|
|
|
|
+ if ((unsigned int)index == f->index)
|
|
|
break;
|
|
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;
|
|
|
|
|
}
|
|
}
|
|
|
|
|
+ if (FORMATS == i)
|
|
|
|
|
+ return -EINVAL;
|
|
|
|
|
|
|
|
- case VIDIOCCAPTURE:
|
|
|
|
|
- case VIDIOC_OVERLAY:
|
|
|
|
|
- {
|
|
|
|
|
- struct bttv_buffer *new;
|
|
|
|
|
- int *on = arg;
|
|
|
|
|
|
|
+ f->pixelformat = formats[i].fourcc;
|
|
|
|
|
+ strlcpy(f->description, formats[i].name, sizeof(f->description));
|
|
|
|
|
|
|
|
- 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;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ return i;
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
- if (!check_alloc_btres(btv,fh,RESOURCE_OVERLAY))
|
|
|
|
|
- return -EBUSY;
|
|
|
|
|
|
|
+static int bttv_enum_fmt_cap(struct file *file, void *priv,
|
|
|
|
|
+ struct v4l2_fmtdesc *f)
|
|
|
|
|
+{
|
|
|
|
|
+ int rc = bttv_enum_fmt_cap_ovr(f);
|
|
|
|
|
|
|
|
- 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;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ if (rc < 0)
|
|
|
|
|
+ return rc;
|
|
|
|
|
|
|
|
- /* switch over */
|
|
|
|
|
- retval = bttv_switch_overlay(btv,fh,new);
|
|
|
|
|
- mutex_unlock(&fh->cap.lock);
|
|
|
|
|
- return retval;
|
|
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static int bttv_enum_fmt_overlay(struct file *file, void *priv,
|
|
|
|
|
+ struct v4l2_fmtdesc *f)
|
|
|
|
|
+{
|
|
|
|
|
+ int rc;
|
|
|
|
|
+
|
|
|
|
|
+ if (no_overlay > 0) {
|
|
|
|
|
+ printk(KERN_ERR "V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
|
|
|
|
|
+ return -EINVAL;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- case VIDIOCGMBUF:
|
|
|
|
|
- {
|
|
|
|
|
- struct video_mbuf *mbuf = arg;
|
|
|
|
|
- unsigned int i;
|
|
|
|
|
|
|
+ rc = bttv_enum_fmt_cap_ovr(f);
|
|
|
|
|
|
|
|
- retval = videobuf_mmap_setup(&fh->cap,gbuffers,gbufsize,
|
|
|
|
|
- V4L2_MEMORY_MMAP);
|
|
|
|
|
- if (retval < 0)
|
|
|
|
|
- return retval;
|
|
|
|
|
|
|
+ if (rc < 0)
|
|
|
|
|
+ return rc;
|
|
|
|
|
|
|
|
- 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;
|
|
|
|
|
|
|
+ if (!(formats[rc].flags & FORMAT_FLAGS_PACKED))
|
|
|
|
|
+ return -EINVAL;
|
|
|
|
|
|
|
|
- if (vm->frame >= VIDEO_MAX_FRAME)
|
|
|
|
|
- return -EINVAL;
|
|
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
- res = bttv_resource(fh);
|
|
|
|
|
- if (!check_alloc_btres(btv, fh, res))
|
|
|
|
|
- return -EBUSY;
|
|
|
|
|
|
|
+static int bttv_g_fbuf(struct file *file, void *f,
|
|
|
|
|
+ struct v4l2_framebuffer *fb)
|
|
|
|
|
+{
|
|
|
|
|
+ struct bttv_fh *fh = f;
|
|
|
|
|
+ struct bttv *btv = fh->btv;
|
|
|
|
|
|
|
|
- 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;
|
|
|
|
|
|
|
+ *fb = btv->fbuf;
|
|
|
|
|
+ fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING;
|
|
|
|
|
+ if (fh->ovfmt)
|
|
|
|
|
+ fb->fmt.pixelformat = fh->ovfmt->fourcc;
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
- 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;
|
|
|
|
|
- }
|
|
|
|
|
- case VIDIOCSYNC:
|
|
|
|
|
- {
|
|
|
|
|
- int *frame = arg;
|
|
|
|
|
- struct bttv_buffer *buf;
|
|
|
|
|
|
|
+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;
|
|
|
|
|
|
|
|
- if (*frame >= VIDEO_MAX_FRAME)
|
|
|
|
|
|
|
+ if (on) {
|
|
|
|
|
+ /* verify args */
|
|
|
|
|
+ if (NULL == btv->fbuf.base)
|
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
|
+ if (!fh->ov.setup_ok) {
|
|
|
|
|
+ dprintk("bttv%d: overlay: !setup_ok\n", btv->c.nr);
|
|
|
|
|
+ return -EINVAL;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- 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 (!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;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /* switch over */
|
|
|
|
|
+ retval = bttv_switch_overlay(btv, fh, new);
|
|
|
|
|
+ mutex_unlock(&fh->cap.lock);
|
|
|
|
|
+ return retval;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+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;
|
|
|
|
|
+
|
|
|
|
|
+ /* 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)
|
|
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;
|
|
|
|
|
|
|
+ return retval;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- 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;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ /* 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;
|
|
|
|
|
|
|
|
- /* fall through */
|
|
|
|
|
|
|
+ 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;
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
- 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_reqbufs(struct file *file, void *priv,
|
|
|
|
|
+ struct v4l2_requestbuffers *p)
|
|
|
|
|
+{
|
|
|
|
|
+ struct bttv_fh *fh = priv;
|
|
|
|
|
+ return videobuf_reqbufs(bttv_queue(fh), p);
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
- 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;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+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_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_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);
|
|
|
|
|
|
|
|
- /* 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)
|
|
|
|
|
- return -EINVAL;
|
|
|
|
|
|
|
+ if (!check_alloc_btres(btv, fh, res))
|
|
|
|
|
+ return -EBUSY;
|
|
|
|
|
|
|
|
- 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:
|
|
|
|
|
- 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;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ return videobuf_qbuf(bttv_queue(fh), b);
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
- 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);
|
|
|
|
|
- }
|
|
|
|
|
|
|
+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);
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
- case VIDIOC_G_FBUF:
|
|
|
|
|
- {
|
|
|
|
|
- struct v4l2_framebuffer *fb = arg;
|
|
|
|
|
|
|
+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);
|
|
|
|
|
|
|
|
- *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;
|
|
|
|
|
|
|
+ if (!check_alloc_btres(btv, fh, res))
|
|
|
|
|
+ return -EBUSY;
|
|
|
|
|
+ return videobuf_streamon(bttv_queue(fh));
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
- 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;
|
|
|
|
|
|
|
+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);
|
|
|
|
|
|
|
|
- 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);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- mutex_unlock(&fh->cap.lock);
|
|
|
|
|
|
|
+ retval = videobuf_streamoff(bttv_queue(fh));
|
|
|
|
|
+ if (retval < 0)
|
|
|
return retval;
|
|
return retval;
|
|
|
- }
|
|
|
|
|
|
|
+ free_btres(btv, fh, res);
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
- case VIDIOC_REQBUFS:
|
|
|
|
|
- return videobuf_reqbufs(bttv_queue(fh),arg);
|
|
|
|
|
|
|
+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_QUERYBUF:
|
|
|
|
|
- return videobuf_querybuf(bttv_queue(fh),arg);
|
|
|
|
|
|
|
+ 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;
|
|
|
|
|
|
|
|
- case VIDIOC_QBUF:
|
|
|
|
|
- {
|
|
|
|
|
- int res = bttv_resource(fh);
|
|
|
|
|
|
|
+ if (!btv->volume_gpio && (c->id == V4L2_CID_AUDIO_VOLUME))
|
|
|
|
|
+ *c = no_ctl;
|
|
|
|
|
+ else {
|
|
|
|
|
+ ctrl = ctrl_by_id(c->id);
|
|
|
|
|
|
|
|
- if (!check_alloc_btres(btv, fh, res))
|
|
|
|
|
- return -EBUSY;
|
|
|
|
|
- return videobuf_qbuf(bttv_queue(fh),arg);
|
|
|
|
|
|
|
+ *c = (NULL != ctrl) ? *ctrl : no_ctl;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- case VIDIOC_DQBUF:
|
|
|
|
|
- return videobuf_dqbuf(bttv_queue(fh),arg,
|
|
|
|
|
- file->f_flags & O_NONBLOCK);
|
|
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
- case VIDIOC_STREAMON:
|
|
|
|
|
- {
|
|
|
|
|
- int res = bttv_resource(fh);
|
|
|
|
|
|
|
+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 (!check_alloc_btres(btv,fh,res))
|
|
|
|
|
- return -EBUSY;
|
|
|
|
|
- return videobuf_streamon(bttv_queue(fh));
|
|
|
|
|
- }
|
|
|
|
|
- case VIDIOC_STREAMOFF:
|
|
|
|
|
- {
|
|
|
|
|
- int res = bttv_resource(fh);
|
|
|
|
|
|
|
+ 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;
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
- retval = videobuf_streamoff(bttv_queue(fh));
|
|
|
|
|
- if (retval < 0)
|
|
|
|
|
- return retval;
|
|
|
|
|
- free_btres(btv,fh,res);
|
|
|
|
|
- return 0;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+static int bttv_g_tuner(struct file *file, void *priv,
|
|
|
|
|
+ struct v4l2_tuner *t)
|
|
|
|
|
+{
|
|
|
|
|
+ struct bttv_fh *fh = priv;
|
|
|
|
|
+ struct bttv *btv = fh->btv;
|
|
|
|
|
|
|
|
- case VIDIOC_QUERYCTRL:
|
|
|
|
|
- {
|
|
|
|
|
- struct v4l2_queryctrl *c = arg;
|
|
|
|
|
- int i;
|
|
|
|
|
|
|
+ if (UNSET == bttv_tvcards[btv->c.type].tuner)
|
|
|
|
|
+ return -EINVAL;
|
|
|
|
|
+ if (0 != t->index)
|
|
|
|
|
+ return -EINVAL;
|
|
|
|
|
|
|
|
- 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;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ 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);
|
|
|
|
|
|
|
|
- case VIDIOC_G_PRIORITY:
|
|
|
|
|
- {
|
|
|
|
|
- enum v4l2_priority *p = arg;
|
|
|
|
|
|
|
+ mutex_unlock(&btv->lock);
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
- *p = v4l2_prio_max(&btv->prio);
|
|
|
|
|
- return 0;
|
|
|
|
|
- }
|
|
|
|
|
- case VIDIOC_S_PRIORITY:
|
|
|
|
|
- {
|
|
|
|
|
- enum v4l2_priority *prio = arg;
|
|
|
|
|
|
|
+static int bttv_g_priority(struct file *file, void *f, enum v4l2_priority *p)
|
|
|
|
|
+{
|
|
|
|
|
+ struct bttv_fh *fh = f;
|
|
|
|
|
+ struct bttv *btv = fh->btv;
|
|
|
|
|
|
|
|
- return v4l2_prio_change(&btv->prio, &fh->prio, *prio);
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ *p = v4l2_prio_max(&btv->prio);
|
|
|
|
|
|
|
|
- case VIDIOC_CROPCAP:
|
|
|
|
|
- {
|
|
|
|
|
- struct v4l2_cropcap *cap = arg;
|
|
|
|
|
- enum v4l2_buf_type type;
|
|
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
- type = cap->type;
|
|
|
|
|
|
|
+static int bttv_s_priority(struct file *file, void *f,
|
|
|
|
|
+ enum v4l2_priority prio)
|
|
|
|
|
+{
|
|
|
|
|
+ struct bttv_fh *fh = f;
|
|
|
|
|
+ struct bttv *btv = fh->btv;
|
|
|
|
|
|
|
|
- if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
|
|
|
|
|
- type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
|
|
|
|
|
- return -EINVAL;
|
|
|
|
|
|
|
+ return v4l2_prio_change(&btv->prio, &fh->prio, prio);
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
- *cap = bttv_tvnorms[btv->tvnorm].cropcap;
|
|
|
|
|
- cap->type = type;
|
|
|
|
|
|
|
+static int bttv_cropcap(struct file *file, void *priv,
|
|
|
|
|
+ struct v4l2_cropcap *cap)
|
|
|
|
|
+{
|
|
|
|
|
+ struct bttv_fh *fh = priv;
|
|
|
|
|
+ struct bttv *btv = fh->btv;
|
|
|
|
|
|
|
|
- return 0;
|
|
|
|
|
- }
|
|
|
|
|
- case VIDIOC_G_CROP:
|
|
|
|
|
- {
|
|
|
|
|
- struct v4l2_crop * crop = arg;
|
|
|
|
|
|
|
+ if (cap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
|
|
|
|
|
+ cap->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
|
|
|
|
|
+ return -EINVAL;
|
|
|
|
|
|
|
|
- if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
|
|
|
|
|
- crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
|
|
|
|
|
- return -EINVAL;
|
|
|
|
|
|
|
+ *cap = bttv_tvnorms[btv->tvnorm].cropcap;
|
|
|
|
|
|
|
|
- /* 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. */
|
|
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
- crop->c = btv->crop[!!fh->do_crop].rect;
|
|
|
|
|
|
|
+static int bttv_g_crop(struct file *file, void *f, struct v4l2_crop *crop)
|
|
|
|
|
+{
|
|
|
|
|
+ struct bttv_fh *fh = f;
|
|
|
|
|
+ struct bttv *btv = fh->btv;
|
|
|
|
|
|
|
|
- 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;
|
|
|
|
|
|
|
+ if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
|
|
|
|
|
+ crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
|
|
|
|
|
+ return -EINVAL;
|
|
|
|
|
|
|
|
- retval = v4l2_prio_check(&btv->prio,&fh->prio);
|
|
|
|
|
- if (0 != retval)
|
|
|
|
|
- return retval;
|
|
|
|
|
|
|
+ /* 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. */
|
|
|
|
|
|
|
|
- /* 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);
|
|
|
|
|
|
|
+ crop->c = btv->crop[!!fh->do_crop].rect;
|
|
|
|
|
|
|
|
- retval = -EBUSY;
|
|
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
- if (locked_btres(fh->btv, VIDEO_RESOURCES))
|
|
|
|
|
- goto btv_unlock_and_return;
|
|
|
|
|
|
|
+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;
|
|
|
|
|
|
|
|
- b = &bttv_tvnorms[btv->tvnorm].cropcap.bounds;
|
|
|
|
|
|
|
+ if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
|
|
|
|
|
+ crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
|
|
|
|
|
+ return -EINVAL;
|
|
|
|
|
|
|
|
- b_left = b->left;
|
|
|
|
|
- b_right = b_left + b->width;
|
|
|
|
|
- b_bottom = b->top + b->height;
|
|
|
|
|
|
|
+ retval = v4l2_prio_check(&btv->prio, &fh->prio);
|
|
|
|
|
+ if (0 != retval)
|
|
|
|
|
+ return retval;
|
|
|
|
|
|
|
|
- b_top = max(b->top, btv->vbi_end);
|
|
|
|
|
- if (b_top + 32 >= b_bottom)
|
|
|
|
|
- goto btv_unlock_and_return;
|
|
|
|
|
|
|
+ /* 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);
|
|
|
|
|
|
|
|
- /* 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);
|
|
|
|
|
|
|
+ retval = -EBUSY;
|
|
|
|
|
|
|
|
- c.rect.width = clamp(crop->c.width,
|
|
|
|
|
- 48, b_right - c.rect.left);
|
|
|
|
|
|
|
+ if (locked_btres(fh->btv, VIDEO_RESOURCES)) {
|
|
|
|
|
+ mutex_unlock(&btv->lock);
|
|
|
|
|
+ return retval;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- 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;
|
|
|
|
|
|
|
+ b = &bttv_tvnorms[btv->tvnorm].cropcap.bounds;
|
|
|
|
|
|
|
|
- c.rect.height = clamp(crop->c.height,
|
|
|
|
|
- 32, b_bottom - c.rect.top);
|
|
|
|
|
- c.rect.height = (c.rect.height + 1) & ~1;
|
|
|
|
|
|
|
+ b_left = b->left;
|
|
|
|
|
+ b_right = b_left + b->width;
|
|
|
|
|
+ b_bottom = b->top + b->height;
|
|
|
|
|
|
|
|
- bttv_crop_calc_limits(&c);
|
|
|
|
|
|
|
+ b_top = max(b->top, btv->vbi_end);
|
|
|
|
|
+ if (b_top + 32 >= b_bottom) {
|
|
|
|
|
+ mutex_unlock(&btv->lock);
|
|
|
|
|
+ return retval;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- btv->crop[1] = c;
|
|
|
|
|
|
|
+ /* 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);
|
|
|
|
|
|
|
|
- mutex_unlock(&btv->lock);
|
|
|
|
|
|
|
+ c.rect.width = clamp(crop->c.width,
|
|
|
|
|
+ 48, b_right - c.rect.left);
|
|
|
|
|
|
|
|
- fh->do_crop = 1;
|
|
|
|
|
|
|
+ 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;
|
|
|
|
|
|
|
|
- mutex_lock(&fh->cap.lock);
|
|
|
|
|
|
|
+ c.rect.height = clamp(crop->c.height,
|
|
|
|
|
+ 32, b_bottom - c.rect.top);
|
|
|
|
|
+ c.rect.height = (c.rect.height + 1) & ~1;
|
|
|
|
|
|
|
|
- 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;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ bttv_crop_calc_limits(&c);
|
|
|
|
|
|
|
|
- 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;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ btv->crop[1] = c;
|
|
|
|
|
|
|
|
- mutex_unlock(&fh->cap.lock);
|
|
|
|
|
|
|
+ mutex_unlock(&btv->lock);
|
|
|
|
|
|
|
|
- return 0;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ fh->do_crop = 1;
|
|
|
|
|
|
|
|
- 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);
|
|
|
|
|
|
|
+ mutex_lock(&fh->cap.lock);
|
|
|
|
|
|
|
|
- default:
|
|
|
|
|
- return -ENOIOCTLCMD;
|
|
|
|
|
|
|
+ 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 (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;
|
|
|
}
|
|
}
|
|
|
- return 0;
|
|
|
|
|
|
|
|
|
|
- fh_unlock_and_return:
|
|
|
|
|
mutex_unlock(&fh->cap.lock);
|
|
mutex_unlock(&fh->cap.lock);
|
|
|
- return retval;
|
|
|
|
|
|
|
|
|
|
- btv_unlock_and_return:
|
|
|
|
|
- mutex_unlock(&btv->lock);
|
|
|
|
|
- return retval;
|
|
|
|
|
|
|
+ return 0;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-static int bttv_ioctl(struct inode *inode, struct file *file,
|
|
|
|
|
- unsigned int cmd, unsigned long arg)
|
|
|
|
|
|
|
+static int bttv_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
|
|
|
{
|
|
{
|
|
|
- struct bttv_fh *fh = file->private_data;
|
|
|
|
|
-
|
|
|
|
|
- switch (cmd) {
|
|
|
|
|
- case BTTV_VBISIZE:
|
|
|
|
|
- {
|
|
|
|
|
- const struct bttv_tvnorm *tvnorm;
|
|
|
|
|
-
|
|
|
|
|
- tvnorm = fh->vbi_fmt.tvnorm;
|
|
|
|
|
-
|
|
|
|
|
- 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;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- bttv_switch_type(fh,V4L2_BUF_TYPE_VBI_CAPTURE);
|
|
|
|
|
- return (fh->vbi_fmt.fmt.count[0] * 2
|
|
|
|
|
- * fh->vbi_fmt.fmt.samples_per_line);
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ strcpy(a->name, "audio");
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
- default:
|
|
|
|
|
- return video_usercopy(inode, file, cmd, arg, bttv_do_ioctl);
|
|
|
|
|
- }
|
|
|
|
|
|
|
+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,
|
|
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);
|
|
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 POLLIN|POLLRDNORM;
|
|
|
return 0;
|
|
return 0;
|
|
|
}
|
|
}
|
|
@@ -3777,7 +3263,7 @@ static int bttv_open(struct inode *inode, struct file *file)
|
|
|
V4L2_FIELD_SEQ_TB,
|
|
V4L2_FIELD_SEQ_TB,
|
|
|
sizeof(struct bttv_buffer),
|
|
sizeof(struct bttv_buffer),
|
|
|
fh);
|
|
fh);
|
|
|
- i2c_vidiocschan(btv);
|
|
|
|
|
|
|
+ set_tvnorm(btv,btv->tvnorm);
|
|
|
|
|
|
|
|
btv->users++;
|
|
btv->users++;
|
|
|
|
|
|
|
@@ -3857,7 +3343,7 @@ static const struct file_operations bttv_fops =
|
|
|
.owner = THIS_MODULE,
|
|
.owner = THIS_MODULE,
|
|
|
.open = bttv_open,
|
|
.open = bttv_open,
|
|
|
.release = bttv_release,
|
|
.release = bttv_release,
|
|
|
- .ioctl = bttv_ioctl,
|
|
|
|
|
|
|
+ .ioctl = video_ioctl2,
|
|
|
.compat_ioctl = v4l_compat_ioctl32,
|
|
.compat_ioctl = v4l_compat_ioctl32,
|
|
|
.llseek = no_llseek,
|
|
.llseek = no_llseek,
|
|
|
.read = bttv_read,
|
|
.read = bttv_read,
|
|
@@ -3867,19 +3353,61 @@ static const struct file_operations bttv_fops =
|
|
|
|
|
|
|
|
static struct video_device bttv_video_template =
|
|
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,
|
|
.fops = &bttv_fops,
|
|
|
.minor = -1,
|
|
.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)
|
|
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;
|
|
struct rds_command cmd;
|
|
|
|
|
|
|
|
btv->radio_user--;
|
|
btv->radio_user--;
|
|
@@ -3928,59 +3456,116 @@ static int radio_release(struct inode *inode, struct file *file)
|
|
|
return 0;
|
|
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;
|
|
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,
|
|
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,
|
|
.open = radio_open,
|
|
|
.read = radio_read,
|
|
.read = radio_read,
|
|
|
.release = radio_release,
|
|
.release = radio_release,
|
|
|
- .ioctl = radio_ioctl,
|
|
|
|
|
|
|
+ .ioctl = video_ioctl2,
|
|
|
.llseek = no_llseek,
|
|
.llseek = no_llseek,
|
|
|
.poll = radio_poll,
|
|
.poll = radio_poll,
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
static struct video_device radio_template =
|
|
static struct video_device radio_template =
|
|
|
{
|
|
{
|
|
|
- .name = "bt848/878 radio",
|
|
|
|
|
- .type = VID_TYPE_TUNER,
|
|
|
|
|
.fops = &radio_fops,
|
|
.fops = &radio_fops,
|
|
|
.minor = -1,
|
|
.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);
|
|
bttv_set_dma(btv, 0);
|
|
|
|
|
|
|
|
/* wake up */
|
|
/* 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 */
|
|
/* cancel all outstanding capture / vbi requests */
|
|
|
while (!list_empty(&btv->capture)) {
|
|
while (!list_empty(&btv->capture)) {
|
|
|
item = list_entry(btv->capture.next, struct bttv_buffer, vb.queue);
|
|
item = list_entry(btv->capture.next, struct bttv_buffer, vb.queue);
|
|
|
list_del(&item->vb.queue);
|
|
list_del(&item->vb.queue);
|
|
|
- item->vb.state = STATE_ERROR;
|
|
|
|
|
|
|
+ item->vb.state = VIDEOBUF_ERROR;
|
|
|
wake_up(&item->vb.done);
|
|
wake_up(&item->vb.done);
|
|
|
}
|
|
}
|
|
|
while (!list_empty(&btv->vcapture)) {
|
|
while (!list_empty(&btv->vcapture)) {
|
|
|
item = list_entry(btv->vcapture.next, struct bttv_buffer, vb.queue);
|
|
item = list_entry(btv->vcapture.next, struct bttv_buffer, vb.queue);
|
|
|
list_del(&item->vb.queue);
|
|
list_del(&item->vb.queue);
|
|
|
- item->vb.state = STATE_ERROR;
|
|
|
|
|
|
|
+ item->vb.state = VIDEOBUF_ERROR;
|
|
|
wake_up(&item->vb.done);
|
|
wake_up(&item->vb.done);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -4344,7 +3941,7 @@ bttv_irq_wakeup_top(struct bttv *btv)
|
|
|
|
|
|
|
|
do_gettimeofday(&wakeup->vb.ts);
|
|
do_gettimeofday(&wakeup->vb.ts);
|
|
|
wakeup->vb.field_count = btv->field_count;
|
|
wakeup->vb.field_count = btv->field_count;
|
|
|
- wakeup->vb.state = STATE_DONE;
|
|
|
|
|
|
|
+ wakeup->vb.state = VIDEOBUF_DONE;
|
|
|
wake_up(&wakeup->vb.done);
|
|
wake_up(&wakeup->vb.done);
|
|
|
spin_unlock(&btv->s_lock);
|
|
spin_unlock(&btv->s_lock);
|
|
|
}
|
|
}
|
|
@@ -4393,7 +3990,7 @@ bttv_irq_switch_video(struct bttv *btv)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/* wake up finished buffers */
|
|
/* 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);
|
|
spin_unlock(&btv->s_lock);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -4426,7 +4023,7 @@ bttv_irq_switch_vbi(struct bttv *btv)
|
|
|
bttv_buffer_activate_vbi(btv, new);
|
|
bttv_buffer_activate_vbi(btv, new);
|
|
|
bttv_set_dma(btv, 0);
|
|
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);
|
|
spin_unlock(&btv->s_lock);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -4548,8 +4145,9 @@ static irqreturn_t bttv_irq(int irq, void *dev_id)
|
|
|
/* initialitation */
|
|
/* initialitation */
|
|
|
|
|
|
|
|
static struct video_device *vdev_init(struct bttv *btv,
|
|
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;
|
|
struct video_device *vfd;
|
|
|
|
|
|
|
@@ -4560,9 +4158,10 @@ static struct video_device *vdev_init(struct bttv *btv,
|
|
|
vfd->minor = -1;
|
|
vfd->minor = -1;
|
|
|
vfd->dev = &btv->c.pci->dev;
|
|
vfd->dev = &btv->c.pci->dev;
|
|
|
vfd->release = video_device_release;
|
|
vfd->release = video_device_release;
|
|
|
|
|
+ vfd->type = type;
|
|
|
snprintf(vfd->name, sizeof(vfd->name), "BT%d%s %s (%s)",
|
|
snprintf(vfd->name, sizeof(vfd->name), "BT%d%s %s (%s)",
|
|
|
btv->id, (btv->id==848 && btv->revision==0x12) ? "A" : "",
|
|
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;
|
|
return vfd;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -4594,6 +4193,11 @@ static void bttv_unregister_video(struct bttv *btv)
|
|
|
/* register video4linux devices */
|
|
/* register video4linux devices */
|
|
|
static int __devinit bttv_register_video(struct bttv *btv)
|
|
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) {
|
|
if (no_overlay <= 0) {
|
|
|
bttv_video_template.type |= VID_TYPE_OVERLAY;
|
|
bttv_video_template.type |= VID_TYPE_OVERLAY;
|
|
|
} else {
|
|
} else {
|
|
@@ -4601,7 +4205,9 @@ static int __devinit bttv_register_video(struct bttv *btv)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/* video */
|
|
/* 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)
|
|
if (NULL == btv->video_dev)
|
|
|
goto err;
|
|
goto err;
|
|
|
if (video_register_device(btv->video_dev,VFL_TYPE_GRABBER,video_nr)<0)
|
|
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 */
|
|
/* 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)
|
|
if (NULL == btv->vbi_dev)
|
|
|
goto err;
|
|
goto err;
|
|
|
if (video_register_device(btv->vbi_dev,VFL_TYPE_VBI,vbi_nr)<0)
|
|
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)
|
|
if (!btv->has_radio)
|
|
|
return 0;
|
|
return 0;
|
|
|
/* radio */
|
|
/* 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)
|
|
if (NULL == btv->radio_dev)
|
|
|
goto err;
|
|
goto err;
|
|
|
if (video_register_device(btv->radio_dev, VFL_TYPE_RADIO,radio_nr)<0)
|
|
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.btv = btv;
|
|
|
btv->init.ov.w.width = 320;
|
|
btv->init.ov.w.width = 320;
|
|
|
btv->init.ov.w.height = 240;
|
|
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.width = 320;
|
|
|
btv->init.height = 240;
|
|
btv->init.height = 240;
|
|
|
btv->input = 0;
|
|
btv->input = 0;
|
|
@@ -5013,14 +4622,17 @@ static int __init bttv_init_module(void)
|
|
|
printk(KERN_WARNING "bttv: bus_register error: %d\n", ret);
|
|
printk(KERN_WARNING "bttv: bus_register error: %d\n", ret);
|
|
|
return 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)
|
|
static void __exit bttv_cleanup_module(void)
|
|
|
{
|
|
{
|
|
|
pci_unregister_driver(&bttv_pci_driver);
|
|
pci_unregister_driver(&bttv_pci_driver);
|
|
|
bus_unregister(&bttv_sub_bus_type);
|
|
bus_unregister(&bttv_sub_bus_type);
|
|
|
- return;
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
module_init(bttv_init_module);
|
|
module_init(bttv_init_module);
|