/*
   Videoblaster SE100 driver by Kate Alhola
   Copyright Kate Alhola 1995
   kate@nic.funet.fi
   http://www.funet.fi/~kate

   Supports chipset:
   SAA7195A   Video memory controller
   SAA7165    Video Enchancement D/A processor ( VEDA2 )
   SAA7110    One Chip Frontend 1 (OFC1)
   TDA4686    Video Processor with automatic cut-off and white level controll

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License version 2, as
   published by the Free Software Foundation.

   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., 675 Mass Ave, Cambridge MA 02139, USA.

   This program is based solely to publicly avaiable databook 
   information about philips chipset.

*/
#include "sys/types.h"
#include "stdio.h"
#include <sys/mman.h>
#include <fcntl.h>

/* x must be signed for the following to work correctly */
#define limit(x) (((x>0xffffff)?0xff0000:((x<=0xffff)?0:x&0xff0000))>>16)

static inline void outb(int value, int port)
{
  __asm__ volatile ("outb %0,%1"
  : : "a"  ((unsigned char)value), "d" ((unsigned short)port));
}

static inline void outw(unsigned short value, int port)
{
  __asm__ volatile ("outw %0,%1"
  : : "a"  ((unsigned short)value), "d" ((unsigned short)port));
}

static inline int inb(int port)
{
  unsigned char value;
  __asm__ volatile ("inb %1,%0"
          : "=a" (value)
          : "d" ((unsigned short)port));
  return value;
}

#define MONITOR_PORT (0x278 | 0x400)   /* CENTRONIX PORT for init */
#define IOBASE        0x718
#define UIO_DIR       3
#define UIO_DATA      4
#define SCL_H         4
#define SCL_OUT       4
#define SDA_H         8
#define SDA_OUT       8
#define SCL           0
#define SDA           1
#define LOW           0
#define TRISTATE      1
#define REPEAT        10

char init_veda[] = { /* initialization sequence for VEDA2 SAA7165 */
  0xbe, /* I2C address */
  0x01, /* subaddress */
  0x00,
  0x80, /* 422 input */
  0x01  /* Polarity of colour diference is inverted */
};

char init_4680[] = { /* Initialization for TDA4686 */
  0x88, /* I2C address */
  0x00, /* subaddress */
  0x23, /* 00 Brightness */
  0x18, /* 01 Saturation */
  0x2c, /* 02 Contrast */
  0x1f, /* 03 Hue Controll voltage */
  0x1c, /* 04 Red gain */
  0x1c, /* 05 Green gain */
  0x1c, /* 06 Blue gain */
  0x20, /* 07 Red level reference ( RESERVED in TDA4686 )*/
  0x20, /* 08 Green level reference ( RESERVED in TDA4686 )*/
  0x20, /* 09 Blue level reference ( RESERVED in TDA4686 )*/
  0x30, /* 0a Peak drive limit */
  0xc1, /* 0b ( RESERVED in TDA4686 )*/
  0x80, /* 0c Controll register 1 */
  0x10, /* 0d Controll register 2 */
  0x00
};

