Commit 6c3a69b2 authored by Vincent Cheng's avatar Vincent Cheng

Imported Upstream version 0.6

parent 79a28a3a
......@@ -5,3 +5,5 @@ Module.symvers
*.mod.c
*.o
modules.order
bbswitch-*.tar.gz
.*.sw*
This diff is collapsed.
Version 0.6 - 19 March 2013
* Add workaround for Linux 3.8 regression (not present in earlier or latter
versions) that prevented the video card from turned off unless a driver was
loaded before.
* Compatibility with grsec patches.
* Add 'skip_optimus_dsm' module option so users of Lenovo T410s can use bbswitch
by setting this option to true.
* Clarify license (GPLv3).
Version 0.5 - 22 October 2012
* Improved compatibility with older DKMS versions.
......
......@@ -94,6 +94,9 @@ same behavior as:
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`.
The Lenovo T410s laptop needs the module option `skip_optimus_dsm=1`, otherwise
it will detect the wrong methods which result in the card not being disabled.
### Disable card on boot
These options can be useful to disable the card on boot time. Depending on your
......
......@@ -9,6 +9,20 @@
* Get status
* # cat /proc/acpi/bbswitch
*/
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/pci.h>
......@@ -19,7 +33,7 @@
#include <linux/seq_file.h>
#include <linux/pm_runtime.h>
#define BBSWITCH_VERSION "0.5"
#define BBSWITCH_VERSION "0.6"
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Toggle the discrete graphics card");
......@@ -38,6 +52,9 @@ module_param(load_state, int, 0400);
static int unload_state = CARD_UNCHANGED;
MODULE_PARM_DESC(unload_state, "Card state on unload (0 = off, 1 = on, -1 = unchanged)");
module_param(unload_state, int, 0600);
static bool skip_optimus_dsm = false;
MODULE_PARM_DESC(skip_optimus_dsm, "Skip probe of Optimus discrete DSM (default = false)");
module_param(skip_optimus_dsm, bool, 0400);
extern struct proc_dir_entry *acpi_root_dir;
......@@ -69,8 +86,6 @@ static int dsm_type = DSM_TYPE_UNSUPPORTED;
static struct pci_dev *dis_dev;
static acpi_handle dis_handle;
/* used for keeping the PM event handler */
static struct notifier_block nb;
/* whether the card was off before suspend or not; on: 0, off: 1 */
static int dis_before_suspend_disabled;
......@@ -235,6 +250,20 @@ static void bbswitch_off(void) {
pci_save_state(dis_dev);
pci_clear_master(dis_dev);
pci_disable_device(dis_dev);
do {
struct acpi_device *ad = NULL;
int r;
r = acpi_bus_get_device(dis_handle, &ad);
if (r || !ad) {
pr_warn("Cannot get ACPI device for PCI device\n");
break;
}
if (ad->power.state == ACPI_STATE_UNKNOWN) {
pr_debug("ACPI power state is unknown, forcing D0\n");
ad->power.state = ACPI_STATE_D0;
}
} while (0);
pci_set_power_state(dis_dev, PCI_D3cold);
if (bbswitch_acpi_off())
......@@ -344,6 +373,10 @@ static struct file_operations bbswitch_fops = {
.release= single_release
};
static struct notifier_block nb = {
.notifier_call = &bbswitch_pm_handler
};
static int __init bbswitch_init(void) {
struct proc_dir_entry *acpi_entry;
struct pci_dev *pdev = NULL;
......@@ -387,7 +420,8 @@ static int __init bbswitch_init(void) {
return -ENODEV;
}
if (has_dsm_func(acpi_optimus_dsm_muid, 0x100, 0x1A)) {
if (!skip_optimus_dsm &&
has_dsm_func(acpi_optimus_dsm_muid, 0x100, 0x1A)) {
dsm_type = DSM_TYPE_OPTIMUS;
pr_info("detected an Optimus _DSM function\n");
} else if (has_dsm_func(acpi_nvidia_dsm_muid, 0x102, 0x3)) {
......@@ -425,7 +459,6 @@ static int __init bbswitch_init(void) {
dis_dev_put();
nb.notifier_call = &bbswitch_pm_handler;
register_pm_notifier(&nb);
return 0;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment