aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/nouveau_acpi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/nouveau/nouveau_acpi.c')
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_acpi.c138
1 files changed, 38 insertions, 100 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c
index ba0183fb84f3..3c149617cfcb 100644
--- a/drivers/gpu/drm/nouveau/nouveau_acpi.c
+++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c
@@ -1,15 +1,10 @@
1#include <linux/pci.h> 1#include <linux/pci.h>
2#include <linux/acpi.h> 2#include <linux/acpi.h>
3#include <linux/slab.h> 3#include <linux/slab.h>
4#include <acpi/acpi_drivers.h>
5#include <acpi/acpi_bus.h>
6#include <acpi/video.h>
7#include <acpi/acpi.h>
8#include <linux/mxm-wmi.h> 4#include <linux/mxm-wmi.h>
9
10#include <linux/vga_switcheroo.h> 5#include <linux/vga_switcheroo.h>
11
12#include <drm/drm_edid.h> 6#include <drm/drm_edid.h>
7#include <acpi/video.h>
13 8
14#include "nouveau_drm.h" 9#include "nouveau_drm.h"
15#include "nouveau_acpi.h" 10#include "nouveau_acpi.h"
@@ -78,124 +73,66 @@ static const char nouveau_op_dsm_muid[] = {
78 73
79static int nouveau_optimus_dsm(acpi_handle handle, int func, int arg, uint32_t *result) 74static int nouveau_optimus_dsm(acpi_handle handle, int func, int arg, uint32_t *result)
80{ 75{
81 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; 76 int i;
82 struct acpi_object_list input;
83 union acpi_object params[4];
84 union acpi_object *obj; 77 union acpi_object *obj;
85 int i, err;
86 char args_buff[4]; 78 char args_buff[4];
79 union acpi_object argv4 = {
80 .buffer.type = ACPI_TYPE_BUFFER,
81 .buffer.length = 4,
82 .buffer.pointer = args_buff
83 };
87 84
88 input.count = 4;
89 input.pointer = params;
90 params[0].type = ACPI_TYPE_BUFFER;
91 params[0].buffer.length = sizeof(nouveau_op_dsm_muid);
92 params[0].buffer.pointer = (char *)nouveau_op_dsm_muid;
93 params[1].type = ACPI_TYPE_INTEGER;
94 params[1].integer.value = 0x00000100;
95 params[2].type = ACPI_TYPE_INTEGER;
96 params[2].integer.value = func;
97 params[3].type = ACPI_TYPE_BUFFER;
98 params[3].buffer.length = 4;
99 /* ACPI is little endian, AABBCCDD becomes {DD,CC,BB,AA} */ 85 /* ACPI is little endian, AABBCCDD becomes {DD,CC,BB,AA} */
100 for (i = 0; i < 4; i++) 86 for (i = 0; i < 4; i++)
101 args_buff[i] = (arg >> i * 8) & 0xFF; 87 args_buff[i] = (arg >> i * 8) & 0xFF;
102 params[3].buffer.pointer = args_buff;
103
104 err = acpi_evaluate_object(handle, "_DSM", &input, &output);
105 if (err) {
106 printk(KERN_INFO "failed to evaluate _DSM: %d\n", err);
107 return err;
108 }
109
110 obj = (union acpi_object *)output.pointer;
111 88
112 if (obj->type == ACPI_TYPE_INTEGER) 89 *result = 0;
113 if (obj->integer.value == 0x80000002) { 90 obj = acpi_evaluate_dsm_typed(handle, nouveau_op_dsm_muid, 0x00000100,
114 return -ENODEV; 91 func, &argv4, ACPI_TYPE_BUFFER);
115 } 92 if (!obj) {
116 93 acpi_handle_info(handle, "failed to evaluate _DSM\n");
117 if (obj->type == ACPI_TYPE_BUFFER) { 94 return AE_ERROR;
118 if (obj->buffer.length == 4 && result) { 95 } else {
119 *result = 0; 96 if (obj->buffer.length == 4) {
120 *result |= obj->buffer.pointer[0]; 97 *result |= obj->buffer.pointer[0];
121 *result |= (obj->buffer.pointer[1] << 8); 98 *result |= (obj->buffer.pointer[1] << 8);
122 *result |= (obj->buffer.pointer[2] << 16); 99 *result |= (obj->buffer.pointer[2] << 16);
123 *result |= (obj->buffer.pointer[3] << 24); 100 *result |= (obj->buffer.pointer[3] << 24);
124 } 101 }
102 ACPI_FREE(obj);
125 } 103 }
126 104
127 kfree(output.pointer);
128 return 0; 105 return 0;
129} 106}
130 107
131static int nouveau_dsm(acpi_handle handle, int func, int arg, uint32_t *result) 108static int nouveau_dsm(acpi_handle handle, int func, int arg)
132{ 109{
133 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; 110 int ret = 0;
134 struct acpi_object_list input;
135 union acpi_object params[4];
136 union acpi_object *obj; 111 union acpi_object *obj;
137 int err; 112 union acpi_object argv4 = {
138 113 .integer.type = ACPI_TYPE_INTEGER,
139 input.count = 4; 114 .integer.value = arg,
140 input.pointer = params; 115 };
141 params[0].type = ACPI_TYPE_BUFFER; 116
142 params[0].buffer.length = sizeof(nouveau_dsm_muid); 117 obj = acpi_evaluate_dsm_typed(handle, nouveau_dsm_muid, 0x00000102,
143 params[0].buffer.pointer = (char *)nouveau_dsm_muid; 118 func, &argv4, ACPI_TYPE_INTEGER);
144 params[1].type = ACPI_TYPE_INTEGER; 119 if (!obj) {
145 params[1].integer.value = 0x00000102; 120 acpi_handle_info(handle, "failed to evaluate _DSM\n");
146 params[2].type = ACPI_TYPE_INTEGER; 121 return AE_ERROR;
147 params[2].integer.value = func; 122 } else {
148 params[3].type = ACPI_TYPE_INTEGER;
149 params[3].integer.value = arg;
150
151 err = acpi_evaluate_object(handle, "_DSM", &input, &output);
152 if (err) {
153 printk(KERN_INFO "failed to evaluate _DSM: %d\n", err);
154 return err;
155 }
156
157 obj = (union acpi_object *)output.pointer;
158
159 if (obj->type == ACPI_TYPE_INTEGER)
160 if (obj->integer.value == 0x80000002) 123 if (obj->integer.value == 0x80000002)
161 return -ENODEV; 124 ret = -ENODEV;
162 125 ACPI_FREE(obj);
163 if (obj->type == ACPI_TYPE_BUFFER) {
164 if (obj->buffer.length == 4 && result) {
165 *result = 0;
166 *result |= obj->buffer.pointer[0];
167 *result |= (obj->buffer.pointer[1] << 8);
168 *result |= (obj->buffer.pointer[2] << 16);
169 *result |= (obj->buffer.pointer[3] << 24);
170 }
171 } 126 }
172 127
173 kfree(output.pointer); 128 return ret;
174 return 0;
175}
176
177/* Returns 1 if a DSM function is usable and 0 otherwise */
178static int nouveau_test_dsm(acpi_handle test_handle,
179 int (*dsm_func)(acpi_handle, int, int, uint32_t *),
180 int sfnc)
181{
182 u32 result = 0;
183
184 /* Function 0 returns a Buffer containing available functions. The args
185 * parameter is ignored for function 0, so just put 0 in it */
186 if (dsm_func(test_handle, 0, 0, &result))
187 return 0;
188
189 /* ACPI Spec v4 9.14.1: if bit 0 is zero, no function is supported. If
190 * the n-th bit is enabled, function n is supported */
191 return result & 1 && result & (1 << sfnc);
192} 129}
193 130
194static int nouveau_dsm_switch_mux(acpi_handle handle, int mux_id) 131static int nouveau_dsm_switch_mux(acpi_handle handle, int mux_id)
195{ 132{
196 mxm_wmi_call_mxmx(mux_id == NOUVEAU_DSM_LED_STAMINA ? MXM_MXDS_ADAPTER_IGD : MXM_MXDS_ADAPTER_0); 133 mxm_wmi_call_mxmx(mux_id == NOUVEAU_DSM_LED_STAMINA ? MXM_MXDS_ADAPTER_IGD : MXM_MXDS_ADAPTER_0);
197 mxm_wmi_call_mxds(mux_id == NOUVEAU_DSM_LED_STAMINA ? MXM_MXDS_ADAPTER_IGD : MXM_MXDS_ADAPTER_0); 134 mxm_wmi_call_mxds(mux_id == NOUVEAU_DSM_LED_STAMINA ? MXM_MXDS_ADAPTER_IGD : MXM_MXDS_ADAPTER_0);
198 return nouveau_dsm(handle, NOUVEAU_DSM_LED, mux_id, NULL); 135 return nouveau_dsm(handle, NOUVEAU_DSM_LED, mux_id);
199} 136}
200 137
201static int nouveau_dsm_set_discrete_state(acpi_handle handle, enum vga_switcheroo_state state) 138static int nouveau_dsm_set_discrete_state(acpi_handle handle, enum vga_switcheroo_state state)
@@ -205,7 +142,7 @@ static int nouveau_dsm_set_discrete_state(acpi_handle handle, enum vga_switchero
205 arg = NOUVEAU_DSM_POWER_SPEED; 142 arg = NOUVEAU_DSM_POWER_SPEED;
206 else 143 else
207 arg = NOUVEAU_DSM_POWER_STAMINA; 144 arg = NOUVEAU_DSM_POWER_STAMINA;
208 nouveau_dsm(handle, NOUVEAU_DSM_POWER, arg, NULL); 145 nouveau_dsm(handle, NOUVEAU_DSM_POWER, arg);
209 return 0; 146 return 0;
210} 147}
211 148
@@ -265,11 +202,12 @@ static int nouveau_dsm_pci_probe(struct pci_dev *pdev)
265 nouveau_dsm_priv.other_handle = dhandle; 202 nouveau_dsm_priv.other_handle = dhandle;
266 return false; 203 return false;
267 } 204 }
268 if (nouveau_test_dsm(dhandle, nouveau_dsm, NOUVEAU_DSM_POWER)) 205 if (acpi_check_dsm(dhandle, nouveau_dsm_muid, 0x00000102,
206 1 << NOUVEAU_DSM_POWER))
269 retval |= NOUVEAU_DSM_HAS_MUX; 207 retval |= NOUVEAU_DSM_HAS_MUX;
270 208
271 if (nouveau_test_dsm(dhandle, nouveau_optimus_dsm, 209 if (acpi_check_dsm(dhandle, nouveau_op_dsm_muid, 0x00000100,
272 NOUVEAU_DSM_OPTIMUS_CAPS)) 210 1 << NOUVEAU_DSM_OPTIMUS_CAPS))
273 retval |= NOUVEAU_DSM_HAS_OPT; 211 retval |= NOUVEAU_DSM_HAS_OPT;
274 212
275 if (retval & NOUVEAU_DSM_HAS_OPT) { 213 if (retval & NOUVEAU_DSM_HAS_OPT) {