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