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