//==========================================================================
//
//      mxc_ipu.c
//
//      IPU support on Freescale MXC platforms, base on Freescale Linux BSP
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos 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 or (at your option) any later version.
//
// eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s):
// Contributors:
// Date:
// Purpose:
// Description:
// Copyright:    2008 Kinpo Beijing, Inc.
//
//####DESCRIPTIONEND####
//
//==========================================================================
//V01.1   2008.03.28  modified framebuffer_mxc.cdl use libextras.a,
//                    RedBoot_init and others.
//
//
//============================================================================

#include <redboot.h>
#include <stdlib.h>
#include <pkgconf/hal.h>
#include <cyg/hal/hal_arch.h>
#include <cyg/hal/hal_cache.h>
#include <cyg/hal/hal_io.h>
#include <cyg/hal/hal_soc.h>
#include <cyg/io/mxc_ipu.h>
#include <cyg/io/mx31_pins.h>
#include <cyg/io/crm_regs.h>
//#include <include/img.h>
#define writemaskval(addr, mask, val) writel(((readl(addr)&(~(mask))) | val),addr)

#define writeval(x, y)      writel(readl(x)|(y),x)

#define DELAYTIMEOUT                1000
#define FLOW_ARM                    0
#define eBUF_0 0
#define SDC_DMA_CHANNEL 14


typedef struct {
    cyg_uint32 datamasken:1;
    cyg_uint32 clkidleen :1;
    cyg_uint32 clkselen  :1;
    cyg_uint32 vsyncpol  :1;
    cyg_uint32 outenable :1;
    cyg_uint32 datapolinvert :1;
    cyg_uint32 clkrise    :1;
    cyg_uint32 hsyncactive  :1;
    cyg_uint32 Dummy      :24;
} ipu_di_signal;

typedef struct panelstruc{
    cyg_uint32 pixel_fmt;
    cyg_uint32 bpp;
    cyg_uint32 xres;
    cyg_uint32 yres;
    cyg_uint32 left_margin;
    cyg_uint32 right_margin;
    cyg_uint32 upper_margin;
    cyg_uint32 lower_margin;
    cyg_uint32 hsync_len;
    cyg_uint32 vsync_len;
    ipu_di_signal sync;
}panel_info;

#define TRUE 1
#define FALSE 0
#define ENABLE 1

static const cyg_uint32 di_mappings[] = {
	0x1600AAAA, 0x00E05555, 0x00070000, 3,	/* RGB888 */
	0x0005000F, 0x000B000F, 0x0011000F, 1,	/* RGB666 */
	0x0011000F, 0x000B000F, 0x0005000F, 1,	/* BGR666 */
	0x0005000F, 0x000b000F, 0x0011000F, 1	/* RGB565 */
};




enum {
	PIX_FMT_RGB888=0,
	PIX_FMT_RGB666=1,
        PIX_FMT_BGR666=2,
        PIX_FMT_RGB565=3,
};

cyg_uint32 Temp;

panel_info currentPanel={
        PIX_FMT_RGB565,
        16,//16bpp
        320, 240, 20,  20,  17, 17, 10,  4,
        {
            FALSE,
            FALSE,
            FALSE,
            FALSE,
            FALSE,
            FALSE,
            TRUE,
            FALSE,
        }
};
#define OFS0_SHIFT (99-96)
#define OFS1_SHIFT (104-96)
#define OFS2_SHIFT (109-96)
#define OFS3_SHIFT (114-96)

#define WID0_SHIFT (119-96)
#define WID1_SHIFT (122-96)
#define WID2_SHIFT (125-96)
#define WID3_SHIFT (128-128)
#define NSB (46-32)
#define FW  (108-96)
#define FH_L (120-96)
#define FH_H (132-128)

#define MEM_NU_SHIFT 16
#define ROW_NU_SHIFT 3
#define WORD_NU_SHIFT 0
#define IDMAC   1

#define BPP_SHIFT (64-64)
#define SL_SHIFT  (67-64)
#define PFS_SHIFT (81-64)
#define BAM_SHIFT (84-64)
#define NPB_SHIFT (89-64)
#define SAT_SHIFT (96-96)
cyg_uint32 bamdata=0;//no flip
cyg_uint32 pfsdata=0;
cyg_uint32 bppdata=0;
cyg_uint32 npbdata=0;
cyg_uint32 ofsdata=0;
cyg_uint32 widdata=0;
cyg_uint32 stadata=0;//mcu access type 0:8bit 1:16bit 2:32bit 3:reserved


