/*
** $Id: hi3560_fbvideo.c 10629 2008-08-07 03:45:43Z tangjianbin $
**
** hi3560_fbvideo.c: NewGAL Engine for hi3560
**
** Copyright (C) 2007 Feynman Software.
**
** All rights reserved by Feynman Software.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <linux/fb.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <asm/page.h>        /* For definition of PAGE_SIZE */

#include "common.h"
#ifdef _MGGAL_HI3560
#include "minigui.h"
#include "misc.h"
#include "newgal.h"
#include "pixels_c.h"
#include "hi3560_fb.h"
#include "hi3560_fbvideo.h" 
//#include "tde_interface.h"
#include "hi_api.h"

//#define DBGLINE() printf("---%s;%s:%d\n",__FILE__,__func__,__LINE__);
#define DBGLINE()  

typedef struct taghifb_argb
{
	struct fb_bitfield red;		/* bitfield in fb mem if true color, */
	struct fb_bitfield green;	/* else only length is significant */
	struct fb_bitfield blue;
	struct fb_bitfield transp;	/* transparency			*/	
}HI_GC_CMAP_S;

#ifndef _MGRM_THREADS
#define REQID_HWSURFACE         0x0013
#endif

//#define FBCON_DEBUG 1
//#define _PC_DEBUG 1  
#define _USE_2D_ACCEL 1

#ifdef _USE_2D_ACCEL
#include "hi_tde.h" 
#endif

#ifdef _PC_DEBUG
/*hi3560fb extend*/
typedef struct tagfb_colorkey
{
    unsigned long key;
    unsigned char key_enable;	
    unsigned char mask_enable;	
    unsigned char rmask;
    unsigned char gmask;
    unsigned char bmask;
    char  reserved[3];
}fb_colorkey;

#define FBIOGET_COLORKEY_HI3560       0x4690  /*hi3560 extend*/
#define FBIOPUT_COLORKEY_HI3560       0x4691  /*hi3560 extend*/
#define FBIOGET_ALPHA_HI3560          0x4692  /*hi3560 extend*/
#define FBIOPUT_ALPHA_HI3560          0x4693  /*hi3560 extend*/
#define FBIOPUT_SCREEN_ORIGIN_HI3560  0x4694  /*hi3560 extend*/
#define FBIOGET_SCREEN_ORIGIN_HI3560  0x4695  /*hi3560 extend*/
#endif

//#define     TDE_OFFSET      0x300 /* 3560 */
#define     TDE_OFFSET      0x800   /* 3560 */

typedef enum {
	HI_GC_PF_PALETTE,
	HI_GC_PF_RGB4444,
	HI_GC_PF_RGB1555,
	HI_GC_PF_RGB565,
	HI_GC_PF_RGB8888,
	HI_GC_PF_MAX,
}HI_GC_PIXEL_FMT;

extern BOOL mgIsServer;
extern GAL_VideoDevice* current_video;

#ifndef _MGRM_THREADS
struct private_hwdata
{
	const vidmem_bucket* pBucket;
    GAL_VideoDevice* pDevice; //该变量用于区分哪个图层，在硬件加速blit中用到
};

static int HI3560_SetLayerAlpha(int  fd,  Uint32* pAlpha);
static int HI3560_SetLayerAttr(_THIS, Uint8 siAttr, void * pValue);
static struct private_hwdata* HI3560_CreateHwData(_THIS, const vidmem_bucket* pBucket);
#endif

/* Initialization/Query functions */
static int HI3560_VideoInit(_THIS, GAL_PixelFormat *vformat);
static GAL_Rect **HI3560_ListModes(_THIS, GAL_PixelFormat *format, Uint32 flags);
static GAL_Surface *HI3560_SetVideoMode(_THIS, GAL_Surface *current, int width, int height, int bpp, Uint32 flags);
static void HI3560_VideoQuit(_THIS);

/* Hardware surface functions */
static int HI3560_InitHWSurfaces(_THIS, GAL_Surface *screen, char *base, int size);
static void HI3560_FreeHWSurfaces(_THIS);
static void HI3560_RequestHWSurface (_THIS, const REQ_HWSURFACE* request, REP_HWSURFACE* reply);
static int HI3560_AllocHWSurface(_THIS, GAL_Surface *surface);
static void HI3560_FreeHWSurface(_THIS, GAL_Surface *surface);
static void HI3560_WaitVBL(_THIS);
static void HI3560_WaitIdle(_THIS);

static int hi3560_console = 0;

static void HI_DEVICE_OPEN()
{
    DISPLAY_ATTR_S l_display_attr;
    if(mgIsServer){
        if(HI_API_DISPLAY_Open() != HI_RET_SUCCESS){
            printf("HI_API_DISPLAY_Open error\n");
            return 0;
        }

        if(HI_API_DISPLAY_GetAttr (&l_display_attr) != HI_RET_SUCCESS){
            printf("HI_API_DISPLAY_GetArrt error\n");
            return 0;
        }
        printf("screen width=%d,screen height=%d\n",l_display_attr.lcd_config.HACT,l_display_attr.lcd_config.VACT);
        /*Sansung LCD screen configure*/
        l_display_attr.enable = HI_TRUE ;
        l_display_attr.gpc_layer_enable[2] = HI_FALSE;
        l_display_attr.display_mode = DISPLAY_MODE_DIGITAL;
        l_display_attr.lcd_config.HACT =800;
        l_display_attr.lcd_config.VBB =10;   //7;   //10;
        l_display_attr.lcd_config.VFB =4;   //10;
        l_display_attr.lcd_config.HBB =15;   //160;
        l_display_attr.lcd_config.HFB =7;    //10;
        l_display_attr.lcd_config.VPW =2;   //10;
        l_display_attr.lcd_config.HPW =3;   //10;
        l_display_attr.lcd_config.ClockReversal =HI_FALSE;   //10;
        l_display_attr.lcd_config.DataWidth =VOU_DATA_WIDTH24;   //10;
        l_display_attr.lcd_config.ItfFormat =VOU_FORMAT_RGB888;   //10;
        l_display_attr.lcd_config.DitherEnable =HI_FALSE;   //10;
        l_display_attr.lcd_config.IDV =HI_FALSE;   //10;
        l_display_attr.lcd_config.IHS =HI_FALSE;   //10;
        l_display_attr.lcd_config.IVS =HI_FALSE;   //10;

#if 0
        /*others LCD screen configure*/
        l_display_attr.enable = HI_TRUE ;
        l_display_attr.gpc_layer_enable[2] = HI_FALSE;
        l_display_attr.display_mode = DISPLAY_MODE_DIGITAL;
        l_display_attr.lcd_config.HACT =800;
        l_display_attr.lcd_config.VBB =23;   //10;
        l_display_attr.lcd_config.VFB =4;   //10;
        l_display_attr.lcd_config.HBB =46;   //160;
        l_display_attr.lcd_config.HFB =8;    //10;
        l_display_attr.lcd_config.VPW =2;   //10;
        l_display_attr.lcd_config.HPW =3;   //10;
        l_display_attr.lcd_config.ClockReversal =HI_FALSE;   //10;
        l_display_attr.lcd_config.DataWidth =VOU_DATA_WIDTH24;   //10;
        l_display_attr.lcd_config.ItfFormat =VOU_FORMAT_RGB888;   //10;
        l_display_attr.lcd_config.DitherEnable =HI_FALSE;   //10;
        l_display_attr.lcd_config.IDV =HI_FALSE;   //10;
        l_display_attr.lcd_config.IHS =HI_FALSE;   //10;
        l_display_attr.lcd_config.IVS =HI_FALSE;   //10;
#endif


        if(HI_API_DISPLAY_SetAttr (&l_display_attr) != HI_RET_SUCCESS){
            printf("HI_API_DISPLAY_SetAttr error\n");
            return 0;
        }
    }
}

static void HI_DEVICE_CLOSE()
{
    if(mgIsServer){
        HI_API_DISPLAY_Close();
    }
}

static int HI3560_Available(void)
{
    const char *GAL_fbdev;

    GAL_fbdev = getenv("FRAMEBUFFER");
    if ( GAL_fbdev == NULL ) {
        GAL_fbdev = "/dev/fb/0";
    }

    HI_DEVICE_OPEN();

    hi3560_console = open(GAL_fbdev, O_RDWR, 0);

    if ( hi3560_console >= 0 ) {
        close(hi3560_console);
    }
    else {
    	fprintf(stderr, "failed to open file :%s!\n", GAL_fbdev);
        return 0;
    }
    HI_DEVICE_CLOSE();

    return(hi3560_console >= 0);
}

#ifdef _MGRM_THREADS
struct GAL_PrivateVideoData g_stHidden_3560 = { 0 };
#else
static struct GAL_PrivateVideoData g_stHidden_3560[2]; //two layers
#endif

#ifdef _MGRM_THREADS
struct GAL_VideoDevice *g_pVideo_3560 = NULL;
#endif

GAL_Surface logosurface;

#include "pix_array.c"

#ifdef _USE_2D_ACCEL
#ifdef _USE_DBUF
#if (defined(_TAP_ALL) || defined(_TAP3_VERT_HORI) || defined(_TAP2_VERT) \
	|| defined(_TAP2_VERT_HORI) || defined(_TAP3_VERT))
    
static int HI3560_AntiFlicker(_THIS, GAL_Surface *src, 
	                                GAL_Rect *srcrect, GAL_Surface *dst, 
	                                GAL_Rect *dstrect, Uint32 *puiOffsetX, 
	                                Uint32 *puiOffsetY);

static int HI3560_SetOffset(int fd, 
                                  Uint32 uiOffsetX, 
                                  Uint32 uiOffsetY);

#endif
#define HI3560_ALIGN_4(x) (((x)+3)&~3)
static  int HI3560_GetColorFmt(const GAL_PixelFormat* pixel_fmt, TDE_COLOR_FORMAT* fmt)
{
    int ret = -1;
    Uint32 Rmask, Gmask, Bmask, Amask;

    Rmask = pixel_fmt->Rmask;
    Gmask = pixel_fmt->Gmask;
    Bmask = pixel_fmt->Bmask;
    Amask = pixel_fmt->Amask;
    
    switch (pixel_fmt->BitsPerPixel)
    {
       case 12 : //RGB,4:4:4
           if (Rmask==0x0f00 && (Gmask == 0x00f0) && Bmask == 0x000f)
           {
           	   *fmt = TDE_COLOR_FORMAT_RGB444;
           	   ret = 0;
           }
           break;
           
       case 16 :
           if (Rmask == 0x0f00 && (Gmask == 0x00f0) && Bmask == 0x000f && Amask == 0xf000)
           {
           	   assert(Rmask+Amask+Gmask+Bmask == 0xffff);
               *fmt = TDE_COLOR_FORMAT_RGB4444;
               ret = 0;
           }
           else if (Rmask == 0x7c00 && (Gmask == 0x03e0) && Bmask == 0x001f && Amask == 0x0000)	
           {
           	   assert(Rmask+Amask+Gmask+Bmask == 0xffff);
               *fmt = TDE_COLOR_FORMAT_RGB555;
               ret = 0;
           }
           else if (Rmask == 0x7c00 && (Gmask == 0x03e0) && Bmask == 0x001f && Amask == 0x8000)	
           {
           	   assert(Rmask+Amask+Gmask+Bmask == 0xffff);           	
               *fmt = TDE_COLOR_FORMAT_RGB1555;
               ret = 0;
           }
           else if (Rmask == 0xf800 && (Gmask == 0x07e0) && Bmask == 0x001f && Amask == 0x0000)	
           {
           	   assert(Rmask+Amask+Gmask+Bmask == 0xffff);           	
               *fmt = TDE_COLOR_FORMAT_RGB565;
               ret = 0;
           }
           break;
       case 24 :
           if (Rmask == 0xff0000 && (Gmask == 0x00ff0) && Bmask == 0x0000ff && Amask == 0x000000)	
           {
           	   assert(Rmask+Amask+Gmask+Bmask == 0xffffff);           	
               *fmt = TDE_COLOR_FORMAT_RGB888;
               ret = 0;
           }
           break;
       case 32 :
           if (Rmask == 0xff0000 && (Gmask == 0x00ff00) && Bmask == 0x0000ff && Amask == 0xff000000)	
           {
           	   assert(Rmask+Amask+Gmask+Bmask == 0xffffffff);           	
               *fmt = TDE_COLOR_FORMAT_RGB8888;
               ret = 0;
           }
           break;
           
       default:
           ret = -1;
    }

	return ret;
}
	
#define HI3560_GET_PHY(virtual_addr) ((U8*)(virtual_addr-mapped_mem + saved_finfo.smem_start))
#define HI3560_CHECK_VIRTUAL_ADDR(virtual_addr)  assert(virtual_addr-mapped_mem < saved_finfo.smem_len)

static void HI3560_GetRGB(gal_pixel color, GAL_PixelFormat* fmt, Uint8* r, Uint8* g, Uint8 *b)
{
    GAL_GetRGB(color, fmt, r, g, b);
    if (fmt->Rloss && (*r & 0x80))
    {
        *r += 0xff >> (8-fmt->Rloss);
    }
    if (fmt->Gloss && (*g & 0x80))
    {
        *g += 0xff >> (8-fmt->Gloss);
    }

    if (fmt->Bloss && (*b & 0x80))
    {
        *b += 0xff >> (8-fmt->Bloss);
    }
}

#if 0
static int ShowLogo (_THIS, Uint32* dst)
{
    TDE_MoveBlitParam param;
    Uint8* pvirtual_addr;
    GAL_Rect OutRect = {470, 490, 198, 51};

    logosurface.pitch = BM_WIDTH*2;
    memset(&param, 0x00, sizeof(param));
    param.DataOpt = TDE_DATA_OPT_ALPHA_INTERNAL;
    param.InternalAlpha = 30;

    param.opt_width = (U16)(OutRect.w);
    param.opt_height = (U16)(OutRect.h);

    param.out_stride = (U16)HI3560_ALIGN_4(__gal_screen->pitch);
    param.out_pixels = (Uint8*)dst + OutRect.x*2+ OutRect.y*__gal_screen->pitch;
    param.InColorFormat = param.OutColorFormat = TDE_COLOR_FORMAT_RGB1555;
    param.dst_pixels = param.out_pixels;
    param.dst_stride = HI3560_ALIGN_4(param.out_stride);

    pvirtual_addr = (Uint8*)logosurface.pixels;

    HI3560_CHECK_VIRTUAL_ADDR(pvirtual_addr);    
    param.src_pixels = HI3560_GET_PHY(pvirtual_addr);
    param.src_stride = HI3560_ALIGN_4(logosurface.pitch);
    printMBParam(&param);

    #if 0
    {
      Uint8  *psrc, *pdst;

      psrc = logosurface.pixels;
      pdst = (Uint8*)dst + OutRect.x * 2+ OutRect.y*__gal_screen->pitch;

      printf ("pitch = %d\n", HI3560_ALIGN_4(param.out_stride));
     
      for (i = 0; i < OutRect.h; i++)
      {
          memcpy(pdst, psrc, HI3560_ALIGN_4(param.out_stride));          
          psrc += HI3560_ALIGN_4(logosurface.pitch);
          pdst += HI3560_ALIGN_4(param.out_stride);

      }

      return 0;
    }
    #else
    if(HI_SUCCESS != TDE_MoveBlit(&param))
    {
        fprintf(stderr,"error: file:%s, line:%d\n", __FILE__, __LINE__);
        return -1;
    }
    #endif

	return 0;
}
#endif

static int HI3560_HWAccelBlit(GAL_Surface *src, GAL_Rect *srcrect,
                       GAL_Surface *dst, GAL_Rect *dstrect)
{
	TDE_MoveBlitParam param;
	Uint8 r,g,b;
	Uint8* pvirtual_addr;
    TDE_COLOR_FORMAT color_fmt;
    //TDE_SURFACE_S src_sur,dst_sur;
    //fb_fix_screeninfo stFixInfo;

#if (defined(_TAP_ALL) || defined(_TAP3_VERT_HORI) || defined(_TAP2_VERT) \
     || defined(_TAP2_VERT_HORI)|| defined(_TAP3_VERT)) \
     && defined(_USE_2D_ACCEL) && defined(_USE_DBUF)     
    Uint32 uiOffsetX = 0;
    Uint32 uiOffsetY = 0;
 #endif
    
#ifndef _MGRM_THREADS
    GAL_VideoDevice* this;
    this = ((struct private_hwdata*)src->hwdata)->pDevice;
    #ifdef FBCON_DEBUG    
    if (this == NULL || this != ((struct private_hwdata*)dst->hwdata)->pDevice)
    	fprintf(stderr, "the video device is error! src->pdevice:%p, dst->pdevice:%p",
    	        this, ((struct private_hwdata*)dst->hwdata)->pDevice);
     #endif    	
#endif

#if (defined(_TAP_ALL) || defined(_TAP3_VERT_HORI) || defined(_TAP2_VERT) \
     || defined(_TAP2_VERT_HORI)|| defined(_TAP3_VERT)) \
     && defined(_USE_2D_ACCEL) && defined(_USE_DBUF)
    /*if dst is current video surface, should do antiflicker*/
#ifdef _MGRM_THREADS
    if ((src == __gal_screen) && (src->flags & GAL_HWSURFACE) 	
    	&& (dst == current_video->screen))
#else
    if (mgIsServer && (src->flags & GAL_DOUBLEBUF) 
    	&& (src->flags & GAL_HWSURFACE)	&& (dst == this->screen))
#endif
    {
       //#ifdef ___DELETE___ANTIFLICKER__
       if ((TAP_MIN_VALUE <= tap_level) && (TAP_MAX_VALUE >= tap_level))
       {
#ifdef _MGRM_THREADS
	       if (0 == HI3560_AntiFlicker(current_video, src, srcrect, dst, 
	       	                           dstrect, &uiOffsetX, &uiOffsetY))
#else
           if (0 == HI3560_AntiFlicker(this, src, srcrect, dst, dstrect,
           	                           &uiOffsetX, &uiOffsetY))
#endif
	       {
	           HI3560_SetOffset(console_fd, uiOffsetX, uiOffsetY); 
	           return 0;
	       }
	   }
       //#endif

      }
