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