//-----------------------------------------------------------------------------
//
// Function: ipu_set_bpp
//
// This function is get npb,ofs,wid,bpp register data according bpp.
//
// Parameters:

//      bpp      bit per pixel.
//          [in]
//
// Returns:
//      cyg_uint32
//
//-----------------------------------------------------------------------------
cyg_uint32 ipu_set_bpp(cyg_uint8 bpp)
{
	switch(bpp)
	{
		case 1:
		npbdata=0x3f;
		ofsdata=0;
		widdata=0;
		   return 5;
		case 4:
		npbdata=0x1f;
		ofsdata=0;
		widdata=3;
		   return 4;
		case 8:
		npbdata=0x1f;
		ofsdata=0;//8bit
		widdata=7;//8-1
		   return 3;
		case 16:
		npbdata=0xf;
		ofsdata=(0<<OFS0_SHIFT)|(5<<OFS1_SHIFT)|(11<<OFS2_SHIFT);//16bit
		widdata=(4<<WID0_SHIFT)|(5<<WID1_SHIFT)|(4<<WID2_SHIFT);//rgb565
		   return 2;
		case 24:
		npbdata=0x9;
		ofsdata=(0<<OFS0_SHIFT)|(8<<OFS1_SHIFT)|(16<<OFS2_SHIFT);//24bit
		widdata=(7<<WID0_SHIFT)|(7<<WID1_SHIFT)|(7<<WID2_SHIFT);//rgb888 0= 1bit so 7=8bit
		   return 1;
		case 32:
		npbdata=0x7;
		ofsdata=(0<<OFS0_SHIFT)|(8<<OFS1_SHIFT)|(16<<OFS2_SHIFT)|(24<<OFS3_SHIFT);//32bit,ofs3 is for alpha
		widdata=(7<<WID0_SHIFT)|(7<<WID1_SHIFT)|(7<<WID2_SHIFT);//rgb8888 know wid3 need write next 32bit data
		   return 0;
                default:
		   return 0xff;
	}
}

//-----------------------------------------------------------------------------
//
// Function: init_ipu_dma_buffer
//
// This function init ipu dma buffer
//
// Parameters:

//      width      current frame buffer width.
//          [in]
//      height     current frame buffer height.
//          [in]
//      channel    use sdc dma channel
//          [in]
// Returns:
//      NULL
//
//-----------------------------------------------------------------------------

void init_ipu_dma_buffer(cyg_uint32 width, cyg_uint32 height, cyg_uint32 channel,cyg_uint32 bpp)
{

    cyg_uint32  newVal;

//-----Word 0 for 2*N---------
    newVal=(IDMAC<<MEM_NU_SHIFT)|((2*channel)<<ROW_NU_SHIFT)|(0<<WORD_NU_SHIFT);//from the 1st address start to write
//    oldVal = readl(IPU_IMA_ADDR);

    for(Temp=0; Temp <40000; Temp++);
    writel(newVal,IPU_IMA_ADDR);
    for(Temp=0; Temp <40000; Temp++);
//--------Word0 is 132bit---------
    // Word0--1st 32bit
    writel(0,IPU_IMA_DATA);
    // Word0--2nd 32bit
    writel(1<<NSB,IPU_IMA_DATA);//NSB bit which should initialized to one
    // Word0--3rd 32bit
    writel(0,IPU_IMA_DATA);
    // Word0--4th 32bit
    writel(((width - 1)<<FW)|(((height - 1)&0x00ff)<<FH_L),IPU_IMA_DATA);//(width - 1)= width pixel
    // Word0--5th 8bit
    writel((((height - 1)&0xff00) >>FH_H),IPU_IMA_DATA);

//-----Word 1 for 2*N+1---------
    writel((IDMAC<<MEM_NU_SHIFT)|((2 * channel + 1)<<ROW_NU_SHIFT)|(2<<WORD_NU_SHIFT),IPU_IMA_ADDR);//because we do not use Double buffer,we need not set EBA0,EBA1.So from the 3rd address start to write
    for(Temp=0; Temp <40000; Temp++);
  //--------Word1 is 132bit---------
    // Word1--2nd 32bit
    bppdata=ipu_set_bpp(bpp);

    pfsdata=4;//this is set to RGB
    writel((bppdata<<BPP_SHIFT)|(((width * bpp /8) - 1)<<SL_SHIFT)| (pfsdata<<PFS_SHIFT) | (bamdata<<BAM_SHIFT) | (npbdata<<NPB_SHIFT),IPU_IMA_DATA);
    // Word1--3rd 32bit
    stadata=1;
    writel((stadata<<SAT_SHIFT)|ofsdata|widdata,IPU_IMA_DATA);
    // Word0--4th 32bit
    writel(0,IPU_IMA_DATA);//wid3 is alpha,we set 0

    writel(0,IPU_IMA_ADDR);//over
}

