diff options
Diffstat (limited to 'recipes/kexecboot/linux-kexecboot-2.6.29/isp/omap3camera/0004-omap3isp-Add-ISP-frontend-CCDC.patch')
-rw-r--r-- | recipes/kexecboot/linux-kexecboot-2.6.29/isp/omap3camera/0004-omap3isp-Add-ISP-frontend-CCDC.patch | 1875 |
1 files changed, 1875 insertions, 0 deletions
diff --git a/recipes/kexecboot/linux-kexecboot-2.6.29/isp/omap3camera/0004-omap3isp-Add-ISP-frontend-CCDC.patch b/recipes/kexecboot/linux-kexecboot-2.6.29/isp/omap3camera/0004-omap3isp-Add-ISP-frontend-CCDC.patch new file mode 100644 index 0000000000..4a161729fd --- /dev/null +++ b/recipes/kexecboot/linux-kexecboot-2.6.29/isp/omap3camera/0004-omap3isp-Add-ISP-frontend-CCDC.patch @@ -0,0 +1,1875 @@ +From 9ea796fe5383a6961125a6a18185a901fe8627d7 Mon Sep 17 00:00:00 2001 +From: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com> +Date: Tue, 10 Mar 2009 10:49:02 +0200 +Subject: [PATCH] omap3isp: Add ISP frontend (CCDC) + +Signed-off-by: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com> +--- + drivers/media/video/isp/ispccdc.c | 1638 +++++++++++++++++++++++++++++++++++++ + drivers/media/video/isp/ispccdc.h | 209 +++++ + 2 files changed, 1847 insertions(+), 0 deletions(-) + create mode 100644 drivers/media/video/isp/ispccdc.c + create mode 100644 drivers/media/video/isp/ispccdc.h + +diff --git a/drivers/media/video/isp/ispccdc.c b/drivers/media/video/isp/ispccdc.c +new file mode 100644 +index 0000000..2574ea2 +--- /dev/null ++++ b/drivers/media/video/isp/ispccdc.c +@@ -0,0 +1,1638 @@ ++/* ++ * ispccdc.c ++ * ++ * Driver Library for CCDC module in TI's OMAP3 Camera ISP ++ * ++ * Copyright (C) 2009 Texas Instruments, Inc. ++ * ++ * Contributors: ++ * Senthilvadivu Guruswamy <svadivu@ti.com> ++ * Pallavi Kulkarni <p-kulkarni@ti.com> ++ * Sergio Aguirre <saaguirre@ti.com> ++ * ++ * This package is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR ++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED ++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. ++ */ ++ ++#include <linux/mutex.h> ++#include <linux/module.h> ++#include <linux/uaccess.h> ++ ++#include "isp.h" ++#include "ispreg.h" ++#include "ispccdc.h" ++#include "ispmmu.h" ++ ++#define LSC_TABLE_INIT_SIZE 50052 ++ ++static u32 *fpc_table_add; ++static unsigned long fpc_table_add_m; ++ ++/** ++ * struct isp_ccdc - Structure for the CCDC module to store its own information ++ * @ccdc_inuse: Flag to determine if CCDC has been reserved or not (0 or 1). ++ * @ccdcout_w: CCDC output width. ++ * @ccdcout_h: CCDC output height. ++ * @ccdcin_w: CCDC input width. ++ * @ccdcin_h: CCDC input height. ++ * @ccdcin_woffset: CCDC input horizontal offset. ++ * @ccdcin_hoffset: CCDC input vertical offset. ++ * @crop_w: Crop width. ++ * @crop_h: Crop weight. ++ * @ccdc_inpfmt: CCDC input format. ++ * @ccdc_outfmt: CCDC output format. ++ * @vpout_en: Video port output enable. ++ * @wen: Data write enable. ++ * @exwen: External data write enable. ++ * @refmt_en: Reformatter enable. ++ * @ccdcslave: CCDC slave mode enable. ++ * @syncif_ipmod: Image ++ * @obclamp_en: Data input format. ++ * @mutexlock: Mutex used to get access to the CCDC. ++ */ ++static struct isp_ccdc { ++ u8 ccdc_inuse; ++ u32 ccdcout_w; ++ u32 ccdcout_h; ++ u32 ccdcin_w; ++ u32 ccdcin_h; ++ u32 ccdcin_woffset; ++ u32 ccdcin_hoffset; ++ u32 crop_w; ++ u32 crop_h; ++ u8 ccdc_inpfmt; ++ u8 ccdc_outfmt; ++ u8 vpout_en; ++ u8 wen; ++ u8 exwen; ++ u8 refmt_en; ++ u8 ccdcslave; ++ u8 syncif_ipmod; ++ u8 obclamp_en; ++ u8 pm_state; ++ u8 lsc_enable; ++ int lsc_state; ++ struct mutex mutexlock; /* For checking/modifying ccdc_inuse */ ++ u32 wenlog; ++} ispccdc_obj; ++ ++static struct ispccdc_lsc_config lsc_config; ++static u8 *lsc_gain_table; ++static unsigned long lsc_ispmmu_addr; ++static int lsc_initialized; ++static u8 *lsc_gain_table_tmp; ++ ++/* Structure for saving/restoring CCDC module registers*/ ++static struct isp_reg ispccdc_reg_list[] = { ++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE, 0}, ++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_HD_VD_WID, 0}, ++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_PIX_LINES, 0}, ++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_HORZ_INFO, 0}, ++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_VERT_START, 0}, ++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_VERT_LINES, 0}, ++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CULLING, 0}, ++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_HSIZE_OFF, 0}, ++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST, 0}, ++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDR_ADDR, 0}, ++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CLAMP, 0}, ++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_DCSUB, 0}, ++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_COLPTN, 0}, ++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_BLKCMP, 0}, ++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FPC, 0}, ++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FPC_ADDR, 0}, ++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_VDINT, 0}, ++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_ALAW, 0}, ++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_REC656IF, 0}, ++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CFG, 0}, ++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG, 0}, ++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_HORZ, 0}, ++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_VERT, 0}, ++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_ADDR0, 0}, ++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_ADDR1, 0}, ++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_ADDR2, 0}, ++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_ADDR3, 0}, ++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_ADDR4, 0}, ++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_ADDR5, 0}, ++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_ADDR6, 0}, ++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_ADDR7, 0}, ++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_PRGEVEN0, 0}, ++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_PRGEVEN1, 0}, ++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_PRGODD0, 0}, ++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_PRGODD1, 0}, ++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_VP_OUT, 0}, ++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_CONFIG, 0}, ++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_INITIAL, 0}, ++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_TABLE_BASE, 0}, ++ {OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_TABLE_OFFSET, 0}, ++ {0, ISP_TOK_TERM, 0} ++}; ++ ++/** ++ * omap34xx_isp_ccdc_config - Sets CCDC configuration from userspace ++ * @userspace_add: Structure containing CCDC configuration sent from userspace. ++ * ++ * Returns 0 if successful, -EINVAL if the pointer to the configuration ++ * structure is null, or the copy_from_user function fails to copy user space ++ * memory to kernel space memory. ++ **/ ++int omap34xx_isp_ccdc_config(void *userspace_add) ++{ ++ struct ispccdc_bclamp bclamp_t; ++ struct ispccdc_blcomp blcomp_t; ++ struct ispccdc_fpc fpc_t; ++ struct ispccdc_culling cull_t; ++ struct ispccdc_update_config *ccdc_struct; ++ ++ if (userspace_add == NULL) ++ return -EINVAL; ++ ++ ccdc_struct = userspace_add; ++ ++ if (ISP_ABS_CCDC_ALAW & ccdc_struct->flag) { ++ if (ISP_ABS_CCDC_ALAW & ccdc_struct->update) ++ ispccdc_config_alaw(ccdc_struct->alawip); ++ ispccdc_enable_alaw(1); ++ } else if (ISP_ABS_CCDC_ALAW & ccdc_struct->update) ++ ispccdc_enable_alaw(0); ++ ++ if (ISP_ABS_CCDC_LPF & ccdc_struct->flag) ++ ispccdc_enable_lpf(1); ++ else ++ ispccdc_enable_lpf(0); ++ ++ if (ISP_ABS_CCDC_BLCLAMP & ccdc_struct->flag) { ++ if (ISP_ABS_CCDC_BLCLAMP & ccdc_struct->update) { ++ if (copy_from_user(&bclamp_t, (struct ispccdc_bclamp *) ++ ccdc_struct->bclamp, ++ sizeof(struct ispccdc_bclamp))) ++ goto copy_from_user_err; ++ ++ ispccdc_enable_black_clamp(1); ++ ispccdc_config_black_clamp(bclamp_t); ++ } else ++ ispccdc_enable_black_clamp(1); ++ } else { ++ if (ISP_ABS_CCDC_BLCLAMP & ccdc_struct->update) { ++ if (copy_from_user(&bclamp_t, (struct ispccdc_bclamp *) ++ ccdc_struct->bclamp, ++ sizeof(struct ispccdc_bclamp))) ++ goto copy_from_user_err; ++ ++ ispccdc_enable_black_clamp(0); ++ ispccdc_config_black_clamp(bclamp_t); ++ } ++ } ++ ++ if (ISP_ABS_CCDC_BCOMP & ccdc_struct->update) { ++ if (copy_from_user(&blcomp_t, (struct ispccdc_blcomp *) ++ ccdc_struct->blcomp, ++ sizeof(blcomp_t))) ++ goto copy_from_user_err; ++ ++ ispccdc_config_black_comp(blcomp_t); ++ } ++ ++ if (ISP_ABS_CCDC_FPC & ccdc_struct->flag) { ++ if (ISP_ABS_CCDC_FPC & ccdc_struct->update) { ++ if (copy_from_user(&fpc_t, (struct ispccdc_fpc *) ++ ccdc_struct->fpc, ++ sizeof(fpc_t))) ++ goto copy_from_user_err; ++ fpc_table_add = kmalloc(64 + fpc_t.fpnum * 4, ++ GFP_KERNEL | GFP_DMA); ++ if (!fpc_table_add) { ++ printk(KERN_ERR "Cannot allocate memory for" ++ " FPC table"); ++ return -ENOMEM; ++ } ++ while (((unsigned long)fpc_table_add & 0xFFFFFFC0) ++ != (unsigned long)fpc_table_add) ++ fpc_table_add++; ++ ++ fpc_table_add_m = ispmmu_kmap(virt_to_phys ++ (fpc_table_add), ++ fpc_t.fpnum * 4); ++ ++ if (copy_from_user(fpc_table_add, (u32 *)fpc_t.fpcaddr, ++ fpc_t.fpnum * 4)) ++ goto copy_from_user_err; ++ ++ fpc_t.fpcaddr = fpc_table_add_m; ++ ispccdc_config_fpc(fpc_t); ++ } ++ ispccdc_enable_fpc(1); ++ } else if (ISP_ABS_CCDC_FPC & ccdc_struct->update) ++ ispccdc_enable_fpc(0); ++ ++ if (ISP_ABS_CCDC_CULL & ccdc_struct->update) { ++ if (copy_from_user(&cull_t, (struct ispccdc_culling *) ++ ccdc_struct->cull, ++ sizeof(cull_t))) ++ goto copy_from_user_err; ++ ispccdc_config_culling(cull_t); ++ } ++ ++ if (is_isplsc_activated()) { ++ if (ISP_ABS_CCDC_CONFIG_LSC & ccdc_struct->flag) { ++ if (ISP_ABS_CCDC_CONFIG_LSC & ccdc_struct->update) { ++ if (copy_from_user( ++ &lsc_config, ++ (struct ispccdc_lsc_config *) ++ ccdc_struct->lsc_cfg, ++ sizeof(struct ispccdc_lsc_config))) ++ goto copy_from_user_err; ++ ispccdc_config_lsc(&lsc_config); ++ } ++ ispccdc_enable_lsc(1); ++ } else if (ISP_ABS_CCDC_CONFIG_LSC & ccdc_struct->update) { ++ ispccdc_enable_lsc(0); ++ } ++ if (ISP_ABS_TBL_LSC & ccdc_struct->update) { ++ if (copy_from_user(lsc_gain_table, ++ ccdc_struct->lsc, lsc_config.size)) ++ goto copy_from_user_err; ++ ispccdc_load_lsc(lsc_gain_table, lsc_config.size); ++ } ++ } ++ ++ if (ISP_ABS_CCDC_COLPTN & ccdc_struct->update) ++ ispccdc_config_imgattr(ccdc_struct->colptn); ++ ++ return 0; ++ ++copy_from_user_err: ++ printk(KERN_ERR "CCDC Config:Copy From User Error"); ++ return -EINVAL ; ++} ++EXPORT_SYMBOL(omap34xx_isp_ccdc_config); ++ ++/** ++ * Set the value to be used for CCDC_CFG.WENLOG. ++ * w - Value of wenlog. ++ */ ++void ispccdc_set_wenlog(u32 wenlog) ++{ ++ ispccdc_obj.wenlog = wenlog; ++} ++EXPORT_SYMBOL(ispccdc_set_wenlog); ++ ++/** ++ * ispccdc_request - Reserves the CCDC module. ++ * ++ * Reserves the CCDC module and assures that is used only once at a time. ++ * ++ * Returns 0 if successful, or -EBUSY if CCDC module is busy. ++ **/ ++int ispccdc_request(void) ++{ ++ mutex_lock(&ispccdc_obj.mutexlock); ++ if (ispccdc_obj.ccdc_inuse) { ++ mutex_unlock(&ispccdc_obj.mutexlock); ++ DPRINTK_ISPCCDC("ISP_ERR : CCDC Module Busy\n"); ++ return -EBUSY; ++ } ++ ++ ispccdc_obj.ccdc_inuse = 1; ++ mutex_unlock(&ispccdc_obj.mutexlock); ++ isp_reg_or(OMAP3_ISP_IOMEM_MAIN, ISP_CTRL, ISPCTRL_CCDC_RAM_EN | ++ ISPCTRL_CCDC_CLK_EN | ++ ISPCTRL_SBL_WR1_RAM_EN); ++ isp_reg_or(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CFG, ISPCCDC_CFG_VDLC); ++ return 0; ++} ++EXPORT_SYMBOL(ispccdc_request); ++ ++/** ++ * ispccdc_free - Frees the CCDC module. ++ * ++ * Frees the CCDC module so it can be used by another process. ++ * ++ * Returns 0 if successful, or -EINVAL if module has been already freed. ++ **/ ++int ispccdc_free(void) ++{ ++ mutex_lock(&ispccdc_obj.mutexlock); ++ if (!ispccdc_obj.ccdc_inuse) { ++ mutex_unlock(&ispccdc_obj.mutexlock); ++ DPRINTK_ISPCCDC("ISP_ERR: CCDC Module already freed\n"); ++ return -EINVAL; ++ } ++ ++ ispccdc_obj.ccdc_inuse = 0; ++ mutex_unlock(&ispccdc_obj.mutexlock); ++ isp_reg_and(OMAP3_ISP_IOMEM_MAIN, ISP_CTRL, ++ ~(ISPCTRL_CCDC_CLK_EN | ++ ISPCTRL_CCDC_RAM_EN | ++ ISPCTRL_SBL_WR1_RAM_EN)); ++ return 0; ++} ++EXPORT_SYMBOL(ispccdc_free); ++ ++/** ++ * ispccdc_free_lsc - Frees Lens Shading Compensation table ++ * ++ * Always returns 0. ++ **/ ++static int ispccdc_free_lsc(void) ++{ ++ if (!lsc_ispmmu_addr) ++ return 0; ++ ++ ispccdc_enable_lsc(0); ++ lsc_initialized = 0; ++ isp_reg_writel(0, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_TABLE_BASE); ++ ispmmu_kunmap(lsc_ispmmu_addr); ++ kfree(lsc_gain_table); ++ return 0; ++} ++ ++/** ++ * ispccdc_allocate_lsc - Allocate space for Lens Shading Compensation table ++ * @table_size: LSC gain table size. ++ * ++ * Returns 0 if successful, -ENOMEM of its no memory available, or -EINVAL if ++ * table_size is zero. ++ **/ ++static int ispccdc_allocate_lsc(u32 table_size) ++{ ++ if (table_size == 0) ++ return -EINVAL; ++ ++ if ((lsc_config.size >= table_size) && lsc_gain_table) ++ return 0; ++ ++ ispccdc_free_lsc(); ++ ++ lsc_gain_table = kmalloc(table_size, GFP_KERNEL | GFP_DMA); ++ ++ if (!lsc_gain_table) { ++ printk(KERN_ERR "Cannot allocate memory for gain tables \n"); ++ return -ENOMEM; ++ } ++ ++ lsc_ispmmu_addr = ispmmu_kmap(virt_to_phys(lsc_gain_table), table_size); ++ if (lsc_ispmmu_addr <= 0) { ++ printk(KERN_ERR "Cannot map memory for gain tables \n"); ++ kfree(lsc_gain_table); ++ return -ENOMEM; ++ } ++ ++ return 0; ++} ++ ++/** ++ * ispccdc_program_lsc - Program Lens Shading Compensation table. ++ * @table_size: LSC gain table size. ++ * ++ * Returns 0 if successful, or -EINVAL if there's no mapped address for the ++ * table yet. ++ **/ ++static int ispccdc_program_lsc(void) ++{ ++ if (!lsc_ispmmu_addr) ++ return -EINVAL; ++ ++ if (lsc_initialized) ++ return 0; ++ ++ isp_reg_writel(lsc_ispmmu_addr, OMAP3_ISP_IOMEM_CCDC, ++ ISPCCDC_LSC_TABLE_BASE); ++ lsc_initialized = 1; ++ return 0; ++} ++ ++/** ++ * ispccdc_load_lsc - Load Lens Shading Compensation table. ++ * @table_addr: LSC gain table MMU Mapped address. ++ * @table_size: LSC gain table size. ++ * ++ * Returns 0 if successful, -ENOMEM of its no memory available, or -EINVAL if ++ * table_size is zero. ++ **/ ++int ispccdc_load_lsc(u8 *table_addr, u32 table_size) ++{ ++ int ret; ++ ++ if (!is_isplsc_activated()) ++ return 0; ++ ++ if (!table_addr) ++ return -EINVAL; ++ ++ ret = ispccdc_allocate_lsc(table_size); ++ if (ret) ++ return ret; ++ ++ if (table_addr != lsc_gain_table) ++ memcpy(lsc_gain_table, table_addr, table_size); ++ ret = ispccdc_program_lsc(); ++ if (ret) ++ return ret; ++ return 0; ++} ++EXPORT_SYMBOL(ispccdc_load_lsc); ++ ++/** ++ * ispccdc_config_lsc - Configures the lens shading compensation module ++ * @lsc_cfg: LSC configuration structure ++ **/ ++void ispccdc_config_lsc(struct ispccdc_lsc_config *lsc_cfg) ++{ ++ int reg; ++ ++ if (!is_isplsc_activated()) ++ return; ++ ++ ispccdc_enable_lsc(0); ++ isp_reg_writel(lsc_cfg->offset, OMAP3_ISP_IOMEM_CCDC, ++ ISPCCDC_LSC_TABLE_OFFSET); ++ ++ reg = 0; ++ reg |= lsc_cfg->gain_mode_n << ISPCCDC_LSC_GAIN_MODE_N_SHIFT; ++ reg |= lsc_cfg->gain_mode_m << ISPCCDC_LSC_GAIN_MODE_M_SHIFT; ++ reg |= lsc_cfg->gain_format << ISPCCDC_LSC_GAIN_FORMAT_SHIFT; ++ isp_reg_writel(reg, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_CONFIG); ++ ++ reg = 0; ++ reg &= ~ISPCCDC_LSC_INITIAL_X_MASK; ++ reg |= lsc_cfg->initial_x << ISPCCDC_LSC_INITIAL_X_SHIFT; ++ reg &= ~ISPCCDC_LSC_INITIAL_Y_MASK; ++ reg |= lsc_cfg->initial_y << ISPCCDC_LSC_INITIAL_Y_SHIFT; ++ isp_reg_writel(reg, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_INITIAL); ++} ++EXPORT_SYMBOL(ispccdc_config_lsc); ++ ++int __ispccdc_enable_lsc(u8 enable) ++{ ++ if (!is_isplsc_activated()) ++ return -ENODEV; ++ ++ if (enable) { ++ if (!ispccdc_busy()) { ++ isp_reg_or(OMAP3_ISP_IOMEM_MAIN, ISP_CTRL, ++ ISPCTRL_SBL_SHARED_RPORTB ++ | ISPCTRL_SBL_RD_RAM_EN); ++ ++ isp_reg_or(OMAP3_ISP_IOMEM_CCDC, ++ ISPCCDC_LSC_CONFIG, 0x1); ++ ++ ispccdc_obj.lsc_state = 1; ++ } else { ++ /* Postpone enabling LSC */ ++ ispccdc_obj.lsc_enable = 1; ++ return -EBUSY; ++ } ++ } else { ++ isp_reg_and(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_CONFIG, 0xFFFE); ++ ispccdc_obj.lsc_state = ispccdc_obj.lsc_enable = 0; ++ } ++ ++ return 0; ++} ++ ++/** ++ * ispccdc_enable_lsc - Enables/Disables the Lens Shading Compensation module. ++ * @enable: 0 Disables LSC, 1 Enables LSC. ++ **/ ++void ispccdc_enable_lsc(u8 enable) ++{ ++ if (__ispccdc_enable_lsc(enable)) { ++ if (enable) ++ ispccdc_obj.lsc_state = 1; ++ else ++ ispccdc_obj.lsc_state = ispccdc_obj.lsc_enable = 0; ++ } ++} ++EXPORT_SYMBOL(ispccdc_enable_lsc); ++ ++void ispccdc_lsc_error_handler(void) ++{ ++ int lsc_enable = ispccdc_obj.lsc_state; ++ ++ ispccdc_enable_lsc(0); ++ ++ ispccdc_obj.lsc_enable = lsc_enable; ++} ++ ++/** ++ * ispccdc_config_crop - Configures crop parameters for the ISP CCDC. ++ * @left: Left offset of the crop area. ++ * @top: Top offset of the crop area. ++ * @height: Height of the crop area. ++ * @width: Width of the crop area. ++ * ++ * The following restrictions are applied for the crop settings. If incoming ++ * values do not follow these restrictions then we map the settings to the ++ * closest acceptable crop value. ++ * 1) Left offset is always odd. This can be avoided if we enable byte swap ++ * option for incoming data into CCDC. ++ * 2) Top offset is always even. ++ * 3) Crop height is always even. ++ * 4) Crop width is always a multiple of 16 pixels ++ **/ ++void ispccdc_config_crop(u32 left, u32 top, u32 height, u32 width) ++{ ++ ispccdc_obj.ccdcin_woffset = left + (left % 2); ++ ispccdc_obj.ccdcin_hoffset = top + (top % 2); ++ ++ ispccdc_obj.crop_w = width - (width % 16); ++ ispccdc_obj.crop_h = height + (height % 2); ++ ++ DPRINTK_ISPCCDC("\n\tOffsets L %d T %d W %d H %d\n", ++ ispccdc_obj.ccdcin_woffset, ++ ispccdc_obj.ccdcin_hoffset, ++ ispccdc_obj.crop_w, ++ ispccdc_obj.crop_h); ++} ++ ++/** ++ * ispccdc_config_datapath - Specifies the input and output modules for CCDC. ++ * @input: Indicates the module that inputs the image to the CCDC. ++ * @output: Indicates the module to which the CCDC outputs the image. ++ * ++ * Configures the default configuration for the CCDC to work with. ++ * ++ * The valid values for the input are CCDC_RAW (0), CCDC_YUV_SYNC (1), ++ * CCDC_YUV_BT (2), and CCDC_OTHERS (3). ++ * ++ * The valid values for the output are CCDC_YUV_RSZ (0), CCDC_YUV_MEM_RSZ (1), ++ * CCDC_OTHERS_VP (2), CCDC_OTHERS_MEM (3), CCDC_OTHERS_VP_MEM (4). ++ * ++ * Returns 0 if successful, or -EINVAL if wrong I/O combination or wrong input ++ * or output values. ++ **/ ++int ispccdc_config_datapath(enum ccdc_input input, enum ccdc_output output) ++{ ++ u32 syn_mode = 0; ++ struct ispccdc_vp vpcfg; ++ struct ispccdc_syncif syncif; ++ struct ispccdc_bclamp blkcfg; ++ ++ u32 colptn = ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP0PLC0_SHIFT | ++ ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP0PLC1_SHIFT | ++ ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP0PLC2_SHIFT | ++ ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP0PLC3_SHIFT | ++ ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP1PLC0_SHIFT | ++ ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP1PLC1_SHIFT | ++ ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP1PLC2_SHIFT | ++ ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP1PLC3_SHIFT | ++ ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP2PLC0_SHIFT | ++ ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP2PLC1_SHIFT | ++ ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP2PLC2_SHIFT | ++ ISPCCDC_COLPTN_R_Ye << ISPCCDC_COLPTN_CP2PLC3_SHIFT | ++ ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP3PLC0_SHIFT | ++ ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP3PLC1_SHIFT | ++ ISPCCDC_COLPTN_B_Mg << ISPCCDC_COLPTN_CP3PLC2_SHIFT | ++ ISPCCDC_COLPTN_Gb_G << ISPCCDC_COLPTN_CP3PLC3_SHIFT; ++ ++ /* CCDC does not convert the image format */ ++ if ((input == CCDC_RAW || input == CCDC_OTHERS) && ++ output == CCDC_YUV_RSZ) { ++ DPRINTK_ISPCCDC("ISP_ERR: Wrong CCDC I/O Combination\n"); ++ return -EINVAL; ++ } ++ ++ syn_mode = isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE); ++ ++ switch (output) { ++ case CCDC_YUV_RSZ: ++ syn_mode |= ISPCCDC_SYN_MODE_SDR2RSZ; ++ syn_mode &= ~ISPCCDC_SYN_MODE_WEN; ++ break; ++ ++ case CCDC_YUV_MEM_RSZ: ++ syn_mode |= ISPCCDC_SYN_MODE_SDR2RSZ; ++ ispccdc_obj.wen = 1; ++ syn_mode |= ISPCCDC_SYN_MODE_WEN; ++ break; ++ ++ case CCDC_OTHERS_VP: ++ syn_mode &= ~ISPCCDC_SYN_MODE_VP2SDR; ++ syn_mode &= ~ISPCCDC_SYN_MODE_SDR2RSZ; ++ syn_mode &= ~ISPCCDC_SYN_MODE_WEN; ++ vpcfg.bitshift_sel = BIT9_0; ++ vpcfg.freq_sel = PIXCLKBY2; ++ ispccdc_config_vp(vpcfg); ++ ispccdc_enable_vp(1); ++ break; ++ ++ case CCDC_OTHERS_MEM: ++ syn_mode &= ~ISPCCDC_SYN_MODE_VP2SDR; ++ syn_mode &= ~ISPCCDC_SYN_MODE_SDR2RSZ; ++ syn_mode |= ISPCCDC_SYN_MODE_WEN; ++ syn_mode &= ~ISPCCDC_SYN_MODE_EXWEN; ++ isp_reg_and(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CFG, ++ ~ISPCCDC_CFG_WENLOG); ++ vpcfg.bitshift_sel = BIT11_2; ++ vpcfg.freq_sel = PIXCLKBY2; ++ ispccdc_config_vp(vpcfg); ++ ispccdc_enable_vp(0); ++ break; ++ ++ case CCDC_OTHERS_VP_MEM: ++ syn_mode &= ~ISPCCDC_SYN_MODE_VP2SDR; ++ syn_mode &= ~ISPCCDC_SYN_MODE_SDR2RSZ; ++ syn_mode |= ISPCCDC_SYN_MODE_WEN; ++ syn_mode &= ~ISPCCDC_SYN_MODE_EXWEN; ++ ++ isp_reg_and_or(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CFG, ++ ~ISPCCDC_CFG_WENLOG, ++ ispccdc_obj.wenlog); ++ vpcfg.bitshift_sel = BIT9_0; ++ vpcfg.freq_sel = PIXCLKBY2; ++ ispccdc_config_vp(vpcfg); ++ ispccdc_enable_vp(1); ++ break; ++ default: ++ DPRINTK_ISPCCDC("ISP_ERR: Wrong CCDC Output\n"); ++ return -EINVAL; ++ }; ++ ++ isp_reg_writel(syn_mode, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE); ++ ++ switch (input) { ++ case CCDC_RAW: ++ syncif.ccdc_mastermode = 0; ++ syncif.datapol = 0; ++ syncif.datsz = DAT10; ++ syncif.fldmode = 0; ++ syncif.fldout = 0; ++ syncif.fldpol = 0; ++ syncif.fldstat = 0; ++ syncif.hdpol = 0; ++ syncif.ipmod = RAW; ++ syncif.vdpol = 0; ++ ispccdc_config_sync_if(syncif); ++ ispccdc_config_imgattr(colptn); ++ blkcfg.dcsubval = 64; ++ ispccdc_config_black_clamp(blkcfg); ++ if (is_isplsc_activated()) { ++ ispccdc_config_lsc(&lsc_config); ++ ispccdc_load_lsc(lsc_gain_table_tmp, ++ LSC_TABLE_INIT_SIZE); ++ } ++ ++ break; ++ case CCDC_YUV_SYNC: ++ syncif.ccdc_mastermode = 0; ++ syncif.datapol = 0; ++ syncif.datsz = DAT8; ++ syncif.fldmode = 0; ++ syncif.fldout = 0; ++ syncif.fldpol = 0; ++ syncif.fldstat = 0; ++ syncif.hdpol = 0; ++ syncif.ipmod = YUV16; ++ syncif.vdpol = 1; ++ ispccdc_config_imgattr(0); ++ ispccdc_config_sync_if(syncif); ++ blkcfg.dcsubval = 0; ++ ispccdc_config_black_clamp(blkcfg); ++ break; ++ case CCDC_YUV_BT: ++ break; ++ case CCDC_OTHERS: ++ break; ++ default: ++ DPRINTK_ISPCCDC("ISP_ERR: Wrong CCDC Input\n"); ++ return -EINVAL; ++ } ++ ++ ispccdc_obj.ccdc_inpfmt = input; ++ ispccdc_obj.ccdc_outfmt = output; ++ ispccdc_print_status(); ++ isp_print_status(); ++ return 0; ++} ++EXPORT_SYMBOL(ispccdc_config_datapath); ++ ++/** ++ * ispccdc_config_sync_if - Sets the sync i/f params between sensor and CCDC. ++ * @syncif: Structure containing the sync parameters like field state, CCDC in ++ * master/slave mode, raw/yuv data, polarity of data, field, hs, vs ++ * signals. ++ **/ ++void ispccdc_config_sync_if(struct ispccdc_syncif syncif) ++{ ++ u32 syn_mode = isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE); ++ ++ syn_mode |= ISPCCDC_SYN_MODE_VDHDEN; ++ ++ if (syncif.fldstat) ++ syn_mode |= ISPCCDC_SYN_MODE_FLDSTAT; ++ else ++ syn_mode &= ~ISPCCDC_SYN_MODE_FLDSTAT; ++ ++ syn_mode &= ISPCCDC_SYN_MODE_INPMOD_MASK; ++ ispccdc_obj.syncif_ipmod = syncif.ipmod; ++ ++ switch (syncif.ipmod) { ++ case RAW: ++ break; ++ case YUV16: ++ syn_mode |= ISPCCDC_SYN_MODE_INPMOD_YCBCR16; ++ break; ++ case YUV8: ++ syn_mode |= ISPCCDC_SYN_MODE_INPMOD_YCBCR8; ++ break; ++ }; ++ ++ syn_mode &= ISPCCDC_SYN_MODE_DATSIZ_MASK; ++ switch (syncif.datsz) { ++ case DAT8: ++ syn_mode |= ISPCCDC_SYN_MODE_DATSIZ_8; ++ break; ++ case DAT10: ++ syn_mode |= ISPCCDC_SYN_MODE_DATSIZ_10; ++ break; ++ case DAT11: ++ syn_mode |= ISPCCDC_SYN_MODE_DATSIZ_11; ++ break; ++ case DAT12: ++ syn_mode |= ISPCCDC_SYN_MODE_DATSIZ_12; ++ break; ++ }; ++ ++ if (syncif.fldmode) ++ syn_mode |= ISPCCDC_SYN_MODE_FLDMODE; ++ else ++ syn_mode &= ~ISPCCDC_SYN_MODE_FLDMODE; ++ ++ if (syncif.datapol) ++ syn_mode |= ISPCCDC_SYN_MODE_DATAPOL; ++ else ++ syn_mode &= ~ISPCCDC_SYN_MODE_DATAPOL; ++ ++ if (syncif.fldpol) ++ syn_mode |= ISPCCDC_SYN_MODE_FLDPOL; ++ else ++ syn_mode &= ~ISPCCDC_SYN_MODE_FLDPOL; ++ ++ if (syncif.hdpol) ++ syn_mode |= ISPCCDC_SYN_MODE_HDPOL; ++ else ++ syn_mode &= ~ISPCCDC_SYN_MODE_HDPOL; ++ ++ if (syncif.vdpol) ++ syn_mode |= ISPCCDC_SYN_MODE_VDPOL; ++ else ++ syn_mode &= ~ISPCCDC_SYN_MODE_VDPOL; ++ ++ if (syncif.ccdc_mastermode) { ++ syn_mode |= ISPCCDC_SYN_MODE_FLDOUT | ISPCCDC_SYN_MODE_VDHDOUT; ++ isp_reg_writel(syncif.hs_width << ISPCCDC_HD_VD_WID_HDW_SHIFT ++ | syncif.vs_width << ISPCCDC_HD_VD_WID_VDW_SHIFT, ++ OMAP3_ISP_IOMEM_CCDC, ++ ISPCCDC_HD_VD_WID); ++ ++ isp_reg_writel(syncif.ppln << ISPCCDC_PIX_LINES_PPLN_SHIFT ++ | syncif.hlprf << ISPCCDC_PIX_LINES_HLPRF_SHIFT, ++ OMAP3_ISP_IOMEM_CCDC, ++ ISPCCDC_PIX_LINES); ++ } else ++ syn_mode &= ~(ISPCCDC_SYN_MODE_FLDOUT | ++ ISPCCDC_SYN_MODE_VDHDOUT); ++ ++ isp_reg_writel(syn_mode, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE); ++ ++ if (!(syncif.bt_r656_en)) { ++ isp_reg_and(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_REC656IF, ++ ~ISPCCDC_REC656IF_R656ON); ++ } ++} ++EXPORT_SYMBOL(ispccdc_config_sync_if); ++ ++/** ++ * ispccdc_config_black_clamp - Configures the clamp parameters in CCDC. ++ * @bclamp: Structure containing the optical black average gain, optical black ++ * sample length, sample lines, and the start pixel position of the ++ * samples w.r.t the HS pulse. ++ * Configures the clamp parameters in CCDC. Either if its being used the ++ * optical black clamp, or the digital clamp. If its a digital clamp, then ++ * assures to put a valid DC substraction level. ++ * ++ * Returns always 0 when completed. ++ **/ ++int ispccdc_config_black_clamp(struct ispccdc_bclamp bclamp) ++{ ++ u32 bclamp_val = 0; ++ ++ if (ispccdc_obj.obclamp_en) { ++ bclamp_val |= bclamp.obgain << ISPCCDC_CLAMP_OBGAIN_SHIFT; ++ bclamp_val |= bclamp.oblen << ISPCCDC_CLAMP_OBSLEN_SHIFT; ++ bclamp_val |= bclamp.oblines << ISPCCDC_CLAMP_OBSLN_SHIFT; ++ bclamp_val |= bclamp.obstpixel << ISPCCDC_CLAMP_OBST_SHIFT; ++ isp_reg_writel(bclamp_val, OMAP3_ISP_IOMEM_CCDC, ++ ISPCCDC_CLAMP); ++ } else { ++ if (omap_rev() < OMAP3430_REV_ES2_0) ++ if (ispccdc_obj.syncif_ipmod == YUV16 || ++ ispccdc_obj.syncif_ipmod == YUV8 || ++ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ++ ISPCCDC_REC656IF) & ++ ISPCCDC_REC656IF_R656ON) ++ bclamp.dcsubval = 0; ++ isp_reg_writel(bclamp.dcsubval, OMAP3_ISP_IOMEM_CCDC, ++ ISPCCDC_DCSUB); ++ } ++ return 0; ++} ++EXPORT_SYMBOL(ispccdc_config_black_clamp); ++ ++/** ++ * ispccdc_enable_black_clamp - Enables/Disables the optical black clamp. ++ * @enable: 0 Disables optical black clamp, 1 Enables optical black clamp. ++ * ++ * Enables or disables the optical black clamp. When disabled, the digital ++ * clamp operates. ++ **/ ++void ispccdc_enable_black_clamp(u8 enable) ++{ ++ isp_reg_and_or(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CLAMP, ++ ~ISPCCDC_CLAMP_CLAMPEN, ++ enable ? ISPCCDC_CLAMP_CLAMPEN : 0); ++ ispccdc_obj.obclamp_en = enable; ++} ++EXPORT_SYMBOL(ispccdc_enable_black_clamp); ++ ++/** ++ * ispccdc_config_fpc - Configures the Faulty Pixel Correction parameters. ++ * @fpc: Structure containing the number of faulty pixels corrected in the ++ * frame, address of the FPC table. ++ * ++ * Returns 0 if successful, or -EINVAL if FPC Address is not on the 64 byte ++ * boundary. ++ **/ ++int ispccdc_config_fpc(struct ispccdc_fpc fpc) ++{ ++ u32 fpc_val = 0; ++ ++ fpc_val = isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FPC); ++ ++ if ((fpc.fpcaddr & 0xFFFFFFC0) == fpc.fpcaddr) { ++ isp_reg_writel(fpc_val & (~ISPCCDC_FPC_FPCEN), ++ OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FPC); ++ isp_reg_writel(fpc.fpcaddr, ++ OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FPC_ADDR); ++ } else { ++ DPRINTK_ISPCCDC("FPC Address should be on 64byte boundary\n"); ++ return -EINVAL; ++ } ++ isp_reg_writel(fpc_val | (fpc.fpnum << ISPCCDC_FPC_FPNUM_SHIFT), ++ OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FPC); ++ return 0; ++} ++EXPORT_SYMBOL(ispccdc_config_fpc); ++ ++/** ++ * ispccdc_enable_fpc - Enables the Faulty Pixel Correction. ++ * @enable: 0 Disables FPC, 1 Enables FPC. ++ **/ ++void ispccdc_enable_fpc(u8 enable) ++{ ++ isp_reg_and_or(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FPC, ++ ~ISPCCDC_FPC_FPCEN, ++ enable ? ISPCCDC_FPC_FPCEN : 0); ++} ++EXPORT_SYMBOL(ispccdc_enable_fpc); ++ ++/** ++ * ispccdc_config_black_comp - Configures Black Level Compensation parameters. ++ * @blcomp: Structure containing the black level compensation value for RGrGbB ++ * pixels. in 2's complement. ++ **/ ++void ispccdc_config_black_comp(struct ispccdc_blcomp blcomp) ++{ ++ u32 blcomp_val = 0; ++ ++ blcomp_val |= blcomp.b_mg << ISPCCDC_BLKCMP_B_MG_SHIFT; ++ blcomp_val |= blcomp.gb_g << ISPCCDC_BLKCMP_GB_G_SHIFT; ++ blcomp_val |= blcomp.gr_cy << ISPCCDC_BLKCMP_GR_CY_SHIFT; ++ blcomp_val |= blcomp.r_ye << ISPCCDC_BLKCMP_R_YE_SHIFT; ++ ++ isp_reg_writel(blcomp_val, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_BLKCMP); ++} ++EXPORT_SYMBOL(ispccdc_config_black_comp); ++ ++/** ++ * ispccdc_config_vp - Configures the Video Port Configuration parameters. ++ * @vpcfg: Structure containing the Video Port input frequency, and the 10 bit ++ * format. ++ **/ ++void ispccdc_config_vp(struct ispccdc_vp vpcfg) ++{ ++ u32 fmtcfg_vp = isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG); ++ ++ fmtcfg_vp &= ISPCCDC_FMTCFG_VPIN_MASK & ISPCCDC_FMTCF_VPIF_FRQ_MASK; ++ ++ switch (vpcfg.bitshift_sel) { ++ case BIT9_0: ++ fmtcfg_vp |= ISPCCDC_FMTCFG_VPIN_9_0; ++ break; ++ case BIT10_1: ++ fmtcfg_vp |= ISPCCDC_FMTCFG_VPIN_10_1; ++ break; ++ case BIT11_2: ++ fmtcfg_vp |= ISPCCDC_FMTCFG_VPIN_11_2; ++ break; ++ case BIT12_3: ++ fmtcfg_vp |= ISPCCDC_FMTCFG_VPIN_12_3; ++ break; ++ }; ++ switch (vpcfg.freq_sel) { ++ case PIXCLKBY2: ++ fmtcfg_vp |= ISPCCDC_FMTCF_VPIF_FRQ_BY2; ++ break; ++ case PIXCLKBY3_5: ++ fmtcfg_vp |= ISPCCDC_FMTCF_VPIF_FRQ_BY3; ++ break; ++ case PIXCLKBY4_5: ++ fmtcfg_vp |= ISPCCDC_FMTCF_VPIF_FRQ_BY4; ++ break; ++ case PIXCLKBY5_5: ++ fmtcfg_vp |= ISPCCDC_FMTCF_VPIF_FRQ_BY5; ++ break; ++ case PIXCLKBY6_5: ++ fmtcfg_vp |= ISPCCDC_FMTCF_VPIF_FRQ_BY6; ++ break; ++ }; ++ isp_reg_writel(fmtcfg_vp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG); ++} ++EXPORT_SYMBOL(ispccdc_config_vp); ++ ++/** ++ * ispccdc_enable_vp - Enables the Video Port. ++ * @enable: 0 Disables VP, 1 Enables VP ++ **/ ++void ispccdc_enable_vp(u8 enable) ++{ ++ isp_reg_and_or(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG, ++ ~ISPCCDC_FMTCFG_VPEN, ++ enable ? ISPCCDC_FMTCFG_VPEN : 0); ++} ++EXPORT_SYMBOL(ispccdc_enable_vp); ++ ++/** ++ * ispccdc_config_reformatter - Configures the Reformatter. ++ * @refmt: Structure containing the memory address to format and the bit fields ++ * for the reformatter registers. ++ * ++ * Configures the Reformatter register values if line alternating is disabled. ++ * Else, just enabling line alternating is enough. ++ **/ ++void ispccdc_config_reformatter(struct ispccdc_refmt refmt) ++{ ++ u32 fmtcfg_val = 0; ++ ++ fmtcfg_val = isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG); ++ ++ if (refmt.lnalt) ++ fmtcfg_val |= ISPCCDC_FMTCFG_LNALT; ++ else { ++ fmtcfg_val &= ~ISPCCDC_FMTCFG_LNALT; ++ fmtcfg_val &= 0xFFFFF003; ++ fmtcfg_val |= refmt.lnum << ISPCCDC_FMTCFG_LNUM_SHIFT; ++ fmtcfg_val |= refmt.plen_even << ++ ISPCCDC_FMTCFG_PLEN_EVEN_SHIFT; ++ fmtcfg_val |= refmt.plen_odd << ISPCCDC_FMTCFG_PLEN_ODD_SHIFT; ++ ++ isp_reg_writel(refmt.prgeven0, OMAP3_ISP_IOMEM_CCDC, ++ ISPCCDC_PRGEVEN0); ++ isp_reg_writel(refmt.prgeven1, OMAP3_ISP_IOMEM_CCDC, ++ ISPCCDC_PRGEVEN1); ++ isp_reg_writel(refmt.prgodd0, OMAP3_ISP_IOMEM_CCDC, ++ ISPCCDC_PRGODD0); ++ isp_reg_writel(refmt.prgodd1, OMAP3_ISP_IOMEM_CCDC, ++ ISPCCDC_PRGODD1); ++ isp_reg_writel(refmt.fmtaddr0, OMAP3_ISP_IOMEM_CCDC, ++ ISPCCDC_FMT_ADDR0); ++ isp_reg_writel(refmt.fmtaddr1, OMAP3_ISP_IOMEM_CCDC, ++ ISPCCDC_FMT_ADDR1); ++ isp_reg_writel(refmt.fmtaddr2, OMAP3_ISP_IOMEM_CCDC, ++ ISPCCDC_FMT_ADDR2); ++ isp_reg_writel(refmt.fmtaddr3, OMAP3_ISP_IOMEM_CCDC, ++ ISPCCDC_FMT_ADDR3); ++ isp_reg_writel(refmt.fmtaddr4, OMAP3_ISP_IOMEM_CCDC, ++ ISPCCDC_FMT_ADDR4); ++ isp_reg_writel(refmt.fmtaddr5, OMAP3_ISP_IOMEM_CCDC, ++ ISPCCDC_FMT_ADDR5); ++ isp_reg_writel(refmt.fmtaddr6, OMAP3_ISP_IOMEM_CCDC, ++ ISPCCDC_FMT_ADDR6); ++ isp_reg_writel(refmt.fmtaddr7, OMAP3_ISP_IOMEM_CCDC, ++ ISPCCDC_FMT_ADDR7); ++ } ++ isp_reg_writel(fmtcfg_val, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG); ++} ++EXPORT_SYMBOL(ispccdc_config_reformatter); ++ ++/** ++ * ispccdc_enable_reformatter - Enables the Reformatter. ++ * @enable: 0 Disables Reformatter, 1- Enables Data Reformatter ++ **/ ++void ispccdc_enable_reformatter(u8 enable) ++{ ++ isp_reg_and_or(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG, ++ ~ISPCCDC_FMTCFG_FMTEN, ++ enable ? ISPCCDC_FMTCFG_FMTEN : 0); ++ ispccdc_obj.refmt_en = enable; ++} ++EXPORT_SYMBOL(ispccdc_enable_reformatter); ++ ++/** ++ * ispccdc_config_culling - Configures the culling parameters. ++ * @cull: Structure containing the vertical culling pattern, and horizontal ++ * culling pattern for odd and even lines. ++ **/ ++void ispccdc_config_culling(struct ispccdc_culling cull) ++{ ++ u32 culling_val = 0; ++ ++ culling_val |= cull.v_pattern << ISPCCDC_CULLING_CULV_SHIFT; ++ culling_val |= cull.h_even << ISPCCDC_CULLING_CULHEVN_SHIFT; ++ culling_val |= cull.h_odd << ISPCCDC_CULLING_CULHODD_SHIFT; ++ ++ isp_reg_writel(culling_val, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CULLING); ++} ++EXPORT_SYMBOL(ispccdc_config_culling); ++ ++/** ++ * ispccdc_enable_lpf - Enables the Low-Pass Filter (LPF). ++ * @enable: 0 Disables LPF, 1 Enables LPF ++ **/ ++void ispccdc_enable_lpf(u8 enable) ++{ ++ isp_reg_and_or(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE, ++ ~ISPCCDC_SYN_MODE_LPF, ++ enable ? ISPCCDC_SYN_MODE_LPF : 0); ++} ++EXPORT_SYMBOL(ispccdc_enable_lpf); ++ ++/** ++ * ispccdc_config_alaw - Configures the input width for A-law. ++ * @ipwidth: Input width for A-law ++ **/ ++void ispccdc_config_alaw(enum alaw_ipwidth ipwidth) ++{ ++ isp_reg_writel(ipwidth << ISPCCDC_ALAW_GWDI_SHIFT, ++ OMAP3_ISP_IOMEM_CCDC, ISPCCDC_ALAW); ++} ++EXPORT_SYMBOL(ispccdc_config_alaw); ++ ++/** ++ * ispccdc_enable_alaw - Enables the A-law compression. ++ * @enable: 0 - Disables A-law, 1 - Enables A-law ++ **/ ++void ispccdc_enable_alaw(u8 enable) ++{ ++ isp_reg_and_or(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_ALAW, ++ ~ISPCCDC_ALAW_CCDTBL, ++ enable ? ISPCCDC_ALAW_CCDTBL : 0); ++} ++EXPORT_SYMBOL(ispccdc_enable_alaw); ++ ++/** ++ * ispccdc_config_imgattr - Configures the sensor image specific attributes. ++ * @colptn: Color pattern of the sensor. ++ **/ ++void ispccdc_config_imgattr(u32 colptn) ++{ ++ isp_reg_writel(colptn, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_COLPTN); ++} ++EXPORT_SYMBOL(ispccdc_config_imgattr); ++ ++void ispccdc_config_shadow_registers(void) ++{ ++ if (ispccdc_obj.lsc_enable) { ++ ispccdc_enable_lsc(1); ++ ispccdc_obj.lsc_enable = 0; ++ } ++} ++ ++/** ++ * ispccdc_try_size - Checks if requested Input/output dimensions are valid ++ * @input_w: input width for the CCDC in number of pixels per line ++ * @input_h: input height for the CCDC in number of lines ++ * @output_w: output width from the CCDC in number of pixels per line ++ * @output_h: output height for the CCDC in number of lines ++ * ++ * Calculates the number of pixels cropped if the reformater is disabled, ++ * Fills up the output width and height variables in the isp_ccdc structure. ++ * ++ * Returns 0 if successful, or -EINVAL if the input width is less than 2 pixels ++ **/ ++int ispccdc_try_size(u32 input_w, u32 input_h, u32 *output_w, u32 *output_h) ++{ ++ if (input_w < 32 || input_h < 32) { ++ DPRINTK_ISPCCDC("ISP_ERR: CCDC cannot handle input width less" ++ " than 32 pixels or height less than 32\n"); ++ return -EINVAL; ++ } ++ ++ if (ispccdc_obj.crop_w) ++ *output_w = ispccdc_obj.crop_w; ++ else ++ *output_w = input_w; ++ ++ if (ispccdc_obj.crop_h) ++ *output_h = ispccdc_obj.crop_h; ++ else ++ *output_h = input_h; ++ ++ if (!ispccdc_obj.refmt_en ++ && ispccdc_obj.ccdc_outfmt != CCDC_OTHERS_MEM ++ && ispccdc_obj.ccdc_outfmt != CCDC_OTHERS_VP_MEM) ++ *output_h -= 1; ++ ++ if (ispccdc_obj.ccdc_outfmt == CCDC_OTHERS_MEM ++ || ispccdc_obj.ccdc_outfmt == CCDC_OTHERS_VP_MEM) { ++ if (*output_w % 16) { ++ *output_w -= (*output_w % 16); ++ *output_w += 16; ++ } ++ } ++ ++ ispccdc_obj.ccdcout_w = *output_w; ++ ispccdc_obj.ccdcout_h = *output_h; ++ ispccdc_obj.ccdcin_w = input_w; ++ ispccdc_obj.ccdcin_h = input_h; ++ ++ DPRINTK_ISPCCDC("try size: ccdcin_w=%u,ccdcin_h=%u,ccdcout_w=%u," ++ " ccdcout_h=%u\n", ++ ispccdc_obj.ccdcin_w, ++ ispccdc_obj.ccdcin_h, ++ ispccdc_obj.ccdcout_w, ++ ispccdc_obj.ccdcout_h); ++ ++ return 0; ++} ++EXPORT_SYMBOL(ispccdc_try_size); ++ ++/** ++ * ispccdc_config_size - Configure the dimensions of the CCDC input/output ++ * @input_w: input width for the CCDC in number of pixels per line ++ * @input_h: input height for the CCDC in number of lines ++ * @output_w: output width from the CCDC in number of pixels per line ++ * @output_h: output height for the CCDC in number of lines ++ * ++ * Configures the appropriate values stored in the isp_ccdc structure to ++ * HORZ/VERT_INFO registers and the VP_OUT depending on whether the image ++ * is stored in memory or given to the another module in the ISP pipeline. ++ * ++ * Returns 0 if successful, or -EINVAL if try_size was not called before to ++ * validate the requested dimensions. ++ **/ ++int ispccdc_config_size(u32 input_w, u32 input_h, u32 output_w, u32 output_h) ++{ ++ DPRINTK_ISPCCDC("config size: input_w=%u, input_h=%u, output_w=%u," ++ " output_h=%u\n", ++ input_w, input_h, ++ output_w, output_h); ++ if (output_w != ispccdc_obj.ccdcout_w ++ || output_h != ispccdc_obj.ccdcout_h) { ++ DPRINTK_ISPCCDC("ISP_ERR : ispccdc_try_size should" ++ " be called before config size\n"); ++ return -EINVAL; ++ } ++ ++ if (ispccdc_obj.ccdc_outfmt == CCDC_OTHERS_VP) { ++ isp_reg_writel((ispccdc_obj.ccdcin_woffset << ++ ISPCCDC_FMT_HORZ_FMTSPH_SHIFT) | ++ (ispccdc_obj.ccdcin_w << ++ ISPCCDC_FMT_HORZ_FMTLNH_SHIFT), ++ OMAP3_ISP_IOMEM_CCDC, ++ ISPCCDC_FMT_HORZ); ++ isp_reg_writel((ispccdc_obj.ccdcin_hoffset << ++ ISPCCDC_FMT_VERT_FMTSLV_SHIFT) | ++ (ispccdc_obj.ccdcin_h << ++ ISPCCDC_FMT_VERT_FMTLNV_SHIFT), ++ OMAP3_ISP_IOMEM_CCDC, ++ ISPCCDC_FMT_VERT); ++ isp_reg_writel((ispccdc_obj.ccdcout_w << ++ ISPCCDC_VP_OUT_HORZ_NUM_SHIFT) | ++ (ispccdc_obj.ccdcout_h - 1) << ++ ISPCCDC_VP_OUT_VERT_NUM_SHIFT, ++ OMAP3_ISP_IOMEM_CCDC, ++ ISPCCDC_VP_OUT); ++ isp_reg_writel((((ispccdc_obj.ccdcout_h - 25) & ++ ISPCCDC_VDINT_0_MASK) << ++ ISPCCDC_VDINT_0_SHIFT) | ++ ((50 & ISPCCDC_VDINT_1_MASK) << ++ ISPCCDC_VDINT_1_SHIFT), ++ OMAP3_ISP_IOMEM_CCDC, ++ ISPCCDC_VDINT); ++ ++ } else if (ispccdc_obj.ccdc_outfmt == CCDC_OTHERS_MEM) { ++ isp_reg_writel(0, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_VP_OUT); ++ if (ispccdc_obj.ccdc_inpfmt == CCDC_RAW) { ++ isp_reg_writel(0 << ISPCCDC_HORZ_INFO_SPH_SHIFT ++ | ((ispccdc_obj.ccdcout_w - 1) ++ << ISPCCDC_HORZ_INFO_NPH_SHIFT), ++ OMAP3_ISP_IOMEM_CCDC, ++ ISPCCDC_HORZ_INFO); ++ } else { ++ isp_reg_writel(0 << ISPCCDC_HORZ_INFO_SPH_SHIFT ++ | ((ispccdc_obj.ccdcout_w - 1) ++ << ISPCCDC_HORZ_INFO_NPH_SHIFT), ++ OMAP3_ISP_IOMEM_CCDC, ++ ISPCCDC_HORZ_INFO); ++ } ++ isp_reg_writel(0 << ISPCCDC_VERT_START_SLV0_SHIFT, ++ OMAP3_ISP_IOMEM_CCDC, ++ ISPCCDC_VERT_START); ++ isp_reg_writel((ispccdc_obj.ccdcout_h - 1) << ++ ISPCCDC_VERT_LINES_NLV_SHIFT, ++ OMAP3_ISP_IOMEM_CCDC, ++ ISPCCDC_VERT_LINES); ++ ++ ispccdc_config_outlineoffset(ispccdc_obj.ccdcout_w * 2, 0, 0); ++ isp_reg_writel((((ispccdc_obj.ccdcout_h - 2) & ++ ISPCCDC_VDINT_0_MASK) << ++ ISPCCDC_VDINT_0_SHIFT) | ++ ((100 & ISPCCDC_VDINT_1_MASK) << ++ ISPCCDC_VDINT_1_SHIFT), ++ OMAP3_ISP_IOMEM_CCDC, ++ ISPCCDC_VDINT); ++ } else if (ispccdc_obj.ccdc_outfmt == CCDC_OTHERS_VP_MEM) { ++ isp_reg_writel((0 << ISPCCDC_FMT_HORZ_FMTSPH_SHIFT) | ++ (ispccdc_obj.ccdcin_w << ++ ISPCCDC_FMT_HORZ_FMTLNH_SHIFT), ++ OMAP3_ISP_IOMEM_CCDC, ++ ISPCCDC_FMT_HORZ); ++ isp_reg_writel((0 << ISPCCDC_FMT_VERT_FMTSLV_SHIFT) | ++ ((ispccdc_obj.ccdcin_h) << ++ ISPCCDC_FMT_VERT_FMTLNV_SHIFT), ++ OMAP3_ISP_IOMEM_CCDC, ++ ISPCCDC_FMT_VERT); ++ isp_reg_writel((ispccdc_obj.ccdcout_w ++ << ISPCCDC_VP_OUT_HORZ_NUM_SHIFT) | ++ ((ispccdc_obj.ccdcout_h - 1) << ++ ISPCCDC_VP_OUT_VERT_NUM_SHIFT), ++ OMAP3_ISP_IOMEM_CCDC, ++ ISPCCDC_VP_OUT); ++ isp_reg_writel(0 << ISPCCDC_HORZ_INFO_SPH_SHIFT | ++ ((ispccdc_obj.ccdcout_w - 1) << ++ ISPCCDC_HORZ_INFO_NPH_SHIFT), ++ OMAP3_ISP_IOMEM_CCDC, ++ ISPCCDC_HORZ_INFO); ++ isp_reg_writel(0 << ISPCCDC_VERT_START_SLV0_SHIFT, ++ OMAP3_ISP_IOMEM_CCDC, ++ ISPCCDC_VERT_START); ++ isp_reg_writel((ispccdc_obj.ccdcout_h - 1) << ++ ISPCCDC_VERT_LINES_NLV_SHIFT, ++ OMAP3_ISP_IOMEM_CCDC, ++ ISPCCDC_VERT_LINES); ++ ispccdc_config_outlineoffset(ispccdc_obj.ccdcout_w * 2, 0, 0); ++ isp_reg_writel((((ispccdc_obj.ccdcout_h - 2) & ++ ISPCCDC_VDINT_0_MASK) << ++ ISPCCDC_VDINT_0_SHIFT) | ++ ((100 & ISPCCDC_VDINT_1_MASK) << ++ ISPCCDC_VDINT_1_SHIFT), ++ OMAP3_ISP_IOMEM_CCDC, ++ ISPCCDC_VDINT); ++ } ++ ++ if (is_isplsc_activated()) { ++ if (ispccdc_obj.ccdc_inpfmt == CCDC_RAW) { ++ ispccdc_config_lsc(&lsc_config); ++ ispccdc_load_lsc(lsc_gain_table, lsc_config.size); ++ } ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL(ispccdc_config_size); ++ ++/** ++ * ispccdc_config_outlineoffset - Configures the output line offset ++ * @offset: Must be twice the Output width and aligned on 32 byte boundary ++ * @oddeven: Specifies the odd/even line pattern to be chosen to store the ++ * output. ++ * @numlines: Set the value 0-3 for +1-4lines, 4-7 for -1-4lines. ++ * ++ * - Configures the output line offset when stored in memory ++ * - Sets the odd/even line pattern to store the output ++ * (EVENEVEN (1), ODDEVEN (2), EVENODD (3), ODDODD (4)) ++ * - Configures the number of even and odd line fields in case of rearranging ++ * the lines. ++ * ++ * Returns 0 if successful, or -EINVAL if the offset is not in 32 byte ++ * boundary. ++ **/ ++int ispccdc_config_outlineoffset(u32 offset, u8 oddeven, u8 numlines) ++{ ++ if ((offset & ISP_32B_BOUNDARY_OFFSET) == offset) { ++ isp_reg_writel((offset & 0xFFFF), OMAP3_ISP_IOMEM_CCDC, ++ ISPCCDC_HSIZE_OFF); ++ } else { ++ DPRINTK_ISPCCDC("ISP_ERR : Offset should be in 32 byte" ++ " boundary\n"); ++ return -EINVAL; ++ } ++ ++ isp_reg_and(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST, ++ ~ISPCCDC_SDOFST_FINV); ++ ++ isp_reg_and(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST, ++ ~ISPCCDC_SDOFST_FOFST_4L); ++ ++ switch (oddeven) { ++ case EVENEVEN: ++ isp_reg_or(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST, ++ (numlines & 0x7) << ISPCCDC_SDOFST_LOFST0_SHIFT); ++ break; ++ case ODDEVEN: ++ isp_reg_or(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST, ++ (numlines & 0x7) << ISPCCDC_SDOFST_LOFST1_SHIFT); ++ break; ++ case EVENODD: ++ isp_reg_or(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST, ++ (numlines & 0x7) << ISPCCDC_SDOFST_LOFST2_SHIFT); ++ break; ++ case ODDODD: ++ isp_reg_or(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST, ++ (numlines & 0x7) << ISPCCDC_SDOFST_LOFST3_SHIFT); ++ break; ++ default: ++ break; ++ } ++ return 0; ++} ++EXPORT_SYMBOL(ispccdc_config_outlineoffset); ++ ++/** ++ * ispccdc_set_outaddr - Sets the memory address where the output will be saved ++ * @addr: 32-bit memory address aligned on 32 byte boundary. ++ * ++ * Sets the memory address where the output will be saved. ++ * ++ * Returns 0 if successful, or -EINVAL if the address is not in the 32 byte ++ * boundary. ++ **/ ++int ispccdc_set_outaddr(u32 addr) ++{ ++ if ((addr & ISP_32B_BOUNDARY_BUF) == addr) { ++ isp_reg_writel(addr, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDR_ADDR); ++ return 0; ++ } else { ++ DPRINTK_ISPCCDC("ISP_ERR : Address should be in 32 byte" ++ " boundary\n"); ++ return -EINVAL; ++ } ++ ++} ++EXPORT_SYMBOL(ispccdc_set_outaddr); ++ ++void __ispccdc_enable(u8 enable) ++{ ++ if (enable) { ++ if (ispccdc_obj.lsc_enable ++ && ispccdc_obj.ccdc_inpfmt == CCDC_RAW) ++ ispccdc_enable_lsc(1); ++ ++ } else { ++ ispccdc_obj.lsc_enable = ispccdc_obj.lsc_state; ++ } ++ ++ isp_reg_and_or(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_PCR, ~ISPCCDC_PCR_EN, ++ enable ? ISPCCDC_PCR_EN : 0); ++} ++ ++/** ++ * ispccdc_enable - Enables the CCDC module. ++ * @enable: 0 Disables CCDC, 1 Enables CCDC ++ * ++ * Client should configure all the sub modules in CCDC before this. ++ **/ ++void ispccdc_enable(u8 enable) ++{ ++ __ispccdc_enable(enable); ++ ispccdc_obj.pm_state = enable; ++} ++EXPORT_SYMBOL(ispccdc_enable); ++ ++/** ++ * ispccdc_suspend - Suspend the CCDC module. ++ **/ ++void ispccdc_suspend(void) ++{ ++ if (ispccdc_obj.pm_state) { ++ if (ispccdc_obj.lsc_state) ++ __ispccdc_enable_lsc(0); ++ else if (ispccdc_obj.lsc_enable) { ++ ispccdc_obj.lsc_state = 1; ++ ispccdc_obj.lsc_enable = 0; ++ } ++ __ispccdc_enable(0); ++ } ++} ++EXPORT_SYMBOL(ispccdc_suspend); ++ ++/** ++ * ispccdc_resume - Resume the CCDC module. ++ **/ ++void ispccdc_resume(void) ++{ ++ if (ispccdc_obj.pm_state) { ++ if (ispccdc_obj.lsc_state) ++ __ispccdc_enable_lsc(1); ++ __ispccdc_enable(1); ++ } ++} ++EXPORT_SYMBOL(ispccdc_resume); ++ ++/* ++ * Returns zero if the CCDC is idle and the image has been written to ++ * memory, too. ++ */ ++int ispccdc_sbl_busy(void) ++{ ++ return ispccdc_busy() ++ | (isp_reg_readl(OMAP3_ISP_IOMEM_SBL, ISPSBL_CCDC_WR_0) & ++ ISPSBL_CCDC_WR_0_DATA_READY) ++ | (isp_reg_readl(OMAP3_ISP_IOMEM_SBL, ISPSBL_CCDC_WR_1) & ++ ISPSBL_CCDC_WR_0_DATA_READY) ++ | (isp_reg_readl(OMAP3_ISP_IOMEM_SBL, ISPSBL_CCDC_WR_2) & ++ ISPSBL_CCDC_WR_0_DATA_READY) ++ | (isp_reg_readl(OMAP3_ISP_IOMEM_SBL, ISPSBL_CCDC_WR_3) & ++ ISPSBL_CCDC_WR_0_DATA_READY); ++} ++EXPORT_SYMBOL(ispccdc_sbl_busy); ++ ++/** ++ * ispccdc_busy - Gets busy state of the CCDC. ++ **/ ++int ispccdc_busy(void) ++{ ++ return isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_PCR) & ++ ISPCCDC_PCR_BUSY; ++} ++EXPORT_SYMBOL(ispccdc_busy); ++ ++/** ++ * ispccdc_save_context - Saves the values of the CCDC module registers ++ **/ ++void ispccdc_save_context(void) ++{ ++ DPRINTK_ISPCCDC("Saving context\n"); ++ isp_save_context(ispccdc_reg_list); ++} ++EXPORT_SYMBOL(ispccdc_save_context); ++ ++/** ++ * ispccdc_restore_context - Restores the values of the CCDC module registers ++ **/ ++void ispccdc_restore_context(void) ++{ ++ DPRINTK_ISPCCDC("Restoring context\n"); ++ isp_restore_context(ispccdc_reg_list); ++} ++EXPORT_SYMBOL(ispccdc_restore_context); ++ ++/** ++ * ispccdc_print_status - Prints the values of the CCDC Module registers ++ * ++ * Also prints other debug information stored in the CCDC module. ++ **/ ++void ispccdc_print_status(void) ++{ ++ if (!is_ispccdc_debug_enabled()) ++ return; ++ ++ DPRINTK_ISPCCDC("Module in use =%d\n", ispccdc_obj.ccdc_inuse); ++ DPRINTK_ISPCCDC("Accepted CCDC Input (width = %d,Height = %d)\n", ++ ispccdc_obj.ccdcin_w, ++ ispccdc_obj.ccdcin_h); ++ DPRINTK_ISPCCDC("Accepted CCDC Output (width = %d,Height = %d)\n", ++ ispccdc_obj.ccdcout_w, ++ ispccdc_obj.ccdcout_h); ++ DPRINTK_ISPCCDC("###CCDC PCR=0x%x\n", ++ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_PCR)); ++ DPRINTK_ISPCCDC("ISP_CTRL =0x%x\n", ++ isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_CTRL)); ++ switch (ispccdc_obj.ccdc_inpfmt) { ++ case CCDC_RAW: ++ DPRINTK_ISPCCDC("ccdc input format is CCDC_RAW\n"); ++ break; ++ case CCDC_YUV_SYNC: ++ DPRINTK_ISPCCDC("ccdc input format is CCDC_YUV_SYNC\n"); ++ break; ++ case CCDC_YUV_BT: ++ DPRINTK_ISPCCDC("ccdc input format is CCDC_YUV_BT\n"); ++ break; ++ } ++ ++ switch (ispccdc_obj.ccdc_outfmt) { ++ case CCDC_OTHERS_VP: ++ DPRINTK_ISPCCDC("ccdc output format is CCDC_OTHERS_VP\n"); ++ break; ++ case CCDC_OTHERS_MEM: ++ DPRINTK_ISPCCDC("ccdc output format is CCDC_OTHERS_MEM\n"); ++ break; ++ case CCDC_YUV_RSZ: ++ DPRINTK_ISPCCDC("ccdc output format is CCDC_YUV_RSZ\n"); ++ break; ++ } ++ ++ DPRINTK_ISPCCDC("###ISP_CTRL in ccdc =0x%x\n", ++ isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_CTRL)); ++ DPRINTK_ISPCCDC("###ISP_IRQ0ENABLE in ccdc =0x%x\n", ++ isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE)); ++ DPRINTK_ISPCCDC("###ISP_IRQ0STATUS in ccdc =0x%x\n", ++ isp_reg_readl(OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS)); ++ DPRINTK_ISPCCDC("###CCDC SYN_MODE=0x%x\n", ++ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE)); ++ DPRINTK_ISPCCDC("###CCDC HORZ_INFO=0x%x\n", ++ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_HORZ_INFO)); ++ DPRINTK_ISPCCDC("###CCDC VERT_START=0x%x\n", ++ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ++ ISPCCDC_VERT_START)); ++ DPRINTK_ISPCCDC("###CCDC VERT_LINES=0x%x\n", ++ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ++ ISPCCDC_VERT_LINES)); ++ DPRINTK_ISPCCDC("###CCDC CULLING=0x%x\n", ++ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CULLING)); ++ DPRINTK_ISPCCDC("###CCDC HSIZE_OFF=0x%x\n", ++ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_HSIZE_OFF)); ++ DPRINTK_ISPCCDC("###CCDC SDOFST=0x%x\n", ++ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST)); ++ DPRINTK_ISPCCDC("###CCDC SDR_ADDR=0x%x\n", ++ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDR_ADDR)); ++ DPRINTK_ISPCCDC("###CCDC CLAMP=0x%x\n", ++ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CLAMP)); ++ DPRINTK_ISPCCDC("###CCDC COLPTN=0x%x\n", ++ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_COLPTN)); ++ DPRINTK_ISPCCDC("###CCDC CFG=0x%x\n", ++ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CFG)); ++ DPRINTK_ISPCCDC("###CCDC VP_OUT=0x%x\n", ++ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_VP_OUT)); ++ DPRINTK_ISPCCDC("###CCDC_SDR_ADDR= 0x%x\n", ++ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDR_ADDR)); ++ DPRINTK_ISPCCDC("###CCDC FMTCFG=0x%x\n", ++ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG)); ++ DPRINTK_ISPCCDC("###CCDC FMT_HORZ=0x%x\n", ++ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_HORZ)); ++ DPRINTK_ISPCCDC("###CCDC FMT_VERT=0x%x\n", ++ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_VERT)); ++ DPRINTK_ISPCCDC("###CCDC LSC_CONFIG=0x%x\n", ++ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ++ ISPCCDC_LSC_CONFIG)); ++ DPRINTK_ISPCCDC("###CCDC LSC_INIT=0x%x\n", ++ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ++ ISPCCDC_LSC_INITIAL)); ++ DPRINTK_ISPCCDC("###CCDC LSC_TABLE BASE=0x%x\n", ++ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ++ ISPCCDC_LSC_TABLE_BASE)); ++ DPRINTK_ISPCCDC("###CCDC LSC TABLE OFFSET=0x%x\n", ++ isp_reg_readl(OMAP3_ISP_IOMEM_CCDC, ++ ISPCCDC_LSC_TABLE_OFFSET)); ++} ++EXPORT_SYMBOL(ispccdc_print_status); ++ ++/** ++ * isp_ccdc_init - CCDC module initialization. ++ * ++ * Always returns 0 ++ **/ ++int __init isp_ccdc_init(void) ++{ ++ ispccdc_obj.ccdc_inuse = 0; ++ ispccdc_config_crop(0, 0, 0, 0); ++ mutex_init(&ispccdc_obj.mutexlock); ++ ++ if (is_isplsc_activated()) { ++ lsc_gain_table_tmp = kmalloc(LSC_TABLE_INIT_SIZE, GFP_KERNEL | ++ GFP_DMA); ++ memset(lsc_gain_table_tmp, 0x40, LSC_TABLE_INIT_SIZE); ++ lsc_config.initial_x = 0; ++ lsc_config.initial_y = 0; ++ lsc_config.gain_mode_n = 0x6; ++ lsc_config.gain_mode_m = 0x6; ++ lsc_config.gain_format = 0x4; ++ lsc_config.offset = 0x60; ++ lsc_config.size = LSC_TABLE_INIT_SIZE; ++ ispccdc_obj.lsc_enable = 1; ++ } ++ ++ return 0; ++} ++ ++/** ++ * isp_ccdc_cleanup - CCDC module cleanup. ++ **/ ++void isp_ccdc_cleanup(void) ++{ ++ if (is_isplsc_activated()) { ++ ispccdc_free_lsc(); ++ kfree(lsc_gain_table_tmp); ++ } ++ ++ if (fpc_table_add_m != 0) { ++ ispmmu_kunmap(fpc_table_add_m); ++ kfree(fpc_table_add); ++ } ++} +diff --git a/drivers/media/video/isp/ispccdc.h b/drivers/media/video/isp/ispccdc.h +new file mode 100644 +index 0000000..4ef40a6 +--- /dev/null ++++ b/drivers/media/video/isp/ispccdc.h +@@ -0,0 +1,209 @@ ++/* ++ * ispccdc.h ++ * ++ * Driver header file for CCDC module in TI's OMAP3 Camera ISP ++ * ++ * Copyright (C) 2009 Texas Instruments, Inc. ++ * ++ * Contributors: ++ * Senthilvadivu Guruswamy <svadivu@ti.com> ++ * Pallavi Kulkarni <p-kulkarni@ti.com> ++ * Sergio Aguirre <saaguirre@ti.com> ++ * ++ * This package is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR ++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED ++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. ++ */ ++ ++#ifndef OMAP_ISP_CCDC_H ++#define OMAP_ISP_CCDC_H ++ ++#include <mach/isp_user.h> ++ ++#define is_isplsc_activated() 1 ++ ++/* Enumeration constants for CCDC input output format */ ++enum ccdc_input { ++ CCDC_RAW, ++ CCDC_YUV_SYNC, ++ CCDC_YUV_BT, ++ CCDC_OTHERS ++}; ++ ++enum ccdc_output { ++ CCDC_YUV_RSZ, ++ CCDC_YUV_MEM_RSZ, ++ CCDC_OTHERS_VP, ++ CCDC_OTHERS_MEM, ++ CCDC_OTHERS_VP_MEM ++}; ++ ++/* Enumeration constants for the sync interface parameters */ ++enum inpmode { ++ RAW, ++ YUV16, ++ YUV8 ++}; ++enum datasize { ++ DAT8, ++ DAT10, ++ DAT11, ++ DAT12 ++}; ++ ++ ++/** ++ * struct ispccdc_syncif - Structure for Sync Interface between sensor and CCDC ++ * @ccdc_mastermode: Master mode. 1 - Master, 0 - Slave. ++ * @fldstat: Field state. 0 - Odd Field, 1 - Even Field. ++ * @ipmod: Input mode. ++ * @datsz: Data size. ++ * @fldmode: 0 - Progressive, 1 - Interlaced. ++ * @datapol: 0 - Positive, 1 - Negative. ++ * @fldpol: 0 - Positive, 1 - Negative. ++ * @hdpol: 0 - Positive, 1 - Negative. ++ * @vdpol: 0 - Positive, 1 - Negative. ++ * @fldout: 0 - Input, 1 - Output. ++ * @hs_width: Width of the Horizontal Sync pulse, used for HS/VS Output. ++ * @vs_width: Width of the Vertical Sync pulse, used for HS/VS Output. ++ * @ppln: Number of pixels per line, used for HS/VS Output. ++ * @hlprf: Number of half lines per frame, used for HS/VS Output. ++ * @bt_r656_en: 1 - Enable ITU-R BT656 mode, 0 - Sync mode. ++ */ ++struct ispccdc_syncif { ++ u8 ccdc_mastermode; ++ u8 fldstat; ++ enum inpmode ipmod; ++ enum datasize datsz; ++ u8 fldmode; ++ u8 datapol; ++ u8 fldpol; ++ u8 hdpol; ++ u8 vdpol; ++ u8 fldout; ++ u8 hs_width; ++ u8 vs_width; ++ u8 ppln; ++ u8 hlprf; ++ u8 bt_r656_en; ++}; ++ ++/** ++ * ispccdc_refmt - Structure for Reformatter parameters ++ * @lnalt: Line alternating mode enable. 0 - Enable, 1 - Disable. ++ * @lnum: Number of output lines from 1 input line. 1 to 4 lines. ++ * @plen_even: Number of program entries in even line minus 1. ++ * @plen_odd: Number of program entries in odd line minus 1. ++ * @prgeven0: Program entries 0-7 for even lines register ++ * @prgeven1: Program entries 8-15 for even lines register ++ * @prgodd0: Program entries 0-7 for odd lines register ++ * @prgodd1: Program entries 8-15 for odd lines register ++ * @fmtaddr0: Output line in which the original pixel is to be placed ++ * @fmtaddr1: Output line in which the original pixel is to be placed ++ * @fmtaddr2: Output line in which the original pixel is to be placed ++ * @fmtaddr3: Output line in which the original pixel is to be placed ++ * @fmtaddr4: Output line in which the original pixel is to be placed ++ * @fmtaddr5: Output line in which the original pixel is to be placed ++ * @fmtaddr6: Output line in which the original pixel is to be placed ++ * @fmtaddr7: Output line in which the original pixel is to be placed ++ */ ++struct ispccdc_refmt { ++ u8 lnalt; ++ u8 lnum; ++ u8 plen_even; ++ u8 plen_odd; ++ u32 prgeven0; ++ u32 prgeven1; ++ u32 prgodd0; ++ u32 prgodd1; ++ u32 fmtaddr0; ++ u32 fmtaddr1; ++ u32 fmtaddr2; ++ u32 fmtaddr3; ++ u32 fmtaddr4; ++ u32 fmtaddr5; ++ u32 fmtaddr6; ++ u32 fmtaddr7; ++}; ++ ++int ispccdc_request(void); ++ ++int ispccdc_free(void); ++ ++int ispccdc_config_datapath(enum ccdc_input input, enum ccdc_output output); ++ ++void ispccdc_config_crop(u32 left, u32 top, u32 height, u32 width); ++ ++void ispccdc_config_sync_if(struct ispccdc_syncif syncif); ++ ++int ispccdc_config_black_clamp(struct ispccdc_bclamp bclamp); ++ ++void ispccdc_enable_black_clamp(u8 enable); ++ ++int ispccdc_config_fpc(struct ispccdc_fpc fpc); ++ ++void ispccdc_enable_fpc(u8 enable); ++ ++void ispccdc_config_black_comp(struct ispccdc_blcomp blcomp); ++ ++void ispccdc_config_vp(struct ispccdc_vp vp); ++ ++void ispccdc_enable_vp(u8 enable); ++ ++void ispccdc_config_reformatter(struct ispccdc_refmt refmt); ++ ++void ispccdc_enable_reformatter(u8 enable); ++ ++void ispccdc_config_culling(struct ispccdc_culling culling); ++ ++void ispccdc_enable_lpf(u8 enable); ++ ++void ispccdc_config_alaw(enum alaw_ipwidth ipwidth); ++ ++void ispccdc_enable_alaw(u8 enable); ++ ++int ispccdc_load_lsc(u8 *table_addr, u32 table_size); ++ ++void ispccdc_config_lsc(struct ispccdc_lsc_config *lsc_cfg); ++ ++void ispccdc_enable_lsc(u8 enable); ++ ++void ispccdc_lsc_error_handler(void); ++ ++void ispccdc_config_imgattr(u32 colptn); ++ ++void ispccdc_config_shadow_registers(void); ++ ++int ispccdc_try_size(u32 input_w, u32 input_h, u32 *output_w, u32 *output_h); ++ ++int ispccdc_config_size(u32 input_w, u32 input_h, u32 output_w, u32 output_h); ++ ++int ispccdc_config_outlineoffset(u32 offset, u8 oddeven, u8 numlines); ++ ++int ispccdc_set_outaddr(u32 addr); ++ ++void ispccdc_enable(u8 enable); ++ ++void ispccdc_suspend(void); ++ ++void ispccdc_resume(void); ++ ++int ispccdc_sbl_busy(void); ++ ++int ispccdc_busy(void); ++ ++void ispccdc_save_context(void); ++ ++void ispccdc_restore_context(void); ++ ++void ispccdc_print_status(void); ++ ++int omap34xx_isp_ccdc_config(void *userspace_add); ++ ++void ispccdc_set_wenlog(u32 wenlog); ++ ++#endif /* OMAP_ISP_CCDC_H */ +-- +1.5.6.5 + |