aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform
diff options
context:
space:
mode:
authorIke Panhc <ike.pan@canonical.com>2010-10-01 03:39:49 -0400
committerMatthew Garrett <mjg@redhat.com>2010-10-21 09:36:50 -0400
commit2b7266bd49efc84f6642cf9bb7fb37d286345d15 (patch)
tree024771a34a04b365ee6114b98104c73d43c866d9 /drivers/platform
parent26c81d5c9a88af404a5fef43caa259e8637fec94 (diff)
ideapad: rewrite the hw rfkill notify
1. Read hw rfkill status by ec command 2. Not to touch sw status of each rfkill when hw rfkill notify 3. Initial rfkill status when module loaded Signed-off-by: Ike Panhc <ike.pan@canonical.com> Signed-off-by: Matthew Garrett <mjg@redhat.com>
Diffstat (limited to 'drivers/platform')
-rw-r--r--drivers/platform/x86/ideapad_acpi.c53
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
163static 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
189static int ideapad_dev_set_state(int device, int state) 163static 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 = {
253static void ideapad_sync_rfk_state(struct acpi_device *adevice) 227static 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
271static int ideapad_register_rfkill(struct acpi_device *adevice, int dev) 243static 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]);