diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9d6c35d --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +*.cmd +.tmp_versions +Module.symvers +*.ko +*.mod.c +*.o +modules.order diff --git a/NEWS b/NEWS new file mode 100644 index 0000000..1d1c033 --- /dev/null +++ b/NEWS @@ -0,0 +1,10 @@ +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. diff --git a/README.md b/README.md index feca059..5376608 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,43 @@ unload the driver, $ dmesg |tail -1 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 -------------- diff --git a/bbswitch.c b/bbswitch.c index dfd634a..7d69dee 100644 --- a/bbswitch.c +++ b/bbswitch.c @@ -19,7 +19,7 @@ MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Toggle the discrete graphics card"); MODULE_AUTHOR("Peter Lekensteyn "); -MODULE_VERSION("0.2"); +MODULE_VERSION("0.3"); enum { CARD_UNCHANGED = -1, @@ -328,6 +328,7 @@ static struct file_operations bbswitch_fops = { static int __init bbswitch_init(void) { struct proc_dir_entry *acpi_entry; struct pci_dev *pdev = NULL; + acpi_handle igd_handle = NULL; int class = PCI_CLASS_DISPLAY_VGA << 8; while ((pdev = pci_get_class(class, pdev)) != NULL) { @@ -338,10 +339,15 @@ static int __init bbswitch_init(void) { if (!handle) continue; - if (pdev->vendor != PCI_VENDOR_ID_INTEL) { + 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_handle = handle; - acpi_get_name(handle, ACPI_FULL_PATHNAME, &buf); printk(KERN_INFO "bbswitch: Found discrete VGA device %s: %s\n", dev_name(&pdev->dev), (char *)buf.pointer); } @@ -360,8 +366,17 @@ static int __init bbswitch_init(void) { dsm_type = DSM_TYPE_NVIDIA; printk(KERN_INFO "bbswitch: detected a nVidia _DSM function\n"); } else { - printk(KERN_ERR "bbswitch: No suitable _DSM call found.\n"); - return -ENODEV; + /* 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 { + printk(KERN_ERR "bbswitch: No suitable _DSM call found.\n"); + return -ENODEV; + } } acpi_entry = proc_create("bbswitch", 0660, acpi_root_dir, &bbswitch_fops);