Esempio n. 1
0
static int cm3663_setup_reg(struct cm3663_data *cm3663)
{
	int err = 0;
	u8 tmp;

	/* initializing the proximity and light sensor registers */
	mutex_lock(&cm3663->power_lock);
	cm3663->pdata->proximity_power(1);
	cm3663_i2c_read(cm3663, REGS_ARA, &tmp);
	cm3663_i2c_read(cm3663, REGS_ARA, &tmp);
	cm3663_i2c_read(cm3663, REGS_ARA, &tmp);
	cm3663_i2c_write(cm3663, REGS_INIT, reg_defaults[3]);
	cm3663_i2c_write(cm3663, REGS_PS_THD, reg_defaults[7]);
	cm3663_i2c_write(cm3663, REGS_PS_CMD, reg_defaults[5]);
	mutex_unlock(&cm3663->power_lock);

	/* printing the inital proximity value with no contact */
	msleep(50);
	err = cm3663_i2c_read(cm3663, REGS_PS_DATA, &tmp);
	if (err < 0) {
		pr_err("%s: read ps_data failed\n", __func__);
		err = -EIO;
	}
	pr_err("%s: initial proximity value = %d\n", __func__, tmp);
	mutex_lock(&cm3663->power_lock);
	cm3663_i2c_write(cm3663, REGS_PS_CMD, 0x01);
	cm3663->pdata->proximity_power(0);
	mutex_unlock(&cm3663->power_lock);

	return err;
}
Esempio n. 2
0
static void cm3663_light_enable(struct cm3663_data *cm3663)
{
	u8 tmp;
	cm3663_i2c_read(cm3663, REGS_ARA, &tmp);
	cm3663_i2c_read(cm3663, REGS_ARA, &tmp);
	cm3663_i2c_read(cm3663, REGS_ARA, &tmp);
	cm3663_i2c_write(cm3663, REGS_INIT, reg_defaults[3]);
	cm3663_i2c_write(cm3663, REGS_ALS_CMD, reg_defaults[1]);
	hrtimer_start(&cm3663->light_timer, cm3663->light_poll_delay,
						HRTIMER_MODE_REL);
}
static int lightsensor_get_alsvalue(struct cm3663_data *cm3663)
{
	int value = 0;
	u8 als_high, als_low;

	/* get ALS */
	cm3663_i2c_read(cm3663, REGS_ALS_LSB, &als_low);
	cm3663_i2c_read(cm3663, REGS_ALS_MSB, &als_high);

	value = ((als_high << 8) | als_low) * 5;
	return value;
}
Esempio n. 4
0
static int lightsensor_get_alsvalue(struct cm3663_data *cm3663)
{
        int als_result = 0;
	u8 als_high, als_low;

	/* get ALS */
	cm3663_i2c_read(cm3663, REGS_ALS_LSB, &als_low);
	cm3663_i2c_read(cm3663, REGS_ALS_MSB, &als_high);

        als_result = ((als_high << 8) | als_low);
	als_raw = als_result;
    
	return als_result * 5;
}
Esempio n. 5
0
static void cm3663_light_enable(struct cm3663_data *cm3663)
{
	u8 tmp;
#if defined(CONFIG_MACH_S2PLUS)
	printk(KERN_INFO "[%s]\n", __func__);
#endif
	cm3663_i2c_read(cm3663, REGS_ARA, &tmp);
	cm3663_i2c_read(cm3663, REGS_ARA, &tmp);
	cm3663_i2c_read(cm3663, REGS_ARA, &tmp);
	cm3663_i2c_write(cm3663, REGS_INIT, reg_defaults[3]);
	cm3663_i2c_write(cm3663, REGS_ALS_CMD, reg_defaults[1]);
	hrtimer_start(&cm3663->light_timer, cm3663->light_poll_delay,
						HRTIMER_MODE_REL);
}
Esempio n. 6
0
static ssize_t proximity_state_show(struct device *dev,
	struct device_attribute *attr, char *buf)
{
	struct cm3663_data *cm3663 = dev_get_drvdata(dev);
	u8 proximity_value = 0;

