2 * Copyright (C) 2012 Texas Instruments Inc
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation version 2.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 * Manjunath Hadli <manjunath.hadli@ti.com>
19 * Prabhakar Lad <prabhakar.lad@ti.com>
22 #include "dm365_ipipe_hw.h"
24 #define IPIPE_MODE_CONTINUOUS 0
25 #define IPIPE_MODE_SINGLE_SHOT 1
27 static void ipipe_clock_enable(void __iomem *base_addr)
29 /* enable IPIPE MMR for register write access */
30 regw_ip(base_addr, IPIPE_GCK_MMR_DEFAULT, IPIPE_GCK_MMR);
32 /* enable the clock wb,cfa,dfc,d2f,pre modules */
33 regw_ip(base_addr, IPIPE_GCK_PIX_DEFAULT, IPIPE_GCK_PIX);
37 rsz_set_common_params(void __iomem *rsz_base, struct resizer_params *params)
39 struct rsz_common_params *rsz_common = ¶ms->rsz_common;
43 regw_rsz(rsz_base, params->oper_mode, RSZ_SRC_MODE);
45 /* data source selection and bypass */
46 val = (rsz_common->passthrough << RSZ_BYPASS_SHIFT) |
48 regw_rsz(rsz_base, val, RSZ_SRC_FMT0);
50 /* src image selection */
51 val = (rsz_common->raw_flip & 1) |
52 (rsz_common->src_img_fmt << RSZ_SRC_IMG_FMT_SHIFT) |
53 ((rsz_common->y_c & 1) << RSZ_SRC_Y_C_SEL_SHIFT);
54 regw_rsz(rsz_base, val, RSZ_SRC_FMT1);
56 regw_rsz(rsz_base, rsz_common->vps & IPIPE_RSZ_VPS_MASK, RSZ_SRC_VPS);
57 regw_rsz(rsz_base, rsz_common->hps & IPIPE_RSZ_HPS_MASK, RSZ_SRC_HPS);
58 regw_rsz(rsz_base, rsz_common->vsz & IPIPE_RSZ_VSZ_MASK, RSZ_SRC_VSZ);
59 regw_rsz(rsz_base, rsz_common->hsz & IPIPE_RSZ_HSZ_MASK, RSZ_SRC_HSZ);
60 regw_rsz(rsz_base, rsz_common->yuv_y_min, RSZ_YUV_Y_MIN);
61 regw_rsz(rsz_base, rsz_common->yuv_y_max, RSZ_YUV_Y_MAX);
62 regw_rsz(rsz_base, rsz_common->yuv_c_min, RSZ_YUV_C_MIN);
63 regw_rsz(rsz_base, rsz_common->yuv_c_max, RSZ_YUV_C_MAX);
64 /* chromatic position */
65 regw_rsz(rsz_base, rsz_common->out_chr_pos, RSZ_YUV_PHS);
69 rsz_set_rsz_regs(void __iomem *rsz_base, unsigned int rsz_id,
70 struct resizer_params *params)
72 struct resizer_scale_param *rsc_params;
73 struct rsz_ext_mem_param *ext_mem;
74 struct resizer_rgb *rgb;
78 rsc_params = ¶ms->rsz_rsc_param[rsz_id];
79 rgb = ¶ms->rsz2rgb[rsz_id];
80 ext_mem = ¶ms->ext_mem_param[rsz_id];
82 if (rsz_id == RSZ_A) {
83 val = rsc_params->h_flip << RSZA_H_FLIP_SHIFT;
84 val |= rsc_params->v_flip << RSZA_V_FLIP_SHIFT;
87 val = rsc_params->h_flip << RSZB_H_FLIP_SHIFT;
88 val |= rsc_params->v_flip << RSZB_V_FLIP_SHIFT;
91 /* update flip settings */
92 regw_rsz(rsz_base, val, RSZ_SEQ);
94 regw_rsz(rsz_base, params->oper_mode, reg_base + RSZ_MODE);
96 val = (rsc_params->cen << RSZ_CEN_SHIFT) | rsc_params->yen;
97 regw_rsz(rsz_base, val, reg_base + RSZ_420);
99 regw_rsz(rsz_base, rsc_params->i_vps & RSZ_VPS_MASK,
100 reg_base + RSZ_I_VPS);
101 regw_rsz(rsz_base, rsc_params->i_hps & RSZ_HPS_MASK,
102 reg_base + RSZ_I_HPS);
103 regw_rsz(rsz_base, rsc_params->o_vsz & RSZ_O_VSZ_MASK,
104 reg_base + RSZ_O_VSZ);
105 regw_rsz(rsz_base, rsc_params->o_hsz & RSZ_O_HSZ_MASK,
106 reg_base + RSZ_O_HSZ);
107 regw_rsz(rsz_base, rsc_params->v_phs_y & RSZ_V_PHS_MASK,
108 reg_base + RSZ_V_PHS_Y);
109 regw_rsz(rsz_base, rsc_params->v_phs_c & RSZ_V_PHS_MASK,
110 reg_base + RSZ_V_PHS_C);
112 /* keep this additional adjustment to zero for now */
113 regw_rsz(rsz_base, rsc_params->v_dif & RSZ_V_DIF_MASK,
114 reg_base + RSZ_V_DIF);
116 val = (rsc_params->v_typ_y & 1) |
117 ((rsc_params->v_typ_c & 1) << RSZ_TYP_C_SHIFT);
118 regw_rsz(rsz_base, val, reg_base + RSZ_V_TYP);
120 val = (rsc_params->v_lpf_int_y & RSZ_LPF_INT_MASK) |
121 ((rsc_params->v_lpf_int_c & RSZ_LPF_INT_MASK) <<
122 RSZ_LPF_INT_C_SHIFT);
123 regw_rsz(rsz_base, val, reg_base + RSZ_V_LPF);
125 regw_rsz(rsz_base, rsc_params->h_phs &
126 RSZ_H_PHS_MASK, reg_base + RSZ_H_PHS);
128 regw_rsz(rsz_base, 0, reg_base + RSZ_H_PHS_ADJ);
129 regw_rsz(rsz_base, rsc_params->h_dif &
130 RSZ_H_DIF_MASK, reg_base + RSZ_H_DIF);
132 val = (rsc_params->h_typ_y & 1) |
133 ((rsc_params->h_typ_c & 1) << RSZ_TYP_C_SHIFT);
134 regw_rsz(rsz_base, val, reg_base + RSZ_H_TYP);
136 val = (rsc_params->h_lpf_int_y & RSZ_LPF_INT_MASK) |
137 ((rsc_params->h_lpf_int_c & RSZ_LPF_INT_MASK) <<
138 RSZ_LPF_INT_C_SHIFT);
139 regw_rsz(rsz_base, val, reg_base + RSZ_H_LPF);
141 regw_rsz(rsz_base, rsc_params->dscale_en & 1, reg_base + RSZ_DWN_EN);
143 val = (rsc_params->h_dscale_ave_sz & RSZ_DWN_SCALE_AV_SZ_MASK) |
144 ((rsc_params->v_dscale_ave_sz & RSZ_DWN_SCALE_AV_SZ_MASK) <<
145 RSZ_DWN_SCALE_AV_SZ_V_SHIFT);
146 regw_rsz(rsz_base, val, reg_base + RSZ_DWN_AV);
148 /* setting rgb conversion parameters */
149 regw_rsz(rsz_base, rgb->rgb_en, reg_base + RSZ_RGB_EN);
151 val = (rgb->rgb_typ << RSZ_RGB_TYP_SHIFT) |
152 (rgb->rgb_msk0 << RSZ_RGB_MSK0_SHIFT) |
153 (rgb->rgb_msk1 << RSZ_RGB_MSK1_SHIFT);
154 regw_rsz(rsz_base, val, reg_base + RSZ_RGB_TYP);
156 regw_rsz(rsz_base, rgb->rgb_alpha_val & RSZ_RGB_ALPHA_MASK,
157 reg_base + RSZ_RGB_BLD);
159 /* setting external memory parameters */
160 regw_rsz(rsz_base, ext_mem->rsz_sdr_oft_y, reg_base + RSZ_SDR_Y_OFT);
161 regw_rsz(rsz_base, ext_mem->rsz_sdr_ptr_s_y,
162 reg_base + RSZ_SDR_Y_PTR_S);
163 regw_rsz(rsz_base, ext_mem->rsz_sdr_ptr_e_y,
164 reg_base + RSZ_SDR_Y_PTR_E);
165 regw_rsz(rsz_base, ext_mem->rsz_sdr_oft_c, reg_base + RSZ_SDR_C_OFT);
166 regw_rsz(rsz_base, ext_mem->rsz_sdr_ptr_s_c,
167 reg_base + RSZ_SDR_C_PTR_S);
168 regw_rsz(rsz_base, (ext_mem->rsz_sdr_ptr_e_c >> 1),
169 reg_base + RSZ_SDR_C_PTR_E);
172 /*set the registers of either RSZ0 or RSZ1 */
174 ipipe_setup_resizer(void __iomem *rsz_base, struct resizer_params *params)
176 /* enable MMR gate to write to Resizer */
177 regw_rsz(rsz_base, 1, RSZ_GCK_MMR);
179 /* Enable resizer if it is not in bypass mode */
180 if (params->rsz_common.passthrough)
181 regw_rsz(rsz_base, 0, RSZ_GCK_SDR);
183 regw_rsz(rsz_base, 1, RSZ_GCK_SDR);
185 rsz_set_common_params(rsz_base, params);
187 regw_rsz(rsz_base, params->rsz_en[RSZ_A], RSZ_EN_A);
189 if (params->rsz_en[RSZ_A])
190 /*setting rescale parameters */
191 rsz_set_rsz_regs(rsz_base, RSZ_A, params);
193 regw_rsz(rsz_base, params->rsz_en[RSZ_B], RSZ_EN_B);
195 if (params->rsz_en[RSZ_B])
196 rsz_set_rsz_regs(rsz_base, RSZ_B, params);
199 static u32 ipipe_get_color_pat(u32 pix)
202 case MEDIA_BUS_FMT_SGRBG10_ALAW8_1X8:
203 case MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8:
204 case MEDIA_BUS_FMT_SGRBG12_1X12:
205 return ipipe_sgrbg_pattern;
208 return ipipe_srggb_pattern;
212 static int ipipe_get_data_path(struct vpfe_ipipe_device *ipipe)
216 switch (ipipe->formats[IPIPE_PAD_SINK].code) {
217 case MEDIA_BUS_FMT_SBGGR8_1X8:
218 case MEDIA_BUS_FMT_SGRBG10_ALAW8_1X8:
219 case MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8:
220 case MEDIA_BUS_FMT_SGRBG12_1X12:
221 temp_pix_fmt = MEDIA_BUS_FMT_SGRBG12_1X12;
225 temp_pix_fmt = MEDIA_BUS_FMT_UYVY8_2X8;
228 if (temp_pix_fmt == MEDIA_BUS_FMT_SGRBG12_1X12) {
229 if (ipipe->formats[IPIPE_PAD_SOURCE].code ==
230 MEDIA_BUS_FMT_SGRBG12_1X12)
231 return IPIPE_RAW2RAW;
232 return IPIPE_RAW2YUV;
235 return IPIPE_YUV2YUV;
238 static int get_ipipe_mode(struct vpfe_ipipe_device *ipipe)
240 struct vpfe_device *vpfe_dev = to_vpfe_device(ipipe);
241 u16 ipipeif_sink = vpfe_dev->vpfe_ipipeif.input;
243 if (ipipeif_sink == IPIPEIF_INPUT_MEMORY)
244 return IPIPE_MODE_SINGLE_SHOT;
245 else if (ipipeif_sink == IPIPEIF_INPUT_ISIF)
246 return IPIPE_MODE_CONTINUOUS;
251 int config_ipipe_hw(struct vpfe_ipipe_device *ipipe)
253 struct vpfe_ipipe_input_config *config = &ipipe->config.input_config;
254 void __iomem *ipipe_base = ipipe->base_addr;
255 struct v4l2_mbus_framefmt *outformat;
260 /* enable clock to IPIPE */
261 vpss_enable_clock(VPSS_IPIPE_CLOCK, 1);
262 ipipe_clock_enable(ipipe_base);
264 if (ipipe->input == IPIPE_INPUT_NONE) {
265 regw_ip(ipipe_base, 0, IPIPE_SRC_EN);
269 ipipe_mode = get_ipipe_mode(ipipe);
270 if (ipipe_mode < 0) {
271 pr_err("Failed to get ipipe mode");
274 regw_ip(ipipe_base, ipipe_mode, IPIPE_SRC_MODE);
276 data_path = ipipe_get_data_path(ipipe);
277 regw_ip(ipipe_base, data_path, IPIPE_SRC_FMT);
279 regw_ip(ipipe_base, config->vst & IPIPE_RSZ_VPS_MASK, IPIPE_SRC_VPS);
280 regw_ip(ipipe_base, config->hst & IPIPE_RSZ_HPS_MASK, IPIPE_SRC_HPS);
282 outformat = &ipipe->formats[IPIPE_PAD_SOURCE];
283 regw_ip(ipipe_base, (outformat->height + 1) & IPIPE_RSZ_VSZ_MASK,
285 regw_ip(ipipe_base, (outformat->width + 1) & IPIPE_RSZ_HSZ_MASK,
288 if (data_path == IPIPE_RAW2YUV ||
289 data_path == IPIPE_RAW2RAW) {
291 ipipe_get_color_pat(ipipe->formats[IPIPE_PAD_SINK].code);
292 regw_ip(ipipe_base, color_pat, IPIPE_SRC_COL);
299 * config_rsz_hw() - Performs hardware setup of resizer.
301 int config_rsz_hw(struct vpfe_resizer_device *resizer,
302 struct resizer_params *config)
304 struct vpfe_device *vpfe_dev = to_vpfe_device(resizer);
305 void __iomem *ipipe_base = vpfe_dev->vpfe_ipipe.base_addr;
306 void __iomem *rsz_base = vpfe_dev->vpfe_resizer.base_addr;
308 /* enable VPSS clock */
309 vpss_enable_clock(VPSS_IPIPE_CLOCK, 1);
310 ipipe_clock_enable(ipipe_base);
312 ipipe_setup_resizer(rsz_base, config);
318 rsz_set_y_address(void __iomem *rsz_base, unsigned int address,
323 val = address & SET_LOW_ADDR;
324 regw_rsz(rsz_base, val, offset + RSZ_SDR_Y_BAD_L);
325 regw_rsz(rsz_base, val, offset + RSZ_SDR_Y_SAD_L);
327 val = (address & SET_HIGH_ADDR) >> 16;
328 regw_rsz(rsz_base, val, offset + RSZ_SDR_Y_BAD_H);
329 regw_rsz(rsz_base, val, offset + RSZ_SDR_Y_SAD_H);
333 rsz_set_c_address(void __iomem *rsz_base, unsigned int address,
338 val = address & SET_LOW_ADDR;
339 regw_rsz(rsz_base, val, offset + RSZ_SDR_C_BAD_L);
340 regw_rsz(rsz_base, val, offset + RSZ_SDR_C_SAD_L);
342 val = (address & SET_HIGH_ADDR) >> 16;
343 regw_rsz(rsz_base, val, offset + RSZ_SDR_C_BAD_H);
344 regw_rsz(rsz_base, val, offset + RSZ_SDR_C_SAD_H);
348 * resizer_set_outaddr() - set the address for given resize_no
349 * @rsz_base: resizer base address
350 * @params: pointer to ipipe_params structure
351 * @resize_no: 0 - Resizer-A, 1 - Resizer B
352 * @address: the address to set
355 resizer_set_outaddr(void __iomem *rsz_base, struct resizer_params *params,
356 int resize_no, unsigned int address)
358 struct resizer_scale_param *rsc_param;
359 struct rsz_ext_mem_param *mem_param;
360 struct rsz_common_params *rsz_common;
361 unsigned int rsz_start_add;
364 if (resize_no != RSZ_A && resize_no != RSZ_B)
367 mem_param = ¶ms->ext_mem_param[resize_no];
368 rsc_param = ¶ms->rsz_rsc_param[resize_no];
369 rsz_common = ¶ms->rsz_common;
371 if (resize_no == RSZ_A)
372 rsz_start_add = RSZ_EN_A;
374 rsz_start_add = RSZ_EN_B;
376 /* y_c = 0 for y, = 1 for c */
377 if (rsz_common->src_img_fmt == RSZ_IMG_420) {
378 if (rsz_common->y_c) {
380 val = address + mem_param->flip_ofst_c;
381 rsz_set_c_address(rsz_base, val, rsz_start_add);
383 val = address + mem_param->flip_ofst_y;
384 rsz_set_y_address(rsz_base, val, rsz_start_add);
387 if (rsc_param->cen && rsc_param->yen) {
389 val = address + mem_param->c_offset +
390 mem_param->flip_ofst_c +
391 mem_param->user_y_ofst +
392 mem_param->user_c_ofst;
393 if (resize_no == RSZ_B)
395 params->ext_mem_param[RSZ_A].user_y_ofst +
396 params->ext_mem_param[RSZ_A].user_c_ofst;
398 rsz_set_c_address(rsz_base, val, rsz_start_add);
400 val = address + mem_param->flip_ofst_y + mem_param->user_y_ofst;
401 if (resize_no == RSZ_B)
402 val += params->ext_mem_param[RSZ_A].user_y_ofst +
403 params->ext_mem_param[RSZ_A].user_c_ofst;
405 rsz_set_y_address(rsz_base, val, rsz_start_add);
407 /* resizer must be enabled */
408 regw_rsz(rsz_base, params->rsz_en[resize_no], rsz_start_add);
414 ipipe_set_lutdpc_regs(void __iomem *base_addr, void __iomem *isp5_base_addr,
415 struct vpfe_ipipe_lutdpc *dpc)
417 u32 max_tbl_size = LUT_DPC_MAX_SIZE >> 1;
418 u32 lut_start_addr = DPC_TB0_START_ADDR;
422 ipipe_clock_enable(base_addr);
423 regw_ip(base_addr, dpc->en, DPC_LUT_EN);
428 val = LUTDPC_TBL_256_EN | (dpc->repl_white & 1);
429 regw_ip(base_addr, val, DPC_LUT_SEL);
430 regw_ip(base_addr, LUT_DPC_START_ADDR, DPC_LUT_ADR);
431 regw_ip(base_addr, dpc->dpc_size, DPC_LUT_SIZ & LUT_DPC_SIZE_MASK);
433 if (dpc->table == NULL)
436 for (count = 0; count < dpc->dpc_size; count++) {
437 if (count >= max_tbl_size)
438 lut_start_addr = DPC_TB1_START_ADDR;
439 val = (dpc->table[count].horz_pos & LUT_DPC_H_POS_MASK) |
440 ((dpc->table[count].vert_pos & LUT_DPC_V_POS_MASK) <<
441 LUT_DPC_V_POS_SHIFT) | (dpc->table[count].method <<
442 LUT_DPC_CORR_METH_SHIFT);
443 w_ip_table(isp5_base_addr, val, (lut_start_addr +
444 ((count % max_tbl_size) << 2)));
449 set_dpc_thresholds(void __iomem *base_addr,
450 struct vpfe_ipipe_otfdpc_2_0_cfg *dpc_thr)
452 regw_ip(base_addr, dpc_thr->corr_thr.r & OTFDPC_DPC2_THR_MASK,
454 regw_ip(base_addr, dpc_thr->corr_thr.gr & OTFDPC_DPC2_THR_MASK,
456 regw_ip(base_addr, dpc_thr->corr_thr.gb & OTFDPC_DPC2_THR_MASK,
458 regw_ip(base_addr, dpc_thr->corr_thr.b & OTFDPC_DPC2_THR_MASK,
460 regw_ip(base_addr, dpc_thr->det_thr.r & OTFDPC_DPC2_THR_MASK,
462 regw_ip(base_addr, dpc_thr->det_thr.gr & OTFDPC_DPC2_THR_MASK,
464 regw_ip(base_addr, dpc_thr->det_thr.gb & OTFDPC_DPC2_THR_MASK,
466 regw_ip(base_addr, dpc_thr->det_thr.b & OTFDPC_DPC2_THR_MASK,
470 void ipipe_set_otfdpc_regs(void __iomem *base_addr,
471 struct vpfe_ipipe_otfdpc *otfdpc)
473 struct vpfe_ipipe_otfdpc_2_0_cfg *dpc_2_0 = &otfdpc->alg_cfg.dpc_2_0;
474 struct vpfe_ipipe_otfdpc_3_0_cfg *dpc_3_0 = &otfdpc->alg_cfg.dpc_3_0;
477 ipipe_clock_enable(base_addr);
479 regw_ip(base_addr, (otfdpc->en & 1), DPC_OTF_EN);
484 val = (otfdpc->det_method << OTF_DET_METHOD_SHIFT) | otfdpc->alg;
485 regw_ip(base_addr, val, DPC_OTF_TYP);
487 if (otfdpc->det_method == VPFE_IPIPE_DPC_OTF_MIN_MAX) {
488 /* ALG= 0, TYP = 0, DPC_OTF_2D_THR_[x]=0
489 * DPC_OTF_2C_THR_[x] = Maximum thresohld
492 dpc_2_0->det_thr.r = dpc_2_0->det_thr.gb =
493 dpc_2_0->det_thr.gr = dpc_2_0->det_thr.b = 0;
494 set_dpc_thresholds(base_addr, dpc_2_0);
498 if (otfdpc->alg == VPFE_IPIPE_OTFDPC_2_0) {
499 set_dpc_thresholds(base_addr, dpc_2_0);
502 regw_ip(base_addr, dpc_3_0->act_adj_shf &
503 OTF_DPC3_0_SHF_MASK, DPC_OTF_3_SHF);
504 /* Detection thresholds */
505 regw_ip(base_addr, ((dpc_3_0->det_thr & OTF_DPC3_0_THR_MASK) <<
506 OTF_DPC3_0_THR_SHIFT), DPC_OTF_3D_THR);
507 regw_ip(base_addr, dpc_3_0->det_slp &
508 OTF_DPC3_0_SLP_MASK, DPC_OTF_3D_SLP);
509 regw_ip(base_addr, dpc_3_0->det_thr_min &
510 OTF_DPC3_0_DET_MASK, DPC_OTF_3D_MIN);
511 regw_ip(base_addr, dpc_3_0->det_thr_max &
512 OTF_DPC3_0_DET_MASK, DPC_OTF_3D_MAX);
513 /* Correction thresholds */
514 regw_ip(base_addr, ((dpc_3_0->corr_thr & OTF_DPC3_0_THR_MASK) <<
515 OTF_DPC3_0_THR_SHIFT), DPC_OTF_3C_THR);
516 regw_ip(base_addr, dpc_3_0->corr_slp &
517 OTF_DPC3_0_SLP_MASK, DPC_OTF_3C_SLP);
518 regw_ip(base_addr, dpc_3_0->corr_thr_min &
519 OTF_DPC3_0_CORR_MASK, DPC_OTF_3C_MIN);
520 regw_ip(base_addr, dpc_3_0->corr_thr_max &
521 OTF_DPC3_0_CORR_MASK, DPC_OTF_3C_MAX);
524 /* 2D Noise filter */
526 ipipe_set_d2f_regs(void __iomem *base_addr, unsigned int id,
527 struct vpfe_ipipe_nf *noise_filter)
530 u32 offset = D2F_1ST;
534 if (id == IPIPE_D2F_2ND)
537 ipipe_clock_enable(base_addr);
538 regw_ip(base_addr, noise_filter->en & 1, offset + D2F_EN);
539 if (!noise_filter->en)
542 /*noise filter enabled */
543 /* Combine all the fields to make D2F_CFG register of IPIPE */
544 val = ((noise_filter->spread_val & D2F_SPR_VAL_MASK) <<
545 D2F_SPR_VAL_SHIFT) | ((noise_filter->shft_val &
546 D2F_SHFT_VAL_MASK) << D2F_SHFT_VAL_SHIFT) |
547 (noise_filter->gr_sample_meth << D2F_SAMPLE_METH_SHIFT) |
548 ((noise_filter->apply_lsc_gain & 1) <<
549 D2F_APPLY_LSC_GAIN_SHIFT) | D2F_USE_SPR_REG_VAL;
550 regw_ip(base_addr, val, offset + D2F_TYP);
552 /* edge detection minimum */
553 regw_ip(base_addr, noise_filter->edge_det_min_thr &
554 D2F_EDGE_DET_THR_MASK, offset + D2F_EDG_MIN);
556 /* edge detection maximum */
557 regw_ip(base_addr, noise_filter->edge_det_max_thr &
558 D2F_EDGE_DET_THR_MASK, offset + D2F_EDG_MAX);
560 for (count = 0; count < VPFE_IPIPE_NF_STR_TABLE_SIZE; count++)
562 (noise_filter->str[count] & D2F_STR_VAL_MASK),
563 offset + D2F_STR + count * 4);
565 for (count = 0; count < VPFE_IPIPE_NF_THR_TABLE_SIZE; count++)
566 regw_ip(base_addr, noise_filter->thr[count] & D2F_THR_VAL_MASK,
567 offset + D2F_THR + count * 4);
570 #define IPIPE_U8Q5(decimal, integer) \
571 (((decimal & 0x1f) | ((integer & 0x7) << 5)))
573 /* Green Imbalance Correction */
574 void ipipe_set_gic_regs(void __iomem *base_addr, struct vpfe_ipipe_gic *gic)
578 ipipe_clock_enable(base_addr);
579 regw_ip(base_addr, gic->en & 1, GIC_EN);
585 val = (gic->wt_fn_type << GIC_TYP_SHIFT) |
586 (gic->thr_sel << GIC_THR_SEL_SHIFT) |
587 ((gic->apply_lsc_gain & 1) << GIC_APPLY_LSC_GAIN_SHIFT);
588 regw_ip(base_addr, val, GIC_TYP);
590 regw_ip(base_addr, gic->gain & GIC_GAIN_MASK, GIC_GAN);
592 if (gic->gic_alg != VPFE_IPIPE_GIC_ALG_ADAPT_GAIN) {
593 /* Constant Gain. Set threshold to maximum */
594 regw_ip(base_addr, GIC_THR_MASK, GIC_THR);
598 if (gic->thr_sel == VPFE_IPIPE_GIC_THR_REG) {
599 regw_ip(base_addr, gic->thr & GIC_THR_MASK, GIC_THR);
600 regw_ip(base_addr, gic->slope & GIC_SLOPE_MASK, GIC_SLP);
602 /* Use NF thresholds */
603 val = IPIPE_U8Q5(gic->nf2_thr_gain.decimal,
604 gic->nf2_thr_gain.integer);
605 regw_ip(base_addr, val, GIC_NFGAN);
609 #define IPIPE_U13Q9(decimal, integer) \
610 (((decimal & 0x1ff) | ((integer & 0xf) << 9)))
612 void ipipe_set_wb_regs(void __iomem *base_addr, struct vpfe_ipipe_wb *wb)
616 ipipe_clock_enable(base_addr);
618 regw_ip(base_addr, wb->ofst_r & WB_OFFSET_MASK, WB2_OFT_R);
619 regw_ip(base_addr, wb->ofst_gr & WB_OFFSET_MASK, WB2_OFT_GR);
620 regw_ip(base_addr, wb->ofst_gb & WB_OFFSET_MASK, WB2_OFT_GB);
621 regw_ip(base_addr, wb->ofst_b & WB_OFFSET_MASK, WB2_OFT_B);
624 val = IPIPE_U13Q9(wb->gain_r.decimal, wb->gain_r.integer);
625 regw_ip(base_addr, val, WB2_WGN_R);
627 val = IPIPE_U13Q9(wb->gain_gr.decimal, wb->gain_gr.integer);
628 regw_ip(base_addr, val, WB2_WGN_GR);
630 val = IPIPE_U13Q9(wb->gain_gb.decimal, wb->gain_gb.integer);
631 regw_ip(base_addr, val, WB2_WGN_GB);
633 val = IPIPE_U13Q9(wb->gain_b.decimal, wb->gain_b.integer);
634 regw_ip(base_addr, val, WB2_WGN_B);
638 void ipipe_set_cfa_regs(void __iomem *base_addr, struct vpfe_ipipe_cfa *cfa)
640 ipipe_clock_enable(base_addr);
642 regw_ip(base_addr, cfa->alg, CFA_MODE);
643 regw_ip(base_addr, cfa->hpf_thr_2dir & CFA_HPF_THR_2DIR_MASK,
645 regw_ip(base_addr, cfa->hpf_slp_2dir & CFA_HPF_SLOPE_2DIR_MASK,
647 regw_ip(base_addr, cfa->hp_mix_thr_2dir & CFA_HPF_MIX_THR_2DIR_MASK,
649 regw_ip(base_addr, cfa->hp_mix_slope_2dir & CFA_HPF_MIX_SLP_2DIR_MASK,
651 regw_ip(base_addr, cfa->dir_thr_2dir & CFA_DIR_THR_2DIR_MASK,
653 regw_ip(base_addr, cfa->dir_slope_2dir & CFA_DIR_SLP_2DIR_MASK,
655 regw_ip(base_addr, cfa->nd_wt_2dir & CFA_ND_WT_2DIR_MASK,
657 regw_ip(base_addr, cfa->hue_fract_daa & CFA_DAA_HUE_FRA_MASK,
659 regw_ip(base_addr, cfa->edge_thr_daa & CFA_DAA_EDG_THR_MASK,
661 regw_ip(base_addr, cfa->thr_min_daa & CFA_DAA_THR_MIN_MASK,
663 regw_ip(base_addr, cfa->thr_slope_daa & CFA_DAA_THR_SLP_MASK,
665 regw_ip(base_addr, cfa->slope_min_daa & CFA_DAA_SLP_MIN_MASK,
667 regw_ip(base_addr, cfa->slope_slope_daa & CFA_DAA_SLP_SLP_MASK,
669 regw_ip(base_addr, cfa->lp_wt_daa & CFA_DAA_LP_WT_MASK,
674 ipipe_set_rgb2rgb_regs(void __iomem *base_addr, unsigned int id,
675 struct vpfe_ipipe_rgb2rgb *rgb)
677 u32 offset_mask = RGB2RGB_1_OFST_MASK;
678 u32 offset = RGB1_MUL_BASE;
679 u32 integ_mask = 0xf;
682 ipipe_clock_enable(base_addr);
684 if (id == IPIPE_RGB2RGB_2) {
685 /* For second RGB module, gain integer is 3 bits instead
686 of 4, offset has 11 bits insread of 13 */
687 offset = RGB2_MUL_BASE;
689 offset_mask = RGB2RGB_2_OFST_MASK;
692 val = (rgb->coef_rr.decimal & 0xff) |
693 ((rgb->coef_rr.integer & integ_mask) << 8);
694 regw_ip(base_addr, val, offset + RGB_MUL_RR);
695 val = (rgb->coef_gr.decimal & 0xff) |
696 ((rgb->coef_gr.integer & integ_mask) << 8);
697 regw_ip(base_addr, val, offset + RGB_MUL_GR);
698 val = (rgb->coef_br.decimal & 0xff) |
699 ((rgb->coef_br.integer & integ_mask) << 8);
700 regw_ip(base_addr, val, offset + RGB_MUL_BR);
701 val = (rgb->coef_rg.decimal & 0xff) |
702 ((rgb->coef_rg.integer & integ_mask) << 8);
703 regw_ip(base_addr, val, offset + RGB_MUL_RG);
704 val = (rgb->coef_gg.decimal & 0xff) |
705 ((rgb->coef_gg.integer & integ_mask) << 8);
706 regw_ip(base_addr, val, offset + RGB_MUL_GG);
707 val = (rgb->coef_bg.decimal & 0xff) |
708 ((rgb->coef_bg.integer & integ_mask) << 8);
709 regw_ip(base_addr, val, offset + RGB_MUL_BG);
710 val = (rgb->coef_rb.decimal & 0xff) |
711 ((rgb->coef_rb.integer & integ_mask) << 8);
712 regw_ip(base_addr, val, offset + RGB_MUL_RB);
713 val = (rgb->coef_gb.decimal & 0xff) |
714 ((rgb->coef_gb.integer & integ_mask) << 8);
715 regw_ip(base_addr, val, offset + RGB_MUL_GB);
716 val = (rgb->coef_bb.decimal & 0xff) |
717 ((rgb->coef_bb.integer & integ_mask) << 8);
718 regw_ip(base_addr, val, offset + RGB_MUL_BB);
721 regw_ip(base_addr, rgb->out_ofst_r & offset_mask, offset + RGB_OFT_OR);
722 regw_ip(base_addr, rgb->out_ofst_g & offset_mask, offset + RGB_OFT_OG);
723 regw_ip(base_addr, rgb->out_ofst_b & offset_mask, offset + RGB_OFT_OB);
727 ipipe_update_gamma_tbl(void __iomem *isp5_base_addr,
728 struct vpfe_ipipe_gamma_entry *table, int size, u32 addr)
733 for (count = 0; count < size; count++) {
734 val = table[count].slope & GAMMA_MASK;
735 val |= (table[count].offset & GAMMA_MASK) << GAMMA_SHIFT;
736 w_ip_table(isp5_base_addr, val, (addr + (count * 4)));
741 ipipe_set_gamma_regs(void __iomem *base_addr, void __iomem *isp5_base_addr,
742 struct vpfe_ipipe_gamma *gamma)
747 ipipe_clock_enable(base_addr);
748 val = (gamma->bypass_r << GAMMA_BYPR_SHIFT) |
749 (gamma->bypass_b << GAMMA_BYPG_SHIFT) |
750 (gamma->bypass_g << GAMMA_BYPB_SHIFT) |
751 (gamma->tbl_sel << GAMMA_TBL_SEL_SHIFT) |
752 (gamma->tbl_size << GAMMA_TBL_SIZE_SHIFT);
754 regw_ip(base_addr, val, GMM_CFG);
756 if (gamma->tbl_sel != VPFE_IPIPE_GAMMA_TBL_RAM)
759 table_size = gamma->tbl_size;
761 if (!gamma->bypass_r && gamma->table_r != NULL)
762 ipipe_update_gamma_tbl(isp5_base_addr, gamma->table_r,
763 table_size, GAMMA_R_START_ADDR);
764 if (!gamma->bypass_b && gamma->table_b != NULL)
765 ipipe_update_gamma_tbl(isp5_base_addr, gamma->table_b,
766 table_size, GAMMA_B_START_ADDR);
767 if (!gamma->bypass_g && gamma->table_g != NULL)
768 ipipe_update_gamma_tbl(isp5_base_addr, gamma->table_g,
769 table_size, GAMMA_G_START_ADDR);
773 ipipe_set_3d_lut_regs(void __iomem *base_addr, void __iomem *isp5_base_addr,
774 struct vpfe_ipipe_3d_lut *lut_3d)
776 struct vpfe_ipipe_3d_lut_entry *tbl;
782 ipipe_clock_enable(base_addr);
783 regw_ip(base_addr, lut_3d->en, D3LUT_EN);
794 for (i = 0; i < VPFE_IPIPE_MAX_SIZE_3D_LUT; i++) {
795 /* Each entry has 0-9 (B), 10-19 (G) and
797 val = tbl[i].b & D3_LUT_ENTRY_MASK;
798 val |= (tbl[i].g & D3_LUT_ENTRY_MASK) <<
799 D3_LUT_ENTRY_G_SHIFT;
800 val |= (tbl[i].r & D3_LUT_ENTRY_MASK) <<
801 D3_LUT_ENTRY_R_SHIFT;
806 w_ip_table(isp5_base_addr, val,
807 tbl_index + D3L_TB0_START_ADDR);
808 else if (bnk_index == 1)
809 w_ip_table(isp5_base_addr, val,
810 tbl_index + D3L_TB1_START_ADDR);
811 else if (bnk_index == 2)
812 w_ip_table(isp5_base_addr, val,
813 tbl_index + D3L_TB2_START_ADDR);
815 w_ip_table(isp5_base_addr, val,
816 tbl_index + D3L_TB3_START_ADDR);
820 /* Lumina adjustments */
822 ipipe_set_lum_adj_regs(void __iomem *base_addr, struct ipipe_lum_adj *lum_adj)
826 ipipe_clock_enable(base_addr);
828 /* combine fields of YUV_ADJ to set brightness and contrast */
829 val = lum_adj->contrast << LUM_ADJ_CONTR_SHIFT |
830 lum_adj->brightness << LUM_ADJ_BRIGHT_SHIFT;
831 regw_ip(base_addr, val, YUV_ADJ);
834 #define IPIPE_S12Q8(decimal, integer) \
835 (((decimal & 0xff) | ((integer & 0xf) << 8)))
837 void ipipe_set_rgb2ycbcr_regs(void __iomem *base_addr,
838 struct vpfe_ipipe_rgb2yuv *yuv)
843 ipipe_clock_enable(base_addr);
844 val = IPIPE_S12Q8(yuv->coef_ry.decimal, yuv->coef_ry.integer);
845 regw_ip(base_addr, val, YUV_MUL_RY);
846 val = IPIPE_S12Q8(yuv->coef_gy.decimal, yuv->coef_gy.integer);
847 regw_ip(base_addr, val, YUV_MUL_GY);
848 val = IPIPE_S12Q8(yuv->coef_by.decimal, yuv->coef_by.integer);
849 regw_ip(base_addr, val, YUV_MUL_BY);
850 val = IPIPE_S12Q8(yuv->coef_rcb.decimal, yuv->coef_rcb.integer);
851 regw_ip(base_addr, val, YUV_MUL_RCB);
852 val = IPIPE_S12Q8(yuv->coef_gcb.decimal, yuv->coef_gcb.integer);
853 regw_ip(base_addr, val, YUV_MUL_GCB);
854 val = IPIPE_S12Q8(yuv->coef_bcb.decimal, yuv->coef_bcb.integer);
855 regw_ip(base_addr, val, YUV_MUL_BCB);
856 val = IPIPE_S12Q8(yuv->coef_rcr.decimal, yuv->coef_rcr.integer);
857 regw_ip(base_addr, val, YUV_MUL_RCR);
858 val = IPIPE_S12Q8(yuv->coef_gcr.decimal, yuv->coef_gcr.integer);
859 regw_ip(base_addr, val, YUV_MUL_GCR);
860 val = IPIPE_S12Q8(yuv->coef_bcr.decimal, yuv->coef_bcr.integer);
861 regw_ip(base_addr, val, YUV_MUL_BCR);
862 regw_ip(base_addr, yuv->out_ofst_y & RGB2YCBCR_OFST_MASK, YUV_OFT_Y);
863 regw_ip(base_addr, yuv->out_ofst_cb & RGB2YCBCR_OFST_MASK, YUV_OFT_CB);
864 regw_ip(base_addr, yuv->out_ofst_cr & RGB2YCBCR_OFST_MASK, YUV_OFT_CR);
867 /* YUV 422 conversion */
869 ipipe_set_yuv422_conv_regs(void __iomem *base_addr,
870 struct vpfe_ipipe_yuv422_conv *conv)
874 ipipe_clock_enable(base_addr);
876 /* Combine all the fields to make YUV_PHS register of IPIPE */
877 val = (conv->chrom_pos << 0) | (conv->en_chrom_lpf << 1);
878 regw_ip(base_addr, val, YUV_PHS);
882 ipipe_set_gbce_regs(void __iomem *base_addr, void __iomem *isp5_base_addr,
883 struct vpfe_ipipe_gbce *gbce)
886 u32 mask = GBCE_Y_VAL_MASK;
888 if (gbce->type == VPFE_IPIPE_GBCE_GAIN_TBL)
889 mask = GBCE_GAIN_VAL_MASK;
891 ipipe_clock_enable(base_addr);
892 regw_ip(base_addr, gbce->en & 1, GBCE_EN);
897 regw_ip(base_addr, gbce->type, GBCE_TYP);
902 for (count = 0; count < VPFE_IPIPE_MAX_SIZE_GBCE_LUT; count += 2)
903 w_ip_table(isp5_base_addr, ((gbce->table[count + 1] & mask) <<
904 GBCE_ENTRY_SHIFT) | (gbce->table[count] & mask),
905 ((count/2) << 2) + GBCE_TB_START_ADDR);
909 ipipe_set_ee_regs(void __iomem *base_addr, void __iomem *isp5_base_addr,
910 struct vpfe_ipipe_yee *ee)
915 ipipe_clock_enable(base_addr);
916 regw_ip(base_addr, ee->en, YEE_EN);
921 val = ee->en_halo_red & 1;
922 val |= ee->merge_meth << YEE_HALO_RED_EN_SHIFT;
923 regw_ip(base_addr, val, YEE_TYP);
925 regw_ip(base_addr, ee->hpf_shft, YEE_SHF);
926 regw_ip(base_addr, ee->hpf_coef_00 & YEE_COEF_MASK, YEE_MUL_00);
927 regw_ip(base_addr, ee->hpf_coef_01 & YEE_COEF_MASK, YEE_MUL_01);
928 regw_ip(base_addr, ee->hpf_coef_02 & YEE_COEF_MASK, YEE_MUL_02);
929 regw_ip(base_addr, ee->hpf_coef_10 & YEE_COEF_MASK, YEE_MUL_10);
930 regw_ip(base_addr, ee->hpf_coef_11 & YEE_COEF_MASK, YEE_MUL_11);
931 regw_ip(base_addr, ee->hpf_coef_12 & YEE_COEF_MASK, YEE_MUL_12);
932 regw_ip(base_addr, ee->hpf_coef_20 & YEE_COEF_MASK, YEE_MUL_20);
933 regw_ip(base_addr, ee->hpf_coef_21 & YEE_COEF_MASK, YEE_MUL_21);
934 regw_ip(base_addr, ee->hpf_coef_22 & YEE_COEF_MASK, YEE_MUL_22);
935 regw_ip(base_addr, ee->yee_thr & YEE_THR_MASK, YEE_THR);
936 regw_ip(base_addr, ee->es_gain & YEE_ES_GAIN_MASK, YEE_E_GAN);
937 regw_ip(base_addr, ee->es_thr1 & YEE_ES_THR1_MASK, YEE_E_THR1);
938 regw_ip(base_addr, ee->es_thr2 & YEE_THR_MASK, YEE_E_THR2);
939 regw_ip(base_addr, ee->es_gain_grad & YEE_THR_MASK, YEE_G_GAN);
940 regw_ip(base_addr, ee->es_ofst_grad & YEE_THR_MASK, YEE_G_OFT);
942 if (ee->table == NULL)
945 for (count = 0; count < VPFE_IPIPE_MAX_SIZE_YEE_LUT; count += 2)
946 w_ip_table(isp5_base_addr, ((ee->table[count + 1] &
947 YEE_ENTRY_MASK) << YEE_ENTRY_SHIFT) |
948 (ee->table[count] & YEE_ENTRY_MASK),
949 ((count/2) << 2) + YEE_TB_START_ADDR);
952 /* Chromatic Artifact Correction. CAR */
953 static void ipipe_set_mf(void __iomem *base_addr)
955 /* typ to dynamic switch */
956 regw_ip(base_addr, VPFE_IPIPE_CAR_DYN_SWITCH, CAR_TYP);
957 /* Set SW0 to maximum */
958 regw_ip(base_addr, CAR_MF_THR, CAR_SW);
962 ipipe_set_gain_ctrl(void __iomem *base_addr, struct vpfe_ipipe_car *car)
964 regw_ip(base_addr, VPFE_IPIPE_CAR_CHR_GAIN_CTRL, CAR_TYP);
965 regw_ip(base_addr, car->hpf, CAR_HPF_TYP);
966 regw_ip(base_addr, car->hpf_shft & CAR_HPF_SHIFT_MASK, CAR_HPF_SHF);
967 regw_ip(base_addr, car->hpf_thr, CAR_HPF_THR);
968 regw_ip(base_addr, car->gain1.gain, CAR_GN1_GAN);
969 regw_ip(base_addr, car->gain1.shft & CAR_GAIN1_SHFT_MASK, CAR_GN1_SHF);
970 regw_ip(base_addr, car->gain1.gain_min & CAR_GAIN_MIN_MASK,
972 regw_ip(base_addr, car->gain2.gain, CAR_GN2_GAN);
973 regw_ip(base_addr, car->gain2.shft & CAR_GAIN2_SHFT_MASK, CAR_GN2_SHF);
974 regw_ip(base_addr, car->gain2.gain_min & CAR_GAIN_MIN_MASK,
978 void ipipe_set_car_regs(void __iomem *base_addr, struct vpfe_ipipe_car *car)
982 ipipe_clock_enable(base_addr);
983 regw_ip(base_addr, car->en, CAR_EN);
989 case VPFE_IPIPE_CAR_MED_FLTR:
990 ipipe_set_mf(base_addr);
993 case VPFE_IPIPE_CAR_CHR_GAIN_CTRL:
994 ipipe_set_gain_ctrl(base_addr, car);
998 /* Dynamic switch between MF and Gain Ctrl. */
999 ipipe_set_mf(base_addr);
1000 ipipe_set_gain_ctrl(base_addr, car);
1001 /* Set the threshold for switching between
1002 * the two Here we overwrite the MF SW0 value
1004 regw_ip(base_addr, VPFE_IPIPE_CAR_DYN_SWITCH, CAR_TYP);
1006 val <<= CAR_SW1_SHIFT;
1008 regw_ip(base_addr, val, CAR_SW);
1012 /* Chromatic Gain Suppression */
1013 void ipipe_set_cgs_regs(void __iomem *base_addr, struct vpfe_ipipe_cgs *cgs)
1015 ipipe_clock_enable(base_addr);
1016 regw_ip(base_addr, cgs->en, CGS_EN);
1021 /* Set the bright side parameters */
1022 regw_ip(base_addr, cgs->h_thr, CGS_GN1_H_THR);
1023 regw_ip(base_addr, cgs->h_slope, CGS_GN1_H_GAN);
1024 regw_ip(base_addr, cgs->h_shft & CAR_SHIFT_MASK, CGS_GN1_H_SHF);
1025 regw_ip(base_addr, cgs->h_min, CGS_GN1_H_MIN);
1028 void rsz_src_enable(void __iomem *rsz_base, int enable)
1030 regw_rsz(rsz_base, enable, RSZ_SRC_EN);
1033 int rsz_enable(void __iomem *rsz_base, int rsz_id, int enable)
1035 if (rsz_id == RSZ_A) {
1036 regw_rsz(rsz_base, enable, RSZ_EN_A);
1037 /* We always enable RSZ_A. RSZ_B is enable upon request from
1038 * application. So enable RSZ_SRC_EN along with RSZ_A
1040 regw_rsz(rsz_base, enable, RSZ_SRC_EN);
1041 } else if (rsz_id == RSZ_B) {
1042 regw_rsz(rsz_base, enable, RSZ_EN_B);