summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/i915/display/intel_dsb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/i915/display/intel_dsb.c')
-rw-r--r--drivers/gpu/drm/i915/display/intel_dsb.c42
1 files changed, 27 insertions, 15 deletions
diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c b/drivers/gpu/drm/i915/display/intel_dsb.c
index 96bc117fd6a0..bed058d2c3ac 100644
--- a/drivers/gpu/drm/i915/display/intel_dsb.c
+++ b/drivers/gpu/drm/i915/display/intel_dsb.c
@@ -11,6 +11,7 @@
#include "intel_de.h"
#include "intel_display_types.h"
#include "intel_dsb.h"
+#include "intel_dsb_regs.h"
struct i915_vma;
@@ -88,7 +89,8 @@ static bool assert_dsb_has_room(struct intel_dsb *dsb)
/* each instruction is 2 dwords */
return !drm_WARN(&i915->drm, dsb->free_pos > dsb->size - 2,
- "DSB buffer overflow\n");
+ "[CRTC:%d:%s] DSB %d buffer overflow\n",
+ crtc->base.base.id, crtc->base.name, dsb->id);
}
static bool is_dsb_busy(struct drm_i915_private *i915, enum pipe pipe,
@@ -198,7 +200,7 @@ void intel_dsb_reg_write(struct intel_dsb *dsb,
}
}
-static u32 intel_dsb_align_tail(struct intel_dsb *dsb)
+static void intel_dsb_align_tail(struct intel_dsb *dsb)
{
u32 aligned_tail, tail;
@@ -210,49 +212,58 @@ static u32 intel_dsb_align_tail(struct intel_dsb *dsb)
aligned_tail - tail);
dsb->free_pos = aligned_tail / 4;
+}
- return aligned_tail;
+void intel_dsb_finish(struct intel_dsb *dsb)
+{
+ intel_dsb_align_tail(dsb);
}
/**
* intel_dsb_commit() - Trigger workload execution of DSB.
* @dsb: DSB context
+ * @wait_for_vblank: wait for vblank before executing
*
* This function is used to do actual write to hardware using DSB.
*/
-void intel_dsb_commit(struct intel_dsb *dsb)
+void intel_dsb_commit(struct intel_dsb *dsb, bool wait_for_vblank)
{
struct intel_crtc *crtc = dsb->crtc;
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
enum pipe pipe = crtc->pipe;
u32 tail;
- tail = intel_dsb_align_tail(dsb);
- if (tail == 0)
+ tail = dsb->free_pos * 4;
+ if (drm_WARN_ON(&dev_priv->drm, !IS_ALIGNED(tail, CACHELINE_BYTES)))
return;
if (is_dsb_busy(dev_priv, pipe, dsb->id)) {
- drm_err(&dev_priv->drm, "DSB engine is busy.\n");
- goto reset;
+ drm_err(&dev_priv->drm, "[CRTC:%d:%s] DSB %d is busy\n",
+ crtc->base.base.id, crtc->base.name, dsb->id);
+ return;
}
intel_de_write(dev_priv, DSB_CTRL(pipe, dsb->id),
+ (wait_for_vblank ? DSB_WAIT_FOR_VBLANK : 0) |
DSB_ENABLE);
intel_de_write(dev_priv, DSB_HEAD(pipe, dsb->id),
i915_ggtt_offset(dsb->vma));
intel_de_write(dev_priv, DSB_TAIL(pipe, dsb->id),
i915_ggtt_offset(dsb->vma) + tail);
+}
- drm_dbg_kms(&dev_priv->drm,
- "DSB execution started - head 0x%x, tail 0x%x\n",
- i915_ggtt_offset(dsb->vma),
- i915_ggtt_offset(dsb->vma) + tail);
+void intel_dsb_wait(struct intel_dsb *dsb)
+{
+ struct intel_crtc *crtc = dsb->crtc;
+ struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+ enum pipe pipe = crtc->pipe;
if (wait_for(!is_dsb_busy(dev_priv, pipe, dsb->id), 1))
drm_err(&dev_priv->drm,
- "Timed out waiting for DSB workload completion.\n");
+ "[CRTC:%d:%s] DSB %d timed out waiting for idle\n",
+ crtc->base.base.id, crtc->base.name, dsb->id);
-reset:
+ /* Attempt to reset it */
dsb->free_pos = 0;
dsb->ins_start_offset = 0;
intel_de_write(dev_priv, DSB_CTRL(pipe, dsb->id), 0);
@@ -325,7 +336,8 @@ out_put_rpm:
kfree(dsb);
out:
drm_info_once(&i915->drm,
- "DSB queue setup failed, will fallback to MMIO for display HW programming\n");
+ "[CRTC:%d:%s] DSB %d queue setup failed, will fallback to MMIO for display HW programming\n",
+ crtc->base.base.id, crtc->base.name, DSB1);
return NULL;
}