Lines Matching +full:kbd +full:- +full:led +full:- +full:backlight
1 // SPDX-License-Identifier: GPL-2.0+
17 #include "hid-ids.h"
49 enum lg_g15_led_type led; member
56 /* Protects the transfer_buf and led brightness */
66 /******** G15 and G15 v2 LED functions ********/
72 ret = hid_hw_raw_request(g15->hdev, LG_G15_FEATURE_REPORT, in lg_g15_update_led_brightness()
73 g15->transfer_buf, 4, in lg_g15_update_led_brightness()
76 hid_err(g15->hdev, "Error getting LED brightness: %d\n", ret); in lg_g15_update_led_brightness()
77 return (ret < 0) ? ret : -EIO; in lg_g15_update_led_brightness()
80 g15->leds[LG_G15_KBD_BRIGHTNESS].brightness = g15->transfer_buf[1]; in lg_g15_update_led_brightness()
81 g15->leds[LG_G15_LCD_BRIGHTNESS].brightness = g15->transfer_buf[2]; in lg_g15_update_led_brightness()
83 g15->leds[LG_G15_MACRO_PRESET1].brightness = in lg_g15_update_led_brightness()
84 !(g15->transfer_buf[3] & 0x01); in lg_g15_update_led_brightness()
85 g15->leds[LG_G15_MACRO_PRESET2].brightness = in lg_g15_update_led_brightness()
86 !(g15->transfer_buf[3] & 0x02); in lg_g15_update_led_brightness()
87 g15->leds[LG_G15_MACRO_PRESET3].brightness = in lg_g15_update_led_brightness()
88 !(g15->transfer_buf[3] & 0x04); in lg_g15_update_led_brightness()
89 g15->leds[LG_G15_MACRO_RECORD].brightness = in lg_g15_update_led_brightness()
90 !(g15->transfer_buf[3] & 0x08); in lg_g15_update_led_brightness()
99 struct lg_g15_data *g15 = dev_get_drvdata(led_cdev->dev->parent); in lg_g15_led_get()
102 mutex_lock(&g15->mutex); in lg_g15_led_get()
104 brightness = g15->leds[g15_led->led].brightness; in lg_g15_led_get()
105 mutex_unlock(&g15->mutex); in lg_g15_led_get()
115 struct lg_g15_data *g15 = dev_get_drvdata(led_cdev->dev->parent); in lg_g15_led_set()
119 /* Ignore LED off on unregister / keyboard unplug */ in lg_g15_led_set()
120 if (led_cdev->flags & LED_UNREGISTERING) in lg_g15_led_set()
123 mutex_lock(&g15->mutex); in lg_g15_led_set()
125 g15->transfer_buf[0] = LG_G15_FEATURE_REPORT; in lg_g15_led_set()
126 g15->transfer_buf[3] = 0; in lg_g15_led_set()
128 if (g15_led->led < LG_G15_BRIGHTNESS_MAX) { in lg_g15_led_set()
129 g15->transfer_buf[1] = g15_led->led + 1; in lg_g15_led_set()
130 g15->transfer_buf[2] = brightness << (g15_led->led * 4); in lg_g15_led_set()
133 if (i == g15_led->led) in lg_g15_led_set()
136 val = g15->leds[i].brightness; in lg_g15_led_set()
139 mask |= 1 << (i - LG_G15_MACRO_PRESET1); in lg_g15_led_set()
142 g15->transfer_buf[1] = 0x04; in lg_g15_led_set()
143 g15->transfer_buf[2] = ~mask; in lg_g15_led_set()
146 ret = hid_hw_raw_request(g15->hdev, LG_G15_FEATURE_REPORT, in lg_g15_led_set()
147 g15->transfer_buf, 4, in lg_g15_led_set()
151 g15_led->brightness = brightness; in lg_g15_led_set()
154 hid_err(g15->hdev, "Error setting LED brightness: %d\n", ret); in lg_g15_led_set()
155 ret = (ret < 0) ? ret : -EIO; in lg_g15_led_set()
158 mutex_unlock(&g15->mutex); in lg_g15_led_set()
170 mutex_lock(&g15->mutex); in lg_g15_leds_changed_work()
172 old_brightness[i] = g15->leds[i].brightness; in lg_g15_leds_changed_work()
177 brightness[i] = g15->leds[i].brightness; in lg_g15_leds_changed_work()
178 mutex_unlock(&g15->mutex); in lg_g15_leds_changed_work()
187 led_classdev_notify_brightness_hw_changed(&g15->leds[i].cdev, in lg_g15_leds_changed_work()
192 /******** G510 LED functions ********/
198 ret = hid_hw_raw_request(g15->hdev, LG_G510_FEATURE_BACKLIGHT_RGB + i, in lg_g510_get_initial_led_brightness()
199 g15->transfer_buf, 4, in lg_g510_get_initial_led_brightness()
202 hid_err(g15->hdev, "Error getting LED brightness: %d\n", ret); in lg_g510_get_initial_led_brightness()
203 return (ret < 0) ? ret : -EIO; in lg_g510_get_initial_led_brightness()
206 high = max3(g15->transfer_buf[1], g15->transfer_buf[2], in lg_g510_get_initial_led_brightness()
207 g15->transfer_buf[3]); in lg_g510_get_initial_led_brightness()
210 g15->leds[i].red = in lg_g510_get_initial_led_brightness()
211 DIV_ROUND_CLOSEST(g15->transfer_buf[1] * 255, high); in lg_g510_get_initial_led_brightness()
212 g15->leds[i].green = in lg_g510_get_initial_led_brightness()
213 DIV_ROUND_CLOSEST(g15->transfer_buf[2] * 255, high); in lg_g510_get_initial_led_brightness()
214 g15->leds[i].blue = in lg_g510_get_initial_led_brightness()
215 DIV_ROUND_CLOSEST(g15->transfer_buf[3] * 255, high); in lg_g510_get_initial_led_brightness()
216 g15->leds[i].brightness = high; in lg_g510_get_initial_led_brightness()
218 g15->leds[i].red = 255; in lg_g510_get_initial_led_brightness()
219 g15->leds[i].green = 255; in lg_g510_get_initial_led_brightness()
220 g15->leds[i].blue = 255; in lg_g510_get_initial_led_brightness()
221 g15->leds[i].brightness = 0; in lg_g510_get_initial_led_brightness()
227 /* Must be called with g15->mutex locked */
234 g15->transfer_buf[0] = 5 + g15_led->led; in lg_g510_kbd_led_write()
235 g15->transfer_buf[1] = in lg_g510_kbd_led_write()
236 DIV_ROUND_CLOSEST(g15_led->red * brightness, 255); in lg_g510_kbd_led_write()
237 g15->transfer_buf[2] = in lg_g510_kbd_led_write()
238 DIV_ROUND_CLOSEST(g15_led->green * brightness, 255); in lg_g510_kbd_led_write()
239 g15->transfer_buf[3] = in lg_g510_kbd_led_write()
240 DIV_ROUND_CLOSEST(g15_led->blue * brightness, 255); in lg_g510_kbd_led_write()
242 ret = hid_hw_raw_request(g15->hdev, in lg_g510_kbd_led_write()
243 LG_G510_FEATURE_BACKLIGHT_RGB + g15_led->led, in lg_g510_kbd_led_write()
244 g15->transfer_buf, 4, in lg_g510_kbd_led_write()
248 g15_led->brightness = brightness; in lg_g510_kbd_led_write()
251 hid_err(g15->hdev, "Error setting LED brightness: %d\n", ret); in lg_g510_kbd_led_write()
252 ret = (ret < 0) ? ret : -EIO; in lg_g510_kbd_led_write()
263 struct lg_g15_data *g15 = dev_get_drvdata(led_cdev->dev->parent); in lg_g510_kbd_led_set()
266 /* Ignore LED off on unregister / keyboard unplug */ in lg_g510_kbd_led_set()
267 if (led_cdev->flags & LED_UNREGISTERING) in lg_g510_kbd_led_set()
270 mutex_lock(&g15->mutex); in lg_g510_kbd_led_set()
272 mutex_unlock(&g15->mutex); in lg_g510_kbd_led_set()
282 return g15_led->brightness; in lg_g510_kbd_led_get()
291 struct lg_g15_data *g15 = dev_get_drvdata(led_cdev->dev->parent); in color_store()
296 return -EINVAL; in color_store()
299 return -EINVAL; in color_store()
305 mutex_lock(&g15->mutex); in color_store()
306 g15_led->red = (value & 0xff0000) >> 16; in color_store()
307 g15_led->green = (value & 0x00ff00) >> 8; in color_store()
308 g15_led->blue = (value & 0x0000ff); in color_store()
309 ret = lg_g510_kbd_led_write(g15, g15_led, g15_led->brightness); in color_store()
310 mutex_unlock(&g15->mutex); in color_store()
321 struct lg_g15_data *g15 = dev_get_drvdata(led_cdev->dev->parent); in color_show()
324 mutex_lock(&g15->mutex); in color_show()
326 g15_led->red, g15_led->green, g15_led->blue); in color_show()
327 mutex_unlock(&g15->mutex); in color_show()
352 mutex_lock(&g15->mutex); in lg_g510_leds_sync_work()
353 lg_g510_kbd_led_write(g15, &g15->leds[LG_G15_KBD_BRIGHTNESS], in lg_g510_leds_sync_work()
354 g15->leds[LG_G15_KBD_BRIGHTNESS].brightness); in lg_g510_leds_sync_work()
355 mutex_unlock(&g15->mutex); in lg_g510_leds_sync_work()
362 ret = hid_hw_raw_request(g15->hdev, LG_G510_FEATURE_M_KEYS_LEDS, in lg_g510_update_mkey_led_brightness()
363 g15->transfer_buf, 2, in lg_g510_update_mkey_led_brightness()
366 hid_err(g15->hdev, "Error getting LED brightness: %d\n", ret); in lg_g510_update_mkey_led_brightness()
367 ret = (ret < 0) ? ret : -EIO; in lg_g510_update_mkey_led_brightness()
370 g15->leds[LG_G15_MACRO_PRESET1].brightness = in lg_g510_update_mkey_led_brightness()
371 !!(g15->transfer_buf[1] & 0x80); in lg_g510_update_mkey_led_brightness()
372 g15->leds[LG_G15_MACRO_PRESET2].brightness = in lg_g510_update_mkey_led_brightness()
373 !!(g15->transfer_buf[1] & 0x40); in lg_g510_update_mkey_led_brightness()
374 g15->leds[LG_G15_MACRO_PRESET3].brightness = in lg_g510_update_mkey_led_brightness()
375 !!(g15->transfer_buf[1] & 0x20); in lg_g510_update_mkey_led_brightness()
376 g15->leds[LG_G15_MACRO_RECORD].brightness = in lg_g510_update_mkey_led_brightness()
377 !!(g15->transfer_buf[1] & 0x10); in lg_g510_update_mkey_led_brightness()
386 struct lg_g15_data *g15 = dev_get_drvdata(led_cdev->dev->parent); in lg_g510_mkey_led_get()
389 mutex_lock(&g15->mutex); in lg_g510_mkey_led_get()
391 brightness = g15->leds[g15_led->led].brightness; in lg_g510_mkey_led_get()
392 mutex_unlock(&g15->mutex); in lg_g510_mkey_led_get()
402 struct lg_g15_data *g15 = dev_get_drvdata(led_cdev->dev->parent); in lg_g510_mkey_led_set()
406 /* Ignore LED off on unregister / keyboard unplug */ in lg_g510_mkey_led_set()
407 if (led_cdev->flags & LED_UNREGISTERING) in lg_g510_mkey_led_set()
410 mutex_lock(&g15->mutex); in lg_g510_mkey_led_set()
413 if (i == g15_led->led) in lg_g510_mkey_led_set()
416 val = g15->leds[i].brightness; in lg_g510_mkey_led_set()
419 mask |= 0x80 >> (i - LG_G15_MACRO_PRESET1); in lg_g510_mkey_led_set()
422 g15->transfer_buf[0] = LG_G510_FEATURE_M_KEYS_LEDS; in lg_g510_mkey_led_set()
423 g15->transfer_buf[1] = mask; in lg_g510_mkey_led_set()
425 ret = hid_hw_raw_request(g15->hdev, LG_G510_FEATURE_M_KEYS_LEDS, in lg_g510_mkey_led_set()
426 g15->transfer_buf, 2, in lg_g510_mkey_led_set()
430 g15_led->brightness = brightness; in lg_g510_mkey_led_set()
433 hid_err(g15->hdev, "Error setting LED brightness: %d\n", ret); in lg_g510_mkey_led_set()
434 ret = (ret < 0) ? ret : -EIO; in lg_g510_mkey_led_set()
437 mutex_unlock(&g15->mutex); in lg_g510_mkey_led_set()
442 /******** Generic LED functions ********/
447 switch (g15->model) { in lg_g15_get_initial_led_brightness()
464 * Getting the LCD backlight brightness is not supported. in lg_g15_get_initial_led_brightness()
465 * Reading Feature(2) fails with -EPIPE and this crashes in lg_g15_get_initial_led_brightness()
470 return -EINVAL; /* Never reached */ in lg_g15_get_initial_led_brightness()
481 input_report_key(g15->input, KEY_KBD_LCD_MENU1, data[8] & 0x80); in lg_g15_handle_lcd_menu_keys()
485 input_report_key(g15->input, KEY_KBD_LCD_MENU2 + i, val); in lg_g15_handle_lcd_menu_keys()
493 /* G1 - G6 */ in lg_g15_event()
496 input_report_key(g15->input, KEY_MACRO1 + i, val); in lg_g15_event()
498 /* G7 - G12 */ in lg_g15_event()
501 input_report_key(g15->input, KEY_MACRO7 + i, val); in lg_g15_event()
503 /* G13 - G17 */ in lg_g15_event()
506 input_report_key(g15->input, KEY_MACRO13 + i, val); in lg_g15_event()
509 input_report_key(g15->input, KEY_MACRO18, data[8] & 0x40); in lg_g15_event()
511 /* M1 - M3 */ in lg_g15_event()
514 input_report_key(g15->input, KEY_MACRO_PRESET1 + i, val); in lg_g15_event()
517 input_report_key(g15->input, KEY_MACRO_RECORD_START, data[7] & 0x40); in lg_g15_event()
521 /* Backlight cycle button pressed? */ in lg_g15_event()
523 schedule_work(&g15->work); in lg_g15_event()
525 input_sync(g15->input); in lg_g15_event()
533 /* G1 - G6 */ in lg_g15_v2_event()
536 input_report_key(g15->input, KEY_MACRO1 + i, val); in lg_g15_v2_event()
539 /* M1 - M3 + MR */ in lg_g15_v2_event()
540 input_report_key(g15->input, KEY_MACRO_PRESET1, data[1] & 0x40); in lg_g15_v2_event()
541 input_report_key(g15->input, KEY_MACRO_PRESET2, data[1] & 0x80); in lg_g15_v2_event()
542 input_report_key(g15->input, KEY_MACRO_PRESET3, data[2] & 0x20); in lg_g15_v2_event()
543 input_report_key(g15->input, KEY_MACRO_RECORD_START, data[2] & 0x40); in lg_g15_v2_event()
546 input_report_key(g15->input, KEY_KBD_LCD_MENU1, data[2] & 0x80); in lg_g15_v2_event()
550 input_report_key(g15->input, KEY_KBD_LCD_MENU2 + i, val); in lg_g15_v2_event()
553 /* Backlight cycle button pressed? */ in lg_g15_v2_event()
555 schedule_work(&g15->work); in lg_g15_v2_event()
557 input_sync(g15->input); in lg_g15_v2_event()
566 /* G1 - G18 */ in lg_g510_event()
569 input_report_key(g15->input, KEY_MACRO1 + i, val); in lg_g510_event()
574 if (game_mode_enabled != g15->game_mode_enabled) { in lg_g510_event()
576 hid_info(g15->hdev, "Game Mode enabled, Windows (super) key is disabled\n"); in lg_g510_event()
578 hid_info(g15->hdev, "Game Mode disabled\n"); in lg_g510_event()
579 g15->game_mode_enabled = game_mode_enabled; in lg_g510_event()
582 /* M1 - M3 */ in lg_g510_event()
585 input_report_key(g15->input, KEY_MACRO_PRESET1 + i, val); in lg_g510_event()
588 input_report_key(g15->input, KEY_MACRO_RECORD_START, data[3] & 0x80); in lg_g510_event()
593 input_report_key(g15->input, KEY_KBD_LCD_MENU1 + i, val); in lg_g510_event()
597 input_report_key(g15->input, KEY_MUTE, data[4] & 0x20); in lg_g510_event()
599 input_report_key(g15->input, KEY_F20, data[4] & 0x40); in lg_g510_event()
601 input_sync(g15->input); in lg_g510_event()
610 * The G510 ignores backlight updates when the backlight is turned off in lg_g510_leds_event()
612 * we queue a workitem to sync values when the backlight is turned on. in lg_g510_leds_event()
616 schedule_work(&g15->work); in lg_g510_leds_event()
629 switch (g15->model) { in lg_g15_raw_event()
641 input_sync(g15->input); in lg_g15_raw_event()
672 g15->leds[i].led = i; in lg_g15_register_led()
673 g15->leds[i].cdev.name = name; in lg_g15_register_led()
675 switch (g15->model) { in lg_g15_register_led()
678 g15->leds[i].cdev.brightness_get = lg_g15_led_get; in lg_g15_register_led()
681 g15->leds[i].cdev.brightness_set_blocking = lg_g15_led_set; in lg_g15_register_led()
683 g15->leds[i].cdev.flags = LED_BRIGHT_HW_CHANGED; in lg_g15_register_led()
684 g15->leds[i].cdev.max_brightness = 2; in lg_g15_register_led()
686 g15->leds[i].cdev.max_brightness = 1; in lg_g15_register_led()
695 * but it does have a separate power-on (reset) value. in lg_g15_register_led()
697 g15->leds[i].cdev.name = "g15::power_on_backlight_val"; in lg_g15_register_led()
700 g15->leds[i].cdev.brightness_set_blocking = in lg_g15_register_led()
702 g15->leds[i].cdev.brightness_get = in lg_g15_register_led()
704 g15->leds[i].cdev.max_brightness = 255; in lg_g15_register_led()
705 g15->leds[i].cdev.groups = lg_g510_kbd_led_groups; in lg_g15_register_led()
708 g15->leds[i].cdev.brightness_set_blocking = in lg_g15_register_led()
710 g15->leds[i].cdev.brightness_get = in lg_g15_register_led()
712 g15->leds[i].cdev.max_brightness = 1; in lg_g15_register_led()
717 return devm_led_classdev_register(&g15->hdev->dev, &g15->leds[i].cdev); in lg_g15_register_led()
720 /* Common input device init code shared between keyboards and Z-10 speaker handling */
726 input->name = name; in lg_g15_init_input_dev()
727 input->phys = hdev->phys; in lg_g15_init_input_dev()
728 input->uniq = hdev->uniq; in lg_g15_init_input_dev()
729 input->id.bustype = hdev->bus; in lg_g15_init_input_dev()
730 input->id.vendor = hdev->vendor; in lg_g15_init_input_dev()
731 input->id.product = hdev->product; in lg_g15_init_input_dev()
732 input->id.version = hdev->version; in lg_g15_init_input_dev()
733 input->dev.parent = &hdev->dev; in lg_g15_init_input_dev()
734 input->open = lg_g15_input_open; in lg_g15_init_input_dev()
735 input->close = lg_g15_input_close; in lg_g15_init_input_dev()
762 hdev->quirks |= HID_QUIRK_INPUT_PER_APP; in lg_g15_probe()
772 rep_enum = &hdev->report_enum[HID_INPUT_REPORT]; in lg_g15_probe()
773 list_for_each_entry(rep, &rep_enum->report_list, list) { in lg_g15_probe()
774 if (rep->application == 0xff000000) in lg_g15_probe()
780 g15 = devm_kzalloc(&hdev->dev, sizeof(*g15), GFP_KERNEL); in lg_g15_probe()
782 return -ENOMEM; in lg_g15_probe()
784 mutex_init(&g15->mutex); in lg_g15_probe()
786 input = devm_input_allocate_device(&hdev->dev); in lg_g15_probe()
788 return -ENOMEM; in lg_g15_probe()
790 g15->hdev = hdev; in lg_g15_probe()
791 g15->model = id->driver_data; in lg_g15_probe()
792 g15->input = input; in lg_g15_probe()
796 switch (g15->model) { in lg_g15_probe()
798 INIT_WORK(&g15->work, lg_g15_leds_changed_work); in lg_g15_probe()
800 * The G15 and G15 v2 use a separate usb-device (on a builtin in lg_g15_probe()
801 * hub) which emulates a keyboard for the F1 - F12 emulation in lg_g15_probe()
802 * on the G-keys, which we disable, rendering the emulated kbd in lg_g15_probe()
803 * non-functional, so we do not let hid-input connect. in lg_g15_probe()
810 INIT_WORK(&g15->work, lg_g15_leds_changed_work); in lg_g15_probe()
817 INIT_WORK(&g15->work, lg_g510_leds_sync_work); in lg_g15_probe()
831 /* Tell the keyboard to stop sending F1-F12 + 1-6 for G1 - G18 */ in lg_g15_probe()
833 g15->transfer_buf[0] = gkeys_settings_output_report; in lg_g15_probe()
834 memset(g15->transfer_buf + 1, 0, gkeys); in lg_g15_probe()
836 * The kbd ignores our output report if we do not queue in lg_g15_probe()
842 ret = hid_hw_output_report(hdev, g15->transfer_buf, gkeys + 1); in lg_g15_probe()
847 g15->transfer_buf[0] = gkeys_settings_feature_report; in lg_g15_probe()
848 memset(g15->transfer_buf + 1, 0, gkeys); in lg_g15_probe()
849 ret = hid_hw_raw_request(g15->hdev, in lg_g15_probe()
851 g15->transfer_buf, gkeys + 1, in lg_g15_probe()
856 …hid_err(hdev, "Error %d disabling keyboard emulation for the G-keys, falling back to generic hid-i… in lg_g15_probe()
867 if (g15->model == LG_Z10) { in lg_g15_probe()
868 lg_g15_init_input_dev(hdev, g15->input, "Logitech Z-10 LCD Menu Keys"); in lg_g15_probe()
869 ret = input_register_device(g15->input); in lg_g15_probe()
873 ret = lg_g15_register_led(g15, 1, "z-10::lcd_backlight"); in lg_g15_probe()
883 /* G-keys */ in lg_g15_probe()
887 /* M1 - M3 and MR keys */ in lg_g15_probe()
897 if (g15->model == LG_G510) { in lg_g15_probe()
907 /* Register LED devices */ in lg_g15_probe()
940 /* Z-10 speakers */
949 .name = "lg-g15",