From: Jonathan LoBue Date: Sun, 25 Feb 2024 14:43:01 -0800 Subject: [PATCH] iio: imu: bmi323: Implement ACPI method ROTM for mount matrix Retrieve mount matrix from ACPI ROTM table. --- drivers/iio/imu/bmi323/bmi323_core.c | 79 ++++++++++++++++++++++++++-- 1 file changed, 76 insertions(+), 3 deletions(-) diff --git a/drivers/iio/imu/bmi323/bmi323_core.c b/drivers/iio/imu/bmi323/bmi323_core.c index 183af482828f..bb9f05183814 100644 --- a/drivers/iio/imu/bmi323/bmi323_core.c +++ b/drivers/iio/imu/bmi323/bmi323_core.c @@ -7,6 +7,7 @@ * Datasheet: https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bmi323-ds000.pdf */ +#include #include #include #include @@ -1997,6 +1998,76 @@ static int bmi323_set_bw(struct bmi323_data *data, FIELD_PREP(BMI323_ACC_GYRO_CONF_BW_MSK, bw)); } +static bool bmi323_acpi_orientation(struct device *dev, + struct iio_mount_matrix *orientation) +{ + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; + struct acpi_device *adev = ACPI_COMPANION(dev); + char *str; + union acpi_object *obj, *elements; + acpi_status status; + int i, j, val[3]; + bool ret = false; + + if (!acpi_has_method(adev->handle, "ROTM")) + return false; + + status = acpi_evaluate_object(adev->handle, "ROTM", NULL, &buffer); + if (ACPI_FAILURE(status)) { + dev_err(dev, "Failed to get ACPI mount matrix: %d\n", status); + return false; + } + + obj = buffer.pointer; + if (obj->type != ACPI_TYPE_PACKAGE || obj->package.count != 3) { + dev_err(dev, "Unknown ACPI mount matrix package format\n"); + goto out_free_buffer; + } + + elements = obj->package.elements; + for (i = 0; i < 3; i++) { + if (elements[i].type != ACPI_TYPE_STRING) { + dev_err(dev, "Unknown ACPI mount matrix element format\n"); + goto out_free_buffer; + } + + str = elements[i].string.pointer; + if (sscanf(str, "%d %d %d", &val[0], &val[1], &val[2]) != 3) { + dev_err(dev, "Incorrect ACPI mount matrix string format\n"); + goto out_free_buffer; + } + + 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: + dev_err(dev, "Invalid value in ACPI mount matrix: %d\n", val[j]); + goto out_free_buffer; + } + orientation->rotation[i * 3 + j] = str; + } + } + + ret = true; + +out_free_buffer: + kfree(buffer.pointer); + return ret; +} + +static bool bmi323_apply_acpi_orientation(struct device *dev, + struct iio_mount_matrix *orientation) +{ + struct acpi_device *adev = ACPI_COMPANION(dev); + + if (adev) + return bmi323_acpi_orientation(dev, orientation); + + return false; +} + static int bmi323_init(struct bmi323_data *data) { int ret, val; @@ -2099,9 +2170,11 @@ int bmi323_core_probe(struct device *dev) if (ret) return -EINVAL; - ret = iio_read_mount_matrix(dev, &data->orientation); - if (ret) - return ret; + if (!bmi323_apply_acpi_orientation(dev, &data->orientation)) { + ret = iio_read_mount_matrix(dev, &data->orientation); + if (ret) + return ret; + } indio_dev->name = "bmi323-imu"; indio_dev->info = &bmi323_info; diff --git a/drivers/iio/imu/bmi323/bmi323_core.c b/drivers/iio/imu/bmi323/bmi323_core.c index 0bd5ded..ded8596 100644 --- a/drivers/iio/imu/bmi323/bmi323_core.c +++ b/drivers/iio/imu/bmi323/bmi323_core.c @@ -285,6 +286,9 @@ static const int bmi323_acc_gyro_odr[][2] = { { 200, 0 }, { 400, 0 }, { 800, 0 }, + { 1600, 0}, + { 3200, 0}, + { 6400, 0}, }; static const int bmi323_acc_gyro_odrns[] = {