drivers/thermal/intel/int340x_thermal/int3406_thermal.c

Source file repositories/reference/linux-study-clean/drivers/thermal/intel/int340x_thermal/int3406_thermal.c

File Facts

System
Linux kernel
Corpus path
drivers/thermal/intel/int340x_thermal/int3406_thermal.c
Extension
.c
Size
5403 bytes
Lines
209
Domain
Driver Families
Bucket
drivers/thermal
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 int3406_thermal_data {
	int upper_limit;
	int lower_limit;
	acpi_handle handle;
	struct acpi_video_device_brightness *br;
	struct backlight_device *raw_bd;
	struct thermal_cooling_device *cooling_dev;
};

/*
 * According to the ACPI spec,
 * "Each brightness level is represented by a number between 0 and 100,
 * and can be thought of as a percentage. For example, 50 can be 50%
 * power consumption or 50% brightness, as defined by the OEM."
 *
 * As int3406 device uses this value to communicate with the native
 * graphics driver, we make the assumption that it represents
 * the percentage of brightness only
 */
#define ACPI_TO_RAW(v, d) (d->raw_bd->props.max_brightness * v / 100)
#define RAW_TO_ACPI(v, d) (v * 100 / d->raw_bd->props.max_brightness)

static int
int3406_thermal_get_max_state(struct thermal_cooling_device *cooling_dev,
			      unsigned long *state)
{
	struct int3406_thermal_data *d = cooling_dev->devdata;

	*state = d->upper_limit - d->lower_limit;
	return 0;
}

static int
int3406_thermal_set_cur_state(struct thermal_cooling_device *cooling_dev,
			      unsigned long state)
{
	struct int3406_thermal_data *d = cooling_dev->devdata;
	int acpi_level, raw_level;

	if (state > d->upper_limit - d->lower_limit)
		return -EINVAL;

	acpi_level = d->br->levels[d->upper_limit - state];

	raw_level = ACPI_TO_RAW(acpi_level, d);

	return backlight_device_set_brightness(d->raw_bd, raw_level);
}

static int
int3406_thermal_get_cur_state(struct thermal_cooling_device *cooling_dev,
			      unsigned long *state)
{
	struct int3406_thermal_data *d = cooling_dev->devdata;
	int acpi_level;
	int index;

	acpi_level = RAW_TO_ACPI(d->raw_bd->props.brightness, d);

	/*
	 * There is no 1:1 mapping between the firmware interface level
	 * with the raw interface level, we will have to find one that is
	 * right above it.
	 */
	for (index = d->lower_limit; index < d->upper_limit; index++) {
		if (acpi_level <= d->br->levels[index])
			break;
	}

	*state = d->upper_limit - index;
	return 0;
}

static const struct thermal_cooling_device_ops video_cooling_ops = {
	.get_max_state = int3406_thermal_get_max_state,
	.get_cur_state = int3406_thermal_get_cur_state,
	.set_cur_state = int3406_thermal_set_cur_state,
};

static int int3406_thermal_get_index(int *array, int nr, int value)
{
	int i;

	for (i = 2; i < nr; i++) {
		if (array[i] == value)
			break;
	}
	return i == nr ? -ENOENT : i;
}

Annotation

Implementation Notes