diff options
Diffstat (limited to 'drivers/media/video/davinci')
| -rw-r--r-- | drivers/media/video/davinci/Kconfig | 93 | ||||
| -rw-r--r-- | drivers/media/video/davinci/Makefile | 18 | ||||
| -rw-r--r-- | drivers/media/video/davinci/ccdc_hw_device.h | 110 | ||||
| -rw-r--r-- | drivers/media/video/davinci/dm355_ccdc.c | 1082 | ||||
| -rw-r--r-- | drivers/media/video/davinci/dm355_ccdc_regs.h | 310 | ||||
| -rw-r--r-- | drivers/media/video/davinci/dm644x_ccdc.c | 1091 | ||||
| -rw-r--r-- | drivers/media/video/davinci/dm644x_ccdc_regs.h | 153 | ||||
| -rw-r--r-- | drivers/media/video/davinci/isif.c | 1172 | ||||
| -rw-r--r-- | drivers/media/video/davinci/isif_regs.h | 269 | ||||
| -rw-r--r-- | drivers/media/video/davinci/vpfe_capture.c | 2096 | ||||
| -rw-r--r-- | drivers/media/video/davinci/vpif.c | 296 | ||||
| -rw-r--r-- | drivers/media/video/davinci/vpif.h | 642 | ||||
| -rw-r--r-- | drivers/media/video/davinci/vpif_capture.c | 2169 | ||||
| -rw-r--r-- | drivers/media/video/davinci/vpif_capture.h | 165 | ||||
| -rw-r--r-- | drivers/media/video/davinci/vpif_display.c | 1657 | ||||
| -rw-r--r-- | drivers/media/video/davinci/vpif_display.h | 175 | ||||
| -rw-r--r-- | drivers/media/video/davinci/vpss.c | 482 |
17 files changed, 0 insertions, 11980 deletions
diff --git a/drivers/media/video/davinci/Kconfig b/drivers/media/video/davinci/Kconfig deleted file mode 100644 index 6b195403564..00000000000 --- a/drivers/media/video/davinci/Kconfig +++ /dev/null @@ -1,93 +0,0 @@ -config DISPLAY_DAVINCI_DM646X_EVM - tristate "DM646x EVM Video Display" - depends on VIDEO_DEV && MACH_DAVINCI_DM6467_EVM - select VIDEOBUF_DMA_CONTIG - select VIDEO_DAVINCI_VPIF - select VIDEO_ADV7343 - select VIDEO_THS7303 - help - Support for DM6467 based display device. - - To compile this driver as a module, choose M here: the - module will be called vpif_display. - -config CAPTURE_DAVINCI_DM646X_EVM - tristate "DM646x EVM Video Capture" - depends on VIDEO_DEV && MACH_DAVINCI_DM6467_EVM - select VIDEOBUF_DMA_CONTIG - select VIDEO_DAVINCI_VPIF - help - Support for DM6467 based capture device. - - To compile this driver as a module, choose M here: the - module will be called vpif_capture. - -config VIDEO_DAVINCI_VPIF - tristate "DaVinci VPIF Driver" - depends on DISPLAY_DAVINCI_DM646X_EVM - help - Support for DaVinci VPIF Driver. - - To compile this driver as a module, choose M here: the - module will be called vpif. - -config VIDEO_VPSS_SYSTEM - tristate "VPSS System module driver" - depends on ARCH_DAVINCI - help - Support for vpss system module for video driver - -config VIDEO_VPFE_CAPTURE - tristate "VPFE Video Capture Driver" - depends on VIDEO_V4L2 && (ARCH_DAVINCI || ARCH_OMAP3) - select VIDEOBUF_DMA_CONTIG - help - Support for DMx/AMx VPFE based frame grabber. This is the - common V4L2 module for following DMx/AMx SoCs from Texas - Instruments:- DM6446, DM365, DM355 & AM3517/05. - - To compile this driver as a module, choose M here: the - module will be called vpfe-capture. - -config VIDEO_DM6446_CCDC - tristate "DM6446 CCDC HW module" - depends on VIDEO_VPFE_CAPTURE - select VIDEO_VPSS_SYSTEM - default y - help - Enables DaVinci CCD hw module. DaVinci CCDC hw interfaces - with decoder modules such as TVP5146 over BT656 or - sensor module such as MT9T001 over a raw interface. This - module configures the interface and CCDC/ISIF to do - video frame capture from slave decoders. - - To compile this driver as a module, choose M here: the - module will be called vpfe. - -config VIDEO_DM355_CCDC - tristate "DM355 CCDC HW module" - depends on ARCH_DAVINCI_DM355 && VIDEO_VPFE_CAPTURE - select VIDEO_VPSS_SYSTEM - default y - help - Enables DM355 CCD hw module. DM355 CCDC hw interfaces - with decoder modules such as TVP5146 over BT656 or - sensor module such as MT9T001 over a raw interface. This - module configures the interface and CCDC/ISIF to do - video frame capture from a slave decoders - - To compile this driver as a module, choose M here: the - module will be called vpfe. - -config VIDEO_ISIF - tristate "ISIF HW module" - depends on ARCH_DAVINCI_DM365 && VIDEO_VPFE_CAPTURE - select VIDEO_VPSS_SYSTEM - default y - help - Enables ISIF hw module. This is the hardware module for - configuring ISIF in VPFE to capture Raw Bayer RGB data from - a image sensor or YUV data from a YUV source. - - To compile this driver as a module, choose M here: the - module will be called vpfe. diff --git a/drivers/media/video/davinci/Makefile b/drivers/media/video/davinci/Makefile deleted file mode 100644 index a37955745aa..00000000000 --- a/drivers/media/video/davinci/Makefile +++ /dev/null @@ -1,18 +0,0 @@ -# -# Makefile for the davinci video device drivers. -# - -# VPIF -obj-$(CONFIG_VIDEO_DAVINCI_VPIF) += vpif.o - -#DM646x EVM Display driver -obj-$(CONFIG_DISPLAY_DAVINCI_DM646X_EVM) += vpif_display.o -#DM646x EVM Capture driver -obj-$(CONFIG_CAPTURE_DAVINCI_DM646X_EVM) += vpif_capture.o - -# Capture: DM6446 and DM355 -obj-$(CONFIG_VIDEO_VPSS_SYSTEM) += vpss.o -obj-$(CONFIG_VIDEO_VPFE_CAPTURE) += vpfe_capture.o -obj-$(CONFIG_VIDEO_DM6446_CCDC) += dm644x_ccdc.o -obj-$(CONFIG_VIDEO_DM355_CCDC) += dm355_ccdc.o -obj-$(CONFIG_VIDEO_ISIF) += isif.o diff --git a/drivers/media/video/davinci/ccdc_hw_device.h b/drivers/media/video/davinci/ccdc_hw_device.h deleted file mode 100644 index 86b9b351896..00000000000 --- a/drivers/media/video/davinci/ccdc_hw_device.h +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (C) 2008-2009 Texas Instruments Inc - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * ccdc device API - */ -#ifndef _CCDC_HW_DEVICE_H -#define _CCDC_HW_DEVICE_H - -#ifdef __KERNEL__ -#include <linux/videodev2.h> -#include <linux/device.h> -#include <media/davinci/vpfe_types.h> -#include <media/davinci/ccdc_types.h> - -/* - * ccdc hw operations - */ -struct ccdc_hw_ops { - /* Pointer to initialize function to initialize ccdc device */ - int (*open) (struct device *dev); - /* Pointer to deinitialize function */ - int (*close) (struct device *dev); - /* set ccdc base address */ - void (*set_ccdc_base)(void *base, int size); - /* Pointer to function to enable or disable ccdc */ - void (*enable) (int en); - /* reset sbl. only for 6446 */ - void (*reset) (void); - /* enable output to sdram */ - void (*enable_out_to_sdram) (int en); - /* Pointer to function to set hw parameters */ - int (*set_hw_if_params) (struct vpfe_hw_if_param *param); - /* get interface parameters */ - int (*get_hw_if_params) (struct vpfe_hw_if_param *param); - /* - * Pointer to function to set parameters. Used - * for implementing VPFE_S_CCDC_PARAMS - */ - int (*set_params) (void *params); - /* - * Pointer to function to get parameter. Used - * for implementing VPFE_G_CCDC_PARAMS - */ - int (*get_params) (void *params); - /* Pointer to function to configure ccdc */ - int (*configure) (void); - - /* Pointer to function to set buffer type */ - int (*set_buftype) (enum ccdc_buftype buf_type); - /* Pointer to function to get buffer type */ - enum ccdc_buftype (*get_buftype) (void); - /* Pointer to function to set frame format */ - int (*set_frame_format) (enum ccdc_frmfmt frm_fmt); - /* Pointer to function to get frame format */ - enum ccdc_frmfmt (*get_frame_format) (void); - /* enumerate hw pix formats */ - int (*enum_pix)(u32 *hw_pix, int i); - /* Pointer to function to set buffer type */ - u32 (*get_pixel_format) (void); - /* Pointer to function to get pixel format. */ - int (*set_pixel_format) (u32 pixfmt); - /* Pointer to function to set image window */ - int (*set_image_window) (struct v4l2_rect *win); - /* Pointer to function to set image window */ - void (*get_image_window) (struct v4l2_rect *win); - /* Pointer to function to get line length */ - unsigned int (*get_line_length) (void); - - /* Query CCDC control IDs */ - int (*queryctrl)(struct v4l2_queryctrl *qctrl); - /* Set CCDC control */ - int (*set_control)(struct v4l2_control *ctrl); - /* Get CCDC control */ - int (*get_control)(struct v4l2_control *ctrl); - - /* Pointer to function to set frame buffer address */ - void (*setfbaddr) (unsigned long addr); - /* Pointer to function to get field id */ - int (*getfid) (void); -}; - -struct ccdc_hw_device { - /* ccdc device name */ - char name[32]; - /* module owner */ - struct module *owner; - /* hw ops */ - struct ccdc_hw_ops hw_ops; -}; - -/* Used by CCDC module to register & unregister with vpfe capture driver */ -int vpfe_register_ccdc_device(struct ccdc_hw_device *dev); -void vpfe_unregister_ccdc_device(struct ccdc_hw_device *dev); - -#endif -#endif diff --git a/drivers/media/video/davinci/dm355_ccdc.c b/drivers/media/video/davinci/dm355_ccdc.c deleted file mode 100644 index c29ac88ffd7..00000000000 --- a/drivers/media/video/davinci/dm355_ccdc.c +++ /dev/null @@ -1,1082 +0,0 @@ -/* - * Copyright (C) 2005-2009 Texas Instruments Inc - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * CCDC hardware module for DM355 - * ------------------------------ - * - * This module is for configuring DM355 CCD controller of VPFE to capture - * Raw yuv or Bayer RGB data from a decoder. CCDC has several modules - * such as Defect Pixel Correction, Color Space Conversion etc to - * pre-process the Bayer RGB data, before writing it to SDRAM. This - * module also allows application to configure individual - * module parameters through VPFE_CMD_S_CCDC_RAW_PARAMS IOCTL. - * To do so, application include dm355_ccdc.h and vpfe_capture.h header - * files. The setparams() API is called by vpfe_capture driver - * to configure module parameters - * - * TODO: 1) Raw bayer parameter settings and bayer capture - * 2) Split module parameter structure to module specific ioctl structs - * 3) add support for lense shading correction - * 4) investigate if enum used for user space type definition - * to be replaced by #defines or integer - */ -#include <linux/platform_device.h> -#include <linux/uaccess.h> -#include <linux/videodev2.h> -#include <linux/clk.h> -#include <linux/err.h> - -#include <media/davinci/dm355_ccdc.h> -#include <media/davinci/vpss.h> - -#include "dm355_ccdc_regs.h" -#include "ccdc_hw_device.h" - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("CCDC Driver for DM355"); -MODULE_AUTHOR("Texas Instruments"); - -static struct ccdc_oper_config { - struct device *dev; - /* CCDC interface type */ - enum vpfe_hw_if_type if_type; - /* Raw Bayer configuration */ - struct ccdc_params_raw bayer; - /* YCbCr configuration */ - struct ccdc_params_ycbcr ycbcr; - /* Master clock */ - struct clk *mclk; - /* slave clock */ - struct clk *sclk; - /* ccdc base address */ - void __iomem *base_addr; -} ccdc_cfg = { - /* Raw configurations */ - .bayer = { - .pix_fmt = CCDC_PIXFMT_RAW, - .frm_fmt = CCDC_FRMFMT_PROGRESSIVE, - .win = CCDC_WIN_VGA, - .fid_pol = VPFE_PINPOL_POSITIVE, - .vd_pol = VPFE_PINPOL_POSITIVE, - .hd_pol = VPFE_PINPOL_POSITIVE, - .gain = { - .r_ye = 256, - .gb_g = 256, - .gr_cy = 256, - .b_mg = 256 - }, - .config_params = { - .datasft = 2, - .mfilt1 = CCDC_NO_MEDIAN_FILTER1, - .mfilt2 = CCDC_NO_MEDIAN_FILTER2, - .alaw = { - .gama_wd = 2, - }, - .blk_clamp = { - .sample_pixel = 1, - .dc_sub = 25 - }, - .col_pat_field0 = { - .olop = CCDC_GREEN_BLUE, - .olep = CCDC_BLUE, - .elop = CCDC_RED, - .elep = CCDC_GREEN_RED - }, - .col_pat_field1 = { - .olop = CCDC_GREEN_BLUE, - .olep = CCDC_BLUE, - .elop = CCDC_RED, - .elep = CCDC_GREEN_RED - }, - }, - }, - /* YCbCr configuration */ - .ycbcr = { - .win = CCDC_WIN_PAL, - .pix_fmt = CCDC_PIXFMT_YCBCR_8BIT, - .frm_fmt = CCDC_FRMFMT_INTERLACED, - .fid_pol = VPFE_PINPOL_POSITIVE, - .vd_pol = VPFE_PINPOL_POSITIVE, - .hd_pol = VPFE_PINPOL_POSITIVE, - .bt656_enable = 1, - .pix_order = CCDC_PIXORDER_CBYCRY, - .buf_type = CCDC_BUFTYPE_FLD_INTERLEAVED - }, -}; - - -/* Raw Bayer formats */ -static u32 ccdc_raw_bayer_pix_formats[] = - {V4L2_PIX_FMT_SBGGR8, V4L2_PIX_FMT_SBGGR16}; - -/* Raw YUV formats */ -static u32 ccdc_raw_yuv_pix_formats[] = - {V4L2_PIX_FMT_UYVY, V4L2_PIX_FMT_YUYV}; - -/* register access routines */ -static inline u32 regr(u32 offset) -{ - return __raw_readl(ccdc_cfg.base_addr + offset); -} - -static inline void regw(u32 val, u32 offset) -{ - __raw_writel(val, ccdc_cfg.base_addr + offset); -} - -static void ccdc_enable(int en) -{ - unsigned int temp; - temp = regr(SYNCEN); - temp &= (~CCDC_SYNCEN_VDHDEN_MASK); - temp |= (en & CCDC_SYNCEN_VDHDEN_MASK); - regw(temp, SYNCEN); -} - -static void ccdc_enable_output_to_sdram(int en) -{ - unsigned int temp; - temp = regr(SYNCEN); - temp &= (~(CCDC_SYNCEN_WEN_MASK)); - temp |= ((en << CCDC_SYNCEN_WEN_SHIFT) & CCDC_SYNCEN_WEN_MASK); - regw(temp, SYNCEN); -} - -static void ccdc_config_gain_offset(void) -{ - /* configure gain */ - regw(ccdc_cfg.bayer.gain.r_ye, RYEGAIN); - regw(ccdc_cfg.bayer.gain.gr_cy, GRCYGAIN); - regw(ccdc_cfg.bayer.gain.gb_g, GBGGAIN); - regw(ccdc_cfg.bayer.gain.b_mg, BMGGAIN); - /* configure offset */ - regw(ccdc_cfg.bayer.ccdc_offset, OFFSET); -} - -/* - * ccdc_restore_defaults() - * This function restore power on defaults in the ccdc registers - */ -static int ccdc_restore_defaults(void) -{ - int i; - - dev_dbg(ccdc_cfg.dev, "\nstarting ccdc_restore_defaults..."); - /* set all registers to zero */ - for (i = 0; i <= CCDC_REG_LAST; i += 4) - regw(0, i); - - /* now override the values with power on defaults in registers */ - regw(MODESET_DEFAULT, MODESET); - /* no culling support */ - regw(CULH_DEFAULT, CULH); - regw(CULV_DEFAULT, CULV); - /* Set default Gain and Offset */ - ccdc_cfg.bayer.gain.r_ye = GAIN_DEFAULT; - ccdc_cfg.bayer.gain.gb_g = GAIN_DEFAULT; - ccdc_cfg.bayer.gain.gr_cy = GAIN_DEFAULT; - ccdc_cfg.bayer.gain.b_mg = GAIN_DEFAULT; - ccdc_config_gain_offset(); - regw(OUTCLIP_DEFAULT, OUTCLIP); - regw(LSCCFG2_DEFAULT, LSCCFG2); - /* select ccdc input */ - if (vpss_select_ccdc_source(VPSS_CCDCIN)) { - dev_dbg(ccdc_cfg.dev, "\ncouldn't select ccdc input source"); - return -EFAULT; - } - /* select ccdc clock */ - if (vpss_enable_clock(VPSS_CCDC_CLOCK, 1) < 0) { - dev_dbg(ccdc_cfg.dev, "\ncouldn't enable ccdc clock"); - return -EFAULT; - } - dev_dbg(ccdc_cfg.dev, "\nEnd of ccdc_restore_defaults..."); - return 0; -} - -static int ccdc_open(struct device *device) -{ - return ccdc_restore_defaults(); -} - -static int ccdc_close(struct device *device) -{ - /* disable clock */ - vpss_enable_clock(VPSS_CCDC_CLOCK, 0); - /* do nothing for now */ - return 0; -} -/* - * ccdc_setwin() - * This function will configure the window size to - * be capture in CCDC reg. - */ -static void ccdc_setwin(struct v4l2_rect *image_win, - enum ccdc_frmfmt frm_fmt, int ppc) -{ - int horz_start, horz_nr_pixels; - int vert_start, vert_nr_lines; - int mid_img = 0; - - dev_dbg(ccdc_cfg.dev, "\nStarting ccdc_setwin..."); - - /* - * ppc - per pixel count. indicates how many pixels per cell - * output to SDRAM. example, for ycbcr, it is one y and one c, so 2. - * raw capture this is 1 - */ - horz_start = image_win->left << (ppc - 1); - horz_nr_pixels = ((image_win->width) << (ppc - 1)) - 1; - - /* Writing the horizontal info into the registers */ - regw(horz_start, SPH); - regw(horz_nr_pixels, NPH); - vert_start = image_win->top; - - if (frm_fmt == CCDC_FRMFMT_INTERLACED) { - vert_nr_lines = (image_win->height >> 1) - 1; - vert_start >>= 1; - /* Since first line doesn't have any data */ - vert_start += 1; - /* configure VDINT0 and VDINT1 */ - regw(vert_start, VDINT0); - } else { - /* Since first line doesn't have any data */ - vert_start += 1; - vert_nr_lines = image_win->height - 1; - /* configure VDINT0 and VDINT1 */ - mid_img = vert_start + (image_win->height / 2); - regw(vert_start, VDINT0); - regw(mid_img, VDINT1); - } - regw(vert_start & CCDC_START_VER_ONE_MASK, SLV0); - regw(vert_start & CCDC_START_VER_TWO_MASK, SLV1); - regw(vert_nr_lines & CCDC_NUM_LINES_VER, NLV); - dev_dbg(ccdc_cfg.dev, "\nEnd of ccdc_setwin..."); -} - -static int validate_ccdc_param(struct ccdc_config_params_raw *ccdcparam) -{ - if (ccdcparam->datasft < CCDC_DATA_NO_SHIFT || - ccdcparam->datasft > CCDC_DATA_SHIFT_6BIT) { - dev_dbg(ccdc_cfg.dev, "Invalid value of data shift\n"); - return -EINVAL; - } - - if (ccdcparam->mfilt1 < CCDC_NO_MEDIAN_FILTER1 || - ccdcparam->mfilt1 > CCDC_MEDIAN_FILTER1) { - dev_dbg(ccdc_cfg.dev, "Invalid value of median filter1\n"); - return -EINVAL; - } - - if (ccdcparam->mfilt2 < CCDC_NO_MEDIAN_FILTER2 || - ccdcparam->mfilt2 > CCDC_MEDIAN_FILTER2) { - dev_dbg(ccdc_cfg.dev, "Invalid value of median filter2\n"); - return -EINVAL; - } - - if ((ccdcparam->med_filt_thres < 0) || - (ccdcparam->med_filt_thres > CCDC_MED_FILT_THRESH)) { - dev_dbg(ccdc_cfg.dev, - "Invalid value of median filter thresold\n"); - return -EINVAL; - } - - if (ccdcparam->data_sz < CCDC_DATA_16BITS || - ccdcparam->data_sz > CCDC_DATA_8BITS) { - dev_dbg(ccdc_cfg.dev, "Invalid value of data size\n"); - return -EINVAL; - } - - if (ccdcparam->alaw.enable) { - if (ccdcparam->alaw.gama_wd < CCDC_GAMMA_BITS_13_4 || - ccdcparam->alaw.gama_wd > CCDC_GAMMA_BITS_09_0) { - dev_dbg(ccdc_cfg.dev, "Invalid value of ALAW\n"); - return -EINVAL; - } - } - - if (ccdcparam->blk_clamp.b_clamp_enable) { - if (ccdcparam->blk_clamp.sample_pixel < CCDC_SAMPLE_1PIXELS || - ccdcparam->blk_clamp.sample_pixel > CCDC_SAMPLE_16PIXELS) { - dev_dbg(ccdc_cfg.dev, - "Invalid value of sample pixel\n"); - return -EINVAL; - } - if (ccdcparam->blk_clamp.sample_ln < CCDC_SAMPLE_1LINES || - ccdcparam->blk_clamp.sample_ln > CCDC_SAMPLE_16LINES) { - dev_dbg(ccdc_cfg.dev, - "Invalid value of sample lines\n"); - return -EINVAL; - } - } - return 0; -} - -/* Parameter operations */ -static int ccdc_set_params(void __user *params) -{ - struct ccdc_config_params_raw ccdc_raw_params; - int x; - - /* only raw module parameters can be set through the IOCTL */ - if (ccdc_cfg.if_type != VPFE_RAW_BAYER) - return -EINVAL; - - x = copy_from_user(&ccdc_raw_params, params, sizeof(ccdc_raw_params)); - if (x) { - dev_dbg(ccdc_cfg.dev, "ccdc_set_params: error in copying ccdc" - "params, %d\n", x); - return -EFAULT; - } - - if (!validate_ccdc_param(&ccdc_raw_params)) { - memcpy(&ccdc_cfg.bayer.config_params, - &ccdc_raw_params, - sizeof(ccdc_raw_params)); - return 0; - } - return -EINVAL; -} - -/* This function will configure CCDC for YCbCr video capture */ -static void ccdc_config_ycbcr(void) -{ - struct ccdc_params_ycbcr *params = &ccdc_cfg.ycbcr; - u32 temp; - - /* first set the CCDC power on defaults values in all registers */ - dev_dbg(ccdc_cfg.dev, "\nStarting ccdc_config_ycbcr..."); - ccdc_restore_defaults(); - - /* configure pixel format & video frame format */ - temp = (((params->pix_fmt & CCDC_INPUT_MODE_MASK) << - CCDC_INPUT_MODE_SHIFT) | - ((params->frm_fmt & CCDC_FRM_FMT_MASK) << - CCDC_FRM_FMT_SHIFT)); - - /* setup BT.656 sync mode */ - if (params->bt656_enable) { - regw(CCDC_REC656IF_BT656_EN, REC656IF); - /* - * configure the FID, VD, HD pin polarity fld,hd pol positive, - * vd negative, 8-bit pack mode - */ - temp |= CCDC_VD_POL_NEGATIVE; - } else { /* y/c external sync mode */ - temp |= (((params->fid_pol & CCDC_FID_POL_MASK) << - CCDC_FID_POL_SHIFT) | - ((params->hd_pol & CCDC_HD_POL_MASK) << - CCDC_HD_POL_SHIFT) | - ((params->vd_pol & CCDC_VD_POL_MASK) << - CCDC_VD_POL_SHIFT)); - } - - /* pack the data to 8-bit */ - temp |= CCDC_DATA_PACK_ENABLE; - - regw(temp, MODESET); - - /* configure video window */ - ccdc_setwin(¶ms->win, params->frm_fmt, 2); - - /* configure the order of y cb cr in SD-RAM */ - temp = (params->pix_order << CCDC_Y8POS_SHIFT); - temp |= CCDC_LATCH_ON_VSYNC_DISABLE | CCDC_CCDCFG_FIDMD_NO_LATCH_VSYNC; - regw(temp, CCDCFG); - - /* - * configure the horizontal line offset. This is done by rounding up - * width to a multiple of 16 pixels and multiply by two to account for - * y:cb:cr 4:2:2 data - */ - regw(((params->win.width * 2 + 31) >> 5), HSIZE); - - /* configure the memory line offset */ - if (params->buf_type == CCDC_BUFTYPE_FLD_INTERLEAVED) { - /* two fields are interleaved in memory */ - regw(CCDC_SDOFST_FIELD_INTERLEAVED, SDOFST); - } - - dev_dbg(ccdc_cfg.dev, "\nEnd of ccdc_config_ycbcr...\n"); -} - -/* - * ccdc_config_black_clamp() - * configure parameters for Optical Black Clamp - */ -static void ccdc_config_black_clamp(struct ccdc_black_clamp *bclamp) -{ - u32 val; - - if (!bclamp->b_clamp_enable) { - /* configure DCSub */ - regw(bclamp->dc_sub & CCDC_BLK_DC_SUB_MASK, DCSUB); - regw(0x0000, CLAMP); - return; - } - /* Enable the Black clamping, set sample lines and pixels */ - val = (bclamp->start_pixel & CCDC_BLK_ST_PXL_MASK) | - ((bclamp->sample_pixel & CCDC_BLK_SAMPLE_LN_MASK) << - CCDC_BLK_SAMPLE_LN_SHIFT) | CCDC_BLK_CLAMP_ENABLE; - regw(val, CLAMP); - - /* If Black clamping is enable then make dcsub 0 */ - val = (bclamp->sample_ln & CCDC_NUM_LINE_CALC_MASK) - << CCDC_NUM_LINE_CALC_SHIFT; - regw(val, DCSUB); -} - -/* - * ccdc_config_black_compense() - * configure parameters for Black Compensation - */ -static void ccdc_config_black_compense(struct ccdc_black_compensation *bcomp) -{ - u32 val; - - val = (bcomp->b & CCDC_BLK_COMP_MASK) | - ((bcomp->gb & CCDC_BLK_COMP_MASK) << - CCDC_BLK_COMP_GB_COMP_SHIFT); - regw(val, BLKCMP1); - - val = ((bcomp->gr & CCDC_BLK_COMP_MASK) << - CCDC_BLK_COMP_GR_COMP_SHIFT) | - ((bcomp->r & CCDC_BLK_COMP_MASK) << - CCDC_BLK_COMP_R_COMP_SHIFT); - regw(val, BLKCMP0); -} - -/* - * ccdc_write_dfc_entry() - * write an entry in the dfc table. - */ -int ccdc_write_dfc_entry(int index, struct ccdc_vertical_dft *dfc) -{ -/* TODO This is to be re-visited and adjusted */ -#define DFC_WRITE_WAIT_COUNT 1000 - u32 val, count = DFC_WRITE_WAIT_COUNT; - - regw(dfc->dft_corr_vert[index], DFCMEM0); - regw(dfc->dft_corr_horz[index], DFCMEM1); - regw(dfc->dft_corr_sub1[index], DFCMEM2); - regw(dfc->dft_corr_sub2[index], DFCMEM3); - regw(dfc->dft_corr_sub3[index], DFCMEM4); - /* set WR bit to write */ - val = regr(DFCMEMCTL) | CCDC_DFCMEMCTL_DFCMWR_MASK; - regw(val, DFCMEMCTL); - - /* - * Assume, it is very short. If we get an error, we need to - * adjust this value - */ - while (regr(DFCMEMCTL) & CCDC_DFCMEMCTL_DFCMWR_MASK) - count--; - /* - * TODO We expect the count to be non-zero to be successful. Adjust - * the count if write requires more time - */ - - if (count) { - dev_err(ccdc_cfg.dev, "defect table write timeout !!!\n"); - return -1; - } - return 0; -} - -/* - * ccdc_config_vdfc() - * configure parameters for Vertical Defect Correction - */ -static int ccdc_config_vdfc(struct ccdc_vertical_dft *dfc) -{ - u32 val; - int i; - - /* Configure General Defect Correction. The table used is from IPIPE */ - val = dfc->gen_dft_en & CCDC_DFCCTL_GDFCEN_MASK; - - /* Configure Vertical Defect Correction if needed */ - if (!dfc->ver_dft_en) { - /* Enable only General Defect Correction */ - regw(val, DFCCTL); - return 0; - } - - if (dfc->table_size > CCDC_DFT_TABLE_SIZE) - return -EINVAL; - - val |= CCDC_DFCCTL_VDFC_DISABLE; - val |= (dfc->dft_corr_ctl.vdfcsl & CCDC_DFCCTL_VDFCSL_MASK) << - CCDC_DFCCTL_VDFCSL_SHIFT; - val |= (dfc->dft_corr_ctl.vdfcuda & CCDC_DFCCTL_VDFCUDA_MASK) << - CCDC_DFCCTL_VDFCUDA_SHIFT; - val |= (dfc->dft_corr_ctl.vdflsft & CCDC_DFCCTL_VDFLSFT_MASK) << - CCDC_DFCCTL_VDFLSFT_SHIFT; - regw(val , DFCCTL); - - /* clear address ptr to offset 0 */ - val = CCDC_DFCMEMCTL_DFCMARST_MASK << CCDC_DFCMEMCTL_DFCMARST_SHIFT; - - /* write defect table entries */ - for (i = 0; i < dfc->table_size; i++) { - /* increment address for non zero index */ - if (i != 0) - val = CCDC_DFCMEMCTL_INC_ADDR; - regw(val, DFCMEMCTL); - if (ccdc_write_dfc_entry(i, dfc) < 0) - return -EFAULT; - } - - /* update saturation level and enable dfc */ - regw(dfc->saturation_ctl & CCDC_VDC_DFCVSAT_MASK, DFCVSAT); - val = regr(DFCCTL) | (CCDC_DFCCTL_VDFCEN_MASK << - CCDC_DFCCTL_VDFCEN_SHIFT); - regw(val, DFCCTL); - return 0; -} - -/* - * ccdc_config_csc() - * configure parameters for color space conversion - * Each register CSCM0-7 has two values in S8Q5 format. - */ -static void ccdc_config_csc(struct ccdc_csc *csc) -{ - u32 val1, val2; - int i; - - if (!csc->enable) - return; - - /* Enable the CSC sub-module */ - regw(CCDC_CSC_ENABLE, CSCCTL); - - /* Converting the co-eff as per the format of the register */ - for (i = 0; i < CCDC_CSC_COEFF_TABLE_SIZE; i++) { - if ((i % 2) == 0) { - /* CSCM - LSB */ - val1 = (csc->coeff[i].integer & - CCDC_CSC_COEF_INTEG_MASK) - << CCDC_CSC_COEF_INTEG_SHIFT; - /* - * convert decimal part to binary. Use 2 decimal - * precision, user values range from .00 - 0.99 - */ - val1 |= (((csc->coeff[i].decimal & - CCDC_CSC_COEF_DECIMAL_MASK) * - CCDC_CSC_DEC_MAX) / 100); - } else { - - /* CSCM - MSB */ - val2 = (csc->coeff[i].integer & - CCDC_CSC_COEF_INTEG_MASK) - << CCDC_CSC_COEF_INTEG_SHIFT; - val2 |= (((csc->coeff[i].decimal & - CCDC_CSC_COEF_DECIMAL_MASK) * - CCDC_CSC_DEC_MAX) / 100); - val2 <<= CCDC_CSCM_MSB_SHIFT; - val2 |= val1; - regw(val2, (CSCM0 + ((i - 1) << 1))); - } - } -} - -/* - * ccdc_config_color_patterns() - * configure parameters for color patterns - */ -static void ccdc_config_color_patterns(struct ccdc_col_pat *pat0, - struct ccdc_col_pat *pat1) -{ - u32 val; - - val = (pat0->olop | (pat0->olep << 2) | (pat0->elop << 4) | - (pat0->elep << 6) | (pat1->olop << 8) | (pat1->olep << 10) | - (pat1->elop << 12) | (pat1->elep << 14)); - regw(val, COLPTN); -} - -/* This function will configure CCDC for Raw mode image capture */ -static int ccdc_config_raw(void) -{ - struct ccdc_params_raw *params = &ccdc_cfg.bayer; - struct ccdc_config_params_raw *config_params = - &ccdc_cfg.bayer.config_params; - unsigned int val; - - dev_dbg(ccdc_cfg.dev, "\nStarting ccdc_config_raw..."); - - /* restore power on defaults to register */ - ccdc_restore_defaults(); - - /* CCDCFG register: - * set CCD Not to swap input since input is RAW data - * set FID detection function to Latch at V-Sync - * set WENLOG - ccdc valid area to AND - * set TRGSEL to WENBIT - * set EXTRG to DISABLE - * disable latching function on VSYNC - shadowed registers - */ - regw(CCDC_YCINSWP_RAW | CCDC_CCDCFG_FIDMD_LATCH_VSYNC | - CCDC_CCDCFG_WENLOG_AND | CCDC_CCDCFG_TRGSEL_WEN | - CCDC_CCDCFG_EXTRG_DISABLE | CCDC_LATCH_ON_VSYNC_DISABLE, CCDCFG); - - /* - * Set VDHD direction to input, input type to raw input - * normal data polarity, do not use external WEN - */ - val = (CCDC_VDHDOUT_INPUT | CCDC_RAW_IP_MODE | CCDC_DATAPOL_NORMAL | - CCDC_EXWEN_DISABLE); - - /* - * Configure the vertical sync polarity (MODESET.VDPOL), horizontal - * sync polarity (MODESET.HDPOL), field id polarity (MODESET.FLDPOL), - * frame format(progressive or interlace), & pixel format (Input mode) - */ - val |= (((params->vd_pol & CCDC_VD_POL_MASK) << CCDC_VD_POL_SHIFT) | - ((params->hd_pol & CCDC_HD_POL_MASK) << CCDC_HD_POL_SHIFT) | - ((params->fid_pol & CCDC_FID_POL_MASK) << CCDC_FID_POL_SHIFT) | - ((params->frm_fmt & CCDC_FRM_FMT_MASK) << CCDC_FRM_FMT_SHIFT) | - ((params->pix_fmt & CCDC_PIX_FMT_MASK) << CCDC_PIX_FMT_SHIFT)); - - /* set pack for alaw compression */ - if ((config_params->data_sz == CCDC_DATA_8BITS) || - config_params->alaw.enable) - val |= CCDC_DATA_PACK_ENABLE; - - /* Configure for LPF */ - if (config_params->lpf_enable) - val |= (config_params->lpf_enable & CCDC_LPF_MASK) << - CCDC_LPF_SHIFT; - - /* Configure the data shift */ - val |= (config_params->datasft & CCDC_DATASFT_MASK) << - CCDC_DATASFT_SHIFT; - regw(val , MODESET); - dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to MODESET...\n", val); - - /* Configure the Median Filter threshold */ - regw((config_params->med_filt_thres) & CCDC_MED_FILT_THRESH, MEDFILT); - - /* Configure GAMMAWD register. defaur 11-2, and Mosaic cfa pattern */ - val = CCDC_GAMMA_BITS_11_2 << CCDC_GAMMAWD_INPUT_SHIFT | - CCDC_CFA_MOSAIC; - - /* Enable and configure aLaw register if needed */ - if (config_params->alaw.enable) { - val |= (CCDC_ALAW_ENABLE | - ((config_params->alaw.gama_wd & - CCDC_ALAW_GAMA_WD_MASK) << - CCDC_GAMMAWD_INPUT_SHIFT)); - } - - /* Configure Median filter1 & filter2 */ - val |= ((config_params->mfilt1 << CCDC_MFILT1_SHIFT) | - (config_params->mfilt2 << CCDC_MFILT2_SHIFT)); - - regw(val, GAMMAWD); - dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to GAMMAWD...\n", val); - - /* configure video window */ - ccdc_setwin(¶ms->win, params->frm_fmt, 1); - - /* Optical Clamp Averaging */ - ccdc_config_black_clamp(&config_params->blk_clamp); - - /* Black level compensation */ - ccdc_config_black_compense(&config_params->blk_comp); - - /* Vertical Defect Correction if needed */ - if (ccdc_config_vdfc(&config_params->vertical_dft) < 0) - return -EFAULT; - - /* color space conversion */ - ccdc_config_csc(&config_params->csc); - - /* color pattern */ - ccdc_config_color_patterns(&config_params->col_pat_field0, - &config_params->col_pat_field1); - - /* Configure the Gain & offset control */ - ccdc_config_gain_offset(); - - dev_dbg(ccdc_cfg.dev, "\nWriting %x to COLPTN...\n", val); - - /* Configure DATAOFST register */ - val = (config_params->data_offset.horz_offset & CCDC_DATAOFST_MASK) << - CCDC_DATAOFST_H_SHIFT; - val |= (config_params->data_offset.vert_offset & CCDC_DATAOFST_MASK) << - CCDC_DATAOFST_V_SHIFT; - regw(val, DATAOFST); - - /* configuring HSIZE register */ - val = (params->horz_flip_enable & CCDC_HSIZE_FLIP_MASK) << - CCDC_HSIZE_FLIP_SHIFT; - - /* If pack 8 is enable then 1 pixel will take 1 byte */ - if ((config_params->data_sz == CCDC_DATA_8BITS) || - config_params->alaw.enable) { - val |= (((params->win.width) + 31) >> 5) & - CCDC_HSIZE_VAL_MASK; - - /* adjust to multiple of 32 */ - dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to HSIZE...\n", - (((params->win.width) + 31) >> 5) & - CCDC_HSIZE_VAL_MASK); - } else { - /* else one pixel will take 2 byte */ - val |= (((params->win.width * 2) + 31) >> 5) & - CCDC_HSIZE_VAL_MASK; - - dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to HSIZE...\n", - (((params->win.width * 2) + 31) >> 5) & - CCDC_HSIZE_VAL_MASK); - } - regw(val, HSIZE); - - /* Configure SDOFST register */ - if (params->frm_fmt == CCDC_FRMFMT_INTERLACED) { - if (params->image_invert_enable) { - /* For interlace inverse mode */ - regw(CCDC_SDOFST_INTERLACE_INVERSE, SDOFST); - dev_dbg(ccdc_cfg.dev, "\nWriting %x to SDOFST...\n", - CCDC_SDOFST_INTERLACE_INVERSE); - } else { - /* For interlace non inverse mode */ - regw(CCDC_SDOFST_INTERLACE_NORMAL, SDOFST); - dev_dbg(ccdc_cfg.dev, "\nWriting %x to SDOFST...\n", - CCDC_SDOFST_INTERLACE_NORMAL); - } - } else if (params->frm_fmt == CCDC_FRMFMT_PROGRESSIVE) { - if (params->image_invert_enable) { - /* For progessive inverse mode */ - regw(CCDC_SDOFST_PROGRESSIVE_INVERSE, SDOFST); - dev_dbg(ccdc_cfg.dev, "\nWriting %x to SDOFST...\n", - CCDC_SDOFST_PROGRESSIVE_INVERSE); - } else { - /* For progessive non inverse mode */ - regw(CCDC_SDOFST_PROGRESSIVE_NORMAL, SDOFST); - dev_dbg(ccdc_cfg.dev, "\nWriting %x to SDOFST...\n", - CCDC_SDOFST_PROGRESSIVE_NORMAL); - } - } - dev_dbg(ccdc_cfg.dev, "\nend of ccdc_config_raw..."); - return 0; -} - -static int ccdc_configure(void) -{ - if (ccdc_cfg.if_type == VPFE_RAW_BAYER) - return ccdc_config_raw(); - else - ccdc_config_ycbcr(); - return 0; -} - -static int ccdc_set_buftype(enum ccdc_buftype buf_type) -{ - if (ccdc_cfg.if_type == VPFE_RAW_BAYER) - ccdc_cfg.bayer.buf_type = buf_type; - else - ccdc_cfg.ycbcr.buf_type = buf_type; - return 0; -} -static enum ccdc_buftype ccdc_get_buftype(void) -{ - if (ccdc_cfg.if_type == VPFE_RAW_BAYER) - return ccdc_cfg.bayer.buf_type; - return ccdc_cfg.ycbcr.buf_type; -} - -static int ccdc_enum_pix(u32 *pix, int i) -{ - int ret = -EINVAL; - if (ccdc_cfg.if_type == VPFE_RAW_BAYER) { - if (i < ARRAY_SIZE(ccdc_raw_bayer_pix_formats)) { - *pix = ccdc_raw_bayer_pix_formats[i]; - ret = 0; - } - } else { - if (i < ARRAY_SIZE(ccdc_raw_yuv_pix_formats)) { - *pix = ccdc_raw_yuv_pix_formats[i]; - ret = 0; - } - } - return ret; -} - -static int ccdc_set_pixel_format(u32 pixfmt) -{ - struct ccdc_a_law *alaw = &ccdc_cfg.bayer.config_params.alaw; - - if (ccdc_cfg.if_type == VPFE_RAW_BAYER) { - ccdc_cfg.bayer.pix_fmt = CCDC_PIXFMT_RAW; - if (pixfmt == V4L2_PIX_FMT_SBGGR8) - alaw->enable = 1; - else if (pixfmt != V4L2_PIX_FMT_SBGGR16) - return -EINVAL; - } else { - if (pixfmt == V4L2_PIX_FMT_YUYV) - ccdc_cfg.ycbcr.pix_order = CCDC_PIXORDER_YCBYCR; - else if (pixfmt == V4L2_PIX_FMT_UYVY) - ccdc_cfg.ycbcr.pix_order = CCDC_PIXORDER_CBYCRY; - else - return -EINVAL; - } - return 0; -} -static u32 ccdc_get_pixel_format(void) -{ - struct ccdc_a_law *alaw = &ccdc_cfg.bayer.config_params.alaw; - u32 pixfmt; - - if (ccdc_cfg.if_type == VPFE_RAW_BAYER) - if (alaw->enable) - pixfmt = V4L2_PIX_FMT_SBGGR8; - else - pixfmt = V4L2_PIX_FMT_SBGGR16; - else { - if (ccdc_cfg.ycbcr.pix_order == CCDC_PIXORDER_YCBYCR) - pixfmt = V4L2_PIX_FMT_YUYV; - else - pixfmt = V4L2_PIX_FMT_UYVY; - } - return pixfmt; -} -static int ccdc_set_image_window(struct v4l2_rect *win) -{ - if (ccdc_cfg.if_type == VPFE_RAW_BAYER) - ccdc_cfg.bayer.win = *win; - else - ccdc_cfg.ycbcr.win = *win; - return 0; -} - -static void ccdc_get_image_window(struct v4l2_rect *win) -{ - if (ccdc_cfg.if_type == VPFE_RAW_BAYER) - *win = ccdc_cfg.bayer.win; - else - *win = ccdc_cfg.ycbcr.win; -} - -static unsigned int ccdc_get_line_length(void) -{ - struct ccdc_config_params_raw *config_params = - &ccdc_cfg.bayer.config_params; - unsigned int len; - - if (ccdc_cfg.if_type == VPFE_RAW_BAYER) { - if ((config_params->alaw.enable) || - (config_params->data_sz == CCDC_DATA_8BITS)) - len = ccdc_cfg.bayer.win.width; - else - len = ccdc_cfg.bayer.win.width * 2; - } else - len = ccdc_cfg.ycbcr.win.width * 2; - return ALIGN(len, 32); -} - -static int ccdc_set_frame_format(enum ccdc_frmfmt frm_fmt) -{ - if (ccdc_cfg.if_type == VPFE_RAW_BAYER) - ccdc_cfg.bayer.frm_fmt = frm_fmt; - else - ccdc_cfg.ycbcr.frm_fmt = frm_fmt; - return 0; -} - -static enum ccdc_frmfmt ccdc_get_frame_format(void) -{ - if (ccdc_cfg.if_type == VPFE_RAW_BAYER) - return ccdc_cfg.bayer.frm_fmt; - else - return ccdc_cfg.ycbcr.frm_fmt; -} - -static int ccdc_getfid(void) -{ - return (regr(MODESET) >> 15) & 1; -} - -/* misc operations */ -static inline void ccdc_setfbaddr(unsigned long addr) -{ - regw((addr >> 21) & 0x007f, STADRH); - regw((addr >> 5) & 0x0ffff, STADRL); -} - -static int ccdc_set_hw_if_params(struct vpfe_hw_if_param *params) -{ - ccdc_cfg.if_type = params->if_type; - - switch (params->if_type) { - case VPFE_BT656: - case VPFE_YCBCR_SYNC_16: - case VPFE_YCBCR_SYNC_8: - ccdc_cfg.ycbcr.vd_pol = params->vdpol; - ccdc_cfg.ycbcr.hd_pol = params->hdpol; - break; - default: - /* TODO add support for raw bayer here */ - return -EINVAL; - } - return 0; -} - -static struct ccdc_hw_device ccdc_hw_dev = { - .name = "DM355 CCDC", - .owner = THIS_MODULE, - .hw_ops = { - .open = ccdc_open, - .close = ccdc_close, - .enable = ccdc_enable, - .enable_out_to_sdram = ccdc_enable_output_to_sdram, - .set_hw_if_params = ccdc_set_hw_if_params, - .set_params = ccdc_set_params, - .configure = ccdc_configure, - .set_buftype = ccdc_set_buftype, - .get_buftype = ccdc_get_buftype, - .enum_pix = ccdc_enum_pix, - .set_pixel_format = ccdc_set_pixel_format, - .get_pixel_format = ccdc_get_pixel_format, - .set_frame_format = ccdc_set_frame_format, - .get_frame_format = ccdc_get_frame_format, - .set_image_window = ccdc_set_image_window, - .get_image_window = ccdc_get_image_window, - .get_line_length = ccdc_get_line_length, - .setfbaddr = ccdc_setfbaddr, - .getfid = ccdc_getfid, - }, -}; - -static int __init dm355_ccdc_probe(struct platform_device *pdev) -{ - void (*setup_pinmux)(void); - struct resource *res; - int status = 0; - - /* - * first try to register with vpfe. If not correct platform, then we - * don't have to iomap - */ - status = vpfe_register_ccdc_device(&ccdc_hw_dev); - if (status < 0) - return status; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - status = -ENODEV; - goto fail_nores; - } - - res = request_mem_region(res->start, resource_size(res), res->name); - if (!res) { - status = -EBUSY; - goto fail_nores; - } - - ccdc_cfg.base_addr = ioremap_nocache(res->start, resource_size(res)); - if (!ccdc_cfg.base_addr) { - status = -ENOMEM; - goto fail_nomem; - } - - /* Get and enable Master clock */ - ccdc_cfg.mclk = clk_get(&pdev->dev, "master"); - if (IS_ERR(ccdc_cfg.mclk)) { - status = PTR_ERR(ccdc_cfg.mclk); - goto fail_nomap; - } - if (clk_enable(ccdc_cfg.mclk)) { - status = -ENODEV; - goto fail_mclk; - } - - /* Get and enable Slave clock */ - ccdc_cfg.sclk = clk_get(&pdev->dev, "slave"); - if (IS_ERR(ccdc_cfg.sclk)) { - status = PTR_ERR(ccdc_cfg.sclk); - goto fail_mclk; - } - if (clk_enable(ccdc_cfg.sclk)) { - status = -ENODEV; - goto fail_sclk; - } - - /* Platform data holds setup_pinmux function ptr */ - if (NULL == pdev->dev.platform_data) { - status = -ENODEV; - goto fail_sclk; - } - setup_pinmux = pdev->dev.platform_data; - /* - * setup Mux configuration for ccdc which may be different for - * different SoCs using this CCDC - */ - setup_pinmux(); - ccdc_cfg.dev = &pdev->dev; - printk(KERN_NOTICE "%s is registered with vpfe.\n", ccdc_hw_dev.name); - return 0; -fail_sclk: - clk_put(ccdc_cfg.sclk); -fail_mclk: - clk_put(ccdc_cfg.mclk); -fail_nomap: - iounmap(ccdc_cfg.base_addr); -fail_nomem: - release_mem_region(res->start, resource_size(res)); -fail_nores: - vpfe_unregister_ccdc_device(&ccdc_hw_dev); - return status; -} - -static int dm355_ccdc_remove(struct platform_device *pdev) -{ - struct resource *res; - - clk_put(ccdc_cfg.mclk); - clk_put(ccdc_cfg.sclk); - iounmap(ccdc_cfg.base_addr); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (res) - release_mem_region(res->start, resource_size(res)); - vpfe_unregister_ccdc_device(&ccdc_hw_dev); - return 0; -} - -static struct platform_driver dm355_ccdc_driver = { - .driver = { - .name = "dm355_ccdc", - .owner = THIS_MODULE, - }, - .remove = __devexit_p(dm355_ccdc_remove), - .probe = dm355_ccdc_probe, -}; - -static int __init dm355_ccdc_init(void) -{ - return platform_driver_register(&dm355_ccdc_driver); -} - -static void __exit dm355_ccdc_exit(void) -{ - platform_driver_unregister(&dm355_ccdc_driver); -} - -module_init(dm355_ccdc_init); -module_exit(dm355_ccdc_exit); diff --git a/drivers/media/video/davinci/dm355_ccdc_regs.h b/drivers/media/video/davinci/dm355_ccdc_regs.h deleted file mode 100644 index d6d2ef0533b..00000000000 --- a/drivers/media/video/davinci/dm355_ccdc_regs.h +++ /dev/null @@ -1,310 +0,0 @@ -/* - * Copyright (C) 2005-2009 Texas Instruments Inc - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#ifndef _DM355_CCDC_REGS_H -#define _DM355_CCDC_REGS_H - -/**************************************************************************\ -* Register OFFSET Definitions -\**************************************************************************/ -#define SYNCEN 0x00 -#define MODESET 0x04 -#define HDWIDTH 0x08 -#define VDWIDTH 0x0c -#define PPLN 0x10 -#define LPFR 0x14 -#define SPH 0x18 -#define NPH 0x1c -#define SLV0 0x20 -#define SLV1 0x24 -#define NLV 0x28 -#define CULH 0x2c -#define CULV 0x30 -#define HSIZE 0x34 -#define SDOFST 0x38 -#define STADRH 0x3c -#define STADRL 0x40 -#define CLAMP 0x44 -#define DCSUB 0x48 -#define COLPTN 0x4c -#define BLKCMP0 0x50 -#define BLKCMP1 0x54 -#define MEDFILT 0x58 -#define RYEGAIN 0x5c -#define GRCYGAIN 0x60 -#define GBGGAIN 0x64 -#define BMGGAIN 0x68 -#define OFFSET 0x6c -#define OUTCLIP 0x70 -#define VDINT0 0x74 -#define VDINT1 0x78 -#define RSV0 0x7c -#define GAMMAWD 0x80 -#define REC656IF 0x84 -#define CCDCFG 0x88 -#define FMTCFG 0x8c -#define FMTPLEN 0x90 -#define FMTSPH 0x94 -#define FMTLNH 0x98 -#define FMTSLV 0x9c -#define FMTLNV 0xa0 -#define FMTRLEN 0xa4 -#define FMTHCNT 0xa8 -#define FMT_ADDR_PTR_B 0xac -#define FMT_ADDR_PTR(i) (FMT_ADDR_PTR_B + (i * 4)) -#define FMTPGM_VF0 0xcc -#define FMTPGM_VF1 0xd0 -#define FMTPGM_AP0 0xd4 -#define FMTPGM_AP1 0xd8 -#define FMTPGM_AP2 0xdc -#define FMTPGM_AP3 0xe0 -#define FMTPGM_AP4 0xe4 -#define FMTPGM_AP5 0xe8 -#define FMTPGM_AP6 0xec -#define FMTPGM_AP7 0xf0 -#define LSCCFG1 0xf4 -#define LSCCFG2 0xf8 -#define LSCH0 0xfc -#define LSCV0 0x100 -#define LSCKH 0x104 -#define LSCKV 0x108 -#define LSCMEMCTL 0x10c -#define LSCMEMD 0x110 -#define LSCMEMQ 0x114 -#define DFCCTL 0x118 -#define DFCVSAT 0x11c -#define DFCMEMCTL 0x120 -#define DFCMEM0 0x124 -#define DFCMEM1 0x128 -#define DFCMEM2 0x12c -#define DFCMEM3 0x130 -#define DFCMEM4 0x134 -#define CSCCTL 0x138 -#define CSCM0 0x13c -#define CSCM1 0x140 -#define CSCM2 0x144 -#define CSCM3 0x148 -#define CSCM4 0x14c -#define CSCM5 0x150 -#define CSCM6 0x154 -#define CSCM7 0x158 -#define DATAOFST 0x15c -#define CCDC_REG_LAST DATAOFST -/************************************************************** -* Define for various register bit mask and shifts for CCDC -* -**************************************************************/ -#define CCDC_RAW_IP_MODE 0 -#define CCDC_VDHDOUT_INPUT 0 -#define CCDC_YCINSWP_RAW (0 << 4) -#define CCDC_EXWEN_DISABLE 0 -#define CCDC_DATAPOL_NORMAL 0 -#define CCDC_CCDCFG_FIDMD_LATCH_VSYNC 0 -#define CCDC_CCDCFG_FIDMD_NO_LATCH_VSYNC (1 << 6) -#define CCDC_CCDCFG_WENLOG_AND 0 -#define CCDC_CCDCFG_TRGSEL_WEN 0 -#define CCDC_CCDCFG_EXTRG_DISABLE 0 -#define CCDC_CFA_MOSAIC 0 -#define CCDC_Y8POS_SHIFT 11 - -#define CCDC_VDC_DFCVSAT_MASK 0x3fff -#define CCDC_DATAOFST_MASK 0x0ff -#define CCDC_DATAOFST_H_SHIFT 0 -#define CCDC_DATAOFST_V_SHIFT 8 -#define CCDC_GAMMAWD_CFA_MASK 1 -#define CCDC_GAMMAWD_CFA_SHIFT 5 -#define CCDC_GAMMAWD_INPUT_SHIFT 2 -#define CCDC_FID_POL_MASK 1 -#define CCDC_FID_POL_SHIFT 4 -#define CCDC_HD_POL_MASK 1 -#define CCDC_HD_POL_SHIFT 3 -#define CCDC_VD_POL_MASK 1 -#define CCDC_VD_POL_SHIFT 2 -#define CCDC_VD_POL_NEGATIVE (1 << 2) -#define CCDC_FRM_FMT_MASK 1 -#define CCDC_FRM_FMT_SHIFT 7 -#define CCDC_DATA_SZ_MASK 7 -#define CCDC_DATA_SZ_SHIFT 8 -#define CCDC_VDHDOUT_MASK 1 -#define CCDC_VDHDOUT_SHIFT 0 -#define CCDC_EXWEN_MASK 1 -#define CCDC_EXWEN_SHIFT 5 -#define CCDC_INPUT_MODE_MASK 3 -#define CCDC_INPUT_MODE_SHIFT 12 -#define CCDC_PIX_FMT_MASK 3 -#define CCDC_PIX_FMT_SHIFT 12 -#define CCDC_DATAPOL_MASK 1 -#define CCDC_DATAPOL_SHIFT 6 -#define CCDC_WEN_ENABLE (1 << 1) -#define CCDC_VDHDEN_ENABLE (1 << 16) -#define CCDC_LPF_ENABLE (1 << 14) -#define CCDC_ALAW_ENABLE 1 -#define CCDC_ALAW_GAMA_WD_MASK 7 -#define CCDC_REC656IF_BT656_EN 3 - -#define CCDC_FMTCFG_FMTMODE_MASK 3 -#define CCDC_FMTCFG_FMTMODE_SHIFT 1 -#define CCDC_FMTCFG_LNUM_MASK 3 -#define CCDC_FMTCFG_LNUM_SHIFT 4 -#define CCDC_FMTCFG_ADDRINC_MASK 7 -#define CCDC_FMTCFG_ADDRINC_SHIFT 8 - -#define CCDC_CCDCFG_FIDMD_SHIFT 6 -#define CCDC_CCDCFG_WENLOG_SHIFT 8 -#define CCDC_CCDCFG_TRGSEL_SHIFT 9 -#define CCDC_CCDCFG_EXTRG_SHIFT 10 -#define CCDC_CCDCFG_MSBINVI_SHIFT 13 - -#define CCDC_HSIZE_FLIP_SHIFT 12 -#define CCDC_HSIZE_FLIP_MASK 1 -#define CCDC_HSIZE_VAL_MASK 0xFFF -#define CCDC_SDOFST_FIELD_INTERLEAVED 0x249 -#define CCDC_SDOFST_INTERLACE_INVERSE 0x4B6D -#define CCDC_SDOFST_INTERLACE_NORMAL 0x0B6D -#define CCDC_SDOFST_PROGRESSIVE_INVERSE 0x4000 -#define CCDC_SDOFST_PROGRESSIVE_NORMAL 0 -#define CCDC_START_PX_HOR_MASK 0x7FFF -#define CCDC_NUM_PX_HOR_MASK 0x7FFF -#define CCDC_START_VER_ONE_MASK 0x7FFF -#define CCDC_START_VER_TWO_MASK 0x7FFF -#define CCDC_NUM_LINES_VER 0x7FFF - -#define CCDC_BLK_CLAMP_ENABLE (1 << 15) -#define CCDC_BLK_SGAIN_MASK 0x1F -#define CCDC_BLK_ST_PXL_MASK 0x1FFF -#define CCDC_BLK_SAMPLE_LN_MASK 3 -#define CCDC_BLK_SAMPLE_LN_SHIFT 13 - -#define CCDC_NUM_LINE_CALC_MASK 3 -#define CCDC_NUM_LINE_CALC_SHIFT 14 - -#define CCDC_BLK_DC_SUB_MASK 0x3FFF -#define CCDC_BLK_COMP_MASK 0xFF -#define CCDC_BLK_COMP_GB_COMP_SHIFT 8 -#define CCDC_BLK_COMP_GR_COMP_SHIFT 0 -#define CCDC_BLK_COMP_R_COMP_SHIFT 8 -#define CCDC_LATCH_ON_VSYNC_DISABLE (1 << 15) -#define CCDC_LATCH_ON_VSYNC_ENABLE (0 << 15) -#define CCDC_FPC_ENABLE (1 << 15) -#define CCDC_FPC_FPC_NUM_MASK 0x7FFF -#define CCDC_DATA_PACK_ENABLE (1 << 11) -#define CCDC_FMT_HORZ_FMTLNH_MASK 0x1FFF -#define CCDC_FMT_HORZ_FMTSPH_MASK 0x1FFF -#define CCDC_FMT_HORZ_FMTSPH_SHIFT 16 -#define CCDC_FMT_VERT_FMTLNV_MASK 0x1FFF -#define CCDC_FMT_VERT_FMTSLV_MASK 0x1FFF -#define CCDC_FMT_VERT_FMTSLV_SHIFT 16 -#define CCDC_VP_OUT_VERT_NUM_MASK 0x3FFF -#define CCDC_VP_OUT_VERT_NUM_SHIFT 17 -#define CCDC_VP_OUT_HORZ_NUM_MASK 0x1FFF -#define CCDC_VP_OUT_HORZ_NUM_SHIFT 4 -#define CCDC_VP_OUT_HORZ_ST_MASK 0xF - -#define CCDC_CSC_COEF_INTEG_MASK 7 -#define CCDC_CSC_COEF_DECIMAL_MASK 0x1f -#define CCDC_CSC_COEF_INTEG_SHIFT 5 -#define CCDC_CSCM_MSB_SHIFT 8 -#define CCDC_CSC_ENABLE 1 -#define CCDC_CSC_DEC_MAX 32 - -#define CCDC_MFILT1_SHIFT 10 -#define CCDC_MFILT2_SHIFT 8 -#define CCDC_MED_FILT_THRESH 0x3FFF -#define CCDC_LPF_MASK 1 -#define CCDC_LPF_SHIFT 14 -#define CCDC_OFFSET_MASK 0x3FF -#define CCDC_DATASFT_MASK 7 -#define CCDC_DATASFT_SHIFT 8 - -#define CCDC_DF_ENABLE 1 - -#define CCDC_FMTPLEN_P0_MASK 0xF -#define CCDC_FMTPLEN_P1_MASK 0xF -#define CCDC_FMTPLEN_P2_MASK 7 -#define CCDC_FMTPLEN_P3_MASK 7 -#define CCDC_FMTPLEN_P0_SHIFT 0 -#define CCDC_FMTPLEN_P1_SHIFT 4 -#define CCDC_FMTPLEN_P2_SHIFT 8 -#define CCDC_FMTPLEN_P3_SHIFT 12 - -#define CCDC_FMTSPH_MASK 0x1FFF -#define CCDC_FMTLNH_MASK 0x1FFF -#define CCDC_FMTSLV_MASK 0x1FFF -#define CCDC_FMTLNV_MASK 0x7FFF -#define CCDC_FMTRLEN_MASK 0x1FFF -#define CCDC_FMTHCNT_MASK 0x1FFF - -#define CCDC_ADP_INIT_MASK 0x1FFF -#define CCDC_ADP_LINE_SHIFT 13 -#define CCDC_ADP_LINE_MASK 3 -#define CCDC_FMTPGN_APTR_MASK 7 - -#define CCDC_DFCCTL_GDFCEN_MASK 1 -#define CCDC_DFCCTL_VDFCEN_MASK 1 -#define CCDC_DFCCTL_VDFC_DISABLE (0 << 4) -#define CCDC_DFCCTL_VDFCEN_SHIFT 4 -#define CCDC_DFCCTL_VDFCSL_MASK 3 -#define CCDC_DFCCTL_VDFCSL_SHIFT 5 -#define CCDC_DFCCTL_VDFCUDA_MASK 1 -#define CCDC_DFCCTL_VDFCUDA_SHIFT 7 -#define CCDC_DFCCTL_VDFLSFT_MASK 3 -#define CCDC_DFCCTL_VDFLSFT_SHIFT 8 -#define CCDC_DFCMEMCTL_DFCMARST_MASK 1 -#define CCDC_DFCMEMCTL_DFCMARST_SHIFT 2 -#define CCDC_DFCMEMCTL_DFCMWR_MASK 1 -#define CCDC_DFCMEMCTL_DFCMWR_SHIFT 0 -#define CCDC_DFCMEMCTL_INC_ADDR (0 << 2) - -#define CCDC_LSCCFG_GFTSF_MASK 7 -#define CCDC_LSCCFG_GFTSF_SHIFT 1 -#define CCDC_LSCCFG_GFTINV_MASK 0xf -#define CCDC_LSCCFG_GFTINV_SHIFT 4 -#define CCDC_LSC_GFTABLE_SEL_MASK 3 -#define CCDC_LSC_GFTABLE_EPEL_SHIFT 8 -#define CCDC_LSC_GFTABLE_OPEL_SHIFT 10 -#define CCDC_LSC_GFTABLE_EPOL_SHIFT 12 -#define CCDC_LSC_GFTABLE_OPOL_SHIFT 14 -#define CCDC_LSC_GFMODE_MASK 3 -#define CCDC_LSC_GFMODE_SHIFT 4 -#define CCDC_LSC_DISABLE 0 -#define CCDC_LSC_ENABLE 1 -#define CCDC_LSC_TABLE1_SLC 0 -#define CCDC_LSC_TABLE2_SLC 1 -#define CCDC_LSC_TABLE3_SLC 2 -#define CCDC_LSC_MEMADDR_RESET (1 << 2) -#define CCDC_LSC_MEMADDR_INCR (0 << 2) -#define CCDC_LSC_FRAC_MASK_T1 0xFF -#define CCDC_LSC_INT_MASK 3 -#define CCDC_LSC_FRAC_MASK 0x3FFF -#define CCDC_LSC_CENTRE_MASK 0x3FFF -#define CCDC_LSC_COEF_MASK 0xff -#define CCDC_LSC_COEFL_SHIFT 0 -#define CCDC_LSC_COEFU_SHIFT 8 -#define CCDC_GAIN_MASK 0x7FF -#define CCDC_SYNCEN_VDHDEN_MASK (1 << 0) -#define CCDC_SYNCEN_WEN_MASK (1 << 1) -#define CCDC_SYNCEN_WEN_SHIFT 1 - -/* Power on Defaults in hardware */ -#define MODESET_DEFAULT 0x200 -#define CULH_DEFAULT 0xFFFF -#define CULV_DEFAULT 0xFF -#define GAIN_DEFAULT 256 -#define OUTCLIP_DEFAULT 0x3FFF -#define LSCCFG2_DEFAULT 0xE - -#endif diff --git a/drivers/media/video/davinci/dm644x_ccdc.c b/drivers/media/video/davinci/dm644x_ccdc.c deleted file mode 100644 index 490aafb34e2..00000000000 --- a/drivers/media/video/davinci/dm644x_ccdc.c +++ /dev/null @@ -1,1091 +0,0 @@ -/* - * Copyright (C) 2006-2009 Texas Instruments Inc - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * CCDC hardware module for DM6446 - * ------------------------------ - * - * This module is for configuring CCD controller of DM6446 VPFE to capture - * Raw yuv or Bayer RGB data from a decoder. CCDC has several modules - * such as Defect Pixel Correction, Color Space Conversion etc to - * pre-process the Raw Bayer RGB data, before writing it to SDRAM. This - * module also allows application to configure individual - * module parameters through VPFE_CMD_S_CCDC_RAW_PARAMS IOCTL. - * To do so, application includes dm644x_ccdc.h and vpfe_capture.h header - * files. The setparams() API is called by vpfe_capture driver - * to configure module parameters. This file is named DM644x so that other - * variants such DM6443 may be supported using the same module. - * - * TODO: Test Raw bayer parameter settings and bayer capture - * Split module parameter structure to module specific ioctl structs - * investigate if enum used for user space type definition - * to be replaced by #defines or integer - */ -#include <linux/platform_device.h> -#include <linux/uaccess.h> -#include <linux/videodev2.h> -#include <linux/gfp.h> -#include <linux/clk.h> -#include <linux/err.h> - -#include <media/davinci/dm644x_ccdc.h> -#include <media/davinci/vpss.h> - -#include "dm644x_ccdc_regs.h" -#include "ccdc_hw_device.h" - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("CCDC Driver for DM6446"); -MODULE_AUTHOR("Texas Instruments"); - -static struct ccdc_oper_config { - struct device *dev; - /* CCDC interface type */ - enum vpfe_hw_if_type if_type; - /* Raw Bayer configuration */ - struct ccdc_params_raw bayer; - /* YCbCr configuration */ - struct ccdc_params_ycbcr ycbcr; - /* Master clock */ - struct clk *mclk; - /* slave clock */ - struct clk *sclk; - /* ccdc base address */ - void __iomem *base_addr; -} ccdc_cfg = { - /* Raw configurations */ - .bayer = { - .pix_fmt = CCDC_PIXFMT_RAW, - .frm_fmt = CCDC_FRMFMT_PROGRESSIVE, - .win = CCDC_WIN_VGA, - .fid_pol = VPFE_PINPOL_POSITIVE, - .vd_pol = VPFE_PINPOL_POSITIVE, - .hd_pol = VPFE_PINPOL_POSITIVE, - .config_params = { - .data_sz = CCDC_DATA_10BITS, - }, - }, - .ycbcr = { - .pix_fmt = CCDC_PIXFMT_YCBCR_8BIT, - .frm_fmt = CCDC_FRMFMT_INTERLACED, - .win = CCDC_WIN_PAL, - .fid_pol = VPFE_PINPOL_POSITIVE, - .vd_pol = VPFE_PINPOL_POSITIVE, - .hd_pol = VPFE_PINPOL_POSITIVE, - .bt656_enable = 1, - .pix_order = CCDC_PIXORDER_CBYCRY, - .buf_type = CCDC_BUFTYPE_FLD_INTERLEAVED - }, -}; - -#define CCDC_MAX_RAW_YUV_FORMATS 2 - -/* Raw Bayer formats */ -static u32 ccdc_raw_bayer_pix_formats[] = - {V4L2_PIX_FMT_SBGGR8, V4L2_PIX_FMT_SBGGR16}; - -/* Raw YUV formats */ -static u32 ccdc_raw_yuv_pix_formats[] = - {V4L2_PIX_FMT_UYVY, V4L2_PIX_FMT_YUYV}; - -/* CCDC Save/Restore context */ -static u32 ccdc_ctx[CCDC_REG_END / sizeof(u32)]; - -/* register access routines */ -static inline u32 regr(u32 offset) -{ - return __raw_readl(ccdc_cfg.base_addr + offset); -} - -static inline void regw(u32 val, u32 offset) -{ - __raw_writel(val, ccdc_cfg.base_addr + offset); -} - -static void ccdc_enable(int flag) -{ - regw(flag, CCDC_PCR); -} - -static void ccdc_enable_vport(int flag) -{ - if (flag) - /* enable video port */ - regw(CCDC_ENABLE_VIDEO_PORT, CCDC_FMTCFG); - else - regw(CCDC_DISABLE_VIDEO_PORT, CCDC_FMTCFG); -} - -/* - * ccdc_setwin() - * This function will configure the window size - * to be capture in CCDC reg - */ -void ccdc_setwin(struct v4l2_rect *image_win, - enum ccdc_frmfmt frm_fmt, - int ppc) -{ - int horz_start, horz_nr_pixels; - int vert_start, vert_nr_lines; - int val = 0, mid_img = 0; - - dev_dbg(ccdc_cfg.dev, "\nStarting ccdc_setwin..."); - /* - * ppc - per pixel count. indicates how many pixels per cell - * output to SDRAM. example, for ycbcr, it is one y and one c, so 2. - * raw capture this is 1 - */ - horz_start = image_win->left << (ppc - 1); - horz_nr_pixels = (image_win->width << (ppc - 1)) - 1; - regw((horz_start << CCDC_HORZ_INFO_SPH_SHIFT) | horz_nr_pixels, - CCDC_HORZ_INFO); - - vert_start = image_win->top; - - if (frm_fmt == CCDC_FRMFMT_INTERLACED) { - vert_nr_lines = (image_win->height >> 1) - 1; - vert_start >>= 1; - /* Since first line doesn't have any data */ - vert_start += 1; - /* configure VDINT0 */ - val = (vert_start << CCDC_VDINT_VDINT0_SHIFT); - regw(val, CCDC_VDINT); - - } else { - /* Since first line doesn't have any data */ - vert_start += 1; - vert_nr_lines = image_win->height - 1; - /* - * configure VDINT0 and VDINT1. VDINT1 will be at half - * of image height - */ - mid_img = vert_start + (image_win->height / 2); - val = (vert_start << CCDC_VDINT_VDINT0_SHIFT) | - (mid_img & CCDC_VDINT_VDINT1_MASK); - regw(val, CCDC_VDINT); - - } - regw((vert_start << CCDC_VERT_START_SLV0_SHIFT) | vert_start, - CCDC_VERT_START); - regw(vert_nr_lines, CCDC_VERT_LINES); - dev_dbg(ccdc_cfg.dev, "\nEnd of ccdc_setwin..."); -} - -static void ccdc_readregs(void) -{ - unsigned int val = 0; - - val = regr(CCDC_ALAW); - dev_notice(ccdc_cfg.dev, "\nReading 0x%x to ALAW...\n", val); - val = regr(CCDC_CLAMP); - dev_notice(ccdc_cfg.dev, "\nReading 0x%x to CLAMP...\n", val); - val = regr(CCDC_DCSUB); - dev_notice(ccdc_cfg.dev, "\nReading 0x%x to DCSUB...\n", val); - val = regr(CCDC_BLKCMP); - dev_notice(ccdc_cfg.dev, "\nReading 0x%x to BLKCMP...\n", val); - val = regr(CCDC_FPC_ADDR); - dev_notice(ccdc_cfg.dev, "\nReading 0x%x to FPC_ADDR...\n", val); - val = regr(CCDC_FPC); - dev_notice(ccdc_cfg.dev, "\nReading 0x%x to FPC...\n", val); - val = regr(CCDC_FMTCFG); - dev_notice(ccdc_cfg.dev, "\nReading 0x%x to FMTCFG...\n", val); - val = regr(CCDC_COLPTN); - dev_notice(ccdc_cfg.dev, "\nReading 0x%x to COLPTN...\n", val); - val = regr(CCDC_FMT_HORZ); - dev_notice(ccdc_cfg.dev, "\nReading 0x%x to FMT_HORZ...\n", val); - val = regr(CCDC_FMT_VERT); - dev_notice(ccdc_cfg.dev, "\nReading 0x%x to FMT_VERT...\n", val); - val = regr(CCDC_HSIZE_OFF); - dev_notice(ccdc_cfg.dev, "\nReading 0x%x to HSIZE_OFF...\n", val); - val = regr(CCDC_SDOFST); - dev_notice(ccdc_cfg.dev, "\nReading 0x%x to SDOFST...\n", val); - val = regr(CCDC_VP_OUT); - dev_notice(ccdc_cfg.dev, "\nReading 0x%x to VP_OUT...\n", val); - val = regr(CCDC_SYN_MODE); - dev_notice(ccdc_cfg.dev, "\nReading 0x%x to SYN_MODE...\n", val); - val = regr(CCDC_HORZ_INFO); - dev_notice(ccdc_cfg.dev, "\nReading 0x%x to HORZ_INFO...\n", val); - val = regr(CCDC_VERT_START); - dev_notice(ccdc_cfg.dev, "\nReading 0x%x to VERT_START...\n", val); - val = regr(CCDC_VERT_LINES); - dev_notice(ccdc_cfg.dev, "\nReading 0x%x to VERT_LINES...\n", val); -} - -static int validate_ccdc_param(struct ccdc_config_params_raw *ccdcparam) -{ - if (ccdcparam->alaw.enable) { - if ((ccdcparam->alaw.gama_wd > CCDC_GAMMA_BITS_09_0) || - (ccdcparam->alaw.gama_wd < CCDC_GAMMA_BITS_15_6) || - (ccdcparam->alaw.gama_wd < ccdcparam->data_sz)) { - dev_dbg(ccdc_cfg.dev, "\nInvalid data line select"); - return -1; - } - } - return 0; -} - -static int ccdc_update_raw_params(struct ccdc_config_params_raw *raw_params) -{ - struct ccdc_config_params_raw *config_params = - &ccdc_cfg.bayer.config_params; - unsigned int *fpc_virtaddr = NULL; - unsigned int *fpc_physaddr = NULL; - - memcpy(config_params, raw_params, sizeof(*raw_params)); - /* - * allocate memory for fault pixel table and copy the user - * values to the table - */ - if (!config_params->fault_pxl.enable) - return 0; - - fpc_physaddr = (unsigned int *)config_params->fault_pxl.fpc_table_addr; - fpc_virtaddr = (unsigned int *)phys_to_virt( - (unsigned long)fpc_physaddr); - /* - * Allocate memory for FPC table if current - * FPC table buffer is not big enough to - * accomodate FPC Number requested - */ - if (raw_params->fault_pxl.fp_num != config_params->fault_pxl.fp_num) { - if (fpc_physaddr != NULL) { - free_pages((unsigned long)fpc_physaddr, - get_order - (config_params->fault_pxl.fp_num * - FP_NUM_BYTES)); - } - - /* Allocate memory for FPC table */ - fpc_virtaddr = - (unsigned int *)__get_free_pages(GFP_KERNEL | GFP_DMA, - get_order(raw_params-> - fault_pxl.fp_num * - FP_NUM_BYTES)); - - if (fpc_virtaddr == NULL) { - dev_dbg(ccdc_cfg.dev, - "\nUnable to allocate memory for FPC"); - return -EFAULT; - } - fpc_physaddr = - (unsigned int *)virt_to_phys((void *)fpc_virtaddr); - } - - /* Copy number of fault pixels and FPC table */ - config_params->fault_pxl.fp_num = raw_params->fault_pxl.fp_num; - if (copy_from_user(fpc_virtaddr, - (void __user *)raw_params->fault_pxl.fpc_table_addr, - config_params->fault_pxl.fp_num * FP_NUM_BYTES)) { - dev_dbg(ccdc_cfg.dev, "\n copy_from_user failed"); - return -EFAULT; - } - config_params->fault_pxl.fpc_table_addr = (unsigned int)fpc_physaddr; - return 0; -} - -static int ccdc_close(struct device *dev) -{ - struct ccdc_config_params_raw *config_params = - &ccdc_cfg.bayer.config_params; - unsigned int *fpc_physaddr = NULL, *fpc_virtaddr = NULL; - - fpc_physaddr = (unsigned int *)config_params->fault_pxl.fpc_table_addr; - - if (fpc_physaddr != NULL) { - fpc_virtaddr = (unsigned int *) - phys_to_virt((unsigned long)fpc_physaddr); - free_pages((unsigned long)fpc_virtaddr, - get_order(config_params->fault_pxl.fp_num * - FP_NUM_BYTES)); - } - return 0; -} - -/* - * ccdc_restore_defaults() - * This function will write defaults to all CCDC registers - */ -static void ccdc_restore_defaults(void) -{ - int i; - - /* disable CCDC */ - ccdc_enable(0); - /* set all registers to default value */ - for (i = 4; i <= 0x94; i += 4) - regw(0, i); - regw(CCDC_NO_CULLING, CCDC_CULLING); - regw(CCDC_GAMMA_BITS_11_2, CCDC_ALAW); -} - -static int ccdc_open(struct device *device) -{ - ccdc_restore_defaults(); - if (ccdc_cfg.if_type == VPFE_RAW_BAYER) - ccdc_enable_vport(1); - return 0; -} - -static void ccdc_sbl_reset(void) -{ - vpss_clear_wbl_overflow(VPSS_PCR_CCDC_WBL_O); -} - -/* Parameter operations */ -static int ccdc_set_params(void __user *params) -{ - struct ccdc_config_params_raw ccdc_raw_params; - int x; - - if (ccdc_cfg.if_type != VPFE_RAW_BAYER) - return -EINVAL; - - x = copy_from_user(&ccdc_raw_params, params, sizeof(ccdc_raw_params)); - if (x) { - dev_dbg(ccdc_cfg.dev, "ccdc_set_params: error in copying" - "ccdc params, %d\n", x); - return -EFAULT; - } - - if (!validate_ccdc_param(&ccdc_raw_params)) { - if (!ccdc_update_raw_params(&ccdc_raw_params)) - return 0; - } - return -EINVAL; -} - -/* - * ccdc_config_ycbcr() - * This function will configure CCDC for YCbCr video capture - */ -void ccdc_config_ycbcr(void) -{ - struct ccdc_params_ycbcr *params = &ccdc_cfg.ycbcr; - u32 syn_mode; - - dev_dbg(ccdc_cfg.dev, "\nStarting ccdc_config_ycbcr..."); - /* - * first restore the CCDC registers to default values - * This is important since we assume default values to be set in - * a lot of registers that we didn't touch - */ - ccdc_restore_defaults(); - - /* - * configure pixel format, frame format, configure video frame - * format, enable output to SDRAM, enable internal timing generator - * and 8bit pack mode - */ - syn_mode = (((params->pix_fmt & CCDC_SYN_MODE_INPMOD_MASK) << - CCDC_SYN_MODE_INPMOD_SHIFT) | - ((params->frm_fmt & CCDC_SYN_FLDMODE_MASK) << - CCDC_SYN_FLDMODE_SHIFT) | CCDC_VDHDEN_ENABLE | - CCDC_WEN_ENABLE | CCDC_DATA_PACK_ENABLE); - - /* setup BT.656 sync mode */ - if (params->bt656_enable) { - regw(CCDC_REC656IF_BT656_EN, CCDC_REC656IF); - - /* - * configure the FID, VD, HD pin polarity, - * fld,hd pol positive, vd negative, 8-bit data - */ - syn_mode |= CCDC_SYN_MODE_VD_POL_NEGATIVE; - if (ccdc_cfg.if_type == VPFE_BT656_10BIT) - syn_mode |= CCDC_SYN_MODE_10BITS; - else - syn_mode |= CCDC_SYN_MODE_8BITS; - } else { - /* y/c external sync mode */ - syn_mode |= (((params->fid_pol & CCDC_FID_POL_MASK) << - CCDC_FID_POL_SHIFT) | - ((params->hd_pol & CCDC_HD_POL_MASK) << - CCDC_HD_POL_SHIFT) | - ((params->vd_pol & CCDC_VD_POL_MASK) << - CCDC_VD_POL_SHIFT)); - } - regw(syn_mode, CCDC_SYN_MODE); - - /* configure video window */ - ccdc_setwin(¶ms->win, params->frm_fmt, 2); - - /* - * configure the order of y cb cr in SDRAM, and disable latch - * internal register on vsync - */ - if (ccdc_cfg.if_type == VPFE_BT656_10BIT) - regw((params->pix_order << CCDC_CCDCFG_Y8POS_SHIFT) | - CCDC_LATCH_ON_VSYNC_DISABLE | CCDC_CCDCFG_BW656_10BIT, - CCDC_CCDCFG); - else - regw((params->pix_order << CCDC_CCDCFG_Y8POS_SHIFT) | - CCDC_LATCH_ON_VSYNC_DISABLE, CCDC_CCDCFG); - - /* - * configure the horizontal line offset. This should be a - * on 32 byte bondary. So clear LSB 5 bits - */ - regw(((params->win.width * 2 + 31) & ~0x1f), CCDC_HSIZE_OFF); - - /* configure the memory line offset */ - if (params->buf_type == CCDC_BUFTYPE_FLD_INTERLEAVED) - /* two fields are interleaved in memory */ - regw(CCDC_SDOFST_FIELD_INTERLEAVED, CCDC_SDOFST); - - ccdc_sbl_reset(); - dev_dbg(ccdc_cfg.dev, "\nEnd of ccdc_config_ycbcr...\n"); -} - -static void ccdc_config_black_clamp(struct ccdc_black_clamp *bclamp) -{ - u32 val; - - if (!bclamp->enable) { - /* configure DCSub */ - val = (bclamp->dc_sub) & CCDC_BLK_DC_SUB_MASK; - regw(val, CCDC_DCSUB); - dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to DCSUB...\n", val); - regw(CCDC_CLAMP_DEFAULT_VAL, CCDC_CLAMP); - dev_dbg(ccdc_cfg.dev, "\nWriting 0x0000 to CLAMP...\n"); - return; - } - /* - * Configure gain, Start pixel, No of line to be avg, - * No of pixel/line to be avg, & Enable the Black clamping - */ - val = ((bclamp->sgain & CCDC_BLK_SGAIN_MASK) | - ((bclamp->start_pixel & CCDC_BLK_ST_PXL_MASK) << - CCDC_BLK_ST_PXL_SHIFT) | - ((bclamp->sample_ln & CCDC_BLK_SAMPLE_LINE_MASK) << - CCDC_BLK_SAMPLE_LINE_SHIFT) | - ((bclamp->sample_pixel & CCDC_BLK_SAMPLE_LN_MASK) << - CCDC_BLK_SAMPLE_LN_SHIFT) | CCDC_BLK_CLAMP_ENABLE); - regw(val, CCDC_CLAMP); - dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to CLAMP...\n", val); - /* If Black clamping is enable then make dcsub 0 */ - regw(CCDC_DCSUB_DEFAULT_VAL, CCDC_DCSUB); - dev_dbg(ccdc_cfg.dev, "\nWriting 0x00000000 to DCSUB...\n"); -} - -static void ccdc_config_black_compense(struct ccdc_black_compensation *bcomp) -{ - u32 val; - - val = ((bcomp->b & CCDC_BLK_COMP_MASK) | - ((bcomp->gb & CCDC_BLK_COMP_MASK) << - CCDC_BLK_COMP_GB_COMP_SHIFT) | - ((bcomp->gr & CCDC_BLK_COMP_MASK) << - CCDC_BLK_COMP_GR_COMP_SHIFT) | - ((bcomp->r & CCDC_BLK_COMP_MASK) << - CCDC_BLK_COMP_R_COMP_SHIFT)); - regw(val, CCDC_BLKCMP); -} - -static void ccdc_config_fpc(struct ccdc_fault_pixel *fpc) -{ - u32 val; - - /* Initially disable FPC */ - val = CCDC_FPC_DISABLE; - regw(val, CCDC_FPC); - - if (!fpc->enable) - return; - - /* Configure Fault pixel if needed */ - regw(fpc->fpc_table_addr, CCDC_FPC_ADDR); - dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to FPC_ADDR...\n", - (fpc->fpc_table_addr)); - /* Write the FPC params with FPC disable */ - val = fpc->fp_num & CCDC_FPC_FPC_NUM_MASK; - regw(val, CCDC_FPC); - - dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to FPC...\n", val); - /* read the FPC register */ - val = regr(CCDC_FPC) | CCDC_FPC_ENABLE; - regw(val, CCDC_FPC); - dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to FPC...\n", val); -} - -/* - * ccdc_config_raw() - * This function will configure CCDC for Raw capture mode - */ -void ccdc_config_raw(void) -{ - struct ccdc_params_raw *params = &ccdc_cfg.bayer; - struct ccdc_config_params_raw *config_params = - &ccdc_cfg.bayer.config_params; - unsigned int syn_mode = 0; - unsigned int val; - - dev_dbg(ccdc_cfg.dev, "\nStarting ccdc_config_raw..."); - - /* Reset CCDC */ - ccdc_restore_defaults(); - - /* Disable latching function registers on VSYNC */ - regw(CCDC_LATCH_ON_VSYNC_DISABLE, CCDC_CCDCFG); - - /* - * Configure the vertical sync polarity(SYN_MODE.VDPOL), - * horizontal sync polarity (SYN_MODE.HDPOL), frame id polarity - * (SYN_MODE.FLDPOL), frame format(progressive or interlace), - * data size(SYNMODE.DATSIZ), &pixel format (Input mode), output - * SDRAM, enable internal timing generator - */ - syn_mode = - (((params->vd_pol & CCDC_VD_POL_MASK) << CCDC_VD_POL_SHIFT) | - ((params->hd_pol & CCDC_HD_POL_MASK) << CCDC_HD_POL_SHIFT) | - ((params->fid_pol & CCDC_FID_POL_MASK) << CCDC_FID_POL_SHIFT) | - ((params->frm_fmt & CCDC_FRM_FMT_MASK) << CCDC_FRM_FMT_SHIFT) | - ((config_params->data_sz & CCDC_DATA_SZ_MASK) << - CCDC_DATA_SZ_SHIFT) | - ((params->pix_fmt & CCDC_PIX_FMT_MASK) << CCDC_PIX_FMT_SHIFT) | - CCDC_WEN_ENABLE | CCDC_VDHDEN_ENABLE); - - /* Enable and configure aLaw register if needed */ - if (config_params->alaw.enable) { - val = ((config_params->alaw.gama_wd & - CCDC_ALAW_GAMA_WD_MASK) | CCDC_ALAW_ENABLE); - regw(val, CCDC_ALAW); - dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to ALAW...\n", val); - } - - /* Configure video window */ - ccdc_setwin(¶ms->win, params->frm_fmt, CCDC_PPC_RAW); - - /* Configure Black Clamp */ - ccdc_config_black_clamp(&config_params->blk_clamp); - - /* Configure Black level compensation */ - ccdc_config_black_compense(&config_params->blk_comp); - - /* Configure Fault Pixel Correction */ - ccdc_config_fpc(&config_params->fault_pxl); - - /* If data size is 8 bit then pack the data */ - if ((config_params->data_sz == CCDC_DATA_8BITS) || - config_params->alaw.enable) - syn_mode |= CCDC_DATA_PACK_ENABLE; - -#ifdef CONFIG_DM644X_VIDEO_PORT_ENABLE - /* enable video port */ - val = CCDC_ENABLE_VIDEO_PORT; -#else - /* disable video port */ - val = CCDC_DISABLE_VIDEO_PORT; -#endif - - if (config_params->data_sz == CCDC_DATA_8BITS) - val |= (CCDC_DATA_10BITS & CCDC_FMTCFG_VPIN_MASK) - << CCDC_FMTCFG_VPIN_SHIFT; - else - val |= (config_params->data_sz & CCDC_FMTCFG_VPIN_MASK) - << CCDC_FMTCFG_VPIN_SHIFT; - /* Write value in FMTCFG */ - regw(val, CCDC_FMTCFG); - - dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to FMTCFG...\n", val); - /* Configure the color pattern according to mt9t001 sensor */ - regw(CCDC_COLPTN_VAL, CCDC_COLPTN); - - dev_dbg(ccdc_cfg.dev, "\nWriting 0xBB11BB11 to COLPTN...\n"); - /* - * Configure Data formatter(Video port) pixel selection - * (FMT_HORZ, FMT_VERT) - */ - val = ((params->win.left & CCDC_FMT_HORZ_FMTSPH_MASK) << - CCDC_FMT_HORZ_FMTSPH_SHIFT) | - (params->win.width & CCDC_FMT_HORZ_FMTLNH_MASK); - regw(val, CCDC_FMT_HORZ); - - dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to FMT_HORZ...\n", val); - val = (params->win.top & CCDC_FMT_VERT_FMTSLV_MASK) - << CCDC_FMT_VERT_FMTSLV_SHIFT; - if (params->frm_fmt == CCDC_FRMFMT_PROGRESSIVE) - val |= (params->win.height) & CCDC_FMT_VERT_FMTLNV_MASK; - else - val |= (params->win.height >> 1) & CCDC_FMT_VERT_FMTLNV_MASK; - - dev_dbg(ccdc_cfg.dev, "\nparams->win.height 0x%x ...\n", - params->win.height); - regw(val, CCDC_FMT_VERT); - - dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to FMT_VERT...\n", val); - - dev_dbg(ccdc_cfg.dev, "\nbelow regw(val, FMT_VERT)..."); - - /* - * Configure Horizontal offset register. If pack 8 is enabled then - * 1 pixel will take 1 byte - */ - if ((config_params->data_sz == CCDC_DATA_8BITS) || - config_params->alaw.enable) - regw((params->win.width + CCDC_32BYTE_ALIGN_VAL) & - CCDC_HSIZE_OFF_MASK, CCDC_HSIZE_OFF); - else - /* else one pixel will take 2 byte */ - regw(((params->win.width * CCDC_TWO_BYTES_PER_PIXEL) + - CCDC_32BYTE_ALIGN_VAL) & CCDC_HSIZE_OFF_MASK, - CCDC_HSIZE_OFF); - - /* Set value for SDOFST */ - if (params->frm_fmt == CCDC_FRMFMT_INTERLACED) { - if (params->image_invert_enable) { - /* For intelace inverse mode */ - regw(CCDC_INTERLACED_IMAGE_INVERT, CCDC_SDOFST); - dev_dbg(ccdc_cfg.dev, "\nWriting 0x4B6D to SDOFST..\n"); - } - - else { - /* For intelace non inverse mode */ - regw(CCDC_INTERLACED_NO_IMAGE_INVERT, CCDC_SDOFST); - dev_dbg(ccdc_cfg.dev, "\nWriting 0x0249 to SDOFST..\n"); - } - } else if (params->frm_fmt == CCDC_FRMFMT_PROGRESSIVE) { - regw(CCDC_PROGRESSIVE_NO_IMAGE_INVERT, CCDC_SDOFST); - dev_dbg(ccdc_cfg.dev, "\nWriting 0x0000 to SDOFST...\n"); - } - - /* - * Configure video port pixel selection (VPOUT) - * Here -1 is to make the height value less than FMT_VERT.FMTLNV - */ - if (params->frm_fmt == CCDC_FRMFMT_PROGRESSIVE) - val = (((params->win.height - 1) & CCDC_VP_OUT_VERT_NUM_MASK)) - << CCDC_VP_OUT_VERT_NUM_SHIFT; - else - val = - ((((params->win.height >> CCDC_INTERLACED_HEIGHT_SHIFT) - - 1) & CCDC_VP_OUT_VERT_NUM_MASK)) << - CCDC_VP_OUT_VERT_NUM_SHIFT; - - val |= ((((params->win.width))) & CCDC_VP_OUT_HORZ_NUM_MASK) - << CCDC_VP_OUT_HORZ_NUM_SHIFT; - val |= (params->win.left) & CCDC_VP_OUT_HORZ_ST_MASK; - regw(val, CCDC_VP_OUT); - - dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to VP_OUT...\n", val); - regw(syn_mode, CCDC_SYN_MODE); - dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to SYN_MODE...\n", syn_mode); - - ccdc_sbl_reset(); - dev_dbg(ccdc_cfg.dev, "\nend of ccdc_config_raw..."); - ccdc_readregs(); -} - -static int ccdc_configure(void) -{ - if (ccdc_cfg.if_type == VPFE_RAW_BAYER) - ccdc_config_raw(); - else - ccdc_config_ycbcr(); - return 0; -} - -static int ccdc_set_buftype(enum ccdc_buftype buf_type) -{ - if (ccdc_cfg.if_type == VPFE_RAW_BAYER) - ccdc_cfg.bayer.buf_type = buf_type; - else - ccdc_cfg.ycbcr.buf_type = buf_type; - return 0; -} - -static enum ccdc_buftype ccdc_get_buftype(void) -{ - if (ccdc_cfg.if_type == VPFE_RAW_BAYER) - return ccdc_cfg.bayer.buf_type; - return ccdc_cfg.ycbcr.buf_type; -} - -static int ccdc_enum_pix(u32 *pix, int i) -{ - int ret = -EINVAL; - if (ccdc_cfg.if_type == VPFE_RAW_BAYER) { - if (i < ARRAY_SIZE(ccdc_raw_bayer_pix_formats)) { - *pix = ccdc_raw_bayer_pix_formats[i]; - ret = 0; - } - } else { - if (i < ARRAY_SIZE(ccdc_raw_yuv_pix_formats)) { - *pix = ccdc_raw_yuv_pix_formats[i]; - ret = 0; - } - } - return ret; -} - -static int ccdc_set_pixel_format(u32 pixfmt) -{ - if (ccdc_cfg.if_type == VPFE_RAW_BAYER) { - ccdc_cfg.bayer.pix_fmt = CCDC_PIXFMT_RAW; - if (pixfmt == V4L2_PIX_FMT_SBGGR8) - ccdc_cfg.bayer.config_params.alaw.enable = 1; - else if (pixfmt != V4L2_PIX_FMT_SBGGR16) - return -EINVAL; - } else { - if (pixfmt == V4L2_PIX_FMT_YUYV) - ccdc_cfg.ycbcr.pix_order = CCDC_PIXORDER_YCBYCR; - else if (pixfmt == V4L2_PIX_FMT_UYVY) - ccdc_cfg.ycbcr.pix_order = CCDC_PIXORDER_CBYCRY; - else - return -EINVAL; - } - return 0; -} - -static u32 ccdc_get_pixel_format(void) -{ - struct ccdc_a_law *alaw = &ccdc_cfg.bayer.config_params.alaw; - u32 pixfmt; - - if (ccdc_cfg.if_type == VPFE_RAW_BAYER) - if (alaw->enable) - pixfmt = V4L2_PIX_FMT_SBGGR8; - else - pixfmt = V4L2_PIX_FMT_SBGGR16; - else { - if (ccdc_cfg.ycbcr.pix_order == CCDC_PIXORDER_YCBYCR) - pixfmt = V4L2_PIX_FMT_YUYV; - else - pixfmt = V4L2_PIX_FMT_UYVY; - } - return pixfmt; -} - -static int ccdc_set_image_window(struct v4l2_rect *win) -{ - if (ccdc_cfg.if_type == VPFE_RAW_BAYER) - ccdc_cfg.bayer.win = *win; - else - ccdc_cfg.ycbcr.win = *win; - return 0; -} - -static void ccdc_get_image_window(struct v4l2_rect *win) -{ - if (ccdc_cfg.if_type == VPFE_RAW_BAYER) - *win = ccdc_cfg.bayer.win; - else - *win = ccdc_cfg.ycbcr.win; -} - -static unsigned int ccdc_get_line_length(void) -{ - struct ccdc_config_params_raw *config_params = - &ccdc_cfg.bayer.config_params; - unsigned int len; - - if (ccdc_cfg.if_type == VPFE_RAW_BAYER) { - if ((config_params->alaw.enable) || - (config_params->data_sz == CCDC_DATA_8BITS)) - len = ccdc_cfg.bayer.win.width; - else - len = ccdc_cfg.bayer.win.width * 2; - } else - len = ccdc_cfg.ycbcr.win.width * 2; - return ALIGN(len, 32); -} - -static int ccdc_set_frame_format(enum ccdc_frmfmt frm_fmt) -{ - if (ccdc_cfg.if_type == VPFE_RAW_BAYER) - ccdc_cfg.bayer.frm_fmt = frm_fmt; - else - ccdc_cfg.ycbcr.frm_fmt = frm_fmt; - return 0; -} - -static enum ccdc_frmfmt ccdc_get_frame_format(void) -{ - if (ccdc_cfg.if_type == VPFE_RAW_BAYER) - return ccdc_cfg.bayer.frm_fmt; - else - return ccdc_cfg.ycbcr.frm_fmt; -} - -static int ccdc_getfid(void) -{ - return (regr(CCDC_SYN_MODE) >> 15) & 1; -} - -/* misc operations */ -static inline void ccdc_setfbaddr(unsigned long addr) -{ - regw(addr & 0xffffffe0, CCDC_SDR_ADDR); -} - -static int ccdc_set_hw_if_params(struct vpfe_hw_if_param *params) -{ - ccdc_cfg.if_type = params->if_type; - - switch (params->if_type) { - case VPFE_BT656: - case VPFE_YCBCR_SYNC_16: - case VPFE_YCBCR_SYNC_8: - case VPFE_BT656_10BIT: - ccdc_cfg.ycbcr.vd_pol = params->vdpol; - ccdc_cfg.ycbcr.hd_pol = params->hdpol; - break; - default: - /* TODO add support for raw bayer here */ - return -EINVAL; - } - return 0; -} - -static void ccdc_save_context(void) -{ - ccdc_ctx[CCDC_PCR >> 2] = regr(CCDC_PCR); - ccdc_ctx[CCDC_SYN_MODE >> 2] = regr(CCDC_SYN_MODE); - ccdc_ctx[CCDC_HD_VD_WID >> 2] = regr(CCDC_HD_VD_WID); - ccdc_ctx[CCDC_PIX_LINES >> 2] = regr(CCDC_PIX_LINES); - ccdc_ctx[CCDC_HORZ_INFO >> 2] = regr(CCDC_HORZ_INFO); - ccdc_ctx[CCDC_VERT_START >> 2] = regr(CCDC_VERT_START); - ccdc_ctx[CCDC_VERT_LINES >> 2] = regr(CCDC_VERT_LINES); - ccdc_ctx[CCDC_CULLING >> 2] = regr(CCDC_CULLING); - ccdc_ctx[CCDC_HSIZE_OFF >> 2] = regr(CCDC_HSIZE_OFF); - ccdc_ctx[CCDC_SDOFST >> 2] = regr(CCDC_SDOFST); - ccdc_ctx[CCDC_SDR_ADDR >> 2] = regr(CCDC_SDR_ADDR); - ccdc_ctx[CCDC_CLAMP >> 2] = regr(CCDC_CLAMP); - ccdc_ctx[CCDC_DCSUB >> 2] = regr(CCDC_DCSUB); - ccdc_ctx[CCDC_COLPTN >> 2] = regr(CCDC_COLPTN); - ccdc_ctx[CCDC_BLKCMP >> 2] = regr(CCDC_BLKCMP); - ccdc_ctx[CCDC_FPC >> 2] = regr(CCDC_FPC); - ccdc_ctx[CCDC_FPC_ADDR >> 2] = regr(CCDC_FPC_ADDR); - ccdc_ctx[CCDC_VDINT >> 2] = regr(CCDC_VDINT); - ccdc_ctx[CCDC_ALAW >> 2] = regr(CCDC_ALAW); - ccdc_ctx[CCDC_REC656IF >> 2] = regr(CCDC_REC656IF); - ccdc_ctx[CCDC_CCDCFG >> 2] = regr(CCDC_CCDCFG); - ccdc_ctx[CCDC_FMTCFG >> 2] = regr(CCDC_FMTCFG); - ccdc_ctx[CCDC_FMT_HORZ >> 2] = regr(CCDC_FMT_HORZ); - ccdc_ctx[CCDC_FMT_VERT >> 2] = regr(CCDC_FMT_VERT); - ccdc_ctx[CCDC_FMT_ADDR0 >> 2] = regr(CCDC_FMT_ADDR0); - ccdc_ctx[CCDC_FMT_ADDR1 >> 2] = regr(CCDC_FMT_ADDR1); - ccdc_ctx[CCDC_FMT_ADDR2 >> 2] = regr(CCDC_FMT_ADDR2); - ccdc_ctx[CCDC_FMT_ADDR3 >> 2] = regr(CCDC_FMT_ADDR3); - ccdc_ctx[CCDC_FMT_ADDR4 >> 2] = regr(CCDC_FMT_ADDR4); - ccdc_ctx[CCDC_FMT_ADDR5 >> 2] = regr(CCDC_FMT_ADDR5); - ccdc_ctx[CCDC_FMT_ADDR6 >> 2] = regr(CCDC_FMT_ADDR6); - ccdc_ctx[CCDC_FMT_ADDR7 >> 2] = regr(CCDC_FMT_ADDR7); - ccdc_ctx[CCDC_PRGEVEN_0 >> 2] = regr(CCDC_PRGEVEN_0); - ccdc_ctx[CCDC_PRGEVEN_1 >> 2] = regr(CCDC_PRGEVEN_1); - ccdc_ctx[CCDC_PRGODD_0 >> 2] = regr(CCDC_PRGODD_0); - ccdc_ctx[CCDC_PRGODD_1 >> 2] = regr(CCDC_PRGODD_1); - ccdc_ctx[CCDC_VP_OUT >> 2] = regr(CCDC_VP_OUT); -} - -static void ccdc_restore_context(void) -{ - regw(ccdc_ctx[CCDC_SYN_MODE >> 2], CCDC_SYN_MODE); - regw(ccdc_ctx[CCDC_HD_VD_WID >> 2], CCDC_HD_VD_WID); - regw(ccdc_ctx[CCDC_PIX_LINES >> 2], CCDC_PIX_LINES); - regw(ccdc_ctx[CCDC_HORZ_INFO >> 2], CCDC_HORZ_INFO); - regw(ccdc_ctx[CCDC_VERT_START >> 2], CCDC_VERT_START); - regw(ccdc_ctx[CCDC_VERT_LINES >> 2], CCDC_VERT_LINES); - regw(ccdc_ctx[CCDC_CULLING >> 2], CCDC_CULLING); - regw(ccdc_ctx[CCDC_HSIZE_OFF >> 2], CCDC_HSIZE_OFF); - regw(ccdc_ctx[CCDC_SDOFST >> 2], CCDC_SDOFST); - regw(ccdc_ctx[CCDC_SDR_ADDR >> 2], CCDC_SDR_ADDR); - regw(ccdc_ctx[CCDC_CLAMP >> 2], CCDC_CLAMP); - regw(ccdc_ctx[CCDC_DCSUB >> 2], CCDC_DCSUB); - regw(ccdc_ctx[CCDC_COLPTN >> 2], CCDC_COLPTN); - regw(ccdc_ctx[CCDC_BLKCMP >> 2], CCDC_BLKCMP); - regw(ccdc_ctx[CCDC_FPC >> 2], CCDC_FPC); - regw(ccdc_ctx[CCDC_FPC_ADDR >> 2], CCDC_FPC_ADDR); - regw(ccdc_ctx[CCDC_VDINT >> 2], CCDC_VDINT); - regw(ccdc_ctx[CCDC_ALAW >> 2], CCDC_ALAW); - regw(ccdc_ctx[CCDC_REC656IF >> 2], CCDC_REC656IF); - regw(ccdc_ctx[CCDC_CCDCFG >> 2], CCDC_CCDCFG); - regw(ccdc_ctx[CCDC_FMTCFG >> 2], CCDC_FMTCFG); - regw(ccdc_ctx[CCDC_FMT_HORZ >> 2], CCDC_FMT_HORZ); - regw(ccdc_ctx[CCDC_FMT_VERT >> 2], CCDC_FMT_VERT); - regw(ccdc_ctx[CCDC_FMT_ADDR0 >> 2], CCDC_FMT_ADDR0); - regw(ccdc_ctx[CCDC_FMT_ADDR1 >> 2], CCDC_FMT_ADDR1); - regw(ccdc_ctx[CCDC_FMT_ADDR2 >> 2], CCDC_FMT_ADDR2); - regw(ccdc_ctx[CCDC_FMT_ADDR3 >> 2], CCDC_FMT_ADDR3); - regw(ccdc_ctx[CCDC_FMT_ADDR4 >> 2], CCDC_FMT_ADDR4); - regw(ccdc_ctx[CCDC_FMT_ADDR5 >> 2], CCDC_FMT_ADDR5); - regw(ccdc_ctx[CCDC_FMT_ADDR6 >> 2], CCDC_FMT_ADDR6); - regw(ccdc_ctx[CCDC_FMT_ADDR7 >> 2], CCDC_FMT_ADDR7); - regw(ccdc_ctx[CCDC_PRGEVEN_0 >> 2], CCDC_PRGEVEN_0); - regw(ccdc_ctx[CCDC_PRGEVEN_1 >> 2], CCDC_PRGEVEN_1); - regw(ccdc_ctx[CCDC_PRGODD_0 >> 2], CCDC_PRGODD_0); - regw(ccdc_ctx[CCDC_PRGODD_1 >> 2], CCDC_PRGODD_1); - regw(ccdc_ctx[CCDC_VP_OUT >> 2], CCDC_VP_OUT); - regw(ccdc_ctx[CCDC_PCR >> 2], CCDC_PCR); -} -static struct ccdc_hw_device ccdc_hw_dev = { - .name = "DM6446 CCDC", - .owner = THIS_MODULE, - .hw_ops = { - .open = ccdc_open, - .close = ccdc_close, - .reset = ccdc_sbl_reset, - .enable = ccdc_enable, - .set_hw_if_params = ccdc_set_hw_if_params, - .set_params = ccdc_set_params, - .configure = ccdc_configure, - .set_buftype = ccdc_set_buftype, - .get_buftype = ccdc_get_buftype, - .enum_pix = ccdc_enum_pix, - .set_pixel_format = ccdc_set_pixel_format, - .get_pixel_format = ccdc_get_pixel_format, - .set_frame_format = ccdc_set_frame_format, - .get_frame_format = ccdc_get_frame_format, - .set_image_window = ccdc_set_image_window, - .get_image_window = ccdc_get_image_window, - .get_line_length = ccdc_get_line_length, - .setfbaddr = ccdc_setfbaddr, - .getfid = ccdc_getfid, - }, -}; - -static int __init dm644x_ccdc_probe(struct platform_device *pdev) -{ - struct resource *res; - int status = 0; - - /* - * first try to register with vpfe. If not correct platform, then we - * don't have to iomap - */ - status = vpfe_register_ccdc_device(&ccdc_hw_dev); - if (status < 0) - return status; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - status = -ENODEV; - goto fail_nores; - } - - res = request_mem_region(res->start, resource_size(res), res->name); - if (!res) { - status = -EBUSY; - goto fail_nores; - } - - ccdc_cfg.base_addr = ioremap_nocache(res->start, resource_size(res)); - if (!ccdc_cfg.base_addr) { - status = -ENOMEM; - goto fail_nomem; - } - - /* Get and enable Master clock */ - ccdc_cfg.mclk = clk_get(&pdev->dev, "master"); - if (IS_ERR(ccdc_cfg.mclk)) { - status = PTR_ERR(ccdc_cfg.mclk); - goto fail_nomap; - } - if (clk_enable(ccdc_cfg.mclk)) { - status = -ENODEV; - goto fail_mclk; - } - - /* Get and enable Slave clock */ - ccdc_cfg.sclk = clk_get(&pdev->dev, "slave"); - if (IS_ERR(ccdc_cfg.sclk)) { - status = PTR_ERR(ccdc_cfg.sclk); - goto fail_mclk; - } - if (clk_enable(ccdc_cfg.sclk)) { - status = -ENODEV; - goto fail_sclk; - } - ccdc_cfg.dev = &pdev->dev; - printk(KERN_NOTICE "%s is registered with vpfe.\n", ccdc_hw_dev.name); - return 0; -fail_sclk: - clk_put(ccdc_cfg.sclk); -fail_mclk: - clk_put(ccdc_cfg.mclk); -fail_nomap: - iounmap(ccdc_cfg.base_addr); -fail_nomem: - release_mem_region(res->start, resource_size(res)); -fail_nores: - vpfe_unregister_ccdc_device(&ccdc_hw_dev); - return status; -} - -static int dm644x_ccdc_remove(struct platform_device *pdev) -{ - struct resource *res; - - clk_put(ccdc_cfg.mclk); - clk_put(ccdc_cfg.sclk); - iounmap(ccdc_cfg.base_addr); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (res) - release_mem_region(res->start, resource_size(res)); - vpfe_unregister_ccdc_device(&ccdc_hw_dev); - return 0; -} - -static int dm644x_ccdc_suspend(struct device *dev) -{ - /* Save CCDC context */ - ccdc_save_context(); - /* Disable CCDC */ - ccdc_enable(0); - /* Disable both master and slave clock */ - clk_disable(ccdc_cfg.mclk); - clk_disable(ccdc_cfg.sclk); - - return 0; -} - -static int dm644x_ccdc_resume(struct device *dev) -{ - /* Enable both master and slave clock */ - clk_enable(ccdc_cfg.mclk); - clk_enable(ccdc_cfg.sclk); - /* Restore CCDC context */ - ccdc_restore_context(); - - return 0; -} - -static const struct dev_pm_ops dm644x_ccdc_pm_ops = { - .suspend = dm644x_ccdc_suspend, - .resume = dm644x_ccdc_resume, -}; - -static struct platform_driver dm644x_ccdc_driver = { - .driver = { - .name = "dm644x_ccdc", - .owner = THIS_MODULE, - .pm = &dm644x_ccdc_pm_ops, - }, - .remove = __devexit_p(dm644x_ccdc_remove), - .probe = dm644x_ccdc_probe, -}; - -static int __init dm644x_ccdc_init(void) -{ - return platform_driver_register(&dm644x_ccdc_driver); -} - -static void __exit dm644x_ccdc_exit(void) -{ - platform_driver_unregister(&dm644x_ccdc_driver); -} - -module_init(dm644x_ccdc_init); -module_exit(dm644x_ccdc_exit); diff --git a/drivers/media/video/davinci/dm644x_ccdc_regs.h b/drivers/media/video/davinci/dm644x_ccdc_regs.h deleted file mode 100644 index 90370e414e2..00000000000 --- a/drivers/media/video/davinci/dm644x_ccdc_regs.h +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright (C) 2006-2009 Texas Instruments Inc - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#ifndef _DM644X_CCDC_REGS_H -#define _DM644X_CCDC_REGS_H - -/**************************************************************************\ -* Register OFFSET Definitions -\**************************************************************************/ -#define CCDC_PID 0x0 -#define CCDC_PCR 0x4 -#define CCDC_SYN_MODE 0x8 -#define CCDC_HD_VD_WID 0xc -#define CCDC_PIX_LINES 0x10 -#define CCDC_HORZ_INFO 0x14 -#define CCDC_VERT_START 0x18 -#define CCDC_VERT_LINES 0x1c -#define CCDC_CULLING 0x20 -#define CCDC_HSIZE_OFF 0x24 -#define CCDC_SDOFST 0x28 -#define CCDC_SDR_ADDR 0x2c -#define CCDC_CLAMP 0x30 -#define CCDC_DCSUB 0x34 -#define CCDC_COLPTN 0x38 -#define CCDC_BLKCMP 0x3c -#define CCDC_FPC 0x40 -#define CCDC_FPC_ADDR 0x44 -#define CCDC_VDINT 0x48 -#define CCDC_ALAW 0x4c -#define CCDC_REC656IF 0x50 -#define CCDC_CCDCFG 0x54 -#define CCDC_FMTCFG 0x58 -#define CCDC_FMT_HORZ 0x5c -#define CCDC_FMT_VERT 0x60 -#define CCDC_FMT_ADDR0 0x64 -#define CCDC_FMT_ADDR1 0x68 -#define CCDC_FMT_ADDR2 0x6c -#define CCDC_FMT_ADDR3 0x70 -#define CCDC_FMT_ADDR4 0x74 -#define CCDC_FMT_ADDR5 0x78 -#define CCDC_FMT_ADDR6 0x7c -#define CCDC_FMT_ADDR7 0x80 -#define CCDC_PRGEVEN_0 0x84 -#define CCDC_PRGEVEN_1 0x88 -#define CCDC_PRGODD_0 0x8c -#define CCDC_PRGODD_1 0x90 -#define CCDC_VP_OUT 0x94 -#define CCDC_REG_END 0x98 - -/*************************************************************** -* Define for various register bit mask and shifts for CCDC -****************************************************************/ -#define CCDC_FID_POL_MASK 1 -#define CCDC_FID_POL_SHIFT 4 -#define CCDC_HD_POL_MASK 1 -#define CCDC_HD_POL_SHIFT 3 -#define CCDC_VD_POL_MASK 1 -#define CCDC_VD_POL_SHIFT 2 -#define CCDC_HSIZE_OFF_MASK 0xffffffe0 -#define CCDC_32BYTE_ALIGN_VAL 31 -#define CCDC_FRM_FMT_MASK 0x1 -#define CCDC_FRM_FMT_SHIFT 7 -#define CCDC_DATA_SZ_MASK 7 -#define CCDC_DATA_SZ_SHIFT 8 -#define CCDC_PIX_FMT_MASK 3 -#define CCDC_PIX_FMT_SHIFT 12 -#define CCDC_VP2SDR_DISABLE 0xFFFBFFFF -#define CCDC_WEN_ENABLE (1 << 17) -#define CCDC_SDR2RSZ_DISABLE 0xFFF7FFFF -#define CCDC_VDHDEN_ENABLE (1 << 16) -#define CCDC_LPF_ENABLE (1 << 14) -#define CCDC_ALAW_ENABLE (1 << 3) -#define CCDC_ALAW_GAMA_WD_MASK 7 -#define CCDC_BLK_CLAMP_ENABLE (1 << 31) -#define CCDC_BLK_SGAIN_MASK 0x1F -#define CCDC_BLK_ST_PXL_MASK 0x7FFF -#define CCDC_BLK_ST_PXL_SHIFT 10 -#define CCDC_BLK_SAMPLE_LN_MASK 7 -#define CCDC_BLK_SAMPLE_LN_SHIFT 28 -#define CCDC_BLK_SAMPLE_LINE_MASK 7 -#define CCDC_BLK_SAMPLE_LINE_SHIFT 25 -#define CCDC_BLK_DC_SUB_MASK 0x03FFF -#define CCDC_BLK_COMP_MASK 0xFF -#define CCDC_BLK_COMP_GB_COMP_SHIFT 8 -#define CCDC_BLK_COMP_GR_COMP_SHIFT 16 -#define CCDC_BLK_COMP_R_COMP_SHIFT 24 -#define CCDC_LATCH_ON_VSYNC_DISABLE (1 << 15) -#define CCDC_FPC_ENABLE (1 << 15) -#define CCDC_FPC_DISABLE 0 -#define CCDC_FPC_FPC_NUM_MASK 0x7FFF -#define CCDC_DATA_PACK_ENABLE (1 << 11) -#define CCDC_FMTCFG_VPIN_MASK 7 -#define CCDC_FMTCFG_VPIN_SHIFT 12 -#define CCDC_FMT_HORZ_FMTLNH_MASK 0x1FFF -#define CCDC_FMT_HORZ_FMTSPH_MASK 0x1FFF -#define CCDC_FMT_HORZ_FMTSPH_SHIFT 16 -#define CCDC_FMT_VERT_FMTLNV_MASK 0x1FFF -#define CCDC_FMT_VERT_FMTSLV_MASK 0x1FFF -#define CCDC_FMT_VERT_FMTSLV_SHIFT 16 -#define CCDC_VP_OUT_VERT_NUM_MASK 0x3FFF -#define CCDC_VP_OUT_VERT_NUM_SHIFT 17 -#define CCDC_VP_OUT_HORZ_NUM_MASK 0x1FFF -#define CCDC_VP_OUT_HORZ_NUM_SHIFT 4 -#define CCDC_VP_OUT_HORZ_ST_MASK 0xF -#define CCDC_HORZ_INFO_SPH_SHIFT 16 -#define CCDC_VERT_START_SLV0_SHIFT 16 -#define CCDC_VDINT_VDINT0_SHIFT 16 -#define CCDC_VDINT_VDINT1_MASK 0xFFFF -#define CCDC_PPC_RAW 1 -#define CCDC_DCSUB_DEFAULT_VAL 0 -#define CCDC_CLAMP_DEFAULT_VAL 0 -#define CCDC_ENABLE_VIDEO_PORT 0x8000 -#define CCDC_DISABLE_VIDEO_PORT 0 -#define CCDC_COLPTN_VAL 0xBB11BB11 -#define CCDC_TWO_BYTES_PER_PIXEL 2 -#define CCDC_INTERLACED_IMAGE_INVERT 0x4B6D -#define CCDC_INTERLACED_NO_IMAGE_INVERT 0x0249 -#define CCDC_PROGRESSIVE_IMAGE_INVERT 0x4000 -#define CCDC_PROGRESSIVE_NO_IMAGE_INVERT 0 -#define CCDC_INTERLACED_HEIGHT_SHIFT 1 -#define CCDC_SYN_MODE_INPMOD_SHIFT 12 -#define CCDC_SYN_MODE_INPMOD_MASK 3 -#define CCDC_SYN_MODE_8BITS (7 << 8) -#define CCDC_SYN_MODE_10BITS (6 << 8) -#define CCDC_SYN_MODE_11BITS (5 << 8) -#define CCDC_SYN_MODE_12BITS (4 << 8) -#define CCDC_SYN_MODE_13BITS (3 << 8) -#define CCDC_SYN_MODE_14BITS (2 << 8) -#define CCDC_SYN_MODE_15BITS (1 << 8) -#define CCDC_SYN_MODE_16BITS (0 << 8) -#define CCDC_SYN_FLDMODE_MASK 1 -#define CCDC_SYN_FLDMODE_SHIFT 7 -#define CCDC_REC656IF_BT656_EN 3 -#define CCDC_SYN_MODE_VD_POL_NEGATIVE (1 << 2) -#define CCDC_CCDCFG_Y8POS_SHIFT 11 -#define CCDC_CCDCFG_BW656_10BIT (1 << 5) -#define CCDC_SDOFST_FIELD_INTERLEAVED 0x249 -#define CCDC_NO_CULLING 0xffff00ff -#endif diff --git a/drivers/media/video/davinci/isif.c b/drivers/media/video/davinci/isif.c deleted file mode 100644 index 29c29c66859..00000000000 --- a/drivers/media/video/davinci/isif.c +++ /dev/null @@ -1,1172 +0,0 @@ -/* - * Copyright (C) 2008-2009 Texas Instruments Inc - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Image Sensor Interface (ISIF) driver - * - * This driver is for configuring the ISIF IP available on DM365 or any other - * TI SoCs. This is used for capturing yuv or bayer video or image data - * from a decoder or sensor. This IP is similar to the CCDC IP on DM355 - * and DM6446, but with enhanced or additional ip blocks. The driver - * configures the ISIF upon commands from the vpfe bridge driver through - * ccdc_hw_device interface. - * - * TODO: 1) Raw bayer parameter settings and bayer capture - * 2) Add support for control ioctl - */ -#include <linux/delay.h> -#include <linux/platform_device.h> -#include <linux/uaccess.h> -#include <linux/io.h> -#include <linux/videodev2.h> -#include <linux/clk.h> -#include <linux/err.h> - -#include <mach/mux.h> - -#include <media/davinci/isif.h> -#include <media/davinci/vpss.h> - -#include "isif_regs.h" -#include "ccdc_hw_device.h" - -/* Defaults for module configuration parameters */ -static struct isif_config_params_raw isif_config_defaults = { - .linearize = { - .en = 0, - .corr_shft = ISIF_NO_SHIFT, - .scale_fact = {1, 0}, - }, - .df_csc = { - .df_or_csc = 0, - .csc = { - .en = 0, - }, - }, - .dfc = { - .en = 0, - }, - .bclamp = { - .en = 0, - }, - .gain_offset = { - .gain = { - .r_ye = {1, 0}, - .gr_cy = {1, 0}, - .gb_g = {1, 0}, - .b_mg = {1, 0}, - }, - }, - .culling = { - .hcpat_odd = 0xff, - .hcpat_even = 0xff, - .vcpat = 0xff, - }, - .compress = { - .alg = ISIF_ALAW, - }, -}; - -/* ISIF operation configuration */ -static struct isif_oper_config { - struct device *dev; - enum vpfe_hw_if_type if_type; - struct isif_ycbcr_config ycbcr; - struct isif_params_raw bayer; - enum isif_data_pack data_pack; - /* Master clock */ - struct clk *mclk; - /* ISIF base address */ - void __iomem *base_addr; - /* ISIF Linear Table 0 */ - void __iomem *linear_tbl0_addr; - /* ISIF Linear Table 1 */ - void __iomem *linear_tbl1_addr; -} isif_cfg = { - .ycbcr = { - .pix_fmt = CCDC_PIXFMT_YCBCR_8BIT, - .frm_fmt = CCDC_FRMFMT_INTERLACED, - .win = ISIF_WIN_NTSC, - .fid_pol = VPFE_PINPOL_POSITIVE, - .vd_pol = VPFE_PINPOL_POSITIVE, - .hd_pol = VPFE_PINPOL_POSITIVE, - .pix_order = CCDC_PIXORDER_CBYCRY, - .buf_type = CCDC_BUFTYPE_FLD_INTERLEAVED, - }, - .bayer = { - .pix_fmt = CCDC_PIXFMT_RAW, - .frm_fmt = CCDC_FRMFMT_PROGRESSIVE, - .win = ISIF_WIN_VGA, - .fid_pol = VPFE_PINPOL_POSITIVE, - .vd_pol = VPFE_PINPOL_POSITIVE, - .hd_pol = VPFE_PINPOL_POSITIVE, - .gain = { - .r_ye = {1, 0}, - .gr_cy = {1, 0}, - .gb_g = {1, 0}, - .b_mg = {1, 0}, - }, - .cfa_pat = ISIF_CFA_PAT_MOSAIC, - .data_msb = ISIF_BIT_MSB_11, - .config_params = { - .data_shift = ISIF_NO_SHIFT, - .col_pat_field0 = { - .olop = ISIF_GREEN_BLUE, - .olep = ISIF_BLUE, - .elop = ISIF_RED, - .elep = ISIF_GREEN_RED, - }, - .col_pat_field1 = { - .olop = ISIF_GREEN_BLUE, - .olep = ISIF_BLUE, - .elop = ISIF_RED, - .elep = ISIF_GREEN_RED, - }, - .test_pat_gen = 0, - }, - }, - .data_pack = ISIF_DATA_PACK8, -}; - -/* Raw Bayer formats */ -static const u32 isif_raw_bayer_pix_formats[] = { - V4L2_PIX_FMT_SBGGR8, V4L2_PIX_FMT_SBGGR16}; - -/* Raw YUV formats */ -static const u32 isif_raw_yuv_pix_formats[] = { - V4L2_PIX_FMT_UYVY, V4L2_PIX_FMT_YUYV}; - -/* register access routines */ -static inline u32 regr(u32 offset) -{ - return __raw_readl(isif_cfg.base_addr + offset); -} - -static inline void regw(u32 val, u32 offset) -{ - __raw_writel(val, isif_cfg.base_addr + offset); -} - -/* reg_modify() - read, modify and write register */ -static inline u32 reg_modify(u32 mask, u32 val, u32 offset) -{ - u32 new_val = (regr(offset) & ~mask) | (val & mask); - - regw(new_val, offset); - return new_val; -} - -static inline void regw_lin_tbl(u32 val, u32 offset, int i) -{ - if (!i) - __raw_writel(val, isif_cfg.linear_tbl0_addr + offset); - else - __raw_writel(val, isif_cfg.linear_tbl1_addr + offset); -} - -static void isif_disable_all_modules(void) -{ - /* disable BC */ - regw(0, CLAMPCFG); - /* disable vdfc */ - regw(0, DFCCTL); - /* disable CSC */ - regw(0, CSCCTL); - /* disable linearization */ - regw(0, LINCFG0); - /* disable other modules here as they are supported */ -} - -static void isif_enable(int en) -{ - if (!en) { - /* Before disable isif, disable all ISIF modules */ - isif_disable_all_modules(); - /* - * wait for next VD. Assume lowest scan rate is 12 Hz. So - * 100 msec delay is good enough - */ - msleep(100); - } - reg_modify(ISIF_SYNCEN_VDHDEN_MASK, en, SYNCEN); -} - -static void isif_enable_output_to_sdram(int en) -{ - reg_modify(ISIF_SYNCEN_WEN_MASK, en << ISIF_SYNCEN_WEN_SHIFT, SYNCEN); -} - -static void isif_config_culling(struct isif_cul *cul) -{ - u32 val; - - /* Horizontal pattern */ - val = (cul->hcpat_even << CULL_PAT_EVEN_LINE_SHIFT) | cul->hcpat_odd; - regw(val, CULH); - - /* vertical pattern */ - regw(cul->vcpat, CULV); - - /* LPF */ - reg_modify(ISIF_LPF_MASK << ISIF_LPF_SHIFT, - cul->en_lpf << ISIF_LPF_SHIFT, MODESET); -} - -static void isif_config_gain_offset(void) -{ - struct isif_gain_offsets_adj *gain_off_p = - &isif_cfg.bayer.config_params.gain_offset; - u32 val; - - val = (!!gain_off_p->gain_sdram_en << GAIN_SDRAM_EN_SHIFT) | - (!!gain_off_p->gain_ipipe_en << GAIN_IPIPE_EN_SHIFT) | - (!!gain_off_p->gain_h3a_en << GAIN_H3A_EN_SHIFT) | - (!!gain_off_p->offset_sdram_en << OFST_SDRAM_EN_SHIFT) | - (!!gain_off_p->offset_ipipe_en << OFST_IPIPE_EN_SHIFT) | - (!!gain_off_p->offset_h3a_en << OFST_H3A_EN_SHIFT); - - reg_modify(GAIN_OFFSET_EN_MASK, val, CGAMMAWD); - - val = (gain_off_p->gain.r_ye.integer << GAIN_INTEGER_SHIFT) | - gain_off_p->gain.r_ye.decimal; - regw(val, CRGAIN); - - val = (gain_off_p->gain.gr_cy.integer << GAIN_INTEGER_SHIFT) | - gain_off_p->gain.gr_cy.decimal; - regw(val, CGRGAIN); - - val = (gain_off_p->gain.gb_g.integer << GAIN_INTEGER_SHIFT) | - gain_off_p->gain.gb_g.decimal; - regw(val, CGBGAIN); - - val = (gain_off_p->gain.b_mg.integer << GAIN_INTEGER_SHIFT) | - gain_off_p->gain.b_mg.decimal; - regw(val, CBGAIN); - - regw(gain_off_p->offset, COFSTA); -} - -static void isif_restore_defaults(void) -{ - enum vpss_ccdc_source_sel source = VPSS_CCDCIN; - - dev_dbg(isif_cfg.dev, "\nstarting isif_restore_defaults..."); - isif_cfg.bayer.config_params = isif_config_defaults; - /* Enable clock to ISIF, IPIPEIF and BL */ - vpss_enable_clock(VPSS_CCDC_CLOCK, 1); - vpss_enable_clock(VPSS_IPIPEIF_CLOCK, 1); - vpss_enable_clock(VPSS_BL_CLOCK, 1); - /* Set default offset and gain */ - isif_config_gain_offset(); - vpss_select_ccdc_source(source); - dev_dbg(isif_cfg.dev, "\nEnd of isif_restore_defaults..."); -} - -static int isif_open(struct device *device) -{ - isif_restore_defaults(); - return 0; -} - -/* This function will configure the window size to be capture in ISIF reg */ -static void isif_setwin(struct v4l2_rect *image_win, - enum ccdc_frmfmt frm_fmt, int ppc) -{ - int horz_start, horz_nr_pixels; - int vert_start, vert_nr_lines; - int mid_img = 0; - - dev_dbg(isif_cfg.dev, "\nStarting isif_setwin..."); - /* - * ppc - per pixel count. indicates how many pixels per cell - * output to SDRAM. example, for ycbcr, it is one y and one c, so 2. - * raw capture this is 1 - */ - horz_start = image_win->left << (ppc - 1); - horz_nr_pixels = ((image_win->width) << (ppc - 1)) - 1; - - /* Writing the horizontal info into the registers */ - regw(horz_start & START_PX_HOR_MASK, SPH); - regw(horz_nr_pixels & NUM_PX_HOR_MASK, LNH); - vert_start = image_win->top; - - if (frm_fmt == CCDC_FRMFMT_INTERLACED) { - vert_nr_lines = (image_win->height >> 1) - 1; - vert_start >>= 1; - /* To account for VD since line 0 doesn't have any data */ - vert_start += 1; - } else { - /* To account for VD since line 0 doesn't have any data */ - vert_start += 1; - vert_nr_lines = image_win->height - 1; - /* configure VDINT0 and VDINT1 */ - mid_img = vert_start + (image_win->height / 2); - regw(mid_img, VDINT1); - } - - regw(0, VDINT0); - regw(vert_start & START_VER_ONE_MASK, SLV0); - regw(vert_start & START_VER_TWO_MASK, SLV1); - regw(vert_nr_lines & NUM_LINES_VER, LNV); -} - -static void isif_config_bclamp(struct isif_black_clamp *bc) -{ - u32 val; - - /* - * DC Offset is always added to image data irrespective of bc enable - * status - */ - regw(bc->dc_offset, CLDCOFST); - - if (bc->en) { - val = bc->bc_mode_color << ISIF_BC_MODE_COLOR_SHIFT; - - /* Enable BC and horizontal clamp caculation paramaters */ - val = val | 1 | (bc->horz.mode << ISIF_HORZ_BC_MODE_SHIFT); - - regw(val, CLAMPCFG); - - if (bc->horz.mode != ISIF_HORZ_BC_DISABLE) { - /* - * Window count for calculation - * Base window selection - * pixel limit - * Horizontal size of window - * vertical size of the window - * Horizontal start position of the window - * Vertical start position of the window - */ - val = bc->horz.win_count_calc | - ((!!bc->horz.base_win_sel_calc) << - ISIF_HORZ_BC_WIN_SEL_SHIFT) | - ((!!bc->horz.clamp_pix_limit) << - ISIF_HORZ_BC_PIX_LIMIT_SHIFT) | - (bc->horz.win_h_sz_calc << - ISIF_HORZ_BC_WIN_H_SIZE_SHIFT) | - (bc->horz.win_v_sz_calc << - ISIF_HORZ_BC_WIN_V_SIZE_SHIFT); - regw(val, CLHWIN0); - - regw(bc->horz.win_start_h_calc, CLHWIN1); - regw(bc->horz.win_start_v_calc, CLHWIN2); - } - - /* vertical clamp caculation paramaters */ - - /* Reset clamp value sel for previous line */ - val |= - (bc->vert.reset_val_sel << ISIF_VERT_BC_RST_VAL_SEL_SHIFT) | - (bc->vert.line_ave_coef << ISIF_VERT_BC_LINE_AVE_COEF_SHIFT); - regw(val, CLVWIN0); - - /* Optical Black horizontal start position */ - regw(bc->vert.ob_start_h, CLVWIN1); - /* Optical Black vertical start position */ - regw(bc->vert.ob_start_v, CLVWIN2); - /* Optical Black vertical size for calculation */ - regw(bc->vert.ob_v_sz_calc, CLVWIN3); - /* Vertical start position for BC subtraction */ - regw(bc->vert_start_sub, CLSV); - } -} - -static void isif_config_linearization(struct isif_linearize *linearize) -{ - u32 val, i; - - if (!linearize->en) { - regw(0, LINCFG0); - return; - } - - /* shift value for correction & enable linearization (set lsb) */ - val = (linearize->corr_shft << ISIF_LIN_CORRSFT_SHIFT) | 1; - regw(val, LINCFG0); - - /* Scale factor */ - val = ((!!linearize->scale_fact.integer) << - ISIF_LIN_SCALE_FACT_INTEG_SHIFT) | - linearize->scale_fact.decimal; - regw(val, LINCFG1); - - for (i = 0; i < ISIF_LINEAR_TAB_SIZE; i++) { - if (i % 2) - regw_lin_tbl(linearize->table[i], ((i >> 1) << 2), 1); - else - regw_lin_tbl(linearize->table[i], ((i >> 1) << 2), 0); - } -} - -static int isif_config_dfc(struct isif_dfc *vdfc) -{ - /* initialize retries to loop for max ~ 250 usec */ - u32 val, count, retries = loops_per_jiffy / (4000/HZ); - int i; - - if (!vdfc->en) - return 0; - - /* Correction mode */ - val = (vdfc->corr_mode << ISIF_VDFC_CORR_MOD_SHIFT); - - /* Correct whole line or partial */ - if (vdfc->corr_whole_line) - val |= 1 << ISIF_VDFC_CORR_WHOLE_LN_SHIFT; - - /* level shift value */ - val |= vdfc->def_level_shift << ISIF_VDFC_LEVEL_SHFT_SHIFT; - - regw(val, DFCCTL); - - /* Defect saturation level */ - regw(vdfc->def_sat_level, VDFSATLV); - - regw(vdfc->table[0].pos_vert, DFCMEM0); - regw(vdfc->table[0].pos_horz, DFCMEM1); - if (vdfc->corr_mode == ISIF_VDFC_NORMAL || - vdfc->corr_mode == ISIF_VDFC_HORZ_INTERPOL_IF_SAT) { - regw(vdfc->table[0].level_at_pos, DFCMEM2); - regw(vdfc->table[0].level_up_pixels, DFCMEM3); - regw(vdfc->table[0].level_low_pixels, DFCMEM4); - } - - /* set DFCMARST and set DFCMWR */ - val = regr(DFCMEMCTL) | (1 << ISIF_DFCMEMCTL_DFCMARST_SHIFT) | 1; - regw(val, DFCMEMCTL); - - count = retries; - while (count && (regr(DFCMEMCTL) & 0x1)) - count--; - - if (!count) { - dev_dbg(isif_cfg.dev, "defect table write timeout !!!\n"); - return -1; - } - - for (i = 1; i < vdfc->num_vdefects; i++) { - regw(vdfc->table[i].pos_vert, DFCMEM0); - regw(vdfc->table[i].pos_horz, DFCMEM1); - if (vdfc->corr_mode == ISIF_VDFC_NORMAL || - vdfc->corr_mode == ISIF_VDFC_HORZ_INTERPOL_IF_SAT) { - regw(vdfc->table[i].level_at_pos, DFCMEM2); - regw(vdfc->table[i].level_up_pixels, DFCMEM3); - regw(vdfc->table[i].level_low_pixels, DFCMEM4); - } - val = regr(DFCMEMCTL); - /* clear DFCMARST and set DFCMWR */ - val &= ~BIT(ISIF_DFCMEMCTL_DFCMARST_SHIFT); - val |= 1; - regw(val, DFCMEMCTL); - - count = retries; - while (count && (regr(DFCMEMCTL) & 0x1)) - count--; - - if (!count) { - dev_err(isif_cfg.dev, - "defect table write timeout !!!\n"); - return -1; - } - } - if (vdfc->num_vdefects < ISIF_VDFC_TABLE_SIZE) { - /* Extra cycle needed */ - regw(0, DFCMEM0); - regw(0x1FFF, DFCMEM1); - regw(1, DFCMEMCTL); - } - - /* enable VDFC */ - reg_modify((1 << ISIF_VDFC_EN_SHIFT), (1 << ISIF_VDFC_EN_SHIFT), - DFCCTL); - return 0; -} - -static void isif_config_csc(struct isif_df_csc *df_csc) -{ - u32 val1 = 0, val2 = 0, i; - - if (!df_csc->csc.en) { - regw(0, CSCCTL); - return; - } - for (i = 0; i < ISIF_CSC_NUM_COEFF; i++) { - if ((i % 2) == 0) { - /* CSCM - LSB */ - val1 = (df_csc->csc.coeff[i].integer << - ISIF_CSC_COEF_INTEG_SHIFT) | - df_csc->csc.coeff[i].decimal; - } else { - - /* CSCM - MSB */ - val2 = (df_csc->csc.coeff[i].integer << - ISIF_CSC_COEF_INTEG_SHIFT) | - df_csc->csc.coeff[i].decimal; - val2 <<= ISIF_CSCM_MSB_SHIFT; - val2 |= val1; - regw(val2, (CSCM0 + ((i - 1) << 1))); - } - } - - /* program the active area */ - regw(df_csc->start_pix, FMTSPH); - /* - * one extra pixel as required for CSC. Actually number of - * pixel - 1 should be configured in this register. So we - * need to subtract 1 before writing to FMTSPH, but we will - * not do this since csc requires one extra pixel - */ - regw(df_csc->num_pixels, FMTLNH); - regw(df_csc->start_line, FMTSLV); - /* - * one extra line as required for CSC. See reason documented for - * num_pixels - */ - regw(df_csc->num_lines, FMTLNV); - - /* Enable CSC */ - regw(1, CSCCTL); -} - -static int isif_config_raw(void) -{ - struct isif_params_raw *params = &isif_cfg.bayer; - struct isif_config_params_raw *module_params = - &isif_cfg.bayer.config_params; - struct vpss_pg_frame_size frame_size; - struct vpss_sync_pol sync; - u32 val; - - dev_dbg(isif_cfg.dev, "\nStarting isif_config_raw..\n"); - - /* - * Configure CCDCFG register:- - * Set CCD Not to swap input since input is RAW data - * Set FID detection function to Latch at V-Sync - * Set WENLOG - isif valid area - * Set TRGSEL - * Set EXTRG - * Packed to 8 or 16 bits - */ - - val = ISIF_YCINSWP_RAW | ISIF_CCDCFG_FIDMD_LATCH_VSYNC | - ISIF_CCDCFG_WENLOG_AND | ISIF_CCDCFG_TRGSEL_WEN | - ISIF_CCDCFG_EXTRG_DISABLE | isif_cfg.data_pack; - - dev_dbg(isif_cfg.dev, "Writing 0x%x to ...CCDCFG \n", val); - regw(val, CCDCFG); - - /* - * Configure the vertical sync polarity(MODESET.VDPOL) - * Configure the horizontal sync polarity (MODESET.HDPOL) - * Configure frame id polarity (MODESET.FLDPOL) - * Configure data polarity - * Configure External WEN Selection - * Configure frame format(progressive or interlace) - * Configure pixel format (Input mode) - * Configure the data shift - */ - - val = ISIF_VDHDOUT_INPUT | (params->vd_pol << ISIF_VD_POL_SHIFT) | - (params->hd_pol << ISIF_HD_POL_SHIFT) | - (params->fid_pol << ISIF_FID_POL_SHIFT) | - (ISIF_DATAPOL_NORMAL << ISIF_DATAPOL_SHIFT) | - (ISIF_EXWEN_DISABLE << ISIF_EXWEN_SHIFT) | - (params->frm_fmt << ISIF_FRM_FMT_SHIFT) | - (params->pix_fmt << ISIF_INPUT_SHIFT) | - (params->config_params.data_shift << ISIF_DATASFT_SHIFT); - - regw(val, MODESET); - dev_dbg(isif_cfg.dev, "Writing 0x%x to MODESET...\n", val); - - /* - * Configure GAMMAWD register - * CFA pattern setting - */ - val = params->cfa_pat << ISIF_GAMMAWD_CFA_SHIFT; - - /* Gamma msb */ - if (module_params->compress.alg == ISIF_ALAW) - val |= ISIF_ALAW_ENABLE; - - val |= (params->data_msb << ISIF_ALAW_GAMA_WD_SHIFT); - regw(val, CGAMMAWD); - - /* Configure DPCM compression settings */ - if (module_params->compress.alg == ISIF_DPCM) { - val = BIT(ISIF_DPCM_EN_SHIFT) | - (module_params->compress.pred << - ISIF_DPCM_PREDICTOR_SHIFT); - } - - regw(val, MISC); - - /* Configure Gain & Offset */ - isif_config_gain_offset(); - - /* Configure Color pattern */ - val = (params->config_params.col_pat_field0.olop) | - (params->config_params.col_pat_field0.olep << 2) | - (params->config_params.col_pat_field0.elop << 4) | - (params->config_params.col_pat_field0.elep << 6) | - (params->config_params.col_pat_field1.olop << 8) | - (params->config_params.col_pat_field1.olep << 10) | - (params->config_params.col_pat_field1.elop << 12) | - (params->config_params.col_pat_field1.elep << 14); - regw(val, CCOLP); - dev_dbg(isif_cfg.dev, "Writing %x to CCOLP ...\n", val); - - /* Configure HSIZE register */ - val = (!!params->horz_flip_en) << ISIF_HSIZE_FLIP_SHIFT; - - /* calculate line offset in 32 bytes based on pack value */ - if (isif_cfg.data_pack == ISIF_PACK_8BIT) - val |= ((params->win.width + 31) >> 5); - else if (isif_cfg.data_pack == ISIF_PACK_12BIT) - val |= (((params->win.width + - (params->win.width >> 2)) + 31) >> 5); - else - val |= (((params->win.width * 2) + 31) >> 5); - regw(val, HSIZE); - - /* Configure SDOFST register */ - if (params->frm_fmt == CCDC_FRMFMT_INTERLACED) { - if (params->image_invert_en) { - /* For interlace inverse mode */ - regw(0x4B6D, SDOFST); - dev_dbg(isif_cfg.dev, "Writing 0x4B6D to SDOFST...\n"); - } else { - /* For interlace non inverse mode */ - regw(0x0B6D, SDOFST); - dev_dbg(isif_cfg.dev, "Writing 0x0B6D to SDOFST...\n"); - } - } else if (params->frm_fmt == CCDC_FRMFMT_PROGRESSIVE) { - if (params->image_invert_en) { - /* For progressive inverse mode */ - regw(0x4000, SDOFST); - dev_dbg(isif_cfg.dev, "Writing 0x4000 to SDOFST...\n"); - } else { - /* For progressive non inverse mode */ - regw(0x0000, SDOFST); - dev_dbg(isif_cfg.dev, "Writing 0x0000 to SDOFST...\n"); - } - } - - /* Configure video window */ - isif_setwin(¶ms->win, params->frm_fmt, 1); - - /* Configure Black Clamp */ - isif_config_bclamp(&module_params->bclamp); - - /* Configure Vertical Defection Pixel Correction */ - if (isif_config_dfc(&module_params->dfc) < 0) - return -EFAULT; - - if (!module_params->df_csc.df_or_csc) - /* Configure Color Space Conversion */ - isif_config_csc(&module_params->df_csc); - - isif_config_linearization(&module_params->linearize); - - /* Configure Culling */ - isif_config_culling(&module_params->culling); - - /* Configure horizontal and vertical offsets(DFC,LSC,Gain) */ - regw(module_params->horz_offset, DATAHOFST); - regw(module_params->vert_offset, DATAVOFST); - - /* Setup test pattern if enabled */ - if (params->config_params.test_pat_gen) { - /* Use the HD/VD pol settings from user */ - sync.ccdpg_hdpol = params->hd_pol; - sync.ccdpg_vdpol = params->vd_pol; - dm365_vpss_set_sync_pol(sync); - frame_size.hlpfr = isif_cfg.bayer.win.width; - frame_size.pplen = isif_cfg.bayer.win.height; - dm365_vpss_set_pg_frame_size(frame_size); - vpss_select_ccdc_source(VPSS_PGLPBK); - } - - dev_dbg(isif_cfg.dev, "\nEnd of isif_config_ycbcr...\n"); - return 0; -} - -static int isif_set_buftype(enum ccdc_buftype buf_type) -{ - if (isif_cfg.if_type == VPFE_RAW_BAYER) - isif_cfg.bayer.buf_type = buf_type; - else - isif_cfg.ycbcr.buf_type = buf_type; - - return 0; - -} -static enum ccdc_buftype isif_get_buftype(void) -{ - if (isif_cfg.if_type == VPFE_RAW_BAYER) - return isif_cfg.bayer.buf_type; - - return isif_cfg.ycbcr.buf_type; -} - -static int isif_enum_pix(u32 *pix, int i) -{ - int ret = -EINVAL; - - if (isif_cfg.if_type == VPFE_RAW_BAYER) { - if (i < ARRAY_SIZE(isif_raw_bayer_pix_formats)) { - *pix = isif_raw_bayer_pix_formats[i]; - ret = 0; - } - } else { - if (i < ARRAY_SIZE(isif_raw_yuv_pix_formats)) { - *pix = isif_raw_yuv_pix_formats[i]; - ret = 0; - } - } - - return ret; -} - -static int isif_set_pixel_format(unsigned int pixfmt) -{ - if (isif_cfg.if_type == VPFE_RAW_BAYER) { - if (pixfmt == V4L2_PIX_FMT_SBGGR8) { - if ((isif_cfg.bayer.config_params.compress.alg != - ISIF_ALAW) && - (isif_cfg.bayer.config_params.compress.alg != - ISIF_DPCM)) { - dev_dbg(isif_cfg.dev, - "Either configure A-Law or DPCM\n"); - return -EINVAL; - } - isif_cfg.data_pack = ISIF_PACK_8BIT; - } else if (pixfmt == V4L2_PIX_FMT_SBGGR16) { - isif_cfg.bayer.config_params.compress.alg = - ISIF_NO_COMPRESSION; - isif_cfg.data_pack = ISIF_PACK_16BIT; - } else - return -EINVAL; - isif_cfg.bayer.pix_fmt = CCDC_PIXFMT_RAW; - } else { - if (pixfmt == V4L2_PIX_FMT_YUYV) - isif_cfg.ycbcr.pix_order = CCDC_PIXORDER_YCBYCR; - else if (pixfmt == V4L2_PIX_FMT_UYVY) - isif_cfg.ycbcr.pix_order = CCDC_PIXORDER_CBYCRY; - else - return -EINVAL; - isif_cfg.data_pack = ISIF_PACK_8BIT; - } - return 0; -} - -static u32 isif_get_pixel_format(void) -{ - u32 pixfmt; - - if (isif_cfg.if_type == VPFE_RAW_BAYER) - if (isif_cfg.bayer.config_params.compress.alg == ISIF_ALAW || - isif_cfg.bayer.config_params.compress.alg == ISIF_DPCM) - pixfmt = V4L2_PIX_FMT_SBGGR8; - else - pixfmt = V4L2_PIX_FMT_SBGGR16; - else { - if (isif_cfg.ycbcr.pix_order == CCDC_PIXORDER_YCBYCR) - pixfmt = V4L2_PIX_FMT_YUYV; - else - pixfmt = V4L2_PIX_FMT_UYVY; - } - return pixfmt; -} - -static int isif_set_image_window(struct v4l2_rect *win) -{ - if (isif_cfg.if_type == VPFE_RAW_BAYER) { - isif_cfg.bayer.win.top = win->top; - isif_cfg.bayer.win.left = win->left; - isif_cfg.bayer.win.width = win->width; - isif_cfg.bayer.win.height = win->height; - } else { - isif_cfg.ycbcr.win.top = win->top; - isif_cfg.ycbcr.win.left = win->left; - isif_cfg.ycbcr.win.width = win->width; - isif_cfg.ycbcr.win.height = win->height; - } - return 0; -} - -static void isif_get_image_window(struct v4l2_rect *win) -{ - if (isif_cfg.if_type == VPFE_RAW_BAYER) - *win = isif_cfg.bayer.win; - else - *win = isif_cfg.ycbcr.win; -} - -static unsigned int isif_get_line_length(void) -{ - unsigned int len; - - if (isif_cfg.if_type == VPFE_RAW_BAYER) { - if (isif_cfg.data_pack == ISIF_PACK_8BIT) - len = ((isif_cfg.bayer.win.width)); - else if (isif_cfg.data_pack == ISIF_PACK_12BIT) - len = (((isif_cfg.bayer.win.width * 2) + - (isif_cfg.bayer.win.width >> 2))); - else - len = (((isif_cfg.bayer.win.width * 2))); - } else - len = (((isif_cfg.ycbcr.win.width * 2))); - return ALIGN(len, 32); -} - -static int isif_set_frame_format(enum ccdc_frmfmt frm_fmt) -{ - if (isif_cfg.if_type == VPFE_RAW_BAYER) - isif_cfg.bayer.frm_fmt = frm_fmt; - else - isif_cfg.ycbcr.frm_fmt = frm_fmt; - return 0; -} -static enum ccdc_frmfmt isif_get_frame_format(void) -{ - if (isif_cfg.if_type == VPFE_RAW_BAYER) - return isif_cfg.bayer.frm_fmt; - return isif_cfg.ycbcr.frm_fmt; -} - -static int isif_getfid(void) -{ - return (regr(MODESET) >> 15) & 0x1; -} - -/* misc operations */ -static void isif_setfbaddr(unsigned long addr) -{ - regw((addr >> 21) & 0x07ff, CADU); - regw((addr >> 5) & 0x0ffff, CADL); -} - -static int isif_set_hw_if_params(struct vpfe_hw_if_param *params) -{ - isif_cfg.if_type = params->if_type; - - switch (params->if_type) { - case VPFE_BT656: - case VPFE_BT656_10BIT: - case VPFE_YCBCR_SYNC_8: - isif_cfg.ycbcr.pix_fmt = CCDC_PIXFMT_YCBCR_8BIT; - isif_cfg.ycbcr.pix_order = CCDC_PIXORDER_CBYCRY; - break; - case VPFE_BT1120: - case VPFE_YCBCR_SYNC_16: - isif_cfg.ycbcr.pix_fmt = CCDC_PIXFMT_YCBCR_16BIT; - isif_cfg.ycbcr.pix_order = CCDC_PIXORDER_CBYCRY; - break; - case VPFE_RAW_BAYER: - isif_cfg.bayer.pix_fmt = CCDC_PIXFMT_RAW; - break; - default: - dev_dbg(isif_cfg.dev, "Invalid interface type\n"); - return -EINVAL; - } - - return 0; -} - -/* This function will configure ISIF for YCbCr parameters. */ -static int isif_config_ycbcr(void) -{ - struct isif_ycbcr_config *params = &isif_cfg.ycbcr; - struct vpss_pg_frame_size frame_size; - u32 modeset = 0, ccdcfg = 0; - struct vpss_sync_pol sync; - - dev_dbg(isif_cfg.dev, "\nStarting isif_config_ycbcr..."); - - /* configure pixel format or input mode */ - modeset = modeset | (params->pix_fmt << ISIF_INPUT_SHIFT) | - (params->frm_fmt << ISIF_FRM_FMT_SHIFT) | - (params->fid_pol << ISIF_FID_POL_SHIFT) | - (params->hd_pol << ISIF_HD_POL_SHIFT) | - (params->vd_pol << ISIF_VD_POL_SHIFT); - - /* pack the data to 8-bit ISIFCFG */ - switch (isif_cfg.if_type) { - case VPFE_BT656: - if (params->pix_fmt != CCDC_PIXFMT_YCBCR_8BIT) { - dev_dbg(isif_cfg.dev, "Invalid pix_fmt(input mode)\n"); - return -EINVAL; - } - modeset |= (VPFE_PINPOL_NEGATIVE << ISIF_VD_POL_SHIFT); - regw(3, REC656IF); - ccdcfg = ccdcfg | ISIF_DATA_PACK8 | ISIF_YCINSWP_YCBCR; - break; - case VPFE_BT656_10BIT: - if (params->pix_fmt != CCDC_PIXFMT_YCBCR_8BIT) { - dev_dbg(isif_cfg.dev, "Invalid pix_fmt(input mode)\n"); - return -EINVAL; - } - /* setup BT.656, embedded sync */ - regw(3, REC656IF); - /* enable 10 bit mode in ccdcfg */ - ccdcfg = ccdcfg | ISIF_DATA_PACK8 | ISIF_YCINSWP_YCBCR | - ISIF_BW656_ENABLE; - break; - case VPFE_BT1120: - if (params->pix_fmt != CCDC_PIXFMT_YCBCR_16BIT) { - dev_dbg(isif_cfg.dev, "Invalid pix_fmt(input mode)\n"); - return -EINVAL; - } - regw(3, REC656IF); - break; - - case VPFE_YCBCR_SYNC_8: - ccdcfg |= ISIF_DATA_PACK8; - ccdcfg |= ISIF_YCINSWP_YCBCR; - if (params->pix_fmt != CCDC_PIXFMT_YCBCR_8BIT) { - dev_dbg(isif_cfg.dev, "Invalid pix_fmt(input mode)\n"); - return -EINVAL; - } - break; - case VPFE_YCBCR_SYNC_16: - if (params->pix_fmt != CCDC_PIXFMT_YCBCR_16BIT) { - dev_dbg(isif_cfg.dev, "Invalid pix_fmt(input mode)\n"); - return -EINVAL; - } - break; - default: - /* should never come here */ - dev_dbg(isif_cfg.dev, "Invalid interface type\n"); - return -EINVAL; - } - - regw(modeset, MODESET); - - /* Set up pix order */ - ccdcfg |= params->pix_order << ISIF_PIX_ORDER_SHIFT; - - regw(ccdcfg, CCDCFG); - - /* configure video window */ - if ((isif_cfg.if_type == VPFE_BT1120) || - (isif_cfg.if_type == VPFE_YCBCR_SYNC_16)) - isif_setwin(¶ms->win, params->frm_fmt, 1); - else - isif_setwin(¶ms->win, params->frm_fmt, 2); - - /* - * configure the horizontal line offset - * this is done by rounding up width to a multiple of 16 pixels - * and multiply by two to account for y:cb:cr 4:2:2 data - */ - regw(((((params->win.width * 2) + 31) & 0xffffffe0) >> 5), HSIZE); - - /* configure the memory line offset */ - if ((params->frm_fmt == CCDC_FRMFMT_INTERLACED) && - (params->buf_type == CCDC_BUFTYPE_FLD_INTERLEAVED)) - /* two fields are interleaved in memory */ - regw(0x00000249, SDOFST); - - /* Setup test pattern if enabled */ - if (isif_cfg.bayer.config_params.test_pat_gen) { - sync.ccdpg_hdpol = params->hd_pol; - sync.ccdpg_vdpol = params->vd_pol; - dm365_vpss_set_sync_pol(sync); - dm365_vpss_set_pg_frame_size(frame_size); - } - return 0; -} - -static int isif_configure(void) -{ - if (isif_cfg.if_type == VPFE_RAW_BAYER) - return isif_config_raw(); - return isif_config_ycbcr(); -} - -static int isif_close(struct device *device) -{ - /* copy defaults to module params */ - isif_cfg.bayer.config_params = isif_config_defaults; - return 0; -} - -static struct ccdc_hw_device isif_hw_dev = { - .name = "ISIF", - .owner = THIS_MODULE, - .hw_ops = { - .open = isif_open, - .close = isif_close, - .enable = isif_enable, - .enable_out_to_sdram = isif_enable_output_to_sdram, - .set_hw_if_params = isif_set_hw_if_params, - .configure = isif_configure, - .set_buftype = isif_set_buftype, - .get_buftype = isif_get_buftype, - .enum_pix = isif_enum_pix, - .set_pixel_format = isif_set_pixel_format, - .get_pixel_format = isif_get_pixel_format, - .set_frame_format = isif_set_frame_format, - .get_frame_format = isif_get_frame_format, - .set_image_window = isif_set_image_window, - .get_image_window = isif_get_image_window, - .get_line_length = isif_get_line_length, - .setfbaddr = isif_setfbaddr, - .getfid = isif_getfid, - }, -}; - -static int __init isif_probe(struct platform_device *pdev) -{ - void (*setup_pinmux)(void); - struct resource *res; - void *__iomem addr; - int status = 0, i; - - /* - * first try to register with vpfe. If not correct platform, then we - * don't have to iomap - */ - status = vpfe_register_ccdc_device(&isif_hw_dev); - if (status < 0) - return status; - - /* Get and enable Master clock */ - isif_cfg.mclk = clk_get(&pdev->dev, "master"); - if (IS_ERR(isif_cfg.mclk)) { - status = PTR_ERR(isif_cfg.mclk); - goto fail_mclk; - } - if (clk_enable(isif_cfg.mclk)) { - status = -ENODEV; - goto fail_mclk; - } - - /* Platform data holds setup_pinmux function ptr */ - if (NULL == pdev->dev.platform_data) { - status = -ENODEV; - goto fail_mclk; - } - setup_pinmux = pdev->dev.platform_data; - /* - * setup Mux configuration for ccdc which may be different for - * different SoCs using this CCDC - */ - setup_pinmux(); - - i = 0; - /* Get the ISIF base address, linearization table0 and table1 addr. */ - while (i < 3) { - res = platform_get_resource(pdev, IORESOURCE_MEM, i); - if (!res) { - status = -ENODEV; - goto fail_nobase_res; - } - res = request_mem_region(res->start, resource_size(res), - res->name); - if (!res) { - status = -EBUSY; - goto fail_nobase_res; - } - addr = ioremap_nocache(res->start, resource_size(res)); - if (!addr) { - status = -ENOMEM; - goto fail_base_iomap; - } - switch (i) { - case 0: - /* ISIF base address */ - isif_cfg.base_addr = addr; - break; - case 1: - /* ISIF linear tbl0 address */ - isif_cfg.linear_tbl0_addr = addr; - break; - default: - /* ISIF linear tbl0 address */ - isif_cfg.linear_tbl1_addr = addr; - break; - } - i++; - } - isif_cfg.dev = &pdev->dev; - - printk(KERN_NOTICE "%s is registered with vpfe.\n", - isif_hw_dev.name); - return 0; -fail_base_iomap: - release_mem_region(res->start, resource_size(res)); - i--; -fail_nobase_res: - if (isif_cfg.base_addr) - iounmap(isif_cfg.base_addr); - if (isif_cfg.linear_tbl0_addr) - iounmap(isif_cfg.linear_tbl0_addr); - - while (i >= 0) { - res = platform_get_resource(pdev, IORESOURCE_MEM, i); - release_mem_region(res->start, resource_size(res)); - i--; - } -fail_mclk: - clk_put(isif_cfg.mclk); - vpfe_unregister_ccdc_device(&isif_hw_dev); - return status; -} - -static int isif_remove(struct platform_device *pdev) -{ - struct resource *res; - int i = 0; - - iounmap(isif_cfg.base_addr); - iounmap(isif_cfg.linear_tbl0_addr); - iounmap(isif_cfg.linear_tbl1_addr); - while (i < 3) { - res = platform_get_resource(pdev, IORESOURCE_MEM, i); - if (res) - release_mem_region(res->start, resource_size(res)); - i++; - } - vpfe_unregister_ccdc_device(&isif_hw_dev); - return 0; -} - -static struct platform_driver isif_driver = { - .driver = { - .name = "isif", - .owner = THIS_MODULE, - }, - .remove = __devexit_p(isif_remove), - .probe = isif_probe, -}; - -static int __init isif_init(void) -{ - return platform_driver_register(&isif_driver); -} - -static void isif_exit(void) -{ - platform_driver_unregister(&isif_driver); -} - -module_init(isif_init); -module_exit(isif_exit); - -MODULE_LICENSE("GPL"); diff --git a/drivers/media/video/davinci/isif_regs.h b/drivers/media/video/davinci/isif_regs.h deleted file mode 100644 index aa69a463c12..00000000000 --- a/drivers/media/video/davinci/isif_regs.h +++ /dev/null @@ -1,269 +0,0 @@ -/* - * Copyright (C) 2008-2009 Texas Instruments Inc - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#ifndef _ISIF_REGS_H -#define _ISIF_REGS_H - -/* ISIF registers relative offsets */ -#define SYNCEN 0x00 -#define MODESET 0x04 -#define HDW 0x08 -#define VDW 0x0c -#define PPLN 0x10 -#define LPFR 0x14 -#define SPH 0x18 -#define LNH 0x1c -#define SLV0 0x20 -#define SLV1 0x24 -#define LNV 0x28 -#define CULH 0x2c -#define CULV 0x30 -#define HSIZE 0x34 -#define SDOFST 0x38 -#define CADU 0x3c -#define CADL 0x40 -#define LINCFG0 0x44 -#define LINCFG1 0x48 -#define CCOLP 0x4c -#define CRGAIN 0x50 -#define CGRGAIN 0x54 -#define CGBGAIN 0x58 -#define CBGAIN 0x5c -#define COFSTA 0x60 -#define FLSHCFG0 0x64 -#define FLSHCFG1 0x68 -#define FLSHCFG2 0x6c -#define VDINT0 0x70 -#define VDINT1 0x74 -#define VDINT2 0x78 -#define MISC 0x7c -#define CGAMMAWD 0x80 -#define REC656IF 0x84 -#define CCDCFG 0x88 -/***************************************************** -* Defect Correction registers -*****************************************************/ -#define DFCCTL 0x8c -#define VDFSATLV 0x90 -#define DFCMEMCTL 0x94 -#define DFCMEM0 0x98 -#define DFCMEM1 0x9c -#define DFCMEM2 0xa0 -#define DFCMEM3 0xa4 -#define DFCMEM4 0xa8 -/**************************************************** -* Black Clamp registers -****************************************************/ -#define CLAMPCFG 0xac -#define CLDCOFST 0xb0 -#define CLSV 0xb4 -#define CLHWIN0 0xb8 -#define CLHWIN1 0xbc -#define CLHWIN2 0xc0 -#define CLVRV 0xc4 -#define CLVWIN0 0xc8 -#define CLVWIN1 0xcc -#define CLVWIN2 0xd0 -#define CLVWIN3 0xd4 -/**************************************************** -* Lense Shading Correction -****************************************************/ -#define DATAHOFST 0xd8 -#define DATAVOFST 0xdc -#define LSCHVAL 0xe0 -#define LSCVVAL 0xe4 -#define TWODLSCCFG 0xe8 -#define TWODLSCOFST 0xec -#define TWODLSCINI 0xf0 -#define TWODLSCGRBU 0xf4 -#define TWODLSCGRBL 0xf8 -#define TWODLSCGROF 0xfc -#define TWODLSCORBU 0x100 -#define TWODLSCORBL 0x104 -#define TWODLSCOROF 0x108 -#define TWODLSCIRQEN 0x10c -#define TWODLSCIRQST 0x110 -/**************************************************** -* Data formatter -****************************************************/ -#define FMTCFG 0x114 -#define FMTPLEN 0x118 -#define FMTSPH 0x11c -#define FMTLNH 0x120 -#define FMTSLV 0x124 -#define FMTLNV 0x128 -#define FMTRLEN 0x12c -#define FMTHCNT 0x130 -#define FMTAPTR_BASE 0x134 -/* Below macro for addresses FMTAPTR0 - FMTAPTR15 */ -#define FMTAPTR(i) (FMTAPTR_BASE + (i * 4)) -#define FMTPGMVF0 0x174 -#define FMTPGMVF1 0x178 -#define FMTPGMAPU0 0x17c -#define FMTPGMAPU1 0x180 -#define FMTPGMAPS0 0x184 -#define FMTPGMAPS1 0x188 -#define FMTPGMAPS2 0x18c -#define FMTPGMAPS3 0x190 -#define FMTPGMAPS4 0x194 -#define FMTPGMAPS5 0x198 -#define FMTPGMAPS6 0x19c -#define FMTPGMAPS7 0x1a0 -/************************************************ -* Color Space Converter -************************************************/ -#define CSCCTL 0x1a4 -#define CSCM0 0x1a8 -#define CSCM1 0x1ac -#define CSCM2 0x1b0 -#define CSCM3 0x1b4 -#define CSCM4 0x1b8 -#define CSCM5 0x1bc -#define CSCM6 0x1c0 -#define CSCM7 0x1c4 -#define OBWIN0 0x1c8 -#define OBWIN1 0x1cc -#define OBWIN2 0x1d0 -#define OBWIN3 0x1d4 -#define OBVAL0 0x1d8 -#define OBVAL1 0x1dc -#define OBVAL2 0x1e0 -#define OBVAL3 0x1e4 -#define OBVAL4 0x1e8 -#define OBVAL5 0x1ec -#define OBVAL6 0x1f0 -#define OBVAL7 0x1f4 -#define CLKCTL 0x1f8 - -/* Masks & Shifts below */ -#define START_PX_HOR_MASK 0x7FFF -#define NUM_PX_HOR_MASK 0x7FFF -#define START_VER_ONE_MASK 0x7FFF -#define START_VER_TWO_MASK 0x7FFF -#define NUM_LINES_VER 0x7FFF - -/* gain - offset masks */ -#define GAIN_INTEGER_SHIFT 9 -#define OFFSET_MASK 0xFFF -#define GAIN_SDRAM_EN_SHIFT 12 -#define GAIN_IPIPE_EN_SHIFT 13 -#define GAIN_H3A_EN_SHIFT 14 -#define OFST_SDRAM_EN_SHIFT 8 -#define OFST_IPIPE_EN_SHIFT 9 -#define OFST_H3A_EN_SHIFT 10 -#define GAIN_OFFSET_EN_MASK 0x7700 - -/* Culling */ -#define CULL_PAT_EVEN_LINE_SHIFT 8 - -/* CCDCFG register */ -#define ISIF_YCINSWP_RAW (0x00 << 4) -#define ISIF_YCINSWP_YCBCR (0x01 << 4) -#define ISIF_CCDCFG_FIDMD_LATCH_VSYNC (0x00 << 6) -#define ISIF_CCDCFG_WENLOG_AND (0x00 << 8) -#define ISIF_CCDCFG_TRGSEL_WEN (0x00 << 9) -#define ISIF_CCDCFG_EXTRG_DISABLE (0x00 << 10) -#define ISIF_LATCH_ON_VSYNC_DISABLE (0x01 << 15) -#define ISIF_LATCH_ON_VSYNC_ENABLE (0x00 << 15) -#define ISIF_DATA_PACK_MASK 3 -#define ISIF_DATA_PACK16 0 -#define ISIF_DATA_PACK12 1 -#define ISIF_DATA_PACK8 2 -#define ISIF_PIX_ORDER_SHIFT 11 -#define ISIF_BW656_ENABLE (0x01 << 5) - -/* MODESET registers */ -#define ISIF_VDHDOUT_INPUT (0x00 << 0) -#define ISIF_INPUT_SHIFT 12 -#define ISIF_RAW_INPUT_MODE 0 -#define ISIF_FID_POL_SHIFT 4 -#define ISIF_HD_POL_SHIFT 3 -#define ISIF_VD_POL_SHIFT 2 -#define ISIF_DATAPOL_NORMAL 0 -#define ISIF_DATAPOL_SHIFT 6 -#define ISIF_EXWEN_DISABLE 0 -#define ISIF_EXWEN_SHIFT 5 -#define ISIF_FRM_FMT_SHIFT 7 -#define ISIF_DATASFT_SHIFT 8 -#define ISIF_LPF_SHIFT 14 -#define ISIF_LPF_MASK 1 - -/* GAMMAWD registers */ -#define ISIF_ALAW_GAMA_WD_MASK 0xF -#define ISIF_ALAW_GAMA_WD_SHIFT 1 -#define ISIF_ALAW_ENABLE 1 -#define ISIF_GAMMAWD_CFA_SHIFT 5 - -/* HSIZE registers */ -#define ISIF_HSIZE_FLIP_MASK 1 -#define ISIF_HSIZE_FLIP_SHIFT 12 - -/* MISC registers */ -#define ISIF_DPCM_EN_SHIFT 12 -#define ISIF_DPCM_PREDICTOR_SHIFT 13 - -/* Black clamp related */ -#define ISIF_BC_MODE_COLOR_SHIFT 4 -#define ISIF_HORZ_BC_MODE_SHIFT 1 -#define ISIF_HORZ_BC_WIN_SEL_SHIFT 5 -#define ISIF_HORZ_BC_PIX_LIMIT_SHIFT 6 -#define ISIF_HORZ_BC_WIN_H_SIZE_SHIFT 8 -#define ISIF_HORZ_BC_WIN_V_SIZE_SHIFT 12 -#define ISIF_VERT_BC_RST_VAL_SEL_SHIFT 4 -#define ISIF_VERT_BC_LINE_AVE_COEF_SHIFT 8 - -/* VDFC registers */ -#define ISIF_VDFC_EN_SHIFT 4 -#define ISIF_VDFC_CORR_MOD_SHIFT 5 -#define ISIF_VDFC_CORR_WHOLE_LN_SHIFT 7 -#define ISIF_VDFC_LEVEL_SHFT_SHIFT 8 -#define ISIF_VDFC_POS_MASK 0x1FFF -#define ISIF_DFCMEMCTL_DFCMARST_SHIFT 2 - -/* CSC registers */ -#define ISIF_CSC_COEF_INTEG_MASK 7 -#define ISIF_CSC_COEF_DECIMAL_MASK 0x1f -#define ISIF_CSC_COEF_INTEG_SHIFT 5 -#define ISIF_CSCM_MSB_SHIFT 8 -#define ISIF_DF_CSC_SPH_MASK 0x1FFF -#define ISIF_DF_CSC_LNH_MASK 0x1FFF -#define ISIF_DF_CSC_SLV_MASK 0x1FFF -#define ISIF_DF_CSC_LNV_MASK 0x1FFF -#define ISIF_DF_NUMLINES 0x7FFF -#define ISIF_DF_NUMPIX 0x1FFF - -/* Offsets for LSC/DFC/Gain */ -#define ISIF_DATA_H_OFFSET_MASK 0x1FFF -#define ISIF_DATA_V_OFFSET_MASK 0x1FFF - -/* Linearization */ -#define ISIF_LIN_CORRSFT_SHIFT 4 -#define ISIF_LIN_SCALE_FACT_INTEG_SHIFT 10 - - -/* Pattern registers */ -#define ISIF_PG_EN (1 << 3) -#define ISIF_SEL_PG_SRC (3 << 4) -#define ISIF_PG_VD_POL_SHIFT 0 -#define ISIF_PG_HD_POL_SHIFT 1 - -/*random other junk*/ -#define ISIF_SYNCEN_VDHDEN_MASK (1 << 0) -#define ISIF_SYNCEN_WEN_MASK (1 << 1) -#define ISIF_SYNCEN_WEN_SHIFT 1 - -#endif diff --git a/drivers/media/video/davinci/vpfe_capture.c b/drivers/media/video/davinci/vpfe_capture.c deleted file mode 100644 index d8e38cc4ec4..00000000000 --- a/drivers/media/video/davinci/vpfe_capture.c +++ /dev/null @@ -1,2096 +0,0 @@ -/* - * Copyright (C) 2008-2009 Texas Instruments Inc - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Driver name : VPFE Capture driver - * VPFE Capture driver allows applications to capture and stream video - * frames on DaVinci SoCs (DM6446, DM355 etc) from a YUV source such as - * TVP5146 or Raw Bayer RGB image data from an image sensor - * such as Microns' MT9T001, MT9T031 etc. - * - * These SoCs have, in common, a Video Processing Subsystem (VPSS) that - * consists of a Video Processing Front End (VPFE) for capturing - * video/raw image data and Video Processing Back End (VPBE) for displaying - * YUV data through an in-built analog encoder or Digital LCD port. This - * driver is for capture through VPFE. A typical EVM using these SoCs have - * following high level configuration. - * - * - * decoder(TVP5146/ YUV/ - * MT9T001) --> Raw Bayer RGB ---> MUX -> VPFE (CCDC/ISIF) - * data input | | - * V | - * SDRAM | - * V - * Image Processor - * | - * V - * SDRAM - * The data flow happens from a decoder connected to the VPFE over a - * YUV embedded (BT.656/BT.1120) or separate sync or raw bayer rgb interface - * and to the input of VPFE through an optional MUX (if more inputs are - * to be interfaced on the EVM). The input data is first passed through - * CCDC (CCD Controller, a.k.a Image Sensor Interface, ISIF). The CCDC - * does very little or no processing on YUV data and does pre-process Raw - * Bayer RGB data through modules such as Defect Pixel Correction (DFC) - * Color Space Conversion (CSC), data gain/offset etc. After this, data - * can be written to SDRAM or can be connected to the image processing - * block such as IPIPE (on DM355 only). - * - * Features supported - * - MMAP IO - * - Capture using TVP5146 over BT.656 - * - support for interfacing decoders using sub device model - * - Work with DM355 or DM6446 CCDC to do Raw Bayer RGB/YUV - * data capture to SDRAM. - * TODO list - * - Support multiple REQBUF after open - * - Support for de-allocating buffers through REQBUF - * - Support for Raw Bayer RGB capture - * - Support for chaining Image Processor - * - Support for static allocation of buffers - * - Support for USERPTR IO - * - Support for STREAMON before QBUF - * - Support for control ioctls - */ -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/init.h> -#include <linux/platform_device.h> -#include <linux/interrupt.h> -#include <media/v4l2-common.h> -#include <linux/io.h> -#include <media/davinci/vpfe_capture.h> -#include "ccdc_hw_device.h" - -static int debug; -static u32 numbuffers = 3; -static u32 bufsize = (720 * 576 * 2); - -module_param(numbuffers, uint, S_IRUGO); -module_param(bufsize, uint, S_IRUGO); -module_param(debug, int, 0644); - -MODULE_PARM_DESC(numbuffers, "buffer count (default:3)"); -MODULE_PARM_DESC(bufsize, "buffer size in bytes (default:720 x 576 x 2)"); -MODULE_PARM_DESC(debug, "Debug level 0-1"); - -MODULE_DESCRIPTION("VPFE Video for Linux Capture Driver"); -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Texas Instruments"); - -/* standard information */ -struct vpfe_standard { - v4l2_std_id std_id; - unsigned int width; - unsigned int height; - struct v4l2_fract pixelaspect; - /* 0 - progressive, 1 - interlaced */ - int frame_format; -}; - -/* ccdc configuration */ -struct ccdc_config { - /* This make sure vpfe is probed and ready to go */ - int vpfe_probed; - /* name of ccdc device */ - char name[32]; -}; - -/* data structures */ -static struct vpfe_config_params config_params = { - .min_numbuffers = 3, - .numbuffers = 3, - .min_bufsize = 720 * 480 * 2, - .device_bufsize = 720 * 576 * 2, -}; - -/* ccdc device registered */ -static struct ccdc_hw_device *ccdc_dev; -/* lock for accessing ccdc information */ -static DEFINE_MUTEX(ccdc_lock); -/* ccdc configuration */ -static struct ccdc_config *ccdc_cfg; - -const struct vpfe_standard vpfe_standards[] = { - {V4L2_STD_525_60, 720, 480, {11, 10}, 1}, - {V4L2_STD_625_50, 720, 576, {54, 59}, 1}, -}; - -/* Used when raw Bayer image from ccdc is directly captured to SDRAM */ -static const struct vpfe_pixel_format vpfe_pix_fmts[] = { - { - .fmtdesc = { - .index = 0, - .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, - .description = "Bayer GrRBGb 8bit A-Law compr.", - .pixelformat = V4L2_PIX_FMT_SBGGR8, - }, - .bpp = 1, - }, - { - .fmtdesc = { - .index = 1, - .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, - .description = "Bayer GrRBGb - 16bit", - .pixelformat = V4L2_PIX_FMT_SBGGR16, - }, - .bpp = 2, - }, - { - .fmtdesc = { - .index = 2, - .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, - .description = "Bayer GrRBGb 8bit DPCM compr.", - .pixelformat = V4L2_PIX_FMT_SGRBG10DPCM8, - }, - .bpp = 1, - }, - { - .fmtdesc = { - .index = 3, - .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, - .description = "YCbCr 4:2:2 Interleaved UYVY", - .pixelformat = V4L2_PIX_FMT_UYVY, - }, - .bpp = 2, - }, - { - .fmtdesc = { - .index = 4, - .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, - .description = "YCbCr 4:2:2 Interleaved YUYV", - .pixelformat = V4L2_PIX_FMT_YUYV, - }, - .bpp = 2, - }, - { - .fmtdesc = { - .index = 5, - .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, - .description = "Y/CbCr 4:2:0 - Semi planar", - .pixelformat = V4L2_PIX_FMT_NV12, - }, - .bpp = 1, - }, -}; - -/* - * vpfe_lookup_pix_format() - * lookup an entry in the vpfe pix format table based on pix_format - */ -static const struct vpfe_pixel_format *vpfe_lookup_pix_format(u32 pix_format) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(vpfe_pix_fmts); i++) { - if (pix_format == vpfe_pix_fmts[i].fmtdesc.pixelformat) - return &vpfe_pix_fmts[i]; - } - return NULL; -} - -/* - * vpfe_register_ccdc_device. CCDC module calls this to - * register with vpfe capture - */ -int vpfe_register_ccdc_device(struct ccdc_hw_device *dev) -{ - int ret = 0; - printk(KERN_NOTICE "vpfe_register_ccdc_device: %s\n", dev->name); - - BUG_ON(!dev->hw_ops.open); - BUG_ON(!dev->hw_ops.enable); - BUG_ON(!dev->hw_ops.set_hw_if_params); - BUG_ON(!dev->hw_ops.configure); - BUG_ON(!dev->hw_ops.set_buftype); - BUG_ON(!dev->hw_ops.get_buftype); - BUG_ON(!dev->hw_ops.enum_pix); - BUG_ON(!dev->hw_ops.set_frame_format); - BUG_ON(!dev->hw_ops.get_frame_format); - BUG_ON(!dev->hw_ops.get_pixel_format); - BUG_ON(!dev->hw_ops.set_pixel_format); - BUG_ON(!dev->hw_ops.set_image_window); - BUG_ON(!dev->hw_ops.get_image_window); - BUG_ON(!dev->hw_ops.get_line_length); - BUG_ON(!dev->hw_ops.getfid); - - mutex_lock(&ccdc_lock); - if (NULL == ccdc_cfg) { - /* - * TODO. Will this ever happen? if so, we need to fix it. - * Proabably we need to add the request to a linked list and - * walk through it during vpfe probe - */ - printk(KERN_ERR "vpfe capture not initialized\n"); - ret = -EFAULT; - goto unlock; - } - - if (strcmp(dev->name, ccdc_cfg->name)) { - /* ignore this ccdc */ - ret = -EINVAL; - goto unlock; - } - - if (ccdc_dev) { - printk(KERN_ERR "ccdc already registered\n"); - ret = -EINVAL; - goto unlock; - } - - ccdc_dev = dev; -unlock: - mutex_unlock(&ccdc_lock); - return ret; -} -EXPORT_SYMBOL(vpfe_register_ccdc_device); - -/* - * vpfe_unregister_ccdc_device. CCDC module calls this to - * unregister with vpfe capture - */ -void vpfe_unregister_ccdc_device(struct ccdc_hw_device *dev) -{ - if (NULL == dev) { - printk(KERN_ERR "invalid ccdc device ptr\n"); - return; - } - - printk(KERN_NOTICE "vpfe_unregister_ccdc_device, dev->name = %s\n", - dev->name); - - if (strcmp(dev->name, ccdc_cfg->name)) { - /* ignore this ccdc */ - return; - } - - mutex_lock(&ccdc_lock); - ccdc_dev = NULL; - mutex_unlock(&ccdc_lock); - return; -} -EXPORT_SYMBOL(vpfe_unregister_ccdc_device); - -/* - * vpfe_get_ccdc_image_format - Get image parameters based on CCDC settings - */ -static int vpfe_get_ccdc_image_format(struct vpfe_device *vpfe_dev, - struct v4l2_format *f) -{ - struct v4l2_rect image_win; - enum ccdc_buftype buf_type; - enum ccdc_frmfmt frm_fmt; - - memset(f, 0, sizeof(*f)); - f->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; - ccdc_dev->hw_ops.get_image_window(&image_win); - f->fmt.pix.width = image_win.width; - f->fmt.pix.height = image_win.height; - f->fmt.pix.bytesperline = ccdc_dev->hw_ops.get_line_length(); - f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * - f->fmt.pix.height; - buf_type = ccdc_dev->hw_ops.get_buftype(); - f->fmt.pix.pixelformat = ccdc_dev->hw_ops.get_pixel_format(); - frm_fmt = ccdc_dev->hw_ops.get_frame_format(); - if (frm_fmt == CCDC_FRMFMT_PROGRESSIVE) - f->fmt.pix.field = V4L2_FIELD_NONE; - else if (frm_fmt == CCDC_FRMFMT_INTERLACED) { - if (buf_type == CCDC_BUFTYPE_FLD_INTERLEAVED) - f->fmt.pix.field = V4L2_FIELD_INTERLACED; - else if (buf_type == CCDC_BUFTYPE_FLD_SEPARATED) - f->fmt.pix.field = V4L2_FIELD_SEQ_TB; - else { - v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf_type\n"); - return -EINVAL; - } - } else { - v4l2_err(&vpfe_dev->v4l2_dev, "Invalid frm_fmt\n"); - return -EINVAL; - } - return 0; -} - -/* - * vpfe_config_ccdc_image_format() - * For a pix format, configure ccdc to setup the capture - */ -static int vpfe_config_ccdc_image_format(struct vpfe_device *vpfe_dev) -{ - enum ccdc_frmfmt frm_fmt = CCDC_FRMFMT_INTERLACED; - int ret = 0; - - if (ccdc_dev->hw_ops.set_pixel_format( - vpfe_dev->fmt.fmt.pix.pixelformat) < 0) { - v4l2_err(&vpfe_dev->v4l2_dev, - "couldn't set pix format in ccdc\n"); - return -EINVAL; - } - /* configure the image window */ - ccdc_dev->hw_ops.set_image_window(&vpfe_dev->crop); - - switch (vpfe_dev->fmt.fmt.pix.field) { - case V4L2_FIELD_INTERLACED: - /* do nothing, since it is default */ - ret = ccdc_dev->hw_ops.set_buftype( - CCDC_BUFTYPE_FLD_INTERLEAVED); - break; - case V4L2_FIELD_NONE: - frm_fmt = CCDC_FRMFMT_PROGRESSIVE; - /* buffer type only applicable for interlaced scan */ - break; - case V4L2_FIELD_SEQ_TB: - ret = ccdc_dev->hw_ops.set_buftype( - CCDC_BUFTYPE_FLD_SEPARATED); - break; - default: - return -EINVAL; - } - - /* set the frame format */ - if (!ret) - ret = ccdc_dev->hw_ops.set_frame_format(frm_fmt); - return ret; -} -/* - * vpfe_config_image_format() - * For a given standard, this functions sets up the default - * pix format & crop values in the vpfe device and ccdc. It first - * starts with defaults based values from the standard table. - * It then checks if sub device support g_mbus_fmt and then override the - * values based on that.Sets crop values to match with scan resolution - * starting at 0,0. It calls vpfe_config_ccdc_image_format() set the - * values in ccdc - */ -static int vpfe_config_image_format(struct vpfe_device *vpfe_dev, - const v4l2_std_id *std_id) -{ - struct vpfe_subdev_info *sdinfo = vpfe_dev->current_subdev; - struct v4l2_mbus_framefmt mbus_fmt; - struct v4l2_pix_format *pix = &vpfe_dev->fmt.fmt.pix; - int i, ret = 0; - - for (i = 0; i < ARRAY_SIZE(vpfe_standards); i++) { - if (vpfe_standards[i].std_id & *std_id) { - vpfe_dev->std_info.active_pixels = - vpfe_standards[i].width; - vpfe_dev->std_info.active_lines = - vpfe_standards[i].height; - vpfe_dev->std_info.frame_format = - vpfe_standards[i].frame_format; - vpfe_dev->std_index = i; - break; - } - } - - if (i == ARRAY_SIZE(vpfe_standards)) { - v4l2_err(&vpfe_dev->v4l2_dev, "standard not supported\n"); - return -EINVAL; - } - - vpfe_dev->crop.top = 0; - vpfe_dev->crop.left = 0; - vpfe_dev->crop.width = vpfe_dev->std_info.active_pixels; - vpfe_dev->crop.height = vpfe_dev->std_info.active_lines; - pix->width = vpfe_dev->crop.width; - pix->height = vpfe_dev->crop.height; - - /* first field and frame format based on standard frame format */ - if (vpfe_dev->std_info.frame_format) { - pix->field = V4L2_FIELD_INTERLACED; - /* assume V4L2_PIX_FMT_UYVY as default */ - pix->pixelformat = V4L2_PIX_FMT_UYVY; - v4l2_fill_mbus_format(&mbus_fmt, pix, - V4L2_MBUS_FMT_YUYV10_2X10); - } else { - pix->field = V4L2_FIELD_NONE; - /* assume V4L2_PIX_FMT_SBGGR8 */ - pix->pixelformat = V4L2_PIX_FMT_SBGGR8; - v4l2_fill_mbus_format(&mbus_fmt, pix, - V4L2_MBUS_FMT_SBGGR8_1X8); - } - - /* if sub device supports g_mbus_fmt, override the defaults */ - ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, - sdinfo->grp_id, video, g_mbus_fmt, &mbus_fmt); - - if (ret && ret != -ENOIOCTLCMD) { - v4l2_err(&vpfe_dev->v4l2_dev, - "error in getting g_mbus_fmt from sub device\n"); - return ret; - } - v4l2_fill_pix_format(pix, &mbus_fmt); - pix->bytesperline = pix->width * 2; - pix->sizeimage = pix->bytesperline * pix->height; - - /* Sets the values in CCDC */ - ret = vpfe_config_ccdc_image_format(vpfe_dev); - if (ret) - return ret; - - /* Update the values of sizeimage and bytesperline */ - if (!ret) { - pix->bytesperline = ccdc_dev->hw_ops.get_line_length(); - pix->sizeimage = pix->bytesperline * pix->height; - } - return ret; -} - -static int vpfe_initialize_device(struct vpfe_device *vpfe_dev) -{ - int ret = 0; - - /* set first input of current subdevice as the current input */ - vpfe_dev->current_input = 0; - - /* set default standard */ - vpfe_dev->std_index = 0; - - /* Configure the default format information */ - ret = vpfe_config_image_format(vpfe_dev, - &vpfe_standards[vpfe_dev->std_index].std_id); - if (ret) - return ret; - - /* now open the ccdc device to initialize it */ - mutex_lock(&ccdc_lock); - if (NULL == ccdc_dev) { - v4l2_err(&vpfe_dev->v4l2_dev, "ccdc device not registered\n"); - ret = -ENODEV; - goto unlock; - } - - if (!try_module_get(ccdc_dev->owner)) { - v4l2_err(&vpfe_dev->v4l2_dev, "Couldn't lock ccdc module\n"); - ret = -ENODEV; - goto unlock; - } - ret = ccdc_dev->hw_ops.open(vpfe_dev->pdev); - if (!ret) - vpfe_dev->initialized = 1; - - /* Clear all VPFE/CCDC interrupts */ - if (vpfe_dev->cfg->clr_intr) - vpfe_dev->cfg->clr_intr(-1); - -unlock: - mutex_unlock(&ccdc_lock); - return ret; -} - -/* - * vpfe_open : It creates object of file handle structure and - * stores it in private_data member of filepointer - */ -static int vpfe_open(struct file *file) -{ - struct vpfe_device *vpfe_dev = video_drvdata(file); - struct vpfe_fh *fh; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_open\n"); - - if (!vpfe_dev->cfg->num_subdevs) { - v4l2_err(&vpfe_dev->v4l2_dev, "No decoder registered\n"); - return -ENODEV; - } - - /* Allocate memory for the file handle object */ - fh = kmalloc(sizeof(struct vpfe_fh), GFP_KERNEL); - if (NULL == fh) { - v4l2_err(&vpfe_dev->v4l2_dev, - "unable to allocate memory for file handle object\n"); - return -ENOMEM; - } - /* store pointer to fh in private_data member of file */ - file->private_data = fh; - fh->vpfe_dev = vpfe_dev; - mutex_lock(&vpfe_dev->lock); - /* If decoder is not initialized. initialize it */ - if (!vpfe_dev->initialized) { - if (vpfe_initialize_device(vpfe_dev)) { - mutex_unlock(&vpfe_dev->lock); - return -ENODEV; - } - } - /* Increment device usrs counter */ - vpfe_dev->usrs++; - /* Set io_allowed member to false */ - fh->io_allowed = 0; - /* Initialize priority of this instance to default priority */ - fh->prio = V4L2_PRIORITY_UNSET; - v4l2_prio_open(&vpfe_dev->prio, &fh->prio); - mutex_unlock(&vpfe_dev->lock); - return 0; -} - -static void vpfe_schedule_next_buffer(struct vpfe_device *vpfe_dev) -{ - unsigned long addr; - - vpfe_dev->next_frm = list_entry(vpfe_dev->dma_queue.next, - struct videobuf_buffer, queue); - list_del(&vpfe_dev->next_frm->queue); - vpfe_dev->next_frm->state = VIDEOBUF_ACTIVE; - addr = videobuf_to_dma_contig(vpfe_dev->next_frm); - - ccdc_dev->hw_ops.setfbaddr(addr); -} - -static void vpfe_schedule_bottom_field(struct vpfe_device *vpfe_dev) -{ - unsigned long addr; - - addr = videobuf_to_dma_contig(vpfe_dev->cur_frm); - addr += vpfe_dev->field_off; - ccdc_dev->hw_ops.setfbaddr(addr); -} - -static void vpfe_process_buffer_complete(struct vpfe_device *vpfe_dev) -{ - struct timeval timevalue; - - do_gettimeofday(&timevalue); - vpfe_dev->cur_frm->ts = timevalue; - vpfe_dev->cur_frm->state = VIDEOBUF_DONE; - vpfe_dev->cur_frm->size = vpfe_dev->fmt.fmt.pix.sizeimage; - wake_up_interruptible(&vpfe_dev->cur_frm->done); - vpfe_dev->cur_frm = vpfe_dev->next_frm; -} - -/* ISR for VINT0*/ -static irqreturn_t vpfe_isr(int irq, void *dev_id) -{ - struct vpfe_device *vpfe_dev = dev_id; - enum v4l2_field field; - int fid; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "\nStarting vpfe_isr...\n"); - field = vpfe_dev->fmt.fmt.pix.field; - - /* if streaming not started, don't do anything */ - if (!vpfe_dev->started) - goto clear_intr; - - /* only for 6446 this will be applicable */ - if (NULL != ccdc_dev->hw_ops.reset) - ccdc_dev->hw_ops.reset(); - - if (field == V4L2_FIELD_NONE) { - /* handle progressive frame capture */ - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, - "frame format is progressive...\n"); - if (vpfe_dev->cur_frm != vpfe_dev->next_frm) - vpfe_process_buffer_complete(vpfe_dev); - goto clear_intr; - } - - /* interlaced or TB capture check which field we are in hardware */ - fid = ccdc_dev->hw_ops.getfid(); - - /* switch the software maintained field id */ - vpfe_dev->field_id ^= 1; - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "field id = %x:%x.\n", - fid, vpfe_dev->field_id); - if (fid == vpfe_dev->field_id) { - /* we are in-sync here,continue */ - if (fid == 0) { - /* - * One frame is just being captured. If the next frame - * is available, release the current frame and move on - */ - if (vpfe_dev->cur_frm != vpfe_dev->next_frm) - vpfe_process_buffer_complete(vpfe_dev); - /* - * based on whether the two fields are stored - * interleavely or separately in memory, reconfigure - * the CCDC memory address - */ - if (field == V4L2_FIELD_SEQ_TB) { - vpfe_schedule_bottom_field(vpfe_dev); - } - goto clear_intr; - } - /* - * if one field is just being captured configure - * the next frame get the next frame from the empty - * queue if no frame is available hold on to the - * current buffer - */ - spin_lock(&vpfe_dev->dma_queue_lock); - if (!list_empty(&vpfe_dev->dma_queue) && - vpfe_dev->cur_frm == vpfe_dev->next_frm) - vpfe_schedule_next_buffer(vpfe_dev); - spin_unlock(&vpfe_dev->dma_queue_lock); - } else if (fid == 0) { - /* - * out of sync. Recover from any hardware out-of-sync. - * May loose one frame - */ - vpfe_dev->field_id = fid; - } -clear_intr: - if (vpfe_dev->cfg->clr_intr) - vpfe_dev->cfg->clr_intr(irq); - - return IRQ_HANDLED; -} - -/* vdint1_isr - isr handler for VINT1 interrupt */ -static irqreturn_t vdint1_isr(int irq, void *dev_id) -{ - struct vpfe_device *vpfe_dev = dev_id; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "\nInside vdint1_isr...\n"); - - /* if streaming not started, don't do anything */ - if (!vpfe_dev->started) { - if (vpfe_dev->cfg->clr_intr) - vpfe_dev->cfg->clr_intr(irq); - return IRQ_HANDLED; - } - - spin_lock(&vpfe_dev->dma_queue_lock); - if ((vpfe_dev->fmt.fmt.pix.field == V4L2_FIELD_NONE) && - !list_empty(&vpfe_dev->dma_queue) && - vpfe_dev->cur_frm == vpfe_dev->next_frm) - vpfe_schedule_next_buffer(vpfe_dev); - spin_unlock(&vpfe_dev->dma_queue_lock); - - if (vpfe_dev->cfg->clr_intr) - vpfe_dev->cfg->clr_intr(irq); - - return IRQ_HANDLED; -} - -static void vpfe_detach_irq(struct vpfe_device *vpfe_dev) -{ - enum ccdc_frmfmt frame_format; - - frame_format = ccdc_dev->hw_ops.get_frame_format(); - if (frame_format == CCDC_FRMFMT_PROGRESSIVE) - free_irq(vpfe_dev->ccdc_irq1, vpfe_dev); -} - -static int vpfe_attach_irq(struct vpfe_device *vpfe_dev) -{ - enum ccdc_frmfmt frame_format; - - frame_format = ccdc_dev->hw_ops.get_frame_format(); - if (frame_format == CCDC_FRMFMT_PROGRESSIVE) { - return request_irq(vpfe_dev->ccdc_irq1, vdint1_isr, - IRQF_DISABLED, "vpfe_capture1", - vpfe_dev); - } - return 0; -} - -/* vpfe_stop_ccdc_capture: stop streaming in ccdc/isif */ -static void vpfe_stop_ccdc_capture(struct vpfe_device *vpfe_dev) -{ - vpfe_dev->started = 0; - ccdc_dev->hw_ops.enable(0); - if (ccdc_dev->hw_ops.enable_out_to_sdram) - ccdc_dev->hw_ops.enable_out_to_sdram(0); -} - -/* - * vpfe_release : This function deletes buffer queue, frees the - * buffers and the vpfe file handle - */ -static int vpfe_release(struct file *file) -{ - struct vpfe_device *vpfe_dev = video_drvdata(file); - struct vpfe_fh *fh = file->private_data; - struct vpfe_subdev_info *sdinfo; - int ret; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_release\n"); - - /* Get the device lock */ - mutex_lock(&vpfe_dev->lock); - /* if this instance is doing IO */ - if (fh->io_allowed) { - if (vpfe_dev->started) { - sdinfo = vpfe_dev->current_subdev; - ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, - sdinfo->grp_id, - video, s_stream, 0); - if (ret && (ret != -ENOIOCTLCMD)) - v4l2_err(&vpfe_dev->v4l2_dev, - "stream off failed in subdev\n"); - vpfe_stop_ccdc_capture(vpfe_dev); - vpfe_detach_irq(vpfe_dev); - videobuf_streamoff(&vpfe_dev->buffer_queue); - } - vpfe_dev->io_usrs = 0; - vpfe_dev->numbuffers = config_params.numbuffers; - } - - /* Decrement device usrs counter */ - vpfe_dev->usrs--; - /* Close the priority */ - v4l2_prio_close(&vpfe_dev->prio, fh->prio); - /* If this is the last file handle */ - if (!vpfe_dev->usrs) { - vpfe_dev->initialized = 0; - if (ccdc_dev->hw_ops.close) - ccdc_dev->hw_ops.close(vpfe_dev->pdev); - module_put(ccdc_dev->owner); - } - mutex_unlock(&vpfe_dev->lock); - file->private_data = NULL; - /* Free memory allocated to file handle object */ - kfree(fh); - return 0; -} - -/* - * vpfe_mmap : It is used to map kernel space buffers - * into user spaces - */ -static int vpfe_mmap(struct file *file, struct vm_area_struct *vma) -{ - /* Get the device object and file handle object */ - struct vpfe_device *vpfe_dev = video_drvdata(file); - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_mmap\n"); - - return videobuf_mmap_mapper(&vpfe_dev->buffer_queue, vma); -} - -/* - * vpfe_poll: It is used for select/poll system call - */ -static unsigned int vpfe_poll(struct file *file, poll_table *wait) -{ - struct vpfe_device *vpfe_dev = video_drvdata(file); - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_poll\n"); - - if (vpfe_dev->started) - return videobuf_poll_stream(file, - &vpfe_dev->buffer_queue, wait); - return 0; -} - -/* vpfe capture driver file operations */ -static const struct v4l2_file_operations vpfe_fops = { - .owner = THIS_MODULE, - .open = vpfe_open, - .release = vpfe_release, - .unlocked_ioctl = video_ioctl2, - .mmap = vpfe_mmap, - .poll = vpfe_poll -}; - -/* - * vpfe_check_format() - * This function adjust the input pixel format as per hardware - * capabilities and update the same in pixfmt. - * Following algorithm used :- - * - * If given pixformat is not in the vpfe list of pix formats or not - * supported by the hardware, current value of pixformat in the device - * is used - * If given field is not supported, then current field is used. If field - * is different from current, then it is matched with that from sub device. - * Minimum height is 2 lines for interlaced or tb field and 1 line for - * progressive. Maximum height is clamped to active active lines of scan - * Minimum width is 32 bytes in memory and width is clamped to active - * pixels of scan. - * bytesperline is a multiple of 32. - */ -static const struct vpfe_pixel_format * - vpfe_check_format(struct vpfe_device *vpfe_dev, - struct v4l2_pix_format *pixfmt) -{ - u32 min_height = 1, min_width = 32, max_width, max_height; - const struct vpfe_pixel_format *vpfe_pix_fmt; - u32 pix; - int temp, found; - - vpfe_pix_fmt = vpfe_lookup_pix_format(pixfmt->pixelformat); - if (NULL == vpfe_pix_fmt) { - /* - * use current pixel format in the vpfe device. We - * will find this pix format in the table - */ - pixfmt->pixelformat = vpfe_dev->fmt.fmt.pix.pixelformat; - vpfe_pix_fmt = vpfe_lookup_pix_format(pixfmt->pixelformat); - } - - /* check if hw supports it */ - temp = 0; - found = 0; - while (ccdc_dev->hw_ops.enum_pix(&pix, temp) >= 0) { - if (vpfe_pix_fmt->fmtdesc.pixelformat == pix) { - found = 1; - break; - } - temp++; - } - - if (!found) { - /* use current pixel format */ - pixfmt->pixelformat = vpfe_dev->fmt.fmt.pix.pixelformat; - /* - * Since this is currently used in the vpfe device, we - * will find this pix format in the table - */ - vpfe_pix_fmt = vpfe_lookup_pix_format(pixfmt->pixelformat); - } - - /* check what field format is supported */ - if (pixfmt->field == V4L2_FIELD_ANY) { - /* if field is any, use current value as default */ - pixfmt->field = vpfe_dev->fmt.fmt.pix.field; - } - - /* - * if field is not same as current field in the vpfe device - * try matching the field with the sub device field - */ - if (vpfe_dev->fmt.fmt.pix.field != pixfmt->field) { - /* - * If field value is not in the supported fields, use current - * field used in the device as default - */ - switch (pixfmt->field) { - case V4L2_FIELD_INTERLACED: - case V4L2_FIELD_SEQ_TB: - /* if sub device is supporting progressive, use that */ - if (!vpfe_dev->std_info.frame_format) - pixfmt->field = V4L2_FIELD_NONE; - break; - case V4L2_FIELD_NONE: - if (vpfe_dev->std_info.frame_format) - pixfmt->field = V4L2_FIELD_INTERLACED; - break; - - default: - /* use current field as default */ - pixfmt->field = vpfe_dev->fmt.fmt.pix.field; - break; - } - } - - /* Now adjust image resolutions supported */ - if (pixfmt->field == V4L2_FIELD_INTERLACED || - pixfmt->field == V4L2_FIELD_SEQ_TB) - min_height = 2; - - max_width = vpfe_dev->std_info.active_pixels; - max_height = vpfe_dev->std_info.active_lines; - min_width /= vpfe_pix_fmt->bpp; - - v4l2_info(&vpfe_dev->v4l2_dev, "width = %d, height = %d, bpp = %d\n", - pixfmt->width, pixfmt->height, vpfe_pix_fmt->bpp); - - pixfmt->width = clamp((pixfmt->width), min_width, max_width); - pixfmt->height = clamp((pixfmt->height), min_height, max_height); - - /* If interlaced, adjust height to be a multiple of 2 */ - if (pixfmt->field == V4L2_FIELD_INTERLACED) - pixfmt->height &= (~1); - /* - * recalculate bytesperline and sizeimage since width - * and height might have changed - */ - pixfmt->bytesperline = (((pixfmt->width * vpfe_pix_fmt->bpp) + 31) - & ~31); - if (pixfmt->pixelformat == V4L2_PIX_FMT_NV12) - pixfmt->sizeimage = - pixfmt->bytesperline * pixfmt->height + - ((pixfmt->bytesperline * pixfmt->height) >> 1); - else - pixfmt->sizeimage = pixfmt->bytesperline * pixfmt->height; - - v4l2_info(&vpfe_dev->v4l2_dev, "adjusted width = %d, height =" - " %d, bpp = %d, bytesperline = %d, sizeimage = %d\n", - pixfmt->width, pixfmt->height, vpfe_pix_fmt->bpp, - pixfmt->bytesperline, pixfmt->sizeimage); - return vpfe_pix_fmt; -} - -static int vpfe_querycap(struct file *file, void *priv, - struct v4l2_capability *cap) -{ - struct vpfe_device *vpfe_dev = video_drvdata(file); - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_querycap\n"); - - cap->version = VPFE_CAPTURE_VERSION_CODE; - cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; - strlcpy(cap->driver, CAPTURE_DRV_NAME, sizeof(cap->driver)); - strlcpy(cap->bus_info, "VPFE", sizeof(cap->bus_info)); - strlcpy(cap->card, vpfe_dev->cfg->card_name, sizeof(cap->card)); - return 0; -} - -static int vpfe_g_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *fmt) -{ - struct vpfe_device *vpfe_dev = video_drvdata(file); - int ret = 0; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_g_fmt_vid_cap\n"); - /* Fill in the information about format */ - *fmt = vpfe_dev->fmt; - return ret; -} - -static int vpfe_enum_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_fmtdesc *fmt) -{ - struct vpfe_device *vpfe_dev = video_drvdata(file); - const struct vpfe_pixel_format *pix_fmt; - int temp_index; - u32 pix; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_enum_fmt_vid_cap\n"); - - if (ccdc_dev->hw_ops.enum_pix(&pix, fmt->index) < 0) - return -EINVAL; - - /* Fill in the information about format */ - pix_fmt = vpfe_lookup_pix_format(pix); - if (NULL != pix_fmt) { - temp_index = fmt->index; - *fmt = pix_fmt->fmtdesc; - fmt->index = temp_index; - return 0; - } - return -EINVAL; -} - -static int vpfe_s_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *fmt) -{ - struct vpfe_device *vpfe_dev = video_drvdata(file); - const struct vpfe_pixel_format *pix_fmts; - int ret = 0; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_fmt_vid_cap\n"); - - /* If streaming is started, return error */ - if (vpfe_dev->started) { - v4l2_err(&vpfe_dev->v4l2_dev, "Streaming is started\n"); - return -EBUSY; - } - - /* Check for valid frame format */ - pix_fmts = vpfe_check_format(vpfe_dev, &fmt->fmt.pix); - - if (NULL == pix_fmts) - return -EINVAL; - - /* store the pixel format in the device object */ - ret = mutex_lock_interruptible(&vpfe_dev->lock); - if (ret) - return ret; - - /* First detach any IRQ if currently attached */ - vpfe_detach_irq(vpfe_dev); - vpfe_dev->fmt = *fmt; - /* set image capture parameters in the ccdc */ - ret = vpfe_config_ccdc_image_format(vpfe_dev); - mutex_unlock(&vpfe_dev->lock); - return ret; -} - -static int vpfe_try_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct vpfe_device *vpfe_dev = video_drvdata(file); - const struct vpfe_pixel_format *pix_fmts; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_try_fmt_vid_cap\n"); - - pix_fmts = vpfe_check_format(vpfe_dev, &f->fmt.pix); - if (NULL == pix_fmts) - return -EINVAL; - return 0; -} - -/* - * vpfe_get_subdev_input_index - Get subdev index and subdev input index for a - * given app input index - */ -static int vpfe_get_subdev_input_index(struct vpfe_device *vpfe_dev, - int *subdev_index, - int *subdev_input_index, - int app_input_index) -{ - struct vpfe_config *cfg = vpfe_dev->cfg; - struct vpfe_subdev_info *sdinfo; - int i, j = 0; - - for (i = 0; i < cfg->num_subdevs; i++) { - sdinfo = &cfg->sub_devs[i]; - if (app_input_index < (j + sdinfo->num_inputs)) { - *subdev_index = i; - *subdev_input_index = app_input_index - j; - return 0; - } - j += sdinfo->num_inputs; - } - return -EINVAL; -} - -/* - * vpfe_get_app_input - Get app input index for a given subdev input index - * driver stores the input index of the current sub device and translate it - * when application request the current input - */ -static int vpfe_get_app_input_index(struct vpfe_device *vpfe_dev, - int *app_input_index) -{ - struct vpfe_config *cfg = vpfe_dev->cfg; - struct vpfe_subdev_info *sdinfo; - int i, j = 0; - - for (i = 0; i < cfg->num_subdevs; i++) { - sdinfo = &cfg->sub_devs[i]; - if (!strcmp(sdinfo->name, vpfe_dev->current_subdev->name)) { - if (vpfe_dev->current_input >= sdinfo->num_inputs) - return -1; - *app_input_index = j + vpfe_dev->current_input; - return 0; - } - j += sdinfo->num_inputs; - } - return -EINVAL; -} - -static int vpfe_enum_input(struct file *file, void *priv, - struct v4l2_input *inp) -{ - struct vpfe_device *vpfe_dev = video_drvdata(file); - struct vpfe_subdev_info *sdinfo; - int subdev, index ; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_enum_input\n"); - - if (vpfe_get_subdev_input_index(vpfe_dev, - &subdev, - &index, - inp->index) < 0) { - v4l2_err(&vpfe_dev->v4l2_dev, "input information not found" - " for the subdev\n"); - return -EINVAL; - } - sdinfo = &vpfe_dev->cfg->sub_devs[subdev]; - memcpy(inp, &sdinfo->inputs[index], sizeof(struct v4l2_input)); - return 0; -} - -static int vpfe_g_input(struct file *file, void *priv, unsigned int *index) -{ - struct vpfe_device *vpfe_dev = video_drvdata(file); - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_g_input\n"); - - return vpfe_get_app_input_index(vpfe_dev, index); -} - - -static int vpfe_s_input(struct file *file, void *priv, unsigned int index) -{ - struct vpfe_device *vpfe_dev = video_drvdata(file); - struct vpfe_subdev_info *sdinfo; - int subdev_index, inp_index; - struct vpfe_route *route; - u32 input = 0, output = 0; - int ret = -EINVAL; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_input\n"); - - ret = mutex_lock_interruptible(&vpfe_dev->lock); - if (ret) - return ret; - - /* - * If streaming is started return device busy - * error - */ - if (vpfe_dev->started) { - v4l2_err(&vpfe_dev->v4l2_dev, "Streaming is on\n"); - ret = -EBUSY; - goto unlock_out; - } - - if (vpfe_get_subdev_input_index(vpfe_dev, - &subdev_index, - &inp_index, - index) < 0) { - v4l2_err(&vpfe_dev->v4l2_dev, "invalid input index\n"); - goto unlock_out; - } - - sdinfo = &vpfe_dev->cfg->sub_devs[subdev_index]; - route = &sdinfo->routes[inp_index]; - if (route && sdinfo->can_route) { - input = route->input; - output = route->output; - } - - ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id, - video, s_routing, input, output, 0); - - if (ret) { - v4l2_err(&vpfe_dev->v4l2_dev, - "vpfe_doioctl:error in setting input in decoder\n"); - ret = -EINVAL; - goto unlock_out; - } - vpfe_dev->current_subdev = sdinfo; - vpfe_dev->current_input = index; - vpfe_dev->std_index = 0; - - /* set the bus/interface parameter for the sub device in ccdc */ - ret = ccdc_dev->hw_ops.set_hw_if_params(&sdinfo->ccdc_if_params); - if (ret) - goto unlock_out; - - /* set the default image parameters in the device */ - ret = vpfe_config_image_format(vpfe_dev, - &vpfe_standards[vpfe_dev->std_index].std_id); -unlock_out: - mutex_unlock(&vpfe_dev->lock); - return ret; -} - -static int vpfe_querystd(struct file *file, void *priv, v4l2_std_id *std_id) -{ - struct vpfe_device *vpfe_dev = video_drvdata(file); - struct vpfe_subdev_info *sdinfo; - int ret = 0; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_querystd\n"); - - ret = mutex_lock_interruptible(&vpfe_dev->lock); - sdinfo = vpfe_dev->current_subdev; - if (ret) - return ret; - /* Call querystd function of decoder device */ - ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id, - video, querystd, std_id); - mutex_unlock(&vpfe_dev->lock); - return ret; -} - -static int vpfe_s_std(struct file *file, void *priv, v4l2_std_id *std_id) -{ - struct vpfe_device *vpfe_dev = video_drvdata(file); - struct vpfe_subdev_info *sdinfo; - int ret = 0; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_std\n"); - - /* Call decoder driver function to set the standard */ - ret = mutex_lock_interruptible(&vpfe_dev->lock); - if (ret) - return ret; - - sdinfo = vpfe_dev->current_subdev; - /* If streaming is started, return device busy error */ - if (vpfe_dev->started) { - v4l2_err(&vpfe_dev->v4l2_dev, "streaming is started\n"); - ret = -EBUSY; - goto unlock_out; - } - - ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id, - core, s_std, *std_id); - if (ret < 0) { - v4l2_err(&vpfe_dev->v4l2_dev, "Failed to set standard\n"); - goto unlock_out; - } - ret = vpfe_config_image_format(vpfe_dev, std_id); - -unlock_out: - mutex_unlock(&vpfe_dev->lock); - return ret; -} - -static int vpfe_g_std(struct file *file, void *priv, v4l2_std_id *std_id) -{ - struct vpfe_device *vpfe_dev = video_drvdata(file); - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_g_std\n"); - - *std_id = vpfe_standards[vpfe_dev->std_index].std_id; - return 0; -} -/* - * Videobuf operations - */ -static int vpfe_videobuf_setup(struct videobuf_queue *vq, - unsigned int *count, - unsigned int *size) -{ - struct vpfe_fh *fh = vq->priv_data; - struct vpfe_device *vpfe_dev = fh->vpfe_dev; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_buffer_setup\n"); - *size = vpfe_dev->fmt.fmt.pix.sizeimage; - if (vpfe_dev->memory == V4L2_MEMORY_MMAP && - vpfe_dev->fmt.fmt.pix.sizeimage > config_params.device_bufsize) - *size = config_params.device_bufsize; - - if (*count < config_params.min_numbuffers) - *count = config_params.min_numbuffers; - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, - "count=%d, size=%d\n", *count, *size); - return 0; -} - -static int vpfe_videobuf_prepare(struct videobuf_queue *vq, - struct videobuf_buffer *vb, - enum v4l2_field field) -{ - struct vpfe_fh *fh = vq->priv_data; - struct vpfe_device *vpfe_dev = fh->vpfe_dev; - unsigned long addr; - int ret; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_buffer_prepare\n"); - - /* If buffer is not initialized, initialize it */ - if (VIDEOBUF_NEEDS_INIT == vb->state) { - vb->width = vpfe_dev->fmt.fmt.pix.width; - vb->height = vpfe_dev->fmt.fmt.pix.height; - vb->size = vpfe_dev->fmt.fmt.pix.sizeimage; - vb->field = field; - - ret = videobuf_iolock(vq, vb, NULL);; - if (ret < 0) - return ret; - - addr = videobuf_to_dma_contig(vb); - /* Make sure user addresses are aligned to 32 bytes */ - if (!ALIGN(addr, 32)) - return -EINVAL; - - vb->state = VIDEOBUF_PREPARED; - } - return 0; -} - -static void vpfe_videobuf_queue(struct videobuf_queue *vq, - struct videobuf_buffer *vb) -{ - /* Get the file handle object and device object */ - struct vpfe_fh *fh = vq->priv_data; - struct vpfe_device *vpfe_dev = fh->vpfe_dev; - unsigned long flags; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_buffer_queue\n"); - - /* add the buffer to the DMA queue */ - spin_lock_irqsave(&vpfe_dev->dma_queue_lock, flags); - list_add_tail(&vb->queue, &vpfe_dev->dma_queue); - spin_unlock_irqrestore(&vpfe_dev->dma_queue_lock, flags); - - /* Change state of the buffer */ - vb->state = VIDEOBUF_QUEUED; -} - -static void vpfe_videobuf_release(struct videobuf_queue *vq, - struct videobuf_buffer *vb) -{ - struct vpfe_fh *fh = vq->priv_data; - struct vpfe_device *vpfe_dev = fh->vpfe_dev; - unsigned long flags; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_videobuf_release\n"); - - /* - * We need to flush the buffer from the dma queue since - * they are de-allocated - */ - spin_lock_irqsave(&vpfe_dev->dma_queue_lock, flags); - INIT_LIST_HEAD(&vpfe_dev->dma_queue); - spin_unlock_irqrestore(&vpfe_dev->dma_queue_lock, flags); - videobuf_dma_contig_free(vq, vb); - vb->state = VIDEOBUF_NEEDS_INIT; -} - -static struct videobuf_queue_ops vpfe_videobuf_qops = { - .buf_setup = vpfe_videobuf_setup, - .buf_prepare = vpfe_videobuf_prepare, - .buf_queue = vpfe_videobuf_queue, - .buf_release = vpfe_videobuf_release, -}; - -/* - * vpfe_reqbufs. currently support REQBUF only once opening - * the device. - */ -static int vpfe_reqbufs(struct file *file, void *priv, - struct v4l2_requestbuffers *req_buf) -{ - struct vpfe_device *vpfe_dev = video_drvdata(file); - struct vpfe_fh *fh = file->private_data; - int ret = 0; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_reqbufs\n"); - - if (V4L2_BUF_TYPE_VIDEO_CAPTURE != req_buf->type) { - v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buffer type\n"); - return -EINVAL; - } - - ret = mutex_lock_interruptible(&vpfe_dev->lock); - if (ret) - return ret; - - if (vpfe_dev->io_usrs != 0) { - v4l2_err(&vpfe_dev->v4l2_dev, "Only one IO user allowed\n"); - ret = -EBUSY; - goto unlock_out; - } - - vpfe_dev->memory = req_buf->memory; - videobuf_queue_dma_contig_init(&vpfe_dev->buffer_queue, - &vpfe_videobuf_qops, - vpfe_dev->pdev, - &vpfe_dev->irqlock, - req_buf->type, - vpfe_dev->fmt.fmt.pix.field, - sizeof(struct videobuf_buffer), - fh, NULL); - - fh->io_allowed = 1; - vpfe_dev->io_usrs = 1; - INIT_LIST_HEAD(&vpfe_dev->dma_queue); - ret = videobuf_reqbufs(&vpfe_dev->buffer_queue, req_buf); -unlock_out: - mutex_unlock(&vpfe_dev->lock); - return ret; -} - -static int vpfe_querybuf(struct file *file, void *priv, - struct v4l2_buffer *buf) -{ - struct vpfe_device *vpfe_dev = video_drvdata(file); - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_querybuf\n"); - - if (V4L2_BUF_TYPE_VIDEO_CAPTURE != buf->type) { - v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf type\n"); - return -EINVAL; - } - - if (vpfe_dev->memory != V4L2_MEMORY_MMAP) { - v4l2_err(&vpfe_dev->v4l2_dev, "Invalid memory\n"); - return -EINVAL; - } - /* Call videobuf_querybuf to get information */ - return videobuf_querybuf(&vpfe_dev->buffer_queue, buf); -} - -static int vpfe_qbuf(struct file *file, void *priv, - struct v4l2_buffer *p) -{ - struct vpfe_device *vpfe_dev = video_drvdata(file); - struct vpfe_fh *fh = file->private_data; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_qbuf\n"); - - if (V4L2_BUF_TYPE_VIDEO_CAPTURE != p->type) { - v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf type\n"); - return -EINVAL; - } - - /* - * If this file handle is not allowed to do IO, - * return error - */ - if (!fh->io_allowed) { - v4l2_err(&vpfe_dev->v4l2_dev, "fh->io_allowed\n"); - return -EACCES; - } - return videobuf_qbuf(&vpfe_dev->buffer_queue, p); -} - -static int vpfe_dqbuf(struct file *file, void *priv, - struct v4l2_buffer *buf) -{ - struct vpfe_device *vpfe_dev = video_drvdata(file); - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_dqbuf\n"); - - if (V4L2_BUF_TYPE_VIDEO_CAPTURE != buf->type) { - v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf type\n"); - return -EINVAL; - } - return videobuf_dqbuf(&vpfe_dev->buffer_queue, - buf, file->f_flags & O_NONBLOCK); -} - -static int vpfe_queryctrl(struct file *file, void *priv, - struct v4l2_queryctrl *qctrl) -{ - struct vpfe_device *vpfe_dev = video_drvdata(file); - struct vpfe_subdev_info *sdinfo; - - sdinfo = vpfe_dev->current_subdev; - - return v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id, - core, queryctrl, qctrl); - -} - -static int vpfe_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) -{ - struct vpfe_device *vpfe_dev = video_drvdata(file); - struct vpfe_subdev_info *sdinfo; - - sdinfo = vpfe_dev->current_subdev; - - return v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id, - core, g_ctrl, ctrl); -} - -static int vpfe_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) -{ - struct vpfe_device *vpfe_dev = video_drvdata(file); - struct vpfe_subdev_info *sdinfo; - - sdinfo = vpfe_dev->current_subdev; - - return v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id, - core, s_ctrl, ctrl); -} - -/* - * vpfe_calculate_offsets : This function calculates buffers offset - * for top and bottom field - */ -static void vpfe_calculate_offsets(struct vpfe_device *vpfe_dev) -{ - struct v4l2_rect image_win; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_calculate_offsets\n"); - - ccdc_dev->hw_ops.get_image_window(&image_win); - vpfe_dev->field_off = image_win.height * image_win.width; -} - -/* vpfe_start_ccdc_capture: start streaming in ccdc/isif */ -static void vpfe_start_ccdc_capture(struct vpfe_device *vpfe_dev) -{ - ccdc_dev->hw_ops.enable(1); - if (ccdc_dev->hw_ops.enable_out_to_sdram) - ccdc_dev->hw_ops.enable_out_to_sdram(1); - vpfe_dev->started = 1; -} - -/* - * vpfe_streamon. Assume the DMA queue is not empty. - * application is expected to call QBUF before calling - * this ioctl. If not, driver returns error - */ -static int vpfe_streamon(struct file *file, void *priv, - enum v4l2_buf_type buf_type) -{ - struct vpfe_device *vpfe_dev = video_drvdata(file); - struct vpfe_fh *fh = file->private_data; - struct vpfe_subdev_info *sdinfo; - unsigned long addr; - int ret = 0; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_streamon\n"); - - if (V4L2_BUF_TYPE_VIDEO_CAPTURE != buf_type) { - v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf type\n"); - return -EINVAL; - } - - /* If file handle is not allowed IO, return error */ - if (!fh->io_allowed) { - v4l2_err(&vpfe_dev->v4l2_dev, "fh->io_allowed\n"); - return -EACCES; - } - - sdinfo = vpfe_dev->current_subdev; - ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id, - video, s_stream, 1); - - if (ret && (ret != -ENOIOCTLCMD)) { - v4l2_err(&vpfe_dev->v4l2_dev, "stream on failed in subdev\n"); - return -EINVAL; - } - - /* If buffer queue is empty, return error */ - if (list_empty(&vpfe_dev->buffer_queue.stream)) { - v4l2_err(&vpfe_dev->v4l2_dev, "buffer queue is empty\n"); - return -EIO; - } - - /* Call videobuf_streamon to start streaming * in videobuf */ - ret = videobuf_streamon(&vpfe_dev->buffer_queue); - if (ret) - return ret; - - - ret = mutex_lock_interruptible(&vpfe_dev->lock); - if (ret) - goto streamoff; - /* Get the next frame from the buffer queue */ - vpfe_dev->next_frm = list_entry(vpfe_dev->dma_queue.next, - struct videobuf_buffer, queue); - vpfe_dev->cur_frm = vpfe_dev->next_frm; - /* Remove buffer from the buffer queue */ - list_del(&vpfe_dev->cur_frm->queue); - /* Mark state of the current frame to active */ - vpfe_dev->cur_frm->state = VIDEOBUF_ACTIVE; - /* Initialize field_id and started member */ - vpfe_dev->field_id = 0; - addr = videobuf_to_dma_contig(vpfe_dev->cur_frm); - - /* Calculate field offset */ - vpfe_calculate_offsets(vpfe_dev); - - if (vpfe_attach_irq(vpfe_dev) < 0) { - v4l2_err(&vpfe_dev->v4l2_dev, - "Error in attaching interrupt handle\n"); - ret = -EFAULT; - goto unlock_out; - } - if (ccdc_dev->hw_ops.configure() < 0) { - v4l2_err(&vpfe_dev->v4l2_dev, - "Error in configuring ccdc\n"); - ret = -EINVAL; - goto unlock_out; - } - ccdc_dev->hw_ops.setfbaddr((unsigned long)(addr)); - vpfe_start_ccdc_capture(vpfe_dev); - mutex_unlock(&vpfe_dev->lock); - return ret; -unlock_out: - mutex_unlock(&vpfe_dev->lock); -streamoff: - ret = videobuf_streamoff(&vpfe_dev->buffer_queue); - return ret; -} - -static int vpfe_streamoff(struct file *file, void *priv, - enum v4l2_buf_type buf_type) -{ - struct vpfe_device *vpfe_dev = video_drvdata(file); - struct vpfe_fh *fh = file->private_data; - struct vpfe_subdev_info *sdinfo; - int ret = 0; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_streamoff\n"); - - if (V4L2_BUF_TYPE_VIDEO_CAPTURE != buf_type) { - v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf type\n"); - return -EINVAL; - } - - /* If io is allowed for this file handle, return error */ - if (!fh->io_allowed) { - v4l2_err(&vpfe_dev->v4l2_dev, "fh->io_allowed\n"); - return -EACCES; - } - - /* If streaming is not started, return error */ - if (!vpfe_dev->started) { - v4l2_err(&vpfe_dev->v4l2_dev, "device started\n"); - return -EINVAL; - } - - ret = mutex_lock_interruptible(&vpfe_dev->lock); - if (ret) - return ret; - - vpfe_stop_ccdc_capture(vpfe_dev); - vpfe_detach_irq(vpfe_dev); - - sdinfo = vpfe_dev->current_subdev; - ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id, - video, s_stream, 0); - - if (ret && (ret != -ENOIOCTLCMD)) - v4l2_err(&vpfe_dev->v4l2_dev, "stream off failed in subdev\n"); - ret = videobuf_streamoff(&vpfe_dev->buffer_queue); - mutex_unlock(&vpfe_dev->lock); - return ret; -} - -static int vpfe_cropcap(struct file *file, void *priv, - struct v4l2_cropcap *crop) -{ - struct vpfe_device *vpfe_dev = video_drvdata(file); - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_cropcap\n"); - - if (vpfe_dev->std_index >= ARRAY_SIZE(vpfe_standards)) - return -EINVAL; - - memset(crop, 0, sizeof(struct v4l2_cropcap)); - crop->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - crop->bounds.width = crop->defrect.width = - vpfe_standards[vpfe_dev->std_index].width; - crop->bounds.height = crop->defrect.height = - vpfe_standards[vpfe_dev->std_index].height; - crop->pixelaspect = vpfe_standards[vpfe_dev->std_index].pixelaspect; - return 0; -} - -static int vpfe_g_crop(struct file *file, void *priv, - struct v4l2_crop *crop) -{ - struct vpfe_device *vpfe_dev = video_drvdata(file); - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_g_crop\n"); - - crop->c = vpfe_dev->crop; - return 0; -} - -static int vpfe_s_crop(struct file *file, void *priv, - struct v4l2_crop *crop) -{ - struct vpfe_device *vpfe_dev = video_drvdata(file); - int ret = 0; - - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_crop\n"); - - if (vpfe_dev->started) { - /* make sure streaming is not started */ - v4l2_err(&vpfe_dev->v4l2_dev, - "Cannot change crop when streaming is ON\n"); - return -EBUSY; - } - - ret = mutex_lock_interruptible(&vpfe_dev->lock); - if (ret) - return ret; - - if (crop->c.top < 0 || crop->c.left < 0) { - v4l2_err(&vpfe_dev->v4l2_dev, - "doesn't support negative values for top & left\n"); - ret = -EINVAL; - goto unlock_out; - } - - /* adjust the width to 16 pixel boundry */ - crop->c.width = ((crop->c.width + 15) & ~0xf); - - /* make sure parameters are valid */ - if ((crop->c.left + crop->c.width > - vpfe_dev->std_info.active_pixels) || - (crop->c.top + crop->c.height > - vpfe_dev->std_info.active_lines)) { - v4l2_err(&vpfe_dev->v4l2_dev, "Error in S_CROP params\n"); - ret = -EINVAL; - goto unlock_out; - } - ccdc_dev->hw_ops.set_image_window(&crop->c); - vpfe_dev->fmt.fmt.pix.width = crop->c.width; - vpfe_dev->fmt.fmt.pix.height = crop->c.height; - vpfe_dev->fmt.fmt.pix.bytesperline = - ccdc_dev->hw_ops.get_line_length(); - vpfe_dev->fmt.fmt.pix.sizeimage = - vpfe_dev->fmt.fmt.pix.bytesperline * - vpfe_dev->fmt.fmt.pix.height; - vpfe_dev->crop = crop->c; -unlock_out: - mutex_unlock(&vpfe_dev->lock); - return ret; -} - - -static long vpfe_param_handler(struct file *file, void *priv, - int cmd, void *param) -{ - struct vpfe_device *vpfe_dev = video_drvdata(file); - int ret = 0; - - v4l2_dbg(2, debug, &vpfe_dev->v4l2_dev, "vpfe_param_handler\n"); - - if (vpfe_dev->started) { - /* only allowed if streaming is not started */ - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, - "device already started\n"); - return -EBUSY; - } - - ret = mutex_lock_interruptible(&vpfe_dev->lock); - if (ret) - return ret; - - switch (cmd) { - case VPFE_CMD_S_CCDC_RAW_PARAMS: - v4l2_warn(&vpfe_dev->v4l2_dev, - "VPFE_CMD_S_CCDC_RAW_PARAMS: experimental ioctl\n"); - if (ccdc_dev->hw_ops.set_params) { - ret = ccdc_dev->hw_ops.set_params(param); - if (ret) { - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, - "Error setting parameters in CCDC\n"); - goto unlock_out; - } - if (vpfe_get_ccdc_image_format(vpfe_dev, - &vpfe_dev->fmt) < 0) { - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, - "Invalid image format at CCDC\n"); - goto unlock_out; - } - } else { - ret = -EINVAL; - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, - "VPFE_CMD_S_CCDC_RAW_PARAMS not supported\n"); - } - break; - default: - ret = -EINVAL; - } -unlock_out: - mutex_unlock(&vpfe_dev->lock); - return ret; -} - - -/* vpfe capture ioctl operations */ -static const struct v4l2_ioctl_ops vpfe_ioctl_ops = { - .vidioc_querycap = vpfe_querycap, - .vidioc_g_fmt_vid_cap = vpfe_g_fmt_vid_cap, - .vidioc_enum_fmt_vid_cap = vpfe_enum_fmt_vid_cap, - .vidioc_s_fmt_vid_cap = vpfe_s_fmt_vid_cap, - .vidioc_try_fmt_vid_cap = vpfe_try_fmt_vid_cap, - .vidioc_enum_input = vpfe_enum_input, - .vidioc_g_input = vpfe_g_input, - .vidioc_s_input = vpfe_s_input, - .vidioc_querystd = vpfe_querystd, - .vidioc_s_std = vpfe_s_std, - .vidioc_g_std = vpfe_g_std, - .vidioc_queryctrl = vpfe_queryctrl, - .vidioc_g_ctrl = vpfe_g_ctrl, - .vidioc_s_ctrl = vpfe_s_ctrl, - .vidioc_reqbufs = vpfe_reqbufs, - .vidioc_querybuf = vpfe_querybuf, - .vidioc_qbuf = vpfe_qbuf, - .vidioc_dqbuf = vpfe_dqbuf, - .vidioc_streamon = vpfe_streamon, - .vidioc_streamoff = vpfe_streamoff, - .vidioc_cropcap = vpfe_cropcap, - .vidioc_g_crop = vpfe_g_crop, - .vidioc_s_crop = vpfe_s_crop, - .vidioc_default = vpfe_param_handler, -}; - -static struct vpfe_device *vpfe_initialize(void) -{ - struct vpfe_device *vpfe_dev; - - /* Default number of buffers should be 3 */ - if ((numbuffers > 0) && - (numbuffers < config_params.min_numbuffers)) - numbuffers = config_params.min_numbuffers; - - /* - * Set buffer size to min buffers size if invalid buffer size is - * given - */ - if (bufsize < config_params.min_bufsize) - bufsize = config_params.min_bufsize; - - config_params.numbuffers = numbuffers; - - if (numbuffers) - config_params.device_bufsize = bufsize; - - /* Allocate memory for device objects */ - vpfe_dev = kzalloc(sizeof(*vpfe_dev), GFP_KERNEL); - - return vpfe_dev; -} - -/* - * vpfe_probe : This function creates device entries by register - * itself to the V4L2 driver and initializes fields of each - * device objects - */ -static __init int vpfe_probe(struct platform_device *pdev) -{ - struct vpfe_subdev_info *sdinfo; - struct vpfe_config *vpfe_cfg; - struct resource *res1; - struct vpfe_device *vpfe_dev; - struct i2c_adapter *i2c_adap; - struct video_device *vfd; - int ret = -ENOMEM, i, j; - int num_subdevs = 0; - - /* Get the pointer to the device object */ - vpfe_dev = vpfe_initialize(); - - if (!vpfe_dev) { - v4l2_err(pdev->dev.driver, - "Failed to allocate memory for vpfe_dev\n"); - return ret; - } - - vpfe_dev->pdev = &pdev->dev; - - if (NULL == pdev->dev.platform_data) { - v4l2_err(pdev->dev.driver, "Unable to get vpfe config\n"); - ret = -ENODEV; - goto probe_free_dev_mem; - } - - vpfe_cfg = pdev->dev.platform_data; - vpfe_dev->cfg = vpfe_cfg; - if (NULL == vpfe_cfg->ccdc || - NULL == vpfe_cfg->card_name || - NULL == vpfe_cfg->sub_devs) { - v4l2_err(pdev->dev.driver, "null ptr in vpfe_cfg\n"); - ret = -ENOENT; - goto probe_free_dev_mem; - } - - /* Allocate memory for ccdc configuration */ - ccdc_cfg = kmalloc(sizeof(struct ccdc_config), GFP_KERNEL); - if (NULL == ccdc_cfg) { - v4l2_err(pdev->dev.driver, - "Memory allocation failed for ccdc_cfg\n"); - goto probe_free_lock; - } - - mutex_lock(&ccdc_lock); - - strncpy(ccdc_cfg->name, vpfe_cfg->ccdc, 32); - /* Get VINT0 irq resource */ - res1 = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (!res1) { - v4l2_err(pdev->dev.driver, - "Unable to get interrupt for VINT0\n"); - ret = -ENODEV; - goto probe_free_ccdc_cfg_mem; - } - vpfe_dev->ccdc_irq0 = res1->start; - - /* Get VINT1 irq resource */ - res1 = platform_get_resource(pdev, IORESOURCE_IRQ, 1); - if (!res1) { - v4l2_err(pdev->dev.driver, - "Unable to get interrupt for VINT1\n"); - ret = -ENODEV; - goto probe_free_ccdc_cfg_mem; - } - vpfe_dev->ccdc_irq1 = res1->start; - - ret = request_irq(vpfe_dev->ccdc_irq0, vpfe_isr, IRQF_DISABLED, - "vpfe_capture0", vpfe_dev); - - if (0 != ret) { - v4l2_err(pdev->dev.driver, "Unable to request interrupt\n"); - goto probe_free_ccdc_cfg_mem; - } - - /* Allocate memory for video device */ - vfd = video_device_alloc(); - if (NULL == vfd) { - ret = -ENOMEM; - v4l2_err(pdev->dev.driver, "Unable to alloc video device\n"); - goto probe_out_release_irq; - } - - /* Initialize field of video device */ - vfd->release = video_device_release; - vfd->fops = &vpfe_fops; - vfd->ioctl_ops = &vpfe_ioctl_ops; - vfd->tvnorms = 0; - vfd->current_norm = V4L2_STD_PAL; - vfd->v4l2_dev = &vpfe_dev->v4l2_dev; - snprintf(vfd->name, sizeof(vfd->name), - "%s_V%d.%d.%d", - CAPTURE_DRV_NAME, - (VPFE_CAPTURE_VERSION_CODE >> 16) & 0xff, - (VPFE_CAPTURE_VERSION_CODE >> 8) & 0xff, - (VPFE_CAPTURE_VERSION_CODE) & 0xff); - /* Set video_dev to the video device */ - vpfe_dev->video_dev = vfd; - - ret = v4l2_device_register(&pdev->dev, &vpfe_dev->v4l2_dev); - if (ret) { - v4l2_err(pdev->dev.driver, - "Unable to register v4l2 device.\n"); - goto probe_out_video_release; - } - v4l2_info(&vpfe_dev->v4l2_dev, "v4l2 device registered\n"); - spin_lock_init(&vpfe_dev->irqlock); - spin_lock_init(&vpfe_dev->dma_queue_lock); - mutex_init(&vpfe_dev->lock); - - /* Initialize field of the device objects */ - vpfe_dev->numbuffers = config_params.numbuffers; - - /* Initialize prio member of device object */ - v4l2_prio_init(&vpfe_dev->prio); - /* register video device */ - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, - "trying to register vpfe device.\n"); - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, - "video_dev=%x\n", (int)&vpfe_dev->video_dev); - vpfe_dev->fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - ret = video_register_device(vpfe_dev->video_dev, - VFL_TYPE_GRABBER, -1); - - if (ret) { - v4l2_err(pdev->dev.driver, - "Unable to register video device.\n"); - goto probe_out_v4l2_unregister; - } - - v4l2_info(&vpfe_dev->v4l2_dev, "video device registered\n"); - /* set the driver data in platform device */ - platform_set_drvdata(pdev, vpfe_dev); - /* set driver private data */ - video_set_drvdata(vpfe_dev->video_dev, vpfe_dev); - i2c_adap = i2c_get_adapter(vpfe_cfg->i2c_adapter_id); - num_subdevs = vpfe_cfg->num_subdevs; - vpfe_dev->sd = kmalloc(sizeof(struct v4l2_subdev *) * num_subdevs, - GFP_KERNEL); - if (NULL == vpfe_dev->sd) { - v4l2_err(&vpfe_dev->v4l2_dev, - "unable to allocate memory for subdevice pointers\n"); - ret = -ENOMEM; - goto probe_out_video_unregister; - } - - for (i = 0; i < num_subdevs; i++) { - struct v4l2_input *inps; - - sdinfo = &vpfe_cfg->sub_devs[i]; - - /* Load up the subdevice */ - vpfe_dev->sd[i] = - v4l2_i2c_new_subdev_board(&vpfe_dev->v4l2_dev, - i2c_adap, - NULL, - &sdinfo->board_info, - NULL); - if (vpfe_dev->sd[i]) { - v4l2_info(&vpfe_dev->v4l2_dev, - "v4l2 sub device %s registered\n", - sdinfo->name); - vpfe_dev->sd[i]->grp_id = sdinfo->grp_id; - /* update tvnorms from the sub devices */ - for (j = 0; j < sdinfo->num_inputs; j++) { - inps = &sdinfo->inputs[j]; - vfd->tvnorms |= inps->std; - } - } else { - v4l2_info(&vpfe_dev->v4l2_dev, - "v4l2 sub device %s register fails\n", - sdinfo->name); - goto probe_sd_out; - } - } - - /* set first sub device as current one */ - vpfe_dev->current_subdev = &vpfe_cfg->sub_devs[0]; - - /* We have at least one sub device to work with */ - mutex_unlock(&ccdc_lock); - return 0; - -probe_sd_out: - kfree(vpfe_dev->sd); -probe_out_video_unregister: - video_unregister_device(vpfe_dev->video_dev); -probe_out_v4l2_unregister: - v4l2_device_unregister(&vpfe_dev->v4l2_dev); -probe_out_video_release: - if (!video_is_registered(vpfe_dev->video_dev)) - video_device_release(vpfe_dev->video_dev); -probe_out_release_irq: - free_irq(vpfe_dev->ccdc_irq0, vpfe_dev); -probe_free_ccdc_cfg_mem: - kfree(ccdc_cfg); -probe_free_lock: - mutex_unlock(&ccdc_lock); -probe_free_dev_mem: - kfree(vpfe_dev); - return ret; -} - -/* - * vpfe_remove : It un-register device from V4L2 driver - */ -static int __devexit vpfe_remove(struct platform_device *pdev) -{ - struct vpfe_device *vpfe_dev = platform_get_drvdata(pdev); - - v4l2_info(pdev->dev.driver, "vpfe_remove\n"); - - free_irq(vpfe_dev->ccdc_irq0, vpfe_dev); - kfree(vpfe_dev->sd); - v4l2_device_unregister(&vpfe_dev->v4l2_dev); - video_unregister_device(vpfe_dev->video_dev); - kfree(vpfe_dev); - kfree(ccdc_cfg); - return 0; -} - -static int vpfe_suspend(struct device *dev) -{ - return 0; -} - -static int vpfe_resume(struct device *dev) -{ - return 0; -} - -static const struct dev_pm_ops vpfe_dev_pm_ops = { - .suspend = vpfe_suspend, - .resume = vpfe_resume, -}; - -static struct platform_driver vpfe_driver = { - .driver = { - .name = CAPTURE_DRV_NAME, - .owner = THIS_MODULE, - .pm = &vpfe_dev_pm_ops, - }, - .probe = vpfe_probe, - .remove = __devexit_p(vpfe_remove), -}; - -static __init int vpfe_init(void) -{ - printk(KERN_NOTICE "vpfe_init\n"); - /* Register driver to the kernel */ - return platform_driver_register(&vpfe_driver); -} - -/* - * vpfe_cleanup : This function un-registers device driver - */ -static void vpfe_cleanup(void) -{ - platform_driver_unregister(&vpfe_driver); -} - -module_init(vpfe_init); -module_exit(vpfe_cleanup); diff --git a/drivers/media/video/davinci/vpif.c b/drivers/media/video/davinci/vpif.c deleted file mode 100644 index 1f532e31cd4..00000000000 --- a/drivers/media/video/davinci/vpif.c +++ /dev/null @@ -1,296 +0,0 @@ -/* - * vpif - DM646x Video Port Interface driver - * VPIF is a receiver and transmitter for video data. It has two channels(0, 1) - * that receiveing video byte stream and two channels(2, 3) for video output. - * The hardware supports SDTV, HDTV formats, raw data capture. - * Currently, the driver supports NTSC and PAL standards. - * - * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/ - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation version 2. - * - * This program is distributed .as is. WITHOUT ANY WARRANTY of any - * kind, whether express or implied; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include <linux/init.h> -#include <linux/module.h> -#include <linux/platform_device.h> -#include <linux/spinlock.h> -#include <linux/kernel.h> -#include <linux/io.h> -#include <mach/hardware.h> - -#include "vpif.h" - -MODULE_DESCRIPTION("TI DaVinci Video Port Interface driver"); -MODULE_LICENSE("GPL"); - -#define VPIF_CH0_MAX_MODES (22) -#define VPIF_CH1_MAX_MODES (02) -#define VPIF_CH2_MAX_MODES (15) -#define VPIF_CH3_MAX_MODES (02) - -static resource_size_t res_len; -static struct resource *res; -spinlock_t vpif_lock; - -void __iomem *vpif_base; - -static inline void vpif_wr_bit(u32 reg, u32 bit, u32 val) -{ - if (val) - vpif_set_bit(reg, bit); - else - vpif_clr_bit(reg, bit); -} - -/* This structure is used to keep track of VPIF size register's offsets */ -struct vpif_registers { - u32 h_cfg, v_cfg_00, v_cfg_01, v_cfg_02, v_cfg, ch_ctrl; - u32 line_offset, vanc0_strt, vanc0_size, vanc1_strt; - u32 vanc1_size, width_mask, len_mask; - u8 max_modes; -}; - -static const struct vpif_registers vpifregs[VPIF_NUM_CHANNELS] = { - /* Channel0 */ - { - VPIF_CH0_H_CFG, VPIF_CH0_V_CFG_00, VPIF_CH0_V_CFG_01, - VPIF_CH0_V_CFG_02, VPIF_CH0_V_CFG_03, VPIF_CH0_CTRL, - VPIF_CH0_IMG_ADD_OFST, 0, 0, 0, 0, 0x1FFF, 0xFFF, - VPIF_CH0_MAX_MODES, - }, - /* Channel1 */ - { - VPIF_CH1_H_CFG, VPIF_CH1_V_CFG_00, VPIF_CH1_V_CFG_01, - VPIF_CH1_V_CFG_02, VPIF_CH1_V_CFG_03, VPIF_CH1_CTRL, - VPIF_CH1_IMG_ADD_OFST, 0, 0, 0, 0, 0x1FFF, 0xFFF, - VPIF_CH1_MAX_MODES, - }, - /* Channel2 */ - { - VPIF_CH2_H_CFG, VPIF_CH2_V_CFG_00, VPIF_CH2_V_CFG_01, - VPIF_CH2_V_CFG_02, VPIF_CH2_V_CFG_03, VPIF_CH2_CTRL, - VPIF_CH2_IMG_ADD_OFST, VPIF_CH2_VANC0_STRT, VPIF_CH2_VANC0_SIZE, - VPIF_CH2_VANC1_STRT, VPIF_CH2_VANC1_SIZE, 0x7FF, 0x7FF, - VPIF_CH2_MAX_MODES - }, - /* Channel3 */ - { - VPIF_CH3_H_CFG, VPIF_CH3_V_CFG_00, VPIF_CH3_V_CFG_01, - VPIF_CH3_V_CFG_02, VPIF_CH3_V_CFG_03, VPIF_CH3_CTRL, - VPIF_CH3_IMG_ADD_OFST, VPIF_CH3_VANC0_STRT, VPIF_CH3_VANC0_SIZE, - VPIF_CH3_VANC1_STRT, VPIF_CH3_VANC1_SIZE, 0x7FF, 0x7FF, - VPIF_CH3_MAX_MODES - }, -}; - -/* vpif_set_mode_info: - * This function is used to set horizontal and vertical config parameters - * As per the standard in the channel, configure the values of L1, L3, - * L5, L7 L9, L11 in VPIF Register , also write width and height - */ -static void vpif_set_mode_info(const struct vpif_channel_config_params *config, - u8 channel_id, u8 config_channel_id) -{ - u32 value; - - value = (config->eav2sav & vpifregs[config_channel_id].width_mask); - value <<= VPIF_CH_LEN_SHIFT; - value |= (config->sav2eav & vpifregs[config_channel_id].width_mask); - regw(value, vpifregs[channel_id].h_cfg); - - value = (config->l1 & vpifregs[config_channel_id].len_mask); - value <<= VPIF_CH_LEN_SHIFT; - value |= (config->l3 & vpifregs[config_channel_id].len_mask); - regw(value, vpifregs[channel_id].v_cfg_00); - - value = (config->l5 & vpifregs[config_channel_id].len_mask); - value <<= VPIF_CH_LEN_SHIFT; - value |= (config->l7 & vpifregs[config_channel_id].len_mask); - regw(value, vpifregs[channel_id].v_cfg_01); - - value = (config->l9 & vpifregs[config_channel_id].len_mask); - value <<= VPIF_CH_LEN_SHIFT; - value |= (config->l11 & vpifregs[config_channel_id].len_mask); - regw(value, vpifregs[channel_id].v_cfg_02); - - value = (config->vsize & vpifregs[config_channel_id].len_mask); - regw(value, vpifregs[channel_id].v_cfg); -} - -/* config_vpif_params - * Function to set the parameters of a channel - * Mainly modifies the channel ciontrol register - * It sets frame format, yc mux mode - */ -static void config_vpif_params(struct vpif_params *vpifparams, - u8 channel_id, u8 found) -{ - const struct vpif_channel_config_params *config = &vpifparams->std_info; - u32 value, ch_nip, reg; - u8 start, end; - int i; - - start = channel_id; - end = channel_id + found; - - for (i = start; i < end; i++) { - reg = vpifregs[i].ch_ctrl; - if (channel_id < 2) - ch_nip = VPIF_CAPTURE_CH_NIP; - else - ch_nip = VPIF_DISPLAY_CH_NIP; - - vpif_wr_bit(reg, ch_nip, config->frm_fmt); - vpif_wr_bit(reg, VPIF_CH_YC_MUX_BIT, config->ycmux_mode); - vpif_wr_bit(reg, VPIF_CH_INPUT_FIELD_FRAME_BIT, - vpifparams->video_params.storage_mode); - - /* Set raster scanning SDR Format */ - vpif_clr_bit(reg, VPIF_CH_SDR_FMT_BIT); - vpif_wr_bit(reg, VPIF_CH_DATA_MODE_BIT, config->capture_format); - - if (channel_id > 1) /* Set the Pixel enable bit */ - vpif_set_bit(reg, VPIF_DISPLAY_PIX_EN_BIT); - else if (config->capture_format) { - /* Set the polarity of various pins */ - vpif_wr_bit(reg, VPIF_CH_FID_POLARITY_BIT, - vpifparams->iface.fid_pol); - vpif_wr_bit(reg, VPIF_CH_V_VALID_POLARITY_BIT, - vpifparams->iface.vd_pol); - vpif_wr_bit(reg, VPIF_CH_H_VALID_POLARITY_BIT, - vpifparams->iface.hd_pol); - - value = regr(reg); - /* Set data width */ - value &= ((~(unsigned int)(0x3)) << - VPIF_CH_DATA_WIDTH_BIT); - value |= ((vpifparams->params.data_sz) << - VPIF_CH_DATA_WIDTH_BIT); - regw(value, reg); - } - - /* Write the pitch in the driver */ - regw((vpifparams->video_params.hpitch), - vpifregs[i].line_offset); - } -} - -/* vpif_set_video_params - * This function is used to set video parameters in VPIF register - */ -int vpif_set_video_params(struct vpif_params *vpifparams, u8 channel_id) -{ - const struct vpif_channel_config_params *config = &vpifparams->std_info; - int found = 1; - - vpif_set_mode_info(config, channel_id, channel_id); - if (!config->ycmux_mode) { - /* YC are on separate channels (HDTV formats) */ - vpif_set_mode_info(config, channel_id + 1, channel_id); - found = 2; - } - - config_vpif_params(vpifparams, channel_id, found); - - regw(0x80, VPIF_REQ_SIZE); - regw(0x01, VPIF_EMULATION_CTRL); - - return found; -} -EXPORT_SYMBOL(vpif_set_video_params); - -void vpif_set_vbi_display_params(struct vpif_vbi_params *vbiparams, - u8 channel_id) -{ - u32 value; - - value = 0x3F8 & (vbiparams->hstart0); - value |= 0x3FFFFFF & ((vbiparams->vstart0) << 16); - regw(value, vpifregs[channel_id].vanc0_strt); - - value = 0x3F8 & (vbiparams->hstart1); - value |= 0x3FFFFFF & ((vbiparams->vstart1) << 16); - regw(value, vpifregs[channel_id].vanc1_strt); - - value = 0x3F8 & (vbiparams->hsize0); - value |= 0x3FFFFFF & ((vbiparams->vsize0) << 16); - regw(value, vpifregs[channel_id].vanc0_size); - - value = 0x3F8 & (vbiparams->hsize1); - value |= 0x3FFFFFF & ((vbiparams->vsize1) << 16); - regw(value, vpifregs[channel_id].vanc1_size); - -} -EXPORT_SYMBOL(vpif_set_vbi_display_params); - -int vpif_channel_getfid(u8 channel_id) -{ - return (regr(vpifregs[channel_id].ch_ctrl) & VPIF_CH_FID_MASK) - >> VPIF_CH_FID_SHIFT; -} -EXPORT_SYMBOL(vpif_channel_getfid); - -static int __init vpif_probe(struct platform_device *pdev) -{ - int status = 0; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) - return -ENOENT; - - res_len = res->end - res->start + 1; - - res = request_mem_region(res->start, res_len, res->name); - if (!res) - return -EBUSY; - - vpif_base = ioremap(res->start, res_len); - if (!vpif_base) { - status = -EBUSY; - goto fail; - } - - spin_lock_init(&vpif_lock); - dev_info(&pdev->dev, "vpif probe success\n"); - return 0; - -fail: - release_mem_region(res->start, res_len); - return status; -} - -static int __devexit vpif_remove(struct platform_device *pdev) -{ - iounmap(vpif_base); - release_mem_region(res->start, res_len); - return 0; -} - -static struct platform_driver vpif_driver = { - .driver = { - .name = "vpif", - .owner = THIS_MODULE, - }, - .remove = __devexit_p(vpif_remove), - .probe = vpif_probe, -}; - -static void vpif_exit(void) -{ - platform_driver_unregister(&vpif_driver); -} - -static int __init vpif_init(void) -{ - return platform_driver_register(&vpif_driver); -} -subsys_initcall(vpif_init); -module_exit(vpif_exit); - diff --git a/drivers/media/video/davinci/vpif.h b/drivers/media/video/davinci/vpif.h deleted file mode 100644 index 188841b476e..00000000000 --- a/drivers/media/video/davinci/vpif.h +++ /dev/null @@ -1,642 +0,0 @@ -/* - * VPIF header file - * - * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/ - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation version 2. - * - * This program is distributed .as is. WITHOUT ANY WARRANTY of any - * kind, whether express or implied; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef VPIF_H -#define VPIF_H - -#include <linux/io.h> -#include <linux/videodev2.h> -#include <mach/hardware.h> -#include <mach/dm646x.h> - -/* Maximum channel allowed */ -#define VPIF_NUM_CHANNELS (4) -#define VPIF_CAPTURE_NUM_CHANNELS (2) -#define VPIF_DISPLAY_NUM_CHANNELS (2) - -/* Macros to read/write registers */ -extern void __iomem *vpif_base; -extern spinlock_t vpif_lock; - -#define regr(reg) readl((reg) + vpif_base) -#define regw(value, reg) writel(value, (reg + vpif_base)) - -/* Register Addresss Offsets */ -#define VPIF_PID (0x0000) -#define VPIF_CH0_CTRL (0x0004) -#define VPIF_CH1_CTRL (0x0008) -#define VPIF_CH2_CTRL (0x000C) -#define VPIF_CH3_CTRL (0x0010) - -#define VPIF_INTEN (0x0020) -#define VPIF_INTEN_SET (0x0024) -#define VPIF_INTEN_CLR (0x0028) -#define VPIF_STATUS (0x002C) -#define VPIF_STATUS_CLR (0x0030) -#define VPIF_EMULATION_CTRL (0x0034) -#define VPIF_REQ_SIZE (0x0038) - -#define VPIF_CH0_TOP_STRT_ADD_LUMA (0x0040) -#define VPIF_CH0_BTM_STRT_ADD_LUMA (0x0044) -#define VPIF_CH0_TOP_STRT_ADD_CHROMA (0x0048) -#define VPIF_CH0_BTM_STRT_ADD_CHROMA (0x004c) -#define VPIF_CH0_TOP_STRT_ADD_HANC (0x0050) -#define VPIF_CH0_BTM_STRT_ADD_HANC (0x0054) -#define VPIF_CH0_TOP_STRT_ADD_VANC (0x0058) -#define VPIF_CH0_BTM_STRT_ADD_VANC (0x005c) -#define VPIF_CH0_SP_CFG (0x0060) -#define VPIF_CH0_IMG_ADD_OFST (0x0064) -#define VPIF_CH0_HANC_ADD_OFST (0x0068) -#define VPIF_CH0_H_CFG (0x006c) -#define VPIF_CH0_V_CFG_00 (0x0070) -#define VPIF_CH0_V_CFG_01 (0x0074) -#define VPIF_CH0_V_CFG_02 (0x0078) -#define VPIF_CH0_V_CFG_03 (0x007c) - -#define VPIF_CH1_TOP_STRT_ADD_LUMA (0x0080) -#define VPIF_CH1_BTM_STRT_ADD_LUMA (0x0084) -#define VPIF_CH1_TOP_STRT_ADD_CHROMA (0x0088) -#define VPIF_CH1_BTM_STRT_ADD_CHROMA (0x008c) -#define VPIF_CH1_TOP_STRT_ADD_HANC (0x0090) -#define VPIF_CH1_BTM_STRT_ADD_HANC (0x0094) -#define VPIF_CH1_TOP_STRT_ADD_VANC (0x0098) -#define VPIF_CH1_BTM_STRT_ADD_VANC (0x009c) -#define VPIF_CH1_SP_CFG (0x00a0) -#define VPIF_CH1_IMG_ADD_OFST (0x00a4) -#define VPIF_CH1_HANC_ADD_OFST (0x00a8) -#define VPIF_CH1_H_CFG (0x00ac) -#define VPIF_CH1_V_CFG_00 (0x00b0) -#define VPIF_CH1_V_CFG_01 (0x00b4) -#define VPIF_CH1_V_CFG_02 (0x00b8) -#define VPIF_CH1_V_CFG_03 (0x00bc) - -#define VPIF_CH2_TOP_STRT_ADD_LUMA (0x00c0) -#define VPIF_CH2_BTM_STRT_ADD_LUMA (0x00c4) -#define VPIF_CH2_TOP_STRT_ADD_CHROMA (0x00c8) -#define VPIF_CH2_BTM_STRT_ADD_CHROMA (0x00cc) -#define VPIF_CH2_TOP_STRT_ADD_HANC (0x00d0) -#define VPIF_CH2_BTM_STRT_ADD_HANC (0x00d4) -#define VPIF_CH2_TOP_STRT_ADD_VANC (0x00d8) -#define VPIF_CH2_BTM_STRT_ADD_VANC (0x00dc) -#define VPIF_CH2_SP_CFG (0x00e0) -#define VPIF_CH2_IMG_ADD_OFST (0x00e4) -#define VPIF_CH2_HANC_ADD_OFST (0x00e8) -#define VPIF_CH2_H_CFG (0x00ec) -#define VPIF_CH2_V_CFG_00 (0x00f0) -#define VPIF_CH2_V_CFG_01 (0x00f4) -#define VPIF_CH2_V_CFG_02 (0x00f8) -#define VPIF_CH2_V_CFG_03 (0x00fc) -#define VPIF_CH2_HANC0_STRT (0x0100) -#define VPIF_CH2_HANC0_SIZE (0x0104) -#define VPIF_CH2_HANC1_STRT (0x0108) -#define VPIF_CH2_HANC1_SIZE (0x010c) -#define VPIF_CH2_VANC0_STRT (0x0110) -#define VPIF_CH2_VANC0_SIZE (0x0114) -#define VPIF_CH2_VANC1_STRT (0x0118) -#define VPIF_CH2_VANC1_SIZE (0x011c) - -#define VPIF_CH3_TOP_STRT_ADD_LUMA (0x0140) -#define VPIF_CH3_BTM_STRT_ADD_LUMA (0x0144) -#define VPIF_CH3_TOP_STRT_ADD_CHROMA (0x0148) -#define VPIF_CH3_BTM_STRT_ADD_CHROMA (0x014c) -#define VPIF_CH3_TOP_STRT_ADD_HANC (0x0150) -#define VPIF_CH3_BTM_STRT_ADD_HANC (0x0154) -#define VPIF_CH3_TOP_STRT_ADD_VANC (0x0158) -#define VPIF_CH3_BTM_STRT_ADD_VANC (0x015c) -#define VPIF_CH3_SP_CFG (0x0160) -#define VPIF_CH3_IMG_ADD_OFST (0x0164) -#define VPIF_CH3_HANC_ADD_OFST (0x0168) -#define VPIF_CH3_H_CFG (0x016c) -#define VPIF_CH3_V_CFG_00 (0x0170) -#define VPIF_CH3_V_CFG_01 (0x0174) -#define VPIF_CH3_V_CFG_02 (0x0178) -#define VPIF_CH3_V_CFG_03 (0x017c) -#define VPIF_CH3_HANC0_STRT (0x0180) -#define VPIF_CH3_HANC0_SIZE (0x0184) -#define VPIF_CH3_HANC1_STRT (0x0188) -#define VPIF_CH3_HANC1_SIZE (0x018c) -#define VPIF_CH3_VANC0_STRT (0x0190) -#define VPIF_CH3_VANC0_SIZE (0x0194) -#define VPIF_CH3_VANC1_STRT (0x0198) -#define VPIF_CH3_VANC1_SIZE (0x019c) - -#define VPIF_IODFT_CTRL (0x01c0) - -/* Functions for bit Manipulation */ -static inline void vpif_set_bit(u32 reg, u32 bit) -{ - regw((regr(reg)) | (0x01 << bit), reg); -} - -static inline void vpif_clr_bit(u32 reg, u32 bit) -{ - regw(((regr(reg)) & ~(0x01 << bit)), reg); -} - -/* Macro for Generating mask */ -#ifdef GENERATE_MASK -#undef GENERATE_MASK -#endif - -#define GENERATE_MASK(bits, pos) \ - ((((0xFFFFFFFF) << (32 - bits)) >> (32 - bits)) << pos) - -/* Bit positions in the channel control registers */ -#define VPIF_CH_DATA_MODE_BIT (2) -#define VPIF_CH_YC_MUX_BIT (3) -#define VPIF_CH_SDR_FMT_BIT (4) -#define VPIF_CH_HANC_EN_BIT (8) -#define VPIF_CH_VANC_EN_BIT (9) - -#define VPIF_CAPTURE_CH_NIP (10) -#define VPIF_DISPLAY_CH_NIP (11) - -#define VPIF_DISPLAY_PIX_EN_BIT (10) - -#define VPIF_CH_INPUT_FIELD_FRAME_BIT (12) - -#define VPIF_CH_FID_POLARITY_BIT (15) -#define VPIF_CH_V_VALID_POLARITY_BIT (14) -#define VPIF_CH_H_VALID_POLARITY_BIT (13) -#define VPIF_CH_DATA_WIDTH_BIT (28) - -#define VPIF_CH_CLK_EDGE_CTRL_BIT (31) - -/* Mask various length */ -#define VPIF_CH_EAVSAV_MASK GENERATE_MASK(13, 0) -#define VPIF_CH_LEN_MASK GENERATE_MASK(12, 0) -#define VPIF_CH_WIDTH_MASK GENERATE_MASK(13, 0) -#define VPIF_CH_LEN_SHIFT (16) - -/* VPIF masks for registers */ -#define VPIF_REQ_SIZE_MASK (0x1ff) - -/* bit posotion of interrupt vpif_ch_intr register */ -#define VPIF_INTEN_FRAME_CH0 (0x00000001) -#define VPIF_INTEN_FRAME_CH1 (0x00000002) -#define VPIF_INTEN_FRAME_CH2 (0x00000004) -#define VPIF_INTEN_FRAME_CH3 (0x00000008) - -/* bit position of clock and channel enable in vpif_chn_ctrl register */ - -#define VPIF_CH0_CLK_EN (0x00000002) -#define VPIF_CH0_EN (0x00000001) -#define VPIF_CH1_CLK_EN (0x00000002) -#define VPIF_CH1_EN (0x00000001) -#define VPIF_CH2_CLK_EN (0x00000002) -#define VPIF_CH2_EN (0x00000001) -#define VPIF_CH3_CLK_EN (0x00000002) -#define VPIF_CH3_EN (0x00000001) -#define VPIF_CH_CLK_EN (0x00000002) -#define VPIF_CH_EN (0x00000001) - -#define VPIF_INT_TOP (0x00) -#define VPIF_INT_BOTTOM (0x01) -#define VPIF_INT_BOTH (0x02) - -#define VPIF_CH0_INT_CTRL_SHIFT (6) -#define VPIF_CH1_INT_CTRL_SHIFT (6) -#define VPIF_CH2_INT_CTRL_SHIFT (6) -#define VPIF_CH3_INT_CTRL_SHIFT (6) -#define VPIF_CH_INT_CTRL_SHIFT (6) - -/* enabled interrupt on both the fields on vpid_ch0_ctrl register */ -#define channel0_intr_assert() (regw((regr(VPIF_CH0_CTRL)|\ - (VPIF_INT_BOTH << VPIF_CH0_INT_CTRL_SHIFT)), VPIF_CH0_CTRL)) - -/* enabled interrupt on both the fields on vpid_ch1_ctrl register */ -#define channel1_intr_assert() (regw((regr(VPIF_CH1_CTRL)|\ - (VPIF_INT_BOTH << VPIF_CH1_INT_CTRL_SHIFT)), VPIF_CH1_CTRL)) - -/* enabled interrupt on both the fields on vpid_ch0_ctrl register */ -#define channel2_intr_assert() (regw((regr(VPIF_CH2_CTRL)|\ - (VPIF_INT_BOTH << VPIF_CH2_INT_CTRL_SHIFT)), VPIF_CH2_CTRL)) - -/* enabled interrupt on both the fields on vpid_ch1_ctrl register */ -#define channel3_intr_assert() (regw((regr(VPIF_CH3_CTRL)|\ - (VPIF_INT_BOTH << VPIF_CH3_INT_CTRL_SHIFT)), VPIF_CH3_CTRL)) - -#define VPIF_CH_FID_MASK (0x20) -#define VPIF_CH_FID_SHIFT (5) - -#define VPIF_NTSC_VBI_START_FIELD0 (1) -#define VPIF_NTSC_VBI_START_FIELD1 (263) -#define VPIF_PAL_VBI_START_FIELD0 (624) -#define VPIF_PAL_VBI_START_FIELD1 (311) - -#define VPIF_NTSC_HBI_START_FIELD0 (1) -#define VPIF_NTSC_HBI_START_FIELD1 (263) -#define VPIF_PAL_HBI_START_FIELD0 (624) -#define VPIF_PAL_HBI_START_FIELD1 (311) - -#define VPIF_NTSC_VBI_COUNT_FIELD0 (20) -#define VPIF_NTSC_VBI_COUNT_FIELD1 (19) -#define VPIF_PAL_VBI_COUNT_FIELD0 (24) -#define VPIF_PAL_VBI_COUNT_FIELD1 (25) - -#define VPIF_NTSC_HBI_COUNT_FIELD0 (263) -#define VPIF_NTSC_HBI_COUNT_FIELD1 (262) -#define VPIF_PAL_HBI_COUNT_FIELD0 (312) -#define VPIF_PAL_HBI_COUNT_FIELD1 (313) - -#define VPIF_NTSC_VBI_SAMPLES_PER_LINE (720) -#define VPIF_PAL_VBI_SAMPLES_PER_LINE (720) -#define VPIF_NTSC_HBI_SAMPLES_PER_LINE (268) -#define VPIF_PAL_HBI_SAMPLES_PER_LINE (280) - -#define VPIF_CH_VANC_EN (0x20) -#define VPIF_DMA_REQ_SIZE (0x080) -#define VPIF_EMULATION_DISABLE (0x01) - -extern u8 irq_vpif_capture_channel[VPIF_NUM_CHANNELS]; - -/* inline function to enable/disable channel0 */ -static inline void enable_channel0(int enable) -{ - if (enable) - regw((regr(VPIF_CH0_CTRL) | (VPIF_CH0_EN)), VPIF_CH0_CTRL); - else - regw((regr(VPIF_CH0_CTRL) & (~VPIF_CH0_EN)), VPIF_CH0_CTRL); -} - -/* inline function to enable/disable channel1 */ -static inline void enable_channel1(int enable) -{ - if (enable) - regw((regr(VPIF_CH1_CTRL) | (VPIF_CH1_EN)), VPIF_CH1_CTRL); - else - regw((regr(VPIF_CH1_CTRL) & (~VPIF_CH1_EN)), VPIF_CH1_CTRL); -} - -/* inline function to enable interrupt for channel0 */ -static inline void channel0_intr_enable(int enable) -{ - unsigned long flags; - - spin_lock_irqsave(&vpif_lock, flags); - - if (enable) { - regw((regr(VPIF_INTEN) | 0x10), VPIF_INTEN); - regw((regr(VPIF_INTEN_SET) | 0x10), VPIF_INTEN_SET); - - regw((regr(VPIF_INTEN) | VPIF_INTEN_FRAME_CH0), VPIF_INTEN); - regw((regr(VPIF_INTEN_SET) | VPIF_INTEN_FRAME_CH0), - VPIF_INTEN_SET); - } else { - regw((regr(VPIF_INTEN) & (~VPIF_INTEN_FRAME_CH0)), VPIF_INTEN); - regw((regr(VPIF_INTEN_SET) | VPIF_INTEN_FRAME_CH0), - VPIF_INTEN_SET); - } - spin_unlock_irqrestore(&vpif_lock, flags); -} - -/* inline function to enable interrupt for channel1 */ -static inline void channel1_intr_enable(int enable) -{ - unsigned long flags; - - spin_lock_irqsave(&vpif_lock, flags); - - if (enable) { - regw((regr(VPIF_INTEN) | 0x10), VPIF_INTEN); - regw((regr(VPIF_INTEN_SET) | 0x10), VPIF_INTEN_SET); - - regw((regr(VPIF_INTEN) | VPIF_INTEN_FRAME_CH1), VPIF_INTEN); - regw((regr(VPIF_INTEN_SET) | VPIF_INTEN_FRAME_CH1), - VPIF_INTEN_SET); - } else { - regw((regr(VPIF_INTEN) & (~VPIF_INTEN_FRAME_CH1)), VPIF_INTEN); - regw((regr(VPIF_INTEN_SET) | VPIF_INTEN_FRAME_CH1), - VPIF_INTEN_SET); - } - spin_unlock_irqrestore(&vpif_lock, flags); -} - -/* inline function to set buffer addresses in case of Y/C non mux mode */ -static inline void ch0_set_videobuf_addr_yc_nmux(unsigned long top_strt_luma, - unsigned long btm_strt_luma, - unsigned long top_strt_chroma, - unsigned long btm_strt_chroma) -{ - regw(top_strt_luma, VPIF_CH0_TOP_STRT_ADD_LUMA); - regw(btm_strt_luma, VPIF_CH0_BTM_STRT_ADD_LUMA); - regw(top_strt_chroma, VPIF_CH1_TOP_STRT_ADD_CHROMA); - regw(btm_strt_chroma, VPIF_CH1_BTM_STRT_ADD_CHROMA); -} - -/* inline function to set buffer addresses in VPIF registers for video data */ -static inline void ch0_set_videobuf_addr(unsigned long top_strt_luma, - unsigned long btm_strt_luma, - unsigned long top_strt_chroma, - unsigned long btm_strt_chroma) -{ - regw(top_strt_luma, VPIF_CH0_TOP_STRT_ADD_LUMA); - regw(btm_strt_luma, VPIF_CH0_BTM_STRT_ADD_LUMA); - regw(top_strt_chroma, VPIF_CH0_TOP_STRT_ADD_CHROMA); - regw(btm_strt_chroma, VPIF_CH0_BTM_STRT_ADD_CHROMA); -} - -static inline void ch1_set_videobuf_addr(unsigned long top_strt_luma, - unsigned long btm_strt_luma, - unsigned long top_strt_chroma, - unsigned long btm_strt_chroma) -{ - - regw(top_strt_luma, VPIF_CH1_TOP_STRT_ADD_LUMA); - regw(btm_strt_luma, VPIF_CH1_BTM_STRT_ADD_LUMA); - regw(top_strt_chroma, VPIF_CH1_TOP_STRT_ADD_CHROMA); - regw(btm_strt_chroma, VPIF_CH1_BTM_STRT_ADD_CHROMA); -} - -static inline void ch0_set_vbi_addr(unsigned long top_vbi, - unsigned long btm_vbi, unsigned long a, unsigned long b) -{ - regw(top_vbi, VPIF_CH0_TOP_STRT_ADD_VANC); - regw(btm_vbi, VPIF_CH0_BTM_STRT_ADD_VANC); -} - -static inline void ch0_set_hbi_addr(unsigned long top_vbi, - unsigned long btm_vbi, unsigned long a, unsigned long b) -{ - regw(top_vbi, VPIF_CH0_TOP_STRT_ADD_HANC); - regw(btm_vbi, VPIF_CH0_BTM_STRT_ADD_HANC); -} - -static inline void ch1_set_vbi_addr(unsigned long top_vbi, - unsigned long btm_vbi, unsigned long a, unsigned long b) -{ - regw(top_vbi, VPIF_CH1_TOP_STRT_ADD_VANC); - regw(btm_vbi, VPIF_CH1_BTM_STRT_ADD_VANC); -} - -static inline void ch1_set_hbi_addr(unsigned long top_vbi, - unsigned long btm_vbi, unsigned long a, unsigned long b) -{ - regw(top_vbi, VPIF_CH1_TOP_STRT_ADD_HANC); - regw(btm_vbi, VPIF_CH1_BTM_STRT_ADD_HANC); -} - -/* Inline function to enable raw vbi in the given channel */ -static inline void disable_raw_feature(u8 channel_id, u8 index) -{ - u32 ctrl_reg; - if (0 == channel_id) - ctrl_reg = VPIF_CH0_CTRL; - else - ctrl_reg = VPIF_CH1_CTRL; - - if (1 == index) - vpif_clr_bit(ctrl_reg, VPIF_CH_VANC_EN_BIT); - else - vpif_clr_bit(ctrl_reg, VPIF_CH_HANC_EN_BIT); -} - -static inline void enable_raw_feature(u8 channel_id, u8 index) -{ - u32 ctrl_reg; - if (0 == channel_id) - ctrl_reg = VPIF_CH0_CTRL; - else - ctrl_reg = VPIF_CH1_CTRL; - - if (1 == index) - vpif_set_bit(ctrl_reg, VPIF_CH_VANC_EN_BIT); - else - vpif_set_bit(ctrl_reg, VPIF_CH_HANC_EN_BIT); -} - -/* inline function to enable/disable channel2 */ -static inline void enable_channel2(int enable) -{ - if (enable) { - regw((regr(VPIF_CH2_CTRL) | (VPIF_CH2_CLK_EN)), VPIF_CH2_CTRL); - regw((regr(VPIF_CH2_CTRL) | (VPIF_CH2_EN)), VPIF_CH2_CTRL); - } else { - regw((regr(VPIF_CH2_CTRL) & (~VPIF_CH2_CLK_EN)), VPIF_CH2_CTRL); - regw((regr(VPIF_CH2_CTRL) & (~VPIF_CH2_EN)), VPIF_CH2_CTRL); - } -} - -/* inline function to enable/disable channel3 */ -static inline void enable_channel3(int enable) -{ - if (enable) { - regw((regr(VPIF_CH3_CTRL) | (VPIF_CH3_CLK_EN)), VPIF_CH3_CTRL); - regw((regr(VPIF_CH3_CTRL) | (VPIF_CH3_EN)), VPIF_CH3_CTRL); - } else { - regw((regr(VPIF_CH3_CTRL) & (~VPIF_CH3_CLK_EN)), VPIF_CH3_CTRL); - regw((regr(VPIF_CH3_CTRL) & (~VPIF_CH3_EN)), VPIF_CH3_CTRL); - } -} - -/* inline function to enable interrupt for channel2 */ -static inline void channel2_intr_enable(int enable) -{ - unsigned long flags; - - spin_lock_irqsave(&vpif_lock, flags); - - if (enable) { - regw((regr(VPIF_INTEN) | 0x10), VPIF_INTEN); - regw((regr(VPIF_INTEN_SET) | 0x10), VPIF_INTEN_SET); - regw((regr(VPIF_INTEN) | VPIF_INTEN_FRAME_CH2), VPIF_INTEN); - regw((regr(VPIF_INTEN_SET) | VPIF_INTEN_FRAME_CH2), - VPIF_INTEN_SET); - } else { - regw((regr(VPIF_INTEN) & (~VPIF_INTEN_FRAME_CH2)), VPIF_INTEN); - regw((regr(VPIF_INTEN_SET) | VPIF_INTEN_FRAME_CH2), - VPIF_INTEN_SET); - } - spin_unlock_irqrestore(&vpif_lock, flags); -} - -/* inline function to enable interrupt for channel3 */ -static inline void channel3_intr_enable(int enable) -{ - unsigned long flags; - - spin_lock_irqsave(&vpif_lock, flags); - - if (enable) { - regw((regr(VPIF_INTEN) | 0x10), VPIF_INTEN); - regw((regr(VPIF_INTEN_SET) | 0x10), VPIF_INTEN_SET); - - regw((regr(VPIF_INTEN) | VPIF_INTEN_FRAME_CH3), VPIF_INTEN); - regw((regr(VPIF_INTEN_SET) | VPIF_INTEN_FRAME_CH3), - VPIF_INTEN_SET); - } else { - regw((regr(VPIF_INTEN) & (~VPIF_INTEN_FRAME_CH3)), VPIF_INTEN); - regw((regr(VPIF_INTEN_SET) | VPIF_INTEN_FRAME_CH3), - VPIF_INTEN_SET); - } - spin_unlock_irqrestore(&vpif_lock, flags); -} - -/* inline function to enable raw vbi data for channel2 */ -static inline void channel2_raw_enable(int enable, u8 index) -{ - u32 mask; - - if (1 == index) - mask = VPIF_CH_VANC_EN_BIT; - else - mask = VPIF_CH_HANC_EN_BIT; - - if (enable) - vpif_set_bit(VPIF_CH2_CTRL, mask); - else - vpif_clr_bit(VPIF_CH2_CTRL, mask); -} - -/* inline function to enable raw vbi data for channel3*/ -static inline void channel3_raw_enable(int enable, u8 index) -{ - u32 mask; - - if (1 == index) - mask = VPIF_CH_VANC_EN_BIT; - else - mask = VPIF_CH_HANC_EN_BIT; - - if (enable) - vpif_set_bit(VPIF_CH3_CTRL, mask); - else - vpif_clr_bit(VPIF_CH3_CTRL, mask); -} - -/* inline function to set buffer addresses in case of Y/C non mux mode */ -static inline void ch2_set_videobuf_addr_yc_nmux(unsigned long top_strt_luma, - unsigned long btm_strt_luma, - unsigned long top_strt_chroma, - unsigned long btm_strt_chroma) -{ - regw(top_strt_luma, VPIF_CH2_TOP_STRT_ADD_LUMA); - regw(btm_strt_luma, VPIF_CH2_BTM_STRT_ADD_LUMA); - regw(top_strt_chroma, VPIF_CH3_TOP_STRT_ADD_CHROMA); - regw(btm_strt_chroma, VPIF_CH3_BTM_STRT_ADD_CHROMA); -} - -/* inline function to set buffer addresses in VPIF registers for video data */ -static inline void ch2_set_videobuf_addr(unsigned long top_strt_luma, - unsigned long btm_strt_luma, - unsigned long top_strt_chroma, - unsigned long btm_strt_chroma) -{ - regw(top_strt_luma, VPIF_CH2_TOP_STRT_ADD_LUMA); - regw(btm_strt_luma, VPIF_CH2_BTM_STRT_ADD_LUMA); - regw(top_strt_chroma, VPIF_CH2_TOP_STRT_ADD_CHROMA); - regw(btm_strt_chroma, VPIF_CH2_BTM_STRT_ADD_CHROMA); -} - -static inline void ch3_set_videobuf_addr(unsigned long top_strt_luma, - unsigned long btm_strt_luma, - unsigned long top_strt_chroma, - unsigned long btm_strt_chroma) -{ - regw(top_strt_luma, VPIF_CH3_TOP_STRT_ADD_LUMA); - regw(btm_strt_luma, VPIF_CH3_BTM_STRT_ADD_LUMA); - regw(top_strt_chroma, VPIF_CH3_TOP_STRT_ADD_CHROMA); - regw(btm_strt_chroma, VPIF_CH3_BTM_STRT_ADD_CHROMA); -} - -/* inline function to set buffer addresses in VPIF registers for vbi data */ -static inline void ch2_set_vbi_addr(unsigned long top_strt_luma, - unsigned long btm_strt_luma, - unsigned long top_strt_chroma, - unsigned long btm_strt_chroma) -{ - regw(top_strt_luma, VPIF_CH2_TOP_STRT_ADD_VANC); - regw(btm_strt_luma, VPIF_CH2_BTM_STRT_ADD_VANC); -} - -static inline void ch3_set_vbi_addr(unsigned long top_strt_luma, - unsigned long btm_strt_luma, - unsigned long top_strt_chroma, - unsigned long btm_strt_chroma) -{ - regw(top_strt_luma, VPIF_CH3_TOP_STRT_ADD_VANC); - regw(btm_strt_luma, VPIF_CH3_BTM_STRT_ADD_VANC); -} - -#define VPIF_MAX_NAME (30) - -/* This structure will store size parameters as per the mode selected by user */ -struct vpif_channel_config_params { - char name[VPIF_MAX_NAME]; /* Name of the mode */ - u16 width; /* Indicates width of the image */ - u16 height; /* Indicates height of the image */ - u8 fps; - u8 frm_fmt; /* Indicates whether this is interlaced - * or progressive format */ - u8 ycmux_mode; /* Indicates whether this mode requires - * single or two channels */ - u16 eav2sav; /* length of sav 2 eav */ - u16 sav2eav; /* length of sav 2 eav */ - u16 l1, l3, l5, l7, l9, l11; /* Other parameter configurations */ - u16 vsize; /* Vertical size of the image */ - u8 capture_format; /* Indicates whether capture format - * is in BT or in CCD/CMOS */ - u8 vbi_supported; /* Indicates whether this mode - * supports capturing vbi or not */ - u8 hd_sd; - v4l2_std_id stdid; -}; - -struct vpif_video_params; -struct vpif_params; -struct vpif_vbi_params; - -int vpif_set_video_params(struct vpif_params *vpifparams, u8 channel_id); -void vpif_set_vbi_display_params(struct vpif_vbi_params *vbiparams, - u8 channel_id); -int vpif_channel_getfid(u8 channel_id); - -enum data_size { - _8BITS = 0, - _10BITS, - _12BITS, -}; - -/* Structure for vpif parameters for raw vbi data */ -struct vpif_vbi_params { - __u32 hstart0; /* Horizontal start of raw vbi data for first field */ - __u32 vstart0; /* Vertical start of raw vbi data for first field */ - __u32 hsize0; /* Horizontal size of raw vbi data for first field */ - __u32 vsize0; /* Vertical size of raw vbi data for first field */ - __u32 hstart1; /* Horizontal start of raw vbi data for second field */ - __u32 vstart1; /* Vertical start of raw vbi data for second field */ - __u32 hsize1; /* Horizontal size of raw vbi data for second field */ - __u32 vsize1; /* Vertical size of raw vbi data for second field */ -}; - -/* structure for vpif parameters */ -struct vpif_video_params { - __u8 storage_mode; /* Indicates field or frame mode */ - unsigned long hpitch; - v4l2_std_id stdid; -}; - -struct vpif_params { - struct vpif_interface iface; - struct vpif_video_params video_params; - struct vpif_channel_config_params std_info; - union param { - struct vpif_vbi_params vbi_params; - enum data_size data_sz; - } params; -}; - -#endif /* End of #ifndef VPIF_H */ - diff --git a/drivers/media/video/davinci/vpif_capture.c b/drivers/media/video/davinci/vpif_capture.c deleted file mode 100644 index 6ac6acd1635..00000000000 --- a/drivers/media/video/davinci/vpif_capture.c +++ /dev/null @@ -1,2169 +0,0 @@ -/* - * Copyright (C) 2009 Texas Instruments Inc - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * TODO : add support for VBI & HBI data service - * add static buffer allocation - */ -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/module.h> -#include <linux/errno.h> -#include <linux/fs.h> -#include <linux/mm.h> -#include <linux/interrupt.h> -#include <linux/workqueue.h> -#include <linux/string.h> -#include <linux/videodev2.h> -#include <linux/wait.h> -#include <linux/time.h> -#include <linux/i2c.h> -#include <linux/platform_device.h> -#include <linux/io.h> -#include <linux/version.h> -#include <linux/slab.h> -#include <media/v4l2-device.h> -#include <media/v4l2-ioctl.h> - -#include "vpif_capture.h" -#include "vpif.h" - -MODULE_DESCRIPTION("TI DaVinci VPIF Capture driver"); -MODULE_LICENSE("GPL"); - -#define vpif_err(fmt, arg...) v4l2_err(&vpif_obj.v4l2_dev, fmt, ## arg) -#define vpif_dbg(level, debug, fmt, arg...) \ - v4l2_dbg(level, debug, &vpif_obj.v4l2_dev, fmt, ## arg) - -static int debug = 1; -static u32 ch0_numbuffers = 3; -static u32 ch1_numbuffers = 3; -static u32 ch0_bufsize = 1920 * 1080 * 2; -static u32 ch1_bufsize = 720 * 576 * 2; - -module_param(debug, int, 0644); -module_param(ch0_numbuffers, uint, S_IRUGO); -module_param(ch1_numbuffers, uint, S_IRUGO); -module_param(ch0_bufsize, uint, S_IRUGO); -module_param(ch1_bufsize, uint, S_IRUGO); - -MODULE_PARM_DESC(debug, "Debug level 0-1"); -MODULE_PARM_DESC(ch2_numbuffers, "Channel0 buffer count (default:3)"); -MODULE_PARM_DESC(ch3_numbuffers, "Channel1 buffer count (default:3)"); -MODULE_PARM_DESC(ch2_bufsize, "Channel0 buffer size (default:1920 x 1080 x 2)"); -MODULE_PARM_DESC(ch3_bufsize, "Channel1 buffer size (default:720 x 576 x 2)"); - -static struct vpif_config_params config_params = { - .min_numbuffers = 3, - .numbuffers[0] = 3, - .numbuffers[1] = 3, - .min_bufsize[0] = 720 * 480 * 2, - .min_bufsize[1] = 720 * 480 * 2, - .channel_bufsize[0] = 1920 * 1080 * 2, - .channel_bufsize[1] = 720 * 576 * 2, -}; - -/* global variables */ -static struct vpif_device vpif_obj = { {NULL} }; -static struct device *vpif_dev; - -/** - * ch_params: video standard configuration parameters for vpif - */ -static const struct vpif_channel_config_params ch_params[] = { - { - "NTSC_M", 720, 480, 30, 0, 1, 268, 1440, 1, 23, 263, 266, - 286, 525, 525, 0, 1, 0, V4L2_STD_525_60, - }, - { - "PAL_BDGHIK", 720, 576, 25, 0, 1, 280, 1440, 1, 23, 311, 313, - 336, 624, 625, 0, 1, 0, V4L2_STD_625_50, - }, -}; - -/** - * vpif_uservirt_to_phys : translate user/virtual address to phy address - * @virtp: user/virtual address - * - * This inline function is used to convert user space virtual address to - * physical address. - */ -static inline u32 vpif_uservirt_to_phys(u32 virtp) -{ - unsigned long physp = 0; - struct mm_struct *mm = current->mm; - struct vm_area_struct *vma; - - vma = find_vma(mm, virtp); - - /* For kernel direct-mapped memory, take the easy way */ - if (virtp >= PAGE_OFFSET) - physp = virt_to_phys((void *)virtp); - else if (vma && (vma->vm_flags & VM_IO) && (vma->vm_pgoff)) - /** - * this will catch, kernel-allocated, mmaped-to-usermode - * addresses - */ - physp = (vma->vm_pgoff << PAGE_SHIFT) + (virtp - vma->vm_start); - else { - /* otherwise, use get_user_pages() for general userland pages */ - int res, nr_pages = 1; - struct page *pages; - - down_read(¤t->mm->mmap_sem); - - res = get_user_pages(current, current->mm, - virtp, nr_pages, 1, 0, &pages, NULL); - up_read(¤t->mm->mmap_sem); - - if (res == nr_pages) - physp = __pa(page_address(&pages[0]) + - (virtp & ~PAGE_MASK)); - else { - vpif_err("get_user_pages failed\n"); - return 0; - } - } - return physp; -} - -/** - * buffer_prepare : callback function for buffer prepare - * @q : buffer queue ptr - * @vb: ptr to video buffer - * @field: field info - * - * This is the callback function for buffer prepare when videobuf_qbuf() - * function is called. The buffer is prepared and user space virtual address - * or user address is converted into physical address - */ -static int vpif_buffer_prepare(struct videobuf_queue *q, - struct videobuf_buffer *vb, - enum v4l2_field field) -{ - /* Get the file handle object and channel object */ - struct vpif_fh *fh = q->priv_data; - struct channel_obj *ch = fh->channel; - struct common_obj *common; - unsigned long addr; - - - vpif_dbg(2, debug, "vpif_buffer_prepare\n"); - - common = &ch->common[VPIF_VIDEO_INDEX]; - - /* If buffer is not initialized, initialize it */ - if (VIDEOBUF_NEEDS_INIT == vb->state) { - vb->width = common->width; - vb->height = common->height; - vb->size = vb->width * vb->height; - vb->field = field; - } - vb->state = VIDEOBUF_PREPARED; - /** - * if user pointer memory mechanism is used, get the physical - * address of the buffer - */ - if (V4L2_MEMORY_USERPTR == common->memory) { - if (0 == vb->baddr) { - vpif_dbg(1, debug, "buffer address is 0\n"); - return -EINVAL; - - } - vb->boff = vpif_uservirt_to_phys(vb->baddr); - if (!IS_ALIGNED(vb->boff, 8)) - goto exit; - } - - addr = vb->boff; - if (q->streaming) { - if (!IS_ALIGNED((addr + common->ytop_off), 8) || - !IS_ALIGNED((addr + common->ybtm_off), 8) || - !IS_ALIGNED((addr + common->ctop_off), 8) || - !IS_ALIGNED((addr + common->cbtm_off), 8)) - goto exit; - } - return 0; -exit: - vpif_dbg(1, debug, "buffer_prepare:offset is not aligned to 8 bytes\n"); - return -EINVAL; -} - -/** - * vpif_buffer_setup : Callback function for buffer setup. - * @q: buffer queue ptr - * @count: number of buffers - * @size: size of the buffer - * - * This callback function is called when reqbuf() is called to adjust - * the buffer count and buffer size - */ -static int vpif_buffer_setup(struct videobuf_queue *q, unsigned int *count, - unsigned int *size) -{ - /* Get the file handle object and channel object */ - struct vpif_fh *fh = q->priv_data; - struct channel_obj *ch = fh->channel; - struct common_obj *common; - - common = &ch->common[VPIF_VIDEO_INDEX]; - - vpif_dbg(2, debug, "vpif_buffer_setup\n"); - - /* If memory type is not mmap, return */ - if (V4L2_MEMORY_MMAP != common->memory) - return 0; - - /* Calculate the size of the buffer */ - *size = config_params.channel_bufsize[ch->channel_id]; - - if (*count < config_params.min_numbuffers) - *count = config_params.min_numbuffers; - return 0; -} - -/** - * vpif_buffer_queue : Callback function to add buffer to DMA queue - * @q: ptr to videobuf_queue - * @vb: ptr to videobuf_buffer - */ -static void vpif_buffer_queue(struct videobuf_queue *q, - struct videobuf_buffer *vb) -{ - /* Get the file handle object and channel object */ - struct vpif_fh *fh = q->priv_data; - struct channel_obj *ch = fh->channel; - struct common_obj *common; - - common = &ch->common[VPIF_VIDEO_INDEX]; - - vpif_dbg(2, debug, "vpif_buffer_queue\n"); - - /* add the buffer to the DMA queue */ - list_add_tail(&vb->queue, &common->dma_queue); - /* Change state of the buffer */ - vb->state = VIDEOBUF_QUEUED; -} - -/** - * vpif_buffer_release : Callback function to free buffer - * @q: buffer queue ptr - * @vb: ptr to video buffer - * - * This function is called from the videobuf layer to free memory - * allocated to the buffers - */ -static void vpif_buffer_release(struct videobuf_queue *q, - struct videobuf_buffer *vb) -{ - /* Get the file handle object and channel object */ - struct vpif_fh *fh = q->priv_data; - struct channel_obj *ch = fh->channel; - struct common_obj *common; - - common = &ch->common[VPIF_VIDEO_INDEX]; - - videobuf_dma_contig_free(q, vb); - vb->state = VIDEOBUF_NEEDS_INIT; -} - -static struct videobuf_queue_ops video_qops = { - .buf_setup = vpif_buffer_setup, - .buf_prepare = vpif_buffer_prepare, - .buf_queue = vpif_buffer_queue, - .buf_release = vpif_buffer_release, -}; - -static u8 channel_first_int[VPIF_NUMBER_OF_OBJECTS][2] = - { {1, 1} }; - -/** - * vpif_process_buffer_complete: process a completed buffer - * @common: ptr to common channel object - * - * This function time stamp the buffer and mark it as DONE. It also - * wake up any process waiting on the QUEUE and set the next buffer - * as current - */ -static void vpif_process_buffer_complete(struct common_obj *common) -{ - do_gettimeofday(&common->cur_frm->ts); - common->cur_frm->state = VIDEOBUF_DONE; - wake_up_interruptible(&common->cur_frm->done); - /* Make curFrm pointing to nextFrm */ - common->cur_frm = common->next_frm; -} - -/** - * vpif_schedule_next_buffer: set next buffer address for capture - * @common : ptr to common channel object - * - * This function will get next buffer from the dma queue and - * set the buffer address in the vpif register for capture. - * the buffer is marked active - */ -static void vpif_schedule_next_buffer(struct common_obj *common) -{ - unsigned long addr = 0; - - common->next_frm = list_entry(common->dma_queue.next, - struct videobuf_buffer, queue); - /* Remove that buffer from the buffer queue */ - list_del(&common->next_frm->queue); - common->next_frm->state = VIDEOBUF_ACTIVE; - if (V4L2_MEMORY_USERPTR == common->memory) - addr = common->next_frm->boff; - else - addr = videobuf_to_dma_contig(common->next_frm); - - /* Set top and bottom field addresses in VPIF registers */ - common->set_addr(addr + common->ytop_off, - addr + common->ybtm_off, - addr + common->ctop_off, - addr + common->cbtm_off); -} - -/** - * vpif_channel_isr : ISR handler for vpif capture - * @irq: irq number - * @dev_id: dev_id ptr - * - * It changes status of the captured buffer, takes next buffer from the queue - * and sets its address in VPIF registers - */ -static irqreturn_t vpif_channel_isr(int irq, void *dev_id) -{ - struct vpif_device *dev = &vpif_obj; - struct common_obj *common; - struct channel_obj *ch; - enum v4l2_field field; - int channel_id = 0; - int fid = -1, i; - - channel_id = *(int *)(dev_id); - ch = dev->dev[channel_id]; - - field = ch->common[VPIF_VIDEO_INDEX].fmt.fmt.pix.field; - - for (i = 0; i < VPIF_NUMBER_OF_OBJECTS; i++) { - common = &ch->common[i]; - /* skip If streaming is not started in this channel */ - if (0 == common->started) - continue; - - /* Check the field format */ - if (1 == ch->vpifparams.std_info.frm_fmt) { - /* Progressive mode */ - if (list_empty(&common->dma_queue)) - continue; - - if (!channel_first_int[i][channel_id]) - vpif_process_buffer_complete(common); - - channel_first_int[i][channel_id] = 0; - - vpif_schedule_next_buffer(common); - - - channel_first_int[i][channel_id] = 0; - } else { - /** - * Interlaced mode. If it is first interrupt, ignore - * it - */ - if (channel_first_int[i][channel_id]) { - channel_first_int[i][channel_id] = 0; - continue; - } - if (0 == i) { - ch->field_id ^= 1; - /* Get field id from VPIF registers */ - fid = vpif_channel_getfid(ch->channel_id); - if (fid != ch->field_id) { - /** - * If field id does not match stored - * field id, make them in sync - */ - if (0 == fid) - ch->field_id = fid; - return IRQ_HANDLED; - } - } - /* device field id and local field id are in sync */ - if (0 == fid) { - /* this is even field */ - if (common->cur_frm == common->next_frm) - continue; - - /* mark the current buffer as done */ - vpif_process_buffer_complete(common); - } else if (1 == fid) { - /* odd field */ - if (list_empty(&common->dma_queue) || - (common->cur_frm != common->next_frm)) - continue; - - vpif_schedule_next_buffer(common); - } - } - } - return IRQ_HANDLED; -} - -/** - * vpif_update_std_info() - update standard related info - * @ch: ptr to channel object - * - * For a given standard selected by application, update values - * in the device data structures - */ -static int vpif_update_std_info(struct channel_obj *ch) -{ - struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; - struct vpif_params *vpifparams = &ch->vpifparams; - const struct vpif_channel_config_params *config; - struct vpif_channel_config_params *std_info; - struct video_obj *vid_ch = &ch->video; - int index; - - vpif_dbg(2, debug, "vpif_update_std_info\n"); - - std_info = &vpifparams->std_info; - - for (index = 0; index < ARRAY_SIZE(ch_params); index++) { - config = &ch_params[index]; - if (config->stdid & vid_ch->stdid) { - memcpy(std_info, config, sizeof(*config)); - break; - } - } - - /* standard not found */ - if (index == ARRAY_SIZE(ch_params)) - return -EINVAL; - - common->fmt.fmt.pix.width = std_info->width; - common->width = std_info->width; - common->fmt.fmt.pix.height = std_info->height; - common->height = std_info->height; - common->fmt.fmt.pix.bytesperline = std_info->width; - vpifparams->video_params.hpitch = std_info->width; - vpifparams->video_params.storage_mode = std_info->frm_fmt; - return 0; -} - -/** - * vpif_calculate_offsets : This function calculates buffers offsets - * @ch : ptr to channel object - * - * This function calculates buffer offsets for Y and C in the top and - * bottom field - */ -static void vpif_calculate_offsets(struct channel_obj *ch) -{ - unsigned int hpitch, vpitch, sizeimage; - struct video_obj *vid_ch = &(ch->video); - struct vpif_params *vpifparams = &ch->vpifparams; - struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; - enum v4l2_field field = common->fmt.fmt.pix.field; - - vpif_dbg(2, debug, "vpif_calculate_offsets\n"); - - if (V4L2_FIELD_ANY == field) { - if (vpifparams->std_info.frm_fmt) - vid_ch->buf_field = V4L2_FIELD_NONE; - else - vid_ch->buf_field = V4L2_FIELD_INTERLACED; - } else - vid_ch->buf_field = common->fmt.fmt.pix.field; - - if (V4L2_MEMORY_USERPTR == common->memory) - sizeimage = common->fmt.fmt.pix.sizeimage; - else - sizeimage = config_params.channel_bufsize[ch->channel_id]; - - hpitch = common->fmt.fmt.pix.bytesperline; - vpitch = sizeimage / (hpitch * 2); - - if ((V4L2_FIELD_NONE == vid_ch->buf_field) || - (V4L2_FIELD_INTERLACED == vid_ch->buf_field)) { - /* Calculate offsets for Y top, Y Bottom, C top and C Bottom */ - common->ytop_off = 0; - common->ybtm_off = hpitch; - common->ctop_off = sizeimage / 2; - common->cbtm_off = sizeimage / 2 + hpitch; - } else if (V4L2_FIELD_SEQ_TB == vid_ch->buf_field) { - /* Calculate offsets for Y top, Y Bottom, C top and C Bottom */ - common->ytop_off = 0; - common->ybtm_off = sizeimage / 4; - common->ctop_off = sizeimage / 2; - common->cbtm_off = common->ctop_off + sizeimage / 4; - } else if (V4L2_FIELD_SEQ_BT == vid_ch->buf_field) { - /* Calculate offsets for Y top, Y Bottom, C top and C Bottom */ - common->ybtm_off = 0; - common->ytop_off = sizeimage / 4; - common->cbtm_off = sizeimage / 2; - common->ctop_off = common->cbtm_off + sizeimage / 4; - } - if ((V4L2_FIELD_NONE == vid_ch->buf_field) || - (V4L2_FIELD_INTERLACED == vid_ch->buf_field)) - vpifparams->video_params.storage_mode = 1; - else - vpifparams->video_params.storage_mode = 0; - - if (1 == vpifparams->std_info.frm_fmt) - vpifparams->video_params.hpitch = - common->fmt.fmt.pix.bytesperline; - else { - if ((field == V4L2_FIELD_ANY) - || (field == V4L2_FIELD_INTERLACED)) - vpifparams->video_params.hpitch = - common->fmt.fmt.pix.bytesperline * 2; - else - vpifparams->video_params.hpitch = - common->fmt.fmt.pix.bytesperline; - } - - ch->vpifparams.video_params.stdid = vpifparams->std_info.stdid; -} - -/** - * vpif_config_format: configure default frame format in the device - * ch : ptr to channel object - */ -static void vpif_config_format(struct channel_obj *ch) -{ - struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; - - vpif_dbg(2, debug, "vpif_config_format\n"); - - common->fmt.fmt.pix.field = V4L2_FIELD_ANY; - if (config_params.numbuffers[ch->channel_id] == 0) - common->memory = V4L2_MEMORY_USERPTR; - else - common->memory = V4L2_MEMORY_MMAP; - - common->fmt.fmt.pix.sizeimage - = config_params.channel_bufsize[ch->channel_id]; - - if (ch->vpifparams.iface.if_type == VPIF_IF_RAW_BAYER) - common->fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_SBGGR8; - else - common->fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUV422P; - common->fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; -} - -/** - * vpif_get_default_field() - Get default field type based on interface - * @vpif_params - ptr to vpif params - */ -static inline enum v4l2_field vpif_get_default_field( - struct vpif_interface *iface) -{ - return (iface->if_type == VPIF_IF_RAW_BAYER) ? V4L2_FIELD_NONE : - V4L2_FIELD_INTERLACED; -} - -/** - * vpif_check_format() - check given pixel format for compatibility - * @ch - channel ptr - * @pixfmt - Given pixel format - * @update - update the values as per hardware requirement - * - * Check the application pixel format for S_FMT and update the input - * values as per hardware limits for TRY_FMT. The default pixel and - * field format is selected based on interface type. - */ -static int vpif_check_format(struct channel_obj *ch, - struct v4l2_pix_format *pixfmt, - int update) -{ - struct common_obj *common = &(ch->common[VPIF_VIDEO_INDEX]); - struct vpif_params *vpif_params = &ch->vpifparams; - enum v4l2_field field = pixfmt->field; - u32 sizeimage, hpitch, vpitch; - int ret = -EINVAL; - - vpif_dbg(2, debug, "vpif_check_format\n"); - /** - * first check for the pixel format. If if_type is Raw bayer, - * only V4L2_PIX_FMT_SBGGR8 format is supported. Otherwise only - * V4L2_PIX_FMT_YUV422P is supported - */ - if (vpif_params->iface.if_type == VPIF_IF_RAW_BAYER) { - if (pixfmt->pixelformat != V4L2_PIX_FMT_SBGGR8) { - if (!update) { - vpif_dbg(2, debug, "invalid pix format\n"); - goto exit; - } - pixfmt->pixelformat = V4L2_PIX_FMT_SBGGR8; - } - } else { - if (pixfmt->pixelformat != V4L2_PIX_FMT_YUV422P) { - if (!update) { - vpif_dbg(2, debug, "invalid pixel format\n"); - goto exit; - } - pixfmt->pixelformat = V4L2_PIX_FMT_YUV422P; - } - } - - if (!(VPIF_VALID_FIELD(field))) { - if (!update) { - vpif_dbg(2, debug, "invalid field format\n"); - goto exit; - } - /** - * By default use FIELD_NONE for RAW Bayer capture - * and FIELD_INTERLACED for other interfaces - */ - field = vpif_get_default_field(&vpif_params->iface); - } else if (field == V4L2_FIELD_ANY) - /* unsupported field. Use default */ - field = vpif_get_default_field(&vpif_params->iface); - - /* validate the hpitch */ - hpitch = pixfmt->bytesperline; - if (hpitch < vpif_params->std_info.width) { - if (!update) { - vpif_dbg(2, debug, "invalid hpitch\n"); - goto exit; - } - hpitch = vpif_params->std_info.width; - } - - if (V4L2_MEMORY_USERPTR == common->memory) - sizeimage = pixfmt->sizeimage; - else - sizeimage = config_params.channel_bufsize[ch->channel_id]; - - vpitch = sizeimage / (hpitch * 2); - - /* validate the vpitch */ - if (vpitch < vpif_params->std_info.height) { - if (!update) { - vpif_dbg(2, debug, "Invalid vpitch\n"); - goto exit; - } - vpitch = vpif_params->std_info.height; - } - - /* Check for 8 byte alignment */ - if (!ALIGN(hpitch, 8)) { - if (!update) { - vpif_dbg(2, debug, "invalid pitch alignment\n"); - goto exit; - } - /* adjust to next 8 byte boundary */ - hpitch = (((hpitch + 7) / 8) * 8); - } - /* if update is set, modify the bytesperline and sizeimage */ - if (update) { - pixfmt->bytesperline = hpitch; - pixfmt->sizeimage = hpitch * vpitch * 2; - } - /** - * Image width and height is always based on current standard width and - * height - */ - pixfmt->width = common->fmt.fmt.pix.width; - pixfmt->height = common->fmt.fmt.pix.height; - return 0; -exit: - return ret; -} - -/** - * vpif_config_addr() - function to configure buffer address in vpif - * @ch - channel ptr - * @muxmode - channel mux mode - */ -static void vpif_config_addr(struct channel_obj *ch, int muxmode) -{ - struct common_obj *common; - - vpif_dbg(2, debug, "vpif_config_addr\n"); - - common = &(ch->common[VPIF_VIDEO_INDEX]); - - if (VPIF_CHANNEL1_VIDEO == ch->channel_id) - common->set_addr = ch1_set_videobuf_addr; - else if (2 == muxmode) - common->set_addr = ch0_set_videobuf_addr_yc_nmux; - else - common->set_addr = ch0_set_videobuf_addr; -} - -/** - * vpfe_mmap : It is used to map kernel space buffers into user spaces - * @filep: file pointer - * @vma: ptr to vm_area_struct - */ -static int vpif_mmap(struct file *filep, struct vm_area_struct *vma) -{ - /* Get the channel object and file handle object */ - struct vpif_fh *fh = filep->private_data; - struct channel_obj *ch = fh->channel; - struct common_obj *common = &(ch->common[VPIF_VIDEO_INDEX]); - - vpif_dbg(2, debug, "vpif_mmap\n"); - - return videobuf_mmap_mapper(&common->buffer_queue, vma); -} - -/** - * vpif_poll: It is used for select/poll system call - * @filep: file pointer - * @wait: poll table to wait - */ -static unsigned int vpif_poll(struct file *filep, poll_table * wait) -{ - struct vpif_fh *fh = filep->private_data; - struct channel_obj *channel = fh->channel; - struct common_obj *common = &(channel->common[VPIF_VIDEO_INDEX]); - - vpif_dbg(2, debug, "vpif_poll\n"); - - if (common->started) - return videobuf_poll_stream(filep, &common->buffer_queue, wait); - return 0; -} - -/** - * vpif_open : vpif open handler - * @filep: file ptr - * - * It creates object of file handle structure and stores it in private_data - * member of filepointer - */ -static int vpif_open(struct file *filep) -{ - struct vpif_capture_config *config = vpif_dev->platform_data; - struct video_device *vdev = video_devdata(filep); - struct common_obj *common; - struct video_obj *vid_ch; - struct channel_obj *ch; - struct vpif_fh *fh; - int i, ret = 0; - - vpif_dbg(2, debug, "vpif_open\n"); - - ch = video_get_drvdata(vdev); - - vid_ch = &ch->video; - common = &ch->common[VPIF_VIDEO_INDEX]; - - if (mutex_lock_interruptible(&common->lock)) - return -ERESTARTSYS; - - if (NULL == ch->curr_subdev_info) { - /** - * search through the sub device to see a registered - * sub device and make it as current sub device - */ - for (i = 0; i < config->subdev_count; i++) { - if (vpif_obj.sd[i]) { - /* the sub device is registered */ - ch->curr_subdev_info = &config->subdev_info[i]; - /* make first input as the current input */ - vid_ch->input_idx = 0; - break; - } - } - if (i == config->subdev_count) { - vpif_err("No sub device registered\n"); - ret = -ENOENT; - goto exit; - } - } - - /* Allocate memory for the file handle object */ - fh = kzalloc(sizeof(struct vpif_fh), GFP_KERNEL); - if (NULL == fh) { - vpif_err("unable to allocate memory for file handle object\n"); - ret = -ENOMEM; - goto exit; - } - - /* store pointer to fh in private_data member of filep */ - filep->private_data = fh; - fh->channel = ch; - fh->initialized = 0; - /* If decoder is not initialized. initialize it */ - if (!ch->initialized) { - fh->initialized = 1; - ch->initialized = 1; - memset(&(ch->vpifparams), 0, sizeof(struct vpif_params)); - } - /* Increment channel usrs counter */ - ch->usrs++; - /* Set io_allowed member to false */ - fh->io_allowed[VPIF_VIDEO_INDEX] = 0; - /* Initialize priority of this instance to default priority */ - fh->prio = V4L2_PRIORITY_UNSET; - v4l2_prio_open(&ch->prio, &fh->prio); -exit: - mutex_unlock(&common->lock); - return ret; -} - -/** - * vpif_release : function to clean up file close - * @filep: file pointer - * - * This function deletes buffer queue, frees the buffers and the vpfe file - * handle - */ -static int vpif_release(struct file *filep) -{ - struct vpif_fh *fh = filep->private_data; - struct channel_obj *ch = fh->channel; - struct common_obj *common; - - vpif_dbg(2, debug, "vpif_release\n"); - - common = &ch->common[VPIF_VIDEO_INDEX]; - - if (mutex_lock_interruptible(&common->lock)) - return -ERESTARTSYS; - - /* if this instance is doing IO */ - if (fh->io_allowed[VPIF_VIDEO_INDEX]) { - /* Reset io_usrs member of channel object */ - common->io_usrs = 0; - /* Disable channel as per its device type and channel id */ - if (VPIF_CHANNEL0_VIDEO == ch->channel_id) { - enable_channel0(0); - channel0_intr_enable(0); - } - if ((VPIF_CHANNEL1_VIDEO == ch->channel_id) || - (2 == common->started)) { - enable_channel1(0); - channel1_intr_enable(0); - } - common->started = 0; - /* Free buffers allocated */ - videobuf_queue_cancel(&common->buffer_queue); - videobuf_mmap_free(&common->buffer_queue); - } - - /* Decrement channel usrs counter */ - ch->usrs--; - - /* unlock mutex on channel object */ - mutex_unlock(&common->lock); - - /* Close the priority */ - v4l2_prio_close(&ch->prio, fh->prio); - - if (fh->initialized) - ch->initialized = 0; - - filep->private_data = NULL; - kfree(fh); - return 0; -} - -/** - * vpif_reqbufs() - request buffer handler - * @file: file ptr - * @priv: file handle - * @reqbuf: request buffer structure ptr - */ -static int vpif_reqbufs(struct file *file, void *priv, - struct v4l2_requestbuffers *reqbuf) -{ - struct vpif_fh *fh = priv; - struct channel_obj *ch = fh->channel; - struct common_obj *common; - u8 index = 0; - int ret = 0; - - vpif_dbg(2, debug, "vpif_reqbufs\n"); - - /** - * This file handle has not initialized the channel, - * It is not allowed to do settings - */ - if ((VPIF_CHANNEL0_VIDEO == ch->channel_id) - || (VPIF_CHANNEL1_VIDEO == ch->channel_id)) { - if (!fh->initialized) { - vpif_dbg(1, debug, "Channel Busy\n"); - return -EBUSY; - } - } - - if (V4L2_BUF_TYPE_VIDEO_CAPTURE != reqbuf->type) - return -EINVAL; - - index = VPIF_VIDEO_INDEX; - - common = &ch->common[index]; - - if (mutex_lock_interruptible(&common->lock)) - return -ERESTARTSYS; - - if (0 != common->io_usrs) { - ret = -EBUSY; - goto reqbuf_exit; - } - - /* Initialize videobuf queue as per the buffer type */ - videobuf_queue_dma_contig_init(&common->buffer_queue, - &video_qops, NULL, - &common->irqlock, - reqbuf->type, - common->fmt.fmt.pix.field, - sizeof(struct videobuf_buffer), fh, - NULL); - - /* Set io allowed member of file handle to TRUE */ - fh->io_allowed[index] = 1; - /* Increment io usrs member of channel object to 1 */ - common->io_usrs = 1; - /* Store type of memory requested in channel object */ - common->memory = reqbuf->memory; - INIT_LIST_HEAD(&common->dma_queue); - - /* Allocate buffers */ - ret = videobuf_reqbufs(&common->buffer_queue, reqbuf); - -reqbuf_exit: - mutex_unlock(&common->lock); - return ret; -} - -/** - * vpif_querybuf() - query buffer handler - * @file: file ptr - * @priv: file handle - * @buf: v4l2 buffer structure ptr - */ -static int vpif_querybuf(struct file *file, void *priv, - struct v4l2_buffer *buf) -{ - struct vpif_fh *fh = priv; - struct channel_obj *ch = fh->channel; - struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; - - vpif_dbg(2, debug, "vpif_querybuf\n"); - - if (common->fmt.type != buf->type) - return -EINVAL; - - if (common->memory != V4L2_MEMORY_MMAP) { - vpif_dbg(1, debug, "Invalid memory\n"); - return -EINVAL; - } - - return videobuf_querybuf(&common->buffer_queue, buf); -} - -/** - * vpif_qbuf() - query buffer handler - * @file: file ptr - * @priv: file handle - * @buf: v4l2 buffer structure ptr - */ -static int vpif_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) -{ - - struct vpif_fh *fh = priv; - struct channel_obj *ch = fh->channel; - struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; - struct v4l2_buffer tbuf = *buf; - struct videobuf_buffer *buf1; - unsigned long addr = 0; - unsigned long flags; - int ret = 0; - - vpif_dbg(2, debug, "vpif_qbuf\n"); - - if (common->fmt.type != tbuf.type) { - vpif_err("invalid buffer type\n"); - return -EINVAL; - } - - if (!fh->io_allowed[VPIF_VIDEO_INDEX]) { - vpif_err("fh io not allowed \n"); - return -EACCES; - } - - if (!(list_empty(&common->dma_queue)) || - (common->cur_frm != common->next_frm) || - !common->started || - (common->started && (0 == ch->field_id))) - return videobuf_qbuf(&common->buffer_queue, buf); - - /* bufferqueue is empty store buffer address in VPIF registers */ - mutex_lock(&common->buffer_queue.vb_lock); - buf1 = common->buffer_queue.bufs[tbuf.index]; - - if ((buf1->state == VIDEOBUF_QUEUED) || - (buf1->state == VIDEOBUF_ACTIVE)) { - vpif_err("invalid state\n"); - goto qbuf_exit; - } - - switch (buf1->memory) { - case V4L2_MEMORY_MMAP: - if (buf1->baddr == 0) - goto qbuf_exit; - break; - - case V4L2_MEMORY_USERPTR: - if (tbuf.length < buf1->bsize) - goto qbuf_exit; - - if ((VIDEOBUF_NEEDS_INIT != buf1->state) - && (buf1->baddr != tbuf.m.userptr)) { - vpif_buffer_release(&common->buffer_queue, buf1); - buf1->baddr = tbuf.m.userptr; - } - break; - - default: - goto qbuf_exit; - } - - local_irq_save(flags); - ret = vpif_buffer_prepare(&common->buffer_queue, buf1, - common->buffer_queue.field); - if (ret < 0) { - local_irq_restore(flags); - goto qbuf_exit; - } - - buf1->state = VIDEOBUF_ACTIVE; - - if (V4L2_MEMORY_USERPTR == common->memory) - addr = buf1->boff; - else - addr = videobuf_to_dma_contig(buf1); - - common->next_frm = buf1; - common->set_addr(addr + common->ytop_off, - addr + common->ybtm_off, - addr + common->ctop_off, - addr + common->cbtm_off); - - local_irq_restore(flags); - list_add_tail(&buf1->stream, &common->buffer_queue.stream); - mutex_unlock(&common->buffer_queue.vb_lock); - return 0; - -qbuf_exit: - mutex_unlock(&common->buffer_queue.vb_lock); - return -EINVAL; -} - -/** - * vpif_dqbuf() - query buffer handler - * @file: file ptr - * @priv: file handle - * @buf: v4l2 buffer structure ptr - */ -static int vpif_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) -{ - struct vpif_fh *fh = priv; - struct channel_obj *ch = fh->channel; - struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; - - vpif_dbg(2, debug, "vpif_dqbuf\n"); - - return videobuf_dqbuf(&common->buffer_queue, buf, - file->f_flags & O_NONBLOCK); -} - -/** - * vpif_streamon() - streamon handler - * @file: file ptr - * @priv: file handle - * @buftype: v4l2 buffer type - */ -static int vpif_streamon(struct file *file, void *priv, - enum v4l2_buf_type buftype) -{ - - struct vpif_capture_config *config = vpif_dev->platform_data; - struct vpif_fh *fh = priv; - struct channel_obj *ch = fh->channel; - struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; - struct channel_obj *oth_ch = vpif_obj.dev[!ch->channel_id]; - struct vpif_params *vpif; - unsigned long addr = 0; - int ret = 0; - - vpif_dbg(2, debug, "vpif_streamon\n"); - - vpif = &ch->vpifparams; - - if (buftype != V4L2_BUF_TYPE_VIDEO_CAPTURE) { - vpif_dbg(1, debug, "buffer type not supported\n"); - return -EINVAL; - } - - /* If file handle is not allowed IO, return error */ - if (!fh->io_allowed[VPIF_VIDEO_INDEX]) { - vpif_dbg(1, debug, "io not allowed\n"); - return -EACCES; - } - - /* If Streaming is already started, return error */ - if (common->started) { - vpif_dbg(1, debug, "channel->started\n"); - return -EBUSY; - } - - if ((ch->channel_id == VPIF_CHANNEL0_VIDEO && - oth_ch->common[VPIF_VIDEO_INDEX].started && - vpif->std_info.ycmux_mode == 0) || - ((ch->channel_id == VPIF_CHANNEL1_VIDEO) && - (2 == oth_ch->common[VPIF_VIDEO_INDEX].started))) { - vpif_dbg(1, debug, "other channel is being used\n"); - return -EBUSY; - } - - ret = vpif_check_format(ch, &common->fmt.fmt.pix, 0); - if (ret) - return ret; - - /* Enable streamon on the sub device */ - ret = v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], video, - s_stream, 1); - - if (ret && (ret != -ENOIOCTLCMD)) { - vpif_dbg(1, debug, "stream on failed in subdev\n"); - return ret; - } - - /* Call videobuf_streamon to start streaming in videobuf */ - ret = videobuf_streamon(&common->buffer_queue); - if (ret) { - vpif_dbg(1, debug, "videobuf_streamon\n"); - return ret; - } - - if (mutex_lock_interruptible(&common->lock)) { - ret = -ERESTARTSYS; - goto streamoff_exit; - } - - /* If buffer queue is empty, return error */ - if (list_empty(&common->dma_queue)) { - vpif_dbg(1, debug, "buffer queue is empty\n"); - ret = -EIO; - goto exit; - } - - /* Get the next frame from the buffer queue */ - common->cur_frm = list_entry(common->dma_queue.next, - struct videobuf_buffer, queue); - common->next_frm = common->cur_frm; - - /* Remove buffer from the buffer queue */ - list_del(&common->cur_frm->queue); - /* Mark state of the current frame to active */ - common->cur_frm->state = VIDEOBUF_ACTIVE; - /* Initialize field_id and started member */ - ch->field_id = 0; - common->started = 1; - - if (V4L2_MEMORY_USERPTR == common->memory) - addr = common->cur_frm->boff; - else - addr = videobuf_to_dma_contig(common->cur_frm); - - /* Calculate the offset for Y and C data in the buffer */ - vpif_calculate_offsets(ch); - - if ((vpif->std_info.frm_fmt && - ((common->fmt.fmt.pix.field != V4L2_FIELD_NONE) && - (common->fmt.fmt.pix.field != V4L2_FIELD_ANY))) || - (!vpif->std_info.frm_fmt && - (common->fmt.fmt.pix.field == V4L2_FIELD_NONE))) { - vpif_dbg(1, debug, "conflict in field format and std format\n"); - ret = -EINVAL; - goto exit; - } - - /* configure 1 or 2 channel mode */ - ret = config->setup_input_channel_mode(vpif->std_info.ycmux_mode); - - if (ret < 0) { - vpif_dbg(1, debug, "can't set vpif channel mode\n"); - goto exit; - } - - /* Call vpif_set_params function to set the parameters and addresses */ - ret = vpif_set_video_params(vpif, ch->channel_id); - - if (ret < 0) { - vpif_dbg(1, debug, "can't set video params\n"); - goto exit; - } - - common->started = ret; - vpif_config_addr(ch, ret); - - common->set_addr(addr + common->ytop_off, - addr + common->ybtm_off, - addr + common->ctop_off, - addr + common->cbtm_off); - - /** - * Set interrupt for both the fields in VPIF Register enable channel in - * VPIF register - */ - if ((VPIF_CHANNEL0_VIDEO == ch->channel_id)) { - channel0_intr_assert(); - channel0_intr_enable(1); - enable_channel0(1); - } - if ((VPIF_CHANNEL1_VIDEO == ch->channel_id) || - (common->started == 2)) { - channel1_intr_assert(); - channel1_intr_enable(1); - enable_channel1(1); - } - channel_first_int[VPIF_VIDEO_INDEX][ch->channel_id] = 1; - mutex_unlock(&common->lock); - return ret; - -exit: - mutex_unlock(&common->lock); -streamoff_exit: - ret = videobuf_streamoff(&common->buffer_queue); - return ret; -} - -/** - * vpif_streamoff() - streamoff handler - * @file: file ptr - * @priv: file handle - * @buftype: v4l2 buffer type - */ -static int vpif_streamoff(struct file *file, void *priv, - enum v4l2_buf_type buftype) -{ - - struct vpif_fh *fh = priv; - struct channel_obj *ch = fh->channel; - struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; - int ret; - - vpif_dbg(2, debug, "vpif_streamoff\n"); - - if (buftype != V4L2_BUF_TYPE_VIDEO_CAPTURE) { - vpif_dbg(1, debug, "buffer type not supported\n"); - return -EINVAL; - } - - /* If io is allowed for this file handle, return error */ - if (!fh->io_allowed[VPIF_VIDEO_INDEX]) { - vpif_dbg(1, debug, "io not allowed\n"); - return -EACCES; - } - - /* If streaming is not started, return error */ - if (!common->started) { - vpif_dbg(1, debug, "channel->started\n"); - return -EINVAL; - } - - if (mutex_lock_interruptible(&common->lock)) - return -ERESTARTSYS; - - /* disable channel */ - if (VPIF_CHANNEL0_VIDEO == ch->channel_id) { - enable_channel0(0); - channel0_intr_enable(0); - } else { - enable_channel1(0); - channel1_intr_enable(0); - } - - common->started = 0; - - ret = v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], video, - s_stream, 0); - - if (ret && (ret != -ENOIOCTLCMD)) - vpif_dbg(1, debug, "stream off failed in subdev\n"); - - mutex_unlock(&common->lock); - - return videobuf_streamoff(&common->buffer_queue); -} - -/** - * vpif_map_sub_device_to_input() - Maps sub device to input - * @ch - ptr to channel - * @config - ptr to capture configuration - * @input_index - Given input index from application - * @sub_device_index - index into sd table - * - * lookup the sub device information for a given input index. - * we report all the inputs to application. inputs table also - * has sub device name for the each input - */ -static struct vpif_subdev_info *vpif_map_sub_device_to_input( - struct channel_obj *ch, - struct vpif_capture_config *vpif_cfg, - int input_index, - int *sub_device_index) -{ - struct vpif_capture_chan_config *chan_cfg; - struct vpif_subdev_info *subdev_info = NULL; - const char *subdev_name = NULL; - int i; - - vpif_dbg(2, debug, "vpif_map_sub_device_to_input\n"); - - chan_cfg = &vpif_cfg->chan_config[ch->channel_id]; - - /** - * search through the inputs to find the sub device supporting - * the input - */ - for (i = 0; i < chan_cfg->input_count; i++) { - /* For each sub device, loop through input */ - if (i == input_index) { - subdev_name = chan_cfg->inputs[i].subdev_name; - break; - } - } - - /* if reached maximum. return null */ - if (i == chan_cfg->input_count || (NULL == subdev_name)) - return subdev_info; - - /* loop through the sub device list to get the sub device info */ - for (i = 0; i < vpif_cfg->subdev_count; i++) { - subdev_info = &vpif_cfg->subdev_info[i]; - if (!strcmp(subdev_info->name, subdev_name)) - break; - } - - if (i == vpif_cfg->subdev_count) - return subdev_info; - - /* check if the sub device is registered */ - if (NULL == vpif_obj.sd[i]) - return NULL; - - *sub_device_index = i; - return subdev_info; -} - -/** - * vpif_querystd() - querystd handler - * @file: file ptr - * @priv: file handle - * @std_id: ptr to std id - * - * This function is called to detect standard at the selected input - */ -static int vpif_querystd(struct file *file, void *priv, v4l2_std_id *std_id) -{ - struct vpif_fh *fh = priv; - struct channel_obj *ch = fh->channel; - struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; - int ret = 0; - - vpif_dbg(2, debug, "vpif_querystd\n"); - - if (mutex_lock_interruptible(&common->lock)) - return -ERESTARTSYS; - - /* Call querystd function of decoder device */ - ret = v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], video, - querystd, std_id); - if (ret < 0) - vpif_dbg(1, debug, "Failed to set standard for sub devices\n"); - - mutex_unlock(&common->lock); - return ret; -} - -/** - * vpif_g_std() - get STD handler - * @file: file ptr - * @priv: file handle - * @std_id: ptr to std id - */ -static int vpif_g_std(struct file *file, void *priv, v4l2_std_id *std) -{ - struct vpif_fh *fh = priv; - struct channel_obj *ch = fh->channel; - - vpif_dbg(2, debug, "vpif_g_std\n"); - - *std = ch->video.stdid; - return 0; -} - -/** - * vpif_s_std() - set STD handler - * @file: file ptr - * @priv: file handle - * @std_id: ptr to std id - */ -static int vpif_s_std(struct file *file, void *priv, v4l2_std_id *std_id) -{ - struct vpif_fh *fh = priv; - struct channel_obj *ch = fh->channel; - struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; - int ret = 0; - - vpif_dbg(2, debug, "vpif_s_std\n"); - - if (common->started) { - vpif_err("streaming in progress\n"); - return -EBUSY; - } - - if ((VPIF_CHANNEL0_VIDEO == ch->channel_id) || - (VPIF_CHANNEL1_VIDEO == ch->channel_id)) { - if (!fh->initialized) { - vpif_dbg(1, debug, "Channel Busy\n"); - return -EBUSY; - } - } - - ret = v4l2_prio_check(&ch->prio, fh->prio); - if (0 != ret) - return ret; - - fh->initialized = 1; - - /* Call encoder subdevice function to set the standard */ - if (mutex_lock_interruptible(&common->lock)) - return -ERESTARTSYS; - - ch->video.stdid = *std_id; - - /* Get the information about the standard */ - if (vpif_update_std_info(ch)) { - ret = -EINVAL; - vpif_err("Error getting the standard info\n"); - goto s_std_exit; - } - - /* Configure the default format information */ - vpif_config_format(ch); - - /* set standard in the sub device */ - ret = v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], core, - s_std, *std_id); - if (ret < 0) - vpif_dbg(1, debug, "Failed to set standard for sub devices\n"); - -s_std_exit: - mutex_unlock(&common->lock); - return ret; -} - -/** - * vpif_enum_input() - ENUMINPUT handler - * @file: file ptr - * @priv: file handle - * @input: ptr to input structure - */ -static int vpif_enum_input(struct file *file, void *priv, - struct v4l2_input *input) -{ - - struct vpif_capture_config *config = vpif_dev->platform_data; - struct vpif_capture_chan_config *chan_cfg; - struct vpif_fh *fh = priv; - struct channel_obj *ch = fh->channel; - - chan_cfg = &config->chan_config[ch->channel_id]; - - if (input->index >= chan_cfg->input_count) { - vpif_dbg(1, debug, "Invalid input index\n"); - return -EINVAL; - } - - memcpy(input, &chan_cfg->inputs[input->index].input, - sizeof(*input)); - return 0; -} - -/** - * vpif_g_input() - Get INPUT handler - * @file: file ptr - * @priv: file handle - * @index: ptr to input index - */ -static int vpif_g_input(struct file *file, void *priv, unsigned int *index) -{ - struct vpif_fh *fh = priv; - struct channel_obj *ch = fh->channel; - struct video_obj *vid_ch = &ch->video; - - *index = vid_ch->input_idx; - - return 0; -} - -/** - * vpif_s_input() - Set INPUT handler - * @file: file ptr - * @priv: file handle - * @index: input index - */ -static int vpif_s_input(struct file *file, void *priv, unsigned int index) -{ - struct vpif_capture_config *config = vpif_dev->platform_data; - struct vpif_capture_chan_config *chan_cfg; - struct vpif_fh *fh = priv; - struct channel_obj *ch = fh->channel; - struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; - struct video_obj *vid_ch = &ch->video; - struct vpif_subdev_info *subdev_info; - int ret = 0, sd_index = 0; - u32 input = 0, output = 0; - - chan_cfg = &config->chan_config[ch->channel_id]; - - if (common->started) { - vpif_err("Streaming in progress\n"); - return -EBUSY; - } - - if ((VPIF_CHANNEL0_VIDEO == ch->channel_id) || - (VPIF_CHANNEL1_VIDEO == ch->channel_id)) { - if (!fh->initialized) { - vpif_dbg(1, debug, "Channel Busy\n"); - return -EBUSY; - } - } - - ret = v4l2_prio_check(&ch->prio, fh->prio); - if (0 != ret) - return ret; - - fh->initialized = 1; - subdev_info = vpif_map_sub_device_to_input(ch, config, index, - &sd_index); - if (NULL == subdev_info) { - vpif_dbg(1, debug, - "couldn't lookup sub device for the input index\n"); - return -EINVAL; - } - - if (mutex_lock_interruptible(&common->lock)) - return -ERESTARTSYS; - - /* first setup input path from sub device to vpif */ - if (config->setup_input_path) { - ret = config->setup_input_path(ch->channel_id, - subdev_info->name); - if (ret < 0) { - vpif_dbg(1, debug, "couldn't setup input path for the" - " sub device %s, for input index %d\n", - subdev_info->name, index); - goto exit; - } - } - - if (subdev_info->can_route) { - input = subdev_info->input; - output = subdev_info->output; - ret = v4l2_subdev_call(vpif_obj.sd[sd_index], video, s_routing, - input, output, 0); - if (ret < 0) { - vpif_dbg(1, debug, "Failed to set input\n"); - goto exit; - } - } - vid_ch->input_idx = index; - ch->curr_subdev_info = subdev_info; - ch->curr_sd_index = sd_index; - /* copy interface parameters to vpif */ - ch->vpifparams.iface = subdev_info->vpif_if; - - /* update tvnorms from the sub device input info */ - ch->video_dev->tvnorms = chan_cfg->inputs[index].input.std; - -exit: - mutex_unlock(&common->lock); - return ret; -} - -/** - * vpif_enum_fmt_vid_cap() - ENUM_FMT handler - * @file: file ptr - * @priv: file handle - * @index: input index - */ -static int vpif_enum_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_fmtdesc *fmt) -{ - struct vpif_fh *fh = priv; - struct channel_obj *ch = fh->channel; - - if (fmt->index != 0) { - vpif_dbg(1, debug, "Invalid format index\n"); - return -EINVAL; - } - - /* Fill in the information about format */ - if (ch->vpifparams.iface.if_type == VPIF_IF_RAW_BAYER) { - fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - strcpy(fmt->description, "Raw Mode -Bayer Pattern GrRBGb"); - fmt->pixelformat = V4L2_PIX_FMT_SBGGR8; - } else { - fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - strcpy(fmt->description, "YCbCr4:2:2 YC Planar"); - fmt->pixelformat = V4L2_PIX_FMT_YUV422P; - } - return 0; -} - -/** - * vpif_try_fmt_vid_cap() - TRY_FMT handler - * @file: file ptr - * @priv: file handle - * @fmt: ptr to v4l2 format structure - */ -static int vpif_try_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *fmt) -{ - struct vpif_fh *fh = priv; - struct channel_obj *ch = fh->channel; - struct v4l2_pix_format *pixfmt = &fmt->fmt.pix; - - return vpif_check_format(ch, pixfmt, 1); -} - - -/** - * vpif_g_fmt_vid_cap() - Set INPUT handler - * @file: file ptr - * @priv: file handle - * @fmt: ptr to v4l2 format structure - */ -static int vpif_g_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *fmt) -{ - struct vpif_fh *fh = priv; - struct channel_obj *ch = fh->channel; - struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; - - /* Check the validity of the buffer type */ - if (common->fmt.type != fmt->type) - return -EINVAL; - - /* Fill in the information about format */ - if (mutex_lock_interruptible(&common->lock)) - return -ERESTARTSYS; - - *fmt = common->fmt; - mutex_unlock(&common->lock); - return 0; -} - -/** - * vpif_s_fmt_vid_cap() - Set FMT handler - * @file: file ptr - * @priv: file handle - * @fmt: ptr to v4l2 format structure - */ -static int vpif_s_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *fmt) -{ - struct vpif_fh *fh = priv; - struct channel_obj *ch = fh->channel; - struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; - struct v4l2_pix_format *pixfmt; - int ret = 0; - - vpif_dbg(2, debug, "VIDIOC_S_FMT\n"); - - /* If streaming is started, return error */ - if (common->started) { - vpif_dbg(1, debug, "Streaming is started\n"); - return -EBUSY; - } - - if ((VPIF_CHANNEL0_VIDEO == ch->channel_id) || - (VPIF_CHANNEL1_VIDEO == ch->channel_id)) { - if (!fh->initialized) { - vpif_dbg(1, debug, "Channel Busy\n"); - return -EBUSY; - } - } - - ret = v4l2_prio_check(&ch->prio, fh->prio); - if (0 != ret) - return ret; - - fh->initialized = 1; - - pixfmt = &fmt->fmt.pix; - /* Check for valid field format */ - ret = vpif_check_format(ch, pixfmt, 0); - - if (ret) - return ret; - /* store the format in the channel object */ - if (mutex_lock_interruptible(&common->lock)) - return -ERESTARTSYS; - - common->fmt = *fmt; - mutex_unlock(&common->lock); - - return 0; -} - -/** - * vpif_querycap() - QUERYCAP handler - * @file: file ptr - * @priv: file handle - * @cap: ptr to v4l2_capability structure - */ -static int vpif_querycap(struct file *file, void *priv, - struct v4l2_capability *cap) -{ - struct vpif_capture_config *config = vpif_dev->platform_data; - - cap->version = VPIF_CAPTURE_VERSION_CODE; - cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; - strlcpy(cap->driver, "vpif capture", sizeof(cap->driver)); - strlcpy(cap->bus_info, "DM646x Platform", sizeof(cap->bus_info)); - strlcpy(cap->card, config->card_name, sizeof(cap->card)); - - return 0; -} - -/** - * vpif_g_priority() - get priority handler - * @file: file ptr - * @priv: file handle - * @prio: ptr to v4l2_priority structure - */ -static int vpif_g_priority(struct file *file, void *priv, - enum v4l2_priority *prio) -{ - struct vpif_fh *fh = priv; - struct channel_obj *ch = fh->channel; - - *prio = v4l2_prio_max(&ch->prio); - - return 0; -} - -/** - * vpif_s_priority() - set priority handler - * @file: file ptr - * @priv: file handle - * @prio: ptr to v4l2_priority structure - */ -static int vpif_s_priority(struct file *file, void *priv, enum v4l2_priority p) -{ - struct vpif_fh *fh = priv; - struct channel_obj *ch = fh->channel; - - return v4l2_prio_change(&ch->prio, &fh->prio, p); -} - -/** - * vpif_cropcap() - cropcap handler - * @file: file ptr - * @priv: file handle - * @crop: ptr to v4l2_cropcap structure - */ -static int vpif_cropcap(struct file *file, void *priv, - struct v4l2_cropcap *crop) -{ - struct vpif_fh *fh = priv; - struct channel_obj *ch = fh->channel; - struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; - - if (V4L2_BUF_TYPE_VIDEO_CAPTURE != crop->type) - return -EINVAL; - - crop->bounds.left = 0; - crop->bounds.top = 0; - crop->bounds.height = common->height; - crop->bounds.width = common->width; - crop->defrect = crop->bounds; - return 0; -} - -/* vpif capture ioctl operations */ -static const struct v4l2_ioctl_ops vpif_ioctl_ops = { - .vidioc_querycap = vpif_querycap, - .vidioc_g_priority = vpif_g_priority, - .vidioc_s_priority = vpif_s_priority, - .vidioc_enum_fmt_vid_cap = vpif_enum_fmt_vid_cap, - .vidioc_g_fmt_vid_cap = vpif_g_fmt_vid_cap, - .vidioc_s_fmt_vid_cap = vpif_s_fmt_vid_cap, - .vidioc_try_fmt_vid_cap = vpif_try_fmt_vid_cap, - .vidioc_enum_input = vpif_enum_input, - .vidioc_s_input = vpif_s_input, - .vidioc_g_input = vpif_g_input, - .vidioc_reqbufs = vpif_reqbufs, - .vidioc_querybuf = vpif_querybuf, - .vidioc_querystd = vpif_querystd, - .vidioc_s_std = vpif_s_std, - .vidioc_g_std = vpif_g_std, - .vidioc_qbuf = vpif_qbuf, - .vidioc_dqbuf = vpif_dqbuf, - .vidioc_streamon = vpif_streamon, - .vidioc_streamoff = vpif_streamoff, - .vidioc_cropcap = vpif_cropcap, -}; - -/* vpif file operations */ -static struct v4l2_file_operations vpif_fops = { - .owner = THIS_MODULE, - .open = vpif_open, - .release = vpif_release, - .ioctl = video_ioctl2, - .mmap = vpif_mmap, - .poll = vpif_poll -}; - -/* vpif video template */ -static struct video_device vpif_video_template = { - .name = "vpif", - .fops = &vpif_fops, - .minor = -1, - .ioctl_ops = &vpif_ioctl_ops, -}; - -/** - * initialize_vpif() - Initialize vpif data structures - * - * Allocate memory for data structures and initialize them - */ -static int initialize_vpif(void) -{ - int err = 0, i, j; - int free_channel_objects_index; - - /* Default number of buffers should be 3 */ - if ((ch0_numbuffers > 0) && - (ch0_numbuffers < config_params.min_numbuffers)) - ch0_numbuffers = config_params.min_numbuffers; - if ((ch1_numbuffers > 0) && - (ch1_numbuffers < config_params.min_numbuffers)) - ch1_numbuffers = config_params.min_numbuffers; - - /* Set buffer size to min buffers size if it is invalid */ - if (ch0_bufsize < config_params.min_bufsize[VPIF_CHANNEL0_VIDEO]) - ch0_bufsize = - config_params.min_bufsize[VPIF_CHANNEL0_VIDEO]; - if (ch1_bufsize < config_params.min_bufsize[VPIF_CHANNEL1_VIDEO]) - ch1_bufsize = - config_params.min_bufsize[VPIF_CHANNEL1_VIDEO]; - - config_params.numbuffers[VPIF_CHANNEL0_VIDEO] = ch0_numbuffers; - config_params.numbuffers[VPIF_CHANNEL1_VIDEO] = ch1_numbuffers; - if (ch0_numbuffers) { - config_params.channel_bufsize[VPIF_CHANNEL0_VIDEO] - = ch0_bufsize; - } - if (ch1_numbuffers) { - config_params.channel_bufsize[VPIF_CHANNEL1_VIDEO] - = ch1_bufsize; - } - - /* Allocate memory for six channel objects */ - for (i = 0; i < VPIF_CAPTURE_MAX_DEVICES; i++) { - vpif_obj.dev[i] = - kzalloc(sizeof(*vpif_obj.dev[i]), GFP_KERNEL); - /* If memory allocation fails, return error */ - if (!vpif_obj.dev[i]) { - free_channel_objects_index = i; - err = -ENOMEM; - goto vpif_init_free_channel_objects; - } - } - return 0; - -vpif_init_free_channel_objects: - for (j = 0; j < free_channel_objects_index; j++) - kfree(vpif_obj.dev[j]); - return err; -} - -/** - * vpif_probe : This function probes the vpif capture driver - * @pdev: platform device pointer - * - * This creates device entries by register itself to the V4L2 driver and - * initializes fields of each channel objects - */ -static __init int vpif_probe(struct platform_device *pdev) -{ - struct vpif_subdev_info *subdevdata; - struct vpif_capture_config *config; - int i, j, k, m, q, err; - struct i2c_adapter *i2c_adap; - struct channel_obj *ch; - struct common_obj *common; - struct video_device *vfd; - struct resource *res; - int subdev_count; - - vpif_dev = &pdev->dev; - - err = initialize_vpif(); - if (err) { - v4l2_err(vpif_dev->driver, "Error initializing vpif\n"); - return err; - } - - k = 0; - while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, k))) { - for (i = res->start; i <= res->end; i++) { - if (request_irq(i, vpif_channel_isr, IRQF_DISABLED, - "DM646x_Capture", - (void *)(&vpif_obj.dev[k]->channel_id))) { - err = -EBUSY; - i--; - goto vpif_int_err; - } - } - k++; - } - - for (i = 0; i < VPIF_CAPTURE_MAX_DEVICES; i++) { - /* Get the pointer to the channel object */ - ch = vpif_obj.dev[i]; - /* Allocate memory for video device */ - vfd = video_device_alloc(); - if (NULL == vfd) { - for (j = 0; j < i; j++) { - ch = vpif_obj.dev[j]; - video_device_release(ch->video_dev); - } - err = -ENOMEM; - goto vpif_dev_alloc_err; - } - - /* Initialize field of video device */ - *vfd = vpif_video_template; - vfd->v4l2_dev = &vpif_obj.v4l2_dev; - vfd->release = video_device_release; - snprintf(vfd->name, sizeof(vfd->name), - "DM646x_VPIFCapture_DRIVER_V%d.%d.%d", - (VPIF_CAPTURE_VERSION_CODE >> 16) & 0xff, - (VPIF_CAPTURE_VERSION_CODE >> 8) & 0xff, - (VPIF_CAPTURE_VERSION_CODE) & 0xff); - /* Set video_dev to the video device */ - ch->video_dev = vfd; - } - - for (j = 0; j < VPIF_CAPTURE_MAX_DEVICES; j++) { - ch = vpif_obj.dev[j]; - ch->channel_id = j; - common = &(ch->common[VPIF_VIDEO_INDEX]); - spin_lock_init(&common->irqlock); - mutex_init(&common->lock); - /* Initialize prio member of channel object */ - v4l2_prio_init(&ch->prio); - err = video_register_device(ch->video_dev, - VFL_TYPE_GRABBER, (j ? 1 : 0)); - if (err) - goto probe_out; - - video_set_drvdata(ch->video_dev, ch); - - } - - i2c_adap = i2c_get_adapter(1); - config = pdev->dev.platform_data; - - subdev_count = config->subdev_count; - vpif_obj.sd = kzalloc(sizeof(struct v4l2_subdev *) * subdev_count, - GFP_KERNEL); - if (vpif_obj.sd == NULL) { - vpif_err("unable to allocate memory for subdevice pointers\n"); - err = -ENOMEM; - goto probe_out; - } - - err = v4l2_device_register(vpif_dev, &vpif_obj.v4l2_dev); - if (err) { - v4l2_err(vpif_dev->driver, "Error registering v4l2 device\n"); - goto probe_subdev_out; - } - - for (i = 0; i < subdev_count; i++) { - subdevdata = &config->subdev_info[i]; - vpif_obj.sd[i] = - v4l2_i2c_new_subdev_board(&vpif_obj.v4l2_dev, - i2c_adap, - NULL, - &subdevdata->board_info, - NULL); - - if (!vpif_obj.sd[i]) { - vpif_err("Error registering v4l2 subdevice\n"); - goto probe_subdev_out; - } - v4l2_info(&vpif_obj.v4l2_dev, "registered sub device %s\n", - subdevdata->name); - - if (vpif_obj.sd[i]) - vpif_obj.sd[i]->grp_id = 1 << i; - } - v4l2_info(&vpif_obj.v4l2_dev, "DM646x VPIF Capture driver" - " initialized\n"); - - return 0; - -probe_subdev_out: - /* free sub devices memory */ - kfree(vpif_obj.sd); - - j = VPIF_CAPTURE_MAX_DEVICES; -probe_out: - v4l2_device_unregister(&vpif_obj.v4l2_dev); - for (k = 0; k < j; k++) { - /* Get the pointer to the channel object */ - ch = vpif_obj.dev[k]; - /* Unregister video device */ - video_unregister_device(ch->video_dev); - } - -vpif_dev_alloc_err: - k = VPIF_CAPTURE_MAX_DEVICES-1; - res = platform_get_resource(pdev, IORESOURCE_IRQ, k); - i = res->end; - -vpif_int_err: - for (q = k; q >= 0; q--) { - for (m = i; m >= (int)res->start; m--) - free_irq(m, (void *)(&vpif_obj.dev[q]->channel_id)); - - res = platform_get_resource(pdev, IORESOURCE_IRQ, q-1); - if (res) - i = res->end; - } - return err; -} - -/** - * vpif_remove() - driver remove handler - * @device: ptr to platform device structure - * - * The vidoe device is unregistered - */ -static int vpif_remove(struct platform_device *device) -{ - int i; - struct channel_obj *ch; - - v4l2_device_unregister(&vpif_obj.v4l2_dev); - - /* un-register device */ - for (i = 0; i < VPIF_CAPTURE_MAX_DEVICES; i++) { - /* Get the pointer to the channel object */ - ch = vpif_obj.dev[i]; - /* Unregister video device */ - video_unregister_device(ch->video_dev); - } - return 0; -} - -/** - * vpif_suspend: vpif device suspend - * - * TODO: Add suspend code here - */ -static int -vpif_suspend(struct device *dev) -{ - return -1; -} - -/** - * vpif_resume: vpif device suspend - * - * TODO: Add resume code here - */ -static int -vpif_resume(struct device *dev) -{ - return -1; -} - -static const struct dev_pm_ops vpif_dev_pm_ops = { - .suspend = vpif_suspend, - .resume = vpif_resume, -}; - -static __refdata struct platform_driver vpif_driver = { - .driver = { - .name = "vpif_capture", - .owner = THIS_MODULE, - .pm = &vpif_dev_pm_ops, - }, - .probe = vpif_probe, - .remove = vpif_remove, -}; - -/** - * vpif_init: initialize the vpif driver - * - * This function registers device and driver to the kernel, requests irq - * handler and allocates memory - * for channel objects - */ -static __init int vpif_init(void) -{ - return platform_driver_register(&vpif_driver); -} - -/** - * vpif_cleanup : This function clean up the vpif capture resources - * - * This will un-registers device and driver to the kernel, frees - * requested irq handler and de-allocates memory allocated for channel - * objects. - */ -static void vpif_cleanup(void) -{ - struct platform_device *pdev; - struct resource *res; - int irq_num; - int i = 0; - - pdev = container_of(vpif_dev, struct platform_device, dev); - while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, i))) { - for (irq_num = res->start; irq_num <= res->end; irq_num++) - free_irq(irq_num, - (void *)(&vpif_obj.dev[i]->channel_id)); - i++; - } - - platform_driver_unregister(&vpif_driver); - - kfree(vpif_obj.sd); - for (i = 0; i < VPIF_CAPTURE_MAX_DEVICES; i++) - kfree(vpif_obj.dev[i]); -} - -/* Function for module initialization and cleanup */ -module_init(vpif_init); -module_exit(vpif_cleanup); diff --git a/drivers/media/video/davinci/vpif_capture.h b/drivers/media/video/davinci/vpif_capture.h deleted file mode 100644 index 4e12ec8cac6..00000000000 --- a/drivers/media/video/davinci/vpif_capture.h +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright (C) 2009 Texas Instruments Inc - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef VPIF_CAPTURE_H -#define VPIF_CAPTURE_H - -#ifdef __KERNEL__ - -/* Header files */ -#include <linux/videodev2.h> -#include <linux/version.h> -#include <media/v4l2-common.h> -#include <media/v4l2-device.h> -#include <media/videobuf-core.h> -#include <media/videobuf-dma-contig.h> -#include <mach/dm646x.h> - -#include "vpif.h" - -/* Macros */ -#define VPIF_MAJOR_RELEASE 0 -#define VPIF_MINOR_RELEASE 0 -#define VPIF_BUILD 1 -#define VPIF_CAPTURE_VERSION_CODE ((VPIF_MAJOR_RELEASE << 16) | \ - (VPIF_MINOR_RELEASE << 8) | VPIF_BUILD) - -#define VPIF_VALID_FIELD(field) (((V4L2_FIELD_ANY == field) || \ - (V4L2_FIELD_NONE == field)) || \ - (((V4L2_FIELD_INTERLACED == field) || \ - (V4L2_FIELD_SEQ_TB == field)) || \ - (V4L2_FIELD_SEQ_BT == field))) - -#define VPIF_CAPTURE_MAX_DEVICES 2 -#define VPIF_VIDEO_INDEX 0 -#define VPIF_NUMBER_OF_OBJECTS 1 - -/* Enumerated data type to give id to each device per channel */ -enum vpif_channel_id { - VPIF_CHANNEL0_VIDEO = 0, - VPIF_CHANNEL1_VIDEO, -}; - -struct video_obj { - enum v4l2_field buf_field; - /* Currently selected or default standard */ - v4l2_std_id stdid; - /* This is to track the last input that is passed to application */ - u32 input_idx; -}; - -struct common_obj { - /* Pointer pointing to current v4l2_buffer */ - struct videobuf_buffer *cur_frm; - /* Pointer pointing to current v4l2_buffer */ - struct videobuf_buffer *next_frm; - /* - * This field keeps track of type of buffer exchange mechanism - * user has selected - */ - enum v4l2_memory memory; - /* Used to store pixel format */ - struct v4l2_format fmt; - /* Buffer queue used in video-buf */ - struct videobuf_queue buffer_queue; - /* Queue of filled frames */ - struct list_head dma_queue; - /* Used in video-buf */ - spinlock_t irqlock; - /* lock used to access this structure */ - struct mutex lock; - /* number of users performing IO */ - u32 io_usrs; - /* Indicates whether streaming started */ - u8 started; - /* Function pointer to set the addresses */ - void (*set_addr) (unsigned long, unsigned long, unsigned long, - unsigned long); - /* offset where Y top starts from the starting of the buffer */ - u32 ytop_off; - /* offset where Y bottom starts from the starting of the buffer */ - u32 ybtm_off; - /* offset where C top starts from the starting of the buffer */ - u32 ctop_off; - /* offset where C bottom starts from the starting of the buffer */ - u32 cbtm_off; - /* Indicates width of the image data */ - u32 width; - /* Indicates height of the image data */ - u32 height; -}; - -struct channel_obj { - /* Identifies video device for this channel */ - struct video_device *video_dev; - /* Used to keep track of state of the priority */ - struct v4l2_prio_state prio; - /* number of open instances of the channel */ - int usrs; - /* Indicates id of the field which is being displayed */ - u32 field_id; - /* flag to indicate whether decoder is initialized */ - u8 initialized; - /* Identifies channel */ - enum vpif_channel_id channel_id; - /* index into sd table */ - int curr_sd_index; - /* ptr to current sub device information */ - struct vpif_subdev_info *curr_subdev_info; - /* vpif configuration params */ - struct vpif_params vpifparams; - /* common object array */ - struct common_obj common[VPIF_NUMBER_OF_OBJECTS]; - /* video object */ - struct video_obj video; -}; - -/* File handle structure */ -struct vpif_fh { - /* pointer to channel object for opened device */ - struct channel_obj *channel; - /* Indicates whether this file handle is doing IO */ - u8 io_allowed[VPIF_NUMBER_OF_OBJECTS]; - /* Used to keep track priority of this instance */ - enum v4l2_priority prio; - /* Used to indicate channel is initialize or not */ - u8 initialized; -}; - -struct vpif_device { - struct v4l2_device v4l2_dev; - struct channel_obj *dev[VPIF_CAPTURE_NUM_CHANNELS]; - struct v4l2_subdev **sd; -}; - -struct vpif_config_params { - u8 min_numbuffers; - u8 numbuffers[VPIF_CAPTURE_NUM_CHANNELS]; - s8 device_type; - u32 min_bufsize[VPIF_CAPTURE_NUM_CHANNELS]; - u32 channel_bufsize[VPIF_CAPTURE_NUM_CHANNELS]; - u8 default_device[VPIF_CAPTURE_NUM_CHANNELS]; - u8 max_device_type; -}; -/* Struct which keeps track of the line numbers for the sliced vbi service */ -struct vpif_service_line { - u16 service_id; - u16 service_line[2]; -}; -#endif /* End of __KERNEL__ */ -#endif /* VPIF_CAPTURE_H */ diff --git a/drivers/media/video/davinci/vpif_display.c b/drivers/media/video/davinci/vpif_display.c deleted file mode 100644 index 685f6a6ee60..00000000000 --- a/drivers/media/video/davinci/vpif_display.c +++ /dev/null @@ -1,1657 +0,0 @@ -/* - * vpif-display - VPIF display driver - * Display driver for TI DaVinci VPIF - * - * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/ - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation version 2. - * - * This program is distributed .as is. WITHOUT ANY WARRANTY of any - * kind, whether express or implied; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/module.h> -#include <linux/errno.h> -#include <linux/fs.h> -#include <linux/mm.h> -#include <linux/interrupt.h> -#include <linux/workqueue.h> -#include <linux/string.h> -#include <linux/videodev2.h> -#include <linux/wait.h> -#include <linux/time.h> -#include <linux/i2c.h> -#include <linux/platform_device.h> -#include <linux/io.h> -#include <linux/version.h> -#include <linux/slab.h> - -#include <asm/irq.h> -#include <asm/page.h> - -#include <media/adv7343.h> -#include <media/v4l2-device.h> -#include <media/v4l2-ioctl.h> - -#include <mach/dm646x.h> - -#include "vpif_display.h" -#include "vpif.h" - -MODULE_DESCRIPTION("TI DaVinci VPIF Display driver"); -MODULE_LICENSE("GPL"); - -#define DM646X_V4L2_STD (V4L2_STD_525_60 | V4L2_STD_625_50) - -#define vpif_err(fmt, arg...) v4l2_err(&vpif_obj.v4l2_dev, fmt, ## arg) -#define vpif_dbg(level, debug, fmt, arg...) \ - v4l2_dbg(level, debug, &vpif_obj.v4l2_dev, fmt, ## arg) - -static int debug = 1; -static u32 ch2_numbuffers = 3; -static u32 ch3_numbuffers = 3; -static u32 ch2_bufsize = 1920 * 1080 * 2; -static u32 ch3_bufsize = 720 * 576 * 2; - -module_param(debug, int, 0644); -module_param(ch2_numbuffers, uint, S_IRUGO); -module_param(ch3_numbuffers, uint, S_IRUGO); -module_param(ch2_bufsize, uint, S_IRUGO); -module_param(ch3_bufsize, uint, S_IRUGO); - -MODULE_PARM_DESC(debug, "Debug level 0-1"); -MODULE_PARM_DESC(ch2_numbuffers, "Channel2 buffer count (default:3)"); -MODULE_PARM_DESC(ch3_numbuffers, "Channel3 buffer count (default:3)"); -MODULE_PARM_DESC(ch2_bufsize, "Channel2 buffer size (default:1920 x 1080 x 2)"); -MODULE_PARM_DESC(ch3_bufsize, "Channel3 buffer size (default:720 x 576 x 2)"); - -static struct vpif_config_params config_params = { - .min_numbuffers = 3, - .numbuffers[0] = 3, - .numbuffers[1] = 3, - .min_bufsize[0] = 720 * 480 * 2, - .min_bufsize[1] = 720 * 480 * 2, - .channel_bufsize[0] = 1920 * 1080 * 2, - .channel_bufsize[1] = 720 * 576 * 2, -}; - -static struct vpif_device vpif_obj = { {NULL} }; -static struct device *vpif_dev; - -static const struct vpif_channel_config_params ch_params[] = { - { - "NTSC", 720, 480, 30, 0, 1, 268, 1440, 1, 23, 263, 266, - 286, 525, 525, 0, 1, 0, V4L2_STD_525_60, - }, - { - "PAL", 720, 576, 25, 0, 1, 280, 1440, 1, 23, 311, 313, - 336, 624, 625, 0, 1, 0, V4L2_STD_625_50, - }, -}; - -/* - * vpif_uservirt_to_phys: This function is used to convert user - * space virtual address to physical address. - */ -static u32 vpif_uservirt_to_phys(u32 virtp) -{ - struct mm_struct *mm = current->mm; - unsigned long physp = 0; - struct vm_area_struct *vma; - - vma = find_vma(mm, virtp); - - /* For kernel direct-mapped memory, take the easy way */ - if (virtp >= PAGE_OFFSET) { - physp = virt_to_phys((void *)virtp); - } else if (vma && (vma->vm_flags & VM_IO) && (vma->vm_pgoff)) { - /* this will catch, kernel-allocated, mmaped-to-usermode addr */ - physp = (vma->vm_pgoff << PAGE_SHIFT) + (virtp - vma->vm_start); - } else { - /* otherwise, use get_user_pages() for general userland pages */ - int res, nr_pages = 1; - struct page *pages; - down_read(¤t->mm->mmap_sem); - - res = get_user_pages(current, current->mm, - virtp, nr_pages, 1, 0, &pages, NULL); - up_read(¤t->mm->mmap_sem); - - if (res == nr_pages) { - physp = __pa(page_address(&pages[0]) + - (virtp & ~PAGE_MASK)); - } else { - vpif_err("get_user_pages failed\n"); - return 0; - } - } - - return physp; -} - -/* - * buffer_prepare: This is the callback function called from videobuf_qbuf() - * function the buffer is prepared and user space virtual address is converted - * into physical address - */ -static int vpif_buffer_prepare(struct videobuf_queue *q, - struct videobuf_buffer *vb, - enum v4l2_field field) -{ - struct vpif_fh *fh = q->priv_data; - struct common_obj *common; - unsigned long addr; - - common = &fh->channel->common[VPIF_VIDEO_INDEX]; - if (VIDEOBUF_NEEDS_INIT == vb->state) { - vb->width = common->width; - vb->height = common->height; - vb->size = vb->width * vb->height; - vb->field = field; - } - vb->state = VIDEOBUF_PREPARED; - - /* if user pointer memory mechanism is used, get the physical - * address of the buffer */ - if (V4L2_MEMORY_USERPTR == common->memory) { - if (!vb->baddr) { - vpif_err("buffer_address is 0\n"); - return -EINVAL; - } - - vb->boff = vpif_uservirt_to_phys(vb->baddr); - if (!ISALIGNED(vb->boff)) - goto buf_align_exit; - } - - addr = vb->boff; - if (q->streaming && (V4L2_BUF_TYPE_SLICED_VBI_OUTPUT != q->type)) { - if (!ISALIGNED(addr + common->ytop_off) || - !ISALIGNED(addr + common->ybtm_off) || - !ISALIGNED(addr + common->ctop_off) || - !ISALIGNED(addr + common->cbtm_off)) - goto buf_align_exit; - } - return 0; - -buf_align_exit: - vpif_err("buffer offset not aligned to 8 bytes\n"); - return -EINVAL; -} - -/* - * vpif_buffer_setup: This function allocates memory for the buffers - */ -static int vpif_buffer_setup(struct videobuf_queue *q, unsigned int *count, - unsigned int *size) -{ - struct vpif_fh *fh = q->priv_data; - struct channel_obj *ch = fh->channel; - struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; - - if (V4L2_MEMORY_MMAP != common->memory) - return 0; - - *size = config_params.channel_bufsize[ch->channel_id]; - if (*count < config_params.min_numbuffers) - *count = config_params.min_numbuffers; - - return 0; -} - -/* - * vpif_buffer_queue: This function adds the buffer to DMA queue - */ -static void vpif_buffer_queue(struct videobuf_queue *q, - struct videobuf_buffer *vb) -{ - struct vpif_fh *fh = q->priv_data; - struct common_obj *common; - - common = &fh->channel->common[VPIF_VIDEO_INDEX]; - - /* add the buffer to the DMA queue */ - list_add_tail(&vb->queue, &common->dma_queue); - vb->state = VIDEOBUF_QUEUED; -} - -/* - * vpif_buffer_release: This function is called from the videobuf layer to - * free memory allocated to the buffers - */ -static void vpif_buffer_release(struct videobuf_queue *q, - struct videobuf_buffer *vb) -{ - struct vpif_fh *fh = q->priv_data; - struct channel_obj *ch = fh->channel; - struct common_obj *common; - unsigned int buf_size = 0; - - common = &ch->common[VPIF_VIDEO_INDEX]; - - videobuf_dma_contig_free(q, vb); - vb->state = VIDEOBUF_NEEDS_INIT; - - if (V4L2_MEMORY_MMAP != common->memory) - return; - - buf_size = config_params.channel_bufsize[ch->channel_id]; -} - -static struct videobuf_queue_ops video_qops = { - .buf_setup = vpif_buffer_setup, - .buf_prepare = vpif_buffer_prepare, - .buf_queue = vpif_buffer_queue, - .buf_release = vpif_buffer_release, -}; -static u8 channel_first_int[VPIF_NUMOBJECTS][2] = { {1, 1} }; - -static void process_progressive_mode(struct common_obj *common) -{ - unsigned long addr = 0; - - /* Get the next buffer from buffer queue */ - common->next_frm = list_entry(common->dma_queue.next, - struct videobuf_buffer, queue); - /* Remove that buffer from the buffer queue */ - list_del(&common->next_frm->queue); - /* Mark status of the buffer as active */ - common->next_frm->state = VIDEOBUF_ACTIVE; - - /* Set top and bottom field addrs in VPIF registers */ - addr = videobuf_to_dma_contig(common->next_frm); - common->set_addr(addr + common->ytop_off, - addr + common->ybtm_off, - addr + common->ctop_off, - addr + common->cbtm_off); -} - -static void process_interlaced_mode(int fid, struct common_obj *common) -{ - /* device field id and local field id are in sync */ - /* If this is even field */ - if (0 == fid) { - if (common->cur_frm == common->next_frm) - return; - - /* one frame is displayed If next frame is - * available, release cur_frm and move on */ - /* Copy frame display time */ - do_gettimeofday(&common->cur_frm->ts); - /* Change status of the cur_frm */ - common->cur_frm->state = VIDEOBUF_DONE; - /* unlock semaphore on cur_frm */ - wake_up_interruptible(&common->cur_frm->done); - /* Make cur_frm pointing to next_frm */ - common->cur_frm = common->next_frm; - - } else if (1 == fid) { /* odd field */ - if (list_empty(&common->dma_queue) - || (common->cur_frm != common->next_frm)) { - return; - } - /* one field is displayed configure the next - * frame if it is available else hold on current - * frame */ - /* Get next from the buffer queue */ - process_progressive_mode(common); - - } -} - -/* - * vpif_channel_isr: It changes status of the displayed buffer, takes next - * buffer from the queue and sets its address in VPIF registers - */ -static irqreturn_t vpif_channel_isr(int irq, void *dev_id) -{ - struct vpif_device *dev = &vpif_obj; - struct channel_obj *ch; - struct common_obj *common; - enum v4l2_field field; - int fid = -1, i; - int channel_id = 0; - - channel_id = *(int *)(dev_id); - ch = dev->dev[channel_id]; - field = ch->common[VPIF_VIDEO_INDEX].fmt.fmt.pix.field; - for (i = 0; i < VPIF_NUMOBJECTS; i++) { - common = &ch->common[i]; - /* If streaming is started in this channel */ - if (0 == common->started) - continue; - - if (1 == ch->vpifparams.std_info.frm_fmt) { - if (list_empty(&common->dma_queue)) - continue; - - /* Progressive mode */ - if (!channel_first_int[i][channel_id]) { - /* Mark status of the cur_frm to - * done and unlock semaphore on it */ - do_gettimeofday(&common->cur_frm->ts); - common->cur_frm->state = VIDEOBUF_DONE; - wake_up_interruptible(&common->cur_frm->done); - /* Make cur_frm pointing to next_frm */ - common->cur_frm = common->next_frm; - } - - channel_first_int[i][channel_id] = 0; - process_progressive_mode(common); - } else { - /* Interlaced mode */ - /* If it is first interrupt, ignore it */ - - if (channel_first_int[i][channel_id]) { - channel_first_int[i][channel_id] = 0; - continue; - } - - if (0 == i) { - ch->field_id ^= 1; - /* Get field id from VPIF registers */ - fid = vpif_channel_getfid(ch->channel_id + 2); - /* If fid does not match with stored field id */ - if (fid != ch->field_id) { - /* Make them in sync */ - if (0 == fid) - ch->field_id = fid; - - return IRQ_HANDLED; - } - } - process_interlaced_mode(fid, common); - } - } - - return IRQ_HANDLED; -} - -static int vpif_get_std_info(struct channel_obj *ch) -{ - struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; - struct video_obj *vid_ch = &ch->video; - struct vpif_params *vpifparams = &ch->vpifparams; - struct vpif_channel_config_params *std_info = &vpifparams->std_info; - const struct vpif_channel_config_params *config; - - int index; - - std_info->stdid = vid_ch->stdid; - if (!std_info->stdid) - return -1; - - for (index = 0; index < ARRAY_SIZE(ch_params); index++) { - config = &ch_params[index]; - if (config->stdid & std_info->stdid) { - memcpy(std_info, config, sizeof(*config)); - break; - } - } - - if (index == ARRAY_SIZE(ch_params)) - return -1; - - common->fmt.fmt.pix.width = std_info->width; - common->fmt.fmt.pix.height = std_info->height; - vpif_dbg(1, debug, "Pixel details: Width = %d,Height = %d\n", - common->fmt.fmt.pix.width, common->fmt.fmt.pix.height); - - /* Set height and width paramateres */ - ch->common[VPIF_VIDEO_INDEX].height = std_info->height; - ch->common[VPIF_VIDEO_INDEX].width = std_info->width; - - return 0; -} - -/* - * vpif_calculate_offsets: This function calculates buffers offset for Y and C - * in the top and bottom field - */ -static void vpif_calculate_offsets(struct channel_obj *ch) -{ - struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; - struct vpif_params *vpifparams = &ch->vpifparams; - enum v4l2_field field = common->fmt.fmt.pix.field; - struct video_obj *vid_ch = &ch->video; - unsigned int hpitch, vpitch, sizeimage; - - if (V4L2_FIELD_ANY == common->fmt.fmt.pix.field) { - if (ch->vpifparams.std_info.frm_fmt) - vid_ch->buf_field = V4L2_FIELD_NONE; - else - vid_ch->buf_field = V4L2_FIELD_INTERLACED; - } else { - vid_ch->buf_field = common->fmt.fmt.pix.field; - } - - if (V4L2_MEMORY_USERPTR == common->memory) - sizeimage = common->fmt.fmt.pix.sizeimage; - else - sizeimage = config_params.channel_bufsize[ch->channel_id]; - - hpitch = common->fmt.fmt.pix.bytesperline; - vpitch = sizeimage / (hpitch * 2); - if ((V4L2_FIELD_NONE == vid_ch->buf_field) || - (V4L2_FIELD_INTERLACED == vid_ch->buf_field)) { - common->ytop_off = 0; - common->ybtm_off = hpitch; - common->ctop_off = sizeimage / 2; - common->cbtm_off = sizeimage / 2 + hpitch; - } else if (V4L2_FIELD_SEQ_TB == vid_ch->buf_field) { - common->ytop_off = 0; - common->ybtm_off = sizeimage / 4; - common->ctop_off = sizeimage / 2; - common->cbtm_off = common->ctop_off + sizeimage / 4; - } else if (V4L2_FIELD_SEQ_BT == vid_ch->buf_field) { - common->ybtm_off = 0; - common->ytop_off = sizeimage / 4; - common->cbtm_off = sizeimage / 2; - common->ctop_off = common->cbtm_off + sizeimage / 4; - } - - if ((V4L2_FIELD_NONE == vid_ch->buf_field) || - (V4L2_FIELD_INTERLACED == vid_ch->buf_field)) { - vpifparams->video_params.storage_mode = 1; - } else { - vpifparams->video_params.storage_mode = 0; - } - - if (ch->vpifparams.std_info.frm_fmt == 1) { - vpifparams->video_params.hpitch = - common->fmt.fmt.pix.bytesperline; - } else { - if ((field == V4L2_FIELD_ANY) || - (field == V4L2_FIELD_INTERLACED)) - vpifparams->video_params.hpitch = - common->fmt.fmt.pix.bytesperline * 2; - else - vpifparams->video_params.hpitch = - common->fmt.fmt.pix.bytesperline; - } - - ch->vpifparams.video_params.stdid = ch->vpifparams.std_info.stdid; -} - -static void vpif_config_format(struct channel_obj *ch) -{ - struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; - - common->fmt.fmt.pix.field = V4L2_FIELD_ANY; - if (config_params.numbuffers[ch->channel_id] == 0) - common->memory = V4L2_MEMORY_USERPTR; - else - common->memory = V4L2_MEMORY_MMAP; - - common->fmt.fmt.pix.sizeimage = - config_params.channel_bufsize[ch->channel_id]; - common->fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUV422P; - common->fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; -} - -static int vpif_check_format(struct channel_obj *ch, - struct v4l2_pix_format *pixfmt) -{ - struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; - enum v4l2_field field = pixfmt->field; - u32 sizeimage, hpitch, vpitch; - - if (pixfmt->pixelformat != V4L2_PIX_FMT_YUV422P) - goto invalid_fmt_exit; - - if (!(VPIF_VALID_FIELD(field))) - goto invalid_fmt_exit; - - if (pixfmt->bytesperline <= 0) - goto invalid_pitch_exit; - - if (V4L2_MEMORY_USERPTR == common->memory) - sizeimage = pixfmt->sizeimage; - else - sizeimage = config_params.channel_bufsize[ch->channel_id]; - - if (vpif_get_std_info(ch)) { - vpif_err("Error getting the standard info\n"); - return -EINVAL; - } - - hpitch = pixfmt->bytesperline; - vpitch = sizeimage / (hpitch * 2); - - /* Check for valid value of pitch */ - if ((hpitch < ch->vpifparams.std_info.width) || - (vpitch < ch->vpifparams.std_info.height)) - goto invalid_pitch_exit; - - /* Check for 8 byte alignment */ - if (!ISALIGNED(hpitch)) { - vpif_err("invalid pitch alignment\n"); - return -EINVAL; - } - pixfmt->width = common->fmt.fmt.pix.width; - pixfmt->height = common->fmt.fmt.pix.height; - - return 0; - -invalid_fmt_exit: - vpif_err("invalid field format\n"); - return -EINVAL; - -invalid_pitch_exit: - vpif_err("invalid pitch\n"); - return -EINVAL; -} - -static void vpif_config_addr(struct channel_obj *ch, int muxmode) -{ - struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; - - if (VPIF_CHANNEL3_VIDEO == ch->channel_id) { - common->set_addr = ch3_set_videobuf_addr; - } else { - if (2 == muxmode) - common->set_addr = ch2_set_videobuf_addr_yc_nmux; - else - common->set_addr = ch2_set_videobuf_addr; - } -} - -/* - * vpif_mmap: It is used to map kernel space buffers into user spaces - */ -static int vpif_mmap(struct file *filep, struct vm_area_struct *vma) -{ - struct vpif_fh *fh = filep->private_data; - struct common_obj *common = &fh->channel->common[VPIF_VIDEO_INDEX]; - - return videobuf_mmap_mapper(&common->buffer_queue, vma); -} - -/* - * vpif_poll: It is used for select/poll system call - */ -static unsigned int vpif_poll(struct file *filep, poll_table *wait) -{ - struct vpif_fh *fh = filep->private_data; - struct channel_obj *ch = fh->channel; - struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; - - if (common->started) - return videobuf_poll_stream(filep, &common->buffer_queue, wait); - - return 0; -} - -/* - * vpif_open: It creates object of file handle structure and stores it in - * private_data member of filepointer - */ -static int vpif_open(struct file *filep) -{ - struct video_device *vdev = video_devdata(filep); - struct channel_obj *ch = NULL; - struct vpif_fh *fh = NULL; - - ch = video_get_drvdata(vdev); - /* Allocate memory for the file handle object */ - fh = kzalloc(sizeof(struct vpif_fh), GFP_KERNEL); - if (fh == NULL) { - vpif_err("unable to allocate memory for file handle object\n"); - return -ENOMEM; - } - - /* store pointer to fh in private_data member of filep */ - filep->private_data = fh; - fh->channel = ch; - fh->initialized = 0; - if (!ch->initialized) { - fh->initialized = 1; - ch->initialized = 1; - memset(&ch->vpifparams, 0, sizeof(ch->vpifparams)); - } - - /* Increment channel usrs counter */ - atomic_inc(&ch->usrs); - /* Set io_allowed[VPIF_VIDEO_INDEX] member to false */ - fh->io_allowed[VPIF_VIDEO_INDEX] = 0; - /* Initialize priority of this instance to default priority */ - fh->prio = V4L2_PRIORITY_UNSET; - v4l2_prio_open(&ch->prio, &fh->prio); - - return 0; -} - -/* - * vpif_release: This function deletes buffer queue, frees the buffers and - * the vpif file handle - */ -static int vpif_release(struct file *filep) -{ - struct vpif_fh *fh = filep->private_data; - struct channel_obj *ch = fh->channel; - struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; - - if (mutex_lock_interruptible(&common->lock)) - return -ERESTARTSYS; - - /* if this instance is doing IO */ - if (fh->io_allowed[VPIF_VIDEO_INDEX]) { - /* Reset io_usrs member of channel object */ - common->io_usrs = 0; - /* Disable channel */ - if (VPIF_CHANNEL2_VIDEO == ch->channel_id) { - enable_channel2(0); - channel2_intr_enable(0); - } - if ((VPIF_CHANNEL3_VIDEO == ch->channel_id) || - (2 == common->started)) { - enable_channel3(0); - channel3_intr_enable(0); - } - common->started = 0; - /* Free buffers allocated */ - videobuf_queue_cancel(&common->buffer_queue); - videobuf_mmap_free(&common->buffer_queue); - common->numbuffers = - config_params.numbuffers[ch->channel_id]; - } - - mutex_unlock(&common->lock); - - /* Decrement channel usrs counter */ - atomic_dec(&ch->usrs); - /* If this file handle has initialize encoder device, reset it */ - if (fh->initialized) - ch->initialized = 0; - - /* Close the priority */ - v4l2_prio_close(&ch->prio, fh->prio); - filep->private_data = NULL; - fh->initialized = 0; - kfree(fh); - - return 0; -} - -/* functions implementing ioctls */ - -static int vpif_querycap(struct file *file, void *priv, - struct v4l2_capability *cap) -{ - struct vpif_display_config *config = vpif_dev->platform_data; - - cap->version = VPIF_DISPLAY_VERSION_CODE; - cap->capabilities = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING; - strlcpy(cap->driver, "vpif display", sizeof(cap->driver)); - strlcpy(cap->bus_info, "Platform", sizeof(cap->bus_info)); - strlcpy(cap->card, config->card_name, sizeof(cap->card)); - - return 0; -} - -static int vpif_enum_fmt_vid_out(struct file *file, void *priv, - struct v4l2_fmtdesc *fmt) -{ - if (fmt->index != 0) { - vpif_err("Invalid format index\n"); - return -EINVAL; - } - - /* Fill in the information about format */ - fmt->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; - strcpy(fmt->description, "YCbCr4:2:2 YC Planar"); - fmt->pixelformat = V4L2_PIX_FMT_YUV422P; - - return 0; -} - -static int vpif_g_fmt_vid_out(struct file *file, void *priv, - struct v4l2_format *fmt) -{ - struct vpif_fh *fh = priv; - struct channel_obj *ch = fh->channel; - struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; - - /* Check the validity of the buffer type */ - if (common->fmt.type != fmt->type) - return -EINVAL; - - /* Fill in the information about format */ - if (mutex_lock_interruptible(&common->lock)) - return -ERESTARTSYS; - - if (vpif_get_std_info(ch)) { - vpif_err("Error getting the standard info\n"); - return -EINVAL; - } - - *fmt = common->fmt; - mutex_unlock(&common->lock); - return 0; -} - -static int vpif_s_fmt_vid_out(struct file *file, void *priv, - struct v4l2_format *fmt) -{ - struct vpif_fh *fh = priv; - struct v4l2_pix_format *pixfmt; - struct channel_obj *ch = fh->channel; - struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; - int ret = 0; - - if ((VPIF_CHANNEL2_VIDEO == ch->channel_id) - || (VPIF_CHANNEL3_VIDEO == ch->channel_id)) { - if (!fh->initialized) { - vpif_dbg(1, debug, "Channel Busy\n"); - return -EBUSY; - } - - /* Check for the priority */ - ret = v4l2_prio_check(&ch->prio, fh->prio); - if (0 != ret) - return ret; - fh->initialized = 1; - } - - if (common->started) { - vpif_dbg(1, debug, "Streaming in progress\n"); - return -EBUSY; - } - - pixfmt = &fmt->fmt.pix; - /* Check for valid field format */ - ret = vpif_check_format(ch, pixfmt); - if (ret) - return ret; - - /* store the pix format in the channel object */ - common->fmt.fmt.pix = *pixfmt; - /* store the format in the channel object */ - if (mutex_lock_interruptible(&common->lock)) - return -ERESTARTSYS; - - common->fmt = *fmt; - mutex_unlock(&common->lock); - - return 0; -} - -static int vpif_try_fmt_vid_out(struct file *file, void *priv, - struct v4l2_format *fmt) -{ - struct vpif_fh *fh = priv; - struct channel_obj *ch = fh->channel; - struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; - struct v4l2_pix_format *pixfmt = &fmt->fmt.pix; - int ret = 0; - - ret = vpif_check_format(ch, pixfmt); - if (ret) { - *pixfmt = common->fmt.fmt.pix; - pixfmt->sizeimage = pixfmt->width * pixfmt->height * 2; - } - - return ret; -} - -static int vpif_reqbufs(struct file *file, void *priv, - struct v4l2_requestbuffers *reqbuf) -{ - struct vpif_fh *fh = priv; - struct channel_obj *ch = fh->channel; - struct common_obj *common; - enum v4l2_field field; - u8 index = 0; - int ret = 0; - - /* This file handle has not initialized the channel, - It is not allowed to do settings */ - if ((VPIF_CHANNEL2_VIDEO == ch->channel_id) - || (VPIF_CHANNEL3_VIDEO == ch->channel_id)) { - if (!fh->initialized) { - vpif_err("Channel Busy\n"); - return -EBUSY; - } - } - - if (V4L2_BUF_TYPE_VIDEO_OUTPUT != reqbuf->type) - return -EINVAL; - - index = VPIF_VIDEO_INDEX; - - common = &ch->common[index]; - if (mutex_lock_interruptible(&common->lock)) - return -ERESTARTSYS; - - if (common->fmt.type != reqbuf->type) { - ret = -EINVAL; - goto reqbuf_exit; - } - - if (0 != common->io_usrs) { - ret = -EBUSY; - goto reqbuf_exit; - } - - if (reqbuf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { - if (common->fmt.fmt.pix.field == V4L2_FIELD_ANY) - field = V4L2_FIELD_INTERLACED; - else - field = common->fmt.fmt.pix.field; - } else { - field = V4L2_VBI_INTERLACED; - } - - /* Initialize videobuf queue as per the buffer type */ - videobuf_queue_dma_contig_init(&common->buffer_queue, - &video_qops, NULL, - &common->irqlock, - reqbuf->type, field, - sizeof(struct videobuf_buffer), fh, - NULL); - - /* Set io allowed member of file handle to TRUE */ - fh->io_allowed[index] = 1; - /* Increment io usrs member of channel object to 1 */ - common->io_usrs = 1; - /* Store type of memory requested in channel object */ - common->memory = reqbuf->memory; - INIT_LIST_HEAD(&common->dma_queue); - - /* Allocate buffers */ - ret = videobuf_reqbufs(&common->buffer_queue, reqbuf); - -reqbuf_exit: - mutex_unlock(&common->lock); - return ret; -} - -static int vpif_querybuf(struct file *file, void *priv, - struct v4l2_buffer *tbuf) -{ - struct vpif_fh *fh = priv; - struct channel_obj *ch = fh->channel; - struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; - - if (common->fmt.type != tbuf->type) - return -EINVAL; - - return videobuf_querybuf(&common->buffer_queue, tbuf); -} - -static int vpif_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) -{ - - struct vpif_fh *fh = priv; - struct channel_obj *ch = fh->channel; - struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; - struct v4l2_buffer tbuf = *buf; - struct videobuf_buffer *buf1; - unsigned long addr = 0; - unsigned long flags; - int ret = 0; - - if (common->fmt.type != tbuf.type) - return -EINVAL; - - if (!fh->io_allowed[VPIF_VIDEO_INDEX]) { - vpif_err("fh->io_allowed\n"); - return -EACCES; - } - - if (!(list_empty(&common->dma_queue)) || - (common->cur_frm != common->next_frm) || - !(common->started) || - (common->started && (0 == ch->field_id))) - return videobuf_qbuf(&common->buffer_queue, buf); - - /* bufferqueue is empty store buffer address in VPIF registers */ - mutex_lock(&common->buffer_queue.vb_lock); - buf1 = common->buffer_queue.bufs[tbuf.index]; - if (buf1->memory != tbuf.memory) { - vpif_err("invalid buffer type\n"); - goto qbuf_exit; - } - - if ((buf1->state == VIDEOBUF_QUEUED) || - (buf1->state == VIDEOBUF_ACTIVE)) { - vpif_err("invalid state\n"); - goto qbuf_exit; - } - - switch (buf1->memory) { - case V4L2_MEMORY_MMAP: - if (buf1->baddr == 0) - goto qbuf_exit; - break; - - case V4L2_MEMORY_USERPTR: - if (tbuf.length < buf1->bsize) - goto qbuf_exit; - - if ((VIDEOBUF_NEEDS_INIT != buf1->state) - && (buf1->baddr != tbuf.m.userptr)) { - vpif_buffer_release(&common->buffer_queue, buf1); - buf1->baddr = tbuf.m.userptr; - } - break; - - default: - goto qbuf_exit; - } - - local_irq_save(flags); - ret = vpif_buffer_prepare(&common->buffer_queue, buf1, - common->buffer_queue.field); - if (ret < 0) { - local_irq_restore(flags); - goto qbuf_exit; - } - - buf1->state = VIDEOBUF_ACTIVE; - addr = buf1->boff; - common->next_frm = buf1; - if (tbuf.type != V4L2_BUF_TYPE_SLICED_VBI_OUTPUT) { - common->set_addr((addr + common->ytop_off), - (addr + common->ybtm_off), - (addr + common->ctop_off), - (addr + common->cbtm_off)); - } - - local_irq_restore(flags); - list_add_tail(&buf1->stream, &common->buffer_queue.stream); - mutex_unlock(&common->buffer_queue.vb_lock); - return 0; - -qbuf_exit: - mutex_unlock(&common->buffer_queue.vb_lock); - return -EINVAL; -} - -static int vpif_s_std(struct file *file, void *priv, v4l2_std_id *std_id) -{ - struct vpif_fh *fh = priv; - struct channel_obj *ch = fh->channel; - struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; - int ret = 0; - - if (!(*std_id & DM646X_V4L2_STD)) - return -EINVAL; - - if (common->started) { - vpif_err("streaming in progress\n"); - return -EBUSY; - } - - /* Call encoder subdevice function to set the standard */ - if (mutex_lock_interruptible(&common->lock)) - return -ERESTARTSYS; - - ch->video.stdid = *std_id; - /* Get the information about the standard */ - if (vpif_get_std_info(ch)) { - vpif_err("Error getting the standard info\n"); - return -EINVAL; - } - - if ((ch->vpifparams.std_info.width * - ch->vpifparams.std_info.height * 2) > - config_params.channel_bufsize[ch->channel_id]) { - vpif_err("invalid std for this size\n"); - ret = -EINVAL; - goto s_std_exit; - } - - common->fmt.fmt.pix.bytesperline = common->fmt.fmt.pix.width; - /* Configure the default format information */ - vpif_config_format(ch); - - ret = v4l2_device_call_until_err(&vpif_obj.v4l2_dev, 1, video, - s_std_output, *std_id); - if (ret < 0) { - vpif_err("Failed to set output standard\n"); - goto s_std_exit; - } - - ret = v4l2_device_call_until_err(&vpif_obj.v4l2_dev, 1, core, - s_std, *std_id); - if (ret < 0) - vpif_err("Failed to set standard for sub devices\n"); - -s_std_exit: - mutex_unlock(&common->lock); - return ret; -} - -static int vpif_g_std(struct file *file, void *priv, v4l2_std_id *std) -{ - struct vpif_fh *fh = priv; - struct channel_obj *ch = fh->channel; - - *std = ch->video.stdid; - return 0; -} - -static int vpif_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) -{ - struct vpif_fh *fh = priv; - struct channel_obj *ch = fh->channel; - struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; - - return videobuf_dqbuf(&common->buffer_queue, p, - (file->f_flags & O_NONBLOCK)); -} - -static int vpif_streamon(struct file *file, void *priv, - enum v4l2_buf_type buftype) -{ - struct vpif_fh *fh = priv; - struct channel_obj *ch = fh->channel; - struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; - struct channel_obj *oth_ch = vpif_obj.dev[!ch->channel_id]; - struct vpif_params *vpif = &ch->vpifparams; - struct vpif_display_config *vpif_config_data = - vpif_dev->platform_data; - unsigned long addr = 0; - int ret = 0; - - if (buftype != V4L2_BUF_TYPE_VIDEO_OUTPUT) { - vpif_err("buffer type not supported\n"); - return -EINVAL; - } - - if (!fh->io_allowed[VPIF_VIDEO_INDEX]) { - vpif_err("fh->io_allowed\n"); - return -EACCES; - } - - /* If Streaming is already started, return error */ - if (common->started) { - vpif_err("channel->started\n"); - return -EBUSY; - } - - if ((ch->channel_id == VPIF_CHANNEL2_VIDEO - && oth_ch->common[VPIF_VIDEO_INDEX].started && - ch->vpifparams.std_info.ycmux_mode == 0) - || ((ch->channel_id == VPIF_CHANNEL3_VIDEO) - && (2 == oth_ch->common[VPIF_VIDEO_INDEX].started))) { - vpif_err("other channel is using\n"); - return -EBUSY; - } - - ret = vpif_check_format(ch, &common->fmt.fmt.pix); - if (ret < 0) - return ret; - - /* Call videobuf_streamon to start streaming in videobuf */ - ret = videobuf_streamon(&common->buffer_queue); - if (ret < 0) { - vpif_err("videobuf_streamon\n"); - return ret; - } - - if (mutex_lock_interruptible(&common->lock)) - return -ERESTARTSYS; - - /* If buffer queue is empty, return error */ - if (list_empty(&common->dma_queue)) { - vpif_err("buffer queue is empty\n"); - ret = -EIO; - goto streamon_exit; - } - - /* Get the next frame from the buffer queue */ - common->next_frm = common->cur_frm = - list_entry(common->dma_queue.next, - struct videobuf_buffer, queue); - - list_del(&common->cur_frm->queue); - /* Mark state of the current frame to active */ - common->cur_frm->state = VIDEOBUF_ACTIVE; - - /* Initialize field_id and started member */ - ch->field_id = 0; - common->started = 1; - if (buftype == V4L2_BUF_TYPE_VIDEO_OUTPUT) { - addr = common->cur_frm->boff; - /* Calculate the offset for Y and C data in the buffer */ - vpif_calculate_offsets(ch); - - if ((ch->vpifparams.std_info.frm_fmt && - ((common->fmt.fmt.pix.field != V4L2_FIELD_NONE) - && (common->fmt.fmt.pix.field != V4L2_FIELD_ANY))) - || (!ch->vpifparams.std_info.frm_fmt - && (common->fmt.fmt.pix.field == V4L2_FIELD_NONE))) { - vpif_err("conflict in field format and std format\n"); - ret = -EINVAL; - goto streamon_exit; - } - - /* clock settings */ - ret = - vpif_config_data->set_clock(ch->vpifparams.std_info.ycmux_mode, - ch->vpifparams.std_info.hd_sd); - if (ret < 0) { - vpif_err("can't set clock\n"); - goto streamon_exit; - } - - /* set the parameters and addresses */ - ret = vpif_set_video_params(vpif, ch->channel_id + 2); - if (ret < 0) - goto streamon_exit; - - common->started = ret; - vpif_config_addr(ch, ret); - common->set_addr((addr + common->ytop_off), - (addr + common->ybtm_off), - (addr + common->ctop_off), - (addr + common->cbtm_off)); - - /* Set interrupt for both the fields in VPIF - Register enable channel in VPIF register */ - if (VPIF_CHANNEL2_VIDEO == ch->channel_id) { - channel2_intr_assert(); - channel2_intr_enable(1); - enable_channel2(1); - } - - if ((VPIF_CHANNEL3_VIDEO == ch->channel_id) - || (common->started == 2)) { - channel3_intr_assert(); - channel3_intr_enable(1); - enable_channel3(1); - } - channel_first_int[VPIF_VIDEO_INDEX][ch->channel_id] = 1; - } - -streamon_exit: - mutex_unlock(&common->lock); - return ret; -} - -static int vpif_streamoff(struct file *file, void *priv, - enum v4l2_buf_type buftype) -{ - struct vpif_fh *fh = priv; - struct channel_obj *ch = fh->channel; - struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; - - if (buftype != V4L2_BUF_TYPE_VIDEO_OUTPUT) { - vpif_err("buffer type not supported\n"); - return -EINVAL; - } - - if (!fh->io_allowed[VPIF_VIDEO_INDEX]) { - vpif_err("fh->io_allowed\n"); - return -EACCES; - } - - if (!common->started) { - vpif_err("channel->started\n"); - return -EINVAL; - } - - if (mutex_lock_interruptible(&common->lock)) - return -ERESTARTSYS; - - if (buftype == V4L2_BUF_TYPE_VIDEO_OUTPUT) { - /* disable channel */ - if (VPIF_CHANNEL2_VIDEO == ch->channel_id) { - enable_channel2(0); - channel2_intr_enable(0); - } - if ((VPIF_CHANNEL3_VIDEO == ch->channel_id) || - (2 == common->started)) { - enable_channel3(0); - channel3_intr_enable(0); - } - } - - common->started = 0; - mutex_unlock(&common->lock); - - return videobuf_streamoff(&common->buffer_queue); -} - -static int vpif_cropcap(struct file *file, void *priv, - struct v4l2_cropcap *crop) -{ - struct vpif_fh *fh = priv; - struct channel_obj *ch = fh->channel; - struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; - if (V4L2_BUF_TYPE_VIDEO_OUTPUT != crop->type) - return -EINVAL; - - crop->bounds.left = crop->bounds.top = 0; - crop->defrect.left = crop->defrect.top = 0; - crop->defrect.height = crop->bounds.height = common->height; - crop->defrect.width = crop->bounds.width = common->width; - - return 0; -} - -static int vpif_enum_output(struct file *file, void *fh, - struct v4l2_output *output) -{ - - struct vpif_display_config *config = vpif_dev->platform_data; - - if (output->index >= config->output_count) { - vpif_dbg(1, debug, "Invalid output index\n"); - return -EINVAL; - } - - strcpy(output->name, config->output[output->index]); - output->type = V4L2_OUTPUT_TYPE_ANALOG; - output->std = DM646X_V4L2_STD; - - return 0; -} - -static int vpif_s_output(struct file *file, void *priv, unsigned int i) -{ - struct vpif_fh *fh = priv; - struct channel_obj *ch = fh->channel; - struct video_obj *vid_ch = &ch->video; - struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; - int ret = 0; - - if (mutex_lock_interruptible(&common->lock)) - return -ERESTARTSYS; - - if (common->started) { - vpif_err("Streaming in progress\n"); - ret = -EBUSY; - goto s_output_exit; - } - - ret = v4l2_device_call_until_err(&vpif_obj.v4l2_dev, 1, video, - s_routing, 0, i, 0); - - if (ret < 0) - vpif_err("Failed to set output standard\n"); - - vid_ch->output_id = i; - -s_output_exit: - mutex_unlock(&common->lock); - return ret; -} - -static int vpif_g_output(struct file *file, void *priv, unsigned int *i) -{ - struct vpif_fh *fh = priv; - struct channel_obj *ch = fh->channel; - struct video_obj *vid_ch = &ch->video; - - *i = vid_ch->output_id; - - return 0; -} - -static int vpif_g_priority(struct file *file, void *priv, enum v4l2_priority *p) -{ - struct vpif_fh *fh = priv; - struct channel_obj *ch = fh->channel; - - *p = v4l2_prio_max(&ch->prio); - - return 0; -} - -static int vpif_s_priority(struct file *file, void *priv, enum v4l2_priority p) -{ - struct vpif_fh *fh = priv; - struct channel_obj *ch = fh->channel; - - return v4l2_prio_change(&ch->prio, &fh->prio, p); -} - -/* vpif display ioctl operations */ -static const struct v4l2_ioctl_ops vpif_ioctl_ops = { - .vidioc_querycap = vpif_querycap, - .vidioc_g_priority = vpif_g_priority, - .vidioc_s_priority = vpif_s_priority, - .vidioc_enum_fmt_vid_out = vpif_enum_fmt_vid_out, - .vidioc_g_fmt_vid_out = vpif_g_fmt_vid_out, - .vidioc_s_fmt_vid_out = vpif_s_fmt_vid_out, - .vidioc_try_fmt_vid_out = vpif_try_fmt_vid_out, - .vidioc_reqbufs = vpif_reqbufs, - .vidioc_querybuf = vpif_querybuf, - .vidioc_qbuf = vpif_qbuf, - .vidioc_dqbuf = vpif_dqbuf, - .vidioc_streamon = vpif_streamon, - .vidioc_streamoff = vpif_streamoff, - .vidioc_s_std = vpif_s_std, - .vidioc_g_std = vpif_g_std, - .vidioc_enum_output = vpif_enum_output, - .vidioc_s_output = vpif_s_output, - .vidioc_g_output = vpif_g_output, - .vidioc_cropcap = vpif_cropcap, -}; - -static const struct v4l2_file_operations vpif_fops = { - .owner = THIS_MODULE, - .open = vpif_open, - .release = vpif_release, - .ioctl = video_ioctl2, - .mmap = vpif_mmap, - .poll = vpif_poll -}; - -static struct video_device vpif_video_template = { - .name = "vpif", - .fops = &vpif_fops, - .ioctl_ops = &vpif_ioctl_ops, - .tvnorms = DM646X_V4L2_STD, - .current_norm = V4L2_STD_625_50, - -}; - -/*Configure the channels, buffer sizei, request irq */ -static int initialize_vpif(void) -{ - int free_channel_objects_index; - int free_buffer_channel_index; - int free_buffer_index; - int err = 0, i, j; - - /* Default number of buffers should be 3 */ - if ((ch2_numbuffers > 0) && - (ch2_numbuffers < config_params.min_numbuffers)) - ch2_numbuffers = config_params.min_numbuffers; - if ((ch3_numbuffers > 0) && - (ch3_numbuffers < config_params.min_numbuffers)) - ch3_numbuffers = config_params.min_numbuffers; - - /* Set buffer size to min buffers size if invalid buffer size is - * given */ - if (ch2_bufsize < config_params.min_bufsize[VPIF_CHANNEL2_VIDEO]) - ch2_bufsize = - config_params.min_bufsize[VPIF_CHANNEL2_VIDEO]; - if (ch3_bufsize < config_params.min_bufsize[VPIF_CHANNEL3_VIDEO]) - ch3_bufsize = - config_params.min_bufsize[VPIF_CHANNEL3_VIDEO]; - - config_params.numbuffers[VPIF_CHANNEL2_VIDEO] = ch2_numbuffers; - - if (ch2_numbuffers) { - config_params.channel_bufsize[VPIF_CHANNEL2_VIDEO] = - ch2_bufsize; - } - config_params.numbuffers[VPIF_CHANNEL3_VIDEO] = ch3_numbuffers; - - if (ch3_numbuffers) { - config_params.channel_bufsize[VPIF_CHANNEL3_VIDEO] = - ch3_bufsize; - } - - /* Allocate memory for six channel objects */ - for (i = 0; i < VPIF_DISPLAY_MAX_DEVICES; i++) { - vpif_obj.dev[i] = - kzalloc(sizeof(struct channel_obj), GFP_KERNEL); - /* If memory allocation fails, return error */ - if (!vpif_obj.dev[i]) { - free_channel_objects_index = i; - err = -ENOMEM; - goto vpif_init_free_channel_objects; - } - } - - free_channel_objects_index = VPIF_DISPLAY_MAX_DEVICES; - free_buffer_channel_index = VPIF_DISPLAY_NUM_CHANNELS; - free_buffer_index = config_params.numbuffers[i - 1]; - - return 0; - -vpif_init_free_channel_objects: - for (j = 0; j < free_channel_objects_index; j++) - kfree(vpif_obj.dev[j]); - return err; -} - -/* - * vpif_probe: This function creates device entries by register itself to the - * V4L2 driver and initializes fields of each channel objects - */ -static __init int vpif_probe(struct platform_device *pdev) -{ - struct vpif_subdev_info *subdevdata; - struct vpif_display_config *config; - int i, j = 0, k, q, m, err = 0; - struct i2c_adapter *i2c_adap; - struct common_obj *common; - struct channel_obj *ch; - struct video_device *vfd; - struct resource *res; - int subdev_count; - - vpif_dev = &pdev->dev; - - err = initialize_vpif(); - - if (err) { - v4l2_err(vpif_dev->driver, "Error initializing vpif\n"); - return err; - } - - err = v4l2_device_register(vpif_dev, &vpif_obj.v4l2_dev); - if (err) { - v4l2_err(vpif_dev->driver, "Error registering v4l2 device\n"); - return err; - } - - k = 0; - while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, k))) { - for (i = res->start; i <= res->end; i++) { - if (request_irq(i, vpif_channel_isr, IRQF_DISABLED, - "DM646x_Display", - (void *)(&vpif_obj.dev[k]->channel_id))) { - err = -EBUSY; - goto vpif_int_err; - } - } - k++; - } - - for (i = 0; i < VPIF_DISPLAY_MAX_DEVICES; i++) { - - /* Get the pointer to the channel object */ - ch = vpif_obj.dev[i]; - - /* Allocate memory for video device */ - vfd = video_device_alloc(); - if (vfd == NULL) { - for (j = 0; j < i; j++) { - ch = vpif_obj.dev[j]; - video_device_release(ch->video_dev); - } - err = -ENOMEM; - goto vpif_int_err; - } - - /* Initialize field of video device */ - *vfd = vpif_video_template; - vfd->v4l2_dev = &vpif_obj.v4l2_dev; - vfd->release = video_device_release; - snprintf(vfd->name, sizeof(vfd->name), - "DM646x_VPIFDisplay_DRIVER_V%d.%d.%d", - (VPIF_DISPLAY_VERSION_CODE >> 16) & 0xff, - (VPIF_DISPLAY_VERSION_CODE >> 8) & 0xff, - (VPIF_DISPLAY_VERSION_CODE) & 0xff); - - /* Set video_dev to the video device */ - ch->video_dev = vfd; - } - - for (j = 0; j < VPIF_DISPLAY_MAX_DEVICES; j++) { - ch = vpif_obj.dev[j]; - /* Initialize field of the channel objects */ - atomic_set(&ch->usrs, 0); - for (k = 0; k < VPIF_NUMOBJECTS; k++) { - ch->common[k].numbuffers = 0; - common = &ch->common[k]; - common->io_usrs = 0; - common->started = 0; - spin_lock_init(&common->irqlock); - mutex_init(&common->lock); - common->numbuffers = 0; - common->set_addr = NULL; - common->ytop_off = common->ybtm_off = 0; - common->ctop_off = common->cbtm_off = 0; - common->cur_frm = common->next_frm = NULL; - memset(&common->fmt, 0, sizeof(common->fmt)); - common->numbuffers = config_params.numbuffers[k]; - - } - ch->initialized = 0; - ch->channel_id = j; - if (j < 2) - ch->common[VPIF_VIDEO_INDEX].numbuffers = - config_params.numbuffers[ch->channel_id]; - else - ch->common[VPIF_VIDEO_INDEX].numbuffers = 0; - - memset(&ch->vpifparams, 0, sizeof(ch->vpifparams)); - - /* Initialize prio member of channel object */ - v4l2_prio_init(&ch->prio); - ch->common[VPIF_VIDEO_INDEX].fmt.type = - V4L2_BUF_TYPE_VIDEO_OUTPUT; - - /* register video device */ - vpif_dbg(1, debug, "channel=%x,channel->video_dev=%x\n", - (int)ch, (int)&ch->video_dev); - - err = video_register_device(ch->video_dev, - VFL_TYPE_GRABBER, (j ? 3 : 2)); - if (err < 0) - goto probe_out; - - video_set_drvdata(ch->video_dev, ch); - } - - i2c_adap = i2c_get_adapter(1); - config = pdev->dev.platform_data; - subdev_count = config->subdev_count; - subdevdata = config->subdevinfo; - vpif_obj.sd = kzalloc(sizeof(struct v4l2_subdev *) * subdev_count, - GFP_KERNEL); - if (vpif_obj.sd == NULL) { - vpif_err("unable to allocate memory for subdevice pointers\n"); - err = -ENOMEM; - goto probe_out; - } - - for (i = 0; i < subdev_count; i++) { - vpif_obj.sd[i] = v4l2_i2c_new_subdev_board(&vpif_obj.v4l2_dev, - i2c_adap, NULL, - &subdevdata[i].board_info, - NULL); - if (!vpif_obj.sd[i]) { - vpif_err("Error registering v4l2 subdevice\n"); - goto probe_subdev_out; - } - - if (vpif_obj.sd[i]) - vpif_obj.sd[i]->grp_id = 1 << i; - } - - return 0; - -probe_subdev_out: - kfree(vpif_obj.sd); -probe_out: - for (k = 0; k < j; k++) { - ch = vpif_obj.dev[k]; - video_unregister_device(ch->video_dev); - video_device_release(ch->video_dev); - ch->video_dev = NULL; - } -vpif_int_err: - v4l2_device_unregister(&vpif_obj.v4l2_dev); - vpif_err("VPIF IRQ request failed\n"); - for (q = k; k >= 0; k--) { - for (m = i; m >= res->start; m--) - free_irq(m, (void *)(&vpif_obj.dev[k]->channel_id)); - res = platform_get_resource(pdev, IORESOURCE_IRQ, k-1); - m = res->end; - } - - return err; -} - -/* - * vpif_remove: It un-register channels from V4L2 driver - */ -static int vpif_remove(struct platform_device *device) -{ - struct channel_obj *ch; - int i; - - v4l2_device_unregister(&vpif_obj.v4l2_dev); - - /* un-register device */ - for (i = 0; i < VPIF_DISPLAY_MAX_DEVICES; i++) { - /* Get the pointer to the channel object */ - ch = vpif_obj.dev[i]; - /* Unregister video device */ - video_unregister_device(ch->video_dev); - - ch->video_dev = NULL; - } - - return 0; -} - -static __refdata struct platform_driver vpif_driver = { - .driver = { - .name = "vpif_display", - .owner = THIS_MODULE, - }, - .probe = vpif_probe, - .remove = vpif_remove, -}; - -static __init int vpif_init(void) -{ - return platform_driver_register(&vpif_driver); -} - -/* - * vpif_cleanup: This function un-registers device and driver to the kernel, - * frees requested irq handler and de-allocates memory allocated for channel - * objects. - */ -static void vpif_cleanup(void) -{ - struct platform_device *pdev; - struct resource *res; - int irq_num; - int i = 0; - - pdev = container_of(vpif_dev, struct platform_device, dev); - - while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, i))) { - for (irq_num = res->start; irq_num <= res->end; irq_num++) - free_irq(irq_num, - (void *)(&vpif_obj.dev[i]->channel_id)); - i++; - } - - platform_driver_unregister(&vpif_driver); - kfree(vpif_obj.sd); - for (i = 0; i < VPIF_DISPLAY_MAX_DEVICES; i++) - kfree(vpif_obj.dev[i]); -} - -module_init(vpif_init); -module_exit(vpif_cleanup); diff --git a/drivers/media/video/davinci/vpif_display.h b/drivers/media/video/davinci/vpif_display.h deleted file mode 100644 index a2a7cd166bb..00000000000 --- a/drivers/media/video/davinci/vpif_display.h +++ /dev/null @@ -1,175 +0,0 @@ -/* - * DM646x display header file - * - * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/ - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation version 2. - * - * This program is distributed .as is. WITHOUT ANY WARRANTY of any - * kind, whether express or implied; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef DAVINCIHD_DISPLAY_H -#define DAVINCIHD_DISPLAY_H - -/* Header files */ -#include <linux/videodev2.h> -#include <linux/version.h> -#include <media/v4l2-common.h> -#include <media/v4l2-device.h> -#include <media/videobuf-core.h> -#include <media/videobuf-dma-contig.h> - -#include "vpif.h" - -/* Macros */ -#define VPIF_MAJOR_RELEASE (0) -#define VPIF_MINOR_RELEASE (0) -#define VPIF_BUILD (1) - -#define VPIF_DISPLAY_VERSION_CODE \ - ((VPIF_MAJOR_RELEASE << 16) | (VPIF_MINOR_RELEASE << 8) | VPIF_BUILD) - -#define VPIF_VALID_FIELD(field) \ - (((V4L2_FIELD_ANY == field) || (V4L2_FIELD_NONE == field)) || \ - (((V4L2_FIELD_INTERLACED == field) || (V4L2_FIELD_SEQ_TB == field)) || \ - (V4L2_FIELD_SEQ_BT == field))) - -#define VPIF_DISPLAY_MAX_DEVICES (2) -#define VPIF_SLICED_BUF_SIZE (256) -#define VPIF_SLICED_MAX_SERVICES (3) -#define VPIF_VIDEO_INDEX (0) -#define VPIF_VBI_INDEX (1) -#define VPIF_HBI_INDEX (2) - -/* Setting it to 1 as HBI/VBI support yet to be added , else 3*/ -#define VPIF_NUMOBJECTS (1) - -/* Macros */ -#define ISALIGNED(a) (0 == ((a) & 7)) - -/* enumerated data types */ -/* Enumerated data type to give id to each device per channel */ -enum vpif_channel_id { - VPIF_CHANNEL2_VIDEO = 0, /* Channel2 Video */ - VPIF_CHANNEL3_VIDEO, /* Channel3 Video */ -}; - -/* structures */ - -struct video_obj { - enum v4l2_field buf_field; - u32 latest_only; /* indicate whether to return - * most recent displayed frame only */ - v4l2_std_id stdid; /* Currently selected or default - * standard */ - u32 output_id; /* Current output id */ -}; - -struct vbi_obj { - int num_services; - struct vpif_vbi_params vbiparams; /* vpif parameters for the raw - * vbi data */ -}; - -struct common_obj { - /* Buffer specific parameters */ - u8 *fbuffers[VIDEO_MAX_FRAME]; /* List of buffer pointers for - * storing frames */ - u32 numbuffers; /* number of buffers */ - struct videobuf_buffer *cur_frm; /* Pointer pointing to current - * videobuf_buffer */ - struct videobuf_buffer *next_frm; /* Pointer pointing to next - * videobuf_buffer */ - enum v4l2_memory memory; /* This field keeps track of - * type of buffer exchange - * method user has selected */ - struct v4l2_format fmt; /* Used to store the format */ - struct videobuf_queue buffer_queue; /* Buffer queue used in - * video-buf */ - struct list_head dma_queue; /* Queue of filled frames */ - spinlock_t irqlock; /* Used in video-buf */ - - /* channel specific parameters */ - struct mutex lock; /* lock used to access this - * structure */ - u32 io_usrs; /* number of users performing - * IO */ - u8 started; /* Indicates whether streaming - * started */ - u32 ytop_off; /* offset of Y top from the - * starting of the buffer */ - u32 ybtm_off; /* offset of Y bottom from the - * starting of the buffer */ - u32 ctop_off; /* offset of C top from the - * starting of the buffer */ - u32 cbtm_off; /* offset of C bottom from the - * starting of the buffer */ - /* Function pointer to set the addresses */ - void (*set_addr) (unsigned long, unsigned long, - unsigned long, unsigned long); - u32 height; - u32 width; -}; - -struct channel_obj { - /* V4l2 specific parameters */ - struct video_device *video_dev; /* Identifies video device for - * this channel */ - struct v4l2_prio_state prio; /* Used to keep track of state of - * the priority */ - atomic_t usrs; /* number of open instances of - * the channel */ - u32 field_id; /* Indicates id of the field - * which is being displayed */ - u8 initialized; /* flag to indicate whether - * encoder is initialized */ - - enum vpif_channel_id channel_id;/* Identifies channel */ - struct vpif_params vpifparams; - struct common_obj common[VPIF_NUMOBJECTS]; - struct video_obj video; - struct vbi_obj vbi; -}; - -/* File handle structure */ -struct vpif_fh { - struct channel_obj *channel; /* pointer to channel object for - * opened device */ - u8 io_allowed[VPIF_NUMOBJECTS]; /* Indicates whether this file handle - * is doing IO */ - enum v4l2_priority prio; /* Used to keep track priority of - * this instance */ - u8 initialized; /* Used to keep track of whether this - * file handle has initialized - * channel or not */ -}; - -/* vpif device structure */ -struct vpif_device { - struct v4l2_device v4l2_dev; - struct channel_obj *dev[VPIF_DISPLAY_NUM_CHANNELS]; - struct v4l2_subdev **sd; - -}; - -struct vpif_config_params { - u32 min_bufsize[VPIF_DISPLAY_NUM_CHANNELS]; - u32 channel_bufsize[VPIF_DISPLAY_NUM_CHANNELS]; - u8 numbuffers[VPIF_DISPLAY_NUM_CHANNELS]; - u8 min_numbuffers; -}; - -/* Struct which keeps track of the line numbers for the sliced vbi service */ -struct vpif_service_line { - u16 service_id; - u16 service_line[2]; - u16 enc_service_id; - u8 bytestowrite; -}; - -#endif /* DAVINCIHD_DISPLAY_H */ diff --git a/drivers/media/video/davinci/vpss.c b/drivers/media/video/davinci/vpss.c deleted file mode 100644 index 7918680917d..00000000000 --- a/drivers/media/video/davinci/vpss.c +++ /dev/null @@ -1,482 +0,0 @@ -/* - * Copyright (C) 2009 Texas Instruments. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * common vpss system module platform driver for all video drivers. - */ -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/init.h> -#include <linux/module.h> -#include <linux/platform_device.h> -#include <linux/spinlock.h> -#include <linux/compiler.h> -#include <linux/io.h> -#include <mach/hardware.h> -#include <media/davinci/vpss.h> - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("VPSS Driver"); -MODULE_AUTHOR("Texas Instruments"); - -/* DM644x defines */ -#define DM644X_SBL_PCR_VPSS (4) - -#define DM355_VPSSBL_INTSEL 0x10 -#define DM355_VPSSBL_EVTSEL 0x14 -/* vpss BL register offsets */ -#define DM355_VPSSBL_CCDCMUX 0x1c -/* vpss CLK register offsets */ -#define DM355_VPSSCLK_CLKCTRL 0x04 -/* masks and shifts */ -#define VPSS_HSSISEL_SHIFT 4 -/* - * VDINT0 - vpss_int0, VDINT1 - vpss_int1, H3A - vpss_int4, - * IPIPE_INT1_SDR - vpss_int5 - */ -#define DM355_VPSSBL_INTSEL_DEFAULT 0xff83ff10 -/* VENCINT - vpss_int8 */ -#define DM355_VPSSBL_EVTSEL_DEFAULT 0x4 - -#define DM365_ISP5_PCCR 0x04 -#define DM365_ISP5_INTSEL1 0x10 -#define DM365_ISP5_INTSEL2 0x14 -#define DM365_ISP5_INTSEL3 0x18 -#define DM365_ISP5_CCDCMUX 0x20 -#define DM365_ISP5_PG_FRAME_SIZE 0x28 -#define DM365_VPBE_CLK_CTRL 0x00 -/* - * vpss interrupts. VDINT0 - vpss_int0, VDINT1 - vpss_int1, - * AF - vpss_int3 - */ -#define DM365_ISP5_INTSEL1_DEFAULT 0x0b1f0100 -/* AEW - vpss_int6, RSZ_INT_DMA - vpss_int5 */ -#define DM365_ISP5_INTSEL2_DEFAULT 0x1f0a0f1f -/* VENC - vpss_int8 */ -#define DM365_ISP5_INTSEL3_DEFAULT 0x00000015 - -/* masks and shifts for DM365*/ -#define DM365_CCDC_PG_VD_POL_SHIFT 0 -#define DM365_CCDC_PG_HD_POL_SHIFT 1 - -#define CCD_SRC_SEL_MASK (BIT_MASK(5) | BIT_MASK(4)) -#define CCD_SRC_SEL_SHIFT 4 - -/* Different SoC platforms supported by this driver */ -enum vpss_platform_type { - DM644X, - DM355, - DM365, -}; - -/* - * vpss operations. Depends on platform. Not all functions are available - * on all platforms. The api, first check if a functio is available before - * invoking it. In the probe, the function ptrs are intialized based on - * vpss name. vpss name can be "dm355_vpss", "dm644x_vpss" etc. - */ -struct vpss_hw_ops { - /* enable clock */ - int (*enable_clock)(enum vpss_clock_sel clock_sel, int en); - /* select input to ccdc */ - void (*select_ccdc_source)(enum vpss_ccdc_source_sel src_sel); - /* clear wbl overflow bit */ - int (*clear_wbl_overflow)(enum vpss_wbl_sel wbl_sel); -}; - -/* vpss configuration */ -struct vpss_oper_config { - __iomem void *vpss_regs_base0; - __iomem void *vpss_regs_base1; - enum vpss_platform_type platform; - spinlock_t vpss_lock; - struct vpss_hw_ops hw_ops; -}; - -static struct vpss_oper_config oper_cfg; - -/* register access routines */ -static inline u32 bl_regr(u32 offset) -{ - return __raw_readl(oper_cfg.vpss_regs_base0 + offset); -} - -static inline void bl_regw(u32 val, u32 offset) -{ - __raw_writel(val, oper_cfg.vpss_regs_base0 + offset); -} - -static inline u32 vpss_regr(u32 offset) -{ - return __raw_readl(oper_cfg.vpss_regs_base1 + offset); -} - -static inline void vpss_regw(u32 val, u32 offset) -{ - __raw_writel(val, oper_cfg.vpss_regs_base1 + offset); -} - -/* For DM365 only */ -static inline u32 isp5_read(u32 offset) -{ - return __raw_readl(oper_cfg.vpss_regs_base0 + offset); -} - -/* For DM365 only */ -static inline void isp5_write(u32 val, u32 offset) -{ - __raw_writel(val, oper_cfg.vpss_regs_base0 + offset); -} - -static void dm365_select_ccdc_source(enum vpss_ccdc_source_sel src_sel) -{ - u32 temp = isp5_read(DM365_ISP5_CCDCMUX) & ~CCD_SRC_SEL_MASK; - - /* if we are using pattern generator, enable it */ - if (src_sel == VPSS_PGLPBK || src_sel == VPSS_CCDCPG) - temp |= 0x08; - - temp |= (src_sel << CCD_SRC_SEL_SHIFT); - isp5_write(temp, DM365_ISP5_CCDCMUX); -} - -static void dm355_select_ccdc_source(enum vpss_ccdc_source_sel src_sel) -{ - bl_regw(src_sel << VPSS_HSSISEL_SHIFT, DM355_VPSSBL_CCDCMUX); -} - -int vpss_select_ccdc_source(enum vpss_ccdc_source_sel src_sel) -{ - if (!oper_cfg.hw_ops.select_ccdc_source) - return -EINVAL; - - oper_cfg.hw_ops.select_ccdc_source(src_sel); - return 0; -} -EXPORT_SYMBOL(vpss_select_ccdc_source); - -static int dm644x_clear_wbl_overflow(enum vpss_wbl_sel wbl_sel) -{ - u32 mask = 1, val; - - if (wbl_sel < VPSS_PCR_AEW_WBL_0 || - wbl_sel > VPSS_PCR_CCDC_WBL_O) - return -EINVAL; - - /* writing a 0 clear the overflow */ - mask = ~(mask << wbl_sel); - val = bl_regr(DM644X_SBL_PCR_VPSS) & mask; - bl_regw(val, DM644X_SBL_PCR_VPSS); - return 0; -} - -int vpss_clear_wbl_overflow(enum vpss_wbl_sel wbl_sel) -{ - if (!oper_cfg.hw_ops.clear_wbl_overflow) - return -EINVAL; - - return oper_cfg.hw_ops.clear_wbl_overflow(wbl_sel); -} -EXPORT_SYMBOL(vpss_clear_wbl_overflow); - -/* - * dm355_enable_clock - Enable VPSS Clock - * @clock_sel: CLock to be enabled/disabled - * @en: enable/disable flag - * - * This is called to enable or disable a vpss clock - */ -static int dm355_enable_clock(enum vpss_clock_sel clock_sel, int en) -{ - unsigned long flags; - u32 utemp, mask = 0x1, shift = 0; - - switch (clock_sel) { - case VPSS_VPBE_CLOCK: - /* nothing since lsb */ - break; - case VPSS_VENC_CLOCK_SEL: - shift = 2; - break; - case VPSS_CFALD_CLOCK: - shift = 3; - break; - case VPSS_H3A_CLOCK: - shift = 4; - break; - case VPSS_IPIPE_CLOCK: - shift = 5; - break; - case VPSS_CCDC_CLOCK: - shift = 6; - break; - default: - printk(KERN_ERR "dm355_enable_clock:" - " Invalid selector: %d\n", clock_sel); - return -EINVAL; - } - - spin_lock_irqsave(&oper_cfg.vpss_lock, flags); - utemp = vpss_regr(DM355_VPSSCLK_CLKCTRL); - if (!en) - utemp &= ~(mask << shift); - else - utemp |= (mask << shift); - - vpss_regw(utemp, DM355_VPSSCLK_CLKCTRL); - spin_unlock_irqrestore(&oper_cfg.vpss_lock, flags); - return 0; -} - -static int dm365_enable_clock(enum vpss_clock_sel clock_sel, int en) -{ - unsigned long flags; - u32 utemp, mask = 0x1, shift = 0, offset = DM365_ISP5_PCCR; - u32 (*read)(u32 offset) = isp5_read; - void(*write)(u32 val, u32 offset) = isp5_write; - - switch (clock_sel) { - case VPSS_BL_CLOCK: - break; - case VPSS_CCDC_CLOCK: - shift = 1; - break; - case VPSS_H3A_CLOCK: - shift = 2; - break; - case VPSS_RSZ_CLOCK: - shift = 3; - break; - case VPSS_IPIPE_CLOCK: - shift = 4; - break; - case VPSS_IPIPEIF_CLOCK: - shift = 5; - break; - case VPSS_PCLK_INTERNAL: - shift = 6; - break; - case VPSS_PSYNC_CLOCK_SEL: - shift = 7; - break; - case VPSS_VPBE_CLOCK: - read = vpss_regr; - write = vpss_regw; - offset = DM365_VPBE_CLK_CTRL; - break; - case VPSS_VENC_CLOCK_SEL: - shift = 2; - read = vpss_regr; - write = vpss_regw; - offset = DM365_VPBE_CLK_CTRL; - break; - case VPSS_LDC_CLOCK: - shift = 3; - read = vpss_regr; - write = vpss_regw; - offset = DM365_VPBE_CLK_CTRL; - break; - case VPSS_FDIF_CLOCK: - shift = 4; - read = vpss_regr; - write = vpss_regw; - offset = DM365_VPBE_CLK_CTRL; - break; - case VPSS_OSD_CLOCK_SEL: - shift = 6; - read = vpss_regr; - write = vpss_regw; - offset = DM365_VPBE_CLK_CTRL; - break; - case VPSS_LDC_CLOCK_SEL: - shift = 7; - read = vpss_regr; - write = vpss_regw; - offset = DM365_VPBE_CLK_CTRL; - break; - default: - printk(KERN_ERR "dm365_enable_clock: Invalid selector: %d\n", - clock_sel); - return -1; - } - - spin_lock_irqsave(&oper_cfg.vpss_lock, flags); - utemp = read(offset); - if (!en) { - mask = ~mask; - utemp &= (mask << shift); - } else - utemp |= (mask << shift); - - write(utemp, offset); - spin_unlock_irqrestore(&oper_cfg.vpss_lock, flags); - - return 0; -} - -int vpss_enable_clock(enum vpss_clock_sel clock_sel, int en) -{ - if (!oper_cfg.hw_ops.enable_clock) - return -EINVAL; - - return oper_cfg.hw_ops.enable_clock(clock_sel, en); -} -EXPORT_SYMBOL(vpss_enable_clock); - -void dm365_vpss_set_sync_pol(struct vpss_sync_pol sync) -{ - int val = 0; - val = isp5_read(DM365_ISP5_CCDCMUX); - - val |= (sync.ccdpg_hdpol << DM365_CCDC_PG_HD_POL_SHIFT); - val |= (sync.ccdpg_vdpol << DM365_CCDC_PG_VD_POL_SHIFT); - - isp5_write(val, DM365_ISP5_CCDCMUX); -} -EXPORT_SYMBOL(dm365_vpss_set_sync_pol); - -void dm365_vpss_set_pg_frame_size(struct vpss_pg_frame_size frame_size) -{ - int current_reg = ((frame_size.hlpfr >> 1) - 1) << 16; - - current_reg |= (frame_size.pplen - 1); - isp5_write(current_reg, DM365_ISP5_PG_FRAME_SIZE); -} -EXPORT_SYMBOL(dm365_vpss_set_pg_frame_size); - -static int __init vpss_probe(struct platform_device *pdev) -{ - struct resource *r1, *r2; - char *platform_name; - int status; - - if (!pdev->dev.platform_data) { - dev_err(&pdev->dev, "no platform data\n"); - return -ENOENT; - } - - platform_name = pdev->dev.platform_data; - if (!strcmp(platform_name, "dm355_vpss")) - oper_cfg.platform = DM355; - else if (!strcmp(platform_name, "dm365_vpss")) - oper_cfg.platform = DM365; - else if (!strcmp(platform_name, "dm644x_vpss")) - oper_cfg.platform = DM644X; - else { - dev_err(&pdev->dev, "vpss driver not supported on" - " this platform\n"); - return -ENODEV; - } - - dev_info(&pdev->dev, "%s vpss probed\n", platform_name); - r1 = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!r1) - return -ENOENT; - - r1 = request_mem_region(r1->start, resource_size(r1), r1->name); - if (!r1) - return -EBUSY; - - oper_cfg.vpss_regs_base0 = ioremap(r1->start, resource_size(r1)); - if (!oper_cfg.vpss_regs_base0) { - status = -EBUSY; - goto fail1; - } - - if (oper_cfg.platform == DM355 || oper_cfg.platform == DM365) { - r2 = platform_get_resource(pdev, IORESOURCE_MEM, 1); - if (!r2) { - status = -ENOENT; - goto fail2; - } - r2 = request_mem_region(r2->start, resource_size(r2), r2->name); - if (!r2) { - status = -EBUSY; - goto fail2; - } - - oper_cfg.vpss_regs_base1 = ioremap(r2->start, - resource_size(r2)); - if (!oper_cfg.vpss_regs_base1) { - status = -EBUSY; - goto fail3; - } - } - - if (oper_cfg.platform == DM355) { - oper_cfg.hw_ops.enable_clock = dm355_enable_clock; - oper_cfg.hw_ops.select_ccdc_source = dm355_select_ccdc_source; - /* Setup vpss interrupts */ - bl_regw(DM355_VPSSBL_INTSEL_DEFAULT, DM355_VPSSBL_INTSEL); - bl_regw(DM355_VPSSBL_EVTSEL_DEFAULT, DM355_VPSSBL_EVTSEL); - } else if (oper_cfg.platform == DM365) { - oper_cfg.hw_ops.enable_clock = dm365_enable_clock; - oper_cfg.hw_ops.select_ccdc_source = dm365_select_ccdc_source; - /* Setup vpss interrupts */ - isp5_write(DM365_ISP5_INTSEL1_DEFAULT, DM365_ISP5_INTSEL1); - isp5_write(DM365_ISP5_INTSEL2_DEFAULT, DM365_ISP5_INTSEL2); - isp5_write(DM365_ISP5_INTSEL3_DEFAULT, DM365_ISP5_INTSEL3); - } else - oper_cfg.hw_ops.clear_wbl_overflow = dm644x_clear_wbl_overflow; - - spin_lock_init(&oper_cfg.vpss_lock); - dev_info(&pdev->dev, "%s vpss probe success\n", platform_name); - return 0; - -fail3: - release_mem_region(r2->start, resource_size(r2)); -fail2: - iounmap(oper_cfg.vpss_regs_base0); -fail1: - release_mem_region(r1->start, resource_size(r1)); - return status; -} - -static int __devexit vpss_remove(struct platform_device *pdev) -{ - struct resource *res; - - iounmap(oper_cfg.vpss_regs_base0); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - release_mem_region(res->start, resource_size(res)); - if (oper_cfg.platform == DM355 || oper_cfg.platform == DM365) { - iounmap(oper_cfg.vpss_regs_base1); - res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - release_mem_region(res->start, resource_size(res)); - } - return 0; -} - -static struct platform_driver vpss_driver = { - .driver = { - .name = "vpss", - .owner = THIS_MODULE, - }, - .remove = __devexit_p(vpss_remove), - .probe = vpss_probe, -}; - -static void vpss_exit(void) -{ - platform_driver_unregister(&vpss_driver); -} - -static int __init vpss_init(void) -{ - return platform_driver_register(&vpss_driver); -} -subsys_initcall(vpss_init); -module_exit(vpss_exit); |
