From patchwork Thu Jun 30 13:13:11 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Manjunath Hadli X-Patchwork-Id: 932762 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.4) with ESMTP id p5UDDiZg029769 for ; Thu, 30 Jun 2011 13:13:45 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753712Ab1F3NNn (ORCPT ); Thu, 30 Jun 2011 09:13:43 -0400 Received: from arroyo.ext.ti.com ([192.94.94.40]:39095 "EHLO arroyo.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753652Ab1F3NNb (ORCPT ); Thu, 30 Jun 2011 09:13:31 -0400 Received: from dbdp20.itg.ti.com ([172.24.170.38]) by arroyo.ext.ti.com (8.13.7/8.13.7) with ESMTP id p5UDDQI9006610 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Thu, 30 Jun 2011 08:13:28 -0500 Received: from dbde71.ent.ti.com (localhost [127.0.0.1]) by dbdp20.itg.ti.com (8.13.8/8.13.8) with ESMTP id p5UDDMlN005296; Thu, 30 Jun 2011 18:43:22 +0530 (IST) Received: from dbdp31.itg.ti.com (172.24.170.98) by DBDE71.ent.ti.com (172.24.170.149) with Microsoft SMTP Server id 8.3.106.1; Thu, 30 Jun 2011 18:43:22 +0530 Received: from psplinux051.india.ti.com (psplinux051.india.ti.com [172.24.162.244]) by dbdp31.itg.ti.com (8.13.8/8.13.8) with ESMTP id p5UDDI87010562; Thu, 30 Jun 2011 18:43:18 +0530 (IST) Received: from psplinux051.india.ti.com (localhost [127.0.0.1]) by psplinux051.india.ti.com (8.13.1/8.13.1) with ESMTP id p5UDDIIX016049; Thu, 30 Jun 2011 18:43:18 +0530 Received: (from x0144960@localhost) by psplinux051.india.ti.com (8.13.1/8.13.1/Submit) id p5UDDImk016046; Thu, 30 Jun 2011 18:43:18 +0530 From: Manjunath Hadli To: LMML CC: dlos , Nagabhushana Netagunte , Manjunath Hadli Subject: [RFC PATCH 2/8] davinci: vpfe: add IPIPE hardware layer support Date: Thu, 30 Jun 2011 18:43:11 +0530 Message-ID: <1309439597-15998-3-git-send-email-manjunath.hadli@ti.com> X-Mailer: git-send-email 1.6.2.4 In-Reply-To: <1309439597-15998-1-git-send-email-manjunath.hadli@ti.com> References: <1309439597-15998-1-git-send-email-manjunath.hadli@ti.com> MIME-Version: 1.0 Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]); Thu, 30 Jun 2011 13:13:45 +0000 (UTC) From: Nagabhushana Netagunte add dm365 IPIPE hardware support. IPIPE is the hardware IP which implements the functionality required for resizer, previewer and the associated feature support. This is built along with the vpfe driver, and implements hardware setup including coeffcient programming for various hardware filters, gamma, cfa and clock enable. Signed-off-by: Manjunath Hadli Signed-off-by: Nagabhushana Netagunte --- drivers/media/video/davinci/dm365_ipipe_hw.c | 1012 ++++++++++++++++++++++++++ drivers/media/video/davinci/dm365_ipipe_hw.h | 539 ++++++++++++++ 2 files changed, 1551 insertions(+), 0 deletions(-) create mode 100644 drivers/media/video/davinci/dm365_ipipe_hw.c create mode 100644 drivers/media/video/davinci/dm365_ipipe_hw.h diff --git a/drivers/media/video/davinci/dm365_ipipe_hw.c b/drivers/media/video/davinci/dm365_ipipe_hw.c new file mode 100644 index 0000000..b88e8e8 --- /dev/null +++ b/drivers/media/video/davinci/dm365_ipipe_hw.c @@ -0,0 +1,1012 @@ +/* +* Copyright (C) 2011 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 version 2. +* +* 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 +*/ +#include +#include +#include +#include +#include +#include +#include "dm365_ipipe_hw.h" + +static void ipipe_clock_enable(void) +{ + /* enable IPIPE MMR for register write access */ + regw_ip(IPIPE_GCK_MMR_DEFAULT, IPIPE_GCK_MMR); + /* enable the clock wb,cfa,dfc,d2f,pre modules */ + regw_ip(IPIPE_GCK_PIX_DEFAULT, IPIPE_GCK_PIX); + /* enable RSZ MMR for register write access */ +} + +/* Set input channel format to either 420 Y or C format */ +int rsz_set_in_pix_format(unsigned char y_c) +{ + u32 val; + + val = regr_rsz(RSZ_SRC_FMT1); + val |= (y_c & 1); + regw_rsz(val, RSZ_SRC_FMT1); + + return 0; +} + +static int rsz_set_common_params(struct ipipe_params *params) +{ + struct rsz_common_params *rsz_common = ¶ms->rsz_common; + u32 val; + + /* Set mode */ + regw_rsz(params->ipipe_mode, RSZ_SRC_MODE); + + /* data source selection and bypass */ + val = ((rsz_common->passthrough << RSZ_BYPASS_SHIFT) | + (rsz_common->source)); + + regw_rsz(val, RSZ_SRC_FMT0); + val = regr_rsz(RSZ_SRC_MODE); + /* src image selection */ + val = (rsz_common->raw_flip & 1) | + (rsz_common->src_img_fmt << RSZ_SRC_IMG_FMT_SHIFT) | + ((rsz_common->y_c & 1) << RSZ_SRC_Y_C_SEL_SHIFT); + + regw_rsz(val, RSZ_SRC_FMT1); + regw_rsz(rsz_common->vps & IPIPE_RSZ_VPS_MASK, RSZ_SRC_VPS); + regw_rsz(rsz_common->hps & IPIPE_RSZ_HPS_MASK, RSZ_SRC_HPS); + regw_rsz(rsz_common->vsz & IPIPE_RSZ_VSZ_MASK, RSZ_SRC_VSZ); + regw_rsz(rsz_common->hsz & IPIPE_RSZ_HSZ_MASK, RSZ_SRC_HSZ); + regw_rsz(rsz_common->yuv_y_min, RSZ_YUV_Y_MIN); + regw_rsz(rsz_common->yuv_y_max, RSZ_YUV_Y_MAX); + regw_rsz(rsz_common->yuv_c_min, RSZ_YUV_C_MIN); + regw_rsz(rsz_common->yuv_c_max, RSZ_YUV_C_MAX); + /* chromatic position */ + regw_rsz(rsz_common->out_chr_pos, RSZ_YUV_PHS); + val = regr_rsz(RSZ_SRC_MODE); + + return 0; +} + +static void rsz_set_rsz_regs(unsigned int rsz_id, struct ipipe_params *params) +{ + struct ipipe_rsz_rescale_param *rsc_params; + struct ipipe_ext_mem_param *ext_mem; + struct ipipe_rsz_resize2rgb *rgb; + u32 reg_base; + u32 val; + + val = regr_rsz(RSZ_SEQ); + if (rsz_id == RSZ_A) { + rsc_params = ¶ms->rsz_rsc_param[RSZ_A]; + rgb = ¶ms->rsz2rgb[RSZ_A]; + ext_mem = ¶ms->ext_mem_param[RSZ_A]; + val = rsc_params->h_flip << RSZA_H_FLIP_SHIFT; + val |= rsc_params->v_flip << RSZA_V_FLIP_SHIFT; + reg_base = RSZ_EN_A; + } else { + rsc_params = ¶ms->rsz_rsc_param[RSZ_B]; + rgb = ¶ms->rsz2rgb[RSZ_B]; + ext_mem = ¶ms->ext_mem_param[RSZ_B]; + val = rsc_params->h_flip << RSZB_H_FLIP_SHIFT; + val |= rsc_params->v_flip << RSZB_V_FLIP_SHIFT; + reg_base = RSZ_EN_B; + } + /* update flip settings */ + regw_rsz(val, RSZ_SEQ); + + regw_rsz(rsc_params->mode, reg_base + RSZ_MODE); + val = (rsc_params->cen << RSZ_CEN_SHIFT) | rsc_params->yen; + regw_rsz(val, reg_base + RSZ_420); + regw_rsz(rsc_params->i_vps & RSZ_VPS_MASK, reg_base + RSZ_I_VPS); + regw_rsz(rsc_params->i_hps & RSZ_HPS_MASK, reg_base + RSZ_I_HPS); + regw_rsz(rsc_params->o_vsz & RSZ_O_VSZ_MASK, reg_base + RSZ_O_VSZ); + regw_rsz(rsc_params->o_hsz & RSZ_O_HSZ_MASK, reg_base + RSZ_O_HSZ); + regw_rsz(rsc_params->v_phs_y & RSZ_V_PHS_MASK, reg_base + RSZ_V_PHS_Y); + regw_rsz(rsc_params->v_phs_c & RSZ_V_PHS_MASK, reg_base + RSZ_V_PHS_C); + /* keep this additional adjustment to zero for now */ + regw_rsz(rsc_params->v_dif & RSZ_V_DIF_MASK, reg_base + RSZ_V_DIF); + + val = (rsc_params->v_typ_y & 1) + | ((rsc_params->v_typ_c & 1) << RSZ_TYP_C_SHIFT); + regw_rsz(val, reg_base + RSZ_V_TYP); + + val = (rsc_params->v_lpf_int_y & RSZ_LPF_INT_MASK) | + ((rsc_params->v_lpf_int_c & RSZ_LPF_INT_MASK) << + RSZ_LPF_INT_C_SHIFT); + regw_rsz(val, reg_base + RSZ_V_LPF); + + regw_rsz(rsc_params->h_phs & RSZ_H_PHS_MASK, reg_base + RSZ_H_PHS); + regw_rsz(0, reg_base + RSZ_H_PHS_ADJ); + regw_rsz(rsc_params->h_dif & RSZ_H_DIF_MASK, reg_base + RSZ_H_DIF); + val = (rsc_params->h_typ_y & 1) | + ((rsc_params->h_typ_c & 1) << RSZ_TYP_C_SHIFT); + regw_rsz(val, reg_base + RSZ_H_TYP); + val = (rsc_params->h_lpf_int_y & RSZ_LPF_INT_MASK) | + ((rsc_params->h_lpf_int_c & RSZ_LPF_INT_MASK) << + RSZ_LPF_INT_C_SHIFT); + regw_rsz(val, reg_base + RSZ_H_LPF); + + regw_rsz(rsc_params->dscale_en & 1, reg_base + RSZ_DWN_EN); + val = rsc_params->h_dscale_ave_sz & RSZ_DWN_SCALE_AV_SZ_MASK; + val |= ((rsc_params->v_dscale_ave_sz & RSZ_DWN_SCALE_AV_SZ_MASK) << + RSZ_DWN_SCALE_AV_SZ_V_SHIFT); + regw_rsz(val, reg_base + RSZ_DWN_AV); + + /* setting rgb conversion parameters */ + regw_rsz(rgb->rgb_en, reg_base + RSZ_RGB_EN); + val = ((rgb->rgb_typ << RSZ_RGB_TYP_SHIFT) | + (rgb->rgb_msk0 << RSZ_RGB_MSK0_SHIFT) | + (rgb->rgb_msk1) << RSZ_RGB_MSK1_SHIFT); + regw_rsz(val, reg_base + RSZ_RGB_TYP); + regw_rsz(rgb->rgb_alpha_val & RSZ_RGB_ALPHA_MASK, + reg_base + RSZ_RGB_BLD); + + /* setting external memory parameters */ + regw_rsz(ext_mem->rsz_sdr_oft_y, reg_base + RSZ_SDR_Y_OFT); + regw_rsz(ext_mem->rsz_sdr_ptr_s_y, reg_base + RSZ_SDR_Y_PTR_S); + regw_rsz(ext_mem->rsz_sdr_ptr_e_y, reg_base + RSZ_SDR_Y_PTR_E); + regw_rsz(ext_mem->rsz_sdr_oft_c, reg_base + RSZ_SDR_C_OFT); + regw_rsz(ext_mem->rsz_sdr_ptr_s_c, reg_base + RSZ_SDR_C_PTR_S); + regw_rsz((ext_mem->rsz_sdr_ptr_e_c >> 1), reg_base + RSZ_SDR_C_PTR_E); +} + +static int ipipe_setup_resizer(struct ipipe_params *params) +{ /*set the registers of either RSZ0 or RSZ1 */ + u32 val; + + /* enable MMR gate to write to Resizer */ + regw_rsz(1, RSZ_GCK_MMR); + + /* Enable resizer if it is not in bypass mode */ + if (params->rsz_common.passthrough) + regw_rsz(0, RSZ_GCK_SDR); + else + regw_rsz(1, RSZ_GCK_SDR); + + rsz_set_common_params(params); + + regw_rsz(params->rsz_en[0], RSZ_EN_A); + if (params->rsz_en[0]) + /*setting rescale parameters */ + rsz_set_rsz_regs(RSZ_A, params); + + regw_rsz(params->rsz_en[1], RSZ_EN_B); + if (params->rsz_en[1]) + rsz_set_rsz_regs(RSZ_B, params); + + val = regr_rsz(RSZ_SRC_MODE); + + return 0; +} + +/* ipipe_hw_setup:It is used for Hardware Setup */ +int ipipe_hw_setup(struct ipipe_params *config) +{ + u32 data_format; + u32 val; + + if (!config) { + printk(KERN_ERR "NULL config block received\n"); + return -EINVAL; + } + + if (ipipeif_hw_setup(&config->ipipeif_param) < 0) { + printk(KERN_ERR "Unable to configure IPIPEIF"); + return -EINVAL; + } + + /* enable clock to IPIPE */ + vpss_enable_clock(VPSS_IPIPE_CLOCK, 1); + /* enable clock to MMR and modules before writting + * to ipipe registers + */ + ipipe_clock_enable(); + + if (config->rsz_common.source == IPIPEIF_DATA) { + /* we need to skip configuring IPIPE */ + regw_ip(0, IPIPE_SRC_EN); + } else { + /* enable ipipe mode to either one shot or continuous */ + val = config->ipipe_mode; + regw_ip((val), IPIPE_SRC_MODE); + data_format = config->ipipe_dpaths_fmt; + regw_ip(data_format, IPIPE_SRC_FMT); + /* set size */ + regw_ip(config->ipipe_vps & IPIPE_RSZ_VPS_MASK, IPIPE_SRC_VPS); + regw_ip(config->ipipe_hps & IPIPE_RSZ_HPS_MASK, IPIPE_SRC_HPS); + regw_ip(config->ipipe_vsz & IPIPE_RSZ_VSZ_MASK, IPIPE_SRC_VSZ); + regw_ip(config->ipipe_hsz & IPIPE_RSZ_HSZ_MASK, IPIPE_SRC_HSZ); + + if ((data_format == IPIPE_RAW2YUV) || + (data_format == IPIPE_RAW2RAW)) { + /* Combine all the fields to make COLPAT register + * of IPIPE + */ + val = (config->ipipe_colpat_elep << + COLPAT_EE_SHIFT); + val |= (config->ipipe_colpat_elop << + COLPAT_EO_SHIFT); + val |= (config->ipipe_colpat_olep << + COLPAT_OE_SHIFT); + val |= (config->ipipe_colpat_olop << + COLPAT_OO_SHIFT); + regw_ip(val, IPIPE_SRC_COL); + } + } + + return ipipe_setup_resizer(config); +} + +static void rsz_set_y_address(unsigned int address, unsigned int offset) +{ + u32 val; + + val = (address & SET_LOW_ADD); + regw_rsz(val, offset + RSZ_SDR_Y_BAD_L); + regw_rsz(val, offset + RSZ_SDR_Y_SAD_L); + val = (address & SET_HIGH_ADD) >> 16; + regw_rsz(val, offset + RSZ_SDR_Y_BAD_H); + regw_rsz(val, offset + RSZ_SDR_Y_SAD_H); +} + +static void rsz_set_c_address(unsigned int address, unsigned int offset) +{ + u32 val; + + val = (address & SET_LOW_ADD); + + regw_rsz(val, offset + RSZ_SDR_C_BAD_L); + regw_rsz(val, offset + RSZ_SDR_C_SAD_L); + val = (address & SET_HIGH_ADD) >> 16; + regw_rsz(val, offset + RSZ_SDR_C_BAD_H); + regw_rsz(val, offset + RSZ_SDR_C_SAD_H); +} + +/* Assume we get a valid params ptr and resize_no set to RSZ_A + * or RSZ_B. This could be called in the interrupt context and + * must be efficient + */ +int rsz_set_output_address(struct ipipe_params *params, + int resize_no, unsigned int address) +{ + unsigned int rsz_start_add; + unsigned int val; + + struct ipipe_ext_mem_param *mem_param = + ¶ms->ext_mem_param[resize_no]; + struct rsz_common_params *rsz_common = + ¶ms->rsz_common; + struct ipipe_rsz_rescale_param *rsc_param = + ¶ms->rsz_rsc_param[resize_no]; + + if (resize_no == RSZ_A) + rsz_start_add = RSZ_EN_A; + else + rsz_start_add = RSZ_EN_B; + /* y_c = 0 for y, = 1 for c */ + if (rsz_common->src_img_fmt == RSZ_IMG_420) { + if (rsz_common->y_c) { + /* C channel */ + val = (address + mem_param->flip_ofst_c); + rsz_set_c_address(val, rsz_start_add); + } else { + val = (address + mem_param->flip_ofst_y); + rsz_set_y_address(val, rsz_start_add); + } + } else { + if (rsc_param->cen && rsc_param->yen) { + /* 420 */ + val = (address + mem_param->c_offset); + val = (address + mem_param->c_offset + + mem_param->flip_ofst_c); + val += mem_param->user_y_ofst + + mem_param->user_c_ofst; + if (resize_no == RSZ_B) + val += + params->ext_mem_param[RSZ_A].user_y_ofst + + params->ext_mem_param[RSZ_A].user_c_ofst; + /* set C address */ + rsz_set_c_address(val, rsz_start_add); + } + val = (address + mem_param->flip_ofst_y); + val += mem_param->user_y_ofst; + if (resize_no == RSZ_B) + val += params->ext_mem_param[RSZ_A].user_y_ofst + + params->ext_mem_param[RSZ_A].user_c_ofst; + /* set Y address */ + rsz_set_y_address(val, rsz_start_add); + } + /* resizer must be enabled */ + regw_rsz(params->rsz_en[resize_no], rsz_start_add); + + return 0; +} + +int ipipe_set_lutdpc_regs(struct prev_lutdpc *dpc) +{ + u32 max_tbl_size = (LUT_DPC_MAX_SIZE >> 1); + u32 lut_start_addr = DPC_TB0_START_ADDR; + u32 val; + u32 count; + + ipipe_clock_enable(); + regw_ip(dpc->en, DPC_LUT_EN); + if (1 != dpc->en) + return 0; + + /* if dpc is enabled */ + val = LUTDPC_TBL_256_EN; + val |= (dpc->repl_white & 1); + regw_ip(val, DPC_LUT_SEL); + regw_ip(LUT_DPC_START_ADDR, DPC_LUT_ADR); + regw_ip(dpc->dpc_size, DPC_LUT_SIZ & LUT_DPC_SIZE_MASK); + if (dpc->table != NULL) { + count = 0; + while (count < dpc->dpc_size) { + if (count >= max_tbl_size) + lut_start_addr = DPC_TB1_START_ADDR; + val = + (dpc->table[count].horz_pos + & LUT_DPC_H_POS_MASK); + val |= ((dpc->table[count].vert_pos + & LUT_DPC_V_POS_MASK) + << LUT_DPC_V_POS_SHIFT); + val |= (dpc->table[count].method + << LUT_DPC_CORR_METH_SHIFT); + w_ip_table(val, (lut_start_addr + + ((count % max_tbl_size) << 2))); + count++; + } + } + return 0; +} + +static void set_dpc_thresholds(struct prev_otfdpc_2_0 *dpc_thr) +{ + regw_ip((dpc_thr->corr_thr.r & OTFDPC_DPC2_THR_MASK), + DPC_OTF_2C_THR_R); + regw_ip((dpc_thr->corr_thr.gr & OTFDPC_DPC2_THR_MASK), + DPC_OTF_2C_THR_GR); + regw_ip((dpc_thr->corr_thr.gb & OTFDPC_DPC2_THR_MASK), + DPC_OTF_2C_THR_GB); + regw_ip((dpc_thr->corr_thr.b & OTFDPC_DPC2_THR_MASK), + DPC_OTF_2C_THR_B); + regw_ip((dpc_thr->det_thr.r & OTFDPC_DPC2_THR_MASK), + DPC_OTF_2D_THR_R); + regw_ip((dpc_thr->det_thr.gr & OTFDPC_DPC2_THR_MASK), + DPC_OTF_2D_THR_GR); + regw_ip((dpc_thr->det_thr.gb & OTFDPC_DPC2_THR_MASK), + DPC_OTF_2D_THR_GB); + regw_ip((dpc_thr->det_thr.b & OTFDPC_DPC2_THR_MASK), + DPC_OTF_2D_THR_B); +} + +int ipipe_set_otfdpc_regs(struct prev_otfdpc *otfdpc) +{ + struct prev_otfdpc_2_0 *dpc_2_0 = &otfdpc->alg_cfg.dpc_2_0; + struct prev_otfdpc_3_0 *dpc_3_0 = &otfdpc->alg_cfg.dpc_3_0; + u32 val; + + ipipe_clock_enable(); + + regw_ip((otfdpc->en & 1), DPC_OTF_EN); + if (1 != otfdpc->en) + return 0; + + /* dpc enabled */ + val = (otfdpc->det_method << OTF_DET_METHOD_SHIFT); + val |= otfdpc->alg; + regw_ip(val, DPC_OTF_TYP); + if (otfdpc->det_method == IPIPE_DPC_OTF_MIN_MAX) { + /* ALG= 0, TYP = 0, DPC_OTF_2D_THR_[x]=0 + * DPC_OTF_2C_THR_[x] = Maximum thresohld + * MinMax method + */ + dpc_2_0->det_thr.r = dpc_2_0->det_thr.gb = + dpc_2_0->det_thr.gr = dpc_2_0->det_thr.b = 0; + set_dpc_thresholds(dpc_2_0); + } else { + /* MinMax2 */ + if (otfdpc->alg == IPIPE_OTFDPC_2_0) + set_dpc_thresholds(dpc_2_0); + else { + regw_ip((dpc_3_0->act_adj_shf + & OTF_DPC3_0_SHF_MASK), DPC_OTF_3_SHF); + /* Detection thresholds */ + regw_ip(((dpc_3_0->det_thr + & OTF_DPC3_0_THR_MASK) << + OTF_DPC3_0_THR_SHIFT), DPC_OTF_3D_THR); + regw_ip((dpc_3_0->det_slp + & OTF_DPC3_0_SLP_MASK), + DPC_OTF_3D_SLP); + regw_ip((dpc_3_0->det_thr_min + & OTF_DPC3_0_DET_MASK), + DPC_OTF_3D_MIN); + regw_ip((dpc_3_0->det_thr_max + & OTF_DPC3_0_DET_MASK), + DPC_OTF_3D_MAX); + /* Correction thresholds */ + regw_ip(((dpc_3_0->corr_thr + & OTF_DPC3_0_THR_MASK) << + OTF_DPC3_0_THR_SHIFT), DPC_OTF_3C_THR); + regw_ip((dpc_3_0->corr_slp + & OTF_DPC3_0_SLP_MASK), + DPC_OTF_3C_SLP); + regw_ip((dpc_3_0->corr_thr_min + & OTF_DPC3_0_CORR_MASK), + DPC_OTF_3C_MIN); + regw_ip((dpc_3_0->corr_thr_max + & OTF_DPC3_0_CORR_MASK), + DPC_OTF_3C_MAX); + } + } + + return 0; +} + +/* 2D Noise filter */ +int ipipe_set_d2f_regs(unsigned int id, struct prev_nf *noise_filter) +{ + + u32 offset = D2F_1ST; + int count; + u32 val; + + /* id = 0 , NF1 & id = 1, NF 2 */ + if (id) + offset = D2F_2ND; + ipipe_clock_enable(); + regw_ip(noise_filter->en & 1, offset + D2F_EN); + if (1 != noise_filter->en) + return 0; + + /*noise filter enabled */ + /* Combine all the fields to make D2F_CFG register of IPIPE */ + val = ((noise_filter->spread_val & D2F_SPR_VAL_MASK) << + D2F_SPR_VAL_SHIFT) | + ((noise_filter->shft_val & D2F_SHFT_VAL_MASK) << + D2F_SHFT_VAL_SHIFT) | + (noise_filter->gr_sample_meth << + D2F_SAMPLE_METH_SHIFT) | + ((noise_filter->apply_lsc_gain & 1) << + D2F_APPLY_LSC_GAIN_SHIFT) | D2F_USE_SPR_REG_VAL; + + regw_ip(val, offset + D2F_TYP); + /* edge detection minimum */ + regw_ip(noise_filter->edge_det_min_thr & D2F_EDGE_DET_THR_MASK, + offset + D2F_EDG_MIN); + /* edge detection maximum */ + regw_ip(noise_filter->edge_det_max_thr & D2F_EDGE_DET_THR_MASK, + offset + D2F_EDG_MAX); + count = 0; + while (count < IPIPE_NF_STR_TABLE_SIZE) { + regw_ip((noise_filter->str[count] & D2F_STR_VAL_MASK), + offset + D2F_STR + count * 4); + count++; + } + count = 0; + while (count < IPIPE_NF_THR_TABLE_SIZE) { + regw_ip(noise_filter->thr[count] & D2F_THR_VAL_MASK, + offset + D2F_THR + count * 4); + count++; + } + + return 0; +} + +#define IPIPE_U8Q5(decimal, integer) \ + (((decimal & 0x1f) | ((integer & 0x7) << 5))) + +/* Green Imbalance Correction */ +int ipipe_set_gic_regs(struct prev_gic *gic) +{ + u32 val; + + ipipe_clock_enable(); + regw_ip(gic->en & 1, GIC_EN); + + if (!gic->en) + return 0; + + /*gic enabled */ + val = gic->wt_fn_type << GIC_TYP_SHIFT; + val |= (gic->thr_sel << GIC_THR_SEL_SHIFT); + val |= ((gic->apply_lsc_gain & 1) << + GIC_APPLY_LSC_GAIN_SHIFT); + regw_ip(val, GIC_TYP); + regw_ip(gic->gain & GIC_GAIN_MASK, GIC_GAN); + if (gic->gic_alg == IPIPE_GIC_ALG_ADAPT_GAIN) { + if (gic->thr_sel == IPIPE_GIC_THR_REG) { + regw_ip(gic->thr & GIC_THR_MASK, GIC_THR); + regw_ip(gic->slope & GIC_SLOPE_MASK, GIC_SLP); + } else { + /* Use NF thresholds */ + val = IPIPE_U8Q5(gic->nf2_thr_gain.decimal, \ + gic->nf2_thr_gain.integer); + regw_ip(val, GIC_NFGAN); + } + } else + /* Constant Gain. Set threshold to maximum */ + regw_ip(GIC_THR_MASK, GIC_THR); + + return 0; +} + +#define IPIPE_U13Q9(decimal, integer) \ + (((decimal & 0x1ff) | ((integer & 0xf) << 9))) +/* White balance */ +int ipipe_set_wb_regs(struct prev_wb *wb) +{ + u32 val; + + ipipe_clock_enable(); + /* Ofsets. S12 */ + regw_ip(wb->ofst_r & WB_OFFSET_MASK, WB2_OFT_R); + regw_ip(wb->ofst_gr & WB_OFFSET_MASK, WB2_OFT_GR); + regw_ip(wb->ofst_gb & WB_OFFSET_MASK, WB2_OFT_GB); + regw_ip(wb->ofst_b & WB_OFFSET_MASK, WB2_OFT_B); + + /* Gains. U13Q9 */ + val = IPIPE_U13Q9((wb->gain_r.decimal), (wb->gain_r.integer)); + regw_ip(val, WB2_WGN_R); + val = IPIPE_U13Q9((wb->gain_gr.decimal), (wb->gain_gr.integer)); + regw_ip(val, WB2_WGN_GR); + val = IPIPE_U13Q9((wb->gain_gb.decimal), (wb->gain_gb.integer)); + regw_ip(val, WB2_WGN_GB); + val = IPIPE_U13Q9((wb->gain_b.decimal), (wb->gain_b.integer)); + regw_ip(val, WB2_WGN_B); + + return 0; +} + +/* CFA */ +int ipipe_set_cfa_regs(struct prev_cfa *cfa) +{ + ipipe_clock_enable(); + regw_ip(cfa->alg, CFA_MODE); + regw_ip(cfa->hpf_thr_2dir & CFA_HPF_THR_2DIR_MASK, CFA_2DIR_HPF_THR); + regw_ip(cfa->hpf_slp_2dir & CFA_HPF_SLOPE_2DIR_MASK, CFA_2DIR_HPF_SLP); + regw_ip(cfa->hp_mix_thr_2dir & CFA_HPF_MIX_THR_2DIR_MASK, + CFA_2DIR_MIX_THR); + regw_ip(cfa->hp_mix_slope_2dir & CFA_HPF_MIX_SLP_2DIR_MASK, + CFA_2DIR_MIX_SLP); + regw_ip(cfa->dir_thr_2dir & CFA_DIR_THR_2DIR_MASK, CFA_2DIR_DIR_THR); + regw_ip(cfa->dir_slope_2dir & CFA_DIR_SLP_2DIR_MASK, CFA_2DIR_DIR_SLP); + regw_ip(cfa->nd_wt_2dir & CFA_ND_WT_2DIR_MASK, CFA_2DIR_NDWT); + regw_ip(cfa->hue_fract_daa & CFA_DAA_HUE_FRA_MASK, CFA_MONO_HUE_FRA); + regw_ip(cfa->edge_thr_daa & CFA_DAA_EDG_THR_MASK, CFA_MONO_EDG_THR); + regw_ip(cfa->thr_min_daa & CFA_DAA_THR_MIN_MASK, CFA_MONO_THR_MIN); + regw_ip(cfa->thr_slope_daa & CFA_DAA_THR_SLP_MASK, CFA_MONO_THR_SLP); + regw_ip(cfa->slope_min_daa & CFA_DAA_SLP_MIN_MASK, CFA_MONO_SLP_MIN); + regw_ip(cfa->slope_slope_daa & CFA_DAA_SLP_SLP_MASK, CFA_MONO_SLP_SLP); + regw_ip(cfa->lp_wt_daa & CFA_DAA_LP_WT_MASK, CFA_MONO_LPWT); + + return 0; +} + +int ipipe_set_rgb2rgb_regs(unsigned int id, struct prev_rgb2rgb *rgb) +{ + u32 offset_mask = RGB2RGB_1_OFST_MASK; + u32 offset = RGB1_MUL_BASE; + u32 integ_mask = 0xf; + u32 val; + + ipipe_clock_enable(); + + if (id) { + /* For second RGB module, gain integer is 3 bits instead + of 4, offset has 11 bits insread of 13 */ + offset = RGB2_MUL_BASE; + integ_mask = 0x7; + offset_mask = RGB2RGB_2_OFST_MASK; + } + /* Gains */ + val = ((rgb->coef_rr.decimal & 0xff) | + (((rgb->coef_rr.integer) & integ_mask) << 8)); + regw_ip(val, offset + RGB_MUL_RR); + val = ((rgb->coef_gr.decimal & 0xff) | + (((rgb->coef_gr.integer) & integ_mask) << 8)); + regw_ip(val, offset + RGB_MUL_GR); + val = ((rgb->coef_br.decimal & 0xff) | + (((rgb->coef_br.integer) & integ_mask) << 8)); + regw_ip(val, offset + RGB_MUL_BR); + val = ((rgb->coef_rg.decimal & 0xff) | + (((rgb->coef_rg.integer) & integ_mask) << 8)); + regw_ip(val, offset + RGB_MUL_RG); + val = ((rgb->coef_gg.decimal & 0xff) | + (((rgb->coef_gg.integer) & integ_mask) << 8)); + regw_ip(val, offset + RGB_MUL_GG); + val = ((rgb->coef_bg.decimal & 0xff) | + (((rgb->coef_bg.integer) & integ_mask) << 8)); + regw_ip(val, offset + RGB_MUL_BG); + val = ((rgb->coef_rb.decimal & 0xff) | + (((rgb->coef_rb.integer) & integ_mask) << 8)); + regw_ip(val, offset + RGB_MUL_RB); + val = ((rgb->coef_gb.decimal & 0xff) | + (((rgb->coef_gb.integer) & integ_mask) << 8)); + regw_ip(val, offset + RGB_MUL_GB); + val = ((rgb->coef_bb.decimal & 0xff) | + (((rgb->coef_bb.integer) & integ_mask) << 8)); + regw_ip(val, offset + RGB_MUL_BB); + + /* Offsets */ + regw_ip(rgb->out_ofst_r & offset_mask, offset + RGB_OFT_OR); + regw_ip(rgb->out_ofst_g & offset_mask, offset + RGB_OFT_OG); + regw_ip(rgb->out_ofst_b & offset_mask, offset + RGB_OFT_OB); + + return 0; +} + +static void ipipe_update_gamma_tbl(struct ipipe_gamma_entry *table, + int size, u32 addr) +{ + int count; + u32 val; + + for (count = 0; count < size; count++) { + val = table[count].slope & GAMMA_MASK; + val |= ((table[count].offset & GAMMA_MASK) << GAMMA_SHIFT); + w_ip_table(val, (addr + (count * 4))); + } +} + +/* Gamma correction */ +int ipipe_set_gamma_regs(struct prev_gamma *gamma) +{ + int table_size; + u32 val; + + ipipe_clock_enable(); + val = ((gamma->bypass_r << GAMMA_BYPR_SHIFT) + | (gamma->bypass_b << GAMMA_BYPG_SHIFT) + | (gamma->bypass_g << GAMMA_BYPB_SHIFT) + | (gamma->tbl_sel << GAMMA_TBL_SEL_SHIFT) + | (gamma->tbl_size << GAMMA_TBL_SIZE_SHIFT)); + + regw_ip(val, GMM_CFG); + + if (gamma->tbl_sel == IPIPE_GAMMA_TBL_RAM) { + if (gamma->tbl_size == IPIPE_GAMMA_TBL_SZ_64) + table_size = 64; + else if (gamma->tbl_size == IPIPE_GAMMA_TBL_SZ_128) + table_size = 128; + else if (gamma->tbl_size == IPIPE_GAMMA_TBL_SZ_256) + table_size = 256; + else if (gamma->tbl_size == IPIPE_GAMMA_TBL_SZ_512) + table_size = 512; + else + table_size = 0; + + if (!(gamma->bypass_r)) { + if (gamma->table_r != NULL) + ipipe_update_gamma_tbl(gamma->table_r, + table_size, + GAMMA_R_START_ADDR); + } + if (!(gamma->bypass_b)) { + if (gamma->table_b != NULL) + ipipe_update_gamma_tbl(gamma->table_b, + table_size, + GAMMA_B_START_ADDR); + } + if (!(gamma->bypass_g)) { + if (gamma->table_g != NULL) + ipipe_update_gamma_tbl(gamma->table_g, + table_size, + GAMMA_G_START_ADDR); + } + } + + return 0; +} + +/* 3D LUT */ +int ipipe_set_3d_lut_regs(struct prev_3d_lut *lut_3d) +{ + struct ipipe_3d_lut_entry *tbl; + u32 bnk_index; + u32 tbl_index; + u32 val; + u32 i; + + ipipe_clock_enable(); + regw_ip(lut_3d->en, D3LUT_EN); + + if (!lut_3d->en) + return 0; + + /* lut_3d enabled */ + if (!lut_3d->table) + return 0; + + /* valied table */ + tbl = lut_3d->table; + for (i = 0 ; i < MAX_SIZE_3D_LUT; i++) { + /* Each entry has 0-9 (B), 10-19 (G) and + 20-29 R values */ + val = (tbl[i].b & D3_LUT_ENTRY_MASK); + val |= ((tbl[i].g & D3_LUT_ENTRY_MASK) << + D3_LUT_ENTRY_G_SHIFT); + val |= ((tbl[i].r & D3_LUT_ENTRY_MASK) << + D3_LUT_ENTRY_R_SHIFT); + bnk_index = (i % 4); + tbl_index = (i >> 2); + tbl_index <<= 2; + if (bnk_index == 0) + w_ip_table(val, tbl_index + D3L_TB0_START_ADDR); + else if (bnk_index == 1) + w_ip_table(val, tbl_index + D3L_TB1_START_ADDR); + else if (bnk_index == 2) + w_ip_table(val, tbl_index + D3L_TB2_START_ADDR); + else + w_ip_table(val, tbl_index + D3L_TB3_START_ADDR); + } + + return 0; +} + +/* Lumina adjustments */ +int ipipe_set_lum_adj_regs(struct prev_lum_adj *lum_adj) +{ + u32 val; + + ipipe_clock_enable(); + /* combine fields of YUV_ADJ to set brightness and contrast */ + val = ((lum_adj->contrast << LUM_ADJ_CONTR_SHIFT) + |(lum_adj->brightness << LUM_ADJ_BRIGHT_SHIFT)); + regw_ip(val, YUV_ADJ); + + return 0; +} + +#define IPIPE_S12Q8(decimal, integer) \ + (((decimal & 0xff) | ((integer & 0xf) << 8))) +/* RGB2YUV */ +int ipipe_set_rgb2ycbcr_regs(struct prev_rgb2yuv *yuv) +{ + u32 val; + + /* S10Q8 */ + ipipe_clock_enable(); + val = IPIPE_S12Q8((yuv->coef_ry.decimal), (yuv->coef_ry.integer)); + regw_ip(val, YUV_MUL_RY); + val = IPIPE_S12Q8((yuv->coef_gy.decimal), (yuv->coef_gy.integer)); + regw_ip(val, YUV_MUL_GY); + val = IPIPE_S12Q8((yuv->coef_by.decimal), (yuv->coef_by.integer)); + regw_ip(val, YUV_MUL_BY); + val = IPIPE_S12Q8((yuv->coef_rcb.decimal), (yuv->coef_rcb.integer)); + regw_ip(val, YUV_MUL_RCB); + val = IPIPE_S12Q8((yuv->coef_gcb.decimal), (yuv->coef_gcb.integer)); + regw_ip(val, YUV_MUL_GCB); + val = IPIPE_S12Q8((yuv->coef_bcb.decimal), (yuv->coef_bcb.integer)); + regw_ip(val, YUV_MUL_BCB); + val = IPIPE_S12Q8((yuv->coef_rcr.decimal), (yuv->coef_rcr.integer)); + regw_ip(val, YUV_MUL_RCR); + val = IPIPE_S12Q8((yuv->coef_gcr.decimal), (yuv->coef_gcr.integer)); + regw_ip(val, YUV_MUL_GCR); + val = IPIPE_S12Q8((yuv->coef_bcr.decimal), (yuv->coef_bcr.integer)); + regw_ip(val, YUV_MUL_BCR); + regw_ip(yuv->out_ofst_y & RGB2YCBCR_OFST_MASK, YUV_OFT_Y); + regw_ip(yuv->out_ofst_cb & RGB2YCBCR_OFST_MASK, YUV_OFT_CB); + regw_ip(yuv->out_ofst_cr & RGB2YCBCR_OFST_MASK, YUV_OFT_CR); + + return 0; +} + +/* YUV 422 conversion */ +int ipipe_set_yuv422_conv_regs(struct prev_yuv422_conv *conv) +{ + u32 val; + + ipipe_clock_enable(); + /* Combine all the fields to make YUV_PHS register of IPIPE */ + val = ((conv->chrom_pos << 0) | (conv->en_chrom_lpf << 1)); + regw_ip(val, YUV_PHS); + + return 0; +} + +/* GBCE */ +int ipipe_set_gbce_regs(struct prev_gbce *gbce) +{ + unsigned int tbl_index; + unsigned int count; + u32 mask = GBCE_Y_VAL_MASK; + u32 val; + + if (gbce->type == IPIPE_GBCE_GAIN_TBL) + mask = GBCE_GAIN_VAL_MASK; + + ipipe_clock_enable(); + regw_ip(gbce->en & 1, GBCE_EN); + + /* set to 0 */ + val = 0; + + if (gbce->en) { + regw_ip(gbce->type, GBCE_TYP); + if (gbce->table) { + for (count = 0; count < MAX_SIZE_GBCE_LUT; count++) { + tbl_index = count >> 1; + tbl_index <<= 2; + /* Each table has 2 LUT entries, first in LS + * and second in MS positions + */ + if (count % 2) { + val |= + ((gbce->table[count] & mask) << + GBCE_ENTRY_SHIFT); + w_ip_table(val, + tbl_index + GBCE_TB_START_ADDR); + } else + val = gbce->table[count] & mask; + } + } + } + + return 0; +} +/* Edge Enhancement */ +int ipipe_set_ee_regs(struct prev_yee *ee) +{ + unsigned int tbl_index; + unsigned int count; + u32 val; + + ipipe_clock_enable(); + regw_ip(ee->en, YEE_EN); + + if (1 == ee->en) { + val = ee->en_halo_red & 1; + val |= (ee->merge_meth << YEE_HALO_RED_EN_SHIFT); + regw_ip(val, YEE_TYP); + regw_ip(ee->hpf_shft, YEE_SHF); + regw_ip(ee->hpf_coef_00 & YEE_COEF_MASK, YEE_MUL_00); + regw_ip(ee->hpf_coef_01 & YEE_COEF_MASK, YEE_MUL_01); + regw_ip(ee->hpf_coef_02 & YEE_COEF_MASK, YEE_MUL_02); + regw_ip(ee->hpf_coef_10 & YEE_COEF_MASK, YEE_MUL_10); + regw_ip(ee->hpf_coef_11 & YEE_COEF_MASK, YEE_MUL_11); + regw_ip(ee->hpf_coef_12 & YEE_COEF_MASK, YEE_MUL_12); + regw_ip(ee->hpf_coef_20 & YEE_COEF_MASK, YEE_MUL_20); + regw_ip(ee->hpf_coef_21 & YEE_COEF_MASK, YEE_MUL_21); + regw_ip(ee->hpf_coef_22 & YEE_COEF_MASK, YEE_MUL_22); + regw_ip(ee->yee_thr & YEE_THR_MASK, YEE_THR); + regw_ip(ee->es_gain & YEE_ES_GAIN_MASK, YEE_E_GAN); + regw_ip(ee->es_thr1 & YEE_ES_THR1_MASK, YEE_E_THR1); + regw_ip(ee->es_thr2 & YEE_THR_MASK, YEE_E_THR2); + regw_ip(ee->es_gain_grad & YEE_THR_MASK, YEE_G_GAN); + regw_ip(ee->es_ofst_grad & YEE_THR_MASK, YEE_G_OFT); + + if (ee->table != NULL) { + for (count = 0; count < MAX_SIZE_YEE_LUT; count++) { + tbl_index = count >> 1; + tbl_index <<= 2; + /* Each table has 2 LUT entries, first in LS + * and second in MS positions + */ + if (count % 2) { + val |= ((ee->table[count] & + YEE_ENTRY_MASK) << + YEE_ENTRY_SHIFT); + w_ip_table(val, + tbl_index + YEE_TB_START_ADDR); + } else + val = ee->table[count] & + YEE_ENTRY_MASK; + } + } + } + + return 0; +} + +/* Chromatic Artifact Correction. CAR */ +static void ipipe_set_mf(void) +{ + /* typ to dynamic switch */ + regw_ip(IPIPE_CAR_DYN_SWITCH, CAR_TYP); + /* Set SW0 to maximum */ + regw_ip(CAR_MF_THR, CAR_SW); +} + +static void ipipe_set_gain_ctrl(struct prev_car *car) +{ + regw_ip(IPIPE_CAR_CHR_GAIN_CTRL, CAR_TYP); + regw_ip(car->hpf, CAR_HPF_TYP); + regw_ip(car->hpf_shft & CAR_HPF_SHIFT_MASK, CAR_HPF_SHF); + regw_ip(car->hpf_thr, CAR_HPF_THR); + regw_ip(car->gain1.gain, CAR_GN1_GAN); + regw_ip(car->gain1.shft & CAR_GAIN1_SHFT_MASK, CAR_GN1_SHF); + regw_ip(car->gain1.gain_min & CAR_GAIN_MIN_MASK, CAR_GN1_MIN); + regw_ip(car->gain2.gain, CAR_GN2_GAN); + regw_ip(car->gain2.shft & CAR_GAIN2_SHFT_MASK, CAR_GN2_SHF); + regw_ip(car->gain2.gain_min & CAR_GAIN_MIN_MASK, CAR_GN2_MIN); +} + +int ipipe_set_car_regs(struct prev_car *car) +{ + u32 val; + + ipipe_clock_enable(); + regw_ip(car->en, CAR_EN); + + if (car->en) { + switch (car->meth) { + case IPIPE_CAR_MED_FLTR: + { + ipipe_set_mf(); + break; + } + case IPIPE_CAR_CHR_GAIN_CTRL: + { + ipipe_set_gain_ctrl(car); + break; + } + default: + { + /* Dynamic switch between MF and Gain Ctrl. */ + ipipe_set_mf(); + ipipe_set_gain_ctrl(car); + /* Set the threshold for switching between + * the two Here we overwrite the MF SW0 value + */ + regw_ip(IPIPE_CAR_DYN_SWITCH, CAR_TYP); + val = car->sw1; + val <<= CAR_SW1_SHIFT; + val |= car->sw0; + regw_ip(val, CAR_SW); + } + } + } + + return 0; +} + +/* Chromatic Gain Suppression */ +int ipipe_set_cgs_regs(struct prev_cgs *cgs) +{ + ipipe_clock_enable(); + regw_ip(cgs->en, CGS_EN); + + if (cgs->en) { + /* Set the bright side parameters */ + regw_ip(cgs->h_thr, CGS_GN1_H_THR); + regw_ip(cgs->h_slope, CGS_GN1_H_GAN); + regw_ip(cgs->h_shft & CAR_SHIFT_MASK, CGS_GN1_H_SHF); + regw_ip(cgs->h_min, CGS_GN1_H_MIN); + } + + return 0; +} + +void rsz_src_enable(int enable) +{ + regw_rsz(enable, RSZ_SRC_EN); +} + +int rsz_enable(int rsz_id, int enable) +{ + if (rsz_id == RSZ_A) { + regw_rsz(enable, RSZ_EN_A); + /* We always enable RSZ_A. RSZ_B is enable upon request from + * application. So enable RSZ_SRC_EN along with RSZ_A + */ + regw_rsz(enable, RSZ_SRC_EN); + } else if (rsz_id == RSZ_B) + regw_rsz(enable, RSZ_EN_B); + else + return -EINVAL; + + return 0; +} diff --git a/drivers/media/video/davinci/dm365_ipipe_hw.h b/drivers/media/video/davinci/dm365_ipipe_hw.h new file mode 100644 index 0000000..c3c79c6 --- /dev/null +++ b/drivers/media/video/davinci/dm365_ipipe_hw.h @@ -0,0 +1,539 @@ +/* +* Copyright (C) 2011 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 version 2. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +#ifndef _DM365_IPIPE_HW_H +#define _DM365_IPIPE_HW_H + +#include +#include + +#define IPIPE_IOBASE_VADDR IO_ADDRESS(0x01C70800) +#define RSZ_IOBASE_VADDR IO_ADDRESS(0x01C70400) +#define IPIPE_INT_TABLE_IOBASE_VADDR IO_ADDRESS(0x01C70000) + +#define SET_LOW_ADD 0x0000FFFF +#define SET_HIGH_ADD 0xFFFF0000 + +/* Below are the internal tables */ +#define DPC_TB0_START_ADDR (0x8000) +#define DPC_TB1_START_ADDR (0x8400) + +#define GAMMA_R_START_ADDR (0xA800) +#define GAMMA_G_START_ADDR (0xB000) +#define GAMMA_B_START_ADDR (0xB800) + +/* RAM table addresses for edge enhancement correction*/ +#define YEE_TB_START_ADDR (0x8800) + +/* RAM table address for GBC LUT */ +#define GBCE_TB_START_ADDR (0x9000) + +/* RAM table for 3D NF LUT */ +#define D3L_TB0_START_ADDR (0x9800) +#define D3L_TB1_START_ADDR (0x9C00) +#define D3L_TB2_START_ADDR (0xA000) +#define D3L_TB3_START_ADDR (0xA400) + +/* IPIPE Register Offsets from the base address */ +#define IPIPE_SRC_EN (0x0000) +#define IPIPE_SRC_MODE (0x0004) +#define IPIPE_SRC_FMT (0x0008) +#define IPIPE_SRC_COL (0x000C) +#define IPIPE_SRC_VPS (0x0010) +#define IPIPE_SRC_VSZ (0x0014) +#define IPIPE_SRC_HPS (0x0018) +#define IPIPE_SRC_HSZ (0x001C) + +#define IPIPE_SEL_SBU (0x0020) + +#define IPIPE_DMA_STA (0x0024) +#define IPIPE_GCK_MMR (0x0028) +#define IPIPE_GCK_PIX (0x002C) +#define IPIPE_RESERVED0 (0x0030) + +/* Defect Correction */ +#define DPC_LUT_EN (0x0034) +#define DPC_LUT_SEL (0x0038) +#define DPC_LUT_ADR (0x003C) +#define DPC_LUT_SIZ (0x0040) +#define DPC_OTF_EN (0x0044) +#define DPC_OTF_TYP (0x0048) +#define DPC_OTF_2D_THR_R (0x004C) +#define DPC_OTF_2D_THR_GR (0x0050) +#define DPC_OTF_2D_THR_GB (0x0054) +#define DPC_OTF_2D_THR_B (0x0058) +#define DPC_OTF_2C_THR_R (0x005C) +#define DPC_OTF_2C_THR_GR (0x0060) +#define DPC_OTF_2C_THR_GB (0x0064) +#define DPC_OTF_2C_THR_B (0x0068) +#define DPC_OTF_3_SHF (0x006C) +#define DPC_OTF_3D_THR (0x0070) +#define DPC_OTF_3D_SLP (0x0074) +#define DPC_OTF_3D_MIN (0x0078) +#define DPC_OTF_3D_MAX (0x007C) +#define DPC_OTF_3C_THR (0x0080) +#define DPC_OTF_3C_SLP (0x0084) +#define DPC_OTF_3C_MIN (0x0088) +#define DPC_OTF_3C_MAX (0x008C) + +/* Lense Shading Correction */ +#define LSC_VOFT (0x90) +#define LSC_VA2 (0x94) +#define LSC_VA1 (0x98) +#define LSC_VS (0x9C) +#define LSC_HOFT (0xA0) +#define LSC_HA2 (0xA4) +#define LSC_HA1 (0xA8) +#define LSC_HS (0xAC) +#define LSC_GAIN_R (0xB0) +#define LSC_GAIN_GR (0xB4) +#define LSC_GAIN_GB (0xB8) +#define LSC_GAIN_B (0xBC) +#define LSC_OFT_R (0xC0) +#define LSC_OFT_GR (0xC4) +#define LSC_OFT_GB (0xC8) +#define LSC_OFT_B (0xCC) +#define LSC_SHF (0xD0) +#define LSC_MAX (0xD4) + +/* Noise Filter 1. Ofsets from start address given */ +#define D2F_1ST (0xD8) +#define D2F_EN (0x0) +#define D2F_TYP (0x4) +#define D2F_THR (0x8) +#define D2F_STR (0x28) +#define D2F_SPR (0x48) +#define D2F_EDG_MIN (0x68) +#define D2F_EDG_MAX (0x6C) + +/* Noise Filter 2 */ +#define D2F_2ND (0x148) + +/* GIC */ +#define GIC_EN (0x1B8) +#define GIC_TYP (0x1BC) +#define GIC_GAN (0x1C0) +#define GIC_NFGAN (0x1C4) +#define GIC_THR (0x1C8) +#define GIC_SLP (0x1CC) + +/* White Balance */ +#define WB2_OFT_R (0x1D0) +#define WB2_OFT_GR (0x1D4) +#define WB2_OFT_GB (0x1D8) +#define WB2_OFT_B (0x1DC) +#define WB2_WGN_R (0x1E0) +#define WB2_WGN_GR (0x1E4) +#define WB2_WGN_GB (0x1E8) +#define WB2_WGN_B (0x1EC) + +/* CFA interpolation */ +#define CFA_MODE (0x1F0) +#define CFA_2DIR_HPF_THR (0x1F4) +#define CFA_2DIR_HPF_SLP (0x1F8) +#define CFA_2DIR_MIX_THR (0x1FC) +#define CFA_2DIR_MIX_SLP (0x200) +#define CFA_2DIR_DIR_THR (0x204) +#define CFA_2DIR_DIR_SLP (0x208) +#define CFA_2DIR_NDWT (0x20C) +#define CFA_MONO_HUE_FRA (0x210) +#define CFA_MONO_EDG_THR (0x214) +#define CFA_MONO_THR_MIN (0x218) +#define CFA_MONO_THR_SLP (0x21C) +#define CFA_MONO_SLP_MIN (0x220) +#define CFA_MONO_SLP_SLP (0x224) +#define CFA_MONO_LPWT (0x228) + +/* RGB to RGB conversiona - 1st */ +#define RGB1_MUL_BASE (0x22C) +/* Offsets from base */ +#define RGB_MUL_RR (0x0) +#define RGB_MUL_GR (0x4) +#define RGB_MUL_BR (0x8) +#define RGB_MUL_RG (0xC) +#define RGB_MUL_GG (0x10) +#define RGB_MUL_BG (0x14) +#define RGB_MUL_RB (0x18) +#define RGB_MUL_GB (0x1C) +#define RGB_MUL_BB (0x20) +#define RGB_OFT_OR (0x24) +#define RGB_OFT_OG (0x28) +#define RGB_OFT_OB (0x2C) + +/* Gamma */ +#define GMM_CFG (0x25C) + +/* RGB to RGB conversiona - 2nd */ +#define RGB2_MUL_BASE (0x260) + +/* 3D LUT */ +#define D3LUT_EN (0x290) + +/* RGB to YUV(YCbCr) conversion */ +#define YUV_ADJ (0x294) +#define YUV_MUL_RY (0x298) +#define YUV_MUL_GY (0x29C) +#define YUV_MUL_BY (0x2A0) +#define YUV_MUL_RCB (0x2A4) +#define YUV_MUL_GCB (0x2A8) +#define YUV_MUL_BCB (0x2AC) +#define YUV_MUL_RCR (0x2B0) +#define YUV_MUL_GCR (0x2B4) +#define YUV_MUL_BCR (0x2B8) +#define YUV_OFT_Y (0x2BC) +#define YUV_OFT_CB (0x2C0) +#define YUV_OFT_CR (0x2C4) +#define YUV_PHS (0x2C8) + +/* Global Brightness and Contrast */ +#define GBCE_EN (0x2CC) +#define GBCE_TYP (0x2D0) + +/* Edge Enhancer */ +#define YEE_EN (0x2D4) +#define YEE_TYP (0x2D8) +#define YEE_SHF (0x2DC) +#define YEE_MUL_00 (0x2E0) +#define YEE_MUL_01 (0x2E4) +#define YEE_MUL_02 (0x2E8) +#define YEE_MUL_10 (0x2EC) +#define YEE_MUL_11 (0x2F0) +#define YEE_MUL_12 (0x2F4) +#define YEE_MUL_20 (0x2F8) +#define YEE_MUL_21 (0x2FC) +#define YEE_MUL_22 (0x300) +#define YEE_THR (0x304) +#define YEE_E_GAN (0x308) +#define YEE_E_THR1 (0x30C) +#define YEE_E_THR2 (0x310) +#define YEE_G_GAN (0x314) +#define YEE_G_OFT (0x318) + +/* Chroma Artifact Reduction */ +#define CAR_EN (0x31C) +#define CAR_TYP (0x320) +#define CAR_SW (0x324) +#define CAR_HPF_TYP (0x328) +#define CAR_HPF_SHF (0x32C) +#define CAR_HPF_THR (0x330) +#define CAR_GN1_GAN (0x334) +#define CAR_GN1_SHF (0x338) +#define CAR_GN1_MIN (0x33C) +#define CAR_GN2_GAN (0x340) +#define CAR_GN2_SHF (0x344) +#define CAR_GN2_MIN (0x348) + +/* Chroma Gain Suppression */ +#define CGS_EN (0x34C) +#define CGS_GN1_L_THR (0x350) +#define CGS_GN1_L_GAN (0x354) +#define CGS_GN1_L_SHF (0x358) +#define CGS_GN1_L_MIN (0x35C) +#define CGS_GN1_H_THR (0x360) +#define CGS_GN1_H_GAN (0x364) +#define CGS_GN1_H_SHF (0x368) +#define CGS_GN1_H_MIN (0x36C) +#define CGS_GN2_L_THR (0x370) +#define CGS_GN2_L_GAN (0x374) +#define CGS_GN2_L_SHF (0x378) +#define CGS_GN2_L_MIN (0x37C) + +/* Resizer */ +#define RSZ_SRC_EN (0x0) +#define RSZ_SRC_MODE (0x4) +#define RSZ_SRC_FMT0 (0x8) +#define RSZ_SRC_FMT1 (0xC) +#define RSZ_SRC_VPS (0x10) +#define RSZ_SRC_VSZ (0x14) +#define RSZ_SRC_HPS (0x18) +#define RSZ_SRC_HSZ (0x1C) +#define RSZ_DMA_RZA (0x20) +#define RSZ_DMA_RZB (0x24) +#define RSZ_DMA_STA (0x28) +#define RSZ_GCK_MMR (0x2C) +#define RSZ_RESERVED0 (0x30) +#define RSZ_GCK_SDR (0x34) +#define RSZ_IRQ_RZA (0x38) +#define RSZ_IRQ_RZB (0x3C) +#define RSZ_YUV_Y_MIN (0x40) +#define RSZ_YUV_Y_MAX (0x44) +#define RSZ_YUV_C_MIN (0x48) +#define RSZ_YUV_C_MAX (0x4C) +#define RSZ_YUV_PHS (0x50) +#define RSZ_SEQ (0x54) + +/* Resizer Rescale Parameters */ +#define RSZ_EN_A (0x58) +#define RSZ_EN_B (0xE8) +/* offset of the registers to be added with base register of + either RSZ0 or RSZ1 +*/ +#define RSZ_MODE (0x4) +#define RSZ_420 (0x8) +#define RSZ_I_VPS (0xC) +#define RSZ_I_HPS (0x10) +#define RSZ_O_VSZ (0x14) +#define RSZ_O_HSZ (0x18) +#define RSZ_V_PHS_Y (0x1C) +#define RSZ_V_PHS_C (0x20) +#define RSZ_V_DIF (0x24) +#define RSZ_V_TYP (0x28) +#define RSZ_V_LPF (0x2C) +#define RSZ_H_PHS (0x30) +#define RSZ_H_PHS_ADJ (0x34) +#define RSZ_H_DIF (0x38) +#define RSZ_H_TYP (0x3C) +#define RSZ_H_LPF (0x40) +#define RSZ_DWN_EN (0x44) +#define RSZ_DWN_AV (0x48) + +/* Resizer RGB Conversion Parameters */ +#define RSZ_RGB_EN (0x4C) +#define RSZ_RGB_TYP (0x50) +#define RSZ_RGB_BLD (0x54) + +/* Resizer External Memory Parameters */ +#define RSZ_SDR_Y_BAD_H (0x58) +#define RSZ_SDR_Y_BAD_L (0x5C) +#define RSZ_SDR_Y_SAD_H (0x60) +#define RSZ_SDR_Y_SAD_L (0x64) +#define RSZ_SDR_Y_OFT (0x68) +#define RSZ_SDR_Y_PTR_S (0x6C) +#define RSZ_SDR_Y_PTR_E (0x70) +#define RSZ_SDR_C_BAD_H (0x74) +#define RSZ_SDR_C_BAD_L (0x78) +#define RSZ_SDR_C_SAD_H (0x7C) +#define RSZ_SDR_C_SAD_L (0x80) +#define RSZ_SDR_C_OFT (0x84) +#define RSZ_SDR_C_PTR_S (0x88) +#define RSZ_SDR_C_PTR_E (0x8C) + +/* Macro for resizer */ +#define IPIPE_RESIZER_A(i) (RSZ_IOBASE_VADDR + RSZ_EN_A + i) +#define IPIPE_RESIZER_B(i) (RSZ_IOBASE_VADDR + RSZ_EN_B + i) + +#define RSZ_YUV_Y_MIN (0x40) +#define RSZ_YUV_Y_MAX (0x44) +#define RSZ_YUV_C_MIN (0x48) +#define RSZ_YUV_C_MAX (0x4C) + +#define IPIPE_GCK_MMR_DEFAULT (1) +#define IPIPE_GCK_PIX_DEFAULT (0xE) +#define RSZ_GCK_MMR_DEFAULT (1) +#define RSZ_GCK_SDR_DEFAULT (1) + +/* Below defines for masks and shifts */ +#define COLPAT_EE_SHIFT (0) +#define COLPAT_EO_SHIFT (2) +#define COLPAT_OE_SHIFT (4) +#define COLPAT_OO_SHIFT (6) + +/* LUTDPC */ +#define LUTDPC_TBL_256_EN (0 << 1) +#define LUTDPC_INF_TBL_EN (1) +#define LUT_DPC_START_ADDR (0) +#define LUT_DPC_H_POS_MASK (0x1FFF) +#define LUT_DPC_V_POS_MASK (0x1FFF) +#define LUT_DPC_V_POS_SHIFT (13) +#define LUT_DPC_CORR_METH_SHIFT (26) +#define LUT_DPC_MAX_SIZE (256) +#define LUT_DPC_SIZE_MASK (0x3FF) + +/* OTFDPC */ +#define OTFDPC_DPC2_THR_MASK (0xFFF) +#define OTF_DET_METHOD_SHIFT (1) +#define OTF_DPC3_0_SHF_MASK (3) +#define OTF_DPC3_0_THR_SHIFT (6) +#define OTF_DPC3_0_THR_MASK (0x3F) +#define OTF_DPC3_0_SLP_MASK (0x3F) +#define OTF_DPC3_0_DET_MASK (0xFFF) +#define OTF_DPC3_0_CORR_MASK (0xFFF) + +/* NF (D2F) */ +#define D2F_SPR_VAL_MASK (0x1F) +#define D2F_SPR_VAL_SHIFT (0) +#define D2F_SHFT_VAL_MASK (3) +#define D2F_SHFT_VAL_SHIFT (5) +#define D2F_SAMPLE_METH_SHIFT (7) +#define D2F_APPLY_LSC_GAIN_SHIFT (8) +#define D2F_USE_SPR_REG_VAL (0 << 9) +#define D2F_STR_VAL_MASK (0x1F) +#define D2F_THR_VAL_MASK (0x3FF) +#define D2F_EDGE_DET_THR_MASK (0x7FF) + +/* Green Imbalance Correction */ +#define GIC_TYP_SHIFT (0) +#define GIC_THR_SEL_SHIFT (1) +#define GIC_APPLY_LSC_GAIN_SHIFT (2) +#define GIC_GAIN_MASK (0xFF) +#define GIC_THR_MASK (0xFFF) +#define GIC_SLOPE_MASK (0xFFF) +#define GIC_NFGAN_INT_MASK (7) +#define GIC_NFGAN_DECI_MASK (0x1F) + +/* WB */ +#define WB_OFFSET_MASK (0xFFF) +#define WB_GAIN_INT_MASK (0xF) +#define WB_GAIN_DECI_MASK (0x1FF) + +/* CFA */ +#define CFA_HPF_THR_2DIR_MASK (0x1FFF) +#define CFA_HPF_SLOPE_2DIR_MASK (0x3FF) +#define CFA_HPF_MIX_THR_2DIR_MASK (0x1FFF) +#define CFA_HPF_MIX_SLP_2DIR_MASK (0x3FF) +#define CFA_DIR_THR_2DIR_MASK (0x3FF) +#define CFA_DIR_SLP_2DIR_MASK (0x7F) +#define CFA_ND_WT_2DIR_MASK (0x3F) +#define CFA_DAA_HUE_FRA_MASK (0x3F) +#define CFA_DAA_EDG_THR_MASK (0xFF) +#define CFA_DAA_THR_MIN_MASK (0x3FF) +#define CFA_DAA_THR_SLP_MASK (0x3FF) +#define CFA_DAA_SLP_MIN_MASK (0x3FF) +#define CFA_DAA_SLP_SLP_MASK (0x3FF) +#define CFA_DAA_LP_WT_MASK (0x3F) + +/* RGB2RGB */ +#define RGB2RGB_1_OFST_MASK (0x1FFF) +#define RGB2RGB_1_GAIN_INT_MASK (0xF) +#define RGB2RGB_GAIN_DECI_MASK (0xFF) +#define RGB2RGB_2_OFST_MASK (0x7FF) +#define RGB2RGB_2_GAIN_INT_MASK (0x7) + +/* Gamma */ +#define GAMMA_BYPR_SHIFT (0) +#define GAMMA_BYPG_SHIFT (1) +#define GAMMA_BYPB_SHIFT (2) +#define GAMMA_TBL_SEL_SHIFT (4) +#define GAMMA_TBL_SIZE_SHIFT (5) +#define GAMMA_MASK (0x3FF) +#define GAMMA_SHIFT (10) + +/* 3D LUT */ +#define D3_LUT_ENTRY_MASK (0x3FF) +#define D3_LUT_ENTRY_R_SHIFT (20) +#define D3_LUT_ENTRY_G_SHIFT (10) +#define D3_LUT_ENTRY_B_SHIFT (0) + +/* Lumina adj */ +#define LUM_ADJ_CONTR_SHIFT (0) +#define LUM_ADJ_BRIGHT_SHIFT (8) + +/* RGB2YCbCr */ +#define RGB2YCBCR_OFST_MASK (0x7FF) +#define RGB2YCBCR_COEF_INT_MASK (0xF) +#define RGB2YCBCR_COEF_DECI_MASK (0xFF) + +/* GBCE */ +#define GBCE_Y_VAL_MASK (0xFF) +#define GBCE_GAIN_VAL_MASK (0x3FF) +#define GBCE_ENTRY_SHIFT (10) + +/* Edge Enhancements */ +#define YEE_HALO_RED_EN_SHIFT (1) +#define YEE_HPF_SHIFT_MASK (0xF) +#define YEE_COEF_MASK (0x3FF) +#define YEE_THR_MASK (0x3F) +#define YEE_ES_GAIN_MASK (0xFFF) +#define YEE_ES_THR1_MASK (0xFFF) +#define YEE_ENTRY_SHIFT (9) +#define YEE_ENTRY_MASK (0x1FF) + +/* CAR */ +#define CAR_MF_THR (0xFF) +#define CAR_SW1_SHIFT (8) +#define CAR_GAIN1_SHFT_MASK (7) +#define CAR_GAIN_MIN_MASK (0x1FF) +#define CAR_GAIN2_SHFT_MASK (0xF) +#define CAR_HPF_SHIFT_MASK (3) + +/* CGS */ +#define CAR_SHIFT_MASK (3) + +/* Resizer */ +#define RSZ_BYPASS_SHIFT (1) +#define RSZ_SRC_IMG_FMT_SHIFT (1) +#define RSZ_SRC_Y_C_SEL_SHIFT (2) +#define IPIPE_RSZ_VPS_MASK (0xFFFF) +#define IPIPE_RSZ_HPS_MASK (0xFFFF) +#define IPIPE_RSZ_VSZ_MASK (0x1FFF) +#define IPIPE_RSZ_HSZ_MASK (0x1FFF) +#define RSZ_HPS_MASK (0x1FFF) +#define RSZ_VPS_MASK (0x1FFF) +#define RSZ_O_HSZ_MASK (0x1FFF) +#define RSZ_O_VSZ_MASK (0x1FFF) +#define RSZ_V_PHS_MASK (0x3FFF) +#define RSZ_V_DIF_MASK (0x3FFF) + +#define RSZA_H_FLIP_SHIFT (0) +#define RSZA_V_FLIP_SHIFT (1) +#define RSZB_H_FLIP_SHIFT (2) +#define RSZB_V_FLIP_SHIFT (3) +#define RSZ_A (0) +#define RSZ_B (1) +#define RSZ_CEN_SHIFT (1) +#define RSZ_YEN_SHIFT (0) +#define RSZ_TYP_Y_SHIFT (0) +#define RSZ_TYP_C_SHIFT (1) +#define RSZ_LPF_INT_MASK (0x3F) +#define RSZ_LPF_INT_MASK (0x3F) +#define RSZ_LPF_INT_C_SHIFT (6) +#define RSZ_H_PHS_MASK (0x3FFF) +#define RSZ_H_DIF_MASK (0x3FFF) +#define RSZ_DIFF_DOWN_THR (256) +#define RSZ_DWN_SCALE_AV_SZ_V_SHIFT (3) +#define RSZ_DWN_SCALE_AV_SZ_MASK (7) +#define RSZ_RGB_MSK1_SHIFT (2) +#define RSZ_RGB_MSK0_SHIFT (1) +#define RSZ_RGB_TYP_SHIFT (0) +#define RSZ_RGB_ALPHA_MASK (0xFF) + +static inline u32 regr_ip(u32 offset) +{ + return readl(IPIPE_IOBASE_VADDR + offset); +} + +static inline u32 regw_ip(u32 val, u32 offset) +{ + writel(val, IPIPE_IOBASE_VADDR + offset); + + return val; +} + +static inline u32 r_ip_table(u32 offset) +{ + return readl(IPIPE_INT_TABLE_IOBASE_VADDR + offset); +} + +static inline u32 w_ip_table(u32 val, u32 offset) +{ + writel(val, IPIPE_INT_TABLE_IOBASE_VADDR + offset); + + return val; +} + +static inline u32 regr_rsz(u32 offset) +{ + return readl(RSZ_IOBASE_VADDR + offset); +} + +static inline u32 regw_rsz(u32 val, u32 offset) +{ + writel(val, RSZ_IOBASE_VADDR + offset); + + return val; +} + +#endif /* End of #ifdef _DM365_IPIPE_HW_H */