www.pudn.com > zc030x.rar > zc030x_cameras.c, change:2008-06-04,size:29843b




/* Include headers */
#include "zc030x_cameras.h"
/* Include bridge chip communication */
#include "zc030x_reg.h"
/* Include memory management */
#include "zc030x_mm.h"
/* Include gamma sequence creation */
#include "zc030x_matrix.h"

/* Include sensors declarations */
#include "sensors/CS2102.h"
#include "sensors/CS2103.h"
#include "sensors/HDCS1020.h"
#include "sensors/HDCS2020.h"
#include "sensors/HV7121B.h"
#include "sensors/HV7131B.h"
#include "sensors/ICM102A.h"
#include "sensors/ICM105A.h"
#include "sensors/OV7620.h"
#include "sensors/OVCIF.h"
#include "sensors/PAS106B.h"
#include "sensors/PAS202B.h"
#include "sensors/PB0111.h"
#include "sensors/PB0330.h"
#include "sensors/TAS5130C.h"
#include "sensors/TAS5110B.h"

/* Declare declaration macro */
#define DeclareI2CInit(Name, E1, A1, V1, A2, V2, A3, V3, A4, V4, A5, V5, A6, V6) \
    const I2CInitSequence i2c_init_##Name = { .Direction = { 1, 0, 0, 0, 0, 0 }, \
      .Address = { A1, A2, A3, A4, A5, A6 }, \
      .Value = { V1, V2, V3, V4, V5, V6 }, \
      .ReturnSize = { 1, 0, 0, 0, 0, 0 }, \
      .ReturnValue = { E1, 0, 0, 0, 0, 0 } }
      
/* Declare I2CInitSequences */
/* Look at the sniff after a plugin sequence first 6 packets */
DeclareI2CInit(WebcamNXPro    , 0x00, 0x10, 0x01, 0x00, 0x01, 0x10, 0x00, 0x01, 0x01, 0x12, 0x03, 0x12, 0x01);
DeclareI2CInit(Generic        , 0x00, 0x10, 0x01, 0x00, 0x01, 0x10, 0x00, 0x01, 0x01, 0x12, 0x03, 0x12, 0x01);
DeclareI2CInit(WebcamNX       , 0x00, 0x10, 0x01, 0x00, 0x01, 0x10, 0x0f, 0x01, 0x01, 0x12, 0x03, 0x8d, 0x08);
DeclareI2CInit(GeniusV2       , 0x00, 0x10, 0x01, 0x00, 0x01, 0x10, 0x00, 0x01, 0x01, 0x12, 0x03, 0x12, 0x01);
DeclareI2CInit(GeniusV4       , 0x00, 0x10, 0x01, 0x00, 0x01, 0x10, 0x00, 0x01, 0x01, 0x12, 0x03, 0x12, 0x01);
DeclareI2CInit(MustekW300A    , 0x00, 0x10, 0x01, 0x00, 0x01, 0x10, 0x00, 0x01, 0x01, 0x12, 0x03, 0x12, 0x01);
/* This one is different */
DeclareI2CInit(ZStarCorp      , 0x00, 0x10, 0x01, 0x00, 0x01, 0x10, 0x0c, 0x01, 0x01, 0x12, 0x03, 0x12, 0x01);
DeclareI2CInit(BenqCam        , 0x01, 0x10, 0x01, 0x00, 0x01, 0x10, 0x01, 0x01, 0x01, 0x12, 0x03, 0x12, 0x01);
DeclareI2CInit(WebcamMobile   , 0x00, 0x10, 0x01, 0x00, 0x01, 0x10, 0x00, 0x01, 0x01, 0x12, 0x03, 0x12, 0x01);
DeclareI2CInit(WebcamNotebook , 0x00, 0x10, 0x01, 0x00, 0x01, 0x10, 0x00, 0x01, 0x01, 0x12, 0x03, 0x8d, 0x04);
DeclareI2CInit(WebcamNXPro2   , 0x00, 0x10, 0x01, 0x00, 0x01, 0x10, 0x0f, 0x01, 0x01, 0x12, 0x03, 0x8d, 0x08);
DeclareI2CInit(WebcamInstant  , 0x00, 0x10, 0x01, 0x00, 0x01, 0x10, 0x0f, 0x01, 0x01, 0x12, 0x03, 0x8d, 0x08);
DeclareI2CInit(MustekW300A2   , 0x00, 0x10, 0x01, 0x00, 0x01, 0x10, 0x00, 0x01, 0x01, 0x12, 0x03, 0x12, 0x01);
DeclareI2CInit(LabtechWcamPro , 0x00, 0x10, 0x01, 0x00, 0x01, 0x10, 0x00, 0x01, 0x01, 0x12, 0x03, 0x12, 0x01);

#define MaxNbCamera (sizeof(CamList) / sizeof(CamList[0]))

