cregit-Linux how code gets into the kernel

Release 4.11 drivers/media/platform/davinci/dm355_ccdc.c

/*
 * Copyright (C) 2005-2009 Texas Instruments Inc
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * CCDC hardware module for DM355
 * ------------------------------
 *
 * This module is for configuring DM355 CCD controller of VPFE to capture
 * Raw yuv or Bayer RGB data from a decoder. CCDC has several modules
 * such as Defect Pixel Correction, Color Space Conversion etc to
 * pre-process the Bayer RGB data, before writing it to SDRAM. This
 * module also allows application to configure individual
 * module parameters through VPFE_CMD_S_CCDC_RAW_PARAMS IOCTL.
 * To do so, application include dm355_ccdc.h and vpfe_capture.h header
 * files. The setparams() API is called by vpfe_capture driver
 * to configure module parameters
 *
 * TODO: 1) Raw bayer parameter settings and bayer capture
 *       2) Split module parameter structure to module specific ioctl structs
 *       3) add support for lense shading correction
 *       4) investigate if enum used for user space type definition
 *          to be replaced by #defines or integer
 */
#include <linux/platform_device.h>
#include <linux/uaccess.h>
#include <linux/videodev2.h>
#include <linux/err.h>
#include <linux/module.h>

#include <media/davinci/dm355_ccdc.h>
#include <media/davinci/vpss.h>

#include "dm355_ccdc_regs.h"
#include "ccdc_hw_device.h"

MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("CCDC Driver for DM355");
MODULE_AUTHOR("Texas Instruments");


static struct ccdc_oper_config {
	
struct device *dev;
	/* CCDC interface type */
	
enum vpfe_hw_if_type if_type;
	/* Raw Bayer configuration */
	
struct ccdc_params_raw bayer;
	/* YCbCr configuration */
	
struct ccdc_params_ycbcr ycbcr;
	/* ccdc base address */
	
void __iomem *base_addr;
} 
ccdc_cfg = {
	/* Raw configurations */
	.bayer = {
		.pix_fmt = CCDC_PIXFMT_RAW,
		.frm_fmt = CCDC_FRMFMT_PROGRESSIVE,
		.win = CCDC_WIN_VGA,
		.fid_pol = VPFE_PINPOL_POSITIVE,
		.vd_pol = VPFE_PINPOL_POSITIVE,
		.hd_pol = VPFE_PINPOL_POSITIVE,
		.gain = {
			.r_ye = 256,
			.gb_g = 256,
			.gr_cy = 256,
			.b_mg = 256
		},
		.config_params = {
			.datasft = 2,
			.mfilt1 = CCDC_NO_MEDIAN_FILTER1,
			.mfilt2 = CCDC_NO_MEDIAN_FILTER2,
			.alaw = {
				.gamma_wd = 2,
                        },
			.blk_clamp = {
				.sample_pixel = 1,
				.dc_sub = 25
			},
			.col_pat_field0 = {
				.olop = CCDC_GREEN_BLUE,
				.olep = CCDC_BLUE,
				.elop = CCDC_RED,
				.elep = CCDC_GREEN_RED
			},
			.col_pat_field1 = {
				.olop = CCDC_GREEN_BLUE,
				.olep = CCDC_BLUE,
				.elop = CCDC_RED,
				.elep = CCDC_GREEN_RED
			},
                },
        },
	/* YCbCr configuration */
	.ycbcr = {
		.win = CCDC_WIN_PAL,
		.pix_fmt = CCDC_PIXFMT_YCBCR_8BIT,
		.frm_fmt = CCDC_FRMFMT_INTERLACED,
		.fid_pol = VPFE_PINPOL_POSITIVE,
		.vd_pol = VPFE_PINPOL_POSITIVE,
		.hd_pol = VPFE_PINPOL_POSITIVE,
		.bt656_enable = 1,
		.pix_order = CCDC_PIXORDER_CBYCRY,
		.buf_type = CCDC_BUFTYPE_FLD_INTERLEAVED
	},
};


/* Raw Bayer formats */

static u32 ccdc_raw_bayer_pix_formats[] =
		{V4L2_PIX_FMT_SBGGR8, V4L2_PIX_FMT_SBGGR16};

/* Raw YUV formats */

static u32 ccdc_raw_yuv_pix_formats[] =
		{V4L2_PIX_FMT_UYVY, V4L2_PIX_FMT_YUYV};

/* register access routines */

static inline u32 regr(u32 offset) { return __raw_readl(ccdc_cfg.base_addr + offset); }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri20100.00%2100.00%
Total20100.00%2100.00%


static inline void regw(u32 val, u32 offset) { __raw_writel(val, ccdc_cfg.base_addr + offset); }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri24100.00%2100.00%
Total24100.00%2100.00%


static void ccdc_enable(int en) { unsigned int temp; temp = regr(SYNCEN); temp &= (~CCDC_SYNCEN_VDHDEN_MASK); temp |= (en & CCDC_SYNCEN_VDHDEN_MASK); regw(temp, SYNCEN); }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri42100.00%1100.00%
Total42100.00%1100.00%


