drivers/leds/rgb/leds-lp5860-core.c

Source file repositories/reference/linux-study-clean/drivers/leds/rgb/leds-lp5860-core.c

File Facts

System
Linux kernel
Corpus path
drivers/leds/rgb/leds-lp5860-core.c
Extension
.c
Size
5993 bytes
Lines
235
Domain
Driver Families
Bucket
drivers/leds
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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

if (ret) {
			dev_err_probe(led->chip->dev, ret,
				      "%pfwP: Cannot read 'color' property. Skipping.\n", led_node);
			fwnode_handle_put(led_node);
			return ret;
		}

		ret = fwnode_property_read_u32(led_node, "reg", &channel);
		if (ret < 0 || channel > LP5860_MAX_LED) {
			dev_err_probe(led->chip->dev, ret,
				      "%pfwP: 'reg' property is missing. Skipping.\n", led_node);
			fwnode_handle_put(led_node);
			return ret;
		}

		led->mc_cdev.subled_info[subled].color_index = color_index;
		led->mc_cdev.subled_info[subled].channel = channel;
		ret = lp5860_led_init(led, init_data->fwnode, channel);
		if (ret) {
			dev_err_probe(led->chip->dev, ret,
				      "%pfwP: Failed to init LED\n", led_node);
			fwnode_handle_put(led_node);
			return ret;
		}

		subled++;
	}

	return 0;
}

static int lp5860_init_dt(struct lp5860 *lp)
{
	struct led_init_data init_data = {};
	struct led_classdev *led_cdev;
	struct mc_subled *mc_led_info;
	struct lp5860_led *led;
	int led_index = 0;
	int chan;
	int ret;

	device_for_each_child_node_scoped(lp->dev, multi_led) {
		led = &lp->leds[led_index];

		init_data.fwnode = multi_led;

		/* Count the number of channels in this multi_led */
		chan = fwnode_get_child_node_count(multi_led);
		if (!chan || chan > LP5860_MAX_LED_CHANNELS)
			return -EINVAL;

		led->mc_cdev.num_colors = chan;

		mc_led_info = devm_kcalloc(lp->dev, chan, sizeof(*mc_led_info), GFP_KERNEL);
		if (!mc_led_info)
			return -ENOMEM;

		led->chip = lp;
		led->mc_cdev.subled_info = mc_led_info;
		led_cdev = &led->mc_cdev.led_cdev;
		led_cdev->max_brightness = LP5860_MAX_BRIGHTNESS;
		led_cdev->brightness_set_blocking = lp5860_set_mc_brightness;

		ret = lp5860_iterate_subleds(led, &init_data);
		if (ret)
			continue;

		ret = lp5860_set_mc_brightness(&led->mc_cdev.led_cdev, led->brightness);
		if (ret)
			return dev_err_probe(lp->dev, ret, "%pfwP: Failed to set Multi-Color brightness\n",
					     multi_led);

		ret = devm_led_classdev_multicolor_register_ext(lp->dev, &led->mc_cdev, &init_data);
		if (ret)
			return dev_err_probe(lp->dev, ret, "%pfwP: Failed to register Multi-Color LEDs\n",
					     multi_led);
		led_index++;
	}

	return 0;
}

int lp5860_device_init(struct device *dev)
{
	struct lp5860 *lp = dev_get_drvdata(dev);
	int ret;

	ret = lp5860_chip_enable(lp, LP5860_CHIP_ENABLE);
	if (ret)
		return ret;

Annotation

Implementation Notes