Skip to content

Commit a3a0641

Browse files
Kate HsuanJiri Kosina
authored andcommitted
HID: hid-lg-g15: Use standard multicolor LED API
Replace the custom "color" sysfs attribute with the standard multicolor LED API. This also removes the code for the custom "color" sysfs attribute, the "color" sysfs attribute was never documented so hopefully, it is not used by anyone. If we get complaints, we can re-add the "color" sysfs attribute as a compatibility wrapper setting the subleds intensity. Signed-off-by: Kate Hsuan <hpa@redhat.com> Reviewed-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Jiri Kosina <jkosina@suse.com>
1 parent 27c0278 commit a3a0641

File tree

1 file changed

+65
-81
lines changed

1 file changed

+65
-81
lines changed

drivers/hid/hid-lg-g15.c

Lines changed: 65 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,13 @@
88
#include <linux/device.h>
99
#include <linux/hid.h>
1010
#include <linux/leds.h>
11+
#include <linux/led-class-multicolor.h>
1112
#include <linux/module.h>
1213
#include <linux/random.h>
1314
#include <linux/sched.h>
1415
#include <linux/usb.h>
1516
#include <linux/wait.h>
17+
#include <dt-bindings/leds/common.h>
1618

1719
#include "hid-ids.h"
1820

@@ -44,9 +46,13 @@ enum lg_g15_led_type {
4446
};
4547

4648
struct lg_g15_led {
47-
struct led_classdev cdev;
49+
union {
50+
struct led_classdev cdev;
51+
struct led_classdev_mc mcdev;
52+
};
4853
enum led_brightness brightness;
4954
enum lg_g15_led_type led;
55+
/* Used to store initial color intensities before subled_info is allocated */
5056
u8 red, green, blue;
5157
};
5258

