12 Commits
v0.2 ... v0.4

4 changed files with 107 additions and 11 deletions

7
.gitignore vendored Normal file
View File

@ -0,0 +1,7 @@
*.cmd
.tmp_versions
Module.symvers
*.ko
*.mod.c
*.o
modules.order

15
NEWS Normal file
View File

@ -0,0 +1,15 @@
Version 0.4 - 15 January 2012
* Support for models that have a "3D controller" instead of "VGA compatible
controller".
Version 0.3 - 14 January 2012
* Support for models that have the nvidia DSM method on the integrated Intel
video card instead of the nvidia one. This includes at the Acer Travelmate
8472TG and Acer Aspire 5745G.
Version 0.2 - 2 January 2012
* Initial release, adding a kernel module that can disable discrete nvidia cards
on Optimus systems.

View File

@ -64,6 +64,43 @@ unload the driver,
$ dmesg |tail -1 $ dmesg |tail -1
bbswitch: device 0000:01:00.0 is in use by driver 'nouveau', refusing OFF bbswitch: device 0000:01:00.0 is in use by driver 'nouveau', refusing OFF
Do **not** attempt to load a driver while the card is off or the card won't be
usable until the PCI configuration space has been recovered (for example, after
writing the contents manually or rebooting).
### Module options
The module has some options that control the behavior on loading and unloading:
`load_state` and `unload_state`. Valid values are `-1`, `0` and `1` meaning "do
not change the card state", "turn the card off" and "turn the card on"
respectively. For example, if you want to have `bbswitch` disable the card
immediately when loading the module while disabling the card on unload, load the
module with:
# modprobe bbswitch load_state=0 unload_state=1
The `unload_state` value can be changed on runtime, the above command yields the
same behavior as:
# modprobe bbswitch load_state=0
# echo 1 | tee /sys/module/bbswitch/parameters/unload_state
If not explictly set, the default behavior is not to change the power state of
the discrete video card which equals to `load_state=-1 unload_state=-1`.
### Disable card on boot
These options can be useful to disable the card on boot time. Depending on your
distribution, `/etc/modules`, `/etc/modules.conf` or some other file can be used
to load modules on boot time. Adding the below line to the file makes the card
get disabled on boot:
bbswitch load_state=0
You have to update your initial ramdisk (initrd) for the changes propagate to
the boot process. On Debian and Ubuntu, this can performed by running
`update-initramfs -u` as root.
Reporting bugs Reporting bugs
-------------- --------------
@ -73,6 +110,21 @@ issues on this module in the issue tracker and provide the following details:
- The output of `dmesg | grep -C 10 bbswitch:` - The output of `dmesg | grep -C 10 bbswitch:`
- The kernel version `uname -a` - The kernel version `uname -a`
- Your distribution and version (if applicable) - Your distribution and version (if applicable)
- The output of `lspci -d10de: -vvv`
- The version of your Xorg and the driver - The version of your Xorg and the driver
- The output of `acpidump` (run it as root, e.g. `sudo acpidump > acpidump.txt`) - Submit your machine information on https://bugs.launchpad.net/bugs/752542;
the instructions are listed in the bug description. Summary: install the
packages containing `dmidecode`, `acpidump` and `iasl` and then run:
wget http://lekensteyn.nl/files/get-acpi-info.sh
sh get-acpi-info.sh
- Information about the ACPI handles associated with PCI devices. Since this is
a kernel module, you'll need kernel headers, gcc and automake. Commands:
git clone git://github.com/Lekensteyn/acpi-stuff.git --depth 1
cd acpi-stuff/acpi_dump_info
make
sudo make load
cat /proc/acpi/dump_info
Upload the generated tarball on the above Launchpad URL and provide a link to
the comment containing your report.

View File

