diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/platform/x86/ideapad_acpi.c | 53 |
1 files changed, 17 insertions, 36 deletions
diff --git a/drivers/platform/x86/ideapad_acpi.c b/drivers/platform/x86/ideapad_acpi.c index e45fc50b93dc..09f6ce6b378d 100644 --- a/drivers/platform/x86/ideapad_acpi.c +++ b/drivers/platform/x86/ideapad_acpi.c | |||
@@ -160,32 +160,6 @@ static int write_ec_cmd(acpi_handle handle, int cmd, unsigned long data) | |||
160 | } | 160 | } |
161 | /* the above is ACPI helpers */ | 161 | /* the above is ACPI helpers */ |
162 | 162 | ||
163 | static int ideapad_dev_get_state(int device) | ||
164 | { | ||
165 | acpi_status status; | ||
166 | union acpi_object in_param; | ||
167 | struct acpi_object_list input = { 1, &in_param }; | ||
168 | struct acpi_buffer output; | ||
169 | union acpi_object out_obj; | ||
170 | |||
171 | output.length = sizeof(out_obj); | ||
172 | output.pointer = &out_obj; | ||
173 | |||
174 | in_param.type = ACPI_TYPE_INTEGER; | ||
175 | in_param.integer.value = device + 1; | ||
176 | |||
177 | status = acpi_evaluate_object(NULL, "\\_SB_.GECN", &input, &output); | ||
178 | if (ACPI_FAILURE(status)) { | ||
179 | printk(KERN_WARNING "IdeaPAD \\_SB_.GECN method failed %d\n", status); | ||
180 | return -ENODEV; | ||
181 | } | ||
182 | if (out_obj.type != ACPI_TYPE_INTEGER) { | ||
183 | printk(KERN_WARNING "IdeaPAD \\_SB_.GECN method returned unexpected type\n"); | ||
184 | return -ENODEV; | ||
185 | } | ||
186 | return out_obj.integer.value; | ||
187 | } | ||
188 | |||
189 | static int ideapad_dev_set_state(int device, int state) | 163 | static int ideapad_dev_set_state(int device, int state) |
190 | { | 164 | { |
191 | acpi_status status; | 165 | acpi_status status; |
@@ -253,32 +227,39 @@ static struct rfkill_ops ideapad_rfk_ops = { | |||
253 | static void ideapad_sync_rfk_state(struct acpi_device *adevice) | 227 | static void ideapad_sync_rfk_state(struct acpi_device *adevice) |
254 | { | 228 | { |
255 | struct ideapad_private *priv = dev_get_drvdata(&adevice->dev); | 229 | struct ideapad_private *priv = dev_get_drvdata(&adevice->dev); |
256 | int hw_blocked = !ideapad_dev_get_state(IDEAPAD_DEV_KILLSW); | 230 | acpi_handle handle = priv->handle; |
231 | unsigned long hw_blocked; | ||
257 | int i; | 232 | int i; |
258 | 233 | ||
259 | rfkill_set_hw_state(priv->rfk[IDEAPAD_DEV_KILLSW], hw_blocked); | 234 | if (read_ec_data(handle, 0x23, &hw_blocked)) |
260 | for (i = IDEAPAD_DEV_WLAN; i < IDEAPAD_DEV_KILLSW; i++) | ||
261 | if (priv->rfk[i]) | ||
262 | rfkill_set_hw_state(priv->rfk[i], hw_blocked); | ||
263 | if (hw_blocked) | ||
264 | return; | 235 | return; |
236 | hw_blocked = !hw_blocked; | ||
265 | 237 | ||
266 | for (i = IDEAPAD_DEV_WLAN; i < IDEAPAD_DEV_KILLSW; i++) | 238 | for (i = IDEAPAD_DEV_WLAN; i <= IDEAPAD_DEV_KILLSW; i++) |
267 | if (priv->rfk[i]) | 239 | if (priv->rfk[i]) |
268 | rfkill_set_sw_state(priv->rfk[i], !ideapad_dev_get_state(i)); | 240 | rfkill_set_hw_state(priv->rfk[i], hw_blocked); |
269 | } | 241 | } |
270 | 242 | ||
271 | static int ideapad_register_rfkill(struct acpi_device *adevice, int dev) | 243 | static int ideapad_register_rfkill(struct acpi_device *adevice, int dev) |
272 | { | 244 | { |
273 | struct ideapad_private *priv = dev_get_drvdata(&adevice->dev); | 245 | struct ideapad_private *priv = dev_get_drvdata(&adevice->dev); |
274 | int ret; | 246 | int ret; |
247 | unsigned long sw_blocked; | ||
275 | 248 | ||
276 | priv->rfk[dev] = rfkill_alloc(ideapad_rfk_data[dev-1].name, &adevice->dev, | 249 | priv->rfk[dev] = rfkill_alloc(ideapad_rfk_data[dev].name, &adevice->dev, |
277 | ideapad_rfk_data[dev-1].type, &ideapad_rfk_ops, | 250 | ideapad_rfk_data[dev].type, &ideapad_rfk_ops, |
278 | (void *)(long)dev); | 251 | (void *)(long)dev); |
279 | if (!priv->rfk[dev]) | 252 | if (!priv->rfk[dev]) |
280 | return -ENOMEM; | 253 | return -ENOMEM; |
281 | 254 | ||
255 | if (read_ec_data(ideapad_priv->handle, ideapad_rfk_data[dev].opcode-1, | ||
256 | &sw_blocked)) { | ||
257 | rfkill_init_sw_state(priv->rfk[dev], 0); | ||
258 | } else { | ||
259 | sw_blocked = !sw_blocked; | ||
260 | rfkill_init_sw_state(priv->rfk[dev], sw_blocked); | ||
261 | } | ||
262 | |||
282 | ret = rfkill_register(priv->rfk[dev]); | 263 | ret = rfkill_register(priv->rfk[dev]); |
283 | if (ret) { | 264 | if (ret) { |
284 | rfkill_destroy(priv->rfk[dev]); | 265 | rfkill_destroy(priv->rfk[dev]); |