linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/6] Memsic MMC35230 magnetometer fixes
@ 2015-06-05 11:03 Daniel Baluta
  2015-06-05 11:03 ` [PATCH v2 1/6] iio: magnetometer: mmc35240: i2c device name should be lower case Daniel Baluta
                   ` (5 more replies)
  0 siblings, 6 replies; 13+ messages in thread
From: Daniel Baluta @ 2015-06-05 11:03 UTC (permalink / raw)
  To: jic23, pmeerw; +Cc: daniel.baluta, knaack.h, lars, linux-kernel, linux-iio

First 5 patches are bugfixes or small enhancements found during
tests with a real platform.

The last patch adds compensation for raw values allowing proper
calibration for Android compass apps.

Changes since v1:
	* fixed nits reported by Peter
		* few whitespaces and spelling erorrs
		* added MMC35240_ prefix to some macro's
	
Daniel Baluta (6):
  iio: magnetometer: mmc35240: i2c device name should be lower case
  iio: magnetometer: mmc35240: NULL terminate attribute array
  iio: magnetometer: mmc35240: Fix broken processed value
  iio: magnetometer: mmc35240: Use a smaller sleep value
  iio: magnetometer: mmc35240: Fix sensitivity on z-axis
  iio: magnetometer: mmc35240: Add compensation for raw values

 drivers/iio/magnetometer/mmc35240.c | 113 ++++++++++++++++++++++++++++--------
 1 file changed, 90 insertions(+), 23 deletions(-)

-- 
1.9.1


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v2 1/6] iio: magnetometer: mmc35240: i2c device name should be lower case
  2015-06-05 11:03 [PATCH v2 0/6] Memsic MMC35230 magnetometer fixes Daniel Baluta
@ 2015-06-05 11:03 ` Daniel Baluta
  2015-06-07 15:33   ` Jonathan Cameron
  2015-06-05 11:03 ` [PATCH v2 2/6] iio: magnetometer: mmc35240: NULL terminate attribute array Daniel Baluta
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 13+ messages in thread
From: Daniel Baluta @ 2015-06-05 11:03 UTC (permalink / raw)
  To: jic23, pmeerw; +Cc: daniel.baluta, knaack.h, lars, linux-kernel, linux-iio

This is the standard convention for i2c device name and
also this is the name used in some Intel platforms DT
files.

Fixes: abeb6b1e7b ("iio: magnetometer: Add support for MEMSIC MMC35240")
Signed-off-by: Daniel Baluta <daniel.baluta@intel.com>
---
 drivers/iio/magnetometer/mmc35240.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iio/magnetometer/mmc35240.c b/drivers/iio/magnetometer/mmc35240.c
index aa6e25d..417eca1 100644
--- a/drivers/iio/magnetometer/mmc35240.c
+++ b/drivers/iio/magnetometer/mmc35240.c
@@ -490,7 +490,7 @@ static const struct acpi_device_id mmc35240_acpi_match[] = {
 MODULE_DEVICE_TABLE(acpi, mmc35240_acpi_match);
 
 static const struct i2c_device_id mmc35240_id[] = {
-	{"MMC35240", 0},
+	{"mmc35240", 0},
 	{}
 };
 MODULE_DEVICE_TABLE(i2c, mmc35240_id);
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2 2/6] iio: magnetometer: mmc35240: NULL terminate attribute array
  2015-06-05 11:03 [PATCH v2 0/6] Memsic MMC35230 magnetometer fixes Daniel Baluta
  2015-06-05 11:03 ` [PATCH v2 1/6] iio: magnetometer: mmc35240: i2c device name should be lower case Daniel Baluta
@ 2015-06-05 11:03 ` Daniel Baluta
  2015-06-07 15:33   ` Jonathan Cameron
  2015-06-05 11:03 ` [PATCH v2 3/6] iio: magnetometer: mmc35240: Fix broken processed value Daniel Baluta
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 13+ messages in thread
From: Daniel Baluta @ 2015-06-05 11:03 UTC (permalink / raw)
  To: jic23, pmeerw; +Cc: daniel.baluta, knaack.h, lars, linux-kernel, linux-iio

This avoid nasty crashes when registering the IIO device.

Fixes: abeb6b1e7b ("iio: magnetometer: Add support for MEMSIC MMC35240")
Signed-off-by: Daniel Baluta <daniel.baluta@intel.com>
---
 drivers/iio/magnetometer/mmc35240.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/iio/magnetometer/mmc35240.c b/drivers/iio/magnetometer/mmc35240.c
index 417eca1..9d62c53 100644
--- a/drivers/iio/magnetometer/mmc35240.c
+++ b/drivers/iio/magnetometer/mmc35240.c
@@ -125,6 +125,7 @@ static const struct iio_chan_spec mmc35240_channels[] = {
 
 static struct attribute *mmc35240_attributes[] = {
 	&iio_const_attr_sampling_frequency_available.dev_attr.attr,
+	NULL
 };
 
 static const struct attribute_group mmc35240_attribute_group = {
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2 3/6] iio: magnetometer: mmc35240: Fix broken processed value
  2015-06-05 11:03 [PATCH v2 0/6] Memsic MMC35230 magnetometer fixes Daniel Baluta
  2015-06-05 11:03 ` [PATCH v2 1/6] iio: magnetometer: mmc35240: i2c device name should be lower case Daniel Baluta
  2015-06-05 11:03 ` [PATCH v2 2/6] iio: magnetometer: mmc35240: NULL terminate attribute array Daniel Baluta
@ 2015-06-05 11:03 ` Daniel Baluta
  2015-06-07 15:34   ` Jonathan Cameron
  2015-06-05 11:03 ` [PATCH v2 4/6] iio: magnetometer: mmc35240: Use a smaller sleep value Daniel Baluta
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 13+ messages in thread
From: Daniel Baluta @ 2015-06-05 11:03 UTC (permalink / raw)
  To: jic23, pmeerw; +Cc: daniel.baluta, knaack.h, lars, linux-kernel, linux-iio

