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