//-----------------------------------------------------------------------------
//
// Function: iomux_config_mux
//
// This function config iomux pin
//
// Parameters:

//      pin
//          [in]
//      out         outputfunction
//          [in]
//      in          inputfunction
//          [in]

// Returns:
//      NULL
//
//-----------------------------------------------------------------------------

void iomux_config_mux(unsigned int pin, int out, int in)
{
    volatile cyg_uint32 *base =(volatile cyg_uint32 *)(IOMUXC_BASE_ADDR + 0xc);
    cyg_uint32 mux_index = PIN_TO_IOMUX_INDEX(pin);
    cyg_uint32 mux_field = PIN_TO_IOMUX_FIELD(pin);

    base[mux_index] =(base[mux_index] & (~(0xFF << (mux_field * MUX_CTL_BIT_LEN)))) |(((out << 4) | in) << (mux_field * MUX_CTL_BIT_LEN));
}

extern void cpld_lcdblk(int on);
//-----------------------------------------------------------------------------
//
// Function: ipu_enable_sdc_bg
//
// This function enable sdc bg.
//
// Parameters:

//      flag
//          [in] true is enable,false is disable
// Returns:
//      NULL
//
//-----------------------------------------------------------------------------

void ipu_enable_sdc_bg(bool flag)
{
    if(flag==ENABLE)
	writel(readl(SDC_COM_CONF)| SDC_COM_BG_EN, SDC_COM_CONF);
    else
        writel(readl(SDC_COM_CONF)&(~ SDC_COM_BG_EN), SDC_COM_CONF);
}

//-----------------------------------------------------------------------------
//
// Function: ipu_config_sdc
//
// This function config ipu configer register for sdc.
//
// Parameters:

//         NULL
// Returns:
//      NULL
//
//-----------------------------------------------------------------------------
void ipu_config_sdc(void)
{

    writel((readl(IPU_CONF)|IPU_CONF_SDC_EN|IPU_CONF_DI_EN)&(~IPU_CONF_PXL_ENDIAN) ,IPU_CONF);
}
//-----------------------------------------------------------------------------
//
// Function: ipu_dma_channel_enable
//
// This function enable idma channel .
//
// Parameters:
//           channel  channel mask
//              [in]
//             flag TRUE is enable,Flase is disable
// Returns:
//      NULL
//
//-----------------------------------------------------------------------------
void ipu_dma_channel_enable(cyg_uint32 channel,bool flag)
{
	if(flag==TRUE)
		writel(readl(IDMAC_CHA_EN)|channel,IDMAC_CHA_EN);
	else
		writel(readl(IDMAC_CHA_EN)&(~channel),IDMAC_CHA_EN);
}
//-----------------------------------------------------------------------------
//
// Function: ipu_enable_sdc
//
// This function is used to enable sdc.
//
// Parameters:
//      NULL

