diff options
| author | Peter Lekensteyn <lekensteyn@gmail.com> | 2011-12-17 06:53:43 -0500 |
|---|---|---|
| committer | Dave Airlie <airlied@redhat.com> | 2012-01-13 04:09:07 -0500 |
| commit | 9075e85f46c598e4dfc852b16b256a32e2fb396f (patch) | |
| tree | 841922a76fb85d8cbcaa7d6f64b5ea6c4d067370 /drivers/gpu | |
| parent | 3b32a592ea6e49145d4dc610b85dd9042226896d (diff) | |
nouveau: properly check for _DSM function support
According to the ACPI spec version 4, section 9.14.1, _DSM functions
must return a value with the first bit enabled if any DSM functions are
supported for the given UUID and revision ID. For a given function index n
to be marked supported, bit n must be enabled.
Signed-off-by: Peter Lekensteyn <lekensteyn@gmail.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu')
| -rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_acpi.c | 35 |
1 files changed, 22 insertions, 13 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c index 525744d593c1..96756d0d6411 100644 --- a/drivers/gpu/drm/nouveau/nouveau_acpi.c +++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c | |||
| @@ -18,12 +18,6 @@ | |||
| 18 | 18 | ||
| 19 | #include <linux/vga_switcheroo.h> | 19 | #include <linux/vga_switcheroo.h> |
| 20 | 20 | ||
| 21 | #define NOUVEAU_DSM_SUPPORTED 0x00 | ||
| 22 | #define NOUVEAU_DSM_SUPPORTED_FUNCTIONS 0x00 | ||
| 23 | |||
| 24 | #define NOUVEAU_DSM_ACTIVE 0x01 | ||
| 25 | #define NOUVEAU_DSM_ACTIVE_QUERY 0x00 | ||
| 26 | |||
| 27 | #define NOUVEAU_DSM_LED 0x02 | 21 | #define NOUVEAU_DSM_LED 0x02 |
| 28 | #define NOUVEAU_DSM_LED_STATE 0x00 | 22 | #define NOUVEAU_DSM_LED_STATE 0x00 |
| 29 | #define NOUVEAU_DSM_LED_OFF 0x10 | 23 | #define NOUVEAU_DSM_LED_OFF 0x10 |
| @@ -35,6 +29,7 @@ | |||
| 35 | #define NOUVEAU_DSM_POWER_SPEED 0x01 | 29 | #define NOUVEAU_DSM_POWER_SPEED 0x01 |
| 36 | #define NOUVEAU_DSM_POWER_STAMINA 0x02 | 30 | #define NOUVEAU_DSM_POWER_STAMINA 0x02 |
| 37 | 31 | ||
| 32 | #define NOUVEAU_DSM_OPTIMUS_FN 0x1A | ||
| 38 | static struct nouveau_dsm_priv { | 33 | static struct nouveau_dsm_priv { |
| 39 | bool dsm_detected; | 34 | bool dsm_detected; |
| 40 | bool optimus_detected; | 35 | bool optimus_detected; |
| @@ -148,6 +143,23 @@ static int nouveau_dsm(acpi_handle handle, int func, int arg, uint32_t *result) | |||
| 148 | return 0; | 143 | return 0; |
| 149 | } | 144 | } |
| 150 | 145 | ||
| 146 | /* Returns 1 if a DSM function is usable and 0 otherwise */ | ||
| 147 | static int nouveau_test_dsm(acpi_handle test_handle, | ||
| 148 | int (*dsm_func)(acpi_handle, int, int, uint32_t *), | ||
| 149 | int sfnc) | ||
| 150 | { | ||
| 151 | u32 result = 0; | ||
| 152 | |||
| 153 | /* Function 0 returns a Buffer containing available functions. The args | ||
| 154 | * parameter is ignored for function 0, so just put 0 in it */ | ||
| 155 | if (dsm_func(test_handle, 0, 0, &result)) | ||
| 156 | return 0; | ||
| 157 | |||
| 158 | /* ACPI Spec v4 9.14.1: if bit 0 is zero, no function is supported. If | ||
| 159 | * the n-th bit is enabled, function n is supported */ | ||
| 160 | return result & 1 && result & (1 << sfnc); | ||
| 161 | } | ||
| 162 | |||
| 151 | static int nouveau_dsm_switch_mux(acpi_handle handle, int mux_id) | 163 | static int nouveau_dsm_switch_mux(acpi_handle handle, int mux_id) |
| 152 | { | 164 | { |
| 153 | mxm_wmi_call_mxmx(mux_id == NOUVEAU_DSM_LED_STAMINA ? MXM_MXDS_ADAPTER_IGD : MXM_MXDS_ADAPTER_0); | 165 | mxm_wmi_call_mxmx(mux_id == NOUVEAU_DSM_LED_STAMINA ? MXM_MXDS_ADAPTER_IGD : MXM_MXDS_ADAPTER_0); |
| @@ -212,8 +224,7 @@ static int nouveau_dsm_pci_probe(struct pci_dev *pdev) | |||
| 212 | { | 224 | { |
| 213 | acpi_handle dhandle, nvidia_handle; | 225 | acpi_handle dhandle, nvidia_handle; |
| 214 | acpi_status status; | 226 | acpi_status status; |
| 215 | int ret, retval = 0; | 227 | int retval = 0; |
| 216 | uint32_t result; | ||
| 217 | 228 | ||
| 218 | dhandle = DEVICE_ACPI_HANDLE(&pdev->dev); | 229 | dhandle = DEVICE_ACPI_HANDLE(&pdev->dev); |
| 219 | if (!dhandle) | 230 | if (!dhandle) |
| @@ -224,13 +235,11 @@ static int nouveau_dsm_pci_probe(struct pci_dev *pdev) | |||
| 224 | return false; | 235 | return false; |
| 225 | } | 236 | } |
| 226 | 237 | ||
| 227 | ret = nouveau_dsm(dhandle, NOUVEAU_DSM_SUPPORTED, | 238 | if (nouveau_test_dsm(dhandle, nouveau_dsm, NOUVEAU_DSM_POWER)) |
| 228 | NOUVEAU_DSM_SUPPORTED_FUNCTIONS, &result); | ||
| 229 | if (ret == 0) | ||
| 230 | retval |= NOUVEAU_DSM_HAS_MUX; | 239 | retval |= NOUVEAU_DSM_HAS_MUX; |
| 231 | 240 | ||
| 232 | ret = nouveau_optimus_dsm(dhandle, 0, 0, &result); | 241 | if (nouveau_test_dsm(dhandle, nouveau_optimus_dsm, |
| 233 | if (ret == 0) | 242 | NOUVEAU_DSM_OPTIMUS_FN)) |
| 234 | retval |= NOUVEAU_DSM_HAS_OPT; | 243 | retval |= NOUVEAU_DSM_HAS_OPT; |
| 235 | 244 | ||
| 236 | if (retval) | 245 | if (retval) |
