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