Linux Audio

Check our new training course

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}