lkml.org 
[lkml]   [2022]   [Jun]   [15]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Subject[PATCH] iio: accel: mxc4005: report orientation of accelerometer
Date
From: Quentin Schulz <quentin.schulz@theobroma-systems.com>

The accelerometer can report precise values for x, y and z accelerations
but it can also simply report its orientation on XY plane and Z axis.

Since the orientation of the device may be enough information for
userspace and allows to avoid expensive fusion algorithms, let's add
support for it.

The orientation register stores a 2b value for XY plane orientation:
between 225° and 315°, returns 0, between 315° and 45°, 1, between 45°
and 135°, 2 and between 135° and 225°, 3. We "round" those to 270°,
0°, 90° and 180° degrees.

For Z axis, the register bit returns 0 if facing the user, 1 otherwise,
which the driver translates to 0° and 180° respectively.

Those values are proper if the accelerometer is mounted such that the
XYZ axes are as follows when the device is facing the user in portrait
mode (respecting the right-hand rule):

y
^
|
|
|
+----------> x
/
/
/
L
z

Since this information is very basic, imprecise (only 4 values for XY
plane and 2 for Z axis) and can be extrapolated from the actual,
precise, x, y and z acceleration values, it is not made available
through buffers.

A change in XY plane or Z axis orientation can also trigger an interrupt
but this feature is not added in this commit.

Signed-off-by: Quentin Schulz <quentin.schulz@theobroma-systems.com>
---
drivers/iio/accel/mxc4005.c | 39 +++++++++++++++++++++++++++++++++++++
1 file changed, 39 insertions(+)

diff --git a/drivers/iio/accel/mxc4005.c b/drivers/iio/accel/mxc4005.c
index b3afbf064915..61f24058d239 100644
--- a/drivers/iio/accel/mxc4005.c
+++ b/drivers/iio/accel/mxc4005.c
@@ -20,6 +20,11 @@
#define MXC4005_IRQ_NAME "mxc4005_event"
#define MXC4005_REGMAP_NAME "mxc4005_regmap"

+#define MXC4005_REG_TILT_ORIENT 0x01
+#define MXC4005_REG_TILT_ORIENT_Z_MASK BIT(6)
+#define MXC4005_REG_TILT_ORIENT_XY_MASK GENMASK(5, 4)
+#define MXC4005_REG_TILT_ORIENT_XY_SHIFT 4
+
#define MXC4005_REG_XOUT_UPPER 0x03
#define MXC4005_REG_XOUT_LOWER 0x04
#define MXC4005_REG_YOUT_UPPER 0x05
@@ -96,6 +101,7 @@ static const struct attribute_group mxc4005_attrs_group = {
static bool mxc4005_is_readable_reg(struct device *dev, unsigned int reg)
{
switch (reg) {
+ case MXC4005_REG_TILT_ORIENT:
case MXC4005_REG_XOUT_UPPER:
case MXC4005_REG_XOUT_LOWER:
case MXC4005_REG_YOUT_UPPER:
@@ -214,6 +220,28 @@ static int mxc4005_read_raw(struct iio_dev *indio_dev,
int ret;

switch (mask) {
+ case IIO_CHAN_INFO_PROCESSED:
+ switch (chan->type) {
+ case IIO_ROT:
+ ret = regmap_read(data->regmap, chan->address, val);
+ if (ret < 0) {
+ dev_err(data->dev, "failed to read rotation\n");
+ return ret;
+ }
+
+ if (chan->channel2 == IIO_MOD_X_AND_Y) {
+ *val &= MXC4005_REG_TILT_ORIENT_XY_MASK;
+ *val >>= MXC4005_REG_TILT_ORIENT_XY_SHIFT;
+ /* 00 = 270°; 01 = 0°; 10 = 90°; 11 = 180° */
+ *val = (360 + (*val - 1) * 90) % 360;
+ } else {
+ *val &= MXC4005_REG_TILT_ORIENT_Z_MASK;
+ *val = *val ? 180 : 0;
+ }
+ return IIO_VAL_INT;
+ default:
+ return -EINVAL;
+ }
case IIO_CHAN_INFO_RAW:
switch (chan->type) {
case IIO_ACCEL:
@@ -287,11 +315,22 @@ static const unsigned long mxc4005_scan_masks[] = {
}, \
}

+#define MXC4005_CHANNEL_ORIENTATION(_axis) { \
+ .type = IIO_ROT, \
+ .modified = 1, \
+ .channel2 = IIO_MOD_##_axis, \
+ .address = MXC4005_REG_TILT_ORIENT, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), \
+ .scan_index = -1, \
+}
+
static const struct iio_chan_spec mxc4005_channels[] = {
MXC4005_CHANNEL(X, MXC4005_REG_XOUT_UPPER),
MXC4005_CHANNEL(Y, MXC4005_REG_YOUT_UPPER),
MXC4005_CHANNEL(Z, MXC4005_REG_ZOUT_UPPER),
IIO_CHAN_SOFT_TIMESTAMP(3),
+ MXC4005_CHANNEL_ORIENTATION(X_AND_Y),
+ MXC4005_CHANNEL_ORIENTATION(Z),
};

static irqreturn_t mxc4005_trigger_handler(int irq, void *private)
--
2.36.1
\
 
 \ /
  Last update: 2022-06-15 13:05    [W:0.049 / U:0.260 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site