Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  1// SPDX-License-Identifier: GPL-2.0-only
  2/* IIO ACPI helper functions */
  3
  4#include <linux/acpi.h>
  5#include <linux/device.h>
  6#include <linux/export.h>
  7#include <linux/iio/iio.h>
  8#include <linux/sprintf.h>
  9
 10/**
 11 * iio_read_acpi_mount_matrix() - Read accelerometer mount matrix info from ACPI
 12 * @dev:		Device structure
 13 * @orientation:	iio_mount_matrix struct to fill
 14 * @acpi_method:	ACPI method name to read the matrix from, usually "ROTM"
 15 *
 16 * Try to read the mount-matrix by calling the specified method on the device's
 17 * ACPI firmware-node. If the device has no ACPI firmware-node; or the method
 18 * does not exist then this will fail silently. This expects the method to
 19 * return data in the ACPI "ROTM" format defined by Microsoft:
 20 * https://learn.microsoft.com/en-us/windows-hardware/drivers/sensors/sensors-acpi-entries
 21 * This is a Microsoft extension and not part of the official ACPI spec.
 22 * The method name is configurable because some dual-accel setups define 2 mount
 23 * matrices in a single ACPI device using separate "ROMK" and "ROMS" methods.
 24 *
 25 * Returns: true if the matrix was successfully, false otherwise.
 26 */
 27bool iio_read_acpi_mount_matrix(struct device *dev,
 28				struct iio_mount_matrix *orientation,
 29				char *acpi_method)
 30{
 31	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
 32	char *str;
 33	union acpi_object *obj, *elements;
 34	acpi_handle handle;
 35	acpi_status status;
 36	int i, j, val[3];
 37	bool ret = false;
 38
 39	handle = ACPI_HANDLE(dev);
 40	if (!handle)
 41		return false;
 42
 43	if (!acpi_has_method(handle, acpi_method))
 44		return false;
 45
 46	status = acpi_evaluate_object(handle, acpi_method, NULL, &buffer);
 47	if (ACPI_FAILURE(status)) {
 48		dev_err(dev, "Failed to get ACPI mount matrix: %d\n", status);
 49		return false;
 50	}
 51
 52	obj = buffer.pointer;
 53	if (obj->type != ACPI_TYPE_PACKAGE || obj->package.count != 3) {
 54		dev_err(dev, "Unknown ACPI mount matrix package format\n");
 55		goto out_free_buffer;
 56	}
 57
 58	elements = obj->package.elements;
 59	for (i = 0; i < 3; i++) {
 60		if (elements[i].type != ACPI_TYPE_STRING) {
 61			dev_err(dev, "Unknown ACPI mount matrix element format\n");
 62			goto out_free_buffer;
 63		}
 64
 65		str = elements[i].string.pointer;
 66		if (sscanf(str, "%d %d %d", &val[0], &val[1], &val[2]) != 3) {
 67			dev_err(dev, "Incorrect ACPI mount matrix string format\n");
 68			goto out_free_buffer;
 69		}
 70
 71		for (j = 0; j < 3; j++) {
 72			switch (val[j]) {
 73			case -1: str = "-1"; break;
 74			case 0:  str = "0";  break;
 75			case 1:  str = "1";  break;
 76			default:
 77				dev_err(dev, "Invalid value in ACPI mount matrix: %d\n", val[j]);
 78				goto out_free_buffer;
 79			}
 80			orientation->rotation[i * 3 + j] = str;
 81		}
 82	}
 83
 84	ret = true;
 85
 86out_free_buffer:
 87	kfree(buffer.pointer);
 88	return ret;
 89}
 90EXPORT_SYMBOL_GPL(iio_read_acpi_mount_matrix);
 91
 92/**
 93 * iio_get_acpi_device_name_and_data() - Return ACPI device instance name and driver data
 94 * @dev:		Device structure
 95 * @data:		Optional pointer to return driver data
 96 *
 97 * When device was enumerated by ACPI ID matching, the user might
 98 * want to set description for the physical chip. In such cases
 99 * the ACPI device instance name might be used. This call may be
100 * performed to retrieve this information.
101 *
102 * NOTE: This helper function exists only for backward compatibility,
103 * do not use in a new code!
104 *
105 * Returns: ACPI device instance name or %NULL.
106 */
107const char *iio_get_acpi_device_name_and_data(struct device *dev, const void **data)
108{
109	const struct acpi_device_id *id;
110	acpi_handle handle;
111
112	handle = ACPI_HANDLE(dev);
113	if (!handle)
114		return NULL;
115
116	id = acpi_match_device(dev->driver->acpi_match_table, dev);
117	if (!id)
118		return NULL;
119
120	if (data)
121		*data = (const void *)id->driver_data;
122
123	return dev_name(dev);
124}
125EXPORT_SYMBOL_GPL(iio_get_acpi_device_name_and_data);