Loading...
Note: File does not exist in v4.6.
1// SPDX-License-Identifier: MIT
2/*
3 * Copyright © 2023 Intel Corporation
4 */
5
6#include "xe_display.h"
7#include "regs/xe_regs.h"
8
9#include <linux/fb.h>
10
11#include <drm/drm_drv.h>
12#include <drm/drm_managed.h>
13#include <drm/xe_drm.h>
14
15#include "soc/intel_dram.h"
16#include "i915_drv.h" /* FIXME: HAS_DISPLAY() depends on this */
17#include "intel_acpi.h"
18#include "intel_audio.h"
19#include "intel_bw.h"
20#include "intel_display.h"
21#include "intel_display_driver.h"
22#include "intel_display_irq.h"
23#include "intel_display_types.h"
24#include "intel_dmc.h"
25#include "intel_dp.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
34static bool has_display(struct xe_device *xe)
35{
36 return HAS_DISPLAY(xe);
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 */
46bool xe_display_driver_probe_defer(struct pci_dev *pdev)
47{
48 if (!xe_modparam.enable_display)
49 return 0;
50
51 return intel_display_driver_probe_defer(pdev);
52}
53
54static void xe_display_last_close(struct drm_device *dev)
55{
56 struct xe_device *xe = to_xe_device(dev);
57
58 if (xe->info.enable_display)
59 intel_fbdev_restore_mode(to_xe_device(dev));
60}
61
62/**
63 * xe_display_driver_set_hooks - Add driver flags and hooks for display
64 * @driver: DRM device driver
65 *
66 * Set features and function hooks in @driver that are needed for driving the
67 * display IP. This sets the driver's capability of driving display, regardless
68 * if the device has it enabled
69 */
70void xe_display_driver_set_hooks(struct drm_driver *driver)
71{
72 if (!xe_modparam.enable_display)
73 return;
74
75 driver->driver_features |= DRIVER_MODESET | DRIVER_ATOMIC;
76 driver->lastclose = xe_display_last_close;
77}
78
79static void unset_display_features(struct xe_device *xe)
80{
81 xe->drm.driver_features &= ~(DRIVER_MODESET | DRIVER_ATOMIC);
82}
83
84static void display_destroy(struct drm_device *dev, void *dummy)
85{
86 struct xe_device *xe = to_xe_device(dev);
87
88 destroy_workqueue(xe->display.hotplug.dp_wq);
89}
90
91/**
92 * xe_display_create - create display struct
93 * @xe: XE device instance
94 *
95 * Initialize all fields used by the display part.
96 *
97 * TODO: once everything can be inside a single struct, make the struct opaque
98 * to the rest of xe and return it to be xe->display.
99 *
100 * Returns: 0 on success
101 */
102int xe_display_create(struct xe_device *xe)
103{
104 int err;
105
106 spin_lock_init(&xe->display.fb_tracking.lock);
107
108 xe->display.hotplug.dp_wq = alloc_ordered_workqueue("xe-dp", 0);
109
110 drmm_mutex_init(&xe->drm, &xe->sb_lock);
111 drmm_mutex_init(&xe->drm, &xe->display.backlight.lock);
112 drmm_mutex_init(&xe->drm, &xe->display.audio.mutex);
113 drmm_mutex_init(&xe->drm, &xe->display.wm.wm_mutex);
114 drmm_mutex_init(&xe->drm, &xe->display.pps.mutex);
115 drmm_mutex_init(&xe->drm, &xe->display.hdcp.hdcp_mutex);
116 xe->enabled_irq_mask = ~0;
117
118 err = drmm_add_action_or_reset(&xe->drm, display_destroy, NULL);
119 if (err)
120 return err;
121
122 return 0;
123}
124
125static void xe_display_fini_nommio(struct drm_device *dev, void *dummy)
126{
127 struct xe_device *xe = to_xe_device(dev);
128
129 if (!xe->info.enable_display)
130 return;
131
132 intel_power_domains_cleanup(xe);
133}
134
135int xe_display_init_nommio(struct xe_device *xe)
136{
137 if (!xe->info.enable_display)
138 return 0;
139
140 /* Fake uncore lock */
141 spin_lock_init(&xe->uncore.lock);
142
143 /* This must be called before any calls to HAS_PCH_* */
144 intel_detect_pch(xe);
145
146 return drmm_add_action_or_reset(&xe->drm, xe_display_fini_nommio, xe);
147}
148
149static void xe_display_fini_noirq(struct drm_device *dev, void *dummy)
150{
151 struct xe_device *xe = to_xe_device(dev);
152
153 if (!xe->info.enable_display)
154 return;
155
156 intel_display_driver_remove_noirq(xe);
157 intel_power_domains_driver_remove(xe);
158}
159
160int xe_display_init_noirq(struct xe_device *xe)
161{
162 int err;
163
164 if (!xe->info.enable_display)
165 return 0;
166
167 intel_display_driver_early_probe(xe);
168
169 /* Early display init.. */
170 intel_opregion_setup(xe);
171
172 /*
173 * Fill the dram structure to get the system dram info. This will be
174 * used for memory latency calculation.
175 */
176 intel_dram_detect(xe);
177
178 intel_bw_init_hw(xe);
179
180 intel_display_device_info_runtime_init(xe);
181
182 err = intel_display_driver_probe_noirq(xe);
183 if (err)
184 return err;
185
186 return drmm_add_action_or_reset(&xe->drm, xe_display_fini_noirq, NULL);
187}
188
189static void xe_display_fini_noaccel(struct drm_device *dev, void *dummy)
190{
191 struct xe_device *xe = to_xe_device(dev);
192
193 if (!xe->info.enable_display)
194 return;
195
196 intel_display_driver_remove_nogem(xe);
197}
198
199int xe_display_init_noaccel(struct xe_device *xe)
200{
201 int err;
202
203 if (!xe->info.enable_display)
204 return 0;
205
206 err = intel_display_driver_probe_nogem(xe);
207 if (err)
208 return err;
209
210 return drmm_add_action_or_reset(&xe->drm, xe_display_fini_noaccel, NULL);
211}
212
213int xe_display_init(struct xe_device *xe)
214{
215 if (!xe->info.enable_display)
216 return 0;
217
218 return intel_display_driver_probe(xe);
219}
220
221void xe_display_fini(struct xe_device *xe)
222{
223 if (!xe->info.enable_display)
224 return;
225
226 /* poll work can call into fbdev, hence clean that up afterwards */
227 intel_hpd_poll_fini(xe);
228 intel_fbdev_fini(xe);
229
230 intel_hdcp_component_fini(xe);
231 intel_audio_deinit(xe);
232}
233
234void xe_display_register(struct xe_device *xe)
235{
236 if (!xe->info.enable_display)
237 return;
238
239 intel_display_driver_register(xe);
240 intel_register_dsm_handler();
241 intel_power_domains_enable(xe);
242}
243
244void xe_display_unregister(struct xe_device *xe)
245{
246 if (!xe->info.enable_display)
247 return;
248
249 intel_unregister_dsm_handler();
250 intel_power_domains_disable(xe);
251 intel_display_driver_unregister(xe);
252}
253
254void xe_display_driver_remove(struct xe_device *xe)
255{
256 if (!xe->info.enable_display)
257 return;
258
259 intel_display_driver_remove(xe);
260
261 intel_display_device_remove(xe);
262}
263
264/* IRQ-related functions */
265
266void xe_display_irq_handler(struct xe_device *xe, u32 master_ctl)
267{
268 if (!xe->info.enable_display)
269 return;
270
271 if (master_ctl & DISPLAY_IRQ)
272 gen11_display_irq_handler(xe);
273}
274
275void xe_display_irq_enable(struct xe_device *xe, u32 gu_misc_iir)
276{
277 if (!xe->info.enable_display)
278 return;
279
280 if (gu_misc_iir & GU_MISC_GSE)
281 intel_opregion_asle_intr(xe);
282}
283
284void xe_display_irq_reset(struct xe_device *xe)
285{
286 if (!xe->info.enable_display)
287 return;
288
289 gen11_display_irq_reset(xe);
290}
291
292void xe_display_irq_postinstall(struct xe_device *xe, struct xe_gt *gt)
293{
294 if (!xe->info.enable_display)
295 return;
296
297 if (gt->info.id == XE_GT0)
298 gen11_de_irq_postinstall(xe);
299}
300
301static void intel_suspend_encoders(struct xe_device *xe)
302{
303 struct drm_device *dev = &xe->drm;
304 struct intel_encoder *encoder;
305
306 if (has_display(xe))
307 return;
308
309 drm_modeset_lock_all(dev);
310 for_each_intel_encoder(dev, encoder)
311 if (encoder->suspend)
312 encoder->suspend(encoder);
313 drm_modeset_unlock_all(dev);
314}
315
316static bool suspend_to_idle(void)
317{
318#if IS_ENABLED(CONFIG_ACPI_SLEEP)
319 if (acpi_target_system_state() < ACPI_STATE_S3)
320 return true;
321#endif
322 return false;
323}
324
325void xe_display_pm_suspend(struct xe_device *xe)
326{
327 bool s2idle = suspend_to_idle();
328 if (!xe->info.enable_display)
329 return;
330
331 /*
332 * We do a lot of poking in a lot of registers, make sure they work
333 * properly.
334 */
335 intel_power_domains_disable(xe);
336 if (has_display(xe))
337 drm_kms_helper_poll_disable(&xe->drm);
338
339 intel_display_driver_suspend(xe);
340
341 intel_dp_mst_suspend(xe);
342
343 intel_hpd_cancel_work(xe);
344
345 intel_suspend_encoders(xe);
346
347 intel_opregion_suspend(xe, s2idle ? PCI_D1 : PCI_D3cold);
348
349 intel_fbdev_set_suspend(&xe->drm, FBINFO_STATE_SUSPENDED, true);
350
351 intel_dmc_suspend(xe);
352}
353
354void xe_display_pm_suspend_late(struct xe_device *xe)
355{
356 bool s2idle = suspend_to_idle();
357 if (!xe->info.enable_display)
358 return;
359
360 intel_power_domains_suspend(xe, s2idle);
361
362 intel_display_power_suspend_late(xe);
363}
364
365void xe_display_pm_resume_early(struct xe_device *xe)
366{
367 if (!xe->info.enable_display)
368 return;
369
370 intel_display_power_resume_early(xe);
371
372 intel_power_domains_resume(xe);
373}
374
375void xe_display_pm_resume(struct xe_device *xe)
376{
377 if (!xe->info.enable_display)
378 return;
379
380 intel_dmc_resume(xe);
381
382 if (has_display(xe))
383 drm_mode_config_reset(&xe->drm);
384
385 intel_display_driver_init_hw(xe);
386 intel_hpd_init(xe);
387
388 /* MST sideband requires HPD interrupts enabled */
389 intel_dp_mst_resume(xe);
390 intel_display_driver_resume(xe);
391
392 intel_hpd_poll_disable(xe);
393 if (has_display(xe))
394 drm_kms_helper_poll_enable(&xe->drm);
395
396 intel_opregion_resume(xe);
397
398 intel_fbdev_set_suspend(&xe->drm, FBINFO_STATE_RUNNING, false);
399
400 intel_power_domains_enable(xe);
401}
402
403void xe_display_probe(struct xe_device *xe)
404{
405 if (!xe->info.enable_display)
406 goto no_display;
407
408 intel_display_device_probe(xe);
409
410 if (has_display(xe))
411 return;
412
413no_display:
414 xe->info.enable_display = false;
415 unset_display_features(xe);
416}