| 
									
										
										
										
											2010-02-21 15:48:27 -03:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * 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/err.h>
 | 
					
						
							| 
									
										
										
										
											2012-02-08 12:44:30 -03:00
										 |  |  | #include <linux/module.h>
 | 
					
						
							| 
									
										
										
										
											2010-02-21 15:48:27 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | #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; | 
					
						
							|  |  |  | 	/* 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; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-04 07:24:07 -03:00
										 |  |  | 	val |= (params->data_msb << ISIF_ALAW_GAMMA_WD_SHIFT); | 
					
						
							| 
									
										
										
										
											2010-02-21 15:48:27 -03:00
										 |  |  | 	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, | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-12-21 13:17:53 -08:00
										 |  |  | static int isif_probe(struct platform_device *pdev) | 
					
						
							| 
									
										
										
										
											2010-02-21 15:48:27 -03:00
										 |  |  | { | 
					
						
							|  |  |  | 	void (*setup_pinmux)(void); | 
					
						
							|  |  |  | 	struct resource	*res; | 
					
						
							|  |  |  | 	void *__iomem addr; | 
					
						
							|  |  |  | 	int status = 0, i; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-22 04:53:12 -03:00
										 |  |  | 	/* Platform data holds setup_pinmux function ptr */ | 
					
						
							|  |  |  | 	if (!pdev->dev.platform_data) | 
					
						
							|  |  |  | 		return -ENODEV; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-21 15:48:27 -03:00
										 |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * 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; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	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--; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	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; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-14 01:23:09 -03:00
										 |  |  | static struct platform_driver isif_driver = { | 
					
						
							| 
									
										
										
										
											2010-02-21 15:48:27 -03:00
										 |  |  | 	.driver = { | 
					
						
							|  |  |  | 		.name	= "isif", | 
					
						
							|  |  |  | 		.owner = THIS_MODULE, | 
					
						
							|  |  |  | 	}, | 
					
						
							| 
									
										
										
										
											2012-12-21 13:17:53 -08:00
										 |  |  | 	.remove = isif_remove, | 
					
						
							| 
									
										
										
										
											2010-02-21 15:48:27 -03:00
										 |  |  | 	.probe = isif_probe, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-10 03:21:49 -03:00
										 |  |  | module_platform_driver(isif_driver); | 
					
						
							| 
									
										
										
										
											2010-02-21 15:48:27 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | MODULE_LICENSE("GPL"); |