static int gp2a_i2c_remove(struct i2c_client *client) { struct gp2a_data *gp2a = i2c_get_clientdata(client); sysfs_remove_group(&gp2a->light_input_dev->dev.kobj, &light_attribute_group); input_unregister_device(gp2a->light_input_dev); sysfs_remove_group(&gp2a->proximity_input_dev->dev.kobj, &proximity_attribute_group); input_unregister_device(gp2a->proximity_input_dev); platform_device_unregister(pdev_gp2a_adc); free_irq(gp2a->irq, NULL); gpio_free(gp2a->pdata->p_out); if (gp2a->power_state) { if (gp2a->power_state & LIGHT_ENABLED) gp2a_light_disable(gp2a); /* gp2a->pdata->power(false); */ } destroy_workqueue(gp2a->wq); mutex_destroy(&gp2a->power_mutex); mutex_destroy(&gp2a->adc_mutex); wake_lock_destroy(&gp2a->prx_wake_lock); s3c_adc_release(gp2a->padc); kfree(gp2a); return 0; }
static int __devexit exynos_adc_remove(struct platform_device *dev) { misc_deregister(&misc); s3c_adc_release(adcdev.client); return 0; }
void remove_temphumidity_factorytest(struct ssp_data *data) { if (data->adc_client) s3c_adc_release(data->adc_client); if (data->pdev_pam_temp) platform_device_put(data->pdev_pam_temp); sensors_unregister(data->temphumidity_device, temphumidity_attrs); kfree(data->comp_engine_ver); ssp_temphumidity_fops.unlocked_ioctl = NULL; misc_deregister(&data->shtc1_device); }
static int __devexit s3c_hwmon_remove(struct platform_device *dev) { struct s3c_hwmon *hwmon = platform_get_drvdata(dev); int i; s3c_hwmon_remove_raw(&dev->dev); for (i = 0; i < ARRAY_SIZE(hwmon->attrs); i++) s3c_hwmon_remove_attr(&dev->dev, &hwmon->attrs[i]); hwmon_device_unregister(hwmon->hwmon_dev); s3c_adc_release(hwmon->client); return 0; }
static int __devexit sec_therm_remove(struct platform_device *pdev) { struct sec_therm_info *info = platform_get_drvdata(pdev); if (!info) return 0; sysfs_remove_group(&info->dev->kobj, &sec_therm_group); cancel_delayed_work(&info->polling_work); s3c_adc_release(info->padc); kfree(info); return 0; }
static int fl2440adc_release(struct inode *inodp, struct file *filp) { int channel; DPRINTK("File operations release...\n"); channel = MINOR(inodp->i_rdev); mutex_lock(&adc_dev.mutex); if(!(atomic_add_unless(&adc_dev.client_ref[channel], -1, 0))) { s3c_adc_release(adc_dev.client[channel]); adc_dev.client[channel] = NULL; } mutex_unlock(&adc_dev.mutex); return 0; }
static int instinctq_battery_remove(struct platform_device *pdev) { struct instinctq_battery *bat = platform_get_drvdata(pdev); struct instinctq_battery_pdata *pdata = bat->pdata; int i; disable_irq_wake(bat->irq_pok); free_irq(IRQ_BATF, bat); free_irq(bat->irq_pok, bat); if (pdata->supply_detect_cleanup) pdata->supply_detect_cleanup(); for (i = 0; i < ARRAY_SIZE(battery_attrs); ++i) device_remove_file(bat->bat.dev, battery_attrs[i]); power_supply_unregister(&bat->bat); #ifdef CONFIG_HAS_WAKELOCK device_remove_file(bat->psy[instinctq_BATTERY_AC].dev, &dev_attr_suspend_lock); #endif for (i = 0; i < instinctq_BATTERY_NUM; ++i) power_supply_unregister(&bat->psy[i]); cancel_work_sync(&bat->work); cancel_delayed_work_sync(&bat->poll_work); destroy_workqueue(bat->workqueue); s3c_adc_release(bat->client); kfree(bat->temp_lookup.table); kfree(bat->volt_lookup.table); kfree(bat->percent_lookup.table); gpio_set_value(pdata->gpio_en, pdata->gpio_en_inverted); #ifdef CONFIG_HAS_WAKELOCK wake_lock_destroy(&bat->fault_wakelock); wake_lock_destroy(&bat->chg_wakelock); wake_lock_destroy(&bat->wakelock); wake_lock_destroy(&bat->suspend_lock); #endif kfree(bat); return 0; }
static int s3c_adc_bat_remove(struct platform_device *pdev) { struct s3c_adc_client *client = platform_get_drvdata(pdev); struct s3c_adc_bat_pdata *pdata = pdev->dev.platform_data; power_supply_unregister(&main_bat.psy); if (pdata->backup_volt_mult) power_supply_unregister(&backup_bat.psy); s3c_adc_release(client); if (pdata->gpio_charge_finished >= 0) { free_irq(gpio_to_irq(pdata->gpio_charge_finished), NULL); gpio_free(pdata->gpio_charge_finished); } cancel_delayed_work(&bat_work); if (pdata->exit) pdata->exit(); return 0; }
static int __devexit gpio_switch_remove(struct platform_device *pdev) { struct gpio_switch_data *switch_data = platform_get_drvdata(pdev); if (is_adc_timer_on) del_timer(&detect_mic_adc_timer); cancel_delayed_work_sync(&switch_data->del_work); cancel_work_sync(&mic_adc_work); input_unregister_device(mic_input_dev); gpio_free(switch_data->gpio); switch_dev_unregister(&switch_data->sdev); kfree(switch_data); gpio_free(switch_data->gpio); switch_dev_unregister(&switch_data->sdev); kfree(switch_data); s3c_adc_release(switch_data->client); return 0; }
static int instinctq_battery_probe(struct platform_device *pdev) { struct s3c_adc_client *client; struct instinctq_battery_pdata *pdata = pdev->dev.platform_data; struct instinctq_battery *bat; int ret, i, irq; /* Platform data is required */ if (!pdata) { dev_err(&pdev->dev, "no platform data supplied\n"); return -ENODEV; } /* Check GPIOs */ if (!gpio_is_valid(pdata->gpio_pok)) { dev_err(&pdev->dev, "Invalid gpio pin for POK line\n"); return -EINVAL; } if (!gpio_is_valid(pdata->gpio_chg)) { dev_err(&pdev->dev, "Invalid gpio pin for CHG line\n"); return -EINVAL; } if (!gpio_is_valid(pdata->gpio_en)) { dev_err(&pdev->dev, "Invalid gpio pin for EN line\n"); return -EINVAL; } if (!pdata->supply_detect_init) { dev_err(&pdev->dev, "Supply detection is required\n"); return -EINVAL; } /* Register ADC client */ client = s3c_adc_register(pdev, NULL, NULL, 0); if (IS_ERR(client)) { dev_err(&pdev->dev, "could not register adc\n"); return PTR_ERR(client); } /* Allocate driver data */ bat = kzalloc(sizeof(struct instinctq_battery), GFP_KERNEL); if (!bat) { dev_err(&pdev->dev, "could not allocate driver data\n"); ret = -ENOMEM; goto err_free_adc; } /* Claim and setup GPIOs */ ret = gpio_request(pdata->gpio_pok, dev_name(&pdev->dev)); if (ret) { dev_err(&pdev->dev, "Failed to request POK pin: %d\n", ret); goto err_free; } ret = gpio_direction_input(pdata->gpio_pok); if (ret) { dev_err(&pdev->dev, "Failed to set POK to input: %d\n", ret); goto err_gpio_pok_free; } ret = gpio_request(pdata->gpio_chg, dev_name(&pdev->dev)); if (ret) { dev_err(&pdev->dev, "Failed to request CHG pin: %d\n", ret); goto err_gpio_pok_free; } ret = gpio_direction_input(pdata->gpio_chg); if (ret) { dev_err(&pdev->dev, "Failed to set CHG to input: %d\n", ret); goto err_gpio_chg_free; } ret = gpio_request(pdata->gpio_en, dev_name(&pdev->dev)); if (ret) { dev_err(&pdev->dev, "Failed to request EN pin: %d\n", ret); goto err_gpio_chg_free; } ret = gpio_direction_output(pdata->gpio_en, pdata->gpio_en_inverted); if (ret) { dev_err(&pdev->dev, "Failed to set EN to output: %d\n", ret); goto err_gpio_en_free; } platform_set_drvdata(pdev, bat); bat->dev = &pdev->dev; bat->client = client; bat->pdata = pdata; bat->status = POWER_SUPPLY_STATUS_DISCHARGING; bat->health = POWER_SUPPLY_HEALTH_GOOD; bat->supply = instinctq_BATTERY_NONE; bat->interval = BAT_POLL_INTERVAL; bat->calibration = pdata->calibration; ret = create_lookup_table(pdata->percent_lut, pdata->percent_lut_cnt, &bat->percent_lookup); if (ret) { dev_err(&pdev->dev, "could not get create percentage lookup table"); goto err_gpio_en_free; } ret = create_lookup_table(pdata->volt_lut, pdata->volt_lut_cnt, &bat->volt_lookup); if (ret) { dev_err(&pdev->dev, "could not get create voltage lookup table"); goto err_percent_free; } ret = create_lookup_table(pdata->temp_lut, pdata->temp_lut_cnt, &bat->temp_lookup); if (ret) { dev_err(&pdev->dev, "could not get create temperature lookup table"); goto err_volt_free; } INIT_WORK(&bat->work, instinctq_battery_work); INIT_DELAYED_WORK(&bat->poll_work, instinctq_battery_poll); mutex_init(&bat->mutex); #ifdef CONFIG_HAS_WAKELOCK wake_lock_init(&bat->wakelock, WAKE_LOCK_SUSPEND, "battery"); wake_lock_init(&bat->chg_wakelock, WAKE_LOCK_SUSPEND, "charger"); wake_lock_init(&bat->fault_wakelock, WAKE_LOCK_SUSPEND, "battery fault"); wake_lock_init(&bat->suspend_lock, WAKE_LOCK_SUSPEND, "suspend_lock"); #endif #ifdef CONFIG_RTC_INTF_ALARM alarm_init(&bat->alarm, ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP, instinctq_battery_alarm); #endif /* Get some initial data for averaging */ for (i = 0; i < NUM_SAMPLES; ++i) { int sample; /* Get a voltage sample from the ADC */ sample = instinctq_battery_adc_read(bat->client, bat->pdata->volt_channel); if (sample < 0) { dev_warn(&pdev->dev, "Failed to get ADC sample.\n"); continue; } sample += bat->compensation; bat->vol_adc = sample; /* Put the sample and get the new average */ bat->volt_value = put_sample_get_avg(&bat->volt_avg, sample); /* Get a temperature sample from the ADC */ sample = instinctq_battery_adc_read(bat->client, bat->pdata->temp_channel); if (sample < 0) { dev_warn(&pdev->dev, "Failed to get ADC sample.\n"); continue; } bat->temp_adc = sample; /* Put the sample and get the new average */ bat->temp_value = put_sample_get_avg(&bat->temp_avg, sample); } bat->percent_value = lookup_value(&bat->percent_lookup, bat->volt_value); bat->volt_value = lookup_value(&bat->volt_lookup, bat->volt_value); bat->temp_value = lookup_value(&bat->temp_lookup, bat->temp_value); bat->last_sample = ktime_get_boottime(); /* Register the power supplies */ for (i = 0; i < instinctq_BATTERY_NUM; ++i) { bat->psy[i] = instinctq_chg_templates[i]; ret = power_supply_register(&pdev->dev, &bat->psy[i]); if (ret < 0) { dev_err(&pdev->dev, "Failed to register power supply %s (%d)\n", bat->psy[i].name, ret); break; } } /* Undo the loop on error */ if (i-- != instinctq_BATTERY_NUM) { for (; i >= 0; --i) power_supply_unregister(&bat->psy[i]); goto err_temp_free; } #ifdef CONFIG_HAS_WAKELOCK ret = device_create_file(bat->psy[instinctq_BATTERY_AC].dev, &dev_attr_suspend_lock); if (ret < 0) { dev_err(&pdev->dev, "Failed to register device attribute.\n"); goto err_psy_unreg; } #endif /* Register the battery */ bat->bat = instinctq_bat_template; ret = power_supply_register(&pdev->dev, &bat->bat); if (ret < 0) { dev_err(&pdev->dev, "Failed to register battery power supply: %d\n", ret); goto err_attr_unreg; } for (i = 0; i < ARRAY_SIZE(battery_attrs); ++i) { ret = device_create_file(bat->bat.dev, battery_attrs[i]); if (ret < 0) break; } if (ret < 0) { for (; i >= 0; --i) device_remove_file(bat->bat.dev, battery_attrs[i]); goto err_bat_unreg; } bat->workqueue = create_freezable_workqueue(dev_name(&pdev->dev)); if (!bat->workqueue) { dev_err(&pdev->dev, "Failed to create freezeable workqueue\n"); ret = -ENOMEM; goto err_remove_bat_attr; } /* Claim IRQs */ irq = gpio_to_irq(pdata->gpio_pok); if (irq <= 0) { dev_err(&pdev->dev, "POK irq invalid.\n"); goto err_destroy_workqueue; } bat->irq_pok = irq; ret = request_irq(irq, instinctq_charger_irq, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, dev_name(&pdev->dev), bat); if (ret) { dev_err(&pdev->dev, "Failed to request POK irq (%d)\n", ret); goto err_destroy_workqueue; } ret = request_irq(IRQ_BATF, instinctq_battery_fault_irq, 0, dev_name(&pdev->dev), bat); if (ret) { dev_err(&pdev->dev, "Failed to request battery fault irq (%d)\n", ret); goto err_pok_irq_free; } enable_irq_wake(bat->irq_pok); instinctq_battery_set_fault_enable(1); /* Finish */ dev_info(&pdev->dev, "successfully loaded\n"); device_init_wakeup(&pdev->dev, 1); pdata->supply_detect_init(instinctq_battery_supply_notify); /* Schedule work to check current status */ #ifdef CONFIG_HAS_WAKELOCK wake_lock(&bat->wakelock); #endif queue_work(bat->workqueue, &bat->work); return 0; err_pok_irq_free: free_irq(bat->irq_pok, bat); err_destroy_workqueue: destroy_workqueue(bat->workqueue); err_remove_bat_attr: for (i = 0; i < ARRAY_SIZE(battery_attrs); ++i) device_remove_file(bat->bat.dev, battery_attrs[i]); err_bat_unreg: power_supply_unregister(&bat->bat); err_attr_unreg: #ifdef CONFIG_HAS_WAKELOCK device_remove_file(bat->psy[instinctq_BATTERY_AC].dev, &dev_attr_suspend_lock); err_psy_unreg: #endif for (i = 0; i < instinctq_BATTERY_NUM; ++i) power_supply_unregister(&bat->psy[i]); err_temp_free: #ifdef CONFIG_HAS_WAKELOCK wake_lock_destroy(&bat->wakelock); wake_lock_destroy(&bat->chg_wakelock); wake_lock_destroy(&bat->fault_wakelock); wake_lock_destroy(&bat->suspend_lock); #endif kfree(bat->temp_lookup.table); err_volt_free: kfree(bat->volt_lookup.table); err_percent_free: kfree(bat->percent_lookup.table); err_gpio_en_free: gpio_free(pdata->gpio_en); err_gpio_chg_free: gpio_free(pdata->gpio_chg); err_gpio_pok_free: gpio_free(pdata->gpio_pok); err_free: kfree(bat); err_free_adc: s3c_adc_release(client); return ret; }
/** * s3c_hwmon_probe - device probe entry. * @dev: The device being probed. */ static int __devinit s3c_hwmon_probe(struct platform_device *dev) { struct s3c_hwmon_pdata *pdata = dev->dev.platform_data; struct s3c_hwmon *hwmon; int ret = 0; int i; if (!pdata) { dev_err(&dev->dev, "no platform data supplied\n"); return -EINVAL; } shwmon = hwmon = kzalloc(sizeof(struct s3c_hwmon), GFP_KERNEL); if (hwmon == NULL) { dev_err(&dev->dev, "no memory\n"); return -ENOMEM; } platform_set_drvdata(dev, hwmon); mutex_init(&hwmon->lock); /* Register with the core ADC driver. */ hwmon->client = s3c_adc_register(dev, NULL, NULL, 0); if (IS_ERR(hwmon->client)) { dev_err(&dev->dev, "cannot register adc\n"); ret = PTR_ERR(hwmon->client); goto err_mem; } /* add attributes for our adc devices. */ ret = s3c_hwmon_add_raw(&dev->dev); if (ret) goto err_registered; /* register with the hwmon core */ hwmon->hwmon_dev = hwmon_device_register(&dev->dev); if (IS_ERR(hwmon->hwmon_dev)) { dev_err(&dev->dev, "error registering with hwmon\n"); ret = PTR_ERR(hwmon->hwmon_dev); goto err_raw_attribute; } for (i = 0; i < ARRAY_SIZE(pdata->in); i++) { struct s3c_hwmon_chcfg *cfg = pdata->in[i]; if (!cfg) continue; if (cfg->mult >= 0x10000) dev_warn(&dev->dev, "channel %d multiplier too large\n", i); if (cfg->div == 0) { dev_err(&dev->dev, "channel %d divider zero\n", i); continue; } ret = s3c_hwmon_create_attr(&dev->dev, pdata->in[i], &hwmon->attrs[i], i); if (ret) { dev_err(&dev->dev, "error creating channel %d\n", i); for (i--; i >= 0; i--) s3c_hwmon_remove_attr(&dev->dev, &hwmon->attrs[i]); goto err_hwmon_register; } } return 0; err_hwmon_register: hwmon_device_unregister(hwmon->hwmon_dev); err_raw_attribute: s3c_hwmon_remove_raw(&dev->dev); err_registered: s3c_adc_release(hwmon->client); err_mem: kfree(hwmon); return ret; }
static bool sec_bat_adc_ap_exit(void) { s3c_adc_release(adc_client); return true; }
static int gp2a_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { int ret = -ENODEV; struct input_dev *input_dev; struct gp2a_data *gp2a; struct gp2a_platform_data *pdata = client->dev.platform_data; pr_info("==============================\n"); pr_info("========= GP2A =======\n"); pr_info("==============================\n"); if (!pdata) { pr_err("%s: missing pdata!\n", __func__); return ret; } /* if (!pdata->power || !pdata->light_adc_value) { pr_err("%s: incomplete pdata!\n", __func__); return ret; } */ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { pr_err("%s: i2c functionality check failed!\n", __func__); return ret; } gp2a = kzalloc(sizeof(struct gp2a_data), GFP_KERNEL); if (!gp2a) { pr_err("%s: failed to alloc memory for module data\n", __func__); return -ENOMEM; } #if defined(CONFIG_OPTICAL_WAKE_ENABLE) if (system_rev >= 0x03) { pr_info("GP2A Reset GPIO = GPX0(1) (rev%02d)\n", system_rev); gp2a->enable_wakeup = true; } else { pr_info("GP2A Reset GPIO = GPL0(6) (rev%02d)\n", system_rev); gp2a->enable_wakeup = false; } #else gp2a->enable_wakeup = false; #endif gp2a->pdata = pdata; gp2a->i2c_client = client; i2c_set_clientdata(client, gp2a); /* wake lock init */ wake_lock_init(&gp2a->prx_wake_lock, WAKE_LOCK_SUSPEND, "prx_wake_lock"); mutex_init(&gp2a->power_mutex); mutex_init(&gp2a->adc_mutex); ret = gp2a_setup_irq(gp2a); if (ret) { pr_err("%s: could not setup irq\n", __func__); goto err_setup_irq; } /* allocate proximity input_device */ input_dev = input_allocate_device(); if (!input_dev) { pr_err("%s: could not allocate input device\n", __func__); goto err_input_allocate_device_proximity; } gp2a->proximity_input_dev = input_dev; input_set_drvdata(input_dev, gp2a); input_dev->name = "proximity_sensor"; input_set_capability(input_dev, EV_ABS, ABS_DISTANCE); input_set_abs_params(input_dev, ABS_DISTANCE, 0, 1, 0, 0); gp2a_dbgmsg("registering proximity input device\n"); ret = input_register_device(input_dev); if (ret < 0) { pr_err("%s: could not register input device\n", __func__); input_free_device(input_dev); goto err_input_register_device_proximity; } ret = sysfs_create_group(&input_dev->dev.kobj, &proximity_attribute_group); if (ret) { pr_err("%s: could not create sysfs group\n", __func__); goto err_sysfs_create_group_proximity; } /* hrtimer settings. we poll for light values using a timer. */ hrtimer_init(&gp2a->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); gp2a->light_poll_delay = ns_to_ktime(LIGHT_TIMER_PERIOD_MS * NSEC_PER_MSEC); gp2a->timer.function = gp2a_timer_func; /* the timer just fires off a work queue request. we need a thread to read the i2c (can be slow and blocking). */ gp2a->wq = create_singlethread_workqueue("gp2a_wq"); if (!gp2a->wq) { ret = -ENOMEM; pr_err("%s: could not create workqueue\n", __func__); goto err_create_workqueue; } /* this is the thread function we run on the work queue */ INIT_WORK(&gp2a->work_light, gp2a_work_func_light); #ifdef GP2A_MODE_B /* this is the thread function we run on the work queue */ INIT_WORK(&gp2a->work_proximity, gp2a_work_func_proximity); #endif /* allocate lightsensor-level input_device */ input_dev = input_allocate_device(); if (!input_dev) { pr_err("%s: could not allocate input device\n", __func__); ret = -ENOMEM; goto err_input_allocate_device_light; } input_set_drvdata(input_dev, gp2a); input_dev->name = "light_sensor"; input_set_capability(input_dev, EV_ABS, ABS_MISC); input_set_abs_params(input_dev, ABS_MISC, 0, 1, 0, 0); gp2a_dbgmsg("registering lightsensor-level input device\n"); ret = input_register_device(input_dev); if (ret < 0) { pr_err("%s: could not register input device\n", __func__); input_free_device(input_dev); goto err_input_register_device_light; } gp2a->light_input_dev = input_dev; ret = sysfs_create_group(&input_dev->dev.kobj, &light_attribute_group); if (ret) { pr_err("%s: could not create sysfs group\n", __func__); goto err_sysfs_create_group_light; } /* alloc platform device for adc client */ pdev_gp2a_adc = platform_device_alloc("gp2a-adc", -1); if (!pdev_gp2a_adc) { pr_err("%s: could not allocation pdev_gp2a_adc.\n", __func__); ret = -ENOMEM; goto err_platform_allocate_device_adc; } /* Register adc client */ gp2a->padc = s3c_adc_register(pdev_gp2a_adc, NULL, NULL, 0); if (IS_ERR(gp2a->padc)) { dev_err(&pdev_gp2a_adc->dev, "cannot register adc\n"); ret = PTR_ERR(gp2a->padc); goto err_platform_register_device_adc; } /* set sysfs for light sensor */ ret = misc_register(&light_device); if (ret) pr_err(KERN_ERR "misc_register failed - light\n"); gp2a->lightsensor_class = class_create(THIS_MODULE, "lightsensor"); if (IS_ERR(gp2a->lightsensor_class)) pr_err("Failed to create class(lightsensor)!\n"); gp2a->switch_cmd_dev = device_create(gp2a->lightsensor_class, NULL, 0, NULL, "switch_cmd"); if (IS_ERR(gp2a->switch_cmd_dev)) pr_err("Failed to create device(switch_cmd_dev)!\n"); if (device_create_file(gp2a->switch_cmd_dev, &dev_attr_lightsensor_file_illuminance) < 0) pr_err("Failed to create device file(%s)!\n", dev_attr_lightsensor_file_illuminance.attr.name); dev_set_drvdata(gp2a->switch_cmd_dev, gp2a); /* set initial proximity value as 1 */ input_report_abs(gp2a->proximity_input_dev, ABS_DISTANCE, 1); input_sync(gp2a->proximity_input_dev); gp2a->adc_total = 0; goto done; /* error, unwind it all */ err_sysfs_create_group_light: input_unregister_device(gp2a->light_input_dev); err_input_register_device_light: err_input_allocate_device_light: destroy_workqueue(gp2a->wq); err_platform_allocate_device_adc: platform_device_unregister(pdev_gp2a_adc); err_platform_register_device_adc: s3c_adc_release(gp2a->padc); err_create_workqueue: sysfs_remove_group(&gp2a->proximity_input_dev->dev.kobj, &proximity_attribute_group); err_sysfs_create_group_proximity: input_unregister_device(gp2a->proximity_input_dev); err_input_register_device_proximity: err_input_allocate_device_proximity: free_irq(gp2a->irq, 0); gpio_free(gp2a->pdata->p_out); err_setup_irq: mutex_destroy(&gp2a->adc_mutex); mutex_destroy(&gp2a->power_mutex); wake_lock_destroy(&gp2a->prx_wake_lock); kfree(gp2a); done: return ret; }
static int __devinit gpio_switch_probe(struct platform_device *pdev) { struct gpio_switch_platform_data *pdata = pdev->dev.platform_data; int ret = 0; if (!pdata) return -EBUSY; switch_data = kzalloc(sizeof(struct gpio_switch_data), GFP_KERNEL); if (!switch_data) return -ENOMEM; platform_set_drvdata(pdev, switch_data); switch_data->sdev.name = pdata->name; switch_data->gpio = pdata->gpio; switch_data->name_on = pdata->name_on; switch_data->name_off = pdata->name_off; switch_data->state_on = pdata->state_on; switch_data->state_off = pdata->state_off; switch_data->sdev.print_state = switch_gpio_print_state; switch_data->active_level = pdata->active_level; switch_data->adc_channel = pdata->adc_channel; ret = switch_dev_register(&switch_data->sdev); if (ret < 0) goto err_switch_dev_register; ret = gpio_request(switch_data->gpio, pdev->name); if (ret < 0) goto err_request_gpio; ret = gpio_direction_input(switch_data->gpio); if (ret < 0) goto err_set_gpio_input; INIT_DELAYED_WORK(&switch_data->del_work, gpio_switch_work); INIT_WORK(&mic_adc_work, mic_adc_work_func); mic_input_dev = input_allocate_device(); mic_input_dev->name = "mx-mic-input"; mic_input_dev->phys = "mx-mic-input/input0"; if (input_register_device(mic_input_dev) != 0) { input_free_device(mic_input_dev); goto err_request_irq; } set_bit(EV_KEY, mic_input_dev->evbit); set_bit(KEY_FORWARDMAIL, mic_input_dev->keybit); switch_data->client = s3c_adc_register(pdev, NULL, NULL, 0); if (IS_ERR(switch_data->client)) { dev_err(&pdev->dev, "cannot register adc\n"); ret = PTR_ERR(switch_data->client); goto err_request_adc; } setup_timer(&detect_mic_adc_timer, mic_adc_detect_timer_func, 0); s3c_gpio_setpull(switch_data->gpio, S3C_GPIO_PULL_UP); switch_data->irq = gpio_to_irq(switch_data->gpio); if (switch_data->irq < 0) { ret = switch_data->irq; goto err_detect_irq_num_failed; } ret = request_threaded_irq(switch_data->irq, NULL, gpio_irq_handler, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, pdev->name, switch_data); if (ret < 0) goto err_request_irq; #ifdef CONFIG_EARLYSUSPEND switch_data->early_suspends.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN; switch_data->early_suspends.suspend = gpio_switch_early_suspend; switch_data->early_suspends.resume= gpio_switch_late_resume; register_early_suspend(&switch_data->early_suspends); #endif schedule_delayed_work(&switch_data->del_work, msecs_to_jiffies(10)); return 0; err_request_irq: s3c_adc_release(switch_data->client); err_request_adc: err_detect_irq_num_failed: err_set_gpio_input: gpio_free(switch_data->gpio); err_request_gpio: switch_dev_unregister(&switch_data->sdev); err_switch_dev_register: kfree(switch_data); return ret; }