aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/radeon/radeon_acpi.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-10-04 02:29:23 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-10-04 02:29:23 -0400
commit612a9aab56a93533e76e3ad91642db7033e03b69 (patch)
tree8402096973f67af941f9392f7da06cca03e0b58a /drivers/gpu/drm/radeon/radeon_acpi.c
parent3a494318b14b1bc0f59d2d6ce84c505c74d82d2a (diff)
parent268d28371cd326be4dfcd7eba5917bf4b9d30c8f (diff)
Merge branch 'drm-next' of git://people.freedesktop.org/~airlied/linux
Pull drm merge (part 1) from Dave Airlie: "So first of all my tree and uapi stuff has a conflict mess, its my fault as the nouveau stuff didn't hit -next as were trying to rebase regressions out of it before we merged. Highlights: - SH mobile modesetting driver and associated helpers - some DRM core documentation - i915 modesetting rework, haswell hdmi, haswell and vlv fixes, write combined pte writing, ilk rc6 support, - nouveau: major driver rework into a hw core driver, makes features like SLI a lot saner to implement, - psb: add eDP/DP support for Cedarview - radeon: 2 layer page tables, async VM pte updates, better PLL selection for > 2 screens, better ACPI interactions The rest is general grab bag of fixes. So why part 1? well I have the exynos pull req which came in a bit late but was waiting for me to do something they shouldn't have and it looks fairly safe, and David Howells has some more header cleanups he'd like me to pull, that seem like a good idea, but I'd like to get this merge out of the way so -next dosen't get blocked." Tons of conflicts mostly due to silly include line changes, but mostly mindless. A few other small semantic conflicts too, noted from Dave's pre-merged branch. * 'drm-next' of git://people.freedesktop.org/~airlied/linux: (447 commits) drm/nv98/crypt: fix fuc build with latest envyas drm/nouveau/devinit: fixup various issues with subdev ctor/init ordering drm/nv41/vm: fix and enable use of "real" pciegart drm/nv44/vm: fix and enable use of "real" pciegart drm/nv04/dmaobj: fixup vm target handling in preparation for nv4x pcie drm/nouveau: store supported dma mask in vmmgr drm/nvc0/ibus: initial implementation of subdev drm/nouveau/therm: add support for fan-control modes drm/nouveau/hwmon: rename pwm0* to pmw1* to follow hwmon's rules drm/nouveau/therm: calculate the pwm divisor on nv50+ drm/nouveau/fan: rewrite the fan tachometer driver to get more precision, faster drm/nouveau/therm: move thermal-related functions to the therm subdev drm/nouveau/bios: parse the pwm divisor from the perf table drm/nouveau/therm: use the EXTDEV table to detect i2c monitoring devices drm/nouveau/therm: rework thermal table parsing drm/nouveau/gpio: expose the PWM/TOGGLE parameter found in the gpio vbios table drm/nouveau: fix pm initialization order drm/nouveau/bios: check that fixed tvdac gpio data is valid before using it drm/nouveau: log channel debug/error messages from client object rather than drm client drm/nouveau: have drm debugging macros build on top of core macros ...
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_acpi.c')
-rw-r--r--drivers/gpu/drm/radeon/radeon_acpi.c607
1 files changed, 594 insertions, 13 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_acpi.c b/drivers/gpu/drm/radeon/radeon_acpi.c
index 215063e1a292..b0a5688c67f8 100644
--- a/drivers/gpu/drm/radeon/radeon_acpi.c
+++ b/drivers/gpu/drm/radeon/radeon_acpi.c
@@ -1,33 +1,118 @@
1/*
2 * Copyright 2012 Advanced Micro Devices, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 */
23
1#include <linux/pci.h> 24#include <linux/pci.h>
2#include <linux/acpi.h> 25#include <linux/acpi.h>
3#include <linux/slab.h> 26#include <linux/slab.h>
27#include <linux/power_supply.h>
4#include <acpi/acpi_drivers.h> 28#include <acpi/acpi_drivers.h>
5#include <acpi/acpi_bus.h> 29#include <acpi/acpi_bus.h>
30#include <acpi/video.h>
6 31
7#include <drm/drmP.h> 32#include <drm/drmP.h>
8#include <drm/drm_crtc_helper.h> 33#include <drm/drm_crtc_helper.h>
9#include "radeon.h" 34#include "radeon.h"
35#include "radeon_acpi.h"
36#include "atom.h"
10 37
11#include <linux/vga_switcheroo.h> 38#include <linux/vga_switcheroo.h>
12 39
40#define ACPI_AC_CLASS "ac_adapter"
41
42extern void radeon_pm_acpi_event_handler(struct radeon_device *rdev);
43
44struct atif_verify_interface {
45 u16 size; /* structure size in bytes (includes size field) */
46 u16 version; /* version */
47 u32 notification_mask; /* supported notifications mask */
48 u32 function_bits; /* supported functions bit vector */
49} __packed;
50
51struct atif_system_params {
52 u16 size; /* structure size in bytes (includes size field) */
53 u32 valid_mask; /* valid flags mask */
54 u32 flags; /* flags */
55 u8 command_code; /* notify command code */
56} __packed;
57
58struct atif_sbios_requests {
59 u16 size; /* structure size in bytes (includes size field) */
60 u32 pending; /* pending sbios requests */
61 u8 panel_exp_mode; /* panel expansion mode */
62 u8 thermal_gfx; /* thermal state: target gfx controller */
63 u8 thermal_state; /* thermal state: state id (0: exit state, non-0: state) */
64 u8 forced_power_gfx; /* forced power state: target gfx controller */
65 u8 forced_power_state; /* forced power state: state id */
66 u8 system_power_src; /* system power source */
67 u8 backlight_level; /* panel backlight level (0-255) */
68} __packed;
69
70#define ATIF_NOTIFY_MASK 0x3
71#define ATIF_NOTIFY_NONE 0
72#define ATIF_NOTIFY_81 1
73#define ATIF_NOTIFY_N 2
74
75struct atcs_verify_interface {
76 u16 size; /* structure size in bytes (includes size field) */
77 u16 version; /* version */
78 u32 function_bits; /* supported functions bit vector */
79} __packed;
80
13/* Call the ATIF method 81/* Call the ATIF method
82 */
83/**
84 * radeon_atif_call - call an ATIF method
14 * 85 *
15 * Note: currently we discard the output 86 * @handle: acpi handle
87 * @function: the ATIF function to execute
88 * @params: ATIF function params
89 *
90 * Executes the requested ATIF function (all asics).
91 * Returns a pointer to the acpi output buffer.
16 */ 92 */
17static int radeon_atif_call(acpi_handle handle) 93static union acpi_object *radeon_atif_call(acpi_handle handle, int function,
94 struct acpi_buffer *params)
18{ 95{
19 acpi_status status; 96 acpi_status status;
20 union acpi_object atif_arg_elements[2]; 97 union acpi_object atif_arg_elements[2];
21 struct acpi_object_list atif_arg; 98 struct acpi_object_list atif_arg;
22 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL}; 99 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
23 100
24 atif_arg.count = 2; 101 atif_arg.count = 2;
25 atif_arg.pointer = &atif_arg_elements[0]; 102 atif_arg.pointer = &atif_arg_elements[0];
26 103
27 atif_arg_elements[0].type = ACPI_TYPE_INTEGER; 104 atif_arg_elements[0].type = ACPI_TYPE_INTEGER;
28 atif_arg_elements[0].integer.value = 0; 105 atif_arg_elements[0].integer.value = function;
29 atif_arg_elements[1].type = ACPI_TYPE_INTEGER; 106
30 atif_arg_elements[1].integer.value = 0; 107 if (params) {
108 atif_arg_elements[1].type = ACPI_TYPE_BUFFER;
109 atif_arg_elements[1].buffer.length = params->length;
110 atif_arg_elements[1].buffer.pointer = params->pointer;
111 } else {
112 /* We need a second fake parameter */
113 atif_arg_elements[1].type = ACPI_TYPE_INTEGER;
114 atif_arg_elements[1].integer.value = 0;
115 }
31 116
32 status = acpi_evaluate_object(handle, "ATIF", &atif_arg, &buffer); 117 status = acpi_evaluate_object(handle, "ATIF", &atif_arg, &buffer);
33 118
@@ -36,17 +121,434 @@ static int radeon_atif_call(acpi_handle handle)
36 DRM_DEBUG_DRIVER("failed to evaluate ATIF got %s\n", 121 DRM_DEBUG_DRIVER("failed to evaluate ATIF got %s\n",
37 acpi_format_exception(status)); 122 acpi_format_exception(status));
38 kfree(buffer.pointer); 123 kfree(buffer.pointer);
39 return 1; 124 return NULL;
40 } 125 }
41 126
42 kfree(buffer.pointer); 127 return buffer.pointer;
43 return 0; 128}
129
130/**
131 * radeon_atif_parse_notification - parse supported notifications
132 *
133 * @n: supported notifications struct
134 * @mask: supported notifications mask from ATIF
135 *
136 * Use the supported notifications mask from ATIF function
137 * ATIF_FUNCTION_VERIFY_INTERFACE to determine what notifications
138 * are supported (all asics).
139 */
140static void radeon_atif_parse_notification(struct radeon_atif_notifications *n, u32 mask)
141{
142 n->display_switch = mask & ATIF_DISPLAY_SWITCH_REQUEST_SUPPORTED;
143 n->expansion_mode_change = mask & ATIF_EXPANSION_MODE_CHANGE_REQUEST_SUPPORTED;
144 n->thermal_state = mask & ATIF_THERMAL_STATE_CHANGE_REQUEST_SUPPORTED;
145 n->forced_power_state = mask & ATIF_FORCED_POWER_STATE_CHANGE_REQUEST_SUPPORTED;
146 n->system_power_state = mask & ATIF_SYSTEM_POWER_SOURCE_CHANGE_REQUEST_SUPPORTED;
147 n->display_conf_change = mask & ATIF_DISPLAY_CONF_CHANGE_REQUEST_SUPPORTED;
148 n->px_gfx_switch = mask & ATIF_PX_GFX_SWITCH_REQUEST_SUPPORTED;
149 n->brightness_change = mask & ATIF_PANEL_BRIGHTNESS_CHANGE_REQUEST_SUPPORTED;
150 n->dgpu_display_event = mask & ATIF_DGPU_DISPLAY_EVENT_SUPPORTED;
151}
152
153/**
154 * radeon_atif_parse_functions - parse supported functions
155 *
156 * @f: supported functions struct
157 * @mask: supported functions mask from ATIF
158 *
159 * Use the supported functions mask from ATIF function
160 * ATIF_FUNCTION_VERIFY_INTERFACE to determine what functions
161 * are supported (all asics).
162 */
163static void radeon_atif_parse_functions(struct radeon_atif_functions *f, u32 mask)
164{
165 f->system_params = mask & ATIF_GET_SYSTEM_PARAMETERS_SUPPORTED;
166 f->sbios_requests = mask & ATIF_GET_SYSTEM_BIOS_REQUESTS_SUPPORTED;
167 f->select_active_disp = mask & ATIF_SELECT_ACTIVE_DISPLAYS_SUPPORTED;
168 f->lid_state = mask & ATIF_GET_LID_STATE_SUPPORTED;
169 f->get_tv_standard = mask & ATIF_GET_TV_STANDARD_FROM_CMOS_SUPPORTED;
170 f->set_tv_standard = mask & ATIF_SET_TV_STANDARD_IN_CMOS_SUPPORTED;
171 f->get_panel_expansion_mode = mask & ATIF_GET_PANEL_EXPANSION_MODE_FROM_CMOS_SUPPORTED;
172 f->set_panel_expansion_mode = mask & ATIF_SET_PANEL_EXPANSION_MODE_IN_CMOS_SUPPORTED;
173 f->temperature_change = mask & ATIF_TEMPERATURE_CHANGE_NOTIFICATION_SUPPORTED;
174 f->graphics_device_types = mask & ATIF_GET_GRAPHICS_DEVICE_TYPES_SUPPORTED;
175}
176
177/**
178 * radeon_atif_verify_interface - verify ATIF
179 *
180 * @handle: acpi handle
181 * @atif: radeon atif struct
182 *
183 * Execute the ATIF_FUNCTION_VERIFY_INTERFACE ATIF function
184 * to initialize ATIF and determine what features are supported
185 * (all asics).
186 * returns 0 on success, error on failure.
187 */
188static int radeon_atif_verify_interface(acpi_handle handle,
189 struct radeon_atif *atif)
190{
191 union acpi_object *info;
192 struct atif_verify_interface output;
193 size_t size;
194 int err = 0;
195
196 info = radeon_atif_call(handle, ATIF_FUNCTION_VERIFY_INTERFACE, NULL);
197 if (!info)
198 return -EIO;
199
200 memset(&output, 0, sizeof(output));
201
202 size = *(u16 *) info->buffer.pointer;
203 if (size < 12) {
204 DRM_INFO("ATIF buffer is too small: %lu\n", size);
205 err = -EINVAL;
206 goto out;
207 }
208 size = min(sizeof(output), size);
209
210 memcpy(&output, info->buffer.pointer, size);
211
212 /* TODO: check version? */
213 DRM_DEBUG_DRIVER("ATIF version %u\n", output.version);
214
215 radeon_atif_parse_notification(&atif->notifications, output.notification_mask);
216 radeon_atif_parse_functions(&atif->functions, output.function_bits);
217
218out:
219 kfree(info);
220 return err;
221}
222
223/**
224 * radeon_atif_get_notification_params - determine notify configuration
225 *
226 * @handle: acpi handle
227 * @n: atif notification configuration struct
228 *
229 * Execute the ATIF_FUNCTION_GET_SYSTEM_PARAMETERS ATIF function
230 * to determine if a notifier is used and if so which one
231 * (all asics). This is either Notify(VGA, 0x81) or Notify(VGA, n)
232 * where n is specified in the result if a notifier is used.
233 * Returns 0 on success, error on failure.
234 */
235static int radeon_atif_get_notification_params(acpi_handle handle,
236 struct radeon_atif_notification_cfg *n)
237{
238 union acpi_object *info;
239 struct atif_system_params params;
240 size_t size;
241 int err = 0;
242
243 info = radeon_atif_call(handle, ATIF_FUNCTION_GET_SYSTEM_PARAMETERS, NULL);
244 if (!info) {
245 err = -EIO;
246 goto out;
247 }
248
249 size = *(u16 *) info->buffer.pointer;
250 if (size < 10) {
251 err = -EINVAL;
252 goto out;
253 }
254
255 memset(&params, 0, sizeof(params));
256 size = min(sizeof(params), size);
257 memcpy(&params, info->buffer.pointer, size);
258
259 DRM_DEBUG_DRIVER("SYSTEM_PARAMS: mask = %#x, flags = %#x\n",
260 params.flags, params.valid_mask);
261 params.flags = params.flags & params.valid_mask;
262
263 if ((params.flags & ATIF_NOTIFY_MASK) == ATIF_NOTIFY_NONE) {
264 n->enabled = false;
265 n->command_code = 0;
266 } else if ((params.flags & ATIF_NOTIFY_MASK) == ATIF_NOTIFY_81) {
267 n->enabled = true;
268 n->command_code = 0x81;
269 } else {
270 if (size < 11) {
271 err = -EINVAL;
272 goto out;
273 }
274 n->enabled = true;
275 n->command_code = params.command_code;
276 }
277
278out:
279 DRM_DEBUG_DRIVER("Notification %s, command code = %#x\n",
280 (n->enabled ? "enabled" : "disabled"),
281 n->command_code);
282 kfree(info);
283 return err;
284}
285
286/**
287 * radeon_atif_get_sbios_requests - get requested sbios event
288 *
289 * @handle: acpi handle
290 * @req: atif sbios request struct
291 *
292 * Execute the ATIF_FUNCTION_GET_SYSTEM_BIOS_REQUESTS ATIF function
293 * to determine what requests the sbios is making to the driver
294 * (all asics).
295 * Returns 0 on success, error on failure.
296 */
297static int radeon_atif_get_sbios_requests(acpi_handle handle,
298 struct atif_sbios_requests *req)
299{
300 union acpi_object *info;
301 size_t size;
302 int count = 0;
303
304 info = radeon_atif_call(handle, ATIF_FUNCTION_GET_SYSTEM_BIOS_REQUESTS, NULL);
305 if (!info)
306 return -EIO;
307
308 size = *(u16 *)info->buffer.pointer;
309 if (size < 0xd) {
310 count = -EINVAL;
311 goto out;
312 }
313 memset(req, 0, sizeof(*req));
314
315 size = min(sizeof(*req), size);
316 memcpy(req, info->buffer.pointer, size);
317 DRM_DEBUG_DRIVER("SBIOS pending requests: %#x\n", req->pending);
318
319 count = hweight32(req->pending);
320
321out:
322 kfree(info);
323 return count;
324}
325
326/**
327 * radeon_atif_handler - handle ATIF notify requests
328 *
329 * @rdev: radeon_device pointer
330 * @event: atif sbios request struct
331 *
332 * Checks the acpi event and if it matches an atif event,
333 * handles it.
334 * Returns NOTIFY code
335 */
336int radeon_atif_handler(struct radeon_device *rdev,
337 struct acpi_bus_event *event)
338{
339 struct radeon_atif *atif = &rdev->atif;
340 struct atif_sbios_requests req;
341 acpi_handle handle;
342 int count;
343
344 DRM_DEBUG_DRIVER("event, device_class = %s, type = %#x\n",
345 event->device_class, event->type);
346
347 if (strcmp(event->device_class, ACPI_VIDEO_CLASS) != 0)
348 return NOTIFY_DONE;
349
350 if (!atif->notification_cfg.enabled ||
351 event->type != atif->notification_cfg.command_code)
352 /* Not our event */
353 return NOTIFY_DONE;
354
355 /* Check pending SBIOS requests */
356 handle = DEVICE_ACPI_HANDLE(&rdev->pdev->dev);
357 count = radeon_atif_get_sbios_requests(handle, &req);
358
359 if (count <= 0)
360 return NOTIFY_DONE;
361
362 DRM_DEBUG_DRIVER("ATIF: %d pending SBIOS requests\n", count);
363
364 if (req.pending & ATIF_PANEL_BRIGHTNESS_CHANGE_REQUEST) {
365 struct radeon_encoder *enc = atif->encoder_for_bl;
366
367 if (enc) {
368 DRM_DEBUG_DRIVER("Changing brightness to %d\n",
369 req.backlight_level);
370
371 radeon_set_backlight_level(rdev, enc, req.backlight_level);
372
373 if (rdev->is_atom_bios) {
374 struct radeon_encoder_atom_dig *dig = enc->enc_priv;
375 backlight_force_update(dig->bl_dev,
376 BACKLIGHT_UPDATE_HOTKEY);
377 } else {
378 struct radeon_encoder_lvds *dig = enc->enc_priv;
379 backlight_force_update(dig->bl_dev,
380 BACKLIGHT_UPDATE_HOTKEY);
381 }
382 }
383 }
384 /* TODO: check other events */
385
386 /* We've handled the event, stop the notifier chain. The ACPI interface
387 * overloads ACPI_VIDEO_NOTIFY_PROBE, we don't want to send that to
388 * userspace if the event was generated only to signal a SBIOS
389 * request.
390 */
391 return NOTIFY_BAD;
392}
393
394/* Call the ATCS method
395 */
396/**
397 * radeon_atcs_call - call an ATCS method
398 *
399 * @handle: acpi handle
400 * @function: the ATCS function to execute
401 * @params: ATCS function params
402 *
403 * Executes the requested ATCS function (all asics).
404 * Returns a pointer to the acpi output buffer.
405 */
406static union acpi_object *radeon_atcs_call(acpi_handle handle, int function,
407 struct acpi_buffer *params)
408{
409 acpi_status status;
410 union acpi_object atcs_arg_elements[2];
411 struct acpi_object_list atcs_arg;
412 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
413
414 atcs_arg.count = 2;
415 atcs_arg.pointer = &atcs_arg_elements[0];
416
417 atcs_arg_elements[0].type = ACPI_TYPE_INTEGER;
418 atcs_arg_elements[0].integer.value = function;
419
420 if (params) {
421 atcs_arg_elements[1].type = ACPI_TYPE_BUFFER;
422 atcs_arg_elements[1].buffer.length = params->length;
423 atcs_arg_elements[1].buffer.pointer = params->pointer;
424 } else {
425 /* We need a second fake parameter */
426 atcs_arg_elements[1].type = ACPI_TYPE_INTEGER;
427 atcs_arg_elements[1].integer.value = 0;
428 }
429
430 status = acpi_evaluate_object(handle, "ATCS", &atcs_arg, &buffer);
431
432 /* Fail only if calling the method fails and ATIF is supported */
433 if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
434 DRM_DEBUG_DRIVER("failed to evaluate ATCS got %s\n",
435 acpi_format_exception(status));
436 kfree(buffer.pointer);
437 return NULL;
438 }
439
440 return buffer.pointer;
441}
442
443/**
444 * radeon_atcs_parse_functions - parse supported functions
445 *
446 * @f: supported functions struct
447 * @mask: supported functions mask from ATCS
448 *
449 * Use the supported functions mask from ATCS function
450 * ATCS_FUNCTION_VERIFY_INTERFACE to determine what functions
451 * are supported (all asics).
452 */
453static void radeon_atcs_parse_functions(struct radeon_atcs_functions *f, u32 mask)
454{
455 f->get_ext_state = mask & ATCS_GET_EXTERNAL_STATE_SUPPORTED;
456 f->pcie_perf_req = mask & ATCS_PCIE_PERFORMANCE_REQUEST_SUPPORTED;
457 f->pcie_dev_rdy = mask & ATCS_PCIE_DEVICE_READY_NOTIFICATION_SUPPORTED;
458 f->pcie_bus_width = mask & ATCS_SET_PCIE_BUS_WIDTH_SUPPORTED;
459}
460
461/**
462 * radeon_atcs_verify_interface - verify ATCS
463 *
464 * @handle: acpi handle
465 * @atcs: radeon atcs struct
466 *
467 * Execute the ATCS_FUNCTION_VERIFY_INTERFACE ATCS function
468 * to initialize ATCS and determine what features are supported
469 * (all asics).
470 * returns 0 on success, error on failure.
471 */
472static int radeon_atcs_verify_interface(acpi_handle handle,
473 struct radeon_atcs *atcs)
474{
475 union acpi_object *info;
476 struct atcs_verify_interface output;
477 size_t size;
478 int err = 0;
479
480 info = radeon_atcs_call(handle, ATCS_FUNCTION_VERIFY_INTERFACE, NULL);
481 if (!info)
482 return -EIO;
483
484 memset(&output, 0, sizeof(output));
485
486 size = *(u16 *) info->buffer.pointer;
487 if (size < 8) {
488 DRM_INFO("ATCS buffer is too small: %lu\n", size);
489 err = -EINVAL;
490 goto out;
491 }
492 size = min(sizeof(output), size);
493
494 memcpy(&output, info->buffer.pointer, size);
495
496 /* TODO: check version? */
497 DRM_DEBUG_DRIVER("ATCS version %u\n", output.version);
498
499 radeon_atcs_parse_functions(&atcs->functions, output.function_bits);
500
501out:
502 kfree(info);
503 return err;
504}
505
506/**
507 * radeon_acpi_event - handle notify events
508 *
509 * @nb: notifier block
510 * @val: val
511 * @data: acpi event
512 *
513 * Calls relevant radeon functions in response to various
514 * acpi events.
515 * Returns NOTIFY code
516 */
517static int radeon_acpi_event(struct notifier_block *nb,
518 unsigned long val,
519 void *data)
520{
521 struct radeon_device *rdev = container_of(nb, struct radeon_device, acpi_nb);
522 struct acpi_bus_event *entry = (struct acpi_bus_event *)data;
523
524 if (strcmp(entry->device_class, ACPI_AC_CLASS) == 0) {
525 if (power_supply_is_system_supplied() > 0)
526 DRM_DEBUG_DRIVER("pm: AC\n");
527 else
528 DRM_DEBUG_DRIVER("pm: DC\n");
529
530 radeon_pm_acpi_event_handler(rdev);
531 }
532
533 /* Check for pending SBIOS requests */
534 return radeon_atif_handler(rdev, entry);
44} 535}
45 536
46/* Call all ACPI methods here */ 537/* Call all ACPI methods here */
538/**
539 * radeon_acpi_init - init driver acpi support
540 *
541 * @rdev: radeon_device pointer
542 *
543 * Verifies the AMD ACPI interfaces and registers with the acpi
544 * notifier chain (all asics).
545 * Returns 0 on success, error on failure.
546 */
47int radeon_acpi_init(struct radeon_device *rdev) 547int radeon_acpi_init(struct radeon_device *rdev)
48{ 548{
49 acpi_handle handle; 549 acpi_handle handle;
550 struct radeon_atif *atif = &rdev->atif;
551 struct radeon_atcs *atcs = &rdev->atcs;
50 int ret; 552 int ret;
51 553
52 /* Get the device handle */ 554 /* Get the device handle */
@@ -56,11 +558,90 @@ int radeon_acpi_init(struct radeon_device *rdev)
56 if (!ASIC_IS_AVIVO(rdev) || !rdev->bios || !handle) 558 if (!ASIC_IS_AVIVO(rdev) || !rdev->bios || !handle)
57 return 0; 559 return 0;
58 560
561 /* Call the ATCS method */
562 ret = radeon_atcs_verify_interface(handle, atcs);
563 if (ret) {
564 DRM_DEBUG_DRIVER("Call to ATCS verify_interface failed: %d\n", ret);
565 }
566
59 /* Call the ATIF method */ 567 /* Call the ATIF method */
60 ret = radeon_atif_call(handle); 568 ret = radeon_atif_verify_interface(handle, atif);
61 if (ret) 569 if (ret) {
62 return ret; 570 DRM_DEBUG_DRIVER("Call to ATIF verify_interface failed: %d\n", ret);
571 goto out;
572 }
573
574 if (atif->notifications.brightness_change) {
575 struct drm_encoder *tmp;
576 struct radeon_encoder *target = NULL;
577
578 /* Find the encoder controlling the brightness */
579 list_for_each_entry(tmp, &rdev->ddev->mode_config.encoder_list,
580 head) {
581 struct radeon_encoder *enc = to_radeon_encoder(tmp);
582
583 if ((enc->devices & (ATOM_DEVICE_LCD_SUPPORT)) &&
584 enc->enc_priv) {
585 if (rdev->is_atom_bios) {
586 struct radeon_encoder_atom_dig *dig = enc->enc_priv;
587 if (dig->bl_dev) {
588 target = enc;
589 break;
590 }
591 } else {
592 struct radeon_encoder_lvds *dig = enc->enc_priv;
593 if (dig->bl_dev) {
594 target = enc;
595 break;
596 }
597 }
598 }
599 }
600
601 atif->encoder_for_bl = target;
602 if (!target) {
603 /* Brightness change notification is enabled, but we
604 * didn't find a backlight controller, this should
605 * never happen.
606 */
607 DRM_ERROR("Cannot find a backlight controller\n");
608 }
609 }
63 610
64 return 0; 611 if (atif->functions.sbios_requests && !atif->functions.system_params) {
612 /* XXX check this workraround, if sbios request function is
613 * present we have to see how it's configured in the system
614 * params
615 */
616 atif->functions.system_params = true;
617 }
618
619 if (atif->functions.system_params) {
620 ret = radeon_atif_get_notification_params(handle,
621 &atif->notification_cfg);
622 if (ret) {
623 DRM_DEBUG_DRIVER("Call to GET_SYSTEM_PARAMS failed: %d\n",
624 ret);
625 /* Disable notification */
626 atif->notification_cfg.enabled = false;
627 }
628 }
629
630out:
631 rdev->acpi_nb.notifier_call = radeon_acpi_event;
632 register_acpi_notifier(&rdev->acpi_nb);
633
634 return ret;
65} 635}
66 636
637/**
638 * radeon_acpi_fini - tear down driver acpi support
639 *
640 * @rdev: radeon_device pointer
641 *
642 * Unregisters with the acpi notifier chain (all asics).
643 */
644void radeon_acpi_fini(struct radeon_device *rdev)
645{
646 unregister_acpi_notifier(&rdev->acpi_nb);
647}