コード例 #1
0
static void rk29_adc_battery_lowpower_check(struct rk29_adc_battery_data *bat)
{
	int i;
	int level, oldlevel;
	struct rk29_adc_battery_platform_data *pdata = bat->pdata;

	printk("%s--%d:\n", __FUNCTION__, __LINE__);

	old_charge_level = -1;
	pSamples = bat->adc_samples;

	adc_sync_read(bat->client); //start adc sample
	level = oldlevel = rk29_adc_battery_status_samples(bat); //init charge status

	/* Fill sample buffer with values */
	bat->full_times = 0;
	for (i = 0; i < NUM_VOLTAGE_SAMPLE; i++) //0.3 s
	{
		mdelay(1);
		rk29_adc_battery_voltage_samples(bat); //get voltage
		//level = rk29_adc_battery_status_samples(bat);       //check charge status
		level = rk29_adc_battery_get_charge_level(bat);
		if (oldlevel != level)
		{
			oldlevel = level; //if charge status changed, reset sample
			i = 0;
		}
	}

	bat->bat_capacity = rk29_adc_battery_voltage_to_capacity(bat, bat->bat_voltageAvg);

	bat->bat_status = POWER_SUPPLY_STATUS_NOT_CHARGING;
	if (rk29_adc_battery_get_charge_level(bat))
	{
		bat->bat_status = POWER_SUPPLY_STATUS_CHARGING;
		if (pdata->charge_ok_pin != INVALID_GPIO)
		{
			if (gpio_get_value(pdata->charge_ok_pin) == pdata->charge_ok_level)
			{
				bat->bat_status = POWER_SUPPLY_STATUS_FULL;
				bat->bat_capacity = 100;
			}
		}
	}

#if 0
	rk29_adc_battery_poweron_capacity_check();
#else
	poweron_check = 1;
#endif

	/* Immediate power off for battery protection */
	if (bat->bat_voltageAvg <= (pdata->adc_bat_levels[BATT_ZERO_VOL_IDX] + 50))
	{
		printk("%umV -> low battery: powerdown (%u)\n", bat->bat_voltageAvg, pdata->adc_bat_levels[BATT_ZERO_VOL_IDX]+50);
		system_state = SYSTEM_POWER_OFF;
		pm_power_off();
	}
}
コード例 #2
0
static void adc_timer_work(struct work_struct *work)
{	
	int sync_read = 0;
	struct adc_test_data *test = container_of(work, struct adc_test_data,
						timer_work);
	adc_async_read(test->client);
	sync_read = adc_sync_read(test->client);
	dev_info(test->client->adc->dev, "[chn%d] sync_read = %d\n", 0, sync_read);
}
コード例 #3
0
/** Wakeup after power management standby.
 *
 * This function needs to fill the measurement buffer first
 * before the normal way of operation can be continued.
 */
static void rk29_adc_battery_resume_check(struct work_struct *work)
{
	int i;
	int level,oldlevel;
	int new_capacity, old_capacity;
	struct rk29_adc_battery_data *bat = gBatteryData;

	old_charge_level = -1;
	pSamples = bat->adc_samples;

	adc_sync_read(bat->client); //start adc sample
	level = oldlevel = rk29_adc_battery_status_samples(bat);//init charge status

	for (i = 0; i < NUM_VOLTAGE_SAMPLE; i++)	// 300 samples per s
	{
		mdelay(1);
		rk29_adc_battery_voltage_samples(bat); //get voltage
		level = rk29_adc_battery_status_samples(bat);//check charge status
		if (oldlevel != level)
		{
			oldlevel = level; //if charge status changed, reset sample
			i = 0;
		}
	}
	new_capacity = rk29_adc_battery_voltage_to_capacity(bat, bat->bat_voltageAvg);
	old_capacity = suspend_capacity;

#if 0
	if (bat->bat_status != POWER_SUPPLY_STATUS_NOT_CHARGING)
	{
		//chargeing state
		bat->bat_capacity = (new_capacity > old_capacity) ? new_capacity : old_capacity;
	}
	else
	{
		bat->bat_capacity = (new_capacity < old_capacity) ? new_capacity : old_capacity;
	}
#else
	bat->bat_capacity = new_capacity;
#endif
	printk("rk29_adc_battery_resume: status = %d, voltage = %d, capacity = %d, new_capacity = %d, old_capacity = %d\n",
			bat->bat_status, bat->bat_voltageNow, bat->bat_capacity, new_capacity, old_capacity);

	//start timer scan
	schedule_work(&bat->timer_work);
	bat->timer.expires = jiffies + 10;
	add_timer(&bat->timer);
}
コード例 #4
0
static void rk2918_low_battery_check(void)
{
    int i;
    int tmp = 0;
    
    for (i = 0; i < 100; i++)
    {
        tmp += adc_sync_read(gBatteryData->client);
        mdelay(1);
    }
    tmp = tmp / 100;
    //gBatteryData->adc_val = tmp;
    //gBatVoltage = (tmp * BAT_2V5_VALUE * (BAT_PULL_UP_R + BAT_PULL_DOWN_R)) / (1024 * BAT_PULL_DOWN_R);
    //rk2918_get_charge_status();
    //gBatCapacity = rk2918_get_bat_capacity_raw(gBatVoltage);
    rk2918_get_charge_status();
    tmp = (tmp * BAT_2V5_VALUE * (BAT_PULL_UP_R + BAT_PULL_DOWN_R)) / (1024 * BAT_PULL_DOWN_R);
	if(RK29_ADC_CLI_ADD)
		tmp += RK29_ADC_CLI_VALUE;
	else
		tmp -= RK29_ADC_CLI_VALUE;
    gBatCapacity = rk2918_get_bat_capacity_raw(tmp);
    if (gBatCapacity == 0) gBatCapacity = 1;
    printk("rk2918_low_battery_check: gBatVoltage = %d, gBatCapacity = %d\n", gBatVoltage, gBatCapacity);
    
    if (gBatVoltage <= BATT_ZERO_VOL_VALUE + 50)
    {
        printk("low battery: powerdown\n");
        gpio_direction_output(POWER_ON_PIN, GPIO_LOW);
        tmp = 0;
        while(1)
        {
            if(gpio_get_value(POWER_ON_PIN) == GPIO_HIGH)
		    {
			    gpio_set_value(POWER_ON_PIN,GPIO_LOW);
		    }
		    mdelay(5);
		    if (++tmp > 50) break;
		}
    }
    gpio_direction_output(POWER_ON_PIN, GPIO_HIGH);
}
コード例 #5
0
static void c5_lcd_detect()
{
	if (board_type != BOARD_C5)
		return;

	struct adc_client	*client;
	client = adc_register(2, wld_adc_callback, NULL);

	if (!client) {
		printk("adc_register failed\n");
		return;
	}
			
	int adc_val = adc_sync_read(client);
	if (adc_val < 10) {
		panel_type = PANEL_HX8394;	
	} else {
		panel_type = PANEL_MQ0801D;
	}
}
コード例 #6
0
/** Battery Monitor Initialization.
 *
 * When this function is called the driver probes and installs the
 * battery monitor driver.
 */
