summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/mfd/Makefile1
-rw-r--r--drivers/mfd/m4sensorhub-core.c12
-rw-r--r--drivers/mfd/m4sensorhub-extern.c158
-rw-r--r--drivers/mfd/m4sensorhub-panic.c1
-rw-r--r--drivers/misc/c55_ctrl.c16
-rw-r--r--drivers/misc/m4sensorhub_pedometer.c101
-rw-r--r--drivers/video/omap2/displays/panel-minnow.c13
-rw-r--r--include/linux/m4sensorhub.h7
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__ */