/* Kirby: add new-style driver {*/
static int OV8825AF_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
    int i4RetValue = 0;

    OV8825AFDB("[OV8825AF] Attach I2C \n");

    /* Kirby: add new-style driver { */
    g_pstOV8825AF_I2Cclient = client;
    
    //g_pstOV8825AF_I2Cclient->addr = g_pstOV8825AF_I2Cclient->addr >> 1;
    g_pstOV8825AF_I2Cclient->addr = OV8825AF_VCM_WRITE_ID >> 1;
    //Register char driver
    i4RetValue = Register_OV8825AF_CharDrv();

    if(i4RetValue){

        OV8825AFDB("[OV8825AF] register char device failed!\n");

        return i4RetValue;
    }

    spin_lock_init(&g_OV8825AF_SpinLock);

    OV8825AFDB("[OV8825AF] Attached!! \n");

    return 0;
}
inline static int Register_OV8825AF_CharDrv(void)
{
    struct device* vcm_device = NULL;

    //Allocate char driver no.
    if( alloc_chrdev_region(&g_OV8825AF_devno, 0, 1,OV8825AF_DRVNAME) )
    {
        OV8825AFDB("[OV8825AF] Allocate device no failed\n");

        return -EAGAIN;
    }

    //Allocate driver
    g_pOV8825AF_CharDrv = cdev_alloc();

    if(NULL == g_pOV8825AF_CharDrv)
    {
        unregister_chrdev_region(g_OV8825AF_devno, 1);

        OV8825AFDB("[OV8825AF] Allocate mem for kobject failed\n");

        return -ENOMEM;
    }

    //Attatch file operation.
    cdev_init(g_pOV8825AF_CharDrv, &g_stOV8825AF_fops);

    g_pOV8825AF_CharDrv->owner = THIS_MODULE;

    //Add to system
    if(cdev_add(g_pOV8825AF_CharDrv, g_OV8825AF_devno, 1))
    {
        OV8825AFDB("[OV8825AF] Attatch file operation failed\n");

        unregister_chrdev_region(g_OV8825AF_devno, 1);

        return -EAGAIN;
    }

    actuator_class = class_create(THIS_MODULE, "actuatordrv5");
    if (IS_ERR(actuator_class)) {
        int ret = PTR_ERR(actuator_class);
        OV8825AFDB("Unable to create class, err = %d\n", ret);
        return ret;            
    }

    vcm_device = device_create(actuator_class, NULL, g_OV8825AF_devno, NULL, OV8825AF_DRVNAME);

    if(NULL == vcm_device)
    {
        return -EIO;
    }
    
    return 0;
}
static int s4OV8825AF_WriteReg(u16 a_u2Data)
{
    u16 temp,SlewRate=1;
    OV8825AFDB("s4OV8825AF_WriteReg = %d \n", a_u2Data);
	
	temp=(a_u2Data<<4)+SlewRate;
	OV8825AFDB("-----stemp=(a_u2Data<<4)+SlewRate = %d----- \n", temp);
	
	OV8825AF_write_cmos_sensor(0x3619,(temp>>8)&0xff);
	
	OV8825AF_write_cmos_sensor(0x3618,temp&0xff);

    return 0;
}
Esempio n. 4
0
static int __init OV8825AF_i2C_init(void)
{
	i2c_register_board_info(LENS_I2C_BUSNUM, &kd_lens_dev, 1);
  if(platform_device_register(&g_stOV8825AF_device)){
    OV8825AFDB("failed to register AF driver\n");
    return -ENODEV;
  }
	if (platform_driver_register(&g_stOV8825AF_Driver)) {
		OV8825AFDB("failed to register OV8825AF driver\n");
		return -ENODEV;
	}

	return 0;
}
static long OV8825AF_Ioctl(
struct file * a_pstFile,
unsigned int a_u4Command,
unsigned long a_u4Param)
{
    long i4RetValue = 0;

    switch(a_u4Command)
    {
        case OV8825AFIOC_G_MOTORINFO :
            i4RetValue = getOV8825AFInfo((__user stOV8825AF_MotorInfo *)(a_u4Param));
        break;

        case OV8825AFIOC_T_MOVETO :
            i4RetValue = moveOV8825AF(a_u4Param);
        break;
 
        case OV8825AFIOC_T_SETINFPOS :
            i4RetValue = setOV8825AFInf(a_u4Param);
        break;

        case OV8825AFIOC_T_SETMACROPOS :
            i4RetValue = setOV8825AFMacro(a_u4Param);
        break;
		
        default :
      	    OV8825AFDB("[OV8825AF] No CMD \n");
            i4RetValue = -EPERM;
        break;
    }

    return i4RetValue;
}
Esempio n. 6
0
//Main jobs:
//Break down move step for eliminating noise
static int breakDownSteps(int max_step, int interval, int CurrentPos, int TargetPos)
{
    unsigned short tmpTargetPos;
    short sign = 0;
    
    OV8825AFDB("[OV8825AF] break down steps from=%d, to=%d \n", CurrentPos, TargetPos);
    if (TargetPos < CurrentPos)
        sign = -1;
    else if (TargetPos > CurrentPos)
        sign = 1;

    while( abs(CurrentPos - TargetPos) > max_step ){
        tmpTargetPos = CurrentPos + max_step * sign;
            
        OV8825AFDB("tmpTargetPos=%d\n", tmpTargetPos);
        if(s4OV8825AF_WriteReg(tmpTargetPos) == 0)
        {
            CurrentPos = tmpTargetPos;
            OV8825AFDB("CurrentPos=%d\n", CurrentPos);
        }
        else
        {
            OV8825AFDB("[OV8825AF] set I2C failed when moving the motor \n");
            g_i4MotorStatus = -1;
        }
        
        //Delay for few milli-second
        OV8825AFDB("start delay \n");
        msleep(interval);
        OV8825AFDB("after delay \n");
    }

    OV8825AFDB("Last step from=%d, to=%d \n", CurrentPos, TargetPos);
    if(s4OV8825AF_WriteReg(TargetPos) == 0)
    {
          CurrentPos = TargetPos;
    }
    else
    {
          OV8825AFDB("[OV8825AF] set I2C failed when moving the motor \n");
          g_i4MotorStatus = -1;
    }
    g_u4CurrPosition = CurrentPos;
    
    OV8825AFDB("Leave breakdown\n");
    
    return 0;
}
static int s4OV8825AF_ReadReg(unsigned short * a_pu2Result)
{
    int  temp = 0;
    char pBuff[2];

    temp = (OV8825AF_read_cmos_sensor(0x3618)+ (OV8825AF_read_cmos_sensor(0x3619)<<8))>>4;

    *a_pu2Result = temp;
	OV8825AFDB("s4OV8825AF_ReadReg = %d \n", temp);
    return 0;
}
Esempio n. 8
0
/* Q1 : Try release multiple times. */
static int OV8825AF_Release(struct inode *a_pstInode, struct file *a_pstFile)
{
	if (g_s4OV8825AF_Opened == 2) 
    {
		g_sr = 5;

		if (g_u4CurrPosition > 700) {
			s4OV8825AF_WriteReg(700);
			msleep(3);
		}

		if (g_u4CurrPosition > 600) {
			s4OV8825AF_WriteReg(600);
			msleep(3);
		}

		if (g_u4CurrPosition > 500) {
			s4OV8825AF_WriteReg(500);
			msleep(3);
		}

		if (g_u4CurrPosition > 400) {
			s4OV8825AF_WriteReg(400);
			msleep(3);
		}

		if (g_u4CurrPosition > 300) {
			s4OV8825AF_WriteReg(300);
			msleep(3);
		}

		if (g_u4CurrPosition > 200) {
			s4OV8825AF_WriteReg(200);
			msleep(3);
		}

		if (g_u4CurrPosition > 100) {
			s4OV8825AF_WriteReg(100);
			msleep(3);
		}
	}

	if (g_s4OV8825AF_Opened) 
    {
		OV8825AFDB("[OV8825AF] feee\n");

		spin_lock(&g_OV8825AF_SpinLock);
		g_s4OV8825AF_Opened = 0;
		spin_unlock(&g_OV8825AF_SpinLock);
	}


	return 0;
}
Esempio n. 9
0
/* CAM_RESET */
static int OV8825AF_Open(struct inode *a_pstInode, struct file *a_pstFile)
{

	if (g_s4OV8825AF_Opened) {
		OV8825AFDB("[OV8825AF] the device is opened\n");
		return -EBUSY;
	}

	spin_lock(&g_OV8825AF_SpinLock);
	g_s4OV8825AF_Opened = 1;
	spin_unlock(&g_OV8825AF_SpinLock);

	return 0;
}
Esempio n. 10
0
inline static int getOV8825AFInfo(__user stOV8825AF_MotorInfo * pstMotorInfo)
{
    stOV8825AF_MotorInfo stMotorInfo;
    stMotorInfo.u4MacroPosition   = g_u4OV8825AF_MACRO;
    stMotorInfo.u4InfPosition     = g_u4OV8825AF_INF;
    stMotorInfo.u4CurrentPosition = g_u4CurrPosition;
	if (g_i4MotorStatus == 1)	{stMotorInfo.bIsMotorMoving = TRUE;}
	else						{stMotorInfo.bIsMotorMoving = FALSE;}

	if (g_s4OV8825AF_Opened >= 1)	{stMotorInfo.bIsMotorOpen = TRUE;}
	else						{stMotorInfo.bIsMotorOpen = FALSE;}

    if(copy_to_user(pstMotorInfo , &stMotorInfo , sizeof(stOV8825AF_MotorInfo)))
    {
        OV8825AFDB("[OV8825AF] copy to user failed when getting motor information \n");
    }

    return 0;
}
Esempio n. 11
0
//Main jobs:
// 1.Deallocate anything that "open" allocated in private_data.
// 2.Shut down the device on last close.
// 3.Only called once on last time.
// Q1 : Try release multiple times.
static int OV8825AF_Release(struct inode * a_pstInode, struct file * a_pstFile)
{
    if (g_s4OV8825AF_Opened)
    {
        OV8825AFDB("[OV8825AF] feee \n");
        g_sr = 5;
	    s4OV8825AF_WriteReg(200);
        msleep(10);
	    s4OV8825AF_WriteReg(100);
        msleep(10);
            	            	    	    
        spin_lock(&g_OV8825AF_SpinLock);
        g_s4OV8825AF_Opened = 0;
        spin_unlock(&g_OV8825AF_SpinLock);

    }

    return 0;
}
Esempio n. 12
0
inline static int moveOV8825AF(unsigned long a_u4Position)
{
    if((a_u4Position > g_u4OV8825AF_MACRO) || (a_u4Position < g_u4OV8825AF_INF))
    {
        OV8825AFDB("[OV8825AF] out of range \n");
        return -EINVAL;
    }

	if (g_s4OV8825AF_Opened == 1)
	{
		unsigned short InitPos;
	
		if(s4OV8825AF_ReadReg(&InitPos) == 0)
		{
			OV8825AFDB("[OV8825AF] Init Pos %6d \n", InitPos);
		
			g_u4CurrPosition = (unsigned long)InitPos;
		}
		else
		{
			g_u4CurrPosition = 0;
		}
		
		g_s4OV8825AF_Opened = 2;
	}

	if      (g_u4CurrPosition < a_u4Position)	{g_i4Dir = 1;}
	else if (g_u4CurrPosition > a_u4Position)	{g_i4Dir = -1;}
	else										{return 0;}

	if (1)
	{
		g_i4Position = (long)g_u4CurrPosition;
		g_u4TargetPosition = a_u4Position;

		if (g_i4Dir == 1)
		{
			//if ((g_u4TargetPosition - g_u4CurrPosition)<60)
			{		
				g_i4MotorStatus = 0;
				if(s4OV8825AF_WriteReg((unsigned short)g_u4TargetPosition) == 0)
				{
					g_u4CurrPosition = (unsigned long)g_u4TargetPosition;
				}
				else
				{
					OV8825AFDB("[OV8825AF] set I2C failed when moving the motor \n");
					g_i4MotorStatus = -1;
				}
			}
			//else
			//{
			//	g_i4MotorStatus = 1;
			//}
		}
		else if (g_i4Dir == -1)
		{
			//if ((g_u4CurrPosition - g_u4TargetPosition)<60)
			{
				g_i4MotorStatus = 0;		
				if(s4OV8825AF_WriteReg((unsigned short)g_u4TargetPosition) == 0)
				{
					g_u4CurrPosition = (unsigned long)g_u4TargetPosition;
				}
				else
				{
					OV8825AFDB("[OV8825AF] set I2C failed when moving the motor \n");
					g_i4MotorStatus = -1;
				}
			}
			//else
			//{
			//	g_i4MotorStatus = 1;		
			//}
		}
	}
	else
	{
	g_i4Position = (long)g_u4CurrPosition;
	g_u4TargetPosition = a_u4Position;
	g_i4MotorStatus = 1;
	}

    return 0;
}
Esempio n. 13
0
inline static int moveOV8825AF(unsigned long a_u4Position)
{
	int ret = 0;

	if ((a_u4Position > g_u4OV8825AF_MACRO) || (a_u4Position < g_u4OV8825AF_INF)) {
		OV8825AFDB("[OV8825AF] out of range\n");
		return -EINVAL;
	}

	if (g_s4OV8825AF_Opened == 1) {
		unsigned short InitPos;
		ret = s4OV8825AF_ReadReg(&InitPos);


		if (ret == 0) {
			OV8825AFDB("[OV8825AF] Init Pos %6d\n", InitPos);

			spin_lock(&g_OV8825AF_SpinLock);
			g_u4CurrPosition = (unsigned long)InitPos;
			spin_unlock(&g_OV8825AF_SpinLock);
		} else {
			spin_lock(&g_OV8825AF_SpinLock);
			g_u4CurrPosition = 0;
			spin_unlock(&g_OV8825AF_SpinLock);
		}
		spin_lock(&g_OV8825AF_SpinLock);
		g_s4OV8825AF_Opened = 2;
		spin_unlock(&g_OV8825AF_SpinLock);
	}

	if (g_u4CurrPosition < a_u4Position) {
		spin_lock(&g_OV8825AF_SpinLock);
		g_i4Dir = 1;
		spin_unlock(&g_OV8825AF_SpinLock);
	} else if (g_u4CurrPosition > a_u4Position) {
		spin_lock(&g_OV8825AF_SpinLock);
		g_i4Dir = -1;
		spin_unlock(&g_OV8825AF_SpinLock);
	} else {
		return 0;
	}

	spin_lock(&g_OV8825AF_SpinLock);
	g_u4TargetPosition = a_u4Position;
	spin_unlock(&g_OV8825AF_SpinLock);

	/* OV8825AFDB("[OV8825AF] move [curr] %d [target] %d\n", g_u4CurrPosition, g_u4TargetPosition); */

	spin_lock(&g_OV8825AF_SpinLock);
	g_sr = 3;
	g_i4MotorStatus = 0;
	spin_unlock(&g_OV8825AF_SpinLock);

	if (s4OV8825AF_WriteReg((unsigned short)g_u4TargetPosition) == 0) {
		spin_lock(&g_OV8825AF_SpinLock);
		g_u4CurrPosition = (unsigned long)g_u4TargetPosition;
		spin_unlock(&g_OV8825AF_SpinLock);
	} else {
		OV8825AFDB("[OV8825AF] set I2C failed when moving the motor\n");
		spin_lock(&g_OV8825AF_SpinLock);
		g_i4MotorStatus = -1;
		spin_unlock(&g_OV8825AF_SpinLock);
	}

	return 0;
}
Esempio n. 14
0
inline static int moveOV8825AF(unsigned long a_u4Position)
{
    int ret = 0;

    OV8825AFDB("a_u4Position = %d \n", a_u4Position);
    if((a_u4Position > g_u4OV8825AF_MACRO) || (a_u4Position < g_u4OV8825AF_INF))
    {
        OV8825AFDB("[OV8825AF] out of range \n");
        return -EINVAL;
    }

    if (g_s4OV8825AF_Opened == 1)
    {
        unsigned short InitPos;
        ret = s4OV8825AF_ReadReg(&InitPos);
	    
        spin_lock(&g_OV8825AF_SpinLock);
        if(ret == 0)
        {
            OV8825AFDB("[OV8825AF] Init Pos %6d \n", InitPos);
            g_u4CurrPosition = (unsigned long)InitPos;
        }
        else
        {		
            g_u4CurrPosition = 0;
        }
        g_s4OV8825AF_Opened = 2;
        spin_unlock(&g_OV8825AF_SpinLock);
    }

    if (g_u4CurrPosition < a_u4Position)
    {
        spin_lock(&g_OV8825AF_SpinLock);	
        g_i4Dir = 1;
        spin_unlock(&g_OV8825AF_SpinLock);	
    }
    else if (g_u4CurrPosition > a_u4Position)
    {
        spin_lock(&g_OV8825AF_SpinLock);	
        g_i4Dir = -1;
        spin_unlock(&g_OV8825AF_SpinLock);			
    }
    else										{return 0;}
    	
    	
    spin_lock(&g_OV8825AF_SpinLock);
    //g_i4Position = (long)g_u4CurrPosition;
    g_u4TargetPosition = a_u4Position;       
    g_sr = 3;
    g_i4MotorStatus = 0;
    spin_unlock(&g_OV8825AF_SpinLock);    

            
    if(abs(g_u4CurrPosition - g_u4TargetPosition) > MAX_MOVE_STEP)
    {
        OV8825AFDB("[OV8825AF] in small stepLeave breakdown \n");
        breakDownSteps(MAX_MOVE_STEP, MOVE_INTERVAL, g_u4CurrPosition, g_u4TargetPosition);
    } 
    else
    {   
        if(s4OV8825AF_WriteReg((unsigned short)g_u4TargetPosition) == 0)
        {
            spin_lock(&g_OV8825AF_SpinLock);      
            g_u4CurrPosition = (unsigned long)g_u4TargetPosition;
            spin_unlock(&g_OV8825AF_SpinLock);                
        }
        else
        {
            OV8825AFDB("[OV8825AF] set I2C failed when moving the motor \n");         
            spin_lock(&g_OV8825AF_SpinLock);
            g_i4MotorStatus = -1;
            spin_unlock(&g_OV8825AF_SpinLock);             
        }
    }

    return 0;
}