platform/x86: intel_pmc_core: fix: Replace dev_dbg macro with dev_info()
[sfrench/cifs-2.6.git] / drivers / platform / x86 / toshiba_bluetooth.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Toshiba Bluetooth Enable Driver
4  *
5  * Copyright (C) 2009 Jes Sorensen <Jes.Sorensen@gmail.com>
6  * Copyright (C) 2015 Azael Avalos <coproscefalo@gmail.com>
7  *
8  * Thanks to Matthew Garrett for background info on ACPI innards which
9  * normal people aren't meant to understand :-)
10  */
11
12 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
13
14 #include <linux/kernel.h>
15 #include <linux/module.h>
16 #include <linux/init.h>
17 #include <linux/types.h>
18 #include <linux/acpi.h>
19 #include <linux/rfkill.h>
20
21 #define BT_KILLSWITCH_MASK      0x01
22 #define BT_PLUGGED_MASK         0x40
23 #define BT_POWER_MASK           0x80
24
25 MODULE_AUTHOR("Jes Sorensen <Jes.Sorensen@gmail.com>");
26 MODULE_DESCRIPTION("Toshiba Laptop ACPI Bluetooth Enable Driver");
27 MODULE_LICENSE("GPL");
28
29 struct toshiba_bluetooth_dev {
30         struct acpi_device *acpi_dev;
31         struct rfkill *rfk;
32
33         bool killswitch;
34         bool plugged;
35         bool powered;
36 };
37
38 static int toshiba_bt_rfkill_add(struct acpi_device *device);
39 static int toshiba_bt_rfkill_remove(struct acpi_device *device);
40 static void toshiba_bt_rfkill_notify(struct acpi_device *device, u32 event);
41
42 static const struct acpi_device_id bt_device_ids[] = {
43         { "TOS6205", 0},
44         { "", 0},
45 };
46 MODULE_DEVICE_TABLE(acpi, bt_device_ids);
47
48 #ifdef CONFIG_PM_SLEEP
49 static int toshiba_bt_resume(struct device *dev);
50 #endif
51 static SIMPLE_DEV_PM_OPS(toshiba_bt_pm, NULL, toshiba_bt_resume);
52
53 static struct acpi_driver toshiba_bt_rfkill_driver = {
54         .name =         "Toshiba BT",
55         .class =        "Toshiba",
56         .ids =          bt_device_ids,
57         .ops =          {
58                                 .add =          toshiba_bt_rfkill_add,
59                                 .remove =       toshiba_bt_rfkill_remove,
60                                 .notify =       toshiba_bt_rfkill_notify,
61                         },
62         .owner =        THIS_MODULE,
63         .drv.pm =       &toshiba_bt_pm,
64 };
65
66 static int toshiba_bluetooth_present(acpi_handle handle)
67 {
68         acpi_status result;
69         u64 bt_present;
70
71         /*
72          * Some Toshiba laptops may have a fake TOS6205 device in
73          * their ACPI BIOS, so query the _STA method to see if there
74          * is really anything there.
75          */
76         result = acpi_evaluate_integer(handle, "_STA", NULL, &bt_present);
77         if (ACPI_FAILURE(result)) {
78                 pr_err("ACPI call to query Bluetooth presence failed\n");
79                 return -ENXIO;
80         }
81
82         if (!bt_present) {
83                 pr_info("Bluetooth device not present\n");
84                 return -ENODEV;
85         }
86
87         return 0;
88 }
89
90 static int toshiba_bluetooth_status(acpi_handle handle)
91 {
92         acpi_status result;
93         u64 status;
94
95         result = acpi_evaluate_integer(handle, "BTST", NULL, &status);
96         if (ACPI_FAILURE(result)) {
97                 pr_err("Could not get Bluetooth device status\n");
98                 return -ENXIO;
99         }
100
101         return status;
102 }
103
104 static int toshiba_bluetooth_enable(acpi_handle handle)
105 {
106         acpi_status result;
107
108         result = acpi_evaluate_object(handle, "AUSB", NULL, NULL);
109         if (ACPI_FAILURE(result)) {
110                 pr_err("Could not attach USB Bluetooth device\n");
111                 return -ENXIO;
112         }
113
114         result = acpi_evaluate_object(handle, "BTPO", NULL, NULL);
115         if (ACPI_FAILURE(result)) {
116                 pr_err("Could not power ON Bluetooth device\n");
117                 return -ENXIO;
118         }
119
120         return 0;
121 }
122
123 static int toshiba_bluetooth_disable(acpi_handle handle)
124 {
125         acpi_status result;
126
127         result = acpi_evaluate_object(handle, "BTPF", NULL, NULL);
128         if (ACPI_FAILURE(result)) {
129                 pr_err("Could not power OFF Bluetooth device\n");
130                 return -ENXIO;
131         }
132
133         result = acpi_evaluate_object(handle, "DUSB", NULL, NULL);
134         if (ACPI_FAILURE(result)) {
135                 pr_err("Could not detach USB Bluetooth device\n");
136                 return -ENXIO;
137         }
138
139         return 0;
140 }
141
142 /* Helper function */
143 static int toshiba_bluetooth_sync_status(struct toshiba_bluetooth_dev *bt_dev)
144 {
145         int status;
146
147         status = toshiba_bluetooth_status(bt_dev->acpi_dev->handle);
148         if (status < 0) {
149                 pr_err("Could not sync bluetooth device status\n");
150                 return status;
151         }
152
153         bt_dev->killswitch = (status & BT_KILLSWITCH_MASK) ? true : false;
154         bt_dev->plugged = (status & BT_PLUGGED_MASK) ? true : false;
155         bt_dev->powered = (status & BT_POWER_MASK) ? true : false;
156
157         pr_debug("Bluetooth status %d killswitch %d plugged %d powered %d\n",
158                  status, bt_dev->killswitch, bt_dev->plugged, bt_dev->powered);
159
160         return 0;
161 }
162
163 /* RFKill handlers */
164 static int bt_rfkill_set_block(void *data, bool blocked)
165 {
166         struct toshiba_bluetooth_dev *bt_dev = data;
167         int ret;
168
169         ret = toshiba_bluetooth_sync_status(bt_dev);
170         if (ret)
171                 return ret;
172
173         if (!bt_dev->killswitch)
174                 return 0;
175
176         if (blocked)
177                 ret = toshiba_bluetooth_disable(bt_dev->acpi_dev->handle);
178         else
179                 ret = toshiba_bluetooth_enable(bt_dev->acpi_dev->handle);
180
181         return ret;
182 }
183
184 static void bt_rfkill_poll(struct rfkill *rfkill, void *data)
185 {
186         struct toshiba_bluetooth_dev *bt_dev = data;
187
188         if (toshiba_bluetooth_sync_status(bt_dev))
189                 return;
190
191         /*
192          * Note the Toshiba Bluetooth RFKill switch seems to be a strange
193          * fish. It only provides a BT event when the switch is flipped to
194          * the 'on' position. When flipping it to 'off', the USB device is
195          * simply pulled away underneath us, without any BT event being
196          * delivered.
197          */
198         rfkill_set_hw_state(bt_dev->rfk, !bt_dev->killswitch);
199 }
200
201 static const struct rfkill_ops rfk_ops = {
202         .set_block = bt_rfkill_set_block,
203         .poll = bt_rfkill_poll,
204 };
205
206 /* ACPI driver functions */
207 static void toshiba_bt_rfkill_notify(struct acpi_device *device, u32 event)
208 {
209         struct toshiba_bluetooth_dev *bt_dev = acpi_driver_data(device);
210
211         if (toshiba_bluetooth_sync_status(bt_dev))
212                 return;
213
214         rfkill_set_hw_state(bt_dev->rfk, !bt_dev->killswitch);
215 }
216
217 #ifdef CONFIG_PM_SLEEP
218 static int toshiba_bt_resume(struct device *dev)
219 {
220         struct toshiba_bluetooth_dev *bt_dev;
221         int ret;
222
223         bt_dev = acpi_driver_data(to_acpi_device(dev));
224
225         ret = toshiba_bluetooth_sync_status(bt_dev);
226         if (ret)
227                 return ret;
228
229         rfkill_set_hw_state(bt_dev->rfk, !bt_dev->killswitch);
230
231         return 0;
232 }
233 #endif
234
235 static int toshiba_bt_rfkill_add(struct acpi_device *device)
236 {
237         struct toshiba_bluetooth_dev *bt_dev;
238         int result;
239
240         result = toshiba_bluetooth_present(device->handle);
241         if (result)
242                 return result;
243
244         pr_info("Toshiba ACPI Bluetooth device driver\n");
245
246         bt_dev = kzalloc(sizeof(*bt_dev), GFP_KERNEL);
247         if (!bt_dev)
248                 return -ENOMEM;
249         bt_dev->acpi_dev = device;
250         device->driver_data = bt_dev;
251         dev_set_drvdata(&device->dev, bt_dev);
252
253         result = toshiba_bluetooth_sync_status(bt_dev);
254         if (result) {
255                 kfree(bt_dev);
256                 return result;
257         }
258
259         bt_dev->rfk = rfkill_alloc("Toshiba Bluetooth",
260                                    &device->dev,
261                                    RFKILL_TYPE_BLUETOOTH,
262                                    &rfk_ops,
263                                    bt_dev);
264         if (!bt_dev->rfk) {
265                 pr_err("Unable to allocate rfkill device\n");
266                 kfree(bt_dev);
267                 return -ENOMEM;
268         }
269
270         rfkill_set_hw_state(bt_dev->rfk, !bt_dev->killswitch);
271
272         result = rfkill_register(bt_dev->rfk);
273         if (result) {
274                 pr_err("Unable to register rfkill device\n");
275                 rfkill_destroy(bt_dev->rfk);
276                 kfree(bt_dev);
277         }
278
279         return result;
280 }
281
282 static int toshiba_bt_rfkill_remove(struct acpi_device *device)
283 {
284         struct toshiba_bluetooth_dev *bt_dev = acpi_driver_data(device);
285
286         /* clean up */
287         if (bt_dev->rfk) {
288                 rfkill_unregister(bt_dev->rfk);
289                 rfkill_destroy(bt_dev->rfk);
290         }
291
292         kfree(bt_dev);
293
294         return toshiba_bluetooth_disable(device->handle);
295 }
296
297 module_acpi_driver(toshiba_bt_rfkill_driver);