/* Declare declaration macro */
#define DeclareCam(Nam, VID, PID, ID) \
    { .ProductID = PID, .VendorID = VID, .Index = ID, .Name = #Nam, .pI2CInitSeq = &i2c_init_##Nam } 
/* And the supported camera */
const CameraList CamList[] = 
{
    DeclareCam(MustekW300A    , 0x055f, 0xd003, 0),
    DeclareCam(WebcamNXPro    , 0x041e, 0x401e, 1),
    DeclareCam(WebcamNX       , 0x041e, 0x401c, 2),
    DeclareCam(GeniusV2       , 0x0458, 0x7007, 3),
    DeclareCam(BenqCam        , 0x0ac8, 0x0302, 4),
    DeclareCam(ZStarCorp      , 0x0ac8, 0x301b, 5),
    DeclareCam(Generic        , 0x0ac8, 0x0301, 6),
    DeclareCam(WebcamMobile   , 0x041e, 0x4017, 7),
    DeclareCam(WebcamNotebook , 0x041e, 0x401f, 8),
    DeclareCam(WebcamNXPro2   , 0x041e, 0x403a, 9),
    DeclareCam(GeniusV4       , 0x0458, 0x700f, 10),
    DeclareCam(WebcamInstant  , 0x041e, 0x4034, 11),
    DeclareCam(MustekW300A2   , 0x055f, 0xd005, 12),
    DeclareCam(LabtechWcamPro , 0x046d, 0x08a2, 13),
    

};


/* Declare the static usb_device_id
   Sadly, this can't be dynamic !            */
const struct usb_device_id zc030x_table[] = 
{
      {USB_DEVICE (0x055f, 0xd003)},
      {USB_DEVICE (0x041e, 0x401e)},
      {USB_DEVICE (0x041e, 0x401c)},
      {USB_DEVICE (0x0458, 0x7007)},
      {USB_DEVICE (0x0ac8, 0x0302)},
      {USB_DEVICE (0x0ac8, 0x301b)},
      {USB_DEVICE (0x0ac8, 0x0301)},
      {USB_DEVICE (0x041e, 0x4017)},
      {USB_DEVICE (0x041e, 0x401f)},
      {USB_DEVICE (0x041e, 0x403a)},
      {USB_DEVICE (0x0458, 0x700f)},
      {USB_DEVICE (0x041e, 0x4034)},
      {USB_DEVICE (0x055f, 0xd005)},
      {USB_DEVICE (0x046d, 0x08a2)},
      {}                            /* Terminating entry */
};



#define MaxNbSensor (sizeof(SensList) / sizeof(SensList[0]))

/* Declare declaration macro */
#define DeclareSensor(Nam, ID) \
    { .Index = ID, .Name = #Nam, .Address = ZcVal_##Nam, .pSignature = &sig_##Nam } 

/* And the supported camera */
const SensorList SensList[] = 
{
    DeclareSensor(CS2102  , 0 ),
    DeclareSensor(CS2103  , 1 ),
    DeclareSensor(HDCS1020, 2 ),
    DeclareSensor(HDCS2020, 3 ),
    DeclareSensor(HV7121B , 4 ),
    DeclareSensor(HV7131B , 5 ),
    DeclareSensor(ICM102A , 6 ),
    DeclareSensor(ICM105A , 7 ),
    DeclareSensor(OV7620  , 8 ),
    DeclareSensor(OVCIF   , 9 ),
    DeclareSensor(PAS106B , 10),
    DeclareSensor(PAS202B , 11),
    DeclareSensor(PB0111  , 12),
    DeclareSensor(PB0330  , 13),
    DeclareSensor(TAS5130C, 14),
    DeclareSensor(TAS5110B, 15),
};

/* Default sharpness sequence */
__u8 SharpnessControlSeq[6] = { 0x10, 0x00, 0x01, 0x01, 0x01, 0x1e };

/* Default RGB matrix sequence */
__u8 RGBMatrix[3][4] = 
{
    { 0x5a, 0xf3, 0xf3, 0x00 },
    { 0xf3, 0x5a, 0xf3, 0x00 },
    { 0xf3, 0xf3, 0x5a, 0x00 }
};
    
#define MaxNbSensor (sizeof(SensList) / sizeof(SensList[0]))

/* Declare declaration macro */
#define DeclareSensorSize(Nam, width, height, firstpixel, enable) \
    { .Width = width, .Height = height, .FirstPixel = firstpixel, .Enable = enable } 

/* And the supported camera */
const SensorSize SensorSizeList[] = 
{
    DeclareSensorSize(CS2102  , 640, 480, ZV(EnableInterpol) | ZV(GammaCorrection) | ZV(ColorCorrection), 0),
    DeclareSensorSize(CS2103  , 352, 288, ZV(EnableInterpol) | ZV(GammaCorrection) | ZV(ColorCorrection), 0),
    DeclareSensorSize(HDCS1020, 352, 288, ZV(EnableInterpol) | ZV(GammaCorrection) | ZV(ColorCorrection), 0),
    DeclareSensorSize(HDCS2020, 640, 480, ZV(GInterpolMedian) | ZV(RBInterpolAvg) | ZV(FirstPixelIsGreen) | ZV(EnableInterpol) | ZV(GammaCorrection) | ZV(ColorCorrection), 0),
    DeclareSensorSize(HV7121B , 352, 288, ZV(EnableInterpol) | ZV(GammaCorrection) | ZV(ColorCorrection), ZV(EnableSensor)),
    DeclareSensorSize(HV7131B , 640, 480, ZV(EnableInterpol) | ZV(GammaCorrection) | ZV(ColorCorrection), ZV(EnableSensor)),
    DeclareSensorSize(ICM102A , 352, 288, ZV(EnableInterpol) | ZV(GammaCorrection) | ZV(ColorCorrection), 0),
    DeclareSensorSize(ICM105A , 640, 480, ZV(EnableInterpol) | ZV(GammaCorrection) | ZV(ColorCorrection), 0),
    DeclareSensorSize(OV7620  , 640, 480, ZV(EnableInterpol) | ZV(GammaCorrection) | ZV(ColorCorrection), 0),
    DeclareSensorSize(OVCIF   , 352, 288, ZV(EnableInterpol) | ZV(GammaCorrection) | ZV(ColorCorrection), 0),
    DeclareSensorSize(PAS106B , 352, 288, ZV(EnableInterpol) | ZV(GammaCorrection) | ZV(ColorCorrection), 0),
    DeclareSensorSize(PAS202B , 640, 480, ZV(EnableInterpol) | ZV(GammaCorrection) | ZV(ColorCorrection), 0),
    DeclareSensorSize(PB0111  , 352, 288, ZV(EnableInterpol) | ZV(GammaCorrection) | ZV(ColorCorrection), ZV(EnableSensor)),
    DeclareSensorSize(PB0330  , 640, 480, ZV(EnableInterpol) | ZV(GammaCorrection) | ZV(ColorCorrection), ZV(EnableSensor)),
    DeclareSensorSize(TAS5130C, 640, 480, ZV(GInterpolMedian) | ZV(RBInterpolAvg) | ZV(FirstPixelIsGreen) | ZV(EnableInterpol) | ZV(GammaCorrection) | ZV(ColorCorrection), ZV(EnableSensor)),
    DeclareSensorSize(TAS5110B, 352, 288, ZV(EnableInterpol) | ZV(GammaCorrection) | ZV(ColorCorrection), ZV(EnableSensor)),
};

/* Declare declaration macro */
#define DeclareSensorConfig(Nam) \
 &sc_##Nam  

/* And the supported camera */
const SensorConfig * SensConfList[] = 
{
    DeclareSensorConfig(CS2102  ),
    DeclareSensorConfig(CS2103  ),
    DeclareSensorConfig(HDCS1020),
    DeclareSensorConfig(HDCS2020),
    DeclareSensorConfig(HV7121B ),
    DeclareSensorConfig(HV7131B ),
    DeclareSensorConfig(ICM102A ),
    DeclareSensorConfig(ICM105A ),
    DeclareSensorConfig(OV7620  ),
    DeclareSensorConfig(OVCIF   ),
    DeclareSensorConfig(PAS106B ),
    DeclareSensorConfig(PAS202B ),
    DeclareSensorConfig(PB0111  ),
    DeclareSensorConfig(PB0330  ),
    DeclareSensorConfig(TAS5130C),
    DeclareSensorConfig(TAS5110B),
};

/* Detect the sensor */
int zc030x_detect_sensor(struct usb_zc030x * dev, int id)
{
    /* Iterators */
    int i = 0;
    /* Sensor address */
    unsigned char addr = 0;

    /* Find the sensor now */
    addr = zc030x_i2c_detect(dev->udev, CamList[id].pI2CInitSeq);
    if (addr <= 0 || addr > 0x3f)
    {
        PDEBUG (1, "Sensor not found");
        return -1;    
    }
    
    /* Found */
    dev->sensor_addr = addr - 1;

    /* Check the sensors signatures now */
    i = 0;
    while (i < MaxNbSensor && SensList[i].pSignature != NULL 
        && zc030x_i2c_checksignature(dev->udev, SensList[i].pSignature) < sensoraccept)
        i++;
    if (i == MaxNbSensor)
    {
        PDEBUG (1, "Unsupported sensor or sensor not detected. Exiting\n");
        PDEBUG (1, "To help up improve this driver, please send the informations below");
        /* Get a simple register map */
        zc030x_i2c_simple_registermap(dev->udev);
        PDEBUG (1, "To zc0302-devs@lists.sf.net, with your ProductID:SensorID");
        PDEBUG (1, "and your sensor type, if you could know this. Thanks");
        return -1;
    }

    /* Found */
    dev->sensor_id = SensList[i].Index;
    
    /* Check if this is a PAS106B or not (this is due to a bug in PAS202B) */
    if (SensList[dev->sensor_id].pSignature->sensor_id == PAS106B && dev->sensor_addr == ZV(PAS202B))
    {
        dev->sensor_addr = ZV(PAS106B);
        PDEBUG(1, "Corrected sensor to address %02X", dev->sensor_addr);
    }
   
    /* Okay, return */
    return 0;
}

/* Detect the camera */
int zc030x_detect_camera(struct usb_zc030x * dev)
{
    /* Get the USB device */
    struct usb_device *udev = dev->udev;
    /* Get Vendor ID */
    int vend_id = udev->descriptor.idVendor;
    /* Get Product ID */
    int prod_id = udev->descriptor.idProduct;
    /* Get release number */
    int release = udev->descriptor.bcdDevice;
    /* Iterators */
    int i = 0, id = 0;
    /* Some tests */
    int sa = 0;
    int sb, sc, sd, se, sf;
    int ident = 0;
    
    /* some info about the device */
    PDEBUG (1, "vend_id : %04x", vend_id);
    PDEBUG (1, "prod_id : %04x", prod_id);
    PDEBUG (1, "Release : %04x", release);
    
    /*   See if the device offered us matches what we can accept */

    /* Find the vendor ID in the camera list */
    while (id < MaxNbCamera && (CamList[id].VendorID != vend_id || CamList[id].ProductID != prod_id) ) id++;
    /* Check the research */
    if (id == MaxNbCamera)
    {
        PDEBUG (1, "Unsupported webcam. Exiting");
        return -1;
    }

    /* Found */
    dev->vend_id = vend_id;
    dev->prod_id = prod_id;
    dev->type_id = CamList[id].Index;
    
    /* Read the test register */
    ident = zc030x_reg_read(dev->udev, ZR(TestModeControl), 0x01, 1);
    if ((ident & ZV(Zc301Plus)) == ZV(Zc301Plus))
    {
        PDEBUG(1, "Detected Zc0301+ bridge chip");
    }
    else
    {
        PDEBUG(1, "Detected Zc0302 bridge chip");
    }

    /* Reset the camera */
    if (zc030x_reg_reset(dev->udev) == REG_Error)
    {
        PDEBUG (1, "Cannot reset the camera");
        return -1;    
    }
    
    

    /* Get the sensor address by reading the 0x10 register */
    sa = zc030x_reg_read(dev->udev, ZR(CMOSSensorSelect), 0x01, 1);
    sb = zc030x_reg_read(dev->udev, ZR(WinYStartLow), 0x01, 1);
    sc = zc030x_reg_read(dev->udev, ZR(WinXStartLow), 0x01, 1);
    sd = zc030x_reg_read(dev->udev, ZR(CompabilityMode), 0x01, 1);
    se = zc030x_reg_read(dev->udev, ZR(I2CIdleAndNAck), 0x01, 1);
    sf = (zc030x_reg_read(dev->udev, ZR(I2CDeviceAddr), 0x01, 1) & 0x7F);
    
    
    /* Check the macro */
    if (strcmp(sensor, "auto") == 0)
    {
        PDEBUG(1, "Asked for autodectection...");
        if (zc030x_detect_sensor(dev, id)<0)
            return -1;
    } else
    {
        // Need to parse the sensor name specified at insmoding
        i = 0;
        while (i < MaxNbSensor && strcmp(sensor, SensList[i].Name) != 0)
        {
            i++;
        }
        
        if (i == MaxNbSensor)
        {
            // Invalid name or sensor not supported, detect it
            PDEBUG(1, "Invalid name or sensor not supported, detection...");
            if (zc030x_detect_sensor(dev, id)<0)
                return -1;
        }
        else
        {
            // Ugly debug to be tested
            if (strcmp(sensor, "TAS5130C")==0)
            {
            }
            
            // Found
            PDEBUG(1, "Sensor set to %s", sensor);
            dev->sensor_addr = SensList[i].Address;
            dev->sensor_id   = SensList[i].Index;
        }
    }
    
    /* Debug this */
    PDEBUG(1, "MaxNbSensor : %d", MaxNbSensor);
    PDEBUG(1, "Found sensor at address %02X", dev->sensor_addr);
    
    
    /* Debug this */
    PDEBUG (1, "Detected camera %s with sensor id %s\n", CamList[dev->type_id].Name, SensList[dev->sensor_id].Name);
    PDEBUG (4, "HM[0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X]", sa, sb, sc, sd, se, sf);
    
    return 0;
}

/* Send the sharpness sequence */
int zc030x_send_sharpness(struct usb_device *udev, const __u8 * value)
{
    /* Check arguments */
    if (udev == NULL || value == NULL)
    {
        PDEBUG(1, "udev or value is null");
        return -1;
    }
    
    /* Send the sharpness sequence */
    zc030x_reg_write(udev, ZR(Sharpness00), value[0]);
    zc030x_reg_read(udev, ZR(Sharpness01), value[1], 1);
    zc030x_reg_read(udev, ZR(Sharpness02), value[2], 1);
    zc030x_reg_read(udev, ZR(Sharpness03), value[3], 1);
    zc030x_reg_read(udev, ZR(Sharpness04), value[4], 1);
    zc030x_reg_write(udev, ZR(Sharpness05), value[5]);
    
    /* Return */
    return 0;
}

/* Send the gamma sequence */
int zc030x_send_gamma(struct usb_device *udev, const __u16 brightness, const __u16 contrast, const __u16 gamma)
{
    /* Iterator */
    int i = 0;
    /* Need to convert the value to emulated floating points */
    const FPNum dBrightness = CreateFPNumFromInt(((int)brightness - 32768));
    const FPNum dContrast = CreateFPNumFromInt(((int)contrast - 32768));
    const FPNum dGamma = CreateFPNumFromInt((int)gamma);
    FPNum OneOutOf256;
    FPNum OneOutOf32768;
    
    /* Init the FP Numbers */
    InitFPNum(&OneOutOf256, "0.00390625");
    InitFPNum(&OneOutOf32768, "0.000030517578125");

    /* Gamma matrix */
    {
        const __u8  * Gamma = zc030x_gamma_create_FPNum(Mul(dGamma, OneOutOf256), Mul(dBrightness, OneOutOf32768), Mul(dContrast, OneOutOf32768));
        PDEBUG(4, "Gamma matrix [%02X%02X%02X%02X %02X%02X%02X%02X %02X%02X%02X%02X %02X%02X%02X%02X]", Gamma[0x00], Gamma[0x01], Gamma[0x02], Gamma[0x03], Gamma[0x04], Gamma[0x05], Gamma[0x06], Gamma[0x07], Gamma[0x08], Gamma[0x09], Gamma[0x0a], Gamma[0x0b], Gamma[0x0c], Gamma[0x0d], Gamma[0x0e], Gamma[0x0f]);
        PDEBUG(4, "Gamma Slope matrix [%02X%02X%02X%02X %02X%02X%02X%02X %02X%02X%02X%02X %02X%02X%02X%02X]", Gamma[0x10], Gamma[0x11], Gamma[0x12], Gamma[0x13], Gamma[0x14], Gamma[0x15], Gamma[0x16], Gamma[0x17], Gamma[0x18], Gamma[0x19], Gamma[0x1a], Gamma[0x1b], Gamma[0x1c], Gamma[0x1d], Gamma[0x1e], Gamma[0x1f]);
    
        /* Check arguments */
        if (udev == NULL || Gamma == NULL)
        {
            PDEBUG(1, "udev or gamma is null");
            return -1;
        }
        
        /* Send the gamma sequence */
        for (; i < 32; i++)
            zc030x_reg_write(udev, ZR(Gamma00) + i, Gamma[i]);
    }
    /* Return */
    return 0;
}

/* Send the RGB to RGB conversion matrix */
int zc030x_send_RGBmatrix(struct usb_device *udev, __u8 matrix[3][4])
{

    /* Check arguments */
    if (udev == NULL)
    {
        PDEBUG(1, "udev is null");
        return -1;
    }
    
    /* Send the sharpness sequence */
    zc030x_reg_write(udev, ZR(RGB00), matrix[0][0]);
    zc030x_reg_write(udev, ZR(RGB01), matrix[0][1]);
    zc030x_reg_write(udev, ZR(RGB02), matrix[0][2]);
    zc030x_reg_write(udev, ZR(RGB03), matrix[0][3]);
    zc030x_reg_write(udev, ZR(RGB10), matrix[1][0]);
    zc030x_reg_write(udev, ZR(RGB11), matrix[1][1]);
    zc030x_reg_write(udev, ZR(RGB12), matrix[1][2]);
    zc030x_reg_write(udev, ZR(RGB13), matrix[1][3]);
    zc030x_reg_write(udev, ZR(RGB20), matrix[2][0]);
    zc030x_reg_write(udev, ZR(RGB21), matrix[2][1]);
    zc030x_reg_write(udev, ZR(RGB22), matrix[2][2]);
    zc030x_reg_write(udev, ZR(RGB23), matrix[2][3]);
    
    /* Return */
    return 0;
}

/* Configure the camera */
int zc030x_configure_camera(struct usb_zc030x * dev, int width, int height, int quality)
{
    /* Iterator */
//    int i = 0;
    
    /* Debug this */
    PDEBUG(1, ">>> CONFCAM %dx%d:%d", width, height, quality);

    /* Allocate buffers */
    if (zc030x_allocate_buffers(dev) < 0)
    {
        PDEBUG(1, "Failed while allocating the buffers!");
        return -1;
    }
    
    /* Reset the camera */
    if (zc030x_reg_reset(dev->udev) != REG_OK)
    {
        PDEBUG(1, "Failed while resetting the camera!");
        return -1;
    }
    
    /* Send the I2C start sequence */
    zc030x_i2c_start(dev->udev, CamList[dev->type_id].pI2CInitSeq, dev->sensor_addr);
    
    /* Change the interface */
    usb_set_interface (dev->udev, 0, 6);

    /* Change the debug level */
    if (debug == 5) debug = 6;
    
    /* Reset the camera */
    zc030x_reg_write(dev->udev, ZR(SystemControl), ZV(Reset));
    /* Resend the sensor address after a reset */
    zc030x_reg_write(dev->udev, ZR(CMOSSensorSelect), dev->sensor_addr);
    /* Start operating */
    zc030x_reg_write(dev->udev, ZR(SystemOperating), ZV(Start));

    /* Reset the internal stuff */
    zc030x_reg_write(dev->udev, ZR(VideoControlFunc), SensorSizeList[dev->sensor_id].Enable | ZV(ResetSensor)|ZV(SensorTurnOn));
    zc030x_reg_write(dev->udev, ZR(VideoControlFunc), SensorSizeList[dev->sensor_id].Enable | ZV(SensorTurnOn));

    PDEBUG(1, "Please report this to the list [101=%02X, %s-VID%04X:PID%04X:SID-%s]", zc030x_reg_read(dev->udev, ZR(SensorCorrection), 1, 1), CamList[dev->type_id].Name, dev->udev->descriptor.idVendor, dev->udev->descriptor.idProduct, SensList[dev->sensor_id].Name);
    

    /* Set the window size */
    switch(SensList[dev->sensor_id].pSignature->sensor_id)
    {
        case TAS5130C:
            /* Set the size */
            if (zc030x_reg_setsize(dev, width, height, ZV(DoubleClock)) != REG_OK)
            {
                PDEBUG(1, "Failed while setting the size!");
                return -1;
            }
            zc030x_reg_write(dev->udev, ZR(CompabilityMode) , ZV(TASxxxxC)|ZV(Round9To8Bit));
            zc030x_reg_write(dev->udev, ZR(WinYStartHigh), ZV(HalfscalY_Default));
            if (currentheight < SensorSizeList[dev->sensor_id].Height)
                zc030x_reg_write(dev->udev, ZR(WinYStartLow), ZV(HalfscalY_TASCVGA));
            else
                zc030x_reg_write(dev->udev, ZR(WinYStartLow), ZV(FullscalY_TASCVGA));
                
            zc030x_reg_write(dev->udev, ZR(WinXStartHigh), ZV(HalfscalX_Default));
            if (currentwidth < SensorSizeList[dev->sensor_id].Width)
                zc030x_reg_write(dev->udev, ZR(WinXStartLow), ZV(HalfscalX_TASCVGA));
            else
                zc030x_reg_write(dev->udev, ZR(WinXStartLow), ZV(FullscalX_TASCVGA));
        break;
        case TAS5110B:
            /* Set the size */
            if (zc030x_reg_setsize(dev, width, height, ZV(DoubleClock)) != REG_OK)
            {
                PDEBUG(1, "Failed while setting the size!");
                return -1;
            }
            zc030x_reg_write(dev->udev, ZR(CompabilityMode) , ZV(TASxxxxC)|ZV(Round9To8Bit));
            zc030x_reg_write(dev->udev, ZR(WinYStartHigh), ZV(HalfscalY_Default));
            if (currentheight < SensorSizeList[dev->sensor_id].Height)
                zc030x_reg_write(dev->udev, ZR(WinYStartLow), ZV(HalfscalY_TASCCIF));
            else
                zc030x_reg_write(dev->udev, ZR(WinYStartLow), ZV(FullscalY_TASCCIF));
                
            zc030x_reg_write(dev->udev, ZR(WinXStartHigh), ZV(HalfscalX_Default));
            if (currentwidth < SensorSizeList[dev->sensor_id].Width)
                zc030x_reg_write(dev->udev, ZR(WinXStartLow), ZV(HalfscalX_TASCCIF));
            else
                zc030x_reg_write(dev->udev, ZR(WinXStartLow), ZV(FullscalX_TASCCIF));
        break;
            
        case ICM105A:
        case ICM102A:
            /* Set the size */
            if (zc030x_reg_setsize(dev, width, height, 0) != REG_OK)
            {
                PDEBUG(1, "Failed while setting the size!");
                return -1;
            }
            zc030x_reg_write(dev->udev, ZR(CompabilityMode), 0);
            zc030x_reg_write(dev->udev, ZR(WinYStartHigh), ZV(HalfscalY_Default));
            if (currentheight < SensorSizeList[dev->sensor_id].Height)
                zc030x_reg_write(dev->udev, ZR(WinYStartLow), ZV(HalfscalY_ICM));
            else
                zc030x_reg_write(dev->udev, ZR(WinYStartLow), ZV(FullscalY_ICM));
                
            zc030x_reg_write(dev->udev, ZR(WinXStartHigh), ZV(HalfscalX_Default));
            if (currentwidth < SensorSizeList[dev->sensor_id].Width)
                zc030x_reg_write(dev->udev, ZR(WinXStartLow), ZV(HalfscalX_ICM));
            else
                zc030x_reg_write(dev->udev, ZR(WinXStartLow), ZV(FullscalX_ICM));
        break;
        case OV7620:
        case OVCIF:
            /* Set the size */
            if (zc030x_reg_setsize(dev, width, height, 0) != REG_OK)
            {
                PDEBUG(1, "Failed while setting the size!");
                return -1;
            }
            zc030x_reg_write(dev->udev, ZR(CompabilityMode), ZV(OVSensor));
        break;
        case PAS202B:
        case PAS106B:
            /* Set the size */
            if (zc030x_reg_setsize(dev, width, height, width < SensorSizeList[dev->sensor_id].Width / 2 ? ZV(PCLCK_750Khz) : 0) != REG_OK)
            {
                PDEBUG(1, "Failed while setting the size!");
                return -1;
            }
            zc030x_reg_write(dev->udev, ZR(CompabilityMode), ZV(OVSensor));
            zc030x_reg_write(dev->udev, ZR(WinYStartHigh), ZV(HalfscalY_Default));
            zc030x_reg_write(dev->udev, ZR(WinYStartLow), ZV(HalfscalY_Default));
            zc030x_reg_write(dev->udev, ZR(WinXStartHigh), ZV(HalfscalX_Default));
            if (currentwidth < SensorSizeList[dev->sensor_id].Width)
                zc030x_reg_write(dev->udev, ZR(WinXStartLow), ZV(HalfscalX_PAS));
            else
                zc030x_reg_write(dev->udev, ZR(WinXStartLow), ZV(FullscalX_PAS));
        break;
        case HDCS2020:
            /* Set the size */
            if (zc030x_reg_setsize(dev, width, height, width < SensorSizeList[dev->sensor_id].Width / 2 ? ZV(PCLCK_3Mhz) : 0) != REG_OK)
            {
                PDEBUG(1, "Failed while setting the size!");
                return -1;
            }
            /* Sensor parameters */
            if (currentwidth >= SensorSizeList[dev->sensor_id].Width)
                zc030x_reg_write(dev->udev, ZR(SensorCorrection), SensorSizeList[dev->sensor_id].FirstPixel | ZV(FirstLineIsGBGBG));
                
        case HV7131B:
        default:
            /* Set the size */
            if (zc030x_reg_setsize(dev, width, height, 0) != REG_OK)
            {
                PDEBUG(1, "Failed while setting the size!");
                return -1;
            }
            zc030x_reg_write(dev->udev, ZR(CompabilityMode), 0);
            zc030x_reg_write(dev->udev, ZR(WinYStartHigh), ZV(HalfscalY_Default));
            zc030x_reg_write(dev->udev, ZR(WinYStartLow), ZV(HalfscalY_Default));
            zc030x_reg_write(dev->udev, ZR(WinXStartHigh), ZV(HalfscalX_Default));
            zc030x_reg_write(dev->udev, ZR(WinXStartLow), ZV(HalfscalX_Default));
        break;
    }
    
    /* Set the window size */
    switch(SensList[dev->sensor_id].pSignature->sensor_id)
    {
        case HDCS2020:
        case TAS5130C:
        case TAS5110B:
        if (currentheight < SensorSizeList[dev->sensor_id].Height)
        {
            zc030x_reg_write(dev->udev, ZR(MaxXHigh), 0x03);
            zc030x_reg_write(dev->udev, ZR(MaxXLow), 0xc0);
            zc030x_reg_write(dev->udev, ZR(ExposureTimeHigh), 0x01);
            zc030x_reg_write(dev->udev, ZR(ExposureTimeLow), 0x77);
            zc030x_reg_write(dev->udev, ZR(ExposureGain), 0x01);
        }
        else
        {
            zc030x_reg_write(dev->udev, ZR(MaxXHigh), ZV(XMaxHighDefault));
            zc030x_reg_write(dev->udev, ZR(MaxXLow), ZV(XMaxLowVGADefault));
            zc030x_reg_write(dev->udev, ZR(ExposureTimeHigh), ZV(DefExpTimeVGAHigh));
            zc030x_reg_write(dev->udev, ZR(ExposureTimeLow), ZV(DefExpTimeVGALow));
            zc030x_reg_write(dev->udev, ZR(ExposureGain), ZV(DefExpGainVGA));
        }    
        zc030x_reg_write(dev->udev, ZR(ExposureBlackLvl), 0x3c);
        break;
        default:
        break;
    }
    
    /* Set the automatic features */
    zc030x_reg_write(dev->udev, ZR(OperationMode), ZV(DigitalColorGain)|ZV(YGammaGain)|ZV(DigitalGlobalGain));

    /* Auto white balance */
    WriteDefaultValue(dev->udev, AWBStatus);
    /* Sharpness */
    zc030x_reg_write(dev->udev, ZR(SharpnessMode), ZV(UseAvgValue)|ZV(EnableSharpening));
    
    /* Write the Zc030x I2C registers */
    zc030x_i2c_writeconfig(dev->udev, SensConfList[dev->sensor_id]);

    /* Dead pixels */
    zc030x_reg_write(dev->udev, ZR(DeadPixelsMode), ZV(RemoveDeadPixels));
    zc030x_reg_write(dev->udev, ZR(EEPROMAccess), ZV(BatchReadControl));

    /* Enable autoexposure */
    zc030x_reg_write(dev->udev, ZR(AutoCorrectEnable), ZV(AutoWhiteBalance) | ZV(AutoColorGain) | ZV(AutoExpAntiFlick));
    /* Set the Auto exposure window */
    WriteDefaultValue(dev->udev, WinXStart);
    WriteDefaultValue(dev->udev, WinXWidth);
    WriteDefaultValue(dev->udev, WinXCenter);
    WriteDefaultValue(dev->udev, WinYStart);
    WriteDefaultValue(dev->udev, WinYWidth);
    WriteDefaultValue(dev->udev, WinYCenter);
    /* Control the AE */
    zc030x_reg_write(dev->udev, ZR(AEStatus), ZV(WinAndBlockWeight)|ZV(LargeCenterWindow));
    zc030x_reg_write(dev->udev, ZR(AEFreeze), MakeAELockRange(0x14));
    zc030x_reg_write(dev->udev, ZR(AEUnfreeze), MakeAELockRange(0x20));
    
    /* Sensor parameters */
    zc030x_reg_write(dev->udev, ZR(SensorCorrection), SensorSizeList[dev->sensor_id].FirstPixel);
    
    /* Reset the clock */
    zc030x_reg_write(dev->udev, ZR(ClockSetting), ZV(Rounding)|ZV(QuarterQuant));
    
    /* And send the sharpness informations */
    zc030x_send_sharpness(dev->udev, SharpnessControlSeq);
    
    /* Send the gamma sequence */
    zc030x_send_gamma(dev->udev, dev->Brightness, dev->Contrast, dev->Gamma);
    
    /* Send the RGB matrix sequence */
    zc030x_send_RGBmatrix(dev->udev, RGBMatrix);

    /* Set the gains */
    zc030x_reg_write(dev->udev, ZR(RGain), MakeGain(1,0));
    zc030x_reg_write(dev->udev, ZR(GGain), MakeGain(1,0));
    zc030x_reg_write(dev->udev, ZR(BGain), MakeGain(1,0));
    zc030x_reg_write(dev->udev, ZR(GlobalGain), MakeGain(1,0));
    
    zc030x_reg_write(dev->udev, ZR(DigitalGain), MakeDigitalGain(1,0));
    zc030x_reg_write(dev->udev, ZR(DigitalLimitDiff), MakeDigitalLimitDiff(0x0c));
    zc030x_reg_write(dev->udev, ZR(DigitalGainStep), MakeDigitalGainStep(2,4));

    
    /* Set the clocks now */
    zc030x_reg_write(dev->udev, ZR(Sync00Low) , 0x00);
    zc030x_reg_write(dev->udev, ZR(Sync00Mid) , 0x04);
    zc030x_reg_write(dev->udev, ZR(Sync00High), 0x20);
    zc030x_reg_write(dev->udev, ZR(Sync01Low) , 0x00);
    zc030x_reg_write(dev->udev, ZR(Sync01Mid) , 0x00);
    zc030x_reg_write(dev->udev, ZR(Sync01High), 0x84);
    
    
    /* The horizontal and vertical synchros */
    zc030x_reg_write(dev->udev, ZR(HSYNC_0) , 0xe3);
    zc030x_reg_write(dev->udev, ZR(HSYNC_1) , 0xec);
    zc030x_reg_write(dev->udev, ZR(HSYNC_2) , 0xf5);
    zc030x_reg_write(dev->udev, ZR(HSYNC_3) , 0xff);

    /* The PB0330 stuff */
    if (SensList[dev->sensor_id].pSignature->sensor_id == PB0330)
    {
        zc030x_reg_write(dev->udev, 0x1ad, 0x09);
        zc030x_reg_write(dev->udev, 0x1ae, 0x15);
        zc030x_reg_write(dev->udev, 0x1a9, 0x14);
        zc030x_reg_write(dev->udev, 0x197, 0x8a);
        zc030x_reg_write(dev->udev, 0x191, 0x07);
        zc030x_reg_write(dev->udev, 0x192, 0x8c);
    
        zc030x_reg_write(dev->udev, 0x101, 0x37);
        zc030x_reg_write(dev->udev, 0x11a, 0x00);
        zc030x_reg_write(dev->udev, 0x11c, 0x00);
        zc030x_reg_write(dev->udev, 0x11d, 0x60);
        zc030x_reg_write(dev->udev, 0x180, 0x42);
        zc030x_reg_write(dev->udev, 0x189, 0x06);
        zc030x_reg_write(dev->udev, 0x18c, 0x10);
        zc030x_reg_write(dev->udev, 0x18d, 0x6c);
        
        zc030x_reg_write(dev->udev, 0x019, 0x00);
        zc030x_reg_write(dev->udev, 0x087, 0x10);
        zc030x_reg_write(dev->udev, 0x08d, 0x08);
    }

    /* Mostly implemented yet */
    PDEBUG(1, "<<< CONFCAM");
    
    /* Reset the previous debug level */
    if (debug == 6) debug = 5;
    return 0;
}