1 // SPDX-License-Identifier: MIT 2 /* 3 * Copyright © 2019 Intel Corporation 4 * 5 */ 6 7 #include "gem/i915_gem_internal.h" 8 9 #include "i915_drv.h" 10 #include "i915_reg.h" 11 #include "intel_de.h" 12 #include "intel_display_types.h" 13 #include "intel_dsb.h" 14 15 struct i915_vma; 16 17 enum dsb_id { 18 INVALID_DSB = -1, 19 DSB1, 20 DSB2, 21 DSB3, 22 MAX_DSB_PER_PIPE 23 }; 24 25 struct intel_dsb { 26 enum dsb_id id; 27 28 u32 *cmd_buf; 29 struct i915_vma *vma; 30 struct intel_crtc *crtc; 31 32 /* 33 * maximum number of dwords the buffer will hold. 34 */ 35 unsigned int size; 36 37 /* 38 * free_pos will point the first free dword and 39 * help in calculating tail of command buffer. 40 */ 41 unsigned int free_pos; 42 43 /* 44 * ins_start_offset will help to store start dword of the dsb 45 * instuction and help in identifying the batch of auto-increment 46 * register. 47 */ 48 unsigned int ins_start_offset; 49 }; 50 51 /** 52 * DOC: DSB 53 * 54 * A DSB (Display State Buffer) is a queue of MMIO instructions in the memory 55 * which can be offloaded to DSB HW in Display Controller. DSB HW is a DMA 56 * engine that can be programmed to download the DSB from memory. 57 * It allows driver to batch submit display HW programming. This helps to 58 * reduce loading time and CPU activity, thereby making the context switch 59 * faster. DSB Support added from Gen12 Intel graphics based platform. 60 * 61 * DSB's can access only the pipe, plane, and transcoder Data Island Packet 62 * registers. 63 * 64 * DSB HW can support only register writes (both indexed and direct MMIO 65 * writes). There are no registers reads possible with DSB HW engine. 66 */ 67 68 /* DSB opcodes. */ 69 #define DSB_OPCODE_SHIFT 24 70 #define DSB_OPCODE_NOOP 0x0 71 #define DSB_OPCODE_MMIO_WRITE 0x1 72 #define DSB_OPCODE_WAIT_USEC 0x2 73 #define DSB_OPCODE_WAIT_LINES 0x3 74 #define DSB_OPCODE_WAIT_VBLANKS 0x4 75 #define DSB_OPCODE_WAIT_DSL_IN 0x5 76 #define DSB_OPCODE_WAIT_DSL_OUT 0x6 77 #define DSB_OPCODE_INTERRUPT 0x7 78 #define DSB_OPCODE_INDEXED_WRITE 0x9 79 #define DSB_OPCODE_POLL 0xA 80 #define DSB_BYTE_EN 0xF 81 #define DSB_BYTE_EN_SHIFT 20 82 #define DSB_REG_VALUE_MASK 0xfffff 83 84 static bool assert_dsb_has_room(struct intel_dsb *dsb) 85 { 86 struct intel_crtc *crtc = dsb->crtc; 87 struct drm_i915_private *i915 = to_i915(crtc->base.dev); 88 89 /* each instruction is 2 dwords */ 90 return !drm_WARN(&i915->drm, dsb->free_pos > dsb->size - 2, 91 "DSB buffer overflow\n"); 92 } 93 94 static bool is_dsb_busy(struct drm_i915_private *i915, enum pipe pipe, 95 enum dsb_id id) 96 { 97 return intel_de_read(i915, DSB_CTRL(pipe, id)) & DSB_STATUS_BUSY; 98 } 99 100 static void intel_dsb_emit(struct intel_dsb *dsb, u32 ldw, u32 udw) 101 { 102 u32 *buf = dsb->cmd_buf; 103 104 if (!assert_dsb_has_room(dsb)) 105 return; 106 107 /* Every instruction should be 8 byte aligned. */ 108 dsb->free_pos = ALIGN(dsb->free_pos, 2); 109 110 dsb->ins_start_offset = dsb->free_pos; 111 112 buf[dsb->free_pos++] = ldw; 113 buf[dsb->free_pos++] = udw; 114 } 115 116 static bool intel_dsb_prev_ins_is_write(struct intel_dsb *dsb, 117 u32 opcode, i915_reg_t reg) 118 { 119 const u32 *buf = dsb->cmd_buf; 120 u32 prev_opcode, prev_reg; 121 122 prev_opcode = buf[dsb->ins_start_offset + 1] >> DSB_OPCODE_SHIFT; 123 prev_reg = buf[dsb->ins_start_offset + 1] & DSB_REG_VALUE_MASK; 124 125 return prev_opcode == opcode && prev_reg == i915_mmio_reg_offset(reg); 126 } 127 128 static bool intel_dsb_prev_ins_is_mmio_write(struct intel_dsb *dsb, i915_reg_t reg) 129 { 130 return intel_dsb_prev_ins_is_write(dsb, DSB_OPCODE_MMIO_WRITE, reg); 131 } 132 133 static bool intel_dsb_prev_ins_is_indexed_write(struct intel_dsb *dsb, i915_reg_t reg) 134 { 135 return intel_dsb_prev_ins_is_write(dsb, DSB_OPCODE_INDEXED_WRITE, reg); 136 } 137 138 /** 139 * intel_dsb_reg_write() - Emit register wriite to the DSB context 140 * @dsb: DSB context 141 * @reg: register address. 142 * @val: value. 143 * 144 * This function is used for writing register-value pair in command 145 * buffer of DSB. 146 */ 147 void intel_dsb_reg_write(struct intel_dsb *dsb, 148 i915_reg_t reg, u32 val) 149 { 150 /* 151 * For example the buffer will look like below for 3 dwords for auto 152 * increment register: 153 * +--------------------------------------------------------+ 154 * | size = 3 | offset &| value1 | value2 | value3 | zero | 155 * | | opcode | | | | | 156 * +--------------------------------------------------------+ 157 * + + + + + + + 158 * 0 4 8 12 16 20 24 159 * Byte 160 * 161 * As every instruction is 8 byte aligned the index of dsb instruction 162 * will start always from even number while dealing with u32 array. If 163 * we are writing odd no of dwords, Zeros will be added in the end for 164 * padding. 165 */ 166 if (!intel_dsb_prev_ins_is_mmio_write(dsb, reg) && 167 !intel_dsb_prev_ins_is_indexed_write(dsb, reg)) { 168 intel_dsb_emit(dsb, val, 169 (DSB_OPCODE_MMIO_WRITE << DSB_OPCODE_SHIFT) | 170 (DSB_BYTE_EN << DSB_BYTE_EN_SHIFT) | 171 i915_mmio_reg_offset(reg)); 172 } else { 173 u32 *buf = dsb->cmd_buf; 174 175 if (!assert_dsb_has_room(dsb)) 176 return; 177 178 /* convert to indexed write? */ 179 if (intel_dsb_prev_ins_is_mmio_write(dsb, reg)) { 180 u32 prev_val = buf[dsb->ins_start_offset + 0]; 181 182 buf[dsb->ins_start_offset + 0] = 1; /* count */ 183 buf[dsb->ins_start_offset + 1] = 184 (DSB_OPCODE_INDEXED_WRITE << DSB_OPCODE_SHIFT) | 185 i915_mmio_reg_offset(reg); 186 buf[dsb->ins_start_offset + 2] = prev_val; 187 188 dsb->free_pos++; 189 } 190 191 buf[dsb->free_pos++] = val; 192 /* Update the count */ 193 buf[dsb->ins_start_offset]++; 194 195 /* if number of data words is odd, then the last dword should be 0.*/ 196 if (dsb->free_pos & 0x1) 197 buf[dsb->free_pos] = 0; 198 } 199 } 200 201 static u32 intel_dsb_align_tail(struct intel_dsb *dsb) 202 { 203 u32 aligned_tail, tail; 204 205 tail = dsb->free_pos * 4; 206 aligned_tail = ALIGN(tail, CACHELINE_BYTES); 207 208 if (aligned_tail > tail) 209 memset(&dsb->cmd_buf[dsb->free_pos], 0, 210 aligned_tail - tail); 211 212 dsb->free_pos = aligned_tail / 4; 213 214 return aligned_tail; 215 } 216 217 /** 218 * intel_dsb_commit() - Trigger workload execution of DSB. 219 * @dsb: DSB context 220 * 221 * This function is used to do actual write to hardware using DSB. 222 */ 223 void intel_dsb_commit(struct intel_dsb *dsb) 224 { 225 struct intel_crtc *crtc = dsb->crtc; 226 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); 227 enum pipe pipe = crtc->pipe; 228 u32 tail; 229 230 tail = intel_dsb_align_tail(dsb); 231 if (tail == 0) 232 return; 233 234 if (is_dsb_busy(dev_priv, pipe, dsb->id)) { 235 drm_err(&dev_priv->drm, "DSB engine is busy.\n"); 236 goto reset; 237 } 238 239 intel_de_write(dev_priv, DSB_CTRL(pipe, dsb->id), 240 DSB_ENABLE); 241 intel_de_write(dev_priv, DSB_HEAD(pipe, dsb->id), 242 i915_ggtt_offset(dsb->vma)); 243 intel_de_write(dev_priv, DSB_TAIL(pipe, dsb->id), 244 i915_ggtt_offset(dsb->vma) + tail); 245 246 drm_dbg_kms(&dev_priv->drm, 247 "DSB execution started - head 0x%x, tail 0x%x\n", 248 i915_ggtt_offset(dsb->vma), 249 i915_ggtt_offset(dsb->vma) + tail); 250 251 if (wait_for(!is_dsb_busy(dev_priv, pipe, dsb->id), 1)) 252 drm_err(&dev_priv->drm, 253 "Timed out waiting for DSB workload completion.\n"); 254 255 reset: 256 dsb->free_pos = 0; 257 dsb->ins_start_offset = 0; 258 intel_de_write(dev_priv, DSB_CTRL(pipe, dsb->id), 0); 259 } 260 261 /** 262 * intel_dsb_prepare() - Allocate, pin and map the DSB command buffer. 263 * @crtc: the CRTC 264 * @max_cmds: number of commands we need to fit into command buffer 265 * 266 * This function prepare the command buffer which is used to store dsb 267 * instructions with data. 268 * 269 * Returns: 270 * DSB context, NULL on failure 271 */ 272 struct intel_dsb *intel_dsb_prepare(struct intel_crtc *crtc, 273 unsigned int max_cmds) 274 { 275 struct drm_i915_private *i915 = to_i915(crtc->base.dev); 276 struct drm_i915_gem_object *obj; 277 intel_wakeref_t wakeref; 278 struct intel_dsb *dsb; 279 struct i915_vma *vma; 280 unsigned int size; 281 u32 *buf; 282 283 if (!HAS_DSB(i915)) 284 return NULL; 285 286 dsb = kzalloc(sizeof(*dsb), GFP_KERNEL); 287 if (!dsb) 288 goto out; 289 290 wakeref = intel_runtime_pm_get(&i915->runtime_pm); 291 292 /* ~1 qword per instruction, full cachelines */ 293 size = ALIGN(max_cmds * 8, CACHELINE_BYTES); 294 295 obj = i915_gem_object_create_internal(i915, PAGE_ALIGN(size)); 296 if (IS_ERR(obj)) 297 goto out_put_rpm; 298 299 vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0, 0); 300 if (IS_ERR(vma)) { 301 i915_gem_object_put(obj); 302 goto out_put_rpm; 303 } 304 305 buf = i915_gem_object_pin_map_unlocked(vma->obj, I915_MAP_WC); 306 if (IS_ERR(buf)) { 307 i915_vma_unpin_and_release(&vma, I915_VMA_RELEASE_MAP); 308 goto out_put_rpm; 309 } 310 311 intel_runtime_pm_put(&i915->runtime_pm, wakeref); 312 313 dsb->id = DSB1; 314 dsb->vma = vma; 315 dsb->crtc = crtc; 316 dsb->cmd_buf = buf; 317 dsb->size = size / 4; /* in dwords */ 318 dsb->free_pos = 0; 319 dsb->ins_start_offset = 0; 320 321 return dsb; 322 323 out_put_rpm: 324 intel_runtime_pm_put(&i915->runtime_pm, wakeref); 325 kfree(dsb); 326 out: 327 drm_info_once(&i915->drm, 328 "DSB queue setup failed, will fallback to MMIO for display HW programming\n"); 329 330 return NULL; 331 } 332 333 /** 334 * intel_dsb_cleanup() - To cleanup DSB context. 335 * @dsb: DSB context 336 * 337 * This function cleanup the DSB context by unpinning and releasing 338 * the VMA object associated with it. 339 */ 340 void intel_dsb_cleanup(struct intel_dsb *dsb) 341 { 342 i915_vma_unpin_and_release(&dsb->vma, I915_VMA_RELEASE_MAP); 343 kfree(dsb); 344 } 345