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