/** 
 * db9000_ctrl.c
 *
 * Copyright (C) 2015 - 2017 Fuji Xerox Co.,Ltd. All rights reserved.
 *
 * This is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc., 59
 * Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * The full GNU General Public License is included in this distribution in the
 * file called COPYING.
 */
#ifdef __KERNEL__
 #include <linux/stddef.h>
 #include <linux/types.h>
#else
 #include <stddef.h>
 #include <stdint.h>
#endif
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/jiffies.h>
#include <linux/platform_device.h>
#include <linux/semaphore.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <asm/types.h>
#include <asm/io.h>
#include <linux/atomic.h>
#include <linux/mm.h>
#include <linux/vmalloc.h>
#include <linux/slab.h>
#include <linux/list.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/of_device.h>
#include <linux/of_platform.h>
#include <linux/dma-mapping.h>
#include <linux/device.h>
#include <linux/spinlock.h>
#include <linux/fb.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/fxprivate/kernelOsddi.h>
#include "fxfb_drv.h"
extern void osUIPowOn(void);
#ifdef PRINT_DB9000_MSG
 #define PRINT_ISR_REG
#endif
void IO_SYNC(void) { }
#ifdef PRINT_ISR_REG
static int32_t isrCheckCount = 0;
static void print_isrReg(uint32_t regBaseAddr,
      const char *pFunction,int lineNo,int counter)
{
 volatile regISR regIsrData;
 FXFB_REG_READ(regBaseAddr,DB9000_ISR,&regIsrData.all);
 PUTDBGMSG("%s %d Interrupt Status Register(%d) : 0x%08X\n",
    pFunction,lineNo,counter,regIsrData.all);
}
#endif
bool db9000_error_condtion(uint32_t regBaseAddr)
{
 volatile regISR regIsrData;
 FXFB_ALIGN_BYTES(volatile bool error_flag);
  PFXFBLOCAL pFxfb_local = fxfb_get_local_info();
 FXFB_BOARD_REVISION board_rev;
 if(pFxfb_local == NULL){
  return true;
 }
 error_flag = false;
 board_rev = fxfb_get_board_revision(pFxfb_local);
 FXFB_REG_READ(regBaseAddr,DB9000_ISR,&regIsrData.all);
 if (regIsrData.bit.OFU) {
  error_flag = true;
 } else if (regIsrData.bit.OFO) {
  error_flag = true;
 } else if (regIsrData.bit.IFU) {
  error_flag = true;
 } else if (regIsrData.bit.IFO) {
  error_flag = true;
 } else if (regIsrData.bit.MBE) {
  if (board_rev == FXFB_BOARD_TYPE_IS_C0 || board_rev == FXFB_BOARD_TYPE_IS_C0_Vx1) {
   error_flag = true;
  }
 }
 if (error_flag) {
  fxfb_setErrorCode(EIO);
  return true;
 }
 return false;
}
void db9000_all_reg_read(uint32_t regBaseAddr,PDB9000CTRLREG pDb9000_reg)
{
 FXFB_REG_READ(regBaseAddr,DB9000_CR1 ,&pDb9000_reg->reg_CR1.all);
 FXFB_REG_READ(regBaseAddr,DB9000_HTR ,&pDb9000_reg->reg_HTR.all);
 FXFB_REG_READ(regBaseAddr,DB9000_VTR1 ,&pDb9000_reg->reg_VTR1.all);
 FXFB_REG_READ(regBaseAddr,DB9000_VTR2 ,&pDb9000_reg->reg_VTR2.all);
 FXFB_REG_READ(regBaseAddr,DB9000_PCTR ,&pDb9000_reg->reg_PCTR.all);
 FXFB_REG_READ(regBaseAddr,DB9000_ISR ,&pDb9000_reg->reg_ISR.all);
 FXFB_REG_READ(regBaseAddr,DB9000_IMR ,&pDb9000_reg->reg_IMR.all);
 FXFB_REG_READ(regBaseAddr,DB9000_IVR ,&pDb9000_reg->reg_IVR.all);
 FXFB_REG_READ(regBaseAddr,DB9000_ISCR ,&pDb9000_reg->reg_ISCR.all);
 FXFB_REG_READ(regBaseAddr,DB9000_DBAR ,&pDb9000_reg->reg_DBAR.all);
 FXFB_REG_READ(regBaseAddr,DB9000_DCAR ,&pDb9000_reg->reg_DCAR.all);
 FXFB_REG_READ(regBaseAddr,DB9000_DEAR ,&pDb9000_reg->reg_DEAR.all);
 FXFB_REG_READ(regBaseAddr,DB9000_PWMFR ,&pDb9000_reg->reg_PWMFR.all);
 FXFB_REG_READ(regBaseAddr,DB9000_PWMDCR,&pDb9000_reg->reg_PWMDCR.all);
 FXFB_REG_READ(regBaseAddr,DB9000_DFBAR ,&pDb9000_reg->reg_DFBAR.all);
 FXFB_REG_READ(regBaseAddr,DB9000_DFLAR ,&pDb9000_reg->reg_DFLAR.all);
 FXFB_REG_READ(regBaseAddr,DB9000_HVTER ,&pDb9000_reg->reg_HVTER.all);
 FXFB_REG_READ(regBaseAddr,DB9000_HPPLOR,&pDb9000_reg->reg_HPPLOR.all);
 FXFB_REG_READ(regBaseAddr,DB9000_CIR ,&pDb9000_reg->reg_CIR.all);
 FXFB_REG_READ(regBaseAddr,DB9000_MRR ,&pDb9000_reg->reg_MRR.all);
}
void us_wait(int32_t usCount)
{
 if (usCount <= 0) {
  return;
 }
 udelay((unsigned long)usCount);
}
void ms_wait(int32_t msCount)
{
 if (msCount <= 0) {
  return;
 }
 mdelay((unsigned long)msCount);
}
#if 0
static int32_t db9000_wait_cancel(struct fb_info *info,int32_t waitIndex)
{
 FXFB_ALIGN_BYTES(PFXFBLOCAL pFxfb_local);
 FXFB_ALIGN_BYTES(int32_t ret) = FXFB_SUCCESS;
 FXFB_ALIGN_BYTES(bool doIt);
 if (!info) {
  PUTFXFBMSG("%s() parameter \"info\" is NULL.\n",__FUNCTION__);
  fxfb_setErrorCode(EINVAL);
  return FXFB_ERROR;
 }
 pFxfb_local = (PFXFBLOCAL)info->par;
 fxfb_disable_irq(pFxfb_local);
 doIt = (bool)isset(pFxfb_local->waitStatus,waitIndex);
 if (!doIt) {
  fxfb_enable_irq(pFxfb_local);
  return ret;
 }
 setbit(pFxfb_local->waitCancelStatus,waitIndex);
 if (waitIndex == DB9000_VSYNC_WAIT) {
  vsync_wait_complete(pFxfb_local);
 }
#ifdef BAU_ISR_VALID
     else if (waitIndex == DB9000_BAU_WAIT) {
  bau_wait_complete(pFxfb_local);
 }
#endif
 fxfb_enable_irq(pFxfb_local);
 do {
  doIt = (bool)isset(pFxfb_local->waitStatus,waitIndex);
  schedule();
 } while(doIt);
 fxfb_disable_irq(pFxfb_local);
 clrbit(pFxfb_local->waitCancelStatus,waitIndex);
 fxfb_enable_irq(pFxfb_local);
 return ret;
}
int32_t db9000_vsync_wait_cancel(struct fb_info *info)
{
 int32_t ret = FXFB_SUCCESS;
 ret = db9000_wait_cancel(info,DB9000_VSYNC_WAIT);
 return ret;
}
#endif
static void set_isr_wait(PFXFBLOCAL pFxfb_local,int32_t waitIsrIndex,long *pTimeOut)
{
 int32_t waitTimer;
 pFxfb_local->fxfb_wait_status[waitIsrIndex].first = 0;
 pFxfb_local->fxfb_wait_status[waitIsrIndex].status = FXFB_WAIT_PROS_INIT;
 setbit(pFxfb_local->waitStatus,waitIsrIndex);
 clrbit(pFxfb_local->waitCancelStatus,waitIsrIndex);
 pFxfb_local->waitFlags[waitIsrIndex] = false;
 switch (waitIsrIndex) {
  case DB9000_VSYNC_WAIT:
  waitTimer = FXFB_VSYNC_TIMEOUT_MSEC;
  break;
  case DB9000_BAU_WAIT:
  waitTimer = FXFB_BAU_TIMEOUT_MSEC;
  break;
  case DB9000_STOP_WAIT:
  waitTimer = FXFB_STOP_TIMEOUT_MSEC;
  break;
  default :
  waitTimer = FXFB_STOP_TIMEOUT_MSEC;
  break;
 }
 *pTimeOut = FXFB_WAITMSEC(waitTimer);
}
static int32_t isr_wait(PFXFBLOCAL pFxfb_local,int32_t waitIsrIndex,long timeOut)
{
 int32_t ret;
 do {
  ret = wait_event_timeout(pFxfb_local->db9000_waitCtrl[waitIsrIndex],
         pFxfb_local->waitFlags[waitIsrIndex], timeOut);
  if (ret != 0) {
   pFxfb_local->fxfb_wait_status[waitIsrIndex].status = FXFB_WAIT_PROS_COMPLETE;
   ret = FXFB_SUCCESS;
   break;
  } else {
   setbit(pFxfb_local->waitCancelStatus,waitIsrIndex);
   FXFB_ERR("interrupt wait timed out (idx=%d, timeOut=%ld)\n", waitIsrIndex, timeOut);
   fxfb_setErrorCode(ETIMEDOUT);
   ret = FXFB_ERROR;
   break;
  }
 } while (!pFxfb_local->waitFlags[waitIsrIndex]);
 return ret;
}
static int32_t db9000_isr_wait(struct fb_info *info,int32_t waitIsrIndex,bool doNotLock)
{
 FXFB_ALIGN_BYTES(PFXFBLOCAL pFxfb_local);
 FXFB_ALIGN_BYTES(volatile unsigned long flags) = 0UL;
 FXFB_ALIGN_BYTES(volatile long timeOut);
 FXFB_ALIGN_BYTES(int32_t ret);
 FXFB_ALIGN_BYTES(int32_t spinlocked);
 if (!info) {
  PUTFXFBMSG("%s() parameter \"info\" is NULL.\n",__FUNCTION__);
  fxfb_setErrorCode(EINVAL);
  return FXFB_ERROR;
 }
 pFxfb_local = (PFXFBLOCAL)info->par;
 if (!doNotLock) {
  fxfb_spin_lock(pFxfb_local,(unsigned long *)&flags,&spinlocked);
 } else {
  spinlocked = false;
 }
 if (!isset(pFxfb_local->fxfb_status,FXFB_DRVSTS_ACTIVE) ||
  isset(pFxfb_local->fxfb_status,FXFB_DRVSTS_SUSPEND)) {
#ifdef FXFB_DRVINFO
  PUTFXFBMSG("db9000 is not active -> %s() escape(not an error). \n",__FUNCTION__);
#endif
  fxfb_spin_unlock(pFxfb_local,flags,spinlocked);
  return FXFB_SUCCESS;
 }
 if (db9000_error_condtion(pFxfb_local->fxfb_reg_base_addr)) {
  put_error_message(__FILE__,__FUNCTION__,__LINE__,EIO);
  fxfb_spin_unlock(pFxfb_local,flags,spinlocked);
  return FXFB_ERROR;
 }
 fxfb_disable_irq(pFxfb_local);
 set_isr_wait(pFxfb_local,waitIsrIndex,(long *)&timeOut);
 fxfb_spin_unlock(pFxfb_local,flags,spinlocked);
 fxfb_enable_irq(pFxfb_local);
 ret = isr_wait(pFxfb_local,waitIsrIndex,timeOut);
 if (ret != FXFB_SUCCESS) {
  FXFB_ERR("isr_wait failed (idx=%d, timeOut=%ld)\n", waitIsrIndex, timeOut);
 }
 pFxfb_local->waitFlags[waitIsrIndex] = FALSE;
 clrbit(pFxfb_local->waitStatus,waitIsrIndex);
 return ret;
}
int32_t db9000_vsync_wait(struct fb_info *info,bool doNotLock)
{
 int32_t ret;
 ret = db9000_isr_wait(info,DB9000_VSYNC_WAIT,doNotLock);
 return ret;
}
#ifdef BAU_ISR_VALID
#if 0
int32_t db9000_bau_wait_cancel(struct fb_info *info)
{
 int32_t ret = FXFB_SUCCESS;
 ret = db9000_wait_cancel(info,DB9000_BAU_WAIT);
 return ret;
}
#endif
int32_t db9000_bau_wait(struct fb_info *info,bool doNotLock)
{
 int32_t ret;
 ret = db9000_isr_wait(info,DB9000_BAU_WAIT,doNotLock);
 return ret;
}
#endif
static void db9000_set_Horizontal_Timing_Register(struct fb_info *info)
{
 FXFB_ALIGN_BYTES(PFXFBLOCAL pFxfb_local);
 if (!info) {
  PUTFXFBMSG("%s() parameter \"info\" is NULL.\n",__FUNCTION__);
  fxfb_setErrorCode(EINVAL);
  return;
 }
 pFxfb_local = (PFXFBLOCAL)info->par;
 FXFB_REG_READ(pFxfb_local->fxfb_reg_base_addr,DB9000_HTR,&pFxfb_local->db9000_reg.reg_HTR.all);
 FXFB_REG_READ(pFxfb_local->fxfb_reg_base_addr,DB9000_HVTER,&pFxfb_local->db9000_reg.reg_HVTER.all);
 if (info->var.right_margin < 256) {
  pFxfb_local->db9000_reg.reg_HTR.bit.HFP = info->var.right_margin;
  pFxfb_local->db9000_reg.reg_HVTER.bit.HFPE = 0;
 } else {
  pFxfb_local->db9000_reg.reg_HTR.bit.HFP = info->var.right_margin & 0x000000FF;
  pFxfb_local->db9000_reg.reg_HVTER.bit.HFPE = (info->var.right_margin & 0x00000300) >> 8;
 }
 pFxfb_local->db9000_reg.reg_HTR.bit.PPL = info->var.xres / 16;
 if (info->var.left_margin < 256) {
  pFxfb_local->db9000_reg.reg_HTR.bit.HBP = info->var.left_margin;
  pFxfb_local->db9000_reg.reg_HVTER.bit.HBPE = 0;
 } else {
  pFxfb_local->db9000_reg.reg_HTR.bit.HBP = info->var.left_margin & 0x000000FF;
  pFxfb_local->db9000_reg.reg_HVTER.bit.HBPE = (info->var.left_margin & 0x00000300) >> 8;
 }
 pFxfb_local->db9000_reg.reg_HTR.bit.HSW = info->var.hsync_len;
 FXFB_REG_WRITE(pFxfb_local->fxfb_reg_base_addr,DB9000_HTR,pFxfb_local->db9000_reg.reg_HTR.all);
 FXFB_REG_WRITE(pFxfb_local->fxfb_reg_base_addr,DB9000_HVTER,pFxfb_local->db9000_reg.reg_HVTER.all);
}
static void db9000_set_Vertical_Timing_Register(struct fb_info *info)
{
 FXFB_ALIGN_BYTES(PFXFBLOCAL pFxfb_local);
 if (!info) {
  PUTFXFBMSG("%s() parameter \"info\" is NULL.\n",__FUNCTION__);
  fxfb_setErrorCode(EINVAL);
  return;
 }
 pFxfb_local = (PFXFBLOCAL)info->par;
 FXFB_REG_READ(pFxfb_local->fxfb_reg_base_addr,DB9000_VTR1,&pFxfb_local->db9000_reg.reg_VTR1.all);
 FXFB_REG_READ(pFxfb_local->fxfb_reg_base_addr,DB9000_HVTER,&pFxfb_local->db9000_reg.reg_HVTER.all);
 pFxfb_local->db9000_reg.reg_VTR1.bit.VSW = info->var.vsync_len;
 if (info->var.lower_margin < 256 ) {
  pFxfb_local->db9000_reg.reg_VTR1.bit.VFP = info->var.lower_margin;
  pFxfb_local->db9000_reg.reg_HVTER.bit.VFPE = 0;
 } else {
  pFxfb_local->db9000_reg.reg_VTR1.bit.VFP = info->var.lower_margin & 0x000000FF;
  pFxfb_local->db9000_reg.reg_HVTER.bit.VFPE = (info->var.lower_margin & 0x00000300) >> 8;
 }
 if (info->var.upper_margin < 256) {
  pFxfb_local->db9000_reg.reg_VTR1.bit.VBP = info->var.upper_margin;
  pFxfb_local->db9000_reg.reg_HVTER.bit.VBPE = 0;
 } else {
  pFxfb_local->db9000_reg.reg_VTR1.bit.VBP = info->var.upper_margin & 0x000000FF;
  pFxfb_local->db9000_reg.reg_HVTER.bit.VBPE = (info->var.upper_margin & 0x00000300) >> 8;
 }
 FXFB_REG_WRITE(pFxfb_local->fxfb_reg_base_addr,DB9000_VTR1,pFxfb_local->db9000_reg.reg_VTR1.all);
 FXFB_REG_WRITE(pFxfb_local->fxfb_reg_base_addr,DB9000_HVTER,pFxfb_local->db9000_reg.reg_HVTER.all);
 FXFB_REG_READ(pFxfb_local->fxfb_reg_base_addr,DB9000_VTR2,&pFxfb_local->db9000_reg.reg_VTR2);
 pFxfb_local->db9000_reg.reg_VTR2.bit.LPP = info->var.yres;
 FXFB_REG_WRITE(pFxfb_local->fxfb_reg_base_addr,DB9000_VTR2,pFxfb_local->db9000_reg.reg_VTR2.all);
}
static void db9000_set_Control_Register1(struct fb_info *info)
{
 FXFB_ALIGN_BYTES(PFXFBLOCAL pFxfb_local);
 if (!info) {
  PUTFXFBMSG("%s() parameter \"info\" is NULL.\n",__FUNCTION__);
  fxfb_setErrorCode(EINVAL);
  return;
 }
 pFxfb_local = (PFXFBLOCAL)info->par;
 FXFB_REG_READ(pFxfb_local->fxfb_reg_base_addr,DB9000_CR1,&pFxfb_local->db9000_reg.reg_CR1.all);
 pFxfb_local->db9000_reg.reg_CR1.bit.BPP = 6;
 pFxfb_local->db9000_reg.reg_CR1.bit.RGB = 1;
 pFxfb_local->db9000_reg.reg_CR1.bit.EPO = 0;
 pFxfb_local->db9000_reg.reg_CR1.bit.EBO = 0;
 pFxfb_local->db9000_reg.reg_CR1.bit.DEP = 1;
 pFxfb_local->db9000_reg.reg_CR1.bit.PCP = 0;
 pFxfb_local->db9000_reg.reg_CR1.bit.HSP = 1;
 pFxfb_local->db9000_reg.reg_CR1.bit.VSP = 1;
 pFxfb_local->db9000_reg.reg_CR1.bit.OPS = 0;
 pFxfb_local->db9000_reg.reg_CR1.bit.PSS = 0;
 pFxfb_local->db9000_reg.reg_CR1.bit.FDW = 1;
 pFxfb_local->db9000_reg.reg_CR1.bit.LPS = 0;
 pFxfb_local->db9000_reg.reg_CR1.bit.FBP = 0;
 pFxfb_local->db9000_reg.reg_CR1.bit.DFR = 0;
 pFxfb_local->db9000_reg.reg_CR1.bit.DFB = 1;
 pFxfb_local->db9000_reg.reg_CR1.bit.DFE = 1;
 pFxfb_local->db9000_reg.reg_CR1.bit.LCE = 0;
 pFxfb_local->db9000_reg.reg_CR1.bit.LPE = 1;
#ifdef LCD_INITIALIZE_START
 pFxfb_local->db9000_reg.reg_CR1.bit.LCE = 1;
#endif
 FXFB_REG_WRITE(pFxfb_local->fxfb_reg_base_addr,DB9000_CR1,pFxfb_local->db9000_reg.reg_CR1.all);
}
static void db9000_setPCTR(struct fb_info *info)
{
 FXFB_ALIGN_BYTES(PFXFBLOCAL pFxfb_local);
 if (!info) {
  PUTFXFBMSG("%s() parameter \"info\" is NULL.\n",__FUNCTION__);
  fxfb_setErrorCode(EINVAL);
  return;
 }
 pFxfb_local = (PFXFBLOCAL)info->par;
 FXFB_REG_READ(pFxfb_local->fxfb_reg_base_addr,DB9000_PCTR,&pFxfb_local->db9000_reg.reg_PCTR.all);
 pFxfb_local->db9000_reg.reg_PCTR.bit.PCR = 0;
 pFxfb_local->db9000_reg.reg_PCTR.bit.PCI = 1;
 pFxfb_local->db9000_reg.reg_PCTR.bit.PCB = 0;
 pFxfb_local->db9000_reg.reg_PCTR.bit.PCD = pFxfb_local->pcd;
 FXFB_REG_WRITE(pFxfb_local->fxfb_reg_base_addr,DB9000_PCTR,pFxfb_local->db9000_reg.reg_PCTR.all);
#if 0
 ms_wait(1);
 pFxfb_local->db9000_reg.reg_PCTR = fxfb_reg_read(REGPCTR);
 LCDLIB_IO_SYNC;
 LCDLIB_REG_COPY(pFxfb_local->db9000_reg.reg_PCTR.all);
 LCDLIB_IO_SYNC;
 pFxfb_local->db9000_reg.reg_PCTR.bit.PCD = pFxfb_local->pcd;
 pFxfb_local->db9000_reg.reg_PCTR.bit.PCI = 1;
 pFxfb_local->db9000_reg.reg_PCTR.bit.PCB = 0;
#endif
 pFxfb_local->db9000_reg.reg_PCTR.bit.PCR = 1;
 FXFB_REG_WRITE(pFxfb_local->fxfb_reg_base_addr,DB9000_PCTR,pFxfb_local->db9000_reg.reg_PCTR.all);
}
void set_LCD_overlayCtrl(void)
{
 volatile uint32_t regAddr;
 regAddr = (uint32_t)ioremap(SYS_OVLCTL_REG_BASE,PAGE_SIZE);
 FXFB_REG_WRITE(regAddr,BITMAPUI_SYS_OVLCTL7,BITMAPUI_VAL_SYS_OVLCTL7);
 FXFB_REG_WRITE(regAddr,BITMAPUI_SYS_OVLCTL8,BITMAPUI_VAL_SYS_OVLCTL8);
 FXFB_REG_WRITE(regAddr,BITMAPUI_SYS_OVLCTL9,BITMAPUI_VAL_SYS_OVLCTL9);
 iounmap((void *)regAddr);
}
static void set_dma_addr(PFXFBLOCAL pFxfb_local,uint64_t dmaStartAddr,uint64_t dmaEndAddr)
{
 pFxfb_local->dmaStartAddr = dmaStartAddr;
 pFxfb_local->dmaEndAddr = dmaEndAddr;
 if (pFxfb_local->fxfb_cur_screen == FXFB_SCREEN_NO1) {
  pFxfb_local->desc[1]->next_addr |= 0x00000001;
  pFxfb_local->desc[0]->next_addr &= (~0x00000001);
 }
 else {
  pFxfb_local->desc[0]->next_addr |= 0x00000001;
  pFxfb_local->desc[1]->next_addr &= (~0x00000001);
 }
 FXFB_REG_READ(pFxfb_local->fxfb_reg_base_addr,DB9000_CR1,&pFxfb_local->db9000_reg.reg_CR1.all);
 pFxfb_local->db9000_reg.reg_CR1.bit.DFR = 1;
 FXFB_REG_WRITE(pFxfb_local->fxfb_reg_base_addr,DB9000_CR1,pFxfb_local->db9000_reg.reg_CR1.all);
}
static void db9000_setup_desc(struct fb_info *info)
{
 PFXFBLOCAL pFxfb_local;
 volatile uint64_t dmaStartAddr[2];
 volatile uint64_t dmaEndAddr[2];
 volatile dma_addr_t desc_bus;
 volatile uint32_t reg;
 int scrn_idx;
 pFxfb_local = (PFXFBLOCAL)info->par;
 dmaStartAddr[0] = pFxfb_local->fxfb_dma_busAddr;
 dmaEndAddr[0] = dmaStartAddr[0] + pFxfb_local->fxfb_screen_size;
 reg = (uint32_t)(pFxfb_local->desc_bus[1] & 0x00000000FFFFFFFFULL);
 pFxfb_local->desc[0]->next_addr = reg | 0x00000000;
 pFxfb_local->desc[0]->load_enable = 0x1;
 pFxfb_local->desc[0]->base_addr = (uint32_t)(dmaStartAddr[0] & 0x00000000FFFFFFFFULL);
 pFxfb_local->desc[0]->end_addr = (uint32_t)(dmaEndAddr[0] & 0x00000000FFFFFFFFULL);
 dmaStartAddr[1] = pFxfb_local->fxfb_dma_busAddr + pFxfb_local->fxfb_screen_size;
 dmaEndAddr[1] = dmaStartAddr[1] + pFxfb_local->fxfb_screen_size;
 reg = (uint32_t)(pFxfb_local->desc_bus[0] & 0x00000000FFFFFFFFULL);
 pFxfb_local->desc[1]->next_addr = reg | 0x00000000;
 pFxfb_local->desc[1]->load_enable = 0x1;
 pFxfb_local->desc[1]->base_addr = (uint32_t)(dmaStartAddr[1] & 0x00000000FFFFFFFFULL);
 pFxfb_local->desc[1]->end_addr = (uint32_t)(dmaEndAddr[1] & 0x00000000FFFFFFFFULL);
 if (pFxfb_local->fxfb_cur_screen == FXFB_SCREEN_NO1) {
  scrn_idx = 0;
 }
 else {
  scrn_idx = 1;
 }
 desc_bus = pFxfb_local->desc_bus[scrn_idx];
 pFxfb_local->dmaStartAddr = dmaStartAddr[scrn_idx];
 pFxfb_local->dmaEndAddr = dmaEndAddr[scrn_idx];
 FXFB_REG_WRITE(pFxfb_local->fxfb_reg_base_addr, DB9000_DFBAR,
       (uint32_t)(desc_bus & 0x00000000FFFFFFFFULL));
}
bool db9000_check_lockn_ok(void)
{
 int status;
 status = kernelGioStatus(OS_GIO_9TH_LOCKN);
 if (status == OS_STATUS_LOW) {
  return true;
 }
 return false;
}
static int32_t db9000_wait_lockn_ok(PFXFBLOCAL pFxfb_local)
{
 int i;
 i = 0;
 while (1) {
  if (db9000_check_lockn_ok()) {
   FXFB_INFO("Detected Vx1 Lock (%d us)\n", i);
   return FXFB_SUCCESS;
  }
  i++;
  us_wait(500);
  if (i == 20) {
   FXFB_LOCKN_ERR(pFxfb_local, "LOCKN timeout\n");
   return fxfb_set_return_code(EIO);
  }
 }
}
int db9000_setup(struct fb_info *info)
{
 FXFB_ALIGN_BYTES(PFXFBLOCAL pFxfb_local);
 volatile uint32_t reg;
 volatile uint32_t regAddr;
 volatile int32_t lcdadbctl;
 volatile int32_t i;
 int32_t ret;
 int32_t self_ret = FXFB_SUCCESS;
 if (!info) {
  PUTFXFBMSG("%s() parameter \"info\" is NULL.\n",__FUNCTION__);
  fxfb_setErrorCode(EINVAL);
  return FXFB_ERROR;
 }
 pFxfb_local = (PFXFBLOCAL)info->par;
 db9000_set_Horizontal_Timing_Register(info);
 db9000_set_Vertical_Timing_Register(info);
 db9000_setPCTR(info);
 regAddr = (uint32_t)ioremap(LCDGPF_BASE,PAGE_SIZE);
 if (fxfb_get_board_revision(pFxfb_local) == FXFB_BOARD_TYPE_IS_A0) {
  lcdadbctl = BITMAPUI_LCDADBCTL_A0;
 } else {
  lcdadbctl = BITMAPUI_LCDADBCTL_B0;
 }
 db9000_setup_desc(info);
 FXFB_REG_WRITE(pFxfb_local->fxfb_reg_base_addr,DB9000_MRR,0x0);
 FXFB_REG_WRITE(regAddr, lcdadbctl, 0x80);
 FXFB_REG_READ(regAddr,BITMAPUI_LCD_LVDSVX1_CSR1,&reg);
 reg &= BITMAPUI_MASK_LVDSVX1_CSR1_1;
 reg |= BITMAPUI_VAL_LVDSVX1_CSR1_1_24BIT;
 FXFB_REG_WRITE(regAddr,BITMAPUI_LCD_LVDSVX1_CSR1,reg);
 reg &= BITMAPUI_MASK_LVDSVX1_CSR1_2;
 FXFB_REG_WRITE(regAddr,BITMAPUI_LCD_LVDSVX1_CSR1,reg);
 if (fxfb_get_board_revision(pFxfb_local) == FXFB_BOARD_TYPE_IS_C0_Vx1) {
  FXFB_REG_READ(regAddr,BITMAPUI_LCD_LVDSVX1_CSR1,&reg);
  reg |= 5;
  FXFB_REG_WRITE(regAddr,BITMAPUI_LCD_LVDSVX1_CSR1,reg);
  FXFB_REG_READ(regAddr,BITMAPUI_LCD_LVDSVX1_CSR1,&reg);
  reg |= BITMAPUI_MASK_LVDSVX1_CSR1_SCRAMBLE_ENABLE;
  FXFB_REG_WRITE(regAddr,BITMAPUI_LCD_LVDSVX1_CSR1,reg);
  FXFB_REG_READ(regAddr,BITMAPUI_LCD_LVDSVX1_CSR1,&reg);
  reg |= BITMAPUI_MASK_LVDSVX1_CSR1_TX_RDVAL0;
  FXFB_REG_WRITE(regAddr,BITMAPUI_LCD_LVDSVX1_CSR1,reg);
  FXFB_REG_READ(regAddr,BITMAPUI_LCD_LVDSVX1_CSR1,&reg);
  reg |= BITMAPUI_MASK_LVDSVX1_CSR1_TX_RDN0;
  FXFB_REG_WRITE(regAddr,BITMAPUI_LCD_LVDSVX1_CSR1,reg);
  reg &= ~BITMAPUI_MASK_LVDSVX1_CSR1_TX_RDN0;
  FXFB_REG_WRITE(regAddr,BITMAPUI_LCD_LVDSVX1_CSR1,reg);
  reg |= BITMAPUI_MASK_LVDSVX1_CSR1_TX_RDN0;
  FXFB_REG_WRITE(regAddr,BITMAPUI_LCD_LVDSVX1_CSR1,reg);
  FXFB_REG_READ(regAddr,BITMAPUI_LCD_LVDSVX1_CSR1,&reg);
  reg |= BITMAPUI_MASK_LVDSVX1_CSR1_TX_RDVAL1;
  FXFB_REG_WRITE(regAddr,BITMAPUI_LCD_LVDSVX1_CSR1,reg);
  FXFB_REG_READ(regAddr,BITMAPUI_LCD_LVDSVX1_CSR1,&reg);
  reg |= BITMAPUI_MASK_LVDSVX1_CSR1_TX_RDN1;
  FXFB_REG_WRITE(regAddr,BITMAPUI_LCD_LVDSVX1_CSR1,reg);
  reg &= ~BITMAPUI_MASK_LVDSVX1_CSR1_TX_RDN1;
  FXFB_REG_WRITE(regAddr,BITMAPUI_LCD_LVDSVX1_CSR1,reg);
  reg |= BITMAPUI_MASK_LVDSVX1_CSR1_TX_RDN1;
  FXFB_REG_WRITE(regAddr,BITMAPUI_LCD_LVDSVX1_CSR1,reg);
 }
 else {
  reg = 0;
  i = 0;
  while (1) {
   FXFB_REG_READ(regAddr,BITMAPUI_LCD_LVDSVX1_CSR1,&reg);
   if (reg & BITMAPUI_TX_PLL_LOCK) {
    break;
   }
   us_wait(1);
   i++;
   if (i >= BITMAPUI_PLL_LOCK_TIMEOUT_US) {
    PUTFXFBMSG("%s() %s\n",__FUNCTION__,"PLL lock timed out.");
    fxfb_setErrorCode(ETIMEDOUT);
    iounmap((void *)regAddr);
    return FXFB_ERROR;
   }
  }
 }
 db9000_set_Control_Register1(info);
 FXFB_REG_WRITE(pFxfb_local->fxfb_reg_base_addr,DB9000_ISCR,VFP_COMMING_STATUS);
 if ( pFxfb_local->db9000_reg.reg_CIR.bit.CIR_REV < DB9000_VERSION_1_14) {
  pFxfb_local->db9000_reg.reg_CR1.bit.DEE = 1;
 }
 FXFB_REG_READ(pFxfb_local->fxfb_reg_base_addr,DB9000_ISR,&pFxfb_local->db9000_reg.reg_ISR.all);
 FXFB_REG_WRITE(pFxfb_local->fxfb_reg_base_addr,DB9000_ISR,pFxfb_local->db9000_reg.reg_ISR.all);
#ifdef PRINT_ISR_REG
 print_isrReg(pFxfb_local->fxfb_reg_base_addr,__FUNCTION__,__LINE__,isrCheckCount++);
#endif
#ifdef PRINT_ISR_REG
 print_isrReg(pFxfb_local->fxfb_reg_base_addr,__FUNCTION__,__LINE__,isrCheckCount++);
#endif
 FXFB_REG_READ(pFxfb_local->fxfb_reg_base_addr,DB9000_CR1,&pFxfb_local->db9000_reg.reg_CR1.all);
 pFxfb_local->db9000_reg.reg_CR1.bit.LPE = 1;
 pFxfb_local->db9000_reg.reg_CR1.bit.LCE = 1;
 FXFB_REG_WRITE(pFxfb_local->fxfb_reg_base_addr,DB9000_CR1,pFxfb_local->db9000_reg.reg_CR1.all);
 if (fxfb_get_board_revision(pFxfb_local) == FXFB_BOARD_TYPE_IS_C0_Vx1) {
  mdelay(2);
  FXFB_REG_READ(regAddr,BITMAPUI_LCD_LVDSVX1_CSR2,&reg);
  reg |= BITMAPUI_MASK_LVDSVX1_CSR2_VX1_TX_ENABLE;
  FXFB_REG_WRITE(regAddr,BITMAPUI_LCD_LVDSVX1_CSR2,reg);
  ret = db9000_wait_lockn_ok(pFxfb_local);
  if (ret < 0) {
   FXFB_ERR("db9000_wait_lockn_ok failed\n");
   self_ret = ret;
  }
  FXFB_REG_READ(regAddr,BITMAPUI_LCD_LVDSVX1_CSR2,&reg);
  reg |= BITMAPUI_MASK_LVDSVX1_CSR2_VX1_RX_PHY_LOCK;
  FXFB_REG_WRITE(regAddr,BITMAPUI_LCD_LVDSVX1_CSR2,reg);
 }
 iounmap((void *)regAddr);
 setbit(pFxfb_local->fxfb_status,FXFB_DRVSTS_ACTIVE);
 return self_ret;
}
int db9000_boot_setup(struct fb_info *info)
{
 PFXFBLOCAL pFxfb_local;
 pFxfb_local = (PFXFBLOCAL)info->par;
 FXFB_REG_WRITE(pFxfb_local->fxfb_reg_base_addr,DB9000_ISCR,VFP_COMMING_STATUS);
 db9000_setup_desc(info);
 FXFB_REG_READ(pFxfb_local->fxfb_reg_base_addr,DB9000_CR1,&pFxfb_local->db9000_reg.reg_CR1.all);
 pFxfb_local->db9000_reg.reg_CR1.bit.DFB = 1;
 pFxfb_local->db9000_reg.reg_CR1.bit.DFE = 1;
 FXFB_REG_WRITE(pFxfb_local->fxfb_reg_base_addr,DB9000_CR1,pFxfb_local->db9000_reg.reg_CR1.all);
 setbit(pFxfb_local->fxfb_status,FXFB_DRVSTS_ACTIVE);
 return FXFB_SUCCESS;
}
int32_t db9000_stop_non_interrupt(struct fb_info *info)
{
 FXFB_ALIGN_BYTES(PFXFBLOCAL pFxfb_local);
 FXFB_ALIGN_BYTES(volatile regISR regIsrData);
 FXFB_ALIGN_BYTES(int32_t timeOut);
 FXFB_ALIGN_BYTES(int32_t ret) = FXFB_SUCCESS;
 if (!info) {
  PUTFXFBMSG("%s() parameter \"info\" is NULL.\n",__FUNCTION__);
  fxfb_setErrorCode(EINVAL);
  return FXFB_ERROR;
 }
 pFxfb_local = (PFXFBLOCAL)info->par;
 FXFB_REG_READ(pFxfb_local->fxfb_reg_base_addr,DB9000_CR1,&pFxfb_local->db9000_reg.reg_CR1.all);
 if (!pFxfb_local->db9000_reg.reg_CR1.bit.LCE) {
  return FXFB_SUCCESS;
 }
 pFxfb_local->db9000_reg.reg_CR1.bit.LCE = 0;
 if ( pFxfb_local->db9000_reg.reg_CIR.bit.CIR_REV < DB9000_VERSION_1_14) {
  pFxfb_local->db9000_reg.reg_CR1.bit.DEE = 0;
 }
 FXFB_REG_WRITE(pFxfb_local->fxfb_reg_base_addr,DB9000_CR1,pFxfb_local->db9000_reg.reg_CR1.all);
 timeOut = 100;
 do {
  FXFB_REG_READ(pFxfb_local->fxfb_reg_base_addr,DB9000_ISR,&regIsrData.all);
  if (regIsrData.bit.LDD) {
   break;
  }
  ms_wait(1);
  timeOut--;
 } while(timeOut);
 if (!timeOut) {
  PUTFXFBMSG("%s() %s\n",__FUNCTION__,"interrupt wait timed out.");
  fxfb_setErrorCode(ETIMEDOUT);
  ret = FXFB_ERROR;
 } else {
  FXFB_REG_READ(pFxfb_local->fxfb_reg_base_addr,DB9000_CR1,&pFxfb_local->db9000_reg.reg_CR1.all);
  pFxfb_local->db9000_reg.reg_CR1.bit.LPE = 0;
  FXFB_REG_WRITE(pFxfb_local->fxfb_reg_base_addr,DB9000_CR1,pFxfb_local->db9000_reg.reg_CR1.all);
 }
 return ret;
}
int fxfb_hw_init(struct fb_info *info)
{
 volatile int32_t ret;
 FXFB_ALIGN_BYTES(PFXFBLOCAL pFxfb_local);
 if (!info) {
  PUTFXFBMSG("%s() parameter \"info\" is NULL.\n",__FUNCTION__);
  fxfb_setErrorCode(EINVAL);
  return fxfb_set_return_code(EINVAL);
 }
 pFxfb_local = (PFXFBLOCAL)info->par;
#ifdef PRINT_ISR_REG
 print_isrReg(pFxfb_local->fxfb_reg_base_addr,__FUNCTION__,__LINE__,isrCheckCount++);
#endif
 ret = db9000_setup(info);
 if (ret != FXFB_SUCCESS) {
  return fxfb_set_return_code(fxfb_getErrorCode());
 }
 if (db9000_error_condtion(pFxfb_local->fxfb_reg_base_addr)) {
  put_error_message(__FILE__,__FUNCTION__,__LINE__,EIO);
  ret = -EIO;
 }
 return ret;
}
int32_t db9000_change_addr(struct fb_info *info,bool doNotLock)
{
 FXFB_ALIGN_BYTES(PFXFBLOCAL pFxfb_local);
 volatile uint64_t dmaStartAddr;
 volatile uint64_t dmaEndAddr;
 FXFB_ALIGN_BYTES(volatile unsigned long flags) = 0UL;
 FXFB_ALIGN_BYTES(int32_t spinlocked);
 if (!info) {
  PUTFXFBMSG("%s() parameter \"info\" is NULL.\n",__FUNCTION__);
  fxfb_setErrorCode(EINVAL);
  return FXFB_ERROR;
 }
 pFxfb_local = (PFXFBLOCAL)info->par;
 if (!doNotLock) {
  fxfb_spin_lock(pFxfb_local,(unsigned long *)&flags,&spinlocked);
 } else {
  spinlocked = false;
 }
 if (db9000_error_condtion(pFxfb_local->fxfb_reg_base_addr)) {
  put_error_message(__FILE__,__FUNCTION__,__LINE__,EIO);
  fxfb_spin_unlock(pFxfb_local,flags,spinlocked);
  return FXFB_ERROR;
 }
 dmaStartAddr = pFxfb_local->fxfb_dma_busAddr;
 if (pFxfb_local->fxfb_cur_screen != FXFB_SCREEN_NO1) {
  dmaStartAddr += pFxfb_local->fxfb_screen_size;
 }
 dmaEndAddr = dmaStartAddr + pFxfb_local->fxfb_screen_size;
 if (pFxfb_local->dmaStartAddr != dmaStartAddr || pFxfb_local->dmaEndAddr != dmaEndAddr) {
  set_dma_addr(pFxfb_local,dmaStartAddr,dmaEndAddr);
 }
 fxfb_spin_unlock(pFxfb_local,flags,spinlocked);
 return FXFB_SUCCESS;
}
#if 0
int32_t db9000_stop_wait_cancel(struct fb_info *info)
{
 FXFB_ALIGN_BYTES(PFXFBLOCAL pFxfb_local);
 FXFB_ALIGN_BYTES(int32_t ret) = FXFB_SUCCESS;
 FXFB_ALIGN_BYTES(bool doIt);
 if (!info) {
  PUTFXFBMSG("%s() parameter \"info\" is NULL.\n",__FUNCTION__);
  fxfb_setErrorCode(EINVAL);
  return FXFB_ERROR;
 }
 pFxfb_local = (PFXFBLOCAL)info->par;
 fxfb_disable_irq(pFxfb_local);
 doIt = (bool)isset(pFxfb_local->waitStatus,DB9000_STOP_WAIT);
 if (!doIt) {
  fxfb_enable_irq(pFxfb_local);
  return ret;
 }
 setbit(pFxfb_local->waitCancelStatus,DB9000_STOP_WAIT);
 pFxfb_local->waitFlags[DB9000_STOP_WAIT] = TRUE;
 wake_up(&pFxfb_local->db9000_waitCtrl[DB9000_STOP_WAIT]);
 fxfb_enable_irq(pFxfb_local);
 do {
  doIt = (bool)isset(pFxfb_local->waitStatus,DB9000_STOP_WAIT);
  schedule();
 } while(doIt);
 fxfb_disable_irq(pFxfb_local);
 clrbit(pFxfb_local->waitCancelStatus,DB9000_STOP_WAIT);
 fxfb_enable_irq(pFxfb_local);
 return ret;
}
#endif
int32_t db9000_stop(struct fb_info *info,bool doNotLock)
{
 FXFB_ALIGN_BYTES(PFXFBLOCAL pFxfb_local);
 FXFB_ALIGN_BYTES(volatile unsigned long flags) = 0UL;
 FXFB_ALIGN_BYTES(volatile long timeOut);
 FXFB_ALIGN_BYTES(int32_t ret);
 FXFB_ALIGN_BYTES(int32_t spinlocked);
 if (!info) {
  PUTFXFBMSG("%s() parameter \"info\" is NULL.\n",__FUNCTION__);
  fxfb_setErrorCode(EINVAL);
  return FXFB_ERROR;
 }
 pFxfb_local = (PFXFBLOCAL)info->par;
 if (!doNotLock) {
  fxfb_spin_lock(pFxfb_local,(unsigned long *)&flags,&spinlocked);
 } else {
  spinlocked = false;
 }
 FXFB_REG_READ(pFxfb_local->fxfb_reg_base_addr,DB9000_CR1,&pFxfb_local->db9000_reg.reg_CR1.all);
 if (!isset(pFxfb_local->fxfb_status,FXFB_DRVSTS_ACTIVE) ||
   isset(pFxfb_local->fxfb_status,FXFB_DRVSTS_SUSPEND) || !pFxfb_local->db9000_reg.reg_CR1.bit.LCE) {
  fxfb_spin_unlock(pFxfb_local,flags,spinlocked);
#ifdef FXFB_DRVINFO
  PUTFXFBMSG("%s() db9000 is already stopped(not an error).\n",__FUNCTION__);
#endif
  return FXFB_SUCCESS;
 }
 if (db9000_error_condtion(pFxfb_local->fxfb_reg_base_addr)) {
  put_error_message(__FILE__,__FUNCTION__,__LINE__,EIO);
  fxfb_spin_unlock(pFxfb_local,flags,spinlocked);
  return FXFB_ERROR;
 }
 fxfb_disable_irq(pFxfb_local);
 fxfb_clear_all_irq(pFxfb_local);
 pFxfb_local->db9000_reg.reg_CR1.bit.LCE = 0;
 if ( pFxfb_local->db9000_reg.reg_CIR.bit.CIR_REV < DB9000_VERSION_1_14) {
  pFxfb_local->db9000_reg.reg_CR1.bit.DEE = 0;
 }
 set_isr_wait(pFxfb_local,DB9000_STOP_WAIT,(long *)&timeOut);
 FXFB_REG_WRITE(pFxfb_local->fxfb_reg_base_addr,DB9000_CR1,pFxfb_local->db9000_reg.reg_CR1.all);
 fxfb_spin_unlock(pFxfb_local,flags,spinlocked);
 fxfb_enable_irq(pFxfb_local);
 ret = isr_wait(pFxfb_local,DB9000_STOP_WAIT,timeOut);
 if (ret != FXFB_SUCCESS) {
  FXFB_ERR("isr_wait(STOP_WAIT) failed (timeOut=%ld)\n", timeOut);
  fxfb_nvm_err_countup(FXFB_NVM_ERR_LDD_TIMEOUT);
  pFxfb_local->fxfb_lddTimeoutCount++;
 }
 fxfb_disable_irq(pFxfb_local);
 fxfb_clear_all_irq(pFxfb_local);
 fxfb_spin_lock(pFxfb_local,(unsigned long *)&flags,&spinlocked);
 FXFB_REG_READ(pFxfb_local->fxfb_reg_base_addr,DB9000_CR1,&pFxfb_local->db9000_reg.reg_CR1.all);
 pFxfb_local->db9000_reg.reg_CR1.bit.LPE = 0;
 FXFB_REG_WRITE(pFxfb_local->fxfb_reg_base_addr,DB9000_CR1,pFxfb_local->db9000_reg.reg_CR1.all);
 clrbit(pFxfb_local->waitStatus,DB9000_STOP_WAIT);
 clrbit(pFxfb_local->fxfb_status,FXFB_DRVSTS_ACTIVE);
 fxfb_spin_unlock(pFxfb_local,flags,spinlocked);
 fxfb_enable_irq(pFxfb_local);
 return ret;
}
static int fxfb_setLvdsVx1TxPll(struct fb_info *info)
{
 FXFB_ALIGN_BYTES(PFXFBLOCAL pFxfb_local);
 volatile uint32_t gpfLcdAdr, lvdsVx1TxAdr;
 uint32_t reg, loopCnt;
 pFxfb_local = (PFXFBLOCAL)info->par;
 gpfLcdAdr = (uint32_t)ioremap(LCDGPF_BASE, 0x100);
 lvdsVx1TxAdr = (uint32_t)ioremap(LVDSVX1TX_BASE, 0x300);
 FXFB_REG_READ(gpfLcdAdr, BITMAPUI_LCD_LVDSVX1_CSR1, &reg);
 reg &= ~(BITMAPUI_MASK_LVDSVX1_CSR1_TX_PD);
 FXFB_REG_WRITE(gpfLcdAdr, BITMAPUI_LCD_LVDSVX1_CSR1, reg);
 FXFB_REG_READ(gpfLcdAdr, BITMAPUI_LCD_LVDSVX1_CSR1, &reg);
 reg |= BITMAPUI_MASK_LVDSVX1_CSR1_TX_NRST;
 FXFB_REG_WRITE(gpfLcdAdr, BITMAPUI_LCD_LVDSVX1_CSR1, reg);
 FXFB_REG_READ(lvdsVx1TxAdr, BITMAPUI_LVDSVX1TX_PLL0, &reg);
 reg |= BITMAPUI_MASK_LVDSVX1TX_PLL0_NRST;
 FXFB_REG_WRITE(lvdsVx1TxAdr, BITMAPUI_LVDSVX1TX_PLL0, reg);
 if (fxfb_get_board_revision(pFxfb_local) == FXFB_BOARD_TYPE_IS_C0_Vx1) {
  FXFB_REG_READ(lvdsVx1TxAdr, BITMAPUI_LVDSVX1TX_PLL0, &reg);
  reg |= BITMAPUI_MASK_LVDSVX1TX_PLL0_FR;
  FXFB_REG_WRITE(lvdsVx1TxAdr, BITMAPUI_LVDSVX1TX_PLL0, reg);
  FXFB_REG_WRITE(lvdsVx1TxAdr, BITMAPUI_LVDSVX1TX_M, BITMAPUI_VAL_LVDSVX1TX_M__C0_VX1);
  FXFB_REG_WRITE(lvdsVx1TxAdr, BITMAPUI_LVDSVX1TX_N0,
        BITMAPUI_VAL_LVDSVX1TX_N__C0_VX1 & 0xFF);
  FXFB_REG_WRITE(lvdsVx1TxAdr, BITMAPUI_LVDSVX1TX_N1,
        (BITMAPUI_VAL_LVDSVX1TX_N__C0_VX1 >> 8) & 0xFF);
  FXFB_REG_WRITE(lvdsVx1TxAdr, BITMAPUI_LVDSVX1TX_N2,
        (BITMAPUI_VAL_LVDSVX1TX_N__C0_VX1 >> 16) & 0xFF);
  FXFB_REG_WRITE(lvdsVx1TxAdr, BITMAPUI_LVDSVX1TX_N3,
        0x20 | ((BITMAPUI_VAL_LVDSVX1TX_N__C0_VX1 >> 24) & 0x07));
  FXFB_REG_WRITE(lvdsVx1TxAdr, BITMAPUI_LVDSVX1TX_PLL1,
        BITMAPUI_VAL_LVDSVX1TX_PLL1__C0_VX1);
  FXFB_REG_WRITE(lvdsVx1TxAdr, BITMAPUI_LVDSVX1TX_PLL2,
        BITMAPUI_VAL_LVDSVX1TX_PLL2__C0_VX1);
 }
 else {
  FXFB_REG_READ(lvdsVx1TxAdr, BITMAPUI_LVDSVX1TX_PLL0, &reg);
  reg &= ~(BITMAPUI_MASK_LVDSVX1TX_PLL0_FR);
  FXFB_REG_WRITE(lvdsVx1TxAdr, BITMAPUI_LVDSVX1TX_PLL0, reg);
  FXFB_REG_WRITE(lvdsVx1TxAdr, BITMAPUI_LVDSVX1TX_M, BITMAPUI_VAL_LVDSVX1TX_M);
  FXFB_REG_WRITE(lvdsVx1TxAdr, BITMAPUI_LVDSVX1TX_N0, BITMAPUI_VAL_LVDSVX1TX_N0);
  FXFB_REG_WRITE(lvdsVx1TxAdr, BITMAPUI_LVDSVX1TX_N1, BITMAPUI_VAL_LVDSVX1TX_N1);
  FXFB_REG_WRITE(lvdsVx1TxAdr, BITMAPUI_LVDSVX1TX_N2, BITMAPUI_VAL_LVDSVX1TX_N2);
  FXFB_REG_READ(lvdsVx1TxAdr, BITMAPUI_LVDSVX1TX_N3, &reg);
  reg &= ~(BITMAPUI_MASK_LVDSVX1TX_N3_N);
  FXFB_REG_WRITE(lvdsVx1TxAdr, BITMAPUI_LVDSVX1TX_N3, reg);
  FXFB_REG_READ(lvdsVx1TxAdr, BITMAPUI_LVDSVX1TX_N3, &reg);
  reg &= ~(BITMAPUI_MASK_LVDSVX1TX_N3_CP_I_SEL);
  FXFB_REG_WRITE(lvdsVx1TxAdr, BITMAPUI_LVDSVX1TX_N3,
        reg | (BITMAPUI_VAL_LVDSVX1TX_N3_CP_I_SEL << (BITMAPUI_SHIFT_LVDSVX1TX_N3_CP_I_SEL)));
  FXFB_REG_READ(lvdsVx1TxAdr, BITMAPUI_LVDSVX1TX_PLL1, &reg);
  reg &= ~(BITMAPUI_MASK_LVDSVX1TX_PLL1_C1 | BITMAPUI_MASK_LVDSVX1TX_PLL1_C2 | BITMAPUI_MASK_LVDSVX1TX_PLL1_R);
  reg |= ((BITMAPUI_VAL_LVDSVX1TX_PLL1_C1 << BITMAPUI_SHIFT_LVDSVX1TX_PLL1_C1) |
    (BITMAPUI_VAL_LVDSVX1TX_PLL1_C2 << BITMAPUI_SHIFT_LVDSVX1TX_PLL1_C2) |
    (BITMAPUI_VAL_LVDSVX1TX_PLL1_R << BITMAPUI_SHIFT_LVDSVX1TX_PLL1_R ));
  FXFB_REG_WRITE(lvdsVx1TxAdr, BITMAPUI_LVDSVX1TX_PLL1, reg);
  FXFB_REG_READ(lvdsVx1TxAdr, BITMAPUI_LVDSVX1TX_PLL2, &reg);
  reg &= ~(BITMAPUI_MASK_LVDSVX1TX_PLL2_R3);
  reg |= BITMAPUI_VAL_LVDSVX1TX_PLL2_R3;
  FXFB_REG_WRITE(lvdsVx1TxAdr, BITMAPUI_LVDSVX1TX_PLL2, reg);
 }
 FXFB_REG_WRITE(lvdsVx1TxAdr, BITMAPUI_LVDSVX1TX_MISC0, BITMAPUI_VAL_LVDSVX1TX_MISC0);
 if (fxfb_get_board_revision(pFxfb_local) == FXFB_BOARD_TYPE_IS_C0_Vx1) {
  FXFB_REG_WRITE(lvdsVx1TxAdr, BITMAPUI_LVDSVX1TX_LVDS0,
        BITMAPUI_VAL_LVDSVX1TX_LVDS0__C0_VX1);
  FXFB_REG_WRITE(lvdsVx1TxAdr, BITMAPUI_LVDSVX1TX_LVDS1,
        BITMAPUI_VAL_LVDSVX1TX_LVDS1__C0_VX1);
 }
 else {
  FXFB_REG_READ(lvdsVx1TxAdr, BITMAPUI_LVDSVX1TX_LVDS1, &reg);
  reg &= ~(BITMAPUI_MASK_LVDSVX1TX_LVDS1_LANE_PD);
  FXFB_REG_WRITE(lvdsVx1TxAdr, BITMAPUI_LVDSVX1TX_LVDS1, reg);
 }
 if (fxfb_get_board_revision(pFxfb_local) == FXFB_BOARD_TYPE_IS_A0) {
  FXFB_REG_WRITE(gpfLcdAdr, BITMAPUI_LCD_PCLK_DIVCTRL_A0,
        BITMAPUI_VAL_PCLK_DIVCTRL & 0xffffff00);
 }
 else if (fxfb_get_board_revision(pFxfb_local) == FXFB_BOARD_TYPE_IS_C0_Vx1) {
  FXFB_REG_WRITE(gpfLcdAdr, BITMAPUI_LCD_PCLK_DIVCTRL_B0,
        BITMAPUI_VAL_PCLK_DIVCTRL__C0_VX1 & 0xffffff00);
 }
 else {
  FXFB_REG_WRITE(gpfLcdAdr, BITMAPUI_LCD_PCLK_DIVCTRL_B0,
        BITMAPUI_VAL_PCLK_DIVCTRL & 0xffffff00);
 }
 FXFB_REG_READ(lvdsVx1TxAdr, BITMAPUI_LVDSVX1TX_PLL0, &reg);
 reg &= ~(BITMAPUI_MASK_LVDSVX1_PLL0_LPFRST);
 FXFB_REG_WRITE(lvdsVx1TxAdr, BITMAPUI_LVDSVX1TX_PLL0, reg);
 loopCnt = BITMAPUI_LOOP_LIMIT;
 reg = 0;
 while (((reg & BITMAPUI_TX_PLL_LOCK) != BITMAPUI_TX_PLL_LOCK) && (loopCnt != 0)) {
  FXFB_REG_READ(gpfLcdAdr, BITMAPUI_LCD_LVDSVX1_CSR1, &reg);
  loopCnt--;
 }
 if (loopCnt == 0) {
  PUTFXFBMSG("%s() did not achieve lock status ERROR in bitmapuiSetLvdsVx1TxPll.\n",__FUNCTION__);
  fxfb_setErrorCode(ETIMEDOUT);
  iounmap((void *)gpfLcdAdr);
  iounmap((void *)lvdsVx1TxAdr);
  return FXFB_ERROR;
 }
 if (fxfb_get_board_revision(pFxfb_local) == FXFB_BOARD_TYPE_IS_A0) {
  FXFB_REG_WRITE(gpfLcdAdr, BITMAPUI_LCD_PCLK_CST_A0, BITMAPUI_VAL_PCLK_CST);
  FXFB_REG_WRITE(gpfLcdAdr, BITMAPUI_LCD_PCLK_DIVCTRL_A0, BITMAPUI_VAL_PCLK_DIVCTRL);
 }
 else if (fxfb_get_board_revision(pFxfb_local) == FXFB_BOARD_TYPE_IS_C0_Vx1) {
  FXFB_REG_WRITE(gpfLcdAdr, BITMAPUI_LCD_PCLK_CST_B0, BITMAPUI_VAL_PCLK_CST);
  FXFB_REG_WRITE(gpfLcdAdr, BITMAPUI_LCD_PCLK_DIVCTRL_B0, BITMAPUI_VAL_PCLK_DIVCTRL__C0_VX1);
 }
 else {
  FXFB_REG_WRITE(gpfLcdAdr, BITMAPUI_LCD_PCLK_CST_B0, BITMAPUI_VAL_PCLK_CST);
  FXFB_REG_WRITE(gpfLcdAdr, BITMAPUI_LCD_PCLK_DIVCTRL_B0, BITMAPUI_VAL_PCLK_DIVCTRL);
 }
 iounmap((void *)gpfLcdAdr);
 iounmap((void *)lvdsVx1TxAdr);
 return FXFB_SUCCESS;
}
int32_t db9000_lcd_reset(struct fb_info *info)
{
 PFXFBLOCAL pFxfb_local;
 volatile uint32_t rstAddr;
 volatile uint32_t reg;
 if (!info) {
  PUTFXFBMSG("%s() parameter \"info\" is NULL.\n",__FUNCTION__);
  fxfb_setErrorCode(EINVAL);
  return fxfb_set_return_code(EINVAL);
 }
 pFxfb_local = (PFXFBLOCAL)info->par;
 rstAddr = (uint32_t)ioremap(RSTGEN_BASE, PAGE_SIZE);
 FXFB_REG_READ(rstAddr, RSTGEN_RSTGENSWRSTSTATIC6, &reg);
 reg |= RSTGEN_RSTGENSWRSTSTATIC6_MASK_MFP_LCD;
 reg |= RSTGEN_RSTGENSWRSTSTATIC6_MASK_MFP_LCD_SHORT;
 reg |= RSTGEN_RSTGENSWRSTSTATIC6_MASK_MFP_LCD_MEDIUM;
 FXFB_REG_WRITE(rstAddr, RSTGEN_RSTGENSWRSTSTATIC6, reg);
 ndelay(60);
 FXFB_REG_READ(rstAddr, RSTGEN_RSTGENSWRSTSTATIC6, &reg);
 reg &= ~RSTGEN_RSTGENSWRSTSTATIC6_MASK_MFP_LCD_SHORT;
 FXFB_REG_WRITE(rstAddr, RSTGEN_RSTGENSWRSTSTATIC6, reg);
 FXFB_REG_READ(rstAddr, RSTGEN_RSTGENSWRSTSTATIC6, &reg);
 reg &= ~RSTGEN_RSTGENSWRSTSTATIC6_MASK_MFP_LCD_MEDIUM;
 FXFB_REG_WRITE(rstAddr, RSTGEN_RSTGENSWRSTSTATIC6, reg);
 FXFB_REG_READ(rstAddr, RSTGEN_RSTGENSWRSTSTATIC6, &reg);
 reg &= ~RSTGEN_RSTGENSWRSTSTATIC6_MASK_MFP_LCD;
 FXFB_REG_WRITE(rstAddr, RSTGEN_RSTGENSWRSTSTATIC6, reg);
 ndelay(60);
 iounmap((void *)rstAddr);
 return FXFB_SUCCESS;
}
int32_t db9000_wake_up(struct fb_info *info,bool doNotLock)
{
 FXFB_ALIGN_BYTES(PFXFBLOCAL pFxfb_local);
 FXFB_ALIGN_BYTES(int32_t ret) = FXFB_SUCCESS;
 FXFB_ALIGN_BYTES(int32_t mutexlocked);
 if (!info) {
  PUTFXFBMSG("%s() parameter \"info\" is NULL.\n",__FUNCTION__);
  fxfb_setErrorCode(EINVAL);
  return fxfb_set_return_code(EINVAL);
 }
 pFxfb_local = (PFXFBLOCAL)info->par;
 put_function_start_message(__FILE__,__FUNCTION__,__LINE__);
 if (!doNotLock) {
  fxfb_mutex_lock(pFxfb_local,&mutexlocked);
 } else {
  mutexlocked = false;
 }
 fxfb_disable_irq(pFxfb_local);
 fxfb_clear_all_irq(pFxfb_local);
 ret = db9000_lcd_reset(info);
 if (ret != FXFB_SUCCESS) {
  FXFB_ERR("db9000_lcd_reset failed (ret=%d)\n", ret);
  goto db9000_wake_up_exit;
 }
 ret = fxfb_setLvdsVx1TxPll(info);
 if (ret != FXFB_SUCCESS) goto db9000_wake_up_exit;
 ret = fxfb_hw_init(info);
 fxfb_enable_irq(pFxfb_local);
 if (ret != FXFB_SUCCESS) {
  goto db9000_wake_up_exit;
 }
 clrbit(pFxfb_local->fxfb_status,FXFB_DRVSTS_SUSPEND);
 pFxfb_local->fxfb_locknDropLogCount = 0;
db9000_wake_up_exit:
 put_error_message(__FILE__,__FUNCTION__,__LINE__,ret);
 fxfb_mutex_unlock(pFxfb_local,mutexlocked);
 return ret;
}
int32_t db9000_power_down(struct fb_info *info,bool doNotLock)
{
 FXFB_ALIGN_BYTES(PFXFBLOCAL pFxfb_local);
 FXFB_ALIGN_BYTES(int32_t ret) = FXFB_SUCCESS;
 FXFB_ALIGN_BYTES(int32_t mutexlocked);
 if (!info) {
  PUTFXFBMSG("%s() parameter \"info\" is NULL.\n",__FUNCTION__);
  fxfb_setErrorCode(EINVAL);
  return fxfb_set_return_code(EINVAL);
 }
 pFxfb_local = (PFXFBLOCAL)info->par;
 put_function_start_message(__FILE__,__FUNCTION__,__LINE__);
 if (!doNotLock) {
  fxfb_mutex_lock(pFxfb_local,&mutexlocked);
 } else {
  mutexlocked = false;
 }
 (void)fxfb_set_screen_OFF(info,false);
 setbit(pFxfb_local->fxfb_status,FXFB_DRVSTS_SUSPEND);
 fxfb_mutex_unlock(pFxfb_local,mutexlocked);
 put_error_message(__FILE__,__FUNCTION__,__LINE__,ret);
 return ret;
}
int32_t db9000_reset(struct fb_info *info)
{
 FXFB_ALIGN_BYTES(PFXFBLOCAL pFxfb_local);
 FXFB_ALIGN_BYTES(int32_t self_ret) = FXFB_SUCCESS;
 FXFB_ALIGN_BYTES(int32_t ret) = FXFB_SUCCESS;
 FXFB_ALIGN_BYTES(int32_t mutexlocked);
 FXFB_ALIGN_BYTES(bool is_suspended);
 volatile uint32_t rstAddr;
 volatile uint32_t lcdgpfAddr;
 volatile uint32_t reg;
 volatile regISR regIsrData;
 volatile long timeOut;
 FXFB_FUNC_ENTRY_INFO();
 if (!info) {
  PUTFXFBMSG("%s() parameter \"info\" is NULL.\n",__FUNCTION__);
  fxfb_setErrorCode(EINVAL);
  return fxfb_set_return_code(EINVAL);
 }
 pFxfb_local = (PFXFBLOCAL)info->par;
 lcdgpfAddr = (uint32_t)ioremap(LCDGPF_BASE,PAGE_SIZE);
 fxfb_mutex_lock(pFxfb_local,&mutexlocked);
 fxfb_nvm_err_countup(FXFB_NVM_ERR_VSYNC);
 is_suspended = (bool)isset(pFxfb_local->fxfb_status, FXFB_DRVSTS_SUSPEND);
 if (is_suspended) {
  FXFB_ERR("power save mode. canceled reset process.\n");
  self_ret = fxfb_set_return_code(EIO);
  goto RESET_END;
 }
 fxfb_dbg_reg_store(FXFB_REG_VAL_ERR1, false);
 fxfb_disable_irq(pFxfb_local);
 fxfb_clear_all_irq(pFxfb_local);
 FXFB_REG_READ(pFxfb_local->fxfb_reg_base_addr, DB9000_CR1, &pFxfb_local->db9000_reg.reg_CR1.all);
 pFxfb_local->db9000_reg.reg_CR1.bit.LCE = 0;
 FXFB_REG_WRITE(pFxfb_local->fxfb_reg_base_addr, DB9000_CR1, pFxfb_local->db9000_reg.reg_CR1.all);
 timeOut = 100;
 do {
  FXFB_REG_READ(pFxfb_local->fxfb_reg_base_addr, DB9000_ISR, &regIsrData.all);
  if (regIsrData.bit.LDD) {
   break;
  }
  ms_wait(1);
  timeOut--;
 } while(timeOut);
 if (!timeOut) {
  FXFB_ERR("LDD interrupt wait timed out\n");
 }
 FXFB_INFO("wait LDD (ISR : 0x%x, time : %ld ms)\n", regIsrData.bit.LDD, 100-timeOut);
 if (fxfb_get_board_revision(pFxfb_local) == FXFB_BOARD_TYPE_IS_C0_Vx1) {
  rstAddr = (uint32_t)ioremap(RSTGEN_BASE, PAGE_SIZE);
  FXFB_REG_READ(rstAddr, RSTGEN_RSTGENSWRSTSTATIC6, &reg);
  reg |= RSTGEN_RSTGENSWRSTSTATIC6_MASK_MFP_LCD;
  reg |= RSTGEN_RSTGENSWRSTSTATIC6_MASK_MFP_LCD_SHORT;
  reg |= RSTGEN_RSTGENSWRSTSTATIC6_MASK_MFP_LCD_MEDIUM;
  FXFB_REG_WRITE(rstAddr, RSTGEN_RSTGENSWRSTSTATIC6, reg);
  ndelay(60);
  mdelay(10);
  FXFB_REG_READ(rstAddr, RSTGEN_RSTGENSWRSTSTATIC6, &reg);
  reg &= ~RSTGEN_RSTGENSWRSTSTATIC6_MASK_MFP_LCD_SHORT;
  FXFB_REG_WRITE(rstAddr, RSTGEN_RSTGENSWRSTSTATIC6, reg);
  FXFB_REG_READ(rstAddr, RSTGEN_RSTGENSWRSTSTATIC6, &reg);
  reg &= ~RSTGEN_RSTGENSWRSTSTATIC6_MASK_MFP_LCD_MEDIUM;
  FXFB_REG_WRITE(rstAddr, RSTGEN_RSTGENSWRSTSTATIC6, reg);
  FXFB_REG_READ(rstAddr, RSTGEN_RSTGENSWRSTSTATIC6, &reg);
  reg &= ~RSTGEN_RSTGENSWRSTSTATIC6_MASK_MFP_LCD;
  FXFB_REG_WRITE(rstAddr, RSTGEN_RSTGENSWRSTSTATIC6, reg);
  ndelay(60);
  iounmap((void *)rstAddr);
 }
 else {
  ret = db9000_lcd_reset(info);
  if (ret != FXFB_SUCCESS) {
   FXFB_ERR("db9000_lcd_reset failed (ret=%d)\n", ret);
   self_ret = ret;
  }
 }
 ret = fxfb_setLvdsVx1TxPll(info);
 if (ret != FXFB_SUCCESS) {
  FXFB_ERR("fxfb_setLvdsVx1TxPll failed\n");
  self_ret = ret;
 }
 ret = fxfb_hw_init(info);
 if (ret != FXFB_SUCCESS) {
  FXFB_ERR("fxfb_hw_init failed\n");
  self_ret = ret;
 }
 fxfb_enable_irq(pFxfb_local);
RESET_END:
 fxfb_mutex_unlock(pFxfb_local,mutexlocked);
 iounmap((void *)lcdgpfAddr);
 FXFB_FUNC_EXIT_INFO();
 return self_ret;
}
int32_t db9000_recover_lockn(struct fb_info *info)
{
 PFXFBLOCAL pFxfb_local;
 int32_t mutexlocked;
 volatile uint32_t regAddr;
 volatile uint32_t reg;
 bool is_suspended;
 int32_t ret;
 int32_t self_ret = FXFB_SUCCESS;
 if (!info) {
  PUTFXFBMSG("%s() parameter \"info\" is NULL.\n",__FUNCTION__);
  fxfb_setErrorCode(EINVAL);
  return fxfb_set_return_code(EINVAL);
 }
 pFxfb_local = (PFXFBLOCAL)info->par;
 FXFB_LOCKN_INFO(pFxfb_local, "%s enter\n", __FUNCTION__);
 regAddr = (uint32_t)ioremap(LCDGPF_BASE,PAGE_SIZE);
 fxfb_mutex_lock(pFxfb_local,&mutexlocked);
 is_suspended = (bool)isset(pFxfb_local->fxfb_status, FXFB_DRVSTS_SUSPEND);
 if (is_suspended) {
  FXFB_ERR("power save mode. canceled recovery process.\n");
  self_ret = fxfb_set_return_code(EIO);
  goto RECOVERY_END;
 }
 if (db9000_check_lockn_ok()) {
  FXFB_LOCKN_ERR(pFxfb_local, "already locked\n");
  goto RECOVERY_END;
 }
 FXFB_REG_READ(regAddr,BITMAPUI_LCD_LVDSVX1_CSR2,&reg);
 reg &= ~(BITMAPUI_MASK_LVDSVX1_CSR2_VX1_TX_ENABLE
    | BITMAPUI_MASK_LVDSVX1_CSR2_VX1_RX_PHY_LOCK);
 FXFB_REG_WRITE(regAddr,BITMAPUI_LCD_LVDSVX1_CSR2,reg);
 FXFB_REG_READ(regAddr,BITMAPUI_LCD_LVDSVX1_CSR2,&reg);
 reg |= BITMAPUI_MASK_LVDSVX1_CSR2_VX1_TX_ENABLE;
 FXFB_REG_WRITE(regAddr,BITMAPUI_LCD_LVDSVX1_CSR2,reg);
 ret = db9000_wait_lockn_ok(pFxfb_local);
 if (ret != FXFB_SUCCESS) {
  FXFB_LOCKN_ERR(pFxfb_local, "db9000_wait_lockn_ok failed\n");
  self_ret = ret;
 }
 FXFB_REG_READ(regAddr,BITMAPUI_LCD_LVDSVX1_CSR2,&reg);
 reg |= BITMAPUI_MASK_LVDSVX1_CSR2_VX1_RX_PHY_LOCK;
 FXFB_REG_WRITE(regAddr,BITMAPUI_LCD_LVDSVX1_CSR2,reg);
RECOVERY_END:
 fxfb_mutex_unlock(pFxfb_local,mutexlocked);
 iounmap((void *)regAddr);
 FXFB_LOCKN_INFO(pFxfb_local, "%s exit\n", __FUNCTION__);
 return self_ret;
}
