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