diff options
| -rw-r--r-- | drivers/mfd/Makefile | 1 | ||||
| -rw-r--r-- | drivers/mfd/m4sensorhub-core.c | 12 | ||||
| -rw-r--r-- | drivers/mfd/m4sensorhub-extern.c | 158 | ||||
| -rw-r--r-- | drivers/mfd/m4sensorhub-panic.c | 1 | ||||
| -rw-r--r-- | drivers/misc/c55_ctrl.c | 16 | ||||
| -rw-r--r-- | drivers/misc/m4sensorhub_pedometer.c | 101 | ||||
| -rw-r--r-- | drivers/video/omap2/displays/panel-minnow.c | 13 | ||||
| -rw-r--r-- | include/linux/m4sensorhub.h | 7 |
8 files changed, 258 insertions, 51 deletions
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index c0704d70b97..e14fcb9363f 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -171,6 +171,7 @@ m4sensorhub-objs := m4sensorhub-core.o \ m4sensorhub-reg.o \ m4sensorhub-irq.o \ m4sensorhub-panic.o \ + m4sensorhub-extern.o \ m4sensorhub-stm32-fw.o \ m4sensorhub-stm32_401-fw.o diff --git a/drivers/mfd/m4sensorhub-core.c b/drivers/mfd/m4sensorhub-core.c index bc8aa45c7b7..203109e6ac7 100644 --- a/drivers/mfd/m4sensorhub-core.c +++ b/drivers/mfd/m4sensorhub-core.c @@ -90,6 +90,12 @@ static ssize_t m4sensorhub_get_dbg(struct device *dev, /* BEGIN BOARD FILE */ /* TODO: replace with request array */ +int m4sensorhub_get_current_mode(void) +{ + return m4sensorhub_misc_data.mode; +} +EXPORT_SYMBOL_GPL(m4sensorhub_get_current_mode); + int m4sensorhub_set_bootmode(struct m4sensorhub_data *m4sensorhub, enum m4sensorhub_bootmode bootmode) { @@ -496,6 +502,12 @@ static void m4sensorhub_initialize(const struct firmware *firmware, return; } + err = m4sensorhub_extern_init(&m4sensorhub_misc_data); + if (err < 0) { + KDEBUG(M4SH_ERROR, "%s: Extern init failed.\n", __func__); + return; + } + /* Initialize all the m4 drivers */ inc = inithead; arg.p_m4sensorhub_data = &m4sensorhub_misc_data; diff --git a/drivers/mfd/m4sensorhub-extern.c b/drivers/mfd/m4sensorhub-extern.c new file mode 100644 index 00000000000..771dc5cc4f3 --- /dev/null +++ b/drivers/mfd/m4sensorhub-extern.c @@ -0,0 +1,158 @@ +/* + * Copyright (C) 2014 Motorola, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Adds ability to program periodic interrupts from user space that + * can wake the phone out of low power modes. + * + */ + +#include <linux/module.h> +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/m4sensorhub.h> +#include <linux/slab.h> + +#define m4ext_err(format, args...) KDEBUG(M4SH_ERROR, format, ## args) + +struct m4sensorhub_data *m4ext_m4; +DEFINE_MUTEX(m4ext_mutex); +uint8_t m4ext_display_status; +uint8_t m4ext_audio_status; + +static void m4ext_panic_callback(struct m4sensorhub_data *m4, void *context) +{ + int err; + + mutex_lock(&m4ext_mutex); + + if (m4ext_m4 == NULL) { + m4ext_err("%s: M4 data is NULL.\n", __func__); + err = -ENODATA; + goto m4ext_panic_callback_fail; + } + + err = m4sensorhub_reg_write(m4, M4SH_REG_USERSETTINGS_SCREENSTATUS, + (char *)&m4ext_display_status, m4sh_no_mask); + if (err < 0) + m4ext_err("%s: Screen status write failed (%d).\n", + __func__, err); + else if (err != 1) + m4ext_err("%s: Screen status wrote %d bytes instead of 1.\n", + __func__, err); + + err = m4sensorhub_reg_write(m4, M4SH_REG_USERSETTINGS_AUDIOSTATUS, + (char *)&m4ext_audio_status, m4sh_no_mask); + if (err < 0) + m4ext_err("%s: Audio status write failed (%d).\n", + __func__, err); + else if (err != 1) + m4ext_err("%s: Audio status wrote %d bytes instead of 1.\n", + __func__, err); + +m4ext_panic_callback_fail: + mutex_unlock(&m4ext_mutex); + return; +} + +int m4sensorhub_extern_init(struct m4sensorhub_data *m4) +{ + int err; + + mutex_lock(&m4ext_mutex); + + err = m4sensorhub_panic_register(m4, PANICHDL_EXTERN_RESTORE, + m4ext_panic_callback, NULL); + if (err < 0) { + m4ext_err("%s: Failed to register panic callback.\n", __func__); + goto m4sensorhub_extern_init_fail; + } + + m4ext_m4 = m4; + +m4sensorhub_extern_init_fail: + mutex_unlock(&m4ext_mutex); + return err; +} +EXPORT_SYMBOL_GPL(m4sensorhub_extern_init); + +int m4sensorhub_extern_set_display_status(uint8_t status) +{ + int err; + + mutex_lock(&m4ext_mutex); + + if (m4ext_m4 == NULL) { + m4ext_err("%s: M4 data is NULL.\n", __func__); + err = -ENODATA; + goto m4sensorhub_extern_set_display_status_fail; + } + + m4ext_display_status = status; + + err = m4sensorhub_reg_write(m4ext_m4, + M4SH_REG_USERSETTINGS_SCREENSTATUS, + (char *)&status, m4sh_no_mask); + if (err < 0) { + m4ext_err("%s: I2C write failed (%d).\n", __func__, err); + goto m4sensorhub_extern_set_display_status_fail; + } else if (err != 1) { + m4ext_err("%s: Wrote %d bytes instead of 1.\n", __func__, err); + err = -EINVAL; + goto m4sensorhub_extern_set_display_status_fail; + } + + err = 0; + +m4sensorhub_extern_set_display_status_fail: + mutex_unlock(&m4ext_mutex); + return err; +} +EXPORT_SYMBOL_GPL(m4sensorhub_extern_set_display_status); + +int m4sensorhub_extern_set_audio_status(uint8_t status) +{ + int err; + + mutex_lock(&m4ext_mutex); + + if (m4ext_m4 == NULL) { + m4ext_err("%s: M4 data is NULL.\n", __func__); + err = -ENODATA; + goto m4sensorhub_extern_set_audio_status_fail; + } + + m4ext_audio_status = status; + + err = m4sensorhub_reg_write(m4ext_m4, + M4SH_REG_USERSETTINGS_AUDIOSTATUS, + (char *)&status, m4sh_no_mask); + if (err < 0) { + m4ext_err("%s: I2C write failed (%d).\n", __func__, err); + goto m4sensorhub_extern_set_audio_status_fail; + } else if (err != 1) { + m4ext_err("%s: Wrote %d bytes instead of 1.\n", __func__, err); + err = -EINVAL; + goto m4sensorhub_extern_set_audio_status_fail; + } + + err = 0; + +m4sensorhub_extern_set_audio_status_fail: + mutex_unlock(&m4ext_mutex); + return err; +} +EXPORT_SYMBOL_GPL(m4sensorhub_extern_set_audio_status); diff --git a/drivers/mfd/m4sensorhub-panic.c b/drivers/mfd/m4sensorhub-panic.c index b127adeba5c..34ad6658453 100644 --- a/drivers/mfd/m4sensorhub-panic.c +++ b/drivers/mfd/m4sensorhub-panic.c @@ -40,6 +40,7 @@ static const char *callback_name[PANICHDL_MAX] = { [PANICHDL_FUSION_RESTORE] = "fusion_restore", [PANICHDL_MPU9150_RESTORE] = "mpu9150_restore", [PANICHDL_PEDOMETER_RESTORE] = "pedometer_restore", + [PANICHDL_EXTERN_RESTORE] = "extern_restore", }; struct m4sensorhub_panic_callback { diff --git a/drivers/misc/c55_ctrl.c b/drivers/misc/c55_ctrl.c index 54ffc6e5b2b..cf763272922 100644 --- a/drivers/misc/c55_ctrl.c +++ b/drivers/misc/c55_ctrl.c @@ -143,7 +143,6 @@ static ssize_t c55_ctrl_enable(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct c55_ctrl_data *cdata = dev_get_drvdata(dev); - struct m4sensorhub_data *m4sensorhub = m4sensorhub_client_get_drvdata(); int mode; if (kstrtoint(buf, 10, &mode) < 0) @@ -154,7 +153,7 @@ static ssize_t c55_ctrl_enable(struct device *dev, return -EINVAL; } - if (m4sensorhub->mode != NORMALMODE) { + if (m4sensorhub_get_current_mode() != NORMALMODE) { dev_err(dev, "M4 not ready, Unable to set screen status\n"); return -EINVAL; } @@ -169,9 +168,7 @@ static ssize_t c55_ctrl_enable(struct device *dev, gpio_set_value(cdata->ap_c55_int_gpio, 1); - if (m4sensorhub_reg_write_1byte - (m4sensorhub, M4SH_REG_USERSETTINGS_AUDIOSTATUS, - AUDIO_STATUS_ON, 0xFF) != 1) { + if (m4sensorhub_extern_set_audio_status(AUDIO_STATUS_ON) < 0) { dev_err(dev, "Unable to set screen status to 0x01\n"); mutex_unlock(&cdata->ctrl_mutex); return -EINVAL; @@ -189,9 +186,7 @@ static ssize_t c55_ctrl_enable(struct device *dev, cdata->c55_ap_int_enabled = 0; } - if (m4sensorhub_reg_write_1byte - (m4sensorhub, M4SH_REG_USERSETTINGS_AUDIOSTATUS, - AUDIO_STATUS_OFF, 0xFF) != 1) { + if (m4sensorhub_extern_set_audio_status(AUDIO_STATUS_OFF) < 0) { dev_err(dev, "Unable to set screen status to 0x00\n"); mutex_unlock(&cdata->ctrl_mutex); return -EINVAL; @@ -363,7 +358,6 @@ static int c55_ctrl_remove(struct platform_device *pdev) static int c55_ctrl_suspend(struct platform_device *dev, pm_message_t state) { struct c55_ctrl_data *cdata = dev_get_drvdata(&dev->dev); - struct m4sensorhub_data *m4sensorhub = m4sensorhub_client_get_drvdata(); if (cdata->c55_mode != C55_OFF) { dev_warn(&dev->dev, "C55 still ON when going into suspend\n"); @@ -375,9 +369,7 @@ static int c55_ctrl_suspend(struct platform_device *dev, pm_message_t state) cdata->c55_ap_int_enabled = 0; } - if (m4sensorhub_reg_write_1byte - (m4sensorhub, M4SH_REG_USERSETTINGS_AUDIOSTATUS, - AUDIO_STATUS_OFF, 0xFF) != 1) { + if (m4sensorhub_extern_set_audio_status(AUDIO_STATUS_OFF) < 0) { dev_err(&dev->dev, "Unable to set screen status to 0x00\n"); } diff --git a/drivers/misc/m4sensorhub_pedometer.c b/drivers/misc/m4sensorhub_pedometer.c index 9a990f014be..0be14698e1d 100644 --- a/drivers/misc/m4sensorhub_pedometer.c +++ b/drivers/misc/m4sensorhub_pedometer.c @@ -40,6 +40,8 @@ #define M4PED_IRQ_ENABLED_BIT 0 #define M4PED_FEATURE_ENABLED_BIT 1 +#define M4PED_USERDATA_SIZE 5 + struct m4ped_driver_data { struct platform_device *pdev; struct m4sensorhub_data *m4; @@ -48,9 +50,11 @@ struct m4ped_driver_data { struct m4sensorhub_pedometer_iio_data iiodat; struct m4sensorhub_pedometer_iio_data base_dat; struct m4sensorhub_pedometer_iio_data last_dat; - struct delayed_work m4ped_work; + struct delayed_work m4ped_work; + int16_t samplerate; int16_t fastest_rate; + uint8_t userdata[M4PED_USERDATA_SIZE]; uint16_t status; }; @@ -234,6 +238,42 @@ static void m4ped_work_func(struct work_struct *work) return; } +static int m4ped_write_userdata(struct m4ped_driver_data *dd) +{ + int err; + + err = m4sensorhub_reg_write(dd->m4, M4SH_REG_USERSETTINGS_USERAGE, + &(dd->userdata[0]), m4sh_no_mask); + if (err < 0) { + m4ped_err("%s: Failed to write age.\n", __func__); + goto m4ped_write_userdata_fail; + } + + err = m4sensorhub_reg_write(dd->m4, M4SH_REG_USERSETTINGS_USERGENDER, + &(dd->userdata[1]), m4sh_no_mask); + if (err < 0) { + m4ped_err("%s: Failed to write gender.\n", __func__); + goto m4ped_write_userdata_fail; + } + + err = m4sensorhub_reg_write(dd->m4, M4SH_REG_USERSETTINGS_USERHEIGHT, + &(dd->userdata[2]), m4sh_no_mask); + if (err < 0) { + m4ped_err("%s: Failed to write height.\n", __func__); + goto m4ped_write_userdata_fail; + } + + err = m4sensorhub_reg_write(dd->m4, M4SH_REG_USERSETTINGS_USERWEIGHT, + &(dd->userdata[3]), m4sh_no_mask); + if (err < 0) { + m4ped_err("%s: Failed to write weight.\n", __func__); + goto m4ped_write_userdata_fail; + } + +m4ped_write_userdata_fail: + return err; +} + static int m4ped_set_samplerate(struct iio_dev *iio, int16_t rate) { int err = 0; @@ -352,11 +392,11 @@ static ssize_t m4ped_userdata_show(struct device *dev, struct iio_dev *iio = platform_get_drvdata(pdev); struct m4ped_driver_data *dd = iio_priv(iio); ssize_t size = 0; - uint8_t data[5] = {0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t data[M4PED_USERDATA_SIZE] = {0x00}; mutex_lock(&(dd->mutex)); - err = m4sensorhub_reg_read_n(dd->m4, M4SH_REG_USERSETTINGS_SCREENSTATUS, + err = m4sensorhub_reg_read_n(dd->m4, M4SH_REG_USERSETTINGS_USERAGE, (char *)&(data[0]), ARRAY_SIZE(data)); if (err < 0) { m4ped_err("%s: Failed to read user data.\n", __func__); @@ -369,11 +409,11 @@ static ssize_t m4ped_userdata_show(struct device *dev, } size = snprintf(buf, PAGE_SIZE, - "%s%s\n%s%hhu\n%s%hhu\n%s%hhu\n", - "Gender (M/F): ", data[2] ? "M" : "F", - "Age (yrs): ", data[1], - "Height (cm): ", data[3], - "Weight (kg): ", data[4]); + "%s%s\n%s%hhu\n%s%hhu\n%s%hu\n", + "Gender (M/F): ", data[1] ? "M" : "F", + "Age (yrs): ", data[0], + "Height (cm): ", data[2], + "Weight (kg): ", data[3] | (data[4] << 8)); m4ped_userdata_show_fail: mutex_unlock(&(dd->mutex)); @@ -388,6 +428,7 @@ m4ped_userdata_show_fail: * Example: * Female, 22, 168cm, 49kg * 0x00,0x16,0xA7,0x31\n + * echo 0x00,0x16,0xA7,0x31 > userdata */ static ssize_t m4ped_userdata_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) @@ -398,7 +439,7 @@ static ssize_t m4ped_userdata_store(struct device *dev, struct m4ped_driver_data *dd = iio_priv(iio); unsigned int value = 0; unsigned char convbuf[5] = {0x00, 0x00, 0x00, 0x00, 0x00}; - unsigned char outbuf[4] = {0x00, 0x00, 0x00, 0x00}; + unsigned char outbuf[M4PED_USERDATA_SIZE] = {0x00}; int i = 0; mutex_lock(&(dd->mutex)); @@ -427,31 +468,16 @@ static ssize_t m4ped_userdata_store(struct device *dev, outbuf[i] = (unsigned char) value; } - err = m4sensorhub_reg_write(dd->m4, M4SH_REG_USERSETTINGS_USERAGE, - &(outbuf[1]), m4sh_no_mask); - if (err < 0) { - m4ped_err("%s: Failed to write user data.\n", __func__); - goto m4ped_userdata_store_fail; - } + for (i = 0; i < M4PED_USERDATA_SIZE; i++) + dd->userdata[i] = outbuf[i]; - err = m4sensorhub_reg_write(dd->m4, M4SH_REG_USERSETTINGS_USERGENDER, - &(outbuf[0]), m4sh_no_mask); - if (err < 0) { - m4ped_err("%s: Failed to write user data.\n", __func__); - goto m4ped_userdata_store_fail; - } + dd->userdata[0] = outbuf[1]; /* Age */ + dd->userdata[1] = outbuf[0]; /* Gender */ - err = m4sensorhub_reg_write(dd->m4, M4SH_REG_USERSETTINGS_USERHEIGHT, - &(outbuf[2]), m4sh_no_mask); - if (err < 0) { - m4ped_err("%s: Failed to write user data.\n", __func__); - goto m4ped_userdata_store_fail; - } - - err = m4sensorhub_reg_write_n(dd->m4, M4SH_REG_USERSETTINGS_USERWEIGHT, - &(outbuf[3]), m4sh_no_mask, 1); + err = m4ped_write_userdata(dd); if (err < 0) { - m4ped_err("%s: Failed to write user data.\n", __func__); + m4ped_err("%s: Failed to write user data (%d).\n", + __func__, err); goto m4ped_userdata_store_fail; } @@ -660,6 +686,13 @@ static void m4ped_panic_restore(struct m4sensorhub_data *m4sensorhub, mutex_lock(&(dd->mutex)); + err = m4ped_write_userdata(dd); + if (err < 0) { + m4ped_err("%s: Failed to write user data (%d).\n", + __func__, err); + goto m4ped_panic_restore_fail; + } + if (!(dd->status & (1 << M4PED_FEATURE_ENABLED_BIT))) { err = m4sensorhub_reg_write(dd->m4, M4SH_REG_PEDOMETER_ENABLE, &disable, m4sh_no_mask); @@ -751,6 +784,12 @@ static int m4ped_probe(struct platform_device *pdev) dd->fastest_rate = 1000; /* in milli secs */ dd->status = dd->status | (1 << M4PED_FEATURE_ENABLED_BIT); + dd->userdata[0] = 0x23; /* Age (35) */ + dd->userdata[1] = 0x01; /* Gender (Male) */ + dd->userdata[2] = 0xB2; /* Height (178cm) */ + dd->userdata[3] = 0x5B; /* Weight (91kg) */ + dd->userdata[4] = 0x00; /* Weight */ + err = m4ped_create_iiodev(iio); /* iio and dd are freed on fail */ if (err < 0) { m4ped_err("%s: Failed to create IIO device.\n", __func__); diff --git a/drivers/video/omap2/displays/panel-minnow.c b/drivers/video/omap2/displays/panel-minnow.c index cc231d4da58..59c3113dea4 100644 --- a/drivers/video/omap2/displays/panel-minnow.c +++ b/drivers/video/omap2/displays/panel-minnow.c @@ -3181,7 +3181,6 @@ static void minnow_panel_disable_mlocked(struct minnow_panel_data *mpd) static void minnow_panel_sync_display_status_mlocked( struct minnow_panel_data *mpd) { - struct m4sensorhub_data *m4sensorhub; enum display_state m4_state = mpd->state; /* special case for dock mode, set to DISPLAY_ENABLE * to block all wakeup gestures @@ -3194,21 +3193,19 @@ static void minnow_panel_sync_display_status_mlocked( /* be safety to sync resume states first */ minnow_panel_sync_resume_mlocked(mpd); - m4sensorhub = m4sensorhub_client_get_drvdata(); - if (m4sensorhub->mode != NORMALMODE) { + if (m4sensorhub_get_current_mode() != NORMALMODE) { dev_err(&mpd->dssdev->dev, "M4 is not ready, unable to set screen status(%d)\n", m4_state); return; } - if (m4sensorhub_reg_write_1byte(m4sensorhub, - M4SH_REG_USERSETTINGS_SCREENSTATUS, - m4_state, 0xFF) != 1) { + + if (m4sensorhub_extern_set_display_status(m4_state) < 0) { dev_err(&mpd->dssdev->dev, - "Unable to set screen status(%d) to M4\n", - m4_state); + "Unable to set screen status(%d) to M4\n", m4_state); return; } + dev_dbg(&mpd->dssdev->dev, "Set screen status(%d) to M4 success!\n", m4_state); mpd->m4_state = m4_state; diff --git a/include/linux/m4sensorhub.h b/include/linux/m4sensorhub.h index 5bc54f0885b..5eb2ec0586f 100644 --- a/include/linux/m4sensorhub.h +++ b/include/linux/m4sensorhub.h @@ -73,6 +73,7 @@ enum m4sensorhub_panichdl_index { PANICHDL_ALS_RESTORE, PANICHDL_MPU9150_RESTORE, PANICHDL_PEDOMETER_RESTORE, + PANICHDL_EXTERN_RESTORE, /* * Please add enum before PANICHDL_IRQ_RESTORE * to make sure IRQ restore will be called last. @@ -241,5 +242,11 @@ bool m4sensorhub_preflash_callbacks_exist(void); /* For FW flash core */ int m4sensorhub_irq_disable_all(struct m4sensorhub_data *m4sensorhub); +/* External System Calls for Non-M4 Drivers */ +int m4sensorhub_extern_init(struct m4sensorhub_data *m4); /* Init for core */ +int m4sensorhub_extern_set_audio_status(uint8_t status); +int m4sensorhub_extern_set_display_status(uint8_t status); +int m4sensorhub_get_current_mode(void); + #endif /* __KERNEL__ */ #endif /* __M4SENSORHUB_H__ */ |