Re: [PATCH - v1 3/6] V4L-vpfe-capture-Adding ISIF driver for DM365 - source

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thursday 10 December 2009 18:00:26 m-karicheri2@xxxxxx wrote:
> From: Muralidharan Karicheri <m-karicheri2@xxxxxx>
> 
> This is the source file for ISIF driver for DM365. This has comments incorporated from
> initial version.
> 
> ISIF driver is equivalent to CCDC driver on DM355 and DM644x. This driver is tested for
> YUV capture from TVP514x driver. This patch contains the header files required for
> this driver. The name of the file is changed to reflect the name of IP.
> 
> Reviewed-by: Nori, Sekhar <nsekhar@xxxxxx>
> Signed-off-by: Muralidharan Karicheri <m-karicheri2@xxxxxx>
> ---
> Applies to linux-next tree of v4l-dvb 
>  drivers/media/video/davinci/isif.c | 1498 ++++++++++++++++++++++++++++++++++++
>  1 files changed, 1498 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/media/video/davinci/isif.c
> 
> diff --git a/drivers/media/video/davinci/isif.c b/drivers/media/video/davinci/isif.c
> new file mode 100644
> index 0000000..916afab
> --- /dev/null
> +++ b/drivers/media/video/davinci/isif.c
> @@ -0,0 +1,1498 @@
> +/*
> + * 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
> + *
> + * This is the isif hardware module.
> + * 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 <mach/mux.h>
> +
> +#include <media/davinci/isif.h>
> +#include <media/davinci/vpss.h>
> +
> +#include "isif_regs.h"
> +#include "ccdc_hw_device.h"
> +
> +/* Defauts for module configuation paramaters */

Typos: 'Defaults', 'configuration' and 'parameters'.

BTW: Please comment somewhere what 'ISIF' stands for!

> +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 u32 isif_raw_bayer_pix_formats[] =
> +		{V4L2_PIX_FMT_SBGGR8, V4L2_PIX_FMT_SBGGR16};
> +
> +/* Raw YUV formats */
> +static u32 isif_raw_yuv_pix_formats[] =
> +		{V4L2_PIX_FMT_UYVY, V4L2_PIX_FMT_YUYV};

Can these two arrays be const? Just wondering.

