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) |