@ -19,7 +19,7 @@
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Toggle the discrete graphics card"); MODULE_DESCRIPTION("Toggle the discrete graphics card");
MODULE_AUTHOR("Peter Lekensteyn <lekensteyn@gmail.com>"); MODULE_AUTHOR("Peter Lekensteyn <lekensteyn@gmail.com>");
MODULE_VERSION("0.2"); MODULE_VERSION("0.4");
enum { enum {
CARD_UNCHANGED = -1, CARD_UNCHANGED = -1,
@ -328,20 +328,33 @@ static struct file_operations bbswitch_fops = {
static int __init bbswitch_init(void) { static int __init bbswitch_init(void) {
struct proc_dir_entry *acpi_entry; struct proc_dir_entry *acpi_entry;
struct pci_dev *pdev = NULL; struct pci_dev *pdev = NULL;
int class = PCI_CLASS_DISPLAY_VGA << 8; acpi_handle igd_handle = NULL;
while ((pdev = pci_get_class(class, pdev)) != NULL) { while ((pdev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pdev)) != NULL) {
struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL }; struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL };
acpi_handle handle; acpi_handle handle;
int pci_class = pdev->class >> 8;
handle = DEVICE_ACPI_HANDLE(&pdev->dev); if (pci_class != PCI_CLASS_DISPLAY_VGA &&
if (!handle) pci_class != PCI_CLASS_DISPLAY_3D)
continue; continue;
if (pdev->vendor != PCI_VENDOR_ID_INTEL) { handle = DEVICE_ACPI_HANDLE(&pdev->dev);
if (!handle) {
printk(KERN_WARNING "bbswitch: cannot find ACPI handle for VGA"
" device %s\n", dev_name(&pdev->dev));
continue;
}
acpi_get_name(handle, ACPI_FULL_PATHNAME, &buf);
if (pdev->vendor == PCI_VENDOR_ID_INTEL) {
igd_handle = handle;
printk(KERN_INFO "bbswitch: Found integrated VGA device %s: %s\n",
dev_name(&pdev->dev), (char *)buf.pointer);
} else {
dis_dev = pdev; dis_dev = pdev;
dis_handle = handle; dis_handle = handle;
acpi_get_name(handle, ACPI_FULL_PATHNAME, &buf);
printk(KERN_INFO "bbswitch: Found discrete VGA device %s: %s\n", printk(KERN_INFO "bbswitch: Found discrete VGA device %s: %s\n",
dev_name(&pdev->dev), (char *)buf.pointer); dev_name(&pdev->dev), (char *)buf.pointer);
} }
@ -359,10 +372,19 @@ static int __init bbswitch_init(void) {
} else if (has_dsm_func(acpi_nvidia_dsm_muid, 0x102, 0x3)) { } else if (has_dsm_func(acpi_nvidia_dsm_muid, 0x102, 0x3)) {
dsm_type = DSM_TYPE_NVIDIA; dsm_type = DSM_TYPE_NVIDIA;
printk(KERN_INFO "bbswitch: detected a nVidia _DSM function\n"); printk(KERN_INFO "bbswitch: detected a nVidia _DSM function\n");
} else {
/* At least two Acer machines are known to use the intel ACPI handle
* with the legacy nvidia DSM */
dis_handle = igd_handle;
if (has_dsm_func(acpi_nvidia_dsm_muid, 0x102, 0x3)) {
dsm_type = DSM_TYPE_NVIDIA;
printk(KERN_INFO "bbswitch: detected a nVidia _DSM function on the"
" integrated video card\n");
} else { } else {
printk(KERN_ERR "bbswitch: No suitable _DSM call found.\n"); printk(KERN_ERR "bbswitch: No suitable _DSM call found.\n");
return -ENODEV; return -ENODEV;
} }
}
acpi_entry = proc_create("bbswitch", 0660, acpi_root_dir, &bbswitch_fops); acpi_entry = proc_create("bbswitch", 0660, acpi_root_dir, &bbswitch_fops);
if (acpi_entry == NULL) { if (acpi_entry == NULL) {