[RFC PATCH 2/2] iio: magnetometer: ak8975: Improve performance of raw reads

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Define a channel to read x,y and z together. This raw read takes
50% less time reading all axes together than individual reads.

Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@xxxxxxxxxxxxxxx>
---
 drivers/iio/magnetometer/ak8975.c | 58 ++++++++++++++++++++++++++-------------
 1 file changed, 39 insertions(+), 19 deletions(-)

diff --git a/drivers/iio/magnetometer/ak8975.c b/drivers/iio/magnetometer/ak8975.c
index 24fc917..b6041ca 100644
--- a/drivers/iio/magnetometer/ak8975.c
+++ b/drivers/iio/magnetometer/ak8975.c
@@ -1,3 +1,4 @@
+
 /*
  * A sensor driver for the magnetometer AK8975.
  *
@@ -373,12 +374,14 @@ static int wait_conversion_complete_interrupt(struct ak8975_data *data)
 }
 
 /*
- * Emits the raw flux value for the x, y, or z axis.
+ * Emits the raw flux value for the x, y, or z individual or multiple axes
  */
-static int ak8975_read_axis(struct iio_dev *indio_dev, int index, int *val)
+static int ak8975_read_axis(struct iio_dev *indio_dev, int axes_size,
+			    int *indexes, int *vals)
 {
 	struct ak8975_data *data = iio_priv(indio_dev);
 	struct i2c_client *client = data->client;
+	int i;
 	int ret;
 
 	mutex_lock(&data->lock);
@@ -421,36 +424,50 @@ static int ak8975_read_axis(struct iio_dev *indio_dev, int index, int *val)
 
 	/* Read the flux value from the appropriate register
 	   (the register is specified in the iio device attributes). */
-	ret = i2c_smbus_read_word_data(client, ak8975_index_to_reg[index]);
-	if (ret < 0) {
-		dev_err(&client->dev, "Read axis data fails\n");
-		goto exit;
+	for (i = 0; i < axes_size; ++i) {
+		ret = i2c_smbus_read_word_data(client,
+					ak8975_index_to_reg[*indexes++]);
+		if (ret < 0) {
+			dev_err(&client->dev, "Read axis data fails\n");
+			goto exit;
+		}
+		/* Clamp to valid range. */
+		vals[i] = clamp_t(s16, ret, -4096, 4095);
 	}
 
 	mutex_unlock(&data->lock);
 
-	/* Clamp to valid range. */
-	*val = clamp_t(s16, ret, -4096, 4095);
-	return IIO_VAL_INT;
-
+	if (axes_size > 1)
+		return IIO_VAL_INT_MULTIPLE;
+	else
+		return IIO_VAL_INT;
 exit:
 	mutex_unlock(&data->lock);
 	return ret;
 }
 
-static int ak8975_read_raw(struct iio_dev *indio_dev,
-			   struct iio_chan_spec const *chan,
-			   int *val, int *val2,
-			   long mask)
+static int ak8975_read_raw_multi(struct iio_dev *indio_dev,
+				 struct iio_chan_spec const *chan,
+				 int size, int *vals, int *val_len,
+				 long mask)
 {
 	struct ak8975_data *data = iio_priv(indio_dev);
+	int ret;
 
 	switch (mask) {
 	case IIO_CHAN_INFO_RAW:
-		return ak8975_read_axis(indio_dev, chan->address, val);
+		if (size >= 3 && chan->address == 3) {
+			int indexes[3] = {0, 1, 2};
+
+			ret = ak8975_read_axis(indio_dev, 3, indexes, vals);
+			*val_len = 3;
+		} else
+			ret = ak8975_read_axis(indio_dev, 1,
+					       (int *)&chan->address, vals);
+		return ret;
 	case IIO_CHAN_INFO_SCALE:
-		*val = 0;
-		*val2 = data->raw_to_gauss[chan->address];
+		vals[0] = 0;
+		vals[1] = data->raw_to_gauss[chan->address];
 		return IIO_VAL_INT_PLUS_MICRO;
 	}
 	return -EINVAL;
@@ -467,11 +484,14 @@ static int ak8975_read_raw(struct iio_dev *indio_dev,
 	}
 
 static const struct iio_chan_spec ak8975_channels[] = {
-	AK8975_CHANNEL(X, 0), AK8975_CHANNEL(Y, 1), AK8975_CHANNEL(Z, 2),
+	AK8975_CHANNEL(X, 0),
+	AK8975_CHANNEL(Y, 1),
+	AK8975_CHANNEL(Z, 2),
+	AK8975_CHANNEL(X_AND_Y_AND_Z, 3)
 };
 
 static const struct iio_info ak8975_info = {
-	.read_raw = &ak8975_read_raw,
+	.read_raw_multi = &ak8975_read_raw_multi,
 	.driver_module = THIS_MODULE,
 };
 
-- 
1.8.3.2

--
To unsubscribe from this list: send the line "unsubscribe linux-iio" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Input]     [Linux Kernel]     [Linux SCSI]     [X.org]

  Powered by Linux