From 0fe76b198d482b41771a8d17b45fb726d13083cf Mon Sep 17 00:00:00 2001 From: Drew Davenport Date: Mon, 26 Dec 2022 22:53:24 -0700 Subject: [PATCH 01/67] drm/i915/display: Check source height is > 0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The error message suggests that the height of the src rect must be at least 1. Reject source with height of 0. Cc: stable@vger.kernel.org Signed-off-by: Drew Davenport Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221226225246.1.I15dff7bb5a0e485c862eae61a69096caf12ef29f@changeid --- drivers/gpu/drm/i915/display/skl_universal_plane.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index 76490cc59d8f..7d07fa3123ec 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -1627,7 +1627,7 @@ static int skl_check_main_surface(struct intel_plane_state *plane_state) u32 offset; int ret; - if (w > max_width || w < min_width || h > max_height) { + if (w > max_width || w < min_width || h > max_height || h < 1) { drm_dbg_kms(&dev_priv->drm, "requested Y/RGB source size %dx%d outside limits (min: %dx1 max: %dx%d)\n", w, h, min_width, max_width, max_height); From e13f2615f7e9eb56bc8723a296d67e18509330ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 16 Dec 2022 02:37:58 +0200 Subject: [PATCH 02/67] drm/i915/dsb: Stop with the RMW MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We don't want to keep random bits set in DSB_CTRL. Stop the harmful RMW. Also flip the reverse & around to appease my ocd. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221216003810.13338-2-ville.syrjala@linux.intel.com Reviewed-by: Animesh Manna --- drivers/gpu/drm/i915/display/intel_dsb.c | 22 +++++++--------------- drivers/gpu/drm/i915/i915_reg.h | 2 +- 2 files changed, 8 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c b/drivers/gpu/drm/i915/display/intel_dsb.c index 3d63c1bf1e4f..ebebaf802dee 100644 --- a/drivers/gpu/drm/i915/display/intel_dsb.c +++ b/drivers/gpu/drm/i915/display/intel_dsb.c @@ -73,42 +73,34 @@ struct intel_dsb { static bool is_dsb_busy(struct drm_i915_private *i915, enum pipe pipe, enum dsb_id id) { - return DSB_STATUS & intel_de_read(i915, DSB_CTRL(pipe, id)); + return intel_de_read(i915, DSB_CTRL(pipe, id)) & DSB_STATUS_BUSY; } static bool intel_dsb_enable_engine(struct drm_i915_private *i915, enum pipe pipe, enum dsb_id id) { - u32 dsb_ctrl; - - dsb_ctrl = intel_de_read(i915, DSB_CTRL(pipe, id)); - if (DSB_STATUS & dsb_ctrl) { + if (is_dsb_busy(i915, pipe, id)) { drm_dbg_kms(&i915->drm, "DSB engine is busy.\n"); return false; } - dsb_ctrl |= DSB_ENABLE; - intel_de_write(i915, DSB_CTRL(pipe, id), dsb_ctrl); - + intel_de_write(i915, DSB_CTRL(pipe, id), DSB_ENABLE); intel_de_posting_read(i915, DSB_CTRL(pipe, id)); + return true; } static bool intel_dsb_disable_engine(struct drm_i915_private *i915, enum pipe pipe, enum dsb_id id) { - u32 dsb_ctrl; - - dsb_ctrl = intel_de_read(i915, DSB_CTRL(pipe, id)); - if (DSB_STATUS & dsb_ctrl) { + if (is_dsb_busy(i915, pipe, id)) { drm_dbg_kms(&i915->drm, "DSB engine is busy.\n"); return false; } - dsb_ctrl &= ~DSB_ENABLE; - intel_de_write(i915, DSB_CTRL(pipe, id), dsb_ctrl); - + intel_de_write(i915, DSB_CTRL(pipe, id), 0); intel_de_posting_read(i915, DSB_CTRL(pipe, id)); + return true; } diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index c76a02c6d22c..18c16e0bed11 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -8102,7 +8102,7 @@ enum skl_power_gate { #define DSB_TAIL(pipe, id) _MMIO(DSBSL_INSTANCE(pipe, id) + 0x4) #define DSB_CTRL(pipe, id) _MMIO(DSBSL_INSTANCE(pipe, id) + 0x8) #define DSB_ENABLE (1 << 31) -#define DSB_STATUS (1 << 0) +#define DSB_STATUS_BUSY (1 << 0) #define CLKREQ_POLICY _MMIO(0x101038) #define CLKREQ_POLICY_MEM_UP_OVRD REG_BIT(1) From f9e2ada6fed6f0067b1d7380f960bc02dcc8acd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 16 Dec 2022 02:37:59 +0200 Subject: [PATCH 03/67] drm/i915/dsb: Inline DSB_CTRL writes into intel_dsb_commit() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No point in having these wrappers for a simple DSB_CTRL write. Inline them into intel_dsb_commit(). Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221216003810.13338-3-ville.syrjala@linux.intel.com Reviewed-by: Animesh Manna --- drivers/gpu/drm/i915/display/intel_dsb.c | 62 ++++++------------------ 1 file changed, 14 insertions(+), 48 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c b/drivers/gpu/drm/i915/display/intel_dsb.c index ebebaf802dee..90a22af30aab 100644 --- a/drivers/gpu/drm/i915/display/intel_dsb.c +++ b/drivers/gpu/drm/i915/display/intel_dsb.c @@ -76,34 +76,6 @@ static bool is_dsb_busy(struct drm_i915_private *i915, enum pipe pipe, return intel_de_read(i915, DSB_CTRL(pipe, id)) & DSB_STATUS_BUSY; } -static bool intel_dsb_enable_engine(struct drm_i915_private *i915, - enum pipe pipe, enum dsb_id id) -{ - if (is_dsb_busy(i915, pipe, id)) { - drm_dbg_kms(&i915->drm, "DSB engine is busy.\n"); - return false; - } - - intel_de_write(i915, DSB_CTRL(pipe, id), DSB_ENABLE); - intel_de_posting_read(i915, DSB_CTRL(pipe, id)); - - return true; -} - -static bool intel_dsb_disable_engine(struct drm_i915_private *i915, - enum pipe pipe, enum dsb_id id) -{ - if (is_dsb_busy(i915, pipe, id)) { - drm_dbg_kms(&i915->drm, "DSB engine is busy.\n"); - return false; - } - - intel_de_write(i915, DSB_CTRL(pipe, id), 0); - intel_de_posting_read(i915, DSB_CTRL(pipe, id)); - - return true; -} - /** * intel_dsb_indexed_reg_write() -Write to the DSB context for auto * increment register. @@ -223,42 +195,36 @@ void intel_dsb_commit(struct intel_dsb *dsb) if (!(dsb && dsb->free_pos)) return; - if (!intel_dsb_enable_engine(dev_priv, pipe, dsb->id)) - goto reset; - - if (is_dsb_busy(dev_priv, pipe, dsb->id)) { - drm_err(&dev_priv->drm, - "HEAD_PTR write failed - dsb engine is busy.\n"); - goto reset; - } - intel_de_write(dev_priv, DSB_HEAD(pipe, dsb->id), - i915_ggtt_offset(dsb->vma)); - tail = ALIGN(dsb->free_pos * 4, CACHELINE_BYTES); if (tail > dsb->free_pos * 4) memset(&dsb->cmd_buf[dsb->free_pos], 0, (tail - dsb->free_pos * 4)); if (is_dsb_busy(dev_priv, pipe, dsb->id)) { - drm_err(&dev_priv->drm, - "TAIL_PTR write failed - dsb engine is busy.\n"); + drm_err(&dev_priv->drm, "DSB engine is busy.\n"); goto reset; } - drm_dbg_kms(&dev_priv->drm, - "DSB execution started - head 0x%x, tail 0x%x\n", - i915_ggtt_offset(dsb->vma), tail); + + intel_de_write(dev_priv, DSB_CTRL(pipe, dsb->id), + 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); - if (wait_for(!is_dsb_busy(dev_priv, pipe, dsb->id), 1)) { + + 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); + + 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"); - goto reset; - } reset: dsb->free_pos = 0; dsb->ins_start_offset = 0; - intel_dsb_disable_engine(dev_priv, pipe, dsb->id); + intel_de_write(dev_priv, DSB_CTRL(pipe, dsb->id), 0); } /** From 3229319e446cafe51e8d3060bdf39203b95a5c98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 16 Dec 2022 02:38:00 +0200 Subject: [PATCH 04/67] drm/i915/dsb: Align DSB register writes to 8 bytes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Every DSB instruction has to be 8byte aligned. Make sure that is the case for the non-indexed register writes as well. The way this could end up unaligned is we emitted an odd number of indexed register writes beforehand. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221216003810.13338-4-ville.syrjala@linux.intel.com Reviewed-by: Animesh Manna --- drivers/gpu/drm/i915/display/intel_dsb.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c b/drivers/gpu/drm/i915/display/intel_dsb.c index 90a22af30aab..6abfd0fc541a 100644 --- a/drivers/gpu/drm/i915/display/intel_dsb.c +++ b/drivers/gpu/drm/i915/display/intel_dsb.c @@ -172,6 +172,9 @@ void intel_dsb_reg_write(struct intel_dsb *dsb, return; } + /* Every instruction should be 8 byte aligned. */ + dsb->free_pos = ALIGN(dsb->free_pos, 2); + dsb->ins_start_offset = dsb->free_pos; buf[dsb->free_pos++] = val; buf[dsb->free_pos++] = (DSB_OPCODE_MMIO_WRITE << DSB_OPCODE_SHIFT) | From 488dd0758366213ab85701d7e687458cfa598c49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 16 Dec 2022 02:38:01 +0200 Subject: [PATCH 05/67] drm/i915/dsb: Fix DSB command buffer size checks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit free_pos is in dwords, DSB_BUF_SIZE in bytes. Directly comparing the two is nonsense. Fix it up, and make sure we also account for the 8byte alignment requirement for each instruction, and also assume that each instruction normally eats two dwords. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221216003810.13338-5-ville.syrjala@linux.intel.com Reviewed-by: Animesh Manna --- drivers/gpu/drm/i915/display/intel_dsb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c b/drivers/gpu/drm/i915/display/intel_dsb.c index 6abfd0fc541a..fbcbf9efd039 100644 --- a/drivers/gpu/drm/i915/display/intel_dsb.c +++ b/drivers/gpu/drm/i915/display/intel_dsb.c @@ -97,7 +97,7 @@ void intel_dsb_indexed_reg_write(struct intel_dsb *dsb, u32 *buf = dsb->cmd_buf; u32 reg_val; - if (drm_WARN_ON(&dev_priv->drm, dsb->free_pos >= DSB_BUF_SIZE)) { + if (drm_WARN_ON(&dev_priv->drm, ALIGN(dsb->free_pos, 2) > DSB_BUF_SIZE / 4 - 2)) { drm_dbg_kms(&dev_priv->drm, "DSB buffer overflow\n"); return; } @@ -167,7 +167,7 @@ void intel_dsb_reg_write(struct intel_dsb *dsb, struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); u32 *buf = dsb->cmd_buf; - if (drm_WARN_ON(&dev_priv->drm, dsb->free_pos >= DSB_BUF_SIZE)) { + if (drm_WARN_ON(&dev_priv->drm, ALIGN(dsb->free_pos, 2) > DSB_BUF_SIZE / 4 - 2)) { drm_dbg_kms(&dev_priv->drm, "DSB buffer overflow\n"); return; } From aab8fbc92ff4cd5b3cb2445402603c7401b60758 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 16 Dec 2022 02:38:02 +0200 Subject: [PATCH 06/67] drm/i915/dsb: Extract assert_dsb_has_room() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pull the DSB command buffer size checks into a small helper so we don't have repeat the same thing multiple times. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221216003810.13338-6-ville.syrjala@linux.intel.com Reviewed-by: Animesh Manna --- drivers/gpu/drm/i915/display/intel_dsb.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c b/drivers/gpu/drm/i915/display/intel_dsb.c index fbcbf9efd039..6fc7d087a7ca 100644 --- a/drivers/gpu/drm/i915/display/intel_dsb.c +++ b/drivers/gpu/drm/i915/display/intel_dsb.c @@ -70,6 +70,16 @@ struct intel_dsb { #define DSB_BYTE_EN_SHIFT 20 #define DSB_REG_VALUE_MASK 0xfffff +static bool assert_dsb_has_room(struct intel_dsb *dsb) +{ + struct intel_crtc *crtc = dsb->crtc; + struct drm_i915_private *i915 = to_i915(crtc->base.dev); + + /* each instruction is 2 dwords */ + return !drm_WARN(&i915->drm, ALIGN(dsb->free_pos, 2) > DSB_BUF_SIZE / 4 - 2, + "DSB buffer overflow\n"); +} + static bool is_dsb_busy(struct drm_i915_private *i915, enum pipe pipe, enum dsb_id id) { @@ -92,15 +102,11 @@ static bool is_dsb_busy(struct drm_i915_private *i915, enum pipe pipe, void intel_dsb_indexed_reg_write(struct intel_dsb *dsb, i915_reg_t reg, u32 val) { - struct intel_crtc *crtc = dsb->crtc; - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); u32 *buf = dsb->cmd_buf; u32 reg_val; - if (drm_WARN_ON(&dev_priv->drm, ALIGN(dsb->free_pos, 2) > DSB_BUF_SIZE / 4 - 2)) { - drm_dbg_kms(&dev_priv->drm, "DSB buffer overflow\n"); + if (!assert_dsb_has_room(dsb)) return; - } /* * For example the buffer will look like below for 3 dwords for auto @@ -163,14 +169,10 @@ void intel_dsb_indexed_reg_write(struct intel_dsb *dsb, void intel_dsb_reg_write(struct intel_dsb *dsb, i915_reg_t reg, u32 val) { - struct intel_crtc *crtc = dsb->crtc; - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); u32 *buf = dsb->cmd_buf; - if (drm_WARN_ON(&dev_priv->drm, ALIGN(dsb->free_pos, 2) > DSB_BUF_SIZE / 4 - 2)) { - drm_dbg_kms(&dev_priv->drm, "DSB buffer overflow\n"); + if (!assert_dsb_has_room(dsb)) return; - } /* Every instruction should be 8 byte aligned. */ dsb->free_pos = ALIGN(dsb->free_pos, 2); From 35118c4c8f564c7aec20eaf8675f5e1cda177a35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 16 Dec 2022 02:38:03 +0200 Subject: [PATCH 07/67] drm/i915/dsb: Extract intel_dsb_emit() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extract a small helper to emit a DSB intstruction. Should become useful if/when we need to start emitting other instructions besides register writes. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221216003810.13338-7-ville.syrjala@linux.intel.com Reviewed-by: Animesh Manna --- drivers/gpu/drm/i915/display/intel_dsb.c | 30 ++++++++++++++++-------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c b/drivers/gpu/drm/i915/display/intel_dsb.c index 6fc7d087a7ca..fb20d9ee84a4 100644 --- a/drivers/gpu/drm/i915/display/intel_dsb.c +++ b/drivers/gpu/drm/i915/display/intel_dsb.c @@ -86,6 +86,22 @@ static bool is_dsb_busy(struct drm_i915_private *i915, enum pipe pipe, return intel_de_read(i915, DSB_CTRL(pipe, id)) & DSB_STATUS_BUSY; } +static void intel_dsb_emit(struct intel_dsb *dsb, u32 ldw, u32 udw) +{ + u32 *buf = dsb->cmd_buf; + + if (!assert_dsb_has_room(dsb)) + return; + + /* Every instruction should be 8 byte aligned. */ + dsb->free_pos = ALIGN(dsb->free_pos, 2); + + dsb->ins_start_offset = dsb->free_pos; + + buf[dsb->free_pos++] = ldw; + buf[dsb->free_pos++] = udw; +} + /** * intel_dsb_indexed_reg_write() -Write to the DSB context for auto * increment register. @@ -169,19 +185,13 @@ void intel_dsb_indexed_reg_write(struct intel_dsb *dsb, void intel_dsb_reg_write(struct intel_dsb *dsb, i915_reg_t reg, u32 val) { - u32 *buf = dsb->cmd_buf; - if (!assert_dsb_has_room(dsb)) return; - /* Every instruction should be 8 byte aligned. */ - dsb->free_pos = ALIGN(dsb->free_pos, 2); - - dsb->ins_start_offset = dsb->free_pos; - buf[dsb->free_pos++] = val; - buf[dsb->free_pos++] = (DSB_OPCODE_MMIO_WRITE << DSB_OPCODE_SHIFT) | - (DSB_BYTE_EN << DSB_BYTE_EN_SHIFT) | - i915_mmio_reg_offset(reg); + intel_dsb_emit(dsb, val, + (DSB_OPCODE_MMIO_WRITE << DSB_OPCODE_SHIFT) | + (DSB_BYTE_EN << DSB_BYTE_EN_SHIFT) | + i915_mmio_reg_offset(reg)); } /** From 08b462fd841205a807e4bc0ba58aed7e90ec8bad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 16 Dec 2022 02:38:04 +0200 Subject: [PATCH 08/67] drm/i915/dsb: Improve the indexed reg write checks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently intel_dsb_indexed_reg_write() just assumes the previous instructions is also an indexed register write, and thus only checks the register offset. Make the check more robust by actually checking the instruction opcode as well. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221216003810.13338-8-ville.syrjala@linux.intel.com Reviewed-by: Animesh Manna --- drivers/gpu/drm/i915/display/intel_dsb.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c b/drivers/gpu/drm/i915/display/intel_dsb.c index fb20d9ee84a4..fcc3f49c5445 100644 --- a/drivers/gpu/drm/i915/display/intel_dsb.c +++ b/drivers/gpu/drm/i915/display/intel_dsb.c @@ -102,6 +102,23 @@ static void intel_dsb_emit(struct intel_dsb *dsb, u32 ldw, u32 udw) buf[dsb->free_pos++] = udw; } +static bool intel_dsb_prev_ins_is_write(struct intel_dsb *dsb, + u32 opcode, i915_reg_t reg) +{ + const u32 *buf = dsb->cmd_buf; + u32 prev_opcode, prev_reg; + + prev_opcode = buf[dsb->ins_start_offset + 1] >> DSB_OPCODE_SHIFT; + prev_reg = buf[dsb->ins_start_offset + 1] & DSB_REG_VALUE_MASK; + + return prev_opcode == opcode && prev_reg == i915_mmio_reg_offset(reg); +} + +static bool intel_dsb_prev_ins_is_indexed_write(struct intel_dsb *dsb, i915_reg_t reg) +{ + return intel_dsb_prev_ins_is_write(dsb, DSB_OPCODE_INDEXED_WRITE, reg); +} + /** * intel_dsb_indexed_reg_write() -Write to the DSB context for auto * increment register. @@ -119,7 +136,6 @@ void intel_dsb_indexed_reg_write(struct intel_dsb *dsb, i915_reg_t reg, u32 val) { u32 *buf = dsb->cmd_buf; - u32 reg_val; if (!assert_dsb_has_room(dsb)) return; @@ -140,8 +156,7 @@ void intel_dsb_indexed_reg_write(struct intel_dsb *dsb, * we are writing odd no of dwords, Zeros will be added in the end for * padding. */ - reg_val = buf[dsb->ins_start_offset + 1] & DSB_REG_VALUE_MASK; - if (reg_val != i915_mmio_reg_offset(reg)) { + if (!intel_dsb_prev_ins_is_indexed_write(dsb, reg)) { /* Every instruction should be 8 byte aligned. */ dsb->free_pos = ALIGN(dsb->free_pos, 2); From 2f65fb5466b498982b2f820f3c06dd28b84110aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 16 Dec 2022 02:38:05 +0200 Subject: [PATCH 09/67] drm/i915/dsb: Handle the indexed vs. not inside the DSB code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The DSB indexed register write insturction is purely an internal DSB implementation detail, no reason why the caller should have to know about it. So let's just have the caller emit blind register writes let the DSB code convert things to an indexed write if/when multiple writes occur to the same register offset in a row. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221216003810.13338-9-ville.syrjala@linux.intel.com Reviewed-by: Animesh Manna --- drivers/gpu/drm/i915/display/intel_color.c | 45 ++++------ drivers/gpu/drm/i915/display/intel_dsb.c | 96 +++++++++------------- drivers/gpu/drm/i915/display/intel_dsb.h | 2 - 3 files changed, 54 insertions(+), 89 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index d57631b0bb9a..76603357252d 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -847,17 +847,6 @@ static void ilk_lut_write(const struct intel_crtc_state *crtc_state, intel_de_write_fw(i915, reg, val); } -static void ilk_lut_write_indexed(const struct intel_crtc_state *crtc_state, - i915_reg_t reg, u32 val) -{ - struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); - - if (crtc_state->dsb) - intel_dsb_indexed_reg_write(crtc_state->dsb, reg, val); - else - intel_de_write_fw(i915, reg, val); -} - static void ilk_load_lut_8(const struct intel_crtc_state *crtc_state, const struct drm_property_blob *blob) { @@ -962,8 +951,8 @@ static void bdw_load_lut_10(const struct intel_crtc_state *crtc_state, prec_index); for (i = 0; i < lut_size; i++) - ilk_lut_write_indexed(crtc_state, PREC_PAL_DATA(pipe), - ilk_lut_10(&lut[i])); + ilk_lut_write(crtc_state, PREC_PAL_DATA(pipe), + ilk_lut_10(&lut[i])); /* * Reset the index, otherwise it prevents the legacy palette to be @@ -1093,13 +1082,13 @@ static void glk_load_degamma_lut(const struct intel_crtc_state *crtc_state, * ToDo: Extend to max 7.0. Enable 32 bit input value * as compared to just 16 to achieve this. */ - ilk_lut_write_indexed(crtc_state, PRE_CSC_GAMC_DATA(pipe), - lut[i].green); + ilk_lut_write(crtc_state, PRE_CSC_GAMC_DATA(pipe), + lut[i].green); } /* Clamp values > 1.0. */ while (i++ < glk_degamma_lut_size(i915)) - ilk_lut_write_indexed(crtc_state, PRE_CSC_GAMC_DATA(pipe), 1 << 16); + ilk_lut_write(crtc_state, PRE_CSC_GAMC_DATA(pipe), 1 << 16); ilk_lut_write(crtc_state, PRE_CSC_GAMC_INDEX(pipe), 0); } @@ -1165,10 +1154,10 @@ icl_program_gamma_superfine_segment(const struct intel_crtc_state *crtc_state) for (i = 0; i < 9; i++) { const struct drm_color_lut *entry = &lut[i]; - ilk_lut_write_indexed(crtc_state, PREC_PAL_MULTI_SEG_DATA(pipe), - ilk_lut_12p4_ldw(entry)); - ilk_lut_write_indexed(crtc_state, PREC_PAL_MULTI_SEG_DATA(pipe), - ilk_lut_12p4_udw(entry)); + ilk_lut_write(crtc_state, PREC_PAL_MULTI_SEG_DATA(pipe), + ilk_lut_12p4_ldw(entry)); + ilk_lut_write(crtc_state, PREC_PAL_MULTI_SEG_DATA(pipe), + ilk_lut_12p4_udw(entry)); } ilk_lut_write(crtc_state, PREC_PAL_MULTI_SEG_INDEX(pipe), @@ -1204,10 +1193,10 @@ icl_program_gamma_multi_segment(const struct intel_crtc_state *crtc_state) for (i = 1; i < 257; i++) { entry = &lut[i * 8]; - ilk_lut_write_indexed(crtc_state, PREC_PAL_DATA(pipe), - ilk_lut_12p4_ldw(entry)); - ilk_lut_write_indexed(crtc_state, PREC_PAL_DATA(pipe), - ilk_lut_12p4_udw(entry)); + ilk_lut_write(crtc_state, PREC_PAL_DATA(pipe), + ilk_lut_12p4_ldw(entry)); + ilk_lut_write(crtc_state, PREC_PAL_DATA(pipe), + ilk_lut_12p4_udw(entry)); } /* @@ -1225,10 +1214,10 @@ icl_program_gamma_multi_segment(const struct intel_crtc_state *crtc_state) for (i = 0; i < 256; i++) { entry = &lut[i * 8 * 128]; - ilk_lut_write_indexed(crtc_state, PREC_PAL_DATA(pipe), - ilk_lut_12p4_ldw(entry)); - ilk_lut_write_indexed(crtc_state, PREC_PAL_DATA(pipe), - ilk_lut_12p4_udw(entry)); + ilk_lut_write(crtc_state, PREC_PAL_DATA(pipe), + ilk_lut_12p4_ldw(entry)); + ilk_lut_write(crtc_state, PREC_PAL_DATA(pipe), + ilk_lut_12p4_udw(entry)); } ilk_lut_write(crtc_state, PREC_PAL_INDEX(pipe), diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c b/drivers/gpu/drm/i915/display/intel_dsb.c index fcc3f49c5445..fa4b808a8134 100644 --- a/drivers/gpu/drm/i915/display/intel_dsb.c +++ b/drivers/gpu/drm/i915/display/intel_dsb.c @@ -114,32 +114,28 @@ static bool intel_dsb_prev_ins_is_write(struct intel_dsb *dsb, return prev_opcode == opcode && prev_reg == i915_mmio_reg_offset(reg); } +static bool intel_dsb_prev_ins_is_mmio_write(struct intel_dsb *dsb, i915_reg_t reg) +{ + return intel_dsb_prev_ins_is_write(dsb, DSB_OPCODE_MMIO_WRITE, reg); +} + static bool intel_dsb_prev_ins_is_indexed_write(struct intel_dsb *dsb, i915_reg_t reg) { return intel_dsb_prev_ins_is_write(dsb, DSB_OPCODE_INDEXED_WRITE, reg); } /** - * intel_dsb_indexed_reg_write() -Write to the DSB context for auto - * increment register. + * intel_dsb_reg_write() - Emit register wriite to the DSB context * @dsb: DSB context * @reg: register address. * @val: value. * * This function is used for writing register-value pair in command - * buffer of DSB for auto-increment register. During command buffer overflow, - * a warning is thrown and rest all erroneous condition register programming - * is done through mmio write. + * buffer of DSB. */ - -void intel_dsb_indexed_reg_write(struct intel_dsb *dsb, - i915_reg_t reg, u32 val) +void intel_dsb_reg_write(struct intel_dsb *dsb, + i915_reg_t reg, u32 val) { - u32 *buf = dsb->cmd_buf; - - if (!assert_dsb_has_room(dsb)) - return; - /* * For example the buffer will look like below for 3 dwords for auto * increment register: @@ -156,57 +152,39 @@ void intel_dsb_indexed_reg_write(struct intel_dsb *dsb, * we are writing odd no of dwords, Zeros will be added in the end for * padding. */ - if (!intel_dsb_prev_ins_is_indexed_write(dsb, reg)) { - /* Every instruction should be 8 byte aligned. */ - dsb->free_pos = ALIGN(dsb->free_pos, 2); - - dsb->ins_start_offset = dsb->free_pos; - - /* Update the size. */ - buf[dsb->free_pos++] = 1; - - /* Update the opcode and reg. */ - buf[dsb->free_pos++] = (DSB_OPCODE_INDEXED_WRITE << - DSB_OPCODE_SHIFT) | - i915_mmio_reg_offset(reg); - - /* Update the value. */ - buf[dsb->free_pos++] = val; + if (!intel_dsb_prev_ins_is_mmio_write(dsb, reg) && + !intel_dsb_prev_ins_is_indexed_write(dsb, reg)) { + intel_dsb_emit(dsb, val, + (DSB_OPCODE_MMIO_WRITE << DSB_OPCODE_SHIFT) | + (DSB_BYTE_EN << DSB_BYTE_EN_SHIFT) | + i915_mmio_reg_offset(reg)); } else { - /* Update the new value. */ - buf[dsb->free_pos++] = val; + u32 *buf = dsb->cmd_buf; + if (!assert_dsb_has_room(dsb)) + return; + + /* convert to indexed write? */ + if (intel_dsb_prev_ins_is_mmio_write(dsb, reg)) { + u32 prev_val = buf[dsb->ins_start_offset + 0]; + + buf[dsb->ins_start_offset + 0] = 1; /* size */ + buf[dsb->ins_start_offset + 1] = + (DSB_OPCODE_INDEXED_WRITE << DSB_OPCODE_SHIFT) | + i915_mmio_reg_offset(reg); + buf[dsb->ins_start_offset + 2] = prev_val; + + dsb->free_pos++; + } + + buf[dsb->free_pos++] = val; /* Update the size. */ buf[dsb->ins_start_offset]++; + + /* if number of data words is odd, then the last dword should be 0.*/ + if (dsb->free_pos & 0x1) + buf[dsb->free_pos] = 0; } - - /* if number of data words is odd, then the last dword should be 0.*/ - if (dsb->free_pos & 0x1) - buf[dsb->free_pos] = 0; -} - -/** - * intel_dsb_reg_write() -Write to the DSB context for normal - * register. - * @crtc_state: intel_crtc_state structure - * @reg: register address. - * @val: value. - * - * This function is used for writing register-value pair in command - * buffer of DSB. During command buffer overflow, a warning is thrown - * and rest all erroneous condition register programming is done - * through mmio write. - */ -void intel_dsb_reg_write(struct intel_dsb *dsb, - i915_reg_t reg, u32 val) -{ - if (!assert_dsb_has_room(dsb)) - return; - - intel_dsb_emit(dsb, val, - (DSB_OPCODE_MMIO_WRITE << DSB_OPCODE_SHIFT) | - (DSB_BYTE_EN << DSB_BYTE_EN_SHIFT) | - i915_mmio_reg_offset(reg)); } /** diff --git a/drivers/gpu/drm/i915/display/intel_dsb.h b/drivers/gpu/drm/i915/display/intel_dsb.h index 25f13c4d5389..25d774049cc2 100644 --- a/drivers/gpu/drm/i915/display/intel_dsb.h +++ b/drivers/gpu/drm/i915/display/intel_dsb.h @@ -17,8 +17,6 @@ struct intel_dsb *intel_dsb_prepare(struct intel_crtc *crtc); void intel_dsb_cleanup(struct intel_dsb *dsb); void intel_dsb_reg_write(struct intel_dsb *dsb, i915_reg_t reg, u32 val); -void intel_dsb_indexed_reg_write(struct intel_dsb *dsb, - i915_reg_t reg, u32 val); void intel_dsb_commit(struct intel_dsb *dsb); #endif From e485a3e6a2d22580ea70c27fc66474f5a28165fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 16 Dec 2022 02:38:06 +0200 Subject: [PATCH 10/67] drm/i915/dsb: Introduce intel_dsb_align_tail() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the DSB tail cacheline alignment to a helper. No need to pollute the caller with mundane details like this. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221216003810.13338-10-ville.syrjala@linux.intel.com Reviewed-by: Animesh Manna --- drivers/gpu/drm/i915/display/intel_dsb.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c b/drivers/gpu/drm/i915/display/intel_dsb.c index fa4b808a8134..636c57767f97 100644 --- a/drivers/gpu/drm/i915/display/intel_dsb.c +++ b/drivers/gpu/drm/i915/display/intel_dsb.c @@ -187,6 +187,22 @@ void intel_dsb_reg_write(struct intel_dsb *dsb, } } +static u32 intel_dsb_align_tail(struct intel_dsb *dsb) +{ + u32 aligned_tail, tail; + + tail = dsb->free_pos * 4; + aligned_tail = ALIGN(tail, CACHELINE_BYTES); + + if (aligned_tail > tail) + memset(&dsb->cmd_buf[dsb->free_pos], 0, + aligned_tail - tail); + + dsb->free_pos = aligned_tail / 4; + + return aligned_tail; +} + /** * intel_dsb_commit() - Trigger workload execution of DSB. * @dsb: DSB context @@ -200,14 +216,10 @@ void intel_dsb_commit(struct intel_dsb *dsb) enum pipe pipe = crtc->pipe; u32 tail; - if (!(dsb && dsb->free_pos)) + tail = intel_dsb_align_tail(dsb); + if (tail == 0) return; - tail = ALIGN(dsb->free_pos * 4, CACHELINE_BYTES); - if (tail > dsb->free_pos * 4) - memset(&dsb->cmd_buf[dsb->free_pos], 0, - (tail - dsb->free_pos * 4)); - if (is_dsb_busy(dev_priv, pipe, dsb->id)) { drm_err(&dev_priv->drm, "DSB engine is busy.\n"); goto reset; From f021dfd232317dd149d3aea09f5d7b7853d00caf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 16 Dec 2022 02:38:07 +0200 Subject: [PATCH 11/67] drm/i915/dsb: Allow the caller to pass in the DSB buffer size MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221216003810.13338-11-ville.syrjala@linux.intel.com Reviewed-by: Animesh Manna --- drivers/gpu/drm/i915/display/intel_color.c | 2 +- drivers/gpu/drm/i915/display/intel_dsb.c | 42 +++++++++++++--------- drivers/gpu/drm/i915/display/intel_dsb.h | 3 +- 3 files changed, 29 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index 76603357252d..8d97c299e657 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -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 */ 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) diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c b/drivers/gpu/drm/i915/display/intel_dsb.c index 636c57767f97..7c593ec84d41 100644 --- a/drivers/gpu/drm/i915/display/intel_dsb.c +++ b/drivers/gpu/drm/i915/display/intel_dsb.c @@ -30,21 +30,24 @@ struct intel_dsb { struct intel_crtc *crtc; /* - * free_pos will point the first free entry position - * and help in calculating tail of command buffer. + * maximum number of dwords the buffer will hold. */ - 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 * register. */ - u32 ins_start_offset; + unsigned int ins_start_offset; }; -#define DSB_BUF_SIZE (2 * PAGE_SIZE) - /** * DOC: 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); /* 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"); } @@ -168,7 +171,7 @@ void intel_dsb_reg_write(struct intel_dsb *dsb, if (intel_dsb_prev_ins_is_mmio_write(dsb, reg)) { 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] = (DSB_OPCODE_INDEXED_WRITE << DSB_OPCODE_SHIFT) | i915_mmio_reg_offset(reg); @@ -178,7 +181,7 @@ void intel_dsb_reg_write(struct intel_dsb *dsb, } buf[dsb->free_pos++] = val; - /* Update the size. */ + /* Update the count */ buf[dsb->ins_start_offset]++; /* if number of data words is odd, then the last dword should be 0.*/ @@ -250,6 +253,7 @@ reset: /** * intel_dsb_prepare() - Allocate, pin and map the DSB command buffer. * @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 * instructions with data. @@ -257,25 +261,30 @@ reset: * Returns: * 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 intel_dsb *dsb; struct drm_i915_gem_object *obj; - struct i915_vma *vma; - u32 *buf; intel_wakeref_t wakeref; + struct intel_dsb *dsb; + struct i915_vma *vma; + unsigned int size; + u32 *buf; if (!HAS_DSB(i915)) return NULL; - dsb = kmalloc(sizeof(*dsb), GFP_KERNEL); + dsb = kzalloc(sizeof(*dsb), GFP_KERNEL); if (!dsb) goto out; 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)) goto out_put_rpm; @@ -297,6 +306,7 @@ struct intel_dsb *intel_dsb_prepare(struct intel_crtc *crtc) dsb->vma = vma; dsb->crtc = crtc; dsb->cmd_buf = buf; + dsb->size = size / 4; /* in dwords */ dsb->free_pos = 0; dsb->ins_start_offset = 0; diff --git a/drivers/gpu/drm/i915/display/intel_dsb.h b/drivers/gpu/drm/i915/display/intel_dsb.h index 25d774049cc2..05c221b6d0a4 100644 --- a/drivers/gpu/drm/i915/display/intel_dsb.h +++ b/drivers/gpu/drm/i915/display/intel_dsb.h @@ -13,7 +13,8 @@ struct intel_crtc; 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_reg_write(struct intel_dsb *dsb, i915_reg_t reg, u32 val); From d0cc74dafba5de159e680533409f87fe7ec46ba9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 16 Dec 2022 02:38:08 +0200 Subject: [PATCH 12/67] drm/i915/dsb: Add mode DSB opcodes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add all the know DSB instruction opcodes. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221216003810.13338-12-ville.syrjala@linux.intel.com Reviewed-by: Animesh Manna --- drivers/gpu/drm/i915/display/intel_dsb.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c b/drivers/gpu/drm/i915/display/intel_dsb.c index 7c593ec84d41..96bc117fd6a0 100644 --- a/drivers/gpu/drm/i915/display/intel_dsb.c +++ b/drivers/gpu/drm/i915/display/intel_dsb.c @@ -67,8 +67,16 @@ struct intel_dsb { /* DSB opcodes. */ #define DSB_OPCODE_SHIFT 24 +#define DSB_OPCODE_NOOP 0x0 #define DSB_OPCODE_MMIO_WRITE 0x1 +#define DSB_OPCODE_WAIT_USEC 0x2 +#define DSB_OPCODE_WAIT_LINES 0x3 +#define DSB_OPCODE_WAIT_VBLANKS 0x4 +#define DSB_OPCODE_WAIT_DSL_IN 0x5 +#define DSB_OPCODE_WAIT_DSL_OUT 0x6 +#define DSB_OPCODE_INTERRUPT 0x7 #define DSB_OPCODE_INDEXED_WRITE 0x9 +#define DSB_OPCODE_POLL 0xA #define DSB_BYTE_EN 0xF #define DSB_BYTE_EN_SHIFT 20 #define DSB_REG_VALUE_MASK 0xfffff From 40a7463c7fe75a886ad7fc5f61371add49b34957 Mon Sep 17 00:00:00 2001 From: Deepak R Varma Date: Wed, 11 Jan 2023 21:21:20 +0530 Subject: [PATCH 13/67] drm/i915/display: Avoid full proxy f_ops for DRRS debug attributes Using DEFINE_SIMPLE_ATTRIBUTE macro with the debugfs_create_file() function adds the overhead of introducing a proxy file operation functions to wrap the original read/write inside file removal protection functions. This adds significant overhead in terms of introducing and managing the proxy factory file operations structure and function wrapping at runtime. As a replacement, a combination of DEFINE_DEBUGFS_ATTRIBUTE macro paired with debugfs_create_file_unsafe() is suggested to be used instead. The DEFINE_DEBUGFS_ATTRIBUTE utilises debugfs_file_get() and debugfs_file_put() wrappers to protect the original read and write function calls for the debug attributes. There is no need for any runtime proxy file operations to be managed by the debugfs core. Following coccicheck make command helped identify this change: make coccicheck M=drivers/gpu/drm/i915/ MODE=patch COCCI=./scripts/coccinelle/api/debugfs/debugfs_simple_attr.cocci Signed-off-by: Deepak R Varma Reviewed-by: Rodrigo Vivi Signed-off-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/9e08dd1b5fabf3e4f54dda27dd1d6ea1dbe6c542.1673451705.git.drv@mailo.com --- drivers/gpu/drm/i915/display/intel_drrs.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_drrs.c b/drivers/gpu/drm/i915/display/intel_drrs.c index 5b9e44443814..29c6421cd666 100644 --- a/drivers/gpu/drm/i915/display/intel_drrs.c +++ b/drivers/gpu/drm/i915/display/intel_drrs.c @@ -374,16 +374,16 @@ out: return ret; } -DEFINE_SIMPLE_ATTRIBUTE(intel_drrs_debugfs_ctl_fops, - NULL, intel_drrs_debugfs_ctl_set, "%llu\n"); +DEFINE_DEBUGFS_ATTRIBUTE(intel_drrs_debugfs_ctl_fops, + NULL, intel_drrs_debugfs_ctl_set, "%llu\n"); void intel_drrs_crtc_debugfs_add(struct intel_crtc *crtc) { debugfs_create_file("i915_drrs_status", 0444, crtc->base.debugfs_entry, crtc, &intel_drrs_debugfs_status_fops); - debugfs_create_file("i915_drrs_ctl", 0644, crtc->base.debugfs_entry, - crtc, &intel_drrs_debugfs_ctl_fops); + debugfs_create_file_unsafe("i915_drrs_ctl", 0644, crtc->base.debugfs_entry, + crtc, &intel_drrs_debugfs_ctl_fops); } static int intel_drrs_debugfs_type_show(struct seq_file *m, void *unused) From c52f523756608e52ab916fc62b537b90a027d3de Mon Sep 17 00:00:00 2001 From: Deepak R Varma Date: Wed, 11 Jan 2023 21:21:59 +0530 Subject: [PATCH 14/67] drm/i915/fbc: Avoid full proxy f_ops for FBC debug attributes Using DEFINE_SIMPLE_ATTRIBUTE macro with the debugfs_create_file() function adds the overhead of introducing a proxy file operation functions to wrap the original read/write inside file removal protection functions. This adds significant overhead in terms of introducing and managing the proxy factory file operations structure and function wrapping at runtime. As a replacement, a combination of DEFINE_DEBUGFS_ATTRIBUTE macro paired with debugfs_create_file_unsafe() is suggested to be used instead. The DEFINE_DEBUGFS_ATTRIBUTE utilises debugfs_file_get() and debugfs_file_put() wrappers to protect the original read and write function calls for the debug attributes. There is no need for any runtime proxy file operations to be managed by the debugfs core. Following coccicheck make command helped identify this change: make coccicheck M=drivers/gpu/drm/i915/ MODE=patch COCCI=./scripts/coccinelle/api/debugfs/debugfs_simple_attr.cocci Signed-off-by: Deepak R Varma Reviewed-by: Rodrigo Vivi Signed-off-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/5d26e924ec8dea21925c77fa79a2bf2a34cef705.1673451705.git.drv@mailo.com --- drivers/gpu/drm/i915/display/intel_fbc.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index 5e69d3c11d21..c508dcf415b4 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -1807,10 +1807,10 @@ static int intel_fbc_debugfs_false_color_set(void *data, u64 val) return 0; } -DEFINE_SIMPLE_ATTRIBUTE(intel_fbc_debugfs_false_color_fops, - intel_fbc_debugfs_false_color_get, - intel_fbc_debugfs_false_color_set, - "%llu\n"); +DEFINE_DEBUGFS_ATTRIBUTE(intel_fbc_debugfs_false_color_fops, + intel_fbc_debugfs_false_color_get, + intel_fbc_debugfs_false_color_set, + "%llu\n"); static void intel_fbc_debugfs_add(struct intel_fbc *fbc, struct dentry *parent) @@ -1819,8 +1819,8 @@ static void intel_fbc_debugfs_add(struct intel_fbc *fbc, fbc, &intel_fbc_debugfs_status_fops); if (fbc->funcs->set_false_color) - debugfs_create_file("i915_fbc_false_color", 0644, parent, - fbc, &intel_fbc_debugfs_false_color_fops); + debugfs_create_file_unsafe("i915_fbc_false_color", 0644, parent, + fbc, &intel_fbc_debugfs_false_color_fops); } void intel_fbc_crtc_debugfs_add(struct intel_crtc *crtc) From cfc10489828a855d671a368d231842f174fe6d26 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 4 Jan 2023 17:32:58 +0200 Subject: [PATCH 15/67] drm/i915/display: drop redundant display/ from #includes Drop the redundant sub-directory from #includes under display/. Group and sort the results. v2: Rebase Reviewed-by: Arun R Murthy Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20230104153258.453431-1-jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_bios.c | 9 ++-- drivers/gpu/drm/i915/display/intel_display.c | 51 ++++++++++---------- drivers/gpu/drm/i915/display/intel_psr.c | 3 +- 3 files changed, 30 insertions(+), 33 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c index 55544d484318..78abe34c7a42 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.c +++ b/drivers/gpu/drm/i915/display/intel_bios.c @@ -25,16 +25,15 @@ * */ -#include #include #include - -#include "display/intel_display.h" -#include "display/intel_display_types.h" -#include "display/intel_gmbus.h" +#include #include "i915_drv.h" #include "i915_reg.h" +#include "intel_display.h" +#include "intel_display_types.h" +#include "intel_gmbus.h" #define _INTEL_BIOS_PRIVATE #include "intel_vbt_defs.h" diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index e75b9b2a0e01..734e8e613f8e 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -24,15 +24,15 @@ * Eric Anholt */ -#include +#include #include #include #include #include -#include #include #include #include +#include #include #include @@ -45,28 +45,6 @@ #include #include -#include "display/intel_audio.h" -#include "display/intel_crt.h" -#include "display/intel_ddi.h" -#include "display/intel_display_debugfs.h" -#include "display/intel_display_power.h" -#include "display/intel_dp.h" -#include "display/intel_dp_mst.h" -#include "display/intel_dpll.h" -#include "display/intel_dpll_mgr.h" -#include "display/intel_drrs.h" -#include "display/intel_dsi.h" -#include "display/intel_dvo.h" -#include "display/intel_fb.h" -#include "display/intel_gmbus.h" -#include "display/intel_hdmi.h" -#include "display/intel_lvds.h" -#include "display/intel_sdvo.h" -#include "display/intel_snps_phy.h" -#include "display/intel_tv.h" -#include "display/intel_vdsc.h" -#include "display/intel_vrr.h" - #include "gem/i915_gem_lmem.h" #include "gem/i915_gem_object.h" @@ -76,31 +54,48 @@ #include "i915_drv.h" #include "i915_reg.h" #include "i915_utils.h" +#include "i9xx_plane.h" #include "icl_dsi.h" #include "intel_acpi.h" #include "intel_atomic.h" #include "intel_atomic_plane.h" +#include "intel_audio.h" #include "intel_bw.h" #include "intel_cdclk.h" #include "intel_color.h" +#include "intel_crt.h" #include "intel_crtc.h" #include "intel_crtc_state_dump.h" +#include "intel_ddi.h" #include "intel_de.h" +#include "intel_display_debugfs.h" +#include "intel_display_power.h" #include "intel_display_types.h" #include "intel_dmc.h" +#include "intel_dp.h" #include "intel_dp_link_training.h" +#include "intel_dp_mst.h" #include "intel_dpio_phy.h" +#include "intel_dpll.h" +#include "intel_dpll_mgr.h" #include "intel_dpt.h" +#include "intel_drrs.h" +#include "intel_dsi.h" +#include "intel_dvo.h" +#include "intel_fb.h" #include "intel_fbc.h" #include "intel_fbdev.h" #include "intel_fdi.h" #include "intel_fifo_underrun.h" #include "intel_frontbuffer.h" +#include "intel_gmbus.h" #include "intel_hdcp.h" +#include "intel_hdmi.h" #include "intel_hotplug.h" #include "intel_hti.h" -#include "intel_modeset_verify.h" +#include "intel_lvds.h" #include "intel_modeset_setup.h" +#include "intel_modeset_verify.h" #include "intel_overlay.h" #include "intel_panel.h" #include "intel_pch_display.h" @@ -112,10 +107,14 @@ #include "intel_pps.h" #include "intel_psr.h" #include "intel_quirks.h" +#include "intel_sdvo.h" +#include "intel_snps_phy.h" #include "intel_sprite.h" #include "intel_tc.h" +#include "intel_tv.h" +#include "intel_vdsc.h" #include "intel_vga.h" -#include "i9xx_plane.h" +#include "intel_vrr.h" #include "skl_scaler.h" #include "skl_universal_plane.h" #include "skl_watermark.h" diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index d0d774219cc5..c9c00f8fa1b2 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -24,14 +24,13 @@ #include #include -#include "display/intel_dp.h" - #include "i915_drv.h" #include "i915_reg.h" #include "intel_atomic.h" #include "intel_crtc.h" #include "intel_de.h" #include "intel_display_types.h" +#include "intel_dp.h" #include "intel_dp_aux.h" #include "intel_hdmi.h" #include "intel_psr.h" From af9f44d3515119c7e8c8f30e5556e6a477f2f34e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jouni=20H=C3=B6gander?= Date: Thu, 5 Jan 2023 08:56:37 +0200 Subject: [PATCH 16/67] drm/i915/psr: Implement Wa_14015648006 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add 4th pipe and extend TGL Wa_16013835468 to support ADLP, MTL and DG2 and all TGL steppings. BSpec: 54369, 55378, 66624 v3: - commit message modified v2: - apply for PSR1 as well - remove stepping information from comments Cc: Matt Roper Cc: José Roberto de Souza Cc: Stanislav Lisovskiy Signed-off-by: Mika Kahola Signed-off-by: Jouni Högander Reviewed-by: Matt Roper Signed-off-by: Stanislav Lisovskiy Link: https://patchwork.freedesktop.org/patch/msgid/20230105065637.2063311-1-jouni.hogander@intel.com --- drivers/gpu/drm/i915/display/intel_psr.c | 48 ++++++++++++++---------- drivers/gpu/drm/i915/i915_reg.h | 1 + 2 files changed, 29 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index c9c00f8fa1b2..7d4a15a283a0 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -1111,6 +1111,8 @@ static u32 wa_16013835468_bit_get(struct intel_dp *intel_dp) return LATENCY_REPORTING_REMOVED_PIPE_B; case PIPE_C: return LATENCY_REPORTING_REMOVED_PIPE_C; + case PIPE_D: + return LATENCY_REPORTING_REMOVED_PIPE_D; default: MISSING_CASE(intel_dp->psr.pipe); return 0; @@ -1162,6 +1164,23 @@ static void intel_psr_enable_source(struct intel_dp *intel_dp, intel_dp->psr.psr2_sel_fetch_enabled ? IGNORE_PSR2_HW_TRACKING : 0); + /* + * Wa_16013835468 + * Wa_14015648006 + */ + if (IS_MTL_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0) || + IS_DISPLAY_VER(dev_priv, 12, 13)) { + u16 vtotal, vblank; + + vtotal = crtc_state->uapi.adjusted_mode.crtc_vtotal - + crtc_state->uapi.adjusted_mode.crtc_vdisplay; + vblank = crtc_state->uapi.adjusted_mode.crtc_vblank_end - + crtc_state->uapi.adjusted_mode.crtc_vblank_start; + if (vblank > vtotal) + intel_de_rmw(dev_priv, GEN8_CHICKEN_DCPR_1, 0, + wa_16013835468_bit_get(intel_dp)); + } + if (intel_dp->psr.psr2_enabled) { if (DISPLAY_VER(dev_priv) == 9) intel_de_rmw(dev_priv, CHICKEN_TRANS(cpu_transcoder), 0, @@ -1195,20 +1214,6 @@ static void intel_psr_enable_source(struct intel_dp *intel_dp, else if (IS_ALDERLAKE_P(dev_priv)) intel_de_rmw(dev_priv, CLKGATE_DIS_MISC, 0, CLKGATE_DIS_MISC_DMASC_GATING_DIS); - - /* Wa_16013835468:tgl[b0+], dg1 */ - if (IS_TGL_DISPLAY_STEP(dev_priv, STEP_B0, STEP_FOREVER) || - IS_DG1(dev_priv)) { - u16 vtotal, vblank; - - vtotal = crtc_state->uapi.adjusted_mode.crtc_vtotal - - crtc_state->uapi.adjusted_mode.crtc_vdisplay; - vblank = crtc_state->uapi.adjusted_mode.crtc_vblank_end - - crtc_state->uapi.adjusted_mode.crtc_vblank_start; - if (vblank > vtotal) - intel_de_rmw(dev_priv, GEN8_CHICKEN_DCPR_1, 0, - wa_16013835468_bit_get(intel_dp)); - } } } @@ -1361,6 +1366,15 @@ static void intel_psr_disable_locked(struct intel_dp *intel_dp) intel_de_rmw(dev_priv, CHICKEN_PAR1_1, DIS_RAM_BYPASS_PSR2_MAN_TRACK, 0); + /* + * Wa_16013835468 + * Wa_14015648006 + */ + if (IS_MTL_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0) || + IS_DISPLAY_VER(dev_priv, 12, 13)) + intel_de_rmw(dev_priv, GEN8_CHICKEN_DCPR_1, + wa_16013835468_bit_get(intel_dp), 0); + if (intel_dp->psr.psr2_enabled) { /* Wa_16011168373:adl-p */ if (IS_ADLP_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0)) @@ -1376,12 +1390,6 @@ static void intel_psr_disable_locked(struct intel_dp *intel_dp) else if (IS_ALDERLAKE_P(dev_priv)) intel_de_rmw(dev_priv, CLKGATE_DIS_MISC, CLKGATE_DIS_MISC_DMASC_GATING_DIS, 0); - - /* Wa_16013835468:tgl[b0+], dg1 */ - if (IS_TGL_DISPLAY_STEP(dev_priv, STEP_B0, STEP_FOREVER) || - IS_DG1(dev_priv)) - intel_de_rmw(dev_priv, GEN8_CHICKEN_DCPR_1, - wa_16013835468_bit_get(intel_dp), 0); } intel_snps_phy_update_psr_power_state(dev_priv, phy, false); diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 18c16e0bed11..e89236cf96dc 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -5734,6 +5734,7 @@ #define RESET_PCH_HANDSHAKE_ENABLE REG_BIT(4) #define GEN8_CHICKEN_DCPR_1 _MMIO(0x46430) +#define LATENCY_REPORTING_REMOVED_PIPE_D REG_BIT(31) #define SKL_SELECT_ALTERNATE_DC_EXIT REG_BIT(30) #define LATENCY_REPORTING_REMOVED_PIPE_C REG_BIT(25) #define LATENCY_REPORTING_REMOVED_PIPE_B REG_BIT(24) From 62fe4515cf202700a346bb0c3436ae538a888707 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 16 Jan 2023 14:56:12 +0200 Subject: [PATCH 17/67] drm/i915/irq: split out vblank/scanline code to intel_vblank.[ch] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The vblank/scanline code is fairly isolated in i915_irq.c. Split it out to new intel_vblank.[ch]. Cc: Ville Syrjälä Signed-off-by: Jani Nikula Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/3e3e9016f5135dccae5110c291ba048567622e7a.1673873708.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/Makefile | 1 + drivers/gpu/drm/i915/display/intel_crtc.c | 1 + .../drm/i915/display/intel_display_trace.h | 1 + drivers/gpu/drm/i915/display/intel_vblank.c | 419 ++++++++++++++++++ drivers/gpu/drm/i915/display/intel_vblank.h | 21 + drivers/gpu/drm/i915/i915_irq.c | 408 ----------------- drivers/gpu/drm/i915/i915_irq.h | 6 - 7 files changed, 443 insertions(+), 414 deletions(-) create mode 100644 drivers/gpu/drm/i915/display/intel_vblank.c create mode 100644 drivers/gpu/drm/i915/display/intel_vblank.h diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 7046e435a155..05c17565cf31 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -263,6 +263,7 @@ i915-y += \ display/intel_quirks.o \ display/intel_sprite.o \ display/intel_tc.o \ + display/intel_vblank.o \ display/intel_vga.o \ display/i9xx_plane.o \ display/skl_scaler.o \ diff --git a/drivers/gpu/drm/i915/display/intel_crtc.c b/drivers/gpu/drm/i915/display/intel_crtc.c index 037fc140b585..82be0fbe9934 100644 --- a/drivers/gpu/drm/i915/display/intel_crtc.c +++ b/drivers/gpu/drm/i915/display/intel_crtc.c @@ -28,6 +28,7 @@ #include "intel_pipe_crc.h" #include "intel_psr.h" #include "intel_sprite.h" +#include "intel_vblank.h" #include "intel_vrr.h" #include "skl_universal_plane.h" diff --git a/drivers/gpu/drm/i915/display/intel_display_trace.h b/drivers/gpu/drm/i915/display/intel_display_trace.h index 725aba3fa531..651ea8564e1b 100644 --- a/drivers/gpu/drm/i915/display/intel_display_trace.h +++ b/drivers/gpu/drm/i915/display/intel_display_trace.h @@ -17,6 +17,7 @@ #include "i915_irq.h" #include "intel_crtc.h" #include "intel_display_types.h" +#include "intel_vblank.h" #define __dev_name_i915(i915) dev_name((i915)->drm.dev) #define __dev_name_kms(obj) dev_name((obj)->base.dev->dev) diff --git a/drivers/gpu/drm/i915/display/intel_vblank.c b/drivers/gpu/drm/i915/display/intel_vblank.c new file mode 100644 index 000000000000..6392a56ae7d4 --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_vblank.c @@ -0,0 +1,419 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2022-2023 Intel Corporation + */ + +#include "i915_drv.h" +#include "i915_reg.h" +#include "intel_de.h" +#include "intel_display_types.h" +#include "intel_vblank.h" + +/* + * This timing diagram depicts the video signal in and + * around the vertical blanking period. + * + * Assumptions about the fictitious mode used in this example: + * vblank_start >= 3 + * vsync_start = vblank_start + 1 + * vsync_end = vblank_start + 2 + * vtotal = vblank_start + 3 + * + * start of vblank: + * latch double buffered registers + * increment frame counter (ctg+) + * generate start of vblank interrupt (gen4+) + * | + * | frame start: + * | generate frame start interrupt (aka. vblank interrupt) (gmch) + * | may be shifted forward 1-3 extra lines via PIPECONF + * | | + * | | start of vsync: + * | | generate vsync interrupt + * | | | + * ___xxxx___ ___xxxx___ ___xxxx___ ___xxxx___ ___xxxx___ ___xxxx + * . \hs/ . \hs/ \hs/ \hs/ . \hs/ + * ----va---> <-----------------vb--------------------> <--------va------------- + * | | <----vs-----> | + * -vbs-----> <---vbs+1---> <---vbs+2---> <-----0-----> <-----1-----> <-----2--- (scanline counter gen2) + * -vbs-2---> <---vbs-1---> <---vbs-----> <---vbs+1---> <---vbs+2---> <-----0--- (scanline counter gen3+) + * -vbs-2---> <---vbs-2---> <---vbs-1---> <---vbs-----> <---vbs+1---> <---vbs+2- (scanline counter hsw+ hdmi) + * | | | + * last visible pixel first visible pixel + * | increment frame counter (gen3/4) + * pixel counter = vblank_start * htotal pixel counter = 0 (gen3/4) + * + * x = horizontal active + * _ = horizontal blanking + * hs = horizontal sync + * va = vertical active + * vb = vertical blanking + * vs = vertical sync + * vbs = vblank_start (number) + * + * Summary: + * - most events happen at the start of horizontal sync + * - frame start happens at the start of horizontal blank, 1-4 lines + * (depending on PIPECONF settings) after the start of vblank + * - gen3/4 pixel and frame counter are synchronized with the start + * of horizontal active on the first line of vertical active + */ + +/* + * Called from drm generic code, passed a 'crtc', which we use as a pipe index. + */ +u32 i915_get_vblank_counter(struct drm_crtc *crtc) +{ + struct drm_i915_private *dev_priv = to_i915(crtc->dev); + struct drm_vblank_crtc *vblank = &dev_priv->drm.vblank[drm_crtc_index(crtc)]; + const struct drm_display_mode *mode = &vblank->hwmode; + enum pipe pipe = to_intel_crtc(crtc)->pipe; + i915_reg_t high_frame, low_frame; + u32 high1, high2, low, pixel, vbl_start, hsync_start, htotal; + unsigned long irqflags; + + /* + * On i965gm TV output the frame counter only works up to + * the point when we enable the TV encoder. After that the + * frame counter ceases to work and reads zero. We need a + * vblank wait before enabling the TV encoder and so we + * have to enable vblank interrupts while the frame counter + * is still in a working state. However the core vblank code + * does not like us returning non-zero frame counter values + * when we've told it that we don't have a working frame + * counter. Thus we must stop non-zero values leaking out. + */ + if (!vblank->max_vblank_count) + return 0; + + htotal = mode->crtc_htotal; + hsync_start = mode->crtc_hsync_start; + vbl_start = mode->crtc_vblank_start; + if (mode->flags & DRM_MODE_FLAG_INTERLACE) + vbl_start = DIV_ROUND_UP(vbl_start, 2); + + /* Convert to pixel count */ + vbl_start *= htotal; + + /* Start of vblank event occurs at start of hsync */ + vbl_start -= htotal - hsync_start; + + high_frame = PIPEFRAME(pipe); + low_frame = PIPEFRAMEPIXEL(pipe); + + spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); + + /* + * High & low register fields aren't synchronized, so make sure + * we get a low value that's stable across two reads of the high + * register. + */ + do { + high1 = intel_de_read_fw(dev_priv, high_frame) & PIPE_FRAME_HIGH_MASK; + low = intel_de_read_fw(dev_priv, low_frame); + high2 = intel_de_read_fw(dev_priv, high_frame) & PIPE_FRAME_HIGH_MASK; + } while (high1 != high2); + + spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); + + high1 >>= PIPE_FRAME_HIGH_SHIFT; + pixel = low & PIPE_PIXEL_MASK; + low >>= PIPE_FRAME_LOW_SHIFT; + + /* + * The frame counter increments at beginning of active. + * Cook up a vblank counter by also checking the pixel + * counter against vblank start. + */ + return (((high1 << 8) | low) + (pixel >= vbl_start)) & 0xffffff; +} + +u32 g4x_get_vblank_counter(struct drm_crtc *crtc) +{ + struct drm_i915_private *dev_priv = to_i915(crtc->dev); + struct drm_vblank_crtc *vblank = &dev_priv->drm.vblank[drm_crtc_index(crtc)]; + enum pipe pipe = to_intel_crtc(crtc)->pipe; + + if (!vblank->max_vblank_count) + return 0; + + return intel_uncore_read(&dev_priv->uncore, PIPE_FRMCOUNT_G4X(pipe)); +} + +static u32 intel_crtc_scanlines_since_frame_timestamp(struct intel_crtc *crtc) +{ + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + struct drm_vblank_crtc *vblank = + &crtc->base.dev->vblank[drm_crtc_index(&crtc->base)]; + const struct drm_display_mode *mode = &vblank->hwmode; + u32 htotal = mode->crtc_htotal; + u32 clock = mode->crtc_clock; + u32 scan_prev_time, scan_curr_time, scan_post_time; + + /* + * To avoid the race condition where we might cross into the + * next vblank just between the PIPE_FRMTMSTMP and TIMESTAMP_CTR + * reads. We make sure we read PIPE_FRMTMSTMP and TIMESTAMP_CTR + * during the same frame. + */ + do { + /* + * This field provides read back of the display + * pipe frame time stamp. The time stamp value + * is sampled at every start of vertical blank. + */ + scan_prev_time = intel_de_read_fw(dev_priv, + PIPE_FRMTMSTMP(crtc->pipe)); + + /* + * The TIMESTAMP_CTR register has the current + * time stamp value. + */ + scan_curr_time = intel_de_read_fw(dev_priv, IVB_TIMESTAMP_CTR); + + scan_post_time = intel_de_read_fw(dev_priv, + PIPE_FRMTMSTMP(crtc->pipe)); + } while (scan_post_time != scan_prev_time); + + return div_u64(mul_u32_u32(scan_curr_time - scan_prev_time, + clock), 1000 * htotal); +} + +/* + * On certain encoders on certain platforms, pipe + * scanline register will not work to get the scanline, + * since the timings are driven from the PORT or issues + * with scanline register updates. + * This function will use Framestamp and current + * timestamp registers to calculate the scanline. + */ +static u32 __intel_get_crtc_scanline_from_timestamp(struct intel_crtc *crtc) +{ + struct drm_vblank_crtc *vblank = + &crtc->base.dev->vblank[drm_crtc_index(&crtc->base)]; + const struct drm_display_mode *mode = &vblank->hwmode; + u32 vblank_start = mode->crtc_vblank_start; + u32 vtotal = mode->crtc_vtotal; + u32 scanline; + + scanline = intel_crtc_scanlines_since_frame_timestamp(crtc); + scanline = min(scanline, vtotal - 1); + scanline = (scanline + vblank_start) % vtotal; + + return scanline; +} + +/* + * intel_de_read_fw(), only for fast reads of display block, no need for + * forcewake etc. + */ +static int __intel_get_crtc_scanline(struct intel_crtc *crtc) +{ + struct drm_device *dev = crtc->base.dev; + struct drm_i915_private *dev_priv = to_i915(dev); + const struct drm_display_mode *mode; + struct drm_vblank_crtc *vblank; + enum pipe pipe = crtc->pipe; + int position, vtotal; + + if (!crtc->active) + return 0; + + vblank = &crtc->base.dev->vblank[drm_crtc_index(&crtc->base)]; + mode = &vblank->hwmode; + + if (crtc->mode_flags & I915_MODE_FLAG_GET_SCANLINE_FROM_TIMESTAMP) + return __intel_get_crtc_scanline_from_timestamp(crtc); + + vtotal = mode->crtc_vtotal; + if (mode->flags & DRM_MODE_FLAG_INTERLACE) + vtotal /= 2; + + position = intel_de_read_fw(dev_priv, PIPEDSL(pipe)) & PIPEDSL_LINE_MASK; + + /* + * On HSW, the DSL reg (0x70000) appears to return 0 if we + * read it just before the start of vblank. So try it again + * so we don't accidentally end up spanning a vblank frame + * increment, causing the pipe_update_end() code to squak at us. + * + * The nature of this problem means we can't simply check the ISR + * bit and return the vblank start value; nor can we use the scanline + * debug register in the transcoder as it appears to have the same + * problem. We may need to extend this to include other platforms, + * but so far testing only shows the problem on HSW. + */ + if (HAS_DDI(dev_priv) && !position) { + int i, temp; + + for (i = 0; i < 100; i++) { + udelay(1); + temp = intel_de_read_fw(dev_priv, PIPEDSL(pipe)) & PIPEDSL_LINE_MASK; + if (temp != position) { + position = temp; + break; + } + } + } + + /* + * See update_scanline_offset() for the details on the + * scanline_offset adjustment. + */ + return (position + crtc->scanline_offset) % vtotal; +} + +static bool i915_get_crtc_scanoutpos(struct drm_crtc *_crtc, + bool in_vblank_irq, + int *vpos, int *hpos, + ktime_t *stime, ktime_t *etime, + const struct drm_display_mode *mode) +{ + struct drm_device *dev = _crtc->dev; + struct drm_i915_private *dev_priv = to_i915(dev); + struct intel_crtc *crtc = to_intel_crtc(_crtc); + enum pipe pipe = crtc->pipe; + int position; + int vbl_start, vbl_end, hsync_start, htotal, vtotal; + unsigned long irqflags; + bool use_scanline_counter = DISPLAY_VER(dev_priv) >= 5 || + IS_G4X(dev_priv) || DISPLAY_VER(dev_priv) == 2 || + crtc->mode_flags & I915_MODE_FLAG_USE_SCANLINE_COUNTER; + + if (drm_WARN_ON(&dev_priv->drm, !mode->crtc_clock)) { + drm_dbg(&dev_priv->drm, + "trying to get scanoutpos for disabled pipe %c\n", + pipe_name(pipe)); + return false; + } + + htotal = mode->crtc_htotal; + hsync_start = mode->crtc_hsync_start; + vtotal = mode->crtc_vtotal; + vbl_start = mode->crtc_vblank_start; + vbl_end = mode->crtc_vblank_end; + + if (mode->flags & DRM_MODE_FLAG_INTERLACE) { + vbl_start = DIV_ROUND_UP(vbl_start, 2); + vbl_end /= 2; + vtotal /= 2; + } + + /* + * Lock uncore.lock, as we will do multiple timing critical raw + * register reads, potentially with preemption disabled, so the + * following code must not block on uncore.lock. + */ + spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); + + /* preempt_disable_rt() should go right here in PREEMPT_RT patchset. */ + + /* Get optional system timestamp before query. */ + if (stime) + *stime = ktime_get(); + + if (crtc->mode_flags & I915_MODE_FLAG_VRR) { + int scanlines = intel_crtc_scanlines_since_frame_timestamp(crtc); + + position = __intel_get_crtc_scanline(crtc); + + /* + * Already exiting vblank? If so, shift our position + * so it looks like we're already apporaching the full + * vblank end. This should make the generated timestamp + * more or less match when the active portion will start. + */ + if (position >= vbl_start && scanlines < position) + position = min(crtc->vmax_vblank_start + scanlines, vtotal - 1); + } else if (use_scanline_counter) { + /* No obvious pixelcount register. Only query vertical + * scanout position from Display scan line register. + */ + position = __intel_get_crtc_scanline(crtc); + } else { + /* + * Have access to pixelcount since start of frame. + * We can split this into vertical and horizontal + * scanout position. + */ + position = (intel_de_read_fw(dev_priv, PIPEFRAMEPIXEL(pipe)) & PIPE_PIXEL_MASK) >> PIPE_PIXEL_SHIFT; + + /* convert to pixel counts */ + vbl_start *= htotal; + vbl_end *= htotal; + vtotal *= htotal; + + /* + * In interlaced modes, the pixel counter counts all pixels, + * so one field will have htotal more pixels. In order to avoid + * the reported position from jumping backwards when the pixel + * counter is beyond the length of the shorter field, just + * clamp the position the length of the shorter field. This + * matches how the scanline counter based position works since + * the scanline counter doesn't count the two half lines. + */ + if (position >= vtotal) + position = vtotal - 1; + + /* + * Start of vblank interrupt is triggered at start of hsync, + * just prior to the first active line of vblank. However we + * consider lines to start at the leading edge of horizontal + * active. So, should we get here before we've crossed into + * the horizontal active of the first line in vblank, we would + * not set the DRM_SCANOUTPOS_INVBL flag. In order to fix that, + * always add htotal-hsync_start to the current pixel position. + */ + position = (position + htotal - hsync_start) % vtotal; + } + + /* Get optional system timestamp after query. */ + if (etime) + *etime = ktime_get(); + + /* preempt_enable_rt() should go right here in PREEMPT_RT patchset. */ + + spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); + + /* + * While in vblank, position will be negative + * counting up towards 0 at vbl_end. And outside + * vblank, position will be positive counting + * up since vbl_end. + */ + if (position >= vbl_start) + position -= vbl_end; + else + position += vtotal - vbl_end; + + if (use_scanline_counter) { + *vpos = position; + *hpos = 0; + } else { + *vpos = position / htotal; + *hpos = position - (*vpos * htotal); + } + + return true; +} + +bool intel_crtc_get_vblank_timestamp(struct drm_crtc *crtc, int *max_error, + ktime_t *vblank_time, bool in_vblank_irq) +{ + return drm_crtc_vblank_helper_get_vblank_timestamp_internal( + crtc, max_error, vblank_time, in_vblank_irq, + i915_get_crtc_scanoutpos); +} + +int intel_get_crtc_scanline(struct intel_crtc *crtc) +{ + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + unsigned long irqflags; + int position; + + spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); + position = __intel_get_crtc_scanline(crtc); + spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); + + return position; +} diff --git a/drivers/gpu/drm/i915/display/intel_vblank.h b/drivers/gpu/drm/i915/display/intel_vblank.h new file mode 100644 index 000000000000..c68eda6488bf --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_vblank.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2022-2023 Intel Corporation + */ + +#ifndef __INTEL_VBLANK_H__ +#define __INTEL_VBLANK_H__ + +#include +#include + +struct drm_crtc; +struct intel_crtc; + +u32 i915_get_vblank_counter(struct drm_crtc *crtc); +u32 g4x_get_vblank_counter(struct drm_crtc *crtc); +bool intel_crtc_get_vblank_timestamp(struct drm_crtc *crtc, int *max_error, + ktime_t *vblank_time, bool in_vblank_irq); +int intel_get_crtc_scanline(struct intel_crtc *crtc); + +#endif /* __INTEL_VBLANK_H__ */ diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 54ea28cf8a1a..240d5e198904 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -614,414 +614,6 @@ static void i915_enable_asle_pipestat(struct drm_i915_private *dev_priv) spin_unlock_irq(&dev_priv->irq_lock); } -/* - * This timing diagram depicts the video signal in and - * around the vertical blanking period. - * - * Assumptions about the fictitious mode used in this example: - * vblank_start >= 3 - * vsync_start = vblank_start + 1 - * vsync_end = vblank_start + 2 - * vtotal = vblank_start + 3 - * - * start of vblank: - * latch double buffered registers - * increment frame counter (ctg+) - * generate start of vblank interrupt (gen4+) - * | - * | frame start: - * | generate frame start interrupt (aka. vblank interrupt) (gmch) - * | may be shifted forward 1-3 extra lines via PIPECONF - * | | - * | | start of vsync: - * | | generate vsync interrupt - * | | | - * ___xxxx___ ___xxxx___ ___xxxx___ ___xxxx___ ___xxxx___ ___xxxx - * . \hs/ . \hs/ \hs/ \hs/ . \hs/ - * ----va---> <-----------------vb--------------------> <--------va------------- - * | | <----vs-----> | - * -vbs-----> <---vbs+1---> <---vbs+2---> <-----0-----> <-----1-----> <-----2--- (scanline counter gen2) - * -vbs-2---> <---vbs-1---> <---vbs-----> <---vbs+1---> <---vbs+2---> <-----0--- (scanline counter gen3+) - * -vbs-2---> <---vbs-2---> <---vbs-1---> <---vbs-----> <---vbs+1---> <---vbs+2- (scanline counter hsw+ hdmi) - * | | | - * last visible pixel first visible pixel - * | increment frame counter (gen3/4) - * pixel counter = vblank_start * htotal pixel counter = 0 (gen3/4) - * - * x = horizontal active - * _ = horizontal blanking - * hs = horizontal sync - * va = vertical active - * vb = vertical blanking - * vs = vertical sync - * vbs = vblank_start (number) - * - * Summary: - * - most events happen at the start of horizontal sync - * - frame start happens at the start of horizontal blank, 1-4 lines - * (depending on PIPECONF settings) after the start of vblank - * - gen3/4 pixel and frame counter are synchronized with the start - * of horizontal active on the first line of vertical active - */ - -/* Called from drm generic code, passed a 'crtc', which - * we use as a pipe index - */ -u32 i915_get_vblank_counter(struct drm_crtc *crtc) -{ - struct drm_i915_private *dev_priv = to_i915(crtc->dev); - struct drm_vblank_crtc *vblank = &dev_priv->drm.vblank[drm_crtc_index(crtc)]; - const struct drm_display_mode *mode = &vblank->hwmode; - enum pipe pipe = to_intel_crtc(crtc)->pipe; - i915_reg_t high_frame, low_frame; - u32 high1, high2, low, pixel, vbl_start, hsync_start, htotal; - unsigned long irqflags; - - /* - * On i965gm TV output the frame counter only works up to - * the point when we enable the TV encoder. After that the - * frame counter ceases to work and reads zero. We need a - * vblank wait before enabling the TV encoder and so we - * have to enable vblank interrupts while the frame counter - * is still in a working state. However the core vblank code - * does not like us returning non-zero frame counter values - * when we've told it that we don't have a working frame - * counter. Thus we must stop non-zero values leaking out. - */ - if (!vblank->max_vblank_count) - return 0; - - htotal = mode->crtc_htotal; - hsync_start = mode->crtc_hsync_start; - vbl_start = mode->crtc_vblank_start; - if (mode->flags & DRM_MODE_FLAG_INTERLACE) - vbl_start = DIV_ROUND_UP(vbl_start, 2); - - /* Convert to pixel count */ - vbl_start *= htotal; - - /* Start of vblank event occurs at start of hsync */ - vbl_start -= htotal - hsync_start; - - high_frame = PIPEFRAME(pipe); - low_frame = PIPEFRAMEPIXEL(pipe); - - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); - - /* - * High & low register fields aren't synchronized, so make sure - * we get a low value that's stable across two reads of the high - * register. - */ - do { - high1 = intel_de_read_fw(dev_priv, high_frame) & PIPE_FRAME_HIGH_MASK; - low = intel_de_read_fw(dev_priv, low_frame); - high2 = intel_de_read_fw(dev_priv, high_frame) & PIPE_FRAME_HIGH_MASK; - } while (high1 != high2); - - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); - - high1 >>= PIPE_FRAME_HIGH_SHIFT; - pixel = low & PIPE_PIXEL_MASK; - low >>= PIPE_FRAME_LOW_SHIFT; - - /* - * The frame counter increments at beginning of active. - * Cook up a vblank counter by also checking the pixel - * counter against vblank start. - */ - return (((high1 << 8) | low) + (pixel >= vbl_start)) & 0xffffff; -} - -u32 g4x_get_vblank_counter(struct drm_crtc *crtc) -{ - struct drm_i915_private *dev_priv = to_i915(crtc->dev); - struct drm_vblank_crtc *vblank = &dev_priv->drm.vblank[drm_crtc_index(crtc)]; - enum pipe pipe = to_intel_crtc(crtc)->pipe; - - if (!vblank->max_vblank_count) - return 0; - - return intel_uncore_read(&dev_priv->uncore, PIPE_FRMCOUNT_G4X(pipe)); -} - -static u32 intel_crtc_scanlines_since_frame_timestamp(struct intel_crtc *crtc) -{ - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - struct drm_vblank_crtc *vblank = - &crtc->base.dev->vblank[drm_crtc_index(&crtc->base)]; - const struct drm_display_mode *mode = &vblank->hwmode; - u32 htotal = mode->crtc_htotal; - u32 clock = mode->crtc_clock; - u32 scan_prev_time, scan_curr_time, scan_post_time; - - /* - * To avoid the race condition where we might cross into the - * next vblank just between the PIPE_FRMTMSTMP and TIMESTAMP_CTR - * reads. We make sure we read PIPE_FRMTMSTMP and TIMESTAMP_CTR - * during the same frame. - */ - do { - /* - * This field provides read back of the display - * pipe frame time stamp. The time stamp value - * is sampled at every start of vertical blank. - */ - scan_prev_time = intel_de_read_fw(dev_priv, - PIPE_FRMTMSTMP(crtc->pipe)); - - /* - * The TIMESTAMP_CTR register has the current - * time stamp value. - */ - scan_curr_time = intel_de_read_fw(dev_priv, IVB_TIMESTAMP_CTR); - - scan_post_time = intel_de_read_fw(dev_priv, - PIPE_FRMTMSTMP(crtc->pipe)); - } while (scan_post_time != scan_prev_time); - - return div_u64(mul_u32_u32(scan_curr_time - scan_prev_time, - clock), 1000 * htotal); -} - -/* - * On certain encoders on certain platforms, pipe - * scanline register will not work to get the scanline, - * since the timings are driven from the PORT or issues - * with scanline register updates. - * This function will use Framestamp and current - * timestamp registers to calculate the scanline. - */ -static u32 __intel_get_crtc_scanline_from_timestamp(struct intel_crtc *crtc) -{ - struct drm_vblank_crtc *vblank = - &crtc->base.dev->vblank[drm_crtc_index(&crtc->base)]; - const struct drm_display_mode *mode = &vblank->hwmode; - u32 vblank_start = mode->crtc_vblank_start; - u32 vtotal = mode->crtc_vtotal; - u32 scanline; - - scanline = intel_crtc_scanlines_since_frame_timestamp(crtc); - scanline = min(scanline, vtotal - 1); - scanline = (scanline + vblank_start) % vtotal; - - return scanline; -} - -/* - * intel_de_read_fw(), only for fast reads of display block, no need for - * forcewake etc. - */ -static int __intel_get_crtc_scanline(struct intel_crtc *crtc) -{ - struct drm_device *dev = crtc->base.dev; - struct drm_i915_private *dev_priv = to_i915(dev); - const struct drm_display_mode *mode; - struct drm_vblank_crtc *vblank; - enum pipe pipe = crtc->pipe; - int position, vtotal; - - if (!crtc->active) - return 0; - - vblank = &crtc->base.dev->vblank[drm_crtc_index(&crtc->base)]; - mode = &vblank->hwmode; - - if (crtc->mode_flags & I915_MODE_FLAG_GET_SCANLINE_FROM_TIMESTAMP) - return __intel_get_crtc_scanline_from_timestamp(crtc); - - vtotal = mode->crtc_vtotal; - if (mode->flags & DRM_MODE_FLAG_INTERLACE) - vtotal /= 2; - - position = intel_de_read_fw(dev_priv, PIPEDSL(pipe)) & PIPEDSL_LINE_MASK; - - /* - * On HSW, the DSL reg (0x70000) appears to return 0 if we - * read it just before the start of vblank. So try it again - * so we don't accidentally end up spanning a vblank frame - * increment, causing the pipe_update_end() code to squak at us. - * - * The nature of this problem means we can't simply check the ISR - * bit and return the vblank start value; nor can we use the scanline - * debug register in the transcoder as it appears to have the same - * problem. We may need to extend this to include other platforms, - * but so far testing only shows the problem on HSW. - */ - if (HAS_DDI(dev_priv) && !position) { - int i, temp; - - for (i = 0; i < 100; i++) { - udelay(1); - temp = intel_de_read_fw(dev_priv, PIPEDSL(pipe)) & PIPEDSL_LINE_MASK; - if (temp != position) { - position = temp; - break; - } - } - } - - /* - * See update_scanline_offset() for the details on the - * scanline_offset adjustment. - */ - return (position + crtc->scanline_offset) % vtotal; -} - -static bool i915_get_crtc_scanoutpos(struct drm_crtc *_crtc, - bool in_vblank_irq, - int *vpos, int *hpos, - ktime_t *stime, ktime_t *etime, - const struct drm_display_mode *mode) -{ - struct drm_device *dev = _crtc->dev; - struct drm_i915_private *dev_priv = to_i915(dev); - struct intel_crtc *crtc = to_intel_crtc(_crtc); - enum pipe pipe = crtc->pipe; - int position; - int vbl_start, vbl_end, hsync_start, htotal, vtotal; - unsigned long irqflags; - bool use_scanline_counter = DISPLAY_VER(dev_priv) >= 5 || - IS_G4X(dev_priv) || DISPLAY_VER(dev_priv) == 2 || - crtc->mode_flags & I915_MODE_FLAG_USE_SCANLINE_COUNTER; - - if (drm_WARN_ON(&dev_priv->drm, !mode->crtc_clock)) { - drm_dbg(&dev_priv->drm, - "trying to get scanoutpos for disabled " - "pipe %c\n", pipe_name(pipe)); - return false; - } - - htotal = mode->crtc_htotal; - hsync_start = mode->crtc_hsync_start; - vtotal = mode->crtc_vtotal; - vbl_start = mode->crtc_vblank_start; - vbl_end = mode->crtc_vblank_end; - - if (mode->flags & DRM_MODE_FLAG_INTERLACE) { - vbl_start = DIV_ROUND_UP(vbl_start, 2); - vbl_end /= 2; - vtotal /= 2; - } - - /* - * Lock uncore.lock, as we will do multiple timing critical raw - * register reads, potentially with preemption disabled, so the - * following code must not block on uncore.lock. - */ - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); - - /* preempt_disable_rt() should go right here in PREEMPT_RT patchset. */ - - /* Get optional system timestamp before query. */ - if (stime) - *stime = ktime_get(); - - if (crtc->mode_flags & I915_MODE_FLAG_VRR) { - int scanlines = intel_crtc_scanlines_since_frame_timestamp(crtc); - - position = __intel_get_crtc_scanline(crtc); - - /* - * Already exiting vblank? If so, shift our position - * so it looks like we're already apporaching the full - * vblank end. This should make the generated timestamp - * more or less match when the active portion will start. - */ - if (position >= vbl_start && scanlines < position) - position = min(crtc->vmax_vblank_start + scanlines, vtotal - 1); - } else if (use_scanline_counter) { - /* No obvious pixelcount register. Only query vertical - * scanout position from Display scan line register. - */ - position = __intel_get_crtc_scanline(crtc); - } else { - /* Have access to pixelcount since start of frame. - * We can split this into vertical and horizontal - * scanout position. - */ - position = (intel_de_read_fw(dev_priv, PIPEFRAMEPIXEL(pipe)) & PIPE_PIXEL_MASK) >> PIPE_PIXEL_SHIFT; - - /* convert to pixel counts */ - vbl_start *= htotal; - vbl_end *= htotal; - vtotal *= htotal; - - /* - * In interlaced modes, the pixel counter counts all pixels, - * so one field will have htotal more pixels. In order to avoid - * the reported position from jumping backwards when the pixel - * counter is beyond the length of the shorter field, just - * clamp the position the length of the shorter field. This - * matches how the scanline counter based position works since - * the scanline counter doesn't count the two half lines. - */ - if (position >= vtotal) - position = vtotal - 1; - - /* - * Start of vblank interrupt is triggered at start of hsync, - * just prior to the first active line of vblank. However we - * consider lines to start at the leading edge of horizontal - * active. So, should we get here before we've crossed into - * the horizontal active of the first line in vblank, we would - * not set the DRM_SCANOUTPOS_INVBL flag. In order to fix that, - * always add htotal-hsync_start to the current pixel position. - */ - position = (position + htotal - hsync_start) % vtotal; - } - - /* Get optional system timestamp after query. */ - if (etime) - *etime = ktime_get(); - - /* preempt_enable_rt() should go right here in PREEMPT_RT patchset. */ - - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); - - /* - * While in vblank, position will be negative - * counting up towards 0 at vbl_end. And outside - * vblank, position will be positive counting - * up since vbl_end. - */ - if (position >= vbl_start) - position -= vbl_end; - else - position += vtotal - vbl_end; - - if (use_scanline_counter) { - *vpos = position; - *hpos = 0; - } else { - *vpos = position / htotal; - *hpos = position - (*vpos * htotal); - } - - return true; -} - -bool intel_crtc_get_vblank_timestamp(struct drm_crtc *crtc, int *max_error, - ktime_t *vblank_time, bool in_vblank_irq) -{ - return drm_crtc_vblank_helper_get_vblank_timestamp_internal( - crtc, max_error, vblank_time, in_vblank_irq, - i915_get_crtc_scanoutpos); -} - -int intel_get_crtc_scanline(struct intel_crtc *crtc) -{ - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - unsigned long irqflags; - int position; - - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); - position = __intel_get_crtc_scanline(crtc); - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); - - return position; -} - /** * ivb_parity_work - Workqueue called when a parity error interrupt * occurred. diff --git a/drivers/gpu/drm/i915/i915_irq.h b/drivers/gpu/drm/i915/i915_irq.h index 9b004fc3444e..03ee4c8b1ed3 100644 --- a/drivers/gpu/drm/i915/i915_irq.h +++ b/drivers/gpu/drm/i915/i915_irq.h @@ -66,18 +66,12 @@ bool intel_irqs_enabled(struct drm_i915_private *dev_priv); void intel_synchronize_irq(struct drm_i915_private *i915); void intel_synchronize_hardirq(struct drm_i915_private *i915); -int intel_get_crtc_scanline(struct intel_crtc *crtc); void gen8_irq_power_well_post_enable(struct drm_i915_private *dev_priv, u8 pipe_mask); void gen8_irq_power_well_pre_disable(struct drm_i915_private *dev_priv, u8 pipe_mask); u32 gen8_de_pipe_underrun_mask(struct drm_i915_private *dev_priv); -bool intel_crtc_get_vblank_timestamp(struct drm_crtc *crtc, int *max_error, - ktime_t *vblank_time, bool in_vblank_irq); - -u32 i915_get_vblank_counter(struct drm_crtc *crtc); -u32 g4x_get_vblank_counter(struct drm_crtc *crtc); int i8xx_enable_vblank(struct drm_crtc *crtc); int i915gm_enable_vblank(struct drm_crtc *crtc); From 61a0e794ed58435cc683488b98e0efad2f05bf66 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 16 Jan 2023 14:56:13 +0200 Subject: [PATCH 18/67] drm/i915/display: move more scanline functions to intel_vblank.[ch] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reduce clutter in intel_display.c by moving the scanline moving/stopped wait functions to intel_vblank.[ch]. Cc: Ville Syrjälä Reviewed-by: Arun R Murthy Signed-off-by: Jani Nikula Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/3613b8c22e5022ebf61ab942e6bc81b717e8f520.1673873708.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 36 +------------------- drivers/gpu/drm/i915/display/intel_vblank.c | 35 +++++++++++++++++++ drivers/gpu/drm/i915/display/intel_vblank.h | 2 ++ 3 files changed, 38 insertions(+), 35 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 734e8e613f8e..b5c0ab0f5e51 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -112,6 +112,7 @@ #include "intel_sprite.h" #include "intel_tc.h" #include "intel_tv.h" +#include "intel_vblank.h" #include "intel_vdsc.h" #include "intel_vga.h" #include "intel_vrr.h" @@ -384,41 +385,6 @@ struct intel_crtc *intel_master_crtc(const struct intel_crtc_state *crtc_state) return to_intel_crtc(crtc_state->uapi.crtc); } -static bool pipe_scanline_is_moving(struct drm_i915_private *dev_priv, - enum pipe pipe) -{ - i915_reg_t reg = PIPEDSL(pipe); - u32 line1, line2; - - line1 = intel_de_read(dev_priv, reg) & PIPEDSL_LINE_MASK; - msleep(5); - line2 = intel_de_read(dev_priv, reg) & PIPEDSL_LINE_MASK; - - return line1 != line2; -} - -static void wait_for_pipe_scanline_moving(struct intel_crtc *crtc, bool state) -{ - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - enum pipe pipe = crtc->pipe; - - /* Wait for the display line to settle/start moving */ - if (wait_for(pipe_scanline_is_moving(dev_priv, pipe) == state, 100)) - drm_err(&dev_priv->drm, - "pipe %c scanline %s wait timed out\n", - pipe_name(pipe), str_on_off(state)); -} - -static void intel_wait_for_pipe_scanline_stopped(struct intel_crtc *crtc) -{ - wait_for_pipe_scanline_moving(crtc, false); -} - -static void intel_wait_for_pipe_scanline_moving(struct intel_crtc *crtc) -{ - wait_for_pipe_scanline_moving(crtc, true); -} - static void intel_wait_for_pipe_off(const struct intel_crtc_state *old_crtc_state) { diff --git a/drivers/gpu/drm/i915/display/intel_vblank.c b/drivers/gpu/drm/i915/display/intel_vblank.c index 6392a56ae7d4..bc792b363ffc 100644 --- a/drivers/gpu/drm/i915/display/intel_vblank.c +++ b/drivers/gpu/drm/i915/display/intel_vblank.c @@ -417,3 +417,38 @@ int intel_get_crtc_scanline(struct intel_crtc *crtc) return position; } + +static bool pipe_scanline_is_moving(struct drm_i915_private *dev_priv, + enum pipe pipe) +{ + i915_reg_t reg = PIPEDSL(pipe); + u32 line1, line2; + + line1 = intel_de_read(dev_priv, reg) & PIPEDSL_LINE_MASK; + msleep(5); + line2 = intel_de_read(dev_priv, reg) & PIPEDSL_LINE_MASK; + + return line1 != line2; +} + +static void wait_for_pipe_scanline_moving(struct intel_crtc *crtc, bool state) +{ + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + enum pipe pipe = crtc->pipe; + + /* Wait for the display line to settle/start moving */ + if (wait_for(pipe_scanline_is_moving(dev_priv, pipe) == state, 100)) + drm_err(&dev_priv->drm, + "pipe %c scanline %s wait timed out\n", + pipe_name(pipe), str_on_off(state)); +} + +void intel_wait_for_pipe_scanline_stopped(struct intel_crtc *crtc) +{ + wait_for_pipe_scanline_moving(crtc, false); +} + +void intel_wait_for_pipe_scanline_moving(struct intel_crtc *crtc) +{ + wait_for_pipe_scanline_moving(crtc, true); +} diff --git a/drivers/gpu/drm/i915/display/intel_vblank.h b/drivers/gpu/drm/i915/display/intel_vblank.h index c68eda6488bf..c9fea2c2a990 100644 --- a/drivers/gpu/drm/i915/display/intel_vblank.h +++ b/drivers/gpu/drm/i915/display/intel_vblank.h @@ -17,5 +17,7 @@ u32 g4x_get_vblank_counter(struct drm_crtc *crtc); bool intel_crtc_get_vblank_timestamp(struct drm_crtc *crtc, int *max_error, ktime_t *vblank_time, bool in_vblank_irq); int intel_get_crtc_scanline(struct intel_crtc *crtc); +void intel_wait_for_pipe_scanline_stopped(struct intel_crtc *crtc); +void intel_wait_for_pipe_scanline_moving(struct intel_crtc *crtc); #endif /* __INTEL_VBLANK_H__ */ From e8adda5187ac4552c3a3e313c0ab883722367e82 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 16 Jan 2023 14:56:14 +0200 Subject: [PATCH 19/67] drm/i915/display: use common function for checking scanline is moving MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit cpt_verify_modeset() is roughly the same as intel_wait_for_pipe_scanline_moving(). Assume it's close enough. Cc: Ville Syrjälä Reviewed-by: Arun R Murthy Signed-off-by: Jani Nikula Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/bf26763caaad25f3dfcf6f8e468421f93fb99646.1673873708.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index b5c0ab0f5e51..9b73663a0499 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -1060,22 +1060,6 @@ intel_get_crtc_new_encoder(const struct intel_atomic_state *state, return encoder; } -static void cpt_verify_modeset(struct drm_i915_private *dev_priv, - enum pipe pipe) -{ - i915_reg_t dslreg = PIPEDSL(pipe); - u32 temp; - - temp = intel_de_read(dev_priv, dslreg); - udelay(500); - if (wait_for(intel_de_read(dev_priv, dslreg) != temp, 5)) { - if (wait_for(intel_de_read(dev_priv, dslreg) != temp, 5)) - drm_err(&dev_priv->drm, - "mode set failed: pipe %c stuck\n", - pipe_name(pipe)); - } -} - static void ilk_pfit_enable(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); @@ -1770,7 +1754,7 @@ static void ilk_crtc_enable(struct intel_atomic_state *state, intel_encoders_enable(state, crtc); if (HAS_PCH_CPT(dev_priv)) - cpt_verify_modeset(dev_priv, pipe); + intel_wait_for_pipe_scanline_moving(crtc); /* * Must wait for vblank to avoid spurious PCH FIFO underruns. From 75018f47acd49ace947a2e99cb5c2114f0f68ebd Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 16 Jan 2023 14:56:15 +0200 Subject: [PATCH 20/67] drm/i915/vblank: use intel_de_read() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the intel_de_* functions for display registers. Cc: Ville Syrjälä Reviewed-by: Arun R Murthy Signed-off-by: Jani Nikula Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/ecfac5ebddcb46be1ddf2e34e52648fbf9fa4ca6.1673873708.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_vblank.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_vblank.c b/drivers/gpu/drm/i915/display/intel_vblank.c index bc792b363ffc..b2d4d289aaa7 100644 --- a/drivers/gpu/drm/i915/display/intel_vblank.c +++ b/drivers/gpu/drm/i915/display/intel_vblank.c @@ -137,7 +137,7 @@ u32 g4x_get_vblank_counter(struct drm_crtc *crtc) if (!vblank->max_vblank_count) return 0; - return intel_uncore_read(&dev_priv->uncore, PIPE_FRMCOUNT_G4X(pipe)); + return intel_de_read(dev_priv, PIPE_FRMCOUNT_G4X(pipe)); } static u32 intel_crtc_scanlines_since_frame_timestamp(struct intel_crtc *crtc) From 1af13bc6d0470e6c425c52944739fdc74f46ed02 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 16 Jan 2023 14:56:16 +0200 Subject: [PATCH 21/67] drm/i915/vblank: add and use intel_de_read64_2x32() to read vblank counter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add intel_de_read64_2x32() wrapper for the uncore version of the same, and use it to read the high and low frame registers. Avoid duplicating code for existing helpers. The slight functional difference is checking that the entire high register remains the same across two reads, instead of just the part we're interested in. This should be of no consequence. (Unless those bits function as a PRNG.) Cc: Ville Syrjälä Signed-off-by: Jani Nikula Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/33853549adff82045b95af527e14cfdff5712470.1673873708.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_de.h | 7 ++++++ drivers/gpu/drm/i915/display/intel_vblank.c | 25 +++++---------------- 2 files changed, 13 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_de.h b/drivers/gpu/drm/i915/display/intel_de.h index 3dbd76fdabd6..42552d8c151e 100644 --- a/drivers/gpu/drm/i915/display/intel_de.h +++ b/drivers/gpu/drm/i915/display/intel_de.h @@ -22,6 +22,13 @@ intel_de_read8(struct drm_i915_private *i915, i915_reg_t reg) return intel_uncore_read8(&i915->uncore, reg); } +static inline u64 +intel_de_read64_2x32(struct drm_i915_private *i915, + i915_reg_t lower_reg, i915_reg_t upper_reg) +{ + return intel_uncore_read64_2x32(&i915->uncore, lower_reg, upper_reg); +} + static inline void intel_de_posting_read(struct drm_i915_private *i915, i915_reg_t reg) { diff --git a/drivers/gpu/drm/i915/display/intel_vblank.c b/drivers/gpu/drm/i915/display/intel_vblank.c index b2d4d289aaa7..4c83e2320bca 100644 --- a/drivers/gpu/drm/i915/display/intel_vblank.c +++ b/drivers/gpu/drm/i915/display/intel_vblank.c @@ -68,9 +68,8 @@ u32 i915_get_vblank_counter(struct drm_crtc *crtc) struct drm_vblank_crtc *vblank = &dev_priv->drm.vblank[drm_crtc_index(crtc)]; const struct drm_display_mode *mode = &vblank->hwmode; enum pipe pipe = to_intel_crtc(crtc)->pipe; - i915_reg_t high_frame, low_frame; - u32 high1, high2, low, pixel, vbl_start, hsync_start, htotal; - unsigned long irqflags; + u32 pixel, vbl_start, hsync_start, htotal; + u64 frame; /* * On i965gm TV output the frame counter only works up to @@ -98,34 +97,22 @@ u32 i915_get_vblank_counter(struct drm_crtc *crtc) /* Start of vblank event occurs at start of hsync */ vbl_start -= htotal - hsync_start; - high_frame = PIPEFRAME(pipe); - low_frame = PIPEFRAMEPIXEL(pipe); - - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); - /* * High & low register fields aren't synchronized, so make sure * we get a low value that's stable across two reads of the high * register. */ - do { - high1 = intel_de_read_fw(dev_priv, high_frame) & PIPE_FRAME_HIGH_MASK; - low = intel_de_read_fw(dev_priv, low_frame); - high2 = intel_de_read_fw(dev_priv, high_frame) & PIPE_FRAME_HIGH_MASK; - } while (high1 != high2); + frame = intel_de_read64_2x32(dev_priv, PIPEFRAMEPIXEL(pipe), PIPEFRAME(pipe)); - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); - - high1 >>= PIPE_FRAME_HIGH_SHIFT; - pixel = low & PIPE_PIXEL_MASK; - low >>= PIPE_FRAME_LOW_SHIFT; + pixel = frame & PIPE_PIXEL_MASK; + frame = (frame >> PIPE_FRAME_LOW_SHIFT) & 0xffffff; /* * The frame counter increments at beginning of active. * Cook up a vblank counter by also checking the pixel * counter against vblank start. */ - return (((high1 << 8) | low) + (pixel >= vbl_start)) & 0xffffff; + return (frame + (pixel >= vbl_start)) & 0xffffff; } u32 g4x_get_vblank_counter(struct drm_crtc *crtc) From 1eca0778f4b35d63cb224a460bcebd5eb13f5da9 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 16 Jan 2023 19:34:21 +0200 Subject: [PATCH 22/67] drm/i915: add struct i915_dsm to wrap dsm members together Wrap the stolen memory related struct drm_i915_private members (dsm, dsm_reserved, and stolen_usable_size) together in a a new struct i915_dsm. Signed-off-by: Jani Nikula Reviewed-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20230116173422.1858527-1-jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_fbc.c | 10 ++-- drivers/gpu/drm/i915/display/intel_fbdev.c | 2 +- .../drm/i915/display/intel_plane_initial.c | 2 +- drivers/gpu/drm/i915/gem/i915_gem_stolen.c | 36 ++++++------ drivers/gpu/drm/i915/gt/intel_rc6.c | 12 ++-- drivers/gpu/drm/i915/gt/selftest_reset.c | 2 +- drivers/gpu/drm/i915/i915_drv.h | 55 +++++++++++-------- drivers/gpu/drm/i915/selftests/i915_gem.c | 4 +- 8 files changed, 66 insertions(+), 57 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index c508dcf415b4..b507ff944864 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -331,15 +331,15 @@ static void i8xx_fbc_program_cfb(struct intel_fbc *fbc) { struct drm_i915_private *i915 = fbc->i915; - GEM_BUG_ON(range_overflows_end_t(u64, i915->dsm.start, + GEM_BUG_ON(range_overflows_end_t(u64, i915->dsm.stolen.start, fbc->compressed_fb.start, U32_MAX)); - GEM_BUG_ON(range_overflows_end_t(u64, i915->dsm.start, + GEM_BUG_ON(range_overflows_end_t(u64, i915->dsm.stolen.start, fbc->compressed_llb.start, U32_MAX)); intel_de_write(i915, FBC_CFB_BASE, - i915->dsm.start + fbc->compressed_fb.start); + i915->dsm.stolen.start + fbc->compressed_fb.start); intel_de_write(i915, FBC_LL_BASE, - i915->dsm.start + fbc->compressed_llb.start); + i915->dsm.stolen.start + fbc->compressed_llb.start); } static const struct intel_fbc_funcs i8xx_fbc_funcs = { @@ -712,7 +712,7 @@ static u64 intel_fbc_stolen_end(struct drm_i915_private *i915) * underruns, even if that range is not reserved by the BIOS. */ if (IS_BROADWELL(i915) || (DISPLAY_VER(i915) == 9 && !IS_BROXTON(i915))) - end = resource_size(&i915->dsm) - 8 * 1024 * 1024; + end = resource_size(&i915->dsm.stolen) - 8 * 1024 * 1024; else end = U64_MAX; diff --git a/drivers/gpu/drm/i915/display/intel_fbdev.c b/drivers/gpu/drm/i915/display/intel_fbdev.c index 5575d7abdc09..f88ccc1bb3ac 100644 --- a/drivers/gpu/drm/i915/display/intel_fbdev.c +++ b/drivers/gpu/drm/i915/display/intel_fbdev.c @@ -170,7 +170,7 @@ static int intelfb_alloc(struct drm_fb_helper *helper, * important and we should probably use that space with FBC or other * features. */ - if (size * 2 < dev_priv->stolen_usable_size) + if (size * 2 < dev_priv->dsm.usable_size) obj = i915_gem_object_create_stolen(dev_priv, size); if (IS_ERR(obj)) obj = i915_gem_object_create_shmem(dev_priv, size); diff --git a/drivers/gpu/drm/i915/display/intel_plane_initial.c b/drivers/gpu/drm/i915/display/intel_plane_initial.c index 76be796df255..bb6ea7de5c61 100644 --- a/drivers/gpu/drm/i915/display/intel_plane_initial.c +++ b/drivers/gpu/drm/i915/display/intel_plane_initial.c @@ -107,7 +107,7 @@ initial_plane_vma(struct drm_i915_private *i915, */ if (IS_ENABLED(CONFIG_FRAMEBUFFER_CONSOLE) && mem == i915->mm.stolen_region && - size * 2 > i915->stolen_usable_size) + size * 2 > i915->dsm.usable_size) return NULL; obj = i915_gem_object_create_region_at(mem, phys_base, size, 0); diff --git a/drivers/gpu/drm/i915/gem/i915_gem_stolen.c b/drivers/gpu/drm/i915/gem/i915_gem_stolen.c index bc9521078807..de873498d95b 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_stolen.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_stolen.c @@ -211,7 +211,7 @@ static void g4x_get_stolen_reserved(struct drm_i915_private *i915, IS_GM45(i915) ? CTG_STOLEN_RESERVED : ELK_STOLEN_RESERVED); - resource_size_t stolen_top = i915->dsm.end + 1; + resource_size_t stolen_top = i915->dsm.stolen.end + 1; drm_dbg(&i915->drm, "%s_STOLEN_RESERVED = %08x\n", IS_GM45(i915) ? "CTG" : "ELK", reg_val); @@ -276,7 +276,7 @@ static void vlv_get_stolen_reserved(struct drm_i915_private *i915, resource_size_t *size) { u32 reg_val = intel_uncore_read(uncore, GEN6_STOLEN_RESERVED); - resource_size_t stolen_top = i915->dsm.end + 1; + resource_size_t stolen_top = i915->dsm.stolen.end + 1; drm_dbg(&i915->drm, "GEN6_STOLEN_RESERVED = %08x\n", reg_val); @@ -365,7 +365,7 @@ static void bdw_get_stolen_reserved(struct drm_i915_private *i915, resource_size_t *size) { u32 reg_val = intel_uncore_read(uncore, GEN6_STOLEN_RESERVED); - resource_size_t stolen_top = i915->dsm.end + 1; + resource_size_t stolen_top = i915->dsm.stolen.end + 1; drm_dbg(&i915->drm, "GEN6_STOLEN_RESERVED = %08x\n", reg_val); @@ -414,7 +414,7 @@ static void icl_get_stolen_reserved(struct drm_i915_private *i915, } /* - * Initialize i915->dsm_reserved to contain the reserved space within the Data + * Initialize i915->dsm.reserved to contain the reserved space within the Data * Stolen Memory. This is a range on the top of DSM that is reserved, not to * be used by driver, so must be excluded from the region passed to the * allocator later. In the spec this is also called as WOPCM. @@ -430,7 +430,7 @@ static int init_reserved_stolen(struct drm_i915_private *i915) resource_size_t reserved_size; int ret = 0; - stolen_top = i915->dsm.end + 1; + stolen_top = i915->dsm.stolen.end + 1; reserved_base = stolen_top; reserved_size = 0; @@ -471,13 +471,13 @@ static int init_reserved_stolen(struct drm_i915_private *i915) goto bail_out; } - i915->dsm_reserved = + i915->dsm.reserved = (struct resource)DEFINE_RES_MEM(reserved_base, reserved_size); - if (!resource_contains(&i915->dsm, &i915->dsm_reserved)) { + if (!resource_contains(&i915->dsm.stolen, &i915->dsm.reserved)) { drm_err(&i915->drm, "Stolen reserved area %pR outside stolen memory %pR\n", - &i915->dsm_reserved, &i915->dsm); + &i915->dsm.reserved, &i915->dsm.stolen); ret = -EINVAL; goto bail_out; } @@ -485,7 +485,7 @@ static int init_reserved_stolen(struct drm_i915_private *i915) return 0; bail_out: - i915->dsm_reserved = + i915->dsm.reserved = (struct resource)DEFINE_RES_MEM(reserved_base, 0); return ret; @@ -517,27 +517,27 @@ static int i915_gem_init_stolen(struct intel_memory_region *mem) if (request_smem_stolen(i915, &mem->region)) return -ENOSPC; - i915->dsm = mem->region; + i915->dsm.stolen = mem->region; if (init_reserved_stolen(i915)) return -ENOSPC; /* Exclude the reserved region from driver use */ - mem->region.end = i915->dsm_reserved.start - 1; + mem->region.end = i915->dsm.reserved.start - 1; mem->io_size = min(mem->io_size, resource_size(&mem->region)); - i915->stolen_usable_size = resource_size(&mem->region); + i915->dsm.usable_size = resource_size(&mem->region); drm_dbg(&i915->drm, "Memory reserved for graphics device: %lluK, usable: %lluK\n", - (u64)resource_size(&i915->dsm) >> 10, - (u64)i915->stolen_usable_size >> 10); + (u64)resource_size(&i915->dsm.stolen) >> 10, + (u64)i915->dsm.usable_size >> 10); - if (i915->stolen_usable_size == 0) + if (i915->dsm.usable_size == 0) return -ENOSPC; /* Basic memrange allocator for stolen space. */ - drm_mm_init(&i915->mm.stolen, 0, i915->stolen_usable_size); + drm_mm_init(&i915->mm.stolen, 0, i915->dsm.usable_size); return 0; } @@ -587,7 +587,7 @@ i915_pages_create_for_stolen(struct drm_device *dev, struct sg_table *st; struct scatterlist *sg; - GEM_BUG_ON(range_overflows(offset, size, resource_size(&i915->dsm))); + GEM_BUG_ON(range_overflows(offset, size, resource_size(&i915->dsm.stolen))); /* We hide that we have no struct page backing our stolen object * by wrapping the contiguous physical allocation with a fake @@ -607,7 +607,7 @@ i915_pages_create_for_stolen(struct drm_device *dev, sg->offset = 0; sg->length = size; - sg_dma_address(sg) = (dma_addr_t)i915->dsm.start + offset; + sg_dma_address(sg) = (dma_addr_t)i915->dsm.stolen.start + offset; sg_dma_len(sg) = size; return st; diff --git a/drivers/gpu/drm/i915/gt/intel_rc6.c b/drivers/gpu/drm/i915/gt/intel_rc6.c index 2ee4051e4d96..5c91622dfca4 100644 --- a/drivers/gpu/drm/i915/gt/intel_rc6.c +++ b/drivers/gpu/drm/i915/gt/intel_rc6.c @@ -301,7 +301,7 @@ static int chv_rc6_init(struct intel_rc6 *rc6) pcbr = intel_uncore_read(uncore, VLV_PCBR); if ((pcbr >> VLV_PCBR_ADDR_SHIFT) == 0) { drm_dbg(&i915->drm, "BIOS didn't set up PCBR, fixing up\n"); - paddr = i915->dsm.end + 1 - pctx_size; + paddr = i915->dsm.stolen.end + 1 - pctx_size; GEM_BUG_ON(paddr > U32_MAX); pctx_paddr = (paddr & ~4095); @@ -325,7 +325,7 @@ static int vlv_rc6_init(struct intel_rc6 *rc6) /* BIOS set it up already, grab the pre-alloc'd space */ resource_size_t pcbr_offset; - pcbr_offset = (pcbr & ~4095) - i915->dsm.start; + pcbr_offset = (pcbr & ~4095) - i915->dsm.stolen.start; pctx = i915_gem_object_create_region_at(i915->mm.stolen_region, pcbr_offset, pctx_size, @@ -354,10 +354,10 @@ static int vlv_rc6_init(struct intel_rc6 *rc6) } GEM_BUG_ON(range_overflows_end_t(u64, - i915->dsm.start, + i915->dsm.stolen.start, pctx->stolen->start, U32_MAX)); - pctx_paddr = i915->dsm.start + pctx->stolen->start; + pctx_paddr = i915->dsm.stolen.start + pctx->stolen->start; intel_uncore_write(uncore, VLV_PCBR, pctx_paddr); out: @@ -448,8 +448,8 @@ static bool bxt_check_bios_rc6_setup(struct intel_rc6 *rc6) */ rc6_ctx_base = intel_uncore_read(uncore, RC6_CTX_BASE) & RC6_CTX_BASE_MASK; - if (!(rc6_ctx_base >= i915->dsm_reserved.start && - rc6_ctx_base + PAGE_SIZE < i915->dsm_reserved.end)) { + if (!(rc6_ctx_base >= i915->dsm.reserved.start && + rc6_ctx_base + PAGE_SIZE < i915->dsm.reserved.end)) { drm_dbg(&i915->drm, "RC6 Base address not as expected.\n"); enable_rc6 = false; } diff --git a/drivers/gpu/drm/i915/gt/selftest_reset.c b/drivers/gpu/drm/i915/gt/selftest_reset.c index 37c38bdd5f47..a9e0a91bc0e0 100644 --- a/drivers/gpu/drm/i915/gt/selftest_reset.c +++ b/drivers/gpu/drm/i915/gt/selftest_reset.c @@ -20,7 +20,7 @@ __igt_reset_stolen(struct intel_gt *gt, const char *msg) { struct i915_ggtt *ggtt = gt->ggtt; - const struct resource *dsm = >->i915->dsm; + const struct resource *dsm = >->i915->dsm.stolen; resource_size_t num_pages, page; struct intel_engine_cs *engine; intel_wakeref_t wakeref; diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 360743a8a163..83bc69892a86 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -85,6 +85,37 @@ struct vlv_s0ix_state; #define GEM_QUIRK_PIN_SWIZZLED_PAGES BIT(0) +/* Data Stolen Memory (DSM) aka "i915 stolen memory" */ +struct i915_dsm { + /* + * The start and end of DSM which we can optionally use to create GEM + * objects backed by stolen memory. + * + * Note that usable_size tells us exactly how much of this we are + * actually allowed to use, given that some portion of it is in fact + * reserved for use by hardware functions. + */ + struct resource stolen; + + /* + * Reserved portion of DSM. + */ + struct resource reserved; + + /* + * Total size minus reserved ranges. + * + * DSM is segmented in hardware with different portions offlimits to + * certain functions. + * + * The drm_mm is initialised to the total accessible range, as found + * from the PCI config. On Broadwell+, this is further restricted to + * avoid the first page! The upper end of DSM is reserved for hardware + * functions and similarly removed from the accessible range. + */ + resource_size_t usable_size; +}; + struct i915_suspend_saved_registers { u32 saveDSPARB; u32 saveSWF0[16]; @@ -204,29 +235,7 @@ struct drm_i915_private { struct intel_runtime_info __runtime; /* Use RUNTIME_INFO() to access. */ struct intel_driver_caps caps; - /** - * Data Stolen Memory - aka "i915 stolen memory" gives us the start and - * end of stolen which we can optionally use to create GEM objects - * backed by stolen memory. Note that stolen_usable_size tells us - * exactly how much of this we are actually allowed to use, given that - * some portion of it is in fact reserved for use by hardware functions. - */ - struct resource dsm; - /** - * Reseved portion of Data Stolen Memory - */ - struct resource dsm_reserved; - - /* - * Stolen memory is segmented in hardware with different portions - * offlimits to certain functions. - * - * The drm_mm is initialised to the total accessible range, as found - * from the PCI config. On Broadwell+, this is further restricted to - * avoid the first page! The upper end of stolen memory is reserved for - * hardware functions and similarly removed from the accessible range. - */ - resource_size_t stolen_usable_size; /* Total size minus reserved ranges */ + struct i915_dsm dsm; struct intel_uncore uncore; struct intel_uncore_mmio_debug mmio_debug; diff --git a/drivers/gpu/drm/i915/selftests/i915_gem.c b/drivers/gpu/drm/i915/selftests/i915_gem.c index e5dd82e7e480..0917315a67de 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem.c @@ -44,7 +44,7 @@ static void trash_stolen(struct drm_i915_private *i915) { struct i915_ggtt *ggtt = to_gt(i915)->ggtt; const u64 slot = ggtt->error_capture.start; - const resource_size_t size = resource_size(&i915->dsm); + const resource_size_t size = resource_size(&i915->dsm.stolen); unsigned long page; u32 prng = 0x12345678; @@ -53,7 +53,7 @@ static void trash_stolen(struct drm_i915_private *i915) return; for (page = 0; page < size; page += PAGE_SIZE) { - const dma_addr_t dma = i915->dsm.start + page; + const dma_addr_t dma = i915->dsm.stolen.start + page; u32 __iomem *s; int x; From e54051782e5d78a22d38ea361bd4013fa33b1060 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 16 Jan 2023 19:34:22 +0200 Subject: [PATCH 23/67] drm/i915: drop cast from DEFINE_RES_MEM() usage Since commit 52c4d11f1dce ("resource: Convert DEFINE_RES_NAMED() to be compound literal") it's no longer necessary to cast DEFINE_RES_MEM() to struct resource. This also fixes sparse warnings "cast from non-scalar" and "cast to non-scalar". Signed-off-by: Jani Nikula Reviewed-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20230116173422.1858527-2-jani.nikula@intel.com --- drivers/gpu/drm/i915/gem/i915_gem_stolen.c | 10 +++------- drivers/gpu/drm/i915/gt/intel_ggtt.c | 4 ++-- drivers/gpu/drm/i915/gt/intel_ggtt_gmch.c | 3 +-- drivers/gpu/drm/i915/intel_memory_region.c | 2 +- drivers/gpu/drm/i915/selftests/mock_gtt.c | 2 +- 5 files changed, 8 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_stolen.c b/drivers/gpu/drm/i915/gem/i915_gem_stolen.c index de873498d95b..90a967374b1a 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_stolen.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_stolen.c @@ -110,9 +110,7 @@ static int adjust_stolen(struct drm_i915_private *i915, else ggtt_start &= PGTBL_ADDRESS_LO_MASK; - ggtt_res = - (struct resource) DEFINE_RES_MEM(ggtt_start, - ggtt_total_entries(ggtt) * 4); + ggtt_res = DEFINE_RES_MEM(ggtt_start, ggtt_total_entries(ggtt) * 4); if (ggtt_res.start >= stolen[0].start && ggtt_res.start < stolen[0].end) stolen[0].end = ggtt_res.start; @@ -471,8 +469,7 @@ static int init_reserved_stolen(struct drm_i915_private *i915) goto bail_out; } - i915->dsm.reserved = - (struct resource)DEFINE_RES_MEM(reserved_base, reserved_size); + i915->dsm.reserved = DEFINE_RES_MEM(reserved_base, reserved_size); if (!resource_contains(&i915->dsm.stolen, &i915->dsm.reserved)) { drm_err(&i915->drm, @@ -485,8 +482,7 @@ static int init_reserved_stolen(struct drm_i915_private *i915) return 0; bail_out: - i915->dsm.reserved = - (struct resource)DEFINE_RES_MEM(reserved_base, 0); + i915->dsm.reserved = DEFINE_RES_MEM(reserved_base, 0); return ret; } diff --git a/drivers/gpu/drm/i915/gt/intel_ggtt.c b/drivers/gpu/drm/i915/gt/intel_ggtt.c index 8145851ad23d..2e75e3c10403 100644 --- a/drivers/gpu/drm/i915/gt/intel_ggtt.c +++ b/drivers/gpu/drm/i915/gt/intel_ggtt.c @@ -920,8 +920,8 @@ static void gen6_gmch_remove(struct i915_address_space *vm) static struct resource pci_resource(struct pci_dev *pdev, int bar) { - return (struct resource)DEFINE_RES_MEM(pci_resource_start(pdev, bar), - pci_resource_len(pdev, bar)); + return DEFINE_RES_MEM(pci_resource_start(pdev, bar), + pci_resource_len(pdev, bar)); } static int gen8_gmch_probe(struct i915_ggtt *ggtt) diff --git a/drivers/gpu/drm/i915/gt/intel_ggtt_gmch.c b/drivers/gpu/drm/i915/gt/intel_ggtt_gmch.c index 4e2163a1aa46..4192d06df0f2 100644 --- a/drivers/gpu/drm/i915/gt/intel_ggtt_gmch.c +++ b/drivers/gpu/drm/i915/gt/intel_ggtt_gmch.c @@ -89,8 +89,7 @@ int intel_ggtt_gmch_probe(struct i915_ggtt *ggtt) intel_gmch_gtt_get(&ggtt->vm.total, &gmadr_base, &ggtt->mappable_end); - ggtt->gmadr = - (struct resource)DEFINE_RES_MEM(gmadr_base, ggtt->mappable_end); + ggtt->gmadr = DEFINE_RES_MEM(gmadr_base, ggtt->mappable_end); ggtt->vm.alloc_pt_dma = alloc_pt_dma; ggtt->vm.alloc_scratch_dma = alloc_pt_dma; diff --git a/drivers/gpu/drm/i915/intel_memory_region.c b/drivers/gpu/drm/i915/intel_memory_region.c index b9a164efd6ae..3d1fdea9811d 100644 --- a/drivers/gpu/drm/i915/intel_memory_region.c +++ b/drivers/gpu/drm/i915/intel_memory_region.c @@ -235,7 +235,7 @@ intel_memory_region_create(struct drm_i915_private *i915, return ERR_PTR(-ENOMEM); mem->i915 = i915; - mem->region = (struct resource)DEFINE_RES_MEM(start, size); + mem->region = DEFINE_RES_MEM(start, size); mem->io_start = io_start; mem->io_size = io_size; mem->min_page_size = min_page_size; diff --git a/drivers/gpu/drm/i915/selftests/mock_gtt.c b/drivers/gpu/drm/i915/selftests/mock_gtt.c index 568840e7ca66..ece97e4faacb 100644 --- a/drivers/gpu/drm/i915/selftests/mock_gtt.c +++ b/drivers/gpu/drm/i915/selftests/mock_gtt.c @@ -112,7 +112,7 @@ void mock_init_ggtt(struct intel_gt *gt) ggtt->vm.i915 = gt->i915; ggtt->vm.is_ggtt = true; - ggtt->gmadr = (struct resource) DEFINE_RES_MEM(0, 2048 * PAGE_SIZE); + ggtt->gmadr = DEFINE_RES_MEM(0, 2048 * PAGE_SIZE); ggtt->mappable_end = resource_size(&ggtt->gmadr); ggtt->vm.total = 4096 * PAGE_SIZE; From 3a7e2d58f8002a71d9f2f803e2fd6ba05a07b404 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 17 Jan 2023 16:39:44 +0200 Subject: [PATCH 24/67] drm/i915: move snps_phy_failed_calibration to display sub-struct under snps Move the display related member to the struct drm_i915_private display sub-struct. Signed-off-by: Jani Nikula Reviewed-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20230117143946.2426043-1-jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_ddi.c | 2 +- drivers/gpu/drm/i915/display/intel_display_core.h | 8 ++++++++ drivers/gpu/drm/i915/display/intel_snps_phy.c | 2 +- drivers/gpu/drm/i915/i915_drv.h | 6 ------ 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 1f5a471a0adf..0034a43f56e5 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -4323,7 +4323,7 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port) } if (intel_phy_is_snps(dev_priv, phy) && - dev_priv->snps_phy_failed_calibration & BIT(phy)) { + dev_priv->display.snps.phy_failed_calibration & BIT(phy)) { drm_dbg_kms(&dev_priv->drm, "SNPS PHY %c failed to calibrate, proceeding anyway\n", phy_name(phy)); diff --git a/drivers/gpu/drm/i915/display/intel_display_core.h b/drivers/gpu/drm/i915/display/intel_display_core.h index 57ddce3ba02b..2e85dd0ef4b5 100644 --- a/drivers/gpu/drm/i915/display/intel_display_core.h +++ b/drivers/gpu/drm/i915/display/intel_display_core.h @@ -428,6 +428,14 @@ struct intel_display { u32 block_time_us; } sagv; + struct { + /* + * DG2: Mask of PHYs that were not calibrated by the firmware + * and should not be used. + */ + u8 phy_failed_calibration; + } snps; + struct { /* ordered wq for modesets */ struct workqueue_struct *modeset; diff --git a/drivers/gpu/drm/i915/display/intel_snps_phy.c b/drivers/gpu/drm/i915/display/intel_snps_phy.c index 9494cfd45519..c65c771f5c46 100644 --- a/drivers/gpu/drm/i915/display/intel_snps_phy.c +++ b/drivers/gpu/drm/i915/display/intel_snps_phy.c @@ -40,7 +40,7 @@ void intel_snps_phy_wait_for_calibration(struct drm_i915_private *i915) */ if (intel_de_wait_for_clear(i915, DG2_PHY_MISC(phy), DG2_PHY_DP_TX_ACK_MASK, 25)) - i915->snps_phy_failed_calibration |= BIT(phy); + i915->display.snps.phy_failed_calibration |= BIT(phy); } } diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 83bc69892a86..bedcd0891c48 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -381,12 +381,6 @@ struct drm_i915_private { bool irq_enabled; - /* - * DG2: Mask of PHYs that were not calibrated by the firmware - * and should not be used. - */ - u8 snps_phy_failed_calibration; - struct i915_pmu pmu; struct i915_drm_clients clients; From a3f839762ceb72699f5c6c313bf90c374b860a7c Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 17 Jan 2023 16:39:45 +0200 Subject: [PATCH 25/67] drm/i915: move pch_ssc_use to display sub-struct under dpll Move the display related member to the struct drm_i915_private display sub-struct. Signed-off-by: Jani Nikula Reviewed-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20230117143946.2426043-2-jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_display_core.h | 5 +++++ drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 4 ++-- drivers/gpu/drm/i915/display/intel_pch_refclk.c | 10 +++++----- drivers/gpu/drm/i915/i915_drv.h | 2 -- 4 files changed, 12 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_core.h b/drivers/gpu/drm/i915/display/intel_display_core.h index 2e85dd0ef4b5..c0eb753112d5 100644 --- a/drivers/gpu/drm/i915/display/intel_display_core.h +++ b/drivers/gpu/drm/i915/display/intel_display_core.h @@ -122,6 +122,11 @@ struct intel_dpll { int nssc; int ssc; } ref_clks; + + /* + * Bitmask of PLLs using the PCH SSC, indexed using enum intel_dpll_id. + */ + u8 pch_ssc_use; }; struct intel_frontbuffer_tracking { diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index 1974eb580ed1..380368eff31a 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -618,7 +618,7 @@ static void hsw_ddi_wrpll_disable(struct drm_i915_private *dev_priv, * Try to set up the PCH reference clock once all DPLLs * that depend on it have been shut down. */ - if (dev_priv->pch_ssc_use & BIT(id)) + if (dev_priv->display.dpll.pch_ssc_use & BIT(id)) intel_init_pch_refclk(dev_priv); } @@ -636,7 +636,7 @@ static void hsw_ddi_spll_disable(struct drm_i915_private *dev_priv, * Try to set up the PCH reference clock once all DPLLs * that depend on it have been shut down. */ - if (dev_priv->pch_ssc_use & BIT(id)) + if (dev_priv->display.dpll.pch_ssc_use & BIT(id)) intel_init_pch_refclk(dev_priv); } diff --git a/drivers/gpu/drm/i915/display/intel_pch_refclk.c b/drivers/gpu/drm/i915/display/intel_pch_refclk.c index 08a94365b7d1..3657b2940702 100644 --- a/drivers/gpu/drm/i915/display/intel_pch_refclk.c +++ b/drivers/gpu/drm/i915/display/intel_pch_refclk.c @@ -467,24 +467,24 @@ static void lpt_init_pch_refclk(struct drm_i915_private *dev_priv) * clock hierarchy. That would also allow us to do * clock bending finally. */ - dev_priv->pch_ssc_use = 0; + dev_priv->display.dpll.pch_ssc_use = 0; if (spll_uses_pch_ssc(dev_priv)) { drm_dbg_kms(&dev_priv->drm, "SPLL using PCH SSC\n"); - dev_priv->pch_ssc_use |= BIT(DPLL_ID_SPLL); + dev_priv->display.dpll.pch_ssc_use |= BIT(DPLL_ID_SPLL); } if (wrpll_uses_pch_ssc(dev_priv, DPLL_ID_WRPLL1)) { drm_dbg_kms(&dev_priv->drm, "WRPLL1 using PCH SSC\n"); - dev_priv->pch_ssc_use |= BIT(DPLL_ID_WRPLL1); + dev_priv->display.dpll.pch_ssc_use |= BIT(DPLL_ID_WRPLL1); } if (wrpll_uses_pch_ssc(dev_priv, DPLL_ID_WRPLL2)) { drm_dbg_kms(&dev_priv->drm, "WRPLL2 using PCH SSC\n"); - dev_priv->pch_ssc_use |= BIT(DPLL_ID_WRPLL2); + dev_priv->display.dpll.pch_ssc_use |= BIT(DPLL_ID_WRPLL2); } - if (dev_priv->pch_ssc_use) + if (dev_priv->display.dpll.pch_ssc_use) return; if (has_fdi) { diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index bedcd0891c48..4e24d6f597d5 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -374,8 +374,6 @@ struct drm_i915_private { struct file *mmap_singleton; } gem; - u8 pch_ssc_use; - /* For i915gm/i945gm vblank irq workaround */ u8 vblank_enabled; From e2855f8e913dac4fc699a54b793cd4753c30b4d3 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 17 Jan 2023 16:39:46 +0200 Subject: [PATCH 26/67] drm/i915: move chv_dpll_md and bxt_phy_grc to display sub-struct under state Move the display related members to the struct drm_i915_private display sub-struct. Put them under "state", as they are related to storing values that aren't readable from the hardware, to appease the state checker. Signed-off-by: Jani Nikula Reviewed-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20230117143946.2426043-3-jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 2 +- drivers/gpu/drm/i915/display/intel_display_core.h | 10 ++++++++++ drivers/gpu/drm/i915/display/intel_dpio_phy.c | 9 +++++---- drivers/gpu/drm/i915/display/intel_dpll.c | 2 +- drivers/gpu/drm/i915/i915_drv.h | 8 -------- 5 files changed, 17 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 9b73663a0499..c38a54efedbe 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -3241,7 +3241,7 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc, if (DISPLAY_VER(dev_priv) >= 4) { /* No way to read it out on pipes B and C */ if (IS_CHERRYVIEW(dev_priv) && crtc->pipe != PIPE_A) - tmp = dev_priv->chv_dpll_md[crtc->pipe]; + tmp = dev_priv->display.state.chv_dpll_md[crtc->pipe]; else tmp = intel_de_read(dev_priv, DPLL_MD(crtc->pipe)); pipe_config->pixel_multiplier = diff --git a/drivers/gpu/drm/i915/display/intel_display_core.h b/drivers/gpu/drm/i915/display/intel_display_core.h index c0eb753112d5..24c792d44b8f 100644 --- a/drivers/gpu/drm/i915/display/intel_display_core.h +++ b/drivers/gpu/drm/i915/display/intel_display_core.h @@ -441,6 +441,16 @@ struct intel_display { u8 phy_failed_calibration; } snps; + struct { + /* + * Shadows for CHV DPLL_MD regs to keep the state + * checker somewhat working in the presence hardware + * crappiness (can't read out DPLL_MD for pipes B & C). + */ + u32 chv_dpll_md[I915_MAX_PIPES]; + u32 bxt_phy_grc; + } state; + struct { /* ordered wq for modesets */ struct workqueue_struct *modeset; diff --git a/drivers/gpu/drm/i915/display/intel_dpio_phy.c b/drivers/gpu/drm/i915/display/intel_dpio_phy.c index 7eb7440b3180..565c06de2432 100644 --- a/drivers/gpu/drm/i915/display/intel_dpio_phy.c +++ b/drivers/gpu/drm/i915/display/intel_dpio_phy.c @@ -376,7 +376,7 @@ static void _bxt_ddi_phy_init(struct drm_i915_private *dev_priv, if (bxt_ddi_phy_is_enabled(dev_priv, phy)) { /* Still read out the GRC value for state verification */ if (phy_info->rcomp_phy != -1) - dev_priv->bxt_phy_grc = bxt_get_grc(dev_priv, phy); + dev_priv->display.state.bxt_phy_grc = bxt_get_grc(dev_priv, phy); if (bxt_ddi_phy_verify_state(dev_priv, phy)) { drm_dbg(&dev_priv->drm, "DDI PHY %d already enabled, " @@ -442,8 +442,9 @@ static void _bxt_ddi_phy_init(struct drm_i915_private *dev_priv, * the corresponding calibrated value from PHY1, and disable * the automatic calibration on PHY0. */ - val = dev_priv->bxt_phy_grc = bxt_get_grc(dev_priv, - phy_info->rcomp_phy); + val = bxt_get_grc(dev_priv, phy_info->rcomp_phy); + dev_priv->display.state.bxt_phy_grc = val; + grc_code = val << GRC_CODE_FAST_SHIFT | val << GRC_CODE_SLOW_SHIFT | val; @@ -568,7 +569,7 @@ bool bxt_ddi_phy_verify_state(struct drm_i915_private *dev_priv, "BXT_PORT_CL2CM_DW6(%d)", phy); if (phy_info->rcomp_phy != -1) { - u32 grc_code = dev_priv->bxt_phy_grc; + u32 grc_code = dev_priv->display.state.bxt_phy_grc; grc_code = grc_code << GRC_CODE_FAST_SHIFT | grc_code << GRC_CODE_SLOW_SHIFT | diff --git a/drivers/gpu/drm/i915/display/intel_dpll.c b/drivers/gpu/drm/i915/display/intel_dpll.c index c236aafe9be0..4e9c18be7e1f 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll.c +++ b/drivers/gpu/drm/i915/display/intel_dpll.c @@ -1910,7 +1910,7 @@ void chv_enable_pll(const struct intel_crtc_state *crtc_state) intel_de_write(dev_priv, DPLL_MD(PIPE_B), crtc_state->dpll_hw_state.dpll_md); intel_de_write(dev_priv, CBR4_VLV, 0); - dev_priv->chv_dpll_md[pipe] = crtc_state->dpll_hw_state.dpll_md; + dev_priv->display.state.chv_dpll_md[pipe] = crtc_state->dpll_hw_state.dpll_md; /* * DPLLB VGA mode also seems to cause problems. diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 4e24d6f597d5..bdb853bb668a 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -308,14 +308,6 @@ struct drm_i915_private { struct i915_gpu_error gpu_error; - /* - * Shadows for CHV DPLL_MD regs to keep the state - * checker somewhat working in the presence hardware - * crappiness (can't read out DPLL_MD for pipes B & C). - */ - u32 chv_dpll_md[I915_MAX_PIPES]; - u32 bxt_phy_grc; - u32 suspend_count; struct i915_suspend_saved_registers regfile; struct vlv_s0ix_state *vlv_s0ix_state; From 24d97468f4f325e2c0ac052907c59e6956e96dee Mon Sep 17 00:00:00 2001 From: Deepak R Varma Date: Sat, 14 Jan 2023 19:33:53 +0530 Subject: [PATCH 27/67] drm/i915/display: Convert i9xx_pipe_crc_auto_source to void Convert function i9xx_pipe_crc_auto_source() to return void instead of int since the current implementation always returns 0 to the caller. Issue identified using returnvar Coccinelle semantic patch. $ make coccicheck COCCI=scripts/coccinelle/misc/returnvar.cocci \ M=drivers/gpu/drm/i915/ Signed-off-by: Deepak R Varma Reviewed-by: Rodrigo Vivi Signed-off-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/Y8K2SS/zNiPAmLsS@ubun2204.myguest.virtualbox.org --- drivers/gpu/drm/i915/display/intel_pipe_crc.c | 23 ++++++------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_pipe_crc.c b/drivers/gpu/drm/i915/display/intel_pipe_crc.c index e9774670e3f6..8d3ea8d7b737 100644 --- a/drivers/gpu/drm/i915/display/intel_pipe_crc.c +++ b/drivers/gpu/drm/i915/display/intel_pipe_crc.c @@ -72,14 +72,13 @@ static int i8xx_pipe_crc_ctl_reg(enum intel_pipe_crc_source *source, return 0; } -static int i9xx_pipe_crc_auto_source(struct drm_i915_private *dev_priv, - enum pipe pipe, - enum intel_pipe_crc_source *source) +static void i9xx_pipe_crc_auto_source(struct drm_i915_private *dev_priv, + enum pipe pipe, + enum intel_pipe_crc_source *source) { struct intel_encoder *encoder; struct intel_crtc *crtc; struct intel_digital_port *dig_port; - int ret = 0; *source = INTEL_PIPE_CRC_SOURCE_PIPE; @@ -121,8 +120,6 @@ static int i9xx_pipe_crc_auto_source(struct drm_i915_private *dev_priv, } } drm_modeset_unlock_all(&dev_priv->drm); - - return ret; } static int vlv_pipe_crc_ctl_reg(struct drm_i915_private *dev_priv, @@ -132,11 +129,8 @@ static int vlv_pipe_crc_ctl_reg(struct drm_i915_private *dev_priv, { bool need_stable_symbols = false; - if (*source == INTEL_PIPE_CRC_SOURCE_AUTO) { - int ret = i9xx_pipe_crc_auto_source(dev_priv, pipe, source); - if (ret) - return ret; - } + if (*source == INTEL_PIPE_CRC_SOURCE_AUTO) + i9xx_pipe_crc_auto_source(dev_priv, pipe, source); switch (*source) { case INTEL_PIPE_CRC_SOURCE_PIPE: @@ -200,11 +194,8 @@ static int i9xx_pipe_crc_ctl_reg(struct drm_i915_private *dev_priv, enum intel_pipe_crc_source *source, u32 *val) { - if (*source == INTEL_PIPE_CRC_SOURCE_AUTO) { - int ret = i9xx_pipe_crc_auto_source(dev_priv, pipe, source); - if (ret) - return ret; - } + if (*source == INTEL_PIPE_CRC_SOURCE_AUTO) + i9xx_pipe_crc_auto_source(dev_priv, pipe, source); switch (*source) { case INTEL_PIPE_CRC_SOURCE_PIPE: From ff1e93e924f236ab7f5b445820bf4e81cf9845b7 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 18 Jan 2023 15:15:32 +0200 Subject: [PATCH 28/67] drm/i915: add i915_config.h and move relevant declarations there We already have i915_config.c. Add the i915_config.h counterpart, and declutter i915_drv.h in the process. Signed-off-by: Jani Nikula Reviewed-by: Tvrtko Ursulin Acked-by: Nirmoy Das Link: https://patchwork.freedesktop.org/patch/msgid/20230118131538.3558599-1-jani.nikula@intel.com --- .../gpu/drm/i915/display/intel_atomic_plane.c | 1 + drivers/gpu/drm/i915/gem/i915_gem_clflush.c | 1 + drivers/gpu/drm/i915/i915_config.c | 5 +++- drivers/gpu/drm/i915/i915_config.h | 23 +++++++++++++++++++ drivers/gpu/drm/i915/i915_drv.h | 9 -------- drivers/gpu/drm/i915/i915_request.c | 1 + 6 files changed, 30 insertions(+), 10 deletions(-) create mode 100644 drivers/gpu/drm/i915/i915_config.h diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.c b/drivers/gpu/drm/i915/display/intel_atomic_plane.c index 10e1fc9d0698..1409bcfb6fd3 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.c @@ -36,6 +36,7 @@ #include "gt/intel_rps.h" +#include "i915_config.h" #include "intel_atomic_plane.h" #include "intel_cdclk.h" #include "intel_display_trace.h" diff --git a/drivers/gpu/drm/i915/gem/i915_gem_clflush.c b/drivers/gpu/drm/i915/gem/i915_gem_clflush.c index b3b398fe689c..385ffc575b48 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_clflush.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_clflush.c @@ -8,6 +8,7 @@ #include "display/intel_frontbuffer.h" +#include "i915_config.h" #include "i915_drv.h" #include "i915_gem_clflush.h" #include "i915_sw_fence_work.h" diff --git a/drivers/gpu/drm/i915/i915_config.c b/drivers/gpu/drm/i915/i915_config.c index afb828dab53b..24e5bb8a670e 100644 --- a/drivers/gpu/drm/i915/i915_config.c +++ b/drivers/gpu/drm/i915/i915_config.c @@ -3,7 +3,10 @@ * Copyright © 2020 Intel Corporation */ -#include "i915_drv.h" +#include + +#include "i915_config.h" +#include "i915_utils.h" unsigned long i915_fence_context_timeout(const struct drm_i915_private *i915, u64 context) diff --git a/drivers/gpu/drm/i915/i915_config.h b/drivers/gpu/drm/i915/i915_config.h new file mode 100644 index 000000000000..10e18b036489 --- /dev/null +++ b/drivers/gpu/drm/i915/i915_config.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2023 Intel Corporation + */ + +#ifndef __I915_CONFIG_H__ +#define __I915_CONFIG_H__ + +#include +#include + +struct drm_i915_private; + +unsigned long i915_fence_context_timeout(const struct drm_i915_private *i915, + u64 context); + +static inline unsigned long +i915_fence_timeout(const struct drm_i915_private *i915) +{ + return i915_fence_context_timeout(i915, U64_MAX); +} + +#endif /* __I915_CONFIG_H__ */ diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index bdb853bb668a..c2cf1de017b5 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -195,15 +195,6 @@ struct i915_gem_mm { #define I915_IDLE_ENGINES_TIMEOUT (200) /* in ms */ -unsigned long i915_fence_context_timeout(const struct drm_i915_private *i915, - u64 context); - -static inline unsigned long -i915_fence_timeout(const struct drm_i915_private *i915) -{ - return i915_fence_context_timeout(i915, U64_MAX); -} - #define HAS_HW_SAGV_WM(i915) (DISPLAY_VER(i915) >= 13 && !IS_DGFX(i915)) struct i915_virtual_gpu { diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c index f949a9495758..7503dcb9043b 100644 --- a/drivers/gpu/drm/i915/i915_request.c +++ b/drivers/gpu/drm/i915/i915_request.c @@ -43,6 +43,7 @@ #include "gt/intel_rps.h" #include "i915_active.h" +#include "i915_config.h" #include "i915_deps.h" #include "i915_driver.h" #include "i915_drv.h" From 6c13c8250c00a92067dba70d26c432eac7fcb357 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 18 Jan 2023 15:15:33 +0200 Subject: [PATCH 29/67] drm/i915: move I915_IDLE_ENGINES_TIMEOUT next to its only user Declutter i915_drv.h. If there's ever a need to use this in more than one place, we can figure out a better spot then. For now, this seems easiest. Signed-off-by: Jani Nikula Acked-by: Tvrtko Ursulin Acked-by: Nirmoy Das Link: https://patchwork.freedesktop.org/patch/msgid/20230118131538.3558599-2-jani.nikula@intel.com --- drivers/gpu/drm/i915/i915_debugfs.c | 3 +++ drivers/gpu/drm/i915/i915_drv.h | 2 -- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 6c7ac73b69a5..3279de32111b 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -648,6 +648,9 @@ i915_drop_caches_get(void *data, u64 *val) return 0; } + +#define I915_IDLE_ENGINES_TIMEOUT (200) /* in ms */ + static int gt_drop_caches(struct intel_gt *gt, u64 val) { diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index c2cf1de017b5..6e7691f51961 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -193,8 +193,6 @@ struct i915_gem_mm { u32 shrink_count; }; -#define I915_IDLE_ENGINES_TIMEOUT (200) /* in ms */ - #define HAS_HW_SAGV_WM(i915) (DISPLAY_VER(i915) >= 13 && !IS_DGFX(i915)) struct i915_virtual_gpu { From 0d885242f335a6332a173f1884b20f90e3f71f33 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 18 Jan 2023 15:15:34 +0200 Subject: [PATCH 30/67] drm/i915: drop a number of unnecessary forward declarations Remove leftovers from earlier cleanups. Signed-off-by: Jani Nikula Acked-by: Tvrtko Ursulin Acked-by: Nirmoy Das Link: https://patchwork.freedesktop.org/patch/msgid/20230118131538.3558599-3-jani.nikula@intel.com --- drivers/gpu/drm/i915/i915_drv.h | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 6e7691f51961..a8696c3cf29a 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -65,13 +65,6 @@ #include "intel_uncore.h" struct drm_i915_clock_gating_funcs; -struct drm_i915_gem_object; -struct drm_i915_private; -struct intel_connector; -struct intel_dp; -struct intel_encoder; -struct intel_limit; -struct intel_overlay_error_state; struct vlv_s0ix_state; #define I915_GEM_GPU_DOMAINS \ From fff6172798cdc83ec1a17b4816b752172f86b51f Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 18 Jan 2023 15:15:35 +0200 Subject: [PATCH 31/67] drm/i915: move a few HAS_ macros closer to their place There's not that much organization with where the various HAS_FEATURE() macros are placed, but at least try to group them closer together. Signed-off-by: Jani Nikula Acked-by: Nirmoy Das Link: https://patchwork.freedesktop.org/patch/msgid/20230118131538.3558599-4-jani.nikula@intel.com --- drivers/gpu/drm/i915/i915_drv.h | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index a8696c3cf29a..60661d89f350 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -186,8 +186,6 @@ struct i915_gem_mm { u32 shrink_count; }; -#define HAS_HW_SAGV_WM(i915) (DISPLAY_VER(i915) >= 13 && !IS_DGFX(i915)) - struct i915_virtual_gpu { struct mutex lock; /* serialises sending of g2v_notify command pkts */ bool active; @@ -441,9 +439,6 @@ static inline struct intel_gt *to_gt(struct drm_i915_private *i915) #define INTEL_REVID(dev_priv) (to_pci_dev((dev_priv)->drm.dev)->revision) -#define HAS_DSB(dev_priv) (INTEL_INFO(dev_priv)->display.has_dsb) -#define HAS_DSC(__i915) (RUNTIME_INFO(__i915)->has_dsc) - #define INTEL_DISPLAY_STEP(__i915) (RUNTIME_INFO(__i915)->step.display_step) #define INTEL_GRAPHICS_STEP(__i915) (RUNTIME_INFO(__i915)->step.graphics_step) #define INTEL_MEDIA_STEP(__i915) (RUNTIME_INFO(__i915)->step.media_step) @@ -855,6 +850,9 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915, #define HAS_RPS(dev_priv) (INTEL_INFO(dev_priv)->has_rps) #define HAS_DMC(dev_priv) (RUNTIME_INFO(dev_priv)->has_dmc) +#define HAS_DSB(dev_priv) (INTEL_INFO(dev_priv)->display.has_dsb) +#define HAS_DSC(__i915) (RUNTIME_INFO(__i915)->has_dsc) +#define HAS_HW_SAGV_WM(i915) (DISPLAY_VER(i915) >= 13 && !IS_DGFX(i915)) #define HAS_HECI_PXP(dev_priv) \ (INTEL_INFO(dev_priv)->has_heci_pxp) From 0b31a427b9f28ba1ec099b236da1fea0c513b815 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 18 Jan 2023 15:15:36 +0200 Subject: [PATCH 32/67] drm/i915: move I915_GEM_GPU_DOMAINS to i915_gem.h Declutter i915_drv.h. Signed-off-by: Jani Nikula Acked-by: Tvrtko Ursulin Reviewed-by: Nirmoy Das Link: https://patchwork.freedesktop.org/patch/msgid/20230118131538.3558599-5-jani.nikula@intel.com --- drivers/gpu/drm/i915/i915_drv.h | 7 ------- drivers/gpu/drm/i915/i915_gem.h | 7 +++++++ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 60661d89f350..00fa7547d982 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -67,13 +67,6 @@ struct drm_i915_clock_gating_funcs; struct vlv_s0ix_state; -#define I915_GEM_GPU_DOMAINS \ - (I915_GEM_DOMAIN_RENDER | \ - I915_GEM_DOMAIN_SAMPLER | \ - I915_GEM_DOMAIN_COMMAND | \ - I915_GEM_DOMAIN_INSTRUCTION | \ - I915_GEM_DOMAIN_VERTEX) - #define I915_COLOR_UNEVICTABLE (-1) /* a non-vma sharing the address space */ #define GEM_QUIRK_PIN_SWIZZLED_PAGES BIT(0) diff --git a/drivers/gpu/drm/i915/i915_gem.h b/drivers/gpu/drm/i915/i915_gem.h index a5cdf6662d01..82e9d289398c 100644 --- a/drivers/gpu/drm/i915/i915_gem.h +++ b/drivers/gpu/drm/i915/i915_gem.h @@ -39,6 +39,13 @@ struct i915_gem_ww_ctx; struct i915_gtt_view; struct i915_vma; +#define I915_GEM_GPU_DOMAINS \ + (I915_GEM_DOMAIN_RENDER | \ + I915_GEM_DOMAIN_SAMPLER | \ + I915_GEM_DOMAIN_COMMAND | \ + I915_GEM_DOMAIN_INSTRUCTION | \ + I915_GEM_DOMAIN_VERTEX) + void i915_gem_init_early(struct drm_i915_private *i915); void i915_gem_cleanup_early(struct drm_i915_private *i915); From 0cfee2d7fd992d51cd68cc333dfebadc923abd92 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 18 Jan 2023 15:15:37 +0200 Subject: [PATCH 33/67] drm/i915: move I915_COLOR_UNEVICTABLE to i915_gem_gtt.h Declutter i915_drv.h. Signed-off-by: Jani Nikula Acked-by: Tvrtko Ursulin Acked-by: Nirmoy Das Link: https://patchwork.freedesktop.org/patch/msgid/20230118131538.3558599-6-jani.nikula@intel.com --- drivers/gpu/drm/i915/i915_drv.h | 2 -- drivers/gpu/drm/i915/i915_gem_gtt.h | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 00fa7547d982..a2dcd08c925c 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -67,8 +67,6 @@ struct drm_i915_clock_gating_funcs; struct vlv_s0ix_state; -#define I915_COLOR_UNEVICTABLE (-1) /* a non-vma sharing the address space */ - #define GEM_QUIRK_PIN_SWIZZLED_PAGES BIT(0) /* Data Stolen Memory (DSM) aka "i915 stolen memory" */ diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h index 8c2f57eb5dda..4c299800cfed 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.h +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h @@ -18,6 +18,8 @@ struct drm_i915_gem_object; struct i915_address_space; struct i915_gem_ww_ctx; +#define I915_COLOR_UNEVICTABLE (-1) /* a non-vma sharing the address space */ + int __must_check i915_gem_gtt_prepare_pages(struct drm_i915_gem_object *obj, struct sg_table *pages); void i915_gem_gtt_finish_pages(struct drm_i915_gem_object *obj, From 72b9da733bab037f596e06513912ecaa2e3171b8 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 18 Jan 2023 15:15:38 +0200 Subject: [PATCH 34/67] drm/i915: move GT_FREQUENCY_MULTIPLIER and GEN9_FREQ_SCALER to intel_rps.h Declutter i915_drv.h. Signed-off-by: Jani Nikula Acked-by: Tvrtko Ursulin Acked-by: Nirmoy Das Link: https://patchwork.freedesktop.org/patch/msgid/20230118131538.3558599-7-jani.nikula@intel.com --- drivers/gpu/drm/i915/gt/intel_rps.h | 3 +++ drivers/gpu/drm/i915/i915_drv.h | 3 --- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_rps.h b/drivers/gpu/drm/i915/gt/intel_rps.h index 9e1cad9ba0e9..c622962c6bef 100644 --- a/drivers/gpu/drm/i915/gt/intel_rps.h +++ b/drivers/gpu/drm/i915/gt/intel_rps.h @@ -12,6 +12,9 @@ struct i915_request; struct drm_printer; +#define GT_FREQUENCY_MULTIPLIER 50 +#define GEN9_FREQ_SCALER 3 + void intel_rps_init_early(struct intel_rps *rps); void intel_rps_init(struct intel_rps *rps); void intel_rps_sanitize(struct intel_rps *rps); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index a2dcd08c925c..ac4c3c6f5541 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -905,9 +905,6 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915, #define NUM_L3_SLICES(dev_priv) (IS_HSW_GT3(dev_priv) ? \ 2 : HAS_L3_DPF(dev_priv)) -#define GT_FREQUENCY_MULTIPLIER 50 -#define GEN9_FREQ_SCALER 3 - #define INTEL_NUM_PIPES(dev_priv) (hweight8(RUNTIME_INFO(dev_priv)->pipe_mask)) #define HAS_DISPLAY(dev_priv) (RUNTIME_INFO(dev_priv)->pipe_mask != 0) From fdbc5aeb6b7824e45a0a1775a1c8d999c9f7e65a Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Fri, 20 Jan 2023 06:06:58 -0500 Subject: [PATCH 35/67] drm/i915/debugfs: Get rid of single use macros. No good reason for these indirection cases. Cc: Jani Nikula Signed-off-by: Rodrigo Vivi Reviewed-by: Andi Shyti Link: https://patchwork.freedesktop.org/patch/msgid/20230120110658.1083757-1-rodrigo.vivi@intel.com --- drivers/gpu/drm/i915/i915_debugfs.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 3279de32111b..518c8fb8fd12 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -649,15 +649,13 @@ i915_drop_caches_get(void *data, u64 *val) return 0; } -#define I915_IDLE_ENGINES_TIMEOUT (200) /* in ms */ - static int gt_drop_caches(struct intel_gt *gt, u64 val) { int ret; if (val & DROP_RESET_ACTIVE && - wait_for(intel_engines_are_idle(gt), I915_IDLE_ENGINES_TIMEOUT)) + wait_for(intel_engines_are_idle(gt), 200)) intel_gt_set_wedged(gt); if (val & DROP_RETIRE) @@ -765,7 +763,6 @@ static const struct drm_info_list i915_debugfs_list[] = { {"i915_sseu_status", i915_sseu_status, 0}, {"i915_rps_boost_info", i915_rps_boost_info, 0}, }; -#define I915_DEBUGFS_ENTRIES ARRAY_SIZE(i915_debugfs_list) static const struct i915_debugfs_files { const char *name; @@ -798,6 +795,6 @@ void i915_debugfs_register(struct drm_i915_private *dev_priv) } drm_debugfs_create_files(i915_debugfs_list, - I915_DEBUGFS_ENTRIES, + ARRAY_SIZE(i915_debugfs_list), minor->debugfs_root, minor); } From 3af2ff0840be88c6c17f057ec285ab4dc2ff214f Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 2 Jan 2023 20:33:24 +0200 Subject: [PATCH 36/67] drm/i915: Enable a PIPEDMC whenever its corresponding pipe is enabled Make sure that PIPEDMCs are enabled whenever the corresponding pipe is enabled. This is required at least by the latest ADLP v2.18 firmware, which adds a new handler enabled by default and running whenever the pipe is enabled at the vertical referesh rate. Bspec: 50344, 67620 Signed-off-by: Imre Deak Reviewed-by: Rodrigo Vivi Tested-by: Gustavo Sousa Link: https://patchwork.freedesktop.org/patch/msgid/20230102183324.862279-1-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 5 ++++ drivers/gpu/drm/i915/display/intel_dmc.c | 24 +++++++++++++++++++ drivers/gpu/drm/i915/display/intel_dmc.h | 4 ++++ drivers/gpu/drm/i915/display/intel_dmc_regs.h | 10 ++++++++ .../drm/i915/display/intel_modeset_setup.c | 4 +++- 5 files changed, 46 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index c38a54efedbe..e37cca6b18c6 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -1867,6 +1867,8 @@ static void hsw_crtc_enable(struct intel_atomic_state *state, if (drm_WARN_ON(&dev_priv->drm, crtc->active)) return; + intel_dmc_enable_pipe(dev_priv, crtc->pipe); + if (!new_crtc_state->bigjoiner_pipes) { intel_encoders_pre_pll_enable(state, crtc); @@ -2002,6 +2004,7 @@ static void hsw_crtc_disable(struct intel_atomic_state *state, { const struct intel_crtc_state *old_crtc_state = intel_atomic_get_old_crtc_state(state, crtc); + struct drm_i915_private *i915 = to_i915(crtc->base.dev); /* * FIXME collapse everything to one hook. @@ -2011,6 +2014,8 @@ static void hsw_crtc_disable(struct intel_atomic_state *state, intel_encoders_disable(state, crtc); intel_encoders_post_disable(state, crtc); } + + intel_dmc_disable_pipe(i915, crtc->pipe); } static void i9xx_pfit_enable(const struct intel_crtc_state *crtc_state) diff --git a/drivers/gpu/drm/i915/display/intel_dmc.c b/drivers/gpu/drm/i915/display/intel_dmc.c index 4124b3d37110..370c91d323fc 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc.c +++ b/drivers/gpu/drm/i915/display/intel_dmc.c @@ -97,6 +97,8 @@ MODULE_FIRMWARE(BXT_DMC_PATH); #define DMC_V3_MAX_MMIO_COUNT 20 #define DMC_V1_MMIO_START_RANGE 0x80000 +#define PIPE_TO_DMC_ID(pipe) (DMC_FW_PIPEA + ((pipe) - PIPE_A)) + struct intel_css_header { /* 0x09 for DMC */ u32 module_type; @@ -396,6 +398,28 @@ static void pipedmc_clock_gating_wa(struct drm_i915_private *i915, bool enable) PIPEDMC_GATING_DIS, 0); } +void intel_dmc_enable_pipe(struct drm_i915_private *i915, enum pipe pipe) +{ + if (!has_dmc_id_fw(i915, PIPE_TO_DMC_ID(pipe))) + return; + + if (DISPLAY_VER(i915) >= 14) + intel_de_rmw(i915, MTL_PIPEDMC_CONTROL, 0, PIPEDMC_ENABLE_MTL(pipe)); + else + intel_de_rmw(i915, PIPEDMC_CONTROL(pipe), 0, PIPEDMC_ENABLE); +} + +void intel_dmc_disable_pipe(struct drm_i915_private *i915, enum pipe pipe) +{ + if (!has_dmc_id_fw(i915, PIPE_TO_DMC_ID(pipe))) + return; + + if (DISPLAY_VER(i915) >= 14) + intel_de_rmw(i915, MTL_PIPEDMC_CONTROL, PIPEDMC_ENABLE_MTL(pipe), 0); + else + intel_de_rmw(i915, PIPEDMC_CONTROL(pipe), PIPEDMC_ENABLE, 0); +} + /** * intel_dmc_load_program() - write the firmware from memory to register. * @dev_priv: i915 drm device. diff --git a/drivers/gpu/drm/i915/display/intel_dmc.h b/drivers/gpu/drm/i915/display/intel_dmc.h index 435eab9b016b..fd1725de4289 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc.h +++ b/drivers/gpu/drm/i915/display/intel_dmc.h @@ -13,6 +13,8 @@ struct drm_i915_error_state_buf; struct drm_i915_private; +enum pipe; + enum { DMC_FW_MAIN = 0, DMC_FW_PIPEA, @@ -47,6 +49,8 @@ struct intel_dmc { void intel_dmc_ucode_init(struct drm_i915_private *i915); void intel_dmc_load_program(struct drm_i915_private *i915); void intel_dmc_disable_program(struct drm_i915_private *i915); +void intel_dmc_enable_pipe(struct drm_i915_private *i915, enum pipe pipe); +void intel_dmc_disable_pipe(struct drm_i915_private *i915, enum pipe pipe); void intel_dmc_ucode_fini(struct drm_i915_private *i915); void intel_dmc_ucode_suspend(struct drm_i915_private *i915); void intel_dmc_ucode_resume(struct drm_i915_private *i915); diff --git a/drivers/gpu/drm/i915/display/intel_dmc_regs.h b/drivers/gpu/drm/i915/display/intel_dmc_regs.h index 5e5e41644ddf..cf10094acae3 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc_regs.h +++ b/drivers/gpu/drm/i915/display/intel_dmc_regs.h @@ -11,6 +11,16 @@ #define DMC_PROGRAM(addr, i) _MMIO((addr) + (i) * 4) #define DMC_SSP_BASE_ADDR_GEN9 0x00002FC0 +#define _PIPEDMC_CONTROL_A 0x45250 +#define _PIPEDMC_CONTROL_B 0x45254 +#define PIPEDMC_CONTROL(pipe) _MMIO_PIPE(pipe, \ + _PIPEDMC_CONTROL_A, \ + _PIPEDMC_CONTROL_B) +#define PIPEDMC_ENABLE REG_BIT(0) + +#define MTL_PIPEDMC_CONTROL _MMIO(0x45250) +#define PIPEDMC_ENABLE_MTL(pipe) REG_BIT(((pipe) - PIPE_A) * 4) + #define _ADLP_PIPEDMC_REG_MMIO_BASE_A 0x5f000 #define _TGL_PIPEDMC_REG_MMIO_BASE_A 0x92000 diff --git a/drivers/gpu/drm/i915/display/intel_modeset_setup.c b/drivers/gpu/drm/i915/display/intel_modeset_setup.c index 96395bfbd41d..52cdbd4fc2fa 100644 --- a/drivers/gpu/drm/i915/display/intel_modeset_setup.c +++ b/drivers/gpu/drm/i915/display/intel_modeset_setup.c @@ -698,8 +698,10 @@ void intel_modeset_setup_hw_state(struct drm_i915_private *i915, drm_crtc_vblank_reset(&crtc->base); - if (crtc_state->hw.active) + if (crtc_state->hw.active) { + intel_dmc_enable_pipe(i915, crtc->pipe); intel_crtc_vblank_on(crtc_state); + } } intel_fbc_sanitize(i915); From 21e18febba163b816e66f85f97b04732fdb9e3f9 Mon Sep 17 00:00:00 2001 From: Luca Coelho Date: Fri, 13 Jan 2023 13:39:05 +0200 Subject: [PATCH 37/67] drm/i915: update src and dst scaler limits for display ver 12 and 13 The bspec has been updated and now display versions 12 and 13 support source width up to 5120 pixels, source height up to 8192 lines, destination width up to 8192 and destination height up to 8192. Update the code accordingly. BSpec: 50441 Reviewed-by: Ankit Nautiyal Signed-off-by: Luca Coelho Signed-off-by: Stanislav Lisovskiy Link: https://patchwork.freedesktop.org/patch/msgid/20230113113905.130405-1-luciano.coelho@intel.com --- drivers/gpu/drm/i915/display/skl_scaler.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/skl_scaler.c b/drivers/gpu/drm/i915/display/skl_scaler.c index 01e881293612..473d53610b92 100644 --- a/drivers/gpu/drm/i915/display/skl_scaler.c +++ b/drivers/gpu/drm/i915/display/skl_scaler.c @@ -87,6 +87,10 @@ static u16 skl_scaler_calc_phase(int sub, int scale, bool chroma_cosited) #define ICL_MAX_SRC_H 4096 #define ICL_MAX_DST_W 5120 #define ICL_MAX_DST_H 4096 +#define TGL_MAX_SRC_W 5120 +#define TGL_MAX_SRC_H 8192 +#define TGL_MAX_DST_W 8192 +#define TGL_MAX_DST_H 8192 #define MTL_MAX_SRC_W 4096 #define MTL_MAX_SRC_H 8192 #define MTL_MAX_DST_W 8192 @@ -173,11 +177,16 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach, max_src_h = SKL_MAX_SRC_H; max_dst_w = SKL_MAX_DST_W; max_dst_h = SKL_MAX_DST_H; - } else if (DISPLAY_VER(dev_priv) < 14) { + } else if (DISPLAY_VER(dev_priv) < 12) { max_src_w = ICL_MAX_SRC_W; max_src_h = ICL_MAX_SRC_H; max_dst_w = ICL_MAX_DST_W; max_dst_h = ICL_MAX_DST_H; + } else if (DISPLAY_VER(dev_priv) < 14) { + max_src_w = TGL_MAX_SRC_W; + max_src_h = TGL_MAX_SRC_H; + max_dst_w = TGL_MAX_DST_W; + max_dst_h = TGL_MAX_DST_H; } else { max_src_w = MTL_MAX_SRC_W; max_src_h = MTL_MAX_SRC_H; From ff6f11afd792b59563b12b382d496279d63a55c0 Mon Sep 17 00:00:00 2001 From: Gustavo Sousa Date: Mon, 23 Jan 2023 15:20:20 -0300 Subject: [PATCH 38/67] drm/i915/dmc: Prepare to use unversioned paths New DMC releases in linux-firmware will stop using version number in blob filenames. This new convention provides the following benefits: 1. It simplifies code maintenance, as new DMC releases for a platform using the new convention will always use the same filename for the blob. 2. It allows DMC to be loaded even if the target system does not have the most recent firmware installed. Prepare the driver by: - Using the new convention for DMC_PATH() and renaming the currently used one to make it clear it is for the legacy scheme. - Implementing a fallback mechanism for future transitions from versioned to unversioned paths so that we do not cause a regression for systems not having the most up-to-date linux-firmware files. v2: - Keep using request_firmware() instead of firmware_request_nowarn(). (Jani) v3: - Keep current DMC paths instead of directly using unversioned ones, so that we do not disturb initrd generation. (Lucas, Rodrigo) Signed-off-by: Gustavo Sousa Cc: Jani Nikula Cc: Lucas De Marchi Cc: Rodrigo Vivi Reviewed-by: Rodrigo Vivi Signed-off-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20230123182021.31239-2-gustavo.sousa@intel.com --- drivers/gpu/drm/i915/display/intel_dmc.c | 62 ++++++++++++++++++------ 1 file changed, 46 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dmc.c b/drivers/gpu/drm/i915/display/intel_dmc.c index 370c91d323fc..2464796c769d 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc.c +++ b/drivers/gpu/drm/i915/display/intel_dmc.c @@ -42,51 +42,59 @@ #define DMC_VERSION_MAJOR(version) ((version) >> 16) #define DMC_VERSION_MINOR(version) ((version) & 0xffff) -#define DMC_PATH(platform, major, minor) \ - "i915/" \ - __stringify(platform) "_dmc_ver" \ - __stringify(major) "_" \ +#define DMC_PATH(platform) \ + "i915/" __stringify(platform) "_dmc.bin" + +/* + * New DMC additions should not use this. This is used solely to remain + * compatible with systems that have not yet updated DMC blobs to use + * unversioned file names. + */ +#define DMC_LEGACY_PATH(platform, major, minor) \ + "i915/" \ + __stringify(platform) "_dmc_ver" \ + __stringify(major) "_" \ __stringify(minor) ".bin" #define DISPLAY_VER13_DMC_MAX_FW_SIZE 0x20000 #define DISPLAY_VER12_DMC_MAX_FW_SIZE ICL_DMC_MAX_FW_SIZE -#define DG2_DMC_PATH DMC_PATH(dg2, 2, 08) +#define DG2_DMC_PATH DMC_LEGACY_PATH(dg2, 2, 08) MODULE_FIRMWARE(DG2_DMC_PATH); -#define ADLP_DMC_PATH DMC_PATH(adlp, 2, 16) +#define ADLP_DMC_PATH DMC_LEGACY_PATH(adlp, 2, 16) MODULE_FIRMWARE(ADLP_DMC_PATH); -#define ADLS_DMC_PATH DMC_PATH(adls, 2, 01) +#define ADLS_DMC_PATH DMC_LEGACY_PATH(adls, 2, 01) MODULE_FIRMWARE(ADLS_DMC_PATH); -#define DG1_DMC_PATH DMC_PATH(dg1, 2, 02) +#define DG1_DMC_PATH DMC_LEGACY_PATH(dg1, 2, 02) MODULE_FIRMWARE(DG1_DMC_PATH); -#define RKL_DMC_PATH DMC_PATH(rkl, 2, 03) +#define RKL_DMC_PATH DMC_LEGACY_PATH(rkl, 2, 03) MODULE_FIRMWARE(RKL_DMC_PATH); -#define TGL_DMC_PATH DMC_PATH(tgl, 2, 12) +#define TGL_DMC_PATH DMC_LEGACY_PATH(tgl, 2, 12) MODULE_FIRMWARE(TGL_DMC_PATH); -#define ICL_DMC_PATH DMC_PATH(icl, 1, 09) +#define ICL_DMC_PATH DMC_LEGACY_PATH(icl, 1, 09) #define ICL_DMC_MAX_FW_SIZE 0x6000 MODULE_FIRMWARE(ICL_DMC_PATH); -#define GLK_DMC_PATH DMC_PATH(glk, 1, 04) +#define GLK_DMC_PATH DMC_LEGACY_PATH(glk, 1, 04) #define GLK_DMC_MAX_FW_SIZE 0x4000 MODULE_FIRMWARE(GLK_DMC_PATH); -#define KBL_DMC_PATH DMC_PATH(kbl, 1, 04) +#define KBL_DMC_PATH DMC_LEGACY_PATH(kbl, 1, 04) #define KBL_DMC_MAX_FW_SIZE BXT_DMC_MAX_FW_SIZE MODULE_FIRMWARE(KBL_DMC_PATH); -#define SKL_DMC_PATH DMC_PATH(skl, 1, 27) +#define SKL_DMC_PATH DMC_LEGACY_PATH(skl, 1, 27) #define SKL_DMC_MAX_FW_SIZE BXT_DMC_MAX_FW_SIZE MODULE_FIRMWARE(SKL_DMC_PATH); -#define BXT_DMC_PATH DMC_PATH(bxt, 1, 07) +#define BXT_DMC_PATH DMC_LEGACY_PATH(bxt, 1, 07) #define BXT_DMC_MAX_FW_SIZE 0x3000 MODULE_FIRMWARE(BXT_DMC_PATH); @@ -845,16 +853,38 @@ static void intel_dmc_runtime_pm_put(struct drm_i915_private *dev_priv) intel_display_power_put(dev_priv, POWER_DOMAIN_INIT, wakeref); } +static const char *dmc_fallback_path(struct drm_i915_private *i915) +{ + /* No fallback paths for now. */ + return NULL; +} + static void dmc_load_work_fn(struct work_struct *work) { struct drm_i915_private *dev_priv; struct intel_dmc *dmc; const struct firmware *fw = NULL; + const char *fallback_path; + int err; dev_priv = container_of(work, typeof(*dev_priv), display.dmc.work); dmc = &dev_priv->display.dmc; - request_firmware(&fw, dev_priv->display.dmc.fw_path, dev_priv->drm.dev); + err = request_firmware(&fw, dev_priv->display.dmc.fw_path, dev_priv->drm.dev); + + if (err == -ENOENT && !dev_priv->params.dmc_firmware_path) { + fallback_path = dmc_fallback_path(dev_priv); + if (fallback_path) { + drm_dbg_kms(&dev_priv->drm, + "%s not found, falling back to %s\n", + dmc->fw_path, + fallback_path); + err = request_firmware(&fw, fallback_path, dev_priv->drm.dev); + if (err == 0) + dev_priv->display.dmc.fw_path = fallback_path; + } + } + parse_dmc_fw(dev_priv, fw); if (intel_dmc_has_payload(dev_priv)) { From 81f66500f7c9e80c01bde8eb2cb78054051058e2 Mon Sep 17 00:00:00 2001 From: Gustavo Sousa Date: Mon, 23 Jan 2023 15:20:21 -0300 Subject: [PATCH 39/67] drm/i915/dmc: Use unversioned path for ADLP The new DMC release for ADLP (v2.18) in linux-firmware adopted the new convention of using unversioned filenames, so update the driver code for that new release. Keep the latest versioned path as fallback so we do not cause regressions. Signed-off-by: Gustavo Sousa Reviewed-by: Rodrigo Vivi Signed-off-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20230123182021.31239-3-gustavo.sousa@intel.com --- drivers/gpu/drm/i915/display/intel_dmc.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dmc.c b/drivers/gpu/drm/i915/display/intel_dmc.c index 2464796c769d..257aa2b7cf20 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc.c +++ b/drivers/gpu/drm/i915/display/intel_dmc.c @@ -63,8 +63,10 @@ #define DG2_DMC_PATH DMC_LEGACY_PATH(dg2, 2, 08) MODULE_FIRMWARE(DG2_DMC_PATH); -#define ADLP_DMC_PATH DMC_LEGACY_PATH(adlp, 2, 16) +#define ADLP_DMC_PATH DMC_PATH(adlp) +#define ADLP_DMC_FALLBACK_PATH DMC_LEGACY_PATH(adlp, 2, 16) MODULE_FIRMWARE(ADLP_DMC_PATH); +MODULE_FIRMWARE(ADLP_DMC_FALLBACK_PATH); #define ADLS_DMC_PATH DMC_LEGACY_PATH(adls, 2, 01) MODULE_FIRMWARE(ADLS_DMC_PATH); @@ -855,7 +857,9 @@ static void intel_dmc_runtime_pm_put(struct drm_i915_private *dev_priv) static const char *dmc_fallback_path(struct drm_i915_private *i915) { - /* No fallback paths for now. */ + if (IS_ALDERLAKE_P(i915)) + return ADLP_DMC_FALLBACK_PATH; + return NULL; } From 343cb0f9234ec5f5d86e47c33d2c6fa649cef2fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 24 Jan 2023 16:46:16 +0200 Subject: [PATCH 40/67] drm/i915/audio: Don't program the hardware ELD buffer on ilk+ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since we use the audio component to transfer the ELD to the audio driver on ilk+ platforms there is no point in even programming the hardware ELD buffer. Stop doing so. The one slight caveat here is that this is not strictly legal according to the HDA spec. PD=1;ELD=0 is only documented as an intermediate state during modeset. But if there is no hardware that depends on that then I guess we're fine. Or we could perhaps set ELD=1 without actually programming the buffer? Note that the bspec sequence of PD=0;ELD=0 -> PD=1;ELD=0 -> PD=1;ELD=1 is also not strictly correct according to the HDA spec, as the only documented transition from PD=0;ELD=0 is straight to PD=1;ELD=1. But that is not even possible on these platforms as the bits live in different registers. Cc: Chaitanya Kumar Borah Cc: Takashi Iwai Reviewed-by: Kai Vehmanen Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20230124144628.4649-2-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_audio.c | 39 +++------------------- 1 file changed, 4 insertions(+), 35 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_audio.c b/drivers/gpu/drm/i915/display/intel_audio.c index 626c47e96a6d..fb8a960a4b3d 100644 --- a/drivers/gpu/drm/i915/display/intel_audio.c +++ b/drivers/gpu/drm/i915/display/intel_audio.c @@ -691,20 +691,6 @@ static void ilk_audio_regs_init(struct drm_i915_private *i915, } } -/* ELD buffer size in dwords */ -static int ilk_eld_buffer_size(struct drm_i915_private *i915, - enum pipe pipe) -{ - struct ilk_audio_regs regs; - u32 tmp; - - ilk_audio_regs_init(i915, pipe, ®s); - - tmp = intel_de_read(i915, regs.aud_cntl_st); - - return REG_FIELD_GET(IBX_ELD_BUFFER_SIZE_MASK, tmp); -} - static void ilk_audio_codec_disable(struct intel_encoder *encoder, const struct intel_crtc_state *old_crtc_state, const struct drm_connector_state *old_conn_state) @@ -747,11 +733,8 @@ static void ilk_audio_codec_enable(struct intel_encoder *encoder, { struct drm_i915_private *i915 = to_i915(encoder->base.dev); struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct drm_connector *connector = conn_state->connector; - const u32 *eld = (const u32 *)connector->eld; enum port port = encoder->port; enum pipe pipe = crtc->pipe; - int eld_buffer_size, len, i; struct ilk_audio_regs regs; if (drm_WARN_ON(&i915->drm, port == PORT_A)) @@ -767,24 +750,10 @@ static void ilk_audio_codec_enable(struct intel_encoder *encoder, intel_de_rmw(i915, regs.aud_cntrl_st2, IBX_ELD_VALID(port), 0); - /* Reset ELD address */ - intel_de_rmw(i915, regs.aud_cntl_st, - IBX_ELD_ADDRESS_MASK, 0); - - eld_buffer_size = ilk_eld_buffer_size(i915, pipe); - len = min(drm_eld_size(connector->eld) / 4, eld_buffer_size); - - for (i = 0; i < len; i++) - intel_de_write(i915, regs.hdmiw_hdmiedid, eld[i]); - for (; i < eld_buffer_size; i++) - intel_de_write(i915, regs.hdmiw_hdmiedid, 0); - - drm_WARN_ON(&i915->drm, - (intel_de_read(i915, regs.aud_cntl_st) & IBX_ELD_ADDRESS_MASK) != 0); - - /* ELD valid */ - intel_de_rmw(i915, regs.aud_cntrl_st2, - 0, IBX_ELD_VALID(port)); + /* + * The audio componenent is used to convey the ELD + * instead using of the hardware ELD buffer. + */ /* Enable timestamps */ intel_de_rmw(i915, regs.aud_config, From 68470541e630bb43f047cd372cc49489c0e82084 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 24 Jan 2023 16:46:17 +0200 Subject: [PATCH 41/67] drm/i915/audio: Don't program the hardware ELD buffer on hsw+ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since we use the audio component to transfer the ELD to the audio driver on hsw+ platforms there is no point in even programming the hardware ELD buffer. Stop doing so. The one slight caveat here is that this is not strictly legal according to the HDA spec. PD=1;ELD=0 is only documented as an intermediate state during modeset. But if there is no hardware that depends on that then I guess we're fine. Or we could perhaps set ELD=1 without actually programming the buffer? Note that the bspec sequence of PD=0;ELD=0 -> PD=1;ELD=0 -> PD=1;ELD=1 is also not strictly correct according to the HDA spec, as the only documented transition from PD=0;ELD=0 is straight to PD=1;ELD=1. Additionally on hsw/bdw the hardware buffer is tied in with the dedicated display HDA controller's power state, so currently we mostly fail at proramming the buffer anyway. When the HDA side is not sufficiently powered up the ELD address bits get stuck and the ELD data register accesses go nowhere. Cc: Chaitanya Kumar Borah Cc: Takashi Iwai References: https://lore.kernel.org/intel-gfx/20221012104936.30911-1-ville.syrjala@linux.intel.com/ Reviewed-by: Kai Vehmanen Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20230124144628.4649-3-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_audio.c | 37 +++------------------- 1 file changed, 4 insertions(+), 33 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_audio.c b/drivers/gpu/drm/i915/display/intel_audio.c index fb8a960a4b3d..afebae999c50 100644 --- a/drivers/gpu/drm/i915/display/intel_audio.c +++ b/drivers/gpu/drm/i915/display/intel_audio.c @@ -459,17 +459,6 @@ hsw_audio_config_update(struct intel_encoder *encoder, hsw_hdmi_audio_config_update(encoder, crtc_state); } -/* ELD buffer size in dwords */ -static int hsw_eld_buffer_size(struct drm_i915_private *i915, - enum transcoder cpu_transcoder) -{ - u32 tmp; - - tmp = intel_de_read(i915, HSW_AUD_DIP_ELD_CTRL(cpu_transcoder)); - - return REG_FIELD_GET(IBX_ELD_BUFFER_SIZE_MASK, tmp); -} - static void hsw_audio_codec_disable(struct intel_encoder *encoder, const struct intel_crtc_state *old_crtc_state, const struct drm_connector_state *old_conn_state) @@ -618,10 +607,7 @@ static void hsw_audio_codec_enable(struct intel_encoder *encoder, { struct drm_i915_private *i915 = to_i915(encoder->base.dev); struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct drm_connector *connector = conn_state->connector; enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; - const u32 *eld = (const u32 *)connector->eld; - int eld_buffer_size, len, i; mutex_lock(&i915->display.audio.mutex); @@ -639,25 +625,10 @@ static void hsw_audio_codec_enable(struct intel_encoder *encoder, intel_de_rmw(i915, HSW_AUD_PIN_ELD_CP_VLD, AUDIO_ELD_VALID(cpu_transcoder), 0); - /* Reset ELD address */ - intel_de_rmw(i915, HSW_AUD_DIP_ELD_CTRL(cpu_transcoder), - IBX_ELD_ADDRESS_MASK, 0); - - eld_buffer_size = hsw_eld_buffer_size(i915, cpu_transcoder); - len = min(drm_eld_size(connector->eld) / 4, eld_buffer_size); - - for (i = 0; i < len; i++) - intel_de_write(i915, HSW_AUD_EDID_DATA(cpu_transcoder), eld[i]); - for (; i < eld_buffer_size; i++) - intel_de_write(i915, HSW_AUD_EDID_DATA(cpu_transcoder), 0); - - drm_WARN_ON(&i915->drm, - (intel_de_read(i915, HSW_AUD_DIP_ELD_CTRL(cpu_transcoder)) & - IBX_ELD_ADDRESS_MASK) != 0); - - /* ELD valid */ - intel_de_rmw(i915, HSW_AUD_PIN_ELD_CP_VLD, - 0, AUDIO_ELD_VALID(cpu_transcoder)); + /* + * The audio componenent is used to convey the ELD + * instead using of the hardware ELD buffer. + */ /* Enable timestamps */ hsw_audio_config_update(encoder, crtc_state); From c7104c382b10b9ea020ee6bca8ab9644770925a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 24 Jan 2023 16:46:18 +0200 Subject: [PATCH 42/67] drm/i915/audio: Introduce a struct for the acomp audio state MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently we're spreading the stashed state for use of the audio component hooks all over the place. Start collecting it up into a single spot. Cc: Chaitanya Kumar Borah Cc: Takashi Iwai Reviewed-by: Kai Vehmanen Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20230124144628.4649-4-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_audio.c | 106 ++++++++++-------- .../gpu/drm/i915/display/intel_display_core.h | 9 +- .../drm/i915/display/intel_display_types.h | 2 - 3 files changed, 65 insertions(+), 52 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_audio.c b/drivers/gpu/drm/i915/display/intel_audio.c index afebae999c50..f4cfb7c3a7ca 100644 --- a/drivers/gpu/drm/i915/display/intel_audio.c +++ b/drivers/gpu/drm/i915/display/intel_audio.c @@ -765,27 +765,29 @@ void intel_audio_codec_enable(struct intel_encoder *encoder, struct drm_i915_private *i915 = to_i915(encoder->base.dev); struct i915_audio_component *acomp = i915->display.audio.component; struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct drm_connector *connector = conn_state->connector; + struct intel_connector *connector = to_intel_connector(conn_state->connector); const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; + struct intel_audio_state *audio_state; enum port port = encoder->port; enum pipe pipe = crtc->pipe; if (!crtc_state->has_audio) return; - drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s][ENCODER:%d:%s] Enable audio codec on pipe %c, %u bytes ELD\n", - connector->base.id, connector->name, + drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s][ENCODER:%d:%s] Enable audio codec on [CRTC:%d:%s], %u bytes ELD\n", + connector->base.base.id, connector->base.name, encoder->base.base.id, encoder->base.name, - pipe_name(pipe), drm_eld_size(connector->eld)); + crtc->base.base.id, crtc->base.name, + drm_eld_size(connector->base.eld)); /* FIXME precompute the ELD in .compute_config() */ - if (!connector->eld[0]) + if (!connector->base.eld[0]) drm_dbg_kms(&i915->drm, "Bogus ELD on [CONNECTOR:%d:%s]\n", - connector->base.id, connector->name); + connector->base.base.id, connector->base.name); - connector->eld[6] = drm_av_sync_delay(connector, adjusted_mode) / 2; + connector->base.eld[6] = drm_av_sync_delay(&connector->base, adjusted_mode) / 2; if (i915->display.funcs.audio) i915->display.funcs.audio->audio_codec_enable(encoder, @@ -793,10 +795,12 @@ void intel_audio_codec_enable(struct intel_encoder *encoder, conn_state); mutex_lock(&i915->display.audio.mutex); - encoder->audio_connector = connector; - /* referred in audio callbacks */ - i915->display.audio.encoder_map[pipe] = encoder; + audio_state = &i915->display.audio.state[pipe]; + + audio_state->encoder = encoder; + audio_state->connector = connector; + mutex_unlock(&i915->display.audio.mutex); if (acomp && acomp->base.audio_ops && @@ -808,7 +812,7 @@ void intel_audio_codec_enable(struct intel_encoder *encoder, (int)port, (int)pipe); } - intel_lpe_audio_notify(i915, pipe, port, connector->eld, + intel_lpe_audio_notify(i915, pipe, port, connector->base.eld, crtc_state->port_clock, intel_crtc_has_dp_encoder(crtc_state)); } @@ -829,16 +833,18 @@ void intel_audio_codec_disable(struct intel_encoder *encoder, struct drm_i915_private *i915 = to_i915(encoder->base.dev); struct i915_audio_component *acomp = i915->display.audio.component; struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); - struct drm_connector *connector = old_conn_state->connector; + struct intel_connector *connector = to_intel_connector(old_conn_state->connector); + struct intel_audio_state *audio_state; enum port port = encoder->port; enum pipe pipe = crtc->pipe; if (!old_crtc_state->has_audio) return; - drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s][ENCODER:%d:%s] Disable audio codec on pipe %c\n", - connector->base.id, connector->name, - encoder->base.base.id, encoder->base.name, pipe_name(pipe)); + drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s][ENCODER:%d:%s] Disable audio codec on [CRTC:%d:%s]\n", + connector->base.base.id, connector->base.name, + encoder->base.base.id, encoder->base.name, + crtc->base.base.id, crtc->base.name); if (i915->display.funcs.audio) i915->display.funcs.audio->audio_codec_disable(encoder, @@ -846,8 +852,12 @@ void intel_audio_codec_disable(struct intel_encoder *encoder, old_conn_state); mutex_lock(&i915->display.audio.mutex); - encoder->audio_connector = NULL; - i915->display.audio.encoder_map[pipe] = NULL; + + audio_state = &i915->display.audio.state[pipe]; + + audio_state->encoder = NULL; + audio_state->connector = NULL; + mutex_unlock(&i915->display.audio.mutex); if (acomp && acomp->base.audio_ops && @@ -1068,35 +1078,32 @@ static int i915_audio_component_get_cdclk_freq(struct device *kdev) } /* - * get the intel_encoder according to the parameter port and pipe - * intel_encoder is saved by the index of pipe - * MST & (pipe >= 0): return the audio.encoder_map[pipe], + * get the intel audio state according to the parameter port and pipe + * MST & (pipe >= 0): return the audio.state[pipe].encoder], * when port is matched * MST & (pipe < 0): this is invalid * Non-MST & (pipe >= 0): only pipe = 0 (the first device entry) * will get the right intel_encoder with port matched * Non-MST & (pipe < 0): get the right intel_encoder with port matched */ -static struct intel_encoder *get_saved_enc(struct drm_i915_private *i915, - int port, int pipe) +static struct intel_audio_state *find_audio_state(struct drm_i915_private *i915, + int port, int pipe) { /* MST */ if (pipe >= 0) { + struct intel_audio_state *audio_state; struct intel_encoder *encoder; if (drm_WARN_ON(&i915->drm, - pipe >= ARRAY_SIZE(i915->display.audio.encoder_map))) + pipe >= ARRAY_SIZE(i915->display.audio.state))) return NULL; - encoder = i915->display.audio.encoder_map[pipe]; - /* - * when bootup, audio driver may not know it is - * MST or not. So it will poll all the port & pipe - * combinations - */ + audio_state = &i915->display.audio.state[pipe]; + encoder = audio_state->encoder; + if (encoder && encoder->port == port && encoder->type == INTEL_OUTPUT_DP_MST) - return encoder; + return audio_state; } /* Non-MST */ @@ -1104,13 +1111,15 @@ static struct intel_encoder *get_saved_enc(struct drm_i915_private *i915, return NULL; for_each_pipe(i915, pipe) { + struct intel_audio_state *audio_state; struct intel_encoder *encoder; - encoder = i915->display.audio.encoder_map[pipe]; + audio_state = &i915->display.audio.state[pipe]; + encoder = audio_state->encoder; if (encoder && encoder->port == port && encoder->type != INTEL_OUTPUT_DP_MST) - return encoder; + return audio_state; } return NULL; @@ -1121,6 +1130,7 @@ static int i915_audio_component_sync_audio_rate(struct device *kdev, int port, { struct drm_i915_private *i915 = kdev_to_i915(kdev); struct i915_audio_component *acomp = i915->display.audio.component; + const struct intel_audio_state *audio_state; struct intel_encoder *encoder; struct intel_crtc *crtc; unsigned long cookie; @@ -1132,20 +1142,22 @@ static int i915_audio_component_sync_audio_rate(struct device *kdev, int port, cookie = i915_audio_component_get_power(kdev); mutex_lock(&i915->display.audio.mutex); - /* 1. get the pipe */ - encoder = get_saved_enc(i915, port, pipe); - if (!encoder || !encoder->base.crtc) { - drm_dbg_kms(&i915->drm, "Not valid for port %c\n", - port_name(port)); + audio_state = find_audio_state(i915, port, pipe); + if (!audio_state) { + drm_dbg_kms(&i915->drm, "Not valid for port %c\n", port_name(port)); err = -ENODEV; goto unlock; } + encoder = audio_state->encoder; + + /* FIXME stop using the legacy crtc pointer */ crtc = to_intel_crtc(encoder->base.crtc); /* port must be valid now, otherwise the pipe will be invalid */ acomp->aud_sample_rate[port] = rate; + /* FIXME get rid of the crtc->config stuff */ hsw_audio_config_update(encoder, crtc->config); unlock: @@ -1159,24 +1171,22 @@ static int i915_audio_component_get_eld(struct device *kdev, int port, unsigned char *buf, int max_bytes) { struct drm_i915_private *i915 = kdev_to_i915(kdev); - struct intel_encoder *intel_encoder; - const u8 *eld; - int ret = -EINVAL; + const struct intel_audio_state *audio_state; + int ret = 0; mutex_lock(&i915->display.audio.mutex); - intel_encoder = get_saved_enc(i915, port, pipe); - if (!intel_encoder) { - drm_dbg_kms(&i915->drm, "Not valid for port %c\n", - port_name(port)); + audio_state = find_audio_state(i915, port, pipe); + if (!audio_state) { + drm_dbg_kms(&i915->drm, "Not valid for port %c\n", port_name(port)); mutex_unlock(&i915->display.audio.mutex); - return ret; + return -EINVAL; } - ret = 0; - *enabled = intel_encoder->audio_connector != NULL; + *enabled = audio_state->connector != NULL; if (*enabled) { - eld = intel_encoder->audio_connector->eld; + const u8 *eld = audio_state->connector->base.eld; + ret = drm_eld_size(eld); memcpy(buf, eld, min(max_bytes, ret)); } diff --git a/drivers/gpu/drm/i915/display/intel_display_core.h b/drivers/gpu/drm/i915/display/intel_display_core.h index 24c792d44b8f..0e4c42af25a6 100644 --- a/drivers/gpu/drm/i915/display/intel_display_core.h +++ b/drivers/gpu/drm/i915/display/intel_display_core.h @@ -87,6 +87,11 @@ struct intel_wm_funcs { int (*compute_global_watermarks)(struct intel_atomic_state *state); }; +struct intel_audio_state { + struct intel_encoder *encoder; + struct intel_connector *connector; +}; + struct intel_audio { /* hda/i915 audio component */ struct i915_audio_component *component; @@ -96,8 +101,8 @@ struct intel_audio { int power_refcount; u32 freq_cntrl; - /* Used to save the pipe-to-encoder mapping for audio */ - struct intel_encoder *encoder_map[I915_MAX_PIPES]; + /* current audio state for the audio component hooks */ + struct intel_audio_state state[I915_MAX_PIPES]; /* necessary resource sharing with HDMI LPE audio driver. */ struct { diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 32e8b2fc3cc6..a447a44db1eb 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -262,8 +262,6 @@ struct intel_encoder { enum hpd_pin hpd_pin; enum intel_display_power_domain power_domain; - /* for communication with audio component; protected by av_mutex */ - const struct drm_connector *audio_connector; /* VBT information for this encoder (may be NULL for older platforms) */ const struct intel_bios_encoder_data *devdata; From 5d986635e2969a7eba8a8b475744256d3fec6160 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 24 Jan 2023 16:46:19 +0200 Subject: [PATCH 43/67] drm/i915/audio: Precompute the ELD MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Stash the ELD into the crtc_state and precompute it. This gets rid of the ugly ELD mutation during intel_audio_codec_enable(), and opens the door for the state checker. v2: Make another copy for the acomp hooks (Chaitanya) Split out the bogus ELD handling change (Jani) Cc: Chaitanya Kumar Borah Cc: Takashi Iwai Reviewed-by: Jani Nikula #v1 Reviewed-by: Kai Vehmanen Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20230124144628.4649-5-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_audio.c | 50 ++++++++++++------- drivers/gpu/drm/i915/display/intel_audio.h | 5 ++ .../gpu/drm/i915/display/intel_display_core.h | 2 +- .../drm/i915/display/intel_display_types.h | 2 + drivers/gpu/drm/i915/display/intel_dp.c | 4 +- drivers/gpu/drm/i915/display/intel_hdmi.c | 4 +- 6 files changed, 45 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_audio.c b/drivers/gpu/drm/i915/display/intel_audio.c index f4cfb7c3a7ca..326e93768687 100644 --- a/drivers/gpu/drm/i915/display/intel_audio.c +++ b/drivers/gpu/drm/i915/display/intel_audio.c @@ -335,8 +335,7 @@ static void g4x_audio_codec_enable(struct intel_encoder *encoder, { struct drm_i915_private *i915 = to_i915(encoder->base.dev); struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct drm_connector *connector = conn_state->connector; - const u32 *eld = (const u32 *)connector->eld; + const u32 *eld = (const u32 *)crtc_state->eld; int eld_buffer_size, len, i; intel_crtc_wait_for_next_vblank(crtc); @@ -345,7 +344,7 @@ static void g4x_audio_codec_enable(struct intel_encoder *encoder, G4X_ELD_VALID | G4X_ELD_ADDRESS_MASK, 0); eld_buffer_size = g4x_eld_buffer_size(i915); - len = min(drm_eld_size(connector->eld) / 4, eld_buffer_size); + len = min(drm_eld_size(crtc_state->eld) / 4, eld_buffer_size); for (i = 0; i < len; i++) intel_de_write(i915, G4X_HDMIW_HDMIEDID, eld[i]); @@ -749,6 +748,28 @@ void intel_audio_sdp_split_update(struct intel_encoder *encoder, crtc_state->sdp_split_enable ? AUD_ENABLE_SDP_SPLIT : 0); } +bool intel_audio_compute_config(struct intel_encoder *encoder, + struct intel_crtc_state *crtc_state, + struct drm_connector_state *conn_state) +{ + struct drm_i915_private *i915 = to_i915(encoder->base.dev); + struct drm_connector *connector = conn_state->connector; + const struct drm_display_mode *adjusted_mode = + &crtc_state->hw.adjusted_mode; + + if (!connector->eld[0]) + drm_dbg_kms(&i915->drm, + "Bogus ELD on [CONNECTOR:%d:%s]\n", + connector->base.id, connector->name); + + BUILD_BUG_ON(sizeof(crtc_state->eld) != sizeof(connector->eld)); + memcpy(crtc_state->eld, connector->eld, sizeof(crtc_state->eld)); + + crtc_state->eld[6] = drm_av_sync_delay(connector, adjusted_mode) / 2; + + return true; +} + /** * intel_audio_codec_enable - Enable the audio codec for HD audio * @encoder: encoder on which to enable audio @@ -766,8 +787,6 @@ void intel_audio_codec_enable(struct intel_encoder *encoder, struct i915_audio_component *acomp = i915->display.audio.component; struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct intel_connector *connector = to_intel_connector(conn_state->connector); - const struct drm_display_mode *adjusted_mode = - &crtc_state->hw.adjusted_mode; struct intel_audio_state *audio_state; enum port port = encoder->port; enum pipe pipe = crtc->pipe; @@ -779,15 +798,7 @@ void intel_audio_codec_enable(struct intel_encoder *encoder, connector->base.base.id, connector->base.name, encoder->base.base.id, encoder->base.name, crtc->base.base.id, crtc->base.name, - drm_eld_size(connector->base.eld)); - - /* FIXME precompute the ELD in .compute_config() */ - if (!connector->base.eld[0]) - drm_dbg_kms(&i915->drm, - "Bogus ELD on [CONNECTOR:%d:%s]\n", - connector->base.base.id, connector->base.name); - - connector->base.eld[6] = drm_av_sync_delay(&connector->base, adjusted_mode) / 2; + drm_eld_size(crtc_state->eld)); if (i915->display.funcs.audio) i915->display.funcs.audio->audio_codec_enable(encoder, @@ -799,7 +810,8 @@ void intel_audio_codec_enable(struct intel_encoder *encoder, audio_state = &i915->display.audio.state[pipe]; audio_state->encoder = encoder; - audio_state->connector = connector; + BUILD_BUG_ON(sizeof(audio_state->eld) != sizeof(crtc_state->eld)); + memcpy(audio_state->eld, crtc_state->eld, sizeof(audio_state->eld)); mutex_unlock(&i915->display.audio.mutex); @@ -812,7 +824,7 @@ void intel_audio_codec_enable(struct intel_encoder *encoder, (int)port, (int)pipe); } - intel_lpe_audio_notify(i915, pipe, port, connector->base.eld, + intel_lpe_audio_notify(i915, pipe, port, crtc_state->eld, crtc_state->port_clock, intel_crtc_has_dp_encoder(crtc_state)); } @@ -856,7 +868,7 @@ void intel_audio_codec_disable(struct intel_encoder *encoder, audio_state = &i915->display.audio.state[pipe]; audio_state->encoder = NULL; - audio_state->connector = NULL; + memset(audio_state->eld, 0, sizeof(audio_state->eld)); mutex_unlock(&i915->display.audio.mutex); @@ -1183,9 +1195,9 @@ static int i915_audio_component_get_eld(struct device *kdev, int port, return -EINVAL; } - *enabled = audio_state->connector != NULL; + *enabled = audio_state->encoder != NULL; if (*enabled) { - const u8 *eld = audio_state->connector->base.eld; + const u8 *eld = audio_state->eld; ret = drm_eld_size(eld); memcpy(buf, eld, min(max_bytes, ret)); diff --git a/drivers/gpu/drm/i915/display/intel_audio.h b/drivers/gpu/drm/i915/display/intel_audio.h index 1b87257c6a17..521c56338834 100644 --- a/drivers/gpu/drm/i915/display/intel_audio.h +++ b/drivers/gpu/drm/i915/display/intel_audio.h @@ -6,12 +6,17 @@ #ifndef __INTEL_AUDIO_H__ #define __INTEL_AUDIO_H__ +#include + struct drm_connector_state; struct drm_i915_private; struct intel_crtc_state; struct intel_encoder; void intel_audio_hooks_init(struct drm_i915_private *dev_priv); +bool intel_audio_compute_config(struct intel_encoder *encoder, + struct intel_crtc_state *crtc_state, + struct drm_connector_state *conn_state); void intel_audio_codec_enable(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state); diff --git a/drivers/gpu/drm/i915/display/intel_display_core.h b/drivers/gpu/drm/i915/display/intel_display_core.h index 0e4c42af25a6..7b3e00f3e6ee 100644 --- a/drivers/gpu/drm/i915/display/intel_display_core.h +++ b/drivers/gpu/drm/i915/display/intel_display_core.h @@ -89,7 +89,7 @@ struct intel_wm_funcs { struct intel_audio_state { struct intel_encoder *encoder; - struct intel_connector *connector; + u8 eld[MAX_ELD_BYTES]; }; struct intel_audio { diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index a447a44db1eb..8173af26951b 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -1259,6 +1259,8 @@ struct intel_crtc_state { struct drm_dp_vsc_sdp vsc; } infoframes; + u8 eld[MAX_ELD_BYTES]; + /* HDMI scrambling status */ bool hdmi_scrambling; diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 80d95cec8f9d..478653e11f4d 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -2080,7 +2080,9 @@ intel_dp_compute_config(struct intel_encoder *encoder, if (HAS_PCH_SPLIT(dev_priv) && !HAS_DDI(dev_priv) && encoder->port != PORT_A) pipe_config->has_pch_encoder = true; - pipe_config->has_audio = intel_dp_has_audio(encoder, pipe_config, conn_state); + pipe_config->has_audio = + intel_dp_has_audio(encoder, pipe_config, conn_state) && + intel_audio_compute_config(encoder, pipe_config, conn_state); fixed_mode = intel_panel_fixed_mode(connector, adjusted_mode); if (intel_dp_is_edp(intel_dp) && fixed_mode) { diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c index 6a2ee342eab5..eb0dc376028a 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.c +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c @@ -44,6 +44,7 @@ #include "i915_drv.h" #include "i915_reg.h" #include "intel_atomic.h" +#include "intel_audio.h" #include "intel_connector.h" #include "intel_ddi.h" #include "intel_de.h" @@ -2271,7 +2272,8 @@ int intel_hdmi_compute_config(struct intel_encoder *encoder, pipe_config->pixel_multiplier = 2; pipe_config->has_audio = - intel_hdmi_has_audio(encoder, pipe_config, conn_state); + intel_hdmi_has_audio(encoder, pipe_config, conn_state) && + intel_audio_compute_config(encoder, pipe_config, conn_state); /* * Try to respect downstream TMDS clock limits first, if From d6393793848550e22cf7f4263f1a520b987d589a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 24 Jan 2023 16:46:20 +0200 Subject: [PATCH 44/67] drm/i915/audio: Don't enable audio with bogus ELD MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently we just print a debug message if the ELD is bogus. Maybe we should just not enable audio at all in that case? Cc: Chaitanya Kumar Borah Cc: Takashi Iwai Reviewed-by: Kai Vehmanen Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20230124144628.4649-6-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_audio.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_audio.c b/drivers/gpu/drm/i915/display/intel_audio.c index 326e93768687..5123bab17063 100644 --- a/drivers/gpu/drm/i915/display/intel_audio.c +++ b/drivers/gpu/drm/i915/display/intel_audio.c @@ -757,10 +757,12 @@ bool intel_audio_compute_config(struct intel_encoder *encoder, const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; - if (!connector->eld[0]) + if (!connector->eld[0]) { drm_dbg_kms(&i915->drm, "Bogus ELD on [CONNECTOR:%d:%s]\n", connector->base.id, connector->name); + return false; + } BUILD_BUG_ON(sizeof(crtc_state->eld) != sizeof(connector->eld)); memcpy(crtc_state->eld, connector->eld, sizeof(crtc_state->eld)); From 61a60df6271fae484f3871fcbd91ecdd89a3fff3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 24 Jan 2023 16:46:21 +0200 Subject: [PATCH 45/67] drm/i915/audio: Hardware ELD readout MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Read out the ELD from the hardware buffer, or from our stashed copy for the audio component, so that we can hook up the state checker to validate it. v2: Deal with the platforms using acomp Cc: Chaitanya Kumar Borah Cc: Takashi Iwai Reviewed-by: Jani Nikula #v1 Reviewed-by: Kai Vehmanen Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20230124144628.4649-7-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/g4x_dp.c | 2 + drivers/gpu/drm/i915/display/g4x_hdmi.c | 2 + drivers/gpu/drm/i915/display/intel_audio.c | 56 ++++++++++++++++++++++ drivers/gpu/drm/i915/display/intel_audio.h | 2 + drivers/gpu/drm/i915/display/intel_ddi.c | 2 + 5 files changed, 64 insertions(+) diff --git a/drivers/gpu/drm/i915/display/g4x_dp.c b/drivers/gpu/drm/i915/display/g4x_dp.c index 24ef36ec2d3d..fa754038d669 100644 --- a/drivers/gpu/drm/i915/display/g4x_dp.c +++ b/drivers/gpu/drm/i915/display/g4x_dp.c @@ -398,6 +398,8 @@ static void intel_dp_get_config(struct intel_encoder *encoder, if (intel_dp_is_edp(intel_dp)) intel_edp_fixup_vbt_bpp(encoder, pipe_config->pipe_bpp); + + intel_audio_codec_get_config(encoder, pipe_config); } static void diff --git a/drivers/gpu/drm/i915/display/g4x_hdmi.c b/drivers/gpu/drm/i915/display/g4x_hdmi.c index c3580d96765c..64c3b3990702 100644 --- a/drivers/gpu/drm/i915/display/g4x_hdmi.c +++ b/drivers/gpu/drm/i915/display/g4x_hdmi.c @@ -155,6 +155,8 @@ static void intel_hdmi_get_config(struct intel_encoder *encoder, intel_read_infoframe(encoder, pipe_config, HDMI_INFOFRAME_TYPE_VENDOR, &pipe_config->infoframes.hdmi); + + intel_audio_codec_get_config(encoder, pipe_config); } static void g4x_hdmi_enable_port(struct intel_encoder *encoder, diff --git a/drivers/gpu/drm/i915/display/intel_audio.c b/drivers/gpu/drm/i915/display/intel_audio.c index 5123bab17063..f7b460a9c76e 100644 --- a/drivers/gpu/drm/i915/display/intel_audio.c +++ b/drivers/gpu/drm/i915/display/intel_audio.c @@ -71,6 +71,8 @@ struct intel_audio_funcs { void (*audio_codec_disable)(struct intel_encoder *encoder, const struct intel_crtc_state *old_crtc_state, const struct drm_connector_state *old_conn_state); + void (*audio_codec_get_config)(struct intel_encoder *encoder, + struct intel_crtc_state *crtc_state); }; /* DP N/M table */ @@ -314,6 +316,27 @@ static int g4x_eld_buffer_size(struct drm_i915_private *i915) return REG_FIELD_GET(G4X_ELD_BUFFER_SIZE_MASK, tmp); } +static void g4x_audio_codec_get_config(struct intel_encoder *encoder, + struct intel_crtc_state *crtc_state) +{ + struct drm_i915_private *i915 = to_i915(encoder->base.dev); + u32 *eld = (u32 *)crtc_state->eld; + int eld_buffer_size, len, i; + u32 tmp; + + tmp = intel_de_read(i915, G4X_AUD_CNTL_ST); + if ((tmp & G4X_ELD_VALID) == 0) + return; + + intel_de_rmw(i915, G4X_AUD_CNTL_ST, G4X_ELD_ADDRESS_MASK, 0); + + eld_buffer_size = g4x_eld_buffer_size(i915); + len = min_t(int, sizeof(crtc_state->eld) / 4, eld_buffer_size); + + for (i = 0; i < len; i++) + eld[i] = intel_de_read(i915, G4X_HDMIW_HDMIEDID); +} + static void g4x_audio_codec_disable(struct intel_encoder *encoder, const struct intel_crtc_state *old_crtc_state, const struct drm_connector_state *old_conn_state) @@ -886,19 +909,52 @@ void intel_audio_codec_disable(struct intel_encoder *encoder, intel_lpe_audio_notify(i915, pipe, port, NULL, 0, false); } +static void intel_acomp_get_config(struct intel_encoder *encoder, + struct intel_crtc_state *crtc_state) +{ + struct drm_i915_private *i915 = to_i915(encoder->base.dev); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + struct intel_audio_state *audio_state; + enum pipe pipe = crtc->pipe; + + mutex_lock(&i915->display.audio.mutex); + + audio_state = &i915->display.audio.state[pipe]; + + if (audio_state->encoder) + memcpy(crtc_state->eld, audio_state->eld, sizeof(audio_state->eld)); + + mutex_unlock(&i915->display.audio.mutex); +} + +void intel_audio_codec_get_config(struct intel_encoder *encoder, + struct intel_crtc_state *crtc_state) +{ + struct drm_i915_private *i915 = to_i915(encoder->base.dev); + + if (!crtc_state->has_audio) + return; + + if (i915->display.funcs.audio) + i915->display.funcs.audio->audio_codec_get_config(encoder, crtc_state); +} + static const struct intel_audio_funcs g4x_audio_funcs = { .audio_codec_enable = g4x_audio_codec_enable, .audio_codec_disable = g4x_audio_codec_disable, + .audio_codec_get_config = g4x_audio_codec_get_config, }; static const struct intel_audio_funcs ilk_audio_funcs = { .audio_codec_enable = ilk_audio_codec_enable, .audio_codec_disable = ilk_audio_codec_disable, + .audio_codec_get_config = intel_acomp_get_config, }; static const struct intel_audio_funcs hsw_audio_funcs = { .audio_codec_enable = hsw_audio_codec_enable, .audio_codec_disable = hsw_audio_codec_disable, + .audio_codec_get_config = intel_acomp_get_config, }; /** diff --git a/drivers/gpu/drm/i915/display/intel_audio.h b/drivers/gpu/drm/i915/display/intel_audio.h index 521c56338834..07d034a981e9 100644 --- a/drivers/gpu/drm/i915/display/intel_audio.h +++ b/drivers/gpu/drm/i915/display/intel_audio.h @@ -23,6 +23,8 @@ void intel_audio_codec_enable(struct intel_encoder *encoder, void intel_audio_codec_disable(struct intel_encoder *encoder, const struct intel_crtc_state *old_crtc_state, const struct drm_connector_state *old_conn_state); +void intel_audio_codec_get_config(struct intel_encoder *encoder, + struct intel_crtc_state *crtc_state); void intel_audio_cdclk_change_pre(struct drm_i915_private *dev_priv); void intel_audio_cdclk_change_post(struct drm_i915_private *dev_priv); void intel_audio_init(struct drm_i915_private *dev_priv); diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 0034a43f56e5..254559abedfb 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -3496,6 +3496,8 @@ static void intel_ddi_get_config(struct intel_encoder *encoder, intel_read_dp_sdp(encoder, pipe_config, DP_SDP_VSC); intel_psr_get_config(encoder, pipe_config); + + intel_audio_codec_get_config(encoder, pipe_config); } void intel_ddi_get_clock(struct intel_encoder *encoder, From 8e10cd133de3dd4557eec0f4b9853f4e72b40eba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 24 Jan 2023 16:46:22 +0200 Subject: [PATCH 46/67] drm/i915/sdvo: Precompute the ELD MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the precomputed crtc_state->eld for audio setup on SDVO just like we do with native HDMI. Cc: Chaitanya Kumar Borah Cc: Takashi Iwai Reviewed-by: Jani Nikula Reviewed-by: Kai Vehmanen Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20230124144628.4649-8-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_sdvo.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_sdvo.c b/drivers/gpu/drm/i915/display/intel_sdvo.c index 21805c15d5eb..c0d7d5272eb8 100644 --- a/drivers/gpu/drm/i915/display/intel_sdvo.c +++ b/drivers/gpu/drm/i915/display/intel_sdvo.c @@ -39,6 +39,7 @@ #include "i915_drv.h" #include "i915_reg.h" #include "intel_atomic.h" +#include "intel_audio.h" #include "intel_connector.h" #include "intel_crtc.h" #include "intel_de.h" @@ -1378,7 +1379,9 @@ static int intel_sdvo_compute_config(struct intel_encoder *encoder, pipe_config->has_hdmi_sink = intel_has_hdmi_sink(intel_sdvo, conn_state); - pipe_config->has_audio = intel_sdvo_has_audio(encoder, pipe_config, conn_state); + pipe_config->has_audio = + intel_sdvo_has_audio(encoder, pipe_config, conn_state) && + intel_audio_compute_config(encoder, pipe_config, conn_state); pipe_config->limited_color_range = intel_sdvo_limited_color_range(encoder, pipe_config, @@ -1753,12 +1756,7 @@ static void intel_sdvo_enable_audio(struct intel_sdvo *intel_sdvo, const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state) { - const struct drm_display_mode *adjusted_mode = - &crtc_state->hw.adjusted_mode; - struct drm_connector *connector = conn_state->connector; - u8 *eld = connector->eld; - - eld[6] = drm_av_sync_delay(connector, adjusted_mode) / 2; + const u8 *eld = crtc_state->eld; intel_sdvo_set_audio_state(intel_sdvo, 0); From b9c92d78151f330524e90ac3ed21568b87c7cec3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 24 Jan 2023 16:46:23 +0200 Subject: [PATCH 47/67] drm/i915/sdvo: Only use "presence detect" for has_audio readout MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Align the SDVO audio code with the native HDMI/DP audio and use just the "presence detect" bit for the has_audio readout. The "ELD valid" bit will be used for ELD readout soon. Cc: Chaitanya Kumar Borah Cc: Takashi Iwai Reviewed-by: Kai Vehmanen Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20230124144628.4649-9-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_sdvo.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_sdvo.c b/drivers/gpu/drm/i915/display/intel_sdvo.c index c0d7d5272eb8..68e5c7be2135 100644 --- a/drivers/gpu/drm/i915/display/intel_sdvo.c +++ b/drivers/gpu/drm/i915/display/intel_sdvo.c @@ -1732,9 +1732,7 @@ static void intel_sdvo_get_config(struct intel_encoder *encoder, if (intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_AUDIO_STAT, &val, 1)) { - u8 mask = SDVO_AUDIO_ELD_VALID | SDVO_AUDIO_PRESENCE_DETECT; - - if ((val & mask) == mask) + if (val & SDVO_AUDIO_PRESENCE_DETECT) pipe_config->has_audio = true; } From 72715b54d4601dca6ebfdaee8a5d327d4441e95f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 24 Jan 2023 16:46:24 +0200 Subject: [PATCH 48/67] drm/i915/sdvo: Do ELD hardware readout MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Read out the ELD from the hw so the state checker can verify it. v2: Check the "ELD valid" bit separately v3: Fix ELD tx rate handling during readout Cc: Chaitanya Kumar Borah Cc: Takashi Iwai Reviewed-by: Jani Nikula #v1 Reviewed-by: Kai Vehmanen Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20230124144628.4649-10-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_sdvo.c | 27 ++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_sdvo.c b/drivers/gpu/drm/i915/display/intel_sdvo.c index 68e5c7be2135..c469ec3e6042 100644 --- a/drivers/gpu/drm/i915/display/intel_sdvo.c +++ b/drivers/gpu/drm/i915/display/intel_sdvo.c @@ -1069,7 +1069,8 @@ static ssize_t intel_sdvo_read_infoframe(struct intel_sdvo *intel_sdvo, &tx_rate, 1)) return -ENXIO; - if (tx_rate == SDVO_HBUF_TX_DISABLED) + /* TX_DISABLED doesn't mean disabled for ELD */ + if (if_index != SDVO_HBUF_INDEX_ELD && tx_rate == SDVO_HBUF_TX_DISABLED) return 0; if (!intel_sdvo_get_hbuf_size(intel_sdvo, &hbuf_size)) @@ -1186,6 +1187,28 @@ static void intel_sdvo_get_avi_infoframe(struct intel_sdvo *intel_sdvo, frame->any.type, HDMI_INFOFRAME_TYPE_AVI); } +static void intel_sdvo_get_eld(struct intel_sdvo *intel_sdvo, + struct intel_crtc_state *crtc_state) +{ + struct drm_i915_private *i915 = to_i915(intel_sdvo->base.base.dev); + ssize_t len; + u8 val; + + if (!crtc_state->has_audio) + return; + + if (!intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_AUDIO_STAT, &val, 1)) + return; + + if ((val & SDVO_AUDIO_ELD_VALID) == 0) + return; + + len = intel_sdvo_read_infoframe(intel_sdvo, SDVO_HBUF_INDEX_ELD, + crtc_state->eld, sizeof(crtc_state->eld)); + if (len < 0) + drm_dbg_kms(&i915->drm, "failed to read ELD\n"); +} + static bool intel_sdvo_set_tv_format(struct intel_sdvo *intel_sdvo, const struct drm_connector_state *conn_state) { @@ -1743,6 +1766,8 @@ static void intel_sdvo_get_config(struct intel_encoder *encoder, } intel_sdvo_get_avi_infoframe(intel_sdvo, pipe_config); + + intel_sdvo_get_eld(intel_sdvo, pipe_config); } static void intel_sdvo_disable_audio(struct intel_sdvo *intel_sdvo) From 8b5a2aedd298c433af9c89d338c949a4f703d5c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 24 Jan 2023 16:46:25 +0200 Subject: [PATCH 49/67] drm/i915/audio: Hook up ELD into the state checker MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Have the state checker validate the ELD. For now we'll just dump it out as a hex buffer on a mismatch, maybe someone will get inspired to decode it properly at some point... Cc: Chaitanya Kumar Borah Cc: Takashi Iwai Reviewed-by: Jani Nikula Reviewed-by: Kai Vehmanen Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20230124144628.4649-11-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 43 ++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index e37cca6b18c6..717ca3d7890d 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -5383,6 +5383,12 @@ intel_compare_dp_vsc_sdp(const struct drm_dp_vsc_sdp *a, return memcmp(a, b, sizeof(*a)) == 0; } +static bool +intel_compare_buffer(const u8 *a, const u8 *b, size_t len) +{ + return memcmp(a, b, len) == 0; +} + static void pipe_config_infoframe_mismatch(struct drm_i915_private *dev_priv, bool fastset, const char *name, @@ -5433,6 +5439,30 @@ pipe_config_dp_vsc_sdp_mismatch(struct drm_i915_private *dev_priv, } } +static void +pipe_config_buffer_mismatch(struct drm_i915_private *dev_priv, + bool fastset, const char *name, + const u8 *a, const u8 *b, size_t len) +{ + if (fastset) { + if (!drm_debug_enabled(DRM_UT_KMS)) + return; + + drm_dbg_kms(&dev_priv->drm, + "fastset mismatch in %s buffer\n", name); + print_hex_dump(KERN_DEBUG, "expected: ", DUMP_PREFIX_NONE, + 16, 0, a, len, false); + print_hex_dump(KERN_DEBUG, "found: ", DUMP_PREFIX_NONE, + 16, 0, b, len, false); + } else { + drm_err(&dev_priv->drm, "mismatch in %s buffer\n", name); + print_hex_dump(KERN_ERR, "expected: ", DUMP_PREFIX_NONE, + 16, 0, a, len, false); + print_hex_dump(KERN_ERR, "found: ", DUMP_PREFIX_NONE, + 16, 0, b, len, false); + } +} + static void __printf(4, 5) pipe_config_mismatch(bool fastset, const struct intel_crtc *crtc, const char *name, const char *format, ...) @@ -5631,6 +5661,18 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, } \ } while (0) +#define PIPE_CONF_CHECK_BUFFER(name, len) do { \ + BUILD_BUG_ON(sizeof(current_config->name) != (len)); \ + BUILD_BUG_ON(sizeof(pipe_config->name) != (len)); \ + if (!intel_compare_buffer(current_config->name, pipe_config->name, (len))) { \ + pipe_config_buffer_mismatch(dev_priv, fastset, __stringify(name), \ + current_config->name, \ + pipe_config->name, \ + (len)); \ + ret = false; \ + } \ +} while (0) + #define PIPE_CONF_CHECK_COLOR_LUT(lut, is_pre_csc_lut) do { \ if (current_config->gamma_mode == pipe_config->gamma_mode && \ !intel_color_lut_equal(current_config, \ @@ -5702,6 +5744,7 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, PIPE_CONF_CHECK_BOOL(fec_enable); PIPE_CONF_CHECK_BOOL_INCOMPLETE(has_audio); + PIPE_CONF_CHECK_BUFFER(eld, MAX_ELD_BYTES); PIPE_CONF_CHECK_X(gmch_pfit.control); /* pfit ratios are autocomputed by the hw on gen4+ */ From ba9f03fd896bfac5ef53c9fc9da1a0fec7de303f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 24 Jan 2023 16:46:26 +0200 Subject: [PATCH 50/67] drm/i915/audio: Include ELD in the state dump MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Include the ELD has a hex blob in the crtc state dump. Cc: Chaitanya Kumar Borah Cc: Takashi Iwai Reviewed-by: Jani Nikula Reviewed-by: Kai Vehmanen Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20230124144628.4649-12-ville.syrjala@linux.intel.com --- .../drm/i915/display/intel_crtc_state_dump.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c b/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c index e3273fe8ddac..2422d6ef5777 100644 --- a/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c +++ b/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c @@ -3,6 +3,8 @@ * Copyright © 2022 Intel Corporation */ +#include + #include "i915_drv.h" #include "intel_crtc_state_dump.h" #include "intel_display_types.h" @@ -56,6 +58,17 @@ intel_dump_dp_vsc_sdp(struct drm_i915_private *i915, drm_dp_vsc_sdp_log(KERN_DEBUG, i915->drm.dev, vsc); } +static void +intel_dump_buffer(struct drm_i915_private *i915, + const char *prefix, const u8 *buf, size_t len) +{ + if (!drm_debug_enabled(DRM_UT_KMS)) + return; + + print_hex_dump(KERN_DEBUG, prefix, DUMP_PREFIX_NONE, + 16, 0, buf, len, false); +} + #define OUTPUT_TYPE(x) [INTEL_OUTPUT_ ## x] = #x static const char * const output_type_str[] = { @@ -236,6 +249,10 @@ void intel_crtc_state_dump(const struct intel_crtc_state *pipe_config, intel_hdmi_infoframe_enable(DP_SDP_VSC)) intel_dump_dp_vsc_sdp(i915, &pipe_config->infoframes.vsc); + if (pipe_config->has_audio) + intel_dump_buffer(i915, "ELD: ", pipe_config->eld, + drm_eld_size(pipe_config->eld)); + drm_dbg_kms(&i915->drm, "vrr: %s, vmin: %d, vmax: %d, pipeline full: %d, guardband: %d flipline: %d, vmin vblank: %d, vmax vblank: %d\n", str_yes_no(pipe_config->vrr.enable), pipe_config->vrr.vmin, pipe_config->vrr.vmax, From 7e95cb0963f021dc3e84b3eb012981ecf0bdf3d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 24 Jan 2023 16:46:27 +0200 Subject: [PATCH 51/67] drm/i915/audio: s/ilk/ibx/ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename the ilk stuff to ibx, as the audio logic lives in the PCH. The only exception are VLV/CHV but their audio hardware was stolen from ibx so the name still fits. Also most of the register defines also use the IBX namespace. Cc: Chaitanya Kumar Borah Cc: Takashi Iwai Reviewed-by: Kai Vehmanen Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20230124144628.4649-13-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_audio.c | 28 +++++++++++----------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_audio.c b/drivers/gpu/drm/i915/display/intel_audio.c index f7b460a9c76e..99a3ed84dac9 100644 --- a/drivers/gpu/drm/i915/display/intel_audio.c +++ b/drivers/gpu/drm/i915/display/intel_audio.c @@ -658,13 +658,13 @@ static void hsw_audio_codec_enable(struct intel_encoder *encoder, mutex_unlock(&i915->display.audio.mutex); } -struct ilk_audio_regs { +struct ibx_audio_regs { i915_reg_t hdmiw_hdmiedid, aud_config, aud_cntl_st, aud_cntrl_st2; }; -static void ilk_audio_regs_init(struct drm_i915_private *i915, +static void ibx_audio_regs_init(struct drm_i915_private *i915, enum pipe pipe, - struct ilk_audio_regs *regs) + struct ibx_audio_regs *regs) { if (HAS_PCH_IBX(i915)) { regs->hdmiw_hdmiedid = IBX_HDMIW_HDMIEDID(pipe); @@ -684,7 +684,7 @@ static void ilk_audio_regs_init(struct drm_i915_private *i915, } } -static void ilk_audio_codec_disable(struct intel_encoder *encoder, +static void ibx_audio_codec_disable(struct intel_encoder *encoder, const struct intel_crtc_state *old_crtc_state, const struct drm_connector_state *old_conn_state) { @@ -692,12 +692,12 @@ static void ilk_audio_codec_disable(struct intel_encoder *encoder, struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); enum port port = encoder->port; enum pipe pipe = crtc->pipe; - struct ilk_audio_regs regs; + struct ibx_audio_regs regs; if (drm_WARN_ON(&i915->drm, port == PORT_A)) return; - ilk_audio_regs_init(i915, pipe, ®s); + ibx_audio_regs_init(i915, pipe, ®s); mutex_lock(&i915->display.audio.mutex); @@ -720,7 +720,7 @@ static void ilk_audio_codec_disable(struct intel_encoder *encoder, intel_crtc_wait_for_next_vblank(crtc); } -static void ilk_audio_codec_enable(struct intel_encoder *encoder, +static void ibx_audio_codec_enable(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state) { @@ -728,14 +728,14 @@ static void ilk_audio_codec_enable(struct intel_encoder *encoder, struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); enum port port = encoder->port; enum pipe pipe = crtc->pipe; - struct ilk_audio_regs regs; + struct ibx_audio_regs regs; if (drm_WARN_ON(&i915->drm, port == PORT_A)) return; intel_crtc_wait_for_next_vblank(crtc); - ilk_audio_regs_init(i915, pipe, ®s); + ibx_audio_regs_init(i915, pipe, ®s); mutex_lock(&i915->display.audio.mutex); @@ -945,9 +945,9 @@ static const struct intel_audio_funcs g4x_audio_funcs = { .audio_codec_get_config = g4x_audio_codec_get_config, }; -static const struct intel_audio_funcs ilk_audio_funcs = { - .audio_codec_enable = ilk_audio_codec_enable, - .audio_codec_disable = ilk_audio_codec_disable, +static const struct intel_audio_funcs ibx_audio_funcs = { + .audio_codec_enable = ibx_audio_codec_enable, + .audio_codec_disable = ibx_audio_codec_disable, .audio_codec_get_config = intel_acomp_get_config, }; @@ -966,11 +966,11 @@ void intel_audio_hooks_init(struct drm_i915_private *i915) if (IS_G4X(i915)) i915->display.funcs.audio = &g4x_audio_funcs; else if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) - i915->display.funcs.audio = &ilk_audio_funcs; + i915->display.funcs.audio = &ibx_audio_funcs; else if (IS_HASWELL(i915) || DISPLAY_VER(i915) >= 8) i915->display.funcs.audio = &hsw_audio_funcs; else if (HAS_PCH_SPLIT(i915)) - i915->display.funcs.audio = &ilk_audio_funcs; + i915->display.funcs.audio = &ibx_audio_funcs; } struct aud_ts_cdclk_m_n { From 31395fba97f2bbe33237125e2dc97b4c998d0b68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 24 Jan 2023 16:46:28 +0200 Subject: [PATCH 52/67] drm/i915/audio: Clean up the PCH type checks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use explicit PCH type checks to make it more clear which platforms use which codepaths. Also reorder the branches in ibx_audio_regs_init() a bit to be more in chronological order. Cc: Chaitanya Kumar Borah Cc: Takashi Iwai Reviewed-by: Kai Vehmanen Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20230124144628.4649-14-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_audio.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_audio.c b/drivers/gpu/drm/i915/display/intel_audio.c index 99a3ed84dac9..a9335c856644 100644 --- a/drivers/gpu/drm/i915/display/intel_audio.c +++ b/drivers/gpu/drm/i915/display/intel_audio.c @@ -666,21 +666,21 @@ static void ibx_audio_regs_init(struct drm_i915_private *i915, enum pipe pipe, struct ibx_audio_regs *regs) { - if (HAS_PCH_IBX(i915)) { - regs->hdmiw_hdmiedid = IBX_HDMIW_HDMIEDID(pipe); - regs->aud_config = IBX_AUD_CFG(pipe); - regs->aud_cntl_st = IBX_AUD_CNTL_ST(pipe); - regs->aud_cntrl_st2 = IBX_AUD_CNTL_ST2; - } else if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) { + if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) { regs->hdmiw_hdmiedid = VLV_HDMIW_HDMIEDID(pipe); regs->aud_config = VLV_AUD_CFG(pipe); regs->aud_cntl_st = VLV_AUD_CNTL_ST(pipe); regs->aud_cntrl_st2 = VLV_AUD_CNTL_ST2; - } else { + } else if (HAS_PCH_CPT(i915)) { regs->hdmiw_hdmiedid = CPT_HDMIW_HDMIEDID(pipe); regs->aud_config = CPT_AUD_CFG(pipe); regs->aud_cntl_st = CPT_AUD_CNTL_ST(pipe); regs->aud_cntrl_st2 = CPT_AUD_CNTRL_ST2; + } else if (HAS_PCH_IBX(i915)) { + regs->hdmiw_hdmiedid = IBX_HDMIW_HDMIEDID(pipe); + regs->aud_config = IBX_AUD_CFG(pipe); + regs->aud_cntl_st = IBX_AUD_CNTL_ST(pipe); + regs->aud_cntrl_st2 = IBX_AUD_CNTL_ST2; } } @@ -965,12 +965,11 @@ void intel_audio_hooks_init(struct drm_i915_private *i915) { if (IS_G4X(i915)) i915->display.funcs.audio = &g4x_audio_funcs; - else if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) + else if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915) || + HAS_PCH_CPT(i915) || HAS_PCH_IBX(i915)) i915->display.funcs.audio = &ibx_audio_funcs; else if (IS_HASWELL(i915) || DISPLAY_VER(i915) >= 8) i915->display.funcs.audio = &hsw_audio_funcs; - else if (HAS_PCH_SPLIT(i915)) - i915->display.funcs.audio = &ibx_audio_funcs; } struct aud_ts_cdclk_m_n { From 9bd5de4abd444fd4466150091d4bb38ef2052e8d Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 17 Jan 2023 14:33:06 +0200 Subject: [PATCH 53/67] drm/i915: add gmch substruct to struct drm_i915_private MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Group the GMCH related members together. Signed-off-by: Jani Nikula Reviewed-by: Rodrigo Vivi Acked-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/c10c8f16cb5d12041e009f788bd9810225d6962d.1673958757.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_vga.c | 4 +- drivers/gpu/drm/i915/gt/intel_ggtt_gmch.c | 2 +- drivers/gpu/drm/i915/i915_driver.c | 58 +++++++++++------------ drivers/gpu/drm/i915/i915_drv.h | 10 ++-- 4 files changed, 37 insertions(+), 37 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_vga.c b/drivers/gpu/drm/i915/display/intel_vga.c index a69bfcac9a94..9cedeb8c2f4d 100644 --- a/drivers/gpu/drm/i915/display/intel_vga.c +++ b/drivers/gpu/drm/i915/display/intel_vga.c @@ -104,7 +104,7 @@ intel_vga_set_state(struct drm_i915_private *i915, bool enable_decode) unsigned int reg = DISPLAY_VER(i915) >= 6 ? SNB_GMCH_CTRL : INTEL_GMCH_CTRL; u16 gmch_ctrl; - if (pci_read_config_word(i915->bridge_dev, reg, &gmch_ctrl)) { + if (pci_read_config_word(i915->gmch.pdev, reg, &gmch_ctrl)) { drm_err(&i915->drm, "failed to read control word\n"); return -EIO; } @@ -117,7 +117,7 @@ intel_vga_set_state(struct drm_i915_private *i915, bool enable_decode) else gmch_ctrl |= INTEL_GMCH_VGA_DISABLE; - if (pci_write_config_word(i915->bridge_dev, reg, gmch_ctrl)) { + if (pci_write_config_word(i915->gmch.pdev, reg, gmch_ctrl)) { drm_err(&i915->drm, "failed to write control word\n"); return -EIO; } diff --git a/drivers/gpu/drm/i915/gt/intel_ggtt_gmch.c b/drivers/gpu/drm/i915/gt/intel_ggtt_gmch.c index 1c492eaee7d9..77c793812eb4 100644 --- a/drivers/gpu/drm/i915/gt/intel_ggtt_gmch.c +++ b/drivers/gpu/drm/i915/gt/intel_ggtt_gmch.c @@ -80,7 +80,7 @@ int intel_ggtt_gmch_probe(struct i915_ggtt *ggtt) phys_addr_t gmadr_base; int ret; - ret = intel_gmch_probe(i915->bridge_dev, to_pci_dev(i915->drm.dev), NULL); + ret = intel_gmch_probe(i915->gmch.pdev, to_pci_dev(i915->drm.dev), NULL); if (!ret) { drm_err(&i915->drm, "failed to set up gmch\n"); return -EIO; diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c index c1e427ba57ae..59cbc24cda6c 100644 --- a/drivers/gpu/drm/i915/i915_driver.c +++ b/drivers/gpu/drm/i915/i915_driver.c @@ -117,15 +117,15 @@ static int i915_get_bridge_dev(struct drm_i915_private *dev_priv) { int domain = pci_domain_nr(to_pci_dev(dev_priv->drm.dev)->bus); - dev_priv->bridge_dev = + dev_priv->gmch.pdev = pci_get_domain_bus_and_slot(domain, 0, PCI_DEVFN(0, 0)); - if (!dev_priv->bridge_dev) { + if (!dev_priv->gmch.pdev) { drm_err(&dev_priv->drm, "bridge device not found\n"); return -EIO; } return drmm_add_action_or_reset(&dev_priv->drm, i915_release_bridge_dev, - dev_priv->bridge_dev); + dev_priv->gmch.pdev); } /* Allocate space for the MCH regs if needed, return nonzero on error */ @@ -138,8 +138,8 @@ intel_alloc_mchbar_resource(struct drm_i915_private *dev_priv) int ret; if (GRAPHICS_VER(dev_priv) >= 4) - pci_read_config_dword(dev_priv->bridge_dev, reg + 4, &temp_hi); - pci_read_config_dword(dev_priv->bridge_dev, reg, &temp_lo); + pci_read_config_dword(dev_priv->gmch.pdev, reg + 4, &temp_hi); + pci_read_config_dword(dev_priv->gmch.pdev, reg, &temp_lo); mchbar_addr = ((u64)temp_hi << 32) | temp_lo; /* If ACPI doesn't have it, assume we need to allocate it ourselves */ @@ -150,26 +150,26 @@ intel_alloc_mchbar_resource(struct drm_i915_private *dev_priv) #endif /* Get some space for it */ - dev_priv->mch_res.name = "i915 MCHBAR"; - dev_priv->mch_res.flags = IORESOURCE_MEM; - ret = pci_bus_alloc_resource(dev_priv->bridge_dev->bus, - &dev_priv->mch_res, + dev_priv->gmch.mch_res.name = "i915 MCHBAR"; + dev_priv->gmch.mch_res.flags = IORESOURCE_MEM; + ret = pci_bus_alloc_resource(dev_priv->gmch.pdev->bus, + &dev_priv->gmch.mch_res, MCHBAR_SIZE, MCHBAR_SIZE, PCIBIOS_MIN_MEM, 0, pcibios_align_resource, - dev_priv->bridge_dev); + dev_priv->gmch.pdev); if (ret) { drm_dbg(&dev_priv->drm, "failed bus alloc: %d\n", ret); - dev_priv->mch_res.start = 0; + dev_priv->gmch.mch_res.start = 0; return ret; } if (GRAPHICS_VER(dev_priv) >= 4) - pci_write_config_dword(dev_priv->bridge_dev, reg + 4, - upper_32_bits(dev_priv->mch_res.start)); + pci_write_config_dword(dev_priv->gmch.pdev, reg + 4, + upper_32_bits(dev_priv->gmch.mch_res.start)); - pci_write_config_dword(dev_priv->bridge_dev, reg, - lower_32_bits(dev_priv->mch_res.start)); + pci_write_config_dword(dev_priv->gmch.pdev, reg, + lower_32_bits(dev_priv->gmch.mch_res.start)); return 0; } @@ -184,13 +184,13 @@ intel_setup_mchbar(struct drm_i915_private *dev_priv) if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) return; - dev_priv->mchbar_need_disable = false; + dev_priv->gmch.mchbar_need_disable = false; if (IS_I915G(dev_priv) || IS_I915GM(dev_priv)) { - pci_read_config_dword(dev_priv->bridge_dev, DEVEN, &temp); + pci_read_config_dword(dev_priv->gmch.pdev, DEVEN, &temp); enabled = !!(temp & DEVEN_MCHBAR_EN); } else { - pci_read_config_dword(dev_priv->bridge_dev, mchbar_reg, &temp); + pci_read_config_dword(dev_priv->gmch.pdev, mchbar_reg, &temp); enabled = temp & 1; } @@ -201,15 +201,15 @@ intel_setup_mchbar(struct drm_i915_private *dev_priv) if (intel_alloc_mchbar_resource(dev_priv)) return; - dev_priv->mchbar_need_disable = true; + dev_priv->gmch.mchbar_need_disable = true; /* Space is allocated or reserved, so enable it. */ if (IS_I915G(dev_priv) || IS_I915GM(dev_priv)) { - pci_write_config_dword(dev_priv->bridge_dev, DEVEN, + pci_write_config_dword(dev_priv->gmch.pdev, DEVEN, temp | DEVEN_MCHBAR_EN); } else { - pci_read_config_dword(dev_priv->bridge_dev, mchbar_reg, &temp); - pci_write_config_dword(dev_priv->bridge_dev, mchbar_reg, temp | 1); + pci_read_config_dword(dev_priv->gmch.pdev, mchbar_reg, &temp); + pci_write_config_dword(dev_priv->gmch.pdev, mchbar_reg, temp | 1); } } @@ -218,28 +218,28 @@ intel_teardown_mchbar(struct drm_i915_private *dev_priv) { int mchbar_reg = GRAPHICS_VER(dev_priv) >= 4 ? MCHBAR_I965 : MCHBAR_I915; - if (dev_priv->mchbar_need_disable) { + if (dev_priv->gmch.mchbar_need_disable) { if (IS_I915G(dev_priv) || IS_I915GM(dev_priv)) { u32 deven_val; - pci_read_config_dword(dev_priv->bridge_dev, DEVEN, + pci_read_config_dword(dev_priv->gmch.pdev, DEVEN, &deven_val); deven_val &= ~DEVEN_MCHBAR_EN; - pci_write_config_dword(dev_priv->bridge_dev, DEVEN, + pci_write_config_dword(dev_priv->gmch.pdev, DEVEN, deven_val); } else { u32 mchbar_val; - pci_read_config_dword(dev_priv->bridge_dev, mchbar_reg, + pci_read_config_dword(dev_priv->gmch.pdev, mchbar_reg, &mchbar_val); mchbar_val &= ~1; - pci_write_config_dword(dev_priv->bridge_dev, mchbar_reg, + pci_write_config_dword(dev_priv->gmch.pdev, mchbar_reg, mchbar_val); } } - if (dev_priv->mch_res.start) - release_resource(&dev_priv->mch_res); + if (dev_priv->gmch.mch_res.start) + release_resource(&dev_priv->gmch.mch_res); } static int i915_workqueues_init(struct drm_i915_private *dev_priv) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 2a6e212f8824..902ca4747e0a 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -216,13 +216,15 @@ struct drm_i915_private { struct intel_gvt *gvt; - struct pci_dev *bridge_dev; + struct { + struct pci_dev *pdev; + struct resource mch_res; + bool mchbar_need_disable; + } gmch; struct rb_root uabi_engines; unsigned int engine_uabi_class_count[I915_LAST_UABI_ENGINE_CLASS + 1]; - struct resource mch_res; - /* protects the irq masks */ spinlock_t irq_lock; @@ -268,8 +270,6 @@ struct drm_i915_private { struct i915_gem_mm mm; - bool mchbar_need_disable; - struct intel_l3_parity l3_parity; /* From a13144e2286b0fbabd0794218ee699e37a8d4210 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 17 Jan 2023 14:33:07 +0200 Subject: [PATCH 54/67] drm/i915/gmch: split out soc/intel_gmch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The GMCH related code is a bit too low level and out of place for the high level i915_driver.c file. Split out to a separate file under soc/. Rename the functions accordingly. Signed-off-by: Jani Nikula Reviewed-by: Rodrigo Vivi Acked-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/980a5e08b397bc0dbccf93cd84798772233ce75c.1673958757.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/Makefile | 1 + drivers/gpu/drm/i915/i915_driver.c | 145 +------------------------- drivers/gpu/drm/i915/soc/intel_gmch.c | 145 ++++++++++++++++++++++++++ drivers/gpu/drm/i915/soc/intel_gmch.h | 15 +++ 4 files changed, 166 insertions(+), 140 deletions(-) create mode 100644 drivers/gpu/drm/i915/soc/intel_gmch.c create mode 100644 drivers/gpu/drm/i915/soc/intel_gmch.h diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 2184bc5b2be7..918470a04591 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -63,6 +63,7 @@ i915-y += i915_driver.o \ # core peripheral code i915-y += \ soc/intel_dram.o \ + soc/intel_gmch.o \ soc/intel_pch.o # core library code diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c index 59cbc24cda6c..41384626577d 100644 --- a/drivers/gpu/drm/i915/i915_driver.c +++ b/drivers/gpu/drm/i915/i915_driver.c @@ -34,7 +34,6 @@ #include #include #include -#include #include #include #include @@ -78,6 +77,7 @@ #include "pxp/intel_pxp_pm.h" #include "soc/intel_dram.h" +#include "soc/intel_gmch.h" #include "i915_file_private.h" #include "i915_debugfs.h" @@ -107,141 +107,6 @@ static const struct drm_driver i915_drm_driver; -static void i915_release_bridge_dev(struct drm_device *dev, - void *bridge) -{ - pci_dev_put(bridge); -} - -static int i915_get_bridge_dev(struct drm_i915_private *dev_priv) -{ - int domain = pci_domain_nr(to_pci_dev(dev_priv->drm.dev)->bus); - - dev_priv->gmch.pdev = - pci_get_domain_bus_and_slot(domain, 0, PCI_DEVFN(0, 0)); - if (!dev_priv->gmch.pdev) { - drm_err(&dev_priv->drm, "bridge device not found\n"); - return -EIO; - } - - return drmm_add_action_or_reset(&dev_priv->drm, i915_release_bridge_dev, - dev_priv->gmch.pdev); -} - -/* Allocate space for the MCH regs if needed, return nonzero on error */ -static int -intel_alloc_mchbar_resource(struct drm_i915_private *dev_priv) -{ - int reg = GRAPHICS_VER(dev_priv) >= 4 ? MCHBAR_I965 : MCHBAR_I915; - u32 temp_lo, temp_hi = 0; - u64 mchbar_addr; - int ret; - - if (GRAPHICS_VER(dev_priv) >= 4) - pci_read_config_dword(dev_priv->gmch.pdev, reg + 4, &temp_hi); - pci_read_config_dword(dev_priv->gmch.pdev, reg, &temp_lo); - mchbar_addr = ((u64)temp_hi << 32) | temp_lo; - - /* If ACPI doesn't have it, assume we need to allocate it ourselves */ -#ifdef CONFIG_PNP - if (mchbar_addr && - pnp_range_reserved(mchbar_addr, mchbar_addr + MCHBAR_SIZE)) - return 0; -#endif - - /* Get some space for it */ - dev_priv->gmch.mch_res.name = "i915 MCHBAR"; - dev_priv->gmch.mch_res.flags = IORESOURCE_MEM; - ret = pci_bus_alloc_resource(dev_priv->gmch.pdev->bus, - &dev_priv->gmch.mch_res, - MCHBAR_SIZE, MCHBAR_SIZE, - PCIBIOS_MIN_MEM, - 0, pcibios_align_resource, - dev_priv->gmch.pdev); - if (ret) { - drm_dbg(&dev_priv->drm, "failed bus alloc: %d\n", ret); - dev_priv->gmch.mch_res.start = 0; - return ret; - } - - if (GRAPHICS_VER(dev_priv) >= 4) - pci_write_config_dword(dev_priv->gmch.pdev, reg + 4, - upper_32_bits(dev_priv->gmch.mch_res.start)); - - pci_write_config_dword(dev_priv->gmch.pdev, reg, - lower_32_bits(dev_priv->gmch.mch_res.start)); - return 0; -} - -/* Setup MCHBAR if possible, return true if we should disable it again */ -static void -intel_setup_mchbar(struct drm_i915_private *dev_priv) -{ - int mchbar_reg = GRAPHICS_VER(dev_priv) >= 4 ? MCHBAR_I965 : MCHBAR_I915; - u32 temp; - bool enabled; - - if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) - return; - - dev_priv->gmch.mchbar_need_disable = false; - - if (IS_I915G(dev_priv) || IS_I915GM(dev_priv)) { - pci_read_config_dword(dev_priv->gmch.pdev, DEVEN, &temp); - enabled = !!(temp & DEVEN_MCHBAR_EN); - } else { - pci_read_config_dword(dev_priv->gmch.pdev, mchbar_reg, &temp); - enabled = temp & 1; - } - - /* If it's already enabled, don't have to do anything */ - if (enabled) - return; - - if (intel_alloc_mchbar_resource(dev_priv)) - return; - - dev_priv->gmch.mchbar_need_disable = true; - - /* Space is allocated or reserved, so enable it. */ - if (IS_I915G(dev_priv) || IS_I915GM(dev_priv)) { - pci_write_config_dword(dev_priv->gmch.pdev, DEVEN, - temp | DEVEN_MCHBAR_EN); - } else { - pci_read_config_dword(dev_priv->gmch.pdev, mchbar_reg, &temp); - pci_write_config_dword(dev_priv->gmch.pdev, mchbar_reg, temp | 1); - } -} - -static void -intel_teardown_mchbar(struct drm_i915_private *dev_priv) -{ - int mchbar_reg = GRAPHICS_VER(dev_priv) >= 4 ? MCHBAR_I965 : MCHBAR_I915; - - if (dev_priv->gmch.mchbar_need_disable) { - if (IS_I915G(dev_priv) || IS_I915GM(dev_priv)) { - u32 deven_val; - - pci_read_config_dword(dev_priv->gmch.pdev, DEVEN, - &deven_val); - deven_val &= ~DEVEN_MCHBAR_EN; - pci_write_config_dword(dev_priv->gmch.pdev, DEVEN, - deven_val); - } else { - u32 mchbar_val; - - pci_read_config_dword(dev_priv->gmch.pdev, mchbar_reg, - &mchbar_val); - mchbar_val &= ~1; - pci_write_config_dword(dev_priv->gmch.pdev, mchbar_reg, - mchbar_val); - } - } - - if (dev_priv->gmch.mch_res.start) - release_resource(&dev_priv->gmch.mch_res); -} - static int i915_workqueues_init(struct drm_i915_private *dev_priv) { /* @@ -447,7 +312,7 @@ static int i915_driver_mmio_probe(struct drm_i915_private *dev_priv) if (i915_inject_probe_failure(dev_priv)) return -ENODEV; - ret = i915_get_bridge_dev(dev_priv); + ret = intel_gmch_bridge_setup(dev_priv); if (ret < 0) return ret; @@ -464,7 +329,7 @@ static int i915_driver_mmio_probe(struct drm_i915_private *dev_priv) } /* Try to make sure MCHBAR is enabled before poking at it */ - intel_setup_mchbar(dev_priv); + intel_gmch_bar_setup(dev_priv); intel_device_info_runtime_init(dev_priv); for_each_gt(gt, dev_priv, i) { @@ -479,7 +344,7 @@ static int i915_driver_mmio_probe(struct drm_i915_private *dev_priv) return 0; err_uncore: - intel_teardown_mchbar(dev_priv); + intel_gmch_bar_teardown(dev_priv); return ret; } @@ -490,7 +355,7 @@ err_uncore: */ static void i915_driver_mmio_release(struct drm_i915_private *dev_priv) { - intel_teardown_mchbar(dev_priv); + intel_gmch_bar_teardown(dev_priv); } /** diff --git a/drivers/gpu/drm/i915/soc/intel_gmch.c b/drivers/gpu/drm/i915/soc/intel_gmch.c new file mode 100644 index 000000000000..75916aa072e7 --- /dev/null +++ b/drivers/gpu/drm/i915/soc/intel_gmch.c @@ -0,0 +1,145 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2023 Intel Corporation + */ + +#include +#include + +#include + +#include "i915_drv.h" +#include "intel_gmch.h" +#include "intel_pci_config.h" + +static void intel_gmch_bridge_release(struct drm_device *dev, void *bridge) +{ + pci_dev_put(bridge); +} + +int intel_gmch_bridge_setup(struct drm_i915_private *dev_priv) +{ + int domain = pci_domain_nr(to_pci_dev(dev_priv->drm.dev)->bus); + + dev_priv->gmch.pdev = + pci_get_domain_bus_and_slot(domain, 0, PCI_DEVFN(0, 0)); + if (!dev_priv->gmch.pdev) { + drm_err(&dev_priv->drm, "bridge device not found\n"); + return -EIO; + } + + return drmm_add_action_or_reset(&dev_priv->drm, intel_gmch_bridge_release, + dev_priv->gmch.pdev); +} + +/* Allocate space for the MCH regs if needed, return nonzero on error */ +static int +intel_alloc_mchbar_resource(struct drm_i915_private *dev_priv) +{ + int reg = GRAPHICS_VER(dev_priv) >= 4 ? MCHBAR_I965 : MCHBAR_I915; + u32 temp_lo, temp_hi = 0; + u64 mchbar_addr; + int ret; + + if (GRAPHICS_VER(dev_priv) >= 4) + pci_read_config_dword(dev_priv->gmch.pdev, reg + 4, &temp_hi); + pci_read_config_dword(dev_priv->gmch.pdev, reg, &temp_lo); + mchbar_addr = ((u64)temp_hi << 32) | temp_lo; + + /* If ACPI doesn't have it, assume we need to allocate it ourselves */ +#ifdef CONFIG_PNP + if (mchbar_addr && + pnp_range_reserved(mchbar_addr, mchbar_addr + MCHBAR_SIZE)) + return 0; +#endif + + /* Get some space for it */ + dev_priv->gmch.mch_res.name = "i915 MCHBAR"; + dev_priv->gmch.mch_res.flags = IORESOURCE_MEM; + ret = pci_bus_alloc_resource(dev_priv->gmch.pdev->bus, + &dev_priv->gmch.mch_res, + MCHBAR_SIZE, MCHBAR_SIZE, + PCIBIOS_MIN_MEM, + 0, pcibios_align_resource, + dev_priv->gmch.pdev); + if (ret) { + drm_dbg(&dev_priv->drm, "failed bus alloc: %d\n", ret); + dev_priv->gmch.mch_res.start = 0; + return ret; + } + + if (GRAPHICS_VER(dev_priv) >= 4) + pci_write_config_dword(dev_priv->gmch.pdev, reg + 4, + upper_32_bits(dev_priv->gmch.mch_res.start)); + + pci_write_config_dword(dev_priv->gmch.pdev, reg, + lower_32_bits(dev_priv->gmch.mch_res.start)); + return 0; +} + +/* Setup MCHBAR if possible, return true if we should disable it again */ +void intel_gmch_bar_setup(struct drm_i915_private *dev_priv) +{ + int mchbar_reg = GRAPHICS_VER(dev_priv) >= 4 ? MCHBAR_I965 : MCHBAR_I915; + u32 temp; + bool enabled; + + if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) + return; + + dev_priv->gmch.mchbar_need_disable = false; + + if (IS_I915G(dev_priv) || IS_I915GM(dev_priv)) { + pci_read_config_dword(dev_priv->gmch.pdev, DEVEN, &temp); + enabled = !!(temp & DEVEN_MCHBAR_EN); + } else { + pci_read_config_dword(dev_priv->gmch.pdev, mchbar_reg, &temp); + enabled = temp & 1; + } + + /* If it's already enabled, don't have to do anything */ + if (enabled) + return; + + if (intel_alloc_mchbar_resource(dev_priv)) + return; + + dev_priv->gmch.mchbar_need_disable = true; + + /* Space is allocated or reserved, so enable it. */ + if (IS_I915G(dev_priv) || IS_I915GM(dev_priv)) { + pci_write_config_dword(dev_priv->gmch.pdev, DEVEN, + temp | DEVEN_MCHBAR_EN); + } else { + pci_read_config_dword(dev_priv->gmch.pdev, mchbar_reg, &temp); + pci_write_config_dword(dev_priv->gmch.pdev, mchbar_reg, temp | 1); + } +} + +void intel_gmch_bar_teardown(struct drm_i915_private *dev_priv) +{ + int mchbar_reg = GRAPHICS_VER(dev_priv) >= 4 ? MCHBAR_I965 : MCHBAR_I915; + + if (dev_priv->gmch.mchbar_need_disable) { + if (IS_I915G(dev_priv) || IS_I915GM(dev_priv)) { + u32 deven_val; + + pci_read_config_dword(dev_priv->gmch.pdev, DEVEN, + &deven_val); + deven_val &= ~DEVEN_MCHBAR_EN; + pci_write_config_dword(dev_priv->gmch.pdev, DEVEN, + deven_val); + } else { + u32 mchbar_val; + + pci_read_config_dword(dev_priv->gmch.pdev, mchbar_reg, + &mchbar_val); + mchbar_val &= ~1; + pci_write_config_dword(dev_priv->gmch.pdev, mchbar_reg, + mchbar_val); + } + } + + if (dev_priv->gmch.mch_res.start) + release_resource(&dev_priv->gmch.mch_res); +} diff --git a/drivers/gpu/drm/i915/soc/intel_gmch.h b/drivers/gpu/drm/i915/soc/intel_gmch.h new file mode 100644 index 000000000000..bbc52dbab708 --- /dev/null +++ b/drivers/gpu/drm/i915/soc/intel_gmch.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2023 Intel Corporation + */ + +#ifndef __INTEL_GMCH_H__ +#define __INTEL_GMCH_H__ + +struct drm_i915_private; + +int intel_gmch_bridge_setup(struct drm_i915_private *i915); +void intel_gmch_bar_setup(struct drm_i915_private *i915); +void intel_gmch_bar_teardown(struct drm_i915_private *i915); + +#endif /* __INTEL_GMCH_H__ */ From b1e7d8b008439615df69ba632d66098004a5367d Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 17 Jan 2023 14:33:08 +0200 Subject: [PATCH 55/67] drm/i915/gmch: mass rename dev_priv to i915 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prefer the contemporary naming. Signed-off-by: Jani Nikula Reviewed-by: Rodrigo Vivi Acked-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/3e4aaadeb4a027165f5724027963aa5e8d747190.1673958757.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/soc/intel_gmch.c | 95 +++++++++++++-------------- 1 file changed, 47 insertions(+), 48 deletions(-) diff --git a/drivers/gpu/drm/i915/soc/intel_gmch.c b/drivers/gpu/drm/i915/soc/intel_gmch.c index 75916aa072e7..d5fbb7907725 100644 --- a/drivers/gpu/drm/i915/soc/intel_gmch.c +++ b/drivers/gpu/drm/i915/soc/intel_gmch.c @@ -17,33 +17,32 @@ static void intel_gmch_bridge_release(struct drm_device *dev, void *bridge) pci_dev_put(bridge); } -int intel_gmch_bridge_setup(struct drm_i915_private *dev_priv) +int intel_gmch_bridge_setup(struct drm_i915_private *i915) { - int domain = pci_domain_nr(to_pci_dev(dev_priv->drm.dev)->bus); + int domain = pci_domain_nr(to_pci_dev(i915->drm.dev)->bus); - dev_priv->gmch.pdev = - pci_get_domain_bus_and_slot(domain, 0, PCI_DEVFN(0, 0)); - if (!dev_priv->gmch.pdev) { - drm_err(&dev_priv->drm, "bridge device not found\n"); + i915->gmch.pdev = pci_get_domain_bus_and_slot(domain, 0, PCI_DEVFN(0, 0)); + if (!i915->gmch.pdev) { + drm_err(&i915->drm, "bridge device not found\n"); return -EIO; } - return drmm_add_action_or_reset(&dev_priv->drm, intel_gmch_bridge_release, - dev_priv->gmch.pdev); + return drmm_add_action_or_reset(&i915->drm, intel_gmch_bridge_release, + i915->gmch.pdev); } /* Allocate space for the MCH regs if needed, return nonzero on error */ static int -intel_alloc_mchbar_resource(struct drm_i915_private *dev_priv) +intel_alloc_mchbar_resource(struct drm_i915_private *i915) { - int reg = GRAPHICS_VER(dev_priv) >= 4 ? MCHBAR_I965 : MCHBAR_I915; + int reg = GRAPHICS_VER(i915) >= 4 ? MCHBAR_I965 : MCHBAR_I915; u32 temp_lo, temp_hi = 0; u64 mchbar_addr; int ret; - if (GRAPHICS_VER(dev_priv) >= 4) - pci_read_config_dword(dev_priv->gmch.pdev, reg + 4, &temp_hi); - pci_read_config_dword(dev_priv->gmch.pdev, reg, &temp_lo); + if (GRAPHICS_VER(i915) >= 4) + pci_read_config_dword(i915->gmch.pdev, reg + 4, &temp_hi); + pci_read_config_dword(i915->gmch.pdev, reg, &temp_lo); mchbar_addr = ((u64)temp_hi << 32) | temp_lo; /* If ACPI doesn't have it, assume we need to allocate it ourselves */ @@ -54,46 +53,46 @@ intel_alloc_mchbar_resource(struct drm_i915_private *dev_priv) #endif /* Get some space for it */ - dev_priv->gmch.mch_res.name = "i915 MCHBAR"; - dev_priv->gmch.mch_res.flags = IORESOURCE_MEM; - ret = pci_bus_alloc_resource(dev_priv->gmch.pdev->bus, - &dev_priv->gmch.mch_res, + i915->gmch.mch_res.name = "i915 MCHBAR"; + i915->gmch.mch_res.flags = IORESOURCE_MEM; + ret = pci_bus_alloc_resource(i915->gmch.pdev->bus, + &i915->gmch.mch_res, MCHBAR_SIZE, MCHBAR_SIZE, PCIBIOS_MIN_MEM, 0, pcibios_align_resource, - dev_priv->gmch.pdev); + i915->gmch.pdev); if (ret) { - drm_dbg(&dev_priv->drm, "failed bus alloc: %d\n", ret); - dev_priv->gmch.mch_res.start = 0; + drm_dbg(&i915->drm, "failed bus alloc: %d\n", ret); + i915->gmch.mch_res.start = 0; return ret; } - if (GRAPHICS_VER(dev_priv) >= 4) - pci_write_config_dword(dev_priv->gmch.pdev, reg + 4, - upper_32_bits(dev_priv->gmch.mch_res.start)); + if (GRAPHICS_VER(i915) >= 4) + pci_write_config_dword(i915->gmch.pdev, reg + 4, + upper_32_bits(i915->gmch.mch_res.start)); - pci_write_config_dword(dev_priv->gmch.pdev, reg, - lower_32_bits(dev_priv->gmch.mch_res.start)); + pci_write_config_dword(i915->gmch.pdev, reg, + lower_32_bits(i915->gmch.mch_res.start)); return 0; } /* Setup MCHBAR if possible, return true if we should disable it again */ -void intel_gmch_bar_setup(struct drm_i915_private *dev_priv) +void intel_gmch_bar_setup(struct drm_i915_private *i915) { - int mchbar_reg = GRAPHICS_VER(dev_priv) >= 4 ? MCHBAR_I965 : MCHBAR_I915; + int mchbar_reg = GRAPHICS_VER(i915) >= 4 ? MCHBAR_I965 : MCHBAR_I915; u32 temp; bool enabled; - if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) + if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) return; - dev_priv->gmch.mchbar_need_disable = false; + i915->gmch.mchbar_need_disable = false; - if (IS_I915G(dev_priv) || IS_I915GM(dev_priv)) { - pci_read_config_dword(dev_priv->gmch.pdev, DEVEN, &temp); + if (IS_I915G(i915) || IS_I915GM(i915)) { + pci_read_config_dword(i915->gmch.pdev, DEVEN, &temp); enabled = !!(temp & DEVEN_MCHBAR_EN); } else { - pci_read_config_dword(dev_priv->gmch.pdev, mchbar_reg, &temp); + pci_read_config_dword(i915->gmch.pdev, mchbar_reg, &temp); enabled = temp & 1; } @@ -101,45 +100,45 @@ void intel_gmch_bar_setup(struct drm_i915_private *dev_priv) if (enabled) return; - if (intel_alloc_mchbar_resource(dev_priv)) + if (intel_alloc_mchbar_resource(i915)) return; - dev_priv->gmch.mchbar_need_disable = true; + i915->gmch.mchbar_need_disable = true; /* Space is allocated or reserved, so enable it. */ - if (IS_I915G(dev_priv) || IS_I915GM(dev_priv)) { - pci_write_config_dword(dev_priv->gmch.pdev, DEVEN, + if (IS_I915G(i915) || IS_I915GM(i915)) { + pci_write_config_dword(i915->gmch.pdev, DEVEN, temp | DEVEN_MCHBAR_EN); } else { - pci_read_config_dword(dev_priv->gmch.pdev, mchbar_reg, &temp); - pci_write_config_dword(dev_priv->gmch.pdev, mchbar_reg, temp | 1); + pci_read_config_dword(i915->gmch.pdev, mchbar_reg, &temp); + pci_write_config_dword(i915->gmch.pdev, mchbar_reg, temp | 1); } } -void intel_gmch_bar_teardown(struct drm_i915_private *dev_priv) +void intel_gmch_bar_teardown(struct drm_i915_private *i915) { - int mchbar_reg = GRAPHICS_VER(dev_priv) >= 4 ? MCHBAR_I965 : MCHBAR_I915; + int mchbar_reg = GRAPHICS_VER(i915) >= 4 ? MCHBAR_I965 : MCHBAR_I915; - if (dev_priv->gmch.mchbar_need_disable) { - if (IS_I915G(dev_priv) || IS_I915GM(dev_priv)) { + if (i915->gmch.mchbar_need_disable) { + if (IS_I915G(i915) || IS_I915GM(i915)) { u32 deven_val; - pci_read_config_dword(dev_priv->gmch.pdev, DEVEN, + pci_read_config_dword(i915->gmch.pdev, DEVEN, &deven_val); deven_val &= ~DEVEN_MCHBAR_EN; - pci_write_config_dword(dev_priv->gmch.pdev, DEVEN, + pci_write_config_dword(i915->gmch.pdev, DEVEN, deven_val); } else { u32 mchbar_val; - pci_read_config_dword(dev_priv->gmch.pdev, mchbar_reg, + pci_read_config_dword(i915->gmch.pdev, mchbar_reg, &mchbar_val); mchbar_val &= ~1; - pci_write_config_dword(dev_priv->gmch.pdev, mchbar_reg, + pci_write_config_dword(i915->gmch.pdev, mchbar_reg, mchbar_val); } } - if (dev_priv->gmch.mch_res.start) - release_resource(&dev_priv->gmch.mch_res); + if (i915->gmch.mch_res.start) + release_resource(&i915->gmch.mch_res); } From eee838e40a621168993515b4b50cc1545857df8f Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 17 Jan 2023 14:33:09 +0200 Subject: [PATCH 56/67] drm/i915/gmch: move VGA set state to GMCH code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is the only user for the GMCH bridge device in display. Move it to GMCH code. Signed-off-by: Jani Nikula Reviewed-by: Rodrigo Vivi Acked-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/9bd50fe508246a547cf6e7abfe44ed686a4b3e3a.1673958757.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_vga.c | 32 +++--------------------- drivers/gpu/drm/i915/soc/intel_gmch.c | 27 ++++++++++++++++++++ drivers/gpu/drm/i915/soc/intel_gmch.h | 3 +++ 3 files changed, 33 insertions(+), 29 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_vga.c b/drivers/gpu/drm/i915/display/intel_vga.c index 9cedeb8c2f4d..286a0bdd28c6 100644 --- a/drivers/gpu/drm/i915/display/intel_vga.c +++ b/drivers/gpu/drm/i915/display/intel_vga.c @@ -6,9 +6,10 @@ #include #include -#include #include