| .. | .. |
|---|
| 27 | 27 | #include <linux/power_supply.h> |
|---|
| 28 | 28 | #include <linux/pm_runtime.h> |
|---|
| 29 | 29 | #include <acpi/video.h> |
|---|
| 30 | | -#include <drm/drmP.h> |
|---|
| 30 | + |
|---|
| 31 | 31 | #include <drm/drm_crtc_helper.h> |
|---|
| 32 | 32 | #include "amdgpu.h" |
|---|
| 33 | 33 | #include "amdgpu_pm.h" |
|---|
| 34 | +#include "amdgpu_display.h" |
|---|
| 34 | 35 | #include "amd_acpi.h" |
|---|
| 35 | 36 | #include "atom.h" |
|---|
| 36 | 37 | |
|---|
| .. | .. |
|---|
| 40 | 41 | }; |
|---|
| 41 | 42 | |
|---|
| 42 | 43 | struct amdgpu_atif_notifications { |
|---|
| 43 | | - bool display_switch; |
|---|
| 44 | | - bool expansion_mode_change; |
|---|
| 45 | 44 | bool thermal_state; |
|---|
| 46 | 45 | bool forced_power_state; |
|---|
| 47 | 46 | bool system_power_state; |
|---|
| 48 | | - bool display_conf_change; |
|---|
| 49 | | - bool px_gfx_switch; |
|---|
| 50 | 47 | bool brightness_change; |
|---|
| 51 | 48 | bool dgpu_display_event; |
|---|
| 49 | + bool gpu_package_power_limit; |
|---|
| 52 | 50 | }; |
|---|
| 53 | 51 | |
|---|
| 54 | 52 | struct amdgpu_atif_functions { |
|---|
| 55 | 53 | bool system_params; |
|---|
| 56 | 54 | bool sbios_requests; |
|---|
| 57 | | - bool select_active_disp; |
|---|
| 58 | | - bool lid_state; |
|---|
| 59 | | - bool get_tv_standard; |
|---|
| 60 | | - bool set_tv_standard; |
|---|
| 61 | | - bool get_panel_expansion_mode; |
|---|
| 62 | | - bool set_panel_expansion_mode; |
|---|
| 63 | 55 | bool temperature_change; |
|---|
| 64 | | - bool graphics_device_types; |
|---|
| 56 | + bool query_backlight_transfer_characteristics; |
|---|
| 57 | + bool ready_to_undock; |
|---|
| 58 | + bool external_gpu_information; |
|---|
| 65 | 59 | }; |
|---|
| 66 | 60 | |
|---|
| 67 | 61 | struct amdgpu_atif { |
|---|
| .. | .. |
|---|
| 70 | 64 | struct amdgpu_atif_notifications notifications; |
|---|
| 71 | 65 | struct amdgpu_atif_functions functions; |
|---|
| 72 | 66 | struct amdgpu_atif_notification_cfg notification_cfg; |
|---|
| 73 | | - struct amdgpu_encoder *encoder_for_bl; |
|---|
| 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; |
|---|
| 74 | 71 | }; |
|---|
| 75 | 72 | |
|---|
| 76 | 73 | /* Call the ATIF method |
|---|
| .. | .. |
|---|
| 136 | 133 | */ |
|---|
| 137 | 134 | static void amdgpu_atif_parse_notification(struct amdgpu_atif_notifications *n, u32 mask) |
|---|
| 138 | 135 | { |
|---|
| 139 | | - n->display_switch = mask & ATIF_DISPLAY_SWITCH_REQUEST_SUPPORTED; |
|---|
| 140 | | - n->expansion_mode_change = mask & ATIF_EXPANSION_MODE_CHANGE_REQUEST_SUPPORTED; |
|---|
| 141 | 136 | n->thermal_state = mask & ATIF_THERMAL_STATE_CHANGE_REQUEST_SUPPORTED; |
|---|
| 142 | 137 | n->forced_power_state = mask & ATIF_FORCED_POWER_STATE_CHANGE_REQUEST_SUPPORTED; |
|---|
| 143 | 138 | n->system_power_state = mask & ATIF_SYSTEM_POWER_SOURCE_CHANGE_REQUEST_SUPPORTED; |
|---|
| 144 | | - n->display_conf_change = mask & ATIF_DISPLAY_CONF_CHANGE_REQUEST_SUPPORTED; |
|---|
| 145 | | - n->px_gfx_switch = mask & ATIF_PX_GFX_SWITCH_REQUEST_SUPPORTED; |
|---|
| 146 | 139 | n->brightness_change = mask & ATIF_PANEL_BRIGHTNESS_CHANGE_REQUEST_SUPPORTED; |
|---|
| 147 | 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; |
|---|
| 148 | 142 | } |
|---|
| 149 | 143 | |
|---|
| 150 | 144 | /** |
|---|
| .. | .. |
|---|
| 161 | 155 | { |
|---|
| 162 | 156 | f->system_params = mask & ATIF_GET_SYSTEM_PARAMETERS_SUPPORTED; |
|---|
| 163 | 157 | f->sbios_requests = mask & ATIF_GET_SYSTEM_BIOS_REQUESTS_SUPPORTED; |
|---|
| 164 | | - f->select_active_disp = mask & ATIF_SELECT_ACTIVE_DISPLAYS_SUPPORTED; |
|---|
| 165 | | - f->lid_state = mask & ATIF_GET_LID_STATE_SUPPORTED; |
|---|
| 166 | | - f->get_tv_standard = mask & ATIF_GET_TV_STANDARD_FROM_CMOS_SUPPORTED; |
|---|
| 167 | | - f->set_tv_standard = mask & ATIF_SET_TV_STANDARD_IN_CMOS_SUPPORTED; |
|---|
| 168 | | - f->get_panel_expansion_mode = mask & ATIF_GET_PANEL_EXPANSION_MODE_FROM_CMOS_SUPPORTED; |
|---|
| 169 | | - f->set_panel_expansion_mode = mask & ATIF_SET_PANEL_EXPANSION_MODE_IN_CMOS_SUPPORTED; |
|---|
| 170 | 158 | f->temperature_change = mask & ATIF_TEMPERATURE_CHANGE_NOTIFICATION_SUPPORTED; |
|---|
| 171 | | - f->graphics_device_types = mask & ATIF_GET_GRAPHICS_DEVICE_TYPES_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; |
|---|
| 172 | 163 | } |
|---|
| 173 | 164 | |
|---|
| 174 | 165 | /** |
|---|
| .. | .. |
|---|
| 310 | 301 | } |
|---|
| 311 | 302 | |
|---|
| 312 | 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 | + */ |
|---|
| 319 | +static 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 | + ¶ms); |
|---|
| 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; |
|---|
| 357 | +out: |
|---|
| 358 | + kfree(info); |
|---|
| 359 | + return err; |
|---|
| 360 | +} |
|---|
| 361 | + |
|---|
| 362 | +/** |
|---|
| 313 | 363 | * amdgpu_atif_get_sbios_requests - get requested sbios event |
|---|
| 314 | 364 | * |
|---|
| 315 | 365 | * @handle: acpi handle |
|---|
| .. | .. |
|---|
| 396 | 446 | |
|---|
| 397 | 447 | DRM_DEBUG_DRIVER("ATIF: %d pending SBIOS requests\n", count); |
|---|
| 398 | 448 | |
|---|
| 399 | | - /* todo: add DC handling */ |
|---|
| 400 | | - if ((req.pending & ATIF_PANEL_BRIGHTNESS_CHANGE_REQUEST) && |
|---|
| 401 | | - !amdgpu_device_has_dc_support(adev)) { |
|---|
| 402 | | - struct amdgpu_encoder *enc = atif->encoder_for_bl; |
|---|
| 403 | | - |
|---|
| 404 | | - if (enc) { |
|---|
| 405 | | - struct amdgpu_encoder_atom_dig *dig = enc->enc_priv; |
|---|
| 406 | | - |
|---|
| 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) { |
|---|
| 407 | 452 | DRM_DEBUG_DRIVER("Changing brightness to %d\n", |
|---|
| 408 | 453 | req.backlight_level); |
|---|
| 409 | | - |
|---|
| 410 | | - amdgpu_display_backlight_set_level(adev, enc, req.backlight_level); |
|---|
| 411 | | - |
|---|
| 412 | | -#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) || defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE) |
|---|
| 413 | | - backlight_force_update(dig->bl_dev, |
|---|
| 414 | | - BACKLIGHT_UPDATE_HOTKEY); |
|---|
| 415 | | -#endif |
|---|
| 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); |
|---|
| 416 | 460 | } |
|---|
| 461 | +#endif |
|---|
| 417 | 462 | } |
|---|
| 463 | + |
|---|
| 418 | 464 | if (req.pending & ATIF_DGPU_DISPLAY_EVENT) { |
|---|
| 419 | 465 | if (adev->flags & AMD_IS_PX) { |
|---|
| 420 | | - pm_runtime_get_sync(adev->ddev->dev); |
|---|
| 466 | + pm_runtime_get_sync(adev_to_drm(adev)->dev); |
|---|
| 421 | 467 | /* Just fire off a uevent and let userspace tell us what to do */ |
|---|
| 422 | | - drm_helper_hpd_irq_event(adev->ddev); |
|---|
| 423 | | - pm_runtime_mark_last_busy(adev->ddev->dev); |
|---|
| 424 | | - pm_runtime_put_autosuspend(adev->ddev->dev); |
|---|
| 468 | + drm_helper_hpd_irq_event(adev_to_drm(adev)); |
|---|
| 469 | + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); |
|---|
| 470 | + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); |
|---|
| 425 | 471 | } |
|---|
| 426 | 472 | } |
|---|
| 427 | 473 | /* TODO: check other events */ |
|---|
| .. | .. |
|---|
| 760 | 806 | } |
|---|
| 761 | 807 | adev->atif = atif; |
|---|
| 762 | 808 | |
|---|
| 809 | +#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) || defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE) |
|---|
| 763 | 810 | if (atif->notifications.brightness_change) { |
|---|
| 764 | | - struct drm_encoder *tmp; |
|---|
| 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; |
|---|
| 765 | 818 | |
|---|
| 766 | | - /* Find the encoder controlling the brightness */ |
|---|
| 767 | | - list_for_each_entry(tmp, &adev->ddev->mode_config.encoder_list, |
|---|
| 768 | | - head) { |
|---|
| 769 | | - struct amdgpu_encoder *enc = to_amdgpu_encoder(tmp); |
|---|
| 819 | + /* Find the encoder controlling the brightness */ |
|---|
| 820 | + list_for_each_entry(tmp, &adev_to_drm(adev)->mode_config.encoder_list, |
|---|
| 821 | + head) { |
|---|
| 822 | + struct amdgpu_encoder *enc = to_amdgpu_encoder(tmp); |
|---|
| 770 | 823 | |
|---|
| 771 | | - if ((enc->devices & (ATOM_DEVICE_LCD_SUPPORT)) && |
|---|
| 772 | | - enc->enc_priv) { |
|---|
| 773 | | - struct amdgpu_encoder_atom_dig *dig = enc->enc_priv; |
|---|
| 774 | | - if (dig->bl_dev) { |
|---|
| 775 | | - atif->encoder_for_bl = enc; |
|---|
| 776 | | - break; |
|---|
| 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 | + } |
|---|
| 777 | 831 | } |
|---|
| 778 | 832 | } |
|---|
| 779 | 833 | } |
|---|
| 780 | 834 | } |
|---|
| 835 | +#endif |
|---|
| 781 | 836 | |
|---|
| 782 | 837 | if (atif->functions.sbios_requests && !atif->functions.system_params) { |
|---|
| 783 | 838 | /* XXX check this workraround, if sbios request function is |
|---|
| .. | .. |
|---|
| 797 | 852 | } |
|---|
| 798 | 853 | } |
|---|
| 799 | 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 | + |
|---|
| 800 | 866 | out: |
|---|
| 801 | 867 | adev->acpi_nb.notifier_call = amdgpu_acpi_event; |
|---|
| 802 | 868 | register_acpi_notifier(&adev->acpi_nb); |
|---|
| 803 | 869 | |
|---|
| 804 | 870 | return ret; |
|---|
| 871 | +} |
|---|
| 872 | + |
|---|
| 873 | +void 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; |
|---|
| 805 | 883 | } |
|---|
| 806 | 884 | |
|---|
| 807 | 885 | /** |
|---|
| .. | .. |
|---|
| 814 | 892 | void amdgpu_acpi_fini(struct amdgpu_device *adev) |
|---|
| 815 | 893 | { |
|---|
| 816 | 894 | unregister_acpi_notifier(&adev->acpi_nb); |
|---|
| 817 | | - if (adev->atif) |
|---|
| 818 | | - kfree(adev->atif); |
|---|
| 895 | + kfree(adev->atif); |
|---|
| 819 | 896 | } |
|---|