static int skeleton_probe()

in v4l/v4l2-pci-skeleton.c [754:895]


static int skeleton_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
	/* The initial timings are chosen to be 720p60. */
	static const struct v4l2_dv_timings timings_def =
		V4L2_DV_BT_CEA_1280X720P60;
	struct skeleton *skel;
	struct video_device *vdev;
	struct v4l2_ctrl_handler *hdl;
	struct vb2_queue *q;
	int ret;

	/* Enable PCI */
	ret = pci_enable_device(pdev);
	if (ret)
		return ret;
	ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
	if (ret) {
		dev_err(&pdev->dev, "no suitable DMA available.\n");
		goto disable_pci;
	}

	/* Allocate a new instance */
	skel = devm_kzalloc(&pdev->dev, sizeof(struct skeleton), GFP_KERNEL);
	if (!skel) {
		ret = -ENOMEM;
		goto disable_pci;
	}

	/* Allocate the interrupt */
	ret = devm_request_irq(&pdev->dev, pdev->irq,
			       skeleton_irq, 0, KBUILD_MODNAME, skel);
	if (ret) {
		dev_err(&pdev->dev, "request_irq failed\n");
		goto disable_pci;
	}
	skel->pdev = pdev;

	/* Fill in the initial format-related settings */
	skel->timings = timings_def;
	skel->std = V4L2_STD_625_50;
	skeleton_fill_pix_format(skel, &skel->format);

	/* Initialize the top-level structure */
	ret = v4l2_device_register(&pdev->dev, &skel->v4l2_dev);
	if (ret)
		goto disable_pci;

	mutex_init(&skel->lock);

	/* Add the controls */
	hdl = &skel->ctrl_handler;
	v4l2_ctrl_handler_init(hdl, 4);
	v4l2_ctrl_new_std(hdl, &skel_ctrl_ops,
			  V4L2_CID_BRIGHTNESS, 0, 255, 1, 127);
	v4l2_ctrl_new_std(hdl, &skel_ctrl_ops,
			  V4L2_CID_CONTRAST, 0, 255, 1, 16);
	v4l2_ctrl_new_std(hdl, &skel_ctrl_ops,
			  V4L2_CID_SATURATION, 0, 255, 1, 127);
	v4l2_ctrl_new_std(hdl, &skel_ctrl_ops,
			  V4L2_CID_HUE, -128, 127, 1, 0);
	if (hdl->error) {
		ret = hdl->error;
		goto free_hdl;
	}
	skel->v4l2_dev.ctrl_handler = hdl;

	/* Initialize the vb2 queue */
	q = &skel->queue;
	q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
	q->io_modes = VB2_MMAP | VB2_DMABUF | VB2_READ;
	q->dev = &pdev->dev;
	q->drv_priv = skel;
	q->buf_struct_size = sizeof(struct skel_buffer);
	q->ops = &skel_qops;
	q->mem_ops = &vb2_dma_contig_memops;
	q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
	/*
	 * Assume that this DMA engine needs to have at least two buffers
	 * available before it can be started. The start_streaming() op
	 * won't be called until at least this many buffers are queued up.
	 */
	q->min_buffers_needed = 2;
	/*
	 * The serialization lock for the streaming ioctls. This is the same
	 * as the main serialization lock, but if some of the non-streaming
	 * ioctls could take a long time to execute, then you might want to
	 * have a different lock here to prevent VIDIOC_DQBUF from being
	 * blocked while waiting for another action to finish. This is
	 * generally not needed for PCI devices, but USB devices usually do
	 * want a separate lock here.
	 */
	q->lock = &skel->lock;
	/*
	 * Since this driver can only do 32-bit DMA we must make sure that
	 * the vb2 core will allocate the buffers in 32-bit DMA memory.
	 */
	q->gfp_flags = GFP_DMA32;
	ret = vb2_queue_init(q);
	if (ret)
		goto free_hdl;

	INIT_LIST_HEAD(&skel->buf_list);
	spin_lock_init(&skel->qlock);

	/* Initialize the video_device structure */
	vdev = &skel->vdev;
	strlcpy(vdev->name, KBUILD_MODNAME, sizeof(vdev->name));
	/*
	 * There is nothing to clean up, so release is set to an empty release
	 * function. The release callback must be non-NULL.
	 */
	vdev->release = video_device_release_empty;
	vdev->fops = &skel_fops,
	vdev->ioctl_ops = &skel_ioctl_ops,
	vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
			    V4L2_CAP_STREAMING;
	/*
	 * The main serialization lock. All ioctls are serialized by this
	 * lock. Exception: if q->lock is set, then the streaming ioctls
	 * are serialized by that separate lock.
	 */
	vdev->lock = &skel->lock;
	vdev->queue = q;
	vdev->v4l2_dev = &skel->v4l2_dev;
	/* Supported SDTV standards, if any */
	vdev->tvnorms = SKEL_TVNORMS;
	video_set_drvdata(vdev, skel);

	ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
	if (ret)
		goto free_hdl;

	dev_info(&pdev->dev, "V4L2 PCI Skeleton Driver loaded\n");
	return 0;

free_hdl:
	v4l2_ctrl_handler_free(&skel->ctrl_handler);
	v4l2_device_unregister(&skel->v4l2_dev);
disable_pci:
	pci_disable_device(pdev);
	return ret;
}