/*
 * OmniVision ov5017 CMOS-chip driver  
 *
 * (c) 2001 Axel Burri <aburri@ee.ethz.ch>
 *
 * 
 * Note: "vis" stands for "Video-Image-Sensor"
 *
 * v0.01: - register r/w (using PIO) works
 * v0.02: - dma read works
 * v0.03: - changed data bits from 15..8 to 7..0
 * v0.1 : - multiple access implemented, stable
 * v0.2 : - direct access to memory implemented
 *          (WARNING: this is a hack and works only because the ETRAX100
 *          does not have a MMU !!!)
 *
 * TODO : - real mmap() functions
 *        - different minor numbers for differnt file formats
 *          (e.g. 0=raw data, 1=tiff, 2=jpeg etc.)
 */

#define VIS_VERSION		"0.2"

#define VIS_DEBUG 
#undef  VIS_DEBUG
#define VIS_LOWDEBUG 
#undef  VIS_LOWDEBUG 


#include <linux/errno.h>
#include <linux/malloc.h>

#include <asm/io.h>
#include <asm/irq.h>
#include <asm/svinto.h>

#include "etrax100vis.h"


#define VIS_ATA_IRQ 4    /* (ATA-irq on ETRAX) */
#define VIS_DMA3_IRQ 19  /* (DMA3-irq on ETRAX) */


struct vis_dev {
  int usage;
  void *img_buf;               /* image buffer starts here */
  unsigned char *tiff_img_buf; /* tiff image buffer */
  struct wait_queue *wait_q;
  etrax_dma_descr ata_dma_descr[2];
};
static struct vis_dev vis_devices[CONFIG_ETRAX100_OV5017_MAX_READER];



/*
 * A reader in need of a new image is enqueued to the request-queue.
 * On next ata_intr (VSYNC) the next reader on this queue gets the new image.
 */
struct img_request_queue {
  struct vis_dev *dev;
  struct img_request_queue *next;
};
static struct img_request_queue *img_request_q;



/*
 * state: Current state of the driver.
 * This is used in vis_dma_intr to determine if image is ready or 
 * if second part has to be read.
 */
static int state;
#define STATE_IDLE 0
#define STATE_DMA_READ_FIRST 1
#define STATE_DMA_READ_SECOND 2


/*
 * The TIFF header and trailer
 */
static const unsigned short tiff_head[] = 
{18761,   42,   45352,   1};
static const unsigned short tiff_tail[] = {
  17,  254,  4,  1,  0,  0,  0,  256,
  3,  1,  0,  385,  0,  257,  3,  1,
  0,  288,  0,  258,  3,  1,  0,  8,
  0,  259,  3,  1,  0,  1,  0,  262,
  3,  1,  0,  1,  0,  269,  2,  23,
  0,  45562,  1,  270,  2,  22,  0,  45586,
  1,  273,  4,  5,  0,  45608,  1,  274,
  3,  1,  0,  1,  0,  277,  3,  1,
  0,  1,  0,  278,  3,  1,  0,  64,
  0,  279,  4,  5,  0,  45628,  1,  282,
  5,  1,  0,  45648,  1,  283,  5,  1,
  0,  45656,  1,  284,  3,  1,  0,  1,
  0,  296,  3,  1,  0,  2,  0,  0,
  0,  26671,  28015,  12133,  25185,  29743,  29541,  12148,
  25972,  29811,  29742,  26217,  0,  29251,  24933,  25972,
  8292,  26999,  26740,  18464,  28793,  29285,  24899,  109,
  8,  0,  24648,  0,  49288,  0,  8392,  1,
  33032,  1,  24640,  0,  24640,  0,  24640,  0,
  24640,  0,  12320,  0,  0,  18432,  0,  256,
  0,  18432,  0,  256
};


/*
 * enqueue a reader to the request-queue
 */
static void vis_enqueue_reader(struct vis_dev *dev) {
  struct img_request_queue *p;
  struct img_request_queue *q = NULL;
  struct img_request_queue *n;    
  unsigned long flags;

  n = (struct img_request_queue *) kmalloc(sizeof(struct img_request_queue), GFP_ATOMIC);
  if(n == NULL) {
    printk("vis_enqueue_reader: kmalloc error\n");
  }
  else {
    n->dev = dev;
    n->next = NULL;
	
    save_flags(flags); cli(); /* do not disturb! */
    p = img_request_q;
    while(p != NULL) {
      q = p;
      p = p->next;
    }

    if(q == NULL) /* img_request_q == NULL */
      img_request_q = n;
    else
      q->next = p;
    restore_flags(flags);
  }
  /*      *R_IRQ_MASK0_SET = IO_STATE( R_IRQ_MASK0_SET, ata_irq2, set ); */
}



