root/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. amdgpu_atif_call
  2. amdgpu_atif_parse_notification
  3. amdgpu_atif_parse_functions
  4. amdgpu_atif_verify_interface
  5. amdgpu_atif_probe_handle
  6. amdgpu_atif_get_notification_params
  7. amdgpu_atif_query_backlight_caps
  8. amdgpu_atif_get_sbios_requests
  9. amdgpu_atif_handler
  10. amdgpu_atcs_call
  11. amdgpu_atcs_parse_functions
  12. amdgpu_atcs_verify_interface
  13. amdgpu_acpi_is_pcie_performance_request_supported
  14. amdgpu_acpi_pcie_notify_device_ready
  15. amdgpu_acpi_pcie_performance_request
  16. amdgpu_acpi_event
  17. amdgpu_acpi_init
  18. amdgpu_acpi_get_backlight_caps
  19. amdgpu_acpi_fini

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

/* [<][>][^][v][top][bottom][index][help] */