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