#endif
    /*if (HI3560_GetColorFmt(src->format, &color_fmt) < 0)
    {
        fprintf(stderr,"error: file:%s, line:%d\n", __FILE__, __LINE__);
        return -1;
    }

    if (ioctl(console_fd, FBIOGET_FSCREENINFO, &stFixInfo) < 0)
    {
        printf("process frame buffer device error\n");
        goto FB_PROCESS_ERROR0;
    }

    u32Size     = stFixInfo.smem_len;

    src_sur.enColorFmt = color_fmt;
    src_sur.pu8PhyAddr = (HI_U8*)stFixInfo.smem_start;
    src_sur.u16Width = SCREEN_WIDTH;
    src_sur.u16Height = SCREEN_HEIGHT;
    src_sur.u16Stride = g_stScreen[0].u16Width * BPP;*/

    memset(&param, 0x00, sizeof(param));
    if (HI3560_GetColorFmt(src->format, &color_fmt) < 0)
    {
        fprintf(stderr,"error: file:%s, line:%d\n", __FILE__, __LINE__);
        return -1;
    }
    
    if (src->flags & GAL_SRCCOLORKEY)
    {
        param.ColorSpaceOpt = TDE_COLORSPACE_ENABLE;
        HI3560_GetRGB(src->format->colorkey.low, src->format, &r, &g, &b);
        param.ColorSpaceMin = MAKERGB(r, g, b);
        HI3560_GetRGB(src->format->colorkey.high, src->format, &r, &g, &b);
        param.ColorSpaceMax = MAKERGB(r, g, b);
    }

    if (src->flags & GAL_SRCALPHA)
    {
    	if (0)//(src->format->Amask != 0)
    	{
    	    param.DataOpt = TDE_DATA_OPT_ALPHA_SRC;
    	}
    	else
    	{
    	    param.DataOpt = TDE_DATA_OPT_ALPHA_INTERNAL;
    	    param.InternalAlpha = src->format->alpha;
    	}
    }

    if ((src->flags & GAL_ROP) && src->format->rop != ROP_SET)
    {
    	if (src->format->rop == ROP_AND)
    	    param.RopCode = TDE_ROP_PSDa;
    	else if (src->format->rop == ROP_OR)
    		param.RopCode = TDE_ROP_PSDo;
    	else if (src->format->rop == ROP_XOR)
    		param.RopCode = TDE_ROP_PSDx;
        else 
           printf("the rop is invalid, file:%s, line:%d!\n", __FILE__,__LINE__);
        param.DataOpt = TDE_DATA_OPT_ROP;
    }
    assert(dstrect->w==srcrect->w && dstrect->h==srcrect->h);
    param.opt_width = (U16)(dstrect->w);
    param.opt_height = (U16)(dstrect->h);

    param.out_stride = (U16)HI3560_ALIGN_4(dst->pitch);
    pvirtual_addr = (Uint8*)dst->pixels + dstrect->x*dst->format->BytesPerPixel+ dstrect->y*dst->pitch;
    HI3560_CHECK_VIRTUAL_ADDR(pvirtual_addr);
    param.out_pixels = HI3560_GET_PHY(pvirtual_addr);
    param.InColorFormat = param.OutColorFormat = color_fmt;
    param.dst_pixels = param.out_pixels;
    param.dst_stride = HI3560_ALIGN_4(param.out_stride);

    pvirtual_addr = (Uint8*)src->pixels + srcrect->x*src->format->BytesPerPixel+ srcrect->y*src->pitch;
    HI3560_CHECK_VIRTUAL_ADDR(pvirtual_addr);
    param.src_pixels = HI3560_GET_PHY(pvirtual_addr);
    param.src_stride = HI3560_ALIGN_4(src->pitch);
    printMBParam(&param);

    if(HI_SUCCESS != TDE_MoveBlit(&param))
    {
        fprintf(stderr,"error: file:%s, line:%d\n", __FILE__, __LINE__);
        return -1;
    }
    
    return 0;
}

static int HI3560_CheckHWBlit(_THIS, GAL_Surface *src, GAL_Surface *dst)
{
    TDE_COLOR_FORMAT color_fmt;

    src->flags &= ~GAL_HWACCEL;
    src->map->hw_blit = NULL;

    //only supported the hw surface accelerated.
    if (!(src->flags & GAL_HWSURFACE) || !(dst->flags & GAL_HWSURFACE))
    {
    	return -1;
    }

    if ((src->flags&GAL_DESTCOLORKEY))
    {
    	fprintf(stderr, "src->flags:%x,unsupported GAL_DESTCOLORKEY\n", src->flags);
        return -1;
    }
    
    if ((src->flags&GAL_SRCALPHA) && (src->flags&GAL_ROP) && (src->format->rop != ROP_SET))
    {
    	fprintf(stderr, "unsupported GAL_SRCALPHA|GAL_ROP\n");
        return -1;	
    }

    if(HI3560_GetColorFmt(src->format, &color_fmt) < 0)
    {
        fprintf(stderr,"error: file:%s, line:%d\n", __FILE__, __LINE__);
        return -1;
    }
    src->flags |= GAL_HWACCEL;
    src->map->hw_blit = HI3560_HWAccelBlit;
    return 0;

}


 /* Fills a surface rectangle with the given color */
int HI3560_FillHWRect(_THIS, GAL_Surface *dst, GAL_Rect *rect, Uint32 color)
{
	Uint8 r,g,b;
	Uint8* pvirtual_addr;
	TDE_SolidDrawParam param;
    TDE_COLOR_FORMAT color_fmt;
    	
	if (!(dst->flags & GAL_HWSURFACE))
	{
		return -1;
	}

    memset(&param, 0x00, sizeof(param));

    GAL_GetRGB(color, dst->format, &r, &g, &b);
    param.sd_fill_color = MAKERGB(r, g, b);

    param.ColorSpaceOpt = TDE_COLORSPACE_DISABLE;

    if (dst->format->Amask == 0xff000000)
    {
 	    param.DataOpt = TDE_DATA_OPT_ALPHA_INTERNAL;
    	    param.InternalAlpha = 0xff;
            param.OutAlphaFrom = TDE_OUT_ALPHAFROM_INTERNAL;
    }
    else
    {
        param.DataOpt = TDE_DATA_OPT_NONE;
        param.OutAlphaFrom = TDE_OUT_ALPHAFROM_SRC;
    }
    if (HI3560_GetColorFmt(dst->format, &color_fmt) < 0)
    {
        fprintf(stderr, "error: file:%s, line:%d\n", __FILE__, __LINE__);
    	return -1;
    }
    
    param.InColorFormat = color_fmt;
    param.OutColorFormat = color_fmt;

    param.opt_width = (U16)(rect->w);
    param.opt_height = (U16)(rect->h);
    param.out_stride = (U16)HI3560_ALIGN_4(dst->pitch);
    pvirtual_addr = (Uint8*)dst->pixels + rect->x*dst->format->BytesPerPixel+ rect->y*dst->pitch;
    HI3560_CHECK_VIRTUAL_ADDR(pvirtual_addr);
    param.out_pixels = HI3560_GET_PHY(pvirtual_addr);

    if(HI_SUCCESS != TDE_SolidDraw(&param))
    {
        fprintf(stderr,"error: file:%s, line:%d\n", __FILE__, __LINE__);
        return -1;
    }

    	
    printSDParam(&param);
	return 0;
}

/* Fills a surface rectangle with the given bitmap */
int HI3560_FillHWRectWithPattern(_THIS, GAL_Surface	*dst, GAL_Rect *rect, PBITMAP pattern)
{
	Uint8* pvirtual_addr;
	TDE_PatternFillParam param;
    TDE_COLOR_FORMAT color_fmt;
    
	if (!(dst->flags & GAL_HWSURFACE))
	{
        fprintf(stderr,"error: file:%s, line:%d\n", __FILE__, __LINE__);
		return -1;
	}
  
    if (pattern->bmPitch > 64)
    {
        return -1;
    }
    //not allocate from vram
    if (!(pattern->bmType & 0x80))
    {
        fprintf(stderr, "error,file:%s, line:%d\n", __FILE__, __LINE__);
        return -1;
    }

    memset(&param, 0x00, sizeof(param));
    if (HI3560_GetColorFmt(dst->format, &color_fmt) < 0)
    {
        fprintf(stderr, "error,file:%s, line:%d\n", __FILE__, __LINE__);
    	return -1;
    }

    if (rect == NULL)
    {
        fprintf(stderr, "error,file:%s, line:%d\n", __FILE__, __LINE__);
    	return -1;
    }

    if (pattern->bmType & BMP_TYPE_COLORKEY)
    {
        param.ColorSpaceOpt = TDE_COLORSPACE_ENABLE;
        param.ColorSpaceMin = pattern->bmColorKey;
        param.ColorSpaceMax = pattern->bmColorKey;
    }

    if (pattern->bmType & BMP_TYPE_ALPHACHANNEL)
    {
    	param.DataOpt = TDE_DATA_OPT_ALPHA_INTERNAL;
    	param.InternalAlpha = pattern->bmAlpha;
    }

    param.opt_width = (U16)(rect->w);
    param.opt_height = (U16)(rect->h);
    param.out_stride = (U16)HI3560_ALIGN_4(dst->pitch);
    pvirtual_addr = (Uint8*)dst->pixels + rect->x*dst->format->BytesPerPixel+ rect->y*dst->pitch;
    HI3560_CHECK_VIRTUAL_ADDR(pvirtual_addr);
    param.out_pixels = HI3560_GET_PHY(pvirtual_addr);
    param.InColorFormat = param.OutColorFormat = color_fmt;
    param.pattern_width= pattern->bmWidth;
    param.pattern_height = pattern->bmHeight;
    
    //memmove(pattern_addr, pattern->bmBits, pattern_size);
    param.src_pixels = HI3560_GET_PHY(pattern->bmBits);
    param.src_stride = HI3560_ALIGN_4(pattern->bmPitch);
    if(HI_SUCCESS != TDE_PatternFill(&param))
    {
        fprintf(stderr, "error,file:%s, line:%d\n", __FILE__, __LINE__);
        return -1;
    }
    printPFParam(&param);
	return 0;
}

#if (defined(_TAP_ALL) || defined(_TAP3_VERT_HORI) || defined(_TAP2_VERT) \
     || defined(_TAP2_VERT_HORI)|| defined(_TAP3_VERT)) \
     && defined(_USE_2D_ACCEL) && defined(_USE_DBUF)  
    
