drivers/video/backlight/pwm_bl.c

Source file repositories/reference/linux-study-clean/drivers/video/backlight/pwm_bl.c

File Facts

System
Linux kernel
Corpus path
drivers/video/backlight/pwm_bl.c
Extension
.c
Size
18431 bytes
Lines
709
Domain
Driver Families
Bucket
drivers/video
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 pwm_bl_data {
	struct pwm_device	*pwm;
	struct device		*dev;
	unsigned int		lth_brightness;
	unsigned int		*levels;
	bool			enabled;
	struct regulator	*power_supply;
	struct gpio_desc	*enable_gpio;
	unsigned int		scale;
	unsigned int		post_pwm_on_delay;
	unsigned int		pwm_off_delay;
	int			(*notify)(struct device *,
					  int brightness);
	void			(*notify_after)(struct device *,
					int brightness);
	void			(*exit)(struct device *);
};

static void pwm_backlight_power_on(struct pwm_bl_data *pb)
{
	int err;

	if (pb->enabled)
		return;

	if (pb->power_supply) {
		err = regulator_enable(pb->power_supply);
		if (err < 0)
			dev_err(pb->dev, "failed to enable power supply\n");
	}

	if (pb->post_pwm_on_delay)
		msleep(pb->post_pwm_on_delay);

	gpiod_set_value_cansleep(pb->enable_gpio, 1);

	pb->enabled = true;
}

static void pwm_backlight_power_off(struct pwm_bl_data *pb)
{
	if (!pb->enabled)
		return;

	gpiod_set_value_cansleep(pb->enable_gpio, 0);

	if (pb->pwm_off_delay)
		msleep(pb->pwm_off_delay);

	if (pb->power_supply)
		regulator_disable(pb->power_supply);
	pb->enabled = false;
}

static int compute_duty_cycle(struct pwm_bl_data *pb, int brightness, struct pwm_state *state)
{
	unsigned int lth = pb->lth_brightness;
	u64 duty_cycle;

	if (pb->levels)
		duty_cycle = pb->levels[brightness];
	else
		duty_cycle = brightness;

	duty_cycle *= state->period - lth;
	do_div(duty_cycle, pb->scale);

	return duty_cycle + lth;
}

static int pwm_backlight_update_status(struct backlight_device *bl)
{
	struct pwm_bl_data *pb = bl_get_data(bl);
	int brightness = backlight_get_brightness(bl);
	struct pwm_state state;

	if (pb->notify)
		brightness = pb->notify(pb->dev, brightness);

	if (brightness > 0) {
		pwm_get_state(pb->pwm, &state);
		state.duty_cycle = compute_duty_cycle(pb, brightness, &state);
		state.enabled = true;
		pwm_apply_might_sleep(pb->pwm, &state);

		pwm_backlight_power_on(pb);
	} else {
		pwm_backlight_power_off(pb);

		pwm_get_state(pb->pwm, &state);

Annotation

Implementation Notes