Merge tag 'pm-5.11-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
[linux-2.6-microblaze.git] / drivers / hid / hid-gt683r.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * MSI GT683R led driver
4  *
5  * Copyright (c) 2014 Janne Kanniainen <janne.kanniainen@gmail.com>
6  */
7
8 #include <linux/device.h>
9 #include <linux/hid.h>
10 #include <linux/kernel.h>
11 #include <linux/leds.h>
12 #include <linux/module.h>
13
14 #include "hid-ids.h"
15
16 #define GT683R_BUFFER_SIZE                      8
17
18 /*
19  * GT683R_LED_OFF: all LEDs are off
20  * GT683R_LED_AUDIO: LEDs brightness depends on sound level
21  * GT683R_LED_BREATHING: LEDs brightness varies at human breathing rate
22  * GT683R_LED_NORMAL: LEDs are fully on when enabled
23  */
24 enum gt683r_led_mode {
25         GT683R_LED_OFF = 0,
26         GT683R_LED_AUDIO = 2,
27         GT683R_LED_BREATHING = 3,
28         GT683R_LED_NORMAL = 5
29 };
30
31 enum gt683r_panels {
32         GT683R_LED_BACK = 0,
33         GT683R_LED_SIDE = 1,
34         GT683R_LED_FRONT = 2,
35         GT683R_LED_COUNT,
36 };
37
38 static const char * const gt683r_panel_names[] = {
39         "back",
40         "side",
41         "front",
42 };
43
44 struct gt683r_led {
45         struct hid_device *hdev;
46         struct led_classdev led_devs[GT683R_LED_COUNT];
47         struct mutex lock;
48         struct work_struct work;
49         enum led_brightness brightnesses[GT683R_LED_COUNT];
50         enum gt683r_led_mode mode;
51 };
52
53 static const struct hid_device_id gt683r_led_id[] = {
54         { HID_USB_DEVICE(USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GT683R_LED_PANEL) },
55         { }
56 };
57
58 static void gt683r_brightness_set(struct led_classdev *led_cdev,
59                                 enum led_brightness brightness)
60 {
61         int i;
62         struct device *dev = led_cdev->dev->parent;
63         struct hid_device *hdev = to_hid_device(dev);
64         struct gt683r_led *led = hid_get_drvdata(hdev);
65
66         for (i = 0; i < GT683R_LED_COUNT; i++) {
67                 if (led_cdev == &led->led_devs[i])
68                         break;
69         }
70
71         if (i < GT683R_LED_COUNT) {
72                 led->brightnesses[i] = brightness;
73                 schedule_work(&led->work);
74         }
75 }
76
77 static ssize_t mode_show(struct device *dev,
78                                 struct device_attribute *attr,
79                                 char *buf)
80 {
81         u8 sysfs_mode;
82         struct hid_device *hdev = to_hid_device(dev->parent);
83         struct gt683r_led *led = hid_get_drvdata(hdev);
84
85         if (led->mode == GT683R_LED_NORMAL)
86                 sysfs_mode = 0;
87         else if (led->mode == GT683R_LED_AUDIO)
88                 sysfs_mode = 1;
89         else
90                 sysfs_mode = 2;
91
92         return scnprintf(buf, PAGE_SIZE, "%u\n", sysfs_mode);
93 }
94
95 static ssize_t mode_store(struct device *dev,
96                                 struct device_attribute *attr,
97                                 const char *buf, size_t count)
98 {
99         u8 sysfs_mode;
100         struct hid_device *hdev = to_hid_device(dev->parent);
101         struct gt683r_led *led = hid_get_drvdata(hdev);
102
103
104         if (kstrtou8(buf, 10, &sysfs_mode) || sysfs_mode > 2)
105                 return -EINVAL;
106
107         mutex_lock(&led->lock);
108
109         if (sysfs_mode == 0)
110                 led->mode = GT683R_LED_NORMAL;
111         else if (sysfs_mode == 1)
112                 led->mode = GT683R_LED_AUDIO;
113         else
114                 led->mode = GT683R_LED_BREATHING;
115
116         mutex_unlock(&led->lock);
117         schedule_work(&led->work);
118
119         return count;
120 }
121
122 static int gt683r_led_snd_msg(struct gt683r_led *led, u8 *msg)
123 {
124         int ret;
125
126         ret = hid_hw_raw_request(led->hdev, msg[0], msg, GT683R_BUFFER_SIZE,
127                                 HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
128         if (ret != GT683R_BUFFER_SIZE) {
129                 hid_err(led->hdev,
130                         "failed to send set report request: %i\n", ret);
131                 if (ret < 0)
132                         return ret;
133                 return -EIO;
134         }
135
136         return 0;
137 }
138
139 static int gt683r_leds_set(struct gt683r_led *led, u8 leds)
140 {
141         int ret;
142         u8 *buffer;
143
144         buffer = kzalloc(GT683R_BUFFER_SIZE, GFP_KERNEL);
145         if (!buffer)
146                 return -ENOMEM;
147
148         buffer[0] = 0x01;
149         buffer[1] = 0x02;
150         buffer[2] = 0x30;
151         buffer[3] = leds;
152         ret = gt683r_led_snd_msg(led, buffer);
153
154         kfree(buffer);
155         return ret;
156 }
157
158 static int gt683r_mode_set(struct gt683r_led *led, u8 mode)
159 {
160         int ret;
161         u8 *buffer;
162
163         buffer = kzalloc(GT683R_BUFFER_SIZE, GFP_KERNEL);
164         if (!buffer)
165                 return -ENOMEM;
166
167         buffer[0] = 0x01;
168         buffer[1] = 0x02;
169         buffer[2] = 0x20;
170         buffer[3] = mode;
171         buffer[4] = 0x01;
172         ret = gt683r_led_snd_msg(led, buffer);
173
174         kfree(buffer);
175         return ret;
176 }
177
178 static void gt683r_led_work(struct work_struct *work)
179 {
180         int i;
181         u8 leds = 0;
182         u8 mode;
183         struct gt683r_led *led = container_of(work, struct gt683r_led, work);
184
185         mutex_lock(&led->lock);
186
187         for (i = 0; i < GT683R_LED_COUNT; i++) {
188                 if (led->brightnesses[i])
189                         leds |= BIT(i);
190         }
191
192         if (gt683r_leds_set(led, leds))
193                 goto fail;
194
195         if (leds)
196                 mode = led->mode;
197         else
198                 mode = GT683R_LED_OFF;
199
200         gt683r_mode_set(led, mode);
201 fail:
202         mutex_unlock(&led->lock);
203 }
204
205 static DEVICE_ATTR_RW(mode);
206
207 static struct attribute *gt683r_led_attrs[] = {
208         &dev_attr_mode.attr,
209         NULL
210 };
211
212 static const struct attribute_group gt683r_led_group = {
213         .name = "gt683r",
214         .attrs = gt683r_led_attrs,
215 };
216
217 static const struct attribute_group *gt683r_led_groups[] = {
218         &gt683r_led_group,
219         NULL
220 };
221
222 static int gt683r_led_probe(struct hid_device *hdev,
223                         const struct hid_device_id *id)
224 {
225         int i;
226         int ret;
227         int name_sz;
228         char *name;
229         struct gt683r_led *led;
230
231         led = devm_kzalloc(&hdev->dev, sizeof(*led), GFP_KERNEL);
232         if (!led)
233                 return -ENOMEM;
234
235         mutex_init(&led->lock);
236         INIT_WORK(&led->work, gt683r_led_work);
237
238         led->mode = GT683R_LED_NORMAL;
239         led->hdev = hdev;
240         hid_set_drvdata(hdev, led);
241
242         ret = hid_parse(hdev);
243         if (ret) {
244                 hid_err(hdev, "hid parsing failed\n");
245                 return ret;
246         }
247
248         ret = hid_hw_start(hdev, HID_CONNECT_HIDRAW);
249         if (ret) {
250                 hid_err(hdev, "hw start failed\n");
251                 return ret;
252         }
253
254         for (i = 0; i < GT683R_LED_COUNT; i++) {
255                 name_sz = strlen(dev_name(&hdev->dev)) +
256                                 strlen(gt683r_panel_names[i]) + 3;
257
258                 name = devm_kzalloc(&hdev->dev, name_sz, GFP_KERNEL);
259                 if (!name) {
260                         ret = -ENOMEM;
261                         goto fail;
262                 }
263
264                 snprintf(name, name_sz, "%s::%s",
265                                 dev_name(&hdev->dev), gt683r_panel_names[i]);
266                 led->led_devs[i].name = name;
267                 led->led_devs[i].max_brightness = 1;
268                 led->led_devs[i].brightness_set = gt683r_brightness_set;
269                 led->led_devs[i].groups = gt683r_led_groups;
270
271                 ret = led_classdev_register(&hdev->dev, &led->led_devs[i]);
272                 if (ret) {
273                         hid_err(hdev, "could not register led device\n");
274                         goto fail;
275                 }
276         }
277
278         return 0;
279
280 fail:
281         for (i = i - 1; i >= 0; i--)
282                 led_classdev_unregister(&led->led_devs[i]);
283         hid_hw_stop(hdev);
284         return ret;
285 }
286
287 static void gt683r_led_remove(struct hid_device *hdev)
288 {
289         int i;
290         struct gt683r_led *led = hid_get_drvdata(hdev);
291
292         for (i = 0; i < GT683R_LED_COUNT; i++)
293                 led_classdev_unregister(&led->led_devs[i]);
294         flush_work(&led->work);
295         hid_hw_stop(hdev);
296 }
297
298 static struct hid_driver gt683r_led_driver = {
299         .probe = gt683r_led_probe,
300         .remove = gt683r_led_remove,
301         .name = "gt683r_led",
302         .id_table = gt683r_led_id,
303 };
304
305 module_hid_driver(gt683r_led_driver);
306
307 MODULE_AUTHOR("Janne Kanniainen");
308 MODULE_DESCRIPTION("MSI GT683R led driver");
309 MODULE_LICENSE("GPL");