提交 26c0e999 编写于 作者: M Manjunath Hadli 提交者: Mauro Carvalho Chehab

[media] davinci: vpfe: dm365: add IPIPE hardware layer support

IPIPE is the hardware IP which implements the functionality
required for resizer, ipipe(colorspace converter) and
the associated hardware support. This patch implements hardware
setup including coefficient programming for various hardware
filters, gamma, cfa and clock enabling.
Signed-off-by: NManjunath Hadli <manjunath.hadli@ti.com>
Signed-off-by: NLad, Prabhakar <prabhakar.lad@ti.com>
Acked-by: NLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: NSakari Ailus <sakari.ailus@iki.fi>
Acked-by: NHans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: NMauro Carvalho Chehab <mchehab@redhat.com>
上级 da43b6cc
/*
* Copyright (C) 2012 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
*
* Contributors:
* Manjunath Hadli <manjunath.hadli@ti.com>
* Prabhakar Lad <prabhakar.lad@ti.com>
*/
#include "dm365_ipipe_hw.h"
#define IPIPE_MODE_CONTINUOUS 0
#define IPIPE_MODE_SINGLE_SHOT 1
static void ipipe_clock_enable(void *__iomem base_addr)
{
/* enable IPIPE MMR for register write access */
regw_ip(base_addr, IPIPE_GCK_MMR_DEFAULT, IPIPE_GCK_MMR);
/* enable the clock wb,cfa,dfc,d2f,pre modules */
regw_ip(base_addr, IPIPE_GCK_PIX_DEFAULT, IPIPE_GCK_PIX);
}
static void
rsz_set_common_params(void *__iomem rsz_base, struct resizer_params *params)
{
struct rsz_common_params *rsz_common = &params->rsz_common;
u32 val;
/* Set mode */
regw_rsz(rsz_base, params->oper_mode, RSZ_SRC_MODE);
/* data source selection and bypass */
val = (rsz_common->passthrough << RSZ_BYPASS_SHIFT) |
rsz_common->source;
regw_rsz(rsz_base, val, RSZ_SRC_FMT0);
/* 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(rsz_base, val, RSZ_SRC_FMT1);
regw_rsz(rsz_base, rsz_common->vps & IPIPE_RSZ_VPS_MASK, RSZ_SRC_VPS);
regw_rsz(rsz_base, rsz_common->hps & IPIPE_RSZ_HPS_MASK, RSZ_SRC_HPS);
regw_rsz(rsz_base, rsz_common->vsz & IPIPE_RSZ_VSZ_MASK, RSZ_SRC_VSZ);
regw_rsz(rsz_base, rsz_common->hsz & IPIPE_RSZ_HSZ_MASK, RSZ_SRC_HSZ);
regw_rsz(rsz_base, rsz_common->yuv_y_min, RSZ_YUV_Y_MIN);
regw_rsz(rsz_base, rsz_common->yuv_y_max, RSZ_YUV_Y_MAX);
regw_rsz(rsz_base, rsz_common->yuv_c_min, RSZ_YUV_C_MIN);
regw_rsz(rsz_base, rsz_common->yuv_c_max, RSZ_YUV_C_MAX);
/* chromatic position */
regw_rsz(rsz_base, rsz_common->out_chr_pos, RSZ_YUV_PHS);
}
static void
rsz_set_rsz_regs(void *__iomem rsz_base, unsigned int rsz_id,
struct resizer_params *params)
{
struct resizer_scale_param *rsc_params;
struct rsz_ext_mem_param *ext_mem;
struct resizer_rgb *rgb;
u32 reg_base;
u32 val;
rsc_params = &params->rsz_rsc_param[rsz_id];
rgb = &params->rsz2rgb[rsz_id];
ext_mem = &params->ext_mem_param[rsz_id];
if (rsz_id == 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 {
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(rsz_base, val, RSZ_SEQ);
regw_rsz(rsz_base, params->oper_mode, reg_base + RSZ_MODE);
val = (rsc_params->cen << RSZ_CEN_SHIFT) | rsc_params->yen;
regw_rsz(rsz_base, val, reg_base + RSZ_420);
regw_rsz(rsz_base, rsc_params->i_vps & RSZ_VPS_MASK,
reg_base + RSZ_I_VPS);
regw_rsz(rsz_base, rsc_params->i_hps & RSZ_HPS_MASK,
reg_base + RSZ_I_HPS);
regw_rsz(rsz_base, rsc_params->o_vsz & RSZ_O_VSZ_MASK,
reg_base + RSZ_O_VSZ);
regw_rsz(rsz_base, rsc_params->o_hsz & RSZ_O_HSZ_MASK,
reg_base + RSZ_O_HSZ);
regw_rsz(rsz_base, rsc_params->v_phs_y & RSZ_V_PHS_MASK,
reg_base + RSZ_V_PHS_Y);
regw_rsz(rsz_base, 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(rsz_base, 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(rsz_base, 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(rsz_base, val, reg_base + RSZ_V_LPF);
regw_rsz(rsz_base, rsc_params->h_phs &
RSZ_H_PHS_MASK, reg_base + RSZ_H_PHS);
regw_rsz(rsz_base, 0, reg_base + RSZ_H_PHS_ADJ);
regw_rsz(rsz_base, 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(rsz_base, 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(rsz_base, val, reg_base + RSZ_H_LPF);
regw_rsz(rsz_base, rsc_params->dscale_en & 1, reg_base + RSZ_DWN_EN);
val = (rsc_params->h_dscale_ave_sz & RSZ_DWN_SCALE_AV_SZ_MASK) |
((rsc_params->v_dscale_ave_sz & RSZ_DWN_SCALE_AV_SZ_MASK) <<
RSZ_DWN_SCALE_AV_SZ_V_SHIFT);
regw_rsz(rsz_base, val, reg_base + RSZ_DWN_AV);
/* setting rgb conversion parameters */
regw_rsz(rsz_base, 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(rsz_base, val, reg_base + RSZ_RGB_TYP);
regw_rsz(rsz_base, rgb->rgb_alpha_val & RSZ_RGB_ALPHA_MASK,
reg_base + RSZ_RGB_BLD);
/* setting external memory parameters */
regw_rsz(rsz_base, ext_mem->rsz_sdr_oft_y, reg_base + RSZ_SDR_Y_OFT);
regw_rsz(rsz_base, ext_mem->rsz_sdr_ptr_s_y,
reg_base + RSZ_SDR_Y_PTR_S);
regw_rsz(rsz_base, ext_mem->rsz_sdr_ptr_e_y,
reg_base + RSZ_SDR_Y_PTR_E);
regw_rsz(rsz_base, ext_mem->rsz_sdr_oft_c, reg_base + RSZ_SDR_C_OFT);
regw_rsz(rsz_base, ext_mem->rsz_sdr_ptr_s_c,
reg_base + RSZ_SDR_C_PTR_S);
regw_rsz(rsz_base, (ext_mem->rsz_sdr_ptr_e_c >> 1),
reg_base + RSZ_SDR_C_PTR_E);
}
/*set the registers of either RSZ0 or RSZ1 */
static void
ipipe_setup_resizer(void *__iomem rsz_base, struct resizer_params *params)
{
/* enable MMR gate to write to Resizer */
regw_rsz(rsz_base, 1, RSZ_GCK_MMR);
/* Enable resizer if it is not in bypass mode */
if (params->rsz_common.passthrough)
regw_rsz(rsz_base, 0, RSZ_GCK_SDR);
else
regw_rsz(rsz_base, 1, RSZ_GCK_SDR);
rsz_set_common_params(rsz_base, params);
regw_rsz(rsz_base, params->rsz_en[RSZ_A], RSZ_EN_A);
if (params->rsz_en[RSZ_A])
/*setting rescale parameters */
rsz_set_rsz_regs(rsz_base, RSZ_A, params);
regw_rsz(rsz_base, params->rsz_en[RSZ_B], RSZ_EN_B);
if (params->rsz_en[RSZ_B])
rsz_set_rsz_regs(rsz_base, RSZ_B, params);
}
static u32 ipipe_get_color_pat(enum v4l2_mbus_pixelcode pix)
{
switch (pix) {
case V4L2_MBUS_FMT_SGRBG10_ALAW8_1X8:
case V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8:
case V4L2_MBUS_FMT_SGRBG12_1X12:
return ipipe_sgrbg_pattern;
default:
return ipipe_srggb_pattern;
}
}
static int ipipe_get_data_path(struct vpfe_ipipe_device *ipipe)
{
enum v4l2_mbus_pixelcode temp_pix_fmt;
switch (ipipe->formats[IPIPE_PAD_SINK].code) {
case V4L2_MBUS_FMT_SBGGR8_1X8:
case V4L2_MBUS_FMT_SGRBG10_ALAW8_1X8:
case V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8:
case V4L2_MBUS_FMT_SGRBG12_1X12:
temp_pix_fmt = V4L2_MBUS_FMT_SGRBG12_1X12;
break;
default:
temp_pix_fmt = V4L2_MBUS_FMT_UYVY8_2X8;
}
if (temp_pix_fmt == V4L2_MBUS_FMT_SGRBG12_1X12) {
if (ipipe->formats[IPIPE_PAD_SOURCE].code ==
V4L2_MBUS_FMT_SGRBG12_1X12)
return IPIPE_RAW2RAW;
return IPIPE_RAW2YUV;
}
return IPIPE_YUV2YUV;
}
static int get_ipipe_mode(struct vpfe_ipipe_device *ipipe)
{
struct vpfe_device *vpfe_dev = to_vpfe_device(ipipe);
u16 ipipeif_sink = vpfe_dev->vpfe_ipipeif.input;
if (ipipeif_sink == IPIPEIF_INPUT_MEMORY)
return IPIPE_MODE_SINGLE_SHOT;
else if (ipipeif_sink == IPIPEIF_INPUT_ISIF)
return IPIPE_MODE_CONTINUOUS;
return -EINVAL;
}
int config_ipipe_hw(struct vpfe_ipipe_device *ipipe)
{
struct vpfe_ipipe_input_config *config = &ipipe->config.input_config;
void __iomem *ipipe_base = ipipe->base_addr;
struct v4l2_mbus_framefmt *outformat;
u32 color_pat;
u32 ipipe_mode;
u32 data_path;
/* enable clock to IPIPE */
vpss_enable_clock(VPSS_IPIPE_CLOCK, 1);
ipipe_clock_enable(ipipe_base);
if (ipipe->input == IPIPE_INPUT_NONE) {
regw_ip(ipipe_base, 0, IPIPE_SRC_EN);
return 0;
}
ipipe_mode = get_ipipe_mode(ipipe);
if (ipipe < 0) {
pr_err("Failed to get ipipe mode");
return -EINVAL;
}
regw_ip(ipipe_base, ipipe_mode, IPIPE_SRC_MODE);
data_path = ipipe_get_data_path(ipipe);
regw_ip(ipipe_base, data_path, IPIPE_SRC_FMT);
regw_ip(ipipe_base, config->vst & IPIPE_RSZ_VPS_MASK, IPIPE_SRC_VPS);
regw_ip(ipipe_base, config->hst & IPIPE_RSZ_HPS_MASK, IPIPE_SRC_HPS);
outformat = &ipipe->formats[IPIPE_PAD_SOURCE];
regw_ip(ipipe_base, (outformat->height + 1) & IPIPE_RSZ_VSZ_MASK,
IPIPE_SRC_VSZ);
regw_ip(ipipe_base, (outformat->width + 1) & IPIPE_RSZ_HSZ_MASK,
IPIPE_SRC_HSZ);
if (data_path == IPIPE_RAW2YUV ||
data_path == IPIPE_RAW2RAW) {
color_pat =
ipipe_get_color_pat(ipipe->formats[IPIPE_PAD_SINK].code);
regw_ip(ipipe_base, color_pat, IPIPE_SRC_COL);
}
return 0;
}
/*
* config_rsz_hw() - Performs hardware setup of resizer.
*/
int config_rsz_hw(struct vpfe_resizer_device *resizer,
struct resizer_params *config)
{
struct vpfe_device *vpfe_dev = to_vpfe_device(resizer);
void *__iomem ipipe_base = vpfe_dev->vpfe_ipipe.base_addr;
void *__iomem rsz_base = vpfe_dev->vpfe_resizer.base_addr;
/* enable VPSS clock */
vpss_enable_clock(VPSS_IPIPE_CLOCK, 1);
ipipe_clock_enable(ipipe_base);
ipipe_setup_resizer(rsz_base, config);
return 0;
}
static void
rsz_set_y_address(void *__iomem rsz_base, unsigned int address,
unsigned int offset)
{
u32 val;
val = address & SET_LOW_ADDR;
regw_rsz(rsz_base, val, offset + RSZ_SDR_Y_BAD_L);
regw_rsz(rsz_base, val, offset + RSZ_SDR_Y_SAD_L);
val = (address & SET_HIGH_ADDR) >> 16;
regw_rsz(rsz_base, val, offset + RSZ_SDR_Y_BAD_H);
regw_rsz(rsz_base, val, offset + RSZ_SDR_Y_SAD_H);
}
static void
rsz_set_c_address(void *__iomem rsz_base, unsigned int address,
unsigned int offset)
{
u32 val;
val = address & SET_LOW_ADDR;
regw_rsz(rsz_base, val, offset + RSZ_SDR_C_BAD_L);
regw_rsz(rsz_base, val, offset + RSZ_SDR_C_SAD_L);
val = (address & SET_HIGH_ADDR) >> 16;
regw_rsz(rsz_base, val, offset + RSZ_SDR_C_BAD_H);
regw_rsz(rsz_base, val, offset + RSZ_SDR_C_SAD_H);
}
/*
* resizer_set_outaddr() - set the address for given resize_no
* @rsz_base: resizer base address
* @params: pointer to ipipe_params structure
* @resize_no: 0 - Resizer-A, 1 - Resizer B
* @address: the address to set
*/
int
resizer_set_outaddr(void *__iomem rsz_base, struct resizer_params *params,
int resize_no, unsigned int address)
{
struct resizer_scale_param *rsc_param;
struct rsz_ext_mem_param *mem_param;
struct rsz_common_params *rsz_common;
unsigned int rsz_start_add;
unsigned int val;
if (resize_no != RSZ_A && resize_no != RSZ_B)
return -EINVAL;
mem_param = &params->ext_mem_param[resize_no];
rsc_param = &params->rsz_rsc_param[resize_no];
rsz_common = &params->rsz_common;
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(rsz_base, val, rsz_start_add);
} else {
val = address + mem_param->flip_ofst_y;
rsz_set_y_address(rsz_base, val, rsz_start_add);
}
} else {
if (rsc_param->cen && rsc_param->yen) {
/* 420 */
val = address + mem_param->c_offset +
mem_param->flip_ofst_c +
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(rsz_base, val, rsz_start_add);
}
val = address + mem_param->flip_ofst_y + 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(rsz_base, val, rsz_start_add);
}
/* resizer must be enabled */
regw_rsz(rsz_base, params->rsz_en[resize_no], rsz_start_add);
return 0;
}
void
ipipe_set_lutdpc_regs(void *__iomem base_addr, void *__iomem isp5_base_addr,
struct vpfe_ipipe_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(base_addr);
regw_ip(base_addr, dpc->en, DPC_LUT_EN);
if (dpc->en != 1)
return;
val = LUTDPC_TBL_256_EN | (dpc->repl_white & 1);
regw_ip(base_addr, val, DPC_LUT_SEL);
regw_ip(base_addr, LUT_DPC_START_ADDR, DPC_LUT_ADR);
regw_ip(base_addr, dpc->dpc_size, DPC_LUT_SIZ & LUT_DPC_SIZE_MASK);
if (dpc->table == NULL)
return;
for (count = 0; count < dpc->dpc_size; count++) {
if (count >= max_tbl_size)
lut_start_addr = DPC_TB1_START_ADDR;
val = (dpc->table[count].horz_pos & LUT_DPC_H_POS_MASK) |
((dpc->table[count].vert_pos & LUT_DPC_V_POS_MASK) <<
LUT_DPC_V_POS_SHIFT) | (dpc->table[count].method <<
LUT_DPC_CORR_METH_SHIFT);
w_ip_table(isp5_base_addr, val, (lut_start_addr +
((count % max_tbl_size) << 2)));
}
}
static void
set_dpc_thresholds(void *__iomem base_addr,
struct vpfe_ipipe_otfdpc_2_0_cfg *dpc_thr)
{
regw_ip(base_addr, dpc_thr->corr_thr.r & OTFDPC_DPC2_THR_MASK,
DPC_OTF_2C_THR_R);
regw_ip(base_addr, dpc_thr->corr_thr.gr & OTFDPC_DPC2_THR_MASK,
DPC_OTF_2C_THR_GR);
regw_ip(base_addr, dpc_thr->corr_thr.gb & OTFDPC_DPC2_THR_MASK,
DPC_OTF_2C_THR_GB);
regw_ip(base_addr, dpc_thr->corr_thr.b & OTFDPC_DPC2_THR_MASK,
DPC_OTF_2C_THR_B);
regw_ip(base_addr, dpc_thr->det_thr.r & OTFDPC_DPC2_THR_MASK,
DPC_OTF_2D_THR_R);
regw_ip(base_addr, dpc_thr->det_thr.gr & OTFDPC_DPC2_THR_MASK,
DPC_OTF_2D_THR_GR);
regw_ip(base_addr, dpc_thr->det_thr.gb & OTFDPC_DPC2_THR_MASK,
DPC_OTF_2D_THR_GB);
regw_ip(base_addr, dpc_thr->det_thr.b & OTFDPC_DPC2_THR_MASK,
DPC_OTF_2D_THR_B);
}
void ipipe_set_otfdpc_regs(void *__iomem base_addr,
struct vpfe_ipipe_otfdpc *otfdpc)
{
struct vpfe_ipipe_otfdpc_2_0_cfg *dpc_2_0 = &otfdpc->alg_cfg.dpc_2_0;
struct vpfe_ipipe_otfdpc_3_0_cfg *dpc_3_0 = &otfdpc->alg_cfg.dpc_3_0;
u32 val;
ipipe_clock_enable(base_addr);
regw_ip(base_addr, (otfdpc->en & 1), DPC_OTF_EN);
if (!otfdpc->en)
return;
/* dpc enabled */
val = (otfdpc->det_method << OTF_DET_METHOD_SHIFT) | otfdpc->alg;
regw_ip(base_addr, val, DPC_OTF_TYP);
if (otfdpc->det_method == VPFE_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(base_addr, dpc_2_0);
return;
}
/* MinMax2 */
if (otfdpc->alg == VPFE_IPIPE_OTFDPC_2_0) {
set_dpc_thresholds(base_addr, dpc_2_0);
return;
}
regw_ip(base_addr, dpc_3_0->act_adj_shf &
OTF_DPC3_0_SHF_MASK, DPC_OTF_3_SHF);
/* Detection thresholds */
regw_ip(base_addr, ((dpc_3_0->det_thr & OTF_DPC3_0_THR_MASK) <<
OTF_DPC3_0_THR_SHIFT), DPC_OTF_3D_THR);
regw_ip(base_addr, dpc_3_0->det_slp &
OTF_DPC3_0_SLP_MASK, DPC_OTF_3D_SLP);
regw_ip(base_addr, dpc_3_0->det_thr_min &
OTF_DPC3_0_DET_MASK, DPC_OTF_3D_MIN);
regw_ip(base_addr, dpc_3_0->det_thr_max &
OTF_DPC3_0_DET_MASK, DPC_OTF_3D_MAX);
/* Correction thresholds */
regw_ip(base_addr, ((dpc_3_0->corr_thr & OTF_DPC3_0_THR_MASK) <<
OTF_DPC3_0_THR_SHIFT), DPC_OTF_3C_THR);
regw_ip(base_addr, dpc_3_0->corr_slp &
OTF_DPC3_0_SLP_MASK, DPC_OTF_3C_SLP);
regw_ip(base_addr, dpc_3_0->corr_thr_min &
OTF_DPC3_0_CORR_MASK, DPC_OTF_3C_MIN);
regw_ip(base_addr, dpc_3_0->corr_thr_max &
OTF_DPC3_0_CORR_MASK, DPC_OTF_3C_MAX);
}
/* 2D Noise filter */
void
ipipe_set_d2f_regs(void *__iomem base_addr, unsigned int id,
struct vpfe_ipipe_nf *noise_filter)
{
u32 offset = D2F_1ST;
int count;
u32 val;
if (id == IPIPE_D2F_2ND)
offset = D2F_2ND;
ipipe_clock_enable(base_addr);
regw_ip(base_addr, noise_filter->en & 1, offset + D2F_EN);
if (!noise_filter->en)
return;
/*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(base_addr, val, offset + D2F_TYP);
/* edge detection minimum */
regw_ip(base_addr, noise_filter->edge_det_min_thr &
D2F_EDGE_DET_THR_MASK, offset + D2F_EDG_MIN);
/* edge detection maximum */
regw_ip(base_addr, noise_filter->edge_det_max_thr &
D2F_EDGE_DET_THR_MASK, offset + D2F_EDG_MAX);
for (count = 0; count < VPFE_IPIPE_NF_STR_TABLE_SIZE; count++)
regw_ip(base_addr,
(noise_filter->str[count] & D2F_STR_VAL_MASK),
offset + D2F_STR + count * 4);
for (count = 0; count < VPFE_IPIPE_NF_THR_TABLE_SIZE; count++)
regw_ip(base_addr, noise_filter->thr[count] & D2F_THR_VAL_MASK,
offset + D2F_THR + count * 4);
}
#define IPIPE_U8Q5(decimal, integer) \
(((decimal & 0x1f) | ((integer & 0x7) << 5)))
/* Green Imbalance Correction */
void ipipe_set_gic_regs(void *__iomem base_addr, struct vpfe_ipipe_gic *gic)
{
u32 val;
ipipe_clock_enable(base_addr);
regw_ip(base_addr, gic->en & 1, GIC_EN);
if (!gic->en)
return;
/*gic enabled */
val = (gic->wt_fn_type << GIC_TYP_SHIFT) |
(gic->thr_sel << GIC_THR_SEL_SHIFT) |
((gic->apply_lsc_gain & 1) << GIC_APPLY_LSC_GAIN_SHIFT);
regw_ip(base_addr, val, GIC_TYP);
regw_ip(base_addr, gic->gain & GIC_GAIN_MASK, GIC_GAN);
if (gic->gic_alg != VPFE_IPIPE_GIC_ALG_ADAPT_GAIN) {
/* Constant Gain. Set threshold to maximum */
regw_ip(base_addr, GIC_THR_MASK, GIC_THR);
return;
}
if (gic->thr_sel == VPFE_IPIPE_GIC_THR_REG) {
regw_ip(base_addr, gic->thr & GIC_THR_MASK, GIC_THR);
regw_ip(base_addr, 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(base_addr, val, GIC_NFGAN);
}
}
#define IPIPE_U13Q9(decimal, integer) \
(((decimal & 0x1ff) | ((integer & 0xf) << 9)))
/* White balance */
void ipipe_set_wb_regs(void *__iomem base_addr, struct vpfe_ipipe_wb *wb)
{
u32 val;
ipipe_clock_enable(base_addr);
/* Ofsets. S12 */
regw_ip(base_addr, wb->ofst_r & WB_OFFSET_MASK, WB2_OFT_R);
regw_ip(base_addr, wb->ofst_gr & WB_OFFSET_MASK, WB2_OFT_GR);
regw_ip(base_addr, wb->ofst_gb & WB_OFFSET_MASK, WB2_OFT_GB);
regw_ip(base_addr, wb->ofst_b & WB_OFFSET_MASK, WB2_OFT_B);
/* Gains. U13Q9 */
val = IPIPE_U13Q9(wb->gain_r.decimal, wb->gain_r.integer);
regw_ip(base_addr, val, WB2_WGN_R);
val = IPIPE_U13Q9(wb->gain_gr.decimal, wb->gain_gr.integer);
regw_ip(base_addr, val, WB2_WGN_GR);
val = IPIPE_U13Q9(wb->gain_gb.decimal, wb->gain_gb.integer);
regw_ip(base_addr, val, WB2_WGN_GB);
val = IPIPE_U13Q9(wb->gain_b.decimal, wb->gain_b.integer);
regw_ip(base_addr, val, WB2_WGN_B);
}
/* CFA */
void ipipe_set_cfa_regs(void *__iomem base_addr, struct vpfe_ipipe_cfa *cfa)
{
ipipe_clock_enable(base_addr);
regw_ip(base_addr, cfa->alg, CFA_MODE);
regw_ip(base_addr, cfa->hpf_thr_2dir & CFA_HPF_THR_2DIR_MASK,
CFA_2DIR_HPF_THR);
regw_ip(base_addr, cfa->hpf_slp_2dir & CFA_HPF_SLOPE_2DIR_MASK,
CFA_2DIR_HPF_SLP);
regw_ip(base_addr, cfa->hp_mix_thr_2dir & CFA_HPF_MIX_THR_2DIR_MASK,
CFA_2DIR_MIX_THR);
regw_ip(base_addr, cfa->hp_mix_slope_2dir & CFA_HPF_MIX_SLP_2DIR_MASK,
CFA_2DIR_MIX_SLP);
regw_ip(base_addr, cfa->dir_thr_2dir & CFA_DIR_THR_2DIR_MASK,
CFA_2DIR_DIR_THR);
regw_ip(base_addr, cfa->dir_slope_2dir & CFA_DIR_SLP_2DIR_MASK,
CFA_2DIR_DIR_SLP);
regw_ip(base_addr, cfa->nd_wt_2dir & CFA_ND_WT_2DIR_MASK,
CFA_2DIR_NDWT);
regw_ip(base_addr, cfa->hue_fract_daa & CFA_DAA_HUE_FRA_MASK,
CFA_MONO_HUE_FRA);
regw_ip(base_addr, cfa->edge_thr_daa & CFA_DAA_EDG_THR_MASK,
CFA_MONO_EDG_THR);
regw_ip(base_addr, cfa->thr_min_daa & CFA_DAA_THR_MIN_MASK,
CFA_MONO_THR_MIN);
regw_ip(base_addr, cfa->thr_slope_daa & CFA_DAA_THR_SLP_MASK,
CFA_MONO_THR_SLP);
regw_ip(base_addr, cfa->slope_min_daa & CFA_DAA_SLP_MIN_MASK,
CFA_MONO_SLP_MIN);
regw_ip(base_addr, cfa->slope_slope_daa & CFA_DAA_SLP_SLP_MASK,
CFA_MONO_SLP_SLP);
regw_ip(base_addr, cfa->lp_wt_daa & CFA_DAA_LP_WT_MASK,
CFA_MONO_LPWT);
}
void
ipipe_set_rgb2rgb_regs(void *__iomem base_addr, unsigned int id,
struct vpfe_ipipe_rgb2rgb *rgb)
{
u32 offset_mask = RGB2RGB_1_OFST_MASK;
u32 offset = RGB1_MUL_BASE;
u32 integ_mask = 0xf;
u32 val;
ipipe_clock_enable(base_addr);
if (id == IPIPE_RGB2RGB_2) {
/* 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(base_addr, val, offset + RGB_MUL_RR);
val = (rgb->coef_gr.decimal & 0xff) |
((rgb->coef_gr.integer & integ_mask) << 8);
regw_ip(base_addr, val, offset + RGB_MUL_GR);
val = (rgb->coef_br.decimal & 0xff) |
((rgb->coef_br.integer & integ_mask) << 8);
regw_ip(base_addr, val, offset + RGB_MUL_BR);
val = (rgb->coef_rg.decimal & 0xff) |
((rgb->coef_rg.integer & integ_mask) << 8);
regw_ip(base_addr, val, offset + RGB_MUL_RG);
val = (rgb->coef_gg.decimal & 0xff) |
((rgb->coef_gg.integer & integ_mask) << 8);
regw_ip(base_addr, val, offset + RGB_MUL_GG);
val = (rgb->coef_bg.decimal & 0xff) |
((rgb->coef_bg.integer & integ_mask) << 8);
regw_ip(base_addr, val, offset + RGB_MUL_BG);
val = (rgb->coef_rb.decimal & 0xff) |
((rgb->coef_rb.integer & integ_mask) << 8);
regw_ip(base_addr, val, offset + RGB_MUL_RB);
val = (rgb->coef_gb.decimal & 0xff) |
((rgb->coef_gb.integer & integ_mask) << 8);
regw_ip(base_addr, val, offset + RGB_MUL_GB);
val = (rgb->coef_bb.decimal & 0xff) |
((rgb->coef_bb.integer & integ_mask) << 8);
regw_ip(base_addr, val, offset + RGB_MUL_BB);
/* Offsets */
regw_ip(base_addr, rgb->out_ofst_r & offset_mask, offset + RGB_OFT_OR);
regw_ip(base_addr, rgb->out_ofst_g & offset_mask, offset + RGB_OFT_OG);
regw_ip(base_addr, rgb->out_ofst_b & offset_mask, offset + RGB_OFT_OB);
}
static void
ipipe_update_gamma_tbl(void *__iomem isp5_base_addr,
struct vpfe_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(isp5_base_addr, val, (addr + (count * 4)));
}
}
void
ipipe_set_gamma_regs(void *__iomem base_addr, void *__iomem isp5_base_addr,
struct vpfe_ipipe_gamma *gamma)
{
int table_size;
u32 val;
ipipe_clock_enable(base_addr);
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(base_addr, val, GMM_CFG);
if (gamma->tbl_sel != VPFE_IPIPE_GAMMA_TBL_RAM)
return;
table_size = gamma->tbl_size;
if (!gamma->bypass_r && gamma->table_r != NULL)
ipipe_update_gamma_tbl(isp5_base_addr, gamma->table_r,
table_size, GAMMA_R_START_ADDR);
if (!gamma->bypass_b && gamma->table_b != NULL)
ipipe_update_gamma_tbl(isp5_base_addr, gamma->table_b,
table_size, GAMMA_B_START_ADDR);
if (!gamma->bypass_g && gamma->table_g != NULL)
ipipe_update_gamma_tbl(isp5_base_addr, gamma->table_g,
table_size, GAMMA_G_START_ADDR);
}
void
ipipe_set_3d_lut_regs(void *__iomem base_addr, void *__iomem isp5_base_addr,
struct vpfe_ipipe_3d_lut *lut_3d)
{
struct vpfe_ipipe_3d_lut_entry *tbl;
u32 bnk_index;
u32 tbl_index;
u32 val;
u32 i;
ipipe_clock_enable(base_addr);
regw_ip(base_addr, lut_3d->en, D3LUT_EN);
if (!lut_3d->en)
return;
/* lut_3d enabled */
if (!lut_3d->table)
return;
/* valied table */
tbl = lut_3d->table;
for (i = 0 ; i < VPFE_IPIPE_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(isp5_base_addr, val,
tbl_index + D3L_TB0_START_ADDR);
else if (bnk_index == 1)
w_ip_table(isp5_base_addr, val,
tbl_index + D3L_TB1_START_ADDR);
else if (bnk_index == 2)
w_ip_table(isp5_base_addr, val,
tbl_index + D3L_TB2_START_ADDR);
else
w_ip_table(isp5_base_addr, val,
tbl_index + D3L_TB3_START_ADDR);
}
}
/* Lumina adjustments */
void
ipipe_set_lum_adj_regs(void *__iomem base_addr, struct ipipe_lum_adj *lum_adj)
{
u32 val;
ipipe_clock_enable(base_addr);
/* 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(base_addr, val, YUV_ADJ);
}
#define IPIPE_S12Q8(decimal, integer) \
(((decimal & 0xff) | ((integer & 0xf) << 8)))
void ipipe_set_rgb2ycbcr_regs(void *__iomem base_addr,
struct vpfe_ipipe_rgb2yuv *yuv)
{
u32 val;
/* S10Q8 */
ipipe_clock_enable(base_addr);
val = IPIPE_S12Q8(yuv->coef_ry.decimal, yuv->coef_ry.integer);
regw_ip(base_addr, val, YUV_MUL_RY);
val = IPIPE_S12Q8(yuv->coef_gy.decimal, yuv->coef_gy.integer);
regw_ip(base_addr, val, YUV_MUL_GY);
val = IPIPE_S12Q8(yuv->coef_by.decimal, yuv->coef_by.integer);
regw_ip(base_addr, val, YUV_MUL_BY);
val = IPIPE_S12Q8(yuv->coef_rcb.decimal, yuv->coef_rcb.integer);
regw_ip(base_addr, val, YUV_MUL_RCB);
val = IPIPE_S12Q8(yuv->coef_gcb.decimal, yuv->coef_gcb.integer);
regw_ip(base_addr, val, YUV_MUL_GCB);
val = IPIPE_S12Q8(yuv->coef_bcb.decimal, yuv->coef_bcb.integer);
regw_ip(base_addr, val, YUV_MUL_BCB);
val = IPIPE_S12Q8(yuv->coef_rcr.decimal, yuv->coef_rcr.integer);
regw_ip(base_addr, val, YUV_MUL_RCR);
val = IPIPE_S12Q8(yuv->coef_gcr.decimal, yuv->coef_gcr.integer);
regw_ip(base_addr, val, YUV_MUL_GCR);
val = IPIPE_S12Q8(yuv->coef_bcr.decimal, yuv->coef_bcr.integer);
regw_ip(base_addr, val, YUV_MUL_BCR);
regw_ip(base_addr, yuv->out_ofst_y & RGB2YCBCR_OFST_MASK, YUV_OFT_Y);
regw_ip(base_addr, yuv->out_ofst_cb & RGB2YCBCR_OFST_MASK, YUV_OFT_CB);
regw_ip(base_addr, yuv->out_ofst_cr & RGB2YCBCR_OFST_MASK, YUV_OFT_CR);
}
/* YUV 422 conversion */
void
ipipe_set_yuv422_conv_regs(void *__iomem base_addr,
struct vpfe_ipipe_yuv422_conv *conv)
{
u32 val;
ipipe_clock_enable(base_addr);
/* Combine all the fields to make YUV_PHS register of IPIPE */
val = (conv->chrom_pos << 0) | (conv->en_chrom_lpf << 1);
regw_ip(base_addr, val, YUV_PHS);
}
void
ipipe_set_gbce_regs(void *__iomem base_addr, void *__iomem isp5_base_addr,
struct vpfe_ipipe_gbce *gbce)
{
unsigned int count;
u32 mask = GBCE_Y_VAL_MASK;
if (gbce->type == VPFE_IPIPE_GBCE_GAIN_TBL)
mask = GBCE_GAIN_VAL_MASK;
ipipe_clock_enable(base_addr);
regw_ip(base_addr, gbce->en & 1, GBCE_EN);
if (!gbce->en)
return;
regw_ip(base_addr, gbce->type, GBCE_TYP);
if (!gbce->table)
return;
for (count = 0; count < VPFE_IPIPE_MAX_SIZE_GBCE_LUT ; count += 2)
w_ip_table(isp5_base_addr, ((gbce->table[count + 1] & mask) <<
GBCE_ENTRY_SHIFT) | (gbce->table[count] & mask),
((count/2) << 2) + GBCE_TB_START_ADDR);
}
void
ipipe_set_ee_regs(void *__iomem base_addr, void *__iomem isp5_base_addr,
struct vpfe_ipipe_yee *ee)
{
unsigned int count;
u32 val;
ipipe_clock_enable(base_addr);
regw_ip(base_addr, ee->en, YEE_EN);
if (!ee->en)
return;
val = ee->en_halo_red & 1;
val |= ee->merge_meth << YEE_HALO_RED_EN_SHIFT;
regw_ip(base_addr, val, YEE_TYP);
regw_ip(base_addr, ee->hpf_shft, YEE_SHF);
regw_ip(base_addr, ee->hpf_coef_00 & YEE_COEF_MASK, YEE_MUL_00);
regw_ip(base_addr, ee->hpf_coef_01 & YEE_COEF_MASK, YEE_MUL_01);
regw_ip(base_addr, ee->hpf_coef_02 & YEE_COEF_MASK, YEE_MUL_02);
regw_ip(base_addr, ee->hpf_coef_10 & YEE_COEF_MASK, YEE_MUL_10);
regw_ip(base_addr, ee->hpf_coef_11 & YEE_COEF_MASK, YEE_MUL_11);
regw_ip(base_addr, ee->hpf_coef_12 & YEE_COEF_MASK, YEE_MUL_12);
regw_ip(base_addr, ee->hpf_coef_20 & YEE_COEF_MASK, YEE_MUL_20);
regw_ip(base_addr, ee->hpf_coef_21 & YEE_COEF_MASK, YEE_MUL_21);
regw_ip(base_addr, ee->hpf_coef_22 & YEE_COEF_MASK, YEE_MUL_22);
regw_ip(base_addr, ee->yee_thr & YEE_THR_MASK, YEE_THR);
regw_ip(base_addr, ee->es_gain & YEE_ES_GAIN_MASK, YEE_E_GAN);
regw_ip(base_addr, ee->es_thr1 & YEE_ES_THR1_MASK, YEE_E_THR1);
regw_ip(base_addr, ee->es_thr2 & YEE_THR_MASK, YEE_E_THR2);
regw_ip(base_addr, ee->es_gain_grad & YEE_THR_MASK, YEE_G_GAN);
regw_ip(base_addr, ee->es_ofst_grad & YEE_THR_MASK, YEE_G_OFT);
if (ee->table == NULL)
return;
for (count = 0; count < VPFE_IPIPE_MAX_SIZE_YEE_LUT; count += 2)
w_ip_table(isp5_base_addr, ((ee->table[count + 1] &
YEE_ENTRY_MASK) << YEE_ENTRY_SHIFT) |
(ee->table[count] & YEE_ENTRY_MASK),
((count/2) << 2) + YEE_TB_START_ADDR);
}
/* Chromatic Artifact Correction. CAR */
static void ipipe_set_mf(void *__iomem base_addr)
{
/* typ to dynamic switch */
regw_ip(base_addr, VPFE_IPIPE_CAR_DYN_SWITCH, CAR_TYP);
/* Set SW0 to maximum */
regw_ip(base_addr, CAR_MF_THR, CAR_SW);
}
static void
ipipe_set_gain_ctrl(void *__iomem base_addr, struct vpfe_ipipe_car *car)
{
regw_ip(base_addr, VPFE_IPIPE_CAR_CHR_GAIN_CTRL, CAR_TYP);
regw_ip(base_addr, car->hpf, CAR_HPF_TYP);
regw_ip(base_addr, car->hpf_shft & CAR_HPF_SHIFT_MASK, CAR_HPF_SHF);
regw_ip(base_addr, car->hpf_thr, CAR_HPF_THR);
regw_ip(base_addr, car->gain1.gain, CAR_GN1_GAN);
regw_ip(base_addr, car->gain1.shft & CAR_GAIN1_SHFT_MASK, CAR_GN1_SHF);
regw_ip(base_addr, car->gain1.gain_min & CAR_GAIN_MIN_MASK,
CAR_GN1_MIN);
regw_ip(base_addr, car->gain2.gain, CAR_GN2_GAN);
regw_ip(base_addr, car->gain2.shft & CAR_GAIN2_SHFT_MASK, CAR_GN2_SHF);
regw_ip(base_addr, car->gain2.gain_min & CAR_GAIN_MIN_MASK,
CAR_GN2_MIN);
}
void ipipe_set_car_regs(void *__iomem base_addr, struct vpfe_ipipe_car *car)
{
u32 val;
ipipe_clock_enable(base_addr);
regw_ip(base_addr, car->en, CAR_EN);
if (!car->en)
return;
switch (car->meth) {
case VPFE_IPIPE_CAR_MED_FLTR:
ipipe_set_mf(base_addr);
break;
case VPFE_IPIPE_CAR_CHR_GAIN_CTRL:
ipipe_set_gain_ctrl(base_addr, car);
break;
default:
/* Dynamic switch between MF and Gain Ctrl. */
ipipe_set_mf(base_addr);
ipipe_set_gain_ctrl(base_addr, car);
/* Set the threshold for switching between
* the two Here we overwrite the MF SW0 value
*/
regw_ip(base_addr, VPFE_IPIPE_CAR_DYN_SWITCH, CAR_TYP);
val = car->sw1;
val <<= CAR_SW1_SHIFT;
val |= car->sw0;
regw_ip(base_addr, val, CAR_SW);
}
}
/* Chromatic Gain Suppression */
void ipipe_set_cgs_regs(void *__iomem base_addr, struct vpfe_ipipe_cgs *cgs)
{
ipipe_clock_enable(base_addr);
regw_ip(base_addr, cgs->en, CGS_EN);
if (!cgs->en)
return;
/* Set the bright side parameters */
regw_ip(base_addr, cgs->h_thr, CGS_GN1_H_THR);
regw_ip(base_addr, cgs->h_slope, CGS_GN1_H_GAN);
regw_ip(base_addr, cgs->h_shft & CAR_SHIFT_MASK, CGS_GN1_H_SHF);
regw_ip(base_addr, cgs->h_min, CGS_GN1_H_MIN);
}
void rsz_src_enable(void *__iomem rsz_base, int enable)
{
regw_rsz(rsz_base, enable, RSZ_SRC_EN);
}
int rsz_enable(void *__iomem rsz_base, int rsz_id, int enable)
{
if (rsz_id == RSZ_A) {
regw_rsz(rsz_base, 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(rsz_base, enable, RSZ_SRC_EN);
} else if (rsz_id == RSZ_B) {
regw_rsz(rsz_base, enable, RSZ_EN_B);
} else {
BUG();
}
return 0;
}
/*
* Copyright (C) 2012 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
*
* Contributors:
* Manjunath Hadli <manjunath.hadli@ti.com>
* Prabhakar Lad <prabhakar.lad@ti.com>
*/
#ifndef _DAVINCI_VPFE_DM365_IPIPE_HW_H
#define _DAVINCI_VPFE_DM365_IPIPE_HW_H
#include "vpfe_mc_capture.h"
#define SET_LOW_ADDR 0x0000ffff
#define SET_HIGH_ADDR 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 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
/* LUTDPC */
#define LUTDPC_TBL_256_EN 0
#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
#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(void *__iomem addr, u32 offset)
{
return readl(addr + offset);
}
static inline void regw_ip(void *__iomem addr, u32 val, u32 offset)
{
writel(val, addr + offset);
}
static inline u32 w_ip_table(void *__iomem addr, u32 val, u32 offset)
{
writel(val, addr + offset);
return val;
}
static inline u32 regr_rsz(void *__iomem addr, u32 offset)
{
return readl(addr + offset);
}
static inline u32 regw_rsz(void *__iomem addr, u32 val, u32 offset)
{
writel(val, addr + offset);
return val;
}
int config_ipipe_hw(struct vpfe_ipipe_device *ipipe);
int resizer_set_outaddr(void *__iomem rsz_base, struct resizer_params *params,
int resize_no, unsigned int address);
int rsz_enable(void *__iomem rsz_base, int rsz_id, int enable);
void rsz_src_enable(void *__iomem rsz_base, int enable);
void rsz_set_in_pix_format(unsigned char y_c);
int config_rsz_hw(struct vpfe_resizer_device *resizer,
struct resizer_params *config);
void ipipe_set_d2f_regs(void *__iomem base_addr, unsigned int id,
struct vpfe_ipipe_nf *noise_filter);
void ipipe_set_rgb2rgb_regs(void *__iomem base_addr, unsigned int id,
struct vpfe_ipipe_rgb2rgb *rgb);
void ipipe_set_yuv422_conv_regs(void *__iomem base_addr,
struct vpfe_ipipe_yuv422_conv *conv);
void ipipe_set_lum_adj_regs(void *__iomem base_addr,
struct ipipe_lum_adj *lum_adj);
void ipipe_set_rgb2ycbcr_regs(void *__iomem base_addr,
struct vpfe_ipipe_rgb2yuv *yuv);
void ipipe_set_lutdpc_regs(void *__iomem base_addr,
void *__iomem isp5_base_addr, struct vpfe_ipipe_lutdpc *lutdpc);
void ipipe_set_otfdpc_regs(void *__iomem base_addr,
struct vpfe_ipipe_otfdpc *otfdpc);
void ipipe_set_3d_lut_regs(void *__iomem base_addr,
void *__iomem isp5_base_addr, struct vpfe_ipipe_3d_lut *lut_3d);
void ipipe_set_gamma_regs(void *__iomem base_addr,
void *__iomem isp5_base_addr, struct vpfe_ipipe_gamma *gamma);
void ipipe_set_ee_regs(void *__iomem base_addr,
void *__iomem isp5_base_addr, struct vpfe_ipipe_yee *ee);
void ipipe_set_gbce_regs(void *__iomem base_addr,
void *__iomem isp5_base_addr, struct vpfe_ipipe_gbce *gbce);
void ipipe_set_gic_regs(void *__iomem base_addr, struct vpfe_ipipe_gic *gic);
void ipipe_set_cfa_regs(void *__iomem base_addr, struct vpfe_ipipe_cfa *cfa);
void ipipe_set_car_regs(void *__iomem base_addr, struct vpfe_ipipe_car *car);
void ipipe_set_cgs_regs(void *__iomem base_addr, struct vpfe_ipipe_cgs *cgs);
void ipipe_set_wb_regs(void *__iomem base_addr, struct vpfe_ipipe_wb *wb);
#endif /* _DAVINCI_VPFE_DM365_IPIPE_HW_H */
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册