aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorJiang Liu <jiang.liu@linux.intel.com>2013-12-19 07:38:22 -0500
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2014-01-05 10:07:15 -0500
commitb072e53b0a27a885d8be3d08c8d8758292762f39 (patch)
tree177e2c32c572665f4ec1b933599a4f3c13c41de1 /drivers
parent4988d0aeb6843b7070e406f8e6cb095c74e5f136 (diff)
ACPI / nouveau: replace open-coded _DSM code with helper functions
Use helper functions to simplify _DSM related code in nouveau driver. After analyzing the ACPI _DSM related code, I changed nouveau_optimus_dsm() to expect a buffer and nouveau_dsm() to expect an integer only. Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/mxm/base.c48
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_acpi.c136
2 files changed, 54 insertions, 130 deletions
diff --git a/drivers/gpu/drm/nouveau/core/subdev/mxm/base.c b/drivers/gpu/drm/nouveau/core/subdev/mxm/base.c
index 129120473f6c..13c5af88a601 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/mxm/base.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/mxm/base.c
@@ -87,55 +87,39 @@ mxm_shadow_dsm(struct nouveau_mxm *mxm, u8 version)
87 0xB8, 0x9C, 0x79, 0xB6, 0x2F, 0xD5, 0x56, 0x65 87 0xB8, 0x9C, 0x79, 0xB6, 0x2F, 0xD5, 0x56, 0x65
88 }; 88 };
89 u32 mxms_args[] = { 0x00000000 }; 89 u32 mxms_args[] = { 0x00000000 };
90 union acpi_object args[4] = { 90 union acpi_object argv4 = {
91 /* _DSM MUID */ 91 .buffer.type = ACPI_TYPE_BUFFER,
92 { .buffer.type = 3, 92 .buffer.length = sizeof(mxms_args),
93 .buffer.length = sizeof(muid), 93 .buffer.pointer = (char *)mxms_args,
94 .buffer.pointer = muid,
95 },
96 /* spec says this can be zero to mean "highest revision", but
97 * of course there's at least one bios out there which fails
98 * unless you pass in exactly the version it supports..
99 */
100 { .integer.type = ACPI_TYPE_INTEGER,
101 .integer.value = (version & 0xf0) << 4 | (version & 0x0f),
102 },
103 /* MXMS function */
104 { .integer.type = ACPI_TYPE_INTEGER,
105 .integer.value = 0x00000010,
106 },
107 /* Pointer to MXMS arguments */
108 { .buffer.type = ACPI_TYPE_BUFFER,
109 .buffer.length = sizeof(mxms_args),
110 .buffer.pointer = (char *)mxms_args,
111 },
112 }; 94 };
113 struct acpi_object_list list = { ARRAY_SIZE(args), args };
114 struct acpi_buffer retn = { ACPI_ALLOCATE_BUFFER, NULL };
115 union acpi_object *obj; 95 union acpi_object *obj;
116 acpi_handle handle; 96 acpi_handle handle;
117 int ret; 97 int rev;
118 98
119 handle = ACPI_HANDLE(&device->pdev->dev); 99 handle = ACPI_HANDLE(&device->pdev->dev);
120 if (!handle) 100 if (!handle)
121 return false; 101 return false;
122 102
123 ret = acpi_evaluate_object(handle, "_DSM", &list, &retn); 103 /*
124 if (ret) { 104 * spec says this can be zero to mean "highest revision", but
125 nv_debug(mxm, "DSM MXMS failed: %d\n", ret); 105 * of course there's at least one bios out there which fails
106 * unless you pass in exactly the version it supports..
107 */
108 rev = (version & 0xf0) << 4 | (version & 0x0f);
109 obj = acpi_evaluate_dsm(handle, muid, rev, 0x00000010, &argv4);
110 if (!obj) {
111 nv_debug(mxm, "DSM MXMS failed\n");
126 return false; 112 return false;
127 } 113 }
128 114
129 obj = retn.pointer;
130 if (obj->type == ACPI_TYPE_BUFFER) { 115 if (obj->type == ACPI_TYPE_BUFFER) {
131 mxm->mxms = kmemdup(obj->buffer.pointer, 116 mxm->mxms = kmemdup(obj->buffer.pointer,
132 obj->buffer.length, GFP_KERNEL); 117 obj->buffer.length, GFP_KERNEL);
133 } else 118 } else if (obj->type == ACPI_TYPE_INTEGER) {
134 if (obj->type == ACPI_TYPE_INTEGER) {
135 nv_debug(mxm, "DSM MXMS returned 0x%llx\n", obj->integer.value); 119 nv_debug(mxm, "DSM MXMS returned 0x%llx\n", obj->integer.value);
136 } 120 }
137 121
138 kfree(obj); 122 ACPI_FREE(obj);
139 return mxm->mxms != NULL; 123 return mxm->mxms != NULL;
140} 124}
141#endif 125#endif
diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c
index 3f721e317fef..879a8b474bfe 100644
--- a/drivers/gpu/drm/nouveau/nouveau_acpi.c
+++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c
@@ -78,127 +78,66 @@ static const char nouveau_op_dsm_muid[] = {
78 78
79static int nouveau_optimus_dsm(acpi_handle handle, int func, int arg, uint32_t *result) 79static int nouveau_optimus_dsm(acpi_handle handle, int func, int arg, uint32_t *result)
80{ 80{
81 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; 81 int i;
82 struct acpi_object_list input;
83 union acpi_object params[4];
84 union acpi_object *obj; 82 union acpi_object *obj;
85 int i, err;
86 char args_buff[4]; 83 char args_buff[4];
84 union acpi_object argv4 = {
85 .buffer.type = ACPI_TYPE_BUFFER,
86 .buffer.length = 4,
87 .buffer.pointer = args_buff
88 };
87 89
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} */ 90 /* ACPI is little endian, AABBCCDD becomes {DD,CC,BB,AA} */
100 for (i = 0; i < 4; i++) 91 for (i = 0; i < 4; i++)
101 args_buff[i] = (arg >> i * 8) & 0xFF; 92 args_buff[i] = (arg >> i * 8) & 0xFF;
102 params[3].buffer.pointer = args_buff;
103 93
104 err = acpi_evaluate_object(handle, "_DSM", &input, &output); 94 *result = 0;
105 if (err) { 95 obj = acpi_evaluate_dsm_typed(handle, nouveau_op_dsm_muid, 0x00000100,
106 printk(KERN_INFO "failed to evaluate _DSM: %d\n", err); 96 func, &argv4, ACPI_TYPE_BUFFER);
107 return err; 97 if (!obj) {
108 } 98 acpi_handle_info(handle, "failed to evaluate _DSM\n");
109 99 return AE_ERROR;
110 obj = (union acpi_object *)output.pointer; 100 } else {
111 101 if (obj->buffer.length == 4) {
112 if (obj->type == ACPI_TYPE_INTEGER)
113 if (obj->integer.value == 0x80000002) {
114 kfree(output.pointer);
115 return -ENODEV;
116 }
117
118 if (obj->type == ACPI_TYPE_BUFFER) {
119 if (obj->buffer.length == 4 && result) {
120 *result = 0;
121 *result |= obj->buffer.pointer[0]; 102 *result |= obj->buffer.pointer[0];
122 *result |= (obj->buffer.pointer[1] << 8); 103 *result |= (obj->buffer.pointer[1] << 8);
123 *result |= (obj->buffer.pointer[2] << 16); 104 *result |= (obj->buffer.pointer[2] << 16);
124 *result |= (obj->buffer.pointer[3] << 24); 105 *result |= (obj->buffer.pointer[3] << 24);
125 } 106 }
107 ACPI_FREE(obj);
126 } 108 }
127 109
128 kfree(output.pointer);
129 return 0; 110 return 0;
130} 111}
131 112
132static int nouveau_dsm(acpi_handle handle, int func, int arg, uint32_t *result) 113static int nouveau_dsm(acpi_handle handle, int func, int arg)
133{ 114{
134 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; 115 int ret = 0;
135 struct acpi_object_list input;
136 union acpi_object params[4];
137 union acpi_object *obj; 116 union acpi_object *obj;
138 int err; 117 union acpi_object argv4 = {
139 118 .integer.type = ACPI_TYPE_INTEGER,
140 input.count = 4; 119 .integer.value = arg,
141 input.pointer = params; 120 };
142 params[0].type = ACPI_TYPE_BUFFER; 121
143 params[0].buffer.length = sizeof(nouveau_dsm_muid); 122 obj = acpi_evaluate_dsm_typed(handle, nouveau_dsm_muid, 0x00000102,
144 params[0].buffer.pointer = (char *)nouveau_dsm_muid; 123 func, &argv4, ACPI_TYPE_INTEGER);
145 params[1].type = ACPI_TYPE_INTEGER; 124 if (!obj) {
146 params[1].integer.value = 0x00000102; 125 acpi_handle_info(handle, "failed to evaluate _DSM\n");
147 params[2].type = ACPI_TYPE_INTEGER; 126 return AE_ERROR;
148 params[2].integer.value = func; 127 } else {
149 params[3].type = ACPI_TYPE_INTEGER; 128 if (obj->integer.value == 0x80000002)
150 params[3].integer.value = arg; 129 ret = -ENODEV;
151 130 ACPI_FREE(obj);
152 err = acpi_evaluate_object(handle, "_DSM", &input, &output);
153 if (err) {
154 printk(KERN_INFO "failed to evaluate _DSM: %d\n", err);
155 return err;
156 }
157
158 obj = (union acpi_object *)output.pointer;
159
160 if (obj->type == ACPI_TYPE_INTEGER)
161 if (obj->integer.value == 0x80000002) {
162 kfree(output.pointer);
163 return -ENODEV;
164 }
165
166 if (obj->type == ACPI_TYPE_BUFFER) {
167 if (obj->buffer.length == 4 && result) {
168 *result = 0;
169 *result |= obj->buffer.pointer[0];
170 *result |= (obj->buffer.pointer[1] << 8);
171 *result |= (obj->buffer.pointer[2] << 16);
172 *result |= (obj->buffer.pointer[3] << 24);
173 }
174 } 131 }
175 132
176 kfree(output.pointer); 133 return ret;
177 return 0;
178}
179
180/* Returns 1 if a DSM function is usable and 0 otherwise */
181static int nouveau_test_dsm(acpi_handle test_handle,
182 int (*dsm_func)(acpi_handle, int, int, uint32_t *),
183 int sfnc)
184{
185 u32 result = 0;
186
187 /* Function 0 returns a Buffer containing available functions. The args
188 * parameter is ignored for function 0, so just put 0 in it */
189 if (dsm_func(test_handle, 0, 0, &result))
190 return 0;
191
192 /* ACPI Spec v4 9.14.1: if bit 0 is zero, no function is supported. If
193 * the n-th bit is enabled, function n is supported */
194 return result & 1 && result & (1 << sfnc);
195} 134}
196 135
197static int nouveau_dsm_switch_mux(acpi_handle handle, int mux_id) 136static int nouveau_dsm_switch_mux(acpi_handle handle, int mux_id)
198{ 137{
199 mxm_wmi_call_mxmx(mux_id == NOUVEAU_DSM_LED_STAMINA ? MXM_MXDS_ADAPTER_IGD : MXM_MXDS_ADAPTER_0); 138 mxm_wmi_call_mxmx(mux_id == NOUVEAU_DSM_LED_STAMINA ? MXM_MXDS_ADAPTER_IGD : MXM_MXDS_ADAPTER_0);
200 mxm_wmi_call_mxds(mux_id == NOUVEAU_DSM_LED_STAMINA ? MXM_MXDS_ADAPTER_IGD : MXM_MXDS_ADAPTER_0); 139 mxm_wmi_call_mxds(mux_id == NOUVEAU_DSM_LED_STAMINA ? MXM_MXDS_ADAPTER_IGD : MXM_MXDS_ADAPTER_0);
201 return nouveau_dsm(handle, NOUVEAU_DSM_LED, mux_id, NULL); 140 return nouveau_dsm(handle, NOUVEAU_DSM_LED, mux_id);
202} 141}
203 142
204static int nouveau_dsm_set_discrete_state(acpi_handle handle, enum vga_switcheroo_state state) 143static int nouveau_dsm_set_discrete_state(acpi_handle handle, enum vga_switcheroo_state state)
@@ -208,7 +147,7 @@ static int nouveau_dsm_set_discrete_state(acpi_handle handle, enum vga_switchero
208 arg = NOUVEAU_DSM_POWER_SPEED; 147 arg = NOUVEAU_DSM_POWER_SPEED;
209 else 148 else
210 arg = NOUVEAU_DSM_POWER_STAMINA; 149 arg = NOUVEAU_DSM_POWER_STAMINA;
211 nouveau_dsm(handle, NOUVEAU_DSM_POWER, arg, NULL); 150 nouveau_dsm(handle, NOUVEAU_DSM_POWER, arg);
212 return 0; 151 return 0;
213} 152}
214 153
@@ -268,11 +207,12 @@ static int nouveau_dsm_pci_probe(struct pci_dev *pdev)
268 nouveau_dsm_priv.other_handle = dhandle; 207 nouveau_dsm_priv.other_handle = dhandle;
269 return false; 208 return false;
270 } 209 }
271 if (nouveau_test_dsm(dhandle, nouveau_dsm, NOUVEAU_DSM_POWER)) 210 if (acpi_check_dsm(dhandle, nouveau_dsm_muid, 0x00000102,
211 1 << NOUVEAU_DSM_POWER))
272 retval |= NOUVEAU_DSM_HAS_MUX; 212 retval |= NOUVEAU_DSM_HAS_MUX;
273 213
274 if (nouveau_test_dsm(dhandle, nouveau_optimus_dsm, 214 if (acpi_check_dsm(dhandle, nouveau_op_dsm_muid, 0x00000100,
275 NOUVEAU_DSM_OPTIMUS_CAPS)) 215 1 << NOUVEAU_DSM_OPTIMUS_CAPS))
276 retval |= NOUVEAU_DSM_HAS_OPT; 216 retval |= NOUVEAU_DSM_HAS_OPT;
277 217
278 if (retval & NOUVEAU_DSM_HAS_OPT) { 218 if (retval & NOUVEAU_DSM_HAS_OPT) {