drivers/leds/leds-el15203000.c

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

File Facts

System
Linux kernel
Corpus path
drivers/leds/leds-el15203000.c
Extension
.c
Size
8758 bytes
Lines
341
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 el15203000_led {
	struct led_classdev	ldev;
	struct el15203000	*priv;
	u32			reg;
};

struct el15203000 {
	struct device		*dev;
	struct mutex		lock;
	struct spi_device	*spi;
	unsigned long		delay;
	size_t			count;
	struct el15203000_led	leds[] __counted_by(count);
};

#define to_el15203000_led(d)	container_of(d, struct el15203000_led, ldev)

static int el15203000_cmd(struct el15203000_led *led, u8 brightness)
{
	int		ret;
	u8		cmd[2];
	size_t		i;

	mutex_lock(&led->priv->lock);

	dev_dbg(led->priv->dev, "Set brightness of 0x%02x(%c) to 0x%02x(%c)",
		led->reg, led->reg, brightness, brightness);

	/* to avoid SPI mistiming with firmware we should wait some time */
	if (time_after(led->priv->delay, jiffies)) {
		dev_dbg(led->priv->dev, "Wait %luus to sync",
			EL_FW_DELAY_USEC);

		usleep_range(EL_FW_DELAY_USEC,
			     EL_FW_DELAY_USEC + 1);
	}

	cmd[0] = led->reg;
	cmd[1] = brightness;

	for (i = 0; i < ARRAY_SIZE(cmd); i++) {
		if (i)
			usleep_range(EL_FW_DELAY_USEC,
				     EL_FW_DELAY_USEC + 1);

		ret = spi_write(led->priv->spi, &cmd[i], sizeof(cmd[i]));
		if (ret) {
			dev_err(led->priv->dev,
				"spi_write() error %d", ret);
			break;
		}
	}

	led->priv->delay = jiffies + usecs_to_jiffies(EL_FW_DELAY_USEC);

	mutex_unlock(&led->priv->lock);

	return ret;
}

static int el15203000_set_blocking(struct led_classdev *ldev,
				   enum led_brightness brightness)
{
	struct el15203000_led *led = to_el15203000_led(ldev);

	return el15203000_cmd(led, brightness == LED_OFF ? EL_OFF : EL_ON);
}

static int el15203000_pattern_set_S(struct led_classdev *ldev,
				    struct led_pattern *pattern,
				    u32 len, int repeat)
{
	struct el15203000_led *led = to_el15203000_led(ldev);

	if (repeat > 0 || len != 2 ||
	    pattern[0].delta_t != 4000 || pattern[0].brightness != 0 ||
	    pattern[1].delta_t != 4000 || pattern[1].brightness != 1)
		return -EINVAL;

	dev_dbg(led->priv->dev, "Breathing mode for 0x%02x(%c)",
		led->reg, led->reg);

	return el15203000_cmd(led, EL_SCREEN_BREATHING);
}

static bool is_cascade(const struct led_pattern *pattern, u32 len,
		       bool inv, bool right)
{
	int val, t;
	u32 i;

Annotation

Implementation Notes