drivers/leds/flash/leds-s2m-flash.c

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

File Facts

System
Linux kernel
Corpus path
drivers/leds/flash/leds-s2m-flash.c
Extension
.c
Size
9473 bytes
Lines
351
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 s2m_led {
	struct regmap *regmap;
	struct led_classdev_flash fled;
	struct v4l2_flash *v4l2_flash;
	/*
	 * The mutex object prevents the concurrent access of flash control
	 * registers by the LED and V4L2 subsystems.
	 */
	struct mutex lock;
	unsigned int reg_enable;
	u8 channel;
	u8 flash_brightness;
	u8 flash_timeout;
};

static struct s2m_led *to_s2m_led(struct led_classdev_flash *fled)
{
	return container_of(fled, struct s2m_led, fled);
}

static struct led_classdev_flash *to_s2m_fled(struct led_classdev *cdev)
{
	return container_of(cdev, struct led_classdev_flash, led_cdev);
}

static int s2m_fled_flash_brightness_set(struct led_classdev_flash *fled, u32 brightness)
{
	struct s2m_led *led = to_s2m_led(fled);
	struct led_flash_setting *setting = &fled->brightness;

	mutex_lock(&led->lock);
	led->flash_brightness = (brightness - setting->min) / setting->step;
	mutex_unlock(&led->lock);

	return 0;
}

static int s2m_fled_flash_timeout_set(struct led_classdev_flash *fled, u32 timeout)
{
	struct s2m_led *led = to_s2m_led(fled);
	struct led_flash_setting *setting = &fled->timeout;

	mutex_lock(&led->lock);
	led->flash_timeout = (timeout - setting->min) / setting->step;
	mutex_unlock(&led->lock);

	return 0;
}

#if IS_ENABLED(CONFIG_V4L2_FLASH_LED_CLASS)
static int s2m_fled_flash_external_strobe_set(struct v4l2_flash *v4l2_flash, bool enable)
{
	struct s2m_led *led = to_s2m_led(v4l2_flash->fled_cdev);

	return led->fled.ops->strobe_set(&led->fled, enable);
}

static const struct v4l2_flash_ops s2m_fled_v4l2_flash_ops = {
	.external_strobe_set = s2m_fled_flash_external_strobe_set,
};
#else
static const struct v4l2_flash_ops s2m_fled_v4l2_flash_ops;
#endif

static void s2m_fled_v4l2_flash_release(void *v4l2_flash)
{
	v4l2_flash_release(v4l2_flash);
}

static int s2mu005_fled_torch_brightness_set(struct led_classdev *cdev, enum led_brightness value)
{
	struct s2m_led *led = to_s2m_led(to_s2m_fled(cdev));
	int ret;

	mutex_lock(&led->lock);

	if (!value) {
		ret = regmap_clear_bits(led->regmap, led->reg_enable,
					S2MU005_FLED_TORCH_EN(led->channel));
		if (ret)
			dev_err(cdev->dev, "failed to disable torch LED\n");
		goto unlock;
	}

	ret = regmap_update_bits(led->regmap, S2MU005_REG_FLED_CH_CTRL1(led->channel),
				 S2MU005_FLED_TORCH_IOUT,
				 FIELD_PREP(S2MU005_FLED_TORCH_IOUT, value - 1));
	if (ret) {
		dev_err(cdev->dev, "failed to set torch current\n");
		goto unlock;

Annotation

Implementation Notes