diff options
author | Alex Deucher <alexander.deucher@amd.com> | 2012-08-16 11:13:43 -0400 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2012-09-20 13:10:37 -0400 |
commit | e3a1592085988c60a2207eb492b89493573a0303 (patch) | |
tree | 15fe7eb1e2dd281ff0a03dd576145734efe4424a /drivers/gpu/drm | |
parent | 82e029357d4726bbfb31b4169f82dcaea5fa3eba (diff) |
drm/radeon: add initial support for ATCS ACPI methods
Just verify the interface and track what functions are
supported. Not actually used yet.
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r-- | drivers/gpu/drm/radeon/radeon.h | 12 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_acpi.c | 127 |
2 files changed, 138 insertions, 1 deletions
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index b5b16878f0cf..99a5c8445014 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h | |||
@@ -1464,6 +1464,17 @@ struct radeon_atif { | |||
1464 | struct radeon_encoder *backlight_ctl; | 1464 | struct radeon_encoder *backlight_ctl; |
1465 | }; | 1465 | }; |
1466 | 1466 | ||
1467 | struct radeon_atcs_functions { | ||
1468 | bool get_ext_state; | ||
1469 | bool pcie_perf_req; | ||
1470 | bool pcie_dev_rdy; | ||
1471 | bool pcie_bus_width; | ||
1472 | }; | ||
1473 | |||
1474 | struct radeon_atcs { | ||
1475 | struct radeon_atcs_functions functions; | ||
1476 | }; | ||
1477 | |||
1467 | /* | 1478 | /* |
1468 | * Core structure, functions and helpers. | 1479 | * Core structure, functions and helpers. |
1469 | */ | 1480 | */ |
@@ -1557,6 +1568,7 @@ struct radeon_device { | |||
1557 | struct mutex gpu_clock_mutex; | 1568 | struct mutex gpu_clock_mutex; |
1558 | /* ACPI interface */ | 1569 | /* ACPI interface */ |
1559 | struct radeon_atif atif; | 1570 | struct radeon_atif atif; |
1571 | struct radeon_atcs atcs; | ||
1560 | }; | 1572 | }; |
1561 | 1573 | ||
1562 | int radeon_device_init(struct radeon_device *rdev, | 1574 | int radeon_device_init(struct radeon_device *rdev, |
diff --git a/drivers/gpu/drm/radeon/radeon_acpi.c b/drivers/gpu/drm/radeon/radeon_acpi.c index 49a7d64be9e3..cae895ba8e2f 100644 --- a/drivers/gpu/drm/radeon/radeon_acpi.c +++ b/drivers/gpu/drm/radeon/radeon_acpi.c | |||
@@ -74,6 +74,12 @@ struct atif_sbios_requests { | |||
74 | #define ATIF_NOTIFY_81 1 | 74 | #define ATIF_NOTIFY_81 1 |
75 | #define ATIF_NOTIFY_N 2 | 75 | #define ATIF_NOTIFY_N 2 |
76 | 76 | ||
77 | struct atcs_verify_interface { | ||
78 | u16 size; /* structure size in bytes (includes size field) */ | ||
79 | u16 version; /* version */ | ||
80 | u32 function_bits; /* supported functions bit vector */ | ||
81 | } __packed; | ||
82 | |||
77 | /* Call the ATIF method | 83 | /* Call the ATIF method |
78 | */ | 84 | */ |
79 | /** | 85 | /** |
@@ -383,6 +389,118 @@ int radeon_atif_handler(struct radeon_device *rdev, | |||
383 | return NOTIFY_BAD; | 389 | return NOTIFY_BAD; |
384 | } | 390 | } |
385 | 391 | ||
392 | /* Call the ATCS method | ||
393 | */ | ||
394 | /** | ||
395 | * radeon_atcs_call - call an ATCS method | ||
396 | * | ||
397 | * @handle: acpi handle | ||
398 | * @function: the ATCS function to execute | ||
399 | * @params: ATCS function params | ||
400 | * | ||
401 | * Executes the requested ATCS function (all asics). | ||
402 | * Returns a pointer to the acpi output buffer. | ||
403 | */ | ||
404 | static union acpi_object *radeon_atcs_call(acpi_handle handle, int function, | ||
405 | struct acpi_buffer *params) | ||
406 | { | ||
407 | acpi_status status; | ||
408 | union acpi_object atcs_arg_elements[2]; | ||
409 | struct acpi_object_list atcs_arg; | ||
410 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | ||
411 | |||
412 | atcs_arg.count = 2; | ||
413 | atcs_arg.pointer = &atcs_arg_elements[0]; | ||
414 | |||
415 | atcs_arg_elements[0].type = ACPI_TYPE_INTEGER; | ||
416 | atcs_arg_elements[0].integer.value = function; | ||
417 | |||
418 | if (params) { | ||
419 | atcs_arg_elements[1].type = ACPI_TYPE_BUFFER; | ||
420 | atcs_arg_elements[1].buffer.length = params->length; | ||
421 | atcs_arg_elements[1].buffer.pointer = params->pointer; | ||
422 | } else { | ||
423 | /* We need a second fake parameter */ | ||
424 | atcs_arg_elements[1].type = ACPI_TYPE_INTEGER; | ||
425 | atcs_arg_elements[1].integer.value = 0; | ||
426 | } | ||
427 | |||
428 | status = acpi_evaluate_object(handle, "ATCS", &atcs_arg, &buffer); | ||
429 | |||
430 | /* Fail only if calling the method fails and ATIF is supported */ | ||
431 | if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { | ||
432 | DRM_DEBUG_DRIVER("failed to evaluate ATCS got %s\n", | ||
433 | acpi_format_exception(status)); | ||
434 | kfree(buffer.pointer); | ||
435 | return NULL; | ||
436 | } | ||
437 | |||
438 | return buffer.pointer; | ||
439 | } | ||
440 | |||
441 | /** | ||
442 | * radeon_atcs_parse_functions - parse supported functions | ||
443 | * | ||
444 | * @f: supported functions struct | ||
445 | * @mask: supported functions mask from ATCS | ||
446 | * | ||
447 | * Use the supported functions mask from ATCS function | ||
448 | * ATCS_FUNCTION_VERIFY_INTERFACE to determine what functions | ||
449 | * are supported (all asics). | ||
450 | */ | ||
451 | static void radeon_atcs_parse_functions(struct radeon_atcs_functions *f, u32 mask) | ||
452 | { | ||
453 | f->get_ext_state = mask & ATCS_GET_EXTERNAL_STATE_SUPPORTED; | ||
454 | f->pcie_perf_req = mask & ATCS_PCIE_PERFORMANCE_REQUEST_SUPPORTED; | ||
455 | f->pcie_dev_rdy = mask & ATCS_PCIE_DEVICE_READY_NOTIFICATION_SUPPORTED; | ||
456 | f->pcie_bus_width = mask & ATCS_SET_PCIE_BUS_WIDTH_SUPPORTED; | ||
457 | } | ||
458 | |||
459 | /** | ||
460 | * radeon_atcs_verify_interface - verify ATCS | ||
461 | * | ||
462 | * @handle: acpi handle | ||
463 | * @atcs: radeon atcs struct | ||
464 | * | ||
465 | * Execute the ATCS_FUNCTION_VERIFY_INTERFACE ATCS function | ||
466 | * to initialize ATCS and determine what features are supported | ||
467 | * (all asics). | ||
468 | * returns 0 on success, error on failure. | ||
469 | */ | ||
470 | static int radeon_atcs_verify_interface(acpi_handle handle, | ||
471 | struct radeon_atcs *atcs) | ||
472 | { | ||
473 | union acpi_object *info; | ||
474 | struct atcs_verify_interface output; | ||
475 | size_t size; | ||
476 | int err = 0; | ||
477 | |||
478 | info = radeon_atcs_call(handle, ATCS_FUNCTION_VERIFY_INTERFACE, NULL); | ||
479 | if (!info) | ||
480 | return -EIO; | ||
481 | |||
482 | memset(&output, 0, sizeof(output)); | ||
483 | |||
484 | size = *(u16 *) info->buffer.pointer; | ||
485 | if (size < 8) { | ||
486 | DRM_INFO("ATCS buffer is too small: %lu\n", size); | ||
487 | err = -EINVAL; | ||
488 | goto out; | ||
489 | } | ||
490 | size = min(sizeof(output), size); | ||
491 | |||
492 | memcpy(&output, info->buffer.pointer, size); | ||
493 | |||
494 | /* TODO: check version? */ | ||
495 | DRM_DEBUG_DRIVER("ATCS version %u\n", output.version); | ||
496 | |||
497 | radeon_atcs_parse_functions(&atcs->functions, output.function_bits); | ||
498 | |||
499 | out: | ||
500 | kfree(info); | ||
501 | return err; | ||
502 | } | ||
503 | |||
386 | /** | 504 | /** |
387 | * radeon_acpi_event - handle notify events | 505 | * radeon_acpi_event - handle notify events |
388 | * | 506 | * |
@@ -428,6 +546,7 @@ int radeon_acpi_init(struct radeon_device *rdev) | |||
428 | { | 546 | { |
429 | acpi_handle handle; | 547 | acpi_handle handle; |
430 | struct radeon_atif *atif = &rdev->atif; | 548 | struct radeon_atif *atif = &rdev->atif; |
549 | struct radeon_atcs *atcs = &rdev->atcs; | ||
431 | int ret; | 550 | int ret; |
432 | 551 | ||
433 | /* Get the device handle */ | 552 | /* Get the device handle */ |
@@ -437,10 +556,16 @@ int radeon_acpi_init(struct radeon_device *rdev) | |||
437 | if (!ASIC_IS_AVIVO(rdev) || !rdev->bios || !handle) | 556 | if (!ASIC_IS_AVIVO(rdev) || !rdev->bios || !handle) |
438 | return 0; | 557 | return 0; |
439 | 558 | ||
559 | /* Call the ATCS method */ | ||
560 | ret = radeon_atcs_verify_interface(handle, atcs); | ||
561 | if (ret) { | ||
562 | DRM_DEBUG_DRIVER("Call to ATCS verify_interface failed: %d\n", ret); | ||
563 | } | ||
564 | |||
440 | /* Call the ATIF method */ | 565 | /* Call the ATIF method */ |
441 | ret = radeon_atif_verify_interface(handle, atif); | 566 | ret = radeon_atif_verify_interface(handle, atif); |
442 | if (ret) { | 567 | if (ret) { |
443 | DRM_DEBUG_DRIVER("Call to verify_interface failed: %d\n", ret); | 568 | DRM_DEBUG_DRIVER("Call to ATIF verify_interface failed: %d\n", ret); |
444 | goto out; | 569 | goto out; |
445 | } | 570 | } |
446 | 571 | ||