Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/i915/dsb: DSB code refactoring

Refactor DSB implementation to be compatible with Xe driver.

v1: RFC version.
v2: Make intel_dsb structure opaque from external usage. [Jani]
v3: Rebased on latest.
v4:
- Add boundary check in dsb_buffer_memset(). [Luca]
- Use size_t instead of u32. [Luca]
v5: WARN_ON() added for out of boudary case with some optimization. [Luca]
v6: Rebased on latest and fix a rebase-miss.

Cc: Jani Nikula <jani.nikula@intel.com>
Reviewed-by: Luca Coelho <luciano.coelho@intel.com>
Signed-off-by: Animesh Manna <animesh.manna@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20231110032518.3564279-1-animesh.manna@intel.com

+148 -62
+1
drivers/gpu/drm/i915/Makefile
··· 277 277 display/intel_dpt.o \ 278 278 display/intel_drrs.o \ 279 279 display/intel_dsb.o \ 280 + display/intel_dsb_buffer.o \ 280 281 display/intel_fb.o \ 281 282 display/intel_fb_pin.o \ 282 283 display/intel_fbc.o \
+36 -62
drivers/gpu/drm/i915/display/intel_dsb.c
··· 4 4 * 5 5 */ 6 6 7 - #include "gem/i915_gem_internal.h" 8 - #include "gem/i915_gem_lmem.h" 9 - 10 7 #include "i915_drv.h" 11 8 #include "i915_irq.h" 12 9 #include "i915_reg.h" ··· 11 14 #include "intel_de.h" 12 15 #include "intel_display_types.h" 13 16 #include "intel_dsb.h" 17 + #include "intel_dsb_buffer.h" 14 18 #include "intel_dsb_regs.h" 15 19 #include "intel_vblank.h" 16 20 #include "intel_vrr.h" 17 21 #include "skl_watermark.h" 18 22 19 - struct i915_vma; 23 + #define CACHELINE_BYTES 64 20 24 21 25 enum dsb_id { 22 26 INVALID_DSB = -1, ··· 30 32 struct intel_dsb { 31 33 enum dsb_id id; 32 34 33 - u32 *cmd_buf; 34 - struct i915_vma *vma; 35 + struct intel_dsb_buffer dsb_buf; 35 36 struct intel_crtc *crtc; 36 37 37 38 /* ··· 106 109 { 107 110 struct intel_crtc *crtc = dsb->crtc; 108 111 struct drm_i915_private *i915 = to_i915(crtc->base.dev); 109 - const u32 *buf = dsb->cmd_buf; 110 112 int i; 111 113 112 114 drm_dbg_kms(&i915->drm, "[CRTC:%d:%s] DSB %d commands {\n", 113 115 crtc->base.base.id, crtc->base.name, dsb->id); 114 116 for (i = 0; i < ALIGN(dsb->free_pos, 64 / 4); i += 4) 115 117 drm_dbg_kms(&i915->drm, 116 - " 0x%08x: 0x%08x 0x%08x 0x%08x 0x%08x\n", 117 - i * 4, buf[i], buf[i+1], buf[i+2], buf[i+3]); 118 + " 0x%08x: 0x%08x 0x%08x 0x%08x 0x%08x\n", i * 4, 119 + intel_dsb_buffer_read(&dsb->dsb_buf, i), 120 + intel_dsb_buffer_read(&dsb->dsb_buf, i + 1), 121 + intel_dsb_buffer_read(&dsb->dsb_buf, i + 2), 122 + intel_dsb_buffer_read(&dsb->dsb_buf, i + 3)); 118 123 drm_dbg_kms(&i915->drm, "}\n"); 119 124 } 120 125 ··· 128 129 129 130 static void intel_dsb_emit(struct intel_dsb *dsb, u32 ldw, u32 udw) 130 131 { 131 - u32 *buf = dsb->cmd_buf; 132 - 133 132 if (!assert_dsb_has_room(dsb)) 134 133 return; 135 134 ··· 136 139 137 140 dsb->ins_start_offset = dsb->free_pos; 138 141 139 - buf[dsb->free_pos++] = ldw; 140 - buf[dsb->free_pos++] = udw; 142 + intel_dsb_buffer_write(&dsb->dsb_buf, dsb->free_pos++, ldw); 143 + intel_dsb_buffer_write(&dsb->dsb_buf, dsb->free_pos++, udw); 141 144 } 142 145 143 146 static bool intel_dsb_prev_ins_is_write(struct intel_dsb *dsb, 144 147 u32 opcode, i915_reg_t reg) 145 148 { 146 - const u32 *buf = dsb->cmd_buf; 147 149 u32 prev_opcode, prev_reg; 148 150 149 151 /* ··· 153 157 if (dsb->free_pos == 0) 154 158 return false; 155 159 156 - prev_opcode = buf[dsb->ins_start_offset + 1] & ~DSB_REG_VALUE_MASK; 157 - prev_reg = buf[dsb->ins_start_offset + 1] & DSB_REG_VALUE_MASK; 160 + prev_opcode = intel_dsb_buffer_read(&dsb->dsb_buf, 161 + dsb->ins_start_offset + 1) & ~DSB_REG_VALUE_MASK; 162 + prev_reg = intel_dsb_buffer_read(&dsb->dsb_buf, 163 + dsb->ins_start_offset + 1) & DSB_REG_VALUE_MASK; 158 164 159 165 return prev_opcode == opcode && prev_reg == i915_mmio_reg_offset(reg); 160 166 } ··· 189 191 void intel_dsb_reg_write(struct intel_dsb *dsb, 190 192 i915_reg_t reg, u32 val) 191 193 { 194 + u32 old_val; 195 + 192 196 /* 193 197 * For example the buffer will look like below for 3 dwords for auto 194 198 * increment register: ··· 214 214 (DSB_BYTE_EN << DSB_BYTE_EN_SHIFT) | 215 215 i915_mmio_reg_offset(reg)); 216 216 } else { 217 - u32 *buf = dsb->cmd_buf; 218 - 219 217 if (!assert_dsb_has_room(dsb)) 220 218 return; 221 219 222 220 /* convert to indexed write? */ 223 221 if (intel_dsb_prev_ins_is_mmio_write(dsb, reg)) { 224 - u32 prev_val = buf[dsb->ins_start_offset + 0]; 222 + u32 prev_val = intel_dsb_buffer_read(&dsb->dsb_buf, 223 + dsb->ins_start_offset + 0); 225 224 226 - buf[dsb->ins_start_offset + 0] = 1; /* count */ 227 - buf[dsb->ins_start_offset + 1] = 228 - (DSB_OPCODE_INDEXED_WRITE << DSB_OPCODE_SHIFT) | 229 - i915_mmio_reg_offset(reg); 230 - buf[dsb->ins_start_offset + 2] = prev_val; 225 + intel_dsb_buffer_write(&dsb->dsb_buf, 226 + dsb->ins_start_offset + 0, 1); /* count */ 227 + intel_dsb_buffer_write(&dsb->dsb_buf, dsb->ins_start_offset + 1, 228 + (DSB_OPCODE_INDEXED_WRITE << DSB_OPCODE_SHIFT) | 229 + i915_mmio_reg_offset(reg)); 230 + intel_dsb_buffer_write(&dsb->dsb_buf, dsb->ins_start_offset + 2, prev_val); 231 231 232 232 dsb->free_pos++; 233 233 } 234 234 235 - buf[dsb->free_pos++] = val; 235 + intel_dsb_buffer_write(&dsb->dsb_buf, dsb->free_pos++, val); 236 236 /* Update the count */ 237 - buf[dsb->ins_start_offset]++; 237 + old_val = intel_dsb_buffer_read(&dsb->dsb_buf, dsb->ins_start_offset); 238 + intel_dsb_buffer_write(&dsb->dsb_buf, dsb->ins_start_offset, old_val + 1); 238 239 239 240 /* if number of data words is odd, then the last dword should be 0.*/ 240 241 if (dsb->free_pos & 0x1) 241 - buf[dsb->free_pos] = 0; 242 + intel_dsb_buffer_write(&dsb->dsb_buf, dsb->free_pos, 0); 242 243 } 243 244 } 244 245 ··· 298 297 aligned_tail = ALIGN(tail, CACHELINE_BYTES); 299 298 300 299 if (aligned_tail > tail) 301 - memset(&dsb->cmd_buf[dsb->free_pos], 0, 302 - aligned_tail - tail); 300 + intel_dsb_buffer_memset(&dsb->dsb_buf, dsb->free_pos, 0, 301 + aligned_tail - tail); 303 302 304 303 dsb->free_pos = aligned_tail / 4; 305 304 } ··· 318 317 319 318 intel_dsb_align_tail(dsb); 320 319 321 - i915_gem_object_flush_map(dsb->vma->obj); 320 + intel_dsb_buffer_flush_map(&dsb->dsb_buf); 322 321 } 323 322 324 323 static int intel_dsb_dewake_scanline(const struct intel_crtc_state *crtc_state) ··· 362 361 ctrl | DSB_ENABLE); 363 362 364 363 intel_de_write_fw(dev_priv, DSB_HEAD(pipe, dsb->id), 365 - i915_ggtt_offset(dsb->vma)); 364 + intel_dsb_buffer_ggtt_offset(&dsb->dsb_buf)); 366 365 367 366 if (dewake_scanline >= 0) { 368 367 int diff, hw_dewake_scanline; ··· 384 383 } 385 384 386 385 intel_de_write_fw(dev_priv, DSB_TAIL(pipe, dsb->id), 387 - i915_ggtt_offset(dsb->vma) + tail); 386 + intel_dsb_buffer_ggtt_offset(&dsb->dsb_buf) + tail); 388 387 } 389 388 390 389 /** ··· 409 408 enum pipe pipe = crtc->pipe; 410 409 411 410 if (wait_for(!is_dsb_busy(dev_priv, pipe, dsb->id), 1)) { 412 - u32 offset = i915_ggtt_offset(dsb->vma); 411 + u32 offset = intel_dsb_buffer_ggtt_offset(&dsb->dsb_buf); 413 412 414 413 intel_de_write_fw(dev_priv, DSB_CTRL(pipe, dsb->id), 415 414 DSB_ENABLE | DSB_HALT); ··· 446 445 { 447 446 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 448 447 struct drm_i915_private *i915 = to_i915(crtc->base.dev); 449 - struct drm_i915_gem_object *obj; 450 448 intel_wakeref_t wakeref; 451 449 struct intel_dsb *dsb; 452 - struct i915_vma *vma; 453 450 unsigned int size; 454 - u32 *buf; 455 451 456 452 if (!HAS_DSB(i915)) 457 453 return NULL; ··· 462 464 /* ~1 qword per instruction, full cachelines */ 463 465 size = ALIGN(max_cmds * 8, CACHELINE_BYTES); 464 466 465 - if (HAS_LMEM(i915)) { 466 - obj = i915_gem_object_create_lmem(i915, PAGE_ALIGN(size), 467 - I915_BO_ALLOC_CONTIGUOUS); 468 - if (IS_ERR(obj)) 469 - goto out_put_rpm; 470 - } else { 471 - obj = i915_gem_object_create_internal(i915, PAGE_ALIGN(size)); 472 - if (IS_ERR(obj)) 473 - goto out_put_rpm; 474 - 475 - i915_gem_object_set_cache_coherency(obj, I915_CACHE_NONE); 476 - } 477 - 478 - vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0, 0); 479 - if (IS_ERR(vma)) { 480 - i915_gem_object_put(obj); 467 + if (!intel_dsb_buffer_create(crtc, &dsb->dsb_buf, size)) 481 468 goto out_put_rpm; 482 - } 483 - 484 - buf = i915_gem_object_pin_map_unlocked(vma->obj, I915_MAP_WC); 485 - if (IS_ERR(buf)) { 486 - i915_vma_unpin_and_release(&vma, I915_VMA_RELEASE_MAP); 487 - goto out_put_rpm; 488 - } 489 469 490 470 intel_runtime_pm_put(&i915->runtime_pm, wakeref); 491 471 492 472 dsb->id = DSB1; 493 - dsb->vma = vma; 494 473 dsb->crtc = crtc; 495 - dsb->cmd_buf = buf; 496 474 dsb->size = size / 4; /* in dwords */ 497 475 dsb->free_pos = 0; 498 476 dsb->ins_start_offset = 0; ··· 496 522 */ 497 523 void intel_dsb_cleanup(struct intel_dsb *dsb) 498 524 { 499 - i915_vma_unpin_and_release(&dsb->vma, I915_VMA_RELEASE_MAP); 525 + intel_dsb_buffer_cleanup(&dsb->dsb_buf); 500 526 kfree(dsb); 501 527 }
+82
drivers/gpu/drm/i915/display/intel_dsb_buffer.c
··· 1 + // SPDX-License-Identifier: MIT 2 + /* 3 + * Copyright 2023, Intel Corporation. 4 + */ 5 + 6 + #include "gem/i915_gem_internal.h" 7 + #include "gem/i915_gem_lmem.h" 8 + #include "i915_drv.h" 9 + #include "i915_vma.h" 10 + #include "intel_display_types.h" 11 + #include "intel_dsb_buffer.h" 12 + 13 + u32 intel_dsb_buffer_ggtt_offset(struct intel_dsb_buffer *dsb_buf) 14 + { 15 + return i915_ggtt_offset(dsb_buf->vma); 16 + } 17 + 18 + void intel_dsb_buffer_write(struct intel_dsb_buffer *dsb_buf, u32 idx, u32 val) 19 + { 20 + dsb_buf->cmd_buf[idx] = val; 21 + } 22 + 23 + u32 intel_dsb_buffer_read(struct intel_dsb_buffer *dsb_buf, u32 idx) 24 + { 25 + return dsb_buf->cmd_buf[idx]; 26 + } 27 + 28 + void intel_dsb_buffer_memset(struct intel_dsb_buffer *dsb_buf, u32 idx, u32 val, size_t size) 29 + { 30 + WARN_ON(idx > (dsb_buf->buf_size - size) / sizeof(*dsb_buf->cmd_buf)); 31 + 32 + memset(&dsb_buf->cmd_buf[idx], val, size); 33 + } 34 + 35 + bool intel_dsb_buffer_create(struct intel_crtc *crtc, struct intel_dsb_buffer *dsb_buf, size_t size) 36 + { 37 + struct drm_i915_private *i915 = to_i915(crtc->base.dev); 38 + struct drm_i915_gem_object *obj; 39 + struct i915_vma *vma; 40 + u32 *buf; 41 + 42 + if (HAS_LMEM(i915)) { 43 + obj = i915_gem_object_create_lmem(i915, PAGE_ALIGN(size), 44 + I915_BO_ALLOC_CONTIGUOUS); 45 + if (IS_ERR(obj)) 46 + return false; 47 + } else { 48 + obj = i915_gem_object_create_internal(i915, PAGE_ALIGN(size)); 49 + if (IS_ERR(obj)) 50 + return false; 51 + 52 + i915_gem_object_set_cache_coherency(obj, I915_CACHE_NONE); 53 + } 54 + 55 + vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0, 0); 56 + if (IS_ERR(vma)) { 57 + i915_gem_object_put(obj); 58 + return false; 59 + } 60 + 61 + buf = i915_gem_object_pin_map_unlocked(vma->obj, I915_MAP_WC); 62 + if (IS_ERR(buf)) { 63 + i915_vma_unpin_and_release(&vma, I915_VMA_RELEASE_MAP); 64 + return false; 65 + } 66 + 67 + dsb_buf->vma = vma; 68 + dsb_buf->cmd_buf = buf; 69 + dsb_buf->buf_size = size; 70 + 71 + return true; 72 + } 73 + 74 + void intel_dsb_buffer_cleanup(struct intel_dsb_buffer *dsb_buf) 75 + { 76 + i915_vma_unpin_and_release(&dsb_buf->vma, I915_VMA_RELEASE_MAP); 77 + } 78 + 79 + void intel_dsb_buffer_flush_map(struct intel_dsb_buffer *dsb_buf) 80 + { 81 + i915_gem_object_flush_map(dsb_buf->vma->obj); 82 + }
+29
drivers/gpu/drm/i915/display/intel_dsb_buffer.h
··· 1 + /* SPDX-License-Identifier: MIT 2 + * 3 + * Copyright © 2023 Intel Corporation 4 + */ 5 + 6 + #ifndef _INTEL_DSB_BUFFER_H 7 + #define _INTEL_DSB_BUFFER_H 8 + 9 + #include <linux/types.h> 10 + 11 + struct intel_crtc; 12 + struct i915_vma; 13 + 14 + struct intel_dsb_buffer { 15 + u32 *cmd_buf; 16 + struct i915_vma *vma; 17 + size_t buf_size; 18 + }; 19 + 20 + u32 intel_dsb_buffer_ggtt_offset(struct intel_dsb_buffer *dsb_buf); 21 + void intel_dsb_buffer_write(struct intel_dsb_buffer *dsb_buf, u32 idx, u32 val); 22 + u32 intel_dsb_buffer_read(struct intel_dsb_buffer *dsb_buf, u32 idx); 23 + void intel_dsb_buffer_memset(struct intel_dsb_buffer *dsb_buf, u32 idx, u32 val, size_t size); 24 + bool intel_dsb_buffer_create(struct intel_crtc *crtc, struct intel_dsb_buffer *dsb_buf, 25 + size_t size); 26 + void intel_dsb_buffer_cleanup(struct intel_dsb_buffer *dsb_buf); 27 + void intel_dsb_buffer_flush_map(struct intel_dsb_buffer *dsb_buf); 28 + 29 + #endif