summaryrefslogtreecommitdiff
path: root/drivers/leds/leds-lm3535.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/leds/leds-lm3535.c')
-rw-r--r--drivers/leds/leds-lm3535.c158
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;
}