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