/*
 * dequeue a reader from the request-queue
 */
static struct img_request_queue * vis_dequeue_reader() {
  struct img_request_queue *q = img_request_q;

  /* since this is used in interrupt handler only, there is no need for cli();sti(); */
  img_request_q = img_request_q->next;
  return q;
}



/*
 * The video data is read in this function (using ATA-DMA)
 */
inline void vis_dma_read(etrax_dma_descr *dma_descr, int count) {
  unsigned long status;

#ifdef VIS_LOWDEBUG
  printk("vis_dma_read: state %i\n", state);
#endif

  /* make sure the DMA channel is available */
  RESET_DMA(3);
  WAIT_DMA(3); 
  /* 
   * DMA write to buffer (specified in dma_descr)
   */

  /* start the dma channel */
  *R_DMA_CH3_FIRST = (unsigned long)dma_descr;
  *R_DMA_CH3_CMD = IO_STATE(R_DMA_CH3_CMD, cmd, start);

  *R_ATA_TRANSFER_CNT = count;  

  /* initiate a multi word dma read using DMA handshaking */
  *R_ATA_CTRL_DATA = 
    IO_FIELD(R_ATA_CTRL_DATA, sel,      2        ) | /* ATA bus 2 */
    IO_STATE(R_ATA_CTRL_DATA, cs1,      active   ) | 
    IO_STATE(R_ATA_CTRL_DATA, cs0,      active   ) | 
    IO_STATE(R_ATA_CTRL_DATA, rw,       read     ) |
    IO_STATE(R_ATA_CTRL_DATA, src_dst,  dma      ) |
    IO_STATE(R_ATA_CTRL_DATA, handsh,   dma      ) |
    IO_STATE(R_ATA_CTRL_DATA, multi,    on       ) |
    IO_STATE(R_ATA_CTRL_DATA, dma_size, byte     );

#ifdef VIS_LOWDEBUG
  printk("vis_dma_read: read complete\n");
#endif

}



/*
 * single byte transfer from ov5017 register
 */
static unsigned char vis_pio_read(unsigned char reg) {
  int status;

  /* make sure the DMA channel is available */
  RESET_DMA(3);
  WAIT_DMA(3); 

  /* invert address (for use on the devboard, it's inverted there) */
  reg = ~reg & 0x7;
	

  /* wait for busy flag to clear */
  while(*R_ATA_STATUS_DATA & IO_MASK(R_ATA_STATUS_DATA, busy));
    

  /* 
   * initiate PIO single byte read (initiated when register is written)
   */
  *R_ATA_CTRL_DATA = (reg << 25) | 
    IO_FIELD(R_ATA_CTRL_DATA, sel,      2        ) | /* ATA bus 2 */
    IO_STATE(R_ATA_CTRL_DATA, cs1,      active   ) | 
    IO_STATE(R_ATA_CTRL_DATA, cs0,      inactive ) | 
    IO_STATE(R_ATA_CTRL_DATA, rw,       read     ) | 
    IO_STATE(R_ATA_CTRL_DATA, src_dst,  register ) | /* output to R_ATA_STATUS_DATA */
    IO_STATE(R_ATA_CTRL_DATA, handsh,   pio      ) | 
    IO_STATE(R_ATA_CTRL_DATA, multi,    off      ) | 
    IO_STATE(R_ATA_CTRL_DATA, dma_size, byte     );
 
  /* wait for busy flag to clear */
  while(*R_ATA_STATUS_DATA & IO_MASK(R_ATA_STATUS_DATA, busy));

  /* wait for dav (data available) and read the value from R_ATA_STATUS_DATA */
  while(!((status = *R_ATA_STATUS_DATA) & IO_MASK(R_ATA_STATUS_DATA, dav)));

#ifdef VIS_DEBUG
  printk("vis_pio_read: 0x%x from reg 0x%x\n", status, ~reg & 0x7);
#endif
  return (unsigned char)(status & 0xff) ; /* return bits 0..7 of R_ATA_STATUS_DATA */
}



/*
 * single byte transfer to ov5017 register
 */
