Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Apple Gmux DebugFS
diff -uprN linux-3.16.1-org/drivers/platform/x86/apple-gmux.c linux-3.16.1-patched/drivers/platform/x86/apple-gmux.c
--- a/drivers/platform/x86/apple-gmux.c 2014-08-14 04:36:35.000000000 +0200
+++ b/drivers/platform/x86/apple-gmux.c 2014-09-10 17:12:47.000000000 +0200
@@ -22,6 +22,10 @@
#include <linux/delay.h>
#include <linux/pci.h>
#include <linux/vga_switcheroo.h>
+#include <linux/seq_file.h>
+#include <linux/uaccess.h>
+#include <linux/fs.h>
+#include <linux/debugfs.h>
#include <acpi/video.h>
#include <asm/io.h>
@@ -39,10 +43,17 @@ struct apple_gmux_data {
enum vga_switcheroo_client_id resume_client_id;
enum vga_switcheroo_state power_state;
struct completion powerchange_done;
+
+ /*debugfs data*/
+ struct dentry *debugfs_root;
+ struct dentry *switch_file;
};
static struct apple_gmux_data *apple_gmux_data;
+static int apple_gmux_debugfs_init(struct apple_gmux_data *gmux_data);
+static void apple_gmux_debugfs_fini(struct apple_gmux_data *gmux_data);
+
/*
* gmux port offsets. Many of these are not yet used, but may be in the
* future, and it's useful to have them documented here anyhow.
@@ -560,6 +571,7 @@ static int gmux_probe(struct pnp_dev *pn
init_completion(&gmux_data->powerchange_done);
apple_gmux_data = gmux_data;
gmux_enable_interrupts(gmux_data);
+ apple_gmux_debugfs_init(gmux_data);
return 0;
@@ -584,6 +596,8 @@ static void gmux_remove(struct pnp_dev *
{
struct apple_gmux_data *gmux_data = pnp_get_drvdata(pnp);
+ apple_gmux_debugfs_fini(gmux_data);
+
vga_switcheroo_unregister_handler();
gmux_disable_interrupts(gmux_data);
if (gmux_data->gpe >= 0) {
@@ -604,6 +618,94 @@ static void gmux_remove(struct pnp_dev *
apple_bl_register();
}
+static int apple_gmux_show(struct seq_file *m, void *v)
+{
+ seq_printf(m, "Active Device: %s\nDiscrete Powered: %s\n",
+ gmux_active_client(apple_gmux_data) == VGA_SWITCHEROO_DIS ? "DIS" : "IGD",
+ apple_gmux_data->power_state == VGA_SWITCHEROO_ON ? "ON" : "OFF"
+ );
+ return 0;
+}
+
+static int apple_gmux_debugfs_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, apple_gmux_show, NULL);
+}
+
+static ssize_t
+apple_gmux_debugfs_write(struct file *filp, const char __user *ubuf,
+ size_t cnt, loff_t *ppos)
+{
+ char usercmd[64];
+ if (cnt > 63)
+ cnt = 63;
+
+ if (copy_from_user(usercmd, ubuf, cnt))
+ return -EFAULT;
+
+ /*switch to IGD*/
+ if (strncmp(usercmd, "IGD", 3) == 0)
+ gmux_switchto(VGA_SWITCHEROO_IGD);
+
+ /*switch to DIS*/
+ if (strncmp(usercmd, "DIS", 3) == 0)
+ gmux_switchto(VGA_SWITCHEROO_DIS);
+
+ /*change power state*/
+ if (strncmp(usercmd, "OFF", 3) == 0)
+ gmux_set_discrete_state(apple_gmux_data, VGA_SWITCHEROO_OFF);
+
+ if (strncmp(usercmd, "ON", 2) == 0)
+ gmux_set_discrete_state(apple_gmux_data, VGA_SWITCHEROO_ON);
+
+ return cnt;
+}
+
+static const struct file_operations apple_gmux_debugfs_fops = {
+ .owner = THIS_MODULE,
+ .open = apple_gmux_debugfs_open,
+ .write = apple_gmux_debugfs_write,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static void apple_gmux_debugfs_fini(struct apple_gmux_data *gmux_data)
+{
+ if (gmux_data->switch_file) {
+ debugfs_remove(gmux_data->switch_file);
+ gmux_data->switch_file = NULL;
+ }
+ if (gmux_data->debugfs_root) {
+ debugfs_remove(gmux_data->debugfs_root);
+ gmux_data->debugfs_root = NULL;
+ }
+}
+
+static int apple_gmux_debugfs_init(struct apple_gmux_data *gmux_data)
+{
+ /* already initialised */
+ if (gmux_data->debugfs_root)
+ return 0;
+ gmux_data->debugfs_root = debugfs_create_dir("applegmux", NULL);
+
+ if (!gmux_data->debugfs_root) {
+ printk(KERN_ERR "apple_gmux: Cannot create /sys/kernel/debug/applegmux\n");
+ goto fail;
+ }
+
+ gmux_data->switch_file = debugfs_create_file("switch", 0644,
+ gmux_data->debugfs_root, NULL, &apple_gmux_debugfs_fops);
+ if (!gmux_data->switch_file) {
+ printk(KERN_ERR "apple_gmux: cannot create /sys/kernel/debug/applegmux/switch\n");
+ goto fail;
+ }
+ return 0;
+fail:
+ apple_gmux_debugfs_fini(gmux_data);
+ return -1;
+}
+
static const struct pnp_device_id gmux_device_ids[] = {
{"APP000B", 0},
{"", 0}
@GrantWagner
Copy link

GrantWagner commented Oct 6, 2014

I saw your link from the issue list of HA's gmux patchs. I would like to try this on my mbp 11,3. However, a kernel patch and compile is new to me. Do you have same basic instructions as to how I can get started with using this patch?

@jkotzker
Copy link

jkotzker commented Oct 23, 2014

Hi, I'm very excited to use this; any chance you could point me in the right direction for how to apply this patch to my current kernel? I'm new to patching. Thanks.

@masumhabib
Copy link

masumhabib commented Feb 18, 2015

Thanks for the patch. Works like a charm.

@nathanielwarner
Copy link

nathanielwarner commented Jun 1, 2015

Hi- I'm having trouble getting the patch to work (using kernel 4.0.4 from kernel.org). I save the raw text (https://gist.githubusercontent.com/Drakulix/1064a8e18f6feab6a604/raw/4a210c93e0c2099b11c62030e43f05c3275221ad/0001-apple_gmux-Add-sys-debugfs) into a file called "apple-gmux-fix.patch" in the kernel source directory. I run "patch -p1 > apple-gmux-fix.patch" and it reports patching one file successfully. I can compile, install, and boot the kernel normally (https://wiki.archlinux.org/index.php/Kernels/Compilation/Traditional). However, there is no directory "/sys/kernel/debug/apple_gmux". Do you know what I could be doing wrong?

@akatrevorjay
Copy link

akatrevorjay commented May 17, 2016

Hi, have you submitted this to the kernel? It's about time this got released!

@WellDone2094
Copy link

WellDone2094 commented Aug 20, 2016

Hi, i'm trying to apply this patch as well, anyone can help me?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment