cregit-Linux how code gets into the kernel

Release 4.11 drivers/media/platform/davinci/vpfe_capture.c

/*
 * Copyright (C) 2008-2009 Texas Instruments Inc
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * Driver name : VPFE Capture driver
 *    VPFE Capture driver allows applications to capture and stream video
 *    frames on DaVinci SoCs (DM6446, DM355 etc) from a YUV source such as
 *    TVP5146 or  Raw Bayer RGB image data from an image sensor
 *    such as Microns' MT9T001, MT9T031 etc.
 *
 *    These SoCs have, in common, a Video Processing Subsystem (VPSS) that
 *    consists of a Video Processing Front End (VPFE) for capturing
 *    video/raw image data and Video Processing Back End (VPBE) for displaying
 *    YUV data through an in-built analog encoder or Digital LCD port. This
 *    driver is for capture through VPFE. A typical EVM using these SoCs have
 *    following high level configuration.
 *
 *
 *    decoder(TVP5146/          YUV/
 *           MT9T001)   -->  Raw Bayer RGB ---> MUX -> VPFE (CCDC/ISIF)
 *                              data input              |      |
 *                                                      V      |
 *                                                    SDRAM    |
 *                                                             V
 *                                                         Image Processor
 *                                                             |
 *                                                             V
 *                                                           SDRAM
 *    The data flow happens from a decoder connected to the VPFE over a
 *    YUV embedded (BT.656/BT.1120) or separate sync or raw bayer rgb interface
 *    and to the input of VPFE through an optional MUX (if more inputs are
 *    to be interfaced on the EVM). The input data is first passed through
 *    CCDC (CCD Controller, a.k.a Image Sensor Interface, ISIF). The CCDC
 *    does very little or no processing on YUV data and does pre-process Raw
 *    Bayer RGB data through modules such as Defect Pixel Correction (DFC)
 *    Color Space Conversion (CSC), data gain/offset etc. After this, data
 *    can be written to SDRAM or can be connected to the image processing
 *    block such as IPIPE (on DM355 only).
 *
 *    Features supported
 *              - MMAP IO
 *              - Capture using TVP5146 over BT.656
 *              - support for interfacing decoders using sub device model
 *              - Work with DM355 or DM6446 CCDC to do Raw Bayer RGB/YUV
 *                data capture to SDRAM.
 *    TODO list
 *              - Support multiple REQBUF after open
 *              - Support for de-allocating buffers through REQBUF
 *              - Support for Raw Bayer RGB capture
 *              - Support for chaining Image Processor
 *              - Support for static allocation of buffers
 *              - Support for USERPTR IO
 *              - Support for STREAMON before QBUF
 *              - Support for control ioctls
 */
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <media/v4l2-common.h>
#include <linux/io.h>
#include <media/davinci/vpfe_capture.h>
#include "ccdc_hw_device.h"


static int debug;

static u32 numbuffers = 3;

static u32 bufsize = (720 * 576 * 2);

module_param(numbuffers, uint, S_IRUGO);
module_param(bufsize, uint, S_IRUGO);
module_param(debug, int, 0644);

MODULE_PARM_DESC(numbuffers, "buffer count (default:3)");
MODULE_PARM_DESC(bufsize, "buffer size in bytes (default:720 x 576 x 2)");
MODULE_PARM_DESC(debug, "Debug level 0-1");

MODULE_DESCRIPTION("VPFE Video for Linux Capture Driver");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Texas Instruments");

/* standard information */

struct vpfe_standard {
	
v4l2_std_id std_id;
	
unsigned int width;
	
unsigned int height;
	
struct v4l2_fract pixelaspect;
	/* 0 - progressive, 1 - interlaced */
	
int frame_format;
};

/* ccdc configuration */

struct ccdc_config {
	/* This make sure vpfe is probed and ready to go */
	
int vpfe_probed;
	/* name of ccdc device */
	
char name[32];
};

/* data structures */

static struct vpfe_config_params config_params = {
	.min_numbuffers = 3,
	.numbuffers = 3,
	.min_bufsize = 720 * 480 * 2,
	.device_bufsize = 720 * 576 * 2,
};

/* ccdc device registered */

static struct ccdc_hw_device *ccdc_dev;
/* lock for accessing ccdc information */
static DEFINE_MUTEX(ccdc_lock);
/* ccdc configuration */

static struct ccdc_config *ccdc_cfg;


static const struct vpfe_standard vpfe_standards[] = {
	{V4L2_STD_525_60, 720, 480, {11, 10}, 1},
	{V4L2_STD_625_50, 720, 576, {54, 59}, 1},
};

/* Used when raw Bayer image from ccdc is directly captured to SDRAM */

static const struct vpfe_pixel_format vpfe_pix_fmts[] = {
	{
		.fmtdesc = {
			.index = 0,
			.type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
			.description = "Bayer GrRBGb 8bit A-Law compr.",
			.pixelformat = V4L2_PIX_FMT_SBGGR8,
                },
		.bpp = 1,
        },
	{
		.fmtdesc = {
			.index = 1,
			.type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
			.description = "Bayer GrRBGb - 16bit",
			.pixelformat = V4L2_PIX_FMT_SBGGR16,
                },
		.bpp = 2,
        },
	{
		.fmtdesc = {
			.index = 2,
			.type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
			.description = "Bayer GrRBGb 8bit DPCM compr.",
			.pixelformat = V4L2_PIX_FMT_SGRBG10DPCM8,
                },
		.bpp = 1,
        },
	{
		.fmtdesc = {
			.index = 3,
			.type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
			.description = "YCbCr 4:2:2 Interleaved UYVY",
			.pixelformat = V4L2_PIX_FMT_UYVY,
                },
		.bpp = 2,
        },
	{
		.fmtdesc = {
			.index = 4,
			.type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
			.description = "YCbCr 4:2:2 Interleaved YUYV",
			.pixelformat = V4L2_PIX_FMT_YUYV,
                },
		.bpp = 2,
        },
	{
		.fmtdesc = {
			.index = 5,
			.type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
			.description = "Y/CbCr 4:2:0 - Semi planar",
			.pixelformat = V4L2_PIX_FMT_NV12,
                },
		.bpp = 1,
        },
};

/*
 * vpfe_lookup_pix_format()
 * lookup an entry in the vpfe pix format table based on pix_format
 */

static const struct vpfe_pixel_format *vpfe_lookup_pix_format(u32 pix_format) { int i; for (i = 0; i < ARRAY_SIZE(vpfe_pix_fmts); i++) { if (pix_format == vpfe_pix_fmts[i].fmtdesc.pixelformat) return &vpfe_pix_fmts[i]; } return NULL; }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri56100.00%1100.00%
Total56100.00%1100.00%

