.. | .. |
---|
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 | } |
---|