drivers/iio/light/cm32181.c

Source file repositories/reference/linux-study-clean/drivers/iio/light/cm32181.c

File Facts

System
Linux kernel
Corpus path
drivers/iio/light/cm32181.c
Extension
.c
Size
14755 bytes
Lines
552
Domain
Driver Families
Bucket
drivers/iio
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct cm32181_chip {
	struct i2c_client *client;
	struct device *dev;
	struct mutex lock;
	u16 conf_regs[CM32181_CONF_REG_NUM];
	unsigned long init_regs_bitmap;
	int calibscale;
	int lux_per_bit;
	int lux_per_bit_base_it;
	int num_als_it;
	const int *als_it_bits;
	const int *als_it_values;
};

static int cm32181_read_als_it(struct cm32181_chip *cm32181, int *val2);

#ifdef CONFIG_ACPI
/**
 * cm32181_acpi_get_cpm() - Get CPM object from ACPI
 * @dev:	pointer of struct device.
 * @obj_name:	pointer of ACPI object name.
 * @values:	pointer of array for return elements.
 * @count:	maximum size of return array.
 *
 * Convert ACPI CPM table to array.
 *
 * Return: -ENODEV for fail.  Otherwise is number of elements.
 */
static int cm32181_acpi_get_cpm(struct device *dev, char *obj_name,
				u64 *values, int count)
{
	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
	union acpi_object *cpm, *elem;
	acpi_handle handle;
	acpi_status status;
	int i;

	handle = ACPI_HANDLE(dev);
	if (!handle)
		return -ENODEV;

	status = acpi_evaluate_object(handle, obj_name, NULL, &buffer);
	if (ACPI_FAILURE(status)) {
		dev_err(dev, "object %s not found\n", obj_name);
		return -ENODEV;
	}

	cpm = buffer.pointer;
	if (cpm->package.count > count)
		dev_warn(dev, "%s table contains %u values, only using first %d values\n",
			 obj_name, cpm->package.count, count);

	count = min_t(int, cpm->package.count, count);
	for (i = 0; i < count; i++) {
		elem = &(cpm->package.elements[i]);
		values[i] = elem->integer.value;
	}

	kfree(buffer.pointer);

	return count;
}

static void cm32181_acpi_parse_cpm_tables(struct cm32181_chip *cm32181)
{
	u64 vals[CPM0_HEADER_SIZE + CM32181_CONF_REG_NUM];
	struct device *dev = cm32181->dev;
	int i, count;

	count = cm32181_acpi_get_cpm(dev, "CPM0", vals, ARRAY_SIZE(vals));
	if (count <= CPM0_HEADER_SIZE)
		return;

	count -= CPM0_HEADER_SIZE;

	cm32181->init_regs_bitmap = vals[CPM0_REGS_BITMAP];
	cm32181->init_regs_bitmap &= GENMASK(count - 1, 0);
	for_each_set_bit(i, &cm32181->init_regs_bitmap, count)
		cm32181->conf_regs[i] =	vals[CPM0_HEADER_SIZE + i];

	count = cm32181_acpi_get_cpm(dev, "CPM1", vals, ARRAY_SIZE(vals));
	if (count != CPM1_SIZE)
		return;

	cm32181->lux_per_bit = vals[CPM1_LUX_PER_BIT];

	/* Check for uncalibrated devices */
	if (vals[CPM1_CALIBSCALE] == CM32181_CALIBSCALE_DEFAULT)
		return;

Annotation

Implementation Notes