iio: imu: lsm6dsx: Add ACPI mount matrix retrieval
DSDT ROTM method seen in the wild with SMO8B30 _HID. Making assumption it is similar to that used for bmc150 plus information from Darrell that the rotation is out by 90 degrees at boot. Method (ROTM, 0, NotSerialized) { Name (RBUF, Package (0x03) { "0 -1 0", "1 0 0", "0 0 1" }) Return (RBUF) /* \_SB_.PCI0.I2C5.DEV_.ROTM.RBUF */ } Reported-by: Darrell Kavanagh <darrell.kavanagh@gmail.com> Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> Tested-by: Darrell Kavanagh <darrell.kavanagh@gmail.org> Link: https://lore.kernel.org/r/20230130201018.981024-3-jic23@kernel.org Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
This commit is contained in:
parent
bd66b6acd2
commit
dc3d25f22b
1 changed files with 74 additions and 3 deletions
|
@ -56,6 +56,7 @@
|
||||||
|
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
|
#include <linux/acpi.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/iio/events.h>
|
#include <linux/iio/events.h>
|
||||||
#include <linux/iio/iio.h>
|
#include <linux/iio/iio.h>
|
||||||
|
@ -2624,6 +2625,73 @@ static int st_lsm6dsx_init_regulators(struct device *dev)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_ACPI
|
||||||
|
|
||||||
|
static int lsm6dsx_get_acpi_mount_matrix(struct device *dev,
|
||||||
|
struct iio_mount_matrix *orientation)
|
||||||
|
{
|
||||||
|
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
|
||||||
|
struct acpi_device *adev = ACPI_COMPANION(dev);
|
||||||
|
union acpi_object *obj, *elements;
|
||||||
|
acpi_status status;
|
||||||
|
int i, j, val[3];
|
||||||
|
char *str;
|
||||||
|
|
||||||
|
if (!has_acpi_companion(dev))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (!acpi_has_method(adev->handle, "ROTM"))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
status = acpi_evaluate_object(adev->handle, "ROTM", NULL, &buffer);
|
||||||
|
if (ACPI_FAILURE(status)) {
|
||||||
|
dev_warn(dev, "Failed to get ACPI mount matrix: %d\n", status);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj = buffer.pointer;
|
||||||
|
if (obj->type != ACPI_TYPE_PACKAGE || obj->package.count != 3)
|
||||||
|
goto unknown_format;
|
||||||
|
|
||||||
|
elements = obj->package.elements;
|
||||||
|
for (i = 0; i < 3; i++) {
|
||||||
|
if (elements[i].type != ACPI_TYPE_STRING)
|
||||||
|
goto unknown_format;
|
||||||
|
|
||||||
|
str = elements[i].string.pointer;
|
||||||
|
if (sscanf(str, "%d %d %d", &val[0], &val[1], &val[2]) != 3)
|
||||||
|
goto unknown_format;
|
||||||
|
|
||||||
|
for (j = 0; j < 3; j++) {
|
||||||
|
switch (val[j]) {
|
||||||
|
case -1: str = "-1"; break;
|
||||||
|
case 0: str = "0"; break;
|
||||||
|
case 1: str = "1"; break;
|
||||||
|
default: goto unknown_format;
|
||||||
|
}
|
||||||
|
orientation->rotation[i * 3 + j] = str;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
kfree(buffer.pointer);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
unknown_format:
|
||||||
|
dev_warn(dev, "Unknown ACPI mount matrix format, ignoring\n");
|
||||||
|
kfree(buffer.pointer);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
static int lsm6dsx_get_acpi_mount_matrix(struct device *dev,
|
||||||
|
struct iio_mount_matrix *orientation)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
int st_lsm6dsx_probe(struct device *dev, int irq, int hw_id,
|
int st_lsm6dsx_probe(struct device *dev, int irq, int hw_id,
|
||||||
struct regmap *regmap)
|
struct regmap *regmap)
|
||||||
{
|
{
|
||||||
|
@ -2698,9 +2766,12 @@ int st_lsm6dsx_probe(struct device *dev, int irq, int hw_id,
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = iio_read_mount_matrix(hw->dev, &hw->orientation);
|
err = lsm6dsx_get_acpi_mount_matrix(hw->dev, &hw->orientation);
|
||||||
if (err)
|
if (err) {
|
||||||
return err;
|
err = iio_read_mount_matrix(hw->dev, &hw->orientation);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) {
|
for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) {
|
||||||
if (!hw->iio_devs[i])
|
if (!hw->iio_devs[i])
|
||||||
|
|
Loading…
Add table
Reference in a new issue