/*obligate middle video memory for antiflicker*/
static int HI3560_GetAllAFVMem(_THIS, 
                                  Uint32 iPitch, 
                                  Uint32 iHeight,
                                  Uint32 *puiVirtualYRes)
{    
    struct fb_fix_screeninfo finfo;
    Uint32 iSize = iPitch * iHeight;
    if ( ioctl(console_fd, FBIOGET_FSCREENINFO, &finfo) < 0 ) 
    {
	    fprintf (stderr, "Couldn't get console hardware info");	    
	    return -1;
    }
#if defined(_TAP_ALL) || defined(_TAP3_VERT_HORI)
    if (mapped_memlen >= iSize*5)
    {
        middle_buf1 = (Uint32)finfo.smem_start + mapped_offset;
        middle_buf2 = middle_buf1 + iSize;
        middle_buf3 = middle_buf2 + iSize;  
        current_buf = middle_buf3 + iSize;
        tap_level = TAP_2_VERT;//TAP_3_VERT_HORI;   
        *puiVirtualYRes = iHeight << 2;
        return iSize*3;
    }
    else
    {
       return -1;
    }
#elif defined(_TAP2_VERT)
    if (mapped_memlen >= iSize*3)
    {
        middle_buf1 = (Uint32)finfo.smem_start + mapped_offset;  
        current_buf = middle_buf1 + iSize;
        tap_level = TAP_2_VERT;
        *puiVirtualYRes = iHeight << 1;
        return iSize;
    }
    else
    {
       return -1;
    }
#elif defined(_TAP2_VERT_HORI)
    if (mapped_memlen >= (iSize<<2))
    {
        middle_buf1 = (Uint32)finfo.smem_start + mapped_offset;
        middle_buf2 = middle_buf1 + iSize; 
        current_buf = middle_buf2 + iSize;
        tap_level = TAP_2_VERT_HORI;
        *puiVirtualYRes = 3 * iHeight;
        return iSize<<1;
    }
    else
    {
       return -1;
    }
#else //defined(_TAP3_VERT)
    if (mapped_memlen >= iSize<<2)
    {
        middle_buf1 = (Uint32)finfo.smem_start + mapped_offset;
        middle_buf2 = middle_buf1 + iSize;  
        current_buf = middle_buf2 + iSize;
        tap_level = TAP_3_VERT;
        *puiVirtualYRes = 3 * iHeight;
        return iSize<<1;
    }
    else
    {
       return -1;
    }
#endif
}

/*该变量用于统计gui刷新屏幕的次数，主要用于启动画面到桌面，中间没有黑屏出现
将在DEMO中mginit.c文件中使用*/
int g_offset_counter = 0;
static int HI3560_SetOffset(int fd, 
                                  Uint32 uiOffsetX, 
                                  Uint32 uiOffsetY)
{
    struct fb_var_screeninfo vinfo;
    memset(&vinfo, 0, sizeof(struct fb_var_screeninfo));
    /* Set the video mode and get the final screen format */
    if ( ioctl(fd, FBIOGET_VSCREENINFO, &vinfo) < 0 )
    {
        fprintf (stderr, "Couldn't get console screen info");
        return -1;
    }
    vinfo.xoffset = uiOffsetX;
    vinfo.yoffset = uiOffsetY;
    if (ioctl(fd, FBIOPAN_DISPLAY, &vinfo) < 0)
    {
        fprintf(stderr, "Serious error, offset framebuffer failed.\n");
        return -1;
    }

    if (++g_offset_counter == 3)
    {
    	Uint32 alpha = 255;
    	HI3560_SetLayerAlpha(fd, &alpha);
    }
    
    return 0;    
}

#ifdef _TAP_ALL

/*set antiflicker level*/
static int SetTapLevel(int iLayerIndex, int iLevel)
{ 
    if ((0 > iLayerIndex) || (1 < iLayerIndex)
    	|| (0 > iLevel) || (TAP_MAX_VALUE < iLevel)
    	|| (0 == g_stHidden_3560[iLayerIndex].uiMiddleBuf1))
    {
        return -1;
    }
    TDE_WaitForDone();
    g_stHidden_3560[iLayerIndex].uiTapLevel = (Uint32)iLevel;   
   
    if (0 == iLevel)
    {                
        HI3560_SetOffset(g_stHidden_3560[iLayerIndex].console_fd1,
                         0, 
                        (g_stHidden_3560[iLayerIndex].uiCurrentBuf
                        - g_stHidden_3560[iLayerIndex].uiMiddleBuf1)/
                        g_stHidden_3560[iLayerIndex].finfo.line_length);
                   
    }
    return 0;
}
#endif
struct timeval tv1, tv2;
static int HI3560_AntiFlicker(_THIS, GAL_Surface *src, 
	                                GAL_Rect *srcrect, GAL_Surface *dst, 
	                                GAL_Rect *dstrect, Uint32 *puiOffsetX, 
	                                Uint32 *puiOffsetY)
{
    static Uint32 uiDisplay = 0;
    static Uint32 uiOffset = 0;
    Uint8 *pBuf;
    if (shadow_buf == 0)
    {
        shadow_buf = current_buf
                     + (src->pixels - dst->pixels);
        uiOffset = this->offset_y * this->screen->pitch 
        	       + this->offset_x * this->screen->format->BytesPerPixel;
    }
    switch (tap_level)
    {
        case 1:
        {        
        	if (uiDisplay == current_buf)
        	{
        	    uiDisplay = middle_buf1;
        	}
        	else
        	{
        	    uiDisplay = current_buf;
        	}
            pBuf = (Uint8 *)(mapped_mem + (uiDisplay - middle_buf1));
            memset(pBuf, 
            	   0, 
            	   this->screen->pitch * this->screen->h);
            TDE_AntiFlicker(shadow_buf, 
	                    shadow_buf + this->screen->pitch, 
	                    uiDisplay, 
	                    this->screen->w - this->offset_x, 
	                    this->screen->h - 1 - this->offset_y,
	                    this->screen->pitch, 50, 1, uiOffset);
            
    	    
        	break;
        }
        case 2:
        {
            if (uiDisplay == current_buf)
            {
                uiDisplay = middle_buf2;
            }
            else
            {
                uiDisplay = current_buf;
            }
#if 1
            pBuf = (Uint8 *)(mapped_mem + (uiDisplay - middle_buf1));
            memset(pBuf, 
            	   0, 
            	   this->screen->pitch * this->screen->h);
#endif     
   	TDE_AntiFlicker(shadow_buf, 
                    shadow_buf + this->screen->pitch, 
                    middle_buf1, this->screen->w, 
                    this->screen->h - 1,
                    this->screen->pitch, 50, 0, 0);
            TDE_AntiFlicker(middle_buf1, 
            	middle_buf1 + this->screen->format->BytesPerPixel, 
            	uiDisplay, 
	            this->screen->w - 1 - - this->offset_x, 
	            this->screen->h - 2 - - this->offset_y, 
	            this->screen->pitch, 50, 1, uiOffset); 
        	break;
        }
        case 3:
        {
            if (uiDisplay == current_buf)
            {
                uiDisplay = middle_buf2;
            }
            else
            {
                uiDisplay = current_buf;
            }
            pBuf = (Uint8 *)(mapped_mem + (uiDisplay - middle_buf1));
            memset(pBuf, 
            	   0, 
            	   this->screen->pitch * this->screen->h);
            TDE_AntiFlicker(shadow_buf,
                shadow_buf + this->screen->pitch,
                middle_buf1, this->screen->w,
                this->screen->h - 1,
                this->screen->pitch, 33, 0, 0);
            TDE_AntiFlicker(middle_buf1, 
            	shadow_buf + (this->screen->pitch<<1), 
           	    uiDisplay,
                this->screen->w  - this->offset_x,
                this->screen->h  - this->offset_y,
                this->screen->pitch, 75, 1, uiOffset);

        	break;
        }
        case 4:
        {
            // gettimeofday(&tv1, NULL);
            if (uiDisplay == current_buf)
            {
                uiDisplay = middle_buf3;
            }
            else
            {
                uiDisplay = current_buf;
            }
#if 1
            pBuf = (Uint8 *)(mapped_mem + (uiDisplay - middle_buf1));
            memset(pBuf, 
            	   0, 
            	   this->screen->pitch * this->screen->h);
#endif     
       TDE_AntiFlicker(shadow_buf,
                shadow_buf + this->screen->pitch,
                middle_buf1, this->screen->w,
                this->screen->h - 1,
                this->screen->pitch, 33, 0, 0);
            TDE_AntiFlicker(middle_buf1, 
            	shadow_buf + (this->screen->pitch<<1) , 
            	middle_buf1,
                this->screen->w,
                this->screen->h - 2,
                this->screen->pitch, 75, 0, 0);
            TDE_AntiFlicker(middle_buf1, middle_buf1 + 2 , middle_buf2,
               this->screen->w - 1,
               this->screen->h - 2,
               this->screen->pitch, 33, 0, 0);
            TDE_AntiFlicker(middle_buf2, middle_buf1 + 4 , uiDisplay,
               this->screen->w - 2 - this->offset_x,
               this->screen->h - 2 - this->offset_y,
               this->screen->pitch, 75, 1, uiOffset);
           // gettimeofday(&tv2, NULL);
           // printf("anti, use time:%d\n",
             //   (tv2.tv_sec - tv1.tv_sec)*1000000 + tv2.tv_usec - tv1.tv_usec);
        	break;
        }
        default:
        	return -1;
    }
    *puiOffsetX = 0;
    *puiOffsetY = (uiDisplay - middle_buf1)/this->screen->pitch;

    //ShowLogo (this, uiDisplay);
    
    return 0;
}
 
//
#endif
#endif
#endif
static void HI3560_DeleteDevice(GAL_VideoDevice *device)
{
}

#ifdef _MGRM_THREADS
BOOL HI3560_CreateDevice(GAL_VideoDevice *device)
{
    int console;
    const char *GAL_fbdev;
    GAL_VideoDevice *this = device;

    if (device == NULL)
    {
        return FALSE;
    }

    GAL_fbdev = "/dev/fb/0";
    console_fd = open(GAL_fbdev, O_RDWR, 0);
    if ( console_fd < 0 ) 
    {
        return FALSE;
    }
    
    
    memset(this, 0, (sizeof *this));
 
    wait_vbl = HI3560_WaitVBL;
    wait_idle = HI3560_WaitIdle;

    this->name = "fbcon";

    /* Set the function pointers */
    this->VideoInit = HI3560_VideoInit;
    this->ListModes = HI3560_ListModes;
    this->SetVideoMode = HI3560_SetVideoMode;
    this->VideoQuit = HI3560_VideoQuit;
    this->AllocHWSurface = HI3560_AllocHWSurface;
#ifdef _USE_2D_ACCEL
#ifdef _USE_DBUF
    this->CheckHWBlit = HI3560_CheckHWBlit;
    this->FillHWRect = HI3560_FillHWRect;
    this->FillHWRectWithPattern = NULL;//the pattern fill is slower than do by software,so do not use it.
#endif
#endif
    this->FreeHWSurface = HI3560_FreeHWSurface;
    this->free = HI3560_DeleteDevice;
    g_pVideo_3560 = this;

    return TRUE;
}
#endif

static int HI3560_VideoInit(_THIS, GAL_PixelFormat *vformat)
{
    struct fb_fix_screeninfo finfo;
    struct fb_var_screeninfo vinfo;
    GAL_VideoInfo* paccel_info =  &this->info;
    int i;
#ifdef _PC_DEBUG
    static unsigned char tde_register_base[0x100];
#endif
    console_fd = hi3560_console;
    /* Get the type of video hardware */
    if ( ioctl(console_fd, FBIOGET_FSCREENINFO, &finfo) < 0 ) 
    {
        fprintf (stderr, "Couldn't get console hardware info\n");
        HI3560_VideoQuit(this);
        return(-1);
    }

    /* Memory map the device, compensating for buggy PPC mmap() */
    mapped_offset = (((long)finfo.smem_start) -
                    (((long)finfo.smem_start)&~(PAGE_SIZE-1)));
    mapped_memlen = finfo.smem_len+mapped_offset;
    mapped_mem = mmap(NULL, mapped_memlen,
                      PROT_READ|PROT_WRITE, MAP_SHARED, console_fd, 0);

    if ( mapped_mem == (Uint8 *)-1 ) {
        fprintf (stderr, "Unable to memory map the video hardware\n");
        mapped_mem = NULL;
        HI3560_VideoQuit(this);
        return(-1);
    }

    /* Determine the current screen depth */
    if ( ioctl(console_fd, FBIOGET_VSCREENINFO, &vinfo) < 0 ) {
        fprintf (stderr, "Couldn't get console pixel format\n");
        HI3560_VideoQuit(this);
        return(-1);
    }
    vformat->BitsPerPixel = vinfo.bits_per_pixel;
 
    for ( i=0; i<vinfo.red.length; ++i ) {
        vformat->Rmask <<= 1;
        vformat->Rmask |= (0x00000001<<vinfo.red.offset);
    }
    for ( i=0; i<vinfo.green.length; ++i ) {
        vformat->Gmask <<= 1;
        vformat->Gmask |= (0x00000001<<vinfo.green.offset);
    }
    for ( i=0; i<vinfo.blue.length; ++i ) {
        vformat->Bmask <<= 1;
        vformat->Bmask |= (0x00000001<<vinfo.blue.offset);
    }

    for ( i=0; i<vinfo.transp.length; ++i ) {
        vformat->Amask <<= 1;
        vformat->Amask |= (0x00000001<<vinfo.transp.offset);
    }

    if ( finfo.accel && finfo.mmio_len ) {
        mapped_iolen = finfo.mmio_len;
        mapped_io = mmap(NULL, mapped_iolen, PROT_READ|PROT_WRITE,
                         MAP_SHARED, console_fd, mapped_memlen);
        if ( mapped_io == (Uint8 *)-1 ) {
            /* Hmm, failed to memory map I/O registers */
            mapped_io = NULL;
            fprintf(stderr, "failed to mmap 2d register!\n");
            return -1;
        }
    }

    paccel_info->hw_available = 1;
    paccel_info->video_mem = finfo.smem_len/1024;
#ifdef _USE_2D_ACCEL
    paccel_info->blit_fill = 1;
    paccel_info->blit_hw = 1;
    paccel_info->blit_hw_A = 1;
    paccel_info->blit_hw_CC = 1;
#if 0
    paccel_info->blit_hw_CS = 1;
    paccel_info->blit_hw_rop = 1;
    paccel_info->blit_patternfill =0;
#endif
//#ifndef _PC_DEBUG
//    TDE_Init(mapped_io+TDE_OFFSET);
//#else
//    TDE_Init(tde_register_base);
//#endif
#endif

    /* We're done! */
    printf ("you are using console frame buffer video driver!\n");
    return(0);
}

static GAL_Rect **HI3560_ListModes(_THIS, GAL_PixelFormat *format, Uint32 flags)
{
    return (GAL_Rect**)(-1);
}


#ifdef FBCON_DEBUG
static void print_vinfo(struct fb_var_screeninfo *vinfo)
{
    fprintf(stderr, "Printing vinfo:\n");
    fprintf(stderr, "txres: %d\n", vinfo->xres);
    fprintf(stderr, "tyres: %d\n", vinfo->yres);
    fprintf(stderr, "txres_virtual: %d\n", vinfo->xres_virtual);
    fprintf(stderr, "tyres_virtual: %d\n", vinfo->yres_virtual);
    fprintf(stderr, "txoffset: %d\n", vinfo->xoffset);
    fprintf(stderr, "tyoffset: %d\n", vinfo->yoffset);
    fprintf(stderr, "tbits_per_pixel: %d\n", vinfo->bits_per_pixel);
    fprintf(stderr, "tgrayscale: %d\n", vinfo->grayscale);
    fprintf(stderr, "tnonstd: %d\n", vinfo->nonstd);
    fprintf(stderr, "tactivate: %d\n", vinfo->activate);
    fprintf(stderr, "theight: %d\n", vinfo->height);
    fprintf(stderr, "twidth: %d\n", vinfo->width);
    fprintf(stderr, "taccel_flags: %d\n", vinfo->accel_flags);
    fprintf(stderr, "tpixclock: %d\n", vinfo->pixclock);
    fprintf(stderr, "tleft_margin: %d\n", vinfo->left_margin);
    fprintf(stderr, "tright_margin: %d\n", vinfo->right_margin);
    fprintf(stderr, "tupper_margin: %d\n", vinfo->upper_margin);
    fprintf(stderr, "tlower_margin: %d\n", vinfo->lower_margin);
    fprintf(stderr, "thsync_len: %d\n", vinfo->hsync_len);
    fprintf(stderr, "tvsync_len: %d\n", vinfo->vsync_len);
    fprintf(stderr, "tsync: %d\n", vinfo->sync);
    fprintf(stderr, "tvmode: %d\n", vinfo->vmode);
    fprintf(stderr, "tred: %d/%d\n", vinfo->red.length, vinfo->red.offset);
    fprintf(stderr, "tgreen: %d/%d\n", vinfo->green.length, vinfo->green.offset);
    fprintf(stderr, "tblue: %d/%d\n", vinfo->blue.length, vinfo->blue.offset);
    fprintf(stderr, "talpha: %d/%d\n", vinfo->transp.length, vinfo->transp.offset);
}

static void print_finfo(struct fb_fix_screeninfo *finfo)
{
    fprintf(stderr, "Printing finfo:\n");
    fprintf(stderr, "tsmem_start = %p\n", (char *)finfo->smem_start);
    fprintf(stderr, "tsmem_len = %d\n", finfo->smem_len);
    fprintf(stderr, "ttype = %d\n", finfo->type);
    fprintf(stderr, "ttype_aux = %d\n", finfo->type_aux);
    fprintf(stderr, "tvisual = %d\n", finfo->visual);
    fprintf(stderr, "txpanstep = %d\n", finfo->xpanstep);
    fprintf(stderr, "typanstep = %d\n", finfo->ypanstep);
    fprintf(stderr, "tywrapstep = %d\n", finfo->ywrapstep);
    fprintf(stderr, "tline_length = %d\n", finfo->line_length);
    fprintf(stderr, "tmmio_start = %p\n", (char *)finfo->mmio_start);
    fprintf(stderr, "tmmio_len = %d\n", finfo->mmio_len);
    fprintf(stderr, "taccel = %d\n", finfo->accel);
}
#endif

static const HI_GC_CMAP_S s_fbargb[] = 
{
#if 0	
    {
        .red    = {8, 4, 0}, //RGB444
        .green  = {4, 4, 0},
        .blue   = {0, 4, 0},
        .transp = {0, 0, 0},
    },
#endif    
    {
        .red    = {8, 4, 0}, //RGB4444
        .green  = {4, 4, 0},
        .blue   = {0, 4, 0},
        .transp = {12, 4, 0},
    },
#if 0
	{
        .red    = {10, 5, 0}, //RGB555
        .green  = {5, 5, 0},
        .blue   = {0, 5, 0},
        .transp = {0, 0, 0},
    },
 #endif   
    {
        .red    = {10, 5, 0},//RGB1555
        .green  = {5, 5, 0},
        .blue   = {0, 5, 0},
        .transp = {15, 1, 0},
    },

    {
        .red    = {11, 5, 0},//RGB565
        .green  = {5, 6, 0},
        .blue   = {0, 5, 0},
        .transp = {0, 0, 0},
    },
    
#if 0
	{
        .red    = {16, 8, 0},//RGB888
        .green  = {8, 8, 0},
        .blue   = {0, 8, 0},
        .transp = {0, 0, 0},
    },
 #endif   
    {
        .red    = {16, 8, 0},//RGB8888
        .green  = {8, 8, 0},
        .blue   = {0, 8, 0},
        .transp = {24, 8, 0},
    }
};
static GAL_Surface *HI3560_SetVideoMode(_THIS, GAL_Surface *current,
                int width, int height, int bpp, Uint32 flags)
{
    struct fb_var_screeninfo vinfo;
    int i;
    Uint32 Rmask;
    Uint32 Gmask;
    Uint32 Bmask;
    Uint32 Amask;
    Uint8 *surfaces_mem;
    int surfaces_len;
    int iAFBufLen = -1;
    
printf ("{%s}[%s](%d), w=%d,h=%d\n", __FILE__, __func__, __LINE__, width, height);
#if (defined(_TAP_ALL) || defined(_TAP3_VERT_HORI) || defined(_TAP2_VERT) \
     || defined(_TAP2_VERT_HORI)|| defined(_TAP3_VERT)) \
     && defined(_USE_2D_ACCEL) && defined(_USE_DBUF)    
	Uint32 uiVirtualYRes = 0;     
