aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform/x86/ideapad-laptop.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/platform/x86/ideapad-laptop.c')
-rw-r--r--drivers/platform/x86/ideapad-laptop.c71
1 files changed, 29 insertions, 42 deletions
diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c
index 37fe0d0448c9..114d95247cdf 100644
--- a/drivers/platform/x86/ideapad-laptop.c
+++ b/drivers/platform/x86/ideapad-laptop.c
@@ -31,32 +31,15 @@
31#include <linux/input.h> 31#include <linux/input.h>
32#include <linux/input/sparse-keymap.h> 32#include <linux/input/sparse-keymap.h>
33 33
34#define IDEAPAD_DEV_CAMERA 0 34#define IDEAPAD_RFKILL_DEV_NUM (3)
35#define IDEAPAD_DEV_WLAN 1
36#define IDEAPAD_DEV_BLUETOOTH 2
37#define IDEAPAD_DEV_3G 3
38#define IDEAPAD_DEV_KILLSW 4
39 35
40struct ideapad_private { 36struct ideapad_private {
41 acpi_handle handle; 37 struct rfkill *rfk[IDEAPAD_RFKILL_DEV_NUM];
42 struct rfkill *rfk[5];
43 struct platform_device *platform_device; 38 struct platform_device *platform_device;
44 struct input_dev *inputdev; 39 struct input_dev *inputdev;
45} *ideapad_priv;
46
47static struct {
48 char *name;
49 int cfgbit;
50 int opcode;
51 int type;
52} ideapad_rfk_data[] = {
53 { "ideapad_camera", 19, 0x1E, NUM_RFKILL_TYPES },
54 { "ideapad_wlan", 18, 0x15, RFKILL_TYPE_WLAN },
55 { "ideapad_bluetooth", 16, 0x17, RFKILL_TYPE_BLUETOOTH },
56 { "ideapad_3g", 17, 0x20, RFKILL_TYPE_WWAN },
57 { "ideapad_killsw", 0, 0, RFKILL_TYPE_WLAN }
58}; 40};
59 41
42static acpi_handle ideapad_handle;
60static bool no_bt_rfkill; 43static bool no_bt_rfkill;
61module_param(no_bt_rfkill, bool, 0444); 44module_param(no_bt_rfkill, bool, 0444);
62MODULE_PARM_DESC(no_bt_rfkill, "No rfkill for bluetooth."); 45MODULE_PARM_DESC(no_bt_rfkill, "No rfkill for bluetooth.");
@@ -176,11 +159,9 @@ static ssize_t show_ideapad_cam(struct device *dev,
176 struct device_attribute *attr, 159 struct device_attribute *attr,
177 char *buf) 160 char *buf)
178{ 161{
179 struct ideapad_private *priv = dev_get_drvdata(dev);
180 acpi_handle handle = priv->handle;
181 unsigned long result; 162 unsigned long result;
182 163
183 if (read_ec_data(handle, 0x1D, &result)) 164 if (read_ec_data(ideapad_handle, 0x1D, &result))
184 return sprintf(buf, "-1\n"); 165 return sprintf(buf, "-1\n");
185 return sprintf(buf, "%lu\n", result); 166 return sprintf(buf, "%lu\n", result);
186} 167}
@@ -189,15 +170,13 @@ static ssize_t store_ideapad_cam(struct device *dev,
189 struct device_attribute *attr, 170 struct device_attribute *attr,
190 const char *buf, size_t count) 171 const char *buf, size_t count)
191{ 172{
192 struct ideapad_private *priv = dev_get_drvdata(dev);
193 acpi_handle handle = priv->handle;
194 int ret, state; 173 int ret, state;
195 174
196 if (!count) 175 if (!count)
197 return 0; 176 return 0;
198 if (sscanf(buf, "%i", &state) != 1) 177 if (sscanf(buf, "%i", &state) != 1)
199 return -EINVAL; 178 return -EINVAL;
200 ret = write_ec_cmd(handle, 0x1E, state); 179 ret = write_ec_cmd(ideapad_handle, 0x1E, state);
201 if (ret < 0) 180 if (ret < 0)
202 return ret; 181 return ret;
203 return count; 182 return count;
@@ -208,16 +187,24 @@ static DEVICE_ATTR(camera_power, 0644, show_ideapad_cam, store_ideapad_cam);
208/* 187/*
209 * Rfkill 188 * Rfkill
210 */ 189 */
190struct ideapad_rfk_data {
191 char *name;
192 int cfgbit;
193 int opcode;
194 int type;
195};
196
197const struct ideapad_rfk_data ideapad_rfk_data[] = {
198 { "ideapad_wlan", 18, 0x15, RFKILL_TYPE_WLAN },
199 { "ideapad_bluetooth", 16, 0x17, RFKILL_TYPE_BLUETOOTH },
200 { "ideapad_3g", 17, 0x20, RFKILL_TYPE_WWAN },
201};
202
211static int ideapad_rfk_set(void *data, bool blocked) 203static int ideapad_rfk_set(void *data, bool blocked)
212{ 204{
213 int device = (unsigned long)data; 205 unsigned long opcode = (unsigned long)data;
214
215 if (device == IDEAPAD_DEV_KILLSW)
216 return -EINVAL;
217 206
218 return write_ec_cmd(ideapad_priv->handle, 207 return write_ec_cmd(ideapad_handle, opcode, !blocked);
219 ideapad_rfk_data[device].opcode,
220 !blocked);
221} 208}
222 209
223static struct rfkill_ops ideapad_rfk_ops = { 210static struct rfkill_ops ideapad_rfk_ops = {
@@ -227,15 +214,14 @@ static struct rfkill_ops ideapad_rfk_ops = {
227static void ideapad_sync_rfk_state(struct acpi_device *adevice) 214static void ideapad_sync_rfk_state(struct acpi_device *adevice)
228{ 215{
229 struct ideapad_private *priv = dev_get_drvdata(&adevice->dev); 216 struct ideapad_private *priv = dev_get_drvdata(&adevice->dev);
230 acpi_handle handle = priv->handle;
231 unsigned long hw_blocked; 217 unsigned long hw_blocked;
232 int i; 218 int i;
233 219
234 if (read_ec_data(handle, 0x23, &hw_blocked)) 220 if (read_ec_data(ideapad_handle, 0x23, &hw_blocked))
235 return; 221 return;
236 hw_blocked = !hw_blocked; 222 hw_blocked = !hw_blocked;
237 223
238 for (i = IDEAPAD_DEV_WLAN; i <= IDEAPAD_DEV_KILLSW; i++) 224 for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++)
239 if (priv->rfk[i]) 225 if (priv->rfk[i])
240 rfkill_set_hw_state(priv->rfk[i], hw_blocked); 226 rfkill_set_hw_state(priv->rfk[i], hw_blocked);
241} 227}
@@ -250,7 +236,7 @@ static int __devinit ideapad_register_rfkill(struct acpi_device *adevice,
250 if (no_bt_rfkill && 236 if (no_bt_rfkill &&
251 (ideapad_rfk_data[dev].type == RFKILL_TYPE_BLUETOOTH)) { 237 (ideapad_rfk_data[dev].type == RFKILL_TYPE_BLUETOOTH)) {
252 /* Force to enable bluetooth when no_bt_rfkill=1 */ 238 /* Force to enable bluetooth when no_bt_rfkill=1 */
253 write_ec_cmd(ideapad_priv->handle, 239 write_ec_cmd(ideapad_handle,
254 ideapad_rfk_data[dev].opcode, 1); 240 ideapad_rfk_data[dev].opcode, 1);
255 return 0; 241 return 0;
256 } 242 }
@@ -261,7 +247,7 @@ static int __devinit ideapad_register_rfkill(struct acpi_device *adevice,
261 if (!priv->rfk[dev]) 247 if (!priv->rfk[dev])
262 return -ENOMEM; 248 return -ENOMEM;
263 249
264 if (read_ec_data(ideapad_priv->handle, ideapad_rfk_data[dev].opcode-1, 250 if (read_ec_data(ideapad_handle, ideapad_rfk_data[dev].opcode-1,
265 &sw_blocked)) { 251 &sw_blocked)) {
266 rfkill_init_sw_state(priv->rfk[dev], 0); 252 rfkill_init_sw_state(priv->rfk[dev], 0);
267 } else { 253 } else {
@@ -414,9 +400,8 @@ static int __devinit ideapad_acpi_add(struct acpi_device *adevice)
414 priv = kzalloc(sizeof(*priv), GFP_KERNEL); 400 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
415 if (!priv) 401 if (!priv)
416 return -ENOMEM; 402 return -ENOMEM;
417 ideapad_priv = priv;
418 priv->handle = adevice->handle;
419 dev_set_drvdata(&adevice->dev, priv); 403 dev_set_drvdata(&adevice->dev, priv);
404 ideapad_handle = adevice->handle;
420 405
421 ret = ideapad_platform_init(priv); 406 ret = ideapad_platform_init(priv);
422 if (ret) 407 if (ret)
@@ -426,9 +411,11 @@ static int __devinit ideapad_acpi_add(struct acpi_device *adevice)
426 if (ret) 411 if (ret)
427 goto input_failed; 412 goto input_failed;
428 413
429 for (i = IDEAPAD_DEV_WLAN; i < IDEAPAD_DEV_KILLSW; i++) { 414 for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++) {
430 if (test_bit(ideapad_rfk_data[i].cfgbit, (unsigned long *)&cfg)) 415 if (test_bit(ideapad_rfk_data[i].cfgbit, (unsigned long *)&cfg))
431 ideapad_register_rfkill(adevice, i); 416 ideapad_register_rfkill(adevice, i);
417 else
418 priv->rfk[i] = NULL;
432 } 419 }
433 ideapad_sync_rfk_state(adevice); 420 ideapad_sync_rfk_state(adevice);
434 421
@@ -446,7 +433,7 @@ static int __devexit ideapad_acpi_remove(struct acpi_device *adevice, int type)
446 struct ideapad_private *priv = dev_get_drvdata(&adevice->dev); 433 struct ideapad_private *priv = dev_get_drvdata(&adevice->dev);
447 int i; 434 int i;
448 435
449 for (i = IDEAPAD_DEV_WLAN; i < IDEAPAD_DEV_KILLSW; i++) 436 for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++)
450 ideapad_unregister_rfkill(adevice, i); 437 ideapad_unregister_rfkill(adevice, i);
451 ideapad_input_exit(priv); 438 ideapad_input_exit(priv);
452 ideapad_platform_exit(priv); 439 ideapad_platform_exit(priv);