diff options
| author | mattis fjallstrom <mattis@acm.org> | 2015-05-21 12:00:33 -0700 |
|---|---|---|
| committer | mattis fjallstrom <mattis@acm.org> | 2015-05-21 13:24:30 -0700 |
| commit | 7d990a059acf5eb46ae99c058fc9911cbdce131d (patch) | |
| tree | ac9531b3ff2b2670dabc84c248a1770c84109586 /drivers/misc/m4sensorhub_als.c | |
| parent | e8980e2a6a7392ae5a1f882d1ba01e03ac83f899 (diff) | |
| parent | 89fdc2c4bb83fff36199cd883a27efb317f02037 (diff) | |
| download | olio-linux-3.10-7d990a059acf5eb46ae99c058fc9911cbdce131d.tar.xz olio-linux-3.10-7d990a059acf5eb46ae99c058fc9911cbdce131d.zip | |
Merge branch 'android-omap-minnow-3.10-lollipop-wear-release' of https://android.googlesource.com/kernel/omap into mattis_devmattis_dev
Change-Id: I46165dd7747b9b6289eb44cb96cbef2de46c10ba
Diffstat (limited to 'drivers/misc/m4sensorhub_als.c')
| -rw-r--r-- | drivers/misc/m4sensorhub_als.c | 118 |
1 files changed, 107 insertions, 11 deletions
diff --git a/drivers/misc/m4sensorhub_als.c b/drivers/misc/m4sensorhub_als.c index 3f61edefff2..6445d9f0181 100644 --- a/drivers/misc/m4sensorhub_als.c +++ b/drivers/misc/m4sensorhub_als.c @@ -28,12 +28,21 @@ #include <linux/m4sensorhub.h> #include <linux/input.h> #include <linux/slab.h> +#include <linux/delay.h> +#ifdef CONFIG_WAKEUP_SOURCE_NOTIFY +#include <linux/notifier.h> +#include <linux/als_notify.h> +#ifdef CONFIG_ALS_WHILE_CHARGING +#include <linux/wakeup_source_notify.h> +#endif /* CONFIG_ALS_WHILE_CHARGING */ +#endif #define m4als_err(format, args...) KDEBUG(M4SH_ERROR, format, ## args) #define M4ALS_DRIVER_NAME "m4sensorhub_als" #define M4ALS_IRQ_ENABLED_BIT 0 +#define ALS_SAMPLERATE_WHILE_DOCKED 10 /* in seconds */ struct m4als_driver_data { struct platform_device *pdev; @@ -42,13 +51,39 @@ struct m4als_driver_data { struct input_dev *indev; struct delayed_work m4als_work; + /* Beware of changing this from uint16, check als_notify.h + since notifier uses values outside luminosity range for + conveying enable/disable status */ uint16_t luminosity; int16_t samplerate; int16_t latest_samplerate; int16_t fastest_rate; uint16_t status; +#ifdef CONFIG_ALS_WHILE_CHARGING + struct notifier_block charger_nb; + bool chargerstatus; +#endif }; +#ifdef CONFIG_ALS_WHILE_CHARGING +static int charger_notify(struct notifier_block *self, + unsigned long action, void *dev) +{ + struct m4als_driver_data *dd = + container_of(self, struct m4als_driver_data, charger_nb); + switch (action) { + case DISPLAY_WAKE_EVENT_DOCKON: + case DISPLAY_WAKE_EVENT_DOCKOFF: + dd->chargerstatus = (action == DISPLAY_WAKE_EVENT_DOCKON); + pr_info("%s: dd->chargerstatus is %d\n", + __func__, dd->chargerstatus); + break; + } + + return NOTIFY_OK; +} +#endif + static void m4als_work_func(struct work_struct *work) { int err = 0; @@ -81,8 +116,18 @@ static void m4als_work_func(struct work_struct *work) dd->luminosity = luminosity; - input_event(dd->indev, EV_MSC, MSC_RAW, dd->luminosity); - input_sync(dd->indev); +#ifdef CONFIG_ALS_WHILE_CHARGING + if (dd->chargerstatus == true) { + als_notify_subscriber(luminosity); + } else { + input_event(dd->indev, EV_MSC, MSC_RAW, dd->luminosity); + input_sync(dd->indev); + } +#else + input_event(dd->indev, EV_MSC, MSC_RAW, dd->luminosity); + input_sync(dd->indev); +#endif + if (dd->samplerate > 0) queue_delayed_work(system_freezable_wq, &(dd->m4als_work), msecs_to_jiffies(dd->samplerate)); @@ -101,6 +146,12 @@ static int m4als_set_samplerate(struct m4als_driver_data *dd, int16_t rate) int err = 0; int size = 0; +#ifdef CONFIG_ALS_WHILE_CHARGING + if (rate == -1 && dd->chargerstatus == true) { + rate = ALS_SAMPLERATE_WHILE_DOCKED * 1000; + } +#endif + if ((rate >= 0) && (rate <= dd->fastest_rate)) rate = dd->fastest_rate; @@ -132,9 +183,17 @@ static int m4als_set_samplerate(struct m4als_driver_data *dd, int16_t rate) } cancel_delayed_work(&(dd->m4als_work)); dd->samplerate = rate; - if (dd->samplerate > 0) + if (dd->samplerate > 0) { queue_delayed_work(system_freezable_wq, &(dd->m4als_work), msecs_to_jiffies(rate)); +#ifdef CONFIG_WAKEUP_SOURCE_NOTIFY + als_notify_subscriber(ALS_ENABLED); +#endif + } else { +#ifdef CONFIG_WAKEUP_SOURCE_NOTIFY + als_notify_subscriber(ALS_DISABLED); +#endif + } m4als_set_samplerate_fail: return err; @@ -153,6 +212,8 @@ static ssize_t m4als_setrate_store(struct device *dev, int err = 0; struct m4als_driver_data *dd = dev_get_drvdata(dev); int value = 0; + int regsize = 0; + uint16_t luminosity = 0; mutex_lock(&(dd->mutex)); @@ -175,6 +236,32 @@ static ssize_t m4als_setrate_store(struct device *dev, goto m4als_enable_store_exit; } + /* Read and send raw value for gesture wakeup */ + msleep(120); + regsize = m4sensorhub_reg_getsize(dd->m4, M4SH_REG_LIGHTSENSOR_SIGNAL); + if (regsize < 0) { + m4als_err("%s: Reading from invalid register %d.\n", + __func__, regsize); + err = regsize; + goto m4als_enable_store_exit; + } + + err = m4sensorhub_reg_read(dd->m4, M4SH_REG_LIGHTSENSOR_SIGNAL, + (char *)&luminosity); + if (err < 0) { + m4als_err("%s: Failed to read luminosity data.\n", __func__); + goto m4als_enable_store_exit; + } else if (err != regsize) { + m4als_err("%s: Read %d bytes instead of %d.\n", + __func__, err, regsize); + goto m4als_enable_store_exit; + } + + dd->luminosity = luminosity; + + input_event(dd->indev, EV_MSC, MSC_RAW, dd->luminosity); + input_sync(dd->indev); + m4als_enable_store_exit: if (err < 0) m4als_err("%s: Failed with error code %d.\n", __func__, err); @@ -304,12 +391,6 @@ static int m4als_driver_init(struct init_calldata *p_arg) goto m4als_driver_init_fail; } - err = m4als_create_sysfs(dd); - if (err < 0) { - m4als_err("%s: Failed to create sysfs.\n", __func__); - goto m4als_driver_init_sysfs_fail; - } - INIT_DELAYED_WORK(&(dd->m4als_work), m4als_work_func); err = m4sensorhub_panic_register(dd->m4, PANICHDL_ALS_RESTORE, @@ -318,8 +399,6 @@ static int m4als_driver_init(struct init_calldata *p_arg) KDEBUG(M4SH_ERROR, "Als panic callback register failed\n"); goto m4als_driver_init_exit; -m4als_driver_init_sysfs_fail: - input_unregister_device(dd->indev); m4als_driver_init_fail: m4als_err("%s: Init failed with error code %d.\n", __func__, err); m4als_driver_init_exit: @@ -359,8 +438,22 @@ static int m4als_probe(struct platform_device *pdev) goto m4als_probe_fail; } + err = m4als_create_sysfs(dd); + if (err < 0) { + m4als_err("%s: Failed to create sysfs.\n", __func__); + goto m4als_driver_init_sysfs_fail; + } + +#ifdef CONFIG_ALS_WHILE_CHARGING + dd->chargerstatus = false; + dd->charger_nb.notifier_call = charger_notify; + wakeup_source_register_notify(&dd->charger_nb); +#endif + return 0; +m4als_driver_init_sysfs_fail: + m4sensorhub_unregister_initcall(m4als_driver_init); m4als_probe_fail: mutex_destroy(&(dd->mutex)); kfree(dd); @@ -377,6 +470,9 @@ static int __exit m4als_remove(struct platform_device *pdev) cancel_delayed_work(&(dd->m4als_work)); m4als_remove_sysfs(dd); m4sensorhub_unregister_initcall(m4als_driver_init); +#ifdef CONFIG_ALS_WHILE_CHARGING + wakeup_source_unregister_notify(&dd->charger_nb); +#endif if (dd->indev != NULL) input_unregister_device(dd->indev); mutex_destroy(&(dd->mutex)); |