Ejemplo n.º 1
0
static ssize_t bh1721fvc_light_sensor_mode_store(struct device *dev,
				struct device_attribute *attr,
				const char *buf, size_t size)
{
	u8 measure_mode;
	struct bh1721fvc_data *bh1721fvc = dev_get_drvdata(dev);

	bh1721fvc_dbmsg("bh1721fvc_light_sensor_mode_store +\n");

	if (sysfs_streq(buf, "auto")) {
		measure_mode = AUTO_MEASURE;
	} else if (sysfs_streq(buf, "high")) {
		measure_mode = H_MEASURE;
	} else if (sysfs_streq(buf, "low")) {
		measure_mode = L_MEASURE;
	} else {
		pr_err("%s: invalid value %s\n", __func__, buf);
		return -EINVAL;
	}

	mutex_lock(&bh1721fvc->lock);
	if (bh1721fvc->measure_mode != measure_mode) {
		bh1721fvc->measure_mode = measure_mode;
		if (bh1721fvc_is_measuring(bh1721fvc)) {
			bh1721fvc_disable(bh1721fvc);
			bh1721fvc_enable(bh1721fvc);
			bh1721fvc->state = measure_mode;
		}
	}
	mutex_unlock(&bh1721fvc->lock);

	bh1721fvc_dbmsg("bh1721fvc_light_sensor_mode_store -\n");

	return size;
}
Ejemplo n.º 2
0
static int  bh1721fvc_remove(struct i2c_client *client)
{
	struct bh1721fvc_data *bh1721fvc = i2c_get_clientdata(client);

	bh1721fvc_dbmsg("bh1721fvc_remove +\n");

#ifdef FACTORY_TEST
	device_remove_file(bh1721fvc->factory_dev,
			&dev_attr_lightsensor_file_cmd);
	device_remove_file(bh1721fvc->factory_dev,
			&dev_attr_lightsensor_file_illuminance);
	device_destroy(bh1721fvc->factory_class, 0);
	class_destroy(bh1721fvc->factory_class);
#endif

	sysfs_remove_group(&bh1721fvc->input_dev->dev.kobj,
				&bh1721fvc_attribute_group);
	input_unregister_device(bh1721fvc->input_dev);

	if (bh1721fvc_is_measuring(bh1721fvc))
		bh1721fvc_disable(bh1721fvc);

	destroy_workqueue(bh1721fvc->wq);
	mutex_destroy(&bh1721fvc->lock);
	kfree(bh1721fvc);

	bh1721fvc_dbmsg("bh1721fvc_remove -\n");
	return 0;
}
Ejemplo n.º 3
0
static int bh1721fvc_resume(struct device *dev)
{

	int err = 0;

	struct i2c_client *client = to_i2c_client(dev);

	struct bh1721fvc_data *bh1721fvc = i2c_get_clientdata(client);

	bh1721fvc_dbmsg("bh1721fvc_resume +\n");

	if (bh1721fvc_is_measuring(bh1721fvc)) {

		err = bh1721fvc_enable(bh1721fvc);

		if (err)

			pr_err("%s: could not enable\n", __func__);

	}

	bh1721fvc_dbmsg("bh1721fvc_resume -\n");

	return err;

}
Ejemplo n.º 4
0
static void __exit bh1721fvc_exit(void)
{

	bh1721fvc_dbmsg("bh1721fvc_exit +\n");

	i2c_del_driver(&bh1721fvc_driver);

	bh1721fvc_dbmsg("bh1721fvc_exit -\n");

}
Ejemplo n.º 5
0
static void bh1721fvc_work_func_light(struct work_struct *work)
{

	int err;
	u16 lux;
	u32 result;
	struct bh1721fvc_data *bh1721fvc = container_of(work,
							struct bh1721fvc_data,
							work_light);

	err = bh1721fvc_get_luxvalue(bh1721fvc, &lux);
	if (!err) {
		result = (lux * 89) / 10;
		bh1721fvc_dbmsg("lux 0x%0X (%d)\n", result, result);
		if (result > 60000)
			result = 60000;
		if (!result)
			result = 1;
		input_report_rel(bh1721fvc->input_dev, REL_MISC, result);
		input_sync(bh1721fvc->input_dev);
	} else {
		pr_err("%s: read word failed! (errno=%d)\n", __func__, err);
	}

}
Ejemplo n.º 6
0
static int bh1721fvc_remove(struct i2c_client *client)
{

	struct bh1721fvc_data *bh1721fvc = i2c_get_clientdata(client);

	sensors_unregister(bh1721fvc->light_sensor_device);

	sysfs_remove_group(&bh1721fvc->input_dev->dev.kobj,
			   &bh1721fvc_attribute_group);

	input_unregister_device(bh1721fvc->input_dev);

	if (bh1721fvc_is_measuring(bh1721fvc))

		bh1721fvc_disable(bh1721fvc);

	destroy_workqueue(bh1721fvc->wq);

	mutex_destroy(&bh1721fvc->lock);

	kfree(bh1721fvc);

	bh1721fvc_dbmsg("bh1721fvc_remove -\n");

	return 0;

}
Ejemplo n.º 7
0
static ssize_t bh1721fvc_poll_delay_store(struct device *dev,
				struct device_attribute *attr,
				const char *buf, size_t size)
{
	int err;
	int64_t new_delay;
	struct bh1721fvc_data *bh1721fvc = dev_get_drvdata(dev);

	err = strict_strtoll(buf, 10, &new_delay);
	if (err < 0)
		return err;

	bh1721fvc_dbmsg("new delay = %lldns, old delay = %lldns\n",
			new_delay, ktime_to_ns(bh1721fvc->light_poll_delay));

	mutex_lock(&bh1721fvc->lock);
	if (new_delay != ktime_to_ns(bh1721fvc->light_poll_delay)) {
		bh1721fvc->light_poll_delay = ns_to_ktime(new_delay);
		if (bh1721fvc_is_measuring(bh1721fvc)) {
			bh1721fvc_disable(bh1721fvc);
			bh1721fvc_enable(bh1721fvc);
		}

	}
	mutex_unlock(&bh1721fvc->lock);

	return size;
}
Ejemplo n.º 8
0
static ssize_t bh1721fvc_light_enable_store(struct device *dev,
					struct device_attribute *attr,
					const char *buf, size_t size)
{
	int err = 0;
	bool new_value = false;
	struct bh1721fvc_data *bh1721fvc = dev_get_drvdata(dev);

	bh1721fvc_dbmsg("enable %s\n", buf);

	if (sysfs_streq(buf, "1")) {
		new_value = true;
	} else if (sysfs_streq(buf, "0")) {
		new_value = false;
	} else {
		pr_err("%s: invalid value %d\n", __func__, *buf);
		return -EINVAL;
	}

	bh1721fvc_dbmsg("new_value = %d, old state = %d\n",
			new_value, bh1721fvc_is_measuring(bh1721fvc));

	mutex_lock(&bh1721fvc->lock);
	if (new_value && (!bh1721fvc_is_measuring(bh1721fvc))) {
		err = bh1721fvc_enable(bh1721fvc);
		if (!err) {
			bh1721fvc->state = bh1721fvc->measure_mode;
		} else {
			pr_err("%s: couldn't enable", __func__);
			bh1721fvc->state = POWER_DOWN;
		}
		bh1721fvc->als_buf_initialized = false;
	} else if (!new_value && (bh1721fvc_is_measuring(bh1721fvc))) {
		err = bh1721fvc_disable(bh1721fvc);
		if (!err)
			bh1721fvc->state = POWER_DOWN;
		else
			pr_err("%s: couldn't enable", __func__);
	} else {
		bh1721fvc_dbmsg("no nothing\n");
	}

	mutex_unlock(&bh1721fvc->lock);

	return size;
}
Ejemplo n.º 9
0
static int bh1721fvc_enable(struct bh1721fvc_data *bh1721fvc)
{

	int err;

	bh1721fvc_dbmsg("starting poll timer, delay %lldns\n",
			ktime_to_ns(bh1721fvc->light_poll_delay));

	err = bh1721fvc_write_byte(bh1721fvc->client, commands[POWER_ON]);

	if (err) {

		pr_err("%s: Failed to write byte (POWER_ON)\n", __func__);

		goto err_power_on;

	}

	err =
	    bh1721fvc_write_byte(bh1721fvc->client,
				 commands[bh1721fvc->measure_mode]);

	if (err) {

		pr_err("%s: Failed to write byte (measure mode)\n", __func__);

		goto err_measure_mode;

	}

	if (bh1721fvc->measure_mode == H_MEASURE)

		mdelay(120);

	else if (bh1721fvc->measure_mode == L_MEASURE)

		mdelay(16);

	else
		/* AUTO_MEASURE */
		mdelay(120 + 16);

	hrtimer_start(&bh1721fvc->timer, bh1721fvc->light_poll_delay,
		      HRTIMER_MODE_REL);

	goto done;

err_measure_mode:
err_power_on:
	bh1721fvc_write_byte(bh1721fvc->client, commands[POWER_DOWN]);

done:
	return err;

}
Ejemplo n.º 10
0
static int bh1721fvc_resume(struct device *dev)
{
	int err = 0;
	struct i2c_client *client = to_i2c_client(dev);
	struct bh1721fvc_data *bh1721fvc = i2c_get_clientdata(client);

	bh1721fvc_dbmsg("bh1721fvc_resume +\n");

#if defined(CONFIG_MACH_SAMSUNG_P5)
	bh1721fvc->output(1);
#endif

	if (bh1721fvc_is_measuring(bh1721fvc)) {
		err = bh1721fvc_enable(bh1721fvc);
		if (err)
			pr_err("%s: could not enable\n", __func__);
	}

	bh1721fvc_dbmsg("bh1721fvc_resume -\n");
	return err;
}
Ejemplo n.º 11
0
static int bh1721fvc_enable(struct bh1721fvc_data *bh1721fvc)
{
    int err;

#if defined(CONFIG_MACH_SAMSUNG_P4TMO)
    bh1721fvc->light_buffer = 0;
    bh1721fvc->light_count = 0;
    bh1721fvc->light_level_state = 0;
    bh1721fvc->light_buffer_cnt = LIGHT_UPWORD_BUFFER;
#endif

#if defined(CONFIG_MACH_SAMSUNG_P5)
    bh1721fvc->reset_cnt = 0;
    bh1721fvc->zero_cnt = 0;
#endif

    bh1721fvc_dbmsg("starting poll timer, delay %lldns\n",
                    ktime_to_ns(bh1721fvc->light_poll_delay));

    err = bh1721fvc_write_byte(bh1721fvc->client, commands[POWER_ON]);
    if (err) {
        pr_err("%s: Failed to write byte (POWER_ON)\n", __func__);
        goto err_power_on;
    }

    err = bh1721fvc_write_byte(bh1721fvc->client,
                               commands[bh1721fvc->measure_mode]);
    if (err) {
        pr_err("%s: Failed to write byte (measure mode)\n", __func__);
        goto err_measure_mode;
    }

    if (bh1721fvc->measure_mode == H_MEASURE)
        mdelay(120);
    else if (bh1721fvc->measure_mode == L_MEASURE)
        mdelay(16);
    else	/* AUTO_MEASURE */
        mdelay(120 + 16);

    hrtimer_start(&bh1721fvc->timer, bh1721fvc->light_poll_delay,
                  HRTIMER_MODE_REL);
    goto done;

err_measure_mode:
err_power_on:
    bh1721fvc_write_byte(bh1721fvc->client, commands[POWER_DOWN]);
done:
    return err;
}
Ejemplo n.º 12
0
static void bh1721fvc_work_func_light(struct work_struct *work)
{
	int err;
	u16 lux;
	u32 result;
	struct bh1721fvc_data *bh1721fvc = container_of(work,
					struct bh1721fvc_data, work_light);

	err = bh1721fvc_get_luxvalue(bh1721fvc, &lux);
	if (!err) {
		result = lux;
		result = (result * 10) / 12;
		result = result * 139 / 13;
		bh1721fvc_dbmsg("lux 0x%0X (%d)\n", result, result);
		input_report_abs(bh1721fvc->input_dev, ABS_MISC, result);
		input_sync(bh1721fvc->input_dev);
	} else {
		pr_err("%s: read word failed! (errno=%d)\n", __func__,
			err);
	}
}
Ejemplo n.º 13
0
static void bh1721fvc_work_func_light(struct work_struct *work)
{
	int err;
	u16 lux;
	static int cnt = 0;
	unsigned int result = 0;
	
	struct bh1721fvc_data *bh1721fvc = container_of(work,
					struct bh1721fvc_data, work_light);

	err = bh1721fvc_get_luxvalue(bh1721fvc, &lux);
	if (err ==0)
	{
		result = (lux * 10) / 12;
		result = result * 139 / 13;
		if(result > 65000) result = 65000;
			
		bh1721fvc_dbmsg("lux 0x%0X (%d)\n", result, result);
		input_report_abs(bh1721fvc->input_dev, ABS_MISC, result);
		input_sync(bh1721fvc->input_dev);
	} else {
		pr_err("%s: read word failed! (errno=%d)\n", __func__, err);
	}

#if defined(CONFIG_MACH_SAMSUNG_P5)
	if(result == 0) cnt++;
	else cnt =0;
	
	if(cnt > 25)
	{
		cnt = 0;
		printk("Lux Value : 0 during 5 sec...\n");
		bh1721fvc_reset(bh1721fvc);
	}
#endif

}
Ejemplo n.º 14
0
static int __devinit bh1721fvc_probe(struct i2c_client *client,
				     const struct i2c_device_id *id)
{

	int err = 0;

	struct bh1721fvc_data *bh1721fvc;

	struct input_dev *input_dev;

	struct bh1721fvc_platform_data *pdata = client->dev.platform_data;

	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);

	if (!i2c_check_functionality(adapter, I2C_FUNC_I2C))

		return -EIO;

	bh1721fvc = kzalloc(sizeof(*bh1721fvc), GFP_KERNEL);

	if (!bh1721fvc) {

		pr_err("%s, failed to alloc memory for module data\n",
		       __func__);

		return -ENOMEM;

	}

	bh1721fvc->reset = pdata->reset;

	if (!bh1721fvc->reset) {

		pr_err("%s: reset callback is null\n", __func__);

		err = -EIO;

		goto err_reset_null;

	}

	err = bh1721fvc->reset();

	if (err) {

		pr_err("%s: Failed to reset\n", __func__);

		goto err_reset_failed;

	}

	bh1721fvc->client = client;

	i2c_set_clientdata(client, bh1721fvc);

	mutex_init(&bh1721fvc->lock);

	bh1721fvc->state = POWER_DOWN;

	bh1721fvc->measure_mode = AUTO_MEASURE;

	err = bh1721fvc_test_luxvalue(bh1721fvc);

	if (err < 0) {

		pr_err("%s: No search bh1721fvc lightsensor!\n", __func__);

		goto err_test_lightsensor;

	} else {

		printk(KERN_ERR "Lux : %d\n", err);

	}

	hrtimer_init(&bh1721fvc->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);

	bh1721fvc->light_poll_delay = ns_to_ktime(200 * NSEC_PER_MSEC);

	bh1721fvc->timer.function = bh1721fvc_timer_func;

	bh1721fvc->wq =
	    alloc_workqueue("bh1721fvc_wq", WQ_UNBOUND | WQ_RESCUER, 1);

	if (!bh1721fvc->wq) {

		err = -ENOMEM;

		pr_err("%s: could not create workqueue\n", __func__);

		goto err_create_workqueue;

	}

	INIT_WORK(&bh1721fvc->work_light, bh1721fvc_work_func_light);

	input_dev = input_allocate_device();

	if (!input_dev) {

		pr_err("%s: could not allocate input device\n", __func__);

		err = -ENOMEM;

		goto err_input_allocate_device_light;

	}

	input_set_drvdata(input_dev, bh1721fvc);

	input_dev->name = "light_sensor";

	input_set_capability(input_dev, EV_REL, REL_MISC);

	bh1721fvc_dbmsg("registering lightsensor-level input device\n");

	err = input_register_device(input_dev);

	if (err < 0) {

		pr_err("%s: could not register input device\n", __func__);

		input_free_device(input_dev);

		goto err_input_register_device_light;

	}

	bh1721fvc->input_dev = input_dev;

	err =
	    sysfs_create_group(&input_dev->dev.kobj,
			       &bh1721fvc_attribute_group);
	if (err) {
		pr_err("%s: could not create sysfs group\n", __func__);
		goto err_sysfs_create_group_light;
	}

	err = sensors_register(bh1721fvc->light_sensor_device,
		bh1721fvc, additional_light_attrs, "light_sensor");
	if (err) {
		pr_err("%s: cound not register sensor device\n", __func__);
		goto err_sysfs_create_factory_light;
	}
	printk(KERN_INFO "%s: success!\n", __func__);

	goto done;

