1/*
2 * Copyright (C) 2012 Texas Instruments Inc
3 *
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.
7 *
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.
12 *
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
16 *
17 * Contributors:
18 *      Manjunath Hadli <manjunath.hadli@ti.com>
19 *      Prabhakar Lad <prabhakar.lad@ti.com>
20 */
21
22#include "dm365_ipipe_hw.h"
23
24#define IPIPE_MODE_CONTINUOUS		0
25#define IPIPE_MODE_SINGLE_SHOT		1
26
27static void ipipe_clock_enable(void *__iomem base_addr)
28{
29	/* enable IPIPE MMR for register write access */
30	regw_ip(base_addr, IPIPE_GCK_MMR_DEFAULT, IPIPE_GCK_MMR);
31
32	/* enable the clock wb,cfa,dfc,d2f,pre modules */
33	regw_ip(base_addr, IPIPE_GCK_PIX_DEFAULT, IPIPE_GCK_PIX);
34}
35
36static void
37rsz_set_common_params(void *__iomem rsz_base, struct resizer_params *params)
38{
39	struct rsz_common_params *rsz_common = &params->rsz_common;
40	u32 val;
41
42	/* Set mode */
43	regw_rsz(rsz_base, params->oper_mode, RSZ_SRC_MODE);
44
45	/* data source selection  and bypass */
46	val = (rsz_common->passthrough << RSZ_BYPASS_SHIFT) |
47	      rsz_common->source;
48	regw_rsz(rsz_base, val, RSZ_SRC_FMT0);
49
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);
55
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);
66}
67
68static void
69rsz_set_rsz_regs(void *__iomem rsz_base, unsigned int rsz_id,
70		 struct resizer_params *params)
71{
72	struct resizer_scale_param *rsc_params;
73	struct rsz_ext_mem_param *ext_mem;
74	struct resizer_rgb *rgb;
75	u32 reg_base;
76	u32 val;
77
78	rsc_params = &params->rsz_rsc_param[rsz_id];
79	rgb = &params->rsz2rgb[rsz_id];
80	ext_mem = &params->ext_mem_param[rsz_id];
81
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;
85		reg_base = RSZ_EN_A;
86	} else {
87		val = rsc_params->h_flip << RSZB_H_FLIP_SHIFT;
88		val |= rsc_params->v_flip << RSZB_V_FLIP_SHIFT;
89		reg_base = RSZ_EN_B;
90	}
91	/* update flip settings */
92	regw_rsz(rsz_base, val, RSZ_SEQ);
93
94	regw_rsz(rsz_base, params->oper_mode, reg_base + RSZ_MODE);
95
96	val = (rsc_params->cen << RSZ_CEN_SHIFT) | rsc_params->yen;
97	regw_rsz(rsz_base, val, reg_base + RSZ_420);
98
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);
111
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);
115
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);
119
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);
124
125	regw_rsz(rsz_base, rsc_params->h_phs &
126		RSZ_H_PHS_MASK, reg_base + RSZ_H_PHS);
127
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);
131
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);
135
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);
140
141	regw_rsz(rsz_base, rsc_params->dscale_en & 1, reg_base + RSZ_DWN_EN);
142
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);
147
148	/* setting rgb conversion parameters */
149	regw_rsz(rsz_base, rgb->rgb_en, reg_base + RSZ_RGB_EN);
150
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);
155
156	regw_rsz(rsz_base, rgb->rgb_alpha_val & RSZ_RGB_ALPHA_MASK,
157		reg_base + RSZ_RGB_BLD);
158
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);
170}
171
172/*set the registers of either RSZ0 or RSZ1 */
173static void
174ipipe_setup_resizer(void *__iomem rsz_base, struct resizer_params *params)
175{
176	/* enable MMR gate to write to Resizer */
177	regw_rsz(rsz_base, 1, RSZ_GCK_MMR);
178
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);
182	else
183		regw_rsz(rsz_base, 1, RSZ_GCK_SDR);
184
185	rsz_set_common_params(rsz_base, params);
186
187	regw_rsz(rsz_base, params->rsz_en[RSZ_A], RSZ_EN_A);
188
189	if (params->rsz_en[RSZ_A])
190		/*setting rescale parameters */
191		rsz_set_rsz_regs(rsz_base, RSZ_A, params);
192
193	regw_rsz(rsz_base, params->rsz_en[RSZ_B], RSZ_EN_B);
194
195	if (params->rsz_en[RSZ_B])
196		rsz_set_rsz_regs(rsz_base, RSZ_B, params);
197}
198
199static u32 ipipe_get_color_pat(enum v4l2_mbus_pixelcode pix)
200{
201	switch (pix) {
202	case V4L2_MBUS_FMT_SGRBG10_ALAW8_1X8:
203	case V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8:
204	case V4L2_MBUS_FMT_SGRBG12_1X12:
205		return ipipe_sgrbg_pattern;
206
207	default:
208		return ipipe_srggb_pattern;
209	}
210}
211
212static int ipipe_get_data_path(struct vpfe_ipipe_device *ipipe)
213{
214	enum v4l2_mbus_pixelcode temp_pix_fmt;
215
216	switch (ipipe->formats[IPIPE_PAD_SINK].code) {
217	case V4L2_MBUS_FMT_SBGGR8_1X8:
218	case V4L2_MBUS_FMT_SGRBG10_ALAW8_1X8:
219	case V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8:
220	case V4L2_MBUS_FMT_SGRBG12_1X12:
221		temp_pix_fmt = V4L2_MBUS_FMT_SGRBG12_1X12;
222		break;
223
224	default:
225		temp_pix_fmt = V4L2_MBUS_FMT_UYVY8_2X8;
226	}
227
228	if (temp_pix_fmt == V4L2_MBUS_FMT_SGRBG12_1X12) {
229		if (ipipe->formats[IPIPE_PAD_SOURCE].code ==
230			V4L2_MBUS_FMT_SGRBG12_1X12)
231			return IPIPE_RAW2RAW;
232		return IPIPE_RAW2YUV;
233	}
234
235	return IPIPE_YUV2YUV;
236}
237
238static int get_ipipe_mode(struct vpfe_ipipe_device *ipipe)
239{
240	struct vpfe_device *vpfe_dev = to_vpfe_device(ipipe);
241	u16 ipipeif_sink = vpfe_dev->vpfe_ipipeif.input;
242
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;
247
248	return -EINVAL;
249}
250
251int config_ipipe_hw(struct vpfe_ipipe_device *ipipe)
252{
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;
256	u32 color_pat;
257	u32 ipipe_mode;
258	u32 data_path;
259
260	/* enable clock to IPIPE */
261	vpss_enable_clock(VPSS_IPIPE_CLOCK, 1);
262	ipipe_clock_enable(ipipe_base);
263
264	if (ipipe->input == IPIPE_INPUT_NONE) {
265		regw_ip(ipipe_base, 0, IPIPE_SRC_EN);
266		return 0;
267	}
268
269	ipipe_mode = get_ipipe_mode(ipipe);
270	if (ipipe_mode < 0) {
271		pr_err("Failed to get ipipe mode");
272		return -EINVAL;
273	}
274	regw_ip(ipipe_base, ipipe_mode, IPIPE_SRC_MODE);
275
276	data_path = ipipe_get_data_path(ipipe);
277	regw_ip(ipipe_base, data_path, IPIPE_SRC_FMT);
278
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);
281
282	outformat = &ipipe->formats[IPIPE_PAD_SOURCE];
283	regw_ip(ipipe_base, (outformat->height + 1) & IPIPE_RSZ_VSZ_MASK,
284		IPIPE_SRC_VSZ);
285	regw_ip(ipipe_base, (outformat->width + 1) & IPIPE_RSZ_HSZ_MASK,
286		IPIPE_SRC_HSZ);
287
288	if (data_path == IPIPE_RAW2YUV ||
289	    data_path == IPIPE_RAW2RAW) {
290		color_pat =
291		ipipe_get_color_pat(ipipe->formats[IPIPE_PAD_SINK].code);
292		regw_ip(ipipe_base, color_pat, IPIPE_SRC_COL);
293	}
294
295	return 0;
296}
297
298/*
299 * config_rsz_hw() - Performs hardware setup of resizer.
300 */
301int config_rsz_hw(struct vpfe_resizer_device *resizer,
302		  struct resizer_params *config)
303{
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;
307
308	/* enable VPSS clock */
309	vpss_enable_clock(VPSS_IPIPE_CLOCK, 1);
310	ipipe_clock_enable(ipipe_base);
311
312	ipipe_setup_resizer(rsz_base, config);
313
314	return 0;
315}
316
317static void
318rsz_set_y_address(void *__iomem rsz_base, unsigned int address,
319		  unsigned int offset)
320{
321	u32 val;
322
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);
326
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);
330}
331
332static void
333rsz_set_c_address(void *__iomem rsz_base, unsigned int address,
334		  unsigned int offset)
335{
336	u32 val;
337
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);
341
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);
345}
346
347/*
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
353 */
354int
355resizer_set_outaddr(void *__iomem rsz_base, struct resizer_params *params,
356		    int resize_no, unsigned int address)
357{
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;
362	unsigned int val;
363
364	if (resize_no != RSZ_A && resize_no != RSZ_B)
365		return -EINVAL;
366
367	mem_param = &params->ext_mem_param[resize_no];
368	rsc_param = &params->rsz_rsc_param[resize_no];
369	rsz_common = &params->rsz_common;
370
371	if (resize_no == RSZ_A)
372		rsz_start_add = RSZ_EN_A;
373	else
374		rsz_start_add = RSZ_EN_B;
375
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) {
379			/* C channel */
380			val = address + mem_param->flip_ofst_c;
381			rsz_set_c_address(rsz_base, val, rsz_start_add);
382		} else {
383			val = address + mem_param->flip_ofst_y;
384			rsz_set_y_address(rsz_base, val, rsz_start_add);
385		}
386	} else {
387		if (rsc_param->cen && rsc_param->yen) {
388			/* 420 */
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)
394				val +=
395				params->ext_mem_param[RSZ_A].user_y_ofst +
396				params->ext_mem_param[RSZ_A].user_c_ofst;
397			/* set C address */
398			rsz_set_c_address(rsz_base, val, rsz_start_add);
399		}
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;
404		/* set Y address */
405		rsz_set_y_address(rsz_base, val, rsz_start_add);
406	}
407	/* resizer must be enabled */
408	regw_rsz(rsz_base, params->rsz_en[resize_no], rsz_start_add);
409
410	return 0;
411}
412
413void
414ipipe_set_lutdpc_regs(void *__iomem base_addr, void *__iomem isp5_base_addr,
415		      struct vpfe_ipipe_lutdpc *dpc)
416{
417	u32 max_tbl_size = LUT_DPC_MAX_SIZE >> 1;
418	u32 lut_start_addr = DPC_TB0_START_ADDR;
419	u32 val;
420	u32 count;
421
422	ipipe_clock_enable(base_addr);
423	regw_ip(base_addr, dpc->en, DPC_LUT_EN);
424
425	if (dpc->en != 1)
426		return;
427
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);
432
433	if (dpc->table == NULL)
434		return;
435
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)));
445	}
446}
447
448static void
449set_dpc_thresholds(void *__iomem base_addr,
450		   struct vpfe_ipipe_otfdpc_2_0_cfg *dpc_thr)
451{
452	regw_ip(base_addr, dpc_thr->corr_thr.r & OTFDPC_DPC2_THR_MASK,
453		DPC_OTF_2C_THR_R);
454	regw_ip(base_addr, dpc_thr->corr_thr.gr & OTFDPC_DPC2_THR_MASK,
455		DPC_OTF_2C_THR_GR);
456	regw_ip(base_addr, dpc_thr->corr_thr.gb & OTFDPC_DPC2_THR_MASK,
457		DPC_OTF_2C_THR_GB);
458	regw_ip(base_addr, dpc_thr->corr_thr.b & OTFDPC_DPC2_THR_MASK,
459		DPC_OTF_2C_THR_B);
460	regw_ip(base_addr, dpc_thr->det_thr.r & OTFDPC_DPC2_THR_MASK,
461		DPC_OTF_2D_THR_R);
462	regw_ip(base_addr, dpc_thr->det_thr.gr & OTFDPC_DPC2_THR_MASK,
463		DPC_OTF_2D_THR_GR);
464	regw_ip(base_addr, dpc_thr->det_thr.gb & OTFDPC_DPC2_THR_MASK,
465		DPC_OTF_2D_THR_GB);
466	regw_ip(base_addr, dpc_thr->det_thr.b & OTFDPC_DPC2_THR_MASK,
467		DPC_OTF_2D_THR_B);
468}
469
470void ipipe_set_otfdpc_regs(void *__iomem base_addr,
471			   struct vpfe_ipipe_otfdpc *otfdpc)
472{
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;
475	u32 val;
476
477	ipipe_clock_enable(base_addr);
478
479	regw_ip(base_addr, (otfdpc->en & 1), DPC_OTF_EN);
480	if (!otfdpc->en)
481		return;
482
483	/* dpc enabled */
484	val = (otfdpc->det_method << OTF_DET_METHOD_SHIFT) | otfdpc->alg;
485	regw_ip(base_addr, val, DPC_OTF_TYP);
486
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
490		 * MinMax method
491		 */
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);
495		return;
496	}
497	/* MinMax2 */
498	if (otfdpc->alg == VPFE_IPIPE_OTFDPC_2_0) {
499		set_dpc_thresholds(base_addr, dpc_2_0);
500		return;
501	}
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);
522}
523
524/* 2D Noise filter */
525void
526ipipe_set_d2f_regs(void *__iomem base_addr, unsigned int id,
527		   struct vpfe_ipipe_nf *noise_filter)
528{
529
530	u32 offset = D2F_1ST;
531	int count;
532	u32 val;
533
534	if (id == IPIPE_D2F_2ND)
535		offset = D2F_2ND;
536
537	ipipe_clock_enable(base_addr);
538	regw_ip(base_addr, noise_filter->en & 1, offset + D2F_EN);
539	if (!noise_filter->en)
540		return;
541
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);
551
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);
555
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);
559
560	for (count = 0; count < VPFE_IPIPE_NF_STR_TABLE_SIZE; count++)
561		regw_ip(base_addr,
562			(noise_filter->str[count] & D2F_STR_VAL_MASK),
563			offset + D2F_STR + count * 4);
564
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);
568}
569
570#define IPIPE_U8Q5(decimal, integer) \
571	(((decimal & 0x1f) | ((integer & 0x7) << 5)))
572
573/* Green Imbalance Correction */
574void ipipe_set_gic_regs(void *__iomem base_addr, struct vpfe_ipipe_gic *gic)
575{
576	u32 val;
577
578	ipipe_clock_enable(base_addr);
579	regw_ip(base_addr, gic->en & 1, GIC_EN);
580
581	if (!gic->en)
582		return;
583
584	/*gic enabled */
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);
589
590	regw_ip(base_addr, gic->gain & GIC_GAIN_MASK, GIC_GAN);
591
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);
595		return;
596	}
597
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);
601	} else {
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);
606	}
607}
608
609#define IPIPE_U13Q9(decimal, integer) \
610	(((decimal & 0x1ff) | ((integer & 0xf) << 9)))
611/* White balance */
612void ipipe_set_wb_regs(void *__iomem base_addr, struct vpfe_ipipe_wb *wb)
613{
614	u32 val;
615
616	ipipe_clock_enable(base_addr);
617	/* Ofsets. S12 */
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);
622
623	/* Gains. U13Q9 */
624	val = IPIPE_U13Q9(wb->gain_r.decimal, wb->gain_r.integer);
625	regw_ip(base_addr, val, WB2_WGN_R);
626
627	val = IPIPE_U13Q9(wb->gain_gr.decimal, wb->gain_gr.integer);
628	regw_ip(base_addr, val, WB2_WGN_GR);
629
630	val = IPIPE_U13Q9(wb->gain_gb.decimal, wb->gain_gb.integer);
631	regw_ip(base_addr, val, WB2_WGN_GB);
632
633	val = IPIPE_U13Q9(wb->gain_b.decimal, wb->gain_b.integer);
634	regw_ip(base_addr, val, WB2_WGN_B);
635}
636
637/* CFA */
638void ipipe_set_cfa_regs(void *__iomem base_addr, struct vpfe_ipipe_cfa *cfa)
639{
640	ipipe_clock_enable(base_addr);
641
642	regw_ip(base_addr, cfa->alg, CFA_MODE);
643	regw_ip(base_addr, cfa->hpf_thr_2dir & CFA_HPF_THR_2DIR_MASK,
644		CFA_2DIR_HPF_THR);
645	regw_ip(base_addr, cfa->hpf_slp_2dir & CFA_HPF_SLOPE_2DIR_MASK,
646		CFA_2DIR_HPF_SLP);
647	regw_ip(base_addr, cfa->hp_mix_thr_2dir & CFA_HPF_MIX_THR_2DIR_MASK,
648		CFA_2DIR_MIX_THR);
649	regw_ip(base_addr, cfa->hp_mix_slope_2dir & CFA_HPF_MIX_SLP_2DIR_MASK,
650		CFA_2DIR_MIX_SLP);
651	regw_ip(base_addr, cfa->dir_thr_2dir & CFA_DIR_THR_2DIR_MASK,
652		CFA_2DIR_DIR_THR);
653	regw_ip(base_addr, cfa->dir_slope_2dir & CFA_DIR_SLP_2DIR_MASK,
654		CFA_2DIR_DIR_SLP);
655	regw_ip(base_addr, cfa->nd_wt_2dir & CFA_ND_WT_2DIR_MASK,
656		CFA_2DIR_NDWT);
657	regw_ip(base_addr, cfa->hue_fract_daa & CFA_DAA_HUE_FRA_MASK,
658		CFA_MONO_HUE_FRA);
659	regw_ip(base_addr, cfa->edge_thr_daa & CFA_DAA_EDG_THR_MASK,
660		CFA_MONO_EDG_THR);
661	regw_ip(base_addr, cfa->thr_min_daa & CFA_DAA_THR_MIN_MASK,
662		CFA_MONO_THR_MIN);
663	regw_ip(base_addr, cfa->thr_slope_daa & CFA_DAA_THR_SLP_MASK,
664		CFA_MONO_THR_SLP);
665	regw_ip(base_addr, cfa->slope_min_daa & CFA_DAA_SLP_MIN_MASK,
666		CFA_MONO_SLP_MIN);
667	regw_ip(base_addr, cfa->slope_slope_daa & CFA_DAA_SLP_SLP_MASK,
668		CFA_MONO_SLP_SLP);
669	regw_ip(base_addr, cfa->lp_wt_daa & CFA_DAA_LP_WT_MASK,
670		CFA_MONO_LPWT);
671}
672
673void
674ipipe_set_rgb2rgb_regs(void *__iomem base_addr, unsigned int id,
675		       struct vpfe_ipipe_rgb2rgb *rgb)
676{
677	u32 offset_mask = RGB2RGB_1_OFST_MASK;
678	u32 offset = RGB1_MUL_BASE;
679	u32 integ_mask = 0xf;
680	u32 val;
681
682	ipipe_clock_enable(base_addr);
683
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;
688		integ_mask = 0x7;
689		offset_mask = RGB2RGB_2_OFST_MASK;
690	}
691	/* Gains */
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);
719
720	/* Offsets */
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);
724}
725
726static void
727ipipe_update_gamma_tbl(void *__iomem isp5_base_addr,
728	struct vpfe_ipipe_gamma_entry *table, int size, u32 addr)
729{
730	int count;
731	u32 val;
732
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)));
737	}
738}
739
740void
741ipipe_set_gamma_regs(void *__iomem base_addr, void *__iomem isp5_base_addr,
742			  struct vpfe_ipipe_gamma *gamma)
743{
744	int table_size;
745	u32 val;
746
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);
753
754	regw_ip(base_addr, val, GMM_CFG);
755
756	if (gamma->tbl_sel != VPFE_IPIPE_GAMMA_TBL_RAM)
757		return;
758
759	table_size = gamma->tbl_size;
760
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);
770}
771
772void
773ipipe_set_3d_lut_regs(void *__iomem base_addr, void *__iomem isp5_base_addr,
774			   struct vpfe_ipipe_3d_lut *lut_3d)
775{
776	struct vpfe_ipipe_3d_lut_entry *tbl;
777	u32 bnk_index;
778	u32 tbl_index;
779	u32 val;
780	u32 i;
781
782	ipipe_clock_enable(base_addr);
783	regw_ip(base_addr, lut_3d->en, D3LUT_EN);
784
785	if (!lut_3d->en)
786		return;
787
788	/* lut_3d enabled */
789	if (!lut_3d->table)
790		return;
791
792	/* valied table */
793	tbl = lut_3d->table;
794	for (i = 0; i < VPFE_IPIPE_MAX_SIZE_3D_LUT; i++) {
795		/* Each entry has 0-9 (B), 10-19 (G) and
796		20-29 R values */
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;
802		bnk_index = i % 4;
803		tbl_index = i >> 2;
804		tbl_index <<= 2;
805		if (bnk_index == 0)
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);
814		else
815			w_ip_table(isp5_base_addr, val,
816				   tbl_index + D3L_TB3_START_ADDR);
817	}
818}
819
820/* Lumina adjustments */
821void
822ipipe_set_lum_adj_regs(void *__iomem base_addr, struct ipipe_lum_adj *lum_adj)
823{
824	u32 val;
825
826	ipipe_clock_enable(base_addr);
827
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);
832}
833
834#define IPIPE_S12Q8(decimal, integer) \
835	(((decimal & 0xff) | ((integer & 0xf) << 8)))
836
837void ipipe_set_rgb2ycbcr_regs(void *__iomem base_addr,
838			      struct vpfe_ipipe_rgb2yuv *yuv)
839{
840	u32 val;
841
842	/* S10Q8 */
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);
865}
866
867/* YUV 422 conversion */
868void
869ipipe_set_yuv422_conv_regs(void *__iomem base_addr,
870			   struct vpfe_ipipe_yuv422_conv *conv)
871{
872	u32 val;
873
874	ipipe_clock_enable(base_addr);
875
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);
879}
880
881void
882ipipe_set_gbce_regs(void *__iomem base_addr, void *__iomem isp5_base_addr,
883		    struct vpfe_ipipe_gbce *gbce)
884{
885	unsigned int count;
886	u32 mask = GBCE_Y_VAL_MASK;
887
888	if (gbce->type == VPFE_IPIPE_GBCE_GAIN_TBL)
889		mask = GBCE_GAIN_VAL_MASK;
890
891	ipipe_clock_enable(base_addr);
892	regw_ip(base_addr, gbce->en & 1, GBCE_EN);
893
894	if (!gbce->en)
895		return;
896
897	regw_ip(base_addr, gbce->type, GBCE_TYP);
898
899	if (!gbce->table)
900		return;
901
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);
906}
907
908void
909ipipe_set_ee_regs(void *__iomem base_addr, void *__iomem isp5_base_addr,
910		  struct vpfe_ipipe_yee *ee)
911{
912	unsigned int count;
913	u32 val;
914
915	ipipe_clock_enable(base_addr);
916	regw_ip(base_addr, ee->en, YEE_EN);
917
918	if (!ee->en)
919		return;
920
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);
924
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);
941
942	if (ee->table == NULL)
943		return;
944
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);
950}
951
952/* Chromatic Artifact Correction. CAR */
953static void ipipe_set_mf(void *__iomem base_addr)
954{
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);
959}
960
961static void
962ipipe_set_gain_ctrl(void *__iomem base_addr, struct vpfe_ipipe_car *car)
963{
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,
971		CAR_GN1_MIN);
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,
975		CAR_GN2_MIN);
976}
977
978void ipipe_set_car_regs(void *__iomem base_addr, struct vpfe_ipipe_car *car)
979{
980	u32 val;
981
982	ipipe_clock_enable(base_addr);
983	regw_ip(base_addr, car->en, CAR_EN);
984
985	if (!car->en)
986		return;
987
988	switch (car->meth) {
989	case VPFE_IPIPE_CAR_MED_FLTR:
990		ipipe_set_mf(base_addr);
991		break;
992
993	case VPFE_IPIPE_CAR_CHR_GAIN_CTRL:
994		ipipe_set_gain_ctrl(base_addr, car);
995		break;
996
997	default:
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
1003		  */
1004		regw_ip(base_addr, VPFE_IPIPE_CAR_DYN_SWITCH, CAR_TYP);
1005		val = car->sw1;
1006		val <<= CAR_SW1_SHIFT;
1007		val |= car->sw0;
1008		regw_ip(base_addr, val, CAR_SW);
1009	}
1010}
1011
1012/* Chromatic Gain Suppression */
1013void ipipe_set_cgs_regs(void *__iomem base_addr, struct vpfe_ipipe_cgs *cgs)
1014{
1015	ipipe_clock_enable(base_addr);
1016	regw_ip(base_addr, cgs->en, CGS_EN);
1017
1018	if (!cgs->en)
1019		return;
1020
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);
1026}
1027
1028void rsz_src_enable(void *__iomem rsz_base, int enable)
1029{
1030	regw_rsz(rsz_base, enable, RSZ_SRC_EN);
1031}
1032
1033int rsz_enable(void *__iomem rsz_base, int rsz_id, int enable)
1034{
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
1039		 */
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);
1043	} else {
1044		BUG();
1045	}
1046
1047	return 0;
1048}
1049