www.pudn.com > spca5xx-.rar > mr97311.h


/****************************************************************************
#	 	Mars-Semi MR97311A library                                  #
# 		Copyright (C) 2005                     #
# Part of spca5xx project                                                   #
# This program is free software; you can redistribute it and/or modify      #
# it under the terms of the GNU General Public License as published by      #
# the Free Software Foundation; either version 2 of the License, or         #
# (at your option) any later version.                                       #
#                                                                           #
# 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA #
#                                                                           #
****************************************************************************/
static int pcam_start( struct usb_spca50x *pcam );
static inline void pcam_stop( struct usb_spca50x *pcam );
static int mr97311_config (struct usb_spca50x *pcam );

static int pcam_reg_write(struct usb_device *dev,
                           __u16 index,
                           unsigned char *value,
                           int length );

static void MISensor_BulkWrite( struct usb_device *dev , unsigned short *pch , char Address , int length , char controlbyte);

//MI Register table //elvis
enum {
        REG_HW_MI_0,
        REG_HW_MI_1,
        REG_HW_MI_2,
        REG_HW_MI_3,
        REG_HW_MI_4,
        REG_HW_MI_5,
        REG_HW_MI_6,
        REG_HW_MI_7,
        REG_HW_MI_9 = 0x09,
        REG_HW_MI_B = 0x0B,
        REG_HW_MI_C,
        REG_HW_MI_D,
        REG_HW_MI_1E = 0x1E,
        REG_HW_MI_20 = 0x20,
        REG_HW_MI_2B = 0x2B,
        REG_HW_MI_2C,
        REG_HW_MI_2D,
        REG_HW_MI_2E,
        REG_HW_MI_35 = 0x35,
        REG_HW_MI_5F = 0x5F,
        REG_HW_MI_60,
        REG_HW_MI_61,
        REG_HW_MI_62,
        REG_HW_MI_63,
        REG_HW_MI_64,
        REG_HW_MI_F1 = 0xF1,
        ATTR_TOTAL_MI_REG = 242

};
static inline void pcam_stop( struct usb_spca50x *pcam )
{
	int result ;
	char data[2];
	
	memset( data , 0 , 2 );
	
	data[0] = 1;
	data[1] = 0;
	result = pcam_reg_write( pcam->dev , data[0] , data , 2 );	
	if( result < 0 )
	   printk("Camera Stop failed \n");
	   
}
static int pcam_reg_write(struct usb_device *dev,
                           __u16 index,
                           unsigned char *value,
                           int length )
{
      unsigned char buf[12];
      int rc;
      int i;
      unsigned char index_value=0;
                
      memset(buf , 0 , sizeof(buf));
      
      for( i =0 ; i < length ; i++ )
	 buf[i]=value[i];
   
      rc = usb_control_msg(dev,
                usb_sndbulkpipe(dev,4),
                0x12,
                0xc8,
                index_value,
                index,
                value, length , 5*HZ);

      PDEBUG(1,"reg write: 0x%02X , result = 0x%x \n", index , rc);
      
      if (rc < 0)
      {
          PDEBUG(1,"reg write: error %d \n", rc);
      }
      return rc;
}

