diff options
Diffstat (limited to 'drivers/leds/leds-lm3535.c')
| -rw-r--r-- | drivers/leds/leds-lm3535.c | 158 |
1 files changed, 127 insertions, 31 deletions
diff --git a/drivers/leds/leds-lm3535.c b/drivers/leds/leds-lm3535.c index 3f157942803..23b7558674e 100644 --- a/drivers/leds/leds-lm3535.c +++ b/drivers/leds/leds-lm3535.c @@ -50,10 +50,11 @@ #ifdef CONFIG_LM3535_ESD_RECOVERY #include <mot/esd_poll.h> #endif /* CONFIG_LM3535_ESD_RECOVERY */ -#ifdef CONFIG_WAKEUP_SOURCE_NOTIFY #include <linux/notifier.h> +#ifdef CONFIG_WAKEUP_SOURCE_NOTIFY +#include <linux/als_notify.h> #include <linux/wakeup_source_notify.h> -#define MIN_DOCK_BVALUE 36 +#define MIN_DOCK_BVALUE 36 #include <linux/m4sensorhub.h> #include <linux/m4sensorhub/MemMapUserSettings.h> #endif @@ -273,7 +274,12 @@ struct lm3535 { int prevent_als_read; /* Whether to prevent als reads for a time */ #ifdef CONFIG_WAKEUP_SOURCE_NOTIFY atomic_t docked; + atomic_t alsstatus; +#ifdef CONFIG_ALS_WHILE_CHARGING + atomic_t interactive; +#endif struct notifier_block dock_nb; + struct notifier_block als_nb; #endif }; static DEFINE_MUTEX(lm3535_mutex); @@ -574,30 +580,34 @@ static uint8_t lm3535_convert_value (unsigned value, unsigned zone) reg = res / als_denom; #ifdef CONFIG_WAKEUP_SOURCE_NOTIFY - if (!lm3535_data.prevent_als_read) { - /* make sure this is atleast as high as corresponding ambient - * mode value for current ALS condition */ - m4sensorhub = m4sensorhub_client_get_drvdata(); - size = m4sensorhub_reg_getsize(m4sensorhub, - M4SH_REG_LIGHTSENSOR_SIGNAL); - if (size != sizeof(als)) { - pr_err("can't get M4 reg size for ALS\n"); - ambient_als_backlight = 0; - } else if (size != m4sensorhub_reg_read(m4sensorhub, - M4SH_REG_LIGHTSENSOR_SIGNAL, - (char *)&als)) { - pr_err("error reading M4 ALS value\n"); - ambient_als_backlight = 0; - } else { - adjust_als = true; - /* prevent als reads for next 500 ms */ - lm3535_data.prevent_als_read = 1; - schedule_delayed_work(&lm3535_data.als_delayed_work, - msecs_to_jiffies(500)); + if (atomic_read(&lm3535_data.alsstatus)) { + if (!lm3535_data.prevent_als_read) { + /* make sure this is atleast as + high as corresponding ambient + * mode value for current ALS condition */ + m4sensorhub = m4sensorhub_client_get_drvdata(); + size = m4sensorhub_reg_getsize(m4sensorhub, + M4SH_REG_LIGHTSENSOR_SIGNAL); + if (size != sizeof(als)) { + pr_err("can't get M4 reg size for ALS\n"); + ambient_als_backlight = 0; + } else if (size != m4sensorhub_reg_read(m4sensorhub, + M4SH_REG_LIGHTSENSOR_SIGNAL, + (char *)&als)) { + pr_err("error reading M4 ALS value\n"); + ambient_als_backlight = 0; + } else { + adjust_als = true; + /* prevent als reads for next 500 ms */ + lm3535_data.prevent_als_read = 1; + schedule_delayed_work( + &lm3535_data.als_delayed_work, + msecs_to_jiffies(500)); + } + } else if (ambient_als_backlight > reg) { + /* If valid, use previously read als value */ + reg = ambient_als_backlight; } - } else if (ambient_als_backlight > reg) { - /* If valid, use previously read als value */ - reg = ambient_als_backlight; } if (adjust_als) { @@ -606,7 +616,7 @@ static uint8_t lm3535_convert_value (unsigned value, unsigned zone) if (ambient_als_backlight > reg) reg = ambient_als_backlight; } -#endif +#endif /* CONFIG_WAKEUP_SOURCE_NOTIFY*/ printk_br(KERN_INFO "%s: v=%d, z=%d, res=0x%x, reg=0x%x\n", __func__, value, zone, res, reg); @@ -660,6 +670,31 @@ static void lm3535_brightness_set_raw_als(struct led_classdev *led_cdev, mutex_unlock(&lm3535_mutex); } #endif + +#ifdef CONFIG_WAKEUP_SOURCE_NOTIFY +static int lm3535_als_notifier(struct notifier_block *self, + unsigned long action, void *dev) +{ + pr_info("%s: ALS value is %lu\n", __func__, action); + switch (action) { + case ALS_ENABLED: + case ALS_DISABLED: + atomic_set(&lm3535_data.use_als, (action == ALS_ENABLED)); + break; + default: +#ifdef CONFIG_ALS_WHILE_CHARGING + if (atomic_read(&lm3535_data.interactive) == 0) + lm3535_brightness_set_raw_als(led_get_default_dev(), + (unsigned int)action); + else + pr_info("%s: ignoring ALS notifications\n", __func__); +#endif + break; + } + return NOTIFY_OK; +} +#endif /* CONFIG_WAKEUP_SOURCE_NOTIFY */ + static void lm3535_brightness_set (struct led_classdev *led_cdev, enum led_brightness value) { @@ -707,6 +742,7 @@ static void lm3535_brightness_set (struct led_classdev *led_cdev, /* Calculate brightness value for each zone relative to its cap */ bvalue = lm3535_convert_value (value, bright_zone); + #ifdef CONFIG_WAKEUP_SOURCE_NOTIFY if (atomic_read(&lm3535_data.docked) && (bvalue < MIN_DOCK_BVALUE)) bvalue = MIN_DOCK_BVALUE; /* hard code for dock mode */ @@ -922,6 +958,38 @@ static ssize_t lm3535_suspend_store (struct device *dev, } static DEVICE_ATTR(suspend, 0644, lm3535_suspend_show, lm3535_suspend_store); +#ifdef CONFIG_ALS_WHILE_CHARGING +static ssize_t lm3535_interactive_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return sprintf(buf, "%d\n", atomic_read(&lm3535_data.interactive)); +} + +static ssize_t lm3535_interactive_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + unsigned value = 0; + + if (!buf || size == 0) { + pr_err("%s: invalid command\n", __func__); + return -EINVAL; + } + + sscanf(buf, "%d", &value); + if (value) + atomic_set(&lm3535_data.interactive, 1); + else + atomic_set(&lm3535_data.interactive, 0); + + return size; +} +static DEVICE_ATTR(interactive, S_IRUGO | S_IWUSR, + lm3535_interactive_show, + lm3535_interactive_store); +#endif + /* This function is called by i2c_probe */ static int lm3535_probe (struct i2c_client *client, const struct i2c_device_id *id) @@ -997,6 +1065,18 @@ static int lm3535_probe (struct i2c_client *client, misc_deregister (&als_miscdev); return ret; } +#ifdef CONFIG_ALS_WHILE_CHARGING + ret = device_create_file(lm3535_led.dev, &dev_attr_interactive); + if (ret) { + pr_err("err creating interactive file for %s: %d\n", + lm3535_led.name, ret); + led_classdev_unregister(&lm3535_led); + led_classdev_unregister(&lm3535_led_noramp); + device_remove_file(lm3535_led.dev, &dev_attr_suspend); + misc_deregister(&als_miscdev); + return ret; + } +#endif dev_set_drvdata (lm3535_led.dev, &lm3535_led); #if 0 lm3535_data.idev = input_allocate_device(); @@ -1029,15 +1109,23 @@ static int lm3535_probe (struct i2c_client *client, register_early_suspend (&early_suspend_data); #endif - lm3535_led.brightness = 255; - lm3535_led_noramp.brightness = 255; - //lm3535_brightness_set (&lm3535_led_noramp, 255); - lm3535_write_reg (LM3535_BRIGHTNESS_CTRL_REG_A, 0x79, __FUNCTION__); - lm3535_data.initialized = 1; + lm3535_led.brightness = 84; + lm3535_led_noramp.brightness = 84; + /* lm3535_brightness_set (&lm3535_led_noramp, 255); */ + lm3535_write_reg(LM3535_BRIGHTNESS_CTRL_REG_A, 87, __func__); + lm3535_data.initialized = 1; #ifdef CONFIG_WAKEUP_SOURCE_NOTIFY atomic_set(&lm3535_data.docked, 0); + /* default setting for minnow is to use ALS */ + atomic_set(&lm3535_data.alsstatus, 1); +#ifdef CONFIG_ALS_WHILE_CHARGING + atomic_set(&lm3535_data.interactive, 1); +#endif lm3535_data.dock_nb.notifier_call = lm3535_dock_notifier; wakeup_source_register_notify(&lm3535_data.dock_nb); + + lm3535_data.als_nb.notifier_call = lm3535_als_notifier; + als_register_notify(&lm3535_data.als_nb); #endif /* CONFIG_WAKEUP_SOURCE_NOTIFY */ INIT_DELAYED_WORK(&lm3535_data.als_delayed_work, @@ -1515,10 +1603,18 @@ static int lm3535_remove (struct i2c_client *client) /* led_classdev_unregister (&lm3535_led_noramp); */ misc_deregister (&als_miscdev); device_remove_file (lm3535_led.dev, &dev_attr_suspend); +#ifdef CONFIG_ALS_WHILE_CHARGING + device_remove_file(lm3535_led.dev, &dev_attr_interactive); +#endif #if 0 input_unregister_device (lm3535_data.idev); input_free_device (lm3535_data.idev); #endif + +#ifdef CONFIG_WAKEUP_SOURCE_NOTIFY + wakeup_source_unregister_notify(&lm3535_data.dock_nb); + als_unregister_notify(&lm3535_data.als_nb); +#endif return 0; } |