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