示例#1
0
static int rockchip_vpu_video_device_register(struct rockchip_vpu_dev *vpu)
{
	const struct of_device_id *match;
	struct video_device *vfd;
	int function, ret;

	match = of_match_node(of_rockchip_vpu_match, vpu->dev->of_node);
	vfd = video_device_alloc();
	if (!vfd) {
		v4l2_err(&vpu->v4l2_dev, "Failed to allocate video device\n");
		return -ENOMEM;
	}

	vfd->fops = &rockchip_vpu_fops;
	vfd->release = video_device_release;
	vfd->lock = &vpu->vpu_mutex;
	vfd->v4l2_dev = &vpu->v4l2_dev;
	vfd->vfl_dir = VFL_DIR_M2M;
	vfd->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_M2M_MPLANE;
	vfd->ioctl_ops = &rockchip_vpu_enc_ioctl_ops;
	snprintf(vfd->name, sizeof(vfd->name), "%s-enc", match->compatible);
	vpu->vfd_enc = vfd;
	video_set_drvdata(vfd, vpu);

	ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0);
	if (ret) {
		v4l2_err(&vpu->v4l2_dev, "Failed to register video device\n");
		goto err_free_dev;
	}
	v4l2_info(&vpu->v4l2_dev, "registered as /dev/video%d\n", vfd->num);

	function = MEDIA_ENT_F_PROC_VIDEO_ENCODER;
	ret = v4l2_m2m_register_media_controller(vpu->m2m_dev, vfd, function);
	if (ret) {
		v4l2_err(&vpu->v4l2_dev, "Failed to init mem2mem media controller\n");
		goto err_unreg_video;
	}
	return 0;

err_unreg_video:
	video_unregister_device(vfd);
err_free_dev:
	video_device_release(vfd);
	return ret;
}
示例#2
0
int isp_video_init(struct isp_video *video, const char *name)
{
	const char *direction;
	int ret;

	switch (video->type) {
	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
		direction = "output";
		video->pad.type = MEDIA_PAD_TYPE_INPUT;
		break;
	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
		direction = "input";
		video->pad.type = MEDIA_PAD_TYPE_OUTPUT;
		break;

	default:
		return -EINVAL;
	}

	ret = media_entity_init(&video->video.entity, 1, &video->pad, 0);
	if (ret < 0)
		return ret;

	mutex_init(&video->mutex);
	atomic_set(&video->active, 0);
	atomic_set(&video->users, 0);

	spin_lock_init(&video->__pipe.lock);
	mutex_init(&video->stream_lock);

	/* Initialize the video device. */
	if (video->ops == NULL)
		video->ops = &isp_video_dummy_ops;

	video->video.fops = &isp_video_fops;
	snprintf(video->video.name, sizeof(video->video.name),
		 "OMAP3 ISP %s %s", name, direction);
	video->video.vfl_type = VFL_TYPE_GRABBER;
	video->video.release = video_device_release_empty;
	video->video.ioctl_ops = &isp_video_ioctl_ops;

	video_set_drvdata(&video->video, video);

	return 0;
}
示例#3
0
文件: f_uvc.c 项目: asmalldev/linux
static int
uvc_register_video(struct uvc_device *uvc)
{
	struct usb_composite_dev *cdev = uvc->func.config->cdev;

	/* TODO reference counting. */
	uvc->vdev.v4l2_dev = &uvc->v4l2_dev;
	uvc->vdev.fops = &uvc_v4l2_fops;
	uvc->vdev.ioctl_ops = &uvc_v4l2_ioctl_ops;
	uvc->vdev.release = video_device_release_empty;
	uvc->vdev.vfl_dir = VFL_DIR_TX;
	uvc->vdev.lock = &uvc->video.mutex;
	strlcpy(uvc->vdev.name, cdev->gadget->name, sizeof(uvc->vdev.name));

	video_set_drvdata(&uvc->vdev, uvc);

	return video_register_device(&uvc->vdev, VFL_TYPE_GRABBER, -1);
}
示例#4
0
int fimc_register_m2m_device(struct fimc_dev *fimc,
                             struct v4l2_device *v4l2_dev)
{
    struct video_device *vfd = &fimc->m2m.vfd;
    int ret;

    fimc->v4l2_dev = v4l2_dev;

    memset(vfd, 0, sizeof(*vfd));
    vfd->fops = &fimc_m2m_fops;
    vfd->ioctl_ops = &fimc_m2m_ioctl_ops;
    vfd->v4l2_dev = v4l2_dev;
    vfd->minor = -1;
    vfd->release = video_device_release_empty;
    vfd->lock = &fimc->lock;
    vfd->vfl_dir = VFL_DIR_M2M;

    snprintf(vfd->name, sizeof(vfd->name), "fimc.%d.m2m", fimc->id);
    video_set_drvdata(vfd, fimc);

    fimc->m2m.m2m_dev = v4l2_m2m_init(&m2m_ops);
    if (IS_ERR(fimc->m2m.m2m_dev)) {
        v4l2_err(v4l2_dev, "failed to initialize v4l2-m2m device\n");
        return PTR_ERR(fimc->m2m.m2m_dev);
    }

    ret = media_entity_init(&vfd->entity, 0, NULL, 0);
    if (ret)
        goto err_me;

    ret = video_register_device(vfd, VFL_TYPE_GRABBER, -1);
    if (ret)
        goto err_vd;

    v4l2_info(v4l2_dev, "Registered %s as /dev/%s\n",
              vfd->name, video_device_node_name(vfd));
    return 0;

err_vd:
    media_entity_cleanup(&vfd->entity);
err_me:
    v4l2_m2m_release(fimc->m2m.m2m_dev);
    return ret;
}
示例#5
0
int stk1160_video_register(struct stk1160 *dev)
{
	int rc;

	/* Initialize video_device with a template structure */
	dev->vdev = v4l_template;
	dev->vdev.debug = vidioc_debug;
	dev->vdev.queue = &dev->vb_vidq;

	/*
	 * Provide mutexes for v4l2 core and for videobuf2 queue.
	 * It will be used to protect *only* v4l2 ioctls.
	 */
	dev->vdev.lock = &dev->v4l_lock;
	dev->vdev.queue->lock = &dev->vb_queue_lock;

	/* This will be used to set video_device parent */
	dev->vdev.v4l2_dev = &dev->v4l2_dev;
	set_bit(V4L2_FL_USE_FH_PRIO, &dev->vdev.flags);

	/* NTSC is default */
	dev->norm = V4L2_STD_NTSC_M;
	dev->width = 720;
	dev->height = 480;

	/* set default format */
	dev->fmt = &format[0];
	stk1160_set_std(dev);

	v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std,
			dev->norm);

	video_set_drvdata(&dev->vdev, dev);
	rc = video_register_device(&dev->vdev, VFL_TYPE_GRABBER, -1);
	if (rc < 0) {
		stk1160_err("video_register_device failed (%d)\n", rc);
		return rc;
	}

	v4l2_info(&dev->v4l2_dev, "V4L2 device registered as %s\n",
		  video_device_node_name(&dev->vdev));

	return 0;
}
static int register_v4l2_device(void)
{
  int ret;
  struct fmdev *fmdev = NULL;
	struct video_device *radio = video_device_alloc();
	if (!radio)
	{
		TROUT_PRINT("Could not allocate video_device");
		return -EINVAL;
	}
	strlcpy(radio->name, DRIVER_NAME, sizeof(radio->name));
	radio->fops = &trout_fops;
	radio->release = video_device_release;
	radio->ioctl_ops = &trout_ioctl_ops;
	if (video_register_device(radio, VFL_TYPE_RADIO, -1))
	{
		TROUT_PRINT("Could not register video_device");
		video_device_release(radio);
	  return -EINVAL;
	}
  s_radio = radio;

  fmdev = (struct fmdev *)kzalloc(sizeof(struct fmdev), GFP_KERNEL);
  if (!fmdev)
  {
    TROUT_PRINT("Could not allocate fmdev");
    return -EINVAL;
  }
  video_set_drvdata(radio, fmdev);
  radio->ctrl_handler = &fmdev->ctrl_handler;
  ret = v4l2_ctrl_handler_init(&fmdev->ctrl_handler, 1);
  if (ret < 0)
  {
    TROUT_PRINT("Failed to int v4l2_ctrl_handler");
    v4l2_ctrl_handler_free(&fmdev->ctrl_handler);
    return -EINVAL;
  }
  v4l2_ctrl_new_std(&fmdev->ctrl_handler, &trout_ctrl_ops,
      V4L2_CID_PRIVATE_FM_AUDIO, 0, 1, 1, 0);

	TROUT_PRINT("Registered Trout FM Receiver.");
	return 0;
}
int fimc_is_video_probe(struct fimc_is_video *video,
	char *video_name,
	u32 video_number,
	u32 vfl_dir,
	struct fimc_is_mem *mem,
	struct v4l2_device *v4l2_dev,
	struct mutex *lock,
	const struct v4l2_file_operations *fops,
	const struct v4l2_ioctl_ops *ioctl_ops)
{
	int ret = 0;
	u32 video_id;

	vref_init(video);
	mutex_init(&video->lock);
	snprintf(video->vd.name, sizeof(video->vd.name), "%s", video_name);
	video->id		= video_number;
	video->vb2		= mem->vb2;
	video->alloc_ctx	= mem->alloc_ctx;
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0))
	video->vd.vfl_dir	= vfl_dir;
#endif
	video->vd.v4l2_dev	= v4l2_dev;
	video->vd.fops		= fops;
	video->vd.ioctl_ops	= ioctl_ops;
	video->vd.minor		= -1;
	video->vd.release	= video_device_release;
	video->vd.lock		= lock;
	video_set_drvdata(&video->vd, video);

	video_id = EXYNOS_VIDEONODE_FIMC_IS + video_number;
	ret = video_register_device(&video->vd,
		VFL_TYPE_GRABBER,
		(EXYNOS_VIDEONODE_FIMC_IS + video_number));
	if (ret) {
		err("Failed to register video device");
		goto p_err;
	}

