xref: /linux/drivers/gpu/drm/i915/i915_dsb_buffer.c (revision 4a57e0913e8c7fff407e97909f4ae48caa84d612)
1 // SPDX-License-Identifier: MIT
2 /*
3  * Copyright 2023, Intel Corporation.
4  */
5 
6 #include <drm/intel/display_parent_interface.h>
7 
8 #include "gem/i915_gem_internal.h"
9 #include "gem/i915_gem_lmem.h"
10 #include "i915_drv.h"
11 #include "i915_dsb_buffer.h"
12 #include "i915_vma.h"
13 
14 struct intel_dsb_buffer {
15 	u32 *cmd_buf;
16 	struct i915_vma *vma;
17 	size_t buf_size;
18 };
19 
20 static u32 intel_dsb_buffer_ggtt_offset(struct intel_dsb_buffer *dsb_buf)
21 {
22 	return i915_ggtt_offset(dsb_buf->vma);
23 }
24 
25 static void intel_dsb_buffer_write(struct intel_dsb_buffer *dsb_buf, u32 idx, u32 val)
26 {
27 	dsb_buf->cmd_buf[idx] = val;
28 }
29 
30 static u32 intel_dsb_buffer_read(struct intel_dsb_buffer *dsb_buf, u32 idx)
31 {
32 	return dsb_buf->cmd_buf[idx];
33 }
34 
35 static void intel_dsb_buffer_fill(struct intel_dsb_buffer *dsb_buf, u32 idx, u32 val, size_t size)
36 {
37 	WARN_ON(idx > (dsb_buf->buf_size - size) / sizeof(*dsb_buf->cmd_buf));
38 
39 	memset(&dsb_buf->cmd_buf[idx], val, size);
40 }
41 
42 static struct intel_dsb_buffer *intel_dsb_buffer_create(struct drm_device *drm, size_t size)
43 {
44 	struct drm_i915_private *i915 = to_i915(drm);
45 	struct intel_dsb_buffer *dsb_buf;
46 	struct drm_i915_gem_object *obj;
47 	struct i915_vma *vma;
48 	u32 *buf;
49 	int ret;
50 
51 	dsb_buf = kzalloc_obj(*dsb_buf);
52 	if (!dsb_buf)
53 		return ERR_PTR(-ENOMEM);
54 
55 	if (HAS_LMEM(i915)) {
56 		obj = i915_gem_object_create_lmem(i915, PAGE_ALIGN(size),
57 						  I915_BO_ALLOC_CONTIGUOUS);
58 		if (IS_ERR(obj)) {
59 			ret = PTR_ERR(obj);
60 			goto err;
61 		}
62 	} else {
63 		obj = i915_gem_object_create_internal(i915, PAGE_ALIGN(size));
64 		if (IS_ERR(obj)) {
65 			ret = PTR_ERR(obj);
66 			goto err;
67 		}
68 
69 		i915_gem_object_set_cache_coherency(obj, I915_CACHE_NONE);
70 	}
71 
72 	vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0, 0);
73 	if (IS_ERR(vma)) {
74 		ret = PTR_ERR(vma);
75 		i915_gem_object_put(obj);
76 		goto err;
77 	}
78 
79 	buf = i915_gem_object_pin_map_unlocked(vma->obj, I915_MAP_WC);
80 	if (IS_ERR(buf)) {
81 		ret = PTR_ERR(buf);
82 		i915_vma_unpin_and_release(&vma, I915_VMA_RELEASE_MAP);
83 		goto err;
84 	}
85 
86 	dsb_buf->vma = vma;
87 	dsb_buf->cmd_buf = buf;
88 	dsb_buf->buf_size = size;
89 
90 	return dsb_buf;
91 
92 err:
93 	kfree(dsb_buf);
94 
95 	return ERR_PTR(ret);
96 }
97 
98 static void intel_dsb_buffer_cleanup(struct intel_dsb_buffer *dsb_buf)
99 {
100 	i915_vma_unpin_and_release(&dsb_buf->vma, I915_VMA_RELEASE_MAP);
101 	kfree(dsb_buf);
102 }
103 
104 static void intel_dsb_buffer_flush_map(struct intel_dsb_buffer *dsb_buf)
105 {
106 	i915_gem_object_flush_map(dsb_buf->vma->obj);
107 }
108 
109 const struct intel_display_dsb_interface i915_display_dsb_interface = {
110 	.ggtt_offset = intel_dsb_buffer_ggtt_offset,
111 	.write = intel_dsb_buffer_write,
112 	.read = intel_dsb_buffer_read,
113 	.fill = intel_dsb_buffer_fill,
114 	.create = intel_dsb_buffer_create,
115 	.cleanup = intel_dsb_buffer_cleanup,
116 	.flush_map = intel_dsb_buffer_flush_map,
117 };
118