> +
> +/* 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_MASK) <<
> +		GAIN_INTEGER_SHIFT) |
> +		(gain_off_p->gain.r_ye.decimal & GAIN_DECIMAL_MASK);
> +	regw(val, CRGAIN);
> +
> +	val = ((gain_off_p->gain.gr_cy.integer & GAIN_INTEGER_MASK) <<
> +		GAIN_INTEGER_SHIFT) |
> +		(gain_off_p->gain.gr_cy.decimal & GAIN_DECIMAL_MASK);
> +	regw(val, CGRGAIN);
> +
> +	val = ((gain_off_p->gain.gb_g.integer & GAIN_INTEGER_MASK) <<
> +		GAIN_INTEGER_SHIFT) |
> +		(gain_off_p->gain.gb_g.decimal & GAIN_DECIMAL_MASK);
> +	regw(val, CGBGAIN);
> +
> +	val = ((gain_off_p->gain.b_mg.integer & GAIN_INTEGER_MASK) <<
> +		GAIN_INTEGER_SHIFT) |
> +		(gain_off_p->gain.b_mg.decimal & GAIN_DECIMAL_MASK);
> +	regw(val, CBGAIN);
> +
> +	regw((gain_off_p->offset & OFFSET_MASK), COFSTA);
> +}
> +
> +static void isif_restore_defaults(void)
> +{
> +	enum vpss_ccdc_source_sel source = VPSS_CCDCIN;
> +
> +	dev_dbg(isif_cfg.dev, "\nstarting isif_restore_defaults...");
> +	memcpy(&isif_cfg.bayer.config_params, &isif_config_defaults,
> +		sizeof(struct isif_config_params_raw));
> +	/* 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
> +	 */
> +	val = bc->dc_offset & ISIF_BC_DCOFFSET_MASK;
> +	regw(val, CLDCOFST);
> +
> +	if (bc->en) {
> +		val = (bc->bc_mode_color & ISIF_BC_MODE_COLOR_MASK) <<
> +			ISIF_BC_MODE_COLOR_SHIFT;
> +
> +		/* Enable BC and horizontal clamp caculation paramaters */
> +		val = val | 1 | ((bc->horz.mode & ISIF_HORZ_BC_MODE_MASK) <<
> +			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 &
> +				ISIF_HORZ_BC_WIN_COUNT_MASK) |
> +				((!!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_MASK) <<
> +				ISIF_HORZ_BC_WIN_H_SIZE_SHIFT) |
> +				((bc->horz.win_v_sz_calc &
> +				ISIF_HORZ_BC_WIN_V_SIZE_MASK) <<
> +				ISIF_HORZ_BC_WIN_V_SIZE_SHIFT);
> +
> +			regw(val, CLHWIN0);
> +
> +			regw(bc->horz.win_start_h_calc &
> +			     ISIF_HORZ_BC_WIN_START_H_MASK, CLHWIN1);
> +
> +			regw(bc->horz.win_start_v_calc &
> +			     ISIF_HORZ_BC_WIN_START_V_MASK, CLHWIN2);
> +		}
> +
> +		/* vertical clamp caculation paramaters */
> +
> +		/* OB H Valid */
> +		val = (bc->vert.ob_h_sz_calc & ISIF_VERT_BC_OB_H_SZ_MASK);
> +
> +		/* Reset clamp value sel for previous line */
> +		val |= ((bc->vert.reset_val_sel &
> +			ISIF_VERT_BC_RST_VAL_SEL_MASK) <<
> +			ISIF_VERT_BC_RST_VAL_SEL_SHIFT) |
> +			(bc->vert.line_ave_coef <<
> +			ISIF_VERT_BC_LINE_AVE_COEF_SHIFT);
> +		regw(val, CLVWIN0);
> +
> +		/* Configured reset value */
> +		if (bc->vert.reset_val_sel ==
> +		    ISIF_VERT_BC_USE_CONFIG_CLAMP_VAL) {
> +			regw(bc->vert.reset_clamp_val &
> +			       ISIF_VERT_BC_RST_VAL_MASK, CLVRV);
> +		}
> +
> +		/* Optical Black horizontal start position */
> +		regw(bc->vert.ob_start_h & ISIF_VERT_BC_OB_START_HORZ_MASK,
> +		     CLVWIN1);
> +
> +		/* Optical Black vertical start position */
> +		regw(bc->vert.ob_start_v & ISIF_VERT_BC_OB_START_VERT_MASK,
> +		     CLVWIN2);
> +
> +		regw(bc->vert.ob_v_sz_calc & ISIF_VERT_BC_OB_VERT_SZ_MASK,
> +		     CLVWIN3);
> +
> +		/* Vertical start position for BC subtraction */
> +		regw(bc->vert_start_sub & ISIF_BC_VERT_START_SUB_V_MASK, 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_MASK) <<
> +	       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 &
> +	       ISIF_LIN_SCALE_FACT_DECIMAL_MASK);
> +	regw(val, LINCFG1);
> +
> +	for (i = 0; i < ISIF_LINEAR_TAB_SIZE; i++) {
> +		val = linearize->table[i] & ISIF_LIN_ENTRY_MASK;
> +		if (i % 2)
> +			regw_lin_tbl(val, ((i >> 1) << 2), 1);
> +		else
> +			regw_lin_tbl(val, ((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_MASK) <<
> +		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_MASK) <<
> +		ISIF_VDFC_LEVEL_SHFT_SHIFT;
> +
> +	regw(val, DFCCTL);
> +
> +	/* Defect saturation level */
> +	val = vdfc->def_sat_level & ISIF_VDFC_SAT_LEVEL_MASK;
> +	regw(val, VDFSATLV);
> +
> +	regw(vdfc->table[0].pos_vert & ISIF_VDFC_POS_MASK, DFCMEM0);
> +	regw(vdfc->table[0].pos_horz & ISIF_VDFC_POS_MASK, 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 & ISIF_VDFC_POS_MASK,
> +			   DFCMEM0);
> +		regw(vdfc->table[i].pos_horz & ISIF_VDFC_POS_MASK,
> +			   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_MASK) <<
> +				ISIF_CSC_COEF_INTEG_SHIFT) |
> +				((df_csc->csc.coeff[i].decimal &
> +				ISIF_CSC_COEF_DECIMAL_MASK));
> +		} else {
> +
> +			/* CSCM - MSB */
> +			val2 = ((df_csc->csc.coeff[i].integer &
> +				ISIF_CSC_COEF_INTEG_MASK) <<
> +				ISIF_CSC_COEF_INTEG_SHIFT) |
> +				((df_csc->csc.coeff[i].decimal &
> +				ISIF_CSC_COEF_DECIMAL_MASK));
> +			val2 <<= ISIF_CSCM_MSB_SHIFT;
> +			val2 |= val1;
> +			regw(val2, (CSCM0 + ((i - 1) << 1)));
> +		}
> +	}
> +
> +	/* program the active area */
> +	regw(df_csc->start_pix & ISIF_DF_CSC_SPH_MASK, 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) & ISIF_DF_CSC_SPH_MASK, FMTLNH);
> +	regw(df_csc->start_line & ISIF_DF_CSC_SPH_MASK, FMTSLV);
> +	/*
> +	 * one extra line as required for CSC. See reason documented for
> +	 * num_pixels
> +	 */
> +	regw((df_csc->num_lines) & ISIF_DF_CSC_SPH_MASK, 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 &
> +		ISIF_DATA_PACK_MASK);
> +
> +	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_MASK) << ISIF_VD_POL_SHIFT) |
> +		((params->hd_pol & ISIF_HD_POL_MASK) << ISIF_HD_POL_SHIFT) |
> +		((params->fid_pol & ISIF_FID_POL_MASK) << ISIF_FID_POL_SHIFT) |
> +		((ISIF_DATAPOL_NORMAL & ISIF_DATAPOL_MASK) <<
> +		ISIF_DATAPOL_SHIFT) |
> +		((ISIF_EXWEN_DISABLE & ISIF_EXWEN_MASK) << ISIF_EXWEN_SHIFT) |
> +		((params->frm_fmt & ISIF_FRM_FMT_MASK) << ISIF_FRM_FMT_SHIFT) |
> +		((params->pix_fmt & ISIF_INPUT_MASK) << ISIF_INPUT_SHIFT) |
> +		((params->config_params.data_shift & ISIF_DATASFT_MASK) <<
> +		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_MASK) <<
> +		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_MASK) <<
> +			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_MASK) << 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_MASK) <<
> +		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) & ISIF_LINEOFST_MASK);
> +	else if (isif_cfg.data_pack == ISIF_PACK_12BIT)
> +		val |= ((((params->win.width +
> +			(params->win.width >> 2)) + 31) >> 5) &
> +			ISIF_LINEOFST_MASK);
> +	else
> +		val |= ((((params->win.width * 2) + 31) >> 5) &
> +			ISIF_LINEOFST_MASK);
> +	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 progessive inverse mode */