p_err:
	info("[VID] %s(%d) is created\n", video_name, video_id);
	return ret;
}
示例#8
0
int gsc_register_m2m_device(struct gsc_dev *gsc)
{
	struct platform_device *pdev;
	int ret;

	if (!gsc)
		return -ENODEV;

	pdev = gsc->pdev;

	gsc->vdev.fops		= &gsc_m2m_fops;
	gsc->vdev.ioctl_ops	= &gsc_m2m_ioctl_ops;
	gsc->vdev.release	= video_device_release_empty;
	gsc->vdev.lock		= &gsc->lock;
	gsc->vdev.vfl_dir	= VFL_DIR_M2M;
	gsc->vdev.v4l2_dev	= &gsc->v4l2_dev;
	snprintf(gsc->vdev.name, sizeof(gsc->vdev.name), "%s.%d:m2m",
					GSC_MODULE_NAME, gsc->id);

	video_set_drvdata(&gsc->vdev, gsc);

	gsc->m2m.vfd = &gsc->vdev;
	gsc->m2m.m2m_dev = v4l2_m2m_init(&gsc_m2m_ops);
	if (IS_ERR(gsc->m2m.m2m_dev)) {
		dev_err(&pdev->dev, "failed to initialize v4l2-m2m device\n");
		return PTR_ERR(gsc->m2m.m2m_dev);
	}

	ret = video_register_device(&gsc->vdev, VFL_TYPE_GRABBER, -1);
	if (ret) {
		dev_err(&pdev->dev,
			 "%s(): failed to register video device\n", __func__);
		goto err_m2m_release;
	}

	pr_debug("gsc m2m driver registered as /dev/video%d", gsc->vdev.num);
	return 0;

err_m2m_release:
	v4l2_m2m_release(gsc->m2m.m2m_dev);

	return ret;
}
示例#9
0
文件: f_uvc.c 项目: 7799/linux
static int
uvc_register_video(struct uvc_device *uvc)
{
	struct usb_composite_dev *cdev = uvc->func.config->cdev;
	struct video_device *video;

	/* TODO reference counting. */
	video = video_device_alloc();
	if (video == NULL)
		return -ENOMEM;

	video->v4l2_dev = &uvc->v4l2_dev;
	video->fops = &uvc_v4l2_fops;
	video->release = video_device_release;
	strlcpy(video->name, cdev->gadget->name, sizeof(video->name));

	uvc->vdev = video;
	video_set_drvdata(video, uvc);

	return video_register_device(video, VFL_TYPE_GRABBER, -1);
}
static int empress_init(struct saa7134_dev *dev)
{
	int err;

	dprintk("%s: %s\n",dev->name,__func__);
	dev->empress_dev = video_device_alloc();
	if (NULL == dev->empress_dev)
		return -ENOMEM;
	*(dev->empress_dev) = saa7134_empress_template;
	dev->empress_dev->parent  = &dev->pci->dev;
	dev->empress_dev->release = video_device_release;
	snprintf(dev->empress_dev->name, sizeof(dev->empress_dev->name),
		 "%s empress (%s)", dev->name,
		 saa7134_boards[dev->board].name);

	INIT_WORK(&dev->empress_workqueue, empress_signal_update);

	video_set_drvdata(dev->empress_dev, dev);
	err = video_register_device(dev->empress_dev,VFL_TYPE_GRABBER,
				    empress_nr[dev->nr]);
	if (err < 0) {
		printk(KERN_INFO "%s: can't register video device\n",
		       dev->name);
		video_device_release(dev->empress_dev);
		dev->empress_dev = NULL;
		return err;
	}
	printk(KERN_INFO "%s: registered device %s [mpeg]\n",
	       dev->name, video_device_node_name(dev->empress_dev));

	videobuf_queue_sg_init(&dev->empress_tsq, &saa7134_ts_qops,
			    &dev->pci->dev, &dev->slock,
			    V4L2_BUF_TYPE_VIDEO_CAPTURE,
			    V4L2_FIELD_ALTERNATE,
			    sizeof(struct saa7134_buf),
			    dev);

	empress_signal_update(&dev->empress_workqueue);
	return 0;
}
示例#11
0
/*
 * initialize all the tea575x chips
 */
void snd_tea575x_init(struct snd_tea575x *tea)
{
	unsigned int val;

	val = tea->ops->read(tea);
	if (val == 0x1ffffff || val == 0) {
		snd_printk(KERN_ERR "Cannot find TEA575x chip\n");
		return;
	}

	memset(&tea->vd, 0, sizeof(tea->vd));
	tea->vd.owner = tea->card->module;
	strcpy(tea->vd.name, tea->tea5759 ? "TEA5759 radio" : "TEA5757 radio");
	tea->vd.type = VID_TYPE_TUNER;
	tea->vd.release = snd_tea575x_release;
	video_set_drvdata(&tea->vd, tea);
	tea->vd.fops = &tea->fops;
	tea->fops.owner = tea->card->module;
	tea->fops.open = video_exclusive_open;
	tea->fops.release = video_exclusive_release;
	tea->fops.ioctl = snd_tea575x_ioctl;
	if (video_register_device(&tea->vd, VFL_TYPE_RADIO, tea->dev_nr - 1) < 0) {
		snd_printk(KERN_ERR "unable to register tea575x tuner\n");
		return;
	}
	tea->vd_registered = 1;

	tea->val = TEA575X_BIT_BAND_FM | TEA575X_BIT_SEARCH_10_40;
	tea->freq = 90500 * 16;		/* 90.5Mhz default */

	snd_tea575x_set_freq(tea);

	/* mute on init */
	if (tea->ops->mute)
		tea->ops->mute(tea, 1);
}
示例#12
0
static int zr364xx_probe(struct usb_interface *intf,
			 const struct usb_device_id *id)
{
	struct usb_device *udev = interface_to_usbdev(intf);
	struct zr364xx_camera *cam = NULL;
	int err;

	DBG("probing...");

	dev_info(&intf->dev, DRIVER_DESC " compatible webcam plugged\n");
	dev_info(&intf->dev, "model %04x:%04x detected\n",
		 le16_to_cpu(udev->descriptor.idVendor),
		 le16_to_cpu(udev->descriptor.idProduct));

	cam = kzalloc(sizeof(struct zr364xx_camera), GFP_KERNEL);
	if (cam == NULL) {
		dev_err(&udev->dev, "cam: out of memory !\n");
		return -ENOMEM;
	}
	/* save the init method used by this camera */
	cam->method = id->driver_info;

	cam->vdev = video_device_alloc();
	if (cam->vdev == NULL) {
		dev_err(&udev->dev, "cam->vdev: out of memory !\n");
		kfree(cam);
		return -ENOMEM;
	}
	memcpy(cam->vdev, &zr364xx_template, sizeof(zr364xx_template));
	video_set_drvdata(cam->vdev, cam);
	if (debug)
		cam->vdev->debug = V4L2_DEBUG_IOCTL | V4L2_DEBUG_IOCTL_ARG;

	cam->udev = udev;

	if ((cam->buffer = kmalloc(BUFFER_SIZE, GFP_KERNEL)) == NULL) {
		dev_info(&udev->dev, "cam->buffer: out of memory !\n");
		video_device_release(cam->vdev);
		kfree(cam);
		return -ENODEV;
	}

	switch (mode) {
	case 1:
		dev_info(&udev->dev, "160x120 mode selected\n");
		cam->width = 160;
		cam->height = 120;
		break;
	case 2:
		dev_info(&udev->dev, "640x480 mode selected\n");
		cam->width = 640;
		cam->height = 480;
		break;
	default:
		dev_info(&udev->dev, "320x240 mode selected\n");
		cam->width = 320;
		cam->height = 240;
		break;
	}

	m0d1[0] = mode;
	m1[2].value = 0xf000 + mode;
	m2[1].value = 0xf000 + mode;
	header2[437] = cam->height / 256;
	header2[438] = cam->height % 256;
	header2[439] = cam->width / 256;
	header2[440] = cam->width % 256;

	cam->nb = 0;
	cam->brightness = 64;
	mutex_init(&cam->lock);

	err = video_register_device(cam->vdev, VFL_TYPE_GRABBER, -1);
	if (err) {
		dev_err(&udev->dev, "video_register_device failed\n");
		video_device_release(cam->vdev);
		kfree(cam->buffer);
		kfree(cam);
		return err;
	}

	usb_set_intfdata(intf, cam);

	dev_info(&udev->dev, DRIVER_DESC " controlling video device %d\n",
		 cam->vdev->num);
	return 0;
}
static int __devinit vcap_probe(struct platform_device *pdev)
{
	struct vcap_dev *dev;
	struct video_device *vfd;
	int ret;

	dprintk(1, "Probe started\n");
	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
	if (!dev)
		return -ENOMEM;
	vcap_ctrl = dev;
	dev->vcap_pdata = pdev->dev.platform_data;

	dev->vcapmem = platform_get_resource_byname(pdev,
			IORESOURCE_MEM, "vcap");
	if (!dev->vcapmem) {
		pr_err("VCAP: %s: no mem resource?\n", __func__);
		ret = -ENODEV;
		goto free_dev;
	}

	dev->vcapio = request_mem_region(dev->vcapmem->start,
		resource_size(dev->vcapmem), pdev->name);
	if (!dev->vcapio) {
		pr_err("VCAP: %s: no valid mem region\n", __func__);
		ret = -EBUSY;
		goto free_dev;
	}

	dev->vcapbase = ioremap(dev->vcapmem->start,
		resource_size(dev->vcapmem));
	if (!dev->vcapbase) {
		ret = -ENOMEM;
		pr_err("VCAP: %s: vcap ioremap failed\n", __func__);
		goto free_resource;
	}

	dev->vcirq = platform_get_resource_byname(pdev,
					IORESOURCE_IRQ, "vc_irq");
	if (!dev->vcirq) {
		pr_err("%s: no vc irq resource?\n", __func__);
		ret = -ENODEV;
		goto free_resource;
	}
	dev->vpirq = platform_get_resource_byname(pdev,
					IORESOURCE_IRQ, "vp_irq");
	if (!dev->vpirq) {
		pr_err("%s: no vp irq resource?\n", __func__);
		ret = -ENODEV;
		goto free_resource;
	}


	ret = request_irq(dev->vcirq->start, vcap_vc_handler,
		IRQF_TRIGGER_RISING, "vc_irq", 0);
	if (ret < 0) {
		pr_err("%s: vc irq request fail\n", __func__);
		ret = -EBUSY;
		goto free_resource;
	}
	disable_irq(dev->vcirq->start);

	ret = request_irq(dev->vpirq->start, vcap_vp_handler,
		IRQF_TRIGGER_RISING, "vp_irq", 0);

	if (ret < 0) {
		pr_err("%s: vp irq request fail\n", __func__);
		ret = -EBUSY;
		goto free_resource;
	}
	disable_irq(dev->vpirq->start);

	snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name),
			"%s", MSM_VCAP_DRV_NAME);

	ret = v4l2_device_register(NULL, &dev->v4l2_dev);
	if (ret)
		goto free_resource;

	ret = vcap_enable(dev, &pdev->dev);
	if (ret)
		goto unreg_dev;
	msm_bus_scale_client_update_request(dev->bus_client_handle, 3);

	ret = detect_vc(dev);

	if (ret)
		goto power_down;

	/* init video device*/
	vfd = video_device_alloc();
	if (!vfd)
		goto deinit_vc;

	*vfd = vcap_template;
	vfd->v4l2_dev = &dev->v4l2_dev;

	ret = video_register_device(vfd, VFL_TYPE_GRABBER, -1);
	if (ret < 0)
		goto rel_vdev;

	dev->vfd = vfd;
	video_set_drvdata(vfd, dev);

	dev->vcap_wq = create_workqueue("vcap");
	if (!dev->vcap_wq) {
		pr_err("Could not create workqueue");
		goto rel_vdev;
	}

	dev->ion_client = msm_ion_client_create(-1, "vcap");
	if (IS_ERR((void *)dev->ion_client)) {
		pr_err("could not get ion client");
		goto rel_vcap_wq;
	}

	atomic_set(&dev->vc_enabled, 0);
	atomic_set(&dev->vp_enabled, 0);

	dprintk(1, "Exit probe succesfully");
	return 0;
rel_vcap_wq:
	destroy_workqueue(dev->vcap_wq);
rel_vdev:
	video_device_release(vfd);
deinit_vc:
	deinit_vc();
power_down:
	vcap_disable(dev);
unreg_dev:
	v4l2_device_unregister(&dev->v4l2_dev);
free_resource:
	iounmap(dev->vcapbase);
	release_mem_region(dev->vcapmem->start, resource_size(dev->vcapmem));
free_dev:
	vcap_ctrl = NULL;
	kfree(dev);
	return ret;
}
int camera_init_v4l2(struct device *dev, unsigned int *session)
{
	struct msm_video_device *pvdev;
	struct v4l2_device *v4l2_dev;
	int rc = 0;

	pvdev = kzalloc(sizeof(struct msm_video_device),
		GFP_KERNEL);
	if (WARN_ON(!pvdev)) {
		rc = -ENOMEM;
		goto init_end;
	}

	pvdev->vdev = video_device_alloc();
	if (WARN_ON(!pvdev->vdev)) {
		rc = -ENOMEM;
		goto video_fail;
	}

	v4l2_dev = kzalloc(sizeof(struct v4l2_device), GFP_KERNEL);
	if (WARN_ON(!v4l2_dev)) {
		rc = -ENOMEM;
		goto v4l2_fail;
	}

#if defined(CONFIG_MEDIA_CONTROLLER)
	v4l2_dev->mdev = kzalloc(sizeof(struct media_device),
							 GFP_KERNEL);
	if (!v4l2_dev->mdev) {
		rc = -ENOMEM;
		goto mdev_fail;
	}
	strlcpy(v4l2_dev->mdev->model, MSM_CAMERA_NAME,
			sizeof(v4l2_dev->mdev->model));

	v4l2_dev->mdev->dev = dev;

	rc = media_device_register(v4l2_dev->mdev);
	if (WARN_ON(rc < 0))
		goto media_fail;

	rc = media_entity_init(&pvdev->vdev->entity, 0, NULL, 0);
	if (WARN_ON(rc < 0))
		goto entity_fail;
	pvdev->vdev->entity.type = MEDIA_ENT_T_DEVNODE_V4L;
	pvdev->vdev->entity.group_id = QCAMERA_VNODE_GROUP_ID;
#endif

	v4l2_dev->notify = NULL;
	pvdev->vdev->v4l2_dev = v4l2_dev;

	rc = v4l2_device_register(dev, pvdev->vdev->v4l2_dev);
	if (WARN_ON(rc < 0))
		goto register_fail;

	strlcpy(pvdev->vdev->name, "msm-sensor", sizeof(pvdev->vdev->name));
	pvdev->vdev->release  = video_device_release;
	pvdev->vdev->fops     = &camera_v4l2_fops;
	pvdev->vdev->ioctl_ops = &camera_v4l2_ioctl_ops;
	pvdev->vdev->minor     = -1;
	pvdev->vdev->vfl_type  = VFL_TYPE_GRABBER;
	rc = video_register_device(pvdev->vdev,
		VFL_TYPE_GRABBER, -1);
	if (WARN_ON(rc < 0))
		goto video_register_fail;
#if defined(CONFIG_MEDIA_CONTROLLER)
	/* FIXME: How to get rid of this messy? */
	pvdev->vdev->entity.name = video_device_node_name(pvdev->vdev);
#endif

	*session = pvdev->vdev->num;
	atomic_set(&pvdev->opened, 0);
	atomic_set(&pvdev->stream_cnt, 0);
	video_set_drvdata(pvdev->vdev, pvdev);
	device_init_wakeup(&pvdev->vdev->dev, 1);
    if(!cam_wakelock_init)
    {
        cam_wakelock_init = 1;
        wake_lock_init(&cam_wakelock, WAKE_LOCK_SUSPEND, "cam_wakelock");
    }
	goto init_end;

video_register_fail:
	v4l2_device_unregister(pvdev->vdev->v4l2_dev);
register_fail:
#if defined(CONFIG_MEDIA_CONTROLLER)
	media_entity_cleanup(&pvdev->vdev->entity);
entity_fail:
	media_device_unregister(v4l2_dev->mdev);
media_fail:
	kzfree(v4l2_dev->mdev);
mdev_fail:
#endif
	kzfree(v4l2_dev);
v4l2_fail:
	video_device_release(pvdev->vdev);
video_fail:
	kzfree(pvdev);
init_end:
	return rc;
}
示例#15
0
/* Initialize camera device. Setup all internal flags, set a
   default video mode, setup ccd-chip, register v4l device etc..
   Also used for 'probing' of hardware.
   -1 on error */
static int w9966_init(struct w9966 *cam, struct parport *port)
{
	struct v4l2_device *v4l2_dev = &cam->v4l2_dev;

	if (cam->dev_state != 0)
		return -1;

	strlcpy(v4l2_dev->name, "w9966", sizeof(v4l2_dev->name));

	if (v4l2_device_register(NULL, v4l2_dev) < 0) {
		v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
		return -1;
	}
	cam->pport = port;
	cam->brightness = 128;
	cam->contrast = 64;
	cam->color = 64;
	cam->hue = 0;

	/* Select requested transfer mode */
	switch (parmode) {
	default:	/* Auto-detect (priority: hw-ecp, hw-epp, sw-ecp) */
	case 0:
		if (port->modes & PARPORT_MODE_ECP)
			cam->ppmode = IEEE1284_MODE_ECP;
		else if (port->modes & PARPORT_MODE_EPP)
			cam->ppmode = IEEE1284_MODE_EPP;
		else
			cam->ppmode = IEEE1284_MODE_ECP;
		break;
	case 1:		/* hw- or sw-ecp */
		cam->ppmode = IEEE1284_MODE_ECP;
		break;
	case 2:		/* hw- or sw-epp */
		cam->ppmode = IEEE1284_MODE_EPP;
		break;
	}

	/* Tell the parport driver that we exists */
	cam->pdev = parport_register_device(port, "w9966", NULL, NULL, NULL, 0, NULL);
	if (cam->pdev == NULL) {
		DPRINTF("parport_register_device() failed\n");
		return -1;
	}
	w9966_set_state(cam, W9966_STATE_PDEV, W9966_STATE_PDEV);

	w9966_pdev_claim(cam);

	/* Setup a default capture mode */
	if (w9966_setup(cam, 0, 0, 1023, 1023, 200, 160) != 0) {
		DPRINTF("w9966_setup() failed.\n");
		return -1;
	}

	w9966_pdev_release(cam);

	/* Fill in the video_device struct and register us to v4l */
	strlcpy(cam->vdev.name, W9966_DRIVERNAME, sizeof(cam->vdev.name));
	cam->vdev.v4l2_dev = v4l2_dev;
	cam->vdev.fops = &w9966_fops;
	cam->vdev.ioctl_ops = &w9966_ioctl_ops;
	cam->vdev.release = video_device_release_empty;
	video_set_drvdata(&cam->vdev, cam);

	mutex_init(&cam->lock);

	if (video_register_device(&cam->vdev, VFL_TYPE_GRABBER, video_nr) < 0)
		return -1;

	w9966_set_state(cam, W9966_STATE_VDEV, W9966_STATE_VDEV);

	/* All ok */
	v4l2_info(v4l2_dev, "Found and initialized a webcam on %s.\n",
			cam->pport->name);
	return 0;
}
示例#16
0
int
hwcam_dev_create(
        struct device* dev,
        int* dev_num)
{
	int rc = 0;
    struct v4l2_device* v4l2 = NULL;
    struct video_device* vdev = NULL;
    struct media_device* mdev = NULL;
    hwcam_dev_t* cam = NULL;

    cam = kzalloc(sizeof(hwcam_dev_t), GFP_KERNEL);
	if (WARN_ON(!cam)) {
		rc = -ENOMEM;
		goto init_end;
	}
    v4l2 = &cam->v4l2;

    vdev = video_device_alloc();
    if (!vdev) {
		rc = -ENOMEM;
		goto video_alloc_fail;
    }

    mdev = kzalloc(sizeof(struct media_device), GFP_KERNEL);
	if (!mdev) {
		rc = -ENOMEM;
		goto media_alloc_fail;
	}

	strlcpy(mdev->model, HWCAM_MODEL_USER, sizeof(mdev->model));
	mdev->dev = dev;
	rc = media_device_register(mdev);
	if (rc < 0) {
		goto media_register_fail;
    }

	rc = media_entity_init(&vdev->entity, 0, NULL, 0);
	if (rc < 0) {
		goto entity_init_fail;
    }

    v4l2->mdev = mdev;
	v4l2->notify = NULL;
	rc = v4l2_device_register(dev, v4l2);
	if (rc < 0) {
		goto v4l2_register_fail;
    }

	strlcpy(vdev->name, "hwcam-userdev", sizeof(vdev->name));
	vdev->entity.type = MEDIA_ENT_T_DEVNODE_V4L;
	vdev->entity.group_id = HWCAM_DEVICE_GROUP_ID;
	vdev->v4l2_dev = v4l2;
	vdev->release = video_device_release;
	vdev->fops = &s_fops_hwcam_dev;
	vdev->ioctl_ops = &s_iops_hwcam_dev;
	vdev->minor = -1;
	vdev->vfl_type = VFL_TYPE_GRABBER;
	rc = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
	if (rc < 0) {
		goto video_register_fail;
    }
	cam_debug("video dev name %s %s",vdev->dev.kobj.name,vdev->name);
    mutex_init(&cam->lock);
    vdev->lock = &cam->lock;
	vdev->entity.name = video_device_node_name(vdev);
	video_set_drvdata(vdev, cam);
    cam->vdev = vdev;
    cam->mdev = mdev;
    cam->intf.vtbl = &s_vtbl_hwcam_dev;
    *dev_num = vdev->num;

	goto init_end;

video_register_fail:
	v4l2_device_unregister(v4l2);

v4l2_register_fail:
	media_entity_cleanup(&vdev->entity);

entity_init_fail:
	media_device_unregister(mdev);

media_register_fail:
    kzfree(mdev);

media_alloc_fail:
	video_device_release(vdev);

video_alloc_fail:
	kzfree(cam);

init_end:
	return rc;
}
示例#17
0
static int empress_init(struct saa7134_dev *dev)
{
    struct v4l2_ctrl_handler *hdl = &dev->empress_ctrl_handler;
    struct vb2_queue *q;
    int err;

    pr_debug("%s: %s\n", dev->name, __func__);
    dev->empress_dev = video_device_alloc();
    if (NULL == dev->empress_dev)
        return -ENOMEM;
    *(dev->empress_dev) = saa7134_empress_template;
    dev->empress_dev->v4l2_dev  = &dev->v4l2_dev;
    dev->empress_dev->release = video_device_release;
    dev->empress_dev->lock = &dev->lock;
    snprintf(dev->empress_dev->name, sizeof(dev->empress_dev->name),
             "%s empress (%s)", dev->name,
             saa7134_boards[dev->board].name);
    v4l2_ctrl_handler_init(hdl, 21);
    v4l2_ctrl_add_handler(hdl, &dev->ctrl_handler, empress_ctrl_filter);
    if (dev->empress_sd)
        v4l2_ctrl_add_handler(hdl, dev->empress_sd->ctrl_handler, NULL);
    if (hdl->error) {
        video_device_release(dev->empress_dev);
        return hdl->error;
    }
    dev->empress_dev->ctrl_handler = hdl;

    INIT_WORK(&dev->empress_workqueue, empress_signal_update);

    q = &dev->empress_vbq;
    q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    /*
     * Do not add VB2_USERPTR: the saa7134 DMA engine cannot handle
     * transfers that do not start at the beginning of a page. A USERPTR
     * can start anywhere in a page, so USERPTR support is a no-go.
     */
    q->io_modes = VB2_MMAP | VB2_DMABUF | VB2_READ;
    q->drv_priv = &dev->ts_q;
    q->ops = &saa7134_empress_qops;
    q->gfp_flags = GFP_DMA32;
    q->mem_ops = &vb2_dma_sg_memops;
    q->buf_struct_size = sizeof(struct saa7134_buf);
    q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
    q->lock = &dev->lock;
    q->dev = &dev->pci->dev;
    err = vb2_queue_init(q);
    if (err)
        return err;
    dev->empress_dev->queue = q;

    video_set_drvdata(dev->empress_dev, dev);
    err = video_register_device(dev->empress_dev,VFL_TYPE_GRABBER,
                                empress_nr[dev->nr]);
    if (err < 0) {
        pr_info("%s: can't register video device\n",
                dev->name);
        video_device_release(dev->empress_dev);
        dev->empress_dev = NULL;
        return err;
    }
    pr_info("%s: registered device %s [mpeg]\n",
            dev->name, video_device_node_name(dev->empress_dev));

    empress_signal_update(&dev->empress_workqueue);
    return 0;
}
示例#18
0
/*!
 * Probe routine for the framebuffer driver. It is called during the
 * driver binding process.      The following functions are performed in
 * this routine: Framebuffer initialization, Memory allocation and
 * mapping, Framebuffer registration, IPU initialization.
 *
 * @return      Appropriate error code to the kernel common code
 */
static int mxc_v4l2out_probe(struct device *dev)
{
	int i;
	vout_data *vout;

	FUNC_START;
	/*
	 * Allocate sufficient memory for the fb structure
	 */
	vout = kmalloc(sizeof(vout_data), GFP_KERNEL);

	if (!vout)
		return 0;

	memset(vout, 0, sizeof(vout_data));

	vout->video_dev = video_device_alloc();
	if (vout->video_dev == NULL)
		return -1;
	vout->video_dev->dev = dev;
	vout->video_dev->minor = -1;

	*(vout->video_dev) = mxc_v4l2out_template;

	/* register v4l device */
	if (video_register_device(vout->video_dev,
				  VFL_TYPE_GRABBER, video_nr) == -1) {
		printk(KERN_DEBUG "video_register_device failed\n");
		return 0;
	}
	printk(KERN_INFO "mxc_v4l2out: registered device video%d\n",
	       vout->video_dev->minor & 0x1f);

	video_set_drvdata(vout->video_dev, vout);

	init_MUTEX(&vout->param_lock);
	init_MUTEX(&vout->busy_lock);

	/* setup outputs and cropping */
	vout->cur_disp_output = -1;
	for (i = 0; i < num_registered_fb; i++) {
		char *idstr = registered_fb[i]->fix.id;
		if (strncmp(idstr, "DISP", 4) == 0) {
			int disp_num = idstr[4] - '0';
			if ((disp_num == 3) &&
			    (strncmp(idstr, "DISP3 BG", 8) != 0)) {
				continue;
			}
			vout->crop_bounds[disp_num].left = 0;
			vout->crop_bounds[disp_num].top = 0;
			vout->crop_bounds[disp_num].width =
			    registered_fb[i]->var.xres;
			vout->crop_bounds[disp_num].height =
			    registered_fb[i]->var.yres;
			vout->output_enabled[disp_num] = true;
			vout->output_fb_num[disp_num] = i;
			if (vout->cur_disp_output == -1)
				vout->cur_disp_output = disp_num;
		}

	}
	vout->crop_current = vout->crop_bounds[vout->cur_disp_output];

	FUNC_END;
	return 0;
}
static __init int vpif_probe(struct platform_device *pdev)
{
	struct vpif_subdev_info *subdevdata;
	struct vpif_capture_config *config;
	int i, j, k, m, q, err;
	struct i2c_adapter *i2c_adap;
	struct channel_obj *ch;
	struct common_obj *common;
	struct video_device *vfd;
	struct resource *res;
	int subdev_count;

	vpif_dev = &pdev->dev;

	err = initialize_vpif();
	if (err) {
		v4l2_err(vpif_dev->driver, "Error initializing vpif\n");
		return err;
	}

	k = 0;
	while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, k))) {
		for (i = res->start; i <= res->end; i++) {
			if (request_irq(i, vpif_channel_isr, IRQF_DISABLED,
					"DM646x_Capture",
				(void *)(&vpif_obj.dev[k]->channel_id))) {
				err = -EBUSY;
				i--;
				goto vpif_int_err;
			}
		}
		k++;
	}

	for (i = 0; i < VPIF_CAPTURE_MAX_DEVICES; i++) {
		/* Get the pointer to the channel object */
		ch = vpif_obj.dev[i];
		/* Allocate memory for video device */
		vfd = video_device_alloc();
		if (NULL == vfd) {
			for (j = 0; j < i; j++) {
				ch = vpif_obj.dev[j];
				video_device_release(ch->video_dev);
			}
			err = -ENOMEM;
			goto vpif_dev_alloc_err;
		}

		/* Initialize field of video device */
		*vfd = vpif_video_template;
		vfd->v4l2_dev = &vpif_obj.v4l2_dev;
		vfd->release = video_device_release;
		snprintf(vfd->name, sizeof(vfd->name),
			 "DM646x_VPIFCapture_DRIVER_V%d.%d.%d",
			 (VPIF_CAPTURE_VERSION_CODE >> 16) & 0xff,
			 (VPIF_CAPTURE_VERSION_CODE >> 8) & 0xff,
			 (VPIF_CAPTURE_VERSION_CODE) & 0xff);
		/* Set video_dev to the video device */
		ch->video_dev = vfd;
	}

	for (j = 0; j < VPIF_CAPTURE_MAX_DEVICES; j++) {
		ch = vpif_obj.dev[j];
		ch->channel_id = j;
		common = &(ch->common[VPIF_VIDEO_INDEX]);
		spin_lock_init(&common->irqlock);
		mutex_init(&common->lock);
		/* Initialize prio member of channel object */
		v4l2_prio_init(&ch->prio);
		err = video_register_device(ch->video_dev,
					    VFL_TYPE_GRABBER, (j ? 1 : 0));
		if (err)
			goto probe_out;

		video_set_drvdata(ch->video_dev, ch);

	}

	i2c_adap = i2c_get_adapter(1);
	config = pdev->dev.platform_data;

	subdev_count = config->subdev_count;
	vpif_obj.sd = kmalloc(sizeof(struct v4l2_subdev *) * subdev_count,
				GFP_KERNEL);
	if (vpif_obj.sd == NULL) {
		vpif_err("unable to allocate memory for subdevice pointers\n");
		err = -ENOMEM;
		goto probe_out;
	}

	err = v4l2_device_register(vpif_dev, &vpif_obj.v4l2_dev);
	if (err) {
		v4l2_err(vpif_dev->driver, "Error registering v4l2 device\n");
		goto probe_subdev_out;
	}

	for (i = 0; i < subdev_count; i++) {
		subdevdata = &config->subdev_info[i];
		vpif_obj.sd[i] =
			v4l2_i2c_new_subdev_board(&vpif_obj.v4l2_dev,
						  i2c_adap,
						  subdevdata->name,
						  &subdevdata->board_info,
						  NULL);

		if (!vpif_obj.sd[i]) {
			vpif_err("Error registering v4l2 subdevice\n");
			goto probe_subdev_out;
		}
		v4l2_info(&vpif_obj.v4l2_dev, "registered sub device %s\n",
			  subdevdata->name);

		if (vpif_obj.sd[i])
			vpif_obj.sd[i]->grp_id = 1 << i;
	}
	v4l2_info(&vpif_obj.v4l2_dev, "DM646x VPIF Capture driver"
		  " initialized\n");

	return 0;

probe_subdev_out:
	/* free sub devices memory */
	kfree(vpif_obj.sd);

	j = VPIF_CAPTURE_MAX_DEVICES;
probe_out:
	v4l2_device_unregister(&vpif_obj.v4l2_dev);
	for (k = 0; k < j; k++) {
		/* Get the pointer to the channel object */
		ch = vpif_obj.dev[k];
		/* Unregister video device */
		video_unregister_device(ch->video_dev);
	}

vpif_dev_alloc_err:
	k = VPIF_CAPTURE_MAX_DEVICES-1;
	res = platform_get_resource(pdev, IORESOURCE_IRQ, k);
	i = res->end;

vpif_int_err:
	for (q = k; q >= 0; q--) {
		for (m = i; m >= (int)res->start; m--)
			free_irq(m, (void *)(&vpif_obj.dev[q]->channel_id));

		res = platform_get_resource(pdev, IORESOURCE_IRQ, q-1);
		if (res)
			i = res->end;
	}
	return err;
}
示例#20
0
int fm_v4l2_init_video_device(struct fmdev *fmdev, int radio_nr)
{
	struct v4l2_ctrl *ctrl;
	int ret;

	/* Init mutex for core locking */
	mutex_init(&fmdev->mutex);

	/* Allocate new video device */
	gradio_dev = video_device_alloc();
	if (NULL == gradio_dev) {
		fmerr("Can't allocate video device\n");
		return -ENOMEM;
	}

	/* Setup FM driver's V4L2 properties */
	memcpy(gradio_dev, &fm_viddev_template, sizeof(fm_viddev_template));

	video_set_drvdata(gradio_dev, fmdev);

	gradio_dev->lock = &fmdev->mutex;

	/* Register with V4L2 subsystem as RADIO device */
	if (video_register_device(gradio_dev, VFL_TYPE_RADIO, radio_nr)) {
		video_device_release(gradio_dev);
		fmerr("Could not register video device\n");
		return -ENOMEM;
	}

	fmdev->radio_dev = gradio_dev;

	/* Register to v4l2 ctrl handler framework */
	fmdev->radio_dev->ctrl_handler = &fmdev->ctrl_handler;

	ret = v4l2_ctrl_handler_init(&fmdev->ctrl_handler, 5);
	if (ret < 0) {
		fmerr("(fmdev): Can't init ctrl handler\n");
		v4l2_ctrl_handler_free(&fmdev->ctrl_handler);
		return -EBUSY;
	}

	/*
	 * Following controls are handled by V4L2 control framework.
	 * Added in ascending ID order.
	 */
	v4l2_ctrl_new_std(&fmdev->ctrl_handler, &fm_ctrl_ops,
			V4L2_CID_AUDIO_VOLUME, FM_RX_VOLUME_MIN,
			FM_RX_VOLUME_MAX, 1, FM_RX_VOLUME_MAX);

	v4l2_ctrl_new_std(&fmdev->ctrl_handler, &fm_ctrl_ops,
			V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0);

	v4l2_ctrl_new_std(&fmdev->ctrl_handler, &fm_ctrl_ops,
			V4L2_CID_RDS_TX_PI, 0x0, 0xffff, 1, 0x0);

	v4l2_ctrl_new_std(&fmdev->ctrl_handler, &fm_ctrl_ops,
			V4L2_CID_RDS_TX_PTY, 0, 32, 1, 0);

	v4l2_ctrl_new_std(&fmdev->ctrl_handler, &fm_ctrl_ops,
			V4L2_CID_RDS_TX_PS_NAME, 0, 0xffff, 1, 0);

	v4l2_ctrl_new_std(&fmdev->ctrl_handler, &fm_ctrl_ops,
			V4L2_CID_RDS_TX_RADIO_TEXT, 0, 0xffff, 1, 0);

	v4l2_ctrl_new_std_menu(&fmdev->ctrl_handler, &fm_ctrl_ops,
			V4L2_CID_TUNE_PREEMPHASIS, V4L2_PREEMPHASIS_75_uS,
			0, V4L2_PREEMPHASIS_75_uS);

	v4l2_ctrl_new_std(&fmdev->ctrl_handler, &fm_ctrl_ops,
			V4L2_CID_TUNE_POWER_LEVEL, FM_PWR_LVL_LOW,
			FM_PWR_LVL_HIGH, 1, FM_PWR_LVL_HIGH);

	ctrl = v4l2_ctrl_new_std(&fmdev->ctrl_handler, &fm_ctrl_ops,
			V4L2_CID_TUNE_ANTENNA_CAPACITOR, 0,
			255, 1, 255);

	if (ctrl)
		ctrl->is_volatile = 1;

	return 0;
}
示例#21
0
/*
 * si470x_usb_driver_probe - probe for the device
 */
static int si470x_usb_driver_probe(struct usb_interface *intf,
		const struct usb_device_id *id)
{
	struct si470x_device *radio;
	int retval = 0;

	/* private data allocation and initialization */
	radio = kzalloc(sizeof(struct si470x_device), GFP_KERNEL);
	if (!radio) {
		retval = -ENOMEM;
		goto err_initial;
	}
	radio->users = 0;
	radio->disconnected = 0;
	radio->usbdev = interface_to_usbdev(intf);
	radio->intf = intf;
	mutex_init(&radio->disconnect_lock);
	mutex_init(&radio->lock);

	/* video device allocation and initialization */
	radio->videodev = video_device_alloc();
	if (!radio->videodev) {
		retval = -ENOMEM;
		goto err_radio;
	}
	memcpy(radio->videodev, &si470x_viddev_template,
			sizeof(si470x_viddev_template));
	video_set_drvdata(radio->videodev, radio);

	/* show some infos about the specific si470x device */
	if (si470x_get_all_registers(radio) < 0) {
		retval = -EIO;
		goto err_video;
	}
	printk(KERN_INFO DRIVER_NAME ": DeviceID=0x%4.4hx ChipID=0x%4.4hx\n",
			radio->registers[DEVICEID], radio->registers[CHIPID]);

	/* get software and hardware versions */
	if (si470x_get_scratch_page_versions(radio) < 0) {
		retval = -EIO;
		goto err_video;
	}
	printk(KERN_INFO DRIVER_NAME
			": software version %d, hardware version %d\n",
			radio->software_version, radio->hardware_version);

	/* check if device and firmware is current */
	if ((radio->registers[CHIPID] & CHIPID_FIRMWARE)
			< RADIO_SW_VERSION_CURRENT) {
		printk(KERN_WARNING DRIVER_NAME
			": This driver is known to work with "
			"firmware version %hu,\n", RADIO_SW_VERSION_CURRENT);
		printk(KERN_WARNING DRIVER_NAME
			": but the device has firmware version %hu.\n",
			radio->registers[CHIPID] & CHIPID_FIRMWARE);
		printk(KERN_WARNING DRIVER_NAME
			": If you have some trouble using this driver,\n");
		printk(KERN_WARNING DRIVER_NAME
			": please report to V4L ML at "
			"[email protected]\n");
	}

	/* set initial frequency */
	si470x_set_freq(radio, 87.5 * FREQ_MUL); /* available in all regions */

	/* set led to connect state */
	si470x_set_led_state(radio, BLINK_GREEN_LED);

	/* rds buffer allocation */
	radio->buf_size = rds_buf * 3;
	radio->buffer = kmalloc(radio->buf_size, GFP_KERNEL);
	if (!radio->buffer) {
		retval = -EIO;
		goto err_video;
	}

	/* rds buffer configuration */
	radio->wr_index = 0;
	radio->rd_index = 0;
	init_waitqueue_head(&radio->read_queue);

	/* prepare rds work function */
	INIT_DELAYED_WORK(&radio->work, si470x_work);

	/* register video device */
	retval = video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr);
	if (retval) {
		printk(KERN_WARNING DRIVER_NAME
				": Could not register video device\n");
		goto err_all;
	}
	usb_set_intfdata(intf, radio);

	return 0;
err_all:
	kfree(radio->buffer);
err_video:
	video_device_release(radio->videodev);
err_radio:
	kfree(radio);
err_initial:
	return retval;
}
示例#22
0
int fimc_isp_video_device_register(struct fimc_isp *isp,
				   struct v4l2_device *v4l2_dev,
				   enum v4l2_buf_type type)
{
	struct vb2_queue *q = &isp->video_capture.vb_queue;
	struct fimc_is_video *iv;
	struct video_device *vdev;
	int ret;

	if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
		iv = &isp->video_capture;
	else
		return -ENOSYS;

	mutex_init(&isp->video_lock);
	INIT_LIST_HEAD(&iv->pending_buf_q);
	INIT_LIST_HEAD(&iv->active_buf_q);
	iv->format = fimc_isp_find_format(NULL, NULL, 0);
	iv->pixfmt.width = IS_DEFAULT_WIDTH;
	iv->pixfmt.height = IS_DEFAULT_HEIGHT;
	iv->pixfmt.pixelformat = iv->format->fourcc;
	iv->pixfmt.colorspace = V4L2_COLORSPACE_SRGB;
	iv->reqbufs_count = 0;

	memset(q, 0, sizeof(*q));
	q->type = type;
	q->io_modes = VB2_MMAP | VB2_USERPTR;
	q->ops = &isp_video_capture_qops;
	q->mem_ops = &vb2_dma_contig_memops;
	q->buf_struct_size = sizeof(struct isp_video_buf);
	q->drv_priv = isp;
	q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
	q->lock = &isp->video_lock;

	ret = vb2_queue_init(q);
	if (ret < 0)
		return ret;

	vdev = &iv->ve.vdev;
	memset(vdev, 0, sizeof(*vdev));
	snprintf(vdev->name, sizeof(vdev->name), "fimc-is-isp.%s",
			type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE ?
			"capture" : "output");
	vdev->queue = q;
	vdev->fops = &isp_video_fops;
	vdev->ioctl_ops = &isp_video_ioctl_ops;
	vdev->v4l2_dev = v4l2_dev;
	vdev->minor = -1;
	vdev->release = video_device_release_empty;
	vdev->lock = &isp->video_lock;

	iv->pad.flags = MEDIA_PAD_FL_SINK;
	ret = media_entity_pads_init(&vdev->entity, 1, &iv->pad);
	if (ret < 0)
		return ret;

	video_set_drvdata(vdev, isp);

	ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
	if (ret < 0) {
		media_entity_cleanup(&vdev->entity);
		return ret;
	}

	v4l2_info(v4l2_dev, "Registered %s as /dev/%s\n",
		  vdev->name, video_device_node_name(vdev));

	return 0;
}
/*
 * si470x_i2c_probe - probe for the device
 */
static int __devinit si470x_i2c_probe(struct i2c_client *client,
		const struct i2c_device_id *id)
{
	struct si470x_device *radio;
	int retval = 0;
	unsigned char version_warning = 0;

	/* private data allocation and initialization */
	radio = kzalloc(sizeof(struct si470x_device), GFP_KERNEL);
	if (!radio) {
		retval = -ENOMEM;
		goto err_initial;
	}

	radio->users = 0;
	radio->client = client;
	mutex_init(&radio->lock);

	/* video device allocation and initialization */
	radio->videodev = video_device_alloc();
	if (!radio->videodev) {
		retval = -ENOMEM;
		goto err_radio;
	}
	memcpy(radio->videodev, &si470x_viddev_template,
			sizeof(si470x_viddev_template));
	video_set_drvdata(radio->videodev, radio);

	/* power up : need 110ms */
	radio->registers[POWERCFG] = POWERCFG_ENABLE;
	if (si470x_set_register(radio, POWERCFG) < 0) {
		retval = -EIO;
		goto err_video;
	}
	msleep(110);

	/* get device and chip versions */
	if (si470x_get_all_registers(radio) < 0) {
		retval = -EIO;
		goto err_video;
	}
	dev_info(&client->dev, "DeviceID=0x%4.4hx ChipID=0x%4.4hx\n",
			radio->registers[DEVICEID], radio->registers[CHIPID]);
	if ((radio->registers[CHIPID] & CHIPID_FIRMWARE) < RADIO_FW_VERSION) {
		dev_warn(&client->dev,
			"This driver is known to work with "
			"firmware version %hu,\n", RADIO_FW_VERSION);
		dev_warn(&client->dev,
			"but the device has firmware version %hu.\n",
			radio->registers[CHIPID] & CHIPID_FIRMWARE);
		version_warning = 1;
	}

	/* give out version warning */
	if (version_warning == 1) {
		dev_warn(&client->dev,
			"If you have some trouble using this driver,\n");
		dev_warn(&client->dev,
			"please report to V4L ML at "
			"[email protected]\n");
	}

	/* set initial frequency */
	si470x_set_freq(radio, 87.5 * FREQ_MUL); /* available in all regions */

	/* rds buffer allocation */
	radio->buf_size = rds_buf * 3;
	radio->buffer = kmalloc(radio->buf_size, GFP_KERNEL);
	if (!radio->buffer) {
		retval = -EIO;
		goto err_video;
	}

	/* rds buffer configuration */
	radio->wr_index = 0;
	radio->rd_index = 0;
	init_waitqueue_head(&radio->read_queue);

	/* mark Seek/Tune Complete Interrupt enabled */
	radio->stci_enabled = true;
	init_completion(&radio->completion);

	retval = request_threaded_irq(client->irq, NULL, si470x_i2c_interrupt,
			IRQF_TRIGGER_FALLING, DRIVER_NAME, radio);
	if (retval) {
		dev_err(&client->dev, "Failed to register interrupt\n");
		goto err_rds;
	}

	/* register video device */
	retval = video_register_device(radio->videodev, VFL_TYPE_RADIO,
			radio_nr);
	if (retval) {
		dev_warn(&client->dev, "Could not register video device\n");
		goto err_all;
	}
	i2c_set_clientdata(client, radio);

	return 0;
err_all:
	free_irq(client->irq, radio);
err_rds:
	kfree(radio->buffer);
err_video:
	video_device_release(radio->videodev);
err_radio:
	kfree(radio);
err_initial:
	return retval;
}
示例#24
0
static int fimc_lite_subdev_registered(struct v4l2_subdev *sd)
{
	struct fimc_lite *fimc = v4l2_get_subdevdata(sd);
	struct vb2_queue *q = &fimc->vb_queue;
	struct video_device *vfd;
	int ret;

	fimc->fmt = &fimc_lite_formats[0];
	fimc->out_path = FIMC_IO_DMA;

	vfd = video_device_alloc();
	if (!vfd) {
		v4l2_err(sd->v4l2_dev, "Failed to allocate video device\n");
		return -ENOMEM;
	}

	snprintf(vfd->name, sizeof(vfd->name), "fimc-lite.%d.capture",
		 fimc->index);

	vfd->fops = &fimc_lite_fops;
	vfd->ioctl_ops = &fimc_lite_ioctl_ops;
	vfd->v4l2_dev = sd->v4l2_dev;
	vfd->minor = -1;
	vfd->release = video_device_release;
	vfd->lock = &fimc->lock;
	fimc->vfd = vfd;
	fimc->ref_count = 0;
	fimc->reqbufs_count = 0;

	INIT_LIST_HEAD(&fimc->pending_buf_q);
	INIT_LIST_HEAD(&fimc->active_buf_q);

	memset(q, 0, sizeof(*q));
	q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
	q->io_modes = VB2_MMAP | VB2_USERPTR;
	q->ops = &fimc_lite_qops;
	q->mem_ops = &vb2_dma_contig_memops;
	q->buf_struct_size = sizeof(struct flite_buffer);
	q->drv_priv = fimc;

	vb2_queue_init(q);

	fimc->vd_pad.flags = MEDIA_PAD_FL_SINK;
	ret = media_entity_init(&vfd->entity, 1, &fimc->vd_pad, 0);
	if (ret)
		goto err;

	video_set_drvdata(vfd, fimc);

	ret = video_register_device(vfd, VFL_TYPE_GRABBER, -1);
	if (ret)
		goto err_vd;

	v4l2_info(sd->v4l2_dev, "Registered %s as /dev/%s\n",
		  vfd->name, video_device_node_name(vfd));
	return 0;

 err_vd:
	media_entity_cleanup(&vfd->entity);
 err:
	video_device_release(vfd);
	return ret;
}
示例#25
0
static int fimc_is_probe(struct platform_device *pdev)
{
	struct exynos4_platform_fimc_is *pdata;
	struct resource *mem_res;
	struct resource *regs_res;
	struct fimc_is_dev *dev;
#if defined(CONFIG_VIDEO_EXYNOS_FIMC_IS_BAYER)
	struct v4l2_device *v4l2_dev;
	struct vb2_queue *isp_q;
#endif
	int ret = -ENODEV;

	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
	if (!dev) {
		dev_err(&pdev->dev, "Not enough memory for FIMC-IS device.\n");
		return -ENOMEM;
	}
	mutex_init(&dev->lock);
	spin_lock_init(&dev->slock);
	init_waitqueue_head(&dev->irq_queue1);

	dev->pdev = pdev;
	if (!dev->pdev) {
		dev_err(&pdev->dev, "No platform data specified\n");
		goto p_err_info;
	}

	pdata = pdev->dev.platform_data;
	if (!pdata) {
		dev_err(&pdev->dev, "Platform data not set\n");
		goto p_err_info;
	}
	dev->pdata = pdata;
	/*
	 * I/O remap
	*/
	mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!mem_res) {
		dev_err(&pdev->dev, "Failed to get io memory region\n");
		ret = -ENOENT;
		goto p_err_info;
	}

	regs_res = request_mem_region(mem_res->start,
		resource_size(mem_res), pdev->name);
	if (!regs_res) {
		dev_err(&pdev->dev, "Failed to request io memory region\n");
		ret = -ENOENT;
		goto p_err_info;
	}
	dev->regs_res = regs_res;

	dev->regs = ioremap(mem_res->start, resource_size(mem_res));
	if (!dev->regs) {
		dev_err(&pdev->dev, "Failed to remap io region\n");
		ret = -ENXIO;
		goto p_err_req_region;
	}

	/*
	 * initialize IRQ , FIMC-IS IRQ : ISP[0] -> SPI[90] , ISP[1] -> SPI[95]
	*/
	dev->irq1 = platform_get_irq(pdev, 0);
	if (dev->irq1 < 0) {
		ret = dev->irq1;
		dev_err(&pdev->dev, "Failed to get irq\n");
		goto p_err_get_irq;
	}

	ret = request_irq(dev->irq1, fimc_is_irq_handler1,
		IRQF_DISABLED, dev_name(&pdev->dev), dev);
	if (ret) {
		dev_err(&pdev->dev, "failed to allocate irq (%d)\n", ret);
		goto p_err_req_irq;
	}

#if defined(CONFIG_VIDEO_EXYNOS_FIMC_IS_BAYER)
	/* Init v4l2 device (ISP) */
#if defined(CONFIG_VIDEOBUF2_CMA_PHYS)
	dev->vb2 = &fimc_is_vb2_cma;
#elif defined(CONFIG_VIDEOBUF2_ION)
	dev->vb2 = &fimc_is_vb2_ion;
#endif

	/* Init and register V4L2 device */
	v4l2_dev = &dev->video[FIMC_IS_VIDEO_NUM_BAYER].v4l2_dev;
	if (!v4l2_dev->name[0])
		snprintf(v4l2_dev->name, sizeof(v4l2_dev->name),
			 "%s.isp", dev_name(&dev->pdev->dev));
	ret = v4l2_device_register(NULL, v4l2_dev);

	snprintf(dev->video[FIMC_IS_VIDEO_NUM_BAYER].vd.name,
			sizeof(dev->video[FIMC_IS_VIDEO_NUM_BAYER].vd.name),
			"%s", "exynos4-fimc-is-bayer");
	dev->video[FIMC_IS_VIDEO_NUM_BAYER].vd.fops		=
						&fimc_is_isp_video_fops;
	dev->video[FIMC_IS_VIDEO_NUM_BAYER].vd.ioctl_ops	=
						&fimc_is_isp_video_ioctl_ops;
	dev->video[FIMC_IS_VIDEO_NUM_BAYER].vd.minor		= -1;
	dev->video[FIMC_IS_VIDEO_NUM_BAYER].vd.release		=
						video_device_release;
	dev->video[FIMC_IS_VIDEO_NUM_BAYER].vd.lock		=
						&dev->lock;
	video_set_drvdata(&dev->video[FIMC_IS_VIDEO_NUM_BAYER].vd, dev);
	dev->video[FIMC_IS_VIDEO_NUM_BAYER].dev = dev;

	isp_q = &dev->video[FIMC_IS_VIDEO_NUM_BAYER].vbq;
	memset(isp_q, 0, sizeof(*isp_q));
	isp_q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
	isp_q->io_modes = VB2_MMAP | VB2_USERPTR;
	isp_q->drv_priv = &dev->video[FIMC_IS_VIDEO_NUM_BAYER];
	isp_q->ops = &fimc_is_isp_qops;
	isp_q->mem_ops = dev->vb2->ops;

	vb2_queue_init(isp_q);

	ret = video_register_device(&dev->video[FIMC_IS_VIDEO_NUM_BAYER].vd,
							VFL_TYPE_GRABBER, 30);
	if (ret) {
		v4l2_err(v4l2_dev, "Failed to register video device\n");
		goto err_vd_reg;
	}

	printk(KERN_INFO "FIMC-IS Video node :: ISP %d minor : %d\n",
		dev->video[FIMC_IS_VIDEO_NUM_BAYER].vd.num,
		dev->video[FIMC_IS_VIDEO_NUM_BAYER].vd.minor);
#endif
	/*
	 * initialize memory manager
	*/
	ret = fimc_is_init_mem_mgr(dev);
	if (ret) {
		dev_err(&pdev->dev,
			"failed to fimc_is_init_mem_mgr (%d)\n", ret);
		goto p_err_init_mem;
	}
	dbg("Parameter region = 0x%08x\n", (unsigned int)dev->is_p_region);

	/*
	 * Get related clock for FIMC-IS
	*/
	if (dev->pdata->clk_get) {
		dev->pdata->clk_get(pdev);
	} else {
		err("#### failed to Get Clock####\n");
		goto p_err_init_mem;
	}
	/* Init v4l2 sub device */
	v4l2_subdev_init(&dev->sd, &fimc_is_subdev_ops);
	dev->sd.owner = THIS_MODULE;
	strcpy(dev->sd.name, MODULE_NAME);
	v4l2_set_subdevdata(&dev->sd, pdev);

	platform_set_drvdata(pdev, &dev->sd);

	pm_runtime_enable(&pdev->dev);

#if defined(CONFIG_BUSFREQ_OPP) || defined(CONFIG_BUSFREQ_LOCK_WRAPPER)
	/* To lock bus frequency in OPP mode */
	dev->bus_dev = dev_get("exynos-busfreq");
#endif
	dev->power = 0;
	dev->state = 0;
	dev->sensor_num = FIMC_IS_SENSOR_NUM;
	dev->sensor.id = 0;
	dev->p_region_index1 = 0;
	dev->p_region_index2 = 0;
	dev->sensor.offset_x = 16;
	dev->sensor.offset_y = 12;
	dev->sensor.framerate_update = false;
	atomic_set(&dev->p_region_num, 0);
	set_bit(IS_ST_IDLE, &dev->state);
	set_bit(IS_PWR_ST_POWEROFF, &dev->power);
	dev->af.af_state = FIMC_IS_AF_IDLE;
	dev->af.mode = IS_FOCUS_MODE_IDLE;
	dev->low_power_mode = false;
	dev->fw.state = 0;
	dev->setfile.state = 0;
#if defined(M0)
	s5k6a3_dev = device_create(camera_class, NULL, 0, NULL, "front");
	if (IS_ERR(s5k6a3_dev)) {
		printk(KERN_ERR "failed to create device!\n");
	} else {
		if (device_create_file(s5k6a3_dev, &dev_attr_front_camtype)
				< 0) {
			printk(KERN_ERR "failed to create device file, %s\n",
				dev_attr_front_camtype.attr.name);
		}
		if (device_create_file(s5k6a3_dev, &dev_attr_front_camfw) < 0) {
			printk(KERN_ERR "failed to create device file, %s\n",
				dev_attr_front_camfw.attr.name);
		}
	}
#endif
	printk(KERN_INFO "FIMC-IS probe completed\n");
	return 0;

p_err_init_mem:
	free_irq(dev->irq1, dev);