static int rk29_adc_battery_probe(struct platform_device *pdev)
{
	int ret;
	int irq;
	int irq_flag;
	struct adc_client *client;
	struct rk29_adc_battery_data *data;
	struct rk29_adc_battery_platform_data *pdata = pdev->dev.platform_data;

	printk("%s--%d:\n", __FUNCTION__, __LINE__);
	data = kzalloc(sizeof(*data), GFP_KERNEL);
	if (data == NULL)
	{
		ret = -ENOMEM;
		goto err_data_alloc_failed;
	}
	gBatteryData = data;
	platform_set_drvdata(pdev, data);

	ret = rk29_adc_battery_io_init(data, pdata);
	if (ret)
	{
		goto err_io_init;
	}

	/* Register ADC memory for battery sampling and mean value calc. */
	memset(data->adc_samples, 0, sizeof(int) * (NUM_VOLTAGE_SAMPLE + 2));
	client = adc_register(0, rk29_adc_battery_callback, NULL);
	if (!client)
		goto err_adc_register_failed;

	//variable init
	data->client = client;
	data->adc_val = adc_sync_read(client);

	/* Setup timers for ADC and battery work queues. */
	setup_timer(&data->timer, rk29_adc_battery_scan_timer, (unsigned long)data);
	data->timer.expires = jiffies + 2000; /* First start delayed by 2s to finish init. */
	add_timer(&data->timer);

	INIT_WORK(&data->timer_work, rk29_adc_battery_timer_work);
	INIT_WORK(&data->resume_work, rk29_adc_battery_resume_check);

#if defined(CONFIG_BATTERY_RK29_AC_CHARGE)
	//init dc dectet irq & delay work
	if (pdata->dc_det_pin != INVALID_GPIO)
	{
		irq = gpio_to_irq(pdata->dc_det_pin);

		irq_flag = gpio_get_value (pdata->dc_det_pin) ? IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING;
		ret = request_irq(irq, rk29_adc_battery_dc_wakeup, irq_flag, "rk29_adc_battery", NULL);
		if (ret)
		{
			printk("failed to request dc det irq\n");
			goto err_dcirq_failed;
		}
		enable_irq_wake(irq);

		INIT_WORK(&data->dcwakeup_work, rk29_adc_battery_dcdet_delaywork);
	}
#endif

	/* Power on Battery detection. */
	rk29_adc_battery_lowpower_check(data);

	/* Power supply register. */
	wake_lock_init(&batt_wake_lock, WAKE_LOCK_SUSPEND, "batt_lock");

	ret = power_supply_register(&pdev->dev, &rk29_battery_supply);
	if (ret)
	{
		printk(KERN_INFO "fail to battery power_supply_register\n");
		goto err_battery_failed;
	}

#if defined(CONFIG_BATTERY_RK29_AC_CHARGE)
	ret = power_supply_register(&pdev->dev, &rk29_ac_supply);
	if (ret)
	{
		printk(KERN_INFO "fail to ac power_supply_register\n");
		goto err_ac_failed;
	}
#endif

#if defined(CONFIG_BATTERY_RK29_USB_CHARGE)
	ret = power_supply_register(&pdev->dev, &rk29_usb_supply);
	if (ret)
	{
		printk(KERN_INFO "fail to usb power_supply_register\n");
		goto err_usb_failed;
	}
#endif

	printk(KERN_INFO "rk29_adc_battery: driver initialized\n");

	return 0;

#if defined(CONFIG_BATTERY_RK29_USB_CHARGE)
	err_usb_failed:
	power_supply_unregister(&rk29_usb_supply);
#endif

	err_ac_failed:
#if defined(CONFIG_BATTERY_RK29_AC_CHARGE)
	power_supply_unregister(&rk29_ac_supply);
#endif

err_battery_failed:
	power_supply_unregister(&rk29_battery_supply);

err_dcirq_failed:
	free_irq(gpio_to_irq(pdata->dc_det_pin), data);

err_adc_register_failed:
err_io_init:
err_data_alloc_failed:
	kfree(data);

	printk("rk29_adc_battery: error!\n");

	return ret;
}
コード例 #7
0
static int rk2918_battery_resume_get_Capacity(int deltatime)
{
	int i;
    int tmp = 0;
    int capacity = 0;

	for (i = 0; i < 20; i++)
    {
        tmp += adc_sync_read(gBatteryData->client);
        mdelay(1);
    }
    tmp = tmp / 20;
    //tmp = (tmp * BAT_2V5_VALUE * (BAT_PULL_UP_R + BAT_PULL_DOWN_R)) / (1024 * BAT_PULL_DOWN_R);
    tmp = adc_to_voltage(tmp);
    capacity = rk2918_get_bat_capacity_raw(tmp);
    //if last status is charging FULL, will return 100
	if(last_BatChargeStatus == POWER_SUPPLY_STATUS_FULL)
		return 100;
	//if last status is charging , and now still charging
    if ((gBatChargeStatus == 1) && (last_BatChargeStatus == 1))
    {
    	/*
        if (deltatime > (100 - gBatCapacity) * CHARGE_MIN_SECOND)
            deltatime = (100 - gBatCapacity) * CHARGE_MIN_SECOND;
        if (capacity > gBatCapacity + (deltatime / CHARGE_MIN_SECOND))       //采样电池容量偏差较大,将容量拉回
        {
            capacity = gBatCapacity + (deltatime / CHARGE_MIN_SECOND);
        }
		*/
		//
		if((gBatCapacity > 80))
		{
			capacity = gBatCapacity + deltatime/CHARGE_MID_SECOND;
		}
		else
		{
			/*some battery cannot arrive to 4.1V when charging full*/
			if((deltatime > (100 - gBatCapacity) * CHARGE_MID_SECOND))
			{
				capacity = 99;
				if (rk29_battery_dbg_level)
					printk("0000rk2918_battery_resume: last_BatChargeStatus: %d, gBatChargeStatus: %d, gBatVoltage = %d, gBatCapacity = %d, deltatime = %d, capacity = %d\n", 
	           			last_BatChargeStatus, gBatChargeStatus, gBatVoltage, gBatCapacity, deltatime, capacity);
				if (gBatStatus == POWER_SUPPLY_STATUS_FULL)
				{
					capacity = 100;
				}
   				return capacity;
			}
			/*if battery is not full after long charging*/
			if((capacity > 80))
			{
				if(capacity < gBatCapacity + deltatime/CHARGE_MID_SECOND)
					capacity = gBatCapacity + deltatime/CHARGE_MID_SECOND;
				if(capacity >= 100)
					capacity = 99;
				if (gBatStatus == POWER_SUPPLY_STATUS_FULL)
				{
					capacity = 100;
				}
				if (rk29_battery_dbg_level)
					printk("11111rk2918_battery_resume: last_BatChargeStatus: %d, gBatChargeStatus: %d, gBatVoltage = %d, gBatCapacity = %d, deltatime = %d, capacity = %d\n", 
		       			last_BatChargeStatus, gBatChargeStatus, gBatVoltage, gBatCapacity, deltatime, capacity);
				return capacity;
			}
			
			if(capacity > gBatCapacity)
	        {
	        	if((capacity-gBatCapacity)>15)
					gBatCapacity = capacity;
				else
				{
					if(gBatCapacity > 20)
					 	capacity=gBatCapacity;
					else
						gBatCapacity =(gBatCapacity + capacity)/2;
				}
	        }
	        else if (capacity < gBatCapacity)
	        {
	        	if((gBatCapacity - capacity)>10)
					gBatCapacity = capacity;
				else
					 capacity=gBatCapacity ;
	        }
		}
		if (capacity >= 100) 
			capacity = 99;
    }
    else
    {
    	/*
        if (deltatime > gBatCapacity * DISCHARGE_MIN_SECOND)
            deltatime = gBatCapacity * DISCHARGE_MIN_SECOND;            
        if (capacity < gBatCapacity - (deltatime / DISCHARGE_MIN_SECOND))    //采样电池容量偏差较大,将容量拉回
        {
            capacity = gBatCapacity - (deltatime / DISCHARGE_MIN_SECOND);
        }
		*/
		if (rk29_battery_dbg_level)
			printk("333rk2918_battery_resume: last_BatChargeStatus: %d, gBatChargeStatus: %d, gBatVoltage = %d, gBatCapacity = %d, deltatime = %d, capacity = %d\n", 
	           			last_BatChargeStatus, gBatChargeStatus, gBatVoltage, gBatCapacity, deltatime, capacity);
		/*to ensure battery show 100% after long charging during sleep and then pug out charger*/
		if((deltatime > (100 - gBatCapacity) * CHARGE_MID_SECOND) && (last_BatChargeStatus == 1))
		{
			if(capacity < 99)
				capacity = 99;
			if(capacity >= 100)
				capacity = 100;
			return capacity;
		}
		
        if (capacity < gBatCapacity)
        {
			if((gBatCapacity - capacity)>10)
				gBatCapacity = capacity;
			else
				 capacity=gBatCapacity ;
        }
        else if (capacity > gBatCapacity)
        {
        	if((capacity-gBatCapacity)>15)
				gBatCapacity = capacity;
			else
				 capacity=gBatCapacity ;
        }
    }
	
    if (capacity == 0) 
		capacity = 1;
    if (capacity >= 100) 
		capacity = 100;
    
    if (gBatStatus == POWER_SUPPLY_STATUS_FULL)
	{
	    capacity = 100;
	}
	if (rk29_battery_dbg_level)	
	    printk("rk2918_battery_resume: last_BatChargeStatus: %d, gBatChargeStatus: %d, gBatVoltage = %d, gBatCapacity = %d, deltatime = %d, ktmietmp.tv.sec = %lu, capacity = %d\n", 
	           last_BatChargeStatus, gBatChargeStatus, gBatVoltage, gBatCapacity, deltatime, batteryspendcnt, capacity);
    
    return capacity;
}
コード例 #8
0
static int rk2918_battery_load_capacity(void)
{
    int i;
    int tmp = 0;
	int  loadcapacity = 0;
	int  truecapacity = 0;
    char value[11];
    static char lastthree[6]= {0};
	char* p = value;
    struct file* fp = filp_open(BATT_FILENAME,O_RDONLY,0);
    
    //get true capacity
    for (i = 0; i < 20; i++)
    {
        tmp += adc_to_voltage(adc_sync_read(gBatteryData->client));
        mdelay(1);
    }
    tmp = tmp / 20;

	lastlost = tmp;
    truecapacity = rk2918_get_bat_capacity_raw(tmp);
    
	if(IS_ERR(fp))
    {
		printk("bryan---->open file /data/bat_last_capacity.dat failed\n");
		printk("truecapacity = %d\n", truecapacity);
		if(truecapacity>=100)
			truecapacity = 100;
	 	if(truecapacity==0)
			truecapacity=1;
		openfailflag = 1;

		if (openfailcount <= 5)
		{
			lastthree[openfailcount-1] = truecapacity;

			if (openfailcount == 1)
			{
				tmp = 0;
				for (i=0;i<5;i++)
				{
					tmp += lastthree[4-i];	
					printk("%s...............%d\n",__func__,tmp);
				}

				truecapacity = tmp/5;
				printk("%s...............%d\n",__func__,tmp);

			}
		}
		return truecapacity;
	}
	else
	{
		openfailflag = 0;
		openfailcount = 0;
	}
	kernel_read(fp,0,value,10);
    filp_close(fp,NULL);

	value[10]=0;
	while(*p)
	{
	    if(*p==0x0d)
	    {
			*p=0;
			break;
		}
		p++;
	}	
	sscanf(value,"%d",&loadcapacity);
	printk("bryan---->loadcapacity = %d, truecapacity = %d\n",loadcapacity, truecapacity);
	
    if ((loadcapacity <= 0) || (loadcapacity > 100))
	{
	    loadcapacity = truecapacity;
	}
	//如果从文件中读取的电压比实际的高很多的话,说明是长时间放置导致放电
	if (loadcapacity > truecapacity)
	{
	    if (loadcapacity - truecapacity > 20)
	    {
	        loadcapacity = truecapacity;
	    }
	}
	else
	{
		if ( ((truecapacity-loadcapacity) >= 20))
		{

			if (truecapacity < 30)
			{
				if (loadcapacity < 10)
				{
					loadcapacity = truecapacity/2;
				}
			}
			else
			{

				loadcapacity = truecapacity;	
				
			}

		}
	}
	    
	
	if (loadcapacity <= 0)
	{
		loadcapacity = 1;
	}
	if (loadcapacity >= 100)
	{
		loadcapacity = 100;
	}
	return loadcapacity;
}
コード例 #9
0
static int rk2918_battery_probe(struct platform_device *pdev)
{
	int ret;
	struct adc_client *client;
	struct rk2918_battery_data *data;
	struct rk2918_battery_platform_data *pdata = pdev->dev.platform_data;
	int irq_flag;
	int i = 0;
	
	data = kzalloc(sizeof(*data), GFP_KERNEL);
	if (data == NULL) {
		ret = -ENOMEM;
		goto err_data_alloc_failed;
	}
	gBatteryData = data;

    //clear io
    data->dc_det_pin     = INVALID_GPIO;
    data->batt_low_pin   = INVALID_GPIO;
    data->charge_set_pin = INVALID_GPIO;
	data->charge_ok_pin  = INVALID_GPIO;
	
	if (pdata && pdata->io_init) {
		ret = pdata->io_init();
		if (ret) 
			goto err_free_gpio1;		
	}
	
	//dc det
	if (pdata->dc_det_pin != INVALID_GPIO)
	{
	#ifndef DC_DET_WITH_USB_INT
    	ret = gpio_request(pdata->dc_det_pin, NULL);
    	if (ret) {
    		printk("failed to request dc_det gpio\n");
    		goto err_free_gpio1;
    	}
	#endif
		if(pdata->dc_det_level)
    		gpio_pull_updown(pdata->dc_det_pin, 0);//important
    	else
			gpio_pull_updown(pdata->dc_det_pin, GPIOPullUp);//important
    	ret = gpio_direction_input(pdata->dc_det_pin);
    	if (ret) {
    		printk("failed to set gpio dc_det input\n");
    		goto err_free_gpio1;
    	}
    	data->dc_det_pin   = pdata->dc_det_pin;
    	data->dc_det_level = pdata->dc_det_level;
    }

	if (pdata->charge_cur_ctl != INVALID_GPIO) {

		ret = gpio_request(pdata->charge_cur_ctl, "DC_CURRENT_CONTROL");
		if (ret < 0) {
    		printk("failed to request charge current control gpio\n");
    		goto err_free_gpio2;
		}

		ret = gpio_direction_output(pdata->charge_cur_ctl, !pdata->charge_cur_ctl_level);
		if (ret < 0) {
			printk("rk29_battery: failed to set charge current control gpio\n");
    		goto err_free_gpio2;
		}
		gpio_pull_updown(pdata->charge_cur_ctl, !pdata->charge_cur_ctl_level);
		gpio_set_value(pdata->charge_cur_ctl, !pdata->charge_cur_ctl_level);
		data->charge_cur_ctl = pdata->charge_cur_ctl;
		data->charge_cur_ctl_level = pdata->charge_cur_ctl_level;
	}
	
	//charge set for usb charge
	if (pdata->charge_set_pin != INVALID_GPIO)
	{
    	ret = gpio_request(pdata->charge_set_pin, NULL);
    	if (ret) {
    		printk("failed to request dc_det gpio\n");
    		goto err_free_gpio2;
    	}
    	data->charge_set_pin = pdata->charge_set_pin;
    	data->charge_set_level = pdata->charge_set_level;
    	gpio_direction_output(pdata->charge_set_pin, 1 - pdata->charge_set_level);
    }
	
	//charge_ok
	if (pdata->charge_ok_pin != INVALID_GPIO)
	{
        ret = gpio_request(pdata->charge_ok_pin, NULL);
    	if (ret) {
    		printk("failed to request charge_ok gpio\n");
    		goto err_free_gpio3;
    	}
	
    	gpio_pull_updown(pdata->charge_ok_pin, GPIOPullUp);//important
    	ret = gpio_direction_input(pdata->charge_ok_pin);
    	if (ret) {
    		printk("failed to set gpio charge_ok input\n");
    		goto err_free_gpio3;
    	}
    	data->charge_ok_pin   = pdata->charge_ok_pin;
    	data->charge_ok_level = pdata->charge_ok_level;
    }
    
	client = adc_register(0, rk2918_battery_callback, NULL);
    if(!client)
		goto err_adc_register_failed;
    
	memset(gBatVoltageSamples, 0, sizeof(gBatVoltageSamples));
	spin_lock_init(&data->lock);
    data->adc_val = adc_sync_read(client);
	data->client = client;
    data->battery.properties = rk2918_battery_props;
	data->battery.num_properties = ARRAY_SIZE(rk2918_battery_props);
	data->battery.get_property = rk2918_battery_get_property;
	data->battery.name = "battery";
	data->battery.type = POWER_SUPPLY_TYPE_BATTERY;
	data->adc_bat_divider = 414;
	data->bat_max = BATT_MAX_VOL_VALUE;
	data->bat_min = BATT_ZERO_VOL_VALUE;
	DBG("bat_min = %d\n",data->bat_min);
	
#ifdef RK29_USB_CHARGE_SUPPORT
	data->usb.properties = rk2918_usb_props;
	data->usb.num_properties = ARRAY_SIZE(rk2918_usb_props);
	data->usb.get_property = rk2918_usb_get_property;
	data->usb.name = "usb";
	data->usb.type = POWER_SUPPLY_TYPE_USB;
#endif

	data->ac.properties = rk2918_ac_props;
	data->ac.num_properties = ARRAY_SIZE(rk2918_ac_props);
	data->ac.get_property = rk2918_ac_get_property;
	data->ac.name = "ac";
	data->ac.type = POWER_SUPPLY_TYPE_MAINS;	
	
	rk2918_low_battery_check();
    
	ret = power_supply_register(&pdev->dev, &data->ac);
	if (ret)
	{
		printk(KERN_INFO "fail to ac power_supply_register\n");
		goto err_ac_failed;
	}
#if 0
	ret = power_supply_register(&pdev->dev, &data->usb);
	if (ret)
	{
		printk(KERN_INFO "fail to usb power_supply_register\n");
		goto err_usb_failed;
	}
#endif
	ret = power_supply_register(&pdev->dev, &data->battery);
	if (ret)
	{
		printk(KERN_INFO "fail to battery power_supply_register\n");
		goto err_battery_failed;
	}
	platform_set_drvdata(pdev, data);
	
	INIT_WORK(&data->timer_work, rk2918_battery_timer_work);
	
//    irq_flag = (pdata->charge_ok_level) ? IRQF_TRIGGER_RISING : IRQF_TRIGGER_FALLING;
//	ret = request_irq(gpio_to_irq(pdata->charge_ok_pin), rk2918_battery_interrupt, irq_flag, "rk2918_battery", data);
//	if (ret) {
//		printk("failed to request irq\n");
//		goto err_irq_failed;
//	}
#ifndef DC_DET_WITH_USB_INT
    if (pdata->dc_det_pin != INVALID_GPIO)
    {
        irq_flag = (!gpio_get_value (pdata->dc_det_pin)) ? IRQF_TRIGGER_RISING : IRQF_TRIGGER_FALLING;
    	ret = request_irq(gpio_to_irq(pdata->dc_det_pin), rk2918_dc_wakeup, irq_flag, "rk2918_battery", data);
    	if (ret) {
    		printk("failed to request dc det irq\n");
    		goto err_dcirq_failed;
    	}
    	data->dc_det_irq = gpio_to_irq(pdata->dc_det_pin);
    	//data->wq = create_rt_workqueue("rk2918_battery");
    	data->wq = create_workqueue("rk2918_battery");
    	INIT_DELAYED_WORK(&data->work, rk2918_battery_work);
    	
    	enable_irq_wake(gpio_to_irq(pdata->dc_det_pin));
    }
#endif

	setup_timer(&data->timer, rk2918_batscan_timer, (unsigned long)data);
	//data->timer.expires  = jiffies + 2000;
	//add_timer(&data->timer);
   
    rk29_battery_dbg_class = class_create(THIS_MODULE, "rk29_battery");
	battery_dev = device_create(rk29_battery_dbg_class, NULL, MKDEV(0, 1), NULL, "battery");
	ret = device_create_file(battery_dev, &dev_attr_rk29_battery_dbg);
	if (ret)
	{
		printk("create file sys failed!!! \n");
		//goto err_dcirq_failed;
	}
	for(i = 0; i<10; i++)
	{
		ret = device_create_file(&pdev->dev, &dev_attr_startget);
		if (ret)
		{
			printk("make a mistake in creating devices  attr file, failed times: %d\n\n ", i+1);
			continue;
		}
		break;
	}
	printk(KERN_INFO "rk2918_battery: driver initialized\n");
	
	return 0;
	
err_dcirq_failed:
    free_irq(gpio_to_irq(pdata->dc_det_pin), data);
    
err_irq_failed:
	free_irq(gpio_to_irq(pdata->charge_ok_pin), data);
    
err_battery_failed:
//	power_supply_unregister(&data->usb);
//err_usb_failed:
err_ac_failed:
	power_supply_unregister(&data->ac);
	
err_adc_register_failed:
err_free_gpio3:
	gpio_free(pdata->charge_ok_pin);
err_free_gpio2:
	gpio_free(pdata->charge_cur_ctl);
err_free_gpio1:
    gpio_free(pdata->dc_det_pin);
    
err_data_alloc_failed:
	kfree(data);

    printk("rk2918_battery: error!\n");
    
	return ret;
}
コード例 #10
0
static int rk2918_battery_resume_get_Capacity(int deltatime)
{
	int i;
    int tmp = 0;
    int capacity = 0;
	gFlagLoop = 0;
	pSamples = &gBatVoltageSamples[0];
    for (i = 0; i < 80; i++)
    {
        tmp += adc_sync_read(gBatteryData->client);
        mdelay(1);
    }
    tmp = tmp / 80;
    tmp = (tmp * BAT_2V5_VALUE * (BAT_PULL_UP_R + BAT_PULL_DOWN_R)) / (1024 * BAT_PULL_DOWN_R);
	if(RK29_ADC_CLI_ADD)
		tmp += RK29_ADC_CLI_VALUE;
	else
		tmp -= RK29_ADC_CLI_VALUE;
    capacity = rk2918_get_bat_capacity_raw(tmp);
	
    if (gBatChargeStatus == 1)
    {
    	/*
        if (deltatime > (100 - gBatCapacity) * CHARGE_MIN_SECOND)
            deltatime = (100 - gBatCapacity) * CHARGE_MIN_SECOND;
        if (capacity > gBatCapacity + (deltatime / CHARGE_MIN_SECOND))       //采样电池容量偏差较大,将容量拉回
        {
            capacity = gBatCapacity + (deltatime / CHARGE_MIN_SECOND);
        }
		*/
		//
		if(gBatCapacity > 80)
		{
			if(gBatChargeStatus == last_BatChargeStatus)
				capacity = gBatCapacity + deltatime/CHARGE_MID_SECOND;
		}
		else
		{
			/*some battery cannot arrive to 4.1V when charging full*/
			if((deltatime > (100 - gBatCapacity) * CHARGE_MID_SECOND) && (gBatChargeStatus == last_BatChargeStatus))
			{
				capacity = 99;
				printk("0000rk2918_battery_resume: last_BatChargeStatus: %d, gBatChargeStatus: %d, gBatVoltage = %d, gBatCapacity = %d, deltatime = %d, capacity = %d\n", 
           			last_BatChargeStatus, gBatChargeStatus, gBatVoltage, gBatCapacity, deltatime, capacity);
				if (gBatStatus == POWER_SUPPLY_STATUS_FULL)
				{
					capacity = 100;
				}
   				return capacity;
			}
			/*if battery is not full after long charging*/
			if((capacity > 80)&& (gBatChargeStatus == last_BatChargeStatus))
			{
				if(capacity < gBatCapacity + deltatime/CHARGE_MID_SECOND)
					capacity = gBatCapacity + deltatime/CHARGE_MID_SECOND;
				if(capacity >= 100)
					capacity = 99;
				if (gBatStatus == POWER_SUPPLY_STATUS_FULL)
				{
					capacity = 100;
				}
				printk("11111rk2918_battery_resume: last_BatChargeStatus: %d, gBatChargeStatus: %d, gBatVoltage = %d, gBatCapacity = %d, deltatime = %d, capacity = %d\n", 
           			last_BatChargeStatus, gBatChargeStatus, gBatVoltage, gBatCapacity, deltatime, capacity);
				return capacity;
			}
			
			if(capacity > gBatCapacity)
	        {
	        	if((capacity-gBatCapacity)>15)
					gBatCapacity = capacity;
				else
					 capacity=gBatCapacity ;
	        }
	        else if (capacity < gBatCapacity)
	        {
	        	if((gBatCapacity - capacity)>10)
					gBatCapacity = capacity;
				else
					 capacity=gBatCapacity ;
	        }
		}
		if (capacity >= 100) 
			capacity = 99;
    }
    else
    {
    	/*
        if (deltatime > gBatCapacity * DISCHARGE_MIN_SECOND)
            deltatime = gBatCapacity * DISCHARGE_MIN_SECOND;            
        if (capacity < gBatCapacity - (deltatime / DISCHARGE_MIN_SECOND))    //采样电池容量偏差较大,将容量拉回
        {
            capacity = gBatCapacity - (deltatime / DISCHARGE_MIN_SECOND);
        }
		*/
		
        if (capacity < gBatCapacity)
        {
			if((gBatCapacity - capacity)>10)
				gBatCapacity = capacity;
			else
				 capacity=gBatCapacity ;
        }
        else if (capacity > gBatCapacity)
        {
        	if((capacity-gBatCapacity)>15)
				gBatCapacity = capacity;
			else
				 capacity=gBatCapacity ;
        }
    }
	
    if (capacity == 0) 
		capacity = 1;
    if (capacity >= 100) 
		capacity = 100;
    
    if (gBatStatus == POWER_SUPPLY_STATUS_FULL)
	{
	    capacity = 100;
	}
		
    printk("rk2918_battery_resume: last_BatChargeStatus: %d, gBatChargeStatus: %d, gBatVoltage = %d, gBatCapacity = %d, deltatime = %d, ktmietmp.tv.sec = %lu, capacity = %d\n", 
           last_BatChargeStatus, gBatChargeStatus, gBatVoltage, gBatCapacity, deltatime, batteryspendcnt, capacity);
    
    return capacity;
}
コード例 #11
0
static int rk2918_battery_load_capacity(void)
{
    int i;
    int tmp = 0;
	int  loadcapacity = 0;
	int  truecapacity = 0;
    char value[11];
    static char lastthree[6]= {0};
	char* p = value;
	unsigned long spendcnt_intervals = 0;
	ktime_t ktimetmp; 
	
	ktimetmp = ktime_get_real();
    struct file* fp = filp_open(BATT_FILENAME,O_RDONLY,0);
    
    //get true capacity
    for (i = 0; i < 50; i++)
    {
        tmp += adc_sync_read(gBatteryData->client);
        mdelay(1);
    }
    tmp = tmp / 50;
    tmp = (tmp * BAT_2V5_VALUE * (BAT_PULL_UP_R + BAT_PULL_DOWN_R)) / (1024 * BAT_PULL_DOWN_R);
	
	if(RK29_ADC_CLI_ADD)
		tmp += RK29_ADC_CLI_VALUE;
	else
		tmp -= RK29_ADC_CLI_VALUE;
	
    truecapacity = rk2918_get_bat_capacity_raw(tmp);
    
	if(IS_ERR(fp))
    {
		printk("hj---->open file /data/bat_last_capacity.dat failed\n");
		printk("truecapacity = %d\n", truecapacity);
		
		if(truecapacity>=100)
			truecapacity = 100;
	 	if(truecapacity==0)
			truecapacity=1;
			
		openfailflag = 1;

		if (openfailcount <= 5)
		{
			lastthree[openfailcount-1] = truecapacity;

			if (openfailcount == 1)
			{
				tmp = 0;
				for (i=0;i<5;i++)
				{
					tmp += lastthree[4-i];	
					printk("%s...............%d\n",__func__,tmp);
				}

				truecapacity = tmp/5;
				printk("%s...............%d\n",__func__,tmp);

			}
		}
		return truecapacity;
	}
	else
	{
		openfailflag = 0;
		openfailcount = 0;
	}
	kernel_read(fp,0,value,10);
    filp_close(fp,NULL);

	value[10]=0;
	while(*p)
	{
	    if(*p==0x0d)
	    {
			*p=0;
			break;
		}
		p++;
	}	

	//spendcnt_intervals = ktimetmp.tv.sec - get_spendcnt_from_datefile();
	sscanf(value,"%d",&loadcapacity);
	printk("hj---->loadcapacity = %d, truecapacity = %d\n",loadcapacity, truecapacity);
	if((loadcapacity < 0) || (loadcapacity > 100))
		loadcapacity = truecapacity;
	// will show capacity in last poweroff if not more than 6 houre in off state
#if !(defined (CONFIG_MACH_M900) || defined (CONFIG_MACH_M900HD) || defined (CONFIG_MACH_M900HDW))
	if(( spendcnt_intervals < SPENDCNT_IN_OFF_STATE) && ((truecapacity-loadcapacity) < 25))
	{			
		if (loadcapacity == 0)
		{
			loadcapacity = 1;
		}
		else
		{
			if (loadcapacity >= 100)
			{
				loadcapacity = 100;
			}
		}	
		return loadcapacity;
	}
	printk("off state more than 1 housr\n");
#endif
	//如果从文件中读取的电压比实际的高很多的话,说明是长时间放置导致放电
	if (loadcapacity > truecapacity)
	{
	    if (loadcapacity - truecapacity > 20)
	    {
	        loadcapacity = truecapacity;
	    }
	}
	else
	{
		if ( ((truecapacity-loadcapacity) >= 20))
		{

			if (truecapacity < 30)
			{
				if (loadcapacity < 10)
				{
					loadcapacity = truecapacity/2;
				}
			}
			else
			{

				loadcapacity = truecapacity;	
				
			}

		}


	}
	    
	if (loadcapacity == 0)
	{
		loadcapacity = 1;
	}
	else
	{
		if (loadcapacity >= 100)
		{
			loadcapacity = 100;
		}
	}
	
	lastlost = loadcapacity;
	return loadcapacity;
}
コード例 #12
0
static int rk30_adc_probe(struct platform_device *pdev)
{
        struct adc_platform_data *pdata = pdev->dev.platform_data;
	struct adc_host *adc = NULL;
	struct rk30_adc_device *dev;
	struct resource *res;
	int ret = 0, i, v;

        if(!pdata)
                return -EINVAL;

	adc = adc_alloc_host(&pdev->dev, sizeof(struct rk30_adc_device), SARADC_CHN_MASK);
	if (!adc)
		return -ENOMEM;
	adc->ops = &rk30_adc_ops;
        adc->pdata = pdata;
	dev = adc_priv(adc);
	dev->adc = adc;
	dev->irq = platform_get_irq(pdev, 0);
	if (dev->irq <= 0) {
		dev_err(&pdev->dev, "failed to get adc irq\n");
		ret = -ENOENT;
		goto err_alloc;
	}

	ret = request_threaded_irq(dev->irq, NULL, rk30_adc_irq, IRQF_ONESHOT, pdev->name, dev);
	if (ret < 0) {
		dev_err(&pdev->dev, "failed to attach adc irq\n");
		goto err_alloc;
	}

	dev->pclk = clk_get(&pdev->dev, "pclk_saradc");
	if (IS_ERR(dev->pclk)) {
		dev_err(&pdev->dev, "failed to get adc pclk\n");
		ret = PTR_ERR(dev->pclk);
		goto err_irq;
	}
	clk_enable(dev->pclk);

	dev->clk = clk_get(&pdev->dev, "saradc");
	if (IS_ERR(dev->clk)) {
		dev_err(&pdev->dev, "failed to get adc clock\n");
		ret = PTR_ERR(dev->clk);
		goto err_pclk;
	}

	ret = clk_set_rate(dev->clk, ADC_CLK_RATE * 1000 * 1000);
	if(ret < 0) {
		dev_err(&pdev->dev, "failed to set adc clk\n");
		goto err_clk2;
	}
	clk_enable(dev->clk);

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res) {
		dev_err(&pdev->dev, "cannot find IO resource\n");
		ret = -ENOENT;
		goto err_clk;
	}
	dev->ioarea = request_mem_region(res->start, (res->end - res->start) + 1, 
									pdev->name);
	if(dev->ioarea == NULL) {
		dev_err(&pdev->dev, "cannot request IO\n");
		ret = -ENXIO;
		goto err_clk;
	}
	dev->regs = ioremap(res->start, (res->end - res->start) + 1);
	if (!dev->regs) {
		dev_err(&pdev->dev, "cannot map IO\n");
		ret = -ENXIO;
		goto err_ioarea;
	}
        g_adc = adc;
	platform_set_drvdata(pdev, dev);

        if(adc->pdata->base_chn > 0){
                adc->base_client = adc_register(adc->pdata->base_chn, NULL, NULL);
                if(!adc->base_client){
		        dev_err(&pdev->dev, "adc_register(base_chn: %d) failed\n", adc->pdata->base_chn);
                        ret = -ENOMEM;
                        goto err_adc_register;
                }
                for(i = 0; i < SAMPLE_COUNT; i++){
                        v = adc_sync_read(adc->base_client);
                        if(v < 0){
		                dev_err(&pdev->dev, "adc_register(base_chn: %d) failed\n", adc->pdata->base_chn);
                                ret = v;
                                goto err_adc_sync_read;
                        }else if(v < MIN_SAMPLE_VALUE){
		                dev_info(&pdev->dev, "chn[%d]: adc value(%d) is invalide\n", adc->pdata->base_chn, v);
                                adc_unregister(adc->base_client);
                                adc->base_client = NULL;
                                break;
                        }
                        adc_dbg(&pdev->dev, "read ref_adc: %d\n", v);
                        mdelay(1);
                }
        }
	dev_info(&pdev->dev, "rk30 adc: driver initialized\n");
	return 0;