err_sysfs_create_factory_light:
	sysfs_remove_group(&bh1721fvc->input_dev->dev.kobj,
			   &bh1721fvc_attribute_group);
err_sysfs_create_group_light:
	input_unregister_device(bh1721fvc->input_dev);
err_input_register_device_light:
err_input_allocate_device_light:
	destroy_workqueue(bh1721fvc->wq);
err_create_workqueue:
err_test_lightsensor:
	mutex_destroy(&bh1721fvc->lock);
err_reset_failed:
err_reset_null:
	kfree(bh1721fvc);

done:
	return err;

}
Ejemplo n.º 15
0
static void bh1721fvc_work_func_light(struct work_struct *work)
{
    int i;
    int err;
    u16 lux;
    unsigned int result = 0;
    struct bh1721fvc_data *bh1721fvc =
        container_of(work, struct bh1721fvc_data, work_light);

    err = bh1721fvc_get_luxvalue(bh1721fvc, &lux);

    /*
     *	result = (lux * 10) / 12;
     *	result = result * 139 / 13;
     */
    result = (lux * 89) / 10;
    if (result <= 8)
        result = 0;

#if defined(CONFIG_MACH_SAMSUNG_P5)
    if (result > 69000)
        result = 69000;
#else
    if (result > 60000)
        result = 60000;
#endif

#if 0
    for (i = 0; ARRAY_SIZE(adc_table); i++)
        if (result <= adc_table[i])
            break;

    if (bh1721fvc->light_buffer == i) {
        if (bh1721fvc->light_count++ >= bh1721fvc->light_buffer_cnt) {
            bh1721fvc_dbmsg("lux 0x%0X (%d)\n", result, result);
            input_report_rel(bh1721fvc->input_dev,
                             REL_MISC, result+1);
            input_sync(bh1721fvc->input_dev);
            bh1721fvc->light_level_state = i;
            bh1721fvc->light_count = 0;
        }
    } else {
        bh1721fvc->light_buffer = i;
        bh1721fvc->light_count = 0;

        if (bh1721fvc->light_level_state >= i)
            bh1721fvc->light_buffer_cnt = LIGHT_DOWNWORD_BUFFER;
        else
            bh1721fvc->light_buffer_cnt = LIGHT_UPWORD_BUFFER;
    }
#else
    input_report_rel(bh1721fvc->input_dev, REL_MISC, result+1);
    input_sync(bh1721fvc->input_dev);
#endif

#if defined(CONFIG_MACH_SAMSUNG_P5)
    if (result == 0) {
        if (bh1721fvc->zero_cnt++ > 25) {
            bh1721fvc->zero_cnt = 0;
            if (bh1721fvc->reset_cnt++ <= LIMIT_RESET_COUNT)
                bh1721fvc_reset(bh1721fvc);
            else
                bh1721fvc->reset_cnt == LIMIT_RESET_COUNT + 1;
        }
    } else {
        bh1721fvc->reset_cnt = 0;
        bh1721fvc->zero_cnt = 0;
    }
#endif
}
Ejemplo n.º 16
0
static int __devinit bh1721fvc_probe(struct i2c_client *client,
					const struct i2c_device_id *id)
{
	int err = 0;
	struct bh1721fvc_data *bh1721fvc;
	struct input_dev *input_dev;
	struct bh1721fvc_platform_data *pdata = client->dev.platform_data;
	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);

	pr_info("%s: is started!\n", __func__);
	if (!i2c_check_functionality(adapter, I2C_FUNC_I2C))
		return -EIO;

	bh1721fvc = kzalloc(sizeof(*bh1721fvc), GFP_KERNEL);
	if (!bh1721fvc) {
		pr_err("%s, failed to alloc memory for module data\n",
			__func__);
		return -ENOMEM;
	}

	if (pdata != NULL) {
		bh1721fvc->reset = pdata->reset;
		if (!bh1721fvc->reset) {
			pr_err("%s: reset callback is null\n", __func__);
			err = -EIO;
			goto err_reset_null;
		}

		err = bh1721fvc->reset();
		if (err) {
			pr_err("%s: Failed to reset\n", __func__);
			goto err_reset_failed;
		}
	}

	bh1721fvc->client = client;
	i2c_set_clientdata(client, bh1721fvc);

	mutex_init(&bh1721fvc->lock);
	bh1721fvc->state = POWER_DOWN;
	bh1721fvc->measure_mode = AUTO_MEASURE;

	err = bh1721fvc_test_luxvalue(bh1721fvc);
	if (err < 0) {
		pr_err("%s: No search bh1721fvc lightsensor!\n", __func__);
		goto err_test_lightsensor;
	} else {
		printk(KERN_ERR"Lux : %d\n", err);
	}

	hrtimer_init(&bh1721fvc->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);

	bh1721fvc->light_poll_delay = ns_to_ktime(200 * NSEC_PER_MSEC);
	bh1721fvc->timer.function = bh1721fvc_timer_func;

	bh1721fvc->wq = alloc_workqueue("bh1721fvc_wq",
		WQ_UNBOUND | WQ_RESCUER, 1);
	if (!bh1721fvc->wq) {
		err = -ENOMEM;
		pr_err("%s: could not create workqueue\n", __func__);
		goto err_create_workqueue;
	}

	INIT_WORK(&bh1721fvc->work_light, bh1721fvc_work_func_light);

	input_dev = input_allocate_device();
	if (!input_dev) {
		pr_err("%s: could not allocate input device\n", __func__);
		err = -ENOMEM;
		goto err_input_allocate_device_light;
	}
	input_set_drvdata(input_dev, bh1721fvc);
	input_dev->name = "light_sensor";
