#include #include #include #include "hui_internal.h" #include "hui_generic.h" #define MAX_LEDS 3 struct hui_generic_led_class { struct hui_generic_led led; struct led_classdev *leds[MAX_LEDS]; }; static int led_out(struct hui_generic_led *_led, struct led_color color) { int j; struct hui_generic_led_class *led = container_of(_led, struct hui_generic_led_class, led); color = led_color_premultiply(color); for (j = 0; j < MAX_LEDS; j++) { if (!led->leds[j]) continue; led_set_brightness(led->leds[j], color.c[j]); } return 0; } static int led_probe(struct platform_device *pdev) { int err, i; struct device *dev = &pdev->dev; struct hui_generic_led_class *led; struct device_node *node = dev->of_node; const char *name = node->name; const char *type; led = devm_kzalloc(dev, sizeof(*led), GFP_KERNEL); if (!led) return -ENOMEM; led->led.dev = dev; led->led.name = name; led->led.code = BLINK_CODE(.type = blink_off); led->led.out = led_out; err = of_property_read_string(node, "led-type", &type); if (err == -EINVAL) type = name; else if (err) return err; for (i = 0; i < MAX_LEDS; i++) { struct led_classdev *led_class; led_class = devm_of_led_get(dev, i); if (IS_ERR(led_class)) { if (PTR_ERR(led_class) != -ENOENT) return PTR_ERR(led_class); continue; } led->leds[i] = led_class; led_trigger_remove(led_class); led_sysfs_disable(led_class); } if (!led->leds[0]) { dev_err(dev, "No valid leds specified\n"); return -ENODEV; } led->led.handle = avm_hui_add_led(name, type, node, &hui_generic_ops, &led->led); // TODO add as res to free later if (IS_ERR(led->led.handle)) { return PTR_ERR(led->led.handle); } err = hui_generic_blink_add_led(&led->led); if (err) return err; return 0; } static const struct of_device_id hui_generic_led_class_match[] = { { .compatible = "avm,hui-generic-led-class" }, {}, }; MODULE_DEVICE_TABLE(of, hui_generic_led_class_match); struct platform_driver hui_generic_led_class = { .probe = led_probe, .driver = { .name = "avm,hui-generic-led-class", .of_match_table = hui_generic_led_class_match, }, };