xref: /linux/drivers/gpu/drm/i915/display/intel_display_rps.c (revision 1fd1dc41724319406b0aff221a352a400b0ddfc5)
1 // SPDX-License-Identifier: MIT
2 /*
3  * Copyright © 2023 Intel Corporation
4  */
5 
6 #include <linux/dma-fence.h>
7 
8 #include <drm/drm_crtc.h>
9 #include <drm/drm_vblank.h>
10 
11 #include "i915_reg.h"
12 #include "intel_display_core.h"
13 #include "intel_display_irq.h"
14 #include "intel_display_rps.h"
15 #include "intel_display_types.h"
16 #include "intel_parent.h"
17 
18 struct wait_rps_boost {
19 	struct wait_queue_entry wait;
20 
21 	struct drm_crtc *crtc;
22 	struct dma_fence *fence;
23 };
24 
25 static int do_rps_boost(struct wait_queue_entry *_wait,
26 			unsigned mode, int sync, void *key)
27 {
28 	struct wait_rps_boost *wait = container_of(_wait, typeof(*wait), wait);
29 	struct intel_display *display = to_intel_display(wait->crtc->dev);
30 
31 	/*
32 	 * If we missed the vblank, but the request is already running it
33 	 * is reasonable to assume that it will complete before the next
34 	 * vblank without our intervention, so leave RPS alone if not started.
35 	 */
36 	intel_parent_rps_boost_if_not_started(display, wait->fence);
37 
38 	dma_fence_put(wait->fence);
39 
40 	drm_crtc_vblank_put(wait->crtc);
41 
42 	list_del(&wait->wait.entry);
43 	kfree(wait);
44 	return 1;
45 }
46 
47 void intel_display_rps_boost_after_vblank(struct drm_crtc *crtc,
48 					  struct dma_fence *fence)
49 {
50 	struct intel_display *display = to_intel_display(crtc->dev);
51 	struct wait_rps_boost *wait;
52 
53 	if (!intel_parent_rps_available(display))
54 		return;
55 
56 	if (DISPLAY_VER(display) < 6)
57 		return;
58 
59 	if (drm_crtc_vblank_get(crtc))
60 		return;
61 
62 	wait = kmalloc_obj(*wait);
63 	if (!wait) {
64 		drm_crtc_vblank_put(crtc);
65 		return;
66 	}
67 
68 	wait->fence = dma_fence_get(fence);
69 	wait->crtc = crtc;
70 
71 	wait->wait.func = do_rps_boost;
72 	wait->wait.flags = 0;
73 
74 	add_wait_queue(drm_crtc_vblank_waitqueue(crtc), &wait->wait);
75 }
76 
77 void intel_display_rps_mark_interactive(struct intel_display *display,
78 					struct intel_atomic_state *state,
79 					bool interactive)
80 {
81 	if (!intel_parent_rps_available(display))
82 		return;
83 
84 	if (state->rps_interactive == interactive)
85 		return;
86 
87 	intel_parent_rps_mark_interactive(display, interactive);
88 
89 	state->rps_interactive = interactive;
90 }
91 
92 void ilk_display_rps_enable(struct intel_display *display)
93 {
94 	spin_lock(&display->irq.lock);
95 	ilk_enable_display_irq(display, DE_PCU_EVENT);
96 	spin_unlock(&display->irq.lock);
97 }
98 
99 void ilk_display_rps_disable(struct intel_display *display)
100 {
101 	spin_lock(&display->irq.lock);
102 	ilk_disable_display_irq(display, DE_PCU_EVENT);
103 	spin_unlock(&display->irq.lock);
104 }
105 
106 void ilk_display_rps_irq_handler(struct intel_display *display)
107 {
108 	intel_parent_rps_ilk_irq_handler(display);
109 }
110