#if 0
	input_set_capability(input_dev, EV_ABS, ABS_MISC);
	input_set_abs_params(input_dev, ABS_MISC,
		LUX_MIN_VALUE, LUX_MAX_VALUE, 0, 0);
#else
	input_set_capability(input_dev, EV_REL, REL_MISC);
#endif
	bh1721fvc_dbmsg("registering lightsensor-level input device\n");
	err = input_register_device(input_dev);
	if (err < 0) {
		pr_err("%s: could not register input device\n", __func__);
		input_free_device(input_dev);
		goto err_input_register_device_light;
	}
	bh1721fvc->input_dev = input_dev;
	err = sysfs_create_group(&input_dev->dev.kobj,
		&bh1721fvc_attribute_group);
	if (err) {
		pr_err("%s: could not create sysfs group\n", __func__);
		goto err_sysfs_create_group_light;
	}

	/* set sysfs for light sensor */
	bh1721fvc->light_dev = sensors_classdev_register("light_sensor");
	if (IS_ERR(bh1721fvc->light_dev)) {
		pr_err("%s: could not create light_dev\n", __func__);
		goto err_light_device_create;
	}

	if (device_create_file(bh1721fvc->light_dev, &dev_attr_raw_data) < 0) {
		pr_err("%s: could not create device file(%s)!\n", __func__,
		       dev_attr_raw_data.attr.name);
		goto err_light_device_create_file1;
	}

	if (device_create_file(bh1721fvc->light_dev, &dev_attr_vendor) < 0) {
		pr_err("%s: could not create device file(%s)!\n", __func__,
		       dev_attr_vendor.attr.name);
		goto err_light_device_create_file2;
	}

	if (device_create_file(bh1721fvc->light_dev, &dev_attr_name) < 0) {
		pr_err("%s: could not create device file(%s)!\n", __func__,
		       dev_attr_name.attr.name);
		goto err_light_device_create_file3;
	}

	dev_set_drvdata(bh1721fvc->light_dev, bh1721fvc);
	pr_info("%s: success!\n", __func__);


	goto done;