The current computation for fractional part of the magnetic
field is broken. This patch fixes it by taking a different
approach. We expose the raw reading in milli Gauss (to avoid
rounding errors) with a scale of 0.001.

Thus the final computation is done in userspace where floating
point operation are more relaxed.

Fixes: abeb6b1e7b ("iio: magnetometer: Add support for MEMSIC MMC35240")
Signed-off-by: Daniel Baluta <daniel.baluta@intel.com>
---
 drivers/iio/magnetometer/mmc35240.c | 43 +++++++++++++++++++++++--------------
 1 file changed, 27 insertions(+), 16 deletions(-)

diff --git a/drivers/iio/magnetometer/mmc35240.c b/drivers/iio/magnetometer/mmc35240.c
index 9d62c53..7fff38e 100644
--- a/drivers/iio/magnetometer/mmc35240.c
+++ b/drivers/iio/magnetometer/mmc35240.c
@@ -113,8 +113,9 @@ static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("100 200 333 666");
 	.modified = 1, \
 	.channel2 = IIO_MOD_ ## _axis, \
 	.address = AXIS_ ## _axis, \
-	.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), \
-	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
+			BIT(IIO_CHAN_INFO_SCALE), \
 }
 
 static const struct iio_chan_spec mmc35240_channels[] = {
@@ -241,9 +242,19 @@ static int mmc35240_read_measurement(struct mmc35240_data *data, __le16 buf[3])
 				3 * sizeof(__le16));
 }
 
