From fd847b8e60e0db72fd7d8922da0d1b07c1454efa Mon Sep 17 00:00:00 2001 From: José Roberto de Souza Date: Tue, 18 Sep 2018 13:47:11 -0700 Subject: drm/i915: Do not modifiy reserved bit in gens that do not have IPC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit IPC was only added in SKL+(actually we don't even enable for SKL due WA) so without this change, driver was writing to a reserved bit. Also removing the uncessary dev_priv->ipc_enabled = false; as now gens without IPC will not have IPC enabled. v2(Rodrigo): - moved the new handling of WA #0477 to the next patch Reviewed-by: Rodrigo Vivi Signed-off-by: José Roberto de Souza Signed-off-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20180918204714.27306-3-jose.souza@intel.com --- drivers/gpu/drm/i915/intel_pm.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 1db9b8328275..e2ca04534e23 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -6117,6 +6117,9 @@ void intel_enable_ipc(struct drm_i915_private *dev_priv) { u32 val; + if (!HAS_IPC(dev_priv)) + return; + /* Display WA #0477 WaDisableIPC: skl */ if (IS_SKYLAKE(dev_priv)) dev_priv->ipc_enabled = false; @@ -6138,7 +6141,6 @@ void intel_enable_ipc(struct drm_i915_private *dev_priv) void intel_init_ipc(struct drm_i915_private *dev_priv) { - dev_priv->ipc_enabled = false; if (!HAS_IPC(dev_priv)) return; -- cgit From 6323113b7af6ef2f095f159752b06e83a64d8b9a Mon Sep 17 00:00:00 2001 From: José Roberto de Souza Date: Tue, 18 Sep 2018 13:47:12 -0700 Subject: drm/i915: Move SKL IPC WA to HAS_IPC() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SKL has IPC but it should not be set according to the WA, so lets just mark as it don't have it to simply the code and avoid unnecessary MMIO writes at every call to intel_enable_ipc(). Reviewed-by: Rodrigo Vivi Signed-off-by: José Roberto de Souza Signed-off-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20180918204714.27306-4-jose.souza@intel.com --- drivers/gpu/drm/i915/intel_pm.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index e2ca04534e23..538bcde0bf7d 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -6120,10 +6120,6 @@ void intel_enable_ipc(struct drm_i915_private *dev_priv) if (!HAS_IPC(dev_priv)) return; - /* Display WA #0477 WaDisableIPC: skl */ - if (IS_SKYLAKE(dev_priv)) - dev_priv->ipc_enabled = false; - /* Display WA #1141: SKL:all KBL:all CFL */ if ((IS_KABYLAKE(dev_priv) || IS_COFFEELAKE(dev_priv)) && !dev_priv->dram_info.symmetric_memory) -- cgit From c9b818d3f9f4eca54a2ad3083b4584f453b20bed Mon Sep 17 00:00:00 2001 From: José Roberto de Souza Date: Tue, 18 Sep 2018 13:47:13 -0700 Subject: drm/i915: Move IPC WA #1141 to init_ipc() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit symmetric_memory do not change after initialization so lets just set ipc_enabled once for this WA. Reviewed-by: Rodrigo Vivi Signed-off-by: José Roberto de Souza Signed-off-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20180918204714.27306-5-jose.souza@intel.com --- drivers/gpu/drm/i915/intel_pm.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 538bcde0bf7d..1392aa56a55a 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -6120,11 +6120,6 @@ void intel_enable_ipc(struct drm_i915_private *dev_priv) if (!HAS_IPC(dev_priv)) return; - /* Display WA #1141: SKL:all KBL:all CFL */ - if ((IS_KABYLAKE(dev_priv) || IS_COFFEELAKE(dev_priv)) && - !dev_priv->dram_info.symmetric_memory) - dev_priv->ipc_enabled = false; - val = I915_READ(DISP_ARB_CTL2); if (dev_priv->ipc_enabled) @@ -6140,7 +6135,12 @@ void intel_init_ipc(struct drm_i915_private *dev_priv) if (!HAS_IPC(dev_priv)) return; - dev_priv->ipc_enabled = true; + /* Display WA #1141: SKL:all KBL:all CFL */ + if (IS_KABYLAKE(dev_priv) || IS_COFFEELAKE(dev_priv)) + dev_priv->ipc_enabled = dev_priv->dram_info.symmetric_memory; + else + dev_priv->ipc_enabled = true; + intel_enable_ipc(dev_priv); } -- cgit From 91961a850d31a05067fe53a7fe16d255a1c8a159 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Thu, 4 Oct 2018 16:15:56 -0700 Subject: drm/i915: fix the transition minimums for gen9+ watermarks The transition minimum is 14 blocks for gens 9 and 10, and 4 blocks for gen 11. This minimum value is supposed to be added to the configurable trans_amount. This matches both BSpec and additional information provided by our HW engineers. Reviewed-by: Matt Roper Signed-off-by: Paulo Zanoni Link: https://patchwork.freedesktop.org/patch/msgid/20181004231600.14101-3-paulo.r.zanoni@intel.com --- drivers/gpu/drm/i915/intel_pm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 1392aa56a55a..983af46197b1 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4875,8 +4875,8 @@ static void skl_compute_transition_wm(struct intel_crtc_state *cstate, if (!dev_priv->ipc_enabled) goto exit; - trans_min = 0; - if (INTEL_GEN(dev_priv) >= 10) + trans_min = 14; + if (INTEL_GEN(dev_priv) >= 11) trans_min = 4; trans_offset_b = trans_min + trans_amount; -- cgit From 077b5820af74507a1d748f215d6e0753616dfb3d Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Thu, 4 Oct 2018 16:15:57 -0700 Subject: drm/i915: fix the watermark result selection on glk/gen10+ On these platforms we're supposed to unconditonally pick the method 2 result instead of the minimum. Reviewed-by: Matt Roper Signed-off-by: Paulo Zanoni Link: https://patchwork.freedesktop.org/patch/msgid/20181004231600.14101-4-paulo.r.zanoni@intel.com --- drivers/gpu/drm/i915/intel_pm.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 983af46197b1..43fb1f8fced8 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4672,15 +4672,24 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, } else { if ((wp->cpp * cstate->base.adjusted_mode.crtc_htotal / wp->dbuf_block_size < 1) && - (wp->plane_bytes_per_line / wp->dbuf_block_size < 1)) + (wp->plane_bytes_per_line / wp->dbuf_block_size < 1)) { selected_result = method2; - else if (ddb_allocation >= - fixed16_to_u32_round_up(wp->plane_blocks_per_line)) - selected_result = min_fixed16(method1, method2); - else if (latency >= wp->linetime_us) - selected_result = min_fixed16(method1, method2); - else + } else if (ddb_allocation >= + fixed16_to_u32_round_up(wp->plane_blocks_per_line)) { + if (INTEL_GEN(dev_priv) == 9 && + !IS_GEMINILAKE(dev_priv)) + selected_result = min_fixed16(method1, method2); + else + selected_result = method2; + } else if (latency >= wp->linetime_us) { + if (INTEL_GEN(dev_priv) == 9 && + !IS_GEMINILAKE(dev_priv)) + selected_result = min_fixed16(method1, method2); + else + selected_result = method2; + } else { selected_result = method1; + } } res_blocks = fixed16_to_u32_round_up(selected_result) + 1; -- cgit From cbacc79db6ac932f7ac86ff01086302bfb79e5d0 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Thu, 4 Oct 2018 16:15:58 -0700 Subject: drm/i915: transition WMs ask for Selected Result Blocks The transition watermarks ask for Selected Result Blocks (the real value), not Result Blocks (the integer value). Given how ceilings are applied in both the non-transition and the transition watermarks calculations, we can get away with assuming that Selected Result Blocks is actually Result Blocks minus 1 without any rounding errors. Reviewed-by: Matt Roper Signed-off-by: Paulo Zanoni Link: https://patchwork.freedesktop.org/patch/msgid/20181004231600.14101-5-paulo.r.zanoni@intel.com --- drivers/gpu/drm/i915/intel_pm.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 43fb1f8fced8..8bd45586e01a 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4871,7 +4871,7 @@ static void skl_compute_transition_wm(struct intel_crtc_state *cstate, const struct drm_i915_private *dev_priv = to_i915(dev); uint16_t trans_min, trans_y_tile_min; const uint16_t trans_amount = 10; /* This is configurable amount */ - uint16_t trans_offset_b, res_blocks; + uint16_t wm0_sel_res_b, trans_offset_b, res_blocks; if (!cstate->base.active) goto exit; @@ -4890,13 +4890,25 @@ static void skl_compute_transition_wm(struct intel_crtc_state *cstate, trans_offset_b = trans_min + trans_amount; + /* + * The spec asks for Selected Result Blocks for wm0 (the real value), + * not Result Blocks (the integer value). Pay attention to the capital + * letters. The value wm_l0->plane_res_b is actually Result Blocks, but + * since Result Blocks is the ceiling of Selected Result Blocks plus 1, + * and since we later will have to get the ceiling of the sum in the + * transition watermarks calculation, we can just pretend Selected + * Result Blocks is Result Blocks minus 1 and it should work for the + * current platforms. + */ + wm0_sel_res_b = wm_l0->plane_res_b - 1; + if (wp->y_tiled) { trans_y_tile_min = (uint16_t) mul_round_up_u32_fixed16(2, wp->y_tile_minimum); - res_blocks = max(wm_l0->plane_res_b, trans_y_tile_min) + + res_blocks = max(wm0_sel_res_b, trans_y_tile_min) + trans_offset_b; } else { - res_blocks = wm_l0->plane_res_b + trans_offset_b; + res_blocks = wm0_sel_res_b + trans_offset_b; /* WA BUG:1938466 add one block for non y-tile planes */ if (IS_CNL_REVID(dev_priv, CNL_REVID_A0, CNL_REVID_A0)) -- cgit From 9e44b180f81bbc69d15807e113675d19bf538c77 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Thu, 4 Oct 2018 16:15:59 -0700 Subject: drm/i915: don't write PLANE_BUF_CFG twice every time We were writing to PLANE_BUF_CFG(pipe, plane_id) twice for every platform, and we were even using different values on the gen10- planar case. The first write is useless since it just gets replaced with the next one, so kill it. There's a lot to improve in the DDB code, but let's start by avoiding the double write. Reviewed-by: Matt Roper Signed-off-by: Paulo Zanoni Link: https://patchwork.freedesktop.org/patch/msgid/20181004231600.14101-6-paulo.r.zanoni@intel.com --- drivers/gpu/drm/i915/intel_pm.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 8bd45586e01a..e76a1398b74f 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5037,8 +5037,6 @@ static void skl_write_plane_wm(struct intel_crtc *intel_crtc, skl_write_wm_level(dev_priv, PLANE_WM_TRANS(pipe, plane_id), &wm->trans_wm); - skl_ddb_entry_write(dev_priv, PLANE_BUF_CFG(pipe, plane_id), - &ddb->plane[pipe][plane_id]); /* FIXME: add proper NV12 support for ICL. */ if (INTEL_GEN(dev_priv) >= 11) return skl_ddb_entry_write(dev_priv, -- cgit From b9117149fefdcdc6fcd12a14a26d71979582c057 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Thu, 4 Oct 2018 16:16:00 -0700 Subject: drm/i915: promote ddb update message to DRM_DEBUG_KMS This message is currently marked as DRM_DEBUG_ATOMIC. I would like it to be DRM_DEBUG_KMS since it is more KMS than atomic, and this will also make the message appear in the CI logs, which may or may not help us with some FIFO underrun bugs. Reviewed-by: Matt Roper Signed-off-by: Paulo Zanoni Link: https://patchwork.freedesktop.org/patch/msgid/20181004231600.14101-7-paulo.r.zanoni@intel.com --- drivers/gpu/drm/i915/intel_pm.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index e76a1398b74f..fa5c48778a80 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5230,11 +5230,11 @@ skl_print_wm_changes(const struct drm_atomic_state *state) if (skl_ddb_entry_equal(old, new)) continue; - DRM_DEBUG_ATOMIC("[PLANE:%d:%s] ddb (%d - %d) -> (%d - %d)\n", - intel_plane->base.base.id, - intel_plane->base.name, - old->start, old->end, - new->start, new->end); + DRM_DEBUG_KMS("[PLANE:%d:%s] ddb (%d - %d) -> (%d - %d)\n", + intel_plane->base.base.id, + intel_plane->base.name, + old->start, old->end, + new->start, new->end); } } } -- cgit From 04c388d429568f03e2719bfb56ebfdb115896bd0 Mon Sep 17 00:00:00 2001 From: Mahesh Kumar Date: Thu, 11 Oct 2018 15:57:25 -0700 Subject: drm/i915/icl: enable SAGV for ICL platform Enable SAGV for ICL platform. Cc: Gwan-gyeong Mun Tested-by: Gwan-gyeong Mun Reviewed-by: James Ausmus Reviewed-by: Paulo Zanoni Signed-off-by: Mahesh Kumar Signed-off-by: Paulo Zanoni Link: https://patchwork.freedesktop.org/patch/msgid/20181011225725.21208-1-paulo.r.zanoni@intel.com --- drivers/gpu/drm/i915/intel_pm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index fa5c48778a80..67a4d0735291 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3613,7 +3613,7 @@ static bool intel_has_sagv(struct drm_i915_private *dev_priv) { if (IS_KABYLAKE(dev_priv) || IS_COFFEELAKE(dev_priv) || - IS_CANNONLAKE(dev_priv)) + IS_CANNONLAKE(dev_priv) || IS_ICELAKE(dev_priv)) return true; if (IS_SKYLAKE(dev_priv) && -- cgit From 24719e94ca2a9397f1385da4bce6a7adea1868a7 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Mon, 22 Oct 2018 12:20:00 +0200 Subject: drm/i915: Fix unsigned overflow when calculating total data rate, v2. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On gen11, we can definitely smash the 32-bits barrier with just a when we enable all planes in the next patch. Changes since v1: - Use div64_u64 (ickle). Signed-off-by: Maarten Lankhorst Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20181022102000.30255-1-maarten.lankhorst@linux.intel.com --- drivers/gpu/drm/i915/intel_pm.c | 47 +++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 25 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 67a4d0735291..f42b8c319046 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3784,7 +3784,7 @@ bool intel_can_enable_sagv(struct drm_atomic_state *state) static u16 intel_get_ddb_size(struct drm_i915_private *dev_priv, const struct intel_crtc_state *cstate, - const unsigned int total_data_rate, + const u64 total_data_rate, const int num_active, struct skl_ddb_allocation *ddb) { @@ -3798,12 +3798,12 @@ static u16 intel_get_ddb_size(struct drm_i915_private *dev_priv, return ddb_size - 4; /* 4 blocks for bypass path allocation */ adjusted_mode = &cstate->base.adjusted_mode; - total_data_bw = (u64)total_data_rate * drm_mode_vrefresh(adjusted_mode); + total_data_bw = total_data_rate * drm_mode_vrefresh(adjusted_mode); /* * 12GB/s is maximum BW supported by single DBuf slice. */ - if (total_data_bw >= GBps(12) || num_active > 1) { + if (num_active > 1 || total_data_bw >= GBps(12)) { ddb->enabled_slices = 2; } else { ddb->enabled_slices = 1; @@ -3816,7 +3816,7 @@ static u16 intel_get_ddb_size(struct drm_i915_private *dev_priv, static void skl_ddb_get_pipe_allocation_limits(struct drm_device *dev, const struct intel_crtc_state *cstate, - const unsigned int total_data_rate, + const u64 total_data_rate, struct skl_ddb_allocation *ddb, struct skl_ddb_entry *alloc, /* out */ int *num_active /* out */) @@ -4139,7 +4139,7 @@ int skl_check_pipe_max_pixel_rate(struct intel_crtc *intel_crtc, return 0; } -static unsigned int +static u64 skl_plane_relative_data_rate(const struct intel_crtc_state *cstate, const struct drm_plane_state *pstate, const int plane) @@ -4151,6 +4151,7 @@ skl_plane_relative_data_rate(const struct intel_crtc_state *cstate, struct drm_framebuffer *fb; u32 format; uint_fixed_16_16_t down_scale_amount; + u64 rate; if (!intel_pstate->base.visible) return 0; @@ -4177,28 +4178,26 @@ skl_plane_relative_data_rate(const struct intel_crtc_state *cstate, height /= 2; } - data_rate = width * height * fb->format->cpp[plane]; + data_rate = width * height; down_scale_amount = skl_plane_downscale_amount(cstate, intel_pstate); - return mul_round_up_u32_fixed16(data_rate, down_scale_amount); + rate = mul_round_up_u32_fixed16(data_rate, down_scale_amount); + + rate *= fb->format->cpp[plane]; + return rate; } -/* - * We don't overflow 32 bits. Worst case is 3 planes enabled, each fetching - * a 8192x4096@32bpp framebuffer: - * 3 * 4096 * 8192 * 4 < 2^32 - */ -static unsigned int +static u64 skl_get_total_relative_data_rate(struct intel_crtc_state *intel_cstate, - unsigned int *plane_data_rate, - unsigned int *uv_plane_data_rate) + u64 *plane_data_rate, + u64 *uv_plane_data_rate) { struct drm_crtc_state *cstate = &intel_cstate->base; struct drm_atomic_state *state = cstate->state; struct drm_plane *plane; const struct drm_plane_state *pstate; - unsigned int total_data_rate = 0; + u64 total_data_rate = 0; if (WARN_ON(!state)) return 0; @@ -4206,7 +4205,7 @@ skl_get_total_relative_data_rate(struct intel_crtc_state *intel_cstate, /* Calculate and cache data rate for each plane */ drm_atomic_crtc_state_for_each_plane_state(plane, pstate, cstate) { enum plane_id plane_id = to_intel_plane(plane)->id; - unsigned int rate; + u64 rate; /* packed/y */ rate = skl_plane_relative_data_rate(intel_cstate, @@ -4325,11 +4324,11 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, uint16_t alloc_size, start; uint16_t minimum[I915_MAX_PLANES] = {}; uint16_t uv_minimum[I915_MAX_PLANES] = {}; - unsigned int total_data_rate; + u64 total_data_rate; enum plane_id plane_id; int num_active; - unsigned int plane_data_rate[I915_MAX_PLANES] = {}; - unsigned int uv_plane_data_rate[I915_MAX_PLANES] = {}; + u64 plane_data_rate[I915_MAX_PLANES] = {}; + u64 uv_plane_data_rate[I915_MAX_PLANES] = {}; uint16_t total_min_blocks = 0; /* Clear the partitioning for disabled planes. */ @@ -4388,7 +4387,7 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, start = alloc->start; for_each_plane_id_on_crtc(intel_crtc, plane_id) { - unsigned int data_rate, uv_data_rate; + u64 data_rate, uv_data_rate; uint16_t plane_blocks, uv_plane_blocks; if (plane_id == PLANE_CURSOR) @@ -4402,8 +4401,7 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, * result is < available as data_rate / total_data_rate < 1 */ plane_blocks = minimum[plane_id]; - plane_blocks += div_u64((uint64_t)alloc_size * data_rate, - total_data_rate); + plane_blocks += div64_u64(alloc_size * data_rate, total_data_rate); /* Leave disabled planes at (0,0) */ if (data_rate) { @@ -4417,8 +4415,7 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, uv_data_rate = uv_plane_data_rate[plane_id]; uv_plane_blocks = uv_minimum[plane_id]; - uv_plane_blocks += div_u64((uint64_t)alloc_size * uv_data_rate, - total_data_rate); + uv_plane_blocks += div64_u64(alloc_size * uv_data_rate, total_data_rate); if (uv_data_rate) { ddb->uv_plane[pipe][plane_id].start = start; -- cgit From 1ab554b0099b655141c47ec5cd05d126eaed4868 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Mon, 22 Oct 2018 15:51:52 +0200 Subject: drm/i915/gen11: Link nv12 Y and UV planes in the atomic state, v5. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To make NV12 working on icl, we need to update 2 planes simultaneously. I've chosen to do this in the CRTC step after plane validation is done, so we know what planes are (in)visible. The linked Y plane will get updated in intel_plane_update_planes_on_crtc(), by the call to update_slave, which gets the master's plane_state as argument. The link requires both planes for atomic_update to work, so make sure skl_ddb_add_affected_planes() adds both states. Changes since v1: - Introduce icl_is_nv12_y_plane(), instead of hardcoding sprite numbers. - Put all the state updating login in intel_plane_atomic_check_with_state(). - Clean up changes in intel_plane_atomic_check(). Changes since v2: - Fix intel_atomic_get_old_plane_state() to actually return old state. - Move visibility changes to preparation patch. - Only try to find a Y plane on gen11, earlier platforms only require a single plane. Changes since v3: - Fix checkpatch warning about to_intel_crtc() usage. - Add affected planes from icl_add_linked_planes() before check_planes(), it's a cleaner way to do this. (Ville) Changes since v4: - Clear plane links in icl_check_nv12_planes() for clarity. - Only pass crtc_state to icl_check_nv12_planes(). - Use for_each_new_intel_plane_in_state() in icl_check_nv12_planes. - Rename aux to linked. (Ville) Signed-off-by: Maarten Lankhorst Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20181022135152.15324-1-maarten.lankhorst@linux.intel.com [mlankhorst: Change bool slave to u32, to satisfy checkpatch] [mlankhorst: Add WARN_ON's based on Ville's suggestion] --- drivers/gpu/drm/i915/intel_pm.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index f42b8c319046..9ba39a9c7d1c 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5153,11 +5153,12 @@ skl_ddb_add_affected_planes(struct intel_crtc_state *cstate) struct intel_atomic_state *intel_state = to_intel_atomic_state(state); struct skl_ddb_allocation *new_ddb = &intel_state->wm_results.ddb; struct skl_ddb_allocation *cur_ddb = &dev_priv->wm.skl_hw.ddb; - struct drm_plane_state *plane_state; struct drm_plane *plane; enum pipe pipe = intel_crtc->pipe; drm_for_each_plane_mask(plane, dev, cstate->base.plane_mask) { + struct drm_plane_state *plane_state; + struct intel_plane *linked; enum plane_id plane_id = to_intel_plane(plane)->id; if (skl_ddb_entry_equal(&cur_ddb->plane[pipe][plane_id], @@ -5169,6 +5170,15 @@ skl_ddb_add_affected_planes(struct intel_crtc_state *cstate) plane_state = drm_atomic_get_plane_state(state, plane); if (IS_ERR(plane_state)) return PTR_ERR(plane_state); + + /* Make sure linked plane is updated too */ + linked = to_intel_plane_state(plane_state)->linked_plane; + if (!linked) + continue; + + plane_state = drm_atomic_get_plane_state(state, &linked->base); + if (IS_ERR(plane_state)) + return PTR_ERR(plane_state); } return 0; -- cgit From b048a00b3d9635141c7b1d4eabf6cff869a92238 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Thu, 18 Oct 2018 13:51:30 +0200 Subject: drm/i915/gen11: Handle watermarks correctly for separate Y/UV planes, v2. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Skylake style watermarks program the UV parameters into wm->uv_wm, and have a separate DDB allocation for UV blocks into the same plane. Gen11 watermarks have a separate plane for Y and UV, with separate mechanisms. The simplest way to make it work is to keep the current way of programming watermarks and calculate the Y and UV plane watermarks from the master plane. Changes since v1: - Constify crtc_state where possible. - Make separate paths for planar formats in skl_build_pipe_wm() (Matt) - Make separate paths for calculating total data rate. (Matt) - Make sure UV watermarks are unused on gen11+ by adding a WARN. (Matt) Signed-off-by: Maarten Lankhorst Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20181018115134.9061-5-maarten.lankhorst@linux.intel.com --- drivers/gpu/drm/i915/intel_pm.c | 301 +++++++++++++++++++++++++++------------- 1 file changed, 207 insertions(+), 94 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 9ba39a9c7d1c..7b49b3c2f9e9 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3814,7 +3814,7 @@ static u16 intel_get_ddb_size(struct drm_i915_private *dev_priv, } static void -skl_ddb_get_pipe_allocation_limits(struct drm_device *dev, +skl_ddb_get_pipe_allocation_limits(struct drm_i915_private *dev_priv, const struct intel_crtc_state *cstate, const u64 total_data_rate, struct skl_ddb_allocation *ddb, @@ -3823,7 +3823,6 @@ skl_ddb_get_pipe_allocation_limits(struct drm_device *dev, { struct drm_atomic_state *state = cstate->base.state; struct intel_atomic_state *intel_state = to_intel_atomic_state(state); - struct drm_i915_private *dev_priv = to_i915(dev); struct drm_crtc *for_crtc = cstate->base.crtc; const struct drm_crtc_state *crtc_state; const struct drm_crtc *crtc; @@ -3945,14 +3944,9 @@ skl_ddb_get_hw_plane_state(struct drm_i915_private *dev_priv, val & PLANE_CTL_ALPHA_MASK); val = I915_READ(PLANE_BUF_CFG(pipe, plane_id)); - /* - * FIXME: add proper NV12 support for ICL. Avoid reading unclaimed - * registers for now. - */ - if (INTEL_GEN(dev_priv) < 11) + if (fourcc == DRM_FORMAT_NV12 && INTEL_GEN(dev_priv) < 11) { val2 = I915_READ(PLANE_NV12_BUF_CFG(pipe, plane_id)); - if (fourcc == DRM_FORMAT_NV12) { skl_ddb_entry_init_from_hw(dev_priv, &ddb->plane[pipe][plane_id], val2); skl_ddb_entry_init_from_hw(dev_priv, @@ -4141,11 +4135,11 @@ int skl_check_pipe_max_pixel_rate(struct intel_crtc *intel_crtc, static u64 skl_plane_relative_data_rate(const struct intel_crtc_state *cstate, - const struct drm_plane_state *pstate, + const struct intel_plane_state *intel_pstate, const int plane) { - struct intel_plane *intel_plane = to_intel_plane(pstate->plane); - struct intel_plane_state *intel_pstate = to_intel_plane_state(pstate); + struct intel_plane *intel_plane = + to_intel_plane(intel_pstate->base.plane); uint32_t data_rate; uint32_t width = 0, height = 0; struct drm_framebuffer *fb; @@ -4156,7 +4150,7 @@ skl_plane_relative_data_rate(const struct intel_crtc_state *cstate, if (!intel_pstate->base.visible) return 0; - fb = pstate->fb; + fb = intel_pstate->base.fb; format = fb->format->format; if (intel_plane->id == PLANE_CURSOR) @@ -4206,25 +4200,80 @@ skl_get_total_relative_data_rate(struct intel_crtc_state *intel_cstate, drm_atomic_crtc_state_for_each_plane_state(plane, pstate, cstate) { enum plane_id plane_id = to_intel_plane(plane)->id; u64 rate; + const struct intel_plane_state *intel_pstate = + to_intel_plane_state(pstate); /* packed/y */ rate = skl_plane_relative_data_rate(intel_cstate, - pstate, 0); + intel_pstate, 0); plane_data_rate[plane_id] = rate; - total_data_rate += rate; /* uv-plane */ rate = skl_plane_relative_data_rate(intel_cstate, - pstate, 1); + intel_pstate, 1); uv_plane_data_rate[plane_id] = rate; - total_data_rate += rate; } return total_data_rate; } +static u64 +icl_get_total_relative_data_rate(struct intel_crtc_state *intel_cstate, + u64 *plane_data_rate) +{ + struct drm_crtc_state *cstate = &intel_cstate->base; + struct drm_atomic_state *state = cstate->state; + struct drm_plane *plane; + const struct drm_plane_state *pstate; + u64 total_data_rate = 0; + + if (WARN_ON(!state)) + return 0; + + /* Calculate and cache data rate for each plane */ + drm_atomic_crtc_state_for_each_plane_state(plane, pstate, cstate) { + const struct intel_plane_state *intel_pstate = + to_intel_plane_state(pstate); + enum plane_id plane_id = to_intel_plane(plane)->id; + u64 rate; + + if (!intel_pstate->linked_plane) { + rate = skl_plane_relative_data_rate(intel_cstate, + intel_pstate, 0); + plane_data_rate[plane_id] = rate; + total_data_rate += rate; + } else { + enum plane_id y_plane_id; + + /* + * The slave plane might not iterate in + * drm_atomic_crtc_state_for_each_plane_state(), + * and needs the master plane state which may be + * NULL if we try get_new_plane_state(), so we + * always calculate from the master. + */ + if (intel_pstate->slave) + continue; + + /* Y plane rate is calculated on the slave */ + rate = skl_plane_relative_data_rate(intel_cstate, + intel_pstate, 0); + y_plane_id = intel_pstate->linked_plane->id; + plane_data_rate[y_plane_id] = rate; + total_data_rate += rate; + + rate = skl_plane_relative_data_rate(intel_cstate, + intel_pstate, 1); + plane_data_rate[plane_id] = rate; + total_data_rate += rate; + } + } + + return total_data_rate; +} + static uint16_t skl_ddb_min_alloc(const struct drm_plane_state *pstate, const int plane) { @@ -4297,15 +4346,25 @@ skl_ddb_calc_min(const struct intel_crtc_state *cstate, int num_active, drm_atomic_crtc_state_for_each_plane_state(plane, pstate, &cstate->base) { enum plane_id plane_id = to_intel_plane(plane)->id; + struct intel_plane_state *plane_state = to_intel_plane_state(pstate); if (plane_id == PLANE_CURSOR) continue; - if (!pstate->visible) + /* slave plane must be invisible and calculated from master */ + if (!pstate->visible || WARN_ON(plane_state->slave)) continue; - minimum[plane_id] = skl_ddb_min_alloc(pstate, 0); - uv_minimum[plane_id] = skl_ddb_min_alloc(pstate, 1); + if (!plane_state->linked_plane) { + minimum[plane_id] = skl_ddb_min_alloc(pstate, 0); + uv_minimum[plane_id] = skl_ddb_min_alloc(pstate, 1); + } else { + enum plane_id y_plane_id = + plane_state->linked_plane->id; + + minimum[y_plane_id] = skl_ddb_min_alloc(pstate, 0); + minimum[plane_id] = skl_ddb_min_alloc(pstate, 1); + } } minimum[PLANE_CURSOR] = skl_cursor_allocation(num_active); @@ -4317,7 +4376,7 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, { struct drm_atomic_state *state = cstate->base.state; struct drm_crtc *crtc = cstate->base.crtc; - struct drm_device *dev = crtc->dev; + struct drm_i915_private *dev_priv = to_i915(crtc->dev); struct intel_crtc *intel_crtc = to_intel_crtc(crtc); enum pipe pipe = intel_crtc->pipe; struct skl_ddb_entry *alloc = &cstate->wm.skl.ddb; @@ -4343,11 +4402,18 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, return 0; } - total_data_rate = skl_get_total_relative_data_rate(cstate, - plane_data_rate, - uv_plane_data_rate); - skl_ddb_get_pipe_allocation_limits(dev, cstate, total_data_rate, ddb, - alloc, &num_active); + if (INTEL_GEN(dev_priv) < 11) + total_data_rate = + skl_get_total_relative_data_rate(cstate, + plane_data_rate, + uv_plane_data_rate); + else + total_data_rate = + icl_get_total_relative_data_rate(cstate, + plane_data_rate); + + skl_ddb_get_pipe_allocation_limits(dev_priv, cstate, total_data_rate, + ddb, alloc, &num_active); alloc_size = skl_ddb_entry_size(alloc); if (alloc_size == 0) return 0; @@ -4417,6 +4483,9 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, uv_plane_blocks = uv_minimum[plane_id]; uv_plane_blocks += div64_u64(alloc_size * uv_data_rate, total_data_rate); + /* Gen11+ uses a separate plane for UV watermarks */ + WARN_ON(INTEL_GEN(dev_priv) >= 11 && uv_plane_blocks); + if (uv_data_rate) { ddb->uv_plane[pipe][plane_id].start = start; ddb->uv_plane[pipe][plane_id].end = @@ -4473,7 +4542,7 @@ static uint_fixed_16_16_t skl_wm_method2(uint32_t pixel_rate, } static uint_fixed_16_16_t -intel_get_linetime_us(struct intel_crtc_state *cstate) +intel_get_linetime_us(const struct intel_crtc_state *cstate) { uint32_t pixel_rate; uint32_t crtc_htotal; @@ -4517,7 +4586,7 @@ skl_adjusted_plane_pixel_rate(const struct intel_crtc_state *cstate, static int skl_compute_plane_wm_params(const struct drm_i915_private *dev_priv, - struct intel_crtc_state *cstate, + const struct intel_crtc_state *cstate, const struct intel_plane_state *intel_pstate, struct skl_wm_params *wp, int plane_id) { @@ -4624,7 +4693,7 @@ skl_compute_plane_wm_params(const struct drm_i915_private *dev_priv, } static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, - struct intel_crtc_state *cstate, + const struct intel_crtc_state *cstate, const struct intel_plane_state *intel_pstate, uint16_t ddb_allocation, int level, @@ -4784,38 +4853,22 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, static int skl_compute_wm_levels(const struct drm_i915_private *dev_priv, struct skl_ddb_allocation *ddb, - struct intel_crtc_state *cstate, + const struct intel_crtc_state *cstate, const struct intel_plane_state *intel_pstate, + uint16_t ddb_blocks, const struct skl_wm_params *wm_params, struct skl_plane_wm *wm, - int plane_id) + struct skl_wm_level *levels) { - struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc); - struct drm_plane *plane = intel_pstate->base.plane; - struct intel_plane *intel_plane = to_intel_plane(plane); - uint16_t ddb_blocks; - enum pipe pipe = intel_crtc->pipe; int level, max_level = ilk_wm_max_level(dev_priv); - enum plane_id intel_plane_id = intel_plane->id; + struct skl_wm_level *result_prev = &levels[0]; int ret; if (WARN_ON(!intel_pstate->base.fb)) return -EINVAL; - ddb_blocks = plane_id ? - skl_ddb_entry_size(&ddb->uv_plane[pipe][intel_plane_id]) : - skl_ddb_entry_size(&ddb->plane[pipe][intel_plane_id]); - for (level = 0; level <= max_level; level++) { - struct skl_wm_level *result = plane_id ? &wm->uv_wm[level] : - &wm->wm[level]; - struct skl_wm_level *result_prev; - - if (level) - result_prev = plane_id ? &wm->uv_wm[level - 1] : - &wm->wm[level - 1]; - else - result_prev = plane_id ? &wm->uv_wm[0] : &wm->wm[0]; + struct skl_wm_level *result = &levels[level]; ret = skl_compute_plane_wm(dev_priv, cstate, @@ -4827,6 +4880,8 @@ skl_compute_wm_levels(const struct drm_i915_private *dev_priv, result); if (ret) return ret; + + result_prev = result; } if (intel_pstate->base.fb->format->format == DRM_FORMAT_NV12) @@ -4836,7 +4891,7 @@ skl_compute_wm_levels(const struct drm_i915_private *dev_priv, } static uint32_t -skl_compute_linetime_wm(struct intel_crtc_state *cstate) +skl_compute_linetime_wm(const struct intel_crtc_state *cstate) { struct drm_atomic_state *state = cstate->base.state; struct drm_i915_private *dev_priv = to_i915(state->dev); @@ -4858,7 +4913,7 @@ skl_compute_linetime_wm(struct intel_crtc_state *cstate) return linetime_wm; } -static void skl_compute_transition_wm(struct intel_crtc_state *cstate, +static void skl_compute_transition_wm(const struct intel_crtc_state *cstate, struct skl_wm_params *wp, struct skl_wm_level *wm_l0, uint16_t ddb_allocation, @@ -4925,16 +4980,101 @@ exit: trans_wm->plane_en = false; } +static int __skl_build_plane_wm_single(struct skl_ddb_allocation *ddb, + struct skl_pipe_wm *pipe_wm, + enum plane_id plane_id, + const struct intel_crtc_state *cstate, + const struct intel_plane_state *pstate, + int color_plane) +{ + struct drm_i915_private *dev_priv = to_i915(pstate->base.plane->dev); + struct skl_plane_wm *wm = &pipe_wm->planes[plane_id]; + enum pipe pipe = to_intel_plane(pstate->base.plane)->pipe; + struct skl_wm_params wm_params; + uint16_t ddb_blocks = skl_ddb_entry_size(&ddb->plane[pipe][plane_id]); + int ret; + + ret = skl_compute_plane_wm_params(dev_priv, cstate, pstate, + &wm_params, color_plane); + if (ret) + return ret; + + ret = skl_compute_wm_levels(dev_priv, ddb, cstate, pstate, + ddb_blocks, &wm_params, wm, wm->wm); + + if (ret) + return ret; + + skl_compute_transition_wm(cstate, &wm_params, &wm->wm[0], + ddb_blocks, &wm->trans_wm); + + return 0; +} + +static int skl_build_plane_wm_single(struct skl_ddb_allocation *ddb, + struct skl_pipe_wm *pipe_wm, + const struct intel_crtc_state *cstate, + const struct intel_plane_state *pstate) +{ + enum plane_id plane_id = to_intel_plane(pstate->base.plane)->id; + + return __skl_build_plane_wm_single(ddb, pipe_wm, plane_id, cstate, pstate, 0); +} + +static int skl_build_plane_wm_planar(struct skl_ddb_allocation *ddb, + struct skl_pipe_wm *pipe_wm, + const struct intel_crtc_state *cstate, + const struct intel_plane_state *pstate) +{ + struct intel_plane *plane = to_intel_plane(pstate->base.plane); + struct drm_i915_private *dev_priv = to_i915(plane->base.dev); + enum plane_id plane_id = plane->id; + struct skl_plane_wm *wm = &pipe_wm->planes[plane_id]; + struct skl_wm_params wm_params; + enum pipe pipe = plane->pipe; + uint16_t ddb_blocks = skl_ddb_entry_size(&ddb->plane[pipe][plane_id]); + int ret; + + ret = __skl_build_plane_wm_single(ddb, pipe_wm, plane_id, cstate, pstate, 0); + if (ret) + return ret; + + /* uv plane watermarks must also be validated for NV12/Planar */ + ddb_blocks = skl_ddb_entry_size(&ddb->uv_plane[pipe][plane_id]); + + ret = skl_compute_plane_wm_params(dev_priv, cstate, pstate, &wm_params, 1); + if (ret) + return ret; + + return skl_compute_wm_levels(dev_priv, ddb, cstate, pstate, + ddb_blocks, &wm_params, wm, wm->uv_wm); +} + +static int icl_build_plane_wm_planar(struct skl_ddb_allocation *ddb, + struct skl_pipe_wm *pipe_wm, + const struct intel_crtc_state *cstate, + const struct intel_plane_state *pstate) +{ + int ret; + enum plane_id y_plane_id = pstate->linked_plane->id; + enum plane_id uv_plane_id = to_intel_plane(pstate->base.plane)->id; + + ret = __skl_build_plane_wm_single(ddb, pipe_wm, y_plane_id, + cstate, pstate, 0); + if (ret) + return ret; + + return __skl_build_plane_wm_single(ddb, pipe_wm, uv_plane_id, + cstate, pstate, 1); +} + static int skl_build_pipe_wm(struct intel_crtc_state *cstate, struct skl_ddb_allocation *ddb, struct skl_pipe_wm *pipe_wm) { - struct drm_device *dev = cstate->base.crtc->dev; struct drm_crtc_state *crtc_state = &cstate->base; - const struct drm_i915_private *dev_priv = to_i915(dev); struct drm_plane *plane; const struct drm_plane_state *pstate; - struct skl_plane_wm *wm; int ret; /* @@ -4946,44 +5086,21 @@ static int skl_build_pipe_wm(struct intel_crtc_state *cstate, drm_atomic_crtc_state_for_each_plane_state(plane, pstate, crtc_state) { const struct intel_plane_state *intel_pstate = to_intel_plane_state(pstate); - enum plane_id plane_id = to_intel_plane(plane)->id; - struct skl_wm_params wm_params; - enum pipe pipe = to_intel_crtc(cstate->base.crtc)->pipe; - uint16_t ddb_blocks; - wm = &pipe_wm->planes[plane_id]; - ddb_blocks = skl_ddb_entry_size(&ddb->plane[pipe][plane_id]); + /* Watermarks calculated in master */ + if (intel_pstate->slave) + continue; - ret = skl_compute_plane_wm_params(dev_priv, cstate, - intel_pstate, &wm_params, 0); - if (ret) - return ret; + if (intel_pstate->linked_plane) + ret = icl_build_plane_wm_planar(ddb, pipe_wm, cstate, intel_pstate); + else if (intel_pstate->base.fb && + intel_pstate->base.fb->format->format == DRM_FORMAT_NV12) + ret = skl_build_plane_wm_planar(ddb, pipe_wm, cstate, intel_pstate); + else + ret = skl_build_plane_wm_single(ddb, pipe_wm, cstate, intel_pstate); - ret = skl_compute_wm_levels(dev_priv, ddb, cstate, - intel_pstate, &wm_params, wm, 0); if (ret) return ret; - - skl_compute_transition_wm(cstate, &wm_params, &wm->wm[0], - ddb_blocks, &wm->trans_wm); - - /* uv plane watermarks must also be validated for NV12/Planar */ - if (wm_params.is_planar) { - memset(&wm_params, 0, sizeof(struct skl_wm_params)); - wm->is_planar = true; - - ret = skl_compute_plane_wm_params(dev_priv, cstate, - intel_pstate, - &wm_params, 1); - if (ret) - return ret; - - ret = skl_compute_wm_levels(dev_priv, ddb, cstate, - intel_pstate, &wm_params, - wm, 1); - if (ret) - return ret; - } } pipe_wm->linetime = skl_compute_linetime_wm(cstate); @@ -5034,12 +5151,7 @@ static void skl_write_plane_wm(struct intel_crtc *intel_crtc, skl_write_wm_level(dev_priv, PLANE_WM_TRANS(pipe, plane_id), &wm->trans_wm); - /* FIXME: add proper NV12 support for ICL. */ - if (INTEL_GEN(dev_priv) >= 11) - return skl_ddb_entry_write(dev_priv, - PLANE_BUF_CFG(pipe, plane_id), - &ddb->plane[pipe][plane_id]); - if (wm->is_planar) { + if (wm->is_planar && INTEL_GEN(dev_priv) < 11) { skl_ddb_entry_write(dev_priv, PLANE_BUF_CFG(pipe, plane_id), &ddb->uv_plane[pipe][plane_id]); skl_ddb_entry_write(dev_priv, @@ -5048,7 +5160,8 @@ static void skl_write_plane_wm(struct intel_crtc *intel_crtc, } else { skl_ddb_entry_write(dev_priv, PLANE_BUF_CFG(pipe, plane_id), &ddb->plane[pipe][plane_id]); - I915_WRITE(PLANE_NV12_BUF_CFG(pipe, plane_id), 0x0); + if (INTEL_GEN(dev_priv) < 11) + I915_WRITE(PLANE_NV12_BUF_CFG(pipe, plane_id), 0x0); } } -- cgit From 5d6f36b27d2764f3dc940606ee6b7ec5c669af3e Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 23 Oct 2018 21:21:02 +0300 Subject: drm/i915: Don't apply the 16Gb DIMM wm latency w/a to BXT/GLK MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The 16Gb DIMM w/a is not applicable to BXT or GLK. Limit it to the appropriate platforms. This was especially harsh on GLK since we don't even try to read the DIMM information on that platforms, hence valid_dimm was always false and thus we always tried to apply the w/a. Furthermore the w/a pushed the level 0 latency above the level 1 latency, which doesn't really make sense. v2: Do the check when populating is_16gb_dimm (Mahesh) Cc: Mahesh Kumar Cc: Maarten Lankhorst Fixes: 86b592876cb6 ("drm/i915: Implement 16GB dimm wa for latency level-0") Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20181023182102.31549-1-ville.syrjala@linux.intel.com Reviewed-by: Rodrigo Vivi Reviewed-by: Mahesh Kumar --- drivers/gpu/drm/i915/intel_pm.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 7b49b3c2f9e9..688298cf1aaf 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2881,8 +2881,7 @@ static void intel_read_wm_latency(struct drm_i915_private *dev_priv, * any underrun. If not able to get Dimm info assume 16GB dimm * to avoid any underrun. */ - if (!dev_priv->dram_info.valid_dimm || - dev_priv->dram_info.is_16gb_dimm) + if (dev_priv->dram_info.is_16gb_dimm) wm[0] += 1; } else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) { -- cgit From 9e7833758b9feebc37b9988d13b017534c90a4a2 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Fri, 26 Oct 2018 12:51:42 -0700 Subject: drm/i915: Prefer IS_GEN check with bitmask. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Whenever possible we should stick with IS_GEN checks. Bitmaks has been introduced on commit ae7617f0ef18 ("drm/i915: Allow optimized platform checks") for efficiency. Let's stick with it whenever possible. This patch was generated with coccinelle: spatch -sp_file is_gen.cocci *{c,h} --in-place is_gen.cocci: @gen2@ expression e; @@ -INTEL_GEN(e) == 2 +IS_GEN2(e) @gen3@ expression e; @@ -INTEL_GEN(e) == 3 +IS_GEN3(e) @gen4@ expression e; @@ -INTEL_GEN(e) == 4 +IS_GEN4(e) @gen5@ expression e; @@ -INTEL_GEN(e) == 5 +IS_GEN5(e) @gen6@ expression e; @@ -INTEL_GEN(e) == 6 +IS_GEN6(e) @gen7@ expression e; @@ -INTEL_GEN(e) == 7 +IS_GEN7(e) @gen8@ expression e; @@ -INTEL_GEN(e) == 8 +IS_GEN8(e) @gen9@ expression e; @@ -INTEL_GEN(e) == 9 +IS_GEN9(e) @gen10@ expression e; @@ -INTEL_GEN(e) == 10 +IS_GEN10(e) @gen11@ expression e; @@ -INTEL_GEN(e) == 11 +IS_GEN11(e) Cc: Tvrtko Ursulin Signed-off-by: Rodrigo Vivi Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20181026195143.20353-1-rodrigo.vivi@intel.com --- drivers/gpu/drm/i915/intel_pm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 688298cf1aaf..bc70f6bb86ae 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4741,13 +4741,13 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, selected_result = method2; } else if (ddb_allocation >= fixed16_to_u32_round_up(wp->plane_blocks_per_line)) { - if (INTEL_GEN(dev_priv) == 9 && + if (IS_GEN9(dev_priv) && !IS_GEMINILAKE(dev_priv)) selected_result = min_fixed16(method1, method2); else selected_result = method2; } else if (latency >= wp->linetime_us) { - if (INTEL_GEN(dev_priv) == 9 && + if (IS_GEN9(dev_priv) && !IS_GEMINILAKE(dev_priv)) selected_result = min_fixed16(method1, method2); else -- cgit From 1ca2b067d07b491bd82bbaf235841b2a9b3d0c09 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Fri, 26 Oct 2018 13:03:17 -0700 Subject: drm/i915: Simplify has_sagv function The specially case for SKL for not controlled sagv is already taken care inside intel_enable_sagv, so there's no need to duplicate the check here. v2: Go one step further and remove skl special case. (Jani) v3: Separate runtime status handle from has_sagv flag. v4: Go back and accept simple Jani proposed solution. Signed-off-by: Rodrigo Vivi Reviewed-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20181026200317.21726-1-rodrigo.vivi@intel.com --- drivers/gpu/drm/i915/intel_pm.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index bc70f6bb86ae..82c82e233154 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3611,15 +3611,8 @@ static bool skl_needs_memory_bw_wa(struct intel_atomic_state *state) static bool intel_has_sagv(struct drm_i915_private *dev_priv) { - if (IS_KABYLAKE(dev_priv) || IS_COFFEELAKE(dev_priv) || - IS_CANNONLAKE(dev_priv) || IS_ICELAKE(dev_priv)) - return true; - - if (IS_SKYLAKE(dev_priv) && - dev_priv->sagv_status != I915_SAGV_NOT_CONTROLLED) - return true; - - return false; + return (IS_GEN9_BC(dev_priv) || INTEL_GEN(dev_priv) >= 10) && + dev_priv->sagv_status != I915_SAGV_NOT_CONTROLLED; } /* -- cgit From 28b2f4e19600c62021e73f9093174ed9989a73c5 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Wed, 31 Oct 2018 09:28:43 -0700 Subject: drm/i915: Kill WA 0826 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to BSpec this is not needed anymore: "This workaround is no longer needed since NV12 support is dropped for the affected projects. " Cc: Maarten Lankhorst Cc: Ville Syrjälä Signed-off-by: Rodrigo Vivi Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20181031162845.12419-2-rodrigo.vivi@intel.com --- drivers/gpu/drm/i915/intel_pm.c | 11 ----------- 1 file changed, 11 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 82c82e233154..2c3dc10f0255 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4823,17 +4823,6 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, } } - /* - * Display WA #826 (SKL:ALL, BXT:ALL) & #1059 (CNL:A) - * disable wm level 1-7 on NV12 planes - */ - if (wp->is_planar && level >= 1 && - (IS_SKYLAKE(dev_priv) || IS_BROXTON(dev_priv) || - IS_CNL_REVID(dev_priv, CNL_REVID_A0, CNL_REVID_A0))) { - result->plane_en = false; - return 0; - } - /* The number of lines are ignored for the level 0 watermark. */ result->plane_res_b = res_blocks; result->plane_res_l = res_lines; -- cgit From 622b3f68139e93266447ddb584ad7e057c85627e Mon Sep 17 00:00:00 2001 From: Radhakrishna Sripada Date: Tue, 30 Oct 2018 01:45:01 -0700 Subject: drm/i915/icl: Add WaEnable32PlaneMode Gen11 Display suports 32 planes in total. Enable the new format in context status to be used and expanded to 32 planes. V2: Move the WA to display WA's(Chris) Cc: Chris Wilson Cc: Michel Thierry Cc: James Ausmus Reviewed-by: Anusha Srivatsa Signed-off-by: Radhakrishna Sripada Signed-off-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20181030084504.21537-1-radhakrishna.sripada@intel.com --- drivers/gpu/drm/i915/intel_pm.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 2c3dc10f0255..9da8ff263d36 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -8854,6 +8854,10 @@ static void icl_init_clock_gating(struct drm_i915_private *dev_priv) /* This is not an Wa. Enable to reduce Sampler power */ I915_WRITE(GEN10_DFR_RATIO_EN_AND_CHICKEN, I915_READ(GEN10_DFR_RATIO_EN_AND_CHICKEN) & ~DFR_DISABLE); + + /* WaEnable32PlaneMode:icl */ + I915_WRITE(GEN9_CSFE_CHICKEN1_RCS, + _MASKED_BIT_ENABLE(GEN11_ENABLE_32_PLANE_MODE)); } static void cnp_init_clock_gating(struct drm_i915_private *dev_priv) -- cgit From acde44b5008671b06a8a1c7c6443b9f54ef4be03 Mon Sep 17 00:00:00 2001 From: José Roberto de Souza Date: Wed, 7 Nov 2018 16:16:45 -0800 Subject: drm/i915: Move FBC init and cleanup calls to modeset functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Although FBC helps save power it do not belongs to power management also the cleanup was placed in i915_driver_unload() also not a good place. intel_modeset_init()/intel_modeset_cleanup() are better places also this will help make easy disable features that depends in display being enabled in driver. Cc: Jani Nikula Cc: Ville Syrjälä Signed-off-by: José Roberto de Souza Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20181108001647.11276-2-jose.souza@intel.com --- drivers/gpu/drm/i915/intel_pm.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 9da8ff263d36..dc034617febb 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -9435,8 +9435,6 @@ void intel_init_clock_gating_hooks(struct drm_i915_private *dev_priv) /* Set up chip specific power management-related functions */ void intel_init_pm(struct drm_i915_private *dev_priv) { - intel_fbc_init(dev_priv); - /* For cxsr */ if (IS_PINEVIEW(dev_priv)) i915_pineview_get_mem_freq(dev_priv); -- cgit From 53cc688036681cc17f6db43744db6bb7703246fe Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 1 Nov 2018 17:05:59 +0200 Subject: drm/i915: Generalize skl_ddb_allocation_overlaps() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make skl_ddb_allocation_overlaps() useful for other callers besides skl_update_crtcs(). We'll need it to do plane updates as well. And while we're here we can reduce the stack utilization a bit by noting that each struct skl_ddb_entry is 4 bytes whereas a pointer to one is 8 bytes (on 64bit). So we'll switch to an array of structs from the array of pointers we used before. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20181101150605.18235-9-ville.syrjala@linux.intel.com Reviewed-by: Rodrigo Vivi --- drivers/gpu/drm/i915/intel_pm.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index dc034617febb..5df7f6e1ab5e 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5186,16 +5186,15 @@ static inline bool skl_ddb_entries_overlap(const struct skl_ddb_entry *a, return a->start < b->end && b->start < a->end; } -bool skl_ddb_allocation_overlaps(struct drm_i915_private *dev_priv, - const struct skl_ddb_entry **entries, - const struct skl_ddb_entry *ddb, - int ignore) +bool skl_ddb_allocation_overlaps(const struct skl_ddb_entry *ddb, + const struct skl_ddb_entry entries[], + int num_entries, int ignore_idx) { - enum pipe pipe; + int i; - for_each_pipe(dev_priv, pipe) { - if (pipe != ignore && entries[pipe] && - skl_ddb_entries_overlap(ddb, entries[pipe])) + for (i = 0; i < num_entries; i++) { + if (i != ignore_idx && + skl_ddb_entries_overlap(ddb, &entries[i])) return true; } -- cgit From f255c624c11a5f58ff7c866f2bef6d850905dc20 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 8 Nov 2018 17:10:13 +0200 Subject: drm/i915: Move skip_intermediate_wm handling into ilk_compute_intermediate_wm() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No point in cluttering the common codepaths with the skip_intermediate_wm handling. Just move it into ilk_compute_intermediate_wm() as those are the only platforms using this. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20181108151013.24064-1-ville.syrjala@linux.intel.com Reviewed-by: Maarten Lankhorst #irc --- drivers/gpu/drm/i915/intel_pm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 5df7f6e1ab5e..27498ded4949 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3159,7 +3159,8 @@ static int ilk_compute_intermediate_wm(struct drm_device *dev, * and after the vblank. */ *a = newstate->wm.ilk.optimal; - if (!newstate->base.active || drm_atomic_crtc_needs_modeset(&newstate->base)) + if (!newstate->base.active || drm_atomic_crtc_needs_modeset(&newstate->base) || + intel_state->skip_intermediate_wm) return 0; a->pipe_enabled |= b->pipe_enabled; -- cgit From 03981c6ebec4fc7056b9b45f847393aeac90d060 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 14 Nov 2018 19:34:40 +0200 Subject: drm/i915: Disable LP3 watermarks on all SNB machines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I have a Thinkpad X220 Tablet in my hands that is losing vblank interrupts whenever LP3 watermarks are used. If I nudge the latency value written to the WM3 register just by one in either direction the problem disappears. That to me suggests that the punit will not enter the corrsponding powersave mode (MPLL shutdown IIRC) unless the latency value in the register matches exactly what we read from SSKPD. Ie. it's not really a latency value but rather just a cookie by which the punit can identify the desired power saving state. On HSW/BDW this was changed such that we actually just write the WM level number into those bits, which makes much more sense given the observed behaviour. We could try to handle this by disallowing LP3 watermarks only when vblank interrupts are enabled but we'd first have to prove that only vblank interrupts are affected, which seems unlikely. Also we can't grab the wm mutex from the vblank enable/disable hooks because those are called with various spinlocks held. Thus we'd have to redesigne the watermark locking. So to play it safe and keep the code simple we simply disable LP3 watermarks on all SNB machines. To do that we simply zero out the latency values for watermark level 3, and we adjust the watermark computation to check for that. The behaviour now matches that of the g4x/vlv/skl wm code in the presence of a zeroed latency value. v2: s/USHRT_MAX/U32_MAX/ for consistency with the types (Chris) Cc: stable@vger.kernel.org Cc: Chris Wilson Acked-by: Chris Wilson Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=101269 Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=103713 Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20181114173440.6730-1-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/intel_pm.c | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 27498ded4949..897a791662c5 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2493,6 +2493,9 @@ static uint32_t ilk_compute_pri_wm(const struct intel_crtc_state *cstate, uint32_t method1, method2; int cpp; + if (mem_value == 0) + return U32_MAX; + if (!intel_wm_plane_visible(cstate, pstate)) return 0; @@ -2522,6 +2525,9 @@ static uint32_t ilk_compute_spr_wm(const struct intel_crtc_state *cstate, uint32_t method1, method2; int cpp; + if (mem_value == 0) + return U32_MAX; + if (!intel_wm_plane_visible(cstate, pstate)) return 0; @@ -2545,6 +2551,9 @@ static uint32_t ilk_compute_cur_wm(const struct intel_crtc_state *cstate, { int cpp; + if (mem_value == 0) + return U32_MAX; + if (!intel_wm_plane_visible(cstate, pstate)) return 0; @@ -3008,6 +3017,34 @@ static void snb_wm_latency_quirk(struct drm_i915_private *dev_priv) intel_print_wm_latency(dev_priv, "Cursor", dev_priv->wm.cur_latency); } +static void snb_wm_lp3_irq_quirk(struct drm_i915_private *dev_priv) +{ + /* + * On some SNB machines (Thinkpad X220 Tablet at least) + * LP3 usage can cause vblank interrupts to be lost. + * The DEIIR bit will go high but it looks like the CPU + * never gets interrupted. + * + * It's not clear whether other interrupt source could + * be affected or if this is somehow limited to vblank + * interrupts only. To play it safe we disable LP3 + * watermarks entirely. + */ + if (dev_priv->wm.pri_latency[3] == 0 && + dev_priv->wm.spr_latency[3] == 0 && + dev_priv->wm.cur_latency[3] == 0) + return; + + dev_priv->wm.pri_latency[3] = 0; + dev_priv->wm.spr_latency[3] = 0; + dev_priv->wm.cur_latency[3] = 0; + + DRM_DEBUG_KMS("LP3 watermarks disabled due to potential for lost interrupts\n"); + intel_print_wm_latency(dev_priv, "Primary", dev_priv->wm.pri_latency); + intel_print_wm_latency(dev_priv, "Sprite", dev_priv->wm.spr_latency); + intel_print_wm_latency(dev_priv, "Cursor", dev_priv->wm.cur_latency); +} + static void ilk_setup_wm_latency(struct drm_i915_private *dev_priv) { intel_read_wm_latency(dev_priv, dev_priv->wm.pri_latency); @@ -3024,8 +3061,10 @@ static void ilk_setup_wm_latency(struct drm_i915_private *dev_priv) intel_print_wm_latency(dev_priv, "Sprite", dev_priv->wm.spr_latency); intel_print_wm_latency(dev_priv, "Cursor", dev_priv->wm.cur_latency); - if (IS_GEN6(dev_priv)) + if (IS_GEN6(dev_priv)) { snb_wm_latency_quirk(dev_priv); + snb_wm_lp3_irq_quirk(dev_priv); + } } static void skl_setup_wm_latency(struct drm_i915_private *dev_priv) -- cgit