1 // SPDX-License-Identifier: GPL-2.0
2 // LED Multicolor class interface
3 // Copyright (C) 2019-20 Texas Instruments Incorporated - http://www.ti.com/
6 #include <linux/device.h>
7 #include <linux/init.h>
8 #include <linux/led-class-multicolor.h>
9 #include <linux/module.h>
10 #include <linux/slab.h>
11 #include <linux/uaccess.h>
15 int led_mc_calc_color_components(struct led_classdev_mc *mcled_cdev,
16 enum led_brightness brightness)
18 struct led_classdev *led_cdev = &mcled_cdev->led_cdev;
21 for (i = 0; i < mcled_cdev->num_colors; i++)
22 mcled_cdev->subled_info[i].brightness = brightness *
23 mcled_cdev->subled_info[i].intensity /
24 led_cdev->max_brightness;
28 EXPORT_SYMBOL_GPL(led_mc_calc_color_components);
30 static ssize_t multi_intensity_store(struct device *dev,
31 struct device_attribute *intensity_attr,
32 const char *buf, size_t size)
34 struct led_classdev *led_cdev = dev_get_drvdata(dev);
35 struct led_classdev_mc *mcled_cdev = lcdev_to_mccdev(led_cdev);
36 int nrchars, offset = 0;
37 int intensity_value[LED_COLOR_ID_MAX];
41 mutex_lock(&led_cdev->led_access);
43 for (i = 0; i < mcled_cdev->num_colors; i++) {
44 ret = sscanf(buf + offset, "%i%n",
45 &intensity_value[i], &nrchars);
59 for (i = 0; i < mcled_cdev->num_colors; i++)
60 mcled_cdev->subled_info[i].intensity = intensity_value[i];
62 led_set_brightness(led_cdev, led_cdev->brightness);
65 mutex_unlock(&led_cdev->led_access);
69 static ssize_t multi_intensity_show(struct device *dev,
70 struct device_attribute *intensity_attr,
73 struct led_classdev *led_cdev = dev_get_drvdata(dev);
74 struct led_classdev_mc *mcled_cdev = lcdev_to_mccdev(led_cdev);
78 for (i = 0; i < mcled_cdev->num_colors; i++) {
79 len += sprintf(buf + len, "%d",
80 mcled_cdev->subled_info[i].intensity);
81 if (i < mcled_cdev->num_colors - 1)
82 len += sprintf(buf + len, " ");
88 static DEVICE_ATTR_RW(multi_intensity);
90 static ssize_t multi_index_show(struct device *dev,
91 struct device_attribute *multi_index_attr,
94 struct led_classdev *led_cdev = dev_get_drvdata(dev);
95 struct led_classdev_mc *mcled_cdev = lcdev_to_mccdev(led_cdev);
100 for (i = 0; i < mcled_cdev->num_colors; i++) {
101 index = mcled_cdev->subled_info[i].color_index;
102 len += sprintf(buf + len, "%s", led_colors[index]);
103 if (i < mcled_cdev->num_colors - 1)
104 len += sprintf(buf + len, " ");
110 static DEVICE_ATTR_RO(multi_index);
112 static struct attribute *led_multicolor_attrs[] = {
113 &dev_attr_multi_intensity.attr,
114 &dev_attr_multi_index.attr,
117 ATTRIBUTE_GROUPS(led_multicolor);
119 int led_classdev_multicolor_register_ext(struct device *parent,
120 struct led_classdev_mc *mcled_cdev,
121 struct led_init_data *init_data)
123 struct led_classdev *led_cdev;
128 if (mcled_cdev->num_colors <= 0)
131 if (mcled_cdev->num_colors > LED_COLOR_ID_MAX)
134 led_cdev = &mcled_cdev->led_cdev;
135 mcled_cdev->led_cdev.groups = led_multicolor_groups;
137 return led_classdev_register_ext(parent, led_cdev, init_data);
139 EXPORT_SYMBOL_GPL(led_classdev_multicolor_register_ext);
141 void led_classdev_multicolor_unregister(struct led_classdev_mc *mcled_cdev)
146 led_classdev_unregister(&mcled_cdev->led_cdev);
148 EXPORT_SYMBOL_GPL(led_classdev_multicolor_unregister);
150 static void devm_led_classdev_multicolor_release(struct device *dev, void *res)
152 led_classdev_multicolor_unregister(*(struct led_classdev_mc **)res);
155 int devm_led_classdev_multicolor_register_ext(struct device *parent,
156 struct led_classdev_mc *mcled_cdev,
157 struct led_init_data *init_data)
159 struct led_classdev_mc **dr;
162 dr = devres_alloc(devm_led_classdev_multicolor_release,
163 sizeof(*dr), GFP_KERNEL);
167 ret = led_classdev_multicolor_register_ext(parent, mcled_cdev,
175 devres_add(parent, dr);
179 EXPORT_SYMBOL_GPL(devm_led_classdev_multicolor_register_ext);
181 static int devm_led_classdev_multicolor_match(struct device *dev,
182 void *res, void *data)
184 struct led_classdev_mc **p = res;
186 if (WARN_ON(!p || !*p))
192 void devm_led_classdev_multicolor_unregister(struct device *dev,
193 struct led_classdev_mc *mcled_cdev)
195 WARN_ON(devres_release(dev,
196 devm_led_classdev_multicolor_release,
197 devm_led_classdev_multicolor_match, mcled_cdev));
199 EXPORT_SYMBOL_GPL(devm_led_classdev_multicolor_unregister);
202 MODULE_DESCRIPTION("Multicolor LED class interface");
203 MODULE_LICENSE("GPL v2");