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