1 // SPDX-License-Identifier: MIT 2 /* 3 * Copyright © 2023 Intel Corporation 4 */ 5 6 #include "xe_display.h" 7 #include "regs/xe_irq_regs.h" 8 9 #include <linux/fb.h> 10 11 #include <drm/drm_drv.h> 12 #include <drm/drm_managed.h> 13 #include <uapi/drm/xe_drm.h> 14 15 #include "soc/intel_dram.h" 16 #include "intel_acpi.h" 17 #include "intel_audio.h" 18 #include "intel_bw.h" 19 #include "intel_display.h" 20 #include "intel_display_driver.h" 21 #include "intel_display_irq.h" 22 #include "intel_display_types.h" 23 #include "intel_dmc.h" 24 #include "intel_dp.h" 25 #include "intel_encoder.h" 26 #include "intel_fbdev.h" 27 #include "intel_hdcp.h" 28 #include "intel_hotplug.h" 29 #include "intel_opregion.h" 30 #include "xe_module.h" 31 32 /* Xe device functions */ 33 34 static bool has_display(struct xe_device *xe) 35 { 36 return HAS_DISPLAY(&xe->display); 37 } 38 39 /** 40 * xe_display_driver_probe_defer - Detect if we need to wait for other drivers 41 * early on 42 * @pdev: PCI device 43 * 44 * Returns: true if probe needs to be deferred, false otherwise 45 */ 46 bool xe_display_driver_probe_defer(struct pci_dev *pdev) 47 { 48 if (!xe_modparam.probe_display) 49 return 0; 50 51 return intel_display_driver_probe_defer(pdev); 52 } 53 54 /** 55 * xe_display_driver_set_hooks - Add driver flags and hooks for display 56 * @driver: DRM device driver 57 * 58 * Set features and function hooks in @driver that are needed for driving the 59 * display IP. This sets the driver's capability of driving display, regardless 60 * if the device has it enabled 61 */ 62 void xe_display_driver_set_hooks(struct drm_driver *driver) 63 { 64 if (!xe_modparam.probe_display) 65 return; 66 67 driver->driver_features |= DRIVER_MODESET | DRIVER_ATOMIC; 68 } 69 70 static void unset_display_features(struct xe_device *xe) 71 { 72 xe->drm.driver_features &= ~(DRIVER_MODESET | DRIVER_ATOMIC); 73 } 74 75 static void display_destroy(struct drm_device *dev, void *dummy) 76 { 77 struct xe_device *xe = to_xe_device(dev); 78 79 destroy_workqueue(xe->display.hotplug.dp_wq); 80 } 81 82 /** 83 * xe_display_create - create display struct 84 * @xe: XE device instance 85 * 86 * Initialize all fields used by the display part. 87 * 88 * TODO: once everything can be inside a single struct, make the struct opaque 89 * to the rest of xe and return it to be xe->display. 90 * 91 * Returns: 0 on success 92 */ 93 int xe_display_create(struct xe_device *xe) 94 { 95 spin_lock_init(&xe->display.fb_tracking.lock); 96 97 xe->display.hotplug.dp_wq = alloc_ordered_workqueue("xe-dp", 0); 98 99 return drmm_add_action_or_reset(&xe->drm, display_destroy, NULL); 100 } 101 102 static void xe_display_fini_nommio(struct drm_device *dev, void *dummy) 103 { 104 struct xe_device *xe = to_xe_device(dev); 105 106 if (!xe->info.probe_display) 107 return; 108 109 intel_power_domains_cleanup(xe); 110 } 111 112 int xe_display_init_nommio(struct xe_device *xe) 113 { 114 if (!xe->info.probe_display) 115 return 0; 116 117 /* Fake uncore lock */ 118 spin_lock_init(&xe->uncore.lock); 119 120 /* This must be called before any calls to HAS_PCH_* */ 121 intel_detect_pch(xe); 122 123 return drmm_add_action_or_reset(&xe->drm, xe_display_fini_nommio, xe); 124 } 125 126 static void xe_display_fini_noirq(void *arg) 127 { 128 struct xe_device *xe = arg; 129 struct intel_display *display = &xe->display; 130 131 if (!xe->info.probe_display) 132 return; 133 134 intel_display_driver_remove_noirq(xe); 135 intel_opregion_cleanup(display); 136 } 137 138 int xe_display_init_noirq(struct xe_device *xe) 139 { 140 struct intel_display *display = &xe->display; 141 int err; 142 143 if (!xe->info.probe_display) 144 return 0; 145 146 intel_display_driver_early_probe(xe); 147 148 /* Early display init.. */ 149 intel_opregion_setup(display); 150 151 /* 152 * Fill the dram structure to get the system dram info. This will be 153 * used for memory latency calculation. 154 */ 155 intel_dram_detect(xe); 156 157 intel_bw_init_hw(xe); 158 159 intel_display_device_info_runtime_init(xe); 160 161 err = intel_display_driver_probe_noirq(xe); 162 if (err) { 163 intel_opregion_cleanup(display); 164 return err; 165 } 166 167 return devm_add_action_or_reset(xe->drm.dev, xe_display_fini_noirq, xe); 168 } 169 170 static void xe_display_fini_noaccel(void *arg) 171 { 172 struct xe_device *xe = arg; 173 174 if (!xe->info.probe_display) 175 return; 176 177 intel_display_driver_remove_nogem(xe); 178 } 179 180 int xe_display_init_noaccel(struct xe_device *xe) 181 { 182 int err; 183 184 if (!xe->info.probe_display) 185 return 0; 186 187 err = intel_display_driver_probe_nogem(xe); 188 if (err) 189 return err; 190 191 return devm_add_action_or_reset(xe->drm.dev, xe_display_fini_noaccel, xe); 192 } 193 194 int xe_display_init(struct xe_device *xe) 195 { 196 if (!xe->info.probe_display) 197 return 0; 198 199 return intel_display_driver_probe(xe); 200 } 201 202 void xe_display_fini(struct xe_device *xe) 203 { 204 if (!xe->info.probe_display) 205 return; 206 207 intel_hpd_poll_fini(xe); 208 209 intel_hdcp_component_fini(xe); 210 intel_audio_deinit(xe); 211 } 212 213 void xe_display_register(struct xe_device *xe) 214 { 215 if (!xe->info.probe_display) 216 return; 217 218 intel_display_driver_register(xe); 219 intel_register_dsm_handler(); 220 intel_power_domains_enable(xe); 221 } 222 223 void xe_display_unregister(struct xe_device *xe) 224 { 225 if (!xe->info.probe_display) 226 return; 227 228 intel_unregister_dsm_handler(); 229 intel_power_domains_disable(xe); 230 intel_display_driver_unregister(xe); 231 } 232 233 void xe_display_driver_remove(struct xe_device *xe) 234 { 235 if (!xe->info.probe_display) 236 return; 237 238 intel_display_driver_remove(xe); 239 } 240 241 /* IRQ-related functions */ 242 243 void xe_display_irq_handler(struct xe_device *xe, u32 master_ctl) 244 { 245 if (!xe->info.probe_display) 246 return; 247 248 if (master_ctl & DISPLAY_IRQ) 249 gen11_display_irq_handler(xe); 250 } 251 252 void xe_display_irq_enable(struct xe_device *xe, u32 gu_misc_iir) 253 { 254 struct intel_display *display = &xe->display; 255 256 if (!xe->info.probe_display) 257 return; 258 259 if (gu_misc_iir & GU_MISC_GSE) 260 intel_opregion_asle_intr(display); 261 } 262 263 void xe_display_irq_reset(struct xe_device *xe) 264 { 265 if (!xe->info.probe_display) 266 return; 267 268 gen11_display_irq_reset(xe); 269 } 270 271 void xe_display_irq_postinstall(struct xe_device *xe, struct xe_gt *gt) 272 { 273 if (!xe->info.probe_display) 274 return; 275 276 if (gt->info.id == XE_GT0) 277 gen11_de_irq_postinstall(xe); 278 } 279 280 static bool suspend_to_idle(void) 281 { 282 #if IS_ENABLED(CONFIG_ACPI_SLEEP) 283 if (acpi_target_system_state() < ACPI_STATE_S3) 284 return true; 285 #endif 286 return false; 287 } 288 289 static void xe_display_flush_cleanup_work(struct xe_device *xe) 290 { 291 struct intel_crtc *crtc; 292 293 for_each_intel_crtc(&xe->drm, crtc) { 294 struct drm_crtc_commit *commit; 295 296 spin_lock(&crtc->base.commit_lock); 297 commit = list_first_entry_or_null(&crtc->base.commit_list, 298 struct drm_crtc_commit, commit_entry); 299 if (commit) 300 drm_crtc_commit_get(commit); 301 spin_unlock(&crtc->base.commit_lock); 302 303 if (commit) { 304 wait_for_completion(&commit->cleanup_done); 305 drm_crtc_commit_put(commit); 306 } 307 } 308 } 309 310 /* TODO: System and runtime suspend/resume sequences will be sanitized as a follow-up. */ 311 static void __xe_display_pm_suspend(struct xe_device *xe, bool runtime) 312 { 313 struct intel_display *display = &xe->display; 314 bool s2idle = suspend_to_idle(); 315 if (!xe->info.probe_display) 316 return; 317 318 /* 319 * We do a lot of poking in a lot of registers, make sure they work 320 * properly. 321 */ 322 intel_power_domains_disable(xe); 323 intel_fbdev_set_suspend(&xe->drm, FBINFO_STATE_SUSPENDED, true); 324 if (!runtime && has_display(xe)) { 325 drm_kms_helper_poll_disable(&xe->drm); 326 intel_display_driver_disable_user_access(xe); 327 intel_display_driver_suspend(xe); 328 } 329 330 xe_display_flush_cleanup_work(xe); 331 332 intel_dp_mst_suspend(xe); 333 334 intel_hpd_cancel_work(xe); 335 336 if (!runtime && has_display(xe)) { 337 intel_display_driver_suspend_access(xe); 338 intel_encoder_suspend_all(&xe->display); 339 } 340 341 intel_opregion_suspend(display, s2idle ? PCI_D1 : PCI_D3cold); 342 343 intel_dmc_suspend(xe); 344 } 345 346 void xe_display_pm_suspend(struct xe_device *xe) 347 { 348 __xe_display_pm_suspend(xe, false); 349 } 350 351 void xe_display_pm_shutdown(struct xe_device *xe) 352 { 353 struct intel_display *display = &xe->display; 354 355 if (!xe->info.probe_display) 356 return; 357 358 intel_power_domains_disable(xe); 359 intel_fbdev_set_suspend(&xe->drm, FBINFO_STATE_SUSPENDED, true); 360 if (has_display(xe)) { 361 drm_kms_helper_poll_disable(&xe->drm); 362 intel_display_driver_disable_user_access(xe); 363 intel_display_driver_suspend(xe); 364 } 365 366 xe_display_flush_cleanup_work(xe); 367 intel_dp_mst_suspend(xe); 368 intel_hpd_cancel_work(xe); 369 370 if (has_display(xe)) 371 intel_display_driver_suspend_access(xe); 372 373 intel_encoder_suspend_all(display); 374 intel_encoder_shutdown_all(display); 375 376 intel_opregion_suspend(display, PCI_D3cold); 377 378 intel_dmc_suspend(xe); 379 } 380 381 void xe_display_pm_runtime_suspend(struct xe_device *xe) 382 { 383 if (!xe->info.probe_display) 384 return; 385 386 if (xe->d3cold.allowed) 387 __xe_display_pm_suspend(xe, true); 388 389 intel_hpd_poll_enable(xe); 390 } 391 392 void xe_display_pm_suspend_late(struct xe_device *xe) 393 { 394 bool s2idle = suspend_to_idle(); 395 if (!xe->info.probe_display) 396 return; 397 398 intel_power_domains_suspend(xe, s2idle); 399 400 intel_display_power_suspend_late(xe); 401 } 402 403 void xe_display_pm_shutdown_late(struct xe_device *xe) 404 { 405 if (!xe->info.probe_display) 406 return; 407 408 /* 409 * The only requirement is to reboot with display DC states disabled, 410 * for now leaving all display power wells in the INIT power domain 411 * enabled. 412 */ 413 intel_power_domains_driver_remove(xe); 414 } 415 416 void xe_display_pm_resume_early(struct xe_device *xe) 417 { 418 if (!xe->info.probe_display) 419 return; 420 421 intel_display_power_resume_early(xe); 422 423 intel_power_domains_resume(xe); 424 } 425 426 static void __xe_display_pm_resume(struct xe_device *xe, bool runtime) 427 { 428 struct intel_display *display = &xe->display; 429 430 if (!xe->info.probe_display) 431 return; 432 433 intel_dmc_resume(xe); 434 435 if (has_display(xe)) 436 drm_mode_config_reset(&xe->drm); 437 438 intel_display_driver_init_hw(xe); 439 intel_hpd_init(xe); 440 441 if (!runtime && has_display(xe)) 442 intel_display_driver_resume_access(xe); 443 444 /* MST sideband requires HPD interrupts enabled */ 445 intel_dp_mst_resume(xe); 446 if (!runtime && has_display(xe)) { 447 intel_display_driver_resume(xe); 448 drm_kms_helper_poll_enable(&xe->drm); 449 intel_display_driver_enable_user_access(xe); 450 intel_hpd_poll_disable(xe); 451 } 452 453 intel_opregion_resume(display); 454 455 intel_fbdev_set_suspend(&xe->drm, FBINFO_STATE_RUNNING, false); 456 457 intel_power_domains_enable(xe); 458 } 459 460 void xe_display_pm_resume(struct xe_device *xe) 461 { 462 __xe_display_pm_resume(xe, false); 463 } 464 465 void xe_display_pm_runtime_resume(struct xe_device *xe) 466 { 467 if (!xe->info.probe_display) 468 return; 469 470 intel_hpd_poll_disable(xe); 471 472 if (xe->d3cold.allowed) 473 __xe_display_pm_resume(xe, true); 474 } 475 476 477 static void display_device_remove(struct drm_device *dev, void *arg) 478 { 479 struct xe_device *xe = arg; 480 481 intel_display_device_remove(xe); 482 } 483 484 int xe_display_probe(struct xe_device *xe) 485 { 486 int err; 487 488 if (!xe->info.probe_display) 489 goto no_display; 490 491 intel_display_device_probe(xe); 492 493 err = drmm_add_action_or_reset(&xe->drm, display_device_remove, xe); 494 if (err) 495 return err; 496 497 if (has_display(xe)) 498 return 0; 499 500 no_display: 501 xe->info.probe_display = false; 502 unset_display_features(xe); 503 return 0; 504 } 505