iio: accel: st_sensors: Support generic mounting matrix
The ST accelerators support a special type of quirky mounting matrix found in ACPI systems, but not a generic mounting matrix such as from the device tree. Augment the ACPI hack to be a bit more generic and accept a mounting matrix from device properties. This makes it possible to fix orientation on the Ux500 HREF device. Cc: Hans de Goede <hdegoede@redhat.com> Cc: Denis Ciocca <denis.ciocca@st.com> Cc: Daniel Drake <drake@endlessm.com> Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Signed-off-by: Stephan Gerhold <stephan@gerhold.net> Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Reviewed-by: Hans de Goede <hdegoede@redhat.com> Link: https://lore.kernel.org/r/20210518230722.522446-2-linus.walleij@linaro.org Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
This commit is contained in:
Родитель
42ef8aa226
Коммит
3d8ad94bb1
|
@ -41,51 +41,74 @@
|
||||||
#define ST_ACCEL_FS_AVL_200G 200
|
#define ST_ACCEL_FS_AVL_200G 200
|
||||||
#define ST_ACCEL_FS_AVL_400G 400
|
#define ST_ACCEL_FS_AVL_400G 400
|
||||||
|
|
||||||
|
static const struct iio_mount_matrix *
|
||||||
|
st_accel_get_mount_matrix(const struct iio_dev *indio_dev,
|
||||||
|
const struct iio_chan_spec *chan)
|
||||||
|
{
|
||||||
|
struct st_sensor_data *adata = iio_priv(indio_dev);
|
||||||
|
|
||||||
|
return &adata->mount_matrix;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct iio_chan_spec_ext_info st_accel_mount_matrix_ext_info[] = {
|
||||||
|
IIO_MOUNT_MATRIX(IIO_SHARED_BY_ALL, st_accel_get_mount_matrix),
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
|
||||||
static const struct iio_chan_spec st_accel_8bit_channels[] = {
|
static const struct iio_chan_spec st_accel_8bit_channels[] = {
|
||||||
ST_SENSORS_LSM_CHANNELS(IIO_ACCEL,
|
ST_SENSORS_LSM_CHANNELS_EXT(IIO_ACCEL,
|
||||||
BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
|
BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
|
||||||
ST_SENSORS_SCAN_X, 1, IIO_MOD_X, 's', IIO_LE, 8, 8,
|
ST_SENSORS_SCAN_X, 1, IIO_MOD_X, 's', IIO_LE, 8, 8,
|
||||||
ST_ACCEL_DEFAULT_OUT_X_L_ADDR+1),
|
ST_ACCEL_DEFAULT_OUT_X_L_ADDR+1,
|
||||||
ST_SENSORS_LSM_CHANNELS(IIO_ACCEL,
|
st_accel_mount_matrix_ext_info),
|
||||||
|
ST_SENSORS_LSM_CHANNELS_EXT(IIO_ACCEL,
|
||||||
BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
|
BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
|
||||||
ST_SENSORS_SCAN_Y, 1, IIO_MOD_Y, 's', IIO_LE, 8, 8,
|
ST_SENSORS_SCAN_Y, 1, IIO_MOD_Y, 's', IIO_LE, 8, 8,
|
||||||
ST_ACCEL_DEFAULT_OUT_Y_L_ADDR+1),
|
ST_ACCEL_DEFAULT_OUT_Y_L_ADDR+1,
|
||||||
ST_SENSORS_LSM_CHANNELS(IIO_ACCEL,
|
st_accel_mount_matrix_ext_info),
|
||||||
|
ST_SENSORS_LSM_CHANNELS_EXT(IIO_ACCEL,
|
||||||
BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
|
BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
|
||||||
ST_SENSORS_SCAN_Z, 1, IIO_MOD_Z, 's', IIO_LE, 8, 8,
|
ST_SENSORS_SCAN_Z, 1, IIO_MOD_Z, 's', IIO_LE, 8, 8,
|
||||||
ST_ACCEL_DEFAULT_OUT_Z_L_ADDR+1),
|
ST_ACCEL_DEFAULT_OUT_Z_L_ADDR+1,
|
||||||
|
st_accel_mount_matrix_ext_info),
|
||||||
IIO_CHAN_SOFT_TIMESTAMP(3)
|
IIO_CHAN_SOFT_TIMESTAMP(3)
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct iio_chan_spec st_accel_12bit_channels[] = {
|
static const struct iio_chan_spec st_accel_12bit_channels[] = {
|
||||||
ST_SENSORS_LSM_CHANNELS(IIO_ACCEL,
|
ST_SENSORS_LSM_CHANNELS_EXT(IIO_ACCEL,
|
||||||
BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
|
BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
|
||||||
ST_SENSORS_SCAN_X, 1, IIO_MOD_X, 's', IIO_LE, 12, 16,
|
ST_SENSORS_SCAN_X, 1, IIO_MOD_X, 's', IIO_LE, 12, 16,
|
||||||
ST_ACCEL_DEFAULT_OUT_X_L_ADDR),
|
ST_ACCEL_DEFAULT_OUT_X_L_ADDR,
|
||||||
ST_SENSORS_LSM_CHANNELS(IIO_ACCEL,
|
st_accel_mount_matrix_ext_info),
|
||||||
|
ST_SENSORS_LSM_CHANNELS_EXT(IIO_ACCEL,
|
||||||
BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
|
BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
|
||||||
ST_SENSORS_SCAN_Y, 1, IIO_MOD_Y, 's', IIO_LE, 12, 16,
|
ST_SENSORS_SCAN_Y, 1, IIO_MOD_Y, 's', IIO_LE, 12, 16,
|
||||||
ST_ACCEL_DEFAULT_OUT_Y_L_ADDR),
|
ST_ACCEL_DEFAULT_OUT_Y_L_ADDR,
|
||||||
ST_SENSORS_LSM_CHANNELS(IIO_ACCEL,
|
st_accel_mount_matrix_ext_info),
|
||||||
|
ST_SENSORS_LSM_CHANNELS_EXT(IIO_ACCEL,
|
||||||
BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
|
BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
|
||||||
ST_SENSORS_SCAN_Z, 1, IIO_MOD_Z, 's', IIO_LE, 12, 16,
|
ST_SENSORS_SCAN_Z, 1, IIO_MOD_Z, 's', IIO_LE, 12, 16,
|
||||||
ST_ACCEL_DEFAULT_OUT_Z_L_ADDR),
|
ST_ACCEL_DEFAULT_OUT_Z_L_ADDR,
|
||||||
|
st_accel_mount_matrix_ext_info),
|
||||||
IIO_CHAN_SOFT_TIMESTAMP(3)
|
IIO_CHAN_SOFT_TIMESTAMP(3)
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct iio_chan_spec st_accel_16bit_channels[] = {
|
static const struct iio_chan_spec st_accel_16bit_channels[] = {
|
||||||
ST_SENSORS_LSM_CHANNELS(IIO_ACCEL,
|
ST_SENSORS_LSM_CHANNELS_EXT(IIO_ACCEL,
|
||||||
BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
|
BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
|
||||||
ST_SENSORS_SCAN_X, 1, IIO_MOD_X, 's', IIO_LE, 16, 16,
|
ST_SENSORS_SCAN_X, 1, IIO_MOD_X, 's', IIO_LE, 16, 16,
|
||||||
ST_ACCEL_DEFAULT_OUT_X_L_ADDR),
|
ST_ACCEL_DEFAULT_OUT_X_L_ADDR,
|
||||||
ST_SENSORS_LSM_CHANNELS(IIO_ACCEL,
|
st_accel_mount_matrix_ext_info),
|
||||||
|
ST_SENSORS_LSM_CHANNELS_EXT(IIO_ACCEL,
|
||||||
BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
|
BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
|
||||||
ST_SENSORS_SCAN_Y, 1, IIO_MOD_Y, 's', IIO_LE, 16, 16,
|
ST_SENSORS_SCAN_Y, 1, IIO_MOD_Y, 's', IIO_LE, 16, 16,
|
||||||
ST_ACCEL_DEFAULT_OUT_Y_L_ADDR),
|
ST_ACCEL_DEFAULT_OUT_Y_L_ADDR,
|
||||||
ST_SENSORS_LSM_CHANNELS(IIO_ACCEL,
|
st_accel_mount_matrix_ext_info),
|
||||||
|
ST_SENSORS_LSM_CHANNELS_EXT(IIO_ACCEL,
|
||||||
BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
|
BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
|
||||||
ST_SENSORS_SCAN_Z, 1, IIO_MOD_Z, 's', IIO_LE, 16, 16,
|
ST_SENSORS_SCAN_Z, 1, IIO_MOD_Z, 's', IIO_LE, 16, 16,
|
||||||
ST_ACCEL_DEFAULT_OUT_Z_L_ADDR),
|
ST_ACCEL_DEFAULT_OUT_Z_L_ADDR,
|
||||||
|
st_accel_mount_matrix_ext_info),
|
||||||
IIO_CHAN_SOFT_TIMESTAMP(3)
|
IIO_CHAN_SOFT_TIMESTAMP(3)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1162,25 +1185,10 @@ static const struct iio_trigger_ops st_accel_trigger_ops = {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_ACPI
|
#ifdef CONFIG_ACPI
|
||||||
static const struct iio_mount_matrix *
|
|
||||||
get_mount_matrix(const struct iio_dev *indio_dev,
|
|
||||||
const struct iio_chan_spec *chan)
|
|
||||||
{
|
|
||||||
struct st_sensor_data *adata = iio_priv(indio_dev);
|
|
||||||
|
|
||||||
return adata->mount_matrix;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct iio_chan_spec_ext_info mount_matrix_ext_info[] = {
|
|
||||||
IIO_MOUNT_MATRIX(IIO_SHARED_BY_ALL, get_mount_matrix),
|
|
||||||
{ },
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Read ST-specific _ONT orientation data from ACPI and generate an
|
/* Read ST-specific _ONT orientation data from ACPI and generate an
|
||||||
* appropriate mount matrix.
|
* appropriate mount matrix.
|
||||||
*/
|
*/
|
||||||
static int apply_acpi_orientation(struct iio_dev *indio_dev,
|
static int apply_acpi_orientation(struct iio_dev *indio_dev)
|
||||||
struct iio_chan_spec *channels)
|
|
||||||
{
|
{
|
||||||
struct st_sensor_data *adata = iio_priv(indio_dev);
|
struct st_sensor_data *adata = iio_priv(indio_dev);
|
||||||
struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
|
struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
|
||||||
|
@ -1269,14 +1277,6 @@ static int apply_acpi_orientation(struct iio_dev *indio_dev,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Convert our integer matrix to a string-based iio_mount_matrix */
|
/* Convert our integer matrix to a string-based iio_mount_matrix */
|
||||||
adata->mount_matrix = devm_kmalloc(&indio_dev->dev,
|
|
||||||
sizeof(*adata->mount_matrix),
|
|
||||||
GFP_KERNEL);
|
|
||||||
if (!adata->mount_matrix) {
|
|
||||||
ret = -ENOMEM;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < 3; i++) {
|
for (i = 0; i < 3; i++) {
|
||||||
for (j = 0; j < 3; j++) {
|
for (j = 0; j < 3; j++) {
|
||||||
int matrix_val = final_ont[i][j];
|
int matrix_val = final_ont[i][j];
|
||||||
|
@ -1295,26 +1295,25 @@ static int apply_acpi_orientation(struct iio_dev *indio_dev,
|
||||||
default:
|
default:
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
adata->mount_matrix->rotation[i * 3 + j] = str_value;
|
adata->mount_matrix.rotation[i * 3 + j] = str_value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Expose the mount matrix via ext_info */
|
|
||||||
for (i = 0; i < indio_dev->num_channels; i++)
|
|
||||||
channels[i].ext_info = mount_matrix_ext_info;
|
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
dev_info(&indio_dev->dev, "computed mount matrix from ACPI\n");
|
dev_info(&indio_dev->dev, "computed mount matrix from ACPI\n");
|
||||||
|
|
||||||
out:
|
out:
|
||||||
kfree(buffer.pointer);
|
kfree(buffer.pointer);
|
||||||
|
if (ret)
|
||||||
|
dev_dbg(&indio_dev->dev,
|
||||||
|
"failed to apply ACPI orientation data: %d\n", ret);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
#else /* !CONFIG_ACPI */
|
#else /* !CONFIG_ACPI */
|
||||||
static int apply_acpi_orientation(struct iio_dev *indio_dev,
|
static int apply_acpi_orientation(struct iio_dev *indio_dev)
|
||||||
struct iio_chan_spec *channels)
|
|
||||||
{
|
{
|
||||||
return 0;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1361,9 +1360,16 @@ int st_accel_common_probe(struct iio_dev *indio_dev)
|
||||||
if (!channels)
|
if (!channels)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
if (apply_acpi_orientation(indio_dev, channels))
|
/*
|
||||||
dev_warn(&indio_dev->dev,
|
* First try specific ACPI methods to retrieve orientation then try the
|
||||||
"failed to apply ACPI orientation data: %d\n", err);
|
* generic function.
|
||||||
|
*/
|
||||||
|
err = apply_acpi_orientation(indio_dev);
|
||||||
|
if (err) {
|
||||||
|
err = iio_read_mount_matrix(adata->dev, &adata->mount_matrix);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
indio_dev->channels = channels;
|
indio_dev->channels = channels;
|
||||||
adata->current_fullscale = &adata->sensor_settings->fs.fs_avl[0];
|
adata->current_fullscale = &adata->sensor_settings->fs.fs_avl[0];
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include <linux/i2c.h>
|
#include <linux/i2c.h>
|
||||||
#include <linux/spi/spi.h>
|
#include <linux/spi/spi.h>
|
||||||
#include <linux/irqreturn.h>
|
#include <linux/irqreturn.h>
|
||||||
|
#include <linux/iio/iio.h>
|
||||||
#include <linux/iio/trigger.h>
|
#include <linux/iio/trigger.h>
|
||||||
#include <linux/bitops.h>
|
#include <linux/bitops.h>
|
||||||
#include <linux/regulator/consumer.h>
|
#include <linux/regulator/consumer.h>
|
||||||
|
@ -221,6 +222,7 @@ struct st_sensor_settings {
|
||||||
* struct st_sensor_data - ST sensor device status
|
* struct st_sensor_data - ST sensor device status
|
||||||
* @dev: Pointer to instance of struct device (I2C or SPI).
|
* @dev: Pointer to instance of struct device (I2C or SPI).
|
||||||
* @trig: The trigger in use by the core driver.
|
* @trig: The trigger in use by the core driver.
|
||||||
|
* @mount_matrix: The mounting matrix of the sensor.
|
||||||
* @sensor_settings: Pointer to the specific sensor settings in use.
|
* @sensor_settings: Pointer to the specific sensor settings in use.
|
||||||
* @current_fullscale: Maximum range of measure by the sensor.
|
* @current_fullscale: Maximum range of measure by the sensor.
|
||||||
* @vdd: Pointer to sensor's Vdd power supply
|
* @vdd: Pointer to sensor's Vdd power supply
|
||||||
|
@ -240,7 +242,7 @@ struct st_sensor_settings {
|
||||||
struct st_sensor_data {
|
struct st_sensor_data {
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
struct iio_trigger *trig;
|
struct iio_trigger *trig;
|
||||||
struct iio_mount_matrix *mount_matrix;
|
struct iio_mount_matrix mount_matrix;
|
||||||
struct st_sensor_settings *sensor_settings;
|
struct st_sensor_settings *sensor_settings;
|
||||||
struct st_sensor_fullscale_avl *current_fullscale;
|
struct st_sensor_fullscale_avl *current_fullscale;
|
||||||
struct regulator *vdd;
|
struct regulator *vdd;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче