drivers/leds/leds-an30259a.c

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

File Facts

System
Linux kernel
Corpus path
drivers/leds/leds-an30259a.c
Extension
.c
Size
8431 bytes
Lines
353
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 an30259a_led {
	struct an30259a *chip;
	struct fwnode_handle *fwnode;
	struct led_classdev cdev;
	u32 num;
	enum led_default_state default_state;
	bool sloping;
};

struct an30259a {
	struct mutex mutex; /* held when writing to registers */
	struct i2c_client *client;
	struct an30259a_led leds[AN30259A_MAX_LEDS];
	struct regmap *regmap;
	int num_leds;
};

static int an30259a_brightness_set(struct led_classdev *cdev,
				   enum led_brightness brightness)
{
	struct an30259a_led *led;
	int ret;
	unsigned int led_on;

	led = container_of(cdev, struct an30259a_led, cdev);
	mutex_lock(&led->chip->mutex);

	ret = regmap_read(led->chip->regmap, AN30259A_REG_LED_ON, &led_on);
	if (ret)
		goto error;

	switch (brightness) {
	case LED_OFF:
		led_on &= ~AN30259A_LED_EN(led->num);
		led_on &= ~AN30259A_LED_SLOPE(led->num);
		led->sloping = false;
		break;
	default:
		led_on |= AN30259A_LED_EN(led->num);
		if (led->sloping)
			led_on |= AN30259A_LED_SLOPE(led->num);
		ret = regmap_write(led->chip->regmap,
				   AN30259A_REG_LEDCNT1(led->num),
				   AN30259A_LED_DUTYMAX(0xf) |
				   AN30259A_LED_DUTYMID(0xf));
		if (ret)
			goto error;
		break;
	}

	ret = regmap_write(led->chip->regmap, AN30259A_REG_LED_ON, led_on);
	if (ret)
		goto error;

	ret = regmap_write(led->chip->regmap, AN30259A_REG_LEDCC(led->num),
			   brightness);

error:
	mutex_unlock(&led->chip->mutex);

	return ret;
}

static int an30259a_blink_set(struct led_classdev *cdev,
			      unsigned long *delay_off, unsigned long *delay_on)
{
	struct an30259a_led *led;
	int ret, num;
	unsigned int led_on;
	unsigned long off = *delay_off, on = *delay_on;

	led = container_of(cdev, struct an30259a_led, cdev);

	mutex_lock(&led->chip->mutex);
	num = led->num;

	/* slope time can only be a multiple of 500ms. */
	if (off % AN30259A_SLOPE_RESOLUTION || on % AN30259A_SLOPE_RESOLUTION) {
		ret = -EINVAL;
		goto error;
	}

	/* up to a maximum of 7500ms. */
	if (off > AN30259A_BLINK_MAX_TIME || on > AN30259A_BLINK_MAX_TIME) {
		ret = -EINVAL;
		goto error;
	}

	/* if no blink specified, default to 1 Hz. */
	if (!off && !on) {

Annotation

Implementation Notes