// Returns:
//      NULL
//
//-----------------------------------------------------------------------------
#define DI_EN_SHIFT 6
#define SDC_EN_SHIFT 4
#define ENABLE 1
#define DMASDC_0_CHAN_EN SDC_DMA_CHANNEL
void ipu_enable_sdc(void)
{
	
	
    // Configure IOMUX to request IPU SDC pins
    iomux_config_mux(MX31_PIN_LD0, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
    iomux_config_mux(MX31_PIN_LD1, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
    iomux_config_mux(MX31_PIN_LD2, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
    iomux_config_mux(MX31_PIN_LD3, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
    iomux_config_mux(MX31_PIN_LD4, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
    iomux_config_mux(MX31_PIN_LD5, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
    iomux_config_mux(MX31_PIN_LD6, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
    iomux_config_mux(MX31_PIN_LD7, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
    iomux_config_mux(MX31_PIN_LD8, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
    iomux_config_mux(MX31_PIN_LD9, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
    iomux_config_mux(MX31_PIN_LD10, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
    iomux_config_mux(MX31_PIN_LD11, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
    iomux_config_mux(MX31_PIN_LD12, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
    iomux_config_mux(MX31_PIN_LD13, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
    iomux_config_mux(MX31_PIN_LD14, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
    iomux_config_mux(MX31_PIN_LD15, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
    iomux_config_mux(MX31_PIN_LD16, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);	// LD16
    iomux_config_mux(MX31_PIN_LD17, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);	// LD17
    iomux_config_mux(MX31_PIN_VSYNC3,OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);	// VSYNC
    iomux_config_mux(MX31_PIN_HSYNC, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);	// HSYNC
    iomux_config_mux(MX31_PIN_FPSHIFT,OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);	// CLK
    iomux_config_mux(MX31_PIN_DRDY0, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);	// DRDY
    iomux_config_mux(MX31_PIN_SD_D_IO, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);	// SD_D_IO
    iomux_config_mux(MX31_PIN_SD_D_CLK, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);	// SD_D_CLK
    iomux_config_mux(MX31_PIN_LCS0, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);	// LCS0
    CYGACC_CALL_IF_DELAY_US(10000);


	



	
    //cpldLCDOn();//backlight on
 
    ipu_config_sdc();
    ipu_dma_channel_enable(IDMA_SDC_BG,1);
    ipu_enable_sdc_bg(ENABLE);
    writeval(IPU_CHA_BUF0_RDY,(1<<14));
}

//-----------------------------------------------------------------------------
//
// Function: ipu_set_sdc_mode
//
// This function is set sdc mode.
//
// Parameters:
//      sdcmode
//             [in]
//sdcmode
//00 TFT monochrome
//01 TFT color
//10 YUV progressive
//11 YUV interlaced

// Returns:
//      NULL
//
//-----------------------------------------------------------------------------
void  ipu_set_sdc_mode(cyg_uint32 sdcmode)
{
	writel(sdcmode,SDC_COM_CONF);
}
//-----------------------------------------------------------------------------
//
// Function: ipu_channel_config
//
// This function is used to config channel.
//
// Parameters:
//      channel
//             [in]    channel mask

// Returns:
//      NULL
//
//-----------------------------------------------------------------------------
void  ipu_channel_config(cyg_uint32 channel)
{
//Double buffer is not used for this channel
writel(readl(IPU_CHA_DB_MODE_SEL)&(~channel),IPU_CHA_DB_MODE_SEL);
//Current buffer used by DMA is buffer 0.
writel(readl(IPU_CHA_CUR_BUF)&(~channel),IPU_CHA_CUR_BUF);
//Channel has high priority.
writel(readl(IDMAC_CHA_PRI)|channel,IDMAC_CHA_PRI);
}
//-----------------------------------------------------------------------------
//
// Function: ipu_init_panel
//
// This function is used to config ipu register with lcd panel info.
//
// Parameters:
//      currentPanel
//         [in]
// Returns:
//      NULL
//
//-----------------------------------------------------------------------------
#define SCR_SHIFT 25
#define CC_EN_SHIFT 24
#define PWM_SHIFT 16
enum{
	HSYNC=0,
	PIXCLK=1,
	HSPCLK=2,
	RESERVED=3,
};
void ipu_init_panel(panel_info *currentPanel)
{
    cyg_uint32  temp = 0,PixelClock = 0,PixelDivider,ipuclk;
    ipu_di_signal syncpol;
    syncpol = currentPanel ->sync;
    writemaskval(MXC_CCM_CGR1, (3<<(((27) % 16) << 1)),  (3<<(((27) % 16) << 1)));
    //writemaskval(IPU_CONF,(((1U<<1)-1)<<8),0);
    //writel(1,SDC_COM_CONF);
    ipu_set_sdc_mode(1);//TFT color
    writel((((cyg_uint32) (currentPanel ->xres + currentPanel ->left_margin + currentPanel ->right_margin)) <<16)|((currentPanel ->hsync_len - 1)<<26),SDC_HOR_CONF);
    writel((1<<0)|(((cyg_uint32) (currentPanel -> yres + currentPanel ->upper_margin + currentPanel ->lower_margin))<<16)|(currentPanel -> vsync_len<<26),SDC_VER_CONF);
    temp = readl(DI_DISP_IF_CONF) & 0x78FFFFFF;
    writel((syncpol.datamasken<<DI_D3_DATAMSK_SHIFT) | (syncpol.clkselen<<DI_D3_CLK_SEL_SHIFT) | (syncpol.clkidleen<<DI_D3_CLK_IDLE_SHIFT) | temp,DI_DISP_IF_CONF);
    temp = readl(DI_DISP_SIG_POL) & 0xE0FFFFFF;
    writel((syncpol.datapolinvert<<DI_D3_DATA_POL_SHIFT) | (syncpol.clkrise<<DI_D3_CLK_POL_SHIFT) | (syncpol.outenable<<DI_D3_DRDY_SHARP_POL_SHIFT) | (syncpol.hsyncactive<<DI_D3_HSYNC_POL_SHIFT) | (syncpol.vsyncpol<<DI_D3_VSYNC_POL_SHIFT) | temp,DI_DISP_SIG_POL);
    writel((16)|(16<<16),DI_HSP_CLK_PER);
    PixelClock = (currentPanel -> xres + currentPanel -> left_margin + currentPanel -> hsync_len + currentPanel -> right_margin) *(currentPanel -> yres + currentPanel -> upper_margin + currentPanel -> vsync_len + currentPanel -> lower_margin) * 81;
    //diag_printf("PixelClock=%d\n",PixelClock);
    ipuclk = 133000000;
    PixelClock=8312500;//add this like kernel setting
    PixelDivider = (ipuclk << 4) / PixelClock;	
    if (PixelDivider < 0x40) // Divider less than 4
    {
        PixelDivider = 0x40;
    }
    //diag_printf("m_PixelDivider=%x\n",PixelDivider);
    Temp=(((PixelDivider / 8) - 1)<<22)|PixelDivider;
    writel(Temp,DI_DISP3_TIME_CONF);

    switch(currentPanel->pixel_fmt)
    {
	case PIX_FMT_RGB888:
	writel(di_mappings[0], DI_DISP3_B0_MAP);
	writel(di_mappings[1], DI_DISP3_B1_MAP);
	writel(di_mappings[2], DI_DISP3_B2_MAP);
	writel(readl(DI_DISP_ACC_CC) &~((di_mappings[3] - 1) << 12), DI_DISP_ACC_CC);
	break;
	case PIX_FMT_RGB666:
	writel(di_mappings[4], DI_DISP3_B0_MAP);
	writel(di_mappings[5], DI_DISP3_B1_MAP);
	writel(di_mappings[6], DI_DISP3_B2_MAP);
	writel(readl(DI_DISP_ACC_CC) |((di_mappings[7] - 1) << 12), DI_DISP_ACC_CC);
	break;
	case PIX_FMT_BGR666:
	writel(di_mappings[8], DI_DISP3_B0_MAP);
	writel(di_mappings[9], DI_DISP3_B1_MAP);
	writel(di_mappings[10], DI_DISP3_B2_MAP);
	writel(readl(DI_DISP_ACC_CC) |((di_mappings[11] - 1) << 12), DI_DISP_ACC_CC);
	break;
	default:
        writel(di_mappings[12], DI_DISP3_B0_MAP);
	writel(di_mappings[13], DI_DISP3_B1_MAP);
	writel(di_mappings[14], DI_DISP3_B2_MAP);
        writel(readl(DI_DISP_ACC_CC) |((di_mappings[15] - 1) << 12), DI_DISP_ACC_CC);
        break;
    }
    writel(((currentPanel -> left_margin<<16)|currentPanel -> upper_margin),SDC_BG_POS);
    writel((((currentPanel -> left_margin + 1)<<16)| currentPanel -> upper_margin),SDC_FG_POS);
    ipu_channel_config(IDMA_SDC_BG);
    writel(0,IPU_FS_DISP_FLOW);
    writel(PIXCLK<<SCR_SHIFT,SDC_PWM_CTRL);
    init_ipu_dma_buffer(currentPanel ->xres  , currentPanel ->yres ,  SDC_DMA_CHANNEL,currentPanel->bpp);
}
//-----------------------------------------------------------------------------
//
// Function: ipu_sdc_channel_buffer
//
// This function is used to config ipu channel buffer,use this to set frame buffer address.
//
// Parameters:
//      channel
//         [in]
//      pAddr
//         [in]  frame buffer address
//      bufNum
//         [in] 0 or 1
// Returns:
//      NULL
//
//-----------------------------------------------------------------------------
void ipu_sdc_channel_buffer(cyg_int32 channel, cyg_uint32  *pAddr, cyg_int8 bufNum)
{
    cyg_uint32 wordNo = (bufNum == eBUF_0) ? 0 : 1;
    cyg_uint32  newVal;
    newVal = ((IDMAC<<MEM_NU_SHIFT)|((2 * channel + 1)<<ROW_NU_SHIFT)|(wordNo<<WORD_NU_SHIFT));
    writel(newVal,IPU_IMA_ADDR );
    for(Temp=0; Temp <400000; Temp++);
    diag_printf("pAddr=%x\n",(cyg_uint32)pAddr);
    writel((cyg_uint32)pAddr,IPU_IMA_DATA);
    writel(0,IPU_IMA_ADDR);

}

extern unsigned int pmic_reg(unsigned int reg, unsigned int val, unsigned int write);
#define PMIC_SPI_DATA_LSH       0
#define PMIC_SPI_NULL_LSH       24
#define PMIC_SPI_ADDR_LSH       25
#define PMIC_SPI_RW_LSH         31

#define PMIC_SPI_DATA_WID       24
#define PMIC_SPI_NULL_WID       1
#define PMIC_SPI_ADDR_WID       6
#define PMIC_SPI_RW_WID         1

#define PMIC_SPI_RW_READ        0
#define PMIC_SPI_RW_WRITE       1

extern void main_menu(void);
#define CSP_BASE_REG_PA_CSPI1                   (0x43FA4000)
#define FRAMEBUFFERADD 0x80900000


//-----------------------------------------------------------------------------
//
// Function: mxc_framebuffer
//
// This function is used to make sdc bg frame buffer work.
//
// Parameters:
//      NULL
// Returns:
//      NULL
//
//-----------------------------------------------------------------------------

void mxc_framebuffer_init(void)
{
#if 0
    iomux_config_mux(MX31_PIN_CSPI1_SPI_RDY, OUTPUTCONFIG_FUNC,
                     INPUTCONFIG_FUNC);
    iomux_config_mux(MX31_PIN_CSPI1_SCLK, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
    iomux_config_mux(MX31_PIN_CSPI1_SS2,  OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
    iomux_config_mux(MX31_PIN_CSPI1_SS1,  OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
    iomux_config_mux(MX31_PIN_CSPI1_SS0,  OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
    iomux_config_mux(MX31_PIN_CSPI1_MISO, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
    iomux_config_mux(MX31_PIN_CSPI1_MOSI, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
    writemaskval(MXC_CCM_CGR2, (3<<((33 % 16) << 1)), (3<<((33 % 16) << 1)));
    pmic_reg(30, 0x0200, 1);
    pmic_reg(31, 0x0B7F, 1);
    pmic_reg(33, 0x9800, 1);
#endif
    ipu_init_panel(&currentPanel);
    ipu_sdc_channel_buffer(SDC_DMA_CHANNEL, (cyg_uint32 *)FRAMEBUFFERADD,
                           eBUF_0);
    ipu_enable_sdc();
}

void data13783(int argc,char *argv[]);
RedBoot_cmd("read13783",
            "read 13783 data\nSyntax:",
            "read13783",
             data13783
           );

void data13783(int argc,char *argv[])
{
	cyg_int32 i;
	for(i=0;i<=63;i++)
	diag_printf("[%d]=%x\n",i+1,pmic_reg(i+1,0 ,0));

}



RedBoot_cmd("ipudata",
            "ipu frame buffer on\nSyntax:",
            "mxc ipu",
             readipu
           );

void readipu(int argc,char *argv[])
{
	cyg_int32 i;	

	for(i=0;i<111;i++)
	{
	diag_printf("[%d]=%x\n",i,*((cyg_uint32*)IPU_REG_BASE+i));
	}
}

RedBoot_cmd("frame",
            "ipu frame buffer",
            "mxc ipu",
             do_frame
           );

void do_frame(int argc,char *argv[])
{
    diag_printf("do_frame\n");
    main_menu();
}


void lcd_on(void)
{
	ipu_enable_sdc_bg(1);
	cpld_lcdblk(1);
	pmic_reg(33, 0x9800, 1);
}

void lcd_off(void)
{
	ipu_enable_sdc_bg(0);
	pmic_reg(33, 0x9000, 1);
	cpld_lcdblk(0);
}

RedBoot_cmd("lcdswitch",
            "ipu frame buffer",
            "[-f flag]",
             lcd_on_off
           );

void lcd_on_off(int argc,char *argv[])
{
	bool flag_set;
	struct option_info opts[1];
	char *flag;
	init_opts(&opts[0], 'f', true, OPTION_ARG_TYPE_STR,
			(void *)&flag, (bool *)&flag_set, "flag");
	if (!scan_opts(argc, argv, 1, opts, 1, NULL, 0, NULL))
		return;
	if (strcmp(flag,"on")==0) {
		lcd_on();
	} else if(strcmp(flag,"off")==0) {
		lcd_off();
	} else {
		return;
	}
}