#endif   

    /* Set the video mode and get the final screen format */
    if ( ioctl(console_fd, FBIOGET_VSCREENINFO, &vinfo) < 0 ) 
    {
        fprintf (stderr, "Couldn't get console screen info");
        return(NULL);
    }
    
#ifdef FBCON_DEBUG
    fprintf(stderr, "Printing original vinfo:\n");
    print_vinfo(&vinfo);
#endif

  	if (mgIsServer)
  	{
	    vinfo.activate = FB_ACTIVATE_NOW;
	    vinfo.accel_flags = 0;
	    vinfo.bits_per_pixel = bpp;
	    vinfo.xres = width;
	    //vinfo.xres_virtual = width;
	    vinfo.xres_virtual = 800;
	    vinfo.yres = height;
	    //vinfo.yres_virtual = height;
	    vinfo.yres_virtual = 480;
	    vinfo.xoffset = 0;
	    vinfo.yoffset = 0;
#if 0	    
	    vinfo.red.length = vinfo.red.offset = 0;
	    vinfo.green.length = vinfo.green.offset = 0;
	    vinfo.blue.length = vinfo.blue.offset = 0;
	    vinfo.transp.length = vinfo.transp.offset = 0;
#endif
		vinfo.red  = s_fbargb[HI_GC_PF_RGB1555-1].red;
		vinfo.blue = s_fbargb[HI_GC_PF_RGB1555-1].blue;
		vinfo.green = s_fbargb[HI_GC_PF_RGB1555-1].green;		
		vinfo.transp = s_fbargb[HI_GC_PF_RGB1555-1].transp;
		
	#ifdef FBCON_DEBUG
	    fprintf(stderr, "Printing wanted vinfo:\n");
	    print_vinfo(&vinfo);
	#endif
printf ("{%s}[%s](%d)\n", __FILE__, __func__, __LINE__);
	    if ( ioctl(console_fd, FBIOPUT_VSCREENINFO, &vinfo) < 0 ) 
	    {
	            fprintf (stderr, "Couldn't set console screen info");
	            return(NULL);
	    }
    }

printf ("{%s}[%s](%d), %d,%d, w=%d,h=%d\n", __FILE__, __func__, __LINE__, vinfo.xres, vinfo.yres, width, height);
    /* Get the fixed information about the console hardware.
       This is necessary since finfo.line_length changes.
     */
    if ( ioctl(console_fd, FBIOGET_FSCREENINFO, &saved_finfo) < 0) 
    {
        fprintf (stderr, "Couldn't get console hardware info");
        return(NULL);
    }
    

#if (defined(_TAP_ALL) || defined(_TAP3_VERT_HORI) || defined(_TAP2_VERT) \
     || defined(_TAP2_VERT_HORI)|| defined(_TAP3_VERT)) \
     && defined(_USE_2D_ACCEL) && defined(_USE_DBUF)
    if (-1 == (iAFBufLen = HI3560_GetAllAFVMem(this,
    	   saved_finfo.line_length, vinfo.yres, &uiVirtualYRes)))
    {
       fprintf(stderr, "Don't have enough video mem for AntiFlicker\n");
       tap_level = 0;
    }   
    else
    {
        if (mgIsServer)
        {
	        /* Set the video mode and get the final screen format */
	        memset(&vinfo, 0, sizeof(struct fb_var_screeninfo));       
printf ("{%s}[%s](%d)\n", __FILE__, __func__, __LINE__);
		    if ( ioctl(console_fd, FBIOGET_VSCREENINFO, &vinfo) < 0 ) 
		    {
		        fprintf (stderr, "Couldn't get console screen info");
		        return(NULL);
		    }
		    vinfo.yres_virtual = uiVirtualYRes;
		    
	#ifdef FBCON_DEBUG
		    fprintf(stderr, "Printing final vinfo:\n");
		    print_vinfo(&vinfo);
	#endif

		    if ( ioctl(console_fd, FBIOPUT_VSCREENINFO, &vinfo) < 0 ) 
	        {
	            fprintf (stderr, "Couldn't set console screen info");
	            return(NULL);
	        }
	    }
        
        /*obligate some video memory for antiflicker*/
	    current->pixels = (void *)((Uint32)mapped_mem 
	                      + (Uint32)mapped_offset + (Uint32)iAFBufLen); 
	    surfaces_mem = (Uint8 *)((Uint32)current->pixels 
	    	            + (Uint32)saved_finfo.line_length * vinfo.yres);
#if 0         
   icount = 0;
            k = 0;
            while(icount < 1000)
            {
                printf("i = %d\n", icount);
                printf("i = %d\n", icount);
               if (k == 0)
               {
                memset(mapped_mem + mapped_offset, 0x55, saved_finfo.line_length*vinfo.yres);
                k = 1;
                printf("res:0\n");
	        HI3560_SetOffset(console_fd, 0, 0);
               }
               else
               {
                memset(mapped_mem + mapped_offset + saved_finfo.line_length*vinfo.yres, 0x55, saved_finfo.line_length*(vinfo.yres - 500));
                memset(mapped_mem + mapped_offset + saved_finfo.line_length*(1*vinfo.yres-500), 0x99, saved_finfo.line_length*400);
                memset(mapped_mem + mapped_offset + saved_finfo.line_length*(1*vinfo.yres-100), 0x55, saved_finfo.line_length*100);
                k = 0;
                printf("res:%d\n", vinfo.yres);
	        HI3560_SetOffset(console_fd, 0, vinfo.yres);
               
               }           
                usleep(50000);
               icount++;
           }
#endif
            
	    if (mgIsServer)
	    {
printf ("{%s}[%s](%d)\n", __FILE__, __func__, __LINE__);
	        HI3560_SetOffset(console_fd, 0, iAFBufLen/saved_finfo.line_length);
	    }
	}
#endif
     
    
#ifdef FBCON_DEBUG
    fprintf (stderr, "Printing actual vinfo:\n");
    print_vinfo(&vinfo);
#endif
    Rmask = 0;
    for ( i=0; i<vinfo.red.length; ++i ) {
        Rmask <<= 1;
        Rmask |= (0x00000001<<vinfo.red.offset);
    }
    Gmask = 0;
    for ( i=0; i<vinfo.green.length; ++i ) {
        Gmask <<= 1;
        Gmask |= (0x00000001<<vinfo.green.offset);
    }
    Bmask = 0;
    for ( i=0; i<vinfo.blue.length; ++i ) {
        Bmask <<= 1;
        Bmask |= (0x00000001<<vinfo.blue.offset);
    }

    Amask = 0;
    for ( i=0; i<vinfo.transp.length; ++i ) {
        Amask <<= 1;
        Amask |= (0x00000001<<vinfo.transp.offset);
    }

    if (!GAL_ReallocFormat(current, vinfo.bits_per_pixel,
                                      Rmask, Gmask, Bmask, Amask) ) 
    {
        return(NULL);
    }    

    /* Set up the new mode framebuffer */
    //current->flags = (GAL_FULLSCREEN|GAL_HWSURFACE);
    current->w = vinfo.xres;
    current->h = vinfo.yres;
    current->pitch = saved_finfo.line_length;

    printf ("{%s}[%s](%d):%d,%d\n", __FILE__, __func__, __LINE__, current->w, current->h);
    if (-1 == iAFBufLen)
    {
        current->pixels = mapped_mem+mapped_offset;

        /* Set up the information for hardware surfaces */
        surfaces_mem = (char *)current->pixels + vinfo.yres * current->pitch;
    }
    
    surfaces_len = (mapped_memlen -(surfaces_mem-mapped_mem));    

#ifdef _MGRM_PROCESSES
    if (mgIsServer)
#endif
    {
        DBGLINE();
        HI3560_FreeHWSurfaces(this);
        HI3560_InitHWSurfaces(this, current, surfaces_mem, surfaces_len);

        /*logosurface.w = BM_WIDTH;
        logosurface.h = BM_HEIGHT;
        logosurface.pitch = 2 * BM_WIDTH;
        this->screen = current;
        HI3560_AllocHWSurface (this, &logosurface);
        FillMemWithData(logosurface.pixels);     */
        DBGLINE();
    }
#ifdef _MGRM_PROCESSES
    else 
    {
    	static struct private_hwdata data;
    	data.pDevice = this;
        current->hwdata = &data;
    }
#endif

   current->flags = (GAL_FULLSCREEN|GAL_HWSURFACE);

printf ("{%s}[%s](%d)\n", __FILE__, __func__, __LINE__);
    /* We're done */
    return(current);
}

