0001
0002
0003
0004
0005
0006
0007 #include "gem/i915_gem_internal.h"
0008
0009 #include "i915_drv.h"
0010 #include "intel_de.h"
0011 #include "intel_display_types.h"
0012
0013 #define DSB_BUF_SIZE (2 * PAGE_SIZE)
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033 #define DSB_OPCODE_SHIFT 24
0034 #define DSB_OPCODE_MMIO_WRITE 0x1
0035 #define DSB_OPCODE_INDEXED_WRITE 0x9
0036 #define DSB_BYTE_EN 0xF
0037 #define DSB_BYTE_EN_SHIFT 20
0038 #define DSB_REG_VALUE_MASK 0xfffff
0039
0040 static bool is_dsb_busy(struct drm_i915_private *i915, enum pipe pipe,
0041 enum dsb_id id)
0042 {
0043 return DSB_STATUS & intel_de_read(i915, DSB_CTRL(pipe, id));
0044 }
0045
0046 static bool intel_dsb_enable_engine(struct drm_i915_private *i915,
0047 enum pipe pipe, enum dsb_id id)
0048 {
0049 u32 dsb_ctrl;
0050
0051 dsb_ctrl = intel_de_read(i915, DSB_CTRL(pipe, id));
0052 if (DSB_STATUS & dsb_ctrl) {
0053 drm_dbg_kms(&i915->drm, "DSB engine is busy.\n");
0054 return false;
0055 }
0056
0057 dsb_ctrl |= DSB_ENABLE;
0058 intel_de_write(i915, DSB_CTRL(pipe, id), dsb_ctrl);
0059
0060 intel_de_posting_read(i915, DSB_CTRL(pipe, id));
0061 return true;
0062 }
0063
0064 static bool intel_dsb_disable_engine(struct drm_i915_private *i915,
0065 enum pipe pipe, enum dsb_id id)
0066 {
0067 u32 dsb_ctrl;
0068
0069 dsb_ctrl = intel_de_read(i915, DSB_CTRL(pipe, id));
0070 if (DSB_STATUS & dsb_ctrl) {
0071 drm_dbg_kms(&i915->drm, "DSB engine is busy.\n");
0072 return false;
0073 }
0074
0075 dsb_ctrl &= ~DSB_ENABLE;
0076 intel_de_write(i915, DSB_CTRL(pipe, id), dsb_ctrl);
0077
0078 intel_de_posting_read(i915, DSB_CTRL(pipe, id));
0079 return true;
0080 }
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095 void intel_dsb_indexed_reg_write(const struct intel_crtc_state *crtc_state,
0096 i915_reg_t reg, u32 val)
0097 {
0098 struct intel_dsb *dsb = crtc_state->dsb;
0099 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
0100 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
0101 u32 *buf;
0102 u32 reg_val;
0103
0104 if (!dsb) {
0105 intel_de_write_fw(dev_priv, reg, val);
0106 return;
0107 }
0108 buf = dsb->cmd_buf;
0109 if (drm_WARN_ON(&dev_priv->drm, dsb->free_pos >= DSB_BUF_SIZE)) {
0110 drm_dbg_kms(&dev_priv->drm, "DSB buffer overflow\n");
0111 return;
0112 }
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130 reg_val = buf[dsb->ins_start_offset + 1] & DSB_REG_VALUE_MASK;
0131 if (reg_val != i915_mmio_reg_offset(reg)) {
0132
0133 dsb->free_pos = ALIGN(dsb->free_pos, 2);
0134
0135 dsb->ins_start_offset = dsb->free_pos;
0136
0137
0138 buf[dsb->free_pos++] = 1;
0139
0140
0141 buf[dsb->free_pos++] = (DSB_OPCODE_INDEXED_WRITE <<
0142 DSB_OPCODE_SHIFT) |
0143 i915_mmio_reg_offset(reg);
0144
0145
0146 buf[dsb->free_pos++] = val;
0147 } else {
0148
0149 buf[dsb->free_pos++] = val;
0150
0151
0152 buf[dsb->ins_start_offset]++;
0153 }
0154
0155
0156 if (dsb->free_pos & 0x1)
0157 buf[dsb->free_pos] = 0;
0158 }
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172 void intel_dsb_reg_write(const struct intel_crtc_state *crtc_state,
0173 i915_reg_t reg, u32 val)
0174 {
0175 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
0176 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
0177 struct intel_dsb *dsb;
0178 u32 *buf;
0179
0180 dsb = crtc_state->dsb;
0181 if (!dsb) {
0182 intel_de_write_fw(dev_priv, reg, val);
0183 return;
0184 }
0185
0186 buf = dsb->cmd_buf;
0187 if (drm_WARN_ON(&dev_priv->drm, dsb->free_pos >= DSB_BUF_SIZE)) {
0188 drm_dbg_kms(&dev_priv->drm, "DSB buffer overflow\n");
0189 return;
0190 }
0191
0192 dsb->ins_start_offset = dsb->free_pos;
0193 buf[dsb->free_pos++] = val;
0194 buf[dsb->free_pos++] = (DSB_OPCODE_MMIO_WRITE << DSB_OPCODE_SHIFT) |
0195 (DSB_BYTE_EN << DSB_BYTE_EN_SHIFT) |
0196 i915_mmio_reg_offset(reg);
0197 }
0198
0199
0200
0201
0202
0203
0204
0205
0206 void intel_dsb_commit(const struct intel_crtc_state *crtc_state)
0207 {
0208 struct intel_dsb *dsb = crtc_state->dsb;
0209 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
0210 struct drm_device *dev = crtc->base.dev;
0211 struct drm_i915_private *dev_priv = to_i915(dev);
0212 enum pipe pipe = crtc->pipe;
0213 u32 tail;
0214
0215 if (!(dsb && dsb->free_pos))
0216 return;
0217
0218 if (!intel_dsb_enable_engine(dev_priv, pipe, dsb->id))
0219 goto reset;
0220
0221 if (is_dsb_busy(dev_priv, pipe, dsb->id)) {
0222 drm_err(&dev_priv->drm,
0223 "HEAD_PTR write failed - dsb engine is busy.\n");
0224 goto reset;
0225 }
0226 intel_de_write(dev_priv, DSB_HEAD(pipe, dsb->id),
0227 i915_ggtt_offset(dsb->vma));
0228
0229 tail = ALIGN(dsb->free_pos * 4, CACHELINE_BYTES);
0230 if (tail > dsb->free_pos * 4)
0231 memset(&dsb->cmd_buf[dsb->free_pos], 0,
0232 (tail - dsb->free_pos * 4));
0233
0234 if (is_dsb_busy(dev_priv, pipe, dsb->id)) {
0235 drm_err(&dev_priv->drm,
0236 "TAIL_PTR write failed - dsb engine is busy.\n");
0237 goto reset;
0238 }
0239 drm_dbg_kms(&dev_priv->drm,
0240 "DSB execution started - head 0x%x, tail 0x%x\n",
0241 i915_ggtt_offset(dsb->vma), tail);
0242 intel_de_write(dev_priv, DSB_TAIL(pipe, dsb->id),
0243 i915_ggtt_offset(dsb->vma) + tail);
0244 if (wait_for(!is_dsb_busy(dev_priv, pipe, dsb->id), 1)) {
0245 drm_err(&dev_priv->drm,
0246 "Timed out waiting for DSB workload completion.\n");
0247 goto reset;
0248 }
0249
0250 reset:
0251 dsb->free_pos = 0;
0252 dsb->ins_start_offset = 0;
0253 intel_dsb_disable_engine(dev_priv, pipe, dsb->id);
0254 }
0255
0256
0257
0258
0259
0260
0261
0262
0263 void intel_dsb_prepare(struct intel_crtc_state *crtc_state)
0264 {
0265 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
0266 struct drm_i915_private *i915 = to_i915(crtc->base.dev);
0267 struct intel_dsb *dsb;
0268 struct drm_i915_gem_object *obj;
0269 struct i915_vma *vma;
0270 u32 *buf;
0271 intel_wakeref_t wakeref;
0272
0273 if (!HAS_DSB(i915))
0274 return;
0275
0276 dsb = kmalloc(sizeof(*dsb), GFP_KERNEL);
0277 if (!dsb) {
0278 drm_err(&i915->drm, "DSB object creation failed\n");
0279 return;
0280 }
0281
0282 wakeref = intel_runtime_pm_get(&i915->runtime_pm);
0283
0284 obj = i915_gem_object_create_internal(i915, DSB_BUF_SIZE);
0285 if (IS_ERR(obj)) {
0286 kfree(dsb);
0287 goto out;
0288 }
0289
0290 vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0, 0);
0291 if (IS_ERR(vma)) {
0292 i915_gem_object_put(obj);
0293 kfree(dsb);
0294 goto out;
0295 }
0296
0297 buf = i915_gem_object_pin_map_unlocked(vma->obj, I915_MAP_WC);
0298 if (IS_ERR(buf)) {
0299 i915_vma_unpin_and_release(&vma, I915_VMA_RELEASE_MAP);
0300 kfree(dsb);
0301 goto out;
0302 }
0303
0304 dsb->id = DSB1;
0305 dsb->vma = vma;
0306 dsb->cmd_buf = buf;
0307 dsb->free_pos = 0;
0308 dsb->ins_start_offset = 0;
0309 crtc_state->dsb = dsb;
0310 out:
0311 if (!crtc_state->dsb)
0312 drm_info(&i915->drm,
0313 "DSB queue setup failed, will fallback to MMIO for display HW programming\n");
0314
0315 intel_runtime_pm_put(&i915->runtime_pm, wakeref);
0316 }
0317
0318
0319
0320
0321
0322
0323
0324
0325 void intel_dsb_cleanup(struct intel_crtc_state *crtc_state)
0326 {
0327 if (!crtc_state->dsb)
0328 return;
0329
0330 i915_vma_unpin_and_release(&crtc_state->dsb->vma, I915_VMA_RELEASE_MAP);
0331 kfree(crtc_state->dsb);
0332 crtc_state->dsb = NULL;
0333 }