err_light_device_create_file3:
	device_remove_file(bh1721fvc->light_dev, &dev_attr_vendor);
err_light_device_create_file2:
	device_remove_file(bh1721fvc->light_dev, &dev_attr_raw_data);
err_light_device_create_file1:
	sensors_classdev_unregister(bh1721fvc->light_dev);
err_light_device_create:
	sysfs_remove_group(&bh1721fvc->input_dev->dev.kobj,
				&bh1721fvc_attribute_group);
err_sysfs_create_group_light:
	input_unregister_device(bh1721fvc->input_dev);
err_input_register_device_light:
err_input_allocate_device_light:
	destroy_workqueue(bh1721fvc->wq);
err_create_workqueue:
err_test_lightsensor:
	mutex_destroy(&bh1721fvc->lock);
err_reset_failed:
err_reset_null:
	kfree(bh1721fvc);
done:
	return err;
}
Ejemplo n.º 17
0
static int __devinit bh1721fvc_probe(struct i2c_client *client,
                                     const struct i2c_device_id *id)
{
    int err = 0;
    struct bh1721fvc_data *bh1721fvc;
    struct input_dev *input_dev;
    struct bh1721fvc_platform_data *pdata = client->dev.platform_data;
    struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);

    printk(KERN_INFO "%s: start!\n", __func__);

    if (!i2c_check_functionality(adapter, I2C_FUNC_I2C))
        return -EIO;

    bh1721fvc = kzalloc(sizeof(*bh1721fvc), GFP_KERNEL);
    if (!bh1721fvc) {
        pr_err("%s, failed to alloc memory for module data\n",
               __func__);
        return -ENOMEM;
    }