static void vis_pio_write(unsigned char reg, unsigned char data) {
  int status;

#ifdef VIS_DEBUG
  printk("vis_pio_write: reg 0x%x, data 0x%x\n", reg & 0x7, data);
#endif

  /* make sure the DMA channel is available */
  RESET_DMA(2);
  WAIT_DMA(2); 

  /* invert address (for use on the devboard, it's inverted there) */
  reg = ~reg & 0x7;

  /* 
   * initiate PIO single byte read (initiated when register is written)
   */
  *R_ATA_CTRL_DATA = (reg << 25) | (data) |
    IO_FIELD(R_ATA_CTRL_DATA, sel, 2)            | /* ATA bus 2 */
    IO_STATE(R_ATA_CTRL_DATA, cs1, inactive)     | /* cs1 inactive */
    IO_STATE(R_ATA_CTRL_DATA, cs0, active)       | /* cs0 active */
    IO_STATE(R_ATA_CTRL_DATA, rw, write)         | /* write data */
    IO_STATE(R_ATA_CTRL_DATA, src_dst, register) | /* output to R_ATA_STATUS_DATA */
    IO_STATE(R_ATA_CTRL_DATA, handsh, pio)       | /* PIO mode */
    IO_STATE(R_ATA_CTRL_DATA, multi, off)        | /* stop after this transfer */
    IO_STATE(R_ATA_CTRL_DATA, dma_size, byte);     /* 8 bit transfer */

  /* wait for transmitter ready */
  while(!(*R_ATA_STATUS_DATA & IO_MASK(R_ATA_STATUS_DATA, tr_rdy)));
}



/*
 * The ATA interrupt handler.
 * Called on every VSYNC of the image.
 * Image is updated for the first item in the request-queue .
 */
void vis_ata_intr (int irq, void *dev_id, struct pt_regs *regs) {
#ifdef VIS_LOWDEBUG
  printk("intr\n");
  /*      printk("vis_ata_intr: jiffies %i\n", jiffies); */
#endif
  if (state == STATE_IDLE) {
    if (img_request_q != NULL) {
      /* start reading the image here */
      state = STATE_DMA_READ_FIRST;
      vis_dma_read(&(img_request_q->dev->ata_dma_descr[0]), 65536);
    }
  }
  else {
  }
}



/*
 * Called when a DMA-interrupt occurs.
 * This happens when a DMA transfer is finished and is used:
 * 1) to initiate the second DMA-transfer if state=STATE_DMA_READ_FIRST and
 * 2) to dequeue the reader and wake him up if state=STATE_DMA_READ_SECOND.
 */
void vis_dma_intr (int irq, void *dev_id, struct pt_regs *regs) {
#ifdef VIS_LOWDEBUG
  printk("vis_dma_intr\n");
#endif
  /*      if (*R_IRQ_MASK2_RD & IO_MASK( R_IRQ_MASK2_RD, dma3_eop)) { */
  *R_DMA_CH3_CLR_INTR = IO_STATE( R_DMA_CH3_CLR_INTR, clr_descr, do );  
  if(state == STATE_DMA_READ_FIRST) {
    *R_ATA_TRANSFER_CNT = 65536;
    state = STATE_DMA_READ_SECOND;
  }
  else if(state == STATE_DMA_READ_SECOND) {
    /* image ready, wake up waiting process */
    wake_up_interruptible(&(img_request_q->dev->wait_q)); 
    /* process with next reader in img_request_q (if any)*/
    kfree(vis_dequeue_reader());
    state = STATE_IDLE;
  }
}



/*
 * general purpose test routine
 */
static int vis_test(unsigned long arg) {
#ifdef VIS_DEBUG
  printk("vis_test called\n");
#endif
    
#if 0
  *R_ATA_CONFIG = ( IO_FIELD( R_ATA_CONFIG, enable,     1 ) |
		    IO_FIELD( R_ATA_CONFIG, dma_strobe,  arg & 0xff) |
		    IO_FIELD( R_ATA_CONFIG, dma_hold,    CONFIG_ETRAX100_OV5017_ATA_DMA_HOLD) |
		    IO_FIELD( R_ATA_CONFIG, pio_setup,   CONFIG_ETRAX100_OV5017_ATA_PIO_SETUP) |
		    IO_FIELD( R_ATA_CONFIG, pio_strobe,  CONFIG_ETRAX100_OV5017_ATA_PIO_STROBE) |
		    IO_FIELD( R_ATA_CONFIG, pio_hold,    CONFIG_ETRAX100_OV5017_ATA_PIO_HOLD) );
#endif
  return 0;
}



