Commit e75f9cee authored by Mauro Carvalho Chehab's avatar Mauro Carvalho Chehab

V4L/DVB (4861): Remove the need of a STD array for drivers using video_ioctl2

video_ioctl2 will auto-generate standard entries at ENUM_FMT.
Also, now, a driver may return a subset of the video array at
the return, to be stored as the current_norm.
For example, a driver may ask for V4L2_STD_PAL. At return,
driver may change it to V4L2_STD_PAL_B. This way, a futher call
to G_STD will return the exact detected video std.
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@infradead.org>
parent 207705cd
...@@ -1679,24 +1679,11 @@ static int cafe_vidioc_s_input(struct file *filp, void *priv, unsigned int i) ...@@ -1679,24 +1679,11 @@ static int cafe_vidioc_s_input(struct file *filp, void *priv, unsigned int i)
} }
/* from vivi.c */ /* from vivi.c */
static int cafe_vidioc_s_std(struct file *filp, void *priv, v4l2_std_id a) static int cafe_vidioc_s_std(struct file *filp, void *priv, v4l2_std_id *a)
{ {
return 0; return 0;
} }
/*
* The TV Norm stuff is weird - we're a camera with little to do with TV,
* really. The following is what vivi does.
*/
static struct v4l2_tvnorm cafe_tvnorm[] = {
{
.name = "NTSC-M",
.id = V4L2_STD_NTSC_M,
}
};
static void cafe_v4l_dev_release(struct video_device *vd) static void cafe_v4l_dev_release(struct video_device *vd)
{ {
struct cafe_camera *cam = container_of(vd, struct cafe_camera, v4ldev); struct cafe_camera *cam = container_of(vd, struct cafe_camera, v4ldev);
...@@ -1726,8 +1713,7 @@ static struct video_device cafe_v4l_template = { ...@@ -1726,8 +1713,7 @@ static struct video_device cafe_v4l_template = {
.type = VFL_TYPE_GRABBER, .type = VFL_TYPE_GRABBER,
.type2 = VID_TYPE_CAPTURE, .type2 = VID_TYPE_CAPTURE,
.minor = -1, /* Get one dynamically */ .minor = -1, /* Get one dynamically */
.tvnorms = cafe_tvnorm, .tvnorms = V4L2_STD_NTSC_M,
.tvnormsize = 1,
.current_norm = V4L2_STD_NTSC_M, /* make mplayer happy */ .current_norm = V4L2_STD_NTSC_M, /* make mplayer happy */
.fops = &cafe_v4l_fops, .fops = &cafe_v4l_fops,
......
...@@ -87,6 +87,78 @@ MODULE_LICENSE("GPL"); ...@@ -87,6 +87,78 @@ MODULE_LICENSE("GPL");
*/ */
char *v4l2_norm_to_name(v4l2_std_id id)
{
char *name;
switch (id) {
case V4L2_STD_PAL:
name="PAL"; break;
case V4L2_STD_PAL_BG:
name="PAL-BG"; break;
case V4L2_STD_PAL_DK:
name="PAL-DK"; break;
case V4L2_STD_PAL_B:
name="PAL-B"; break;
case V4L2_STD_PAL_B1:
name="PAL-B1"; break;
case V4L2_STD_PAL_G:
name="PAL-G"; break;
case V4L2_STD_PAL_H:
name="PAL-H"; break;
case V4L2_STD_PAL_I:
name="PAL-I"; break;
case V4L2_STD_PAL_D:
name="PAL-D"; break;
case V4L2_STD_PAL_D1:
name="PAL-D1"; break;
case V4L2_STD_PAL_K:
name="PAL-K"; break;
case V4L2_STD_PAL_M:
name="PAL-M"; break;
case V4L2_STD_PAL_N:
name="PAL-N"; break;
case V4L2_STD_PAL_Nc:
name="PAL-Nc"; break;
case V4L2_STD_PAL_60:
name="PAL-60"; break;
case V4L2_STD_NTSC:
name="NTSC"; break;
case V4L2_STD_NTSC_M:
name="NTSC-M"; break;
case V4L2_STD_NTSC_M_JP:
name="NTSC-M-JP"; break;
case V4L2_STD_NTSC_443:
name="NTSC-443"; break;
case V4L2_STD_NTSC_M_KR:
name="NTSC-M-KR"; break;
case V4L2_STD_SECAM:
name="SECAM"; break;
case V4L2_STD_SECAM_DK:
name="SECAM-DK"; break;
case V4L2_STD_SECAM_B:
name="SECAM-B"; break;
case V4L2_STD_SECAM_D:
name="SECAM-D"; break;
case V4L2_STD_SECAM_G:
name="SECAM-G"; break;
case V4L2_STD_SECAM_H:
name="SECAM-H"; break;
case V4L2_STD_SECAM_K:
name="SECAM-K"; break;
case V4L2_STD_SECAM_K1:
name="SECAM-K1"; break;
case V4L2_STD_SECAM_L:
name="SECAM-L"; break;
case V4L2_STD_SECAM_LC:
name="SECAM-LC"; break;
default:
name="Unknown"; break;
}
return name;
}
/* Fill in the fields of a v4l2_standard structure according to the /* Fill in the fields of a v4l2_standard structure according to the
'id' and 'transmission' parameters. Returns negative on error. */ 'id' and 'transmission' parameters. Returns negative on error. */
int v4l2_video_std_construct(struct v4l2_standard *vs, int v4l2_video_std_construct(struct v4l2_standard *vs,
...@@ -1453,6 +1525,7 @@ u32 v4l2_ctrl_next(const u32 * const * ctrl_classes, u32 id) ...@@ -1453,6 +1525,7 @@ u32 v4l2_ctrl_next(const u32 * const * ctrl_classes, u32 id)
/* ----------------------------------------------------------------- */ /* ----------------------------------------------------------------- */
EXPORT_SYMBOL(v4l2_norm_to_name);
EXPORT_SYMBOL(v4l2_video_std_construct); EXPORT_SYMBOL(v4l2_video_std_construct);
EXPORT_SYMBOL(v4l2_prio_init); EXPORT_SYMBOL(v4l2_prio_init);
......
...@@ -833,20 +833,85 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, ...@@ -833,20 +833,85 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
case VIDIOC_ENUMSTD: case VIDIOC_ENUMSTD:
{ {
struct v4l2_standard *p = arg; struct v4l2_standard *p = arg;
unsigned int index = p->index; v4l2_std_id id = vfd->tvnorms,curr_id=0;
unsigned int index = p->index,i;
if (!vfd->tvnormsize) { if (index<0) {
printk (KERN_WARNING "%s: no TV norms defined!\n", ret=-EINVAL;
vfd->name);
break; break;
} }
if (index<0 || index >= vfd->tvnormsize) { /* Return norm array on a canonical way */
ret=-EINVAL; for (i=0;i<= index && id; i++) {
break; if ( (id & V4L2_STD_PAL) == V4L2_STD_PAL) {
curr_id = V4L2_STD_PAL;
} else if ( (id & V4L2_STD_PAL_BG) == V4L2_STD_PAL_BG) {
curr_id = V4L2_STD_PAL_BG;
} else if ( (id & V4L2_STD_PAL_DK) == V4L2_STD_PAL_DK) {
curr_id = V4L2_STD_PAL_DK;
} else if ( (id & V4L2_STD_PAL_B) == V4L2_STD_PAL_B) {
curr_id = V4L2_STD_PAL_B;
} else if ( (id & V4L2_STD_PAL_B1) == V4L2_STD_PAL_B1) {
curr_id = V4L2_STD_PAL_B1;
} else if ( (id & V4L2_STD_PAL_G) == V4L2_STD_PAL_G) {
curr_id = V4L2_STD_PAL_G;
} else if ( (id & V4L2_STD_PAL_H) == V4L2_STD_PAL_H) {
curr_id = V4L2_STD_PAL_H;
} else if ( (id & V4L2_STD_PAL_I) == V4L2_STD_PAL_I) {
curr_id = V4L2_STD_PAL_I;
} else if ( (id & V4L2_STD_PAL_D) == V4L2_STD_PAL_D) {
curr_id = V4L2_STD_PAL_D;
} else if ( (id & V4L2_STD_PAL_D1) == V4L2_STD_PAL_D1) {
curr_id = V4L2_STD_PAL_D1;
} else if ( (id & V4L2_STD_PAL_K) == V4L2_STD_PAL_K) {
curr_id = V4L2_STD_PAL_K;
} else if ( (id & V4L2_STD_PAL_M) == V4L2_STD_PAL_M) {
curr_id = V4L2_STD_PAL_M;
} else if ( (id & V4L2_STD_PAL_N) == V4L2_STD_PAL_N) {
curr_id = V4L2_STD_PAL_N;
} else if ( (id & V4L2_STD_PAL_Nc) == V4L2_STD_PAL_Nc) {
curr_id = V4L2_STD_PAL_Nc;
} else if ( (id & V4L2_STD_PAL_60) == V4L2_STD_PAL_60) {
curr_id = V4L2_STD_PAL_60;
} else if ( (id & V4L2_STD_NTSC) == V4L2_STD_NTSC) {
curr_id = V4L2_STD_NTSC;
} else if ( (id & V4L2_STD_NTSC_M) == V4L2_STD_NTSC_M) {
curr_id = V4L2_STD_NTSC_M;
} else if ( (id & V4L2_STD_NTSC_M_JP) == V4L2_STD_NTSC_M_JP) {
curr_id = V4L2_STD_NTSC_M_JP;
} else if ( (id & V4L2_STD_NTSC_443) == V4L2_STD_NTSC_443) {
curr_id = V4L2_STD_NTSC_443;
} else if ( (id & V4L2_STD_NTSC_M_KR) == V4L2_STD_NTSC_M_KR) {
curr_id = V4L2_STD_NTSC_M_KR;
} else if ( (id & V4L2_STD_SECAM) == V4L2_STD_SECAM) {
curr_id = V4L2_STD_SECAM;
} else if ( (id & V4L2_STD_SECAM_DK) == V4L2_STD_SECAM_DK) {
curr_id = V4L2_STD_SECAM_DK;
} else if ( (id & V4L2_STD_SECAM_B) == V4L2_STD_SECAM_B) {
curr_id = V4L2_STD_SECAM_B;
} else if ( (id & V4L2_STD_SECAM_D) == V4L2_STD_SECAM_D) {
curr_id = V4L2_STD_SECAM_D;
} else if ( (id & V4L2_STD_SECAM_G) == V4L2_STD_SECAM_G) {
curr_id = V4L2_STD_SECAM_G;
} else if ( (id & V4L2_STD_SECAM_H) == V4L2_STD_SECAM_H) {
curr_id = V4L2_STD_SECAM_H;
} else if ( (id & V4L2_STD_SECAM_K) == V4L2_STD_SECAM_K) {
curr_id = V4L2_STD_SECAM_K;
} else if ( (id & V4L2_STD_SECAM_K1) == V4L2_STD_SECAM_K1) {
curr_id = V4L2_STD_SECAM_K1;
} else if ( (id & V4L2_STD_SECAM_L) == V4L2_STD_SECAM_L) {
curr_id = V4L2_STD_SECAM_L;
} else if ( (id & V4L2_STD_SECAM_LC) == V4L2_STD_SECAM_LC) {
curr_id = V4L2_STD_SECAM_LC;
} else {
break;
}
id &= ~curr_id;
} }
v4l2_video_std_construct(p, vfd->tvnorms[p->index].id, if (i<=index)
vfd->tvnorms[p->index].name); return -EINVAL;
v4l2_video_std_construct(p, curr_id,v4l2_norm_to_name(curr_id));
p->index = index; p->index = index;
dbgarg (cmd, "index=%d, id=%Ld, name=%s, fps=%d/%d, " dbgarg (cmd, "index=%d, id=%Ld, name=%s, fps=%d/%d, "
...@@ -872,39 +937,23 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, ...@@ -872,39 +937,23 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
} }
case VIDIOC_S_STD: case VIDIOC_S_STD:
{ {
v4l2_std_id *id = arg; v4l2_std_id *id = arg,norm;
unsigned int i;
if (!vfd->tvnormsize) {
printk (KERN_WARNING "%s: no TV norms defined!\n",
vfd->name);
break;
}
dbgarg (cmd, "value=%Lu\n", (long long unsigned) *id); dbgarg (cmd, "value=%Lu\n", (long long unsigned) *id);
/* First search for exact match */ norm = (*id) & vfd->tvnorms;
for (i = 0; i < vfd->tvnormsize; i++) if ( vfd->tvnorms && !norm) /* Check if std is supported */
if (*id == vfd->tvnorms[i].id)
break;
/* Then for a generic video std that contains desired std */
if (i == vfd->tvnormsize)
for (i = 0; i < vfd->tvnormsize; i++)
if (*id & vfd->tvnorms[i].id)
break;
if (i == vfd->tvnormsize) {
break; break;
}
/* Calls the specific handler */ /* Calls the specific handler */
if (vfd->vidioc_s_std) if (vfd->vidioc_s_std)
ret=vfd->vidioc_s_std(file, fh, i); ret=vfd->vidioc_s_std(file, fh, &norm);
else else
ret=-EINVAL; ret=-EINVAL;
/* Updates standard information */ /* Updates standard information */
if (!ret) if (ret>=0)
vfd->current_norm=*id; vfd->current_norm=norm;
break; break;
} }
...@@ -1296,25 +1345,12 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, ...@@ -1296,25 +1345,12 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
ret=vfd->vidioc_g_parm(file, fh, p); ret=vfd->vidioc_g_parm(file, fh, p);
} else { } else {
struct v4l2_standard s; struct v4l2_standard s;
int i;
if (!vfd->tvnormsize) {
printk (KERN_WARNING "%s: no TV norms defined!\n",
vfd->name);
break;
}
if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL; return -EINVAL;
for (i = 0; i < vfd->tvnormsize; i++)
if (vfd->tvnorms[i].id == vfd->current_norm)
break;
if (i >= vfd->tvnormsize)
return -EINVAL;
v4l2_video_std_construct(&s, vfd->current_norm, v4l2_video_std_construct(&s, vfd->current_norm,
vfd->tvnorms[i].name); v4l2_norm_to_name(vfd->current_norm));
memset(p,0,sizeof(*p)); memset(p,0,sizeof(*p));
......
...@@ -1044,16 +1044,8 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) ...@@ -1044,16 +1044,8 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
return (0); return (0);
} }
static struct v4l2_tvnorm tvnorms[] = { static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *i)
{
.name = "NTSC-M",
.id = V4L2_STD_NTSC_M,
}
};
static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id a)
{ {
return 0; return 0;
} }
...@@ -1333,8 +1325,8 @@ static struct video_device vivi = { ...@@ -1333,8 +1325,8 @@ static struct video_device vivi = {
#ifdef CONFIG_VIDEO_V4L1_COMPAT #ifdef CONFIG_VIDEO_V4L1_COMPAT
.vidiocgmbuf = vidiocgmbuf, .vidiocgmbuf = vidiocgmbuf,
#endif #endif
.tvnorms = tvnorms, .tvnorms = V4L2_STD_NTSC_M,
.tvnormsize = ARRAY_SIZE(tvnorms), .current_norm = V4L2_STD_NTSC_M,
}; };
/* ----------------------------------------------------------------- /* -----------------------------------------------------------------
Initialization and module stuff Initialization and module stuff
...@@ -1361,8 +1353,6 @@ static int __init vivi_init(void) ...@@ -1361,8 +1353,6 @@ static int __init vivi_init(void)
dev->vidq.timeout.data = (unsigned long)dev; dev->vidq.timeout.data = (unsigned long)dev;
init_timer(&dev->vidq.timeout); init_timer(&dev->vidq.timeout);
vivi.current_norm = tvnorms[0].id;
ret = video_register_device(&vivi, VFL_TYPE_GRABBER, video_nr); ret = video_register_device(&vivi, VFL_TYPE_GRABBER, video_nr);
printk(KERN_INFO "Video Technology Magazine Virtual Video Capture Board (Load status: %d)\n", ret); printk(KERN_INFO "Video Technology Magazine Virtual Video Capture Board (Load status: %d)\n", ret);
return ret; return ret;
......
...@@ -43,6 +43,7 @@ ...@@ -43,6 +43,7 @@
/* Video standard functions */ /* Video standard functions */
extern unsigned int v4l2_video_std_fps(struct v4l2_standard *vs); extern unsigned int v4l2_video_std_fps(struct v4l2_standard *vs);
extern char *v4l2_norm_to_name(v4l2_std_id id);
extern int v4l2_video_std_construct(struct v4l2_standard *vs, extern int v4l2_video_std_construct(struct v4l2_standard *vs,
int id, char *name); int id, char *name);
...@@ -81,12 +82,6 @@ extern long v4l_compat_ioctl32(struct file *file, unsigned int cmd, ...@@ -81,12 +82,6 @@ extern long v4l_compat_ioctl32(struct file *file, unsigned int cmd,
* This version moves redundant code from video device code to * This version moves redundant code from video device code to
* the common handler * the common handler
*/ */
struct v4l2_tvnorm {
char *name;
v4l2_std_id id;
void *priv_data;
};
struct video_device struct video_device
{ {
...@@ -104,9 +99,8 @@ struct video_device ...@@ -104,9 +99,8 @@ struct video_device
int debug; /* Activates debug level*/ int debug; /* Activates debug level*/
/* Video standard vars */ /* Video standard vars */
int tvnormsize; /* Size of tvnorm array */ v4l2_std_id tvnorms; /* Supported tv norms */
v4l2_std_id current_norm; /* Current tvnorm */ v4l2_std_id current_norm; /* Current tvnorm */
struct v4l2_tvnorm *tvnorms;
/* callbacks */ /* callbacks */
void (*release)(struct video_device *vfd); void (*release)(struct video_device *vfd);
...@@ -211,7 +205,7 @@ struct video_device ...@@ -211,7 +205,7 @@ struct video_device
/* Standard handling /* Standard handling
G_STD and ENUMSTD are handled by videodev.c G_STD and ENUMSTD are handled by videodev.c
*/ */
int (*vidioc_s_std) (struct file *file, void *fh, v4l2_std_id a); int (*vidioc_s_std) (struct file *file, void *fh, v4l2_std_id *norm);
int (*vidioc_querystd) (struct file *file, void *fh, v4l2_std_id *a); int (*vidioc_querystd) (struct file *file, void *fh, v4l2_std_id *a);
/* Input handling */ /* Input handling */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment