1*dfb99b05SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 20185f850SArnd Bergmann /* 30185f850SArnd Bergmann * This is a V4L2 PCI Skeleton Driver. It gives an initial skeleton source 40185f850SArnd Bergmann * for use with other PCI drivers. 50185f850SArnd Bergmann * 60185f850SArnd Bergmann * This skeleton PCI driver assumes that the card has an S-Video connector as 70185f850SArnd Bergmann * input 0 and an HDMI connector as input 1. 80185f850SArnd Bergmann * 90185f850SArnd Bergmann * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved. 100185f850SArnd Bergmann */ 110185f850SArnd Bergmann 120185f850SArnd Bergmann #include <linux/types.h> 130185f850SArnd Bergmann #include <linux/kernel.h> 140185f850SArnd Bergmann #include <linux/module.h> 150185f850SArnd Bergmann #include <linux/init.h> 160185f850SArnd Bergmann #include <linux/kmod.h> 170185f850SArnd Bergmann #include <linux/mutex.h> 180185f850SArnd Bergmann #include <linux/pci.h> 190185f850SArnd Bergmann #include <linux/interrupt.h> 200185f850SArnd Bergmann #include <linux/videodev2.h> 210185f850SArnd Bergmann #include <linux/v4l2-dv-timings.h> 220185f850SArnd Bergmann #include <media/v4l2-device.h> 230185f850SArnd Bergmann #include <media/v4l2-dev.h> 240185f850SArnd Bergmann #include <media/v4l2-ioctl.h> 250185f850SArnd Bergmann #include <media/v4l2-dv-timings.h> 260185f850SArnd Bergmann #include <media/v4l2-ctrls.h> 270185f850SArnd Bergmann #include <media/v4l2-event.h> 280185f850SArnd Bergmann #include <media/videobuf2-v4l2.h> 290185f850SArnd Bergmann #include <media/videobuf2-dma-contig.h> 300185f850SArnd Bergmann 310185f850SArnd Bergmann MODULE_DESCRIPTION("V4L2 PCI Skeleton Driver"); 320185f850SArnd Bergmann MODULE_AUTHOR("Hans Verkuil"); 330185f850SArnd Bergmann MODULE_LICENSE("GPL v2"); 340185f850SArnd Bergmann 350185f850SArnd Bergmann /** 360185f850SArnd Bergmann * struct skeleton - All internal data for one instance of device 370185f850SArnd Bergmann * @pdev: PCI device 380185f850SArnd Bergmann * @v4l2_dev: top-level v4l2 device struct 390185f850SArnd Bergmann * @vdev: video node structure 400185f850SArnd Bergmann * @ctrl_handler: control handler structure 410185f850SArnd Bergmann * @lock: ioctl serialization mutex 420185f850SArnd Bergmann * @std: current SDTV standard 430185f850SArnd Bergmann * @timings: current HDTV timings 440185f850SArnd Bergmann * @format: current pix format 450185f850SArnd Bergmann * @input: current video input (0 = SDTV, 1 = HDTV) 460185f850SArnd Bergmann * @queue: vb2 video capture queue 470185f850SArnd Bergmann * @qlock: spinlock controlling access to buf_list and sequence 480185f850SArnd Bergmann * @buf_list: list of buffers queued for DMA 499bec226dSHans Verkuil * @field: the field (TOP/BOTTOM/other) of the current buffer 500185f850SArnd Bergmann * @sequence: frame sequence counter 510185f850SArnd Bergmann */ 520185f850SArnd Bergmann struct skeleton { 530185f850SArnd Bergmann struct pci_dev *pdev; 540185f850SArnd Bergmann struct v4l2_device v4l2_dev; 550185f850SArnd Bergmann struct video_device vdev; 560185f850SArnd Bergmann struct v4l2_ctrl_handler ctrl_handler; 570185f850SArnd Bergmann struct mutex lock; 580185f850SArnd Bergmann v4l2_std_id std; 590185f850SArnd Bergmann struct v4l2_dv_timings timings; 600185f850SArnd Bergmann struct v4l2_pix_format format; 610185f850SArnd Bergmann unsigned input; 620185f850SArnd Bergmann 630185f850SArnd Bergmann struct vb2_queue queue; 640185f850SArnd Bergmann 650185f850SArnd Bergmann spinlock_t qlock; 660185f850SArnd Bergmann struct list_head buf_list; 670185f850SArnd Bergmann unsigned field; 680185f850SArnd Bergmann unsigned sequence; 690185f850SArnd Bergmann }; 700185f850SArnd Bergmann 710185f850SArnd Bergmann struct skel_buffer { 72b52b88ceSMichael Tretter struct vb2_v4l2_buffer vb; 730185f850SArnd Bergmann struct list_head list; 740185f850SArnd Bergmann }; 750185f850SArnd Bergmann 76b52b88ceSMichael Tretter static inline struct skel_buffer *to_skel_buffer(struct vb2_v4l2_buffer *vbuf) 770185f850SArnd Bergmann { 78b52b88ceSMichael Tretter return container_of(vbuf, struct skel_buffer, vb); 790185f850SArnd Bergmann } 800185f850SArnd Bergmann 810185f850SArnd Bergmann static const struct pci_device_id skeleton_pci_tbl[] = { 820185f850SArnd Bergmann /* { PCI_DEVICE(PCI_VENDOR_ID_, PCI_DEVICE_ID_) }, */ 830185f850SArnd Bergmann { 0, } 840185f850SArnd Bergmann }; 850185f850SArnd Bergmann MODULE_DEVICE_TABLE(pci, skeleton_pci_tbl); 860185f850SArnd Bergmann 870185f850SArnd Bergmann /* 880185f850SArnd Bergmann * HDTV: this structure has the capabilities of the HDTV receiver. 890185f850SArnd Bergmann * It is used to constrain the huge list of possible formats based 900185f850SArnd Bergmann * upon the hardware capabilities. 910185f850SArnd Bergmann */ 920185f850SArnd Bergmann static const struct v4l2_dv_timings_cap skel_timings_cap = { 930185f850SArnd Bergmann .type = V4L2_DV_BT_656_1120, 940185f850SArnd Bergmann /* keep this initialization for compatibility with GCC < 4.4.6 */ 950185f850SArnd Bergmann .reserved = { 0 }, 960185f850SArnd Bergmann V4L2_INIT_BT_TIMINGS( 970185f850SArnd Bergmann 720, 1920, /* min/max width */ 980185f850SArnd Bergmann 480, 1080, /* min/max height */ 990185f850SArnd Bergmann 27000000, 74250000, /* min/max pixelclock*/ 1000185f850SArnd Bergmann V4L2_DV_BT_STD_CEA861, /* Supported standards */ 1010185f850SArnd Bergmann /* capabilities */ 1020185f850SArnd Bergmann V4L2_DV_BT_CAP_INTERLACED | V4L2_DV_BT_CAP_PROGRESSIVE 1030185f850SArnd Bergmann ) 1040185f850SArnd Bergmann }; 1050185f850SArnd Bergmann 1060185f850SArnd Bergmann /* 1070185f850SArnd Bergmann * Supported SDTV standards. This does the same job as skel_timings_cap, but 1080185f850SArnd Bergmann * for standard TV formats. 1090185f850SArnd Bergmann */ 1100185f850SArnd Bergmann #define SKEL_TVNORMS V4L2_STD_ALL 1110185f850SArnd Bergmann 1120185f850SArnd Bergmann /* 1130185f850SArnd Bergmann * Interrupt handler: typically interrupts happen after a new frame has been 1140185f850SArnd Bergmann * captured. It is the job of the handler to remove the new frame from the 1150185f850SArnd Bergmann * internal list and give it back to the vb2 framework, updating the sequence 1160185f850SArnd Bergmann * counter, field and timestamp at the same time. 1170185f850SArnd Bergmann */ 1180185f850SArnd Bergmann static irqreturn_t skeleton_irq(int irq, void *dev_id) 1190185f850SArnd Bergmann { 1200185f850SArnd Bergmann #ifdef TODO 1210185f850SArnd Bergmann struct skeleton *skel = dev_id; 1220185f850SArnd Bergmann 1230185f850SArnd Bergmann /* handle interrupt */ 1240185f850SArnd Bergmann 1250185f850SArnd Bergmann /* Once a new frame has been captured, mark it as done like this: */ 1260185f850SArnd Bergmann if (captured_new_frame) { 1270185f850SArnd Bergmann ... 1280185f850SArnd Bergmann spin_lock(&skel->qlock); 1290185f850SArnd Bergmann list_del(&new_buf->list); 1300185f850SArnd Bergmann spin_unlock(&skel->qlock); 13160b65279SHans Verkuil new_buf->vb.vb2_buf.timestamp = ktime_get_ns(); 13260b65279SHans Verkuil new_buf->vb.sequence = skel->sequence++; 13360b65279SHans Verkuil new_buf->vb.field = skel->field; 1340185f850SArnd Bergmann if (skel->format.field == V4L2_FIELD_ALTERNATE) { 1350185f850SArnd Bergmann if (skel->field == V4L2_FIELD_BOTTOM) 1360185f850SArnd Bergmann skel->field = V4L2_FIELD_TOP; 1370185f850SArnd Bergmann else if (skel->field == V4L2_FIELD_TOP) 1380185f850SArnd Bergmann skel->field = V4L2_FIELD_BOTTOM; 1390185f850SArnd Bergmann } 14060b65279SHans Verkuil vb2_buffer_done(&new_buf->vb.vb2_buf, VB2_BUF_STATE_DONE); 1410185f850SArnd Bergmann } 1420185f850SArnd Bergmann #endif 1430185f850SArnd Bergmann return IRQ_HANDLED; 1440185f850SArnd Bergmann } 1450185f850SArnd Bergmann 1460185f850SArnd Bergmann /* 1470185f850SArnd Bergmann * Setup the constraints of the queue: besides setting the number of planes 1480185f850SArnd Bergmann * per buffer and the size and allocation context of each plane, it also 1490185f850SArnd Bergmann * checks if sufficient buffers have been allocated. Usually 3 is a good 1500185f850SArnd Bergmann * minimum number: many DMA engines need a minimum of 2 buffers in the 1510185f850SArnd Bergmann * queue and you need to have another available for userspace processing. 1520185f850SArnd Bergmann */ 1530185f850SArnd Bergmann static int queue_setup(struct vb2_queue *vq, 1540185f850SArnd Bergmann unsigned int *nbuffers, unsigned int *nplanes, 15536c0f8b3SHans Verkuil unsigned int sizes[], struct device *alloc_devs[]) 1560185f850SArnd Bergmann { 1570185f850SArnd Bergmann struct skeleton *skel = vb2_get_drv_priv(vq); 1580185f850SArnd Bergmann 1590185f850SArnd Bergmann skel->field = skel->format.field; 1600185f850SArnd Bergmann if (skel->field == V4L2_FIELD_ALTERNATE) { 1610185f850SArnd Bergmann /* 1620185f850SArnd Bergmann * You cannot use read() with FIELD_ALTERNATE since the field 1630185f850SArnd Bergmann * information (TOP/BOTTOM) cannot be passed back to the user. 1640185f850SArnd Bergmann */ 1650185f850SArnd Bergmann if (vb2_fileio_is_active(vq)) 1660185f850SArnd Bergmann return -EINVAL; 1670185f850SArnd Bergmann skel->field = V4L2_FIELD_TOP; 1680185f850SArnd Bergmann } 1690185f850SArnd Bergmann 1700185f850SArnd Bergmann if (vq->num_buffers + *nbuffers < 3) 1710185f850SArnd Bergmann *nbuffers = 3 - vq->num_buffers; 1720185f850SArnd Bergmann 1730185f850SArnd Bergmann if (*nplanes) 1740185f850SArnd Bergmann return sizes[0] < skel->format.sizeimage ? -EINVAL : 0; 1750185f850SArnd Bergmann *nplanes = 1; 1760185f850SArnd Bergmann sizes[0] = skel->format.sizeimage; 1770185f850SArnd Bergmann return 0; 1780185f850SArnd Bergmann } 1790185f850SArnd Bergmann 1800185f850SArnd Bergmann /* 1810185f850SArnd Bergmann * Prepare the buffer for queueing to the DMA engine: check and set the 1820185f850SArnd Bergmann * payload size. 1830185f850SArnd Bergmann */ 1840185f850SArnd Bergmann static int buffer_prepare(struct vb2_buffer *vb) 1850185f850SArnd Bergmann { 1860185f850SArnd Bergmann struct skeleton *skel = vb2_get_drv_priv(vb->vb2_queue); 1870185f850SArnd Bergmann unsigned long size = skel->format.sizeimage; 1880185f850SArnd Bergmann 1890185f850SArnd Bergmann if (vb2_plane_size(vb, 0) < size) { 1900185f850SArnd Bergmann dev_err(&skel->pdev->dev, "buffer too small (%lu < %lu)\n", 1910185f850SArnd Bergmann vb2_plane_size(vb, 0), size); 1920185f850SArnd Bergmann return -EINVAL; 1930185f850SArnd Bergmann } 1940185f850SArnd Bergmann 1950185f850SArnd Bergmann vb2_set_plane_payload(vb, 0, size); 1960185f850SArnd Bergmann return 0; 1970185f850SArnd Bergmann } 1980185f850SArnd Bergmann 1990185f850SArnd Bergmann /* 2000185f850SArnd Bergmann * Queue this buffer to the DMA engine. 2010185f850SArnd Bergmann */ 2020185f850SArnd Bergmann static void buffer_queue(struct vb2_buffer *vb) 2030185f850SArnd Bergmann { 204b52b88ceSMichael Tretter struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 2050185f850SArnd Bergmann struct skeleton *skel = vb2_get_drv_priv(vb->vb2_queue); 206b52b88ceSMichael Tretter struct skel_buffer *buf = to_skel_buffer(vbuf); 2070185f850SArnd Bergmann unsigned long flags; 2080185f850SArnd Bergmann 2090185f850SArnd Bergmann spin_lock_irqsave(&skel->qlock, flags); 2100185f850SArnd Bergmann list_add_tail(&buf->list, &skel->buf_list); 2110185f850SArnd Bergmann 2120185f850SArnd Bergmann /* TODO: Update any DMA pointers if necessary */ 2130185f850SArnd Bergmann 2140185f850SArnd Bergmann spin_unlock_irqrestore(&skel->qlock, flags); 2150185f850SArnd Bergmann } 2160185f850SArnd Bergmann 2170185f850SArnd Bergmann static void return_all_buffers(struct skeleton *skel, 2180185f850SArnd Bergmann enum vb2_buffer_state state) 2190185f850SArnd Bergmann { 2200185f850SArnd Bergmann struct skel_buffer *buf, *node; 2210185f850SArnd Bergmann unsigned long flags; 2220185f850SArnd Bergmann 2230185f850SArnd Bergmann spin_lock_irqsave(&skel->qlock, flags); 2240185f850SArnd Bergmann list_for_each_entry_safe(buf, node, &skel->buf_list, list) { 225b52b88ceSMichael Tretter vb2_buffer_done(&buf->vb.vb2_buf, state); 2260185f850SArnd Bergmann list_del(&buf->list); 2270185f850SArnd Bergmann } 2280185f850SArnd Bergmann spin_unlock_irqrestore(&skel->qlock, flags); 2290185f850SArnd Bergmann } 2300185f850SArnd Bergmann 2310185f850SArnd Bergmann /* 2320185f850SArnd Bergmann * Start streaming. First check if the minimum number of buffers have been 2330185f850SArnd Bergmann * queued. If not, then return -ENOBUFS and the vb2 framework will call 2340185f850SArnd Bergmann * this function again the next time a buffer has been queued until enough 2350185f850SArnd Bergmann * buffers are available to actually start the DMA engine. 2360185f850SArnd Bergmann */ 2370185f850SArnd Bergmann static int start_streaming(struct vb2_queue *vq, unsigned int count) 2380185f850SArnd Bergmann { 2390185f850SArnd Bergmann struct skeleton *skel = vb2_get_drv_priv(vq); 2400185f850SArnd Bergmann int ret = 0; 2410185f850SArnd Bergmann 2420185f850SArnd Bergmann skel->sequence = 0; 2430185f850SArnd Bergmann 2440185f850SArnd Bergmann /* TODO: start DMA */ 2450185f850SArnd Bergmann 2460185f850SArnd Bergmann if (ret) { 2470185f850SArnd Bergmann /* 2480185f850SArnd Bergmann * In case of an error, return all active buffers to the 2490185f850SArnd Bergmann * QUEUED state 2500185f850SArnd Bergmann */ 2510185f850SArnd Bergmann return_all_buffers(skel, VB2_BUF_STATE_QUEUED); 2520185f850SArnd Bergmann } 2530185f850SArnd Bergmann return ret; 2540185f850SArnd Bergmann } 2550185f850SArnd Bergmann 2560185f850SArnd Bergmann /* 2570185f850SArnd Bergmann * Stop the DMA engine. Any remaining buffers in the DMA queue are dequeued 2580185f850SArnd Bergmann * and passed on to the vb2 framework marked as STATE_ERROR. 2590185f850SArnd Bergmann */ 2600185f850SArnd Bergmann static void stop_streaming(struct vb2_queue *vq) 2610185f850SArnd Bergmann { 2620185f850SArnd Bergmann struct skeleton *skel = vb2_get_drv_priv(vq); 2630185f850SArnd Bergmann 2640185f850SArnd Bergmann /* TODO: stop DMA */ 2650185f850SArnd Bergmann 2660185f850SArnd Bergmann /* Release all active buffers */ 2670185f850SArnd Bergmann return_all_buffers(skel, VB2_BUF_STATE_ERROR); 2680185f850SArnd Bergmann } 2690185f850SArnd Bergmann 2700185f850SArnd Bergmann /* 2710185f850SArnd Bergmann * The vb2 queue ops. Note that since q->lock is set we can use the standard 2720185f850SArnd Bergmann * vb2_ops_wait_prepare/finish helper functions. If q->lock would be NULL, 2730185f850SArnd Bergmann * then this driver would have to provide these ops. 2740185f850SArnd Bergmann */ 275aa7d01fdSJulia Lawall static const struct vb2_ops skel_qops = { 2760185f850SArnd Bergmann .queue_setup = queue_setup, 2770185f850SArnd Bergmann .buf_prepare = buffer_prepare, 2780185f850SArnd Bergmann .buf_queue = buffer_queue, 2790185f850SArnd Bergmann .start_streaming = start_streaming, 2800185f850SArnd Bergmann .stop_streaming = stop_streaming, 2810185f850SArnd Bergmann .wait_prepare = vb2_ops_wait_prepare, 2820185f850SArnd Bergmann .wait_finish = vb2_ops_wait_finish, 2830185f850SArnd Bergmann }; 2840185f850SArnd Bergmann 2850185f850SArnd Bergmann /* 2860185f850SArnd Bergmann * Required ioctl querycap. Note that the version field is prefilled with 2870185f850SArnd Bergmann * the version of the kernel. 2880185f850SArnd Bergmann */ 2890185f850SArnd Bergmann static int skeleton_querycap(struct file *file, void *priv, 2900185f850SArnd Bergmann struct v4l2_capability *cap) 2910185f850SArnd Bergmann { 2920185f850SArnd Bergmann struct skeleton *skel = video_drvdata(file); 2930185f850SArnd Bergmann 2940185f850SArnd Bergmann strlcpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver)); 2950185f850SArnd Bergmann strlcpy(cap->card, "V4L2 PCI Skeleton", sizeof(cap->card)); 2960185f850SArnd Bergmann snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s", 2970185f850SArnd Bergmann pci_name(skel->pdev)); 2980185f850SArnd Bergmann return 0; 2990185f850SArnd Bergmann } 3000185f850SArnd Bergmann 3010185f850SArnd Bergmann /* 3020185f850SArnd Bergmann * Helper function to check and correct struct v4l2_pix_format. It's used 3030185f850SArnd Bergmann * not only in VIDIOC_TRY/S_FMT, but also elsewhere if changes to the SDTV 3040185f850SArnd Bergmann * standard, HDTV timings or the video input would require updating the 3050185f850SArnd Bergmann * current format. 3060185f850SArnd Bergmann */ 3070185f850SArnd Bergmann static void skeleton_fill_pix_format(struct skeleton *skel, 3080185f850SArnd Bergmann struct v4l2_pix_format *pix) 3090185f850SArnd Bergmann { 3100185f850SArnd Bergmann pix->pixelformat = V4L2_PIX_FMT_YUYV; 3110185f850SArnd Bergmann if (skel->input == 0) { 3120185f850SArnd Bergmann /* S-Video input */ 3130185f850SArnd Bergmann pix->width = 720; 3140185f850SArnd Bergmann pix->height = (skel->std & V4L2_STD_525_60) ? 480 : 576; 3150185f850SArnd Bergmann pix->field = V4L2_FIELD_INTERLACED; 3160185f850SArnd Bergmann pix->colorspace = V4L2_COLORSPACE_SMPTE170M; 3170185f850SArnd Bergmann } else { 3180185f850SArnd Bergmann /* HDMI input */ 3190185f850SArnd Bergmann pix->width = skel->timings.bt.width; 3200185f850SArnd Bergmann pix->height = skel->timings.bt.height; 3210185f850SArnd Bergmann if (skel->timings.bt.interlaced) { 3220185f850SArnd Bergmann pix->field = V4L2_FIELD_ALTERNATE; 3230185f850SArnd Bergmann pix->height /= 2; 3240185f850SArnd Bergmann } else { 3250185f850SArnd Bergmann pix->field = V4L2_FIELD_NONE; 3260185f850SArnd Bergmann } 3270185f850SArnd Bergmann pix->colorspace = V4L2_COLORSPACE_REC709; 3280185f850SArnd Bergmann } 3290185f850SArnd Bergmann 3300185f850SArnd Bergmann /* 3310185f850SArnd Bergmann * The YUYV format is four bytes for every two pixels, so bytesperline 3320185f850SArnd Bergmann * is width * 2. 3330185f850SArnd Bergmann */ 3340185f850SArnd Bergmann pix->bytesperline = pix->width * 2; 3350185f850SArnd Bergmann pix->sizeimage = pix->bytesperline * pix->height; 3360185f850SArnd Bergmann pix->priv = 0; 3370185f850SArnd Bergmann } 3380185f850SArnd Bergmann 3390185f850SArnd Bergmann static int skeleton_try_fmt_vid_cap(struct file *file, void *priv, 3400185f850SArnd Bergmann struct v4l2_format *f) 3410185f850SArnd Bergmann { 3420185f850SArnd Bergmann struct skeleton *skel = video_drvdata(file); 3430185f850SArnd Bergmann struct v4l2_pix_format *pix = &f->fmt.pix; 3440185f850SArnd Bergmann 3450185f850SArnd Bergmann /* 3460185f850SArnd Bergmann * Due to historical reasons providing try_fmt with an unsupported 3470185f850SArnd Bergmann * pixelformat will return -EINVAL for video receivers. Webcam drivers, 3480185f850SArnd Bergmann * however, will silently correct the pixelformat. Some video capture 3490185f850SArnd Bergmann * applications rely on this behavior... 3500185f850SArnd Bergmann */ 3510185f850SArnd Bergmann if (pix->pixelformat != V4L2_PIX_FMT_YUYV) 3520185f850SArnd Bergmann return -EINVAL; 3530185f850SArnd Bergmann skeleton_fill_pix_format(skel, pix); 3540185f850SArnd Bergmann return 0; 3550185f850SArnd Bergmann } 3560185f850SArnd Bergmann 3570185f850SArnd Bergmann static int skeleton_s_fmt_vid_cap(struct file *file, void *priv, 3580185f850SArnd Bergmann struct v4l2_format *f) 3590185f850SArnd Bergmann { 3600185f850SArnd Bergmann struct skeleton *skel = video_drvdata(file); 3610185f850SArnd Bergmann int ret; 3620185f850SArnd Bergmann 3630185f850SArnd Bergmann ret = skeleton_try_fmt_vid_cap(file, priv, f); 3640185f850SArnd Bergmann if (ret) 3650185f850SArnd Bergmann return ret; 3660185f850SArnd Bergmann 3670185f850SArnd Bergmann /* 3680185f850SArnd Bergmann * It is not allowed to change the format while buffers for use with 3690185f850SArnd Bergmann * streaming have already been allocated. 3700185f850SArnd Bergmann */ 3710185f850SArnd Bergmann if (vb2_is_busy(&skel->queue)) 3720185f850SArnd Bergmann return -EBUSY; 3730185f850SArnd Bergmann 3740185f850SArnd Bergmann /* TODO: change format */ 3750185f850SArnd Bergmann skel->format = f->fmt.pix; 3760185f850SArnd Bergmann return 0; 3770185f850SArnd Bergmann } 3780185f850SArnd Bergmann 3790185f850SArnd Bergmann static int skeleton_g_fmt_vid_cap(struct file *file, void *priv, 3800185f850SArnd Bergmann struct v4l2_format *f) 3810185f850SArnd Bergmann { 3820185f850SArnd Bergmann struct skeleton *skel = video_drvdata(file); 3830185f850SArnd Bergmann 3840185f850SArnd Bergmann f->fmt.pix = skel->format; 3850185f850SArnd Bergmann return 0; 3860185f850SArnd Bergmann } 3870185f850SArnd Bergmann 3880185f850SArnd Bergmann static int skeleton_enum_fmt_vid_cap(struct file *file, void *priv, 3890185f850SArnd Bergmann struct v4l2_fmtdesc *f) 3900185f850SArnd Bergmann { 3910185f850SArnd Bergmann if (f->index != 0) 3920185f850SArnd Bergmann return -EINVAL; 3930185f850SArnd Bergmann 3940185f850SArnd Bergmann f->pixelformat = V4L2_PIX_FMT_YUYV; 3950185f850SArnd Bergmann return 0; 3960185f850SArnd Bergmann } 3970185f850SArnd Bergmann 3980185f850SArnd Bergmann static int skeleton_s_std(struct file *file, void *priv, v4l2_std_id std) 3990185f850SArnd Bergmann { 4000185f850SArnd Bergmann struct skeleton *skel = video_drvdata(file); 4010185f850SArnd Bergmann 4020185f850SArnd Bergmann /* S_STD is not supported on the HDMI input */ 4030185f850SArnd Bergmann if (skel->input) 4040185f850SArnd Bergmann return -ENODATA; 4050185f850SArnd Bergmann 4060185f850SArnd Bergmann /* 4070185f850SArnd Bergmann * No change, so just return. Some applications call S_STD again after 4080185f850SArnd Bergmann * the buffers for streaming have been set up, so we have to allow for 4090185f850SArnd Bergmann * this behavior. 4100185f850SArnd Bergmann */ 4110185f850SArnd Bergmann if (std == skel->std) 4120185f850SArnd Bergmann return 0; 4130185f850SArnd Bergmann 4140185f850SArnd Bergmann /* 4150185f850SArnd Bergmann * Changing the standard implies a format change, which is not allowed 4160185f850SArnd Bergmann * while buffers for use with streaming have already been allocated. 4170185f850SArnd Bergmann */ 4180185f850SArnd Bergmann if (vb2_is_busy(&skel->queue)) 4190185f850SArnd Bergmann return -EBUSY; 4200185f850SArnd Bergmann 4210185f850SArnd Bergmann /* TODO: handle changing std */ 4220185f850SArnd Bergmann 4230185f850SArnd Bergmann skel->std = std; 4240185f850SArnd Bergmann 4250185f850SArnd Bergmann /* Update the internal format */ 4260185f850SArnd Bergmann skeleton_fill_pix_format(skel, &skel->format); 4270185f850SArnd Bergmann return 0; 4280185f850SArnd Bergmann } 4290185f850SArnd Bergmann 4300185f850SArnd Bergmann static int skeleton_g_std(struct file *file, void *priv, v4l2_std_id *std) 4310185f850SArnd Bergmann { 4320185f850SArnd Bergmann struct skeleton *skel = video_drvdata(file); 4330185f850SArnd Bergmann 4340185f850SArnd Bergmann /* G_STD is not supported on the HDMI input */ 4350185f850SArnd Bergmann if (skel->input) 4360185f850SArnd Bergmann return -ENODATA; 4370185f850SArnd Bergmann 4380185f850SArnd Bergmann *std = skel->std; 4390185f850SArnd Bergmann return 0; 4400185f850SArnd Bergmann } 4410185f850SArnd Bergmann 4420185f850SArnd Bergmann /* 4430185f850SArnd Bergmann * Query the current standard as seen by the hardware. This function shall 4440185f850SArnd Bergmann * never actually change the standard, it just detects and reports. 4450185f850SArnd Bergmann * The framework will initially set *std to tvnorms (i.e. the set of 4460185f850SArnd Bergmann * supported standards by this input), and this function should just AND 4470185f850SArnd Bergmann * this value. If there is no signal, then *std should be set to 0. 4480185f850SArnd Bergmann */ 4490185f850SArnd Bergmann static int skeleton_querystd(struct file *file, void *priv, v4l2_std_id *std) 4500185f850SArnd Bergmann { 4510185f850SArnd Bergmann struct skeleton *skel = video_drvdata(file); 4520185f850SArnd Bergmann 4530185f850SArnd Bergmann /* QUERY_STD is not supported on the HDMI input */ 4540185f850SArnd Bergmann if (skel->input) 4550185f850SArnd Bergmann return -ENODATA; 4560185f850SArnd Bergmann 4570185f850SArnd Bergmann #ifdef TODO 4580185f850SArnd Bergmann /* 4590185f850SArnd Bergmann * Query currently seen standard. Initial value of *std is 4600185f850SArnd Bergmann * V4L2_STD_ALL. This function should look something like this: 4610185f850SArnd Bergmann */ 4620185f850SArnd Bergmann get_signal_info(); 4630185f850SArnd Bergmann if (no_signal) { 4640185f850SArnd Bergmann *std = 0; 4650185f850SArnd Bergmann return 0; 4660185f850SArnd Bergmann } 4670185f850SArnd Bergmann /* Use signal information to reduce the number of possible standards */ 4680185f850SArnd Bergmann if (signal_has_525_lines) 4690185f850SArnd Bergmann *std &= V4L2_STD_525_60; 4700185f850SArnd Bergmann else 4710185f850SArnd Bergmann *std &= V4L2_STD_625_50; 4720185f850SArnd Bergmann #endif 4730185f850SArnd Bergmann return 0; 4740185f850SArnd Bergmann } 4750185f850SArnd Bergmann 4760185f850SArnd Bergmann static int skeleton_s_dv_timings(struct file *file, void *_fh, 4770185f850SArnd Bergmann struct v4l2_dv_timings *timings) 4780185f850SArnd Bergmann { 4790185f850SArnd Bergmann struct skeleton *skel = video_drvdata(file); 4800185f850SArnd Bergmann 4810185f850SArnd Bergmann /* S_DV_TIMINGS is not supported on the S-Video input */ 4820185f850SArnd Bergmann if (skel->input == 0) 4830185f850SArnd Bergmann return -ENODATA; 4840185f850SArnd Bergmann 4850185f850SArnd Bergmann /* Quick sanity check */ 4860185f850SArnd Bergmann if (!v4l2_valid_dv_timings(timings, &skel_timings_cap, NULL, NULL)) 4870185f850SArnd Bergmann return -EINVAL; 4880185f850SArnd Bergmann 4890185f850SArnd Bergmann /* Check if the timings are part of the CEA-861 timings. */ 4900185f850SArnd Bergmann if (!v4l2_find_dv_timings_cap(timings, &skel_timings_cap, 4910185f850SArnd Bergmann 0, NULL, NULL)) 4920185f850SArnd Bergmann return -EINVAL; 4930185f850SArnd Bergmann 4940185f850SArnd Bergmann /* Return 0 if the new timings are the same as the current timings. */ 4950185f850SArnd Bergmann if (v4l2_match_dv_timings(timings, &skel->timings, 0, false)) 4960185f850SArnd Bergmann return 0; 4970185f850SArnd Bergmann 4980185f850SArnd Bergmann /* 4990185f850SArnd Bergmann * Changing the timings implies a format change, which is not allowed 5000185f850SArnd Bergmann * while buffers for use with streaming have already been allocated. 5010185f850SArnd Bergmann */ 5020185f850SArnd Bergmann if (vb2_is_busy(&skel->queue)) 5030185f850SArnd Bergmann return -EBUSY; 5040185f850SArnd Bergmann 5050185f850SArnd Bergmann /* TODO: Configure new timings */ 5060185f850SArnd Bergmann 5070185f850SArnd Bergmann /* Save timings */ 5080185f850SArnd Bergmann skel->timings = *timings; 5090185f850SArnd Bergmann 5100185f850SArnd Bergmann /* Update the internal format */ 5110185f850SArnd Bergmann skeleton_fill_pix_format(skel, &skel->format); 5120185f850SArnd Bergmann return 0; 5130185f850SArnd Bergmann } 5140185f850SArnd Bergmann 5150185f850SArnd Bergmann static int skeleton_g_dv_timings(struct file *file, void *_fh, 5160185f850SArnd Bergmann struct v4l2_dv_timings *timings) 5170185f850SArnd Bergmann { 5180185f850SArnd Bergmann struct skeleton *skel = video_drvdata(file); 5190185f850SArnd Bergmann 5200185f850SArnd Bergmann /* G_DV_TIMINGS is not supported on the S-Video input */ 5210185f850SArnd Bergmann if (skel->input == 0) 5220185f850SArnd Bergmann return -ENODATA; 5230185f850SArnd Bergmann 5240185f850SArnd Bergmann *timings = skel->timings; 5250185f850SArnd Bergmann return 0; 5260185f850SArnd Bergmann } 5270185f850SArnd Bergmann 5280185f850SArnd Bergmann static int skeleton_enum_dv_timings(struct file *file, void *_fh, 5290185f850SArnd Bergmann struct v4l2_enum_dv_timings *timings) 5300185f850SArnd Bergmann { 5310185f850SArnd Bergmann struct skeleton *skel = video_drvdata(file); 5320185f850SArnd Bergmann 5330185f850SArnd Bergmann /* ENUM_DV_TIMINGS is not supported on the S-Video input */ 5340185f850SArnd Bergmann if (skel->input == 0) 5350185f850SArnd Bergmann return -ENODATA; 5360185f850SArnd Bergmann 5370185f850SArnd Bergmann return v4l2_enum_dv_timings_cap(timings, &skel_timings_cap, 5380185f850SArnd Bergmann NULL, NULL); 5390185f850SArnd Bergmann } 5400185f850SArnd Bergmann 5410185f850SArnd Bergmann /* 5420185f850SArnd Bergmann * Query the current timings as seen by the hardware. This function shall 5430185f850SArnd Bergmann * never actually change the timings, it just detects and reports. 5440185f850SArnd Bergmann * If no signal is detected, then return -ENOLINK. If the hardware cannot 5450185f850SArnd Bergmann * lock to the signal, then return -ENOLCK. If the signal is out of range 5460185f850SArnd Bergmann * of the capabilities of the system (e.g., it is possible that the receiver 5470185f850SArnd Bergmann * can lock but that the DMA engine it is connected to cannot handle 5480185f850SArnd Bergmann * pixelclocks above a certain frequency), then -ERANGE is returned. 5490185f850SArnd Bergmann */ 5500185f850SArnd Bergmann static int skeleton_query_dv_timings(struct file *file, void *_fh, 5510185f850SArnd Bergmann struct v4l2_dv_timings *timings) 5520185f850SArnd Bergmann { 5530185f850SArnd Bergmann struct skeleton *skel = video_drvdata(file); 5540185f850SArnd Bergmann 5550185f850SArnd Bergmann /* QUERY_DV_TIMINGS is not supported on the S-Video input */ 5560185f850SArnd Bergmann if (skel->input == 0) 5570185f850SArnd Bergmann return -ENODATA; 5580185f850SArnd Bergmann 5590185f850SArnd Bergmann #ifdef TODO 5600185f850SArnd Bergmann /* 5610185f850SArnd Bergmann * Query currently seen timings. This function should look 5620185f850SArnd Bergmann * something like this: 5630185f850SArnd Bergmann */ 5640185f850SArnd Bergmann detect_timings(); 5650185f850SArnd Bergmann if (no_signal) 5660185f850SArnd Bergmann return -ENOLINK; 5670185f850SArnd Bergmann if (cannot_lock_to_signal) 5680185f850SArnd Bergmann return -ENOLCK; 5690185f850SArnd Bergmann if (signal_out_of_range_of_capabilities) 5700185f850SArnd Bergmann return -ERANGE; 5710185f850SArnd Bergmann 5720185f850SArnd Bergmann /* Useful for debugging */ 5730185f850SArnd Bergmann v4l2_print_dv_timings(skel->v4l2_dev.name, "query_dv_timings:", 5740185f850SArnd Bergmann timings, true); 5750185f850SArnd Bergmann #endif 5760185f850SArnd Bergmann return 0; 5770185f850SArnd Bergmann } 5780185f850SArnd Bergmann 5790185f850SArnd Bergmann static int skeleton_dv_timings_cap(struct file *file, void *fh, 5800185f850SArnd Bergmann struct v4l2_dv_timings_cap *cap) 5810185f850SArnd Bergmann { 5820185f850SArnd Bergmann struct skeleton *skel = video_drvdata(file); 5830185f850SArnd Bergmann 5840185f850SArnd Bergmann /* DV_TIMINGS_CAP is not supported on the S-Video input */ 5850185f850SArnd Bergmann if (skel->input == 0) 5860185f850SArnd Bergmann return -ENODATA; 5870185f850SArnd Bergmann *cap = skel_timings_cap; 5880185f850SArnd Bergmann return 0; 5890185f850SArnd Bergmann } 5900185f850SArnd Bergmann 5910185f850SArnd Bergmann static int skeleton_enum_input(struct file *file, void *priv, 5920185f850SArnd Bergmann struct v4l2_input *i) 5930185f850SArnd Bergmann { 5940185f850SArnd Bergmann if (i->index > 1) 5950185f850SArnd Bergmann return -EINVAL; 5960185f850SArnd Bergmann 5970185f850SArnd Bergmann i->type = V4L2_INPUT_TYPE_CAMERA; 5980185f850SArnd Bergmann if (i->index == 0) { 5990185f850SArnd Bergmann i->std = SKEL_TVNORMS; 6000185f850SArnd Bergmann strlcpy(i->name, "S-Video", sizeof(i->name)); 6010185f850SArnd Bergmann i->capabilities = V4L2_IN_CAP_STD; 6020185f850SArnd Bergmann } else { 6030185f850SArnd Bergmann i->std = 0; 6040185f850SArnd Bergmann strlcpy(i->name, "HDMI", sizeof(i->name)); 6050185f850SArnd Bergmann i->capabilities = V4L2_IN_CAP_DV_TIMINGS; 6060185f850SArnd Bergmann } 6070185f850SArnd Bergmann return 0; 6080185f850SArnd Bergmann } 6090185f850SArnd Bergmann 6100185f850SArnd Bergmann static int skeleton_s_input(struct file *file, void *priv, unsigned int i) 6110185f850SArnd Bergmann { 6120185f850SArnd Bergmann struct skeleton *skel = video_drvdata(file); 6130185f850SArnd Bergmann 6140185f850SArnd Bergmann if (i > 1) 6150185f850SArnd Bergmann return -EINVAL; 6160185f850SArnd Bergmann 6170185f850SArnd Bergmann /* 6180185f850SArnd Bergmann * Changing the input implies a format change, which is not allowed 6190185f850SArnd Bergmann * while buffers for use with streaming have already been allocated. 6200185f850SArnd Bergmann */ 6210185f850SArnd Bergmann if (vb2_is_busy(&skel->queue)) 6220185f850SArnd Bergmann return -EBUSY; 6230185f850SArnd Bergmann 6240185f850SArnd Bergmann skel->input = i; 6250185f850SArnd Bergmann /* 6260185f850SArnd Bergmann * Update tvnorms. The tvnorms value is used by the core to implement 6270185f850SArnd Bergmann * VIDIOC_ENUMSTD so it has to be correct. If tvnorms == 0, then 6280185f850SArnd Bergmann * ENUMSTD will return -ENODATA. 6290185f850SArnd Bergmann */ 6300185f850SArnd Bergmann skel->vdev.tvnorms = i ? 0 : SKEL_TVNORMS; 6310185f850SArnd Bergmann 6320185f850SArnd Bergmann /* Update the internal format */ 6330185f850SArnd Bergmann skeleton_fill_pix_format(skel, &skel->format); 6340185f850SArnd Bergmann return 0; 6350185f850SArnd Bergmann } 6360185f850SArnd Bergmann 6370185f850SArnd Bergmann static int skeleton_g_input(struct file *file, void *priv, unsigned int *i) 6380185f850SArnd Bergmann { 6390185f850SArnd Bergmann struct skeleton *skel = video_drvdata(file); 6400185f850SArnd Bergmann 6410185f850SArnd Bergmann *i = skel->input; 6420185f850SArnd Bergmann return 0; 6430185f850SArnd Bergmann } 6440185f850SArnd Bergmann 6450185f850SArnd Bergmann /* The control handler. */ 6460185f850SArnd Bergmann static int skeleton_s_ctrl(struct v4l2_ctrl *ctrl) 6470185f850SArnd Bergmann { 6480185f850SArnd Bergmann /*struct skeleton *skel = 6490185f850SArnd Bergmann container_of(ctrl->handler, struct skeleton, ctrl_handler);*/ 6500185f850SArnd Bergmann 6510185f850SArnd Bergmann switch (ctrl->id) { 6520185f850SArnd Bergmann case V4L2_CID_BRIGHTNESS: 6530185f850SArnd Bergmann /* TODO: set brightness to ctrl->val */ 6540185f850SArnd Bergmann break; 6550185f850SArnd Bergmann case V4L2_CID_CONTRAST: 6560185f850SArnd Bergmann /* TODO: set contrast to ctrl->val */ 6570185f850SArnd Bergmann break; 6580185f850SArnd Bergmann case V4L2_CID_SATURATION: 6590185f850SArnd Bergmann /* TODO: set saturation to ctrl->val */ 6600185f850SArnd Bergmann break; 6610185f850SArnd Bergmann case V4L2_CID_HUE: 6620185f850SArnd Bergmann /* TODO: set hue to ctrl->val */ 6630185f850SArnd Bergmann break; 6640185f850SArnd Bergmann default: 6650185f850SArnd Bergmann return -EINVAL; 6660185f850SArnd Bergmann } 6670185f850SArnd Bergmann return 0; 6680185f850SArnd Bergmann } 6690185f850SArnd Bergmann 6700185f850SArnd Bergmann /* ------------------------------------------------------------------ 6710185f850SArnd Bergmann File operations for the device 6720185f850SArnd Bergmann ------------------------------------------------------------------*/ 6730185f850SArnd Bergmann 6740185f850SArnd Bergmann static const struct v4l2_ctrl_ops skel_ctrl_ops = { 6750185f850SArnd Bergmann .s_ctrl = skeleton_s_ctrl, 6760185f850SArnd Bergmann }; 6770185f850SArnd Bergmann 6780185f850SArnd Bergmann /* 6790185f850SArnd Bergmann * The set of all supported ioctls. Note that all the streaming ioctls 6800185f850SArnd Bergmann * use the vb2 helper functions that take care of all the locking and 6810185f850SArnd Bergmann * that also do ownership tracking (i.e. only the filehandle that requested 6820185f850SArnd Bergmann * the buffers can call the streaming ioctls, all other filehandles will 6830185f850SArnd Bergmann * receive -EBUSY if they attempt to call the same streaming ioctls). 6840185f850SArnd Bergmann * 6850185f850SArnd Bergmann * The last three ioctls also use standard helper functions: these implement 6860185f850SArnd Bergmann * standard behavior for drivers with controls. 6870185f850SArnd Bergmann */ 6880185f850SArnd Bergmann static const struct v4l2_ioctl_ops skel_ioctl_ops = { 6890185f850SArnd Bergmann .vidioc_querycap = skeleton_querycap, 6900185f850SArnd Bergmann .vidioc_try_fmt_vid_cap = skeleton_try_fmt_vid_cap, 6910185f850SArnd Bergmann .vidioc_s_fmt_vid_cap = skeleton_s_fmt_vid_cap, 6920185f850SArnd Bergmann .vidioc_g_fmt_vid_cap = skeleton_g_fmt_vid_cap, 6930185f850SArnd Bergmann .vidioc_enum_fmt_vid_cap = skeleton_enum_fmt_vid_cap, 6940185f850SArnd Bergmann 6950185f850SArnd Bergmann .vidioc_g_std = skeleton_g_std, 6960185f850SArnd Bergmann .vidioc_s_std = skeleton_s_std, 6970185f850SArnd Bergmann .vidioc_querystd = skeleton_querystd, 6980185f850SArnd Bergmann 6990185f850SArnd Bergmann .vidioc_s_dv_timings = skeleton_s_dv_timings, 7000185f850SArnd Bergmann .vidioc_g_dv_timings = skeleton_g_dv_timings, 7010185f850SArnd Bergmann .vidioc_enum_dv_timings = skeleton_enum_dv_timings, 7020185f850SArnd Bergmann .vidioc_query_dv_timings = skeleton_query_dv_timings, 7030185f850SArnd Bergmann .vidioc_dv_timings_cap = skeleton_dv_timings_cap, 7040185f850SArnd Bergmann 7050185f850SArnd Bergmann .vidioc_enum_input = skeleton_enum_input, 7060185f850SArnd Bergmann .vidioc_g_input = skeleton_g_input, 7070185f850SArnd Bergmann .vidioc_s_input = skeleton_s_input, 7080185f850SArnd Bergmann 7090185f850SArnd Bergmann .vidioc_reqbufs = vb2_ioctl_reqbufs, 7100185f850SArnd Bergmann .vidioc_create_bufs = vb2_ioctl_create_bufs, 7110185f850SArnd Bergmann .vidioc_querybuf = vb2_ioctl_querybuf, 7120185f850SArnd Bergmann .vidioc_qbuf = vb2_ioctl_qbuf, 7130185f850SArnd Bergmann .vidioc_dqbuf = vb2_ioctl_dqbuf, 7140185f850SArnd Bergmann .vidioc_expbuf = vb2_ioctl_expbuf, 7150185f850SArnd Bergmann .vidioc_streamon = vb2_ioctl_streamon, 7160185f850SArnd Bergmann .vidioc_streamoff = vb2_ioctl_streamoff, 7170185f850SArnd Bergmann 7180185f850SArnd Bergmann .vidioc_log_status = v4l2_ctrl_log_status, 7190185f850SArnd Bergmann .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, 7200185f850SArnd Bergmann .vidioc_unsubscribe_event = v4l2_event_unsubscribe, 7210185f850SArnd Bergmann }; 7220185f850SArnd Bergmann 7230185f850SArnd Bergmann /* 7240185f850SArnd Bergmann * The set of file operations. Note that all these ops are standard core 7250185f850SArnd Bergmann * helper functions. 7260185f850SArnd Bergmann */ 7270185f850SArnd Bergmann static const struct v4l2_file_operations skel_fops = { 7280185f850SArnd Bergmann .owner = THIS_MODULE, 7290185f850SArnd Bergmann .open = v4l2_fh_open, 7300185f850SArnd Bergmann .release = vb2_fop_release, 7310185f850SArnd Bergmann .unlocked_ioctl = video_ioctl2, 7320185f850SArnd Bergmann .read = vb2_fop_read, 7330185f850SArnd Bergmann .mmap = vb2_fop_mmap, 7340185f850SArnd Bergmann .poll = vb2_fop_poll, 7350185f850SArnd Bergmann }; 7360185f850SArnd Bergmann 7370185f850SArnd Bergmann /* 7380185f850SArnd Bergmann * The initial setup of this device instance. Note that the initial state of 7390185f850SArnd Bergmann * the driver should be complete. So the initial format, standard, timings 7400185f850SArnd Bergmann * and video input should all be initialized to some reasonable value. 7410185f850SArnd Bergmann */ 7420185f850SArnd Bergmann static int skeleton_probe(struct pci_dev *pdev, const struct pci_device_id *ent) 7430185f850SArnd Bergmann { 7440185f850SArnd Bergmann /* The initial timings are chosen to be 720p60. */ 7450185f850SArnd Bergmann static const struct v4l2_dv_timings timings_def = 7460185f850SArnd Bergmann V4L2_DV_BT_CEA_1280X720P60; 7470185f850SArnd Bergmann struct skeleton *skel; 7480185f850SArnd Bergmann struct video_device *vdev; 7490185f850SArnd Bergmann struct v4l2_ctrl_handler *hdl; 7500185f850SArnd Bergmann struct vb2_queue *q; 7510185f850SArnd Bergmann int ret; 7520185f850SArnd Bergmann 7530185f850SArnd Bergmann /* Enable PCI */ 7540185f850SArnd Bergmann ret = pci_enable_device(pdev); 7550185f850SArnd Bergmann if (ret) 7560185f850SArnd Bergmann return ret; 757fba09099SChristophe JAILLET ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); 7580185f850SArnd Bergmann if (ret) { 7590185f850SArnd Bergmann dev_err(&pdev->dev, "no suitable DMA available.\n"); 7600185f850SArnd Bergmann goto disable_pci; 7610185f850SArnd Bergmann } 7620185f850SArnd Bergmann 7630185f850SArnd Bergmann /* Allocate a new instance */ 7640185f850SArnd Bergmann skel = devm_kzalloc(&pdev->dev, sizeof(struct skeleton), GFP_KERNEL); 76515a35ca6SChristophe JAILLET if (!skel) { 76615a35ca6SChristophe JAILLET ret = -ENOMEM; 76715a35ca6SChristophe JAILLET goto disable_pci; 76815a35ca6SChristophe JAILLET } 7690185f850SArnd Bergmann 7700185f850SArnd Bergmann /* Allocate the interrupt */ 7710185f850SArnd Bergmann ret = devm_request_irq(&pdev->dev, pdev->irq, 7720185f850SArnd Bergmann skeleton_irq, 0, KBUILD_MODNAME, skel); 7730185f850SArnd Bergmann if (ret) { 7740185f850SArnd Bergmann dev_err(&pdev->dev, "request_irq failed\n"); 7750185f850SArnd Bergmann goto disable_pci; 7760185f850SArnd Bergmann } 7770185f850SArnd Bergmann skel->pdev = pdev; 7780185f850SArnd Bergmann 7790185f850SArnd Bergmann /* Fill in the initial format-related settings */ 7800185f850SArnd Bergmann skel->timings = timings_def; 7810185f850SArnd Bergmann skel->std = V4L2_STD_625_50; 7820185f850SArnd Bergmann skeleton_fill_pix_format(skel, &skel->format); 7830185f850SArnd Bergmann 7840185f850SArnd Bergmann /* Initialize the top-level structure */ 7850185f850SArnd Bergmann ret = v4l2_device_register(&pdev->dev, &skel->v4l2_dev); 7860185f850SArnd Bergmann if (ret) 7870185f850SArnd Bergmann goto disable_pci; 7880185f850SArnd Bergmann 7890185f850SArnd Bergmann mutex_init(&skel->lock); 7900185f850SArnd Bergmann 7910185f850SArnd Bergmann /* Add the controls */ 7920185f850SArnd Bergmann hdl = &skel->ctrl_handler; 7930185f850SArnd Bergmann v4l2_ctrl_handler_init(hdl, 4); 7940185f850SArnd Bergmann v4l2_ctrl_new_std(hdl, &skel_ctrl_ops, 7950185f850SArnd Bergmann V4L2_CID_BRIGHTNESS, 0, 255, 1, 127); 7960185f850SArnd Bergmann v4l2_ctrl_new_std(hdl, &skel_ctrl_ops, 7970185f850SArnd Bergmann V4L2_CID_CONTRAST, 0, 255, 1, 16); 7980185f850SArnd Bergmann v4l2_ctrl_new_std(hdl, &skel_ctrl_ops, 7990185f850SArnd Bergmann V4L2_CID_SATURATION, 0, 255, 1, 127); 8000185f850SArnd Bergmann v4l2_ctrl_new_std(hdl, &skel_ctrl_ops, 8010185f850SArnd Bergmann V4L2_CID_HUE, -128, 127, 1, 0); 8020185f850SArnd Bergmann if (hdl->error) { 8030185f850SArnd Bergmann ret = hdl->error; 8040185f850SArnd Bergmann goto free_hdl; 8050185f850SArnd Bergmann } 8060185f850SArnd Bergmann skel->v4l2_dev.ctrl_handler = hdl; 8070185f850SArnd Bergmann 8080185f850SArnd Bergmann /* Initialize the vb2 queue */ 8090185f850SArnd Bergmann q = &skel->queue; 8100185f850SArnd Bergmann q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 8110185f850SArnd Bergmann q->io_modes = VB2_MMAP | VB2_DMABUF | VB2_READ; 8128f10c2dbSHans Verkuil q->dev = &pdev->dev; 8130185f850SArnd Bergmann q->drv_priv = skel; 8140185f850SArnd Bergmann q->buf_struct_size = sizeof(struct skel_buffer); 8150185f850SArnd Bergmann q->ops = &skel_qops; 8160185f850SArnd Bergmann q->mem_ops = &vb2_dma_contig_memops; 8170185f850SArnd Bergmann q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; 8180185f850SArnd Bergmann /* 8190185f850SArnd Bergmann * Assume that this DMA engine needs to have at least two buffers 8200185f850SArnd Bergmann * available before it can be started. The start_streaming() op 8210185f850SArnd Bergmann * won't be called until at least this many buffers are queued up. 8220185f850SArnd Bergmann */ 8230185f850SArnd Bergmann q->min_buffers_needed = 2; 8240185f850SArnd Bergmann /* 8250185f850SArnd Bergmann * The serialization lock for the streaming ioctls. This is the same 8260185f850SArnd Bergmann * as the main serialization lock, but if some of the non-streaming 8270185f850SArnd Bergmann * ioctls could take a long time to execute, then you might want to 8280185f850SArnd Bergmann * have a different lock here to prevent VIDIOC_DQBUF from being 8290185f850SArnd Bergmann * blocked while waiting for another action to finish. This is 8300185f850SArnd Bergmann * generally not needed for PCI devices, but USB devices usually do 8310185f850SArnd Bergmann * want a separate lock here. 8320185f850SArnd Bergmann */ 8330185f850SArnd Bergmann q->lock = &skel->lock; 8340185f850SArnd Bergmann /* 8350185f850SArnd Bergmann * Since this driver can only do 32-bit DMA we must make sure that 8360185f850SArnd Bergmann * the vb2 core will allocate the buffers in 32-bit DMA memory. 8370185f850SArnd Bergmann */ 8380185f850SArnd Bergmann q->gfp_flags = GFP_DMA32; 8390185f850SArnd Bergmann ret = vb2_queue_init(q); 8400185f850SArnd Bergmann if (ret) 8410185f850SArnd Bergmann goto free_hdl; 8420185f850SArnd Bergmann 8430185f850SArnd Bergmann INIT_LIST_HEAD(&skel->buf_list); 8440185f850SArnd Bergmann spin_lock_init(&skel->qlock); 8450185f850SArnd Bergmann 8460185f850SArnd Bergmann /* Initialize the video_device structure */ 8470185f850SArnd Bergmann vdev = &skel->vdev; 8480185f850SArnd Bergmann strlcpy(vdev->name, KBUILD_MODNAME, sizeof(vdev->name)); 8490185f850SArnd Bergmann /* 8500185f850SArnd Bergmann * There is nothing to clean up, so release is set to an empty release 8510185f850SArnd Bergmann * function. The release callback must be non-NULL. 8520185f850SArnd Bergmann */ 8530185f850SArnd Bergmann vdev->release = video_device_release_empty; 8540185f850SArnd Bergmann vdev->fops = &skel_fops, 8550185f850SArnd Bergmann vdev->ioctl_ops = &skel_ioctl_ops, 8560185f850SArnd Bergmann vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | 8570185f850SArnd Bergmann V4L2_CAP_STREAMING; 8580185f850SArnd Bergmann /* 8590185f850SArnd Bergmann * The main serialization lock. All ioctls are serialized by this 8600185f850SArnd Bergmann * lock. Exception: if q->lock is set, then the streaming ioctls 8610185f850SArnd Bergmann * are serialized by that separate lock. 8620185f850SArnd Bergmann */ 8630185f850SArnd Bergmann vdev->lock = &skel->lock; 8640185f850SArnd Bergmann vdev->queue = q; 8650185f850SArnd Bergmann vdev->v4l2_dev = &skel->v4l2_dev; 8660185f850SArnd Bergmann /* Supported SDTV standards, if any */ 8670185f850SArnd Bergmann vdev->tvnorms = SKEL_TVNORMS; 8680185f850SArnd Bergmann video_set_drvdata(vdev, skel); 8690185f850SArnd Bergmann 870238e4a5bSHans Verkuil ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1); 8710185f850SArnd Bergmann if (ret) 8728f10c2dbSHans Verkuil goto free_hdl; 8730185f850SArnd Bergmann 8740185f850SArnd Bergmann dev_info(&pdev->dev, "V4L2 PCI Skeleton Driver loaded\n"); 8750185f850SArnd Bergmann return 0; 8760185f850SArnd Bergmann 8770185f850SArnd Bergmann free_hdl: 8780185f850SArnd Bergmann v4l2_ctrl_handler_free(&skel->ctrl_handler); 8790185f850SArnd Bergmann v4l2_device_unregister(&skel->v4l2_dev); 8800185f850SArnd Bergmann disable_pci: 8810185f850SArnd Bergmann pci_disable_device(pdev); 8820185f850SArnd Bergmann return ret; 8830185f850SArnd Bergmann } 8840185f850SArnd Bergmann 8850185f850SArnd Bergmann static void skeleton_remove(struct pci_dev *pdev) 8860185f850SArnd Bergmann { 8870185f850SArnd Bergmann struct v4l2_device *v4l2_dev = pci_get_drvdata(pdev); 8880185f850SArnd Bergmann struct skeleton *skel = container_of(v4l2_dev, struct skeleton, v4l2_dev); 8890185f850SArnd Bergmann 8900185f850SArnd Bergmann video_unregister_device(&skel->vdev); 8910185f850SArnd Bergmann v4l2_ctrl_handler_free(&skel->ctrl_handler); 8920185f850SArnd Bergmann v4l2_device_unregister(&skel->v4l2_dev); 8930185f850SArnd Bergmann pci_disable_device(skel->pdev); 8940185f850SArnd Bergmann } 8950185f850SArnd Bergmann 8960185f850SArnd Bergmann static struct pci_driver skeleton_driver = { 8970185f850SArnd Bergmann .name = KBUILD_MODNAME, 8980185f850SArnd Bergmann .probe = skeleton_probe, 8990185f850SArnd Bergmann .remove = skeleton_remove, 9000185f850SArnd Bergmann .id_table = skeleton_pci_tbl, 9010185f850SArnd Bergmann }; 9020185f850SArnd Bergmann 9030185f850SArnd Bergmann module_pci_driver(skeleton_driver); 904