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(); } }
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); }
/** 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); }
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); }
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; } }
/** 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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
//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; }