Commit f021dfd2 authored by Ville Syrjälä's avatar Ville Syrjälä

drm/i915/dsb: Allow the caller to pass in the DSB buffer size

The caller should more or less know how many DSB commands it
wants to emit into the command buffer, so allow it to specify
the size of the command buffer rather than having the low level
DSB code guess it.

Technically we can emit as many as 134+1033 (for adl+ degamma +
10bit gamma) register writes but thanks to the DSB indexed register
write command we get significant space savings so the current size
estimate of 8KiB (~1024 DSB commands) is sufficient for now.
Signed-off-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20221216003810.13338-11-ville.syrjala@linux.intel.comReviewed-by: default avatarAnimesh Manna <animesh.manna@intel.com>
parent e485a3e6
...@@ -1380,7 +1380,7 @@ void intel_color_prepare_commit(struct intel_crtc_state *crtc_state) ...@@ -1380,7 +1380,7 @@ void intel_color_prepare_commit(struct intel_crtc_state *crtc_state)
/* FIXME DSB has issues loading LUTs, disable it for now */ /* FIXME DSB has issues loading LUTs, disable it for now */
return; return;
crtc_state->dsb = intel_dsb_prepare(crtc); crtc_state->dsb = intel_dsb_prepare(crtc, 1024);
} }
void intel_color_cleanup_commit(struct intel_crtc_state *crtc_state) void intel_color_cleanup_commit(struct intel_crtc_state *crtc_state)
......
...@@ -30,21 +30,24 @@ struct intel_dsb { ...@@ -30,21 +30,24 @@ struct intel_dsb {
struct intel_crtc *crtc; struct intel_crtc *crtc;
/* /*
* free_pos will point the first free entry position * maximum number of dwords the buffer will hold.
* and help in calculating tail of command buffer.
*/ */
int free_pos; unsigned int size;
/* /*
* ins_start_offset will help to store start address of the dsb * free_pos will point the first free dword and
* help in calculating tail of command buffer.
*/
unsigned int free_pos;
/*
* ins_start_offset will help to store start dword of the dsb
* instuction and help in identifying the batch of auto-increment * instuction and help in identifying the batch of auto-increment
* register. * register.
*/ */
u32 ins_start_offset; unsigned int ins_start_offset;
}; };
#define DSB_BUF_SIZE (2 * PAGE_SIZE)
/** /**
* DOC: DSB * DOC: DSB
* *
...@@ -76,7 +79,7 @@ static bool assert_dsb_has_room(struct intel_dsb *dsb) ...@@ -76,7 +79,7 @@ static bool assert_dsb_has_room(struct intel_dsb *dsb)
struct drm_i915_private *i915 = to_i915(crtc->base.dev); struct drm_i915_private *i915 = to_i915(crtc->base.dev);
/* each instruction is 2 dwords */ /* each instruction is 2 dwords */
return !drm_WARN(&i915->drm, ALIGN(dsb->free_pos, 2) > DSB_BUF_SIZE / 4 - 2, return !drm_WARN(&i915->drm, dsb->free_pos > dsb->size - 2,
"DSB buffer overflow\n"); "DSB buffer overflow\n");
} }
...@@ -168,7 +171,7 @@ void intel_dsb_reg_write(struct intel_dsb *dsb, ...@@ -168,7 +171,7 @@ void intel_dsb_reg_write(struct intel_dsb *dsb,
if (intel_dsb_prev_ins_is_mmio_write(dsb, reg)) { if (intel_dsb_prev_ins_is_mmio_write(dsb, reg)) {
u32 prev_val = buf[dsb->ins_start_offset + 0]; u32 prev_val = buf[dsb->ins_start_offset + 0];
buf[dsb->ins_start_offset + 0] = 1; /* size */ buf[dsb->ins_start_offset + 0] = 1; /* count */
buf[dsb->ins_start_offset + 1] = buf[dsb->ins_start_offset + 1] =
(DSB_OPCODE_INDEXED_WRITE << DSB_OPCODE_SHIFT) | (DSB_OPCODE_INDEXED_WRITE << DSB_OPCODE_SHIFT) |
i915_mmio_reg_offset(reg); i915_mmio_reg_offset(reg);
...@@ -178,7 +181,7 @@ void intel_dsb_reg_write(struct intel_dsb *dsb, ...@@ -178,7 +181,7 @@ void intel_dsb_reg_write(struct intel_dsb *dsb,
} }
buf[dsb->free_pos++] = val; buf[dsb->free_pos++] = val;
/* Update the size. */ /* Update the count */
buf[dsb->ins_start_offset]++; buf[dsb->ins_start_offset]++;
/* if number of data words is odd, then the last dword should be 0.*/ /* if number of data words is odd, then the last dword should be 0.*/
...@@ -250,6 +253,7 @@ void intel_dsb_commit(struct intel_dsb *dsb) ...@@ -250,6 +253,7 @@ void intel_dsb_commit(struct intel_dsb *dsb)
/** /**
* intel_dsb_prepare() - Allocate, pin and map the DSB command buffer. * intel_dsb_prepare() - Allocate, pin and map the DSB command buffer.
* @crtc: the CRTC * @crtc: the CRTC
* @max_cmds: number of commands we need to fit into command buffer
* *
* This function prepare the command buffer which is used to store dsb * This function prepare the command buffer which is used to store dsb
* instructions with data. * instructions with data.
...@@ -257,25 +261,30 @@ void intel_dsb_commit(struct intel_dsb *dsb) ...@@ -257,25 +261,30 @@ void intel_dsb_commit(struct intel_dsb *dsb)
* Returns: * Returns:
* DSB context, NULL on failure * DSB context, NULL on failure
*/ */
struct intel_dsb *intel_dsb_prepare(struct intel_crtc *crtc) struct intel_dsb *intel_dsb_prepare(struct intel_crtc *crtc,
unsigned int max_cmds)
{ {
struct drm_i915_private *i915 = to_i915(crtc->base.dev); struct drm_i915_private *i915 = to_i915(crtc->base.dev);
struct intel_dsb *dsb;
struct drm_i915_gem_object *obj; struct drm_i915_gem_object *obj;
intel_wakeref_t wakeref;
struct intel_dsb *dsb;
struct i915_vma *vma; struct i915_vma *vma;
unsigned int size;
u32 *buf; u32 *buf;
intel_wakeref_t wakeref;
if (!HAS_DSB(i915)) if (!HAS_DSB(i915))
return NULL; return NULL;
dsb = kmalloc(sizeof(*dsb), GFP_KERNEL); dsb = kzalloc(sizeof(*dsb), GFP_KERNEL);
if (!dsb) if (!dsb)
goto out; goto out;
wakeref = intel_runtime_pm_get(&i915->runtime_pm); wakeref = intel_runtime_pm_get(&i915->runtime_pm);
obj = i915_gem_object_create_internal(i915, DSB_BUF_SIZE); /* ~1 qword per instruction, full cachelines */
size = ALIGN(max_cmds * 8, CACHELINE_BYTES);
obj = i915_gem_object_create_internal(i915, PAGE_ALIGN(size));
if (IS_ERR(obj)) if (IS_ERR(obj))
goto out_put_rpm; goto out_put_rpm;
...@@ -297,6 +306,7 @@ struct intel_dsb *intel_dsb_prepare(struct intel_crtc *crtc) ...@@ -297,6 +306,7 @@ struct intel_dsb *intel_dsb_prepare(struct intel_crtc *crtc)
dsb->vma = vma; dsb->vma = vma;
dsb->crtc = crtc; dsb->crtc = crtc;
dsb->cmd_buf = buf; dsb->cmd_buf = buf;
dsb->size = size / 4; /* in dwords */
dsb->free_pos = 0; dsb->free_pos = 0;
dsb->ins_start_offset = 0; dsb->ins_start_offset = 0;
......
...@@ -13,7 +13,8 @@ ...@@ -13,7 +13,8 @@
struct intel_crtc; struct intel_crtc;
struct intel_dsb; struct intel_dsb;
struct intel_dsb *intel_dsb_prepare(struct intel_crtc *crtc); struct intel_dsb *intel_dsb_prepare(struct intel_crtc *crtc,
unsigned int max_cmds);
void intel_dsb_cleanup(struct intel_dsb *dsb); void intel_dsb_cleanup(struct intel_dsb *dsb);
void intel_dsb_reg_write(struct intel_dsb *dsb, void intel_dsb_reg_write(struct intel_dsb *dsb,
i915_reg_t reg, u32 val); i915_reg_t reg, u32 val);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment