aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform/x86/samsung-laptop.c
diff options
context:
space:
mode:
authorCorentin Chary <corentincj@iksaif.net>2011-11-26 05:00:03 -0500
committerMatthew Garrett <mjg@redhat.com>2012-03-20 12:02:08 -0400
commit5b80fc40e5c53da2c69382c20cfc2ece19ece9ce (patch)
tree42080e2e731acd938bc56bc0000e6ca99cbab147 /drivers/platform/x86/samsung-laptop.c
parent7e9607118b08bd4e1dae65d56e425e8de7f3da1c (diff)
samsung-laptop: add a small debugfs interface
This allow to call arbitrary sabi commands wihout modifying the driver at all. For example, setting the keyboard backlight brightness to 5 using debugfs interface can be done like that: ; Set the command echo 0x78 > command ; Set the data echo 0x0582 > d0 ; Fill the rest with 0 echo 0 > d1 echo 0 > d2 echo 0 > d3 ; And issue the command cat call Signed-off-by: Corentin Chary <corentincj@iksaif.net> Acked-by: Greg Kroah-Hartman <gregkh@suse.de> Signed-off-by: Matthew Garrett <mjg@redhat.com>
Diffstat (limited to 'drivers/platform/x86/samsung-laptop.c')
-rw-r--r--drivers/platform/x86/samsung-laptop.c147
1 files changed, 147 insertions, 0 deletions
diff --git a/drivers/platform/x86/samsung-laptop.c b/drivers/platform/x86/samsung-laptop.c
index 134444f176e6..d15b6874b1b2 100644
--- a/drivers/platform/x86/samsung-laptop.c
+++ b/drivers/platform/x86/samsung-laptop.c
@@ -22,6 +22,8 @@
22#include <linux/platform_device.h> 22#include <linux/platform_device.h>
23#include <linux/rfkill.h> 23#include <linux/rfkill.h>
24#include <linux/acpi.h> 24#include <linux/acpi.h>
25#include <linux/seq_file.h>
26#include <linux/debugfs.h>
25 27
26/* 28/*
27 * This driver is needed because a number of Samsung laptops do not hook 29 * This driver is needed because a number of Samsung laptops do not hook
@@ -226,6 +228,35 @@ static const struct sabi_config sabi_configs[] = {
226 { }, 228 { },
227}; 229};
228 230
231/*
232 * samsung-laptop/ - debugfs root directory
233 * f0000_segment - dump f0000 segment
234 * command - current command
235 * data - current data
236 * d0, d1, d2, d3 - data fields
237 * call - call SABI using command and data
238 *
239 * This allow to call arbitrary sabi commands wihout
240 * modifying the driver at all.
241 * For example, setting the keyboard backlight brightness to 5
242 *
243 * echo 0x78 > command
244 * echo 0x0582 > d0
245 * echo 0 > d1
246 * echo 0 > d2
247 * echo 0 > d3
248 * cat call
249 */
250
251struct samsung_laptop_debug {
252 struct dentry *root;
253 struct sabi_data data;
254 u16 command;
255
256 struct debugfs_blob_wrapper f0000_wrapper;
257 struct debugfs_blob_wrapper data_wrapper;
258};
259
229struct samsung_laptop { 260struct samsung_laptop {
230 const struct sabi_config *config; 261 const struct sabi_config *config;
231 262
@@ -239,6 +270,8 @@ struct samsung_laptop {
239 struct backlight_device *backlight_device; 270 struct backlight_device *backlight_device;
240 struct rfkill *rfk; 271 struct rfkill *rfk;
241 272
273 struct samsung_laptop_debug debug;
274
242 bool handle_backlight; 275 bool handle_backlight;
243 bool has_stepping_quirk; 276 bool has_stepping_quirk;
244}; 277};
@@ -680,6 +713,113 @@ static int __init samsung_sysfs_init(struct samsung_laptop *samsung)
680 713
681} 714}
682 715
716static int show_call(struct seq_file *m, void *data)
717{
718 struct samsung_laptop *samsung = m->private;
719 struct sabi_data *sdata = &samsung->debug.data;
720 int ret;
721
722 seq_printf(m, "SABI 0x%04x {0x%08x, 0x%08x, 0x%04x, 0x%02x}\n",
723 samsung->debug.command,
724 sdata->d0, sdata->d1, sdata->d2, sdata->d3);
725
726 ret = sabi_command(samsung, samsung->debug.command, sdata, sdata);
727
728 if (ret) {
729 seq_printf(m, "SABI command 0x%04x failed\n",
730 samsung->debug.command);
731 return ret;
732 }
733
734 seq_printf(m, "SABI {0x%08x, 0x%08x, 0x%04x, 0x%02x}\n",
735 sdata->d0, sdata->d1, sdata->d2, sdata->d3);
736 return 0;
737}
738
739static int samsung_debugfs_open(struct inode *inode, struct file *file)
740{
741 return single_open(file, show_call, inode->i_private);
742}
743
744static const struct file_operations samsung_laptop_call_io_ops = {
745 .owner = THIS_MODULE,
746 .open = samsung_debugfs_open,
747 .read = seq_read,
748 .llseek = seq_lseek,
749 .release = single_release,
750};
751
752static void samsung_debugfs_exit(struct samsung_laptop *samsung)
753{
754 debugfs_remove_recursive(samsung->debug.root);
755}
756
757static int samsung_debugfs_init(struct samsung_laptop *samsung)
758{
759 struct dentry *dent;
760
761 samsung->debug.root = debugfs_create_dir("samsung-laptop", NULL);
762 if (!samsung->debug.root) {
763 pr_err("failed to create debugfs directory");
764 goto error_debugfs;
765 }
766
767 samsung->debug.f0000_wrapper.data = samsung->f0000_segment;
768 samsung->debug.f0000_wrapper.size = 0xffff;
769
770 samsung->debug.data_wrapper.data = &samsung->debug.data;
771 samsung->debug.data_wrapper.size = sizeof(samsung->debug.data);
772
773 dent = debugfs_create_u16("command", S_IRUGO | S_IWUSR,
774 samsung->debug.root, &samsung->debug.command);
775 if (!dent)
776 goto error_debugfs;
777
778 dent = debugfs_create_u32("d0", S_IRUGO | S_IWUSR, samsung->debug.root,
779 &samsung->debug.data.d0);
780 if (!dent)
781 goto error_debugfs;
782
783 dent = debugfs_create_u32("d1", S_IRUGO | S_IWUSR, samsung->debug.root,
784 &samsung->debug.data.d1);
785 if (!dent)
786 goto error_debugfs;
787
788 dent = debugfs_create_u16("d2", S_IRUGO | S_IWUSR, samsung->debug.root,
789 &samsung->debug.data.d2);
790 if (!dent)
791 goto error_debugfs;
792
793 dent = debugfs_create_u8("d3", S_IRUGO | S_IWUSR, samsung->debug.root,
794 &samsung->debug.data.d3);
795 if (!dent)
796 goto error_debugfs;
797
798 dent = debugfs_create_blob("data", S_IRUGO | S_IWUSR,
799 samsung->debug.root,
800 &samsung->debug.data_wrapper);
801 if (!dent)
802 goto error_debugfs;
803
804 dent = debugfs_create_blob("f0000_segment", S_IRUSR | S_IWUSR,
805 samsung->debug.root,
806 &samsung->debug.f0000_wrapper);
807 if (!dent)
808 goto error_debugfs;
809
810 dent = debugfs_create_file("call", S_IFREG | S_IRUGO,
811 samsung->debug.root, samsung,
812 &samsung_laptop_call_io_ops);
813 if (!dent)
814 goto error_debugfs;
815
816 return 0;
817
818error_debugfs:
819 samsung_debugfs_exit(samsung);
820 return -ENOMEM;
821}
822
683static void samsung_sabi_exit(struct samsung_laptop *samsung) 823static void samsung_sabi_exit(struct samsung_laptop *samsung)
684{ 824{
685 const struct sabi_config *config = samsung->config; 825 const struct sabi_config *config = samsung->config;
@@ -1123,9 +1263,15 @@ static int __init samsung_init(void)
1123 if (ret) 1263 if (ret)
1124 goto error_rfkill; 1264 goto error_rfkill;
1125 1265
1266 ret = samsung_debugfs_init(samsung);
1267 if (ret)
1268 goto error_debugfs;
1269
1126 samsung_platform_device = samsung->platform_device; 1270 samsung_platform_device = samsung->platform_device;
1127 return ret; 1271 return ret;
1128 1272
1273error_debugfs:
1274 samsung_rfkill_exit(samsung);
1129error_rfkill: 1275error_rfkill:
1130 samsung_backlight_exit(samsung); 1276 samsung_backlight_exit(samsung);
1131error_backlight: 1277error_backlight:
@@ -1145,6 +1291,7 @@ static void __exit samsung_exit(void)
1145 1291
1146 samsung = platform_get_drvdata(samsung_platform_device); 1292 samsung = platform_get_drvdata(samsung_platform_device);
1147 1293
1294 samsung_debugfs_exit(samsung);
1148 samsung_rfkill_exit(samsung); 1295 samsung_rfkill_exit(samsung);
1149 samsung_backlight_exit(samsung); 1296 samsung_backlight_exit(samsung);
1150 samsung_sysfs_exit(samsung); 1297 samsung_sysfs_exit(samsung);