/*
 * ioctl() system call handler
 */
static int vis_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) {
  struct vis_dev *dev;
#ifdef VIS_DEBUG
  printk("vis_ioctl called\n");
#endif

  /*  don't decode wrong commands */
  if(_IOC_TYPE(cmd) != VIS_IOC_MAGIC) return -EINVAL;
  if(_IOC_NR(cmd) > VIS_IOC_MAXNR) return -EINVAL;

  switch(cmd) {
  case VIS_IOC_TEST:
    return vis_test(arg);
  case VIS_IOC_GET_IMAGE:
    dev = (struct vis_dev *)filp->private_data;
    vis_enqueue_reader(dev);
    interruptible_sleep_on(&(dev->wait_q));
    memcpy_tofs((void *)arg, dev->img_buf, VIS_IMAGESIZE);
    return 0;
  case VIS_IOC_GET_BASE_ADR:
    /* (WARNING: this is a hack and works only because the ETRAX100
     * does not have a MMU !!!) */
    dev = (struct vis_dev *)filp->private_data;
    return (int)dev->img_buf;
  case VIS_IOC_UPDATE_IMAGE:
    dev = (struct vis_dev *)filp->private_data;
    vis_enqueue_reader(dev);
    interruptible_sleep_on(&(dev->wait_q));
    return 0;
  case VIS_IOC_REGISTER_READ:
    return (int)vis_pio_read((unsigned char)arg);
  case VIS_IOC_REGISTER_WRITE:
    vis_pio_write((unsigned char)(arg >> 16), (unsigned char)arg);
    return 0;
  }

  return 0;
}


/*
 * open() system call handler
 */
static int vis_open(struct inode *inode, struct file *filp) {
  int i;
  unsigned char *buf;
  struct vis_dev *dev;
  unsigned long flags;
#ifdef VIS_DEBUG
  printk("vis_open called\n");
#endif

  save_flags(flags); cli(); /* do not disturb! */

  /* get a free vis_device */
  i = 0;
  while((i < CONFIG_ETRAX100_OV5017_MAX_READER) && (vis_devices[i].usage)) 
    i++;

  if (i == CONFIG_ETRAX100_OV5017_MAX_READER) { /* all devices used */
    restore_flags(flags);
    printk("vis_open: No more readers allowed\n");
    return -ENODEV;
  }
  dev = &vis_devices[i];
  dev->usage = 1;

  restore_flags(flags);

  /*
   * get memory and copy TIFF header and trailer
   */
  if((buf =  kmalloc(VIS_TIFF_IMAGESIZE, GFP_DMA | GFP_KERNEL)) == NULL) {
    dev->usage = 0;
    printk("vis_open: kmalloc error\n");
    return -ENODEV;
  }
  memcpy(&buf[0], (void *)tiff_head, VIS_TIFF_HEAD_SIZE);
  memcpy(&buf[VIS_TIFF_HEAD_SIZE + VIS_IMAGESIZE], (void *)tiff_tail, VIS_TIFF_TAIL_SIZE);
#ifdef VIS_DEBUG
  for (i=0; i < VIS_IMAGESIZE; i++) 
    buf[i + VIS_TIFF_HEAD_SIZE] = 0;
#endif

	
  dev->tiff_img_buf = buf;
  dev->img_buf = buf + VIS_TIFF_HEAD_SIZE;


  /* 
   * setup DMA descriptors 
   */
  dev->ata_dma_descr[0].sw_len = VIS_IMAGESIZE >> 1; 
  dev->ata_dma_descr[0].sw_len = (288 - 170) * 385; 
  dev->ata_dma_descr[0].ctrl= d_int;
  dev->ata_dma_descr[0].buf = (unsigned long)(dev->img_buf);
  dev->ata_dma_descr[0].next = (unsigned long)&(dev->ata_dma_descr[1]);
  dev->ata_dma_descr[0].hw_len = 0;
  dev->ata_dma_descr[0].status = 0;
  dev->ata_dma_descr[0].fifo_len = 0;

  dev->ata_dma_descr[1].sw_len = VIS_IMAGESIZE >> 1;
  dev->ata_dma_descr[1].sw_len = 170 * 385; 
  dev->ata_dma_descr[1].ctrl= d_eop | d_eol | d_int;
  dev->ata_dma_descr[1].buf = (unsigned long)(dev->img_buf) + (VIS_IMAGESIZE >> 1);
  dev->ata_dma_descr[1].buf = (unsigned long)(dev->img_buf) + (288 - 170) * 385;
  dev->ata_dma_descr[1].next = 0;
  dev->ata_dma_descr[1].hw_len = 0;
  dev->ata_dma_descr[1].status = 0;
  dev->ata_dma_descr[1].fifo_len = 0;

  filp->private_data = dev;
  return 0;
}



/*
 * release() system call handler
 */
static void vis_release(struct inode *inode, struct file *filp) {
  struct vis_dev *dev = filp->private_data;
#ifdef VIS_DEBUG
  printk("vis_release called\n");
#endif
  kfree(dev->tiff_img_buf);
  dev->usage = 0;
}


/* 
 * returns a TIFF image
 * Image transfer is initiated if f_pos = 0
 */
static int vis_read(struct inode *inode, struct file *filp, char *buf, int count) {
  /*    struct wait_queue wait = { current, NULL }; */
  unsigned long f_pos = (unsigned long)(filp->f_pos);
  struct vis_dev *dev = filp->private_data;
#ifdef VIS_DEBUG
  printk("vis_read: f_pos %i, count %i\n", f_pos, count);
#endif
    
  /* check size of transfer */
  if (f_pos > VIS_TIFF_IMAGESIZE) 
    return 0;
  if (f_pos + count > VIS_TIFF_IMAGESIZE) 
    count = VIS_TIFF_IMAGESIZE - f_pos;

  if (f_pos == 0) {
    /* initiate DMA transfer, sleep until image ready */
    vis_enqueue_reader(dev);
    interruptible_sleep_on(&(dev->wait_q));
  }

  /* copy buffer form kernel space to user space */  
  memcpy_tofs(buf, &(dev->tiff_img_buf[f_pos]), count);

  filp->f_pos += count;
  return count;
}



/*
 * possible file_operations
 */
static struct file_operations vis_fops = {
  NULL,           /* No lseek */
  vis_read,
  NULL,           /* No write */
  NULL,           /* No readdir */
  NULL,           /* No select */
  vis_ioctl,          
  NULL,           /* No mmap */
  vis_open,
  vis_release
};


/*
 * initialization of the OV5017 chip
 */
static int vis_ov5017_init(void) {
#ifdef VIS_DEBUG
  printk("vis_ov5017_init: setting register defaults\n");
#endif
  /* write config data to ov5017 registers */
  vis_pio_write(VIS_REG_FCTL, CONFIG_ETRAX100_OV5017_FCTL);
  vis_pio_write(VIS_REG_EXCTL, CONFIG_ETRAX100_OV5017_EXCTL);
  vis_pio_write(VIS_REG_GCTL, CONFIG_ETRAX100_OV5017_GCTL);
  vis_pio_write(VIS_REG_FRCTL, CONFIG_ETRAX100_OV5017_FRCTL);
  vis_pio_write(VIS_REG_MCTL, CONFIG_ETRAX100_OV5017_MCTL);
  vis_pio_write(VIS_REG_HWCTL, CONFIG_ETRAX100_OV5017_HWCTL);
  vis_pio_write(VIS_REG_VWCTL, CONFIG_ETRAX100_OV5017_VWCTL);
}


/*
 * initialization of the ATA-Bus
 * set interrupt handlers
 */