@@ -229,15 +235,15 @@ static int lg_g510_kbd_led_write(struct lg_g15_data *g15,
229235
struct lg_g15_led *g15_led,
230236
enum led_brightness brightness)
231237
{
238+
struct mc_subled *subleds = g15_led->mcdev.subled_info;
232239
int ret;
233240

241+
led_mc_calc_color_components(&g15_led->mcdev, brightness);
242+
234243
g15->transfer_buf[0] = 5 + g15_led->led;
235-
g15->transfer_buf[1] =
236-
DIV_ROUND_CLOSEST(g15_led->red * brightness, 255);
237-
g15->transfer_buf[2] =
238-
DIV_ROUND_CLOSEST(g15_led->green * brightness, 255);
239-
g15->transfer_buf[3] =
240-
DIV_ROUND_CLOSEST(g15_led->blue * brightness, 255);
244+
g15->transfer_buf[1] = subleds[0].brightness;
245+
g15->transfer_buf[2] = subleds[1].brightness;
246+
g15->transfer_buf[3] = subleds[2].brightness;
241247

242248
ret = hid_hw_raw_request(g15->hdev,
243249
LG_G510_FEATURE_BACKLIGHT_RGB + g15_led->led,
@@ -258,8 +264,9 @@ static int lg_g510_kbd_led_write(struct lg_g15_data *g15,
258264
static int lg_g510_kbd_led_set(struct led_classdev *led_cdev,
259265
enum led_brightness brightness)
260266
{
267+
struct led_classdev_mc *mc = lcdev_to_mccdev(led_cdev);
261268
struct lg_g15_led *g15_led =
262-
container_of(led_cdev, struct lg_g15_led, cdev);
269+
container_of(mc, struct lg_g15_led, mcdev);
263270
struct lg_g15_data *g15 = dev_get_drvdata(led_cdev->dev->parent);
264271
int ret;
265272

@@ -276,82 +283,20 @@ static int lg_g510_kbd_led_set(struct led_classdev *led_cdev,
276283

277284
static enum led_brightness lg_g510_kbd_led_get(struct led_classdev *led_cdev)
278285
{
286+
struct led_classdev_mc *mc = lcdev_to_mccdev(led_cdev);
279287
struct lg_g15_led *g15_led =
280-
container_of(led_cdev, struct lg_g15_led, cdev);
288+
container_of(mc, struct lg_g15_led, mcdev);
281289

282290
return g15_led->brightness;
283291
}
284292

285-
static ssize_t color_store(struct device *dev, struct device_attribute *attr,
286-
const char *buf, size_t count)
287-
{
288-
struct led_classdev *led_cdev = dev_get_drvdata(dev);
289-
struct lg_g15_led *g15_led =
290-
container_of(led_cdev, struct lg_g15_led, cdev);
291-
struct lg_g15_data *g15 = dev_get_drvdata(led_cdev->dev->parent);
292-
unsigned long value;
293-
int ret;
294-
295-
if (count < 7 || (count == 8 && buf[7] != '\n') || count > 8)
296-
return -EINVAL;
297-
298-
if (buf[0] != '#')
299-
return -EINVAL;
300-
301-
ret = kstrtoul(buf + 1, 16, &value);
302-
if (ret)
303-
return ret;
304-
305-
mutex_lock(&g15->mutex);
306-
g15_led->red = (value & 0xff0000) >> 16;
307-
g15_led->green = (value & 0x00ff00) >> 8;
308-
g15_led->blue = (value & 0x0000ff);
309-
ret = lg_g510_kbd_led_write(g15, g15_led, g15_led->brightness);
310-
mutex_unlock(&g15->mutex);
311-
312-
return (ret < 0) ? ret : count;
313-
}
314-
315-
static ssize_t color_show(struct device *dev, struct device_attribute *attr,
316-
char *buf)
317-
{
318-
struct led_classdev *led_cdev = dev_get_drvdata(dev);
319-
struct lg_g15_led *g15_led =
320-
container_of(led_cdev, struct lg_g15_led, cdev);
321-
struct lg_g15_data *g15 = dev_get_drvdata(led_cdev->dev->parent);
322-
ssize_t ret;
323-
324-
mutex_lock(&g15->mutex);
325-
ret = sprintf(buf, "#%02x%02x%02x\n",
326-
g15_led->red, g15_led->green, g15_led->blue);
327-
mutex_unlock(&g15->mutex);
328-
329-
return ret;
330-
}
331-
332-
static DEVICE_ATTR_RW(color);
333-
334-
static struct attribute *lg_g510_kbd_led_attrs[] = {
335-
&dev_attr_color.attr,
336-
NULL,
337-
};
338-
339-
static const struct attribute_group lg_g510_kbd_led_group = {
340-
.attrs = lg_g510_kbd_led_attrs,
341-
};
342-
343-
static const struct attribute_group *lg_g510_kbd_led_groups[] = {
344-
&lg_g510_kbd_led_group,
345-
NULL,
346-
};
347-
348293
static void lg_g510_leds_sync_work(struct work_struct *work)
349294
{
350295
struct lg_g15_data *g15 = container_of(work, struct lg_g15_data, work);
296+
struct lg_g15_led *g15_led = &g15->leds[LG_G15_KBD_BRIGHTNESS];
351297

352298
mutex_lock(&g15->mutex);
353-
lg_g510_kbd_led_write(g15, &g15->leds[LG_G15_KBD_BRIGHTNESS],
354-
g15->leds[LG_G15_KBD_BRIGHTNESS].brightness);
299+
lg_g510_kbd_led_write(g15, g15_led, g15_led->brightness);
355300
mutex_unlock(&g15->mutex);
356301
}
357302

@@ -667,8 +612,46 @@ static void lg_g15_input_close(struct input_dev *dev)
667612
hid_hw_close(hdev);
668613
}
669614

615+
static void lg_g15_setup_led_rgb(struct lg_g15_data *g15, int index)
616+
{
617+
int i;
618+
struct mc_subled *subled_info;
619+
620+
g15->leds[index].mcdev.led_cdev.brightness_set_blocking =
621+
lg_g510_kbd_led_set;
622+
g15->leds[index].mcdev.led_cdev.brightness_get =
623+
lg_g510_kbd_led_get;
624+
g15->leds[index].mcdev.led_cdev.max_brightness = 255;
625+
g15->leds[index].mcdev.num_colors = 3;
626+
627+
subled_info = devm_kcalloc(&g15->hdev->dev, 3, sizeof(*subled_info), GFP_KERNEL);
628+
if (!subled_info)
629+
return;
630+
631+
for (i = 0; i < 3; i++) {
632+
switch (i + 1) {
633+
case LED_COLOR_ID_RED:
634+
subled_info[i].color_index = LED_COLOR_ID_RED;
635+
subled_info[i].intensity = g15->leds[index].red;
636+
break;
637+
case LED_COLOR_ID_GREEN:
638+
subled_info[i].color_index = LED_COLOR_ID_GREEN;
639+
subled_info[i].intensity = g15->leds[index].green;
640+
break;
641+
case LED_COLOR_ID_BLUE:
642+
subled_info[i].color_index = LED_COLOR_ID_BLUE;
643+
subled_info[i].intensity = g15->leds[index].blue;
644+
break;
645+
}
646+
subled_info[i].channel = i;
647+
}
648+
g15->leds[index].mcdev.subled_info = subled_info;
649+
}
650+
670651
static int lg_g15_register_led(struct lg_g15_data *g15, int i, const char *name)
671652
{
653+
int ret;
654+
672655
g15->leds[i].led = i;
673656
g15->leds[i].cdev.name = name;
674657

@@ -685,6 +668,7 @@ static int lg_g15_register_led(struct lg_g15_data *g15, int i, const char *name)
685668
} else {
686669
g15->leds[i].cdev.max_brightness = 1;
687670
}
671+
ret = devm_led_classdev_register(&g15->hdev->dev, &g15->leds[i].cdev);
688672
break;
689673
case LG_G510:
690674
case LG_G510_USB_AUDIO:
@@ -697,24 +681,24 @@ static int lg_g15_register_led(struct lg_g15_data *g15, int i, const char *name)
697681
g15->leds[i].cdev.name = "g15::power_on_backlight_val";
698682
fallthrough;
699683
case LG_G15_KBD_BRIGHTNESS:
700-
g15->leds[i].cdev.brightness_set_blocking =
701-
lg_g510_kbd_led_set;
702-
g15->leds[i].cdev.brightness_get =
703-
lg_g510_kbd_led_get;
704-
g15->leds[i].cdev.max_brightness = 255;
705-
g15->leds[i].cdev.groups = lg_g510_kbd_led_groups;
684+
/* register multicolor LED */
685+
lg_g15_setup_led_rgb(g15, i);
686+
ret = devm_led_classdev_multicolor_register_ext(&g15->hdev->dev,
687+
&g15->leds[i].mcdev,
688+
NULL);
706689
break;
707690
default:
708691
g15->leds[i].cdev.brightness_set_blocking =
709692
lg_g510_mkey_led_set;
710693
g15->leds[i].cdev.brightness_get =
711694
lg_g510_mkey_led_get;
712695
g15->leds[i].cdev.max_brightness = 1;
696+
ret = devm_led_classdev_register(&g15->hdev->dev, &g15->leds[i].cdev);
713697
}
714698
break;
715699
}
716700

717-
return devm_led_classdev_register(&g15->hdev->dev, &g15->leds[i].cdev);
701+
return ret;
718702
}
719703

720704
/* Common input device init code shared between keyboards and Z-10 speaker handling */

0 commit comments

Comments
 (0)