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 
ipipe_clock_enable(void __iomem * base_addr)27 static 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 
36 static void
rsz_set_common_params(void __iomem * rsz_base,struct resizer_params * params)37 rsz_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 
68 static void
rsz_set_rsz_regs(void __iomem * rsz_base,unsigned int rsz_id,struct resizer_params * params)69 rsz_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 */
173 static void
ipipe_setup_resizer(void __iomem * rsz_base,struct resizer_params * params)174 ipipe_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 
ipipe_get_color_pat(u32 pix)199 static u32 ipipe_get_color_pat(u32 pix)
200 {
201 	switch (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;
206 
207 	default:
208 		return ipipe_srggb_pattern;
209 	}
210 }
211 
ipipe_get_data_path(struct vpfe_ipipe_device * ipipe)212 static int ipipe_get_data_path(struct vpfe_ipipe_device *ipipe)
213 {
214 	u32 temp_pix_fmt;
215 
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;
222 		break;
223 
224 	default:
225 		temp_pix_fmt = MEDIA_BUS_FMT_UYVY8_2X8;
226 	}
227 
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;
233 	}
234 
235 	return IPIPE_YUV2YUV;
236 }
237 
get_ipipe_mode(struct vpfe_ipipe_device * ipipe)238 static 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 	if (ipipeif_sink == IPIPEIF_INPUT_ISIF)
246 		return IPIPE_MODE_CONTINUOUS;
247 
248 	return -EINVAL;
249 }
250 
config_ipipe_hw(struct vpfe_ipipe_device * ipipe)251 int 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 	int 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  */
config_rsz_hw(struct vpfe_resizer_device * resizer,struct resizer_params * config)301 int 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 
317 static void
rsz_set_y_address(void __iomem * rsz_base,unsigned int address,unsigned int offset)318 rsz_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 
332 static void
rsz_set_c_address(void __iomem * rsz_base,unsigned int address,unsigned int offset)333 rsz_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  */
354 int
resizer_set_outaddr(void __iomem * rsz_base,struct resizer_params * params,int resize_no,unsigned int address)355 resizer_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 
413 void
ipipe_set_lutdpc_regs(void __iomem * base_addr,void __iomem * isp5_base_addr,struct vpfe_ipipe_lutdpc * dpc)414 ipipe_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 	for (count = 0; count < dpc->dpc_size; count++) {
434 		if (count >= max_tbl_size)
435 			lut_start_addr = DPC_TB1_START_ADDR;
436 		val = (dpc->table[count].horz_pos & LUT_DPC_H_POS_MASK) |
437 		      ((dpc->table[count].vert_pos & LUT_DPC_V_POS_MASK) <<
438 			LUT_DPC_V_POS_SHIFT) | (dpc->table[count].method <<
439 			LUT_DPC_CORR_METH_SHIFT);
440 		w_ip_table(isp5_base_addr, val, (lut_start_addr +
441 		((count % max_tbl_size) << 2)));
442 	}
443 }
444 
445 static void
set_dpc_thresholds(void __iomem * base_addr,struct vpfe_ipipe_otfdpc_2_0_cfg * dpc_thr)446 set_dpc_thresholds(void __iomem *base_addr,
447 		   struct vpfe_ipipe_otfdpc_2_0_cfg *dpc_thr)
448 {
449 	regw_ip(base_addr, dpc_thr->corr_thr.r & OTFDPC_DPC2_THR_MASK,
450 		DPC_OTF_2C_THR_R);
451 	regw_ip(base_addr, dpc_thr->corr_thr.gr & OTFDPC_DPC2_THR_MASK,
452 		DPC_OTF_2C_THR_GR);
453 	regw_ip(base_addr, dpc_thr->corr_thr.gb & OTFDPC_DPC2_THR_MASK,
454 		DPC_OTF_2C_THR_GB);
455 	regw_ip(base_addr, dpc_thr->corr_thr.b & OTFDPC_DPC2_THR_MASK,
456 		DPC_OTF_2C_THR_B);
457 	regw_ip(base_addr, dpc_thr->det_thr.r & OTFDPC_DPC2_THR_MASK,
458 		DPC_OTF_2D_THR_R);
459 	regw_ip(base_addr, dpc_thr->det_thr.gr & OTFDPC_DPC2_THR_MASK,
460 		DPC_OTF_2D_THR_GR);
461 	regw_ip(base_addr, dpc_thr->det_thr.gb & OTFDPC_DPC2_THR_MASK,
462 		DPC_OTF_2D_THR_GB);
463 	regw_ip(base_addr, dpc_thr->det_thr.b & OTFDPC_DPC2_THR_MASK,
464 		DPC_OTF_2D_THR_B);
465 }
466 
ipipe_set_otfdpc_regs(void __iomem * base_addr,struct vpfe_ipipe_otfdpc * otfdpc)467 void ipipe_set_otfdpc_regs(void __iomem *base_addr,
468 			   struct vpfe_ipipe_otfdpc *otfdpc)
469 {
470 	struct vpfe_ipipe_otfdpc_2_0_cfg *dpc_2_0 = &otfdpc->alg_cfg.dpc_2_0;
471 	struct vpfe_ipipe_otfdpc_3_0_cfg *dpc_3_0 = &otfdpc->alg_cfg.dpc_3_0;
472 	u32 val;
473 
474 	ipipe_clock_enable(base_addr);
475 
476 	regw_ip(base_addr, (otfdpc->en & 1), DPC_OTF_EN);
477 	if (!otfdpc->en)
478 		return;
479 
480 	/* dpc enabled */
481 	val = (otfdpc->det_method << OTF_DET_METHOD_SHIFT) | otfdpc->alg;
482 	regw_ip(base_addr, val, DPC_OTF_TYP);
483 
484 	if (otfdpc->det_method == VPFE_IPIPE_DPC_OTF_MIN_MAX) {
485 		/* ALG= 0, TYP = 0, DPC_OTF_2D_THR_[x]=0
486 		 * DPC_OTF_2C_THR_[x] = Maximum thresohld
487 		 * MinMax method
488 		 */
489 		dpc_2_0->det_thr.r = dpc_2_0->det_thr.gb =
490 		dpc_2_0->det_thr.gr = dpc_2_0->det_thr.b = 0;
491 		set_dpc_thresholds(base_addr, dpc_2_0);
492 		return;
493 	}
494 	/* MinMax2 */
495 	if (otfdpc->alg == VPFE_IPIPE_OTFDPC_2_0) {
496 		set_dpc_thresholds(base_addr, dpc_2_0);
497 		return;
498 	}
499 	regw_ip(base_addr, dpc_3_0->act_adj_shf &
500 		OTF_DPC3_0_SHF_MASK, DPC_OTF_3_SHF);
501 	/* Detection thresholds */
502 	regw_ip(base_addr, ((dpc_3_0->det_thr & OTF_DPC3_0_THR_MASK) <<
503 		OTF_DPC3_0_THR_SHIFT), DPC_OTF_3D_THR);
504 	regw_ip(base_addr, dpc_3_0->det_slp &
505 		OTF_DPC3_0_SLP_MASK, DPC_OTF_3D_SLP);
506 	regw_ip(base_addr, dpc_3_0->det_thr_min &
507 		OTF_DPC3_0_DET_MASK, DPC_OTF_3D_MIN);
508 	regw_ip(base_addr, dpc_3_0->det_thr_max &
509 		OTF_DPC3_0_DET_MASK, DPC_OTF_3D_MAX);
510 	/* Correction thresholds */
511 	regw_ip(base_addr, ((dpc_3_0->corr_thr & OTF_DPC3_0_THR_MASK) <<
512 		OTF_DPC3_0_THR_SHIFT), DPC_OTF_3C_THR);
513 	regw_ip(base_addr, dpc_3_0->corr_slp &
514 		OTF_DPC3_0_SLP_MASK, DPC_OTF_3C_SLP);
515 	regw_ip(base_addr, dpc_3_0->corr_thr_min &
516 		OTF_DPC3_0_CORR_MASK, DPC_OTF_3C_MIN);
517 	regw_ip(base_addr, dpc_3_0->corr_thr_max &
518 		OTF_DPC3_0_CORR_MASK, DPC_OTF_3C_MAX);
519 }
520 
521 /* 2D Noise filter */
522 void
ipipe_set_d2f_regs(void __iomem * base_addr,unsigned int id,struct vpfe_ipipe_nf * noise_filter)523 ipipe_set_d2f_regs(void __iomem *base_addr, unsigned int id,
524 		   struct vpfe_ipipe_nf *noise_filter)
525 {
526 
527 	u32 offset = D2F_1ST;
528 	int count;
529 	u32 val;
530 
531 	if (id == IPIPE_D2F_2ND)
532 		offset = D2F_2ND;
533 
534 	ipipe_clock_enable(base_addr);
535 	regw_ip(base_addr, noise_filter->en & 1, offset + D2F_EN);
536 	if (!noise_filter->en)
537 		return;
538 
539 	/*noise filter enabled */
540 	/* Combine all the fields to make D2F_CFG register of IPIPE */
541 	val = ((noise_filter->spread_val & D2F_SPR_VAL_MASK) <<
542 		D2F_SPR_VAL_SHIFT) | ((noise_filter->shft_val &
543 		D2F_SHFT_VAL_MASK) << D2F_SHFT_VAL_SHIFT) |
544 		(noise_filter->gr_sample_meth << D2F_SAMPLE_METH_SHIFT) |
545 		((noise_filter->apply_lsc_gain & 1) <<
546 		D2F_APPLY_LSC_GAIN_SHIFT) | D2F_USE_SPR_REG_VAL;
547 	regw_ip(base_addr, val, offset + D2F_TYP);
548 
549 	/* edge detection minimum */
550 	regw_ip(base_addr, noise_filter->edge_det_min_thr &
551 		D2F_EDGE_DET_THR_MASK, offset + D2F_EDG_MIN);
552 
553 	/* edge detection maximum */
554 	regw_ip(base_addr, noise_filter->edge_det_max_thr &
555 		D2F_EDGE_DET_THR_MASK, offset + D2F_EDG_MAX);
556 
557 	for (count = 0; count < VPFE_IPIPE_NF_STR_TABLE_SIZE; count++)
558 		regw_ip(base_addr,
559 			(noise_filter->str[count] & D2F_STR_VAL_MASK),
560 			offset + D2F_STR + count * 4);
561 
562 	for (count = 0; count < VPFE_IPIPE_NF_THR_TABLE_SIZE; count++)
563 		regw_ip(base_addr, noise_filter->thr[count] & D2F_THR_VAL_MASK,
564 			offset + D2F_THR + count * 4);
565 }
566 
567 #define IPIPE_U8Q5(decimal, integer) \
568 	(((decimal & 0x1f) | ((integer & 0x7) << 5)))
569 
570 /* Green Imbalance Correction */
ipipe_set_gic_regs(void __iomem * base_addr,struct vpfe_ipipe_gic * gic)571 void ipipe_set_gic_regs(void __iomem *base_addr, struct vpfe_ipipe_gic *gic)
572 {
573 	u32 val;
574 
575 	ipipe_clock_enable(base_addr);
576 	regw_ip(base_addr, gic->en & 1, GIC_EN);
577 
578 	if (!gic->en)
579 		return;
580 
581 	/*gic enabled */
582 	val = (gic->wt_fn_type << GIC_TYP_SHIFT) |
583 	      (gic->thr_sel << GIC_THR_SEL_SHIFT) |
584 	      ((gic->apply_lsc_gain & 1) << GIC_APPLY_LSC_GAIN_SHIFT);
585 	regw_ip(base_addr, val, GIC_TYP);
586 
587 	regw_ip(base_addr, gic->gain & GIC_GAIN_MASK, GIC_GAN);
588 
589 	if (gic->gic_alg != VPFE_IPIPE_GIC_ALG_ADAPT_GAIN) {
590 		/* Constant Gain. Set threshold to maximum */
591 		regw_ip(base_addr, GIC_THR_MASK, GIC_THR);
592 		return;
593 	}
594 
595 	if (gic->thr_sel == VPFE_IPIPE_GIC_THR_REG) {
596 		regw_ip(base_addr, gic->thr & GIC_THR_MASK, GIC_THR);
597 		regw_ip(base_addr, gic->slope & GIC_SLOPE_MASK, GIC_SLP);
598 	} else {
599 		/* Use NF thresholds */
600 		val = IPIPE_U8Q5(gic->nf2_thr_gain.decimal,
601 				gic->nf2_thr_gain.integer);
602 		regw_ip(base_addr, val, GIC_NFGAN);
603 	}
604 }
605 
606 #define IPIPE_U13Q9(decimal, integer) \
607 	(((decimal & 0x1ff) | ((integer & 0xf) << 9)))
608 /* White balance */
ipipe_set_wb_regs(void __iomem * base_addr,struct vpfe_ipipe_wb * wb)609 void ipipe_set_wb_regs(void __iomem *base_addr, struct vpfe_ipipe_wb *wb)
610 {
611 	u32 val;
612 
613 	ipipe_clock_enable(base_addr);
614 	/* Ofsets. S12 */
615 	regw_ip(base_addr, wb->ofst_r & WB_OFFSET_MASK, WB2_OFT_R);
616 	regw_ip(base_addr, wb->ofst_gr & WB_OFFSET_MASK, WB2_OFT_GR);
617 	regw_ip(base_addr, wb->ofst_gb & WB_OFFSET_MASK, WB2_OFT_GB);
618 	regw_ip(base_addr, wb->ofst_b & WB_OFFSET_MASK, WB2_OFT_B);
619 
620 	/* Gains. U13Q9 */
621 	val = IPIPE_U13Q9(wb->gain_r.decimal, wb->gain_r.integer);
622 	regw_ip(base_addr, val, WB2_WGN_R);
623 
624 	val = IPIPE_U13Q9(wb->gain_gr.decimal, wb->gain_gr.integer);
625 	regw_ip(base_addr, val, WB2_WGN_GR);
626 
627 	val = IPIPE_U13Q9(wb->gain_gb.decimal, wb->gain_gb.integer);
628 	regw_ip(base_addr, val, WB2_WGN_GB);
629 
630 	val = IPIPE_U13Q9(wb->gain_b.decimal, wb->gain_b.integer);
631 	regw_ip(base_addr, val, WB2_WGN_B);
632 }
633 
634 /* CFA */
ipipe_set_cfa_regs(void __iomem * base_addr,struct vpfe_ipipe_cfa * cfa)635 void ipipe_set_cfa_regs(void __iomem *base_addr, struct vpfe_ipipe_cfa *cfa)
636 {
637 	ipipe_clock_enable(base_addr);
638 
639 	regw_ip(base_addr, cfa->alg, CFA_MODE);
640 	regw_ip(base_addr, cfa->hpf_thr_2dir & CFA_HPF_THR_2DIR_MASK,
641 		CFA_2DIR_HPF_THR);
642 	regw_ip(base_addr, cfa->hpf_slp_2dir & CFA_HPF_SLOPE_2DIR_MASK,
643 		CFA_2DIR_HPF_SLP);
644 	regw_ip(base_addr, cfa->hp_mix_thr_2dir & CFA_HPF_MIX_THR_2DIR_MASK,
645 		CFA_2DIR_MIX_THR);
646 	regw_ip(base_addr, cfa->hp_mix_slope_2dir & CFA_HPF_MIX_SLP_2DIR_MASK,
647 		CFA_2DIR_MIX_SLP);
648 	regw_ip(base_addr, cfa->dir_thr_2dir & CFA_DIR_THR_2DIR_MASK,
649 		CFA_2DIR_DIR_THR);
650 	regw_ip(base_addr, cfa->dir_slope_2dir & CFA_DIR_SLP_2DIR_MASK,
651 		CFA_2DIR_DIR_SLP);
652 	regw_ip(base_addr, cfa->nd_wt_2dir & CFA_ND_WT_2DIR_MASK,
653 		CFA_2DIR_NDWT);
654 	regw_ip(base_addr, cfa->hue_fract_daa & CFA_DAA_HUE_FRA_MASK,
655 		CFA_MONO_HUE_FRA);
656 	regw_ip(base_addr, cfa->edge_thr_daa & CFA_DAA_EDG_THR_MASK,
657 		CFA_MONO_EDG_THR);
658 	regw_ip(base_addr, cfa->thr_min_daa & CFA_DAA_THR_MIN_MASK,
659 		CFA_MONO_THR_MIN);
660 	regw_ip(base_addr, cfa->thr_slope_daa & CFA_DAA_THR_SLP_MASK,
661 		CFA_MONO_THR_SLP);
662 	regw_ip(base_addr, cfa->slope_min_daa & CFA_DAA_SLP_MIN_MASK,
663 		CFA_MONO_SLP_MIN);
664 	regw_ip(base_addr, cfa->slope_slope_daa & CFA_DAA_SLP_SLP_MASK,
665 		CFA_MONO_SLP_SLP);
666 	regw_ip(base_addr, cfa->lp_wt_daa & CFA_DAA_LP_WT_MASK,
667 		CFA_MONO_LPWT);
668 }
669 
670 void
ipipe_set_rgb2rgb_regs(void __iomem * base_addr,unsigned int id,struct vpfe_ipipe_rgb2rgb * rgb)671 ipipe_set_rgb2rgb_regs(void __iomem *base_addr, unsigned int id,
672 		       struct vpfe_ipipe_rgb2rgb *rgb)
673 {
674 	u32 offset_mask = RGB2RGB_1_OFST_MASK;
675 	u32 offset = RGB1_MUL_BASE;
676 	u32 integ_mask = 0xf;
677 	u32 val;
678 
679 	ipipe_clock_enable(base_addr);
680 
681 	if (id == IPIPE_RGB2RGB_2) {
682 		/*
683 		 * For second RGB module, gain integer is 3 bits instead
684 		 * of 4, offset has 11 bits insread of 13
685 		 */
686 		offset = RGB2_MUL_BASE;
687 		integ_mask = 0x7;
688 		offset_mask = RGB2RGB_2_OFST_MASK;
689 	}
690 	/* Gains */
691 	val = (rgb->coef_rr.decimal & 0xff) |
692 		((rgb->coef_rr.integer & integ_mask) << 8);
693 	regw_ip(base_addr, val, offset + RGB_MUL_RR);
694 	val = (rgb->coef_gr.decimal & 0xff) |
695 		((rgb->coef_gr.integer & integ_mask) << 8);
696 	regw_ip(base_addr, val, offset + RGB_MUL_GR);
697 	val = (rgb->coef_br.decimal & 0xff) |
698 		((rgb->coef_br.integer & integ_mask) << 8);
699 	regw_ip(base_addr, val, offset + RGB_MUL_BR);
700 	val = (rgb->coef_rg.decimal & 0xff) |
701 		((rgb->coef_rg.integer & integ_mask) << 8);
702 	regw_ip(base_addr, val, offset + RGB_MUL_RG);
703 	val = (rgb->coef_gg.decimal & 0xff) |
704 		((rgb->coef_gg.integer & integ_mask) << 8);
705 	regw_ip(base_addr, val, offset + RGB_MUL_GG);
706 	val = (rgb->coef_bg.decimal & 0xff) |
707 		((rgb->coef_bg.integer & integ_mask) << 8);
708 	regw_ip(base_addr, val, offset + RGB_MUL_BG);
709 	val = (rgb->coef_rb.decimal & 0xff) |
710 		((rgb->coef_rb.integer & integ_mask) << 8);
711 	regw_ip(base_addr, val, offset + RGB_MUL_RB);
712 	val = (rgb->coef_gb.decimal & 0xff) |
713 		((rgb->coef_gb.integer & integ_mask) << 8);
714 	regw_ip(base_addr, val, offset + RGB_MUL_GB);
715 	val = (rgb->coef_bb.decimal & 0xff) |
716 		((rgb->coef_bb.integer & integ_mask) << 8);
717 	regw_ip(base_addr, val, offset + RGB_MUL_BB);
718 
719 	/* Offsets */
720 	regw_ip(base_addr, rgb->out_ofst_r & offset_mask, offset + RGB_OFT_OR);
721 	regw_ip(base_addr, rgb->out_ofst_g & offset_mask, offset + RGB_OFT_OG);
722 	regw_ip(base_addr, rgb->out_ofst_b & offset_mask, offset + RGB_OFT_OB);
723 }
724 
725 static void
ipipe_update_gamma_tbl(void __iomem * isp5_base_addr,struct vpfe_ipipe_gamma_entry * table,int size,u32 addr)726 ipipe_update_gamma_tbl(void __iomem *isp5_base_addr,
727 	struct vpfe_ipipe_gamma_entry *table, int size, u32 addr)
728 {
729 	int count;
730 	u32 val;
731 
732 	for (count = 0; count < size; count++) {
733 		val = table[count].slope & GAMMA_MASK;
734 		val |= (table[count].offset & GAMMA_MASK) << GAMMA_SHIFT;
735 		w_ip_table(isp5_base_addr, val, (addr + (count * 4)));
736 	}
737 }
738 
739 void
ipipe_set_gamma_regs(void __iomem * base_addr,void __iomem * isp5_base_addr,struct vpfe_ipipe_gamma * gamma)740 ipipe_set_gamma_regs(void __iomem *base_addr, void __iomem *isp5_base_addr,
741 			  struct vpfe_ipipe_gamma *gamma)
742 {
743 	int table_size;
744 	u32 val;
745 
746 	ipipe_clock_enable(base_addr);
747 	val = (gamma->bypass_r << GAMMA_BYPR_SHIFT) |
748 		(gamma->bypass_b << GAMMA_BYPG_SHIFT) |
749 		(gamma->bypass_g << GAMMA_BYPB_SHIFT) |
750 		(gamma->tbl_sel << GAMMA_TBL_SEL_SHIFT) |
751 		(gamma->tbl_size << GAMMA_TBL_SIZE_SHIFT);
752 
753 	regw_ip(base_addr, val, GMM_CFG);
754 
755 	if (gamma->tbl_sel != VPFE_IPIPE_GAMMA_TBL_RAM)
756 		return;
757 
758 	table_size = gamma->tbl_size;
759 
760 	if (!gamma->bypass_r)
761 		ipipe_update_gamma_tbl(isp5_base_addr, gamma->table_r,
762 			table_size, GAMMA_R_START_ADDR);
763 	if (!gamma->bypass_b)
764 		ipipe_update_gamma_tbl(isp5_base_addr, gamma->table_b,
765 			table_size, GAMMA_B_START_ADDR);
766 	if (!gamma->bypass_g)
767 		ipipe_update_gamma_tbl(isp5_base_addr, gamma->table_g,
768 			table_size, GAMMA_G_START_ADDR);
769 }
770 
771 void
ipipe_set_3d_lut_regs(void __iomem * base_addr,void __iomem * isp5_base_addr,struct vpfe_ipipe_3d_lut * lut_3d)772 ipipe_set_3d_lut_regs(void __iomem *base_addr, void __iomem *isp5_base_addr,
773 			   struct vpfe_ipipe_3d_lut *lut_3d)
774 {
775 	struct vpfe_ipipe_3d_lut_entry *tbl;
776 	u32 bnk_index;
777 	u32 tbl_index;
778 	u32 val;
779 	u32 i;
780 
781 	ipipe_clock_enable(base_addr);
782 	regw_ip(base_addr, lut_3d->en, D3LUT_EN);
783 
784 	if (!lut_3d->en)
785 		return;
786 
787 	/* valied table */
788 	tbl = lut_3d->table;
789 	for (i = 0; i < VPFE_IPIPE_MAX_SIZE_3D_LUT; i++) {
790 		/*
791 		 * Each entry has 0-9 (B), 10-19 (G) and
792 		 * 20-29 R values
793 		 */
794 		val = tbl[i].b & D3_LUT_ENTRY_MASK;
795 		val |= (tbl[i].g & D3_LUT_ENTRY_MASK) <<
796 			 D3_LUT_ENTRY_G_SHIFT;
797 		val |= (tbl[i].r & D3_LUT_ENTRY_MASK) <<
798 			 D3_LUT_ENTRY_R_SHIFT;
799 		bnk_index = i % 4;
800 		tbl_index = i >> 2;
801 		tbl_index <<= 2;
802 		if (bnk_index == 0)
803 			w_ip_table(isp5_base_addr, val,
804 				   tbl_index + D3L_TB0_START_ADDR);
805 		else if (bnk_index == 1)
806 			w_ip_table(isp5_base_addr, val,
807 				   tbl_index + D3L_TB1_START_ADDR);
808 		else if (bnk_index == 2)
809 			w_ip_table(isp5_base_addr, val,
810 				   tbl_index + D3L_TB2_START_ADDR);
811 		else
812 			w_ip_table(isp5_base_addr, val,
813 				   tbl_index + D3L_TB3_START_ADDR);
814 	}
815 }
816 
817 /* Lumina adjustments */
818 void
ipipe_set_lum_adj_regs(void __iomem * base_addr,struct ipipe_lum_adj * lum_adj)819 ipipe_set_lum_adj_regs(void __iomem *base_addr, struct ipipe_lum_adj *lum_adj)
820 {
821 	u32 val;
822 
823 	ipipe_clock_enable(base_addr);
824 
825 	/* combine fields of YUV_ADJ to set brightness and contrast */
826 	val = lum_adj->contrast << LUM_ADJ_CONTR_SHIFT |
827 	      lum_adj->brightness << LUM_ADJ_BRIGHT_SHIFT;
828 	regw_ip(base_addr, val, YUV_ADJ);
829 }
830 
831 #define IPIPE_S12Q8(decimal, integer) \
832 	(((decimal & 0xff) | ((integer & 0xf) << 8)))
833 
ipipe_set_rgb2ycbcr_regs(void __iomem * base_addr,struct vpfe_ipipe_rgb2yuv * yuv)834 void ipipe_set_rgb2ycbcr_regs(void __iomem *base_addr,
835 			      struct vpfe_ipipe_rgb2yuv *yuv)
836 {
837 	u32 val;
838 
839 	/* S10Q8 */
840 	ipipe_clock_enable(base_addr);
841 	val = IPIPE_S12Q8(yuv->coef_ry.decimal, yuv->coef_ry.integer);
842 	regw_ip(base_addr, val, YUV_MUL_RY);
843 	val = IPIPE_S12Q8(yuv->coef_gy.decimal, yuv->coef_gy.integer);
844 	regw_ip(base_addr, val, YUV_MUL_GY);
845 	val = IPIPE_S12Q8(yuv->coef_by.decimal, yuv->coef_by.integer);
846 	regw_ip(base_addr, val, YUV_MUL_BY);
847 	val = IPIPE_S12Q8(yuv->coef_rcb.decimal, yuv->coef_rcb.integer);
848 	regw_ip(base_addr, val, YUV_MUL_RCB);
849 	val = IPIPE_S12Q8(yuv->coef_gcb.decimal, yuv->coef_gcb.integer);
850 	regw_ip(base_addr, val, YUV_MUL_GCB);
851 	val = IPIPE_S12Q8(yuv->coef_bcb.decimal, yuv->coef_bcb.integer);
852 	regw_ip(base_addr, val, YUV_MUL_BCB);
853 	val = IPIPE_S12Q8(yuv->coef_rcr.decimal, yuv->coef_rcr.integer);
854 	regw_ip(base_addr, val, YUV_MUL_RCR);
855 	val = IPIPE_S12Q8(yuv->coef_gcr.decimal, yuv->coef_gcr.integer);
856 	regw_ip(base_addr, val, YUV_MUL_GCR);
857 	val = IPIPE_S12Q8(yuv->coef_bcr.decimal, yuv->coef_bcr.integer);
858 	regw_ip(base_addr, val, YUV_MUL_BCR);
859 	regw_ip(base_addr, yuv->out_ofst_y & RGB2YCBCR_OFST_MASK, YUV_OFT_Y);
860 	regw_ip(base_addr, yuv->out_ofst_cb & RGB2YCBCR_OFST_MASK, YUV_OFT_CB);
861 	regw_ip(base_addr, yuv->out_ofst_cr & RGB2YCBCR_OFST_MASK, YUV_OFT_CR);
862 }
863 
864 /* YUV 422 conversion */
865 void
ipipe_set_yuv422_conv_regs(void __iomem * base_addr,struct vpfe_ipipe_yuv422_conv * conv)866 ipipe_set_yuv422_conv_regs(void __iomem *base_addr,
867 			   struct vpfe_ipipe_yuv422_conv *conv)
868 {
869 	u32 val;
870 
871 	ipipe_clock_enable(base_addr);
872 
873 	/* Combine all the fields to make YUV_PHS register of IPIPE */
874 	val = (conv->chrom_pos << 0) | (conv->en_chrom_lpf << 1);
875 	regw_ip(base_addr, val, YUV_PHS);
876 }
877 
878 void
ipipe_set_gbce_regs(void __iomem * base_addr,void __iomem * isp5_base_addr,struct vpfe_ipipe_gbce * gbce)879 ipipe_set_gbce_regs(void __iomem *base_addr, void __iomem *isp5_base_addr,
880 		    struct vpfe_ipipe_gbce *gbce)
881 {
882 	unsigned int count;
883 	u32 mask = GBCE_Y_VAL_MASK;
884 
885 	if (gbce->type == VPFE_IPIPE_GBCE_GAIN_TBL)
886 		mask = GBCE_GAIN_VAL_MASK;
887 
888 	ipipe_clock_enable(base_addr);
889 	regw_ip(base_addr, gbce->en & 1, GBCE_EN);
890 
891 	if (!gbce->en)
892 		return;
893 
894 	regw_ip(base_addr, gbce->type, GBCE_TYP);
895 
896 	for (count = 0; count < VPFE_IPIPE_MAX_SIZE_GBCE_LUT; count += 2)
897 		w_ip_table(isp5_base_addr, ((gbce->table[count + 1] & mask) <<
898 		GBCE_ENTRY_SHIFT) | (gbce->table[count] & mask),
899 		((count/2) << 2) + GBCE_TB_START_ADDR);
900 }
901 
902 void
ipipe_set_ee_regs(void __iomem * base_addr,void __iomem * isp5_base_addr,struct vpfe_ipipe_yee * ee)903 ipipe_set_ee_regs(void __iomem *base_addr, void __iomem *isp5_base_addr,
904 		  struct vpfe_ipipe_yee *ee)
905 {
906 	unsigned int count;
907 	u32 val;
908 
909 	ipipe_clock_enable(base_addr);
910 	regw_ip(base_addr, ee->en, YEE_EN);
911 
912 	if (!ee->en)
913 		return;
914 
915 	val = ee->en_halo_red & 1;
916 	val |= ee->merge_meth << YEE_HALO_RED_EN_SHIFT;
917 	regw_ip(base_addr, val, YEE_TYP);
918 
919 	regw_ip(base_addr, ee->hpf_shft, YEE_SHF);
920 	regw_ip(base_addr, ee->hpf_coef_00 & YEE_COEF_MASK, YEE_MUL_00);
921 	regw_ip(base_addr, ee->hpf_coef_01 & YEE_COEF_MASK, YEE_MUL_01);
922 	regw_ip(base_addr, ee->hpf_coef_02 & YEE_COEF_MASK, YEE_MUL_02);
923 	regw_ip(base_addr, ee->hpf_coef_10 & YEE_COEF_MASK, YEE_MUL_10);
924 	regw_ip(base_addr, ee->hpf_coef_11 & YEE_COEF_MASK, YEE_MUL_11);
925 	regw_ip(base_addr, ee->hpf_coef_12 & YEE_COEF_MASK, YEE_MUL_12);
926 	regw_ip(base_addr, ee->hpf_coef_20 & YEE_COEF_MASK, YEE_MUL_20);
927 	regw_ip(base_addr, ee->hpf_coef_21 & YEE_COEF_MASK, YEE_MUL_21);
928 	regw_ip(base_addr, ee->hpf_coef_22 & YEE_COEF_MASK, YEE_MUL_22);
929 	regw_ip(base_addr, ee->yee_thr & YEE_THR_MASK, YEE_THR);
930 	regw_ip(base_addr, ee->es_gain & YEE_ES_GAIN_MASK, YEE_E_GAN);
931 	regw_ip(base_addr, ee->es_thr1 & YEE_ES_THR1_MASK, YEE_E_THR1);
932 	regw_ip(base_addr, ee->es_thr2 & YEE_THR_MASK, YEE_E_THR2);
933 	regw_ip(base_addr, ee->es_gain_grad & YEE_THR_MASK, YEE_G_GAN);
934 	regw_ip(base_addr, ee->es_ofst_grad & YEE_THR_MASK, YEE_G_OFT);
935 
936 	for (count = 0; count < VPFE_IPIPE_MAX_SIZE_YEE_LUT; count += 2)
937 		w_ip_table(isp5_base_addr, ((ee->table[count + 1] &
938 		YEE_ENTRY_MASK) << YEE_ENTRY_SHIFT) |
939 		(ee->table[count] & YEE_ENTRY_MASK),
940 		((count/2) << 2) + YEE_TB_START_ADDR);
941 }
942 
943 /* Chromatic Artifact Correction. CAR */
ipipe_set_mf(void __iomem * base_addr)944 static void ipipe_set_mf(void __iomem *base_addr)
945 {
946 	/* typ to dynamic switch */
947 	regw_ip(base_addr, VPFE_IPIPE_CAR_DYN_SWITCH, CAR_TYP);
948 	/* Set SW0 to maximum */
949 	regw_ip(base_addr, CAR_MF_THR, CAR_SW);
950 }
951 
952 static void
ipipe_set_gain_ctrl(void __iomem * base_addr,struct vpfe_ipipe_car * car)953 ipipe_set_gain_ctrl(void __iomem *base_addr, struct vpfe_ipipe_car *car)
954 {
955 	regw_ip(base_addr, VPFE_IPIPE_CAR_CHR_GAIN_CTRL, CAR_TYP);
956 	regw_ip(base_addr, car->hpf, CAR_HPF_TYP);
957 	regw_ip(base_addr, car->hpf_shft & CAR_HPF_SHIFT_MASK, CAR_HPF_SHF);
958 	regw_ip(base_addr, car->hpf_thr, CAR_HPF_THR);
959 	regw_ip(base_addr, car->gain1.gain, CAR_GN1_GAN);
960 	regw_ip(base_addr, car->gain1.shft & CAR_GAIN1_SHFT_MASK, CAR_GN1_SHF);
961 	regw_ip(base_addr, car->gain1.gain_min & CAR_GAIN_MIN_MASK,
962 		CAR_GN1_MIN);
963 	regw_ip(base_addr, car->gain2.gain, CAR_GN2_GAN);
964 	regw_ip(base_addr, car->gain2.shft & CAR_GAIN2_SHFT_MASK, CAR_GN2_SHF);
965 	regw_ip(base_addr, car->gain2.gain_min & CAR_GAIN_MIN_MASK,
966 		CAR_GN2_MIN);
967 }
968 
ipipe_set_car_regs(void __iomem * base_addr,struct vpfe_ipipe_car * car)969 void ipipe_set_car_regs(void __iomem *base_addr, struct vpfe_ipipe_car *car)
970 {
971 	u32 val;
972 
973 	ipipe_clock_enable(base_addr);
974 	regw_ip(base_addr, car->en, CAR_EN);
975 
976 	if (!car->en)
977 		return;
978 
979 	switch (car->meth) {
980 	case VPFE_IPIPE_CAR_MED_FLTR:
981 		ipipe_set_mf(base_addr);
982 		break;
983 
984 	case VPFE_IPIPE_CAR_CHR_GAIN_CTRL:
985 		ipipe_set_gain_ctrl(base_addr, car);
986 		break;
987 
988 	default:
989 		/* Dynamic switch between MF and Gain Ctrl. */
990 		ipipe_set_mf(base_addr);
991 		ipipe_set_gain_ctrl(base_addr, car);
992 		/* Set the threshold for switching between
993 		 * the two Here we overwrite the MF SW0 value
994 		 */
995 		regw_ip(base_addr, VPFE_IPIPE_CAR_DYN_SWITCH, CAR_TYP);
996 		val = car->sw1;
997 		val <<= CAR_SW1_SHIFT;
998 		val |= car->sw0;
999 		regw_ip(base_addr, val, CAR_SW);
1000 	}
1001 }
1002 
1003 /* Chromatic Gain Suppression */
ipipe_set_cgs_regs(void __iomem * base_addr,struct vpfe_ipipe_cgs * cgs)1004 void ipipe_set_cgs_regs(void __iomem *base_addr, struct vpfe_ipipe_cgs *cgs)
1005 {
1006 	ipipe_clock_enable(base_addr);
1007 	regw_ip(base_addr, cgs->en, CGS_EN);
1008 
1009 	if (!cgs->en)
1010 		return;
1011 
1012 	/* Set the bright side parameters */
1013 	regw_ip(base_addr, cgs->h_thr, CGS_GN1_H_THR);
1014 	regw_ip(base_addr, cgs->h_slope, CGS_GN1_H_GAN);
1015 	regw_ip(base_addr, cgs->h_shft & CAR_SHIFT_MASK, CGS_GN1_H_SHF);
1016 	regw_ip(base_addr, cgs->h_min, CGS_GN1_H_MIN);
1017 }
1018 
rsz_src_enable(void __iomem * rsz_base,int enable)1019 void rsz_src_enable(void __iomem *rsz_base, int enable)
1020 {
1021 	regw_rsz(rsz_base, enable, RSZ_SRC_EN);
1022 }
1023 
rsz_enable(void __iomem * rsz_base,int rsz_id,int enable)1024 int rsz_enable(void __iomem *rsz_base, int rsz_id, int enable)
1025 {
1026 	if (rsz_id == RSZ_A) {
1027 		regw_rsz(rsz_base, enable, RSZ_EN_A);
1028 		/* We always enable RSZ_A. RSZ_B is enable upon request from
1029 		 * application. So enable RSZ_SRC_EN along with RSZ_A
1030 		 */
1031 		regw_rsz(rsz_base, enable, RSZ_SRC_EN);
1032 	} else if (rsz_id == RSZ_B) {
1033 		regw_rsz(rsz_base, enable, RSZ_EN_B);
1034 	} else {
1035 		BUG();
1036 	}
1037 
1038 	return 0;
1039 }
1040