static int vis_ata_init(void) {
  volatile unsigned int dummy;
#ifdef VIS_DEBUG
  printk("vis_ata_init\n");
#endif

  /* setup DMA registers */
  *R_ATA_CTRL_DATA = 0;
  *R_ATA_TRANSFER_CNT = 0;
  *R_ATA_CONFIG = 0;
    
  genconfig_shadow = (genconfig_shadow & 
		      ~IO_MASK(R_GEN_CONFIG, dma2) &
		      ~IO_MASK(R_GEN_CONFIG, dma3) &
		      ~IO_MASK(R_GEN_CONFIG, ata)) | 
    ( IO_STATE( R_GEN_CONFIG, dma3, ata    ) |
      IO_STATE( R_GEN_CONFIG, dma2, ata    ) |
      IO_STATE( R_GEN_CONFIG, ata,  select ) );

  *R_GEN_CONFIG = genconfig_shadow;

  
  /* wait some */
  dummy = 1;
  dummy = 2;
  dummy = 3;

  
  /* make a dummy read to set the ata controller in a proper state */
  dummy = *R_ATA_STATUS_DATA;

  
  /* configure ata transfer times */
  *R_ATA_CONFIG = ( IO_FIELD( R_ATA_CONFIG, enable,     1 ) |
		    IO_FIELD( R_ATA_CONFIG, dma_strobe,  CONFIG_ETRAX100_OV5017_ATA_DMA_STROBE) |
		    IO_FIELD( R_ATA_CONFIG, dma_hold,    CONFIG_ETRAX100_OV5017_ATA_DMA_HOLD)   |
		    IO_FIELD( R_ATA_CONFIG, pio_setup,   CONFIG_ETRAX100_OV5017_ATA_PIO_SETUP)  |
		    IO_FIELD( R_ATA_CONFIG, pio_strobe,  CONFIG_ETRAX100_OV5017_ATA_PIO_STROBE) |
		    IO_FIELD( R_ATA_CONFIG, pio_hold,    CONFIG_ETRAX100_OV5017_ATA_PIO_HOLD) );

  while(*R_ATA_STATUS_DATA & IO_MASK(R_ATA_STATUS_DATA, busy)); /* wait for busy flag to clear */


  /* clear ata_irq2 (INTRQ2) */
  *R_IRQ_MASK0_CLR = IO_STATE( R_IRQ_MASK0_CLR, ata_irq2, clr );

  /* set interrupt handler for VIS_ATA_IRQ */
  if (request_irq(VIS_ATA_IRQ, vis_ata_intr, SA_INTERRUPT, VIS_NAME, NULL)) {
    printk("unable to assign irq %i\n", VIS_ATA_IRQ);
    panic("irq");
  }

  /* enable ata_irq2 (INTRQ2) */
  *R_IRQ_MASK0_SET = IO_STATE( R_IRQ_MASK0_SET, ata_irq2, set );



  /* clear all pending DMA interrupts */
  *R_DMA_CH3_CLR_INTR = IO_STATE( R_DMA_CH3_CLR_INTR, clr_eop,   do ) |
    IO_STATE( R_DMA_CH3_CLR_INTR, clr_descr, do ); 
  /* set interrupt handler for VIS_DMA3_IRQ */
  if (request_irq(VIS_DMA3_IRQ, vis_dma_intr, SA_INTERRUPT, VIS_NAME, NULL)) {
    printk("unable to assign irq %i\n", VIS_DMA3_IRQ);
    panic("irq");
  }
  /* enable DMA-descr-irq (descriptor insterupt) */
  *R_IRQ_MASK2_SET = IO_STATE( R_IRQ_MASK2_SET, dma3_descr, set );
#if 0
  *R_IRQ_MASK2_SET = IO_STATE( R_IRQ_MASK2_SET, dma3_eop, set );
#endif

  /* reset the dma channels we will use */
  RESET_DMA(2);
  RESET_DMA(3);
  WAIT_DMA(2);
  WAIT_DMA(3);

  return 0;
}



/*
 * initialize the driver
 * this function is called from mem.c -> chr_dev_init(void)
 */
int etrax_vis_ov5017_init(void) {
  volatile unsigned int *addr;
  unsigned int val;
  int res;
  unsigned int i;
  unsigned char *buf;
  printk("%s driver v%s (c) 2001 Axel Burri\n", VIS_NAME, VIS_VERSION);

  /*  
   * register the device 
   */
  if ((res = register_chrdev(VIS_MAJOR, VIS_NAME, &vis_fops)) < 0) {
    printk("unable to get major %d for VIS_OV5017\n", VIS_MAJOR);
    return res;
  } 

  /*  
   * init variables
   */
  img_request_q = NULL;
  state = STATE_IDLE;

  for (i = 0; i < CONFIG_ETRAX100_OV5017_MAX_READER; i++) {
    vis_devices[i].usage = 0;
    init_waitqueue(&(vis_devices[i].wait_q));
  }

  /*  
   * init ATA stuff 
   */
  if((res = vis_ata_init()) < 0) {
    printk("error initializing ata port\n");
    return res;
  };
 
  /*  
   * init ov5017 register 
   */
  if((res = vis_ov5017_init()) < 0) {
    printk("error initializing ov5017 chip\n");
    return res;
  };
  return 0;
}
