1/* $NetBSD: amdgpu_acpi.c,v 1.6 2024/04/16 14:34:01 riastradh Exp $ */ 2 3/* 4 * Copyright 2012 Advanced Micro Devices, Inc. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 * OTHER DEALINGS IN THE SOFTWARE. 23 * 24 */ 25 26#include <sys/cdefs.h> 27__KERNEL_RCSID(0, "$NetBSD: amdgpu_acpi.c,v 1.6 2024/04/16 14:34:01 riastradh Exp $"); 28 29#include <linux/pci.h> 30#include <linux/acpi.h> 31#include <linux/slab.h> 32#include <linux/power_supply.h> 33#include <linux/pm_runtime.h> 34#include <acpi/video.h> 35 36#include <drm/drm_crtc_helper.h> 37#include "amdgpu.h" 38#include "amdgpu_pm.h" 39#include "amdgpu_display.h" 40#include "amd_acpi.h" 41#include "atom.h" 42 43#ifdef __NetBSD__ 44#include <dev/acpi/acpi_pci.h> 45#include <dev/acpi/acpireg.h> 46#define _COMPONENT ACPI_DISPLAY_COMPONENT 47ACPI_MODULE_NAME("radeon_acpi") 48#include <linux/nbsd-namespace-acpi.h> 49#endif 50 51struct amdgpu_atif_notification_cfg { 52 bool enabled; 53 int command_code; 54}; 55 56struct amdgpu_atif_notifications { 57 bool thermal_state; 58 bool forced_power_state; 59 bool system_power_state; 60 bool brightness_change; 61 bool dgpu_display_event; 62 bool gpu_package_power_limit; 63}; 64 65struct amdgpu_atif_functions { 66 bool system_params; 67 bool sbios_requests; 68 bool temperature_change; 69 bool query_backlight_transfer_characteristics; 70 bool ready_to_undock; 71 bool external_gpu_information; 72}; 73 74struct amdgpu_atif { 75 acpi_handle handle; 76 77 struct amdgpu_atif_notifications notifications; 78 struct amdgpu_atif_functions functions; 79 struct amdgpu_atif_notification_cfg notification_cfg; 80 struct amdgpu_encoder *encoder_for_bl; 81 struct amdgpu_dm_backlight_caps backlight_caps; 82}; 83 84/* Call the ATIF method 85 */ 86/** 87 * amdgpu_atif_call - call an ATIF method 88 * 89 * @handle: acpi handle 90 * @function: the ATIF function to execute 91 * @params: ATIF function params 92 * 93 * Executes the requested ATIF function (all asics). 94 * Returns a pointer to the acpi output buffer. 95 */ 96static union acpi_object *amdgpu_atif_call(struct amdgpu_atif *atif, 97 int function, 98 struct acpi_buffer *params) 99{ 100 acpi_status status; 101 union acpi_object atif_arg_elements[2]; 102 struct acpi_object_list atif_arg; 103 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 104 105 atif_arg.count = 2; 106 atif_arg.pointer = &atif_arg_elements[0]; 107 108 atif_arg_elements[0].type = ACPI_TYPE_INTEGER; 109 atif_arg_elements[0].integer.value = function; 110 111 if (params) { 112 atif_arg_elements[1].type = ACPI_TYPE_BUFFER; 113 atif_arg_elements[1].buffer.length = params->length; 114 atif_arg_elements[1].buffer.pointer = params->pointer; 115 } else { 116 /* We need a second fake parameter */ 117 atif_arg_elements[1].type = ACPI_TYPE_INTEGER; 118 atif_arg_elements[1].integer.value = 0; 119 } 120 121 status = acpi_evaluate_object(atif->handle, NULL, &atif_arg, 122 &buffer); 123 124 /* Fail only if calling the method fails and ATIF is supported */ 125 if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { 126 DRM_DEBUG_DRIVER("failed to evaluate ATIF got %s\n", 127 acpi_format_exception(status)); 128 ACPI_FREE(buffer.pointer); 129 return NULL; 130 } 131 132 return buffer.pointer; 133} 134 135/** 136 * amdgpu_atif_parse_notification - parse supported notifications 137 * 138 * @n: supported notifications struct 139 * @mask: supported notifications mask from ATIF 140 * 141 * Use the supported notifications mask from ATIF function 142 * ATIF_FUNCTION_VERIFY_INTERFACE to determine what notifications 143 * are supported (all asics). 144 */ 145static void amdgpu_atif_parse_notification(struct amdgpu_atif_notifications *n, u32 mask) 146{ 147 n->thermal_state = mask & ATIF_THERMAL_STATE_CHANGE_REQUEST_SUPPORTED; 148 n->forced_power_state = mask & ATIF_FORCED_POWER_STATE_CHANGE_REQUEST_SUPPORTED; 149 n->system_power_state = mask & ATIF_SYSTEM_POWER_SOURCE_CHANGE_REQUEST_SUPPORTED; 150 n->brightness_change = mask & ATIF_PANEL_BRIGHTNESS_CHANGE_REQUEST_SUPPORTED; 151 n->dgpu_display_event = mask & ATIF_DGPU_DISPLAY_EVENT_SUPPORTED; 152 n->gpu_package_power_limit = mask & ATIF_GPU_PACKAGE_POWER_LIMIT_REQUEST_SUPPORTED; 153} 154 155/** 156 * amdgpu_atif_parse_functions - parse supported functions 157 * 158 * @f: supported functions struct 159 * @mask: supported functions mask from ATIF 160 * 161 * Use the supported functions mask from ATIF function 162 * ATIF_FUNCTION_VERIFY_INTERFACE to determine what functions 163 * are supported (all asics). 164 */ 165static void amdgpu_atif_parse_functions(struct amdgpu_atif_functions *f, u32 mask) 166{ 167 f->system_params = mask & ATIF_GET_SYSTEM_PARAMETERS_SUPPORTED; 168 f->sbios_requests = mask & ATIF_GET_SYSTEM_BIOS_REQUESTS_SUPPORTED; 169 f->temperature_change = mask & ATIF_TEMPERATURE_CHANGE_NOTIFICATION_SUPPORTED; 170 f->query_backlight_transfer_characteristics = 171 mask & ATIF_QUERY_BACKLIGHT_TRANSFER_CHARACTERISTICS_SUPPORTED; 172 f->ready_to_undock = mask & ATIF_READY_TO_UNDOCK_NOTIFICATION_SUPPORTED; 173 f->external_gpu_information = mask & ATIF_GET_EXTERNAL_GPU_INFORMATION_SUPPORTED; 174} 175 176/** 177 * amdgpu_atif_verify_interface - verify ATIF 178 * 179 * @handle: acpi handle 180 * @atif: amdgpu atif struct 181 * 182 * Execute the ATIF_FUNCTION_VERIFY_INTERFACE ATIF function 183 * to initialize ATIF and determine what features are supported 184 * (all asics). 185 * returns 0 on success, error on failure. 186 */ 187static int amdgpu_atif_verify_interface(struct amdgpu_atif *atif) 188{ 189 union acpi_object *info; 190 struct atif_verify_interface output; 191 size_t size; 192 int err = 0; 193 194 info = amdgpu_atif_call(atif, ATIF_FUNCTION_VERIFY_INTERFACE, NULL); 195 if (!info) 196 return -EIO; 197 198 memset(&output, 0, sizeof(output)); 199 200 size = *(u16 *) info->buffer.pointer; 201 if (size < 12) { 202 DRM_INFO("ATIF buffer is too small: %zu\n", size); 203 err = -EINVAL; 204 goto out; 205 } 206 size = min(sizeof(output), size); 207 208 memcpy(&output, info->buffer.pointer, size); 209 210 /* TODO: check version? */ 211 DRM_DEBUG_DRIVER("ATIF version %u\n", output.version); 212 213 amdgpu_atif_parse_notification(&atif->notifications, output.notification_mask); 214 amdgpu_atif_parse_functions(&atif->functions, output.function_bits); 215 216out: 217 ACPI_FREE(info); 218 return err; 219} 220 221static acpi_handle amdgpu_atif_probe_handle(acpi_handle dhandle) 222{ 223 acpi_handle handle = NULL; 224 char acpi_method_name[255] = { 0 }; 225 struct acpi_buffer buffer = { sizeof(acpi_method_name), acpi_method_name }; 226 acpi_status status; 227 228 /* For PX/HG systems, ATIF and ATPX are in the iGPU's namespace, on dGPU only 229 * systems, ATIF is in the dGPU's namespace. 230 */ 231 status = acpi_get_handle(dhandle, "ATIF", &handle); 232 if (ACPI_SUCCESS(status)) 233 goto out; 234 235 if (amdgpu_has_atpx()) { 236 status = acpi_get_handle(amdgpu_atpx_get_dhandle(), "ATIF", 237 &handle); 238 if (ACPI_SUCCESS(status)) 239 goto out; 240 } 241 242 DRM_DEBUG_DRIVER("No ATIF handle found\n"); 243 return NULL; 244out: 245 acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); 246 DRM_DEBUG_DRIVER("Found ATIF handle %s\n", acpi_method_name); 247 return handle; 248} 249 250/** 251 * amdgpu_atif_get_notification_params - determine notify configuration 252 * 253 * @handle: acpi handle 254 * @n: atif notification configuration struct 255 * 256 * Execute the ATIF_FUNCTION_GET_SYSTEM_PARAMETERS ATIF function 257 * to determine if a notifier is used and if so which one 258 * (all asics). This is either Notify(VGA, 0x81) or Notify(VGA, n) 259 * where n is specified in the result if a notifier is used. 260 * Returns 0 on success, error on failure. 261 */ 262static int amdgpu_atif_get_notification_params(struct amdgpu_atif *atif) 263{ 264 union acpi_object *info; 265 struct amdgpu_atif_notification_cfg *n = &atif->notification_cfg; 266 struct atif_system_params params; 267 size_t size; 268 int err = 0; 269 270 info = amdgpu_atif_call(atif, ATIF_FUNCTION_GET_SYSTEM_PARAMETERS, 271 NULL); 272 if (!info) { 273 err = -EIO; 274 goto out; 275 } 276 277 size = *(u16 *) info->buffer.pointer; 278 if (size < 10) { 279 err = -EINVAL; 280 goto out; 281 } 282 283 memset(¶ms, 0, sizeof(params)); 284 size = min(sizeof(params), size); 285 memcpy(¶ms, info->buffer.pointer, size); 286 287 DRM_DEBUG_DRIVER("SYSTEM_PARAMS: mask = %#x, flags = %#x\n", 288 params.flags, params.valid_mask); 289 params.flags = params.flags & params.valid_mask; 290 291 if ((params.flags & ATIF_NOTIFY_MASK) == ATIF_NOTIFY_NONE) { 292 n->enabled = false; 293 n->command_code = 0; 294 } else if ((params.flags & ATIF_NOTIFY_MASK) == ATIF_NOTIFY_81) { 295 n->enabled = true; 296 n->command_code = 0x81; 297 } else { 298 if (size < 11) { 299 err = -EINVAL; 300 goto out; 301 } 302 n->enabled = true; 303 n->command_code = params.command_code; 304 } 305 306out: 307 DRM_DEBUG_DRIVER("Notification %s, command code = %#x\n", 308 (n->enabled ? "enabled" : "disabled"), 309 n->command_code); 310 ACPI_FREE(info); 311 return err; 312} 313 314/** 315 * amdgpu_atif_query_backlight_caps - get min and max backlight input signal 316 * 317 * @handle: acpi handle 318 * 319 * Execute the QUERY_BRIGHTNESS_TRANSFER_CHARACTERISTICS ATIF function 320 * to determine the acceptable range of backlight values 321 * 322 * Backlight_caps.caps_valid will be set to true if the query is successful 323 * 324 * The input signals are in range 0-255 325 * 326 * This function assumes the display with backlight is the first LCD 327 * 328 * Returns 0 on success, error on failure. 329 */ 330static int amdgpu_atif_query_backlight_caps(struct amdgpu_atif *atif) 331{ 332 union acpi_object *info; 333 struct atif_qbtc_output characteristics; 334 struct atif_qbtc_arguments arguments; 335 struct acpi_buffer params; 336 size_t size; 337 int err = 0; 338 339 arguments.size = sizeof(arguments); 340 arguments.requested_display = ATIF_QBTC_REQUEST_LCD1; 341 342 params.length = sizeof(arguments); 343 params.pointer = (void *)&arguments; 344 345 info = amdgpu_atif_call(atif, 346 ATIF_FUNCTION_QUERY_BRIGHTNESS_TRANSFER_CHARACTERISTICS, 347 ¶ms); 348 if (!info) { 349 err = -EIO; 350 goto out; 351 } 352 353 size = *(u16 *) info->buffer.pointer; 354 if (size < 10) { 355 err = -EINVAL; 356 goto out; 357 } 358 359 memset(&characteristics, 0, sizeof(characteristics)); 360 size = min(sizeof(characteristics), size); 361 memcpy(&characteristics, info->buffer.pointer, size); 362 363 atif->backlight_caps.caps_valid = true; 364 atif->backlight_caps.min_input_signal = 365 characteristics.min_input_signal; 366 atif->backlight_caps.max_input_signal = 367 characteristics.max_input_signal; 368out: 369 ACPI_FREE(info); 370 return err; 371} 372 373#ifndef __NetBSD__ /* XXX amdgpu acpi */ 374 375/** 376 * amdgpu_atif_get_sbios_requests - get requested sbios event 377 * 378 * @handle: acpi handle 379 * @req: atif sbios request struct 380 * 381 * Execute the ATIF_FUNCTION_GET_SYSTEM_BIOS_REQUESTS ATIF function 382 * to determine what requests the sbios is making to the driver 383 * (all asics). 384 * Returns 0 on success, error on failure. 385 */ 386static int amdgpu_atif_get_sbios_requests(struct amdgpu_atif *atif, 387 struct atif_sbios_requests *req) 388{ 389 union acpi_object *info; 390 size_t size; 391 int count = 0; 392 393 info = amdgpu_atif_call(atif, ATIF_FUNCTION_GET_SYSTEM_BIOS_REQUESTS, 394 NULL); 395 if (!info) 396 return -EIO; 397 398 size = *(u16 *)info->buffer.pointer; 399 if (size < 0xd) { 400 count = -EINVAL; 401 goto out; 402 } 403 memset(req, 0, sizeof(*req)); 404 405 size = min(sizeof(*req), size); 406 memcpy(req, info->buffer.pointer, size); 407 DRM_DEBUG_DRIVER("SBIOS pending requests: %#x\n", req->pending); 408 409 count = hweight32(req->pending); 410 411out: 412 ACPI_FREE(info); 413 return count; 414} 415 416/** 417 * amdgpu_atif_handler - handle ATIF notify requests 418 * 419 * @adev: amdgpu_device pointer 420 * @event: atif sbios request struct 421 * 422 * Checks the acpi event and if it matches an atif event, 423 * handles it. 424 * 425 * Returns: 426 * NOTIFY_BAD or NOTIFY_DONE, depending on the event. 427 */ 428static int amdgpu_atif_handler(struct amdgpu_device *adev, 429 struct acpi_bus_event *event) 430{ 431 struct amdgpu_atif *atif = adev->atif; 432 int count; 433 434 DRM_DEBUG_DRIVER("event, device_class = %s, type = %#x\n", 435 event->device_class, event->type); 436 437 if (strcmp(event->device_class, ACPI_VIDEO_CLASS) != 0) 438 return NOTIFY_DONE; 439 440 /* Is this actually our event? */ 441 if (!atif || 442 !atif->notification_cfg.enabled || 443 event->type != atif->notification_cfg.command_code) { 444 /* These events will generate keypresses otherwise */ 445 if (event->type == ACPI_VIDEO_NOTIFY_PROBE) 446 return NOTIFY_BAD; 447 else 448 return NOTIFY_DONE; 449 } 450 451 if (atif->functions.sbios_requests) { 452 struct atif_sbios_requests req; 453 454 /* Check pending SBIOS requests */ 455 count = amdgpu_atif_get_sbios_requests(atif, &req); 456 457 if (count <= 0) 458 return NOTIFY_BAD; 459 460 DRM_DEBUG_DRIVER("ATIF: %d pending SBIOS requests\n", count); 461 462 /* todo: add DC handling */ 463 if ((req.pending & ATIF_PANEL_BRIGHTNESS_CHANGE_REQUEST) && 464 !amdgpu_device_has_dc_support(adev)) { 465 struct amdgpu_encoder *enc = atif->encoder_for_bl; 466 467 if (enc) { 468 struct amdgpu_encoder_atom_dig *dig = enc->enc_priv; 469 470 DRM_DEBUG_DRIVER("Changing brightness to %d\n", 471 req.backlight_level); 472 473 amdgpu_display_backlight_set_level(adev, enc, req.backlight_level); 474 475#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) || defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE) 476 backlight_force_update(dig->bl_dev, 477 BACKLIGHT_UPDATE_HOTKEY); 478#endif 479 } 480 } 481 if (req.pending & ATIF_DGPU_DISPLAY_EVENT) { 482 if (adev->flags & AMD_IS_PX) { 483 pm_runtime_get_sync(adev->ddev->dev); 484 /* Just fire off a uevent and let userspace tell us what to do */ 485 drm_helper_hpd_irq_event(adev->ddev); 486 pm_runtime_mark_last_busy(adev->ddev->dev); 487 pm_runtime_put_autosuspend(adev->ddev->dev); 488 } 489 } 490 /* TODO: check other events */ 491 } 492 493 /* We've handled the event, stop the notifier chain. The ACPI interface 494 * overloads ACPI_VIDEO_NOTIFY_PROBE, we don't want to send that to 495 * userspace if the event was generated only to signal a SBIOS 496 * request. 497 */ 498 return NOTIFY_BAD; 499} 500 501#endif /* __NetBSD__ */ 502 503/* Call the ATCS method 504 */ 505/** 506 * amdgpu_atcs_call - call an ATCS method 507 * 508 * @handle: acpi handle 509 * @function: the ATCS function to execute 510 * @params: ATCS function params 511 * 512 * Executes the requested ATCS function (all asics). 513 * Returns a pointer to the acpi output buffer. 514 */ 515static union acpi_object *amdgpu_atcs_call(acpi_handle handle, int function, 516 struct acpi_buffer *params) 517{ 518 acpi_status status; 519 union acpi_object atcs_arg_elements[2]; 520 struct acpi_object_list atcs_arg; 521 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 522 523 atcs_arg.count = 2; 524 atcs_arg.pointer = &atcs_arg_elements[0]; 525 526 atcs_arg_elements[0].type = ACPI_TYPE_INTEGER; 527 atcs_arg_elements[0].integer.value = function; 528 529 if (params) { 530 atcs_arg_elements[1].type = ACPI_TYPE_BUFFER; 531 atcs_arg_elements[1].buffer.length = params->length; 532 atcs_arg_elements[1].buffer.pointer = params->pointer; 533 } else { 534 /* We need a second fake parameter */ 535 atcs_arg_elements[1].type = ACPI_TYPE_INTEGER; 536 atcs_arg_elements[1].integer.value = 0; 537 } 538 539 status = acpi_evaluate_object(handle, "ATCS", &atcs_arg, &buffer); 540 541 /* Fail only if calling the method fails and ATIF is supported */ 542 if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { 543 DRM_DEBUG_DRIVER("failed to evaluate ATCS got %s\n", 544 acpi_format_exception(status)); 545 ACPI_FREE(buffer.pointer); 546 return NULL; 547 } 548 549 return buffer.pointer; 550} 551 552/** 553 * amdgpu_atcs_parse_functions - parse supported functions 554 * 555 * @f: supported functions struct 556 * @mask: supported functions mask from ATCS 557 * 558 * Use the supported functions mask from ATCS function 559 * ATCS_FUNCTION_VERIFY_INTERFACE to determine what functions 560 * are supported (all asics). 561 */ 562static void amdgpu_atcs_parse_functions(struct amdgpu_atcs_functions *f, u32 mask) 563{ 564 f->get_ext_state = mask & ATCS_GET_EXTERNAL_STATE_SUPPORTED; 565 f->pcie_perf_req = mask & ATCS_PCIE_PERFORMANCE_REQUEST_SUPPORTED; 566 f->pcie_dev_rdy = mask & ATCS_PCIE_DEVICE_READY_NOTIFICATION_SUPPORTED; 567 f->pcie_bus_width = mask & ATCS_SET_PCIE_BUS_WIDTH_SUPPORTED; 568} 569 570/** 571 * amdgpu_atcs_verify_interface - verify ATCS 572 * 573 * @handle: acpi handle 574 * @atcs: amdgpu atcs struct 575 * 576 * Execute the ATCS_FUNCTION_VERIFY_INTERFACE ATCS function 577 * to initialize ATCS and determine what features are supported 578 * (all asics). 579 * returns 0 on success, error on failure. 580 */ 581static int amdgpu_atcs_verify_interface(acpi_handle handle, 582 struct amdgpu_atcs *atcs) 583{ 584 union acpi_object *info; 585 struct atcs_verify_interface output; 586 size_t size; 587 int err = 0; 588 589 info = amdgpu_atcs_call(handle, ATCS_FUNCTION_VERIFY_INTERFACE, NULL); 590 if (!info) 591 return -EIO; 592 593 memset(&output, 0, sizeof(output)); 594 595 size = *(u16 *) info->buffer.pointer; 596 if (size < 8) { 597 DRM_INFO("ATCS buffer is too small: %zu\n", size); 598 err = -EINVAL; 599 goto out; 600 } 601 size = min(sizeof(output), size); 602 603 memcpy(&output, info->buffer.pointer, size); 604 605 /* TODO: check version? */ 606 DRM_DEBUG_DRIVER("ATCS version %u\n", output.version); 607 608 amdgpu_atcs_parse_functions(&atcs->functions, output.function_bits); 609 610out: 611 ACPI_FREE(info); 612 return err; 613} 614 615/** 616 * amdgpu_acpi_is_pcie_performance_request_supported 617 * 618 * @adev: amdgpu_device pointer 619 * 620 * Check if the ATCS pcie_perf_req and pcie_dev_rdy methods 621 * are supported (all asics). 622 * returns true if supported, false if not. 623 */ 624bool amdgpu_acpi_is_pcie_performance_request_supported(struct amdgpu_device *adev) 625{ 626 struct amdgpu_atcs *atcs = &adev->atcs; 627 628 if (atcs->functions.pcie_perf_req && atcs->functions.pcie_dev_rdy) 629 return true; 630 631 return false; 632} 633 634/** 635 * amdgpu_acpi_pcie_notify_device_ready 636 * 637 * @adev: amdgpu_device pointer 638 * 639 * Executes the PCIE_DEVICE_READY_NOTIFICATION method 640 * (all asics). 641 * returns 0 on success, error on failure. 642 */ 643int amdgpu_acpi_pcie_notify_device_ready(struct amdgpu_device *adev) 644{ 645 acpi_handle handle; 646 union acpi_object *info; 647 struct amdgpu_atcs *atcs = &adev->atcs; 648 649 /* Get the device handle */ 650#ifdef __NetBSD__ 651 const struct pci_attach_args *pa = &adev->pdev->pd_pa; 652 struct acpi_devnode *const d = 653 acpi_pcidev_find(pci_get_segment(pa->pa_pc), 654 pa->pa_bus, pa->pa_device, pa->pa_function); 655 if (d == NULL) 656 return -EINVAL; 657 handle = d->ad_handle; 658#else 659 handle = ACPI_HANDLE(&adev->pdev->dev); 660#endif 661 if (!handle) 662 return -EINVAL; 663 664 if (!atcs->functions.pcie_dev_rdy) 665 return -EINVAL; 666 667 info = amdgpu_atcs_call(handle, ATCS_FUNCTION_PCIE_DEVICE_READY_NOTIFICATION, NULL); 668 if (!info) 669 return -EIO; 670 671 ACPI_FREE(info); 672 673 return 0; 674} 675 676/** 677 * amdgpu_acpi_pcie_performance_request 678 * 679 * @adev: amdgpu_device pointer 680 * @perf_req: requested perf level (pcie gen speed) 681 * @advertise: set advertise caps flag if set 682 * 683 * Executes the PCIE_PERFORMANCE_REQUEST method to 684 * change the pcie gen speed (all asics). 685 * returns 0 on success, error on failure. 686 */ 687int amdgpu_acpi_pcie_performance_request(struct amdgpu_device *adev, 688 u8 perf_req, bool advertise) 689{ 690 acpi_handle handle; 691 union acpi_object *info; 692 struct amdgpu_atcs *atcs = &adev->atcs; 693 struct atcs_pref_req_input atcs_input; 694 struct atcs_pref_req_output atcs_output; 695 struct acpi_buffer params; 696 size_t size; 697 u32 retry = 3; 698 699 if (amdgpu_acpi_pcie_notify_device_ready(adev)) 700 return -EINVAL; 701 702 /* Get the device handle */ 703#ifdef __NetBSD__ 704 const struct pci_attach_args *pa = &adev->pdev->pd_pa; 705 struct acpi_devnode *const d = 706 acpi_pcidev_find(pci_get_segment(pa->pa_pc), 707 pa->pa_bus, pa->pa_device, pa->pa_function); 708 if (d == NULL) 709 return -EINVAL; 710 handle = d->ad_handle; 711#else 712 handle = ACPI_HANDLE(&adev->pdev->dev); 713#endif 714 if (!handle) 715 return -EINVAL; 716 717 if (!atcs->functions.pcie_perf_req) 718 return -EINVAL; 719 720 atcs_input.size = sizeof(struct atcs_pref_req_input); 721 /* client id (bit 2-0: func num, 7-3: dev num, 15-8: bus num) */ 722 atcs_input.client_id = adev->pdev->devfn | (adev->pdev->bus->number << 8); 723 atcs_input.valid_flags_mask = ATCS_VALID_FLAGS_MASK; 724 atcs_input.flags = ATCS_WAIT_FOR_COMPLETION; 725 if (advertise) 726 atcs_input.flags |= ATCS_ADVERTISE_CAPS; 727 atcs_input.req_type = ATCS_PCIE_LINK_SPEED; 728 atcs_input.perf_req = perf_req; 729 730 params.length = sizeof(struct atcs_pref_req_input); 731 params.pointer = &atcs_input; 732 733 while (retry--) { 734 info = amdgpu_atcs_call(handle, ATCS_FUNCTION_PCIE_PERFORMANCE_REQUEST, ¶ms); 735 if (!info) 736 return -EIO; 737 738 memset(&atcs_output, 0, sizeof(atcs_output)); 739 740 size = *(u16 *) info->buffer.pointer; 741 if (size < 3) { 742 DRM_INFO("ATCS buffer is too small: %zu\n", size); 743 ACPI_FREE(info); 744 return -EINVAL; 745 } 746 size = min(sizeof(atcs_output), size); 747 748 memcpy(&atcs_output, info->buffer.pointer, size); 749 750 ACPI_FREE(info); 751 752 switch (atcs_output.ret_val) { 753 case ATCS_REQUEST_REFUSED: 754 default: 755 return -EINVAL; 756 case ATCS_REQUEST_COMPLETE: 757 return 0; 758 case ATCS_REQUEST_IN_PROGRESS: 759 udelay(10); 760 break; 761 } 762 } 763 764 return 0; 765} 766 767/** 768 * amdgpu_acpi_event - handle notify events 769 * 770 * @nb: notifier block 771 * @val: val 772 * @data: acpi event 773 * 774 * Calls relevant amdgpu functions in response to various 775 * acpi events. 776 * Returns NOTIFY code 777 */ 778#ifndef __NetBSD__ /* XXX amdgpu acpi */ 779static int amdgpu_acpi_event(struct notifier_block *nb, 780 unsigned long val, 781 void *data) 782{ 783 struct amdgpu_device *adev = container_of(nb, struct amdgpu_device, acpi_nb); 784 struct acpi_bus_event *entry = (struct acpi_bus_event *)data; 785 786 if (strcmp(entry->device_class, ACPI_AC_CLASS) == 0) { 787 if (power_supply_is_system_supplied() > 0) 788 DRM_DEBUG_DRIVER("pm: AC\n"); 789 else 790 DRM_DEBUG_DRIVER("pm: DC\n"); 791 792 amdgpu_pm_acpi_event_handler(adev); 793 } 794 795 /* Check for pending SBIOS requests */ 796 return amdgpu_atif_handler(adev, entry); 797} 798#endif 799 800/* Call all ACPI methods here */ 801/** 802 * amdgpu_acpi_init - init driver acpi support 803 * 804 * @adev: amdgpu_device pointer 805 * 806 * Verifies the AMD ACPI interfaces and registers with the acpi 807 * notifier chain (all asics). 808 * Returns 0 on success, error on failure. 809 */ 810int amdgpu_acpi_init(struct amdgpu_device *adev) 811{ 812 acpi_handle handle, atif_handle; 813 struct amdgpu_atif *atif; 814 struct amdgpu_atcs *atcs = &adev->atcs; 815 int ret; 816 817 /* Get the device handle */ 818#ifdef __NetBSD__ 819 const struct pci_attach_args *pa = &adev->pdev->pd_pa; 820 struct acpi_devnode *const d = 821 acpi_pcidev_find(pci_get_segment(pa->pa_pc), 822 pa->pa_bus, pa->pa_device, pa->pa_function); 823 if (d == NULL) 824 return -EINVAL; 825 handle = d->ad_handle; 826#else 827 handle = ACPI_HANDLE(&adev->pdev->dev); 828#endif 829 830 if (!adev->bios || !handle) 831 return 0; 832 833 /* Call the ATCS method */ 834 ret = amdgpu_atcs_verify_interface(handle, atcs); 835 if (ret) { 836 DRM_DEBUG_DRIVER("Call to ATCS verify_interface failed: %d\n", ret); 837 } 838 839 /* Probe for ATIF, and initialize it if found */ 840 atif_handle = amdgpu_atif_probe_handle(handle); 841 if (!atif_handle) 842 goto out; 843 844 atif = kzalloc(sizeof(*atif), GFP_KERNEL); 845 if (!atif) { 846 DRM_WARN("Not enough memory to initialize ATIF\n"); 847 goto out; 848 } 849 atif->handle = atif_handle; 850 851 /* Call the ATIF method */ 852 ret = amdgpu_atif_verify_interface(atif); 853 if (ret) { 854 DRM_DEBUG_DRIVER("Call to ATIF verify_interface failed: %d\n", ret); 855 kfree(atif); 856 goto out; 857 } 858 adev->atif = atif; 859 860 if (atif->notifications.brightness_change) { 861 struct drm_encoder *tmp; 862 863 /* Find the encoder controlling the brightness */ 864 list_for_each_entry(tmp, &adev->ddev->mode_config.encoder_list, 865 head) { 866 struct amdgpu_encoder *enc = to_amdgpu_encoder(tmp); 867 868 if ((enc->devices & (ATOM_DEVICE_LCD_SUPPORT)) && 869 enc->enc_priv) { 870 struct amdgpu_encoder_atom_dig *dig = enc->enc_priv; 871 if (dig->bl_dev) { 872 atif->encoder_for_bl = enc; 873 break; 874 } 875 } 876 } 877 } 878 879 if (atif->functions.sbios_requests && !atif->functions.system_params) { 880 /* XXX check this workraround, if sbios request function is 881 * present we have to see how it's configured in the system 882 * params 883 */ 884 atif->functions.system_params = true; 885 } 886 887 if (atif->functions.system_params) { 888 ret = amdgpu_atif_get_notification_params(atif); 889 if (ret) { 890 DRM_DEBUG_DRIVER("Call to GET_SYSTEM_PARAMS failed: %d\n", 891 ret); 892 /* Disable notification */ 893 atif->notification_cfg.enabled = false; 894 } 895 } 896 897 if (atif->functions.query_backlight_transfer_characteristics) { 898 ret = amdgpu_atif_query_backlight_caps(atif); 899 if (ret) { 900 DRM_DEBUG_DRIVER("Call to QUERY_BACKLIGHT_TRANSFER_CHARACTERISTICS failed: %d\n", 901 ret); 902 atif->backlight_caps.caps_valid = false; 903 } 904 } else { 905 atif->backlight_caps.caps_valid = false; 906 } 907 908out: 909#ifndef __NetBSD__ /* XXX amdgpu acpi */ 910 adev->acpi_nb.notifier_call = amdgpu_acpi_event; 911 register_acpi_notifier(&adev->acpi_nb); 912#endif 913 914 return ret; 915} 916 917void amdgpu_acpi_get_backlight_caps(struct amdgpu_device *adev, 918 struct amdgpu_dm_backlight_caps *caps) 919{ 920 if (!adev->atif) { 921 caps->caps_valid = false; 922 return; 923 } 924 caps->caps_valid = adev->atif->backlight_caps.caps_valid; 925 caps->min_input_signal = adev->atif->backlight_caps.min_input_signal; 926 caps->max_input_signal = adev->atif->backlight_caps.max_input_signal; 927} 928 929/** 930 * amdgpu_acpi_fini - tear down driver acpi support 931 * 932 * @adev: amdgpu_device pointer 933 * 934 * Unregisters with the acpi notifier chain (all asics). 935 */ 936void amdgpu_acpi_fini(struct amdgpu_device *adev) 937{ 938#ifndef __NetBSD__ /* XXX radeon acpi */ 939 unregister_acpi_notifier(&adev->acpi_nb); 940#endif 941 kfree(adev->atif); 942} 943