err_adc_sync_read:
        adc_unregister(adc->base_client);
        adc->base_client = NULL;
err_adc_register:
	iounmap(dev->regs);
err_ioarea:
	release_resource(dev->ioarea);
	kfree(dev->ioarea);

err_clk:
	clk_disable(dev->clk);

err_pclk:
	clk_disable(dev->pclk);
	clk_put(dev->pclk);

err_clk2:
	clk_put(dev->clk);

err_irq:
	free_irq(dev->irq, dev);

err_alloc:
        adc_free_host(dev->adc);
	return ret;
}
コード例 #13
0
static int rk2918_battery_resume_get_Capacity(int deltatime)
{
	int i;
	int tmp = 0;
	int capacity = 0;
	int num = 0;
	int voltagetmp = 0;
	pSamples = &gBatVoltageSamples[0];
    
    for (i = 0; i < 50; i++)
    {
         voltagetmp = adc_sync_read(gBatteryData->client);
         *pSamples = (voltagetmp * BAT_2V5_VALUE * (BAT_PULL_UP_R + BAT_PULL_DOWN_R)) / (1024 * BAT_PULL_DOWN_R);
	 	 tmp = tmp + *pSamples++;	
          mdelay(1);
    }

    tmp = tmp / 50;
    //tmp = (tmp * BAT_2V5_VALUE * (BAT_PULL_UP_R + BAT_PULL_DOWN_R)) / (1024 * BAT_PULL_DOWN_R);
    capacity = rk2918_get_bat_capacity_raw(tmp);
    printk("rk2918_battery_resume:%d,%d,%d,%d\n",capacity,gBatCapacity,tmp,gBatChargeStatus);
    if (gBatChargeStatus == 1)
    {
        //if (deltatime > (100 - gBatCapacity) * CHARGE_MIN_SECOND)
        //    deltatime = (100 - gBatCapacity) * CHARGE_MIN_SECOND;
       // if (capacity > gBatCapacity + (deltatime / CHARGE_MIN_SECOND))       //采样电池容量偏差较大,将容量拉回
        //{
       //     capacity = gBatCapacity + (deltatime / CHARGE_MIN_SECOND);
      //  }
        if(capacity > gBatCapacity)
        {
        	if((capacity-gBatCapacity)>5)
				gBatCapacity = capacity;
			else
			   capacity=gBatCapacity ;
        }
        else 
        {            	
			capacity = gBatCapacity;		
        }

		if ((gpio_get_value(gBatteryData->charge_ok_pin) ==  gBatteryData->charge_ok_level))
			{
				capacity = 100;
				gBatStatus = POWER_SUPPLY_STATUS_FULL;
				 gBatteryData->full_times = NUM_CHARGE_FULL_DELAY_TIMES + 1;
			}
    }
    else
    {
        //if (deltatime > gBatCapacity * DISCHARGE_MIN_SECOND)
           // deltatime = gBatCapacity * DISCHARGE_MIN_SECOND;            
        //if (capacity < gBatCapacity - (deltatime / DISCHARGE_MIN_SECOND))    //采样电池容量偏差较大,将容量拉回
        //{
          //  capacity = gBatCapacity - (deltatime / DISCHARGE_MIN_SECOND);
        //}
        if (capacity < gBatCapacity)
        {
			if((capacity-gBatCapacity)>5)
				gBatCapacity = capacity;
			else
			    capacity=gBatCapacity ;
        }
        else 
        {        	
			 capacity=gBatCapacity ;
        }
    }
    if (capacity == 0) capacity = 1;
    if (capacity >= 100) capacity = 100;
    
    if (gBatStatus == POWER_SUPPLY_STATUS_FULL)
   {
	    capacity = 100;
    }
		
    printk("rk2918_battery_resume: gBatVoltage = %d, gBatCapacity = %d, deltatime = %d, ktmietmp.tv.sec = %ul, capacity = %d,gFlagLoop=%d\n", 
           gBatVoltage, gBatCapacity, deltatime, batteryspendcnt, capacity,gFlagLoop);
    
    return capacity;
}
コード例 #14
0
static int rk2918_battery_load_capacity(void)
{
    int i;
    int tmp = 0;
	int  loadcapacity = 0;
	int  truecapacity = 0;
    char value[11];
    static char lastthree[6]= {0};
	char* p = value;
	int flag = dwc_vbus_status();
    struct file* fp = filp_open(BATT_FILENAME,O_RDONLY,0);
  
    
    //get true capacity
    for (i = 0; i < 30; i++)
    {
        tmp += adc_sync_read(gBatteryData->client);
        mdelay(1);
    }
    tmp = tmp / 30;
    tmp = (tmp * BAT_2V5_VALUE * (BAT_PULL_UP_R + BAT_PULL_DOWN_R)) / (1024 * BAT_PULL_DOWN_R);
    truecapacity = rk2918_get_bat_capacity_raw(tmp);
 	
	
	if(IS_ERR(fp))
    {
		printk("hj---->open file /data/bat_last_capacity.dat failed\n");
		printk("truecapacity = %d\n", truecapacity);
		
		if(truecapacity>=100)
			truecapacity = 100;
	 	if(truecapacity==0)
			truecapacity=1;
#if 0
	if (flag == 1)
	{
		if (truecapacity > 60)
			truecapacity -= 35;
	}
#endif
		openfailflag = 1;

		if (openfailcount <= 5)
		{
			lastthree[openfailcount-1] = truecapacity;

			if (openfailcount == 1)
			{
				tmp = 0;
				for (i=0;i<5;i++)
				{
					tmp += lastthree[4-i];	
					printk("%s...............%d\n",__func__,tmp);
				}

				truecapacity = tmp/5;
				printk("%s...............%d\n",__func__,tmp);

			}
		}
		return truecapacity;
	}
	else
	{
		openfailflag = 0;
		openfailcount = 0;
	}


	kernel_read(fp,0,value,10);
    filp_close(fp,NULL);

	value[10]=0;
	while(*p)
	{
	    if(*p==0x0d)
	    {
			*p=0;
			break;
		}
		p++;
	}	
	sscanf(value,"%d",&loadcapacity);
	printk("hj---->loadcapacity = %d, truecapacity = %d\n",loadcapacity, truecapacity);
	
	//如果从文件中读取的电压比实际的高很多的话,说明是长时间放置导致放电
#if 0
	if (loadcapacity > truecapacity)
	{
	    if ((loadcapacity - truecapacity) > 15)
	    {
	        loadcapacity = truecapacity;
	    }
	}
	else
#endif

	{

		if (((truecapacity-loadcapacity) >= 25))
		{

			if (truecapacity < 30)
			{
				if (loadcapacity < 10)
				{
					loadcapacity = truecapacity/4;
				}
			}
			else
			{
				if (truecapacity < 80)
					loadcapacity = truecapacity - 8;
				else
					loadcapacity = truecapacity;
				
			}

		}
	}
	    
	if (loadcapacity == 0)
	{
		loadcapacity = 1;
	}
	else
	{
		if (loadcapacity >= 100)
		{
			loadcapacity = 99;
		}
	}
/*
	if (gpio_get_value(gBatteryData->charge_ok_pin) ==  gBatteryData->charge_ok_level)
	{
		loadcapacity = 99;
	}

	if (gBatStatus == POWER_SUPPLY_STATUS_FULL)
	{	
		loadcapacity = 100;
	}

*/
	lastlost = loadcapacity;
	return loadcapacity;
}
コード例 #15
0
static int rockchip_headsetobserve_probe(struct platform_device *pdev)
{
	int ret;
	struct headset_priv *headset;
	struct rk_headset_pdata *pdata;

	headset = kzalloc(sizeof(struct headset_priv), GFP_KERNEL);
	if (headset == NULL) {
		dev_err(&pdev->dev, "failed to allocate driver data\n");
		return -ENOMEM;
	}
	headset_info = headset;
	headset->pdata = pdev->dev.platform_data;
	pdata = headset->pdata;
	headset->headset_status = HEADSET_OUT;
	headset->heatset_irq_working = IDLE;
	headset->hook_status = HOOK_UP;
	headset->hook_time = HOOK_ADC_SAMPLE_TIME;
	headset->cur_headset_status = 0;
	headset->sdev.name = "h2w";
	headset->sdev.print_name = h2w_print_name;
	ret = switch_dev_register(&headset->sdev);
	if (ret < 0)
		goto failed_free;
	
//	mutex_init(&headset->mutex_lock[HEADSET]);
//	mutex_init(&headset->mutex_lock[HOOK]);
	wake_lock_init(&headset->headset_on_wake, WAKE_LOCK_SUSPEND, "headset_on_wake");
	INIT_DELAYED_WORK(&headset->h_delayed_work[HEADSET], headsetobserve_work);

	headset->isMic = 0;
//------------------------------------------------------------------		
	// Create and register the input driver. 
	headset->input_dev = input_allocate_device();
	if (!headset->input_dev) {
		dev_err(&pdev->dev, "failed to allocate input device\n");
		ret = -ENOMEM;
		goto failed_free;
	}	
	headset->input_dev->name = pdev->name;
	headset->input_dev->open = rk_Hskey_open;
	headset->input_dev->close = rk_Hskey_close;
	headset->input_dev->dev.parent = &pdev->dev;
	//input_dev->phys = KEY_PHYS_NAME;
	headset->input_dev->id.vendor = 0x0001;
	headset->input_dev->id.product = 0x0001;
	headset->input_dev->id.version = 0x0100;
	// Register the input device 
	ret = input_register_device(headset->input_dev);
	if (ret) {
		dev_err(&pdev->dev, "failed to register input device\n");
		goto failed_free_dev;
	}

	input_set_capability(headset->input_dev, EV_KEY, pdata->hook_key_code);
//------------------------------------------------------------------
	if (pdata->Headset_gpio) {
		ret = pdata->headset_io_init(pdata->Headset_gpio, pdata->headset_gpio_info.iomux_name, pdata->headset_gpio_info.iomux_mode);
		if (ret) 
			goto failed_free;

		headset->irq[HEADSET] = gpio_to_irq(pdata->Headset_gpio);

		if(pdata->headset_in_type == HEADSET_IN_HIGH)
			headset->irq_type[HEADSET] = IRQF_TRIGGER_HIGH|IRQF_ONESHOT;
		else
			headset->irq_type[HEADSET] = IRQF_TRIGGER_LOW|IRQF_ONESHOT;
		ret = request_threaded_irq(headset->irq[HEADSET], NULL,headset_interrupt, headset->irq_type[HEADSET]|IRQF_NO_SUSPEND, "headset_input", NULL);
		if (ret) 
			goto failed_free;
		enable_irq_wake(headset->irq[HEADSET]);
	}
	else
		goto failed_free;
//------------------------------------------------------------------
	if(pdata->Hook_adc_chn>=0 && 3>=pdata->Hook_adc_chn)
	{
		headset->client = adc_register(pdata->Hook_adc_chn, hook_adc_callback, (void *)headset);
		if(!headset->client) {
			printk("hook adc register error\n");
			ret = -EINVAL;
			goto failed_free;
		}
		setup_timer(&headset->hook_timer,hook_timer_callback, (unsigned long)headset);	
		printk("headset adc default value = %d\n",adc_sync_read(headset->client));
	}
	
#ifdef CONFIG_HAS_EARLYSUSPEND
	hs_early_suspend.suspend = NULL;
	hs_early_suspend.resume = headset_early_resume;
	hs_early_suspend.level = ~0x0;
	register_early_suspend(&hs_early_suspend);
#endif

	return 0;	
	
failed_free_dev:
	platform_set_drvdata(pdev, NULL);
	input_free_device(headset->input_dev);
failed_free:
	dev_err(&pdev->dev, "failed to headset probe\n");
	kfree(headset);
	return ret;
}
コード例 #16
0
//1
static irqreturn_t headset_interrupt(int irq, void *dev_id)
{
	struct rk_headset_pdata *pdata = headset_info->pdata;
	static unsigned int old_status = 0;
	int i,level = 0;	
	int adc_value = 0;
	wake_lock(&headset_info->headset_on_wake);
	if(headset_info->heatset_irq_working == BUSY || headset_info->heatset_irq_working == WAIT)
		return IRQ_HANDLED;
	DBG("In the headset_interrupt for read headset level  wake_lock headset_on_wake\n");		
	headset_info->heatset_irq_working = BUSY;
	msleep(150);
	for(i=0; i<3; i++)
	{
		level = gpio_get_value(pdata->Headset_gpio);
		if(level < 0)
		{
			printk("%s:get pin level again,pin=%d,i=%d\n",__FUNCTION__,pdata->Headset_gpio,i);
			msleep(1);
			continue;
		}
		else
		break;
	}
	if(level < 0)
	{
		printk("%s:get pin level  err!\n",__FUNCTION__);
		goto out;
	}

	old_status = headset_info->headset_status;
	switch(pdata->headset_in_type)
	{
	case HEADSET_IN_HIGH:
		if(level > 0)
			headset_info->headset_status = HEADSET_IN;
		else if(level == 0)
			headset_info->headset_status = HEADSET_OUT;	
		break;
	case HEADSET_IN_LOW:
		if(level == 0)
			headset_info->headset_status = HEADSET_IN;
		else if(level > 0)
			headset_info->headset_status = HEADSET_OUT;		
		break;			
	default:
		DBG("---- ERROR: on headset headset_in_type error -----\n");
		break;			
	}
	if(old_status == headset_info->headset_status)
	{
		DBG("Read Headset IO level old status == now status\n");
		goto out;
	}

	DBG("(headset in is %s)headset status is %s\n",
		pdata->headset_in_type?"high level":"low level",
		headset_info->headset_status?"in":"out");
	if(headset_info->headset_status == HEADSET_IN)
	{
		#if 0
		while(1)
		{
			if(adc_sync_read(headset_info->client) > HOOK_DEFAULT_VAL
			 || adc_sync_read(headset_info->client) < 0)
			{
				printk("headset is showly inside\n");
			}
			else
				break;
			msleep(50);
			
			if(pdata->headset_in_type == HEADSET_IN_HIGH)
				old_status = headset_info->headset_status = gpio_get_value(pdata->Headset_gpio)?HEADSET_IN:HEADSET_OUT;
			else
				old_status = headset_info->headset_status = gpio_get_value(pdata->Headset_gpio)?HEADSET_OUT:HEADSET_IN;
			if(headset_info->headset_status == HEADSET_OUT)
				goto out1;
			msleep(5);	
		}
		#endif
		if(pdata->Hook_adc_chn>=0 && 3>=pdata->Hook_adc_chn)
		{
		// wait for find Hook key
			//#ifdef CONFIG_SND_SOC_RT5625
			CHECK_AGAIN:
			//headset_info->isMic = rt5625_headset_mic_detect(true);
			#ifdef CONFIG_SND_SOC_WM8994
			wm8994_headset_mic_detect(true);
			#endif
			#if defined (CONFIG_SND_SOC_RT3261) || defined (CONFIG_SND_SOC_RT3224)
			rt3261_headset_mic_detect(true);
			#endif
			#ifdef CONFIG_SND_SOC_RT5631_PHONE
			rt5631_headset_mic_detect(true);
			#endif			
			//mdelay(400);
			adc_value = adc_sync_read(headset_info->client);
			if(adc_value >= 0 && adc_value < HOOK_LEVEL_LOW)
			{
				headset_info->isMic= 0;//No microphone
				#ifdef CONFIG_SND_SOC_WM8994
				wm8994_headset_mic_detect(false);
				#endif
				#if defined (CONFIG_SND_SOC_RT3261) || defined (CONFIG_SND_SOC_RT3224)
				rt3261_headset_mic_detect(false);
				#endif	
				#ifdef CONFIG_SND_SOC_RT5631_PHONE
				rt5631_headset_mic_detect(false);
				#endif					
			}	
			else if(adc_value >= HOOK_LEVEL_HIGH)
				headset_info->isMic = 1;//have mic

			if(headset_info->isMic < 0)	
			{
				printk("codec is error\n");
				headset_info->heatset_irq_working = WAIT;
				if(pdata->headset_in_type == HEADSET_IN_HIGH)
					irq_set_irq_type(headset_info->irq[HEADSET],IRQF_TRIGGER_LOW|IRQF_ONESHOT);
				else
					irq_set_irq_type(headset_info->irq[HEADSET],IRQF_TRIGGER_HIGH|IRQF_ONESHOT);
				schedule_delayed_work(&headset_info->h_delayed_work[HEADSET], msecs_to_jiffies(0));	
				wake_unlock(&headset_info->headset_on_wake);
				return IRQ_HANDLED;
			}
			//adc_value = adc_sync_read(headset_info->client);
			printk("headset adc value = %d\n",adc_value);
			if(headset_info->isMic) {
				if(adc_value > HOOK_DEFAULT_VAL || adc_value < HOOK_LEVEL_HIGH)
					goto CHECK_AGAIN;
				mod_timer(&headset_info->hook_timer, jiffies + msecs_to_jiffies(1000));
			}	
			//#endif		
			headset_info->cur_headset_status = headset_info->isMic ? BIT_HEADSET:BIT_HEADSET_NO_MIC;
		}
		else
		{
			headset_info->isMic= 0;//No microphone
			headset_info->cur_headset_status = BIT_HEADSET_NO_MIC;
		}
		printk("headset->isMic = %d\n",headset_info->isMic);		
		if(pdata->headset_in_type == HEADSET_IN_HIGH)
			irq_set_irq_type(headset_info->irq[HEADSET],IRQF_TRIGGER_FALLING);
		else
			irq_set_irq_type(headset_info->irq[HEADSET],IRQF_TRIGGER_RISING);
	}
	else if(headset_info->headset_status == HEADSET_OUT)
	{
		headset_info->cur_headset_status = ~(BIT_HEADSET|BIT_HEADSET_NO_MIC);
		del_timer(&headset_info->hook_timer);
		if(headset_info->isMic)
		{
			headset_info->hook_status = HOOK_UP;
			#ifdef CONFIG_SND_SOC_WM8994
			//rt5625_headset_mic_detect(false);
			wm8994_headset_mic_detect(false);
			#endif
			#if defined (CONFIG_SND_SOC_RT3261) || defined (CONFIG_SND_SOC_RT3224)
			rt3261_headset_mic_detect(false);
			#endif
			#ifdef CONFIG_SND_SOC_RT5631_PHONE
			rt5631_headset_mic_detect(false);
			#endif				
		}	
		if(pdata->headset_in_type == HEADSET_IN_HIGH)
			irq_set_irq_type(headset_info->irq[HEADSET],IRQF_TRIGGER_RISING);
		else
			irq_set_irq_type(headset_info->irq[HEADSET],IRQF_TRIGGER_FALLING);			
	}	

	rk28_send_wakeup_key();			
	switch_set_state(&headset_info->sdev, headset_info->cur_headset_status);	
	DBG("headset notice android headset status = %d\n",headset_info->cur_headset_status);	

//	schedule_delayed_work(&headset_info->h_delayed_work[HEADSET], msecs_to_jiffies(0));
out:
	headset_info->heatset_irq_working = IDLE;
	wake_unlock(&headset_info->headset_on_wake);
	return IRQ_HANDLED;
}