drivers/leds/leds-cros_ec.c

Source file repositories/reference/linux-study-clean/drivers/leds/leds-cros_ec.c

File Facts

System
Linux kernel
Corpus path
drivers/leds/leds-cros_ec.c
Extension
.c
Size
7178 bytes
Lines
264
Domain
Driver Families
Bucket
drivers/leds
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 cros_ec_led_priv {
	struct led_classdev_mc led_mc_cdev;
	struct cros_ec_device *cros_ec;
	enum ec_led_id led_id;
};

static inline struct cros_ec_led_priv *cros_ec_led_cdev_to_priv(struct led_classdev *led_cdev)
{
	return container_of(lcdev_to_mccdev(led_cdev), struct cros_ec_led_priv, led_mc_cdev);
}

union cros_ec_led_cmd_data {
	struct ec_params_led_control req;
	struct ec_response_led_control resp;
};

static int cros_ec_led_send_cmd(struct cros_ec_device *cros_ec,
				union cros_ec_led_cmd_data *arg)
{
	int ret;

	ret = cros_ec_cmd(cros_ec, 1, EC_CMD_LED_CONTROL, &arg->req,
			  sizeof(arg->req), &arg->resp, sizeof(arg->resp));
	if (ret < 0)
		return ret;

	return 0;
}

static int cros_ec_led_trigger_activate(struct led_classdev *led_cdev)
{
	struct cros_ec_led_priv *priv = cros_ec_led_cdev_to_priv(led_cdev);
	union cros_ec_led_cmd_data arg = {};

	arg.req.led_id = priv->led_id;
	arg.req.flags = EC_LED_FLAGS_AUTO;

	return cros_ec_led_send_cmd(priv->cros_ec, &arg);
}

static struct led_hw_trigger_type cros_ec_led_trigger_type;

static struct led_trigger cros_ec_led_trigger = {
	.name = "chromeos-auto",
	.trigger_type = &cros_ec_led_trigger_type,
	.activate = cros_ec_led_trigger_activate,
};

static int cros_ec_led_brightness_set_blocking(struct led_classdev *led_cdev,
					       enum led_brightness brightness)
{
	struct cros_ec_led_priv *priv = cros_ec_led_cdev_to_priv(led_cdev);
	union cros_ec_led_cmd_data arg = {};
	enum ec_led_colors led_color;
	struct mc_subled *subled;
	size_t i;

	led_mc_calc_color_components(&priv->led_mc_cdev, brightness);

	arg.req.led_id = priv->led_id;

	for (i = 0; i < priv->led_mc_cdev.num_colors; i++) {
		subled = &priv->led_mc_cdev.subled_info[i];
		led_color = cros_ec_linux_to_ec_id[subled->color_index];
		arg.req.brightness[led_color] = subled->brightness;
	}

	return cros_ec_led_send_cmd(priv->cros_ec, &arg);
}

static int cros_ec_led_count_subleds(struct device *dev,
				     struct ec_response_led_control *resp,
				     unsigned int *max_brightness)
{
	unsigned int range, common_range = 0;
	int num_subleds = 0;
	size_t i;

	for (i = 0; i < EC_LED_COLOR_COUNT; i++) {
		range = resp->brightness_range[i];

		if (!range)
			continue;

		num_subleds++;

		if (!common_range)
			common_range = range;

		if (common_range != range) {

Annotation

Implementation Notes