-static int mmc35240_raw_to_gauss(struct mmc35240_data *data, int index,
-				 __le16 buf[],
-				 int *val, int *val2)
+/**
+ * mmc35240_raw_to_mgauss - convert raw readings to milli gauss. Also apply
+			    compensation for output value.
+ *
+ * @data: device private data
+ * @index: axis index for which we want the conversion
+ * @buf: raw data to be converted, 2 bytes in little endian format
+ * @val: compensated output reading (unit is milli gauss)
+ *
+ * Returns: 0 in case of success, -EINVAL when @index is not valid
+ */
+static int mmc35240_raw_to_mgauss(struct mmc35240_data *data, int index,
+				  __le16 buf[], int *val)
 {
 	int raw_x, raw_y, raw_z;
 	int sens_x, sens_y, sens_z;
@@ -261,18 +272,15 @@ static int mmc35240_raw_to_gauss(struct mmc35240_data *data, int index,
 
 	switch (index) {
 	case AXIS_X:
-		*val = (raw_x - nfo) / sens_x;
-		*val2 = ((raw_x - nfo) % sens_x) * 1000000;
+		*val = (raw_x - nfo) * 1000 / sens_x;
 		break;
 	case AXIS_Y:
-		*val = (raw_y - nfo) / sens_y - (raw_z - nfo) / sens_z;
-		*val2 = (((raw_y - nfo) % sens_y - (raw_z - nfo) % sens_z))
-			* 1000000;
+		*val = (raw_y - nfo) * 1000 / sens_y -
+			(raw_z - nfo)  * 1000 / sens_z;
 		break;
 	case AXIS_Z:
-		*val = (raw_y - nfo) / sens_y + (raw_z - nfo) / sens_z;
-		*val2 = (((raw_y - nfo) % sens_y + (raw_z - nfo) % sens_z))
-			* 1000000;
+		*val = (raw_y - nfo) * 1000 / sens_y +
+			(raw_z - nfo) * 1000 / sens_z;
 		break;
 	default:
 		return -EINVAL;
@@ -290,16 +298,19 @@ static int mmc35240_read_raw(struct iio_dev *indio_dev,
 	__le16 buf[3];
 
 	switch (mask) {
-	case IIO_CHAN_INFO_PROCESSED:
+	case IIO_CHAN_INFO_RAW:
 		mutex_lock(&data->mutex);
 		ret = mmc35240_read_measurement(data, buf);
 		mutex_unlock(&data->mutex);
 		if (ret < 0)
 			return ret;
-		ret = mmc35240_raw_to_gauss(data, chan->address,
-					    buf, val, val2);
+		ret = mmc35240_raw_to_mgauss(data, chan->address, buf, val);
 		if (ret < 0)
 			return ret;
+		return IIO_VAL_INT;
+	case IIO_CHAN_INFO_SCALE:
+		*val = 0;
+		*val2 = 1000;
 		return IIO_VAL_INT_PLUS_MICRO;
 	case IIO_CHAN_INFO_SAMP_FREQ:
 		mutex_lock(&data->mutex);
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2 4/6] iio: magnetometer: mmc35240: Use a smaller sleep value
  2015-06-05 11:03 [PATCH v2 0/6] Memsic MMC35230 magnetometer fixes Daniel Baluta
                   ` (2 preceding siblings ...)
  2015-06-05 11:03 ` [PATCH v2 3/6] iio: magnetometer: mmc35240: Fix broken processed value Daniel Baluta
@ 2015-06-05 11:03 ` Daniel Baluta
  2015-06-07 15:34   ` Jonathan Cameron
  2015-06-05 11:03 ` [PATCH v2 5/6] iio: magnetometer: mmc35240: Fix sensitivity on z-axis Daniel Baluta
  2015-06-05 11:03 ` [PATCH v2 6/6] iio: magnetometer: mmc35240: Add compensation for raw values Daniel Baluta
  5 siblings, 1 reply; 13+ messages in thread
From: Daniel Baluta @ 2015-06-05 11:03 UTC (permalink / raw)
  To: jic23, pmeerw; +Cc: daniel.baluta, knaack.h, lars, linux-kernel, linux-iio

According to datasheet, Page 8, minimum wait time to complete
measurement is 10ms. Adjusting this value will increase the
userspace polling rate.

Fixes: abeb6b1e7b ("iio: magnetometer: Add support for MEMSIC MMC35240")
Signed-off-by: Daniel Baluta <daniel.baluta@intel.com>
---
 drivers/iio/magnetometer/mmc35240.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/iio/magnetometer/mmc35240.c b/drivers/iio/magnetometer/mmc35240.c
index 7fff38e..7bc72b3 100644
--- a/drivers/iio/magnetometer/mmc35240.c
+++ b/drivers/iio/magnetometer/mmc35240.c
@@ -219,7 +219,8 @@ static int mmc35240_take_measurement(struct mmc35240_data *data)
 			return ret;
 		if (reg_status & MMC35240_STATUS_MEAS_DONE_BIT)
 			break;
-		msleep(20);
+		/* minimum wait time to complete measurement is 10 ms */
+		usleep_range(10000, 11000);
 	}
 
 	if (tries < 0) {
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2 5/6] iio: magnetometer: mmc35240: Fix sensitivity on z-axis
  2015-06-05 11:03 [PATCH v2 0/6] Memsic MMC35230 magnetometer fixes Daniel Baluta
                   ` (3 preceding siblings ...)
  2015-06-05 11:03 ` [PATCH v2 4/6] iio: magnetometer: mmc35240: Use a smaller sleep value Daniel Baluta
@ 2015-06-05 11:03 ` Daniel Baluta
  2015-06-07 15:34   ` Jonathan Cameron
  2015-06-05 11:03 ` [PATCH v2 6/6] iio: magnetometer: mmc35240: Add compensation for raw values Daniel Baluta
  5 siblings, 1 reply; 13+ messages in thread
From: Daniel Baluta @ 2015-06-05 11:03 UTC (permalink / raw)
  To: jic23, pmeerw; +Cc: daniel.baluta, knaack.h, lars, linux-kernel, linux-iio

Datasheet says (Page 2) that typical value for sensitivity
for 16 bits mode on Z-axis is 770. Anyhow, looking at the
input driver provided by Memsic the value for MMC35240 is
1024.

Also, testing shows that using 1024 for Z-axis senzitivity
offers better results.

Fixes: abeb6b1e7b ("iio: magnetometer: Add support for MEMSIC MMC35240")
Signed-off-by: Daniel Baluta <daniel.baluta@intel.com>
---
 drivers/iio/magnetometer/mmc35240.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iio/magnetometer/mmc35240.c b/drivers/iio/magnetometer/mmc35240.c
index 7bc72b3..73fa111 100644
--- a/drivers/iio/magnetometer/mmc35240.c
+++ b/drivers/iio/magnetometer/mmc35240.c
@@ -77,7 +77,7 @@ static const struct {
 } mmc35240_props_table[] = {
 	/* 16 bits, 100Hz ODR */
 	{
-		{1024, 1024, 770},
+		{1024, 1024, 1024},
 		32768,
 	},
 	/* 16 bits, 200Hz ODR */
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2 6/6] iio: magnetometer: mmc35240: Add compensation for raw values
  2015-06-05 11:03 [PATCH v2 0/6] Memsic MMC35230 magnetometer fixes Daniel Baluta
                   ` (4 preceding siblings ...)
  2015-06-05 11:03 ` [PATCH v2 5/6] iio: magnetometer: mmc35240: Fix sensitivity on z-axis Daniel Baluta
@ 2015-06-05 11:03 ` Daniel Baluta
  2015-06-07 15:35   ` Jonathan Cameron
  5 siblings, 1 reply; 13+ messages in thread
From: Daniel Baluta @ 2015-06-05 11:03 UTC (permalink / raw)
  To: jic23, pmeerw; +Cc: daniel.baluta, knaack.h, lars, linux-kernel, linux-iio

This patch adds compensation formula to raw readings, borrowed
from Memsic's input driver.

Signed-off-by: Daniel Baluta <daniel.baluta@intel.com>
---
 drivers/iio/magnetometer/mmc35240.c | 62 ++++++++++++++++++++++++++++++++++---
 1 file changed, 58 insertions(+), 4 deletions(-)

diff --git a/drivers/iio/magnetometer/mmc35240.c b/drivers/iio/magnetometer/mmc35240.c
index 73fa111..7540bbf 100644
--- a/drivers/iio/magnetometer/mmc35240.c
+++ b/drivers/iio/magnetometer/mmc35240.c
@@ -58,6 +58,31 @@
 #define MMC35240_WAIT_CHARGE_PUMP	50000	/* us */
 #define MMC53240_WAIT_SET_RESET		1000	/* us */
 
+/*
+ * Memsic OTP process code piece is put here for reference:
+ *
+ * #define OTP_CONVERT(REG)  ((float)((REG) >=32 ? (32 - (REG)) : (REG)) * 0.006
+ * 1) For X axis, the COEFFICIENT is always 1.
+ * 2) For Y axis, the COEFFICIENT is as below:
+ *    f_OTP_matrix[4] = OTP_CONVERT(((reg_data[1] & 0x03) << 4) |
+ *                                   (reg_data[2] >> 4)) + 1.0;
+ * 3) For Z axis, the COEFFICIENT is as below:
+ *    f_OTP_matrix[8] = (OTP_CONVERT(reg_data[3] & 0x3f) + 1) * 1.35;
+ * We implemented the OTP logic into driver.
+ */
+
+/* scale = 1000 here for Y otp */
+#define MMC35240_OTP_CONVERT_Y(REG) (((REG) >= 32 ? (32 - (REG)) : (REG)) * 6)
+
+/* 0.6 * 1.35 = 0.81, scale 10000 for Z otp */
+#define MMC35240_OTP_CONVERT_Z(REG) (((REG) >= 32 ? (32 - (REG)) : (REG)) * 81)
+
+#define MMC35240_X_COEFF(x)	(x)
+#define MMC35240_Y_COEFF(y)	(y + 1000)
+#define MMC35240_Z_COEFF(z)	(z + 13500)
+
+#define MMC35240_OTP_START_ADDR		0x1B
+
 enum mmc35240_resolution {
 	MMC35240_16_BITS_SLOW = 0, /* 100 Hz */
 	MMC35240_16_BITS_FAST,     /* 200 Hz */
@@ -102,6 +127,10 @@ struct mmc35240_data {
 	struct mutex mutex;
 	struct regmap *regmap;
 	enum mmc35240_resolution res;
+
+	/* OTP compensation */
+	int axis_coef[3];
+	int axis_scale[3];
 };
 
 static const int mmc35240_samp_freq[] = {100, 200, 333, 666};
@@ -172,8 +201,9 @@ static int mmc35240_hw_set(struct mmc35240_data *data, bool set)
 
 static int mmc35240_init(struct mmc35240_data *data)
 {
-	int ret;
+	int ret, y_convert, z_convert;
 	unsigned int reg_id;
+	u8 otp_data[6];
 
 	ret = regmap_read(data->regmap, MMC35240_REG_ID, &reg_id);
 	if (ret < 0) {
@@ -197,9 +227,30 @@ static int mmc35240_init(struct mmc35240_data *data)
 		return ret;
 
 	/* set default sampling frequency */
-	return regmap_update_bits(data->regmap, MMC35240_REG_CTRL1,
-				  MMC35240_CTRL1_BW_MASK,
-				  data->res << MMC35240_CTRL1_BW_SHIFT);
+	ret = regmap_update_bits(data->regmap, MMC35240_REG_CTRL1,
+				 MMC35240_CTRL1_BW_MASK,
+				 data->res << MMC35240_CTRL1_BW_SHIFT);
+	if (ret < 0)
+		return ret;
+
+	ret = regmap_bulk_read(data->regmap, MMC35240_OTP_START_ADDR,
+			       (u8 *)otp_data, sizeof(otp_data));
+	if (ret < 0)
+		return ret;
+
+	y_convert = MMC35240_OTP_CONVERT_Y(((otp_data[1] & 0x03) << 4) |
+					   (otp_data[2] >> 4));
+	z_convert = MMC35240_OTP_CONVERT_Z(otp_data[3] & 0x3f);
+
+	data->axis_coef[0] = MMC35240_X_COEFF(1);
+	data->axis_coef[1] = MMC35240_Y_COEFF(y_convert);
+	data->axis_coef[2] = MMC35240_Z_COEFF(z_convert);
+
+	data->axis_scale[0] = 1;
+	data->axis_scale[1] = 1000;
+	data->axis_scale[2] = 10000;
+
+	return 0;
 }
 
 static int mmc35240_take_measurement(struct mmc35240_data *data)
@@ -286,6 +337,9 @@ static int mmc35240_raw_to_mgauss(struct mmc35240_data *data, int index,
 	default:
 		return -EINVAL;
 	}
+	/* apply OTP compensation */
+	*val = (*val) * data->axis_coef[index] / data->axis_scale[index];
+
 	return 0;
 }
 
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH v2 1/6] iio: magnetometer: mmc35240: i2c device name should be lower case
  2015-06-05 11:03 ` [PATCH v2 1/6] iio: magnetometer: mmc35240: i2c device name should be lower case Daniel Baluta
@ 2015-06-07 15:33   ` Jonathan Cameron
  0 siblings, 0 replies; 13+ messages in thread
From: Jonathan Cameron @ 2015-06-07 15:33 UTC (permalink / raw)
  To: Daniel Baluta, pmeerw; +Cc: knaack.h, lars, linux-kernel, linux-iio

On 05/06/15 12:03, Daniel Baluta wrote:
> This is the standard convention for i2c device name and
> also this is the name used in some Intel platforms DT
> files.
> 
> Fixes: abeb6b1e7b ("iio: magnetometer: Add support for MEMSIC MMC35240")
> Signed-off-by: Daniel Baluta <daniel.baluta@intel.com>
applied to the togreg branch of iio.git

Thanks,
> ---
>  drivers/iio/magnetometer/mmc35240.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/iio/magnetometer/mmc35240.c b/drivers/iio/magnetometer/mmc35240.c
> index aa6e25d..417eca1 100644
> --- a/drivers/iio/magnetometer/mmc35240.c
> +++ b/drivers/iio/magnetometer/mmc35240.c
> @@ -490,7 +490,7 @@ static const struct acpi_device_id mmc35240_acpi_match[] = {
>  MODULE_DEVICE_TABLE(acpi, mmc35240_acpi_match);
>  
>  static const struct i2c_device_id mmc35240_id[] = {
> -	{"MMC35240", 0},
> +	{"mmc35240", 0},
>  	{}
>  };
>  MODULE_DEVICE_TABLE(i2c, mmc35240_id);
> 


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v2 2/6] iio: magnetometer: mmc35240: NULL terminate attribute array
  2015-06-05 11:03 ` [PATCH v2 2/6] iio: magnetometer: mmc35240: NULL terminate attribute array Daniel Baluta
@ 2015-06-07 15:33   ` Jonathan Cameron
  0 siblings, 0 replies; 13+ messages in thread
From: Jonathan Cameron @ 2015-06-07 15:33 UTC (permalink / raw)
  To: Daniel Baluta, pmeerw; +Cc: knaack.h, lars, linux-kernel, linux-iio

On 05/06/15 12:03, Daniel Baluta wrote:
> This avoid nasty crashes when registering the IIO device.
> 
> Fixes: abeb6b1e7b ("iio: magnetometer: Add support for MEMSIC MMC35240")
> Signed-off-by: Daniel Baluta <daniel.baluta@intel.com>
Applied to the togreg branch of iio.git
> ---
>  drivers/iio/magnetometer/mmc35240.c | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/drivers/iio/magnetometer/mmc35240.c b/drivers/iio/magnetometer/mmc35240.c
> index 417eca1..9d62c53 100644
> --- a/drivers/iio/magnetometer/mmc35240.c
> +++ b/drivers/iio/magnetometer/mmc35240.c
> @@ -125,6 +125,7 @@ static const struct iio_chan_spec mmc35240_channels[] = {
>  
>  static struct attribute *mmc35240_attributes[] = {
>  	&iio_const_attr_sampling_frequency_available.dev_attr.attr,
> +	NULL
>  };
>  
>  static const struct attribute_group mmc35240_attribute_group = {
> 


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v2 3/6] iio: magnetometer: mmc35240: Fix broken processed value
  2015-06-05 11:03 ` [PATCH v2 3/6] iio: magnetometer: mmc35240: Fix broken processed value Daniel Baluta
@ 2015-06-07 15:34   ` Jonathan Cameron
  0 siblings, 0 replies; 13+ messages in thread
From: Jonathan Cameron @ 2015-06-07 15:34 UTC (permalink / raw)
  To: Daniel Baluta, pmeerw; +Cc: knaack.h, lars, linux-kernel, linux-iio

On 05/06/15 12:03, Daniel Baluta wrote:
> The current computation for fractional part of the magnetic
> field is broken. This patch fixes it by taking a different
> approach. We expose the raw reading in milli Gauss (to avoid
> rounding errors) with a scale of 0.001.
> 
> Thus the final computation is done in userspace where floating
> point operation are more relaxed.
> 
> Fixes: abeb6b1e7b ("iio: magnetometer: Add support for MEMSIC MMC35240")
> Signed-off-by: Daniel Baluta <daniel.baluta@intel.com>
Applied to the togreg branch of iio.git.

Thanks
> ---
>  drivers/iio/magnetometer/mmc35240.c | 43 +++++++++++++++++++++++--------------
>  1 file changed, 27 insertions(+), 16 deletions(-)
> 
> diff --git a/drivers/iio/magnetometer/mmc35240.c b/drivers/iio/magnetometer/mmc35240.c
> index 9d62c53..7fff38e 100644
> --- a/drivers/iio/magnetometer/mmc35240.c
> +++ b/drivers/iio/magnetometer/mmc35240.c
> @@ -113,8 +113,9 @@ static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("100 200 333 666");
>  	.modified = 1, \
>  	.channel2 = IIO_MOD_ ## _axis, \
>  	.address = AXIS_ ## _axis, \
> -	.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), \
> -	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
> +	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
> +	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
> +			BIT(IIO_CHAN_INFO_SCALE), \
>  }
>  
>  static const struct iio_chan_spec mmc35240_channels[] = {
> @@ -241,9 +242,19 @@ static int mmc35240_read_measurement(struct mmc35240_data *data, __le16 buf[3])
>  				3 * sizeof(__le16));
>  }
>  
> -static int mmc35240_raw_to_gauss(struct mmc35240_data *data, int index,
> -				 __le16 buf[],
> -				 int *val, int *val2)
> +/**
> + * mmc35240_raw_to_mgauss - convert raw readings to milli gauss. Also apply
> +			    compensation for output value.
> + *
> + * @data: device private data
> + * @index: axis index for which we want the conversion
> + * @buf: raw data to be converted, 2 bytes in little endian format
> + * @val: compensated output reading (unit is milli gauss)
> + *
> + * Returns: 0 in case of success, -EINVAL when @index is not valid
> + */
> +static int mmc35240_raw_to_mgauss(struct mmc35240_data *data, int index,
> +				  __le16 buf[], int *val)
>  {
>  	int raw_x, raw_y, raw_z;
>  	int sens_x, sens_y, sens_z;
> @@ -261,18 +272,15 @@ static int mmc35240_raw_to_gauss(struct mmc35240_data *data, int index,
>  
>  	switch (index) {
>  	case AXIS_X:
> -		*val = (raw_x - nfo) / sens_x;
> -		*val2 = ((raw_x - nfo) % sens_x) * 1000000;
> +		*val = (raw_x - nfo) * 1000 / sens_x;
>  		break;
>  	case AXIS_Y:
> -		*val = (raw_y - nfo) / sens_y - (raw_z - nfo) / sens_z;
> -		*val2 = (((raw_y - nfo) % sens_y - (raw_z - nfo) % sens_z))
> -			* 1000000;
> +		*val = (raw_y - nfo) * 1000 / sens_y -
> +			(raw_z - nfo)  * 1000 / sens_z;
>  		break;
>  	case AXIS_Z:
> -		*val = (raw_y - nfo) / sens_y + (raw_z - nfo) / sens_z;
> -		*val2 = (((raw_y - nfo) % sens_y + (raw_z - nfo) % sens_z))
> -			* 1000000;
> +		*val = (raw_y - nfo) * 1000 / sens_y +
> +			(raw_z - nfo) * 1000 / sens_z;
>  		break;
>  	default:
>  		return -EINVAL;
> @@ -290,16 +298,19 @@ static int mmc35240_read_raw(struct iio_dev *indio_dev,
>  	__le16 buf[3];
>  
>  	switch (mask) {
> -	case IIO_CHAN_INFO_PROCESSED:
> +	case IIO_CHAN_INFO_RAW:
>  		mutex_lock(&data->mutex);
>  		ret = mmc35240_read_measurement(data, buf);
>  		mutex_unlock(&data->mutex);
>  		if (ret < 0)
>  			return ret;
> -		ret = mmc35240_raw_to_gauss(data, chan->address,
> -					    buf, val, val2);
> +		ret = mmc35240_raw_to_mgauss(data, chan->address, buf, val);
>  		if (ret < 0)
>  			return ret;
> +		return IIO_VAL_INT;
> +	case IIO_CHAN_INFO_SCALE:
> +		*val = 0;
> +		*val2 = 1000;
>  		return IIO_VAL_INT_PLUS_MICRO;
>  	case IIO_CHAN_INFO_SAMP_FREQ:
>  		mutex_lock(&data->mutex);
> 


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v2 4/6] iio: magnetometer: mmc35240: Use a smaller sleep value
  2015-06-05 11:03 ` [PATCH v2 4/6] iio: magnetometer: mmc35240: Use a smaller sleep value Daniel Baluta
@ 2015-06-07 15:34   ` Jonathan Cameron
  0 siblings, 0 replies; 13+ messages in thread
From: Jonathan Cameron @ 2015-06-07 15:34 UTC (permalink / raw)
  To: Daniel Baluta, pmeerw; +Cc: knaack.h, lars, linux-kernel, linux-iio

On 05/06/15 12:03, Daniel Baluta wrote:
> According to datasheet, Page 8, minimum wait time to complete
> measurement is 10ms. Adjusting this value will increase the
> userspace polling rate.
> 
> Fixes: abeb6b1e7b ("iio: magnetometer: Add support for MEMSIC MMC35240")
> Signed-off-by: Daniel Baluta <daniel.baluta@intel.com>
Applied to the togreg branch of iio.git.

Thanks,
> ---
>  drivers/iio/magnetometer/mmc35240.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/iio/magnetometer/mmc35240.c b/drivers/iio/magnetometer/mmc35240.c
> index 7fff38e..7bc72b3 100644
> --- a/drivers/iio/magnetometer/mmc35240.c
> +++ b/drivers/iio/magnetometer/mmc35240.c
> @@ -219,7 +219,8 @@ static int mmc35240_take_measurement(struct mmc35240_data *data)
>  			return ret;
>  		if (reg_status & MMC35240_STATUS_MEAS_DONE_BIT)
>  			break;
> -		msleep(20);
> +		/* minimum wait time to complete measurement is 10 ms */
> +		usleep_range(10000, 11000);
>  	}
>  
>  	if (tries < 0) {
> 


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v2 5/6] iio: magnetometer: mmc35240: Fix sensitivity on z-axis
  2015-06-05 11:03 ` [PATCH v2 5/6] iio: magnetometer: mmc35240: Fix sensitivity on z-axis Daniel Baluta
@ 2015-06-07 15:34   ` Jonathan Cameron
  0 siblings, 0 replies; 13+ messages in thread
From: Jonathan Cameron @ 2015-06-07 15:34 UTC (permalink / raw)
  To: Daniel Baluta, pmeerw; +Cc: knaack.h, lars, linux-kernel, linux-iio

On 05/06/15 12:03, Daniel Baluta wrote:
> Datasheet says (Page 2) that typical value for sensitivity
> for 16 bits mode on Z-axis is 770. Anyhow, looking at the
> input driver provided by Memsic the value for MMC35240 is
> 1024.
> 
> Also, testing shows that using 1024 for Z-axis senzitivity
> offers better results.
> 
> Fixes: abeb6b1e7b ("iio: magnetometer: Add support for MEMSIC MMC35240")
> Signed-off-by: Daniel Baluta <daniel.baluta@intel.com>
applied 
> ---
>  drivers/iio/magnetometer/mmc35240.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/iio/magnetometer/mmc35240.c b/drivers/iio/magnetometer/mmc35240.c
> index 7bc72b3..73fa111 100644
> --- a/drivers/iio/magnetometer/mmc35240.c
> +++ b/drivers/iio/magnetometer/mmc35240.c
> @@ -77,7 +77,7 @@ static const struct {
>  } mmc35240_props_table[] = {
>  	/* 16 bits, 100Hz ODR */
>  	{
> -		{1024, 1024, 770},
> +		{1024, 1024, 1024},
>  		32768,
>  	},
>  	/* 16 bits, 200Hz ODR */
> 


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v2 6/6] iio: magnetometer: mmc35240: Add compensation for raw values
  2015-06-05 11:03 ` [PATCH v2 6/6] iio: magnetometer: mmc35240: Add compensation for raw values Daniel Baluta
@ 2015-06-07 15:35   ` Jonathan Cameron
  0 siblings, 0 replies; 13+ messages in thread
From: Jonathan Cameron @ 2015-06-07 15:35 UTC (permalink / raw)
  To: Daniel Baluta, pmeerw; +Cc: knaack.h, lars, linux-kernel, linux-iio

On 05/06/15 12:03, Daniel Baluta wrote:
> This patch adds compensation formula to raw readings, borrowed
> from Memsic's input driver.
> 
> Signed-off-by: Daniel Baluta <daniel.baluta@intel.com>
Applied to the togreg branch of iio.git, pushed out shortly as testing.

Thanks,

Jonathan
> ---
>  drivers/iio/magnetometer/mmc35240.c | 62 ++++++++++++++++++++++++++++++++++---
>  1 file changed, 58 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/iio/magnetometer/mmc35240.c b/drivers/iio/magnetometer/mmc35240.c
> index 73fa111..7540bbf 100644
> --- a/drivers/iio/magnetometer/mmc35240.c
> +++ b/drivers/iio/magnetometer/mmc35240.c
> @@ -58,6 +58,31 @@
>  #define MMC35240_WAIT_CHARGE_PUMP	50000	/* us */
>  #define MMC53240_WAIT_SET_RESET		1000	/* us */
>  
> +/*
> + * Memsic OTP process code piece is put here for reference:
> + *
> + * #define OTP_CONVERT(REG)  ((float)((REG) >=32 ? (32 - (REG)) : (REG)) * 0.006
> + * 1) For X axis, the COEFFICIENT is always 1.
> + * 2) For Y axis, the COEFFICIENT is as below:
> + *    f_OTP_matrix[4] = OTP_CONVERT(((reg_data[1] & 0x03) << 4) |
> + *                                   (reg_data[2] >> 4)) + 1.0;
> + * 3) For Z axis, the COEFFICIENT is as below:
> + *    f_OTP_matrix[8] = (OTP_CONVERT(reg_data[3] & 0x3f) + 1) * 1.35;
> + * We implemented the OTP logic into driver.
> + */
> +
> +/* scale = 1000 here for Y otp */
> +#define MMC35240_OTP_CONVERT_Y(REG) (((REG) >= 32 ? (32 - (REG)) : (REG)) * 6)
> +
> +/* 0.6 * 1.35 = 0.81, scale 10000 for Z otp */
> +#define MMC35240_OTP_CONVERT_Z(REG) (((REG) >= 32 ? (32 - (REG)) : (REG)) * 81)
> +
> +#define MMC35240_X_COEFF(x)	(x)
> +#define MMC35240_Y_COEFF(y)	(y + 1000)
> +#define MMC35240_Z_COEFF(z)	(z + 13500)
> +
> +#define MMC35240_OTP_START_ADDR		0x1B
> +
>  enum mmc35240_resolution {
>  	MMC35240_16_BITS_SLOW = 0, /* 100 Hz */
>  	MMC35240_16_BITS_FAST,     /* 200 Hz */
> @@ -102,6 +127,10 @@ struct mmc35240_data {
>  	struct mutex mutex;
>  	struct regmap *regmap;
>  	enum mmc35240_resolution res;
> +
> +	/* OTP compensation */
> +	int axis_coef[3];
> +	int axis_scale[3];
>  };
>  
>  static const int mmc35240_samp_freq[] = {100, 200, 333, 666};
> @@ -172,8 +201,9 @@ static int mmc35240_hw_set(struct mmc35240_data *data, bool set)
>  
>  static int mmc35240_init(struct mmc35240_data *data)
>  {
> -	int ret;
> +	int ret, y_convert, z_convert;
>  	unsigned int reg_id;
> +	u8 otp_data[6];
>  
>  	ret = regmap_read(data->regmap, MMC35240_REG_ID, &reg_id);
>  	if (ret < 0) {
> @@ -197,9 +227,30 @@ static int mmc35240_init(struct mmc35240_data *data)
>  		return ret;
>  
>  	/* set default sampling frequency */
> -	return regmap_update_bits(data->regmap, MMC35240_REG_CTRL1,
> -				  MMC35240_CTRL1_BW_MASK,
> -				  data->res << MMC35240_CTRL1_BW_SHIFT);
> +	ret = regmap_update_bits(data->regmap, MMC35240_REG_CTRL1,
> +				 MMC35240_CTRL1_BW_MASK,
> +				 data->res << MMC35240_CTRL1_BW_SHIFT);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = regmap_bulk_read(data->regmap, MMC35240_OTP_START_ADDR,
> +			       (u8 *)otp_data, sizeof(otp_data));
> +	if (ret < 0)
> +		return ret;
> +
> +	y_convert = MMC35240_OTP_CONVERT_Y(((otp_data[1] & 0x03) << 4) |
> +					   (otp_data[2] >> 4));
> +	z_convert = MMC35240_OTP_CONVERT_Z(otp_data[3] & 0x3f);
> +
> +	data->axis_coef[0] = MMC35240_X_COEFF(1);
> +	data->axis_coef[1] = MMC35240_Y_COEFF(y_convert);
> +	data->axis_coef[2] = MMC35240_Z_COEFF(z_convert);
> +
> +	data->axis_scale[0] = 1;
> +	data->axis_scale[1] = 1000;
> +	data->axis_scale[2] = 10000;
> +
> +	return 0;
>  }
>  
>  static int mmc35240_take_measurement(struct mmc35240_data *data)
> @@ -286,6 +337,9 @@ static int mmc35240_raw_to_mgauss(struct mmc35240_data *data, int index,
>  	default:
>  		return -EINVAL;
>  	}
> +	/* apply OTP compensation */
> +	*val = (*val) * data->axis_coef[index] / data->axis_scale[index];
> +
>  	return 0;
>  }
>  
> 


^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2015-06-07 15:35 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-06-05 11:03 [PATCH v2 0/6] Memsic MMC35230 magnetometer fixes Daniel Baluta
2015-06-05 11:03 ` [PATCH v2 1/6] iio: magnetometer: mmc35240: i2c device name should be lower case Daniel Baluta
2015-06-07 15:33   ` Jonathan Cameron
2015-06-05 11:03 ` [PATCH v2 2/6] iio: magnetometer: mmc35240: NULL terminate attribute array Daniel Baluta
2015-06-07 15:33   ` Jonathan Cameron
2015-06-05 11:03 ` [PATCH v2 3/6] iio: magnetometer: mmc35240: Fix broken processed value Daniel Baluta
2015-06-07 15:34   ` Jonathan Cameron
2015-06-05 11:03 ` [PATCH v2 4/6] iio: magnetometer: mmc35240: Use a smaller sleep value Daniel Baluta
2015-06-07 15:34   ` Jonathan Cameron
2015-06-05 11:03 ` [PATCH v2 5/6] iio: magnetometer: mmc35240: Fix sensitivity on z-axis Daniel Baluta
2015-06-07 15:34   ` Jonathan Cameron
2015-06-05 11:03 ` [PATCH v2 6/6] iio: magnetometer: mmc35240: Add compensation for raw values Daniel Baluta
2015-06-07 15:35   ` Jonathan Cameron

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).