drivers/leds/leds-st1202.c

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

File Facts

System
Linux kernel
Corpus path
drivers/leds/leds-st1202.c
Extension
.c
Size
11068 bytes
Lines
416
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 st1202_led {
	struct fwnode_handle *fwnode;
	struct led_classdev led_cdev;
	struct st1202_chip *chip;
	bool is_active;
	int led_num;
};

struct st1202_chip {
	struct i2c_client *client;
	struct mutex lock;
	struct st1202_led leds[ST1202_MAX_LEDS];
};

static struct st1202_led *cdev_to_st1202_led(struct led_classdev *cdev)
{
	return container_of(cdev, struct st1202_led, led_cdev);
}

static int st1202_read_reg(struct st1202_chip *chip, int reg, uint8_t *val)
{
	struct device *dev = &chip->client->dev;
	int ret;

	ret = i2c_smbus_read_byte_data(chip->client, reg);
	if (ret < 0) {
		dev_err(dev, "Failed to read register [0x%x]: %d\n", reg, ret);
		return ret;
	}

	*val = (uint8_t)ret;
	return 0;
}

static int st1202_write_reg(struct st1202_chip *chip, int reg, uint8_t val)
{
	struct device *dev = &chip->client->dev;
	int ret;

	ret = i2c_smbus_write_byte_data(chip->client, reg, val);
	if (ret != 0)
		dev_err(dev, "Failed to write %d to register [0x%x]: %d\n", val, reg, ret);

	return ret;
}

static uint8_t st1202_prescalar_to_miliseconds(unsigned int value)
{
	return value / ST1202_MILLIS_PATTERN_DUR_MIN - 1;
}

static int st1202_pwm_pattern_write(struct st1202_chip *chip, int led_num,
				int pattern, unsigned int value)
{
	u8 value_l, value_h;
	int ret;

	value_l = (u8)value;
	value_h = (u8)(value >> 8);

	/*
	 * Datasheet: Register address low = 1Eh + 2*(xh) + 18h*(yh),
	 * where x is the channel number (led number) in hexadecimal (x = 00h .. 0Bh)
	 * and y is the pattern number in hexadecimal (y = 00h .. 07h)
	 */
	ret = st1202_write_reg(chip, (ST1202_PATTERN_PWM + (led_num * 2) + 0x18 * pattern),
				value_l);
	if (ret != 0)
		return ret;

	/*
	 * Datasheet: Register address high = 1Eh + 01h + 2(xh) +18h*(yh),
	 * where x is the channel number in hexadecimal (x = 00h .. 0Bh)
	 * and y is the pattern number in hexadecimal (y = 00h .. 07h)
	 */
	ret = st1202_write_reg(chip, (ST1202_PATTERN_PWM + 0x1 + (led_num * 2) + 0x18 * pattern),
				value_h);
	if (ret != 0)
		return ret;

	return 0;
}

static int st1202_duration_pattern_write(struct st1202_chip *chip, int pattern,
					unsigned int value)
{
	return st1202_write_reg(chip, (ST1202_PATTERN_DUR + pattern),
				st1202_prescalar_to_miliseconds(value));
}

Annotation

Implementation Notes