	if (!(cm3663->power_state & PROXIMITY_ENABLED)) {
		mutex_lock(&cm3663->power_lock);
		cm3663->pdata->proximity_power(1);
		cm3663_i2c_write(cm3663, REGS_PS_CMD, reg_defaults[5]);
		mutex_unlock(&cm3663->power_lock);
	}

	msleep(20);
	cm3663_i2c_read(cm3663, REGS_PS_DATA, &proximity_value);

	if (!(cm3663->power_state & PROXIMITY_ENABLED)) {
		mutex_lock(&cm3663->power_lock);
		cm3663_i2c_write(cm3663, REGS_PS_CMD, 0x01);
		cm3663->pdata->proximity_power(0);
		mutex_unlock(&cm3663->power_lock);
	}

	return sprintf(buf, "%d", proximity_value);
}
Esempio n. 7
0
static void proxsensor_get_avgvalue(struct cm3663_data *cm3663)
{
	int min = 0, max = 0, avg = 0;
	int i;
	u8 proximity_value = 0;

	for (i = 0; i < PROX_READ_NUM; i++) {
		msleep(40);
		cm3663_i2c_read(cm3663, REGS_PS_DATA, &proximity_value);
		avg += proximity_value;

		if (!i)
			min = proximity_value;
		else if (proximity_value < min)
			min = proximity_value;

		if (proximity_value > max)
			max = proximity_value;
	}
	avg /= PROX_READ_NUM;

	cm3663->avg[0] = min;
	cm3663->avg[1] = avg;
	cm3663->avg[2] = max;
}
Esempio n. 8
0
/* interrupt happened due to transition/change of near/far proximity state */
irqreturn_t cm3663_irq_thread_fn(int irq, void *data)
{
	struct cm3663_data *ip = data;
	u8 val = 1;
	u8 tmp;
  	printk(KERN_INFO "[CM3663] cm3663_irq_thread_fn called\n");
    
	val = gpio_get_value(ip->i2c_client->irq);
	if (val < 0) {
		pr_err("%s: gpio_get_value error %d\n", __func__, val);
		return IRQ_HANDLED;
	}

	/* for debugging : going to be removed */
	cm3663_i2c_read(ip, REGS_PS_DATA, &tmp);
       
	/* 0 is close, 1 is far */
	input_report_abs(ip->proximity_input_dev, ABS_DISTANCE, val);
	input_sync(ip->proximity_input_dev);

        printk(KERN_INFO "[CM3663] proximity value = %d \n",val);
    
	wake_lock_timeout(&ip->prx_wake_lock, 3*HZ);

	return IRQ_HANDLED;
}
Esempio n. 9
0
static ssize_t proximity_enable_store(struct device *dev,
				      struct device_attribute *attr,
				      const char *buf, size_t size)
{
	struct cm3663_data *cm3663 = dev_get_drvdata(dev);
	bool new_value;
	u8 tmp;

	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;
	}

        printk(KERN_INFO "[CM3663] proximity_enable_store : new_value=%d\n", new_value);

	mutex_lock(&cm3663->power_lock);
	if (new_value && !(cm3663->power_state & PROXIMITY_ENABLED)) {
		cm3663->pdata->proximity_power(1);
		cm3663->power_state |= PROXIMITY_ENABLED;

        	input_report_abs(cm3663->proximity_input_dev, ABS_DISTANCE, 1);
        	input_sync(cm3663->proximity_input_dev);
        
		cm3663_i2c_read(cm3663, REGS_ARA, &tmp);
		cm3663_i2c_read(cm3663, REGS_ARA, &tmp);
		cm3663_i2c_read(cm3663, REGS_ARA, &tmp);
		cm3663_i2c_write(cm3663, REGS_INIT, reg_defaults[3]);
		cm3663_i2c_write(cm3663, REGS_PS_THD, reg_defaults[7]);
		cm3663_i2c_write(cm3663, REGS_PS_CMD, reg_defaults[5]);
        
		enable_irq(cm3663->irq);

	} else if (!new_value && (cm3663->power_state & PROXIMITY_ENABLED)) {
		cm3663->power_state &= ~PROXIMITY_ENABLED;
        
		disable_irq(cm3663->irq);
		cm3663_i2c_write(cm3663, REGS_PS_CMD, 0x01);
		cm3663->pdata->proximity_power(0);
	}
	mutex_unlock(&cm3663->power_lock);
	return size;
}
Esempio n. 10
0
/*
 * sysfs interface
 * Turn on or off the proximity
 */
