xref: /linux/drivers/gpu/drm/i915/display/intel_display_power.h (revision 3a2c4d55e32ad65efebdb6de44eef3bfa08bb49d)
1 /* SPDX-License-Identifier: MIT */
2 /*
3  * Copyright © 2019 Intel Corporation
4  */
5 
6 #ifndef __INTEL_DISPLAY_POWER_H__
7 #define __INTEL_DISPLAY_POWER_H__
8 
9 #include <linux/mutex.h>
10 #include <linux/workqueue.h>
11 
12 #include "intel_display_limits.h"
13 
14 enum aux_ch;
15 enum port;
16 struct i915_power_well;
17 struct intel_atomic_state;
18 struct intel_display;
19 struct intel_encoder;
20 struct ref_tracker;
21 struct seq_file;
22 
23 /* -ENOENT means we got the ref, but there's no tracking */
24 #define INTEL_WAKEREF_DEF ERR_PTR(-ENOENT)
25 
26 /*
27  * Keep the pipe, transcoder, port (DDI_LANES,DDI_IO,AUX) domain instances
28  * consecutive, so that the pipe,transcoder,port -> power domain macros
29  * work correctly.
30  */
31 enum intel_display_power_domain {
32 	POWER_DOMAIN_DISPLAY_CORE,
33 	POWER_DOMAIN_PIPE_A,
34 	POWER_DOMAIN_PIPE_B,
35 	POWER_DOMAIN_PIPE_C,
36 	POWER_DOMAIN_PIPE_D,
37 	POWER_DOMAIN_PIPE_PANEL_FITTER_A,
38 	POWER_DOMAIN_PIPE_PANEL_FITTER_B,
39 	POWER_DOMAIN_PIPE_PANEL_FITTER_C,
40 	POWER_DOMAIN_PIPE_PANEL_FITTER_D,
41 	POWER_DOMAIN_TRANSCODER_A,
42 	POWER_DOMAIN_TRANSCODER_B,
43 	POWER_DOMAIN_TRANSCODER_C,
44 	POWER_DOMAIN_TRANSCODER_D,
45 	POWER_DOMAIN_TRANSCODER_EDP,
46 	POWER_DOMAIN_TRANSCODER_DSI_A,
47 	POWER_DOMAIN_TRANSCODER_DSI_C,
48 
49 	/* VDSC/joining for eDP/DSI transcoder (ICL) or pipe A (TGL) */
50 	POWER_DOMAIN_TRANSCODER_VDSC_PW2,
51 
52 	POWER_DOMAIN_PORT_DDI_LANES_A,
53 	POWER_DOMAIN_PORT_DDI_LANES_B,
54 	POWER_DOMAIN_PORT_DDI_LANES_C,
55 	POWER_DOMAIN_PORT_DDI_LANES_D,
56 	POWER_DOMAIN_PORT_DDI_LANES_E,
57 	POWER_DOMAIN_PORT_DDI_LANES_F,
58 
59 	POWER_DOMAIN_PORT_DDI_LANES_TC1,
60 	POWER_DOMAIN_PORT_DDI_LANES_TC2,
61 	POWER_DOMAIN_PORT_DDI_LANES_TC3,
62 	POWER_DOMAIN_PORT_DDI_LANES_TC4,
63 	POWER_DOMAIN_PORT_DDI_LANES_TC5,
64 	POWER_DOMAIN_PORT_DDI_LANES_TC6,
65 
66 	POWER_DOMAIN_PORT_DDI_IO_A,
67 	POWER_DOMAIN_PORT_DDI_IO_B,
68 	POWER_DOMAIN_PORT_DDI_IO_C,
69 	POWER_DOMAIN_PORT_DDI_IO_D,
70 	POWER_DOMAIN_PORT_DDI_IO_E,
71 	POWER_DOMAIN_PORT_DDI_IO_F,
72 
73 	POWER_DOMAIN_PORT_DDI_IO_TC1,
74 	POWER_DOMAIN_PORT_DDI_IO_TC2,
75 	POWER_DOMAIN_PORT_DDI_IO_TC3,
76 	POWER_DOMAIN_PORT_DDI_IO_TC4,
77 	POWER_DOMAIN_PORT_DDI_IO_TC5,
78 	POWER_DOMAIN_PORT_DDI_IO_TC6,
79 
80 	POWER_DOMAIN_PORT_DSI,
81 	POWER_DOMAIN_PORT_CRT,
82 	POWER_DOMAIN_PORT_OTHER,
83 	POWER_DOMAIN_VGA,
84 	POWER_DOMAIN_AUDIO_MMIO,
85 	POWER_DOMAIN_AUDIO_PLAYBACK,
86 
87 	POWER_DOMAIN_AUX_IO_A,
88 	POWER_DOMAIN_AUX_IO_B,
89 	POWER_DOMAIN_AUX_IO_C,
90 	POWER_DOMAIN_AUX_IO_D,
91 	POWER_DOMAIN_AUX_IO_E,
92 	POWER_DOMAIN_AUX_IO_F,
93 
94 	POWER_DOMAIN_AUX_A,
95 	POWER_DOMAIN_AUX_B,
96 	POWER_DOMAIN_AUX_C,
97 	POWER_DOMAIN_AUX_D,
98 	POWER_DOMAIN_AUX_E,
99 	POWER_DOMAIN_AUX_F,
100 
101 	POWER_DOMAIN_AUX_USBC1,
102 	POWER_DOMAIN_AUX_USBC2,
103 	POWER_DOMAIN_AUX_USBC3,
104 	POWER_DOMAIN_AUX_USBC4,
105 	POWER_DOMAIN_AUX_USBC5,
106 	POWER_DOMAIN_AUX_USBC6,
107 
108 	POWER_DOMAIN_AUX_TBT1,
109 	POWER_DOMAIN_AUX_TBT2,
110 	POWER_DOMAIN_AUX_TBT3,
111 	POWER_DOMAIN_AUX_TBT4,
112 	POWER_DOMAIN_AUX_TBT5,
113 	POWER_DOMAIN_AUX_TBT6,
114 
115 	POWER_DOMAIN_GMBUS,
116 	POWER_DOMAIN_GT_IRQ,
117 	POWER_DOMAIN_DC_OFF,
118 	POWER_DOMAIN_TC_COLD_OFF,
119 	POWER_DOMAIN_INIT,
120 
121 	POWER_DOMAIN_NUM,
122 	POWER_DOMAIN_INVALID = POWER_DOMAIN_NUM,
123 };
124 
125 #define POWER_DOMAIN_PIPE(pipe) \
126 	((enum intel_display_power_domain)((pipe) - PIPE_A + POWER_DOMAIN_PIPE_A))
127 #define POWER_DOMAIN_PIPE_PANEL_FITTER(pipe) \
128 	((enum intel_display_power_domain)((pipe) - PIPE_A + POWER_DOMAIN_PIPE_PANEL_FITTER_A))
129 #define POWER_DOMAIN_TRANSCODER(tran) \
130 	((tran) == TRANSCODER_EDP ? POWER_DOMAIN_TRANSCODER_EDP : \
131 	 (enum intel_display_power_domain)((tran) - TRANSCODER_A + POWER_DOMAIN_TRANSCODER_A))
132 
133 struct intel_power_domain_mask {
134 	DECLARE_BITMAP(bits, POWER_DOMAIN_NUM);
135 };
136 
137 /*
138  * DC3CO enabling triggers (bitmask).
139  * DC3CO may be enabled when at least one of these triggers is active.
140  * Additional constraints may still apply.
141  */
142 #define DC3CO_TRIGGER_NONE		(0)
143 #define DC3CO_TRIGGER_PSR2		BIT(0)
144 #define DC3CO_TRIGGER_LOBF		BIT(1)
145 #define DC3CO_TRIGGER_PANEL_REPLAY	BIT(2)
146 #define DC3CO_TRIGGER_ALL		(DC3CO_TRIGGER_PSR2 | \
147 					 DC3CO_TRIGGER_LOBF | \
148 					 DC3CO_TRIGGER_PANEL_REPLAY)
149 
150 /*
151  * Delay to re-enable DC5/DC6 states by 17 ms to avoid the off->on->off
152  * toggling overhead at and above 60 FPS.
153  */
154 #define DC6_PUT_ASYNC_DELAY_MS		17
155 /*
156  * Use minimal re-enable delay to allow DC3CO entry on
157  * the next idle frame.
158  */
159 #define DC3CO_PUT_ASYNC_DELAY_MS	1
160 
161 struct intel_dc3co_state {
162 	struct mutex lock; /* protects allowed and trigger fields */
163 	bool allowed; /* DC3CO compute result */
164 	u32 trigger; /* Bitmask of active DC3CO triggers */
165 };
166 
167 struct i915_power_domains {
168 	/*
169 	 * Power wells needed for initialization at driver init and suspend
170 	 * time are on. They are kept on until after the first modeset.
171 	 */
172 	bool initializing;
173 	bool display_core_suspended;
174 	bool dc3co_to_dc6;
175 	int power_well_count;
176 
177 	u32 dc_state;
178 	u32 target_dc_state;
179 	u32 allowed_dc_mask;
180 
181 	struct ref_tracker *init_wakeref;
182 	struct ref_tracker *disable_wakeref;
183 
184 	struct mutex lock;
185 	int domain_use_count[POWER_DOMAIN_NUM];
186 
187 	struct delayed_work async_put_work;
188 	struct ref_tracker *async_put_wakeref;
189 	struct intel_power_domain_mask async_put_domains[2];
190 	int async_put_next_delay;
191 
192 	struct i915_power_well *power_wells;
193 };
194 
195 struct intel_display_power_domain_set {
196 	struct intel_power_domain_mask mask;
197 #ifdef CONFIG_DRM_I915_DEBUG_RUNTIME_PM
198 	struct ref_tracker *wakerefs[POWER_DOMAIN_NUM];
199 #endif
200 };
201 
202 #define for_each_power_domain(__domain, __mask)				\
203 	for ((__domain) = 0; (__domain) < POWER_DOMAIN_NUM; (__domain)++)	\
204 		for_each_if(test_bit((__domain), (__mask)->bits))
205 
206 int intel_display_power_init(struct intel_display *display);
207 void intel_display_power_cleanup(struct intel_display *display);
208 void intel_display_power_init_hw(struct intel_display *display);
209 void intel_display_power_driver_remove(struct intel_display *display);
210 void intel_display_power_enable(struct intel_display *display);
211 void intel_display_power_disable(struct intel_display *display);
212 void intel_display_power_sanitize_state(struct intel_display *display);
213 
214 void intel_display_power_suspend_late(struct intel_display *display, bool s2idle);
215 void intel_display_power_resume_early(struct intel_display *display);
216 bool intel_display_power_get_and_reset_dc3co_to_dc6(struct intel_display *display);
217 void intel_display_power_set_target_dc_state(struct intel_display *display,
218 					     u32 state);
219 u32 intel_display_power_get_current_dc_state(struct intel_display *display);
220 bool intel_display_power_dc3co_supported(struct intel_display *display);
221 void intel_display_power_dc3co_update(struct intel_display *display, u32 trigger);
222 bool intel_display_power_dc3co_allowed(struct intel_display *display);
223 void intel_display_power_dc3co_compute(struct intel_atomic_state *state);
224 int intel_display_power_select_target_dc_state(struct intel_atomic_state *state);
225 
226 void intel_display_power_runtime_suspend(struct intel_display *display);
227 void intel_display_power_runtime_resume(struct intel_display *display);
228 
229 bool intel_display_power_is_enabled(struct intel_display *display,
230 				    enum intel_display_power_domain domain);
231 struct ref_tracker *intel_display_power_get(struct intel_display *display,
232 					    enum intel_display_power_domain domain);
233 struct ref_tracker *
234 intel_display_power_get_if_enabled(struct intel_display *display,
235 				   enum intel_display_power_domain domain);
236 void __intel_display_power_put_async(struct intel_display *display,
237 				     enum intel_display_power_domain domain,
238 				     struct ref_tracker *wakeref,
239 				     int delay_ms);
240 void intel_display_power_flush_work(struct intel_display *display);
241 #if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)
242 void intel_display_power_put(struct intel_display *display,
243 			     enum intel_display_power_domain domain,
244 			     struct ref_tracker *wakeref);
245 static inline void
246 intel_display_power_put_async(struct intel_display *display,
247 			      enum intel_display_power_domain domain,
248 			      struct ref_tracker *wakeref)
249 {
250 	__intel_display_power_put_async(display, domain, wakeref, -1);
251 }
252 
253 static inline void
254 intel_display_power_put_async_delay(struct intel_display *display,
255 				    enum intel_display_power_domain domain,
256 				    struct ref_tracker *wakeref,
257 				    int delay_ms)
258 {
259 	__intel_display_power_put_async(display, domain, wakeref, delay_ms);
260 }
261 #else
262 void intel_display_power_put_unchecked(struct intel_display *display,
263 				       enum intel_display_power_domain domain);
264 
265 static inline void
266 intel_display_power_put(struct intel_display *display,
267 			enum intel_display_power_domain domain,
268 			struct ref_tracker *wakeref)
269 {
270 	intel_display_power_put_unchecked(display, domain);
271 }
272 
273 static inline void
274 intel_display_power_put_async(struct intel_display *display,
275 			      enum intel_display_power_domain domain,
276 			      struct ref_tracker *wakeref)
277 {
278 	__intel_display_power_put_async(display, domain, INTEL_WAKEREF_DEF, -1);
279 }
280 
281 static inline void
282 intel_display_power_put_async_delay(struct intel_display *display,
283 				    enum intel_display_power_domain domain,
284 				    struct ref_tracker *wakeref,
285 				    int delay_ms)
286 {
287 	__intel_display_power_put_async(display, domain, INTEL_WAKEREF_DEF, delay_ms);
288 }
289 #endif
290 
291 void
292 intel_display_power_get_in_set(struct intel_display *display,
293 			       struct intel_display_power_domain_set *power_domain_set,
294 			       enum intel_display_power_domain domain);
295 
296 bool
297 intel_display_power_get_in_set_if_enabled(struct intel_display *display,
298 					  struct intel_display_power_domain_set *power_domain_set,
299 					  enum intel_display_power_domain domain);
300 
301 void
302 intel_display_power_put_mask_in_set(struct intel_display *display,
303 				    struct intel_display_power_domain_set *power_domain_set,
304 				    struct intel_power_domain_mask *mask);
305 
306 static inline void
307 intel_display_power_put_all_in_set(struct intel_display *display,
308 				   struct intel_display_power_domain_set *power_domain_set)
309 {
310 	intel_display_power_put_mask_in_set(display, power_domain_set, &power_domain_set->mask);
311 }
312 
313 void intel_display_power_debug(struct intel_display *display, struct seq_file *m);
314 
315 enum intel_display_power_domain
316 intel_display_power_ddi_lanes_domain(struct intel_display *display, enum port port);
317 enum intel_display_power_domain
318 intel_display_power_ddi_io_domain(struct intel_display *display, enum port port);
319 enum intel_display_power_domain
320 intel_display_power_aux_io_domain(struct intel_display *display, enum aux_ch aux_ch);
321 enum intel_display_power_domain
322 intel_display_power_legacy_aux_domain(struct intel_display *display, enum aux_ch aux_ch);
323 enum intel_display_power_domain
324 intel_display_power_tbt_aux_domain(struct intel_display *display, enum aux_ch aux_ch);
325 
326 /*
327  * FIXME: We should probably switch this to a 0-based scheme to be consistent
328  * with how we now name/number DBUF_CTL instances.
329  */
330 enum dbuf_slice {
331 	DBUF_S1,
332 	DBUF_S2,
333 	DBUF_S3,
334 	DBUF_S4,
335 	I915_MAX_DBUF_SLICES
336 };
337 
338 void gen9_dbuf_slices_update(struct intel_display *display,
339 			     u8 req_slices);
340 
341 #define __with_intel_display_power(display, domain, wf) \
342 	for (struct ref_tracker *(wf) = intel_display_power_get((display), (domain)); (wf); \
343 	     intel_display_power_put_async((display), (domain), (wf)), (wf) = NULL)
344 
345 #define with_intel_display_power(display, domain) \
346 	__with_intel_display_power(display, domain, __UNIQUE_ID(wakeref))
347 
348 #define __with_intel_display_power_if_enabled(display, domain, wf) \
349 	for (struct ref_tracker *(wf) = intel_display_power_get_if_enabled((display), (domain)); (wf); \
350 	     intel_display_power_put_async((display), (domain), (wf)), (wf) = NULL)
351 
352 #define with_intel_display_power_if_enabled(display, domain) \
353 	__with_intel_display_power_if_enabled(display, domain, __UNIQUE_ID(wakeref))
354 
355 #endif /* __INTEL_DISPLAY_POWER_H__ */
356