xref: /linux/drivers/gpu/drm/i915/i915_overlay.c (revision 4a57e0913e8c7fff407e97909f4ae48caa84d612)
1 // SPDX-License-Identifier: MIT
2 /*
3  * Copyright 2026, Intel Corporation.
4  */
5 
6 #include <drm/drm_print.h>
7 
8 #include <drm/intel/display_parent_interface.h>
9 #include <drm/intel/intel_gmd_interrupt_regs.h>
10 
11 #include "gem/i915_gem_internal.h"
12 #include "gem/i915_gem_object_frontbuffer.h"
13 #include "gem/i915_gem_pm.h"
14 
15 #include "gt/intel_gpu_commands.h"
16 #include "gt/intel_ring.h"
17 
18 #include "i915_drv.h"
19 #include "i915_overlay.h"
20 #include "i915_reg.h"
21 #include "intel_pci_config.h"
22 
23 #include "display/intel_frontbuffer.h"
24 
25 /* overlay flip addr flag */
26 #define OFC_UPDATE		0x1
27 
28 struct i915_overlay {
29 	struct drm_i915_private *i915;
30 	struct intel_context *context;
31 	struct i915_vma *vma;
32 	struct i915_vma *old_vma;
33 	struct i915_frontbuffer *frontbuffer;
34 	/* register access */
35 	struct drm_i915_gem_object *reg_bo;
36 	void __iomem *regs;
37 	u32 flip_addr;
38 	u32 frontbuffer_bits;
39 	/* flip handling */
40 	struct i915_active last_flip;
41 	void (*flip_complete)(struct i915_overlay *overlay);
42 };
43 
44 static void i830_overlay_clock_gating(struct drm_i915_private *i915,
45 				      bool enable)
46 {
47 	struct pci_dev *pdev = to_pci_dev(i915->drm.dev);
48 	u8 val;
49 
50 	/*
51 	 * WA_OVERLAY_CLKGATE:alm
52 	 *
53 	 * FIXME should perhaps be done on the display side?
54 	 */
55 	if (enable)
56 		intel_uncore_write(&i915->uncore, DSPCLK_GATE_D, 0);
57 	else
58 		intel_uncore_write(&i915->uncore, DSPCLK_GATE_D, OVRUNIT_CLOCK_GATE_DISABLE);
59 
60 	/* WA_DISABLE_L2CACHE_CLOCK_GATING:alm */
61 	pci_bus_read_config_byte(pdev->bus,
62 				 PCI_DEVFN(0, 0), I830_CLOCK_GATE, &val);
63 	if (enable)
64 		val &= ~I830_L2_CACHE_CLOCK_GATE_DISABLE;
65 	else
66 		val |= I830_L2_CACHE_CLOCK_GATE_DISABLE;
67 	pci_bus_write_config_byte(pdev->bus,
68 				  PCI_DEVFN(0, 0), I830_CLOCK_GATE, val);
69 }
70 
71 static struct i915_request *
72 alloc_request(struct i915_overlay *overlay, void (*fn)(struct i915_overlay *))
73 {
74 	struct i915_request *rq;
75 	int err;
76 
77 	overlay->flip_complete = fn;
78 
79 	rq = i915_request_create(overlay->context);
80 	if (IS_ERR(rq))
81 		return rq;
82 
83 	err = i915_active_add_request(&overlay->last_flip, rq);
84 	if (err) {
85 		i915_request_add(rq);
86 		return ERR_PTR(err);
87 	}
88 
89 	return rq;
90 }
91 
92 static bool i915_overlay_is_active(struct drm_device *drm)
93 {
94 	struct drm_i915_private *i915 = to_i915(drm);
95 	struct i915_overlay *overlay = i915->overlay;
96 
97 	return overlay->frontbuffer_bits;
98 }
99 
100 /* overlay needs to be disable in OCMD reg */
101 static int i915_overlay_on(struct drm_device *drm,
102 			   u32 frontbuffer_bits)
103 {
104 	struct drm_i915_private *i915 = to_i915(drm);
105 	struct i915_overlay *overlay = i915->overlay;
106 	struct i915_request *rq;
107 	u32 *cs;
108 
109 	drm_WARN_ON(drm, i915_overlay_is_active(drm));
110 
111 	rq = alloc_request(overlay, NULL);
112 	if (IS_ERR(rq))
113 		return PTR_ERR(rq);
114 
115 	cs = intel_ring_begin(rq, 4);
116 	if (IS_ERR(cs)) {
117 		i915_request_add(rq);
118 		return PTR_ERR(cs);
119 	}
120 
121 	overlay->frontbuffer_bits = frontbuffer_bits;
122 
123 	if (IS_I830(i915))
124 		i830_overlay_clock_gating(i915, false);
125 
126 	*cs++ = MI_OVERLAY_FLIP | MI_OVERLAY_ON;
127 	*cs++ = overlay->flip_addr | OFC_UPDATE;
128 	*cs++ = MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP;
129 	*cs++ = MI_NOOP;
130 	intel_ring_advance(rq, cs);
131 
132 	i915_request_add(rq);
133 
134 	return i915_active_wait(&overlay->last_flip);
135 }
136 
137 static void i915_overlay_flip_prepare(struct i915_overlay *overlay,
138 				      struct i915_vma *vma)
139 {
140 	struct drm_i915_private *i915 = overlay->i915;
141 	struct i915_frontbuffer *frontbuffer = NULL;
142 
143 	drm_WARN_ON(&i915->drm, overlay->old_vma);
144 
145 	if (vma)
146 		frontbuffer = i915_gem_object_frontbuffer_get(vma->obj);
147 
148 	i915_gem_object_frontbuffer_track(overlay->frontbuffer, frontbuffer,
149 					  overlay->frontbuffer_bits);
150 
151 	if (overlay->frontbuffer)
152 		i915_gem_object_frontbuffer_put(overlay->frontbuffer);
153 	overlay->frontbuffer = frontbuffer;
154 
155 	overlay->old_vma = overlay->vma;
156 	if (vma)
157 		overlay->vma = i915_vma_get(vma);
158 	else
159 		overlay->vma = NULL;
160 }
161 
162 /* overlay needs to be enabled in OCMD reg */
163 static int i915_overlay_continue(struct drm_device *drm,
164 				 struct i915_vma *vma,
165 				 bool load_polyphase_filter)
166 {
167 	struct drm_i915_private *i915 = to_i915(drm);
168 	struct i915_overlay *overlay = i915->overlay;
169 	struct i915_request *rq;
170 	u32 flip_addr = overlay->flip_addr;
171 	u32 *cs;
172 
173 	drm_WARN_ON(drm, !i915_overlay_is_active(drm));
174 
175 	if (load_polyphase_filter)
176 		flip_addr |= OFC_UPDATE;
177 
178 	rq = alloc_request(overlay, NULL);
179 	if (IS_ERR(rq))
180 		return PTR_ERR(rq);
181 
182 	cs = intel_ring_begin(rq, 2);
183 	if (IS_ERR(cs)) {
184 		i915_request_add(rq);
185 		return PTR_ERR(cs);
186 	}
187 
188 	*cs++ = MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE;
189 	*cs++ = flip_addr;
190 	intel_ring_advance(rq, cs);
191 
192 	i915_overlay_flip_prepare(overlay, vma);
193 	i915_request_add(rq);
194 
195 	return 0;
196 }
197 
198 static void i915_overlay_release_old_vma(struct i915_overlay *overlay)
199 {
200 	struct drm_i915_private *i915 = overlay->i915;
201 	struct intel_display *display = i915->display;
202 	struct i915_vma *vma;
203 
204 	vma = fetch_and_zero(&overlay->old_vma);
205 	if (drm_WARN_ON(&i915->drm, !vma))
206 		return;
207 
208 	intel_frontbuffer_flip(display, overlay->frontbuffer_bits);
209 
210 	i915_vma_unpin(vma);
211 	i915_vma_put(vma);
212 }
213 
214 static void
215 i915_overlay_release_old_vid_tail(struct i915_overlay *overlay)
216 {
217 	i915_overlay_release_old_vma(overlay);
218 }
219 
220 static void i915_overlay_off_tail(struct i915_overlay *overlay)
221 {
222 	struct drm_i915_private *i915 = overlay->i915;
223 
224 	i915_overlay_release_old_vma(overlay);
225 
226 	overlay->frontbuffer_bits = 0;
227 
228 	if (IS_I830(i915))
229 		i830_overlay_clock_gating(i915, true);
230 }
231 
232 static void i915_overlay_last_flip_retire(struct i915_active *active)
233 {
234 	struct i915_overlay *overlay =
235 		container_of(active, typeof(*overlay), last_flip);
236 
237 	if (overlay->flip_complete)
238 		overlay->flip_complete(overlay);
239 }
240 
241 /* overlay needs to be disabled in OCMD reg */
242 static int i915_overlay_off(struct drm_device *drm)
243 {
244 	struct drm_i915_private *i915 = to_i915(drm);
245 	struct i915_overlay *overlay = i915->overlay;
246 	struct i915_request *rq;
247 	u32 *cs, flip_addr = overlay->flip_addr;
248 
249 	drm_WARN_ON(drm, !i915_overlay_is_active(drm));
250 
251 	/*
252 	 * According to intel docs the overlay hw may hang (when switching
253 	 * off) without loading the filter coeffs. It is however unclear whether
254 	 * this applies to the disabling of the overlay or to the switching off
255 	 * of the hw. Do it in both cases.
256 	 */
257 	flip_addr |= OFC_UPDATE;
258 
259 	rq = alloc_request(overlay, i915_overlay_off_tail);
260 	if (IS_ERR(rq))
261 		return PTR_ERR(rq);
262 
263 	cs = intel_ring_begin(rq, 6);
264 	if (IS_ERR(cs)) {
265 		i915_request_add(rq);
266 		return PTR_ERR(cs);
267 	}
268 
269 	/* wait for overlay to go idle */
270 	*cs++ = MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE;
271 	*cs++ = flip_addr;
272 	*cs++ = MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP;
273 
274 	/* turn overlay off */
275 	*cs++ = MI_OVERLAY_FLIP | MI_OVERLAY_OFF;
276 	*cs++ = flip_addr;
277 	*cs++ = MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP;
278 
279 	intel_ring_advance(rq, cs);
280 
281 	i915_overlay_flip_prepare(overlay, NULL);
282 	i915_request_add(rq);
283 
284 	return i915_active_wait(&overlay->last_flip);
285 }
286 
287 /*
288  * Recover from an interruption due to a signal.
289  * We have to be careful not to repeat work forever an make forward progress.
290  */
291 static int i915_overlay_recover_from_interrupt(struct drm_device *drm)
292 {
293 	struct drm_i915_private *i915 = to_i915(drm);
294 	struct i915_overlay *overlay = i915->overlay;
295 
296 	return i915_active_wait(&overlay->last_flip);
297 }
298 
299 /*
300  * Wait for pending overlay flip and release old frame.
301  * Needs to be called before the overlay register are changed
302  * via intel_overlay_(un)map_regs.
303  */
304 static int i915_overlay_release_old_vid(struct drm_device *drm)
305 {
306 	struct drm_i915_private *i915 = to_i915(drm);
307 	struct i915_overlay *overlay = i915->overlay;
308 	struct i915_request *rq;
309 	u32 *cs;
310 
311 	/*
312 	 * Only wait if there is actually an old frame to release to
313 	 * guarantee forward progress.
314 	 */
315 	if (!overlay->old_vma)
316 		return 0;
317 
318 	if (!(intel_uncore_read(&i915->uncore, GEN2_ISR) & I915_OVERLAY_PLANE_FLIP_PENDING_INTERRUPT)) {
319 		i915_overlay_release_old_vid_tail(overlay);
320 		return 0;
321 	}
322 
323 	rq = alloc_request(overlay, i915_overlay_release_old_vid_tail);
324 	if (IS_ERR(rq))
325 		return PTR_ERR(rq);
326 
327 	cs = intel_ring_begin(rq, 2);
328 	if (IS_ERR(cs)) {
329 		i915_request_add(rq);
330 		return PTR_ERR(cs);
331 	}
332 
333 	*cs++ = MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP;
334 	*cs++ = MI_NOOP;
335 	intel_ring_advance(rq, cs);
336 
337 	i915_request_add(rq);
338 
339 	return i915_active_wait(&overlay->last_flip);
340 }
341 
342 static void i915_overlay_reset(struct drm_device *drm)
343 {
344 	struct drm_i915_private *i915 = to_i915(drm);
345 	struct i915_overlay *overlay = i915->overlay;
346 
347 	if (!overlay)
348 		return;
349 
350 	overlay->frontbuffer_bits = 0;
351 }
352 
353 static struct i915_vma *i915_overlay_pin_fb(struct drm_device *drm,
354 					    struct drm_gem_object *obj,
355 					    u32 *offset)
356 {
357 	struct drm_i915_gem_object *new_bo = to_intel_bo(obj);
358 	struct i915_gem_ww_ctx ww;
359 	struct i915_vma *vma;
360 	int ret;
361 
362 	i915_gem_ww_ctx_init(&ww, true);
363 retry:
364 	ret = i915_gem_object_lock(new_bo, &ww);
365 	if (!ret) {
366 		vma = i915_gem_object_pin_to_display_plane(new_bo, &ww, 0, 0,
367 							   NULL, PIN_MAPPABLE);
368 		ret = PTR_ERR_OR_ZERO(vma);
369 	}
370 	if (ret == -EDEADLK) {
371 		ret = i915_gem_ww_ctx_backoff(&ww);
372 		if (!ret)
373 			goto retry;
374 	}
375 	i915_gem_ww_ctx_fini(&ww);
376 	if (ret)
377 		return ERR_PTR(ret);
378 
379 	*offset = i915_ggtt_offset(vma);
380 
381 	return vma;
382 }
383 
384 static void i915_overlay_unpin_fb(struct drm_device *drm,
385 				  struct i915_vma *vma)
386 {
387 	i915_vma_unpin(vma);
388 }
389 
390 static struct drm_gem_object *
391 i915_overlay_obj_lookup(struct drm_device *drm,
392 			struct drm_file *file_priv,
393 			u32 handle)
394 {
395 	struct drm_i915_gem_object *bo;
396 
397 	bo = i915_gem_object_lookup(file_priv, handle);
398 	if (!bo)
399 		return ERR_PTR(-ENOENT);
400 
401 	if (i915_gem_object_is_tiled(bo)) {
402 		drm_dbg(drm, "buffer used for overlay image can not be tiled\n");
403 		i915_gem_object_put(bo);
404 		return ERR_PTR(-EINVAL);
405 	}
406 
407 	return intel_bo_to_drm_bo(bo);
408 }
409 
410 static int get_registers(struct i915_overlay *overlay, bool use_phys)
411 {
412 	struct drm_i915_private *i915 = overlay->i915;
413 	struct drm_i915_gem_object *obj;
414 	struct i915_vma *vma;
415 	int err;
416 
417 	obj = i915_gem_object_create_stolen(i915, PAGE_SIZE);
418 	if (IS_ERR(obj))
419 		obj = i915_gem_object_create_internal(i915, PAGE_SIZE);
420 	if (IS_ERR(obj))
421 		return PTR_ERR(obj);
422 
423 	vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0, PIN_MAPPABLE);
424 	if (IS_ERR(vma)) {
425 		err = PTR_ERR(vma);
426 		goto err_put_bo;
427 	}
428 
429 	if (use_phys)
430 		overlay->flip_addr = sg_dma_address(obj->mm.pages->sgl);
431 	else
432 		overlay->flip_addr = i915_ggtt_offset(vma);
433 	overlay->regs = i915_vma_pin_iomap(vma);
434 	i915_vma_unpin(vma);
435 
436 	if (IS_ERR(overlay->regs)) {
437 		err = PTR_ERR(overlay->regs);
438 		goto err_put_bo;
439 	}
440 
441 	overlay->reg_bo = obj;
442 	return 0;
443 
444 err_put_bo:
445 	i915_gem_object_put(obj);
446 	return err;
447 }
448 
449 static void __iomem *i915_overlay_setup(struct drm_device *drm,
450 					bool needs_physical)
451 {
452 	struct drm_i915_private *i915 = to_i915(drm);
453 	struct intel_engine_cs *engine;
454 	struct i915_overlay *overlay;
455 	int ret;
456 
457 	engine = to_gt(i915)->engine[RCS0];
458 	if (!engine || !engine->kernel_context)
459 		return ERR_PTR(-ENOENT);
460 
461 	overlay = kzalloc_obj(*overlay);
462 	if (!overlay)
463 		return ERR_PTR(-ENOMEM);
464 
465 	overlay->i915 = i915;
466 	overlay->context = engine->kernel_context;
467 
468 	i915_active_init(&overlay->last_flip,
469 			 NULL, i915_overlay_last_flip_retire, 0);
470 
471 	ret = get_registers(overlay, needs_physical);
472 	if (ret) {
473 		kfree(overlay);
474 		return ERR_PTR(ret);
475 	}
476 
477 	i915->overlay = overlay;
478 
479 	return overlay->regs;
480 }
481 
482 static void i915_overlay_cleanup(struct drm_device *drm)
483 {
484 	struct drm_i915_private *i915 = to_i915(drm);
485 	struct i915_overlay *overlay = i915->overlay;
486 
487 	if (!overlay)
488 		return;
489 
490 	/*
491 	 * The bo's should be free'd by the generic code already.
492 	 * Furthermore modesetting teardown happens beforehand so the
493 	 * hardware should be off already.
494 	 */
495 	drm_WARN_ON(drm, i915_overlay_is_active(drm));
496 
497 	i915_gem_object_put(overlay->reg_bo);
498 	i915_active_fini(&overlay->last_flip);
499 
500 	kfree(overlay);
501 	i915->overlay = NULL;
502 }
503 
504 const struct intel_display_overlay_interface i915_display_overlay_interface = {
505 	.is_active = i915_overlay_is_active,
506 	.overlay_on = i915_overlay_on,
507 	.overlay_continue = i915_overlay_continue,
508 	.overlay_off = i915_overlay_off,
509 	.recover_from_interrupt = i915_overlay_recover_from_interrupt,
510 	.release_old_vid = i915_overlay_release_old_vid,
511 	.reset = i915_overlay_reset,
512 	.obj_lookup = i915_overlay_obj_lookup,
513 	.pin_fb = i915_overlay_pin_fb,
514 	.unpin_fb = i915_overlay_unpin_fb,
515 	.setup = i915_overlay_setup,
516 	.cleanup = i915_overlay_cleanup,
517 };
518