summaryrefslogtreecommitdiff
path: root/drivers/input/misc/lps001wp_prs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/misc/lps001wp_prs.c')
-rw-r--r--drivers/input/misc/lps001wp_prs.c389
1 files changed, 274 insertions, 115 deletions
diff --git a/drivers/input/misc/lps001wp_prs.c b/drivers/input/misc/lps001wp_prs.c
index cb60762ac61..1618dfaa16f 100644
--- a/drivers/input/misc/lps001wp_prs.c
+++ b/drivers/input/misc/lps001wp_prs.c
@@ -49,12 +49,12 @@
#include <linux/regulator/consumer.h>
#include <linux/input/lps001wp.h>
-
-
+#ifdef CONFIG_HAS_EARLYSUSPEND
+#include <linux/earlysuspend.h>
+#endif
#define DEBUG 1
-
#define PR_ABS_MAX 0xffff
#define PR_ABS_MIN 0x0000
#define PR_DLT_MAX 0x7ffff
@@ -68,7 +68,7 @@
#define OUTDATA_REG 0x28
-#define INDATA_REG 0X30
+#define REF_PRESS_REG 0X30
#define WHOAMI_LPS001WP_PRS 0xBA /* Expctd content for WAI */
@@ -83,7 +83,7 @@
#define PRESS_OUT_L OUTDATA_REG
-#define REF_P_L INDATA_REG /* pressure reference */
+#define REF_P_L REF_PRESS_REG /* pressure reference */
#define REF_P_H 0x31 /* pressure reference */
#define THS_P_L 0x32 /* pressure threshold */
#define THS_P_H 0x33 /* pressure threshold */
@@ -97,9 +97,8 @@
/* Barometer and Termometer output data rate ODR */
#define LPS001WP_PRS_ODR_MASK 0x30 /* Mask to access odr bits only */
#define LPS001WP_PRS_ODR_7_1 0x00 /* 7Hz baro and 1Hz term ODR */
-#define LPS001WP_PRS_ODR_7_7 0x01 /* 7Hz baro and 7Hz term ODR */
-#define LPS001WP_PRS_ODR_12_12 0x11 /* 12.5Hz baro and 12.5Hz term ODR */
-
+#define LPS001WP_PRS_ODR_7_7 0x10 /* 7Hz baro and 7Hz term ODR */
+#define LPS001WP_PRS_ODR_12_12 0x30 /* 12.5Hz baro and 12.5Hz term ODR */
#define LPS001WP_PRS_ENABLE_MASK 0x40 /* */
#define LPS001WP_PRS_DIFF_MASK 0x08
@@ -145,14 +144,36 @@ static const struct {
{1000, LPS001WP_PRS_ODR_7_1 },
};
+/**
+ * struct lps001wp_prs_data - data structure used by lps001wp_prs driver
+ * @client: i2c client
+ * @pdata: lsm303dlh platform data
+ * @lock: mutex lock for sysfs operations
+ * @input_work: work queue to read sensor data
+ * @input_dev: input device
+ * @regulator: regulator
+ * @early_suspend: early suspend structure
+ * @hw_initialized: saves hw initialisation status
+ * @hw_working: saves hw status
+ * @diff_enabled: store value of diff enable
+ * @lpowmode_enabled: flag to set lowpower mode
+ * @enabled: to store mode of device
+ * @on_before_suspend: to store status of device during suspend
+ * @resume_state:store regester values
+ * @reg_addr: stores reg address to debug
+ */
struct lps001wp_prs_data {
struct i2c_client *client;
struct lps001wp_prs_platform_data *pdata;
struct mutex lock;
+#ifdef CONFIG_LPS001WP_INPUT_DEVICE
struct delayed_work input_work;
-
struct input_dev *input_dev;
+#endif
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ struct early_suspend early_suspend;
+#endif
int hw_initialized;
/* hw_working=-1 means not tested yet */
@@ -178,6 +199,11 @@ struct outputdata {
s16 deltapress;
};
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void lps001wp_prs_early_suspend(struct early_suspend *data);
+static void lps001wp_prs_late_resume(struct early_suspend *data);
+#endif
+
static int lps001wp_prs_i2c_read(struct lps001wp_prs_data *prs,
u8 *buf, int len)
@@ -246,30 +272,10 @@ static int lps001wp_prs_i2c_write(struct lps001wp_prs_data *prs,
return err;
}
-static int lps001wp_prs_i2c_update(struct lps001wp_prs_data *prs,
- u8 reg_address, u8 mask, u8 new_bit_values)
-{
- int err = -1;
- u8 rdbuf[1] = { reg_address };
- u8 wrbuf[2] = { reg_address , 0x00 };
-
- u8 init_val;
- u8 updated_val;
- err = lps001wp_prs_i2c_read(prs, rdbuf, 1);
- if (!(err < 0)) {
- init_val = rdbuf[0];
- updated_val = ((mask & new_bit_values) | ((~mask) & init_val));
- wrbuf[1] = updated_val;
- err = lps001wp_prs_i2c_write(prs, wrbuf, 2);
- }
- return err;
-}
-/* */
-
static int lps001wp_prs_register_write(struct lps001wp_prs_data *prs, u8 *buf,
u8 reg_address, u8 new_value)
{
- int err = -1;
+ int err = -EINVAL;
/* Sets configuration register at reg_address
* NOTE: this is a straight overwrite */
@@ -285,7 +291,7 @@ static int lps001wp_prs_register_read(struct lps001wp_prs_data *prs, u8 *buf,
u8 reg_address)
{
- int err = -1;
+ int err = -EINVAL;
buf[0] = (reg_address);
err = lps001wp_prs_i2c_read(prs, buf, 1);
@@ -295,7 +301,7 @@ static int lps001wp_prs_register_read(struct lps001wp_prs_data *prs, u8 *buf,
static int lps001wp_prs_register_update(struct lps001wp_prs_data *prs, u8 *buf,
u8 reg_address, u8 mask, u8 new_bit_values)
{
- int err = -1;
+ int err = -EINVAL;
u8 init_val;
u8 updated_val;
err = lps001wp_prs_register_read(prs, buf, reg_address);
@@ -313,10 +319,11 @@ static int lps001wp_prs_register_update(struct lps001wp_prs_data *prs, u8 *buf,
static int lps001wp_prs_hw_init(struct lps001wp_prs_data *prs)
{
- int err = -1;
+ int err = -EINVAL;
u8 buf[6];
- printk(KERN_DEBUG "%s: hw init start\n", LPS001WP_PRS_DEV_NAME);
+ dev_dbg(&prs->client->dev, "%s: hw init start\n",
+ LPS001WP_PRS_DEV_NAME);
buf[0] = WHO_AM_I;
err = lps001wp_prs_i2c_read(prs, buf, 1);
@@ -325,12 +332,12 @@ static int lps001wp_prs_hw_init(struct lps001wp_prs_data *prs)
else
prs->hw_working = 1;
if (buf[0] != WHOAMI_LPS001WP_PRS) {
- err = -1; /* TODO:choose the right coded error */
+ err = -EINVAL; /* TODO:choose the right coded error */
goto error_unknown_device;
}
- buf[0] = (I2C_AUTO_INCREMENT | INDATA_REG);
+ buf[0] = (I2C_AUTO_INCREMENT | REF_PRESS_REG);
buf[1] = prs->resume_state[RES_REF_P_L];
buf[2] = prs->resume_state[RES_REF_P_H];
buf[3] = prs->resume_state[RES_THS_P_L];
@@ -355,7 +362,7 @@ static int lps001wp_prs_hw_init(struct lps001wp_prs_data *prs)
prs->hw_initialized = 1;
- printk(KERN_DEBUG "%s: hw init done\n", LPS001WP_PRS_DEV_NAME);
+ dev_dbg(&prs->client->dev, "%s: hw init done\n", LPS001WP_PRS_DEV_NAME);
return 0;
error_firstread:
@@ -398,7 +405,7 @@ static void lps001wp_prs_device_power_off(struct lps001wp_prs_data *prs)
static int lps001wp_prs_device_power_on(struct lps001wp_prs_data *prs)
{
- int err = -1;
+ int err = -EINVAL;
/* get the regulator the first time */
if (!prs->regulator) {
@@ -432,7 +439,7 @@ static int lps001wp_prs_device_power_on(struct lps001wp_prs_data *prs)
int lps001wp_prs_update_odr(struct lps001wp_prs_data *prs, int poll_interval_ms)
{
- int err = -1;
+ int err = -EINVAL;
int i;
u8 buf[2];
@@ -483,12 +490,17 @@ error:
static int lps001wp_prs_set_press_reference(struct lps001wp_prs_data *prs,
u16 new_reference)
{
- int err = -1;
+ int err = -EINVAL;
u8 const reg_addressL = REF_P_L;
u8 const reg_addressH = REF_P_H;
u8 bit_valuesL, bit_valuesH;
u8 buf[2];
-
+ /*
+ * We need to set new configurations, only if device
+ * is currently enabled
+ */
+ if (!atomic_read(&prs->enabled))
+ return err;
bit_valuesL = (u8) (new_reference & 0x00FF);
bit_valuesH = (u8)((new_reference & 0xFF00) >> 8);
@@ -511,12 +523,17 @@ static int lps001wp_prs_set_press_reference(struct lps001wp_prs_data *prs,
static int lps001wp_prs_get_press_reference(struct lps001wp_prs_data *prs,
u16 *buf16)
{
- int err = -1;
+ int err = -EINVAL;
u8 bit_valuesL, bit_valuesH;
u8 buf[2] = {0};
u16 temp = 0;
-
+ /*
+ * We need to read configurations, only if device
+ * is currently enabled
+ */
+ if (!atomic_read(&prs->enabled))
+ return err;
err = lps001wp_prs_register_read(prs, buf, REF_P_L);
if (err < 0)
return err;
@@ -534,11 +551,17 @@ static int lps001wp_prs_get_press_reference(struct lps001wp_prs_data *prs,
static int lps001wp_prs_lpow_manage(struct lps001wp_prs_data *prs, u8 control)
{
- int err = -1;
+ int err = -EINVAL;
u8 buf[2] = {0x00, 0x00};
u8 const mask = LPS001WP_PRS_LPOW_MASK;
u8 bit_values = LPS001WP_PRS_LPOW_OFF;
+ /*
+ * We need to set new configurations, only if device
+ * is currently enabled
+ */
+ if (!atomic_read(&prs->enabled))
+ return err;
if (control >= LPS001WP_PRS_LPOWER_EN) {
bit_values = LPS001WP_PRS_LPOW_ON;
}
@@ -559,11 +582,17 @@ static int lps001wp_prs_lpow_manage(struct lps001wp_prs_data *prs, u8 control)
static int lps001wp_prs_diffen_manage(struct lps001wp_prs_data *prs, u8 control)
{
- int err = -1;
+ int err = -EINVAL;
u8 buf[2] = {0x00, 0x00};
u8 const mask = LPS001WP_PRS_DIFF_MASK;
u8 bit_values = LPS001WP_PRS_DIFF_OFF;
+ /*
+ * We need to set new configurations, only if device
+ * is currently enabled
+ */
+ if (!atomic_read(&prs->enabled))
+ return err;
if (control >= LPS001WP_PRS_DIFF_ENABLE) {
bit_values = LPS001WP_PRS_DIFF_ON;
}
@@ -586,7 +615,7 @@ static int lps001wp_prs_diffen_manage(struct lps001wp_prs_data *prs, u8 control)
static int lps001wp_prs_get_presstemp_data(struct lps001wp_prs_data *prs,
struct outputdata *out)
{
- int err = -1;
+ int err = -EINVAL;
/* Data bytes from hardware PRESS_OUT_L, PRESS_OUT_H,
* TEMP_OUT_L, TEMP_OUT_H,
* DELTA_L, DELTA_H */
@@ -609,8 +638,8 @@ static int lps001wp_prs_get_presstemp_data(struct lps001wp_prs_data *prs,
abspr = ((((u16) prs_data[1] << 8) | ((u16) prs_data[0])));
temperature = ((s16) (((u16) prs_data[3] << 8) | ((u16)prs_data[2])));
- out->abspress = abspr;
- out->temperature = temperature;
+ out->abspress = (abspr >> SENSITIVITY_P_SHIFT);
+ out->temperature = (temperature >> SENSITIVITY_T_SHIFT);
deltapr = ((s16) (((u16) prs_data[5] << 8) | ((u16)prs_data[4])));
out->deltapress = deltapr;
@@ -618,6 +647,7 @@ static int lps001wp_prs_get_presstemp_data(struct lps001wp_prs_data *prs,
return err;
}
+#ifdef CONFIG_LPS001WP_INPUT_DEVICE
static void lps001wp_prs_report_values(struct lps001wp_prs_data *prs,
struct outputdata *out)
{
@@ -626,19 +656,24 @@ static void lps001wp_prs_report_values(struct lps001wp_prs_data *prs,
input_report_abs(prs->input_dev, ABS_DLTPR, out->deltapress);
input_sync(prs->input_dev);
}
+#endif
static int lps001wp_prs_enable(struct lps001wp_prs_data *prs)
{
int err;
if (!atomic_cmpxchg(&prs->enabled, 0, 1)) {
+ if (prs->regulator)
+ regulator_enable(prs->regulator);
err = lps001wp_prs_device_power_on(prs);
if (err < 0) {
atomic_set(&prs->enabled, 0);
return err;
}
+#ifdef CONFIG_LPS001WP_INPUT_DEVICE
schedule_delayed_work(&prs->input_work,
msecs_to_jiffies(prs->pdata->poll_interval));
+#endif
}
return 0;
@@ -647,44 +682,17 @@ static int lps001wp_prs_enable(struct lps001wp_prs_data *prs)
static int lps001wp_prs_disable(struct lps001wp_prs_data *prs)
{
if (atomic_cmpxchg(&prs->enabled, 1, 0)) {
+#ifdef CONFIG_LPS001WP_INPUT_DEVICE
cancel_delayed_work_sync(&prs->input_work);
+#endif
lps001wp_prs_device_power_off(prs);
+ if (prs->regulator)
+ regulator_disable(prs->regulator);
}
return 0;
}
-static ssize_t read_single_reg(struct device *dev, char *buf, u8 reg)
-{
- ssize_t ret;
- struct lps001wp_prs_data *prs = dev_get_drvdata(dev);
- int rc = 0;
-
- u8 data = reg;
- rc = lps001wp_prs_i2c_read(prs, &data, 1);
- /*TODO: error need to be managed */
- ret = sprintf(buf, "0x%02x\n", data);
- return ret;
-
-}
-
-static int write_reg(struct device *dev, const char *buf, u8 reg)
-{
- int rc = 0;
- struct lps001wp_prs_data *prs = dev_get_drvdata(dev);
- u8 x[2];
- unsigned long val;
-
- if (strict_strtoul(buf, 16, &val))
- return -EINVAL;
-
- x[0] = reg;
- x[1] = val;
- rc = lps001wp_prs_i2c_write(prs, x, 1);
- /*TODO: error need to be managed */
- return rc;
-}
-
static ssize_t attr_get_polling_rate(struct device *dev,
struct device_attribute *attr,
char *buf)
@@ -703,6 +711,7 @@ static ssize_t attr_set_polling_rate(struct device *dev,
{
struct lps001wp_prs_data *prs = dev_get_drvdata(dev);
unsigned long interval_ms;
+ int err = -EINVAL;
if (strict_strtoul(buf, 10, &interval_ms))
return -EINVAL;
@@ -710,7 +719,12 @@ static ssize_t attr_set_polling_rate(struct device *dev,
return -EINVAL;
mutex_lock(&prs->lock);
prs->pdata->poll_interval = interval_ms;
- lps001wp_prs_update_odr(prs, interval_ms);
+ err = lps001wp_prs_update_odr(prs, interval_ms);
+ if (err < 0) {
+ dev_err(&prs->client->dev, "failed to update odr %ld\n",
+ interval_ms);
+ size = err;
+ }
mutex_unlock(&prs->lock);
return size;
}
@@ -733,12 +747,18 @@ static ssize_t attr_set_diff_enable(struct device *dev,
{
struct lps001wp_prs_data *prs = dev_get_drvdata(dev);
unsigned long val;
+ int err = -EINVAL;
if (strict_strtoul(buf, 10, &val))
return -EINVAL;
mutex_lock(&prs->lock);
- lps001wp_prs_diffen_manage(prs, (u8) val);
+ err = lps001wp_prs_diffen_manage(prs, (u8) val);
+ if (err < 0) {
+ dev_err(&prs->client->dev, "failed to diff enable %ld\n", val);
+ mutex_unlock(&prs->lock);
+ return err;
+ }
mutex_unlock(&prs->lock);
return size;
}
@@ -772,15 +792,17 @@ static ssize_t attr_set_enable(struct device *dev,
static ssize_t attr_get_press_ref(struct device *dev,
struct device_attribute *attr, char *buf)
{
- int err = -1;
+ int err = -EINVAL;
struct lps001wp_prs_data *prs = dev_get_drvdata(dev);
u16 val = 0;
mutex_lock(&prs->lock);
err = lps001wp_prs_get_press_reference(prs, &val);
mutex_unlock(&prs->lock);
- if (err < 0)
+ if (err < 0) {
+ dev_err(&prs->client->dev, "failed to get ref press\n");
return err;
+ }
return sprintf(buf, "%d\n", val);
}
@@ -789,7 +811,7 @@ static ssize_t attr_set_press_ref(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
{
- int err = -1;
+ int err = -EINVAL;
struct lps001wp_prs_data *prs = dev_get_drvdata(dev);
unsigned long val = 0;
@@ -802,8 +824,11 @@ static ssize_t attr_set_press_ref(struct device *dev,
mutex_lock(&prs->lock);
err = lps001wp_prs_set_press_reference(prs, val);
mutex_unlock(&prs->lock);
- if (err < 0)
+ if (err < 0) {
+ dev_err(&prs->client->dev, "failed to set ref press %ld\n",
+ val);
return err;
+ }
return size;
}
@@ -823,7 +848,7 @@ static ssize_t attr_set_lowpowmode(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
{
- int err = -1;
+ int err = -EINVAL;
struct lps001wp_prs_data *prs = dev_get_drvdata(dev);
unsigned long val;
@@ -833,12 +858,86 @@ static ssize_t attr_set_lowpowmode(struct device *dev,
mutex_lock(&prs->lock);
err = lps001wp_prs_lpow_manage(prs, (u8) val);
mutex_unlock(&prs->lock);
- if (err < 0)
+ if (err < 0) {
+ dev_err(&prs->client->dev, "failed to set low powermode\n");
return err;
+ }
return size;
}
+static ssize_t lps001wp_prs_get_press_data(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct lps001wp_prs_data *prs = dev_get_drvdata(dev);
+ struct outputdata out;
+ int err = -EINVAL;
+ mutex_lock(&prs->lock);
+ /*
+ * If device is currently enabled, we need to read
+ * data from it.
+ */
+ if (!atomic_read(&prs->enabled))
+ goto out;
+ err = lps001wp_prs_get_presstemp_data(prs, &out);
+ if (err < 0) {
+ dev_err(&prs->client->dev, "get_pressure_data failed\n");
+ goto out;
+ }
+ mutex_unlock(&prs->lock);
+ return sprintf(buf, "%d", out.abspress);
+out:
+ mutex_unlock(&prs->lock);
+ return err;
+}
+static ssize_t lps001wp_prs_get_deltapr_data(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct lps001wp_prs_data *prs = dev_get_drvdata(dev);
+ struct outputdata out;
+ int err = -EINVAL;
+ mutex_lock(&prs->lock);
+ /*
+ * If device is currently enabled, we need to read
+ * data from it.
+ */
+ if (!atomic_read(&prs->enabled)) {
+ mutex_unlock(&prs->lock);
+ return err;
+ }
+ err = lps001wp_prs_get_presstemp_data(prs, &out);
+ if (err < 0) {
+ dev_err(&prs->client->dev, "get_deltapress_data failed\n");
+ mutex_unlock(&prs->lock);
+ return err;
+ }
+ mutex_unlock(&prs->lock);
+ return sprintf(buf, "%d", out.deltapress);
+}
+static ssize_t lps001wp_prs_get_temp_data(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct lps001wp_prs_data *prs = dev_get_drvdata(dev);
+ struct outputdata out;
+ int err = -EINVAL;
+ mutex_lock(&prs->lock);
+ /*
+ * If device is currently enabled, we need to read
+ * data from it.
+ */
+ if (!atomic_read(&prs->enabled)) {
+ mutex_unlock(&prs->lock);
+ return err;
+ }
+ err = lps001wp_prs_get_presstemp_data(prs, &out);
+ if (err < 0) {
+ dev_err(&prs->client->dev, "get_temperature_data failed\n");
+ mutex_unlock(&prs->lock);
+ return err;
+ }
+ mutex_unlock(&prs->lock);
+ return sprintf(buf, "%d", out.temperature);
+}
#ifdef DEBUG
static ssize_t attr_reg_set(struct device *dev, struct device_attribute *attr,
const char *buf, size_t size)
@@ -893,14 +992,21 @@ static ssize_t attr_addr_set(struct device *dev, struct device_attribute *attr,
static struct device_attribute attributes[] = {
- __ATTR(pollrate_ms, 0664, attr_get_polling_rate, attr_set_polling_rate),
- __ATTR(enable, 0664, attr_get_enable, attr_set_enable),
- __ATTR(diff_enable, 0664, attr_get_diff_enable, attr_set_diff_enable),
- __ATTR(press_reference, 0664, attr_get_press_ref, attr_set_press_ref),
- __ATTR(lowpow_enable, 0664, attr_get_lowpowmode, attr_set_lowpowmode),
+ __ATTR(pollrate_ms, S_IWUSR | S_IRUGO, attr_get_polling_rate,
+ attr_set_polling_rate),
+ __ATTR(enable, S_IWUSR | S_IRUGO, attr_get_enable, attr_set_enable),
+ __ATTR(diff_enable, S_IWUSR | S_IRUGO, attr_get_diff_enable,
+ attr_set_diff_enable),
+ __ATTR(press_reference, S_IWUSR | S_IRUGO, attr_get_press_ref,
+ attr_set_press_ref),
+ __ATTR(lowpow_enable, S_IWUSR | S_IRUGO, attr_get_lowpowmode,
+ attr_set_lowpowmode),
+ __ATTR(press_data, S_IRUGO, lps001wp_prs_get_press_data, NULL),
+ __ATTR(temp_data, S_IRUGO, lps001wp_prs_get_temp_data, NULL),
+ __ATTR(deltapr_data, S_IRUGO, lps001wp_prs_get_deltapr_data, NULL),
#ifdef DEBUG
- __ATTR(reg_value, 0664, attr_reg_get, attr_reg_set),
- __ATTR(reg_addr, 0220, NULL, attr_addr_set),
+ __ATTR(reg_value, S_IWUSR | S_IRUGO, attr_reg_get, attr_reg_set),
+ __ATTR(reg_addr, S_IWUSR, NULL, attr_addr_set),
#endif
};
@@ -927,7 +1033,7 @@ static int remove_sysfs_interfaces(struct device *dev)
return 0;
}
-
+#ifdef CONFIG_LPS001WP_INPUT_DEVICE
static void lps001wp_prs_input_work_func(struct work_struct *work)
{
struct lps001wp_prs_data *prs;
@@ -964,7 +1070,7 @@ void lps001wp_prs_input_close(struct input_dev *dev)
lps001wp_prs_disable(prs);
}
-
+#endif
static int lps001wp_prs_validate_pdata(struct lps001wp_prs_data *prs)
{
@@ -979,11 +1085,10 @@ static int lps001wp_prs_validate_pdata(struct lps001wp_prs_data *prs)
return 0;
}
-
+#ifdef CONFIG_LPS001WP_INPUT_DEVICE
static int lps001wp_prs_input_init(struct lps001wp_prs_data *prs)
{
int err;
-
INIT_DELAYED_WORK(&prs->input_work, lps001wp_prs_input_work_func);
prs->input_dev = input_allocate_device();
if (!prs->input_dev) {
@@ -1033,12 +1138,12 @@ static void lps001wp_prs_input_cleanup(struct lps001wp_prs_data *prs)
input_unregister_device(prs->input_dev);
input_free_device(prs->input_dev);
}
-
+#endif
static int lps001wp_prs_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct lps001wp_prs_data *prs;
- int err = -1;
+ int err = -EINVAL;
int tempvalue;
pr_info("%s: probe start.\n", LPS001WP_PRS_DEV_NAME);
@@ -1088,23 +1193,31 @@ static int lps001wp_prs_probe(struct i2c_client *client,
prs->client = client;
i2c_set_clientdata(client, prs);
+ prs->regulator = regulator_get(&client->dev, "vdd");
+ if (IS_ERR(prs->regulator)) {
+ dev_err(&client->dev, "failed to get regulator\n");
+ err = PTR_ERR(prs->regulator);
+ prs->regulator = NULL;
+ }
+ if (prs->regulator)
+ regulator_enable(prs->regulator);
if (i2c_smbus_read_byte(client) < 0) {
- printk(KERN_ERR "i2c_smbus_read_byte error!!\n");
+ dev_err(&client->dev, "i2c_smbus_read_byte error!!\n");
goto err_mutexunlockfreedata;
} else {
- printk(KERN_DEBUG "%s Device detected!\n",
+ dev_dbg(&client->dev, "%s Device detected!\n",
LPS001WP_PRS_DEV_NAME);
}
/* read chip id */
tempvalue = i2c_smbus_read_word_data(client, WHO_AM_I);
if ((tempvalue & 0x00FF) == WHOAMI_LPS001WP_PRS) {
- printk(KERN_DEBUG "%s I2C driver registered!\n",
+ dev_dbg(&client->dev, "%s I2C driver registered!\n",
LPS001WP_PRS_DEV_NAME);
} else {
prs->client = NULL;
- printk(KERN_DEBUG "I2C driver not registered!"
+ dev_dbg(&client->dev, "I2C driver not registered!"
" Device unknown\n");
goto err_mutexunlockfreedata;
}
@@ -1163,13 +1276,13 @@ static int lps001wp_prs_probe(struct i2c_client *client,
dev_err(&client->dev, "update_odr failed\n");
goto err_power_off;
}
-
+#ifdef CONFIG_LPS001WP_INPUT_DEVICE
err = lps001wp_prs_input_init(prs);
if (err < 0) {
dev_err(&client->dev, "input init failed\n");
goto err_power_off;
}
-
+#endif
err = create_sysfs_interfaces(&client->dev);
if (err < 0) {
@@ -1177,10 +1290,20 @@ static int lps001wp_prs_probe(struct i2c_client *client,
"device LPS001WP_PRS_DEV_NAME sysfs register failed\n");
goto err_input_cleanup;
}
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ prs->early_suspend.level =
+ EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
+ prs->early_suspend.suspend = lps001wp_prs_early_suspend;
+ prs->early_suspend.resume = lps001wp_prs_late_resume;
+ register_early_suspend(&prs->early_suspend);
+#endif
lps001wp_prs_device_power_off(prs);
+ if (prs->regulator)
+ regulator_disable(prs->regulator);
+
/* As default, do not report information */
atomic_set(&prs->enabled, 0);
@@ -1196,7 +1319,9 @@ remove_sysfs_int:
remove_sysfs_interfaces(&client->dev);
*/
err_input_cleanup:
+#ifdef CONFIG_LPS001WP_INPUT_DEVICE
lps001wp_prs_input_cleanup(prs);
+#endif
err_power_off:
lps001wp_prs_device_power_off(prs);
err2:
@@ -1207,10 +1332,15 @@ exit_kfree_pdata:
err_mutexunlockfreedata:
mutex_unlock(&prs->lock);
+ if (prs->regulator) {
+ regulator_disable(prs->regulator);
+ regulator_put(prs->regulator);
+ }
kfree(prs);
exit_alloc_data_failed:
exit_check_functionality_failed:
- printk(KERN_ERR "%s: Driver Init failed\n", LPS001WP_PRS_DEV_NAME);
+ dev_err(&client->dev, "%s: Driver Init failed\n",
+ LPS001WP_PRS_DEV_NAME);
return err;
}
@@ -1218,9 +1348,17 @@ static int __devexit lps001wp_prs_remove(struct i2c_client *client)
{
struct lps001wp_prs_data *prs = i2c_get_clientdata(client);
+#ifdef CONFIG_LPS001WP_INPUT_DEVICE
lps001wp_prs_input_cleanup(prs);
+#endif
lps001wp_prs_device_power_off(prs);
remove_sysfs_interfaces(&client->dev);
+ if (prs->regulator) {
+ /* Disable the regulator if device is enabled. */
+ if (atomic_read(&prs->enabled))
+ regulator_disable(prs->regulator);
+ regulator_put(prs->regulator);
+ }
if (prs->pdata->exit)
prs->pdata->exit();
@@ -1233,24 +1371,44 @@ static int __devexit lps001wp_prs_remove(struct i2c_client *client)
return 0;
}
-
-static int lps001wp_prs_resume(struct i2c_client *client)
+#if (!defined(CONFIG_HAS_EARLYSUSPEND) && defined(CONFIG_PM))
+static int lps001wp_prs_resume(struct device *dev)
{
- struct lps001wp_prs_data *prs = i2c_get_clientdata(client);
+ struct lps001wp_prs_data *prs = dev_get_drvdata(dev);
if (prs->on_before_suspend)
return lps001wp_prs_enable(prs);
return 0;
}
-static int lps001wp_prs_suspend(struct i2c_client *client, pm_message_t mesg)
+static int lps001wp_prs_suspend(struct device *dev)
{
- struct lps001wp_prs_data *prs = i2c_get_clientdata(client);
-
+ struct lps001wp_prs_data *prs = dev_get_drvdata(dev);
prs->on_before_suspend = atomic_read(&prs->enabled);
return lps001wp_prs_disable(prs);
}
+static const struct dev_pm_ops lps001wp_prs_dev_pm_ops = {
+ .suspend = lps001wp_prs_suspend,
+ .resume = lps001wp_prs_resume,
+};
+#else
+static void lps001wp_prs_early_suspend(struct early_suspend *data)
+{
+ struct lps001wp_prs_data *prs =
+ container_of(data, struct lps001wp_prs_data, early_suspend);
+ prs->on_before_suspend = atomic_read(&prs->enabled);
+ lps001wp_prs_disable(prs);
+}
+
+static void lps001wp_prs_late_resume(struct early_suspend *data)
+{
+ struct lps001wp_prs_data *prs =
+ container_of(data, struct lps001wp_prs_data, early_suspend);
+ if (prs->on_before_suspend)
+ lps001wp_prs_enable(prs);
+}
+#endif
static const struct i2c_device_id lps001wp_prs_id[]
= { { LPS001WP_PRS_DEV_NAME, 0}, { },};
@@ -1260,12 +1418,13 @@ static struct i2c_driver lps001wp_prs_driver = {
.driver = {
.name = LPS001WP_PRS_DEV_NAME,
.owner = THIS_MODULE,
+#if (!defined(CONFIG_HAS_EARLYSUSPEND) && defined(CONFIG_PM))
+ .pm = &lps001wp_prs_dev_pm_ops,
+#endif
},
.probe = lps001wp_prs_probe,
.remove = __devexit_p(lps001wp_prs_remove),
.id_table = lps001wp_prs_id,
- .resume = lps001wp_prs_resume,
- .suspend = lps001wp_prs_suspend,
};
static int __init lps001wp_prs_init(void)