#ifdef FBCON_DEBUG
static void HI3560_DumpHWSurfaces(_THIS)
{
    vidmem_bucket *bucket;

    fprintf(stderr, "Memory left: %d (%d total)\n", surfaces_memleft, surfaces_memtotal);
    fprintf(stderr, "\n");
    fprintf(stderr, "         Base  Size\n");
    for ( bucket=&surfaces; bucket; bucket=bucket->next ) {
        fprintf(stderr, "Bucket:  %p, %d (%s)\n", bucket->base, bucket->size, bucket->used ? "used" : "free");
        if ( bucket->prev ) {
            if ( bucket->base != bucket->prev->base+bucket->prev->size ) {
                fprintf(stderr, "Warning, corrupt bucket list! (prev)\n");
            }
        } else {
            if ( bucket != &surfaces ) {
                fprintf(stderr, "Warning, corrupt bucket list! (!prev)\n");
            }
        }
        if ( bucket->next ) {
            if ( bucket->next->base != bucket->base+bucket->size ) {
                fprintf(stderr, "Warning, corrupt bucket list! (next)\n");
            }
        }
    }
    fprintf(stderr, "\n");
}
#endif

static int HI3560_InitHWSurfaces(_THIS, GAL_Surface *screen, char *base, int size)
{
    vidmem_bucket *bucket;

    surfaces_memtotal = size;
    surfaces_memleft = size;

    if ( surfaces_memleft > 0 ) {
        bucket = (vidmem_bucket *)malloc(sizeof(*bucket));
        if ( bucket == NULL ) {
            fprintf (stderr, "Out of memory\n");
            return(-1);
        }
        bucket->prev = &surfaces;
        bucket->used = 0;

        bucket->base = base;
        bucket->size = size;
        bucket->next = NULL;
    } else {
        bucket = NULL;
    }

    surfaces.prev = NULL;
    surfaces.used = 1;

    surfaces.base = screen->pixels;
    surfaces.size = (unsigned int)((long)base - (long)surfaces.base);
    surfaces.next = bucket;
#ifndef _MGRM_THREADS
    screen->hwdata = HI3560_CreateHwData(this, &surfaces);
#else
    screen->hwdata = (struct private_hwdata *)&surfaces;
#endif    
    return(0);
}

static void HI3560_FreeHWSurfaces(_THIS)
{
    vidmem_bucket *bucket, *freeable;

    bucket = surfaces.next;
    while ( bucket ) {
        freeable = bucket;
        bucket = bucket->next;
        free(freeable);
    }
    surfaces.next = NULL;
}

static void HI3560_RequestHWSurface (_THIS, const REQ_HWSURFACE* request, REP_HWSURFACE* reply)
{
    if (request->bucket == NULL) {     /* alloc hw surface */
        vidmem_bucket *bucket;
        int size;
        int extra;

        reply->bucket = NULL;
        /* Temporarily, we only allow surfaces the same width as display.
           Some blitters require the pitch between two hardware surfaces
           to be the same.  Others have interesting alignment restrictions.
           Until someone who knows these details looks at the code...
        */
        if (request->pitch > this->screen->pitch) {
            fprintf (stderr, "Surface requested wider than screen\n");
            return;
        }

        reply->pitch = this->screen->pitch;
        size = request->h * reply->pitch;
#ifdef FBCON_DEBUG
        fprintf(stderr, "reply->pitch: %d, request->h:%d, Allocating bucket of %d bytes\n", reply->pitch, request->h, size);
#endif

        /* Quick check for available mem */
        if ( size > surfaces_memleft ) {
            fprintf (stderr, "Not enough video memory\n");
            return;
        }

        /* Search for an empty bucket big enough */
        for ( bucket=&surfaces; bucket; bucket=bucket->next ) {
            if ( ! bucket->used && (size <= bucket->size) ) {
                break;
            }
        }
        if ( bucket == NULL ) {
            fprintf (stderr, "Video memory too fragmented\n");
            return;
        }

        /* Create a new bucket for left-over memory */
        extra = (bucket->size - size);
        if ( extra ) {
            vidmem_bucket *newbucket;

#ifdef FBCON_DEBUG
            fprintf(stderr, "Adding new free bucket of %d bytes\n", extra);
#endif
            newbucket = (vidmem_bucket *)malloc(sizeof(*newbucket));
            if ( newbucket == NULL ) {
                fprintf (stderr, "Out of memory\n");
                return;
            }
            newbucket->prev = bucket;
            newbucket->used = 0;
            newbucket->base = bucket->base + size;
            newbucket->size = extra;
            newbucket->next = bucket->next;
            if ( bucket->next ) {
                bucket->next->prev = newbucket;
            }
            bucket->next = newbucket;
        }

        /* Set the current bucket values and return it! */
        bucket->used = 1;
        bucket->size = size;

#ifdef FBCON_DEBUG
        fprintf(stderr, "Allocated %d bytes at %p\n", bucket->size, bucket->base);
#endif
        surfaces_memleft -= size;

        reply->bucket = bucket;
        reply->offset = bucket->base - mapped_mem;
    }
    else {  /* free hw surface */
        vidmem_bucket *bucket, *freeable;

        /* Look for the bucket in the current list */
        for ( bucket=&surfaces; bucket; bucket=bucket->next ) {
            if ( bucket == (vidmem_bucket *)request->bucket) {
                break;
            }
        }
        if ( bucket && bucket->used ) {
        /* Add the memory back to the total */
#ifdef FBCON_DEBUG
            fprintf(stderr, "Freeing bucket of %d bytes\n", bucket->size);
#endif
            surfaces_memleft += bucket->size;

            /* Can we merge the space with surrounding buckets? */
            bucket->used = 0;
            if ( bucket->next && ! bucket->next->used ) {
#ifdef FBCON_DEBUG
                fprintf(stderr, "Merging with next bucket, for %d total bytes\n", bucket->size+bucket->next->size);
#endif
                freeable = bucket->next;
                bucket->size += bucket->next->size;
                bucket->next = bucket->next->next;
                if ( bucket->next ) {
                    bucket->next->prev = bucket;
                }
                free(freeable);
            }
            if ( bucket->prev && ! bucket->prev->used ) {
#ifdef FBCON_DEBUG
                fprintf(stderr, "Merging with previous bucket, for %d total bytes\n", bucket->prev->size+bucket->size);
#endif
                freeable = bucket;
                bucket->prev->size += bucket->size;
                bucket->prev->next = bucket->next;
                if ( bucket->next ) {
                    bucket->next->prev = bucket->prev;
                }
                free(freeable);
            }
        }
    }
}

static int HI3560_AllocHWSurface (_THIS, GAL_Surface *surface)
{
    REQ_HWSURFACE request = {surface->w, surface->h, surface->pitch, 0, NULL};
    REP_HWSURFACE reply = {0, 0, NULL};
#ifdef _MGRM_PROCESSES
    if (mgIsServer)
        
        HI3560_RequestHWSurface (this, &request, &reply);
    else {
        REQUEST req;
        if (surface->w*surface->h == 0)
        {
            goto NEXT;   	
        }
        req.id = REQID_HWSURFACE;
        req.data = &request;
        req.len_data = sizeof (REQ_HWSURFACE);

        ClientRequest (&req, &reply, sizeof (REP_HWSURFACE));
    }
#else
    HI3560_RequestHWSurface (this, &request, &reply);
#endif

    if (reply.bucket == NULL)
        return -1;
NEXT:
    surface->flags |= GAL_HWSURFACE;
    surface->pitch = reply.pitch;
    surface->pixels = mapped_mem + reply.offset;
#ifndef _MGRM_THREADS
    surface->hwdata = (struct private_hwdata *)HI3560_CreateHwData(this, reply.bucket);
#else
    surface->hwdata = (struct private_hwdata *)reply.bucket;
#endif
    return 0;
}

static void HI3560_FreeHWSurface(_THIS, GAL_Surface *surface)
{
    REQ_HWSURFACE request = {surface->w, surface->h, surface->pitch, 0, surface->hwdata};
    REP_HWSURFACE reply = {0, 0};

    request.offset = (char*)surface->pixels - (char*)mapped_mem;

#ifdef _MGRM_PROCESSES
    request.bucket = ((struct private_hwdata*)surface->hwdata)->pBucket;
    if (mgIsServer)
        HI3560_RequestHWSurface (this, &request, &reply);
    else {
        REQUEST req;

        if (surface->hwdata == NULL) {
            surface->pixels = NULL;
            return;
        }

        //request.bucket = surface->hwdata;

        req.id = REQID_HWSURFACE;
        req.data = &request;
        req.len_data = sizeof (REQ_HWSURFACE);

        ClientRequest (&req, &reply, sizeof (REP_HWSURFACE));
    }

    free(surface->hwdata);
#else
    HI3560_RequestHWSurface (this, &request, &reply);
#endif

    surface->pixels = NULL;
    surface->hwdata = NULL;
}


static void HI3560_WaitVBL(_THIS)
{
    return;
}

static void HI3560_WaitIdle(_THIS)
{
    return;
}

/* Note:  If we are terminated, this could be called in the middle of
   another SDL video routine -- notably UpdateRects.
*/