static void ccdc_enable_output_to_sdram(int en) { unsigned int temp; temp = regr(SYNCEN); temp &= (~(CCDC_SYNCEN_WEN_MASK)); temp |= ((en << CCDC_SYNCEN_WEN_SHIFT) & CCDC_SYNCEN_WEN_MASK); regw(temp, SYNCEN); }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri48100.00%1100.00%
Total48100.00%1100.00%


static void ccdc_config_gain_offset(void) { /* configure gain */ regw(ccdc_cfg.bayer.gain.r_ye, RYEGAIN); regw(ccdc_cfg.bayer.gain.gr_cy, GRCYGAIN); regw(ccdc_cfg.bayer.gain.gb_g, GBGGAIN); regw(ccdc_cfg.bayer.gain.b_mg, BMGGAIN); /* configure offset */ regw(ccdc_cfg.bayer.ccdc_offset, OFFSET); }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri73100.00%2100.00%
Total73100.00%2100.00%

/* * ccdc_restore_defaults() * This function restore power on defaults in the ccdc registers */
static int ccdc_restore_defaults(void) { int i; dev_dbg(ccdc_cfg.dev, "\nstarting ccdc_restore_defaults..."); /* set all registers to zero */ for (i = 0; i <= CCDC_REG_LAST; i += 4) regw(0, i); /* now override the values with power on defaults in registers */ regw(MODESET_DEFAULT, MODESET); /* no culling support */ regw(CULH_DEFAULT, CULH); regw(CULV_DEFAULT, CULV); /* Set default Gain and Offset */ ccdc_cfg.bayer.gain.r_ye = GAIN_DEFAULT; ccdc_cfg.bayer.gain.gb_g = GAIN_DEFAULT; ccdc_cfg.bayer.gain.gr_cy = GAIN_DEFAULT; ccdc_cfg.bayer.gain.b_mg = GAIN_DEFAULT; ccdc_config_gain_offset(); regw(OUTCLIP_DEFAULT, OUTCLIP); regw(LSCCFG2_DEFAULT, LSCCFG2); /* select ccdc input */ if (vpss_select_ccdc_source(VPSS_CCDCIN)) { dev_dbg(ccdc_cfg.dev, "\ncouldn't select ccdc input source"); return -EFAULT; } /* select ccdc clock */ if (vpss_enable_clock(VPSS_CCDC_CLOCK, 1) < 0) { dev_dbg(ccdc_cfg.dev, "\ncouldn't enable ccdc clock"); return -EFAULT; } dev_dbg(ccdc_cfg.dev, "\nEnd of ccdc_restore_defaults..."); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri185100.00%2100.00%
Total185100.00%2100.00%


static int ccdc_open(struct device *device) { return ccdc_restore_defaults(); }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri15100.00%1100.00%
Total15100.00%1100.00%


static int ccdc_close(struct device *device) { /* disable clock */ vpss_enable_clock(VPSS_CCDC_CLOCK, 0); /* do nothing for now */ return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri23100.00%1100.00%
Total23100.00%1100.00%

/* * ccdc_setwin() * This function will configure the window size to * be capture in CCDC reg. */
static void ccdc_setwin(struct v4l2_rect *image_win, enum ccdc_frmfmt frm_fmt, int ppc) { int horz_start, horz_nr_pixels; int vert_start, vert_nr_lines; int mid_img = 0; dev_dbg(ccdc_cfg.dev, "\nStarting ccdc_setwin..."); /* * ppc - per pixel count. indicates how many pixels per cell * output to SDRAM. example, for ycbcr, it is one y and one c, so 2. * raw capture this is 1 */ horz_start = image_win->left << (ppc - 1); horz_nr_pixels = ((image_win->width) << (ppc - 1)) - 1; /* Writing the horizontal info into the registers */ regw(horz_start, SPH); regw(horz_nr_pixels, NPH); vert_start = image_win->top; if (frm_fmt == CCDC_FRMFMT_INTERLACED) { vert_nr_lines = (image_win->height >> 1) - 1; vert_start >>= 1; /* Since first line doesn't have any data */ vert_start += 1; /* configure VDINT0 and VDINT1 */ regw(vert_start, VDINT0); } else { /* Since first line doesn't have any data */ vert_start += 1; vert_nr_lines = image_win->height - 1; /* configure VDINT0 and VDINT1 */ mid_img = vert_start + (image_win->height / 2); regw(vert_start, VDINT0); regw(mid_img, VDINT1); } regw(vert_start & CCDC_START_VER_ONE_MASK, SLV0); regw(vert_start & CCDC_START_VER_TWO_MASK, SLV1); regw(vert_nr_lines & CCDC_NUM_LINES_VER, NLV); dev_dbg(ccdc_cfg.dev, "\nEnd of ccdc_setwin..."); }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri210100.00%2100.00%
Total210100.00%2100.00%


static int validate_ccdc_param(struct ccdc_config_params_raw *ccdcparam) { if (ccdcparam->datasft < CCDC_DATA_NO_SHIFT || ccdcparam->datasft > CCDC_DATA_SHIFT_6BIT) { dev_dbg(ccdc_cfg.dev, "Invalid value of data shift\n"); return -EINVAL; } if (ccdcparam->mfilt1 < CCDC_NO_MEDIAN_FILTER1 || ccdcparam->mfilt1 > CCDC_MEDIAN_FILTER1) { dev_dbg(ccdc_cfg.dev, "Invalid value of median filter1\n"); return -EINVAL; } if (ccdcparam->mfilt2 < CCDC_NO_MEDIAN_FILTER2 || ccdcparam->mfilt2 > CCDC_MEDIAN_FILTER2) { dev_dbg(ccdc_cfg.dev, "Invalid value of median filter2\n"); return -EINVAL; } if ((ccdcparam->med_filt_thres < 0) || (ccdcparam->med_filt_thres > CCDC_MED_FILT_THRESH)) { dev_dbg(ccdc_cfg.dev, "Invalid value of median filter threshold\n"); return -EINVAL; } if (ccdcparam->data_sz < CCDC_DATA_16BITS || ccdcparam->data_sz > CCDC_DATA_8BITS) { dev_dbg(ccdc_cfg.dev, "Invalid value of data size\n"); return -EINVAL; } if (ccdcparam->alaw.enable) { if (ccdcparam->alaw.gamma_wd < CCDC_GAMMA_BITS_13_4 || ccdcparam->alaw.gamma_wd > CCDC_GAMMA_BITS_09_0) { dev_dbg(ccdc_cfg.dev, "Invalid value of ALAW\n"); return -EINVAL; } } if (ccdcparam->blk_clamp.b_clamp_enable) { if (ccdcparam->blk_clamp.sample_pixel < CCDC_SAMPLE_1PIXELS || ccdcparam->blk_clamp.sample_pixel > CCDC_SAMPLE_16PIXELS) { dev_dbg(ccdc_cfg.dev, "Invalid value of sample pixel\n"); return -EINVAL; } if (ccdcparam->blk_clamp.sample_ln < CCDC_SAMPLE_1LINES || ccdcparam->blk_clamp.sample_ln > CCDC_SAMPLE_16LINES) { dev_dbg(ccdc_cfg.dev, "Invalid value of sample lines\n"); return -EINVAL; } } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri27998.94%250.00%
Hans Verkuil20.71%125.00%
Masanari Iida10.35%125.00%
Total282100.00%4100.00%

/* Parameter operations */
static int ccdc_set_params(void __user *params) { struct ccdc_config_params_raw ccdc_raw_params; int x; /* only raw module parameters can be set through the IOCTL */ if (ccdc_cfg.if_type != VPFE_RAW_BAYER) return -EINVAL; x = copy_from_user(&ccdc_raw_params, params, sizeof(ccdc_raw_params)); if (x) { dev_dbg(ccdc_cfg.dev, "ccdc_set_params: error in copying ccdcparams, %d\n", x); return -EFAULT; } if (!validate_ccdc_param(&ccdc_raw_params)) { memcpy(&ccdc_cfg.bayer.config_params, &ccdc_raw_params, sizeof(ccdc_raw_params)); return 0; } return -EINVAL; }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri10299.03%266.67%
Mauro Carvalho Chehab10.97%133.33%
Total103100.00%3100.00%

/* This function will configure CCDC for YCbCr video capture */
static void ccdc_config_ycbcr(void) { struct ccdc_params_ycbcr *params = &ccdc_cfg.ycbcr; u32 temp; /* first set the CCDC power on defaults values in all registers */ dev_dbg(ccdc_cfg.dev, "\nStarting ccdc_config_ycbcr..."); ccdc_restore_defaults(); /* configure pixel format & video frame format */ temp = (((params->pix_fmt & CCDC_INPUT_MODE_MASK) << CCDC_INPUT_MODE_SHIFT) | ((params->frm_fmt & CCDC_FRM_FMT_MASK) << CCDC_FRM_FMT_SHIFT)); /* setup BT.656 sync mode */ if (params->bt656_enable) { regw(CCDC_REC656IF_BT656_EN, REC656IF); /* * configure the FID, VD, HD pin polarity fld,hd pol positive, * vd negative, 8-bit pack mode */ temp |= CCDC_VD_POL_NEGATIVE; } else { /* y/c external sync mode */ temp |= (((params->fid_pol & CCDC_FID_POL_MASK) << CCDC_FID_POL_SHIFT) | ((params->hd_pol & CCDC_HD_POL_MASK) << CCDC_HD_POL_SHIFT) | ((params->vd_pol & CCDC_VD_POL_MASK) << CCDC_VD_POL_SHIFT)); } /* pack the data to 8-bit */ temp |= CCDC_DATA_PACK_ENABLE; regw(temp, MODESET); /* configure video window */ ccdc_setwin(&params->win, params->frm_fmt, 2); /* configure the order of y cb cr in SD-RAM */ temp = (params->pix_order << CCDC_Y8POS_SHIFT); temp |= CCDC_LATCH_ON_VSYNC_DISABLE | CCDC_CCDCFG_FIDMD_NO_LATCH_VSYNC; regw(temp, CCDCFG); /* * configure the horizontal line offset. This is done by rounding up * width to a multiple of 16 pixels and multiply by two to account for * y:cb:cr 4:2:2 data */ regw(((params->win.width * 2 + 31) >> 5), HSIZE); /* configure the memory line offset */ if (params->buf_type == CCDC_BUFTYPE_FLD_INTERLEAVED) { /* two fields are interleaved in memory */ regw(CCDC_SDOFST_FIELD_INTERLEAVED, SDOFST); } dev_dbg(ccdc_cfg.dev, "\nEnd of ccdc_config_ycbcr...\n"); }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri229100.00%2100.00%
Total229100.00%2100.00%

/* * ccdc_config_black_clamp() * configure parameters for Optical Black Clamp */
static void ccdc_config_black_clamp(struct ccdc_black_clamp *bclamp) { u32 val; if (!bclamp->b_clamp_enable) { /* configure DCSub */ regw(bclamp->dc_sub & CCDC_BLK_DC_SUB_MASK, DCSUB); regw(0x0000, CLAMP); return; } /* Enable the Black clamping, set sample lines and pixels */ val = (bclamp->start_pixel & CCDC_BLK_ST_PXL_MASK) | ((bclamp->sample_pixel & CCDC_BLK_SAMPLE_LN_MASK) << CCDC_BLK_SAMPLE_LN_SHIFT) | CCDC_BLK_CLAMP_ENABLE; regw(val, CLAMP); /* If Black clamping is enable then make dcsub 0 */ val = (bclamp->sample_ln & CCDC_NUM_LINE_CALC_MASK) << CCDC_NUM_LINE_CALC_SHIFT; regw(val, DCSUB); }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri95100.00%1100.00%
Total95100.00%1100.00%

/* * ccdc_config_black_compense() * configure parameters for Black Compensation */
static void ccdc_config_black_compense(struct ccdc_black_compensation *bcomp) { u32 val; val = (bcomp->b & CCDC_BLK_COMP_MASK) | ((bcomp->gb & CCDC_BLK_COMP_MASK) << CCDC_BLK_COMP_GB_COMP_SHIFT); regw(val, BLKCMP1); val = ((bcomp->gr & CCDC_BLK_COMP_MASK) << CCDC_BLK_COMP_GR_COMP_SHIFT) | ((bcomp->r & CCDC_BLK_COMP_MASK) << CCDC_BLK_COMP_R_COMP_SHIFT); regw(val, BLKCMP0); }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri76100.00%1100.00%
Total76100.00%1100.00%

/* * ccdc_write_dfc_entry() * write an entry in the dfc table. */
static int ccdc_write_dfc_entry(int index, struct ccdc_vertical_dft *dfc) { /* TODO This is to be re-visited and adjusted */ #define DFC_WRITE_WAIT_COUNT 1000 u32 val, count = DFC_WRITE_WAIT_COUNT; regw(dfc->dft_corr_vert[index], DFCMEM0); regw(dfc->dft_corr_horz[index], DFCMEM1); regw(dfc->dft_corr_sub1[index], DFCMEM2); regw(dfc->dft_corr_sub2[index], DFCMEM3); regw(dfc->dft_corr_sub3[index], DFCMEM4); /* set WR bit to write */ val = regr(DFCMEMCTL) | CCDC_DFCMEMCTL_DFCMWR_MASK; regw(val, DFCMEMCTL); /* * Assume, it is very short. If we get an error, we need to * adjust this value */ while (regr(DFCMEMCTL) & CCDC_DFCMEMCTL_DFCMWR_MASK) count--; /* * TODO We expect the count to be non-zero to be successful. Adjust * the count if write requires more time */ if (count) { dev_err(ccdc_cfg.dev, "defect table write timeout !!!\n"); return -1; } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri13899.28%266.67%
Mauro Carvalho Chehab10.72%133.33%
Total139100.00%3100.00%

/* * ccdc_config_vdfc() * configure parameters for Vertical Defect Correction */
static int ccdc_config_vdfc(struct ccdc_vertical_dft *dfc) { u32 val; int i; /* Configure General Defect Correction. The table used is from IPIPE */ val = dfc->gen_dft_en & CCDC_DFCCTL_GDFCEN_MASK; /* Configure Vertical Defect Correction if needed */ if (!dfc->ver_dft_en) { /* Enable only General Defect Correction */ regw(val, DFCCTL); return 0; } if (dfc->table_size > CCDC_DFT_TABLE_SIZE) return -EINVAL; val |= CCDC_DFCCTL_VDFC_DISABLE; val |= (dfc->dft_corr_ctl.vdfcsl & CCDC_DFCCTL_VDFCSL_MASK) << CCDC_DFCCTL_VDFCSL_SHIFT; val |= (dfc->dft_corr_ctl.vdfcuda & CCDC_DFCCTL_VDFCUDA_MASK) << CCDC_DFCCTL_VDFCUDA_SHIFT; val |= (dfc->dft_corr_ctl.vdflsft & CCDC_DFCCTL_VDFLSFT_MASK) << CCDC_DFCCTL_VDFLSFT_SHIFT; regw(val , DFCCTL); /* clear address ptr to offset 0 */ val = CCDC_DFCMEMCTL_DFCMARST_MASK << CCDC_DFCMEMCTL_DFCMARST_SHIFT; /* write defect table entries */ for (i = 0; i < dfc->table_size; i++) { /* increment address for non zero index */ if (i != 0) val = CCDC_DFCMEMCTL_INC_ADDR; regw(val, DFCMEMCTL); if (ccdc_write_dfc_entry(i, dfc) < 0) return -EFAULT; } /* update saturation level and enable dfc */ regw(dfc->saturation_ctl & CCDC_VDC_DFCVSAT_MASK, DFCVSAT); val = regr(DFCCTL) | (CCDC_DFCCTL_VDFCEN_MASK << CCDC_DFCCTL_VDFCEN_SHIFT); regw(val, DFCCTL); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri205100.00%1100.00%
Total205100.00%1100.00%

/* * ccdc_config_csc() * configure parameters for color space conversion * Each register CSCM0-7 has two values in S8Q5 format. */
static void ccdc_config_csc(struct ccdc_csc *csc) { u32 val1 = 0, val2; int i; if (!csc->enable) return; /* Enable the CSC sub-module */ regw(CCDC_CSC_ENABLE, CSCCTL); /* Converting the co-eff as per the format of the register */ for (i = 0; i < CCDC_CSC_COEFF_TABLE_SIZE; i++) { if ((i % 2) == 0) { /* CSCM - LSB */ val1 = (csc->coeff[i].integer & CCDC_CSC_COEF_INTEG_MASK) << CCDC_CSC_COEF_INTEG_SHIFT; /* * convert decimal part to binary. Use 2 decimal * precision, user values range from .00 - 0.99 */ val1 |= (((csc->coeff[i].decimal & CCDC_CSC_COEF_DECIMAL_MASK) * CCDC_CSC_DEC_MAX) / 100); } else { /* CSCM - MSB */ val2 = (csc->coeff[i].integer & CCDC_CSC_COEF_INTEG_MASK) << CCDC_CSC_COEF_INTEG_SHIFT; val2 |= (((csc->coeff[i].decimal & CCDC_CSC_COEF_DECIMAL_MASK) * CCDC_CSC_DEC_MAX) / 100); val2 <<= CCDC_CSCM_MSB_SHIFT; val2 |= val1; regw(val2, (CSCM0 + ((i - 1) << 1))); } } }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri17698.88%150.00%
Lad Prabhakar21.12%150.00%
Total178100.00%2100.00%

/* * ccdc_config_color_patterns() * configure parameters for color patterns */
static void ccdc_config_color_patterns(struct ccdc_col_pat *pat0, struct ccdc_col_pat *pat1) { u32 val; val = (pat0->olop | (pat0->olep << 2) | (pat0->elop << 4) | (pat0->elep << 6) | (pat1->olop << 8) | (pat1->olep << 10) | (pat1->elop << 12) | (pat1->elep << 14)); regw(val, COLPTN); }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri90100.00%1100.00%
Total90100.00%1100.00%

/* This function will configure CCDC for Raw mode image capture */
static int ccdc_config_raw(void) { struct ccdc_params_raw *params = &ccdc_cfg.bayer; struct ccdc_config_params_raw *config_params = &ccdc_cfg.bayer.config_params; unsigned int val; dev_dbg(ccdc_cfg.dev, "\nStarting ccdc_config_raw..."); /* restore power on defaults to register */ ccdc_restore_defaults(); /* CCDCFG register: * set CCD Not to swap input since input is RAW data * set FID detection function to Latch at V-Sync * set WENLOG - ccdc valid area to AND * set TRGSEL to WENBIT * set EXTRG to DISABLE * disable latching function on VSYNC - shadowed registers */ regw(CCDC_YCINSWP_RAW | CCDC_CCDCFG_FIDMD_LATCH_VSYNC | CCDC_CCDCFG_WENLOG_AND | CCDC_CCDCFG_TRGSEL_WEN | CCDC_CCDCFG_EXTRG_DISABLE | CCDC_LATCH_ON_VSYNC_DISABLE, CCDCFG); /* * Set VDHD direction to input, input type to raw input * normal data polarity, do not use external WEN */ val = (CCDC_VDHDOUT_INPUT | CCDC_RAW_IP_MODE | CCDC_DATAPOL_NORMAL | CCDC_EXWEN_DISABLE); /* * Configure the vertical sync polarity (MODESET.VDPOL), horizontal * sync polarity (MODESET.HDPOL), field id polarity (MODESET.FLDPOL), * frame format(progressive or interlace), & pixel format (Input mode) */ val |= (((params->vd_pol & CCDC_VD_POL_MASK) << CCDC_VD_POL_SHIFT) | ((params->hd_pol & CCDC_HD_POL_MASK) << CCDC_HD_POL_SHIFT) | ((params->fid_pol & CCDC_FID_POL_MASK) << CCDC_FID_POL_SHIFT) | ((params->frm_fmt & CCDC_FRM_FMT_MASK) << CCDC_FRM_FMT_SHIFT) | ((params->pix_fmt & CCDC_PIX_FMT_MASK) << CCDC_PIX_FMT_SHIFT)); /* set pack for alaw compression */ if ((config_params->data_sz == CCDC_DATA_8BITS) || config_params->alaw.enable) val |= CCDC_DATA_PACK_ENABLE; /* Configure for LPF */ if (config_params->lpf_enable) val |= (config_params->lpf_enable & CCDC_LPF_MASK) << CCDC_LPF_SHIFT; /* Configure the data shift */ val |= (config_params->datasft & CCDC_DATASFT_MASK) << CCDC_DATASFT_SHIFT; regw(val , MODESET); dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to MODESET...\n", val); /* Configure the Median Filter threshold */ regw((config_params->med_filt_thres) & CCDC_MED_FILT_THRESH, MEDFILT); /* Configure GAMMAWD register. defaur 11-2, and Mosaic cfa pattern */ val = CCDC_GAMMA_BITS_11_2 << CCDC_GAMMAWD_INPUT_SHIFT | CCDC_CFA_MOSAIC; /* Enable and configure aLaw register if needed */ if (config_params->alaw.enable) { val |= (CCDC_ALAW_ENABLE | ((config_params->alaw.gamma_wd & CCDC_ALAW_GAMMA_WD_MASK) << CCDC_GAMMAWD_INPUT_SHIFT)); } /* Configure Median filter1 & filter2 */ val |= ((config_params->mfilt1 << CCDC_MFILT1_SHIFT) | (config_params->mfilt2 << CCDC_MFILT2_SHIFT)); regw(val, GAMMAWD); dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to GAMMAWD...\n", val); /* configure video window */ ccdc_setwin(&params->win, params->frm_fmt, 1); /* Optical Clamp Averaging */ ccdc_config_black_clamp(&config_params->blk_clamp); /* Black level compensation */ ccdc_config_black_compense(&config_params->blk_comp); /* Vertical Defect Correction if needed */ if (ccdc_config_vdfc(&config_params->vertical_dft) < 0) return -EFAULT; /* color space conversion */ ccdc_config_csc(&config_params->csc); /* color pattern */ ccdc_config_color_patterns(&config_params->col_pat_field0, &config_params->col_pat_field1); /* Configure the Gain & offset control */ ccdc_config_gain_offset(); dev_dbg(ccdc_cfg.dev, "\nWriting %x to COLPTN...\n", val); /* Configure DATAOFST register */ val = (config_params->data_offset.horz_offset & CCDC_DATAOFST_MASK) << CCDC_DATAOFST_H_SHIFT; val |= (config_params->data_offset.vert_offset & CCDC_DATAOFST_MASK) << CCDC_DATAOFST_V_SHIFT; regw(val, DATAOFST); /* configuring HSIZE register */ val = (params->horz_flip_enable & CCDC_HSIZE_FLIP_MASK) << CCDC_HSIZE_FLIP_SHIFT; /* If pack 8 is enable then 1 pixel will take 1 byte */ if ((config_params->data_sz == CCDC_DATA_8BITS) || config_params->alaw.enable) { val |= (((params->win.width) + 31) >> 5) & CCDC_HSIZE_VAL_MASK; /* adjust to multiple of 32 */ dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to HSIZE...\n", (((params->win.width) + 31) >> 5) & CCDC_HSIZE_VAL_MASK); } else { /* else one pixel will take 2 byte */ val |= (((params->win.width * 2) + 31) >> 5) & CCDC_HSIZE_VAL_MASK; dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to HSIZE...\n", (((params->win.width * 2) + 31) >> 5) & CCDC_HSIZE_VAL_MASK); } regw(val, HSIZE); /* Configure SDOFST register */ if (params->frm_fmt == CCDC_FRMFMT_INTERLACED) { if (params->image_invert_enable) { /* For interlace inverse mode */ regw(CCDC_SDOFST_INTERLACE_INVERSE, SDOFST); dev_dbg(ccdc_cfg.dev, "\nWriting %x to SDOFST...\n", CCDC_SDOFST_INTERLACE_INVERSE); } else { /* For interlace non inverse mode */ regw(CCDC_SDOFST_INTERLACE_NORMAL, SDOFST); dev_dbg(ccdc_cfg.dev, "\nWriting %x to SDOFST...\n", CCDC_SDOFST_INTERLACE_NORMAL); } } else if (params->frm_fmt == CCDC_FRMFMT_PROGRESSIVE) { if (params->image_invert_enable) { /* For progessive inverse mode */ regw(CCDC_SDOFST_PROGRESSIVE_INVERSE, SDOFST); dev_dbg(ccdc_cfg.dev, "\nWriting %x to SDOFST...\n", CCDC_SDOFST_PROGRESSIVE_INVERSE); } else { /* For progessive non inverse mode */ regw(CCDC_SDOFST_PROGRESSIVE_NORMAL, SDOFST); dev_dbg(ccdc_cfg.dev, "\nWriting %x to SDOFST...\n", CCDC_SDOFST_PROGRESSIVE_NORMAL); } } dev_dbg(ccdc_cfg.dev, "\nend of ccdc_config_raw..."); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri70399.72%266.67%
Hans Verkuil20.28%133.33%
Total705100.00%3100.00%


static int ccdc_configure(void) { if (ccdc_cfg.if_type == VPFE_RAW_BAYER) return ccdc_config_raw(); else ccdc_config_ycbcr(); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri27100.00%2100.00%
Total27100.00%2100.00%


static int ccdc_set_buftype(enum ccdc_buftype buf_type) { if (ccdc_cfg.if_type == VPFE_RAW_BAYER) ccdc_cfg.bayer.buf_type = buf_type; else ccdc_cfg.ycbcr.buf_type = buf_type; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri38100.00%2100.00%
Total38100.00%2100.00%


static enum ccdc_buftype ccdc_get_buftype(void) { if (ccdc_cfg.if_type == VPFE_RAW_BAYER) return ccdc_cfg.bayer.buf_type; return ccdc_cfg.ycbcr.buf_type; }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri31100.00%2100.00%
Total31100.00%2100.00%


static int ccdc_enum_pix(u32 *pix, int i) { int ret = -EINVAL; if (ccdc_cfg.if_type == VPFE_RAW_BAYER) { if (i < ARRAY_SIZE(ccdc_raw_bayer_pix_formats)) { *pix = ccdc_raw_bayer_pix_formats[i]; ret = 0; } } else { if (i < ARRAY_SIZE(ccdc_raw_yuv_pix_formats)) { *pix = ccdc_raw_yuv_pix_formats[i]; ret = 0; } } return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri81100.00%2100.00%
Total81100.00%2100.00%


static int ccdc_set_pixel_format(u32 pixfmt) { struct ccdc_a_law *alaw = &ccdc_cfg.bayer.config_params.alaw; if (ccdc_cfg.if_type == VPFE_RAW_BAYER) { ccdc_cfg.bayer.pix_fmt = CCDC_PIXFMT_RAW; if (pixfmt == V4L2_PIX_FMT_SBGGR8) alaw->enable = 1; else if (pixfmt != V4L2_PIX_FMT_SBGGR16) return -EINVAL; } else { if (pixfmt == V4L2_PIX_FMT_YUYV) ccdc_cfg.ycbcr.pix_order = CCDC_PIXORDER_YCBYCR; else if (pixfmt == V4L2_PIX_FMT_UYVY) ccdc_cfg.ycbcr.pix_order = CCDC_PIXORDER_CBYCRY; else return -EINVAL; } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri104100.00%2100.00%
Total104100.00%2100.00%


static u32 ccdc_get_pixel_format(void) { struct ccdc_a_law *alaw = &ccdc_cfg.bayer.config_params.alaw; u32 pixfmt; if (ccdc_cfg.if_type == VPFE_RAW_BAYER) if (alaw->enable) pixfmt = V4L2_PIX_FMT_SBGGR8; else pixfmt = V4L2_PIX_FMT_SBGGR16; else { if (ccdc_cfg.ycbcr.pix_order == CCDC_PIXORDER_YCBYCR) pixfmt = V4L2_PIX_FMT_YUYV; else pixfmt = V4L2_PIX_FMT_UYVY; } return pixfmt; }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri73100.00%2100.00%
Total73100.00%2100.00%


static int ccdc_set_image_window(struct v4l2_rect *win) { if (ccdc_cfg.if_type == VPFE_RAW_BAYER) ccdc_cfg.bayer.win = *win; else ccdc_cfg.ycbcr.win = *win; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri41100.00%2100.00%
Total41100.00%2100.00%


static void ccdc_get_image_window(struct v4l2_rect *win) { if (ccdc_cfg.if_type == VPFE_RAW_BAYER) *win = ccdc_cfg.bayer.win; else *win = ccdc_cfg.ycbcr.win; }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri38100.00%2100.00%
Total38100.00%2100.00%


static unsigned int ccdc_get_line_length(void) { struct ccdc_config_params_raw *config_params = &ccdc_cfg.bayer.config_params; unsigned int len; if (ccdc_cfg.if_type == VPFE_RAW_BAYER) { if ((config_params->alaw.enable) || (config_params->data_sz == CCDC_DATA_8BITS)) len = ccdc_cfg.bayer.win.width; else len = ccdc_cfg.bayer.win.width * 2; } else len = ccdc_cfg.ycbcr.win.width * 2; return ALIGN(len, 32); }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri97100.00%2100.00%
Total97100.00%2100.00%


static int ccdc_set_frame_format(enum ccdc_frmfmt frm_fmt) { if (ccdc_cfg.if_type == VPFE_RAW_BAYER) ccdc_cfg.bayer.frm_fmt = frm_fmt; else ccdc_cfg.ycbcr.frm_fmt = frm_fmt; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri38100.00%2100.00%
Total38100.00%2100.00%


static enum ccdc_frmfmt ccdc_get_frame_format(void) { if (ccdc_cfg.if_type == VPFE_RAW_BAYER) return ccdc_cfg.bayer.frm_fmt; else return ccdc_cfg.ycbcr.frm_fmt; }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri32100.00%2100.00%
Total32100.00%2100.00%


static int ccdc_getfid(void) { return (regr(MODESET) >> 15) & 1; }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri20100.00%1100.00%
Total20100.00%1100.00%

/* misc operations */
static inline void ccdc_setfbaddr(unsigned long addr) { regw((addr >> 21) & 0x007f, STADRH); regw((addr >> 5) & 0x0ffff, STADRL); }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri37100.00%1100.00%
Total37100.00%1100.00%


static int ccdc_set_hw_if_params(struct vpfe_hw_if_param *params) { ccdc_cfg.if_type = params->if_type; switch (params->if_type) { case VPFE_BT656: case VPFE_YCBCR_SYNC_16: case VPFE_YCBCR_SYNC_8: ccdc_cfg.ycbcr.vd_pol = params->vdpol; ccdc_cfg.ycbcr.hd_pol = params->hdpol; break; default: /* TODO add support for raw bayer here */ return -EINVAL; } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri66100.00%2100.00%
Total66100.00%2100.00%

static struct ccdc_hw_device ccdc_hw_dev = { .name = "DM355 CCDC", .owner = THIS_MODULE, .hw_ops = { .open = ccdc_open, .close = ccdc_close, .enable = ccdc_enable, .enable_out_to_sdram = ccdc_enable_output_to_sdram, .set_hw_if_params = ccdc_set_hw_if_params, .set_params = ccdc_set_params, .configure = ccdc_configure, .set_buftype = ccdc_set_buftype, .get_buftype = ccdc_get_buftype, .enum_pix = ccdc_enum_pix, .set_pixel_format = ccdc_set_pixel_format, .get_pixel_format = ccdc_get_pixel_format, .set_frame_format = ccdc_set_frame_format, .get_frame_format = ccdc_get_frame_format, .set_image_window = ccdc_set_image_window, .get_image_window = ccdc_get_image_window, .get_line_length = ccdc_get_line_length, .setfbaddr = ccdc_setfbaddr, .getfid = ccdc_getfid, }, };
static int dm355_ccdc_probe(struct platform_device *pdev) { void (*setup_pinmux)(void); struct resource *res; int status = 0; /* * first try to register with vpfe. If not correct platform, then we * don't have to iomap */ status = vpfe_register_ccdc_device(&ccdc_hw_dev); if (status < 0) return status; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { status = -ENODEV; goto fail_nores; } res = request_mem_region(res->start, resource_size(res), res->name); if (!res) { status = -EBUSY; goto fail_nores; } ccdc_cfg.base_addr = ioremap_nocache(res->start, resource_size(res)); if (!ccdc_cfg.base_addr) { status = -ENOMEM; goto fail_nomem; } /* Platform data holds setup_pinmux function ptr */ if (NULL == pdev->dev.platform_data) { status = -ENODEV; goto fail_nomap; } setup_pinmux = pdev->dev.platform_data; /* * setup Mux configuration for ccdc which may be different for * different SoCs using this CCDC */ setup_pinmux(); ccdc_cfg.dev = &pdev->dev; printk(KERN_NOTICE "%s is registered with vpfe.\n", ccdc_hw_dev.name); return 0; fail_nomap: iounmap(ccdc_cfg.base_addr); fail_nomem: release_mem_region(res->start, resource_size(res)); fail_nores: vpfe_unregister_ccdc_device(&ccdc_hw_dev); return status; }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri22899.56%266.67%
Lad Prabhakar10.44%133.33%
Total229100.00%3100.00%


static int dm355_ccdc_remove(struct platform_device *pdev) { struct resource *res; iounmap(ccdc_cfg.base_addr); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (res) release_mem_region(res->start, resource_size(res)); vpfe_unregister_ccdc_device(&ccdc_hw_dev); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri59100.00%1100.00%
Total59100.00%1100.00%

static struct platform_driver dm355_ccdc_driver = { .driver = { .name = "dm355_ccdc", }, .remove = dm355_ccdc_remove, .probe = dm355_ccdc_probe, }; module_platform_driver(dm355_ccdc_driver);

Overall Contributors

PersonTokensPropCommitsCommitProp
Murali Karicheri420499.53%216.67%
Lad Prabhakar60.14%325.00%
Hans Verkuil50.12%18.33%
Paul Gortmaker30.07%18.33%
Mauro Carvalho Chehab20.05%216.67%
Axel Lin20.05%18.33%
Masanari Iida10.02%18.33%
Sakari Ailus10.02%18.33%
Total4224100.00%12100.00%
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.