/* * vpfe_register_ccdc_device. CCDC module calls this to * register with vpfe capture */
int vpfe_register_ccdc_device(struct ccdc_hw_device *dev) { int ret = 0; printk(KERN_NOTICE "vpfe_register_ccdc_device: %s\n", dev->name); BUG_ON(!dev->hw_ops.open); BUG_ON(!dev->hw_ops.enable); BUG_ON(!dev->hw_ops.set_hw_if_params); BUG_ON(!dev->hw_ops.configure); BUG_ON(!dev->hw_ops.set_buftype); BUG_ON(!dev->hw_ops.get_buftype); BUG_ON(!dev->hw_ops.enum_pix); BUG_ON(!dev->hw_ops.set_frame_format); BUG_ON(!dev->hw_ops.get_frame_format); BUG_ON(!dev->hw_ops.get_pixel_format); BUG_ON(!dev->hw_ops.set_pixel_format); BUG_ON(!dev->hw_ops.set_image_window); BUG_ON(!dev->hw_ops.get_image_window); BUG_ON(!dev->hw_ops.get_line_length); BUG_ON(!dev->hw_ops.getfid); mutex_lock(&ccdc_lock); if (!ccdc_cfg) { /* * TODO. Will this ever happen? if so, we need to fix it. * Proabably we need to add the request to a linked list and * walk through it during vpfe probe */ printk(KERN_ERR "vpfe capture not initialized\n"); ret = -EFAULT; goto unlock; } if (strcmp(dev->name, ccdc_cfg->name)) { /* ignore this ccdc */ ret = -EINVAL; goto unlock; } if (ccdc_dev) { printk(KERN_ERR "ccdc already registered\n"); ret = -EINVAL; goto unlock; } ccdc_dev = dev; unlock: mutex_unlock(&ccdc_lock); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri26199.62%266.67%
SF Markus Elfring10.38%133.33%
Total262100.00%3100.00%

EXPORT_SYMBOL(vpfe_register_ccdc_device); /* * vpfe_unregister_ccdc_device. CCDC module calls this to * unregister with vpfe capture */
void vpfe_unregister_ccdc_device(struct ccdc_hw_device *dev) { if (!dev) { printk(KERN_ERR "invalid ccdc device ptr\n"); return; } printk(KERN_NOTICE "vpfe_unregister_ccdc_device, dev->name = %s\n", dev->name); if (strcmp(dev->name, ccdc_cfg->name)) { /* ignore this ccdc */ return; } mutex_lock(&ccdc_lock); ccdc_dev = NULL; mutex_unlock(&ccdc_lock); }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri6698.51%150.00%
SF Markus Elfring11.49%150.00%
Total67100.00%2100.00%

EXPORT_SYMBOL(vpfe_unregister_ccdc_device); /* * vpfe_get_ccdc_image_format - Get image parameters based on CCDC settings */
static int vpfe_get_ccdc_image_format(struct vpfe_device *vpfe_dev, struct v4l2_format *f) { struct v4l2_rect image_win; enum ccdc_buftype buf_type; enum ccdc_frmfmt frm_fmt; memset(f, 0, sizeof(*f)); f->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; ccdc_dev->hw_ops.get_image_window(&image_win); f->fmt.pix.width = image_win.width; f->fmt.pix.height = image_win.height; f->fmt.pix.bytesperline = ccdc_dev->hw_ops.get_line_length(); f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * f->fmt.pix.height; buf_type = ccdc_dev->hw_ops.get_buftype(); f->fmt.pix.pixelformat = ccdc_dev->hw_ops.get_pixel_format(); frm_fmt = ccdc_dev->hw_ops.get_frame_format(); if (frm_fmt == CCDC_FRMFMT_PROGRESSIVE) f->fmt.pix.field = V4L2_FIELD_NONE; else if (frm_fmt == CCDC_FRMFMT_INTERLACED) { if (buf_type == CCDC_BUFTYPE_FLD_INTERLEAVED) f->fmt.pix.field = V4L2_FIELD_INTERLACED; else if (buf_type == CCDC_BUFTYPE_FLD_SEPARATED) f->fmt.pix.field = V4L2_FIELD_SEQ_TB; else { v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf_type\n"); return -EINVAL; } } else { v4l2_err(&vpfe_dev->v4l2_dev, "Invalid frm_fmt\n"); return -EINVAL; } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri248100.00%1100.00%
Total248100.00%1100.00%

/* * vpfe_config_ccdc_image_format() * For a pix format, configure ccdc to setup the capture */
static int vpfe_config_ccdc_image_format(struct vpfe_device *vpfe_dev) { enum ccdc_frmfmt frm_fmt = CCDC_FRMFMT_INTERLACED; int ret = 0; if (ccdc_dev->hw_ops.set_pixel_format( vpfe_dev->fmt.fmt.pix.pixelformat) < 0) { v4l2_err(&vpfe_dev->v4l2_dev, "couldn't set pix format in ccdc\n"); return -EINVAL; } /* configure the image window */ ccdc_dev->hw_ops.set_image_window(&vpfe_dev->crop); switch (vpfe_dev->fmt.fmt.pix.field) { case V4L2_FIELD_INTERLACED: /* do nothing, since it is default */ ret = ccdc_dev->hw_ops.set_buftype( CCDC_BUFTYPE_FLD_INTERLEAVED); break; case V4L2_FIELD_NONE: frm_fmt = CCDC_FRMFMT_PROGRESSIVE; /* buffer type only applicable for interlaced scan */ break; case V4L2_FIELD_SEQ_TB: ret = ccdc_dev->hw_ops.set_buftype( CCDC_BUFTYPE_FLD_SEPARATED); break; default: return -EINVAL; } /* set the frame format */ if (!ret) ret = ccdc_dev->hw_ops.set_frame_format(frm_fmt); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri151100.00%1100.00%
Total151100.00%1100.00%

/* * vpfe_config_image_format() * For a given standard, this functions sets up the default * pix format & crop values in the vpfe device and ccdc. It first * starts with defaults based values from the standard table. * It then checks if sub device supports get_fmt and then override the * values based on that.Sets crop values to match with scan resolution * starting at 0,0. It calls vpfe_config_ccdc_image_format() set the * values in ccdc */
static int vpfe_config_image_format(struct vpfe_device *vpfe_dev, v4l2_std_id std_id) { struct vpfe_subdev_info *sdinfo = vpfe_dev->current_subdev; struct v4l2_subdev_format fmt = { .which = V4L2_SUBDEV_FORMAT_ACTIVE, }; struct v4l2_mbus_framefmt *mbus_fmt = &fmt.format; struct v4l2_pix_format *pix = &vpfe_dev->fmt.fmt.pix; int i, ret; for (i = 0; i < ARRAY_SIZE(vpfe_standards); i++) { if (vpfe_standards[i].std_id & std_id) { vpfe_dev->std_info.active_pixels = vpfe_standards[i].width; vpfe_dev->std_info.active_lines = vpfe_standards[i].height; vpfe_dev->std_info.frame_format = vpfe_standards[i].frame_format; vpfe_dev->std_index = i; break; } } if (i == ARRAY_SIZE(vpfe_standards)) { v4l2_err(&vpfe_dev->v4l2_dev, "standard not supported\n"); return -EINVAL; } vpfe_dev->crop.top = 0; vpfe_dev->crop.left = 0; vpfe_dev->crop.width = vpfe_dev->std_info.active_pixels; vpfe_dev->crop.height = vpfe_dev->std_info.active_lines; pix->width = vpfe_dev->crop.width; pix->height = vpfe_dev->crop.height; /* first field and frame format based on standard frame format */ if (vpfe_dev->std_info.frame_format) { pix->field = V4L2_FIELD_INTERLACED; /* assume V4L2_PIX_FMT_UYVY as default */ pix->pixelformat = V4L2_PIX_FMT_UYVY; v4l2_fill_mbus_format(mbus_fmt, pix, MEDIA_BUS_FMT_YUYV10_2X10); } else { pix->field = V4L2_FIELD_NONE; /* assume V4L2_PIX_FMT_SBGGR8 */ pix->pixelformat = V4L2_PIX_FMT_SBGGR8; v4l2_fill_mbus_format(mbus_fmt, pix, MEDIA_BUS_FMT_SBGGR8_1X8); } /* if sub device supports get_fmt, override the defaults */ ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id, pad, get_fmt, NULL, &fmt); if (ret && ret != -ENOIOCTLCMD) { v4l2_err(&vpfe_dev->v4l2_dev, "error in getting get_fmt from sub device\n"); return ret; } v4l2_fill_pix_format(pix, mbus_fmt); pix->bytesperline = pix->width * 2; pix->sizeimage = pix->bytesperline * pix->height; /* Sets the values in CCDC */ ret = vpfe_config_ccdc_image_format(vpfe_dev); if (ret) return ret; /* Update the values of sizeimage and bytesperline */ pix->bytesperline = ccdc_dev->hw_ops.get_line_length(); pix->sizeimage = pix->bytesperline * pix->height; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri30275.12%120.00%
Hans Verkuil9724.13%240.00%
Boris Brezillon20.50%120.00%
Dan Carpenter10.25%120.00%
Total402100.00%5100.00%


static int vpfe_initialize_device(struct vpfe_device *vpfe_dev) { int ret; /* set first input of current subdevice as the current input */ vpfe_dev->current_input = 0; /* set default standard */ vpfe_dev->std_index = 0; /* Configure the default format information */ ret = vpfe_config_image_format(vpfe_dev, vpfe_standards[vpfe_dev->std_index].std_id); if (ret) return ret; /* now open the ccdc device to initialize it */ mutex_lock(&ccdc_lock); if (!ccdc_dev) { v4l2_err(&vpfe_dev->v4l2_dev, "ccdc device not registered\n"); ret = -ENODEV; goto unlock; } if (!try_module_get(ccdc_dev->owner)) { v4l2_err(&vpfe_dev->v4l2_dev, "Couldn't lock ccdc module\n"); ret = -ENODEV; goto unlock; } ret = ccdc_dev->hw_ops.open(vpfe_dev->pdev); if (!ret) vpfe_dev->initialized = 1; /* Clear all VPFE/CCDC interrupts */ if (vpfe_dev->cfg->clr_intr) vpfe_dev->cfg->clr_intr(-1); unlock: mutex_unlock(&ccdc_lock); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri14888.10%133.33%
Vaibhav Hiremath1911.31%133.33%
SF Markus Elfring10.60%133.33%
Total168100.00%3100.00%

/* * vpfe_open : It creates object of file handle structure and * stores it in private_data member of filepointer */
static int vpfe_open(struct file *file) { struct vpfe_device *vpfe_dev = video_drvdata(file); struct video_device *vdev = video_devdata(file); struct vpfe_fh *fh; v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_open\n"); if (!vpfe_dev->cfg->num_subdevs) { v4l2_err(&vpfe_dev->v4l2_dev, "No decoder registered\n"); return -ENODEV; } /* Allocate memory for the file handle object */ fh = kmalloc(sizeof(*fh), GFP_KERNEL); if (!fh) return -ENOMEM; /* store pointer to fh in private_data member of file */ file->private_data = fh; fh->vpfe_dev = vpfe_dev; v4l2_fh_init(&fh->fh, vdev); mutex_lock(&vpfe_dev->lock); /* If decoder is not initialized. initialize it */ if (!vpfe_dev->initialized) { if (vpfe_initialize_device(vpfe_dev)) { mutex_unlock(&vpfe_dev->lock); v4l2_fh_exit(&fh->fh); kfree(fh); return -ENODEV; } } /* Increment device usrs counter */ vpfe_dev->usrs++; /* Set io_allowed member to false */ fh->io_allowed = 0; v4l2_fh_add(&fh->fh); mutex_unlock(&vpfe_dev->lock); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri16781.46%120.00%
Lad Prabhakar2210.73%120.00%
Shailendra Verma136.34%120.00%
SF Markus Elfring31.46%240.00%
Total205100.00%5100.00%


static void vpfe_schedule_next_buffer(struct vpfe_device *vpfe_dev) { unsigned long addr; vpfe_dev->next_frm = list_entry(vpfe_dev->dma_queue.next, struct videobuf_buffer, queue); list_del(&vpfe_dev->next_frm->queue); vpfe_dev->next_frm->state = VIDEOBUF_ACTIVE; addr = videobuf_to_dma_contig(vpfe_dev->next_frm); ccdc_dev->hw_ops.setfbaddr(addr); }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri69100.00%1100.00%
Total69100.00%1100.00%


static void vpfe_schedule_bottom_field(struct vpfe_device *vpfe_dev) { unsigned long addr; addr = videobuf_to_dma_contig(vpfe_dev->cur_frm); addr += vpfe_dev->field_off; ccdc_dev->hw_ops.setfbaddr(addr); }

Contributors

PersonTokensPropCommitsCommitProp
Vaibhav Hiremath39100.00%1100.00%
Total39100.00%1100.00%


static void vpfe_process_buffer_complete(struct vpfe_device *vpfe_dev) { v4l2_get_timestamp(&vpfe_dev->cur_frm->ts); vpfe_dev->cur_frm->state = VIDEOBUF_DONE; vpfe_dev->cur_frm->size = vpfe_dev->fmt.fmt.pix.sizeimage; wake_up_interruptible(&vpfe_dev->cur_frm->done); vpfe_dev->cur_frm = vpfe_dev->next_frm; }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri6196.83%150.00%
Sakari Ailus23.17%150.00%
Total63100.00%2100.00%

/* ISR for VINT0*/
static irqreturn_t vpfe_isr(int irq, void *dev_id) { struct vpfe_device *vpfe_dev = dev_id; enum v4l2_field field; int fid; v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "\nStarting vpfe_isr...\n"); field = vpfe_dev->fmt.fmt.pix.field; /* if streaming not started, don't do anything */ if (!vpfe_dev->started) goto clear_intr; /* only for 6446 this will be applicable */ if (ccdc_dev->hw_ops.reset) ccdc_dev->hw_ops.reset(); if (field == V4L2_FIELD_NONE) { /* handle progressive frame capture */ v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "frame format is progressive...\n"); if (vpfe_dev->cur_frm != vpfe_dev->next_frm) vpfe_process_buffer_complete(vpfe_dev); goto clear_intr; } /* interlaced or TB capture check which field we are in hardware */ fid = ccdc_dev->hw_ops.getfid(); /* switch the software maintained field id */ vpfe_dev->field_id ^= 1; v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "field id = %x:%x.\n", fid, vpfe_dev->field_id); if (fid == vpfe_dev->field_id) { /* we are in-sync here,continue */ if (fid == 0) { /* * One frame is just being captured. If the next frame * is available, release the current frame and move on */ if (vpfe_dev->cur_frm != vpfe_dev->next_frm) vpfe_process_buffer_complete(vpfe_dev); /* * based on whether the two fields are stored * interleavely or separately in memory, reconfigure * the CCDC memory address */ if (field == V4L2_FIELD_SEQ_TB) vpfe_schedule_bottom_field(vpfe_dev); goto clear_intr; } /* * if one field is just being captured configure * the next frame get the next frame from the empty * queue if no frame is available hold on to the * current buffer */ spin_lock(&vpfe_dev->dma_queue_lock); if (!list_empty(&vpfe_dev->dma_queue) && vpfe_dev->cur_frm == vpfe_dev->next_frm) vpfe_schedule_next_buffer(vpfe_dev); spin_unlock(&vpfe_dev->dma_queue_lock); } else if (fid == 0) { /* * out of sync. Recover from any hardware out-of-sync. * May loose one frame */ vpfe_dev->field_id = fid; } clear_intr: if (vpfe_dev->cfg->clr_intr) vpfe_dev->cfg->clr_intr(irq); return IRQ_HANDLED; }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri25889.90%133.33%
Vaibhav Hiremath2910.10%266.67%
Total287100.00%3100.00%

/* vdint1_isr - isr handler for VINT1 interrupt */
static irqreturn_t vdint1_isr(int irq, void *dev_id) { struct vpfe_device *vpfe_dev = dev_id; v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "\nInside vdint1_isr...\n"); /* if streaming not started, don't do anything */ if (!vpfe_dev->started) { if (vpfe_dev->cfg->clr_intr) vpfe_dev->cfg->clr_intr(irq); return IRQ_HANDLED; } spin_lock(&vpfe_dev->dma_queue_lock); if ((vpfe_dev->fmt.fmt.pix.field == V4L2_FIELD_NONE) && !list_empty(&vpfe_dev->dma_queue) && vpfe_dev->cur_frm == vpfe_dev->next_frm) vpfe_schedule_next_buffer(vpfe_dev); spin_unlock(&vpfe_dev->dma_queue_lock); if (vpfe_dev->cfg->clr_intr) vpfe_dev->cfg->clr_intr(irq); return IRQ_HANDLED; }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri10273.91%150.00%
Vaibhav Hiremath3626.09%150.00%
Total138100.00%2100.00%


static void vpfe_detach_irq(struct vpfe_device *vpfe_dev) { enum ccdc_frmfmt frame_format; frame_format = ccdc_dev->hw_ops.get_frame_format(); if (frame_format == CCDC_FRMFMT_PROGRESSIVE) free_irq(vpfe_dev->ccdc_irq1, vpfe_dev); }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri3692.31%150.00%
Vaibhav Hiremath37.69%150.00%
Total39100.00%2100.00%


static int vpfe_attach_irq(struct vpfe_device *vpfe_dev) { enum ccdc_frmfmt frame_format; frame_format = ccdc_dev->hw_ops.get_frame_format(); if (frame_format == CCDC_FRMFMT_PROGRESSIVE) { return request_irq(vpfe_dev->ccdc_irq1, vdint1_isr, 0, "vpfe_capture1", vpfe_dev); } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri5098.04%150.00%
Michael Opdenacker11.96%150.00%
Total51100.00%2100.00%

/* vpfe_stop_ccdc_capture: stop streaming in ccdc/isif */
static void vpfe_stop_ccdc_capture(struct vpfe_device *vpfe_dev) { vpfe_dev->started = 0; ccdc_dev->hw_ops.enable(0); if (ccdc_dev->hw_ops.enable_out_to_sdram) ccdc_dev->hw_ops.enable_out_to_sdram(0); }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri43100.00%1100.00%
Total43100.00%1100.00%

/* * vpfe_release : This function deletes buffer queue, frees the * buffers and the vpfe file handle */
static int vpfe_release(struct file *file) { struct vpfe_device *vpfe_dev = video_drvdata(file); struct vpfe_fh *fh = file->private_data; struct vpfe_subdev_info *sdinfo; int ret; v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_release\n"); /* Get the device lock */ mutex_lock(&vpfe_dev->lock); /* if this instance is doing IO */ if (fh->io_allowed) { if (vpfe_dev->started) { sdinfo = vpfe_dev->current_subdev; ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id, video, s_stream, 0); if (ret && (ret != -ENOIOCTLCMD)) v4l2_err(&vpfe_dev->v4l2_dev, "stream off failed in subdev\n"); vpfe_stop_ccdc_capture(vpfe_dev); vpfe_detach_irq(vpfe_dev); videobuf_streamoff(&vpfe_dev->buffer_queue); } vpfe_dev->io_usrs = 0; vpfe_dev->numbuffers = config_params.numbuffers; videobuf_stop(&vpfe_dev->buffer_queue); videobuf_mmap_free(&vpfe_dev->buffer_queue); } /* Decrement device usrs counter */ vpfe_dev->usrs--; v4l2_fh_del(&fh->fh); v4l2_fh_exit(&fh->fh); /* If this is the last file handle */ if (!vpfe_dev->usrs) { vpfe_dev->initialized = 0; if (ccdc_dev->hw_ops.close) ccdc_dev->hw_ops.close(vpfe_dev->pdev); module_put(ccdc_dev->owner); } mutex_unlock(&vpfe_dev->lock); file->private_data = NULL; /* Free memory allocated to file handle object */ kfree(fh); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri23590.38%133.33%
Lad Prabhakar259.62%266.67%
Total260100.00%3100.00%

/* * vpfe_mmap : It is used to map kernel space buffers * into user spaces */
static int vpfe_mmap(struct file *file, struct vm_area_struct *vma) { /* Get the device object and file handle object */ struct vpfe_device *vpfe_dev = video_drvdata(file); v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_mmap\n"); return videobuf_mmap_mapper(&vpfe_dev->buffer_queue, vma); }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri52100.00%1100.00%
Total52100.00%1100.00%

/* * vpfe_poll: It is used for select/poll system call */
static unsigned int vpfe_poll(struct file *file, poll_table *wait) { struct vpfe_device *vpfe_dev = video_drvdata(file); v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_poll\n"); if (vpfe_dev->started) return videobuf_poll_stream(file, &vpfe_dev->buffer_queue, wait); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri62100.00%1100.00%
Total62100.00%1100.00%

/* vpfe capture driver file operations */ static const struct v4l2_file_operations vpfe_fops = { .owner = THIS_MODULE, .open = vpfe_open, .release = vpfe_release, .unlocked_ioctl = video_ioctl2, .mmap = vpfe_mmap, .poll = vpfe_poll }; /* * vpfe_check_format() * This function adjust the input pixel format as per hardware * capabilities and update the same in pixfmt. * Following algorithm used :- * * If given pixformat is not in the vpfe list of pix formats or not * supported by the hardware, current value of pixformat in the device * is used * If given field is not supported, then current field is used. If field * is different from current, then it is matched with that from sub device. * Minimum height is 2 lines for interlaced or tb field and 1 line for * progressive. Maximum height is clamped to active active lines of scan * Minimum width is 32 bytes in memory and width is clamped to active * pixels of scan. * bytesperline is a multiple of 32. */
static const struct vpfe_pixel_format * vpfe_check_format(struct vpfe_device *vpfe_dev, struct v4l2_pix_format *pixfmt) { u32 min_height = 1, min_width = 32, max_width, max_height; const struct vpfe_pixel_format *vpfe_pix_fmt; u32 pix; int temp, found; vpfe_pix_fmt = vpfe_lookup_pix_format(pixfmt->pixelformat); if (!vpfe_pix_fmt) { /* * use current pixel format in the vpfe device. We * will find this pix format in the table */ pixfmt->pixelformat = vpfe_dev->fmt.fmt.pix.pixelformat; vpfe_pix_fmt = vpfe_lookup_pix_format(pixfmt->pixelformat); } /* check if hw supports it */ temp = 0; found = 0; while (ccdc_dev->hw_ops.enum_pix(&pix, temp) >= 0) { if (vpfe_pix_fmt->fmtdesc.pixelformat == pix) { found = 1; break; } temp++; } if (!found) { /* use current pixel format */ pixfmt->pixelformat = vpfe_dev->fmt.fmt.pix.pixelformat; /* * Since this is currently used in the vpfe device, we * will find this pix format in the table */ vpfe_pix_fmt = vpfe_lookup_pix_format(pixfmt->pixelformat); } /* check what field format is supported */ if (pixfmt->field == V4L2_FIELD_ANY) { /* if field is any, use current value as default */ pixfmt->field = vpfe_dev->fmt.fmt.pix.field; } /* * if field is not same as current field in the vpfe device * try matching the field with the sub device field */ if (vpfe_dev->fmt.fmt.pix.field != pixfmt->field) { /* * If field value is not in the supported fields, use current * field used in the device as default */ switch (pixfmt->field) { case V4L2_FIELD_INTERLACED: case V4L2_FIELD_SEQ_TB: /* if sub device is supporting progressive, use that */ if (!vpfe_dev->std_info.frame_format) pixfmt->field = V4L2_FIELD_NONE; break; case V4L2_FIELD_NONE: if (vpfe_dev->std_info.frame_format) pixfmt->field = V4L2_FIELD_INTERLACED; break; default: /* use current field as default */ pixfmt->field = vpfe_dev->fmt.fmt.pix.field; break; } } /* Now adjust image resolutions supported */ if (pixfmt->field == V4L2_FIELD_INTERLACED || pixfmt->field == V4L2_FIELD_SEQ_TB) min_height = 2; max_width = vpfe_dev->std_info.active_pixels; max_height = vpfe_dev->std_info.active_lines; min_width /= vpfe_pix_fmt->bpp; v4l2_info(&vpfe_dev->v4l2_dev, "width = %d, height = %d, bpp = %d\n", pixfmt->width, pixfmt->height, vpfe_pix_fmt->bpp); pixfmt->width = clamp((pixfmt->width), min_width, max_width); pixfmt->height = clamp((pixfmt->height), min_height, max_height); /* If interlaced, adjust height to be a multiple of 2 */ if (pixfmt->field == V4L2_FIELD_INTERLACED) pixfmt->height &= (~1); /* * recalculate bytesperline and sizeimage since width * and height might have changed */ pixfmt->bytesperline = (((pixfmt->width * vpfe_pix_fmt->bpp) + 31) & ~31); if (pixfmt->pixelformat == V4L2_PIX_FMT_NV12) pixfmt->sizeimage = pixfmt->bytesperline * pixfmt->height + ((pixfmt->bytesperline * pixfmt->height) >> 1); else pixfmt->sizeimage = pixfmt->bytesperline * pixfmt->height; v4l2_info(&vpfe_dev->v4l2_dev, "adjusted width = %d, height = %d, bpp = %d, bytesperline = %d, sizeimage = %d\n", pixfmt->width, pixfmt->height, vpfe_pix_fmt->bpp, pixfmt->bytesperline, pixfmt->sizeimage); return vpfe_pix_fmt; }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri49499.60%133.33%
Mauro Carvalho Chehab10.20%133.33%
SF Markus Elfring10.20%133.33%
Total496100.00%3100.00%


static int vpfe_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { struct vpfe_device *vpfe_dev = video_drvdata(file); v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_querycap\n"); cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; strlcpy(cap->driver, CAPTURE_DRV_NAME, sizeof(cap->driver)); strlcpy(cap->bus_info, "VPFE", sizeof(cap->bus_info)); strlcpy(cap->card, vpfe_dev->cfg->card_name, sizeof(cap->card)); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri10993.16%150.00%
Hans Verkuil86.84%150.00%
Total117100.00%2100.00%


static int vpfe_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *fmt) { struct vpfe_device *vpfe_dev = video_drvdata(file); v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_g_fmt_vid_cap\n"); /* Fill in the information about format */ *fmt = vpfe_dev->fmt; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri5498.18%150.00%
Mauro Carvalho Chehab11.82%150.00%
Total55100.00%2100.00%


static int vpfe_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *fmt) { struct vpfe_device *vpfe_dev = video_drvdata(file); const struct vpfe_pixel_format *pix_fmt; int temp_index; u32 pix; v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_enum_fmt_vid_cap\n"); if (ccdc_dev->hw_ops.enum_pix(&pix, fmt->index) < 0) return -EINVAL; /* Fill in the information about format */ pix_fmt = vpfe_lookup_pix_format(pix); if (pix_fmt) { temp_index = fmt->index; *fmt = pix_fmt->fmtdesc; fmt->index = temp_index; return 0; } return -EINVAL; }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri118100.00%1100.00%
Total118100.00%1100.00%


static int vpfe_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *fmt) { struct vpfe_device *vpfe_dev = video_drvdata(file); const struct vpfe_pixel_format *pix_fmts; int ret; v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_fmt_vid_cap\n"); /* If streaming is started, return error */ if (vpfe_dev->started) { v4l2_err(&vpfe_dev->v4l2_dev, "Streaming is started\n"); return -EBUSY; } /* Check for valid frame format */ pix_fmts = vpfe_check_format(vpfe_dev, &fmt->fmt.pix); if (!pix_fmts) return -EINVAL; /* store the pixel format in the device object */ ret = mutex_lock_interruptible(&vpfe_dev->lock); if (ret) return ret; /* First detach any IRQ if currently attached */ vpfe_detach_irq(vpfe_dev); vpfe_dev->fmt = *fmt; /* set image capture parameters in the ccdc */ ret = vpfe_config_ccdc_image_format(vpfe_dev); mutex_unlock(&vpfe_dev->lock); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri14999.33%150.00%
SF Markus Elfring10.67%150.00%
Total150100.00%2100.00%


static int vpfe_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { struct vpfe_device *vpfe_dev = video_drvdata(file); const struct vpfe_pixel_format *pix_fmts; v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_try_fmt_vid_cap\n"); pix_fmts = vpfe_check_format(vpfe_dev, &f->fmt.pix); if (!pix_fmts) return -EINVAL; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri7598.68%150.00%
SF Markus Elfring11.32%150.00%
Total76100.00%2100.00%

/* * vpfe_get_subdev_input_index - Get subdev index and subdev input index for a * given app input index */
static int vpfe_get_subdev_input_index(struct vpfe_device *vpfe_dev, int *subdev_index, int *subdev_input_index, int app_input_index) { struct vpfe_config *cfg = vpfe_dev->cfg; struct vpfe_subdev_info *sdinfo; int i, j = 0; for (i = 0; i < cfg->num_subdevs; i++) { sdinfo = &cfg->sub_devs[i]; if (app_input_index < (j + sdinfo->num_inputs)) { *subdev_index = i; *subdev_input_index = app_input_index - j; return 0; } j += sdinfo->num_inputs; } return -EINVAL; }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri109100.00%1100.00%
Total109100.00%1100.00%

/* * vpfe_get_app_input - Get app input index for a given subdev input index * driver stores the input index of the current sub device and translate it * when application request the current input */
static int vpfe_get_app_input_index(struct vpfe_device *vpfe_dev, int *app_input_index) { struct vpfe_config *cfg = vpfe_dev->cfg; struct vpfe_subdev_info *sdinfo; int i, j = 0; for (i = 0; i < cfg->num_subdevs; i++) { sdinfo = &cfg->sub_devs[i]; if (!strcmp(sdinfo->name, vpfe_dev->current_subdev->name)) { if (vpfe_dev->current_input >= sdinfo->num_inputs) return -1; *app_input_index = j + vpfe_dev->current_input; return 0; } j += sdinfo->num_inputs; } return -EINVAL; }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri117100.00%1100.00%
Total117100.00%1100.00%


static int vpfe_enum_input(struct file *file, void *priv, struct v4l2_input *inp) { struct vpfe_device *vpfe_dev = video_drvdata(file); struct vpfe_subdev_info *sdinfo; int subdev, index ; v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_enum_input\n"); if (vpfe_get_subdev_input_index(vpfe_dev, &subdev, &index, inp->index) < 0) { v4l2_err(&vpfe_dev->v4l2_dev, "input information not found for the subdev\n"); return -EINVAL; } sdinfo = &vpfe_dev->cfg->sub_devs[subdev]; *inp = sdinfo->inputs[index]; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri11197.37%133.33%
SF Markus Elfring21.75%133.33%
Mauro Carvalho Chehab10.88%133.33%
Total114100.00%3100.00%


static int vpfe_g_input(struct file *file, void *priv, unsigned int *index) { struct vpfe_device *vpfe_dev = video_drvdata(file); v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_g_input\n"); return vpfe_get_app_input_index(vpfe_dev, index); }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri52100.00%1100.00%
Total52100.00%1100.00%


static int vpfe_s_input(struct file *file, void *priv, unsigned int index) { struct vpfe_device *vpfe_dev = video_drvdata(file); struct v4l2_subdev *sd; struct vpfe_subdev_info *sdinfo; int subdev_index, inp_index; struct vpfe_route *route; u32 input, output; int ret; v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_input\n"); ret = mutex_lock_interruptible(&vpfe_dev->lock); if (ret) return ret; /* * If streaming is started return device busy * error */ if (vpfe_dev->started) { v4l2_err(&vpfe_dev->v4l2_dev, "Streaming is on\n"); ret = -EBUSY; goto unlock_out; } ret = vpfe_get_subdev_input_index(vpfe_dev, &subdev_index, &inp_index, index); if (ret < 0) { v4l2_err(&vpfe_dev->v4l2_dev, "invalid input index\n"); goto unlock_out; } sdinfo = &vpfe_dev->cfg->sub_devs[subdev_index]; sd = vpfe_dev->sd[subdev_index]; route = &sdinfo->routes[inp_index]; if (route && sdinfo->can_route) { input = route->input; output = route->output; } else { input = 0; output = 0; } if (sd) ret = v4l2_subdev_call(sd, video, s_routing, input, output, 0); if (ret) { v4l2_err(&vpfe_dev->v4l2_dev, "vpfe_doioctl:error in setting input in decoder\n"); ret = -EINVAL; goto unlock_out; } vpfe_dev->current_subdev = sdinfo; if (sd) vpfe_dev->v4l2_dev.ctrl_handler = sd->ctrl_handler; vpfe_dev->current_input = index; vpfe_dev->std_index = 0; /* set the bus/interface parameter for the sub device in ccdc */ ret = ccdc_dev->hw_ops.set_hw_if_params(&sdinfo->ccdc_if_params); if (ret) goto unlock_out; /* set the default image parameters in the device */ ret = vpfe_config_image_format(vpfe_dev, vpfe_standards[vpfe_dev->std_index].std_id); unlock_out: mutex_unlock(&vpfe_dev->lock); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri29385.17%125.00%
Hans Verkuil349.88%125.00%
SF Markus Elfring113.20%125.00%
Peter Senna Tschudin61.74%125.00%
Total344100.00%4100.00%


static int vpfe_querystd(struct file *file, void *priv, v4l2_std_id *std_id) { struct vpfe_device *vpfe_dev = video_drvdata(file); struct vpfe_subdev_info *sdinfo; int ret; v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_querystd\n"); ret = mutex_lock_interruptible(&vpfe_dev->lock); sdinfo = vpfe_dev->current_subdev; if (ret) return ret; /* Call querystd function of decoder device */ ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id, video, querystd, std_id); mutex_unlock(&vpfe_dev->lock); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri106100.00%1100.00%
Total106100.00%1100.00%


static int vpfe_s_std(struct file *file, void *priv, v4l2_std_id std_id) { struct vpfe_device *vpfe_dev = video_drvdata(file); struct vpfe_subdev_info *sdinfo; int ret; v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_std\n"); /* Call decoder driver function to set the standard */ ret = mutex_lock_interruptible(&vpfe_dev->lock); if (ret) return ret; sdinfo = vpfe_dev->current_subdev; /* If streaming is started, return device busy error */ if (vpfe_dev->started) { v4l2_err(&vpfe_dev->v4l2_dev, "streaming is started\n"); ret = -EBUSY; goto unlock_out; } ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id, video, s_std, std_id); if (ret < 0) { v4l2_err(&vpfe_dev->v4l2_dev, "Failed to set standard\n"); goto unlock_out; } ret = vpfe_config_image_format(vpfe_dev, std_id); unlock_out: mutex_unlock(&vpfe_dev->lock); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri16399.39%150.00%
Laurent Pinchart10.61%150.00%
Total164100.00%2100.00%


static int vpfe_g_std(struct file *file, void *priv, v4l2_std_id *std_id) { struct vpfe_device *vpfe_dev = video_drvdata(file); v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_g_std\n"); *std_id = vpfe_standards[vpfe_dev->std_index].std_id; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri58100.00%1100.00%
Total58100.00%1100.00%

/* * Videobuf operations */
static int vpfe_videobuf_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size) { struct vpfe_fh *fh = vq->priv_data; struct vpfe_device *vpfe_dev = fh->vpfe_dev; v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_buffer_setup\n"); *size = vpfe_dev->fmt.fmt.pix.sizeimage; if (vpfe_dev->memory == V4L2_MEMORY_MMAP && vpfe_dev->fmt.fmt.pix.sizeimage > config_params.device_bufsize) *size = config_params.device_bufsize; if (*count < config_params.min_numbuffers) *count = config_params.min_numbuffers; v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "count=%d, size=%d\n", *count, *size); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri9973.88%150.00%
Vaibhav Hiremath3526.12%150.00%
Total134100.00%2100.00%


static int vpfe_videobuf_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, enum v4l2_field field) { struct vpfe_fh *fh = vq->priv_data; struct vpfe_device *vpfe_dev = fh->vpfe_dev; unsigned long addr; int ret; v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_buffer_prepare\n"); /* If buffer is not initialized, initialize it */ if (VIDEOBUF_NEEDS_INIT == vb->state) { vb->width = vpfe_dev->fmt.fmt.pix.width; vb->height = vpfe_dev->fmt.fmt.pix.height; vb->size = vpfe_dev->fmt.fmt.pix.sizeimage; vb->field = field; ret = videobuf_iolock(vq, vb, NULL); if (ret < 0) return ret; addr = videobuf_to_dma_contig(vb); /* Make sure user addresses are aligned to 32 bytes */ if (!ALIGN(addr, 32)) return -EINVAL; vb->state = VIDEOBUF_PREPARED; } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri11970.41%150.00%
Vaibhav Hiremath5029.59%150.00%
Total169100.00%2100.00%


static void vpfe_videobuf_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) { /* Get the file handle object and device object */ struct vpfe_fh *fh = vq->priv_data; struct vpfe_device *vpfe_dev = fh->vpfe_dev; unsigned long flags; v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_buffer_queue\n"); /* add the buffer to the DMA queue */ spin_lock_irqsave(&vpfe_dev->dma_queue_lock, flags); list_add_tail(&vb->queue, &vpfe_dev->dma_queue); spin_unlock_irqrestore(&vpfe_dev->dma_queue_lock, flags); /* Change state of the buffer */ vb->state = VIDEOBUF_QUEUED; }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri94100.00%1100.00%
Total94100.00%1100.00%


static void vpfe_videobuf_release(struct videobuf_queue *vq, struct videobuf_buffer *vb) { struct vpfe_fh *fh = vq->priv_data; struct vpfe_device *vpfe_dev = fh->vpfe_dev; unsigned long flags; v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_videobuf_release\n"); /* * We need to flush the buffer from the dma queue since * they are de-allocated */ spin_lock_irqsave(&vpfe_dev->dma_queue_lock, flags); INIT_LIST_HEAD(&vpfe_dev->dma_queue); spin_unlock_irqrestore(&vpfe_dev->dma_queue_lock, flags); videobuf_dma_contig_free(vq, vb); vb->state = VIDEOBUF_NEEDS_INIT; }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri94100.00%1100.00%
Total94100.00%1100.00%

static struct videobuf_queue_ops vpfe_videobuf_qops = { .buf_setup = vpfe_videobuf_setup, .buf_prepare = vpfe_videobuf_prepare, .buf_queue = vpfe_videobuf_queue, .buf_release = vpfe_videobuf_release, }; /* * vpfe_reqbufs. currently support REQBUF only once opening * the device. */
static int vpfe_reqbufs(struct file *file, void *priv, struct v4l2_requestbuffers *req_buf) { struct vpfe_device *vpfe_dev = video_drvdata(file); struct vpfe_fh *fh = file->private_data; int ret; v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_reqbufs\n"); if (V4L2_BUF_TYPE_VIDEO_CAPTURE != req_buf->type) { v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buffer type\n"); return -EINVAL; } ret = mutex_lock_interruptible(&vpfe_dev->lock); if (ret) return ret; if (vpfe_dev->io_usrs != 0) { v4l2_err(&vpfe_dev->v4l2_dev, "Only one IO user allowed\n"); ret = -EBUSY; goto unlock_out; } vpfe_dev->memory = req_buf->memory; videobuf_queue_dma_contig_init(&vpfe_dev->buffer_queue, &vpfe_videobuf_qops, vpfe_dev->pdev, &vpfe_dev->irqlock, req_buf->type, vpfe_dev->fmt.fmt.pix.field, sizeof(struct videobuf_buffer), fh, NULL); fh->io_allowed = 1; vpfe_dev->io_usrs = 1; INIT_LIST_HEAD(&vpfe_dev->dma_queue); ret = videobuf_reqbufs(&vpfe_dev->buffer_queue, req_buf); unlock_out: mutex_unlock(&vpfe_dev->lock); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri21797.75%133.33%
Vaibhav Hiremath31.35%133.33%
Hans Verkuil20.90%133.33%
Total222100.00%3100.00%


static int vpfe_querybuf(struct file *file, void *priv, struct v4l2_buffer *buf) { struct vpfe_device *vpfe_dev = video_drvdata(file); v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_querybuf\n"); if (V4L2_BUF_TYPE_VIDEO_CAPTURE != buf->type) { v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf type\n"); return -EINVAL; } if (vpfe_dev->memory != V4L2_MEMORY_MMAP) { v4l2_err(&vpfe_dev->v4l2_dev, "Invalid memory\n"); return -EINVAL; } /* Call videobuf_querybuf to get information */ return videobuf_querybuf(&vpfe_dev->buffer_queue, buf); }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri104100.00%1100.00%
Total104100.00%1100.00%


static int vpfe_qbuf(struct file *file, void *priv, struct v4l2_buffer *p) { struct vpfe_device *vpfe_dev = video_drvdata(file); struct vpfe_fh *fh = file->private_data; v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_qbuf\n"); if (V4L2_BUF_TYPE_VIDEO_CAPTURE != p->type) { v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf type\n"); return -EINVAL; } /* * If this file handle is not allowed to do IO, * return error */ if (!fh->io_allowed) { v4l2_err(&vpfe_dev->v4l2_dev, "fh->io_allowed\n"); return -EACCES; } return videobuf_qbuf(&vpfe_dev->buffer_queue, p); }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri112100.00%1100.00%
Total112100.00%1100.00%


static int vpfe_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) { struct vpfe_device *vpfe_dev = video_drvdata(file); v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_dqbuf\n"); if (V4L2_BUF_TYPE_VIDEO_CAPTURE != buf->type) { v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf type\n"); return -EINVAL; } return videobuf_dqbuf(&vpfe_dev->buffer_queue, buf, file->f_flags & O_NONBLOCK); }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri85100.00%1100.00%
Total85100.00%1100.00%

/* * vpfe_calculate_offsets : This function calculates buffers offset * for top and bottom field */
static void vpfe_calculate_offsets(struct vpfe_device *vpfe_dev) { struct v4l2_rect image_win; v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_calculate_offsets\n"); ccdc_dev->hw_ops.get_image_window(&image_win); vpfe_dev->field_off = image_win.height * image_win.width; }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri51100.00%1100.00%
Total51100.00%1100.00%

/* vpfe_start_ccdc_capture: start streaming in ccdc/isif */
static void vpfe_start_ccdc_capture(struct vpfe_device *vpfe_dev) { ccdc_dev->hw_ops.enable(1); if (ccdc_dev->hw_ops.enable_out_to_sdram) ccdc_dev->hw_ops.enable_out_to_sdram(1); vpfe_dev->started = 1; }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri43100.00%1100.00%
Total43100.00%1100.00%

/* * vpfe_streamon. Assume the DMA queue is not empty. * application is expected to call QBUF before calling * this ioctl. If not, driver returns error */
static int vpfe_streamon(struct file *file, void *priv, enum v4l2_buf_type buf_type) { struct vpfe_device *vpfe_dev = video_drvdata(file); struct vpfe_fh *fh = file->private_data; struct vpfe_subdev_info *sdinfo; unsigned long addr; int ret; v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_streamon\n"); if (V4L2_BUF_TYPE_VIDEO_CAPTURE != buf_type) { v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf type\n"); return -EINVAL; } /* If file handle is not allowed IO, return error */ if (!fh->io_allowed) { v4l2_err(&vpfe_dev->v4l2_dev, "fh->io_allowed\n"); return -EACCES; } sdinfo = vpfe_dev->current_subdev; ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id, video, s_stream, 1); if (ret && (ret != -ENOIOCTLCMD)) { v4l2_err(&vpfe_dev->v4l2_dev, "stream on failed in subdev\n"); return -EINVAL; } /* If buffer queue is empty, return error */ if (list_empty(&vpfe_dev->buffer_queue.stream)) { v4l2_err(&vpfe_dev->v4l2_dev, "buffer queue is empty\n"); return -EIO; } /* Call videobuf_streamon to start streaming * in videobuf */ ret = videobuf_streamon(&vpfe_dev->buffer_queue); if (ret) return ret; ret = mutex_lock_interruptible(&vpfe_dev->lock); if (ret) goto streamoff; /* Get the next frame from the buffer queue */ vpfe_dev->next_frm = list_entry(vpfe_dev->dma_queue.next, struct videobuf_buffer, queue); vpfe_dev->cur_frm = vpfe_dev->next_frm; /* Remove buffer from the buffer queue */ list_del(&vpfe_dev->cur_frm->queue); /* Mark state of the current frame to active */ vpfe_dev->cur_frm->state = VIDEOBUF_ACTIVE; /* Initialize field_id and started member */ vpfe_dev->field_id = 0; addr = videobuf_to_dma_contig(vpfe_dev->cur_frm); /* Calculate field offset */ vpfe_calculate_offsets(vpfe_dev); if (vpfe_attach_irq(vpfe_dev) < 0) { v4l2_err(&vpfe_dev->v4l2_dev, "Error in attaching interrupt handle\n"); ret = -EFAULT; goto unlock_out; } if (ccdc_dev->hw_ops.configure() < 0) { v4l2_err(&vpfe_dev->v4l2_dev, "Error in configuring ccdc\n"); ret = -EINVAL; goto unlock_out; } ccdc_dev->hw_ops.setfbaddr((unsigned long)(addr)); vpfe_start_ccdc_capture(vpfe_dev); mutex_unlock(&vpfe_dev->lock); return ret; unlock_out: mutex_unlock(&vpfe_dev->lock); streamoff: ret = videobuf_streamoff(&vpfe_dev->buffer_queue); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri412100.00%1100.00%
Total412100.00%1100.00%


static int vpfe_streamoff(struct file *file, void *priv, enum v4l2_buf_type buf_type) { struct vpfe_device *vpfe_dev = video_drvdata(file); struct vpfe_fh *fh = file->private_data; struct vpfe_subdev_info *sdinfo; int ret; v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_streamoff\n"); if (V4L2_BUF_TYPE_VIDEO_CAPTURE != buf_type) { v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf type\n"); return -EINVAL; } /* If io is allowed for this file handle, return error */ if (!fh->io_allowed) { v4l2_err(&vpfe_dev->v4l2_dev, "fh->io_allowed\n"); return -EACCES; } /* If streaming is not started, return error */ if (!vpfe_dev->started) { v4l2_err(&vpfe_dev->v4l2_dev, "device started\n"); return -EINVAL; } ret = mutex_lock_interruptible(&vpfe_dev->lock); if (ret) return ret; vpfe_stop_ccdc_capture(vpfe_dev); vpfe_detach_irq(vpfe_dev); sdinfo = vpfe_dev->current_subdev; ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id, video, s_stream, 0); if (ret && (ret != -ENOIOCTLCMD)) v4l2_err(&vpfe_dev->v4l2_dev, "stream off failed in subdev\n"); ret = videobuf_streamoff(&vpfe_dev->buffer_queue); mutex_unlock(&vpfe_dev->lock); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri225100.00%1100.00%
Total225100.00%1100.00%


static int vpfe_cropcap(struct file *file, void *priv, struct v4l2_cropcap *crop) { struct vpfe_device *vpfe_dev = video_drvdata(file); v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_cropcap\n"); if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; /* If std_index is invalid, then just return (== 1:1 aspect) */ if (vpfe_dev->std_index >= ARRAY_SIZE(vpfe_standards)) return 0; crop->pixelaspect = vpfe_standards[vpfe_dev->std_index].pixelaspect; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri7282.76%133.33%
Hans Verkuil1416.09%133.33%
Roel Kluin11.15%133.33%
Total87100.00%3100.00%


static int vpfe_g_selection(struct file *file, void *priv, struct v4l2_selection *sel) { struct vpfe_device *vpfe_dev = video_drvdata(file); v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_g_selection\n"); if (sel->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; switch (sel->target) { case V4L2_SEL_TGT_CROP: sel->r = vpfe_dev->crop; break; case V4L2_SEL_TGT_CROP_DEFAULT: case V4L2_SEL_TGT_CROP_BOUNDS: sel->r.width = vpfe_standards[vpfe_dev->std_index].width; sel->r.height = vpfe_standards[vpfe_dev->std_index].height; break; default: return -EINVAL; } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Hans Verkuil7259.50%150.00%
Murali Karicheri4940.50%150.00%
Total121100.00%2100.00%


static int vpfe_s_selection(struct file *file, void *priv, struct v4l2_selection *sel) { struct vpfe_device *vpfe_dev = video_drvdata(file); struct v4l2_rect rect = sel->r; int ret; v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_selection\n"); if (sel->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || sel->target != V4L2_SEL_TGT_CROP) return -EINVAL; if (vpfe_dev->started) { /* make sure streaming is not started */ v4l2_err(&vpfe_dev->v4l2_dev, "Cannot change crop when streaming is ON\n"); return -EBUSY; } ret = mutex_lock_interruptible(&vpfe_dev->lock); if (ret) return ret; if (rect.top < 0 || rect.left < 0) { v4l2_err(&vpfe_dev->v4l2_dev, "doesn't support negative values for top & left\n"); ret = -EINVAL; goto unlock_out; } /* adjust the width to 16 pixel boundary */ rect.width = ((rect.width + 15) & ~0xf); /* make sure parameters are valid */ if ((rect.left + rect.width > vpfe_dev->std_info.active_pixels) || (rect.top + rect.height > vpfe_dev->std_info.active_lines)) { v4l2_err(&vpfe_dev->v4l2_dev, "Error in S_SELECTION params\n"); ret = -EINVAL; goto unlock_out; } ccdc_dev->hw_ops.set_image_window(&rect); vpfe_dev->fmt.fmt.pix.width = rect.width; vpfe_dev->fmt.fmt.pix.height = rect.height; vpfe_dev->fmt.fmt.pix.bytesperline = ccdc_dev->hw_ops.get_line_length(); vpfe_dev->fmt.fmt.pix.sizeimage = vpfe_dev->fmt.fmt.pix.bytesperline * vpfe_dev->fmt.fmt.pix.height; vpfe_dev->crop = rect; sel->r = rect; unlock_out: mutex_unlock(&vpfe_dev->lock); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri28084.85%125.00%
Hans Verkuil319.39%125.00%
Lad Prabhakar185.45%125.00%
Lucas De Marchi10.30%125.00%
Total330100.00%4100.00%


static long vpfe_param_handler(struct file *file, void *priv, bool valid_prio, unsigned int cmd, void *param) { struct vpfe_device *vpfe_dev = video_drvdata(file); int ret; v4l2_dbg(2, debug, &vpfe_dev->v4l2_dev, "vpfe_param_handler\n"); if (vpfe_dev->started) { /* only allowed if streaming is not started */ v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "device already started\n"); return -EBUSY; } ret = mutex_lock_interruptible(&vpfe_dev->lock); if (ret) return ret; switch (cmd) { case VPFE_CMD_S_CCDC_RAW_PARAMS: v4l2_warn(&vpfe_dev->v4l2_dev, "VPFE_CMD_S_CCDC_RAW_PARAMS: experimental ioctl\n"); if (ccdc_dev->hw_ops.set_params) { ret = ccdc_dev->hw_ops.set_params(param); if (ret) { v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "Error setting parameters in CCDC\n"); goto unlock_out; } ret = vpfe_get_ccdc_image_format(vpfe_dev, &vpfe_dev->fmt); if (ret < 0) { v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "Invalid image format at CCDC\n"); goto unlock_out; } } else { ret = -EINVAL; v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "VPFE_CMD_S_CCDC_RAW_PARAMS not supported\n"); } break; default: ret = -ENOTTY; } unlock_out: mutex_unlock(&vpfe_dev->lock); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri22895.40%233.33%
Peter Senna Tschudin62.51%116.67%
Hans Verkuil41.67%233.33%
Mauro Carvalho Chehab10.42%116.67%
Total239100.00%6100.00%

/* vpfe capture ioctl operations */ static const struct v4l2_ioctl_ops vpfe_ioctl_ops = { .vidioc_querycap = vpfe_querycap, .vidioc_g_fmt_vid_cap = vpfe_g_fmt_vid_cap, .vidioc_enum_fmt_vid_cap = vpfe_enum_fmt_vid_cap, .vidioc_s_fmt_vid_cap = vpfe_s_fmt_vid_cap, .vidioc_try_fmt_vid_cap = vpfe_try_fmt_vid_cap, .vidioc_enum_input = vpfe_enum_input, .vidioc_g_input = vpfe_g_input, .vidioc_s_input = vpfe_s_input, .vidioc_querystd = vpfe_querystd, .vidioc_s_std = vpfe_s_std, .vidioc_g_std = vpfe_g_std, .vidioc_reqbufs = vpfe_reqbufs, .vidioc_querybuf = vpfe_querybuf, .vidioc_qbuf = vpfe_qbuf, .vidioc_dqbuf = vpfe_dqbuf, .vidioc_streamon = vpfe_streamon, .vidioc_streamoff = vpfe_streamoff, .vidioc_cropcap = vpfe_cropcap, .vidioc_g_selection = vpfe_g_selection, .vidioc_s_selection = vpfe_s_selection, .vidioc_default = vpfe_param_handler, };
static struct vpfe_device *vpfe_initialize(void) { struct vpfe_device *vpfe_dev; /* Default number of buffers should be 3 */ if ((numbuffers > 0) && (numbuffers < config_params.min_numbuffers)) numbuffers = config_params.min_numbuffers; /* * Set buffer size to min buffers size if invalid buffer size is * given */ if (bufsize < config_params.min_bufsize) bufsize = config_params.min_bufsize; config_params.numbuffers = numbuffers; if (numbuffers) config_params.device_bufsize = bufsize; /* Allocate memory for device objects */ vpfe_dev = kzalloc(sizeof(*vpfe_dev), GFP_KERNEL); return vpfe_dev; }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri86100.00%1100.00%
Total86100.00%1100.00%

/* * vpfe_probe : This function creates device entries by register * itself to the V4L2 driver and initializes fields of each * device objects */
static int vpfe_probe(struct platform_device *pdev) { struct vpfe_subdev_info *sdinfo; struct vpfe_config *vpfe_cfg; struct resource *res1; struct vpfe_device *vpfe_dev; struct i2c_adapter *i2c_adap; struct video_device *vfd; int ret, i, j; int num_subdevs = 0; /* Get the pointer to the device object */ vpfe_dev = vpfe_initialize(); if (!vpfe_dev) { v4l2_err(pdev->dev.driver, "Failed to allocate memory for vpfe_dev\n"); return -ENOMEM; } vpfe_dev->pdev = &pdev->dev; if (!pdev->dev.platform_data) { v4l2_err(pdev->dev.driver, "Unable to get vpfe config\n"); ret = -ENODEV; goto probe_free_dev_mem; } vpfe_cfg = pdev->dev.platform_data; vpfe_dev->cfg = vpfe_cfg; if (!vpfe_cfg->ccdc || !vpfe_cfg->card_name || !vpfe_cfg->sub_devs) { v4l2_err(pdev->dev.driver, "null ptr in vpfe_cfg\n"); ret = -ENOENT; goto probe_free_dev_mem; } /* Allocate memory for ccdc configuration */ ccdc_cfg = kmalloc(sizeof(*ccdc_cfg), GFP_KERNEL); if (!ccdc_cfg) { ret = -ENOMEM; goto probe_free_dev_mem; } mutex_lock(&ccdc_lock); strncpy(ccdc_cfg->name, vpfe_cfg->ccdc, 32); /* Get VINT0 irq resource */ res1 = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (!res1) { v4l2_err(pdev->dev.driver, "Unable to get interrupt for VINT0\n"); ret = -ENODEV; goto probe_free_ccdc_cfg_mem; } vpfe_dev->ccdc_irq0 = res1->start; /* Get VINT1 irq resource */ res1 = platform_get_resource(pdev, IORESOURCE_IRQ, 1); if (!res1) { v4l2_err(pdev->dev.driver, "Unable to get interrupt for VINT1\n"); ret = -ENODEV; goto probe_free_ccdc_cfg_mem; } vpfe_dev->ccdc_irq1 = res1->start; ret = request_irq(vpfe_dev->ccdc_irq0, vpfe_isr, 0, "vpfe_capture0", vpfe_dev); if (0 != ret) { v4l2_err(pdev->dev.driver, "Unable to request interrupt\n"); goto probe_free_ccdc_cfg_mem; } vfd = &vpfe_dev->video_dev; /* Initialize field of video device */ vfd->release = video_device_release_empty; vfd->fops = &vpfe_fops; vfd->ioctl_ops = &vpfe_ioctl_ops; vfd->tvnorms = 0; vfd->v4l2_dev = &vpfe_dev->v4l2_dev; snprintf(vfd->name, sizeof(vfd->name), "%s_V%d.%d.%d", CAPTURE_DRV_NAME, (VPFE_CAPTURE_VERSION_CODE >> 16) & 0xff, (VPFE_CAPTURE_VERSION_CODE >> 8) & 0xff, (VPFE_CAPTURE_VERSION_CODE) & 0xff); ret = v4l2_device_register(&pdev->dev, &vpfe_dev->v4l2_dev); if (ret) { v4l2_err(pdev->dev.driver, "Unable to register v4l2 device.\n"); goto probe_out_release_irq; } v4l2_info(&vpfe_dev->v4l2_dev, "v4l2 device registered\n"); spin_lock_init(&vpfe_dev->irqlock); spin_lock_init(&vpfe_dev->dma_queue_lock); mutex_init(&vpfe_dev->lock); /* Initialize field of the device objects */ vpfe_dev->numbuffers = config_params.numbuffers; /* register video device */ v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "trying to register vpfe device.\n"); v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "video_dev=%p\n", &vpfe_dev->video_dev); vpfe_dev->fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ret = video_register_device(&vpfe_dev->video_dev, VFL_TYPE_GRABBER, -1); if (ret) { v4l2_err(pdev->dev.driver, "Unable to register video device.\n"); goto probe_out_v4l2_unregister; } v4l2_info(&vpfe_dev->v4l2_dev, "video device registered\n"); /* set the driver data in platform device */ platform_set_drvdata(pdev, vpfe_dev); /* set driver private data */ video_set_drvdata(&vpfe_dev->video_dev, vpfe_dev); i2c_adap = i2c_get_adapter(vpfe_cfg->i2c_adapter_id); num_subdevs = vpfe_cfg->num_subdevs; vpfe_dev->sd = kmalloc_array(num_subdevs, sizeof(*vpfe_dev->sd), GFP_KERNEL); if (!vpfe_dev->sd) { ret = -ENOMEM; goto probe_out_video_unregister; } for (i = 0; i < num_subdevs; i++) { struct v4l2_input *inps; sdinfo = &vpfe_cfg->sub_devs[i]; /* Load up the subdevice */ vpfe_dev->sd[i] = v4l2_i2c_new_subdev_board(&vpfe_dev->v4l2_dev, i2c_adap, &sdinfo->board_info, NULL); if (vpfe_dev->sd[i]) { v4l2_info(&vpfe_dev->v4l2_dev, "v4l2 sub device %s registered\n", sdinfo->name); vpfe_dev->sd[i]->grp_id = sdinfo->grp_id; /* update tvnorms from the sub devices */ for (j = 0; j < sdinfo->num_inputs; j++) { inps = &sdinfo->inputs[j]; vfd->tvnorms |= inps->std; } } else { v4l2_info(&vpfe_dev->v4l2_dev, "v4l2 sub device %s register fails\n", sdinfo->name); ret = -ENXIO; goto probe_sd_out; } } /* set first sub device as current one */ vpfe_dev->current_subdev = &vpfe_cfg->sub_devs[0]; vpfe_dev->v4l2_dev.ctrl_handler = vpfe_dev->sd[0]->ctrl_handler; /* We have at least one sub device to work with */ mutex_unlock(&ccdc_lock); return 0; probe_sd_out: kfree(vpfe_dev->sd); probe_out_video_unregister: video_unregister_device(&vpfe_dev->video_dev); probe_out_v4l2_unregister: v4l2_device_unregister(&vpfe_dev->v4l2_dev); probe_out_release_irq: free_irq(vpfe_dev->ccdc_irq0, vpfe_dev); probe_free_ccdc_cfg_mem: kfree(ccdc_cfg); mutex_unlock(&ccdc_lock); probe_free_dev_mem: kfree(vpfe_dev); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri86293.29%317.65%
Hans Verkuil222.38%211.76%
SF Markus Elfring161.73%529.41%
Lad Prabhakar90.97%211.76%
Dan Carpenter60.65%15.88%
Arnd Bergmann50.54%15.88%
Vaibhav Hiremath20.22%15.88%
Mauro Carvalho Chehab10.11%15.88%
Michael Opdenacker10.11%15.88%
Total924100.00%17100.00%

/* * vpfe_remove : It un-register device from V4L2 driver */
static int vpfe_remove(struct platform_device *pdev) { struct vpfe_device *vpfe_dev = platform_get_drvdata(pdev); v4l2_info(pdev->dev.driver, "vpfe_remove\n"); free_irq(vpfe_dev->ccdc_irq0, vpfe_dev); kfree(vpfe_dev->sd); v4l2_device_unregister(&vpfe_dev->v4l2_dev); video_unregister_device(&vpfe_dev->video_dev); kfree(vpfe_dev); kfree(ccdc_cfg); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri7698.70%150.00%
Lad Prabhakar11.30%150.00%
Total77100.00%2100.00%


static int vpfe_suspend(struct device *dev) { return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri1392.86%150.00%
Vaibhav Hiremath17.14%150.00%
Total14100.00%2100.00%


static int vpfe_resume(struct device *dev) { return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri1392.86%150.00%
Vaibhav Hiremath17.14%150.00%
Total14100.00%2100.00%

static const struct dev_pm_ops vpfe_dev_pm_ops = { .suspend = vpfe_suspend, .resume = vpfe_resume, }; static struct platform_driver vpfe_driver = { .driver = { .name = CAPTURE_DRV_NAME, .pm = &vpfe_dev_pm_ops, }, .probe = vpfe_probe, .remove = vpfe_remove, }; module_platform_driver(vpfe_driver);

Overall Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri841792.50%47.55%
Hans Verkuil2893.18%916.98%
Vaibhav Hiremath2182.40%611.32%
Lad Prabhakar780.86%611.32%
SF Markus Elfring380.42%815.09%
Shailendra Verma130.14%11.89%
Peter Senna Tschudin120.13%11.89%
Dan Carpenter70.08%23.77%
Mauro Carvalho Chehab50.05%47.55%
Arnd Bergmann50.05%11.89%
Tejun Heo30.03%11.89%
Sakari Ailus30.03%23.77%
Michael Opdenacker20.02%11.89%
Axel Lin20.02%11.89%
Boris Brezillon20.02%11.89%
Fengguang Wu10.01%11.89%
Alexey Dobriyan10.01%11.89%
Laurent Pinchart10.01%11.89%
Roel Kluin10.01%11.89%
Lucas De Marchi10.01%11.89%
Total9099100.00%53100.00%
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.