diff options
author | Ike Panhc <ike.pan@canonical.com> | 2011-09-05 14:32:52 -0400 |
---|---|---|
committer | Matthew Garrett <mjg@redhat.com> | 2011-10-24 10:52:39 -0400 |
commit | 773e3206e6a8b4c81826dc76057a96ba3cc96672 (patch) | |
tree | 0287dbaae5700123225bc9681f8984d4f8d466c0 /drivers/platform/x86 | |
parent | f43d9ec06028b8cb122a7a2b367a7af066342918 (diff) |
ideapad: add debugfs support
Add two nodes in debugfs which shows cfg value and its meaning,
and status info read from VPC2004.
Signed-off-by: Ike Panhc <ike.pan@canonical.com>
Signed-off-by: Matthew Garrett <mjg@redhat.com>
Diffstat (limited to 'drivers/platform/x86')
-rw-r--r-- | drivers/platform/x86/ideapad-laptop.c | 152 |
1 files changed, 152 insertions, 0 deletions
diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c index 39a72a8aeb8c..1c8b5065f34c 100644 --- a/drivers/platform/x86/ideapad-laptop.c +++ b/drivers/platform/x86/ideapad-laptop.c | |||
@@ -34,6 +34,8 @@ | |||
34 | #include <linux/input/sparse-keymap.h> | 34 | #include <linux/input/sparse-keymap.h> |
35 | #include <linux/backlight.h> | 35 | #include <linux/backlight.h> |
36 | #include <linux/fb.h> | 36 | #include <linux/fb.h> |
37 | #include <linux/debugfs.h> | ||
38 | #include <linux/seq_file.h> | ||
37 | 39 | ||
38 | #define IDEAPAD_RFKILL_DEV_NUM (3) | 40 | #define IDEAPAD_RFKILL_DEV_NUM (3) |
39 | 41 | ||
@@ -71,10 +73,12 @@ struct ideapad_private { | |||
71 | struct platform_device *platform_device; | 73 | struct platform_device *platform_device; |
72 | struct input_dev *inputdev; | 74 | struct input_dev *inputdev; |
73 | struct backlight_device *blightdev; | 75 | struct backlight_device *blightdev; |
76 | struct dentry *debug; | ||
74 | unsigned long cfg; | 77 | unsigned long cfg; |
75 | }; | 78 | }; |
76 | 79 | ||
77 | static acpi_handle ideapad_handle; | 80 | static acpi_handle ideapad_handle; |
81 | static struct ideapad_private *ideapad_priv; | ||
78 | static bool no_bt_rfkill; | 82 | static bool no_bt_rfkill; |
79 | module_param(no_bt_rfkill, bool, 0444); | 83 | module_param(no_bt_rfkill, bool, 0444); |
80 | MODULE_PARM_DESC(no_bt_rfkill, "No rfkill for bluetooth."); | 84 | MODULE_PARM_DESC(no_bt_rfkill, "No rfkill for bluetooth."); |
@@ -188,6 +192,146 @@ static int write_ec_cmd(acpi_handle handle, int cmd, unsigned long data) | |||
188 | } | 192 | } |
189 | 193 | ||
190 | /* | 194 | /* |
195 | * debugfs | ||
196 | */ | ||
197 | #define DEBUGFS_EVENT_LEN (4096) | ||
198 | static int debugfs_status_show(struct seq_file *s, void *data) | ||
199 | { | ||
200 | unsigned long value; | ||
201 | |||
202 | if (!read_ec_data(ideapad_handle, VPCCMD_R_BL_MAX, &value)) | ||
203 | seq_printf(s, "Backlight max:\t%lu\n", value); | ||
204 | if (!read_ec_data(ideapad_handle, VPCCMD_R_BL, &value)) | ||
205 | seq_printf(s, "Backlight now:\t%lu\n", value); | ||
206 | if (!read_ec_data(ideapad_handle, VPCCMD_R_BL_POWER, &value)) | ||
207 | seq_printf(s, "BL power value:\t%s\n", value ? "On" : "Off"); | ||
208 | seq_printf(s, "=====================\n"); | ||
209 | |||
210 | if (!read_ec_data(ideapad_handle, VPCCMD_R_RF, &value)) | ||
211 | seq_printf(s, "Radio status:\t%s(%lu)\n", | ||
212 | value ? "On" : "Off", value); | ||
213 | if (!read_ec_data(ideapad_handle, VPCCMD_R_WIFI, &value)) | ||
214 | seq_printf(s, "Wifi status:\t%s(%lu)\n", | ||
215 | value ? "On" : "Off", value); | ||
216 | if (!read_ec_data(ideapad_handle, VPCCMD_R_BT, &value)) | ||
217 | seq_printf(s, "BT status:\t%s(%lu)\n", | ||
218 | value ? "On" : "Off", value); | ||
219 | if (!read_ec_data(ideapad_handle, VPCCMD_R_3G, &value)) | ||
220 | seq_printf(s, "3G status:\t%s(%lu)\n", | ||
221 | value ? "On" : "Off", value); | ||
222 | seq_printf(s, "=====================\n"); | ||
223 | |||
224 | if (!read_ec_data(ideapad_handle, VPCCMD_R_TOUCHPAD, &value)) | ||
225 | seq_printf(s, "Touchpad status:%s(%lu)\n", | ||
226 | value ? "On" : "Off", value); | ||
227 | if (!read_ec_data(ideapad_handle, VPCCMD_R_CAMERA, &value)) | ||
228 | seq_printf(s, "Camera status:\t%s(%lu)\n", | ||
229 | value ? "On" : "Off", value); | ||
230 | |||
231 | return 0; | ||
232 | } | ||
233 | |||
234 | static int debugfs_status_open(struct inode *inode, struct file *file) | ||
235 | { | ||
236 | return single_open(file, debugfs_status_show, NULL); | ||
237 | } | ||
238 | |||
239 | static const struct file_operations debugfs_status_fops = { | ||
240 | .owner = THIS_MODULE, | ||
241 | .open = debugfs_status_open, | ||
242 | .read = seq_read, | ||
243 | .llseek = seq_lseek, | ||
244 | .release = single_release, | ||
245 | }; | ||
246 | |||
247 | static int debugfs_cfg_show(struct seq_file *s, void *data) | ||
248 | { | ||
249 | if (!ideapad_priv) { | ||
250 | seq_printf(s, "cfg: N/A\n"); | ||
251 | } else { | ||
252 | seq_printf(s, "cfg: 0x%.8lX\n\nCapability: ", | ||
253 | ideapad_priv->cfg); | ||
254 | if (test_bit(CFG_BT_BIT, &ideapad_priv->cfg)) | ||
255 | seq_printf(s, "Bluetooth "); | ||
256 | if (test_bit(CFG_3G_BIT, &ideapad_priv->cfg)) | ||
257 | seq_printf(s, "3G "); | ||
258 | if (test_bit(CFG_WIFI_BIT, &ideapad_priv->cfg)) | ||
259 | seq_printf(s, "Wireless "); | ||
260 | if (test_bit(CFG_CAMERA_BIT, &ideapad_priv->cfg)) | ||
261 | seq_printf(s, "Camera "); | ||
262 | seq_printf(s, "\nGraphic: "); | ||
263 | switch ((ideapad_priv->cfg)&0x700) { | ||
264 | case 0x100: | ||
265 | seq_printf(s, "Intel"); | ||
266 | break; | ||
267 | case 0x200: | ||
268 | seq_printf(s, "ATI"); | ||
269 | break; | ||
270 | case 0x300: | ||
271 | seq_printf(s, "Nvidia"); | ||
272 | break; | ||
273 | case 0x400: | ||
274 | seq_printf(s, "Intel and ATI"); | ||
275 | break; | ||
276 | case 0x500: | ||
277 | seq_printf(s, "Intel and Nvidia"); | ||
278 | break; | ||
279 | } | ||
280 | seq_printf(s, "\n"); | ||
281 | } | ||
282 | return 0; | ||
283 | } | ||
284 | |||
285 | static int debugfs_cfg_open(struct inode *inode, struct file *file) | ||
286 | { | ||
287 | return single_open(file, debugfs_cfg_show, NULL); | ||
288 | } | ||
289 | |||
290 | static const struct file_operations debugfs_cfg_fops = { | ||
291 | .owner = THIS_MODULE, | ||
292 | .open = debugfs_cfg_open, | ||
293 | .read = seq_read, | ||
294 | .llseek = seq_lseek, | ||
295 | .release = single_release, | ||
296 | }; | ||
297 | |||
298 | static int __devinit ideapad_debugfs_init(struct ideapad_private *priv) | ||
299 | { | ||
300 | struct dentry *node; | ||
301 | |||
302 | priv->debug = debugfs_create_dir("ideapad", NULL); | ||
303 | if (priv->debug == NULL) { | ||
304 | pr_err("failed to create debugfs directory"); | ||
305 | goto errout; | ||
306 | } | ||
307 | |||
308 | node = debugfs_create_file("cfg", S_IRUGO, priv->debug, NULL, | ||
309 | &debugfs_cfg_fops); | ||
310 | if (!node) { | ||
311 | pr_err("failed to create cfg in debugfs"); | ||
312 | goto errout; | ||
313 | } | ||
314 | |||
315 | node = debugfs_create_file("status", S_IRUGO, priv->debug, NULL, | ||
316 | &debugfs_status_fops); | ||
317 | if (!node) { | ||
318 | pr_err("failed to create event in debugfs"); | ||
319 | goto errout; | ||
320 | } | ||
321 | |||
322 | return 0; | ||
323 | |||
324 | errout: | ||
325 | return -ENOMEM; | ||
326 | } | ||
327 | |||
328 | static void ideapad_debugfs_exit(struct ideapad_private *priv) | ||
329 | { | ||
330 | debugfs_remove_recursive(priv->debug); | ||
331 | priv->debug = NULL; | ||
332 | } | ||
333 | |||
334 | /* | ||
191 | * sysfs | 335 | * sysfs |
192 | */ | 336 | */ |
193 | static ssize_t show_ideapad_cam(struct device *dev, | 337 | static ssize_t show_ideapad_cam(struct device *dev, |
@@ -573,6 +717,7 @@ static int __devinit ideapad_acpi_add(struct acpi_device *adevice) | |||
573 | if (!priv) | 717 | if (!priv) |
574 | return -ENOMEM; | 718 | return -ENOMEM; |
575 | dev_set_drvdata(&adevice->dev, priv); | 719 | dev_set_drvdata(&adevice->dev, priv); |
720 | ideapad_priv = priv; | ||
576 | ideapad_handle = adevice->handle; | 721 | ideapad_handle = adevice->handle; |
577 | priv->cfg = cfg; | 722 | priv->cfg = cfg; |
578 | 723 | ||
@@ -580,6 +725,10 @@ static int __devinit ideapad_acpi_add(struct acpi_device *adevice) | |||
580 | if (ret) | 725 | if (ret) |
581 | goto platform_failed; | 726 | goto platform_failed; |
582 | 727 | ||
728 | ret = ideapad_debugfs_init(priv); | ||
729 | if (ret) | ||
730 | goto debugfs_failed; | ||
731 | |||
583 | ret = ideapad_input_init(priv); | 732 | ret = ideapad_input_init(priv); |
584 | if (ret) | 733 | if (ret) |
585 | goto input_failed; | 734 | goto input_failed; |
@@ -605,6 +754,8 @@ backlight_failed: | |||
605 | ideapad_unregister_rfkill(adevice, i); | 754 | ideapad_unregister_rfkill(adevice, i); |
606 | ideapad_input_exit(priv); | 755 | ideapad_input_exit(priv); |
607 | input_failed: | 756 | input_failed: |
757 | ideapad_debugfs_exit(priv); | ||
758 | debugfs_failed: | ||
608 | ideapad_platform_exit(priv); | 759 | ideapad_platform_exit(priv); |
609 | platform_failed: | 760 | platform_failed: |
610 | kfree(priv); | 761 | kfree(priv); |
@@ -620,6 +771,7 @@ static int __devexit ideapad_acpi_remove(struct acpi_device *adevice, int type) | |||
620 | for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++) | 771 | for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++) |
621 | ideapad_unregister_rfkill(adevice, i); | 772 | ideapad_unregister_rfkill(adevice, i); |
622 | ideapad_input_exit(priv); | 773 | ideapad_input_exit(priv); |
774 | ideapad_debugfs_exit(priv); | ||
623 | ideapad_platform_exit(priv); | 775 | ideapad_platform_exit(priv); |
624 | dev_set_drvdata(&adevice->dev, NULL); | 776 | dev_set_drvdata(&adevice->dev, NULL); |
625 | kfree(priv); | 777 | kfree(priv); |