• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6.36/drivers/staging/dream/camera/
1/*
2* Copyright (C) 2008-2009 QUALCOMM Incorporated.
3*/
4#include <linux/slab.h>
5#include <linux/interrupt.h>
6#include <linux/spinlock.h>
7#include <linux/io.h>
8#include <linux/list.h>
9#include <linux/delay.h>
10#include <linux/platform_device.h>
11#include "msm_vfe8x_proc.h"
12#include <media/msm_camera.h>
13
14struct msm_vfe8x_ctrl {
15	/* bit 1:0 ENC_IRQ_MASK = 0x11:
16	 * generate IRQ when both y and cbcr frame is ready. */
17
18	/* bit 1:0 VIEW_IRQ_MASK= 0x11:
19	 * generate IRQ when both y and cbcr frame is ready. */
20	struct vfe_irq_composite_mask_config vfeIrqCompositeMaskLocal;
21	struct vfe_module_enable vfeModuleEnableLocal;
22	struct vfe_camif_cfg_data   vfeCamifConfigLocal;
23	struct vfe_interrupt_mask   vfeImaskLocal;
24	struct vfe_stats_cmd_data   vfeStatsCmdLocal;
25	struct vfe_bus_cfg_data     vfeBusConfigLocal;
26	struct vfe_cmd_bus_pm_start vfeBusPmConfigLocal;
27	struct vfe_bus_cmd_data     vfeBusCmdLocal;
28	enum vfe_interrupt_name     vfeInterruptNameLocal;
29	uint32_t vfeLaBankSel;
30	struct vfe_gamma_lut_sel  vfeGammaLutSel;
31
32	boolean vfeStartAckPendingFlag;
33	boolean vfeStopAckPending;
34	boolean vfeResetAckPending;
35	boolean vfeUpdateAckPending;
36
37	enum VFE_AXI_OUTPUT_MODE        axiOutputMode;
38	enum VFE_START_OPERATION_MODE   vfeOperationMode;
39
40	uint32_t            vfeSnapShotCount;
41	uint32_t            vfeRequestedSnapShotCount;
42	boolean             vfeStatsPingPongReloadFlag;
43	uint32_t            vfeFrameId;
44
45	struct vfe_cmd_frame_skip_config vfeFrameSkip;
46	uint32_t vfeFrameSkipPattern;
47	uint8_t  vfeFrameSkipCount;
48	uint8_t  vfeFrameSkipPeriod;
49
50	boolean  vfeTestGenStartFlag;
51	uint32_t vfeImaskPacked;
52	uint32_t vfeImaskCompositePacked;
53	enum VFE_RAW_PIXEL_DATA_SIZE       axiInputDataSize;
54	struct vfe_irq_thread_msg          vfeIrqThreadMsgLocal;
55
56	struct vfe_output_path_combo  viewPath;
57	struct vfe_output_path_combo  encPath;
58	struct vfe_frame_skip_counts vfeDroppedFrameCounts;
59	struct vfe_stats_control afStatsControl;
60	struct vfe_stats_control awbStatsControl;
61
62	enum VFE_STATE  vstate;
63
64	spinlock_t  ack_lock;
65	spinlock_t  state_lock;
66	spinlock_t  io_lock;
67
68	struct msm_vfe_callback *resp;
69	uint32_t extlen;
70	void *extdata;
71
72	spinlock_t  tasklet_lock;
73	struct list_head tasklet_q;
74
75	int vfeirq;
76	void __iomem *vfebase;
77
78	void *syncdata;
79};
80static struct msm_vfe8x_ctrl *ctrl;
81static irqreturn_t vfe_parse_irq(int irq_num, void *data);
82
83struct isr_queue_cmd {
84	struct list_head list;
85	struct vfe_interrupt_status        vfeInterruptStatus;
86	struct vfe_frame_asf_info          vfeAsfFrameInfo;
87	struct vfe_frame_bpc_info          vfeBpcFrameInfo;
88	struct vfe_msg_camif_status        vfeCamifStatusLocal;
89	struct vfe_bus_performance_monitor vfePmData;
90};
91
92static void vfe_prog_hw(uint8_t *hwreg,
93	uint32_t *inptr, uint32_t regcnt)
94{
95	/* unsigned long flags; */
96	uint32_t i;
97	uint32_t *p;
98
99	/* @todo This is causing issues, need further investigate */
100	/* spin_lock_irqsave(&ctrl->io_lock, flags); */
101
102	p = (uint32_t *)(hwreg);
103	for (i = 0; i < (regcnt >> 2); i++)
104		writel(*inptr++, p++);
105		/* *p++ = *inptr++; */
106
107	/* spin_unlock_irqrestore(&ctrl->io_lock, flags); */
108}
109
110static void vfe_read_reg_values(uint8_t *hwreg,
111	uint32_t *dest, uint32_t count)
112{
113	/* unsigned long flags; */
114	uint32_t *temp;
115	uint32_t i;
116
117	/* @todo This is causing issues, need further investigate */
118	/* spin_lock_irqsave(&ctrl->io_lock, flags); */
119
120	temp = (uint32_t *)(hwreg);
121	for (i = 0; i < count; i++)
122		*dest++ = *temp++;
123
124	/* spin_unlock_irqrestore(&ctrl->io_lock, flags); */
125}
126
127static struct vfe_irqenable vfe_read_irq_mask(void)
128{
129	/* unsigned long flags; */
130	uint32_t *temp;
131	struct vfe_irqenable rc;
132
133	memset(&rc, 0, sizeof(rc));
134
135	/* @todo This is causing issues, need further investigate */
136	/* spin_lock_irqsave(&ctrl->io_lock, flags); */
137	temp = (uint32_t *)(ctrl->vfebase + VFE_IRQ_MASK);
138
139	rc = *((struct vfe_irqenable *)temp);
140	/* spin_unlock_irqrestore(&ctrl->io_lock, flags); */
141
142	return rc;
143}
144
145static void
146vfe_set_bus_pipo_addr(struct vfe_output_path_combo *vpath,
147	struct vfe_output_path_combo *epath)
148{
149	vpath->yPath.hwRegPingAddress = (uint8_t *)
150		(ctrl->vfebase + VFE_BUS_VIEW_Y_WR_PING_ADDR);
151	vpath->yPath.hwRegPongAddress = (uint8_t *)
152		(ctrl->vfebase + VFE_BUS_VIEW_Y_WR_PONG_ADDR);
153	vpath->cbcrPath.hwRegPingAddress = (uint8_t *)
154		(ctrl->vfebase + VFE_BUS_VIEW_CBCR_WR_PING_ADDR);
155	vpath->cbcrPath.hwRegPongAddress = (uint8_t *)
156		(ctrl->vfebase + VFE_BUS_VIEW_CBCR_WR_PONG_ADDR);
157
158	epath->yPath.hwRegPingAddress = (uint8_t *)
159		(ctrl->vfebase + VFE_BUS_ENC_Y_WR_PING_ADDR);
160	epath->yPath.hwRegPongAddress = (uint8_t *)
161		(ctrl->vfebase + VFE_BUS_ENC_Y_WR_PONG_ADDR);
162	epath->cbcrPath.hwRegPingAddress = (uint8_t *)
163		(ctrl->vfebase + VFE_BUS_ENC_CBCR_WR_PING_ADDR);
164	epath->cbcrPath.hwRegPongAddress = (uint8_t *)
165		(ctrl->vfebase + VFE_BUS_ENC_CBCR_WR_PONG_ADDR);
166}
167
168static void vfe_axi_output(struct vfe_cmd_axi_output_config *in,
169	struct vfe_output_path_combo *out1,
170	struct vfe_output_path_combo *out2, uint16_t out)
171{
172	struct vfe_axi_out_cfg cmd;
173
174	uint16_t temp;
175	uint32_t burstLength;
176
177	/* force it to burst length 4, hardware does not support it. */
178	burstLength = 1;
179
180	/* AXI Output 2 Y Configuration*/
181	/* VFE_BUS_ENC_Y_WR_PING_ADDR  */
182	cmd.out2YPingAddr = out2->yPath.addressBuffer[0];
183
184	/* VFE_BUS_ENC_Y_WR_PONG_ADDR  */
185	cmd.out2YPongAddr = out2->yPath.addressBuffer[1];
186
187	/* VFE_BUS_ENC_Y_WR_IMAGE_SIZE */
188	cmd.out2YImageHeight = in->output2.outputY.imageHeight;
189	/* convert the image width and row increment to be in
190	 * unit of 64bit (8 bytes) */
191	temp = (in->output2.outputY.imageWidth + (out - 1)) /
192		out;
193	cmd.out2YImageWidthin64bit = temp;
194
195	/* VFE_BUS_ENC_Y_WR_BUFFER_CFG */
196	cmd.out2YBurstLength = burstLength;
197	cmd.out2YNumRows = in->output2.outputY.outRowCount;
198	temp = (in->output2.outputY.outRowIncrement + (out - 1)) /
199		out;
200	cmd.out2YRowIncrementIn64bit = temp;
201
202	/* AXI Output 2 Cbcr Configuration*/
203	/* VFE_BUS_ENC_Cbcr_WR_PING_ADDR  */
204	cmd.out2CbcrPingAddr = out2->cbcrPath.addressBuffer[0];
205
206	/* VFE_BUS_ENC_Cbcr_WR_PONG_ADDR  */
207	cmd.out2CbcrPongAddr = out2->cbcrPath.addressBuffer[1];
208
209	/* VFE_BUS_ENC_Cbcr_WR_IMAGE_SIZE */
210	cmd.out2CbcrImageHeight = in->output2.outputCbcr.imageHeight;
211	temp = (in->output2.outputCbcr.imageWidth + (out - 1)) /
212		out;
213	cmd.out2CbcrImageWidthIn64bit = temp;
214
215	/* VFE_BUS_ENC_Cbcr_WR_BUFFER_CFG */
216	cmd.out2CbcrBurstLength = burstLength;
217	cmd.out2CbcrNumRows = in->output2.outputCbcr.outRowCount;
218	temp = (in->output2.outputCbcr.outRowIncrement + (out - 1)) /
219		out;
220	cmd.out2CbcrRowIncrementIn64bit = temp;
221
222	/* AXI Output 1 Y Configuration */
223	/* VFE_BUS_VIEW_Y_WR_PING_ADDR  */
224	cmd.out1YPingAddr = out1->yPath.addressBuffer[0];
225
226	/* VFE_BUS_VIEW_Y_WR_PONG_ADDR */
227	cmd.out1YPongAddr = out1->yPath.addressBuffer[1];
228
229	/* VFE_BUS_VIEW_Y_WR_IMAGE_SIZE */
230	cmd.out1YImageHeight = in->output1.outputY.imageHeight;
231	temp = (in->output1.outputY.imageWidth + (out - 1)) /
232		out;
233	cmd.out1YImageWidthin64bit = temp;
234
235	/* VFE_BUS_VIEW_Y_WR_BUFFER_CFG     */
236	cmd.out1YBurstLength = burstLength;
237	cmd.out1YNumRows = in->output1.outputY.outRowCount;
238
239	temp =
240		(in->output1.outputY.outRowIncrement +
241		 (out - 1)) / out;
242	cmd.out1YRowIncrementIn64bit = temp;
243
244	/* AXI Output 1 Cbcr Configuration*/
245	cmd.out1CbcrPingAddr = out1->cbcrPath.addressBuffer[0];
246
247	/* VFE_BUS_VIEW_Cbcr_WR_PONG_ADDR  */
248	cmd.out1CbcrPongAddr =
249		out1->cbcrPath.addressBuffer[1];
250
251	/* VFE_BUS_VIEW_Cbcr_WR_IMAGE_SIZE */
252	cmd.out1CbcrImageHeight = in->output1.outputCbcr.imageHeight;
253	temp = (in->output1.outputCbcr.imageWidth +
254		(out - 1)) / out;
255	cmd.out1CbcrImageWidthIn64bit = temp;
256
257	cmd.out1CbcrBurstLength = burstLength;
258	cmd.out1CbcrNumRows = in->output1.outputCbcr.outRowCount;
259	temp =
260		(in->output1.outputCbcr.outRowIncrement +
261		 (out - 1)) / out;
262
263	cmd.out1CbcrRowIncrementIn64bit = temp;
264
265	vfe_prog_hw(ctrl->vfebase + VFE_BUS_ENC_Y_WR_PING_ADDR,
266		(uint32_t *)&cmd, sizeof(cmd));
267}
268
269static void vfe_reg_bus_cfg(struct vfe_bus_cfg_data *in)
270{
271	struct vfe_axi_bus_cfg cmd;
272
273	cmd.stripeRdPathEn      = in->stripeRdPathEn;
274	cmd.encYWrPathEn        = in->encYWrPathEn;
275	cmd.encCbcrWrPathEn     = in->encCbcrWrPathEn;
276	cmd.viewYWrPathEn       = in->viewYWrPathEn;
277	cmd.viewCbcrWrPathEn    = in->viewCbcrWrPathEn;
278	cmd.rawPixelDataSize    = (uint32_t)in->rawPixelDataSize;
279	cmd.rawWritePathSelect  = (uint32_t)in->rawWritePathSelect;
280
281	/*  program vfe_bus_cfg */
282	writel(*((uint32_t *)&cmd), ctrl->vfebase + VFE_BUS_CFG);
283}
284
285static void vfe_reg_camif_config(struct vfe_camif_cfg_data *in)
286{
287	struct VFE_CAMIFConfigType cfg;
288
289	memset(&cfg, 0, sizeof(cfg));
290
291	cfg.VSyncEdge          =
292		in->camifCfgFromCmd.vSyncEdge;
293
294	cfg.HSyncEdge          =
295		in->camifCfgFromCmd.hSyncEdge;
296
297	cfg.syncMode           =
298		in->camifCfgFromCmd.syncMode;
299
300	cfg.vfeSubsampleEnable =
301		in->camifCfgFromCmd.vfeSubSampleEnable;
302
303	cfg.busSubsampleEnable =
304		in->camifCfgFromCmd.busSubSampleEnable;
305
306	cfg.camif2vfeEnable    =
307		in->camif2OutputEnable;
308
309	cfg.camif2busEnable    =
310		in->camif2BusEnable;
311
312	cfg.irqSubsampleEnable =
313		in->camifCfgFromCmd.irqSubSampleEnable;
314
315	cfg.binningEnable      =
316		in->camifCfgFromCmd.binningEnable;
317
318	cfg.misrEnable         =
319		in->camifCfgFromCmd.misrEnable;
320
321	/*  program camif_config */
322	writel(*((uint32_t *)&cfg), ctrl->vfebase + CAMIF_CONFIG);
323}
324
325static void vfe_reg_bus_cmd(struct vfe_bus_cmd_data *in)
326{
327	struct vfe_buscmd cmd;
328	memset(&cmd, 0, sizeof(cmd));
329
330	cmd.stripeReload        = in->stripeReload;
331	cmd.busPingpongReload   = in->busPingpongReload;
332	cmd.statsPingpongReload = in->statsPingpongReload;
333
334	writel(*((uint32_t *)&cmd), ctrl->vfebase + VFE_BUS_CMD);
335
336	CDBG("bus command = 0x%x\n", (*((uint32_t *)&cmd)));
337
338	/* this is needed, as the control bits are pulse based.
339	 * Don't want to reload bus pingpong again. */
340	in->busPingpongReload = 0;
341	in->statsPingpongReload = 0;
342	in->stripeReload = 0;
343}
344
345static void vfe_reg_module_cfg(struct vfe_module_enable *in)
346{
347	struct vfe_mod_enable ena;
348
349	memset(&ena, 0, sizeof(ena));
350
351	ena.blackLevelCorrectionEnable = in->blackLevelCorrectionEnable;
352	ena.lensRollOffEnable          = in->lensRollOffEnable;
353	ena.demuxEnable                = in->demuxEnable;
354	ena.chromaUpsampleEnable       = in->chromaUpsampleEnable;
355	ena.demosaicEnable             = in->demosaicEnable;
356	ena.statsEnable                = in->statsEnable;
357	ena.cropEnable                 = in->cropEnable;
358	ena.mainScalerEnable           = in->mainScalerEnable;
359	ena.whiteBalanceEnable         = in->whiteBalanceEnable;
360	ena.colorCorrectionEnable      = in->colorCorrectionEnable;
361	ena.yHistEnable                = in->yHistEnable;
362	ena.skinToneEnable             = in->skinToneEnable;
363	ena.lumaAdaptationEnable       = in->lumaAdaptationEnable;
364	ena.rgbLUTEnable               = in->rgbLUTEnable;
365	ena.chromaEnhanEnable          = in->chromaEnhanEnable;
366	ena.asfEnable                  = in->asfEnable;
367	ena.chromaSuppressionEnable    = in->chromaSuppressionEnable;
368	ena.chromaSubsampleEnable      = in->chromaSubsampleEnable;
369	ena.scaler2YEnable             = in->scaler2YEnable;
370	ena.scaler2CbcrEnable          = in->scaler2CbcrEnable;
371
372	writel(*((uint32_t *)&ena), ctrl->vfebase + VFE_MODULE_CFG);
373}
374
375static void vfe_program_dmi_cfg(enum VFE_DMI_RAM_SEL bankSel)
376{
377	/* set bit 8 for auto increment. */
378	uint32_t value = (uint32_t) ctrl->vfebase + VFE_DMI_CFG_DEFAULT;
379
380	value += (uint32_t)bankSel;
381	/* CDBG("dmi cfg input bank is  0x%x\n", bankSel); */
382
383	writel(value, ctrl->vfebase + VFE_DMI_CFG);
384	writel(0, ctrl->vfebase + VFE_DMI_ADDR);
385}
386
387static void vfe_write_lens_roll_off_table(
388	struct vfe_cmd_roll_off_config *in)
389{
390	uint16_t i;
391	uint32_t data;
392
393	uint16_t *initGr = in->initTableGr;
394	uint16_t *initGb = in->initTableGb;
395	uint16_t *initB =  in->initTableB;
396	uint16_t *initR =  in->initTableR;
397
398	int16_t *pDeltaGr = in->deltaTableGr;
399	int16_t *pDeltaGb = in->deltaTableGb;
400	int16_t *pDeltaB =  in->deltaTableB;
401	int16_t *pDeltaR =  in->deltaTableR;
402
403	vfe_program_dmi_cfg(ROLLOFF_RAM);
404
405	/* first pack and write init table */
406	for (i = 0; i < VFE_ROLL_OFF_INIT_TABLE_SIZE; i++) {
407		data = (((uint32_t)(*initR)) & 0x0000FFFF) |
408			(((uint32_t)(*initGr)) << 16);
409		initR++;
410		initGr++;
411
412		writel(data, ctrl->vfebase + VFE_DMI_DATA_LO);
413
414		data = (((uint32_t)(*initB)) & 0x0000FFFF) |
415			(((uint32_t)(*initGr))<<16);
416		initB++;
417		initGb++;
418
419		writel(data, ctrl->vfebase + VFE_DMI_DATA_LO);
420	}
421
422	/* there are gaps between the init table and delta table,
423	 * set the offset for delta table. */
424	writel(LENS_ROLL_OFF_DELTA_TABLE_OFFSET,
425		ctrl->vfebase + VFE_DMI_ADDR);
426
427	/* pack and write delta table */
428	for (i = 0; i < VFE_ROLL_OFF_DELTA_TABLE_SIZE; i++) {
429		data = (((int32_t)(*pDeltaR)) & 0x0000FFFF) |
430			(((int32_t)(*pDeltaGr))<<16);
431		pDeltaR++;
432		pDeltaGr++;
433
434		writel(data, ctrl->vfebase + VFE_DMI_DATA_LO);
435
436		data = (((int32_t)(*pDeltaB)) & 0x0000FFFF) |
437			(((int32_t)(*pDeltaGb))<<16);
438		pDeltaB++;
439		pDeltaGb++;
440
441		writel(data, ctrl->vfebase + VFE_DMI_DATA_LO);
442	}
443
444	/* After DMI transfer, to make it safe, need to set the
445	 * DMI_CFG to unselect any SRAM
446	 */
447	/* unselect the SRAM Bank. */
448	writel(VFE_DMI_CFG_DEFAULT, ctrl->vfebase + VFE_DMI_CFG);
449}
450
451static void vfe_set_default_reg_values(void)
452{
453	writel(0x800080, ctrl->vfebase + VFE_DEMUX_GAIN_0);
454	writel(0x800080, ctrl->vfebase + VFE_DEMUX_GAIN_1);
455	writel(0xFFFFF, ctrl->vfebase + VFE_CGC_OVERRIDE);
456
457	/* default frame drop period and pattern */
458	writel(0x1f, ctrl->vfebase + VFE_FRAMEDROP_ENC_Y_CFG);
459	writel(0x1f, ctrl->vfebase + VFE_FRAMEDROP_ENC_CBCR_CFG);
460	writel(0xFFFFFFFF, ctrl->vfebase + VFE_FRAMEDROP_ENC_Y_PATTERN);
461	writel(0xFFFFFFFF, ctrl->vfebase + VFE_FRAMEDROP_ENC_CBCR_PATTERN);
462	writel(0x1f, ctrl->vfebase + VFE_FRAMEDROP_VIEW_Y_CFG);
463	writel(0x1f, ctrl->vfebase + VFE_FRAMEDROP_VIEW_CBCR_CFG);
464	writel(0xFFFFFFFF, ctrl->vfebase + VFE_FRAMEDROP_VIEW_Y_PATTERN);
465	writel(0xFFFFFFFF, ctrl->vfebase + VFE_FRAMEDROP_VIEW_CBCR_PATTERN);
466	writel(0, ctrl->vfebase + VFE_CLAMP_MIN_CFG);
467	writel(0xFFFFFF, ctrl->vfebase + VFE_CLAMP_MAX_CFG);
468}
469
470static void vfe_config_demux(uint32_t period, uint32_t even, uint32_t odd)
471{
472	writel(period, ctrl->vfebase + VFE_DEMUX_CFG);
473	writel(even, ctrl->vfebase + VFE_DEMUX_EVEN_CFG);
474	writel(odd, ctrl->vfebase + VFE_DEMUX_ODD_CFG);
475}
476
477static void vfe_pm_stop(void)
478{
479	writel(VFE_PERFORMANCE_MONITOR_STOP, ctrl->vfebase + VFE_BUS_PM_CMD);
480}
481
482static void vfe_program_bus_rd_irq_en(uint32_t value)
483{
484	writel(value, ctrl->vfebase + VFE_BUS_PINGPONG_IRQ_EN);
485}
486
487static void vfe_camif_go(void)
488{
489	writel(CAMIF_COMMAND_START, ctrl->vfebase + CAMIF_COMMAND);
490}
491
492static void vfe_camif_stop_immediately(void)
493{
494	writel(CAMIF_COMMAND_STOP_IMMEDIATELY, ctrl->vfebase + CAMIF_COMMAND);
495	writel(0, ctrl->vfebase + VFE_CGC_OVERRIDE);
496}
497
498static void vfe_program_reg_update_cmd(uint32_t value)
499{
500	writel(value, ctrl->vfebase + VFE_REG_UPDATE_CMD);
501}
502
503static void vfe_program_bus_cmd(uint32_t value)
504{
505	writel(value, ctrl->vfebase + VFE_BUS_CMD);
506}
507
508static void vfe_program_global_reset_cmd(uint32_t value)
509{
510	writel(value, ctrl->vfebase + VFE_GLOBAL_RESET_CMD);
511}
512
513static void vfe_program_axi_cmd(uint32_t value)
514{
515	writel(value, ctrl->vfebase + VFE_AXI_CMD);
516}
517
518static void vfe_program_irq_composite_mask(uint32_t value)
519{
520	writel(value, ctrl->vfebase + VFE_IRQ_COMPOSITE_MASK);
521}
522
523static inline void vfe_program_irq_mask(uint32_t value)
524{
525	writel(value, ctrl->vfebase + VFE_IRQ_MASK);
526}
527
528static void vfe_program_chroma_upsample_cfg(uint32_t value)
529{
530	writel(value, ctrl->vfebase + VFE_CHROMA_UPSAMPLE_CFG);
531}
532
533static uint32_t vfe_read_axi_status(void)
534{
535	return readl(ctrl->vfebase + VFE_AXI_STATUS);
536}
537
538static uint32_t vfe_read_pm_status_in_raw_capture(void)
539{
540	return readl(ctrl->vfebase + VFE_BUS_ENC_CBCR_WR_PM_STATS_1);
541}
542
543static void
544vfe_set_stats_pingpong_address(struct vfe_stats_control *afControl,
545	struct vfe_stats_control *awbControl)
546{
547	afControl->hwRegPingAddress = (uint8_t *)
548		(ctrl->vfebase + VFE_BUS_STATS_AF_WR_PING_ADDR);
549	afControl->hwRegPongAddress = (uint8_t *)
550		(ctrl->vfebase + VFE_BUS_STATS_AF_WR_PONG_ADDR);
551
552	awbControl->hwRegPingAddress = (uint8_t *)
553		(ctrl->vfebase + VFE_BUS_STATS_AWB_WR_PING_ADDR);
554	awbControl->hwRegPongAddress = (uint8_t *)
555		(ctrl->vfebase + VFE_BUS_STATS_AWB_WR_PONG_ADDR);
556}
557
558static uint32_t vfe_read_camif_status(void)
559{
560	return readl(ctrl->vfebase + CAMIF_STATUS);
561}
562
563static void vfe_program_lut_bank_sel(struct vfe_gamma_lut_sel *in)
564{
565	struct VFE_GammaLutSelect_ConfigCmdType cmd;
566
567	memset(&cmd, 0, sizeof(cmd));
568
569	cmd.ch0BankSelect = in->ch0BankSelect;
570	cmd.ch1BankSelect = in->ch1BankSelect;
571	cmd.ch2BankSelect = in->ch2BankSelect;
572	CDBG("VFE gamma lut bank selection is 0x%x\n", *((uint32_t *)&cmd));
573	vfe_prog_hw(ctrl->vfebase + VFE_LUT_BANK_SEL,
574		(uint32_t *)&cmd, sizeof(cmd));
575}
576
577static void vfe_program_stats_cmd(struct vfe_stats_cmd_data *in)
578{
579	struct VFE_StatsCmdType stats;
580	memset(&stats, 0, sizeof(stats));
581
582	stats.autoFocusEnable        = in->autoFocusEnable;
583	stats.axwEnable              = in->axwEnable;
584	stats.histEnable             = in->histEnable;
585	stats.clearHistEnable        = in->clearHistEnable;
586	stats.histAutoClearEnable    = in->histAutoClearEnable;
587	stats.colorConversionEnable  = in->colorConversionEnable;
588
589	writel(*((uint32_t *)&stats), ctrl->vfebase + VFE_STATS_CMD);
590}
591
592static void vfe_pm_start(struct vfe_cmd_bus_pm_start *in)
593{
594	struct VFE_Bus_Pm_ConfigCmdType cmd;
595	memset(&cmd, 0, sizeof(struct VFE_Bus_Pm_ConfigCmdType));
596
597	cmd.output2YWrPmEnable     = in->output2YWrPmEnable;
598	cmd.output2CbcrWrPmEnable  = in->output2CbcrWrPmEnable;
599	cmd.output1YWrPmEnable     = in->output1YWrPmEnable;
600	cmd.output1CbcrWrPmEnable  = in->output1CbcrWrPmEnable;
601
602	vfe_prog_hw(ctrl->vfebase + VFE_BUS_PM_CFG,
603		(uint32_t *)&cmd, sizeof(cmd));
604}
605
606static void vfe_8k_pm_start(struct vfe_cmd_bus_pm_start *in)
607{
608	in->output1CbcrWrPmEnable = ctrl->vfeBusConfigLocal.viewCbcrWrPathEn;
609	in->output1YWrPmEnable    = ctrl->vfeBusConfigLocal.viewYWrPathEn;
610	in->output2CbcrWrPmEnable = ctrl->vfeBusConfigLocal.encCbcrWrPathEn;
611	in->output2YWrPmEnable    = ctrl->vfeBusConfigLocal.encYWrPathEn;
612
613	if (in->output1CbcrWrPmEnable || in->output1YWrPmEnable)
614		ctrl->viewPath.pmEnabled = TRUE;
615
616	if (in->output2CbcrWrPmEnable || in->output2YWrPmEnable)
617		ctrl->encPath.pmEnabled = TRUE;
618
619	vfe_pm_start(in);
620
621	writel(VFE_PERFORMANCE_MONITOR_GO, ctrl->vfebase + VFE_BUS_PM_CMD);
622}
623
624static uint32_t vfe_irq_pack(struct vfe_interrupt_mask data)
625{
626	struct vfe_irqenable packedData;
627
628	memset(&packedData, 0, sizeof(packedData));
629
630	packedData.camifErrorIrq          = data.camifErrorIrq;
631	packedData.camifSofIrq            = data.camifSofIrq;
632	packedData.camifEolIrq            = data.camifEolIrq;
633	packedData.camifEofIrq            = data.camifEofIrq;
634	packedData.camifEpoch1Irq         = data.camifEpoch1Irq;
635	packedData.camifEpoch2Irq         = data.camifEpoch2Irq;
636	packedData.camifOverflowIrq       = data.camifOverflowIrq;
637	packedData.ceIrq                  = data.ceIrq;
638	packedData.regUpdateIrq           = data.regUpdateIrq;
639	packedData.resetAckIrq            = data.resetAckIrq;
640	packedData.encYPingpongIrq        = data.encYPingpongIrq;
641	packedData.encCbcrPingpongIrq     = data.encCbcrPingpongIrq;
642	packedData.viewYPingpongIrq       = data.viewYPingpongIrq;
643	packedData.viewCbcrPingpongIrq    = data.viewCbcrPingpongIrq;
644	packedData.rdPingpongIrq          = data.rdPingpongIrq;
645	packedData.afPingpongIrq          = data.afPingpongIrq;
646	packedData.awbPingpongIrq         = data.awbPingpongIrq;
647	packedData.histPingpongIrq        = data.histPingpongIrq;
648	packedData.encIrq                 = data.encIrq;
649	packedData.viewIrq                = data.viewIrq;
650	packedData.busOverflowIrq         = data.busOverflowIrq;
651	packedData.afOverflowIrq          = data.afOverflowIrq;
652	packedData.awbOverflowIrq         = data.awbOverflowIrq;
653	packedData.syncTimer0Irq          = data.syncTimer0Irq;
654	packedData.syncTimer1Irq          = data.syncTimer1Irq;
655	packedData.syncTimer2Irq          = data.syncTimer2Irq;
656	packedData.asyncTimer0Irq         = data.asyncTimer0Irq;
657	packedData.asyncTimer1Irq         = data.asyncTimer1Irq;
658	packedData.asyncTimer2Irq         = data.asyncTimer2Irq;
659	packedData.asyncTimer3Irq         = data.asyncTimer3Irq;
660	packedData.axiErrorIrq            = data.axiErrorIrq;
661	packedData.violationIrq           = data.violationIrq;
662
663	return *((uint32_t *)&packedData);
664}
665
666static uint32_t
667vfe_irq_composite_pack(struct vfe_irq_composite_mask_config data)
668{
669	struct VFE_Irq_Composite_MaskType packedData;
670
671	memset(&packedData, 0, sizeof(packedData));
672
673	packedData.encIrqComMaskBits   = data.encIrqComMask;
674	packedData.viewIrqComMaskBits  = data.viewIrqComMask;
675	packedData.ceDoneSelBits       = data.ceDoneSel;
676
677	return *((uint32_t *)&packedData);
678}
679
680static void vfe_addr_convert(struct msm_vfe_phy_info *pinfo,
681	enum vfe_resp_msg type, void *data, void **ext, int32_t *elen)
682{
683	switch (type) {
684	case VFE_MSG_OUTPUT1: {
685		pinfo->y_phy =
686			((struct vfe_message *)data)->_u.msgOutput1.yBuffer;
687		pinfo->cbcr_phy =
688			((struct vfe_message *)data)->_u.msgOutput1.cbcrBuffer;
689
690		((struct vfe_frame_extra *)ctrl->extdata)->bpcInfo =
691		((struct vfe_message *)data)->_u.msgOutput1.bpcInfo;
692
693		((struct vfe_frame_extra *)ctrl->extdata)->asfInfo =
694		((struct vfe_message *)data)->_u.msgOutput1.asfInfo;
695
696		((struct vfe_frame_extra *)ctrl->extdata)->frameCounter =
697		((struct vfe_message *)data)->_u.msgOutput1.frameCounter;
698
699		((struct vfe_frame_extra *)ctrl->extdata)->pmData =
700		((struct vfe_message *)data)->_u.msgOutput1.pmData;
701
702		*ext  = ctrl->extdata;
703		*elen = ctrl->extlen;
704	}
705		break;
706
707	case VFE_MSG_OUTPUT2: {
708		pinfo->y_phy =
709			((struct vfe_message *)data)->_u.msgOutput2.yBuffer;
710		pinfo->cbcr_phy =
711			((struct vfe_message *)data)->_u.msgOutput2.cbcrBuffer;
712
713		CDBG("vfe_addr_convert, pinfo->y_phy = 0x%x\n", pinfo->y_phy);
714		CDBG("vfe_addr_convert, pinfo->cbcr_phy = 0x%x\n",
715			pinfo->cbcr_phy);
716
717		((struct vfe_frame_extra *)ctrl->extdata)->bpcInfo =
718		((struct vfe_message *)data)->_u.msgOutput2.bpcInfo;
719
720		((struct vfe_frame_extra *)ctrl->extdata)->asfInfo =
721		((struct vfe_message *)data)->_u.msgOutput2.asfInfo;
722
723		((struct vfe_frame_extra *)ctrl->extdata)->frameCounter =
724		((struct vfe_message *)data)->_u.msgOutput2.frameCounter;
725
726		((struct vfe_frame_extra *)ctrl->extdata)->pmData =
727		((struct vfe_message *)data)->_u.msgOutput2.pmData;
728
729		*ext  = ctrl->extdata;
730		*elen = ctrl->extlen;
731	}
732		break;
733
734	case VFE_MSG_STATS_AF:
735		pinfo->sbuf_phy =
736		((struct vfe_message *)data)->_u.msgStatsAf.afBuffer;
737		break;
738
739	case VFE_MSG_STATS_WE:
740		pinfo->sbuf_phy =
741		((struct vfe_message *)data)->_u.msgStatsWbExp.awbBuffer;
742		break;
743
744	default:
745		break;
746	} /* switch */
747}
748
749static void
750vfe_proc_ops(enum VFE_MESSAGE_ID id, void *msg, size_t len)
751{
752	struct msm_vfe_resp *rp;
753
754	/* In 8k, OUTPUT1 & OUTPUT2 messages arrive before
755	 * SNAPSHOT_DONE. We don't send such messages to user */
756
757	CDBG("ctrl->vfeOperationMode = %d, msgId = %d\n",
758		ctrl->vfeOperationMode, id);
759
760	if ((ctrl->vfeOperationMode == VFE_START_OPERATION_MODE_SNAPSHOT) &&
761		(id == VFE_MSG_ID_OUTPUT1 || id == VFE_MSG_ID_OUTPUT2)) {
762		return;
763	}
764
765	rp = ctrl->resp->vfe_alloc(sizeof(struct msm_vfe_resp), ctrl->syncdata);
766	if (!rp) {
767		CDBG("rp: cannot allocate buffer\n");
768		return;
769	}
770
771	CDBG("vfe_proc_ops, msgId = %d\n", id);
772
773	rp->evt_msg.type   = MSM_CAMERA_MSG;
774	rp->evt_msg.msg_id = id;
775	rp->evt_msg.len    = len;
776	rp->evt_msg.data   = msg;
777
778	switch (rp->evt_msg.msg_id) {
779	case VFE_MSG_ID_SNAPSHOT_DONE:
780		rp->type = VFE_MSG_SNAPSHOT;
781		break;
782
783	case VFE_MSG_ID_OUTPUT1:
784		rp->type = VFE_MSG_OUTPUT1;
785		vfe_addr_convert(&(rp->phy), VFE_MSG_OUTPUT1,
786			rp->evt_msg.data, &(rp->extdata),
787			&(rp->extlen));
788		break;
789
790	case VFE_MSG_ID_OUTPUT2:
791		rp->type = VFE_MSG_OUTPUT2;
792		vfe_addr_convert(&(rp->phy), VFE_MSG_OUTPUT2,
793				rp->evt_msg.data, &(rp->extdata),
794				&(rp->extlen));
795		break;
796
797	case VFE_MSG_ID_STATS_AUTOFOCUS:
798		rp->type = VFE_MSG_STATS_AF;
799		vfe_addr_convert(&(rp->phy), VFE_MSG_STATS_AF,
800				rp->evt_msg.data, NULL, NULL);
801		break;
802
803	case VFE_MSG_ID_STATS_WB_EXP:
804		rp->type = VFE_MSG_STATS_WE;
805		vfe_addr_convert(&(rp->phy), VFE_MSG_STATS_WE,
806				rp->evt_msg.data, NULL, NULL);
807		break;
808
809	default:
810		rp->type = VFE_MSG_GENERAL;
811		break;
812	}
813
814	ctrl->resp->vfe_resp(rp, MSM_CAM_Q_VFE_MSG, ctrl->syncdata);
815}
816
817static void vfe_send_msg_no_payload(enum VFE_MESSAGE_ID id)
818{
819	struct vfe_message *msg;
820
821	msg = kzalloc(sizeof(*msg), GFP_ATOMIC);
822	if (!msg)
823		return;
824
825	msg->_d = id;
826	vfe_proc_ops(id, msg, 0);
827}
828
829static void vfe_send_bus_overflow_msg(void)
830{
831	struct vfe_message *msg;
832	msg =
833		kzalloc(sizeof(struct vfe_message), GFP_ATOMIC);
834	if (!msg)
835		return;
836
837	msg->_d = VFE_MSG_ID_BUS_OVERFLOW;
838
839	vfe_proc_ops(VFE_MSG_ID_BUS_OVERFLOW,
840		msg, sizeof(struct vfe_message));
841}
842
843static void vfe_send_camif_error_msg(void)
844{
845}
846
847static void vfe_process_error_irq(
848	struct vfe_interrupt_status *irqstatus)
849{
850	/* all possible error irq.  Note error irqs are not enabled, it is
851	 * checked only when other interrupts are present. */
852	if (irqstatus->afOverflowIrq)
853		vfe_send_msg_no_payload(VFE_MSG_ID_AF_OVERFLOW);
854
855	if (irqstatus->awbOverflowIrq)
856		vfe_send_msg_no_payload(VFE_MSG_ID_AWB_OVERFLOW);
857
858	if (irqstatus->axiErrorIrq)
859		vfe_send_msg_no_payload(VFE_MSG_ID_AXI_ERROR);
860
861	if (irqstatus->busOverflowIrq)
862		vfe_send_bus_overflow_msg();
863
864	if (irqstatus->camifErrorIrq)
865		vfe_send_camif_error_msg();
866
867	if (irqstatus->camifOverflowIrq)
868		vfe_send_msg_no_payload(VFE_MSG_ID_CAMIF_OVERFLOW);
869
870	if (irqstatus->violationIrq)
871		;
872}
873
874static void vfe_process_camif_sof_irq(void)
875{
876	/* increment the frame id number. */
877	ctrl->vfeFrameId++;
878
879	CDBG("camif_sof_irq, frameId = %d\n",
880		ctrl->vfeFrameId);
881
882	/* In snapshot mode, if frame skip is programmed,
883	* need to check it accordingly to stop camif at
884	* correct frame boundary. For the dropped frames,
885	* there won't be any output path irqs, but there is
886	* still SOF irq, which can help us determine when
887	* to stop the camif.
888	*/
889	if (ctrl->vfeOperationMode) {
890		if ((1 << ctrl->vfeFrameSkipCount) &
891				ctrl->vfeFrameSkipPattern) {
892
893			ctrl->vfeSnapShotCount--;
894			if (ctrl->vfeSnapShotCount == 0)
895				/* terminate vfe pipeline at frame boundary. */
896				writel(CAMIF_COMMAND_STOP_AT_FRAME_BOUNDARY,
897					ctrl->vfebase + CAMIF_COMMAND);
898		}
899
900		/* update frame skip counter for bit checking. */
901		ctrl->vfeFrameSkipCount++;
902		if (ctrl->vfeFrameSkipCount ==
903				(ctrl->vfeFrameSkipPeriod + 1))
904			ctrl->vfeFrameSkipCount = 0;
905	}
906}
907
908static int vfe_get_af_pingpong_status(void)
909{
910	uint32_t busPingPongStatus;
911	int rc = 0;
912
913	busPingPongStatus =
914		readl(ctrl->vfebase + VFE_BUS_PINGPONG_STATUS);
915
916	if ((busPingPongStatus & VFE_AF_PINGPONG_STATUS_BIT) == 0)
917		return -EFAULT;
918
919	return rc;
920}
921
922static uint32_t vfe_read_af_buf_addr(boolean pipo)
923{
924	if (pipo == FALSE)
925		return readl(ctrl->vfebase + VFE_BUS_STATS_AF_WR_PING_ADDR);
926	else
927		return readl(ctrl->vfebase + VFE_BUS_STATS_AF_WR_PONG_ADDR);
928}
929
930static void
931vfe_update_af_buf_addr(boolean pipo, uint32_t addr)
932{
933	if (pipo == FALSE)
934		writel(addr, ctrl->vfebase + VFE_BUS_STATS_AF_WR_PING_ADDR);
935	else
936		writel(addr, ctrl->vfebase + VFE_BUS_STATS_AF_WR_PONG_ADDR);
937}
938
939static void
940vfe_send_af_stats_msg(uint32_t afBufAddress)
941{
942	/* unsigned long flags; */
943	struct vfe_message *msg;
944	msg =
945		kzalloc(sizeof(struct vfe_message), GFP_ATOMIC);
946	if (!msg)
947		return;
948
949	/* fill message with right content. */
950	/* @todo This is causing issues, need further investigate */
951	/* spin_lock_irqsave(&ctrl->state_lock, flags); */
952	if (ctrl->vstate != VFE_STATE_ACTIVE) {
953		kfree(msg);
954		goto af_stats_done;
955	}
956
957	msg->_d = VFE_MSG_ID_STATS_AUTOFOCUS;
958	msg->_u.msgStatsAf.afBuffer = afBufAddress;
959	msg->_u.msgStatsAf.frameCounter = ctrl->vfeFrameId;
960
961	vfe_proc_ops(VFE_MSG_ID_STATS_AUTOFOCUS,
962		msg, sizeof(struct vfe_message));
963
964	ctrl->afStatsControl.ackPending = TRUE;
965
966af_stats_done:
967	/* spin_unlock_irqrestore(&ctrl->state_lock, flags); */
968	return;
969}
970
971static void vfe_process_stats_af_irq(void)
972{
973	boolean bufferAvailable;
974
975	if (!(ctrl->afStatsControl.ackPending)) {
976
977		/* read hardware status. */
978		ctrl->afStatsControl.pingPongStatus =
979			vfe_get_af_pingpong_status();
980
981		bufferAvailable =
982			(ctrl->afStatsControl.pingPongStatus) ^ 1;
983
984		ctrl->afStatsControl.bufToRender =
985			vfe_read_af_buf_addr(bufferAvailable);
986
987		/* update the same buffer address (ping or pong) */
988		vfe_update_af_buf_addr(bufferAvailable,
989			ctrl->afStatsControl.nextFrameAddrBuf);
990
991		vfe_send_af_stats_msg(ctrl->afStatsControl.bufToRender);
992	} else
993		ctrl->afStatsControl.droppedStatsFrameCount++;
994}
995
996static boolean vfe_get_awb_pingpong_status(void)
997{
998	uint32_t busPingPongStatus;
999
1000	busPingPongStatus =
1001		readl(ctrl->vfebase + VFE_BUS_PINGPONG_STATUS);
1002
1003	if ((busPingPongStatus & VFE_AWB_PINGPONG_STATUS_BIT) == 0)
1004		return FALSE;
1005
1006	return TRUE;
1007}
1008
1009static uint32_t
1010vfe_read_awb_buf_addr(boolean pingpong)
1011{
1012	if (pingpong == FALSE)
1013		return readl(ctrl->vfebase + VFE_BUS_STATS_AWB_WR_PING_ADDR);
1014	else
1015		return readl(ctrl->vfebase + VFE_BUS_STATS_AWB_WR_PONG_ADDR);
1016}
1017
1018static void vfe_update_awb_buf_addr(
1019	boolean pingpong, uint32_t addr)
1020{
1021	if (pingpong == FALSE)
1022		writel(addr, ctrl->vfebase + VFE_BUS_STATS_AWB_WR_PING_ADDR);
1023	else
1024		writel(addr, ctrl->vfebase + VFE_BUS_STATS_AWB_WR_PONG_ADDR);
1025}
1026
1027static void vfe_send_awb_stats_msg(uint32_t awbBufAddress)
1028{
1029	/* unsigned long flags; */
1030	struct vfe_message   *msg;
1031
1032	msg =
1033		kzalloc(sizeof(struct vfe_message), GFP_ATOMIC);
1034	if (!msg)
1035		return;
1036
1037	/* fill message with right content. */
1038	/* @todo This is causing issues, need further investigate */
1039	/* spin_lock_irqsave(&ctrl->state_lock, flags); */
1040	if (ctrl->vstate != VFE_STATE_ACTIVE) {
1041		kfree(msg);
1042		goto awb_stats_done;
1043	}
1044
1045	msg->_d = VFE_MSG_ID_STATS_WB_EXP;
1046	msg->_u.msgStatsWbExp.awbBuffer = awbBufAddress;
1047	msg->_u.msgStatsWbExp.frameCounter = ctrl->vfeFrameId;
1048
1049	vfe_proc_ops(VFE_MSG_ID_STATS_WB_EXP,
1050		msg, sizeof(struct vfe_message));
1051
1052	ctrl->awbStatsControl.ackPending = TRUE;
1053
1054awb_stats_done:
1055	/* spin_unlock_irqrestore(&ctrl->state_lock, flags); */
1056	return;
1057}
1058
1059static void vfe_process_stats_awb_irq(void)
1060{
1061	boolean bufferAvailable;
1062
1063	if (!(ctrl->awbStatsControl.ackPending)) {
1064
1065		ctrl->awbStatsControl.pingPongStatus =
1066			vfe_get_awb_pingpong_status();
1067
1068		bufferAvailable = (ctrl->awbStatsControl.pingPongStatus) ^ 1;
1069
1070		ctrl->awbStatsControl.bufToRender =
1071			vfe_read_awb_buf_addr(bufferAvailable);
1072
1073		vfe_update_awb_buf_addr(bufferAvailable,
1074			ctrl->awbStatsControl.nextFrameAddrBuf);
1075
1076		vfe_send_awb_stats_msg(ctrl->awbStatsControl.bufToRender);
1077
1078	} else
1079		ctrl->awbStatsControl.droppedStatsFrameCount++;
1080}
1081
1082static void vfe_process_sync_timer_irq(
1083	struct vfe_interrupt_status *irqstatus)
1084{
1085	if (irqstatus->syncTimer0Irq)
1086		vfe_send_msg_no_payload(VFE_MSG_ID_SYNC_TIMER0_DONE);
1087
1088	if (irqstatus->syncTimer1Irq)
1089		vfe_send_msg_no_payload(VFE_MSG_ID_SYNC_TIMER1_DONE);
1090
1091	if (irqstatus->syncTimer2Irq)
1092		vfe_send_msg_no_payload(VFE_MSG_ID_SYNC_TIMER2_DONE);
1093}
1094
1095static void vfe_process_async_timer_irq(
1096	struct vfe_interrupt_status *irqstatus)
1097{
1098
1099	if (irqstatus->asyncTimer0Irq)
1100		vfe_send_msg_no_payload(VFE_MSG_ID_ASYNC_TIMER0_DONE);
1101
1102	if (irqstatus->asyncTimer1Irq)
1103		vfe_send_msg_no_payload(VFE_MSG_ID_ASYNC_TIMER1_DONE);
1104
1105	if (irqstatus->asyncTimer2Irq)
1106		vfe_send_msg_no_payload(VFE_MSG_ID_ASYNC_TIMER2_DONE);
1107
1108	if (irqstatus->asyncTimer3Irq)
1109		vfe_send_msg_no_payload(VFE_MSG_ID_ASYNC_TIMER3_DONE);
1110}
1111
1112static void vfe_send_violation_msg(void)
1113{
1114	vfe_send_msg_no_payload(VFE_MSG_ID_VIOLATION);
1115}
1116
1117static void vfe_send_async_timer_msg(void)
1118{
1119	vfe_send_msg_no_payload(VFE_MSG_ID_ASYNC_TIMER0_DONE);
1120}
1121
1122static void vfe_write_gamma_table(uint8_t channel,
1123	boolean bank, int16_t *pTable)
1124{
1125	uint16_t i;
1126
1127	enum VFE_DMI_RAM_SEL dmiRamSel = NO_MEM_SELECTED;
1128
1129	switch (channel) {
1130	case 0:
1131		if (bank == 0)
1132			dmiRamSel = RGBLUT_RAM_CH0_BANK0;
1133		else
1134			dmiRamSel = RGBLUT_RAM_CH0_BANK1;
1135		break;
1136
1137	case 1:
1138		if (bank == 0)
1139			dmiRamSel = RGBLUT_RAM_CH1_BANK0;
1140		else
1141			dmiRamSel = RGBLUT_RAM_CH1_BANK1;
1142		break;
1143
1144	case 2:
1145		if (bank == 0)
1146			dmiRamSel = RGBLUT_RAM_CH2_BANK0;
1147		else
1148			dmiRamSel = RGBLUT_RAM_CH2_BANK1;
1149		break;
1150
1151	default:
1152		break;
1153	}
1154
1155	vfe_program_dmi_cfg(dmiRamSel);
1156
1157	for (i = 0; i < VFE_GAMMA_TABLE_LENGTH; i++) {
1158		writel((uint32_t)(*pTable), ctrl->vfebase + VFE_DMI_DATA_LO);
1159		pTable++;
1160	}
1161
1162	/* After DMI transfer, need to set the DMI_CFG to unselect any SRAM
1163	unselect the SRAM Bank. */
1164	writel(VFE_DMI_CFG_DEFAULT, ctrl->vfebase + VFE_DMI_CFG);
1165}
1166
1167static void vfe_prog_hw_testgen_cmd(uint32_t value)
1168{
1169	writel(value, ctrl->vfebase + VFE_HW_TESTGEN_CMD);
1170}
1171
1172static inline void vfe_read_irq_status(struct vfe_irq_thread_msg *out)
1173{
1174	uint32_t *temp;
1175
1176	memset(out, 0, sizeof(struct vfe_irq_thread_msg));
1177
1178	temp = (uint32_t *)(ctrl->vfebase + VFE_IRQ_STATUS);
1179	out->vfeIrqStatus = readl(temp);
1180
1181	temp = (uint32_t *)(ctrl->vfebase + CAMIF_STATUS);
1182	out->camifStatus = readl(temp);
1183	writel(0x7, ctrl->vfebase + CAMIF_COMMAND);
1184	writel(0x3, ctrl->vfebase + CAMIF_COMMAND);
1185	CDBG("camifStatus  = 0x%x\n", out->camifStatus);
1186
1187/*
1188	temp = (uint32_t *)(ctrl->vfebase + VFE_DEMOSAIC_STATUS);
1189	out->demosaicStatus = readl(temp);
1190
1191	temp = (uint32_t *)(ctrl->vfebase + VFE_ASF_MAX_EDGE);
1192	out->asfMaxEdge = readl(temp);
1193
1194	temp = (uint32_t *)(ctrl->vfebase + VFE_BUS_ENC_Y_WR_PM_STATS_0);
1195*/
1196
1197}
1198
1199static struct vfe_interrupt_status
1200vfe_parse_interrupt_status(uint32_t irqStatusIn)
1201{
1202	struct vfe_irqenable hwstat;
1203	struct vfe_interrupt_status ret;
1204	boolean temp;
1205
1206	memset(&hwstat, 0, sizeof(hwstat));
1207	memset(&ret, 0, sizeof(ret));
1208
1209	hwstat = *((struct vfe_irqenable *)(&irqStatusIn));
1210
1211	ret.camifErrorIrq       = hwstat.camifErrorIrq;
1212	ret.camifSofIrq         = hwstat.camifSofIrq;
1213	ret.camifEolIrq         = hwstat.camifEolIrq;
1214	ret.camifEofIrq         = hwstat.camifEofIrq;
1215	ret.camifEpoch1Irq      = hwstat.camifEpoch1Irq;
1216	ret.camifEpoch2Irq      = hwstat.camifEpoch2Irq;
1217	ret.camifOverflowIrq    = hwstat.camifOverflowIrq;
1218	ret.ceIrq               = hwstat.ceIrq;
1219	ret.regUpdateIrq        = hwstat.regUpdateIrq;
1220	ret.resetAckIrq         = hwstat.resetAckIrq;
1221	ret.encYPingpongIrq     = hwstat.encYPingpongIrq;
1222	ret.encCbcrPingpongIrq  = hwstat.encCbcrPingpongIrq;
1223	ret.viewYPingpongIrq    = hwstat.viewYPingpongIrq;
1224	ret.viewCbcrPingpongIrq = hwstat.viewCbcrPingpongIrq;
1225	ret.rdPingpongIrq       = hwstat.rdPingpongIrq;
1226	ret.afPingpongIrq       = hwstat.afPingpongIrq;
1227	ret.awbPingpongIrq      = hwstat.awbPingpongIrq;
1228	ret.histPingpongIrq     = hwstat.histPingpongIrq;
1229	ret.encIrq              = hwstat.encIrq;
1230	ret.viewIrq             = hwstat.viewIrq;
1231	ret.busOverflowIrq      = hwstat.busOverflowIrq;
1232	ret.afOverflowIrq       = hwstat.afOverflowIrq;
1233	ret.awbOverflowIrq      = hwstat.awbOverflowIrq;
1234	ret.syncTimer0Irq       = hwstat.syncTimer0Irq;
1235	ret.syncTimer1Irq       = hwstat.syncTimer1Irq;
1236	ret.syncTimer2Irq       = hwstat.syncTimer2Irq;
1237	ret.asyncTimer0Irq      = hwstat.asyncTimer0Irq;
1238	ret.asyncTimer1Irq      = hwstat.asyncTimer1Irq;
1239	ret.asyncTimer2Irq      = hwstat.asyncTimer2Irq;
1240	ret.asyncTimer3Irq      = hwstat.asyncTimer3Irq;
1241	ret.axiErrorIrq         = hwstat.axiErrorIrq;
1242	ret.violationIrq        = hwstat.violationIrq;
1243
1244	/* logic OR of any error bits
1245	 * although each irq corresponds to a bit, the data type here is a
1246	 * boolean already. hence use logic operation.
1247	 */
1248	temp =
1249		ret.camifErrorIrq    ||
1250		ret.camifOverflowIrq ||
1251		ret.afOverflowIrq    ||
1252		ret.awbPingpongIrq   ||
1253		ret.busOverflowIrq   ||
1254		ret.axiErrorIrq      ||
1255		ret.violationIrq;
1256
1257	ret.anyErrorIrqs = temp;
1258
1259	/* logic OR of any output path bits*/
1260	temp =
1261		ret.encYPingpongIrq    ||
1262		ret.encCbcrPingpongIrq ||
1263		ret.encIrq;
1264
1265	ret.anyOutput2PathIrqs = temp;
1266
1267	temp =
1268		ret.viewYPingpongIrq    ||
1269		ret.viewCbcrPingpongIrq ||
1270		ret.viewIrq;
1271
1272	ret.anyOutput1PathIrqs = temp;
1273
1274	ret.anyOutputPathIrqs =
1275		ret.anyOutput1PathIrqs ||
1276		ret.anyOutput2PathIrqs;
1277
1278	/* logic OR of any sync timer bits*/
1279	temp =
1280		ret.syncTimer0Irq ||
1281		ret.syncTimer1Irq ||
1282		ret.syncTimer2Irq;
1283
1284	ret.anySyncTimerIrqs = temp;
1285
1286	/* logic OR of any async timer bits*/
1287	temp =
1288		ret.asyncTimer0Irq ||
1289		ret.asyncTimer1Irq ||
1290		ret.asyncTimer2Irq ||
1291		ret.asyncTimer3Irq;
1292
1293	ret.anyAsyncTimerIrqs = temp;
1294
1295	/* bool for all interrupts that are not allowed in idle state */
1296	temp =
1297		ret.anyErrorIrqs      ||
1298		ret.anyOutputPathIrqs ||
1299		ret.anySyncTimerIrqs  ||
1300		ret.regUpdateIrq      ||
1301		ret.awbPingpongIrq    ||
1302		ret.afPingpongIrq     ||
1303		ret.camifSofIrq       ||
1304		ret.camifEpoch2Irq    ||
1305		ret.camifEpoch1Irq;
1306
1307	ret.anyIrqForActiveStatesOnly =
1308		temp;
1309
1310	return ret;
1311}
1312
1313static struct vfe_frame_asf_info
1314vfe_get_asf_frame_info(struct vfe_irq_thread_msg *in)
1315{
1316	struct vfe_asf_info     asfInfoTemp;
1317	struct vfe_frame_asf_info rc;
1318
1319	memset(&rc, 0, sizeof(rc));
1320	memset(&asfInfoTemp, 0, sizeof(asfInfoTemp));
1321
1322	asfInfoTemp =
1323		*((struct vfe_asf_info *)(&(in->asfMaxEdge)));
1324
1325	rc.asfHbiCount = asfInfoTemp.HBICount;
1326	rc.asfMaxEdge  = asfInfoTemp.maxEdge;
1327
1328	return rc;
1329}
1330
1331static struct vfe_frame_bpc_info
1332vfe_get_demosaic_frame_info(struct vfe_irq_thread_msg *in)
1333{
1334	struct vfe_bps_info     bpcInfoTemp;
1335	struct vfe_frame_bpc_info rc;
1336
1337	memset(&rc, 0, sizeof(rc));
1338	memset(&bpcInfoTemp, 0, sizeof(bpcInfoTemp));
1339
1340	bpcInfoTemp =
1341		*((struct vfe_bps_info *)(&(in->demosaicStatus)));
1342
1343	rc.greenDefectPixelCount    =
1344		bpcInfoTemp.greenBadPixelCount;
1345
1346	rc.redBlueDefectPixelCount  =
1347		bpcInfoTemp.RedBlueBadPixelCount;
1348
1349	return rc;
1350}
1351
1352static struct vfe_msg_camif_status
1353vfe_get_camif_status(struct vfe_irq_thread_msg *in)
1354{
1355	struct vfe_camif_stats camifStatusTemp;
1356	struct vfe_msg_camif_status rc;
1357
1358	memset(&rc, 0, sizeof(rc));
1359	memset(&camifStatusTemp, 0, sizeof(camifStatusTemp));
1360
1361	camifStatusTemp =
1362		*((struct vfe_camif_stats *)(&(in->camifStatus)));
1363
1364	rc.camifState = (boolean)camifStatusTemp.camifHalt;
1365	rc.lineCount  = camifStatusTemp.lineCount;
1366	rc.pixelCount = camifStatusTemp.pixelCount;
1367
1368	return rc;
1369}
1370
1371static struct vfe_bus_performance_monitor
1372vfe_get_performance_monitor_data(struct vfe_irq_thread_msg *in)
1373{
1374	struct vfe_bus_performance_monitor rc;
1375	memset(&rc, 0, sizeof(rc));
1376
1377	rc.encPathPmInfo.yWrPmStats0     =
1378		in->pmInfo.encPathPmInfo.yWrPmStats0;
1379	rc.encPathPmInfo.yWrPmStats1     =
1380		in->pmInfo.encPathPmInfo.yWrPmStats1;
1381	rc.encPathPmInfo.cbcrWrPmStats0  =
1382		in->pmInfo.encPathPmInfo.cbcrWrPmStats0;
1383	rc.encPathPmInfo.cbcrWrPmStats1  =
1384		in->pmInfo.encPathPmInfo.cbcrWrPmStats1;
1385	rc.viewPathPmInfo.yWrPmStats0    =
1386		in->pmInfo.viewPathPmInfo.yWrPmStats0;
1387	rc.viewPathPmInfo.yWrPmStats1    =
1388		in->pmInfo.viewPathPmInfo.yWrPmStats1;
1389	rc.viewPathPmInfo.cbcrWrPmStats0 =
1390		in->pmInfo.viewPathPmInfo.cbcrWrPmStats0;
1391	rc.viewPathPmInfo.cbcrWrPmStats1 =
1392		in->pmInfo.viewPathPmInfo.cbcrWrPmStats1;
1393
1394	return rc;
1395}
1396
1397static void vfe_process_reg_update_irq(void)
1398{
1399	CDBG("vfe_process_reg_update_irq: ackPendingFlag is %d\n",
1400	ctrl->vfeStartAckPendingFlag);
1401	if (ctrl->vfeStartAckPendingFlag == TRUE) {
1402		vfe_send_msg_no_payload(VFE_MSG_ID_START_ACK);
1403		ctrl->vfeStartAckPendingFlag = FALSE;
1404	} else
1405		vfe_send_msg_no_payload(VFE_MSG_ID_UPDATE_ACK);
1406}
1407
1408static void vfe_process_reset_irq(void)
1409{
1410	/* unsigned long flags; */
1411
1412	/* @todo This is causing issues, need further investigate */
1413	/* spin_lock_irqsave(&ctrl->state_lock, flags); */
1414	ctrl->vstate = VFE_STATE_IDLE;
1415	/* spin_unlock_irqrestore(&ctrl->state_lock, flags); */
1416
1417	if (ctrl->vfeStopAckPending == TRUE) {
1418		ctrl->vfeStopAckPending = FALSE;
1419		vfe_send_msg_no_payload(VFE_MSG_ID_STOP_ACK);
1420	} else {
1421		vfe_set_default_reg_values();
1422		vfe_send_msg_no_payload(VFE_MSG_ID_RESET_ACK);
1423	}
1424}
1425
1426static void vfe_process_pingpong_irq(struct vfe_output_path *in,
1427	uint8_t fragmentCount)
1428{
1429	uint16_t circularIndex;
1430	uint32_t nextFragmentAddr;
1431
1432	/* get next fragment address from circular buffer */
1433	circularIndex    = (in->fragIndex) % (2 * fragmentCount);
1434	nextFragmentAddr = in->addressBuffer[circularIndex];
1435
1436	in->fragIndex = circularIndex + 1;
1437
1438	/* use next fragment to program hardware ping/pong address. */
1439	if (in->hwCurrentFlag == ping) {
1440		writel(nextFragmentAddr, in->hwRegPingAddress);
1441		in->hwCurrentFlag = pong;
1442
1443	} else {
1444		writel(nextFragmentAddr, in->hwRegPongAddress);
1445		in->hwCurrentFlag = ping;
1446	}
1447}
1448
1449static void vfe_send_output2_msg(
1450	struct vfe_msg_output *pPayload)
1451{
1452	/* unsigned long flags; */
1453	struct vfe_message *msg;
1454
1455	msg = kzalloc(sizeof(struct vfe_message), GFP_ATOMIC);
1456	if (!msg)
1457		return;
1458
1459	/* fill message with right content. */
1460	/* @todo This is causing issues, need further investigate */
1461	/* spin_lock_irqsave(&ctrl->state_lock, flags); */
1462	if (ctrl->vstate != VFE_STATE_ACTIVE) {
1463		kfree(msg);
1464		goto output2_msg_done;
1465	}
1466
1467	msg->_d = VFE_MSG_ID_OUTPUT2;
1468
1469	memcpy(&(msg->_u.msgOutput2),
1470		(void *)pPayload, sizeof(struct vfe_msg_output));
1471
1472	vfe_proc_ops(VFE_MSG_ID_OUTPUT2,
1473		msg, sizeof(struct vfe_message));
1474
1475	ctrl->encPath.ackPending = TRUE;
1476
1477	if (!(ctrl->vfeRequestedSnapShotCount <= 3) &&
1478			(ctrl->vfeOperationMode ==
1479			 VFE_START_OPERATION_MODE_SNAPSHOT))
1480		ctrl->encPath.ackPending = TRUE;
1481
1482output2_msg_done:
1483	/* spin_unlock_irqrestore(&ctrl->state_lock, flags); */
1484	return;
1485}
1486
1487static void vfe_send_output1_msg(
1488	struct vfe_msg_output *pPayload)
1489{
1490	/* unsigned long flags; */
1491	struct vfe_message *msg;
1492
1493	msg = kzalloc(sizeof(struct vfe_message), GFP_ATOMIC);
1494	if (!msg)
1495		return;
1496
1497	/* @todo This is causing issues, need further investigate */
1498	/* spin_lock_irqsave(&ctrl->state_lock, flags); */
1499	if (ctrl->vstate != VFE_STATE_ACTIVE) {
1500		kfree(msg);
1501		goto output1_msg_done;
1502	}
1503
1504	msg->_d = VFE_MSG_ID_OUTPUT1;
1505	memmove(&(msg->_u),
1506		(void *)pPayload, sizeof(struct vfe_msg_output));
1507
1508	vfe_proc_ops(VFE_MSG_ID_OUTPUT1,
1509		msg, sizeof(struct vfe_message));
1510
1511	ctrl->viewPath.ackPending = TRUE;
1512
1513	if (!(ctrl->vfeRequestedSnapShotCount <= 3) &&
1514			(ctrl->vfeOperationMode ==
1515			 VFE_START_OPERATION_MODE_SNAPSHOT))
1516		ctrl->viewPath.ackPending = TRUE;
1517
1518output1_msg_done:
1519	/* spin_unlock_irqrestore(&ctrl->state_lock, flags); */
1520	return;
1521}
1522
1523static void vfe_send_output_msg(boolean whichOutputPath,
1524	uint32_t yPathAddr, uint32_t cbcrPathAddr)
1525{
1526	struct vfe_msg_output msgPayload;
1527
1528	msgPayload.yBuffer = yPathAddr;
1529	msgPayload.cbcrBuffer = cbcrPathAddr;
1530
1531	/* asf info is common for both output1 and output2 */
1532
1533	/* frame ID is common for both paths. */
1534	msgPayload.frameCounter = ctrl->vfeFrameId;
1535
1536	if (whichOutputPath) {
1537		/* msgPayload.pmData = ctrl->vfePmData.encPathPmInfo; */
1538		vfe_send_output2_msg(&msgPayload);
1539	} else {
1540		/* msgPayload.pmData = ctrl->vfePmData.viewPathPmInfo; */
1541		vfe_send_output1_msg(&msgPayload);
1542	}
1543}
1544
1545static void vfe_process_frame_done_irq_multi_frag(
1546	struct vfe_output_path_combo *in)
1547{
1548	uint32_t yAddress, cbcrAddress;
1549	uint16_t idx;
1550	uint32_t *ptrY;
1551	uint32_t *ptrCbcr;
1552	const uint32_t *ptrSrc;
1553	uint8_t i;
1554
1555	if (!in->ackPending) {
1556
1557		idx = (in->currentFrame) * (in->fragCount);
1558
1559		/* Send output message. */
1560		yAddress = in->yPath.addressBuffer[idx];
1561		cbcrAddress = in->cbcrPath.addressBuffer[idx];
1562
1563		/* copy next frame to current frame. */
1564		ptrSrc  = in->nextFrameAddrBuf;
1565		ptrY    = (uint32_t *)&(in->yPath.addressBuffer[idx]);
1566		ptrCbcr = (uint32_t *)&(in->cbcrPath.addressBuffer[idx]);
1567
1568		/* Copy Y address */
1569		for (i = 0; i < in->fragCount; i++)
1570			*ptrY++ = *ptrSrc++;
1571
1572		/* Copy Cbcr address */
1573		for (i = 0; i < in->fragCount; i++)
1574			*ptrCbcr++ = *ptrSrc++;
1575
1576		vfe_send_output_msg(in->whichOutputPath, yAddress, cbcrAddress);
1577
1578	} else {
1579		if (in->whichOutputPath == 0)
1580			ctrl->vfeDroppedFrameCounts.output1Count++;
1581
1582		if (in->whichOutputPath == 1)
1583			ctrl->vfeDroppedFrameCounts.output2Count++;
1584	}
1585
1586	/* toggle current frame. */
1587	in->currentFrame = in->currentFrame^1;
1588
1589	if (ctrl->vfeOperationMode)
1590		in->snapshotPendingCount--;
1591}
1592
1593static void vfe_process_frame_done_irq_no_frag_io(
1594	struct vfe_output_path_combo *in, uint32_t *pNextAddr,
1595	uint32_t *pdestRenderAddr)
1596{
1597	uint32_t busPingPongStatus;
1598	uint32_t tempAddress;
1599
1600	/* 1. read hw status register. */
1601	busPingPongStatus =
1602		readl(ctrl->vfebase + VFE_BUS_PINGPONG_STATUS);
1603
1604	CDBG("hardware status is 0x%x\n", busPingPongStatus);
1605
1606	/* 2. determine ping or pong */
1607	/* use cbcr status */
1608	busPingPongStatus = busPingPongStatus & (1<<(in->cbcrStatusBit));
1609
1610	/* 3. read out address and update address */
1611	if (busPingPongStatus == 0) {
1612		/* hw is working on ping, render pong buffer */
1613		/* a. read out pong address */
1614		/* read out y address. */
1615		tempAddress = readl(in->yPath.hwRegPongAddress);
1616
1617		CDBG("pong 1 addr = 0x%x\n", tempAddress);
1618		*pdestRenderAddr++ = tempAddress;
1619		/* read out cbcr address. */
1620		tempAddress = readl(in->cbcrPath.hwRegPongAddress);
1621
1622		CDBG("pong 2 addr = 0x%x\n", tempAddress);
1623		*pdestRenderAddr = tempAddress;
1624
1625		/* b. update pong address */
1626		writel(*pNextAddr++, in->yPath.hwRegPongAddress);
1627		writel(*pNextAddr, in->cbcrPath.hwRegPongAddress);
1628	} else {
1629		/* hw is working on pong, render ping buffer */
1630
1631		/* a. read out ping address */
1632		tempAddress = readl(in->yPath.hwRegPingAddress);
1633		CDBG("ping 1 addr = 0x%x\n", tempAddress);
1634		*pdestRenderAddr++ = tempAddress;
1635		tempAddress = readl(in->cbcrPath.hwRegPingAddress);
1636
1637		CDBG("ping 2 addr = 0x%x\n", tempAddress);
1638		*pdestRenderAddr = tempAddress;
1639
1640		/* b. update ping address */
1641		writel(*pNextAddr++, in->yPath.hwRegPingAddress);
1642		CDBG("NextAddress = 0x%x\n", *pNextAddr);
1643		writel(*pNextAddr, in->cbcrPath.hwRegPingAddress);
1644	}
1645}
1646
1647static void vfe_process_frame_done_irq_no_frag(
1648	struct vfe_output_path_combo *in)
1649{
1650	uint32_t addressToRender[2];
1651	static uint32_t fcnt;
1652
1653	if (fcnt++ < 3)
1654		return;
1655
1656	if (!in->ackPending) {
1657		vfe_process_frame_done_irq_no_frag_io(in,
1658			in->nextFrameAddrBuf, addressToRender);
1659
1660		/* use addressToRender to send out message. */
1661		vfe_send_output_msg(in->whichOutputPath,
1662				addressToRender[0], addressToRender[1]);
1663
1664	} else {
1665		/* ackPending is still there, accumulate dropped frame count.
1666		 * These count can be read through ioctrl command. */
1667		CDBG("waiting frame ACK\n");
1668
1669		if (in->whichOutputPath == 0)
1670			ctrl->vfeDroppedFrameCounts.output1Count++;
1671
1672		if (in->whichOutputPath == 1)
1673			ctrl->vfeDroppedFrameCounts.output2Count++;
1674	}
1675
1676	/* in case of multishot when upper layer did not ack, there will still
1677	 * be a snapshot done msg sent out, even though the number of frames
1678	 * sent out may be less than the desired number of frames.  snapshot
1679	 * done msg would be helpful to indicate that vfe pipeline has stop,
1680	 * and in good known state.
1681	 */
1682	if (ctrl->vfeOperationMode)
1683		in->snapshotPendingCount--;
1684}
1685
1686static void vfe_process_output_path_irq(
1687	struct vfe_interrupt_status *irqstatus)
1688{
1689	/* unsigned long flags; */
1690
1691	/* process the view path interrupts */
1692	if (irqstatus->anyOutput1PathIrqs) {
1693		if (ctrl->viewPath.multiFrag) {
1694
1695			if (irqstatus->viewCbcrPingpongIrq)
1696				vfe_process_pingpong_irq(
1697					&(ctrl->viewPath.cbcrPath),
1698					ctrl->viewPath.fragCount);
1699
1700			if (irqstatus->viewYPingpongIrq)
1701				vfe_process_pingpong_irq(
1702					&(ctrl->viewPath.yPath),
1703					ctrl->viewPath.fragCount);
1704
1705			if (irqstatus->viewIrq)
1706				vfe_process_frame_done_irq_multi_frag(
1707					&ctrl->viewPath);
1708
1709		} else {
1710			/* typical case for no fragment,
1711			 only frame done irq is enabled. */
1712			if (irqstatus->viewIrq)
1713				vfe_process_frame_done_irq_no_frag(
1714					&ctrl->viewPath);
1715		}
1716	}
1717
1718	/* process the encoder path interrupts */
1719	if (irqstatus->anyOutput2PathIrqs) {
1720		if (ctrl->encPath.multiFrag) {
1721			if (irqstatus->encCbcrPingpongIrq)
1722				vfe_process_pingpong_irq(
1723					&(ctrl->encPath.cbcrPath),
1724					ctrl->encPath.fragCount);
1725
1726			if (irqstatus->encYPingpongIrq)
1727				vfe_process_pingpong_irq(&(ctrl->encPath.yPath),
1728				ctrl->encPath.fragCount);
1729
1730			if (irqstatus->encIrq)
1731				vfe_process_frame_done_irq_multi_frag(
1732					&ctrl->encPath);
1733
1734		} else {
1735			if (irqstatus->encIrq)
1736				vfe_process_frame_done_irq_no_frag(
1737					&ctrl->encPath);
1738		}
1739	}
1740
1741	if (ctrl->vfeOperationMode) {
1742		if ((ctrl->encPath.snapshotPendingCount == 0) &&
1743				(ctrl->viewPath.snapshotPendingCount == 0)) {
1744
1745			/* @todo This is causing issues, further investigate */
1746			/* spin_lock_irqsave(&ctrl->state_lock, flags); */
1747			ctrl->vstate = VFE_STATE_IDLE;
1748			/* spin_unlock_irqrestore(&ctrl->state_lock, flags); */
1749
1750			vfe_send_msg_no_payload(VFE_MSG_ID_SNAPSHOT_DONE);
1751			vfe_prog_hw_testgen_cmd(VFE_TEST_GEN_STOP);
1752			vfe_pm_stop();
1753		}
1754	}
1755}
1756
1757static void vfe_do_tasklet(unsigned long data)
1758{
1759	unsigned long flags;
1760
1761	struct isr_queue_cmd *qcmd = NULL;
1762
1763	CDBG("=== vfe_do_tasklet start === \n");
1764
1765	spin_lock_irqsave(&ctrl->tasklet_lock, flags);
1766	qcmd = list_first_entry(&ctrl->tasklet_q,
1767			struct isr_queue_cmd, list);
1768
1769	if (!qcmd) {
1770		spin_unlock_irqrestore(&ctrl->tasklet_lock, flags);
1771		return;
1772	}
1773
1774	list_del(&qcmd->list);
1775	spin_unlock_irqrestore(&ctrl->tasklet_lock, flags);
1776
1777	if (qcmd->vfeInterruptStatus.regUpdateIrq) {
1778		CDBG("irq	regUpdateIrq\n");
1779		vfe_process_reg_update_irq();
1780	}
1781
1782	if (qcmd->vfeInterruptStatus.resetAckIrq) {
1783		CDBG("irq	resetAckIrq\n");
1784		vfe_process_reset_irq();
1785	}
1786
1787	spin_lock_irqsave(&ctrl->state_lock, flags);
1788	if (ctrl->vstate != VFE_STATE_ACTIVE) {
1789		spin_unlock_irqrestore(&ctrl->state_lock, flags);
1790		return;
1791	}
1792	spin_unlock_irqrestore(&ctrl->state_lock, flags);
1793
1794
1795	/* next, check output path related interrupts. */
1796	if (qcmd->vfeInterruptStatus.anyOutputPathIrqs) {
1797		CDBG("irq	anyOutputPathIrqs\n");
1798		vfe_process_output_path_irq(&qcmd->vfeInterruptStatus);
1799	}
1800
1801	if (qcmd->vfeInterruptStatus.afPingpongIrq)
1802		vfe_process_stats_af_irq();
1803
1804	if (qcmd->vfeInterruptStatus.awbPingpongIrq)
1805		vfe_process_stats_awb_irq();
1806
1807	/* any error irqs*/
1808	if (qcmd->vfeInterruptStatus.anyErrorIrqs)
1809		vfe_process_error_irq(&qcmd->vfeInterruptStatus);
1810
1811
1812	if (qcmd->vfeInterruptStatus.camifSofIrq) {
1813		CDBG("irq	camifSofIrq\n");
1814		vfe_process_camif_sof_irq();
1815	}
1816
1817	kfree(qcmd);
1818	CDBG("=== vfe_do_tasklet end === \n");
1819}
1820
1821DECLARE_TASKLET(vfe_tasklet, vfe_do_tasklet, 0);
1822
1823static irqreturn_t vfe_parse_irq(int irq_num, void *data)
1824{
1825	unsigned long flags;
1826	uint32_t irqStatusLocal;
1827	struct vfe_irq_thread_msg irq;
1828	struct isr_queue_cmd *qcmd;
1829
1830	CDBG("vfe_parse_irq\n");
1831
1832	vfe_read_irq_status(&irq);
1833
1834	if (irq.vfeIrqStatus == 0) {
1835		CDBG("vfe_parse_irq: irq.vfeIrqStatus is 0\n");
1836		return IRQ_HANDLED;
1837	}
1838
1839	qcmd = kzalloc(sizeof(struct isr_queue_cmd),
1840		GFP_ATOMIC);
1841	if (!qcmd) {
1842		CDBG("vfe_parse_irq: qcmd malloc failed!\n");
1843		return IRQ_HANDLED;
1844	}
1845
1846	spin_lock_irqsave(&ctrl->ack_lock, flags);
1847
1848	if (ctrl->vfeStopAckPending)
1849		irqStatusLocal =
1850			(VFE_IMASK_WHILE_STOPPING & irq.vfeIrqStatus);
1851	else
1852		irqStatusLocal =
1853			((ctrl->vfeImaskPacked | VFE_IMASK_ERROR_ONLY) &
1854				irq.vfeIrqStatus);
1855
1856	spin_unlock_irqrestore(&ctrl->ack_lock, flags);
1857
1858	/* first parse the interrupt status to local data structures. */
1859	qcmd->vfeInterruptStatus = vfe_parse_interrupt_status(irqStatusLocal);
1860	qcmd->vfeAsfFrameInfo = vfe_get_asf_frame_info(&irq);
1861	qcmd->vfeBpcFrameInfo = vfe_get_demosaic_frame_info(&irq);
1862	qcmd->vfeCamifStatusLocal = vfe_get_camif_status(&irq);
1863	qcmd->vfePmData = vfe_get_performance_monitor_data(&irq);
1864
1865	spin_lock_irqsave(&ctrl->tasklet_lock, flags);
1866	list_add_tail(&qcmd->list, &ctrl->tasklet_q);
1867	spin_unlock_irqrestore(&ctrl->tasklet_lock, flags);
1868	tasklet_schedule(&vfe_tasklet);
1869
1870	/* clear the pending interrupt of the same kind.*/
1871	writel(irq.vfeIrqStatus, ctrl->vfebase + VFE_IRQ_CLEAR);
1872
1873	return IRQ_HANDLED;
1874}
1875
1876int vfe_cmd_init(struct msm_vfe_callback *presp,
1877	struct platform_device *pdev, void *sdata)
1878{
1879	struct resource	*vfemem, *vfeirq, *vfeio;
1880	int rc;
1881
1882	vfemem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1883	if (!vfemem) {
1884		CDBG("no mem resource?\n");
1885		return -ENODEV;
1886	}
1887
1888	vfeirq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
1889	if (!vfeirq) {
1890		CDBG("no irq resource?\n");
1891		return -ENODEV;
1892	}
1893
1894	vfeio = request_mem_region(vfemem->start,
1895		resource_size(vfemem), pdev->name);
1896	if (!vfeio) {
1897		CDBG("VFE region already claimed\n");
1898		return -EBUSY;
1899	}
1900
1901	ctrl =
1902	kzalloc(sizeof(struct msm_vfe8x_ctrl), GFP_KERNEL);
1903	if (!ctrl) {
1904		rc = -ENOMEM;
1905		goto cmd_init_failed1;
1906	}
1907
1908	ctrl->vfeirq  = vfeirq->start;
1909
1910	ctrl->vfebase =
1911		ioremap(vfemem->start, (vfemem->end - vfemem->start) + 1);
1912	if (!ctrl->vfebase) {
1913		rc = -ENOMEM;
1914		goto cmd_init_failed2;
1915	}
1916
1917	rc = request_irq(ctrl->vfeirq, vfe_parse_irq,
1918		IRQF_TRIGGER_RISING, "vfe", 0);
1919	if (rc < 0)
1920		goto cmd_init_failed2;
1921
1922	if (presp && presp->vfe_resp)
1923		ctrl->resp = presp;
1924	else {
1925		rc = -EINVAL;
1926		goto cmd_init_failed3;
1927	}
1928
1929	ctrl->extdata =
1930		kmalloc(sizeof(struct vfe_frame_extra), GFP_KERNEL);
1931	if (!ctrl->extdata) {
1932		rc = -ENOMEM;
1933		goto cmd_init_failed3;
1934	}
1935
1936	spin_lock_init(&ctrl->ack_lock);
1937	spin_lock_init(&ctrl->state_lock);
1938	spin_lock_init(&ctrl->io_lock);
1939
1940	ctrl->extlen = sizeof(struct vfe_frame_extra);
1941
1942	spin_lock_init(&ctrl->tasklet_lock);
1943	INIT_LIST_HEAD(&ctrl->tasklet_q);
1944
1945	ctrl->syncdata = sdata;
1946	return 0;
1947
1948cmd_init_failed3:
1949	disable_irq(ctrl->vfeirq);
1950	free_irq(ctrl->vfeirq, 0);
1951	iounmap(ctrl->vfebase);
1952cmd_init_failed2:
1953	kfree(ctrl);
1954cmd_init_failed1:
1955	release_mem_region(vfemem->start, (vfemem->end - vfemem->start) + 1);
1956	return rc;
1957}
1958
1959void vfe_cmd_release(struct platform_device *dev)
1960{
1961	struct resource	*mem;
1962
1963	disable_irq(ctrl->vfeirq);
1964	free_irq(ctrl->vfeirq, 0);
1965
1966	iounmap(ctrl->vfebase);
1967	mem = platform_get_resource(dev, IORESOURCE_MEM, 0);
1968	release_mem_region(mem->start, (mem->end - mem->start) + 1);
1969
1970	ctrl->extlen = 0;
1971
1972	kfree(ctrl->extdata);
1973	kfree(ctrl);
1974}
1975
1976void vfe_stats_af_stop(void)
1977{
1978	ctrl->vfeStatsCmdLocal.autoFocusEnable = FALSE;
1979	ctrl->vfeImaskLocal.afPingpongIrq = FALSE;
1980}
1981
1982void vfe_stop(void)
1983{
1984	boolean vfeAxiBusy;
1985	uint32_t vfeAxiStauts;
1986
1987	/* for reset hw modules, and send msg when reset_irq comes.*/
1988	ctrl->vfeStopAckPending = TRUE;
1989
1990	ctrl->vfeStatsPingPongReloadFlag = FALSE;
1991	vfe_pm_stop();
1992
1993	/* disable all interrupts.  */
1994	vfe_program_irq_mask(VFE_DISABLE_ALL_IRQS);
1995
1996	/* in either continuous or snapshot mode, stop command can be issued
1997	 * at any time.
1998	 */
1999	vfe_camif_stop_immediately();
2000	vfe_program_axi_cmd(AXI_HALT);
2001	vfe_prog_hw_testgen_cmd(VFE_TEST_GEN_STOP);
2002
2003	vfeAxiBusy = TRUE;
2004
2005	while (vfeAxiBusy) {
2006		vfeAxiStauts = vfe_read_axi_status();
2007		if ((vfeAxiStauts & AXI_STATUS_BUSY_MASK) != 0)
2008			vfeAxiBusy = FALSE;
2009	}
2010
2011	vfe_program_axi_cmd(AXI_HALT_CLEAR);
2012
2013	/* clear all pending interrupts */
2014	writel(VFE_CLEAR_ALL_IRQS, ctrl->vfebase + VFE_IRQ_CLEAR);
2015
2016	/* enable reset_ack and async timer interrupt only while stopping
2017	 * the pipeline.
2018	 */
2019	vfe_program_irq_mask(VFE_IMASK_WHILE_STOPPING);
2020
2021	vfe_program_global_reset_cmd(VFE_RESET_UPON_STOP_CMD);
2022}
2023
2024void vfe_update(void)
2025{
2026	ctrl->vfeModuleEnableLocal.statsEnable =
2027		ctrl->vfeStatsCmdLocal.autoFocusEnable |
2028		ctrl->vfeStatsCmdLocal.axwEnable;
2029
2030	vfe_reg_module_cfg(&ctrl->vfeModuleEnableLocal);
2031
2032	vfe_program_stats_cmd(&ctrl->vfeStatsCmdLocal);
2033
2034	ctrl->vfeImaskPacked = vfe_irq_pack(ctrl->vfeImaskLocal);
2035	vfe_program_irq_mask(ctrl->vfeImaskPacked);
2036
2037	if ((ctrl->vfeModuleEnableLocal.statsEnable == TRUE) &&
2038			(ctrl->vfeStatsPingPongReloadFlag == FALSE)) {
2039		ctrl->vfeStatsPingPongReloadFlag = TRUE;
2040
2041		ctrl->vfeBusCmdLocal.statsPingpongReload = TRUE;
2042		vfe_reg_bus_cmd(&ctrl->vfeBusCmdLocal);
2043	}
2044
2045	vfe_program_reg_update_cmd(VFE_REG_UPDATE_TRIGGER);
2046}
2047
2048int vfe_rgb_gamma_update(struct vfe_cmd_rgb_gamma_config *in)
2049{
2050	int rc = 0;
2051
2052	ctrl->vfeModuleEnableLocal.rgbLUTEnable = in->enable;
2053
2054	switch (in->channelSelect) {
2055	case RGB_GAMMA_CH0_SELECTED:
2056		ctrl->vfeGammaLutSel.ch0BankSelect ^= 1;
2057		vfe_write_gamma_table(0,
2058			ctrl->vfeGammaLutSel.ch0BankSelect, in->table);
2059		break;
2060
2061	case RGB_GAMMA_CH1_SELECTED:
2062		ctrl->vfeGammaLutSel.ch1BankSelect ^= 1;
2063		vfe_write_gamma_table(1,
2064			ctrl->vfeGammaLutSel.ch1BankSelect, in->table);
2065		break;
2066
2067	case RGB_GAMMA_CH2_SELECTED:
2068		ctrl->vfeGammaLutSel.ch2BankSelect ^= 1;
2069		vfe_write_gamma_table(2,
2070			ctrl->vfeGammaLutSel.ch2BankSelect, in->table);
2071		break;
2072
2073	case RGB_GAMMA_CH0_CH1_SELECTED:
2074		ctrl->vfeGammaLutSel.ch0BankSelect ^= 1;
2075		ctrl->vfeGammaLutSel.ch1BankSelect ^= 1;
2076		vfe_write_gamma_table(0, ctrl->vfeGammaLutSel.ch0BankSelect,
2077			in->table);
2078		vfe_write_gamma_table(1, ctrl->vfeGammaLutSel.ch1BankSelect,
2079			in->table);
2080		break;
2081
2082	case RGB_GAMMA_CH0_CH2_SELECTED:
2083		ctrl->vfeGammaLutSel.ch0BankSelect ^= 1;
2084		ctrl->vfeGammaLutSel.ch2BankSelect ^= 1;
2085		vfe_write_gamma_table(0, ctrl->vfeGammaLutSel.ch0BankSelect,
2086			in->table);
2087		vfe_write_gamma_table(2, ctrl->vfeGammaLutSel.ch2BankSelect,
2088			in->table);
2089		break;
2090
2091	case RGB_GAMMA_CH1_CH2_SELECTED:
2092		ctrl->vfeGammaLutSel.ch1BankSelect ^= 1;
2093		ctrl->vfeGammaLutSel.ch2BankSelect ^= 1;
2094		vfe_write_gamma_table(1, ctrl->vfeGammaLutSel.ch1BankSelect,
2095			in->table);
2096		vfe_write_gamma_table(2, ctrl->vfeGammaLutSel.ch2BankSelect,
2097			in->table);
2098		break;
2099
2100	case RGB_GAMMA_CH0_CH1_CH2_SELECTED:
2101		ctrl->vfeGammaLutSel.ch0BankSelect ^= 1;
2102		ctrl->vfeGammaLutSel.ch1BankSelect ^= 1;
2103		ctrl->vfeGammaLutSel.ch2BankSelect ^= 1;
2104		vfe_write_gamma_table(0, ctrl->vfeGammaLutSel.ch0BankSelect,
2105			in->table);
2106		vfe_write_gamma_table(1, ctrl->vfeGammaLutSel.ch1BankSelect,
2107			in->table);
2108		vfe_write_gamma_table(2, ctrl->vfeGammaLutSel.ch2BankSelect,
2109			in->table);
2110		break;
2111
2112	default:
2113		return -EINVAL;
2114	} /* switch */
2115
2116	/* update the gammaLutSel register. */
2117	vfe_program_lut_bank_sel(&ctrl->vfeGammaLutSel);
2118
2119	return rc;
2120}
2121
2122int vfe_rgb_gamma_config(struct vfe_cmd_rgb_gamma_config *in)
2123{
2124	int rc = 0;
2125
2126	ctrl->vfeModuleEnableLocal.rgbLUTEnable = in->enable;
2127
2128	switch (in->channelSelect) {
2129	case RGB_GAMMA_CH0_SELECTED:
2130vfe_write_gamma_table(0, 0, in->table);
2131break;
2132
2133	case RGB_GAMMA_CH1_SELECTED:
2134		vfe_write_gamma_table(1, 0, in->table);
2135		break;
2136
2137	case RGB_GAMMA_CH2_SELECTED:
2138		vfe_write_gamma_table(2, 0, in->table);
2139		break;
2140
2141	case RGB_GAMMA_CH0_CH1_SELECTED:
2142		vfe_write_gamma_table(0, 0, in->table);
2143		vfe_write_gamma_table(1, 0, in->table);
2144		break;
2145
2146	case RGB_GAMMA_CH0_CH2_SELECTED:
2147		vfe_write_gamma_table(0, 0, in->table);
2148		vfe_write_gamma_table(2, 0, in->table);
2149		break;
2150
2151	case RGB_GAMMA_CH1_CH2_SELECTED:
2152		vfe_write_gamma_table(1, 0, in->table);
2153		vfe_write_gamma_table(2, 0, in->table);
2154		break;
2155
2156	case RGB_GAMMA_CH0_CH1_CH2_SELECTED:
2157		vfe_write_gamma_table(0, 0, in->table);
2158		vfe_write_gamma_table(1, 0, in->table);
2159		vfe_write_gamma_table(2, 0, in->table);
2160		break;
2161
2162	default:
2163		rc = -EINVAL;
2164		break;
2165	} /* switch */
2166
2167	return rc;
2168}
2169
2170void vfe_stats_af_ack(struct vfe_cmd_stats_af_ack *in)
2171{
2172	ctrl->afStatsControl.nextFrameAddrBuf = in->nextAFOutputBufferAddr;
2173	ctrl->afStatsControl.ackPending = FALSE;
2174}
2175
2176void vfe_stats_wb_exp_ack(struct vfe_cmd_stats_wb_exp_ack *in)
2177{
2178	ctrl->awbStatsControl.nextFrameAddrBuf = in->nextWbExpOutputBufferAddr;
2179	ctrl->awbStatsControl.ackPending = FALSE;
2180}
2181
2182void vfe_output2_ack(struct vfe_cmd_output_ack *in)
2183{
2184	const uint32_t *psrc;
2185	uint32_t *pdest;
2186	uint8_t i;
2187
2188	pdest = ctrl->encPath.nextFrameAddrBuf;
2189
2190	CDBG("output2_ack: ack addr = 0x%x\n", in->ybufaddr[0]);
2191
2192	psrc = in->ybufaddr;
2193	for (i = 0; i < ctrl->encPath.fragCount; i++)
2194		*pdest++ = *psrc++;
2195
2196	psrc = in->chromabufaddr;
2197	for (i = 0; i < ctrl->encPath.fragCount; i++)
2198		*pdest++ = *psrc++;
2199
2200	ctrl->encPath.ackPending = FALSE;
2201}
2202
2203void vfe_output1_ack(struct vfe_cmd_output_ack *in)
2204{
2205	const uint32_t *psrc;
2206	uint32_t *pdest;
2207	uint8_t i;
2208
2209	pdest = ctrl->viewPath.nextFrameAddrBuf;
2210
2211	psrc = in->ybufaddr;
2212	for (i = 0; i < ctrl->viewPath.fragCount; i++)
2213		*pdest++ = *psrc++;
2214
2215	psrc = in->chromabufaddr;
2216	for (i = 0; i < ctrl->viewPath.fragCount; i++)
2217		*pdest++ = *psrc++;
2218
2219	ctrl->viewPath.ackPending = FALSE;
2220}
2221
2222void vfe_start(struct vfe_cmd_start *in)
2223{
2224	unsigned long flags;
2225	uint32_t  pmstatus = 0;
2226	boolean rawmode;
2227	uint32_t  demperiod = 0;
2228	uint32_t  demeven = 0;
2229	uint32_t  demodd = 0;
2230
2231	/* derived from other commands.  (camif config, axi output config,
2232	 * etc)
2233	*/
2234	struct vfe_cfg hwcfg;
2235	struct vfe_upsample_cfg chromupcfg;
2236
2237	CDBG("vfe_start operationMode = %d\n", in->operationMode);
2238
2239	memset(&hwcfg, 0, sizeof(hwcfg));
2240	memset(&chromupcfg, 0, sizeof(chromupcfg));
2241
2242	switch (in->pixel) {
2243	case VFE_BAYER_RGRGRG:
2244		demperiod = 1;
2245		demeven = 0xC9;
2246		demodd = 0xAC;
2247		break;
2248
2249	case VFE_BAYER_GRGRGR:
2250		demperiod = 1;
2251		demeven = 0x9C;
2252		demodd = 0xCA;
2253		break;
2254
2255	case VFE_BAYER_BGBGBG:
2256		demperiod = 1;
2257		demeven = 0xCA;
2258		demodd = 0x9C;
2259		break;
2260
2261	case VFE_BAYER_GBGBGB:
2262		demperiod = 1;
2263		demeven = 0xAC;
2264		demodd = 0xC9;
2265		break;
2266
2267	case VFE_YUV_YCbYCr:
2268		demperiod = 3;
2269		demeven = 0x9CAC;
2270		demodd = 0x9CAC;
2271		break;
2272
2273	case VFE_YUV_YCrYCb:
2274		demperiod = 3;
2275		demeven = 0xAC9C;
2276		demodd = 0xAC9C;
2277		break;
2278
2279	case VFE_YUV_CbYCrY:
2280		demperiod = 3;
2281		demeven = 0xC9CA;
2282		demodd = 0xC9CA;
2283		break;
2284
2285	case VFE_YUV_CrYCbY:
2286		demperiod = 3;
2287		demeven = 0xCAC9;
2288		demodd = 0xCAC9;
2289		break;
2290
2291	default:
2292		return;
2293	}
2294
2295	vfe_config_demux(demperiod, demeven, demodd);
2296
2297	vfe_program_lut_bank_sel(&ctrl->vfeGammaLutSel);
2298
2299	/* save variables to local. */
2300	ctrl->vfeOperationMode = in->operationMode;
2301	if (ctrl->vfeOperationMode ==
2302			VFE_START_OPERATION_MODE_SNAPSHOT) {
2303		/* in snapshot mode, initialize snapshot count*/
2304		ctrl->vfeSnapShotCount = in->snapshotCount;
2305
2306		/* save the requested count, this is temporarily done, to
2307		help with HJR / multishot. */
2308		ctrl->vfeRequestedSnapShotCount = ctrl->vfeSnapShotCount;
2309
2310		CDBG("requested snapshot count = %d\n", ctrl->vfeSnapShotCount);
2311
2312		/* Assumption is to have the same pattern and period for both
2313		paths, if both paths are used. */
2314		if (ctrl->viewPath.pathEnabled) {
2315			ctrl->viewPath.snapshotPendingCount =
2316				in->snapshotCount;
2317
2318			ctrl->vfeFrameSkipPattern =
2319				ctrl->vfeFrameSkip.output1Pattern;
2320			ctrl->vfeFrameSkipPeriod =
2321				ctrl->vfeFrameSkip.output1Period;
2322		}
2323
2324		if (ctrl->encPath.pathEnabled) {
2325			ctrl->encPath.snapshotPendingCount =
2326				in->snapshotCount;
2327
2328			ctrl->vfeFrameSkipPattern =
2329				ctrl->vfeFrameSkip.output2Pattern;
2330			ctrl->vfeFrameSkipPeriod =
2331				ctrl->vfeFrameSkip.output2Period;
2332		}
2333	}
2334
2335	/* enable color conversion for bayer sensor
2336	if stats enabled, need to do color conversion. */
2337	if (in->pixel <= VFE_BAYER_GBGBGB)
2338		ctrl->vfeStatsCmdLocal.colorConversionEnable = TRUE;
2339
2340	vfe_program_stats_cmd(&ctrl->vfeStatsCmdLocal);
2341
2342	if (in->pixel >= VFE_YUV_YCbYCr)
2343		ctrl->vfeModuleEnableLocal.chromaUpsampleEnable = TRUE;
2344
2345	ctrl->vfeModuleEnableLocal.demuxEnable = TRUE;
2346
2347	/* if any stats module is enabled, the main bit is enabled. */
2348	ctrl->vfeModuleEnableLocal.statsEnable =
2349		ctrl->vfeStatsCmdLocal.autoFocusEnable |
2350		ctrl->vfeStatsCmdLocal.axwEnable;
2351
2352	vfe_reg_module_cfg(&ctrl->vfeModuleEnableLocal);
2353
2354	/* in case of offline processing, do not need to config camif. Having
2355	 * bus output enabled in camif_config register might confuse the
2356	 * hardware?
2357	 */
2358	if (in->inputSource != VFE_START_INPUT_SOURCE_AXI) {
2359		vfe_reg_camif_config(&ctrl->vfeCamifConfigLocal);
2360	} else {
2361		/* offline processing, enable axi read */
2362		ctrl->vfeBusConfigLocal.stripeRdPathEn = TRUE;
2363		ctrl->vfeBusCmdLocal.stripeReload = TRUE;
2364		ctrl->vfeBusConfigLocal.rawPixelDataSize =
2365			ctrl->axiInputDataSize;
2366	}
2367
2368	vfe_reg_bus_cfg(&ctrl->vfeBusConfigLocal);
2369
2370	/* directly from start command */
2371	hwcfg.pixelPattern = in->pixel;
2372	hwcfg.inputSource = in->inputSource;
2373	writel(*(uint32_t *)&hwcfg, ctrl->vfebase + VFE_CFG);
2374
2375	/* regardless module enabled or not, it does not hurt
2376	 * to program the cositing mode. */
2377	chromupcfg.chromaCositingForYCbCrInputs =
2378		in->yuvInputCositingMode;
2379
2380	writel(*(uint32_t *)&(chromupcfg),
2381		ctrl->vfebase + VFE_CHROMA_UPSAMPLE_CFG);
2382
2383	/* MISR to monitor the axi read. */
2384	writel(0xd8, ctrl->vfebase + VFE_BUS_MISR_MAST_CFG_0);
2385
2386	/* clear all pending interrupts. */
2387	writel(VFE_CLEAR_ALL_IRQS, ctrl->vfebase + VFE_IRQ_CLEAR);
2388
2389	/*  define how composite interrupt work.  */
2390	ctrl->vfeImaskCompositePacked =
2391		vfe_irq_composite_pack(ctrl->vfeIrqCompositeMaskLocal);
2392
2393	vfe_program_irq_composite_mask(ctrl->vfeImaskCompositePacked);
2394
2395	/*  enable all necessary interrupts.      */
2396	ctrl->vfeImaskLocal.camifSofIrq  = TRUE;
2397	ctrl->vfeImaskLocal.regUpdateIrq = TRUE;
2398	ctrl->vfeImaskLocal.resetAckIrq  = TRUE;
2399
2400	ctrl->vfeImaskPacked = vfe_irq_pack(ctrl->vfeImaskLocal);
2401	vfe_program_irq_mask(ctrl->vfeImaskPacked);
2402
2403	/* enable bus performance monitor */
2404	vfe_8k_pm_start(&ctrl->vfeBusPmConfigLocal);
2405
2406	/* trigger vfe reg update */
2407	ctrl->vfeStartAckPendingFlag = TRUE;
2408
2409	/* write bus command to trigger reload of ping pong buffer. */
2410	ctrl->vfeBusCmdLocal.busPingpongReload = TRUE;
2411
2412	if (ctrl->vfeModuleEnableLocal.statsEnable == TRUE) {
2413		ctrl->vfeBusCmdLocal.statsPingpongReload = TRUE;
2414		ctrl->vfeStatsPingPongReloadFlag = TRUE;
2415	}
2416
2417	writel(VFE_REG_UPDATE_TRIGGER,
2418		ctrl->vfebase + VFE_REG_UPDATE_CMD);
2419
2420	/* program later than the reg update. */
2421	vfe_reg_bus_cmd(&ctrl->vfeBusCmdLocal);
2422
2423	if ((in->inputSource ==
2424			 VFE_START_INPUT_SOURCE_CAMIF) ||
2425			(in->inputSource ==
2426			 VFE_START_INPUT_SOURCE_TESTGEN))
2427		writel(CAMIF_COMMAND_START, ctrl->vfebase + CAMIF_COMMAND);
2428
2429	/* start test gen if it is enabled */
2430	if (ctrl->vfeTestGenStartFlag == TRUE) {
2431		ctrl->vfeTestGenStartFlag = FALSE;
2432		vfe_prog_hw_testgen_cmd(VFE_TEST_GEN_GO);
2433	}
2434
2435	CDBG("ctrl->axiOutputMode = %d\n", ctrl->axiOutputMode);
2436	if (ctrl->axiOutputMode == VFE_AXI_OUTPUT_MODE_CAMIFToAXIViaOutput2) {
2437		/* raw dump mode */
2438		rawmode = TRUE;
2439
2440		while (rawmode) {
2441			pmstatus =
2442				readl(ctrl->vfebase +
2443					VFE_BUS_ENC_CBCR_WR_PM_STATS_1);
2444
2445			if ((pmstatus & VFE_PM_BUF_MAX_CNT_MASK) != 0)
2446				rawmode = FALSE;
2447		}
2448
2449		vfe_send_msg_no_payload(VFE_MSG_ID_START_ACK);
2450		ctrl->vfeStartAckPendingFlag = FALSE;
2451	}
2452
2453	spin_lock_irqsave(&ctrl->state_lock, flags);
2454	ctrl->vstate = VFE_STATE_ACTIVE;
2455	spin_unlock_irqrestore(&ctrl->state_lock, flags);
2456}
2457
2458void vfe_la_update(struct vfe_cmd_la_config *in)
2459{
2460	int16_t *pTable;
2461	enum VFE_DMI_RAM_SEL dmiRamSel;
2462	int i;
2463
2464	pTable = in->table;
2465	ctrl->vfeModuleEnableLocal.lumaAdaptationEnable = in->enable;
2466
2467	/* toggle the bank to be used. */
2468	ctrl->vfeLaBankSel ^= 1;
2469
2470	if (ctrl->vfeLaBankSel == 0)
2471		dmiRamSel = LUMA_ADAPT_LUT_RAM_BANK0;
2472	else
2473		dmiRamSel = LUMA_ADAPT_LUT_RAM_BANK1;
2474
2475	/* configure the DMI_CFG to select right sram */
2476	vfe_program_dmi_cfg(dmiRamSel);
2477
2478	for (i = 0; i < VFE_LA_TABLE_LENGTH; i++) {
2479		writel((uint32_t)(*pTable), ctrl->vfebase + VFE_DMI_DATA_LO);
2480		pTable++;
2481	}
2482
2483	/* After DMI transfer, to make it safe, need to set
2484	 * the DMI_CFG to unselect any SRAM */
2485	writel(VFE_DMI_CFG_DEFAULT, ctrl->vfebase + VFE_DMI_CFG);
2486	writel(ctrl->vfeLaBankSel, ctrl->vfebase + VFE_LA_CFG);
2487}
2488
2489void vfe_la_config(struct vfe_cmd_la_config *in)
2490{
2491	uint16_t i;
2492	int16_t  *pTable;
2493	enum VFE_DMI_RAM_SEL dmiRamSel;
2494
2495	pTable = in->table;
2496	ctrl->vfeModuleEnableLocal.lumaAdaptationEnable = in->enable;
2497
2498	if (ctrl->vfeLaBankSel == 0)
2499		dmiRamSel = LUMA_ADAPT_LUT_RAM_BANK0;
2500	else
2501		dmiRamSel = LUMA_ADAPT_LUT_RAM_BANK1;
2502
2503	/* configure the DMI_CFG to select right sram */
2504	vfe_program_dmi_cfg(dmiRamSel);
2505
2506	for (i = 0; i < VFE_LA_TABLE_LENGTH; i++) {
2507		writel((uint32_t)(*pTable), ctrl->vfebase + VFE_DMI_DATA_LO);
2508		pTable++;
2509	}
2510
2511	/* After DMI transfer, to make it safe, need to set the
2512	 * DMI_CFG to unselect any SRAM */
2513	writel(VFE_DMI_CFG_DEFAULT, ctrl->vfebase + VFE_DMI_CFG);
2514
2515	/* can only be bank 0 or bank 1 for now. */
2516	writel(ctrl->vfeLaBankSel, ctrl->vfebase + VFE_LA_CFG);
2517	CDBG("VFE Luma adaptation bank selection is 0x%x\n",
2518			 *(uint32_t *)&ctrl->vfeLaBankSel);
2519}
2520
2521void vfe_test_gen_start(struct vfe_cmd_test_gen_start *in)
2522{
2523	struct VFE_TestGen_ConfigCmdType cmd;
2524
2525	memset(&cmd, 0, sizeof(cmd));
2526
2527	cmd.numFrame              = in->numFrame;
2528	cmd.pixelDataSelect       = in->pixelDataSelect;
2529	cmd.systematicDataSelect  = in->systematicDataSelect;
2530	cmd.pixelDataSize         = (uint32_t)in->pixelDataSize;
2531	cmd.hsyncEdge             = (uint32_t)in->hsyncEdge;
2532	cmd.vsyncEdge             = (uint32_t)in->vsyncEdge;
2533	cmd.imageWidth            = in->imageWidth;
2534	cmd.imageHeight           = in->imageHeight;
2535	cmd.sofOffset             = in->startOfFrameOffset;
2536	cmd.eofNOffset            = in->endOfFrameNOffset;
2537	cmd.solOffset             = in->startOfLineOffset;
2538	cmd.eolNOffset            = in->endOfLineNOffset;
2539	cmd.hBlankInterval        = in->hbi;
2540	cmd.vBlankInterval        = in->vbl;
2541	cmd.vBlankIntervalEnable  = in->vblEnable;
2542	cmd.sofDummy              = in->startOfFrameDummyLine;
2543	cmd.eofDummy              = in->endOfFrameDummyLine;
2544	cmd.unicolorBarSelect     = in->unicolorBarSelect;
2545	cmd.unicolorBarEnable     = in->unicolorBarEnable;
2546	cmd.splitEnable           = in->colorBarsSplitEnable;
2547	cmd.pixelPattern          = (uint32_t)in->colorBarsPixelPattern;
2548	cmd.rotatePeriod          = in->colorBarsRotatePeriod;
2549	cmd.randomSeed            = in->testGenRandomSeed;
2550
2551	vfe_prog_hw(ctrl->vfebase + VFE_HW_TESTGEN_CFG,
2552		(uint32_t *) &cmd, sizeof(cmd));
2553}
2554
2555void vfe_frame_skip_update(struct vfe_cmd_frame_skip_update *in)
2556{
2557	struct VFE_FRAME_SKIP_UpdateCmdType cmd;
2558
2559	cmd.yPattern    = in->output1Pattern;
2560	cmd.cbcrPattern = in->output1Pattern;
2561	vfe_prog_hw(ctrl->vfebase + VFE_FRAMEDROP_VIEW_Y_PATTERN,
2562		(uint32_t *)&cmd, sizeof(cmd));
2563
2564	cmd.yPattern    = in->output2Pattern;
2565	cmd.cbcrPattern = in->output2Pattern;
2566	vfe_prog_hw(ctrl->vfebase + VFE_FRAMEDROP_ENC_Y_PATTERN,
2567		(uint32_t *)&cmd, sizeof(cmd));
2568}
2569
2570void vfe_frame_skip_config(struct vfe_cmd_frame_skip_config *in)
2571{
2572	struct vfe_frame_skip_cfg cmd;
2573	memset(&cmd, 0, sizeof(cmd));
2574
2575	ctrl->vfeFrameSkip = *in;
2576
2577	cmd.output2YPeriod     = in->output2Period;
2578	cmd.output2CbCrPeriod  = in->output2Period;
2579	cmd.output2YPattern    = in->output2Pattern;
2580	cmd.output2CbCrPattern = in->output2Pattern;
2581	cmd.output1YPeriod     = in->output1Period;
2582	cmd.output1CbCrPeriod  = in->output1Period;
2583	cmd.output1YPattern    = in->output1Pattern;
2584	cmd.output1CbCrPattern = in->output1Pattern;
2585
2586	vfe_prog_hw(ctrl->vfebase + VFE_FRAMEDROP_ENC_Y_CFG,
2587		(uint32_t *)&cmd, sizeof(cmd));
2588}
2589
2590void vfe_output_clamp_config(struct vfe_cmd_output_clamp_config *in)
2591{
2592	struct vfe_output_clamp_cfg cmd;
2593	memset(&cmd, 0, sizeof(cmd));
2594
2595	cmd.yChanMax  = in->maxCh0;
2596	cmd.cbChanMax = in->maxCh1;
2597	cmd.crChanMax = in->maxCh2;
2598
2599	cmd.yChanMin  = in->minCh0;
2600	cmd.cbChanMin = in->minCh1;
2601	cmd.crChanMin = in->minCh2;
2602
2603	vfe_prog_hw(ctrl->vfebase + VFE_CLAMP_MAX_CFG, (uint32_t *)&cmd,
2604		sizeof(cmd));
2605}
2606
2607void vfe_camif_frame_update(struct vfe_cmds_camif_frame *in)
2608{
2609	struct vfe_camifframe_update cmd;
2610
2611	memset(&cmd, 0, sizeof(cmd));
2612
2613	cmd.pixelsPerLine = in->pixelsPerLine;
2614	cmd.linesPerFrame = in->linesPerFrame;
2615
2616	vfe_prog_hw(ctrl->vfebase + CAMIF_FRAME_CONFIG, (uint32_t *)&cmd,
2617		sizeof(cmd));
2618}
2619
2620void vfe_color_correction_config(
2621	struct vfe_cmd_color_correction_config *in)
2622{
2623	struct vfe_color_correction_cfg cmd;
2624
2625	memset(&cmd, 0, sizeof(cmd));
2626	ctrl->vfeModuleEnableLocal.colorCorrectionEnable = in->enable;
2627
2628	cmd.c0 = in->C0;
2629	cmd.c1 = in->C1;
2630	cmd.c2 = in->C2;
2631	cmd.c3 = in->C3;
2632	cmd.c4 = in->C4;
2633	cmd.c5 = in->C5;
2634	cmd.c6 = in->C6;
2635	cmd.c7 = in->C7;
2636	cmd.c8 = in->C8;
2637
2638	cmd.k0 = in->K0;
2639	cmd.k1 = in->K1;
2640	cmd.k2 = in->K2;
2641
2642	cmd.coefQFactor = in->coefQFactor;
2643
2644	vfe_prog_hw(ctrl->vfebase + VFE_COLOR_CORRECT_COEFF_0,
2645		(uint32_t *)&cmd, sizeof(cmd));
2646}
2647
2648void vfe_demosaic_abf_update(struct vfe_cmd_demosaic_abf_update *in)
2649{
2650struct vfe_demosaic_cfg cmd;
2651	struct vfe_demosaic_abf_cfg cmdabf;
2652	uint32_t temp;
2653
2654	memset(&cmd, 0, sizeof(cmd));
2655	temp = readl(ctrl->vfebase + VFE_DEMOSAIC_CFG);
2656
2657	cmd = *((struct vfe_demosaic_cfg *)(&temp));
2658	cmd.abfEnable       = in->abfUpdate.enable;
2659	cmd.forceAbfOn      = in->abfUpdate.forceOn;
2660	cmd.abfShift        = in->abfUpdate.shift;
2661	vfe_prog_hw(ctrl->vfebase + VFE_DEMOSAIC_CFG,
2662		(uint32_t *)&cmd, sizeof(cmd));
2663
2664	cmdabf.lpThreshold  = in->abfUpdate.lpThreshold;
2665	cmdabf.ratio        = in->abfUpdate.ratio;
2666	cmdabf.minValue     = in->abfUpdate.min;
2667	cmdabf.maxValue     = in->abfUpdate.max;
2668	vfe_prog_hw(ctrl->vfebase + VFE_DEMOSAIC_ABF_CFG_0,
2669		(uint32_t *)&cmdabf, sizeof(cmdabf));
2670}
2671
2672void vfe_demosaic_bpc_update(struct vfe_cmd_demosaic_bpc_update *in)
2673{
2674	struct vfe_demosaic_cfg cmd;
2675	struct vfe_demosaic_bpc_cfg cmdbpc;
2676	uint32_t temp;
2677
2678	memset(&cmd, 0, sizeof(cmd));
2679
2680	temp = readl(ctrl->vfebase + VFE_DEMOSAIC_CFG);
2681
2682	cmd = *((struct vfe_demosaic_cfg *)(&temp));
2683	cmd.badPixelCorrEnable = in->bpcUpdate.enable;
2684	cmd.fminThreshold      = in->bpcUpdate.fminThreshold;
2685	cmd.fmaxThreshold      = in->bpcUpdate.fmaxThreshold;
2686
2687	vfe_prog_hw(ctrl->vfebase + VFE_DEMOSAIC_CFG,
2688		(uint32_t *)&cmd, sizeof(cmd));
2689
2690	cmdbpc.blueDiffThreshold  = in->bpcUpdate.blueDiffThreshold;
2691	cmdbpc.redDiffThreshold   = in->bpcUpdate.redDiffThreshold;
2692	cmdbpc.greenDiffThreshold = in->bpcUpdate.greenDiffThreshold;
2693
2694	vfe_prog_hw(ctrl->vfebase + VFE_DEMOSAIC_BPC_CFG_0,
2695		(uint32_t *)&cmdbpc, sizeof(cmdbpc));
2696}
2697
2698void vfe_demosaic_config(struct vfe_cmd_demosaic_config *in)
2699{
2700	struct vfe_demosaic_cfg cmd;
2701	struct vfe_demosaic_bpc_cfg cmd_bpc;
2702	struct vfe_demosaic_abf_cfg cmd_abf;
2703
2704	memset(&cmd, 0, sizeof(cmd));
2705	memset(&cmd_bpc, 0, sizeof(cmd_bpc));
2706	memset(&cmd_abf, 0, sizeof(cmd_abf));
2707
2708	ctrl->vfeModuleEnableLocal.demosaicEnable = in->enable;
2709
2710	cmd.abfEnable          = in->abfConfig.enable;
2711	cmd.badPixelCorrEnable = in->bpcConfig.enable;
2712	cmd.forceAbfOn         = in->abfConfig.forceOn;
2713	cmd.abfShift           = in->abfConfig.shift;
2714	cmd.fminThreshold      = in->bpcConfig.fminThreshold;
2715	cmd.fmaxThreshold      = in->bpcConfig.fmaxThreshold;
2716	cmd.slopeShift         = in->slopeShift;
2717
2718	vfe_prog_hw(ctrl->vfebase + VFE_DEMOSAIC_CFG,
2719		(uint32_t *)&cmd, sizeof(cmd));
2720
2721	cmd_abf.lpThreshold = in->abfConfig.lpThreshold;
2722	cmd_abf.ratio       = in->abfConfig.ratio;
2723	cmd_abf.minValue    = in->abfConfig.min;
2724	cmd_abf.maxValue    = in->abfConfig.max;
2725
2726	vfe_prog_hw(ctrl->vfebase + VFE_DEMOSAIC_ABF_CFG_0,
2727		(uint32_t *)&cmd_abf, sizeof(cmd_abf));
2728
2729	cmd_bpc.blueDiffThreshold   = in->bpcConfig.blueDiffThreshold;
2730	cmd_bpc.redDiffThreshold    = in->bpcConfig.redDiffThreshold;
2731	cmd_bpc.greenDiffThreshold  = in->bpcConfig.greenDiffThreshold;
2732
2733	vfe_prog_hw(ctrl->vfebase + VFE_DEMOSAIC_BPC_CFG_0,
2734		(uint32_t *)&cmd_bpc, sizeof(cmd_bpc));
2735}
2736
2737void vfe_demux_channel_gain_update(
2738	struct vfe_cmd_demux_channel_gain_config *in)
2739{
2740	struct vfe_demux_cfg cmd;
2741
2742	memset(&cmd, 0, sizeof(cmd));
2743
2744	cmd.ch0EvenGain  = in->ch0EvenGain;
2745	cmd.ch0OddGain   = in->ch0OddGain;
2746	cmd.ch1Gain      = in->ch1Gain;
2747	cmd.ch2Gain      = in->ch2Gain;
2748
2749	vfe_prog_hw(ctrl->vfebase + VFE_DEMUX_GAIN_0,
2750		(uint32_t *)&cmd, sizeof(cmd));
2751}
2752
2753void vfe_demux_channel_gain_config(
2754	struct vfe_cmd_demux_channel_gain_config *in)
2755{
2756	struct vfe_demux_cfg cmd;
2757
2758	memset(&cmd, 0, sizeof(cmd));
2759
2760	cmd.ch0EvenGain = in->ch0EvenGain;
2761	cmd.ch0OddGain  = in->ch0OddGain;
2762	cmd.ch1Gain     = in->ch1Gain;
2763	cmd.ch2Gain     = in->ch2Gain;
2764
2765	vfe_prog_hw(ctrl->vfebase + VFE_DEMUX_GAIN_0,
2766		(uint32_t *)&cmd, sizeof(cmd));
2767}
2768
2769void vfe_black_level_update(struct vfe_cmd_black_level_config *in)
2770{
2771	struct vfe_blacklevel_cfg cmd;
2772
2773	memset(&cmd, 0, sizeof(cmd));
2774	ctrl->vfeModuleEnableLocal.blackLevelCorrectionEnable = in->enable;
2775
2776	cmd.evenEvenAdjustment = in->evenEvenAdjustment;
2777	cmd.evenOddAdjustment  = in->evenOddAdjustment;
2778	cmd.oddEvenAdjustment  = in->oddEvenAdjustment;
2779	cmd.oddOddAdjustment   = in->oddOddAdjustment;
2780
2781	vfe_prog_hw(ctrl->vfebase + VFE_BLACK_EVEN_EVEN_VALUE,
2782		(uint32_t *)&cmd, sizeof(cmd));
2783}
2784
2785void vfe_black_level_config(struct vfe_cmd_black_level_config *in)
2786{
2787	struct vfe_blacklevel_cfg cmd;
2788	memset(&cmd, 0, sizeof(cmd));
2789
2790	ctrl->vfeModuleEnableLocal.blackLevelCorrectionEnable = in->enable;
2791
2792	cmd.evenEvenAdjustment = in->evenEvenAdjustment;
2793	cmd.evenOddAdjustment  = in->evenOddAdjustment;
2794	cmd.oddEvenAdjustment  = in->oddEvenAdjustment;
2795	cmd.oddOddAdjustment   = in->oddOddAdjustment;
2796
2797	vfe_prog_hw(ctrl->vfebase + VFE_BLACK_EVEN_EVEN_VALUE,
2798		(uint32_t *)&cmd, sizeof(cmd));
2799}
2800
2801void vfe_asf_update(struct vfe_cmd_asf_update *in)
2802{
2803	struct vfe_asf_update cmd;
2804	memset(&cmd, 0, sizeof(cmd));
2805
2806	ctrl->vfeModuleEnableLocal.asfEnable = in->enable;
2807
2808	cmd.smoothEnable     = in->smoothFilterEnabled;
2809	cmd.sharpMode        = in->sharpMode;
2810	cmd.smoothCoeff1     = in->smoothCoefCenter;
2811	cmd.smoothCoeff0     = in->smoothCoefSurr;
2812	cmd.cropEnable       = in->cropEnable;
2813	cmd.sharpThresholdE1 = in->sharpThreshE1;
2814	cmd.sharpDegreeK1    = in->sharpK1;
2815	cmd.sharpDegreeK2    = in->sharpK2;
2816	cmd.normalizeFactor  = in->normalizeFactor;
2817	cmd.sharpThresholdE2 = in->sharpThreshE2;
2818	cmd.sharpThresholdE3 = in->sharpThreshE3;
2819	cmd.sharpThresholdE4 = in->sharpThreshE4;
2820	cmd.sharpThresholdE5 = in->sharpThreshE5;
2821	cmd.F1Coeff0         = in->filter1Coefficients[0];
2822	cmd.F1Coeff1         = in->filter1Coefficients[1];
2823	cmd.F1Coeff2         = in->filter1Coefficients[2];
2824	cmd.F1Coeff3         = in->filter1Coefficients[3];
2825	cmd.F1Coeff4         = in->filter1Coefficients[4];
2826	cmd.F1Coeff5         = in->filter1Coefficients[5];
2827	cmd.F1Coeff6         = in->filter1Coefficients[6];
2828	cmd.F1Coeff7         = in->filter1Coefficients[7];
2829	cmd.F1Coeff8         = in->filter1Coefficients[8];
2830	cmd.F2Coeff0         = in->filter2Coefficients[0];
2831	cmd.F2Coeff1         = in->filter2Coefficients[1];
2832	cmd.F2Coeff2         = in->filter2Coefficients[2];
2833	cmd.F2Coeff3         = in->filter2Coefficients[3];
2834	cmd.F2Coeff4         = in->filter2Coefficients[4];
2835	cmd.F2Coeff5         = in->filter2Coefficients[5];
2836	cmd.F2Coeff6         = in->filter2Coefficients[6];
2837	cmd.F2Coeff7         = in->filter2Coefficients[7];
2838	cmd.F2Coeff8         = in->filter2Coefficients[8];
2839
2840	vfe_prog_hw(ctrl->vfebase + VFE_ASF_CFG,
2841		(uint32_t *)&cmd, sizeof(cmd));
2842}
2843
2844void vfe_asf_config(struct vfe_cmd_asf_config *in)
2845{
2846	struct vfe_asf_update     cmd;
2847	struct vfe_asfcrop_cfg cmd2;
2848
2849	memset(&cmd, 0, sizeof(cmd));
2850	memset(&cmd2, 0, sizeof(cmd2));
2851
2852	ctrl->vfeModuleEnableLocal.asfEnable = in->enable;
2853
2854	cmd.smoothEnable       = in->smoothFilterEnabled;
2855	cmd.sharpMode          = in->sharpMode;
2856	cmd.smoothCoeff0       = in->smoothCoefCenter;
2857	cmd.smoothCoeff1       = in->smoothCoefSurr;
2858	cmd.cropEnable         = in->cropEnable;
2859	cmd.sharpThresholdE1   = in->sharpThreshE1;
2860	cmd.sharpDegreeK1      = in->sharpK1;
2861	cmd.sharpDegreeK2      = in->sharpK2;
2862	cmd.normalizeFactor    = in->normalizeFactor;
2863	cmd.sharpThresholdE2   = in->sharpThreshE2;
2864	cmd.sharpThresholdE3   = in->sharpThreshE3;
2865	cmd.sharpThresholdE4   = in->sharpThreshE4;
2866	cmd.sharpThresholdE5   = in->sharpThreshE5;
2867	cmd.F1Coeff0           = in->filter1Coefficients[0];
2868	cmd.F1Coeff1           = in->filter1Coefficients[1];
2869	cmd.F1Coeff2           = in->filter1Coefficients[2];
2870	cmd.F1Coeff3           = in->filter1Coefficients[3];
2871	cmd.F1Coeff4           = in->filter1Coefficients[4];
2872	cmd.F1Coeff5           = in->filter1Coefficients[5];
2873	cmd.F1Coeff6           = in->filter1Coefficients[6];
2874	cmd.F1Coeff7           = in->filter1Coefficients[7];
2875	cmd.F1Coeff8           = in->filter1Coefficients[8];
2876	cmd.F2Coeff0           = in->filter2Coefficients[0];
2877	cmd.F2Coeff1           = in->filter2Coefficients[1];
2878	cmd.F2Coeff2           = in->filter2Coefficients[2];
2879	cmd.F2Coeff3           = in->filter2Coefficients[3];
2880	cmd.F2Coeff4           = in->filter2Coefficients[4];
2881	cmd.F2Coeff5           = in->filter2Coefficients[5];
2882	cmd.F2Coeff6           = in->filter2Coefficients[6];
2883	cmd.F2Coeff7           = in->filter2Coefficients[7];
2884	cmd.F2Coeff8           = in->filter2Coefficients[8];
2885
2886	vfe_prog_hw(ctrl->vfebase + VFE_ASF_CFG,
2887		(uint32_t *)&cmd, sizeof(cmd));
2888
2889	cmd2.firstLine  = in->cropFirstLine;
2890	cmd2.lastLine   = in->cropLastLine;
2891	cmd2.firstPixel = in->cropFirstPixel;
2892	cmd2.lastPixel  = in->cropLastPixel;
2893
2894	vfe_prog_hw(ctrl->vfebase + VFE_ASF_CROP_WIDTH_CFG,
2895		(uint32_t *)&cmd2, sizeof(cmd2));
2896}
2897
2898void vfe_white_balance_config(struct vfe_cmd_white_balance_config *in)
2899{
2900	struct vfe_wb_cfg cmd;
2901	memset(&cmd, 0, sizeof(cmd));
2902
2903	ctrl->vfeModuleEnableLocal.whiteBalanceEnable =
2904		in->enable;
2905
2906	cmd.ch0Gain = in->ch0Gain;
2907	cmd.ch1Gain = in->ch1Gain;
2908	cmd.ch2Gain = in->ch2Gain;
2909
2910	vfe_prog_hw(ctrl->vfebase + VFE_WB_CFG,
2911		(uint32_t *)&cmd, sizeof(cmd));
2912}
2913
2914void vfe_chroma_sup_config(struct vfe_cmd_chroma_suppression_config *in)
2915{
2916	struct vfe_chroma_suppress_cfg cmd;
2917	memset(&cmd, 0, sizeof(cmd));
2918
2919	ctrl->vfeModuleEnableLocal.chromaSuppressionEnable = in->enable;
2920
2921	cmd.m1  = in->m1;
2922	cmd.m3  = in->m3;
2923	cmd.n1  = in->n1;
2924	cmd.n3  = in->n3;
2925	cmd.mm1 = in->mm1;
2926	cmd.nn1 = in->nn1;
2927
2928	vfe_prog_hw(ctrl->vfebase + VFE_CHROMA_SUPPRESS_CFG_0,
2929		(uint32_t *)&cmd, sizeof(cmd));
2930}
2931
2932void vfe_roll_off_config(struct vfe_cmd_roll_off_config *in)
2933{
2934	struct vfe_rolloff_cfg cmd;
2935	memset(&cmd, 0, sizeof(cmd));
2936
2937	ctrl->vfeModuleEnableLocal.lensRollOffEnable = in->enable;
2938
2939	cmd.gridWidth   = in->gridWidth;
2940	cmd.gridHeight  = in->gridHeight;
2941	cmd.yDelta      = in->yDelta;
2942	cmd.gridX       = in->gridXIndex;
2943	cmd.gridY       = in->gridYIndex;
2944	cmd.pixelX      = in->gridPixelXIndex;
2945	cmd.pixelY      = in->gridPixelYIndex;
2946	cmd.yDeltaAccum = in->yDeltaAccum;
2947
2948	vfe_prog_hw(ctrl->vfebase + VFE_ROLLOFF_CFG_0,
2949		(uint32_t *)&cmd, sizeof(cmd));
2950
2951	vfe_write_lens_roll_off_table(in);
2952}
2953
2954void vfe_chroma_subsample_config(
2955	struct vfe_cmd_chroma_subsample_config *in)
2956{
2957	struct vfe_chromasubsample_cfg cmd;
2958	memset(&cmd, 0, sizeof(cmd));
2959
2960	ctrl->vfeModuleEnableLocal.chromaSubsampleEnable = in->enable;
2961
2962	cmd.hCositedPhase       = in->hCositedPhase;
2963	cmd.vCositedPhase       = in->vCositedPhase;
2964	cmd.hCosited            = in->hCosited;
2965	cmd.vCosited            = in->vCosited;
2966	cmd.hsubSampleEnable    = in->hsubSampleEnable;
2967	cmd.vsubSampleEnable    = in->vsubSampleEnable;
2968	cmd.cropEnable          = in->cropEnable;
2969	cmd.cropWidthLastPixel  = in->cropWidthLastPixel;
2970	cmd.cropWidthFirstPixel = in->cropWidthFirstPixel;
2971	cmd.cropHeightLastLine  = in->cropHeightLastLine;
2972	cmd.cropHeightFirstLine = in->cropHeightFirstLine;
2973
2974	vfe_prog_hw(ctrl->vfebase + VFE_CHROMA_SUBSAMPLE_CFG,
2975		(uint32_t *)&cmd, sizeof(cmd));
2976}
2977
2978void vfe_chroma_enhan_config(struct vfe_cmd_chroma_enhan_config *in)
2979{
2980	struct vfe_chroma_enhance_cfg cmd;
2981	struct vfe_color_convert_cfg cmd2;
2982
2983	memset(&cmd, 0, sizeof(cmd));
2984	memset(&cmd2, 0, sizeof(cmd2));
2985
2986	ctrl->vfeModuleEnableLocal.chromaEnhanEnable = in->enable;
2987
2988	cmd.ap             = in->ap;
2989	cmd.am             = in->am;
2990	cmd.bp             = in->bp;
2991	cmd.bm             = in->bm;
2992	cmd.cp             = in->cp;
2993	cmd.cm             = in->cm;
2994	cmd.dp             = in->dp;
2995	cmd.dm             = in->dm;
2996	cmd.kcb            = in->kcb;
2997	cmd.kcr            = in->kcr;
2998
2999	cmd2.v0            = in->RGBtoYConversionV0;
3000	cmd2.v1            = in->RGBtoYConversionV1;
3001	cmd2.v2            = in->RGBtoYConversionV2;
3002	cmd2.ConvertOffset = in->RGBtoYConversionOffset;
3003
3004	vfe_prog_hw(ctrl->vfebase + VFE_CHROMA_ENHAN_A,
3005		(uint32_t *)&cmd, sizeof(cmd));
3006
3007	vfe_prog_hw(ctrl->vfebase + VFE_COLOR_CONVERT_COEFF_0,
3008		(uint32_t *)&cmd2, sizeof(cmd2));
3009}
3010
3011void vfe_scaler2cbcr_config(struct vfe_cmd_scaler2_config *in)
3012{
3013	struct vfe_scaler2_cfg cmd;
3014
3015	memset(&cmd, 0, sizeof(cmd));
3016
3017	ctrl->vfeModuleEnableLocal.scaler2CbcrEnable = in->enable;
3018
3019	cmd.hEnable              = in->hconfig.enable;
3020	cmd.vEnable              = in->vconfig.enable;
3021	cmd.inWidth              = in->hconfig.inputSize;
3022	cmd.outWidth             = in->hconfig.outputSize;
3023	cmd.horizPhaseMult       = in->hconfig.phaseMultiplicationFactor;
3024	cmd.horizInterResolution = in->hconfig.interpolationResolution;
3025	cmd.inHeight             = in->vconfig.inputSize;
3026	cmd.outHeight            = in->vconfig.outputSize;
3027	cmd.vertPhaseMult        = in->vconfig.phaseMultiplicationFactor;
3028	cmd.vertInterResolution  = in->vconfig.interpolationResolution;
3029
3030	vfe_prog_hw(ctrl->vfebase + VFE_SCALE_CBCR_CFG,
3031		(uint32_t *)&cmd, sizeof(cmd));
3032}
3033
3034void vfe_scaler2y_config(struct vfe_cmd_scaler2_config *in)
3035{
3036	struct vfe_scaler2_cfg cmd;
3037
3038	memset(&cmd, 0, sizeof(cmd));
3039
3040	ctrl->vfeModuleEnableLocal.scaler2YEnable = in->enable;
3041
3042	cmd.hEnable               = in->hconfig.enable;
3043	cmd.vEnable               = in->vconfig.enable;
3044	cmd.inWidth               = in->hconfig.inputSize;
3045	cmd.outWidth              = in->hconfig.outputSize;
3046	cmd.horizPhaseMult        = in->hconfig.phaseMultiplicationFactor;
3047	cmd.horizInterResolution  = in->hconfig.interpolationResolution;
3048	cmd.inHeight              = in->vconfig.inputSize;
3049	cmd.outHeight             = in->vconfig.outputSize;
3050	cmd.vertPhaseMult         = in->vconfig.phaseMultiplicationFactor;
3051	cmd.vertInterResolution   = in->vconfig.interpolationResolution;
3052
3053	vfe_prog_hw(ctrl->vfebase + VFE_SCALE_Y_CFG,
3054		(uint32_t *)&cmd, sizeof(cmd));
3055}
3056
3057void vfe_main_scaler_config(struct vfe_cmd_main_scaler_config *in)
3058{
3059	struct vfe_main_scaler_cfg cmd;
3060
3061	memset(&cmd, 0, sizeof(cmd));
3062
3063	ctrl->vfeModuleEnableLocal.mainScalerEnable = in->enable;
3064
3065	cmd.hEnable              = in->hconfig.enable;
3066	cmd.vEnable              = in->vconfig.enable;
3067	cmd.inWidth              = in->hconfig.inputSize;
3068	cmd.outWidth             = in->hconfig.outputSize;
3069	cmd.horizPhaseMult       = in->hconfig.phaseMultiplicationFactor;
3070	cmd.horizInterResolution = in->hconfig.interpolationResolution;
3071	cmd.horizMNInit          = in->MNInitH.MNCounterInit;
3072	cmd.horizPhaseInit       = in->MNInitH.phaseInit;
3073	cmd.inHeight             = in->vconfig.inputSize;
3074	cmd.outHeight            = in->vconfig.outputSize;
3075	cmd.vertPhaseMult        = in->vconfig.phaseMultiplicationFactor;
3076	cmd.vertInterResolution  = in->vconfig.interpolationResolution;
3077	cmd.vertMNInit           = in->MNInitV.MNCounterInit;
3078	cmd.vertPhaseInit        = in->MNInitV.phaseInit;
3079
3080	vfe_prog_hw(ctrl->vfebase + VFE_SCALE_CFG,
3081		(uint32_t *)&cmd, sizeof(cmd));
3082}
3083
3084void vfe_stats_wb_exp_stop(void)
3085{
3086	ctrl->vfeStatsCmdLocal.axwEnable = FALSE;
3087	ctrl->vfeImaskLocal.awbPingpongIrq = FALSE;
3088}
3089
3090void vfe_stats_update_wb_exp(struct vfe_cmd_stats_wb_exp_update *in)
3091{
3092	struct vfe_statsawb_update   cmd;
3093	struct vfe_statsawbae_update cmd2;
3094
3095	memset(&cmd, 0, sizeof(cmd));
3096	memset(&cmd2, 0, sizeof(cmd2));
3097
3098	cmd.m1  = in->awbMCFG[0];
3099	cmd.m2  = in->awbMCFG[1];
3100	cmd.m3  = in->awbMCFG[2];
3101	cmd.m4  = in->awbMCFG[3];
3102	cmd.c1  = in->awbCCFG[0];
3103	cmd.c2  = in->awbCCFG[1];
3104	cmd.c3  = in->awbCCFG[2];
3105	cmd.c4  = in->awbCCFG[3];
3106	vfe_prog_hw(ctrl->vfebase + VFE_STATS_AWB_MCFG,
3107		(uint32_t *)&cmd, sizeof(cmd));
3108
3109	cmd2.aeRegionCfg    = in->wbExpRegions;
3110	cmd2.aeSubregionCfg = in->wbExpSubRegion;
3111	cmd2.awbYMin        = in->awbYMin;
3112	cmd2.awbYMax        = in->awbYMax;
3113	vfe_prog_hw(ctrl->vfebase + VFE_STATS_AWBAE_CFG,
3114		(uint32_t *)&cmd2, sizeof(cmd2));
3115}
3116
3117void vfe_stats_update_af(struct vfe_cmd_stats_af_update *in)
3118{
3119	struct vfe_statsaf_update cmd;
3120	memset(&cmd, 0, sizeof(cmd));
3121
3122	cmd.windowVOffset = in->windowVOffset;
3123	cmd.windowHOffset = in->windowHOffset;
3124	cmd.windowMode    = in->windowMode;
3125	cmd.windowHeight  = in->windowHeight;
3126	cmd.windowWidth   = in->windowWidth;
3127
3128	vfe_prog_hw(ctrl->vfebase + VFE_STATS_AF_CFG,
3129		(uint32_t *)&cmd, sizeof(cmd));
3130}
3131
3132void vfe_stats_start_wb_exp(struct vfe_cmd_stats_wb_exp_start *in)
3133{
3134	struct vfe_statsawb_update   cmd;
3135	struct vfe_statsawbae_update cmd2;
3136	struct vfe_statsaxw_hdr_cfg  cmd3;
3137
3138	ctrl->vfeStatsCmdLocal.axwEnable   =  in->enable;
3139	ctrl->vfeImaskLocal.awbPingpongIrq = TRUE;
3140
3141	memset(&cmd, 0, sizeof(cmd));
3142	memset(&cmd2, 0, sizeof(cmd2));
3143	memset(&cmd3, 0, sizeof(cmd3));
3144
3145	cmd.m1  = in->awbMCFG[0];
3146	cmd.m2  = in->awbMCFG[1];
3147	cmd.m3  = in->awbMCFG[2];
3148	cmd.m4  = in->awbMCFG[3];
3149	cmd.c1  = in->awbCCFG[0];
3150	cmd.c2  = in->awbCCFG[1];
3151	cmd.c3  = in->awbCCFG[2];
3152	cmd.c4  = in->awbCCFG[3];
3153	vfe_prog_hw(ctrl->vfebase + VFE_STATS_AWB_MCFG,
3154		(uint32_t *)&cmd, sizeof(cmd));
3155
3156	cmd2.aeRegionCfg     = in->wbExpRegions;
3157	cmd2.aeSubregionCfg  = in->wbExpSubRegion;
3158	cmd2.awbYMin         = in->awbYMin;
3159	cmd2.awbYMax         = in->awbYMax;
3160	vfe_prog_hw(ctrl->vfebase + VFE_STATS_AWBAE_CFG,
3161		(uint32_t *)&cmd2, sizeof(cmd2));
3162
3163	cmd3.axwHeader       = in->axwHeader;
3164	vfe_prog_hw(ctrl->vfebase + VFE_STATS_AXW_HEADER,
3165		(uint32_t *)&cmd3, sizeof(cmd3));
3166}
3167
3168void vfe_stats_start_af(struct vfe_cmd_stats_af_start *in)
3169{
3170	struct vfe_statsaf_update cmd;
3171	struct vfe_statsaf_cfg    cmd2;
3172
3173	memset(&cmd, 0, sizeof(cmd));
3174	memset(&cmd2, 0, sizeof(cmd2));
3175
3176ctrl->vfeStatsCmdLocal.autoFocusEnable = in->enable;
3177ctrl->vfeImaskLocal.afPingpongIrq = TRUE;
3178
3179	cmd.windowVOffset = in->windowVOffset;
3180	cmd.windowHOffset = in->windowHOffset;
3181	cmd.windowMode    = in->windowMode;
3182	cmd.windowHeight  = in->windowHeight;
3183	cmd.windowWidth   = in->windowWidth;
3184
3185	vfe_prog_hw(ctrl->vfebase + VFE_STATS_AF_CFG,
3186		(uint32_t *)&cmd, sizeof(cmd));
3187
3188	cmd2.a00       = in->highPassCoef[0];
3189	cmd2.a04       = in->highPassCoef[1];
3190	cmd2.a20       = in->highPassCoef[2];
3191	cmd2.a21       = in->highPassCoef[3];
3192	cmd2.a22       = in->highPassCoef[4];
3193	cmd2.a23       = in->highPassCoef[5];
3194	cmd2.a24       = in->highPassCoef[6];
3195	cmd2.fvMax     = in->metricMax;
3196	cmd2.fvMetric  = in->metricSelection;
3197	cmd2.afHeader  = in->bufferHeader;
3198	cmd2.entry00   = in->gridForMultiWindows[0];
3199	cmd2.entry01   = in->gridForMultiWindows[1];
3200	cmd2.entry02   = in->gridForMultiWindows[2];
3201	cmd2.entry03   = in->gridForMultiWindows[3];
3202	cmd2.entry10   = in->gridForMultiWindows[4];
3203	cmd2.entry11   = in->gridForMultiWindows[5];
3204	cmd2.entry12   = in->gridForMultiWindows[6];
3205	cmd2.entry13   = in->gridForMultiWindows[7];
3206	cmd2.entry20   = in->gridForMultiWindows[8];
3207	cmd2.entry21   = in->gridForMultiWindows[9];
3208	cmd2.entry22   = in->gridForMultiWindows[10];
3209	cmd2.entry23   = in->gridForMultiWindows[11];
3210	cmd2.entry30   = in->gridForMultiWindows[12];
3211	cmd2.entry31   = in->gridForMultiWindows[13];
3212	cmd2.entry32   = in->gridForMultiWindows[14];
3213	cmd2.entry33   = in->gridForMultiWindows[15];
3214
3215	vfe_prog_hw(ctrl->vfebase + VFE_STATS_AF_GRID_0,
3216		(uint32_t *)&cmd2, sizeof(cmd2));
3217}
3218
3219void vfe_stats_setting(struct vfe_cmd_stats_setting *in)
3220{
3221	struct vfe_statsframe cmd1;
3222	struct vfe_busstats_wrprio cmd2;
3223
3224	memset(&cmd1, 0, sizeof(cmd1));
3225	memset(&cmd2, 0, sizeof(cmd2));
3226
3227	ctrl->afStatsControl.addressBuffer[0] = in->afBuffer[0];
3228	ctrl->afStatsControl.addressBuffer[1] = in->afBuffer[1];
3229	ctrl->afStatsControl.nextFrameAddrBuf = in->afBuffer[2];
3230
3231	ctrl->awbStatsControl.addressBuffer[0] = in->awbBuffer[0];
3232	ctrl->awbStatsControl.addressBuffer[1] = in->awbBuffer[1];
3233	ctrl->awbStatsControl.nextFrameAddrBuf = in->awbBuffer[2];
3234
3235	cmd1.lastPixel = in->frameHDimension;
3236	cmd1.lastLine  = in->frameVDimension;
3237	vfe_prog_hw(ctrl->vfebase + VFE_STATS_FRAME_SIZE,
3238		(uint32_t *)&cmd1, sizeof(cmd1));
3239
3240	cmd2.afBusPriority    = in->afBusPriority;
3241	cmd2.awbBusPriority   = in->awbBusPriority;
3242	cmd2.histBusPriority  = in->histBusPriority;
3243	cmd2.afBusPriorityEn  = in->afBusPrioritySelection;
3244	cmd2.awbBusPriorityEn = in->awbBusPrioritySelection;
3245	cmd2.histBusPriorityEn = in->histBusPrioritySelection;
3246
3247	vfe_prog_hw(ctrl->vfebase + VFE_BUS_STATS_WR_PRIORITY,
3248		(uint32_t *)&cmd2, sizeof(cmd2));
3249
3250	/* Program the bus ping pong address for statistics modules. */
3251	writel(in->afBuffer[0], ctrl->vfebase + VFE_BUS_STATS_AF_WR_PING_ADDR);
3252	writel(in->afBuffer[1], ctrl->vfebase + VFE_BUS_STATS_AF_WR_PONG_ADDR);
3253	writel(in->awbBuffer[0],
3254		ctrl->vfebase + VFE_BUS_STATS_AWB_WR_PING_ADDR);
3255	writel(in->awbBuffer[1],
3256		ctrl->vfebase + VFE_BUS_STATS_AWB_WR_PONG_ADDR);
3257	writel(in->histBuffer[0],
3258		ctrl->vfebase + VFE_BUS_STATS_HIST_WR_PING_ADDR);
3259	writel(in->histBuffer[1],
3260		ctrl->vfebase + VFE_BUS_STATS_HIST_WR_PONG_ADDR);
3261}
3262
3263void vfe_axi_input_config(struct vfe_cmd_axi_input_config *in)
3264{
3265	struct VFE_AxiInputCmdType cmd;
3266	uint32_t xSizeWord, axiRdUnpackPattern;
3267	uint8_t  axiInputPpw;
3268	uint32_t busPingpongRdIrqEnable;
3269
3270	ctrl->vfeImaskLocal.rdPingpongIrq = TRUE;
3271
3272	switch (in->pixelSize) {
3273	case VFE_RAW_PIXEL_DATA_SIZE_10BIT:
3274		ctrl->axiInputDataSize = VFE_RAW_PIXEL_DATA_SIZE_10BIT;
3275		break;
3276
3277	case VFE_RAW_PIXEL_DATA_SIZE_12BIT:
3278		ctrl->axiInputDataSize = VFE_RAW_PIXEL_DATA_SIZE_12BIT;
3279		break;
3280
3281	case VFE_RAW_PIXEL_DATA_SIZE_8BIT:
3282	default:
3283		ctrl->axiInputDataSize = VFE_RAW_PIXEL_DATA_SIZE_8BIT;
3284		break;
3285	}
3286
3287	memset(&cmd, 0, sizeof(cmd));
3288
3289	switch (in->pixelSize) {
3290	case VFE_RAW_PIXEL_DATA_SIZE_10BIT:
3291		axiInputPpw = 6;
3292		axiRdUnpackPattern = 0xD43210;
3293		break;
3294
3295	case VFE_RAW_PIXEL_DATA_SIZE_12BIT:
3296		axiInputPpw = 5;
3297		axiRdUnpackPattern = 0xC3210;
3298		break;
3299
3300	case VFE_RAW_PIXEL_DATA_SIZE_8BIT:
3301	default:
3302		axiInputPpw = 8;
3303		axiRdUnpackPattern = 0xF6543210;
3304		break;
3305	}
3306
3307	xSizeWord =
3308		((((in->xOffset % axiInputPpw) + in->xSize) +
3309			(axiInputPpw-1)) / axiInputPpw) - 1;
3310
3311	cmd.stripeStartAddr0  = in->fragAddr[0];
3312	cmd.stripeStartAddr1  = in->fragAddr[1];
3313	cmd.stripeStartAddr2  = in->fragAddr[2];
3314	cmd.stripeStartAddr3  = in->fragAddr[3];
3315	cmd.ySize             = in->ySize;
3316	cmd.yOffsetDelta      = 0;
3317	cmd.xSizeWord         = xSizeWord;
3318	cmd.burstLength       = 1;
3319	cmd.NumOfRows         = in->numOfRows;
3320	cmd.RowIncrement      =
3321		(in->rowIncrement + (axiInputPpw-1))/axiInputPpw;
3322	cmd.mainUnpackHeight  = in->ySize;
3323	cmd.mainUnpackWidth   = in->xSize - 1;
3324	cmd.mainUnpackHbiSel  = (uint32_t)in->unpackHbi;
3325	cmd.mainUnpackPhase   = in->unpackPhase;
3326	cmd.unpackPattern     = axiRdUnpackPattern;
3327	cmd.padLeft           = in->padRepeatCountLeft;
3328	cmd.padRight          = in->padRepeatCountRight;
3329	cmd.padTop            = in->padRepeatCountTop;
3330	cmd.padBottom         = in->padRepeatCountBottom;
3331	cmd.leftUnpackPattern0   = in->padLeftComponentSelectCycle0;
3332	cmd.leftUnpackPattern1   = in->padLeftComponentSelectCycle1;
3333	cmd.leftUnpackPattern2   = in->padLeftComponentSelectCycle2;
3334	cmd.leftUnpackPattern3   = in->padLeftComponentSelectCycle3;
3335	cmd.leftUnpackStop0      = in->padLeftStopCycle0;
3336	cmd.leftUnpackStop1      = in->padLeftStopCycle1;
3337	cmd.leftUnpackStop2      = in->padLeftStopCycle2;
3338	cmd.leftUnpackStop3      = in->padLeftStopCycle3;
3339	cmd.rightUnpackPattern0  = in->padRightComponentSelectCycle0;
3340	cmd.rightUnpackPattern1  = in->padRightComponentSelectCycle1;
3341	cmd.rightUnpackPattern2  = in->padRightComponentSelectCycle2;
3342	cmd.rightUnpackPattern3  = in->padRightComponentSelectCycle3;
3343	cmd.rightUnpackStop0     = in->padRightStopCycle0;
3344	cmd.rightUnpackStop1     = in->padRightStopCycle1;
3345	cmd.rightUnpackStop2     = in->padRightStopCycle2;
3346	cmd.rightUnpackStop3     = in->padRightStopCycle3;
3347	cmd.topUnapckPattern     = in->padTopLineCount;
3348	cmd.bottomUnapckPattern  = in->padBottomLineCount;
3349
3350	/*  program vfe_bus_cfg */
3351	vfe_prog_hw(ctrl->vfebase + VFE_BUS_STRIPE_RD_ADDR_0,
3352		(uint32_t *)&cmd, sizeof(cmd));
3353
3354	/* hacking code, put it to default value */
3355	busPingpongRdIrqEnable = 0xf;
3356
3357	writel(busPingpongRdIrqEnable,
3358		ctrl->vfebase + VFE_BUS_PINGPONG_IRQ_EN);
3359}
3360
3361void vfe_stats_config(struct vfe_cmd_stats_setting *in)
3362{
3363	ctrl->afStatsControl.addressBuffer[0] = in->afBuffer[0];
3364	ctrl->afStatsControl.addressBuffer[1] = in->afBuffer[1];
3365	ctrl->afStatsControl.nextFrameAddrBuf = in->afBuffer[2];
3366
3367	ctrl->awbStatsControl.addressBuffer[0] = in->awbBuffer[0];
3368	ctrl->awbStatsControl.addressBuffer[1] = in->awbBuffer[1];
3369	ctrl->awbStatsControl.nextFrameAddrBuf = in->awbBuffer[2];
3370
3371	vfe_stats_setting(in);
3372}
3373
3374void vfe_axi_output_config(
3375	struct vfe_cmd_axi_output_config *in)
3376{
3377	/* local variable  */
3378	uint32_t *pcircle;
3379	uint32_t *pdest;
3380	uint32_t *psrc;
3381	uint8_t  i;
3382	uint8_t  fcnt;
3383	uint16_t axioutpw = 8;
3384
3385	/* parameters check, condition and usage mode check */
3386	ctrl->encPath.fragCount = in->output2.fragmentCount;
3387	if (ctrl->encPath.fragCount > 1)
3388		ctrl->encPath.multiFrag = TRUE;
3389
3390	ctrl->viewPath.fragCount = in->output1.fragmentCount;
3391	if (ctrl->viewPath.fragCount > 1)
3392		ctrl->viewPath.multiFrag = TRUE;
3393
3394	/* VFE_BUS_CFG.  raw data size */
3395	ctrl->vfeBusConfigLocal.rawPixelDataSize = in->outputDataSize;
3396
3397	switch (in->outputDataSize) {
3398	case VFE_RAW_PIXEL_DATA_SIZE_8BIT:
3399		axioutpw = 8;
3400		break;
3401
3402	case VFE_RAW_PIXEL_DATA_SIZE_10BIT:
3403		axioutpw = 6;
3404		break;
3405
3406	case VFE_RAW_PIXEL_DATA_SIZE_12BIT:
3407		axioutpw = 5;
3408		break;
3409	}
3410
3411	ctrl->axiOutputMode = in->outputMode;
3412
3413	CDBG("axiOutputMode = %d\n", ctrl->axiOutputMode);
3414
3415	switch (ctrl->axiOutputMode) {
3416	case VFE_AXI_OUTPUT_MODE_Output1: {
3417		ctrl->vfeCamifConfigLocal.camif2BusEnable   = FALSE;
3418		ctrl->vfeCamifConfigLocal.camif2OutputEnable = TRUE;
3419		ctrl->vfeBusConfigLocal.rawWritePathSelect  =
3420			VFE_RAW_OUTPUT_DISABLED;
3421
3422		ctrl->encPath.pathEnabled                   = FALSE;
3423		ctrl->vfeImaskLocal.encIrq                  = FALSE;
3424		ctrl->vfeIrqCompositeMaskLocal.encIrqComMask =
3425			VFE_COMP_IRQ_BOTH_Y_CBCR;
3426
3427		ctrl->vfeBusConfigLocal.encYWrPathEn          = FALSE;
3428		ctrl->vfeBusConfigLocal.encCbcrWrPathEn       = FALSE;
3429		ctrl->viewPath.pathEnabled                    = TRUE;
3430		ctrl->vfeImaskLocal.viewIrq                   = TRUE;
3431		ctrl->vfeIrqCompositeMaskLocal.viewIrqComMask =
3432			VFE_COMP_IRQ_BOTH_Y_CBCR;
3433
3434		ctrl->vfeBusConfigLocal.viewYWrPathEn    = TRUE;
3435		ctrl->vfeBusConfigLocal.viewCbcrWrPathEn = TRUE;
3436
3437		if (ctrl->vfeBusConfigLocal.encYWrPathEn &&
3438				ctrl->encPath.multiFrag)
3439			ctrl->vfeImaskLocal.encYPingpongIrq    = TRUE;
3440
3441		if (ctrl->vfeBusConfigLocal.encCbcrWrPathEn &&
3442				ctrl->encPath.multiFrag)
3443			ctrl->vfeImaskLocal.encCbcrPingpongIrq = TRUE;
3444
3445		if (ctrl->vfeBusConfigLocal.viewYWrPathEn &&
3446				ctrl->viewPath.multiFrag)
3447			ctrl->vfeImaskLocal.viewYPingpongIrq   = TRUE;
3448
3449		if (ctrl->vfeBusConfigLocal.viewCbcrWrPathEn &&
3450				ctrl->viewPath.multiFrag)
3451			ctrl->vfeImaskLocal.viewCbcrPingpongIrq = TRUE;
3452	} /* VFE_AXI_OUTPUT_MODE_Output1 */
3453		break;
3454
3455	case VFE_AXI_OUTPUT_MODE_Output2: {
3456		ctrl->vfeCamifConfigLocal.camif2BusEnable   = FALSE;
3457		ctrl->vfeCamifConfigLocal.camif2OutputEnable = TRUE;
3458		ctrl->vfeBusConfigLocal.rawWritePathSelect  =
3459			VFE_RAW_OUTPUT_DISABLED;
3460
3461		ctrl->encPath.pathEnabled                   = TRUE;
3462		ctrl->vfeImaskLocal.encIrq                  = TRUE;
3463		ctrl->vfeIrqCompositeMaskLocal.encIrqComMask =
3464			VFE_COMP_IRQ_BOTH_Y_CBCR;
3465
3466		ctrl->vfeBusConfigLocal.encYWrPathEn        = TRUE;
3467		ctrl->vfeBusConfigLocal.encCbcrWrPathEn     = TRUE;
3468
3469		ctrl->viewPath.pathEnabled                   = FALSE;
3470		ctrl->vfeImaskLocal.viewIrq                  = FALSE;
3471		ctrl->vfeIrqCompositeMaskLocal.viewIrqComMask =
3472			VFE_COMP_IRQ_BOTH_Y_CBCR;
3473
3474		ctrl->vfeBusConfigLocal.viewYWrPathEn        = FALSE;
3475		ctrl->vfeBusConfigLocal.viewCbcrWrPathEn     = FALSE;
3476
3477		if (ctrl->vfeBusConfigLocal.encYWrPathEn &&
3478				ctrl->encPath.multiFrag)
3479			ctrl->vfeImaskLocal.encYPingpongIrq    = TRUE;
3480
3481		if (ctrl->vfeBusConfigLocal.encCbcrWrPathEn &&
3482				ctrl->encPath.multiFrag)
3483			ctrl->vfeImaskLocal.encCbcrPingpongIrq = TRUE;
3484
3485		if (ctrl->vfeBusConfigLocal.viewYWrPathEn &&
3486				ctrl->viewPath.multiFrag)
3487			ctrl->vfeImaskLocal.viewYPingpongIrq   = TRUE;
3488
3489		if (ctrl->vfeBusConfigLocal.viewCbcrWrPathEn &&
3490				ctrl->viewPath.multiFrag)
3491			ctrl->vfeImaskLocal.viewCbcrPingpongIrq = TRUE;
3492	} /* VFE_AXI_OUTPUT_MODE_Output2 */
3493			break;
3494
3495	case VFE_AXI_OUTPUT_MODE_Output1AndOutput2: {
3496		ctrl->vfeCamifConfigLocal.camif2BusEnable    = FALSE;
3497		ctrl->vfeCamifConfigLocal.camif2OutputEnable = TRUE;
3498		ctrl->vfeBusConfigLocal.rawWritePathSelect   =
3499			VFE_RAW_OUTPUT_DISABLED;
3500
3501		ctrl->encPath.pathEnabled                    = TRUE;
3502		ctrl->vfeImaskLocal.encIrq                   = TRUE;
3503		ctrl->vfeIrqCompositeMaskLocal.encIrqComMask =
3504			VFE_COMP_IRQ_BOTH_Y_CBCR;
3505
3506		ctrl->vfeBusConfigLocal.encYWrPathEn         = TRUE;
3507		ctrl->vfeBusConfigLocal.encCbcrWrPathEn      = TRUE;
3508		ctrl->viewPath.pathEnabled                   = TRUE;
3509		ctrl->vfeImaskLocal.viewIrq                  = TRUE;
3510		ctrl->vfeIrqCompositeMaskLocal.viewIrqComMask =
3511			VFE_COMP_IRQ_BOTH_Y_CBCR;
3512
3513		ctrl->vfeBusConfigLocal.viewYWrPathEn        = TRUE;
3514		ctrl->vfeBusConfigLocal.viewCbcrWrPathEn     = TRUE;
3515
3516		if (ctrl->vfeBusConfigLocal.encYWrPathEn &&
3517				ctrl->encPath.multiFrag)
3518			ctrl->vfeImaskLocal.encYPingpongIrq    = TRUE;
3519
3520		if (ctrl->vfeBusConfigLocal.encCbcrWrPathEn &&
3521				ctrl->encPath.multiFrag)
3522			ctrl->vfeImaskLocal.encCbcrPingpongIrq = TRUE;
3523
3524		if (ctrl->vfeBusConfigLocal.viewYWrPathEn &&
3525				ctrl->viewPath.multiFrag)
3526			ctrl->vfeImaskLocal.viewYPingpongIrq   = TRUE;
3527
3528		if (ctrl->vfeBusConfigLocal.viewCbcrWrPathEn &&
3529				ctrl->viewPath.multiFrag)
3530			ctrl->vfeImaskLocal.viewCbcrPingpongIrq = TRUE;
3531	} /* VFE_AXI_OUTPUT_MODE_Output1AndOutput2 */
3532		break;
3533
3534	case VFE_AXI_OUTPUT_MODE_CAMIFToAXIViaOutput2: {
3535		/* For raw snapshot, we need both ping and pong buffer
3536		 * initialized to the same address. Otherwise, if we
3537		 * leave the pong buffer to NULL, there will be axi_error.
3538		 * Note that ideally we should deal with this at upper layer,
3539		 * which is in msm_vfe8x.c */
3540		if (!in->output2.outputCbcr.outFragments[1][0]) {
3541			in->output2.outputCbcr.outFragments[1][0] =
3542				in->output2.outputCbcr.outFragments[0][0];
3543		}
3544
3545		ctrl->vfeCamifConfigLocal.camif2BusEnable   = TRUE;
3546		ctrl->vfeCamifConfigLocal.camif2OutputEnable = FALSE;
3547		ctrl->vfeBusConfigLocal.rawWritePathSelect  =
3548			VFE_RAW_OUTPUT_ENC_CBCR_PATH;
3549
3550		ctrl->encPath.pathEnabled                   = TRUE;
3551		ctrl->vfeImaskLocal.encIrq                  = TRUE;
3552		ctrl->vfeIrqCompositeMaskLocal.encIrqComMask =
3553			VFE_COMP_IRQ_CBCR_ONLY;
3554
3555		ctrl->vfeBusConfigLocal.encYWrPathEn        = FALSE;
3556		ctrl->vfeBusConfigLocal.encCbcrWrPathEn     = TRUE;
3557
3558		ctrl->viewPath.pathEnabled                   = FALSE;
3559		ctrl->vfeImaskLocal.viewIrq                  = FALSE;
3560		ctrl->vfeIrqCompositeMaskLocal.viewIrqComMask =
3561			VFE_COMP_IRQ_BOTH_Y_CBCR;
3562
3563		ctrl->vfeBusConfigLocal.viewYWrPathEn        = FALSE;
3564		ctrl->vfeBusConfigLocal.viewCbcrWrPathEn     = FALSE;
3565
3566		if (ctrl->vfeBusConfigLocal.encYWrPathEn &&
3567				ctrl->encPath.multiFrag)
3568			ctrl->vfeImaskLocal.encYPingpongIrq    = TRUE;
3569
3570		if (ctrl->vfeBusConfigLocal.encCbcrWrPathEn &&
3571				ctrl->encPath.multiFrag)
3572			ctrl->vfeImaskLocal.encCbcrPingpongIrq = TRUE;
3573
3574		if (ctrl->vfeBusConfigLocal.viewYWrPathEn &&
3575				ctrl->viewPath.multiFrag)
3576			ctrl->vfeImaskLocal.viewYPingpongIrq   = TRUE;
3577
3578		if (ctrl->vfeBusConfigLocal.viewCbcrWrPathEn &&
3579				ctrl->viewPath.multiFrag)
3580			ctrl->vfeImaskLocal.viewCbcrPingpongIrq = TRUE;
3581	} /* VFE_AXI_OUTPUT_MODE_CAMIFToAXIViaOutput2 */
3582		break;
3583
3584	case VFE_AXI_OUTPUT_MODE_Output2AndCAMIFToAXIViaOutput1: {
3585		ctrl->vfeCamifConfigLocal.camif2BusEnable   = TRUE;
3586		ctrl->vfeCamifConfigLocal.camif2OutputEnable = TRUE;
3587		ctrl->vfeBusConfigLocal.rawWritePathSelect  =
3588			VFE_RAW_OUTPUT_VIEW_CBCR_PATH;
3589
3590		ctrl->encPath.pathEnabled                   = TRUE;
3591		ctrl->vfeImaskLocal.encIrq                  = TRUE;
3592		ctrl->vfeIrqCompositeMaskLocal.encIrqComMask =
3593			VFE_COMP_IRQ_BOTH_Y_CBCR;
3594
3595		ctrl->vfeBusConfigLocal.encYWrPathEn        = TRUE;
3596		ctrl->vfeBusConfigLocal.encCbcrWrPathEn     = TRUE;
3597
3598		ctrl->viewPath.pathEnabled                   = TRUE;
3599		ctrl->vfeImaskLocal.viewIrq                  = TRUE;
3600		ctrl->vfeIrqCompositeMaskLocal.viewIrqComMask =
3601			VFE_COMP_IRQ_CBCR_ONLY;
3602
3603		ctrl->vfeBusConfigLocal.viewYWrPathEn        = FALSE;
3604		ctrl->vfeBusConfigLocal.viewCbcrWrPathEn     = TRUE;
3605
3606		if (ctrl->vfeBusConfigLocal.encYWrPathEn &&
3607				ctrl->encPath.multiFrag)
3608			ctrl->vfeImaskLocal.encYPingpongIrq    = TRUE;
3609
3610		if (ctrl->vfeBusConfigLocal.encCbcrWrPathEn &&
3611				ctrl->encPath.multiFrag)
3612			ctrl->vfeImaskLocal.encCbcrPingpongIrq = TRUE;
3613
3614		if (ctrl->vfeBusConfigLocal.viewYWrPathEn &&
3615				ctrl->viewPath.multiFrag)
3616			ctrl->vfeImaskLocal.viewYPingpongIrq   = TRUE;
3617
3618		if (ctrl->vfeBusConfigLocal.viewCbcrWrPathEn &&
3619				ctrl->viewPath.multiFrag)
3620			ctrl->vfeImaskLocal.viewCbcrPingpongIrq = TRUE;
3621	} /* VFE_AXI_OUTPUT_MODE_Output2AndCAMIFToAXIViaOutput1 */
3622		break;
3623
3624	case VFE_AXI_OUTPUT_MODE_Output1AndCAMIFToAXIViaOutput2: {
3625		ctrl->vfeCamifConfigLocal.camif2BusEnable   = TRUE;
3626		ctrl->vfeCamifConfigLocal.camif2OutputEnable = TRUE;
3627		ctrl->vfeBusConfigLocal.rawWritePathSelect  =
3628			VFE_RAW_OUTPUT_ENC_CBCR_PATH;
3629
3630		ctrl->encPath.pathEnabled                     = TRUE;
3631		ctrl->vfeImaskLocal.encIrq                    = TRUE;
3632		ctrl->vfeIrqCompositeMaskLocal.encIrqComMask  =
3633			VFE_COMP_IRQ_CBCR_ONLY;
3634
3635		ctrl->vfeBusConfigLocal.encYWrPathEn          = FALSE;
3636		ctrl->vfeBusConfigLocal.encCbcrWrPathEn       = TRUE;
3637
3638		ctrl->viewPath.pathEnabled                    = TRUE;
3639		ctrl->vfeImaskLocal.viewIrq                   = TRUE;
3640
3641		ctrl->vfeIrqCompositeMaskLocal.viewIrqComMask =
3642			VFE_COMP_IRQ_BOTH_Y_CBCR;
3643
3644		ctrl->vfeBusConfigLocal.viewYWrPathEn         = TRUE;
3645		ctrl->vfeBusConfigLocal.viewCbcrWrPathEn      = TRUE;
3646
3647		if (ctrl->vfeBusConfigLocal.encYWrPathEn &&
3648				ctrl->encPath.multiFrag)
3649			ctrl->vfeImaskLocal.encYPingpongIrq       = TRUE;
3650
3651		if (ctrl->vfeBusConfigLocal.encCbcrWrPathEn &&
3652				ctrl->encPath.multiFrag)
3653			ctrl->vfeImaskLocal.encCbcrPingpongIrq    = TRUE;
3654
3655		if (ctrl->vfeBusConfigLocal.viewYWrPathEn &&
3656				ctrl->viewPath.multiFrag)
3657			ctrl->vfeImaskLocal.viewYPingpongIrq      = TRUE;
3658
3659		if (ctrl->vfeBusConfigLocal.viewCbcrWrPathEn &&
3660				ctrl->viewPath.multiFrag)
3661			ctrl->vfeImaskLocal.viewCbcrPingpongIrq   = TRUE;
3662	} /* VFE_AXI_OUTPUT_MODE_Output1AndCAMIFToAXIViaOutput2 */
3663		break;
3664
3665	case VFE_AXI_LAST_OUTPUT_MODE_ENUM:
3666		break;
3667	} /* switch */
3668
3669	/* Save the addresses for each path. */
3670	/* output2 path */
3671	fcnt = ctrl->encPath.fragCount;
3672
3673	pcircle = ctrl->encPath.yPath.addressBuffer;
3674	pdest = ctrl->encPath.nextFrameAddrBuf;
3675
3676	psrc = &(in->output2.outputY.outFragments[0][0]);
3677	for (i = 0; i < fcnt; i++)
3678		*pcircle++ = *psrc++;
3679
3680	psrc = &(in->output2.outputY.outFragments[1][0]);
3681	for (i = 0; i < fcnt; i++)
3682		*pcircle++ = *psrc++;
3683
3684	psrc = &(in->output2.outputY.outFragments[2][0]);
3685	for (i = 0; i < fcnt; i++)
3686		*pdest++ = *psrc++;
3687
3688	pcircle = ctrl->encPath.cbcrPath.addressBuffer;
3689
3690	psrc = &(in->output2.outputCbcr.outFragments[0][0]);
3691	for (i = 0; i < fcnt; i++)
3692		*pcircle++ = *psrc++;
3693
3694	psrc = &(in->output2.outputCbcr.outFragments[1][0]);
3695	for (i = 0; i < fcnt; i++)
3696		*pcircle++ = *psrc++;
3697
3698	psrc = &(in->output2.outputCbcr.outFragments[2][0]);
3699	for (i = 0; i < fcnt; i++)
3700		*pdest++ = *psrc++;
3701
3702	vfe_set_bus_pipo_addr(&ctrl->viewPath, &ctrl->encPath);
3703
3704	ctrl->encPath.ackPending = FALSE;
3705	ctrl->encPath.currentFrame = ping;
3706	ctrl->encPath.whichOutputPath = 1;
3707	ctrl->encPath.yPath.fragIndex = 2;
3708	ctrl->encPath.cbcrPath.fragIndex = 2;
3709	ctrl->encPath.yPath.hwCurrentFlag = ping;
3710	ctrl->encPath.cbcrPath.hwCurrentFlag = ping;
3711
3712	/* output1 path */
3713	pcircle = ctrl->viewPath.yPath.addressBuffer;
3714	pdest = ctrl->viewPath.nextFrameAddrBuf;
3715	fcnt = ctrl->viewPath.fragCount;
3716
3717	psrc = &(in->output1.outputY.outFragments[0][0]);
3718	for (i = 0; i < fcnt; i++)
3719		*pcircle++ = *psrc++;
3720
3721	psrc = &(in->output1.outputY.outFragments[1][0]);
3722	for (i = 0; i < fcnt; i++)
3723		*pcircle++ = *psrc++;
3724
3725	psrc = &(in->output1.outputY.outFragments[2][0]);
3726	for (i = 0; i < fcnt; i++)
3727		*pdest++ = *psrc++;
3728
3729	pcircle = ctrl->viewPath.cbcrPath.addressBuffer;
3730
3731	psrc = &(in->output1.outputCbcr.outFragments[0][0]);
3732	for (i = 0; i < fcnt; i++)
3733		*pcircle++ = *psrc++;
3734
3735	psrc = &(in->output1.outputCbcr.outFragments[1][0]);
3736	for (i = 0; i < fcnt; i++)
3737		*pcircle++ = *psrc++;
3738
3739	psrc = &(in->output1.outputCbcr.outFragments[2][0]);
3740	for (i = 0; i < fcnt; i++)
3741		*pdest++ = *psrc++;
3742
3743	ctrl->viewPath.ackPending = FALSE;
3744	ctrl->viewPath.currentFrame = ping;
3745	ctrl->viewPath.whichOutputPath = 0;
3746	ctrl->viewPath.yPath.fragIndex = 2;
3747	ctrl->viewPath.cbcrPath.fragIndex = 2;
3748	ctrl->viewPath.yPath.hwCurrentFlag = ping;
3749	ctrl->viewPath.cbcrPath.hwCurrentFlag = ping;
3750
3751	/* call to program the registers. */
3752	vfe_axi_output(in, &ctrl->viewPath, &ctrl->encPath, axioutpw);
3753}
3754
3755void vfe_camif_config(struct vfe_cmd_camif_config *in)
3756{
3757	struct vfe_camifcfg cmd;
3758	memset(&cmd, 0, sizeof(cmd));
3759
3760	CDBG("camif.frame pixelsPerLine = %d\n", in->frame.pixelsPerLine);
3761	CDBG("camif.frame linesPerFrame = %d\n", in->frame.linesPerFrame);
3762	CDBG("camif.window firstpixel = %d\n", in->window.firstpixel);
3763	CDBG("camif.window lastpixel = %d\n",  in->window.lastpixel);
3764	CDBG("camif.window firstline = %d\n",  in->window.firstline);
3765	CDBG("camif.window lastline = %d\n",   in->window.lastline);
3766
3767	/* determine if epoch interrupt needs to be enabled.  */
3768	if ((in->epoch1.enable == TRUE) &&
3769			(in->epoch1.lineindex <=
3770			 in->frame.linesPerFrame))
3771		ctrl->vfeImaskLocal.camifEpoch1Irq = 1;
3772
3773	if ((in->epoch2.enable == TRUE) &&
3774			(in->epoch2.lineindex <=
3775			 in->frame.linesPerFrame)) {
3776		ctrl->vfeImaskLocal.camifEpoch2Irq = 1;
3777	}
3778
3779	/*  save the content to program CAMIF_CONFIG separately. */
3780	ctrl->vfeCamifConfigLocal.camifCfgFromCmd = in->camifConfig;
3781
3782	/* EFS_Config */
3783	cmd.efsEndOfLine     = in->EFS.efsendofline;
3784	cmd.efsStartOfLine   = in->EFS.efsstartofline;
3785	cmd.efsEndOfFrame    = in->EFS.efsendofframe;
3786	cmd.efsStartOfFrame  = in->EFS.efsstartofframe;
3787
3788	/* Frame Config */
3789	cmd.frameConfigPixelsPerLine = in->frame.pixelsPerLine;
3790	cmd.frameConfigLinesPerFrame = in->frame.linesPerFrame;
3791
3792	/* Window Width Config */
3793	cmd.windowWidthCfgLastPixel  = in->window.lastpixel;
3794	cmd.windowWidthCfgFirstPixel = in->window.firstpixel;
3795
3796	/* Window Height Config */
3797	cmd.windowHeightCfglastLine   = in->window.lastline;
3798	cmd.windowHeightCfgfirstLine  = in->window.firstline;
3799
3800	/* Subsample 1 Config */
3801	cmd.subsample1CfgPixelSkip = in->subsample.pixelskipmask;
3802	cmd.subsample1CfgLineSkip  = in->subsample.lineskipmask;
3803
3804	/* Subsample 2 Config */
3805	cmd.subsample2CfgFrameSkip      = in->subsample.frameskip;
3806	cmd.subsample2CfgFrameSkipMode  = in->subsample.frameskipmode;
3807	cmd.subsample2CfgPixelSkipWrap  = in->subsample.pixelskipwrap;
3808
3809	/* Epoch Interrupt */
3810	cmd.epoch1Line = in->epoch1.lineindex;
3811	cmd.epoch2Line = in->epoch2.lineindex;
3812
3813	vfe_prog_hw(ctrl->vfebase + CAMIF_EFS_CONFIG,
3814		(uint32_t *)&cmd, sizeof(cmd));
3815}
3816
3817void vfe_fov_crop_config(struct vfe_cmd_fov_crop_config *in)
3818{
3819	struct vfe_fov_crop_cfg cmd;
3820	memset(&cmd, 0, sizeof(cmd));
3821
3822	ctrl->vfeModuleEnableLocal.cropEnable = in->enable;
3823
3824	/* FOV Corp, Part 1 */
3825	cmd.lastPixel  = in->lastPixel;
3826	cmd.firstPixel = in->firstPixel;
3827
3828	/* FOV Corp, Part 2 */
3829	cmd.lastLine   = in->lastLine;
3830	cmd.firstLine  = in->firstLine;
3831
3832	vfe_prog_hw(ctrl->vfebase + VFE_CROP_WIDTH_CFG,
3833		(uint32_t *)&cmd, sizeof(cmd));
3834}
3835
3836void vfe_get_hw_version(struct vfe_cmd_hw_version *out)
3837{
3838	uint32_t vfeHwVersionPacked;
3839	struct vfe_hw_ver ver;
3840
3841	vfeHwVersionPacked = readl(ctrl->vfebase + VFE_HW_VERSION);
3842
3843	ver = *((struct vfe_hw_ver *)&vfeHwVersionPacked);
3844
3845	out->coreVersion  = ver.coreVersion;
3846	out->minorVersion = ver.minorVersion;
3847	out->majorVersion = ver.majorVersion;
3848}
3849
3850static void vfe_reset_internal_variables(void)
3851{
3852	unsigned long flags;
3853
3854	/* local variables to program the hardware. */
3855	ctrl->vfeImaskPacked = 0;
3856	ctrl->vfeImaskCompositePacked = 0;
3857
3858	/* FALSE = disable,  1 = enable. */
3859	memset(&ctrl->vfeModuleEnableLocal, 0,
3860		sizeof(ctrl->vfeModuleEnableLocal));
3861
3862	/* 0 = disable, 1 = enable */
3863	memset(&ctrl->vfeCamifConfigLocal, 0,
3864		sizeof(ctrl->vfeCamifConfigLocal));
3865	/* 0 = disable, 1 = enable */
3866	memset(&ctrl->vfeImaskLocal, 0, sizeof(ctrl->vfeImaskLocal));
3867	memset(&ctrl->vfeStatsCmdLocal, 0, sizeof(ctrl->vfeStatsCmdLocal));
3868	memset(&ctrl->vfeBusConfigLocal, 0, sizeof(ctrl->vfeBusConfigLocal));
3869	memset(&ctrl->vfeBusPmConfigLocal, 0,
3870		sizeof(ctrl->vfeBusPmConfigLocal));
3871	memset(&ctrl->vfeBusCmdLocal, 0, sizeof(ctrl->vfeBusCmdLocal));
3872	memset(&ctrl->vfeInterruptNameLocal, 0,
3873		sizeof(ctrl->vfeInterruptNameLocal));
3874	memset(&ctrl->vfeDroppedFrameCounts, 0,
3875		sizeof(ctrl->vfeDroppedFrameCounts));
3876	memset(&ctrl->vfeIrqThreadMsgLocal, 0,
3877		sizeof(ctrl->vfeIrqThreadMsgLocal));
3878
3879	/* state control variables */
3880	ctrl->vfeStartAckPendingFlag = FALSE;
3881	ctrl->vfeStopAckPending = FALSE;
3882	ctrl->vfeIrqCompositeMaskLocal.ceDoneSel = 0;
3883	ctrl->vfeIrqCompositeMaskLocal.encIrqComMask =
3884		VFE_COMP_IRQ_BOTH_Y_CBCR;
3885	ctrl->vfeIrqCompositeMaskLocal.viewIrqComMask =
3886		VFE_COMP_IRQ_BOTH_Y_CBCR;
3887
3888	spin_lock_irqsave(&ctrl->state_lock, flags);
3889	ctrl->vstate = VFE_STATE_IDLE;
3890	spin_unlock_irqrestore(&ctrl->state_lock, flags);
3891
3892	ctrl->axiOutputMode = VFE_AXI_LAST_OUTPUT_MODE_ENUM;
3893	/* 0 for continuous mode, 1 for snapshot mode */
3894	ctrl->vfeOperationMode = VFE_START_OPERATION_MODE_CONTINUOUS;
3895	ctrl->vfeSnapShotCount = 0;
3896	ctrl->vfeStatsPingPongReloadFlag = FALSE;
3897	/* this is unsigned 32 bit integer. */
3898	ctrl->vfeFrameId = 0;
3899	ctrl->vfeFrameSkip.output1Pattern = 0xffffffff;
3900	ctrl->vfeFrameSkip.output1Period  = 31;
3901	ctrl->vfeFrameSkip.output2Pattern = 0xffffffff;
3902	ctrl->vfeFrameSkip.output2Period  = 31;
3903	ctrl->vfeFrameSkipPattern = 0xffffffff;
3904	ctrl->vfeFrameSkipCount   = 0;
3905	ctrl->vfeFrameSkipPeriod  = 31;
3906
3907	memset((void *)&ctrl->encPath, 0, sizeof(ctrl->encPath));
3908	memset((void *)&ctrl->viewPath, 0, sizeof(ctrl->viewPath));
3909
3910	ctrl->encPath.whichOutputPath  = 1;
3911	ctrl->encPath.cbcrStatusBit    = 5;
3912	ctrl->viewPath.whichOutputPath = 0;
3913	ctrl->viewPath.cbcrStatusBit   = 7;
3914
3915	ctrl->vfeTestGenStartFlag = FALSE;
3916
3917	/* default to bank 0. */
3918	ctrl->vfeLaBankSel = 0;
3919
3920	/* default to bank 0 for all channels. */
3921	memset(&ctrl->vfeGammaLutSel, 0, sizeof(ctrl->vfeGammaLutSel));
3922
3923	/* Stats control variables. */
3924	memset(&ctrl->afStatsControl, 0, sizeof(ctrl->afStatsControl));
3925	memset(&ctrl->awbStatsControl, 0, sizeof(ctrl->awbStatsControl));
3926	vfe_set_stats_pingpong_address(&ctrl->afStatsControl,
3927		&ctrl->awbStatsControl);
3928}
3929
3930void vfe_reset(void)
3931{
3932	vfe_reset_internal_variables();
3933
3934	ctrl->vfeImaskLocal.resetAckIrq = TRUE;
3935	ctrl->vfeImaskPacked = vfe_irq_pack(ctrl->vfeImaskLocal);
3936
3937	/* disable all interrupts. */
3938	writel(VFE_DISABLE_ALL_IRQS,
3939		ctrl->vfebase + VFE_IRQ_COMPOSITE_MASK);
3940
3941	/* clear all pending interrupts*/
3942	writel(VFE_CLEAR_ALL_IRQS,
3943		ctrl->vfebase + VFE_IRQ_CLEAR);
3944
3945	/* enable reset_ack interrupt.  */
3946	writel(ctrl->vfeImaskPacked,
3947		ctrl->vfebase + VFE_IRQ_MASK);
3948
3949	writel(VFE_RESET_UPON_RESET_CMD,
3950		ctrl->vfebase + VFE_GLOBAL_RESET_CMD);
3951}
3952