drivers/video/backlight/cgbc_bl.c

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

File Facts

System
Linux kernel
Corpus path
drivers/video/backlight/cgbc_bl.c
Extension
.c
Size
4872 bytes
Lines
181
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 cgbc_bl_data {
	struct device *dev;
	struct cgbc_device_data *cgbc;
	unsigned int current_brightness;
};

static int cgbc_bl_read_brightness(struct cgbc_bl_data *bl_data)
{
	u8 cmd_buf[4] = { CGBC_CMD_BLT0_PWM };
	u8 reply_buf[3];
	int ret;

	ret = cgbc_command(bl_data->cgbc, cmd_buf, sizeof(cmd_buf),
			   reply_buf, sizeof(reply_buf), NULL);
	if (ret < 0)
		return ret;

	/*
	 * Get only PWM duty factor percentage,
	 * ignore polarity inversion bit (bit 7)
	 */
	bl_data->current_brightness = FIELD_GET(BLT_PWM_DUTY_MASK, reply_buf[0]);

	return 0;
}

static int cgbc_bl_update_status(struct backlight_device *bl)
{
	struct cgbc_bl_data *bl_data = bl_get_data(bl);
	u8 cmd_buf[4] = { CGBC_CMD_BLT0_PWM };
	u8 reply_buf[3];
	u8 brightness;
	int ret;

	brightness = backlight_get_brightness(bl);

	if (brightness != bl_data->current_brightness) {
		/* Read the current values */
		ret = cgbc_command(bl_data->cgbc, cmd_buf, sizeof(cmd_buf), reply_buf,
				   sizeof(reply_buf), NULL);
		if (ret < 0) {
			dev_err(bl_data->dev, "Failed to read PWM settings: %d\n", ret);
			return ret;
		}

		/*
		 * Prepare command buffer for writing new settings. Only 2nd byte is changed
		 * to set new brightness (PWM duty cycle %). Other values (polarity, frequency)
		 * are preserved from the read values.
		 */
		cmd_buf[1] = (reply_buf[0] & ~BLT_PWM_DUTY_MASK) |
			FIELD_PREP(BLT_PWM_DUTY_MASK, brightness);
		cmd_buf[2] = reply_buf[1];
		cmd_buf[3] = reply_buf[2];

		ret = cgbc_command(bl_data->cgbc, cmd_buf, sizeof(cmd_buf), reply_buf,
				   sizeof(reply_buf), NULL);
		if (ret < 0) {
			dev_err(bl_data->dev, "Failed to set brightness: %d\n", ret);
			return ret;
		}

		bl_data->current_brightness = reply_buf[0] & BLT_PWM_DUTY_MASK;

		/* Verify the setting was applied correctly */
		if (bl_data->current_brightness != brightness) {
			dev_err(bl_data->dev,
				"Brightness setting verification failed (got %u, expected %u)\n",
				bl_data->current_brightness, (unsigned int)brightness);
			return -EIO;
		}
	}

	return 0;
}

static int cgbc_bl_get_brightness(struct backlight_device *bl)
{
	struct cgbc_bl_data *bl_data = bl_get_data(bl);
	int ret;

	ret = cgbc_bl_read_brightness(bl_data);
	if (ret < 0) {
		dev_err(bl_data->dev, "Failed to read brightness: %d\n", ret);
		return ret;
	}

	return bl_data->current_brightness;
}

Annotation

Implementation Notes