For more information, join the team subscribe to the mailing list 
at the bottom of the Launchpad page

    http://launchpad.net/~hybrid-graphics-linux 

Please join this team if you are new by clicking on the "Join 
Team" link at the right of the Launchpad page. It's important to 
have as many users in the community as possible to request for 
appropriate support.

Monday, 28 December 2009

Solution to switch off nvidia card in Linux Asus UL30Vt, UL50V, UL80V

If you are using Linux on an Asus UL30Vt, or Asus UL50Vt or Asus UL80Vt, keep reading...

One of the Linux users has found a solution to switch off the nvidia card in the UL30Vt models,
which by the looks of the DSDT tables, will also work for the UL50Vt and UL80Vt models with nvidia card.

It uses the ACPI P0P1.VGA._OFF method, which is the same for all 3 models.

The code file, "asus_nvidia.c" is derived from "lenovo_acpi.c" by Sylvain Joyeux.

Here is the original post and another one that adds hibernation support:
http://forum.notebookreview.com/showpost.php?p=5663702&postcount=1239
http://forum.notebookreview.com/showpost.php?p=5664880&postcount=1244

asus_nvidia.c
========================================================
#include <acpi/acpi.h>
#include <linux/suspend.h>

MODULE_LICENSE("GPL");

static acpi_handle root_handle;

static int kill_nvidia(void)
{
acpi_status status;
// The device handle
acpi_handle handle;
struct acpi_object_list args;
// For the return value
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };

status = acpi_get_handle(root_handle, "\\_SB.PCI0.P0P1.VGA._OFF", &handle);
if (ACPI_FAILURE(status))
{
printk("%s: cannot get ACPI handle: %s\n", __func__, acpi_format_exception(status));
return -ENOSYS;
}

args.count = 0;
args.pointer = NULL;

status = acpi_evaluate_object(handle, NULL, &args, &buffer);
if (ACPI_FAILURE(status))
{
printk("%s: _OFF method call failed: %s\n", __func__, acpi_format_exception(status));
return -ENOSYS;
}
kfree(buffer.pointer);

printk("%s: disabled the discrete graphics card\n",__func__);
return 0;
}

static int power_event(struct notifier_block *this, unsigned long event,
void *ptr)
{
switch (event) {
case PM_POST_HIBERNATION:
kill_nvidia();
return NOTIFY_DONE;
case PM_POST_SUSPEND:
case PM_HIBERNATION_PREPARE:
case PM_SUSPEND_PREPARE:
default:
return NOTIFY_DONE;
}
}

static struct notifier_block power_notifier = {
.notifier_call = power_event,
};

static int __init asus_nvidia(void)
{
int ret = register_pm_notifier(&power_notifier);
if (ret) return ret;
return kill_nvidia();
}

static void dummy(void)
{
}

module_init(asus_nvidia);
module_exit(dummy);
========================================================

Makefile
========================================================
ifneq ($(KERNELRELEASE),)
obj-m := asus_nvidia.o
else
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)

default:
$(MAKE) -C $(KERNELDIR) M=$(PWD) $(EXTRA_FLAGS) modules

clean:
$(MAKE) -C $(KERNELDIR) M=$(PWD) $(EXTRA_FLAGS) clean

endif
========================================================

To compile it, simply run:

Code:
make
To install it, run as root:
Code:
cp asus_nvidia.ko /lib/modules/`uname -r`/kernel/
depmod
To try it out, run as root:
Code:
modprobe asus_nvidia
To load it on each reboot on Ubuntu, run as root:
Code:
echo asus_nvidia >>/etc/modules
That last step will be different on other distros, e.g., on Gentoo you need to append the module name to /etc/modules.autoload.d/kernel-2.6.


Followers