char init_ocf1[] = { /* Init fot 7110 OCF */
  0x9c,  /* I2C address */
  0x00,  /* subaddress */
  0x4c,  /* 00 Increment delay */
  0x3c,  /* 01 Begin of HSY ( 50Hz )*/
  0x0d,  /* 02 End HSY ( 50Hz )*/
  0xef,  /* 03 Begin of HCL ( 50Hz ) */
  0xbd,  /* 04 End of HCL (50Hz ) */
  0xf0,  /* 05 Horizontal Sync after PHI ( 50 Hz) */
  0x00,  /* 06 Luminance Controll */
  0x00,  /* 07 Hue Controll */
  0xf8,  /* 08 QUAM Color killer thresold */
  0xf8,  /* 09 Secam Color killer thresold */
  0x60,  /* 0a PAL switch sensitivity */
  0x60,  /* 0b SECAM switch sensitivity */
  0x00,  /* 0c AGC loop time constant */
  0x06,  /* 0d Stantard / Mode controll */
  0x18,  /* 0e I/O and clock controll */
  0x90,  /* 0f controll 1 */
  0x00,  /* 10 controll 2 */
  0x2c,  /* 11 Chroma gain reference */
  0x40,  /* 12 Chroma  saturation */
  0x46,  /* 13 Luminance contrast */
  0x42,  /* 14  */
  0x1a,  /* 15  */
  0xff,  /* 16  */ 
  0xda,  /* 17  */
  0xf0,  /* 18  */
  0x8b,  /* 19  */
  0x00,  /* 1a  */
  0x00,  /* 1b  */
  0x00,  /* 1c  */
  0x00,  /* 1d  */
  0x00,  /* 1e  */
  0x00,  /* 1f  */
  0x18,  /* 20  Analog controll 1*/
  0x00,  /* 21  Analog controll 2*/
  0x40,  /* 22  Mix Controll 1*/
  0x41,  /* 23  */
  0x80,  /* 24  */
  0x41,  /* 25  */
  0x80,  /* 26  */
  0x4f,  /* 27  */
  0xfe,  /* 28  */
  0x01,  /* 29  */
  0xcf,  /* 2a  */
  0x0f,  /* 2b  */
  0x03,  /* 2c  */
  0x01,  /* 2d  */
  0x81,  /* 2e  */
  0x03,  /* 2f  */
  0x44,  /* 30  */
  0x75,  /* 31  */
  0x01,  /* 32  */
  0x8c,  /* 33  */
  0x03   /* 34  */
};
#ifdef OLD_OCF1_TABLE
char init_ocf1[] = { /* Init fot 7110 OCF */
  0x9c,  /* I2C address */
  0x00,  /* subaddress */
  0x4c,  /* 00 Increment delay */
  0x3c,  /* 01 Begin of HSY ( 50Hz )*/
  0x0d,  /* 02 End HSY ( 50Hz )*/
  0xef,  /* 03 Begin of HCL ( 50Hz ) */
  0xbd,  /* 04 End of HCL (50Hz ) */
  0xf0,  /* 05 Horizontal Sync after PHI ( 50 Hz) */
  0x01,  /* 06 Luminance Controll */
  0x02,  /* 07 Hue Controll */
  0xf8,  /* 08 QUAM Color killer thresold */
  0xf8,  /* 09 Secam Color killer thresold */
  0x90,  /* 0a PAL switch sensitivity */
  0x90,  /* 0b SECAM switch sensitivity */
  0x00,  /* 0c AGC loop time constant */
  0x86,  /* 0d Stantard / Mode controll */
  0x18,  /* 0e I/O and clock controll */
  0xb0,  /* 0f controll 1 */
  0x00,  /* 10 controll 2 */
  0x59,  /* 11 Chroma gain reference */
  0x40,  /* 12 Chroma  saturation */
  0x46,  /* 13 Luminance contrast */
  0x42,  /* 14  */
  0x1a,  /* 15  */
  0xff,  /* 16  */ 
  0xda,  /* 17  */
  0xf0,  /* 18  */
  0x8b,  /* 19  */
  0x00,  /* 1a  */
  0x00,  /* 1b  */
  0x00,  /* 1c  */
  0x00,  /* 1d  */
  0x00,  /* 1e  */
  0x00,  /* 1f  */
  0xd9,  /* 20  Analog controll 1*/
  0x16,  /* 21  Analog controll 2*/
  0x40,  /* 22  Mix Controll 1*/
  0x41,  /* 23  */
  0x80,  /* 24  */
  0x41,  /* 25  */
  0x80,  /* 26  */
  0x4f,  /* 27  */
  0xfe,  /* 28  */
  0x01,  /* 29  */
  0xcf,  /* 2a  */
  0x0f,  /* 2b  */
  0x03,  /* 2c  */
  0x01,  /* 2d  */
  0x9a,  /* 2e  */
  0x03,  /* 2f  */
  0x44,  /* 30  */
  0x75,  /* 31  */
  0x02,  /* 32  */
  0x8c,  /* 33  */
  0x03   /* 34  */
};
#endif

static int vmc_port;
unsigned char *vmem;

/*
  Init casr address. The cadr is activated wirh special write
  sequence to LP port (0x278) address 

*/


void VMC_ProgIObase(int address)
{
  int port=MONITOR_PORT;
  outb(0xcd,port);  
  outb(0x48,port);
  outb(0xea,port);
  outb(0x67,port);
  outb(0xc6,port);
  outb(0xeb,port);
  outb(address>>2,port);
};

/* Read VMC register */

int VMC_GetReg(int reg)
{
  outb(reg,vmc_port);
  return(inb(vmc_port+1));
}
int VMC_GetWord(int reg)
{
  int x;
  outb(reg,vmc_port);
  x=0xff & inb(vmc_port+1);
  outb(reg+1,vmc_port);
  x+=(0xff & inb(vmc_port+1))<<8;
  return(x);
}

void VMC_SetWord(int reg,int data)
{
  int x;
  outb(reg,vmc_port);
  outb(data & 0xff,vmc_port+1);
  outb(reg+1,vmc_port);
  outb((data>>8) & 0xff,vmc_port+1);
}

/* Set VMC register */

void VMC_SetReg(int reg,int data)
{
  outb(reg,vmc_port);
  outb(data,vmc_port+1);
}

vmc_dump()
{
  int i,x;
  printf("    0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f\n");
  for(i=0;i<256;i++) {
    if((i&15)==0)   printf("%02x  ",i);
    printf("%02x ",VMC_GetReg(i));
    if((i&15)==15)   printf("\n");
  };
  printf("\n");

};

dump_mem(unsigned long *mem,int count)
{
  int i,x;
  printf("      0 1 2 3  4 5 6 7  8 9 a b  c d e f\n");
  for(i=0;i<count;i++) {
    if((i&7)==0)   printf("%04x  ",i);
    printf("%08x ",mem[i]);
    if((i&7)==7)   printf("\n");
  };
  printf("\n");

}

void print_win_posit()
{
  int xs,xl,xz,ys,yl,yz,es,os,li;
  li=VMC_GetWord(0x63);
  xs=VMC_GetWord(0x65);
  xl=VMC_GetWord(0x67);
  xz=VMC_GetWord(0x69);
  ys=VMC_GetWord(0x6b);
  yl=VMC_GetWord(0x6d);
  yz=VMC_GetWord(0x6f);
  printf("li=%d xs=%d xl=%d xz=%d ys=%d yl=%d yz=%d\n",li,xs,xl,xz,ys,yl,yz);
  li=VMC_GetWord(0x83);
  xs=VMC_GetWord(0x85);
  xl=VMC_GetWord(0x87);
  xz=VMC_GetWord(0x89);
  ys=VMC_GetWord(0x8b);
  yl=VMC_GetWord(0x8d);
  yz=VMC_GetWord(0x8f);
  printf("li=%d xs=%d xl=%d xz=%d ys=%d yl=%d yz=%d\n",li,xs,xl,xz,ys,yl,yz);
  os=VMC_GetWord(0xa0);
  es=VMC_GetWord(0xa2);
  li=VMC_GetWord(0xa4);
  xs=VMC_GetWord(0xa6);
  xl=VMC_GetWord(0xa8);
  xz=VMC_GetWord(0xaa);
  ys=VMC_GetWord(0xac);
  yl=VMC_GetWord(0xae);
  yz=VMC_GetWord(0xb0);
  printf("os=%d es=%d li=%d xs=%d xl=%d xz=%d ys=%d yl=%d yz=%d\n",
	 os,es,li,xs,xl,xz,ys,yl,yz);



};

vmc_init()
{
  VMC_SetReg(0,0x59);   /* Misc modes */
  VMC_SetReg(3,0x10);   /* I2C direction */
  VMC_SetReg(4,0x0c);   /* I2C data */
  VMC_SetReg(5,0x00);   /* Video int en */
  VMC_SetReg(8,0xff);   /* Video VRAM write mask */
  VMC_SetReg(9,0xff);   /*  */
  VMC_SetReg(0xa,0xff);   /*  */
  VMC_SetReg(0xb,0xff);   /* CPU VRAM write mask */
  VMC_SetReg(0xc,0xff);   /*  */
  VMC_SetReg(0xd,0xff);   /*  */

  VMC_SetReg(0x10,0x3d);   /*  */
  VMC_SetReg(0x11,0x00);   /*  */
  VMC_SetReg(0x12,0x14);   /*  */
  VMC_SetReg(0x13,0x00);   /*  */
  VMC_SetReg(0x14,0x00);   /*  */
  VMC_SetReg(0x17,0);      /* 16Kbyte UMA bank */
  VMC_SetReg(0x18,21);     /* at d4000 */
  VMC_SetReg(0x19,0x00);   /* Memory bank for UMA paging */

  VMC_SetReg(0x26,0x71);   /* Chroma key settings */
  VMC_SetReg(0x2a,0x01);   /* VLUT bypass and test modes */
  VMC_SetReg(0x2b,0x04);   /* Filtering modes */
  VMC_SetReg(0x2c,0x01);   /* Matrix modes */

  VMC_SetReg(0x2d,0x28);   /* Reformatter mode  */
  VMC_SetReg(0x2e,0x39);   /* Reformatter mode  */
  VMC_SetReg(0x2f,0x00);   /* FIFO modes */

  VMC_SetReg(0x30,0x84);   /* Modes for video accusition */
  VMC_SetReg(0x31,0x00);   /* Modes for display */
  VMC_SetWord(0x32,0x2e);  /* Horizontal offset */
  VMC_SetWord(0x34,0x21);  /* Vertical offset */

  VMC_SetReg(0x42,0x20);   /* Mode controll for color keying */
  VMC_SetReg(0x43,0x02);   /* HREFOUT delay */
  VMC_SetReg(0x44,0x89);   /* VIDEOSELECT delay */
  VMC_SetReg(0x45,0xf9);   /* CHROMAIN delay */
  VMC_SetReg(0x46,0x44);   /* zooming delay */
  VMC_SetReg(0x47,0xff);   /* Chroma keying mask */
  VMC_SetReg(0x48,0xff);   /* HiColour keying mask */
  VMC_SetReg(0x49,0x00);   /* Compare value for Colour keying */
  VMC_SetReg(0x4A,0x00);   /* Compare value for HiColour keying */

  VMC_SetReg(0x60,0x00);   /* Start video accusition address */
  VMC_SetReg(0x61,0x00);   /*  */
  VMC_SetReg(0x62,0x00);   /*  */
  VMC_SetWord(0x63,44);   /* Odd Line increment */
  VMC_SetWord(0x65,0);   /* Odd X start */
  VMC_SetWord(0x67,704); /* Odd X len */
  VMC_SetWord(0x69,456); /* Odd X scale */
  VMC_SetWord(0x6b,0);   /* Odd Y start */
  VMC_SetWord(0x6d,286); /* Odd Y len */
  VMC_SetWord(0x6f,0);   /* Odd Y scale */

  VMC_SetReg(0x60,0x00);   /* Start video accusition address */
  VMC_SetReg(0x61,0x00);   /*  */
  VMC_SetReg(0x62,0x00);   /*  */
  VMC_SetWord(0x83,44);    /* Even Line increment */
  VMC_SetWord(0x85,0);     /* Even X start */
  VMC_SetWord(0x87,704);   /* Even X len */
  VMC_SetWord(0x89,456);   /* Even X scale */
  VMC_SetWord(0x8b,0);     /* Even Y start */
  VMC_SetWord(0x8d,286);   /* Even Y len */
  VMC_SetWord(0x8f,0);     /* Even Y scale */

  VMC_SetWord(0xa0,0);     /* Start Odd display */
  VMC_SetWord(0xa2,0);     /* Start Even display */
  VMC_SetWord(0xa4,0x2c);  /* Line address increment */
  VMC_SetWord(0xa6,0x12c); /* X-start  */
  VMC_SetWord(0xa8,0x190); /* X-Len    */
  VMC_SetWord(0xaa,0x00);  /* X-Zoom   */
  VMC_SetWord(0xac,0x00);  /* Y-start */
  VMC_SetWord(0xae,0x146); /* Y-Len    */
  VMC_SetWord(0xb0,0x7f);  /* Y-Zoom   */

  VMC_SetWord(0xe0,0x009e); /* Pixel clock divisor for PLL   */
  VMC_SetWord(0xe2,0x0);    /* Start window for field detection   */
  VMC_SetWord(0xe4,0x0);    /* End window for field detection   */
  VMC_SetWord(0xe6,0x1);    /* HSOUT phase   */
  VMC_SetReg(0xe8,0x02);    /* Polarity of the sync */

  VMC_I2CsendSeq(sizeof(init_veda),init_veda);
  VMC_I2CsendSeq(sizeof(init_4680),init_4680);

  VMC_I2CsendSeq(sizeof(init_ocf1),init_ocf1);
}


/* 
    Initialize VMC Userio 2 and 3 as I2C bus


*/
void VMC_I2Cinit()
{
  int i,regval;
  regval=VMC_GetReg(UIO_DIR);
  
  for(i=0;i<REPEAT;i++)
    VMC_SetReg(UIO_DIR,regval & ~SCL_OUT & ~SDA_OUT);

  regval=VMC_GetReg(UIO_DATA);
  
  for(i=0;i<REPEAT;i++)
    VMC_SetReg(UIO_DATA,regval & ~SCL_H & ~SDA_H);
}

void VMC_I2CsetLine(int line,int state)
{
  int uio_dir,line_out,i;
  
  line_out=(line==SCL) ? SCL_OUT : SDA_OUT;
  uio_dir=VMC_GetReg(UIO_DIR);
  if(state==TRISTATE) /* Switsh IO port to input */
    {
      for(i=0;i<REPEAT;i++)
	VMC_SetReg(UIO_DIR,uio_dir & ~line_out);
      return;
    }
  /* Switch port to output */
  for(i=0;i<REPEAT;i++) 
    VMC_SetReg(UIO_DIR,uio_dir | line_out);
  return;
}

void VMC_I2Cstart()
{
  VMC_I2CsetLine(SDA,TRISTATE);
  VMC_I2CsetLine(SCL,TRISTATE); 
  VMC_I2CsetLine(SDA,LOW);
  VMC_I2CsetLine(SCL,LOW);
}

void VMC_I2Cstop()
{
  VMC_I2CsetLine(SDA,LOW);
  VMC_I2CsetLine(SCL,TRISTATE);
  VMC_I2CsetLine(SDA,TRISTATE);
}

int VMC_I2CgetAck()
{
  int uio_dir,uio_data;
  VMC_I2CsetLine(SDA,TRISTATE);
  VMC_I2CsetLine(SCL,TRISTATE);
  uio_data=VMC_GetReg(UIO_DATA);
  VMC_I2CsetLine(SCL,LOW);
  return(uio_data & SDA_H);
}

int VMC_I2CwriteByte(int data)
{
  int i;
  for(i=0;i<8;i++) {
    VMC_I2CsetLine(SDA,(data & 0x80) ? TRISTATE : LOW);
    VMC_I2CsetLine(SCL,TRISTATE);
    VMC_I2CsetLine(SCL,LOW);
    data<<=1;
  };
  return(VMC_I2CgetAck());
};

int VMC_I2CreadByte()
{
  int i,uio_data,data;
  data=0;
    VMC_I2CsetLine(SDA,TRISTATE);
  for(i=0;i<8;i++) {
    VMC_I2CsetLine(SCL,TRISTATE);
    uio_data=VMC_GetReg(UIO_DATA) & SDA_H;
    printf("%d",uio_data);
    VMC_I2CsetLine(SCL,LOW);
    data<<=1;
    data=data | (uio_data ?1:0);
  };
  printf("\n");
  return(data);
};
/*

  Send byte string to I2C target 

*/

int VMC_I2CsendSeq(int numbyte,unsigned char *seq)
{
  int i;
  int i2cadr=*seq;
  VMC_I2Cinit();
  VMC_I2Cstart();
  for(i=0;i<10000;i++);
  VMC_I2Cstop();
  for(i=0;i<10000;i++);
  VMC_I2Cstart();
  while(numbyte-->0) {
    if(VMC_I2CwriteByte(*seq)) {
      printf("ack error in transmitting %02x to I2C address %02x\n",*seq,i2cadr);
      return(1);
    };
    seq++;
  };
  VMC_I2Cstop();
  return(0);  
};

