예제 #1
0
int usbtv_video_init(struct usbtv *usbtv)
{
	int ret;

	(void)usbtv_configure_for_norm(usbtv, V4L2_STD_525_60);

	spin_lock_init(&usbtv->buflock);
	mutex_init(&usbtv->v4l2_lock);
	mutex_init(&usbtv->vb2q_lock);
	INIT_LIST_HEAD(&usbtv->bufs);

	/* videobuf2 structure */
	usbtv->vb2q.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
	usbtv->vb2q.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
	usbtv->vb2q.drv_priv = usbtv;
	usbtv->vb2q.buf_struct_size = sizeof(struct usbtv_buf);
	usbtv->vb2q.ops = &usbtv_vb2_ops;
	usbtv->vb2q.mem_ops = &vb2_vmalloc_memops;
	usbtv->vb2q.timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
	usbtv->vb2q.lock = &usbtv->vb2q_lock;
	ret = vb2_queue_init(&usbtv->vb2q);
	if (ret < 0) {
		dev_warn(usbtv->dev, "Could not initialize videobuf2 queue\n");
		return ret;
	}

	/* v4l2 structure */
	usbtv->v4l2_dev.release = usbtv_release;
	ret = v4l2_device_register(usbtv->dev, &usbtv->v4l2_dev);
	if (ret < 0) {
		dev_warn(usbtv->dev, "Could not register v4l2 device\n");
		goto v4l2_fail;
	}

	/* Video structure */
	strlcpy(usbtv->vdev.name, "usbtv", sizeof(usbtv->vdev.name));
	usbtv->vdev.v4l2_dev = &usbtv->v4l2_dev;
	usbtv->vdev.release = video_device_release_empty;
	usbtv->vdev.fops = &usbtv_fops;
	usbtv->vdev.ioctl_ops = &usbtv_ioctl_ops;
	usbtv->vdev.tvnorms = USBTV_TV_STD;
	usbtv->vdev.queue = &usbtv->vb2q;
	usbtv->vdev.lock = &usbtv->v4l2_lock;
	set_bit(V4L2_FL_USE_FH_PRIO, &usbtv->vdev.flags);
	video_set_drvdata(&usbtv->vdev, usbtv);
	ret = video_register_device(&usbtv->vdev, VFL_TYPE_GRABBER, -1);
	if (ret < 0) {
		dev_warn(usbtv->dev, "Could not register video device\n");
		goto vdev_fail;
	}

	return 0;

vdev_fail:
	v4l2_device_unregister(&usbtv->v4l2_dev);
v4l2_fail:
	vb2_queue_release(&usbtv->vb2q);

	return ret;
}
예제 #2
0
static int usbtv_select_norm(struct usbtv *usbtv, v4l2_std_id norm)
{
	int ret;
	static const u16 pal[][2] = {
		{ USBTV_BASE + 0x001a, 0x0068 },
		{ USBTV_BASE + 0x010e, 0x0072 },
		{ USBTV_BASE + 0x010f, 0x00a2 },
		{ USBTV_BASE + 0x0112, 0x00b0 },
		{ USBTV_BASE + 0x0117, 0x0001 },
		{ USBTV_BASE + 0x0118, 0x002c },
		{ USBTV_BASE + 0x012d, 0x0010 },
		{ USBTV_BASE + 0x012f, 0x0020 },
		{ USBTV_BASE + 0x024f, 0x0002 },
		{ USBTV_BASE + 0x0254, 0x0059 },
		{ USBTV_BASE + 0x025a, 0x0016 },
		{ USBTV_BASE + 0x025b, 0x0035 },
		{ USBTV_BASE + 0x0263, 0x0017 },
		{ USBTV_BASE + 0x0266, 0x0016 },
		{ USBTV_BASE + 0x0267, 0x0036 }
	};

	static const u16 ntsc[][2] = {
		{ USBTV_BASE + 0x001a, 0x0079 },
		{ USBTV_BASE + 0x010e, 0x0068 },
		{ USBTV_BASE + 0x010f, 0x009c },
		{ USBTV_BASE + 0x0112, 0x00f0 },
		{ USBTV_BASE + 0x0117, 0x0000 },
		{ USBTV_BASE + 0x0118, 0x00fc },
		{ USBTV_BASE + 0x012d, 0x0004 },
		{ USBTV_BASE + 0x012f, 0x0008 },
		{ USBTV_BASE + 0x024f, 0x0001 },
		{ USBTV_BASE + 0x0254, 0x005f },
		{ USBTV_BASE + 0x025a, 0x0012 },
		{ USBTV_BASE + 0x025b, 0x0001 },
		{ USBTV_BASE + 0x0263, 0x001c },
		{ USBTV_BASE + 0x0266, 0x0011 },
		{ USBTV_BASE + 0x0267, 0x0005 }
	};

	ret = usbtv_configure_for_norm(usbtv, norm);

	if (!ret) {
		if (norm & V4L2_STD_525_60)
			ret = usbtv_set_regs(usbtv, ntsc, ARRAY_SIZE(ntsc));
		else if (norm & V4L2_STD_PAL)
			ret = usbtv_set_regs(usbtv, pal, ARRAY_SIZE(pal));
	}

	return ret;
}