142a0d256SVille Syrjälä // SPDX-License-Identifier: MIT 242a0d256SVille Syrjälä /* 342a0d256SVille Syrjälä * Copyright © 2022 Intel Corporation 442a0d256SVille Syrjälä */ 542a0d256SVille Syrjälä 642a0d256SVille Syrjälä #include <drm/drm_blend.h> 742a0d256SVille Syrjälä 842a0d256SVille Syrjälä #include "intel_atomic.h" 942a0d256SVille Syrjälä #include "intel_atomic_plane.h" 1042a0d256SVille Syrjälä #include "intel_bw.h" 1142a0d256SVille Syrjälä #include "intel_de.h" 1242a0d256SVille Syrjälä #include "intel_display.h" 1342a0d256SVille Syrjälä #include "intel_display_power.h" 1442a0d256SVille Syrjälä #include "intel_display_types.h" 1542a0d256SVille Syrjälä #include "intel_fb.h" 1642a0d256SVille Syrjälä #include "skl_watermark.h" 1742a0d256SVille Syrjälä 1842a0d256SVille Syrjälä #include "i915_drv.h" 1942a0d256SVille Syrjälä #include "i915_fixed.h" 2042a0d256SVille Syrjälä #include "i915_reg.h" 2142a0d256SVille Syrjälä #include "intel_pcode.h" 2242a0d256SVille Syrjälä #include "intel_pm.h" 2342a0d256SVille Syrjälä 2442a0d256SVille Syrjälä static void skl_sagv_disable(struct drm_i915_private *i915); 2542a0d256SVille Syrjälä 2642a0d256SVille Syrjälä /* Stores plane specific WM parameters */ 2742a0d256SVille Syrjälä struct skl_wm_params { 2842a0d256SVille Syrjälä bool x_tiled, y_tiled; 2942a0d256SVille Syrjälä bool rc_surface; 3042a0d256SVille Syrjälä bool is_planar; 3142a0d256SVille Syrjälä u32 width; 3242a0d256SVille Syrjälä u8 cpp; 3342a0d256SVille Syrjälä u32 plane_pixel_rate; 3442a0d256SVille Syrjälä u32 y_min_scanlines; 3542a0d256SVille Syrjälä u32 plane_bytes_per_line; 3642a0d256SVille Syrjälä uint_fixed_16_16_t plane_blocks_per_line; 3742a0d256SVille Syrjälä uint_fixed_16_16_t y_tile_minimum; 3842a0d256SVille Syrjälä u32 linetime_us; 3942a0d256SVille Syrjälä u32 dbuf_block_size; 4042a0d256SVille Syrjälä }; 4142a0d256SVille Syrjälä 4242a0d256SVille Syrjälä u8 intel_enabled_dbuf_slices_mask(struct drm_i915_private *i915) 4342a0d256SVille Syrjälä { 4442a0d256SVille Syrjälä u8 enabled_slices = 0; 4542a0d256SVille Syrjälä enum dbuf_slice slice; 4642a0d256SVille Syrjälä 4742a0d256SVille Syrjälä for_each_dbuf_slice(i915, slice) { 4800136429SJani Nikula if (intel_de_read(i915, DBUF_CTL_S(slice)) & DBUF_POWER_STATE) 4942a0d256SVille Syrjälä enabled_slices |= BIT(slice); 5042a0d256SVille Syrjälä } 5142a0d256SVille Syrjälä 5242a0d256SVille Syrjälä return enabled_slices; 5342a0d256SVille Syrjälä } 5442a0d256SVille Syrjälä 5542a0d256SVille Syrjälä /* 5642a0d256SVille Syrjälä * FIXME: We still don't have the proper code detect if we need to apply the WA, 5742a0d256SVille Syrjälä * so assume we'll always need it in order to avoid underruns. 5842a0d256SVille Syrjälä */ 5942a0d256SVille Syrjälä static bool skl_needs_memory_bw_wa(struct drm_i915_private *i915) 6042a0d256SVille Syrjälä { 6142a0d256SVille Syrjälä return DISPLAY_VER(i915) == 9; 6242a0d256SVille Syrjälä } 6342a0d256SVille Syrjälä 6442a0d256SVille Syrjälä static bool 6542a0d256SVille Syrjälä intel_has_sagv(struct drm_i915_private *i915) 6642a0d256SVille Syrjälä { 6742a0d256SVille Syrjälä return DISPLAY_VER(i915) >= 9 && !IS_LP(i915) && 6842a0d256SVille Syrjälä i915->display.sagv.status != I915_SAGV_NOT_CONTROLLED; 6942a0d256SVille Syrjälä } 7042a0d256SVille Syrjälä 7142a0d256SVille Syrjälä static u32 7242a0d256SVille Syrjälä intel_sagv_block_time(struct drm_i915_private *i915) 7342a0d256SVille Syrjälä { 74825477e7SRadhakrishna Sripada if (DISPLAY_VER(i915) >= 14) { 75825477e7SRadhakrishna Sripada u32 val; 76825477e7SRadhakrishna Sripada 7700136429SJani Nikula val = intel_de_read(i915, MTL_LATENCY_SAGV); 78825477e7SRadhakrishna Sripada 79825477e7SRadhakrishna Sripada return REG_FIELD_GET(MTL_LATENCY_QCLK_SAGV, val); 80825477e7SRadhakrishna Sripada } else if (DISPLAY_VER(i915) >= 12) { 8142a0d256SVille Syrjälä u32 val = 0; 8242a0d256SVille Syrjälä int ret; 8342a0d256SVille Syrjälä 8442a0d256SVille Syrjälä ret = snb_pcode_read(&i915->uncore, 8542a0d256SVille Syrjälä GEN12_PCODE_READ_SAGV_BLOCK_TIME_US, 8642a0d256SVille Syrjälä &val, NULL); 8742a0d256SVille Syrjälä if (ret) { 8842a0d256SVille Syrjälä drm_dbg_kms(&i915->drm, "Couldn't read SAGV block time!\n"); 8942a0d256SVille Syrjälä return 0; 9042a0d256SVille Syrjälä } 9142a0d256SVille Syrjälä 9242a0d256SVille Syrjälä return val; 9342a0d256SVille Syrjälä } else if (DISPLAY_VER(i915) == 11) { 9442a0d256SVille Syrjälä return 10; 9542a0d256SVille Syrjälä } else if (DISPLAY_VER(i915) == 9 && !IS_LP(i915)) { 9642a0d256SVille Syrjälä return 30; 9742a0d256SVille Syrjälä } else { 9842a0d256SVille Syrjälä return 0; 9942a0d256SVille Syrjälä } 10042a0d256SVille Syrjälä } 10142a0d256SVille Syrjälä 10242a0d256SVille Syrjälä static void intel_sagv_init(struct drm_i915_private *i915) 10342a0d256SVille Syrjälä { 10442a0d256SVille Syrjälä if (!intel_has_sagv(i915)) 10542a0d256SVille Syrjälä i915->display.sagv.status = I915_SAGV_NOT_CONTROLLED; 10642a0d256SVille Syrjälä 10742a0d256SVille Syrjälä /* 10842a0d256SVille Syrjälä * Probe to see if we have working SAGV control. 10942a0d256SVille Syrjälä * For icl+ this was already determined by intel_bw_init_hw(). 11042a0d256SVille Syrjälä */ 11142a0d256SVille Syrjälä if (DISPLAY_VER(i915) < 11) 11242a0d256SVille Syrjälä skl_sagv_disable(i915); 11342a0d256SVille Syrjälä 11442a0d256SVille Syrjälä drm_WARN_ON(&i915->drm, i915->display.sagv.status == I915_SAGV_UNKNOWN); 11542a0d256SVille Syrjälä 11642a0d256SVille Syrjälä i915->display.sagv.block_time_us = intel_sagv_block_time(i915); 11742a0d256SVille Syrjälä 11842a0d256SVille Syrjälä drm_dbg_kms(&i915->drm, "SAGV supported: %s, original SAGV block time: %u us\n", 11942a0d256SVille Syrjälä str_yes_no(intel_has_sagv(i915)), i915->display.sagv.block_time_us); 12042a0d256SVille Syrjälä 12142a0d256SVille Syrjälä /* avoid overflow when adding with wm0 latency/etc. */ 12242a0d256SVille Syrjälä if (drm_WARN(&i915->drm, i915->display.sagv.block_time_us > U16_MAX, 12342a0d256SVille Syrjälä "Excessive SAGV block time %u, ignoring\n", 12442a0d256SVille Syrjälä i915->display.sagv.block_time_us)) 12542a0d256SVille Syrjälä i915->display.sagv.block_time_us = 0; 12642a0d256SVille Syrjälä 12742a0d256SVille Syrjälä if (!intel_has_sagv(i915)) 12842a0d256SVille Syrjälä i915->display.sagv.block_time_us = 0; 12942a0d256SVille Syrjälä } 13042a0d256SVille Syrjälä 13142a0d256SVille Syrjälä /* 13242a0d256SVille Syrjälä * SAGV dynamically adjusts the system agent voltage and clock frequencies 13342a0d256SVille Syrjälä * depending on power and performance requirements. The display engine access 13442a0d256SVille Syrjälä * to system memory is blocked during the adjustment time. Because of the 13542a0d256SVille Syrjälä * blocking time, having this enabled can cause full system hangs and/or pipe 13642a0d256SVille Syrjälä * underruns if we don't meet all of the following requirements: 13742a0d256SVille Syrjälä * 13842a0d256SVille Syrjälä * - <= 1 pipe enabled 13942a0d256SVille Syrjälä * - All planes can enable watermarks for latencies >= SAGV engine block time 14042a0d256SVille Syrjälä * - We're not using an interlaced display configuration 14142a0d256SVille Syrjälä */ 14242a0d256SVille Syrjälä static void skl_sagv_enable(struct drm_i915_private *i915) 14342a0d256SVille Syrjälä { 14442a0d256SVille Syrjälä int ret; 14542a0d256SVille Syrjälä 14642a0d256SVille Syrjälä if (!intel_has_sagv(i915)) 14742a0d256SVille Syrjälä return; 14842a0d256SVille Syrjälä 14942a0d256SVille Syrjälä if (i915->display.sagv.status == I915_SAGV_ENABLED) 15042a0d256SVille Syrjälä return; 15142a0d256SVille Syrjälä 15242a0d256SVille Syrjälä drm_dbg_kms(&i915->drm, "Enabling SAGV\n"); 15342a0d256SVille Syrjälä ret = snb_pcode_write(&i915->uncore, GEN9_PCODE_SAGV_CONTROL, 15442a0d256SVille Syrjälä GEN9_SAGV_ENABLE); 15542a0d256SVille Syrjälä 15642a0d256SVille Syrjälä /* We don't need to wait for SAGV when enabling */ 15742a0d256SVille Syrjälä 15842a0d256SVille Syrjälä /* 15942a0d256SVille Syrjälä * Some skl systems, pre-release machines in particular, 16042a0d256SVille Syrjälä * don't actually have SAGV. 16142a0d256SVille Syrjälä */ 16242a0d256SVille Syrjälä if (IS_SKYLAKE(i915) && ret == -ENXIO) { 16342a0d256SVille Syrjälä drm_dbg(&i915->drm, "No SAGV found on system, ignoring\n"); 16442a0d256SVille Syrjälä i915->display.sagv.status = I915_SAGV_NOT_CONTROLLED; 16542a0d256SVille Syrjälä return; 16642a0d256SVille Syrjälä } else if (ret < 0) { 16742a0d256SVille Syrjälä drm_err(&i915->drm, "Failed to enable SAGV\n"); 16842a0d256SVille Syrjälä return; 16942a0d256SVille Syrjälä } 17042a0d256SVille Syrjälä 17142a0d256SVille Syrjälä i915->display.sagv.status = I915_SAGV_ENABLED; 17242a0d256SVille Syrjälä } 17342a0d256SVille Syrjälä 17442a0d256SVille Syrjälä static void skl_sagv_disable(struct drm_i915_private *i915) 17542a0d256SVille Syrjälä { 17642a0d256SVille Syrjälä int ret; 17742a0d256SVille Syrjälä 17842a0d256SVille Syrjälä if (!intel_has_sagv(i915)) 17942a0d256SVille Syrjälä return; 18042a0d256SVille Syrjälä 18142a0d256SVille Syrjälä if (i915->display.sagv.status == I915_SAGV_DISABLED) 18242a0d256SVille Syrjälä return; 18342a0d256SVille Syrjälä 18442a0d256SVille Syrjälä drm_dbg_kms(&i915->drm, "Disabling SAGV\n"); 18542a0d256SVille Syrjälä /* bspec says to keep retrying for at least 1 ms */ 18642a0d256SVille Syrjälä ret = skl_pcode_request(&i915->uncore, GEN9_PCODE_SAGV_CONTROL, 18742a0d256SVille Syrjälä GEN9_SAGV_DISABLE, 18842a0d256SVille Syrjälä GEN9_SAGV_IS_DISABLED, GEN9_SAGV_IS_DISABLED, 18942a0d256SVille Syrjälä 1); 19042a0d256SVille Syrjälä /* 19142a0d256SVille Syrjälä * Some skl systems, pre-release machines in particular, 19242a0d256SVille Syrjälä * don't actually have SAGV. 19342a0d256SVille Syrjälä */ 19442a0d256SVille Syrjälä if (IS_SKYLAKE(i915) && ret == -ENXIO) { 19542a0d256SVille Syrjälä drm_dbg(&i915->drm, "No SAGV found on system, ignoring\n"); 19642a0d256SVille Syrjälä i915->display.sagv.status = I915_SAGV_NOT_CONTROLLED; 19742a0d256SVille Syrjälä return; 19842a0d256SVille Syrjälä } else if (ret < 0) { 19942a0d256SVille Syrjälä drm_err(&i915->drm, "Failed to disable SAGV (%d)\n", ret); 20042a0d256SVille Syrjälä return; 20142a0d256SVille Syrjälä } 20242a0d256SVille Syrjälä 20342a0d256SVille Syrjälä i915->display.sagv.status = I915_SAGV_DISABLED; 20442a0d256SVille Syrjälä } 20542a0d256SVille Syrjälä 20642a0d256SVille Syrjälä static void skl_sagv_pre_plane_update(struct intel_atomic_state *state) 20742a0d256SVille Syrjälä { 20842a0d256SVille Syrjälä struct drm_i915_private *i915 = to_i915(state->base.dev); 20942a0d256SVille Syrjälä const struct intel_bw_state *new_bw_state = 21042a0d256SVille Syrjälä intel_atomic_get_new_bw_state(state); 21142a0d256SVille Syrjälä 21242a0d256SVille Syrjälä if (!new_bw_state) 21342a0d256SVille Syrjälä return; 21442a0d256SVille Syrjälä 21542a0d256SVille Syrjälä if (!intel_can_enable_sagv(i915, new_bw_state)) 21642a0d256SVille Syrjälä skl_sagv_disable(i915); 21742a0d256SVille Syrjälä } 21842a0d256SVille Syrjälä 21942a0d256SVille Syrjälä static void skl_sagv_post_plane_update(struct intel_atomic_state *state) 22042a0d256SVille Syrjälä { 22142a0d256SVille Syrjälä struct drm_i915_private *i915 = to_i915(state->base.dev); 22242a0d256SVille Syrjälä const struct intel_bw_state *new_bw_state = 22342a0d256SVille Syrjälä intel_atomic_get_new_bw_state(state); 22442a0d256SVille Syrjälä 22542a0d256SVille Syrjälä if (!new_bw_state) 22642a0d256SVille Syrjälä return; 22742a0d256SVille Syrjälä 22842a0d256SVille Syrjälä if (intel_can_enable_sagv(i915, new_bw_state)) 22942a0d256SVille Syrjälä skl_sagv_enable(i915); 23042a0d256SVille Syrjälä } 23142a0d256SVille Syrjälä 23242a0d256SVille Syrjälä static void icl_sagv_pre_plane_update(struct intel_atomic_state *state) 23342a0d256SVille Syrjälä { 23442a0d256SVille Syrjälä struct drm_i915_private *i915 = to_i915(state->base.dev); 23542a0d256SVille Syrjälä const struct intel_bw_state *old_bw_state = 23642a0d256SVille Syrjälä intel_atomic_get_old_bw_state(state); 23742a0d256SVille Syrjälä const struct intel_bw_state *new_bw_state = 23842a0d256SVille Syrjälä intel_atomic_get_new_bw_state(state); 23942a0d256SVille Syrjälä u16 old_mask, new_mask; 24042a0d256SVille Syrjälä 24142a0d256SVille Syrjälä if (!new_bw_state) 24242a0d256SVille Syrjälä return; 24342a0d256SVille Syrjälä 24442a0d256SVille Syrjälä old_mask = old_bw_state->qgv_points_mask; 24542a0d256SVille Syrjälä new_mask = old_bw_state->qgv_points_mask | new_bw_state->qgv_points_mask; 24642a0d256SVille Syrjälä 24742a0d256SVille Syrjälä if (old_mask == new_mask) 24842a0d256SVille Syrjälä return; 24942a0d256SVille Syrjälä 25042a0d256SVille Syrjälä WARN_ON(!new_bw_state->base.changed); 25142a0d256SVille Syrjälä 25242a0d256SVille Syrjälä drm_dbg_kms(&i915->drm, "Restricting QGV points: 0x%x -> 0x%x\n", 25342a0d256SVille Syrjälä old_mask, new_mask); 25442a0d256SVille Syrjälä 25542a0d256SVille Syrjälä /* 25642a0d256SVille Syrjälä * Restrict required qgv points before updating the configuration. 25742a0d256SVille Syrjälä * According to BSpec we can't mask and unmask qgv points at the same 25842a0d256SVille Syrjälä * time. Also masking should be done before updating the configuration 25942a0d256SVille Syrjälä * and unmasking afterwards. 26042a0d256SVille Syrjälä */ 26142a0d256SVille Syrjälä icl_pcode_restrict_qgv_points(i915, new_mask); 26242a0d256SVille Syrjälä } 26342a0d256SVille Syrjälä 26442a0d256SVille Syrjälä static void icl_sagv_post_plane_update(struct intel_atomic_state *state) 26542a0d256SVille Syrjälä { 26642a0d256SVille Syrjälä struct drm_i915_private *i915 = to_i915(state->base.dev); 26742a0d256SVille Syrjälä const struct intel_bw_state *old_bw_state = 26842a0d256SVille Syrjälä intel_atomic_get_old_bw_state(state); 26942a0d256SVille Syrjälä const struct intel_bw_state *new_bw_state = 27042a0d256SVille Syrjälä intel_atomic_get_new_bw_state(state); 27142a0d256SVille Syrjälä u16 old_mask, new_mask; 27242a0d256SVille Syrjälä 27342a0d256SVille Syrjälä if (!new_bw_state) 27442a0d256SVille Syrjälä return; 27542a0d256SVille Syrjälä 27642a0d256SVille Syrjälä old_mask = old_bw_state->qgv_points_mask | new_bw_state->qgv_points_mask; 27742a0d256SVille Syrjälä new_mask = new_bw_state->qgv_points_mask; 27842a0d256SVille Syrjälä 27942a0d256SVille Syrjälä if (old_mask == new_mask) 28042a0d256SVille Syrjälä return; 28142a0d256SVille Syrjälä 28242a0d256SVille Syrjälä WARN_ON(!new_bw_state->base.changed); 28342a0d256SVille Syrjälä 28442a0d256SVille Syrjälä drm_dbg_kms(&i915->drm, "Relaxing QGV points: 0x%x -> 0x%x\n", 28542a0d256SVille Syrjälä old_mask, new_mask); 28642a0d256SVille Syrjälä 28742a0d256SVille Syrjälä /* 28842a0d256SVille Syrjälä * Allow required qgv points after updating the configuration. 28942a0d256SVille Syrjälä * According to BSpec we can't mask and unmask qgv points at the same 29042a0d256SVille Syrjälä * time. Also masking should be done before updating the configuration 29142a0d256SVille Syrjälä * and unmasking afterwards. 29242a0d256SVille Syrjälä */ 29342a0d256SVille Syrjälä icl_pcode_restrict_qgv_points(i915, new_mask); 29442a0d256SVille Syrjälä } 29542a0d256SVille Syrjälä 29642a0d256SVille Syrjälä void intel_sagv_pre_plane_update(struct intel_atomic_state *state) 29742a0d256SVille Syrjälä { 29842a0d256SVille Syrjälä struct drm_i915_private *i915 = to_i915(state->base.dev); 29942a0d256SVille Syrjälä 30042a0d256SVille Syrjälä /* 30142a0d256SVille Syrjälä * Just return if we can't control SAGV or don't have it. 30242a0d256SVille Syrjälä * This is different from situation when we have SAGV but just can't 30342a0d256SVille Syrjälä * afford it due to DBuf limitation - in case if SAGV is completely 30442a0d256SVille Syrjälä * disabled in a BIOS, we are not even allowed to send a PCode request, 30542a0d256SVille Syrjälä * as it will throw an error. So have to check it here. 30642a0d256SVille Syrjälä */ 30742a0d256SVille Syrjälä if (!intel_has_sagv(i915)) 30842a0d256SVille Syrjälä return; 30942a0d256SVille Syrjälä 31042a0d256SVille Syrjälä if (DISPLAY_VER(i915) >= 11) 31142a0d256SVille Syrjälä icl_sagv_pre_plane_update(state); 31242a0d256SVille Syrjälä else 31342a0d256SVille Syrjälä skl_sagv_pre_plane_update(state); 31442a0d256SVille Syrjälä } 31542a0d256SVille Syrjälä 31642a0d256SVille Syrjälä void intel_sagv_post_plane_update(struct intel_atomic_state *state) 31742a0d256SVille Syrjälä { 31842a0d256SVille Syrjälä struct drm_i915_private *i915 = to_i915(state->base.dev); 31942a0d256SVille Syrjälä 32042a0d256SVille Syrjälä /* 32142a0d256SVille Syrjälä * Just return if we can't control SAGV or don't have it. 32242a0d256SVille Syrjälä * This is different from situation when we have SAGV but just can't 32342a0d256SVille Syrjälä * afford it due to DBuf limitation - in case if SAGV is completely 32442a0d256SVille Syrjälä * disabled in a BIOS, we are not even allowed to send a PCode request, 32542a0d256SVille Syrjälä * as it will throw an error. So have to check it here. 32642a0d256SVille Syrjälä */ 32742a0d256SVille Syrjälä if (!intel_has_sagv(i915)) 32842a0d256SVille Syrjälä return; 32942a0d256SVille Syrjälä 33042a0d256SVille Syrjälä if (DISPLAY_VER(i915) >= 11) 33142a0d256SVille Syrjälä icl_sagv_post_plane_update(state); 33242a0d256SVille Syrjälä else 33342a0d256SVille Syrjälä skl_sagv_post_plane_update(state); 33442a0d256SVille Syrjälä } 33542a0d256SVille Syrjälä 33642a0d256SVille Syrjälä static bool skl_crtc_can_enable_sagv(const struct intel_crtc_state *crtc_state) 33742a0d256SVille Syrjälä { 33842a0d256SVille Syrjälä struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 33942a0d256SVille Syrjälä struct drm_i915_private *i915 = to_i915(crtc->base.dev); 34042a0d256SVille Syrjälä enum plane_id plane_id; 34142a0d256SVille Syrjälä int max_level = INT_MAX; 34242a0d256SVille Syrjälä 34342a0d256SVille Syrjälä if (!intel_has_sagv(i915)) 34442a0d256SVille Syrjälä return false; 34542a0d256SVille Syrjälä 34642a0d256SVille Syrjälä if (!crtc_state->hw.active) 34742a0d256SVille Syrjälä return true; 34842a0d256SVille Syrjälä 34942a0d256SVille Syrjälä if (crtc_state->hw.pipe_mode.flags & DRM_MODE_FLAG_INTERLACE) 35042a0d256SVille Syrjälä return false; 35142a0d256SVille Syrjälä 35242a0d256SVille Syrjälä for_each_plane_id_on_crtc(crtc, plane_id) { 35342a0d256SVille Syrjälä const struct skl_plane_wm *wm = 35442a0d256SVille Syrjälä &crtc_state->wm.skl.optimal.planes[plane_id]; 35542a0d256SVille Syrjälä int level; 35642a0d256SVille Syrjälä 35742a0d256SVille Syrjälä /* Skip this plane if it's not enabled */ 35842a0d256SVille Syrjälä if (!wm->wm[0].enable) 35942a0d256SVille Syrjälä continue; 36042a0d256SVille Syrjälä 36142a0d256SVille Syrjälä /* Find the highest enabled wm level for this plane */ 36242a0d256SVille Syrjälä for (level = ilk_wm_max_level(i915); 36342a0d256SVille Syrjälä !wm->wm[level].enable; --level) 36442a0d256SVille Syrjälä { } 36542a0d256SVille Syrjälä 36642a0d256SVille Syrjälä /* Highest common enabled wm level for all planes */ 36742a0d256SVille Syrjälä max_level = min(level, max_level); 36842a0d256SVille Syrjälä } 36942a0d256SVille Syrjälä 37042a0d256SVille Syrjälä /* No enabled planes? */ 37142a0d256SVille Syrjälä if (max_level == INT_MAX) 37242a0d256SVille Syrjälä return true; 37342a0d256SVille Syrjälä 37442a0d256SVille Syrjälä for_each_plane_id_on_crtc(crtc, plane_id) { 37542a0d256SVille Syrjälä const struct skl_plane_wm *wm = 37642a0d256SVille Syrjälä &crtc_state->wm.skl.optimal.planes[plane_id]; 37742a0d256SVille Syrjälä 37842a0d256SVille Syrjälä /* 37942a0d256SVille Syrjälä * All enabled planes must have enabled a common wm level that 38042a0d256SVille Syrjälä * can tolerate memory latencies higher than sagv_block_time_us 38142a0d256SVille Syrjälä */ 38242a0d256SVille Syrjälä if (wm->wm[0].enable && !wm->wm[max_level].can_sagv) 38342a0d256SVille Syrjälä return false; 38442a0d256SVille Syrjälä } 38542a0d256SVille Syrjälä 38642a0d256SVille Syrjälä return true; 38742a0d256SVille Syrjälä } 38842a0d256SVille Syrjälä 38942a0d256SVille Syrjälä static bool tgl_crtc_can_enable_sagv(const struct intel_crtc_state *crtc_state) 39042a0d256SVille Syrjälä { 39142a0d256SVille Syrjälä struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 39242a0d256SVille Syrjälä enum plane_id plane_id; 39342a0d256SVille Syrjälä 39442a0d256SVille Syrjälä if (!crtc_state->hw.active) 39542a0d256SVille Syrjälä return true; 39642a0d256SVille Syrjälä 39742a0d256SVille Syrjälä for_each_plane_id_on_crtc(crtc, plane_id) { 39842a0d256SVille Syrjälä const struct skl_plane_wm *wm = 39942a0d256SVille Syrjälä &crtc_state->wm.skl.optimal.planes[plane_id]; 40042a0d256SVille Syrjälä 40142a0d256SVille Syrjälä if (wm->wm[0].enable && !wm->sagv.wm0.enable) 40242a0d256SVille Syrjälä return false; 40342a0d256SVille Syrjälä } 40442a0d256SVille Syrjälä 40542a0d256SVille Syrjälä return true; 40642a0d256SVille Syrjälä } 40742a0d256SVille Syrjälä 40842a0d256SVille Syrjälä static bool intel_crtc_can_enable_sagv(const struct intel_crtc_state *crtc_state) 40942a0d256SVille Syrjälä { 41042a0d256SVille Syrjälä struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 41142a0d256SVille Syrjälä struct drm_i915_private *i915 = to_i915(crtc->base.dev); 41242a0d256SVille Syrjälä 41342a0d256SVille Syrjälä if (DISPLAY_VER(i915) >= 12) 41442a0d256SVille Syrjälä return tgl_crtc_can_enable_sagv(crtc_state); 41542a0d256SVille Syrjälä else 41642a0d256SVille Syrjälä return skl_crtc_can_enable_sagv(crtc_state); 41742a0d256SVille Syrjälä } 41842a0d256SVille Syrjälä 41942a0d256SVille Syrjälä bool intel_can_enable_sagv(struct drm_i915_private *i915, 42042a0d256SVille Syrjälä const struct intel_bw_state *bw_state) 42142a0d256SVille Syrjälä { 42242a0d256SVille Syrjälä if (DISPLAY_VER(i915) < 11 && 42342a0d256SVille Syrjälä bw_state->active_pipes && !is_power_of_2(bw_state->active_pipes)) 42442a0d256SVille Syrjälä return false; 42542a0d256SVille Syrjälä 42642a0d256SVille Syrjälä return bw_state->pipe_sagv_reject == 0; 42742a0d256SVille Syrjälä } 42842a0d256SVille Syrjälä 42942a0d256SVille Syrjälä static int intel_compute_sagv_mask(struct intel_atomic_state *state) 43042a0d256SVille Syrjälä { 43142a0d256SVille Syrjälä struct drm_i915_private *i915 = to_i915(state->base.dev); 43242a0d256SVille Syrjälä int ret; 43342a0d256SVille Syrjälä struct intel_crtc *crtc; 43442a0d256SVille Syrjälä struct intel_crtc_state *new_crtc_state; 43542a0d256SVille Syrjälä struct intel_bw_state *new_bw_state = NULL; 43642a0d256SVille Syrjälä const struct intel_bw_state *old_bw_state = NULL; 43742a0d256SVille Syrjälä int i; 43842a0d256SVille Syrjälä 43942a0d256SVille Syrjälä for_each_new_intel_crtc_in_state(state, crtc, 44042a0d256SVille Syrjälä new_crtc_state, i) { 44142a0d256SVille Syrjälä new_bw_state = intel_atomic_get_bw_state(state); 44242a0d256SVille Syrjälä if (IS_ERR(new_bw_state)) 44342a0d256SVille Syrjälä return PTR_ERR(new_bw_state); 44442a0d256SVille Syrjälä 44542a0d256SVille Syrjälä old_bw_state = intel_atomic_get_old_bw_state(state); 44642a0d256SVille Syrjälä 44742a0d256SVille Syrjälä if (intel_crtc_can_enable_sagv(new_crtc_state)) 44842a0d256SVille Syrjälä new_bw_state->pipe_sagv_reject &= ~BIT(crtc->pipe); 44942a0d256SVille Syrjälä else 45042a0d256SVille Syrjälä new_bw_state->pipe_sagv_reject |= BIT(crtc->pipe); 45142a0d256SVille Syrjälä } 45242a0d256SVille Syrjälä 45342a0d256SVille Syrjälä if (!new_bw_state) 45442a0d256SVille Syrjälä return 0; 45542a0d256SVille Syrjälä 45642a0d256SVille Syrjälä new_bw_state->active_pipes = 45742a0d256SVille Syrjälä intel_calc_active_pipes(state, old_bw_state->active_pipes); 45842a0d256SVille Syrjälä 45942a0d256SVille Syrjälä if (new_bw_state->active_pipes != old_bw_state->active_pipes) { 46042a0d256SVille Syrjälä ret = intel_atomic_lock_global_state(&new_bw_state->base); 46142a0d256SVille Syrjälä if (ret) 46242a0d256SVille Syrjälä return ret; 46342a0d256SVille Syrjälä } 46442a0d256SVille Syrjälä 46542a0d256SVille Syrjälä if (intel_can_enable_sagv(i915, new_bw_state) != 46642a0d256SVille Syrjälä intel_can_enable_sagv(i915, old_bw_state)) { 46742a0d256SVille Syrjälä ret = intel_atomic_serialize_global_state(&new_bw_state->base); 46842a0d256SVille Syrjälä if (ret) 46942a0d256SVille Syrjälä return ret; 47042a0d256SVille Syrjälä } else if (new_bw_state->pipe_sagv_reject != old_bw_state->pipe_sagv_reject) { 47142a0d256SVille Syrjälä ret = intel_atomic_lock_global_state(&new_bw_state->base); 47242a0d256SVille Syrjälä if (ret) 47342a0d256SVille Syrjälä return ret; 47442a0d256SVille Syrjälä } 47542a0d256SVille Syrjälä 47642a0d256SVille Syrjälä for_each_new_intel_crtc_in_state(state, crtc, 47742a0d256SVille Syrjälä new_crtc_state, i) { 47842a0d256SVille Syrjälä struct skl_pipe_wm *pipe_wm = &new_crtc_state->wm.skl.optimal; 47942a0d256SVille Syrjälä 48042a0d256SVille Syrjälä /* 48142a0d256SVille Syrjälä * We store use_sagv_wm in the crtc state rather than relying on 48242a0d256SVille Syrjälä * that bw state since we have no convenient way to get at the 48342a0d256SVille Syrjälä * latter from the plane commit hooks (especially in the legacy 48442a0d256SVille Syrjälä * cursor case) 48542a0d256SVille Syrjälä */ 48642a0d256SVille Syrjälä pipe_wm->use_sagv_wm = !HAS_HW_SAGV_WM(i915) && 48742a0d256SVille Syrjälä DISPLAY_VER(i915) >= 12 && 48842a0d256SVille Syrjälä intel_can_enable_sagv(i915, new_bw_state); 48942a0d256SVille Syrjälä } 49042a0d256SVille Syrjälä 49142a0d256SVille Syrjälä return 0; 49242a0d256SVille Syrjälä } 49342a0d256SVille Syrjälä 49442a0d256SVille Syrjälä static u16 skl_ddb_entry_init(struct skl_ddb_entry *entry, 49542a0d256SVille Syrjälä u16 start, u16 end) 49642a0d256SVille Syrjälä { 49742a0d256SVille Syrjälä entry->start = start; 49842a0d256SVille Syrjälä entry->end = end; 49942a0d256SVille Syrjälä 50042a0d256SVille Syrjälä return end; 50142a0d256SVille Syrjälä } 50242a0d256SVille Syrjälä 50342a0d256SVille Syrjälä static int intel_dbuf_slice_size(struct drm_i915_private *i915) 50442a0d256SVille Syrjälä { 50542a0d256SVille Syrjälä return INTEL_INFO(i915)->display.dbuf.size / 50642a0d256SVille Syrjälä hweight8(INTEL_INFO(i915)->display.dbuf.slice_mask); 50742a0d256SVille Syrjälä } 50842a0d256SVille Syrjälä 50942a0d256SVille Syrjälä static void 51042a0d256SVille Syrjälä skl_ddb_entry_for_slices(struct drm_i915_private *i915, u8 slice_mask, 51142a0d256SVille Syrjälä struct skl_ddb_entry *ddb) 51242a0d256SVille Syrjälä { 51342a0d256SVille Syrjälä int slice_size = intel_dbuf_slice_size(i915); 51442a0d256SVille Syrjälä 51542a0d256SVille Syrjälä if (!slice_mask) { 51642a0d256SVille Syrjälä ddb->start = 0; 51742a0d256SVille Syrjälä ddb->end = 0; 51842a0d256SVille Syrjälä return; 51942a0d256SVille Syrjälä } 52042a0d256SVille Syrjälä 52142a0d256SVille Syrjälä ddb->start = (ffs(slice_mask) - 1) * slice_size; 52242a0d256SVille Syrjälä ddb->end = fls(slice_mask) * slice_size; 52342a0d256SVille Syrjälä 52442a0d256SVille Syrjälä WARN_ON(ddb->start >= ddb->end); 52542a0d256SVille Syrjälä WARN_ON(ddb->end > INTEL_INFO(i915)->display.dbuf.size); 52642a0d256SVille Syrjälä } 52742a0d256SVille Syrjälä 52842a0d256SVille Syrjälä static unsigned int mbus_ddb_offset(struct drm_i915_private *i915, u8 slice_mask) 52942a0d256SVille Syrjälä { 53042a0d256SVille Syrjälä struct skl_ddb_entry ddb; 53142a0d256SVille Syrjälä 53242a0d256SVille Syrjälä if (slice_mask & (BIT(DBUF_S1) | BIT(DBUF_S2))) 53342a0d256SVille Syrjälä slice_mask = BIT(DBUF_S1); 53442a0d256SVille Syrjälä else if (slice_mask & (BIT(DBUF_S3) | BIT(DBUF_S4))) 53542a0d256SVille Syrjälä slice_mask = BIT(DBUF_S3); 53642a0d256SVille Syrjälä 53742a0d256SVille Syrjälä skl_ddb_entry_for_slices(i915, slice_mask, &ddb); 53842a0d256SVille Syrjälä 53942a0d256SVille Syrjälä return ddb.start; 54042a0d256SVille Syrjälä } 54142a0d256SVille Syrjälä 54242a0d256SVille Syrjälä u32 skl_ddb_dbuf_slice_mask(struct drm_i915_private *i915, 54342a0d256SVille Syrjälä const struct skl_ddb_entry *entry) 54442a0d256SVille Syrjälä { 54542a0d256SVille Syrjälä int slice_size = intel_dbuf_slice_size(i915); 54642a0d256SVille Syrjälä enum dbuf_slice start_slice, end_slice; 54742a0d256SVille Syrjälä u8 slice_mask = 0; 54842a0d256SVille Syrjälä 54942a0d256SVille Syrjälä if (!skl_ddb_entry_size(entry)) 55042a0d256SVille Syrjälä return 0; 55142a0d256SVille Syrjälä 55242a0d256SVille Syrjälä start_slice = entry->start / slice_size; 55342a0d256SVille Syrjälä end_slice = (entry->end - 1) / slice_size; 55442a0d256SVille Syrjälä 55542a0d256SVille Syrjälä /* 55642a0d256SVille Syrjälä * Per plane DDB entry can in a really worst case be on multiple slices 55742a0d256SVille Syrjälä * but single entry is anyway contigious. 55842a0d256SVille Syrjälä */ 55942a0d256SVille Syrjälä while (start_slice <= end_slice) { 56042a0d256SVille Syrjälä slice_mask |= BIT(start_slice); 56142a0d256SVille Syrjälä start_slice++; 56242a0d256SVille Syrjälä } 56342a0d256SVille Syrjälä 56442a0d256SVille Syrjälä return slice_mask; 56542a0d256SVille Syrjälä } 56642a0d256SVille Syrjälä 56742a0d256SVille Syrjälä static unsigned int intel_crtc_ddb_weight(const struct intel_crtc_state *crtc_state) 56842a0d256SVille Syrjälä { 56942a0d256SVille Syrjälä const struct drm_display_mode *pipe_mode = &crtc_state->hw.pipe_mode; 57042a0d256SVille Syrjälä int hdisplay, vdisplay; 57142a0d256SVille Syrjälä 57242a0d256SVille Syrjälä if (!crtc_state->hw.active) 57342a0d256SVille Syrjälä return 0; 57442a0d256SVille Syrjälä 57542a0d256SVille Syrjälä /* 57642a0d256SVille Syrjälä * Watermark/ddb requirement highly depends upon width of the 57742a0d256SVille Syrjälä * framebuffer, So instead of allocating DDB equally among pipes 57842a0d256SVille Syrjälä * distribute DDB based on resolution/width of the display. 57942a0d256SVille Syrjälä */ 58042a0d256SVille Syrjälä drm_mode_get_hv_timing(pipe_mode, &hdisplay, &vdisplay); 58142a0d256SVille Syrjälä 58242a0d256SVille Syrjälä return hdisplay; 58342a0d256SVille Syrjälä } 58442a0d256SVille Syrjälä 58542a0d256SVille Syrjälä static void intel_crtc_dbuf_weights(const struct intel_dbuf_state *dbuf_state, 58642a0d256SVille Syrjälä enum pipe for_pipe, 58742a0d256SVille Syrjälä unsigned int *weight_start, 58842a0d256SVille Syrjälä unsigned int *weight_end, 58942a0d256SVille Syrjälä unsigned int *weight_total) 59042a0d256SVille Syrjälä { 59142a0d256SVille Syrjälä struct drm_i915_private *i915 = 59242a0d256SVille Syrjälä to_i915(dbuf_state->base.state->base.dev); 59342a0d256SVille Syrjälä enum pipe pipe; 59442a0d256SVille Syrjälä 59542a0d256SVille Syrjälä *weight_start = 0; 59642a0d256SVille Syrjälä *weight_end = 0; 59742a0d256SVille Syrjälä *weight_total = 0; 59842a0d256SVille Syrjälä 59942a0d256SVille Syrjälä for_each_pipe(i915, pipe) { 60042a0d256SVille Syrjälä int weight = dbuf_state->weight[pipe]; 60142a0d256SVille Syrjälä 60242a0d256SVille Syrjälä /* 60342a0d256SVille Syrjälä * Do not account pipes using other slice sets 60442a0d256SVille Syrjälä * luckily as of current BSpec slice sets do not partially 60542a0d256SVille Syrjälä * intersect(pipes share either same one slice or same slice set 60642a0d256SVille Syrjälä * i.e no partial intersection), so it is enough to check for 60742a0d256SVille Syrjälä * equality for now. 60842a0d256SVille Syrjälä */ 60942a0d256SVille Syrjälä if (dbuf_state->slices[pipe] != dbuf_state->slices[for_pipe]) 61042a0d256SVille Syrjälä continue; 61142a0d256SVille Syrjälä 61242a0d256SVille Syrjälä *weight_total += weight; 61342a0d256SVille Syrjälä if (pipe < for_pipe) { 61442a0d256SVille Syrjälä *weight_start += weight; 61542a0d256SVille Syrjälä *weight_end += weight; 61642a0d256SVille Syrjälä } else if (pipe == for_pipe) { 61742a0d256SVille Syrjälä *weight_end += weight; 61842a0d256SVille Syrjälä } 61942a0d256SVille Syrjälä } 62042a0d256SVille Syrjälä } 62142a0d256SVille Syrjälä 62242a0d256SVille Syrjälä static int 62342a0d256SVille Syrjälä skl_crtc_allocate_ddb(struct intel_atomic_state *state, struct intel_crtc *crtc) 62442a0d256SVille Syrjälä { 62542a0d256SVille Syrjälä struct drm_i915_private *i915 = to_i915(crtc->base.dev); 62642a0d256SVille Syrjälä unsigned int weight_total, weight_start, weight_end; 62742a0d256SVille Syrjälä const struct intel_dbuf_state *old_dbuf_state = 62842a0d256SVille Syrjälä intel_atomic_get_old_dbuf_state(state); 62942a0d256SVille Syrjälä struct intel_dbuf_state *new_dbuf_state = 63042a0d256SVille Syrjälä intel_atomic_get_new_dbuf_state(state); 63142a0d256SVille Syrjälä struct intel_crtc_state *crtc_state; 63242a0d256SVille Syrjälä struct skl_ddb_entry ddb_slices; 63342a0d256SVille Syrjälä enum pipe pipe = crtc->pipe; 63442a0d256SVille Syrjälä unsigned int mbus_offset = 0; 63542a0d256SVille Syrjälä u32 ddb_range_size; 63642a0d256SVille Syrjälä u32 dbuf_slice_mask; 63742a0d256SVille Syrjälä u32 start, end; 63842a0d256SVille Syrjälä int ret; 63942a0d256SVille Syrjälä 64042a0d256SVille Syrjälä if (new_dbuf_state->weight[pipe] == 0) { 64142a0d256SVille Syrjälä skl_ddb_entry_init(&new_dbuf_state->ddb[pipe], 0, 0); 64242a0d256SVille Syrjälä goto out; 64342a0d256SVille Syrjälä } 64442a0d256SVille Syrjälä 64542a0d256SVille Syrjälä dbuf_slice_mask = new_dbuf_state->slices[pipe]; 64642a0d256SVille Syrjälä 64742a0d256SVille Syrjälä skl_ddb_entry_for_slices(i915, dbuf_slice_mask, &ddb_slices); 64842a0d256SVille Syrjälä mbus_offset = mbus_ddb_offset(i915, dbuf_slice_mask); 64942a0d256SVille Syrjälä ddb_range_size = skl_ddb_entry_size(&ddb_slices); 65042a0d256SVille Syrjälä 65142a0d256SVille Syrjälä intel_crtc_dbuf_weights(new_dbuf_state, pipe, 65242a0d256SVille Syrjälä &weight_start, &weight_end, &weight_total); 65342a0d256SVille Syrjälä 65442a0d256SVille Syrjälä start = ddb_range_size * weight_start / weight_total; 65542a0d256SVille Syrjälä end = ddb_range_size * weight_end / weight_total; 65642a0d256SVille Syrjälä 65742a0d256SVille Syrjälä skl_ddb_entry_init(&new_dbuf_state->ddb[pipe], 65842a0d256SVille Syrjälä ddb_slices.start - mbus_offset + start, 65942a0d256SVille Syrjälä ddb_slices.start - mbus_offset + end); 66042a0d256SVille Syrjälä 66142a0d256SVille Syrjälä out: 66242a0d256SVille Syrjälä if (old_dbuf_state->slices[pipe] == new_dbuf_state->slices[pipe] && 66342a0d256SVille Syrjälä skl_ddb_entry_equal(&old_dbuf_state->ddb[pipe], 66442a0d256SVille Syrjälä &new_dbuf_state->ddb[pipe])) 66542a0d256SVille Syrjälä return 0; 66642a0d256SVille Syrjälä 66742a0d256SVille Syrjälä ret = intel_atomic_lock_global_state(&new_dbuf_state->base); 66842a0d256SVille Syrjälä if (ret) 66942a0d256SVille Syrjälä return ret; 67042a0d256SVille Syrjälä 67142a0d256SVille Syrjälä crtc_state = intel_atomic_get_crtc_state(&state->base, crtc); 67242a0d256SVille Syrjälä if (IS_ERR(crtc_state)) 67342a0d256SVille Syrjälä return PTR_ERR(crtc_state); 67442a0d256SVille Syrjälä 67542a0d256SVille Syrjälä /* 67642a0d256SVille Syrjälä * Used for checking overlaps, so we need absolute 67742a0d256SVille Syrjälä * offsets instead of MBUS relative offsets. 67842a0d256SVille Syrjälä */ 67942a0d256SVille Syrjälä crtc_state->wm.skl.ddb.start = mbus_offset + new_dbuf_state->ddb[pipe].start; 68042a0d256SVille Syrjälä crtc_state->wm.skl.ddb.end = mbus_offset + new_dbuf_state->ddb[pipe].end; 68142a0d256SVille Syrjälä 68242a0d256SVille Syrjälä drm_dbg_kms(&i915->drm, 68342a0d256SVille Syrjälä "[CRTC:%d:%s] dbuf slices 0x%x -> 0x%x, ddb (%d - %d) -> (%d - %d), active pipes 0x%x -> 0x%x\n", 68442a0d256SVille Syrjälä crtc->base.base.id, crtc->base.name, 68542a0d256SVille Syrjälä old_dbuf_state->slices[pipe], new_dbuf_state->slices[pipe], 68642a0d256SVille Syrjälä old_dbuf_state->ddb[pipe].start, old_dbuf_state->ddb[pipe].end, 68742a0d256SVille Syrjälä new_dbuf_state->ddb[pipe].start, new_dbuf_state->ddb[pipe].end, 68842a0d256SVille Syrjälä old_dbuf_state->active_pipes, new_dbuf_state->active_pipes); 68942a0d256SVille Syrjälä 69042a0d256SVille Syrjälä return 0; 69142a0d256SVille Syrjälä } 69242a0d256SVille Syrjälä 69342a0d256SVille Syrjälä static int skl_compute_wm_params(const struct intel_crtc_state *crtc_state, 69442a0d256SVille Syrjälä int width, const struct drm_format_info *format, 69542a0d256SVille Syrjälä u64 modifier, unsigned int rotation, 69642a0d256SVille Syrjälä u32 plane_pixel_rate, struct skl_wm_params *wp, 69742a0d256SVille Syrjälä int color_plane); 69842a0d256SVille Syrjälä 69942a0d256SVille Syrjälä static void skl_compute_plane_wm(const struct intel_crtc_state *crtc_state, 70042a0d256SVille Syrjälä struct intel_plane *plane, 70142a0d256SVille Syrjälä int level, 70242a0d256SVille Syrjälä unsigned int latency, 70342a0d256SVille Syrjälä const struct skl_wm_params *wp, 70442a0d256SVille Syrjälä const struct skl_wm_level *result_prev, 70542a0d256SVille Syrjälä struct skl_wm_level *result /* out */); 70642a0d256SVille Syrjälä 70742a0d256SVille Syrjälä static unsigned int 70842a0d256SVille Syrjälä skl_cursor_allocation(const struct intel_crtc_state *crtc_state, 70942a0d256SVille Syrjälä int num_active) 71042a0d256SVille Syrjälä { 71142a0d256SVille Syrjälä struct intel_plane *plane = to_intel_plane(crtc_state->uapi.crtc->cursor); 71242a0d256SVille Syrjälä struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); 71342a0d256SVille Syrjälä int level, max_level = ilk_wm_max_level(i915); 71442a0d256SVille Syrjälä struct skl_wm_level wm = {}; 71542a0d256SVille Syrjälä int ret, min_ddb_alloc = 0; 71642a0d256SVille Syrjälä struct skl_wm_params wp; 71742a0d256SVille Syrjälä 71842a0d256SVille Syrjälä ret = skl_compute_wm_params(crtc_state, 256, 71942a0d256SVille Syrjälä drm_format_info(DRM_FORMAT_ARGB8888), 72042a0d256SVille Syrjälä DRM_FORMAT_MOD_LINEAR, 72142a0d256SVille Syrjälä DRM_MODE_ROTATE_0, 72242a0d256SVille Syrjälä crtc_state->pixel_rate, &wp, 0); 72342a0d256SVille Syrjälä drm_WARN_ON(&i915->drm, ret); 72442a0d256SVille Syrjälä 72542a0d256SVille Syrjälä for (level = 0; level <= max_level; level++) { 72642a0d256SVille Syrjälä unsigned int latency = i915->display.wm.skl_latency[level]; 72742a0d256SVille Syrjälä 72842a0d256SVille Syrjälä skl_compute_plane_wm(crtc_state, plane, level, latency, &wp, &wm, &wm); 72942a0d256SVille Syrjälä if (wm.min_ddb_alloc == U16_MAX) 73042a0d256SVille Syrjälä break; 73142a0d256SVille Syrjälä 73242a0d256SVille Syrjälä min_ddb_alloc = wm.min_ddb_alloc; 73342a0d256SVille Syrjälä } 73442a0d256SVille Syrjälä 73542a0d256SVille Syrjälä return max(num_active == 1 ? 32 : 8, min_ddb_alloc); 73642a0d256SVille Syrjälä } 73742a0d256SVille Syrjälä 73842a0d256SVille Syrjälä static void skl_ddb_entry_init_from_hw(struct skl_ddb_entry *entry, u32 reg) 73942a0d256SVille Syrjälä { 74042a0d256SVille Syrjälä skl_ddb_entry_init(entry, 74142a0d256SVille Syrjälä REG_FIELD_GET(PLANE_BUF_START_MASK, reg), 74242a0d256SVille Syrjälä REG_FIELD_GET(PLANE_BUF_END_MASK, reg)); 74342a0d256SVille Syrjälä if (entry->end) 74442a0d256SVille Syrjälä entry->end++; 74542a0d256SVille Syrjälä } 74642a0d256SVille Syrjälä 74742a0d256SVille Syrjälä static void 74842a0d256SVille Syrjälä skl_ddb_get_hw_plane_state(struct drm_i915_private *i915, 74942a0d256SVille Syrjälä const enum pipe pipe, 75042a0d256SVille Syrjälä const enum plane_id plane_id, 75142a0d256SVille Syrjälä struct skl_ddb_entry *ddb, 75242a0d256SVille Syrjälä struct skl_ddb_entry *ddb_y) 75342a0d256SVille Syrjälä { 75442a0d256SVille Syrjälä u32 val; 75542a0d256SVille Syrjälä 75642a0d256SVille Syrjälä /* Cursor doesn't support NV12/planar, so no extra calculation needed */ 75742a0d256SVille Syrjälä if (plane_id == PLANE_CURSOR) { 75800136429SJani Nikula val = intel_de_read(i915, CUR_BUF_CFG(pipe)); 75942a0d256SVille Syrjälä skl_ddb_entry_init_from_hw(ddb, val); 76042a0d256SVille Syrjälä return; 76142a0d256SVille Syrjälä } 76242a0d256SVille Syrjälä 76300136429SJani Nikula val = intel_de_read(i915, PLANE_BUF_CFG(pipe, plane_id)); 76442a0d256SVille Syrjälä skl_ddb_entry_init_from_hw(ddb, val); 76542a0d256SVille Syrjälä 76642a0d256SVille Syrjälä if (DISPLAY_VER(i915) >= 11) 76742a0d256SVille Syrjälä return; 76842a0d256SVille Syrjälä 76900136429SJani Nikula val = intel_de_read(i915, PLANE_NV12_BUF_CFG(pipe, plane_id)); 77042a0d256SVille Syrjälä skl_ddb_entry_init_from_hw(ddb_y, val); 77142a0d256SVille Syrjälä } 77242a0d256SVille Syrjälä 77342a0d256SVille Syrjälä static void skl_pipe_ddb_get_hw_state(struct intel_crtc *crtc, 77442a0d256SVille Syrjälä struct skl_ddb_entry *ddb, 77542a0d256SVille Syrjälä struct skl_ddb_entry *ddb_y) 77642a0d256SVille Syrjälä { 77742a0d256SVille Syrjälä struct drm_i915_private *i915 = to_i915(crtc->base.dev); 77842a0d256SVille Syrjälä enum intel_display_power_domain power_domain; 77942a0d256SVille Syrjälä enum pipe pipe = crtc->pipe; 78042a0d256SVille Syrjälä intel_wakeref_t wakeref; 78142a0d256SVille Syrjälä enum plane_id plane_id; 78242a0d256SVille Syrjälä 78342a0d256SVille Syrjälä power_domain = POWER_DOMAIN_PIPE(pipe); 78442a0d256SVille Syrjälä wakeref = intel_display_power_get_if_enabled(i915, power_domain); 78542a0d256SVille Syrjälä if (!wakeref) 78642a0d256SVille Syrjälä return; 78742a0d256SVille Syrjälä 78842a0d256SVille Syrjälä for_each_plane_id_on_crtc(crtc, plane_id) 78942a0d256SVille Syrjälä skl_ddb_get_hw_plane_state(i915, pipe, 79042a0d256SVille Syrjälä plane_id, 79142a0d256SVille Syrjälä &ddb[plane_id], 79242a0d256SVille Syrjälä &ddb_y[plane_id]); 79342a0d256SVille Syrjälä 79442a0d256SVille Syrjälä intel_display_power_put(i915, power_domain, wakeref); 79542a0d256SVille Syrjälä } 79642a0d256SVille Syrjälä 79742a0d256SVille Syrjälä struct dbuf_slice_conf_entry { 79842a0d256SVille Syrjälä u8 active_pipes; 79942a0d256SVille Syrjälä u8 dbuf_mask[I915_MAX_PIPES]; 80042a0d256SVille Syrjälä bool join_mbus; 80142a0d256SVille Syrjälä }; 80242a0d256SVille Syrjälä 80342a0d256SVille Syrjälä /* 80442a0d256SVille Syrjälä * Table taken from Bspec 12716 80542a0d256SVille Syrjälä * Pipes do have some preferred DBuf slice affinity, 80642a0d256SVille Syrjälä * plus there are some hardcoded requirements on how 80742a0d256SVille Syrjälä * those should be distributed for multipipe scenarios. 80842a0d256SVille Syrjälä * For more DBuf slices algorithm can get even more messy 80942a0d256SVille Syrjälä * and less readable, so decided to use a table almost 81042a0d256SVille Syrjälä * as is from BSpec itself - that way it is at least easier 81142a0d256SVille Syrjälä * to compare, change and check. 81242a0d256SVille Syrjälä */ 81342a0d256SVille Syrjälä static const struct dbuf_slice_conf_entry icl_allowed_dbufs[] = 81442a0d256SVille Syrjälä /* Autogenerated with igt/tools/intel_dbuf_map tool: */ 81542a0d256SVille Syrjälä { 81642a0d256SVille Syrjälä { 81742a0d256SVille Syrjälä .active_pipes = BIT(PIPE_A), 81842a0d256SVille Syrjälä .dbuf_mask = { 81942a0d256SVille Syrjälä [PIPE_A] = BIT(DBUF_S1), 82042a0d256SVille Syrjälä }, 82142a0d256SVille Syrjälä }, 82242a0d256SVille Syrjälä { 82342a0d256SVille Syrjälä .active_pipes = BIT(PIPE_B), 82442a0d256SVille Syrjälä .dbuf_mask = { 82542a0d256SVille Syrjälä [PIPE_B] = BIT(DBUF_S1), 82642a0d256SVille Syrjälä }, 82742a0d256SVille Syrjälä }, 82842a0d256SVille Syrjälä { 82942a0d256SVille Syrjälä .active_pipes = BIT(PIPE_A) | BIT(PIPE_B), 83042a0d256SVille Syrjälä .dbuf_mask = { 83142a0d256SVille Syrjälä [PIPE_A] = BIT(DBUF_S1), 83242a0d256SVille Syrjälä [PIPE_B] = BIT(DBUF_S2), 83342a0d256SVille Syrjälä }, 83442a0d256SVille Syrjälä }, 83542a0d256SVille Syrjälä { 83642a0d256SVille Syrjälä .active_pipes = BIT(PIPE_C), 83742a0d256SVille Syrjälä .dbuf_mask = { 83842a0d256SVille Syrjälä [PIPE_C] = BIT(DBUF_S2), 83942a0d256SVille Syrjälä }, 84042a0d256SVille Syrjälä }, 84142a0d256SVille Syrjälä { 84242a0d256SVille Syrjälä .active_pipes = BIT(PIPE_A) | BIT(PIPE_C), 84342a0d256SVille Syrjälä .dbuf_mask = { 84442a0d256SVille Syrjälä [PIPE_A] = BIT(DBUF_S1), 84542a0d256SVille Syrjälä [PIPE_C] = BIT(DBUF_S2), 84642a0d256SVille Syrjälä }, 84742a0d256SVille Syrjälä }, 84842a0d256SVille Syrjälä { 84942a0d256SVille Syrjälä .active_pipes = BIT(PIPE_B) | BIT(PIPE_C), 85042a0d256SVille Syrjälä .dbuf_mask = { 85142a0d256SVille Syrjälä [PIPE_B] = BIT(DBUF_S1), 85242a0d256SVille Syrjälä [PIPE_C] = BIT(DBUF_S2), 85342a0d256SVille Syrjälä }, 85442a0d256SVille Syrjälä }, 85542a0d256SVille Syrjälä { 85642a0d256SVille Syrjälä .active_pipes = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C), 85742a0d256SVille Syrjälä .dbuf_mask = { 85842a0d256SVille Syrjälä [PIPE_A] = BIT(DBUF_S1), 85942a0d256SVille Syrjälä [PIPE_B] = BIT(DBUF_S1), 86042a0d256SVille Syrjälä [PIPE_C] = BIT(DBUF_S2), 86142a0d256SVille Syrjälä }, 86242a0d256SVille Syrjälä }, 86342a0d256SVille Syrjälä {} 86442a0d256SVille Syrjälä }; 86542a0d256SVille Syrjälä 86642a0d256SVille Syrjälä /* 86742a0d256SVille Syrjälä * Table taken from Bspec 49255 86842a0d256SVille Syrjälä * Pipes do have some preferred DBuf slice affinity, 86942a0d256SVille Syrjälä * plus there are some hardcoded requirements on how 87042a0d256SVille Syrjälä * those should be distributed for multipipe scenarios. 87142a0d256SVille Syrjälä * For more DBuf slices algorithm can get even more messy 87242a0d256SVille Syrjälä * and less readable, so decided to use a table almost 87342a0d256SVille Syrjälä * as is from BSpec itself - that way it is at least easier 87442a0d256SVille Syrjälä * to compare, change and check. 87542a0d256SVille Syrjälä */ 87642a0d256SVille Syrjälä static const struct dbuf_slice_conf_entry tgl_allowed_dbufs[] = 87742a0d256SVille Syrjälä /* Autogenerated with igt/tools/intel_dbuf_map tool: */ 87842a0d256SVille Syrjälä { 87942a0d256SVille Syrjälä { 88042a0d256SVille Syrjälä .active_pipes = BIT(PIPE_A), 88142a0d256SVille Syrjälä .dbuf_mask = { 88242a0d256SVille Syrjälä [PIPE_A] = BIT(DBUF_S1) | BIT(DBUF_S2), 88342a0d256SVille Syrjälä }, 88442a0d256SVille Syrjälä }, 88542a0d256SVille Syrjälä { 88642a0d256SVille Syrjälä .active_pipes = BIT(PIPE_B), 88742a0d256SVille Syrjälä .dbuf_mask = { 88842a0d256SVille Syrjälä [PIPE_B] = BIT(DBUF_S1) | BIT(DBUF_S2), 88942a0d256SVille Syrjälä }, 89042a0d256SVille Syrjälä }, 89142a0d256SVille Syrjälä { 89242a0d256SVille Syrjälä .active_pipes = BIT(PIPE_A) | BIT(PIPE_B), 89342a0d256SVille Syrjälä .dbuf_mask = { 89442a0d256SVille Syrjälä [PIPE_A] = BIT(DBUF_S2), 89542a0d256SVille Syrjälä [PIPE_B] = BIT(DBUF_S1), 89642a0d256SVille Syrjälä }, 89742a0d256SVille Syrjälä }, 89842a0d256SVille Syrjälä { 89942a0d256SVille Syrjälä .active_pipes = BIT(PIPE_C), 90042a0d256SVille Syrjälä .dbuf_mask = { 90142a0d256SVille Syrjälä [PIPE_C] = BIT(DBUF_S2) | BIT(DBUF_S1), 90242a0d256SVille Syrjälä }, 90342a0d256SVille Syrjälä }, 90442a0d256SVille Syrjälä { 90542a0d256SVille Syrjälä .active_pipes = BIT(PIPE_A) | BIT(PIPE_C), 90642a0d256SVille Syrjälä .dbuf_mask = { 90742a0d256SVille Syrjälä [PIPE_A] = BIT(DBUF_S1), 90842a0d256SVille Syrjälä [PIPE_C] = BIT(DBUF_S2), 90942a0d256SVille Syrjälä }, 91042a0d256SVille Syrjälä }, 91142a0d256SVille Syrjälä { 91242a0d256SVille Syrjälä .active_pipes = BIT(PIPE_B) | BIT(PIPE_C), 91342a0d256SVille Syrjälä .dbuf_mask = { 91442a0d256SVille Syrjälä [PIPE_B] = BIT(DBUF_S1), 91542a0d256SVille Syrjälä [PIPE_C] = BIT(DBUF_S2), 91642a0d256SVille Syrjälä }, 91742a0d256SVille Syrjälä }, 91842a0d256SVille Syrjälä { 91942a0d256SVille Syrjälä .active_pipes = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C), 92042a0d256SVille Syrjälä .dbuf_mask = { 92142a0d256SVille Syrjälä [PIPE_A] = BIT(DBUF_S1), 92242a0d256SVille Syrjälä [PIPE_B] = BIT(DBUF_S1), 92342a0d256SVille Syrjälä [PIPE_C] = BIT(DBUF_S2), 92442a0d256SVille Syrjälä }, 92542a0d256SVille Syrjälä }, 92642a0d256SVille Syrjälä { 92742a0d256SVille Syrjälä .active_pipes = BIT(PIPE_D), 92842a0d256SVille Syrjälä .dbuf_mask = { 92942a0d256SVille Syrjälä [PIPE_D] = BIT(DBUF_S2) | BIT(DBUF_S1), 93042a0d256SVille Syrjälä }, 93142a0d256SVille Syrjälä }, 93242a0d256SVille Syrjälä { 93342a0d256SVille Syrjälä .active_pipes = BIT(PIPE_A) | BIT(PIPE_D), 93442a0d256SVille Syrjälä .dbuf_mask = { 93542a0d256SVille Syrjälä [PIPE_A] = BIT(DBUF_S1), 93642a0d256SVille Syrjälä [PIPE_D] = BIT(DBUF_S2), 93742a0d256SVille Syrjälä }, 93842a0d256SVille Syrjälä }, 93942a0d256SVille Syrjälä { 94042a0d256SVille Syrjälä .active_pipes = BIT(PIPE_B) | BIT(PIPE_D), 94142a0d256SVille Syrjälä .dbuf_mask = { 94242a0d256SVille Syrjälä [PIPE_B] = BIT(DBUF_S1), 94342a0d256SVille Syrjälä [PIPE_D] = BIT(DBUF_S2), 94442a0d256SVille Syrjälä }, 94542a0d256SVille Syrjälä }, 94642a0d256SVille Syrjälä { 94742a0d256SVille Syrjälä .active_pipes = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_D), 94842a0d256SVille Syrjälä .dbuf_mask = { 94942a0d256SVille Syrjälä [PIPE_A] = BIT(DBUF_S1), 95042a0d256SVille Syrjälä [PIPE_B] = BIT(DBUF_S1), 95142a0d256SVille Syrjälä [PIPE_D] = BIT(DBUF_S2), 95242a0d256SVille Syrjälä }, 95342a0d256SVille Syrjälä }, 95442a0d256SVille Syrjälä { 95542a0d256SVille Syrjälä .active_pipes = BIT(PIPE_C) | BIT(PIPE_D), 95642a0d256SVille Syrjälä .dbuf_mask = { 95742a0d256SVille Syrjälä [PIPE_C] = BIT(DBUF_S1), 95842a0d256SVille Syrjälä [PIPE_D] = BIT(DBUF_S2), 95942a0d256SVille Syrjälä }, 96042a0d256SVille Syrjälä }, 96142a0d256SVille Syrjälä { 96242a0d256SVille Syrjälä .active_pipes = BIT(PIPE_A) | BIT(PIPE_C) | BIT(PIPE_D), 96342a0d256SVille Syrjälä .dbuf_mask = { 96442a0d256SVille Syrjälä [PIPE_A] = BIT(DBUF_S1), 96542a0d256SVille Syrjälä [PIPE_C] = BIT(DBUF_S2), 96642a0d256SVille Syrjälä [PIPE_D] = BIT(DBUF_S2), 96742a0d256SVille Syrjälä }, 96842a0d256SVille Syrjälä }, 96942a0d256SVille Syrjälä { 97042a0d256SVille Syrjälä .active_pipes = BIT(PIPE_B) | BIT(PIPE_C) | BIT(PIPE_D), 97142a0d256SVille Syrjälä .dbuf_mask = { 97242a0d256SVille Syrjälä [PIPE_B] = BIT(DBUF_S1), 97342a0d256SVille Syrjälä [PIPE_C] = BIT(DBUF_S2), 97442a0d256SVille Syrjälä [PIPE_D] = BIT(DBUF_S2), 97542a0d256SVille Syrjälä }, 97642a0d256SVille Syrjälä }, 97742a0d256SVille Syrjälä { 97842a0d256SVille Syrjälä .active_pipes = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C) | BIT(PIPE_D), 97942a0d256SVille Syrjälä .dbuf_mask = { 98042a0d256SVille Syrjälä [PIPE_A] = BIT(DBUF_S1), 98142a0d256SVille Syrjälä [PIPE_B] = BIT(DBUF_S1), 98242a0d256SVille Syrjälä [PIPE_C] = BIT(DBUF_S2), 98342a0d256SVille Syrjälä [PIPE_D] = BIT(DBUF_S2), 98442a0d256SVille Syrjälä }, 98542a0d256SVille Syrjälä }, 98642a0d256SVille Syrjälä {} 98742a0d256SVille Syrjälä }; 98842a0d256SVille Syrjälä 98942a0d256SVille Syrjälä static const struct dbuf_slice_conf_entry dg2_allowed_dbufs[] = { 99042a0d256SVille Syrjälä { 99142a0d256SVille Syrjälä .active_pipes = BIT(PIPE_A), 99242a0d256SVille Syrjälä .dbuf_mask = { 99342a0d256SVille Syrjälä [PIPE_A] = BIT(DBUF_S1) | BIT(DBUF_S2), 99442a0d256SVille Syrjälä }, 99542a0d256SVille Syrjälä }, 99642a0d256SVille Syrjälä { 99742a0d256SVille Syrjälä .active_pipes = BIT(PIPE_B), 99842a0d256SVille Syrjälä .dbuf_mask = { 99942a0d256SVille Syrjälä [PIPE_B] = BIT(DBUF_S1) | BIT(DBUF_S2), 100042a0d256SVille Syrjälä }, 100142a0d256SVille Syrjälä }, 100242a0d256SVille Syrjälä { 100342a0d256SVille Syrjälä .active_pipes = BIT(PIPE_A) | BIT(PIPE_B), 100442a0d256SVille Syrjälä .dbuf_mask = { 100542a0d256SVille Syrjälä [PIPE_A] = BIT(DBUF_S1), 100642a0d256SVille Syrjälä [PIPE_B] = BIT(DBUF_S2), 100742a0d256SVille Syrjälä }, 100842a0d256SVille Syrjälä }, 100942a0d256SVille Syrjälä { 101042a0d256SVille Syrjälä .active_pipes = BIT(PIPE_C), 101142a0d256SVille Syrjälä .dbuf_mask = { 101242a0d256SVille Syrjälä [PIPE_C] = BIT(DBUF_S3) | BIT(DBUF_S4), 101342a0d256SVille Syrjälä }, 101442a0d256SVille Syrjälä }, 101542a0d256SVille Syrjälä { 101642a0d256SVille Syrjälä .active_pipes = BIT(PIPE_A) | BIT(PIPE_C), 101742a0d256SVille Syrjälä .dbuf_mask = { 101842a0d256SVille Syrjälä [PIPE_A] = BIT(DBUF_S1) | BIT(DBUF_S2), 101942a0d256SVille Syrjälä [PIPE_C] = BIT(DBUF_S3) | BIT(DBUF_S4), 102042a0d256SVille Syrjälä }, 102142a0d256SVille Syrjälä }, 102242a0d256SVille Syrjälä { 102342a0d256SVille Syrjälä .active_pipes = BIT(PIPE_B) | BIT(PIPE_C), 102442a0d256SVille Syrjälä .dbuf_mask = { 102542a0d256SVille Syrjälä [PIPE_B] = BIT(DBUF_S1) | BIT(DBUF_S2), 102642a0d256SVille Syrjälä [PIPE_C] = BIT(DBUF_S3) | BIT(DBUF_S4), 102742a0d256SVille Syrjälä }, 102842a0d256SVille Syrjälä }, 102942a0d256SVille Syrjälä { 103042a0d256SVille Syrjälä .active_pipes = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C), 103142a0d256SVille Syrjälä .dbuf_mask = { 103242a0d256SVille Syrjälä [PIPE_A] = BIT(DBUF_S1), 103342a0d256SVille Syrjälä [PIPE_B] = BIT(DBUF_S2), 103442a0d256SVille Syrjälä [PIPE_C] = BIT(DBUF_S3) | BIT(DBUF_S4), 103542a0d256SVille Syrjälä }, 103642a0d256SVille Syrjälä }, 103742a0d256SVille Syrjälä { 103842a0d256SVille Syrjälä .active_pipes = BIT(PIPE_D), 103942a0d256SVille Syrjälä .dbuf_mask = { 104042a0d256SVille Syrjälä [PIPE_D] = BIT(DBUF_S3) | BIT(DBUF_S4), 104142a0d256SVille Syrjälä }, 104242a0d256SVille Syrjälä }, 104342a0d256SVille Syrjälä { 104442a0d256SVille Syrjälä .active_pipes = BIT(PIPE_A) | BIT(PIPE_D), 104542a0d256SVille Syrjälä .dbuf_mask = { 104642a0d256SVille Syrjälä [PIPE_A] = BIT(DBUF_S1) | BIT(DBUF_S2), 104742a0d256SVille Syrjälä [PIPE_D] = BIT(DBUF_S3) | BIT(DBUF_S4), 104842a0d256SVille Syrjälä }, 104942a0d256SVille Syrjälä }, 105042a0d256SVille Syrjälä { 105142a0d256SVille Syrjälä .active_pipes = BIT(PIPE_B) | BIT(PIPE_D), 105242a0d256SVille Syrjälä .dbuf_mask = { 105342a0d256SVille Syrjälä [PIPE_B] = BIT(DBUF_S1) | BIT(DBUF_S2), 105442a0d256SVille Syrjälä [PIPE_D] = BIT(DBUF_S3) | BIT(DBUF_S4), 105542a0d256SVille Syrjälä }, 105642a0d256SVille Syrjälä }, 105742a0d256SVille Syrjälä { 105842a0d256SVille Syrjälä .active_pipes = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_D), 105942a0d256SVille Syrjälä .dbuf_mask = { 106042a0d256SVille Syrjälä [PIPE_A] = BIT(DBUF_S1), 106142a0d256SVille Syrjälä [PIPE_B] = BIT(DBUF_S2), 106242a0d256SVille Syrjälä [PIPE_D] = BIT(DBUF_S3) | BIT(DBUF_S4), 106342a0d256SVille Syrjälä }, 106442a0d256SVille Syrjälä }, 106542a0d256SVille Syrjälä { 106642a0d256SVille Syrjälä .active_pipes = BIT(PIPE_C) | BIT(PIPE_D), 106742a0d256SVille Syrjälä .dbuf_mask = { 106842a0d256SVille Syrjälä [PIPE_C] = BIT(DBUF_S3), 106942a0d256SVille Syrjälä [PIPE_D] = BIT(DBUF_S4), 107042a0d256SVille Syrjälä }, 107142a0d256SVille Syrjälä }, 107242a0d256SVille Syrjälä { 107342a0d256SVille Syrjälä .active_pipes = BIT(PIPE_A) | BIT(PIPE_C) | BIT(PIPE_D), 107442a0d256SVille Syrjälä .dbuf_mask = { 107542a0d256SVille Syrjälä [PIPE_A] = BIT(DBUF_S1) | BIT(DBUF_S2), 107642a0d256SVille Syrjälä [PIPE_C] = BIT(DBUF_S3), 107742a0d256SVille Syrjälä [PIPE_D] = BIT(DBUF_S4), 107842a0d256SVille Syrjälä }, 107942a0d256SVille Syrjälä }, 108042a0d256SVille Syrjälä { 108142a0d256SVille Syrjälä .active_pipes = BIT(PIPE_B) | BIT(PIPE_C) | BIT(PIPE_D), 108242a0d256SVille Syrjälä .dbuf_mask = { 108342a0d256SVille Syrjälä [PIPE_B] = BIT(DBUF_S1) | BIT(DBUF_S2), 108442a0d256SVille Syrjälä [PIPE_C] = BIT(DBUF_S3), 108542a0d256SVille Syrjälä [PIPE_D] = BIT(DBUF_S4), 108642a0d256SVille Syrjälä }, 108742a0d256SVille Syrjälä }, 108842a0d256SVille Syrjälä { 108942a0d256SVille Syrjälä .active_pipes = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C) | BIT(PIPE_D), 109042a0d256SVille Syrjälä .dbuf_mask = { 109142a0d256SVille Syrjälä [PIPE_A] = BIT(DBUF_S1), 109242a0d256SVille Syrjälä [PIPE_B] = BIT(DBUF_S2), 109342a0d256SVille Syrjälä [PIPE_C] = BIT(DBUF_S3), 109442a0d256SVille Syrjälä [PIPE_D] = BIT(DBUF_S4), 109542a0d256SVille Syrjälä }, 109642a0d256SVille Syrjälä }, 109742a0d256SVille Syrjälä {} 109842a0d256SVille Syrjälä }; 109942a0d256SVille Syrjälä 110042a0d256SVille Syrjälä static const struct dbuf_slice_conf_entry adlp_allowed_dbufs[] = { 110142a0d256SVille Syrjälä /* 110242a0d256SVille Syrjälä * Keep the join_mbus cases first so check_mbus_joined() 110342a0d256SVille Syrjälä * will prefer them over the !join_mbus cases. 110442a0d256SVille Syrjälä */ 110542a0d256SVille Syrjälä { 110642a0d256SVille Syrjälä .active_pipes = BIT(PIPE_A), 110742a0d256SVille Syrjälä .dbuf_mask = { 110842a0d256SVille Syrjälä [PIPE_A] = BIT(DBUF_S1) | BIT(DBUF_S2) | BIT(DBUF_S3) | BIT(DBUF_S4), 110942a0d256SVille Syrjälä }, 111042a0d256SVille Syrjälä .join_mbus = true, 111142a0d256SVille Syrjälä }, 111242a0d256SVille Syrjälä { 111342a0d256SVille Syrjälä .active_pipes = BIT(PIPE_B), 111442a0d256SVille Syrjälä .dbuf_mask = { 111542a0d256SVille Syrjälä [PIPE_B] = BIT(DBUF_S1) | BIT(DBUF_S2) | BIT(DBUF_S3) | BIT(DBUF_S4), 111642a0d256SVille Syrjälä }, 111742a0d256SVille Syrjälä .join_mbus = true, 111842a0d256SVille Syrjälä }, 111942a0d256SVille Syrjälä { 112042a0d256SVille Syrjälä .active_pipes = BIT(PIPE_A), 112142a0d256SVille Syrjälä .dbuf_mask = { 112242a0d256SVille Syrjälä [PIPE_A] = BIT(DBUF_S1) | BIT(DBUF_S2), 112342a0d256SVille Syrjälä }, 112442a0d256SVille Syrjälä .join_mbus = false, 112542a0d256SVille Syrjälä }, 112642a0d256SVille Syrjälä { 112742a0d256SVille Syrjälä .active_pipes = BIT(PIPE_B), 112842a0d256SVille Syrjälä .dbuf_mask = { 112942a0d256SVille Syrjälä [PIPE_B] = BIT(DBUF_S3) | BIT(DBUF_S4), 113042a0d256SVille Syrjälä }, 113142a0d256SVille Syrjälä .join_mbus = false, 113242a0d256SVille Syrjälä }, 113342a0d256SVille Syrjälä { 113442a0d256SVille Syrjälä .active_pipes = BIT(PIPE_A) | BIT(PIPE_B), 113542a0d256SVille Syrjälä .dbuf_mask = { 113642a0d256SVille Syrjälä [PIPE_A] = BIT(DBUF_S1) | BIT(DBUF_S2), 113742a0d256SVille Syrjälä [PIPE_B] = BIT(DBUF_S3) | BIT(DBUF_S4), 113842a0d256SVille Syrjälä }, 113942a0d256SVille Syrjälä }, 114042a0d256SVille Syrjälä { 114142a0d256SVille Syrjälä .active_pipes = BIT(PIPE_C), 114242a0d256SVille Syrjälä .dbuf_mask = { 114342a0d256SVille Syrjälä [PIPE_C] = BIT(DBUF_S3) | BIT(DBUF_S4), 114442a0d256SVille Syrjälä }, 114542a0d256SVille Syrjälä }, 114642a0d256SVille Syrjälä { 114742a0d256SVille Syrjälä .active_pipes = BIT(PIPE_A) | BIT(PIPE_C), 114842a0d256SVille Syrjälä .dbuf_mask = { 114942a0d256SVille Syrjälä [PIPE_A] = BIT(DBUF_S1) | BIT(DBUF_S2), 115042a0d256SVille Syrjälä [PIPE_C] = BIT(DBUF_S3) | BIT(DBUF_S4), 115142a0d256SVille Syrjälä }, 115242a0d256SVille Syrjälä }, 115342a0d256SVille Syrjälä { 115442a0d256SVille Syrjälä .active_pipes = BIT(PIPE_B) | BIT(PIPE_C), 115542a0d256SVille Syrjälä .dbuf_mask = { 115642a0d256SVille Syrjälä [PIPE_B] = BIT(DBUF_S3) | BIT(DBUF_S4), 115742a0d256SVille Syrjälä [PIPE_C] = BIT(DBUF_S3) | BIT(DBUF_S4), 115842a0d256SVille Syrjälä }, 115942a0d256SVille Syrjälä }, 116042a0d256SVille Syrjälä { 116142a0d256SVille Syrjälä .active_pipes = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C), 116242a0d256SVille Syrjälä .dbuf_mask = { 116342a0d256SVille Syrjälä [PIPE_A] = BIT(DBUF_S1) | BIT(DBUF_S2), 116442a0d256SVille Syrjälä [PIPE_B] = BIT(DBUF_S3) | BIT(DBUF_S4), 116542a0d256SVille Syrjälä [PIPE_C] = BIT(DBUF_S3) | BIT(DBUF_S4), 116642a0d256SVille Syrjälä }, 116742a0d256SVille Syrjälä }, 116842a0d256SVille Syrjälä { 116942a0d256SVille Syrjälä .active_pipes = BIT(PIPE_D), 117042a0d256SVille Syrjälä .dbuf_mask = { 117142a0d256SVille Syrjälä [PIPE_D] = BIT(DBUF_S1) | BIT(DBUF_S2), 117242a0d256SVille Syrjälä }, 117342a0d256SVille Syrjälä }, 117442a0d256SVille Syrjälä { 117542a0d256SVille Syrjälä .active_pipes = BIT(PIPE_A) | BIT(PIPE_D), 117642a0d256SVille Syrjälä .dbuf_mask = { 117742a0d256SVille Syrjälä [PIPE_A] = BIT(DBUF_S1) | BIT(DBUF_S2), 117842a0d256SVille Syrjälä [PIPE_D] = BIT(DBUF_S1) | BIT(DBUF_S2), 117942a0d256SVille Syrjälä }, 118042a0d256SVille Syrjälä }, 118142a0d256SVille Syrjälä { 118242a0d256SVille Syrjälä .active_pipes = BIT(PIPE_B) | BIT(PIPE_D), 118342a0d256SVille Syrjälä .dbuf_mask = { 118442a0d256SVille Syrjälä [PIPE_B] = BIT(DBUF_S3) | BIT(DBUF_S4), 118542a0d256SVille Syrjälä [PIPE_D] = BIT(DBUF_S1) | BIT(DBUF_S2), 118642a0d256SVille Syrjälä }, 118742a0d256SVille Syrjälä }, 118842a0d256SVille Syrjälä { 118942a0d256SVille Syrjälä .active_pipes = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_D), 119042a0d256SVille Syrjälä .dbuf_mask = { 119142a0d256SVille Syrjälä [PIPE_A] = BIT(DBUF_S1) | BIT(DBUF_S2), 119242a0d256SVille Syrjälä [PIPE_B] = BIT(DBUF_S3) | BIT(DBUF_S4), 119342a0d256SVille Syrjälä [PIPE_D] = BIT(DBUF_S1) | BIT(DBUF_S2), 119442a0d256SVille Syrjälä }, 119542a0d256SVille Syrjälä }, 119642a0d256SVille Syrjälä { 119742a0d256SVille Syrjälä .active_pipes = BIT(PIPE_C) | BIT(PIPE_D), 119842a0d256SVille Syrjälä .dbuf_mask = { 119942a0d256SVille Syrjälä [PIPE_C] = BIT(DBUF_S3) | BIT(DBUF_S4), 120042a0d256SVille Syrjälä [PIPE_D] = BIT(DBUF_S1) | BIT(DBUF_S2), 120142a0d256SVille Syrjälä }, 120242a0d256SVille Syrjälä }, 120342a0d256SVille Syrjälä { 120442a0d256SVille Syrjälä .active_pipes = BIT(PIPE_A) | BIT(PIPE_C) | BIT(PIPE_D), 120542a0d256SVille Syrjälä .dbuf_mask = { 120642a0d256SVille Syrjälä [PIPE_A] = BIT(DBUF_S1) | BIT(DBUF_S2), 120742a0d256SVille Syrjälä [PIPE_C] = BIT(DBUF_S3) | BIT(DBUF_S4), 120842a0d256SVille Syrjälä [PIPE_D] = BIT(DBUF_S1) | BIT(DBUF_S2), 120942a0d256SVille Syrjälä }, 121042a0d256SVille Syrjälä }, 121142a0d256SVille Syrjälä { 121242a0d256SVille Syrjälä .active_pipes = BIT(PIPE_B) | BIT(PIPE_C) | BIT(PIPE_D), 121342a0d256SVille Syrjälä .dbuf_mask = { 121442a0d256SVille Syrjälä [PIPE_B] = BIT(DBUF_S3) | BIT(DBUF_S4), 121542a0d256SVille Syrjälä [PIPE_C] = BIT(DBUF_S3) | BIT(DBUF_S4), 121642a0d256SVille Syrjälä [PIPE_D] = BIT(DBUF_S1) | BIT(DBUF_S2), 121742a0d256SVille Syrjälä }, 121842a0d256SVille Syrjälä }, 121942a0d256SVille Syrjälä { 122042a0d256SVille Syrjälä .active_pipes = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C) | BIT(PIPE_D), 122142a0d256SVille Syrjälä .dbuf_mask = { 122242a0d256SVille Syrjälä [PIPE_A] = BIT(DBUF_S1) | BIT(DBUF_S2), 122342a0d256SVille Syrjälä [PIPE_B] = BIT(DBUF_S3) | BIT(DBUF_S4), 122442a0d256SVille Syrjälä [PIPE_C] = BIT(DBUF_S3) | BIT(DBUF_S4), 122542a0d256SVille Syrjälä [PIPE_D] = BIT(DBUF_S1) | BIT(DBUF_S2), 122642a0d256SVille Syrjälä }, 122742a0d256SVille Syrjälä }, 122842a0d256SVille Syrjälä {} 122942a0d256SVille Syrjälä 123042a0d256SVille Syrjälä }; 123142a0d256SVille Syrjälä 123242a0d256SVille Syrjälä static bool check_mbus_joined(u8 active_pipes, 123342a0d256SVille Syrjälä const struct dbuf_slice_conf_entry *dbuf_slices) 123442a0d256SVille Syrjälä { 123542a0d256SVille Syrjälä int i; 123642a0d256SVille Syrjälä 123742a0d256SVille Syrjälä for (i = 0; dbuf_slices[i].active_pipes != 0; i++) { 123842a0d256SVille Syrjälä if (dbuf_slices[i].active_pipes == active_pipes) 123942a0d256SVille Syrjälä return dbuf_slices[i].join_mbus; 124042a0d256SVille Syrjälä } 124142a0d256SVille Syrjälä return false; 124242a0d256SVille Syrjälä } 124342a0d256SVille Syrjälä 124442a0d256SVille Syrjälä static bool adlp_check_mbus_joined(u8 active_pipes) 124542a0d256SVille Syrjälä { 124642a0d256SVille Syrjälä return check_mbus_joined(active_pipes, adlp_allowed_dbufs); 124742a0d256SVille Syrjälä } 124842a0d256SVille Syrjälä 124942a0d256SVille Syrjälä static u8 compute_dbuf_slices(enum pipe pipe, u8 active_pipes, bool join_mbus, 125042a0d256SVille Syrjälä const struct dbuf_slice_conf_entry *dbuf_slices) 125142a0d256SVille Syrjälä { 125242a0d256SVille Syrjälä int i; 125342a0d256SVille Syrjälä 125442a0d256SVille Syrjälä for (i = 0; dbuf_slices[i].active_pipes != 0; i++) { 125542a0d256SVille Syrjälä if (dbuf_slices[i].active_pipes == active_pipes && 125642a0d256SVille Syrjälä dbuf_slices[i].join_mbus == join_mbus) 125742a0d256SVille Syrjälä return dbuf_slices[i].dbuf_mask[pipe]; 125842a0d256SVille Syrjälä } 125942a0d256SVille Syrjälä return 0; 126042a0d256SVille Syrjälä } 126142a0d256SVille Syrjälä 126242a0d256SVille Syrjälä /* 126342a0d256SVille Syrjälä * This function finds an entry with same enabled pipe configuration and 126442a0d256SVille Syrjälä * returns correspondent DBuf slice mask as stated in BSpec for particular 126542a0d256SVille Syrjälä * platform. 126642a0d256SVille Syrjälä */ 126742a0d256SVille Syrjälä static u8 icl_compute_dbuf_slices(enum pipe pipe, u8 active_pipes, bool join_mbus) 126842a0d256SVille Syrjälä { 126942a0d256SVille Syrjälä /* 127042a0d256SVille Syrjälä * FIXME: For ICL this is still a bit unclear as prev BSpec revision 127142a0d256SVille Syrjälä * required calculating "pipe ratio" in order to determine 127242a0d256SVille Syrjälä * if one or two slices can be used for single pipe configurations 127342a0d256SVille Syrjälä * as additional constraint to the existing table. 127442a0d256SVille Syrjälä * However based on recent info, it should be not "pipe ratio" 127542a0d256SVille Syrjälä * but rather ratio between pixel_rate and cdclk with additional 127642a0d256SVille Syrjälä * constants, so for now we are using only table until this is 127742a0d256SVille Syrjälä * clarified. Also this is the reason why crtc_state param is 127842a0d256SVille Syrjälä * still here - we will need it once those additional constraints 127942a0d256SVille Syrjälä * pop up. 128042a0d256SVille Syrjälä */ 128142a0d256SVille Syrjälä return compute_dbuf_slices(pipe, active_pipes, join_mbus, 128242a0d256SVille Syrjälä icl_allowed_dbufs); 128342a0d256SVille Syrjälä } 128442a0d256SVille Syrjälä 128542a0d256SVille Syrjälä static u8 tgl_compute_dbuf_slices(enum pipe pipe, u8 active_pipes, bool join_mbus) 128642a0d256SVille Syrjälä { 128742a0d256SVille Syrjälä return compute_dbuf_slices(pipe, active_pipes, join_mbus, 128842a0d256SVille Syrjälä tgl_allowed_dbufs); 128942a0d256SVille Syrjälä } 129042a0d256SVille Syrjälä 129142a0d256SVille Syrjälä static u8 adlp_compute_dbuf_slices(enum pipe pipe, u8 active_pipes, bool join_mbus) 129242a0d256SVille Syrjälä { 129342a0d256SVille Syrjälä return compute_dbuf_slices(pipe, active_pipes, join_mbus, 129442a0d256SVille Syrjälä adlp_allowed_dbufs); 129542a0d256SVille Syrjälä } 129642a0d256SVille Syrjälä 129742a0d256SVille Syrjälä static u8 dg2_compute_dbuf_slices(enum pipe pipe, u8 active_pipes, bool join_mbus) 129842a0d256SVille Syrjälä { 129942a0d256SVille Syrjälä return compute_dbuf_slices(pipe, active_pipes, join_mbus, 130042a0d256SVille Syrjälä dg2_allowed_dbufs); 130142a0d256SVille Syrjälä } 130242a0d256SVille Syrjälä 130342a0d256SVille Syrjälä static u8 skl_compute_dbuf_slices(struct intel_crtc *crtc, u8 active_pipes, bool join_mbus) 130442a0d256SVille Syrjälä { 130542a0d256SVille Syrjälä struct drm_i915_private *i915 = to_i915(crtc->base.dev); 130642a0d256SVille Syrjälä enum pipe pipe = crtc->pipe; 130742a0d256SVille Syrjälä 130842a0d256SVille Syrjälä if (IS_DG2(i915)) 130942a0d256SVille Syrjälä return dg2_compute_dbuf_slices(pipe, active_pipes, join_mbus); 131042a0d256SVille Syrjälä else if (DISPLAY_VER(i915) >= 13) 131142a0d256SVille Syrjälä return adlp_compute_dbuf_slices(pipe, active_pipes, join_mbus); 131242a0d256SVille Syrjälä else if (DISPLAY_VER(i915) == 12) 131342a0d256SVille Syrjälä return tgl_compute_dbuf_slices(pipe, active_pipes, join_mbus); 131442a0d256SVille Syrjälä else if (DISPLAY_VER(i915) == 11) 131542a0d256SVille Syrjälä return icl_compute_dbuf_slices(pipe, active_pipes, join_mbus); 131642a0d256SVille Syrjälä /* 131742a0d256SVille Syrjälä * For anything else just return one slice yet. 131842a0d256SVille Syrjälä * Should be extended for other platforms. 131942a0d256SVille Syrjälä */ 132042a0d256SVille Syrjälä return active_pipes & BIT(pipe) ? BIT(DBUF_S1) : 0; 132142a0d256SVille Syrjälä } 132242a0d256SVille Syrjälä 132342a0d256SVille Syrjälä static bool 132442a0d256SVille Syrjälä use_minimal_wm0_only(const struct intel_crtc_state *crtc_state, 132542a0d256SVille Syrjälä struct intel_plane *plane) 132642a0d256SVille Syrjälä { 132742a0d256SVille Syrjälä struct drm_i915_private *i915 = to_i915(plane->base.dev); 132842a0d256SVille Syrjälä 132942a0d256SVille Syrjälä return DISPLAY_VER(i915) >= 13 && 133042a0d256SVille Syrjälä crtc_state->uapi.async_flip && 133142a0d256SVille Syrjälä plane->async_flip; 133242a0d256SVille Syrjälä } 133342a0d256SVille Syrjälä 133442a0d256SVille Syrjälä static u64 133542a0d256SVille Syrjälä skl_total_relative_data_rate(const struct intel_crtc_state *crtc_state) 133642a0d256SVille Syrjälä { 133742a0d256SVille Syrjälä struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 133842a0d256SVille Syrjälä struct drm_i915_private *i915 = to_i915(crtc->base.dev); 133942a0d256SVille Syrjälä enum plane_id plane_id; 134042a0d256SVille Syrjälä u64 data_rate = 0; 134142a0d256SVille Syrjälä 134242a0d256SVille Syrjälä for_each_plane_id_on_crtc(crtc, plane_id) { 134342a0d256SVille Syrjälä if (plane_id == PLANE_CURSOR) 134442a0d256SVille Syrjälä continue; 134542a0d256SVille Syrjälä 134642a0d256SVille Syrjälä data_rate += crtc_state->rel_data_rate[plane_id]; 134742a0d256SVille Syrjälä 134842a0d256SVille Syrjälä if (DISPLAY_VER(i915) < 11) 134942a0d256SVille Syrjälä data_rate += crtc_state->rel_data_rate_y[plane_id]; 135042a0d256SVille Syrjälä } 135142a0d256SVille Syrjälä 135242a0d256SVille Syrjälä return data_rate; 135342a0d256SVille Syrjälä } 135442a0d256SVille Syrjälä 135542a0d256SVille Syrjälä static const struct skl_wm_level * 135642a0d256SVille Syrjälä skl_plane_wm_level(const struct skl_pipe_wm *pipe_wm, 135742a0d256SVille Syrjälä enum plane_id plane_id, 135842a0d256SVille Syrjälä int level) 135942a0d256SVille Syrjälä { 136042a0d256SVille Syrjälä const struct skl_plane_wm *wm = &pipe_wm->planes[plane_id]; 136142a0d256SVille Syrjälä 136242a0d256SVille Syrjälä if (level == 0 && pipe_wm->use_sagv_wm) 136342a0d256SVille Syrjälä return &wm->sagv.wm0; 136442a0d256SVille Syrjälä 136542a0d256SVille Syrjälä return &wm->wm[level]; 136642a0d256SVille Syrjälä } 136742a0d256SVille Syrjälä 136842a0d256SVille Syrjälä static const struct skl_wm_level * 136942a0d256SVille Syrjälä skl_plane_trans_wm(const struct skl_pipe_wm *pipe_wm, 137042a0d256SVille Syrjälä enum plane_id plane_id) 137142a0d256SVille Syrjälä { 137242a0d256SVille Syrjälä const struct skl_plane_wm *wm = &pipe_wm->planes[plane_id]; 137342a0d256SVille Syrjälä 137442a0d256SVille Syrjälä if (pipe_wm->use_sagv_wm) 137542a0d256SVille Syrjälä return &wm->sagv.trans_wm; 137642a0d256SVille Syrjälä 137742a0d256SVille Syrjälä return &wm->trans_wm; 137842a0d256SVille Syrjälä } 137942a0d256SVille Syrjälä 138042a0d256SVille Syrjälä /* 138142a0d256SVille Syrjälä * We only disable the watermarks for each plane if 138242a0d256SVille Syrjälä * they exceed the ddb allocation of said plane. This 138342a0d256SVille Syrjälä * is done so that we don't end up touching cursor 138442a0d256SVille Syrjälä * watermarks needlessly when some other plane reduces 138542a0d256SVille Syrjälä * our max possible watermark level. 138642a0d256SVille Syrjälä * 138742a0d256SVille Syrjälä * Bspec has this to say about the PLANE_WM enable bit: 138842a0d256SVille Syrjälä * "All the watermarks at this level for all enabled 138942a0d256SVille Syrjälä * planes must be enabled before the level will be used." 139042a0d256SVille Syrjälä * So this is actually safe to do. 139142a0d256SVille Syrjälä */ 139242a0d256SVille Syrjälä static void 139342a0d256SVille Syrjälä skl_check_wm_level(struct skl_wm_level *wm, const struct skl_ddb_entry *ddb) 139442a0d256SVille Syrjälä { 139542a0d256SVille Syrjälä if (wm->min_ddb_alloc > skl_ddb_entry_size(ddb)) 139642a0d256SVille Syrjälä memset(wm, 0, sizeof(*wm)); 139742a0d256SVille Syrjälä } 139842a0d256SVille Syrjälä 139942a0d256SVille Syrjälä static void 140042a0d256SVille Syrjälä skl_check_nv12_wm_level(struct skl_wm_level *wm, struct skl_wm_level *uv_wm, 140142a0d256SVille Syrjälä const struct skl_ddb_entry *ddb_y, const struct skl_ddb_entry *ddb) 140242a0d256SVille Syrjälä { 140342a0d256SVille Syrjälä if (wm->min_ddb_alloc > skl_ddb_entry_size(ddb_y) || 140442a0d256SVille Syrjälä uv_wm->min_ddb_alloc > skl_ddb_entry_size(ddb)) { 140542a0d256SVille Syrjälä memset(wm, 0, sizeof(*wm)); 140642a0d256SVille Syrjälä memset(uv_wm, 0, sizeof(*uv_wm)); 140742a0d256SVille Syrjälä } 140842a0d256SVille Syrjälä } 140942a0d256SVille Syrjälä 141042a0d256SVille Syrjälä static bool icl_need_wm1_wa(struct drm_i915_private *i915, 141142a0d256SVille Syrjälä enum plane_id plane_id) 141242a0d256SVille Syrjälä { 141342a0d256SVille Syrjälä /* 141442a0d256SVille Syrjälä * Wa_1408961008:icl, ehl 141542a0d256SVille Syrjälä * Wa_14012656716:tgl, adl 141642a0d256SVille Syrjälä * Underruns with WM1+ disabled 141742a0d256SVille Syrjälä */ 141842a0d256SVille Syrjälä return DISPLAY_VER(i915) == 11 || 141942a0d256SVille Syrjälä (IS_DISPLAY_VER(i915, 12, 13) && plane_id == PLANE_CURSOR); 142042a0d256SVille Syrjälä } 142142a0d256SVille Syrjälä 142242a0d256SVille Syrjälä struct skl_plane_ddb_iter { 142342a0d256SVille Syrjälä u64 data_rate; 142442a0d256SVille Syrjälä u16 start, size; 142542a0d256SVille Syrjälä }; 142642a0d256SVille Syrjälä 142742a0d256SVille Syrjälä static void 142842a0d256SVille Syrjälä skl_allocate_plane_ddb(struct skl_plane_ddb_iter *iter, 142942a0d256SVille Syrjälä struct skl_ddb_entry *ddb, 143042a0d256SVille Syrjälä const struct skl_wm_level *wm, 143142a0d256SVille Syrjälä u64 data_rate) 143242a0d256SVille Syrjälä { 143342a0d256SVille Syrjälä u16 size, extra = 0; 143442a0d256SVille Syrjälä 143542a0d256SVille Syrjälä if (data_rate) { 143642a0d256SVille Syrjälä extra = min_t(u16, iter->size, 143742a0d256SVille Syrjälä DIV64_U64_ROUND_UP(iter->size * data_rate, 143842a0d256SVille Syrjälä iter->data_rate)); 143942a0d256SVille Syrjälä iter->size -= extra; 144042a0d256SVille Syrjälä iter->data_rate -= data_rate; 144142a0d256SVille Syrjälä } 144242a0d256SVille Syrjälä 144342a0d256SVille Syrjälä /* 144442a0d256SVille Syrjälä * Keep ddb entry of all disabled planes explicitly zeroed 144542a0d256SVille Syrjälä * to avoid skl_ddb_add_affected_planes() adding them to 144642a0d256SVille Syrjälä * the state when other planes change their allocations. 144742a0d256SVille Syrjälä */ 144842a0d256SVille Syrjälä size = wm->min_ddb_alloc + extra; 144942a0d256SVille Syrjälä if (size) 145042a0d256SVille Syrjälä iter->start = skl_ddb_entry_init(ddb, iter->start, 145142a0d256SVille Syrjälä iter->start + size); 145242a0d256SVille Syrjälä } 145342a0d256SVille Syrjälä 145442a0d256SVille Syrjälä static int 145542a0d256SVille Syrjälä skl_crtc_allocate_plane_ddb(struct intel_atomic_state *state, 145642a0d256SVille Syrjälä struct intel_crtc *crtc) 145742a0d256SVille Syrjälä { 145842a0d256SVille Syrjälä struct drm_i915_private *i915 = to_i915(crtc->base.dev); 145942a0d256SVille Syrjälä struct intel_crtc_state *crtc_state = 146042a0d256SVille Syrjälä intel_atomic_get_new_crtc_state(state, crtc); 146142a0d256SVille Syrjälä const struct intel_dbuf_state *dbuf_state = 146242a0d256SVille Syrjälä intel_atomic_get_new_dbuf_state(state); 146342a0d256SVille Syrjälä const struct skl_ddb_entry *alloc = &dbuf_state->ddb[crtc->pipe]; 146442a0d256SVille Syrjälä int num_active = hweight8(dbuf_state->active_pipes); 146542a0d256SVille Syrjälä struct skl_plane_ddb_iter iter; 146642a0d256SVille Syrjälä enum plane_id plane_id; 146742a0d256SVille Syrjälä u16 cursor_size; 146842a0d256SVille Syrjälä u32 blocks; 146942a0d256SVille Syrjälä int level; 147042a0d256SVille Syrjälä 147142a0d256SVille Syrjälä /* Clear the partitioning for disabled planes. */ 147242a0d256SVille Syrjälä memset(crtc_state->wm.skl.plane_ddb, 0, sizeof(crtc_state->wm.skl.plane_ddb)); 147342a0d256SVille Syrjälä memset(crtc_state->wm.skl.plane_ddb_y, 0, sizeof(crtc_state->wm.skl.plane_ddb_y)); 147442a0d256SVille Syrjälä 147542a0d256SVille Syrjälä if (!crtc_state->hw.active) 147642a0d256SVille Syrjälä return 0; 147742a0d256SVille Syrjälä 147842a0d256SVille Syrjälä iter.start = alloc->start; 147942a0d256SVille Syrjälä iter.size = skl_ddb_entry_size(alloc); 148042a0d256SVille Syrjälä if (iter.size == 0) 148142a0d256SVille Syrjälä return 0; 148242a0d256SVille Syrjälä 148342a0d256SVille Syrjälä /* Allocate fixed number of blocks for cursor. */ 148442a0d256SVille Syrjälä cursor_size = skl_cursor_allocation(crtc_state, num_active); 148542a0d256SVille Syrjälä iter.size -= cursor_size; 148642a0d256SVille Syrjälä skl_ddb_entry_init(&crtc_state->wm.skl.plane_ddb[PLANE_CURSOR], 148742a0d256SVille Syrjälä alloc->end - cursor_size, alloc->end); 148842a0d256SVille Syrjälä 148942a0d256SVille Syrjälä iter.data_rate = skl_total_relative_data_rate(crtc_state); 149042a0d256SVille Syrjälä 149142a0d256SVille Syrjälä /* 149242a0d256SVille Syrjälä * Find the highest watermark level for which we can satisfy the block 149342a0d256SVille Syrjälä * requirement of active planes. 149442a0d256SVille Syrjälä */ 149542a0d256SVille Syrjälä for (level = ilk_wm_max_level(i915); level >= 0; level--) { 149642a0d256SVille Syrjälä blocks = 0; 149742a0d256SVille Syrjälä for_each_plane_id_on_crtc(crtc, plane_id) { 149842a0d256SVille Syrjälä const struct skl_plane_wm *wm = 149942a0d256SVille Syrjälä &crtc_state->wm.skl.optimal.planes[plane_id]; 150042a0d256SVille Syrjälä 150142a0d256SVille Syrjälä if (plane_id == PLANE_CURSOR) { 150242a0d256SVille Syrjälä const struct skl_ddb_entry *ddb = 150342a0d256SVille Syrjälä &crtc_state->wm.skl.plane_ddb[plane_id]; 150442a0d256SVille Syrjälä 150542a0d256SVille Syrjälä if (wm->wm[level].min_ddb_alloc > skl_ddb_entry_size(ddb)) { 150642a0d256SVille Syrjälä drm_WARN_ON(&i915->drm, 150742a0d256SVille Syrjälä wm->wm[level].min_ddb_alloc != U16_MAX); 150842a0d256SVille Syrjälä blocks = U32_MAX; 150942a0d256SVille Syrjälä break; 151042a0d256SVille Syrjälä } 151142a0d256SVille Syrjälä continue; 151242a0d256SVille Syrjälä } 151342a0d256SVille Syrjälä 151442a0d256SVille Syrjälä blocks += wm->wm[level].min_ddb_alloc; 151542a0d256SVille Syrjälä blocks += wm->uv_wm[level].min_ddb_alloc; 151642a0d256SVille Syrjälä } 151742a0d256SVille Syrjälä 151842a0d256SVille Syrjälä if (blocks <= iter.size) { 151942a0d256SVille Syrjälä iter.size -= blocks; 152042a0d256SVille Syrjälä break; 152142a0d256SVille Syrjälä } 152242a0d256SVille Syrjälä } 152342a0d256SVille Syrjälä 152442a0d256SVille Syrjälä if (level < 0) { 152542a0d256SVille Syrjälä drm_dbg_kms(&i915->drm, 152642a0d256SVille Syrjälä "Requested display configuration exceeds system DDB limitations"); 152742a0d256SVille Syrjälä drm_dbg_kms(&i915->drm, "minimum required %d/%d\n", 152842a0d256SVille Syrjälä blocks, iter.size); 152942a0d256SVille Syrjälä return -EINVAL; 153042a0d256SVille Syrjälä } 153142a0d256SVille Syrjälä 153242a0d256SVille Syrjälä /* avoid the WARN later when we don't allocate any extra DDB */ 153342a0d256SVille Syrjälä if (iter.data_rate == 0) 153442a0d256SVille Syrjälä iter.size = 0; 153542a0d256SVille Syrjälä 153642a0d256SVille Syrjälä /* 153742a0d256SVille Syrjälä * Grant each plane the blocks it requires at the highest achievable 153842a0d256SVille Syrjälä * watermark level, plus an extra share of the leftover blocks 153942a0d256SVille Syrjälä * proportional to its relative data rate. 154042a0d256SVille Syrjälä */ 154142a0d256SVille Syrjälä for_each_plane_id_on_crtc(crtc, plane_id) { 154242a0d256SVille Syrjälä struct skl_ddb_entry *ddb = 154342a0d256SVille Syrjälä &crtc_state->wm.skl.plane_ddb[plane_id]; 154442a0d256SVille Syrjälä struct skl_ddb_entry *ddb_y = 154542a0d256SVille Syrjälä &crtc_state->wm.skl.plane_ddb_y[plane_id]; 154642a0d256SVille Syrjälä const struct skl_plane_wm *wm = 154742a0d256SVille Syrjälä &crtc_state->wm.skl.optimal.planes[plane_id]; 154842a0d256SVille Syrjälä 154942a0d256SVille Syrjälä if (plane_id == PLANE_CURSOR) 155042a0d256SVille Syrjälä continue; 155142a0d256SVille Syrjälä 155242a0d256SVille Syrjälä if (DISPLAY_VER(i915) < 11 && 155342a0d256SVille Syrjälä crtc_state->nv12_planes & BIT(plane_id)) { 155442a0d256SVille Syrjälä skl_allocate_plane_ddb(&iter, ddb_y, &wm->wm[level], 155542a0d256SVille Syrjälä crtc_state->rel_data_rate_y[plane_id]); 155642a0d256SVille Syrjälä skl_allocate_plane_ddb(&iter, ddb, &wm->uv_wm[level], 155742a0d256SVille Syrjälä crtc_state->rel_data_rate[plane_id]); 155842a0d256SVille Syrjälä } else { 155942a0d256SVille Syrjälä skl_allocate_plane_ddb(&iter, ddb, &wm->wm[level], 156042a0d256SVille Syrjälä crtc_state->rel_data_rate[plane_id]); 156142a0d256SVille Syrjälä } 156242a0d256SVille Syrjälä } 156342a0d256SVille Syrjälä drm_WARN_ON(&i915->drm, iter.size != 0 || iter.data_rate != 0); 156442a0d256SVille Syrjälä 156542a0d256SVille Syrjälä /* 156642a0d256SVille Syrjälä * When we calculated watermark values we didn't know how high 156742a0d256SVille Syrjälä * of a level we'd actually be able to hit, so we just marked 156842a0d256SVille Syrjälä * all levels as "enabled." Go back now and disable the ones 156942a0d256SVille Syrjälä * that aren't actually possible. 157042a0d256SVille Syrjälä */ 157142a0d256SVille Syrjälä for (level++; level <= ilk_wm_max_level(i915); level++) { 157242a0d256SVille Syrjälä for_each_plane_id_on_crtc(crtc, plane_id) { 157342a0d256SVille Syrjälä const struct skl_ddb_entry *ddb = 157442a0d256SVille Syrjälä &crtc_state->wm.skl.plane_ddb[plane_id]; 157542a0d256SVille Syrjälä const struct skl_ddb_entry *ddb_y = 157642a0d256SVille Syrjälä &crtc_state->wm.skl.plane_ddb_y[plane_id]; 157742a0d256SVille Syrjälä struct skl_plane_wm *wm = 157842a0d256SVille Syrjälä &crtc_state->wm.skl.optimal.planes[plane_id]; 157942a0d256SVille Syrjälä 158042a0d256SVille Syrjälä if (DISPLAY_VER(i915) < 11 && 158142a0d256SVille Syrjälä crtc_state->nv12_planes & BIT(plane_id)) 158242a0d256SVille Syrjälä skl_check_nv12_wm_level(&wm->wm[level], 158342a0d256SVille Syrjälä &wm->uv_wm[level], 158442a0d256SVille Syrjälä ddb_y, ddb); 158542a0d256SVille Syrjälä else 158642a0d256SVille Syrjälä skl_check_wm_level(&wm->wm[level], ddb); 158742a0d256SVille Syrjälä 158842a0d256SVille Syrjälä if (icl_need_wm1_wa(i915, plane_id) && 1589*c580c2d2SVille Syrjälä level == 1 && !wm->wm[level].enable && 1590*c580c2d2SVille Syrjälä wm->wm[0].enable) { 159142a0d256SVille Syrjälä wm->wm[level].blocks = wm->wm[0].blocks; 159242a0d256SVille Syrjälä wm->wm[level].lines = wm->wm[0].lines; 159342a0d256SVille Syrjälä wm->wm[level].ignore_lines = wm->wm[0].ignore_lines; 159442a0d256SVille Syrjälä } 159542a0d256SVille Syrjälä } 159642a0d256SVille Syrjälä } 159742a0d256SVille Syrjälä 159842a0d256SVille Syrjälä /* 159942a0d256SVille Syrjälä * Go back and disable the transition and SAGV watermarks 160042a0d256SVille Syrjälä * if it turns out we don't have enough DDB blocks for them. 160142a0d256SVille Syrjälä */ 160242a0d256SVille Syrjälä for_each_plane_id_on_crtc(crtc, plane_id) { 160342a0d256SVille Syrjälä const struct skl_ddb_entry *ddb = 160442a0d256SVille Syrjälä &crtc_state->wm.skl.plane_ddb[plane_id]; 160542a0d256SVille Syrjälä const struct skl_ddb_entry *ddb_y = 160642a0d256SVille Syrjälä &crtc_state->wm.skl.plane_ddb_y[plane_id]; 160742a0d256SVille Syrjälä struct skl_plane_wm *wm = 160842a0d256SVille Syrjälä &crtc_state->wm.skl.optimal.planes[plane_id]; 160942a0d256SVille Syrjälä 161042a0d256SVille Syrjälä if (DISPLAY_VER(i915) < 11 && 161142a0d256SVille Syrjälä crtc_state->nv12_planes & BIT(plane_id)) { 161242a0d256SVille Syrjälä skl_check_wm_level(&wm->trans_wm, ddb_y); 161342a0d256SVille Syrjälä } else { 161442a0d256SVille Syrjälä WARN_ON(skl_ddb_entry_size(ddb_y)); 161542a0d256SVille Syrjälä 161642a0d256SVille Syrjälä skl_check_wm_level(&wm->trans_wm, ddb); 161742a0d256SVille Syrjälä } 161842a0d256SVille Syrjälä 161942a0d256SVille Syrjälä skl_check_wm_level(&wm->sagv.wm0, ddb); 162042a0d256SVille Syrjälä skl_check_wm_level(&wm->sagv.trans_wm, ddb); 162142a0d256SVille Syrjälä } 162242a0d256SVille Syrjälä 162342a0d256SVille Syrjälä return 0; 162442a0d256SVille Syrjälä } 162542a0d256SVille Syrjälä 162642a0d256SVille Syrjälä /* 162742a0d256SVille Syrjälä * The max latency should be 257 (max the punit can code is 255 and we add 2us 162842a0d256SVille Syrjälä * for the read latency) and cpp should always be <= 8, so that 162942a0d256SVille Syrjälä * should allow pixel_rate up to ~2 GHz which seems sufficient since max 163042a0d256SVille Syrjälä * 2xcdclk is 1350 MHz and the pixel rate should never exceed that. 163142a0d256SVille Syrjälä */ 163242a0d256SVille Syrjälä static uint_fixed_16_16_t 163342a0d256SVille Syrjälä skl_wm_method1(const struct drm_i915_private *i915, u32 pixel_rate, 163442a0d256SVille Syrjälä u8 cpp, u32 latency, u32 dbuf_block_size) 163542a0d256SVille Syrjälä { 163642a0d256SVille Syrjälä u32 wm_intermediate_val; 163742a0d256SVille Syrjälä uint_fixed_16_16_t ret; 163842a0d256SVille Syrjälä 163942a0d256SVille Syrjälä if (latency == 0) 164042a0d256SVille Syrjälä return FP_16_16_MAX; 164142a0d256SVille Syrjälä 164242a0d256SVille Syrjälä wm_intermediate_val = latency * pixel_rate * cpp; 164342a0d256SVille Syrjälä ret = div_fixed16(wm_intermediate_val, 1000 * dbuf_block_size); 164442a0d256SVille Syrjälä 164542a0d256SVille Syrjälä if (DISPLAY_VER(i915) >= 10) 164642a0d256SVille Syrjälä ret = add_fixed16_u32(ret, 1); 164742a0d256SVille Syrjälä 164842a0d256SVille Syrjälä return ret; 164942a0d256SVille Syrjälä } 165042a0d256SVille Syrjälä 165142a0d256SVille Syrjälä static uint_fixed_16_16_t 165242a0d256SVille Syrjälä skl_wm_method2(u32 pixel_rate, u32 pipe_htotal, u32 latency, 165342a0d256SVille Syrjälä uint_fixed_16_16_t plane_blocks_per_line) 165442a0d256SVille Syrjälä { 165542a0d256SVille Syrjälä u32 wm_intermediate_val; 165642a0d256SVille Syrjälä uint_fixed_16_16_t ret; 165742a0d256SVille Syrjälä 165842a0d256SVille Syrjälä if (latency == 0) 165942a0d256SVille Syrjälä return FP_16_16_MAX; 166042a0d256SVille Syrjälä 166142a0d256SVille Syrjälä wm_intermediate_val = latency * pixel_rate; 166242a0d256SVille Syrjälä wm_intermediate_val = DIV_ROUND_UP(wm_intermediate_val, 166342a0d256SVille Syrjälä pipe_htotal * 1000); 166442a0d256SVille Syrjälä ret = mul_u32_fixed16(wm_intermediate_val, plane_blocks_per_line); 166542a0d256SVille Syrjälä return ret; 166642a0d256SVille Syrjälä } 166742a0d256SVille Syrjälä 166842a0d256SVille Syrjälä static uint_fixed_16_16_t 166942a0d256SVille Syrjälä intel_get_linetime_us(const struct intel_crtc_state *crtc_state) 167042a0d256SVille Syrjälä { 167142a0d256SVille Syrjälä struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); 167242a0d256SVille Syrjälä u32 pixel_rate; 167342a0d256SVille Syrjälä u32 crtc_htotal; 167442a0d256SVille Syrjälä uint_fixed_16_16_t linetime_us; 167542a0d256SVille Syrjälä 167642a0d256SVille Syrjälä if (!crtc_state->hw.active) 167742a0d256SVille Syrjälä return u32_to_fixed16(0); 167842a0d256SVille Syrjälä 167942a0d256SVille Syrjälä pixel_rate = crtc_state->pixel_rate; 168042a0d256SVille Syrjälä 168142a0d256SVille Syrjälä if (drm_WARN_ON(&i915->drm, pixel_rate == 0)) 168242a0d256SVille Syrjälä return u32_to_fixed16(0); 168342a0d256SVille Syrjälä 168442a0d256SVille Syrjälä crtc_htotal = crtc_state->hw.pipe_mode.crtc_htotal; 168542a0d256SVille Syrjälä linetime_us = div_fixed16(crtc_htotal * 1000, pixel_rate); 168642a0d256SVille Syrjälä 168742a0d256SVille Syrjälä return linetime_us; 168842a0d256SVille Syrjälä } 168942a0d256SVille Syrjälä 169042a0d256SVille Syrjälä static int 169142a0d256SVille Syrjälä skl_compute_wm_params(const struct intel_crtc_state *crtc_state, 169242a0d256SVille Syrjälä int width, const struct drm_format_info *format, 169342a0d256SVille Syrjälä u64 modifier, unsigned int rotation, 169442a0d256SVille Syrjälä u32 plane_pixel_rate, struct skl_wm_params *wp, 169542a0d256SVille Syrjälä int color_plane) 169642a0d256SVille Syrjälä { 169742a0d256SVille Syrjälä struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 169842a0d256SVille Syrjälä struct drm_i915_private *i915 = to_i915(crtc->base.dev); 169942a0d256SVille Syrjälä u32 interm_pbpl; 170042a0d256SVille Syrjälä 170142a0d256SVille Syrjälä /* only planar format has two planes */ 170242a0d256SVille Syrjälä if (color_plane == 1 && 170342a0d256SVille Syrjälä !intel_format_info_is_yuv_semiplanar(format, modifier)) { 170442a0d256SVille Syrjälä drm_dbg_kms(&i915->drm, 170542a0d256SVille Syrjälä "Non planar format have single plane\n"); 170642a0d256SVille Syrjälä return -EINVAL; 170742a0d256SVille Syrjälä } 170842a0d256SVille Syrjälä 170942a0d256SVille Syrjälä wp->x_tiled = modifier == I915_FORMAT_MOD_X_TILED; 1710d5c45330SVille Syrjälä wp->y_tiled = modifier != I915_FORMAT_MOD_X_TILED && 1711d5c45330SVille Syrjälä intel_fb_is_tiled_modifier(modifier); 1712d5c45330SVille Syrjälä wp->rc_surface = intel_fb_is_ccs_modifier(modifier); 171342a0d256SVille Syrjälä wp->is_planar = intel_format_info_is_yuv_semiplanar(format, modifier); 171442a0d256SVille Syrjälä 171542a0d256SVille Syrjälä wp->width = width; 171642a0d256SVille Syrjälä if (color_plane == 1 && wp->is_planar) 171742a0d256SVille Syrjälä wp->width /= 2; 171842a0d256SVille Syrjälä 171942a0d256SVille Syrjälä wp->cpp = format->cpp[color_plane]; 172042a0d256SVille Syrjälä wp->plane_pixel_rate = plane_pixel_rate; 172142a0d256SVille Syrjälä 172242a0d256SVille Syrjälä if (DISPLAY_VER(i915) >= 11 && 172342a0d256SVille Syrjälä modifier == I915_FORMAT_MOD_Yf_TILED && wp->cpp == 1) 172442a0d256SVille Syrjälä wp->dbuf_block_size = 256; 172542a0d256SVille Syrjälä else 172642a0d256SVille Syrjälä wp->dbuf_block_size = 512; 172742a0d256SVille Syrjälä 172842a0d256SVille Syrjälä if (drm_rotation_90_or_270(rotation)) { 172942a0d256SVille Syrjälä switch (wp->cpp) { 173042a0d256SVille Syrjälä case 1: 173142a0d256SVille Syrjälä wp->y_min_scanlines = 16; 173242a0d256SVille Syrjälä break; 173342a0d256SVille Syrjälä case 2: 173442a0d256SVille Syrjälä wp->y_min_scanlines = 8; 173542a0d256SVille Syrjälä break; 173642a0d256SVille Syrjälä case 4: 173742a0d256SVille Syrjälä wp->y_min_scanlines = 4; 173842a0d256SVille Syrjälä break; 173942a0d256SVille Syrjälä default: 174042a0d256SVille Syrjälä MISSING_CASE(wp->cpp); 174142a0d256SVille Syrjälä return -EINVAL; 174242a0d256SVille Syrjälä } 174342a0d256SVille Syrjälä } else { 174442a0d256SVille Syrjälä wp->y_min_scanlines = 4; 174542a0d256SVille Syrjälä } 174642a0d256SVille Syrjälä 174742a0d256SVille Syrjälä if (skl_needs_memory_bw_wa(i915)) 174842a0d256SVille Syrjälä wp->y_min_scanlines *= 2; 174942a0d256SVille Syrjälä 175042a0d256SVille Syrjälä wp->plane_bytes_per_line = wp->width * wp->cpp; 175142a0d256SVille Syrjälä if (wp->y_tiled) { 175242a0d256SVille Syrjälä interm_pbpl = DIV_ROUND_UP(wp->plane_bytes_per_line * 175342a0d256SVille Syrjälä wp->y_min_scanlines, 175442a0d256SVille Syrjälä wp->dbuf_block_size); 175542a0d256SVille Syrjälä 175642a0d256SVille Syrjälä if (DISPLAY_VER(i915) >= 10) 175742a0d256SVille Syrjälä interm_pbpl++; 175842a0d256SVille Syrjälä 175942a0d256SVille Syrjälä wp->plane_blocks_per_line = div_fixed16(interm_pbpl, 176042a0d256SVille Syrjälä wp->y_min_scanlines); 176142a0d256SVille Syrjälä } else { 176242a0d256SVille Syrjälä interm_pbpl = DIV_ROUND_UP(wp->plane_bytes_per_line, 176342a0d256SVille Syrjälä wp->dbuf_block_size); 176442a0d256SVille Syrjälä 176542a0d256SVille Syrjälä if (!wp->x_tiled || DISPLAY_VER(i915) >= 10) 176642a0d256SVille Syrjälä interm_pbpl++; 176742a0d256SVille Syrjälä 176842a0d256SVille Syrjälä wp->plane_blocks_per_line = u32_to_fixed16(interm_pbpl); 176942a0d256SVille Syrjälä } 177042a0d256SVille Syrjälä 177142a0d256SVille Syrjälä wp->y_tile_minimum = mul_u32_fixed16(wp->y_min_scanlines, 177242a0d256SVille Syrjälä wp->plane_blocks_per_line); 177342a0d256SVille Syrjälä 177442a0d256SVille Syrjälä wp->linetime_us = fixed16_to_u32_round_up(intel_get_linetime_us(crtc_state)); 177542a0d256SVille Syrjälä 177642a0d256SVille Syrjälä return 0; 177742a0d256SVille Syrjälä } 177842a0d256SVille Syrjälä 177942a0d256SVille Syrjälä static int 178042a0d256SVille Syrjälä skl_compute_plane_wm_params(const struct intel_crtc_state *crtc_state, 178142a0d256SVille Syrjälä const struct intel_plane_state *plane_state, 178242a0d256SVille Syrjälä struct skl_wm_params *wp, int color_plane) 178342a0d256SVille Syrjälä { 178442a0d256SVille Syrjälä const struct drm_framebuffer *fb = plane_state->hw.fb; 178542a0d256SVille Syrjälä int width; 178642a0d256SVille Syrjälä 178742a0d256SVille Syrjälä /* 178842a0d256SVille Syrjälä * Src coordinates are already rotated by 270 degrees for 178942a0d256SVille Syrjälä * the 90/270 degree plane rotation cases (to match the 179042a0d256SVille Syrjälä * GTT mapping), hence no need to account for rotation here. 179142a0d256SVille Syrjälä */ 179242a0d256SVille Syrjälä width = drm_rect_width(&plane_state->uapi.src) >> 16; 179342a0d256SVille Syrjälä 179442a0d256SVille Syrjälä return skl_compute_wm_params(crtc_state, width, 179542a0d256SVille Syrjälä fb->format, fb->modifier, 179642a0d256SVille Syrjälä plane_state->hw.rotation, 179742a0d256SVille Syrjälä intel_plane_pixel_rate(crtc_state, plane_state), 179842a0d256SVille Syrjälä wp, color_plane); 179942a0d256SVille Syrjälä } 180042a0d256SVille Syrjälä 180142a0d256SVille Syrjälä static bool skl_wm_has_lines(struct drm_i915_private *i915, int level) 180242a0d256SVille Syrjälä { 180342a0d256SVille Syrjälä if (DISPLAY_VER(i915) >= 10) 180442a0d256SVille Syrjälä return true; 180542a0d256SVille Syrjälä 180642a0d256SVille Syrjälä /* The number of lines are ignored for the level 0 watermark. */ 180742a0d256SVille Syrjälä return level > 0; 180842a0d256SVille Syrjälä } 180942a0d256SVille Syrjälä 181042a0d256SVille Syrjälä static int skl_wm_max_lines(struct drm_i915_private *i915) 181142a0d256SVille Syrjälä { 181242a0d256SVille Syrjälä if (DISPLAY_VER(i915) >= 13) 181342a0d256SVille Syrjälä return 255; 181442a0d256SVille Syrjälä else 181542a0d256SVille Syrjälä return 31; 181642a0d256SVille Syrjälä } 181742a0d256SVille Syrjälä 181842a0d256SVille Syrjälä static void skl_compute_plane_wm(const struct intel_crtc_state *crtc_state, 181942a0d256SVille Syrjälä struct intel_plane *plane, 182042a0d256SVille Syrjälä int level, 182142a0d256SVille Syrjälä unsigned int latency, 182242a0d256SVille Syrjälä const struct skl_wm_params *wp, 182342a0d256SVille Syrjälä const struct skl_wm_level *result_prev, 182442a0d256SVille Syrjälä struct skl_wm_level *result /* out */) 182542a0d256SVille Syrjälä { 182642a0d256SVille Syrjälä struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); 182742a0d256SVille Syrjälä uint_fixed_16_16_t method1, method2; 182842a0d256SVille Syrjälä uint_fixed_16_16_t selected_result; 182942a0d256SVille Syrjälä u32 blocks, lines, min_ddb_alloc = 0; 183042a0d256SVille Syrjälä 183142a0d256SVille Syrjälä if (latency == 0 || 183242a0d256SVille Syrjälä (use_minimal_wm0_only(crtc_state, plane) && level > 0)) { 183342a0d256SVille Syrjälä /* reject it */ 183442a0d256SVille Syrjälä result->min_ddb_alloc = U16_MAX; 183542a0d256SVille Syrjälä return; 183642a0d256SVille Syrjälä } 183742a0d256SVille Syrjälä 183842a0d256SVille Syrjälä /* 183942a0d256SVille Syrjälä * WaIncreaseLatencyIPCEnabled: kbl,cfl 184042a0d256SVille Syrjälä * Display WA #1141: kbl,cfl 184142a0d256SVille Syrjälä */ 184223fbdb07SJani Nikula if ((IS_KABYLAKE(i915) || IS_COFFEELAKE(i915) || IS_COMETLAKE(i915)) && 184323fbdb07SJani Nikula skl_watermark_ipc_enabled(i915)) 184442a0d256SVille Syrjälä latency += 4; 184542a0d256SVille Syrjälä 184642a0d256SVille Syrjälä if (skl_needs_memory_bw_wa(i915) && wp->x_tiled) 184742a0d256SVille Syrjälä latency += 15; 184842a0d256SVille Syrjälä 184942a0d256SVille Syrjälä method1 = skl_wm_method1(i915, wp->plane_pixel_rate, 185042a0d256SVille Syrjälä wp->cpp, latency, wp->dbuf_block_size); 185142a0d256SVille Syrjälä method2 = skl_wm_method2(wp->plane_pixel_rate, 185242a0d256SVille Syrjälä crtc_state->hw.pipe_mode.crtc_htotal, 185342a0d256SVille Syrjälä latency, 185442a0d256SVille Syrjälä wp->plane_blocks_per_line); 185542a0d256SVille Syrjälä 185642a0d256SVille Syrjälä if (wp->y_tiled) { 185742a0d256SVille Syrjälä selected_result = max_fixed16(method2, wp->y_tile_minimum); 185842a0d256SVille Syrjälä } else { 185942a0d256SVille Syrjälä if ((wp->cpp * crtc_state->hw.pipe_mode.crtc_htotal / 186042a0d256SVille Syrjälä wp->dbuf_block_size < 1) && 186142a0d256SVille Syrjälä (wp->plane_bytes_per_line / wp->dbuf_block_size < 1)) { 186242a0d256SVille Syrjälä selected_result = method2; 186342a0d256SVille Syrjälä } else if (latency >= wp->linetime_us) { 186442a0d256SVille Syrjälä if (DISPLAY_VER(i915) == 9) 186542a0d256SVille Syrjälä selected_result = min_fixed16(method1, method2); 186642a0d256SVille Syrjälä else 186742a0d256SVille Syrjälä selected_result = method2; 186842a0d256SVille Syrjälä } else { 186942a0d256SVille Syrjälä selected_result = method1; 187042a0d256SVille Syrjälä } 187142a0d256SVille Syrjälä } 187242a0d256SVille Syrjälä 187342a0d256SVille Syrjälä blocks = fixed16_to_u32_round_up(selected_result) + 1; 187442a0d256SVille Syrjälä /* 187542a0d256SVille Syrjälä * Lets have blocks at minimum equivalent to plane_blocks_per_line 187642a0d256SVille Syrjälä * as there will be at minimum one line for lines configuration. This 187742a0d256SVille Syrjälä * is a work around for FIFO underruns observed with resolutions like 187842a0d256SVille Syrjälä * 4k 60 Hz in single channel DRAM configurations. 187942a0d256SVille Syrjälä * 188042a0d256SVille Syrjälä * As per the Bspec 49325, if the ddb allocation can hold at least 188142a0d256SVille Syrjälä * one plane_blocks_per_line, we should have selected method2 in 188242a0d256SVille Syrjälä * the above logic. Assuming that modern versions have enough dbuf 188342a0d256SVille Syrjälä * and method2 guarantees blocks equivalent to at least 1 line, 188442a0d256SVille Syrjälä * select the blocks as plane_blocks_per_line. 188542a0d256SVille Syrjälä * 188642a0d256SVille Syrjälä * TODO: Revisit the logic when we have better understanding on DRAM 188742a0d256SVille Syrjälä * channels' impact on the level 0 memory latency and the relevant 188842a0d256SVille Syrjälä * wm calculations. 188942a0d256SVille Syrjälä */ 189042a0d256SVille Syrjälä if (skl_wm_has_lines(i915, level)) 189142a0d256SVille Syrjälä blocks = max(blocks, 189242a0d256SVille Syrjälä fixed16_to_u32_round_up(wp->plane_blocks_per_line)); 189342a0d256SVille Syrjälä lines = div_round_up_fixed16(selected_result, 189442a0d256SVille Syrjälä wp->plane_blocks_per_line); 189542a0d256SVille Syrjälä 189642a0d256SVille Syrjälä if (DISPLAY_VER(i915) == 9) { 189742a0d256SVille Syrjälä /* Display WA #1125: skl,bxt,kbl */ 189842a0d256SVille Syrjälä if (level == 0 && wp->rc_surface) 189942a0d256SVille Syrjälä blocks += fixed16_to_u32_round_up(wp->y_tile_minimum); 190042a0d256SVille Syrjälä 190142a0d256SVille Syrjälä /* Display WA #1126: skl,bxt,kbl */ 190242a0d256SVille Syrjälä if (level >= 1 && level <= 7) { 190342a0d256SVille Syrjälä if (wp->y_tiled) { 190442a0d256SVille Syrjälä blocks += fixed16_to_u32_round_up(wp->y_tile_minimum); 190542a0d256SVille Syrjälä lines += wp->y_min_scanlines; 190642a0d256SVille Syrjälä } else { 190742a0d256SVille Syrjälä blocks++; 190842a0d256SVille Syrjälä } 190942a0d256SVille Syrjälä 191042a0d256SVille Syrjälä /* 191142a0d256SVille Syrjälä * Make sure result blocks for higher latency levels are 191242a0d256SVille Syrjälä * at least as high as level below the current level. 191342a0d256SVille Syrjälä * Assumption in DDB algorithm optimization for special 191442a0d256SVille Syrjälä * cases. Also covers Display WA #1125 for RC. 191542a0d256SVille Syrjälä */ 191642a0d256SVille Syrjälä if (result_prev->blocks > blocks) 191742a0d256SVille Syrjälä blocks = result_prev->blocks; 191842a0d256SVille Syrjälä } 191942a0d256SVille Syrjälä } 192042a0d256SVille Syrjälä 192142a0d256SVille Syrjälä if (DISPLAY_VER(i915) >= 11) { 192242a0d256SVille Syrjälä if (wp->y_tiled) { 192342a0d256SVille Syrjälä int extra_lines; 192442a0d256SVille Syrjälä 192542a0d256SVille Syrjälä if (lines % wp->y_min_scanlines == 0) 192642a0d256SVille Syrjälä extra_lines = wp->y_min_scanlines; 192742a0d256SVille Syrjälä else 192842a0d256SVille Syrjälä extra_lines = wp->y_min_scanlines * 2 - 192942a0d256SVille Syrjälä lines % wp->y_min_scanlines; 193042a0d256SVille Syrjälä 193142a0d256SVille Syrjälä min_ddb_alloc = mul_round_up_u32_fixed16(lines + extra_lines, 193242a0d256SVille Syrjälä wp->plane_blocks_per_line); 193342a0d256SVille Syrjälä } else { 193442a0d256SVille Syrjälä min_ddb_alloc = blocks + DIV_ROUND_UP(blocks, 10); 193542a0d256SVille Syrjälä } 193642a0d256SVille Syrjälä } 193742a0d256SVille Syrjälä 193842a0d256SVille Syrjälä if (!skl_wm_has_lines(i915, level)) 193942a0d256SVille Syrjälä lines = 0; 194042a0d256SVille Syrjälä 194142a0d256SVille Syrjälä if (lines > skl_wm_max_lines(i915)) { 194242a0d256SVille Syrjälä /* reject it */ 194342a0d256SVille Syrjälä result->min_ddb_alloc = U16_MAX; 194442a0d256SVille Syrjälä return; 194542a0d256SVille Syrjälä } 194642a0d256SVille Syrjälä 194742a0d256SVille Syrjälä /* 194842a0d256SVille Syrjälä * If lines is valid, assume we can use this watermark level 194942a0d256SVille Syrjälä * for now. We'll come back and disable it after we calculate the 195042a0d256SVille Syrjälä * DDB allocation if it turns out we don't actually have enough 195142a0d256SVille Syrjälä * blocks to satisfy it. 195242a0d256SVille Syrjälä */ 195342a0d256SVille Syrjälä result->blocks = blocks; 195442a0d256SVille Syrjälä result->lines = lines; 195542a0d256SVille Syrjälä /* Bspec says: value >= plane ddb allocation -> invalid, hence the +1 here */ 195642a0d256SVille Syrjälä result->min_ddb_alloc = max(min_ddb_alloc, blocks) + 1; 195742a0d256SVille Syrjälä result->enable = true; 195842a0d256SVille Syrjälä 195942a0d256SVille Syrjälä if (DISPLAY_VER(i915) < 12 && i915->display.sagv.block_time_us) 196042a0d256SVille Syrjälä result->can_sagv = latency >= i915->display.sagv.block_time_us; 196142a0d256SVille Syrjälä } 196242a0d256SVille Syrjälä 196342a0d256SVille Syrjälä static void 196442a0d256SVille Syrjälä skl_compute_wm_levels(const struct intel_crtc_state *crtc_state, 196542a0d256SVille Syrjälä struct intel_plane *plane, 196642a0d256SVille Syrjälä const struct skl_wm_params *wm_params, 196742a0d256SVille Syrjälä struct skl_wm_level *levels) 196842a0d256SVille Syrjälä { 196942a0d256SVille Syrjälä struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); 197042a0d256SVille Syrjälä int level, max_level = ilk_wm_max_level(i915); 197142a0d256SVille Syrjälä struct skl_wm_level *result_prev = &levels[0]; 197242a0d256SVille Syrjälä 197342a0d256SVille Syrjälä for (level = 0; level <= max_level; level++) { 197442a0d256SVille Syrjälä struct skl_wm_level *result = &levels[level]; 197542a0d256SVille Syrjälä unsigned int latency = i915->display.wm.skl_latency[level]; 197642a0d256SVille Syrjälä 197742a0d256SVille Syrjälä skl_compute_plane_wm(crtc_state, plane, level, latency, 197842a0d256SVille Syrjälä wm_params, result_prev, result); 197942a0d256SVille Syrjälä 198042a0d256SVille Syrjälä result_prev = result; 198142a0d256SVille Syrjälä } 198242a0d256SVille Syrjälä } 198342a0d256SVille Syrjälä 198442a0d256SVille Syrjälä static void tgl_compute_sagv_wm(const struct intel_crtc_state *crtc_state, 198542a0d256SVille Syrjälä struct intel_plane *plane, 198642a0d256SVille Syrjälä const struct skl_wm_params *wm_params, 198742a0d256SVille Syrjälä struct skl_plane_wm *plane_wm) 198842a0d256SVille Syrjälä { 198942a0d256SVille Syrjälä struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); 199042a0d256SVille Syrjälä struct skl_wm_level *sagv_wm = &plane_wm->sagv.wm0; 199142a0d256SVille Syrjälä struct skl_wm_level *levels = plane_wm->wm; 199242a0d256SVille Syrjälä unsigned int latency = 0; 199342a0d256SVille Syrjälä 199442a0d256SVille Syrjälä if (i915->display.sagv.block_time_us) 199542a0d256SVille Syrjälä latency = i915->display.sagv.block_time_us + i915->display.wm.skl_latency[0]; 199642a0d256SVille Syrjälä 199742a0d256SVille Syrjälä skl_compute_plane_wm(crtc_state, plane, 0, latency, 199842a0d256SVille Syrjälä wm_params, &levels[0], 199942a0d256SVille Syrjälä sagv_wm); 200042a0d256SVille Syrjälä } 200142a0d256SVille Syrjälä 200242a0d256SVille Syrjälä static void skl_compute_transition_wm(struct drm_i915_private *i915, 200342a0d256SVille Syrjälä struct skl_wm_level *trans_wm, 200442a0d256SVille Syrjälä const struct skl_wm_level *wm0, 200542a0d256SVille Syrjälä const struct skl_wm_params *wp) 200642a0d256SVille Syrjälä { 200742a0d256SVille Syrjälä u16 trans_min, trans_amount, trans_y_tile_min; 200842a0d256SVille Syrjälä u16 wm0_blocks, trans_offset, blocks; 200942a0d256SVille Syrjälä 201042a0d256SVille Syrjälä /* Transition WM don't make any sense if ipc is disabled */ 201123fbdb07SJani Nikula if (!skl_watermark_ipc_enabled(i915)) 201242a0d256SVille Syrjälä return; 201342a0d256SVille Syrjälä 201442a0d256SVille Syrjälä /* 201542a0d256SVille Syrjälä * WaDisableTWM:skl,kbl,cfl,bxt 201642a0d256SVille Syrjälä * Transition WM are not recommended by HW team for GEN9 201742a0d256SVille Syrjälä */ 201842a0d256SVille Syrjälä if (DISPLAY_VER(i915) == 9) 201942a0d256SVille Syrjälä return; 202042a0d256SVille Syrjälä 202142a0d256SVille Syrjälä if (DISPLAY_VER(i915) >= 11) 202242a0d256SVille Syrjälä trans_min = 4; 202342a0d256SVille Syrjälä else 202442a0d256SVille Syrjälä trans_min = 14; 202542a0d256SVille Syrjälä 202642a0d256SVille Syrjälä /* Display WA #1140: glk,cnl */ 202742a0d256SVille Syrjälä if (DISPLAY_VER(i915) == 10) 202842a0d256SVille Syrjälä trans_amount = 0; 202942a0d256SVille Syrjälä else 203042a0d256SVille Syrjälä trans_amount = 10; /* This is configurable amount */ 203142a0d256SVille Syrjälä 203242a0d256SVille Syrjälä trans_offset = trans_min + trans_amount; 203342a0d256SVille Syrjälä 203442a0d256SVille Syrjälä /* 203542a0d256SVille Syrjälä * The spec asks for Selected Result Blocks for wm0 (the real value), 203642a0d256SVille Syrjälä * not Result Blocks (the integer value). Pay attention to the capital 203742a0d256SVille Syrjälä * letters. The value wm_l0->blocks is actually Result Blocks, but 203842a0d256SVille Syrjälä * since Result Blocks is the ceiling of Selected Result Blocks plus 1, 203942a0d256SVille Syrjälä * and since we later will have to get the ceiling of the sum in the 204042a0d256SVille Syrjälä * transition watermarks calculation, we can just pretend Selected 204142a0d256SVille Syrjälä * Result Blocks is Result Blocks minus 1 and it should work for the 204242a0d256SVille Syrjälä * current platforms. 204342a0d256SVille Syrjälä */ 204442a0d256SVille Syrjälä wm0_blocks = wm0->blocks - 1; 204542a0d256SVille Syrjälä 204642a0d256SVille Syrjälä if (wp->y_tiled) { 204742a0d256SVille Syrjälä trans_y_tile_min = 204842a0d256SVille Syrjälä (u16)mul_round_up_u32_fixed16(2, wp->y_tile_minimum); 204942a0d256SVille Syrjälä blocks = max(wm0_blocks, trans_y_tile_min) + trans_offset; 205042a0d256SVille Syrjälä } else { 205142a0d256SVille Syrjälä blocks = wm0_blocks + trans_offset; 205242a0d256SVille Syrjälä } 205342a0d256SVille Syrjälä blocks++; 205442a0d256SVille Syrjälä 205542a0d256SVille Syrjälä /* 205642a0d256SVille Syrjälä * Just assume we can enable the transition watermark. After 205742a0d256SVille Syrjälä * computing the DDB we'll come back and disable it if that 205842a0d256SVille Syrjälä * assumption turns out to be false. 205942a0d256SVille Syrjälä */ 206042a0d256SVille Syrjälä trans_wm->blocks = blocks; 206142a0d256SVille Syrjälä trans_wm->min_ddb_alloc = max_t(u16, wm0->min_ddb_alloc, blocks + 1); 206242a0d256SVille Syrjälä trans_wm->enable = true; 206342a0d256SVille Syrjälä } 206442a0d256SVille Syrjälä 206542a0d256SVille Syrjälä static int skl_build_plane_wm_single(struct intel_crtc_state *crtc_state, 206642a0d256SVille Syrjälä const struct intel_plane_state *plane_state, 206742a0d256SVille Syrjälä struct intel_plane *plane, int color_plane) 206842a0d256SVille Syrjälä { 206942a0d256SVille Syrjälä struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 207042a0d256SVille Syrjälä struct drm_i915_private *i915 = to_i915(crtc->base.dev); 207142a0d256SVille Syrjälä struct skl_plane_wm *wm = &crtc_state->wm.skl.raw.planes[plane->id]; 207242a0d256SVille Syrjälä struct skl_wm_params wm_params; 207342a0d256SVille Syrjälä int ret; 207442a0d256SVille Syrjälä 207542a0d256SVille Syrjälä ret = skl_compute_plane_wm_params(crtc_state, plane_state, 207642a0d256SVille Syrjälä &wm_params, color_plane); 207742a0d256SVille Syrjälä if (ret) 207842a0d256SVille Syrjälä return ret; 207942a0d256SVille Syrjälä 208042a0d256SVille Syrjälä skl_compute_wm_levels(crtc_state, plane, &wm_params, wm->wm); 208142a0d256SVille Syrjälä 208242a0d256SVille Syrjälä skl_compute_transition_wm(i915, &wm->trans_wm, 208342a0d256SVille Syrjälä &wm->wm[0], &wm_params); 208442a0d256SVille Syrjälä 208542a0d256SVille Syrjälä if (DISPLAY_VER(i915) >= 12) { 208642a0d256SVille Syrjälä tgl_compute_sagv_wm(crtc_state, plane, &wm_params, wm); 208742a0d256SVille Syrjälä 208842a0d256SVille Syrjälä skl_compute_transition_wm(i915, &wm->sagv.trans_wm, 208942a0d256SVille Syrjälä &wm->sagv.wm0, &wm_params); 209042a0d256SVille Syrjälä } 209142a0d256SVille Syrjälä 209242a0d256SVille Syrjälä return 0; 209342a0d256SVille Syrjälä } 209442a0d256SVille Syrjälä 209542a0d256SVille Syrjälä static int skl_build_plane_wm_uv(struct intel_crtc_state *crtc_state, 209642a0d256SVille Syrjälä const struct intel_plane_state *plane_state, 209742a0d256SVille Syrjälä struct intel_plane *plane) 209842a0d256SVille Syrjälä { 209942a0d256SVille Syrjälä struct skl_plane_wm *wm = &crtc_state->wm.skl.raw.planes[plane->id]; 210042a0d256SVille Syrjälä struct skl_wm_params wm_params; 210142a0d256SVille Syrjälä int ret; 210242a0d256SVille Syrjälä 210342a0d256SVille Syrjälä wm->is_planar = true; 210442a0d256SVille Syrjälä 210542a0d256SVille Syrjälä /* uv plane watermarks must also be validated for NV12/Planar */ 210642a0d256SVille Syrjälä ret = skl_compute_plane_wm_params(crtc_state, plane_state, 210742a0d256SVille Syrjälä &wm_params, 1); 210842a0d256SVille Syrjälä if (ret) 210942a0d256SVille Syrjälä return ret; 211042a0d256SVille Syrjälä 211142a0d256SVille Syrjälä skl_compute_wm_levels(crtc_state, plane, &wm_params, wm->uv_wm); 211242a0d256SVille Syrjälä 211342a0d256SVille Syrjälä return 0; 211442a0d256SVille Syrjälä } 211542a0d256SVille Syrjälä 211642a0d256SVille Syrjälä static int skl_build_plane_wm(struct intel_crtc_state *crtc_state, 211742a0d256SVille Syrjälä const struct intel_plane_state *plane_state) 211842a0d256SVille Syrjälä { 211942a0d256SVille Syrjälä struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); 212042a0d256SVille Syrjälä enum plane_id plane_id = plane->id; 212142a0d256SVille Syrjälä struct skl_plane_wm *wm = &crtc_state->wm.skl.raw.planes[plane_id]; 212242a0d256SVille Syrjälä const struct drm_framebuffer *fb = plane_state->hw.fb; 212342a0d256SVille Syrjälä int ret; 212442a0d256SVille Syrjälä 212542a0d256SVille Syrjälä memset(wm, 0, sizeof(*wm)); 212642a0d256SVille Syrjälä 212742a0d256SVille Syrjälä if (!intel_wm_plane_visible(crtc_state, plane_state)) 212842a0d256SVille Syrjälä return 0; 212942a0d256SVille Syrjälä 213042a0d256SVille Syrjälä ret = skl_build_plane_wm_single(crtc_state, plane_state, 213142a0d256SVille Syrjälä plane, 0); 213242a0d256SVille Syrjälä if (ret) 213342a0d256SVille Syrjälä return ret; 213442a0d256SVille Syrjälä 213542a0d256SVille Syrjälä if (fb->format->is_yuv && fb->format->num_planes > 1) { 213642a0d256SVille Syrjälä ret = skl_build_plane_wm_uv(crtc_state, plane_state, 213742a0d256SVille Syrjälä plane); 213842a0d256SVille Syrjälä if (ret) 213942a0d256SVille Syrjälä return ret; 214042a0d256SVille Syrjälä } 214142a0d256SVille Syrjälä 214242a0d256SVille Syrjälä return 0; 214342a0d256SVille Syrjälä } 214442a0d256SVille Syrjälä 214542a0d256SVille Syrjälä static int icl_build_plane_wm(struct intel_crtc_state *crtc_state, 214642a0d256SVille Syrjälä const struct intel_plane_state *plane_state) 214742a0d256SVille Syrjälä { 214842a0d256SVille Syrjälä struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); 214942a0d256SVille Syrjälä struct drm_i915_private *i915 = to_i915(plane->base.dev); 215042a0d256SVille Syrjälä enum plane_id plane_id = plane->id; 215142a0d256SVille Syrjälä struct skl_plane_wm *wm = &crtc_state->wm.skl.raw.planes[plane_id]; 215242a0d256SVille Syrjälä int ret; 215342a0d256SVille Syrjälä 215442a0d256SVille Syrjälä /* Watermarks calculated in master */ 215542a0d256SVille Syrjälä if (plane_state->planar_slave) 215642a0d256SVille Syrjälä return 0; 215742a0d256SVille Syrjälä 215842a0d256SVille Syrjälä memset(wm, 0, sizeof(*wm)); 215942a0d256SVille Syrjälä 216042a0d256SVille Syrjälä if (plane_state->planar_linked_plane) { 216142a0d256SVille Syrjälä const struct drm_framebuffer *fb = plane_state->hw.fb; 216242a0d256SVille Syrjälä 216342a0d256SVille Syrjälä drm_WARN_ON(&i915->drm, 216442a0d256SVille Syrjälä !intel_wm_plane_visible(crtc_state, plane_state)); 216542a0d256SVille Syrjälä drm_WARN_ON(&i915->drm, !fb->format->is_yuv || 216642a0d256SVille Syrjälä fb->format->num_planes == 1); 216742a0d256SVille Syrjälä 216842a0d256SVille Syrjälä ret = skl_build_plane_wm_single(crtc_state, plane_state, 216942a0d256SVille Syrjälä plane_state->planar_linked_plane, 0); 217042a0d256SVille Syrjälä if (ret) 217142a0d256SVille Syrjälä return ret; 217242a0d256SVille Syrjälä 217342a0d256SVille Syrjälä ret = skl_build_plane_wm_single(crtc_state, plane_state, 217442a0d256SVille Syrjälä plane, 1); 217542a0d256SVille Syrjälä if (ret) 217642a0d256SVille Syrjälä return ret; 217742a0d256SVille Syrjälä } else if (intel_wm_plane_visible(crtc_state, plane_state)) { 217842a0d256SVille Syrjälä ret = skl_build_plane_wm_single(crtc_state, plane_state, 217942a0d256SVille Syrjälä plane, 0); 218042a0d256SVille Syrjälä if (ret) 218142a0d256SVille Syrjälä return ret; 218242a0d256SVille Syrjälä } 218342a0d256SVille Syrjälä 218442a0d256SVille Syrjälä return 0; 218542a0d256SVille Syrjälä } 218642a0d256SVille Syrjälä 218742a0d256SVille Syrjälä static int skl_build_pipe_wm(struct intel_atomic_state *state, 218842a0d256SVille Syrjälä struct intel_crtc *crtc) 218942a0d256SVille Syrjälä { 219042a0d256SVille Syrjälä struct drm_i915_private *i915 = to_i915(crtc->base.dev); 219142a0d256SVille Syrjälä struct intel_crtc_state *crtc_state = 219242a0d256SVille Syrjälä intel_atomic_get_new_crtc_state(state, crtc); 219342a0d256SVille Syrjälä const struct intel_plane_state *plane_state; 219442a0d256SVille Syrjälä struct intel_plane *plane; 219542a0d256SVille Syrjälä int ret, i; 219642a0d256SVille Syrjälä 219742a0d256SVille Syrjälä for_each_new_intel_plane_in_state(state, plane, plane_state, i) { 219842a0d256SVille Syrjälä /* 219942a0d256SVille Syrjälä * FIXME should perhaps check {old,new}_plane_crtc->hw.crtc 220042a0d256SVille Syrjälä * instead but we don't populate that correctly for NV12 Y 220142a0d256SVille Syrjälä * planes so for now hack this. 220242a0d256SVille Syrjälä */ 220342a0d256SVille Syrjälä if (plane->pipe != crtc->pipe) 220442a0d256SVille Syrjälä continue; 220542a0d256SVille Syrjälä 220642a0d256SVille Syrjälä if (DISPLAY_VER(i915) >= 11) 220742a0d256SVille Syrjälä ret = icl_build_plane_wm(crtc_state, plane_state); 220842a0d256SVille Syrjälä else 220942a0d256SVille Syrjälä ret = skl_build_plane_wm(crtc_state, plane_state); 221042a0d256SVille Syrjälä if (ret) 221142a0d256SVille Syrjälä return ret; 221242a0d256SVille Syrjälä } 221342a0d256SVille Syrjälä 221442a0d256SVille Syrjälä crtc_state->wm.skl.optimal = crtc_state->wm.skl.raw; 221542a0d256SVille Syrjälä 221642a0d256SVille Syrjälä return 0; 221742a0d256SVille Syrjälä } 221842a0d256SVille Syrjälä 221942a0d256SVille Syrjälä static void skl_ddb_entry_write(struct drm_i915_private *i915, 222042a0d256SVille Syrjälä i915_reg_t reg, 222142a0d256SVille Syrjälä const struct skl_ddb_entry *entry) 222242a0d256SVille Syrjälä { 222342a0d256SVille Syrjälä if (entry->end) 222442a0d256SVille Syrjälä intel_de_write_fw(i915, reg, 222542a0d256SVille Syrjälä PLANE_BUF_END(entry->end - 1) | 222642a0d256SVille Syrjälä PLANE_BUF_START(entry->start)); 222742a0d256SVille Syrjälä else 222842a0d256SVille Syrjälä intel_de_write_fw(i915, reg, 0); 222942a0d256SVille Syrjälä } 223042a0d256SVille Syrjälä 223142a0d256SVille Syrjälä static void skl_write_wm_level(struct drm_i915_private *i915, 223242a0d256SVille Syrjälä i915_reg_t reg, 223342a0d256SVille Syrjälä const struct skl_wm_level *level) 223442a0d256SVille Syrjälä { 223542a0d256SVille Syrjälä u32 val = 0; 223642a0d256SVille Syrjälä 223742a0d256SVille Syrjälä if (level->enable) 223842a0d256SVille Syrjälä val |= PLANE_WM_EN; 223942a0d256SVille Syrjälä if (level->ignore_lines) 224042a0d256SVille Syrjälä val |= PLANE_WM_IGNORE_LINES; 224142a0d256SVille Syrjälä val |= REG_FIELD_PREP(PLANE_WM_BLOCKS_MASK, level->blocks); 224242a0d256SVille Syrjälä val |= REG_FIELD_PREP(PLANE_WM_LINES_MASK, level->lines); 224342a0d256SVille Syrjälä 224442a0d256SVille Syrjälä intel_de_write_fw(i915, reg, val); 224542a0d256SVille Syrjälä } 224642a0d256SVille Syrjälä 224742a0d256SVille Syrjälä void skl_write_plane_wm(struct intel_plane *plane, 224842a0d256SVille Syrjälä const struct intel_crtc_state *crtc_state) 224942a0d256SVille Syrjälä { 225042a0d256SVille Syrjälä struct drm_i915_private *i915 = to_i915(plane->base.dev); 225142a0d256SVille Syrjälä int level, max_level = ilk_wm_max_level(i915); 225242a0d256SVille Syrjälä enum plane_id plane_id = plane->id; 225342a0d256SVille Syrjälä enum pipe pipe = plane->pipe; 225442a0d256SVille Syrjälä const struct skl_pipe_wm *pipe_wm = &crtc_state->wm.skl.optimal; 225542a0d256SVille Syrjälä const struct skl_ddb_entry *ddb = 225642a0d256SVille Syrjälä &crtc_state->wm.skl.plane_ddb[plane_id]; 225742a0d256SVille Syrjälä const struct skl_ddb_entry *ddb_y = 225842a0d256SVille Syrjälä &crtc_state->wm.skl.plane_ddb_y[plane_id]; 225942a0d256SVille Syrjälä 226042a0d256SVille Syrjälä for (level = 0; level <= max_level; level++) 226142a0d256SVille Syrjälä skl_write_wm_level(i915, PLANE_WM(pipe, plane_id, level), 226242a0d256SVille Syrjälä skl_plane_wm_level(pipe_wm, plane_id, level)); 226342a0d256SVille Syrjälä 226442a0d256SVille Syrjälä skl_write_wm_level(i915, PLANE_WM_TRANS(pipe, plane_id), 226542a0d256SVille Syrjälä skl_plane_trans_wm(pipe_wm, plane_id)); 226642a0d256SVille Syrjälä 226742a0d256SVille Syrjälä if (HAS_HW_SAGV_WM(i915)) { 226842a0d256SVille Syrjälä const struct skl_plane_wm *wm = &pipe_wm->planes[plane_id]; 226942a0d256SVille Syrjälä 227042a0d256SVille Syrjälä skl_write_wm_level(i915, PLANE_WM_SAGV(pipe, plane_id), 227142a0d256SVille Syrjälä &wm->sagv.wm0); 227242a0d256SVille Syrjälä skl_write_wm_level(i915, PLANE_WM_SAGV_TRANS(pipe, plane_id), 227342a0d256SVille Syrjälä &wm->sagv.trans_wm); 227442a0d256SVille Syrjälä } 227542a0d256SVille Syrjälä 227642a0d256SVille Syrjälä skl_ddb_entry_write(i915, 227742a0d256SVille Syrjälä PLANE_BUF_CFG(pipe, plane_id), ddb); 227842a0d256SVille Syrjälä 227942a0d256SVille Syrjälä if (DISPLAY_VER(i915) < 11) 228042a0d256SVille Syrjälä skl_ddb_entry_write(i915, 228142a0d256SVille Syrjälä PLANE_NV12_BUF_CFG(pipe, plane_id), ddb_y); 228242a0d256SVille Syrjälä } 228342a0d256SVille Syrjälä 228442a0d256SVille Syrjälä void skl_write_cursor_wm(struct intel_plane *plane, 228542a0d256SVille Syrjälä const struct intel_crtc_state *crtc_state) 228642a0d256SVille Syrjälä { 228742a0d256SVille Syrjälä struct drm_i915_private *i915 = to_i915(plane->base.dev); 228842a0d256SVille Syrjälä int level, max_level = ilk_wm_max_level(i915); 228942a0d256SVille Syrjälä enum plane_id plane_id = plane->id; 229042a0d256SVille Syrjälä enum pipe pipe = plane->pipe; 229142a0d256SVille Syrjälä const struct skl_pipe_wm *pipe_wm = &crtc_state->wm.skl.optimal; 229242a0d256SVille Syrjälä const struct skl_ddb_entry *ddb = 229342a0d256SVille Syrjälä &crtc_state->wm.skl.plane_ddb[plane_id]; 229442a0d256SVille Syrjälä 229542a0d256SVille Syrjälä for (level = 0; level <= max_level; level++) 229642a0d256SVille Syrjälä skl_write_wm_level(i915, CUR_WM(pipe, level), 229742a0d256SVille Syrjälä skl_plane_wm_level(pipe_wm, plane_id, level)); 229842a0d256SVille Syrjälä 229942a0d256SVille Syrjälä skl_write_wm_level(i915, CUR_WM_TRANS(pipe), 230042a0d256SVille Syrjälä skl_plane_trans_wm(pipe_wm, plane_id)); 230142a0d256SVille Syrjälä 230242a0d256SVille Syrjälä if (HAS_HW_SAGV_WM(i915)) { 230342a0d256SVille Syrjälä const struct skl_plane_wm *wm = &pipe_wm->planes[plane_id]; 230442a0d256SVille Syrjälä 230542a0d256SVille Syrjälä skl_write_wm_level(i915, CUR_WM_SAGV(pipe), 230642a0d256SVille Syrjälä &wm->sagv.wm0); 230742a0d256SVille Syrjälä skl_write_wm_level(i915, CUR_WM_SAGV_TRANS(pipe), 230842a0d256SVille Syrjälä &wm->sagv.trans_wm); 230942a0d256SVille Syrjälä } 231042a0d256SVille Syrjälä 231142a0d256SVille Syrjälä skl_ddb_entry_write(i915, CUR_BUF_CFG(pipe), ddb); 231242a0d256SVille Syrjälä } 231342a0d256SVille Syrjälä 231442a0d256SVille Syrjälä static bool skl_wm_level_equals(const struct skl_wm_level *l1, 231542a0d256SVille Syrjälä const struct skl_wm_level *l2) 231642a0d256SVille Syrjälä { 231742a0d256SVille Syrjälä return l1->enable == l2->enable && 231842a0d256SVille Syrjälä l1->ignore_lines == l2->ignore_lines && 231942a0d256SVille Syrjälä l1->lines == l2->lines && 232042a0d256SVille Syrjälä l1->blocks == l2->blocks; 232142a0d256SVille Syrjälä } 232242a0d256SVille Syrjälä 232342a0d256SVille Syrjälä static bool skl_plane_wm_equals(struct drm_i915_private *i915, 232442a0d256SVille Syrjälä const struct skl_plane_wm *wm1, 232542a0d256SVille Syrjälä const struct skl_plane_wm *wm2) 232642a0d256SVille Syrjälä { 232742a0d256SVille Syrjälä int level, max_level = ilk_wm_max_level(i915); 232842a0d256SVille Syrjälä 232942a0d256SVille Syrjälä for (level = 0; level <= max_level; level++) { 233042a0d256SVille Syrjälä /* 233142a0d256SVille Syrjälä * We don't check uv_wm as the hardware doesn't actually 233242a0d256SVille Syrjälä * use it. It only gets used for calculating the required 233342a0d256SVille Syrjälä * ddb allocation. 233442a0d256SVille Syrjälä */ 233542a0d256SVille Syrjälä if (!skl_wm_level_equals(&wm1->wm[level], &wm2->wm[level])) 233642a0d256SVille Syrjälä return false; 233742a0d256SVille Syrjälä } 233842a0d256SVille Syrjälä 233942a0d256SVille Syrjälä return skl_wm_level_equals(&wm1->trans_wm, &wm2->trans_wm) && 234042a0d256SVille Syrjälä skl_wm_level_equals(&wm1->sagv.wm0, &wm2->sagv.wm0) && 234142a0d256SVille Syrjälä skl_wm_level_equals(&wm1->sagv.trans_wm, &wm2->sagv.trans_wm); 234242a0d256SVille Syrjälä } 234342a0d256SVille Syrjälä 234442a0d256SVille Syrjälä static bool skl_ddb_entries_overlap(const struct skl_ddb_entry *a, 234542a0d256SVille Syrjälä const struct skl_ddb_entry *b) 234642a0d256SVille Syrjälä { 234742a0d256SVille Syrjälä return a->start < b->end && b->start < a->end; 234842a0d256SVille Syrjälä } 234942a0d256SVille Syrjälä 235042a0d256SVille Syrjälä static void skl_ddb_entry_union(struct skl_ddb_entry *a, 235142a0d256SVille Syrjälä const struct skl_ddb_entry *b) 235242a0d256SVille Syrjälä { 235342a0d256SVille Syrjälä if (a->end && b->end) { 235442a0d256SVille Syrjälä a->start = min(a->start, b->start); 235542a0d256SVille Syrjälä a->end = max(a->end, b->end); 235642a0d256SVille Syrjälä } else if (b->end) { 235742a0d256SVille Syrjälä a->start = b->start; 235842a0d256SVille Syrjälä a->end = b->end; 235942a0d256SVille Syrjälä } 236042a0d256SVille Syrjälä } 236142a0d256SVille Syrjälä 236242a0d256SVille Syrjälä bool skl_ddb_allocation_overlaps(const struct skl_ddb_entry *ddb, 236342a0d256SVille Syrjälä const struct skl_ddb_entry *entries, 236442a0d256SVille Syrjälä int num_entries, int ignore_idx) 236542a0d256SVille Syrjälä { 236642a0d256SVille Syrjälä int i; 236742a0d256SVille Syrjälä 236842a0d256SVille Syrjälä for (i = 0; i < num_entries; i++) { 236942a0d256SVille Syrjälä if (i != ignore_idx && 237042a0d256SVille Syrjälä skl_ddb_entries_overlap(ddb, &entries[i])) 237142a0d256SVille Syrjälä return true; 237242a0d256SVille Syrjälä } 237342a0d256SVille Syrjälä 237442a0d256SVille Syrjälä return false; 237542a0d256SVille Syrjälä } 237642a0d256SVille Syrjälä 237742a0d256SVille Syrjälä static int 237842a0d256SVille Syrjälä skl_ddb_add_affected_planes(const struct intel_crtc_state *old_crtc_state, 237942a0d256SVille Syrjälä struct intel_crtc_state *new_crtc_state) 238042a0d256SVille Syrjälä { 238142a0d256SVille Syrjälä struct intel_atomic_state *state = to_intel_atomic_state(new_crtc_state->uapi.state); 238242a0d256SVille Syrjälä struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc); 238342a0d256SVille Syrjälä struct drm_i915_private *i915 = to_i915(crtc->base.dev); 238442a0d256SVille Syrjälä struct intel_plane *plane; 238542a0d256SVille Syrjälä 238642a0d256SVille Syrjälä for_each_intel_plane_on_crtc(&i915->drm, crtc, plane) { 238742a0d256SVille Syrjälä struct intel_plane_state *plane_state; 238842a0d256SVille Syrjälä enum plane_id plane_id = plane->id; 238942a0d256SVille Syrjälä 239042a0d256SVille Syrjälä if (skl_ddb_entry_equal(&old_crtc_state->wm.skl.plane_ddb[plane_id], 239142a0d256SVille Syrjälä &new_crtc_state->wm.skl.plane_ddb[plane_id]) && 239242a0d256SVille Syrjälä skl_ddb_entry_equal(&old_crtc_state->wm.skl.plane_ddb_y[plane_id], 239342a0d256SVille Syrjälä &new_crtc_state->wm.skl.plane_ddb_y[plane_id])) 239442a0d256SVille Syrjälä continue; 239542a0d256SVille Syrjälä 239642a0d256SVille Syrjälä plane_state = intel_atomic_get_plane_state(state, plane); 239742a0d256SVille Syrjälä if (IS_ERR(plane_state)) 239842a0d256SVille Syrjälä return PTR_ERR(plane_state); 239942a0d256SVille Syrjälä 240042a0d256SVille Syrjälä new_crtc_state->update_planes |= BIT(plane_id); 24019d691c19SAndrzej Hajda new_crtc_state->async_flip_planes = 0; 24029d691c19SAndrzej Hajda new_crtc_state->do_async_flip = false; 240342a0d256SVille Syrjälä } 240442a0d256SVille Syrjälä 240542a0d256SVille Syrjälä return 0; 240642a0d256SVille Syrjälä } 240742a0d256SVille Syrjälä 240842a0d256SVille Syrjälä static u8 intel_dbuf_enabled_slices(const struct intel_dbuf_state *dbuf_state) 240942a0d256SVille Syrjälä { 241042a0d256SVille Syrjälä struct drm_i915_private *i915 = to_i915(dbuf_state->base.state->base.dev); 241142a0d256SVille Syrjälä u8 enabled_slices; 241242a0d256SVille Syrjälä enum pipe pipe; 241342a0d256SVille Syrjälä 241442a0d256SVille Syrjälä /* 241542a0d256SVille Syrjälä * FIXME: For now we always enable slice S1 as per 241642a0d256SVille Syrjälä * the Bspec display initialization sequence. 241742a0d256SVille Syrjälä */ 241842a0d256SVille Syrjälä enabled_slices = BIT(DBUF_S1); 241942a0d256SVille Syrjälä 242042a0d256SVille Syrjälä for_each_pipe(i915, pipe) 242142a0d256SVille Syrjälä enabled_slices |= dbuf_state->slices[pipe]; 242242a0d256SVille Syrjälä 242342a0d256SVille Syrjälä return enabled_slices; 242442a0d256SVille Syrjälä } 242542a0d256SVille Syrjälä 242642a0d256SVille Syrjälä static int 242742a0d256SVille Syrjälä skl_compute_ddb(struct intel_atomic_state *state) 242842a0d256SVille Syrjälä { 242942a0d256SVille Syrjälä struct drm_i915_private *i915 = to_i915(state->base.dev); 243042a0d256SVille Syrjälä const struct intel_dbuf_state *old_dbuf_state; 243142a0d256SVille Syrjälä struct intel_dbuf_state *new_dbuf_state = NULL; 243242a0d256SVille Syrjälä const struct intel_crtc_state *old_crtc_state; 243342a0d256SVille Syrjälä struct intel_crtc_state *new_crtc_state; 243442a0d256SVille Syrjälä struct intel_crtc *crtc; 243542a0d256SVille Syrjälä int ret, i; 243642a0d256SVille Syrjälä 243742a0d256SVille Syrjälä for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) { 243842a0d256SVille Syrjälä new_dbuf_state = intel_atomic_get_dbuf_state(state); 243942a0d256SVille Syrjälä if (IS_ERR(new_dbuf_state)) 244042a0d256SVille Syrjälä return PTR_ERR(new_dbuf_state); 244142a0d256SVille Syrjälä 244242a0d256SVille Syrjälä old_dbuf_state = intel_atomic_get_old_dbuf_state(state); 244342a0d256SVille Syrjälä break; 244442a0d256SVille Syrjälä } 244542a0d256SVille Syrjälä 244642a0d256SVille Syrjälä if (!new_dbuf_state) 244742a0d256SVille Syrjälä return 0; 244842a0d256SVille Syrjälä 244942a0d256SVille Syrjälä new_dbuf_state->active_pipes = 245042a0d256SVille Syrjälä intel_calc_active_pipes(state, old_dbuf_state->active_pipes); 245142a0d256SVille Syrjälä 245242a0d256SVille Syrjälä if (old_dbuf_state->active_pipes != new_dbuf_state->active_pipes) { 245342a0d256SVille Syrjälä ret = intel_atomic_lock_global_state(&new_dbuf_state->base); 245442a0d256SVille Syrjälä if (ret) 245542a0d256SVille Syrjälä return ret; 245642a0d256SVille Syrjälä } 245742a0d256SVille Syrjälä 245842a0d256SVille Syrjälä if (HAS_MBUS_JOINING(i915)) 245942a0d256SVille Syrjälä new_dbuf_state->joined_mbus = 246042a0d256SVille Syrjälä adlp_check_mbus_joined(new_dbuf_state->active_pipes); 246142a0d256SVille Syrjälä 246242a0d256SVille Syrjälä for_each_intel_crtc(&i915->drm, crtc) { 246342a0d256SVille Syrjälä enum pipe pipe = crtc->pipe; 246442a0d256SVille Syrjälä 246542a0d256SVille Syrjälä new_dbuf_state->slices[pipe] = 246642a0d256SVille Syrjälä skl_compute_dbuf_slices(crtc, new_dbuf_state->active_pipes, 246742a0d256SVille Syrjälä new_dbuf_state->joined_mbus); 246842a0d256SVille Syrjälä 246942a0d256SVille Syrjälä if (old_dbuf_state->slices[pipe] == new_dbuf_state->slices[pipe]) 247042a0d256SVille Syrjälä continue; 247142a0d256SVille Syrjälä 247242a0d256SVille Syrjälä ret = intel_atomic_lock_global_state(&new_dbuf_state->base); 247342a0d256SVille Syrjälä if (ret) 247442a0d256SVille Syrjälä return ret; 247542a0d256SVille Syrjälä } 247642a0d256SVille Syrjälä 247742a0d256SVille Syrjälä new_dbuf_state->enabled_slices = intel_dbuf_enabled_slices(new_dbuf_state); 247842a0d256SVille Syrjälä 247942a0d256SVille Syrjälä if (old_dbuf_state->enabled_slices != new_dbuf_state->enabled_slices || 248042a0d256SVille Syrjälä old_dbuf_state->joined_mbus != new_dbuf_state->joined_mbus) { 248142a0d256SVille Syrjälä ret = intel_atomic_serialize_global_state(&new_dbuf_state->base); 248242a0d256SVille Syrjälä if (ret) 248342a0d256SVille Syrjälä return ret; 248442a0d256SVille Syrjälä 248542a0d256SVille Syrjälä if (old_dbuf_state->joined_mbus != new_dbuf_state->joined_mbus) { 248642a0d256SVille Syrjälä /* TODO: Implement vblank synchronized MBUS joining changes */ 24870c316114SVille Syrjälä ret = intel_modeset_all_pipes(state, "MBUS joining change"); 248842a0d256SVille Syrjälä if (ret) 248942a0d256SVille Syrjälä return ret; 249042a0d256SVille Syrjälä } 249142a0d256SVille Syrjälä 249242a0d256SVille Syrjälä drm_dbg_kms(&i915->drm, 249342a0d256SVille Syrjälä "Enabled dbuf slices 0x%x -> 0x%x (total dbuf slices 0x%x), mbus joined? %s->%s\n", 249442a0d256SVille Syrjälä old_dbuf_state->enabled_slices, 249542a0d256SVille Syrjälä new_dbuf_state->enabled_slices, 249642a0d256SVille Syrjälä INTEL_INFO(i915)->display.dbuf.slice_mask, 249742a0d256SVille Syrjälä str_yes_no(old_dbuf_state->joined_mbus), 249842a0d256SVille Syrjälä str_yes_no(new_dbuf_state->joined_mbus)); 249942a0d256SVille Syrjälä } 250042a0d256SVille Syrjälä 250142a0d256SVille Syrjälä for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) { 250242a0d256SVille Syrjälä enum pipe pipe = crtc->pipe; 250342a0d256SVille Syrjälä 250442a0d256SVille Syrjälä new_dbuf_state->weight[pipe] = intel_crtc_ddb_weight(new_crtc_state); 250542a0d256SVille Syrjälä 250642a0d256SVille Syrjälä if (old_dbuf_state->weight[pipe] == new_dbuf_state->weight[pipe]) 250742a0d256SVille Syrjälä continue; 250842a0d256SVille Syrjälä 250942a0d256SVille Syrjälä ret = intel_atomic_lock_global_state(&new_dbuf_state->base); 251042a0d256SVille Syrjälä if (ret) 251142a0d256SVille Syrjälä return ret; 251242a0d256SVille Syrjälä } 251342a0d256SVille Syrjälä 251442a0d256SVille Syrjälä for_each_intel_crtc(&i915->drm, crtc) { 251542a0d256SVille Syrjälä ret = skl_crtc_allocate_ddb(state, crtc); 251642a0d256SVille Syrjälä if (ret) 251742a0d256SVille Syrjälä return ret; 251842a0d256SVille Syrjälä } 251942a0d256SVille Syrjälä 252042a0d256SVille Syrjälä for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, 252142a0d256SVille Syrjälä new_crtc_state, i) { 252242a0d256SVille Syrjälä ret = skl_crtc_allocate_plane_ddb(state, crtc); 252342a0d256SVille Syrjälä if (ret) 252442a0d256SVille Syrjälä return ret; 252542a0d256SVille Syrjälä 252642a0d256SVille Syrjälä ret = skl_ddb_add_affected_planes(old_crtc_state, 252742a0d256SVille Syrjälä new_crtc_state); 252842a0d256SVille Syrjälä if (ret) 252942a0d256SVille Syrjälä return ret; 253042a0d256SVille Syrjälä } 253142a0d256SVille Syrjälä 253242a0d256SVille Syrjälä return 0; 253342a0d256SVille Syrjälä } 253442a0d256SVille Syrjälä 253542a0d256SVille Syrjälä static char enast(bool enable) 253642a0d256SVille Syrjälä { 253742a0d256SVille Syrjälä return enable ? '*' : ' '; 253842a0d256SVille Syrjälä } 253942a0d256SVille Syrjälä 254042a0d256SVille Syrjälä static void 254142a0d256SVille Syrjälä skl_print_wm_changes(struct intel_atomic_state *state) 254242a0d256SVille Syrjälä { 254342a0d256SVille Syrjälä struct drm_i915_private *i915 = to_i915(state->base.dev); 254442a0d256SVille Syrjälä const struct intel_crtc_state *old_crtc_state; 254542a0d256SVille Syrjälä const struct intel_crtc_state *new_crtc_state; 254642a0d256SVille Syrjälä struct intel_plane *plane; 254742a0d256SVille Syrjälä struct intel_crtc *crtc; 254842a0d256SVille Syrjälä int i; 254942a0d256SVille Syrjälä 255042a0d256SVille Syrjälä if (!drm_debug_enabled(DRM_UT_KMS)) 255142a0d256SVille Syrjälä return; 255242a0d256SVille Syrjälä 255342a0d256SVille Syrjälä for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, 255442a0d256SVille Syrjälä new_crtc_state, i) { 255542a0d256SVille Syrjälä const struct skl_pipe_wm *old_pipe_wm, *new_pipe_wm; 255642a0d256SVille Syrjälä 255742a0d256SVille Syrjälä old_pipe_wm = &old_crtc_state->wm.skl.optimal; 255842a0d256SVille Syrjälä new_pipe_wm = &new_crtc_state->wm.skl.optimal; 255942a0d256SVille Syrjälä 256042a0d256SVille Syrjälä for_each_intel_plane_on_crtc(&i915->drm, crtc, plane) { 256142a0d256SVille Syrjälä enum plane_id plane_id = plane->id; 256242a0d256SVille Syrjälä const struct skl_ddb_entry *old, *new; 256342a0d256SVille Syrjälä 256442a0d256SVille Syrjälä old = &old_crtc_state->wm.skl.plane_ddb[plane_id]; 256542a0d256SVille Syrjälä new = &new_crtc_state->wm.skl.plane_ddb[plane_id]; 256642a0d256SVille Syrjälä 256742a0d256SVille Syrjälä if (skl_ddb_entry_equal(old, new)) 256842a0d256SVille Syrjälä continue; 256942a0d256SVille Syrjälä 257042a0d256SVille Syrjälä drm_dbg_kms(&i915->drm, 257142a0d256SVille Syrjälä "[PLANE:%d:%s] ddb (%4d - %4d) -> (%4d - %4d), size %4d -> %4d\n", 257242a0d256SVille Syrjälä plane->base.base.id, plane->base.name, 257342a0d256SVille Syrjälä old->start, old->end, new->start, new->end, 257442a0d256SVille Syrjälä skl_ddb_entry_size(old), skl_ddb_entry_size(new)); 257542a0d256SVille Syrjälä } 257642a0d256SVille Syrjälä 257742a0d256SVille Syrjälä for_each_intel_plane_on_crtc(&i915->drm, crtc, plane) { 257842a0d256SVille Syrjälä enum plane_id plane_id = plane->id; 257942a0d256SVille Syrjälä const struct skl_plane_wm *old_wm, *new_wm; 258042a0d256SVille Syrjälä 258142a0d256SVille Syrjälä old_wm = &old_pipe_wm->planes[plane_id]; 258242a0d256SVille Syrjälä new_wm = &new_pipe_wm->planes[plane_id]; 258342a0d256SVille Syrjälä 258442a0d256SVille Syrjälä if (skl_plane_wm_equals(i915, old_wm, new_wm)) 258542a0d256SVille Syrjälä continue; 258642a0d256SVille Syrjälä 258742a0d256SVille Syrjälä drm_dbg_kms(&i915->drm, 258842a0d256SVille Syrjälä "[PLANE:%d:%s] level %cwm0,%cwm1,%cwm2,%cwm3,%cwm4,%cwm5,%cwm6,%cwm7,%ctwm,%cswm,%cstwm" 258942a0d256SVille Syrjälä " -> %cwm0,%cwm1,%cwm2,%cwm3,%cwm4,%cwm5,%cwm6,%cwm7,%ctwm,%cswm,%cstwm\n", 259042a0d256SVille Syrjälä plane->base.base.id, plane->base.name, 259142a0d256SVille Syrjälä enast(old_wm->wm[0].enable), enast(old_wm->wm[1].enable), 259242a0d256SVille Syrjälä enast(old_wm->wm[2].enable), enast(old_wm->wm[3].enable), 259342a0d256SVille Syrjälä enast(old_wm->wm[4].enable), enast(old_wm->wm[5].enable), 259442a0d256SVille Syrjälä enast(old_wm->wm[6].enable), enast(old_wm->wm[7].enable), 259542a0d256SVille Syrjälä enast(old_wm->trans_wm.enable), 259642a0d256SVille Syrjälä enast(old_wm->sagv.wm0.enable), 259742a0d256SVille Syrjälä enast(old_wm->sagv.trans_wm.enable), 259842a0d256SVille Syrjälä enast(new_wm->wm[0].enable), enast(new_wm->wm[1].enable), 259942a0d256SVille Syrjälä enast(new_wm->wm[2].enable), enast(new_wm->wm[3].enable), 260042a0d256SVille Syrjälä enast(new_wm->wm[4].enable), enast(new_wm->wm[5].enable), 260142a0d256SVille Syrjälä enast(new_wm->wm[6].enable), enast(new_wm->wm[7].enable), 260242a0d256SVille Syrjälä enast(new_wm->trans_wm.enable), 260342a0d256SVille Syrjälä enast(new_wm->sagv.wm0.enable), 260442a0d256SVille Syrjälä enast(new_wm->sagv.trans_wm.enable)); 260542a0d256SVille Syrjälä 260642a0d256SVille Syrjälä drm_dbg_kms(&i915->drm, 260742a0d256SVille Syrjälä "[PLANE:%d:%s] lines %c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%4d" 260842a0d256SVille Syrjälä " -> %c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%4d\n", 260942a0d256SVille Syrjälä plane->base.base.id, plane->base.name, 261042a0d256SVille Syrjälä enast(old_wm->wm[0].ignore_lines), old_wm->wm[0].lines, 261142a0d256SVille Syrjälä enast(old_wm->wm[1].ignore_lines), old_wm->wm[1].lines, 261242a0d256SVille Syrjälä enast(old_wm->wm[2].ignore_lines), old_wm->wm[2].lines, 261342a0d256SVille Syrjälä enast(old_wm->wm[3].ignore_lines), old_wm->wm[3].lines, 261442a0d256SVille Syrjälä enast(old_wm->wm[4].ignore_lines), old_wm->wm[4].lines, 261542a0d256SVille Syrjälä enast(old_wm->wm[5].ignore_lines), old_wm->wm[5].lines, 261642a0d256SVille Syrjälä enast(old_wm->wm[6].ignore_lines), old_wm->wm[6].lines, 261742a0d256SVille Syrjälä enast(old_wm->wm[7].ignore_lines), old_wm->wm[7].lines, 261842a0d256SVille Syrjälä enast(old_wm->trans_wm.ignore_lines), old_wm->trans_wm.lines, 261942a0d256SVille Syrjälä enast(old_wm->sagv.wm0.ignore_lines), old_wm->sagv.wm0.lines, 262042a0d256SVille Syrjälä enast(old_wm->sagv.trans_wm.ignore_lines), old_wm->sagv.trans_wm.lines, 262142a0d256SVille Syrjälä enast(new_wm->wm[0].ignore_lines), new_wm->wm[0].lines, 262242a0d256SVille Syrjälä enast(new_wm->wm[1].ignore_lines), new_wm->wm[1].lines, 262342a0d256SVille Syrjälä enast(new_wm->wm[2].ignore_lines), new_wm->wm[2].lines, 262442a0d256SVille Syrjälä enast(new_wm->wm[3].ignore_lines), new_wm->wm[3].lines, 262542a0d256SVille Syrjälä enast(new_wm->wm[4].ignore_lines), new_wm->wm[4].lines, 262642a0d256SVille Syrjälä enast(new_wm->wm[5].ignore_lines), new_wm->wm[5].lines, 262742a0d256SVille Syrjälä enast(new_wm->wm[6].ignore_lines), new_wm->wm[6].lines, 262842a0d256SVille Syrjälä enast(new_wm->wm[7].ignore_lines), new_wm->wm[7].lines, 262942a0d256SVille Syrjälä enast(new_wm->trans_wm.ignore_lines), new_wm->trans_wm.lines, 263042a0d256SVille Syrjälä enast(new_wm->sagv.wm0.ignore_lines), new_wm->sagv.wm0.lines, 263142a0d256SVille Syrjälä enast(new_wm->sagv.trans_wm.ignore_lines), new_wm->sagv.trans_wm.lines); 263242a0d256SVille Syrjälä 263342a0d256SVille Syrjälä drm_dbg_kms(&i915->drm, 263442a0d256SVille Syrjälä "[PLANE:%d:%s] blocks %4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%5d" 263542a0d256SVille Syrjälä " -> %4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%5d\n", 263642a0d256SVille Syrjälä plane->base.base.id, plane->base.name, 263742a0d256SVille Syrjälä old_wm->wm[0].blocks, old_wm->wm[1].blocks, 263842a0d256SVille Syrjälä old_wm->wm[2].blocks, old_wm->wm[3].blocks, 263942a0d256SVille Syrjälä old_wm->wm[4].blocks, old_wm->wm[5].blocks, 264042a0d256SVille Syrjälä old_wm->wm[6].blocks, old_wm->wm[7].blocks, 264142a0d256SVille Syrjälä old_wm->trans_wm.blocks, 264242a0d256SVille Syrjälä old_wm->sagv.wm0.blocks, 264342a0d256SVille Syrjälä old_wm->sagv.trans_wm.blocks, 264442a0d256SVille Syrjälä new_wm->wm[0].blocks, new_wm->wm[1].blocks, 264542a0d256SVille Syrjälä new_wm->wm[2].blocks, new_wm->wm[3].blocks, 264642a0d256SVille Syrjälä new_wm->wm[4].blocks, new_wm->wm[5].blocks, 264742a0d256SVille Syrjälä new_wm->wm[6].blocks, new_wm->wm[7].blocks, 264842a0d256SVille Syrjälä new_wm->trans_wm.blocks, 264942a0d256SVille Syrjälä new_wm->sagv.wm0.blocks, 265042a0d256SVille Syrjälä new_wm->sagv.trans_wm.blocks); 265142a0d256SVille Syrjälä 265242a0d256SVille Syrjälä drm_dbg_kms(&i915->drm, 265342a0d256SVille Syrjälä "[PLANE:%d:%s] min_ddb %4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%5d" 265442a0d256SVille Syrjälä " -> %4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%5d\n", 265542a0d256SVille Syrjälä plane->base.base.id, plane->base.name, 265642a0d256SVille Syrjälä old_wm->wm[0].min_ddb_alloc, old_wm->wm[1].min_ddb_alloc, 265742a0d256SVille Syrjälä old_wm->wm[2].min_ddb_alloc, old_wm->wm[3].min_ddb_alloc, 265842a0d256SVille Syrjälä old_wm->wm[4].min_ddb_alloc, old_wm->wm[5].min_ddb_alloc, 265942a0d256SVille Syrjälä old_wm->wm[6].min_ddb_alloc, old_wm->wm[7].min_ddb_alloc, 266042a0d256SVille Syrjälä old_wm->trans_wm.min_ddb_alloc, 266142a0d256SVille Syrjälä old_wm->sagv.wm0.min_ddb_alloc, 266242a0d256SVille Syrjälä old_wm->sagv.trans_wm.min_ddb_alloc, 266342a0d256SVille Syrjälä new_wm->wm[0].min_ddb_alloc, new_wm->wm[1].min_ddb_alloc, 266442a0d256SVille Syrjälä new_wm->wm[2].min_ddb_alloc, new_wm->wm[3].min_ddb_alloc, 266542a0d256SVille Syrjälä new_wm->wm[4].min_ddb_alloc, new_wm->wm[5].min_ddb_alloc, 266642a0d256SVille Syrjälä new_wm->wm[6].min_ddb_alloc, new_wm->wm[7].min_ddb_alloc, 266742a0d256SVille Syrjälä new_wm->trans_wm.min_ddb_alloc, 266842a0d256SVille Syrjälä new_wm->sagv.wm0.min_ddb_alloc, 266942a0d256SVille Syrjälä new_wm->sagv.trans_wm.min_ddb_alloc); 267042a0d256SVille Syrjälä } 267142a0d256SVille Syrjälä } 267242a0d256SVille Syrjälä } 267342a0d256SVille Syrjälä 267442a0d256SVille Syrjälä static bool skl_plane_selected_wm_equals(struct intel_plane *plane, 267542a0d256SVille Syrjälä const struct skl_pipe_wm *old_pipe_wm, 267642a0d256SVille Syrjälä const struct skl_pipe_wm *new_pipe_wm) 267742a0d256SVille Syrjälä { 267842a0d256SVille Syrjälä struct drm_i915_private *i915 = to_i915(plane->base.dev); 267942a0d256SVille Syrjälä int level, max_level = ilk_wm_max_level(i915); 268042a0d256SVille Syrjälä 268142a0d256SVille Syrjälä for (level = 0; level <= max_level; level++) { 268242a0d256SVille Syrjälä /* 268342a0d256SVille Syrjälä * We don't check uv_wm as the hardware doesn't actually 268442a0d256SVille Syrjälä * use it. It only gets used for calculating the required 268542a0d256SVille Syrjälä * ddb allocation. 268642a0d256SVille Syrjälä */ 268742a0d256SVille Syrjälä if (!skl_wm_level_equals(skl_plane_wm_level(old_pipe_wm, plane->id, level), 268842a0d256SVille Syrjälä skl_plane_wm_level(new_pipe_wm, plane->id, level))) 268942a0d256SVille Syrjälä return false; 269042a0d256SVille Syrjälä } 269142a0d256SVille Syrjälä 269242a0d256SVille Syrjälä if (HAS_HW_SAGV_WM(i915)) { 269342a0d256SVille Syrjälä const struct skl_plane_wm *old_wm = &old_pipe_wm->planes[plane->id]; 269442a0d256SVille Syrjälä const struct skl_plane_wm *new_wm = &new_pipe_wm->planes[plane->id]; 269542a0d256SVille Syrjälä 269642a0d256SVille Syrjälä if (!skl_wm_level_equals(&old_wm->sagv.wm0, &new_wm->sagv.wm0) || 269742a0d256SVille Syrjälä !skl_wm_level_equals(&old_wm->sagv.trans_wm, &new_wm->sagv.trans_wm)) 269842a0d256SVille Syrjälä return false; 269942a0d256SVille Syrjälä } 270042a0d256SVille Syrjälä 270142a0d256SVille Syrjälä return skl_wm_level_equals(skl_plane_trans_wm(old_pipe_wm, plane->id), 270242a0d256SVille Syrjälä skl_plane_trans_wm(new_pipe_wm, plane->id)); 270342a0d256SVille Syrjälä } 270442a0d256SVille Syrjälä 270542a0d256SVille Syrjälä /* 270642a0d256SVille Syrjälä * To make sure the cursor watermark registers are always consistent 270742a0d256SVille Syrjälä * with our computed state the following scenario needs special 270842a0d256SVille Syrjälä * treatment: 270942a0d256SVille Syrjälä * 271042a0d256SVille Syrjälä * 1. enable cursor 271142a0d256SVille Syrjälä * 2. move cursor entirely offscreen 271242a0d256SVille Syrjälä * 3. disable cursor 271342a0d256SVille Syrjälä * 271442a0d256SVille Syrjälä * Step 2. does call .disable_plane() but does not zero the watermarks 271542a0d256SVille Syrjälä * (since we consider an offscreen cursor still active for the purposes 271642a0d256SVille Syrjälä * of watermarks). Step 3. would not normally call .disable_plane() 271742a0d256SVille Syrjälä * because the actual plane visibility isn't changing, and we don't 271842a0d256SVille Syrjälä * deallocate the cursor ddb until the pipe gets disabled. So we must 271942a0d256SVille Syrjälä * force step 3. to call .disable_plane() to update the watermark 272042a0d256SVille Syrjälä * registers properly. 272142a0d256SVille Syrjälä * 272242a0d256SVille Syrjälä * Other planes do not suffer from this issues as their watermarks are 272342a0d256SVille Syrjälä * calculated based on the actual plane visibility. The only time this 272442a0d256SVille Syrjälä * can trigger for the other planes is during the initial readout as the 272542a0d256SVille Syrjälä * default value of the watermarks registers is not zero. 272642a0d256SVille Syrjälä */ 272742a0d256SVille Syrjälä static int skl_wm_add_affected_planes(struct intel_atomic_state *state, 272842a0d256SVille Syrjälä struct intel_crtc *crtc) 272942a0d256SVille Syrjälä { 273042a0d256SVille Syrjälä struct drm_i915_private *i915 = to_i915(crtc->base.dev); 273142a0d256SVille Syrjälä const struct intel_crtc_state *old_crtc_state = 273242a0d256SVille Syrjälä intel_atomic_get_old_crtc_state(state, crtc); 273342a0d256SVille Syrjälä struct intel_crtc_state *new_crtc_state = 273442a0d256SVille Syrjälä intel_atomic_get_new_crtc_state(state, crtc); 273542a0d256SVille Syrjälä struct intel_plane *plane; 273642a0d256SVille Syrjälä 273742a0d256SVille Syrjälä for_each_intel_plane_on_crtc(&i915->drm, crtc, plane) { 273842a0d256SVille Syrjälä struct intel_plane_state *plane_state; 273942a0d256SVille Syrjälä enum plane_id plane_id = plane->id; 274042a0d256SVille Syrjälä 274142a0d256SVille Syrjälä /* 274242a0d256SVille Syrjälä * Force a full wm update for every plane on modeset. 274342a0d256SVille Syrjälä * Required because the reset value of the wm registers 274442a0d256SVille Syrjälä * is non-zero, whereas we want all disabled planes to 274542a0d256SVille Syrjälä * have zero watermarks. So if we turn off the relevant 274642a0d256SVille Syrjälä * power well the hardware state will go out of sync 274742a0d256SVille Syrjälä * with the software state. 274842a0d256SVille Syrjälä */ 2749882ecff7SVille Syrjälä if (!intel_crtc_needs_modeset(new_crtc_state) && 275042a0d256SVille Syrjälä skl_plane_selected_wm_equals(plane, 275142a0d256SVille Syrjälä &old_crtc_state->wm.skl.optimal, 275242a0d256SVille Syrjälä &new_crtc_state->wm.skl.optimal)) 275342a0d256SVille Syrjälä continue; 275442a0d256SVille Syrjälä 275542a0d256SVille Syrjälä plane_state = intel_atomic_get_plane_state(state, plane); 275642a0d256SVille Syrjälä if (IS_ERR(plane_state)) 275742a0d256SVille Syrjälä return PTR_ERR(plane_state); 275842a0d256SVille Syrjälä 275942a0d256SVille Syrjälä new_crtc_state->update_planes |= BIT(plane_id); 27609d691c19SAndrzej Hajda new_crtc_state->async_flip_planes = 0; 27619d691c19SAndrzej Hajda new_crtc_state->do_async_flip = false; 276242a0d256SVille Syrjälä } 276342a0d256SVille Syrjälä 276442a0d256SVille Syrjälä return 0; 276542a0d256SVille Syrjälä } 276642a0d256SVille Syrjälä 276742a0d256SVille Syrjälä static int 276842a0d256SVille Syrjälä skl_compute_wm(struct intel_atomic_state *state) 276942a0d256SVille Syrjälä { 277042a0d256SVille Syrjälä struct intel_crtc *crtc; 277142a0d256SVille Syrjälä struct intel_crtc_state *new_crtc_state; 277242a0d256SVille Syrjälä int ret, i; 277342a0d256SVille Syrjälä 277442a0d256SVille Syrjälä for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) { 277542a0d256SVille Syrjälä ret = skl_build_pipe_wm(state, crtc); 277642a0d256SVille Syrjälä if (ret) 277742a0d256SVille Syrjälä return ret; 277842a0d256SVille Syrjälä } 277942a0d256SVille Syrjälä 278042a0d256SVille Syrjälä ret = skl_compute_ddb(state); 278142a0d256SVille Syrjälä if (ret) 278242a0d256SVille Syrjälä return ret; 278342a0d256SVille Syrjälä 278442a0d256SVille Syrjälä ret = intel_compute_sagv_mask(state); 278542a0d256SVille Syrjälä if (ret) 278642a0d256SVille Syrjälä return ret; 278742a0d256SVille Syrjälä 278842a0d256SVille Syrjälä /* 278942a0d256SVille Syrjälä * skl_compute_ddb() will have adjusted the final watermarks 279042a0d256SVille Syrjälä * based on how much ddb is available. Now we can actually 279142a0d256SVille Syrjälä * check if the final watermarks changed. 279242a0d256SVille Syrjälä */ 279342a0d256SVille Syrjälä for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) { 279442a0d256SVille Syrjälä ret = skl_wm_add_affected_planes(state, crtc); 279542a0d256SVille Syrjälä if (ret) 279642a0d256SVille Syrjälä return ret; 279742a0d256SVille Syrjälä } 279842a0d256SVille Syrjälä 279942a0d256SVille Syrjälä skl_print_wm_changes(state); 280042a0d256SVille Syrjälä 280142a0d256SVille Syrjälä return 0; 280242a0d256SVille Syrjälä } 280342a0d256SVille Syrjälä 280442a0d256SVille Syrjälä static void skl_wm_level_from_reg_val(u32 val, struct skl_wm_level *level) 280542a0d256SVille Syrjälä { 280642a0d256SVille Syrjälä level->enable = val & PLANE_WM_EN; 280742a0d256SVille Syrjälä level->ignore_lines = val & PLANE_WM_IGNORE_LINES; 280842a0d256SVille Syrjälä level->blocks = REG_FIELD_GET(PLANE_WM_BLOCKS_MASK, val); 280942a0d256SVille Syrjälä level->lines = REG_FIELD_GET(PLANE_WM_LINES_MASK, val); 281042a0d256SVille Syrjälä } 281142a0d256SVille Syrjälä 281242a0d256SVille Syrjälä static void skl_pipe_wm_get_hw_state(struct intel_crtc *crtc, 281342a0d256SVille Syrjälä struct skl_pipe_wm *out) 281442a0d256SVille Syrjälä { 281542a0d256SVille Syrjälä struct drm_i915_private *i915 = to_i915(crtc->base.dev); 281642a0d256SVille Syrjälä enum pipe pipe = crtc->pipe; 281742a0d256SVille Syrjälä int level, max_level; 281842a0d256SVille Syrjälä enum plane_id plane_id; 281942a0d256SVille Syrjälä u32 val; 282042a0d256SVille Syrjälä 282142a0d256SVille Syrjälä max_level = ilk_wm_max_level(i915); 282242a0d256SVille Syrjälä 282342a0d256SVille Syrjälä for_each_plane_id_on_crtc(crtc, plane_id) { 282442a0d256SVille Syrjälä struct skl_plane_wm *wm = &out->planes[plane_id]; 282542a0d256SVille Syrjälä 282642a0d256SVille Syrjälä for (level = 0; level <= max_level; level++) { 282742a0d256SVille Syrjälä if (plane_id != PLANE_CURSOR) 282800136429SJani Nikula val = intel_de_read(i915, PLANE_WM(pipe, plane_id, level)); 282942a0d256SVille Syrjälä else 283000136429SJani Nikula val = intel_de_read(i915, CUR_WM(pipe, level)); 283142a0d256SVille Syrjälä 283242a0d256SVille Syrjälä skl_wm_level_from_reg_val(val, &wm->wm[level]); 283342a0d256SVille Syrjälä } 283442a0d256SVille Syrjälä 283542a0d256SVille Syrjälä if (plane_id != PLANE_CURSOR) 283600136429SJani Nikula val = intel_de_read(i915, PLANE_WM_TRANS(pipe, plane_id)); 283742a0d256SVille Syrjälä else 283800136429SJani Nikula val = intel_de_read(i915, CUR_WM_TRANS(pipe)); 283942a0d256SVille Syrjälä 284042a0d256SVille Syrjälä skl_wm_level_from_reg_val(val, &wm->trans_wm); 284142a0d256SVille Syrjälä 284242a0d256SVille Syrjälä if (HAS_HW_SAGV_WM(i915)) { 284342a0d256SVille Syrjälä if (plane_id != PLANE_CURSOR) 284400136429SJani Nikula val = intel_de_read(i915, PLANE_WM_SAGV(pipe, plane_id)); 284542a0d256SVille Syrjälä else 284600136429SJani Nikula val = intel_de_read(i915, CUR_WM_SAGV(pipe)); 284742a0d256SVille Syrjälä 284842a0d256SVille Syrjälä skl_wm_level_from_reg_val(val, &wm->sagv.wm0); 284942a0d256SVille Syrjälä 285042a0d256SVille Syrjälä if (plane_id != PLANE_CURSOR) 285100136429SJani Nikula val = intel_de_read(i915, PLANE_WM_SAGV_TRANS(pipe, plane_id)); 285242a0d256SVille Syrjälä else 285300136429SJani Nikula val = intel_de_read(i915, CUR_WM_SAGV_TRANS(pipe)); 285442a0d256SVille Syrjälä 285542a0d256SVille Syrjälä skl_wm_level_from_reg_val(val, &wm->sagv.trans_wm); 285642a0d256SVille Syrjälä } else if (DISPLAY_VER(i915) >= 12) { 285742a0d256SVille Syrjälä wm->sagv.wm0 = wm->wm[0]; 285842a0d256SVille Syrjälä wm->sagv.trans_wm = wm->trans_wm; 285942a0d256SVille Syrjälä } 286042a0d256SVille Syrjälä } 286142a0d256SVille Syrjälä } 286242a0d256SVille Syrjälä 286342a0d256SVille Syrjälä void skl_wm_get_hw_state(struct drm_i915_private *i915) 286442a0d256SVille Syrjälä { 286542a0d256SVille Syrjälä struct intel_dbuf_state *dbuf_state = 286642a0d256SVille Syrjälä to_intel_dbuf_state(i915->display.dbuf.obj.state); 286742a0d256SVille Syrjälä struct intel_crtc *crtc; 286842a0d256SVille Syrjälä 286942a0d256SVille Syrjälä if (HAS_MBUS_JOINING(i915)) 287042a0d256SVille Syrjälä dbuf_state->joined_mbus = intel_de_read(i915, MBUS_CTL) & MBUS_JOIN; 287142a0d256SVille Syrjälä 287242a0d256SVille Syrjälä for_each_intel_crtc(&i915->drm, crtc) { 287342a0d256SVille Syrjälä struct intel_crtc_state *crtc_state = 287442a0d256SVille Syrjälä to_intel_crtc_state(crtc->base.state); 287542a0d256SVille Syrjälä enum pipe pipe = crtc->pipe; 287642a0d256SVille Syrjälä unsigned int mbus_offset; 287742a0d256SVille Syrjälä enum plane_id plane_id; 287842a0d256SVille Syrjälä u8 slices; 287942a0d256SVille Syrjälä 288042a0d256SVille Syrjälä memset(&crtc_state->wm.skl.optimal, 0, 288142a0d256SVille Syrjälä sizeof(crtc_state->wm.skl.optimal)); 288242a0d256SVille Syrjälä if (crtc_state->hw.active) 288342a0d256SVille Syrjälä skl_pipe_wm_get_hw_state(crtc, &crtc_state->wm.skl.optimal); 288442a0d256SVille Syrjälä crtc_state->wm.skl.raw = crtc_state->wm.skl.optimal; 288542a0d256SVille Syrjälä 288642a0d256SVille Syrjälä memset(&dbuf_state->ddb[pipe], 0, sizeof(dbuf_state->ddb[pipe])); 288742a0d256SVille Syrjälä 288842a0d256SVille Syrjälä for_each_plane_id_on_crtc(crtc, plane_id) { 288942a0d256SVille Syrjälä struct skl_ddb_entry *ddb = 289042a0d256SVille Syrjälä &crtc_state->wm.skl.plane_ddb[plane_id]; 289142a0d256SVille Syrjälä struct skl_ddb_entry *ddb_y = 289242a0d256SVille Syrjälä &crtc_state->wm.skl.plane_ddb_y[plane_id]; 289342a0d256SVille Syrjälä 289442a0d256SVille Syrjälä if (!crtc_state->hw.active) 289542a0d256SVille Syrjälä continue; 289642a0d256SVille Syrjälä 289742a0d256SVille Syrjälä skl_ddb_get_hw_plane_state(i915, crtc->pipe, 289842a0d256SVille Syrjälä plane_id, ddb, ddb_y); 289942a0d256SVille Syrjälä 290042a0d256SVille Syrjälä skl_ddb_entry_union(&dbuf_state->ddb[pipe], ddb); 290142a0d256SVille Syrjälä skl_ddb_entry_union(&dbuf_state->ddb[pipe], ddb_y); 290242a0d256SVille Syrjälä } 290342a0d256SVille Syrjälä 290442a0d256SVille Syrjälä dbuf_state->weight[pipe] = intel_crtc_ddb_weight(crtc_state); 290542a0d256SVille Syrjälä 290642a0d256SVille Syrjälä /* 290742a0d256SVille Syrjälä * Used for checking overlaps, so we need absolute 290842a0d256SVille Syrjälä * offsets instead of MBUS relative offsets. 290942a0d256SVille Syrjälä */ 291042a0d256SVille Syrjälä slices = skl_compute_dbuf_slices(crtc, dbuf_state->active_pipes, 291142a0d256SVille Syrjälä dbuf_state->joined_mbus); 291242a0d256SVille Syrjälä mbus_offset = mbus_ddb_offset(i915, slices); 291342a0d256SVille Syrjälä crtc_state->wm.skl.ddb.start = mbus_offset + dbuf_state->ddb[pipe].start; 291442a0d256SVille Syrjälä crtc_state->wm.skl.ddb.end = mbus_offset + dbuf_state->ddb[pipe].end; 291542a0d256SVille Syrjälä 291642a0d256SVille Syrjälä /* The slices actually used by the planes on the pipe */ 291742a0d256SVille Syrjälä dbuf_state->slices[pipe] = 291842a0d256SVille Syrjälä skl_ddb_dbuf_slice_mask(i915, &crtc_state->wm.skl.ddb); 291942a0d256SVille Syrjälä 292042a0d256SVille Syrjälä drm_dbg_kms(&i915->drm, 292142a0d256SVille Syrjälä "[CRTC:%d:%s] dbuf slices 0x%x, ddb (%d - %d), active pipes 0x%x, mbus joined: %s\n", 292242a0d256SVille Syrjälä crtc->base.base.id, crtc->base.name, 292342a0d256SVille Syrjälä dbuf_state->slices[pipe], dbuf_state->ddb[pipe].start, 292442a0d256SVille Syrjälä dbuf_state->ddb[pipe].end, dbuf_state->active_pipes, 292542a0d256SVille Syrjälä str_yes_no(dbuf_state->joined_mbus)); 292642a0d256SVille Syrjälä } 292742a0d256SVille Syrjälä 292842a0d256SVille Syrjälä dbuf_state->enabled_slices = i915->display.dbuf.enabled_slices; 292942a0d256SVille Syrjälä } 293042a0d256SVille Syrjälä 293142a0d256SVille Syrjälä static bool skl_dbuf_is_misconfigured(struct drm_i915_private *i915) 293242a0d256SVille Syrjälä { 293342a0d256SVille Syrjälä const struct intel_dbuf_state *dbuf_state = 293442a0d256SVille Syrjälä to_intel_dbuf_state(i915->display.dbuf.obj.state); 293542a0d256SVille Syrjälä struct skl_ddb_entry entries[I915_MAX_PIPES] = {}; 293642a0d256SVille Syrjälä struct intel_crtc *crtc; 293742a0d256SVille Syrjälä 293842a0d256SVille Syrjälä for_each_intel_crtc(&i915->drm, crtc) { 293942a0d256SVille Syrjälä const struct intel_crtc_state *crtc_state = 294042a0d256SVille Syrjälä to_intel_crtc_state(crtc->base.state); 294142a0d256SVille Syrjälä 294242a0d256SVille Syrjälä entries[crtc->pipe] = crtc_state->wm.skl.ddb; 294342a0d256SVille Syrjälä } 294442a0d256SVille Syrjälä 294542a0d256SVille Syrjälä for_each_intel_crtc(&i915->drm, crtc) { 294642a0d256SVille Syrjälä const struct intel_crtc_state *crtc_state = 294742a0d256SVille Syrjälä to_intel_crtc_state(crtc->base.state); 294842a0d256SVille Syrjälä u8 slices; 294942a0d256SVille Syrjälä 295042a0d256SVille Syrjälä slices = skl_compute_dbuf_slices(crtc, dbuf_state->active_pipes, 295142a0d256SVille Syrjälä dbuf_state->joined_mbus); 295242a0d256SVille Syrjälä if (dbuf_state->slices[crtc->pipe] & ~slices) 295342a0d256SVille Syrjälä return true; 295442a0d256SVille Syrjälä 295542a0d256SVille Syrjälä if (skl_ddb_allocation_overlaps(&crtc_state->wm.skl.ddb, entries, 295642a0d256SVille Syrjälä I915_MAX_PIPES, crtc->pipe)) 295742a0d256SVille Syrjälä return true; 295842a0d256SVille Syrjälä } 295942a0d256SVille Syrjälä 296042a0d256SVille Syrjälä return false; 296142a0d256SVille Syrjälä } 296242a0d256SVille Syrjälä 296342a0d256SVille Syrjälä void skl_wm_sanitize(struct drm_i915_private *i915) 296442a0d256SVille Syrjälä { 296542a0d256SVille Syrjälä struct intel_crtc *crtc; 296642a0d256SVille Syrjälä 296742a0d256SVille Syrjälä /* 296842a0d256SVille Syrjälä * On TGL/RKL (at least) the BIOS likes to assign the planes 296942a0d256SVille Syrjälä * to the wrong DBUF slices. This will cause an infinite loop 297042a0d256SVille Syrjälä * in skl_commit_modeset_enables() as it can't find a way to 297142a0d256SVille Syrjälä * transition between the old bogus DBUF layout to the new 297242a0d256SVille Syrjälä * proper DBUF layout without DBUF allocation overlaps between 297342a0d256SVille Syrjälä * the planes (which cannot be allowed or else the hardware 297442a0d256SVille Syrjälä * may hang). If we detect a bogus DBUF layout just turn off 297542a0d256SVille Syrjälä * all the planes so that skl_commit_modeset_enables() can 297642a0d256SVille Syrjälä * simply ignore them. 297742a0d256SVille Syrjälä */ 297842a0d256SVille Syrjälä if (!skl_dbuf_is_misconfigured(i915)) 297942a0d256SVille Syrjälä return; 298042a0d256SVille Syrjälä 298142a0d256SVille Syrjälä drm_dbg_kms(&i915->drm, "BIOS has misprogrammed the DBUF, disabling all planes\n"); 298242a0d256SVille Syrjälä 298342a0d256SVille Syrjälä for_each_intel_crtc(&i915->drm, crtc) { 298442a0d256SVille Syrjälä struct intel_plane *plane = to_intel_plane(crtc->base.primary); 298542a0d256SVille Syrjälä const struct intel_plane_state *plane_state = 298642a0d256SVille Syrjälä to_intel_plane_state(plane->base.state); 298742a0d256SVille Syrjälä struct intel_crtc_state *crtc_state = 298842a0d256SVille Syrjälä to_intel_crtc_state(crtc->base.state); 298942a0d256SVille Syrjälä 299042a0d256SVille Syrjälä if (plane_state->uapi.visible) 299142a0d256SVille Syrjälä intel_plane_disable_noatomic(crtc, plane); 299242a0d256SVille Syrjälä 299342a0d256SVille Syrjälä drm_WARN_ON(&i915->drm, crtc_state->active_planes != 0); 299442a0d256SVille Syrjälä 299542a0d256SVille Syrjälä memset(&crtc_state->wm.skl.ddb, 0, sizeof(crtc_state->wm.skl.ddb)); 299642a0d256SVille Syrjälä } 299742a0d256SVille Syrjälä } 299842a0d256SVille Syrjälä 299942a0d256SVille Syrjälä void intel_wm_state_verify(struct intel_crtc *crtc, 300042a0d256SVille Syrjälä struct intel_crtc_state *new_crtc_state) 300142a0d256SVille Syrjälä { 300242a0d256SVille Syrjälä struct drm_i915_private *i915 = to_i915(crtc->base.dev); 300342a0d256SVille Syrjälä struct skl_hw_state { 300442a0d256SVille Syrjälä struct skl_ddb_entry ddb[I915_MAX_PLANES]; 300542a0d256SVille Syrjälä struct skl_ddb_entry ddb_y[I915_MAX_PLANES]; 300642a0d256SVille Syrjälä struct skl_pipe_wm wm; 300742a0d256SVille Syrjälä } *hw; 300842a0d256SVille Syrjälä const struct skl_pipe_wm *sw_wm = &new_crtc_state->wm.skl.optimal; 300942a0d256SVille Syrjälä int level, max_level = ilk_wm_max_level(i915); 301042a0d256SVille Syrjälä struct intel_plane *plane; 301142a0d256SVille Syrjälä u8 hw_enabled_slices; 301242a0d256SVille Syrjälä 301342a0d256SVille Syrjälä if (DISPLAY_VER(i915) < 9 || !new_crtc_state->hw.active) 301442a0d256SVille Syrjälä return; 301542a0d256SVille Syrjälä 301642a0d256SVille Syrjälä hw = kzalloc(sizeof(*hw), GFP_KERNEL); 301742a0d256SVille Syrjälä if (!hw) 301842a0d256SVille Syrjälä return; 301942a0d256SVille Syrjälä 302042a0d256SVille Syrjälä skl_pipe_wm_get_hw_state(crtc, &hw->wm); 302142a0d256SVille Syrjälä 302242a0d256SVille Syrjälä skl_pipe_ddb_get_hw_state(crtc, hw->ddb, hw->ddb_y); 302342a0d256SVille Syrjälä 302442a0d256SVille Syrjälä hw_enabled_slices = intel_enabled_dbuf_slices_mask(i915); 302542a0d256SVille Syrjälä 302642a0d256SVille Syrjälä if (DISPLAY_VER(i915) >= 11 && 302742a0d256SVille Syrjälä hw_enabled_slices != i915->display.dbuf.enabled_slices) 302842a0d256SVille Syrjälä drm_err(&i915->drm, 302942a0d256SVille Syrjälä "mismatch in DBUF Slices (expected 0x%x, got 0x%x)\n", 303042a0d256SVille Syrjälä i915->display.dbuf.enabled_slices, 303142a0d256SVille Syrjälä hw_enabled_slices); 303242a0d256SVille Syrjälä 303342a0d256SVille Syrjälä for_each_intel_plane_on_crtc(&i915->drm, crtc, plane) { 303442a0d256SVille Syrjälä const struct skl_ddb_entry *hw_ddb_entry, *sw_ddb_entry; 303542a0d256SVille Syrjälä const struct skl_wm_level *hw_wm_level, *sw_wm_level; 303642a0d256SVille Syrjälä 303742a0d256SVille Syrjälä /* Watermarks */ 303842a0d256SVille Syrjälä for (level = 0; level <= max_level; level++) { 303942a0d256SVille Syrjälä hw_wm_level = &hw->wm.planes[plane->id].wm[level]; 304042a0d256SVille Syrjälä sw_wm_level = skl_plane_wm_level(sw_wm, plane->id, level); 304142a0d256SVille Syrjälä 304242a0d256SVille Syrjälä if (skl_wm_level_equals(hw_wm_level, sw_wm_level)) 304342a0d256SVille Syrjälä continue; 304442a0d256SVille Syrjälä 304542a0d256SVille Syrjälä drm_err(&i915->drm, 304642a0d256SVille Syrjälä "[PLANE:%d:%s] mismatch in WM%d (expected e=%d b=%u l=%u, got e=%d b=%u l=%u)\n", 304742a0d256SVille Syrjälä plane->base.base.id, plane->base.name, level, 304842a0d256SVille Syrjälä sw_wm_level->enable, 304942a0d256SVille Syrjälä sw_wm_level->blocks, 305042a0d256SVille Syrjälä sw_wm_level->lines, 305142a0d256SVille Syrjälä hw_wm_level->enable, 305242a0d256SVille Syrjälä hw_wm_level->blocks, 305342a0d256SVille Syrjälä hw_wm_level->lines); 305442a0d256SVille Syrjälä } 305542a0d256SVille Syrjälä 305642a0d256SVille Syrjälä hw_wm_level = &hw->wm.planes[plane->id].trans_wm; 305742a0d256SVille Syrjälä sw_wm_level = skl_plane_trans_wm(sw_wm, plane->id); 305842a0d256SVille Syrjälä 305942a0d256SVille Syrjälä if (!skl_wm_level_equals(hw_wm_level, sw_wm_level)) { 306042a0d256SVille Syrjälä drm_err(&i915->drm, 306142a0d256SVille Syrjälä "[PLANE:%d:%s] mismatch in trans WM (expected e=%d b=%u l=%u, got e=%d b=%u l=%u)\n", 306242a0d256SVille Syrjälä plane->base.base.id, plane->base.name, 306342a0d256SVille Syrjälä sw_wm_level->enable, 306442a0d256SVille Syrjälä sw_wm_level->blocks, 306542a0d256SVille Syrjälä sw_wm_level->lines, 306642a0d256SVille Syrjälä hw_wm_level->enable, 306742a0d256SVille Syrjälä hw_wm_level->blocks, 306842a0d256SVille Syrjälä hw_wm_level->lines); 306942a0d256SVille Syrjälä } 307042a0d256SVille Syrjälä 307142a0d256SVille Syrjälä hw_wm_level = &hw->wm.planes[plane->id].sagv.wm0; 307242a0d256SVille Syrjälä sw_wm_level = &sw_wm->planes[plane->id].sagv.wm0; 307342a0d256SVille Syrjälä 307442a0d256SVille Syrjälä if (HAS_HW_SAGV_WM(i915) && 307542a0d256SVille Syrjälä !skl_wm_level_equals(hw_wm_level, sw_wm_level)) { 307642a0d256SVille Syrjälä drm_err(&i915->drm, 307742a0d256SVille Syrjälä "[PLANE:%d:%s] mismatch in SAGV WM (expected e=%d b=%u l=%u, got e=%d b=%u l=%u)\n", 307842a0d256SVille Syrjälä plane->base.base.id, plane->base.name, 307942a0d256SVille Syrjälä sw_wm_level->enable, 308042a0d256SVille Syrjälä sw_wm_level->blocks, 308142a0d256SVille Syrjälä sw_wm_level->lines, 308242a0d256SVille Syrjälä hw_wm_level->enable, 308342a0d256SVille Syrjälä hw_wm_level->blocks, 308442a0d256SVille Syrjälä hw_wm_level->lines); 308542a0d256SVille Syrjälä } 308642a0d256SVille Syrjälä 308742a0d256SVille Syrjälä hw_wm_level = &hw->wm.planes[plane->id].sagv.trans_wm; 308842a0d256SVille Syrjälä sw_wm_level = &sw_wm->planes[plane->id].sagv.trans_wm; 308942a0d256SVille Syrjälä 309042a0d256SVille Syrjälä if (HAS_HW_SAGV_WM(i915) && 309142a0d256SVille Syrjälä !skl_wm_level_equals(hw_wm_level, sw_wm_level)) { 309242a0d256SVille Syrjälä drm_err(&i915->drm, 309342a0d256SVille Syrjälä "[PLANE:%d:%s] mismatch in SAGV trans WM (expected e=%d b=%u l=%u, got e=%d b=%u l=%u)\n", 309442a0d256SVille Syrjälä plane->base.base.id, plane->base.name, 309542a0d256SVille Syrjälä sw_wm_level->enable, 309642a0d256SVille Syrjälä sw_wm_level->blocks, 309742a0d256SVille Syrjälä sw_wm_level->lines, 309842a0d256SVille Syrjälä hw_wm_level->enable, 309942a0d256SVille Syrjälä hw_wm_level->blocks, 310042a0d256SVille Syrjälä hw_wm_level->lines); 310142a0d256SVille Syrjälä } 310242a0d256SVille Syrjälä 310342a0d256SVille Syrjälä /* DDB */ 310442a0d256SVille Syrjälä hw_ddb_entry = &hw->ddb[PLANE_CURSOR]; 310542a0d256SVille Syrjälä sw_ddb_entry = &new_crtc_state->wm.skl.plane_ddb[PLANE_CURSOR]; 310642a0d256SVille Syrjälä 310742a0d256SVille Syrjälä if (!skl_ddb_entry_equal(hw_ddb_entry, sw_ddb_entry)) { 310842a0d256SVille Syrjälä drm_err(&i915->drm, 310942a0d256SVille Syrjälä "[PLANE:%d:%s] mismatch in DDB (expected (%u,%u), found (%u,%u))\n", 311042a0d256SVille Syrjälä plane->base.base.id, plane->base.name, 311142a0d256SVille Syrjälä sw_ddb_entry->start, sw_ddb_entry->end, 311242a0d256SVille Syrjälä hw_ddb_entry->start, hw_ddb_entry->end); 311342a0d256SVille Syrjälä } 311442a0d256SVille Syrjälä } 311542a0d256SVille Syrjälä 311642a0d256SVille Syrjälä kfree(hw); 311742a0d256SVille Syrjälä } 311842a0d256SVille Syrjälä 311923fbdb07SJani Nikula bool skl_watermark_ipc_enabled(struct drm_i915_private *i915) 312023fbdb07SJani Nikula { 312170296670SJani Nikula return i915->display.wm.ipc_enabled; 312223fbdb07SJani Nikula } 312323fbdb07SJani Nikula 312423fbdb07SJani Nikula void skl_watermark_ipc_update(struct drm_i915_private *i915) 312542a0d256SVille Syrjälä { 312642a0d256SVille Syrjälä if (!HAS_IPC(i915)) 312742a0d256SVille Syrjälä return; 312842a0d256SVille Syrjälä 312900136429SJani Nikula intel_de_rmw(i915, DISP_ARB_CTL2, DISP_IPC_ENABLE, 3130c73cdd12SJani Nikula skl_watermark_ipc_enabled(i915) ? DISP_IPC_ENABLE : 0); 313142a0d256SVille Syrjälä } 313242a0d256SVille Syrjälä 313323fbdb07SJani Nikula static bool skl_watermark_ipc_can_enable(struct drm_i915_private *i915) 313442a0d256SVille Syrjälä { 313542a0d256SVille Syrjälä /* Display WA #0477 WaDisableIPC: skl */ 313642a0d256SVille Syrjälä if (IS_SKYLAKE(i915)) 313742a0d256SVille Syrjälä return false; 313842a0d256SVille Syrjälä 313942a0d256SVille Syrjälä /* Display WA #1141: SKL:all KBL:all CFL */ 314042a0d256SVille Syrjälä if (IS_KABYLAKE(i915) || 314142a0d256SVille Syrjälä IS_COFFEELAKE(i915) || 314242a0d256SVille Syrjälä IS_COMETLAKE(i915)) 314342a0d256SVille Syrjälä return i915->dram_info.symmetric_memory; 314442a0d256SVille Syrjälä 314542a0d256SVille Syrjälä return true; 314642a0d256SVille Syrjälä } 314742a0d256SVille Syrjälä 314823fbdb07SJani Nikula void skl_watermark_ipc_init(struct drm_i915_private *i915) 314942a0d256SVille Syrjälä { 315042a0d256SVille Syrjälä if (!HAS_IPC(i915)) 315142a0d256SVille Syrjälä return; 315242a0d256SVille Syrjälä 315370296670SJani Nikula i915->display.wm.ipc_enabled = skl_watermark_ipc_can_enable(i915); 315442a0d256SVille Syrjälä 315523fbdb07SJani Nikula skl_watermark_ipc_update(i915); 315642a0d256SVille Syrjälä } 315742a0d256SVille Syrjälä 315842a0d256SVille Syrjälä static void 315942a0d256SVille Syrjälä adjust_wm_latency(struct drm_i915_private *i915, 316042a0d256SVille Syrjälä u16 wm[], int max_level, int read_latency) 316142a0d256SVille Syrjälä { 316242a0d256SVille Syrjälä bool wm_lv_0_adjust_needed = i915->dram_info.wm_lv_0_adjust_needed; 316342a0d256SVille Syrjälä int i, level; 316442a0d256SVille Syrjälä 316542a0d256SVille Syrjälä /* 316642a0d256SVille Syrjälä * If a level n (n > 1) has a 0us latency, all levels m (m >= n) 316742a0d256SVille Syrjälä * need to be disabled. We make sure to sanitize the values out 316842a0d256SVille Syrjälä * of the punit to satisfy this requirement. 316942a0d256SVille Syrjälä */ 317042a0d256SVille Syrjälä for (level = 1; level <= max_level; level++) { 317142a0d256SVille Syrjälä if (wm[level] == 0) { 317242a0d256SVille Syrjälä for (i = level + 1; i <= max_level; i++) 317342a0d256SVille Syrjälä wm[i] = 0; 317442a0d256SVille Syrjälä 317542a0d256SVille Syrjälä max_level = level - 1; 317642a0d256SVille Syrjälä break; 317742a0d256SVille Syrjälä } 317842a0d256SVille Syrjälä } 317942a0d256SVille Syrjälä 318042a0d256SVille Syrjälä /* 318142a0d256SVille Syrjälä * WaWmMemoryReadLatency 318242a0d256SVille Syrjälä * 318342a0d256SVille Syrjälä * punit doesn't take into account the read latency so we need 318442a0d256SVille Syrjälä * to add proper adjustement to each valid level we retrieve 318542a0d256SVille Syrjälä * from the punit when level 0 response data is 0us. 318642a0d256SVille Syrjälä */ 318742a0d256SVille Syrjälä if (wm[0] == 0) { 318842a0d256SVille Syrjälä for (level = 0; level <= max_level; level++) 318942a0d256SVille Syrjälä wm[level] += read_latency; 319042a0d256SVille Syrjälä } 319142a0d256SVille Syrjälä 319242a0d256SVille Syrjälä /* 319342a0d256SVille Syrjälä * WA Level-0 adjustment for 16GB DIMMs: SKL+ 319442a0d256SVille Syrjälä * If we could not get dimm info enable this WA to prevent from 319542a0d256SVille Syrjälä * any underrun. If not able to get Dimm info assume 16GB dimm 319642a0d256SVille Syrjälä * to avoid any underrun. 319742a0d256SVille Syrjälä */ 319842a0d256SVille Syrjälä if (wm_lv_0_adjust_needed) 319942a0d256SVille Syrjälä wm[0] += 1; 320042a0d256SVille Syrjälä } 320142a0d256SVille Syrjälä 320242a0d256SVille Syrjälä static void mtl_read_wm_latency(struct drm_i915_private *i915, u16 wm[]) 320342a0d256SVille Syrjälä { 320442a0d256SVille Syrjälä int max_level = ilk_wm_max_level(i915); 320542a0d256SVille Syrjälä u32 val; 320642a0d256SVille Syrjälä 320700136429SJani Nikula val = intel_de_read(i915, MTL_LATENCY_LP0_LP1); 320842a0d256SVille Syrjälä wm[0] = REG_FIELD_GET(MTL_LATENCY_LEVEL_EVEN_MASK, val); 320942a0d256SVille Syrjälä wm[1] = REG_FIELD_GET(MTL_LATENCY_LEVEL_ODD_MASK, val); 321042a0d256SVille Syrjälä 321100136429SJani Nikula val = intel_de_read(i915, MTL_LATENCY_LP2_LP3); 321242a0d256SVille Syrjälä wm[2] = REG_FIELD_GET(MTL_LATENCY_LEVEL_EVEN_MASK, val); 321342a0d256SVille Syrjälä wm[3] = REG_FIELD_GET(MTL_LATENCY_LEVEL_ODD_MASK, val); 321442a0d256SVille Syrjälä 321500136429SJani Nikula val = intel_de_read(i915, MTL_LATENCY_LP4_LP5); 321642a0d256SVille Syrjälä wm[4] = REG_FIELD_GET(MTL_LATENCY_LEVEL_EVEN_MASK, val); 321742a0d256SVille Syrjälä wm[5] = REG_FIELD_GET(MTL_LATENCY_LEVEL_ODD_MASK, val); 321842a0d256SVille Syrjälä 321942a0d256SVille Syrjälä adjust_wm_latency(i915, wm, max_level, 6); 322042a0d256SVille Syrjälä } 322142a0d256SVille Syrjälä 322242a0d256SVille Syrjälä static void skl_read_wm_latency(struct drm_i915_private *i915, u16 wm[]) 322342a0d256SVille Syrjälä { 322442a0d256SVille Syrjälä int max_level = ilk_wm_max_level(i915); 322542a0d256SVille Syrjälä int read_latency = DISPLAY_VER(i915) >= 12 ? 3 : 2; 322642a0d256SVille Syrjälä int mult = IS_DG2(i915) ? 2 : 1; 322742a0d256SVille Syrjälä u32 val; 322842a0d256SVille Syrjälä int ret; 322942a0d256SVille Syrjälä 323042a0d256SVille Syrjälä /* read the first set of memory latencies[0:3] */ 323142a0d256SVille Syrjälä val = 0; /* data0 to be programmed to 0 for first set */ 323242a0d256SVille Syrjälä ret = snb_pcode_read(&i915->uncore, GEN9_PCODE_READ_MEM_LATENCY, &val, NULL); 323342a0d256SVille Syrjälä if (ret) { 323442a0d256SVille Syrjälä drm_err(&i915->drm, "SKL Mailbox read error = %d\n", ret); 323542a0d256SVille Syrjälä return; 323642a0d256SVille Syrjälä } 323742a0d256SVille Syrjälä 32383fecf93cSVille Syrjälä wm[0] = REG_FIELD_GET(GEN9_MEM_LATENCY_LEVEL_0_4_MASK, val) * mult; 32393fecf93cSVille Syrjälä wm[1] = REG_FIELD_GET(GEN9_MEM_LATENCY_LEVEL_1_5_MASK, val) * mult; 32403fecf93cSVille Syrjälä wm[2] = REG_FIELD_GET(GEN9_MEM_LATENCY_LEVEL_2_6_MASK, val) * mult; 32413fecf93cSVille Syrjälä wm[3] = REG_FIELD_GET(GEN9_MEM_LATENCY_LEVEL_3_7_MASK, val) * mult; 324242a0d256SVille Syrjälä 324342a0d256SVille Syrjälä /* read the second set of memory latencies[4:7] */ 324442a0d256SVille Syrjälä val = 1; /* data0 to be programmed to 1 for second set */ 324542a0d256SVille Syrjälä ret = snb_pcode_read(&i915->uncore, GEN9_PCODE_READ_MEM_LATENCY, &val, NULL); 324642a0d256SVille Syrjälä if (ret) { 324742a0d256SVille Syrjälä drm_err(&i915->drm, "SKL Mailbox read error = %d\n", ret); 324842a0d256SVille Syrjälä return; 324942a0d256SVille Syrjälä } 325042a0d256SVille Syrjälä 32513fecf93cSVille Syrjälä wm[4] = REG_FIELD_GET(GEN9_MEM_LATENCY_LEVEL_0_4_MASK, val) * mult; 32523fecf93cSVille Syrjälä wm[5] = REG_FIELD_GET(GEN9_MEM_LATENCY_LEVEL_1_5_MASK, val) * mult; 32533fecf93cSVille Syrjälä wm[6] = REG_FIELD_GET(GEN9_MEM_LATENCY_LEVEL_2_6_MASK, val) * mult; 32543fecf93cSVille Syrjälä wm[7] = REG_FIELD_GET(GEN9_MEM_LATENCY_LEVEL_3_7_MASK, val) * mult; 325542a0d256SVille Syrjälä 325642a0d256SVille Syrjälä adjust_wm_latency(i915, wm, max_level, read_latency); 325742a0d256SVille Syrjälä } 325842a0d256SVille Syrjälä 325942a0d256SVille Syrjälä static void skl_setup_wm_latency(struct drm_i915_private *i915) 326042a0d256SVille Syrjälä { 326142a0d256SVille Syrjälä if (DISPLAY_VER(i915) >= 14) 326242a0d256SVille Syrjälä mtl_read_wm_latency(i915, i915->display.wm.skl_latency); 326342a0d256SVille Syrjälä else 326442a0d256SVille Syrjälä skl_read_wm_latency(i915, i915->display.wm.skl_latency); 326542a0d256SVille Syrjälä 326642a0d256SVille Syrjälä intel_print_wm_latency(i915, "Gen9 Plane", i915->display.wm.skl_latency); 326742a0d256SVille Syrjälä } 326842a0d256SVille Syrjälä 326942a0d256SVille Syrjälä static const struct intel_wm_funcs skl_wm_funcs = { 327042a0d256SVille Syrjälä .compute_global_watermarks = skl_compute_wm, 327142a0d256SVille Syrjälä }; 327242a0d256SVille Syrjälä 327342a0d256SVille Syrjälä void skl_wm_init(struct drm_i915_private *i915) 327442a0d256SVille Syrjälä { 327542a0d256SVille Syrjälä intel_sagv_init(i915); 327642a0d256SVille Syrjälä 327742a0d256SVille Syrjälä skl_setup_wm_latency(i915); 327842a0d256SVille Syrjälä 327942a0d256SVille Syrjälä i915->display.funcs.wm = &skl_wm_funcs; 328042a0d256SVille Syrjälä } 328142a0d256SVille Syrjälä 328242a0d256SVille Syrjälä static struct intel_global_state *intel_dbuf_duplicate_state(struct intel_global_obj *obj) 328342a0d256SVille Syrjälä { 328442a0d256SVille Syrjälä struct intel_dbuf_state *dbuf_state; 328542a0d256SVille Syrjälä 328642a0d256SVille Syrjälä dbuf_state = kmemdup(obj->state, sizeof(*dbuf_state), GFP_KERNEL); 328742a0d256SVille Syrjälä if (!dbuf_state) 328842a0d256SVille Syrjälä return NULL; 328942a0d256SVille Syrjälä 329042a0d256SVille Syrjälä return &dbuf_state->base; 329142a0d256SVille Syrjälä } 329242a0d256SVille Syrjälä 329342a0d256SVille Syrjälä static void intel_dbuf_destroy_state(struct intel_global_obj *obj, 329442a0d256SVille Syrjälä struct intel_global_state *state) 329542a0d256SVille Syrjälä { 329642a0d256SVille Syrjälä kfree(state); 329742a0d256SVille Syrjälä } 329842a0d256SVille Syrjälä 329942a0d256SVille Syrjälä static const struct intel_global_state_funcs intel_dbuf_funcs = { 330042a0d256SVille Syrjälä .atomic_duplicate_state = intel_dbuf_duplicate_state, 330142a0d256SVille Syrjälä .atomic_destroy_state = intel_dbuf_destroy_state, 330242a0d256SVille Syrjälä }; 330342a0d256SVille Syrjälä 330442a0d256SVille Syrjälä struct intel_dbuf_state * 330542a0d256SVille Syrjälä intel_atomic_get_dbuf_state(struct intel_atomic_state *state) 330642a0d256SVille Syrjälä { 330742a0d256SVille Syrjälä struct drm_i915_private *i915 = to_i915(state->base.dev); 330842a0d256SVille Syrjälä struct intel_global_state *dbuf_state; 330942a0d256SVille Syrjälä 331042a0d256SVille Syrjälä dbuf_state = intel_atomic_get_global_obj_state(state, &i915->display.dbuf.obj); 331142a0d256SVille Syrjälä if (IS_ERR(dbuf_state)) 331242a0d256SVille Syrjälä return ERR_CAST(dbuf_state); 331342a0d256SVille Syrjälä 331442a0d256SVille Syrjälä return to_intel_dbuf_state(dbuf_state); 331542a0d256SVille Syrjälä } 331642a0d256SVille Syrjälä 331742a0d256SVille Syrjälä int intel_dbuf_init(struct drm_i915_private *i915) 331842a0d256SVille Syrjälä { 331942a0d256SVille Syrjälä struct intel_dbuf_state *dbuf_state; 332042a0d256SVille Syrjälä 332142a0d256SVille Syrjälä dbuf_state = kzalloc(sizeof(*dbuf_state), GFP_KERNEL); 332242a0d256SVille Syrjälä if (!dbuf_state) 332342a0d256SVille Syrjälä return -ENOMEM; 332442a0d256SVille Syrjälä 332542a0d256SVille Syrjälä intel_atomic_global_obj_init(i915, &i915->display.dbuf.obj, 332642a0d256SVille Syrjälä &dbuf_state->base, &intel_dbuf_funcs); 332742a0d256SVille Syrjälä 332842a0d256SVille Syrjälä return 0; 332942a0d256SVille Syrjälä } 333042a0d256SVille Syrjälä 333142a0d256SVille Syrjälä /* 333242a0d256SVille Syrjälä * Configure MBUS_CTL and all DBUF_CTL_S of each slice to join_mbus state before 333342a0d256SVille Syrjälä * update the request state of all DBUS slices. 333442a0d256SVille Syrjälä */ 333542a0d256SVille Syrjälä static void update_mbus_pre_enable(struct intel_atomic_state *state) 333642a0d256SVille Syrjälä { 333742a0d256SVille Syrjälä struct drm_i915_private *i915 = to_i915(state->base.dev); 333842a0d256SVille Syrjälä u32 mbus_ctl, dbuf_min_tracker_val; 333942a0d256SVille Syrjälä enum dbuf_slice slice; 334042a0d256SVille Syrjälä const struct intel_dbuf_state *dbuf_state = 334142a0d256SVille Syrjälä intel_atomic_get_new_dbuf_state(state); 334242a0d256SVille Syrjälä 334342a0d256SVille Syrjälä if (!HAS_MBUS_JOINING(i915)) 334442a0d256SVille Syrjälä return; 334542a0d256SVille Syrjälä 334642a0d256SVille Syrjälä /* 334742a0d256SVille Syrjälä * TODO: Implement vblank synchronized MBUS joining changes. 334842a0d256SVille Syrjälä * Must be properly coordinated with dbuf reprogramming. 334942a0d256SVille Syrjälä */ 335042a0d256SVille Syrjälä if (dbuf_state->joined_mbus) { 335142a0d256SVille Syrjälä mbus_ctl = MBUS_HASHING_MODE_1x4 | MBUS_JOIN | 335242a0d256SVille Syrjälä MBUS_JOIN_PIPE_SELECT_NONE; 335342a0d256SVille Syrjälä dbuf_min_tracker_val = DBUF_MIN_TRACKER_STATE_SERVICE(3); 335442a0d256SVille Syrjälä } else { 335542a0d256SVille Syrjälä mbus_ctl = MBUS_HASHING_MODE_2x2 | 335642a0d256SVille Syrjälä MBUS_JOIN_PIPE_SELECT_NONE; 335742a0d256SVille Syrjälä dbuf_min_tracker_val = DBUF_MIN_TRACKER_STATE_SERVICE(1); 335842a0d256SVille Syrjälä } 335942a0d256SVille Syrjälä 336042a0d256SVille Syrjälä intel_de_rmw(i915, MBUS_CTL, 336142a0d256SVille Syrjälä MBUS_HASHING_MODE_MASK | MBUS_JOIN | 336242a0d256SVille Syrjälä MBUS_JOIN_PIPE_SELECT_MASK, mbus_ctl); 336342a0d256SVille Syrjälä 336442a0d256SVille Syrjälä for_each_dbuf_slice(i915, slice) 336542a0d256SVille Syrjälä intel_de_rmw(i915, DBUF_CTL_S(slice), 336642a0d256SVille Syrjälä DBUF_MIN_TRACKER_STATE_SERVICE_MASK, 336742a0d256SVille Syrjälä dbuf_min_tracker_val); 336842a0d256SVille Syrjälä } 336942a0d256SVille Syrjälä 337042a0d256SVille Syrjälä void intel_dbuf_pre_plane_update(struct intel_atomic_state *state) 337142a0d256SVille Syrjälä { 337242a0d256SVille Syrjälä struct drm_i915_private *i915 = to_i915(state->base.dev); 337342a0d256SVille Syrjälä const struct intel_dbuf_state *new_dbuf_state = 337442a0d256SVille Syrjälä intel_atomic_get_new_dbuf_state(state); 337542a0d256SVille Syrjälä const struct intel_dbuf_state *old_dbuf_state = 337642a0d256SVille Syrjälä intel_atomic_get_old_dbuf_state(state); 337742a0d256SVille Syrjälä 337842a0d256SVille Syrjälä if (!new_dbuf_state || 337942a0d256SVille Syrjälä (new_dbuf_state->enabled_slices == old_dbuf_state->enabled_slices && 338042a0d256SVille Syrjälä new_dbuf_state->joined_mbus == old_dbuf_state->joined_mbus)) 338142a0d256SVille Syrjälä return; 338242a0d256SVille Syrjälä 338342a0d256SVille Syrjälä WARN_ON(!new_dbuf_state->base.changed); 338442a0d256SVille Syrjälä 338542a0d256SVille Syrjälä update_mbus_pre_enable(state); 338642a0d256SVille Syrjälä gen9_dbuf_slices_update(i915, 338742a0d256SVille Syrjälä old_dbuf_state->enabled_slices | 338842a0d256SVille Syrjälä new_dbuf_state->enabled_slices); 338942a0d256SVille Syrjälä } 339042a0d256SVille Syrjälä 339142a0d256SVille Syrjälä void intel_dbuf_post_plane_update(struct intel_atomic_state *state) 339242a0d256SVille Syrjälä { 339342a0d256SVille Syrjälä struct drm_i915_private *i915 = to_i915(state->base.dev); 339442a0d256SVille Syrjälä const struct intel_dbuf_state *new_dbuf_state = 339542a0d256SVille Syrjälä intel_atomic_get_new_dbuf_state(state); 339642a0d256SVille Syrjälä const struct intel_dbuf_state *old_dbuf_state = 339742a0d256SVille Syrjälä intel_atomic_get_old_dbuf_state(state); 339842a0d256SVille Syrjälä 339942a0d256SVille Syrjälä if (!new_dbuf_state || 340042a0d256SVille Syrjälä (new_dbuf_state->enabled_slices == old_dbuf_state->enabled_slices && 340142a0d256SVille Syrjälä new_dbuf_state->joined_mbus == old_dbuf_state->joined_mbus)) 340242a0d256SVille Syrjälä return; 340342a0d256SVille Syrjälä 340442a0d256SVille Syrjälä WARN_ON(!new_dbuf_state->base.changed); 340542a0d256SVille Syrjälä 340642a0d256SVille Syrjälä gen9_dbuf_slices_update(i915, 340742a0d256SVille Syrjälä new_dbuf_state->enabled_slices); 340842a0d256SVille Syrjälä } 340942a0d256SVille Syrjälä 3410851d635aSRadhakrishna Sripada static bool xelpdp_is_only_pipe_per_dbuf_bank(enum pipe pipe, u8 active_pipes) 3411851d635aSRadhakrishna Sripada { 3412851d635aSRadhakrishna Sripada switch (pipe) { 3413851d635aSRadhakrishna Sripada case PIPE_A: 3414851d635aSRadhakrishna Sripada return !(active_pipes & BIT(PIPE_D)); 3415851d635aSRadhakrishna Sripada case PIPE_D: 3416851d635aSRadhakrishna Sripada return !(active_pipes & BIT(PIPE_A)); 3417851d635aSRadhakrishna Sripada case PIPE_B: 3418851d635aSRadhakrishna Sripada return !(active_pipes & BIT(PIPE_C)); 3419851d635aSRadhakrishna Sripada case PIPE_C: 3420851d635aSRadhakrishna Sripada return !(active_pipes & BIT(PIPE_B)); 3421851d635aSRadhakrishna Sripada default: /* to suppress compiler warning */ 3422851d635aSRadhakrishna Sripada MISSING_CASE(pipe); 3423851d635aSRadhakrishna Sripada break; 3424851d635aSRadhakrishna Sripada } 3425851d635aSRadhakrishna Sripada 3426851d635aSRadhakrishna Sripada return false; 3427851d635aSRadhakrishna Sripada } 3428851d635aSRadhakrishna Sripada 342942a0d256SVille Syrjälä void intel_mbus_dbox_update(struct intel_atomic_state *state) 343042a0d256SVille Syrjälä { 343142a0d256SVille Syrjälä struct drm_i915_private *i915 = to_i915(state->base.dev); 343242a0d256SVille Syrjälä const struct intel_dbuf_state *new_dbuf_state, *old_dbuf_state; 343342a0d256SVille Syrjälä const struct intel_crtc_state *new_crtc_state; 343442a0d256SVille Syrjälä const struct intel_crtc *crtc; 343542a0d256SVille Syrjälä u32 val = 0; 343642a0d256SVille Syrjälä int i; 343742a0d256SVille Syrjälä 343842a0d256SVille Syrjälä if (DISPLAY_VER(i915) < 11) 343942a0d256SVille Syrjälä return; 344042a0d256SVille Syrjälä 344142a0d256SVille Syrjälä new_dbuf_state = intel_atomic_get_new_dbuf_state(state); 344242a0d256SVille Syrjälä old_dbuf_state = intel_atomic_get_old_dbuf_state(state); 344342a0d256SVille Syrjälä if (!new_dbuf_state || 344442a0d256SVille Syrjälä (new_dbuf_state->joined_mbus == old_dbuf_state->joined_mbus && 344542a0d256SVille Syrjälä new_dbuf_state->active_pipes == old_dbuf_state->active_pipes)) 344642a0d256SVille Syrjälä return; 344742a0d256SVille Syrjälä 3448851d635aSRadhakrishna Sripada if (DISPLAY_VER(i915) >= 14) 3449851d635aSRadhakrishna Sripada val |= MBUS_DBOX_I_CREDIT(2); 3450851d635aSRadhakrishna Sripada 345142a0d256SVille Syrjälä if (DISPLAY_VER(i915) >= 12) { 345242a0d256SVille Syrjälä val |= MBUS_DBOX_B2B_TRANSACTIONS_MAX(16); 345342a0d256SVille Syrjälä val |= MBUS_DBOX_B2B_TRANSACTIONS_DELAY(1); 345442a0d256SVille Syrjälä val |= MBUS_DBOX_REGULATE_B2B_TRANSACTIONS_EN; 345542a0d256SVille Syrjälä } 345642a0d256SVille Syrjälä 3457851d635aSRadhakrishna Sripada if (DISPLAY_VER(i915) >= 14) 3458851d635aSRadhakrishna Sripada val |= new_dbuf_state->joined_mbus ? MBUS_DBOX_A_CREDIT(12) : 3459851d635aSRadhakrishna Sripada MBUS_DBOX_A_CREDIT(8); 3460851d635aSRadhakrishna Sripada else if (IS_ALDERLAKE_P(i915)) 346142a0d256SVille Syrjälä /* Wa_22010947358:adl-p */ 346242a0d256SVille Syrjälä val |= new_dbuf_state->joined_mbus ? MBUS_DBOX_A_CREDIT(6) : 346342a0d256SVille Syrjälä MBUS_DBOX_A_CREDIT(4); 346442a0d256SVille Syrjälä else 346542a0d256SVille Syrjälä val |= MBUS_DBOX_A_CREDIT(2); 346642a0d256SVille Syrjälä 3467851d635aSRadhakrishna Sripada if (DISPLAY_VER(i915) >= 14) { 3468851d635aSRadhakrishna Sripada val |= MBUS_DBOX_B_CREDIT(0xA); 3469851d635aSRadhakrishna Sripada } else if (IS_ALDERLAKE_P(i915)) { 347042a0d256SVille Syrjälä val |= MBUS_DBOX_BW_CREDIT(2); 347142a0d256SVille Syrjälä val |= MBUS_DBOX_B_CREDIT(8); 347242a0d256SVille Syrjälä } else if (DISPLAY_VER(i915) >= 12) { 347342a0d256SVille Syrjälä val |= MBUS_DBOX_BW_CREDIT(2); 347442a0d256SVille Syrjälä val |= MBUS_DBOX_B_CREDIT(12); 347542a0d256SVille Syrjälä } else { 347642a0d256SVille Syrjälä val |= MBUS_DBOX_BW_CREDIT(1); 347742a0d256SVille Syrjälä val |= MBUS_DBOX_B_CREDIT(8); 347842a0d256SVille Syrjälä } 347942a0d256SVille Syrjälä 348042a0d256SVille Syrjälä for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) { 3481851d635aSRadhakrishna Sripada u32 pipe_val = val; 3482851d635aSRadhakrishna Sripada 3483851d635aSRadhakrishna Sripada if (!new_crtc_state->hw.active) 348442a0d256SVille Syrjälä continue; 348542a0d256SVille Syrjälä 3486851d635aSRadhakrishna Sripada if (DISPLAY_VER(i915) >= 14) { 3487851d635aSRadhakrishna Sripada if (xelpdp_is_only_pipe_per_dbuf_bank(crtc->pipe, 3488851d635aSRadhakrishna Sripada new_dbuf_state->active_pipes)) 3489851d635aSRadhakrishna Sripada pipe_val |= MBUS_DBOX_BW_8CREDITS_MTL; 3490851d635aSRadhakrishna Sripada else 3491851d635aSRadhakrishna Sripada pipe_val |= MBUS_DBOX_BW_4CREDITS_MTL; 3492851d635aSRadhakrishna Sripada } 3493851d635aSRadhakrishna Sripada 3494851d635aSRadhakrishna Sripada intel_de_write(i915, PIPE_MBUS_DBOX_CTL(crtc->pipe), pipe_val); 349542a0d256SVille Syrjälä } 349642a0d256SVille Syrjälä } 3497dde01ed5SJani Nikula 3498dde01ed5SJani Nikula static int skl_watermark_ipc_status_show(struct seq_file *m, void *data) 3499dde01ed5SJani Nikula { 3500dde01ed5SJani Nikula struct drm_i915_private *i915 = m->private; 3501dde01ed5SJani Nikula 3502dde01ed5SJani Nikula seq_printf(m, "Isochronous Priority Control: %s\n", 3503dde01ed5SJani Nikula str_yes_no(skl_watermark_ipc_enabled(i915))); 3504dde01ed5SJani Nikula return 0; 3505dde01ed5SJani Nikula } 3506dde01ed5SJani Nikula 3507dde01ed5SJani Nikula static int skl_watermark_ipc_status_open(struct inode *inode, struct file *file) 3508dde01ed5SJani Nikula { 3509dde01ed5SJani Nikula struct drm_i915_private *i915 = inode->i_private; 3510dde01ed5SJani Nikula 3511dde01ed5SJani Nikula return single_open(file, skl_watermark_ipc_status_show, i915); 3512dde01ed5SJani Nikula } 3513dde01ed5SJani Nikula 3514dde01ed5SJani Nikula static ssize_t skl_watermark_ipc_status_write(struct file *file, 3515dde01ed5SJani Nikula const char __user *ubuf, 3516dde01ed5SJani Nikula size_t len, loff_t *offp) 3517dde01ed5SJani Nikula { 3518dde01ed5SJani Nikula struct seq_file *m = file->private_data; 3519dde01ed5SJani Nikula struct drm_i915_private *i915 = m->private; 3520dde01ed5SJani Nikula intel_wakeref_t wakeref; 3521dde01ed5SJani Nikula bool enable; 3522dde01ed5SJani Nikula int ret; 3523dde01ed5SJani Nikula 3524dde01ed5SJani Nikula ret = kstrtobool_from_user(ubuf, len, &enable); 3525dde01ed5SJani Nikula if (ret < 0) 3526dde01ed5SJani Nikula return ret; 3527dde01ed5SJani Nikula 3528dde01ed5SJani Nikula with_intel_runtime_pm(&i915->runtime_pm, wakeref) { 3529dde01ed5SJani Nikula if (!skl_watermark_ipc_enabled(i915) && enable) 3530dde01ed5SJani Nikula drm_info(&i915->drm, 3531dde01ed5SJani Nikula "Enabling IPC: WM will be proper only after next commit\n"); 353270296670SJani Nikula i915->display.wm.ipc_enabled = enable; 3533dde01ed5SJani Nikula skl_watermark_ipc_update(i915); 3534dde01ed5SJani Nikula } 3535dde01ed5SJani Nikula 3536dde01ed5SJani Nikula return len; 3537dde01ed5SJani Nikula } 3538dde01ed5SJani Nikula 3539dde01ed5SJani Nikula static const struct file_operations skl_watermark_ipc_status_fops = { 3540dde01ed5SJani Nikula .owner = THIS_MODULE, 3541dde01ed5SJani Nikula .open = skl_watermark_ipc_status_open, 3542dde01ed5SJani Nikula .read = seq_read, 3543dde01ed5SJani Nikula .llseek = seq_lseek, 3544dde01ed5SJani Nikula .release = single_release, 3545dde01ed5SJani Nikula .write = skl_watermark_ipc_status_write 3546dde01ed5SJani Nikula }; 3547dde01ed5SJani Nikula 3548dde01ed5SJani Nikula void skl_watermark_ipc_debugfs_register(struct drm_i915_private *i915) 3549dde01ed5SJani Nikula { 3550dde01ed5SJani Nikula struct drm_minor *minor = i915->drm.primary; 3551dde01ed5SJani Nikula 355262a21a7cSJani Nikula if (!HAS_IPC(i915)) 355362a21a7cSJani Nikula return; 355462a21a7cSJani Nikula 3555dde01ed5SJani Nikula debugfs_create_file("i915_ipc_status", 0644, minor->debugfs_root, i915, 3556dde01ed5SJani Nikula &skl_watermark_ipc_status_fops); 3557dde01ed5SJani Nikula } 3558