#if defined(CONFIG_VIDEO_EXYNOS_FIMC_IS_BAYER)
err_vd_reg:
	video_device_release(&dev->video[FIMC_IS_VIDEO_NUM_BAYER].vd);
#endif
p_err_req_irq:
p_err_get_irq:
	iounmap(dev->regs);
p_err_req_region:
	release_mem_region(regs_res->start, resource_size(regs_res));
p_err_info:
	dev_err(&dev->pdev->dev, "failed to install\n");
	kfree(dev);
	return ret;
}
static int si4703_probe(struct i2c_client *client)
{
	uint16_t id;
	int ret;
	struct si4703_device *chip;
	struct si4703_platform_data *pdata = client->dev.platform_data;

	chip = kmalloc(sizeof(struct si4703_device), GFP_KERNEL);
	if (!chip)
		return -ENOMEM;

	chip->videodev = video_device_alloc();
	if (!chip->videodev) {
		kfree(chip);
		return -ENOMEM;
	}
	chip->client = client;
	chip->irq = client->irq;
	init_waitqueue_head(&chip->wait);
	i2c_set_clientdata(client, chip);

	enable_oscc_tout_s0();
	pdata->setup(client, pdata->context);
	if (chip->irq >= 0) {
		ret = request_irq(chip->irq, si4703_irq_handler,
			       IRQF_TRIGGER_FALLING, "si4703", chip);
		if (ret) {
			kfree(chip->videodev);
			kfree(chip);
			printk(KERN_ERR "request IRQ for si4703 failed!\n");
			return ret;
		}
	}

	/* init shadow registers */
	if (si4703_read(chip, REG_READ_START - 1, &id)) {
		free_irq(chip->irq, chip);
		kfree(chip->videodev);
		kfree(chip);
		printk(KERN_ERR "%s: failed to init shadow registers\n",
			      __FUNCTION__);
		disable_oscc_tout_s0();
		return -EIO;
	}
	si4703_power_up(chip);
	ret = si4703_read(chip, REG_CHIPID, &id);
	if (ret)
		printk(KERN_ERR "%s: failed to detect si4703\n",
			      __FUNCTION__);
	else
		printk(KERN_INFO "%s: si4703(0x%04x) detected\n",
				__FUNCTION__, id);
	si4703_power_down(chip);

	/* init volume to maxium */
	chip->curvol = 0xf;

	memcpy(chip->videodev, &si4703_videodev_template,
		sizeof(si4703_videodev_template));
	chip->removed = 0;
	chip->users = 0;
	chip->curfreq = FREQ_MIN*FREQ_MUL;
	video_set_drvdata(chip->videodev, chip);
	if (video_register_device(chip->videodev, VFL_TYPE_RADIO, 0)) {
		printk(KERN_ERR "Could not register video device");
		free_irq(chip->irq, chip);
		video_device_release(chip->videodev);
		kfree(chip->videodev);
		kfree(chip);
		disable_oscc_tout_s0();
		return -EIO;
	}

	disable_oscc_tout_s0();
	return 0;
}
示例#27
0
static int cx18_reg_dev(struct cx18 *cx, int type)
{
	struct cx18_stream *s = &cx->streams[type];
	int vfl_type = cx18_stream_info[type].vfl_type;
	const char *name;
	int num, ret;

	if (type == CX18_ENC_STREAM_TYPE_TS && s->dvb != NULL) {
		ret = cx18_dvb_register(s);
		if (ret < 0) {
			CX18_ERR("DVB failed to register\n");
			return ret;
		}
	}

	if (s->video_dev == NULL)
		return 0;

	num = s->video_dev->num;
	/* card number + user defined offset + device offset */
	if (type != CX18_ENC_STREAM_TYPE_MPG) {
		struct cx18_stream *s_mpg = &cx->streams[CX18_ENC_STREAM_TYPE_MPG];

		if (s_mpg->video_dev)
			num = s_mpg->video_dev->num
			    + cx18_stream_info[type].num_offset;
	}
	video_set_drvdata(s->video_dev, s);

	/* Register device. First try the desired minor, then any free one. */
	ret = video_register_device_no_warn(s->video_dev, vfl_type, num);
	if (ret < 0) {
		CX18_ERR("Couldn't register v4l2 device for %s (device node number %d)\n",
			s->name, num);
		video_device_release(s->video_dev);
		s->video_dev = NULL;
		return ret;
	}

	name = video_device_node_name(s->video_dev);

	switch (vfl_type) {
	case VFL_TYPE_GRABBER:
		CX18_INFO("Registered device %s for %s (%d x %d.%02d kB)\n",
			  name, s->name, cx->stream_buffers[type],
			  cx->stream_buf_size[type] / 1024,
			  (cx->stream_buf_size[type] * 100 / 1024) % 100);
		break;

	case VFL_TYPE_RADIO:
		CX18_INFO("Registered device %s for %s\n", name, s->name);
		break;

	case VFL_TYPE_VBI:
		if (cx->stream_buffers[type])
			CX18_INFO("Registered device %s for %s "
				  "(%d x %d bytes)\n",
				  name, s->name, cx->stream_buffers[type],
				  cx->stream_buf_size[type]);
		else
			CX18_INFO("Registered device %s for %s\n",
				name, s->name);
		break;
	}

	return 0;
}
示例#28
0
static int __devinit fimc_probe(struct platform_device *pdev)
{
	struct s3c_platform_fimc *pdata;
	struct fimc_control *ctrl;
	int ret;

	if (!fimc_dev) {
		fimc_dev = kzalloc(sizeof(*fimc_dev), GFP_KERNEL);
		if (!fimc_dev) {
			dev_err(&pdev->dev, "%s: not enough memory\n",
				__func__);
			goto err_fimc;
		}
	}

	ctrl = fimc_register_controller(pdev);
	if (!ctrl) {
		printk(KERN_ERR "%s: cannot register fimc\n", __func__);
		goto err_fimc;
	}

	pdata = to_fimc_plat(&pdev->dev);
	if (pdata->cfg_gpio)
		pdata->cfg_gpio(pdev);

	/* V4L2 device-subdev registration */
	ret = v4l2_device_register(&pdev->dev, &ctrl->v4l2_dev);
	if (ret) {
		fimc_err("%s: v4l2 device register failed\n", __func__);
		goto err_v4l2;
	}

	/* things to initialize once */
	if (!fimc_dev->initialized) {
		ret = fimc_init_global(pdev);
		if (ret)
			goto err_global;
	}

	/* v4l2 subdev configuration */
	ret = fimc_configure_subdev(pdev, ctrl->id);
	if (ret) {
		fimc_err("%s: subdev[%d] registering failed\n",
							__func__, ctrl->id);
	}

	/* video device register */
	ret = video_register_device(ctrl->vd, VFL_TYPE_GRABBER, ctrl->id);
	if (ret) {
		fimc_err("%s: cannot register video driver\n", __func__);
		goto err_global;
	}

	video_set_drvdata(ctrl->vd, ctrl);

	ret = device_create_file(&(pdev->dev), &dev_attr_log_level);
	if (ret < 0)
		fimc_err("failed to add sysfs entries\n");

	fimc_info1("controller %d registered successfully\n", ctrl->id);

	return 0;

err_global:
	clk_disable(ctrl->clk);
	clk_put(ctrl->clk);

err_v4l2:
	fimc_unregister_controller(pdev);

err_fimc:
	return -EINVAL;

}
示例#29
0
/*
 * si470x_usb_driver_probe - probe for the device
 */
static int si470x_usb_driver_probe(struct usb_interface *intf,
		const struct usb_device_id *id)
{
	struct si470x_device *radio;
	struct usb_host_interface *iface_desc;
	struct usb_endpoint_descriptor *endpoint;
	int i, int_end_size, retval = 0;
	unsigned char version_warning = 0;

	/* private data allocation and initialization */
	radio = kzalloc(sizeof(struct si470x_device), GFP_KERNEL);
	if (!radio) {
		retval = -ENOMEM;
		goto err_initial;
	}
	radio->usb_buf = kmalloc(MAX_REPORT_SIZE, GFP_KERNEL);
	if (radio->usb_buf == NULL) {
		retval = -ENOMEM;
		goto err_radio;
	}
	radio->usbdev = interface_to_usbdev(intf);
	radio->intf = intf;
	radio->band = 1; /* Default to 76 - 108 MHz */
	mutex_init(&radio->lock);
	init_completion(&radio->completion);

	iface_desc = intf->cur_altsetting;

	/* Set up interrupt endpoint information. */
	for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
		endpoint = &iface_desc->endpoint[i].desc;
		if (usb_endpoint_is_int_in(endpoint))
			radio->int_in_endpoint = endpoint;
	}
	if (!radio->int_in_endpoint) {
		dev_info(&intf->dev, "could not find interrupt in endpoint\n");
		retval = -EIO;
		goto err_usbbuf;
	}

	int_end_size = le16_to_cpu(radio->int_in_endpoint->wMaxPacketSize);

	radio->int_in_buffer = kmalloc(int_end_size, GFP_KERNEL);
	if (!radio->int_in_buffer) {
		dev_info(&intf->dev, "could not allocate int_in_buffer");
		retval = -ENOMEM;
		goto err_usbbuf;
	}

	radio->int_in_urb = usb_alloc_urb(0, GFP_KERNEL);
	if (!radio->int_in_urb) {
		retval = -ENOMEM;
		goto err_intbuffer;
	}

	radio->v4l2_dev.release = si470x_usb_release;

	/*
	 * The si470x SiLabs reference design uses the same USB IDs as
	 * 'Thanko's Raremono' si4734 based receiver. So check here which we
	 * have: attempt to read the device ID from the si470x: the lower 12
	 * bits should be 0x0242 for the si470x.
	 *
	 * We use this check to determine which device we are dealing with.
	 */
	if (id->idVendor == 0x10c4 && id->idProduct == 0x818a) {
		retval = usb_control_msg(radio->usbdev,
				usb_rcvctrlpipe(radio->usbdev, 0),
				HID_REQ_GET_REPORT,
				USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
				1, 2,
				radio->usb_buf, 3, 500);
		if (retval != 3 ||
		    (get_unaligned_be16(&radio->usb_buf[1]) & 0xfff) != 0x0242) {
			dev_info(&intf->dev, "this is not a si470x device.\n");
			retval = -ENODEV;
			goto err_urb;
		}
	}

	retval = v4l2_device_register(&intf->dev, &radio->v4l2_dev);
	if (retval < 0) {
		dev_err(&intf->dev, "couldn't register v4l2_device\n");
		goto err_urb;
	}

	v4l2_ctrl_handler_init(&radio->hdl, 2);
	v4l2_ctrl_new_std(&radio->hdl, &si470x_ctrl_ops,
			  V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1);
	v4l2_ctrl_new_std(&radio->hdl, &si470x_ctrl_ops,
			  V4L2_CID_AUDIO_VOLUME, 0, 15, 1, 15);
	if (radio->hdl.error) {
		retval = radio->hdl.error;
		dev_err(&intf->dev, "couldn't register control\n");
		goto err_dev;
	}
	radio->videodev = si470x_viddev_template;
	radio->videodev.ctrl_handler = &radio->hdl;
	radio->videodev.lock = &radio->lock;
	radio->videodev.v4l2_dev = &radio->v4l2_dev;
	radio->videodev.release = video_device_release_empty;
	video_set_drvdata(&radio->videodev, radio);

	/* get device and chip versions */
	if (si470x_get_all_registers(radio) < 0) {
		retval = -EIO;
		goto err_ctrl;
	}
	dev_info(&intf->dev, "DeviceID=0x%4.4hx ChipID=0x%4.4hx\n",
			radio->registers[DEVICEID], radio->registers[SI_CHIPID]);
	if ((radio->registers[SI_CHIPID] & SI_CHIPID_FIRMWARE) < RADIO_FW_VERSION) {
		dev_warn(&intf->dev,
			"This driver is known to work with firmware version %hu,\n",
			RADIO_FW_VERSION);
		dev_warn(&intf->dev,
			"but the device has firmware version %hu.\n",
			radio->registers[SI_CHIPID] & SI_CHIPID_FIRMWARE);
		version_warning = 1;
	}

	/* get software and hardware versions */
	if (si470x_get_scratch_page_versions(radio) < 0) {
		retval = -EIO;
		goto err_ctrl;
	}
	dev_info(&intf->dev, "software version %d, hardware version %d\n",
			radio->software_version, radio->hardware_version);
	if (radio->hardware_version < RADIO_HW_VERSION) {
		dev_warn(&intf->dev,
			"This driver is known to work with hardware version %hu,\n",
			RADIO_HW_VERSION);
		dev_warn(&intf->dev,
			"but the device has hardware version %hu.\n",
			radio->hardware_version);
		version_warning = 1;
	}

	/* give out version warning */
	if (version_warning == 1) {
		dev_warn(&intf->dev,
			"If you have some trouble using this driver,\n");
		dev_warn(&intf->dev,
			"please report to V4L ML at [email protected]\n");
	}

	/* set led to connect state */
	si470x_set_led_state(radio, BLINK_GREEN_LED);

	/* rds buffer allocation */
	radio->buf_size = rds_buf * 3;
	radio->buffer = kmalloc(radio->buf_size, GFP_KERNEL);
	if (!radio->buffer) {
		retval = -EIO;
		goto err_ctrl;
	}

	/* rds buffer configuration */
	radio->wr_index = 0;
	radio->rd_index = 0;
	init_waitqueue_head(&radio->read_queue);
	usb_set_intfdata(intf, radio);

	/* start radio */
	retval = si470x_start_usb(radio);
	if (retval < 0)
		goto err_all;

	/* set initial frequency */
	si470x_set_freq(radio, 87.5 * FREQ_MUL); /* available in all regions */

	/* register video device */
	retval = video_register_device(&radio->videodev, VFL_TYPE_RADIO,
			radio_nr);
	if (retval) {
		dev_err(&intf->dev, "Could not register video device\n");
		goto err_all;
	}

	return 0;
