xref: /linux/drivers/gpu/drm/i915/display/intel_fb_bo.c (revision 260f6f4fda93c8485c8037865c941b42b9cba5d2)
1 /* SPDX-License-Identifier: MIT */
2 /*
3  * Copyright © 2021 Intel Corporation
4  */
5 
6 #include <drm/drm_framebuffer.h>
7 
8 #include "gem/i915_gem_object.h"
9 
10 #include "i915_drv.h"
11 #include "intel_display_core.h"
12 #include "intel_display_types.h"
13 #include "intel_fb.h"
14 #include "intel_fb_bo.h"
15 
16 void intel_fb_bo_framebuffer_fini(struct drm_gem_object *obj)
17 {
18 	/* Nothing to do for i915 */
19 }
20 
21 int intel_fb_bo_framebuffer_init(struct drm_framebuffer *fb,
22 				 struct drm_gem_object *_obj,
23 				 struct drm_mode_fb_cmd2 *mode_cmd)
24 {
25 	struct drm_i915_gem_object *obj = to_intel_bo(_obj);
26 	struct intel_display *display = to_intel_display(obj->base.dev);
27 	unsigned int tiling, stride;
28 
29 	i915_gem_object_lock(obj, NULL);
30 	tiling = i915_gem_object_get_tiling(obj);
31 	stride = i915_gem_object_get_stride(obj);
32 	i915_gem_object_unlock(obj);
33 
34 	if (mode_cmd->flags & DRM_MODE_FB_MODIFIERS) {
35 		/*
36 		 * If there's a fence, enforce that
37 		 * the fb modifier and tiling mode match.
38 		 */
39 		if (tiling != I915_TILING_NONE &&
40 		    tiling != intel_fb_modifier_to_tiling(mode_cmd->modifier[0])) {
41 			drm_dbg_kms(display->drm,
42 				    "tiling_mode doesn't match fb modifier\n");
43 			return -EINVAL;
44 		}
45 	} else {
46 		if (tiling == I915_TILING_X) {
47 			mode_cmd->modifier[0] = I915_FORMAT_MOD_X_TILED;
48 		} else if (tiling == I915_TILING_Y) {
49 			drm_dbg_kms(display->drm,
50 				    "No Y tiling for legacy addfb\n");
51 			return -EINVAL;
52 		}
53 	}
54 
55 	/*
56 	 * gen2/3 display engine uses the fence if present,
57 	 * so the tiling mode must match the fb modifier exactly.
58 	 */
59 	if (DISPLAY_VER(display) < 4 &&
60 	    tiling != intel_fb_modifier_to_tiling(mode_cmd->modifier[0])) {
61 		drm_dbg_kms(display->drm,
62 			    "tiling_mode must match fb modifier exactly on gen2/3\n");
63 		return -EINVAL;
64 	}
65 
66 	/*
67 	 * If there's a fence, enforce that
68 	 * the fb pitch and fence stride match.
69 	 */
70 	if (tiling != I915_TILING_NONE && mode_cmd->pitches[0] != stride) {
71 		drm_dbg_kms(display->drm,
72 			    "pitch (%d) must match tiling stride (%d)\n",
73 			    mode_cmd->pitches[0], stride);
74 		return -EINVAL;
75 	}
76 
77 	return 0;
78 }
79 
80 struct drm_gem_object *
81 intel_fb_bo_lookup_valid_bo(struct drm_device *drm,
82 			    struct drm_file *filp,
83 			    const struct drm_mode_fb_cmd2 *mode_cmd)
84 {
85 	struct drm_i915_private *i915 = to_i915(drm);
86 	struct drm_i915_gem_object *obj;
87 
88 	obj = i915_gem_object_lookup(filp, mode_cmd->handles[0]);
89 	if (!obj)
90 		return ERR_PTR(-ENOENT);
91 
92 	/* object is backed with LMEM for discrete */
93 	if (HAS_LMEM(i915) && !i915_gem_object_can_migrate(obj, INTEL_REGION_LMEM_0)) {
94 		/* object is "remote", not in local memory */
95 		i915_gem_object_put(obj);
96 		drm_dbg_kms(&i915->drm, "framebuffer must reside in local memory\n");
97 		return ERR_PTR(-EREMOTE);
98 	}
99 
100 	return intel_bo_to_drm_bo(obj);
101 }
102