Path: blob/master/drivers/media/video/davinci/vpfe_capture.c
17613 views
/*1* Copyright (C) 2008-2009 Texas Instruments Inc2*3* This program is free software; you can redistribute it and/or modify4* it under the terms of the GNU General Public License as published by5* the Free Software Foundation; either version 2 of the License, or6* (at your option) any later version.7*8* This program is distributed in the hope that it will be useful,9* but WITHOUT ANY WARRANTY; without even the implied warranty of10* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the11* GNU General Public License for more details.12*13* You should have received a copy of the GNU General Public License14* along with this program; if not, write to the Free Software15* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA16*17* Driver name : VPFE Capture driver18* VPFE Capture driver allows applications to capture and stream video19* frames on DaVinci SoCs (DM6446, DM355 etc) from a YUV source such as20* TVP5146 or Raw Bayer RGB image data from an image sensor21* such as Microns' MT9T001, MT9T031 etc.22*23* These SoCs have, in common, a Video Processing Subsystem (VPSS) that24* consists of a Video Processing Front End (VPFE) for capturing25* video/raw image data and Video Processing Back End (VPBE) for displaying26* YUV data through an in-built analog encoder or Digital LCD port. This27* driver is for capture through VPFE. A typical EVM using these SoCs have28* following high level configuration.29*30*31* decoder(TVP5146/ YUV/32* MT9T001) --> Raw Bayer RGB ---> MUX -> VPFE (CCDC/ISIF)33* data input | |34* V |35* SDRAM |36* V37* Image Processor38* |39* V40* SDRAM41* The data flow happens from a decoder connected to the VPFE over a42* YUV embedded (BT.656/BT.1120) or separate sync or raw bayer rgb interface43* and to the input of VPFE through an optional MUX (if more inputs are44* to be interfaced on the EVM). The input data is first passed through45* CCDC (CCD Controller, a.k.a Image Sensor Interface, ISIF). The CCDC46* does very little or no processing on YUV data and does pre-process Raw47* Bayer RGB data through modules such as Defect Pixel Correction (DFC)48* Color Space Conversion (CSC), data gain/offset etc. After this, data49* can be written to SDRAM or can be connected to the image processing50* block such as IPIPE (on DM355 only).51*52* Features supported53* - MMAP IO54* - Capture using TVP5146 over BT.65655* - support for interfacing decoders using sub device model56* - Work with DM355 or DM6446 CCDC to do Raw Bayer RGB/YUV57* data capture to SDRAM.58* TODO list59* - Support multiple REQBUF after open60* - Support for de-allocating buffers through REQBUF61* - Support for Raw Bayer RGB capture62* - Support for chaining Image Processor63* - Support for static allocation of buffers64* - Support for USERPTR IO65* - Support for STREAMON before QBUF66* - Support for control ioctls67*/68#include <linux/module.h>69#include <linux/slab.h>70#include <linux/init.h>71#include <linux/platform_device.h>72#include <linux/interrupt.h>73#include <media/v4l2-common.h>74#include <linux/io.h>75#include <media/davinci/vpfe_capture.h>76#include "ccdc_hw_device.h"7778static int debug;79static u32 numbuffers = 3;80static u32 bufsize = (720 * 576 * 2);8182module_param(numbuffers, uint, S_IRUGO);83module_param(bufsize, uint, S_IRUGO);84module_param(debug, int, 0644);8586MODULE_PARM_DESC(numbuffers, "buffer count (default:3)");87MODULE_PARM_DESC(bufsize, "buffer size in bytes (default:720 x 576 x 2)");88MODULE_PARM_DESC(debug, "Debug level 0-1");8990MODULE_DESCRIPTION("VPFE Video for Linux Capture Driver");91MODULE_LICENSE("GPL");92MODULE_AUTHOR("Texas Instruments");9394/* standard information */95struct vpfe_standard {96v4l2_std_id std_id;97unsigned int width;98unsigned int height;99struct v4l2_fract pixelaspect;100/* 0 - progressive, 1 - interlaced */101int frame_format;102};103104/* ccdc configuration */105struct ccdc_config {106/* This make sure vpfe is probed and ready to go */107int vpfe_probed;108/* name of ccdc device */109char name[32];110};111112/* data structures */113static struct vpfe_config_params config_params = {114.min_numbuffers = 3,115.numbuffers = 3,116.min_bufsize = 720 * 480 * 2,117.device_bufsize = 720 * 576 * 2,118};119120/* ccdc device registered */121static struct ccdc_hw_device *ccdc_dev;122/* lock for accessing ccdc information */123static DEFINE_MUTEX(ccdc_lock);124/* ccdc configuration */125static struct ccdc_config *ccdc_cfg;126127const struct vpfe_standard vpfe_standards[] = {128{V4L2_STD_525_60, 720, 480, {11, 10}, 1},129{V4L2_STD_625_50, 720, 576, {54, 59}, 1},130};131132/* Used when raw Bayer image from ccdc is directly captured to SDRAM */133static const struct vpfe_pixel_format vpfe_pix_fmts[] = {134{135.fmtdesc = {136.index = 0,137.type = V4L2_BUF_TYPE_VIDEO_CAPTURE,138.description = "Bayer GrRBGb 8bit A-Law compr.",139.pixelformat = V4L2_PIX_FMT_SBGGR8,140},141.bpp = 1,142},143{144.fmtdesc = {145.index = 1,146.type = V4L2_BUF_TYPE_VIDEO_CAPTURE,147.description = "Bayer GrRBGb - 16bit",148.pixelformat = V4L2_PIX_FMT_SBGGR16,149},150.bpp = 2,151},152{153.fmtdesc = {154.index = 2,155.type = V4L2_BUF_TYPE_VIDEO_CAPTURE,156.description = "Bayer GrRBGb 8bit DPCM compr.",157.pixelformat = V4L2_PIX_FMT_SGRBG10DPCM8,158},159.bpp = 1,160},161{162.fmtdesc = {163.index = 3,164.type = V4L2_BUF_TYPE_VIDEO_CAPTURE,165.description = "YCbCr 4:2:2 Interleaved UYVY",166.pixelformat = V4L2_PIX_FMT_UYVY,167},168.bpp = 2,169},170{171.fmtdesc = {172.index = 4,173.type = V4L2_BUF_TYPE_VIDEO_CAPTURE,174.description = "YCbCr 4:2:2 Interleaved YUYV",175.pixelformat = V4L2_PIX_FMT_YUYV,176},177.bpp = 2,178},179{180.fmtdesc = {181.index = 5,182.type = V4L2_BUF_TYPE_VIDEO_CAPTURE,183.description = "Y/CbCr 4:2:0 - Semi planar",184.pixelformat = V4L2_PIX_FMT_NV12,185},186.bpp = 1,187},188};189190/*191* vpfe_lookup_pix_format()192* lookup an entry in the vpfe pix format table based on pix_format193*/194static const struct vpfe_pixel_format *vpfe_lookup_pix_format(u32 pix_format)195{196int i;197198for (i = 0; i < ARRAY_SIZE(vpfe_pix_fmts); i++) {199if (pix_format == vpfe_pix_fmts[i].fmtdesc.pixelformat)200return &vpfe_pix_fmts[i];201}202return NULL;203}204205/*206* vpfe_register_ccdc_device. CCDC module calls this to207* register with vpfe capture208*/209int vpfe_register_ccdc_device(struct ccdc_hw_device *dev)210{211int ret = 0;212printk(KERN_NOTICE "vpfe_register_ccdc_device: %s\n", dev->name);213214BUG_ON(!dev->hw_ops.open);215BUG_ON(!dev->hw_ops.enable);216BUG_ON(!dev->hw_ops.set_hw_if_params);217BUG_ON(!dev->hw_ops.configure);218BUG_ON(!dev->hw_ops.set_buftype);219BUG_ON(!dev->hw_ops.get_buftype);220BUG_ON(!dev->hw_ops.enum_pix);221BUG_ON(!dev->hw_ops.set_frame_format);222BUG_ON(!dev->hw_ops.get_frame_format);223BUG_ON(!dev->hw_ops.get_pixel_format);224BUG_ON(!dev->hw_ops.set_pixel_format);225BUG_ON(!dev->hw_ops.set_image_window);226BUG_ON(!dev->hw_ops.get_image_window);227BUG_ON(!dev->hw_ops.get_line_length);228BUG_ON(!dev->hw_ops.getfid);229230mutex_lock(&ccdc_lock);231if (NULL == ccdc_cfg) {232/*233* TODO. Will this ever happen? if so, we need to fix it.234* Proabably we need to add the request to a linked list and235* walk through it during vpfe probe236*/237printk(KERN_ERR "vpfe capture not initialized\n");238ret = -EFAULT;239goto unlock;240}241242if (strcmp(dev->name, ccdc_cfg->name)) {243/* ignore this ccdc */244ret = -EINVAL;245goto unlock;246}247248if (ccdc_dev) {249printk(KERN_ERR "ccdc already registered\n");250ret = -EINVAL;251goto unlock;252}253254ccdc_dev = dev;255unlock:256mutex_unlock(&ccdc_lock);257return ret;258}259EXPORT_SYMBOL(vpfe_register_ccdc_device);260261/*262* vpfe_unregister_ccdc_device. CCDC module calls this to263* unregister with vpfe capture264*/265void vpfe_unregister_ccdc_device(struct ccdc_hw_device *dev)266{267if (NULL == dev) {268printk(KERN_ERR "invalid ccdc device ptr\n");269return;270}271272printk(KERN_NOTICE "vpfe_unregister_ccdc_device, dev->name = %s\n",273dev->name);274275if (strcmp(dev->name, ccdc_cfg->name)) {276/* ignore this ccdc */277return;278}279280mutex_lock(&ccdc_lock);281ccdc_dev = NULL;282mutex_unlock(&ccdc_lock);283return;284}285EXPORT_SYMBOL(vpfe_unregister_ccdc_device);286287/*288* vpfe_get_ccdc_image_format - Get image parameters based on CCDC settings289*/290static int vpfe_get_ccdc_image_format(struct vpfe_device *vpfe_dev,291struct v4l2_format *f)292{293struct v4l2_rect image_win;294enum ccdc_buftype buf_type;295enum ccdc_frmfmt frm_fmt;296297memset(f, 0, sizeof(*f));298f->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;299ccdc_dev->hw_ops.get_image_window(&image_win);300f->fmt.pix.width = image_win.width;301f->fmt.pix.height = image_win.height;302f->fmt.pix.bytesperline = ccdc_dev->hw_ops.get_line_length();303f->fmt.pix.sizeimage = f->fmt.pix.bytesperline *304f->fmt.pix.height;305buf_type = ccdc_dev->hw_ops.get_buftype();306f->fmt.pix.pixelformat = ccdc_dev->hw_ops.get_pixel_format();307frm_fmt = ccdc_dev->hw_ops.get_frame_format();308if (frm_fmt == CCDC_FRMFMT_PROGRESSIVE)309f->fmt.pix.field = V4L2_FIELD_NONE;310else if (frm_fmt == CCDC_FRMFMT_INTERLACED) {311if (buf_type == CCDC_BUFTYPE_FLD_INTERLEAVED)312f->fmt.pix.field = V4L2_FIELD_INTERLACED;313else if (buf_type == CCDC_BUFTYPE_FLD_SEPARATED)314f->fmt.pix.field = V4L2_FIELD_SEQ_TB;315else {316v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf_type\n");317return -EINVAL;318}319} else {320v4l2_err(&vpfe_dev->v4l2_dev, "Invalid frm_fmt\n");321return -EINVAL;322}323return 0;324}325326/*327* vpfe_config_ccdc_image_format()328* For a pix format, configure ccdc to setup the capture329*/330static int vpfe_config_ccdc_image_format(struct vpfe_device *vpfe_dev)331{332enum ccdc_frmfmt frm_fmt = CCDC_FRMFMT_INTERLACED;333int ret = 0;334335if (ccdc_dev->hw_ops.set_pixel_format(336vpfe_dev->fmt.fmt.pix.pixelformat) < 0) {337v4l2_err(&vpfe_dev->v4l2_dev,338"couldn't set pix format in ccdc\n");339return -EINVAL;340}341/* configure the image window */342ccdc_dev->hw_ops.set_image_window(&vpfe_dev->crop);343344switch (vpfe_dev->fmt.fmt.pix.field) {345case V4L2_FIELD_INTERLACED:346/* do nothing, since it is default */347ret = ccdc_dev->hw_ops.set_buftype(348CCDC_BUFTYPE_FLD_INTERLEAVED);349break;350case V4L2_FIELD_NONE:351frm_fmt = CCDC_FRMFMT_PROGRESSIVE;352/* buffer type only applicable for interlaced scan */353break;354case V4L2_FIELD_SEQ_TB:355ret = ccdc_dev->hw_ops.set_buftype(356CCDC_BUFTYPE_FLD_SEPARATED);357break;358default:359return -EINVAL;360}361362/* set the frame format */363if (!ret)364ret = ccdc_dev->hw_ops.set_frame_format(frm_fmt);365return ret;366}367/*368* vpfe_config_image_format()369* For a given standard, this functions sets up the default370* pix format & crop values in the vpfe device and ccdc. It first371* starts with defaults based values from the standard table.372* It then checks if sub device support g_mbus_fmt and then override the373* values based on that.Sets crop values to match with scan resolution374* starting at 0,0. It calls vpfe_config_ccdc_image_format() set the375* values in ccdc376*/377static int vpfe_config_image_format(struct vpfe_device *vpfe_dev,378const v4l2_std_id *std_id)379{380struct vpfe_subdev_info *sdinfo = vpfe_dev->current_subdev;381struct v4l2_mbus_framefmt mbus_fmt;382struct v4l2_pix_format *pix = &vpfe_dev->fmt.fmt.pix;383int i, ret = 0;384385for (i = 0; i < ARRAY_SIZE(vpfe_standards); i++) {386if (vpfe_standards[i].std_id & *std_id) {387vpfe_dev->std_info.active_pixels =388vpfe_standards[i].width;389vpfe_dev->std_info.active_lines =390vpfe_standards[i].height;391vpfe_dev->std_info.frame_format =392vpfe_standards[i].frame_format;393vpfe_dev->std_index = i;394break;395}396}397398if (i == ARRAY_SIZE(vpfe_standards)) {399v4l2_err(&vpfe_dev->v4l2_dev, "standard not supported\n");400return -EINVAL;401}402403vpfe_dev->crop.top = 0;404vpfe_dev->crop.left = 0;405vpfe_dev->crop.width = vpfe_dev->std_info.active_pixels;406vpfe_dev->crop.height = vpfe_dev->std_info.active_lines;407pix->width = vpfe_dev->crop.width;408pix->height = vpfe_dev->crop.height;409410/* first field and frame format based on standard frame format */411if (vpfe_dev->std_info.frame_format) {412pix->field = V4L2_FIELD_INTERLACED;413/* assume V4L2_PIX_FMT_UYVY as default */414pix->pixelformat = V4L2_PIX_FMT_UYVY;415v4l2_fill_mbus_format(&mbus_fmt, pix,416V4L2_MBUS_FMT_YUYV10_2X10);417} else {418pix->field = V4L2_FIELD_NONE;419/* assume V4L2_PIX_FMT_SBGGR8 */420pix->pixelformat = V4L2_PIX_FMT_SBGGR8;421v4l2_fill_mbus_format(&mbus_fmt, pix,422V4L2_MBUS_FMT_SBGGR8_1X8);423}424425/* if sub device supports g_mbus_fmt, override the defaults */426ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev,427sdinfo->grp_id, video, g_mbus_fmt, &mbus_fmt);428429if (ret && ret != -ENOIOCTLCMD) {430v4l2_err(&vpfe_dev->v4l2_dev,431"error in getting g_mbus_fmt from sub device\n");432return ret;433}434v4l2_fill_pix_format(pix, &mbus_fmt);435pix->bytesperline = pix->width * 2;436pix->sizeimage = pix->bytesperline * pix->height;437438/* Sets the values in CCDC */439ret = vpfe_config_ccdc_image_format(vpfe_dev);440if (ret)441return ret;442443/* Update the values of sizeimage and bytesperline */444if (!ret) {445pix->bytesperline = ccdc_dev->hw_ops.get_line_length();446pix->sizeimage = pix->bytesperline * pix->height;447}448return ret;449}450451static int vpfe_initialize_device(struct vpfe_device *vpfe_dev)452{453int ret = 0;454455/* set first input of current subdevice as the current input */456vpfe_dev->current_input = 0;457458/* set default standard */459vpfe_dev->std_index = 0;460461/* Configure the default format information */462ret = vpfe_config_image_format(vpfe_dev,463&vpfe_standards[vpfe_dev->std_index].std_id);464if (ret)465return ret;466467/* now open the ccdc device to initialize it */468mutex_lock(&ccdc_lock);469if (NULL == ccdc_dev) {470v4l2_err(&vpfe_dev->v4l2_dev, "ccdc device not registered\n");471ret = -ENODEV;472goto unlock;473}474475if (!try_module_get(ccdc_dev->owner)) {476v4l2_err(&vpfe_dev->v4l2_dev, "Couldn't lock ccdc module\n");477ret = -ENODEV;478goto unlock;479}480ret = ccdc_dev->hw_ops.open(vpfe_dev->pdev);481if (!ret)482vpfe_dev->initialized = 1;483484/* Clear all VPFE/CCDC interrupts */485if (vpfe_dev->cfg->clr_intr)486vpfe_dev->cfg->clr_intr(-1);487488unlock:489mutex_unlock(&ccdc_lock);490return ret;491}492493/*494* vpfe_open : It creates object of file handle structure and495* stores it in private_data member of filepointer496*/497static int vpfe_open(struct file *file)498{499struct vpfe_device *vpfe_dev = video_drvdata(file);500struct vpfe_fh *fh;501502v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_open\n");503504if (!vpfe_dev->cfg->num_subdevs) {505v4l2_err(&vpfe_dev->v4l2_dev, "No decoder registered\n");506return -ENODEV;507}508509/* Allocate memory for the file handle object */510fh = kmalloc(sizeof(struct vpfe_fh), GFP_KERNEL);511if (NULL == fh) {512v4l2_err(&vpfe_dev->v4l2_dev,513"unable to allocate memory for file handle object\n");514return -ENOMEM;515}516/* store pointer to fh in private_data member of file */517file->private_data = fh;518fh->vpfe_dev = vpfe_dev;519mutex_lock(&vpfe_dev->lock);520/* If decoder is not initialized. initialize it */521if (!vpfe_dev->initialized) {522if (vpfe_initialize_device(vpfe_dev)) {523mutex_unlock(&vpfe_dev->lock);524return -ENODEV;525}526}527/* Increment device usrs counter */528vpfe_dev->usrs++;529/* Set io_allowed member to false */530fh->io_allowed = 0;531/* Initialize priority of this instance to default priority */532fh->prio = V4L2_PRIORITY_UNSET;533v4l2_prio_open(&vpfe_dev->prio, &fh->prio);534mutex_unlock(&vpfe_dev->lock);535return 0;536}537538static void vpfe_schedule_next_buffer(struct vpfe_device *vpfe_dev)539{540unsigned long addr;541542vpfe_dev->next_frm = list_entry(vpfe_dev->dma_queue.next,543struct videobuf_buffer, queue);544list_del(&vpfe_dev->next_frm->queue);545vpfe_dev->next_frm->state = VIDEOBUF_ACTIVE;546addr = videobuf_to_dma_contig(vpfe_dev->next_frm);547548ccdc_dev->hw_ops.setfbaddr(addr);549}550551static void vpfe_schedule_bottom_field(struct vpfe_device *vpfe_dev)552{553unsigned long addr;554555addr = videobuf_to_dma_contig(vpfe_dev->cur_frm);556addr += vpfe_dev->field_off;557ccdc_dev->hw_ops.setfbaddr(addr);558}559560static void vpfe_process_buffer_complete(struct vpfe_device *vpfe_dev)561{562struct timeval timevalue;563564do_gettimeofday(&timevalue);565vpfe_dev->cur_frm->ts = timevalue;566vpfe_dev->cur_frm->state = VIDEOBUF_DONE;567vpfe_dev->cur_frm->size = vpfe_dev->fmt.fmt.pix.sizeimage;568wake_up_interruptible(&vpfe_dev->cur_frm->done);569vpfe_dev->cur_frm = vpfe_dev->next_frm;570}571572/* ISR for VINT0*/573static irqreturn_t vpfe_isr(int irq, void *dev_id)574{575struct vpfe_device *vpfe_dev = dev_id;576enum v4l2_field field;577int fid;578579v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "\nStarting vpfe_isr...\n");580field = vpfe_dev->fmt.fmt.pix.field;581582/* if streaming not started, don't do anything */583if (!vpfe_dev->started)584goto clear_intr;585586/* only for 6446 this will be applicable */587if (NULL != ccdc_dev->hw_ops.reset)588ccdc_dev->hw_ops.reset();589590if (field == V4L2_FIELD_NONE) {591/* handle progressive frame capture */592v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev,593"frame format is progressive...\n");594if (vpfe_dev->cur_frm != vpfe_dev->next_frm)595vpfe_process_buffer_complete(vpfe_dev);596goto clear_intr;597}598599/* interlaced or TB capture check which field we are in hardware */600fid = ccdc_dev->hw_ops.getfid();601602/* switch the software maintained field id */603vpfe_dev->field_id ^= 1;604v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "field id = %x:%x.\n",605fid, vpfe_dev->field_id);606if (fid == vpfe_dev->field_id) {607/* we are in-sync here,continue */608if (fid == 0) {609/*610* One frame is just being captured. If the next frame611* is available, release the current frame and move on612*/613if (vpfe_dev->cur_frm != vpfe_dev->next_frm)614vpfe_process_buffer_complete(vpfe_dev);615/*616* based on whether the two fields are stored617* interleavely or separately in memory, reconfigure618* the CCDC memory address619*/620if (field == V4L2_FIELD_SEQ_TB) {621vpfe_schedule_bottom_field(vpfe_dev);622}623goto clear_intr;624}625/*626* if one field is just being captured configure627* the next frame get the next frame from the empty628* queue if no frame is available hold on to the629* current buffer630*/631spin_lock(&vpfe_dev->dma_queue_lock);632if (!list_empty(&vpfe_dev->dma_queue) &&633vpfe_dev->cur_frm == vpfe_dev->next_frm)634vpfe_schedule_next_buffer(vpfe_dev);635spin_unlock(&vpfe_dev->dma_queue_lock);636} else if (fid == 0) {637/*638* out of sync. Recover from any hardware out-of-sync.639* May loose one frame640*/641vpfe_dev->field_id = fid;642}643clear_intr:644if (vpfe_dev->cfg->clr_intr)645vpfe_dev->cfg->clr_intr(irq);646647return IRQ_HANDLED;648}649650/* vdint1_isr - isr handler for VINT1 interrupt */651static irqreturn_t vdint1_isr(int irq, void *dev_id)652{653struct vpfe_device *vpfe_dev = dev_id;654655v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "\nInside vdint1_isr...\n");656657/* if streaming not started, don't do anything */658if (!vpfe_dev->started) {659if (vpfe_dev->cfg->clr_intr)660vpfe_dev->cfg->clr_intr(irq);661return IRQ_HANDLED;662}663664spin_lock(&vpfe_dev->dma_queue_lock);665if ((vpfe_dev->fmt.fmt.pix.field == V4L2_FIELD_NONE) &&666!list_empty(&vpfe_dev->dma_queue) &&667vpfe_dev->cur_frm == vpfe_dev->next_frm)668vpfe_schedule_next_buffer(vpfe_dev);669spin_unlock(&vpfe_dev->dma_queue_lock);670671if (vpfe_dev->cfg->clr_intr)672vpfe_dev->cfg->clr_intr(irq);673674return IRQ_HANDLED;675}676677static void vpfe_detach_irq(struct vpfe_device *vpfe_dev)678{679enum ccdc_frmfmt frame_format;680681frame_format = ccdc_dev->hw_ops.get_frame_format();682if (frame_format == CCDC_FRMFMT_PROGRESSIVE)683free_irq(vpfe_dev->ccdc_irq1, vpfe_dev);684}685686static int vpfe_attach_irq(struct vpfe_device *vpfe_dev)687{688enum ccdc_frmfmt frame_format;689690frame_format = ccdc_dev->hw_ops.get_frame_format();691if (frame_format == CCDC_FRMFMT_PROGRESSIVE) {692return request_irq(vpfe_dev->ccdc_irq1, vdint1_isr,693IRQF_DISABLED, "vpfe_capture1",694vpfe_dev);695}696return 0;697}698699/* vpfe_stop_ccdc_capture: stop streaming in ccdc/isif */700static void vpfe_stop_ccdc_capture(struct vpfe_device *vpfe_dev)701{702vpfe_dev->started = 0;703ccdc_dev->hw_ops.enable(0);704if (ccdc_dev->hw_ops.enable_out_to_sdram)705ccdc_dev->hw_ops.enable_out_to_sdram(0);706}707708/*709* vpfe_release : This function deletes buffer queue, frees the710* buffers and the vpfe file handle711*/712static int vpfe_release(struct file *file)713{714struct vpfe_device *vpfe_dev = video_drvdata(file);715struct vpfe_fh *fh = file->private_data;716struct vpfe_subdev_info *sdinfo;717int ret;718719v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_release\n");720721/* Get the device lock */722mutex_lock(&vpfe_dev->lock);723/* if this instance is doing IO */724if (fh->io_allowed) {725if (vpfe_dev->started) {726sdinfo = vpfe_dev->current_subdev;727ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev,728sdinfo->grp_id,729video, s_stream, 0);730if (ret && (ret != -ENOIOCTLCMD))731v4l2_err(&vpfe_dev->v4l2_dev,732"stream off failed in subdev\n");733vpfe_stop_ccdc_capture(vpfe_dev);734vpfe_detach_irq(vpfe_dev);735videobuf_streamoff(&vpfe_dev->buffer_queue);736}737vpfe_dev->io_usrs = 0;738vpfe_dev->numbuffers = config_params.numbuffers;739}740741/* Decrement device usrs counter */742vpfe_dev->usrs--;743/* Close the priority */744v4l2_prio_close(&vpfe_dev->prio, fh->prio);745/* If this is the last file handle */746if (!vpfe_dev->usrs) {747vpfe_dev->initialized = 0;748if (ccdc_dev->hw_ops.close)749ccdc_dev->hw_ops.close(vpfe_dev->pdev);750module_put(ccdc_dev->owner);751}752mutex_unlock(&vpfe_dev->lock);753file->private_data = NULL;754/* Free memory allocated to file handle object */755kfree(fh);756return 0;757}758759/*760* vpfe_mmap : It is used to map kernel space buffers761* into user spaces762*/763static int vpfe_mmap(struct file *file, struct vm_area_struct *vma)764{765/* Get the device object and file handle object */766struct vpfe_device *vpfe_dev = video_drvdata(file);767768v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_mmap\n");769770return videobuf_mmap_mapper(&vpfe_dev->buffer_queue, vma);771}772773/*774* vpfe_poll: It is used for select/poll system call775*/776static unsigned int vpfe_poll(struct file *file, poll_table *wait)777{778struct vpfe_device *vpfe_dev = video_drvdata(file);779780v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_poll\n");781782if (vpfe_dev->started)783return videobuf_poll_stream(file,784&vpfe_dev->buffer_queue, wait);785return 0;786}787788/* vpfe capture driver file operations */789static const struct v4l2_file_operations vpfe_fops = {790.owner = THIS_MODULE,791.open = vpfe_open,792.release = vpfe_release,793.unlocked_ioctl = video_ioctl2,794.mmap = vpfe_mmap,795.poll = vpfe_poll796};797798/*799* vpfe_check_format()800* This function adjust the input pixel format as per hardware801* capabilities and update the same in pixfmt.802* Following algorithm used :-803*804* If given pixformat is not in the vpfe list of pix formats or not805* supported by the hardware, current value of pixformat in the device806* is used807* If given field is not supported, then current field is used. If field808* is different from current, then it is matched with that from sub device.809* Minimum height is 2 lines for interlaced or tb field and 1 line for810* progressive. Maximum height is clamped to active active lines of scan811* Minimum width is 32 bytes in memory and width is clamped to active812* pixels of scan.813* bytesperline is a multiple of 32.814*/815static const struct vpfe_pixel_format *816vpfe_check_format(struct vpfe_device *vpfe_dev,817struct v4l2_pix_format *pixfmt)818{819u32 min_height = 1, min_width = 32, max_width, max_height;820const struct vpfe_pixel_format *vpfe_pix_fmt;821u32 pix;822int temp, found;823824vpfe_pix_fmt = vpfe_lookup_pix_format(pixfmt->pixelformat);825if (NULL == vpfe_pix_fmt) {826/*827* use current pixel format in the vpfe device. We828* will find this pix format in the table829*/830pixfmt->pixelformat = vpfe_dev->fmt.fmt.pix.pixelformat;831vpfe_pix_fmt = vpfe_lookup_pix_format(pixfmt->pixelformat);832}833834/* check if hw supports it */835temp = 0;836found = 0;837while (ccdc_dev->hw_ops.enum_pix(&pix, temp) >= 0) {838if (vpfe_pix_fmt->fmtdesc.pixelformat == pix) {839found = 1;840break;841}842temp++;843}844845if (!found) {846/* use current pixel format */847pixfmt->pixelformat = vpfe_dev->fmt.fmt.pix.pixelformat;848/*849* Since this is currently used in the vpfe device, we850* will find this pix format in the table851*/852vpfe_pix_fmt = vpfe_lookup_pix_format(pixfmt->pixelformat);853}854855/* check what field format is supported */856if (pixfmt->field == V4L2_FIELD_ANY) {857/* if field is any, use current value as default */858pixfmt->field = vpfe_dev->fmt.fmt.pix.field;859}860861/*862* if field is not same as current field in the vpfe device863* try matching the field with the sub device field864*/865if (vpfe_dev->fmt.fmt.pix.field != pixfmt->field) {866/*867* If field value is not in the supported fields, use current868* field used in the device as default869*/870switch (pixfmt->field) {871case V4L2_FIELD_INTERLACED:872case V4L2_FIELD_SEQ_TB:873/* if sub device is supporting progressive, use that */874if (!vpfe_dev->std_info.frame_format)875pixfmt->field = V4L2_FIELD_NONE;876break;877case V4L2_FIELD_NONE:878if (vpfe_dev->std_info.frame_format)879pixfmt->field = V4L2_FIELD_INTERLACED;880break;881882default:883/* use current field as default */884pixfmt->field = vpfe_dev->fmt.fmt.pix.field;885break;886}887}888889/* Now adjust image resolutions supported */890if (pixfmt->field == V4L2_FIELD_INTERLACED ||891pixfmt->field == V4L2_FIELD_SEQ_TB)892min_height = 2;893894max_width = vpfe_dev->std_info.active_pixels;895max_height = vpfe_dev->std_info.active_lines;896min_width /= vpfe_pix_fmt->bpp;897898v4l2_info(&vpfe_dev->v4l2_dev, "width = %d, height = %d, bpp = %d\n",899pixfmt->width, pixfmt->height, vpfe_pix_fmt->bpp);900901pixfmt->width = clamp((pixfmt->width), min_width, max_width);902pixfmt->height = clamp((pixfmt->height), min_height, max_height);903904/* If interlaced, adjust height to be a multiple of 2 */905if (pixfmt->field == V4L2_FIELD_INTERLACED)906pixfmt->height &= (~1);907/*908* recalculate bytesperline and sizeimage since width909* and height might have changed910*/911pixfmt->bytesperline = (((pixfmt->width * vpfe_pix_fmt->bpp) + 31)912& ~31);913if (pixfmt->pixelformat == V4L2_PIX_FMT_NV12)914pixfmt->sizeimage =915pixfmt->bytesperline * pixfmt->height +916((pixfmt->bytesperline * pixfmt->height) >> 1);917else918pixfmt->sizeimage = pixfmt->bytesperline * pixfmt->height;919920v4l2_info(&vpfe_dev->v4l2_dev, "adjusted width = %d, height ="921" %d, bpp = %d, bytesperline = %d, sizeimage = %d\n",922pixfmt->width, pixfmt->height, vpfe_pix_fmt->bpp,923pixfmt->bytesperline, pixfmt->sizeimage);924return vpfe_pix_fmt;925}926927static int vpfe_querycap(struct file *file, void *priv,928struct v4l2_capability *cap)929{930struct vpfe_device *vpfe_dev = video_drvdata(file);931932v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_querycap\n");933934cap->version = VPFE_CAPTURE_VERSION_CODE;935cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;936strlcpy(cap->driver, CAPTURE_DRV_NAME, sizeof(cap->driver));937strlcpy(cap->bus_info, "VPFE", sizeof(cap->bus_info));938strlcpy(cap->card, vpfe_dev->cfg->card_name, sizeof(cap->card));939return 0;940}941942static int vpfe_g_fmt_vid_cap(struct file *file, void *priv,943struct v4l2_format *fmt)944{945struct vpfe_device *vpfe_dev = video_drvdata(file);946int ret = 0;947948v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_g_fmt_vid_cap\n");949/* Fill in the information about format */950*fmt = vpfe_dev->fmt;951return ret;952}953954static int vpfe_enum_fmt_vid_cap(struct file *file, void *priv,955struct v4l2_fmtdesc *fmt)956{957struct vpfe_device *vpfe_dev = video_drvdata(file);958const struct vpfe_pixel_format *pix_fmt;959int temp_index;960u32 pix;961962v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_enum_fmt_vid_cap\n");963964if (ccdc_dev->hw_ops.enum_pix(&pix, fmt->index) < 0)965return -EINVAL;966967/* Fill in the information about format */968pix_fmt = vpfe_lookup_pix_format(pix);969if (NULL != pix_fmt) {970temp_index = fmt->index;971*fmt = pix_fmt->fmtdesc;972fmt->index = temp_index;973return 0;974}975return -EINVAL;976}977978static int vpfe_s_fmt_vid_cap(struct file *file, void *priv,979struct v4l2_format *fmt)980{981struct vpfe_device *vpfe_dev = video_drvdata(file);982const struct vpfe_pixel_format *pix_fmts;983int ret = 0;984985v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_fmt_vid_cap\n");986987/* If streaming is started, return error */988if (vpfe_dev->started) {989v4l2_err(&vpfe_dev->v4l2_dev, "Streaming is started\n");990return -EBUSY;991}992993/* Check for valid frame format */994pix_fmts = vpfe_check_format(vpfe_dev, &fmt->fmt.pix);995996if (NULL == pix_fmts)997return -EINVAL;998999/* store the pixel format in the device object */1000ret = mutex_lock_interruptible(&vpfe_dev->lock);1001if (ret)1002return ret;10031004/* First detach any IRQ if currently attached */1005vpfe_detach_irq(vpfe_dev);1006vpfe_dev->fmt = *fmt;1007/* set image capture parameters in the ccdc */1008ret = vpfe_config_ccdc_image_format(vpfe_dev);1009mutex_unlock(&vpfe_dev->lock);1010return ret;1011}10121013static int vpfe_try_fmt_vid_cap(struct file *file, void *priv,1014struct v4l2_format *f)1015{1016struct vpfe_device *vpfe_dev = video_drvdata(file);1017const struct vpfe_pixel_format *pix_fmts;10181019v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_try_fmt_vid_cap\n");10201021pix_fmts = vpfe_check_format(vpfe_dev, &f->fmt.pix);1022if (NULL == pix_fmts)1023return -EINVAL;1024return 0;1025}10261027/*1028* vpfe_get_subdev_input_index - Get subdev index and subdev input index for a1029* given app input index1030*/1031static int vpfe_get_subdev_input_index(struct vpfe_device *vpfe_dev,1032int *subdev_index,1033int *subdev_input_index,1034int app_input_index)1035{1036struct vpfe_config *cfg = vpfe_dev->cfg;1037struct vpfe_subdev_info *sdinfo;1038int i, j = 0;10391040for (i = 0; i < cfg->num_subdevs; i++) {1041sdinfo = &cfg->sub_devs[i];1042if (app_input_index < (j + sdinfo->num_inputs)) {1043*subdev_index = i;1044*subdev_input_index = app_input_index - j;1045return 0;1046}1047j += sdinfo->num_inputs;1048}1049return -EINVAL;1050}10511052/*1053* vpfe_get_app_input - Get app input index for a given subdev input index1054* driver stores the input index of the current sub device and translate it1055* when application request the current input1056*/1057static int vpfe_get_app_input_index(struct vpfe_device *vpfe_dev,1058int *app_input_index)1059{1060struct vpfe_config *cfg = vpfe_dev->cfg;1061struct vpfe_subdev_info *sdinfo;1062int i, j = 0;10631064for (i = 0; i < cfg->num_subdevs; i++) {1065sdinfo = &cfg->sub_devs[i];1066if (!strcmp(sdinfo->name, vpfe_dev->current_subdev->name)) {1067if (vpfe_dev->current_input >= sdinfo->num_inputs)1068return -1;1069*app_input_index = j + vpfe_dev->current_input;1070return 0;1071}1072j += sdinfo->num_inputs;1073}1074return -EINVAL;1075}10761077static int vpfe_enum_input(struct file *file, void *priv,1078struct v4l2_input *inp)1079{1080struct vpfe_device *vpfe_dev = video_drvdata(file);1081struct vpfe_subdev_info *sdinfo;1082int subdev, index ;10831084v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_enum_input\n");10851086if (vpfe_get_subdev_input_index(vpfe_dev,1087&subdev,1088&index,1089inp->index) < 0) {1090v4l2_err(&vpfe_dev->v4l2_dev, "input information not found"1091" for the subdev\n");1092return -EINVAL;1093}1094sdinfo = &vpfe_dev->cfg->sub_devs[subdev];1095memcpy(inp, &sdinfo->inputs[index], sizeof(struct v4l2_input));1096return 0;1097}10981099static int vpfe_g_input(struct file *file, void *priv, unsigned int *index)1100{1101struct vpfe_device *vpfe_dev = video_drvdata(file);11021103v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_g_input\n");11041105return vpfe_get_app_input_index(vpfe_dev, index);1106}110711081109static int vpfe_s_input(struct file *file, void *priv, unsigned int index)1110{1111struct vpfe_device *vpfe_dev = video_drvdata(file);1112struct vpfe_subdev_info *sdinfo;1113int subdev_index, inp_index;1114struct vpfe_route *route;1115u32 input = 0, output = 0;1116int ret = -EINVAL;11171118v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_input\n");11191120ret = mutex_lock_interruptible(&vpfe_dev->lock);1121if (ret)1122return ret;11231124/*1125* If streaming is started return device busy1126* error1127*/1128if (vpfe_dev->started) {1129v4l2_err(&vpfe_dev->v4l2_dev, "Streaming is on\n");1130ret = -EBUSY;1131goto unlock_out;1132}11331134if (vpfe_get_subdev_input_index(vpfe_dev,1135&subdev_index,1136&inp_index,1137index) < 0) {1138v4l2_err(&vpfe_dev->v4l2_dev, "invalid input index\n");1139goto unlock_out;1140}11411142sdinfo = &vpfe_dev->cfg->sub_devs[subdev_index];1143route = &sdinfo->routes[inp_index];1144if (route && sdinfo->can_route) {1145input = route->input;1146output = route->output;1147}11481149ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id,1150video, s_routing, input, output, 0);11511152if (ret) {1153v4l2_err(&vpfe_dev->v4l2_dev,1154"vpfe_doioctl:error in setting input in decoder\n");1155ret = -EINVAL;1156goto unlock_out;1157}1158vpfe_dev->current_subdev = sdinfo;1159vpfe_dev->current_input = index;1160vpfe_dev->std_index = 0;11611162/* set the bus/interface parameter for the sub device in ccdc */1163ret = ccdc_dev->hw_ops.set_hw_if_params(&sdinfo->ccdc_if_params);1164if (ret)1165goto unlock_out;11661167/* set the default image parameters in the device */1168ret = vpfe_config_image_format(vpfe_dev,1169&vpfe_standards[vpfe_dev->std_index].std_id);1170unlock_out:1171mutex_unlock(&vpfe_dev->lock);1172return ret;1173}11741175static int vpfe_querystd(struct file *file, void *priv, v4l2_std_id *std_id)1176{1177struct vpfe_device *vpfe_dev = video_drvdata(file);1178struct vpfe_subdev_info *sdinfo;1179int ret = 0;11801181v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_querystd\n");11821183ret = mutex_lock_interruptible(&vpfe_dev->lock);1184sdinfo = vpfe_dev->current_subdev;1185if (ret)1186return ret;1187/* Call querystd function of decoder device */1188ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id,1189video, querystd, std_id);1190mutex_unlock(&vpfe_dev->lock);1191return ret;1192}11931194static int vpfe_s_std(struct file *file, void *priv, v4l2_std_id *std_id)1195{1196struct vpfe_device *vpfe_dev = video_drvdata(file);1197struct vpfe_subdev_info *sdinfo;1198int ret = 0;11991200v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_std\n");12011202/* Call decoder driver function to set the standard */1203ret = mutex_lock_interruptible(&vpfe_dev->lock);1204if (ret)1205return ret;12061207sdinfo = vpfe_dev->current_subdev;1208/* If streaming is started, return device busy error */1209if (vpfe_dev->started) {1210v4l2_err(&vpfe_dev->v4l2_dev, "streaming is started\n");1211ret = -EBUSY;1212goto unlock_out;1213}12141215ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id,1216core, s_std, *std_id);1217if (ret < 0) {1218v4l2_err(&vpfe_dev->v4l2_dev, "Failed to set standard\n");1219goto unlock_out;1220}1221ret = vpfe_config_image_format(vpfe_dev, std_id);12221223unlock_out:1224mutex_unlock(&vpfe_dev->lock);1225return ret;1226}12271228static int vpfe_g_std(struct file *file, void *priv, v4l2_std_id *std_id)1229{1230struct vpfe_device *vpfe_dev = video_drvdata(file);12311232v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_g_std\n");12331234*std_id = vpfe_standards[vpfe_dev->std_index].std_id;1235return 0;1236}1237/*1238* Videobuf operations1239*/1240static int vpfe_videobuf_setup(struct videobuf_queue *vq,1241unsigned int *count,1242unsigned int *size)1243{1244struct vpfe_fh *fh = vq->priv_data;1245struct vpfe_device *vpfe_dev = fh->vpfe_dev;12461247v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_buffer_setup\n");1248*size = vpfe_dev->fmt.fmt.pix.sizeimage;1249if (vpfe_dev->memory == V4L2_MEMORY_MMAP &&1250vpfe_dev->fmt.fmt.pix.sizeimage > config_params.device_bufsize)1251*size = config_params.device_bufsize;12521253if (*count < config_params.min_numbuffers)1254*count = config_params.min_numbuffers;1255v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev,1256"count=%d, size=%d\n", *count, *size);1257return 0;1258}12591260static int vpfe_videobuf_prepare(struct videobuf_queue *vq,1261struct videobuf_buffer *vb,1262enum v4l2_field field)1263{1264struct vpfe_fh *fh = vq->priv_data;1265struct vpfe_device *vpfe_dev = fh->vpfe_dev;1266unsigned long addr;1267int ret;12681269v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_buffer_prepare\n");12701271/* If buffer is not initialized, initialize it */1272if (VIDEOBUF_NEEDS_INIT == vb->state) {1273vb->width = vpfe_dev->fmt.fmt.pix.width;1274vb->height = vpfe_dev->fmt.fmt.pix.height;1275vb->size = vpfe_dev->fmt.fmt.pix.sizeimage;1276vb->field = field;12771278ret = videobuf_iolock(vq, vb, NULL);1279if (ret < 0)1280return ret;12811282addr = videobuf_to_dma_contig(vb);1283/* Make sure user addresses are aligned to 32 bytes */1284if (!ALIGN(addr, 32))1285return -EINVAL;12861287vb->state = VIDEOBUF_PREPARED;1288}1289return 0;1290}12911292static void vpfe_videobuf_queue(struct videobuf_queue *vq,1293struct videobuf_buffer *vb)1294{1295/* Get the file handle object and device object */1296struct vpfe_fh *fh = vq->priv_data;1297struct vpfe_device *vpfe_dev = fh->vpfe_dev;1298unsigned long flags;12991300v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_buffer_queue\n");13011302/* add the buffer to the DMA queue */1303spin_lock_irqsave(&vpfe_dev->dma_queue_lock, flags);1304list_add_tail(&vb->queue, &vpfe_dev->dma_queue);1305spin_unlock_irqrestore(&vpfe_dev->dma_queue_lock, flags);13061307/* Change state of the buffer */1308vb->state = VIDEOBUF_QUEUED;1309}13101311static void vpfe_videobuf_release(struct videobuf_queue *vq,1312struct videobuf_buffer *vb)1313{1314struct vpfe_fh *fh = vq->priv_data;1315struct vpfe_device *vpfe_dev = fh->vpfe_dev;1316unsigned long flags;13171318v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_videobuf_release\n");13191320/*1321* We need to flush the buffer from the dma queue since1322* they are de-allocated1323*/1324spin_lock_irqsave(&vpfe_dev->dma_queue_lock, flags);1325INIT_LIST_HEAD(&vpfe_dev->dma_queue);1326spin_unlock_irqrestore(&vpfe_dev->dma_queue_lock, flags);1327videobuf_dma_contig_free(vq, vb);1328vb->state = VIDEOBUF_NEEDS_INIT;1329}13301331static struct videobuf_queue_ops vpfe_videobuf_qops = {1332.buf_setup = vpfe_videobuf_setup,1333.buf_prepare = vpfe_videobuf_prepare,1334.buf_queue = vpfe_videobuf_queue,1335.buf_release = vpfe_videobuf_release,1336};13371338/*1339* vpfe_reqbufs. currently support REQBUF only once opening1340* the device.1341*/1342static int vpfe_reqbufs(struct file *file, void *priv,1343struct v4l2_requestbuffers *req_buf)1344{1345struct vpfe_device *vpfe_dev = video_drvdata(file);1346struct vpfe_fh *fh = file->private_data;1347int ret = 0;13481349v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_reqbufs\n");13501351if (V4L2_BUF_TYPE_VIDEO_CAPTURE != req_buf->type) {1352v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buffer type\n");1353return -EINVAL;1354}13551356ret = mutex_lock_interruptible(&vpfe_dev->lock);1357if (ret)1358return ret;13591360if (vpfe_dev->io_usrs != 0) {1361v4l2_err(&vpfe_dev->v4l2_dev, "Only one IO user allowed\n");1362ret = -EBUSY;1363goto unlock_out;1364}13651366vpfe_dev->memory = req_buf->memory;1367videobuf_queue_dma_contig_init(&vpfe_dev->buffer_queue,1368&vpfe_videobuf_qops,1369vpfe_dev->pdev,1370&vpfe_dev->irqlock,1371req_buf->type,1372vpfe_dev->fmt.fmt.pix.field,1373sizeof(struct videobuf_buffer),1374fh, NULL);13751376fh->io_allowed = 1;1377vpfe_dev->io_usrs = 1;1378INIT_LIST_HEAD(&vpfe_dev->dma_queue);1379ret = videobuf_reqbufs(&vpfe_dev->buffer_queue, req_buf);1380unlock_out:1381mutex_unlock(&vpfe_dev->lock);1382return ret;1383}13841385static int vpfe_querybuf(struct file *file, void *priv,1386struct v4l2_buffer *buf)1387{1388struct vpfe_device *vpfe_dev = video_drvdata(file);13891390v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_querybuf\n");13911392if (V4L2_BUF_TYPE_VIDEO_CAPTURE != buf->type) {1393v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf type\n");1394return -EINVAL;1395}13961397if (vpfe_dev->memory != V4L2_MEMORY_MMAP) {1398v4l2_err(&vpfe_dev->v4l2_dev, "Invalid memory\n");1399return -EINVAL;1400}1401/* Call videobuf_querybuf to get information */1402return videobuf_querybuf(&vpfe_dev->buffer_queue, buf);1403}14041405static int vpfe_qbuf(struct file *file, void *priv,1406struct v4l2_buffer *p)1407{1408struct vpfe_device *vpfe_dev = video_drvdata(file);1409struct vpfe_fh *fh = file->private_data;14101411v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_qbuf\n");14121413if (V4L2_BUF_TYPE_VIDEO_CAPTURE != p->type) {1414v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf type\n");1415return -EINVAL;1416}14171418/*1419* If this file handle is not allowed to do IO,1420* return error1421*/1422if (!fh->io_allowed) {1423v4l2_err(&vpfe_dev->v4l2_dev, "fh->io_allowed\n");1424return -EACCES;1425}1426return videobuf_qbuf(&vpfe_dev->buffer_queue, p);1427}14281429static int vpfe_dqbuf(struct file *file, void *priv,1430struct v4l2_buffer *buf)1431{1432struct vpfe_device *vpfe_dev = video_drvdata(file);14331434v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_dqbuf\n");14351436if (V4L2_BUF_TYPE_VIDEO_CAPTURE != buf->type) {1437v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf type\n");1438return -EINVAL;1439}1440return videobuf_dqbuf(&vpfe_dev->buffer_queue,1441buf, file->f_flags & O_NONBLOCK);1442}14431444static int vpfe_queryctrl(struct file *file, void *priv,1445struct v4l2_queryctrl *qctrl)1446{1447struct vpfe_device *vpfe_dev = video_drvdata(file);1448struct vpfe_subdev_info *sdinfo;14491450sdinfo = vpfe_dev->current_subdev;14511452return v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id,1453core, queryctrl, qctrl);14541455}14561457static int vpfe_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl)1458{1459struct vpfe_device *vpfe_dev = video_drvdata(file);1460struct vpfe_subdev_info *sdinfo;14611462sdinfo = vpfe_dev->current_subdev;14631464return v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id,1465core, g_ctrl, ctrl);1466}14671468static int vpfe_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl)1469{1470struct vpfe_device *vpfe_dev = video_drvdata(file);1471struct vpfe_subdev_info *sdinfo;14721473sdinfo = vpfe_dev->current_subdev;14741475return v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id,1476core, s_ctrl, ctrl);1477}14781479/*1480* vpfe_calculate_offsets : This function calculates buffers offset1481* for top and bottom field1482*/1483static void vpfe_calculate_offsets(struct vpfe_device *vpfe_dev)1484{1485struct v4l2_rect image_win;14861487v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_calculate_offsets\n");14881489ccdc_dev->hw_ops.get_image_window(&image_win);1490vpfe_dev->field_off = image_win.height * image_win.width;1491}14921493/* vpfe_start_ccdc_capture: start streaming in ccdc/isif */1494static void vpfe_start_ccdc_capture(struct vpfe_device *vpfe_dev)1495{1496ccdc_dev->hw_ops.enable(1);1497if (ccdc_dev->hw_ops.enable_out_to_sdram)1498ccdc_dev->hw_ops.enable_out_to_sdram(1);1499vpfe_dev->started = 1;1500}15011502/*1503* vpfe_streamon. Assume the DMA queue is not empty.1504* application is expected to call QBUF before calling1505* this ioctl. If not, driver returns error1506*/1507static int vpfe_streamon(struct file *file, void *priv,1508enum v4l2_buf_type buf_type)1509{1510struct vpfe_device *vpfe_dev = video_drvdata(file);1511struct vpfe_fh *fh = file->private_data;1512struct vpfe_subdev_info *sdinfo;1513unsigned long addr;1514int ret = 0;15151516v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_streamon\n");15171518if (V4L2_BUF_TYPE_VIDEO_CAPTURE != buf_type) {1519v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf type\n");1520return -EINVAL;1521}15221523/* If file handle is not allowed IO, return error */1524if (!fh->io_allowed) {1525v4l2_err(&vpfe_dev->v4l2_dev, "fh->io_allowed\n");1526return -EACCES;1527}15281529sdinfo = vpfe_dev->current_subdev;1530ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id,1531video, s_stream, 1);15321533if (ret && (ret != -ENOIOCTLCMD)) {1534v4l2_err(&vpfe_dev->v4l2_dev, "stream on failed in subdev\n");1535return -EINVAL;1536}15371538/* If buffer queue is empty, return error */1539if (list_empty(&vpfe_dev->buffer_queue.stream)) {1540v4l2_err(&vpfe_dev->v4l2_dev, "buffer queue is empty\n");1541return -EIO;1542}15431544/* Call videobuf_streamon to start streaming * in videobuf */1545ret = videobuf_streamon(&vpfe_dev->buffer_queue);1546if (ret)1547return ret;154815491550ret = mutex_lock_interruptible(&vpfe_dev->lock);1551if (ret)1552goto streamoff;1553/* Get the next frame from the buffer queue */1554vpfe_dev->next_frm = list_entry(vpfe_dev->dma_queue.next,1555struct videobuf_buffer, queue);1556vpfe_dev->cur_frm = vpfe_dev->next_frm;1557/* Remove buffer from the buffer queue */1558list_del(&vpfe_dev->cur_frm->queue);1559/* Mark state of the current frame to active */1560vpfe_dev->cur_frm->state = VIDEOBUF_ACTIVE;1561/* Initialize field_id and started member */1562vpfe_dev->field_id = 0;1563addr = videobuf_to_dma_contig(vpfe_dev->cur_frm);15641565/* Calculate field offset */1566vpfe_calculate_offsets(vpfe_dev);15671568if (vpfe_attach_irq(vpfe_dev) < 0) {1569v4l2_err(&vpfe_dev->v4l2_dev,1570"Error in attaching interrupt handle\n");1571ret = -EFAULT;1572goto unlock_out;1573}1574if (ccdc_dev->hw_ops.configure() < 0) {1575v4l2_err(&vpfe_dev->v4l2_dev,1576"Error in configuring ccdc\n");1577ret = -EINVAL;1578goto unlock_out;1579}1580ccdc_dev->hw_ops.setfbaddr((unsigned long)(addr));1581vpfe_start_ccdc_capture(vpfe_dev);1582mutex_unlock(&vpfe_dev->lock);1583return ret;1584unlock_out:1585mutex_unlock(&vpfe_dev->lock);1586streamoff:1587ret = videobuf_streamoff(&vpfe_dev->buffer_queue);1588return ret;1589}15901591static int vpfe_streamoff(struct file *file, void *priv,1592enum v4l2_buf_type buf_type)1593{1594struct vpfe_device *vpfe_dev = video_drvdata(file);1595struct vpfe_fh *fh = file->private_data;1596struct vpfe_subdev_info *sdinfo;1597int ret = 0;15981599v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_streamoff\n");16001601if (V4L2_BUF_TYPE_VIDEO_CAPTURE != buf_type) {1602v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf type\n");1603return -EINVAL;1604}16051606/* If io is allowed for this file handle, return error */1607if (!fh->io_allowed) {1608v4l2_err(&vpfe_dev->v4l2_dev, "fh->io_allowed\n");1609return -EACCES;1610}16111612/* If streaming is not started, return error */1613if (!vpfe_dev->started) {1614v4l2_err(&vpfe_dev->v4l2_dev, "device started\n");1615return -EINVAL;1616}16171618ret = mutex_lock_interruptible(&vpfe_dev->lock);1619if (ret)1620return ret;16211622vpfe_stop_ccdc_capture(vpfe_dev);1623vpfe_detach_irq(vpfe_dev);16241625sdinfo = vpfe_dev->current_subdev;1626ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id,1627video, s_stream, 0);16281629if (ret && (ret != -ENOIOCTLCMD))1630v4l2_err(&vpfe_dev->v4l2_dev, "stream off failed in subdev\n");1631ret = videobuf_streamoff(&vpfe_dev->buffer_queue);1632mutex_unlock(&vpfe_dev->lock);1633return ret;1634}16351636static int vpfe_cropcap(struct file *file, void *priv,1637struct v4l2_cropcap *crop)1638{1639struct vpfe_device *vpfe_dev = video_drvdata(file);16401641v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_cropcap\n");16421643if (vpfe_dev->std_index >= ARRAY_SIZE(vpfe_standards))1644return -EINVAL;16451646memset(crop, 0, sizeof(struct v4l2_cropcap));1647crop->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;1648crop->bounds.width = crop->defrect.width =1649vpfe_standards[vpfe_dev->std_index].width;1650crop->bounds.height = crop->defrect.height =1651vpfe_standards[vpfe_dev->std_index].height;1652crop->pixelaspect = vpfe_standards[vpfe_dev->std_index].pixelaspect;1653return 0;1654}16551656static int vpfe_g_crop(struct file *file, void *priv,1657struct v4l2_crop *crop)1658{1659struct vpfe_device *vpfe_dev = video_drvdata(file);16601661v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_g_crop\n");16621663crop->c = vpfe_dev->crop;1664return 0;1665}16661667static int vpfe_s_crop(struct file *file, void *priv,1668struct v4l2_crop *crop)1669{1670struct vpfe_device *vpfe_dev = video_drvdata(file);1671int ret = 0;16721673v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_crop\n");16741675if (vpfe_dev->started) {1676/* make sure streaming is not started */1677v4l2_err(&vpfe_dev->v4l2_dev,1678"Cannot change crop when streaming is ON\n");1679return -EBUSY;1680}16811682ret = mutex_lock_interruptible(&vpfe_dev->lock);1683if (ret)1684return ret;16851686if (crop->c.top < 0 || crop->c.left < 0) {1687v4l2_err(&vpfe_dev->v4l2_dev,1688"doesn't support negative values for top & left\n");1689ret = -EINVAL;1690goto unlock_out;1691}16921693/* adjust the width to 16 pixel boundary */1694crop->c.width = ((crop->c.width + 15) & ~0xf);16951696/* make sure parameters are valid */1697if ((crop->c.left + crop->c.width >1698vpfe_dev->std_info.active_pixels) ||1699(crop->c.top + crop->c.height >1700vpfe_dev->std_info.active_lines)) {1701v4l2_err(&vpfe_dev->v4l2_dev, "Error in S_CROP params\n");1702ret = -EINVAL;1703goto unlock_out;1704}1705ccdc_dev->hw_ops.set_image_window(&crop->c);1706vpfe_dev->fmt.fmt.pix.width = crop->c.width;1707vpfe_dev->fmt.fmt.pix.height = crop->c.height;1708vpfe_dev->fmt.fmt.pix.bytesperline =1709ccdc_dev->hw_ops.get_line_length();1710vpfe_dev->fmt.fmt.pix.sizeimage =1711vpfe_dev->fmt.fmt.pix.bytesperline *1712vpfe_dev->fmt.fmt.pix.height;1713vpfe_dev->crop = crop->c;1714unlock_out:1715mutex_unlock(&vpfe_dev->lock);1716return ret;1717}171817191720static long vpfe_param_handler(struct file *file, void *priv,1721bool valid_prio, int cmd, void *param)1722{1723struct vpfe_device *vpfe_dev = video_drvdata(file);1724int ret = 0;17251726v4l2_dbg(2, debug, &vpfe_dev->v4l2_dev, "vpfe_param_handler\n");17271728if (vpfe_dev->started) {1729/* only allowed if streaming is not started */1730v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev,1731"device already started\n");1732return -EBUSY;1733}17341735ret = mutex_lock_interruptible(&vpfe_dev->lock);1736if (ret)1737return ret;17381739switch (cmd) {1740case VPFE_CMD_S_CCDC_RAW_PARAMS:1741v4l2_warn(&vpfe_dev->v4l2_dev,1742"VPFE_CMD_S_CCDC_RAW_PARAMS: experimental ioctl\n");1743if (ccdc_dev->hw_ops.set_params) {1744ret = ccdc_dev->hw_ops.set_params(param);1745if (ret) {1746v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev,1747"Error setting parameters in CCDC\n");1748goto unlock_out;1749}1750if (vpfe_get_ccdc_image_format(vpfe_dev,1751&vpfe_dev->fmt) < 0) {1752v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev,1753"Invalid image format at CCDC\n");1754goto unlock_out;1755}1756} else {1757ret = -EINVAL;1758v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev,1759"VPFE_CMD_S_CCDC_RAW_PARAMS not supported\n");1760}1761break;1762default:1763ret = -EINVAL;1764}1765unlock_out:1766mutex_unlock(&vpfe_dev->lock);1767return ret;1768}176917701771/* vpfe capture ioctl operations */1772static const struct v4l2_ioctl_ops vpfe_ioctl_ops = {1773.vidioc_querycap = vpfe_querycap,1774.vidioc_g_fmt_vid_cap = vpfe_g_fmt_vid_cap,1775.vidioc_enum_fmt_vid_cap = vpfe_enum_fmt_vid_cap,1776.vidioc_s_fmt_vid_cap = vpfe_s_fmt_vid_cap,1777.vidioc_try_fmt_vid_cap = vpfe_try_fmt_vid_cap,1778.vidioc_enum_input = vpfe_enum_input,1779.vidioc_g_input = vpfe_g_input,1780.vidioc_s_input = vpfe_s_input,1781.vidioc_querystd = vpfe_querystd,1782.vidioc_s_std = vpfe_s_std,1783.vidioc_g_std = vpfe_g_std,1784.vidioc_queryctrl = vpfe_queryctrl,1785.vidioc_g_ctrl = vpfe_g_ctrl,1786.vidioc_s_ctrl = vpfe_s_ctrl,1787.vidioc_reqbufs = vpfe_reqbufs,1788.vidioc_querybuf = vpfe_querybuf,1789.vidioc_qbuf = vpfe_qbuf,1790.vidioc_dqbuf = vpfe_dqbuf,1791.vidioc_streamon = vpfe_streamon,1792.vidioc_streamoff = vpfe_streamoff,1793.vidioc_cropcap = vpfe_cropcap,1794.vidioc_g_crop = vpfe_g_crop,1795.vidioc_s_crop = vpfe_s_crop,1796.vidioc_default = vpfe_param_handler,1797};17981799static struct vpfe_device *vpfe_initialize(void)1800{1801struct vpfe_device *vpfe_dev;18021803/* Default number of buffers should be 3 */1804if ((numbuffers > 0) &&1805(numbuffers < config_params.min_numbuffers))1806numbuffers = config_params.min_numbuffers;18071808/*1809* Set buffer size to min buffers size if invalid buffer size is1810* given1811*/1812if (bufsize < config_params.min_bufsize)1813bufsize = config_params.min_bufsize;18141815config_params.numbuffers = numbuffers;18161817if (numbuffers)1818config_params.device_bufsize = bufsize;18191820/* Allocate memory for device objects */1821vpfe_dev = kzalloc(sizeof(*vpfe_dev), GFP_KERNEL);18221823return vpfe_dev;1824}18251826/*1827* vpfe_probe : This function creates device entries by register1828* itself to the V4L2 driver and initializes fields of each1829* device objects1830*/1831static __init int vpfe_probe(struct platform_device *pdev)1832{1833struct vpfe_subdev_info *sdinfo;1834struct vpfe_config *vpfe_cfg;1835struct resource *res1;1836struct vpfe_device *vpfe_dev;1837struct i2c_adapter *i2c_adap;1838struct video_device *vfd;1839int ret = -ENOMEM, i, j;1840int num_subdevs = 0;18411842/* Get the pointer to the device object */1843vpfe_dev = vpfe_initialize();18441845if (!vpfe_dev) {1846v4l2_err(pdev->dev.driver,1847"Failed to allocate memory for vpfe_dev\n");1848return ret;1849}18501851vpfe_dev->pdev = &pdev->dev;18521853if (NULL == pdev->dev.platform_data) {1854v4l2_err(pdev->dev.driver, "Unable to get vpfe config\n");1855ret = -ENODEV;1856goto probe_free_dev_mem;1857}18581859vpfe_cfg = pdev->dev.platform_data;1860vpfe_dev->cfg = vpfe_cfg;1861if (NULL == vpfe_cfg->ccdc ||1862NULL == vpfe_cfg->card_name ||1863NULL == vpfe_cfg->sub_devs) {1864v4l2_err(pdev->dev.driver, "null ptr in vpfe_cfg\n");1865ret = -ENOENT;1866goto probe_free_dev_mem;1867}18681869/* Allocate memory for ccdc configuration */1870ccdc_cfg = kmalloc(sizeof(struct ccdc_config), GFP_KERNEL);1871if (NULL == ccdc_cfg) {1872v4l2_err(pdev->dev.driver,1873"Memory allocation failed for ccdc_cfg\n");1874goto probe_free_lock;1875}18761877mutex_lock(&ccdc_lock);18781879strncpy(ccdc_cfg->name, vpfe_cfg->ccdc, 32);1880/* Get VINT0 irq resource */1881res1 = platform_get_resource(pdev, IORESOURCE_IRQ, 0);1882if (!res1) {1883v4l2_err(pdev->dev.driver,1884"Unable to get interrupt for VINT0\n");1885ret = -ENODEV;1886goto probe_free_ccdc_cfg_mem;1887}1888vpfe_dev->ccdc_irq0 = res1->start;18891890/* Get VINT1 irq resource */1891res1 = platform_get_resource(pdev, IORESOURCE_IRQ, 1);1892if (!res1) {1893v4l2_err(pdev->dev.driver,1894"Unable to get interrupt for VINT1\n");1895ret = -ENODEV;1896goto probe_free_ccdc_cfg_mem;1897}1898vpfe_dev->ccdc_irq1 = res1->start;18991900ret = request_irq(vpfe_dev->ccdc_irq0, vpfe_isr, IRQF_DISABLED,1901"vpfe_capture0", vpfe_dev);19021903if (0 != ret) {1904v4l2_err(pdev->dev.driver, "Unable to request interrupt\n");1905goto probe_free_ccdc_cfg_mem;1906}19071908/* Allocate memory for video device */1909vfd = video_device_alloc();1910if (NULL == vfd) {1911ret = -ENOMEM;1912v4l2_err(pdev->dev.driver, "Unable to alloc video device\n");1913goto probe_out_release_irq;1914}19151916/* Initialize field of video device */1917vfd->release = video_device_release;1918vfd->fops = &vpfe_fops;1919vfd->ioctl_ops = &vpfe_ioctl_ops;1920vfd->tvnorms = 0;1921vfd->current_norm = V4L2_STD_PAL;1922vfd->v4l2_dev = &vpfe_dev->v4l2_dev;1923snprintf(vfd->name, sizeof(vfd->name),1924"%s_V%d.%d.%d",1925CAPTURE_DRV_NAME,1926(VPFE_CAPTURE_VERSION_CODE >> 16) & 0xff,1927(VPFE_CAPTURE_VERSION_CODE >> 8) & 0xff,1928(VPFE_CAPTURE_VERSION_CODE) & 0xff);1929/* Set video_dev to the video device */1930vpfe_dev->video_dev = vfd;19311932ret = v4l2_device_register(&pdev->dev, &vpfe_dev->v4l2_dev);1933if (ret) {1934v4l2_err(pdev->dev.driver,1935"Unable to register v4l2 device.\n");1936goto probe_out_video_release;1937}1938v4l2_info(&vpfe_dev->v4l2_dev, "v4l2 device registered\n");1939spin_lock_init(&vpfe_dev->irqlock);1940spin_lock_init(&vpfe_dev->dma_queue_lock);1941mutex_init(&vpfe_dev->lock);19421943/* Initialize field of the device objects */1944vpfe_dev->numbuffers = config_params.numbuffers;19451946/* Initialize prio member of device object */1947v4l2_prio_init(&vpfe_dev->prio);1948/* register video device */1949v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev,1950"trying to register vpfe device.\n");1951v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev,1952"video_dev=%x\n", (int)&vpfe_dev->video_dev);1953vpfe_dev->fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;1954ret = video_register_device(vpfe_dev->video_dev,1955VFL_TYPE_GRABBER, -1);19561957if (ret) {1958v4l2_err(pdev->dev.driver,1959"Unable to register video device.\n");1960goto probe_out_v4l2_unregister;1961}19621963v4l2_info(&vpfe_dev->v4l2_dev, "video device registered\n");1964/* set the driver data in platform device */1965platform_set_drvdata(pdev, vpfe_dev);1966/* set driver private data */1967video_set_drvdata(vpfe_dev->video_dev, vpfe_dev);1968i2c_adap = i2c_get_adapter(vpfe_cfg->i2c_adapter_id);1969num_subdevs = vpfe_cfg->num_subdevs;1970vpfe_dev->sd = kmalloc(sizeof(struct v4l2_subdev *) * num_subdevs,1971GFP_KERNEL);1972if (NULL == vpfe_dev->sd) {1973v4l2_err(&vpfe_dev->v4l2_dev,1974"unable to allocate memory for subdevice pointers\n");1975ret = -ENOMEM;1976goto probe_out_video_unregister;1977}19781979for (i = 0; i < num_subdevs; i++) {1980struct v4l2_input *inps;19811982sdinfo = &vpfe_cfg->sub_devs[i];19831984/* Load up the subdevice */1985vpfe_dev->sd[i] =1986v4l2_i2c_new_subdev_board(&vpfe_dev->v4l2_dev,1987i2c_adap,1988&sdinfo->board_info,1989NULL);1990if (vpfe_dev->sd[i]) {1991v4l2_info(&vpfe_dev->v4l2_dev,1992"v4l2 sub device %s registered\n",1993sdinfo->name);1994vpfe_dev->sd[i]->grp_id = sdinfo->grp_id;1995/* update tvnorms from the sub devices */1996for (j = 0; j < sdinfo->num_inputs; j++) {1997inps = &sdinfo->inputs[j];1998vfd->tvnorms |= inps->std;1999}2000} else {2001v4l2_info(&vpfe_dev->v4l2_dev,2002"v4l2 sub device %s register fails\n",2003sdinfo->name);2004goto probe_sd_out;2005}2006}20072008/* set first sub device as current one */2009vpfe_dev->current_subdev = &vpfe_cfg->sub_devs[0];20102011/* We have at least one sub device to work with */2012mutex_unlock(&ccdc_lock);2013return 0;20142015probe_sd_out:2016kfree(vpfe_dev->sd);2017probe_out_video_unregister:2018video_unregister_device(vpfe_dev->video_dev);2019probe_out_v4l2_unregister:2020v4l2_device_unregister(&vpfe_dev->v4l2_dev);2021probe_out_video_release:2022if (!video_is_registered(vpfe_dev->video_dev))2023video_device_release(vpfe_dev->video_dev);2024probe_out_release_irq:2025free_irq(vpfe_dev->ccdc_irq0, vpfe_dev);2026probe_free_ccdc_cfg_mem:2027kfree(ccdc_cfg);2028probe_free_lock:2029mutex_unlock(&ccdc_lock);2030probe_free_dev_mem:2031kfree(vpfe_dev);2032return ret;2033}20342035/*2036* vpfe_remove : It un-register device from V4L2 driver2037*/2038static int __devexit vpfe_remove(struct platform_device *pdev)2039{2040struct vpfe_device *vpfe_dev = platform_get_drvdata(pdev);20412042v4l2_info(pdev->dev.driver, "vpfe_remove\n");20432044free_irq(vpfe_dev->ccdc_irq0, vpfe_dev);2045kfree(vpfe_dev->sd);2046v4l2_device_unregister(&vpfe_dev->v4l2_dev);2047video_unregister_device(vpfe_dev->video_dev);2048kfree(vpfe_dev);2049kfree(ccdc_cfg);2050return 0;2051}20522053static int vpfe_suspend(struct device *dev)2054{2055return 0;2056}20572058static int vpfe_resume(struct device *dev)2059{2060return 0;2061}20622063static const struct dev_pm_ops vpfe_dev_pm_ops = {2064.suspend = vpfe_suspend,2065.resume = vpfe_resume,2066};20672068static struct platform_driver vpfe_driver = {2069.driver = {2070.name = CAPTURE_DRV_NAME,2071.owner = THIS_MODULE,2072.pm = &vpfe_dev_pm_ops,2073},2074.probe = vpfe_probe,2075.remove = __devexit_p(vpfe_remove),2076};20772078static __init int vpfe_init(void)2079{2080printk(KERN_NOTICE "vpfe_init\n");2081/* Register driver to the kernel */2082return platform_driver_register(&vpfe_driver);2083}20842085/*2086* vpfe_cleanup : This function un-registers device driver2087*/2088static void vpfe_cleanup(void)2089{2090platform_driver_unregister(&vpfe_driver);2091}20922093module_init(vpfe_init);2094module_exit(vpfe_cleanup);209520962097