参照元†
- struct pci_dev *pdev
- const struct pci_device_id *ent
返り値†
/*
* The initial setup of this device instance. Note that the initial state of
* the driver should be complete. So the initial format, standard, timings
* and video input should all be initialized to some reasonable value.
*/
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)
return -ENOMEM;
/* 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->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;
skel->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
if (IS_ERR(skel->alloc_ctx)) {
dev_err(&pdev->dev, "Can't allocate buffer context");
ret = PTR_ERR(skel->alloc_ctx);
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,
/*
* 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_GRABBER, -1);
if (ret)
goto free_ctx;
dev_info(&pdev->dev, "V4L2 PCI Skeleton Driver loaded\n");
return 0;
free_ctx:
vb2_dma_contig_cleanup_ctx(skel->alloc_ctx);
free_hdl:
v4l2_ctrl_handler_free(&skel->ctrl_handler);
v4l2_device_unregister(&skel->v4l2_dev);
disable_pci:
pci_disable_device(pdev);
return ret;
}
コメント†