forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-01-04 1543e317f1da31b75942316931e8f491a8920811
kernel/drivers/platform/x86/thinkpad_acpi.c
....@@ -1,24 +1,9 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * thinkpad_acpi.c - ThinkPad ACPI Extras
34 *
4
- *
55 * Copyright (C) 2004-2005 Borislav Deianov <borislav@users.sf.net>
66 * Copyright (C) 2006-2009 Henrique de Moraes Holschuh <hmh@hmh.eng.br>
7
- *
8
- * This program is free software; you can redistribute it and/or modify
9
- * it under the terms of the GNU General Public License as published by
10
- * the Free Software Foundation; either version 2 of the License, or
11
- * (at your option) any later version.
12
- *
13
- * This program is distributed in the hope that it will be useful,
14
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
- * GNU General Public License for more details.
17
- *
18
- * You should have received a copy of the GNU General Public License
19
- * along with this program; if not, write to the Free Software
20
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21
- * 02110-1301, USA.
227 */
238
249 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
....@@ -81,7 +66,6 @@
8166 #include <linux/acpi.h>
8267 #include <linux/pci.h>
8368 #include <linux/power_supply.h>
84
-#include <linux/thinkpad_acpi.h>
8569 #include <sound/core.h>
8670 #include <sound/control.h>
8771 #include <sound/initval.h>
....@@ -334,6 +318,7 @@
334318 u32 uwb:1;
335319 u32 fan_ctrl_status_undef:1;
336320 u32 second_fan:1;
321
+ u32 second_fan_ctl:1;
337322 u32 beep_needs_two_args:1;
338323 u32 mixer_no_level_control:1;
339324 u32 battery_force_primary:1;
....@@ -476,6 +461,12 @@
476461 { .vendor = PCI_VENDOR_ID_LENOVO, \
477462 .bios = TPID3(__id1, __id2, __id3), \
478463 .ec = TPACPI_MATCH_ANY, \
464
+ .quirks = (__quirk) }
465
+
466
+#define TPACPI_QEC_IBM(__id1, __id2, __quirk) \
467
+ { .vendor = PCI_VENDOR_ID_IBM, \
468
+ .bios = TPACPI_MATCH_ANY, \
469
+ .ec = TPID(__id1, __id2), \
479470 .quirks = (__quirk) }
480471
481472 #define TPACPI_QEC_LNV(__id1, __id2, __quirk) \
....@@ -894,10 +885,10 @@
894885
895886 if (!ibm || !ibm->write)
896887 return -EINVAL;
897
- if (count > PAGE_SIZE - 2)
888
+ if (count > PAGE_SIZE - 1)
898889 return -EINVAL;
899890
900
- kernbuf = kmalloc(count + 2, GFP_KERNEL);
891
+ kernbuf = kmalloc(count + 1, GFP_KERNEL);
901892 if (!kernbuf)
902893 return -ENOMEM;
903894
....@@ -907,7 +898,6 @@
907898 }
908899
909900 kernbuf[count] = 0;
910
- strcat(kernbuf, ",");
911901 ret = ibm->write(kernbuf);
912902 if (ret == 0)
913903 ret = count;
....@@ -917,31 +907,13 @@
917907 return ret;
918908 }
919909
920
-static const struct file_operations dispatch_proc_fops = {
921
- .owner = THIS_MODULE,
922
- .open = dispatch_proc_open,
923
- .read = seq_read,
924
- .llseek = seq_lseek,
925
- .release = single_release,
926
- .write = dispatch_proc_write,
910
+static const struct proc_ops dispatch_proc_ops = {
911
+ .proc_open = dispatch_proc_open,
912
+ .proc_read = seq_read,
913
+ .proc_lseek = seq_lseek,
914
+ .proc_release = single_release,
915
+ .proc_write = dispatch_proc_write,
927916 };
928
-
929
-static char *next_cmd(char **cmds)
930
-{
931
- char *start = *cmds;
932
- char *end;
933
-
934
- while ((end = strchr(start, ',')) && end == start)
935
- start = end + 1;
936
-
937
- if (!end)
938
- return NULL;
939
-
940
- *end = 0;
941
- *cmds = end + 1;
942
- return start;
943
-}
944
-
945917
946918 /****************************************************************************
947919 ****************************************************************************
....@@ -1424,7 +1396,7 @@
14241396 if (id >= TPACPI_RFK_SW_MAX)
14251397 return -ENODEV;
14261398
1427
- while ((cmd = next_cmd(&buf))) {
1399
+ while ((cmd = strsep(&buf, ","))) {
14281400 if (strlencmp(cmd, "enable") == 0)
14291401 status = TPACPI_RFK_RADIO_ON;
14301402 else if (strlencmp(cmd, "disable") == 0)
....@@ -1932,6 +1904,10 @@
19321904 TP_ACPI_HOTKEYSCAN_CALCULATOR,
19331905 TP_ACPI_HOTKEYSCAN_BLUETOOTH,
19341906 TP_ACPI_HOTKEYSCAN_KEYBOARD,
1907
+ TP_ACPI_HOTKEYSCAN_FN_RIGHT_SHIFT, /* Used by "Lenovo Quick Clean" */
1908
+ TP_ACPI_HOTKEYSCAN_NOTIFICATION_CENTER,
1909
+ TP_ACPI_HOTKEYSCAN_PICKUP_PHONE,
1910
+ TP_ACPI_HOTKEYSCAN_HANGUP_PHONE,
19351911
19361912 /* Hotkey keymap size */
19371913 TPACPI_HOTKEY_MAP_LEN
....@@ -3452,11 +3428,15 @@
34523428 KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
34533429 KEY_UNKNOWN,
34543430
3455
- KEY_FAVORITES, /* Favorite app, 0x311 */
3456
- KEY_RESERVED, /* Clipping tool */
3457
- KEY_CALC, /* Calculator (above numpad, P52) */
3458
- KEY_BLUETOOTH, /* Bluetooth */
3459
- KEY_KEYBOARD /* Keyboard, 0x315 */
3431
+ KEY_BOOKMARKS, /* Favorite app, 0x311 */
3432
+ KEY_SELECTIVE_SCREENSHOT, /* Clipping tool */
3433
+ KEY_CALC, /* Calculator (above numpad, P52) */
3434
+ KEY_BLUETOOTH, /* Bluetooth */
3435
+ KEY_KEYBOARD, /* Keyboard, 0x315 */
3436
+ KEY_FN_RIGHT_SHIFT, /* Fn + right Shift */
3437
+ KEY_NOTIFICATION_CENTER, /* Notification Center */
3438
+ KEY_PICKUP_PHONE, /* Answer incoming call */
3439
+ KEY_HANGUP_PHONE, /* Decline incoming call */
34603440 },
34613441 };
34623442
....@@ -3652,22 +3632,19 @@
36523632 goto err_exit;
36533633
36543634 /* Set up key map */
3655
- hotkey_keycode_map = kmalloc(TPACPI_HOTKEY_MAP_SIZE,
3656
- GFP_KERNEL);
3657
- if (!hotkey_keycode_map) {
3658
- pr_err("failed to allocate memory for key map\n");
3659
- res = -ENOMEM;
3660
- goto err_exit;
3661
- }
3662
-
36633635 keymap_id = tpacpi_check_quirks(tpacpi_keymap_qtable,
36643636 ARRAY_SIZE(tpacpi_keymap_qtable));
36653637 BUG_ON(keymap_id >= ARRAY_SIZE(tpacpi_keymaps));
36663638 dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY,
36673639 "using keymap number %lu\n", keymap_id);
36683640
3669
- memcpy(hotkey_keycode_map, &tpacpi_keymaps[keymap_id],
3670
- TPACPI_HOTKEY_MAP_SIZE);
3641
+ hotkey_keycode_map = kmemdup(&tpacpi_keymaps[keymap_id],
3642
+ TPACPI_HOTKEY_MAP_SIZE, GFP_KERNEL);
3643
+ if (!hotkey_keycode_map) {
3644
+ pr_err("failed to allocate memory for key map\n");
3645
+ res = -ENOMEM;
3646
+ goto err_exit;
3647
+ }
36713648
36723649 input_set_capability(tpacpi_inputdev, EV_MSC, MSC_SCAN);
36733650 tpacpi_inputdev->keycodesize = TPACPI_HOTKEY_MAP_TYPESIZE;
....@@ -4056,8 +4033,8 @@
40564033 return true;
40574034 case TP_HKEY_EV_THM_CSM_COMPLETED:
40584035 pr_debug("EC reports: Thermal Control Command set completed (DYTC)\n");
4059
- /* recommended action: do nothing, we don't have
4060
- * Lenovo ATM information */
4036
+ /* Thermal event - pass on to event handler */
4037
+ tpacpi_driver_event(hkey);
40614038 return true;
40624039 case TP_HKEY_EV_THM_TRANSFM_CHANGED:
40634040 pr_debug("EC reports: Thermal Transformation changed (GMTS)\n");
....@@ -4086,7 +4063,7 @@
40864063 * AC status changed; can be triggered by plugging or
40874064 * unplugging AC adapter, docking or undocking. */
40884065
4089
- /* fallthrough */
4066
+ fallthrough;
40904067
40914068 case TP_HKEY_EV_KEY_NUMLOCK:
40924069 case TP_HKEY_EV_KEY_FN:
....@@ -4208,7 +4185,7 @@
42084185 known_ev = true;
42094186 break;
42104187 }
4211
- /* fallthrough to default */
4188
+ fallthrough; /* to default */
42124189 default:
42134190 known_ev = false;
42144191 }
....@@ -4321,7 +4298,7 @@
43214298 mask = hotkey_user_mask;
43224299
43234300 res = 0;
4324
- while ((cmd = next_cmd(&buf))) {
4301
+ while ((cmd = strsep(&buf, ","))) {
43254302 if (strlencmp(cmd, "enable") == 0) {
43264303 hotkey_enabledisable_warn(1);
43274304 } else if (strlencmp(cmd, "disable") == 0) {
....@@ -5248,7 +5225,7 @@
52485225 enable = 0;
52495226 disable = 0;
52505227
5251
- while ((cmd = next_cmd(&buf))) {
5228
+ while ((cmd = strsep(&buf, ","))) {
52525229 if (strlencmp(cmd, "lcd_enable") == 0) {
52535230 enable |= TP_ACPI_VIDEO_S_LCD;
52545231 } else if (strlencmp(cmd, "lcd_disable") == 0) {
....@@ -5449,8 +5426,7 @@
54495426
54505427 static void kbdlight_exit(void)
54515428 {
5452
- if (tp_features.kbdlight)
5453
- led_classdev_unregister(&tpacpi_led_kbdlight.led_classdev);
5429
+ led_classdev_unregister(&tpacpi_led_kbdlight.led_classdev);
54545430 }
54555431
54565432 static int kbdlight_set_level_and_update(int level)
....@@ -5488,23 +5464,18 @@
54885464 static int kbdlight_write(char *buf)
54895465 {
54905466 char *cmd;
5491
- int level = -1;
5467
+ int res, level = -EINVAL;
54925468
54935469 if (!tp_features.kbdlight)
54945470 return -ENODEV;
54955471
5496
- while ((cmd = next_cmd(&buf))) {
5497
- if (strlencmp(cmd, "0") == 0)
5498
- level = 0;
5499
- else if (strlencmp(cmd, "1") == 0)
5500
- level = 1;
5501
- else if (strlencmp(cmd, "2") == 0)
5502
- level = 2;
5503
- else
5504
- return -EINVAL;
5472
+ while ((cmd = strsep(&buf, ","))) {
5473
+ res = kstrtoint(cmd, 10, &level);
5474
+ if (res < 0)
5475
+ return res;
55055476 }
55065477
5507
- if (level == -1)
5478
+ if (level >= 3 || level < 0)
55085479 return -EINVAL;
55095480
55105481 return kbdlight_set_level_and_update(level);
....@@ -5673,7 +5644,7 @@
56735644 if (!tp_features.light)
56745645 return -ENODEV;
56755646
5676
- while ((cmd = next_cmd(&buf))) {
5647
+ while ((cmd = strsep(&buf, ","))) {
56775648 if (strlencmp(cmd, "on") == 0) {
56785649 newstatus = 1;
56795650 } else if (strlencmp(cmd, "off") == 0) {
....@@ -5758,7 +5729,7 @@
57585729 char *cmd;
57595730 int cmos_cmd, res;
57605731
5761
- while ((cmd = next_cmd(&buf))) {
5732
+ while ((cmd = strsep(&buf, ","))) {
57625733 if (sscanf(cmd, "%u", &cmos_cmd) == 1 &&
57635734 cmos_cmd >= 0 && cmos_cmd <= 21) {
57645735 /* cmos_cmd set */
....@@ -5873,7 +5844,7 @@
58735844 return -EPERM;
58745845 if (!acpi_evalf(led_handle, NULL, NULL, "vdd",
58755846 (1 << led), led_sled_arg1[ledstatus]))
5876
- rc = -EIO;
5847
+ return -EIO;
58775848 break;
58785849 case TPACPI_LED_OLD:
58795850 /* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20 */
....@@ -5897,10 +5868,10 @@
58975868 return -EPERM;
58985869 if (!acpi_evalf(led_handle, NULL, NULL, "vdd",
58995870 led, led_led_arg1[ledstatus]))
5900
- rc = -EIO;
5871
+ return -EIO;
59015872 break;
59025873 default:
5903
- rc = -ENXIO;
5874
+ return -ENXIO;
59045875 }
59055876
59065877 if (!rc)
....@@ -5964,20 +5935,14 @@
59645935 {
59655936 unsigned int i;
59665937
5967
- for (i = 0; i < TPACPI_LED_NUMLEDS; i++) {
5968
- if (tpacpi_leds[i].led_classdev.name)
5969
- led_classdev_unregister(&tpacpi_leds[i].led_classdev);
5970
- }
5938
+ for (i = 0; i < TPACPI_LED_NUMLEDS; i++)
5939
+ led_classdev_unregister(&tpacpi_leds[i].led_classdev);
59715940
59725941 kfree(tpacpi_leds);
59735942 }
59745943
59755944 static int __init tpacpi_init_led(unsigned int led)
59765945 {
5977
- int rc;
5978
-
5979
- tpacpi_leds[led].led = led;
5980
-
59815946 /* LEDs with no name don't get registered */
59825947 if (!tpacpi_led_names[led])
59835948 return 0;
....@@ -5985,17 +5950,12 @@
59855950 tpacpi_leds[led].led_classdev.brightness_set_blocking = &led_sysfs_set;
59865951 tpacpi_leds[led].led_classdev.blink_set = &led_sysfs_blink_set;
59875952 if (led_supported == TPACPI_LED_570)
5988
- tpacpi_leds[led].led_classdev.brightness_get =
5989
- &led_sysfs_get;
5953
+ tpacpi_leds[led].led_classdev.brightness_get = &led_sysfs_get;
59905954
59915955 tpacpi_leds[led].led_classdev.name = tpacpi_led_names[led];
5956
+ tpacpi_leds[led].led = led;
59925957
5993
- rc = led_classdev_register(&tpacpi_pdev->dev,
5994
- &tpacpi_leds[led].led_classdev);
5995
- if (rc < 0)
5996
- tpacpi_leds[led].led_classdev.name = NULL;
5997
-
5998
- return rc;
5958
+ return led_classdev_register(&tpacpi_pdev->dev, &tpacpi_leds[led].led_classdev);
59995959 }
60005960
60015961 static const struct tpacpi_quirk led_useful_qtable[] __initconst = {
....@@ -6042,9 +6002,6 @@
60426002 .quirks = 0x00bfU,
60436003 },
60446004 };
6045
-
6046
-#undef TPACPI_LEDQ_IBM
6047
-#undef TPACPI_LEDQ_LNV
60486005
60496006 static enum led_access_mode __init led_init_detect_mode(void)
60506007 {
....@@ -6108,8 +6065,7 @@
61086065 for (i = 0; i < TPACPI_LED_NUMLEDS; i++) {
61096066 tpacpi_leds[i].led = -1;
61106067
6111
- if (!tpacpi_is_led_restricted(i) &&
6112
- test_bit(i, &useful_leds)) {
6068
+ if (!tpacpi_is_led_restricted(i) && test_bit(i, &useful_leds)) {
61136069 rc = tpacpi_init_led(i);
61146070 if (rc < 0) {
61156071 led_exit();
....@@ -6162,12 +6118,14 @@
61626118 if (!led_supported)
61636119 return -ENODEV;
61646120
6165
- while ((cmd = next_cmd(&buf))) {
6121
+ while ((cmd = strsep(&buf, ","))) {
61666122 if (sscanf(cmd, "%d", &led) != 1)
61676123 return -EINVAL;
61686124
6169
- if (led < 0 || led > (TPACPI_LED_NUMLEDS - 1) ||
6170
- tpacpi_leds[led].led < 0)
6125
+ if (led < 0 || led > (TPACPI_LED_NUMLEDS - 1))
6126
+ return -ENODEV;
6127
+
6128
+ if (tpacpi_leds[led].led < 0)
61716129 return -ENODEV;
61726130
61736131 if (strstr(cmd, "off")) {
....@@ -6247,7 +6205,7 @@
62476205 if (!beep_handle)
62486206 return -ENODEV;
62496207
6250
- while ((cmd = next_cmd(&buf))) {
6208
+ while ((cmd = strsep(&buf, ","))) {
62516209 if (sscanf(cmd, "%u", &beep_cmd) == 1 &&
62526210 beep_cmd >= 0 && beep_cmd <= 17) {
62536211 /* beep_cmd set */
....@@ -6318,8 +6276,8 @@
63186276 t = TP_EC_THERMAL_TMP8;
63196277 idx -= 8;
63206278 }
6321
- /* fallthrough */
63226279 #endif
6280
+ fallthrough;
63236281 case TPACPI_THERMAL_TPEC_8:
63246282 if (idx <= 7) {
63256283 if (!acpi_ec_read(t + idx, &tmp))
....@@ -7030,9 +6988,12 @@
70306988 pr_warn("Cannot enable backlight brightness support, ACPI is already handling it. Refer to the acpi_backlight kernel parameter.\n");
70316989 return 1;
70326990 }
7033
- } else if (tp_features.bright_acpimode && brightness_enable > 1) {
7034
- pr_notice("Standard ACPI backlight interface not available, thinkpad_acpi native brightness control enabled\n");
6991
+ } else if (!tp_features.bright_acpimode) {
6992
+ pr_notice("ACPI backlight interface not available\n");
6993
+ return 1;
70356994 }
6995
+
6996
+ pr_notice("ACPI native brightness control enabled\n");
70366997
70376998 /*
70386999 * Check for module parameter bogosity, note that we
....@@ -7150,7 +7111,7 @@
71507111 if (level < 0)
71517112 return level;
71527113
7153
- while ((cmd = next_cmd(&buf))) {
7114
+ while ((cmd = strsep(&buf, ","))) {
71547115 if (strlencmp(cmd, "up") == 0) {
71557116 if (level < bright_maxlvl)
71567117 level++;
....@@ -7902,7 +7863,7 @@
79027863 new_level = s & TP_EC_AUDIO_LVL_MSK;
79037864 new_mute = s & TP_EC_AUDIO_MUTESW_MSK;
79047865
7905
- while ((cmd = next_cmd(&buf))) {
7866
+ while ((cmd = strsep(&buf, ","))) {
79067867 if (!tp_features.mixer_no_level_control) {
79077868 if (strlencmp(cmd, "up") == 0) {
79087869 if (new_mute)
....@@ -8032,7 +7993,7 @@
80327993 * does so, its initial value is meaningless (0x07).
80337994 *
80347995 * For firmware bugs, refer to:
8035
- * http://thinkwiki.org/wiki/Embedded_Controller_Firmware#Firmware_Issues
7996
+ * https://thinkwiki.org/wiki/Embedded_Controller_Firmware#Firmware_Issues
80367997 *
80377998 * ----
80387999 *
....@@ -8057,7 +8018,7 @@
80578018 * mode.
80588019 *
80598020 * For firmware bugs, refer to:
8060
- * http://thinkwiki.org/wiki/Embedded_Controller_Firmware#Firmware_Issues
8021
+ * https://thinkwiki.org/wiki/Embedded_Controller_Firmware#Firmware_Issues
80618022 *
80628023 * ----
80638024 *
....@@ -8358,11 +8319,19 @@
83588319
83598320 switch (fan_control_access_mode) {
83608321 case TPACPI_FAN_WR_ACPI_SFAN:
8361
- if (level >= 0 && level <= 7) {
8362
- if (!acpi_evalf(sfan_handle, NULL, NULL, "vd", level))
8363
- return -EIO;
8364
- } else
8322
+ if ((level < 0) || (level > 7))
83658323 return -EINVAL;
8324
+
8325
+ if (tp_features.second_fan_ctl) {
8326
+ if (!fan_select_fan2() ||
8327
+ !acpi_evalf(sfan_handle, NULL, NULL, "vd", level)) {
8328
+ pr_warn("Couldn't set 2nd fan level, disabling support\n");
8329
+ tp_features.second_fan_ctl = 0;
8330
+ }
8331
+ fan_select_fan1();
8332
+ }
8333
+ if (!acpi_evalf(sfan_handle, NULL, NULL, "vd", level))
8334
+ return -EIO;
83668335 break;
83678336
83688337 case TPACPI_FAN_WR_ACPI_FANS:
....@@ -8379,6 +8348,15 @@
83798348 else if (level & TP_EC_FAN_AUTO)
83808349 level |= 4; /* safety min speed 4 */
83818350
8351
+ if (tp_features.second_fan_ctl) {
8352
+ if (!fan_select_fan2() ||
8353
+ !acpi_ec_write(fan_status_offset, level)) {
8354
+ pr_warn("Couldn't set 2nd fan level, disabling support\n");
8355
+ tp_features.second_fan_ctl = 0;
8356
+ }
8357
+ fan_select_fan1();
8358
+
8359
+ }
83828360 if (!acpi_ec_write(fan_status_offset, level))
83838361 return -EIO;
83848362 else
....@@ -8795,39 +8773,30 @@
87958773 .attrs = fan_attributes,
87968774 };
87978775
8798
-#define TPACPI_FAN_Q1 0x0001 /* Unitialized HFSP */
8776
+#define TPACPI_FAN_Q1 0x0001 /* Unitialized HFSP */
87998777 #define TPACPI_FAN_2FAN 0x0002 /* EC 0x31 bit 0 selects fan2 */
8800
-
8801
-#define TPACPI_FAN_QI(__id1, __id2, __quirks) \
8802
- { .vendor = PCI_VENDOR_ID_IBM, \
8803
- .bios = TPACPI_MATCH_ANY, \
8804
- .ec = TPID(__id1, __id2), \
8805
- .quirks = __quirks }
8806
-
8807
-#define TPACPI_FAN_QL(__id1, __id2, __quirks) \
8808
- { .vendor = PCI_VENDOR_ID_LENOVO, \
8809
- .bios = TPACPI_MATCH_ANY, \
8810
- .ec = TPID(__id1, __id2), \
8811
- .quirks = __quirks }
8812
-
8813
-#define TPACPI_FAN_QB(__id1, __id2, __quirks) \
8814
- { .vendor = PCI_VENDOR_ID_LENOVO, \
8815
- .bios = TPID(__id1, __id2), \
8816
- .ec = TPACPI_MATCH_ANY, \
8817
- .quirks = __quirks }
8778
+#define TPACPI_FAN_2CTL 0x0004 /* selects fan2 control */
88188779
88198780 static const struct tpacpi_quirk fan_quirk_table[] __initconst = {
8820
- TPACPI_FAN_QI('1', 'Y', TPACPI_FAN_Q1),
8821
- TPACPI_FAN_QI('7', '8', TPACPI_FAN_Q1),
8822
- TPACPI_FAN_QI('7', '6', TPACPI_FAN_Q1),
8823
- TPACPI_FAN_QI('7', '0', TPACPI_FAN_Q1),
8824
- TPACPI_FAN_QL('7', 'M', TPACPI_FAN_2FAN),
8825
- TPACPI_FAN_QB('N', '1', TPACPI_FAN_2FAN),
8781
+ TPACPI_QEC_IBM('1', 'Y', TPACPI_FAN_Q1),
8782
+ TPACPI_QEC_IBM('7', '8', TPACPI_FAN_Q1),
8783
+ TPACPI_QEC_IBM('7', '6', TPACPI_FAN_Q1),
8784
+ TPACPI_QEC_IBM('7', '0', TPACPI_FAN_Q1),
8785
+ TPACPI_QEC_LNV('7', 'M', TPACPI_FAN_2FAN),
8786
+ TPACPI_Q_LNV('N', '1', TPACPI_FAN_2FAN),
8787
+ TPACPI_Q_LNV3('N', '1', 'D', TPACPI_FAN_2CTL), /* P70 */
8788
+ TPACPI_Q_LNV3('N', '1', 'E', TPACPI_FAN_2CTL), /* P50 */
8789
+ TPACPI_Q_LNV3('N', '1', 'T', TPACPI_FAN_2CTL), /* P71 */
8790
+ TPACPI_Q_LNV3('N', '1', 'U', TPACPI_FAN_2CTL), /* P51 */
8791
+ TPACPI_Q_LNV3('N', '2', 'C', TPACPI_FAN_2CTL), /* P52 / P72 */
8792
+ TPACPI_Q_LNV3('N', '2', 'N', TPACPI_FAN_2CTL), /* P53 / P73 */
8793
+ TPACPI_Q_LNV3('N', '2', 'E', TPACPI_FAN_2CTL), /* P1 / X1 Extreme (1st gen) */
8794
+ TPACPI_Q_LNV3('N', '2', 'O', TPACPI_FAN_2CTL), /* P1 / X1 Extreme (2nd gen) */
8795
+ TPACPI_Q_LNV3('N', '2', 'V', TPACPI_FAN_2CTL), /* P1 / X1 Extreme (3nd gen) */
8796
+ TPACPI_Q_LNV3('N', '4', '0', TPACPI_FAN_2CTL), /* P1 / X1 Extreme (4nd gen) */
8797
+ TPACPI_Q_LNV3('N', '3', '0', TPACPI_FAN_2CTL), /* P15 (1st gen) / P15v (1st gen) */
8798
+ TPACPI_Q_LNV3('N', '3', '2', TPACPI_FAN_2CTL), /* X1 Carbon (9th gen) */
88268799 };
8827
-
8828
-#undef TPACPI_FAN_QL
8829
-#undef TPACPI_FAN_QI
8830
-#undef TPACPI_FAN_QB
88318800
88328801 static int __init fan_init(struct ibm_init_struct *iibm)
88338802 {
....@@ -8844,6 +8813,7 @@
88448813 fan_watchdog_maxinterval = 0;
88458814 tp_features.fan_ctrl_status_undef = 0;
88468815 tp_features.second_fan = 0;
8816
+ tp_features.second_fan_ctl = 0;
88478817 fan_control_desired_level = 7;
88488818
88498819 if (tpacpi_is_ibm()) {
....@@ -8868,8 +8838,12 @@
88688838 fan_quirk1_setup();
88698839 if (quirks & TPACPI_FAN_2FAN) {
88708840 tp_features.second_fan = 1;
8871
- dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_FAN,
8872
- "secondary fan support enabled\n");
8841
+ pr_info("secondary fan support enabled\n");
8842
+ }
8843
+ if (quirks & TPACPI_FAN_2CTL) {
8844
+ tp_features.second_fan = 1;
8845
+ tp_features.second_fan_ctl = 1;
8846
+ pr_info("secondary fan control enabled\n");
88738847 }
88748848 } else {
88758849 pr_err("ThinkPad ACPI EC access misbehaving, fan status and control unavailable\n");
....@@ -9204,7 +9178,7 @@
92049178 char *cmd;
92059179 int rc = 0;
92069180
9207
- while (!rc && (cmd = next_cmd(&buf))) {
9181
+ while (!rc && (cmd = strsep(&buf, ","))) {
92089182 if (!((fan_control_commands & TPACPI_FAN_CMD_LEVEL) &&
92099183 fan_write_cmd_level(cmd, &rc)) &&
92109184 !((fan_control_commands & TPACPI_FAN_CMD_ENABLE) &&
....@@ -9235,6 +9209,7 @@
92359209 * Mute LED subdriver
92369210 */
92379211
9212
+#define TPACPI_LED_MAX 2
92389213
92399214 struct tp_led_table {
92409215 acpi_string name;
....@@ -9243,13 +9218,13 @@
92439218 int state;
92449219 };
92459220
9246
-static struct tp_led_table led_tables[] = {
9247
- [TPACPI_LED_MUTE] = {
9221
+static struct tp_led_table led_tables[TPACPI_LED_MAX] = {
9222
+ [LED_AUDIO_MUTE] = {
92489223 .name = "SSMS",
92499224 .on_value = 1,
92509225 .off_value = 0,
92519226 },
9252
- [TPACPI_LED_MICMUTE] = {
9227
+ [LED_AUDIO_MICMUTE] = {
92539228 .name = "MMTS",
92549229 .on_value = 2,
92559230 .off_value = 0,
....@@ -9274,31 +9249,62 @@
92749249 return state;
92759250 }
92769251
9277
-int tpacpi_led_set(int whichled, bool on)
9252
+static int tpacpi_led_set(int whichled, bool on)
92789253 {
92799254 struct tp_led_table *t;
9280
-
9281
- if (whichled < 0 || whichled >= TPACPI_LED_MAX)
9282
- return -EINVAL;
92839255
92849256 t = &led_tables[whichled];
92859257 if (t->state < 0 || t->state == on)
92869258 return t->state;
92879259 return mute_led_on_off(t, on);
92889260 }
9289
-EXPORT_SYMBOL_GPL(tpacpi_led_set);
9261
+
9262
+static int tpacpi_led_mute_set(struct led_classdev *led_cdev,
9263
+ enum led_brightness brightness)
9264
+{
9265
+ return tpacpi_led_set(LED_AUDIO_MUTE, brightness != LED_OFF);
9266
+}
9267
+
9268
+static int tpacpi_led_micmute_set(struct led_classdev *led_cdev,
9269
+ enum led_brightness brightness)
9270
+{
9271
+ return tpacpi_led_set(LED_AUDIO_MICMUTE, brightness != LED_OFF);
9272
+}
9273
+
9274
+static struct led_classdev mute_led_cdev[TPACPI_LED_MAX] = {
9275
+ [LED_AUDIO_MUTE] = {
9276
+ .name = "platform::mute",
9277
+ .max_brightness = 1,
9278
+ .brightness_set_blocking = tpacpi_led_mute_set,
9279
+ .default_trigger = "audio-mute",
9280
+ },
9281
+ [LED_AUDIO_MICMUTE] = {
9282
+ .name = "platform::micmute",
9283
+ .max_brightness = 1,
9284
+ .brightness_set_blocking = tpacpi_led_micmute_set,
9285
+ .default_trigger = "audio-micmute",
9286
+ },
9287
+};
92909288
92919289 static int mute_led_init(struct ibm_init_struct *iibm)
92929290 {
92939291 acpi_handle temp;
9294
- int i;
9292
+ int i, err;
92959293
92969294 for (i = 0; i < TPACPI_LED_MAX; i++) {
92979295 struct tp_led_table *t = &led_tables[i];
9298
- if (ACPI_SUCCESS(acpi_get_handle(hkey_handle, t->name, &temp)))
9299
- mute_led_on_off(t, false);
9300
- else
9296
+ if (ACPI_FAILURE(acpi_get_handle(hkey_handle, t->name, &temp))) {
93019297 t->state = -ENODEV;
9298
+ continue;
9299
+ }
9300
+
9301
+ mute_led_cdev[i].brightness = ledtrig_audio_get(i);
9302
+ err = led_classdev_register(&tpacpi_pdev->dev, &mute_led_cdev[i]);
9303
+ if (err < 0) {
9304
+ while (i--)
9305
+ led_classdev_unregister(&mute_led_cdev[i]);
9306
+ return err;
9307
+ }
93029308 }
93039309 return 0;
93049310 }
....@@ -9307,8 +9313,10 @@
93079313 {
93089314 int i;
93099315
9310
- for (i = 0; i < TPACPI_LED_MAX; i++)
9316
+ for (i = 0; i < TPACPI_LED_MAX; i++) {
9317
+ led_classdev_unregister(&mute_led_cdev[i]);
93119318 tpacpi_led_set(i, false);
9319
+ }
93129320 }
93139321
93149322 static void mute_led_resume(void)
....@@ -9339,9 +9347,6 @@
93399347 #define SET_START "BCCS"
93409348 #define GET_STOP "BCSG"
93419349 #define SET_STOP "BCSS"
9342
-
9343
-#define START_ATTR "charge_start_threshold"
9344
-#define STOP_ATTR "charge_stop_threshold"
93459350
93469351 enum {
93479352 BAT_ANY = 0,
....@@ -9566,7 +9571,7 @@
95669571 if (!battery_info.batteries[battery].start_support)
95679572 return -ENODEV;
95689573 /* valid values are [0, 99] */
9569
- if (value < 0 || value > 99)
9574
+ if (value > 99)
95709575 return -EINVAL;
95719576 if (value > battery_info.batteries[battery].charge_stop)
95729577 return -EINVAL;
....@@ -9628,38 +9633,52 @@
96289633 return sprintf(buf, "%d\n", ret);
96299634 }
96309635
9631
-static ssize_t charge_start_threshold_show(struct device *device,
9636
+static ssize_t charge_control_start_threshold_show(struct device *device,
96329637 struct device_attribute *attr,
96339638 char *buf)
96349639 {
96359640 return tpacpi_battery_show(THRESHOLD_START, device, buf);
96369641 }
96379642
9638
-static ssize_t charge_stop_threshold_show(struct device *device,
9643
+static ssize_t charge_control_end_threshold_show(struct device *device,
96399644 struct device_attribute *attr,
96409645 char *buf)
96419646 {
96429647 return tpacpi_battery_show(THRESHOLD_STOP, device, buf);
96439648 }
96449649
9645
-static ssize_t charge_start_threshold_store(struct device *dev,
9650
+static ssize_t charge_control_start_threshold_store(struct device *dev,
96469651 struct device_attribute *attr,
96479652 const char *buf, size_t count)
96489653 {
96499654 return tpacpi_battery_store(THRESHOLD_START, dev, buf, count);
96509655 }
96519656
9652
-static ssize_t charge_stop_threshold_store(struct device *dev,
9657
+static ssize_t charge_control_end_threshold_store(struct device *dev,
96539658 struct device_attribute *attr,
96549659 const char *buf, size_t count)
96559660 {
96569661 return tpacpi_battery_store(THRESHOLD_STOP, dev, buf, count);
96579662 }
96589663
9659
-static DEVICE_ATTR_RW(charge_start_threshold);
9660
-static DEVICE_ATTR_RW(charge_stop_threshold);
9664
+static DEVICE_ATTR_RW(charge_control_start_threshold);
9665
+static DEVICE_ATTR_RW(charge_control_end_threshold);
9666
+static struct device_attribute dev_attr_charge_start_threshold = __ATTR(
9667
+ charge_start_threshold,
9668
+ 0644,
9669
+ charge_control_start_threshold_show,
9670
+ charge_control_start_threshold_store
9671
+);
9672
+static struct device_attribute dev_attr_charge_stop_threshold = __ATTR(
9673
+ charge_stop_threshold,
9674
+ 0644,
9675
+ charge_control_end_threshold_show,
9676
+ charge_control_end_threshold_store
9677
+);
96619678
96629679 static struct attribute *tpacpi_battery_attrs[] = {
9680
+ &dev_attr_charge_control_start_threshold.attr,
9681
+ &dev_attr_charge_control_end_threshold.attr,
96639682 &dev_attr_charge_start_threshold.attr,
96649683 &dev_attr_charge_stop_threshold.attr,
96659684 NULL,
....@@ -9729,6 +9748,205 @@
97299748 .exit = tpacpi_battery_exit,
97309749 };
97319750
9751
+/*************************************************************************
9752
+ * LCD Shadow subdriver, for the Lenovo PrivacyGuard feature
9753
+ */
9754
+
9755
+static int lcdshadow_state;
9756
+
9757
+static int lcdshadow_on_off(bool state)
9758
+{
9759
+ acpi_handle set_shadow_handle;
9760
+ int output;
9761
+
9762
+ if (ACPI_FAILURE(acpi_get_handle(hkey_handle, "SSSS", &set_shadow_handle))) {
9763
+ pr_warn("Thinkpad ACPI has no %s interface.\n", "SSSS");
9764
+ return -EIO;
9765
+ }
9766
+
9767
+ if (!acpi_evalf(set_shadow_handle, &output, NULL, "dd", (int)state))
9768
+ return -EIO;
9769
+
9770
+ lcdshadow_state = state;
9771
+ return 0;
9772
+}
9773
+
9774
+static int lcdshadow_set(bool on)
9775
+{
9776
+ if (lcdshadow_state < 0)
9777
+ return lcdshadow_state;
9778
+ if (lcdshadow_state == on)
9779
+ return 0;
9780
+ return lcdshadow_on_off(on);
9781
+}
9782
+
9783
+static int tpacpi_lcdshadow_init(struct ibm_init_struct *iibm)
9784
+{
9785
+ acpi_handle get_shadow_handle;
9786
+ int output;
9787
+
9788
+ if (ACPI_FAILURE(acpi_get_handle(hkey_handle, "GSSS", &get_shadow_handle))) {
9789
+ lcdshadow_state = -ENODEV;
9790
+ return 0;
9791
+ }
9792
+
9793
+ if (!acpi_evalf(get_shadow_handle, &output, NULL, "dd", 0)) {
9794
+ lcdshadow_state = -EIO;
9795
+ return -EIO;
9796
+ }
9797
+ if (!(output & 0x10000)) {
9798
+ lcdshadow_state = -ENODEV;
9799
+ return 0;
9800
+ }
9801
+ lcdshadow_state = output & 0x1;
9802
+
9803
+ return 0;
9804
+}
9805
+
9806
+static void lcdshadow_resume(void)
9807
+{
9808
+ if (lcdshadow_state >= 0)
9809
+ lcdshadow_on_off(lcdshadow_state);
9810
+}
9811
+
9812
+static int lcdshadow_read(struct seq_file *m)
9813
+{
9814
+ if (lcdshadow_state < 0) {
9815
+ seq_puts(m, "status:\t\tnot supported\n");
9816
+ } else {
9817
+ seq_printf(m, "status:\t\t%d\n", lcdshadow_state);
9818
+ seq_puts(m, "commands:\t0, 1\n");
9819
+ }
9820
+
9821
+ return 0;
9822
+}
9823
+
9824
+static int lcdshadow_write(char *buf)
9825
+{
9826
+ char *cmd;
9827
+ int res, state = -EINVAL;
9828
+
9829
+ if (lcdshadow_state < 0)
9830
+ return -ENODEV;
9831
+
9832
+ while ((cmd = strsep(&buf, ","))) {
9833
+ res = kstrtoint(cmd, 10, &state);
9834
+ if (res < 0)
9835
+ return res;
9836
+ }
9837
+
9838
+ if (state >= 2 || state < 0)
9839
+ return -EINVAL;
9840
+
9841
+ return lcdshadow_set(state);
9842
+}
9843
+
9844
+static struct ibm_struct lcdshadow_driver_data = {
9845
+ .name = "lcdshadow",
9846
+ .resume = lcdshadow_resume,
9847
+ .read = lcdshadow_read,
9848
+ .write = lcdshadow_write,
9849
+};
9850
+
9851
+/*************************************************************************
9852
+ * DYTC subdriver, for the Lenovo lapmode feature
9853
+ */
9854
+
9855
+#define DYTC_CMD_GET 2 /* To get current IC function and mode */
9856
+#define DYTC_GET_LAPMODE_BIT 17 /* Set when in lapmode */
9857
+
9858
+static bool dytc_lapmode;
9859
+
9860
+static void dytc_lapmode_notify_change(void)
9861
+{
9862
+ sysfs_notify(&tpacpi_pdev->dev.kobj, NULL, "dytc_lapmode");
9863
+}
9864
+
9865
+static int dytc_command(int command, int *output)
9866
+{
9867
+ acpi_handle dytc_handle;
9868
+
9869
+ if (ACPI_FAILURE(acpi_get_handle(hkey_handle, "DYTC", &dytc_handle))) {
9870
+ /* Platform doesn't support DYTC */
9871
+ return -ENODEV;
9872
+ }
9873
+ if (!acpi_evalf(dytc_handle, output, NULL, "dd", command))
9874
+ return -EIO;
9875
+ return 0;
9876
+}
9877
+
9878
+static int dytc_lapmode_get(bool *state)
9879
+{
9880
+ int output, err;
9881
+
9882
+ err = dytc_command(DYTC_CMD_GET, &output);
9883
+ if (err)
9884
+ return err;
9885
+ *state = output & BIT(DYTC_GET_LAPMODE_BIT) ? true : false;
9886
+ return 0;
9887
+}
9888
+
9889
+static void dytc_lapmode_refresh(void)
9890
+{
9891
+ bool new_state;
9892
+ int err;
9893
+
9894
+ err = dytc_lapmode_get(&new_state);
9895
+ if (err || (new_state == dytc_lapmode))
9896
+ return;
9897
+
9898
+ dytc_lapmode = new_state;
9899
+ dytc_lapmode_notify_change();
9900
+}
9901
+
9902
+/* sysfs lapmode entry */
9903
+static ssize_t dytc_lapmode_show(struct device *dev,
9904
+ struct device_attribute *attr,
9905
+ char *buf)
9906
+{
9907
+ return snprintf(buf, PAGE_SIZE, "%d\n", dytc_lapmode);
9908
+}
9909
+
9910
+static DEVICE_ATTR_RO(dytc_lapmode);
9911
+
9912
+static struct attribute *dytc_attributes[] = {
9913
+ &dev_attr_dytc_lapmode.attr,
9914
+ NULL,
9915
+};
9916
+
9917
+static const struct attribute_group dytc_attr_group = {
9918
+ .attrs = dytc_attributes,
9919
+};
9920
+
9921
+static int tpacpi_dytc_init(struct ibm_init_struct *iibm)
9922
+{
9923
+ int err;
9924
+
9925
+ err = dytc_lapmode_get(&dytc_lapmode);
9926
+ /* If support isn't available (ENODEV) then don't return an error
9927
+ * but just don't create the sysfs group
9928
+ */
9929
+ if (err == -ENODEV)
9930
+ return 0;
9931
+ /* For all other errors we can flag the failure */
9932
+ if (err)
9933
+ return err;
9934
+
9935
+ /* Platform supports this feature - create the group */
9936
+ err = sysfs_create_group(&tpacpi_pdev->dev.kobj, &dytc_attr_group);
9937
+ return err;
9938
+}
9939
+
9940
+static void dytc_exit(void)
9941
+{
9942
+ sysfs_remove_group(&tpacpi_pdev->dev.kobj, &dytc_attr_group);
9943
+}
9944
+
9945
+static struct ibm_struct dytc_driver_data = {
9946
+ .name = "dytc",
9947
+ .exit = dytc_exit,
9948
+};
9949
+
97329950 /****************************************************************************
97339951 ****************************************************************************
97349952 *
....@@ -9776,6 +9994,10 @@
97769994
97779995 mutex_unlock(&kbdlight_mutex);
97789996 }
9997
+
9998
+ if (hkey_event == TP_HKEY_EV_THM_CSM_COMPLETED)
9999
+ dytc_lapmode_refresh();
10000
+
977910001 }
978010002
978110003 static void hotkey_driver_event(const unsigned int scancode)
....@@ -9901,7 +10123,7 @@
990110123 if (ibm->write)
990210124 mode |= S_IWUSR;
990310125 entry = proc_create_data(ibm->name, mode, proc_dir,
9904
- &dispatch_proc_fops, ibm);
10126
+ &dispatch_proc_ops, ibm);
990510127 if (!entry) {
990610128 pr_err("unable to create proc entry %s\n", ibm->name);
990710129 ret = -ENODEV;
....@@ -9958,6 +10180,37 @@
995810180 return '\0';
995910181 }
996010182
10183
+static void find_new_ec_fwstr(const struct dmi_header *dm, void *private)
10184
+{
10185
+ char *ec_fw_string = (char *) private;
10186
+ const char *dmi_data = (const char *)dm;
10187
+ /*
10188
+ * ThinkPad Embedded Controller Program Table on newer models
10189
+ *
10190
+ * Offset | Name | Width | Description
10191
+ * ----------------------------------------------------
10192
+ * 0x00 | Type | BYTE | 0x8C
10193
+ * 0x01 | Length | BYTE |
10194
+ * 0x02 | Handle | WORD | Varies
10195
+ * 0x04 | Signature | BYTEx6 | ASCII for "LENOVO"
10196
+ * 0x0A | OEM struct offset | BYTE | 0x0B
10197
+ * 0x0B | OEM struct number | BYTE | 0x07, for this structure
10198
+ * 0x0C | OEM struct revision | BYTE | 0x01, for this format
10199
+ * 0x0D | ECP version ID | STR ID |
10200
+ * 0x0E | ECP release date | STR ID |
10201
+ */
10202
+
10203
+ /* Return if data structure not match */
10204
+ if (dm->type != 140 || dm->length < 0x0F ||
10205
+ memcmp(dmi_data + 4, "LENOVO", 6) != 0 ||
10206
+ dmi_data[0x0A] != 0x0B || dmi_data[0x0B] != 0x07 ||
10207
+ dmi_data[0x0C] != 0x01)
10208
+ return;
10209
+
10210
+ /* fwstr is the first 8byte string */
10211
+ strncpy(ec_fw_string, dmi_data + 0x0F, 8);
10212
+}
10213
+
996110214 /* returns 0 - probe ok, or < 0 - probe error.
996210215 * Probe ok doesn't mean thinkpad found.
996310216 * On error, kfree() cleanup on tp->* is not performed, caller must do it */
....@@ -9965,7 +10218,7 @@
996510218 struct thinkpad_id_data *tp)
996610219 {
996710220 const struct dmi_device *dev = NULL;
9968
- char ec_fw_string[18];
10221
+ char ec_fw_string[18] = {0};
996910222 char const *s;
997010223 char t;
997110224
....@@ -9997,7 +10250,7 @@
999710250 * X32 or newer, all Z series; Some models must have an
999810251 * up-to-date BIOS or they will not be detected.
999910252 *
10000
- * See http://thinkwiki.org/wiki/List_of_DMI_IDs
10253
+ * See https://thinkwiki.org/wiki/List_of_DMI_IDs
1000110254 */
1000210255 while ((dev = dmi_find_device(DMI_DEV_TYPE_OEM_STRING, NULL, dev))) {
1000310256 if (sscanf(dev->name,
....@@ -10005,20 +10258,25 @@
1000510258 ec_fw_string) == 1) {
1000610259 ec_fw_string[sizeof(ec_fw_string) - 1] = 0;
1000710260 ec_fw_string[strcspn(ec_fw_string, " ]")] = 0;
10008
-
10009
- tp->ec_version_str = kstrdup(ec_fw_string, GFP_KERNEL);
10010
- if (!tp->ec_version_str)
10011
- return -ENOMEM;
10012
-
10013
- t = tpacpi_parse_fw_id(ec_fw_string,
10014
- &tp->ec_model, &tp->ec_release);
10015
- if (t != 'H') {
10016
- pr_notice("ThinkPad firmware release %s doesn't match the known patterns\n",
10017
- ec_fw_string);
10018
- pr_notice("please report this to %s\n",
10019
- TPACPI_MAIL);
10020
- }
1002110261 break;
10262
+ }
10263
+ }
10264
+
10265
+ /* Newer ThinkPads have different EC program info table */
10266
+ if (!ec_fw_string[0])
10267
+ dmi_walk(find_new_ec_fwstr, &ec_fw_string);
10268
+
10269
+ if (ec_fw_string[0]) {
10270
+ tp->ec_version_str = kstrdup(ec_fw_string, GFP_KERNEL);
10271
+ if (!tp->ec_version_str)
10272
+ return -ENOMEM;
10273
+
10274
+ t = tpacpi_parse_fw_id(ec_fw_string,
10275
+ &tp->ec_model, &tp->ec_release);
10276
+ if (t != 'H') {
10277
+ pr_notice("ThinkPad firmware release %s doesn't match the known patterns\n",
10278
+ ec_fw_string);
10279
+ pr_notice("please report this to %s\n", TPACPI_MAIL);
1002210280 }
1002310281 }
1002410282
....@@ -10174,6 +10432,14 @@
1017410432 .init = tpacpi_battery_init,
1017510433 .data = &battery_driver_data,
1017610434 },
10435
+ {
10436
+ .init = tpacpi_lcdshadow_init,
10437
+ .data = &lcdshadow_driver_data,
10438
+ },
10439
+ {
10440
+ .init = tpacpi_dytc_init,
10441
+ .data = &dytc_driver_data,
10442
+ },
1017710443 };
1017810444
1017910445 static int __init set_ibm_param(const char *val, const struct kernel_param *kp)
....@@ -10192,10 +10458,9 @@
1019210458 continue;
1019310459
1019410460 if (strcmp(ibm->name, kp->name) == 0 && ibm->write) {
10195
- if (strlen(val) > sizeof(ibms_init[i].param) - 2)
10461
+ if (strlen(val) > sizeof(ibms_init[i].param) - 1)
1019610462 return -ENOSPC;
1019710463 strcpy(ibms_init[i].param, val);
10198
- strcat(ibms_init[i].param, ",");
1019910464 return 0;
1020010465 }
1020110466 }
....@@ -10233,7 +10498,7 @@
1023310498
1023410499 module_param_named(volume_capabilities, volume_capabilities, uint, 0444);
1023510500 MODULE_PARM_DESC(volume_capabilities,
10236
- "Selects the mixer capabilites: 0=auto, 1=volume and mute, 2=mute only");
10501
+ "Selects the mixer capabilities: 0=auto, 1=volume and mute, 2=mute only");
1023710502
1023810503 module_param_named(volume_control, volume_control_allowed, bool, 0444);
1023910504 MODULE_PARM_DESC(volume_control,
....@@ -10508,8 +10773,8 @@
1050810773 /*
1050910774 * DMI matching for module autoloading
1051010775 *
10511
- * See http://thinkwiki.org/wiki/List_of_DMI_IDs
10512
- * See http://thinkwiki.org/wiki/BIOS_Upgrade_Downloads
10776
+ * See https://thinkwiki.org/wiki/List_of_DMI_IDs
10777
+ * See https://thinkwiki.org/wiki/BIOS_Upgrade_Downloads
1051310778 *
1051410779 * Only models listed in thinkwiki will be supported, so add yours
1051510780 * if it is not there yet.