root/drivers/gpu/drm/radeon/radeon_atpx_handler.c

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

DEFINITIONS

This source file includes following definitions.
  1. radeon_has_atpx
  2. radeon_has_atpx_dgpu_power_cntl
  3. radeon_is_atpx_hybrid
  4. radeon_atpx_dgpu_req_power_for_displays
  5. radeon_atpx_call
  6. radeon_atpx_parse_functions
  7. radeon_atpx_validate
  8. radeon_atpx_verify_interface
  9. radeon_atpx_set_discrete_state
  10. radeon_atpx_switch_disp_mux
  11. radeon_atpx_switch_i2c_mux
  12. radeon_atpx_switch_start
  13. radeon_atpx_switch_end
  14. radeon_atpx_switchto
  15. radeon_atpx_power_state
  16. radeon_atpx_pci_probe_handle
  17. radeon_atpx_init
  18. radeon_atpx_get_client_id
  19. radeon_atpx_detect
  20. radeon_register_atpx_handler
  21. radeon_unregister_atpx_handler

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Copyright (c) 2010 Red Hat Inc.
   4  * Author : Dave Airlie <airlied@redhat.com>
   5  *
   6  * ATPX support for both Intel/ATI
   7  */
   8 #include <linux/vga_switcheroo.h>
   9 #include <linux/slab.h>
  10 #include <linux/acpi.h>
  11 #include <linux/pci.h>
  12 #include <linux/delay.h>
  13 
  14 #include "radeon_acpi.h"
  15 
  16 struct radeon_atpx_functions {
  17         bool px_params;
  18         bool power_cntl;
  19         bool disp_mux_cntl;
  20         bool i2c_mux_cntl;
  21         bool switch_start;
  22         bool switch_end;
  23         bool disp_connectors_mapping;
  24         bool disp_detetion_ports;
  25 };
  26 
  27 struct radeon_atpx {
  28         acpi_handle handle;
  29         struct radeon_atpx_functions functions;
  30         bool is_hybrid;
  31         bool dgpu_req_power_for_displays;
  32 };
  33 
  34 static struct radeon_atpx_priv {
  35         bool atpx_detected;
  36         bool bridge_pm_usable;
  37         /* handle for device - and atpx */
  38         acpi_handle dhandle;
  39         struct radeon_atpx atpx;
  40 } radeon_atpx_priv;
  41 
  42 struct atpx_verify_interface {
  43         u16 size;               /* structure size in bytes (includes size field) */
  44         u16 version;            /* version */
  45         u32 function_bits;      /* supported functions bit vector */
  46 } __packed;
  47 
  48 struct atpx_px_params {
  49         u16 size;               /* structure size in bytes (includes size field) */
  50         u32 valid_flags;        /* which flags are valid */
  51         u32 flags;              /* flags */
  52 } __packed;
  53 
  54 struct atpx_power_control {
  55         u16 size;
  56         u8 dgpu_state;
  57 } __packed;
  58 
  59 struct atpx_mux {
  60         u16 size;
  61         u16 mux;
  62 } __packed;
  63 
  64 bool radeon_has_atpx(void) {
  65         return radeon_atpx_priv.atpx_detected;
  66 }
  67 
  68 bool radeon_has_atpx_dgpu_power_cntl(void) {
  69         return radeon_atpx_priv.atpx.functions.power_cntl;
  70 }
  71 
  72 bool radeon_is_atpx_hybrid(void) {
  73         return radeon_atpx_priv.atpx.is_hybrid;
  74 }
  75 
  76 bool radeon_atpx_dgpu_req_power_for_displays(void) {
  77         return radeon_atpx_priv.atpx.dgpu_req_power_for_displays;
  78 }
  79 
  80 /**
  81  * radeon_atpx_call - call an ATPX method
  82  *
  83  * @handle: acpi handle
  84  * @function: the ATPX function to execute
  85  * @params: ATPX function params
  86  *
  87  * Executes the requested ATPX function (all asics).
  88  * Returns a pointer to the acpi output buffer.
  89  */
  90 static union acpi_object *radeon_atpx_call(acpi_handle handle, int function,
  91                                            struct acpi_buffer *params)
  92 {
  93         acpi_status status;
  94         union acpi_object atpx_arg_elements[2];
  95         struct acpi_object_list atpx_arg;
  96         struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
  97 
  98         atpx_arg.count = 2;
  99         atpx_arg.pointer = &atpx_arg_elements[0];
 100 
 101         atpx_arg_elements[0].type = ACPI_TYPE_INTEGER;
 102         atpx_arg_elements[0].integer.value = function;
 103 
 104         if (params) {
 105                 atpx_arg_elements[1].type = ACPI_TYPE_BUFFER;
 106                 atpx_arg_elements[1].buffer.length = params->length;
 107                 atpx_arg_elements[1].buffer.pointer = params->pointer;
 108         } else {
 109                 /* We need a second fake parameter */
 110                 atpx_arg_elements[1].type = ACPI_TYPE_INTEGER;
 111                 atpx_arg_elements[1].integer.value = 0;
 112         }
 113 
 114         status = acpi_evaluate_object(handle, NULL, &atpx_arg, &buffer);
 115 
 116         /* Fail only if calling the method fails and ATPX is supported */
 117         if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
 118                 printk("failed to evaluate ATPX got %s\n",
 119                        acpi_format_exception(status));
 120                 kfree(buffer.pointer);
 121                 return NULL;
 122         }
 123 
 124         return buffer.pointer;
 125 }
 126 
 127 /**
 128  * radeon_atpx_parse_functions - parse supported functions
 129  *
 130  * @f: supported functions struct
 131  * @mask: supported functions mask from ATPX
 132  *
 133  * Use the supported functions mask from ATPX function
 134  * ATPX_FUNCTION_VERIFY_INTERFACE to determine what functions
 135  * are supported (all asics).
 136  */
 137 static void radeon_atpx_parse_functions(struct radeon_atpx_functions *f, u32 mask)
 138 {
 139         f->px_params = mask & ATPX_GET_PX_PARAMETERS_SUPPORTED;
 140         f->power_cntl = mask & ATPX_POWER_CONTROL_SUPPORTED;
 141         f->disp_mux_cntl = mask & ATPX_DISPLAY_MUX_CONTROL_SUPPORTED;
 142         f->i2c_mux_cntl = mask & ATPX_I2C_MUX_CONTROL_SUPPORTED;
 143         f->switch_start = mask & ATPX_GRAPHICS_DEVICE_SWITCH_START_NOTIFICATION_SUPPORTED;
 144         f->switch_end = mask & ATPX_GRAPHICS_DEVICE_SWITCH_END_NOTIFICATION_SUPPORTED;
 145         f->disp_connectors_mapping = mask & ATPX_GET_DISPLAY_CONNECTORS_MAPPING_SUPPORTED;
 146         f->disp_detetion_ports = mask & ATPX_GET_DISPLAY_DETECTION_PORTS_SUPPORTED;
 147 }
 148 
 149 /**
 150  * radeon_atpx_validate_functions - validate ATPX functions
 151  *
 152  * @atpx: radeon atpx struct
 153  *
 154  * Validate that required functions are enabled (all asics).
 155  * returns 0 on success, error on failure.
 156  */
 157 static int radeon_atpx_validate(struct radeon_atpx *atpx)
 158 {
 159         u32 valid_bits = 0;
 160 
 161         if (atpx->functions.px_params) {
 162                 union acpi_object *info;
 163                 struct atpx_px_params output;
 164                 size_t size;
 165 
 166                 info = radeon_atpx_call(atpx->handle, ATPX_FUNCTION_GET_PX_PARAMETERS, NULL);
 167                 if (!info)
 168                         return -EIO;
 169 
 170                 memset(&output, 0, sizeof(output));
 171 
 172                 size = *(u16 *) info->buffer.pointer;
 173                 if (size < 10) {
 174                         printk("ATPX buffer is too small: %zu\n", size);
 175                         kfree(info);
 176                         return -EINVAL;
 177                 }
 178                 size = min(sizeof(output), size);
 179 
 180                 memcpy(&output, info->buffer.pointer, size);
 181 
 182                 valid_bits = output.flags & output.valid_flags;
 183 
 184                 kfree(info);
 185         }
 186 
 187         /* if separate mux flag is set, mux controls are required */
 188         if (valid_bits & ATPX_SEPARATE_MUX_FOR_I2C) {
 189                 atpx->functions.i2c_mux_cntl = true;
 190                 atpx->functions.disp_mux_cntl = true;
 191         }
 192         /* if any outputs are muxed, mux controls are required */
 193         if (valid_bits & (ATPX_CRT1_RGB_SIGNAL_MUXED |
 194                           ATPX_TV_SIGNAL_MUXED |
 195                           ATPX_DFP_SIGNAL_MUXED))
 196                 atpx->functions.disp_mux_cntl = true;
 197 
 198         /* some bioses set these bits rather than flagging power_cntl as supported */
 199         if (valid_bits & (ATPX_DYNAMIC_PX_SUPPORTED |
 200                           ATPX_DYNAMIC_DGPU_POWER_OFF_SUPPORTED))
 201                 atpx->functions.power_cntl = true;
 202 
 203         atpx->is_hybrid = false;
 204         if (valid_bits & ATPX_MS_HYBRID_GFX_SUPPORTED) {
 205                 printk("ATPX Hybrid Graphics\n");
 206                 /*
 207                  * Disable legacy PM methods only when pcie port PM is usable,
 208                  * otherwise the device might fail to power off or power on.
 209                  */
 210                 atpx->functions.power_cntl = !radeon_atpx_priv.bridge_pm_usable;
 211                 atpx->is_hybrid = true;
 212         }
 213 
 214         return 0;
 215 }
 216 
 217 /**
 218  * radeon_atpx_verify_interface - verify ATPX
 219  *
 220  * @atpx: radeon atpx struct
 221  *
 222  * Execute the ATPX_FUNCTION_VERIFY_INTERFACE ATPX function
 223  * to initialize ATPX and determine what features are supported
 224  * (all asics).
 225  * returns 0 on success, error on failure.
 226  */
 227 static int radeon_atpx_verify_interface(struct radeon_atpx *atpx)
 228 {
 229         union acpi_object *info;
 230         struct atpx_verify_interface output;
 231         size_t size;
 232         int err = 0;
 233 
 234         info = radeon_atpx_call(atpx->handle, ATPX_FUNCTION_VERIFY_INTERFACE, NULL);
 235         if (!info)
 236                 return -EIO;
 237 
 238         memset(&output, 0, sizeof(output));
 239 
 240         size = *(u16 *) info->buffer.pointer;
 241         if (size < 8) {
 242                 printk("ATPX buffer is too small: %zu\n", size);
 243                 err = -EINVAL;
 244                 goto out;
 245         }
 246         size = min(sizeof(output), size);
 247 
 248         memcpy(&output, info->buffer.pointer, size);
 249 
 250         /* TODO: check version? */
 251         printk("ATPX version %u, functions 0x%08x\n",
 252                output.version, output.function_bits);
 253 
 254         radeon_atpx_parse_functions(&atpx->functions, output.function_bits);
 255 
 256 out:
 257         kfree(info);
 258         return err;
 259 }
 260 
 261 /**
 262  * radeon_atpx_set_discrete_state - power up/down discrete GPU
 263  *
 264  * @atpx: atpx info struct
 265  * @state: discrete GPU state (0 = power down, 1 = power up)
 266  *
 267  * Execute the ATPX_FUNCTION_POWER_CONTROL ATPX function to
 268  * power down/up the discrete GPU (all asics).
 269  * Returns 0 on success, error on failure.
 270  */
 271 static int radeon_atpx_set_discrete_state(struct radeon_atpx *atpx, u8 state)
 272 {
 273         struct acpi_buffer params;
 274         union acpi_object *info;
 275         struct atpx_power_control input;
 276 
 277         if (atpx->functions.power_cntl) {
 278                 input.size = 3;
 279                 input.dgpu_state = state;
 280                 params.length = input.size;
 281                 params.pointer = &input;
 282                 info = radeon_atpx_call(atpx->handle,
 283                                         ATPX_FUNCTION_POWER_CONTROL,
 284                                         &params);
 285                 if (!info)
 286                         return -EIO;
 287                 kfree(info);
 288 
 289                 /* 200ms delay is required after off */
 290                 if (state == 0)
 291                         msleep(200);
 292         }
 293         return 0;
 294 }
 295 
 296 /**
 297  * radeon_atpx_switch_disp_mux - switch display mux
 298  *
 299  * @atpx: atpx info struct
 300  * @mux_id: mux state (0 = integrated GPU, 1 = discrete GPU)
 301  *
 302  * Execute the ATPX_FUNCTION_DISPLAY_MUX_CONTROL ATPX function to
 303  * switch the display mux between the discrete GPU and integrated GPU
 304  * (all asics).
 305  * Returns 0 on success, error on failure.
 306  */
 307 static int radeon_atpx_switch_disp_mux(struct radeon_atpx *atpx, u16 mux_id)
 308 {
 309         struct acpi_buffer params;
 310         union acpi_object *info;
 311         struct atpx_mux input;
 312 
 313         if (atpx->functions.disp_mux_cntl) {
 314                 input.size = 4;
 315                 input.mux = mux_id;
 316                 params.length = input.size;
 317                 params.pointer = &input;
 318                 info = radeon_atpx_call(atpx->handle,
 319                                         ATPX_FUNCTION_DISPLAY_MUX_CONTROL,
 320                                         &params);
 321                 if (!info)
 322                         return -EIO;
 323                 kfree(info);
 324         }
 325         return 0;
 326 }
 327 
 328 /**
 329  * radeon_atpx_switch_i2c_mux - switch i2c/hpd mux
 330  *
 331  * @atpx: atpx info struct
 332  * @mux_id: mux state (0 = integrated GPU, 1 = discrete GPU)
 333  *
 334  * Execute the ATPX_FUNCTION_I2C_MUX_CONTROL ATPX function to
 335  * switch the i2c/hpd mux between the discrete GPU and integrated GPU
 336  * (all asics).
 337  * Returns 0 on success, error on failure.
 338  */
 339 static int radeon_atpx_switch_i2c_mux(struct radeon_atpx *atpx, u16 mux_id)
 340 {
 341         struct acpi_buffer params;
 342         union acpi_object *info;
 343         struct atpx_mux input;
 344 
 345         if (atpx->functions.i2c_mux_cntl) {
 346                 input.size = 4;
 347                 input.mux = mux_id;
 348                 params.length = input.size;
 349                 params.pointer = &input;
 350                 info = radeon_atpx_call(atpx->handle,
 351                                         ATPX_FUNCTION_I2C_MUX_CONTROL,
 352                                         &params);
 353                 if (!info)
 354                         return -EIO;
 355                 kfree(info);
 356         }
 357         return 0;
 358 }
 359 
 360 /**
 361  * radeon_atpx_switch_start - notify the sbios of a GPU switch
 362  *
 363  * @atpx: atpx info struct
 364  * @mux_id: mux state (0 = integrated GPU, 1 = discrete GPU)
 365  *
 366  * Execute the ATPX_FUNCTION_GRAPHICS_DEVICE_SWITCH_START_NOTIFICATION ATPX
 367  * function to notify the sbios that a switch between the discrete GPU and
 368  * integrated GPU has begun (all asics).
 369  * Returns 0 on success, error on failure.
 370  */
 371 static int radeon_atpx_switch_start(struct radeon_atpx *atpx, u16 mux_id)
 372 {
 373         struct acpi_buffer params;
 374         union acpi_object *info;
 375         struct atpx_mux input;
 376 
 377         if (atpx->functions.switch_start) {
 378                 input.size = 4;
 379                 input.mux = mux_id;
 380                 params.length = input.size;
 381                 params.pointer = &input;
 382                 info = radeon_atpx_call(atpx->handle,
 383                                         ATPX_FUNCTION_GRAPHICS_DEVICE_SWITCH_START_NOTIFICATION,
 384                                         &params);
 385                 if (!info)
 386                         return -EIO;
 387                 kfree(info);
 388         }
 389         return 0;
 390 }
 391 
 392 /**
 393  * radeon_atpx_switch_end - notify the sbios of a GPU switch
 394  *
 395  * @atpx: atpx info struct
 396  * @mux_id: mux state (0 = integrated GPU, 1 = discrete GPU)
 397  *
 398  * Execute the ATPX_FUNCTION_GRAPHICS_DEVICE_SWITCH_END_NOTIFICATION ATPX
 399  * function to notify the sbios that a switch between the discrete GPU and
 400  * integrated GPU has ended (all asics).
 401  * Returns 0 on success, error on failure.
 402  */
 403 static int radeon_atpx_switch_end(struct radeon_atpx *atpx, u16 mux_id)
 404 {
 405         struct acpi_buffer params;
 406         union acpi_object *info;
 407         struct atpx_mux input;
 408 
 409         if (atpx->functions.switch_end) {
 410                 input.size = 4;
 411                 input.mux = mux_id;
 412                 params.length = input.size;
 413                 params.pointer = &input;
 414                 info = radeon_atpx_call(atpx->handle,
 415                                         ATPX_FUNCTION_GRAPHICS_DEVICE_SWITCH_END_NOTIFICATION,
 416                                         &params);
 417                 if (!info)
 418                         return -EIO;
 419                 kfree(info);
 420         }
 421         return 0;
 422 }
 423 
 424 /**
 425  * radeon_atpx_switchto - switch to the requested GPU
 426  *
 427  * @id: GPU to switch to
 428  *
 429  * Execute the necessary ATPX functions to switch between the discrete GPU and
 430  * integrated GPU (all asics).
 431  * Returns 0 on success, error on failure.
 432  */
 433 static int radeon_atpx_switchto(enum vga_switcheroo_client_id id)
 434 {
 435         u16 gpu_id;
 436 
 437         if (id == VGA_SWITCHEROO_IGD)
 438                 gpu_id = ATPX_INTEGRATED_GPU;
 439         else
 440                 gpu_id = ATPX_DISCRETE_GPU;
 441 
 442         radeon_atpx_switch_start(&radeon_atpx_priv.atpx, gpu_id);
 443         radeon_atpx_switch_disp_mux(&radeon_atpx_priv.atpx, gpu_id);
 444         radeon_atpx_switch_i2c_mux(&radeon_atpx_priv.atpx, gpu_id);
 445         radeon_atpx_switch_end(&radeon_atpx_priv.atpx, gpu_id);
 446 
 447         return 0;
 448 }
 449 
 450 /**
 451  * radeon_atpx_power_state - power down/up the requested GPU
 452  *
 453  * @id: GPU to power down/up
 454  * @state: requested power state (0 = off, 1 = on)
 455  *
 456  * Execute the necessary ATPX function to power down/up the discrete GPU
 457  * (all asics).
 458  * Returns 0 on success, error on failure.
 459  */
 460 static int radeon_atpx_power_state(enum vga_switcheroo_client_id id,
 461                                    enum vga_switcheroo_state state)
 462 {
 463         /* on w500 ACPI can't change intel gpu state */
 464         if (id == VGA_SWITCHEROO_IGD)
 465                 return 0;
 466 
 467         radeon_atpx_set_discrete_state(&radeon_atpx_priv.atpx, state);
 468         return 0;
 469 }
 470 
 471 /**
 472  * radeon_atpx_pci_probe_handle - look up the ATPX handle
 473  *
 474  * @pdev: pci device
 475  *
 476  * Look up the ATPX handles (all asics).
 477  * Returns true if the handles are found, false if not.
 478  */
 479 static bool radeon_atpx_pci_probe_handle(struct pci_dev *pdev)
 480 {
 481         acpi_handle dhandle, atpx_handle;
 482         acpi_status status;
 483 
 484         dhandle = ACPI_HANDLE(&pdev->dev);
 485         if (!dhandle)
 486                 return false;
 487 
 488         status = acpi_get_handle(dhandle, "ATPX", &atpx_handle);
 489         if (ACPI_FAILURE(status))
 490                 return false;
 491 
 492         radeon_atpx_priv.dhandle = dhandle;
 493         radeon_atpx_priv.atpx.handle = atpx_handle;
 494         return true;
 495 }
 496 
 497 /**
 498  * radeon_atpx_init - verify the ATPX interface
 499  *
 500  * Verify the ATPX interface (all asics).
 501  * Returns 0 on success, error on failure.
 502  */
 503 static int radeon_atpx_init(void)
 504 {
 505         int r;
 506 
 507         /* set up the ATPX handle */
 508         r = radeon_atpx_verify_interface(&radeon_atpx_priv.atpx);
 509         if (r)
 510                 return r;
 511 
 512         /* validate the atpx setup */
 513         r = radeon_atpx_validate(&radeon_atpx_priv.atpx);
 514         if (r)
 515                 return r;
 516 
 517         return 0;
 518 }
 519 
 520 /**
 521  * radeon_atpx_get_client_id - get the client id
 522  *
 523  * @pdev: pci device
 524  *
 525  * look up whether we are the integrated or discrete GPU (all asics).
 526  * Returns the client id.
 527  */
 528 static enum vga_switcheroo_client_id radeon_atpx_get_client_id(struct pci_dev *pdev)
 529 {
 530         if (radeon_atpx_priv.dhandle == ACPI_HANDLE(&pdev->dev))
 531                 return VGA_SWITCHEROO_IGD;
 532         else
 533                 return VGA_SWITCHEROO_DIS;
 534 }
 535 
 536 static const struct vga_switcheroo_handler radeon_atpx_handler = {
 537         .switchto = radeon_atpx_switchto,
 538         .power_state = radeon_atpx_power_state,
 539         .get_client_id = radeon_atpx_get_client_id,
 540 };
 541 
 542 /**
 543  * radeon_atpx_detect - detect whether we have PX
 544  *
 545  * Check if we have a PX system (all asics).
 546  * Returns true if we have a PX system, false if not.
 547  */
 548 static bool radeon_atpx_detect(void)
 549 {
 550         char acpi_method_name[255] = { 0 };
 551         struct acpi_buffer buffer = {sizeof(acpi_method_name), acpi_method_name};
 552         struct pci_dev *pdev = NULL;
 553         bool has_atpx = false;
 554         int vga_count = 0;
 555         bool d3_supported = false;
 556         struct pci_dev *parent_pdev;
 557 
 558         while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) {
 559                 vga_count++;
 560 
 561                 has_atpx |= (radeon_atpx_pci_probe_handle(pdev) == true);
 562 
 563                 parent_pdev = pci_upstream_bridge(pdev);
 564                 d3_supported |= parent_pdev && parent_pdev->bridge_d3;
 565         }
 566 
 567         /* some newer PX laptops mark the dGPU as a non-VGA display device */
 568         while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_OTHER << 8, pdev)) != NULL) {
 569                 vga_count++;
 570 
 571                 has_atpx |= (radeon_atpx_pci_probe_handle(pdev) == true);
 572 
 573                 parent_pdev = pci_upstream_bridge(pdev);
 574                 d3_supported |= parent_pdev && parent_pdev->bridge_d3;
 575         }
 576 
 577         if (has_atpx && vga_count == 2) {
 578                 acpi_get_name(radeon_atpx_priv.atpx.handle, ACPI_FULL_PATHNAME, &buffer);
 579                 pr_info("vga_switcheroo: detected switching method %s handle\n",
 580                         acpi_method_name);
 581                 radeon_atpx_priv.atpx_detected = true;
 582                 radeon_atpx_priv.bridge_pm_usable = d3_supported;
 583                 radeon_atpx_init();
 584                 return true;
 585         }
 586         return false;
 587 }
 588 
 589 /**
 590  * radeon_register_atpx_handler - register with vga_switcheroo
 591  *
 592  * Register the PX callbacks with vga_switcheroo (all asics).
 593  */
 594 void radeon_register_atpx_handler(void)
 595 {
 596         bool r;
 597         enum vga_switcheroo_handler_flags_t handler_flags = 0;
 598 
 599         /* detect if we have any ATPX + 2 VGA in the system */
 600         r = radeon_atpx_detect();
 601         if (!r)
 602                 return;
 603 
 604         vga_switcheroo_register_handler(&radeon_atpx_handler, handler_flags);
 605 }
 606 
 607 /**
 608  * radeon_unregister_atpx_handler - unregister with vga_switcheroo
 609  *
 610  * Unregister the PX callbacks with vga_switcheroo (all asics).
 611  */
 612 void radeon_unregister_atpx_handler(void)
 613 {
 614         vga_switcheroo_unregister_handler();
 615 }

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