Typo: progressive

> +			regw(0x4000, SDOFST);
> +			dev_dbg(isif_cfg.dev, "Writing 0x4000 to SDOFST...\n");
> +		} else {
> +			/* For progessive non inverse mode */
> +			regw(0x0000, SDOFST);
> +			dev_dbg(isif_cfg.dev, "Writing 0x0000 to SDOFST...\n");
> +		}
> +	}
> +
> +	/* Configure video window */
> +	isif_setwin(&params->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) */
> +	val = module_params->horz_offset & ISIF_DATA_H_OFFSET_MASK;
> +	regw(val, DATAHOFST);
> +
> +	val = module_params->vert_offset & ISIF_DATA_V_OFFSET_MASK;
> +	regw(val, 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 & ISIF_HD_POL_MASK;
> +		sync.ccdpg_vdpol = params->vd_pol & ISIF_VD_POL_MASK;
> +
> +		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_validate_df_csc_params(struct isif_df_csc *df_csc)
> +{
> +	struct isif_color_space_conv *csc;
> +	int i, csc_df_en = 0;
> +	int err = -EINVAL;
> +
> +	if (!df_csc->df_or_csc) {
> +		/* csc configuration */
> +		csc = &df_csc->csc;
> +		if (csc->en) {

You can save one level of indent by doing:

if (!df_csc->df_or_csc && df_csc->csc.en)

> +			csc_df_en = 1;
> +			for (i = 0; i < ISIF_CSC_NUM_COEFF; i++) {
> +				if (csc->coeff[i].integer >
> +					ISIF_CSC_COEF_INTEG_MASK ||
> +				    csc->coeff[i].decimal >
> +					ISIF_CSC_COEF_DECIMAL_MASK) {
> +					dev_dbg(isif_cfg.dev,
> +					       "invalid csc coefficients \n");
> +					return err;
> +				}
> +			}
> +		}
> +	}
> +
> +	if (df_csc->start_pix > ISIF_DF_CSC_SPH_MASK) {
> +		dev_dbg(isif_cfg.dev, "invalid df_csc start pix value \n");
> +		return err;
> +	}
> +	if (df_csc->num_pixels > ISIF_DF_NUMPIX) {
> +		dev_dbg(isif_cfg.dev, "invalid df_csc num pixels value \n");
> +		return err;
> +	}
> +	if (df_csc->start_line > ISIF_DF_CSC_LNH_MASK) {
> +		dev_dbg(isif_cfg.dev, "invalid df_csc start_line value \n");
> +		return err;
> +	}
> +	if (df_csc->num_lines > ISIF_DF_NUMLINES) {
> +		dev_dbg(isif_cfg.dev, "invalid df_csc num_lines value \n");
> +		return err;
> +	}
> +	return 0;
> +}
> +
> +static int isif_validate_dfc_params(struct isif_dfc *dfc)
> +{
> +	int err = -EINVAL;
> +	int i;
> +
> +	if (dfc->en) {

Please invert:

	if (!dfc->en)
		return 0;

The remainder of this function can now be shifted one tab to the left.

> +		if (dfc->corr_whole_line > 1) {
> +			dev_dbg(isif_cfg.dev,
> +				"invalid corr_whole_line value\n");
> +			return err;
> +		}
> +
> +		if (dfc->def_level_shift > 4) {
> +			dev_dbg(isif_cfg.dev,
> +				"invalid def_level_shift value\n");
> +			return err;
> +		}
> +
> +		if (dfc->def_sat_level > 4095) {
> +			dev_dbg(isif_cfg.dev, "invalid def_sat_level value \n");
> +			return err;
> +		}
> +		if ((!dfc->num_vdefects) || (dfc->num_vdefects > 8)) {
> +			dev_dbg(isif_cfg.dev, "invalid num_vdefects value \n");
> +			return err;
> +		}
> +		for (i = 0; i < ISIF_VDFC_TABLE_SIZE; i++) {
> +			if (dfc->table[i].pos_vert > 0x1fff) {
> +				dev_dbg(isif_cfg.dev,
> +					"invalid pos_vert value \n");
> +				return err;
> +			}
> +			if (dfc->table[i].pos_horz > 0x1fff) {
> +				dev_dbg(isif_cfg.dev,
> +					"invalid pos_horz value \n");
> +				return err;
> +			}
> +		}
> +	}
> +	return 0;
> +}
> +
> +static int isif_validate_bclamp_params(struct isif_black_clamp *bclamp)
> +{
> +	int err = -EINVAL;
> +
> +	if (bclamp->dc_offset > 0x1fff) {
> +		dev_dbg(isif_cfg.dev, "invalid bclamp dc_offset value \n");
> +		return err;
> +	}
> +
> +	if (bclamp->en) {

Ditto.

> +		if (bclamp->horz.clamp_pix_limit > 1) {
> +			dev_dbg(isif_cfg.dev,
> +			       "invalid bclamp horz clamp_pix_limit value \n");
> +			return err;
> +		}
> +
> +		if (bclamp->horz.win_count_calc < 1 ||
> +		    bclamp->horz.win_count_calc > 32) {
> +			dev_dbg(isif_cfg.dev,
> +			       "invalid bclamp horz win_count_calc value \n");
> +			return err;
> +		}
> +
> +		if (bclamp->horz.win_start_h_calc > 0x1fff) {
> +			dev_dbg(isif_cfg.dev,
> +			       "invalid bclamp win_start_v_calc value \n");
> +			return err;
> +		}
> +
> +		if (bclamp->horz.win_start_v_calc > 0x1fff) {
> +			dev_dbg(isif_cfg.dev,
> +			       "invalid bclamp win_start_v_calc value \n");
> +			return err;
> +		}
> +
> +		if (bclamp->vert.reset_clamp_val > 0xfff) {
> +			dev_dbg(isif_cfg.dev,
> +			       "invalid bclamp reset_clamp_val value \n");
> +			return err;
> +		}
> +
> +		if (bclamp->vert.ob_v_sz_calc > 0x1fff) {
> +			dev_dbg(isif_cfg.dev,
> +				"invalid bclamp ob_v_sz_calc value \n");
> +			return err;
> +		}
> +
> +		if (bclamp->vert.ob_start_h > 0x1fff) {
> +			dev_dbg(isif_cfg.dev,
> +				"invalid bclamp ob_start_h value \n");
> +			return err;
> +		}
> +
> +		if (bclamp->vert.ob_start_v > 0x1fff) {
> +			dev_dbg(isif_cfg.dev,
> +				"invalid bclamp ob_start_h value \n");
> +			return err;
> +		}
> +	}
> +	return 0;
> +}
> +
> +static int isif_validate_gain_ofst_params(struct isif_gain_offsets_adj
> +					  *gain_offset)
> +{
> +	int err = -EINVAL;
> +
> +	if (gain_offset->gain_sdram_en ||
> +	    gain_offset->gain_ipipe_en ||
> +	    gain_offset->gain_h3a_en) {
> +		if ((gain_offset->gain.r_ye.integer > 7) ||
> +		    (gain_offset->gain.r_ye.decimal > 0x1ff)) {
> +			dev_dbg(isif_cfg.dev, "invalid  gain r_ye\n");
> +			return err;
> +		}
> +		if ((gain_offset->gain.gr_cy.integer > 7) ||
> +		    (gain_offset->gain.gr_cy.decimal > 0x1ff)) {
> +			dev_dbg(isif_cfg.dev, "invalid  gain gr_cy\n");
> +			return err;
> +		}
> +		if ((gain_offset->gain.gb_g.integer > 7) ||
> +		    (gain_offset->gain.gb_g.decimal > 0x1ff)) {
> +			dev_dbg(isif_cfg.dev, "invalid  gain gb_g\n");
> +			return err;
> +		}
> +		if ((gain_offset->gain.b_mg.integer > 7) ||
> +		    (gain_offset->gain.b_mg.decimal > 0x1ff)) {
> +			dev_dbg(isif_cfg.dev, "invalid  gain b_mg\n");
> +			return err;
> +		}
> +	}
> +	if (gain_offset->offset_sdram_en ||
> +	    gain_offset->offset_ipipe_en ||
> +	    gain_offset->offset_h3a_en) {
> +		if (gain_offset->offset > 0xfff) {
> +			dev_dbg(isif_cfg.dev, "invalid  gain b_mg\n");
> +			return err;
> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +static int
> +validate_isif_config_params_raw(struct isif_config_params_raw *params)
> +{
> +	int err;
> +
> +	err = isif_validate_df_csc_params(&params->df_csc);
> +	if (err)
> +		goto exit;

Why goto? Just return here. Ditto for the next two gotos.

> +	err = isif_validate_dfc_params(&params->dfc);
> +	if (err)
> +		goto exit;
> +	err = isif_validate_bclamp_params(&params->bclamp);
> +	if (err)
> +		goto exit;
> +	err = isif_validate_gain_ofst_params(&params->gain_offset);
> +exit:
> +	return err;
> +}
> +
> +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;
> +	else

'else' is not needed here.

> +		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;
> +}
> +
> +/* Parameter operations */
> +static int isif_get_params(void __user *params)
> +{
> +	/* only raw module parameters can be set through the IOCTL */
> +	if (isif_cfg.if_type != VPFE_RAW_BAYER)
> +		return -EINVAL;
> +
> +	if (copy_to_user(params,
> +			&isif_cfg.bayer.config_params,
> +			sizeof(isif_cfg.bayer.config_params))) {
> +		dev_dbg(isif_cfg.dev,
> +			"isif_get_params: error in copying isif params\n");
> +		return -EFAULT;
> +	}
> +	return 0;
> +}
> +
> +/* Parameter operations */
> +static int isif_set_params(void __user *params)
> +{
> +	struct isif_config_params_raw *isif_raw_params;
> +	int ret = -EINVAL;
> +
> +	/* only raw module parameters can be set through the IOCTL */
> +	if (isif_cfg.if_type != VPFE_RAW_BAYER)
> +		return ret;
> +
> +	isif_raw_params = kzalloc(sizeof(*isif_raw_params), GFP_KERNEL);
> +
> +	if (NULL == isif_raw_params)
> +		return -ENOMEM;
> +
> +	ret = copy_from_user(isif_raw_params,
> +			     params, sizeof(*isif_raw_params));
> +	if (ret) {
> +		dev_dbg(isif_cfg.dev, "isif_set_params: error in copying isif"
> +			"params, %d\n", ret);
> +		ret = -EFAULT;
> +		goto free_out;
> +	}
> +
> +	if (!validate_isif_config_params_raw(isif_raw_params)) {
> +		memcpy(&isif_cfg.bayer.config_params,
> +			isif_raw_params,
> +			sizeof(*isif_raw_params));
> +		ret = 0;
> +	} else
> +		ret = -EINVAL;
> +free_out:
> +	kfree(isif_raw_params);
> +	return ret;
> +}
> +
> +/* 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_MASK)
> +		<< ISIF_INPUT_SHIFT) |
> +	((params->frm_fmt & ISIF_FRM_FMT_MASK) << ISIF_FRM_FMT_SHIFT) |
> +	(((params->fid_pol & ISIF_FID_POL_MASK) << ISIF_FID_POL_SHIFT))	|
> +	(((params->hd_pol & ISIF_HD_POL_MASK) << ISIF_HD_POL_SHIFT)) |
> +	(((params->vd_pol & ISIF_VD_POL_MASK) << 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 -1;
> +		}
> +		modeset |=
> +			((VPFE_PINPOL_NEGATIVE & ISIF_VD_POL_MASK)
> +			<< 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 -1;
> +		}
> +		/* 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_MASK) <<
> +		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(&params->win, params->frm_fmt, 1);
> +	else
> +		isif_setwin(&params->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 & ISIF_HD_POL_MASK);
> +		sync.ccdpg_vdpol = (params->vd_pol & ISIF_VD_POL_MASK);
> +		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();
> +	else

'else' not needed here.

> +		isif_config_ycbcr();
> +	return 0;
> +}
> +
> +static int isif_close(struct device *device)
> +{
> +	/* copy defaults to module params */
> +	memcpy(&isif_cfg.bayer.config_params,
> +	       &isif_config_defaults,
> +	       sizeof(struct isif_config_params_raw));

Can you also do: 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,
> +		.set_params = isif_set_params,
> +		.get_params = isif_get_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 (NULL == isif_cfg.mclk) {
> +		status = -ENODEV;
> +		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");
> 

-- 
Hans Verkuil - video4linux developer - sponsored by TANDBERG
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux