2 * Copyright (C) 2008-2009 QUALCOMM Incorporated.
4 #include <linux/slab.h>
5 #include <linux/interrupt.h>
6 #include <linux/spinlock.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>
14 struct msm_vfe8x_ctrl {
15 /* bit 1:0 ENC_IRQ_MASK = 0x11:
16 * generate IRQ when both y and cbcr frame is ready. */
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;
32 boolean vfeStartAckPendingFlag;
33 boolean vfeStopAckPending;
34 boolean vfeResetAckPending;
35 boolean vfeUpdateAckPending;
37 enum VFE_AXI_OUTPUT_MODE axiOutputMode;
38 enum VFE_START_OPERATION_MODE vfeOperationMode;
40 uint32_t vfeSnapShotCount;
41 uint32_t vfeRequestedSnapShotCount;
42 boolean vfeStatsPingPongReloadFlag;
45 struct vfe_cmd_frame_skip_config vfeFrameSkip;
46 uint32_t vfeFrameSkipPattern;
47 uint8_t vfeFrameSkipCount;
48 uint8_t vfeFrameSkipPeriod;
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;
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;
62 enum VFE_STATE vstate;
65 spinlock_t state_lock;
68 struct msm_vfe_callback *resp;
72 spinlock_t tasklet_lock;
73 struct list_head tasklet_q;
76 void __iomem *vfebase;
80 static struct msm_vfe8x_ctrl *ctrl;
81 static irqreturn_t vfe_parse_irq(int irq_num, void *data);
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;
92 static void vfe_prog_hw(uint8_t *hwreg,
93 uint32_t *inptr, uint32_t regcnt)
95 /* unsigned long flags; */
99 /* @todo This is causing issues, need further investigate */
100 /* spin_lock_irqsave(&ctrl->io_lock, flags); */
102 p = (uint32_t *)(hwreg);
103 for (i = 0; i < (regcnt >> 2); i++)
104 writel(*inptr++, p++);
105 /* *p++ = *inptr++; */
107 /* spin_unlock_irqrestore(&ctrl->io_lock, flags); */
110 static void vfe_read_reg_values(uint8_t *hwreg,
111 uint32_t *dest, uint32_t count)
113 /* unsigned long flags; */
117 /* @todo This is causing issues, need further investigate */
118 /* spin_lock_irqsave(&ctrl->io_lock, flags); */
120 temp = (uint32_t *)(hwreg);
121 for (i = 0; i < count; i++)
124 /* spin_unlock_irqrestore(&ctrl->io_lock, flags); */
127 static struct vfe_irqenable vfe_read_irq_mask(void)
129 /* unsigned long flags; */
131 struct vfe_irqenable rc;
133 memset(&rc, 0, sizeof(rc));
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);
139 rc = *((struct vfe_irqenable *)temp);
140 /* spin_unlock_irqrestore(&ctrl->io_lock, flags); */
146 vfe_set_bus_pipo_addr(struct vfe_output_path_combo *vpath,
147 struct vfe_output_path_combo *epath)
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);
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);
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)
172 struct vfe_axi_out_cfg cmd;
175 uint32_t burstLength;
177 /* force it to burst length 4, hardware does not support it. */
180 /* AXI Output 2 Y Configuration*/
181 /* VFE_BUS_ENC_Y_WR_PING_ADDR */
182 cmd.out2YPingAddr = out2->yPath.addressBuffer[0];
184 /* VFE_BUS_ENC_Y_WR_PONG_ADDR */
185 cmd.out2YPongAddr = out2->yPath.addressBuffer[1];
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)) /
193 cmd.out2YImageWidthin64bit = temp;
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)) /
200 cmd.out2YRowIncrementIn64bit = temp;
202 /* AXI Output 2 Cbcr Configuration*/
203 /* VFE_BUS_ENC_Cbcr_WR_PING_ADDR */
204 cmd.out2CbcrPingAddr = out2->cbcrPath.addressBuffer[0];
206 /* VFE_BUS_ENC_Cbcr_WR_PONG_ADDR */
207 cmd.out2CbcrPongAddr = out2->cbcrPath.addressBuffer[1];
209 /* VFE_BUS_ENC_Cbcr_WR_IMAGE_SIZE */
210 cmd.out2CbcrImageHeight = in->output2.outputCbcr.imageHeight;
211 temp = (in->output2.outputCbcr.imageWidth + (out - 1)) /
213 cmd.out2CbcrImageWidthIn64bit = temp;
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)) /
220 cmd.out2CbcrRowIncrementIn64bit = temp;
222 /* AXI Output 1 Y Configuration */
223 /* VFE_BUS_VIEW_Y_WR_PING_ADDR */
224 cmd.out1YPingAddr = out1->yPath.addressBuffer[0];
226 /* VFE_BUS_VIEW_Y_WR_PONG_ADDR */
227 cmd.out1YPongAddr = out1->yPath.addressBuffer[1];
229 /* VFE_BUS_VIEW_Y_WR_IMAGE_SIZE */
230 cmd.out1YImageHeight = in->output1.outputY.imageHeight;
231 temp = (in->output1.outputY.imageWidth + (out - 1)) /
233 cmd.out1YImageWidthin64bit = temp;
235 /* VFE_BUS_VIEW_Y_WR_BUFFER_CFG */
236 cmd.out1YBurstLength = burstLength;
237 cmd.out1YNumRows = in->output1.outputY.outRowCount;
240 (in->output1.outputY.outRowIncrement +
242 cmd.out1YRowIncrementIn64bit = temp;
244 /* AXI Output 1 Cbcr Configuration*/
245 cmd.out1CbcrPingAddr = out1->cbcrPath.addressBuffer[0];
247 /* VFE_BUS_VIEW_Cbcr_WR_PONG_ADDR */
248 cmd.out1CbcrPongAddr =
249 out1->cbcrPath.addressBuffer[1];
251 /* VFE_BUS_VIEW_Cbcr_WR_IMAGE_SIZE */
252 cmd.out1CbcrImageHeight = in->output1.outputCbcr.imageHeight;
253 temp = (in->output1.outputCbcr.imageWidth +
255 cmd.out1CbcrImageWidthIn64bit = temp;
257 cmd.out1CbcrBurstLength = burstLength;
258 cmd.out1CbcrNumRows = in->output1.outputCbcr.outRowCount;
260 (in->output1.outputCbcr.outRowIncrement +
263 cmd.out1CbcrRowIncrementIn64bit = temp;
265 vfe_prog_hw(ctrl->vfebase + VFE_BUS_ENC_Y_WR_PING_ADDR,
266 (uint32_t *)&cmd, sizeof(cmd));
269 static void vfe_reg_bus_cfg(struct vfe_bus_cfg_data *in)
271 struct vfe_axi_bus_cfg cmd;
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;
281 /* program vfe_bus_cfg */
282 writel(*((uint32_t *)&cmd), ctrl->vfebase + VFE_BUS_CFG);
285 static void vfe_reg_camif_config(struct vfe_camif_cfg_data *in)
287 struct VFE_CAMIFConfigType cfg;
289 memset(&cfg, 0, sizeof(cfg));
292 in->camifCfgFromCmd.vSyncEdge;
295 in->camifCfgFromCmd.hSyncEdge;
298 in->camifCfgFromCmd.syncMode;
300 cfg.vfeSubsampleEnable =
301 in->camifCfgFromCmd.vfeSubSampleEnable;
303 cfg.busSubsampleEnable =
304 in->camifCfgFromCmd.busSubSampleEnable;
306 cfg.camif2vfeEnable =
307 in->camif2OutputEnable;
309 cfg.camif2busEnable =
312 cfg.irqSubsampleEnable =
313 in->camifCfgFromCmd.irqSubSampleEnable;
316 in->camifCfgFromCmd.binningEnable;
319 in->camifCfgFromCmd.misrEnable;
321 /* program camif_config */
322 writel(*((uint32_t *)&cfg), ctrl->vfebase + CAMIF_CONFIG);
325 static void vfe_reg_bus_cmd(struct vfe_bus_cmd_data *in)
327 struct vfe_buscmd cmd;
328 memset(&cmd, 0, sizeof(cmd));
330 cmd.stripeReload = in->stripeReload;
331 cmd.busPingpongReload = in->busPingpongReload;
332 cmd.statsPingpongReload = in->statsPingpongReload;
334 writel(*((uint32_t *)&cmd), ctrl->vfebase + VFE_BUS_CMD);
336 CDBG("bus command = 0x%x\n", (*((uint32_t *)&cmd)));
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;
345 static void vfe_reg_module_cfg(struct vfe_module_enable *in)
347 struct vfe_mod_enable ena;
349 memset(&ena, 0, sizeof(ena));
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;
372 writel(*((uint32_t *)&ena), ctrl->vfebase + VFE_MODULE_CFG);
375 static void vfe_program_dmi_cfg(enum VFE_DMI_RAM_SEL bankSel)
377 /* set bit 8 for auto increment. */
378 uint32_t value = (uint32_t) ctrl->vfebase + VFE_DMI_CFG_DEFAULT;
380 value += (uint32_t)bankSel;
381 /* CDBG("dmi cfg input bank is 0x%x\n", bankSel); */
383 writel(value, ctrl->vfebase + VFE_DMI_CFG);
384 writel(0, ctrl->vfebase + VFE_DMI_ADDR);
387 static void vfe_write_lens_roll_off_table(
388 struct vfe_cmd_roll_off_config *in)
393 uint16_t *initGr = in->initTableGr;
394 uint16_t *initGb = in->initTableGb;
395 uint16_t *initB = in->initTableB;
396 uint16_t *initR = in->initTableR;
398 int16_t *pDeltaGr = in->deltaTableGr;
399 int16_t *pDeltaGb = in->deltaTableGb;
400 int16_t *pDeltaB = in->deltaTableB;
401 int16_t *pDeltaR = in->deltaTableR;
403 vfe_program_dmi_cfg(ROLLOFF_RAM);
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);
412 writel(data, ctrl->vfebase + VFE_DMI_DATA_LO);
414 data = (((uint32_t)(*initB)) & 0x0000FFFF) |
415 (((uint32_t)(*initGr))<<16);
419 writel(data, ctrl->vfebase + VFE_DMI_DATA_LO);
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);
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);
434 writel(data, ctrl->vfebase + VFE_DMI_DATA_LO);
436 data = (((int32_t)(*pDeltaB)) & 0x0000FFFF) |
437 (((int32_t)(*pDeltaGb))<<16);
441 writel(data, ctrl->vfebase + VFE_DMI_DATA_LO);
444 /* After DMI transfer, to make it safe, need to set the
445 * DMI_CFG to unselect any SRAM
447 /* unselect the SRAM Bank. */
448 writel(VFE_DMI_CFG_DEFAULT, ctrl->vfebase + VFE_DMI_CFG);
451 static void vfe_set_default_reg_values(void)
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);
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);
470 static void vfe_config_demux(uint32_t period, uint32_t even, uint32_t odd)
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);
477 static void vfe_pm_stop(void)
479 writel(VFE_PERFORMANCE_MONITOR_STOP, ctrl->vfebase + VFE_BUS_PM_CMD);
482 static void vfe_program_bus_rd_irq_en(uint32_t value)
484 writel(value, ctrl->vfebase + VFE_BUS_PINGPONG_IRQ_EN);
487 static void vfe_camif_go(void)
489 writel(CAMIF_COMMAND_START, ctrl->vfebase + CAMIF_COMMAND);
492 static void vfe_camif_stop_immediately(void)
494 writel(CAMIF_COMMAND_STOP_IMMEDIATELY, ctrl->vfebase + CAMIF_COMMAND);
495 writel(0, ctrl->vfebase + VFE_CGC_OVERRIDE);
498 static void vfe_program_reg_update_cmd(uint32_t value)
500 writel(value, ctrl->vfebase + VFE_REG_UPDATE_CMD);
503 static void vfe_program_bus_cmd(uint32_t value)
505 writel(value, ctrl->vfebase + VFE_BUS_CMD);
508 static void vfe_program_global_reset_cmd(uint32_t value)
510 writel(value, ctrl->vfebase + VFE_GLOBAL_RESET_CMD);
513 static void vfe_program_axi_cmd(uint32_t value)
515 writel(value, ctrl->vfebase + VFE_AXI_CMD);
518 static void vfe_program_irq_composite_mask(uint32_t value)
520 writel(value, ctrl->vfebase + VFE_IRQ_COMPOSITE_MASK);
523 static inline void vfe_program_irq_mask(uint32_t value)
525 writel(value, ctrl->vfebase + VFE_IRQ_MASK);
528 static void vfe_program_chroma_upsample_cfg(uint32_t value)
530 writel(value, ctrl->vfebase + VFE_CHROMA_UPSAMPLE_CFG);
533 static uint32_t vfe_read_axi_status(void)
535 return readl(ctrl->vfebase + VFE_AXI_STATUS);
538 static uint32_t vfe_read_pm_status_in_raw_capture(void)
540 return readl(ctrl->vfebase + VFE_BUS_ENC_CBCR_WR_PM_STATS_1);
544 vfe_set_stats_pingpong_address(struct vfe_stats_control *afControl,
545 struct vfe_stats_control *awbControl)
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);
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);
558 static uint32_t vfe_read_camif_status(void)
560 return readl(ctrl->vfebase + CAMIF_STATUS);
563 static void vfe_program_lut_bank_sel(struct vfe_gamma_lut_sel *in)
565 struct VFE_GammaLutSelect_ConfigCmdType cmd;
567 memset(&cmd, 0, sizeof(cmd));
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));
577 static void vfe_program_stats_cmd(struct vfe_stats_cmd_data *in)
579 struct VFE_StatsCmdType stats;
580 memset(&stats, 0, sizeof(stats));
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;
589 writel(*((uint32_t *)&stats), ctrl->vfebase + VFE_STATS_CMD);
592 static void vfe_pm_start(struct vfe_cmd_bus_pm_start *in)
594 struct VFE_Bus_Pm_ConfigCmdType cmd;
595 memset(&cmd, 0, sizeof(struct VFE_Bus_Pm_ConfigCmdType));
597 cmd.output2YWrPmEnable = in->output2YWrPmEnable;
598 cmd.output2CbcrWrPmEnable = in->output2CbcrWrPmEnable;
599 cmd.output1YWrPmEnable = in->output1YWrPmEnable;
600 cmd.output1CbcrWrPmEnable = in->output1CbcrWrPmEnable;
602 vfe_prog_hw(ctrl->vfebase + VFE_BUS_PM_CFG,
603 (uint32_t *)&cmd, sizeof(cmd));
606 static void vfe_8k_pm_start(struct vfe_cmd_bus_pm_start *in)
608 in->output1CbcrWrPmEnable = ctrl->vfeBusConfigLocal.viewCbcrWrPathEn;
609 in->output1YWrPmEnable = ctrl->vfeBusConfigLocal.viewYWrPathEn;
610 in->output2CbcrWrPmEnable = ctrl->vfeBusConfigLocal.encCbcrWrPathEn;
611 in->output2YWrPmEnable = ctrl->vfeBusConfigLocal.encYWrPathEn;
613 if (in->output1CbcrWrPmEnable || in->output1YWrPmEnable)
614 ctrl->viewPath.pmEnabled = TRUE;
616 if (in->output2CbcrWrPmEnable || in->output2YWrPmEnable)
617 ctrl->encPath.pmEnabled = TRUE;
621 writel(VFE_PERFORMANCE_MONITOR_GO, ctrl->vfebase + VFE_BUS_PM_CMD);
624 static uint32_t vfe_irq_pack(struct vfe_interrupt_mask data)
626 struct vfe_irqenable packedData;
628 memset(&packedData, 0, sizeof(packedData));
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;
663 return *((uint32_t *)&packedData);
667 vfe_irq_composite_pack(struct vfe_irq_composite_mask_config data)
669 struct VFE_Irq_Composite_MaskType packedData;
671 memset(&packedData, 0, sizeof(packedData));
673 packedData.encIrqComMaskBits = data.encIrqComMask;
674 packedData.viewIrqComMaskBits = data.viewIrqComMask;
675 packedData.ceDoneSelBits = data.ceDoneSel;
677 return *((uint32_t *)&packedData);
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)
684 case VFE_MSG_OUTPUT1: {
686 ((struct vfe_message *)data)->_u.msgOutput1.yBuffer;
688 ((struct vfe_message *)data)->_u.msgOutput1.cbcrBuffer;
690 ((struct vfe_frame_extra *)ctrl->extdata)->bpcInfo =
691 ((struct vfe_message *)data)->_u.msgOutput1.bpcInfo;
693 ((struct vfe_frame_extra *)ctrl->extdata)->asfInfo =
694 ((struct vfe_message *)data)->_u.msgOutput1.asfInfo;
696 ((struct vfe_frame_extra *)ctrl->extdata)->frameCounter =
697 ((struct vfe_message *)data)->_u.msgOutput1.frameCounter;
699 ((struct vfe_frame_extra *)ctrl->extdata)->pmData =
700 ((struct vfe_message *)data)->_u.msgOutput1.pmData;
702 *ext = ctrl->extdata;
703 *elen = ctrl->extlen;
707 case VFE_MSG_OUTPUT2: {
709 ((struct vfe_message *)data)->_u.msgOutput2.yBuffer;
711 ((struct vfe_message *)data)->_u.msgOutput2.cbcrBuffer;
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",
717 ((struct vfe_frame_extra *)ctrl->extdata)->bpcInfo =
718 ((struct vfe_message *)data)->_u.msgOutput2.bpcInfo;
720 ((struct vfe_frame_extra *)ctrl->extdata)->asfInfo =
721 ((struct vfe_message *)data)->_u.msgOutput2.asfInfo;
723 ((struct vfe_frame_extra *)ctrl->extdata)->frameCounter =
724 ((struct vfe_message *)data)->_u.msgOutput2.frameCounter;
726 ((struct vfe_frame_extra *)ctrl->extdata)->pmData =
727 ((struct vfe_message *)data)->_u.msgOutput2.pmData;
729 *ext = ctrl->extdata;
730 *elen = ctrl->extlen;
734 case VFE_MSG_STATS_AF:
736 ((struct vfe_message *)data)->_u.msgStatsAf.afBuffer;
739 case VFE_MSG_STATS_WE:
741 ((struct vfe_message *)data)->_u.msgStatsWbExp.awbBuffer;
750 vfe_proc_ops(enum VFE_MESSAGE_ID id, void *msg, size_t len)
752 struct msm_vfe_resp *rp;
754 /* In 8k, OUTPUT1 & OUTPUT2 messages arrive before
755 * SNAPSHOT_DONE. We don't send such messages to user */
757 CDBG("ctrl->vfeOperationMode = %d, msgId = %d\n",
758 ctrl->vfeOperationMode, id);
760 if ((ctrl->vfeOperationMode == VFE_START_OPERATION_MODE_SNAPSHOT) &&
761 (id == VFE_MSG_ID_OUTPUT1 || id == VFE_MSG_ID_OUTPUT2)) {
765 rp = ctrl->resp->vfe_alloc(sizeof(struct msm_vfe_resp), ctrl->syncdata);
767 CDBG("rp: cannot allocate buffer\n");
771 CDBG("vfe_proc_ops, msgId = %d\n", id);
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;
778 switch (rp->evt_msg.msg_id) {
779 case VFE_MSG_ID_SNAPSHOT_DONE:
780 rp->type = VFE_MSG_SNAPSHOT;
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),
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),
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);
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);
810 rp->type = VFE_MSG_GENERAL;
814 ctrl->resp->vfe_resp(rp, MSM_CAM_Q_VFE_MSG, ctrl->syncdata);
817 static void vfe_send_msg_no_payload(enum VFE_MESSAGE_ID id)
819 struct vfe_message *msg;
821 msg = kzalloc(sizeof(*msg), GFP_ATOMIC);
826 vfe_proc_ops(id, msg, 0);
829 static void vfe_send_bus_overflow_msg(void)
831 struct vfe_message *msg;
833 kzalloc(sizeof(struct vfe_message), GFP_ATOMIC);
837 msg->_d = VFE_MSG_ID_BUS_OVERFLOW;
839 memcpy(&(msg->_u.msgBusOverflow),
840 &ctrl->vfePmData, sizeof(ctrl->vfePmData));
843 vfe_proc_ops(VFE_MSG_ID_BUS_OVERFLOW,
844 msg, sizeof(struct vfe_message));
847 static void vfe_send_camif_error_msg(void)
850 struct vfe_message *msg;
852 kzalloc(sizeof(struct vfe_message), GFP_ATOMIC);
856 msg->_d = VFE_MSG_ID_CAMIF_ERROR;
857 memcpy(&(msg->_u.msgCamifError),
858 &ctrl->vfeCamifStatusLocal, sizeof(ctrl->vfeCamifStatusLocal));
860 vfe_proc_ops(VFE_MSG_ID_CAMIF_ERROR,
861 msg, sizeof(struct vfe_message));
865 static void vfe_process_error_irq(
866 struct vfe_interrupt_status *irqstatus)
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);
873 if (irqstatus->awbOverflowIrq)
874 vfe_send_msg_no_payload(VFE_MSG_ID_AWB_OVERFLOW);
876 if (irqstatus->axiErrorIrq)
877 vfe_send_msg_no_payload(VFE_MSG_ID_AXI_ERROR);
879 if (irqstatus->busOverflowIrq)
880 vfe_send_bus_overflow_msg();
882 if (irqstatus->camifErrorIrq)
883 vfe_send_camif_error_msg();
885 if (irqstatus->camifOverflowIrq)
886 vfe_send_msg_no_payload(VFE_MSG_ID_CAMIF_OVERFLOW);
888 if (irqstatus->violationIrq)
892 static void vfe_process_camif_sof_irq(void)
894 /* increment the frame id number. */
897 CDBG("camif_sof_irq, frameId = %d\n",
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
907 if (ctrl->vfeOperationMode) {
908 if ((1 << ctrl->vfeFrameSkipCount) &
909 ctrl->vfeFrameSkipPattern) {
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);
918 /* update frame skip counter for bit checking. */
919 ctrl->vfeFrameSkipCount++;
920 if (ctrl->vfeFrameSkipCount ==
921 (ctrl->vfeFrameSkipPeriod + 1))
922 ctrl->vfeFrameSkipCount = 0;
926 static int vfe_get_af_pingpong_status(void)
928 uint32_t busPingPongStatus;
932 readl(ctrl->vfebase + VFE_BUS_PINGPONG_STATUS);
934 if ((busPingPongStatus & VFE_AF_PINGPONG_STATUS_BIT) == 0)
940 static uint32_t vfe_read_af_buf_addr(boolean pipo)
943 return readl(ctrl->vfebase + VFE_BUS_STATS_AF_WR_PING_ADDR);
945 return readl(ctrl->vfebase + VFE_BUS_STATS_AF_WR_PONG_ADDR);
949 vfe_update_af_buf_addr(boolean pipo, uint32_t addr)
952 writel(addr, ctrl->vfebase + VFE_BUS_STATS_AF_WR_PING_ADDR);
954 writel(addr, ctrl->vfebase + VFE_BUS_STATS_AF_WR_PONG_ADDR);
958 vfe_send_af_stats_msg(uint32_t afBufAddress)
960 /* unsigned long flags; */
961 struct vfe_message *msg;
963 kzalloc(sizeof(struct vfe_message), GFP_ATOMIC);
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)
973 msg->_d = VFE_MSG_ID_STATS_AUTOFOCUS;
974 msg->_u.msgStatsAf.afBuffer = afBufAddress;
975 msg->_u.msgStatsAf.frameCounter = ctrl->vfeFrameId;
977 vfe_proc_ops(VFE_MSG_ID_STATS_AUTOFOCUS,
978 msg, sizeof(struct vfe_message));
980 ctrl->afStatsControl.ackPending = TRUE;
983 /* spin_unlock_irqrestore(&ctrl->state_lock, flags); */
987 static void vfe_process_stats_af_irq(void)
989 boolean bufferAvailable;
991 if (!(ctrl->afStatsControl.ackPending)) {
993 /* read hardware status. */
994 ctrl->afStatsControl.pingPongStatus =
995 vfe_get_af_pingpong_status();
998 (ctrl->afStatsControl.pingPongStatus) ^ 1;
1000 ctrl->afStatsControl.bufToRender =
1001 vfe_read_af_buf_addr(bufferAvailable);
1003 /* update the same buffer address (ping or pong) */
1004 vfe_update_af_buf_addr(bufferAvailable,
1005 ctrl->afStatsControl.nextFrameAddrBuf);
1007 vfe_send_af_stats_msg(ctrl->afStatsControl.bufToRender);
1009 ctrl->afStatsControl.droppedStatsFrameCount++;
1012 static boolean vfe_get_awb_pingpong_status(void)
1014 uint32_t busPingPongStatus;
1017 readl(ctrl->vfebase + VFE_BUS_PINGPONG_STATUS);
1019 if ((busPingPongStatus & VFE_AWB_PINGPONG_STATUS_BIT) == 0)
1026 vfe_read_awb_buf_addr(boolean pingpong)
1028 if (pingpong == FALSE)
1029 return readl(ctrl->vfebase + VFE_BUS_STATS_AWB_WR_PING_ADDR);
1031 return readl(ctrl->vfebase + VFE_BUS_STATS_AWB_WR_PONG_ADDR);
1034 static void vfe_update_awb_buf_addr(
1035 boolean pingpong, uint32_t addr)
1037 if (pingpong == FALSE)
1038 writel(addr, ctrl->vfebase + VFE_BUS_STATS_AWB_WR_PING_ADDR);
1040 writel(addr, ctrl->vfebase + VFE_BUS_STATS_AWB_WR_PONG_ADDR);
1043 static void vfe_send_awb_stats_msg(uint32_t awbBufAddress)
1045 /* unsigned long flags; */
1046 struct vfe_message *msg;
1049 kzalloc(sizeof(struct vfe_message), GFP_ATOMIC);
1053 /* fill message with right content. */
1054 /* @todo This is causing issues, need further investigate */
1055 /* spin_lock_irqsave(&ctrl->state_lock, flags); */
1056 if (ctrl->vstate != VFE_STATE_ACTIVE)
1057 goto awb_stats_done;
1059 msg->_d = VFE_MSG_ID_STATS_WB_EXP;
1060 msg->_u.msgStatsWbExp.awbBuffer = awbBufAddress;
1061 msg->_u.msgStatsWbExp.frameCounter = ctrl->vfeFrameId;
1063 vfe_proc_ops(VFE_MSG_ID_STATS_WB_EXP,
1064 msg, sizeof(struct vfe_message));
1066 ctrl->awbStatsControl.ackPending = TRUE;
1069 /* spin_unlock_irqrestore(&ctrl->state_lock, flags); */
1073 static void vfe_process_stats_awb_irq(void)
1075 boolean bufferAvailable;
1077 if (!(ctrl->awbStatsControl.ackPending)) {
1079 ctrl->awbStatsControl.pingPongStatus =
1080 vfe_get_awb_pingpong_status();
1082 bufferAvailable = (ctrl->awbStatsControl.pingPongStatus) ^ 1;
1084 ctrl->awbStatsControl.bufToRender =
1085 vfe_read_awb_buf_addr(bufferAvailable);
1087 vfe_update_awb_buf_addr(bufferAvailable,
1088 ctrl->awbStatsControl.nextFrameAddrBuf);
1090 vfe_send_awb_stats_msg(ctrl->awbStatsControl.bufToRender);
1093 ctrl->awbStatsControl.droppedStatsFrameCount++;
1096 static void vfe_process_sync_timer_irq(
1097 struct vfe_interrupt_status *irqstatus)
1099 if (irqstatus->syncTimer0Irq)
1100 vfe_send_msg_no_payload(VFE_MSG_ID_SYNC_TIMER0_DONE);
1102 if (irqstatus->syncTimer1Irq)
1103 vfe_send_msg_no_payload(VFE_MSG_ID_SYNC_TIMER1_DONE);
1105 if (irqstatus->syncTimer2Irq)
1106 vfe_send_msg_no_payload(VFE_MSG_ID_SYNC_TIMER2_DONE);
1109 static void vfe_process_async_timer_irq(
1110 struct vfe_interrupt_status *irqstatus)
1113 if (irqstatus->asyncTimer0Irq)
1114 vfe_send_msg_no_payload(VFE_MSG_ID_ASYNC_TIMER0_DONE);
1116 if (irqstatus->asyncTimer1Irq)
1117 vfe_send_msg_no_payload(VFE_MSG_ID_ASYNC_TIMER1_DONE);
1119 if (irqstatus->asyncTimer2Irq)
1120 vfe_send_msg_no_payload(VFE_MSG_ID_ASYNC_TIMER2_DONE);
1122 if (irqstatus->asyncTimer3Irq)
1123 vfe_send_msg_no_payload(VFE_MSG_ID_ASYNC_TIMER3_DONE);
1126 static void vfe_send_violation_msg(void)
1128 vfe_send_msg_no_payload(VFE_MSG_ID_VIOLATION);
1131 static void vfe_send_async_timer_msg(void)
1133 vfe_send_msg_no_payload(VFE_MSG_ID_ASYNC_TIMER0_DONE);
1136 static void vfe_write_gamma_table(uint8_t channel,
1137 boolean bank, int16_t *pTable)
1141 enum VFE_DMI_RAM_SEL dmiRamSel = NO_MEM_SELECTED;
1146 dmiRamSel = RGBLUT_RAM_CH0_BANK0;
1148 dmiRamSel = RGBLUT_RAM_CH0_BANK1;
1153 dmiRamSel = RGBLUT_RAM_CH1_BANK0;
1155 dmiRamSel = RGBLUT_RAM_CH1_BANK1;
1160 dmiRamSel = RGBLUT_RAM_CH2_BANK0;
1162 dmiRamSel = RGBLUT_RAM_CH2_BANK1;
1169 vfe_program_dmi_cfg(dmiRamSel);
1171 for (i = 0; i < VFE_GAMMA_TABLE_LENGTH; i++) {
1172 writel((uint32_t)(*pTable), ctrl->vfebase + VFE_DMI_DATA_LO);
1176 /* After DMI transfer, need to set the DMI_CFG to unselect any SRAM
1177 unselect the SRAM Bank. */
1178 writel(VFE_DMI_CFG_DEFAULT, ctrl->vfebase + VFE_DMI_CFG);
1181 static void vfe_prog_hw_testgen_cmd(uint32_t value)
1183 writel(value, ctrl->vfebase + VFE_HW_TESTGEN_CMD);
1186 static inline void vfe_read_irq_status(struct vfe_irq_thread_msg *out)
1190 memset(out, 0, sizeof(struct vfe_irq_thread_msg));
1192 temp = (uint32_t *)(ctrl->vfebase + VFE_IRQ_STATUS);
1193 out->vfeIrqStatus = readl(temp);
1195 temp = (uint32_t *)(ctrl->vfebase + CAMIF_STATUS);
1196 out->camifStatus = readl(temp);
1197 writel(0x7, ctrl->vfebase + CAMIF_COMMAND);
1198 writel(0x3, ctrl->vfebase + CAMIF_COMMAND);
1199 CDBG("camifStatus = 0x%x\n", out->camifStatus);
1202 temp = (uint32_t *)(ctrl->vfebase + VFE_DEMOSAIC_STATUS);
1203 out->demosaicStatus = readl(temp);
1205 temp = (uint32_t *)(ctrl->vfebase + VFE_ASF_MAX_EDGE);
1206 out->asfMaxEdge = readl(temp);
1208 temp = (uint32_t *)(ctrl->vfebase + VFE_BUS_ENC_Y_WR_PM_STATS_0);
1212 out->pmInfo.encPathPmInfo.yWrPmStats0 = readl(temp++);
1213 out->pmInfo.encPathPmInfo.yWrPmStats1 = readl(temp++);
1214 out->pmInfo.encPathPmInfo.cbcrWrPmStats0 = readl(temp++);
1215 out->pmInfo.encPathPmInfo.cbcrWrPmStats1 = readl(temp++);
1216 out->pmInfo.viewPathPmInfo.yWrPmStats0 = readl(temp++);
1217 out->pmInfo.viewPathPmInfo.yWrPmStats1 = readl(temp++);
1218 out->pmInfo.viewPathPmInfo.cbcrWrPmStats0 = readl(temp++);
1219 out->pmInfo.viewPathPmInfo.cbcrWrPmStats1 = readl(temp);
1220 #endif /* if 0 Jeff */
1223 static struct vfe_interrupt_status
1224 vfe_parse_interrupt_status(uint32_t irqStatusIn)
1226 struct vfe_irqenable hwstat;
1227 struct vfe_interrupt_status ret;
1230 memset(&hwstat, 0, sizeof(hwstat));
1231 memset(&ret, 0, sizeof(ret));
1233 hwstat = *((struct vfe_irqenable *)(&irqStatusIn));
1235 ret.camifErrorIrq = hwstat.camifErrorIrq;
1236 ret.camifSofIrq = hwstat.camifSofIrq;
1237 ret.camifEolIrq = hwstat.camifEolIrq;
1238 ret.camifEofIrq = hwstat.camifEofIrq;
1239 ret.camifEpoch1Irq = hwstat.camifEpoch1Irq;
1240 ret.camifEpoch2Irq = hwstat.camifEpoch2Irq;
1241 ret.camifOverflowIrq = hwstat.camifOverflowIrq;
1242 ret.ceIrq = hwstat.ceIrq;
1243 ret.regUpdateIrq = hwstat.regUpdateIrq;
1244 ret.resetAckIrq = hwstat.resetAckIrq;
1245 ret.encYPingpongIrq = hwstat.encYPingpongIrq;
1246 ret.encCbcrPingpongIrq = hwstat.encCbcrPingpongIrq;
1247 ret.viewYPingpongIrq = hwstat.viewYPingpongIrq;
1248 ret.viewCbcrPingpongIrq = hwstat.viewCbcrPingpongIrq;
1249 ret.rdPingpongIrq = hwstat.rdPingpongIrq;
1250 ret.afPingpongIrq = hwstat.afPingpongIrq;
1251 ret.awbPingpongIrq = hwstat.awbPingpongIrq;
1252 ret.histPingpongIrq = hwstat.histPingpongIrq;
1253 ret.encIrq = hwstat.encIrq;
1254 ret.viewIrq = hwstat.viewIrq;
1255 ret.busOverflowIrq = hwstat.busOverflowIrq;
1256 ret.afOverflowIrq = hwstat.afOverflowIrq;
1257 ret.awbOverflowIrq = hwstat.awbOverflowIrq;
1258 ret.syncTimer0Irq = hwstat.syncTimer0Irq;
1259 ret.syncTimer1Irq = hwstat.syncTimer1Irq;
1260 ret.syncTimer2Irq = hwstat.syncTimer2Irq;
1261 ret.asyncTimer0Irq = hwstat.asyncTimer0Irq;
1262 ret.asyncTimer1Irq = hwstat.asyncTimer1Irq;
1263 ret.asyncTimer2Irq = hwstat.asyncTimer2Irq;
1264 ret.asyncTimer3Irq = hwstat.asyncTimer3Irq;
1265 ret.axiErrorIrq = hwstat.axiErrorIrq;
1266 ret.violationIrq = hwstat.violationIrq;
1268 /* logic OR of any error bits
1269 * although each irq corresponds to a bit, the data type here is a
1270 * boolean already. hence use logic operation.
1273 ret.camifErrorIrq ||
1274 ret.camifOverflowIrq ||
1275 ret.afOverflowIrq ||
1276 ret.awbPingpongIrq ||
1277 ret.busOverflowIrq ||
1281 ret.anyErrorIrqs = temp;
1283 /* logic OR of any output path bits*/
1285 ret.encYPingpongIrq ||
1286 ret.encCbcrPingpongIrq ||
1289 ret.anyOutput2PathIrqs = temp;
1292 ret.viewYPingpongIrq ||
1293 ret.viewCbcrPingpongIrq ||
1296 ret.anyOutput1PathIrqs = temp;
1298 ret.anyOutputPathIrqs =
1299 ret.anyOutput1PathIrqs ||
1300 ret.anyOutput2PathIrqs;
1302 /* logic OR of any sync timer bits*/
1304 ret.syncTimer0Irq ||
1305 ret.syncTimer1Irq ||
1308 ret.anySyncTimerIrqs = temp;
1310 /* logic OR of any async timer bits*/
1312 ret.asyncTimer0Irq ||
1313 ret.asyncTimer1Irq ||
1314 ret.asyncTimer2Irq ||
1317 ret.anyAsyncTimerIrqs = temp;
1319 /* bool for all interrupts that are not allowed in idle state */
1322 ret.anyOutputPathIrqs ||
1323 ret.anySyncTimerIrqs ||
1325 ret.awbPingpongIrq ||
1326 ret.afPingpongIrq ||
1328 ret.camifEpoch2Irq ||
1331 ret.anyIrqForActiveStatesOnly =
1337 static struct vfe_frame_asf_info
1338 vfe_get_asf_frame_info(struct vfe_irq_thread_msg *in)
1340 struct vfe_asf_info asfInfoTemp;
1341 struct vfe_frame_asf_info rc;
1343 memset(&rc, 0, sizeof(rc));
1344 memset(&asfInfoTemp, 0, sizeof(asfInfoTemp));
1347 *((struct vfe_asf_info *)(&(in->asfMaxEdge)));
1349 rc.asfHbiCount = asfInfoTemp.HBICount;
1350 rc.asfMaxEdge = asfInfoTemp.maxEdge;
1355 static struct vfe_frame_bpc_info
1356 vfe_get_demosaic_frame_info(struct vfe_irq_thread_msg *in)
1358 struct vfe_bps_info bpcInfoTemp;
1359 struct vfe_frame_bpc_info rc;
1361 memset(&rc, 0, sizeof(rc));
1362 memset(&bpcInfoTemp, 0, sizeof(bpcInfoTemp));
1365 *((struct vfe_bps_info *)(&(in->demosaicStatus)));
1367 rc.greenDefectPixelCount =
1368 bpcInfoTemp.greenBadPixelCount;
1370 rc.redBlueDefectPixelCount =
1371 bpcInfoTemp.RedBlueBadPixelCount;
1376 static struct vfe_msg_camif_status
1377 vfe_get_camif_status(struct vfe_irq_thread_msg *in)
1379 struct vfe_camif_stats camifStatusTemp;
1380 struct vfe_msg_camif_status rc;
1382 memset(&rc, 0, sizeof(rc));
1383 memset(&camifStatusTemp, 0, sizeof(camifStatusTemp));
1386 *((struct vfe_camif_stats *)(&(in->camifStatus)));
1388 rc.camifState = (boolean)camifStatusTemp.camifHalt;
1389 rc.lineCount = camifStatusTemp.lineCount;
1390 rc.pixelCount = camifStatusTemp.pixelCount;
1395 static struct vfe_bus_performance_monitor
1396 vfe_get_performance_monitor_data(struct vfe_irq_thread_msg *in)
1398 struct vfe_bus_performance_monitor rc;
1399 memset(&rc, 0, sizeof(rc));
1401 rc.encPathPmInfo.yWrPmStats0 =
1402 in->pmInfo.encPathPmInfo.yWrPmStats0;
1403 rc.encPathPmInfo.yWrPmStats1 =
1404 in->pmInfo.encPathPmInfo.yWrPmStats1;
1405 rc.encPathPmInfo.cbcrWrPmStats0 =
1406 in->pmInfo.encPathPmInfo.cbcrWrPmStats0;
1407 rc.encPathPmInfo.cbcrWrPmStats1 =
1408 in->pmInfo.encPathPmInfo.cbcrWrPmStats1;
1409 rc.viewPathPmInfo.yWrPmStats0 =
1410 in->pmInfo.viewPathPmInfo.yWrPmStats0;
1411 rc.viewPathPmInfo.yWrPmStats1 =
1412 in->pmInfo.viewPathPmInfo.yWrPmStats1;
1413 rc.viewPathPmInfo.cbcrWrPmStats0 =
1414 in->pmInfo.viewPathPmInfo.cbcrWrPmStats0;
1415 rc.viewPathPmInfo.cbcrWrPmStats1 =
1416 in->pmInfo.viewPathPmInfo.cbcrWrPmStats1;
1421 static void vfe_process_reg_update_irq(void)
1423 CDBG("vfe_process_reg_update_irq: ackPendingFlag is %d\n",
1424 ctrl->vfeStartAckPendingFlag);
1425 if (ctrl->vfeStartAckPendingFlag == TRUE) {
1426 vfe_send_msg_no_payload(VFE_MSG_ID_START_ACK);
1427 ctrl->vfeStartAckPendingFlag = FALSE;
1429 vfe_send_msg_no_payload(VFE_MSG_ID_UPDATE_ACK);
1432 static void vfe_process_reset_irq(void)
1434 /* unsigned long flags; */
1436 /* @todo This is causing issues, need further investigate */
1437 /* spin_lock_irqsave(&ctrl->state_lock, flags); */
1438 ctrl->vstate = VFE_STATE_IDLE;
1439 /* spin_unlock_irqrestore(&ctrl->state_lock, flags); */
1441 if (ctrl->vfeStopAckPending == TRUE) {
1442 ctrl->vfeStopAckPending = FALSE;
1443 vfe_send_msg_no_payload(VFE_MSG_ID_STOP_ACK);
1445 vfe_set_default_reg_values();
1446 vfe_send_msg_no_payload(VFE_MSG_ID_RESET_ACK);
1450 static void vfe_process_pingpong_irq(struct vfe_output_path *in,
1451 uint8_t fragmentCount)
1453 uint16_t circularIndex;
1454 uint32_t nextFragmentAddr;
1456 /* get next fragment address from circular buffer */
1457 circularIndex = (in->fragIndex) % (2 * fragmentCount);
1458 nextFragmentAddr = in->addressBuffer[circularIndex];
1460 in->fragIndex = circularIndex + 1;
1462 /* use next fragment to program hardware ping/pong address. */
1463 if (in->hwCurrentFlag == ping) {
1464 writel(nextFragmentAddr, in->hwRegPingAddress);
1465 in->hwCurrentFlag = pong;
1468 writel(nextFragmentAddr, in->hwRegPongAddress);
1469 in->hwCurrentFlag = ping;
1473 static void vfe_send_output2_msg(
1474 struct vfe_msg_output *pPayload)
1476 /* unsigned long flags; */
1477 struct vfe_message *msg;
1479 msg = kzalloc(sizeof(struct vfe_message), GFP_ATOMIC);
1483 /* fill message with right content. */
1484 /* @todo This is causing issues, need further investigate */
1485 /* spin_lock_irqsave(&ctrl->state_lock, flags); */
1486 if (ctrl->vstate != VFE_STATE_ACTIVE)
1487 goto output2_msg_done;
1489 msg->_d = VFE_MSG_ID_OUTPUT2;
1491 memcpy(&(msg->_u.msgOutput2),
1492 (void *)pPayload, sizeof(struct vfe_msg_output));
1494 vfe_proc_ops(VFE_MSG_ID_OUTPUT2,
1495 msg, sizeof(struct vfe_message));
1497 ctrl->encPath.ackPending = TRUE;
1499 if (!(ctrl->vfeRequestedSnapShotCount <= 3) &&
1500 (ctrl->vfeOperationMode ==
1501 VFE_START_OPERATION_MODE_SNAPSHOT))
1502 ctrl->encPath.ackPending = TRUE;
1505 /* spin_unlock_irqrestore(&ctrl->state_lock, flags); */
1509 static void vfe_send_output1_msg(
1510 struct vfe_msg_output *pPayload)
1512 /* unsigned long flags; */
1513 struct vfe_message *msg;
1515 msg = kzalloc(sizeof(struct vfe_message), GFP_ATOMIC);
1519 /* @todo This is causing issues, need further investigate */
1520 /* spin_lock_irqsave(&ctrl->state_lock, flags); */
1521 if (ctrl->vstate != VFE_STATE_ACTIVE)
1522 goto output1_msg_done;
1524 msg->_d = VFE_MSG_ID_OUTPUT1;
1526 (void *)pPayload, sizeof(struct vfe_msg_output));
1528 vfe_proc_ops(VFE_MSG_ID_OUTPUT1,
1529 msg, sizeof(struct vfe_message));
1531 ctrl->viewPath.ackPending = TRUE;
1533 if (!(ctrl->vfeRequestedSnapShotCount <= 3) &&
1534 (ctrl->vfeOperationMode ==
1535 VFE_START_OPERATION_MODE_SNAPSHOT))
1536 ctrl->viewPath.ackPending = TRUE;
1539 /* spin_unlock_irqrestore(&ctrl->state_lock, flags); */
1543 static void vfe_send_output_msg(boolean whichOutputPath,
1544 uint32_t yPathAddr, uint32_t cbcrPathAddr)
1546 struct vfe_msg_output msgPayload;
1548 msgPayload.yBuffer = yPathAddr;
1549 msgPayload.cbcrBuffer = cbcrPathAddr;
1551 /* asf info is common for both output1 and output2 */
1553 msgPayload.asfInfo.asfHbiCount = ctrl->vfeAsfFrameInfo.asfHbiCount;
1554 msgPayload.asfInfo.asfMaxEdge = ctrl->vfeAsfFrameInfo.asfMaxEdge;
1556 /* demosaic info is common for both output1 and output2 */
1557 msgPayload.bpcInfo.greenDefectPixelCount =
1558 ctrl->vfeBpcFrameInfo.greenDefectPixelCount;
1559 msgPayload.bpcInfo.redBlueDefectPixelCount =
1560 ctrl->vfeBpcFrameInfo.redBlueDefectPixelCount;
1563 /* frame ID is common for both paths. */
1564 msgPayload.frameCounter = ctrl->vfeFrameId;
1566 if (whichOutputPath) {
1567 /* msgPayload.pmData = ctrl->vfePmData.encPathPmInfo; */
1568 vfe_send_output2_msg(&msgPayload);
1570 /* msgPayload.pmData = ctrl->vfePmData.viewPathPmInfo; */
1571 vfe_send_output1_msg(&msgPayload);
1575 static void vfe_process_frame_done_irq_multi_frag(
1576 struct vfe_output_path_combo *in)
1578 uint32_t yAddress, cbcrAddress;
1582 const uint32_t *ptrSrc;
1585 if (!in->ackPending) {
1587 idx = (in->currentFrame) * (in->fragCount);
1589 /* Send output message. */
1590 yAddress = in->yPath.addressBuffer[idx];
1591 cbcrAddress = in->cbcrPath.addressBuffer[idx];
1593 /* copy next frame to current frame. */
1594 ptrSrc = in->nextFrameAddrBuf;
1595 ptrY = (uint32_t *)&(in->yPath.addressBuffer[idx]);
1596 ptrCbcr = (uint32_t *)&(in->cbcrPath.addressBuffer[idx]);
1598 /* Copy Y address */
1599 for (i = 0; i < in->fragCount; i++)
1600 *ptrY++ = *ptrSrc++;
1602 /* Copy Cbcr address */
1603 for (i = 0; i < in->fragCount; i++)
1604 *ptrCbcr++ = *ptrSrc++;
1606 vfe_send_output_msg(in->whichOutputPath, yAddress, cbcrAddress);
1609 if (in->whichOutputPath == 0)
1610 ctrl->vfeDroppedFrameCounts.output1Count++;
1612 if (in->whichOutputPath == 1)
1613 ctrl->vfeDroppedFrameCounts.output2Count++;
1616 /* toggle current frame. */
1617 in->currentFrame = in->currentFrame^1;
1619 if (ctrl->vfeOperationMode)
1620 in->snapshotPendingCount--;
1623 static void vfe_process_frame_done_irq_no_frag_io(
1624 struct vfe_output_path_combo *in, uint32_t *pNextAddr,
1625 uint32_t *pdestRenderAddr)
1627 uint32_t busPingPongStatus;
1628 uint32_t tempAddress;
1630 /* 1. read hw status register. */
1632 readl(ctrl->vfebase + VFE_BUS_PINGPONG_STATUS);
1634 CDBG("hardware status is 0x%x\n", busPingPongStatus);
1636 /* 2. determine ping or pong */
1637 /* use cbcr status */
1638 busPingPongStatus = busPingPongStatus & (1<<(in->cbcrStatusBit));
1640 /* 3. read out address and update address */
1641 if (busPingPongStatus == 0) {
1642 /* hw is working on ping, render pong buffer */
1643 /* a. read out pong address */
1644 /* read out y address. */
1645 tempAddress = readl(in->yPath.hwRegPongAddress);
1647 CDBG("pong 1 addr = 0x%x\n", tempAddress);
1648 *pdestRenderAddr++ = tempAddress;
1649 /* read out cbcr address. */
1650 tempAddress = readl(in->cbcrPath.hwRegPongAddress);
1652 CDBG("pong 2 addr = 0x%x\n", tempAddress);
1653 *pdestRenderAddr = tempAddress;
1655 /* b. update pong address */
1656 writel(*pNextAddr++, in->yPath.hwRegPongAddress);
1657 writel(*pNextAddr, in->cbcrPath.hwRegPongAddress);
1659 /* hw is working on pong, render ping buffer */
1661 /* a. read out ping address */
1662 tempAddress = readl(in->yPath.hwRegPingAddress);
1663 CDBG("ping 1 addr = 0x%x\n", tempAddress);
1664 *pdestRenderAddr++ = tempAddress;
1665 tempAddress = readl(in->cbcrPath.hwRegPingAddress);
1667 CDBG("ping 2 addr = 0x%x\n", tempAddress);
1668 *pdestRenderAddr = tempAddress;
1670 /* b. update ping address */
1671 writel(*pNextAddr++, in->yPath.hwRegPingAddress);
1672 CDBG("NextAddress = 0x%x\n", *pNextAddr);
1673 writel(*pNextAddr, in->cbcrPath.hwRegPingAddress);
1677 static void vfe_process_frame_done_irq_no_frag(
1678 struct vfe_output_path_combo *in)
1680 uint32_t addressToRender[2];
1681 static uint32_t fcnt;
1686 if (!in->ackPending) {
1687 vfe_process_frame_done_irq_no_frag_io(in,
1688 in->nextFrameAddrBuf, addressToRender);
1690 /* use addressToRender to send out message. */
1691 vfe_send_output_msg(in->whichOutputPath,
1692 addressToRender[0], addressToRender[1]);
1695 /* ackPending is still there, accumulate dropped frame count.
1696 * These count can be read through ioctrl command. */
1697 CDBG("waiting frame ACK\n");
1699 if (in->whichOutputPath == 0)
1700 ctrl->vfeDroppedFrameCounts.output1Count++;
1702 if (in->whichOutputPath == 1)
1703 ctrl->vfeDroppedFrameCounts.output2Count++;
1706 /* in case of multishot when upper layer did not ack, there will still
1707 * be a snapshot done msg sent out, even though the number of frames
1708 * sent out may be less than the desired number of frames. snapshot
1709 * done msg would be helpful to indicate that vfe pipeline has stop,
1710 * and in good known state.
1712 if (ctrl->vfeOperationMode)
1713 in->snapshotPendingCount--;
1716 static void vfe_process_output_path_irq(
1717 struct vfe_interrupt_status *irqstatus)
1719 /* unsigned long flags; */
1721 /* process the view path interrupts */
1722 if (irqstatus->anyOutput1PathIrqs) {
1723 if (ctrl->viewPath.multiFrag) {
1725 if (irqstatus->viewCbcrPingpongIrq)
1726 vfe_process_pingpong_irq(
1727 &(ctrl->viewPath.cbcrPath),
1728 ctrl->viewPath.fragCount);
1730 if (irqstatus->viewYPingpongIrq)
1731 vfe_process_pingpong_irq(
1732 &(ctrl->viewPath.yPath),
1733 ctrl->viewPath.fragCount);
1735 if (irqstatus->viewIrq)
1736 vfe_process_frame_done_irq_multi_frag(
1740 /* typical case for no fragment,
1741 only frame done irq is enabled. */
1742 if (irqstatus->viewIrq)
1743 vfe_process_frame_done_irq_no_frag(
1748 /* process the encoder path interrupts */
1749 if (irqstatus->anyOutput2PathIrqs) {
1750 if (ctrl->encPath.multiFrag) {
1751 if (irqstatus->encCbcrPingpongIrq)
1752 vfe_process_pingpong_irq(
1753 &(ctrl->encPath.cbcrPath),
1754 ctrl->encPath.fragCount);
1756 if (irqstatus->encYPingpongIrq)
1757 vfe_process_pingpong_irq(&(ctrl->encPath.yPath),
1758 ctrl->encPath.fragCount);
1760 if (irqstatus->encIrq)
1761 vfe_process_frame_done_irq_multi_frag(
1765 if (irqstatus->encIrq)
1766 vfe_process_frame_done_irq_no_frag(
1771 if (ctrl->vfeOperationMode) {
1772 if ((ctrl->encPath.snapshotPendingCount == 0) &&
1773 (ctrl->viewPath.snapshotPendingCount == 0)) {
1775 /* @todo This is causing issues, further investigate */
1776 /* spin_lock_irqsave(&ctrl->state_lock, flags); */
1777 ctrl->vstate = VFE_STATE_IDLE;
1778 /* spin_unlock_irqrestore(&ctrl->state_lock, flags); */
1780 vfe_send_msg_no_payload(VFE_MSG_ID_SNAPSHOT_DONE);
1781 vfe_prog_hw_testgen_cmd(VFE_TEST_GEN_STOP);
1787 static void vfe_do_tasklet(unsigned long data)
1789 unsigned long flags;
1791 struct isr_queue_cmd *qcmd = NULL;
1793 CDBG("=== vfe_do_tasklet start === \n");
1795 spin_lock_irqsave(&ctrl->tasklet_lock, flags);
1796 qcmd = list_first_entry(&ctrl->tasklet_q,
1797 struct isr_queue_cmd, list);
1800 spin_unlock_irqrestore(&ctrl->tasklet_lock, flags);
1804 list_del(&qcmd->list);
1805 spin_unlock_irqrestore(&ctrl->tasklet_lock, flags);
1807 if (qcmd->vfeInterruptStatus.regUpdateIrq) {
1808 CDBG("irq regUpdateIrq\n");
1809 vfe_process_reg_update_irq();
1812 if (qcmd->vfeInterruptStatus.resetAckIrq) {
1813 CDBG("irq resetAckIrq\n");
1814 vfe_process_reset_irq();
1817 spin_lock_irqsave(&ctrl->state_lock, flags);
1818 if (ctrl->vstate != VFE_STATE_ACTIVE) {
1819 spin_unlock_irqrestore(&ctrl->state_lock, flags);
1822 spin_unlock_irqrestore(&ctrl->state_lock, flags);
1825 if (qcmd->vfeInterruptStatus.camifEpoch1Irq)
1826 vfe_send_msg_no_payload(VFE_MSG_ID_EPOCH1);
1828 if (qcmd->vfeInterruptStatus.camifEpoch2Irq)
1829 vfe_send_msg_no_payload(VFE_MSG_ID_EPOCH2);
1832 /* next, check output path related interrupts. */
1833 if (qcmd->vfeInterruptStatus.anyOutputPathIrqs) {
1834 CDBG("irq anyOutputPathIrqs\n");
1835 vfe_process_output_path_irq(&qcmd->vfeInterruptStatus);
1838 if (qcmd->vfeInterruptStatus.afPingpongIrq)
1839 vfe_process_stats_af_irq();
1841 if (qcmd->vfeInterruptStatus.awbPingpongIrq)
1842 vfe_process_stats_awb_irq();
1845 if (qcmd->vfeInterruptStatus.anyErrorIrqs)
1846 vfe_process_error_irq(&qcmd->vfeInterruptStatus);
1849 if (qcmd->vfeInterruptStatus.anySyncTimerIrqs)
1850 vfe_process_sync_timer_irq();
1852 if (qcmd->vfeInterruptStatus.anyAsyncTimerIrqs)
1853 vfe_process_async_timer_irq();
1856 if (qcmd->vfeInterruptStatus.camifSofIrq) {
1857 CDBG("irq camifSofIrq\n");
1858 vfe_process_camif_sof_irq();
1862 CDBG("=== vfe_do_tasklet end === \n");
1865 DECLARE_TASKLET(vfe_tasklet, vfe_do_tasklet, 0);
1867 static irqreturn_t vfe_parse_irq(int irq_num, void *data)
1869 unsigned long flags;
1870 uint32_t irqStatusLocal;
1871 struct vfe_irq_thread_msg irq;
1872 struct isr_queue_cmd *qcmd;
1874 CDBG("vfe_parse_irq\n");
1876 vfe_read_irq_status(&irq);
1878 if (irq.vfeIrqStatus == 0) {
1879 CDBG("vfe_parse_irq: irq.vfeIrqStatus is 0\n");
1883 qcmd = kzalloc(sizeof(struct isr_queue_cmd),
1886 CDBG("vfe_parse_irq: qcmd malloc failed!\n");
1890 spin_lock_irqsave(&ctrl->ack_lock, flags);
1892 if (ctrl->vfeStopAckPending)
1894 (VFE_IMASK_WHILE_STOPPING & irq.vfeIrqStatus);
1897 ((ctrl->vfeImaskPacked | VFE_IMASK_ERROR_ONLY) &
1900 spin_unlock_irqrestore(&ctrl->ack_lock, flags);
1902 /* first parse the interrupt status to local data structures. */
1903 qcmd->vfeInterruptStatus = vfe_parse_interrupt_status(irqStatusLocal);
1904 qcmd->vfeAsfFrameInfo = vfe_get_asf_frame_info(&irq);
1905 qcmd->vfeBpcFrameInfo = vfe_get_demosaic_frame_info(&irq);
1906 qcmd->vfeCamifStatusLocal = vfe_get_camif_status(&irq);
1907 qcmd->vfePmData = vfe_get_performance_monitor_data(&irq);
1909 spin_lock_irqsave(&ctrl->tasklet_lock, flags);
1910 list_add_tail(&qcmd->list, &ctrl->tasklet_q);
1911 spin_unlock_irqrestore(&ctrl->tasklet_lock, flags);
1912 tasklet_schedule(&vfe_tasklet);
1914 /* clear the pending interrupt of the same kind.*/
1915 writel(irq.vfeIrqStatus, ctrl->vfebase + VFE_IRQ_CLEAR);
1920 int vfe_cmd_init(struct msm_vfe_callback *presp,
1921 struct platform_device *pdev, void *sdata)
1923 struct resource *vfemem, *vfeirq, *vfeio;
1926 vfemem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1928 CDBG("no mem resource?\n");
1932 vfeirq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
1934 CDBG("no irq resource?\n");
1938 vfeio = request_mem_region(vfemem->start,
1939 resource_size(vfemem), pdev->name);
1941 CDBG("VFE region already claimed\n");
1946 kzalloc(sizeof(struct msm_vfe8x_ctrl), GFP_KERNEL);
1949 goto cmd_init_failed1;
1952 ctrl->vfeirq = vfeirq->start;
1955 ioremap(vfemem->start, (vfemem->end - vfemem->start) + 1);
1956 if (!ctrl->vfebase) {
1958 goto cmd_init_failed2;
1961 rc = request_irq(ctrl->vfeirq, vfe_parse_irq,
1962 IRQF_TRIGGER_RISING, "vfe", 0);
1964 goto cmd_init_failed2;
1966 if (presp && presp->vfe_resp)
1970 goto cmd_init_failed3;
1974 kmalloc(sizeof(struct vfe_frame_extra), GFP_KERNEL);
1975 if (!ctrl->extdata) {
1977 goto cmd_init_failed3;
1980 spin_lock_init(&ctrl->ack_lock);
1981 spin_lock_init(&ctrl->state_lock);
1982 spin_lock_init(&ctrl->io_lock);
1984 ctrl->extlen = sizeof(struct vfe_frame_extra);
1986 spin_lock_init(&ctrl->tasklet_lock);
1987 INIT_LIST_HEAD(&ctrl->tasklet_q);
1989 ctrl->syncdata = sdata;
1993 disable_irq(ctrl->vfeirq);
1994 free_irq(ctrl->vfeirq, 0);
1995 iounmap(ctrl->vfebase);
1999 release_mem_region(vfemem->start, (vfemem->end - vfemem->start) + 1);
2003 void vfe_cmd_release(struct platform_device *dev)
2005 struct resource *mem;
2007 disable_irq(ctrl->vfeirq);
2008 free_irq(ctrl->vfeirq, 0);
2010 iounmap(ctrl->vfebase);
2011 mem = platform_get_resource(dev, IORESOURCE_MEM, 0);
2012 release_mem_region(mem->start, (mem->end - mem->start) + 1);
2016 kfree(ctrl->extdata);
2020 void vfe_stats_af_stop(void)
2022 ctrl->vfeStatsCmdLocal.autoFocusEnable = FALSE;
2023 ctrl->vfeImaskLocal.afPingpongIrq = FALSE;
2029 uint32_t vfeAxiStauts;
2031 /* for reset hw modules, and send msg when reset_irq comes.*/
2032 ctrl->vfeStopAckPending = TRUE;
2034 ctrl->vfeStatsPingPongReloadFlag = FALSE;
2037 /* disable all interrupts. */
2038 vfe_program_irq_mask(VFE_DISABLE_ALL_IRQS);
2040 /* in either continuous or snapshot mode, stop command can be issued
2043 vfe_camif_stop_immediately();
2044 vfe_program_axi_cmd(AXI_HALT);
2045 vfe_prog_hw_testgen_cmd(VFE_TEST_GEN_STOP);
2049 while (vfeAxiBusy) {
2050 vfeAxiStauts = vfe_read_axi_status();
2051 if ((vfeAxiStauts & AXI_STATUS_BUSY_MASK) != 0)
2055 vfe_program_axi_cmd(AXI_HALT_CLEAR);
2057 /* clear all pending interrupts */
2058 writel(VFE_CLEAR_ALL_IRQS, ctrl->vfebase + VFE_IRQ_CLEAR);
2060 /* enable reset_ack and async timer interrupt only while stopping
2063 vfe_program_irq_mask(VFE_IMASK_WHILE_STOPPING);
2065 vfe_program_global_reset_cmd(VFE_RESET_UPON_STOP_CMD);
2068 void vfe_update(void)
2070 ctrl->vfeModuleEnableLocal.statsEnable =
2071 ctrl->vfeStatsCmdLocal.autoFocusEnable |
2072 ctrl->vfeStatsCmdLocal.axwEnable;
2074 vfe_reg_module_cfg(&ctrl->vfeModuleEnableLocal);
2076 vfe_program_stats_cmd(&ctrl->vfeStatsCmdLocal);
2078 ctrl->vfeImaskPacked = vfe_irq_pack(ctrl->vfeImaskLocal);
2079 vfe_program_irq_mask(ctrl->vfeImaskPacked);
2081 if ((ctrl->vfeModuleEnableLocal.statsEnable == TRUE) &&
2082 (ctrl->vfeStatsPingPongReloadFlag == FALSE)) {
2083 ctrl->vfeStatsPingPongReloadFlag = TRUE;
2085 ctrl->vfeBusCmdLocal.statsPingpongReload = TRUE;
2086 vfe_reg_bus_cmd(&ctrl->vfeBusCmdLocal);
2089 vfe_program_reg_update_cmd(VFE_REG_UPDATE_TRIGGER);
2092 int vfe_rgb_gamma_update(struct vfe_cmd_rgb_gamma_config *in)
2096 ctrl->vfeModuleEnableLocal.rgbLUTEnable = in->enable;
2098 switch (in->channelSelect) {
2099 case RGB_GAMMA_CH0_SELECTED:
2100 ctrl->vfeGammaLutSel.ch0BankSelect ^= 1;
2101 vfe_write_gamma_table(0,
2102 ctrl->vfeGammaLutSel.ch0BankSelect, in->table);
2105 case RGB_GAMMA_CH1_SELECTED:
2106 ctrl->vfeGammaLutSel.ch1BankSelect ^= 1;
2107 vfe_write_gamma_table(1,
2108 ctrl->vfeGammaLutSel.ch1BankSelect, in->table);
2111 case RGB_GAMMA_CH2_SELECTED:
2112 ctrl->vfeGammaLutSel.ch2BankSelect ^= 1;
2113 vfe_write_gamma_table(2,
2114 ctrl->vfeGammaLutSel.ch2BankSelect, in->table);
2117 case RGB_GAMMA_CH0_CH1_SELECTED:
2118 ctrl->vfeGammaLutSel.ch0BankSelect ^= 1;
2119 ctrl->vfeGammaLutSel.ch1BankSelect ^= 1;
2120 vfe_write_gamma_table(0, ctrl->vfeGammaLutSel.ch0BankSelect,
2122 vfe_write_gamma_table(1, ctrl->vfeGammaLutSel.ch1BankSelect,
2126 case RGB_GAMMA_CH0_CH2_SELECTED:
2127 ctrl->vfeGammaLutSel.ch0BankSelect ^= 1;
2128 ctrl->vfeGammaLutSel.ch2BankSelect ^= 1;
2129 vfe_write_gamma_table(0, ctrl->vfeGammaLutSel.ch0BankSelect,
2131 vfe_write_gamma_table(2, ctrl->vfeGammaLutSel.ch2BankSelect,
2135 case RGB_GAMMA_CH1_CH2_SELECTED:
2136 ctrl->vfeGammaLutSel.ch1BankSelect ^= 1;
2137 ctrl->vfeGammaLutSel.ch2BankSelect ^= 1;
2138 vfe_write_gamma_table(1, ctrl->vfeGammaLutSel.ch1BankSelect,
2140 vfe_write_gamma_table(2, ctrl->vfeGammaLutSel.ch2BankSelect,
2144 case RGB_GAMMA_CH0_CH1_CH2_SELECTED:
2145 ctrl->vfeGammaLutSel.ch0BankSelect ^= 1;
2146 ctrl->vfeGammaLutSel.ch1BankSelect ^= 1;
2147 ctrl->vfeGammaLutSel.ch2BankSelect ^= 1;
2148 vfe_write_gamma_table(0, ctrl->vfeGammaLutSel.ch0BankSelect,
2150 vfe_write_gamma_table(1, ctrl->vfeGammaLutSel.ch1BankSelect,
2152 vfe_write_gamma_table(2, ctrl->vfeGammaLutSel.ch2BankSelect,
2160 /* update the gammaLutSel register. */
2161 vfe_program_lut_bank_sel(&ctrl->vfeGammaLutSel);
2166 int vfe_rgb_gamma_config(struct vfe_cmd_rgb_gamma_config *in)
2170 ctrl->vfeModuleEnableLocal.rgbLUTEnable = in->enable;
2172 switch (in->channelSelect) {
2173 case RGB_GAMMA_CH0_SELECTED:
2174 vfe_write_gamma_table(0, 0, in->table);
2177 case RGB_GAMMA_CH1_SELECTED:
2178 vfe_write_gamma_table(1, 0, in->table);
2181 case RGB_GAMMA_CH2_SELECTED:
2182 vfe_write_gamma_table(2, 0, in->table);
2185 case RGB_GAMMA_CH0_CH1_SELECTED:
2186 vfe_write_gamma_table(0, 0, in->table);
2187 vfe_write_gamma_table(1, 0, in->table);
2190 case RGB_GAMMA_CH0_CH2_SELECTED:
2191 vfe_write_gamma_table(0, 0, in->table);
2192 vfe_write_gamma_table(2, 0, in->table);
2195 case RGB_GAMMA_CH1_CH2_SELECTED:
2196 vfe_write_gamma_table(1, 0, in->table);
2197 vfe_write_gamma_table(2, 0, in->table);
2200 case RGB_GAMMA_CH0_CH1_CH2_SELECTED:
2201 vfe_write_gamma_table(0, 0, in->table);
2202 vfe_write_gamma_table(1, 0, in->table);
2203 vfe_write_gamma_table(2, 0, in->table);
2214 void vfe_stats_af_ack(struct vfe_cmd_stats_af_ack *in)
2216 ctrl->afStatsControl.nextFrameAddrBuf = in->nextAFOutputBufferAddr;
2217 ctrl->afStatsControl.ackPending = FALSE;
2220 void vfe_stats_wb_exp_ack(struct vfe_cmd_stats_wb_exp_ack *in)
2222 ctrl->awbStatsControl.nextFrameAddrBuf = in->nextWbExpOutputBufferAddr;
2223 ctrl->awbStatsControl.ackPending = FALSE;
2226 void vfe_output2_ack(struct vfe_cmd_output_ack *in)
2228 const uint32_t *psrc;
2232 pdest = ctrl->encPath.nextFrameAddrBuf;
2234 CDBG("output2_ack: ack addr = 0x%x\n", in->ybufaddr[0]);
2236 psrc = in->ybufaddr;
2237 for (i = 0; i < ctrl->encPath.fragCount; i++)
2240 psrc = in->chromabufaddr;
2241 for (i = 0; i < ctrl->encPath.fragCount; i++)
2244 ctrl->encPath.ackPending = FALSE;
2247 void vfe_output1_ack(struct vfe_cmd_output_ack *in)
2249 const uint32_t *psrc;
2253 pdest = ctrl->viewPath.nextFrameAddrBuf;
2255 psrc = in->ybufaddr;
2256 for (i = 0; i < ctrl->viewPath.fragCount; i++)
2259 psrc = in->chromabufaddr;
2260 for (i = 0; i < ctrl->viewPath.fragCount; i++)
2263 ctrl->viewPath.ackPending = FALSE;
2266 void vfe_start(struct vfe_cmd_start *in)
2268 unsigned long flags;
2269 uint32_t pmstatus = 0;
2271 uint32_t demperiod = 0;
2272 uint32_t demeven = 0;
2273 uint32_t demodd = 0;
2275 /* derived from other commands. (camif config, axi output config,
2278 struct vfe_cfg hwcfg;
2279 struct vfe_upsample_cfg chromupcfg;
2281 CDBG("vfe_start operationMode = %d\n", in->operationMode);
2283 memset(&hwcfg, 0, sizeof(hwcfg));
2284 memset(&chromupcfg, 0, sizeof(chromupcfg));
2286 switch (in->pixel) {
2287 case VFE_BAYER_RGRGRG:
2293 case VFE_BAYER_GRGRGR:
2299 case VFE_BAYER_BGBGBG:
2305 case VFE_BAYER_GBGBGB:
2311 case VFE_YUV_YCbYCr:
2317 case VFE_YUV_YCrYCb:
2323 case VFE_YUV_CbYCrY:
2329 case VFE_YUV_CrYCbY:
2339 vfe_config_demux(demperiod, demeven, demodd);
2341 vfe_program_lut_bank_sel(&ctrl->vfeGammaLutSel);
2343 /* save variables to local. */
2344 ctrl->vfeOperationMode = in->operationMode;
2345 if (ctrl->vfeOperationMode ==
2346 VFE_START_OPERATION_MODE_SNAPSHOT) {
2347 /* in snapshot mode, initialize snapshot count*/
2348 ctrl->vfeSnapShotCount = in->snapshotCount;
2350 /* save the requested count, this is temporarily done, to
2351 help with HJR / multishot. */
2352 ctrl->vfeRequestedSnapShotCount = ctrl->vfeSnapShotCount;
2354 CDBG("requested snapshot count = %d\n", ctrl->vfeSnapShotCount);
2356 /* Assumption is to have the same pattern and period for both
2357 paths, if both paths are used. */
2358 if (ctrl->viewPath.pathEnabled) {
2359 ctrl->viewPath.snapshotPendingCount =
2362 ctrl->vfeFrameSkipPattern =
2363 ctrl->vfeFrameSkip.output1Pattern;
2364 ctrl->vfeFrameSkipPeriod =
2365 ctrl->vfeFrameSkip.output1Period;
2368 if (ctrl->encPath.pathEnabled) {
2369 ctrl->encPath.snapshotPendingCount =
2372 ctrl->vfeFrameSkipPattern =
2373 ctrl->vfeFrameSkip.output2Pattern;
2374 ctrl->vfeFrameSkipPeriod =
2375 ctrl->vfeFrameSkip.output2Period;
2379 /* enable color conversion for bayer sensor
2380 if stats enabled, need to do color conversion. */
2381 if (in->pixel <= VFE_BAYER_GBGBGB)
2382 ctrl->vfeStatsCmdLocal.colorConversionEnable = TRUE;
2384 vfe_program_stats_cmd(&ctrl->vfeStatsCmdLocal);
2386 if (in->pixel >= VFE_YUV_YCbYCr)
2387 ctrl->vfeModuleEnableLocal.chromaUpsampleEnable = TRUE;
2389 ctrl->vfeModuleEnableLocal.demuxEnable = TRUE;
2391 /* if any stats module is enabled, the main bit is enabled. */
2392 ctrl->vfeModuleEnableLocal.statsEnable =
2393 ctrl->vfeStatsCmdLocal.autoFocusEnable |
2394 ctrl->vfeStatsCmdLocal.axwEnable;
2396 vfe_reg_module_cfg(&ctrl->vfeModuleEnableLocal);
2398 /* in case of offline processing, do not need to config camif. Having
2399 * bus output enabled in camif_config register might confuse the
2402 if (in->inputSource != VFE_START_INPUT_SOURCE_AXI) {
2403 vfe_reg_camif_config(&ctrl->vfeCamifConfigLocal);
2405 /* offline processing, enable axi read */
2406 ctrl->vfeBusConfigLocal.stripeRdPathEn = TRUE;
2407 ctrl->vfeBusCmdLocal.stripeReload = TRUE;
2408 ctrl->vfeBusConfigLocal.rawPixelDataSize =
2409 ctrl->axiInputDataSize;
2412 vfe_reg_bus_cfg(&ctrl->vfeBusConfigLocal);
2414 /* directly from start command */
2415 hwcfg.pixelPattern = in->pixel;
2416 hwcfg.inputSource = in->inputSource;
2417 writel(*(uint32_t *)&hwcfg, ctrl->vfebase + VFE_CFG);
2419 /* regardless module enabled or not, it does not hurt
2420 * to program the cositing mode. */
2421 chromupcfg.chromaCositingForYCbCrInputs =
2422 in->yuvInputCositingMode;
2424 writel(*(uint32_t *)&(chromupcfg),
2425 ctrl->vfebase + VFE_CHROMA_UPSAMPLE_CFG);
2427 /* MISR to monitor the axi read. */
2428 writel(0xd8, ctrl->vfebase + VFE_BUS_MISR_MAST_CFG_0);
2430 /* clear all pending interrupts. */
2431 writel(VFE_CLEAR_ALL_IRQS, ctrl->vfebase + VFE_IRQ_CLEAR);
2433 /* define how composite interrupt work. */
2434 ctrl->vfeImaskCompositePacked =
2435 vfe_irq_composite_pack(ctrl->vfeIrqCompositeMaskLocal);
2437 vfe_program_irq_composite_mask(ctrl->vfeImaskCompositePacked);
2439 /* enable all necessary interrupts. */
2440 ctrl->vfeImaskLocal.camifSofIrq = TRUE;
2441 ctrl->vfeImaskLocal.regUpdateIrq = TRUE;
2442 ctrl->vfeImaskLocal.resetAckIrq = TRUE;
2444 ctrl->vfeImaskPacked = vfe_irq_pack(ctrl->vfeImaskLocal);
2445 vfe_program_irq_mask(ctrl->vfeImaskPacked);
2447 /* enable bus performance monitor */
2448 vfe_8k_pm_start(&ctrl->vfeBusPmConfigLocal);
2450 /* trigger vfe reg update */
2451 ctrl->vfeStartAckPendingFlag = TRUE;
2453 /* write bus command to trigger reload of ping pong buffer. */
2454 ctrl->vfeBusCmdLocal.busPingpongReload = TRUE;
2456 if (ctrl->vfeModuleEnableLocal.statsEnable == TRUE) {
2457 ctrl->vfeBusCmdLocal.statsPingpongReload = TRUE;
2458 ctrl->vfeStatsPingPongReloadFlag = TRUE;
2461 writel(VFE_REG_UPDATE_TRIGGER,
2462 ctrl->vfebase + VFE_REG_UPDATE_CMD);
2464 /* program later than the reg update. */
2465 vfe_reg_bus_cmd(&ctrl->vfeBusCmdLocal);
2467 if ((in->inputSource ==
2468 VFE_START_INPUT_SOURCE_CAMIF) ||
2470 VFE_START_INPUT_SOURCE_TESTGEN))
2471 writel(CAMIF_COMMAND_START, ctrl->vfebase + CAMIF_COMMAND);
2473 /* start test gen if it is enabled */
2474 if (ctrl->vfeTestGenStartFlag == TRUE) {
2475 ctrl->vfeTestGenStartFlag = FALSE;
2476 vfe_prog_hw_testgen_cmd(VFE_TEST_GEN_GO);
2479 CDBG("ctrl->axiOutputMode = %d\n", ctrl->axiOutputMode);
2480 if (ctrl->axiOutputMode == VFE_AXI_OUTPUT_MODE_CAMIFToAXIViaOutput2) {
2486 readl(ctrl->vfebase +
2487 VFE_BUS_ENC_CBCR_WR_PM_STATS_1);
2489 if ((pmstatus & VFE_PM_BUF_MAX_CNT_MASK) != 0)
2493 vfe_send_msg_no_payload(VFE_MSG_ID_START_ACK);
2494 ctrl->vfeStartAckPendingFlag = FALSE;
2497 spin_lock_irqsave(&ctrl->state_lock, flags);
2498 ctrl->vstate = VFE_STATE_ACTIVE;
2499 spin_unlock_irqrestore(&ctrl->state_lock, flags);
2502 void vfe_la_update(struct vfe_cmd_la_config *in)
2505 enum VFE_DMI_RAM_SEL dmiRamSel;
2509 ctrl->vfeModuleEnableLocal.lumaAdaptationEnable = in->enable;
2511 /* toggle the bank to be used. */
2512 ctrl->vfeLaBankSel ^= 1;
2514 if (ctrl->vfeLaBankSel == 0)
2515 dmiRamSel = LUMA_ADAPT_LUT_RAM_BANK0;
2517 dmiRamSel = LUMA_ADAPT_LUT_RAM_BANK1;
2519 /* configure the DMI_CFG to select right sram */
2520 vfe_program_dmi_cfg(dmiRamSel);
2522 for (i = 0; i < VFE_LA_TABLE_LENGTH; i++) {
2523 writel((uint32_t)(*pTable), ctrl->vfebase + VFE_DMI_DATA_LO);
2527 /* After DMI transfer, to make it safe, need to set
2528 * the DMI_CFG to unselect any SRAM */
2529 writel(VFE_DMI_CFG_DEFAULT, ctrl->vfebase + VFE_DMI_CFG);
2530 writel(ctrl->vfeLaBankSel, ctrl->vfebase + VFE_LA_CFG);
2533 void vfe_la_config(struct vfe_cmd_la_config *in)
2537 enum VFE_DMI_RAM_SEL dmiRamSel;
2540 ctrl->vfeModuleEnableLocal.lumaAdaptationEnable = in->enable;
2542 if (ctrl->vfeLaBankSel == 0)
2543 dmiRamSel = LUMA_ADAPT_LUT_RAM_BANK0;
2545 dmiRamSel = LUMA_ADAPT_LUT_RAM_BANK1;
2547 /* configure the DMI_CFG to select right sram */
2548 vfe_program_dmi_cfg(dmiRamSel);
2550 for (i = 0; i < VFE_LA_TABLE_LENGTH; i++) {
2551 writel((uint32_t)(*pTable), ctrl->vfebase + VFE_DMI_DATA_LO);
2555 /* After DMI transfer, to make it safe, need to set the
2556 * DMI_CFG to unselect any SRAM */
2557 writel(VFE_DMI_CFG_DEFAULT, ctrl->vfebase + VFE_DMI_CFG);
2559 /* can only be bank 0 or bank 1 for now. */
2560 writel(ctrl->vfeLaBankSel, ctrl->vfebase + VFE_LA_CFG);
2561 CDBG("VFE Luma adaptation bank selection is 0x%x\n",
2562 *(uint32_t *)&ctrl->vfeLaBankSel);
2565 void vfe_test_gen_start(struct vfe_cmd_test_gen_start *in)
2567 struct VFE_TestGen_ConfigCmdType cmd;
2569 memset(&cmd, 0, sizeof(cmd));
2571 cmd.numFrame = in->numFrame;
2572 cmd.pixelDataSelect = in->pixelDataSelect;
2573 cmd.systematicDataSelect = in->systematicDataSelect;
2574 cmd.pixelDataSize = (uint32_t)in->pixelDataSize;
2575 cmd.hsyncEdge = (uint32_t)in->hsyncEdge;
2576 cmd.vsyncEdge = (uint32_t)in->vsyncEdge;
2577 cmd.imageWidth = in->imageWidth;
2578 cmd.imageHeight = in->imageHeight;
2579 cmd.sofOffset = in->startOfFrameOffset;
2580 cmd.eofNOffset = in->endOfFrameNOffset;
2581 cmd.solOffset = in->startOfLineOffset;
2582 cmd.eolNOffset = in->endOfLineNOffset;
2583 cmd.hBlankInterval = in->hbi;
2584 cmd.vBlankInterval = in->vbl;
2585 cmd.vBlankIntervalEnable = in->vblEnable;
2586 cmd.sofDummy = in->startOfFrameDummyLine;
2587 cmd.eofDummy = in->endOfFrameDummyLine;
2588 cmd.unicolorBarSelect = in->unicolorBarSelect;
2589 cmd.unicolorBarEnable = in->unicolorBarEnable;
2590 cmd.splitEnable = in->colorBarsSplitEnable;
2591 cmd.pixelPattern = (uint32_t)in->colorBarsPixelPattern;
2592 cmd.rotatePeriod = in->colorBarsRotatePeriod;
2593 cmd.randomSeed = in->testGenRandomSeed;
2595 vfe_prog_hw(ctrl->vfebase + VFE_HW_TESTGEN_CFG,
2596 (uint32_t *) &cmd, sizeof(cmd));
2599 void vfe_frame_skip_update(struct vfe_cmd_frame_skip_update *in)
2601 struct VFE_FRAME_SKIP_UpdateCmdType cmd;
2603 cmd.yPattern = in->output1Pattern;
2604 cmd.cbcrPattern = in->output1Pattern;
2605 vfe_prog_hw(ctrl->vfebase + VFE_FRAMEDROP_VIEW_Y_PATTERN,
2606 (uint32_t *)&cmd, sizeof(cmd));
2608 cmd.yPattern = in->output2Pattern;
2609 cmd.cbcrPattern = in->output2Pattern;
2610 vfe_prog_hw(ctrl->vfebase + VFE_FRAMEDROP_ENC_Y_PATTERN,
2611 (uint32_t *)&cmd, sizeof(cmd));
2614 void vfe_frame_skip_config(struct vfe_cmd_frame_skip_config *in)
2616 struct vfe_frame_skip_cfg cmd;
2617 memset(&cmd, 0, sizeof(cmd));
2619 ctrl->vfeFrameSkip = *in;
2621 cmd.output2YPeriod = in->output2Period;
2622 cmd.output2CbCrPeriod = in->output2Period;
2623 cmd.output2YPattern = in->output2Pattern;
2624 cmd.output2CbCrPattern = in->output2Pattern;
2625 cmd.output1YPeriod = in->output1Period;
2626 cmd.output1CbCrPeriod = in->output1Period;
2627 cmd.output1YPattern = in->output1Pattern;
2628 cmd.output1CbCrPattern = in->output1Pattern;
2630 vfe_prog_hw(ctrl->vfebase + VFE_FRAMEDROP_ENC_Y_CFG,
2631 (uint32_t *)&cmd, sizeof(cmd));
2634 void vfe_output_clamp_config(struct vfe_cmd_output_clamp_config *in)
2636 struct vfe_output_clamp_cfg cmd;
2637 memset(&cmd, 0, sizeof(cmd));
2639 cmd.yChanMax = in->maxCh0;
2640 cmd.cbChanMax = in->maxCh1;
2641 cmd.crChanMax = in->maxCh2;
2643 cmd.yChanMin = in->minCh0;
2644 cmd.cbChanMin = in->minCh1;
2645 cmd.crChanMin = in->minCh2;
2647 vfe_prog_hw(ctrl->vfebase + VFE_CLAMP_MAX_CFG, (uint32_t *)&cmd,
2651 void vfe_camif_frame_update(struct vfe_cmds_camif_frame *in)
2653 struct vfe_camifframe_update cmd;
2655 memset(&cmd, 0, sizeof(cmd));
2657 cmd.pixelsPerLine = in->pixelsPerLine;
2658 cmd.linesPerFrame = in->linesPerFrame;
2660 vfe_prog_hw(ctrl->vfebase + CAMIF_FRAME_CONFIG, (uint32_t *)&cmd,
2664 void vfe_color_correction_config(
2665 struct vfe_cmd_color_correction_config *in)
2667 struct vfe_color_correction_cfg cmd;
2669 memset(&cmd, 0, sizeof(cmd));
2670 ctrl->vfeModuleEnableLocal.colorCorrectionEnable = in->enable;
2686 cmd.coefQFactor = in->coefQFactor;
2688 vfe_prog_hw(ctrl->vfebase + VFE_COLOR_CORRECT_COEFF_0,
2689 (uint32_t *)&cmd, sizeof(cmd));
2692 void vfe_demosaic_abf_update(struct vfe_cmd_demosaic_abf_update *in)
2694 struct vfe_demosaic_cfg cmd;
2695 struct vfe_demosaic_abf_cfg cmdabf;
2698 memset(&cmd, 0, sizeof(cmd));
2699 temp = readl(ctrl->vfebase + VFE_DEMOSAIC_CFG);
2701 cmd = *((struct vfe_demosaic_cfg *)(&temp));
2702 cmd.abfEnable = in->abfUpdate.enable;
2703 cmd.forceAbfOn = in->abfUpdate.forceOn;
2704 cmd.abfShift = in->abfUpdate.shift;
2705 vfe_prog_hw(ctrl->vfebase + VFE_DEMOSAIC_CFG,
2706 (uint32_t *)&cmd, sizeof(cmd));
2708 cmdabf.lpThreshold = in->abfUpdate.lpThreshold;
2709 cmdabf.ratio = in->abfUpdate.ratio;
2710 cmdabf.minValue = in->abfUpdate.min;
2711 cmdabf.maxValue = in->abfUpdate.max;
2712 vfe_prog_hw(ctrl->vfebase + VFE_DEMOSAIC_ABF_CFG_0,
2713 (uint32_t *)&cmdabf, sizeof(cmdabf));
2716 void vfe_demosaic_bpc_update(struct vfe_cmd_demosaic_bpc_update *in)
2718 struct vfe_demosaic_cfg cmd;
2719 struct vfe_demosaic_bpc_cfg cmdbpc;
2722 memset(&cmd, 0, sizeof(cmd));
2724 temp = readl(ctrl->vfebase + VFE_DEMOSAIC_CFG);
2726 cmd = *((struct vfe_demosaic_cfg *)(&temp));
2727 cmd.badPixelCorrEnable = in->bpcUpdate.enable;
2728 cmd.fminThreshold = in->bpcUpdate.fminThreshold;
2729 cmd.fmaxThreshold = in->bpcUpdate.fmaxThreshold;
2731 vfe_prog_hw(ctrl->vfebase + VFE_DEMOSAIC_CFG,
2732 (uint32_t *)&cmd, sizeof(cmd));
2734 cmdbpc.blueDiffThreshold = in->bpcUpdate.blueDiffThreshold;
2735 cmdbpc.redDiffThreshold = in->bpcUpdate.redDiffThreshold;
2736 cmdbpc.greenDiffThreshold = in->bpcUpdate.greenDiffThreshold;
2738 vfe_prog_hw(ctrl->vfebase + VFE_DEMOSAIC_BPC_CFG_0,
2739 (uint32_t *)&cmdbpc, sizeof(cmdbpc));
2742 void vfe_demosaic_config(struct vfe_cmd_demosaic_config *in)
2744 struct vfe_demosaic_cfg cmd;
2745 struct vfe_demosaic_bpc_cfg cmd_bpc;
2746 struct vfe_demosaic_abf_cfg cmd_abf;
2748 memset(&cmd, 0, sizeof(cmd));
2749 memset(&cmd_bpc, 0, sizeof(cmd_bpc));
2750 memset(&cmd_abf, 0, sizeof(cmd_abf));
2752 ctrl->vfeModuleEnableLocal.demosaicEnable = in->enable;
2754 cmd.abfEnable = in->abfConfig.enable;
2755 cmd.badPixelCorrEnable = in->bpcConfig.enable;
2756 cmd.forceAbfOn = in->abfConfig.forceOn;
2757 cmd.abfShift = in->abfConfig.shift;
2758 cmd.fminThreshold = in->bpcConfig.fminThreshold;
2759 cmd.fmaxThreshold = in->bpcConfig.fmaxThreshold;
2760 cmd.slopeShift = in->slopeShift;
2762 vfe_prog_hw(ctrl->vfebase + VFE_DEMOSAIC_CFG,
2763 (uint32_t *)&cmd, sizeof(cmd));
2765 cmd_abf.lpThreshold = in->abfConfig.lpThreshold;
2766 cmd_abf.ratio = in->abfConfig.ratio;
2767 cmd_abf.minValue = in->abfConfig.min;
2768 cmd_abf.maxValue = in->abfConfig.max;
2770 vfe_prog_hw(ctrl->vfebase + VFE_DEMOSAIC_ABF_CFG_0,
2771 (uint32_t *)&cmd_abf, sizeof(cmd_abf));
2773 cmd_bpc.blueDiffThreshold = in->bpcConfig.blueDiffThreshold;
2774 cmd_bpc.redDiffThreshold = in->bpcConfig.redDiffThreshold;
2775 cmd_bpc.greenDiffThreshold = in->bpcConfig.greenDiffThreshold;
2777 vfe_prog_hw(ctrl->vfebase + VFE_DEMOSAIC_BPC_CFG_0,
2778 (uint32_t *)&cmd_bpc, sizeof(cmd_bpc));
2781 void vfe_demux_channel_gain_update(
2782 struct vfe_cmd_demux_channel_gain_config *in)
2784 struct vfe_demux_cfg cmd;
2786 memset(&cmd, 0, sizeof(cmd));
2788 cmd.ch0EvenGain = in->ch0EvenGain;
2789 cmd.ch0OddGain = in->ch0OddGain;
2790 cmd.ch1Gain = in->ch1Gain;
2791 cmd.ch2Gain = in->ch2Gain;
2793 vfe_prog_hw(ctrl->vfebase + VFE_DEMUX_GAIN_0,
2794 (uint32_t *)&cmd, sizeof(cmd));
2797 void vfe_demux_channel_gain_config(
2798 struct vfe_cmd_demux_channel_gain_config *in)
2800 struct vfe_demux_cfg cmd;
2802 memset(&cmd, 0, sizeof(cmd));
2804 cmd.ch0EvenGain = in->ch0EvenGain;
2805 cmd.ch0OddGain = in->ch0OddGain;
2806 cmd.ch1Gain = in->ch1Gain;
2807 cmd.ch2Gain = in->ch2Gain;
2809 vfe_prog_hw(ctrl->vfebase + VFE_DEMUX_GAIN_0,
2810 (uint32_t *)&cmd, sizeof(cmd));
2813 void vfe_black_level_update(struct vfe_cmd_black_level_config *in)
2815 struct vfe_blacklevel_cfg cmd;
2817 memset(&cmd, 0, sizeof(cmd));
2818 ctrl->vfeModuleEnableLocal.blackLevelCorrectionEnable = in->enable;
2820 cmd.evenEvenAdjustment = in->evenEvenAdjustment;
2821 cmd.evenOddAdjustment = in->evenOddAdjustment;
2822 cmd.oddEvenAdjustment = in->oddEvenAdjustment;
2823 cmd.oddOddAdjustment = in->oddOddAdjustment;
2825 vfe_prog_hw(ctrl->vfebase + VFE_BLACK_EVEN_EVEN_VALUE,
2826 (uint32_t *)&cmd, sizeof(cmd));
2829 void vfe_black_level_config(struct vfe_cmd_black_level_config *in)
2831 struct vfe_blacklevel_cfg cmd;
2832 memset(&cmd, 0, sizeof(cmd));
2834 ctrl->vfeModuleEnableLocal.blackLevelCorrectionEnable = in->enable;
2836 cmd.evenEvenAdjustment = in->evenEvenAdjustment;
2837 cmd.evenOddAdjustment = in->evenOddAdjustment;
2838 cmd.oddEvenAdjustment = in->oddEvenAdjustment;
2839 cmd.oddOddAdjustment = in->oddOddAdjustment;
2841 vfe_prog_hw(ctrl->vfebase + VFE_BLACK_EVEN_EVEN_VALUE,
2842 (uint32_t *)&cmd, sizeof(cmd));
2845 void vfe_asf_update(struct vfe_cmd_asf_update *in)
2847 struct vfe_asf_update cmd;
2848 memset(&cmd, 0, sizeof(cmd));
2850 ctrl->vfeModuleEnableLocal.asfEnable = in->enable;
2852 cmd.smoothEnable = in->smoothFilterEnabled;
2853 cmd.sharpMode = in->sharpMode;
2854 cmd.smoothCoeff1 = in->smoothCoefCenter;
2855 cmd.smoothCoeff0 = in->smoothCoefSurr;
2856 cmd.cropEnable = in->cropEnable;
2857 cmd.sharpThresholdE1 = in->sharpThreshE1;
2858 cmd.sharpDegreeK1 = in->sharpK1;
2859 cmd.sharpDegreeK2 = in->sharpK2;
2860 cmd.normalizeFactor = in->normalizeFactor;
2861 cmd.sharpThresholdE2 = in->sharpThreshE2;
2862 cmd.sharpThresholdE3 = in->sharpThreshE3;
2863 cmd.sharpThresholdE4 = in->sharpThreshE4;
2864 cmd.sharpThresholdE5 = in->sharpThreshE5;
2865 cmd.F1Coeff0 = in->filter1Coefficients[0];
2866 cmd.F1Coeff1 = in->filter1Coefficients[1];
2867 cmd.F1Coeff2 = in->filter1Coefficients[2];
2868 cmd.F1Coeff3 = in->filter1Coefficients[3];
2869 cmd.F1Coeff4 = in->filter1Coefficients[4];
2870 cmd.F1Coeff5 = in->filter1Coefficients[5];
2871 cmd.F1Coeff6 = in->filter1Coefficients[6];
2872 cmd.F1Coeff7 = in->filter1Coefficients[7];
2873 cmd.F1Coeff8 = in->filter1Coefficients[8];
2874 cmd.F2Coeff0 = in->filter2Coefficients[0];
2875 cmd.F2Coeff1 = in->filter2Coefficients[1];
2876 cmd.F2Coeff2 = in->filter2Coefficients[2];
2877 cmd.F2Coeff3 = in->filter2Coefficients[3];
2878 cmd.F2Coeff4 = in->filter2Coefficients[4];
2879 cmd.F2Coeff5 = in->filter2Coefficients[5];
2880 cmd.F2Coeff6 = in->filter2Coefficients[6];
2881 cmd.F2Coeff7 = in->filter2Coefficients[7];
2882 cmd.F2Coeff8 = in->filter2Coefficients[8];
2884 vfe_prog_hw(ctrl->vfebase + VFE_ASF_CFG,
2885 (uint32_t *)&cmd, sizeof(cmd));
2888 void vfe_asf_config(struct vfe_cmd_asf_config *in)
2890 struct vfe_asf_update cmd;
2891 struct vfe_asfcrop_cfg cmd2;
2893 memset(&cmd, 0, sizeof(cmd));
2894 memset(&cmd2, 0, sizeof(cmd2));
2896 ctrl->vfeModuleEnableLocal.asfEnable = in->enable;
2898 cmd.smoothEnable = in->smoothFilterEnabled;
2899 cmd.sharpMode = in->sharpMode;
2900 cmd.smoothCoeff0 = in->smoothCoefCenter;
2901 cmd.smoothCoeff1 = in->smoothCoefSurr;
2902 cmd.cropEnable = in->cropEnable;
2903 cmd.sharpThresholdE1 = in->sharpThreshE1;
2904 cmd.sharpDegreeK1 = in->sharpK1;
2905 cmd.sharpDegreeK2 = in->sharpK2;
2906 cmd.normalizeFactor = in->normalizeFactor;
2907 cmd.sharpThresholdE2 = in->sharpThreshE2;
2908 cmd.sharpThresholdE3 = in->sharpThreshE3;
2909 cmd.sharpThresholdE4 = in->sharpThreshE4;
2910 cmd.sharpThresholdE5 = in->sharpThreshE5;
2911 cmd.F1Coeff0 = in->filter1Coefficients[0];
2912 cmd.F1Coeff1 = in->filter1Coefficients[1];
2913 cmd.F1Coeff2 = in->filter1Coefficients[2];
2914 cmd.F1Coeff3 = in->filter1Coefficients[3];
2915 cmd.F1Coeff4 = in->filter1Coefficients[4];
2916 cmd.F1Coeff5 = in->filter1Coefficients[5];
2917 cmd.F1Coeff6 = in->filter1Coefficients[6];
2918 cmd.F1Coeff7 = in->filter1Coefficients[7];
2919 cmd.F1Coeff8 = in->filter1Coefficients[8];
2920 cmd.F2Coeff0 = in->filter2Coefficients[0];
2921 cmd.F2Coeff1 = in->filter2Coefficients[1];
2922 cmd.F2Coeff2 = in->filter2Coefficients[2];
2923 cmd.F2Coeff3 = in->filter2Coefficients[3];
2924 cmd.F2Coeff4 = in->filter2Coefficients[4];
2925 cmd.F2Coeff5 = in->filter2Coefficients[5];
2926 cmd.F2Coeff6 = in->filter2Coefficients[6];
2927 cmd.F2Coeff7 = in->filter2Coefficients[7];
2928 cmd.F2Coeff8 = in->filter2Coefficients[8];
2930 vfe_prog_hw(ctrl->vfebase + VFE_ASF_CFG,
2931 (uint32_t *)&cmd, sizeof(cmd));
2933 cmd2.firstLine = in->cropFirstLine;
2934 cmd2.lastLine = in->cropLastLine;
2935 cmd2.firstPixel = in->cropFirstPixel;
2936 cmd2.lastPixel = in->cropLastPixel;
2938 vfe_prog_hw(ctrl->vfebase + VFE_ASF_CROP_WIDTH_CFG,
2939 (uint32_t *)&cmd2, sizeof(cmd2));
2942 void vfe_white_balance_config(struct vfe_cmd_white_balance_config *in)
2944 struct vfe_wb_cfg cmd;
2945 memset(&cmd, 0, sizeof(cmd));
2947 ctrl->vfeModuleEnableLocal.whiteBalanceEnable =
2950 cmd.ch0Gain = in->ch0Gain;
2951 cmd.ch1Gain = in->ch1Gain;
2952 cmd.ch2Gain = in->ch2Gain;
2954 vfe_prog_hw(ctrl->vfebase + VFE_WB_CFG,
2955 (uint32_t *)&cmd, sizeof(cmd));
2958 void vfe_chroma_sup_config(struct vfe_cmd_chroma_suppression_config *in)
2960 struct vfe_chroma_suppress_cfg cmd;
2961 memset(&cmd, 0, sizeof(cmd));
2963 ctrl->vfeModuleEnableLocal.chromaSuppressionEnable = in->enable;
2972 vfe_prog_hw(ctrl->vfebase + VFE_CHROMA_SUPPRESS_CFG_0,
2973 (uint32_t *)&cmd, sizeof(cmd));
2976 void vfe_roll_off_config(struct vfe_cmd_roll_off_config *in)
2978 struct vfe_rolloff_cfg cmd;
2979 memset(&cmd, 0, sizeof(cmd));
2981 ctrl->vfeModuleEnableLocal.lensRollOffEnable = in->enable;
2983 cmd.gridWidth = in->gridWidth;
2984 cmd.gridHeight = in->gridHeight;
2985 cmd.yDelta = in->yDelta;
2986 cmd.gridX = in->gridXIndex;
2987 cmd.gridY = in->gridYIndex;
2988 cmd.pixelX = in->gridPixelXIndex;
2989 cmd.pixelY = in->gridPixelYIndex;
2990 cmd.yDeltaAccum = in->yDeltaAccum;
2992 vfe_prog_hw(ctrl->vfebase + VFE_ROLLOFF_CFG_0,
2993 (uint32_t *)&cmd, sizeof(cmd));
2995 vfe_write_lens_roll_off_table(in);
2998 void vfe_chroma_subsample_config(
2999 struct vfe_cmd_chroma_subsample_config *in)
3001 struct vfe_chromasubsample_cfg cmd;
3002 memset(&cmd, 0, sizeof(cmd));
3004 ctrl->vfeModuleEnableLocal.chromaSubsampleEnable = in->enable;
3006 cmd.hCositedPhase = in->hCositedPhase;
3007 cmd.vCositedPhase = in->vCositedPhase;
3008 cmd.hCosited = in->hCosited;
3009 cmd.vCosited = in->vCosited;
3010 cmd.hsubSampleEnable = in->hsubSampleEnable;
3011 cmd.vsubSampleEnable = in->vsubSampleEnable;
3012 cmd.cropEnable = in->cropEnable;
3013 cmd.cropWidthLastPixel = in->cropWidthLastPixel;
3014 cmd.cropWidthFirstPixel = in->cropWidthFirstPixel;
3015 cmd.cropHeightLastLine = in->cropHeightLastLine;
3016 cmd.cropHeightFirstLine = in->cropHeightFirstLine;
3018 vfe_prog_hw(ctrl->vfebase + VFE_CHROMA_SUBSAMPLE_CFG,
3019 (uint32_t *)&cmd, sizeof(cmd));
3022 void vfe_chroma_enhan_config(struct vfe_cmd_chroma_enhan_config *in)
3024 struct vfe_chroma_enhance_cfg cmd;
3025 struct vfe_color_convert_cfg cmd2;
3027 memset(&cmd, 0, sizeof(cmd));
3028 memset(&cmd2, 0, sizeof(cmd2));
3030 ctrl->vfeModuleEnableLocal.chromaEnhanEnable = in->enable;
3043 cmd2.v0 = in->RGBtoYConversionV0;
3044 cmd2.v1 = in->RGBtoYConversionV1;
3045 cmd2.v2 = in->RGBtoYConversionV2;
3046 cmd2.ConvertOffset = in->RGBtoYConversionOffset;
3048 vfe_prog_hw(ctrl->vfebase + VFE_CHROMA_ENHAN_A,
3049 (uint32_t *)&cmd, sizeof(cmd));
3051 vfe_prog_hw(ctrl->vfebase + VFE_COLOR_CONVERT_COEFF_0,
3052 (uint32_t *)&cmd2, sizeof(cmd2));
3055 void vfe_scaler2cbcr_config(struct vfe_cmd_scaler2_config *in)
3057 struct vfe_scaler2_cfg cmd;
3059 memset(&cmd, 0, sizeof(cmd));
3061 ctrl->vfeModuleEnableLocal.scaler2CbcrEnable = in->enable;
3063 cmd.hEnable = in->hconfig.enable;
3064 cmd.vEnable = in->vconfig.enable;
3065 cmd.inWidth = in->hconfig.inputSize;
3066 cmd.outWidth = in->hconfig.outputSize;
3067 cmd.horizPhaseMult = in->hconfig.phaseMultiplicationFactor;
3068 cmd.horizInterResolution = in->hconfig.interpolationResolution;
3069 cmd.inHeight = in->vconfig.inputSize;
3070 cmd.outHeight = in->vconfig.outputSize;
3071 cmd.vertPhaseMult = in->vconfig.phaseMultiplicationFactor;
3072 cmd.vertInterResolution = in->vconfig.interpolationResolution;
3074 vfe_prog_hw(ctrl->vfebase + VFE_SCALE_CBCR_CFG,
3075 (uint32_t *)&cmd, sizeof(cmd));
3078 void vfe_scaler2y_config(struct vfe_cmd_scaler2_config *in)
3080 struct vfe_scaler2_cfg cmd;
3082 memset(&cmd, 0, sizeof(cmd));
3084 ctrl->vfeModuleEnableLocal.scaler2YEnable = in->enable;
3086 cmd.hEnable = in->hconfig.enable;
3087 cmd.vEnable = in->vconfig.enable;
3088 cmd.inWidth = in->hconfig.inputSize;
3089 cmd.outWidth = in->hconfig.outputSize;
3090 cmd.horizPhaseMult = in->hconfig.phaseMultiplicationFactor;
3091 cmd.horizInterResolution = in->hconfig.interpolationResolution;
3092 cmd.inHeight = in->vconfig.inputSize;
3093 cmd.outHeight = in->vconfig.outputSize;
3094 cmd.vertPhaseMult = in->vconfig.phaseMultiplicationFactor;
3095 cmd.vertInterResolution = in->vconfig.interpolationResolution;
3097 vfe_prog_hw(ctrl->vfebase + VFE_SCALE_Y_CFG,
3098 (uint32_t *)&cmd, sizeof(cmd));
3101 void vfe_main_scaler_config(struct vfe_cmd_main_scaler_config *in)
3103 struct vfe_main_scaler_cfg cmd;
3105 memset(&cmd, 0, sizeof(cmd));
3107 ctrl->vfeModuleEnableLocal.mainScalerEnable = in->enable;
3109 cmd.hEnable = in->hconfig.enable;
3110 cmd.vEnable = in->vconfig.enable;
3111 cmd.inWidth = in->hconfig.inputSize;
3112 cmd.outWidth = in->hconfig.outputSize;
3113 cmd.horizPhaseMult = in->hconfig.phaseMultiplicationFactor;
3114 cmd.horizInterResolution = in->hconfig.interpolationResolution;
3115 cmd.horizMNInit = in->MNInitH.MNCounterInit;
3116 cmd.horizPhaseInit = in->MNInitH.phaseInit;
3117 cmd.inHeight = in->vconfig.inputSize;
3118 cmd.outHeight = in->vconfig.outputSize;
3119 cmd.vertPhaseMult = in->vconfig.phaseMultiplicationFactor;
3120 cmd.vertInterResolution = in->vconfig.interpolationResolution;
3121 cmd.vertMNInit = in->MNInitV.MNCounterInit;
3122 cmd.vertPhaseInit = in->MNInitV.phaseInit;
3124 vfe_prog_hw(ctrl->vfebase + VFE_SCALE_CFG,
3125 (uint32_t *)&cmd, sizeof(cmd));
3128 void vfe_stats_wb_exp_stop(void)
3130 ctrl->vfeStatsCmdLocal.axwEnable = FALSE;
3131 ctrl->vfeImaskLocal.awbPingpongIrq = FALSE;
3134 void vfe_stats_update_wb_exp(struct vfe_cmd_stats_wb_exp_update *in)
3136 struct vfe_statsawb_update cmd;
3137 struct vfe_statsawbae_update cmd2;
3139 memset(&cmd, 0, sizeof(cmd));
3140 memset(&cmd2, 0, sizeof(cmd2));
3142 cmd.m1 = in->awbMCFG[0];
3143 cmd.m2 = in->awbMCFG[1];
3144 cmd.m3 = in->awbMCFG[2];
3145 cmd.m4 = in->awbMCFG[3];
3146 cmd.c1 = in->awbCCFG[0];
3147 cmd.c2 = in->awbCCFG[1];
3148 cmd.c3 = in->awbCCFG[2];
3149 cmd.c4 = in->awbCCFG[3];
3150 vfe_prog_hw(ctrl->vfebase + VFE_STATS_AWB_MCFG,
3151 (uint32_t *)&cmd, sizeof(cmd));
3153 cmd2.aeRegionCfg = in->wbExpRegions;
3154 cmd2.aeSubregionCfg = in->wbExpSubRegion;
3155 cmd2.awbYMin = in->awbYMin;
3156 cmd2.awbYMax = in->awbYMax;
3157 vfe_prog_hw(ctrl->vfebase + VFE_STATS_AWBAE_CFG,
3158 (uint32_t *)&cmd2, sizeof(cmd2));
3161 void vfe_stats_update_af(struct vfe_cmd_stats_af_update *in)
3163 struct vfe_statsaf_update cmd;
3164 memset(&cmd, 0, sizeof(cmd));
3166 cmd.windowVOffset = in->windowVOffset;
3167 cmd.windowHOffset = in->windowHOffset;
3168 cmd.windowMode = in->windowMode;
3169 cmd.windowHeight = in->windowHeight;
3170 cmd.windowWidth = in->windowWidth;
3172 vfe_prog_hw(ctrl->vfebase + VFE_STATS_AF_CFG,
3173 (uint32_t *)&cmd, sizeof(cmd));
3176 void vfe_stats_start_wb_exp(struct vfe_cmd_stats_wb_exp_start *in)
3178 struct vfe_statsawb_update cmd;
3179 struct vfe_statsawbae_update cmd2;
3180 struct vfe_statsaxw_hdr_cfg cmd3;
3182 ctrl->vfeStatsCmdLocal.axwEnable = in->enable;
3183 ctrl->vfeImaskLocal.awbPingpongIrq = TRUE;
3185 memset(&cmd, 0, sizeof(cmd));
3186 memset(&cmd2, 0, sizeof(cmd2));
3187 memset(&cmd3, 0, sizeof(cmd3));
3189 cmd.m1 = in->awbMCFG[0];
3190 cmd.m2 = in->awbMCFG[1];
3191 cmd.m3 = in->awbMCFG[2];
3192 cmd.m4 = in->awbMCFG[3];
3193 cmd.c1 = in->awbCCFG[0];
3194 cmd.c2 = in->awbCCFG[1];
3195 cmd.c3 = in->awbCCFG[2];
3196 cmd.c4 = in->awbCCFG[3];
3197 vfe_prog_hw(ctrl->vfebase + VFE_STATS_AWB_MCFG,
3198 (uint32_t *)&cmd, sizeof(cmd));
3200 cmd2.aeRegionCfg = in->wbExpRegions;
3201 cmd2.aeSubregionCfg = in->wbExpSubRegion;
3202 cmd2.awbYMin = in->awbYMin;
3203 cmd2.awbYMax = in->awbYMax;
3204 vfe_prog_hw(ctrl->vfebase + VFE_STATS_AWBAE_CFG,
3205 (uint32_t *)&cmd2, sizeof(cmd2));
3207 cmd3.axwHeader = in->axwHeader;
3208 vfe_prog_hw(ctrl->vfebase + VFE_STATS_AXW_HEADER,
3209 (uint32_t *)&cmd3, sizeof(cmd3));
3212 void vfe_stats_start_af(struct vfe_cmd_stats_af_start *in)
3214 struct vfe_statsaf_update cmd;
3215 struct vfe_statsaf_cfg cmd2;
3217 memset(&cmd, 0, sizeof(cmd));
3218 memset(&cmd2, 0, sizeof(cmd2));
3220 ctrl->vfeStatsCmdLocal.autoFocusEnable = in->enable;
3221 ctrl->vfeImaskLocal.afPingpongIrq = TRUE;
3223 cmd.windowVOffset = in->windowVOffset;
3224 cmd.windowHOffset = in->windowHOffset;
3225 cmd.windowMode = in->windowMode;
3226 cmd.windowHeight = in->windowHeight;
3227 cmd.windowWidth = in->windowWidth;
3229 vfe_prog_hw(ctrl->vfebase + VFE_STATS_AF_CFG,
3230 (uint32_t *)&cmd, sizeof(cmd));
3232 cmd2.a00 = in->highPassCoef[0];
3233 cmd2.a04 = in->highPassCoef[1];
3234 cmd2.a20 = in->highPassCoef[2];
3235 cmd2.a21 = in->highPassCoef[3];
3236 cmd2.a22 = in->highPassCoef[4];
3237 cmd2.a23 = in->highPassCoef[5];
3238 cmd2.a24 = in->highPassCoef[6];
3239 cmd2.fvMax = in->metricMax;
3240 cmd2.fvMetric = in->metricSelection;
3241 cmd2.afHeader = in->bufferHeader;
3242 cmd2.entry00 = in->gridForMultiWindows[0];
3243 cmd2.entry01 = in->gridForMultiWindows[1];
3244 cmd2.entry02 = in->gridForMultiWindows[2];
3245 cmd2.entry03 = in->gridForMultiWindows[3];
3246 cmd2.entry10 = in->gridForMultiWindows[4];
3247 cmd2.entry11 = in->gridForMultiWindows[5];
3248 cmd2.entry12 = in->gridForMultiWindows[6];
3249 cmd2.entry13 = in->gridForMultiWindows[7];
3250 cmd2.entry20 = in->gridForMultiWindows[8];
3251 cmd2.entry21 = in->gridForMultiWindows[9];
3252 cmd2.entry22 = in->gridForMultiWindows[10];
3253 cmd2.entry23 = in->gridForMultiWindows[11];
3254 cmd2.entry30 = in->gridForMultiWindows[12];
3255 cmd2.entry31 = in->gridForMultiWindows[13];
3256 cmd2.entry32 = in->gridForMultiWindows[14];
3257 cmd2.entry33 = in->gridForMultiWindows[15];
3259 vfe_prog_hw(ctrl->vfebase + VFE_STATS_AF_GRID_0,
3260 (uint32_t *)&cmd2, sizeof(cmd2));
3263 void vfe_stats_setting(struct vfe_cmd_stats_setting *in)
3265 struct vfe_statsframe cmd1;
3266 struct vfe_busstats_wrprio cmd2;
3268 memset(&cmd1, 0, sizeof(cmd1));
3269 memset(&cmd2, 0, sizeof(cmd2));
3271 ctrl->afStatsControl.addressBuffer[0] = in->afBuffer[0];
3272 ctrl->afStatsControl.addressBuffer[1] = in->afBuffer[1];
3273 ctrl->afStatsControl.nextFrameAddrBuf = in->afBuffer[2];
3275 ctrl->awbStatsControl.addressBuffer[0] = in->awbBuffer[0];
3276 ctrl->awbStatsControl.addressBuffer[1] = in->awbBuffer[1];
3277 ctrl->awbStatsControl.nextFrameAddrBuf = in->awbBuffer[2];
3279 cmd1.lastPixel = in->frameHDimension;
3280 cmd1.lastLine = in->frameVDimension;
3281 vfe_prog_hw(ctrl->vfebase + VFE_STATS_FRAME_SIZE,
3282 (uint32_t *)&cmd1, sizeof(cmd1));
3284 cmd2.afBusPriority = in->afBusPriority;
3285 cmd2.awbBusPriority = in->awbBusPriority;
3286 cmd2.histBusPriority = in->histBusPriority;
3287 cmd2.afBusPriorityEn = in->afBusPrioritySelection;
3288 cmd2.awbBusPriorityEn = in->awbBusPrioritySelection;
3289 cmd2.histBusPriorityEn = in->histBusPrioritySelection;
3291 vfe_prog_hw(ctrl->vfebase + VFE_BUS_STATS_WR_PRIORITY,
3292 (uint32_t *)&cmd2, sizeof(cmd2));
3294 /* Program the bus ping pong address for statistics modules. */
3295 writel(in->afBuffer[0], ctrl->vfebase + VFE_BUS_STATS_AF_WR_PING_ADDR);
3296 writel(in->afBuffer[1], ctrl->vfebase + VFE_BUS_STATS_AF_WR_PONG_ADDR);
3297 writel(in->awbBuffer[0],
3298 ctrl->vfebase + VFE_BUS_STATS_AWB_WR_PING_ADDR);
3299 writel(in->awbBuffer[1],
3300 ctrl->vfebase + VFE_BUS_STATS_AWB_WR_PONG_ADDR);
3301 writel(in->histBuffer[0],
3302 ctrl->vfebase + VFE_BUS_STATS_HIST_WR_PING_ADDR);
3303 writel(in->histBuffer[1],
3304 ctrl->vfebase + VFE_BUS_STATS_HIST_WR_PONG_ADDR);
3307 void vfe_axi_input_config(struct vfe_cmd_axi_input_config *in)
3309 struct VFE_AxiInputCmdType cmd;
3310 uint32_t xSizeWord, axiRdUnpackPattern;
3311 uint8_t axiInputPpw;
3312 uint32_t busPingpongRdIrqEnable;
3314 ctrl->vfeImaskLocal.rdPingpongIrq = TRUE;
3316 switch (in->pixelSize) {
3317 case VFE_RAW_PIXEL_DATA_SIZE_10BIT:
3318 ctrl->axiInputDataSize = VFE_RAW_PIXEL_DATA_SIZE_10BIT;
3321 case VFE_RAW_PIXEL_DATA_SIZE_12BIT:
3322 ctrl->axiInputDataSize = VFE_RAW_PIXEL_DATA_SIZE_12BIT;
3325 case VFE_RAW_PIXEL_DATA_SIZE_8BIT:
3327 ctrl->axiInputDataSize = VFE_RAW_PIXEL_DATA_SIZE_8BIT;
3331 memset(&cmd, 0, sizeof(cmd));
3333 switch (in->pixelSize) {
3334 case VFE_RAW_PIXEL_DATA_SIZE_10BIT:
3336 axiRdUnpackPattern = 0xD43210;
3339 case VFE_RAW_PIXEL_DATA_SIZE_12BIT:
3341 axiRdUnpackPattern = 0xC3210;
3344 case VFE_RAW_PIXEL_DATA_SIZE_8BIT:
3347 axiRdUnpackPattern = 0xF6543210;
3352 ((((in->xOffset % axiInputPpw) + in->xSize) +
3353 (axiInputPpw-1)) / axiInputPpw) - 1;
3355 cmd.stripeStartAddr0 = in->fragAddr[0];
3356 cmd.stripeStartAddr1 = in->fragAddr[1];
3357 cmd.stripeStartAddr2 = in->fragAddr[2];
3358 cmd.stripeStartAddr3 = in->fragAddr[3];
3359 cmd.ySize = in->ySize;
3360 cmd.yOffsetDelta = 0;
3361 cmd.xSizeWord = xSizeWord;
3362 cmd.burstLength = 1;
3363 cmd.NumOfRows = in->numOfRows;
3365 (in->rowIncrement + (axiInputPpw-1))/axiInputPpw;
3366 cmd.mainUnpackHeight = in->ySize;
3367 cmd.mainUnpackWidth = in->xSize - 1;
3368 cmd.mainUnpackHbiSel = (uint32_t)in->unpackHbi;
3369 cmd.mainUnpackPhase = in->unpackPhase;
3370 cmd.unpackPattern = axiRdUnpackPattern;
3371 cmd.padLeft = in->padRepeatCountLeft;
3372 cmd.padRight = in->padRepeatCountRight;
3373 cmd.padTop = in->padRepeatCountTop;
3374 cmd.padBottom = in->padRepeatCountBottom;
3375 cmd.leftUnpackPattern0 = in->padLeftComponentSelectCycle0;
3376 cmd.leftUnpackPattern1 = in->padLeftComponentSelectCycle1;
3377 cmd.leftUnpackPattern2 = in->padLeftComponentSelectCycle2;
3378 cmd.leftUnpackPattern3 = in->padLeftComponentSelectCycle3;
3379 cmd.leftUnpackStop0 = in->padLeftStopCycle0;
3380 cmd.leftUnpackStop1 = in->padLeftStopCycle1;
3381 cmd.leftUnpackStop2 = in->padLeftStopCycle2;
3382 cmd.leftUnpackStop3 = in->padLeftStopCycle3;
3383 cmd.rightUnpackPattern0 = in->padRightComponentSelectCycle0;
3384 cmd.rightUnpackPattern1 = in->padRightComponentSelectCycle1;
3385 cmd.rightUnpackPattern2 = in->padRightComponentSelectCycle2;
3386 cmd.rightUnpackPattern3 = in->padRightComponentSelectCycle3;
3387 cmd.rightUnpackStop0 = in->padRightStopCycle0;
3388 cmd.rightUnpackStop1 = in->padRightStopCycle1;
3389 cmd.rightUnpackStop2 = in->padRightStopCycle2;
3390 cmd.rightUnpackStop3 = in->padRightStopCycle3;
3391 cmd.topUnapckPattern = in->padTopLineCount;
3392 cmd.bottomUnapckPattern = in->padBottomLineCount;
3394 /* program vfe_bus_cfg */
3395 vfe_prog_hw(ctrl->vfebase + VFE_BUS_STRIPE_RD_ADDR_0,
3396 (uint32_t *)&cmd, sizeof(cmd));
3398 /* hacking code, put it to default value */
3399 busPingpongRdIrqEnable = 0xf;
3401 writel(busPingpongRdIrqEnable,
3402 ctrl->vfebase + VFE_BUS_PINGPONG_IRQ_EN);
3405 void vfe_stats_config(struct vfe_cmd_stats_setting *in)
3407 ctrl->afStatsControl.addressBuffer[0] = in->afBuffer[0];
3408 ctrl->afStatsControl.addressBuffer[1] = in->afBuffer[1];
3409 ctrl->afStatsControl.nextFrameAddrBuf = in->afBuffer[2];
3411 ctrl->awbStatsControl.addressBuffer[0] = in->awbBuffer[0];
3412 ctrl->awbStatsControl.addressBuffer[1] = in->awbBuffer[1];
3413 ctrl->awbStatsControl.nextFrameAddrBuf = in->awbBuffer[2];
3415 vfe_stats_setting(in);
3418 void vfe_axi_output_config(
3419 struct vfe_cmd_axi_output_config *in)
3421 /* local variable */
3427 uint16_t axioutpw = 8;
3429 /* parameters check, condition and usage mode check */
3430 ctrl->encPath.fragCount = in->output2.fragmentCount;
3431 if (ctrl->encPath.fragCount > 1)
3432 ctrl->encPath.multiFrag = TRUE;
3434 ctrl->viewPath.fragCount = in->output1.fragmentCount;
3435 if (ctrl->viewPath.fragCount > 1)
3436 ctrl->viewPath.multiFrag = TRUE;
3438 /* VFE_BUS_CFG. raw data size */
3439 ctrl->vfeBusConfigLocal.rawPixelDataSize = in->outputDataSize;
3441 switch (in->outputDataSize) {
3442 case VFE_RAW_PIXEL_DATA_SIZE_8BIT:
3446 case VFE_RAW_PIXEL_DATA_SIZE_10BIT:
3450 case VFE_RAW_PIXEL_DATA_SIZE_12BIT:
3455 ctrl->axiOutputMode = in->outputMode;
3457 CDBG("axiOutputMode = %d\n", ctrl->axiOutputMode);
3459 switch (ctrl->axiOutputMode) {
3460 case VFE_AXI_OUTPUT_MODE_Output1: {
3461 ctrl->vfeCamifConfigLocal.camif2BusEnable = FALSE;
3462 ctrl->vfeCamifConfigLocal.camif2OutputEnable = TRUE;
3463 ctrl->vfeBusConfigLocal.rawWritePathSelect =
3464 VFE_RAW_OUTPUT_DISABLED;
3466 ctrl->encPath.pathEnabled = FALSE;
3467 ctrl->vfeImaskLocal.encIrq = FALSE;
3468 ctrl->vfeIrqCompositeMaskLocal.encIrqComMask =
3469 VFE_COMP_IRQ_BOTH_Y_CBCR;
3471 ctrl->vfeBusConfigLocal.encYWrPathEn = FALSE;
3472 ctrl->vfeBusConfigLocal.encCbcrWrPathEn = FALSE;
3473 ctrl->viewPath.pathEnabled = TRUE;
3474 ctrl->vfeImaskLocal.viewIrq = TRUE;
3475 ctrl->vfeIrqCompositeMaskLocal.viewIrqComMask =
3476 VFE_COMP_IRQ_BOTH_Y_CBCR;
3478 ctrl->vfeBusConfigLocal.viewYWrPathEn = TRUE;
3479 ctrl->vfeBusConfigLocal.viewCbcrWrPathEn = TRUE;
3481 if (ctrl->vfeBusConfigLocal.encYWrPathEn &&
3482 ctrl->encPath.multiFrag)
3483 ctrl->vfeImaskLocal.encYPingpongIrq = TRUE;
3485 if (ctrl->vfeBusConfigLocal.encCbcrWrPathEn &&
3486 ctrl->encPath.multiFrag)
3487 ctrl->vfeImaskLocal.encCbcrPingpongIrq = TRUE;
3489 if (ctrl->vfeBusConfigLocal.viewYWrPathEn &&
3490 ctrl->viewPath.multiFrag)
3491 ctrl->vfeImaskLocal.viewYPingpongIrq = TRUE;
3493 if (ctrl->vfeBusConfigLocal.viewCbcrWrPathEn &&
3494 ctrl->viewPath.multiFrag)
3495 ctrl->vfeImaskLocal.viewCbcrPingpongIrq = TRUE;
3496 } /* VFE_AXI_OUTPUT_MODE_Output1 */
3499 case VFE_AXI_OUTPUT_MODE_Output2: {
3500 ctrl->vfeCamifConfigLocal.camif2BusEnable = FALSE;
3501 ctrl->vfeCamifConfigLocal.camif2OutputEnable = TRUE;
3502 ctrl->vfeBusConfigLocal.rawWritePathSelect =
3503 VFE_RAW_OUTPUT_DISABLED;
3505 ctrl->encPath.pathEnabled = TRUE;
3506 ctrl->vfeImaskLocal.encIrq = TRUE;
3507 ctrl->vfeIrqCompositeMaskLocal.encIrqComMask =
3508 VFE_COMP_IRQ_BOTH_Y_CBCR;
3510 ctrl->vfeBusConfigLocal.encYWrPathEn = TRUE;
3511 ctrl->vfeBusConfigLocal.encCbcrWrPathEn = TRUE;
3513 ctrl->viewPath.pathEnabled = FALSE;
3514 ctrl->vfeImaskLocal.viewIrq = FALSE;
3515 ctrl->vfeIrqCompositeMaskLocal.viewIrqComMask =
3516 VFE_COMP_IRQ_BOTH_Y_CBCR;
3518 ctrl->vfeBusConfigLocal.viewYWrPathEn = FALSE;
3519 ctrl->vfeBusConfigLocal.viewCbcrWrPathEn = FALSE;
3521 if (ctrl->vfeBusConfigLocal.encYWrPathEn &&
3522 ctrl->encPath.multiFrag)
3523 ctrl->vfeImaskLocal.encYPingpongIrq = TRUE;
3525 if (ctrl->vfeBusConfigLocal.encCbcrWrPathEn &&
3526 ctrl->encPath.multiFrag)
3527 ctrl->vfeImaskLocal.encCbcrPingpongIrq = TRUE;
3529 if (ctrl->vfeBusConfigLocal.viewYWrPathEn &&
3530 ctrl->viewPath.multiFrag)
3531 ctrl->vfeImaskLocal.viewYPingpongIrq = TRUE;
3533 if (ctrl->vfeBusConfigLocal.viewCbcrWrPathEn &&
3534 ctrl->viewPath.multiFrag)
3535 ctrl->vfeImaskLocal.viewCbcrPingpongIrq = TRUE;
3536 } /* VFE_AXI_OUTPUT_MODE_Output2 */
3539 case VFE_AXI_OUTPUT_MODE_Output1AndOutput2: {
3540 ctrl->vfeCamifConfigLocal.camif2BusEnable = FALSE;
3541 ctrl->vfeCamifConfigLocal.camif2OutputEnable = TRUE;
3542 ctrl->vfeBusConfigLocal.rawWritePathSelect =
3543 VFE_RAW_OUTPUT_DISABLED;
3545 ctrl->encPath.pathEnabled = TRUE;
3546 ctrl->vfeImaskLocal.encIrq = TRUE;
3547 ctrl->vfeIrqCompositeMaskLocal.encIrqComMask =
3548 VFE_COMP_IRQ_BOTH_Y_CBCR;
3550 ctrl->vfeBusConfigLocal.encYWrPathEn = TRUE;
3551 ctrl->vfeBusConfigLocal.encCbcrWrPathEn = TRUE;
3552 ctrl->viewPath.pathEnabled = TRUE;
3553 ctrl->vfeImaskLocal.viewIrq = TRUE;
3554 ctrl->vfeIrqCompositeMaskLocal.viewIrqComMask =
3555 VFE_COMP_IRQ_BOTH_Y_CBCR;
3557 ctrl->vfeBusConfigLocal.viewYWrPathEn = TRUE;
3558 ctrl->vfeBusConfigLocal.viewCbcrWrPathEn = TRUE;
3560 if (ctrl->vfeBusConfigLocal.encYWrPathEn &&
3561 ctrl->encPath.multiFrag)
3562 ctrl->vfeImaskLocal.encYPingpongIrq = TRUE;
3564 if (ctrl->vfeBusConfigLocal.encCbcrWrPathEn &&
3565 ctrl->encPath.multiFrag)
3566 ctrl->vfeImaskLocal.encCbcrPingpongIrq = TRUE;
3568 if (ctrl->vfeBusConfigLocal.viewYWrPathEn &&
3569 ctrl->viewPath.multiFrag)
3570 ctrl->vfeImaskLocal.viewYPingpongIrq = TRUE;
3572 if (ctrl->vfeBusConfigLocal.viewCbcrWrPathEn &&
3573 ctrl->viewPath.multiFrag)
3574 ctrl->vfeImaskLocal.viewCbcrPingpongIrq = TRUE;
3575 } /* VFE_AXI_OUTPUT_MODE_Output1AndOutput2 */
3578 case VFE_AXI_OUTPUT_MODE_CAMIFToAXIViaOutput2: {
3579 /* For raw snapshot, we need both ping and pong buffer
3580 * initialized to the same address. Otherwise, if we
3581 * leave the pong buffer to NULL, there will be axi_error.
3582 * Note that ideally we should deal with this at upper layer,
3583 * which is in msm_vfe8x.c */
3584 if (!in->output2.outputCbcr.outFragments[1][0]) {
3585 in->output2.outputCbcr.outFragments[1][0] =
3586 in->output2.outputCbcr.outFragments[0][0];
3589 ctrl->vfeCamifConfigLocal.camif2BusEnable = TRUE;
3590 ctrl->vfeCamifConfigLocal.camif2OutputEnable = FALSE;
3591 ctrl->vfeBusConfigLocal.rawWritePathSelect =
3592 VFE_RAW_OUTPUT_ENC_CBCR_PATH;
3594 ctrl->encPath.pathEnabled = TRUE;
3595 ctrl->vfeImaskLocal.encIrq = TRUE;
3596 ctrl->vfeIrqCompositeMaskLocal.encIrqComMask =
3597 VFE_COMP_IRQ_CBCR_ONLY;
3599 ctrl->vfeBusConfigLocal.encYWrPathEn = FALSE;
3600 ctrl->vfeBusConfigLocal.encCbcrWrPathEn = TRUE;
3602 ctrl->viewPath.pathEnabled = FALSE;
3603 ctrl->vfeImaskLocal.viewIrq = FALSE;
3604 ctrl->vfeIrqCompositeMaskLocal.viewIrqComMask =
3605 VFE_COMP_IRQ_BOTH_Y_CBCR;
3607 ctrl->vfeBusConfigLocal.viewYWrPathEn = FALSE;
3608 ctrl->vfeBusConfigLocal.viewCbcrWrPathEn = FALSE;
3610 if (ctrl->vfeBusConfigLocal.encYWrPathEn &&
3611 ctrl->encPath.multiFrag)
3612 ctrl->vfeImaskLocal.encYPingpongIrq = TRUE;
3614 if (ctrl->vfeBusConfigLocal.encCbcrWrPathEn &&
3615 ctrl->encPath.multiFrag)
3616 ctrl->vfeImaskLocal.encCbcrPingpongIrq = TRUE;
3618 if (ctrl->vfeBusConfigLocal.viewYWrPathEn &&
3619 ctrl->viewPath.multiFrag)
3620 ctrl->vfeImaskLocal.viewYPingpongIrq = TRUE;
3622 if (ctrl->vfeBusConfigLocal.viewCbcrWrPathEn &&
3623 ctrl->viewPath.multiFrag)
3624 ctrl->vfeImaskLocal.viewCbcrPingpongIrq = TRUE;
3625 } /* VFE_AXI_OUTPUT_MODE_CAMIFToAXIViaOutput2 */
3628 case VFE_AXI_OUTPUT_MODE_Output2AndCAMIFToAXIViaOutput1: {
3629 ctrl->vfeCamifConfigLocal.camif2BusEnable = TRUE;
3630 ctrl->vfeCamifConfigLocal.camif2OutputEnable = TRUE;
3631 ctrl->vfeBusConfigLocal.rawWritePathSelect =
3632 VFE_RAW_OUTPUT_VIEW_CBCR_PATH;
3634 ctrl->encPath.pathEnabled = TRUE;
3635 ctrl->vfeImaskLocal.encIrq = TRUE;
3636 ctrl->vfeIrqCompositeMaskLocal.encIrqComMask =
3637 VFE_COMP_IRQ_BOTH_Y_CBCR;
3639 ctrl->vfeBusConfigLocal.encYWrPathEn = TRUE;
3640 ctrl->vfeBusConfigLocal.encCbcrWrPathEn = TRUE;
3642 ctrl->viewPath.pathEnabled = TRUE;
3643 ctrl->vfeImaskLocal.viewIrq = TRUE;
3644 ctrl->vfeIrqCompositeMaskLocal.viewIrqComMask =
3645 VFE_COMP_IRQ_CBCR_ONLY;
3647 ctrl->vfeBusConfigLocal.viewYWrPathEn = FALSE;
3648 ctrl->vfeBusConfigLocal.viewCbcrWrPathEn = TRUE;
3650 if (ctrl->vfeBusConfigLocal.encYWrPathEn &&
3651 ctrl->encPath.multiFrag)
3652 ctrl->vfeImaskLocal.encYPingpongIrq = TRUE;
3654 if (ctrl->vfeBusConfigLocal.encCbcrWrPathEn &&
3655 ctrl->encPath.multiFrag)
3656 ctrl->vfeImaskLocal.encCbcrPingpongIrq = TRUE;
3658 if (ctrl->vfeBusConfigLocal.viewYWrPathEn &&
3659 ctrl->viewPath.multiFrag)
3660 ctrl->vfeImaskLocal.viewYPingpongIrq = TRUE;
3662 if (ctrl->vfeBusConfigLocal.viewCbcrWrPathEn &&
3663 ctrl->viewPath.multiFrag)
3664 ctrl->vfeImaskLocal.viewCbcrPingpongIrq = TRUE;
3665 } /* VFE_AXI_OUTPUT_MODE_Output2AndCAMIFToAXIViaOutput1 */
3668 case VFE_AXI_OUTPUT_MODE_Output1AndCAMIFToAXIViaOutput2: {
3669 ctrl->vfeCamifConfigLocal.camif2BusEnable = TRUE;
3670 ctrl->vfeCamifConfigLocal.camif2OutputEnable = TRUE;
3671 ctrl->vfeBusConfigLocal.rawWritePathSelect =
3672 VFE_RAW_OUTPUT_ENC_CBCR_PATH;
3674 ctrl->encPath.pathEnabled = TRUE;
3675 ctrl->vfeImaskLocal.encIrq = TRUE;
3676 ctrl->vfeIrqCompositeMaskLocal.encIrqComMask =
3677 VFE_COMP_IRQ_CBCR_ONLY;
3679 ctrl->vfeBusConfigLocal.encYWrPathEn = FALSE;
3680 ctrl->vfeBusConfigLocal.encCbcrWrPathEn = TRUE;
3682 ctrl->viewPath.pathEnabled = TRUE;
3683 ctrl->vfeImaskLocal.viewIrq = TRUE;
3685 ctrl->vfeIrqCompositeMaskLocal.viewIrqComMask =
3686 VFE_COMP_IRQ_BOTH_Y_CBCR;
3688 ctrl->vfeBusConfigLocal.viewYWrPathEn = TRUE;
3689 ctrl->vfeBusConfigLocal.viewCbcrWrPathEn = TRUE;
3691 if (ctrl->vfeBusConfigLocal.encYWrPathEn &&
3692 ctrl->encPath.multiFrag)
3693 ctrl->vfeImaskLocal.encYPingpongIrq = TRUE;
3695 if (ctrl->vfeBusConfigLocal.encCbcrWrPathEn &&
3696 ctrl->encPath.multiFrag)
3697 ctrl->vfeImaskLocal.encCbcrPingpongIrq = TRUE;
3699 if (ctrl->vfeBusConfigLocal.viewYWrPathEn &&
3700 ctrl->viewPath.multiFrag)
3701 ctrl->vfeImaskLocal.viewYPingpongIrq = TRUE;
3703 if (ctrl->vfeBusConfigLocal.viewCbcrWrPathEn &&
3704 ctrl->viewPath.multiFrag)
3705 ctrl->vfeImaskLocal.viewCbcrPingpongIrq = TRUE;
3706 } /* VFE_AXI_OUTPUT_MODE_Output1AndCAMIFToAXIViaOutput2 */
3709 case VFE_AXI_LAST_OUTPUT_MODE_ENUM:
3713 /* Save the addresses for each path. */
3715 fcnt = ctrl->encPath.fragCount;
3717 pcircle = ctrl->encPath.yPath.addressBuffer;
3718 pdest = ctrl->encPath.nextFrameAddrBuf;
3720 psrc = &(in->output2.outputY.outFragments[0][0]);
3721 for (i = 0; i < fcnt; i++)
3722 *pcircle++ = *psrc++;
3724 psrc = &(in->output2.outputY.outFragments[1][0]);
3725 for (i = 0; i < fcnt; i++)
3726 *pcircle++ = *psrc++;
3728 psrc = &(in->output2.outputY.outFragments[2][0]);
3729 for (i = 0; i < fcnt; i++)
3732 pcircle = ctrl->encPath.cbcrPath.addressBuffer;
3734 psrc = &(in->output2.outputCbcr.outFragments[0][0]);
3735 for (i = 0; i < fcnt; i++)
3736 *pcircle++ = *psrc++;
3738 psrc = &(in->output2.outputCbcr.outFragments[1][0]);
3739 for (i = 0; i < fcnt; i++)
3740 *pcircle++ = *psrc++;
3742 psrc = &(in->output2.outputCbcr.outFragments[2][0]);
3743 for (i = 0; i < fcnt; i++)
3746 vfe_set_bus_pipo_addr(&ctrl->viewPath, &ctrl->encPath);
3748 ctrl->encPath.ackPending = FALSE;
3749 ctrl->encPath.currentFrame = ping;
3750 ctrl->encPath.whichOutputPath = 1;
3751 ctrl->encPath.yPath.fragIndex = 2;
3752 ctrl->encPath.cbcrPath.fragIndex = 2;
3753 ctrl->encPath.yPath.hwCurrentFlag = ping;
3754 ctrl->encPath.cbcrPath.hwCurrentFlag = ping;
3757 pcircle = ctrl->viewPath.yPath.addressBuffer;
3758 pdest = ctrl->viewPath.nextFrameAddrBuf;
3759 fcnt = ctrl->viewPath.fragCount;
3761 psrc = &(in->output1.outputY.outFragments[0][0]);
3762 for (i = 0; i < fcnt; i++)
3763 *pcircle++ = *psrc++;
3765 psrc = &(in->output1.outputY.outFragments[1][0]);
3766 for (i = 0; i < fcnt; i++)
3767 *pcircle++ = *psrc++;
3769 psrc = &(in->output1.outputY.outFragments[2][0]);
3770 for (i = 0; i < fcnt; i++)
3773 pcircle = ctrl->viewPath.cbcrPath.addressBuffer;
3775 psrc = &(in->output1.outputCbcr.outFragments[0][0]);
3776 for (i = 0; i < fcnt; i++)
3777 *pcircle++ = *psrc++;
3779 psrc = &(in->output1.outputCbcr.outFragments[1][0]);
3780 for (i = 0; i < fcnt; i++)
3781 *pcircle++ = *psrc++;
3783 psrc = &(in->output1.outputCbcr.outFragments[2][0]);
3784 for (i = 0; i < fcnt; i++)
3787 ctrl->viewPath.ackPending = FALSE;
3788 ctrl->viewPath.currentFrame = ping;
3789 ctrl->viewPath.whichOutputPath = 0;
3790 ctrl->viewPath.yPath.fragIndex = 2;
3791 ctrl->viewPath.cbcrPath.fragIndex = 2;
3792 ctrl->viewPath.yPath.hwCurrentFlag = ping;
3793 ctrl->viewPath.cbcrPath.hwCurrentFlag = ping;
3795 /* call to program the registers. */
3796 vfe_axi_output(in, &ctrl->viewPath, &ctrl->encPath, axioutpw);
3799 void vfe_camif_config(struct vfe_cmd_camif_config *in)
3801 struct vfe_camifcfg cmd;
3802 memset(&cmd, 0, sizeof(cmd));
3804 CDBG("camif.frame pixelsPerLine = %d\n", in->frame.pixelsPerLine);
3805 CDBG("camif.frame linesPerFrame = %d\n", in->frame.linesPerFrame);
3806 CDBG("camif.window firstpixel = %d\n", in->window.firstpixel);
3807 CDBG("camif.window lastpixel = %d\n", in->window.lastpixel);
3808 CDBG("camif.window firstline = %d\n", in->window.firstline);
3809 CDBG("camif.window lastline = %d\n", in->window.lastline);
3811 /* determine if epoch interrupt needs to be enabled. */
3812 if ((in->epoch1.enable == TRUE) &&
3813 (in->epoch1.lineindex <=
3814 in->frame.linesPerFrame))
3815 ctrl->vfeImaskLocal.camifEpoch1Irq = 1;
3817 if ((in->epoch2.enable == TRUE) &&
3818 (in->epoch2.lineindex <=
3819 in->frame.linesPerFrame)) {
3820 ctrl->vfeImaskLocal.camifEpoch2Irq = 1;
3823 /* save the content to program CAMIF_CONFIG seperately. */
3824 ctrl->vfeCamifConfigLocal.camifCfgFromCmd = in->camifConfig;
3827 cmd.efsEndOfLine = in->EFS.efsendofline;
3828 cmd.efsStartOfLine = in->EFS.efsstartofline;
3829 cmd.efsEndOfFrame = in->EFS.efsendofframe;
3830 cmd.efsStartOfFrame = in->EFS.efsstartofframe;
3833 cmd.frameConfigPixelsPerLine = in->frame.pixelsPerLine;
3834 cmd.frameConfigLinesPerFrame = in->frame.linesPerFrame;
3836 /* Window Width Config */
3837 cmd.windowWidthCfgLastPixel = in->window.lastpixel;
3838 cmd.windowWidthCfgFirstPixel = in->window.firstpixel;
3840 /* Window Height Config */
3841 cmd.windowHeightCfglastLine = in->window.lastline;
3842 cmd.windowHeightCfgfirstLine = in->window.firstline;
3844 /* Subsample 1 Config */
3845 cmd.subsample1CfgPixelSkip = in->subsample.pixelskipmask;
3846 cmd.subsample1CfgLineSkip = in->subsample.lineskipmask;
3848 /* Subsample 2 Config */
3849 cmd.subsample2CfgFrameSkip = in->subsample.frameskip;
3850 cmd.subsample2CfgFrameSkipMode = in->subsample.frameskipmode;
3851 cmd.subsample2CfgPixelSkipWrap = in->subsample.pixelskipwrap;
3853 /* Epoch Interrupt */
3854 cmd.epoch1Line = in->epoch1.lineindex;
3855 cmd.epoch2Line = in->epoch2.lineindex;
3857 vfe_prog_hw(ctrl->vfebase + CAMIF_EFS_CONFIG,
3858 (uint32_t *)&cmd, sizeof(cmd));
3861 void vfe_fov_crop_config(struct vfe_cmd_fov_crop_config *in)
3863 struct vfe_fov_crop_cfg cmd;
3864 memset(&cmd, 0, sizeof(cmd));
3866 ctrl->vfeModuleEnableLocal.cropEnable = in->enable;
3868 /* FOV Corp, Part 1 */
3869 cmd.lastPixel = in->lastPixel;
3870 cmd.firstPixel = in->firstPixel;
3872 /* FOV Corp, Part 2 */
3873 cmd.lastLine = in->lastLine;
3874 cmd.firstLine = in->firstLine;
3876 vfe_prog_hw(ctrl->vfebase + VFE_CROP_WIDTH_CFG,
3877 (uint32_t *)&cmd, sizeof(cmd));
3880 void vfe_get_hw_version(struct vfe_cmd_hw_version *out)
3882 uint32_t vfeHwVersionPacked;
3883 struct vfe_hw_ver ver;
3885 vfeHwVersionPacked = readl(ctrl->vfebase + VFE_HW_VERSION);
3887 ver = *((struct vfe_hw_ver *)&vfeHwVersionPacked);
3889 out->coreVersion = ver.coreVersion;
3890 out->minorVersion = ver.minorVersion;
3891 out->majorVersion = ver.majorVersion;
3894 static void vfe_reset_internal_variables(void)
3896 unsigned long flags;
3898 /* local variables to program the hardware. */
3899 ctrl->vfeImaskPacked = 0;
3900 ctrl->vfeImaskCompositePacked = 0;
3902 /* FALSE = disable, 1 = enable. */
3903 memset(&ctrl->vfeModuleEnableLocal, 0,
3904 sizeof(ctrl->vfeModuleEnableLocal));
3906 /* 0 = disable, 1 = enable */
3907 memset(&ctrl->vfeCamifConfigLocal, 0,
3908 sizeof(ctrl->vfeCamifConfigLocal));
3909 /* 0 = disable, 1 = enable */
3910 memset(&ctrl->vfeImaskLocal, 0, sizeof(ctrl->vfeImaskLocal));
3911 memset(&ctrl->vfeStatsCmdLocal, 0, sizeof(ctrl->vfeStatsCmdLocal));
3912 memset(&ctrl->vfeBusConfigLocal, 0, sizeof(ctrl->vfeBusConfigLocal));
3913 memset(&ctrl->vfeBusPmConfigLocal, 0,
3914 sizeof(ctrl->vfeBusPmConfigLocal));
3915 memset(&ctrl->vfeBusCmdLocal, 0, sizeof(ctrl->vfeBusCmdLocal));
3916 memset(&ctrl->vfeInterruptNameLocal, 0,
3917 sizeof(ctrl->vfeInterruptNameLocal));
3918 memset(&ctrl->vfeDroppedFrameCounts, 0,
3919 sizeof(ctrl->vfeDroppedFrameCounts));
3920 memset(&ctrl->vfeIrqThreadMsgLocal, 0,
3921 sizeof(ctrl->vfeIrqThreadMsgLocal));
3923 /* state control variables */
3924 ctrl->vfeStartAckPendingFlag = FALSE;
3925 ctrl->vfeStopAckPending = FALSE;
3926 ctrl->vfeIrqCompositeMaskLocal.ceDoneSel = 0;
3927 ctrl->vfeIrqCompositeMaskLocal.encIrqComMask =
3928 VFE_COMP_IRQ_BOTH_Y_CBCR;
3929 ctrl->vfeIrqCompositeMaskLocal.viewIrqComMask =
3930 VFE_COMP_IRQ_BOTH_Y_CBCR;
3932 spin_lock_irqsave(&ctrl->state_lock, flags);
3933 ctrl->vstate = VFE_STATE_IDLE;
3934 spin_unlock_irqrestore(&ctrl->state_lock, flags);
3936 ctrl->axiOutputMode = VFE_AXI_LAST_OUTPUT_MODE_ENUM;
3937 /* 0 for continuous mode, 1 for snapshot mode */
3938 ctrl->vfeOperationMode = VFE_START_OPERATION_MODE_CONTINUOUS;
3939 ctrl->vfeSnapShotCount = 0;
3940 ctrl->vfeStatsPingPongReloadFlag = FALSE;
3941 /* this is unsigned 32 bit integer. */
3942 ctrl->vfeFrameId = 0;
3943 ctrl->vfeFrameSkip.output1Pattern = 0xffffffff;
3944 ctrl->vfeFrameSkip.output1Period = 31;
3945 ctrl->vfeFrameSkip.output2Pattern = 0xffffffff;
3946 ctrl->vfeFrameSkip.output2Period = 31;
3947 ctrl->vfeFrameSkipPattern = 0xffffffff;
3948 ctrl->vfeFrameSkipCount = 0;
3949 ctrl->vfeFrameSkipPeriod = 31;
3951 memset((void *)&ctrl->encPath, 0, sizeof(ctrl->encPath));
3952 memset((void *)&ctrl->viewPath, 0, sizeof(ctrl->viewPath));
3954 ctrl->encPath.whichOutputPath = 1;
3955 ctrl->encPath.cbcrStatusBit = 5;
3956 ctrl->viewPath.whichOutputPath = 0;
3957 ctrl->viewPath.cbcrStatusBit = 7;
3959 ctrl->vfeTestGenStartFlag = FALSE;
3961 /* default to bank 0. */
3962 ctrl->vfeLaBankSel = 0;
3964 /* default to bank 0 for all channels. */
3965 memset(&ctrl->vfeGammaLutSel, 0, sizeof(ctrl->vfeGammaLutSel));
3967 /* Stats control variables. */
3968 memset(&ctrl->afStatsControl, 0, sizeof(ctrl->afStatsControl));
3969 memset(&ctrl->awbStatsControl, 0, sizeof(ctrl->awbStatsControl));
3970 vfe_set_stats_pingpong_address(&ctrl->afStatsControl,
3971 &ctrl->awbStatsControl);
3974 void vfe_reset(void)
3976 vfe_reset_internal_variables();
3978 ctrl->vfeImaskLocal.resetAckIrq = TRUE;
3979 ctrl->vfeImaskPacked = vfe_irq_pack(ctrl->vfeImaskLocal);
3981 /* disable all interrupts. */
3982 writel(VFE_DISABLE_ALL_IRQS,
3983 ctrl->vfebase + VFE_IRQ_COMPOSITE_MASK);
3985 /* clear all pending interrupts*/
3986 writel(VFE_CLEAR_ALL_IRQS,
3987 ctrl->vfebase + VFE_IRQ_CLEAR);
3989 /* enable reset_ack interrupt. */
3990 writel(ctrl->vfeImaskPacked,
3991 ctrl->vfebase + VFE_IRQ_MASK);
3993 writel(VFE_RESET_UPON_RESET_CMD,
3994 ctrl->vfebase + VFE_GLOBAL_RESET_CMD);