Linux-libre 5.3.12-gnu
[librecmc/linux-libre.git] / drivers / staging / media / davinci_vpfe / dm365_ipipe_hw.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) 2012 Texas Instruments Inc
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License as
7  * published by the Free Software Foundation version 2.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * Contributors:
15  *      Manjunath Hadli <manjunath.hadli@ti.com>
16  *      Prabhakar Lad <prabhakar.lad@ti.com>
17  */
18
19 #include "dm365_ipipe_hw.h"
20
21 #define IPIPE_MODE_CONTINUOUS           0
22 #define IPIPE_MODE_SINGLE_SHOT          1
23
24 static void ipipe_clock_enable(void __iomem *base_addr)
25 {
26         /* enable IPIPE MMR for register write access */
27         regw_ip(base_addr, IPIPE_GCK_MMR_DEFAULT, IPIPE_GCK_MMR);
28
29         /* enable the clock wb,cfa,dfc,d2f,pre modules */
30         regw_ip(base_addr, IPIPE_GCK_PIX_DEFAULT, IPIPE_GCK_PIX);
31 }
32
33 static void
34 rsz_set_common_params(void __iomem *rsz_base, struct resizer_params *params)
35 {
36         struct rsz_common_params *rsz_common = &params->rsz_common;
37         u32 val;
38
39         /* Set mode */
40         regw_rsz(rsz_base, params->oper_mode, RSZ_SRC_MODE);
41
42         /* data source selection  and bypass */
43         val = (rsz_common->passthrough << RSZ_BYPASS_SHIFT) |
44               rsz_common->source;
45         regw_rsz(rsz_base, val, RSZ_SRC_FMT0);
46
47         /* src image selection */
48         val = (rsz_common->raw_flip & 1) |
49               (rsz_common->src_img_fmt << RSZ_SRC_IMG_FMT_SHIFT) |
50               ((rsz_common->y_c & 1) << RSZ_SRC_Y_C_SEL_SHIFT);
51         regw_rsz(rsz_base, val, RSZ_SRC_FMT1);
52
53         regw_rsz(rsz_base, rsz_common->vps & IPIPE_RSZ_VPS_MASK, RSZ_SRC_VPS);
54         regw_rsz(rsz_base, rsz_common->hps & IPIPE_RSZ_HPS_MASK, RSZ_SRC_HPS);
55         regw_rsz(rsz_base, rsz_common->vsz & IPIPE_RSZ_VSZ_MASK, RSZ_SRC_VSZ);
56         regw_rsz(rsz_base, rsz_common->hsz & IPIPE_RSZ_HSZ_MASK, RSZ_SRC_HSZ);
57         regw_rsz(rsz_base, rsz_common->yuv_y_min, RSZ_YUV_Y_MIN);
58         regw_rsz(rsz_base, rsz_common->yuv_y_max, RSZ_YUV_Y_MAX);
59         regw_rsz(rsz_base, rsz_common->yuv_c_min, RSZ_YUV_C_MIN);
60         regw_rsz(rsz_base, rsz_common->yuv_c_max, RSZ_YUV_C_MAX);
61         /* chromatic position */
62         regw_rsz(rsz_base, rsz_common->out_chr_pos, RSZ_YUV_PHS);
63 }
64
65 static void
66 rsz_set_rsz_regs(void __iomem *rsz_base, unsigned int rsz_id,
67                  struct resizer_params *params)
68 {
69         struct resizer_scale_param *rsc_params;
70         struct rsz_ext_mem_param *ext_mem;
71         struct resizer_rgb *rgb;
72         u32 reg_base;
73         u32 val;
74
75         rsc_params = &params->rsz_rsc_param[rsz_id];
76         rgb = &params->rsz2rgb[rsz_id];
77         ext_mem = &params->ext_mem_param[rsz_id];
78
79         if (rsz_id == RSZ_A) {
80                 val = rsc_params->h_flip << RSZA_H_FLIP_SHIFT;
81                 val |= rsc_params->v_flip << RSZA_V_FLIP_SHIFT;
82                 reg_base = RSZ_EN_A;
83         } else {
84                 val = rsc_params->h_flip << RSZB_H_FLIP_SHIFT;
85                 val |= rsc_params->v_flip << RSZB_V_FLIP_SHIFT;
86                 reg_base = RSZ_EN_B;
87         }
88         /* update flip settings */
89         regw_rsz(rsz_base, val, RSZ_SEQ);
90
91         regw_rsz(rsz_base, params->oper_mode, reg_base + RSZ_MODE);
92
93         val = (rsc_params->cen << RSZ_CEN_SHIFT) | rsc_params->yen;
94         regw_rsz(rsz_base, val, reg_base + RSZ_420);
95
96         regw_rsz(rsz_base, rsc_params->i_vps & RSZ_VPS_MASK,
97                  reg_base + RSZ_I_VPS);
98         regw_rsz(rsz_base, rsc_params->i_hps & RSZ_HPS_MASK,
99                  reg_base + RSZ_I_HPS);
100         regw_rsz(rsz_base, rsc_params->o_vsz & RSZ_O_VSZ_MASK,
101                  reg_base + RSZ_O_VSZ);
102         regw_rsz(rsz_base, rsc_params->o_hsz & RSZ_O_HSZ_MASK,
103                  reg_base + RSZ_O_HSZ);
104         regw_rsz(rsz_base, rsc_params->v_phs_y & RSZ_V_PHS_MASK,
105                  reg_base + RSZ_V_PHS_Y);
106         regw_rsz(rsz_base, rsc_params->v_phs_c & RSZ_V_PHS_MASK,
107                  reg_base + RSZ_V_PHS_C);
108
109         /* keep this additional adjustment to zero for now */
110         regw_rsz(rsz_base, rsc_params->v_dif & RSZ_V_DIF_MASK,
111                  reg_base + RSZ_V_DIF);
112
113         val = (rsc_params->v_typ_y & 1) |
114               ((rsc_params->v_typ_c & 1) << RSZ_TYP_C_SHIFT);
115         regw_rsz(rsz_base, val, reg_base + RSZ_V_TYP);
116
117         val = (rsc_params->v_lpf_int_y & RSZ_LPF_INT_MASK) |
118               ((rsc_params->v_lpf_int_c & RSZ_LPF_INT_MASK) <<
119               RSZ_LPF_INT_C_SHIFT);
120         regw_rsz(rsz_base, val, reg_base + RSZ_V_LPF);
121
122         regw_rsz(rsz_base, rsc_params->h_phs &
123                 RSZ_H_PHS_MASK, reg_base + RSZ_H_PHS);
124
125         regw_rsz(rsz_base, 0, reg_base + RSZ_H_PHS_ADJ);
126         regw_rsz(rsz_base, rsc_params->h_dif &
127                 RSZ_H_DIF_MASK, reg_base + RSZ_H_DIF);
128
129         val = (rsc_params->h_typ_y & 1) |
130               ((rsc_params->h_typ_c & 1) << RSZ_TYP_C_SHIFT);
131         regw_rsz(rsz_base, val, reg_base + RSZ_H_TYP);
132
133         val = (rsc_params->h_lpf_int_y & RSZ_LPF_INT_MASK) |
134                  ((rsc_params->h_lpf_int_c & RSZ_LPF_INT_MASK) <<
135                  RSZ_LPF_INT_C_SHIFT);
136         regw_rsz(rsz_base, val, reg_base + RSZ_H_LPF);
137
138         regw_rsz(rsz_base, rsc_params->dscale_en & 1, reg_base + RSZ_DWN_EN);
139
140         val = (rsc_params->h_dscale_ave_sz & RSZ_DWN_SCALE_AV_SZ_MASK) |
141               ((rsc_params->v_dscale_ave_sz & RSZ_DWN_SCALE_AV_SZ_MASK) <<
142               RSZ_DWN_SCALE_AV_SZ_V_SHIFT);
143         regw_rsz(rsz_base, val, reg_base + RSZ_DWN_AV);
144
145         /* setting rgb conversion parameters */
146         regw_rsz(rsz_base, rgb->rgb_en, reg_base + RSZ_RGB_EN);
147
148         val = (rgb->rgb_typ << RSZ_RGB_TYP_SHIFT) |
149               (rgb->rgb_msk0 << RSZ_RGB_MSK0_SHIFT) |
150               (rgb->rgb_msk1 << RSZ_RGB_MSK1_SHIFT);
151         regw_rsz(rsz_base, val, reg_base + RSZ_RGB_TYP);
152
153         regw_rsz(rsz_base, rgb->rgb_alpha_val & RSZ_RGB_ALPHA_MASK,
154                 reg_base + RSZ_RGB_BLD);
155
156         /* setting external memory parameters */
157         regw_rsz(rsz_base, ext_mem->rsz_sdr_oft_y, reg_base + RSZ_SDR_Y_OFT);
158         regw_rsz(rsz_base, ext_mem->rsz_sdr_ptr_s_y,
159                  reg_base + RSZ_SDR_Y_PTR_S);
160         regw_rsz(rsz_base, ext_mem->rsz_sdr_ptr_e_y,
161                  reg_base + RSZ_SDR_Y_PTR_E);
162         regw_rsz(rsz_base, ext_mem->rsz_sdr_oft_c, reg_base + RSZ_SDR_C_OFT);
163         regw_rsz(rsz_base, ext_mem->rsz_sdr_ptr_s_c,
164                  reg_base + RSZ_SDR_C_PTR_S);
165         regw_rsz(rsz_base, (ext_mem->rsz_sdr_ptr_e_c >> 1),
166                  reg_base + RSZ_SDR_C_PTR_E);
167 }
168
169 /*set the registers of either RSZ0 or RSZ1 */
170 static void
171 ipipe_setup_resizer(void __iomem *rsz_base, struct resizer_params *params)
172 {
173         /* enable MMR gate to write to Resizer */
174         regw_rsz(rsz_base, 1, RSZ_GCK_MMR);
175
176         /* Enable resizer if it is not in bypass mode */
177         if (params->rsz_common.passthrough)
178                 regw_rsz(rsz_base, 0, RSZ_GCK_SDR);
179         else
180                 regw_rsz(rsz_base, 1, RSZ_GCK_SDR);
181
182         rsz_set_common_params(rsz_base, params);
183
184         regw_rsz(rsz_base, params->rsz_en[RSZ_A], RSZ_EN_A);
185
186         if (params->rsz_en[RSZ_A])
187                 /*setting rescale parameters */
188                 rsz_set_rsz_regs(rsz_base, RSZ_A, params);
189
190         regw_rsz(rsz_base, params->rsz_en[RSZ_B], RSZ_EN_B);
191
192         if (params->rsz_en[RSZ_B])
193                 rsz_set_rsz_regs(rsz_base, RSZ_B, params);
194 }
195
196 static u32 ipipe_get_color_pat(u32 pix)
197 {
198         switch (pix) {
199         case MEDIA_BUS_FMT_SGRBG10_ALAW8_1X8:
200         case MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8:
201         case MEDIA_BUS_FMT_SGRBG12_1X12:
202                 return ipipe_sgrbg_pattern;
203
204         default:
205                 return ipipe_srggb_pattern;
206         }
207 }
208
209 static int ipipe_get_data_path(struct vpfe_ipipe_device *ipipe)
210 {
211         u32 temp_pix_fmt;
212
213         switch (ipipe->formats[IPIPE_PAD_SINK].code) {
214         case MEDIA_BUS_FMT_SBGGR8_1X8:
215         case MEDIA_BUS_FMT_SGRBG10_ALAW8_1X8:
216         case MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8:
217         case MEDIA_BUS_FMT_SGRBG12_1X12:
218                 temp_pix_fmt = MEDIA_BUS_FMT_SGRBG12_1X12;
219                 break;
220
221         default:
222                 temp_pix_fmt = MEDIA_BUS_FMT_UYVY8_2X8;
223         }
224
225         if (temp_pix_fmt == MEDIA_BUS_FMT_SGRBG12_1X12) {
226                 if (ipipe->formats[IPIPE_PAD_SOURCE].code ==
227                         MEDIA_BUS_FMT_SGRBG12_1X12)
228                         return IPIPE_RAW2RAW;
229                 return IPIPE_RAW2YUV;
230         }
231
232         return IPIPE_YUV2YUV;
233 }
234
235 static int get_ipipe_mode(struct vpfe_ipipe_device *ipipe)
236 {
237         struct vpfe_device *vpfe_dev = to_vpfe_device(ipipe);
238         u16 ipipeif_sink = vpfe_dev->vpfe_ipipeif.input;
239
240         if (ipipeif_sink == IPIPEIF_INPUT_MEMORY)
241                 return IPIPE_MODE_SINGLE_SHOT;
242         if (ipipeif_sink == IPIPEIF_INPUT_ISIF)
243                 return IPIPE_MODE_CONTINUOUS;
244
245         return -EINVAL;
246 }
247
248 int config_ipipe_hw(struct vpfe_ipipe_device *ipipe)
249 {
250         struct vpfe_ipipe_input_config *config = &ipipe->config.input_config;
251         void __iomem *ipipe_base = ipipe->base_addr;
252         struct v4l2_mbus_framefmt *outformat;
253         u32 color_pat;
254         int ipipe_mode;
255         u32 data_path;
256
257         /* enable clock to IPIPE */
258         vpss_enable_clock(VPSS_IPIPE_CLOCK, 1);
259         ipipe_clock_enable(ipipe_base);
260
261         if (ipipe->input == IPIPE_INPUT_NONE) {
262                 regw_ip(ipipe_base, 0, IPIPE_SRC_EN);
263                 return 0;
264         }
265
266         ipipe_mode = get_ipipe_mode(ipipe);
267         if (ipipe_mode < 0) {
268                 pr_err("Failed to get ipipe mode");
269                 return -EINVAL;
270         }
271         regw_ip(ipipe_base, ipipe_mode, IPIPE_SRC_MODE);
272
273         data_path = ipipe_get_data_path(ipipe);
274         regw_ip(ipipe_base, data_path, IPIPE_SRC_FMT);
275
276         regw_ip(ipipe_base, config->vst & IPIPE_RSZ_VPS_MASK, IPIPE_SRC_VPS);
277         regw_ip(ipipe_base, config->hst & IPIPE_RSZ_HPS_MASK, IPIPE_SRC_HPS);
278
279         outformat = &ipipe->formats[IPIPE_PAD_SOURCE];
280         regw_ip(ipipe_base, (outformat->height + 1) & IPIPE_RSZ_VSZ_MASK,
281                 IPIPE_SRC_VSZ);
282         regw_ip(ipipe_base, (outformat->width + 1) & IPIPE_RSZ_HSZ_MASK,
283                 IPIPE_SRC_HSZ);
284
285         if (data_path == IPIPE_RAW2YUV ||
286             data_path == IPIPE_RAW2RAW) {
287                 color_pat =
288                 ipipe_get_color_pat(ipipe->formats[IPIPE_PAD_SINK].code);
289                 regw_ip(ipipe_base, color_pat, IPIPE_SRC_COL);
290         }
291
292         return 0;
293 }
294
295 /*
296  * config_rsz_hw() - Performs hardware setup of resizer.
297  */
298 int config_rsz_hw(struct vpfe_resizer_device *resizer,
299                   struct resizer_params *config)
300 {
301         struct vpfe_device *vpfe_dev = to_vpfe_device(resizer);
302         void __iomem *ipipe_base = vpfe_dev->vpfe_ipipe.base_addr;
303         void __iomem *rsz_base = vpfe_dev->vpfe_resizer.base_addr;
304
305         /* enable VPSS clock */
306         vpss_enable_clock(VPSS_IPIPE_CLOCK, 1);
307         ipipe_clock_enable(ipipe_base);
308
309         ipipe_setup_resizer(rsz_base, config);
310
311         return 0;
312 }
313
314 static void
315 rsz_set_y_address(void __iomem *rsz_base, unsigned int address,
316                   unsigned int offset)
317 {
318         u32 val;
319
320         val = address & SET_LOW_ADDR;
321         regw_rsz(rsz_base, val, offset + RSZ_SDR_Y_BAD_L);
322         regw_rsz(rsz_base, val, offset + RSZ_SDR_Y_SAD_L);
323
324         val = (address & SET_HIGH_ADDR) >> 16;
325         regw_rsz(rsz_base, val, offset + RSZ_SDR_Y_BAD_H);
326         regw_rsz(rsz_base, val, offset + RSZ_SDR_Y_SAD_H);
327 }
328
329 static void
330 rsz_set_c_address(void __iomem *rsz_base, unsigned int address,
331                   unsigned int offset)
332 {
333         u32 val;
334
335         val = address & SET_LOW_ADDR;
336         regw_rsz(rsz_base, val, offset + RSZ_SDR_C_BAD_L);
337         regw_rsz(rsz_base, val, offset + RSZ_SDR_C_SAD_L);
338
339         val = (address & SET_HIGH_ADDR) >> 16;
340         regw_rsz(rsz_base, val, offset + RSZ_SDR_C_BAD_H);
341         regw_rsz(rsz_base, val, offset + RSZ_SDR_C_SAD_H);
342 }
343
344 /*
345  * resizer_set_outaddr() - set the address for given resize_no
346  * @rsz_base: resizer base address
347  * @params: pointer to ipipe_params structure
348  * @resize_no: 0 - Resizer-A, 1 - Resizer B
349  * @address: the address to set
350  */
351 int
352 resizer_set_outaddr(void __iomem *rsz_base, struct resizer_params *params,
353                     int resize_no, unsigned int address)
354 {
355         struct resizer_scale_param *rsc_param;
356         struct rsz_ext_mem_param *mem_param;
357         struct rsz_common_params *rsz_common;
358         unsigned int rsz_start_add;
359         unsigned int val;
360
361         if (resize_no != RSZ_A && resize_no != RSZ_B)
362                 return -EINVAL;
363
364         mem_param = &params->ext_mem_param[resize_no];
365         rsc_param = &params->rsz_rsc_param[resize_no];
366         rsz_common = &params->rsz_common;
367
368         if (resize_no == RSZ_A)
369                 rsz_start_add = RSZ_EN_A;
370         else
371                 rsz_start_add = RSZ_EN_B;
372
373         /* y_c = 0 for y, = 1 for c */
374         if (rsz_common->src_img_fmt == RSZ_IMG_420) {
375                 if (rsz_common->y_c) {
376                         /* C channel */
377                         val = address + mem_param->flip_ofst_c;
378                         rsz_set_c_address(rsz_base, val, rsz_start_add);
379                 } else {
380                         val = address + mem_param->flip_ofst_y;
381                         rsz_set_y_address(rsz_base, val, rsz_start_add);
382                 }
383         } else {
384                 if (rsc_param->cen && rsc_param->yen) {
385                         /* 420 */
386                         val = address + mem_param->c_offset +
387                               mem_param->flip_ofst_c +
388                               mem_param->user_y_ofst +
389                               mem_param->user_c_ofst;
390                         if (resize_no == RSZ_B)
391                                 val +=
392                                 params->ext_mem_param[RSZ_A].user_y_ofst +
393                                 params->ext_mem_param[RSZ_A].user_c_ofst;
394                         /* set C address */
395                         rsz_set_c_address(rsz_base, val, rsz_start_add);
396                 }
397                 val = address + mem_param->flip_ofst_y + mem_param->user_y_ofst;
398                 if (resize_no == RSZ_B)
399                         val += params->ext_mem_param[RSZ_A].user_y_ofst +
400                                 params->ext_mem_param[RSZ_A].user_c_ofst;
401                 /* set Y address */
402                 rsz_set_y_address(rsz_base, val, rsz_start_add);
403         }
404         /* resizer must be enabled */
405         regw_rsz(rsz_base, params->rsz_en[resize_no], rsz_start_add);
406
407         return 0;
408 }
409
410 void
411 ipipe_set_lutdpc_regs(void __iomem *base_addr, void __iomem *isp5_base_addr,
412                       struct vpfe_ipipe_lutdpc *dpc)
413 {
414         u32 max_tbl_size = LUT_DPC_MAX_SIZE >> 1;
415         u32 lut_start_addr = DPC_TB0_START_ADDR;
416         u32 val;
417         u32 count;
418
419         ipipe_clock_enable(base_addr);
420         regw_ip(base_addr, dpc->en, DPC_LUT_EN);
421
422         if (dpc->en != 1)
423                 return;
424
425         val = LUTDPC_TBL_256_EN | (dpc->repl_white & 1);
426         regw_ip(base_addr, val, DPC_LUT_SEL);
427         regw_ip(base_addr, LUT_DPC_START_ADDR, DPC_LUT_ADR);
428         regw_ip(base_addr, dpc->dpc_size, DPC_LUT_SIZ & LUT_DPC_SIZE_MASK);
429
430         for (count = 0; count < dpc->dpc_size; count++) {
431                 if (count >= max_tbl_size)
432                         lut_start_addr = DPC_TB1_START_ADDR;
433                 val = (dpc->table[count].horz_pos & LUT_DPC_H_POS_MASK) |
434                       ((dpc->table[count].vert_pos & LUT_DPC_V_POS_MASK) <<
435                         LUT_DPC_V_POS_SHIFT) | (dpc->table[count].method <<
436                         LUT_DPC_CORR_METH_SHIFT);
437                 w_ip_table(isp5_base_addr, val, (lut_start_addr +
438                 ((count % max_tbl_size) << 2)));
439         }
440 }
441
442 static void
443 set_dpc_thresholds(void __iomem *base_addr,
444                    struct vpfe_ipipe_otfdpc_2_0_cfg *dpc_thr)
445 {
446         regw_ip(base_addr, dpc_thr->corr_thr.r & OTFDPC_DPC2_THR_MASK,
447                 DPC_OTF_2C_THR_R);
448         regw_ip(base_addr, dpc_thr->corr_thr.gr & OTFDPC_DPC2_THR_MASK,
449                 DPC_OTF_2C_THR_GR);
450         regw_ip(base_addr, dpc_thr->corr_thr.gb & OTFDPC_DPC2_THR_MASK,
451                 DPC_OTF_2C_THR_GB);
452         regw_ip(base_addr, dpc_thr->corr_thr.b & OTFDPC_DPC2_THR_MASK,
453                 DPC_OTF_2C_THR_B);
454         regw_ip(base_addr, dpc_thr->det_thr.r & OTFDPC_DPC2_THR_MASK,
455                 DPC_OTF_2D_THR_R);
456         regw_ip(base_addr, dpc_thr->det_thr.gr & OTFDPC_DPC2_THR_MASK,
457                 DPC_OTF_2D_THR_GR);
458         regw_ip(base_addr, dpc_thr->det_thr.gb & OTFDPC_DPC2_THR_MASK,
459                 DPC_OTF_2D_THR_GB);
460         regw_ip(base_addr, dpc_thr->det_thr.b & OTFDPC_DPC2_THR_MASK,
461                 DPC_OTF_2D_THR_B);
462 }
463
464 void ipipe_set_otfdpc_regs(void __iomem *base_addr,
465                            struct vpfe_ipipe_otfdpc *otfdpc)
466 {
467         struct vpfe_ipipe_otfdpc_2_0_cfg *dpc_2_0 = &otfdpc->alg_cfg.dpc_2_0;
468         struct vpfe_ipipe_otfdpc_3_0_cfg *dpc_3_0 = &otfdpc->alg_cfg.dpc_3_0;
469         u32 val;
470
471         ipipe_clock_enable(base_addr);
472
473         regw_ip(base_addr, (otfdpc->en & 1), DPC_OTF_EN);
474         if (!otfdpc->en)
475                 return;
476
477         /* dpc enabled */
478         val = (otfdpc->det_method << OTF_DET_METHOD_SHIFT) | otfdpc->alg;
479         regw_ip(base_addr, val, DPC_OTF_TYP);
480
481         if (otfdpc->det_method == VPFE_IPIPE_DPC_OTF_MIN_MAX) {
482                 /* ALG= 0, TYP = 0, DPC_OTF_2D_THR_[x]=0
483                  * DPC_OTF_2C_THR_[x] = Maximum thresohld
484                  * MinMax method
485                  */
486                 dpc_2_0->det_thr.r = dpc_2_0->det_thr.gb =
487                 dpc_2_0->det_thr.gr = dpc_2_0->det_thr.b = 0;
488                 set_dpc_thresholds(base_addr, dpc_2_0);
489                 return;
490         }
491         /* MinMax2 */
492         if (otfdpc->alg == VPFE_IPIPE_OTFDPC_2_0) {
493                 set_dpc_thresholds(base_addr, dpc_2_0);
494                 return;
495         }
496         regw_ip(base_addr, dpc_3_0->act_adj_shf &
497                 OTF_DPC3_0_SHF_MASK, DPC_OTF_3_SHF);
498         /* Detection thresholds */
499         regw_ip(base_addr, ((dpc_3_0->det_thr & OTF_DPC3_0_THR_MASK) <<
500                 OTF_DPC3_0_THR_SHIFT), DPC_OTF_3D_THR);
501         regw_ip(base_addr, dpc_3_0->det_slp &
502                 OTF_DPC3_0_SLP_MASK, DPC_OTF_3D_SLP);
503         regw_ip(base_addr, dpc_3_0->det_thr_min &
504                 OTF_DPC3_0_DET_MASK, DPC_OTF_3D_MIN);
505         regw_ip(base_addr, dpc_3_0->det_thr_max &
506                 OTF_DPC3_0_DET_MASK, DPC_OTF_3D_MAX);
507         /* Correction thresholds */
508         regw_ip(base_addr, ((dpc_3_0->corr_thr & OTF_DPC3_0_THR_MASK) <<
509                 OTF_DPC3_0_THR_SHIFT), DPC_OTF_3C_THR);
510         regw_ip(base_addr, dpc_3_0->corr_slp &
511                 OTF_DPC3_0_SLP_MASK, DPC_OTF_3C_SLP);
512         regw_ip(base_addr, dpc_3_0->corr_thr_min &
513                 OTF_DPC3_0_CORR_MASK, DPC_OTF_3C_MIN);
514         regw_ip(base_addr, dpc_3_0->corr_thr_max &
515                 OTF_DPC3_0_CORR_MASK, DPC_OTF_3C_MAX);
516 }
517
518 /* 2D Noise filter */
519 void
520 ipipe_set_d2f_regs(void __iomem *base_addr, unsigned int id,
521                    struct vpfe_ipipe_nf *noise_filter)
522 {
523
524         u32 offset = D2F_1ST;
525         int count;
526         u32 val;
527
528         if (id == IPIPE_D2F_2ND)
529                 offset = D2F_2ND;
530
531         ipipe_clock_enable(base_addr);
532         regw_ip(base_addr, noise_filter->en & 1, offset + D2F_EN);
533         if (!noise_filter->en)
534                 return;
535
536         /*noise filter enabled */
537         /* Combine all the fields to make D2F_CFG register of IPIPE */
538         val = ((noise_filter->spread_val & D2F_SPR_VAL_MASK) <<
539                 D2F_SPR_VAL_SHIFT) | ((noise_filter->shft_val &
540                 D2F_SHFT_VAL_MASK) << D2F_SHFT_VAL_SHIFT) |
541                 (noise_filter->gr_sample_meth << D2F_SAMPLE_METH_SHIFT) |
542                 ((noise_filter->apply_lsc_gain & 1) <<
543                 D2F_APPLY_LSC_GAIN_SHIFT) | D2F_USE_SPR_REG_VAL;
544         regw_ip(base_addr, val, offset + D2F_TYP);
545
546         /* edge detection minimum */
547         regw_ip(base_addr, noise_filter->edge_det_min_thr &
548                 D2F_EDGE_DET_THR_MASK, offset + D2F_EDG_MIN);
549
550         /* edge detection maximum */
551         regw_ip(base_addr, noise_filter->edge_det_max_thr &
552                 D2F_EDGE_DET_THR_MASK, offset + D2F_EDG_MAX);
553
554         for (count = 0; count < VPFE_IPIPE_NF_STR_TABLE_SIZE; count++)
555                 regw_ip(base_addr,
556                         (noise_filter->str[count] & D2F_STR_VAL_MASK),
557                         offset + D2F_STR + count * 4);
558
559         for (count = 0; count < VPFE_IPIPE_NF_THR_TABLE_SIZE; count++)
560                 regw_ip(base_addr, noise_filter->thr[count] & D2F_THR_VAL_MASK,
561                         offset + D2F_THR + count * 4);
562 }
563
564 #define IPIPE_U8Q5(decimal, integer) \
565         (((decimal & 0x1f) | ((integer & 0x7) << 5)))
566
567 /* Green Imbalance Correction */
568 void ipipe_set_gic_regs(void __iomem *base_addr, struct vpfe_ipipe_gic *gic)
569 {
570         u32 val;
571
572         ipipe_clock_enable(base_addr);
573         regw_ip(base_addr, gic->en & 1, GIC_EN);
574
575         if (!gic->en)
576                 return;
577
578         /*gic enabled */
579         val = (gic->wt_fn_type << GIC_TYP_SHIFT) |
580               (gic->thr_sel << GIC_THR_SEL_SHIFT) |
581               ((gic->apply_lsc_gain & 1) << GIC_APPLY_LSC_GAIN_SHIFT);
582         regw_ip(base_addr, val, GIC_TYP);
583
584         regw_ip(base_addr, gic->gain & GIC_GAIN_MASK, GIC_GAN);
585
586         if (gic->gic_alg != VPFE_IPIPE_GIC_ALG_ADAPT_GAIN) {
587                 /* Constant Gain. Set threshold to maximum */
588                 regw_ip(base_addr, GIC_THR_MASK, GIC_THR);
589                 return;
590         }
591
592         if (gic->thr_sel == VPFE_IPIPE_GIC_THR_REG) {
593                 regw_ip(base_addr, gic->thr & GIC_THR_MASK, GIC_THR);
594                 regw_ip(base_addr, gic->slope & GIC_SLOPE_MASK, GIC_SLP);
595         } else {
596                 /* Use NF thresholds */
597                 val = IPIPE_U8Q5(gic->nf2_thr_gain.decimal,
598                                 gic->nf2_thr_gain.integer);
599                 regw_ip(base_addr, val, GIC_NFGAN);
600         }
601 }
602
603 #define IPIPE_U13Q9(decimal, integer) \
604         (((decimal & 0x1ff) | ((integer & 0xf) << 9)))
605 /* White balance */
606 void ipipe_set_wb_regs(void __iomem *base_addr, struct vpfe_ipipe_wb *wb)
607 {
608         u32 val;
609
610         ipipe_clock_enable(base_addr);
611         /* Ofsets. S12 */
612         regw_ip(base_addr, wb->ofst_r & WB_OFFSET_MASK, WB2_OFT_R);
613         regw_ip(base_addr, wb->ofst_gr & WB_OFFSET_MASK, WB2_OFT_GR);
614         regw_ip(base_addr, wb->ofst_gb & WB_OFFSET_MASK, WB2_OFT_GB);
615         regw_ip(base_addr, wb->ofst_b & WB_OFFSET_MASK, WB2_OFT_B);
616
617         /* Gains. U13Q9 */
618         val = IPIPE_U13Q9(wb->gain_r.decimal, wb->gain_r.integer);
619         regw_ip(base_addr, val, WB2_WGN_R);
620
621         val = IPIPE_U13Q9(wb->gain_gr.decimal, wb->gain_gr.integer);
622         regw_ip(base_addr, val, WB2_WGN_GR);
623
624         val = IPIPE_U13Q9(wb->gain_gb.decimal, wb->gain_gb.integer);
625         regw_ip(base_addr, val, WB2_WGN_GB);
626
627         val = IPIPE_U13Q9(wb->gain_b.decimal, wb->gain_b.integer);
628         regw_ip(base_addr, val, WB2_WGN_B);
629 }
630
631 /* CFA */
632 void ipipe_set_cfa_regs(void __iomem *base_addr, struct vpfe_ipipe_cfa *cfa)
633 {
634         ipipe_clock_enable(base_addr);
635
636         regw_ip(base_addr, cfa->alg, CFA_MODE);
637         regw_ip(base_addr, cfa->hpf_thr_2dir & CFA_HPF_THR_2DIR_MASK,
638                 CFA_2DIR_HPF_THR);
639         regw_ip(base_addr, cfa->hpf_slp_2dir & CFA_HPF_SLOPE_2DIR_MASK,
640                 CFA_2DIR_HPF_SLP);
641         regw_ip(base_addr, cfa->hp_mix_thr_2dir & CFA_HPF_MIX_THR_2DIR_MASK,
642                 CFA_2DIR_MIX_THR);
643         regw_ip(base_addr, cfa->hp_mix_slope_2dir & CFA_HPF_MIX_SLP_2DIR_MASK,
644                 CFA_2DIR_MIX_SLP);
645         regw_ip(base_addr, cfa->dir_thr_2dir & CFA_DIR_THR_2DIR_MASK,
646                 CFA_2DIR_DIR_THR);
647         regw_ip(base_addr, cfa->dir_slope_2dir & CFA_DIR_SLP_2DIR_MASK,
648                 CFA_2DIR_DIR_SLP);
649         regw_ip(base_addr, cfa->nd_wt_2dir & CFA_ND_WT_2DIR_MASK,
650                 CFA_2DIR_NDWT);
651         regw_ip(base_addr, cfa->hue_fract_daa & CFA_DAA_HUE_FRA_MASK,
652                 CFA_MONO_HUE_FRA);
653         regw_ip(base_addr, cfa->edge_thr_daa & CFA_DAA_EDG_THR_MASK,
654                 CFA_MONO_EDG_THR);
655         regw_ip(base_addr, cfa->thr_min_daa & CFA_DAA_THR_MIN_MASK,
656                 CFA_MONO_THR_MIN);
657         regw_ip(base_addr, cfa->thr_slope_daa & CFA_DAA_THR_SLP_MASK,
658                 CFA_MONO_THR_SLP);
659         regw_ip(base_addr, cfa->slope_min_daa & CFA_DAA_SLP_MIN_MASK,
660                 CFA_MONO_SLP_MIN);
661         regw_ip(base_addr, cfa->slope_slope_daa & CFA_DAA_SLP_SLP_MASK,
662                 CFA_MONO_SLP_SLP);
663         regw_ip(base_addr, cfa->lp_wt_daa & CFA_DAA_LP_WT_MASK,
664                 CFA_MONO_LPWT);
665 }
666
667 void
668 ipipe_set_rgb2rgb_regs(void __iomem *base_addr, unsigned int id,
669                        struct vpfe_ipipe_rgb2rgb *rgb)
670 {
671         u32 offset_mask = RGB2RGB_1_OFST_MASK;
672         u32 offset = RGB1_MUL_BASE;
673         u32 integ_mask = 0xf;
674         u32 val;
675
676         ipipe_clock_enable(base_addr);
677
678         if (id == IPIPE_RGB2RGB_2) {
679                 /*
680                  * For second RGB module, gain integer is 3 bits instead
681                  * of 4, offset has 11 bits insread of 13
682                  */
683                 offset = RGB2_MUL_BASE;
684                 integ_mask = 0x7;
685                 offset_mask = RGB2RGB_2_OFST_MASK;
686         }
687         /* Gains */
688         val = (rgb->coef_rr.decimal & 0xff) |
689                 ((rgb->coef_rr.integer & integ_mask) << 8);
690         regw_ip(base_addr, val, offset + RGB_MUL_RR);
691         val = (rgb->coef_gr.decimal & 0xff) |
692                 ((rgb->coef_gr.integer & integ_mask) << 8);
693         regw_ip(base_addr, val, offset + RGB_MUL_GR);
694         val = (rgb->coef_br.decimal & 0xff) |
695                 ((rgb->coef_br.integer & integ_mask) << 8);
696         regw_ip(base_addr, val, offset + RGB_MUL_BR);
697         val = (rgb->coef_rg.decimal & 0xff) |
698                 ((rgb->coef_rg.integer & integ_mask) << 8);
699         regw_ip(base_addr, val, offset + RGB_MUL_RG);
700         val = (rgb->coef_gg.decimal & 0xff) |
701                 ((rgb->coef_gg.integer & integ_mask) << 8);
702         regw_ip(base_addr, val, offset + RGB_MUL_GG);
703         val = (rgb->coef_bg.decimal & 0xff) |
704                 ((rgb->coef_bg.integer & integ_mask) << 8);
705         regw_ip(base_addr, val, offset + RGB_MUL_BG);
706         val = (rgb->coef_rb.decimal & 0xff) |
707                 ((rgb->coef_rb.integer & integ_mask) << 8);
708         regw_ip(base_addr, val, offset + RGB_MUL_RB);
709         val = (rgb->coef_gb.decimal & 0xff) |
710                 ((rgb->coef_gb.integer & integ_mask) << 8);
711         regw_ip(base_addr, val, offset + RGB_MUL_GB);
712         val = (rgb->coef_bb.decimal & 0xff) |
713                 ((rgb->coef_bb.integer & integ_mask) << 8);
714         regw_ip(base_addr, val, offset + RGB_MUL_BB);
715
716         /* Offsets */
717         regw_ip(base_addr, rgb->out_ofst_r & offset_mask, offset + RGB_OFT_OR);
718         regw_ip(base_addr, rgb->out_ofst_g & offset_mask, offset + RGB_OFT_OG);
719         regw_ip(base_addr, rgb->out_ofst_b & offset_mask, offset + RGB_OFT_OB);
720 }
721
722 static void
723 ipipe_update_gamma_tbl(void __iomem *isp5_base_addr,
724         struct vpfe_ipipe_gamma_entry *table, int size, u32 addr)
725 {
726         int count;
727         u32 val;
728
729         for (count = 0; count < size; count++) {
730                 val = table[count].slope & GAMMA_MASK;
731                 val |= (table[count].offset & GAMMA_MASK) << GAMMA_SHIFT;
732                 w_ip_table(isp5_base_addr, val, (addr + (count * 4)));
733         }
734 }
735
736 void
737 ipipe_set_gamma_regs(void __iomem *base_addr, void __iomem *isp5_base_addr,
738                           struct vpfe_ipipe_gamma *gamma)
739 {
740         int table_size;
741         u32 val;
742
743         ipipe_clock_enable(base_addr);
744         val = (gamma->bypass_r << GAMMA_BYPR_SHIFT) |
745                 (gamma->bypass_b << GAMMA_BYPG_SHIFT) |
746                 (gamma->bypass_g << GAMMA_BYPB_SHIFT) |
747                 (gamma->tbl_sel << GAMMA_TBL_SEL_SHIFT) |
748                 (gamma->tbl_size << GAMMA_TBL_SIZE_SHIFT);
749
750         regw_ip(base_addr, val, GMM_CFG);
751
752         if (gamma->tbl_sel != VPFE_IPIPE_GAMMA_TBL_RAM)
753                 return;
754
755         table_size = gamma->tbl_size;
756
757         if (!gamma->bypass_r)
758                 ipipe_update_gamma_tbl(isp5_base_addr, gamma->table_r,
759                         table_size, GAMMA_R_START_ADDR);
760         if (!gamma->bypass_b)
761                 ipipe_update_gamma_tbl(isp5_base_addr, gamma->table_b,
762                         table_size, GAMMA_B_START_ADDR);
763         if (!gamma->bypass_g)
764                 ipipe_update_gamma_tbl(isp5_base_addr, gamma->table_g,
765                         table_size, GAMMA_G_START_ADDR);
766 }
767
768 void
769 ipipe_set_3d_lut_regs(void __iomem *base_addr, void __iomem *isp5_base_addr,
770                            struct vpfe_ipipe_3d_lut *lut_3d)
771 {
772         struct vpfe_ipipe_3d_lut_entry *tbl;
773         u32 bnk_index;
774         u32 tbl_index;
775         u32 val;
776         u32 i;
777
778         ipipe_clock_enable(base_addr);
779         regw_ip(base_addr, lut_3d->en, D3LUT_EN);
780
781         if (!lut_3d->en)
782                 return;
783
784         /* valid table */
785         tbl = lut_3d->table;
786         for (i = 0; i < VPFE_IPIPE_MAX_SIZE_3D_LUT; i++) {
787                 /*
788                  * Each entry has 0-9 (B), 10-19 (G) and
789                  * 20-29 R values
790                  */
791                 val = tbl[i].b & D3_LUT_ENTRY_MASK;
792                 val |= (tbl[i].g & D3_LUT_ENTRY_MASK) <<
793                          D3_LUT_ENTRY_G_SHIFT;
794                 val |= (tbl[i].r & D3_LUT_ENTRY_MASK) <<
795                          D3_LUT_ENTRY_R_SHIFT;
796                 bnk_index = i % 4;
797                 tbl_index = i >> 2;
798                 tbl_index <<= 2;
799                 if (bnk_index == 0)
800                         w_ip_table(isp5_base_addr, val,
801                                    tbl_index + D3L_TB0_START_ADDR);
802                 else if (bnk_index == 1)
803                         w_ip_table(isp5_base_addr, val,
804                                    tbl_index + D3L_TB1_START_ADDR);
805                 else if (bnk_index == 2)
806                         w_ip_table(isp5_base_addr, val,
807                                    tbl_index + D3L_TB2_START_ADDR);
808                 else
809                         w_ip_table(isp5_base_addr, val,
810                                    tbl_index + D3L_TB3_START_ADDR);
811         }
812 }
813
814 /* Lumina adjustments */
815 void
816 ipipe_set_lum_adj_regs(void __iomem *base_addr, struct ipipe_lum_adj *lum_adj)
817 {
818         u32 val;
819
820         ipipe_clock_enable(base_addr);
821
822         /* combine fields of YUV_ADJ to set brightness and contrast */
823         val = lum_adj->contrast << LUM_ADJ_CONTR_SHIFT |
824               lum_adj->brightness << LUM_ADJ_BRIGHT_SHIFT;
825         regw_ip(base_addr, val, YUV_ADJ);
826 }
827
828 inline u32 ipipe_s12q8(unsigned short decimal, short integer)
829 {
830         return (decimal & 0xff) | ((integer & 0xf) << 8);
831 }
832
833 void ipipe_set_rgb2ycbcr_regs(void __iomem *base_addr,
834                               struct vpfe_ipipe_rgb2yuv *yuv)
835 {
836         u32 val;
837
838         /* S10Q8 */
839         ipipe_clock_enable(base_addr);
840         val = ipipe_s12q8(yuv->coef_ry.decimal, yuv->coef_ry.integer);
841         regw_ip(base_addr, val, YUV_MUL_RY);
842         val = ipipe_s12q8(yuv->coef_gy.decimal, yuv->coef_gy.integer);
843         regw_ip(base_addr, val, YUV_MUL_GY);
844         val = ipipe_s12q8(yuv->coef_by.decimal, yuv->coef_by.integer);
845         regw_ip(base_addr, val, YUV_MUL_BY);
846         val = ipipe_s12q8(yuv->coef_rcb.decimal, yuv->coef_rcb.integer);
847         regw_ip(base_addr, val, YUV_MUL_RCB);
848         val = ipipe_s12q8(yuv->coef_gcb.decimal, yuv->coef_gcb.integer);
849         regw_ip(base_addr, val, YUV_MUL_GCB);
850         val = ipipe_s12q8(yuv->coef_bcb.decimal, yuv->coef_bcb.integer);
851         regw_ip(base_addr, val, YUV_MUL_BCB);
852         val = ipipe_s12q8(yuv->coef_rcr.decimal, yuv->coef_rcr.integer);
853         regw_ip(base_addr, val, YUV_MUL_RCR);
854         val = ipipe_s12q8(yuv->coef_gcr.decimal, yuv->coef_gcr.integer);
855         regw_ip(base_addr, val, YUV_MUL_GCR);
856         val = ipipe_s12q8(yuv->coef_bcr.decimal, yuv->coef_bcr.integer);
857         regw_ip(base_addr, val, YUV_MUL_BCR);
858         regw_ip(base_addr, yuv->out_ofst_y & RGB2YCBCR_OFST_MASK, YUV_OFT_Y);
859         regw_ip(base_addr, yuv->out_ofst_cb & RGB2YCBCR_OFST_MASK, YUV_OFT_CB);
860         regw_ip(base_addr, yuv->out_ofst_cr & RGB2YCBCR_OFST_MASK, YUV_OFT_CR);
861 }
862
863 /* YUV 422 conversion */
864 void
865 ipipe_set_yuv422_conv_regs(void __iomem *base_addr,
866                            struct vpfe_ipipe_yuv422_conv *conv)
867 {
868         u32 val;
869
870         ipipe_clock_enable(base_addr);
871
872         /* Combine all the fields to make YUV_PHS register of IPIPE */
873         val = (conv->chrom_pos << 0) | (conv->en_chrom_lpf << 1);
874         regw_ip(base_addr, val, YUV_PHS);
875 }
876
877 void
878 ipipe_set_gbce_regs(void __iomem *base_addr, void __iomem *isp5_base_addr,
879                     struct vpfe_ipipe_gbce *gbce)
880 {
881         unsigned int count;
882         u32 mask = GBCE_Y_VAL_MASK;
883
884         if (gbce->type == VPFE_IPIPE_GBCE_GAIN_TBL)
885                 mask = GBCE_GAIN_VAL_MASK;
886
887         ipipe_clock_enable(base_addr);
888         regw_ip(base_addr, gbce->en & 1, GBCE_EN);
889
890         if (!gbce->en)
891                 return;
892
893         regw_ip(base_addr, gbce->type, GBCE_TYP);
894
895         for (count = 0; count < VPFE_IPIPE_MAX_SIZE_GBCE_LUT; count += 2)
896                 w_ip_table(isp5_base_addr, ((gbce->table[count + 1] & mask) <<
897                 GBCE_ENTRY_SHIFT) | (gbce->table[count] & mask),
898                 ((count/2) << 2) + GBCE_TB_START_ADDR);
899 }
900
901 void
902 ipipe_set_ee_regs(void __iomem *base_addr, void __iomem *isp5_base_addr,
903                   struct vpfe_ipipe_yee *ee)
904 {
905         unsigned int count;
906         u32 val;
907
908         ipipe_clock_enable(base_addr);
909         regw_ip(base_addr, ee->en, YEE_EN);
910
911         if (!ee->en)
912                 return;
913
914         val = ee->en_halo_red & 1;
915         val |= ee->merge_meth << YEE_HALO_RED_EN_SHIFT;
916         regw_ip(base_addr, val, YEE_TYP);
917
918         regw_ip(base_addr, ee->hpf_shft, YEE_SHF);
919         regw_ip(base_addr, ee->hpf_coef_00 & YEE_COEF_MASK, YEE_MUL_00);
920         regw_ip(base_addr, ee->hpf_coef_01 & YEE_COEF_MASK, YEE_MUL_01);
921         regw_ip(base_addr, ee->hpf_coef_02 & YEE_COEF_MASK, YEE_MUL_02);
922         regw_ip(base_addr, ee->hpf_coef_10 & YEE_COEF_MASK, YEE_MUL_10);
923         regw_ip(base_addr, ee->hpf_coef_11 & YEE_COEF_MASK, YEE_MUL_11);
924         regw_ip(base_addr, ee->hpf_coef_12 & YEE_COEF_MASK, YEE_MUL_12);
925         regw_ip(base_addr, ee->hpf_coef_20 & YEE_COEF_MASK, YEE_MUL_20);
926         regw_ip(base_addr, ee->hpf_coef_21 & YEE_COEF_MASK, YEE_MUL_21);
927         regw_ip(base_addr, ee->hpf_coef_22 & YEE_COEF_MASK, YEE_MUL_22);
928         regw_ip(base_addr, ee->yee_thr & YEE_THR_MASK, YEE_THR);
929         regw_ip(base_addr, ee->es_gain & YEE_ES_GAIN_MASK, YEE_E_GAN);
930         regw_ip(base_addr, ee->es_thr1 & YEE_ES_THR1_MASK, YEE_E_THR1);
931         regw_ip(base_addr, ee->es_thr2 & YEE_THR_MASK, YEE_E_THR2);
932         regw_ip(base_addr, ee->es_gain_grad & YEE_THR_MASK, YEE_G_GAN);
933         regw_ip(base_addr, ee->es_ofst_grad & YEE_THR_MASK, YEE_G_OFT);
934
935         for (count = 0; count < VPFE_IPIPE_MAX_SIZE_YEE_LUT; count += 2)
936                 w_ip_table(isp5_base_addr, ((ee->table[count + 1] &
937                 YEE_ENTRY_MASK) << YEE_ENTRY_SHIFT) |
938                 (ee->table[count] & YEE_ENTRY_MASK),
939                 ((count/2) << 2) + YEE_TB_START_ADDR);
940 }
941
942 /* Chromatic Artifact Correction. CAR */
943 static void ipipe_set_mf(void __iomem *base_addr)
944 {
945         /* typ to dynamic switch */
946         regw_ip(base_addr, VPFE_IPIPE_CAR_DYN_SWITCH, CAR_TYP);
947         /* Set SW0 to maximum */
948         regw_ip(base_addr, CAR_MF_THR, CAR_SW);
949 }
950
951 static void
952 ipipe_set_gain_ctrl(void __iomem *base_addr, struct vpfe_ipipe_car *car)
953 {
954         regw_ip(base_addr, VPFE_IPIPE_CAR_CHR_GAIN_CTRL, CAR_TYP);
955         regw_ip(base_addr, car->hpf, CAR_HPF_TYP);
956         regw_ip(base_addr, car->hpf_shft & CAR_HPF_SHIFT_MASK, CAR_HPF_SHF);
957         regw_ip(base_addr, car->hpf_thr, CAR_HPF_THR);
958         regw_ip(base_addr, car->gain1.gain, CAR_GN1_GAN);
959         regw_ip(base_addr, car->gain1.shft & CAR_GAIN1_SHFT_MASK, CAR_GN1_SHF);
960         regw_ip(base_addr, car->gain1.gain_min & CAR_GAIN_MIN_MASK,
961                 CAR_GN1_MIN);
962         regw_ip(base_addr, car->gain2.gain, CAR_GN2_GAN);
963         regw_ip(base_addr, car->gain2.shft & CAR_GAIN2_SHFT_MASK, CAR_GN2_SHF);
964         regw_ip(base_addr, car->gain2.gain_min & CAR_GAIN_MIN_MASK,
965                 CAR_GN2_MIN);
966 }
967
968 void ipipe_set_car_regs(void __iomem *base_addr, struct vpfe_ipipe_car *car)
969 {
970         u32 val;
971
972         ipipe_clock_enable(base_addr);
973         regw_ip(base_addr, car->en, CAR_EN);
974
975         if (!car->en)
976                 return;
977
978         switch (car->meth) {
979         case VPFE_IPIPE_CAR_MED_FLTR:
980                 ipipe_set_mf(base_addr);
981                 break;
982
983         case VPFE_IPIPE_CAR_CHR_GAIN_CTRL:
984                 ipipe_set_gain_ctrl(base_addr, car);
985                 break;
986
987         default:
988                 /* Dynamic switch between MF and Gain Ctrl. */
989                 ipipe_set_mf(base_addr);
990                 ipipe_set_gain_ctrl(base_addr, car);
991                 /* Set the threshold for switching between
992                  * the two Here we overwrite the MF SW0 value
993                  */
994                 regw_ip(base_addr, VPFE_IPIPE_CAR_DYN_SWITCH, CAR_TYP);
995                 val = car->sw1;
996                 val <<= CAR_SW1_SHIFT;
997                 val |= car->sw0;
998                 regw_ip(base_addr, val, CAR_SW);
999         }
1000 }
1001
1002 /* Chromatic Gain Suppression */
1003 void ipipe_set_cgs_regs(void __iomem *base_addr, struct vpfe_ipipe_cgs *cgs)
1004 {
1005         ipipe_clock_enable(base_addr);
1006         regw_ip(base_addr, cgs->en, CGS_EN);
1007
1008         if (!cgs->en)
1009                 return;
1010
1011         /* Set the bright side parameters */
1012         regw_ip(base_addr, cgs->h_thr, CGS_GN1_H_THR);
1013         regw_ip(base_addr, cgs->h_slope, CGS_GN1_H_GAN);
1014         regw_ip(base_addr, cgs->h_shft & CAR_SHIFT_MASK, CGS_GN1_H_SHF);
1015         regw_ip(base_addr, cgs->h_min, CGS_GN1_H_MIN);
1016 }
1017
1018 void rsz_src_enable(void __iomem *rsz_base, int enable)
1019 {
1020         regw_rsz(rsz_base, enable, RSZ_SRC_EN);
1021 }
1022
1023 int rsz_enable(void __iomem *rsz_base, int rsz_id, int enable)
1024 {
1025         if (rsz_id == RSZ_A) {
1026                 regw_rsz(rsz_base, enable, RSZ_EN_A);
1027                 /* We always enable RSZ_A. RSZ_B is enable upon request from
1028                  * application. So enable RSZ_SRC_EN along with RSZ_A
1029                  */
1030                 regw_rsz(rsz_base, enable, RSZ_SRC_EN);
1031         } else if (rsz_id == RSZ_B) {
1032                 regw_rsz(rsz_base, enable, RSZ_EN_B);
1033         } else {
1034                 BUG();
1035         }
1036
1037         return 0;
1038 }