/*

  Read byte fron I2C target 

*/
int VMC_I2Cread(int addr,int sub)
{
  int i;
  VMC_I2Cinit();
  VMC_I2Cstart();
  for(i=0;i<10000;i++);
  VMC_I2Cstop();
  for(i=0;i<10000;i++);
  VMC_I2Cstart();
  if(VMC_I2CwriteByte(addr & 0xfe)) {
    printf("ack error in transmitting addr %02x I2C\n",addr &0xfe);
  /*  return(-1);*/
  };
  if(VMC_I2CwriteByte(sub)) {
    printf("ack error in transmitting addr %02x I2C\n",sub);
  /*  return(-1);*/
  };
  VMC_I2Cstart();
  if(VMC_I2CwriteByte(addr | 0x01)) {
    printf("ack error in transmitting addr %02x I2C\n",addr | 1);
  /*  return(-1);*/
  };
  i=VMC_I2CreadByte();
  VMC_I2Cstop();
  return(i);
}
/*

  Read byte fron I2C target 

*/
int VMC_I2Cdump(int addr,int sub)
{
  int i,x;
  VMC_I2Cinit();
  VMC_I2Cstart();
  for(i=0;i<10000;i++);
  VMC_I2Cstop();
  for(i=0;i<10000;i++);
  VMC_I2Cstart();
  if(VMC_I2CwriteByte(addr | 0x01)) {
    printf("ack error in transmitting addr %02x I2C\n",addr | 1);
  /*  return(-1);*/
  };
  for(i=0;i<sub;i++) {
    x=VMC_I2CreadByte();
    printf("%02x ",x);
    VMC_I2CsetLine(SDA,LOW);
    VMC_I2CsetLine(SCL,TRISTATE);
    VMC_I2CsetLine(SCL,LOW);
  };
  printf("\n");
  VMC_I2Cstop();
  return(i);
}
/*

  Read byte fron I2C target 

*/
int VMC_I2Cwrite(int addr,int sub,int data)
{
  int i;
  VMC_I2Cinit();
  VMC_I2Cstart();
  for(i=0;i<10000;i++);
  VMC_I2Cstop();
  for(i=0;i<10000;i++);
  VMC_I2Cstart();
  if(VMC_I2CwriteByte(addr)) {
    printf("ack error in transmitting addr %02x I2C\n",addr);
  /*  return(-1);*/
  };
  if(VMC_I2CwriteByte(sub)) {
    printf("ack error in transmitting addr %02x I2C\n",sub);
  /*  return(-1);*/
  };
  if(VMC_I2CwriteByte(data)) {
    printf("ack error in transmitting data %02x I2C\n",data);
  /*  return(-1);*/
  };
  VMC_I2Cstop();
  return(i);
}

/* ====================================

  Freeze picture 

=====================================*/
vmc_freeze()
{
  VMC_SetReg(0x30,0x0);


}
vmc_unfreeze()
{
  VMC_SetReg(0x30,0x84);


}
/*
  Set position of the video window on screen 

*/
vmc_setposit(int x,int y)
{
  VMC_SetWord(0xa6,x);
  VMC_SetWord(0xac,y);
}
/*
  Set size of the video window on screen 

*/
vmc_setsize(int x,int y)
{
  VMC_SetWord(0xa8,x);
  VMC_SetWord(0xae,y);
}

void select_input(int ch)
{
  if(ch==1) {
    VMC_I2Cwrite(0x9c,0x20,0x18);
    VMC_I2Cwrite(0x9c,0x22,0x40);
    VMC_I2Cwrite(0x9c,0x30,0x44);
  };
  if(ch==2) {
    VMC_I2Cwrite(0x9c,0x20,0xb8);
    VMC_I2Cwrite(0x9c,0x22,0x91);
    VMC_I2Cwrite(0x9c,0x30,0x60);
  }



}
 

void init7195()
{
  int mem,i,c,n,x,y,j,bank;
  unsigned short *p;

  if (iopl(3) != 0){
    perror("can't open ports.\n");
    exit(-1);
  }
  if ((mem = open("/dev/mem", O_RDWR)) < 0){
    perror("can't open /dev/mem.\n");
    exit(-1);
  }
  vmem = mmap(
    (caddr_t) (0x00d4000),   /* memoryaddress         */
    0x004000,                            /* size                  */
    PROT_READ|PROT_WRITE,                  /* allow read and write  */
    MAP_SHARED|MAP_FIXED,                  /* fix memory to address */
    mem,
    (0x00d4000)              /* same as first param.  */
  );
  if (vmem <=0){
    perror("can't access memory.\n");
    exit(-1);
  }
  printf("vmem=%08x\n",vmem);

  VMC_ProgIObase(IOBASE);
  vmc_port=IOBASE;
  VMC_SetReg(0x17,0);  /* 16Kbyte UMA bank */
  VMC_SetReg(0x18,21); /* at d4000 */
  VMC_SetReg(0x2d,0x28); /* Reformatter mode  */
  VMC_SetReg(0x2e,0x39); /* Reformatter mode  */
  VMC_SetReg(0x47,0xff);   /* Chroma keying mask */
  VMC_SetReg(0x48,0xff);   /* HiColour keying mask */
  VMC_SetReg(0x49,0x00);   /* Compare value for Colour keying */
  VMC_SetReg(0x4A,0x00);   /* Compare value for HiColour keying */

}

