drivers/leds/flash/leds-mt6370-flash.c

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

File Facts

System
Linux kernel
Corpus path
drivers/leds/flash/leds-mt6370-flash.c
Extension
.c
Size
16020 bytes
Lines
569
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 mt6370_led {
	struct led_classdev_flash flash;
	struct v4l2_flash *v4l2_flash;
	struct mt6370_priv *priv;
	u8 led_no;
};

struct mt6370_priv {
	struct regmap *regmap;
	struct mutex lock;
	unsigned int fled_strobe_used;
	unsigned int fled_torch_used;
	unsigned int leds_active;
	unsigned int leds_count;
	struct mt6370_led leds[] __counted_by(leds_count);
};

static int mt6370_torch_brightness_set(struct led_classdev *lcdev, enum led_brightness level)
{
	struct mt6370_led *led = to_mt6370_led(lcdev, flash.led_cdev);
	struct mt6370_priv *priv = led->priv;
	u32 led_enable_mask = led->led_no == MT6370_LED_JOINT ? MT6370_FLCSEN_MASK_ALL :
			      MT6370_FLCSEN_MASK(led->led_no);
	u32 enable_mask = MT6370_TORCHEN_MASK | led_enable_mask;
	u32 val = level ? led_enable_mask : 0;
	u32 curr;
	int ret, i;

	mutex_lock(&priv->lock);

	/*
	 * There is only one set of flash control logic, and this flag is used to check if 'strobe'
	 * is currently being used.
	 */
	if (priv->fled_strobe_used) {
		dev_warn(lcdev->dev, "Please disable strobe first [%d]\n", priv->fled_strobe_used);
		ret = -EBUSY;
		goto unlock;
	}

	if (level)
		curr = priv->fled_torch_used | BIT(led->led_no);
	else
		curr = priv->fled_torch_used & ~BIT(led->led_no);

	if (curr)
		val |= MT6370_TORCHEN_MASK;

	if (level) {
		level -= 1;
		if (led->led_no == MT6370_LED_JOINT) {
			u32 flevel[MT6370_MAX_LEDS];

			/*
			 * There're two flash channels in MT6370. If joint flash output is used,
			 * torch current will be averaged output from both channels.
			 */
			flevel[0] = level / 2;
			flevel[1] = level - flevel[0];
			for (i = 0; i < MT6370_MAX_LEDS; i++) {
				ret = regmap_update_bits(priv->regmap, MT6370_REG_FLEDITOR(i),
							 MT6370_ITORCH_MASK, flevel[i]);
				if (ret)
					goto unlock;
			}
		} else {
			ret = regmap_update_bits(priv->regmap, MT6370_REG_FLEDITOR(led->led_no),
						 MT6370_ITORCH_MASK, level);
			if (ret)
				goto unlock;
		}
	}

	ret = regmap_update_bits(priv->regmap, MT6370_REG_FLEDEN, enable_mask, val);
	if (ret)
		goto unlock;

	priv->fled_torch_used = curr;

unlock:
	mutex_unlock(&priv->lock);
	return ret;
}

static int mt6370_flash_brightness_set(struct led_classdev_flash *fl_cdev, u32 brightness)
{
	/*
	 * Because of the current spikes when turning on the flash, the brightness should be kept
	 * by the LED framework. This empty function is used to prevent checking failure when
	 * led_classdev_flash registers ops.

Annotation

Implementation Notes