vpfe_capture.c revision 9d8938248c3b67904a8108a6fc3dcceb9d7f2aad
17da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri/*
27da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri * Copyright (C) 2008-2009 Texas Instruments Inc
37da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri *
47da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri * This program is free software; you can redistribute it and/or modify
57da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri * it under the terms of the GNU General Public License as published by
67da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri * the Free Software Foundation; either version 2 of the License, or
77da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri * (at your option) any later version.
87da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri *
97da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri * This program is distributed in the hope that it will be useful,
107da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri * but WITHOUT ANY WARRANTY; without even the implied warranty of
117da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
127da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri * GNU General Public License for more details.
137da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri *
147da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri * You should have received a copy of the GNU General Public License
157da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri * along with this program; if not, write to the Free Software
167da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
177da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri *
187da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri * Driver name : VPFE Capture driver
197da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri *    VPFE Capture driver allows applications to capture and stream video
207da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri *    frames on DaVinci SoCs (DM6446, DM355 etc) from a YUV source such as
217da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri *    TVP5146 or  Raw Bayer RGB image data from an image sensor
227da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri *    such as Microns' MT9T001, MT9T031 etc.
237da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri *
247da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri *    These SoCs have, in common, a Video Processing Subsystem (VPSS) that
257da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri *    consists of a Video Processing Front End (VPFE) for capturing
267da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri *    video/raw image data and Video Processing Back End (VPBE) for displaying
277da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri *    YUV data through an in-built analog encoder or Digital LCD port. This
287da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri *    driver is for capture through VPFE. A typical EVM using these SoCs have
297da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri *    following high level configuration.
307da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri *
317da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri *
327da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri *    decoder(TVP5146/		YUV/
337da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri * 	     MT9T001)   -->  Raw Bayer RGB ---> MUX -> VPFE (CCDC/ISIF)
347da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri *    				data input              |      |
357da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri *							V      |
367da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri *						      SDRAM    |
377da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri *							       V
387da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri *							   Image Processor
397da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri *							       |
407da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri *							       V
417da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri *							     SDRAM
427da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri *    The data flow happens from a decoder connected to the VPFE over a
437da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri *    YUV embedded (BT.656/BT.1120) or separate sync or raw bayer rgb interface
447da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri *    and to the input of VPFE through an optional MUX (if more inputs are
457da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri *    to be interfaced on the EVM). The input data is first passed through
467da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri *    CCDC (CCD Controller, a.k.a Image Sensor Interface, ISIF). The CCDC
477da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri *    does very little or no processing on YUV data and does pre-process Raw
487da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri *    Bayer RGB data through modules such as Defect Pixel Correction (DFC)
497da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri *    Color Space Conversion (CSC), data gain/offset etc. After this, data
507da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri *    can be written to SDRAM or can be connected to the image processing
517da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri *    block such as IPIPE (on DM355 only).
527da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri *
537da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri *    Features supported
547da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri *  		- MMAP IO
557da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri *		- Capture using TVP5146 over BT.656
567da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri *		- support for interfacing decoders using sub device model
577da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri *		- Work with DM355 or DM6446 CCDC to do Raw Bayer RGB/YUV
587da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri *		  data capture to SDRAM.
597da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri *    TODO list
607da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri *		- Support multiple REQBUF after open
617da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri *		- Support for de-allocating buffers through REQBUF
627da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri *		- Support for Raw Bayer RGB capture
637da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri *		- Support for chaining Image Processor
647da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri *		- Support for static allocation of buffers
657da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri *		- Support for USERPTR IO
667da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri *		- Support for STREAMON before QBUF
677da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri *		- Support for control ioctls
687da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri */
697da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri#include <linux/module.h>
707da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri#include <linux/init.h>
717da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri#include <linux/platform_device.h>
727da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri#include <linux/interrupt.h>
737da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri#include <linux/version.h>
747da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri#include <media/v4l2-common.h>
757da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri#include <linux/io.h>
767da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri#include <media/davinci/vpfe_capture.h>
777da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri#include "ccdc_hw_device.h"
787da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
797da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheristatic int debug;
807da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheristatic u32 numbuffers = 3;
817da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheristatic u32 bufsize = (720 * 576 * 2);
827da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
837da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicherimodule_param(numbuffers, uint, S_IRUGO);
847da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicherimodule_param(bufsize, uint, S_IRUGO);
857da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicherimodule_param(debug, int, 0644);
867da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
877da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan KaricheriMODULE_PARM_DESC(numbuffers, "buffer count (default:3)");
887da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan KaricheriMODULE_PARM_DESC(bufsize, "buffer size in bytes (default:720 x 576 x 2)");
897da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan KaricheriMODULE_PARM_DESC(debug, "Debug level 0-1");
907da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
917da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan KaricheriMODULE_DESCRIPTION("VPFE Video for Linux Capture Driver");
927da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan KaricheriMODULE_LICENSE("GPL");
937da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan KaricheriMODULE_AUTHOR("Texas Instruments");
947da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
957da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri/* standard information */
967da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheristruct vpfe_standard {
977da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	v4l2_std_id std_id;
987da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	unsigned int width;
997da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	unsigned int height;
1007da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	struct v4l2_fract pixelaspect;
1017da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* 0 - progressive, 1 - interlaced */
1027da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	int frame_format;
1037da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri};
1047da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
1057da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri/* ccdc configuration */
1067da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheristruct ccdc_config {
1077da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* This make sure vpfe is probed and ready to go */
1087da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	int vpfe_probed;
1097da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* name of ccdc device */
1107da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	char name[32];
1117da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* for storing mem maps for CCDC */
1127da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	int ccdc_addr_size;
1137da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	void *__iomem ccdc_addr;
1147da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri};
1157da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
1167da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri/* data structures */
1177da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheristatic struct vpfe_config_params config_params = {
1187da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	.min_numbuffers = 3,
1197da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	.numbuffers = 3,
1207da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	.min_bufsize = 720 * 480 * 2,
1217da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	.device_bufsize = 720 * 576 * 2,
1227da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri};
1237da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
1247da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri/* ccdc device registered */
1257da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheristatic struct ccdc_hw_device *ccdc_dev;
1267da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri/* lock for accessing ccdc information */
1277da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheristatic DEFINE_MUTEX(ccdc_lock);
1287da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri/* ccdc configuration */
1297da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheristatic struct ccdc_config *ccdc_cfg;
1307da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
1317da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karichericonst struct vpfe_standard vpfe_standards[] = {
1327da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	{V4L2_STD_525_60, 720, 480, {11, 10}, 1},
1337da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	{V4L2_STD_625_50, 720, 576, {54, 59}, 1},
1347da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri};
1357da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
1367da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri/* Used when raw Bayer image from ccdc is directly captured to SDRAM */
1377da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheristatic const struct vpfe_pixel_format vpfe_pix_fmts[] = {
1387da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	{
1397da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		.fmtdesc = {
1407da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			.index = 0,
1417da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			.type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
1427da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			.description = "Bayer GrRBGb 8bit A-Law compr.",
1437da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			.pixelformat = V4L2_PIX_FMT_SBGGR8,
1447da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		},
1457da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		.bpp = 1,
1467da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	},
1477da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	{
1487da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		.fmtdesc = {
1497da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			.index = 1,
1507da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			.type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
1517da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			.description = "Bayer GrRBGb - 16bit",
1527da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			.pixelformat = V4L2_PIX_FMT_SBGGR16,
1537da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		},
1547da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		.bpp = 2,
1557da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	},
1567da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	{
1577da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		.fmtdesc = {
1587da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			.index = 2,
1597da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			.type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
1607da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			.description = "Bayer GrRBGb 8bit DPCM compr.",
1617da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			.pixelformat = V4L2_PIX_FMT_SGRBG10DPCM8,
1627da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		},
1637da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		.bpp = 1,
1647da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	},
1657da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	{
1667da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		.fmtdesc = {
1677da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			.index = 3,
1687da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			.type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
1697da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			.description = "YCbCr 4:2:2 Interleaved UYVY",
1707da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			.pixelformat = V4L2_PIX_FMT_UYVY,
1717da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		},
1727da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		.bpp = 2,
1737da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	},
1747da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	{
1757da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		.fmtdesc = {
1767da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			.index = 4,
1777da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			.type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
1787da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			.description = "YCbCr 4:2:2 Interleaved YUYV",
1797da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			.pixelformat = V4L2_PIX_FMT_YUYV,
1807da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		},
1817da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		.bpp = 2,
1827da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	},
1837da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	{
1847da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		.fmtdesc = {
1857da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			.index = 5,
1867da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			.type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
1877da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			.description = "Y/CbCr 4:2:0 - Semi planar",
1887da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			.pixelformat = V4L2_PIX_FMT_NV12,
1897da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		},
1907da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		.bpp = 1,
1917da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	},
1927da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri};
1937da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
1947da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri/*
1957da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri * vpfe_lookup_pix_format()
1967da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri * lookup an entry in the vpfe pix format table based on pix_format
1977da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri */
1987da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheristatic const struct vpfe_pixel_format *vpfe_lookup_pix_format(u32 pix_format)
1997da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri{
2007da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	int i;
2017da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
2027da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	for (i = 0; i < ARRAY_SIZE(vpfe_pix_fmts); i++) {
2037da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		if (pix_format == vpfe_pix_fmts[i].fmtdesc.pixelformat)
2047da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			return &vpfe_pix_fmts[i];
2057da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
2067da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	return NULL;
2077da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri}
2087da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
2097da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri/*
2107da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri * vpfe_register_ccdc_device. CCDC module calls this to
2117da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri * register with vpfe capture
2127da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri */
2137da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheriint vpfe_register_ccdc_device(struct ccdc_hw_device *dev)
2147da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri{
2157da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	int ret = 0;
2167da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	printk(KERN_NOTICE "vpfe_register_ccdc_device: %s\n", dev->name);
2177da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
2187da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	BUG_ON(!dev->hw_ops.open);
2197da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	BUG_ON(!dev->hw_ops.enable);
2207da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	BUG_ON(!dev->hw_ops.set_hw_if_params);
2217da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	BUG_ON(!dev->hw_ops.configure);
2227da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	BUG_ON(!dev->hw_ops.set_buftype);
2237da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	BUG_ON(!dev->hw_ops.get_buftype);
2247da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	BUG_ON(!dev->hw_ops.enum_pix);
2257da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	BUG_ON(!dev->hw_ops.set_frame_format);
2267da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	BUG_ON(!dev->hw_ops.get_frame_format);
2277da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	BUG_ON(!dev->hw_ops.get_pixel_format);
2287da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	BUG_ON(!dev->hw_ops.set_pixel_format);
2297da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	BUG_ON(!dev->hw_ops.set_params);
2307da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	BUG_ON(!dev->hw_ops.set_image_window);
2317da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	BUG_ON(!dev->hw_ops.get_image_window);
2327da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	BUG_ON(!dev->hw_ops.get_line_length);
2337da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	BUG_ON(!dev->hw_ops.setfbaddr);
2347da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	BUG_ON(!dev->hw_ops.getfid);
2357da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
2367da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	mutex_lock(&ccdc_lock);
2377da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (NULL == ccdc_cfg) {
2387da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		/*
2397da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		 * TODO. Will this ever happen? if so, we need to fix it.
2407da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		 * Proabably we need to add the request to a linked list and
2417da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		 * walk through it during vpfe probe
2427da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		 */
2437da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		printk(KERN_ERR "vpfe capture not initialized\n");
2447da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		ret = -1;
2457da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		goto unlock;
2467da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
2477da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
2487da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (strcmp(dev->name, ccdc_cfg->name)) {
2497da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		/* ignore this ccdc */
2507da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		ret = -1;
2517da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		goto unlock;
2527da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
2537da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
2547da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (ccdc_dev) {
2557da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		printk(KERN_ERR "ccdc already registered\n");
2567da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		ret = -1;
2577da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		goto unlock;
2587da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
2597da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
2607da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	ccdc_dev = dev;
2617da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	dev->hw_ops.set_ccdc_base(ccdc_cfg->ccdc_addr,
2627da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri				  ccdc_cfg->ccdc_addr_size);
2637da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheriunlock:
2647da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	mutex_unlock(&ccdc_lock);
2657da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	return ret;
2667da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri}
2677da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan KaricheriEXPORT_SYMBOL(vpfe_register_ccdc_device);
2687da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
2697da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri/*
2707da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri * vpfe_unregister_ccdc_device. CCDC module calls this to
2717da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri * unregister with vpfe capture
2727da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri */
2737da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicherivoid vpfe_unregister_ccdc_device(struct ccdc_hw_device *dev)
2747da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri{
2757da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (NULL == dev) {
2767da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		printk(KERN_ERR "invalid ccdc device ptr\n");
2777da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		return;
2787da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
2797da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
2807da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	printk(KERN_NOTICE "vpfe_unregister_ccdc_device, dev->name = %s\n",
2817da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		dev->name);
2827da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
2837da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (strcmp(dev->name, ccdc_cfg->name)) {
2847da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		/* ignore this ccdc */
2857da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		return;
2867da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
2877da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
2887da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	mutex_lock(&ccdc_lock);
2897da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	ccdc_dev = NULL;
2907da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	mutex_unlock(&ccdc_lock);
2917da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	return;
2927da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri}
2937da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan KaricheriEXPORT_SYMBOL(vpfe_unregister_ccdc_device);
2947da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
2957da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri/*
2967da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri * vpfe_get_ccdc_image_format - Get image parameters based on CCDC settings
2977da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri */
2987da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheristatic int vpfe_get_ccdc_image_format(struct vpfe_device *vpfe_dev,
2997da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri				 struct v4l2_format *f)
3007da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri{
3017da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	struct v4l2_rect image_win;
3027da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	enum ccdc_buftype buf_type;
3037da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	enum ccdc_frmfmt frm_fmt;
3047da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
3057da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	memset(f, 0, sizeof(*f));
3067da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	f->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
3077da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	ccdc_dev->hw_ops.get_image_window(&image_win);
3087da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	f->fmt.pix.width = image_win.width;
3097da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	f->fmt.pix.height = image_win.height;
3107da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	f->fmt.pix.bytesperline = ccdc_dev->hw_ops.get_line_length();
3117da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	f->fmt.pix.sizeimage = f->fmt.pix.bytesperline *
3127da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri				f->fmt.pix.height;
3137da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	buf_type = ccdc_dev->hw_ops.get_buftype();
3147da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	f->fmt.pix.pixelformat = ccdc_dev->hw_ops.get_pixel_format();
3157da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	frm_fmt = ccdc_dev->hw_ops.get_frame_format();
3167da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (frm_fmt == CCDC_FRMFMT_PROGRESSIVE)
3177da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		f->fmt.pix.field = V4L2_FIELD_NONE;
3187da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	else if (frm_fmt == CCDC_FRMFMT_INTERLACED) {
3197da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		if (buf_type == CCDC_BUFTYPE_FLD_INTERLEAVED)
3207da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			f->fmt.pix.field = V4L2_FIELD_INTERLACED;
3217da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		else if (buf_type == CCDC_BUFTYPE_FLD_SEPARATED)
3227da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			f->fmt.pix.field = V4L2_FIELD_SEQ_TB;
3237da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		else {
3247da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf_type\n");
3257da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			return -EINVAL;
3267da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		}
3277da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	} else {
3287da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		v4l2_err(&vpfe_dev->v4l2_dev, "Invalid frm_fmt\n");
3297da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		return -EINVAL;
3307da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
3317da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	return 0;
3327da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri}
3337da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
3347da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri/*
3357da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri * vpfe_config_ccdc_image_format()
3367da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri * For a pix format, configure ccdc to setup the capture
3377da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri */
3387da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheristatic int vpfe_config_ccdc_image_format(struct vpfe_device *vpfe_dev)
3397da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri{
3407da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	enum ccdc_frmfmt frm_fmt = CCDC_FRMFMT_INTERLACED;
3417da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	int ret = 0;
3427da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
3437da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (ccdc_dev->hw_ops.set_pixel_format(
3447da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			vpfe_dev->fmt.fmt.pix.pixelformat) < 0) {
3457da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		v4l2_err(&vpfe_dev->v4l2_dev,
3467da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			"couldn't set pix format in ccdc\n");
3477da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		return -EINVAL;
3487da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
3497da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* configure the image window */
3507da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	ccdc_dev->hw_ops.set_image_window(&vpfe_dev->crop);
3517da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
3527da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	switch (vpfe_dev->fmt.fmt.pix.field) {
3537da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	case V4L2_FIELD_INTERLACED:
3547da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		/* do nothing, since it is default */
3557da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		ret = ccdc_dev->hw_ops.set_buftype(
3567da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri				CCDC_BUFTYPE_FLD_INTERLEAVED);
3577da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		break;
3587da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	case V4L2_FIELD_NONE:
3597da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		frm_fmt = CCDC_FRMFMT_PROGRESSIVE;
3607da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		/* buffer type only applicable for interlaced scan */
3617da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		break;
3627da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	case V4L2_FIELD_SEQ_TB:
3637da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		ret = ccdc_dev->hw_ops.set_buftype(
3647da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri				CCDC_BUFTYPE_FLD_SEPARATED);
3657da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		break;
3667da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	default:
3677da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		return -EINVAL;
3687da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
3697da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
3707da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* set the frame format */
3717da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (!ret)
3727da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		ret = ccdc_dev->hw_ops.set_frame_format(frm_fmt);
3737da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	return ret;
3747da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri}
3757da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri/*
3767da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri * vpfe_config_image_format()
3777da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri * For a given standard, this functions sets up the default
3787da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri * pix format & crop values in the vpfe device and ccdc.  It first
3797da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri * starts with defaults based values from the standard table.
3807da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri * It then checks if sub device support g_fmt and then override the
3817da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri * values based on that.Sets crop values to match with scan resolution
3827da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri * starting at 0,0. It calls vpfe_config_ccdc_image_format() set the
3837da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri * values in ccdc
3847da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri */
3857da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheristatic int vpfe_config_image_format(struct vpfe_device *vpfe_dev,
3867da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri				    const v4l2_std_id *std_id)
3877da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri{
3887da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	struct vpfe_subdev_info *sdinfo = vpfe_dev->current_subdev;
3897da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	int i, ret = 0;
3907da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
3917da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	for (i = 0; i < ARRAY_SIZE(vpfe_standards); i++) {
3927da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		if (vpfe_standards[i].std_id & *std_id) {
3937da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			vpfe_dev->std_info.active_pixels =
3947da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri					vpfe_standards[i].width;
3957da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			vpfe_dev->std_info.active_lines =
3967da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri					vpfe_standards[i].height;
3977da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			vpfe_dev->std_info.frame_format =
3987da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri					vpfe_standards[i].frame_format;
3997da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			vpfe_dev->std_index = i;
4007da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			break;
4017da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		}
4027da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
4037da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
4047da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (i ==  ARRAY_SIZE(vpfe_standards)) {
4057da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		v4l2_err(&vpfe_dev->v4l2_dev, "standard not supported\n");
4067da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		return -EINVAL;
4077da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
4087da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
4097da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	vpfe_dev->crop.top = 0;
4107da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	vpfe_dev->crop.left = 0;
4117da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	vpfe_dev->crop.width = vpfe_dev->std_info.active_pixels;
4127da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	vpfe_dev->crop.height = vpfe_dev->std_info.active_lines;
4137da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	vpfe_dev->fmt.fmt.pix.width = vpfe_dev->crop.width;
4147da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	vpfe_dev->fmt.fmt.pix.height = vpfe_dev->crop.height;
4157da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
4167da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* first field and frame format based on standard frame format */
4177da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (vpfe_dev->std_info.frame_format) {
4187da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		vpfe_dev->fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
4197da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		/* assume V4L2_PIX_FMT_UYVY as default */
4207da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		vpfe_dev->fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY;
4217da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	} else {
4227da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		vpfe_dev->fmt.fmt.pix.field = V4L2_FIELD_NONE;
4237da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		/* assume V4L2_PIX_FMT_SBGGR8 */
4247da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		vpfe_dev->fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_SBGGR8;
4257da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
4267da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
4277da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* if sub device supports g_fmt, override the defaults */
4287da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev,
4297da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			sdinfo->grp_id, video, g_fmt, &vpfe_dev->fmt);
4307da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
4317da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (ret && ret != -ENOIOCTLCMD) {
4327da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		v4l2_err(&vpfe_dev->v4l2_dev,
4337da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			"error in getting g_fmt from sub device\n");
4347da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		return ret;
4357da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
4367da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
4377da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* Sets the values in CCDC */
4387da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	ret = vpfe_config_ccdc_image_format(vpfe_dev);
4397da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (ret)
4407da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		return ret;
4417da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
4427da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* Update the values of sizeimage and bytesperline */
4437da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (!ret) {
4447da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		vpfe_dev->fmt.fmt.pix.bytesperline =
4457da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			ccdc_dev->hw_ops.get_line_length();
4467da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		vpfe_dev->fmt.fmt.pix.sizeimage =
4477da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			vpfe_dev->fmt.fmt.pix.bytesperline *
4487da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			vpfe_dev->fmt.fmt.pix.height;
4497da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
4507da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	return ret;
4517da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri}
4527da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
4537da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheristatic int vpfe_initialize_device(struct vpfe_device *vpfe_dev)
4547da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri{
4557da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	int ret = 0;
4567da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
4577da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* set first input of current subdevice as the current input */
4587da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	vpfe_dev->current_input = 0;
4597da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
4607da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* set default standard */
4617da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	vpfe_dev->std_index = 0;
4627da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
4637da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* Configure the default format information */
4647da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	ret = vpfe_config_image_format(vpfe_dev,
4657da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri				&vpfe_standards[vpfe_dev->std_index].std_id);
4667da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (ret)
4677da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		return ret;
4687da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
4697da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* now open the ccdc device to initialize it */
4707da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	mutex_lock(&ccdc_lock);
4717da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (NULL == ccdc_dev) {
4727da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		v4l2_err(&vpfe_dev->v4l2_dev, "ccdc device not registered\n");
4737da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		ret = -ENODEV;
4747da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		goto unlock;
4757da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
4767da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
4777da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (!try_module_get(ccdc_dev->owner)) {
4787da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		v4l2_err(&vpfe_dev->v4l2_dev, "Couldn't lock ccdc module\n");
4797da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		ret = -ENODEV;
4807da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		goto unlock;
4817da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
4827da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	ret = ccdc_dev->hw_ops.open(vpfe_dev->pdev);
4837da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (!ret)
4847da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		vpfe_dev->initialized = 1;
4857da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheriunlock:
4867da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	mutex_unlock(&ccdc_lock);
4877da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	return ret;
4887da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri}
4897da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
4907da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri/*
4917da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri * vpfe_open : It creates object of file handle structure and
4927da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri * stores it in private_data  member of filepointer
4937da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri */
4947da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheristatic int vpfe_open(struct file *file)
4957da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri{
4967da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	struct vpfe_device *vpfe_dev = video_drvdata(file);
4977da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	struct vpfe_fh *fh;
4987da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
4997da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_open\n");
5007da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
5017da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (!vpfe_dev->cfg->num_subdevs) {
5027da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		v4l2_err(&vpfe_dev->v4l2_dev, "No decoder registered\n");
5037da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		return -ENODEV;
5047da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
5057da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
5067da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* Allocate memory for the file handle object */
5077da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	fh = kmalloc(sizeof(struct vpfe_fh), GFP_KERNEL);
5087da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (NULL == fh) {
5097da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		v4l2_err(&vpfe_dev->v4l2_dev,
5107da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			"unable to allocate memory for file handle object\n");
5117da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		return -ENOMEM;
5127da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
5137da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* store pointer to fh in private_data member of file */
5147da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	file->private_data = fh;
5157da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	fh->vpfe_dev = vpfe_dev;
5167da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	mutex_lock(&vpfe_dev->lock);
5177da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* If decoder is not initialized. initialize it */
5187da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (!vpfe_dev->initialized) {
5197da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		if (vpfe_initialize_device(vpfe_dev)) {
5207da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			mutex_unlock(&vpfe_dev->lock);
5217da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			return -ENODEV;
5227da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		}
5237da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
5247da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* Increment device usrs counter */
5257da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	vpfe_dev->usrs++;
5267da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* Set io_allowed member to false */
5277da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	fh->io_allowed = 0;
5287da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* Initialize priority of this instance to default priority */
5297da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	fh->prio = V4L2_PRIORITY_UNSET;
5307da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	v4l2_prio_open(&vpfe_dev->prio, &fh->prio);
5317da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	mutex_unlock(&vpfe_dev->lock);
5327da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	return 0;
5337da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri}
5347da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
5357da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheristatic void vpfe_schedule_next_buffer(struct vpfe_device *vpfe_dev)
5367da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri{
5377da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	unsigned long addr;
5387da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
5397da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	vpfe_dev->next_frm = list_entry(vpfe_dev->dma_queue.next,
5407da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri					struct videobuf_buffer, queue);
5417da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	list_del(&vpfe_dev->next_frm->queue);
5427da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	vpfe_dev->next_frm->state = VIDEOBUF_ACTIVE;
5437da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	addr = videobuf_to_dma_contig(vpfe_dev->next_frm);
5447da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	ccdc_dev->hw_ops.setfbaddr(addr);
5457da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri}
5467da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
5477da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheristatic void vpfe_process_buffer_complete(struct vpfe_device *vpfe_dev)
5487da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri{
5497da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	struct timeval timevalue;
5507da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
5517da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	do_gettimeofday(&timevalue);
5527da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	vpfe_dev->cur_frm->ts = timevalue;
5537da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	vpfe_dev->cur_frm->state = VIDEOBUF_DONE;
5547da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	vpfe_dev->cur_frm->size = vpfe_dev->fmt.fmt.pix.sizeimage;
5557da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	wake_up_interruptible(&vpfe_dev->cur_frm->done);
5567da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	vpfe_dev->cur_frm = vpfe_dev->next_frm;
5577da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri}
5587da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
5597da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri/* ISR for VINT0*/
5607da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheristatic irqreturn_t vpfe_isr(int irq, void *dev_id)
5617da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri{
5627da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	struct vpfe_device *vpfe_dev = dev_id;
5637da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	enum v4l2_field field;
5647da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	unsigned long addr;
5657da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	int fid;
5667da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
5677da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "\nStarting vpfe_isr...\n");
5687da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	field = vpfe_dev->fmt.fmt.pix.field;
5697da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
5707da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* if streaming not started, don't do anything */
5717da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (!vpfe_dev->started)
5727da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		return IRQ_HANDLED;
5737da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
5747da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* only for 6446 this will be applicable */
5757da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (NULL != ccdc_dev->hw_ops.reset)
5767da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		ccdc_dev->hw_ops.reset();
5777da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
5787da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (field == V4L2_FIELD_NONE) {
5797da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		/* handle progressive frame capture */
5807da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev,
5817da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			"frame format is progressive...\n");
5827da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		if (vpfe_dev->cur_frm != vpfe_dev->next_frm)
5837da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			vpfe_process_buffer_complete(vpfe_dev);
5847da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		return IRQ_HANDLED;
5857da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
5867da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
5877da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* interlaced or TB capture check which field we are in hardware */
5887da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	fid = ccdc_dev->hw_ops.getfid();
5897da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
5907da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* switch the software maintained field id */
5917da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	vpfe_dev->field_id ^= 1;
5927da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "field id = %x:%x.\n",
5937da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		fid, vpfe_dev->field_id);
5947da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (fid == vpfe_dev->field_id) {
5957da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		/* we are in-sync here,continue */
5967da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		if (fid == 0) {
5977da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			/*
5987da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			 * One frame is just being captured. If the next frame
5997da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			 * is available, release the current frame and move on
6007da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			 */
6017da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			if (vpfe_dev->cur_frm != vpfe_dev->next_frm)
6027da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri				vpfe_process_buffer_complete(vpfe_dev);
6037da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			/*
6047da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			 * based on whether the two fields are stored
6057da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			 * interleavely or separately in memory, reconfigure
6067da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			 * the CCDC memory address
6077da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			 */
6087da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			if (field == V4L2_FIELD_SEQ_TB) {
6097da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri				addr =
6107da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri				  videobuf_to_dma_contig(vpfe_dev->cur_frm);
6117da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri				addr += vpfe_dev->field_off;
6127da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri				ccdc_dev->hw_ops.setfbaddr(addr);
6137da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			}
6147da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			return IRQ_HANDLED;
6157da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		}
6167da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		/*
6177da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		 * if one field is just being captured configure
6187da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		 * the next frame get the next frame from the empty
6197da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		 * queue if no frame is available hold on to the
6207da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		 * current buffer
6217da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		 */
6227da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		spin_lock(&vpfe_dev->dma_queue_lock);
6237da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		if (!list_empty(&vpfe_dev->dma_queue) &&
6247da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		    vpfe_dev->cur_frm == vpfe_dev->next_frm)
6257da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			vpfe_schedule_next_buffer(vpfe_dev);
6267da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		spin_unlock(&vpfe_dev->dma_queue_lock);
6277da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	} else if (fid == 0) {
6287da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		/*
6297da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		 * out of sync. Recover from any hardware out-of-sync.
6307da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		 * May loose one frame
6317da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		 */
6327da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		vpfe_dev->field_id = fid;
6337da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
6347da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	return IRQ_HANDLED;
6357da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri}
6367da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
6377da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri/* vdint1_isr - isr handler for VINT1 interrupt */
6387da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheristatic irqreturn_t vdint1_isr(int irq, void *dev_id)
6397da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri{
6407da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	struct vpfe_device *vpfe_dev = dev_id;
6417da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
6427da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "\nInside vdint1_isr...\n");
6437da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
6447da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* if streaming not started, don't do anything */
6457da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (!vpfe_dev->started)
6467da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		return IRQ_HANDLED;
6477da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
6487da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	spin_lock(&vpfe_dev->dma_queue_lock);
6497da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if ((vpfe_dev->fmt.fmt.pix.field == V4L2_FIELD_NONE) &&
6507da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	    !list_empty(&vpfe_dev->dma_queue) &&
6517da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	    vpfe_dev->cur_frm == vpfe_dev->next_frm)
6527da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		vpfe_schedule_next_buffer(vpfe_dev);
6537da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	spin_unlock(&vpfe_dev->dma_queue_lock);
6547da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	return IRQ_HANDLED;
6557da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri}
6567da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
6577da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheristatic void vpfe_detach_irq(struct vpfe_device *vpfe_dev)
6587da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri{
6597da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	enum ccdc_frmfmt frame_format;
6607da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
6617da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	frame_format = ccdc_dev->hw_ops.get_frame_format();
6627da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (frame_format == CCDC_FRMFMT_PROGRESSIVE)
6631ead696b4c1b719eeae313618bca89e7b37c7d9bVaibhav Hiremath		free_irq(vpfe_dev->ccdc_irq1, vpfe_dev);
6647da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri}
6657da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
6667da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheristatic int vpfe_attach_irq(struct vpfe_device *vpfe_dev)
6677da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri{
6687da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	enum ccdc_frmfmt frame_format;
6697da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
6707da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	frame_format = ccdc_dev->hw_ops.get_frame_format();
6717da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (frame_format == CCDC_FRMFMT_PROGRESSIVE) {
6727da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		return request_irq(vpfe_dev->ccdc_irq1, vdint1_isr,
6737da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri				    IRQF_DISABLED, "vpfe_capture1",
6747da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri				    vpfe_dev);
6757da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
6767da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	return 0;
6777da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri}
6787da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
6797da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri/* vpfe_stop_ccdc_capture: stop streaming in ccdc/isif */
6807da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheristatic void vpfe_stop_ccdc_capture(struct vpfe_device *vpfe_dev)
6817da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri{
6827da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	vpfe_dev->started = 0;
6837da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	ccdc_dev->hw_ops.enable(0);
6847da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (ccdc_dev->hw_ops.enable_out_to_sdram)
6857da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		ccdc_dev->hw_ops.enable_out_to_sdram(0);
6867da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri}
6877da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
6887da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri/*
6897da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri * vpfe_release : This function deletes buffer queue, frees the
6907da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri * buffers and the vpfe file  handle
6917da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri */
6927da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheristatic int vpfe_release(struct file *file)
6937da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri{
6947da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	struct vpfe_device *vpfe_dev = video_drvdata(file);
6957da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	struct vpfe_fh *fh = file->private_data;
6967da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	struct vpfe_subdev_info *sdinfo;
6977da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	int ret;
6987da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
6997da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_release\n");
7007da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
7017da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* Get the device lock */
7027da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	mutex_lock(&vpfe_dev->lock);
7037da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* if this instance is doing IO */
7047da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (fh->io_allowed) {
7057da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		if (vpfe_dev->started) {
7067da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			sdinfo = vpfe_dev->current_subdev;
7077da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev,
7087da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri							 sdinfo->grp_id,
7097da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri							 video, s_stream, 0);
7107da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			if (ret && (ret != -ENOIOCTLCMD))
7117da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri				v4l2_err(&vpfe_dev->v4l2_dev,
7127da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri				"stream off failed in subdev\n");
7137da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			vpfe_stop_ccdc_capture(vpfe_dev);
7147da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			vpfe_detach_irq(vpfe_dev);
7157da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			videobuf_streamoff(&vpfe_dev->buffer_queue);
7167da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		}
7177da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		vpfe_dev->io_usrs = 0;
7187da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		vpfe_dev->numbuffers = config_params.numbuffers;
7197da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
7207da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
7217da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* Decrement device usrs counter */
7227da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	vpfe_dev->usrs--;
7237da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* Close the priority */
7247da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	v4l2_prio_close(&vpfe_dev->prio, &fh->prio);
7257da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* If this is the last file handle */
7267da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (!vpfe_dev->usrs) {
7277da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		vpfe_dev->initialized = 0;
7287da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		if (ccdc_dev->hw_ops.close)
7297da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			ccdc_dev->hw_ops.close(vpfe_dev->pdev);
7307da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		module_put(ccdc_dev->owner);
7317da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
7327da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	mutex_unlock(&vpfe_dev->lock);
7337da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	file->private_data = NULL;
7347da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* Free memory allocated to file handle object */
7357da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	kfree(fh);
7367da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	return 0;
7377da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri}
7387da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
7397da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri/*
7407da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri * vpfe_mmap : It is used to map kernel space buffers
7417da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri * into user spaces
7427da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri */
7437da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheristatic int vpfe_mmap(struct file *file, struct vm_area_struct *vma)
7447da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri{
7457da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* Get the device object and file handle object */
7467da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	struct vpfe_device *vpfe_dev = video_drvdata(file);
7477da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
7487da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_mmap\n");
7497da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
7507da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	return videobuf_mmap_mapper(&vpfe_dev->buffer_queue, vma);
7517da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri}
7527da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
7537da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri/*
7547da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri * vpfe_poll: It is used for select/poll system call
7557da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri */
7567da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheristatic unsigned int vpfe_poll(struct file *file, poll_table *wait)
7577da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri{
7587da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	struct vpfe_device *vpfe_dev = video_drvdata(file);
7597da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
7607da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_poll\n");
7617da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
7627da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (vpfe_dev->started)
7637da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		return videobuf_poll_stream(file,
7647da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri					    &vpfe_dev->buffer_queue, wait);
7657da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	return 0;
7667da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri}
7677da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
7687da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri/* vpfe capture driver file operations */
7697da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheristatic const struct v4l2_file_operations vpfe_fops = {
7707da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	.owner = THIS_MODULE,
7717da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	.open = vpfe_open,
7727da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	.release = vpfe_release,
7737da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	.unlocked_ioctl = video_ioctl2,
7747da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	.mmap = vpfe_mmap,
7757da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	.poll = vpfe_poll
7767da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri};
7777da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
7787da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri/*
7797da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri * vpfe_check_format()
7807da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri * This function adjust the input pixel format as per hardware
7817da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri * capabilities and update the same in pixfmt.
7827da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri * Following algorithm used :-
7837da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri *
7847da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri *	If given pixformat is not in the vpfe list of pix formats or not
7857da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri *	supported by the hardware, current value of pixformat in the device
7867da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri *	is used
7877da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri *	If given field is not supported, then current field is used. If field
7887da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri *	is different from current, then it is matched with that from sub device.
7897da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri *	Minimum height is 2 lines for interlaced or tb field and 1 line for
7907da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri *	progressive. Maximum height is clamped to active active lines of scan
7917da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri *	Minimum width is 32 bytes in memory and width is clamped to active
7927da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri *	pixels of scan.
7937da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri *	bytesperline is a multiple of 32.
7947da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri */
7957da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheristatic const struct vpfe_pixel_format *
7967da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	vpfe_check_format(struct vpfe_device *vpfe_dev,
7977da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			  struct v4l2_pix_format *pixfmt)
7987da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri{
7997da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	u32 min_height = 1, min_width = 32, max_width, max_height;
8007da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	const struct vpfe_pixel_format *vpfe_pix_fmt;
8017da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	u32 pix;
8027da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	int temp, found;
8037da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
8047da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	vpfe_pix_fmt = vpfe_lookup_pix_format(pixfmt->pixelformat);
8057da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (NULL == vpfe_pix_fmt) {
8067da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		/*
8077da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		 * use current pixel format in the vpfe device. We
8087da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		 * will find this pix format in the table
8097da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		 */
8107da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		pixfmt->pixelformat = vpfe_dev->fmt.fmt.pix.pixelformat;
8117da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		vpfe_pix_fmt = vpfe_lookup_pix_format(pixfmt->pixelformat);
8127da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
8137da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
8147da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* check if hw supports it */
8157da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	temp = 0;
8167da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	found = 0;
8177da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	while (ccdc_dev->hw_ops.enum_pix(&pix, temp) >= 0) {
8187da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		if (vpfe_pix_fmt->fmtdesc.pixelformat == pix) {
8197da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			found = 1;
8207da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			break;
8217da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		}
8227da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		temp++;
8237da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
8247da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
8257da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (!found) {
8267da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		/* use current pixel format */
8277da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		pixfmt->pixelformat = vpfe_dev->fmt.fmt.pix.pixelformat;
8287da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		/*
8297da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		 * Since this is currently used in the vpfe device, we
8307da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		 * will find this pix format in the table
8317da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		 */
8327da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		vpfe_pix_fmt = vpfe_lookup_pix_format(pixfmt->pixelformat);
8337da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
8347da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
8357da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* check what field format is supported */
8367da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (pixfmt->field == V4L2_FIELD_ANY) {
8377da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		/* if field is any, use current value as default */
8387da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		pixfmt->field = vpfe_dev->fmt.fmt.pix.field;
8397da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
8407da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
8417da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/*
8427da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	 * if field is not same as current field in the vpfe device
8437da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	 * try matching the field with the sub device field
8447da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	 */
8457da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (vpfe_dev->fmt.fmt.pix.field != pixfmt->field) {
8467da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		/*
8477da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		 * If field value is not in the supported fields, use current
8487da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		 * field used in the device as default
8497da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		 */
8507da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		switch (pixfmt->field) {
8517da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		case V4L2_FIELD_INTERLACED:
8527da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		case V4L2_FIELD_SEQ_TB:
8537da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			/* if sub device is supporting progressive, use that */
8547da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			if (!vpfe_dev->std_info.frame_format)
8557da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri				pixfmt->field = V4L2_FIELD_NONE;
8567da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			break;
8577da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		case V4L2_FIELD_NONE:
8587da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			if (vpfe_dev->std_info.frame_format)
8597da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri				pixfmt->field = V4L2_FIELD_INTERLACED;
8607da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			break;
8617da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
8627da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		default:
8637da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			/* use current field as default */
8647da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			pixfmt->field = vpfe_dev->fmt.fmt.pix.field;
8657da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			break;
8667da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		}
8677da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
8687da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
8697da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* Now adjust image resolutions supported */
8707da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (pixfmt->field == V4L2_FIELD_INTERLACED ||
8717da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	    pixfmt->field == V4L2_FIELD_SEQ_TB)
8727da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		min_height = 2;
8737da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
8747da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	max_width = vpfe_dev->std_info.active_pixels;
8757da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	max_height = vpfe_dev->std_info.active_lines;
8767da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	min_width /= vpfe_pix_fmt->bpp;
8777da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
8787da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	v4l2_info(&vpfe_dev->v4l2_dev, "width = %d, height = %d, bpp = %d\n",
8797da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		  pixfmt->width, pixfmt->height, vpfe_pix_fmt->bpp);
8807da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
8817da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	pixfmt->width = clamp((pixfmt->width), min_width, max_width);
8827da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	pixfmt->height = clamp((pixfmt->height), min_height, max_height);
8837da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
8847da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* If interlaced, adjust height to be a multiple of 2 */
8857da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (pixfmt->field == V4L2_FIELD_INTERLACED)
8867da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		pixfmt->height &= (~1);
8877da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/*
8887da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	 * recalculate bytesperline and sizeimage since width
8897da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	 * and height might have changed
8907da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	 */
8917da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	pixfmt->bytesperline = (((pixfmt->width * vpfe_pix_fmt->bpp) + 31)
8927da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri				& ~31);
8937da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (pixfmt->pixelformat == V4L2_PIX_FMT_NV12)
8947da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		pixfmt->sizeimage =
8957da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			pixfmt->bytesperline * pixfmt->height +
8967da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			((pixfmt->bytesperline * pixfmt->height) >> 1);
8977da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	else
8987da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		pixfmt->sizeimage = pixfmt->bytesperline * pixfmt->height;
8997da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
9007da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	v4l2_info(&vpfe_dev->v4l2_dev, "adjusted width = %d, height ="
9017da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		 " %d, bpp = %d, bytesperline = %d, sizeimage = %d\n",
9027da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		 pixfmt->width, pixfmt->height, vpfe_pix_fmt->bpp,
9037da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		 pixfmt->bytesperline, pixfmt->sizeimage);
9047da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	return vpfe_pix_fmt;
9057da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri}
9067da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
9077da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheristatic int vpfe_querycap(struct file *file, void  *priv,
9087da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			       struct v4l2_capability *cap)
9097da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri{
9107da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	struct vpfe_device *vpfe_dev = video_drvdata(file);
9117da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
9127da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_querycap\n");
9137da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
9147da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	cap->version = VPFE_CAPTURE_VERSION_CODE;
9157da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
9167da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	strlcpy(cap->driver, CAPTURE_DRV_NAME, sizeof(cap->driver));
9177da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	strlcpy(cap->bus_info, "VPFE", sizeof(cap->bus_info));
9187da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	strlcpy(cap->card, vpfe_dev->cfg->card_name, sizeof(cap->card));
9197da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	return 0;
9207da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri}
9217da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
9227da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheristatic int vpfe_g_fmt_vid_cap(struct file *file, void *priv,
9237da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri				struct v4l2_format *fmt)
9247da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri{
9257da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	struct vpfe_device *vpfe_dev = video_drvdata(file);
9267da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	int ret = 0;
9277da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
9287da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_g_fmt_vid_cap\n");
9297da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* Fill in the information about format */
9307da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	*fmt = vpfe_dev->fmt;
9317da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	return ret;
9327da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri}
9337da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
9347da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheristatic int vpfe_enum_fmt_vid_cap(struct file *file, void  *priv,
9357da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri				   struct v4l2_fmtdesc *fmt)
9367da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri{
9377da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	struct vpfe_device *vpfe_dev = video_drvdata(file);
9387da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	const struct vpfe_pixel_format *pix_fmt;
9397da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	int temp_index;
9407da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	u32 pix;
9417da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
9427da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_enum_fmt_vid_cap\n");
9437da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
9447da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (ccdc_dev->hw_ops.enum_pix(&pix, fmt->index) < 0)
9457da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		return -EINVAL;
9467da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
9477da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* Fill in the information about format */
9487da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	pix_fmt = vpfe_lookup_pix_format(pix);
9497da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (NULL != pix_fmt) {
9507da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		temp_index = fmt->index;
9517da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		*fmt = pix_fmt->fmtdesc;
9527da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		fmt->index = temp_index;
9537da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		return 0;
9547da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
9557da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	return -EINVAL;
9567da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri}
9577da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
9587da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheristatic int vpfe_s_fmt_vid_cap(struct file *file, void *priv,
9597da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri				struct v4l2_format *fmt)
9607da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri{
9617da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	struct vpfe_device *vpfe_dev = video_drvdata(file);
9627da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	const struct vpfe_pixel_format *pix_fmts;
9637da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	int ret = 0;
9647da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
9657da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_fmt_vid_cap\n");
9667da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
9677da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* If streaming is started, return error */
9687da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (vpfe_dev->started) {
9697da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		v4l2_err(&vpfe_dev->v4l2_dev, "Streaming is started\n");
9707da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		return -EBUSY;
9717da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
9727da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
9737da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* Check for valid frame format */
9747da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	pix_fmts = vpfe_check_format(vpfe_dev, &fmt->fmt.pix);
9757da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
9767da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (NULL == pix_fmts)
9777da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		return -EINVAL;
9787da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
9797da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* store the pixel format in the device  object */
9807da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	ret = mutex_lock_interruptible(&vpfe_dev->lock);
9817da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (ret)
9827da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		return ret;
9837da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
9847da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* First detach any IRQ if currently attached */
9857da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	vpfe_detach_irq(vpfe_dev);
9867da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	vpfe_dev->fmt = *fmt;
9877da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* set image capture parameters in the ccdc */
9887da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	ret = vpfe_config_ccdc_image_format(vpfe_dev);
9897da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	mutex_unlock(&vpfe_dev->lock);
9907da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	return ret;
9917da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri}
9927da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
9937da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheristatic int vpfe_try_fmt_vid_cap(struct file *file, void *priv,
9947da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri				  struct v4l2_format *f)
9957da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri{
9967da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	struct vpfe_device *vpfe_dev = video_drvdata(file);
9977da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	const struct vpfe_pixel_format *pix_fmts;
9987da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
9997da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_try_fmt_vid_cap\n");
10007da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
10017da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	pix_fmts = vpfe_check_format(vpfe_dev, &f->fmt.pix);
10027da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (NULL == pix_fmts)
10037da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		return -EINVAL;
10047da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	return 0;
10057da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri}
10067da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
10077da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri/*
10087da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri * vpfe_get_subdev_input_index - Get subdev index and subdev input index for a
10097da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri * given app input index
10107da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri */
10117da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheristatic int vpfe_get_subdev_input_index(struct vpfe_device *vpfe_dev,
10127da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri					int *subdev_index,
10137da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri					int *subdev_input_index,
10147da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri					int app_input_index)
10157da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri{
10167da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	struct vpfe_config *cfg = vpfe_dev->cfg;
10177da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	struct vpfe_subdev_info *sdinfo;
10187da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	int i, j = 0;
10197da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
10207da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	for (i = 0; i < cfg->num_subdevs; i++) {
10217da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		sdinfo = &cfg->sub_devs[i];
10227da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		if (app_input_index < (j + sdinfo->num_inputs)) {
10237da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			*subdev_index = i;
10247da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			*subdev_input_index = app_input_index - j;
10257da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			return 0;
10267da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		}
10277da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		j += sdinfo->num_inputs;
10287da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
10297da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	return -EINVAL;
10307da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri}
10317da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
10327da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri/*
10337da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri * vpfe_get_app_input - Get app input index for a given subdev input index
10347da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri * driver stores the input index of the current sub device and translate it
10357da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri * when application request the current input
10367da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri */
10377da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheristatic int vpfe_get_app_input_index(struct vpfe_device *vpfe_dev,
10387da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri				    int *app_input_index)
10397da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri{
10407da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	struct vpfe_config *cfg = vpfe_dev->cfg;
10417da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	struct vpfe_subdev_info *sdinfo;
10427da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	int i, j = 0;
10437da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
10447da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	for (i = 0; i < cfg->num_subdevs; i++) {
10457da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		sdinfo = &cfg->sub_devs[i];
10467da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		if (!strcmp(sdinfo->name, vpfe_dev->current_subdev->name)) {
10477da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			if (vpfe_dev->current_input >= sdinfo->num_inputs)
10487da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri				return -1;
10497da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			*app_input_index = j + vpfe_dev->current_input;
10507da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			return 0;
10517da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		}
10527da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		j += sdinfo->num_inputs;
10537da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
10547da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	return -EINVAL;
10557da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri}
10567da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
10577da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheristatic int vpfe_enum_input(struct file *file, void *priv,
10587da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri				 struct v4l2_input *inp)
10597da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri{
10607da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	struct vpfe_device *vpfe_dev = video_drvdata(file);
10617da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	struct vpfe_subdev_info *sdinfo;
10627da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	int subdev, index ;
10637da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
10647da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_enum_input\n");
10657da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
10667da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (vpfe_get_subdev_input_index(vpfe_dev,
10677da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri					&subdev,
10687da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri					&index,
10697da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri					inp->index) < 0) {
10707da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		v4l2_err(&vpfe_dev->v4l2_dev, "input information not found"
10717da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			 " for the subdev\n");
10727da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		return -EINVAL;
10737da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
10747da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	sdinfo = &vpfe_dev->cfg->sub_devs[subdev];
10757da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	memcpy(inp, &sdinfo->inputs[index], sizeof(struct v4l2_input));
10767da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	return 0;
10777da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri}
10787da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
10797da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheristatic int vpfe_g_input(struct file *file, void *priv, unsigned int *index)
10807da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri{
10817da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	struct vpfe_device *vpfe_dev = video_drvdata(file);
10827da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
10837da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_g_input\n");
10847da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
10857da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	return vpfe_get_app_input_index(vpfe_dev, index);
10867da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri}
10877da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
10887da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
10897da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheristatic int vpfe_s_input(struct file *file, void *priv, unsigned int index)
10907da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri{
10917da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	struct vpfe_device *vpfe_dev = video_drvdata(file);
10927da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	struct vpfe_subdev_info *sdinfo;
10937da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	int subdev_index, inp_index;
10947da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	struct vpfe_route *route;
10957da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	u32 input = 0, output = 0;
10967da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	int ret = -EINVAL;
10977da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
10987da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_input\n");
10997da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
11007da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	ret = mutex_lock_interruptible(&vpfe_dev->lock);
11017da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (ret)
11027da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		return ret;
11037da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
11047da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/*
11057da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	 * If streaming is started return device busy
11067da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	 * error
11077da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	 */
11087da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (vpfe_dev->started) {
11097da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		v4l2_err(&vpfe_dev->v4l2_dev, "Streaming is on\n");
11107da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		ret = -EBUSY;
11117da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		goto unlock_out;
11127da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
11137da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
11147da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (vpfe_get_subdev_input_index(vpfe_dev,
11157da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri					&subdev_index,
11167da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri					&inp_index,
11177da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri					index) < 0) {
11187da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		v4l2_err(&vpfe_dev->v4l2_dev, "invalid input index\n");
11197da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		goto unlock_out;
11207da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
11217da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
11227da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	sdinfo = &vpfe_dev->cfg->sub_devs[subdev_index];
11237da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	route = &sdinfo->routes[inp_index];
11247da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (route && sdinfo->can_route) {
11257da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		input = route->input;
11267da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		output = route->output;
11277da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
11287da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
11297da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id,
11307da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri					 video, s_routing, input, output, 0);
11317da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
11327da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (ret) {
11337da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		v4l2_err(&vpfe_dev->v4l2_dev,
11347da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			"vpfe_doioctl:error in setting input in decoder\n");
11357da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		ret = -EINVAL;
11367da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		goto unlock_out;
11377da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
11387da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	vpfe_dev->current_subdev = sdinfo;
11397da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	vpfe_dev->current_input = index;
11407da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	vpfe_dev->std_index = 0;
11417da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
11427da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* set the bus/interface parameter for the sub device in ccdc */
11437da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	ret = ccdc_dev->hw_ops.set_hw_if_params(&sdinfo->ccdc_if_params);
11447da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (ret)
11457da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		goto unlock_out;
11467da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
11477da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* set the default image parameters in the device */
11487da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	ret = vpfe_config_image_format(vpfe_dev,
11497da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri				&vpfe_standards[vpfe_dev->std_index].std_id);
11507da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheriunlock_out:
11517da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	mutex_unlock(&vpfe_dev->lock);
11527da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	return ret;
11537da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri}
11547da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
11557da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheristatic int vpfe_querystd(struct file *file, void *priv, v4l2_std_id *std_id)
11567da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri{
11577da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	struct vpfe_device *vpfe_dev = video_drvdata(file);
11587da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	struct vpfe_subdev_info *sdinfo;
11597da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	int ret = 0;
11607da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
11617da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_querystd\n");
11627da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
11637da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	ret = mutex_lock_interruptible(&vpfe_dev->lock);
11647da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	sdinfo = vpfe_dev->current_subdev;
11657da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (ret)
11667da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		return ret;
11677da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* Call querystd function of decoder device */
11687da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id,
11697da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri					 video, querystd, std_id);
11707da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	mutex_unlock(&vpfe_dev->lock);
11717da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	return ret;
11727da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri}
11737da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
11747da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheristatic int vpfe_s_std(struct file *file, void *priv, v4l2_std_id *std_id)
11757da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri{
11767da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	struct vpfe_device *vpfe_dev = video_drvdata(file);
11777da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	struct vpfe_subdev_info *sdinfo;
11787da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	int ret = 0;
11797da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
11807da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_std\n");
11817da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
11827da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* Call decoder driver function to set the standard */
11837da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	ret = mutex_lock_interruptible(&vpfe_dev->lock);
11847da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (ret)
11857da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		return ret;
11867da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
11877da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	sdinfo = vpfe_dev->current_subdev;
11887da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* If streaming is started, return device busy error */
11897da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (vpfe_dev->started) {
11907da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		v4l2_err(&vpfe_dev->v4l2_dev, "streaming is started\n");
11917da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		ret = -EBUSY;
11927da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		goto unlock_out;
11937da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
11947da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
11957da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id,
11967da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri					 core, s_std, *std_id);
11977da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (ret < 0) {
11987da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		v4l2_err(&vpfe_dev->v4l2_dev, "Failed to set standard\n");
11997da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		goto unlock_out;
12007da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
12017da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	ret = vpfe_config_image_format(vpfe_dev, std_id);
12027da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
12037da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheriunlock_out:
12047da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	mutex_unlock(&vpfe_dev->lock);
12057da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	return ret;
12067da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri}
12077da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
12087da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheristatic int vpfe_g_std(struct file *file, void *priv, v4l2_std_id *std_id)
12097da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri{
12107da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	struct vpfe_device *vpfe_dev = video_drvdata(file);
12117da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
12127da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_g_std\n");
12137da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
12147da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	*std_id = vpfe_standards[vpfe_dev->std_index].std_id;
12157da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	return 0;
12167da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri}
12177da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri/*
12187da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri *  Videobuf operations
12197da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri */
12207da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheristatic int vpfe_videobuf_setup(struct videobuf_queue *vq,
12217da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri				unsigned int *count,
12227da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri				unsigned int *size)
12237da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri{
12247da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	struct vpfe_fh *fh = vq->priv_data;
12257da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	struct vpfe_device *vpfe_dev = fh->vpfe_dev;
12267da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
12277da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_buffer_setup\n");
12287da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	*size = config_params.device_bufsize;
12297da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
12307da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (*count < config_params.min_numbuffers)
12317da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		*count = config_params.min_numbuffers;
12327da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev,
12337da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		"count=%d, size=%d\n", *count, *size);
12347da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	return 0;
12357da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri}
12367da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
12377da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheristatic int vpfe_videobuf_prepare(struct videobuf_queue *vq,
12387da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri				struct videobuf_buffer *vb,
12397da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri				enum v4l2_field field)
12407da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri{
12417da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	struct vpfe_fh *fh = vq->priv_data;
12427da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	struct vpfe_device *vpfe_dev = fh->vpfe_dev;
12437da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
12447da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_buffer_prepare\n");
12457da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
12467da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* If buffer is not initialized, initialize it */
12477da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (VIDEOBUF_NEEDS_INIT == vb->state) {
12487da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		vb->width = vpfe_dev->fmt.fmt.pix.width;
12497da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		vb->height = vpfe_dev->fmt.fmt.pix.height;
12507da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		vb->size = vpfe_dev->fmt.fmt.pix.sizeimage;
12517da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		vb->field = field;
12527da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
12537da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	vb->state = VIDEOBUF_PREPARED;
12547da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	return 0;
12557da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri}
12567da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
12577da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheristatic void vpfe_videobuf_queue(struct videobuf_queue *vq,
12587da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri				struct videobuf_buffer *vb)
12597da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri{
12607da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* Get the file handle object and device object */
12617da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	struct vpfe_fh *fh = vq->priv_data;
12627da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	struct vpfe_device *vpfe_dev = fh->vpfe_dev;
12637da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	unsigned long flags;
12647da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
12657da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_buffer_queue\n");
12667da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
12677da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* add the buffer to the DMA queue */
12687da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	spin_lock_irqsave(&vpfe_dev->dma_queue_lock, flags);
12697da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	list_add_tail(&vb->queue, &vpfe_dev->dma_queue);
12707da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	spin_unlock_irqrestore(&vpfe_dev->dma_queue_lock, flags);
12717da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
12727da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* Change state of the buffer */
12737da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	vb->state = VIDEOBUF_QUEUED;
12747da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri}
12757da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
12767da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheristatic void vpfe_videobuf_release(struct videobuf_queue *vq,
12777da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri				  struct videobuf_buffer *vb)
12787da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri{
12797da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	struct vpfe_fh *fh = vq->priv_data;
12807da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	struct vpfe_device *vpfe_dev = fh->vpfe_dev;
12817da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	unsigned long flags;
12827da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
12837da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_videobuf_release\n");
12847da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
12857da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/*
12867da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	 * We need to flush the buffer from the dma queue since
12877da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	 * they are de-allocated
12887da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	 */
12897da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	spin_lock_irqsave(&vpfe_dev->dma_queue_lock, flags);
12907da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	INIT_LIST_HEAD(&vpfe_dev->dma_queue);
12917da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	spin_unlock_irqrestore(&vpfe_dev->dma_queue_lock, flags);
12927da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	videobuf_dma_contig_free(vq, vb);
12937da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	vb->state = VIDEOBUF_NEEDS_INIT;
12947da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri}
12957da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
12967da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheristatic struct videobuf_queue_ops vpfe_videobuf_qops = {
12977da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	.buf_setup      = vpfe_videobuf_setup,
12987da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	.buf_prepare    = vpfe_videobuf_prepare,
12997da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	.buf_queue      = vpfe_videobuf_queue,
13007da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	.buf_release    = vpfe_videobuf_release,
13017da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri};
13027da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
13037da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri/*
13047da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri * vpfe_reqbufs. currently support REQBUF only once opening
13057da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri * the device.
13067da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri */
13077da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheristatic int vpfe_reqbufs(struct file *file, void *priv,
13087da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			struct v4l2_requestbuffers *req_buf)
13097da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri{
13107da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	struct vpfe_device *vpfe_dev = video_drvdata(file);
13117da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	struct vpfe_fh *fh = file->private_data;
13127da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	int ret = 0;
13137da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
13147da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_reqbufs\n");
13157da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
13167da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (V4L2_BUF_TYPE_VIDEO_CAPTURE != req_buf->type) {
13177da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buffer type\n");
13187da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		return -EINVAL;
13197da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
13207da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
13217da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (V4L2_MEMORY_USERPTR == req_buf->memory) {
13227da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		/* we don't support user ptr IO */
13237da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_reqbufs:"
13247da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			 " USERPTR IO not supported\n");
13257da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		return  -EINVAL;
13267da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
13277da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
13287da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	ret = mutex_lock_interruptible(&vpfe_dev->lock);
13297da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (ret)
13307da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		return ret;
13317da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
13327da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (vpfe_dev->io_usrs != 0) {
13337da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		v4l2_err(&vpfe_dev->v4l2_dev, "Only one IO user allowed\n");
13347da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		ret = -EBUSY;
13357da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		goto unlock_out;
13367da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
13377da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
13387da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	vpfe_dev->memory = req_buf->memory;
13397da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	videobuf_queue_dma_contig_init(&vpfe_dev->buffer_queue,
13407da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri				&vpfe_videobuf_qops,
1341204e6ea981ac46974508ddf403dbb72dc804dcb3Vaibhav Hiremath				vpfe_dev->pdev,
13427da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri				&vpfe_dev->irqlock,
13437da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri				req_buf->type,
13447da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri				vpfe_dev->fmt.fmt.pix.field,
13457da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri				sizeof(struct videobuf_buffer),
13467da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri				fh);
13477da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
13487da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	fh->io_allowed = 1;
13497da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	vpfe_dev->io_usrs = 1;
13507da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	INIT_LIST_HEAD(&vpfe_dev->dma_queue);
13517da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	ret = videobuf_reqbufs(&vpfe_dev->buffer_queue, req_buf);
13527da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheriunlock_out:
13537da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	mutex_unlock(&vpfe_dev->lock);
13547da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	return ret;
13557da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri}
13567da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
13577da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheristatic int vpfe_querybuf(struct file *file, void *priv,
13587da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			 struct v4l2_buffer *buf)
13597da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri{
13607da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	struct vpfe_device *vpfe_dev = video_drvdata(file);
13617da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
13627da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_querybuf\n");
13637da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
13647da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (V4L2_BUF_TYPE_VIDEO_CAPTURE != buf->type) {
13657da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf type\n");
13667da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		return  -EINVAL;
13677da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
13687da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
13697da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (vpfe_dev->memory != V4L2_MEMORY_MMAP) {
13707da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		v4l2_err(&vpfe_dev->v4l2_dev, "Invalid memory\n");
13717da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		return -EINVAL;
13727da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
13737da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* Call videobuf_querybuf to get information */
13747da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	return videobuf_querybuf(&vpfe_dev->buffer_queue, buf);
13757da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri}
13767da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
13777da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheristatic int vpfe_qbuf(struct file *file, void *priv,
13787da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		     struct v4l2_buffer *p)
13797da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri{
13807da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	struct vpfe_device *vpfe_dev = video_drvdata(file);
13817da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	struct vpfe_fh *fh = file->private_data;
13827da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
13837da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_qbuf\n");
13847da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
13857da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (V4L2_BUF_TYPE_VIDEO_CAPTURE != p->type) {
13867da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf type\n");
13877da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		return -EINVAL;
13887da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
13897da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
13907da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/*
13917da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	 * If this file handle is not allowed to do IO,
13927da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	 * return error
13937da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	 */
13947da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (!fh->io_allowed) {
13957da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		v4l2_err(&vpfe_dev->v4l2_dev, "fh->io_allowed\n");
13967da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		return -EACCES;
13977da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
13987da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	return videobuf_qbuf(&vpfe_dev->buffer_queue, p);
13997da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri}
14007da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
14017da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheristatic int vpfe_dqbuf(struct file *file, void *priv,
14027da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		      struct v4l2_buffer *buf)
14037da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri{
14047da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	struct vpfe_device *vpfe_dev = video_drvdata(file);
14057da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
14067da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_dqbuf\n");
14077da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
14087da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (V4L2_BUF_TYPE_VIDEO_CAPTURE != buf->type) {
14097da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf type\n");
14107da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		return -EINVAL;
14117da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
14127da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	return videobuf_dqbuf(&vpfe_dev->buffer_queue,
14137da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri				      buf, file->f_flags & O_NONBLOCK);
14147da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri}
14157da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
1416d73bfc5fe625f6962d0ced84066e201249f14e53Vaibhav Hiremathstatic int vpfe_queryctrl(struct file *file, void *priv,
1417d73bfc5fe625f6962d0ced84066e201249f14e53Vaibhav Hiremath		struct v4l2_queryctrl *qctrl)
1418d73bfc5fe625f6962d0ced84066e201249f14e53Vaibhav Hiremath{
1419d73bfc5fe625f6962d0ced84066e201249f14e53Vaibhav Hiremath	struct vpfe_device *vpfe_dev = video_drvdata(file);
1420d73bfc5fe625f6962d0ced84066e201249f14e53Vaibhav Hiremath	struct vpfe_subdev_info *sdinfo;
1421d73bfc5fe625f6962d0ced84066e201249f14e53Vaibhav Hiremath
1422d73bfc5fe625f6962d0ced84066e201249f14e53Vaibhav Hiremath	sdinfo = vpfe_dev->current_subdev;
1423d73bfc5fe625f6962d0ced84066e201249f14e53Vaibhav Hiremath
1424d73bfc5fe625f6962d0ced84066e201249f14e53Vaibhav Hiremath	return v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id,
1425d73bfc5fe625f6962d0ced84066e201249f14e53Vaibhav Hiremath					 core, queryctrl, qctrl);
1426d73bfc5fe625f6962d0ced84066e201249f14e53Vaibhav Hiremath
1427d73bfc5fe625f6962d0ced84066e201249f14e53Vaibhav Hiremath}
1428d73bfc5fe625f6962d0ced84066e201249f14e53Vaibhav Hiremath
1429d73bfc5fe625f6962d0ced84066e201249f14e53Vaibhav Hiremathstatic int vpfe_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl)
1430d73bfc5fe625f6962d0ced84066e201249f14e53Vaibhav Hiremath{
1431d73bfc5fe625f6962d0ced84066e201249f14e53Vaibhav Hiremath	struct vpfe_device *vpfe_dev = video_drvdata(file);
1432d73bfc5fe625f6962d0ced84066e201249f14e53Vaibhav Hiremath	struct vpfe_subdev_info *sdinfo;
1433d73bfc5fe625f6962d0ced84066e201249f14e53Vaibhav Hiremath
1434d73bfc5fe625f6962d0ced84066e201249f14e53Vaibhav Hiremath	sdinfo = vpfe_dev->current_subdev;
1435d73bfc5fe625f6962d0ced84066e201249f14e53Vaibhav Hiremath
1436d73bfc5fe625f6962d0ced84066e201249f14e53Vaibhav Hiremath	return v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id,
1437d73bfc5fe625f6962d0ced84066e201249f14e53Vaibhav Hiremath					 core, g_ctrl, ctrl);
1438d73bfc5fe625f6962d0ced84066e201249f14e53Vaibhav Hiremath}
1439d73bfc5fe625f6962d0ced84066e201249f14e53Vaibhav Hiremath
1440d73bfc5fe625f6962d0ced84066e201249f14e53Vaibhav Hiremathstatic int vpfe_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl)
1441d73bfc5fe625f6962d0ced84066e201249f14e53Vaibhav Hiremath{
1442d73bfc5fe625f6962d0ced84066e201249f14e53Vaibhav Hiremath	struct vpfe_device *vpfe_dev = video_drvdata(file);
1443d73bfc5fe625f6962d0ced84066e201249f14e53Vaibhav Hiremath	struct vpfe_subdev_info *sdinfo;
1444d73bfc5fe625f6962d0ced84066e201249f14e53Vaibhav Hiremath
1445d73bfc5fe625f6962d0ced84066e201249f14e53Vaibhav Hiremath	sdinfo = vpfe_dev->current_subdev;
1446d73bfc5fe625f6962d0ced84066e201249f14e53Vaibhav Hiremath
1447d73bfc5fe625f6962d0ced84066e201249f14e53Vaibhav Hiremath	return v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id,
1448d73bfc5fe625f6962d0ced84066e201249f14e53Vaibhav Hiremath					 core, s_ctrl, ctrl);
1449d73bfc5fe625f6962d0ced84066e201249f14e53Vaibhav Hiremath}
1450d73bfc5fe625f6962d0ced84066e201249f14e53Vaibhav Hiremath
14517da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri/*
14527da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri * vpfe_calculate_offsets : This function calculates buffers offset
14537da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri * for top and bottom field
14547da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri */
14557da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheristatic void vpfe_calculate_offsets(struct vpfe_device *vpfe_dev)
14567da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri{
14577da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	struct v4l2_rect image_win;
14587da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
14597da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_calculate_offsets\n");
14607da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
14617da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	ccdc_dev->hw_ops.get_image_window(&image_win);
14627da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	vpfe_dev->field_off = image_win.height * image_win.width;
14637da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri}
14647da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
14657da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri/* vpfe_start_ccdc_capture: start streaming in ccdc/isif */
14667da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheristatic void vpfe_start_ccdc_capture(struct vpfe_device *vpfe_dev)
14677da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri{
14687da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	ccdc_dev->hw_ops.enable(1);
14697da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (ccdc_dev->hw_ops.enable_out_to_sdram)
14707da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		ccdc_dev->hw_ops.enable_out_to_sdram(1);
14717da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	vpfe_dev->started = 1;
14727da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri}
14737da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
14747da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri/*
14757da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri * vpfe_streamon. Assume the DMA queue is not empty.
14767da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri * application is expected to call QBUF before calling
14777da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri * this ioctl. If not, driver returns error
14787da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri */
14797da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheristatic int vpfe_streamon(struct file *file, void *priv,
14807da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			 enum v4l2_buf_type buf_type)
14817da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri{
14827da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	struct vpfe_device *vpfe_dev = video_drvdata(file);
14837da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	struct vpfe_fh *fh = file->private_data;
14847da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	struct vpfe_subdev_info *sdinfo;
14857da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	unsigned long addr;
14867da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	int ret = 0;
14877da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
14887da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_streamon\n");
14897da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
14907da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (V4L2_BUF_TYPE_VIDEO_CAPTURE != buf_type) {
14917da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf type\n");
14927da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		return -EINVAL;
14937da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
14947da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
14957da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* If file handle is not allowed IO, return error */
14967da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (!fh->io_allowed) {
14977da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		v4l2_err(&vpfe_dev->v4l2_dev, "fh->io_allowed\n");
14987da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		return -EACCES;
14997da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
15007da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
15017da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	sdinfo = vpfe_dev->current_subdev;
15027da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id,
15037da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri					video, s_stream, 1);
15047da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
15057da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (ret && (ret != -ENOIOCTLCMD)) {
15067da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		v4l2_err(&vpfe_dev->v4l2_dev, "stream on failed in subdev\n");
15077da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		return -EINVAL;
15087da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
15097da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
15107da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* If buffer queue is empty, return error */
15117da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (list_empty(&vpfe_dev->buffer_queue.stream)) {
15127da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		v4l2_err(&vpfe_dev->v4l2_dev, "buffer queue is empty\n");
15137da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		return -EIO;
15147da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
15157da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
15167da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* Call videobuf_streamon to start streaming * in videobuf */
15177da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	ret = videobuf_streamon(&vpfe_dev->buffer_queue);
15187da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (ret)
15197da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		return ret;
15207da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
15217da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
15227da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	ret = mutex_lock_interruptible(&vpfe_dev->lock);
15237da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (ret)
15247da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		goto streamoff;
15257da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* Get the next frame from the buffer queue */
15267da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	vpfe_dev->next_frm = list_entry(vpfe_dev->dma_queue.next,
15277da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri					struct videobuf_buffer, queue);
15287da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	vpfe_dev->cur_frm = vpfe_dev->next_frm;
15297da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* Remove buffer from the buffer queue */
15307da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	list_del(&vpfe_dev->cur_frm->queue);
15317da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* Mark state of the current frame to active */
15327da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	vpfe_dev->cur_frm->state = VIDEOBUF_ACTIVE;
15337da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* Initialize field_id and started member */
15347da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	vpfe_dev->field_id = 0;
15357da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	addr = videobuf_to_dma_contig(vpfe_dev->cur_frm);
15367da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
15377da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* Calculate field offset */
15387da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	vpfe_calculate_offsets(vpfe_dev);
15397da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
15407da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (vpfe_attach_irq(vpfe_dev) < 0) {
15417da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		v4l2_err(&vpfe_dev->v4l2_dev,
15427da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			 "Error in attaching interrupt handle\n");
15437da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		ret = -EFAULT;
15447da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		goto unlock_out;
15457da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
15467da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (ccdc_dev->hw_ops.configure() < 0) {
15477da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		v4l2_err(&vpfe_dev->v4l2_dev,
15487da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			 "Error in configuring ccdc\n");
15497da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		ret = -EINVAL;
15507da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		goto unlock_out;
15517da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
15527da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	ccdc_dev->hw_ops.setfbaddr((unsigned long)(addr));
15537da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	vpfe_start_ccdc_capture(vpfe_dev);
15547da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	mutex_unlock(&vpfe_dev->lock);
15557da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	return ret;
15567da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheriunlock_out:
15577da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	mutex_unlock(&vpfe_dev->lock);
15587da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheristreamoff:
15597da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	ret = videobuf_streamoff(&vpfe_dev->buffer_queue);
15607da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	return ret;
15617da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri}
15627da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
15637da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheristatic int vpfe_streamoff(struct file *file, void *priv,
15647da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			  enum v4l2_buf_type buf_type)
15657da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri{
15667da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	struct vpfe_device *vpfe_dev = video_drvdata(file);
15677da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	struct vpfe_fh *fh = file->private_data;
15687da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	struct vpfe_subdev_info *sdinfo;
15697da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	int ret = 0;
15707da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
15717da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_streamoff\n");
15727da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
15737da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (V4L2_BUF_TYPE_VIDEO_CAPTURE != buf_type) {
15747da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf type\n");
15757da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		return -EINVAL;
15767da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
15777da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
15787da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* If io is allowed for this file handle, return error */
15797da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (!fh->io_allowed) {
15807da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		v4l2_err(&vpfe_dev->v4l2_dev, "fh->io_allowed\n");
15817da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		return -EACCES;
15827da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
15837da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
15847da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* If streaming is not started, return error */
15857da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (!vpfe_dev->started) {
15867da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		v4l2_err(&vpfe_dev->v4l2_dev, "device started\n");
15877da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		return -EINVAL;
15887da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
15897da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
15907da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	ret = mutex_lock_interruptible(&vpfe_dev->lock);
15917da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (ret)
15927da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		return ret;
15937da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
15947da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	vpfe_stop_ccdc_capture(vpfe_dev);
15957da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	vpfe_detach_irq(vpfe_dev);
15967da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
15977da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	sdinfo = vpfe_dev->current_subdev;
15987da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id,
15997da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri					video, s_stream, 0);
16007da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
16017da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (ret && (ret != -ENOIOCTLCMD))
16027da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		v4l2_err(&vpfe_dev->v4l2_dev, "stream off failed in subdev\n");
16037da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	ret = videobuf_streamoff(&vpfe_dev->buffer_queue);
16047da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	mutex_unlock(&vpfe_dev->lock);
16057da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	return ret;
16067da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri}
16077da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
16087da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheristatic int vpfe_cropcap(struct file *file, void *priv,
16097da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			      struct v4l2_cropcap *crop)
16107da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri{
16117da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	struct vpfe_device *vpfe_dev = video_drvdata(file);
16127da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
16137da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_cropcap\n");
16147da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
16150b66cf90371dcd28c6eb98904adb694ae98eb20fRoel Kluin	if (vpfe_dev->std_index >= ARRAY_SIZE(vpfe_standards))
16167da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		return -EINVAL;
16177da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
16187da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	memset(crop, 0, sizeof(struct v4l2_cropcap));
16197da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	crop->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
16207da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	crop->bounds.width = crop->defrect.width =
16217da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		vpfe_standards[vpfe_dev->std_index].width;
16227da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	crop->bounds.height = crop->defrect.height =
16237da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		vpfe_standards[vpfe_dev->std_index].height;
16247da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	crop->pixelaspect = vpfe_standards[vpfe_dev->std_index].pixelaspect;
16257da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	return 0;
16267da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri}
16277da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
16287da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheristatic int vpfe_g_crop(struct file *file, void *priv,
16297da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			     struct v4l2_crop *crop)
16307da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri{
16317da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	struct vpfe_device *vpfe_dev = video_drvdata(file);
16327da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
16337da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_g_crop\n");
16347da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
16357da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	crop->c = vpfe_dev->crop;
16367da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	return 0;
16377da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri}
16387da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
16397da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheristatic int vpfe_s_crop(struct file *file, void *priv,
16407da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			     struct v4l2_crop *crop)
16417da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri{
16427da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	struct vpfe_device *vpfe_dev = video_drvdata(file);
16437da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	int ret = 0;
16447da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
16457da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_crop\n");
16467da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
16477da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (vpfe_dev->started) {
16487da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		/* make sure streaming is not started */
16497da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		v4l2_err(&vpfe_dev->v4l2_dev,
16507da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			"Cannot change crop when streaming is ON\n");
16517da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		return -EBUSY;
16527da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
16537da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
16547da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	ret = mutex_lock_interruptible(&vpfe_dev->lock);
16557da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (ret)
16567da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		return ret;
16577da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
16587da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (crop->c.top < 0 || crop->c.left < 0) {
16597da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		v4l2_err(&vpfe_dev->v4l2_dev,
16607da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			"doesn't support negative values for top & left\n");
16617da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		ret = -EINVAL;
16627da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		goto unlock_out;
16637da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
16647da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
16657da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* adjust the width to 16 pixel boundry */
16667da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	crop->c.width = ((crop->c.width + 15) & ~0xf);
16677da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
16687da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* make sure parameters are valid */
16697da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if ((crop->c.left + crop->c.width >
16707da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		vpfe_dev->std_info.active_pixels) ||
16717da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	    (crop->c.top + crop->c.height >
16727da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		vpfe_dev->std_info.active_lines)) {
16737da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		v4l2_err(&vpfe_dev->v4l2_dev, "Error in S_CROP params\n");
16747da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		ret = -EINVAL;
16757da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		goto unlock_out;
16767da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
16777da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	ccdc_dev->hw_ops.set_image_window(&crop->c);
16787da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	vpfe_dev->fmt.fmt.pix.width = crop->c.width;
16797da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	vpfe_dev->fmt.fmt.pix.height = crop->c.height;
16807da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	vpfe_dev->fmt.fmt.pix.bytesperline =
16817da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		ccdc_dev->hw_ops.get_line_length();
16827da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	vpfe_dev->fmt.fmt.pix.sizeimage =
16837da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		vpfe_dev->fmt.fmt.pix.bytesperline *
16847da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		vpfe_dev->fmt.fmt.pix.height;
16857da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	vpfe_dev->crop = crop->c;
16867da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheriunlock_out:
16877da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	mutex_unlock(&vpfe_dev->lock);
16887da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	return ret;
16897da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri}
16907da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
16917da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
16927da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheristatic long vpfe_param_handler(struct file *file, void *priv,
16937da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		int cmd, void *param)
16947da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri{
16957da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	struct vpfe_device *vpfe_dev = video_drvdata(file);
16967da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	int ret = 0;
16977da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
16987da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_param_handler\n");
16997da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
17007da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (vpfe_dev->started) {
17017da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		/* only allowed if streaming is not started */
17027da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		v4l2_err(&vpfe_dev->v4l2_dev, "device already started\n");
17037da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		return -EBUSY;
17047da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
17057da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
17067da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	ret = mutex_lock_interruptible(&vpfe_dev->lock);
17077da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (ret)
17087da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		return ret;
17097da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
17107da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	switch (cmd) {
17117da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	case VPFE_CMD_S_CCDC_RAW_PARAMS:
17127da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		v4l2_warn(&vpfe_dev->v4l2_dev,
17137da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			  "VPFE_CMD_S_CCDC_RAW_PARAMS: experimental ioctl\n");
17147da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		ret = ccdc_dev->hw_ops.set_params(param);
17157da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		if (ret) {
17167da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			v4l2_err(&vpfe_dev->v4l2_dev,
17177da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri				"Error in setting parameters in CCDC\n");
17187da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			goto unlock_out;
17197da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		}
17207da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		if (vpfe_get_ccdc_image_format(vpfe_dev, &vpfe_dev->fmt) < 0) {
17217da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			v4l2_err(&vpfe_dev->v4l2_dev,
17227da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri				"Invalid image format at CCDC\n");
17237da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			goto unlock_out;
17247da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		}
17257da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		break;
17267da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	default:
17277da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		ret = -EINVAL;
17287da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
17297da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheriunlock_out:
17307da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	mutex_unlock(&vpfe_dev->lock);
17317da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	return ret;
17327da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri}
17337da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
17347da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
17357da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri/* vpfe capture ioctl operations */
17367da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheristatic const struct v4l2_ioctl_ops vpfe_ioctl_ops = {
17377da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	.vidioc_querycap	 = vpfe_querycap,
17387da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	.vidioc_g_fmt_vid_cap    = vpfe_g_fmt_vid_cap,
17397da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	.vidioc_enum_fmt_vid_cap = vpfe_enum_fmt_vid_cap,
17407da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	.vidioc_s_fmt_vid_cap    = vpfe_s_fmt_vid_cap,
17417da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	.vidioc_try_fmt_vid_cap  = vpfe_try_fmt_vid_cap,
17427da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	.vidioc_enum_input	 = vpfe_enum_input,
17437da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	.vidioc_g_input		 = vpfe_g_input,
17447da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	.vidioc_s_input		 = vpfe_s_input,
17457da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	.vidioc_querystd	 = vpfe_querystd,
17467da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	.vidioc_s_std		 = vpfe_s_std,
17477da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	.vidioc_g_std		 = vpfe_g_std,
1748d73bfc5fe625f6962d0ced84066e201249f14e53Vaibhav Hiremath	.vidioc_queryctrl	 = vpfe_queryctrl,
1749d73bfc5fe625f6962d0ced84066e201249f14e53Vaibhav Hiremath	.vidioc_g_ctrl		 = vpfe_g_ctrl,
1750d73bfc5fe625f6962d0ced84066e201249f14e53Vaibhav Hiremath	.vidioc_s_ctrl		 = vpfe_s_ctrl,
17517da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	.vidioc_reqbufs		 = vpfe_reqbufs,
17527da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	.vidioc_querybuf	 = vpfe_querybuf,
17537da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	.vidioc_qbuf		 = vpfe_qbuf,
17547da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	.vidioc_dqbuf		 = vpfe_dqbuf,
17557da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	.vidioc_streamon	 = vpfe_streamon,
17567da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	.vidioc_streamoff	 = vpfe_streamoff,
17577da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	.vidioc_cropcap		 = vpfe_cropcap,
17587da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	.vidioc_g_crop		 = vpfe_g_crop,
17597da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	.vidioc_s_crop		 = vpfe_s_crop,
17607da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	.vidioc_default		 = vpfe_param_handler,
17617da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri};
17627da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
17637da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheristatic struct vpfe_device *vpfe_initialize(void)
17647da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri{
17657da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	struct vpfe_device *vpfe_dev;
17667da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
17677da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* Default number of buffers should be 3 */
17687da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if ((numbuffers > 0) &&
17697da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	    (numbuffers < config_params.min_numbuffers))
17707da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		numbuffers = config_params.min_numbuffers;
17717da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
17727da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/*
17737da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	 * Set buffer size to min buffers size if invalid buffer size is
17747da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	 * given
17757da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	 */
17767da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (bufsize < config_params.min_bufsize)
17777da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		bufsize = config_params.min_bufsize;
17787da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
17797da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	config_params.numbuffers = numbuffers;
17807da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
17817da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (numbuffers)
17827da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		config_params.device_bufsize = bufsize;
17837da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
17847da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* Allocate memory for device objects */
17857da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	vpfe_dev = kzalloc(sizeof(*vpfe_dev), GFP_KERNEL);
17867da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
17877da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	return vpfe_dev;
17887da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri}
17897da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
17907da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheristatic void vpfe_disable_clock(struct vpfe_device *vpfe_dev)
17917da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri{
17927da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	struct vpfe_config *vpfe_cfg = vpfe_dev->cfg;
17937da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
17947da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	clk_disable(vpfe_cfg->vpssclk);
17957da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	clk_put(vpfe_cfg->vpssclk);
17967da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	clk_disable(vpfe_cfg->slaveclk);
17977da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	clk_put(vpfe_cfg->slaveclk);
17987da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	v4l2_info(vpfe_dev->pdev->driver,
17997da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		 "vpfe vpss master & slave clocks disabled\n");
18007da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri}
18017da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
18027da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheristatic int vpfe_enable_clock(struct vpfe_device *vpfe_dev)
18037da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri{
18047da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	struct vpfe_config *vpfe_cfg = vpfe_dev->cfg;
18057da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	int ret = -ENOENT;
18067da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
18077da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	vpfe_cfg->vpssclk = clk_get(vpfe_dev->pdev, "vpss_master");
18087da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (NULL == vpfe_cfg->vpssclk) {
18097da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		v4l2_err(vpfe_dev->pdev->driver, "No clock defined for"
18107da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			 "vpss_master\n");
18117da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		return ret;
18127da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
18137da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
18147da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (clk_enable(vpfe_cfg->vpssclk)) {
18157da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		v4l2_err(vpfe_dev->pdev->driver,
18167da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			"vpfe vpss master clock not enabled\n");
18177da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		goto out;
18187da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
18197da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	v4l2_info(vpfe_dev->pdev->driver,
18207da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		 "vpfe vpss master clock enabled\n");
18217da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
18227da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	vpfe_cfg->slaveclk = clk_get(vpfe_dev->pdev, "vpss_slave");
18237da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (NULL == vpfe_cfg->slaveclk) {
18247da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		v4l2_err(vpfe_dev->pdev->driver,
18257da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			"No clock defined for vpss slave\n");
18267da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		goto out;
18277da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
18287da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
18297da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (clk_enable(vpfe_cfg->slaveclk)) {
18307da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		v4l2_err(vpfe_dev->pdev->driver,
18317da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			 "vpfe vpss slave clock not enabled\n");
18327da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		goto out;
18337da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
18347da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	v4l2_info(vpfe_dev->pdev->driver, "vpfe vpss slave clock enabled\n");
18357da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	return 0;
18367da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheriout:
18377da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (vpfe_cfg->vpssclk)
18387da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		clk_put(vpfe_cfg->vpssclk);
18397da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (vpfe_cfg->slaveclk)
18407da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		clk_put(vpfe_cfg->slaveclk);
18417da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
18427da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	return -1;
18437da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri}
18447da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
18457da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri/*
18467da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri * vpfe_probe : This function creates device entries by register
18477da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri * itself to the V4L2 driver and initializes fields of each
18487da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri * device objects
18497da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri */
18507da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheristatic __init int vpfe_probe(struct platform_device *pdev)
18517da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri{
18527da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	struct vpfe_subdev_info *sdinfo;
18537da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	struct vpfe_config *vpfe_cfg;
18547da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	struct resource *res1;
18557da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	struct vpfe_device *vpfe_dev;
18567da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	struct i2c_adapter *i2c_adap;
18577da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	struct video_device *vfd;
18587da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	int ret = -ENOMEM, i, j;
18597da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	int num_subdevs = 0;
18607da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
18617da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* Get the pointer to the device object */
18627da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	vpfe_dev = vpfe_initialize();
18637da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
18647da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (!vpfe_dev) {
18657da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		v4l2_err(pdev->dev.driver,
18667da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			"Failed to allocate memory for vpfe_dev\n");
18677da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		return ret;
18687da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
18697da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
18707da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	vpfe_dev->pdev = &pdev->dev;
18717da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
18727da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (NULL == pdev->dev.platform_data) {
18737da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		v4l2_err(pdev->dev.driver, "Unable to get vpfe config\n");
18747da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		ret = -ENOENT;
18757da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		goto probe_free_dev_mem;
18767da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
18777da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
18787da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	vpfe_cfg = pdev->dev.platform_data;
18797da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	vpfe_dev->cfg = vpfe_cfg;
18807da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (NULL == vpfe_cfg->ccdc ||
18817da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	    NULL == vpfe_cfg->card_name ||
18827da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	    NULL == vpfe_cfg->sub_devs) {
18837da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		v4l2_err(pdev->dev.driver, "null ptr in vpfe_cfg\n");
18847da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		ret = -ENOENT;
18857da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		goto probe_free_dev_mem;
18867da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
18877da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
18887da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* enable vpss clocks */
18897da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	ret = vpfe_enable_clock(vpfe_dev);
18907da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (ret)
18917da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		goto probe_free_dev_mem;
18927da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
18937da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	mutex_lock(&ccdc_lock);
18947da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* Allocate memory for ccdc configuration */
18957da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	ccdc_cfg = kmalloc(sizeof(struct ccdc_config), GFP_KERNEL);
18967da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (NULL == ccdc_cfg) {
18977da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		v4l2_err(pdev->dev.driver,
18987da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			 "Memory allocation failed for ccdc_cfg\n");
18997da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		goto probe_disable_clock;
19007da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
19017da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
19027da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	strncpy(ccdc_cfg->name, vpfe_cfg->ccdc, 32);
19037da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* Get VINT0 irq resource */
19047da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	res1 = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
19057da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (!res1) {
19067da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		v4l2_err(pdev->dev.driver,
19077da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			 "Unable to get interrupt for VINT0\n");
19087da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		ret = -ENOENT;
19097da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		goto probe_disable_clock;
19107da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
19117da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	vpfe_dev->ccdc_irq0 = res1->start;
19127da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
19137da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* Get VINT1 irq resource */
19147da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	res1 = platform_get_resource(pdev,
19157da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri				IORESOURCE_IRQ, 1);
19167da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (!res1) {
19177da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		v4l2_err(pdev->dev.driver,
19187da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			 "Unable to get interrupt for VINT1\n");
19197da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		ret = -ENOENT;
19207da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		goto probe_disable_clock;
19217da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
19227da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	vpfe_dev->ccdc_irq1 = res1->start;
19237da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
19247da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* Get address base of CCDC */
19257da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	res1 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
19267da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (!res1) {
19277da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		v4l2_err(pdev->dev.driver,
19287da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			"Unable to get register address map\n");
19297da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		ret = -ENOENT;
19307da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		goto probe_disable_clock;
19317da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
19327da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
19337da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	ccdc_cfg->ccdc_addr_size = res1->end - res1->start + 1;
19347da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (!request_mem_region(res1->start, ccdc_cfg->ccdc_addr_size,
19357da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri				pdev->dev.driver->name)) {
19367da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		v4l2_err(pdev->dev.driver,
19377da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			"Failed request_mem_region for ccdc base\n");
19387da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		ret = -ENXIO;
19397da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		goto probe_disable_clock;
19407da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
19417da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	ccdc_cfg->ccdc_addr = ioremap_nocache(res1->start,
19427da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri					     ccdc_cfg->ccdc_addr_size);
19437da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (!ccdc_cfg->ccdc_addr) {
19447da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		v4l2_err(pdev->dev.driver, "Unable to ioremap ccdc addr\n");
19457da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		ret = -ENXIO;
19467da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		goto probe_out_release_mem1;
19477da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
19487da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
19497da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	ret = request_irq(vpfe_dev->ccdc_irq0, vpfe_isr, IRQF_DISABLED,
19507da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			  "vpfe_capture0", vpfe_dev);
19517da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
19527da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (0 != ret) {
19537da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		v4l2_err(pdev->dev.driver, "Unable to request interrupt\n");
19547da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		goto probe_out_unmap1;
19557da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
19567da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
19577da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* Allocate memory for video device */
19587da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	vfd = video_device_alloc();
19597da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (NULL == vfd) {
19607da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		ret = -ENOMEM;
19617da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		v4l2_err(pdev->dev.driver,
19627da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			"Unable to alloc video device\n");
19637da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		goto probe_out_release_irq;
19647da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
19657da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
19667da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* Initialize field of video device */
19677da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	vfd->release		= video_device_release;
19687da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	vfd->fops		= &vpfe_fops;
19697da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	vfd->ioctl_ops		= &vpfe_ioctl_ops;
19707da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	vfd->tvnorms		= 0;
19717da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	vfd->current_norm	= V4L2_STD_PAL;
19727da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	vfd->v4l2_dev 		= &vpfe_dev->v4l2_dev;
19737da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	snprintf(vfd->name, sizeof(vfd->name),
19747da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		 "%s_V%d.%d.%d",
19757da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		 CAPTURE_DRV_NAME,
19767da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		 (VPFE_CAPTURE_VERSION_CODE >> 16) & 0xff,
19777da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		 (VPFE_CAPTURE_VERSION_CODE >> 8) & 0xff,
19787da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		 (VPFE_CAPTURE_VERSION_CODE) & 0xff);
19797da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* Set video_dev to the video device */
19807da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	vpfe_dev->video_dev	= vfd;
19817da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
19827da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	ret = v4l2_device_register(&pdev->dev, &vpfe_dev->v4l2_dev);
19837da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (ret) {
19847da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		v4l2_err(pdev->dev.driver,
19857da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			"Unable to register v4l2 device.\n");
19867da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		goto probe_out_video_release;
19877da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
19887da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	v4l2_info(&vpfe_dev->v4l2_dev, "v4l2 device registered\n");
19897da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	spin_lock_init(&vpfe_dev->irqlock);
19907da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	spin_lock_init(&vpfe_dev->dma_queue_lock);
19917da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	mutex_init(&vpfe_dev->lock);
19927da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
19937da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* Initialize field of the device objects */
19947da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	vpfe_dev->numbuffers = config_params.numbuffers;
19957da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
19967da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* Initialize prio member of device object */
19977da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	v4l2_prio_init(&vpfe_dev->prio);
19987da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* register video device */
19997da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev,
20007da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		"trying to register vpfe device.\n");
20017da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev,
20027da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		"video_dev=%x\n", (int)&vpfe_dev->video_dev);
20037da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	vpfe_dev->fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
20047da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	ret = video_register_device(vpfe_dev->video_dev,
20057da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri				    VFL_TYPE_GRABBER, -1);
20067da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
20077da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (ret) {
20087da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		v4l2_err(pdev->dev.driver,
20097da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			"Unable to register video device.\n");
20107da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		goto probe_out_v4l2_unregister;
20117da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
20127da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
20137da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	v4l2_info(&vpfe_dev->v4l2_dev, "video device registered\n");
20147da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* set the driver data in platform device */
20157da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	platform_set_drvdata(pdev, vpfe_dev);
20167da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* set driver private data */
20177da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	video_set_drvdata(vpfe_dev->video_dev, vpfe_dev);
201814cbaafe6f8587aed632de747322cd3add421a76Vaibhav Hiremath	i2c_adap = i2c_get_adapter(vpfe_cfg->i2c_adapter_id);
20197da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	num_subdevs = vpfe_cfg->num_subdevs;
20207da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	vpfe_dev->sd = kmalloc(sizeof(struct v4l2_subdev *) * num_subdevs,
20217da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri				GFP_KERNEL);
20227da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	if (NULL == vpfe_dev->sd) {
20237da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		v4l2_err(&vpfe_dev->v4l2_dev,
20247da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			"unable to allocate memory for subdevice pointers\n");
20257da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		ret = -ENOMEM;
20267da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		goto probe_out_video_unregister;
20277da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
20287da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
20297da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	for (i = 0; i < num_subdevs; i++) {
20307da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		struct v4l2_input *inps;
20317da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
20327da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		sdinfo = &vpfe_cfg->sub_devs[i];
20337da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
20347da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		/* Load up the subdevice */
20357da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		vpfe_dev->sd[i] =
20367da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			v4l2_i2c_new_subdev_board(&vpfe_dev->v4l2_dev,
20377da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri						  i2c_adap,
20387da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri						  sdinfo->name,
20397da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri						  &sdinfo->board_info,
20407da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri						  NULL);
20417da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		if (vpfe_dev->sd[i]) {
20427da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			v4l2_info(&vpfe_dev->v4l2_dev,
20437da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri				  "v4l2 sub device %s registered\n",
20447da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri				  sdinfo->name);
20457da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			vpfe_dev->sd[i]->grp_id = sdinfo->grp_id;
20467da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			/* update tvnorms from the sub devices */
20477da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			for (j = 0; j < sdinfo->num_inputs; j++) {
20487da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri				inps = &sdinfo->inputs[j];
20497da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri				vfd->tvnorms |= inps->std;
20507da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			}
20517da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		} else {
20527da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			v4l2_info(&vpfe_dev->v4l2_dev,
20537da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri				  "v4l2 sub device %s register fails\n",
20547da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri				  sdinfo->name);
20557da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri			goto probe_sd_out;
20567da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		}
20577da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	}
20587da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
20597da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* set first sub device as current one */
20607da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	vpfe_dev->current_subdev = &vpfe_cfg->sub_devs[0];
20617da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
20627da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* We have at least one sub device to work with */
20637da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	mutex_unlock(&ccdc_lock);
20647da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	return 0;
20657da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
20667da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheriprobe_sd_out:
20677da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	kfree(vpfe_dev->sd);
20687da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheriprobe_out_video_unregister:
20697da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	video_unregister_device(vpfe_dev->video_dev);
20707da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheriprobe_out_v4l2_unregister:
20717da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	v4l2_device_unregister(&vpfe_dev->v4l2_dev);
20727da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheriprobe_out_video_release:
2073f0813b4c9f7ffbeaddcba1c08a1812f7ff30e1b7Laurent Pinchart	if (!video_is_registered(vpfe_dev->video_dev))
20747da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		video_device_release(vpfe_dev->video_dev);
20757da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheriprobe_out_release_irq:
20767da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	free_irq(vpfe_dev->ccdc_irq0, vpfe_dev);
20777da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheriprobe_out_unmap1:
20787da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	iounmap(ccdc_cfg->ccdc_addr);
20797da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheriprobe_out_release_mem1:
20807da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	release_mem_region(res1->start, res1->end - res1->start + 1);
20817da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheriprobe_disable_clock:
20827da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	vpfe_disable_clock(vpfe_dev);
20837da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	mutex_unlock(&ccdc_lock);
20847da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	kfree(ccdc_cfg);
20857da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheriprobe_free_dev_mem:
20867da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	kfree(vpfe_dev);
20877da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	return ret;
20887da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri}
20897da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
20907da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri/*
20917da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri * vpfe_remove : It un-register device from V4L2 driver
20927da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri */
20939d8938248c3b67904a8108a6fc3dcceb9d7f2aadUwe Kleine-Königstatic int __devexit vpfe_remove(struct platform_device *pdev)
20947da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri{
20957da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	struct vpfe_device *vpfe_dev = platform_get_drvdata(pdev);
20967da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	struct resource *res;
20977da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
20987da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	v4l2_info(pdev->dev.driver, "vpfe_remove\n");
20997da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
21007da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	free_irq(vpfe_dev->ccdc_irq0, vpfe_dev);
21017da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	kfree(vpfe_dev->sd);
21027da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	v4l2_device_unregister(&vpfe_dev->v4l2_dev);
21037da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	video_unregister_device(vpfe_dev->video_dev);
21047da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	mutex_lock(&ccdc_lock);
21057da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
21067da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	release_mem_region(res->start, res->end - res->start + 1);
21077da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	iounmap(ccdc_cfg->ccdc_addr);
21087da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	mutex_unlock(&ccdc_lock);
21097da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	vpfe_disable_clock(vpfe_dev);
21107da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	kfree(vpfe_dev);
21117da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	kfree(ccdc_cfg);
21127da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	return 0;
21137da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri}
21147da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
21157da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheristatic int
21167da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicherivpfe_suspend(struct device *dev)
21177da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri{
21187da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* add suspend code here later */
21197da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	return -1;
21207da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri}
21217da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
21227da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheristatic int
21237da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicherivpfe_resume(struct device *dev)
21247da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri{
21257da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* add resume code here later */
21267da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	return -1;
21277da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri}
21287da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
2129471452104b8520337ae2fb48c4e61cd4896e025dAlexey Dobriyanstatic const struct dev_pm_ops vpfe_dev_pm_ops = {
21307da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	.suspend = vpfe_suspend,
21317da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	.resume = vpfe_resume,
21327da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri};
21337da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
21347da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheristatic struct platform_driver vpfe_driver = {
21357da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	.driver = {
21367da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		.name = CAPTURE_DRV_NAME,
21377da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		.owner = THIS_MODULE,
21387da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri		.pm = &vpfe_dev_pm_ops,
21397da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	},
21407da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	.probe = vpfe_probe,
21417da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	.remove = __devexit_p(vpfe_remove),
21427da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri};
21437da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
21447da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheristatic __init int vpfe_init(void)
21457da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri{
21467da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	printk(KERN_NOTICE "vpfe_init\n");
21477da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	/* Register driver to the kernel */
21487da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	return platform_driver_register(&vpfe_driver);
21497da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri}
21507da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
21517da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri/*
21527da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri * vpfe_cleanup : This function un-registers device driver
21537da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri */
21547da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheristatic void vpfe_cleanup(void)
21557da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri{
21567da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri	platform_driver_unregister(&vpfe_driver);
21577da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri}
21587da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicheri
21597da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicherimodule_init(vpfe_init);
21607da8a6cb3e5b60e73b196f1c71031423e0791032Muralidharan Karicherimodule_exit(vpfe_cleanup);
2161