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

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
Loading
Loading
Loading
Loading
+2 −16
Original line number Diff line number Diff line
@@ -1679,24 +1679,11 @@ static int cafe_vidioc_s_input(struct file *filp, void *priv, unsigned int i)
}

/* 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;
}


/*
 * 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)
{
	struct cafe_camera *cam = container_of(vd, struct cafe_camera, v4ldev);
@@ -1726,8 +1713,7 @@ static struct video_device cafe_v4l_template = {
	.type = VFL_TYPE_GRABBER,
	.type2 = VID_TYPE_CAPTURE,
	.minor = -1, /* Get one dynamically */
	.tvnorms = cafe_tvnorm,
	.tvnormsize = 1,
	.tvnorms = V4L2_STD_NTSC_M,
	.current_norm = V4L2_STD_NTSC_M,  /* make mplayer happy */

	.fops = &cafe_v4l_fops,
+73 −0
Original line number Diff line number Diff line
@@ -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
   'id' and 'transmission' parameters.  Returns negative on error.  */
int v4l2_video_std_construct(struct v4l2_standard *vs,
@@ -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_prio_init);
+81 −45
Original line number Diff line number Diff line
@@ -833,20 +833,85 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
	case VIDIOC_ENUMSTD:
	{
		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) {
			printk (KERN_WARNING "%s: no TV norms defined!\n",
						vfd->name);
		if (index<0) {
			ret=-EINVAL;
			break;
		}

		if (index<0 || index >= vfd->tvnormsize) {
			ret=-EINVAL;
		/* Return norm array on a canonical way */
		for (i=0;i<= index && id; i++) {
			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;
			}
		v4l2_video_std_construct(p, vfd->tvnorms[p->index].id,
					 vfd->tvnorms[p->index].name);
			id &= ~curr_id;
		}
		if (i<=index)
			return -EINVAL;

		v4l2_video_std_construct(p, curr_id,v4l2_norm_to_name(curr_id));
		p->index = index;

		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,
	}
	case VIDIOC_S_STD:
	{
		v4l2_std_id *id = arg;
		unsigned int i;

		if (!vfd->tvnormsize) {
			printk (KERN_WARNING "%s: no TV norms defined!\n",
						vfd->name);
			break;
		}
		v4l2_std_id *id = arg,norm;

		dbgarg (cmd, "value=%Lu\n", (long long unsigned) *id);

		/* First search for exact match */
		for (i = 0; i < vfd->tvnormsize; i++)
			if (*id == vfd->tvnorms[i].id)
		norm = (*id) & vfd->tvnorms;
		if ( vfd->tvnorms && !norm)	/* Check if std is supported */
			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;
		}

		/* Calls the specific handler */
		if (vfd->vidioc_s_std)
			ret=vfd->vidioc_s_std(file, fh, i);
			ret=vfd->vidioc_s_std(file, fh, &norm);
		else
			ret=-EINVAL;

		/* Updates standard information */
		if (!ret)
			vfd->current_norm=*id;
		if (ret>=0)
			vfd->current_norm=norm;

		break;
	}
@@ -1296,25 +1345,12 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
			ret=vfd->vidioc_g_parm(file, fh, p);
		} else {
			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)
				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,
						 vfd->tvnorms[i].name);
						 v4l2_norm_to_name(vfd->current_norm));

			memset(p,0,sizeof(*p));

+3 −13
Original line number Diff line number Diff line
@@ -1044,16 +1044,8 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
	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;
}

@@ -1333,8 +1325,8 @@ static struct video_device vivi = {
#ifdef CONFIG_VIDEO_V4L1_COMPAT
	.vidiocgmbuf          = vidiocgmbuf,
#endif
	.tvnorms              = tvnorms,
	.tvnormsize           = ARRAY_SIZE(tvnorms),
	.tvnorms              = V4L2_STD_NTSC_M,
	.current_norm         = V4L2_STD_NTSC_M,
};
/* -----------------------------------------------------------------
	Initialization and module stuff
@@ -1361,8 +1353,6 @@ static int __init vivi_init(void)
	dev->vidq.timeout.data     = (unsigned long)dev;
	init_timer(&dev->vidq.timeout);

	vivi.current_norm         = tvnorms[0].id;

	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);
	return ret;
+4 −10
Original line number Diff line number Diff line
@@ -43,6 +43,7 @@

/*  Video standard functions  */
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,
				    int id, char *name);

@@ -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
 *	the common handler
 */
struct v4l2_tvnorm {
	char          *name;
	v4l2_std_id   id;

	void          *priv_data;
};

struct video_device
{
@@ -104,9 +99,8 @@ struct video_device
	int debug;	/* Activates debug level*/

	/* Video standard vars */
	int tvnormsize;	/* Size of tvnorm array */
	v4l2_std_id tvnorms;		/* Supported tv norms */
	v4l2_std_id current_norm;	/* Current tvnorm */
	struct v4l2_tvnorm *tvnorms;

	/* callbacks */
	void (*release)(struct video_device *vfd);
@@ -211,7 +205,7 @@ struct video_device
		/* Standard handling
			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);

		/* Input handling */