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