#if defined(CONFIG_MACH_SAMSUNG_P5)
    bh1721fvc->output = pdata->output;
#endif

    bh1721fvc->reset = pdata->reset;
    if (!bh1721fvc->reset) {
        pr_err("%s: reset callback is null\n", __func__);
        err = -EIO;
        goto err_reset_null;
    }

    err = bh1721fvc->reset();
    if (err) {
        pr_err("%s: Failed to reset\n", __func__);
        goto err_reset_failed;
    }

    bh1721fvc->client = client;
    i2c_set_clientdata(client, bh1721fvc);

    mutex_init(&bh1721fvc->lock);

    bh1721fvc->state = POWER_DOWN;
    bh1721fvc->measure_mode = AUTO_MEASURE;

    err = bh1721fvc_test_luxvalue(bh1721fvc);
    if (err < 0) {
        pr_err("%s: No search bh1721fvc lightsensor!\n", __func__);
        goto err_test_lightsensor;
    } else
        printk(KERN_INFO "Lux : %d\n", err);

    hrtimer_init(&bh1721fvc->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);

    bh1721fvc->light_poll_delay = ns_to_ktime(200 * NSEC_PER_MSEC);
    bh1721fvc->timer.function = bh1721fvc_timer_func;
    bh1721fvc->wq = alloc_workqueue("bh1721fvc_wq",
                                    WQ_UNBOUND | WQ_RESCUER, 1);

    if (!bh1721fvc->wq) {
        err = -ENOMEM;
        pr_err("%s: could not create workqueue\n", __func__);
        goto err_create_workqueue;
    }

    INIT_WORK(&bh1721fvc->work_light, bh1721fvc_work_func_light);

    input_dev = input_allocate_device();
    if (!input_dev) {
        pr_err("%s: could not allocate input device\n", __func__);
        err = -ENOMEM;
        goto err_input_allocate_device_light;
    }

    input_set_drvdata(input_dev, bh1721fvc);
    input_dev->name = "light_sensor";
    input_set_capability(input_dev, EV_REL, REL_MISC);

    bh1721fvc_dbmsg("registering lightsensor-level input device\n");
    err = input_register_device(input_dev);
    if (err < 0) {
        pr_err("%s: could not register input device\n", __func__);
        input_free_device(input_dev);
        goto err_input_register_device_light;
    }

    bh1721fvc->input_dev = input_dev;
    err = sysfs_create_group(&input_dev->dev.kobj,
                             &bh1721fvc_attribute_group);
    if (err) {
        pr_err("%s: could not create sysfs group\n", __func__);
        goto err_sysfs_create_group_light;
    }

    bh1721fvc->factory_class = class_create(THIS_MODULE, "lightsensor");

    if (IS_ERR(bh1721fvc->factory_class)) {
        pr_err("Failed to create class(lightsensor)!\n");
        err = PTR_ERR(bh1721fvc->factory_class);
        goto err_factory_sysfs_create;
    }

    bh1721fvc->factory_dev = device_create(bh1721fvc->factory_class,
                                           NULL, 0, bh1721fvc, "switch_cmd");
    if (IS_ERR(bh1721fvc->factory_dev)) {
        pr_err("Failed to create device(switch_cmd_dev)!\n");
        err = PTR_ERR(bh1721fvc->factory_dev);
        goto err_factory_device_create;
    }

    err = device_create_file(bh1721fvc->factory_dev,
                             &dev_attr_lightsensor_file_cmd);
    if (err < 0) {
        pr_err("Failed to create device file(%s)!\n",
               dev_attr_lightsensor_file_cmd.attr.name);
        goto err_file_cmd_attr_create;
    }

    err = device_create_file(bh1721fvc->factory_dev,
                             &dev_attr_lightsensor_file_illuminance);
    if (err < 0) {
        pr_err("Failed to create device file(%s)!\n",
               dev_attr_lightsensor_file_illuminance.attr.name);
        goto err_illuminance_attr_create;
    }

    err = device_create_file(bh1721fvc->factory_dev,
                             &dev_attr_sensor_info);
    if (err < 0) {
        pr_err("Failed to create device file(%s)!\n",
               dev_attr_sensor_info.attr.name);
        goto err_sensor_info_attr_create;
    }

    printk(KERN_INFO "%s: success!\n", __func__);
    goto done;

err_sensor_info_attr_create:
    device_remove_file(bh1721fvc->factory_dev,
                       &dev_attr_lightsensor_file_illuminance);
err_illuminance_attr_create:
    device_remove_file(bh1721fvc->factory_dev,
                       &dev_attr_lightsensor_file_cmd);
err_file_cmd_attr_create:
    device_destroy(bh1721fvc->factory_class, 0);
err_factory_device_create:
    class_destroy(bh1721fvc->factory_class);
err_factory_sysfs_create:
    sysfs_remove_group(&bh1721fvc->input_dev->dev.kobj,
                       &bh1721fvc_attribute_group);
err_sysfs_create_group_light:
    input_unregister_device(bh1721fvc->input_dev);
err_input_register_device_light:
err_input_allocate_device_light:
    destroy_workqueue(bh1721fvc->wq);
err_create_workqueue:
err_test_lightsensor:
    mutex_destroy(&bh1721fvc->lock);
err_reset_failed:
err_reset_null:
    kfree(bh1721fvc);
done:
    printk(KERN_INFO "%s: fail!\n", __func__);

    return err;
}