err_all:
	kfree(radio->buffer);
err_ctrl:
	v4l2_ctrl_handler_free(&radio->hdl);
err_dev:
	v4l2_device_unregister(&radio->v4l2_dev);
err_urb:
	usb_free_urb(radio->int_in_urb);
err_intbuffer:
	kfree(radio->int_in_buffer);
err_usbbuf:
	kfree(radio->usb_buf);
err_radio:
	kfree(radio);
err_initial:
	return retval;
}
示例#30
0
static int create_pipe(int nr)
{
	int minor_in, minor_out , ret;
		
	if (dev_offset == -1) {
		if (inminor == -1) {
		    minor_in  = -1;
		} else {
		    minor_in  = inminor+nr;
		}
		if (outminor == -1) {
		    minor_out = -1;
		} else {
		    minor_out = outminor+nr;
		}
	} else {
		minor_in  = 2*nr   + dev_offset;
		minor_out = 2*nr+1 + dev_offset;
	}

	/* allocate space for this pipe */
	loops[nr]= kmalloc(sizeof(struct vloopback_pipe), GFP_KERNEL);
	if (!loops[nr])
		return -ENOMEM;
	/* set up a new video device plus our private area */
	loops[nr]->vloopin= video_device_alloc();
	if (loops[nr]->vloopin == NULL)
		return -ENOMEM;
	*loops[nr]->vloopin = vloopback_template;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
	video_set_drvdata(loops[nr]->vloopin,kmalloc(sizeof(struct vloopback_private),GFP_KERNEL));
#else
	loops[nr]->vloopin->priv= kmalloc(sizeof(struct vloopback_private),GFP_KERNEL);
#endif	
	
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
	if ((priv_ptr)video_get_drvdata(loops[nr]->vloopin) == NULL) {
#else
	if (loops[nr]->vloopin->priv == NULL) {
#endif	
		kfree(loops[nr]->vloopin);
		return -ENOMEM;
	}
	/* repeat for the output device */
	loops[nr]->vloopout= video_device_alloc();
	if (loops[nr]->vloopout == NULL) {
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
		kfree((priv_ptr)video_get_drvdata(loops[nr]->vloopin));
#else
		kfree(loops[nr]->vloopin->priv);
#endif	
		kfree(loops[nr]->vloopin);
		return -ENOMEM;
	}
	*loops[nr]->vloopout = vloopback_template;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
	video_set_drvdata(loops[nr]->vloopout,kmalloc(sizeof(struct vloopback_private),GFP_KERNEL));
#else
	loops[nr]->vloopout->priv= kmalloc(sizeof(struct vloopback_private),GFP_KERNEL);
#endif	

	if ((priv_ptr)video_get_drvdata(loops[nr]->vloopout) == NULL) {
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
		kfree((priv_ptr)video_get_drvdata(loops[nr]->vloopin));
#else
		kfree(loops[nr]->vloopin->priv);
#endif	
		kfree(loops[nr]->vloopin);
		kfree(loops[nr]->vloopout);
		return -ENOMEM;
	}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
	((priv_ptr)video_get_drvdata(loops[nr]->vloopin))->pipenr=nr;
	((priv_ptr)video_get_drvdata(loops[nr]->vloopout))->pipenr=nr;
#else
	((priv_ptr)loops[nr]->vloopin->priv)->pipenr=nr;
	((priv_ptr)loops[nr]->vloopout->priv)->pipenr=nr;
#endif	

	loops[nr]->invalid_ioctl = 0; /* tibit */
	loops[nr]->buffer=NULL;
	loops[nr]->width=0;
	loops[nr]->height=0;
	loops[nr]->palette=0;
	loops[nr]->frameswrite=0;
	loops[nr]->framesread=0;
	loops[nr]->framesdumped=0;
	loops[nr]->wopen=0;
	loops[nr]->ropen=0;
	loops[nr]->frame=0;
	loops[nr]->pendingread=0;
	
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
	((priv_ptr)video_get_drvdata(loops[nr]->vloopin))->in=1;
	((priv_ptr)video_get_drvdata(loops[nr]->vloopout))->in=0;
#else
	((priv_ptr)loops[nr]->vloopin->priv)->in=1;
	((priv_ptr)loops[nr]->vloopout->priv)->in=0;
#endif	
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
	loops[nr]->vloopin->type=0;
#endif
	sprintf(loops[nr]->vloopin->name, "Video loopback %d input", nr);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
	loops[nr]->vloopout->type=VID_TYPE_CAPTURE;
#endif
	sprintf(loops[nr]->vloopout->name, "Video loopback %d output", nr);
	init_waitqueue_head(&loops[nr]->wait);
	init_MUTEX(&loops[nr]->lock);
	
	ret = video_register_device(loops[nr]->vloopout, VFL_TYPE_GRABBER, minor_out);
	
	if ((ret ==-1) || (ret == -23)) {
		info("error registering device %s", loops[nr]->vloopout->name);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
		kfree(((priv_ptr)video_get_drvdata(loops[nr]->vloopin)));
		video_unregister_device(loops[nr]->vloopin);
		kfree(((priv_ptr)video_get_drvdata(loops[nr]->vloopout)));
#else
		kfree(loops[nr]->vloopin->priv);
		video_unregister_device(loops[nr]->vloopin);
		kfree(loops[nr]->vloopout->priv);
#endif	
		kfree(loops[nr]->vloopout);
		kfree(loops[nr]);
		loops[nr]=NULL;
		return ret;
	}
	
	ret = video_register_device(loops[nr]->vloopin, VFL_TYPE_GRABBER, minor_in);

	if ((ret == -1 ) || ( ret == -23 )) {
		info("error registering device %s",loops[nr]->vloopin->name);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
		kfree(((priv_ptr)video_get_drvdata(loops[nr]->vloopin)));
		kfree(((priv_ptr)video_get_drvdata(loops[nr]->vloopout)));
#else
		kfree(loops[nr]->vloopin->priv);
		kfree(loops[nr]->vloopout->priv);
#endif	

		kfree(loops[nr]->vloopin);
		kfree(loops[nr]->vloopout);
		kfree(loops[nr]);
		loops[nr]=NULL;
		return ret;
	}
	
	loops[nr]->ioctldata=kmalloc(1024, GFP_KERNEL);
	loops[nr]->ioctlretdata=kmalloc(1024, GFP_KERNEL);
	return 0;
}


/****************************************************************************
 *	init stuff
 ****************************************************************************/


MODULE_AUTHOR("J.B. Vreeken ([email protected])");
MODULE_DESCRIPTION("Video4linux loopback device.");

#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
module_param(pipes, int, 000);
#else
MODULE_PARM(pipes, "i");
#endif

MODULE_PARM_DESC(pipes, "Nr of pipes to create (each pipe uses two video devices)");

#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
module_param(spares, int, 000);
#else
MODULE_PARM(spares, "i");
#endif

MODULE_PARM_DESC(spares, "Nr of spare pipes that should be created");

#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
module_param(dev_offset, int, 000);
#else
MODULE_PARM(dev_offset_param, "i");
#endif

#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
module_param(inminor, int, 000);
#else
MODULE_PARM(inminor, "i");
#endif

#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
module_param(outminor, int, 000);
#else
MODULE_PARM(outminor, "i");
#endif

MODULE_PARM_DESC(dev_offset, "Prefered offset for video device numbers");
MODULE_LICENSE("GPL");
MODULE_VERSION( VLOOPBACK_VERSION );

static int __init vloopback_init(void)
{
	int i,ret;

	info("Video4linux loopback driver v"VLOOPBACK_VERSION);

	if (pipes==-1) pipes=1;
	if (pipes > MAX_PIPES) {
		pipes=MAX_PIPES;
		info("Nr of pipes is limited to: %d", MAX_PIPES);
	}

	for (i=0; i<pipes; i++) {
		
		ret = create_pipe(i);

		if (ret == 0) {
			info("Loopback %d registered, input: video%d, output: video%d",
			     i, loops[i]->vloopin->minor,
			     loops[i]->vloopout->minor);
			nr_o_pipes=i+1;
		}else{
			return ret;
		}
	}
	return 0;
}