static int pcam_start( struct usb_spca50x *pcam )
{
	int err_code;
  	unsigned char data[242];
  	unsigned short MI_buf[242];
  	int WriteCount =0;
	int h_size , v_size;
  	int intpipe;
  	//struct usb_device *dev = pcam->dev;
  	memset( data , 0 , 242 );
  	memset( MI_buf, 0 , 242 );
  
	PDEBUG(1,"usb_set_interface in pcamCameraStart , interface %d , alt 8 \n", pcam->iface );
	if (usb_set_interface (pcam->dev, pcam->iface, 8 ) < 0)
    	{
      	    err ("Set packet size: set interface error");
      	    return -EBUSY;
    	}
    	
  	data[0]=0x01; //address
        data[1]=0x01;

        err_code = pcam_reg_write(pcam->dev, data[0] , data , 0x02 );
        if(err_code < 0)
        {
                printk("Register write failed \n");
                return -1;
        }
        PDEBUG(1,"Hold the device '%d' write success , return value = %d \n" ,WriteCount++, err_code);

	/*
		Initialize the MR97113 chip register
	*/
	
        data[0]=0x00;           //address
        data[1]= 0x0c | 0x01;  //reg 0
        data[2]=0x01;           //reg 1

	 switch( pcam->width )
	 {
	 case 1280:
	 	h_size = 1280;
		v_size = 1024;
		break;
	case 640:
		h_size = 640;
		v_size = 480;
		break;
	case 384:
		h_size = 384;
		v_size = 288;
		break;
	case 352:
		h_size = 352;
		v_size = 288;
		break;
	case 320:
		h_size = 320;
		v_size = 240;
		break;
	default:
		h_size = 352;
		v_size = 288;
		break;
	 }
        data[3]=h_size /8;         //h_size , reg 2
        data[4]=v_size /8;         //v_size , reg 3
        data[5] = 0x30;  // reg 4, MI, PAS5101 : 0x30 for 24mhz , 0x28 for 12mhz
	 data[6]=4;      // reg 5, H start
        data[7]=0xc0;   // reg 6, gamma 1.5
        data[8]=3;      // reg 7, V start
       //if(pcam->width == 320 )
		//data[9]= 0x56;	// reg 8, 24MHz, 2:1 scale down
	//else
        	data[9]=0x52;   // reg 8, 24MHz, no scale down
        data[10]=0x5d;          // reg 9, I2C device address [for PAS5101 (0x40)] [for MI (0x5d)]

        err_code = pcam_reg_write(pcam->dev, data[0] , data , 0x0b );
        if(err_code < 0)
        {
                PDEBUG(1,"Register write failed \n");
                return -1;
        }
        PDEBUG(1,"usb_control_msg() '%d' write success , return value = %d \n" ,WriteCount++, err_code);

        data[0]=0x23;   //address
        data[1]=0x09;  // reg 35, append frame header

        err_code = pcam_reg_write(pcam->dev, data[0] , data , 0x02 );
        if(err_code < 0)
        {
                PDEBUG(1,"Register write failed \n");
                return -1;
        }
        PDEBUG(1,"usb_control_msg() '%d' write success , return value = %d \n" ,WriteCount++, err_code);


        data[0]=0x3C; //address
        if(pcam->width == 1280 )
		data[1]= 200;  // reg 60, pc-cam frame size (unit: 4KB) 800KB
	else
        	data[1]=50;  // 50 reg 60, pc-cam frame size (unit: 4KB) 200KB
        err_code = pcam_reg_write(pcam->dev, data[0] , data , 0x02 );
        if(err_code < 0)
        {
                PDEBUG(1,"Register write failed \n");
                return -1;
        }
        PDEBUG(1,"usb_control_msg() '%d' write success , return value = %d \n" ,WriteCount++, err_code);

	if(0)
	{	// fixed dark-gain
		data[1] = 0;    // reg 94, Y Gain (1.75)
		data[2] = 0;    // reg 95, UV Gain (1.75)
		data[3] = 0x3f; // reg 96, Y Gain/UV Gain/disable auto dark-gain
		data[4] = 0;    // reg 97, set fixed dark level
		data[5] = 0;    // reg 98, don't care
	}
	else
	{	// auto dark-gain
		data[1] = 0;    // reg 94, Y Gain (auto)
		data[2] = 0;    // reg 95, UV Gain (1.75)
		data[3] = 0x78; // reg 96, Y Gain/UV Gain/disable auto dark-gain
		switch(pcam->width)
		{
		case 1280:
			data[4] = 154;  // reg 97, %3 shadow point (unit: 256 pixel)
			data[5] = 51;  // reg 98, %1 highlight point (uint: 256 pixel)
			break;
		case 640:
			data[4] = 36;  // reg 97, %3 shadow point (unit: 256 pixel)
			data[5] = 12;  // reg 98, %1 highlight point (uint: 256 pixel)
			break;
		case 320:
			data[4] = 9;  // reg 97, %3 shadow point (unit: 256 pixel)
			data[5] = 3;  // reg 98, %1 highlight point (uint: 256 pixel)
			break;
		}
	}
        // auto dark-gain
        data[0]=0x5E;    // address
        
        err_code = pcam_reg_write(pcam->dev, data[0] , data , 0x06 );
        if(err_code < 0)
        {
                PDEBUG(1,"Register write failed \n");
                return -1;
        }
        PDEBUG(1,"usb_control_msg() '%d' write success , return value = %d \n" ,WriteCount++, err_code);


        data[0] = 0x67;
        data[1] = 0x13; // reg 103, first pixel B, disable sharpness
        err_code = pcam_reg_write(pcam->dev, data[0] , data , 0x02 );
        if(err_code < 0)
        {
                PDEBUG(1,"Register write failed \n");
                return -1;
        }
        PDEBUG(1,"usb_control_msg() '%d' write success , return value = %d \n" ,WriteCount++, err_code);

        /*
        	initialize the value of MI sensor...
	*/
	
        MI_buf[REG_HW_MI_1]    = 0x000a;           
	MI_buf[REG_HW_MI_2]    = 0x000c;
        MI_buf[REG_HW_MI_3]     = 0x0405;
        MI_buf[REG_HW_MI_4]     = 0x0507;
        //mi_Attr_Reg_[REG_HW_MI_5]     = 0x01ff;//13
        MI_buf[REG_HW_MI_5]     = 0x0013;//13
        MI_buf[REG_HW_MI_6]     = 0x001f;  // vertical blanking
        //mi_Attr_Reg_[REG_HW_MI_6]     = 0x0400;  // vertical blanking
        MI_buf[REG_HW_MI_7]     = 0x0002;
        //mi_Attr_Reg_[REG_HW_MI_9]     = 0x015f;
        //mi_Attr_Reg_[REG_HW_MI_9]     = 0x030f;
        MI_buf[REG_HW_MI_9]     = 0x0374;
        MI_buf[REG_HW_MI_B]     = 0x0000;
        MI_buf[REG_HW_MI_C]     = 0x0000;
        MI_buf[REG_HW_MI_D]     = 0x0000;
        MI_buf[REG_HW_MI_1E]    = 0x8000;
//      mi_Attr_Reg_[REG_HW_MI_20]      = 0x1104;
        MI_buf[REG_HW_MI_20]    = 0x1104;//0x111c;
        MI_buf[REG_HW_MI_2B]    = 0x0008;
//      mi_Attr_Reg_[REG_HW_MI_2C]      = 0x000f;
        MI_buf[REG_HW_MI_2C]    = 0x001f;//lita suggest
        MI_buf[REG_HW_MI_2D]    = 0x0008;
        MI_buf[REG_HW_MI_2E]    = 0x0008;
        MI_buf[REG_HW_MI_35]    = 0x0051;
        MI_buf[REG_HW_MI_5F]    = 0x0904;//fail to write
        MI_buf[REG_HW_MI_60]    = 0x0000;
        MI_buf[REG_HW_MI_61]    = 0x0000;
        MI_buf[REG_HW_MI_62]    = 0x0498;
        MI_buf[REG_HW_MI_63]    = 0x0000;
        MI_buf[REG_HW_MI_64]    = 0x0000;
        MI_buf[REG_HW_MI_F1]    = 0x0001;
        //changing while setting up the different value of dx/dy

	if(pcam->width != 1280 )
	{
		MI_buf[0x01] = 0x010a;
		MI_buf[0x02] = 0x014c;
		MI_buf[0x03] = 0x01e5;
		MI_buf[0x04] = 0x0287;
	}
	MI_buf[0x20]=0x1104;	

       MISensor_BulkWrite( pcam->dev, MI_buf+1, 1 , 1, 0 );
      	PDEBUG(1,"usb_control_msg() '%d' write success \n" ,WriteCount++);
	
	MISensor_BulkWrite( pcam->dev, MI_buf+2, 2 , 1, 0 );
	PDEBUG(1,"usb_control_msg() '%d' write success \n" ,WriteCount++);
	
	MISensor_BulkWrite( pcam->dev, MI_buf+3, 3 , 1, 0 );
	PDEBUG(1,"usb_control_msg() '%d' write success \n" ,WriteCount++);
	
	MISensor_BulkWrite( pcam->dev, MI_buf+4, 4 , 1, 0 );
	PDEBUG(1,"usb_control_msg() '%d' write success \n" ,WriteCount++);
	
	MISensor_BulkWrite( pcam->dev, MI_buf+5, 5 , 1, 0 );
	PDEBUG(1,"usb_control_msg() '%d' write success \n" ,WriteCount++);
	
	MISensor_BulkWrite( pcam->dev, MI_buf+6, 6 , 1, 0 );
	PDEBUG(1,"usb_control_msg() '%d' write success \n" ,WriteCount++);
	
	MISensor_BulkWrite( pcam->dev, MI_buf+7, 7 , 1, 0 );
	PDEBUG(1,"usb_control_msg() '%d' write success \n" ,WriteCount++);
	
	MISensor_BulkWrite( pcam->dev, MI_buf+9, 9 , 1, 0 );
	PDEBUG(1,"usb_control_msg() '%d' write success \n" ,WriteCount++);
	
	MISensor_BulkWrite( pcam->dev, MI_buf+0x0B, 0x0B , 1, 0 );
	PDEBUG(1,"usb_control_msg() '%d' write success \n" ,WriteCount++);
	
	MISensor_BulkWrite( pcam->dev, MI_buf+0x0C, 0x0C , 1, 0 );
	PDEBUG(1,"usb_control_msg() '%d' write success \n" ,WriteCount++);
	
	MISensor_BulkWrite( pcam->dev, MI_buf+0x0D, 0x0D , 1, 0 );
	PDEBUG(1,"usb_control_msg() '%d' write success \n" ,WriteCount++);
	
	MISensor_BulkWrite( pcam->dev, MI_buf+0x1E, 0x1E , 1, 0 );
	PDEBUG(1,"usb_control_msg() '%d' write success \n" ,WriteCount++);
	
	MISensor_BulkWrite( pcam->dev, MI_buf+0x20, 0x20 , 1, 0 );
	PDEBUG(1,"usb_control_msg() '%d' write success \n" ,WriteCount++);
	
	MISensor_BulkWrite( pcam->dev, MI_buf+0x2B, 0x2B , 1, 0 );
	PDEBUG(1,"usb_control_msg() '%d' write success \n" ,WriteCount++);
	
	MISensor_BulkWrite( pcam->dev, MI_buf+0x2C, 0x2C , 1, 0 );
	PDEBUG(1,"usb_control_msg() '%d' write success \n" ,WriteCount++);
	
	MISensor_BulkWrite( pcam->dev, MI_buf+0x2D, 0x2D , 1, 0 );
	PDEBUG(1,"usb_control_msg() '%d' write success \n" ,WriteCount++);
	
	MISensor_BulkWrite( pcam->dev, MI_buf+0x2E, 0x2E , 1, 0 );
	PDEBUG(1,"usb_control_msg() '%d' write success \n" ,WriteCount++);
	
	MISensor_BulkWrite( pcam->dev, MI_buf+0x35, 0x35 , 1, 0 );
	PDEBUG(1,"usb_control_msg() '%d' write success \n" ,WriteCount++);
	
	MISensor_BulkWrite( pcam->dev, MI_buf+0x5F, 0x5F , 1, 0 );
	PDEBUG(1,"usb_control_msg() '%d' write success \n" ,WriteCount++);
	
	MISensor_BulkWrite( pcam->dev, MI_buf+0x60, 0x60 , 1, 0 );
	PDEBUG(1,"usb_control_msg() '%d' write success \n" ,WriteCount++);
	
	MISensor_BulkWrite( pcam->dev, MI_buf+0x61, 0x61 , 1, 0 );
	PDEBUG(1,"usb_control_msg() '%d' write success \n" ,WriteCount++);
	
	MISensor_BulkWrite( pcam->dev, MI_buf+0x62, 0x62 , 1, 0 );
	PDEBUG(1,"usb_control_msg() '%d' write success \n" ,WriteCount++);
	
	MISensor_BulkWrite( pcam->dev, MI_buf+0x63, 0x63 , 1, 0 );
	PDEBUG(1,"usb_control_msg() '%d' write success \n" ,WriteCount++);
	
	MISensor_BulkWrite( pcam->dev, MI_buf+0x64, 0x64 , 1, 0 );
	PDEBUG(1,"usb_control_msg() '%d' write success \n" ,WriteCount++);
	
	MISensor_BulkWrite( pcam->dev, MI_buf+0xF1, 0xF1 , 1, 0 );
	PDEBUG(1,"usb_control_msg() '%d' write success \n" ,WriteCount++);

       
	intpipe = usb_sndintpipe (pcam->dev, 0);
	err_code = usb_clear_halt( pcam->dev , intpipe );
	
	data[0] = 0x00;
        data[1] = 0x4D; // ISOC transfering enable...
        err_code = pcam_reg_write(pcam->dev, data[0] , data , 0x02 );
        if(err_code < 0)
        {
                PDEBUG(1,"Register write failed \n");
                return -1;
        }
        PDEBUG(1,"usb_control_msg() '%d' write success , return value = %d \n" ,WriteCount++, err_code);
	
	return 0;
}
static void MISensor_BulkWrite( struct usb_device *dev , unsigned short *pch , char Address , int length , char controlbyte)
{
        int dest , src , result;
        unsigned char data[6];

        memset(data , 0 , 6 );

        for( dest=3 , src =0; src < length ; src++ )
        {
             data[0] = 0x1f;
             data[1] = controlbyte;
             data[2] = Address + src;
             data[dest] = pch[src] >> 8; //high byte;
             data[dest+1] = pch[src]; //low byte;
             data[dest+2] = 0;

             result = usb_control_msg(dev,
              	          usb_sndbulkpipe(dev,4),
                	     0x12,
                          0xc8,
                          0,
                          Address,
                          data, 5 , 5*HZ);

             PDEBUG(1,"reg write: 0x%02X , result = 0x%x \n", Address, result);

             if (result<0)
             {
                 printk("reg write: error %d \n", result);
             }

     }

}
static int mr97311_config(struct usb_spca50x *spca50x )
{
		memset (spca50x->mode_cam, 0x00, TOTMODE * sizeof(struct mwebcam));
		spca50x->mode_cam[VGA].width = 640;
		spca50x->mode_cam[VGA].height = 480;
		spca50x->mode_cam[VGA].t_palette = P_JPEG | P_RAW | P_YUV420 | P_RGB32 | P_RGB24 | P_RGB16;
		spca50x->mode_cam[VGA].pipe = 1023;
		spca50x->mode_cam[VGA].method = 0;
		spca50x->mode_cam[VGA].mode = 1;
		spca50x->mode_cam[PAL].width = 384;
		spca50x->mode_cam[PAL].height = 288;
		spca50x->mode_cam[PAL].t_palette = P_YUV420 | P_RGB32 | P_RGB24 | P_RGB16;
		spca50x->mode_cam[PAL].pipe = 1023;
		spca50x->mode_cam[PAL].method = 1;
		spca50x->mode_cam[PAL].mode = 1;
		spca50x->mode_cam[SIF].width = 352;
		spca50x->mode_cam[SIF].height = 288;
		spca50x->mode_cam[SIF].t_palette = P_YUV420 | P_RGB32 | P_RGB24 | P_RGB16;
		spca50x->mode_cam[SIF].pipe = 1023;
		spca50x->mode_cam[SIF].method = 1;
		spca50x->mode_cam[SIF].mode = 1;
		spca50x->mode_cam[CIF].width = 320;
		spca50x->mode_cam[CIF].height = 240;
		spca50x->mode_cam[CIF].t_palette = P_JPEG | P_RAW | P_YUV420 | P_RGB32 | P_RGB24 | P_RGB16;
		spca50x->mode_cam[CIF].pipe = 896;
		spca50x->mode_cam[CIF].method = 0;
		spca50x->mode_cam[CIF].mode = 2;
		spca50x->mode_cam[QPAL].width = 192;
		spca50x->mode_cam[QPAL].height = 144;
		spca50x->mode_cam[QPAL].t_palette = P_YUV420 | P_RGB32 | P_RGB24 | P_RGB16;
		spca50x->mode_cam[QPAL].pipe = 896;
		spca50x->mode_cam[QPAL].method = 1;
		spca50x->mode_cam[QPAL].mode = 2;
		spca50x->mode_cam[QSIF].width = 176;
		spca50x->mode_cam[QSIF].height = 144;
		spca50x->mode_cam[QSIF].t_palette = P_YUV420 | P_RGB32 | P_RGB24 | P_RGB16;
		spca50x->mode_cam[QSIF].pipe = 896;
		spca50x->mode_cam[QSIF].method = 1;
		spca50x->mode_cam[QSIF].mode = 2;
return 0;
}