static ssize_t cm3663_proximity_enable_store(struct device *dev,
				      struct device_attribute *attr,
				      const char *buf, size_t size)
{
	struct cm3663_data *cm3663 = dev_get_drvdata(dev);
	int enable;
	if (strict_strtoul(buf, 10, &enable))
		return -EINVAL;

	int enabled = (cm3663->power_state & PROXIMITY_ENABLED) >> 1;
	u8 tmp = 0;

	pr_info("[PROXIMITY] %s : new state(%d), old state(%d)\n",
		__func__, enable, enabled);

	if (enable == enabled)
		return size;

	mutex_lock(&cm3663->power_lock);

	if (enable) {
		if (!(cm3663->power_state)) {
			pr_info("\n proximity_power true\n");
			cm3663->pdata->proximity_power(true);
		}

		cm3663->power_state |= PROXIMITY_ENABLED;
		cm3663_i2c_read(cm3663, REGS_ARA, &tmp);
		cm3663_i2c_read(cm3663, REGS_ARA, &tmp);
		cm3663_i2c_write(cm3663, REGS_INIT, reg_defaults[3]);
		cm3663_i2c_write(cm3663, REGS_PS_THD, reg_defaults[7]);
		cm3663_i2c_write(cm3663, REGS_PS_CMD, reg_defaults[5]);
		enable_irq(cm3663->irq);
	} else {
		disable_irq(cm3663->irq);
		cm3663_i2c_write(cm3663, REGS_PS_CMD, 0x01);
		cm3663->power_state &= ~PROXIMITY_ENABLED;

		if (!(cm3663->power_state))
			pr_info("\n proximity_power false\n");
	}

	mutex_unlock(&cm3663->power_lock);
	return size;
}
Esempio n. 11
0
static int cm3663_setup_reg(struct cm3663_data *cm3663)
{
	int err = 0;
	u8 tmp;
#ifdef CONFIG_TARGET_LOCALE_KOR
	if (system_rev <= 0x05)
		reg_defaults[PS_THD] = PS_THD_COMP1; /* PS_THD: 07 */
	else
		reg_defaults[PS_THD] = PS_THD_COMP2; /* PS_THD: 10 */
#endif
	/* initializing the proximity and light sensor registers */
	mutex_lock(&cm3663->power_lock);
	cm3663->pdata->proximity_power(1);
	cm3663_i2c_read(cm3663, REGS_ARA, &tmp);
	cm3663_i2c_read(cm3663, REGS_ARA, &tmp);
	cm3663_i2c_read(cm3663, REGS_ARA, &tmp);
	cm3663_i2c_write(cm3663, REGS_INIT, reg_defaults[3]);
	cm3663_i2c_write(cm3663, REGS_PS_THD, reg_defaults[7]);
	cm3663_i2c_write(cm3663, REGS_PS_CMD, reg_defaults[5]);
	mutex_unlock(&cm3663->power_lock);

	/* printing the inital proximity value with no contact */
	msleep(50);
	err = cm3663_i2c_read(cm3663, REGS_PS_DATA, &tmp);
	if (err < 0) {
		pr_err("%s: read ps_data failed\n", __func__);
		err = -EIO;
	}
	pr_err("%s: initial proximity value = %d\n", __func__, tmp);
	mutex_lock(&cm3663->power_lock);
	cm3663_i2c_write(cm3663, REGS_PS_CMD, 0x01);
	cm3663->pdata->proximity_power(0);
	mutex_unlock(&cm3663->power_lock);

	return err;
}
Esempio n. 12
0
static int lightsensor_get_alsvalue(struct cm3663_data *cm3663)
{
	int value = 0;
	u8 als_high, als_low;

	#ifdef CONFIG_TARGET_LOCALE_KOR
	/* Verify power state of light sensor */
	if (!(cm3663->power_state & LIGHT_ENABLED)) {
		pr_err("%s: Light Sensor was disabled by logic, "
			"cm3663->power_state = 0x%x\n",
			__func__, cm3663->power_state);

		cm3663_light_enable(cm3663);
		cm3663->power_state |= LIGHT_ENABLED;
	}
	#endif

	/* get ALS */
	cm3663_i2c_read(cm3663, REGS_ALS_LSB, &als_low);
	cm3663_i2c_read(cm3663, REGS_ALS_MSB, &als_high);

	value = ((als_high << 8) | als_low) * 5;
	return value;
}
Esempio n. 13
0
/*
 * probe function
 */