static void HI3560_VideoQuit(_THIS)
{
    printf("HI3560_VideoQuit:\n");
    DBGLINE();
#ifdef _MGRM_PROCESSES
    if ( mgIsServer && this->screen ) {
#else
    if ( this->screen ) {
#endif
    DBGLINE();
        /* Clear screen and tell SDL not to free the pixels */
        if ( this->screen->pixels ) {
            memset(this->screen->pixels,0,this->screen->h*this->screen->pitch);
        }
        /* This test fails when using the VGA16 shadow memory */
        if ( ((Uint8*)this->screen->pixels >= mapped_mem) &&
             ((Uint8*)this->screen->pixels < (mapped_mem+mapped_memlen)) ) {
            this->screen->pixels = NULL;
        }
    DBGLINE();
    }

    /* Clear the lock mutex */
#ifdef _MGRM_PROCESSES
    if ( mgIsServer && hw_lock ) {
#else
    if ( hw_lock ) {
#endif
        GAL_DestroyMutex(hw_lock);
        hw_lock = NULL;
    }

    DBGLINE();
    /* Clean up the memory bucket list */
#ifdef _MGRM_PROCESSES
    if (mgIsServer)
#endif
    {
    DBGLINE();
        HI3560_FreeHWSurfaces(this);
#ifndef _MGRM_THREADS
        HI3560_SetLayerAttr(this, SCREEN_ATTR_ALPHA_CHANNEL, NULL);
        HI3560_SetLayerAttr(this, SCREEN_ATTR_COLORKEY, NULL);
    DBGLINE();
#endif
    }

    DBGLINE();
    //HI3560_FreeHWSurface (this, &logosurface);

    DBGLINE();
    /* Close console and input file descriptors */
    printf("HI3560_VideoQuit:close console_fd:%d\n", console_fd);

    if ( console_fd > 0 ) {
        /* Unmap the video framebuffer and I/O registers */
        if ( mapped_mem ) {
            munmap(mapped_mem, mapped_memlen);
            mapped_mem = NULL;
        }
        if ( mapped_io ) {
            munmap(mapped_io, mapped_iolen);
            mapped_io = NULL;
        }

        /* We're all done with the framebuffer */
        close(console_fd);
        console_fd = -1;
    }

#if 1
    DBGLINE();
    HI_DEVICE_CLOSE();
    DBGLINE();
#endif
}

#ifdef _MGRM_THREADS
void* HI3560_MallocFromVram(int size)
{
    REQ_HWSURFACE request = {1, 0, 1, 0, NULL};
    REP_HWSURFACE reply = {0, 0, NULL};
    Uint8* pBlockHead;
    Uint32 pitch = g_pVideo_3560->screen->pitch;

    if (size == 0)
       return NULL;

    size += sizeof(struct private_hwdata *);
    request.h = (size+pitch-1)/pitch;

    HI3560_RequestHWSurface (current_video, &request, &reply);
    
    if (reply.bucket == NULL)
    {
        fprintf(stderr, "failed to malloc vram, size:%d!\n", size); 
        return NULL;
    }

    pBlockHead = mapped_mem + reply.offset;
    *(struct private_hwdata **)pBlockHead = (struct private_hwdata *)reply.bucket;
    return pBlockHead + sizeof(struct private_hwdata *);
}

void HI3560_FreeToVram(void* p)
{
    REQ_HWSURFACE request = {1, 0, 1, 0, 0};
    REP_HWSURFACE reply = {0, 0};
    fprintf(stderr, "hi3560 free vram\n");
    request.offset = (char*)p - (char*)mapped_mem + sizeof(struct private_hwdata *);
    request.bucket = *(char**)((char*)p - sizeof(struct private_hwdata *));
    request.h = request.offset;

    HI3560_RequestHWSurface (current_video, &request, &reply);
}
#endif

#ifndef _MGRM_THREADS
static struct private_hwdata* HI3560_CreateHwData(_THIS, const vidmem_bucket* pBucket)
{
	struct private_hwdata* pData;
	pData = (struct private_hwdata*)malloc(sizeof(struct private_hwdata));
	if (pData == NULL)
	{
		fprintf(stderr, "failed to create private_hwdata!\n");
		exit(-1);
	}
	else
	{
		pData->pBucket = pBucket;
		pData->pDevice = this;
	}
		
	return pData;
}

static int HI3560_SetLayerAlpha(int  fd,  Uint32* pAlpha)
{
    fb_alpha Alpha = {0};

    if (pAlpha == NULL)
    {
        return 0;
    }
    else
    {
        Alpha.bAlphaEnable = HI_TRUE;
        Alpha.bAlphaChannel = HI_FALSE;
        Alpha.u8Alpha0 = (HI_U8)(*pAlpha);
        Alpha.u8Alpha1 = (HI_U8)(*pAlpha);
    }

    if (ioctl(fd, FBIOPUT_ALPHA_HIFB,  &Alpha) <0)
    {
        fprintf(stderr, "failed to set layer alpha attribute!\n");
        return -1;
    }
    return 0;
}

static int HI3560_SetLayerAttr(_THIS, Uint8 siAttr, void * pValue)
{
	int ret = 0;
	switch(siAttr)
	{
		case SCREEN_ATTR_ALPHA_CHANNEL:
		{
#if 0			
    		Uint8 alpha0, alpha1;
    		Uint32 alpha;
			if (pValue != NULL)
			{
				alpha1 = alpha0 = *(Uint8*)pValue;
			}
			else
			{
				alpha1 = alpha0 = 0xff;
			}
			
			alpha  = (alpha1 << 8) + alpha0; 
			if (ioctl(console_fd, FBIOPUT_ALPHA_HIFB,  &alpha) <0)
			{
				fprintf(stderr, "failed to set layer alpha attribute!\n");
				ret = -1;
			}
#endif
                     ret = HI3560_SetLayerAlpha(console_fd, (Uint32*)pValue);
			break;
		}

		case SCREEN_ATTR_COLORKEY:
        {
            fb_colorkey ck = {0};

            if (pValue != NULL)
            {
                ck.u32Key = *(HI_U32*)pValue;
                ck.bKeyEnable = HI_TRUE;
                ck.bMaskEnable = HI_FALSE;
            }
            else
            {
                ck.bKeyEnable = HI_FALSE;
                ck.bMaskEnable = HI_FALSE;
            }

            if (ioctl(console_fd, FBIOPUT_COLORKEY_HIFB, &ck) < 0)
            {
                fprintf(stderr, "failed to set layer color key attribute!\n");
                ret = -1;
            }
            break;
        }
		
		default:
			fprintf(stderr, "the attribute :%d is not supported!\n", siAttr);
			ret = -1;
	}

   return ret;
}

//pszLayer maybe is "fb0" or "fb1"
static GAL_VideoDevice *HI3560_CreateDevice (int devindex)
{
    GAL_VideoDevice *this;
    const char *GAL_fbdev;

    if(mgIsServer){
        HI_DEVICE_OPEN();
#if 0
        DISPLAY_ATTR_S l_display_attr;
        if(HI_API_DISPLAY_Open() != HI_RET_SUCCESS){
            printf("HI_API_DISPLAY_Open error\n");
            return 0;
        }

        if(HI_API_DISPLAY_GetAttr (&l_display_attr) != HI_RET_SUCCESS){
            printf("HI_API_DISPLAY_GetArrt error\n");
            return 0;
        }
        printf("screen width=%d,screen height=%d\n",l_display_attr.lcd_config.HACT,l_display_attr.lcd_config.VACT);
        l_display_attr.enable = HI_TRUE ;
        l_display_attr.gpc_layer_enable[2] = HI_FALSE;
        l_display_attr.display_mode = DISPLAY_MODE_DIGITAL;
        l_display_attr.lcd_config.HACT =800;
        l_display_attr.lcd_config.VBB =10;
        l_display_attr.lcd_config.HBB =160;
        l_display_attr.lcd_config.HFB =10;

        if(HI_API_DISPLAY_SetAttr (&l_display_attr) != HI_RET_SUCCESS){
            printf("HI_API_DISPLAY_SetAttr error\n");
            return 0;
        }

        /*if(HI_API_TDE_Open() !=HI_SUCCESS){
            printf("HI_API_TDE_Open error\n");
            return 0;
        }*/
#endif
    }

    GAL_fbdev = getenv("FRAMEBUFFER");
    if ( GAL_fbdev == NULL ) {
        GAL_fbdev = "/dev/fb/0";
    }

    hi3560_console = open(GAL_fbdev, O_RDWR, 0);
    if(hi3560_console <0){
        fprintf(stderr, "failed to open file :%s!\n", GAL_fbdev);
        return 0;
    }

    /* Initialize all variables that we clean on shutdown */
    this = (GAL_VideoDevice *)malloc(sizeof(GAL_VideoDevice));
    memset(this, 0, (sizeof *this));

    if ( this ) {
        memset(this, 0, (sizeof *this));
        this->hidden = (struct GAL_PrivateVideoData *)
                malloc((sizeof *this->hidden));

        this->name = "hi3560";
        this->gamma = (Uint16*)&g_stHidden_3560[0];
    }

    if ( (this == NULL) || (this->hidden == NULL) ) {
        GAL_OutOfMemory();
        if ( this ) {
            free(this);
        }
        return(0);
    }

    memset(this->hidden, 0, (sizeof *this->hidden));
    wait_vbl = HI3560_WaitVBL;
    wait_idle = HI3560_WaitIdle;


    /* Set the function pointers */
    this->VideoInit = HI3560_VideoInit;
    this->ListModes = HI3560_ListModes;
    this->SetVideoMode = HI3560_SetVideoMode;
    this->VideoQuit = HI3560_VideoQuit;
#ifdef _MGRM_PROCESSES
    this->RequestHWSurface = HI3560_RequestHWSurface;
#endif
    this->AllocHWSurface = HI3560_AllocHWSurface;
#ifdef _USE_2D_ACCEL
#ifdef _USE_DBUF
    this->CheckHWBlit = HI3560_CheckHWBlit;
    this->FillHWRect = HI3560_FillHWRect;
    //this->FillHWRectWithPattern = NULL;//HI3560_FillHWRectWithPattern;
#endif
#endif
    this->FreeHWSurface = HI3560_FreeHWSurface;
    this->SetHWAlpha = NULL;
    this->SetHWColorKey = NULL;
    this->free = HI3560_DeleteDevice;
    //this->SetAttr   = HI3560_SetLayerAttr;

    return this;
}
#endif

VideoBootStrap HI3560_bootstrap = {
    "hi3560", "HI3560 Framebuffer Console",
    HI3560_Available, HI3560_CreateDevice
};

//////////////////////////////////////////////////////////////
//Added by l56244 on 27,July 2006
int HI3560_GetVideoFD(void)
{
	GAL_VideoDevice* this = current_video;
	return console_fd;
}

void* HI3560_GetMM_0(void)
{
	GAL_VideoDevice* this = current_video;
	return mapped_mem;
}

#endif
//Added Ends
