Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'drm-next-4.21' of git://people.freedesktop.org/~agd5f/linux into drm-next

amdgpu and amdkfd:
- Freesync support
- ABM support in DC
- KFD support for vega12 and polaris12
- Add sdma paging queue support for vega
- Use ACPI to query backlight range on supported platforms
- Clean up doorbell handling
- KFD fix for pasid handling under non-HWS
- Misc cleanups and fixes

scheduler:
- Revert "fix timeout handling v2"

radeon:
- Fix possible overflow on 32 bit

ttm:
- Fix for LRU handling for ghost objects

Signed-off-by: Dave Airlie <airlied@redhat.com>

From: Alex Deucher <alexdeucher@gmail.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20181130192505.2946-1-alexander.deucher@amd.com

+2901 -1467
+7
Documentation/gpu/drm-kms.rst
··· 575 575 .. kernel-doc:: drivers/gpu/drm/drm_atomic_uapi.c 576 576 :doc: explicit fencing properties 577 577 578 + 579 + Variable Refresh Properties 580 + --------------------------- 581 + 582 + .. kernel-doc:: drivers/gpu/drm/drm_connector.c 583 + :doc: Variable refresh properties 584 + 578 585 Existing KMS Properties 579 586 ----------------------- 580 587
+9 -133
drivers/gpu/drm/amd/amdgpu/amdgpu.h
··· 81 81 #include "amdgpu_job.h" 82 82 #include "amdgpu_bo_list.h" 83 83 #include "amdgpu_gem.h" 84 + #include "amdgpu_doorbell.h" 84 85 85 86 #define MAX_GPU_INSTANCE 16 86 87 ··· 362 361 void amdgpu_fence_slab_fini(void); 363 362 364 363 /* 365 - * GPU doorbell structures, functions & helpers 366 - */ 367 - typedef enum _AMDGPU_DOORBELL_ASSIGNMENT 368 - { 369 - AMDGPU_DOORBELL_KIQ = 0x000, 370 - AMDGPU_DOORBELL_HIQ = 0x001, 371 - AMDGPU_DOORBELL_DIQ = 0x002, 372 - AMDGPU_DOORBELL_MEC_RING0 = 0x010, 373 - AMDGPU_DOORBELL_MEC_RING1 = 0x011, 374 - AMDGPU_DOORBELL_MEC_RING2 = 0x012, 375 - AMDGPU_DOORBELL_MEC_RING3 = 0x013, 376 - AMDGPU_DOORBELL_MEC_RING4 = 0x014, 377 - AMDGPU_DOORBELL_MEC_RING5 = 0x015, 378 - AMDGPU_DOORBELL_MEC_RING6 = 0x016, 379 - AMDGPU_DOORBELL_MEC_RING7 = 0x017, 380 - AMDGPU_DOORBELL_GFX_RING0 = 0x020, 381 - AMDGPU_DOORBELL_sDMA_ENGINE0 = 0x1E0, 382 - AMDGPU_DOORBELL_sDMA_ENGINE1 = 0x1E1, 383 - AMDGPU_DOORBELL_IH = 0x1E8, 384 - AMDGPU_DOORBELL_MAX_ASSIGNMENT = 0x3FF, 385 - AMDGPU_DOORBELL_INVALID = 0xFFFF 386 - } AMDGPU_DOORBELL_ASSIGNMENT; 387 - 388 - struct amdgpu_doorbell { 389 - /* doorbell mmio */ 390 - resource_size_t base; 391 - resource_size_t size; 392 - u32 __iomem *ptr; 393 - u32 num_doorbells; /* Number of doorbells actually reserved for amdgpu. */ 394 - }; 395 - 396 - /* 397 - * 64bit doorbell, offset are in QWORD, occupy 2KB doorbell space 398 - */ 399 - typedef enum _AMDGPU_DOORBELL64_ASSIGNMENT 400 - { 401 - /* 402 - * All compute related doorbells: kiq, hiq, diq, traditional compute queue, user queue, should locate in 403 - * a continues range so that programming CP_MEC_DOORBELL_RANGE_LOWER/UPPER can cover this range. 404 - * Compute related doorbells are allocated from 0x00 to 0x8a 405 - */ 406 - 407 - 408 - /* kernel scheduling */ 409 - AMDGPU_DOORBELL64_KIQ = 0x00, 410 - 411 - /* HSA interface queue and debug queue */ 412 - AMDGPU_DOORBELL64_HIQ = 0x01, 413 - AMDGPU_DOORBELL64_DIQ = 0x02, 414 - 415 - /* Compute engines */ 416 - AMDGPU_DOORBELL64_MEC_RING0 = 0x03, 417 - AMDGPU_DOORBELL64_MEC_RING1 = 0x04, 418 - AMDGPU_DOORBELL64_MEC_RING2 = 0x05, 419 - AMDGPU_DOORBELL64_MEC_RING3 = 0x06, 420 - AMDGPU_DOORBELL64_MEC_RING4 = 0x07, 421 - AMDGPU_DOORBELL64_MEC_RING5 = 0x08, 422 - AMDGPU_DOORBELL64_MEC_RING6 = 0x09, 423 - AMDGPU_DOORBELL64_MEC_RING7 = 0x0a, 424 - 425 - /* User queue doorbell range (128 doorbells) */ 426 - AMDGPU_DOORBELL64_USERQUEUE_START = 0x0b, 427 - AMDGPU_DOORBELL64_USERQUEUE_END = 0x8a, 428 - 429 - /* Graphics engine */ 430 - AMDGPU_DOORBELL64_GFX_RING0 = 0x8b, 431 - 432 - /* 433 - * Other graphics doorbells can be allocated here: from 0x8c to 0xdf 434 - * Graphics voltage island aperture 1 435 - * default non-graphics QWORD index is 0xe0 - 0xFF inclusive 436 - */ 437 - 438 - /* sDMA engines reserved from 0xe0 -0xef */ 439 - AMDGPU_DOORBELL64_sDMA_ENGINE0 = 0xE0, 440 - AMDGPU_DOORBELL64_sDMA_HI_PRI_ENGINE0 = 0xE1, 441 - AMDGPU_DOORBELL64_sDMA_ENGINE1 = 0xE8, 442 - AMDGPU_DOORBELL64_sDMA_HI_PRI_ENGINE1 = 0xE9, 443 - 444 - /* For vega10 sriov, the sdma doorbell must be fixed as follow 445 - * to keep the same setting with host driver, or it will 446 - * happen conflicts 447 - */ 448 - AMDGPU_VEGA10_DOORBELL64_sDMA_ENGINE0 = 0xF0, 449 - AMDGPU_VEGA10_DOORBELL64_sDMA_HI_PRI_ENGINE0 = 0xF1, 450 - AMDGPU_VEGA10_DOORBELL64_sDMA_ENGINE1 = 0xF2, 451 - AMDGPU_VEGA10_DOORBELL64_sDMA_HI_PRI_ENGINE1 = 0xF3, 452 - 453 - /* Interrupt handler */ 454 - AMDGPU_DOORBELL64_IH = 0xF4, /* For legacy interrupt ring buffer */ 455 - AMDGPU_DOORBELL64_IH_RING1 = 0xF5, /* For page migration request log */ 456 - AMDGPU_DOORBELL64_IH_RING2 = 0xF6, /* For page migration translation/invalidation log */ 457 - 458 - /* VCN engine use 32 bits doorbell */ 459 - AMDGPU_DOORBELL64_VCN0_1 = 0xF8, /* lower 32 bits for VNC0 and upper 32 bits for VNC1 */ 460 - AMDGPU_DOORBELL64_VCN2_3 = 0xF9, 461 - AMDGPU_DOORBELL64_VCN4_5 = 0xFA, 462 - AMDGPU_DOORBELL64_VCN6_7 = 0xFB, 463 - 464 - /* overlap the doorbell assignment with VCN as they are mutually exclusive 465 - * VCE engine's doorbell is 32 bit and two VCE ring share one QWORD 466 - */ 467 - AMDGPU_DOORBELL64_UVD_RING0_1 = 0xF8, 468 - AMDGPU_DOORBELL64_UVD_RING2_3 = 0xF9, 469 - AMDGPU_DOORBELL64_UVD_RING4_5 = 0xFA, 470 - AMDGPU_DOORBELL64_UVD_RING6_7 = 0xFB, 471 - 472 - AMDGPU_DOORBELL64_VCE_RING0_1 = 0xFC, 473 - AMDGPU_DOORBELL64_VCE_RING2_3 = 0xFD, 474 - AMDGPU_DOORBELL64_VCE_RING4_5 = 0xFE, 475 - AMDGPU_DOORBELL64_VCE_RING6_7 = 0xFF, 476 - 477 - AMDGPU_DOORBELL64_MAX_ASSIGNMENT = 0xFF, 478 - AMDGPU_DOORBELL64_INVALID = 0xFFFF 479 - } AMDGPU_DOORBELL64_ASSIGNMENT; 480 - 481 - /* 482 364 * IRQS. 483 365 */ 484 366 ··· 538 654 struct amdgpu_ring *ring); 539 655 /* check if the asic needs a full reset of if soft reset will work */ 540 656 bool (*need_full_reset)(struct amdgpu_device *adev); 657 + /* initialize doorbell layout for specific asic*/ 658 + void (*init_doorbell_index)(struct amdgpu_device *adev); 541 659 }; 542 660 543 661 /* ··· 909 1023 unsigned long last_mm_index; 910 1024 bool in_gpu_reset; 911 1025 struct mutex lock_reset; 1026 + struct amdgpu_doorbell_index doorbell_index; 1027 + int asic_reset_res; 912 1028 }; 913 1029 914 1030 static inline struct amdgpu_device *amdgpu_ttm_adev(struct ttm_bo_device *bdev) ··· 934 1046 935 1047 u32 amdgpu_io_rreg(struct amdgpu_device *adev, u32 reg); 936 1048 void amdgpu_io_wreg(struct amdgpu_device *adev, u32 reg, u32 v); 937 - 938 - u32 amdgpu_mm_rdoorbell(struct amdgpu_device *adev, u32 index); 939 - void amdgpu_mm_wdoorbell(struct amdgpu_device *adev, u32 index, u32 v); 940 - u64 amdgpu_mm_rdoorbell64(struct amdgpu_device *adev, u32 index); 941 - void amdgpu_mm_wdoorbell64(struct amdgpu_device *adev, u32 index, u64 v); 942 1049 943 1050 bool amdgpu_device_asic_has_dc_support(enum amd_asic_type asic_type); 944 1051 bool amdgpu_device_has_dc_support(struct amdgpu_device *adev); ··· 996 1113 #define RREG32_IO(reg) amdgpu_io_rreg(adev, (reg)) 997 1114 #define WREG32_IO(reg, v) amdgpu_io_wreg(adev, (reg), (v)) 998 1115 999 - #define RDOORBELL32(index) amdgpu_mm_rdoorbell(adev, (index)) 1000 - #define WDOORBELL32(index, v) amdgpu_mm_wdoorbell(adev, (index), (v)) 1001 - #define RDOORBELL64(index) amdgpu_mm_rdoorbell64(adev, (index)) 1002 - #define WDOORBELL64(index, v) amdgpu_mm_wdoorbell64(adev, (index), (v)) 1003 - 1004 1116 #define REG_FIELD_SHIFT(reg, field) reg##__##field##__SHIFT 1005 1117 #define REG_FIELD_MASK(reg, field) reg##__##field##_MASK 1006 1118 ··· 1037 1159 #define amdgpu_asic_flush_hdp(adev, r) (adev)->asic_funcs->flush_hdp((adev), (r)) 1038 1160 #define amdgpu_asic_invalidate_hdp(adev, r) (adev)->asic_funcs->invalidate_hdp((adev), (r)) 1039 1161 #define amdgpu_asic_need_full_reset(adev) (adev)->asic_funcs->need_full_reset((adev)) 1162 + #define amdgpu_asic_init_doorbell_index(adev) (adev)->asic_funcs->init_doorbell_index((adev)) 1040 1163 1041 1164 /* Common functions */ 1042 1165 bool amdgpu_device_should_recover_gpu(struct amdgpu_device *adev); ··· 1098 1219 long amdgpu_kms_compat_ioctl(struct file *filp, unsigned int cmd, 1099 1220 unsigned long arg); 1100 1221 1101 - 1102 - /* 1103 - * functions used by amdgpu_xgmi.c 1104 - */ 1105 - int amdgpu_xgmi_add_device(struct amdgpu_device *adev); 1106 - 1107 1222 /* 1108 1223 * functions used by amdgpu_encoder.c 1109 1224 */ ··· 1125 1252 int amdgpu_acpi_pcie_performance_request(struct amdgpu_device *adev, 1126 1253 u8 perf_req, bool advertise); 1127 1254 int amdgpu_acpi_pcie_notify_device_ready(struct amdgpu_device *adev); 1255 + 1256 + void amdgpu_acpi_get_backlight_caps(struct amdgpu_device *adev, 1257 + struct amdgpu_dm_backlight_caps *caps); 1128 1258 #else 1129 1259 static inline int amdgpu_acpi_init(struct amdgpu_device *adev) { return 0; } 1130 1260 static inline void amdgpu_acpi_fini(struct amdgpu_device *adev) { }
+92 -22
drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
··· 41 41 }; 42 42 43 43 struct amdgpu_atif_notifications { 44 - bool display_switch; 45 - bool expansion_mode_change; 46 44 bool thermal_state; 47 45 bool forced_power_state; 48 46 bool system_power_state; 49 - bool display_conf_change; 50 - bool px_gfx_switch; 51 47 bool brightness_change; 52 48 bool dgpu_display_event; 49 + bool gpu_package_power_limit; 53 50 }; 54 51 55 52 struct amdgpu_atif_functions { 56 53 bool system_params; 57 54 bool sbios_requests; 58 - bool select_active_disp; 59 - bool lid_state; 60 - bool get_tv_standard; 61 - bool set_tv_standard; 62 - bool get_panel_expansion_mode; 63 - bool set_panel_expansion_mode; 64 55 bool temperature_change; 65 - bool graphics_device_types; 56 + bool query_backlight_transfer_characteristics; 57 + bool ready_to_undock; 58 + bool external_gpu_information; 66 59 }; 67 60 68 61 struct amdgpu_atif { ··· 65 72 struct amdgpu_atif_functions functions; 66 73 struct amdgpu_atif_notification_cfg notification_cfg; 67 74 struct amdgpu_encoder *encoder_for_bl; 75 + struct amdgpu_dm_backlight_caps backlight_caps; 68 76 }; 69 77 70 78 /* Call the ATIF method ··· 131 137 */ 132 138 static void amdgpu_atif_parse_notification(struct amdgpu_atif_notifications *n, u32 mask) 133 139 { 134 - n->display_switch = mask & ATIF_DISPLAY_SWITCH_REQUEST_SUPPORTED; 135 - n->expansion_mode_change = mask & ATIF_EXPANSION_MODE_CHANGE_REQUEST_SUPPORTED; 136 140 n->thermal_state = mask & ATIF_THERMAL_STATE_CHANGE_REQUEST_SUPPORTED; 137 141 n->forced_power_state = mask & ATIF_FORCED_POWER_STATE_CHANGE_REQUEST_SUPPORTED; 138 142 n->system_power_state = mask & ATIF_SYSTEM_POWER_SOURCE_CHANGE_REQUEST_SUPPORTED; 139 - n->display_conf_change = mask & ATIF_DISPLAY_CONF_CHANGE_REQUEST_SUPPORTED; 140 - n->px_gfx_switch = mask & ATIF_PX_GFX_SWITCH_REQUEST_SUPPORTED; 141 143 n->brightness_change = mask & ATIF_PANEL_BRIGHTNESS_CHANGE_REQUEST_SUPPORTED; 142 144 n->dgpu_display_event = mask & ATIF_DGPU_DISPLAY_EVENT_SUPPORTED; 145 + n->gpu_package_power_limit = mask & ATIF_GPU_PACKAGE_POWER_LIMIT_REQUEST_SUPPORTED; 143 146 } 144 147 145 148 /** ··· 153 162 { 154 163 f->system_params = mask & ATIF_GET_SYSTEM_PARAMETERS_SUPPORTED; 155 164 f->sbios_requests = mask & ATIF_GET_SYSTEM_BIOS_REQUESTS_SUPPORTED; 156 - f->select_active_disp = mask & ATIF_SELECT_ACTIVE_DISPLAYS_SUPPORTED; 157 - f->lid_state = mask & ATIF_GET_LID_STATE_SUPPORTED; 158 - f->get_tv_standard = mask & ATIF_GET_TV_STANDARD_FROM_CMOS_SUPPORTED; 159 - f->set_tv_standard = mask & ATIF_SET_TV_STANDARD_IN_CMOS_SUPPORTED; 160 - f->get_panel_expansion_mode = mask & ATIF_GET_PANEL_EXPANSION_MODE_FROM_CMOS_SUPPORTED; 161 - f->set_panel_expansion_mode = mask & ATIF_SET_PANEL_EXPANSION_MODE_IN_CMOS_SUPPORTED; 162 165 f->temperature_change = mask & ATIF_TEMPERATURE_CHANGE_NOTIFICATION_SUPPORTED; 163 - f->graphics_device_types = mask & ATIF_GET_GRAPHICS_DEVICE_TYPES_SUPPORTED; 166 + f->query_backlight_transfer_characteristics = 167 + mask & ATIF_QUERY_BACKLIGHT_TRANSFER_CHARACTERISTICS_SUPPORTED; 168 + f->ready_to_undock = mask & ATIF_READY_TO_UNDOCK_NOTIFICATION_SUPPORTED; 169 + f->external_gpu_information = mask & ATIF_GET_EXTERNAL_GPU_INFORMATION_SUPPORTED; 164 170 } 165 171 166 172 /** ··· 294 306 DRM_DEBUG_DRIVER("Notification %s, command code = %#x\n", 295 307 (n->enabled ? "enabled" : "disabled"), 296 308 n->command_code); 309 + kfree(info); 310 + return err; 311 + } 312 + 313 + /** 314 + * amdgpu_atif_query_backlight_caps - get min and max backlight input signal 315 + * 316 + * @handle: acpi handle 317 + * 318 + * Execute the QUERY_BRIGHTNESS_TRANSFER_CHARACTERISTICS ATIF function 319 + * to determine the acceptable range of backlight values 320 + * 321 + * Backlight_caps.caps_valid will be set to true if the query is successful 322 + * 323 + * The input signals are in range 0-255 324 + * 325 + * This function assumes the display with backlight is the first LCD 326 + * 327 + * Returns 0 on success, error on failure. 328 + */ 329 + static int amdgpu_atif_query_backlight_caps(struct amdgpu_atif *atif) 330 + { 331 + union acpi_object *info; 332 + struct atif_qbtc_output characteristics; 333 + struct atif_qbtc_arguments arguments; 334 + struct acpi_buffer params; 335 + size_t size; 336 + int err = 0; 337 + 338 + arguments.size = sizeof(arguments); 339 + arguments.requested_display = ATIF_QBTC_REQUEST_LCD1; 340 + 341 + params.length = sizeof(arguments); 342 + params.pointer = (void *)&arguments; 343 + 344 + info = amdgpu_atif_call(atif, 345 + ATIF_FUNCTION_QUERY_BRIGHTNESS_TRANSFER_CHARACTERISTICS, 346 + &params); 347 + if (!info) { 348 + err = -EIO; 349 + goto out; 350 + } 351 + 352 + size = *(u16 *) info->buffer.pointer; 353 + if (size < 10) { 354 + err = -EINVAL; 355 + goto out; 356 + } 357 + 358 + memset(&characteristics, 0, sizeof(characteristics)); 359 + size = min(sizeof(characteristics), size); 360 + memcpy(&characteristics, info->buffer.pointer, size); 361 + 362 + atif->backlight_caps.caps_valid = true; 363 + atif->backlight_caps.min_input_signal = 364 + characteristics.min_input_signal; 365 + atif->backlight_caps.max_input_signal = 366 + characteristics.max_input_signal; 367 + out: 297 368 kfree(info); 298 369 return err; 299 370 } ··· 846 799 } 847 800 } 848 801 802 + if (atif->functions.query_backlight_transfer_characteristics) { 803 + ret = amdgpu_atif_query_backlight_caps(atif); 804 + if (ret) { 805 + DRM_DEBUG_DRIVER("Call to QUERY_BACKLIGHT_TRANSFER_CHARACTERISTICS failed: %d\n", 806 + ret); 807 + atif->backlight_caps.caps_valid = false; 808 + } 809 + } else { 810 + atif->backlight_caps.caps_valid = false; 811 + } 812 + 849 813 out: 850 814 adev->acpi_nb.notifier_call = amdgpu_acpi_event; 851 815 register_acpi_notifier(&adev->acpi_nb); 852 816 853 817 return ret; 818 + } 819 + 820 + void amdgpu_acpi_get_backlight_caps(struct amdgpu_device *adev, 821 + struct amdgpu_dm_backlight_caps *caps) 822 + { 823 + if (!adev->atif) { 824 + caps->caps_valid = false; 825 + return; 826 + } 827 + caps->caps_valid = adev->atif->backlight_caps.caps_valid; 828 + caps->min_input_signal = adev->atif->backlight_caps.min_input_signal; 829 + caps->max_input_signal = adev->atif->backlight_caps.max_input_signal; 854 830 } 855 831 856 832 /**
+10 -19
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
··· 73 73 case CHIP_FIJI: 74 74 case CHIP_POLARIS10: 75 75 case CHIP_POLARIS11: 76 + case CHIP_POLARIS12: 76 77 kfd2kgd = amdgpu_amdkfd_gfx_8_0_get_functions(); 77 78 break; 78 79 case CHIP_VEGA10: 80 + case CHIP_VEGA12: 79 81 case CHIP_VEGA20: 80 82 case CHIP_RAVEN: 81 83 kfd2kgd = amdgpu_amdkfd_gfx_9_0_get_functions(); ··· 181 179 * process in case of 64-bit doorbells so we 182 180 * can use each doorbell assignment twice. 183 181 */ 184 - if (adev->asic_type == CHIP_VEGA10) { 185 - gpu_resources.sdma_doorbell[0][i] = 186 - AMDGPU_VEGA10_DOORBELL64_sDMA_ENGINE0 + (i >> 1); 187 - gpu_resources.sdma_doorbell[0][i+1] = 188 - AMDGPU_VEGA10_DOORBELL64_sDMA_ENGINE0 + 0x200 + (i >> 1); 189 - gpu_resources.sdma_doorbell[1][i] = 190 - AMDGPU_VEGA10_DOORBELL64_sDMA_ENGINE1 + (i >> 1); 191 - gpu_resources.sdma_doorbell[1][i+1] = 192 - AMDGPU_VEGA10_DOORBELL64_sDMA_ENGINE1 + 0x200 + (i >> 1); 193 - } else { 194 - gpu_resources.sdma_doorbell[0][i] = 195 - AMDGPU_DOORBELL64_sDMA_ENGINE0 + (i >> 1); 196 - gpu_resources.sdma_doorbell[0][i+1] = 197 - AMDGPU_DOORBELL64_sDMA_ENGINE0 + 0x200 + (i >> 1); 198 - gpu_resources.sdma_doorbell[1][i] = 199 - AMDGPU_DOORBELL64_sDMA_ENGINE1 + (i >> 1); 200 - gpu_resources.sdma_doorbell[1][i+1] = 201 - AMDGPU_DOORBELL64_sDMA_ENGINE1 + 0x200 + (i >> 1); 202 - } 182 + gpu_resources.sdma_doorbell[0][i] = 183 + adev->doorbell_index.sdma_engine0 + (i >> 1); 184 + gpu_resources.sdma_doorbell[0][i+1] = 185 + adev->doorbell_index.sdma_engine0 + 0x200 + (i >> 1); 186 + gpu_resources.sdma_doorbell[1][i] = 187 + adev->doorbell_index.sdma_engine1 + (i >> 1); 188 + gpu_resources.sdma_doorbell[1][i+1] = 189 + adev->doorbell_index.sdma_engine1 + 0x200 + (i >> 1); 203 190 } 204 191 /* Doorbells 0x0e0-0ff and 0x2e0-2ff are reserved for 205 192 * SDMA, IH and VCN. So don't use them for the CP.
+96 -75
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
··· 46 46 /* Impose limit on how much memory KFD can use */ 47 47 static struct { 48 48 uint64_t max_system_mem_limit; 49 - uint64_t max_userptr_mem_limit; 49 + uint64_t max_ttm_mem_limit; 50 50 int64_t system_mem_used; 51 - int64_t userptr_mem_used; 51 + int64_t ttm_mem_used; 52 52 spinlock_t mem_limit_lock; 53 53 } kfd_mem_limit; 54 54 ··· 90 90 } 91 91 92 92 /* Set memory usage limits. Current, limits are 93 - * System (kernel) memory - 3/8th System RAM 94 - * Userptr memory - 3/4th System RAM 93 + * System (TTM + userptr) memory - 3/4th System RAM 94 + * TTM memory - 3/8th System RAM 95 95 */ 96 96 void amdgpu_amdkfd_gpuvm_init_mem_limits(void) 97 97 { ··· 103 103 mem *= si.mem_unit; 104 104 105 105 spin_lock_init(&kfd_mem_limit.mem_limit_lock); 106 - kfd_mem_limit.max_system_mem_limit = (mem >> 1) - (mem >> 3); 107 - kfd_mem_limit.max_userptr_mem_limit = mem - (mem >> 2); 108 - pr_debug("Kernel memory limit %lluM, userptr limit %lluM\n", 106 + kfd_mem_limit.max_system_mem_limit = (mem >> 1) + (mem >> 2); 107 + kfd_mem_limit.max_ttm_mem_limit = (mem >> 1) - (mem >> 3); 108 + pr_debug("Kernel memory limit %lluM, TTM limit %lluM\n", 109 109 (kfd_mem_limit.max_system_mem_limit >> 20), 110 - (kfd_mem_limit.max_userptr_mem_limit >> 20)); 110 + (kfd_mem_limit.max_ttm_mem_limit >> 20)); 111 111 } 112 112 113 113 static int amdgpu_amdkfd_reserve_system_mem_limit(struct amdgpu_device *adev, 114 - uint64_t size, u32 domain) 114 + uint64_t size, u32 domain, bool sg) 115 115 { 116 - size_t acc_size; 116 + size_t acc_size, system_mem_needed, ttm_mem_needed; 117 117 int ret = 0; 118 118 119 119 acc_size = ttm_bo_dma_acc_size(&adev->mman.bdev, size, 120 120 sizeof(struct amdgpu_bo)); 121 121 122 122 spin_lock(&kfd_mem_limit.mem_limit_lock); 123 + 123 124 if (domain == AMDGPU_GEM_DOMAIN_GTT) { 124 - if (kfd_mem_limit.system_mem_used + (acc_size + size) > 125 - kfd_mem_limit.max_system_mem_limit) { 126 - ret = -ENOMEM; 127 - goto err_no_mem; 128 - } 129 - kfd_mem_limit.system_mem_used += (acc_size + size); 130 - } else if (domain == AMDGPU_GEM_DOMAIN_CPU) { 131 - if ((kfd_mem_limit.system_mem_used + acc_size > 132 - kfd_mem_limit.max_system_mem_limit) || 133 - (kfd_mem_limit.userptr_mem_used + (size + acc_size) > 134 - kfd_mem_limit.max_userptr_mem_limit)) { 135 - ret = -ENOMEM; 136 - goto err_no_mem; 137 - } 138 - kfd_mem_limit.system_mem_used += acc_size; 139 - kfd_mem_limit.userptr_mem_used += size; 125 + /* TTM GTT memory */ 126 + system_mem_needed = acc_size + size; 127 + ttm_mem_needed = acc_size + size; 128 + } else if (domain == AMDGPU_GEM_DOMAIN_CPU && !sg) { 129 + /* Userptr */ 130 + system_mem_needed = acc_size + size; 131 + ttm_mem_needed = acc_size; 132 + } else { 133 + /* VRAM and SG */ 134 + system_mem_needed = acc_size; 135 + ttm_mem_needed = acc_size; 140 136 } 141 - err_no_mem: 137 + 138 + if ((kfd_mem_limit.system_mem_used + system_mem_needed > 139 + kfd_mem_limit.max_system_mem_limit) || 140 + (kfd_mem_limit.ttm_mem_used + ttm_mem_needed > 141 + kfd_mem_limit.max_ttm_mem_limit)) 142 + ret = -ENOMEM; 143 + else { 144 + kfd_mem_limit.system_mem_used += system_mem_needed; 145 + kfd_mem_limit.ttm_mem_used += ttm_mem_needed; 146 + } 147 + 142 148 spin_unlock(&kfd_mem_limit.mem_limit_lock); 143 149 return ret; 144 150 } 145 151 146 152 static void unreserve_system_mem_limit(struct amdgpu_device *adev, 147 - uint64_t size, u32 domain) 153 + uint64_t size, u32 domain, bool sg) 148 154 { 149 155 size_t acc_size; 150 156 ··· 160 154 spin_lock(&kfd_mem_limit.mem_limit_lock); 161 155 if (domain == AMDGPU_GEM_DOMAIN_GTT) { 162 156 kfd_mem_limit.system_mem_used -= (acc_size + size); 163 - } else if (domain == AMDGPU_GEM_DOMAIN_CPU) { 157 + kfd_mem_limit.ttm_mem_used -= (acc_size + size); 158 + } else if (domain == AMDGPU_GEM_DOMAIN_CPU && !sg) { 159 + kfd_mem_limit.system_mem_used -= (acc_size + size); 160 + kfd_mem_limit.ttm_mem_used -= acc_size; 161 + } else { 164 162 kfd_mem_limit.system_mem_used -= acc_size; 165 - kfd_mem_limit.userptr_mem_used -= size; 163 + kfd_mem_limit.ttm_mem_used -= acc_size; 166 164 } 167 165 WARN_ONCE(kfd_mem_limit.system_mem_used < 0, 168 166 "kfd system memory accounting unbalanced"); 169 - WARN_ONCE(kfd_mem_limit.userptr_mem_used < 0, 170 - "kfd userptr memory accounting unbalanced"); 167 + WARN_ONCE(kfd_mem_limit.ttm_mem_used < 0, 168 + "kfd TTM memory accounting unbalanced"); 171 169 172 170 spin_unlock(&kfd_mem_limit.mem_limit_lock); 173 171 } ··· 181 171 spin_lock(&kfd_mem_limit.mem_limit_lock); 182 172 183 173 if (bo->flags & AMDGPU_AMDKFD_USERPTR_BO) { 184 - kfd_mem_limit.system_mem_used -= bo->tbo.acc_size; 185 - kfd_mem_limit.userptr_mem_used -= amdgpu_bo_size(bo); 174 + kfd_mem_limit.system_mem_used -= 175 + (bo->tbo.acc_size + amdgpu_bo_size(bo)); 176 + kfd_mem_limit.ttm_mem_used -= bo->tbo.acc_size; 186 177 } else if (bo->preferred_domains == AMDGPU_GEM_DOMAIN_GTT) { 187 178 kfd_mem_limit.system_mem_used -= 188 179 (bo->tbo.acc_size + amdgpu_bo_size(bo)); 180 + kfd_mem_limit.ttm_mem_used -= 181 + (bo->tbo.acc_size + amdgpu_bo_size(bo)); 182 + } else { 183 + kfd_mem_limit.system_mem_used -= bo->tbo.acc_size; 184 + kfd_mem_limit.ttm_mem_used -= bo->tbo.acc_size; 189 185 } 190 186 WARN_ONCE(kfd_mem_limit.system_mem_used < 0, 191 187 "kfd system memory accounting unbalanced"); 192 - WARN_ONCE(kfd_mem_limit.userptr_mem_used < 0, 193 - "kfd userptr memory accounting unbalanced"); 188 + WARN_ONCE(kfd_mem_limit.ttm_mem_used < 0, 189 + "kfd TTM memory accounting unbalanced"); 194 190 195 191 spin_unlock(&kfd_mem_limit.mem_limit_lock); 196 192 } ··· 411 395 return 0; 412 396 } 413 397 414 - static int sync_vm_fence(struct amdgpu_device *adev, struct amdgpu_sync *sync, 415 - struct dma_fence *f) 416 - { 417 - int ret = amdgpu_sync_fence(adev, sync, f, false); 418 - 419 - /* Sync objects can't handle multiple GPUs (contexts) updating 420 - * sync->last_vm_update. Fortunately we don't need it for 421 - * KFD's purposes, so we can just drop that fence. 422 - */ 423 - if (sync->last_vm_update) { 424 - dma_fence_put(sync->last_vm_update); 425 - sync->last_vm_update = NULL; 426 - } 427 - 428 - return ret; 429 - } 430 - 431 398 static int vm_update_pds(struct amdgpu_vm *vm, struct amdgpu_sync *sync) 432 399 { 433 400 struct amdgpu_bo *pd = vm->root.base.bo; ··· 421 422 if (ret) 422 423 return ret; 423 424 424 - return sync_vm_fence(adev, sync, vm->last_update); 425 + return amdgpu_sync_fence(NULL, sync, vm->last_update, false); 425 426 } 426 427 427 428 /* add_bo_to_vm - Add a BO to a VM ··· 825 826 /* Add the eviction fence back */ 826 827 amdgpu_bo_fence(pd, &vm->process_info->eviction_fence->base, true); 827 828 828 - sync_vm_fence(adev, sync, bo_va->last_pt_update); 829 + amdgpu_sync_fence(NULL, sync, bo_va->last_pt_update, false); 829 830 830 831 return 0; 831 832 } ··· 850 851 return ret; 851 852 } 852 853 853 - return sync_vm_fence(adev, sync, bo_va->last_pt_update); 854 + return amdgpu_sync_fence(NULL, sync, bo_va->last_pt_update, false); 854 855 } 855 856 856 857 static int map_bo_to_gpuvm(struct amdgpu_device *adev, ··· 893 894 list_for_each_entry(peer_vm, &process_info->vm_list_head, 894 895 vm_list_node) { 895 896 ret = vm_validate_pt_pd_bos(peer_vm); 897 + if (ret) 898 + return ret; 899 + } 900 + 901 + return 0; 902 + } 903 + 904 + static int process_sync_pds_resv(struct amdkfd_process_info *process_info, 905 + struct amdgpu_sync *sync) 906 + { 907 + struct amdgpu_vm *peer_vm; 908 + int ret; 909 + 910 + list_for_each_entry(peer_vm, &process_info->vm_list_head, 911 + vm_list_node) { 912 + struct amdgpu_bo *pd = peer_vm->root.base.bo; 913 + 914 + ret = amdgpu_sync_resv(NULL, 915 + sync, pd->tbo.resv, 916 + AMDGPU_FENCE_OWNER_UNDEFINED, false); 896 917 if (ret) 897 918 return ret; 898 919 } ··· 1218 1199 byte_align = (adev->family == AMDGPU_FAMILY_VI && 1219 1200 adev->asic_type != CHIP_FIJI && 1220 1201 adev->asic_type != CHIP_POLARIS10 && 1221 - adev->asic_type != CHIP_POLARIS11) ? 1202 + adev->asic_type != CHIP_POLARIS11 && 1203 + adev->asic_type != CHIP_POLARIS12) ? 1222 1204 VI_BO_SIZE_ALIGN : 1; 1223 1205 1224 1206 mapping_flags = AMDGPU_VM_PAGE_READABLE; ··· 1235 1215 1236 1216 amdgpu_sync_create(&(*mem)->sync); 1237 1217 1238 - ret = amdgpu_amdkfd_reserve_system_mem_limit(adev, size, alloc_domain); 1218 + ret = amdgpu_amdkfd_reserve_system_mem_limit(adev, size, 1219 + alloc_domain, false); 1239 1220 if (ret) { 1240 1221 pr_debug("Insufficient system memory\n"); 1241 - goto err_reserve_system_mem; 1222 + goto err_reserve_limit; 1242 1223 } 1243 1224 1244 1225 pr_debug("\tcreate BO VA 0x%llx size 0x%llx domain %s\n", ··· 1287 1266 allocate_init_user_pages_failed: 1288 1267 amdgpu_bo_unref(&bo); 1289 1268 /* Don't unreserve system mem limit twice */ 1290 - goto err_reserve_system_mem; 1269 + goto err_reserve_limit; 1291 1270 err_bo_create: 1292 - unreserve_system_mem_limit(adev, size, alloc_domain); 1293 - err_reserve_system_mem: 1271 + unreserve_system_mem_limit(adev, size, alloc_domain, false); 1272 + err_reserve_limit: 1294 1273 mutex_destroy(&(*mem)->lock); 1295 1274 kfree(*mem); 1296 1275 return ret; ··· 1426 1405 * the queues are still stopped and we can leave mapping for 1427 1406 * the next restore worker 1428 1407 */ 1429 - if (bo->tbo.mem.mem_type == TTM_PL_SYSTEM) 1408 + if (amdgpu_ttm_tt_get_usermm(bo->tbo.ttm) && 1409 + bo->tbo.mem.mem_type == TTM_PL_SYSTEM) 1430 1410 is_invalid_userptr = true; 1431 1411 1432 1412 if (check_if_add_bo_to_vm(avm, mem)) { ··· 2066 2044 if (ret) 2067 2045 goto validate_map_fail; 2068 2046 2069 - /* Wait for PD/PTs validate to finish */ 2070 - /* FIXME: I think this isn't needed */ 2071 - list_for_each_entry(peer_vm, &process_info->vm_list_head, 2072 - vm_list_node) { 2073 - struct amdgpu_bo *bo = peer_vm->root.base.bo; 2074 - 2075 - ttm_bo_wait(&bo->tbo, false, false); 2047 + ret = process_sync_pds_resv(process_info, &sync_obj); 2048 + if (ret) { 2049 + pr_debug("Memory eviction: Failed to sync to PD BO moving fence. Try again\n"); 2050 + goto validate_map_fail; 2076 2051 } 2077 2052 2078 2053 /* Validate BOs and map them to GPUVM (update VM page tables). */ ··· 2085 2066 pr_debug("Memory eviction: Validate BOs failed. Try again\n"); 2086 2067 goto validate_map_fail; 2087 2068 } 2088 - 2069 + ret = amdgpu_sync_fence(NULL, &sync_obj, bo->tbo.moving, false); 2070 + if (ret) { 2071 + pr_debug("Memory eviction: Sync BO fence failed. Try again\n"); 2072 + goto validate_map_fail; 2073 + } 2089 2074 list_for_each_entry(bo_va_entry, &mem->bo_va_list, 2090 2075 bo_list) { 2091 2076 ret = update_gpuvm_pte((struct amdgpu_device *) ··· 2110 2087 goto validate_map_fail; 2111 2088 } 2112 2089 2090 + /* Wait for validate and PT updates to finish */ 2113 2091 amdgpu_sync_wait(&sync_obj, false); 2114 2092 2115 2093 /* Release old eviction fence and create new one, because fence only ··· 2129 2105 process_info->eviction_fence = new_fence; 2130 2106 *ef = dma_fence_get(&new_fence->base); 2131 2107 2132 - /* Wait for validate to finish and attach new eviction fence */ 2133 - list_for_each_entry(mem, &process_info->kfd_bo_list, 2134 - validate_list.head) 2135 - ttm_bo_wait(&mem->bo->tbo, false, false); 2108 + /* Attach new eviction fence to all BOs */ 2136 2109 list_for_each_entry(mem, &process_info->kfd_bo_list, 2137 2110 validate_list.head) 2138 2111 amdgpu_bo_fence(mem->bo,
+1 -1
drivers/gpu/drm/amd/amdgpu/amdgpu_csa.c
··· 43 43 r = amdgpu_bo_create_kernel(adev, size, PAGE_SIZE, 44 44 domain, bo, 45 45 NULL, &ptr); 46 - if (!bo) 46 + if (!*bo) 47 47 return -ENOMEM; 48 48 49 49 memset(ptr, 0, size);
+1
drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c
··· 39 39 [AMDGPU_HW_IP_UVD_ENC] = 1, 40 40 [AMDGPU_HW_IP_VCN_DEC] = 1, 41 41 [AMDGPU_HW_IP_VCN_ENC] = 1, 42 + [AMDGPU_HW_IP_VCN_JPEG] = 1, 42 43 }; 43 44 44 45 static int amdgput_ctx_total_num_entities(void)
+272 -121
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
··· 59 59 #include "amdgpu_amdkfd.h" 60 60 #include "amdgpu_pm.h" 61 61 62 + #include "amdgpu_xgmi.h" 63 + 62 64 MODULE_FIRMWARE("amdgpu/vega10_gpu_info.bin"); 63 65 MODULE_FIRMWARE("amdgpu/vega12_gpu_info.bin"); 64 66 MODULE_FIRMWARE("amdgpu/raven_gpu_info.bin"); ··· 515 513 */ 516 514 static int amdgpu_device_doorbell_init(struct amdgpu_device *adev) 517 515 { 516 + amdgpu_asic_init_doorbell_index(adev); 517 + 518 518 /* No doorbell on SI hardware generation */ 519 519 if (adev->asic_type < CHIP_BONAIRE) { 520 520 adev->doorbell.base = 0; ··· 534 530 adev->doorbell.size = pci_resource_len(adev->pdev, 2); 535 531 536 532 adev->doorbell.num_doorbells = min_t(u32, adev->doorbell.size / sizeof(u32), 537 - AMDGPU_DOORBELL_MAX_ASSIGNMENT+1); 533 + adev->doorbell_index.max_assignment+1); 538 534 if (adev->doorbell.num_doorbells == 0) 539 535 return -EINVAL; 536 + 537 + /* For Vega, reserve and map two pages on doorbell BAR since SDMA 538 + * paging queue doorbell use the second page. The 539 + * AMDGPU_DOORBELL64_MAX_ASSIGNMENT definition assumes all the 540 + * doorbells are in the first page. So with paging queue enabled, 541 + * the max num_doorbells should + 1 page (0x400 in dword) 542 + */ 543 + if (adev->asic_type >= CHIP_VEGA10) 544 + adev->doorbell.num_doorbells += 0x400; 540 545 541 546 adev->doorbell.ptr = ioremap(adev->doorbell.base, 542 547 adev->doorbell.num_doorbells * ··· 2471 2458 DRM_INFO("register mmio base: 0x%08X\n", (uint32_t)adev->rmmio_base); 2472 2459 DRM_INFO("register mmio size: %u\n", (unsigned)adev->rmmio_size); 2473 2460 2474 - /* doorbell bar mapping */ 2475 - amdgpu_device_doorbell_init(adev); 2476 - 2477 2461 /* io port mapping */ 2478 2462 for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { 2479 2463 if (pci_resource_flags(adev->pdev, i) & IORESOURCE_IO) { ··· 2488 2478 r = amdgpu_device_ip_early_init(adev); 2489 2479 if (r) 2490 2480 return r; 2481 + 2482 + /* doorbell bar mapping and doorbell index init*/ 2483 + amdgpu_device_doorbell_init(adev); 2491 2484 2492 2485 /* if we have > 1 VGA cards, then disable the amdgpu VGA resources */ 2493 2486 /* this will fail for cards that aren't VGA class devices, just ··· 3164 3151 return 0; 3165 3152 } 3166 3153 3167 - /** 3168 - * amdgpu_device_reset - reset ASIC/GPU for bare-metal or passthrough 3169 - * 3170 - * @adev: amdgpu device pointer 3171 - * 3172 - * attempt to do soft-reset or full-reset and reinitialize Asic 3173 - * return 0 means succeeded otherwise failed 3174 - */ 3175 - static int amdgpu_device_reset(struct amdgpu_device *adev) 3176 - { 3177 - bool need_full_reset, vram_lost = 0; 3178 - int r; 3179 - 3180 - need_full_reset = amdgpu_device_ip_need_full_reset(adev); 3181 - 3182 - if (!need_full_reset) { 3183 - amdgpu_device_ip_pre_soft_reset(adev); 3184 - r = amdgpu_device_ip_soft_reset(adev); 3185 - amdgpu_device_ip_post_soft_reset(adev); 3186 - if (r || amdgpu_device_ip_check_soft_reset(adev)) { 3187 - DRM_INFO("soft reset failed, will fallback to full reset!\n"); 3188 - need_full_reset = true; 3189 - } 3190 - } 3191 - 3192 - if (need_full_reset) { 3193 - r = amdgpu_device_ip_suspend(adev); 3194 - 3195 - retry: 3196 - r = amdgpu_asic_reset(adev); 3197 - /* post card */ 3198 - amdgpu_atom_asic_init(adev->mode_info.atom_context); 3199 - 3200 - if (!r) { 3201 - dev_info(adev->dev, "GPU reset succeeded, trying to resume\n"); 3202 - r = amdgpu_device_ip_resume_phase1(adev); 3203 - if (r) 3204 - goto out; 3205 - 3206 - vram_lost = amdgpu_device_check_vram_lost(adev); 3207 - if (vram_lost) { 3208 - DRM_ERROR("VRAM is lost!\n"); 3209 - atomic_inc(&adev->vram_lost_counter); 3210 - } 3211 - 3212 - r = amdgpu_gtt_mgr_recover( 3213 - &adev->mman.bdev.man[TTM_PL_TT]); 3214 - if (r) 3215 - goto out; 3216 - 3217 - r = amdgpu_device_fw_loading(adev); 3218 - if (r) 3219 - return r; 3220 - 3221 - r = amdgpu_device_ip_resume_phase2(adev); 3222 - if (r) 3223 - goto out; 3224 - 3225 - if (vram_lost) 3226 - amdgpu_device_fill_reset_magic(adev); 3227 - } 3228 - } 3229 - 3230 - out: 3231 - if (!r) { 3232 - amdgpu_irq_gpu_reset_resume_helper(adev); 3233 - r = amdgpu_ib_ring_tests(adev); 3234 - if (r) { 3235 - dev_err(adev->dev, "ib ring test failed (%d).\n", r); 3236 - r = amdgpu_device_ip_suspend(adev); 3237 - need_full_reset = true; 3238 - goto retry; 3239 - } 3240 - } 3241 - 3242 - if (!r) 3243 - r = amdgpu_device_recover_vram(adev); 3244 - 3245 - return r; 3246 - } 3247 3154 3248 3155 /** 3249 3156 * amdgpu_device_reset_sriov - reset ASIC for SR-IOV vf ··· 3262 3329 return false; 3263 3330 } 3264 3331 3265 - /** 3266 - * amdgpu_device_gpu_recover - reset the asic and recover scheduler 3267 - * 3268 - * @adev: amdgpu device pointer 3269 - * @job: which job trigger hang 3270 - * 3271 - * Attempt to reset the GPU if it has hung (all asics). 3272 - * Returns 0 for success or an error on failure. 3273 - */ 3274 - int amdgpu_device_gpu_recover(struct amdgpu_device *adev, 3275 - struct amdgpu_job *job) 3332 + 3333 + static int amdgpu_device_pre_asic_reset(struct amdgpu_device *adev, 3334 + struct amdgpu_job *job, 3335 + bool *need_full_reset_arg) 3276 3336 { 3277 - int i, r, resched; 3278 - 3279 - dev_info(adev->dev, "GPU reset begin!\n"); 3280 - 3281 - mutex_lock(&adev->lock_reset); 3282 - atomic_inc(&adev->gpu_reset_counter); 3283 - adev->in_gpu_reset = 1; 3284 - 3285 - /* Block kfd */ 3286 - amdgpu_amdkfd_pre_reset(adev); 3287 - 3288 - /* block TTM */ 3289 - resched = ttm_bo_lock_delayed_workqueue(&adev->mman.bdev); 3337 + int i, r = 0; 3338 + bool need_full_reset = *need_full_reset_arg; 3290 3339 3291 3340 /* block all schedulers and reset given job's ring */ 3292 3341 for (i = 0; i < AMDGPU_MAX_RINGS; ++i) { ··· 3288 3373 amdgpu_fence_driver_force_completion(ring); 3289 3374 } 3290 3375 3291 - if (amdgpu_sriov_vf(adev)) 3292 - r = amdgpu_device_reset_sriov(adev, job ? false : true); 3293 - else 3294 - r = amdgpu_device_reset(adev); 3376 + 3377 + 3378 + if (!amdgpu_sriov_vf(adev)) { 3379 + 3380 + if (!need_full_reset) 3381 + need_full_reset = amdgpu_device_ip_need_full_reset(adev); 3382 + 3383 + if (!need_full_reset) { 3384 + amdgpu_device_ip_pre_soft_reset(adev); 3385 + r = amdgpu_device_ip_soft_reset(adev); 3386 + amdgpu_device_ip_post_soft_reset(adev); 3387 + if (r || amdgpu_device_ip_check_soft_reset(adev)) { 3388 + DRM_INFO("soft reset failed, will fallback to full reset!\n"); 3389 + need_full_reset = true; 3390 + } 3391 + } 3392 + 3393 + if (need_full_reset) 3394 + r = amdgpu_device_ip_suspend(adev); 3395 + 3396 + *need_full_reset_arg = need_full_reset; 3397 + } 3398 + 3399 + return r; 3400 + } 3401 + 3402 + static int amdgpu_do_asic_reset(struct amdgpu_hive_info *hive, 3403 + struct list_head *device_list_handle, 3404 + bool *need_full_reset_arg) 3405 + { 3406 + struct amdgpu_device *tmp_adev = NULL; 3407 + bool need_full_reset = *need_full_reset_arg, vram_lost = false; 3408 + int r = 0; 3409 + 3410 + /* 3411 + * ASIC reset has to be done on all HGMI hive nodes ASAP 3412 + * to allow proper links negotiation in FW (within 1 sec) 3413 + */ 3414 + if (need_full_reset) { 3415 + list_for_each_entry(tmp_adev, device_list_handle, gmc.xgmi.head) { 3416 + r = amdgpu_asic_reset(tmp_adev); 3417 + if (r) 3418 + DRM_WARN("ASIC reset failed with err r, %d for drm dev, %s", 3419 + r, tmp_adev->ddev->unique); 3420 + } 3421 + } 3422 + 3423 + 3424 + list_for_each_entry(tmp_adev, device_list_handle, gmc.xgmi.head) { 3425 + if (need_full_reset) { 3426 + /* post card */ 3427 + if (amdgpu_atom_asic_init(tmp_adev->mode_info.atom_context)) 3428 + DRM_WARN("asic atom init failed!"); 3429 + 3430 + if (!r) { 3431 + dev_info(tmp_adev->dev, "GPU reset succeeded, trying to resume\n"); 3432 + r = amdgpu_device_ip_resume_phase1(tmp_adev); 3433 + if (r) 3434 + goto out; 3435 + 3436 + vram_lost = amdgpu_device_check_vram_lost(tmp_adev); 3437 + if (vram_lost) { 3438 + DRM_ERROR("VRAM is lost!\n"); 3439 + atomic_inc(&tmp_adev->vram_lost_counter); 3440 + } 3441 + 3442 + r = amdgpu_gtt_mgr_recover( 3443 + &tmp_adev->mman.bdev.man[TTM_PL_TT]); 3444 + if (r) 3445 + goto out; 3446 + 3447 + r = amdgpu_device_fw_loading(tmp_adev); 3448 + if (r) 3449 + return r; 3450 + 3451 + r = amdgpu_device_ip_resume_phase2(tmp_adev); 3452 + if (r) 3453 + goto out; 3454 + 3455 + if (vram_lost) 3456 + amdgpu_device_fill_reset_magic(tmp_adev); 3457 + 3458 + /* Update PSP FW topology after reset */ 3459 + if (hive && tmp_adev->gmc.xgmi.num_physical_nodes > 1) 3460 + r = amdgpu_xgmi_update_topology(hive, tmp_adev); 3461 + } 3462 + } 3463 + 3464 + 3465 + out: 3466 + if (!r) { 3467 + amdgpu_irq_gpu_reset_resume_helper(tmp_adev); 3468 + r = amdgpu_ib_ring_tests(tmp_adev); 3469 + if (r) { 3470 + dev_err(tmp_adev->dev, "ib ring test failed (%d).\n", r); 3471 + r = amdgpu_device_ip_suspend(tmp_adev); 3472 + need_full_reset = true; 3473 + r = -EAGAIN; 3474 + goto end; 3475 + } 3476 + } 3477 + 3478 + if (!r) 3479 + r = amdgpu_device_recover_vram(tmp_adev); 3480 + else 3481 + tmp_adev->asic_reset_res = r; 3482 + } 3483 + 3484 + end: 3485 + *need_full_reset_arg = need_full_reset; 3486 + return r; 3487 + } 3488 + 3489 + static void amdgpu_device_post_asic_reset(struct amdgpu_device *adev, 3490 + struct amdgpu_job *job) 3491 + { 3492 + int i; 3295 3493 3296 3494 for (i = 0; i < AMDGPU_MAX_RINGS; ++i) { 3297 3495 struct amdgpu_ring *ring = adev->rings[i]; ··· 3416 3388 * or all rings (in the case @job is NULL) 3417 3389 * after above amdgpu_reset accomplished 3418 3390 */ 3419 - if ((!job || job->base.sched == &ring->sched) && !r) 3391 + if ((!job || job->base.sched == &ring->sched) && !adev->asic_reset_res) 3420 3392 drm_sched_job_recovery(&ring->sched); 3421 3393 3422 3394 kthread_unpark(ring->sched.thread); ··· 3426 3398 drm_helper_resume_force_mode(adev->ddev); 3427 3399 } 3428 3400 3429 - ttm_bo_unlock_delayed_workqueue(&adev->mman.bdev, resched); 3401 + adev->asic_reset_res = 0; 3402 + } 3430 3403 3431 - if (r) { 3432 - /* bad news, how to tell it to userspace ? */ 3433 - dev_info(adev->dev, "GPU reset(%d) failed\n", atomic_read(&adev->gpu_reset_counter)); 3434 - amdgpu_vf_error_put(adev, AMDGIM_ERROR_VF_GPU_RESET_FAIL, 0, r); 3435 - } else { 3436 - dev_info(adev->dev, "GPU reset(%d) succeeded!\n",atomic_read(&adev->gpu_reset_counter)); 3437 - } 3404 + static void amdgpu_device_lock_adev(struct amdgpu_device *adev) 3405 + { 3406 + mutex_lock(&adev->lock_reset); 3407 + atomic_inc(&adev->gpu_reset_counter); 3408 + adev->in_gpu_reset = 1; 3409 + /* Block kfd */ 3410 + amdgpu_amdkfd_pre_reset(adev); 3411 + } 3438 3412 3413 + static void amdgpu_device_unlock_adev(struct amdgpu_device *adev) 3414 + { 3439 3415 /*unlock kfd */ 3440 3416 amdgpu_amdkfd_post_reset(adev); 3441 3417 amdgpu_vf_error_trans_all(adev); 3442 3418 adev->in_gpu_reset = 0; 3443 3419 mutex_unlock(&adev->lock_reset); 3420 + } 3421 + 3422 + 3423 + /** 3424 + * amdgpu_device_gpu_recover - reset the asic and recover scheduler 3425 + * 3426 + * @adev: amdgpu device pointer 3427 + * @job: which job trigger hang 3428 + * 3429 + * Attempt to reset the GPU if it has hung (all asics). 3430 + * Attempt to do soft-reset or full-reset and reinitialize Asic 3431 + * Returns 0 for success or an error on failure. 3432 + */ 3433 + 3434 + int amdgpu_device_gpu_recover(struct amdgpu_device *adev, 3435 + struct amdgpu_job *job) 3436 + { 3437 + int r; 3438 + struct amdgpu_hive_info *hive = NULL; 3439 + bool need_full_reset = false; 3440 + struct amdgpu_device *tmp_adev = NULL; 3441 + struct list_head device_list, *device_list_handle = NULL; 3442 + 3443 + INIT_LIST_HEAD(&device_list); 3444 + 3445 + dev_info(adev->dev, "GPU reset begin!\n"); 3446 + 3447 + /* 3448 + * In case of XGMI hive disallow concurrent resets to be triggered 3449 + * by different nodes. No point also since the one node already executing 3450 + * reset will also reset all the other nodes in the hive. 3451 + */ 3452 + hive = amdgpu_get_xgmi_hive(adev); 3453 + if (hive && adev->gmc.xgmi.num_physical_nodes > 1 && 3454 + !mutex_trylock(&hive->hive_lock)) 3455 + return 0; 3456 + 3457 + /* Start with adev pre asic reset first for soft reset check.*/ 3458 + amdgpu_device_lock_adev(adev); 3459 + r = amdgpu_device_pre_asic_reset(adev, 3460 + job, 3461 + &need_full_reset); 3462 + if (r) { 3463 + /*TODO Should we stop ?*/ 3464 + DRM_ERROR("GPU pre asic reset failed with err, %d for drm dev, %s ", 3465 + r, adev->ddev->unique); 3466 + adev->asic_reset_res = r; 3467 + } 3468 + 3469 + /* Build list of devices to reset */ 3470 + if (need_full_reset && adev->gmc.xgmi.num_physical_nodes > 1) { 3471 + if (!hive) { 3472 + amdgpu_device_unlock_adev(adev); 3473 + return -ENODEV; 3474 + } 3475 + 3476 + /* 3477 + * In case we are in XGMI hive mode device reset is done for all the 3478 + * nodes in the hive to retrain all XGMI links and hence the reset 3479 + * sequence is executed in loop on all nodes. 3480 + */ 3481 + device_list_handle = &hive->device_list; 3482 + } else { 3483 + list_add_tail(&adev->gmc.xgmi.head, &device_list); 3484 + device_list_handle = &device_list; 3485 + } 3486 + 3487 + retry: /* Rest of adevs pre asic reset from XGMI hive. */ 3488 + list_for_each_entry(tmp_adev, device_list_handle, gmc.xgmi.head) { 3489 + 3490 + if (tmp_adev == adev) 3491 + continue; 3492 + 3493 + dev_info(tmp_adev->dev, "GPU reset begin for drm dev %s!\n", adev->ddev->unique); 3494 + 3495 + amdgpu_device_lock_adev(tmp_adev); 3496 + r = amdgpu_device_pre_asic_reset(tmp_adev, 3497 + NULL, 3498 + &need_full_reset); 3499 + /*TODO Should we stop ?*/ 3500 + if (r) { 3501 + DRM_ERROR("GPU pre asic reset failed with err, %d for drm dev, %s ", 3502 + r, tmp_adev->ddev->unique); 3503 + tmp_adev->asic_reset_res = r; 3504 + } 3505 + } 3506 + 3507 + /* Actual ASIC resets if needed.*/ 3508 + /* TODO Implement XGMI hive reset logic for SRIOV */ 3509 + if (amdgpu_sriov_vf(adev)) { 3510 + r = amdgpu_device_reset_sriov(adev, job ? false : true); 3511 + if (r) 3512 + adev->asic_reset_res = r; 3513 + } else { 3514 + r = amdgpu_do_asic_reset(hive, device_list_handle, &need_full_reset); 3515 + if (r && r == -EAGAIN) 3516 + goto retry; 3517 + } 3518 + 3519 + /* Post ASIC reset for all devs .*/ 3520 + list_for_each_entry(tmp_adev, device_list_handle, gmc.xgmi.head) { 3521 + amdgpu_device_post_asic_reset(tmp_adev, tmp_adev == adev ? job : NULL); 3522 + 3523 + if (r) { 3524 + /* bad news, how to tell it to userspace ? */ 3525 + dev_info(tmp_adev->dev, "GPU reset(%d) failed\n", atomic_read(&adev->gpu_reset_counter)); 3526 + amdgpu_vf_error_put(tmp_adev, AMDGIM_ERROR_VF_GPU_RESET_FAIL, 0, r); 3527 + } else { 3528 + dev_info(tmp_adev->dev, "GPU reset(%d) succeeded!\n", atomic_read(&adev->gpu_reset_counter)); 3529 + } 3530 + 3531 + amdgpu_device_unlock_adev(tmp_adev); 3532 + } 3533 + 3534 + if (hive && adev->gmc.xgmi.num_physical_nodes > 1) 3535 + mutex_unlock(&hive->hive_lock); 3536 + 3537 + if (r) 3538 + dev_info(adev->dev, "GPU reset end with ret = %d\n", r); 3444 3539 return r; 3445 3540 } 3446 3541
+11 -1
drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
··· 631 631 drm_property_create_range(adev->ddev, 0, "max bpc", 8, 16); 632 632 if (!adev->mode_info.max_bpc_property) 633 633 return -ENOMEM; 634 + adev->mode_info.abm_level_property = 635 + drm_property_create_range(adev->ddev, 0, 636 + "abm level", 0, 4); 637 + if (!adev->mode_info.abm_level_property) 638 + return -ENOMEM; 634 639 } 635 640 636 641 return 0; ··· 862 857 /* Inside "upper part" of vblank area? Apply corrective offset if so: */ 863 858 if (in_vbl && (*vpos >= vbl_start)) { 864 859 vtotal = mode->crtc_vtotal; 865 - *vpos = *vpos - vtotal; 860 + 861 + /* With variable refresh rate displays the vpos can exceed 862 + * the vtotal value. Clamp to 0 to return -vbl_end instead 863 + * of guessing the remaining number of lines until scanout. 864 + */ 865 + *vpos = (*vpos < vtotal) ? (*vpos - vtotal) : 0; 866 866 } 867 867 868 868 /* Correct for shifted end of vbl at vbl_end. */
+243
drivers/gpu/drm/amd/amdgpu/amdgpu_doorbell.h
··· 1 + /* 2 + * Copyright 2018 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 + /* 25 + * GPU doorbell structures, functions & helpers 26 + */ 27 + struct amdgpu_doorbell { 28 + /* doorbell mmio */ 29 + resource_size_t base; 30 + resource_size_t size; 31 + u32 __iomem *ptr; 32 + u32 num_doorbells; /* Number of doorbells actually reserved for amdgpu. */ 33 + }; 34 + 35 + /* Reserved doorbells for amdgpu (including multimedia). 36 + * KFD can use all the rest in the 2M doorbell bar. 37 + * For asic before vega10, doorbell is 32-bit, so the 38 + * index/offset is in dword. For vega10 and after, doorbell 39 + * can be 64-bit, so the index defined is in qword. 40 + */ 41 + struct amdgpu_doorbell_index { 42 + uint32_t kiq; 43 + uint32_t mec_ring0; 44 + uint32_t mec_ring1; 45 + uint32_t mec_ring2; 46 + uint32_t mec_ring3; 47 + uint32_t mec_ring4; 48 + uint32_t mec_ring5; 49 + uint32_t mec_ring6; 50 + uint32_t mec_ring7; 51 + uint32_t userqueue_start; 52 + uint32_t userqueue_end; 53 + uint32_t gfx_ring0; 54 + uint32_t sdma_engine0; 55 + uint32_t sdma_engine1; 56 + uint32_t sdma_engine2; 57 + uint32_t sdma_engine3; 58 + uint32_t sdma_engine4; 59 + uint32_t sdma_engine5; 60 + uint32_t sdma_engine6; 61 + uint32_t sdma_engine7; 62 + uint32_t ih; 63 + union { 64 + struct { 65 + uint32_t vcn_ring0_1; 66 + uint32_t vcn_ring2_3; 67 + uint32_t vcn_ring4_5; 68 + uint32_t vcn_ring6_7; 69 + } vcn; 70 + struct { 71 + uint32_t uvd_ring0_1; 72 + uint32_t uvd_ring2_3; 73 + uint32_t uvd_ring4_5; 74 + uint32_t uvd_ring6_7; 75 + uint32_t vce_ring0_1; 76 + uint32_t vce_ring2_3; 77 + uint32_t vce_ring4_5; 78 + uint32_t vce_ring6_7; 79 + } uvd_vce; 80 + }; 81 + uint32_t max_assignment; 82 + }; 83 + 84 + typedef enum _AMDGPU_DOORBELL_ASSIGNMENT 85 + { 86 + AMDGPU_DOORBELL_KIQ = 0x000, 87 + AMDGPU_DOORBELL_HIQ = 0x001, 88 + AMDGPU_DOORBELL_DIQ = 0x002, 89 + AMDGPU_DOORBELL_MEC_RING0 = 0x010, 90 + AMDGPU_DOORBELL_MEC_RING1 = 0x011, 91 + AMDGPU_DOORBELL_MEC_RING2 = 0x012, 92 + AMDGPU_DOORBELL_MEC_RING3 = 0x013, 93 + AMDGPU_DOORBELL_MEC_RING4 = 0x014, 94 + AMDGPU_DOORBELL_MEC_RING5 = 0x015, 95 + AMDGPU_DOORBELL_MEC_RING6 = 0x016, 96 + AMDGPU_DOORBELL_MEC_RING7 = 0x017, 97 + AMDGPU_DOORBELL_GFX_RING0 = 0x020, 98 + AMDGPU_DOORBELL_sDMA_ENGINE0 = 0x1E0, 99 + AMDGPU_DOORBELL_sDMA_ENGINE1 = 0x1E1, 100 + AMDGPU_DOORBELL_IH = 0x1E8, 101 + AMDGPU_DOORBELL_MAX_ASSIGNMENT = 0x3FF, 102 + AMDGPU_DOORBELL_INVALID = 0xFFFF 103 + } AMDGPU_DOORBELL_ASSIGNMENT; 104 + 105 + typedef enum _AMDGPU_VEGA20_DOORBELL_ASSIGNMENT 106 + { 107 + /* Compute + GFX: 0~255 */ 108 + AMDGPU_VEGA20_DOORBELL_KIQ = 0x000, 109 + AMDGPU_VEGA20_DOORBELL_HIQ = 0x001, 110 + AMDGPU_VEGA20_DOORBELL_DIQ = 0x002, 111 + AMDGPU_VEGA20_DOORBELL_MEC_RING0 = 0x003, 112 + AMDGPU_VEGA20_DOORBELL_MEC_RING1 = 0x004, 113 + AMDGPU_VEGA20_DOORBELL_MEC_RING2 = 0x005, 114 + AMDGPU_VEGA20_DOORBELL_MEC_RING3 = 0x006, 115 + AMDGPU_VEGA20_DOORBELL_MEC_RING4 = 0x007, 116 + AMDGPU_VEGA20_DOORBELL_MEC_RING5 = 0x008, 117 + AMDGPU_VEGA20_DOORBELL_MEC_RING6 = 0x009, 118 + AMDGPU_VEGA20_DOORBELL_MEC_RING7 = 0x00A, 119 + AMDGPU_VEGA20_DOORBELL_USERQUEUE_START = 0x00B, 120 + AMDGPU_VEGA20_DOORBELL_USERQUEUE_END = 0x08A, 121 + AMDGPU_VEGA20_DOORBELL_GFX_RING0 = 0x08B, 122 + /* SDMA:256~335*/ 123 + AMDGPU_VEGA20_DOORBELL_sDMA_ENGINE0 = 0x100, 124 + AMDGPU_VEGA20_DOORBELL_sDMA_ENGINE1 = 0x10A, 125 + AMDGPU_VEGA20_DOORBELL_sDMA_ENGINE2 = 0x114, 126 + AMDGPU_VEGA20_DOORBELL_sDMA_ENGINE3 = 0x11E, 127 + AMDGPU_VEGA20_DOORBELL_sDMA_ENGINE4 = 0x128, 128 + AMDGPU_VEGA20_DOORBELL_sDMA_ENGINE5 = 0x132, 129 + AMDGPU_VEGA20_DOORBELL_sDMA_ENGINE6 = 0x13C, 130 + AMDGPU_VEGA20_DOORBELL_sDMA_ENGINE7 = 0x146, 131 + /* IH: 376~391 */ 132 + AMDGPU_VEGA20_DOORBELL_IH = 0x178, 133 + /* MMSCH: 392~407 134 + * overlap the doorbell assignment with VCN as they are mutually exclusive 135 + * VCE engine's doorbell is 32 bit and two VCE ring share one QWORD 136 + */ 137 + AMDGPU_VEGA20_DOORBELL64_VCN0_1 = 0x188, /* lower 32 bits for VNC0 and upper 32 bits for VNC1 */ 138 + AMDGPU_VEGA20_DOORBELL64_VCN2_3 = 0x189, 139 + AMDGPU_VEGA20_DOORBELL64_VCN4_5 = 0x18A, 140 + AMDGPU_VEGA20_DOORBELL64_VCN6_7 = 0x18B, 141 + 142 + AMDGPU_VEGA20_DOORBELL64_UVD_RING0_1 = 0x188, 143 + AMDGPU_VEGA20_DOORBELL64_UVD_RING2_3 = 0x189, 144 + AMDGPU_VEGA20_DOORBELL64_UVD_RING4_5 = 0x18A, 145 + AMDGPU_VEGA20_DOORBELL64_UVD_RING6_7 = 0x18B, 146 + 147 + AMDGPU_VEGA20_DOORBELL64_VCE_RING0_1 = 0x18C, 148 + AMDGPU_VEGA20_DOORBELL64_VCE_RING2_3 = 0x18D, 149 + AMDGPU_VEGA20_DOORBELL64_VCE_RING4_5 = 0x18E, 150 + AMDGPU_VEGA20_DOORBELL64_VCE_RING6_7 = 0x18F, 151 + AMDGPU_VEGA20_DOORBELL_MAX_ASSIGNMENT = 0x18F, 152 + AMDGPU_VEGA20_DOORBELL_INVALID = 0xFFFF 153 + } AMDGPU_VEGA20_DOORBELL_ASSIGNMENT; 154 + 155 + /* 156 + * 64bit doorbell, offset are in QWORD, occupy 2KB doorbell space 157 + */ 158 + typedef enum _AMDGPU_DOORBELL64_ASSIGNMENT 159 + { 160 + /* 161 + * All compute related doorbells: kiq, hiq, diq, traditional compute queue, user queue, should locate in 162 + * a continues range so that programming CP_MEC_DOORBELL_RANGE_LOWER/UPPER can cover this range. 163 + * Compute related doorbells are allocated from 0x00 to 0x8a 164 + */ 165 + 166 + 167 + /* kernel scheduling */ 168 + AMDGPU_DOORBELL64_KIQ = 0x00, 169 + 170 + /* HSA interface queue and debug queue */ 171 + AMDGPU_DOORBELL64_HIQ = 0x01, 172 + AMDGPU_DOORBELL64_DIQ = 0x02, 173 + 174 + /* Compute engines */ 175 + AMDGPU_DOORBELL64_MEC_RING0 = 0x03, 176 + AMDGPU_DOORBELL64_MEC_RING1 = 0x04, 177 + AMDGPU_DOORBELL64_MEC_RING2 = 0x05, 178 + AMDGPU_DOORBELL64_MEC_RING3 = 0x06, 179 + AMDGPU_DOORBELL64_MEC_RING4 = 0x07, 180 + AMDGPU_DOORBELL64_MEC_RING5 = 0x08, 181 + AMDGPU_DOORBELL64_MEC_RING6 = 0x09, 182 + AMDGPU_DOORBELL64_MEC_RING7 = 0x0a, 183 + 184 + /* User queue doorbell range (128 doorbells) */ 185 + AMDGPU_DOORBELL64_USERQUEUE_START = 0x0b, 186 + AMDGPU_DOORBELL64_USERQUEUE_END = 0x8a, 187 + 188 + /* Graphics engine */ 189 + AMDGPU_DOORBELL64_GFX_RING0 = 0x8b, 190 + 191 + /* 192 + * Other graphics doorbells can be allocated here: from 0x8c to 0xdf 193 + * Graphics voltage island aperture 1 194 + * default non-graphics QWORD index is 0xe0 - 0xFF inclusive 195 + */ 196 + 197 + /* For vega10 sriov, the sdma doorbell must be fixed as follow 198 + * to keep the same setting with host driver, or it will 199 + * happen conflicts 200 + */ 201 + AMDGPU_DOORBELL64_sDMA_ENGINE0 = 0xF0, 202 + AMDGPU_DOORBELL64_sDMA_HI_PRI_ENGINE0 = 0xF1, 203 + AMDGPU_DOORBELL64_sDMA_ENGINE1 = 0xF2, 204 + AMDGPU_DOORBELL64_sDMA_HI_PRI_ENGINE1 = 0xF3, 205 + 206 + /* Interrupt handler */ 207 + AMDGPU_DOORBELL64_IH = 0xF4, /* For legacy interrupt ring buffer */ 208 + AMDGPU_DOORBELL64_IH_RING1 = 0xF5, /* For page migration request log */ 209 + AMDGPU_DOORBELL64_IH_RING2 = 0xF6, /* For page migration translation/invalidation log */ 210 + 211 + /* VCN engine use 32 bits doorbell */ 212 + AMDGPU_DOORBELL64_VCN0_1 = 0xF8, /* lower 32 bits for VNC0 and upper 32 bits for VNC1 */ 213 + AMDGPU_DOORBELL64_VCN2_3 = 0xF9, 214 + AMDGPU_DOORBELL64_VCN4_5 = 0xFA, 215 + AMDGPU_DOORBELL64_VCN6_7 = 0xFB, 216 + 217 + /* overlap the doorbell assignment with VCN as they are mutually exclusive 218 + * VCE engine's doorbell is 32 bit and two VCE ring share one QWORD 219 + */ 220 + AMDGPU_DOORBELL64_UVD_RING0_1 = 0xF8, 221 + AMDGPU_DOORBELL64_UVD_RING2_3 = 0xF9, 222 + AMDGPU_DOORBELL64_UVD_RING4_5 = 0xFA, 223 + AMDGPU_DOORBELL64_UVD_RING6_7 = 0xFB, 224 + 225 + AMDGPU_DOORBELL64_VCE_RING0_1 = 0xFC, 226 + AMDGPU_DOORBELL64_VCE_RING2_3 = 0xFD, 227 + AMDGPU_DOORBELL64_VCE_RING4_5 = 0xFE, 228 + AMDGPU_DOORBELL64_VCE_RING6_7 = 0xFF, 229 + 230 + AMDGPU_DOORBELL64_MAX_ASSIGNMENT = 0xFF, 231 + AMDGPU_DOORBELL64_INVALID = 0xFFFF 232 + } AMDGPU_DOORBELL64_ASSIGNMENT; 233 + 234 + u32 amdgpu_mm_rdoorbell(struct amdgpu_device *adev, u32 index); 235 + void amdgpu_mm_wdoorbell(struct amdgpu_device *adev, u32 index, u32 v); 236 + u64 amdgpu_mm_rdoorbell64(struct amdgpu_device *adev, u32 index); 237 + void amdgpu_mm_wdoorbell64(struct amdgpu_device *adev, u32 index, u64 v); 238 + 239 + #define RDOORBELL32(index) amdgpu_mm_rdoorbell(adev, (index)) 240 + #define WDOORBELL32(index, v) amdgpu_mm_wdoorbell(adev, (index), (v)) 241 + #define RDOORBELL64(index) amdgpu_mm_rdoorbell64(adev, (index)) 242 + #define WDOORBELL64(index, v) amdgpu_mm_wdoorbell64(adev, (index), (v)) 243 +
+6 -10
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
··· 454 454 455 455 /** 456 456 * DOC: param_buf_per_se (int) 457 - * Override the size of Off-Chip Pramater Cache per Shader Engine in Byte. The default is 0 (depending on gfx). 457 + * Override the size of Off-Chip Parameter Cache per Shader Engine in Byte. 458 + * The default is 0 (depending on gfx). 458 459 */ 459 - MODULE_PARM_DESC(param_buf_per_se, "the size of Off-Chip Pramater Cache per Shader Engine (default depending on gfx)"); 460 + MODULE_PARM_DESC(param_buf_per_se, "the size of Off-Chip Parameter Cache per Shader Engine (default depending on gfx)"); 460 461 module_param_named(param_buf_per_se, amdgpu_param_buf_per_se, int, 0444); 461 462 462 463 /** ··· 1221 1220 .patchlevel = KMS_DRIVER_PATCHLEVEL, 1222 1221 }; 1223 1222 1224 - static struct drm_driver *driver; 1225 - static struct pci_driver *pdriver; 1226 - 1227 1223 static struct pci_driver amdgpu_kms_pci_driver = { 1228 1224 .name = DRIVER_NAME, 1229 1225 .id_table = pciidlist, ··· 1250 1252 goto error_fence; 1251 1253 1252 1254 DRM_INFO("amdgpu kernel modesetting enabled.\n"); 1253 - driver = &kms_driver; 1254 - pdriver = &amdgpu_kms_pci_driver; 1255 - driver->num_ioctls = amdgpu_max_kms_ioctl; 1255 + kms_driver.num_ioctls = amdgpu_max_kms_ioctl; 1256 1256 amdgpu_register_atpx_handler(); 1257 1257 1258 1258 /* Ignore KFD init failures. Normal when CONFIG_HSA_AMD is not set. */ 1259 1259 amdgpu_amdkfd_init(); 1260 1260 1261 1261 /* let modprobe override vga console setting */ 1262 - return pci_register_driver(pdriver); 1262 + return pci_register_driver(&amdgpu_kms_pci_driver); 1263 1263 1264 1264 error_fence: 1265 1265 amdgpu_sync_fini(); ··· 1269 1273 static void __exit amdgpu_exit(void) 1270 1274 { 1271 1275 amdgpu_amdkfd_fini(); 1272 - pci_unregister_driver(pdriver); 1276 + pci_unregister_driver(&amdgpu_kms_pci_driver); 1273 1277 amdgpu_unregister_atpx_handler(); 1274 1278 amdgpu_sync_fini(); 1275 1279 amdgpu_fence_slab_fini();
+1 -1
drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
··· 250 250 ring->adev = NULL; 251 251 ring->ring_obj = NULL; 252 252 ring->use_doorbell = true; 253 - ring->doorbell_index = AMDGPU_DOORBELL_KIQ; 253 + ring->doorbell_index = adev->doorbell_index.kiq; 254 254 255 255 r = amdgpu_gfx_kiq_acquire(adev, ring); 256 256 if (r)
+3 -3
drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
··· 467 467 if (!info->return_size || !info->return_pointer) 468 468 return -EINVAL; 469 469 470 - /* Ensure IB tests are run on ring */ 471 - flush_delayed_work(&adev->late_init_work); 472 - 473 470 switch (info->query) { 474 471 case AMDGPU_INFO_ACCEL_WORKING: 475 472 ui32 = adev->accel_working; ··· 946 949 struct amdgpu_device *adev = dev->dev_private; 947 950 struct amdgpu_fpriv *fpriv; 948 951 int r, pasid; 952 + 953 + /* Ensure IB tests are run on ring */ 954 + flush_delayed_work(&adev->late_init_work); 949 955 950 956 file_priv->driver_priv = NULL; 951 957
+2 -8
drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
··· 38 38 #include <drm/drm_crtc_helper.h> 39 39 #include <drm/drm_fb_helper.h> 40 40 #include <drm/drm_plane_helper.h> 41 - #include <drm/drm_fb_helper.h> 42 41 #include <linux/i2c.h> 43 42 #include <linux/i2c-algo-bit.h> 44 43 #include <linux/hrtimer.h> ··· 293 294 uint16_t connector_object_id, 294 295 struct amdgpu_hpd *hpd, 295 296 struct amdgpu_router *router); 296 - /* it is used to enter or exit into free sync mode */ 297 - int (*notify_freesync)(struct drm_device *dev, void *data, 298 - struct drm_file *filp); 299 - /* it is used to allow enablement of freesync mode */ 300 - int (*set_freesync_property)(struct drm_connector *connector, 301 - struct drm_property *property, 302 - uint64_t val); 303 297 304 298 305 299 }; ··· 332 340 struct drm_property *dither_property; 333 341 /* maximum number of bits per channel for monitor color */ 334 342 struct drm_property *max_bpc_property; 343 + /* Adaptive Backlight Modulation (power feature) */ 344 + struct drm_property *abm_level_property; 335 345 /* hardcoded DFP edid from BIOS */ 336 346 struct edid *bios_hardcoded_edid; 337 347 int bios_hardcoded_edid_size;
+26
drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
··· 33 33 #include <linux/hwmon.h> 34 34 #include <linux/hwmon-sysfs.h> 35 35 #include <linux/nospec.h> 36 + #include "hwmgr.h" 37 + #define WIDTH_4K 3840 36 38 37 39 static int amdgpu_debugfs_pm_init(struct amdgpu_device *adev); 38 40 ··· 1644 1642 attr == &sensor_dev_attr_fan1_enable.dev_attr.attr)) 1645 1643 return 0; 1646 1644 1645 + /* Skip fan attributes on APU */ 1646 + if ((adev->flags & AMD_IS_APU) && 1647 + (attr == &sensor_dev_attr_pwm1.dev_attr.attr || 1648 + attr == &sensor_dev_attr_pwm1_enable.dev_attr.attr || 1649 + attr == &sensor_dev_attr_pwm1_max.dev_attr.attr || 1650 + attr == &sensor_dev_attr_pwm1_min.dev_attr.attr || 1651 + attr == &sensor_dev_attr_fan1_input.dev_attr.attr || 1652 + attr == &sensor_dev_attr_fan1_min.dev_attr.attr || 1653 + attr == &sensor_dev_attr_fan1_max.dev_attr.attr || 1654 + attr == &sensor_dev_attr_fan1_target.dev_attr.attr || 1655 + attr == &sensor_dev_attr_fan1_enable.dev_attr.attr)) 1656 + return 0; 1657 + 1647 1658 /* Skip limit attributes if DPM is not enabled */ 1648 1659 if (!adev->pm.dpm_enabled && 1649 1660 (attr == &sensor_dev_attr_temp1_crit.dev_attr.attr || ··· 1970 1955 mutex_lock(&adev->pm.mutex); 1971 1956 amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_UVD, !enable); 1972 1957 mutex_unlock(&adev->pm.mutex); 1958 + } 1959 + /* enable/disable Low Memory PState for UVD (4k videos) */ 1960 + if (adev->asic_type == CHIP_STONEY && 1961 + adev->uvd.decode_image_width >= WIDTH_4K) { 1962 + struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle; 1963 + 1964 + if (hwmgr && hwmgr->hwmgr_func && 1965 + hwmgr->hwmgr_func->update_nbdpm_pstate) 1966 + hwmgr->hwmgr_func->update_nbdpm_pstate(hwmgr, 1967 + !enable, 1968 + true); 1973 1969 } 1974 1970 } 1975 1971
+2
drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
··· 692 692 buf_sizes[0x1] = dpb_size; 693 693 buf_sizes[0x2] = image_size; 694 694 buf_sizes[0x4] = min_ctx_size; 695 + /* store image width to adjust nb memory pstate */ 696 + adev->uvd.decode_image_width = width; 695 697 return 0; 696 698 } 697 699
+2
drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.h
··· 65 65 struct drm_sched_entity entity; 66 66 struct delayed_work idle_work; 67 67 unsigned harvest_config; 68 + /* store image width to adjust nb memory state */ 69 + unsigned decode_image_width; 68 70 }; 69 71 70 72 int amdgpu_uvd_sw_init(struct amdgpu_device *adev);
+1 -1
drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c
··· 334 334 335 335 if (adev->fw_vram_usage.va != NULL) { 336 336 adev->virt.fw_reserve.p_pf2vf = 337 - (struct amdgim_pf2vf_info_header *)( 337 + (struct amd_sriov_msg_pf2vf_info_header *)( 338 338 adev->fw_vram_usage.va + AMDGIM_DATAEXCHANGE_OFFSET); 339 339 AMDGPU_FW_VRAM_PF2VF_READ(adev, header.size, &pf2vf_size); 340 340 AMDGPU_FW_VRAM_PF2VF_READ(adev, checksum, &checksum);
+14 -10
drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h
··· 63 63 * Firmware Reserve Frame buffer 64 64 */ 65 65 struct amdgpu_virt_fw_reserve { 66 - struct amdgim_pf2vf_info_header *p_pf2vf; 67 - struct amdgim_vf2pf_info_header *p_vf2pf; 66 + struct amd_sriov_msg_pf2vf_info_header *p_pf2vf; 67 + struct amd_sriov_msg_vf2pf_info_header *p_vf2pf; 68 68 unsigned int checksum_key; 69 69 }; 70 70 /* ··· 85 85 AMDGIM_FEATURE_GIM_FLR_VRAMLOST = 0x4, 86 86 }; 87 87 88 - struct amdgim_pf2vf_info_header { 88 + struct amd_sriov_msg_pf2vf_info_header { 89 89 /* the total structure size in byte. */ 90 90 uint32_t size; 91 91 /* version of this structure, written by the GIM */ 92 92 uint32_t version; 93 + /* reserved */ 94 + uint32_t reserved[2]; 93 95 } __aligned(4); 94 96 struct amdgim_pf2vf_info_v1 { 95 97 /* header contains size and version */ 96 - struct amdgim_pf2vf_info_header header; 98 + struct amd_sriov_msg_pf2vf_info_header header; 97 99 /* max_width * max_height */ 98 100 unsigned int uvd_enc_max_pixels_count; 99 101 /* 16x16 pixels/sec, codec independent */ ··· 114 112 115 113 struct amdgim_pf2vf_info_v2 { 116 114 /* header contains size and version */ 117 - struct amdgim_pf2vf_info_header header; 115 + struct amd_sriov_msg_pf2vf_info_header header; 118 116 /* use private key from mailbox 2 to create chueksum */ 119 117 uint32_t checksum; 120 118 /* The features flags of the GIM driver supports. */ ··· 139 137 uint64_t vcefw_kboffset; 140 138 /* VCE FW size in KB */ 141 139 uint32_t vcefw_ksize; 142 - uint32_t reserved[AMDGIM_GET_STRUCTURE_RESERVED_SIZE(256, 0, 0, (9 + sizeof(struct amdgim_pf2vf_info_header)/sizeof(uint32_t)), 3)]; 140 + uint32_t reserved[AMDGIM_GET_STRUCTURE_RESERVED_SIZE(256, 0, 0, (9 + sizeof(struct amd_sriov_msg_pf2vf_info_header)/sizeof(uint32_t)), 3)]; 143 141 } __aligned(4); 144 142 145 143 146 - struct amdgim_vf2pf_info_header { 144 + struct amd_sriov_msg_vf2pf_info_header { 147 145 /* the total structure size in byte. */ 148 146 uint32_t size; 149 147 /*version of this structure, written by the guest */ 150 148 uint32_t version; 149 + /* reserved */ 150 + uint32_t reserved[2]; 151 151 } __aligned(4); 152 152 153 153 struct amdgim_vf2pf_info_v1 { 154 154 /* header contains size and version */ 155 - struct amdgim_vf2pf_info_header header; 155 + struct amd_sriov_msg_vf2pf_info_header header; 156 156 /* driver version */ 157 157 char driver_version[64]; 158 158 /* driver certification, 1=WHQL, 0=None */ ··· 184 180 185 181 struct amdgim_vf2pf_info_v2 { 186 182 /* header contains size and version */ 187 - struct amdgim_vf2pf_info_header header; 183 + struct amd_sriov_msg_vf2pf_info_header header; 188 184 uint32_t checksum; 189 185 /* driver version */ 190 186 uint8_t driver_version[64]; ··· 210 206 uint32_t uvd_enc_usage; 211 207 /* guest uvd engine usage percentage. 0xffff means N/A. */ 212 208 uint32_t uvd_enc_health; 213 - uint32_t reserved[AMDGIM_GET_STRUCTURE_RESERVED_SIZE(256, 64, 0, (12 + sizeof(struct amdgim_vf2pf_info_header)/sizeof(uint32_t)), 0)]; 209 + uint32_t reserved[AMDGIM_GET_STRUCTURE_RESERVED_SIZE(256, 64, 0, (12 + sizeof(struct amd_sriov_msg_vf2pf_info_header)/sizeof(uint32_t)), 0)]; 214 210 } __aligned(4); 215 211 216 212 #define AMDGPU_FW_VRAM_VF2PF_VER 2
+40 -28
drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c
··· 23 23 */ 24 24 #include <linux/list.h> 25 25 #include "amdgpu.h" 26 - #include "amdgpu_psp.h" 26 + #include "amdgpu_xgmi.h" 27 27 28 28 29 29 static DEFINE_MUTEX(xgmi_mutex); ··· 31 31 #define AMDGPU_MAX_XGMI_HIVE 8 32 32 #define AMDGPU_MAX_XGMI_DEVICE_PER_HIVE 4 33 33 34 - struct amdgpu_hive_info { 35 - uint64_t hive_id; 36 - struct list_head device_list; 37 - }; 38 - 39 34 static struct amdgpu_hive_info xgmi_hives[AMDGPU_MAX_XGMI_HIVE]; 40 35 static unsigned hive_count = 0; 41 36 42 - static struct amdgpu_hive_info *amdgpu_get_xgmi_hive(struct amdgpu_device *adev) 37 + 38 + void *amdgpu_xgmi_hive_try_lock(struct amdgpu_hive_info *hive) 39 + { 40 + return &hive->device_list; 41 + } 42 + 43 + struct amdgpu_hive_info *amdgpu_get_xgmi_hive(struct amdgpu_device *adev) 43 44 { 44 45 int i; 45 46 struct amdgpu_hive_info *tmp; ··· 59 58 tmp = &xgmi_hives[hive_count++]; 60 59 tmp->hive_id = adev->gmc.xgmi.hive_id; 61 60 INIT_LIST_HEAD(&tmp->device_list); 61 + mutex_init(&tmp->hive_lock); 62 + 62 63 return tmp; 64 + } 65 + 66 + int amdgpu_xgmi_update_topology(struct amdgpu_hive_info *hive, struct amdgpu_device *adev) 67 + { 68 + int ret = -EINVAL; 69 + 70 + /* Each psp need to set the latest topology */ 71 + ret = psp_xgmi_set_topology_info(&adev->psp, 72 + hive->number_devices, 73 + &hive->topology_info); 74 + if (ret) 75 + dev_err(adev->dev, 76 + "XGMI: Set topology failure on device %llx, hive %llx, ret %d", 77 + adev->gmc.xgmi.node_id, 78 + adev->gmc.xgmi.hive_id, ret); 79 + else 80 + dev_info(adev->dev, "XGMI: Add node %d to hive 0x%llx.\n", 81 + adev->gmc.xgmi.physical_node_id, 82 + adev->gmc.xgmi.hive_id); 83 + 84 + return ret; 63 85 } 64 86 65 87 int amdgpu_xgmi_add_device(struct amdgpu_device *adev) 66 88 { 67 - struct psp_xgmi_topology_info *tmp_topology; 89 + struct psp_xgmi_topology_info *hive_topology; 68 90 struct amdgpu_hive_info *hive; 69 91 struct amdgpu_xgmi *entry; 70 - struct amdgpu_device *tmp_adev; 92 + struct amdgpu_device *tmp_adev = NULL; 71 93 72 94 int count = 0, ret = -EINVAL; 73 95 ··· 100 76 adev->gmc.xgmi.node_id = psp_xgmi_get_node_id(&adev->psp); 101 77 adev->gmc.xgmi.hive_id = psp_xgmi_get_hive_id(&adev->psp); 102 78 103 - tmp_topology = kzalloc(sizeof(struct psp_xgmi_topology_info), GFP_KERNEL); 104 - if (!tmp_topology) 105 - return -ENOMEM; 106 79 mutex_lock(&xgmi_mutex); 107 80 hive = amdgpu_get_xgmi_hive(adev); 108 81 if (!hive) 109 82 goto exit; 110 83 84 + hive_topology = &hive->topology_info; 85 + 111 86 list_add_tail(&adev->gmc.xgmi.head, &hive->device_list); 112 87 list_for_each_entry(entry, &hive->device_list, head) 113 - tmp_topology->nodes[count++].node_id = entry->node_id; 88 + hive_topology->nodes[count++].node_id = entry->node_id; 89 + hive->number_devices = count; 114 90 115 91 /* Each psp need to get the latest topology */ 116 92 list_for_each_entry(tmp_adev, &hive->device_list, gmc.xgmi.head) { 117 - ret = psp_xgmi_get_topology_info(&tmp_adev->psp, count, tmp_topology); 93 + ret = psp_xgmi_get_topology_info(&tmp_adev->psp, count, hive_topology); 118 94 if (ret) { 119 95 dev_err(tmp_adev->dev, 120 96 "XGMI: Get topology failure on device %llx, hive %llx, ret %d", ··· 125 101 } 126 102 } 127 103 128 - /* Each psp need to set the latest topology */ 129 104 list_for_each_entry(tmp_adev, &hive->device_list, gmc.xgmi.head) { 130 - ret = psp_xgmi_set_topology_info(&tmp_adev->psp, count, tmp_topology); 131 - if (ret) { 132 - dev_err(tmp_adev->dev, 133 - "XGMI: Set topology failure on device %llx, hive %llx, ret %d", 134 - tmp_adev->gmc.xgmi.node_id, 135 - tmp_adev->gmc.xgmi.hive_id, ret); 136 - /* To do : continue with some node failed or disable the whole hive */ 105 + ret = amdgpu_xgmi_update_topology(hive, tmp_adev); 106 + if (ret) 137 107 break; 138 - } 139 108 } 140 - if (!ret) 141 - dev_info(adev->dev, "XGMI: Add node %d to hive 0x%llx.\n", 142 - adev->gmc.xgmi.physical_node_id, 143 - adev->gmc.xgmi.hive_id); 144 109 145 110 exit: 146 111 mutex_unlock(&xgmi_mutex); 147 - kfree(tmp_topology); 148 112 return ret; 149 113 }
+39
drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h
··· 1 + /* 2 + * Copyright 2016 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 + #ifndef __AMDGPU_XGMI_H__ 23 + #define __AMDGPU_XGMI_H__ 24 + 25 + #include "amdgpu_psp.h" 26 + 27 + struct amdgpu_hive_info { 28 + uint64_t hive_id; 29 + struct list_head device_list; 30 + struct psp_xgmi_topology_info topology_info; 31 + int number_devices; 32 + struct mutex hive_lock; 33 + }; 34 + 35 + struct amdgpu_hive_info *amdgpu_get_xgmi_hive(struct amdgpu_device *adev); 36 + int amdgpu_xgmi_update_topology(struct amdgpu_hive_info *hive, struct amdgpu_device *adev); 37 + int amdgpu_xgmi_add_device(struct amdgpu_device *adev); 38 + 39 + #endif
+1
drivers/gpu/drm/amd/amdgpu/cik.c
··· 1755 1755 .flush_hdp = &cik_flush_hdp, 1756 1756 .invalidate_hdp = &cik_invalidate_hdp, 1757 1757 .need_full_reset = &cik_need_full_reset, 1758 + .init_doorbell_index = &legacy_doorbell_index_init, 1758 1759 }; 1759 1760 1760 1761 static int cik_common_early_init(void *handle)
+1
drivers/gpu/drm/amd/amdgpu/cik.h
··· 30 30 u32 me, u32 pipe, u32 queue, u32 vmid); 31 31 int cik_set_ip_blocks(struct amdgpu_device *adev); 32 32 33 + void legacy_doorbell_index_init(struct amdgpu_device *adev); 33 34 #endif
+1 -1
drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c
··· 4363 4363 4364 4364 ring->ring_obj = NULL; 4365 4365 ring->use_doorbell = true; 4366 - ring->doorbell_index = AMDGPU_DOORBELL_MEC_RING0 + ring_id; 4366 + ring->doorbell_index = adev->doorbell_index.mec_ring0 + ring_id; 4367 4367 sprintf(ring->name, "comp_%d.%d.%d", ring->me, ring->pipe, ring->queue); 4368 4368 4369 4369 irq_type = AMDGPU_CP_IRQ_COMPUTE_MEC1_PIPE0_EOP
+5 -6
drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
··· 44 44 #include "gca/gfx_8_0_d.h" 45 45 #include "gca/gfx_8_0_enum.h" 46 46 #include "gca/gfx_8_0_sh_mask.h" 47 - #include "gca/gfx_8_0_enum.h" 48 47 49 48 #include "dce/dce_10_0_d.h" 50 49 #include "dce/dce_10_0_sh_mask.h" ··· 1890 1891 1891 1892 ring->ring_obj = NULL; 1892 1893 ring->use_doorbell = true; 1893 - ring->doorbell_index = AMDGPU_DOORBELL_MEC_RING0 + ring_id; 1894 + ring->doorbell_index = adev->doorbell_index.mec_ring0 + ring_id; 1894 1895 ring->eop_gpu_addr = adev->gfx.mec.hpd_eop_gpu_addr 1895 1896 + (ring_id * GFX8_MEC_HPD_SIZE); 1896 1897 sprintf(ring->name, "comp_%d.%d.%d", ring->me, ring->pipe, ring->queue); ··· 2001 2002 /* no gfx doorbells on iceland */ 2002 2003 if (adev->asic_type != CHIP_TOPAZ) { 2003 2004 ring->use_doorbell = true; 2004 - ring->doorbell_index = AMDGPU_DOORBELL_GFX_RING0; 2005 + ring->doorbell_index = adev->doorbell_index.gfx_ring0; 2005 2006 } 2006 2007 2007 2008 r = amdgpu_ring_init(adev, ring, 1024, &adev->gfx.eop_irq, ··· 4215 4216 4216 4217 tmp = REG_SET_FIELD(0, CP_RB_DOORBELL_RANGE_LOWER, 4217 4218 DOORBELL_RANGE_LOWER, 4218 - AMDGPU_DOORBELL_GFX_RING0); 4219 + adev->doorbell_index.gfx_ring0); 4219 4220 WREG32(mmCP_RB_DOORBELL_RANGE_LOWER, tmp); 4220 4221 4221 4222 WREG32(mmCP_RB_DOORBELL_RANGE_UPPER, ··· 4644 4645 static void gfx_v8_0_set_mec_doorbell_range(struct amdgpu_device *adev) 4645 4646 { 4646 4647 if (adev->asic_type > CHIP_TONGA) { 4647 - WREG32(mmCP_MEC_DOORBELL_RANGE_LOWER, AMDGPU_DOORBELL_KIQ << 2); 4648 - WREG32(mmCP_MEC_DOORBELL_RANGE_UPPER, AMDGPU_DOORBELL_MEC_RING7 << 2); 4648 + WREG32(mmCP_MEC_DOORBELL_RANGE_LOWER, adev->doorbell_index.kiq << 2); 4649 + WREG32(mmCP_MEC_DOORBELL_RANGE_UPPER, adev->doorbell_index.mec_ring7 << 2); 4649 4650 } 4650 4651 /* enable doorbells */ 4651 4652 WREG32_FIELD(CP_PQ_STATUS, DOORBELL_ENABLE, 1);
+4 -4
drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
··· 1566 1566 1567 1567 ring->ring_obj = NULL; 1568 1568 ring->use_doorbell = true; 1569 - ring->doorbell_index = (AMDGPU_DOORBELL_MEC_RING0 + ring_id) << 1; 1569 + ring->doorbell_index = (adev->doorbell_index.mec_ring0 + ring_id) << 1; 1570 1570 ring->eop_gpu_addr = adev->gfx.mec.hpd_eop_gpu_addr 1571 1571 + (ring_id * GFX9_MEC_HPD_SIZE); 1572 1572 sprintf(ring->name, "comp_%d.%d.%d", ring->me, ring->pipe, ring->queue); ··· 1655 1655 else 1656 1656 sprintf(ring->name, "gfx_%d", i); 1657 1657 ring->use_doorbell = true; 1658 - ring->doorbell_index = AMDGPU_DOORBELL64_GFX_RING0 << 1; 1658 + ring->doorbell_index = adev->doorbell_index.gfx_ring0 << 1; 1659 1659 r = amdgpu_ring_init(adev, ring, 1024, 1660 1660 &adev->gfx.eop_irq, AMDGPU_CP_IRQ_GFX_EOP); 1661 1661 if (r) ··· 2981 2981 /* enable the doorbell if requested */ 2982 2982 if (ring->use_doorbell) { 2983 2983 WREG32_SOC15(GC, 0, mmCP_MEC_DOORBELL_RANGE_LOWER, 2984 - (AMDGPU_DOORBELL64_KIQ *2) << 2); 2984 + (adev->doorbell_index.kiq * 2) << 2); 2985 2985 WREG32_SOC15(GC, 0, mmCP_MEC_DOORBELL_RANGE_UPPER, 2986 - (AMDGPU_DOORBELL64_USERQUEUE_END * 2) << 2); 2986 + (adev->doorbell_index.userqueue_end * 2) << 2); 2987 2987 } 2988 2988 2989 2989 WREG32_SOC15(GC, 0, mmCP_HQD_PQ_DOORBELL_CONTROL,
+6 -3
drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
··· 338 338 struct amdgpu_vmhub *hub = &adev->vmhub[i]; 339 339 u32 tmp = gmc_v9_0_get_invalidate_req(vmid, flush_type); 340 340 341 - if (i == AMDGPU_GFXHUB && !adev->in_gpu_reset && 342 - adev->gfx.kiq.ring.sched.ready && 343 - (amdgpu_sriov_runtime(adev) || !amdgpu_sriov_vf(adev))) { 341 + /* This is necessary for a HW workaround under SRIOV as well 342 + * as GFXOFF under bare metal 343 + */ 344 + if (adev->gfx.kiq.ring.sched.ready && 345 + (amdgpu_sriov_runtime(adev) || !amdgpu_sriov_vf(adev)) && 346 + !adev->in_gpu_reset) { 344 347 uint32_t req = hub->vm_inv_eng0_req + eng; 345 348 uint32_t ack = hub->vm_inv_eng0_ack + eng; 346 349
-1
drivers/gpu/drm/amd/amdgpu/mxgpu_vi.c
··· 37 37 #include "gmc/gmc_8_2_sh_mask.h" 38 38 #include "oss/oss_3_0_d.h" 39 39 #include "oss/oss_3_0_sh_mask.h" 40 - #include "gca/gfx_8_0_sh_mask.h" 41 40 #include "dce/dce_10_0_d.h" 42 41 #include "dce/dce_10_0_sh_mask.h" 43 42 #include "smu/smu_7_1_3_d.h"
-3
drivers/gpu/drm/amd/amdgpu/psp_v10_0.c
··· 240 240 enum psp_ring_type ring_type) 241 241 { 242 242 int ret = 0; 243 - struct psp_ring *ring; 244 243 unsigned int psp_ring_reg = 0; 245 244 struct amdgpu_device *adev = psp->adev; 246 - 247 - ring = &psp->km_ring; 248 245 249 246 /* Write the ring destroy command to C2PMSG_64 */ 250 247 psp_ring_reg = 3 << 16;
+1 -4
drivers/gpu/drm/amd/amdgpu/psp_v3_1.c
··· 356 356 enum psp_ring_type ring_type) 357 357 { 358 358 int ret = 0; 359 - struct psp_ring *ring; 360 359 unsigned int psp_ring_reg = 0; 361 360 struct amdgpu_device *adev = psp->adev; 362 - 363 - ring = &psp->km_ring; 364 361 365 362 /* Write the ring destroy command to C2PMSG_64 */ 366 363 psp_ring_reg = 3 << 16; ··· 590 593 } 591 594 592 595 /*send the mode 1 reset command*/ 593 - WREG32(offset, 0x70000); 596 + WREG32(offset, GFX_CTRL_CMD_ID_MODE1_RST); 594 597 595 598 mdelay(1000); 596 599
+1 -1
drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c
··· 1146 1146 if (!amdgpu_sriov_vf(adev)) { 1147 1147 ring->use_doorbell = true; 1148 1148 ring->doorbell_index = (i == 0) ? 1149 - AMDGPU_DOORBELL_sDMA_ENGINE0 : AMDGPU_DOORBELL_sDMA_ENGINE1; 1149 + adev->doorbell_index.sdma_engine0 : adev->doorbell_index.sdma_engine1; 1150 1150 } else { 1151 1151 ring->use_pollmem = true; 1152 1152 }
+47 -30
drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c
··· 925 925 OFFSET, ring->doorbell_index); 926 926 WREG32_SDMA(i, mmSDMA0_PAGE_DOORBELL, doorbell); 927 927 WREG32_SDMA(i, mmSDMA0_PAGE_DOORBELL_OFFSET, doorbell_offset); 928 - /* TODO: enable doorbell support */ 929 - /*adev->nbio_funcs->sdma_doorbell_range(adev, i, ring->use_doorbell, 930 - ring->doorbell_index);*/ 931 928 932 - sdma_v4_0_ring_set_wptr(ring); 929 + /* paging queue doorbell range is setup at sdma_v4_0_gfx_resume */ 930 + sdma_v4_0_page_ring_set_wptr(ring); 933 931 934 932 /* set minor_ptr_update to 0 after wptr programed */ 935 933 WREG32_SDMA(i, mmSDMA0_PAGE_MINOR_PTR_UPDATE, 0); ··· 1447 1449 sdma_v4_0_wait_reg_mem(ring, 0, 0, reg, 0, val, mask, 10); 1448 1450 } 1449 1451 1452 + static bool sdma_v4_0_fw_support_paging_queue(struct amdgpu_device *adev) 1453 + { 1454 + uint fw_version = adev->sdma.instance[0].fw_version; 1455 + 1456 + switch (adev->asic_type) { 1457 + case CHIP_VEGA10: 1458 + return fw_version >= 430; 1459 + case CHIP_VEGA12: 1460 + /*return fw_version >= 31;*/ 1461 + return false; 1462 + case CHIP_VEGA20: 1463 + /*return fw_version >= 115;*/ 1464 + return false; 1465 + default: 1466 + return false; 1467 + } 1468 + } 1469 + 1450 1470 static int sdma_v4_0_early_init(void *handle) 1451 1471 { 1452 1472 struct amdgpu_device *adev = (struct amdgpu_device *)handle; 1473 + int r; 1453 1474 1454 - if (adev->asic_type == CHIP_RAVEN) { 1475 + if (adev->asic_type == CHIP_RAVEN) 1455 1476 adev->sdma.num_instances = 1; 1456 - adev->sdma.has_page_queue = false; 1457 - } else { 1477 + else 1458 1478 adev->sdma.num_instances = 2; 1459 - /* TODO: Page queue breaks driver reload under SRIOV */ 1460 - if ((adev->asic_type == CHIP_VEGA10) && amdgpu_sriov_vf((adev))) 1461 - adev->sdma.has_page_queue = false; 1462 - else if (adev->asic_type != CHIP_VEGA20 && 1463 - adev->asic_type != CHIP_VEGA12) 1464 - adev->sdma.has_page_queue = true; 1479 + 1480 + r = sdma_v4_0_init_microcode(adev); 1481 + if (r) { 1482 + DRM_ERROR("Failed to load sdma firmware!\n"); 1483 + return r; 1465 1484 } 1485 + 1486 + /* TODO: Page queue breaks driver reload under SRIOV */ 1487 + if ((adev->asic_type == CHIP_VEGA10) && amdgpu_sriov_vf((adev))) 1488 + adev->sdma.has_page_queue = false; 1489 + else if (sdma_v4_0_fw_support_paging_queue(adev)) 1490 + adev->sdma.has_page_queue = true; 1466 1491 1467 1492 sdma_v4_0_set_ring_funcs(adev); 1468 1493 sdma_v4_0_set_buffer_funcs(adev); ··· 1494 1473 1495 1474 return 0; 1496 1475 } 1497 - 1498 1476 1499 1477 static int sdma_v4_0_sw_init(void *handle) 1500 1478 { ··· 1513 1493 if (r) 1514 1494 return r; 1515 1495 1516 - r = sdma_v4_0_init_microcode(adev); 1517 - if (r) { 1518 - DRM_ERROR("Failed to load sdma firmware!\n"); 1519 - return r; 1520 - } 1521 - 1522 1496 for (i = 0; i < adev->sdma.num_instances; i++) { 1523 1497 ring = &adev->sdma.instance[i].ring; 1524 1498 ring->ring_obj = NULL; ··· 1521 1507 DRM_INFO("use_doorbell being set to: [%s]\n", 1522 1508 ring->use_doorbell?"true":"false"); 1523 1509 1524 - if (adev->asic_type == CHIP_VEGA10) 1525 - ring->doorbell_index = (i == 0) ? 1526 - (AMDGPU_VEGA10_DOORBELL64_sDMA_ENGINE0 << 1) //get DWORD offset 1527 - : (AMDGPU_VEGA10_DOORBELL64_sDMA_ENGINE1 << 1); // get DWORD offset 1528 - else 1529 - ring->doorbell_index = (i == 0) ? 1530 - (AMDGPU_DOORBELL64_sDMA_ENGINE0 << 1) //get DWORD offset 1531 - : (AMDGPU_DOORBELL64_sDMA_ENGINE1 << 1); // get DWORD offset 1532 - 1510 + /* doorbell size is 2 dwords, get DWORD offset */ 1511 + ring->doorbell_index = (i == 0) ? 1512 + (adev->doorbell_index.sdma_engine0 << 1) 1513 + : (adev->doorbell_index.sdma_engine1 << 1); 1533 1514 1534 1515 sprintf(ring->name, "sdma%d", i); 1535 1516 r = amdgpu_ring_init(adev, ring, 1024, ··· 1538 1529 if (adev->sdma.has_page_queue) { 1539 1530 ring = &adev->sdma.instance[i].page; 1540 1531 ring->ring_obj = NULL; 1541 - ring->use_doorbell = false; 1532 + ring->use_doorbell = true; 1533 + 1534 + /* paging queue use same doorbell index/routing as gfx queue 1535 + * with 0x400 (4096 dwords) offset on second doorbell page 1536 + */ 1537 + ring->doorbell_index = (i == 0) ? 1538 + (adev->doorbell_index.sdma_engine0 << 1) 1539 + : (adev->doorbell_index.sdma_engine1 << 1); 1540 + ring->doorbell_index += 0x400; 1542 1541 1543 1542 sprintf(ring->name, "page%d", i); 1544 1543 r = amdgpu_ring_init(adev, ring, 1024,
+22 -1
drivers/gpu/drm/amd/amdgpu/soc15.c
··· 613 613 .flush_hdp = &soc15_flush_hdp, 614 614 .invalidate_hdp = &soc15_invalidate_hdp, 615 615 .need_full_reset = &soc15_need_full_reset, 616 + .init_doorbell_index = &vega10_doorbell_index_init, 617 + }; 618 + 619 + static const struct amdgpu_asic_funcs vega20_asic_funcs = 620 + { 621 + .read_disabled_bios = &soc15_read_disabled_bios, 622 + .read_bios_from_rom = &soc15_read_bios_from_rom, 623 + .read_register = &soc15_read_register, 624 + .reset = &soc15_asic_reset, 625 + .set_vga_state = &soc15_vga_set_state, 626 + .get_xclk = &soc15_get_xclk, 627 + .set_uvd_clocks = &soc15_set_uvd_clocks, 628 + .set_vce_clocks = &soc15_set_vce_clocks, 629 + .get_config_memsize = &soc15_get_config_memsize, 630 + .flush_hdp = &soc15_flush_hdp, 631 + .invalidate_hdp = &soc15_invalidate_hdp, 632 + .need_full_reset = &soc15_need_full_reset, 633 + .init_doorbell_index = &vega20_doorbell_index_init, 616 634 }; 617 635 618 636 static int soc15_common_early_init(void *handle) ··· 650 632 adev->se_cac_rreg = &soc15_se_cac_rreg; 651 633 adev->se_cac_wreg = &soc15_se_cac_wreg; 652 634 653 - adev->asic_funcs = &soc15_asic_funcs; 654 635 655 636 adev->external_rev_id = 0xFF; 656 637 switch (adev->asic_type) { 657 638 case CHIP_VEGA10: 639 + adev->asic_funcs = &soc15_asic_funcs; 658 640 adev->cg_flags = AMD_CG_SUPPORT_GFX_MGCG | 659 641 AMD_CG_SUPPORT_GFX_MGLS | 660 642 AMD_CG_SUPPORT_GFX_RLC_LS | ··· 678 660 adev->external_rev_id = 0x1; 679 661 break; 680 662 case CHIP_VEGA12: 663 + adev->asic_funcs = &soc15_asic_funcs; 681 664 adev->cg_flags = AMD_CG_SUPPORT_GFX_MGCG | 682 665 AMD_CG_SUPPORT_GFX_MGLS | 683 666 AMD_CG_SUPPORT_GFX_CGCG | ··· 701 682 adev->external_rev_id = adev->rev_id + 0x14; 702 683 break; 703 684 case CHIP_VEGA20: 685 + adev->asic_funcs = &vega20_asic_funcs; 704 686 adev->cg_flags = AMD_CG_SUPPORT_GFX_MGCG | 705 687 AMD_CG_SUPPORT_GFX_MGLS | 706 688 AMD_CG_SUPPORT_GFX_CGCG | ··· 724 704 adev->external_rev_id = adev->rev_id + 0x28; 725 705 break; 726 706 case CHIP_RAVEN: 707 + adev->asic_funcs = &soc15_asic_funcs; 727 708 if (adev->rev_id >= 0x8) 728 709 adev->external_rev_id = adev->rev_id + 0x81; 729 710 else if (adev->pdev->device == 0x15d8)
+2
drivers/gpu/drm/amd/amdgpu/soc15.h
··· 58 58 int vega10_reg_base_init(struct amdgpu_device *adev); 59 59 int vega20_reg_base_init(struct amdgpu_device *adev); 60 60 61 + void vega10_doorbell_index_init(struct amdgpu_device *adev); 62 + void vega20_doorbell_index_init(struct amdgpu_device *adev); 61 63 #endif
+1 -1
drivers/gpu/drm/amd/amdgpu/tonga_ih.c
··· 322 322 return r; 323 323 324 324 adev->irq.ih.use_doorbell = true; 325 - adev->irq.ih.doorbell_index = AMDGPU_DOORBELL_IH; 325 + adev->irq.ih.doorbell_index = adev->doorbell_index.ih; 326 326 327 327 r = amdgpu_irq_init(adev); 328 328
+4 -4
drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c
··· 116 116 if (r) 117 117 return r; 118 118 119 - r = amdgpu_uvd_resume(adev); 120 - if (r) 121 - return r; 122 - 123 119 ring = &adev->uvd.inst->ring; 124 120 sprintf(ring->name, "uvd"); 125 121 r = amdgpu_ring_init(adev, ring, 512, &adev->uvd.inst->irq, 0); 122 + if (r) 123 + return r; 124 + 125 + r = amdgpu_uvd_resume(adev); 126 126 if (r) 127 127 return r; 128 128
+4 -4
drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c
··· 113 113 if (r) 114 114 return r; 115 115 116 - r = amdgpu_uvd_resume(adev); 117 - if (r) 118 - return r; 119 - 120 116 ring = &adev->uvd.inst->ring; 121 117 sprintf(ring->name, "uvd"); 122 118 r = amdgpu_ring_init(adev, ring, 512, &adev->uvd.inst->irq, 0); 119 + if (r) 120 + return r; 121 + 122 + r = amdgpu_uvd_resume(adev); 123 123 if (r) 124 124 return r; 125 125
+4 -4
drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c
··· 400 400 DRM_INFO("UVD ENC is disabled\n"); 401 401 } 402 402 403 - r = amdgpu_uvd_resume(adev); 404 - if (r) 405 - return r; 406 - 407 403 ring = &adev->uvd.inst->ring; 408 404 sprintf(ring->name, "uvd"); 409 405 r = amdgpu_ring_init(adev, ring, 512, &adev->uvd.inst->irq, 0); 406 + if (r) 407 + return r; 408 + 409 + r = amdgpu_uvd_resume(adev); 410 410 if (r) 411 411 return r; 412 412
+6 -6
drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c
··· 430 430 DRM_INFO("PSP loading UVD firmware\n"); 431 431 } 432 432 433 - r = amdgpu_uvd_resume(adev); 434 - if (r) 435 - return r; 436 - 437 433 for (j = 0; j < adev->uvd.num_uvd_inst; j++) { 438 434 if (adev->uvd.harvest_config & (1 << j)) 439 435 continue; ··· 451 455 * sriov, so set unused location for other unused rings. 452 456 */ 453 457 if (i == 0) 454 - ring->doorbell_index = AMDGPU_DOORBELL64_UVD_RING0_1 * 2; 458 + ring->doorbell_index = adev->doorbell_index.uvd_vce.uvd_ring0_1 * 2; 455 459 else 456 - ring->doorbell_index = AMDGPU_DOORBELL64_UVD_RING2_3 * 2 + 1; 460 + ring->doorbell_index = adev->doorbell_index.uvd_vce.uvd_ring2_3 * 2 + 1; 457 461 } 458 462 r = amdgpu_ring_init(adev, ring, 512, &adev->uvd.inst[j].irq, 0); 459 463 if (r) 460 464 return r; 461 465 } 462 466 } 467 + 468 + r = amdgpu_uvd_resume(adev); 469 + if (r) 470 + return r; 463 471 464 472 r = amdgpu_uvd_entity_init(adev); 465 473 if (r)
-1
drivers/gpu/drm/amd/amdgpu/vce_v3_0.c
··· 37 37 #include "gca/gfx_8_0_d.h" 38 38 #include "smu/smu_7_1_2_d.h" 39 39 #include "smu/smu_7_1_2_sh_mask.h" 40 - #include "gca/gfx_8_0_d.h" 41 40 #include "gca/gfx_8_0_sh_mask.h" 42 41 #include "ivsrcid/ivsrcid_vislands30.h" 43 42
+2 -2
drivers/gpu/drm/amd/amdgpu/vce_v4_0.c
··· 466 466 * so set unused location for other unused rings. 467 467 */ 468 468 if (i == 0) 469 - ring->doorbell_index = AMDGPU_DOORBELL64_VCE_RING0_1 * 2; 469 + ring->doorbell_index = adev->doorbell_index.uvd_vce.vce_ring0_1 * 2; 470 470 else 471 - ring->doorbell_index = AMDGPU_DOORBELL64_VCE_RING2_3 * 2 + 1; 471 + ring->doorbell_index = adev->doorbell_index.uvd_vce.vce_ring2_3 * 2 + 1; 472 472 } 473 473 r = amdgpu_ring_init(adev, ring, 512, &adev->vce.irq, 0); 474 474 if (r)
+1 -1
drivers/gpu/drm/amd/amdgpu/vega10_ih.c
··· 385 385 return r; 386 386 387 387 adev->irq.ih.use_doorbell = true; 388 - adev->irq.ih.doorbell_index = AMDGPU_DOORBELL64_IH << 1; 388 + adev->irq.ih.doorbell_index = adev->doorbell_index.ih << 1; 389 389 390 390 r = amdgpu_irq_init(adev); 391 391
+28
drivers/gpu/drm/amd/amdgpu/vega10_reg_init.c
··· 56 56 return 0; 57 57 } 58 58 59 + void vega10_doorbell_index_init(struct amdgpu_device *adev) 60 + { 61 + adev->doorbell_index.kiq = AMDGPU_DOORBELL64_KIQ; 62 + adev->doorbell_index.mec_ring0 = AMDGPU_DOORBELL64_MEC_RING0; 63 + adev->doorbell_index.mec_ring1 = AMDGPU_DOORBELL64_MEC_RING1; 64 + adev->doorbell_index.mec_ring2 = AMDGPU_DOORBELL64_MEC_RING2; 65 + adev->doorbell_index.mec_ring3 = AMDGPU_DOORBELL64_MEC_RING3; 66 + adev->doorbell_index.mec_ring4 = AMDGPU_DOORBELL64_MEC_RING4; 67 + adev->doorbell_index.mec_ring5 = AMDGPU_DOORBELL64_MEC_RING5; 68 + adev->doorbell_index.mec_ring6 = AMDGPU_DOORBELL64_MEC_RING6; 69 + adev->doorbell_index.mec_ring7 = AMDGPU_DOORBELL64_MEC_RING7; 70 + adev->doorbell_index.userqueue_start = AMDGPU_DOORBELL64_USERQUEUE_START; 71 + adev->doorbell_index.userqueue_end = AMDGPU_DOORBELL64_USERQUEUE_END; 72 + adev->doorbell_index.gfx_ring0 = AMDGPU_DOORBELL64_GFX_RING0; 73 + adev->doorbell_index.sdma_engine0 = AMDGPU_DOORBELL64_sDMA_ENGINE0; 74 + adev->doorbell_index.sdma_engine1 = AMDGPU_DOORBELL64_sDMA_ENGINE1; 75 + adev->doorbell_index.ih = AMDGPU_DOORBELL64_IH; 76 + adev->doorbell_index.uvd_vce.uvd_ring0_1 = AMDGPU_DOORBELL64_UVD_RING0_1; 77 + adev->doorbell_index.uvd_vce.uvd_ring2_3 = AMDGPU_DOORBELL64_UVD_RING2_3; 78 + adev->doorbell_index.uvd_vce.uvd_ring4_5 = AMDGPU_DOORBELL64_UVD_RING4_5; 79 + adev->doorbell_index.uvd_vce.uvd_ring6_7 = AMDGPU_DOORBELL64_UVD_RING6_7; 80 + adev->doorbell_index.uvd_vce.vce_ring0_1 = AMDGPU_DOORBELL64_VCE_RING0_1; 81 + adev->doorbell_index.uvd_vce.vce_ring2_3 = AMDGPU_DOORBELL64_VCE_RING2_3; 82 + adev->doorbell_index.uvd_vce.vce_ring4_5 = AMDGPU_DOORBELL64_VCE_RING4_5; 83 + adev->doorbell_index.uvd_vce.vce_ring6_7 = AMDGPU_DOORBELL64_VCE_RING6_7; 84 + /* In unit of dword doorbell */ 85 + adev->doorbell_index.max_assignment = AMDGPU_DOORBELL64_MAX_ASSIGNMENT << 1; 86 + } 59 87
+33
drivers/gpu/drm/amd/amdgpu/vega20_reg_init.c
··· 54 54 return 0; 55 55 } 56 56 57 + void vega20_doorbell_index_init(struct amdgpu_device *adev) 58 + { 59 + adev->doorbell_index.kiq = AMDGPU_VEGA20_DOORBELL_KIQ; 60 + adev->doorbell_index.mec_ring0 = AMDGPU_VEGA20_DOORBELL_MEC_RING0; 61 + adev->doorbell_index.mec_ring1 = AMDGPU_VEGA20_DOORBELL_MEC_RING1; 62 + adev->doorbell_index.mec_ring2 = AMDGPU_VEGA20_DOORBELL_MEC_RING2; 63 + adev->doorbell_index.mec_ring3 = AMDGPU_VEGA20_DOORBELL_MEC_RING3; 64 + adev->doorbell_index.mec_ring4 = AMDGPU_VEGA20_DOORBELL_MEC_RING4; 65 + adev->doorbell_index.mec_ring5 = AMDGPU_VEGA20_DOORBELL_MEC_RING5; 66 + adev->doorbell_index.mec_ring6 = AMDGPU_VEGA20_DOORBELL_MEC_RING6; 67 + adev->doorbell_index.mec_ring7 = AMDGPU_VEGA20_DOORBELL_MEC_RING7; 68 + adev->doorbell_index.userqueue_start = AMDGPU_VEGA20_DOORBELL_USERQUEUE_START; 69 + adev->doorbell_index.userqueue_end = AMDGPU_VEGA20_DOORBELL_USERQUEUE_END; 70 + adev->doorbell_index.gfx_ring0 = AMDGPU_VEGA20_DOORBELL_GFX_RING0; 71 + adev->doorbell_index.sdma_engine0 = AMDGPU_VEGA20_DOORBELL_sDMA_ENGINE0; 72 + adev->doorbell_index.sdma_engine1 = AMDGPU_VEGA20_DOORBELL_sDMA_ENGINE1; 73 + adev->doorbell_index.sdma_engine2 = AMDGPU_VEGA20_DOORBELL_sDMA_ENGINE2; 74 + adev->doorbell_index.sdma_engine3 = AMDGPU_VEGA20_DOORBELL_sDMA_ENGINE3; 75 + adev->doorbell_index.sdma_engine4 = AMDGPU_VEGA20_DOORBELL_sDMA_ENGINE4; 76 + adev->doorbell_index.sdma_engine5 = AMDGPU_VEGA20_DOORBELL_sDMA_ENGINE5; 77 + adev->doorbell_index.sdma_engine6 = AMDGPU_VEGA20_DOORBELL_sDMA_ENGINE6; 78 + adev->doorbell_index.sdma_engine7 = AMDGPU_VEGA20_DOORBELL_sDMA_ENGINE7; 79 + adev->doorbell_index.ih = AMDGPU_VEGA20_DOORBELL_IH; 80 + adev->doorbell_index.uvd_vce.uvd_ring0_1 = AMDGPU_VEGA20_DOORBELL64_UVD_RING0_1; 81 + adev->doorbell_index.uvd_vce.uvd_ring2_3 = AMDGPU_VEGA20_DOORBELL64_UVD_RING2_3; 82 + adev->doorbell_index.uvd_vce.uvd_ring4_5 = AMDGPU_VEGA20_DOORBELL64_UVD_RING4_5; 83 + adev->doorbell_index.uvd_vce.uvd_ring6_7 = AMDGPU_VEGA20_DOORBELL64_UVD_RING6_7; 84 + adev->doorbell_index.uvd_vce.vce_ring0_1 = AMDGPU_VEGA20_DOORBELL64_VCE_RING0_1; 85 + adev->doorbell_index.uvd_vce.vce_ring2_3 = AMDGPU_VEGA20_DOORBELL64_VCE_RING2_3; 86 + adev->doorbell_index.uvd_vce.vce_ring4_5 = AMDGPU_VEGA20_DOORBELL64_VCE_RING4_5; 87 + adev->doorbell_index.uvd_vce.vce_ring6_7 = AMDGPU_VEGA20_DOORBELL64_VCE_RING6_7; 88 + adev->doorbell_index.max_assignment = AMDGPU_VEGA20_DOORBELL_MAX_ASSIGNMENT << 1; 89 + } 57 90
+19
drivers/gpu/drm/amd/amdgpu/vi.c
··· 955 955 .flush_hdp = &vi_flush_hdp, 956 956 .invalidate_hdp = &vi_invalidate_hdp, 957 957 .need_full_reset = &vi_need_full_reset, 958 + .init_doorbell_index = &legacy_doorbell_index_init, 958 959 }; 959 960 960 961 #define CZ_REV_BRISTOL(rev) \ ··· 1712 1711 } 1713 1712 1714 1713 return 0; 1714 + } 1715 + 1716 + void legacy_doorbell_index_init(struct amdgpu_device *adev) 1717 + { 1718 + adev->doorbell_index.kiq = AMDGPU_DOORBELL_KIQ; 1719 + adev->doorbell_index.mec_ring0 = AMDGPU_DOORBELL_MEC_RING0; 1720 + adev->doorbell_index.mec_ring1 = AMDGPU_DOORBELL_MEC_RING1; 1721 + adev->doorbell_index.mec_ring2 = AMDGPU_DOORBELL_MEC_RING2; 1722 + adev->doorbell_index.mec_ring3 = AMDGPU_DOORBELL_MEC_RING3; 1723 + adev->doorbell_index.mec_ring4 = AMDGPU_DOORBELL_MEC_RING4; 1724 + adev->doorbell_index.mec_ring5 = AMDGPU_DOORBELL_MEC_RING5; 1725 + adev->doorbell_index.mec_ring6 = AMDGPU_DOORBELL_MEC_RING6; 1726 + adev->doorbell_index.mec_ring7 = AMDGPU_DOORBELL_MEC_RING7; 1727 + adev->doorbell_index.gfx_ring0 = AMDGPU_DOORBELL_GFX_RING0; 1728 + adev->doorbell_index.sdma_engine0 = AMDGPU_DOORBELL_sDMA_ENGINE0; 1729 + adev->doorbell_index.sdma_engine1 = AMDGPU_DOORBELL_sDMA_ENGINE1; 1730 + adev->doorbell_index.ih = AMDGPU_DOORBELL_IH; 1731 + adev->doorbell_index.max_assignment = AMDGPU_DOORBELL_MAX_ASSIGNMENT; 1715 1732 }
+1
drivers/gpu/drm/amd/amdgpu/vi.h
··· 30 30 u32 me, u32 pipe, u32 queue, u32 vmid); 31 31 int vi_set_ip_blocks(struct amdgpu_device *adev); 32 32 33 + void legacy_doorbell_index_init(struct amdgpu_device *adev); 33 34 #endif
+6
drivers/gpu/drm/amd/amdkfd/kfd_crat.c
··· 133 133 #define fiji_cache_info carrizo_cache_info 134 134 #define polaris10_cache_info carrizo_cache_info 135 135 #define polaris11_cache_info carrizo_cache_info 136 + #define polaris12_cache_info carrizo_cache_info 136 137 /* TODO - check & update Vega10 cache details */ 137 138 #define vega10_cache_info carrizo_cache_info 138 139 #define raven_cache_info carrizo_cache_info ··· 648 647 pcache_info = polaris11_cache_info; 649 648 num_of_cache_types = ARRAY_SIZE(polaris11_cache_info); 650 649 break; 650 + case CHIP_POLARIS12: 651 + pcache_info = polaris12_cache_info; 652 + num_of_cache_types = ARRAY_SIZE(polaris12_cache_info); 653 + break; 651 654 case CHIP_VEGA10: 655 + case CHIP_VEGA12: 652 656 case CHIP_VEGA20: 653 657 pcache_info = vega10_cache_info; 654 658 num_of_cache_types = ARRAY_SIZE(vega10_cache_info);
+45
drivers/gpu/drm/amd/amdkfd/kfd_device.c
··· 205 205 .num_sdma_queues_per_engine = 2, 206 206 }; 207 207 208 + static const struct kfd_device_info polaris12_device_info = { 209 + .asic_family = CHIP_POLARIS12, 210 + .max_pasid_bits = 16, 211 + .max_no_of_hqd = 24, 212 + .doorbell_size = 4, 213 + .ih_ring_entry_size = 4 * sizeof(uint32_t), 214 + .event_interrupt_class = &event_interrupt_class_cik, 215 + .num_of_watch_points = 4, 216 + .mqd_size_aligned = MQD_SIZE_ALIGNED, 217 + .supports_cwsr = true, 218 + .needs_iommu_device = false, 219 + .needs_pci_atomics = true, 220 + .num_sdma_engines = 2, 221 + .num_sdma_queues_per_engine = 2, 222 + }; 223 + 208 224 static const struct kfd_device_info vega10_device_info = { 209 225 .asic_family = CHIP_VEGA10, 210 226 .max_pasid_bits = 16, ··· 239 223 240 224 static const struct kfd_device_info vega10_vf_device_info = { 241 225 .asic_family = CHIP_VEGA10, 226 + .max_pasid_bits = 16, 227 + .max_no_of_hqd = 24, 228 + .doorbell_size = 8, 229 + .ih_ring_entry_size = 8 * sizeof(uint32_t), 230 + .event_interrupt_class = &event_interrupt_class_v9, 231 + .num_of_watch_points = 4, 232 + .mqd_size_aligned = MQD_SIZE_ALIGNED, 233 + .supports_cwsr = true, 234 + .needs_iommu_device = false, 235 + .needs_pci_atomics = false, 236 + .num_sdma_engines = 2, 237 + .num_sdma_queues_per_engine = 2, 238 + }; 239 + 240 + static const struct kfd_device_info vega12_device_info = { 241 + .asic_family = CHIP_VEGA12, 242 242 .max_pasid_bits = 16, 243 243 .max_no_of_hqd = 24, 244 244 .doorbell_size = 8, ··· 363 331 { 0x67EB, &polaris11_device_info }, /* Polaris11 */ 364 332 { 0x67EF, &polaris11_device_info }, /* Polaris11 */ 365 333 { 0x67FF, &polaris11_device_info }, /* Polaris11 */ 334 + { 0x6980, &polaris12_device_info }, /* Polaris12 */ 335 + { 0x6981, &polaris12_device_info }, /* Polaris12 */ 336 + { 0x6985, &polaris12_device_info }, /* Polaris12 */ 337 + { 0x6986, &polaris12_device_info }, /* Polaris12 */ 338 + { 0x6987, &polaris12_device_info }, /* Polaris12 */ 339 + { 0x6995, &polaris12_device_info }, /* Polaris12 */ 340 + { 0x6997, &polaris12_device_info }, /* Polaris12 */ 341 + { 0x699F, &polaris12_device_info }, /* Polaris12 */ 366 342 { 0x6860, &vega10_device_info }, /* Vega10 */ 367 343 { 0x6861, &vega10_device_info }, /* Vega10 */ 368 344 { 0x6862, &vega10_device_info }, /* Vega10 */ ··· 380 340 { 0x6868, &vega10_device_info }, /* Vega10 */ 381 341 { 0x686C, &vega10_vf_device_info }, /* Vega10 vf*/ 382 342 { 0x687F, &vega10_device_info }, /* Vega10 */ 343 + { 0x69A0, &vega12_device_info }, /* Vega12 */ 344 + { 0x69A1, &vega12_device_info }, /* Vega12 */ 345 + { 0x69A2, &vega12_device_info }, /* Vega12 */ 346 + { 0x69A3, &vega12_device_info }, /* Vega12 */ 347 + { 0x69AF, &vega12_device_info }, /* Vega12 */ 383 348 { 0x66a0, &vega20_device_info }, /* Vega20 */ 384 349 { 0x66a1, &vega20_device_info }, /* Vega20 */ 385 350 { 0x66a2, &vega20_device_info }, /* Vega20 */
+8 -6
drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
··· 1547 1547 u32 *ctl_stack_used_size, 1548 1548 u32 *save_area_used_size) 1549 1549 { 1550 - struct mqd_manager *mqd; 1550 + struct mqd_manager *mqd_mgr; 1551 1551 int r; 1552 1552 1553 1553 dqm_lock(dqm); ··· 1558 1558 goto dqm_unlock; 1559 1559 } 1560 1560 1561 - mqd = dqm->ops.get_mqd_manager(dqm, KFD_MQD_TYPE_COMPUTE); 1562 - if (!mqd) { 1561 + mqd_mgr = dqm->ops.get_mqd_manager(dqm, KFD_MQD_TYPE_COMPUTE); 1562 + if (!mqd_mgr) { 1563 1563 r = -ENOMEM; 1564 1564 goto dqm_unlock; 1565 1565 } 1566 1566 1567 - if (!mqd->get_wave_state) { 1567 + if (!mqd_mgr->get_wave_state) { 1568 1568 r = -EINVAL; 1569 1569 goto dqm_unlock; 1570 1570 } 1571 1571 1572 - r = mqd->get_wave_state(mqd, q->mqd, ctl_stack, ctl_stack_used_size, 1573 - save_area_used_size); 1572 + r = mqd_mgr->get_wave_state(mqd_mgr, q->mqd, ctl_stack, 1573 + ctl_stack_used_size, save_area_used_size); 1574 1574 1575 1575 dqm_unlock: 1576 1576 dqm_unlock(dqm); ··· 1741 1741 case CHIP_FIJI: 1742 1742 case CHIP_POLARIS10: 1743 1743 case CHIP_POLARIS11: 1744 + case CHIP_POLARIS12: 1744 1745 device_queue_manager_init_vi_tonga(&dqm->asic_ops); 1745 1746 break; 1746 1747 1747 1748 case CHIP_VEGA10: 1749 + case CHIP_VEGA12: 1748 1750 case CHIP_VEGA20: 1749 1751 case CHIP_RAVEN: 1750 1752 device_queue_manager_init_v9(&dqm->asic_ops);
-1
drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_vi.c
··· 24 24 #include "kfd_device_queue_manager.h" 25 25 #include "gca/gfx_8_0_enum.h" 26 26 #include "gca/gfx_8_0_sh_mask.h" 27 - #include "gca/gfx_8_0_enum.h" 28 27 #include "oss/oss_3_0_sh_mask.h" 29 28 30 29 static bool set_cache_memory_policy_vi(struct device_queue_manager *dqm,
+2
drivers/gpu/drm/amd/amdkfd/kfd_flat_memory.c
··· 397 397 case CHIP_FIJI: 398 398 case CHIP_POLARIS10: 399 399 case CHIP_POLARIS11: 400 + case CHIP_POLARIS12: 400 401 kfd_init_apertures_vi(pdd, id); 401 402 break; 402 403 case CHIP_VEGA10: 404 + case CHIP_VEGA12: 403 405 case CHIP_VEGA20: 404 406 case CHIP_RAVEN: 405 407 kfd_init_apertures_v9(pdd, id);
+27 -8
drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c
··· 23 23 #include "kfd_priv.h" 24 24 #include "kfd_events.h" 25 25 #include "soc15_int.h" 26 - 26 + #include "kfd_device_queue_manager.h" 27 27 28 28 static bool event_interrupt_isr_v9(struct kfd_dev *dev, 29 29 const uint32_t *ih_ring_entry, ··· 39 39 vmid > dev->vm_info.last_vmid_kfd) 40 40 return 0; 41 41 42 - /* If there is no valid PASID, it's likely a firmware bug */ 43 - pasid = SOC15_PASID_FROM_IH_ENTRY(ih_ring_entry); 44 - if (WARN_ONCE(pasid == 0, "FW bug: No PASID in KFD interrupt")) 45 - return 0; 46 - 47 42 source_id = SOC15_SOURCE_ID_FROM_IH_ENTRY(ih_ring_entry); 48 43 client_id = SOC15_CLIENT_ID_FROM_IH_ENTRY(ih_ring_entry); 44 + pasid = SOC15_PASID_FROM_IH_ENTRY(ih_ring_entry); 49 45 50 - pr_debug("client id 0x%x, source id %d, pasid 0x%x. raw data:\n", 51 - client_id, source_id, pasid); 46 + /* This is a known issue for gfx9. Under non HWS, pasid is not set 47 + * in the interrupt payload, so we need to find out the pasid on our 48 + * own. 49 + */ 50 + if (!pasid && dev->dqm->sched_policy == KFD_SCHED_POLICY_NO_HWS) { 51 + const uint32_t pasid_mask = 0xffff; 52 + 53 + *patched_flag = true; 54 + memcpy(patched_ihre, ih_ring_entry, 55 + dev->device_info->ih_ring_entry_size); 56 + 57 + pasid = dev->kfd2kgd->get_atc_vmid_pasid_mapping_pasid( 58 + dev->kgd, vmid); 59 + 60 + /* Patch the pasid field */ 61 + patched_ihre[3] = cpu_to_le32((le32_to_cpu(patched_ihre[3]) 62 + & ~pasid_mask) | pasid); 63 + } 64 + 65 + pr_debug("client id 0x%x, source id %d, vmid %d, pasid 0x%x. raw data:\n", 66 + client_id, source_id, vmid, pasid); 52 67 pr_debug("%8X, %8X, %8X, %8X, %8X, %8X, %8X, %8X.\n", 53 68 data[0], data[1], data[2], data[3], 54 69 data[4], data[5], data[6], data[7]); 70 + 71 + /* If there is no valid PASID, it's likely a bug */ 72 + if (WARN_ONCE(pasid == 0, "Bug: No PASID in KFD interrupt")) 73 + return 0; 55 74 56 75 /* Interrupt types we care about: various signals and faults. 57 76 * They will be forwarded to a work queue (see below).
+2
drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c
··· 313 313 case CHIP_FIJI: 314 314 case CHIP_POLARIS10: 315 315 case CHIP_POLARIS11: 316 + case CHIP_POLARIS12: 316 317 kernel_queue_init_vi(&kq->ops_asic_specific); 317 318 break; 318 319 ··· 323 322 break; 324 323 325 324 case CHIP_VEGA10: 325 + case CHIP_VEGA12: 326 326 case CHIP_VEGA20: 327 327 case CHIP_RAVEN: 328 328 kernel_queue_init_v9(&kq->ops_asic_specific);
+2
drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c
··· 38 38 case CHIP_FIJI: 39 39 case CHIP_POLARIS10: 40 40 case CHIP_POLARIS11: 41 + case CHIP_POLARIS12: 41 42 return mqd_manager_init_vi_tonga(type, dev); 42 43 case CHIP_VEGA10: 44 + case CHIP_VEGA12: 43 45 case CHIP_VEGA20: 44 46 case CHIP_RAVEN: 45 47 return mqd_manager_init_v9(type, dev);
+2
drivers/gpu/drm/amd/amdkfd/kfd_packet_manager.c
··· 226 226 case CHIP_FIJI: 227 227 case CHIP_POLARIS10: 228 228 case CHIP_POLARIS11: 229 + case CHIP_POLARIS12: 229 230 pm->pmf = &kfd_vi_pm_funcs; 230 231 break; 231 232 case CHIP_VEGA10: 233 + case CHIP_VEGA12: 232 234 case CHIP_VEGA20: 233 235 case CHIP_RAVEN: 234 236 pm->pmf = &kfd_v9_pm_funcs;
+2
drivers/gpu/drm/amd/amdkfd/kfd_topology.c
··· 1272 1272 case CHIP_FIJI: 1273 1273 case CHIP_POLARIS10: 1274 1274 case CHIP_POLARIS11: 1275 + case CHIP_POLARIS12: 1275 1276 pr_debug("Adding doorbell packet type capability\n"); 1276 1277 dev->node_props.capability |= ((HSA_CAP_DOORBELL_TYPE_1_0 << 1277 1278 HSA_CAP_DOORBELL_TYPE_TOTALBITS_SHIFT) & 1278 1279 HSA_CAP_DOORBELL_TYPE_TOTALBITS_MASK); 1279 1280 break; 1280 1281 case CHIP_VEGA10: 1282 + case CHIP_VEGA12: 1281 1283 case CHIP_VEGA20: 1282 1284 case CHIP_RAVEN: 1283 1285 dev->node_props.capability |= ((HSA_CAP_DOORBELL_TYPE_2_0 <<
+2 -1
drivers/gpu/drm/amd/display/Makefile
··· 32 32 subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/freesync 33 33 subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/color 34 34 subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/info_packet 35 + subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/power 35 36 36 37 #TODO: remove when Timing Sync feature is complete 37 38 subdir-ccflags-y += -DBUILD_FEATURE_TIMING_SYNC=0 38 39 39 - DAL_LIBS = amdgpu_dm dc modules/freesync modules/color modules/info_packet 40 + DAL_LIBS = amdgpu_dm dc modules/freesync modules/color modules/info_packet modules/power 40 41 41 42 AMD_DAL = $(addsuffix /Makefile, $(addprefix $(FULL_AMD_DISPLAY_PATH)/,$(DAL_LIBS))) 42 43
+494 -217
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
··· 38 38 #include "amd_shared.h" 39 39 #include "amdgpu_dm_irq.h" 40 40 #include "dm_helpers.h" 41 - #include "dm_services_types.h" 42 41 #include "amdgpu_dm_mst_types.h" 43 42 #if defined(CONFIG_DEBUG_FS) 44 43 #include "amdgpu_dm_debugfs.h" ··· 71 72 #endif 72 73 73 74 #include "modules/inc/mod_freesync.h" 75 + #include "modules/power/power_helpers.h" 74 76 75 77 #define FIRMWARE_RAVEN_DMCU "amdgpu/raven_dmcu.bin" 76 78 MODULE_FIRMWARE(FIRMWARE_RAVEN_DMCU); ··· 643 643 { 644 644 struct amdgpu_device *adev = (struct amdgpu_device *)handle; 645 645 646 + struct dmcu_iram_parameters params; 647 + unsigned int linear_lut[16]; 648 + int i; 649 + struct dmcu *dmcu = adev->dm.dc->res_pool->dmcu; 650 + bool ret; 651 + 652 + for (i = 0; i < 16; i++) 653 + linear_lut[i] = 0xFFFF * i / 15; 654 + 655 + params.set = 0; 656 + params.backlight_ramping_start = 0xCCCC; 657 + params.backlight_ramping_reduction = 0xCCCCCCCC; 658 + params.backlight_lut_array_size = 16; 659 + params.backlight_lut_array = linear_lut; 660 + 661 + ret = dmcu_load_iram(dmcu, params); 662 + 663 + if (!ret) 664 + return -EINVAL; 665 + 646 666 return detect_mst_link_for_all_connectors(adev->ddev); 647 667 } 648 668 ··· 989 969 }; 990 970 991 971 992 - static struct drm_atomic_state * 993 - dm_atomic_state_alloc(struct drm_device *dev) 994 - { 995 - struct dm_atomic_state *state = kzalloc(sizeof(*state), GFP_KERNEL); 996 - 997 - if (!state) 998 - return NULL; 999 - 1000 - if (drm_atomic_state_init(dev, &state->base) < 0) 1001 - goto fail; 1002 - 1003 - return &state->base; 1004 - 1005 - fail: 1006 - kfree(state); 1007 - return NULL; 1008 - } 1009 - 1010 - static void 1011 - dm_atomic_state_clear(struct drm_atomic_state *state) 1012 - { 1013 - struct dm_atomic_state *dm_state = to_dm_atomic_state(state); 1014 - 1015 - if (dm_state->context) { 1016 - dc_release_state(dm_state->context); 1017 - dm_state->context = NULL; 1018 - } 1019 - 1020 - drm_atomic_state_default_clear(state); 1021 - } 1022 - 1023 - static void 1024 - dm_atomic_state_alloc_free(struct drm_atomic_state *state) 1025 - { 1026 - struct dm_atomic_state *dm_state = to_dm_atomic_state(state); 1027 - drm_atomic_state_default_release(state); 1028 - kfree(dm_state); 1029 - } 1030 - 1031 972 /** 1032 973 * DOC: atomic 1033 974 * ··· 1000 1019 .output_poll_changed = drm_fb_helper_output_poll_changed, 1001 1020 .atomic_check = amdgpu_dm_atomic_check, 1002 1021 .atomic_commit = amdgpu_dm_atomic_commit, 1003 - .atomic_state_alloc = dm_atomic_state_alloc, 1004 - .atomic_state_clear = dm_atomic_state_clear, 1005 - .atomic_state_free = dm_atomic_state_alloc_free 1006 1022 }; 1007 1023 1008 1024 static struct drm_mode_config_helper_funcs amdgpu_dm_mode_config_helperfuncs = { ··· 1521 1543 } 1522 1544 #endif 1523 1545 1546 + /* 1547 + * Acquires the lock for the atomic state object and returns 1548 + * the new atomic state. 1549 + * 1550 + * This should only be called during atomic check. 1551 + */ 1552 + static int dm_atomic_get_state(struct drm_atomic_state *state, 1553 + struct dm_atomic_state **dm_state) 1554 + { 1555 + struct drm_device *dev = state->dev; 1556 + struct amdgpu_device *adev = dev->dev_private; 1557 + struct amdgpu_display_manager *dm = &adev->dm; 1558 + struct drm_private_state *priv_state; 1559 + int ret; 1560 + 1561 + if (*dm_state) 1562 + return 0; 1563 + 1564 + ret = drm_modeset_lock(&dm->atomic_obj_lock, state->acquire_ctx); 1565 + if (ret) 1566 + return ret; 1567 + 1568 + priv_state = drm_atomic_get_private_obj_state(state, &dm->atomic_obj); 1569 + if (IS_ERR(priv_state)) 1570 + return PTR_ERR(priv_state); 1571 + 1572 + *dm_state = to_dm_atomic_state(priv_state); 1573 + 1574 + return 0; 1575 + } 1576 + 1577 + struct dm_atomic_state * 1578 + dm_atomic_get_new_state(struct drm_atomic_state *state) 1579 + { 1580 + struct drm_device *dev = state->dev; 1581 + struct amdgpu_device *adev = dev->dev_private; 1582 + struct amdgpu_display_manager *dm = &adev->dm; 1583 + struct drm_private_obj *obj; 1584 + struct drm_private_state *new_obj_state; 1585 + int i; 1586 + 1587 + for_each_new_private_obj_in_state(state, obj, new_obj_state, i) { 1588 + if (obj->funcs == dm->atomic_obj.funcs) 1589 + return to_dm_atomic_state(new_obj_state); 1590 + } 1591 + 1592 + return NULL; 1593 + } 1594 + 1595 + struct dm_atomic_state * 1596 + dm_atomic_get_old_state(struct drm_atomic_state *state) 1597 + { 1598 + struct drm_device *dev = state->dev; 1599 + struct amdgpu_device *adev = dev->dev_private; 1600 + struct amdgpu_display_manager *dm = &adev->dm; 1601 + struct drm_private_obj *obj; 1602 + struct drm_private_state *old_obj_state; 1603 + int i; 1604 + 1605 + for_each_old_private_obj_in_state(state, obj, old_obj_state, i) { 1606 + if (obj->funcs == dm->atomic_obj.funcs) 1607 + return to_dm_atomic_state(old_obj_state); 1608 + } 1609 + 1610 + return NULL; 1611 + } 1612 + 1613 + static struct drm_private_state * 1614 + dm_atomic_duplicate_state(struct drm_private_obj *obj) 1615 + { 1616 + struct dm_atomic_state *old_state, *new_state; 1617 + 1618 + new_state = kzalloc(sizeof(*new_state), GFP_KERNEL); 1619 + if (!new_state) 1620 + return NULL; 1621 + 1622 + __drm_atomic_helper_private_obj_duplicate_state(obj, &new_state->base); 1623 + 1624 + new_state->context = dc_create_state(); 1625 + if (!new_state->context) { 1626 + kfree(new_state); 1627 + return NULL; 1628 + } 1629 + 1630 + old_state = to_dm_atomic_state(obj->state); 1631 + if (old_state && old_state->context) 1632 + dc_resource_state_copy_construct(old_state->context, 1633 + new_state->context); 1634 + 1635 + return &new_state->base; 1636 + } 1637 + 1638 + static void dm_atomic_destroy_state(struct drm_private_obj *obj, 1639 + struct drm_private_state *state) 1640 + { 1641 + struct dm_atomic_state *dm_state = to_dm_atomic_state(state); 1642 + 1643 + if (dm_state && dm_state->context) 1644 + dc_release_state(dm_state->context); 1645 + 1646 + kfree(dm_state); 1647 + } 1648 + 1649 + static struct drm_private_state_funcs dm_atomic_state_funcs = { 1650 + .atomic_duplicate_state = dm_atomic_duplicate_state, 1651 + .atomic_destroy_state = dm_atomic_destroy_state, 1652 + }; 1653 + 1524 1654 static int amdgpu_dm_mode_config_init(struct amdgpu_device *adev) 1525 1655 { 1656 + struct dm_atomic_state *state; 1526 1657 int r; 1527 1658 1528 1659 adev->mode_info.mode_config_initialized = true; ··· 1649 1562 1650 1563 adev->ddev->mode_config.fb_base = adev->gmc.aper_base; 1651 1564 1565 + drm_modeset_lock_init(&adev->dm.atomic_obj_lock); 1566 + 1567 + state = kzalloc(sizeof(*state), GFP_KERNEL); 1568 + if (!state) 1569 + return -ENOMEM; 1570 + 1571 + state->context = dc_create_state(); 1572 + if (!state->context) { 1573 + kfree(state); 1574 + return -ENOMEM; 1575 + } 1576 + 1577 + dc_resource_state_copy_construct_current(adev->dm.dc, state->context); 1578 + 1579 + drm_atomic_private_obj_init(&adev->dm.atomic_obj, 1580 + &state->base, 1581 + &dm_atomic_state_funcs); 1582 + 1652 1583 r = amdgpu_display_modeset_create_props(adev); 1653 1584 if (r) 1654 1585 return r; ··· 1674 1569 return 0; 1675 1570 } 1676 1571 1572 + #define AMDGPU_DM_DEFAULT_MIN_BACKLIGHT 12 1573 + #define AMDGPU_DM_DEFAULT_MAX_BACKLIGHT 255 1574 + 1677 1575 #if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) ||\ 1678 1576 defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE) 1577 + 1578 + static void amdgpu_dm_update_backlight_caps(struct amdgpu_display_manager *dm) 1579 + { 1580 + #if defined(CONFIG_ACPI) 1581 + struct amdgpu_dm_backlight_caps caps; 1582 + 1583 + if (dm->backlight_caps.caps_valid) 1584 + return; 1585 + 1586 + amdgpu_acpi_get_backlight_caps(dm->adev, &caps); 1587 + if (caps.caps_valid) { 1588 + dm->backlight_caps.min_input_signal = caps.min_input_signal; 1589 + dm->backlight_caps.max_input_signal = caps.max_input_signal; 1590 + dm->backlight_caps.caps_valid = true; 1591 + } else { 1592 + dm->backlight_caps.min_input_signal = 1593 + AMDGPU_DM_DEFAULT_MIN_BACKLIGHT; 1594 + dm->backlight_caps.max_input_signal = 1595 + AMDGPU_DM_DEFAULT_MAX_BACKLIGHT; 1596 + } 1597 + #else 1598 + dm->backlight_caps.min_input_signal = AMDGPU_DM_DEFAULT_MIN_BACKLIGHT; 1599 + dm->backlight_caps.max_input_signal = AMDGPU_DM_DEFAULT_MAX_BACKLIGHT; 1600 + #endif 1601 + } 1679 1602 1680 1603 static int amdgpu_dm_backlight_update_status(struct backlight_device *bd) 1681 1604 { 1682 1605 struct amdgpu_display_manager *dm = bl_get_data(bd); 1606 + struct amdgpu_dm_backlight_caps caps; 1607 + uint32_t brightness = bd->props.brightness; 1683 1608 1684 - /* backlight_pwm_u16_16 parameter is in unsigned 32 bit, 16 bit integer 1685 - * and 16 bit fractional, where 1.0 is max backlight value. 1686 - * bd->props.brightness is 8 bit format and needs to be converted by 1687 - * scaling via copy lower byte to upper byte of 16 bit value. 1688 - */ 1689 - uint32_t brightness = bd->props.brightness * 0x101; 1690 - 1609 + amdgpu_dm_update_backlight_caps(dm); 1610 + caps = dm->backlight_caps; 1691 1611 /* 1692 - * PWM interperts 0 as 100% rather than 0% because of HW 1693 - * limitation for level 0. So limiting minimum brightness level 1694 - * to 1. 1612 + * The brightness input is in the range 0-255 1613 + * It needs to be rescaled to be between the 1614 + * requested min and max input signal 1615 + * 1616 + * It also needs to be scaled up by 0x101 to 1617 + * match the DC interface which has a range of 1618 + * 0 to 0xffff 1695 1619 */ 1696 - if (bd->props.brightness < 1) 1697 - brightness = 0x101; 1620 + brightness = 1621 + brightness 1622 + * 0x101 1623 + * (caps.max_input_signal - caps.min_input_signal) 1624 + / AMDGPU_MAX_BL_LEVEL 1625 + + caps.min_input_signal * 0x101; 1698 1626 1699 1627 if (dc_link_set_backlight_level(dm->backlight_link, 1700 1628 brightness, 0, 0)) ··· 1756 1618 { 1757 1619 char bl_name[16]; 1758 1620 struct backlight_properties props = { 0 }; 1621 + 1622 + amdgpu_dm_update_backlight_caps(dm); 1759 1623 1760 1624 props.max_brightness = AMDGPU_MAX_BL_LEVEL; 1761 1625 props.brightness = AMDGPU_MAX_BL_LEVEL; ··· 1990 1850 static void amdgpu_dm_destroy_drm_device(struct amdgpu_display_manager *dm) 1991 1851 { 1992 1852 drm_mode_config_cleanup(dm->ddev); 1853 + drm_atomic_private_obj_fini(&dm->atomic_obj); 1993 1854 return; 1994 1855 } 1995 1856 ··· 2010 1869 /* TODO: implement later */ 2011 1870 } 2012 1871 2013 - static int amdgpu_notify_freesync(struct drm_device *dev, void *data, 2014 - struct drm_file *filp) 2015 - { 2016 - struct drm_atomic_state *state; 2017 - struct drm_modeset_acquire_ctx ctx; 2018 - struct drm_crtc *crtc; 2019 - struct drm_connector *connector; 2020 - struct drm_connector_state *old_con_state, *new_con_state; 2021 - int ret = 0; 2022 - uint8_t i; 2023 - bool enable = false; 2024 - 2025 - drm_modeset_acquire_init(&ctx, 0); 2026 - 2027 - state = drm_atomic_state_alloc(dev); 2028 - if (!state) { 2029 - ret = -ENOMEM; 2030 - goto out; 2031 - } 2032 - state->acquire_ctx = &ctx; 2033 - 2034 - retry: 2035 - drm_for_each_crtc(crtc, dev) { 2036 - ret = drm_atomic_add_affected_connectors(state, crtc); 2037 - if (ret) 2038 - goto fail; 2039 - 2040 - /* TODO rework amdgpu_dm_commit_planes so we don't need this */ 2041 - ret = drm_atomic_add_affected_planes(state, crtc); 2042 - if (ret) 2043 - goto fail; 2044 - } 2045 - 2046 - for_each_oldnew_connector_in_state(state, connector, old_con_state, new_con_state, i) { 2047 - struct dm_connector_state *dm_new_con_state = to_dm_connector_state(new_con_state); 2048 - struct drm_crtc_state *new_crtc_state; 2049 - struct amdgpu_crtc *acrtc = to_amdgpu_crtc(dm_new_con_state->base.crtc); 2050 - struct dm_crtc_state *dm_new_crtc_state; 2051 - 2052 - if (!acrtc) { 2053 - ASSERT(0); 2054 - continue; 2055 - } 2056 - 2057 - new_crtc_state = drm_atomic_get_new_crtc_state(state, &acrtc->base); 2058 - dm_new_crtc_state = to_dm_crtc_state(new_crtc_state); 2059 - 2060 - dm_new_crtc_state->freesync_enabled = enable; 2061 - } 2062 - 2063 - ret = drm_atomic_commit(state); 2064 - 2065 - fail: 2066 - if (ret == -EDEADLK) { 2067 - drm_atomic_state_clear(state); 2068 - drm_modeset_backoff(&ctx); 2069 - goto retry; 2070 - } 2071 - 2072 - drm_atomic_state_put(state); 2073 - 2074 - out: 2075 - drm_modeset_drop_locks(&ctx); 2076 - drm_modeset_acquire_fini(&ctx); 2077 - return ret; 2078 - } 2079 - 2080 1872 static const struct amdgpu_display_funcs dm_display_funcs = { 2081 1873 .bandwidth_update = dm_bandwidth_update, /* called unconditionally */ 2082 1874 .vblank_get_counter = dm_vblank_get_counter,/* called unconditionally */ ··· 2022 1948 dm_crtc_get_scanoutpos,/* called unconditionally */ 2023 1949 .add_encoder = NULL, /* VBIOS parsing. DAL does it. */ 2024 1950 .add_connector = NULL, /* VBIOS parsing. DAL does it. */ 2025 - .notify_freesync = amdgpu_notify_freesync, 2026 - 2027 1951 }; 2028 1952 2029 1953 #if defined(CONFIG_DEBUG_KERNEL_DC) ··· 2622 2550 static void 2623 2551 fill_stream_properties_from_drm_display_mode(struct dc_stream_state *stream, 2624 2552 const struct drm_display_mode *mode_in, 2625 - const struct drm_connector *connector) 2553 + const struct drm_connector *connector, 2554 + const struct dc_stream_state *old_stream) 2626 2555 { 2627 2556 struct dc_crtc_timing *timing_out = &stream->timing; 2628 2557 const struct drm_display_info *info = &connector->display_info; ··· 2649 2576 connector); 2650 2577 timing_out->scan_type = SCANNING_TYPE_NODATA; 2651 2578 timing_out->hdmi_vic = 0; 2652 - timing_out->vic = drm_match_cea_mode(mode_in); 2579 + 2580 + if(old_stream) { 2581 + timing_out->vic = old_stream->timing.vic; 2582 + timing_out->flags.HSYNC_POSITIVE_POLARITY = old_stream->timing.flags.HSYNC_POSITIVE_POLARITY; 2583 + timing_out->flags.VSYNC_POSITIVE_POLARITY = old_stream->timing.flags.VSYNC_POSITIVE_POLARITY; 2584 + } else { 2585 + timing_out->vic = drm_match_cea_mode(mode_in); 2586 + if (mode_in->flags & DRM_MODE_FLAG_PHSYNC) 2587 + timing_out->flags.HSYNC_POSITIVE_POLARITY = 1; 2588 + if (mode_in->flags & DRM_MODE_FLAG_PVSYNC) 2589 + timing_out->flags.VSYNC_POSITIVE_POLARITY = 1; 2590 + } 2653 2591 2654 2592 timing_out->h_addressable = mode_in->crtc_hdisplay; 2655 2593 timing_out->h_total = mode_in->crtc_htotal; ··· 2676 2592 mode_in->crtc_vsync_end - mode_in->crtc_vsync_start; 2677 2593 timing_out->pix_clk_khz = mode_in->crtc_clock; 2678 2594 timing_out->aspect_ratio = get_aspect_ratio(mode_in); 2679 - if (mode_in->flags & DRM_MODE_FLAG_PHSYNC) 2680 - timing_out->flags.HSYNC_POSITIVE_POLARITY = 1; 2681 - if (mode_in->flags & DRM_MODE_FLAG_PVSYNC) 2682 - timing_out->flags.VSYNC_POSITIVE_POLARITY = 1; 2683 2595 2684 2596 stream->output_color_space = get_output_color_space(timing_out); 2685 2597 ··· 2838 2758 static struct dc_stream_state * 2839 2759 create_stream_for_sink(struct amdgpu_dm_connector *aconnector, 2840 2760 const struct drm_display_mode *drm_mode, 2841 - const struct dm_connector_state *dm_state) 2761 + const struct dm_connector_state *dm_state, 2762 + const struct dc_stream_state *old_stream) 2842 2763 { 2843 2764 struct drm_display_mode *preferred_mode = NULL; 2844 2765 struct drm_connector *drm_connector; 2845 2766 struct dc_stream_state *stream = NULL; 2846 2767 struct drm_display_mode mode = *drm_mode; 2847 2768 bool native_mode_found = false; 2769 + bool scale = dm_state ? (dm_state->scaling != RMX_OFF) : false; 2770 + int mode_refresh; 2771 + int preferred_refresh = 0; 2772 + 2848 2773 struct dc_sink *sink = NULL; 2849 2774 if (aconnector == NULL) { 2850 2775 DRM_ERROR("aconnector is NULL!\n"); ··· 2888 2803 struct drm_display_mode, 2889 2804 head); 2890 2805 2806 + mode_refresh = drm_mode_vrefresh(&mode); 2807 + 2891 2808 if (preferred_mode == NULL) { 2892 2809 /* 2893 2810 * This may not be an error, the use case is when we have no ··· 2902 2815 decide_crtc_timing_for_drm_display_mode( 2903 2816 &mode, preferred_mode, 2904 2817 dm_state ? (dm_state->scaling != RMX_OFF) : false); 2818 + preferred_refresh = drm_mode_vrefresh(preferred_mode); 2905 2819 } 2906 2820 2907 2821 if (!dm_state) 2908 2822 drm_mode_set_crtcinfo(&mode, 0); 2909 2823 2910 - fill_stream_properties_from_drm_display_mode(stream, 2911 - &mode, &aconnector->base); 2824 + /* 2825 + * If scaling is enabled and refresh rate didn't change 2826 + * we copy the vic and polarities of the old timings 2827 + */ 2828 + if (!scale || mode_refresh != preferred_refresh) 2829 + fill_stream_properties_from_drm_display_mode(stream, 2830 + &mode, &aconnector->base, NULL); 2831 + else 2832 + fill_stream_properties_from_drm_display_mode(stream, 2833 + &mode, &aconnector->base, old_stream); 2834 + 2912 2835 update_stream_scaling_settings(&mode, dm_state, stream); 2913 2836 2914 2837 fill_audio_info( ··· 2998 2901 2999 2902 state->adjust = cur->adjust; 3000 2903 state->vrr_infopacket = cur->vrr_infopacket; 3001 - state->freesync_enabled = cur->freesync_enabled; 2904 + state->abm_level = cur->abm_level; 2905 + state->vrr_supported = cur->vrr_supported; 2906 + state->freesync_config = cur->freesync_config; 3002 2907 3003 2908 /* TODO Duplicate dc_stream after objects are stream object is flattened */ 3004 2909 ··· 3094 2995 rmx_type = RMX_FULL; 3095 2996 break; 3096 2997 case DRM_MODE_SCALE_NONE: 3097 - default: 3098 2998 rmx_type = RMX_OFF; 2999 + break; 3000 + default: 3001 + rmx_type = RMX_ASPECT; 3099 3002 break; 3100 3003 } 3101 3004 ··· 3117 3016 ret = 0; 3118 3017 } else if (property == adev->mode_info.max_bpc_property) { 3119 3018 dm_new_state->max_bpc = val; 3019 + ret = 0; 3020 + } else if (property == adev->mode_info.abm_level_property) { 3021 + dm_new_state->abm_level = val; 3120 3022 ret = 0; 3121 3023 } 3122 3024 ··· 3166 3062 } else if (property == adev->mode_info.max_bpc_property) { 3167 3063 *val = dm_state->max_bpc; 3168 3064 ret = 0; 3065 + } else if (property == adev->mode_info.abm_level_property) { 3066 + *val = dm_state->abm_level; 3067 + ret = 0; 3169 3068 } 3069 + 3170 3070 return ret; 3171 3071 } 3172 3072 ··· 3210 3102 state = kzalloc(sizeof(*state), GFP_KERNEL); 3211 3103 3212 3104 if (state) { 3213 - state->scaling = RMX_OFF; 3105 + state->scaling = RMX_ASPECT; 3214 3106 state->underscan_enable = false; 3215 3107 state->underscan_hborder = 0; 3216 3108 state->underscan_vborder = 0; ··· 3234 3126 __drm_atomic_helper_connector_duplicate_state(connector, &new_state->base); 3235 3127 3236 3128 new_state->freesync_capable = state->freesync_capable; 3237 - new_state->freesync_enable = state->freesync_enable; 3129 + new_state->abm_level = state->abm_level; 3238 3130 3239 3131 return &new_state->base; 3240 3132 } ··· 3336 3228 goto fail; 3337 3229 } 3338 3230 3339 - stream = create_stream_for_sink(aconnector, mode, NULL); 3231 + stream = create_stream_for_sink(aconnector, mode, NULL, NULL); 3340 3232 if (stream == NULL) { 3341 3233 DRM_ERROR("Failed to create stream for sink!\n"); 3342 3234 goto fail; ··· 3984 3876 adev->mode_info.max_bpc_property, 3985 3877 0); 3986 3878 3879 + if (connector_type == DRM_MODE_CONNECTOR_eDP && 3880 + dc_is_dmcu_initialized(adev->dm.dc)) { 3881 + drm_object_attach_property(&aconnector->base.base, 3882 + adev->mode_info.abm_level_property, 0); 3883 + } 3884 + 3885 + if (connector_type == DRM_MODE_CONNECTOR_HDMIA || 3886 + connector_type == DRM_MODE_CONNECTOR_DisplayPort) { 3887 + drm_connector_attach_vrr_capable_property( 3888 + &aconnector->base); 3889 + } 3987 3890 } 3988 3891 3989 3892 static int amdgpu_dm_i2c_xfer(struct i2c_adapter *i2c_adap, ··· 4371 4252 acrtc->crtc_id); 4372 4253 } 4373 4254 4255 + struct dc_stream_status *dc_state_get_stream_status( 4256 + struct dc_state *state, 4257 + struct dc_stream_state *stream) 4258 + { 4259 + uint8_t i; 4260 + 4261 + for (i = 0; i < state->stream_count; i++) { 4262 + if (stream == state->streams[i]) 4263 + return &state->stream_status[i]; 4264 + } 4265 + 4266 + return NULL; 4267 + } 4268 + 4269 + static void update_freesync_state_on_stream( 4270 + struct amdgpu_display_manager *dm, 4271 + struct dm_crtc_state *new_crtc_state, 4272 + struct dc_stream_state *new_stream) 4273 + { 4274 + struct mod_vrr_params vrr = {0}; 4275 + struct dc_info_packet vrr_infopacket = {0}; 4276 + struct mod_freesync_config config = new_crtc_state->freesync_config; 4277 + 4278 + if (!new_stream) 4279 + return; 4280 + 4281 + /* 4282 + * TODO: Determine why min/max totals and vrefresh can be 0 here. 4283 + * For now it's sufficient to just guard against these conditions. 4284 + */ 4285 + 4286 + if (!new_stream->timing.h_total || !new_stream->timing.v_total) 4287 + return; 4288 + 4289 + if (new_crtc_state->vrr_supported && 4290 + config.min_refresh_in_uhz && 4291 + config.max_refresh_in_uhz) { 4292 + config.state = new_crtc_state->base.vrr_enabled ? 4293 + VRR_STATE_ACTIVE_VARIABLE : 4294 + VRR_STATE_INACTIVE; 4295 + } else { 4296 + config.state = VRR_STATE_UNSUPPORTED; 4297 + } 4298 + 4299 + mod_freesync_build_vrr_params(dm->freesync_module, 4300 + new_stream, 4301 + &config, &vrr); 4302 + 4303 + mod_freesync_build_vrr_infopacket( 4304 + dm->freesync_module, 4305 + new_stream, 4306 + &vrr, 4307 + packet_type_vrr, 4308 + transfer_func_unknown, 4309 + &vrr_infopacket); 4310 + 4311 + new_crtc_state->freesync_timing_changed = 4312 + (memcmp(&new_crtc_state->adjust, 4313 + &vrr.adjust, 4314 + sizeof(vrr.adjust)) != 0); 4315 + 4316 + new_crtc_state->freesync_vrr_info_changed = 4317 + (memcmp(&new_crtc_state->vrr_infopacket, 4318 + &vrr_infopacket, 4319 + sizeof(vrr_infopacket)) != 0); 4320 + 4321 + new_crtc_state->adjust = vrr.adjust; 4322 + new_crtc_state->vrr_infopacket = vrr_infopacket; 4323 + 4324 + new_stream->adjust = new_crtc_state->adjust; 4325 + new_stream->vrr_infopacket = vrr_infopacket; 4326 + 4327 + if (new_crtc_state->freesync_vrr_info_changed) 4328 + DRM_DEBUG_KMS("VRR packet update: crtc=%u enabled=%d state=%d", 4329 + new_crtc_state->base.crtc->base.id, 4330 + (int)new_crtc_state->base.vrr_enabled, 4331 + (int)vrr.state); 4332 + 4333 + if (new_crtc_state->freesync_timing_changed) 4334 + DRM_DEBUG_KMS("VRR timing update: crtc=%u min=%u max=%u\n", 4335 + new_crtc_state->base.crtc->base.id, 4336 + vrr.adjust.v_total_min, 4337 + vrr.adjust.v_total_max); 4338 + } 4339 + 4374 4340 /* 4375 4341 * Executes flip 4376 4342 * ··· 4477 4273 struct dc_flip_addrs addr = { {0} }; 4478 4274 /* TODO eliminate or rename surface_update */ 4479 4275 struct dc_surface_update surface_updates[1] = { {0} }; 4276 + struct dc_stream_update stream_update = {0}; 4480 4277 struct dm_crtc_state *acrtc_state = to_dm_crtc_state(crtc->state); 4481 4278 struct dc_stream_status *stream_status; 4482 4279 ··· 4550 4345 } 4551 4346 surface_updates->flip_addr = &addr; 4552 4347 4348 + if (acrtc_state->stream) { 4349 + update_freesync_state_on_stream( 4350 + &adev->dm, 4351 + acrtc_state, 4352 + acrtc_state->stream); 4353 + 4354 + if (acrtc_state->freesync_timing_changed) 4355 + stream_update.adjust = 4356 + &acrtc_state->stream->adjust; 4357 + 4358 + if (acrtc_state->freesync_vrr_info_changed) 4359 + stream_update.vrr_infopacket = 4360 + &acrtc_state->stream->vrr_infopacket; 4361 + } 4362 + 4553 4363 dc_commit_updates_for_stream(adev->dm.dc, 4554 4364 surface_updates, 4555 4365 1, 4556 4366 acrtc_state->stream, 4557 - NULL, 4367 + &stream_update, 4558 4368 &surface_updates->surface, 4559 4369 state); 4560 4370 ··· 4602 4382 struct dc_stream_state *dc_stream = dm_new_crtc_state->stream; 4603 4383 struct dc_stream_update *stream_update = 4604 4384 kzalloc(sizeof(struct dc_stream_update), GFP_KERNEL); 4385 + unsigned int abm_level; 4605 4386 4606 4387 if (!stream_update) { 4607 4388 BREAK_TO_DEBUGGER(); ··· 4630 4409 stream_update->dst = dc_stream->dst; 4631 4410 stream_update->out_transfer_func = dc_stream->out_transfer_func; 4632 4411 4633 - if (dm_new_crtc_state->freesync_enabled != dm_old_crtc_state->freesync_enabled) { 4634 - stream_update->vrr_infopacket = &dc_stream->vrr_infopacket; 4635 - stream_update->adjust = &dc_stream->adjust; 4412 + if (dm_new_crtc_state->abm_level != dm_old_crtc_state->abm_level) { 4413 + abm_level = dm_new_crtc_state->abm_level; 4414 + stream_update->abm_level = &abm_level; 4636 4415 } 4637 4416 4638 4417 for (i = 0; i < new_plane_count; i++) { ··· 4676 4455 } 4677 4456 4678 4457 static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, 4458 + struct dc_state *dc_state, 4679 4459 struct drm_device *dev, 4680 4460 struct amdgpu_display_manager *dm, 4681 4461 struct drm_crtc *pcrtc, ··· 4693 4471 struct dm_crtc_state *acrtc_state = to_dm_crtc_state(new_pcrtc_state); 4694 4472 struct dm_crtc_state *dm_old_crtc_state = 4695 4473 to_dm_crtc_state(drm_atomic_get_old_crtc_state(state, pcrtc)); 4696 - struct dm_atomic_state *dm_state = to_dm_atomic_state(state); 4697 4474 int planes_count = 0; 4698 4475 unsigned long flags; 4699 4476 ··· 4753 4532 crtc, 4754 4533 fb, 4755 4534 (uint32_t)drm_crtc_vblank_count(crtc) + *wait_for_vblank, 4756 - dm_state->context); 4535 + dc_state); 4757 4536 } 4758 4537 4759 4538 } ··· 4770 4549 spin_unlock_irqrestore(&pcrtc->dev->event_lock, flags); 4771 4550 } 4772 4551 4773 - dc_stream_attach->adjust = acrtc_state->adjust; 4774 - dc_stream_attach->vrr_infopacket = acrtc_state->vrr_infopacket; 4552 + dc_stream_attach->abm_level = acrtc_state->abm_level; 4775 4553 4776 4554 if (false == commit_planes_to_stream(dm->dc, 4777 4555 plane_states_constructed, 4778 4556 planes_count, 4779 4557 acrtc_state, 4780 4558 dm_old_crtc_state, 4781 - dm_state->context)) 4559 + dc_state)) 4782 4560 dm_error("%s: Failed to attach plane!\n", __func__); 4783 4561 } else { 4784 4562 /*TODO BUG Here should go disable planes on CRTC. */ ··· 4845 4625 struct amdgpu_device *adev = dev->dev_private; 4846 4626 struct amdgpu_display_manager *dm = &adev->dm; 4847 4627 struct dm_atomic_state *dm_state; 4628 + struct dc_state *dc_state = NULL, *dc_state_temp = NULL; 4848 4629 uint32_t i, j; 4849 4630 struct drm_crtc *crtc; 4850 4631 struct drm_crtc_state *old_crtc_state, *new_crtc_state; ··· 4858 4637 4859 4638 drm_atomic_helper_update_legacy_modeset_state(dev, state); 4860 4639 4861 - dm_state = to_dm_atomic_state(state); 4640 + dm_state = dm_atomic_get_new_state(state); 4641 + if (dm_state && dm_state->context) { 4642 + dc_state = dm_state->context; 4643 + } else { 4644 + /* No state changes, retain current state. */ 4645 + dc_state_temp = dc_create_state(); 4646 + ASSERT(dc_state_temp); 4647 + dc_state = dc_state_temp; 4648 + dc_resource_state_copy_construct_current(dm->dc, dc_state); 4649 + } 4862 4650 4863 4651 /* update changed items */ 4864 4652 for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { ··· 4940 4710 } 4941 4711 } /* for_each_crtc_in_state() */ 4942 4712 4943 - if (dm_state->context) { 4944 - dm_enable_per_frame_crtc_master_sync(dm_state->context); 4945 - WARN_ON(!dc_commit_state(dm->dc, dm_state->context)); 4713 + if (dc_state) { 4714 + dm_enable_per_frame_crtc_master_sync(dc_state); 4715 + WARN_ON(!dc_commit_state(dm->dc, dc_state)); 4946 4716 } 4947 4717 4948 4718 for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) { ··· 4955 4725 dc_stream_get_status(dm_new_crtc_state->stream); 4956 4726 4957 4727 if (!status) 4728 + status = dc_state_get_stream_status(dc_state, 4729 + dm_new_crtc_state->stream); 4730 + 4731 + if (!status) 4958 4732 DC_ERR("got no status for stream %p on acrtc%p\n", dm_new_crtc_state->stream, acrtc); 4959 4733 else 4960 4734 acrtc->otg_inst = status->primary_otg_inst; 4961 4735 } 4962 4736 } 4963 4737 4964 - /* Handle scaling and underscan changes*/ 4738 + /* Handle scaling, underscan, and abm changes*/ 4965 4739 for_each_oldnew_connector_in_state(state, connector, old_con_state, new_con_state, i) { 4966 4740 struct dm_connector_state *dm_new_con_state = to_dm_connector_state(new_con_state); 4967 4741 struct dm_connector_state *dm_old_con_state = to_dm_connector_state(old_con_state); ··· 4981 4747 if (!acrtc || drm_atomic_crtc_needs_modeset(new_crtc_state)) 4982 4748 continue; 4983 4749 4984 - /* Skip anything that is not scaling or underscan changes */ 4985 - if (!is_scaling_state_different(dm_new_con_state, dm_old_con_state)) 4986 - continue; 4987 4750 4988 4751 dm_new_crtc_state = to_dm_crtc_state(new_crtc_state); 4752 + dm_old_crtc_state = to_dm_crtc_state(old_crtc_state); 4753 + 4754 + /* Skip anything that is not scaling or underscan changes */ 4755 + if (!is_scaling_state_different(dm_new_con_state, dm_old_con_state) && 4756 + (dm_new_crtc_state->abm_level == dm_old_crtc_state->abm_level)) 4757 + continue; 4989 4758 4990 4759 update_stream_scaling_settings(&dm_new_con_state->base.crtc->mode, 4991 4760 dm_new_con_state, (struct dc_stream_state *)dm_new_crtc_state->stream); ··· 5000 4763 WARN_ON(!status); 5001 4764 WARN_ON(!status->plane_count); 5002 4765 5003 - dm_new_crtc_state->stream->adjust = dm_new_crtc_state->adjust; 5004 - dm_new_crtc_state->stream->vrr_infopacket = dm_new_crtc_state->vrr_infopacket; 4766 + dm_new_crtc_state->stream->abm_level = dm_new_crtc_state->abm_level; 5005 4767 5006 4768 /*TODO How it works with MPO ?*/ 5007 4769 if (!commit_planes_to_stream( ··· 5009 4773 status->plane_count, 5010 4774 dm_new_crtc_state, 5011 4775 to_dm_crtc_state(old_crtc_state), 5012 - dm_state->context)) 4776 + dc_state)) 5013 4777 dm_error("%s: Failed to update stream scaling!\n", __func__); 5014 4778 } 5015 4779 ··· 5042 4806 dm_new_crtc_state = to_dm_crtc_state(new_crtc_state); 5043 4807 5044 4808 if (dm_new_crtc_state->stream) 5045 - amdgpu_dm_commit_planes(state, dev, dm, crtc, &wait_for_vblank); 4809 + amdgpu_dm_commit_planes(state, dc_state, dev, 4810 + dm, crtc, &wait_for_vblank); 5046 4811 } 5047 4812 5048 4813 ··· 5083 4846 for (i = 0; i < crtc_disable_count; i++) 5084 4847 pm_runtime_put_autosuspend(dev->dev); 5085 4848 pm_runtime_mark_last_busy(dev->dev); 4849 + 4850 + if (dc_state_temp) 4851 + dc_release_state(dc_state_temp); 5086 4852 } 5087 4853 5088 4854 ··· 5229 4989 return ret < 0 ? ret : 0; 5230 4990 } 5231 4991 5232 - void set_freesync_on_stream(struct amdgpu_display_manager *dm, 5233 - struct dm_crtc_state *new_crtc_state, 5234 - struct dm_connector_state *new_con_state, 5235 - struct dc_stream_state *new_stream) 4992 + static void get_freesync_config_for_crtc( 4993 + struct dm_crtc_state *new_crtc_state, 4994 + struct dm_connector_state *new_con_state) 5236 4995 { 5237 4996 struct mod_freesync_config config = {0}; 5238 - struct mod_vrr_params vrr = {0}; 5239 - struct dc_info_packet vrr_infopacket = {0}; 5240 4997 struct amdgpu_dm_connector *aconnector = 5241 4998 to_amdgpu_dm_connector(new_con_state->base.connector); 5242 4999 5243 - if (new_con_state->freesync_capable && 5244 - new_con_state->freesync_enable) { 5245 - config.state = new_crtc_state->freesync_enabled ? 5000 + new_crtc_state->vrr_supported = new_con_state->freesync_capable; 5001 + 5002 + if (new_con_state->freesync_capable) { 5003 + config.state = new_crtc_state->base.vrr_enabled ? 5246 5004 VRR_STATE_ACTIVE_VARIABLE : 5247 5005 VRR_STATE_INACTIVE; 5248 5006 config.min_refresh_in_uhz = ··· 5250 5012 config.vsif_supported = true; 5251 5013 } 5252 5014 5253 - mod_freesync_build_vrr_params(dm->freesync_module, 5254 - new_stream, 5255 - &config, &vrr); 5015 + new_crtc_state->freesync_config = config; 5016 + } 5256 5017 5257 - mod_freesync_build_vrr_infopacket(dm->freesync_module, 5258 - new_stream, 5259 - &vrr, 5260 - packet_type_fs1, 5261 - NULL, 5262 - &vrr_infopacket); 5018 + static void reset_freesync_config_for_crtc( 5019 + struct dm_crtc_state *new_crtc_state) 5020 + { 5021 + new_crtc_state->vrr_supported = false; 5263 5022 5264 - new_crtc_state->adjust = vrr.adjust; 5265 - new_crtc_state->vrr_infopacket = vrr_infopacket; 5023 + memset(&new_crtc_state->adjust, 0, 5024 + sizeof(new_crtc_state->adjust)); 5025 + memset(&new_crtc_state->vrr_infopacket, 0, 5026 + sizeof(new_crtc_state->vrr_infopacket)); 5266 5027 } 5267 5028 5268 5029 static int dm_update_crtcs_state(struct amdgpu_display_manager *dm, ··· 5269 5032 bool enable, 5270 5033 bool *lock_and_validation_needed) 5271 5034 { 5035 + struct dm_atomic_state *dm_state = NULL; 5272 5036 struct drm_crtc *crtc; 5273 5037 struct drm_crtc_state *old_crtc_state, *new_crtc_state; 5274 5038 int i; 5275 5039 struct dm_crtc_state *dm_old_crtc_state, *dm_new_crtc_state; 5276 - struct dm_atomic_state *dm_state = to_dm_atomic_state(state); 5277 5040 struct dc_stream_state *new_stream; 5278 5041 int ret = 0; 5279 5042 ··· 5321 5084 5322 5085 new_stream = create_stream_for_sink(aconnector, 5323 5086 &new_crtc_state->mode, 5324 - dm_new_conn_state); 5087 + dm_new_conn_state, 5088 + dm_old_crtc_state->stream); 5325 5089 5326 5090 /* 5327 5091 * we can have no stream on ACTION_SET if a display ··· 5337 5099 break; 5338 5100 } 5339 5101 5340 - set_freesync_on_stream(dm, dm_new_crtc_state, 5341 - dm_new_conn_state, new_stream); 5102 + dm_new_crtc_state->abm_level = dm_new_conn_state->abm_level; 5342 5103 5343 5104 if (dc_is_stream_unchanged(new_stream, dm_old_crtc_state->stream) && 5344 5105 dc_is_stream_scaling_unchanged(new_stream, dm_old_crtc_state->stream)) { ··· 5346 5109 new_crtc_state->mode_changed); 5347 5110 } 5348 5111 } 5349 - 5350 - if (dm_old_crtc_state->freesync_enabled != dm_new_crtc_state->freesync_enabled) 5351 - new_crtc_state->mode_changed = true; 5352 5112 5353 5113 if (!drm_atomic_crtc_needs_modeset(new_crtc_state)) 5354 5114 goto next_crtc; ··· 5368 5134 if (!dm_old_crtc_state->stream) 5369 5135 goto next_crtc; 5370 5136 5137 + ret = dm_atomic_get_state(state, &dm_state); 5138 + if (ret) 5139 + goto fail; 5140 + 5371 5141 DRM_DEBUG_DRIVER("Disabling DRM crtc: %d\n", 5372 5142 crtc->base.id); 5373 5143 ··· 5386 5148 5387 5149 dc_stream_release(dm_old_crtc_state->stream); 5388 5150 dm_new_crtc_state->stream = NULL; 5151 + 5152 + reset_freesync_config_for_crtc(dm_new_crtc_state); 5389 5153 5390 5154 *lock_and_validation_needed = true; 5391 5155 ··· 5407 5167 dm_old_crtc_state->stream)) { 5408 5168 5409 5169 WARN_ON(dm_new_crtc_state->stream); 5170 + 5171 + ret = dm_atomic_get_state(state, &dm_state); 5172 + if (ret) 5173 + goto fail; 5410 5174 5411 5175 dm_new_crtc_state->stream = new_stream; 5412 5176 ··· 5470 5226 amdgpu_dm_set_ctm(dm_new_crtc_state); 5471 5227 } 5472 5228 5473 - 5229 + /* Update Freesync settings. */ 5230 + get_freesync_config_for_crtc(dm_new_crtc_state, 5231 + dm_new_conn_state); 5474 5232 } 5475 5233 5476 5234 return ret; ··· 5488 5242 bool enable, 5489 5243 bool *lock_and_validation_needed) 5490 5244 { 5245 + 5246 + struct dm_atomic_state *dm_state = NULL; 5491 5247 struct drm_crtc *new_plane_crtc, *old_plane_crtc; 5492 5248 struct drm_crtc_state *old_crtc_state, *new_crtc_state; 5493 5249 struct drm_plane *plane; 5494 5250 struct drm_plane_state *old_plane_state, *new_plane_state; 5495 5251 struct dm_crtc_state *dm_new_crtc_state, *dm_old_crtc_state; 5496 - struct dm_atomic_state *dm_state = to_dm_atomic_state(state); 5497 5252 struct dm_plane_state *dm_new_plane_state, *dm_old_plane_state; 5498 5253 int i ; 5499 5254 /* TODO return page_flip_needed() function */ ··· 5531 5284 5532 5285 DRM_DEBUG_ATOMIC("Disabling DRM plane: %d on DRM crtc %d\n", 5533 5286 plane->base.id, old_plane_crtc->base.id); 5287 + 5288 + ret = dm_atomic_get_state(state, &dm_state); 5289 + if (ret) 5290 + return ret; 5534 5291 5535 5292 if (!dc_remove_plane_from_context( 5536 5293 dc, ··· 5590 5339 return ret; 5591 5340 } 5592 5341 5342 + ret = dm_atomic_get_state(state, &dm_state); 5343 + if (ret) { 5344 + dc_plane_state_release(dc_new_plane_state); 5345 + return ret; 5346 + } 5347 + 5593 5348 /* 5594 5349 * Any atomic check errors that occur after this will 5595 5350 * not need a release. The plane state will be attached ··· 5627 5370 5628 5371 return ret; 5629 5372 } 5630 - enum surface_update_type dm_determine_update_type_for_commit(struct dc *dc, struct drm_atomic_state *state) 5373 + 5374 + static int 5375 + dm_determine_update_type_for_commit(struct dc *dc, 5376 + struct drm_atomic_state *state, 5377 + enum surface_update_type *out_type) 5631 5378 { 5632 - 5633 - 5634 - int i, j, num_plane; 5379 + struct dm_atomic_state *dm_state = NULL, *old_dm_state = NULL; 5380 + int i, j, num_plane, ret = 0; 5635 5381 struct drm_plane_state *old_plane_state, *new_plane_state; 5636 5382 struct dm_plane_state *new_dm_plane_state, *old_dm_plane_state; 5637 5383 struct drm_crtc *new_plane_crtc, *old_plane_crtc; ··· 5654 5394 DRM_ERROR("Plane or surface update failed to allocate"); 5655 5395 /* Set type to FULL to avoid crashing in DC*/ 5656 5396 update_type = UPDATE_TYPE_FULL; 5657 - goto ret; 5397 + goto cleanup; 5658 5398 } 5659 5399 5660 5400 for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { ··· 5708 5448 } 5709 5449 5710 5450 if (num_plane > 0) { 5711 - status = dc_stream_get_status(new_dm_crtc_state->stream); 5451 + ret = dm_atomic_get_state(state, &dm_state); 5452 + if (ret) 5453 + goto cleanup; 5454 + 5455 + old_dm_state = dm_atomic_get_old_state(state); 5456 + if (!old_dm_state) { 5457 + ret = -EINVAL; 5458 + goto cleanup; 5459 + } 5460 + 5461 + status = dc_state_get_stream_status(old_dm_state->context, 5462 + new_dm_crtc_state->stream); 5463 + 5712 5464 update_type = dc_check_update_surfaces_for_stream(dc, updates, num_plane, 5713 5465 &stream_update, status); 5714 5466 5715 5467 if (update_type > UPDATE_TYPE_MED) { 5716 5468 update_type = UPDATE_TYPE_FULL; 5717 - goto ret; 5469 + goto cleanup; 5718 5470 } 5719 5471 } 5720 5472 5721 5473 } else if (!new_dm_crtc_state->stream && old_dm_crtc_state->stream) { 5722 5474 update_type = UPDATE_TYPE_FULL; 5723 - goto ret; 5475 + goto cleanup; 5724 5476 } 5725 5477 } 5726 5478 5727 - ret: 5479 + cleanup: 5728 5480 kfree(updates); 5729 5481 kfree(surface); 5730 5482 5731 - return update_type; 5483 + *out_type = update_type; 5484 + return ret; 5732 5485 } 5733 5486 5734 5487 /** ··· 5773 5500 struct drm_atomic_state *state) 5774 5501 { 5775 5502 struct amdgpu_device *adev = dev->dev_private; 5503 + struct dm_atomic_state *dm_state = NULL; 5776 5504 struct dc *dc = adev->dm.dc; 5777 - struct dm_atomic_state *dm_state = to_dm_atomic_state(state); 5778 5505 struct drm_connector *connector; 5779 5506 struct drm_connector_state *old_con_state, *new_con_state; 5780 5507 struct drm_crtc *crtc; ··· 5795 5522 goto fail; 5796 5523 5797 5524 for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { 5798 - struct dm_crtc_state *dm_new_crtc_state = to_dm_crtc_state(new_crtc_state); 5799 - struct dm_crtc_state *dm_old_crtc_state = to_dm_crtc_state(old_crtc_state); 5800 - 5801 5525 if (!drm_atomic_crtc_needs_modeset(new_crtc_state) && 5802 5526 !new_crtc_state->color_mgmt_changed && 5803 - (dm_old_crtc_state->freesync_enabled == dm_new_crtc_state->freesync_enabled)) 5527 + !new_crtc_state->vrr_enabled) 5804 5528 continue; 5805 5529 5806 5530 if (!new_crtc_state->enable) ··· 5811 5541 if (ret) 5812 5542 goto fail; 5813 5543 } 5814 - 5815 - dm_state->context = dc_create_state(); 5816 - ASSERT(dm_state->context); 5817 - dc_resource_state_copy_construct_current(dc, dm_state->context); 5818 5544 5819 5545 /* Remove exiting planes if they are modified */ 5820 5546 ret = dm_update_planes_state(dc, state, false, &lock_and_validation_needed); ··· 5864 5598 lock_and_validation_needed = true; 5865 5599 } 5866 5600 5867 - update_type = dm_determine_update_type_for_commit(dc, state); 5601 + ret = dm_determine_update_type_for_commit(dc, state, &update_type); 5602 + if (ret) 5603 + goto fail; 5868 5604 5869 5605 if (overall_update_type < update_type) 5870 5606 overall_update_type = update_type; ··· 5884 5616 5885 5617 5886 5618 if (overall_update_type > UPDATE_TYPE_FAST) { 5619 + ret = dm_atomic_get_state(state, &dm_state); 5620 + if (ret) 5621 + goto fail; 5887 5622 5888 5623 ret = do_aquire_global_lock(dev, state); 5889 5624 if (ret) ··· 5941 5670 struct detailed_data_monitor_range *range; 5942 5671 struct amdgpu_dm_connector *amdgpu_dm_connector = 5943 5672 to_amdgpu_dm_connector(connector); 5944 - struct dm_connector_state *dm_con_state; 5673 + struct dm_connector_state *dm_con_state = NULL; 5945 5674 5946 5675 struct drm_device *dev = connector->dev; 5947 5676 struct amdgpu_device *adev = dev->dev_private; 5677 + bool freesync_capable = false; 5948 5678 5949 5679 if (!connector->state) { 5950 5680 DRM_ERROR("%s - Connector has no state", __func__); 5951 - return; 5681 + goto update; 5952 5682 } 5953 5683 5954 5684 if (!edid) { ··· 5959 5687 amdgpu_dm_connector->max_vfreq = 0; 5960 5688 amdgpu_dm_connector->pixel_clock_mhz = 0; 5961 5689 5962 - dm_con_state->freesync_capable = false; 5963 - dm_con_state->freesync_enable = false; 5964 - return; 5690 + goto update; 5965 5691 } 5966 5692 5967 5693 dm_con_state = to_dm_connector_state(connector->state); ··· 5967 5697 edid_check_required = false; 5968 5698 if (!amdgpu_dm_connector->dc_sink) { 5969 5699 DRM_ERROR("dc_sink NULL, could not add free_sync module.\n"); 5970 - return; 5700 + goto update; 5971 5701 } 5972 5702 if (!adev->dm.freesync_module) 5973 - return; 5703 + goto update; 5974 5704 /* 5975 5705 * if edid non zero restrict freesync only for dp and edp 5976 5706 */ ··· 5982 5712 amdgpu_dm_connector); 5983 5713 } 5984 5714 } 5985 - dm_con_state->freesync_capable = false; 5986 5715 if (edid_check_required == true && (edid->version > 1 || 5987 5716 (edid->version == 1 && edid->revision > 1))) { 5988 5717 for (i = 0; i < 4; i++) { ··· 6013 5744 if (amdgpu_dm_connector->max_vfreq - 6014 5745 amdgpu_dm_connector->min_vfreq > 10) { 6015 5746 6016 - dm_con_state->freesync_capable = true; 5747 + freesync_capable = true; 6017 5748 } 6018 5749 } 5750 + 5751 + update: 5752 + if (dm_con_state) 5753 + dm_con_state->freesync_capable = freesync_capable; 5754 + 5755 + if (connector->vrr_capable_property) 5756 + drm_connector_set_vrr_capable_property(connector, 5757 + freesync_capable); 6019 5758 } 6020 5759
+33 -3
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
··· 84 84 }; 85 85 86 86 /** 87 + * struct amdgpu_dm_backlight_caps - Usable range of backlight values from ACPI 88 + * @min_input_signal: minimum possible input in range 0-255 89 + * @max_input_signal: maximum possible input in range 0-255 90 + * @caps_valid: true if these values are from the ACPI interface 91 + */ 92 + struct amdgpu_dm_backlight_caps { 93 + int min_input_signal; 94 + int max_input_signal; 95 + bool caps_valid; 96 + }; 97 + 98 + /** 87 99 * struct amdgpu_display_manager - Central amdgpu display manager device 88 100 * 89 101 * @dc: Display Core control structure ··· 122 110 struct amdgpu_device *adev; 123 111 struct drm_device *ddev; 124 112 u16 display_indexes_num; 113 + 114 + /** 115 + * @atomic_obj 116 + * 117 + * In combination with &dm_atomic_state it helps manage 118 + * global atomic state that doesn't map cleanly into existing 119 + * drm resources, like &dc_context. 120 + */ 121 + struct drm_private_obj atomic_obj; 122 + 123 + struct drm_modeset_lock atomic_obj_lock; 125 124 126 125 /** 127 126 * @irq_handler_list_low_tab: ··· 181 158 struct backlight_device *backlight_dev; 182 159 183 160 const struct dc_link *backlight_link; 161 + struct amdgpu_dm_backlight_caps backlight_caps; 184 162 185 163 struct mod_freesync *freesync_module; 186 164 ··· 255 231 int crc_skip_count; 256 232 bool crc_enabled; 257 233 258 - bool freesync_enabled; 234 + bool freesync_timing_changed; 235 + bool freesync_vrr_info_changed; 236 + 237 + bool vrr_supported; 238 + struct mod_freesync_config freesync_config; 259 239 struct dc_crtc_timing_adjust adjust; 260 240 struct dc_info_packet vrr_infopacket; 241 + 242 + int abm_level; 261 243 }; 262 244 263 245 #define to_dm_crtc_state(x) container_of(x, struct dm_crtc_state, base) 264 246 265 247 struct dm_atomic_state { 266 - struct drm_atomic_state base; 248 + struct drm_private_state base; 267 249 268 250 struct dc_state *context; 269 251 }; ··· 284 254 uint8_t underscan_hborder; 285 255 uint8_t max_bpc; 286 256 bool underscan_enable; 287 - bool freesync_enable; 288 257 bool freesync_capable; 258 + uint8_t abm_level; 289 259 }; 290 260 291 261 #define to_dm_connector_state(x)\
+10 -1
drivers/gpu/drm/amd/display/dc/core/dc.c
··· 328 328 enum dc_dither_option option) 329 329 { 330 330 struct bit_depth_reduction_params params; 331 - struct dc_link *link = stream->status.link; 331 + struct dc_link *link = stream->sink->link; 332 332 struct pipe_ctx *pipes = NULL; 333 333 int i; 334 334 ··· 1684 1684 1685 1685 for (i = 0; i < dc->link_count; i++) 1686 1686 core_link_resume(dc->links[i]); 1687 + } 1688 + 1689 + bool dc_is_dmcu_initialized(struct dc *dc) 1690 + { 1691 + struct dmcu *dmcu = dc->res_pool->dmcu; 1692 + 1693 + if (dmcu) 1694 + return dmcu->funcs->is_dmcu_initialized(dmcu); 1695 + return false; 1687 1696 } 1688 1697 1689 1698 bool dc_submit_i2c(
+8 -7
drivers/gpu/drm/amd/display/dc/core/dc_link.c
··· 1396 1396 else 1397 1397 status = DC_FAIL_DP_LINK_TRAINING; 1398 1398 1399 - enable_stream_features(pipe_ctx); 1400 - 1401 1399 return status; 1402 1400 } 1403 1401 ··· 2173 2175 backlight_pwm_u16_16, backlight_pwm_u16_16); 2174 2176 2175 2177 if (dc_is_embedded_signal(link->connector_signal)) { 2176 - if (stream != NULL) { 2177 - for (i = 0; i < MAX_PIPES; i++) { 2178 + for (i = 0; i < MAX_PIPES; i++) { 2179 + if (core_dc->current_state->res_ctx.pipe_ctx[i].stream) { 2178 2180 if (core_dc->current_state->res_ctx. 2179 - pipe_ctx[i].stream 2180 - == stream) 2181 + pipe_ctx[i].stream->sink->link 2182 + == link) 2181 2183 /* DMCU -1 for all controller id values, 2182 2184 * therefore +1 here 2183 2185 */ ··· 2216 2218 struct dc *core_dc = link->ctx->dc; 2217 2219 struct dmcu *dmcu = core_dc->res_pool->dmcu; 2218 2220 2219 - if (dmcu != NULL && link->psr_enabled) 2221 + if ((dmcu != NULL && dmcu->funcs->is_dmcu_initialized(dmcu)) && link->psr_enabled) 2220 2222 dmcu->funcs->set_psr_enable(dmcu, enable, wait); 2221 2223 2222 2224 return true; ··· 2591 2593 2592 2594 core_dc->hwss.unblank_stream(pipe_ctx, 2593 2595 &pipe_ctx->stream->sink->link->cur_link_settings); 2596 + 2597 + if (dc_is_dp_signal(pipe_ctx->stream->signal)) 2598 + enable_stream_features(pipe_ctx); 2594 2599 2595 2600 dc_link_set_backlight_level(pipe_ctx->stream->sink->link, 2596 2601 pipe_ctx->stream->bl_pwm_level,
+255 -428
drivers/gpu/drm/amd/display/dc/core/dc_resource.c
··· 478 478 return dal_pixel_format; 479 479 } 480 480 481 - static void rect_swap_helper(struct rect *rect) 481 + static inline void get_vp_scan_direction( 482 + enum dc_rotation_angle rotation, 483 + bool horizontal_mirror, 484 + bool *orthogonal_rotation, 485 + bool *flip_vert_scan_dir, 486 + bool *flip_horz_scan_dir) 482 487 { 483 - swap(rect->height, rect->width); 484 - swap(rect->x, rect->y); 488 + *orthogonal_rotation = false; 489 + *flip_vert_scan_dir = false; 490 + *flip_horz_scan_dir = false; 491 + if (rotation == ROTATION_ANGLE_180) { 492 + *flip_vert_scan_dir = true; 493 + *flip_horz_scan_dir = true; 494 + } else if (rotation == ROTATION_ANGLE_90) { 495 + *orthogonal_rotation = true; 496 + *flip_horz_scan_dir = true; 497 + } else if (rotation == ROTATION_ANGLE_270) { 498 + *orthogonal_rotation = true; 499 + *flip_vert_scan_dir = true; 500 + } 501 + 502 + if (horizontal_mirror) 503 + *flip_horz_scan_dir = !*flip_horz_scan_dir; 485 504 } 486 505 487 506 static void calculate_viewport(struct pipe_ctx *pipe_ctx) ··· 509 490 const struct dc_stream_state *stream = pipe_ctx->stream; 510 491 struct scaler_data *data = &pipe_ctx->plane_res.scl_data; 511 492 struct rect surf_src = plane_state->src_rect; 512 - struct rect clip = { 0 }; 493 + struct rect clip, dest; 513 494 int vpc_div = (data->format == PIXEL_FORMAT_420BPP8 514 495 || data->format == PIXEL_FORMAT_420BPP10) ? 2 : 1; 515 496 bool pri_split = pipe_ctx->bottom_pipe && 516 497 pipe_ctx->bottom_pipe->plane_state == pipe_ctx->plane_state; 517 498 bool sec_split = pipe_ctx->top_pipe && 518 499 pipe_ctx->top_pipe->plane_state == pipe_ctx->plane_state; 519 - bool flip_vert_scan_dir = false, flip_horz_scan_dir = false; 520 - 521 - 522 - /* 523 - * We need take horizontal mirror into account. On an unrotated surface this means 524 - * that the viewport offset is actually the offset from the other side of source 525 - * image so we have to subtract the right edge of the viewport from the right edge of 526 - * the source window. Similar to mirror we need to take into account how offset is 527 - * affected for 270/180 rotations 528 - */ 529 - if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_180) { 530 - flip_vert_scan_dir = true; 531 - flip_horz_scan_dir = true; 532 - } else if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90) 533 - flip_vert_scan_dir = true; 534 - else if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270) 535 - flip_horz_scan_dir = true; 536 - 537 - if (pipe_ctx->plane_state->horizontal_mirror) 538 - flip_horz_scan_dir = !flip_horz_scan_dir; 500 + bool orthogonal_rotation, flip_y_start, flip_x_start; 539 501 540 502 if (stream->view_format == VIEW_3D_FORMAT_SIDE_BY_SIDE || 541 503 stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) { ··· 524 524 sec_split = false; 525 525 } 526 526 527 - if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90 || 528 - pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270) 529 - rect_swap_helper(&surf_src); 530 - 531 527 /* The actual clip is an intersection between stream 532 528 * source and surface clip 533 529 */ 530 + dest = plane_state->dst_rect; 534 531 clip.x = stream->src.x > plane_state->clip_rect.x ? 535 532 stream->src.x : plane_state->clip_rect.x; 536 533 ··· 544 547 stream->src.y + stream->src.height - clip.y : 545 548 plane_state->clip_rect.y + plane_state->clip_rect.height - clip.y ; 546 549 550 + /* 551 + * Need to calculate how scan origin is shifted in vp space 552 + * to correctly rotate clip and dst 553 + */ 554 + get_vp_scan_direction( 555 + plane_state->rotation, 556 + plane_state->horizontal_mirror, 557 + &orthogonal_rotation, 558 + &flip_y_start, 559 + &flip_x_start); 560 + 561 + if (orthogonal_rotation) { 562 + swap(clip.x, clip.y); 563 + swap(clip.width, clip.height); 564 + swap(dest.x, dest.y); 565 + swap(dest.width, dest.height); 566 + } 567 + if (flip_x_start) { 568 + clip.x = dest.x + dest.width - clip.x - clip.width; 569 + dest.x = 0; 570 + } 571 + if (flip_y_start) { 572 + clip.y = dest.y + dest.height - clip.y - clip.height; 573 + dest.y = 0; 574 + } 575 + 547 576 /* offset = surf_src.ofs + (clip.ofs - surface->dst_rect.ofs) * scl_ratio 548 - * note: surf_src.ofs should be added after rotation/mirror offset direction 549 - * adjustment since it is already in viewport space 550 577 * num_pixels = clip.num_pix * scl_ratio 551 578 */ 552 - data->viewport.x = (clip.x - plane_state->dst_rect.x) * 553 - surf_src.width / plane_state->dst_rect.width; 554 - data->viewport.width = clip.width * 555 - surf_src.width / plane_state->dst_rect.width; 579 + data->viewport.x = surf_src.x + (clip.x - dest.x) * surf_src.width / dest.width; 580 + data->viewport.width = clip.width * surf_src.width / dest.width; 556 581 557 - data->viewport.y = (clip.y - plane_state->dst_rect.y) * 558 - surf_src.height / plane_state->dst_rect.height; 559 - data->viewport.height = clip.height * 560 - surf_src.height / plane_state->dst_rect.height; 582 + data->viewport.y = surf_src.y + (clip.y - dest.y) * surf_src.height / dest.height; 583 + data->viewport.height = clip.height * surf_src.height / dest.height; 561 584 562 - if (flip_vert_scan_dir) 563 - data->viewport.y = surf_src.height - data->viewport.y - data->viewport.height; 564 - if (flip_horz_scan_dir) 565 - data->viewport.x = surf_src.width - data->viewport.x - data->viewport.width; 566 - 567 - data->viewport.x += surf_src.x; 568 - data->viewport.y += surf_src.y; 585 + /* Handle split */ 586 + if (pri_split || sec_split) { 587 + if (orthogonal_rotation) { 588 + if (flip_y_start != pri_split) 589 + data->viewport.height /= 2; 590 + else { 591 + data->viewport.y += data->viewport.height / 2; 592 + /* Ceil offset pipe */ 593 + data->viewport.height = (data->viewport.height + 1) / 2; 594 + } 595 + } else { 596 + if (flip_x_start != pri_split) 597 + data->viewport.width /= 2; 598 + else { 599 + data->viewport.x += data->viewport.width / 2; 600 + /* Ceil offset pipe */ 601 + data->viewport.width = (data->viewport.width + 1) / 2; 602 + } 603 + } 604 + } 569 605 570 606 /* Round down, compensate in init */ 571 607 data->viewport_c.x = data->viewport.x / vpc_div; 572 608 data->viewport_c.y = data->viewport.y / vpc_div; 573 - data->inits.h_c = (data->viewport.x % vpc_div) != 0 ? 574 - dc_fixpt_half : dc_fixpt_zero; 575 - data->inits.v_c = (data->viewport.y % vpc_div) != 0 ? 576 - dc_fixpt_half : dc_fixpt_zero; 609 + data->inits.h_c = (data->viewport.x % vpc_div) != 0 ? dc_fixpt_half : dc_fixpt_zero; 610 + data->inits.v_c = (data->viewport.y % vpc_div) != 0 ? dc_fixpt_half : dc_fixpt_zero; 611 + 577 612 /* Round up, assume original video size always even dimensions */ 578 613 data->viewport_c.width = (data->viewport.width + vpc_div - 1) / vpc_div; 579 614 data->viewport_c.height = (data->viewport.height + vpc_div - 1) / vpc_div; 580 - 581 - /* Handle hsplit */ 582 - if (sec_split) { 583 - data->viewport.x += data->viewport.width / 2; 584 - data->viewport_c.x += data->viewport_c.width / 2; 585 - /* Ceil offset pipe */ 586 - data->viewport.width = (data->viewport.width + 1) / 2; 587 - data->viewport_c.width = (data->viewport_c.width + 1) / 2; 588 - } else if (pri_split) { 589 - if (data->viewport.width > 1) 590 - data->viewport.width /= 2; 591 - if (data->viewport_c.width > 1) 592 - data->viewport_c.width /= 2; 593 - } 594 - 595 - if (plane_state->rotation == ROTATION_ANGLE_90 || 596 - plane_state->rotation == ROTATION_ANGLE_270) { 597 - rect_swap_helper(&data->viewport_c); 598 - rect_swap_helper(&data->viewport); 599 - } 600 615 } 601 616 602 - static void calculate_recout(struct pipe_ctx *pipe_ctx, struct rect *recout_full) 617 + static void calculate_recout(struct pipe_ctx *pipe_ctx) 603 618 { 604 619 const struct dc_plane_state *plane_state = pipe_ctx->plane_state; 605 620 const struct dc_stream_state *stream = pipe_ctx->stream; 606 - struct rect surf_src = plane_state->src_rect; 607 621 struct rect surf_clip = plane_state->clip_rect; 608 622 bool pri_split = pipe_ctx->bottom_pipe && 609 623 pipe_ctx->bottom_pipe->plane_state == pipe_ctx->plane_state; 610 624 bool sec_split = pipe_ctx->top_pipe && 611 625 pipe_ctx->top_pipe->plane_state == pipe_ctx->plane_state; 612 626 bool top_bottom_split = stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM; 613 - 614 - if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90 || 615 - pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270) 616 - rect_swap_helper(&surf_src); 617 627 618 628 pipe_ctx->plane_res.scl_data.recout.x = stream->dst.x; 619 629 if (stream->src.x < surf_clip.x) ··· 650 646 stream->dst.y + stream->dst.height 651 647 - pipe_ctx->plane_res.scl_data.recout.y; 652 648 653 - /* Handle h & vsplit */ 649 + /* Handle h & v split, handle rotation using viewport */ 654 650 if (sec_split && top_bottom_split) { 655 651 pipe_ctx->plane_res.scl_data.recout.y += 656 652 pipe_ctx->plane_res.scl_data.recout.height / 2; ··· 659 655 (pipe_ctx->plane_res.scl_data.recout.height + 1) / 2; 660 656 } else if (pri_split && top_bottom_split) 661 657 pipe_ctx->plane_res.scl_data.recout.height /= 2; 662 - else if (pri_split || sec_split) { 663 - /* HMirror XOR Secondary_pipe XOR Rotation_180 */ 664 - bool right_view = (sec_split != plane_state->horizontal_mirror) != 665 - (plane_state->rotation == ROTATION_ANGLE_180); 666 - 667 - if (plane_state->rotation == ROTATION_ANGLE_90 668 - || plane_state->rotation == ROTATION_ANGLE_270) 669 - /* Secondary_pipe XOR Rotation_270 */ 670 - right_view = (plane_state->rotation == ROTATION_ANGLE_270) != sec_split; 671 - 672 - if (right_view) { 673 - pipe_ctx->plane_res.scl_data.recout.x += 674 - pipe_ctx->plane_res.scl_data.recout.width / 2; 675 - /* Ceil offset pipe */ 676 - pipe_ctx->plane_res.scl_data.recout.width = 677 - (pipe_ctx->plane_res.scl_data.recout.width + 1) / 2; 678 - } else { 679 - if (pipe_ctx->plane_res.scl_data.recout.width > 1) 680 - pipe_ctx->plane_res.scl_data.recout.width /= 2; 681 - } 682 - } 683 - /* Unclipped recout offset = stream dst offset + ((surf dst offset - stream surf_src offset) 684 - * * 1/ stream scaling ratio) - (surf surf_src offset * 1/ full scl 685 - * ratio) 686 - */ 687 - recout_full->x = stream->dst.x + (plane_state->dst_rect.x - stream->src.x) 688 - * stream->dst.width / stream->src.width - 689 - surf_src.x * plane_state->dst_rect.width / surf_src.width 690 - * stream->dst.width / stream->src.width; 691 - recout_full->y = stream->dst.y + (plane_state->dst_rect.y - stream->src.y) 692 - * stream->dst.height / stream->src.height - 693 - surf_src.y * plane_state->dst_rect.height / surf_src.height 694 - * stream->dst.height / stream->src.height; 695 - 696 - recout_full->width = plane_state->dst_rect.width 697 - * stream->dst.width / stream->src.width; 698 - recout_full->height = plane_state->dst_rect.height 699 - * stream->dst.height / stream->src.height; 658 + else if (sec_split) { 659 + pipe_ctx->plane_res.scl_data.recout.x += 660 + pipe_ctx->plane_res.scl_data.recout.width / 2; 661 + /* Ceil offset pipe */ 662 + pipe_ctx->plane_res.scl_data.recout.width = 663 + (pipe_ctx->plane_res.scl_data.recout.width + 1) / 2; 664 + } else if (pri_split) 665 + pipe_ctx->plane_res.scl_data.recout.width /= 2; 700 666 } 701 667 702 668 static void calculate_scaling_ratios(struct pipe_ctx *pipe_ctx) ··· 679 705 const int out_w = stream->dst.width; 680 706 const int out_h = stream->dst.height; 681 707 708 + /*Swap surf_src height and width since scaling ratios are in recout rotation*/ 682 709 if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90 || 683 710 pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270) 684 - rect_swap_helper(&surf_src); 711 + swap(surf_src.height, surf_src.width); 685 712 686 713 pipe_ctx->plane_res.scl_data.ratios.horz = dc_fixpt_from_fraction( 687 714 surf_src.width, ··· 719 744 pipe_ctx->plane_res.scl_data.ratios.vert_c, 19); 720 745 } 721 746 722 - static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx, struct rect *recout_full) 747 + static inline void adjust_vp_and_init_for_seamless_clip( 748 + bool flip_scan_dir, 749 + int recout_skip, 750 + int src_size, 751 + int taps, 752 + struct fixed31_32 ratio, 753 + struct fixed31_32 *init, 754 + int *vp_offset, 755 + int *vp_size) 723 756 { 757 + if (!flip_scan_dir) { 758 + /* Adjust for viewport end clip-off */ 759 + if ((*vp_offset + *vp_size) < src_size) { 760 + int vp_clip = src_size - *vp_size - *vp_offset; 761 + int int_part = dc_fixpt_floor(dc_fixpt_sub(*init, ratio)); 762 + 763 + int_part = int_part > 0 ? int_part : 0; 764 + *vp_size += int_part < vp_clip ? int_part : vp_clip; 765 + } 766 + 767 + /* Adjust for non-0 viewport offset */ 768 + if (*vp_offset) { 769 + int int_part; 770 + 771 + *init = dc_fixpt_add(*init, dc_fixpt_mul_int(ratio, recout_skip)); 772 + int_part = dc_fixpt_floor(*init) - *vp_offset; 773 + if (int_part < taps) { 774 + int int_adj = *vp_offset >= (taps - int_part) ? 775 + (taps - int_part) : *vp_offset; 776 + *vp_offset -= int_adj; 777 + *vp_size += int_adj; 778 + int_part += int_adj; 779 + } else if (int_part > taps) { 780 + *vp_offset += int_part - taps; 781 + *vp_size -= int_part - taps; 782 + int_part = taps; 783 + } 784 + init->value &= 0xffffffff; 785 + *init = dc_fixpt_add_int(*init, int_part); 786 + } 787 + } else { 788 + /* Adjust for non-0 viewport offset */ 789 + if (*vp_offset) { 790 + int int_part = dc_fixpt_floor(dc_fixpt_sub(*init, ratio)); 791 + 792 + int_part = int_part > 0 ? int_part : 0; 793 + *vp_size += int_part < *vp_offset ? int_part : *vp_offset; 794 + *vp_offset -= int_part < *vp_offset ? int_part : *vp_offset; 795 + } 796 + 797 + /* Adjust for viewport end clip-off */ 798 + if ((*vp_offset + *vp_size) < src_size) { 799 + int int_part; 800 + int end_offset = src_size - *vp_offset - *vp_size; 801 + 802 + /* 803 + * this is init if vp had no offset, keep in mind this is from the 804 + * right side of vp due to scan direction 805 + */ 806 + *init = dc_fixpt_add(*init, dc_fixpt_mul_int(ratio, recout_skip)); 807 + /* 808 + * this is the difference between first pixel of viewport available to read 809 + * and init position, takning into account scan direction 810 + */ 811 + int_part = dc_fixpt_floor(*init) - end_offset; 812 + if (int_part < taps) { 813 + int int_adj = end_offset >= (taps - int_part) ? 814 + (taps - int_part) : end_offset; 815 + *vp_size += int_adj; 816 + int_part += int_adj; 817 + } else if (int_part > taps) { 818 + *vp_size += int_part - taps; 819 + int_part = taps; 820 + } 821 + init->value &= 0xffffffff; 822 + *init = dc_fixpt_add_int(*init, int_part); 823 + } 824 + } 825 + } 826 + 827 + static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx) 828 + { 829 + const struct dc_plane_state *plane_state = pipe_ctx->plane_state; 830 + const struct dc_stream_state *stream = pipe_ctx->stream; 724 831 struct scaler_data *data = &pipe_ctx->plane_res.scl_data; 725 832 struct rect src = pipe_ctx->plane_state->src_rect; 833 + int recout_skip_h, recout_skip_v, surf_size_h, surf_size_v; 726 834 int vpc_div = (data->format == PIXEL_FORMAT_420BPP8 727 835 || data->format == PIXEL_FORMAT_420BPP10) ? 2 : 1; 728 - bool flip_vert_scan_dir = false, flip_horz_scan_dir = false; 836 + bool orthogonal_rotation, flip_vert_scan_dir, flip_horz_scan_dir; 729 837 730 838 /* 731 839 * Need to calculate the scan direction for viewport to make adjustments 732 840 */ 733 - if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_180) { 734 - flip_vert_scan_dir = true; 735 - flip_horz_scan_dir = true; 736 - } else if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90) 737 - flip_vert_scan_dir = true; 738 - else if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270) 739 - flip_horz_scan_dir = true; 841 + get_vp_scan_direction( 842 + plane_state->rotation, 843 + plane_state->horizontal_mirror, 844 + &orthogonal_rotation, 845 + &flip_vert_scan_dir, 846 + &flip_horz_scan_dir); 740 847 741 - if (pipe_ctx->plane_state->horizontal_mirror) 742 - flip_horz_scan_dir = !flip_horz_scan_dir; 743 - 744 - if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90 || 745 - pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270) { 746 - rect_swap_helper(&src); 747 - rect_swap_helper(&data->viewport_c); 748 - rect_swap_helper(&data->viewport); 848 + /* Calculate src rect rotation adjusted to recout space */ 849 + surf_size_h = src.x + src.width; 850 + surf_size_v = src.y + src.height; 851 + if (flip_horz_scan_dir) 852 + src.x = 0; 853 + if (flip_vert_scan_dir) 854 + src.y = 0; 855 + if (orthogonal_rotation) { 856 + swap(src.x, src.y); 857 + swap(src.width, src.height); 749 858 } 750 859 860 + /* Recout matching initial vp offset = recout_offset - (stream dst offset + 861 + * ((surf dst offset - stream src offset) * 1/ stream scaling ratio) 862 + * - (surf surf_src offset * 1/ full scl ratio)) 863 + */ 864 + recout_skip_h = data->recout.x - (stream->dst.x + (plane_state->dst_rect.x - stream->src.x) 865 + * stream->dst.width / stream->src.width - 866 + src.x * plane_state->dst_rect.width / src.width 867 + * stream->dst.width / stream->src.width); 868 + recout_skip_v = data->recout.y - (stream->dst.y + (plane_state->dst_rect.y - stream->src.y) 869 + * stream->dst.height / stream->src.height - 870 + src.y * plane_state->dst_rect.height / src.height 871 + * stream->dst.height / stream->src.height); 872 + if (orthogonal_rotation) 873 + swap(recout_skip_h, recout_skip_v); 751 874 /* 752 875 * Init calculated according to formula: 753 876 * init = (scaling_ratio + number_of_taps + 1) / 2 ··· 864 791 data->inits.v_c = dc_fixpt_truncate(dc_fixpt_add(data->inits.v_c, dc_fixpt_div_int( 865 792 dc_fixpt_add_int(data->ratios.vert_c, data->taps.v_taps_c + 1), 2)), 19); 866 793 867 - if (!flip_horz_scan_dir) { 868 - /* Adjust for viewport end clip-off */ 869 - if ((data->viewport.x + data->viewport.width) < (src.x + src.width)) { 870 - int vp_clip = src.x + src.width - data->viewport.width - data->viewport.x; 871 - int int_part = dc_fixpt_floor( 872 - dc_fixpt_sub(data->inits.h, data->ratios.horz)); 873 - 874 - int_part = int_part > 0 ? int_part : 0; 875 - data->viewport.width += int_part < vp_clip ? int_part : vp_clip; 876 - } 877 - if ((data->viewport_c.x + data->viewport_c.width) < (src.x + src.width) / vpc_div) { 878 - int vp_clip = (src.x + src.width) / vpc_div - 879 - data->viewport_c.width - data->viewport_c.x; 880 - int int_part = dc_fixpt_floor( 881 - dc_fixpt_sub(data->inits.h_c, data->ratios.horz_c)); 882 - 883 - int_part = int_part > 0 ? int_part : 0; 884 - data->viewport_c.width += int_part < vp_clip ? int_part : vp_clip; 885 - } 886 - 887 - /* Adjust for non-0 viewport offset */ 888 - if (data->viewport.x) { 889 - int int_part; 890 - 891 - data->inits.h = dc_fixpt_add(data->inits.h, dc_fixpt_mul_int( 892 - data->ratios.horz, data->recout.x - recout_full->x)); 893 - int_part = dc_fixpt_floor(data->inits.h) - data->viewport.x; 894 - if (int_part < data->taps.h_taps) { 895 - int int_adj = data->viewport.x >= (data->taps.h_taps - int_part) ? 896 - (data->taps.h_taps - int_part) : data->viewport.x; 897 - data->viewport.x -= int_adj; 898 - data->viewport.width += int_adj; 899 - int_part += int_adj; 900 - } else if (int_part > data->taps.h_taps) { 901 - data->viewport.x += int_part - data->taps.h_taps; 902 - data->viewport.width -= int_part - data->taps.h_taps; 903 - int_part = data->taps.h_taps; 904 - } 905 - data->inits.h.value &= 0xffffffff; 906 - data->inits.h = dc_fixpt_add_int(data->inits.h, int_part); 907 - } 908 - 909 - if (data->viewport_c.x) { 910 - int int_part; 911 - 912 - data->inits.h_c = dc_fixpt_add(data->inits.h_c, dc_fixpt_mul_int( 913 - data->ratios.horz_c, data->recout.x - recout_full->x)); 914 - int_part = dc_fixpt_floor(data->inits.h_c) - data->viewport_c.x; 915 - if (int_part < data->taps.h_taps_c) { 916 - int int_adj = data->viewport_c.x >= (data->taps.h_taps_c - int_part) ? 917 - (data->taps.h_taps_c - int_part) : data->viewport_c.x; 918 - data->viewport_c.x -= int_adj; 919 - data->viewport_c.width += int_adj; 920 - int_part += int_adj; 921 - } else if (int_part > data->taps.h_taps_c) { 922 - data->viewport_c.x += int_part - data->taps.h_taps_c; 923 - data->viewport_c.width -= int_part - data->taps.h_taps_c; 924 - int_part = data->taps.h_taps_c; 925 - } 926 - data->inits.h_c.value &= 0xffffffff; 927 - data->inits.h_c = dc_fixpt_add_int(data->inits.h_c, int_part); 928 - } 929 - } else { 930 - /* Adjust for non-0 viewport offset */ 931 - if (data->viewport.x) { 932 - int int_part = dc_fixpt_floor( 933 - dc_fixpt_sub(data->inits.h, data->ratios.horz)); 934 - 935 - int_part = int_part > 0 ? int_part : 0; 936 - data->viewport.width += int_part < data->viewport.x ? int_part : data->viewport.x; 937 - data->viewport.x -= int_part < data->viewport.x ? int_part : data->viewport.x; 938 - } 939 - if (data->viewport_c.x) { 940 - int int_part = dc_fixpt_floor( 941 - dc_fixpt_sub(data->inits.h_c, data->ratios.horz_c)); 942 - 943 - int_part = int_part > 0 ? int_part : 0; 944 - data->viewport_c.width += int_part < data->viewport_c.x ? int_part : data->viewport_c.x; 945 - data->viewport_c.x -= int_part < data->viewport_c.x ? int_part : data->viewport_c.x; 946 - } 947 - 948 - /* Adjust for viewport end clip-off */ 949 - if ((data->viewport.x + data->viewport.width) < (src.x + src.width)) { 950 - int int_part; 951 - int end_offset = src.x + src.width 952 - - data->viewport.x - data->viewport.width; 953 - 954 - /* 955 - * this is init if vp had no offset, keep in mind this is from the 956 - * right side of vp due to scan direction 957 - */ 958 - data->inits.h = dc_fixpt_add(data->inits.h, dc_fixpt_mul_int( 959 - data->ratios.horz, data->recout.x - recout_full->x)); 960 - /* 961 - * this is the difference between first pixel of viewport available to read 962 - * and init position, takning into account scan direction 963 - */ 964 - int_part = dc_fixpt_floor(data->inits.h) - end_offset; 965 - if (int_part < data->taps.h_taps) { 966 - int int_adj = end_offset >= (data->taps.h_taps - int_part) ? 967 - (data->taps.h_taps - int_part) : end_offset; 968 - data->viewport.width += int_adj; 969 - int_part += int_adj; 970 - } else if (int_part > data->taps.h_taps) { 971 - data->viewport.width += int_part - data->taps.h_taps; 972 - int_part = data->taps.h_taps; 973 - } 974 - data->inits.h.value &= 0xffffffff; 975 - data->inits.h = dc_fixpt_add_int(data->inits.h, int_part); 976 - } 977 - 978 - if ((data->viewport_c.x + data->viewport_c.width) < (src.x + src.width) / vpc_div) { 979 - int int_part; 980 - int end_offset = (src.x + src.width) / vpc_div 981 - - data->viewport_c.x - data->viewport_c.width; 982 - 983 - /* 984 - * this is init if vp had no offset, keep in mind this is from the 985 - * right side of vp due to scan direction 986 - */ 987 - data->inits.h_c = dc_fixpt_add(data->inits.h_c, dc_fixpt_mul_int( 988 - data->ratios.horz_c, data->recout.x - recout_full->x)); 989 - /* 990 - * this is the difference between first pixel of viewport available to read 991 - * and init position, takning into account scan direction 992 - */ 993 - int_part = dc_fixpt_floor(data->inits.h_c) - end_offset; 994 - if (int_part < data->taps.h_taps_c) { 995 - int int_adj = end_offset >= (data->taps.h_taps_c - int_part) ? 996 - (data->taps.h_taps_c - int_part) : end_offset; 997 - data->viewport_c.width += int_adj; 998 - int_part += int_adj; 999 - } else if (int_part > data->taps.h_taps_c) { 1000 - data->viewport_c.width += int_part - data->taps.h_taps_c; 1001 - int_part = data->taps.h_taps_c; 1002 - } 1003 - data->inits.h_c.value &= 0xffffffff; 1004 - data->inits.h_c = dc_fixpt_add_int(data->inits.h_c, int_part); 1005 - } 1006 - 1007 - } 1008 - if (!flip_vert_scan_dir) { 1009 - /* Adjust for viewport end clip-off */ 1010 - if ((data->viewport.y + data->viewport.height) < (src.y + src.height)) { 1011 - int vp_clip = src.y + src.height - data->viewport.height - data->viewport.y; 1012 - int int_part = dc_fixpt_floor( 1013 - dc_fixpt_sub(data->inits.v, data->ratios.vert)); 1014 - 1015 - int_part = int_part > 0 ? int_part : 0; 1016 - data->viewport.height += int_part < vp_clip ? int_part : vp_clip; 1017 - } 1018 - if ((data->viewport_c.y + data->viewport_c.height) < (src.y + src.height) / vpc_div) { 1019 - int vp_clip = (src.y + src.height) / vpc_div - 1020 - data->viewport_c.height - data->viewport_c.y; 1021 - int int_part = dc_fixpt_floor( 1022 - dc_fixpt_sub(data->inits.v_c, data->ratios.vert_c)); 1023 - 1024 - int_part = int_part > 0 ? int_part : 0; 1025 - data->viewport_c.height += int_part < vp_clip ? int_part : vp_clip; 1026 - } 1027 - 1028 - /* Adjust for non-0 viewport offset */ 1029 - if (data->viewport.y) { 1030 - int int_part; 1031 - 1032 - data->inits.v = dc_fixpt_add(data->inits.v, dc_fixpt_mul_int( 1033 - data->ratios.vert, data->recout.y - recout_full->y)); 1034 - int_part = dc_fixpt_floor(data->inits.v) - data->viewport.y; 1035 - if (int_part < data->taps.v_taps) { 1036 - int int_adj = data->viewport.y >= (data->taps.v_taps - int_part) ? 1037 - (data->taps.v_taps - int_part) : data->viewport.y; 1038 - data->viewport.y -= int_adj; 1039 - data->viewport.height += int_adj; 1040 - int_part += int_adj; 1041 - } else if (int_part > data->taps.v_taps) { 1042 - data->viewport.y += int_part - data->taps.v_taps; 1043 - data->viewport.height -= int_part - data->taps.v_taps; 1044 - int_part = data->taps.v_taps; 1045 - } 1046 - data->inits.v.value &= 0xffffffff; 1047 - data->inits.v = dc_fixpt_add_int(data->inits.v, int_part); 1048 - } 1049 - 1050 - if (data->viewport_c.y) { 1051 - int int_part; 1052 - 1053 - data->inits.v_c = dc_fixpt_add(data->inits.v_c, dc_fixpt_mul_int( 1054 - data->ratios.vert_c, data->recout.y - recout_full->y)); 1055 - int_part = dc_fixpt_floor(data->inits.v_c) - data->viewport_c.y; 1056 - if (int_part < data->taps.v_taps_c) { 1057 - int int_adj = data->viewport_c.y >= (data->taps.v_taps_c - int_part) ? 1058 - (data->taps.v_taps_c - int_part) : data->viewport_c.y; 1059 - data->viewport_c.y -= int_adj; 1060 - data->viewport_c.height += int_adj; 1061 - int_part += int_adj; 1062 - } else if (int_part > data->taps.v_taps_c) { 1063 - data->viewport_c.y += int_part - data->taps.v_taps_c; 1064 - data->viewport_c.height -= int_part - data->taps.v_taps_c; 1065 - int_part = data->taps.v_taps_c; 1066 - } 1067 - data->inits.v_c.value &= 0xffffffff; 1068 - data->inits.v_c = dc_fixpt_add_int(data->inits.v_c, int_part); 1069 - } 1070 - } else { 1071 - /* Adjust for non-0 viewport offset */ 1072 - if (data->viewport.y) { 1073 - int int_part = dc_fixpt_floor( 1074 - dc_fixpt_sub(data->inits.v, data->ratios.vert)); 1075 - 1076 - int_part = int_part > 0 ? int_part : 0; 1077 - data->viewport.height += int_part < data->viewport.y ? int_part : data->viewport.y; 1078 - data->viewport.y -= int_part < data->viewport.y ? int_part : data->viewport.y; 1079 - } 1080 - if (data->viewport_c.y) { 1081 - int int_part = dc_fixpt_floor( 1082 - dc_fixpt_sub(data->inits.v_c, data->ratios.vert_c)); 1083 - 1084 - int_part = int_part > 0 ? int_part : 0; 1085 - data->viewport_c.height += int_part < data->viewport_c.y ? int_part : data->viewport_c.y; 1086 - data->viewport_c.y -= int_part < data->viewport_c.y ? int_part : data->viewport_c.y; 1087 - } 1088 - 1089 - /* Adjust for viewport end clip-off */ 1090 - if ((data->viewport.y + data->viewport.height) < (src.y + src.height)) { 1091 - int int_part; 1092 - int end_offset = src.y + src.height 1093 - - data->viewport.y - data->viewport.height; 1094 - 1095 - /* 1096 - * this is init if vp had no offset, keep in mind this is from the 1097 - * right side of vp due to scan direction 1098 - */ 1099 - data->inits.v = dc_fixpt_add(data->inits.v, dc_fixpt_mul_int( 1100 - data->ratios.vert, data->recout.y - recout_full->y)); 1101 - /* 1102 - * this is the difference between first pixel of viewport available to read 1103 - * and init position, taking into account scan direction 1104 - */ 1105 - int_part = dc_fixpt_floor(data->inits.v) - end_offset; 1106 - if (int_part < data->taps.v_taps) { 1107 - int int_adj = end_offset >= (data->taps.v_taps - int_part) ? 1108 - (data->taps.v_taps - int_part) : end_offset; 1109 - data->viewport.height += int_adj; 1110 - int_part += int_adj; 1111 - } else if (int_part > data->taps.v_taps) { 1112 - data->viewport.height += int_part - data->taps.v_taps; 1113 - int_part = data->taps.v_taps; 1114 - } 1115 - data->inits.v.value &= 0xffffffff; 1116 - data->inits.v = dc_fixpt_add_int(data->inits.v, int_part); 1117 - } 1118 - 1119 - if ((data->viewport_c.y + data->viewport_c.height) < (src.y + src.height) / vpc_div) { 1120 - int int_part; 1121 - int end_offset = (src.y + src.height) / vpc_div 1122 - - data->viewport_c.y - data->viewport_c.height; 1123 - 1124 - /* 1125 - * this is init if vp had no offset, keep in mind this is from the 1126 - * right side of vp due to scan direction 1127 - */ 1128 - data->inits.v_c = dc_fixpt_add(data->inits.v_c, dc_fixpt_mul_int( 1129 - data->ratios.vert_c, data->recout.y - recout_full->y)); 1130 - /* 1131 - * this is the difference between first pixel of viewport available to read 1132 - * and init position, taking into account scan direction 1133 - */ 1134 - int_part = dc_fixpt_floor(data->inits.v_c) - end_offset; 1135 - if (int_part < data->taps.v_taps_c) { 1136 - int int_adj = end_offset >= (data->taps.v_taps_c - int_part) ? 1137 - (data->taps.v_taps_c - int_part) : end_offset; 1138 - data->viewport_c.height += int_adj; 1139 - int_part += int_adj; 1140 - } else if (int_part > data->taps.v_taps_c) { 1141 - data->viewport_c.height += int_part - data->taps.v_taps_c; 1142 - int_part = data->taps.v_taps_c; 1143 - } 1144 - data->inits.v_c.value &= 0xffffffff; 1145 - data->inits.v_c = dc_fixpt_add_int(data->inits.v_c, int_part); 1146 - } 1147 - } 794 + /* 795 + * Taps, inits and scaling ratios are in recout space need to rotate 796 + * to viewport rotation before adjustment 797 + */ 798 + adjust_vp_and_init_for_seamless_clip( 799 + flip_horz_scan_dir, 800 + recout_skip_h, 801 + surf_size_h, 802 + orthogonal_rotation ? data->taps.v_taps : data->taps.h_taps, 803 + orthogonal_rotation ? data->ratios.vert : data->ratios.horz, 804 + orthogonal_rotation ? &data->inits.v : &data->inits.h, 805 + &data->viewport.x, 806 + &data->viewport.width); 807 + adjust_vp_and_init_for_seamless_clip( 808 + flip_horz_scan_dir, 809 + recout_skip_h, 810 + surf_size_h / vpc_div, 811 + orthogonal_rotation ? data->taps.v_taps_c : data->taps.h_taps_c, 812 + orthogonal_rotation ? data->ratios.vert_c : data->ratios.horz_c, 813 + orthogonal_rotation ? &data->inits.v_c : &data->inits.h_c, 814 + &data->viewport_c.x, 815 + &data->viewport_c.width); 816 + adjust_vp_and_init_for_seamless_clip( 817 + flip_vert_scan_dir, 818 + recout_skip_v, 819 + surf_size_v, 820 + orthogonal_rotation ? data->taps.h_taps : data->taps.v_taps, 821 + orthogonal_rotation ? data->ratios.horz : data->ratios.vert, 822 + orthogonal_rotation ? &data->inits.h : &data->inits.v, 823 + &data->viewport.y, 824 + &data->viewport.height); 825 + adjust_vp_and_init_for_seamless_clip( 826 + flip_vert_scan_dir, 827 + recout_skip_v, 828 + surf_size_v / vpc_div, 829 + orthogonal_rotation ? data->taps.h_taps_c : data->taps.v_taps_c, 830 + orthogonal_rotation ? data->ratios.horz_c : data->ratios.vert_c, 831 + orthogonal_rotation ? &data->inits.h_c : &data->inits.v_c, 832 + &data->viewport_c.y, 833 + &data->viewport_c.height); 1148 834 1149 835 /* Interlaced inits based on final vert inits */ 1150 836 data->inits.v_bot = dc_fixpt_add(data->inits.v, data->ratios.vert); 1151 837 data->inits.v_c_bot = dc_fixpt_add(data->inits.v_c, data->ratios.vert_c); 1152 838 1153 - if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90 || 1154 - pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270) { 1155 - rect_swap_helper(&data->viewport_c); 1156 - rect_swap_helper(&data->viewport); 1157 - } 1158 839 } 1159 840 1160 841 bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) 1161 842 { 1162 843 const struct dc_plane_state *plane_state = pipe_ctx->plane_state; 1163 844 struct dc_crtc_timing *timing = &pipe_ctx->stream->timing; 1164 - struct rect recout_full = { 0 }; 1165 845 bool res = false; 1166 846 DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger); 1167 847 /* Important: scaling ratio calculation requires pixel format, ··· 931 1105 if (pipe_ctx->plane_res.scl_data.viewport.height < 16 || pipe_ctx->plane_res.scl_data.viewport.width < 16) 932 1106 return false; 933 1107 934 - calculate_recout(pipe_ctx, &recout_full); 1108 + calculate_recout(pipe_ctx); 935 1109 936 1110 /** 937 1111 * Setting line buffer pixel depth to 24bpp yields banding ··· 972 1146 973 1147 if (res) 974 1148 /* May need to re-check lb size after this in some obscure scenario */ 975 - calculate_inits_and_adj_vp(pipe_ctx, &recout_full); 1149 + calculate_inits_and_adj_vp(pipe_ctx); 976 1150 977 1151 DC_LOG_SCALER( 978 1152 "%s: Viewport:\nheight:%d width:%d x:%d " ··· 1182 1356 return false; 1183 1357 } 1184 1358 1359 + tail_pipe = resource_get_tail_pipe_for_stream(&context->res_ctx, stream); 1360 + ASSERT(tail_pipe); 1361 + 1185 1362 free_pipe = acquire_free_pipe_for_stream(context, pool, stream); 1186 1363 1187 1364 #if defined(CONFIG_DRM_AMD_DC_DCN1_0) ··· 1202 1373 free_pipe->plane_state = plane_state; 1203 1374 1204 1375 if (head_pipe != free_pipe) { 1205 - 1206 - tail_pipe = resource_get_tail_pipe_for_stream(&context->res_ctx, stream); 1207 - ASSERT(tail_pipe); 1208 - 1209 1376 free_pipe->stream_res.tg = tail_pipe->stream_res.tg; 1210 1377 free_pipe->stream_res.abm = tail_pipe->stream_res.abm; 1211 1378 free_pipe->stream_res.opp = tail_pipe->stream_res.opp; ··· 1621 1796 struct dc_state *new_ctx, 1622 1797 struct dc_stream_state *stream) 1623 1798 { 1624 - struct dc_context *dc_ctx = dc->ctx; 1625 1799 enum dc_status res; 1800 + DC_LOGGER_INIT(dc->ctx->logger); 1626 1801 1627 1802 if (new_ctx->stream_count >= dc->res_pool->timing_generator_count) { 1628 - DC_ERROR("Max streams reached, can't add stream %p !\n", stream); 1803 + DC_LOG_WARNING("Max streams reached, can't add stream %p !\n", stream); 1629 1804 return DC_ERROR_UNEXPECTED; 1630 1805 } 1631 1806 ··· 1635 1810 1636 1811 res = dc->res_pool->funcs->add_stream_to_ctx(dc, new_ctx, stream); 1637 1812 if (res != DC_OK) 1638 - DC_ERROR("Adding stream %p to context failed with err %d!\n", stream, res); 1813 + DC_LOG_WARNING("Adding stream %p to context failed with err %d!\n", stream, res); 1639 1814 1640 1815 return res; 1641 1816 } ··· 1800 1975 } 1801 1976 } 1802 1977 */ 1978 + 1979 + calculate_phy_pix_clks(stream); 1803 1980 1804 1981 /* acquire new resources */ 1805 1982 pipe_idx = acquire_first_free_pipe(&context->res_ctx, pool, stream);
-2
drivers/gpu/drm/amd/display/dc/core/dc_stream.c
··· 100 100 /* EDID CAP translation for HDMI 2.0 */ 101 101 stream->timing.flags.LTE_340MCSC_SCRAMBLE = dc_sink_data->edid_caps.lte_340mcsc_scramble; 102 102 103 - stream->status.link = stream->sink->link; 104 - 105 103 update_stream_signal(stream); 106 104 107 105 stream->out_transfer_func = dc_create_transfer_func();
+3 -8
drivers/gpu/drm/amd/display/dc/dc.h
··· 36 36 37 37 #include "inc/hw_sequencer.h" 38 38 #include "inc/compressor.h" 39 + #include "inc/hw/dmcu.h" 39 40 #include "dml/display_mode_lib.h" 40 41 41 - #define DC_VER "3.2.04" 42 + #define DC_VER "3.2.06" 42 43 43 44 #define MAX_SURFACES 3 44 45 #define MAX_STREAMS 6 ··· 48 47 /******************************************************************************* 49 48 * Display Core Interfaces 50 49 ******************************************************************************/ 51 - struct dmcu_version { 52 - unsigned int date; 53 - unsigned int month; 54 - unsigned int year; 55 - unsigned int interface_version; 56 - }; 57 - 58 50 struct dc_versions { 59 51 const char *dc_ver; 60 52 struct dmcu_version dmcu_version; ··· 742 748 struct dc *dc, 743 749 enum dc_acpi_cm_power_state power_state); 744 750 void dc_resume(struct dc *dc); 751 + bool dc_is_dmcu_initialized(struct dc *dc); 745 752 746 753 #endif /* DC_INTERFACE_H_ */
-2
drivers/gpu/drm/amd/display/dc/dc_stream.h
··· 104 104 bool dpms_off; 105 105 bool apply_edp_fast_boot_optimization; 106 106 107 - struct dc_stream_status status; 108 - 109 107 struct dc_cursor_attributes cursor_attributes; 110 108 struct dc_cursor_position cursor_position; 111 109 uint32_t sdr_white_level; // for boosting (SDR) cursor in HDR mode
+10 -5
drivers/gpu/drm/amd/display/dc/dce/dce_clk_mgr.c
··· 94 94 /*ClocksStatePerformance*/ 95 95 { .display_clk_khz = 1133000, .pixel_clk_khz = 600000 } }; 96 96 97 - static int dentist_get_divider_from_did(int did) 97 + int dentist_get_divider_from_did(int did) 98 98 { 99 99 if (did < DENTIST_BASE_DID_1) 100 100 did = DENTIST_BASE_DID_1; ··· 277 277 if (requested_clk_khz == 0) 278 278 clk_mgr_dce->cur_min_clks_state = DM_PP_CLOCKS_STATE_NOMINAL; 279 279 280 - dmcu->funcs->set_psr_wait_loop(dmcu, actual_clock / 1000 / 7); 280 + if (dmcu && dmcu->funcs->is_dmcu_initialized(dmcu)) 281 + dmcu->funcs->set_psr_wait_loop(dmcu, actual_clock / 1000 / 7); 281 282 282 283 return actual_clock; 283 284 } ··· 325 324 bp->funcs->set_dce_clock(bp, &dce_clk_params); 326 325 327 326 if (!IS_FPGA_MAXIMUS_DC(core_dc->ctx->dce_environment)) { 328 - if (clk_mgr_dce->dfs_bypass_disp_clk != actual_clock) 329 - dmcu->funcs->set_psr_wait_loop(dmcu, 330 - actual_clock / 1000 / 7); 327 + if (dmcu && dmcu->funcs->is_dmcu_initialized(dmcu)) { 328 + if (clk_mgr_dce->dfs_bypass_disp_clk != actual_clock) 329 + dmcu->funcs->set_psr_wait_loop(dmcu, 330 + actual_clock / 1000 / 7); 331 + } 331 332 } 332 333 333 334 clk_mgr_dce->dfs_bypass_disp_clk = actual_clock; ··· 590 587 pp_display_cfg->min_engine_clock_khz = determine_sclk_from_bounding_box( 591 588 dc, 592 589 context->bw.dce.sclk_khz); 590 + 591 + pp_display_cfg->min_dcfclock_khz = pp_display_cfg->min_engine_clock_khz; 593 592 594 593 pp_display_cfg->min_engine_clock_deep_sleep_khz 595 594 = context->bw.dce.sclk_deep_sleep_khz;
+2
drivers/gpu/drm/amd/display/dc/dce/dce_clk_mgr.h
··· 165 165 166 166 void dce_clk_mgr_destroy(struct clk_mgr **clk_mgr); 167 167 168 + int dentist_get_divider_from_did(int did); 169 + 168 170 #endif /* _DCE_CLK_MGR_H_ */
+10 -13
drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c
··· 908 908 struct stream_encoder *enc) 909 909 { 910 910 struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc); 911 - uint32_t retries = 0; 912 911 uint32_t reg1 = 0; 913 912 uint32_t max_retries = DP_BLANK_MAX_RETRY * 10; 914 913 ··· 925 926 * (2 = start of the next vertical blank) */ 926 927 REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_DIS_DEFER, 2); 927 928 /* Larger delay to wait until VBLANK - use max retry of 928 - * 10us*3000=30ms. This covers 16.6ms of typical 60 Hz mode + 929 - * a little more because we may not trust delay accuracy. 930 - */ 929 + * 10us*3000=30ms. This covers 16.6ms of typical 60 Hz mode + 930 + * a little more because we may not trust delay accuracy. 931 + */ 931 932 max_retries = DP_BLANK_MAX_RETRY * 150; 932 933 933 934 /* disable DP stream */ 934 935 REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, 0); 935 936 936 937 /* the encoder stops sending the video stream 937 - * at the start of the vertical blanking. 938 - * Poll for DP_VID_STREAM_STATUS == 0 939 - */ 938 + * at the start of the vertical blanking. 939 + * Poll for DP_VID_STREAM_STATUS == 0 940 + */ 940 941 941 942 REG_WAIT(DP_VID_STREAM_CNTL, DP_VID_STREAM_STATUS, 942 943 0, 943 944 10, max_retries); 944 945 945 - ASSERT(retries <= max_retries); 946 - 947 946 /* Tell the DP encoder to ignore timing from CRTC, must be done after 948 - * the polling. If we set DP_STEER_FIFO_RESET before DP stream blank is 949 - * complete, stream status will be stuck in video stream enabled state, 950 - * i.e. DP_VID_STREAM_STATUS stuck at 1. 951 - */ 947 + * the polling. If we set DP_STEER_FIFO_RESET before DP stream blank is 948 + * complete, stream status will be stuck in video stream enabled state, 949 + * i.e. DP_VID_STREAM_STATUS stuck at 1. 950 + */ 952 951 953 952 REG_UPDATE(DP_STEER_FIFO, DP_STEER_FIFO_RESET, true); 954 953 }
+1 -1
drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
··· 2282 2282 int i; 2283 2283 2284 2284 gsl_params.gsl_group = 0; 2285 - gsl_params.gsl_master = grouped_pipes[0]->stream->triggered_crtc_reset.event_source->status.primary_otg_inst; 2285 + gsl_params.gsl_master = 0; 2286 2286 2287 2287 for (i = 0; i < group_size; i++) 2288 2288 grouped_pipes[i]->stream_res.tg->funcs->setup_global_swap_lock(
-1
drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c
··· 41 41 #include "dce/dce_mem_input.h" 42 42 #include "dce/dce_link_encoder.h" 43 43 #include "dce/dce_stream_encoder.h" 44 - #include "dce/dce_mem_input.h" 45 44 #include "dce/dce_ipp.h" 46 45 #include "dce/dce_transform.h" 47 46 #include "dce/dce_opp.h"
+5 -9
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_clk_mgr.c
··· 223 223 &dc->res_pool->pp_smu_req; 224 224 struct pp_smu_display_requirement_rv smu_req = *smu_req_cur; 225 225 struct pp_smu_funcs_rv *pp_smu = dc->res_pool->pp_smu; 226 - struct dm_pp_clock_for_voltage_req clock_voltage_req = {0}; 226 + uint32_t requested_dcf_clock_in_khz = 0; 227 227 bool send_request_to_increase = false; 228 228 bool send_request_to_lower = false; 229 229 int display_count; ··· 263 263 // F Clock 264 264 if (should_set_clock(safe_to_lower, new_clocks->fclk_khz, clk_mgr->clks.fclk_khz)) { 265 265 clk_mgr->clks.fclk_khz = new_clocks->fclk_khz; 266 - clock_voltage_req.clk_type = DM_PP_CLOCK_TYPE_FCLK; 267 - clock_voltage_req.clocks_in_khz = new_clocks->fclk_khz; 268 266 smu_req.hard_min_fclk_mhz = new_clocks->fclk_khz / 1000; 269 267 270 268 notify_hard_min_fclk_to_smu(pp_smu, new_clocks->fclk_khz); ··· 291 293 */ 292 294 if (send_request_to_increase) { 293 295 /*use dcfclk to request voltage*/ 294 - clock_voltage_req.clk_type = DM_PP_CLOCK_TYPE_DCFCLK; 295 - clock_voltage_req.clocks_in_khz = dcn_find_dcfclk_suits_all(dc, new_clocks); 296 + requested_dcf_clock_in_khz = dcn_find_dcfclk_suits_all(dc, new_clocks); 296 297 297 - notify_hard_min_dcfclk_to_smu(pp_smu, clock_voltage_req.clocks_in_khz); 298 + notify_hard_min_dcfclk_to_smu(pp_smu, requested_dcf_clock_in_khz); 298 299 299 300 if (pp_smu->set_display_requirement) 300 301 pp_smu->set_display_requirement(&pp_smu->pp_smu, &smu_req); ··· 314 317 315 318 if (!send_request_to_increase && send_request_to_lower) { 316 319 /*use dcfclk to request voltage*/ 317 - clock_voltage_req.clk_type = DM_PP_CLOCK_TYPE_DCFCLK; 318 - clock_voltage_req.clocks_in_khz = dcn_find_dcfclk_suits_all(dc, new_clocks); 320 + requested_dcf_clock_in_khz = dcn_find_dcfclk_suits_all(dc, new_clocks); 319 321 320 - notify_hard_min_dcfclk_to_smu(pp_smu, clock_voltage_req.clocks_in_khz); 322 + notify_hard_min_dcfclk_to_smu(pp_smu, requested_dcf_clock_in_khz); 321 323 322 324 if (pp_smu->set_display_requirement) 323 325 pp_smu->set_display_requirement(&pp_smu->pp_smu, &smu_req);
+1 -1
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c
··· 100 100 REG_GET(DCHUBBUB_ARB_DRAM_STATE_CNTL, 101 101 DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE, &enable); 102 102 103 - return true ? false : enable; 103 + return enable ? true : false; 104 104 } 105 105 106 106
+52 -44
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c
··· 99 99 return hubp_underflow; 100 100 } 101 101 102 + 103 + void hubp1_clear_underflow(struct hubp *hubp) 104 + { 105 + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); 106 + 107 + REG_UPDATE(DCHUBP_CNTL, HUBP_UNDERFLOW_CLEAR, 1); 108 + } 109 + 102 110 static void hubp1_set_hubp_blank_en(struct hubp *hubp, bool blank) 103 111 { 104 112 struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); ··· 573 565 REFCYC_X_AFTER_SCALER, dlg_attr->refcyc_x_after_scaler, 574 566 DST_Y_AFTER_SCALER, dlg_attr->dst_y_after_scaler); 575 567 576 - if (REG(PREFETCH_SETTINS)) 577 - REG_SET_2(PREFETCH_SETTINS, 0, 578 - DST_Y_PREFETCH, dlg_attr->dst_y_prefetch, 579 - VRATIO_PREFETCH, dlg_attr->vratio_prefetch); 580 - else 581 - REG_SET_2(PREFETCH_SETTINGS, 0, 582 - DST_Y_PREFETCH, dlg_attr->dst_y_prefetch, 583 - VRATIO_PREFETCH, dlg_attr->vratio_prefetch); 584 - 585 - REG_SET_2(VBLANK_PARAMETERS_0, 0, 586 - DST_Y_PER_VM_VBLANK, dlg_attr->dst_y_per_vm_vblank, 587 - DST_Y_PER_ROW_VBLANK, dlg_attr->dst_y_per_row_vblank); 588 - 589 568 REG_SET(REF_FREQ_TO_PIX_FREQ, 0, 590 569 REF_FREQ_TO_PIX_FREQ, dlg_attr->ref_freq_to_pix_freq); 591 570 592 571 /* DLG - Per luma/chroma */ 593 572 REG_SET(VBLANK_PARAMETERS_1, 0, 594 573 REFCYC_PER_PTE_GROUP_VBLANK_L, dlg_attr->refcyc_per_pte_group_vblank_l); 595 - 596 - REG_SET(VBLANK_PARAMETERS_3, 0, 597 - REFCYC_PER_META_CHUNK_VBLANK_L, dlg_attr->refcyc_per_meta_chunk_vblank_l); 598 574 599 575 if (REG(NOM_PARAMETERS_0)) 600 576 REG_SET(NOM_PARAMETERS_0, 0, ··· 594 602 REG_SET(NOM_PARAMETERS_5, 0, 595 603 REFCYC_PER_META_CHUNK_NOM_L, dlg_attr->refcyc_per_meta_chunk_nom_l); 596 604 597 - REG_SET_2(PER_LINE_DELIVERY_PRE, 0, 598 - REFCYC_PER_LINE_DELIVERY_PRE_L, dlg_attr->refcyc_per_line_delivery_pre_l, 599 - REFCYC_PER_LINE_DELIVERY_PRE_C, dlg_attr->refcyc_per_line_delivery_pre_c); 600 - 601 605 REG_SET_2(PER_LINE_DELIVERY, 0, 602 606 REFCYC_PER_LINE_DELIVERY_L, dlg_attr->refcyc_per_line_delivery_l, 603 607 REFCYC_PER_LINE_DELIVERY_C, dlg_attr->refcyc_per_line_delivery_c); 604 608 605 - if (REG(PREFETCH_SETTINS_C)) 606 - REG_SET(PREFETCH_SETTINS_C, 0, 607 - VRATIO_PREFETCH_C, dlg_attr->vratio_prefetch_c); 608 - else 609 - REG_SET(PREFETCH_SETTINGS_C, 0, 610 - VRATIO_PREFETCH_C, dlg_attr->vratio_prefetch_c); 611 - 612 609 REG_SET(VBLANK_PARAMETERS_2, 0, 613 610 REFCYC_PER_PTE_GROUP_VBLANK_C, dlg_attr->refcyc_per_pte_group_vblank_c); 614 - 615 - REG_SET(VBLANK_PARAMETERS_4, 0, 616 - REFCYC_PER_META_CHUNK_VBLANK_C, dlg_attr->refcyc_per_meta_chunk_vblank_c); 617 611 618 612 if (REG(NOM_PARAMETERS_2)) 619 613 REG_SET(NOM_PARAMETERS_2, 0, ··· 620 642 QoS_LEVEL_LOW_WM, ttu_attr->qos_level_low_wm, 621 643 QoS_LEVEL_HIGH_WM, ttu_attr->qos_level_high_wm); 622 644 623 - REG_SET_2(DCN_GLOBAL_TTU_CNTL, 0, 624 - MIN_TTU_VBLANK, ttu_attr->min_ttu_vblank, 625 - QoS_LEVEL_FLIP, ttu_attr->qos_level_flip); 626 - 627 645 /* TTU - per luma/chroma */ 628 646 /* Assumed surf0 is luma and 1 is chroma */ 629 647 ··· 628 654 QoS_LEVEL_FIXED, ttu_attr->qos_level_fixed_l, 629 655 QoS_RAMP_DISABLE, ttu_attr->qos_ramp_disable_l); 630 656 631 - REG_SET(DCN_SURF0_TTU_CNTL1, 0, 632 - REFCYC_PER_REQ_DELIVERY_PRE, 633 - ttu_attr->refcyc_per_req_delivery_pre_l); 634 - 635 657 REG_SET_3(DCN_SURF1_TTU_CNTL0, 0, 636 658 REFCYC_PER_REQ_DELIVERY, ttu_attr->refcyc_per_req_delivery_c, 637 659 QoS_LEVEL_FIXED, ttu_attr->qos_level_fixed_c, 638 660 QoS_RAMP_DISABLE, ttu_attr->qos_ramp_disable_c); 639 661 640 - REG_SET(DCN_SURF1_TTU_CNTL1, 0, 641 - REFCYC_PER_REQ_DELIVERY_PRE, 642 - ttu_attr->refcyc_per_req_delivery_pre_c); 643 - 644 662 REG_SET_3(DCN_CUR0_TTU_CNTL0, 0, 645 663 REFCYC_PER_REQ_DELIVERY, ttu_attr->refcyc_per_req_delivery_cur0, 646 664 QoS_LEVEL_FIXED, ttu_attr->qos_level_fixed_cur0, 647 665 QoS_RAMP_DISABLE, ttu_attr->qos_ramp_disable_cur0); 648 - REG_SET(DCN_CUR0_TTU_CNTL1, 0, 649 - REFCYC_PER_REQ_DELIVERY_PRE, ttu_attr->refcyc_per_req_delivery_pre_cur0); 650 666 } 651 667 652 668 static void hubp1_setup( ··· 652 688 hubp1_program_requestor(hubp, rq_regs); 653 689 hubp1_program_deadline(hubp, dlg_attr, ttu_attr); 654 690 hubp1_vready_workaround(hubp, pipe_dest); 691 + } 692 + 693 + static void hubp1_setup_interdependent( 694 + struct hubp *hubp, 695 + struct _vcs_dpi_display_dlg_regs_st *dlg_attr, 696 + struct _vcs_dpi_display_ttu_regs_st *ttu_attr) 697 + { 698 + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); 699 + 700 + REG_SET_2(PREFETCH_SETTINS, 0, 701 + DST_Y_PREFETCH, dlg_attr->dst_y_prefetch, 702 + VRATIO_PREFETCH, dlg_attr->vratio_prefetch); 703 + 704 + REG_SET(PREFETCH_SETTINS_C, 0, 705 + VRATIO_PREFETCH_C, dlg_attr->vratio_prefetch_c); 706 + 707 + REG_SET_2(VBLANK_PARAMETERS_0, 0, 708 + DST_Y_PER_VM_VBLANK, dlg_attr->dst_y_per_vm_vblank, 709 + DST_Y_PER_ROW_VBLANK, dlg_attr->dst_y_per_row_vblank); 710 + 711 + REG_SET(VBLANK_PARAMETERS_3, 0, 712 + REFCYC_PER_META_CHUNK_VBLANK_L, dlg_attr->refcyc_per_meta_chunk_vblank_l); 713 + 714 + REG_SET(VBLANK_PARAMETERS_4, 0, 715 + REFCYC_PER_META_CHUNK_VBLANK_C, dlg_attr->refcyc_per_meta_chunk_vblank_c); 716 + 717 + REG_SET_2(PER_LINE_DELIVERY_PRE, 0, 718 + REFCYC_PER_LINE_DELIVERY_PRE_L, dlg_attr->refcyc_per_line_delivery_pre_l, 719 + REFCYC_PER_LINE_DELIVERY_PRE_C, dlg_attr->refcyc_per_line_delivery_pre_c); 720 + 721 + REG_SET(DCN_SURF0_TTU_CNTL1, 0, 722 + REFCYC_PER_REQ_DELIVERY_PRE, 723 + ttu_attr->refcyc_per_req_delivery_pre_l); 724 + REG_SET(DCN_SURF1_TTU_CNTL1, 0, 725 + REFCYC_PER_REQ_DELIVERY_PRE, 726 + ttu_attr->refcyc_per_req_delivery_pre_c); 727 + REG_SET(DCN_CUR0_TTU_CNTL1, 0, 728 + REFCYC_PER_REQ_DELIVERY_PRE, ttu_attr->refcyc_per_req_delivery_pre_cur0); 729 + 730 + REG_SET_2(DCN_GLOBAL_TTU_CNTL, 0, 731 + MIN_TTU_VBLANK, ttu_attr->min_ttu_vblank, 732 + QoS_LEVEL_FLIP, ttu_attr->qos_level_flip); 655 733 } 656 734 657 735 bool hubp1_is_flip_pending(struct hubp *hubp) ··· 1184 1178 hubp1_program_surface_config, 1185 1179 .hubp_is_flip_pending = hubp1_is_flip_pending, 1186 1180 .hubp_setup = hubp1_setup, 1181 + .hubp_setup_interdependent = hubp1_setup_interdependent, 1187 1182 .hubp_set_vm_system_aperture_settings = hubp1_set_vm_system_aperture_settings, 1188 1183 .hubp_set_vm_context0_settings = hubp1_set_vm_context0_settings, 1189 1184 .set_blank = hubp1_set_blank, ··· 1197 1190 .hubp_clk_cntl = hubp1_clk_cntl, 1198 1191 .hubp_vtg_sel = hubp1_vtg_sel, 1199 1192 .hubp_read_state = hubp1_read_state, 1193 + .hubp_clear_underflow = hubp1_clear_underflow, 1200 1194 .hubp_disable_control = hubp1_disable_control, 1201 1195 .hubp_get_underflow_status = hubp1_get_underflow_status, 1202 1196
+3
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.h
··· 251 251 HUBP_SF(HUBP0_DCHUBP_CNTL, HUBP_BLANK_EN, mask_sh),\ 252 252 HUBP_SF(HUBP0_DCHUBP_CNTL, HUBP_TTU_DISABLE, mask_sh),\ 253 253 HUBP_SF(HUBP0_DCHUBP_CNTL, HUBP_UNDERFLOW_STATUS, mask_sh),\ 254 + HUBP_SF(HUBP0_DCHUBP_CNTL, HUBP_UNDERFLOW_CLEAR, mask_sh),\ 254 255 HUBP_SF(HUBP0_DCHUBP_CNTL, HUBP_NO_OUTSTANDING_REQ, mask_sh),\ 255 256 HUBP_SF(HUBP0_DCHUBP_CNTL, HUBP_VTG_SEL, mask_sh),\ 256 257 HUBP_SF(HUBP0_DCHUBP_CNTL, HUBP_DISABLE, mask_sh),\ ··· 436 435 type HUBP_NO_OUTSTANDING_REQ;\ 437 436 type HUBP_VTG_SEL;\ 438 437 type HUBP_UNDERFLOW_STATUS;\ 438 + type HUBP_UNDERFLOW_CLEAR;\ 439 439 type NUM_PIPES;\ 440 440 type NUM_BANKS;\ 441 441 type PIPE_INTERLEAVE;\ ··· 741 739 const struct dcn_mi_mask *hubp_mask); 742 740 743 741 void hubp1_read_state(struct hubp *hubp); 742 + void hubp1_clear_underflow(struct hubp *hubp); 744 743 745 744 enum cursor_pitch hubp1_get_cursor_pitch(unsigned int pitch); 746 745
+36 -4
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
··· 1227 1227 tf = plane_state->in_transfer_func; 1228 1228 1229 1229 if (plane_state->gamma_correction && 1230 - !plane_state->gamma_correction->is_identity 1230 + !dpp_base->ctx->dc->debug.always_use_regamma 1231 + && !plane_state->gamma_correction->is_identity 1231 1232 && dce_use_lut(plane_state->format)) 1232 1233 dpp_base->funcs->dpp_program_input_lut(dpp_base, plane_state->gamma_correction); 1233 1234 ··· 1401 1400 if (grouped_pipes[i]->stream_res.tg->funcs->enable_crtc_reset) 1402 1401 grouped_pipes[i]->stream_res.tg->funcs->enable_crtc_reset( 1403 1402 grouped_pipes[i]->stream_res.tg, 1404 - grouped_pipes[i]->stream->triggered_crtc_reset.event_source->status.primary_otg_inst, 1403 + 0, 1405 1404 &grouped_pipes[i]->stream->triggered_crtc_reset); 1406 1405 1407 1406 DC_SYNC_INFO("Waiting for trigger\n"); ··· 1771 1770 } 1772 1771 } 1773 1772 1774 - static void dcn10_get_surface_visual_confirm_color( 1773 + void dcn10_get_surface_visual_confirm_color( 1775 1774 const struct pipe_ctx *pipe_ctx, 1776 1775 struct tg_color *color) 1777 1776 { ··· 1807 1806 } 1808 1807 } 1809 1808 1810 - static void dcn10_get_hdr_visual_confirm_color( 1809 + void dcn10_get_hdr_visual_confirm_color( 1811 1810 struct pipe_ctx *pipe_ctx, 1812 1811 struct tg_color *color) 1813 1812 { ··· 2068 2067 &pipe_ctx->ttu_regs, 2069 2068 &pipe_ctx->rq_regs, 2070 2069 &pipe_ctx->pipe_dlg_param); 2070 + hubp->funcs->hubp_setup_interdependent( 2071 + hubp, 2072 + &pipe_ctx->dlg_regs, 2073 + &pipe_ctx->ttu_regs); 2071 2074 } 2072 2075 2073 2076 size.grph.surface_size = pipe_ctx->plane_res.scl_data.viewport; ··· 2341 2336 program_all_pipe_in_tree(dc, top_pipe_to_program, context); 2342 2337 2343 2338 dcn10_pipe_control_lock(dc, top_pipe_to_program, false); 2339 + 2340 + if (top_pipe_to_program->plane_state && 2341 + top_pipe_to_program->plane_state->update_flags.bits.full_update) 2342 + for (i = 0; i < dc->res_pool->pipe_count; i++) { 2343 + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 2344 + 2345 + /* Skip inactive pipes and ones already updated */ 2346 + if (!pipe_ctx->stream || pipe_ctx->stream == stream) 2347 + continue; 2348 + 2349 + pipe_ctx->stream_res.tg->funcs->lock(pipe_ctx->stream_res.tg); 2350 + 2351 + pipe_ctx->plane_res.hubp->funcs->hubp_setup_interdependent( 2352 + pipe_ctx->plane_res.hubp, 2353 + &pipe_ctx->dlg_regs, 2354 + &pipe_ctx->ttu_regs); 2355 + } 2356 + 2357 + for (i = 0; i < dc->res_pool->pipe_count; i++) { 2358 + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 2359 + 2360 + if (!pipe_ctx->stream || pipe_ctx->stream == stream) 2361 + continue; 2362 + 2363 + dcn10_pipe_control_lock(dc, pipe_ctx, false); 2364 + } 2344 2365 2345 2366 if (num_planes == 0) 2346 2367 false_optc_underflow_wa(dc, stream, tg); ··· 2741 2710 .set_avmute = dce110_set_avmute, 2742 2711 .log_hw_state = dcn10_log_hw_state, 2743 2712 .get_hw_state = dcn10_get_hw_state, 2713 + .clear_status_bits = dcn10_clear_status_bits, 2744 2714 .wait_for_mpcc_disconnect = dcn10_wait_for_mpcc_disconnect, 2745 2715 .edp_backlight_control = hwss_edp_backlight_control, 2746 2716 .edp_power_control = hwss_edp_power_control,
+10
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h
··· 51 51 char *pBuf, unsigned int bufSize, 52 52 unsigned int mask); 53 53 54 + void dcn10_clear_status_bits(struct dc *dc, unsigned int mask); 55 + 54 56 bool is_lower_pipe_tree_visible(struct pipe_ctx *pipe_ctx); 55 57 56 58 bool is_upper_pipe_tree_visible(struct pipe_ctx *pipe_ctx); ··· 62 60 void dcn10_program_pte_vm(struct dce_hwseq *hws, struct hubp *hubp); 63 61 64 62 void set_hdr_multiplier(struct pipe_ctx *pipe_ctx); 63 + 64 + void dcn10_get_surface_visual_confirm_color( 65 + const struct pipe_ctx *pipe_ctx, 66 + struct tg_color *color); 67 + 68 + void dcn10_get_hdr_visual_confirm_color( 69 + struct pipe_ctx *pipe_ctx, 70 + struct tg_color *color); 65 71 66 72 void update_dchubp_dpp( 67 73 struct dc *dc,
+53 -6
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer_debug.c
··· 454 454 455 455 remaining_buffer -= chars_printed; 456 456 pBuf += chars_printed; 457 - 458 - // Clear underflow for debug purposes 459 - // We want to keep underflow sticky bit on for the longevity tests outside of test environment. 460 - // This function is called only from Windows or Diags test environment, hence it's safe to clear 461 - // it from here without affecting the original intent. 462 - tg->funcs->clear_optc_underflow(tg); 463 457 } 464 458 } 465 459 ··· 476 482 dc->current_state->bw.dcn.clk.socclk_khz); 477 483 478 484 return chars_printed; 485 + } 486 + 487 + static void dcn10_clear_otpc_underflow(struct dc *dc) 488 + { 489 + struct resource_pool *pool = dc->res_pool; 490 + int i; 491 + 492 + for (i = 0; i < pool->timing_generator_count; i++) { 493 + struct timing_generator *tg = pool->timing_generators[i]; 494 + struct dcn_otg_state s = {0}; 495 + 496 + optc1_read_otg_state(DCN10TG_FROM_TG(tg), &s); 497 + 498 + if (s.otg_enabled & 1) 499 + tg->funcs->clear_optc_underflow(tg); 500 + } 501 + } 502 + 503 + static void dcn10_clear_hubp_underflow(struct dc *dc) 504 + { 505 + struct resource_pool *pool = dc->res_pool; 506 + int i; 507 + 508 + for (i = 0; i < pool->pipe_count; i++) { 509 + struct hubp *hubp = pool->hubps[i]; 510 + struct dcn_hubp_state *s = &(TO_DCN10_HUBP(hubp)->state); 511 + 512 + hubp->funcs->hubp_read_state(hubp); 513 + 514 + if (!s->blank_en) 515 + hubp->funcs->hubp_clear_underflow(hubp); 516 + } 517 + } 518 + 519 + void dcn10_clear_status_bits(struct dc *dc, unsigned int mask) 520 + { 521 + /* 522 + * Mask Format 523 + * Bit 0 - 31: Status bit to clear 524 + * 525 + * Mask = 0x0 means clear all status bits 526 + */ 527 + const unsigned int DC_HW_STATE_MASK_HUBP_UNDERFLOW = 0x1; 528 + const unsigned int DC_HW_STATE_MASK_OTPC_UNDERFLOW = 0x2; 529 + 530 + if (mask == 0x0) 531 + mask = 0xFFFFFFFF; 532 + 533 + if (mask & DC_HW_STATE_MASK_HUBP_UNDERFLOW) 534 + dcn10_clear_hubp_underflow(dc); 535 + 536 + if (mask & DC_HW_STATE_MASK_OTPC_UNDERFLOW) 537 + dcn10_clear_otpc_underflow(dc); 479 538 } 480 539 481 540 void dcn10_get_hw_state(struct dc *dc, char *pBuf, unsigned int bufSize, unsigned int mask)
+16 -12
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c
··· 335 335 /* Enable stereo - only when we need to pack 3D frame. Other types 336 336 * of stereo handled in explicit call 337 337 */ 338 - h_div_2 = (dc_crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) ? 339 - 1 : 0; 340 338 339 + h_div_2 = optc1_is_two_pixels_per_containter(&patched_crtc_timing); 341 340 REG_UPDATE(OTG_H_TIMING_CNTL, 342 341 OTG_H_TIMING_DIV_BY2, h_div_2); 343 342 ··· 359 360 static void optc1_unblank_crtc(struct timing_generator *optc) 360 361 { 361 362 struct optc *optc1 = DCN10TG_FROM_TG(optc); 362 - uint32_t vertical_interrupt_enable = 0; 363 - 364 - REG_GET(OTG_VERTICAL_INTERRUPT2_CONTROL, 365 - OTG_VERTICAL_INTERRUPT2_INT_ENABLE, &vertical_interrupt_enable); 366 - 367 - /* temporary work around for vertical interrupt, once vertical interrupt enabled, 368 - * this check will be removed. 369 - */ 370 - if (vertical_interrupt_enable) 371 - optc1_set_blank_data_double_buffer(optc, true); 372 363 373 364 REG_UPDATE_2(OTG_BLANK_CONTROL, 374 365 OTG_BLANK_DATA_EN, 0, 375 366 OTG_BLANK_DE_MODE, 0); 367 + 368 + /* W/A for automated testing 369 + * Automated testing will fail underflow test as there 370 + * sporadic underflows which occur during the optc blank 371 + * sequence. As a w/a, clear underflow on unblank. 372 + * This prevents the failure, but will not mask actual 373 + * underflow that affect real use cases. 374 + */ 375 + optc1_clear_optc_underflow(optc); 376 376 } 377 377 378 378 /** ··· 1420 1422 optc1->min_h_sync_width = 8; 1421 1423 optc1->min_v_sync_width = 1; 1422 1424 } 1425 + 1426 + bool optc1_is_two_pixels_per_containter(const struct dc_crtc_timing *timing) 1427 + { 1428 + return timing->pixel_encoding == PIXEL_ENCODING_YCBCR420; 1429 + } 1430 +
+2
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h
··· 565 565 bool optc1_get_crc(struct timing_generator *optc, 566 566 uint32_t *r_cr, uint32_t *g_y, uint32_t *b_cb); 567 567 568 + bool optc1_is_two_pixels_per_containter(const struct dc_crtc_timing *timing); 569 + 568 570 #endif /* __DC_TIMING_GENERATOR_DCN10_H__ */
-3
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c
··· 766 766 struct stream_encoder *enc) 767 767 { 768 768 struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); 769 - uint32_t retries = 0; 770 769 uint32_t reg1 = 0; 771 770 uint32_t max_retries = DP_BLANK_MAX_RETRY * 10; 772 771 ··· 801 802 REG_WAIT(DP_VID_STREAM_CNTL, DP_VID_STREAM_STATUS, 802 803 0, 803 804 10, max_retries); 804 - 805 - ASSERT(retries <= max_retries); 806 805 807 806 /* Tell the DP encoder to ignore timing from CRTC, must be done after 808 807 * the polling. If we set DP_STEER_FIFO_RESET before DP stream blank is
+7
drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h
··· 32 32 DMCU_RUNNING = 1 33 33 }; 34 34 35 + struct dmcu_version { 36 + unsigned int date; 37 + unsigned int month; 38 + unsigned int year; 39 + unsigned int interface_version; 40 + }; 41 + 35 42 struct dmcu { 36 43 struct dc_context *ctx; 37 44 const struct dmcu_funcs *funcs;
+6
drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h
··· 63 63 struct _vcs_dpi_display_rq_regs_st *rq_regs, 64 64 struct _vcs_dpi_display_pipe_dest_params_st *pipe_dest); 65 65 66 + void (*hubp_setup_interdependent)( 67 + struct hubp *hubp, 68 + struct _vcs_dpi_display_dlg_regs_st *dlg_regs, 69 + struct _vcs_dpi_display_ttu_regs_st *ttu_regs); 70 + 66 71 void (*dcc_control)(struct hubp *hubp, bool enable, 67 72 bool independent_64b_blks); 68 73 void (*mem_program_viewport)( ··· 126 121 void (*hubp_clk_cntl)(struct hubp *hubp, bool enable); 127 122 void (*hubp_vtg_sel)(struct hubp *hubp, uint32_t otg_inst); 128 123 void (*hubp_read_state)(struct hubp *hubp); 124 + void (*hubp_clear_underflow)(struct hubp *hubp); 129 125 void (*hubp_disable_control)(struct hubp *hubp, bool disable_hubp); 130 126 unsigned int (*hubp_get_underflow_status)(struct hubp *hubp); 131 127
+1
drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h
··· 200 200 void (*log_hw_state)(struct dc *dc, 201 201 struct dc_log_buffer_ctx *log_ctx); 202 202 void (*get_hw_state)(struct dc *dc, char *pBuf, unsigned int bufSize, unsigned int mask); 203 + void (*clear_status_bits)(struct dc *dc, unsigned int mask); 203 204 204 205 void (*wait_for_mpcc_disconnect)(struct dc *dc, 205 206 struct resource_pool *res_pool,
+11 -5
drivers/gpu/drm/amd/display/modules/color/color_gamma.c
··· 813 813 const struct hw_x_point *coord_x = coordinate_x; 814 814 struct fixed31_32 scaledX = dc_fixpt_zero; 815 815 struct fixed31_32 scaledX1 = dc_fixpt_zero; 816 - struct fixed31_32 max_display = dc_fixpt_from_int(fs_params->max_display); 817 - struct fixed31_32 min_display = dc_fixpt_from_fraction(fs_params->min_display, 10000); 818 - struct fixed31_32 max_content = dc_fixpt_from_int(fs_params->max_content); 819 - struct fixed31_32 min_content = dc_fixpt_from_fraction(fs_params->min_content, 10000); 816 + struct fixed31_32 max_display; 817 + struct fixed31_32 min_display; 818 + struct fixed31_32 max_content; 819 + struct fixed31_32 min_content; 820 820 struct fixed31_32 clip = dc_fixpt_one; 821 821 struct fixed31_32 output; 822 822 bool use_eetf = false; 823 823 bool is_clipped = false; 824 - struct fixed31_32 sdr_white_level = dc_fixpt_from_int(fs_params->sdr_white_level); 824 + struct fixed31_32 sdr_white_level; 825 825 826 826 if (fs_params == NULL || fs_params->max_content == 0 || 827 827 fs_params->max_display == 0) 828 828 return false; 829 + 830 + max_display = dc_fixpt_from_int(fs_params->max_display); 831 + min_display = dc_fixpt_from_fraction(fs_params->min_display, 10000); 832 + max_content = dc_fixpt_from_int(fs_params->max_content); 833 + min_content = dc_fixpt_from_fraction(fs_params->min_content, 10000); 834 + sdr_white_level = dc_fixpt_from_int(fs_params->sdr_white_level); 829 835 830 836 if (fs_params->min_display > 1000) // cap at 0.1 at the bottom 831 837 min_display = dc_fixpt_from_fraction(1, 10);
+31
drivers/gpu/drm/amd/display/modules/power/Makefile
··· 1 + # 2 + # Copyright 2017 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 + # Makefile for the 'power' sub-module of DAL. 24 + # 25 + 26 + MOD_POWER = power_helpers.o 27 + 28 + AMD_DAL_MOD_POWER = $(addprefix $(AMDDALPATH)/modules/power/,$(MOD_POWER)) 29 + #$(info ************ DAL POWER MODULE MAKEFILE ************) 30 + 31 + AMD_DISPLAY_FILES += $(AMD_DAL_MOD_POWER)
+326
drivers/gpu/drm/amd/display/modules/power/power_helpers.c
··· 1 + /* Copyright 2018 Advanced Micro Devices, Inc. 2 + * 3 + * Permission is hereby granted, free of charge, to any person obtaining a 4 + * copy of this software and associated documentation files (the "Software"), 5 + * to deal in the Software without restriction, including without limitation 6 + * the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 + * and/or sell copies of the Software, and to permit persons to whom the 8 + * Software is furnished to do so, subject to the following conditions: 9 + * 10 + * The above copyright notice and this permission notice shall be included in 11 + * all copies or substantial portions of the Software. 12 + * 13 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 17 + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 18 + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 19 + * OTHER DEALINGS IN THE SOFTWARE. 20 + * 21 + * Authors: AMD 22 + * 23 + */ 24 + 25 + #include "power_helpers.h" 26 + #include "dc/inc/hw/dmcu.h" 27 + 28 + #define DIV_ROUNDUP(a, b) (((a)+((b)/2))/(b)) 29 + 30 + /* Possible Min Reduction config from least aggressive to most aggressive 31 + * 0 1 2 3 4 5 6 7 8 9 10 11 12 32 + * 100 98.0 94.1 94.1 85.1 80.3 75.3 69.4 60.0 57.6 50.2 49.8 40.0 % 33 + */ 34 + static const unsigned char min_reduction_table[13] = { 35 + 0xff, 0xfa, 0xf0, 0xf0, 0xd9, 0xcd, 0xc0, 0xb1, 0x99, 0x93, 0x80, 0x82, 0x66}; 36 + 37 + /* Possible Max Reduction configs from least aggressive to most aggressive 38 + * 0 1 2 3 4 5 6 7 8 9 10 11 12 39 + * 96.1 89.8 85.1 80.3 69.4 64.7 64.7 50.2 39.6 30.2 30.2 30.2 19.6 % 40 + */ 41 + static const unsigned char max_reduction_table[13] = { 42 + 0xf5, 0xe5, 0xd9, 0xcd, 0xb1, 0xa5, 0xa5, 0x80, 0x65, 0x4d, 0x4d, 0x4d, 0x32}; 43 + 44 + /* Predefined ABM configuration sets. We may have different configuration sets 45 + * in order to satisfy different power/quality requirements. 46 + */ 47 + static const unsigned char abm_config[abm_defines_max_config][abm_defines_max_level] = { 48 + /* ABM Level 1, ABM Level 2, ABM Level 3, ABM Level 4 */ 49 + { 2, 5, 7, 8 }, /* Default - Medium aggressiveness */ 50 + { 2, 5, 8, 11 }, /* Alt #1 - Increased aggressiveness */ 51 + { 0, 2, 4, 8 }, /* Alt #2 - Minimal aggressiveness */ 52 + { 3, 6, 10, 12 }, /* Alt #3 - Super aggressiveness */ 53 + }; 54 + 55 + #define NUM_AMBI_LEVEL 5 56 + #define NUM_AGGR_LEVEL 4 57 + #define NUM_POWER_FN_SEGS 8 58 + #define NUM_BL_CURVE_SEGS 16 59 + 60 + /* NOTE: iRAM is 256B in size */ 61 + struct iram_table_v_2 { 62 + /* flags */ 63 + uint16_t flags; /* 0x00 U16 */ 64 + 65 + /* parameters for ABM2.0 algorithm */ 66 + uint8_t min_reduction[NUM_AMBI_LEVEL][NUM_AGGR_LEVEL]; /* 0x02 U0.8 */ 67 + uint8_t max_reduction[NUM_AMBI_LEVEL][NUM_AGGR_LEVEL]; /* 0x16 U0.8 */ 68 + uint8_t bright_pos_gain[NUM_AMBI_LEVEL][NUM_AGGR_LEVEL]; /* 0x2a U2.6 */ 69 + uint8_t bright_neg_gain[NUM_AMBI_LEVEL][NUM_AGGR_LEVEL]; /* 0x3e U2.6 */ 70 + uint8_t dark_pos_gain[NUM_AMBI_LEVEL][NUM_AGGR_LEVEL]; /* 0x52 U2.6 */ 71 + uint8_t dark_neg_gain[NUM_AMBI_LEVEL][NUM_AGGR_LEVEL]; /* 0x66 U2.6 */ 72 + uint8_t iir_curve[NUM_AMBI_LEVEL]; /* 0x7a U0.8 */ 73 + uint8_t deviation_gain; /* 0x7f U0.8 */ 74 + 75 + /* parameters for crgb conversion */ 76 + uint16_t crgb_thresh[NUM_POWER_FN_SEGS]; /* 0x80 U3.13 */ 77 + uint16_t crgb_offset[NUM_POWER_FN_SEGS]; /* 0x90 U1.15 */ 78 + uint16_t crgb_slope[NUM_POWER_FN_SEGS]; /* 0xa0 U4.12 */ 79 + 80 + /* parameters for custom curve */ 81 + /* thresholds for brightness --> backlight */ 82 + uint16_t backlight_thresholds[NUM_BL_CURVE_SEGS]; /* 0xb0 U16.0 */ 83 + /* offsets for brightness --> backlight */ 84 + uint16_t backlight_offsets[NUM_BL_CURVE_SEGS]; /* 0xd0 U16.0 */ 85 + 86 + /* For reading PSR State directly from IRAM */ 87 + uint8_t psr_state; /* 0xf0 */ 88 + uint8_t dmcu_interface_version; /* 0xf1 */ 89 + uint8_t dmcu_date_version_year_b0; /* 0xf2 */ 90 + uint8_t dmcu_date_version_year_b1; /* 0xf3 */ 91 + uint8_t dmcu_date_version_month; /* 0xf4 */ 92 + uint8_t dmcu_date_version_day; /* 0xf5 */ 93 + uint8_t dmcu_state; /* 0xf6 */ 94 + 95 + uint16_t blRampReduction; /* 0xf7 */ 96 + uint16_t blRampStart; /* 0xf9 */ 97 + uint8_t dummy5; /* 0xfb */ 98 + uint8_t dummy6; /* 0xfc */ 99 + uint8_t dummy7; /* 0xfd */ 100 + uint8_t dummy8; /* 0xfe */ 101 + uint8_t dummy9; /* 0xff */ 102 + }; 103 + 104 + static uint16_t backlight_8_to_16(unsigned int backlight_8bit) 105 + { 106 + return (uint16_t)(backlight_8bit * 0x101); 107 + } 108 + 109 + static void fill_backlight_transform_table(struct dmcu_iram_parameters params, 110 + struct iram_table_v_2 *table) 111 + { 112 + unsigned int i; 113 + unsigned int num_entries = NUM_BL_CURVE_SEGS; 114 + unsigned int query_input_8bit; 115 + unsigned int query_output_8bit; 116 + unsigned int lut_index; 117 + 118 + table->backlight_thresholds[0] = 0; 119 + table->backlight_offsets[0] = params.backlight_lut_array[0]; 120 + table->backlight_thresholds[num_entries-1] = 0xFFFF; 121 + table->backlight_offsets[num_entries-1] = 122 + params.backlight_lut_array[params.backlight_lut_array_size - 1]; 123 + 124 + /* Setup all brightness levels between 0% and 100% exclusive 125 + * Fills brightness-to-backlight transform table. Backlight custom curve 126 + * describes transform from brightness to backlight. It will be defined 127 + * as set of thresholds and set of offsets, together, implying 128 + * extrapolation of custom curve into 16 uniformly spanned linear 129 + * segments. Each threshold/offset represented by 16 bit entry in 130 + * format U4.10. 131 + */ 132 + for (i = 1; i+1 < num_entries; i++) { 133 + query_input_8bit = DIV_ROUNDUP((i * 256), num_entries); 134 + 135 + lut_index = (params.backlight_lut_array_size - 1) * i / (num_entries - 1); 136 + ASSERT(lut_index < params.backlight_lut_array_size); 137 + query_output_8bit = params.backlight_lut_array[lut_index] >> 8; 138 + 139 + table->backlight_thresholds[i] = 140 + backlight_8_to_16(query_input_8bit); 141 + table->backlight_offsets[i] = 142 + backlight_8_to_16(query_output_8bit); 143 + } 144 + } 145 + 146 + bool dmcu_load_iram(struct dmcu *dmcu, 147 + struct dmcu_iram_parameters params) 148 + { 149 + struct iram_table_v_2 ram_table; 150 + unsigned int set = params.set; 151 + 152 + if (dmcu == NULL) 153 + return false; 154 + 155 + if (!dmcu->funcs->is_dmcu_initialized(dmcu)) 156 + return true; 157 + 158 + memset(&ram_table, 0, sizeof(ram_table)); 159 + 160 + ram_table.flags = 0x0; 161 + ram_table.deviation_gain = 0xb3; 162 + 163 + ram_table.blRampReduction = 164 + cpu_to_be16(params.backlight_ramping_reduction); 165 + ram_table.blRampStart = 166 + cpu_to_be16(params.backlight_ramping_start); 167 + 168 + ram_table.min_reduction[0][0] = min_reduction_table[abm_config[set][0]]; 169 + ram_table.min_reduction[1][0] = min_reduction_table[abm_config[set][0]]; 170 + ram_table.min_reduction[2][0] = min_reduction_table[abm_config[set][0]]; 171 + ram_table.min_reduction[3][0] = min_reduction_table[abm_config[set][0]]; 172 + ram_table.min_reduction[4][0] = min_reduction_table[abm_config[set][0]]; 173 + ram_table.max_reduction[0][0] = max_reduction_table[abm_config[set][0]]; 174 + ram_table.max_reduction[1][0] = max_reduction_table[abm_config[set][0]]; 175 + ram_table.max_reduction[2][0] = max_reduction_table[abm_config[set][0]]; 176 + ram_table.max_reduction[3][0] = max_reduction_table[abm_config[set][0]]; 177 + ram_table.max_reduction[4][0] = max_reduction_table[abm_config[set][0]]; 178 + 179 + ram_table.min_reduction[0][1] = min_reduction_table[abm_config[set][1]]; 180 + ram_table.min_reduction[1][1] = min_reduction_table[abm_config[set][1]]; 181 + ram_table.min_reduction[2][1] = min_reduction_table[abm_config[set][1]]; 182 + ram_table.min_reduction[3][1] = min_reduction_table[abm_config[set][1]]; 183 + ram_table.min_reduction[4][1] = min_reduction_table[abm_config[set][1]]; 184 + ram_table.max_reduction[0][1] = max_reduction_table[abm_config[set][1]]; 185 + ram_table.max_reduction[1][1] = max_reduction_table[abm_config[set][1]]; 186 + ram_table.max_reduction[2][1] = max_reduction_table[abm_config[set][1]]; 187 + ram_table.max_reduction[3][1] = max_reduction_table[abm_config[set][1]]; 188 + ram_table.max_reduction[4][1] = max_reduction_table[abm_config[set][1]]; 189 + 190 + ram_table.min_reduction[0][2] = min_reduction_table[abm_config[set][2]]; 191 + ram_table.min_reduction[1][2] = min_reduction_table[abm_config[set][2]]; 192 + ram_table.min_reduction[2][2] = min_reduction_table[abm_config[set][2]]; 193 + ram_table.min_reduction[3][2] = min_reduction_table[abm_config[set][2]]; 194 + ram_table.min_reduction[4][2] = min_reduction_table[abm_config[set][2]]; 195 + ram_table.max_reduction[0][2] = max_reduction_table[abm_config[set][2]]; 196 + ram_table.max_reduction[1][2] = max_reduction_table[abm_config[set][2]]; 197 + ram_table.max_reduction[2][2] = max_reduction_table[abm_config[set][2]]; 198 + ram_table.max_reduction[3][2] = max_reduction_table[abm_config[set][2]]; 199 + ram_table.max_reduction[4][2] = max_reduction_table[abm_config[set][2]]; 200 + 201 + ram_table.min_reduction[0][3] = min_reduction_table[abm_config[set][3]]; 202 + ram_table.min_reduction[1][3] = min_reduction_table[abm_config[set][3]]; 203 + ram_table.min_reduction[2][3] = min_reduction_table[abm_config[set][3]]; 204 + ram_table.min_reduction[3][3] = min_reduction_table[abm_config[set][3]]; 205 + ram_table.min_reduction[4][3] = min_reduction_table[abm_config[set][3]]; 206 + ram_table.max_reduction[0][3] = max_reduction_table[abm_config[set][3]]; 207 + ram_table.max_reduction[1][3] = max_reduction_table[abm_config[set][3]]; 208 + ram_table.max_reduction[2][3] = max_reduction_table[abm_config[set][3]]; 209 + ram_table.max_reduction[3][3] = max_reduction_table[abm_config[set][3]]; 210 + ram_table.max_reduction[4][3] = max_reduction_table[abm_config[set][3]]; 211 + 212 + ram_table.bright_pos_gain[0][0] = 0x20; 213 + ram_table.bright_pos_gain[0][1] = 0x20; 214 + ram_table.bright_pos_gain[0][2] = 0x20; 215 + ram_table.bright_pos_gain[0][3] = 0x20; 216 + ram_table.bright_pos_gain[1][0] = 0x20; 217 + ram_table.bright_pos_gain[1][1] = 0x20; 218 + ram_table.bright_pos_gain[1][2] = 0x20; 219 + ram_table.bright_pos_gain[1][3] = 0x20; 220 + ram_table.bright_pos_gain[2][0] = 0x20; 221 + ram_table.bright_pos_gain[2][1] = 0x20; 222 + ram_table.bright_pos_gain[2][2] = 0x20; 223 + ram_table.bright_pos_gain[2][3] = 0x20; 224 + ram_table.bright_pos_gain[3][0] = 0x20; 225 + ram_table.bright_pos_gain[3][1] = 0x20; 226 + ram_table.bright_pos_gain[3][2] = 0x20; 227 + ram_table.bright_pos_gain[3][3] = 0x20; 228 + ram_table.bright_pos_gain[4][0] = 0x20; 229 + ram_table.bright_pos_gain[4][1] = 0x20; 230 + ram_table.bright_pos_gain[4][2] = 0x20; 231 + ram_table.bright_pos_gain[4][3] = 0x20; 232 + ram_table.bright_neg_gain[0][1] = 0x00; 233 + ram_table.bright_neg_gain[0][2] = 0x00; 234 + ram_table.bright_neg_gain[0][3] = 0x00; 235 + ram_table.bright_neg_gain[1][0] = 0x00; 236 + ram_table.bright_neg_gain[1][1] = 0x00; 237 + ram_table.bright_neg_gain[1][2] = 0x00; 238 + ram_table.bright_neg_gain[1][3] = 0x00; 239 + ram_table.bright_neg_gain[2][0] = 0x00; 240 + ram_table.bright_neg_gain[2][1] = 0x00; 241 + ram_table.bright_neg_gain[2][2] = 0x00; 242 + ram_table.bright_neg_gain[2][3] = 0x00; 243 + ram_table.bright_neg_gain[3][0] = 0x00; 244 + ram_table.bright_neg_gain[3][1] = 0x00; 245 + ram_table.bright_neg_gain[3][2] = 0x00; 246 + ram_table.bright_neg_gain[3][3] = 0x00; 247 + ram_table.bright_neg_gain[4][0] = 0x00; 248 + ram_table.bright_neg_gain[4][1] = 0x00; 249 + ram_table.bright_neg_gain[4][2] = 0x00; 250 + ram_table.bright_neg_gain[4][3] = 0x00; 251 + ram_table.dark_pos_gain[0][0] = 0x00; 252 + ram_table.dark_pos_gain[0][1] = 0x00; 253 + ram_table.dark_pos_gain[0][2] = 0x00; 254 + ram_table.dark_pos_gain[0][3] = 0x00; 255 + ram_table.dark_pos_gain[1][0] = 0x00; 256 + ram_table.dark_pos_gain[1][1] = 0x00; 257 + ram_table.dark_pos_gain[1][2] = 0x00; 258 + ram_table.dark_pos_gain[1][3] = 0x00; 259 + ram_table.dark_pos_gain[2][0] = 0x00; 260 + ram_table.dark_pos_gain[2][1] = 0x00; 261 + ram_table.dark_pos_gain[2][2] = 0x00; 262 + ram_table.dark_pos_gain[2][3] = 0x00; 263 + ram_table.dark_pos_gain[3][0] = 0x00; 264 + ram_table.dark_pos_gain[3][1] = 0x00; 265 + ram_table.dark_pos_gain[3][2] = 0x00; 266 + ram_table.dark_pos_gain[3][3] = 0x00; 267 + ram_table.dark_pos_gain[4][0] = 0x00; 268 + ram_table.dark_pos_gain[4][1] = 0x00; 269 + ram_table.dark_pos_gain[4][2] = 0x00; 270 + ram_table.dark_pos_gain[4][3] = 0x00; 271 + ram_table.dark_neg_gain[0][0] = 0x00; 272 + ram_table.dark_neg_gain[0][1] = 0x00; 273 + ram_table.dark_neg_gain[0][2] = 0x00; 274 + ram_table.dark_neg_gain[0][3] = 0x00; 275 + ram_table.dark_neg_gain[1][0] = 0x00; 276 + ram_table.dark_neg_gain[1][1] = 0x00; 277 + ram_table.dark_neg_gain[1][2] = 0x00; 278 + ram_table.dark_neg_gain[1][3] = 0x00; 279 + ram_table.dark_neg_gain[2][0] = 0x00; 280 + ram_table.dark_neg_gain[2][1] = 0x00; 281 + ram_table.dark_neg_gain[2][2] = 0x00; 282 + ram_table.dark_neg_gain[2][3] = 0x00; 283 + ram_table.dark_neg_gain[3][0] = 0x00; 284 + ram_table.dark_neg_gain[3][1] = 0x00; 285 + ram_table.dark_neg_gain[3][2] = 0x00; 286 + ram_table.dark_neg_gain[3][3] = 0x00; 287 + ram_table.dark_neg_gain[4][0] = 0x00; 288 + ram_table.dark_neg_gain[4][1] = 0x00; 289 + ram_table.dark_neg_gain[4][2] = 0x00; 290 + ram_table.dark_neg_gain[4][3] = 0x00; 291 + ram_table.iir_curve[0] = 0x65; 292 + ram_table.iir_curve[1] = 0x65; 293 + ram_table.iir_curve[2] = 0x65; 294 + ram_table.iir_curve[3] = 0x65; 295 + ram_table.iir_curve[4] = 0x65; 296 + ram_table.crgb_thresh[0] = cpu_to_be16(0x13b6); 297 + ram_table.crgb_thresh[1] = cpu_to_be16(0x1648); 298 + ram_table.crgb_thresh[2] = cpu_to_be16(0x18e3); 299 + ram_table.crgb_thresh[3] = cpu_to_be16(0x1b41); 300 + ram_table.crgb_thresh[4] = cpu_to_be16(0x1d46); 301 + ram_table.crgb_thresh[5] = cpu_to_be16(0x1f21); 302 + ram_table.crgb_thresh[6] = cpu_to_be16(0x2167); 303 + ram_table.crgb_thresh[7] = cpu_to_be16(0x2384); 304 + ram_table.crgb_offset[0] = cpu_to_be16(0x2999); 305 + ram_table.crgb_offset[1] = cpu_to_be16(0x3999); 306 + ram_table.crgb_offset[2] = cpu_to_be16(0x4666); 307 + ram_table.crgb_offset[3] = cpu_to_be16(0x5999); 308 + ram_table.crgb_offset[4] = cpu_to_be16(0x6333); 309 + ram_table.crgb_offset[5] = cpu_to_be16(0x7800); 310 + ram_table.crgb_offset[6] = cpu_to_be16(0x8c00); 311 + ram_table.crgb_offset[7] = cpu_to_be16(0xa000); 312 + ram_table.crgb_slope[0] = cpu_to_be16(0x3147); 313 + ram_table.crgb_slope[1] = cpu_to_be16(0x2978); 314 + ram_table.crgb_slope[2] = cpu_to_be16(0x23a2); 315 + ram_table.crgb_slope[3] = cpu_to_be16(0x1f55); 316 + ram_table.crgb_slope[4] = cpu_to_be16(0x1c63); 317 + ram_table.crgb_slope[5] = cpu_to_be16(0x1a0f); 318 + ram_table.crgb_slope[6] = cpu_to_be16(0x178d); 319 + ram_table.crgb_slope[7] = cpu_to_be16(0x15ab); 320 + 321 + fill_backlight_transform_table( 322 + params, &ram_table); 323 + 324 + return dmcu->funcs->load_iram( 325 + dmcu, 0, (char *)(&ram_table), sizeof(ram_table)); 326 + }
+47
drivers/gpu/drm/amd/display/modules/power/power_helpers.h
··· 1 + /* Copyright 2018 Advanced Micro Devices, Inc. 2 + * 3 + * Permission is hereby granted, free of charge, to any person obtaining a 4 + * copy of this software and associated documentation files (the "Software"), 5 + * to deal in the Software without restriction, including without limitation 6 + * the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 + * and/or sell copies of the Software, and to permit persons to whom the 8 + * Software is furnished to do so, subject to the following conditions: 9 + * 10 + * The above copyright notice and this permission notice shall be included in 11 + * all copies or substantial portions of the Software. 12 + * 13 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 17 + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 18 + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 19 + * OTHER DEALINGS IN THE SOFTWARE. 20 + * 21 + * Authors: AMD 22 + * 23 + */ 24 + 25 + #ifndef MODULES_POWER_POWER_HELPERS_H_ 26 + #define MODULES_POWER_POWER_HELPERS_H_ 27 + 28 + #include "dc/inc/hw/dmcu.h" 29 + 30 + 31 + enum abm_defines { 32 + abm_defines_max_level = 4, 33 + abm_defines_max_config = 4, 34 + }; 35 + 36 + struct dmcu_iram_parameters { 37 + unsigned int *backlight_lut_array; 38 + unsigned int backlight_lut_array_size; 39 + unsigned int backlight_ramping_reduction; 40 + unsigned int backlight_ramping_start; 41 + unsigned int set; 42 + }; 43 + 44 + bool dmcu_load_iram(struct dmcu *dmcu, 45 + struct dmcu_iram_parameters params); 46 + 47 + #endif /* MODULES_POWER_POWER_HELPERS_H_ */
+71 -104
drivers/gpu/drm/amd/include/amd_acpi.h
··· 52 52 u8 backlight_level; /* panel backlight level (0-255) */ 53 53 } __packed; 54 54 55 + struct atif_qbtc_arguments { 56 + u16 size; /* structure size in bytes (includes size field) */ 57 + u8 requested_display; /* which display is requested */ 58 + } __packed; 59 + 60 + #define ATIF_QBTC_MAX_DATA_POINTS 99 61 + 62 + struct atif_qbtc_data_point { 63 + u8 luminance; /* luminance in percent */ 64 + u8 ipnut_signal; /* input signal in range 0-255 */ 65 + } __packed; 66 + 67 + struct atif_qbtc_output { 68 + u16 size; /* structure size in bytes (includes size field) */ 69 + u16 flags; /* all zeroes */ 70 + u8 error_code; /* error code */ 71 + u8 ac_level; /* default brightness on AC power */ 72 + u8 dc_level; /* default brightness on DC power */ 73 + u8 min_input_signal; /* max input signal in range 0-255 */ 74 + u8 max_input_signal; /* min input signal in range 0-255 */ 75 + u8 number_of_points; /* number of data points */ 76 + struct atif_qbtc_data_point data_points[ATIF_QBTC_MAX_DATA_POINTS]; 77 + } __packed; 78 + 55 79 #define ATIF_NOTIFY_MASK 0x3 56 80 #define ATIF_NOTIFY_NONE 0 57 81 #define ATIF_NOTIFY_81 1 ··· 150 126 * DWORD - supported functions bit vector 151 127 */ 152 128 /* Notifications mask */ 153 - # define ATIF_DISPLAY_SWITCH_REQUEST_SUPPORTED (1 << 0) 154 - # define ATIF_EXPANSION_MODE_CHANGE_REQUEST_SUPPORTED (1 << 1) 155 129 # define ATIF_THERMAL_STATE_CHANGE_REQUEST_SUPPORTED (1 << 2) 156 130 # define ATIF_FORCED_POWER_STATE_CHANGE_REQUEST_SUPPORTED (1 << 3) 157 131 # define ATIF_SYSTEM_POWER_SOURCE_CHANGE_REQUEST_SUPPORTED (1 << 4) 158 - # define ATIF_DISPLAY_CONF_CHANGE_REQUEST_SUPPORTED (1 << 5) 159 - # define ATIF_PX_GFX_SWITCH_REQUEST_SUPPORTED (1 << 6) 160 132 # define ATIF_PANEL_BRIGHTNESS_CHANGE_REQUEST_SUPPORTED (1 << 7) 161 133 # define ATIF_DGPU_DISPLAY_EVENT_SUPPORTED (1 << 8) 134 + # define ATIF_GPU_PACKAGE_POWER_LIMIT_REQUEST_SUPPORTED (1 << 12) 162 135 /* supported functions vector */ 163 136 # define ATIF_GET_SYSTEM_PARAMETERS_SUPPORTED (1 << 0) 164 137 # define ATIF_GET_SYSTEM_BIOS_REQUESTS_SUPPORTED (1 << 1) 165 - # define ATIF_SELECT_ACTIVE_DISPLAYS_SUPPORTED (1 << 2) 166 - # define ATIF_GET_LID_STATE_SUPPORTED (1 << 3) 167 - # define ATIF_GET_TV_STANDARD_FROM_CMOS_SUPPORTED (1 << 4) 168 - # define ATIF_SET_TV_STANDARD_IN_CMOS_SUPPORTED (1 << 5) 169 - # define ATIF_GET_PANEL_EXPANSION_MODE_FROM_CMOS_SUPPORTED (1 << 6) 170 - # define ATIF_SET_PANEL_EXPANSION_MODE_IN_CMOS_SUPPORTED (1 << 7) 171 138 # define ATIF_TEMPERATURE_CHANGE_NOTIFICATION_SUPPORTED (1 << 12) 172 - # define ATIF_GET_GRAPHICS_DEVICE_TYPES_SUPPORTED (1 << 14) 139 + # define ATIF_QUERY_BACKLIGHT_TRANSFER_CHARACTERISTICS_SUPPORTED (1 << 15) 140 + # define ATIF_READY_TO_UNDOCK_NOTIFICATION_SUPPORTED (1 << 16) 173 141 # define ATIF_GET_EXTERNAL_GPU_INFORMATION_SUPPORTED (1 << 20) 174 142 #define ATIF_FUNCTION_GET_SYSTEM_PARAMETERS 0x1 175 143 /* ARG0: ATIF_FUNCTION_GET_SYSTEM_PARAMETERS ··· 186 170 * n (0xd0-0xd9) is specified in notify command code. 187 171 * bit 2: 188 172 * 1 - lid changes not reported though int10 173 + * bit 3: 174 + * 1 - system bios controls overclocking 175 + * bit 4: 176 + * 1 - enable overclocking 189 177 */ 190 178 #define ATIF_FUNCTION_GET_SYSTEM_BIOS_REQUESTS 0x2 191 179 /* ARG0: ATIF_FUNCTION_GET_SYSTEM_BIOS_REQUESTS ··· 197 177 * OUTPUT: 198 178 * WORD - structure size in bytes (includes size field) 199 179 * DWORD - pending sbios requests 200 - * BYTE - panel expansion mode 180 + * BYTE - reserved (all zeroes) 201 181 * BYTE - thermal state: target gfx controller 202 182 * BYTE - thermal state: state id (0: exit state, non-0: state) 203 183 * BYTE - forced power state: target gfx controller 204 - * BYTE - forced power state: state id 184 + * BYTE - forced power state: state id (0: forced state, non-0: state) 205 185 * BYTE - system power source 206 186 * BYTE - panel backlight level (0-255) 187 + * BYTE - GPU package power limit: target gfx controller 188 + * DWORD - GPU package power limit: value (24:8 fractional format, Watts) 207 189 */ 208 190 /* pending sbios requests */ 209 - # define ATIF_DISPLAY_SWITCH_REQUEST (1 << 0) 210 - # define ATIF_EXPANSION_MODE_CHANGE_REQUEST (1 << 1) 211 191 # define ATIF_THERMAL_STATE_CHANGE_REQUEST (1 << 2) 212 192 # define ATIF_FORCED_POWER_STATE_CHANGE_REQUEST (1 << 3) 213 193 # define ATIF_SYSTEM_POWER_SOURCE_CHANGE_REQUEST (1 << 4) 214 - # define ATIF_DISPLAY_CONF_CHANGE_REQUEST (1 << 5) 215 - # define ATIF_PX_GFX_SWITCH_REQUEST (1 << 6) 216 194 # define ATIF_PANEL_BRIGHTNESS_CHANGE_REQUEST (1 << 7) 217 195 # define ATIF_DGPU_DISPLAY_EVENT (1 << 8) 218 - /* panel expansion mode */ 219 - # define ATIF_PANEL_EXPANSION_DISABLE 0 220 - # define ATIF_PANEL_EXPANSION_FULL 1 221 - # define ATIF_PANEL_EXPANSION_ASPECT 2 196 + # define ATIF_GPU_PACKAGE_POWER_LIMIT_REQUEST (1 << 12) 222 197 /* target gfx controller */ 223 198 # define ATIF_TARGET_GFX_SINGLE 0 224 199 # define ATIF_TARGET_GFX_PX_IGPU 1 ··· 223 208 # define ATIF_POWER_SOURCE_DC 2 224 209 # define ATIF_POWER_SOURCE_RESTRICTED_AC_1 3 225 210 # define ATIF_POWER_SOURCE_RESTRICTED_AC_2 4 226 - #define ATIF_FUNCTION_SELECT_ACTIVE_DISPLAYS 0x3 227 - /* ARG0: ATIF_FUNCTION_SELECT_ACTIVE_DISPLAYS 228 - * ARG1: 229 - * WORD - structure size in bytes (includes size field) 230 - * WORD - selected displays 231 - * WORD - connected displays 232 - * OUTPUT: 233 - * WORD - structure size in bytes (includes size field) 234 - * WORD - selected displays 235 - */ 236 - # define ATIF_LCD1 (1 << 0) 237 - # define ATIF_CRT1 (1 << 1) 238 - # define ATIF_TV (1 << 2) 239 - # define ATIF_DFP1 (1 << 3) 240 - # define ATIF_CRT2 (1 << 4) 241 - # define ATIF_LCD2 (1 << 5) 242 - # define ATIF_DFP2 (1 << 7) 243 - # define ATIF_CV (1 << 8) 244 - # define ATIF_DFP3 (1 << 9) 245 - # define ATIF_DFP4 (1 << 10) 246 - # define ATIF_DFP5 (1 << 11) 247 - # define ATIF_DFP6 (1 << 12) 248 - #define ATIF_FUNCTION_GET_LID_STATE 0x4 249 - /* ARG0: ATIF_FUNCTION_GET_LID_STATE 250 - * ARG1: none 251 - * OUTPUT: 252 - * WORD - structure size in bytes (includes size field) 253 - * BYTE - lid state (0: open, 1: closed) 254 - * 255 - * GET_LID_STATE only works at boot and resume, for general lid 256 - * status, use the kernel provided status 257 - */ 258 - #define ATIF_FUNCTION_GET_TV_STANDARD_FROM_CMOS 0x5 259 - /* ARG0: ATIF_FUNCTION_GET_TV_STANDARD_FROM_CMOS 260 - * ARG1: none 261 - * OUTPUT: 262 - * WORD - structure size in bytes (includes size field) 263 - * BYTE - 0 264 - * BYTE - TV standard 265 - */ 266 - # define ATIF_TV_STD_NTSC 0 267 - # define ATIF_TV_STD_PAL 1 268 - # define ATIF_TV_STD_PALM 2 269 - # define ATIF_TV_STD_PAL60 3 270 - # define ATIF_TV_STD_NTSCJ 4 271 - # define ATIF_TV_STD_PALCN 5 272 - # define ATIF_TV_STD_PALN 6 273 - # define ATIF_TV_STD_SCART_RGB 9 274 - #define ATIF_FUNCTION_SET_TV_STANDARD_IN_CMOS 0x6 275 - /* ARG0: ATIF_FUNCTION_SET_TV_STANDARD_IN_CMOS 276 - * ARG1: 277 - * WORD - structure size in bytes (includes size field) 278 - * BYTE - 0 279 - * BYTE - TV standard 280 - * OUTPUT: none 281 - */ 282 - #define ATIF_FUNCTION_GET_PANEL_EXPANSION_MODE_FROM_CMOS 0x7 283 - /* ARG0: ATIF_FUNCTION_GET_PANEL_EXPANSION_MODE_FROM_CMOS 284 - * ARG1: none 285 - * OUTPUT: 286 - * WORD - structure size in bytes (includes size field) 287 - * BYTE - panel expansion mode 288 - */ 289 - #define ATIF_FUNCTION_SET_PANEL_EXPANSION_MODE_IN_CMOS 0x8 290 - /* ARG0: ATIF_FUNCTION_SET_PANEL_EXPANSION_MODE_IN_CMOS 291 - * ARG1: 292 - * WORD - structure size in bytes (includes size field) 293 - * BYTE - panel expansion mode 294 - * OUTPUT: none 295 - */ 296 211 #define ATIF_FUNCTION_TEMPERATURE_CHANGE_NOTIFICATION 0xD 297 212 /* ARG0: ATIF_FUNCTION_TEMPERATURE_CHANGE_NOTIFICATION 298 213 * ARG1: ··· 231 286 * BYTE - current temperature (degress Celsius) 232 287 * OUTPUT: none 233 288 */ 234 - #define ATIF_FUNCTION_GET_GRAPHICS_DEVICE_TYPES 0xF 235 - /* ARG0: ATIF_FUNCTION_GET_GRAPHICS_DEVICE_TYPES 236 - * ARG1: none 289 + #define ATIF_FUNCTION_QUERY_BRIGHTNESS_TRANSFER_CHARACTERISTICS 0x10 290 + /* ARG0: ATIF_FUNCTION_QUERY_BRIGHTNESS_TRANSFER_CHARACTERISTICS 291 + * ARG1: 292 + * WORD - structure size in bytes (includes size field) 293 + * BYTE - requested display 237 294 * OUTPUT: 238 - * WORD - number of gfx devices 239 - * WORD - device structure size in bytes (excludes device size field) 240 - * DWORD - flags \ 241 - * WORD - bus number } repeated structure 242 - * WORD - device number / 295 + * WORD - structure size in bytes (includes size field) 296 + * WORD - flags (currently all 16 bits are reserved) 297 + * BYTE - error code (on failure, disregard all below fields) 298 + * BYTE - AC level (default brightness in percent when machine has full power) 299 + * BYTE - DC level (default brightness in percent when machine is on battery) 300 + * BYTE - min input signal, in range 0-255, corresponding to 0% backlight 301 + * BYTE - max input signal, in range 0-255, corresponding to 100% backlight 302 + * BYTE - number of reported data points 303 + * BYTE - luminance level in percent \ repeated structure 304 + * BYTE - input signal in range 0-255 / does not have entries for 0% and 100% 243 305 */ 244 - /* flags */ 245 - # define ATIF_PX_REMOVABLE_GRAPHICS_DEVICE (1 << 0) 246 - # define ATIF_XGP_PORT (1 << 1) 247 - # define ATIF_VGA_ENABLED_GRAPHICS_DEVICE (1 << 2) 248 - # define ATIF_XGP_PORT_IN_DOCK (1 << 3) 306 + /* requested display */ 307 + # define ATIF_QBTC_REQUEST_LCD1 0 308 + # define ATIF_QBTC_REQUEST_CRT1 1 309 + # define ATIF_QBTC_REQUEST_DFP1 3 310 + # define ATIF_QBTC_REQUEST_CRT2 4 311 + # define ATIF_QBTC_REQUEST_LCD2 5 312 + # define ATIF_QBTC_REQUEST_DFP2 7 313 + # define ATIF_QBTC_REQUEST_DFP3 9 314 + # define ATIF_QBTC_REQUEST_DFP4 10 315 + # define ATIF_QBTC_REQUEST_DFP5 11 316 + # define ATIF_QBTC_REQUEST_DFP6 12 317 + /* error code */ 318 + # define ATIF_QBTC_ERROR_CODE_SUCCESS 0 319 + # define ATIF_QBTC_ERROR_CODE_FAILURE 1 320 + # define ATIF_QBTC_ERROR_CODE_DEVICE_NOT_SUPPORTED 2 321 + #define ATIF_FUNCTION_READY_TO_UNDOCK_NOTIFICATION 0x11 322 + /* ARG0: ATIF_FUNCTION_READY_TO_UNDOCK_NOTIFICATION 323 + * ARG1: none 324 + * OUTPUT: none 325 + */ 249 326 #define ATIF_FUNCTION_GET_EXTERNAL_GPU_INFORMATION 0x15 250 327 /* ARG0: ATIF_FUNCTION_GET_EXTERNAL_GPU_INFORMATION 251 328 * ARG1: none
+26 -26
drivers/gpu/drm/amd/powerplay/amd_powerplay.c
··· 300 300 return -EINVAL; 301 301 302 302 if (hwmgr->hwmgr_func->update_clock_gatings == NULL) { 303 - pr_info("%s was not implemented.\n", __func__); 303 + pr_info_ratelimited("%s was not implemented.\n", __func__); 304 304 return 0; 305 305 } 306 306 ··· 387 387 return 0; 388 388 389 389 if (hwmgr->hwmgr_func->get_sclk == NULL) { 390 - pr_info("%s was not implemented.\n", __func__); 390 + pr_info_ratelimited("%s was not implemented.\n", __func__); 391 391 return 0; 392 392 } 393 393 mutex_lock(&hwmgr->smu_lock); ··· 405 405 return 0; 406 406 407 407 if (hwmgr->hwmgr_func->get_mclk == NULL) { 408 - pr_info("%s was not implemented.\n", __func__); 408 + pr_info_ratelimited("%s was not implemented.\n", __func__); 409 409 return 0; 410 410 } 411 411 mutex_lock(&hwmgr->smu_lock); ··· 422 422 return; 423 423 424 424 if (hwmgr->hwmgr_func->powergate_vce == NULL) { 425 - pr_info("%s was not implemented.\n", __func__); 425 + pr_info_ratelimited("%s was not implemented.\n", __func__); 426 426 return; 427 427 } 428 428 mutex_lock(&hwmgr->smu_lock); ··· 438 438 return; 439 439 440 440 if (hwmgr->hwmgr_func->powergate_uvd == NULL) { 441 - pr_info("%s was not implemented.\n", __func__); 441 + pr_info_ratelimited("%s was not implemented.\n", __func__); 442 442 return; 443 443 } 444 444 mutex_lock(&hwmgr->smu_lock); ··· 505 505 return; 506 506 507 507 if (hwmgr->hwmgr_func->set_fan_control_mode == NULL) { 508 - pr_info("%s was not implemented.\n", __func__); 508 + pr_info_ratelimited("%s was not implemented.\n", __func__); 509 509 return; 510 510 } 511 511 mutex_lock(&hwmgr->smu_lock); ··· 522 522 return 0; 523 523 524 524 if (hwmgr->hwmgr_func->get_fan_control_mode == NULL) { 525 - pr_info("%s was not implemented.\n", __func__); 525 + pr_info_ratelimited("%s was not implemented.\n", __func__); 526 526 return 0; 527 527 } 528 528 mutex_lock(&hwmgr->smu_lock); ··· 540 540 return -EINVAL; 541 541 542 542 if (hwmgr->hwmgr_func->set_fan_speed_percent == NULL) { 543 - pr_info("%s was not implemented.\n", __func__); 543 + pr_info_ratelimited("%s was not implemented.\n", __func__); 544 544 return 0; 545 545 } 546 546 mutex_lock(&hwmgr->smu_lock); ··· 558 558 return -EINVAL; 559 559 560 560 if (hwmgr->hwmgr_func->get_fan_speed_percent == NULL) { 561 - pr_info("%s was not implemented.\n", __func__); 561 + pr_info_ratelimited("%s was not implemented.\n", __func__); 562 562 return 0; 563 563 } 564 564 ··· 594 594 return -EINVAL; 595 595 596 596 if (hwmgr->hwmgr_func->set_fan_speed_rpm == NULL) { 597 - pr_info("%s was not implemented.\n", __func__); 597 + pr_info_ratelimited("%s was not implemented.\n", __func__); 598 598 return 0; 599 599 } 600 600 mutex_lock(&hwmgr->smu_lock); ··· 720 720 return -EINVAL; 721 721 722 722 if (hwmgr->hwmgr_func->force_clock_level == NULL) { 723 - pr_info("%s was not implemented.\n", __func__); 723 + pr_info_ratelimited("%s was not implemented.\n", __func__); 724 724 return 0; 725 725 } 726 726 ··· 745 745 return -EINVAL; 746 746 747 747 if (hwmgr->hwmgr_func->print_clock_levels == NULL) { 748 - pr_info("%s was not implemented.\n", __func__); 748 + pr_info_ratelimited("%s was not implemented.\n", __func__); 749 749 return 0; 750 750 } 751 751 mutex_lock(&hwmgr->smu_lock); ··· 763 763 return -EINVAL; 764 764 765 765 if (hwmgr->hwmgr_func->get_sclk_od == NULL) { 766 - pr_info("%s was not implemented.\n", __func__); 766 + pr_info_ratelimited("%s was not implemented.\n", __func__); 767 767 return 0; 768 768 } 769 769 mutex_lock(&hwmgr->smu_lock); ··· 781 781 return -EINVAL; 782 782 783 783 if (hwmgr->hwmgr_func->set_sclk_od == NULL) { 784 - pr_info("%s was not implemented.\n", __func__); 784 + pr_info_ratelimited("%s was not implemented.\n", __func__); 785 785 return 0; 786 786 } 787 787 ··· 800 800 return -EINVAL; 801 801 802 802 if (hwmgr->hwmgr_func->get_mclk_od == NULL) { 803 - pr_info("%s was not implemented.\n", __func__); 803 + pr_info_ratelimited("%s was not implemented.\n", __func__); 804 804 return 0; 805 805 } 806 806 mutex_lock(&hwmgr->smu_lock); ··· 818 818 return -EINVAL; 819 819 820 820 if (hwmgr->hwmgr_func->set_mclk_od == NULL) { 821 - pr_info("%s was not implemented.\n", __func__); 821 + pr_info_ratelimited("%s was not implemented.\n", __func__); 822 822 return 0; 823 823 } 824 824 mutex_lock(&hwmgr->smu_lock); ··· 878 878 return -EINVAL; 879 879 880 880 if (hwmgr->hwmgr_func->get_power_profile_mode == NULL) { 881 - pr_info("%s was not implemented.\n", __func__); 881 + pr_info_ratelimited("%s was not implemented.\n", __func__); 882 882 return snprintf(buf, PAGE_SIZE, "\n"); 883 883 } 884 884 ··· 894 894 return ret; 895 895 896 896 if (hwmgr->hwmgr_func->set_power_profile_mode == NULL) { 897 - pr_info("%s was not implemented.\n", __func__); 897 + pr_info_ratelimited("%s was not implemented.\n", __func__); 898 898 return ret; 899 899 } 900 900 ··· 917 917 return -EINVAL; 918 918 919 919 if (hwmgr->hwmgr_func->odn_edit_dpm_table == NULL) { 920 - pr_info("%s was not implemented.\n", __func__); 920 + pr_info_ratelimited("%s was not implemented.\n", __func__); 921 921 return -EINVAL; 922 922 } 923 923 ··· 935 935 return -EINVAL; 936 936 937 937 if (hwmgr->hwmgr_func->set_power_profile_mode == NULL) { 938 - pr_info("%s was not implemented.\n", __func__); 938 + pr_info_ratelimited("%s was not implemented.\n", __func__); 939 939 return -EINVAL; 940 940 } 941 941 ··· 972 972 return -EINVAL; 973 973 974 974 if (hwmgr->hwmgr_func->set_power_limit == NULL) { 975 - pr_info("%s was not implemented.\n", __func__); 975 + pr_info_ratelimited("%s was not implemented.\n", __func__); 976 976 return -EINVAL; 977 977 } 978 978 ··· 1212 1212 return -EINVAL; 1213 1213 1214 1214 if (hwmgr->hwmgr_func->powergate_mmhub == NULL) { 1215 - pr_info("%s was not implemented.\n", __func__); 1215 + pr_info_ratelimited("%s was not implemented.\n", __func__); 1216 1216 return 0; 1217 1217 } 1218 1218 ··· 1227 1227 return 0; 1228 1228 1229 1229 if (hwmgr->hwmgr_func->powergate_gfx == NULL) { 1230 - pr_info("%s was not implemented.\n", __func__); 1230 + pr_info_ratelimited("%s was not implemented.\n", __func__); 1231 1231 return 0; 1232 1232 } 1233 1233 ··· 1242 1242 return; 1243 1243 1244 1244 if (hwmgr->hwmgr_func->powergate_acp == NULL) { 1245 - pr_info("%s was not implemented.\n", __func__); 1245 + pr_info_ratelimited("%s was not implemented.\n", __func__); 1246 1246 return; 1247 1247 } 1248 1248 ··· 1257 1257 return; 1258 1258 1259 1259 if (hwmgr->hwmgr_func->powergate_sdma == NULL) { 1260 - pr_info("%s was not implemented.\n", __func__); 1260 + pr_info_ratelimited("%s was not implemented.\n", __func__); 1261 1261 return; 1262 1262 } 1263 1263 ··· 1303 1303 return -EINVAL; 1304 1304 1305 1305 if (hwmgr->hwmgr_func->smus_notify_pwe == NULL) { 1306 - pr_info("%s was not implemented.\n", __func__); 1306 + pr_info_ratelimited("%s was not implemented.\n", __func__); 1307 1307 return -EINVAL;; 1308 1308 } 1309 1309
+3 -3
drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c
··· 269 269 hwmgr->dyn_state.mvdd_dependency_on_mclk); 270 270 271 271 PP_ASSERT_WITH_CODE((0 == result), 272 - "Failed to retrieve SVI2 MVDD table from dependancy table.", 272 + "Failed to retrieve SVI2 MVDD table from dependency table.", 273 273 return result;); 274 274 } 275 275 ··· 288 288 result = phm_get_svi2_voltage_table_v0(&(data->vddci_voltage_table), 289 289 hwmgr->dyn_state.vddci_dependency_on_mclk); 290 290 PP_ASSERT_WITH_CODE((0 == result), 291 - "Failed to retrieve SVI2 VDDCI table from dependancy table.", 291 + "Failed to retrieve SVI2 VDDCI table from dependency table.", 292 292 return result); 293 293 } 294 294 ··· 317 317 table_info->vddc_lookup_table); 318 318 319 319 PP_ASSERT_WITH_CODE((0 == result), 320 - "Failed to retrieve SVI2 VDDC table from dependancy table.", return result;); 320 + "Failed to retrieve SVI2 VDDC table from dependency table.", return result;); 321 321 } 322 322 323 323 tmp = smum_get_mac_definition(hwmgr, SMU_MAX_LEVELS_VDDC);
+2 -4
drivers/gpu/drm/amd/powerplay/hwmgr/smu8_hwmgr.c
··· 1228 1228 1229 1229 static int smu8_dpm_powerdown_uvd(struct pp_hwmgr *hwmgr) 1230 1230 { 1231 - if (PP_CAP(PHM_PlatformCaps_UVDPowerGating)) { 1232 - smu8_nbdpm_pstate_enable_disable(hwmgr, true, true); 1231 + if (PP_CAP(PHM_PlatformCaps_UVDPowerGating)) 1233 1232 return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_UVDPowerOFF); 1234 - } 1235 1233 return 0; 1236 1234 } 1237 1235 1238 1236 static int smu8_dpm_powerup_uvd(struct pp_hwmgr *hwmgr) 1239 1237 { 1240 1238 if (PP_CAP(PHM_PlatformCaps_UVDPowerGating)) { 1241 - smu8_nbdpm_pstate_enable_disable(hwmgr, false, true); 1242 1239 return smum_send_msg_to_smc_with_parameter( 1243 1240 hwmgr, 1244 1241 PPSMC_MSG_UVDPowerON, ··· 1992 1995 .power_state_set = smu8_set_power_state_tasks, 1993 1996 .dynamic_state_management_disable = smu8_disable_dpm_tasks, 1994 1997 .notify_cac_buffer_info = smu8_notify_cac_buffer_info, 1998 + .update_nbdpm_pstate = smu8_nbdpm_pstate_enable_disable, 1995 1999 .get_thermal_temperature_range = smu8_get_thermal_temperature_range, 1996 2000 }; 1997 2001
+3
drivers/gpu/drm/amd/powerplay/inc/hwmgr.h
··· 317 317 uint32_t mc_addr_low, 318 318 uint32_t mc_addr_hi, 319 319 uint32_t size); 320 + int (*update_nbdpm_pstate)(struct pp_hwmgr *hwmgr, 321 + bool enable, 322 + bool lock); 320 323 int (*get_thermal_temperature_range)(struct pp_hwmgr *hwmgr, 321 324 struct PP_TemperatureRange *range); 322 325 int (*get_power_profile_mode)(struct pp_hwmgr *hwmgr, char *buf);
+4
drivers/gpu/drm/drm_atomic_uapi.c
··· 433 433 ret = drm_atomic_set_mode_prop_for_crtc(state, mode); 434 434 drm_property_blob_put(mode); 435 435 return ret; 436 + } else if (property == config->prop_vrr_enabled) { 437 + state->vrr_enabled = val; 436 438 } else if (property == config->degamma_lut_property) { 437 439 ret = drm_atomic_replace_property_blob_from_id(dev, 438 440 &state->degamma_lut, ··· 493 491 *val = state->active; 494 492 else if (property == config->prop_mode_id) 495 493 *val = (state->mode_blob) ? state->mode_blob->base.id : 0; 494 + else if (property == config->prop_vrr_enabled) 495 + *val = state->vrr_enabled; 496 496 else if (property == config->degamma_lut_property) 497 497 *val = (state->degamma_lut) ? state->degamma_lut->base.id : 0; 498 498 else if (property == config->ctm_property)
+117
drivers/gpu/drm/drm_connector.c
··· 1279 1279 EXPORT_SYMBOL(drm_mode_create_scaling_mode_property); 1280 1280 1281 1281 /** 1282 + * DOC: Variable refresh properties 1283 + * 1284 + * Variable refresh rate capable displays can dynamically adjust their 1285 + * refresh rate by extending the duration of their vertical front porch 1286 + * until page flip or timeout occurs. This can reduce or remove stuttering 1287 + * and latency in scenarios where the page flip does not align with the 1288 + * vblank interval. 1289 + * 1290 + * An example scenario would be an application flipping at a constant rate 1291 + * of 48Hz on a 60Hz display. The page flip will frequently miss the vblank 1292 + * interval and the same contents will be displayed twice. This can be 1293 + * observed as stuttering for content with motion. 1294 + * 1295 + * If variable refresh rate was active on a display that supported a 1296 + * variable refresh range from 35Hz to 60Hz no stuttering would be observable 1297 + * for the example scenario. The minimum supported variable refresh rate of 1298 + * 35Hz is below the page flip frequency and the vertical front porch can 1299 + * be extended until the page flip occurs. The vblank interval will be 1300 + * directly aligned to the page flip rate. 1301 + * 1302 + * Not all userspace content is suitable for use with variable refresh rate. 1303 + * Large and frequent changes in vertical front porch duration may worsen 1304 + * perceived stuttering for input sensitive applications. 1305 + * 1306 + * Panel brightness will also vary with vertical front porch duration. Some 1307 + * panels may have noticeable differences in brightness between the minimum 1308 + * vertical front porch duration and the maximum vertical front porch duration. 1309 + * Large and frequent changes in vertical front porch duration may produce 1310 + * observable flickering for such panels. 1311 + * 1312 + * Userspace control for variable refresh rate is supported via properties 1313 + * on the &drm_connector and &drm_crtc objects. 1314 + * 1315 + * "vrr_capable": 1316 + * Optional &drm_connector boolean property that drivers should attach 1317 + * with drm_connector_attach_vrr_capable_property() on connectors that 1318 + * could support variable refresh rates. Drivers should update the 1319 + * property value by calling drm_connector_set_vrr_capable_property(). 1320 + * 1321 + * Absence of the property should indicate absence of support. 1322 + * 1323 + * "vrr_enabled": 1324 + * Default &drm_crtc boolean property that notifies the driver that the 1325 + * content on the CRTC is suitable for variable refresh rate presentation. 1326 + * The driver will take this property as a hint to enable variable 1327 + * refresh rate support if the receiver supports it, ie. if the 1328 + * "vrr_capable" property is true on the &drm_connector object. The 1329 + * vertical front porch duration will be extended until page-flip or 1330 + * timeout when enabled. 1331 + * 1332 + * The minimum vertical front porch duration is defined as the vertical 1333 + * front porch duration for the current mode. 1334 + * 1335 + * The maximum vertical front porch duration is greater than or equal to 1336 + * the minimum vertical front porch duration. The duration is derived 1337 + * from the minimum supported variable refresh rate for the connector. 1338 + * 1339 + * The driver may place further restrictions within these minimum 1340 + * and maximum bounds. 1341 + * 1342 + * The semantics for the vertical blank timestamp differ when 1343 + * variable refresh rate is active. The vertical blank timestamp 1344 + * is defined to be an estimate using the current mode's fixed 1345 + * refresh rate timings. The semantics for the page-flip event 1346 + * timestamp remain the same. 1347 + */ 1348 + 1349 + /** 1350 + * drm_connector_attach_vrr_capable_property - creates the 1351 + * vrr_capable property 1352 + * @connector: connector to create the vrr_capable property on. 1353 + * 1354 + * This is used by atomic drivers to add support for querying 1355 + * variable refresh rate capability for a connector. 1356 + * 1357 + * Returns: 1358 + * Zero on success, negative errono on failure. 1359 + */ 1360 + int drm_connector_attach_vrr_capable_property( 1361 + struct drm_connector *connector) 1362 + { 1363 + struct drm_device *dev = connector->dev; 1364 + struct drm_property *prop; 1365 + 1366 + if (!connector->vrr_capable_property) { 1367 + prop = drm_property_create_bool(dev, DRM_MODE_PROP_IMMUTABLE, 1368 + "vrr_capable"); 1369 + if (!prop) 1370 + return -ENOMEM; 1371 + 1372 + connector->vrr_capable_property = prop; 1373 + drm_object_attach_property(&connector->base, prop, 0); 1374 + } 1375 + 1376 + return 0; 1377 + } 1378 + EXPORT_SYMBOL(drm_connector_attach_vrr_capable_property); 1379 + 1380 + /** 1282 1381 * drm_connector_attach_scaling_mode_property - attach atomic scaling mode property 1283 1382 * @connector: connector to attach scaling mode property on. 1284 1383 * @scaling_mode_mask: or'ed mask of BIT(%DRM_MODE_SCALE_\*). ··· 1738 1639 return 0; 1739 1640 } 1740 1641 EXPORT_SYMBOL(drm_connector_attach_max_bpc_property); 1642 + 1643 + /** 1644 + * drm_connector_set_vrr_capable_property - sets the variable refresh rate 1645 + * capable property for a connector 1646 + * @connector: drm connector 1647 + * @capable: True if the connector is variable refresh rate capable 1648 + * 1649 + * Should be used by atomic drivers to update the indicated support for 1650 + * variable refresh rate over a connector. 1651 + */ 1652 + void drm_connector_set_vrr_capable_property( 1653 + struct drm_connector *connector, bool capable) 1654 + { 1655 + drm_object_property_set_value(&connector->base, 1656 + connector->vrr_capable_property, 1657 + capable); 1658 + } 1659 + EXPORT_SYMBOL(drm_connector_set_vrr_capable_property); 1741 1660 1742 1661 /** 1743 1662 * drm_connector_init_panel_orientation_property -
+2
drivers/gpu/drm/drm_crtc.c
··· 340 340 drm_object_attach_property(&crtc->base, config->prop_mode_id, 0); 341 341 drm_object_attach_property(&crtc->base, 342 342 config->prop_out_fence_ptr, 0); 343 + drm_object_attach_property(&crtc->base, 344 + config->prop_vrr_enabled, 0); 343 345 } 344 346 345 347 return 0;
+6
drivers/gpu/drm/drm_mode_config.c
··· 310 310 return -ENOMEM; 311 311 dev->mode_config.prop_mode_id = prop; 312 312 313 + prop = drm_property_create_bool(dev, 0, 314 + "VRR_ENABLED"); 315 + if (!prop) 316 + return -ENOMEM; 317 + dev->mode_config.prop_vrr_enabled = prop; 318 + 313 319 prop = drm_property_create(dev, 314 320 DRM_MODE_PROP_BLOB, 315 321 "DEGAMMA_LUT", 0);
+1 -1
drivers/gpu/drm/radeon/radeon_vm.c
··· 946 946 bo_va->flags &= ~RADEON_VM_PAGE_WRITEABLE; 947 947 948 948 if (mem) { 949 - addr = mem->start << PAGE_SHIFT; 949 + addr = (u64)mem->start << PAGE_SHIFT; 950 950 if (mem->mem_type != TTM_PL_SYSTEM) { 951 951 bo_va->flags |= RADEON_VM_PAGE_VALID; 952 952 }
+17 -27
drivers/gpu/drm/scheduler/sched_main.c
··· 60 60 61 61 static void drm_sched_process_job(struct dma_fence *f, struct dma_fence_cb *cb); 62 62 63 + static void drm_sched_expel_job_unlocked(struct drm_sched_job *s_job); 64 + 63 65 /** 64 66 * drm_sched_rq_init - initialize a given run queue struct 65 67 * ··· 230 228 231 229 spin_lock(&sched->job_list_lock); 232 230 /* remove job from ring_mirror_list */ 233 - list_del(&s_job->node); 231 + list_del_init(&s_job->node); 234 232 /* queue TDR for next job */ 235 233 drm_sched_start_timeout(sched); 236 234 spin_unlock(&sched->job_list_lock); ··· 263 261 { 264 262 struct drm_gpu_scheduler *sched; 265 263 struct drm_sched_job *job; 266 - int r; 267 264 268 265 sched = container_of(work, struct drm_gpu_scheduler, work_tdr.work); 269 - 270 - spin_lock(&sched->job_list_lock); 271 - list_for_each_entry_reverse(job, &sched->ring_mirror_list, node) { 272 - struct drm_sched_fence *fence = job->s_fence; 273 - 274 - if (!dma_fence_remove_callback(fence->parent, &fence->cb)) 275 - goto already_signaled; 276 - } 277 - 278 266 job = list_first_entry_or_null(&sched->ring_mirror_list, 279 267 struct drm_sched_job, node); 280 - spin_unlock(&sched->job_list_lock); 281 268 282 269 if (job) 283 - sched->ops->timedout_job(job); 270 + job->sched->ops->timedout_job(job); 284 271 285 272 spin_lock(&sched->job_list_lock); 286 - list_for_each_entry(job, &sched->ring_mirror_list, node) { 287 - struct drm_sched_fence *fence = job->s_fence; 288 - 289 - if (!fence->parent || !list_empty(&fence->cb.node)) 290 - continue; 291 - 292 - r = dma_fence_add_callback(fence->parent, &fence->cb, 293 - drm_sched_process_job); 294 - if (r) 295 - drm_sched_process_job(fence->parent, &fence->cb); 296 - 297 - already_signaled: 298 - ; 299 - } 300 273 drm_sched_start_timeout(sched); 301 274 spin_unlock(&sched->job_list_lock); 302 275 } ··· 368 391 r); 369 392 dma_fence_put(fence); 370 393 } else { 394 + if (s_fence->finished.error < 0) 395 + drm_sched_expel_job_unlocked(s_job); 371 396 drm_sched_process_job(NULL, &s_fence->cb); 372 397 } 373 398 spin_lock(&sched->job_list_lock); ··· 574 595 r); 575 596 dma_fence_put(fence); 576 597 } else { 598 + if (s_fence->finished.error < 0) 599 + drm_sched_expel_job_unlocked(sched_job); 577 600 drm_sched_process_job(NULL, &s_fence->cb); 578 601 } 579 602 580 603 wake_up(&sched->job_scheduled); 581 604 } 582 605 return 0; 606 + } 607 + 608 + static void drm_sched_expel_job_unlocked(struct drm_sched_job *s_job) 609 + { 610 + struct drm_gpu_scheduler *sched = s_job->sched; 611 + 612 + spin_lock(&sched->job_list_lock); 613 + list_del_init(&s_job->node); 614 + spin_unlock(&sched->job_list_lock); 583 615 } 584 616 585 617 /**
+3 -1
drivers/gpu/drm/ttm/ttm_bo_util.c
··· 492 492 if (!fbo) 493 493 return -ENOMEM; 494 494 495 - ttm_bo_get(bo); 496 495 fbo->base = *bo; 496 + fbo->base.mem.placement |= TTM_PL_FLAG_NO_EVICT; 497 + 498 + ttm_bo_get(bo); 497 499 fbo->bo = bo; 498 500 499 501 /**
+15
include/drm/drm_connector.h
··· 972 972 struct drm_property *scaling_mode_property; 973 973 974 974 /** 975 + * @vrr_capable_property: Optional property to help userspace 976 + * query hardware support for variable refresh rate on a connector. 977 + * connector. Drivers can add the property to a connector by 978 + * calling drm_connector_attach_vrr_capable_property(). 979 + * 980 + * This should be updated only by calling 981 + * drm_connector_set_vrr_capable_property(). 982 + */ 983 + struct drm_property *vrr_capable_property; 984 + 985 + /** 975 986 * @content_protection_property: DRM ENUM property for content 976 987 * protection. See drm_connector_attach_content_protection_property(). 977 988 */ ··· 1256 1245 int drm_connector_attach_content_type_property(struct drm_connector *dev); 1257 1246 int drm_connector_attach_scaling_mode_property(struct drm_connector *connector, 1258 1247 u32 scaling_mode_mask); 1248 + int drm_connector_attach_vrr_capable_property( 1249 + struct drm_connector *connector); 1259 1250 int drm_connector_attach_content_protection_property( 1260 1251 struct drm_connector *connector); 1261 1252 int drm_mode_create_aspect_ratio_property(struct drm_device *dev); ··· 1274 1261 const struct edid *edid); 1275 1262 void drm_connector_set_link_status_property(struct drm_connector *connector, 1276 1263 uint64_t link_status); 1264 + void drm_connector_set_vrr_capable_property( 1265 + struct drm_connector *connector, bool capable); 1277 1266 int drm_connector_init_panel_orientation_property( 1278 1267 struct drm_connector *connector, int width, int height); 1279 1268 int drm_connector_attach_max_bpc_property(struct drm_connector *connector,
+9
include/drm/drm_crtc.h
··· 291 291 u32 pageflip_flags; 292 292 293 293 /** 294 + * @vrr_enabled: 295 + * 296 + * Indicates if variable refresh rate should be enabled for the CRTC. 297 + * Support for the requested vrr state will depend on driver and 298 + * hardware capabiltiy - lacking support is not treated as failure. 299 + */ 300 + bool vrr_enabled; 301 + 302 + /** 294 303 * @event: 295 304 * 296 305 * Optional pointer to a DRM event to signal upon completion of the
+5
include/drm/drm_mode_config.h
··· 645 645 * connectors must be of and active must be set to disabled, too. 646 646 */ 647 647 struct drm_property *prop_mode_id; 648 + /** 649 + * @prop_vrr_enabled: Default atomic CRTC property to indicate 650 + * whether variable refresh rate should be enabled on the CRTC. 651 + */ 652 + struct drm_property *prop_vrr_enabled; 648 653 649 654 /** 650 655 * @dvi_i_subconnector_property: Optional DVI-I property to