static int cm3663_i2c_probe(struct i2c_client *client,
			  const struct i2c_device_id *id)
{
	int ret = -ENODEV;
	struct input_dev *input_dev;
	struct cm3663_data *cm3663;
	u8 tmp;
	int cnt = 3;
	int i = 0;
	int adc = sizeof(adc_step_table)/sizeof(int);

	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
		pr_err("%s: i2c functionality check failed!\n", __func__);
		return ret;
	}

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

	cm3663->pdata = client->dev.platform_data;
	cm3663->i2c_client = client;
	i2c_set_clientdata(client, cm3663);
	cm3663_gdata = cm3663;

	/* wake lock init */
	wake_lock_init(&cm3663->prx_wake_lock,
		WAKE_LOCK_SUSPEND, "prx_wake_lock");

	mutex_init(&cm3663->power_lock);

	ret = cm3663_setup_irq(cm3663);
	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;
	}
	cm3663->proximity_input_dev = input_dev;
	input_set_drvdata(input_dev, cm3663);
	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);

	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(&cm3663->light_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
	cm3663->light_poll_delay = ns_to_ktime(200 * NSEC_PER_MSEC);
	cm3663->light_timer.function = cm3663_light_timer_func;
	/* prox_timer settings. we poll for light values using a timer. */
	hrtimer_init(&cm3663->prox_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
	cm3663->prox_poll_delay = ns_to_ktime(2000 * NSEC_PER_MSEC);
	cm3663->prox_timer.function = cm3663_prox_timer_func;

	/* the timer just fires off a work queue request.  we need a thread
	   to read the i2c (can be slow and blocking). */
	cm3663->light_wq = create_singlethread_workqueue("cm3663_light_wq");
	if (!cm3663->light_wq) {
		ret = -ENOMEM;
		pr_err("%s: could not create light workqueue\n", __func__);
		goto err_create_light_workqueue;
	}
	cm3663->prox_wq = create_singlethread_workqueue("cm3663_prox_wq");
	if (!cm3663->prox_wq) {
		ret = -ENOMEM;
		pr_err("%s: could not create prox workqueue\n", __func__);
		goto err_create_prox_workqueue;
	}

	/* this is the thread function we run on the work queue */
	INIT_WORK(&cm3663->work_light, cm3663_work_func_light);
	INIT_WORK(&cm3663->work_prox, cm3663_work_func_prox);

	/* 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, cm3663);
	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);

	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;
	}
	cm3663->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;
	}

	ret = sensors_register(cm3663->light_sensor_device,
		cm3663, additional_light_attrs, "light_sensor");
	if (ret) {
		pr_err("%s: cound not register sensor device\n", __func__);
		goto err_sysfs_create_group_light;
	}

	ret = sensors_register(cm3663->proximity_sensor_device,
		cm3663, additional_proximity_attrs, "proximity_sensor");
	if (ret) {
		pr_err("%s: cound not register sensor device\n", __func__);
		goto err_sysfs_create_group_light;
	}

	/* print inital proximity value with no contact */
	mutex_lock(&cm3663->power_lock);

	cm3663_i2c_read(cm3663, REGS_ARA, &tmp);
	cm3663_i2c_read(cm3663, REGS_ARA, &tmp);

	do {
		ret = cm3663_i2c_write(cm3663, REGS_INIT, reg_defaults[3]);
		cnt--;
		if ((!cnt) && (ret < 0))
			goto err_i2c_failed;
	} while (ret < 0);
	ret = 0;

	cm3663_i2c_write(cm3663, REGS_PS_THD, reg_defaults[7]);
	cm3663_i2c_write(cm3663, REGS_PS_CMD, reg_defaults[5]);
	msleep(100);

	cm3663_i2c_read(cm3663, REGS_PS_DATA, &tmp);
	pr_info("%s: initial proximity value = %d\n", __func__, tmp);

	cm3663_i2c_write(cm3663, REGS_PS_CMD, 0x01);
	mutex_unlock(&cm3663->power_lock);

	/* set initial proximity value as 1 */
	input_report_abs(cm3663->proximity_input_dev, ABS_DISTANCE, 1);
	input_sync(cm3663->proximity_input_dev);

	pr_info("CM3663 probe ok!!!\n");
	goto done;

/* error, unwind it all */
err_i2c_failed:
	sysfs_remove_group(&cm3663->light_input_dev->dev.kobj,
		&light_attribute_group);
err_sysfs_create_group_light:
	input_unregister_device(cm3663->light_input_dev);
err_input_register_device_light:
err_input_allocate_device_light:
	destroy_workqueue(cm3663->prox_wq);
err_create_prox_workqueue:
	destroy_workqueue(cm3663->light_wq);
err_create_light_workqueue:
	sysfs_remove_group(&cm3663->proximity_input_dev->dev.kobj,
		&proximity_attribute_group);
err_sysfs_create_group_proximity:
	input_unregister_device(cm3663->proximity_input_dev);
err_input_register_device_proximity:
err_input_allocate_device_proximity:
err_setup_irq:
	mutex_destroy(&cm3663->power_lock);
	wake_lock_destroy(&cm3663->prx_wake_lock);
	kfree(cm3663);
	pr_info("CM3663 probe fail!!!\n");

done:
	return ret;
}
static ssize_t proximity_enable_store(struct device *dev,
				      struct device_attribute *attr,
				      const char *buf, size_t size)
{
	struct cm3663_data *cm3663 = dev_get_drvdata(dev);
	bool new_value;
	u8 tmp;
#if defined(CONFIG_MACH_S2PLUS)
	u8 val = 1;
#endif

	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;
	}

	mutex_lock(&cm3663->power_lock);
	if (new_value && !(cm3663->power_state & PROXIMITY_ENABLED)) {
		cm3663->pdata->proximity_power(1);
		cm3663->power_state |= PROXIMITY_ENABLED;
		cm3663_i2c_read(cm3663, REGS_ARA, &tmp);
		cm3663_i2c_read(cm3663, REGS_ARA, &tmp);
		cm3663_i2c_read(cm3663, REGS_ARA, &tmp);
		cm3663_i2c_write(cm3663, REGS_INIT, reg_defaults[3]);
		cm3663_i2c_write(cm3663, REGS_PS_THD, reg_defaults[7]);
		cm3663_i2c_write(cm3663, REGS_PS_CMD, reg_defaults[5]);

#if defined(CONFIG_MACH_S2PLUS)
		/* report the first value */
		val = gpio_get_value(cm3663->i2c_client->irq);
		if (val < 0) {
			pr_err("%s: gpio_get_value error %d\n", __func__, val);
			return IRQ_HANDLED;
		}

		cm3663_i2c_read(cm3663, REGS_PS_DATA, &tmp);
		printk(KERN_INFO  "%s: proximity value = %d, val = %d\n",
				__func__, tmp, val);

		/* 0 is close, 1 is far */
		input_report_abs(cm3663->proximity_input_dev,
					ABS_DISTANCE, val);
		input_sync(cm3663->proximity_input_dev);
		wake_lock_timeout(&cm3663->prx_wake_lock, 3*HZ);
#endif

		enable_irq(cm3663->irq);
		enable_irq_wake(cm3663->irq);
	} else if (!new_value && (cm3663->power_state & PROXIMITY_ENABLED)) {
		cm3663->power_state &= ~PROXIMITY_ENABLED;
		disable_irq_wake(cm3663->irq);
		disable_irq(cm3663->irq);
		cm3663_i2c_write(cm3663, REGS_PS_CMD, 0x01);
		cm3663->pdata->proximity_power(0);
	}
	mutex_unlock(&cm3663->power_lock);
	return size;
}