#include #include #include #include #include "hui_internal.h" #include "hui_generic.h" struct hui_generic_led_gpio { struct hui_generic_led led; struct gpio_descs *gpios; }; static int gpio_led_out(struct hui_generic_led *_led, struct led_color color) { int j; struct hui_generic_led_gpio *led = container_of(_led, struct hui_generic_led_gpio, led); color = led_color_premultiply(color); for (j = 0; j < led->gpios->ndescs; j++) { u32 c = color.c[j] ? 1: 0; gpiod_set_value(led->gpios->desc[j], c); } return 0; } static int led_probe(struct platform_device *pdev) { int err; struct device *dev = &pdev->dev; struct hui_generic_led_gpio *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 = gpio_led_out; err = of_property_read_string(node, "led-type", &type); if (err == -EINVAL) type = name; else if (err) return err; led->gpios = devm_gpiod_get_array(dev, NULL, GPIOD_OUT_LOW); if (IS_ERR(led->gpios)) return PTR_ERR(led->gpios); if (led->gpios->ndescs > 3) { dev_err(dev, "Ignoring led: more than 3 gpios\n"); return -EINVAL; } 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_gpio_led_match[] = { { .compatible = "avm,hui-generic-led-gpio" }, {}, }; MODULE_DEVICE_TABLE(of, hui_generic_gpio_led_match); struct platform_driver hui_generic_led_gpio = { .probe = led_probe, .driver = { .name = "avm,hui-generic-led-gpio", .of_match_table = hui_generic_gpio_led_match, }, }; struct hui_generic_button_gpio { struct hui_generic_button button; struct gpio_desc *gpio; }; static int gpio_button_in(struct hui_generic_button *_button) { struct hui_generic_button_gpio *button = container_of(_button, struct hui_generic_button_gpio, button); return gpiod_get_value(button->gpio); } static int button_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct device_node *node = dev->of_node; const char *name = node->name; struct hui_generic_button_gpio *button; int err; button = devm_kzalloc(dev, sizeof(*button), GFP_KERNEL); if (!button) return -ENOMEM; button->button.dev = dev; button->button.name = name; button->button.in = gpio_button_in; button->gpio = devm_gpiod_get(dev, NULL, GPIOD_IN); if (IS_ERR(button->gpio)) return PTR_ERR(button->gpio); button->button.handle = avm_hui_add_button(name, name); // TODO add as res to free later if (IS_ERR(button->button.handle)) { return PTR_ERR(button->button.handle); } err = hui_generic_blink_add_button(&button->button); if (err) return err; return 0; } static const struct of_device_id hui_generic_gpio_button_match[] = { { .compatible = "avm,hui-generic-button-gpio" }, {}, }; MODULE_DEVICE_TABLE(of, hui_generic_gpio_button_match); struct platform_driver hui_generic_button_gpio = { .probe = button_probe, .driver = { .name = "avm,hui-generic-button-gpio", .of_match_table = hui_generic_gpio_button_match, }, };