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ä 894b49d53SJani Nikula #include "i915_drv.h" 994b49d53SJani Nikula #include "i915_fixed.h" 1094b49d53SJani Nikula #include "i915_reg.h" 1194b49d53SJani Nikula #include "i9xx_wm.h" 1242a0d256SVille Syrjälä #include "intel_atomic.h" 1342a0d256SVille Syrjälä #include "intel_atomic_plane.h" 1442a0d256SVille Syrjälä #include "intel_bw.h" 1542a0d256SVille Syrjälä #include "intel_de.h" 1642a0d256SVille Syrjälä #include "intel_display.h" 1742a0d256SVille Syrjälä #include "intel_display_power.h" 1842a0d256SVille Syrjälä #include "intel_display_types.h" 1942a0d256SVille Syrjälä #include "intel_fb.h" 2042a0d256SVille Syrjälä #include "intel_pcode.h" 2194b49d53SJani Nikula #include "intel_wm.h" 2294b49d53SJani Nikula #include "skl_watermark.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ä { 6743e6fad1SVille Syrjälä return HAS_SAGV(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; 9543e6fad1SVille Syrjälä } else if (HAS_SAGV(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ä { 10443e6fad1SVille Syrjälä if (!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 */ 3627ee6f99dSVille Syrjälä for (level = i915->display.wm.num_levels - 1; 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ä 707*6b931346SVille Syrjälä static unsigned int skl_wm_latency(struct drm_i915_private *i915, int level, 708*6b931346SVille Syrjälä const struct skl_wm_params *wp) 709*6b931346SVille Syrjälä { 710*6b931346SVille Syrjälä unsigned int latency = i915->display.wm.skl_latency[level]; 711*6b931346SVille Syrjälä 712*6b931346SVille Syrjälä if (latency == 0) 713*6b931346SVille Syrjälä return 0; 714*6b931346SVille Syrjälä 715*6b931346SVille Syrjälä /* 716*6b931346SVille Syrjälä * WaIncreaseLatencyIPCEnabled: kbl,cfl 717*6b931346SVille Syrjälä * Display WA #1141: kbl,cfl 718*6b931346SVille Syrjälä */ 719*6b931346SVille Syrjälä if ((IS_KABYLAKE(i915) || IS_COFFEELAKE(i915) || IS_COMETLAKE(i915)) && 720*6b931346SVille Syrjälä skl_watermark_ipc_enabled(i915)) 721*6b931346SVille Syrjälä latency += 4; 722*6b931346SVille Syrjälä 723*6b931346SVille Syrjälä if (skl_needs_memory_bw_wa(i915) && wp->x_tiled) 724*6b931346SVille Syrjälä latency += 15; 725*6b931346SVille Syrjälä 726*6b931346SVille Syrjälä return latency; 727*6b931346SVille Syrjälä } 728*6b931346SVille Syrjälä 72942a0d256SVille Syrjälä static unsigned int 73042a0d256SVille Syrjälä skl_cursor_allocation(const struct intel_crtc_state *crtc_state, 73142a0d256SVille Syrjälä int num_active) 73242a0d256SVille Syrjälä { 73342a0d256SVille Syrjälä struct intel_plane *plane = to_intel_plane(crtc_state->uapi.crtc->cursor); 73442a0d256SVille Syrjälä struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); 73542a0d256SVille Syrjälä struct skl_wm_level wm = {}; 73642a0d256SVille Syrjälä int ret, min_ddb_alloc = 0; 73742a0d256SVille Syrjälä struct skl_wm_params wp; 7387ee6f99dSVille Syrjälä int level; 73942a0d256SVille Syrjälä 74042a0d256SVille Syrjälä ret = skl_compute_wm_params(crtc_state, 256, 74142a0d256SVille Syrjälä drm_format_info(DRM_FORMAT_ARGB8888), 74242a0d256SVille Syrjälä DRM_FORMAT_MOD_LINEAR, 74342a0d256SVille Syrjälä DRM_MODE_ROTATE_0, 74442a0d256SVille Syrjälä crtc_state->pixel_rate, &wp, 0); 74542a0d256SVille Syrjälä drm_WARN_ON(&i915->drm, ret); 74642a0d256SVille Syrjälä 7477ee6f99dSVille Syrjälä for (level = 0; level < i915->display.wm.num_levels; level++) { 748*6b931346SVille Syrjälä unsigned int latency = skl_wm_latency(i915, level, &wp); 74942a0d256SVille Syrjälä 75042a0d256SVille Syrjälä skl_compute_plane_wm(crtc_state, plane, level, latency, &wp, &wm, &wm); 75142a0d256SVille Syrjälä if (wm.min_ddb_alloc == U16_MAX) 75242a0d256SVille Syrjälä break; 75342a0d256SVille Syrjälä 75442a0d256SVille Syrjälä min_ddb_alloc = wm.min_ddb_alloc; 75542a0d256SVille Syrjälä } 75642a0d256SVille Syrjälä 75742a0d256SVille Syrjälä return max(num_active == 1 ? 32 : 8, min_ddb_alloc); 75842a0d256SVille Syrjälä } 75942a0d256SVille Syrjälä 76042a0d256SVille Syrjälä static void skl_ddb_entry_init_from_hw(struct skl_ddb_entry *entry, u32 reg) 76142a0d256SVille Syrjälä { 76242a0d256SVille Syrjälä skl_ddb_entry_init(entry, 76342a0d256SVille Syrjälä REG_FIELD_GET(PLANE_BUF_START_MASK, reg), 76442a0d256SVille Syrjälä REG_FIELD_GET(PLANE_BUF_END_MASK, reg)); 76542a0d256SVille Syrjälä if (entry->end) 76642a0d256SVille Syrjälä entry->end++; 76742a0d256SVille Syrjälä } 76842a0d256SVille Syrjälä 76942a0d256SVille Syrjälä static void 77042a0d256SVille Syrjälä skl_ddb_get_hw_plane_state(struct drm_i915_private *i915, 77142a0d256SVille Syrjälä const enum pipe pipe, 77242a0d256SVille Syrjälä const enum plane_id plane_id, 77342a0d256SVille Syrjälä struct skl_ddb_entry *ddb, 77442a0d256SVille Syrjälä struct skl_ddb_entry *ddb_y) 77542a0d256SVille Syrjälä { 77642a0d256SVille Syrjälä u32 val; 77742a0d256SVille Syrjälä 77842a0d256SVille Syrjälä /* Cursor doesn't support NV12/planar, so no extra calculation needed */ 77942a0d256SVille Syrjälä if (plane_id == PLANE_CURSOR) { 78000136429SJani Nikula val = intel_de_read(i915, CUR_BUF_CFG(pipe)); 78142a0d256SVille Syrjälä skl_ddb_entry_init_from_hw(ddb, val); 78242a0d256SVille Syrjälä return; 78342a0d256SVille Syrjälä } 78442a0d256SVille Syrjälä 78500136429SJani Nikula val = intel_de_read(i915, PLANE_BUF_CFG(pipe, plane_id)); 78642a0d256SVille Syrjälä skl_ddb_entry_init_from_hw(ddb, val); 78742a0d256SVille Syrjälä 78842a0d256SVille Syrjälä if (DISPLAY_VER(i915) >= 11) 78942a0d256SVille Syrjälä return; 79042a0d256SVille Syrjälä 79100136429SJani Nikula val = intel_de_read(i915, PLANE_NV12_BUF_CFG(pipe, plane_id)); 79242a0d256SVille Syrjälä skl_ddb_entry_init_from_hw(ddb_y, val); 79342a0d256SVille Syrjälä } 79442a0d256SVille Syrjälä 79542a0d256SVille Syrjälä static void skl_pipe_ddb_get_hw_state(struct intel_crtc *crtc, 79642a0d256SVille Syrjälä struct skl_ddb_entry *ddb, 79742a0d256SVille Syrjälä struct skl_ddb_entry *ddb_y) 79842a0d256SVille Syrjälä { 79942a0d256SVille Syrjälä struct drm_i915_private *i915 = to_i915(crtc->base.dev); 80042a0d256SVille Syrjälä enum intel_display_power_domain power_domain; 80142a0d256SVille Syrjälä enum pipe pipe = crtc->pipe; 80242a0d256SVille Syrjälä intel_wakeref_t wakeref; 80342a0d256SVille Syrjälä enum plane_id plane_id; 80442a0d256SVille Syrjälä 80542a0d256SVille Syrjälä power_domain = POWER_DOMAIN_PIPE(pipe); 80642a0d256SVille Syrjälä wakeref = intel_display_power_get_if_enabled(i915, power_domain); 80742a0d256SVille Syrjälä if (!wakeref) 80842a0d256SVille Syrjälä return; 80942a0d256SVille Syrjälä 81042a0d256SVille Syrjälä for_each_plane_id_on_crtc(crtc, plane_id) 81142a0d256SVille Syrjälä skl_ddb_get_hw_plane_state(i915, pipe, 81242a0d256SVille Syrjälä plane_id, 81342a0d256SVille Syrjälä &ddb[plane_id], 81442a0d256SVille Syrjälä &ddb_y[plane_id]); 81542a0d256SVille Syrjälä 81642a0d256SVille Syrjälä intel_display_power_put(i915, power_domain, wakeref); 81742a0d256SVille Syrjälä } 81842a0d256SVille Syrjälä 81942a0d256SVille Syrjälä struct dbuf_slice_conf_entry { 82042a0d256SVille Syrjälä u8 active_pipes; 82142a0d256SVille Syrjälä u8 dbuf_mask[I915_MAX_PIPES]; 82242a0d256SVille Syrjälä bool join_mbus; 82342a0d256SVille Syrjälä }; 82442a0d256SVille Syrjälä 82542a0d256SVille Syrjälä /* 82642a0d256SVille Syrjälä * Table taken from Bspec 12716 82742a0d256SVille Syrjälä * Pipes do have some preferred DBuf slice affinity, 82842a0d256SVille Syrjälä * plus there are some hardcoded requirements on how 82942a0d256SVille Syrjälä * those should be distributed for multipipe scenarios. 83042a0d256SVille Syrjälä * For more DBuf slices algorithm can get even more messy 83142a0d256SVille Syrjälä * and less readable, so decided to use a table almost 83242a0d256SVille Syrjälä * as is from BSpec itself - that way it is at least easier 83342a0d256SVille Syrjälä * to compare, change and check. 83442a0d256SVille Syrjälä */ 83542a0d256SVille Syrjälä static const struct dbuf_slice_conf_entry icl_allowed_dbufs[] = 83642a0d256SVille Syrjälä /* Autogenerated with igt/tools/intel_dbuf_map tool: */ 83742a0d256SVille Syrjälä { 83842a0d256SVille Syrjälä { 83942a0d256SVille Syrjälä .active_pipes = BIT(PIPE_A), 84042a0d256SVille Syrjälä .dbuf_mask = { 84142a0d256SVille Syrjälä [PIPE_A] = BIT(DBUF_S1), 84242a0d256SVille Syrjälä }, 84342a0d256SVille Syrjälä }, 84442a0d256SVille Syrjälä { 84542a0d256SVille Syrjälä .active_pipes = BIT(PIPE_B), 84642a0d256SVille Syrjälä .dbuf_mask = { 84742a0d256SVille Syrjälä [PIPE_B] = BIT(DBUF_S1), 84842a0d256SVille Syrjälä }, 84942a0d256SVille Syrjälä }, 85042a0d256SVille Syrjälä { 85142a0d256SVille Syrjälä .active_pipes = BIT(PIPE_A) | BIT(PIPE_B), 85242a0d256SVille Syrjälä .dbuf_mask = { 85342a0d256SVille Syrjälä [PIPE_A] = BIT(DBUF_S1), 85442a0d256SVille Syrjälä [PIPE_B] = BIT(DBUF_S2), 85542a0d256SVille Syrjälä }, 85642a0d256SVille Syrjälä }, 85742a0d256SVille Syrjälä { 85842a0d256SVille Syrjälä .active_pipes = BIT(PIPE_C), 85942a0d256SVille Syrjälä .dbuf_mask = { 86042a0d256SVille Syrjälä [PIPE_C] = BIT(DBUF_S2), 86142a0d256SVille Syrjälä }, 86242a0d256SVille Syrjälä }, 86342a0d256SVille Syrjälä { 86442a0d256SVille Syrjälä .active_pipes = BIT(PIPE_A) | BIT(PIPE_C), 86542a0d256SVille Syrjälä .dbuf_mask = { 86642a0d256SVille Syrjälä [PIPE_A] = BIT(DBUF_S1), 86742a0d256SVille Syrjälä [PIPE_C] = BIT(DBUF_S2), 86842a0d256SVille Syrjälä }, 86942a0d256SVille Syrjälä }, 87042a0d256SVille Syrjälä { 87142a0d256SVille Syrjälä .active_pipes = BIT(PIPE_B) | BIT(PIPE_C), 87242a0d256SVille Syrjälä .dbuf_mask = { 87342a0d256SVille Syrjälä [PIPE_B] = BIT(DBUF_S1), 87442a0d256SVille Syrjälä [PIPE_C] = BIT(DBUF_S2), 87542a0d256SVille Syrjälä }, 87642a0d256SVille Syrjälä }, 87742a0d256SVille Syrjälä { 87842a0d256SVille Syrjälä .active_pipes = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C), 87942a0d256SVille Syrjälä .dbuf_mask = { 88042a0d256SVille Syrjälä [PIPE_A] = BIT(DBUF_S1), 88142a0d256SVille Syrjälä [PIPE_B] = BIT(DBUF_S1), 88242a0d256SVille Syrjälä [PIPE_C] = BIT(DBUF_S2), 88342a0d256SVille Syrjälä }, 88442a0d256SVille Syrjälä }, 88542a0d256SVille Syrjälä {} 88642a0d256SVille Syrjälä }; 88742a0d256SVille Syrjälä 88842a0d256SVille Syrjälä /* 88942a0d256SVille Syrjälä * Table taken from Bspec 49255 89042a0d256SVille Syrjälä * Pipes do have some preferred DBuf slice affinity, 89142a0d256SVille Syrjälä * plus there are some hardcoded requirements on how 89242a0d256SVille Syrjälä * those should be distributed for multipipe scenarios. 89342a0d256SVille Syrjälä * For more DBuf slices algorithm can get even more messy 89442a0d256SVille Syrjälä * and less readable, so decided to use a table almost 89542a0d256SVille Syrjälä * as is from BSpec itself - that way it is at least easier 89642a0d256SVille Syrjälä * to compare, change and check. 89742a0d256SVille Syrjälä */ 89842a0d256SVille Syrjälä static const struct dbuf_slice_conf_entry tgl_allowed_dbufs[] = 89942a0d256SVille Syrjälä /* Autogenerated with igt/tools/intel_dbuf_map tool: */ 90042a0d256SVille Syrjälä { 90142a0d256SVille Syrjälä { 90242a0d256SVille Syrjälä .active_pipes = BIT(PIPE_A), 90342a0d256SVille Syrjälä .dbuf_mask = { 90442a0d256SVille Syrjälä [PIPE_A] = BIT(DBUF_S1) | BIT(DBUF_S2), 90542a0d256SVille Syrjälä }, 90642a0d256SVille Syrjälä }, 90742a0d256SVille Syrjälä { 90842a0d256SVille Syrjälä .active_pipes = BIT(PIPE_B), 90942a0d256SVille Syrjälä .dbuf_mask = { 91042a0d256SVille Syrjälä [PIPE_B] = BIT(DBUF_S1) | BIT(DBUF_S2), 91142a0d256SVille Syrjälä }, 91242a0d256SVille Syrjälä }, 91342a0d256SVille Syrjälä { 91442a0d256SVille Syrjälä .active_pipes = BIT(PIPE_A) | BIT(PIPE_B), 91542a0d256SVille Syrjälä .dbuf_mask = { 91642a0d256SVille Syrjälä [PIPE_A] = BIT(DBUF_S2), 91742a0d256SVille Syrjälä [PIPE_B] = BIT(DBUF_S1), 91842a0d256SVille Syrjälä }, 91942a0d256SVille Syrjälä }, 92042a0d256SVille Syrjälä { 92142a0d256SVille Syrjälä .active_pipes = BIT(PIPE_C), 92242a0d256SVille Syrjälä .dbuf_mask = { 92342a0d256SVille Syrjälä [PIPE_C] = BIT(DBUF_S2) | BIT(DBUF_S1), 92442a0d256SVille Syrjälä }, 92542a0d256SVille Syrjälä }, 92642a0d256SVille Syrjälä { 92742a0d256SVille Syrjälä .active_pipes = BIT(PIPE_A) | BIT(PIPE_C), 92842a0d256SVille Syrjälä .dbuf_mask = { 92942a0d256SVille Syrjälä [PIPE_A] = BIT(DBUF_S1), 93042a0d256SVille Syrjälä [PIPE_C] = BIT(DBUF_S2), 93142a0d256SVille Syrjälä }, 93242a0d256SVille Syrjälä }, 93342a0d256SVille Syrjälä { 93442a0d256SVille Syrjälä .active_pipes = BIT(PIPE_B) | BIT(PIPE_C), 93542a0d256SVille Syrjälä .dbuf_mask = { 93642a0d256SVille Syrjälä [PIPE_B] = BIT(DBUF_S1), 93742a0d256SVille Syrjälä [PIPE_C] = BIT(DBUF_S2), 93842a0d256SVille Syrjälä }, 93942a0d256SVille Syrjälä }, 94042a0d256SVille Syrjälä { 94142a0d256SVille Syrjälä .active_pipes = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C), 94242a0d256SVille Syrjälä .dbuf_mask = { 94342a0d256SVille Syrjälä [PIPE_A] = BIT(DBUF_S1), 94442a0d256SVille Syrjälä [PIPE_B] = BIT(DBUF_S1), 94542a0d256SVille Syrjälä [PIPE_C] = BIT(DBUF_S2), 94642a0d256SVille Syrjälä }, 94742a0d256SVille Syrjälä }, 94842a0d256SVille Syrjälä { 94942a0d256SVille Syrjälä .active_pipes = BIT(PIPE_D), 95042a0d256SVille Syrjälä .dbuf_mask = { 95142a0d256SVille Syrjälä [PIPE_D] = BIT(DBUF_S2) | BIT(DBUF_S1), 95242a0d256SVille Syrjälä }, 95342a0d256SVille Syrjälä }, 95442a0d256SVille Syrjälä { 95542a0d256SVille Syrjälä .active_pipes = BIT(PIPE_A) | BIT(PIPE_D), 95642a0d256SVille Syrjälä .dbuf_mask = { 95742a0d256SVille Syrjälä [PIPE_A] = 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_B) | BIT(PIPE_D), 96342a0d256SVille Syrjälä .dbuf_mask = { 96442a0d256SVille Syrjälä [PIPE_B] = BIT(DBUF_S1), 96542a0d256SVille Syrjälä [PIPE_D] = BIT(DBUF_S2), 96642a0d256SVille Syrjälä }, 96742a0d256SVille Syrjälä }, 96842a0d256SVille Syrjälä { 96942a0d256SVille Syrjälä .active_pipes = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_D), 97042a0d256SVille Syrjälä .dbuf_mask = { 97142a0d256SVille Syrjälä [PIPE_A] = BIT(DBUF_S1), 97242a0d256SVille Syrjälä [PIPE_B] = BIT(DBUF_S1), 97342a0d256SVille Syrjälä [PIPE_D] = BIT(DBUF_S2), 97442a0d256SVille Syrjälä }, 97542a0d256SVille Syrjälä }, 97642a0d256SVille Syrjälä { 97742a0d256SVille Syrjälä .active_pipes = BIT(PIPE_C) | BIT(PIPE_D), 97842a0d256SVille Syrjälä .dbuf_mask = { 97942a0d256SVille Syrjälä [PIPE_C] = BIT(DBUF_S1), 98042a0d256SVille Syrjälä [PIPE_D] = BIT(DBUF_S2), 98142a0d256SVille Syrjälä }, 98242a0d256SVille Syrjälä }, 98342a0d256SVille Syrjälä { 98442a0d256SVille Syrjälä .active_pipes = BIT(PIPE_A) | BIT(PIPE_C) | BIT(PIPE_D), 98542a0d256SVille Syrjälä .dbuf_mask = { 98642a0d256SVille Syrjälä [PIPE_A] = BIT(DBUF_S1), 98742a0d256SVille Syrjälä [PIPE_C] = BIT(DBUF_S2), 98842a0d256SVille Syrjälä [PIPE_D] = BIT(DBUF_S2), 98942a0d256SVille Syrjälä }, 99042a0d256SVille Syrjälä }, 99142a0d256SVille Syrjälä { 99242a0d256SVille Syrjälä .active_pipes = BIT(PIPE_B) | BIT(PIPE_C) | BIT(PIPE_D), 99342a0d256SVille Syrjälä .dbuf_mask = { 99442a0d256SVille Syrjälä [PIPE_B] = BIT(DBUF_S1), 99542a0d256SVille Syrjälä [PIPE_C] = BIT(DBUF_S2), 99642a0d256SVille Syrjälä [PIPE_D] = BIT(DBUF_S2), 99742a0d256SVille Syrjälä }, 99842a0d256SVille Syrjälä }, 99942a0d256SVille Syrjälä { 100042a0d256SVille Syrjälä .active_pipes = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C) | BIT(PIPE_D), 100142a0d256SVille Syrjälä .dbuf_mask = { 100242a0d256SVille Syrjälä [PIPE_A] = BIT(DBUF_S1), 100342a0d256SVille Syrjälä [PIPE_B] = BIT(DBUF_S1), 100442a0d256SVille Syrjälä [PIPE_C] = BIT(DBUF_S2), 100542a0d256SVille Syrjälä [PIPE_D] = BIT(DBUF_S2), 100642a0d256SVille Syrjälä }, 100742a0d256SVille Syrjälä }, 100842a0d256SVille Syrjälä {} 100942a0d256SVille Syrjälä }; 101042a0d256SVille Syrjälä 101142a0d256SVille Syrjälä static const struct dbuf_slice_conf_entry dg2_allowed_dbufs[] = { 101242a0d256SVille Syrjälä { 101342a0d256SVille Syrjälä .active_pipes = BIT(PIPE_A), 101442a0d256SVille Syrjälä .dbuf_mask = { 101542a0d256SVille Syrjälä [PIPE_A] = BIT(DBUF_S1) | BIT(DBUF_S2), 101642a0d256SVille Syrjälä }, 101742a0d256SVille Syrjälä }, 101842a0d256SVille Syrjälä { 101942a0d256SVille Syrjälä .active_pipes = BIT(PIPE_B), 102042a0d256SVille Syrjälä .dbuf_mask = { 102142a0d256SVille Syrjälä [PIPE_B] = BIT(DBUF_S1) | BIT(DBUF_S2), 102242a0d256SVille Syrjälä }, 102342a0d256SVille Syrjälä }, 102442a0d256SVille Syrjälä { 102542a0d256SVille Syrjälä .active_pipes = BIT(PIPE_A) | BIT(PIPE_B), 102642a0d256SVille Syrjälä .dbuf_mask = { 102742a0d256SVille Syrjälä [PIPE_A] = BIT(DBUF_S1), 102842a0d256SVille Syrjälä [PIPE_B] = BIT(DBUF_S2), 102942a0d256SVille Syrjälä }, 103042a0d256SVille Syrjälä }, 103142a0d256SVille Syrjälä { 103242a0d256SVille Syrjälä .active_pipes = BIT(PIPE_C), 103342a0d256SVille Syrjälä .dbuf_mask = { 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_A) | BIT(PIPE_C), 103942a0d256SVille Syrjälä .dbuf_mask = { 104042a0d256SVille Syrjälä [PIPE_A] = BIT(DBUF_S1) | BIT(DBUF_S2), 104142a0d256SVille Syrjälä [PIPE_C] = BIT(DBUF_S3) | BIT(DBUF_S4), 104242a0d256SVille Syrjälä }, 104342a0d256SVille Syrjälä }, 104442a0d256SVille Syrjälä { 104542a0d256SVille Syrjälä .active_pipes = BIT(PIPE_B) | BIT(PIPE_C), 104642a0d256SVille Syrjälä .dbuf_mask = { 104742a0d256SVille Syrjälä [PIPE_B] = BIT(DBUF_S1) | BIT(DBUF_S2), 104842a0d256SVille Syrjälä [PIPE_C] = BIT(DBUF_S3) | BIT(DBUF_S4), 104942a0d256SVille Syrjälä }, 105042a0d256SVille Syrjälä }, 105142a0d256SVille Syrjälä { 105242a0d256SVille Syrjälä .active_pipes = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C), 105342a0d256SVille Syrjälä .dbuf_mask = { 105442a0d256SVille Syrjälä [PIPE_A] = BIT(DBUF_S1), 105542a0d256SVille Syrjälä [PIPE_B] = BIT(DBUF_S2), 105642a0d256SVille Syrjälä [PIPE_C] = BIT(DBUF_S3) | BIT(DBUF_S4), 105742a0d256SVille Syrjälä }, 105842a0d256SVille Syrjälä }, 105942a0d256SVille Syrjälä { 106042a0d256SVille Syrjälä .active_pipes = BIT(PIPE_D), 106142a0d256SVille Syrjälä .dbuf_mask = { 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_A) | BIT(PIPE_D), 106742a0d256SVille Syrjälä .dbuf_mask = { 106842a0d256SVille Syrjälä [PIPE_A] = BIT(DBUF_S1) | BIT(DBUF_S2), 106942a0d256SVille Syrjälä [PIPE_D] = BIT(DBUF_S3) | BIT(DBUF_S4), 107042a0d256SVille Syrjälä }, 107142a0d256SVille Syrjälä }, 107242a0d256SVille Syrjälä { 107342a0d256SVille Syrjälä .active_pipes = BIT(PIPE_B) | BIT(PIPE_D), 107442a0d256SVille Syrjälä .dbuf_mask = { 107542a0d256SVille Syrjälä [PIPE_B] = BIT(DBUF_S1) | BIT(DBUF_S2), 107642a0d256SVille Syrjälä [PIPE_D] = BIT(DBUF_S3) | BIT(DBUF_S4), 107742a0d256SVille Syrjälä }, 107842a0d256SVille Syrjälä }, 107942a0d256SVille Syrjälä { 108042a0d256SVille Syrjälä .active_pipes = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_D), 108142a0d256SVille Syrjälä .dbuf_mask = { 108242a0d256SVille Syrjälä [PIPE_A] = BIT(DBUF_S1), 108342a0d256SVille Syrjälä [PIPE_B] = BIT(DBUF_S2), 108442a0d256SVille Syrjälä [PIPE_D] = BIT(DBUF_S3) | BIT(DBUF_S4), 108542a0d256SVille Syrjälä }, 108642a0d256SVille Syrjälä }, 108742a0d256SVille Syrjälä { 108842a0d256SVille Syrjälä .active_pipes = BIT(PIPE_C) | BIT(PIPE_D), 108942a0d256SVille Syrjälä .dbuf_mask = { 109042a0d256SVille Syrjälä [PIPE_C] = BIT(DBUF_S3), 109142a0d256SVille Syrjälä [PIPE_D] = BIT(DBUF_S4), 109242a0d256SVille Syrjälä }, 109342a0d256SVille Syrjälä }, 109442a0d256SVille Syrjälä { 109542a0d256SVille Syrjälä .active_pipes = BIT(PIPE_A) | BIT(PIPE_C) | BIT(PIPE_D), 109642a0d256SVille Syrjälä .dbuf_mask = { 109742a0d256SVille Syrjälä [PIPE_A] = BIT(DBUF_S1) | BIT(DBUF_S2), 109842a0d256SVille Syrjälä [PIPE_C] = BIT(DBUF_S3), 109942a0d256SVille Syrjälä [PIPE_D] = BIT(DBUF_S4), 110042a0d256SVille Syrjälä }, 110142a0d256SVille Syrjälä }, 110242a0d256SVille Syrjälä { 110342a0d256SVille Syrjälä .active_pipes = BIT(PIPE_B) | BIT(PIPE_C) | BIT(PIPE_D), 110442a0d256SVille Syrjälä .dbuf_mask = { 110542a0d256SVille Syrjälä [PIPE_B] = BIT(DBUF_S1) | BIT(DBUF_S2), 110642a0d256SVille Syrjälä [PIPE_C] = BIT(DBUF_S3), 110742a0d256SVille Syrjälä [PIPE_D] = BIT(DBUF_S4), 110842a0d256SVille Syrjälä }, 110942a0d256SVille Syrjälä }, 111042a0d256SVille Syrjälä { 111142a0d256SVille Syrjälä .active_pipes = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C) | BIT(PIPE_D), 111242a0d256SVille Syrjälä .dbuf_mask = { 111342a0d256SVille Syrjälä [PIPE_A] = BIT(DBUF_S1), 111442a0d256SVille Syrjälä [PIPE_B] = BIT(DBUF_S2), 111542a0d256SVille Syrjälä [PIPE_C] = BIT(DBUF_S3), 111642a0d256SVille Syrjälä [PIPE_D] = BIT(DBUF_S4), 111742a0d256SVille Syrjälä }, 111842a0d256SVille Syrjälä }, 111942a0d256SVille Syrjälä {} 112042a0d256SVille Syrjälä }; 112142a0d256SVille Syrjälä 112242a0d256SVille Syrjälä static const struct dbuf_slice_conf_entry adlp_allowed_dbufs[] = { 112342a0d256SVille Syrjälä /* 112442a0d256SVille Syrjälä * Keep the join_mbus cases first so check_mbus_joined() 112542a0d256SVille Syrjälä * will prefer them over the !join_mbus cases. 112642a0d256SVille Syrjälä */ 112742a0d256SVille Syrjälä { 112842a0d256SVille Syrjälä .active_pipes = BIT(PIPE_A), 112942a0d256SVille Syrjälä .dbuf_mask = { 113042a0d256SVille Syrjälä [PIPE_A] = BIT(DBUF_S1) | BIT(DBUF_S2) | BIT(DBUF_S3) | BIT(DBUF_S4), 113142a0d256SVille Syrjälä }, 113242a0d256SVille Syrjälä .join_mbus = true, 113342a0d256SVille Syrjälä }, 113442a0d256SVille Syrjälä { 113542a0d256SVille Syrjälä .active_pipes = BIT(PIPE_B), 113642a0d256SVille Syrjälä .dbuf_mask = { 113742a0d256SVille Syrjälä [PIPE_B] = BIT(DBUF_S1) | BIT(DBUF_S2) | BIT(DBUF_S3) | BIT(DBUF_S4), 113842a0d256SVille Syrjälä }, 113942a0d256SVille Syrjälä .join_mbus = true, 114042a0d256SVille Syrjälä }, 114142a0d256SVille Syrjälä { 114242a0d256SVille Syrjälä .active_pipes = BIT(PIPE_A), 114342a0d256SVille Syrjälä .dbuf_mask = { 114442a0d256SVille Syrjälä [PIPE_A] = BIT(DBUF_S1) | BIT(DBUF_S2), 114542a0d256SVille Syrjälä }, 114642a0d256SVille Syrjälä .join_mbus = false, 114742a0d256SVille Syrjälä }, 114842a0d256SVille Syrjälä { 114942a0d256SVille Syrjälä .active_pipes = BIT(PIPE_B), 115042a0d256SVille Syrjälä .dbuf_mask = { 115142a0d256SVille Syrjälä [PIPE_B] = BIT(DBUF_S3) | BIT(DBUF_S4), 115242a0d256SVille Syrjälä }, 115342a0d256SVille Syrjälä .join_mbus = false, 115442a0d256SVille Syrjälä }, 115542a0d256SVille Syrjälä { 115642a0d256SVille Syrjälä .active_pipes = BIT(PIPE_A) | BIT(PIPE_B), 115742a0d256SVille Syrjälä .dbuf_mask = { 115842a0d256SVille Syrjälä [PIPE_A] = BIT(DBUF_S1) | BIT(DBUF_S2), 115942a0d256SVille Syrjälä [PIPE_B] = BIT(DBUF_S3) | BIT(DBUF_S4), 116042a0d256SVille Syrjälä }, 116142a0d256SVille Syrjälä }, 116242a0d256SVille Syrjälä { 116342a0d256SVille Syrjälä .active_pipes = BIT(PIPE_C), 116442a0d256SVille Syrjälä .dbuf_mask = { 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_A) | BIT(PIPE_C), 117042a0d256SVille Syrjälä .dbuf_mask = { 117142a0d256SVille Syrjälä [PIPE_A] = BIT(DBUF_S1) | BIT(DBUF_S2), 117242a0d256SVille Syrjälä [PIPE_C] = BIT(DBUF_S3) | BIT(DBUF_S4), 117342a0d256SVille Syrjälä }, 117442a0d256SVille Syrjälä }, 117542a0d256SVille Syrjälä { 117642a0d256SVille Syrjälä .active_pipes = BIT(PIPE_B) | BIT(PIPE_C), 117742a0d256SVille Syrjälä .dbuf_mask = { 117842a0d256SVille Syrjälä [PIPE_B] = BIT(DBUF_S3) | BIT(DBUF_S4), 117942a0d256SVille Syrjälä [PIPE_C] = BIT(DBUF_S3) | BIT(DBUF_S4), 118042a0d256SVille Syrjälä }, 118142a0d256SVille Syrjälä }, 118242a0d256SVille Syrjälä { 118342a0d256SVille Syrjälä .active_pipes = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C), 118442a0d256SVille Syrjälä .dbuf_mask = { 118542a0d256SVille Syrjälä [PIPE_A] = BIT(DBUF_S1) | BIT(DBUF_S2), 118642a0d256SVille Syrjälä [PIPE_B] = BIT(DBUF_S3) | BIT(DBUF_S4), 118742a0d256SVille Syrjälä [PIPE_C] = BIT(DBUF_S3) | BIT(DBUF_S4), 118842a0d256SVille Syrjälä }, 118942a0d256SVille Syrjälä }, 119042a0d256SVille Syrjälä { 119142a0d256SVille Syrjälä .active_pipes = BIT(PIPE_D), 119242a0d256SVille Syrjälä .dbuf_mask = { 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_A) | BIT(PIPE_D), 119842a0d256SVille Syrjälä .dbuf_mask = { 119942a0d256SVille Syrjälä [PIPE_A] = BIT(DBUF_S1) | BIT(DBUF_S2), 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_B) | BIT(PIPE_D), 120542a0d256SVille Syrjälä .dbuf_mask = { 120642a0d256SVille Syrjälä [PIPE_B] = BIT(DBUF_S3) | BIT(DBUF_S4), 120742a0d256SVille Syrjälä [PIPE_D] = BIT(DBUF_S1) | BIT(DBUF_S2), 120842a0d256SVille Syrjälä }, 120942a0d256SVille Syrjälä }, 121042a0d256SVille Syrjälä { 121142a0d256SVille Syrjälä .active_pipes = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_D), 121242a0d256SVille Syrjälä .dbuf_mask = { 121342a0d256SVille Syrjälä [PIPE_A] = BIT(DBUF_S1) | BIT(DBUF_S2), 121442a0d256SVille Syrjälä [PIPE_B] = BIT(DBUF_S3) | BIT(DBUF_S4), 121542a0d256SVille Syrjälä [PIPE_D] = BIT(DBUF_S1) | BIT(DBUF_S2), 121642a0d256SVille Syrjälä }, 121742a0d256SVille Syrjälä }, 121842a0d256SVille Syrjälä { 121942a0d256SVille Syrjälä .active_pipes = BIT(PIPE_C) | BIT(PIPE_D), 122042a0d256SVille Syrjälä .dbuf_mask = { 122142a0d256SVille Syrjälä [PIPE_C] = BIT(DBUF_S3) | BIT(DBUF_S4), 122242a0d256SVille Syrjälä [PIPE_D] = BIT(DBUF_S1) | BIT(DBUF_S2), 122342a0d256SVille Syrjälä }, 122442a0d256SVille Syrjälä }, 122542a0d256SVille Syrjälä { 122642a0d256SVille Syrjälä .active_pipes = BIT(PIPE_A) | BIT(PIPE_C) | BIT(PIPE_D), 122742a0d256SVille Syrjälä .dbuf_mask = { 122842a0d256SVille Syrjälä [PIPE_A] = BIT(DBUF_S1) | BIT(DBUF_S2), 122942a0d256SVille Syrjälä [PIPE_C] = BIT(DBUF_S3) | BIT(DBUF_S4), 123042a0d256SVille Syrjälä [PIPE_D] = BIT(DBUF_S1) | BIT(DBUF_S2), 123142a0d256SVille Syrjälä }, 123242a0d256SVille Syrjälä }, 123342a0d256SVille Syrjälä { 123442a0d256SVille Syrjälä .active_pipes = BIT(PIPE_B) | BIT(PIPE_C) | BIT(PIPE_D), 123542a0d256SVille Syrjälä .dbuf_mask = { 123642a0d256SVille Syrjälä [PIPE_B] = BIT(DBUF_S3) | BIT(DBUF_S4), 123742a0d256SVille Syrjälä [PIPE_C] = BIT(DBUF_S3) | BIT(DBUF_S4), 123842a0d256SVille Syrjälä [PIPE_D] = BIT(DBUF_S1) | BIT(DBUF_S2), 123942a0d256SVille Syrjälä }, 124042a0d256SVille Syrjälä }, 124142a0d256SVille Syrjälä { 124242a0d256SVille Syrjälä .active_pipes = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C) | BIT(PIPE_D), 124342a0d256SVille Syrjälä .dbuf_mask = { 124442a0d256SVille Syrjälä [PIPE_A] = BIT(DBUF_S1) | BIT(DBUF_S2), 124542a0d256SVille Syrjälä [PIPE_B] = BIT(DBUF_S3) | BIT(DBUF_S4), 124642a0d256SVille Syrjälä [PIPE_C] = BIT(DBUF_S3) | BIT(DBUF_S4), 124742a0d256SVille Syrjälä [PIPE_D] = BIT(DBUF_S1) | BIT(DBUF_S2), 124842a0d256SVille Syrjälä }, 124942a0d256SVille Syrjälä }, 125042a0d256SVille Syrjälä {} 125142a0d256SVille Syrjälä 125242a0d256SVille Syrjälä }; 125342a0d256SVille Syrjälä 125442a0d256SVille Syrjälä static bool check_mbus_joined(u8 active_pipes, 125542a0d256SVille Syrjälä const struct dbuf_slice_conf_entry *dbuf_slices) 125642a0d256SVille Syrjälä { 125742a0d256SVille Syrjälä int i; 125842a0d256SVille Syrjälä 125942a0d256SVille Syrjälä for (i = 0; dbuf_slices[i].active_pipes != 0; i++) { 126042a0d256SVille Syrjälä if (dbuf_slices[i].active_pipes == active_pipes) 126142a0d256SVille Syrjälä return dbuf_slices[i].join_mbus; 126242a0d256SVille Syrjälä } 126342a0d256SVille Syrjälä return false; 126442a0d256SVille Syrjälä } 126542a0d256SVille Syrjälä 126642a0d256SVille Syrjälä static bool adlp_check_mbus_joined(u8 active_pipes) 126742a0d256SVille Syrjälä { 126842a0d256SVille Syrjälä return check_mbus_joined(active_pipes, adlp_allowed_dbufs); 126942a0d256SVille Syrjälä } 127042a0d256SVille Syrjälä 127142a0d256SVille Syrjälä static u8 compute_dbuf_slices(enum pipe pipe, u8 active_pipes, bool join_mbus, 127242a0d256SVille Syrjälä const struct dbuf_slice_conf_entry *dbuf_slices) 127342a0d256SVille Syrjälä { 127442a0d256SVille Syrjälä int i; 127542a0d256SVille Syrjälä 127642a0d256SVille Syrjälä for (i = 0; dbuf_slices[i].active_pipes != 0; i++) { 127742a0d256SVille Syrjälä if (dbuf_slices[i].active_pipes == active_pipes && 127842a0d256SVille Syrjälä dbuf_slices[i].join_mbus == join_mbus) 127942a0d256SVille Syrjälä return dbuf_slices[i].dbuf_mask[pipe]; 128042a0d256SVille Syrjälä } 128142a0d256SVille Syrjälä return 0; 128242a0d256SVille Syrjälä } 128342a0d256SVille Syrjälä 128442a0d256SVille Syrjälä /* 128542a0d256SVille Syrjälä * This function finds an entry with same enabled pipe configuration and 128642a0d256SVille Syrjälä * returns correspondent DBuf slice mask as stated in BSpec for particular 128742a0d256SVille Syrjälä * platform. 128842a0d256SVille Syrjälä */ 128942a0d256SVille Syrjälä static u8 icl_compute_dbuf_slices(enum pipe pipe, u8 active_pipes, bool join_mbus) 129042a0d256SVille Syrjälä { 129142a0d256SVille Syrjälä /* 129242a0d256SVille Syrjälä * FIXME: For ICL this is still a bit unclear as prev BSpec revision 129342a0d256SVille Syrjälä * required calculating "pipe ratio" in order to determine 129442a0d256SVille Syrjälä * if one or two slices can be used for single pipe configurations 129542a0d256SVille Syrjälä * as additional constraint to the existing table. 129642a0d256SVille Syrjälä * However based on recent info, it should be not "pipe ratio" 129742a0d256SVille Syrjälä * but rather ratio between pixel_rate and cdclk with additional 129842a0d256SVille Syrjälä * constants, so for now we are using only table until this is 129942a0d256SVille Syrjälä * clarified. Also this is the reason why crtc_state param is 130042a0d256SVille Syrjälä * still here - we will need it once those additional constraints 130142a0d256SVille Syrjälä * pop up. 130242a0d256SVille Syrjälä */ 130342a0d256SVille Syrjälä return compute_dbuf_slices(pipe, active_pipes, join_mbus, 130442a0d256SVille Syrjälä icl_allowed_dbufs); 130542a0d256SVille Syrjälä } 130642a0d256SVille Syrjälä 130742a0d256SVille Syrjälä static u8 tgl_compute_dbuf_slices(enum pipe pipe, u8 active_pipes, bool join_mbus) 130842a0d256SVille Syrjälä { 130942a0d256SVille Syrjälä return compute_dbuf_slices(pipe, active_pipes, join_mbus, 131042a0d256SVille Syrjälä tgl_allowed_dbufs); 131142a0d256SVille Syrjälä } 131242a0d256SVille Syrjälä 131342a0d256SVille Syrjälä static u8 adlp_compute_dbuf_slices(enum pipe pipe, u8 active_pipes, bool join_mbus) 131442a0d256SVille Syrjälä { 131542a0d256SVille Syrjälä return compute_dbuf_slices(pipe, active_pipes, join_mbus, 131642a0d256SVille Syrjälä adlp_allowed_dbufs); 131742a0d256SVille Syrjälä } 131842a0d256SVille Syrjälä 131942a0d256SVille Syrjälä static u8 dg2_compute_dbuf_slices(enum pipe pipe, u8 active_pipes, bool join_mbus) 132042a0d256SVille Syrjälä { 132142a0d256SVille Syrjälä return compute_dbuf_slices(pipe, active_pipes, join_mbus, 132242a0d256SVille Syrjälä dg2_allowed_dbufs); 132342a0d256SVille Syrjälä } 132442a0d256SVille Syrjälä 132542a0d256SVille Syrjälä static u8 skl_compute_dbuf_slices(struct intel_crtc *crtc, u8 active_pipes, bool join_mbus) 132642a0d256SVille Syrjälä { 132742a0d256SVille Syrjälä struct drm_i915_private *i915 = to_i915(crtc->base.dev); 132842a0d256SVille Syrjälä enum pipe pipe = crtc->pipe; 132942a0d256SVille Syrjälä 133042a0d256SVille Syrjälä if (IS_DG2(i915)) 133142a0d256SVille Syrjälä return dg2_compute_dbuf_slices(pipe, active_pipes, join_mbus); 133242a0d256SVille Syrjälä else if (DISPLAY_VER(i915) >= 13) 133342a0d256SVille Syrjälä return adlp_compute_dbuf_slices(pipe, active_pipes, join_mbus); 133442a0d256SVille Syrjälä else if (DISPLAY_VER(i915) == 12) 133542a0d256SVille Syrjälä return tgl_compute_dbuf_slices(pipe, active_pipes, join_mbus); 133642a0d256SVille Syrjälä else if (DISPLAY_VER(i915) == 11) 133742a0d256SVille Syrjälä return icl_compute_dbuf_slices(pipe, active_pipes, join_mbus); 133842a0d256SVille Syrjälä /* 133942a0d256SVille Syrjälä * For anything else just return one slice yet. 134042a0d256SVille Syrjälä * Should be extended for other platforms. 134142a0d256SVille Syrjälä */ 134242a0d256SVille Syrjälä return active_pipes & BIT(pipe) ? BIT(DBUF_S1) : 0; 134342a0d256SVille Syrjälä } 134442a0d256SVille Syrjälä 134542a0d256SVille Syrjälä static bool 134642a0d256SVille Syrjälä use_minimal_wm0_only(const struct intel_crtc_state *crtc_state, 134742a0d256SVille Syrjälä struct intel_plane *plane) 134842a0d256SVille Syrjälä { 134942a0d256SVille Syrjälä struct drm_i915_private *i915 = to_i915(plane->base.dev); 135042a0d256SVille Syrjälä 135142a0d256SVille Syrjälä return DISPLAY_VER(i915) >= 13 && 135242a0d256SVille Syrjälä crtc_state->uapi.async_flip && 135342a0d256SVille Syrjälä plane->async_flip; 135442a0d256SVille Syrjälä } 135542a0d256SVille Syrjälä 135642a0d256SVille Syrjälä static u64 135742a0d256SVille Syrjälä skl_total_relative_data_rate(const struct intel_crtc_state *crtc_state) 135842a0d256SVille Syrjälä { 135942a0d256SVille Syrjälä struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 136042a0d256SVille Syrjälä struct drm_i915_private *i915 = to_i915(crtc->base.dev); 136142a0d256SVille Syrjälä enum plane_id plane_id; 136242a0d256SVille Syrjälä u64 data_rate = 0; 136342a0d256SVille Syrjälä 136442a0d256SVille Syrjälä for_each_plane_id_on_crtc(crtc, plane_id) { 136542a0d256SVille Syrjälä if (plane_id == PLANE_CURSOR) 136642a0d256SVille Syrjälä continue; 136742a0d256SVille Syrjälä 136842a0d256SVille Syrjälä data_rate += crtc_state->rel_data_rate[plane_id]; 136942a0d256SVille Syrjälä 137042a0d256SVille Syrjälä if (DISPLAY_VER(i915) < 11) 137142a0d256SVille Syrjälä data_rate += crtc_state->rel_data_rate_y[plane_id]; 137242a0d256SVille Syrjälä } 137342a0d256SVille Syrjälä 137442a0d256SVille Syrjälä return data_rate; 137542a0d256SVille Syrjälä } 137642a0d256SVille Syrjälä 137742a0d256SVille Syrjälä static const struct skl_wm_level * 137842a0d256SVille Syrjälä skl_plane_wm_level(const struct skl_pipe_wm *pipe_wm, 137942a0d256SVille Syrjälä enum plane_id plane_id, 138042a0d256SVille Syrjälä int level) 138142a0d256SVille Syrjälä { 138242a0d256SVille Syrjälä const struct skl_plane_wm *wm = &pipe_wm->planes[plane_id]; 138342a0d256SVille Syrjälä 138442a0d256SVille Syrjälä if (level == 0 && pipe_wm->use_sagv_wm) 138542a0d256SVille Syrjälä return &wm->sagv.wm0; 138642a0d256SVille Syrjälä 138742a0d256SVille Syrjälä return &wm->wm[level]; 138842a0d256SVille Syrjälä } 138942a0d256SVille Syrjälä 139042a0d256SVille Syrjälä static const struct skl_wm_level * 139142a0d256SVille Syrjälä skl_plane_trans_wm(const struct skl_pipe_wm *pipe_wm, 139242a0d256SVille Syrjälä enum plane_id plane_id) 139342a0d256SVille Syrjälä { 139442a0d256SVille Syrjälä const struct skl_plane_wm *wm = &pipe_wm->planes[plane_id]; 139542a0d256SVille Syrjälä 139642a0d256SVille Syrjälä if (pipe_wm->use_sagv_wm) 139742a0d256SVille Syrjälä return &wm->sagv.trans_wm; 139842a0d256SVille Syrjälä 139942a0d256SVille Syrjälä return &wm->trans_wm; 140042a0d256SVille Syrjälä } 140142a0d256SVille Syrjälä 140242a0d256SVille Syrjälä /* 140342a0d256SVille Syrjälä * We only disable the watermarks for each plane if 140442a0d256SVille Syrjälä * they exceed the ddb allocation of said plane. This 140542a0d256SVille Syrjälä * is done so that we don't end up touching cursor 140642a0d256SVille Syrjälä * watermarks needlessly when some other plane reduces 140742a0d256SVille Syrjälä * our max possible watermark level. 140842a0d256SVille Syrjälä * 140942a0d256SVille Syrjälä * Bspec has this to say about the PLANE_WM enable bit: 141042a0d256SVille Syrjälä * "All the watermarks at this level for all enabled 141142a0d256SVille Syrjälä * planes must be enabled before the level will be used." 141242a0d256SVille Syrjälä * So this is actually safe to do. 141342a0d256SVille Syrjälä */ 141442a0d256SVille Syrjälä static void 141542a0d256SVille Syrjälä skl_check_wm_level(struct skl_wm_level *wm, const struct skl_ddb_entry *ddb) 141642a0d256SVille Syrjälä { 141742a0d256SVille Syrjälä if (wm->min_ddb_alloc > skl_ddb_entry_size(ddb)) 141842a0d256SVille Syrjälä memset(wm, 0, sizeof(*wm)); 141942a0d256SVille Syrjälä } 142042a0d256SVille Syrjälä 142142a0d256SVille Syrjälä static void 142242a0d256SVille Syrjälä skl_check_nv12_wm_level(struct skl_wm_level *wm, struct skl_wm_level *uv_wm, 142342a0d256SVille Syrjälä const struct skl_ddb_entry *ddb_y, const struct skl_ddb_entry *ddb) 142442a0d256SVille Syrjälä { 142542a0d256SVille Syrjälä if (wm->min_ddb_alloc > skl_ddb_entry_size(ddb_y) || 142642a0d256SVille Syrjälä uv_wm->min_ddb_alloc > skl_ddb_entry_size(ddb)) { 142742a0d256SVille Syrjälä memset(wm, 0, sizeof(*wm)); 142842a0d256SVille Syrjälä memset(uv_wm, 0, sizeof(*uv_wm)); 142942a0d256SVille Syrjälä } 143042a0d256SVille Syrjälä } 143142a0d256SVille Syrjälä 14329fcbae04SStanislav Lisovskiy static bool skl_need_wm_copy_wa(struct drm_i915_private *i915, int level, 14339fcbae04SStanislav Lisovskiy const struct skl_plane_wm *wm) 143442a0d256SVille Syrjälä { 143542a0d256SVille Syrjälä /* 143642a0d256SVille Syrjälä * Wa_1408961008:icl, ehl 143742a0d256SVille Syrjälä * Wa_14012656716:tgl, adl 14389fcbae04SStanislav Lisovskiy * Wa_14017887344:icl 14399fcbae04SStanislav Lisovskiy * Wa_14017868169:adl, tgl 14409fcbae04SStanislav Lisovskiy * Due to some power saving optimizations, different subsystems 14419fcbae04SStanislav Lisovskiy * like PSR, might still use even disabled wm level registers, 14429fcbae04SStanislav Lisovskiy * for "reference", so lets keep at least the values sane. 14439fcbae04SStanislav Lisovskiy * Considering amount of WA requiring us to do similar things, was 14449fcbae04SStanislav Lisovskiy * decided to simply do it for all of the platforms, as those wm 14459fcbae04SStanislav Lisovskiy * levels are disabled, this isn't going to do harm anyway. 144642a0d256SVille Syrjälä */ 14479fcbae04SStanislav Lisovskiy return level > 0 && !wm->wm[level].enable; 144842a0d256SVille Syrjälä } 144942a0d256SVille Syrjälä 145042a0d256SVille Syrjälä struct skl_plane_ddb_iter { 145142a0d256SVille Syrjälä u64 data_rate; 145242a0d256SVille Syrjälä u16 start, size; 145342a0d256SVille Syrjälä }; 145442a0d256SVille Syrjälä 145542a0d256SVille Syrjälä static void 145642a0d256SVille Syrjälä skl_allocate_plane_ddb(struct skl_plane_ddb_iter *iter, 145742a0d256SVille Syrjälä struct skl_ddb_entry *ddb, 145842a0d256SVille Syrjälä const struct skl_wm_level *wm, 145942a0d256SVille Syrjälä u64 data_rate) 146042a0d256SVille Syrjälä { 146142a0d256SVille Syrjälä u16 size, extra = 0; 146242a0d256SVille Syrjälä 146342a0d256SVille Syrjälä if (data_rate) { 146442a0d256SVille Syrjälä extra = min_t(u16, iter->size, 146542a0d256SVille Syrjälä DIV64_U64_ROUND_UP(iter->size * data_rate, 146642a0d256SVille Syrjälä iter->data_rate)); 146742a0d256SVille Syrjälä iter->size -= extra; 146842a0d256SVille Syrjälä iter->data_rate -= data_rate; 146942a0d256SVille Syrjälä } 147042a0d256SVille Syrjälä 147142a0d256SVille Syrjälä /* 147242a0d256SVille Syrjälä * Keep ddb entry of all disabled planes explicitly zeroed 147342a0d256SVille Syrjälä * to avoid skl_ddb_add_affected_planes() adding them to 147442a0d256SVille Syrjälä * the state when other planes change their allocations. 147542a0d256SVille Syrjälä */ 147642a0d256SVille Syrjälä size = wm->min_ddb_alloc + extra; 147742a0d256SVille Syrjälä if (size) 147842a0d256SVille Syrjälä iter->start = skl_ddb_entry_init(ddb, iter->start, 147942a0d256SVille Syrjälä iter->start + size); 148042a0d256SVille Syrjälä } 148142a0d256SVille Syrjälä 148242a0d256SVille Syrjälä static int 148342a0d256SVille Syrjälä skl_crtc_allocate_plane_ddb(struct intel_atomic_state *state, 148442a0d256SVille Syrjälä struct intel_crtc *crtc) 148542a0d256SVille Syrjälä { 148642a0d256SVille Syrjälä struct drm_i915_private *i915 = to_i915(crtc->base.dev); 148742a0d256SVille Syrjälä struct intel_crtc_state *crtc_state = 148842a0d256SVille Syrjälä intel_atomic_get_new_crtc_state(state, crtc); 148942a0d256SVille Syrjälä const struct intel_dbuf_state *dbuf_state = 149042a0d256SVille Syrjälä intel_atomic_get_new_dbuf_state(state); 149142a0d256SVille Syrjälä const struct skl_ddb_entry *alloc = &dbuf_state->ddb[crtc->pipe]; 149242a0d256SVille Syrjälä int num_active = hweight8(dbuf_state->active_pipes); 149342a0d256SVille Syrjälä struct skl_plane_ddb_iter iter; 149442a0d256SVille Syrjälä enum plane_id plane_id; 149542a0d256SVille Syrjälä u16 cursor_size; 149642a0d256SVille Syrjälä u32 blocks; 149742a0d256SVille Syrjälä int level; 149842a0d256SVille Syrjälä 149942a0d256SVille Syrjälä /* Clear the partitioning for disabled planes. */ 150042a0d256SVille Syrjälä memset(crtc_state->wm.skl.plane_ddb, 0, sizeof(crtc_state->wm.skl.plane_ddb)); 150142a0d256SVille Syrjälä memset(crtc_state->wm.skl.plane_ddb_y, 0, sizeof(crtc_state->wm.skl.plane_ddb_y)); 150242a0d256SVille Syrjälä 150342a0d256SVille Syrjälä if (!crtc_state->hw.active) 150442a0d256SVille Syrjälä return 0; 150542a0d256SVille Syrjälä 150642a0d256SVille Syrjälä iter.start = alloc->start; 150742a0d256SVille Syrjälä iter.size = skl_ddb_entry_size(alloc); 150842a0d256SVille Syrjälä if (iter.size == 0) 150942a0d256SVille Syrjälä return 0; 151042a0d256SVille Syrjälä 151142a0d256SVille Syrjälä /* Allocate fixed number of blocks for cursor. */ 151242a0d256SVille Syrjälä cursor_size = skl_cursor_allocation(crtc_state, num_active); 151342a0d256SVille Syrjälä iter.size -= cursor_size; 151442a0d256SVille Syrjälä skl_ddb_entry_init(&crtc_state->wm.skl.plane_ddb[PLANE_CURSOR], 151542a0d256SVille Syrjälä alloc->end - cursor_size, alloc->end); 151642a0d256SVille Syrjälä 151742a0d256SVille Syrjälä iter.data_rate = skl_total_relative_data_rate(crtc_state); 151842a0d256SVille Syrjälä 151942a0d256SVille Syrjälä /* 152042a0d256SVille Syrjälä * Find the highest watermark level for which we can satisfy the block 152142a0d256SVille Syrjälä * requirement of active planes. 152242a0d256SVille Syrjälä */ 15237ee6f99dSVille Syrjälä for (level = i915->display.wm.num_levels - 1; level >= 0; level--) { 152442a0d256SVille Syrjälä blocks = 0; 152542a0d256SVille Syrjälä for_each_plane_id_on_crtc(crtc, plane_id) { 152642a0d256SVille Syrjälä const struct skl_plane_wm *wm = 152742a0d256SVille Syrjälä &crtc_state->wm.skl.optimal.planes[plane_id]; 152842a0d256SVille Syrjälä 152942a0d256SVille Syrjälä if (plane_id == PLANE_CURSOR) { 153042a0d256SVille Syrjälä const struct skl_ddb_entry *ddb = 153142a0d256SVille Syrjälä &crtc_state->wm.skl.plane_ddb[plane_id]; 153242a0d256SVille Syrjälä 153342a0d256SVille Syrjälä if (wm->wm[level].min_ddb_alloc > skl_ddb_entry_size(ddb)) { 153442a0d256SVille Syrjälä drm_WARN_ON(&i915->drm, 153542a0d256SVille Syrjälä wm->wm[level].min_ddb_alloc != U16_MAX); 153642a0d256SVille Syrjälä blocks = U32_MAX; 153742a0d256SVille Syrjälä break; 153842a0d256SVille Syrjälä } 153942a0d256SVille Syrjälä continue; 154042a0d256SVille Syrjälä } 154142a0d256SVille Syrjälä 154242a0d256SVille Syrjälä blocks += wm->wm[level].min_ddb_alloc; 154342a0d256SVille Syrjälä blocks += wm->uv_wm[level].min_ddb_alloc; 154442a0d256SVille Syrjälä } 154542a0d256SVille Syrjälä 154642a0d256SVille Syrjälä if (blocks <= iter.size) { 154742a0d256SVille Syrjälä iter.size -= blocks; 154842a0d256SVille Syrjälä break; 154942a0d256SVille Syrjälä } 155042a0d256SVille Syrjälä } 155142a0d256SVille Syrjälä 155242a0d256SVille Syrjälä if (level < 0) { 155342a0d256SVille Syrjälä drm_dbg_kms(&i915->drm, 155442a0d256SVille Syrjälä "Requested display configuration exceeds system DDB limitations"); 155542a0d256SVille Syrjälä drm_dbg_kms(&i915->drm, "minimum required %d/%d\n", 155642a0d256SVille Syrjälä blocks, iter.size); 155742a0d256SVille Syrjälä return -EINVAL; 155842a0d256SVille Syrjälä } 155942a0d256SVille Syrjälä 156042a0d256SVille Syrjälä /* avoid the WARN later when we don't allocate any extra DDB */ 156142a0d256SVille Syrjälä if (iter.data_rate == 0) 156242a0d256SVille Syrjälä iter.size = 0; 156342a0d256SVille Syrjälä 156442a0d256SVille Syrjälä /* 156542a0d256SVille Syrjälä * Grant each plane the blocks it requires at the highest achievable 156642a0d256SVille Syrjälä * watermark level, plus an extra share of the leftover blocks 156742a0d256SVille Syrjälä * proportional to its relative data rate. 156842a0d256SVille Syrjälä */ 156942a0d256SVille Syrjälä for_each_plane_id_on_crtc(crtc, plane_id) { 157042a0d256SVille Syrjälä struct skl_ddb_entry *ddb = 157142a0d256SVille Syrjälä &crtc_state->wm.skl.plane_ddb[plane_id]; 157242a0d256SVille Syrjälä struct skl_ddb_entry *ddb_y = 157342a0d256SVille Syrjälä &crtc_state->wm.skl.plane_ddb_y[plane_id]; 157442a0d256SVille Syrjälä const struct skl_plane_wm *wm = 157542a0d256SVille Syrjälä &crtc_state->wm.skl.optimal.planes[plane_id]; 157642a0d256SVille Syrjälä 157742a0d256SVille Syrjälä if (plane_id == PLANE_CURSOR) 157842a0d256SVille Syrjälä continue; 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_allocate_plane_ddb(&iter, ddb_y, &wm->wm[level], 158342a0d256SVille Syrjälä crtc_state->rel_data_rate_y[plane_id]); 158442a0d256SVille Syrjälä skl_allocate_plane_ddb(&iter, ddb, &wm->uv_wm[level], 158542a0d256SVille Syrjälä crtc_state->rel_data_rate[plane_id]); 158642a0d256SVille Syrjälä } else { 158742a0d256SVille Syrjälä skl_allocate_plane_ddb(&iter, ddb, &wm->wm[level], 158842a0d256SVille Syrjälä crtc_state->rel_data_rate[plane_id]); 158942a0d256SVille Syrjälä } 159042a0d256SVille Syrjälä } 159142a0d256SVille Syrjälä drm_WARN_ON(&i915->drm, iter.size != 0 || iter.data_rate != 0); 159242a0d256SVille Syrjälä 159342a0d256SVille Syrjälä /* 159442a0d256SVille Syrjälä * When we calculated watermark values we didn't know how high 159542a0d256SVille Syrjälä * of a level we'd actually be able to hit, so we just marked 159642a0d256SVille Syrjälä * all levels as "enabled." Go back now and disable the ones 159742a0d256SVille Syrjälä * that aren't actually possible. 159842a0d256SVille Syrjälä */ 15997ee6f99dSVille Syrjälä for (level++; level < i915->display.wm.num_levels; level++) { 160042a0d256SVille Syrjälä for_each_plane_id_on_crtc(crtc, plane_id) { 160142a0d256SVille Syrjälä const struct skl_ddb_entry *ddb = 160242a0d256SVille Syrjälä &crtc_state->wm.skl.plane_ddb[plane_id]; 160342a0d256SVille Syrjälä const struct skl_ddb_entry *ddb_y = 160442a0d256SVille Syrjälä &crtc_state->wm.skl.plane_ddb_y[plane_id]; 160542a0d256SVille Syrjälä struct skl_plane_wm *wm = 160642a0d256SVille Syrjälä &crtc_state->wm.skl.optimal.planes[plane_id]; 160742a0d256SVille Syrjälä 160842a0d256SVille Syrjälä if (DISPLAY_VER(i915) < 11 && 160942a0d256SVille Syrjälä crtc_state->nv12_planes & BIT(plane_id)) 161042a0d256SVille Syrjälä skl_check_nv12_wm_level(&wm->wm[level], 161142a0d256SVille Syrjälä &wm->uv_wm[level], 161242a0d256SVille Syrjälä ddb_y, ddb); 161342a0d256SVille Syrjälä else 161442a0d256SVille Syrjälä skl_check_wm_level(&wm->wm[level], ddb); 161542a0d256SVille Syrjälä 16169fcbae04SStanislav Lisovskiy if (skl_need_wm_copy_wa(i915, level, wm)) { 16179fcbae04SStanislav Lisovskiy wm->wm[level].blocks = wm->wm[level - 1].blocks; 16189fcbae04SStanislav Lisovskiy wm->wm[level].lines = wm->wm[level - 1].lines; 16199fcbae04SStanislav Lisovskiy wm->wm[level].ignore_lines = wm->wm[level - 1].ignore_lines; 162042a0d256SVille Syrjälä } 162142a0d256SVille Syrjälä } 162242a0d256SVille Syrjälä } 162342a0d256SVille Syrjälä 162442a0d256SVille Syrjälä /* 162542a0d256SVille Syrjälä * Go back and disable the transition and SAGV watermarks 162642a0d256SVille Syrjälä * if it turns out we don't have enough DDB blocks for them. 162742a0d256SVille Syrjälä */ 162842a0d256SVille Syrjälä for_each_plane_id_on_crtc(crtc, plane_id) { 162942a0d256SVille Syrjälä const struct skl_ddb_entry *ddb = 163042a0d256SVille Syrjälä &crtc_state->wm.skl.plane_ddb[plane_id]; 163142a0d256SVille Syrjälä const struct skl_ddb_entry *ddb_y = 163242a0d256SVille Syrjälä &crtc_state->wm.skl.plane_ddb_y[plane_id]; 163342a0d256SVille Syrjälä struct skl_plane_wm *wm = 163442a0d256SVille Syrjälä &crtc_state->wm.skl.optimal.planes[plane_id]; 163542a0d256SVille Syrjälä 163642a0d256SVille Syrjälä if (DISPLAY_VER(i915) < 11 && 163742a0d256SVille Syrjälä crtc_state->nv12_planes & BIT(plane_id)) { 163842a0d256SVille Syrjälä skl_check_wm_level(&wm->trans_wm, ddb_y); 163942a0d256SVille Syrjälä } else { 164042a0d256SVille Syrjälä WARN_ON(skl_ddb_entry_size(ddb_y)); 164142a0d256SVille Syrjälä 164242a0d256SVille Syrjälä skl_check_wm_level(&wm->trans_wm, ddb); 164342a0d256SVille Syrjälä } 164442a0d256SVille Syrjälä 164542a0d256SVille Syrjälä skl_check_wm_level(&wm->sagv.wm0, ddb); 164642a0d256SVille Syrjälä skl_check_wm_level(&wm->sagv.trans_wm, ddb); 164742a0d256SVille Syrjälä } 164842a0d256SVille Syrjälä 164942a0d256SVille Syrjälä return 0; 165042a0d256SVille Syrjälä } 165142a0d256SVille Syrjälä 165242a0d256SVille Syrjälä /* 165342a0d256SVille Syrjälä * The max latency should be 257 (max the punit can code is 255 and we add 2us 165442a0d256SVille Syrjälä * for the read latency) and cpp should always be <= 8, so that 165542a0d256SVille Syrjälä * should allow pixel_rate up to ~2 GHz which seems sufficient since max 165642a0d256SVille Syrjälä * 2xcdclk is 1350 MHz and the pixel rate should never exceed that. 165742a0d256SVille Syrjälä */ 165842a0d256SVille Syrjälä static uint_fixed_16_16_t 165942a0d256SVille Syrjälä skl_wm_method1(const struct drm_i915_private *i915, u32 pixel_rate, 166042a0d256SVille Syrjälä u8 cpp, u32 latency, u32 dbuf_block_size) 166142a0d256SVille Syrjälä { 166242a0d256SVille Syrjälä u32 wm_intermediate_val; 166342a0d256SVille Syrjälä uint_fixed_16_16_t ret; 166442a0d256SVille Syrjälä 166542a0d256SVille Syrjälä if (latency == 0) 166642a0d256SVille Syrjälä return FP_16_16_MAX; 166742a0d256SVille Syrjälä 166842a0d256SVille Syrjälä wm_intermediate_val = latency * pixel_rate * cpp; 166942a0d256SVille Syrjälä ret = div_fixed16(wm_intermediate_val, 1000 * dbuf_block_size); 167042a0d256SVille Syrjälä 167142a0d256SVille Syrjälä if (DISPLAY_VER(i915) >= 10) 167242a0d256SVille Syrjälä ret = add_fixed16_u32(ret, 1); 167342a0d256SVille Syrjälä 167442a0d256SVille Syrjälä return ret; 167542a0d256SVille Syrjälä } 167642a0d256SVille Syrjälä 167742a0d256SVille Syrjälä static uint_fixed_16_16_t 167842a0d256SVille Syrjälä skl_wm_method2(u32 pixel_rate, u32 pipe_htotal, u32 latency, 167942a0d256SVille Syrjälä uint_fixed_16_16_t plane_blocks_per_line) 168042a0d256SVille Syrjälä { 168142a0d256SVille Syrjälä u32 wm_intermediate_val; 168242a0d256SVille Syrjälä uint_fixed_16_16_t ret; 168342a0d256SVille Syrjälä 168442a0d256SVille Syrjälä if (latency == 0) 168542a0d256SVille Syrjälä return FP_16_16_MAX; 168642a0d256SVille Syrjälä 168742a0d256SVille Syrjälä wm_intermediate_val = latency * pixel_rate; 168842a0d256SVille Syrjälä wm_intermediate_val = DIV_ROUND_UP(wm_intermediate_val, 168942a0d256SVille Syrjälä pipe_htotal * 1000); 169042a0d256SVille Syrjälä ret = mul_u32_fixed16(wm_intermediate_val, plane_blocks_per_line); 169142a0d256SVille Syrjälä return ret; 169242a0d256SVille Syrjälä } 169342a0d256SVille Syrjälä 169442a0d256SVille Syrjälä static uint_fixed_16_16_t 169542a0d256SVille Syrjälä intel_get_linetime_us(const struct intel_crtc_state *crtc_state) 169642a0d256SVille Syrjälä { 169742a0d256SVille Syrjälä struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); 169842a0d256SVille Syrjälä u32 pixel_rate; 169942a0d256SVille Syrjälä u32 crtc_htotal; 170042a0d256SVille Syrjälä uint_fixed_16_16_t linetime_us; 170142a0d256SVille Syrjälä 170242a0d256SVille Syrjälä if (!crtc_state->hw.active) 170342a0d256SVille Syrjälä return u32_to_fixed16(0); 170442a0d256SVille Syrjälä 170542a0d256SVille Syrjälä pixel_rate = crtc_state->pixel_rate; 170642a0d256SVille Syrjälä 170742a0d256SVille Syrjälä if (drm_WARN_ON(&i915->drm, pixel_rate == 0)) 170842a0d256SVille Syrjälä return u32_to_fixed16(0); 170942a0d256SVille Syrjälä 171042a0d256SVille Syrjälä crtc_htotal = crtc_state->hw.pipe_mode.crtc_htotal; 171142a0d256SVille Syrjälä linetime_us = div_fixed16(crtc_htotal * 1000, pixel_rate); 171242a0d256SVille Syrjälä 171342a0d256SVille Syrjälä return linetime_us; 171442a0d256SVille Syrjälä } 171542a0d256SVille Syrjälä 171642a0d256SVille Syrjälä static int 171742a0d256SVille Syrjälä skl_compute_wm_params(const struct intel_crtc_state *crtc_state, 171842a0d256SVille Syrjälä int width, const struct drm_format_info *format, 171942a0d256SVille Syrjälä u64 modifier, unsigned int rotation, 172042a0d256SVille Syrjälä u32 plane_pixel_rate, struct skl_wm_params *wp, 172142a0d256SVille Syrjälä int color_plane) 172242a0d256SVille Syrjälä { 172342a0d256SVille Syrjälä struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 172442a0d256SVille Syrjälä struct drm_i915_private *i915 = to_i915(crtc->base.dev); 172542a0d256SVille Syrjälä u32 interm_pbpl; 172642a0d256SVille Syrjälä 172742a0d256SVille Syrjälä /* only planar format has two planes */ 172842a0d256SVille Syrjälä if (color_plane == 1 && 172942a0d256SVille Syrjälä !intel_format_info_is_yuv_semiplanar(format, modifier)) { 173042a0d256SVille Syrjälä drm_dbg_kms(&i915->drm, 173142a0d256SVille Syrjälä "Non planar format have single plane\n"); 173242a0d256SVille Syrjälä return -EINVAL; 173342a0d256SVille Syrjälä } 173442a0d256SVille Syrjälä 173542a0d256SVille Syrjälä wp->x_tiled = modifier == I915_FORMAT_MOD_X_TILED; 1736d5c45330SVille Syrjälä wp->y_tiled = modifier != I915_FORMAT_MOD_X_TILED && 1737d5c45330SVille Syrjälä intel_fb_is_tiled_modifier(modifier); 1738d5c45330SVille Syrjälä wp->rc_surface = intel_fb_is_ccs_modifier(modifier); 173942a0d256SVille Syrjälä wp->is_planar = intel_format_info_is_yuv_semiplanar(format, modifier); 174042a0d256SVille Syrjälä 174142a0d256SVille Syrjälä wp->width = width; 174242a0d256SVille Syrjälä if (color_plane == 1 && wp->is_planar) 174342a0d256SVille Syrjälä wp->width /= 2; 174442a0d256SVille Syrjälä 174542a0d256SVille Syrjälä wp->cpp = format->cpp[color_plane]; 174642a0d256SVille Syrjälä wp->plane_pixel_rate = plane_pixel_rate; 174742a0d256SVille Syrjälä 174842a0d256SVille Syrjälä if (DISPLAY_VER(i915) >= 11 && 174942a0d256SVille Syrjälä modifier == I915_FORMAT_MOD_Yf_TILED && wp->cpp == 1) 175042a0d256SVille Syrjälä wp->dbuf_block_size = 256; 175142a0d256SVille Syrjälä else 175242a0d256SVille Syrjälä wp->dbuf_block_size = 512; 175342a0d256SVille Syrjälä 175442a0d256SVille Syrjälä if (drm_rotation_90_or_270(rotation)) { 175542a0d256SVille Syrjälä switch (wp->cpp) { 175642a0d256SVille Syrjälä case 1: 175742a0d256SVille Syrjälä wp->y_min_scanlines = 16; 175842a0d256SVille Syrjälä break; 175942a0d256SVille Syrjälä case 2: 176042a0d256SVille Syrjälä wp->y_min_scanlines = 8; 176142a0d256SVille Syrjälä break; 176242a0d256SVille Syrjälä case 4: 176342a0d256SVille Syrjälä wp->y_min_scanlines = 4; 176442a0d256SVille Syrjälä break; 176542a0d256SVille Syrjälä default: 176642a0d256SVille Syrjälä MISSING_CASE(wp->cpp); 176742a0d256SVille Syrjälä return -EINVAL; 176842a0d256SVille Syrjälä } 176942a0d256SVille Syrjälä } else { 177042a0d256SVille Syrjälä wp->y_min_scanlines = 4; 177142a0d256SVille Syrjälä } 177242a0d256SVille Syrjälä 177342a0d256SVille Syrjälä if (skl_needs_memory_bw_wa(i915)) 177442a0d256SVille Syrjälä wp->y_min_scanlines *= 2; 177542a0d256SVille Syrjälä 177642a0d256SVille Syrjälä wp->plane_bytes_per_line = wp->width * wp->cpp; 177742a0d256SVille Syrjälä if (wp->y_tiled) { 177842a0d256SVille Syrjälä interm_pbpl = DIV_ROUND_UP(wp->plane_bytes_per_line * 177942a0d256SVille Syrjälä wp->y_min_scanlines, 178042a0d256SVille Syrjälä wp->dbuf_block_size); 178142a0d256SVille Syrjälä 178242a0d256SVille Syrjälä if (DISPLAY_VER(i915) >= 10) 178342a0d256SVille Syrjälä interm_pbpl++; 178442a0d256SVille Syrjälä 178542a0d256SVille Syrjälä wp->plane_blocks_per_line = div_fixed16(interm_pbpl, 178642a0d256SVille Syrjälä wp->y_min_scanlines); 178742a0d256SVille Syrjälä } else { 178842a0d256SVille Syrjälä interm_pbpl = DIV_ROUND_UP(wp->plane_bytes_per_line, 178942a0d256SVille Syrjälä wp->dbuf_block_size); 179042a0d256SVille Syrjälä 179142a0d256SVille Syrjälä if (!wp->x_tiled || DISPLAY_VER(i915) >= 10) 179242a0d256SVille Syrjälä interm_pbpl++; 179342a0d256SVille Syrjälä 179442a0d256SVille Syrjälä wp->plane_blocks_per_line = u32_to_fixed16(interm_pbpl); 179542a0d256SVille Syrjälä } 179642a0d256SVille Syrjälä 179742a0d256SVille Syrjälä wp->y_tile_minimum = mul_u32_fixed16(wp->y_min_scanlines, 179842a0d256SVille Syrjälä wp->plane_blocks_per_line); 179942a0d256SVille Syrjälä 180042a0d256SVille Syrjälä wp->linetime_us = fixed16_to_u32_round_up(intel_get_linetime_us(crtc_state)); 180142a0d256SVille Syrjälä 180242a0d256SVille Syrjälä return 0; 180342a0d256SVille Syrjälä } 180442a0d256SVille Syrjälä 180542a0d256SVille Syrjälä static int 180642a0d256SVille Syrjälä skl_compute_plane_wm_params(const struct intel_crtc_state *crtc_state, 180742a0d256SVille Syrjälä const struct intel_plane_state *plane_state, 180842a0d256SVille Syrjälä struct skl_wm_params *wp, int color_plane) 180942a0d256SVille Syrjälä { 181042a0d256SVille Syrjälä const struct drm_framebuffer *fb = plane_state->hw.fb; 181142a0d256SVille Syrjälä int width; 181242a0d256SVille Syrjälä 181342a0d256SVille Syrjälä /* 181442a0d256SVille Syrjälä * Src coordinates are already rotated by 270 degrees for 181542a0d256SVille Syrjälä * the 90/270 degree plane rotation cases (to match the 181642a0d256SVille Syrjälä * GTT mapping), hence no need to account for rotation here. 181742a0d256SVille Syrjälä */ 181842a0d256SVille Syrjälä width = drm_rect_width(&plane_state->uapi.src) >> 16; 181942a0d256SVille Syrjälä 182042a0d256SVille Syrjälä return skl_compute_wm_params(crtc_state, width, 182142a0d256SVille Syrjälä fb->format, fb->modifier, 182242a0d256SVille Syrjälä plane_state->hw.rotation, 182342a0d256SVille Syrjälä intel_plane_pixel_rate(crtc_state, plane_state), 182442a0d256SVille Syrjälä wp, color_plane); 182542a0d256SVille Syrjälä } 182642a0d256SVille Syrjälä 182742a0d256SVille Syrjälä static bool skl_wm_has_lines(struct drm_i915_private *i915, int level) 182842a0d256SVille Syrjälä { 182942a0d256SVille Syrjälä if (DISPLAY_VER(i915) >= 10) 183042a0d256SVille Syrjälä return true; 183142a0d256SVille Syrjälä 183242a0d256SVille Syrjälä /* The number of lines are ignored for the level 0 watermark. */ 183342a0d256SVille Syrjälä return level > 0; 183442a0d256SVille Syrjälä } 183542a0d256SVille Syrjälä 183642a0d256SVille Syrjälä static int skl_wm_max_lines(struct drm_i915_private *i915) 183742a0d256SVille Syrjälä { 183842a0d256SVille Syrjälä if (DISPLAY_VER(i915) >= 13) 183942a0d256SVille Syrjälä return 255; 184042a0d256SVille Syrjälä else 184142a0d256SVille Syrjälä return 31; 184242a0d256SVille Syrjälä } 184342a0d256SVille Syrjälä 184442a0d256SVille Syrjälä static void skl_compute_plane_wm(const struct intel_crtc_state *crtc_state, 184542a0d256SVille Syrjälä struct intel_plane *plane, 184642a0d256SVille Syrjälä int level, 184742a0d256SVille Syrjälä unsigned int latency, 184842a0d256SVille Syrjälä const struct skl_wm_params *wp, 184942a0d256SVille Syrjälä const struct skl_wm_level *result_prev, 185042a0d256SVille Syrjälä struct skl_wm_level *result /* out */) 185142a0d256SVille Syrjälä { 185242a0d256SVille Syrjälä struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); 185342a0d256SVille Syrjälä uint_fixed_16_16_t method1, method2; 185442a0d256SVille Syrjälä uint_fixed_16_16_t selected_result; 185542a0d256SVille Syrjälä u32 blocks, lines, min_ddb_alloc = 0; 185642a0d256SVille Syrjälä 185742a0d256SVille Syrjälä if (latency == 0 || 185842a0d256SVille Syrjälä (use_minimal_wm0_only(crtc_state, plane) && level > 0)) { 185942a0d256SVille Syrjälä /* reject it */ 186042a0d256SVille Syrjälä result->min_ddb_alloc = U16_MAX; 186142a0d256SVille Syrjälä return; 186242a0d256SVille Syrjälä } 186342a0d256SVille Syrjälä 186442a0d256SVille Syrjälä method1 = skl_wm_method1(i915, wp->plane_pixel_rate, 186542a0d256SVille Syrjälä wp->cpp, latency, wp->dbuf_block_size); 186642a0d256SVille Syrjälä method2 = skl_wm_method2(wp->plane_pixel_rate, 186742a0d256SVille Syrjälä crtc_state->hw.pipe_mode.crtc_htotal, 186842a0d256SVille Syrjälä latency, 186942a0d256SVille Syrjälä wp->plane_blocks_per_line); 187042a0d256SVille Syrjälä 187142a0d256SVille Syrjälä if (wp->y_tiled) { 187242a0d256SVille Syrjälä selected_result = max_fixed16(method2, wp->y_tile_minimum); 187342a0d256SVille Syrjälä } else { 187442a0d256SVille Syrjälä if ((wp->cpp * crtc_state->hw.pipe_mode.crtc_htotal / 187542a0d256SVille Syrjälä wp->dbuf_block_size < 1) && 187642a0d256SVille Syrjälä (wp->plane_bytes_per_line / wp->dbuf_block_size < 1)) { 187742a0d256SVille Syrjälä selected_result = method2; 187842a0d256SVille Syrjälä } else if (latency >= wp->linetime_us) { 187942a0d256SVille Syrjälä if (DISPLAY_VER(i915) == 9) 188042a0d256SVille Syrjälä selected_result = min_fixed16(method1, method2); 188142a0d256SVille Syrjälä else 188242a0d256SVille Syrjälä selected_result = method2; 188342a0d256SVille Syrjälä } else { 188442a0d256SVille Syrjälä selected_result = method1; 188542a0d256SVille Syrjälä } 188642a0d256SVille Syrjälä } 188742a0d256SVille Syrjälä 188842a0d256SVille Syrjälä blocks = fixed16_to_u32_round_up(selected_result) + 1; 188942a0d256SVille Syrjälä /* 189042a0d256SVille Syrjälä * Lets have blocks at minimum equivalent to plane_blocks_per_line 189142a0d256SVille Syrjälä * as there will be at minimum one line for lines configuration. This 189242a0d256SVille Syrjälä * is a work around for FIFO underruns observed with resolutions like 189342a0d256SVille Syrjälä * 4k 60 Hz in single channel DRAM configurations. 189442a0d256SVille Syrjälä * 189542a0d256SVille Syrjälä * As per the Bspec 49325, if the ddb allocation can hold at least 189642a0d256SVille Syrjälä * one plane_blocks_per_line, we should have selected method2 in 189742a0d256SVille Syrjälä * the above logic. Assuming that modern versions have enough dbuf 189842a0d256SVille Syrjälä * and method2 guarantees blocks equivalent to at least 1 line, 189942a0d256SVille Syrjälä * select the blocks as plane_blocks_per_line. 190042a0d256SVille Syrjälä * 190142a0d256SVille Syrjälä * TODO: Revisit the logic when we have better understanding on DRAM 190242a0d256SVille Syrjälä * channels' impact on the level 0 memory latency and the relevant 190342a0d256SVille Syrjälä * wm calculations. 190442a0d256SVille Syrjälä */ 190542a0d256SVille Syrjälä if (skl_wm_has_lines(i915, level)) 190642a0d256SVille Syrjälä blocks = max(blocks, 190742a0d256SVille Syrjälä fixed16_to_u32_round_up(wp->plane_blocks_per_line)); 190842a0d256SVille Syrjälä lines = div_round_up_fixed16(selected_result, 190942a0d256SVille Syrjälä wp->plane_blocks_per_line); 191042a0d256SVille Syrjälä 191142a0d256SVille Syrjälä if (DISPLAY_VER(i915) == 9) { 191242a0d256SVille Syrjälä /* Display WA #1125: skl,bxt,kbl */ 191342a0d256SVille Syrjälä if (level == 0 && wp->rc_surface) 191442a0d256SVille Syrjälä blocks += fixed16_to_u32_round_up(wp->y_tile_minimum); 191542a0d256SVille Syrjälä 191642a0d256SVille Syrjälä /* Display WA #1126: skl,bxt,kbl */ 191742a0d256SVille Syrjälä if (level >= 1 && level <= 7) { 191842a0d256SVille Syrjälä if (wp->y_tiled) { 191942a0d256SVille Syrjälä blocks += fixed16_to_u32_round_up(wp->y_tile_minimum); 192042a0d256SVille Syrjälä lines += wp->y_min_scanlines; 192142a0d256SVille Syrjälä } else { 192242a0d256SVille Syrjälä blocks++; 192342a0d256SVille Syrjälä } 192442a0d256SVille Syrjälä 192542a0d256SVille Syrjälä /* 192642a0d256SVille Syrjälä * Make sure result blocks for higher latency levels are 192742a0d256SVille Syrjälä * at least as high as level below the current level. 192842a0d256SVille Syrjälä * Assumption in DDB algorithm optimization for special 192942a0d256SVille Syrjälä * cases. Also covers Display WA #1125 for RC. 193042a0d256SVille Syrjälä */ 193142a0d256SVille Syrjälä if (result_prev->blocks > blocks) 193242a0d256SVille Syrjälä blocks = result_prev->blocks; 193342a0d256SVille Syrjälä } 193442a0d256SVille Syrjälä } 193542a0d256SVille Syrjälä 193642a0d256SVille Syrjälä if (DISPLAY_VER(i915) >= 11) { 193742a0d256SVille Syrjälä if (wp->y_tiled) { 193842a0d256SVille Syrjälä int extra_lines; 193942a0d256SVille Syrjälä 194042a0d256SVille Syrjälä if (lines % wp->y_min_scanlines == 0) 194142a0d256SVille Syrjälä extra_lines = wp->y_min_scanlines; 194242a0d256SVille Syrjälä else 194342a0d256SVille Syrjälä extra_lines = wp->y_min_scanlines * 2 - 194442a0d256SVille Syrjälä lines % wp->y_min_scanlines; 194542a0d256SVille Syrjälä 194642a0d256SVille Syrjälä min_ddb_alloc = mul_round_up_u32_fixed16(lines + extra_lines, 194742a0d256SVille Syrjälä wp->plane_blocks_per_line); 194842a0d256SVille Syrjälä } else { 194942a0d256SVille Syrjälä min_ddb_alloc = blocks + DIV_ROUND_UP(blocks, 10); 195042a0d256SVille Syrjälä } 195142a0d256SVille Syrjälä } 195242a0d256SVille Syrjälä 195342a0d256SVille Syrjälä if (!skl_wm_has_lines(i915, level)) 195442a0d256SVille Syrjälä lines = 0; 195542a0d256SVille Syrjälä 195642a0d256SVille Syrjälä if (lines > skl_wm_max_lines(i915)) { 195742a0d256SVille Syrjälä /* reject it */ 195842a0d256SVille Syrjälä result->min_ddb_alloc = U16_MAX; 195942a0d256SVille Syrjälä return; 196042a0d256SVille Syrjälä } 196142a0d256SVille Syrjälä 196242a0d256SVille Syrjälä /* 196342a0d256SVille Syrjälä * If lines is valid, assume we can use this watermark level 196442a0d256SVille Syrjälä * for now. We'll come back and disable it after we calculate the 196542a0d256SVille Syrjälä * DDB allocation if it turns out we don't actually have enough 196642a0d256SVille Syrjälä * blocks to satisfy it. 196742a0d256SVille Syrjälä */ 196842a0d256SVille Syrjälä result->blocks = blocks; 196942a0d256SVille Syrjälä result->lines = lines; 197042a0d256SVille Syrjälä /* Bspec says: value >= plane ddb allocation -> invalid, hence the +1 here */ 197142a0d256SVille Syrjälä result->min_ddb_alloc = max(min_ddb_alloc, blocks) + 1; 197242a0d256SVille Syrjälä result->enable = true; 197342a0d256SVille Syrjälä 197442a0d256SVille Syrjälä if (DISPLAY_VER(i915) < 12 && i915->display.sagv.block_time_us) 197542a0d256SVille Syrjälä result->can_sagv = latency >= i915->display.sagv.block_time_us; 197642a0d256SVille Syrjälä } 197742a0d256SVille Syrjälä 197842a0d256SVille Syrjälä static void 197942a0d256SVille Syrjälä skl_compute_wm_levels(const struct intel_crtc_state *crtc_state, 198042a0d256SVille Syrjälä struct intel_plane *plane, 198142a0d256SVille Syrjälä const struct skl_wm_params *wm_params, 198242a0d256SVille Syrjälä struct skl_wm_level *levels) 198342a0d256SVille Syrjälä { 198442a0d256SVille Syrjälä struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); 198542a0d256SVille Syrjälä struct skl_wm_level *result_prev = &levels[0]; 19867ee6f99dSVille Syrjälä int level; 198742a0d256SVille Syrjälä 19887ee6f99dSVille Syrjälä for (level = 0; level < i915->display.wm.num_levels; level++) { 198942a0d256SVille Syrjälä struct skl_wm_level *result = &levels[level]; 1990*6b931346SVille Syrjälä unsigned int latency = skl_wm_latency(i915, level, wm_params); 199142a0d256SVille Syrjälä 199242a0d256SVille Syrjälä skl_compute_plane_wm(crtc_state, plane, level, latency, 199342a0d256SVille Syrjälä wm_params, result_prev, result); 199442a0d256SVille Syrjälä 199542a0d256SVille Syrjälä result_prev = result; 199642a0d256SVille Syrjälä } 199742a0d256SVille Syrjälä } 199842a0d256SVille Syrjälä 199942a0d256SVille Syrjälä static void tgl_compute_sagv_wm(const struct intel_crtc_state *crtc_state, 200042a0d256SVille Syrjälä struct intel_plane *plane, 200142a0d256SVille Syrjälä const struct skl_wm_params *wm_params, 200242a0d256SVille Syrjälä struct skl_plane_wm *plane_wm) 200342a0d256SVille Syrjälä { 200442a0d256SVille Syrjälä struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); 200542a0d256SVille Syrjälä struct skl_wm_level *sagv_wm = &plane_wm->sagv.wm0; 200642a0d256SVille Syrjälä struct skl_wm_level *levels = plane_wm->wm; 200742a0d256SVille Syrjälä unsigned int latency = 0; 200842a0d256SVille Syrjälä 200942a0d256SVille Syrjälä if (i915->display.sagv.block_time_us) 2010*6b931346SVille Syrjälä latency = i915->display.sagv.block_time_us + 2011*6b931346SVille Syrjälä skl_wm_latency(i915, 0, wm_params); 201242a0d256SVille Syrjälä 201342a0d256SVille Syrjälä skl_compute_plane_wm(crtc_state, plane, 0, latency, 201442a0d256SVille Syrjälä wm_params, &levels[0], 201542a0d256SVille Syrjälä sagv_wm); 201642a0d256SVille Syrjälä } 201742a0d256SVille Syrjälä 201842a0d256SVille Syrjälä static void skl_compute_transition_wm(struct drm_i915_private *i915, 201942a0d256SVille Syrjälä struct skl_wm_level *trans_wm, 202042a0d256SVille Syrjälä const struct skl_wm_level *wm0, 202142a0d256SVille Syrjälä const struct skl_wm_params *wp) 202242a0d256SVille Syrjälä { 202342a0d256SVille Syrjälä u16 trans_min, trans_amount, trans_y_tile_min; 202442a0d256SVille Syrjälä u16 wm0_blocks, trans_offset, blocks; 202542a0d256SVille Syrjälä 202642a0d256SVille Syrjälä /* Transition WM don't make any sense if ipc is disabled */ 202723fbdb07SJani Nikula if (!skl_watermark_ipc_enabled(i915)) 202842a0d256SVille Syrjälä return; 202942a0d256SVille Syrjälä 203042a0d256SVille Syrjälä /* 203142a0d256SVille Syrjälä * WaDisableTWM:skl,kbl,cfl,bxt 203242a0d256SVille Syrjälä * Transition WM are not recommended by HW team for GEN9 203342a0d256SVille Syrjälä */ 203442a0d256SVille Syrjälä if (DISPLAY_VER(i915) == 9) 203542a0d256SVille Syrjälä return; 203642a0d256SVille Syrjälä 203742a0d256SVille Syrjälä if (DISPLAY_VER(i915) >= 11) 203842a0d256SVille Syrjälä trans_min = 4; 203942a0d256SVille Syrjälä else 204042a0d256SVille Syrjälä trans_min = 14; 204142a0d256SVille Syrjälä 204242a0d256SVille Syrjälä /* Display WA #1140: glk,cnl */ 204342a0d256SVille Syrjälä if (DISPLAY_VER(i915) == 10) 204442a0d256SVille Syrjälä trans_amount = 0; 204542a0d256SVille Syrjälä else 204642a0d256SVille Syrjälä trans_amount = 10; /* This is configurable amount */ 204742a0d256SVille Syrjälä 204842a0d256SVille Syrjälä trans_offset = trans_min + trans_amount; 204942a0d256SVille Syrjälä 205042a0d256SVille Syrjälä /* 205142a0d256SVille Syrjälä * The spec asks for Selected Result Blocks for wm0 (the real value), 205242a0d256SVille Syrjälä * not Result Blocks (the integer value). Pay attention to the capital 205342a0d256SVille Syrjälä * letters. The value wm_l0->blocks is actually Result Blocks, but 205442a0d256SVille Syrjälä * since Result Blocks is the ceiling of Selected Result Blocks plus 1, 205542a0d256SVille Syrjälä * and since we later will have to get the ceiling of the sum in the 205642a0d256SVille Syrjälä * transition watermarks calculation, we can just pretend Selected 205742a0d256SVille Syrjälä * Result Blocks is Result Blocks minus 1 and it should work for the 205842a0d256SVille Syrjälä * current platforms. 205942a0d256SVille Syrjälä */ 206042a0d256SVille Syrjälä wm0_blocks = wm0->blocks - 1; 206142a0d256SVille Syrjälä 206242a0d256SVille Syrjälä if (wp->y_tiled) { 206342a0d256SVille Syrjälä trans_y_tile_min = 206442a0d256SVille Syrjälä (u16)mul_round_up_u32_fixed16(2, wp->y_tile_minimum); 206542a0d256SVille Syrjälä blocks = max(wm0_blocks, trans_y_tile_min) + trans_offset; 206642a0d256SVille Syrjälä } else { 206742a0d256SVille Syrjälä blocks = wm0_blocks + trans_offset; 206842a0d256SVille Syrjälä } 206942a0d256SVille Syrjälä blocks++; 207042a0d256SVille Syrjälä 207142a0d256SVille Syrjälä /* 207242a0d256SVille Syrjälä * Just assume we can enable the transition watermark. After 207342a0d256SVille Syrjälä * computing the DDB we'll come back and disable it if that 207442a0d256SVille Syrjälä * assumption turns out to be false. 207542a0d256SVille Syrjälä */ 207642a0d256SVille Syrjälä trans_wm->blocks = blocks; 207742a0d256SVille Syrjälä trans_wm->min_ddb_alloc = max_t(u16, wm0->min_ddb_alloc, blocks + 1); 207842a0d256SVille Syrjälä trans_wm->enable = true; 207942a0d256SVille Syrjälä } 208042a0d256SVille Syrjälä 208142a0d256SVille Syrjälä static int skl_build_plane_wm_single(struct intel_crtc_state *crtc_state, 208242a0d256SVille Syrjälä const struct intel_plane_state *plane_state, 208342a0d256SVille Syrjälä struct intel_plane *plane, int color_plane) 208442a0d256SVille Syrjälä { 208542a0d256SVille Syrjälä struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 208642a0d256SVille Syrjälä struct drm_i915_private *i915 = to_i915(crtc->base.dev); 208742a0d256SVille Syrjälä struct skl_plane_wm *wm = &crtc_state->wm.skl.raw.planes[plane->id]; 208842a0d256SVille Syrjälä struct skl_wm_params wm_params; 208942a0d256SVille Syrjälä int ret; 209042a0d256SVille Syrjälä 209142a0d256SVille Syrjälä ret = skl_compute_plane_wm_params(crtc_state, plane_state, 209242a0d256SVille Syrjälä &wm_params, color_plane); 209342a0d256SVille Syrjälä if (ret) 209442a0d256SVille Syrjälä return ret; 209542a0d256SVille Syrjälä 209642a0d256SVille Syrjälä skl_compute_wm_levels(crtc_state, plane, &wm_params, wm->wm); 209742a0d256SVille Syrjälä 209842a0d256SVille Syrjälä skl_compute_transition_wm(i915, &wm->trans_wm, 209942a0d256SVille Syrjälä &wm->wm[0], &wm_params); 210042a0d256SVille Syrjälä 210142a0d256SVille Syrjälä if (DISPLAY_VER(i915) >= 12) { 210242a0d256SVille Syrjälä tgl_compute_sagv_wm(crtc_state, plane, &wm_params, wm); 210342a0d256SVille Syrjälä 210442a0d256SVille Syrjälä skl_compute_transition_wm(i915, &wm->sagv.trans_wm, 210542a0d256SVille Syrjälä &wm->sagv.wm0, &wm_params); 210642a0d256SVille Syrjälä } 210742a0d256SVille Syrjälä 210842a0d256SVille Syrjälä return 0; 210942a0d256SVille Syrjälä } 211042a0d256SVille Syrjälä 211142a0d256SVille Syrjälä static int skl_build_plane_wm_uv(struct intel_crtc_state *crtc_state, 211242a0d256SVille Syrjälä const struct intel_plane_state *plane_state, 211342a0d256SVille Syrjälä struct intel_plane *plane) 211442a0d256SVille Syrjälä { 211542a0d256SVille Syrjälä struct skl_plane_wm *wm = &crtc_state->wm.skl.raw.planes[plane->id]; 211642a0d256SVille Syrjälä struct skl_wm_params wm_params; 211742a0d256SVille Syrjälä int ret; 211842a0d256SVille Syrjälä 211942a0d256SVille Syrjälä wm->is_planar = true; 212042a0d256SVille Syrjälä 212142a0d256SVille Syrjälä /* uv plane watermarks must also be validated for NV12/Planar */ 212242a0d256SVille Syrjälä ret = skl_compute_plane_wm_params(crtc_state, plane_state, 212342a0d256SVille Syrjälä &wm_params, 1); 212442a0d256SVille Syrjälä if (ret) 212542a0d256SVille Syrjälä return ret; 212642a0d256SVille Syrjälä 212742a0d256SVille Syrjälä skl_compute_wm_levels(crtc_state, plane, &wm_params, wm->uv_wm); 212842a0d256SVille Syrjälä 212942a0d256SVille Syrjälä return 0; 213042a0d256SVille Syrjälä } 213142a0d256SVille Syrjälä 213242a0d256SVille Syrjälä static int skl_build_plane_wm(struct intel_crtc_state *crtc_state, 213342a0d256SVille Syrjälä const struct intel_plane_state *plane_state) 213442a0d256SVille Syrjälä { 213542a0d256SVille Syrjälä struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); 213642a0d256SVille Syrjälä enum plane_id plane_id = plane->id; 213742a0d256SVille Syrjälä struct skl_plane_wm *wm = &crtc_state->wm.skl.raw.planes[plane_id]; 213842a0d256SVille Syrjälä const struct drm_framebuffer *fb = plane_state->hw.fb; 213942a0d256SVille Syrjälä int ret; 214042a0d256SVille Syrjälä 214142a0d256SVille Syrjälä memset(wm, 0, sizeof(*wm)); 214242a0d256SVille Syrjälä 214342a0d256SVille Syrjälä if (!intel_wm_plane_visible(crtc_state, plane_state)) 214442a0d256SVille Syrjälä return 0; 214542a0d256SVille Syrjälä 214642a0d256SVille Syrjälä ret = skl_build_plane_wm_single(crtc_state, plane_state, 214742a0d256SVille Syrjälä plane, 0); 214842a0d256SVille Syrjälä if (ret) 214942a0d256SVille Syrjälä return ret; 215042a0d256SVille Syrjälä 215142a0d256SVille Syrjälä if (fb->format->is_yuv && fb->format->num_planes > 1) { 215242a0d256SVille Syrjälä ret = skl_build_plane_wm_uv(crtc_state, plane_state, 215342a0d256SVille Syrjälä plane); 215442a0d256SVille Syrjälä if (ret) 215542a0d256SVille Syrjälä return ret; 215642a0d256SVille Syrjälä } 215742a0d256SVille Syrjälä 215842a0d256SVille Syrjälä return 0; 215942a0d256SVille Syrjälä } 216042a0d256SVille Syrjälä 216142a0d256SVille Syrjälä static int icl_build_plane_wm(struct intel_crtc_state *crtc_state, 216242a0d256SVille Syrjälä const struct intel_plane_state *plane_state) 216342a0d256SVille Syrjälä { 216442a0d256SVille Syrjälä struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); 216542a0d256SVille Syrjälä struct drm_i915_private *i915 = to_i915(plane->base.dev); 216642a0d256SVille Syrjälä enum plane_id plane_id = plane->id; 216742a0d256SVille Syrjälä struct skl_plane_wm *wm = &crtc_state->wm.skl.raw.planes[plane_id]; 216842a0d256SVille Syrjälä int ret; 216942a0d256SVille Syrjälä 217042a0d256SVille Syrjälä /* Watermarks calculated in master */ 217142a0d256SVille Syrjälä if (plane_state->planar_slave) 217242a0d256SVille Syrjälä return 0; 217342a0d256SVille Syrjälä 217442a0d256SVille Syrjälä memset(wm, 0, sizeof(*wm)); 217542a0d256SVille Syrjälä 217642a0d256SVille Syrjälä if (plane_state->planar_linked_plane) { 217742a0d256SVille Syrjälä const struct drm_framebuffer *fb = plane_state->hw.fb; 217842a0d256SVille Syrjälä 217942a0d256SVille Syrjälä drm_WARN_ON(&i915->drm, 218042a0d256SVille Syrjälä !intel_wm_plane_visible(crtc_state, plane_state)); 218142a0d256SVille Syrjälä drm_WARN_ON(&i915->drm, !fb->format->is_yuv || 218242a0d256SVille Syrjälä fb->format->num_planes == 1); 218342a0d256SVille Syrjälä 218442a0d256SVille Syrjälä ret = skl_build_plane_wm_single(crtc_state, plane_state, 218542a0d256SVille Syrjälä plane_state->planar_linked_plane, 0); 218642a0d256SVille Syrjälä if (ret) 218742a0d256SVille Syrjälä return ret; 218842a0d256SVille Syrjälä 218942a0d256SVille Syrjälä ret = skl_build_plane_wm_single(crtc_state, plane_state, 219042a0d256SVille Syrjälä plane, 1); 219142a0d256SVille Syrjälä if (ret) 219242a0d256SVille Syrjälä return ret; 219342a0d256SVille Syrjälä } else if (intel_wm_plane_visible(crtc_state, plane_state)) { 219442a0d256SVille Syrjälä ret = skl_build_plane_wm_single(crtc_state, plane_state, 219542a0d256SVille Syrjälä plane, 0); 219642a0d256SVille Syrjälä if (ret) 219742a0d256SVille Syrjälä return ret; 219842a0d256SVille Syrjälä } 219942a0d256SVille Syrjälä 220042a0d256SVille Syrjälä return 0; 220142a0d256SVille Syrjälä } 220242a0d256SVille Syrjälä 220342a0d256SVille Syrjälä static int skl_build_pipe_wm(struct intel_atomic_state *state, 220442a0d256SVille Syrjälä struct intel_crtc *crtc) 220542a0d256SVille Syrjälä { 220642a0d256SVille Syrjälä struct drm_i915_private *i915 = to_i915(crtc->base.dev); 220742a0d256SVille Syrjälä struct intel_crtc_state *crtc_state = 220842a0d256SVille Syrjälä intel_atomic_get_new_crtc_state(state, crtc); 220942a0d256SVille Syrjälä const struct intel_plane_state *plane_state; 221042a0d256SVille Syrjälä struct intel_plane *plane; 221142a0d256SVille Syrjälä int ret, i; 221242a0d256SVille Syrjälä 221342a0d256SVille Syrjälä for_each_new_intel_plane_in_state(state, plane, plane_state, i) { 221442a0d256SVille Syrjälä /* 221542a0d256SVille Syrjälä * FIXME should perhaps check {old,new}_plane_crtc->hw.crtc 221642a0d256SVille Syrjälä * instead but we don't populate that correctly for NV12 Y 221742a0d256SVille Syrjälä * planes so for now hack this. 221842a0d256SVille Syrjälä */ 221942a0d256SVille Syrjälä if (plane->pipe != crtc->pipe) 222042a0d256SVille Syrjälä continue; 222142a0d256SVille Syrjälä 222242a0d256SVille Syrjälä if (DISPLAY_VER(i915) >= 11) 222342a0d256SVille Syrjälä ret = icl_build_plane_wm(crtc_state, plane_state); 222442a0d256SVille Syrjälä else 222542a0d256SVille Syrjälä ret = skl_build_plane_wm(crtc_state, plane_state); 222642a0d256SVille Syrjälä if (ret) 222742a0d256SVille Syrjälä return ret; 222842a0d256SVille Syrjälä } 222942a0d256SVille Syrjälä 223042a0d256SVille Syrjälä crtc_state->wm.skl.optimal = crtc_state->wm.skl.raw; 223142a0d256SVille Syrjälä 223242a0d256SVille Syrjälä return 0; 223342a0d256SVille Syrjälä } 223442a0d256SVille Syrjälä 223542a0d256SVille Syrjälä static void skl_ddb_entry_write(struct drm_i915_private *i915, 223642a0d256SVille Syrjälä i915_reg_t reg, 223742a0d256SVille Syrjälä const struct skl_ddb_entry *entry) 223842a0d256SVille Syrjälä { 223942a0d256SVille Syrjälä if (entry->end) 224042a0d256SVille Syrjälä intel_de_write_fw(i915, reg, 224142a0d256SVille Syrjälä PLANE_BUF_END(entry->end - 1) | 224242a0d256SVille Syrjälä PLANE_BUF_START(entry->start)); 224342a0d256SVille Syrjälä else 224442a0d256SVille Syrjälä intel_de_write_fw(i915, reg, 0); 224542a0d256SVille Syrjälä } 224642a0d256SVille Syrjälä 224742a0d256SVille Syrjälä static void skl_write_wm_level(struct drm_i915_private *i915, 224842a0d256SVille Syrjälä i915_reg_t reg, 224942a0d256SVille Syrjälä const struct skl_wm_level *level) 225042a0d256SVille Syrjälä { 225142a0d256SVille Syrjälä u32 val = 0; 225242a0d256SVille Syrjälä 225342a0d256SVille Syrjälä if (level->enable) 225442a0d256SVille Syrjälä val |= PLANE_WM_EN; 225542a0d256SVille Syrjälä if (level->ignore_lines) 225642a0d256SVille Syrjälä val |= PLANE_WM_IGNORE_LINES; 225742a0d256SVille Syrjälä val |= REG_FIELD_PREP(PLANE_WM_BLOCKS_MASK, level->blocks); 225842a0d256SVille Syrjälä val |= REG_FIELD_PREP(PLANE_WM_LINES_MASK, level->lines); 225942a0d256SVille Syrjälä 226042a0d256SVille Syrjälä intel_de_write_fw(i915, reg, val); 226142a0d256SVille Syrjälä } 226242a0d256SVille Syrjälä 226342a0d256SVille Syrjälä void skl_write_plane_wm(struct intel_plane *plane, 226442a0d256SVille Syrjälä const struct intel_crtc_state *crtc_state) 226542a0d256SVille Syrjälä { 226642a0d256SVille Syrjälä struct drm_i915_private *i915 = to_i915(plane->base.dev); 226742a0d256SVille Syrjälä enum plane_id plane_id = plane->id; 226842a0d256SVille Syrjälä enum pipe pipe = plane->pipe; 226942a0d256SVille Syrjälä const struct skl_pipe_wm *pipe_wm = &crtc_state->wm.skl.optimal; 227042a0d256SVille Syrjälä const struct skl_ddb_entry *ddb = 227142a0d256SVille Syrjälä &crtc_state->wm.skl.plane_ddb[plane_id]; 227242a0d256SVille Syrjälä const struct skl_ddb_entry *ddb_y = 227342a0d256SVille Syrjälä &crtc_state->wm.skl.plane_ddb_y[plane_id]; 22747ee6f99dSVille Syrjälä int level; 227542a0d256SVille Syrjälä 22767ee6f99dSVille Syrjälä for (level = 0; level < i915->display.wm.num_levels; level++) 227742a0d256SVille Syrjälä skl_write_wm_level(i915, PLANE_WM(pipe, plane_id, level), 227842a0d256SVille Syrjälä skl_plane_wm_level(pipe_wm, plane_id, level)); 227942a0d256SVille Syrjälä 228042a0d256SVille Syrjälä skl_write_wm_level(i915, PLANE_WM_TRANS(pipe, plane_id), 228142a0d256SVille Syrjälä skl_plane_trans_wm(pipe_wm, plane_id)); 228242a0d256SVille Syrjälä 228342a0d256SVille Syrjälä if (HAS_HW_SAGV_WM(i915)) { 228442a0d256SVille Syrjälä const struct skl_plane_wm *wm = &pipe_wm->planes[plane_id]; 228542a0d256SVille Syrjälä 228642a0d256SVille Syrjälä skl_write_wm_level(i915, PLANE_WM_SAGV(pipe, plane_id), 228742a0d256SVille Syrjälä &wm->sagv.wm0); 228842a0d256SVille Syrjälä skl_write_wm_level(i915, PLANE_WM_SAGV_TRANS(pipe, plane_id), 228942a0d256SVille Syrjälä &wm->sagv.trans_wm); 229042a0d256SVille Syrjälä } 229142a0d256SVille Syrjälä 229242a0d256SVille Syrjälä skl_ddb_entry_write(i915, 229342a0d256SVille Syrjälä PLANE_BUF_CFG(pipe, plane_id), ddb); 229442a0d256SVille Syrjälä 229542a0d256SVille Syrjälä if (DISPLAY_VER(i915) < 11) 229642a0d256SVille Syrjälä skl_ddb_entry_write(i915, 229742a0d256SVille Syrjälä PLANE_NV12_BUF_CFG(pipe, plane_id), ddb_y); 229842a0d256SVille Syrjälä } 229942a0d256SVille Syrjälä 230042a0d256SVille Syrjälä void skl_write_cursor_wm(struct intel_plane *plane, 230142a0d256SVille Syrjälä const struct intel_crtc_state *crtc_state) 230242a0d256SVille Syrjälä { 230342a0d256SVille Syrjälä struct drm_i915_private *i915 = to_i915(plane->base.dev); 230442a0d256SVille Syrjälä enum plane_id plane_id = plane->id; 230542a0d256SVille Syrjälä enum pipe pipe = plane->pipe; 230642a0d256SVille Syrjälä const struct skl_pipe_wm *pipe_wm = &crtc_state->wm.skl.optimal; 230742a0d256SVille Syrjälä const struct skl_ddb_entry *ddb = 230842a0d256SVille Syrjälä &crtc_state->wm.skl.plane_ddb[plane_id]; 23097ee6f99dSVille Syrjälä int level; 231042a0d256SVille Syrjälä 23117ee6f99dSVille Syrjälä for (level = 0; level < i915->display.wm.num_levels; level++) 231242a0d256SVille Syrjälä skl_write_wm_level(i915, CUR_WM(pipe, level), 231342a0d256SVille Syrjälä skl_plane_wm_level(pipe_wm, plane_id, level)); 231442a0d256SVille Syrjälä 231542a0d256SVille Syrjälä skl_write_wm_level(i915, CUR_WM_TRANS(pipe), 231642a0d256SVille Syrjälä skl_plane_trans_wm(pipe_wm, plane_id)); 231742a0d256SVille Syrjälä 231842a0d256SVille Syrjälä if (HAS_HW_SAGV_WM(i915)) { 231942a0d256SVille Syrjälä const struct skl_plane_wm *wm = &pipe_wm->planes[plane_id]; 232042a0d256SVille Syrjälä 232142a0d256SVille Syrjälä skl_write_wm_level(i915, CUR_WM_SAGV(pipe), 232242a0d256SVille Syrjälä &wm->sagv.wm0); 232342a0d256SVille Syrjälä skl_write_wm_level(i915, CUR_WM_SAGV_TRANS(pipe), 232442a0d256SVille Syrjälä &wm->sagv.trans_wm); 232542a0d256SVille Syrjälä } 232642a0d256SVille Syrjälä 232742a0d256SVille Syrjälä skl_ddb_entry_write(i915, CUR_BUF_CFG(pipe), ddb); 232842a0d256SVille Syrjälä } 232942a0d256SVille Syrjälä 233042a0d256SVille Syrjälä static bool skl_wm_level_equals(const struct skl_wm_level *l1, 233142a0d256SVille Syrjälä const struct skl_wm_level *l2) 233242a0d256SVille Syrjälä { 233342a0d256SVille Syrjälä return l1->enable == l2->enable && 233442a0d256SVille Syrjälä l1->ignore_lines == l2->ignore_lines && 233542a0d256SVille Syrjälä l1->lines == l2->lines && 233642a0d256SVille Syrjälä l1->blocks == l2->blocks; 233742a0d256SVille Syrjälä } 233842a0d256SVille Syrjälä 233942a0d256SVille Syrjälä static bool skl_plane_wm_equals(struct drm_i915_private *i915, 234042a0d256SVille Syrjälä const struct skl_plane_wm *wm1, 234142a0d256SVille Syrjälä const struct skl_plane_wm *wm2) 234242a0d256SVille Syrjälä { 23437ee6f99dSVille Syrjälä int level; 234442a0d256SVille Syrjälä 23457ee6f99dSVille Syrjälä for (level = 0; level < i915->display.wm.num_levels; level++) { 234642a0d256SVille Syrjälä /* 234742a0d256SVille Syrjälä * We don't check uv_wm as the hardware doesn't actually 234842a0d256SVille Syrjälä * use it. It only gets used for calculating the required 234942a0d256SVille Syrjälä * ddb allocation. 235042a0d256SVille Syrjälä */ 235142a0d256SVille Syrjälä if (!skl_wm_level_equals(&wm1->wm[level], &wm2->wm[level])) 235242a0d256SVille Syrjälä return false; 235342a0d256SVille Syrjälä } 235442a0d256SVille Syrjälä 235542a0d256SVille Syrjälä return skl_wm_level_equals(&wm1->trans_wm, &wm2->trans_wm) && 235642a0d256SVille Syrjälä skl_wm_level_equals(&wm1->sagv.wm0, &wm2->sagv.wm0) && 235742a0d256SVille Syrjälä skl_wm_level_equals(&wm1->sagv.trans_wm, &wm2->sagv.trans_wm); 235842a0d256SVille Syrjälä } 235942a0d256SVille Syrjälä 236042a0d256SVille Syrjälä static bool skl_ddb_entries_overlap(const struct skl_ddb_entry *a, 236142a0d256SVille Syrjälä const struct skl_ddb_entry *b) 236242a0d256SVille Syrjälä { 236342a0d256SVille Syrjälä return a->start < b->end && b->start < a->end; 236442a0d256SVille Syrjälä } 236542a0d256SVille Syrjälä 236642a0d256SVille Syrjälä static void skl_ddb_entry_union(struct skl_ddb_entry *a, 236742a0d256SVille Syrjälä const struct skl_ddb_entry *b) 236842a0d256SVille Syrjälä { 236942a0d256SVille Syrjälä if (a->end && b->end) { 237042a0d256SVille Syrjälä a->start = min(a->start, b->start); 237142a0d256SVille Syrjälä a->end = max(a->end, b->end); 237242a0d256SVille Syrjälä } else if (b->end) { 237342a0d256SVille Syrjälä a->start = b->start; 237442a0d256SVille Syrjälä a->end = b->end; 237542a0d256SVille Syrjälä } 237642a0d256SVille Syrjälä } 237742a0d256SVille Syrjälä 237842a0d256SVille Syrjälä bool skl_ddb_allocation_overlaps(const struct skl_ddb_entry *ddb, 237942a0d256SVille Syrjälä const struct skl_ddb_entry *entries, 238042a0d256SVille Syrjälä int num_entries, int ignore_idx) 238142a0d256SVille Syrjälä { 238242a0d256SVille Syrjälä int i; 238342a0d256SVille Syrjälä 238442a0d256SVille Syrjälä for (i = 0; i < num_entries; i++) { 238542a0d256SVille Syrjälä if (i != ignore_idx && 238642a0d256SVille Syrjälä skl_ddb_entries_overlap(ddb, &entries[i])) 238742a0d256SVille Syrjälä return true; 238842a0d256SVille Syrjälä } 238942a0d256SVille Syrjälä 239042a0d256SVille Syrjälä return false; 239142a0d256SVille Syrjälä } 239242a0d256SVille Syrjälä 239342a0d256SVille Syrjälä static int 239442a0d256SVille Syrjälä skl_ddb_add_affected_planes(const struct intel_crtc_state *old_crtc_state, 239542a0d256SVille Syrjälä struct intel_crtc_state *new_crtc_state) 239642a0d256SVille Syrjälä { 239742a0d256SVille Syrjälä struct intel_atomic_state *state = to_intel_atomic_state(new_crtc_state->uapi.state); 239842a0d256SVille Syrjälä struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc); 239942a0d256SVille Syrjälä struct drm_i915_private *i915 = to_i915(crtc->base.dev); 240042a0d256SVille Syrjälä struct intel_plane *plane; 240142a0d256SVille Syrjälä 240242a0d256SVille Syrjälä for_each_intel_plane_on_crtc(&i915->drm, crtc, plane) { 240342a0d256SVille Syrjälä struct intel_plane_state *plane_state; 240442a0d256SVille Syrjälä enum plane_id plane_id = plane->id; 240542a0d256SVille Syrjälä 240642a0d256SVille Syrjälä if (skl_ddb_entry_equal(&old_crtc_state->wm.skl.plane_ddb[plane_id], 240742a0d256SVille Syrjälä &new_crtc_state->wm.skl.plane_ddb[plane_id]) && 240842a0d256SVille Syrjälä skl_ddb_entry_equal(&old_crtc_state->wm.skl.plane_ddb_y[plane_id], 240942a0d256SVille Syrjälä &new_crtc_state->wm.skl.plane_ddb_y[plane_id])) 241042a0d256SVille Syrjälä continue; 241142a0d256SVille Syrjälä 241242a0d256SVille Syrjälä plane_state = intel_atomic_get_plane_state(state, plane); 241342a0d256SVille Syrjälä if (IS_ERR(plane_state)) 241442a0d256SVille Syrjälä return PTR_ERR(plane_state); 241542a0d256SVille Syrjälä 241642a0d256SVille Syrjälä new_crtc_state->update_planes |= BIT(plane_id); 24179d691c19SAndrzej Hajda new_crtc_state->async_flip_planes = 0; 24189d691c19SAndrzej Hajda new_crtc_state->do_async_flip = false; 241942a0d256SVille Syrjälä } 242042a0d256SVille Syrjälä 242142a0d256SVille Syrjälä return 0; 242242a0d256SVille Syrjälä } 242342a0d256SVille Syrjälä 242442a0d256SVille Syrjälä static u8 intel_dbuf_enabled_slices(const struct intel_dbuf_state *dbuf_state) 242542a0d256SVille Syrjälä { 242642a0d256SVille Syrjälä struct drm_i915_private *i915 = to_i915(dbuf_state->base.state->base.dev); 242742a0d256SVille Syrjälä u8 enabled_slices; 242842a0d256SVille Syrjälä enum pipe pipe; 242942a0d256SVille Syrjälä 243042a0d256SVille Syrjälä /* 243142a0d256SVille Syrjälä * FIXME: For now we always enable slice S1 as per 243242a0d256SVille Syrjälä * the Bspec display initialization sequence. 243342a0d256SVille Syrjälä */ 243442a0d256SVille Syrjälä enabled_slices = BIT(DBUF_S1); 243542a0d256SVille Syrjälä 243642a0d256SVille Syrjälä for_each_pipe(i915, pipe) 243742a0d256SVille Syrjälä enabled_slices |= dbuf_state->slices[pipe]; 243842a0d256SVille Syrjälä 243942a0d256SVille Syrjälä return enabled_slices; 244042a0d256SVille Syrjälä } 244142a0d256SVille Syrjälä 244242a0d256SVille Syrjälä static int 244342a0d256SVille Syrjälä skl_compute_ddb(struct intel_atomic_state *state) 244442a0d256SVille Syrjälä { 244542a0d256SVille Syrjälä struct drm_i915_private *i915 = to_i915(state->base.dev); 244642a0d256SVille Syrjälä const struct intel_dbuf_state *old_dbuf_state; 244742a0d256SVille Syrjälä struct intel_dbuf_state *new_dbuf_state = NULL; 244842a0d256SVille Syrjälä const struct intel_crtc_state *old_crtc_state; 244942a0d256SVille Syrjälä struct intel_crtc_state *new_crtc_state; 245042a0d256SVille Syrjälä struct intel_crtc *crtc; 245142a0d256SVille Syrjälä int ret, i; 245242a0d256SVille Syrjälä 245342a0d256SVille Syrjälä for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) { 245442a0d256SVille Syrjälä new_dbuf_state = intel_atomic_get_dbuf_state(state); 245542a0d256SVille Syrjälä if (IS_ERR(new_dbuf_state)) 245642a0d256SVille Syrjälä return PTR_ERR(new_dbuf_state); 245742a0d256SVille Syrjälä 245842a0d256SVille Syrjälä old_dbuf_state = intel_atomic_get_old_dbuf_state(state); 245942a0d256SVille Syrjälä break; 246042a0d256SVille Syrjälä } 246142a0d256SVille Syrjälä 246242a0d256SVille Syrjälä if (!new_dbuf_state) 246342a0d256SVille Syrjälä return 0; 246442a0d256SVille Syrjälä 246542a0d256SVille Syrjälä new_dbuf_state->active_pipes = 246642a0d256SVille Syrjälä intel_calc_active_pipes(state, old_dbuf_state->active_pipes); 246742a0d256SVille Syrjälä 246842a0d256SVille Syrjälä if (old_dbuf_state->active_pipes != new_dbuf_state->active_pipes) { 246942a0d256SVille Syrjälä ret = intel_atomic_lock_global_state(&new_dbuf_state->base); 247042a0d256SVille Syrjälä if (ret) 247142a0d256SVille Syrjälä return ret; 247242a0d256SVille Syrjälä } 247342a0d256SVille Syrjälä 247442a0d256SVille Syrjälä if (HAS_MBUS_JOINING(i915)) 247542a0d256SVille Syrjälä new_dbuf_state->joined_mbus = 247642a0d256SVille Syrjälä adlp_check_mbus_joined(new_dbuf_state->active_pipes); 247742a0d256SVille Syrjälä 247842a0d256SVille Syrjälä for_each_intel_crtc(&i915->drm, crtc) { 247942a0d256SVille Syrjälä enum pipe pipe = crtc->pipe; 248042a0d256SVille Syrjälä 248142a0d256SVille Syrjälä new_dbuf_state->slices[pipe] = 248242a0d256SVille Syrjälä skl_compute_dbuf_slices(crtc, new_dbuf_state->active_pipes, 248342a0d256SVille Syrjälä new_dbuf_state->joined_mbus); 248442a0d256SVille Syrjälä 248542a0d256SVille Syrjälä if (old_dbuf_state->slices[pipe] == new_dbuf_state->slices[pipe]) 248642a0d256SVille Syrjälä continue; 248742a0d256SVille Syrjälä 248842a0d256SVille Syrjälä ret = intel_atomic_lock_global_state(&new_dbuf_state->base); 248942a0d256SVille Syrjälä if (ret) 249042a0d256SVille Syrjälä return ret; 249142a0d256SVille Syrjälä } 249242a0d256SVille Syrjälä 249342a0d256SVille Syrjälä new_dbuf_state->enabled_slices = intel_dbuf_enabled_slices(new_dbuf_state); 249442a0d256SVille Syrjälä 249542a0d256SVille Syrjälä if (old_dbuf_state->enabled_slices != new_dbuf_state->enabled_slices || 249642a0d256SVille Syrjälä old_dbuf_state->joined_mbus != new_dbuf_state->joined_mbus) { 249742a0d256SVille Syrjälä ret = intel_atomic_serialize_global_state(&new_dbuf_state->base); 249842a0d256SVille Syrjälä if (ret) 249942a0d256SVille Syrjälä return ret; 250042a0d256SVille Syrjälä 250142a0d256SVille Syrjälä if (old_dbuf_state->joined_mbus != new_dbuf_state->joined_mbus) { 250242a0d256SVille Syrjälä /* TODO: Implement vblank synchronized MBUS joining changes */ 25030c316114SVille Syrjälä ret = intel_modeset_all_pipes(state, "MBUS joining change"); 250442a0d256SVille Syrjälä if (ret) 250542a0d256SVille Syrjälä return ret; 250642a0d256SVille Syrjälä } 250742a0d256SVille Syrjälä 250842a0d256SVille Syrjälä drm_dbg_kms(&i915->drm, 250942a0d256SVille Syrjälä "Enabled dbuf slices 0x%x -> 0x%x (total dbuf slices 0x%x), mbus joined? %s->%s\n", 251042a0d256SVille Syrjälä old_dbuf_state->enabled_slices, 251142a0d256SVille Syrjälä new_dbuf_state->enabled_slices, 251242a0d256SVille Syrjälä INTEL_INFO(i915)->display.dbuf.slice_mask, 251342a0d256SVille Syrjälä str_yes_no(old_dbuf_state->joined_mbus), 251442a0d256SVille Syrjälä str_yes_no(new_dbuf_state->joined_mbus)); 251542a0d256SVille Syrjälä } 251642a0d256SVille Syrjälä 251742a0d256SVille Syrjälä for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) { 251842a0d256SVille Syrjälä enum pipe pipe = crtc->pipe; 251942a0d256SVille Syrjälä 252042a0d256SVille Syrjälä new_dbuf_state->weight[pipe] = intel_crtc_ddb_weight(new_crtc_state); 252142a0d256SVille Syrjälä 252242a0d256SVille Syrjälä if (old_dbuf_state->weight[pipe] == new_dbuf_state->weight[pipe]) 252342a0d256SVille Syrjälä continue; 252442a0d256SVille Syrjälä 252542a0d256SVille Syrjälä ret = intel_atomic_lock_global_state(&new_dbuf_state->base); 252642a0d256SVille Syrjälä if (ret) 252742a0d256SVille Syrjälä return ret; 252842a0d256SVille Syrjälä } 252942a0d256SVille Syrjälä 253042a0d256SVille Syrjälä for_each_intel_crtc(&i915->drm, crtc) { 253142a0d256SVille Syrjälä ret = skl_crtc_allocate_ddb(state, crtc); 253242a0d256SVille Syrjälä if (ret) 253342a0d256SVille Syrjälä return ret; 253442a0d256SVille Syrjälä } 253542a0d256SVille Syrjälä 253642a0d256SVille Syrjälä for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, 253742a0d256SVille Syrjälä new_crtc_state, i) { 253842a0d256SVille Syrjälä ret = skl_crtc_allocate_plane_ddb(state, crtc); 253942a0d256SVille Syrjälä if (ret) 254042a0d256SVille Syrjälä return ret; 254142a0d256SVille Syrjälä 254242a0d256SVille Syrjälä ret = skl_ddb_add_affected_planes(old_crtc_state, 254342a0d256SVille Syrjälä new_crtc_state); 254442a0d256SVille Syrjälä if (ret) 254542a0d256SVille Syrjälä return ret; 254642a0d256SVille Syrjälä } 254742a0d256SVille Syrjälä 254842a0d256SVille Syrjälä return 0; 254942a0d256SVille Syrjälä } 255042a0d256SVille Syrjälä 255142a0d256SVille Syrjälä static char enast(bool enable) 255242a0d256SVille Syrjälä { 255342a0d256SVille Syrjälä return enable ? '*' : ' '; 255442a0d256SVille Syrjälä } 255542a0d256SVille Syrjälä 255642a0d256SVille Syrjälä static void 255742a0d256SVille Syrjälä skl_print_wm_changes(struct intel_atomic_state *state) 255842a0d256SVille Syrjälä { 255942a0d256SVille Syrjälä struct drm_i915_private *i915 = to_i915(state->base.dev); 256042a0d256SVille Syrjälä const struct intel_crtc_state *old_crtc_state; 256142a0d256SVille Syrjälä const struct intel_crtc_state *new_crtc_state; 256242a0d256SVille Syrjälä struct intel_plane *plane; 256342a0d256SVille Syrjälä struct intel_crtc *crtc; 256442a0d256SVille Syrjälä int i; 256542a0d256SVille Syrjälä 256642a0d256SVille Syrjälä if (!drm_debug_enabled(DRM_UT_KMS)) 256742a0d256SVille Syrjälä return; 256842a0d256SVille Syrjälä 256942a0d256SVille Syrjälä for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, 257042a0d256SVille Syrjälä new_crtc_state, i) { 257142a0d256SVille Syrjälä const struct skl_pipe_wm *old_pipe_wm, *new_pipe_wm; 257242a0d256SVille Syrjälä 257342a0d256SVille Syrjälä old_pipe_wm = &old_crtc_state->wm.skl.optimal; 257442a0d256SVille Syrjälä new_pipe_wm = &new_crtc_state->wm.skl.optimal; 257542a0d256SVille Syrjälä 257642a0d256SVille Syrjälä for_each_intel_plane_on_crtc(&i915->drm, crtc, plane) { 257742a0d256SVille Syrjälä enum plane_id plane_id = plane->id; 257842a0d256SVille Syrjälä const struct skl_ddb_entry *old, *new; 257942a0d256SVille Syrjälä 258042a0d256SVille Syrjälä old = &old_crtc_state->wm.skl.plane_ddb[plane_id]; 258142a0d256SVille Syrjälä new = &new_crtc_state->wm.skl.plane_ddb[plane_id]; 258242a0d256SVille Syrjälä 258342a0d256SVille Syrjälä if (skl_ddb_entry_equal(old, new)) 258442a0d256SVille Syrjälä continue; 258542a0d256SVille Syrjälä 258642a0d256SVille Syrjälä drm_dbg_kms(&i915->drm, 258742a0d256SVille Syrjälä "[PLANE:%d:%s] ddb (%4d - %4d) -> (%4d - %4d), size %4d -> %4d\n", 258842a0d256SVille Syrjälä plane->base.base.id, plane->base.name, 258942a0d256SVille Syrjälä old->start, old->end, new->start, new->end, 259042a0d256SVille Syrjälä skl_ddb_entry_size(old), skl_ddb_entry_size(new)); 259142a0d256SVille Syrjälä } 259242a0d256SVille Syrjälä 259342a0d256SVille Syrjälä for_each_intel_plane_on_crtc(&i915->drm, crtc, plane) { 259442a0d256SVille Syrjälä enum plane_id plane_id = plane->id; 259542a0d256SVille Syrjälä const struct skl_plane_wm *old_wm, *new_wm; 259642a0d256SVille Syrjälä 259742a0d256SVille Syrjälä old_wm = &old_pipe_wm->planes[plane_id]; 259842a0d256SVille Syrjälä new_wm = &new_pipe_wm->planes[plane_id]; 259942a0d256SVille Syrjälä 260042a0d256SVille Syrjälä if (skl_plane_wm_equals(i915, old_wm, new_wm)) 260142a0d256SVille Syrjälä continue; 260242a0d256SVille Syrjälä 260342a0d256SVille Syrjälä drm_dbg_kms(&i915->drm, 260442a0d256SVille Syrjälä "[PLANE:%d:%s] level %cwm0,%cwm1,%cwm2,%cwm3,%cwm4,%cwm5,%cwm6,%cwm7,%ctwm,%cswm,%cstwm" 260542a0d256SVille Syrjälä " -> %cwm0,%cwm1,%cwm2,%cwm3,%cwm4,%cwm5,%cwm6,%cwm7,%ctwm,%cswm,%cstwm\n", 260642a0d256SVille Syrjälä plane->base.base.id, plane->base.name, 260742a0d256SVille Syrjälä enast(old_wm->wm[0].enable), enast(old_wm->wm[1].enable), 260842a0d256SVille Syrjälä enast(old_wm->wm[2].enable), enast(old_wm->wm[3].enable), 260942a0d256SVille Syrjälä enast(old_wm->wm[4].enable), enast(old_wm->wm[5].enable), 261042a0d256SVille Syrjälä enast(old_wm->wm[6].enable), enast(old_wm->wm[7].enable), 261142a0d256SVille Syrjälä enast(old_wm->trans_wm.enable), 261242a0d256SVille Syrjälä enast(old_wm->sagv.wm0.enable), 261342a0d256SVille Syrjälä enast(old_wm->sagv.trans_wm.enable), 261442a0d256SVille Syrjälä enast(new_wm->wm[0].enable), enast(new_wm->wm[1].enable), 261542a0d256SVille Syrjälä enast(new_wm->wm[2].enable), enast(new_wm->wm[3].enable), 261642a0d256SVille Syrjälä enast(new_wm->wm[4].enable), enast(new_wm->wm[5].enable), 261742a0d256SVille Syrjälä enast(new_wm->wm[6].enable), enast(new_wm->wm[7].enable), 261842a0d256SVille Syrjälä enast(new_wm->trans_wm.enable), 261942a0d256SVille Syrjälä enast(new_wm->sagv.wm0.enable), 262042a0d256SVille Syrjälä enast(new_wm->sagv.trans_wm.enable)); 262142a0d256SVille Syrjälä 262242a0d256SVille Syrjälä drm_dbg_kms(&i915->drm, 262342a0d256SVille 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" 262442a0d256SVille 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", 262542a0d256SVille Syrjälä plane->base.base.id, plane->base.name, 262642a0d256SVille Syrjälä enast(old_wm->wm[0].ignore_lines), old_wm->wm[0].lines, 262742a0d256SVille Syrjälä enast(old_wm->wm[1].ignore_lines), old_wm->wm[1].lines, 262842a0d256SVille Syrjälä enast(old_wm->wm[2].ignore_lines), old_wm->wm[2].lines, 262942a0d256SVille Syrjälä enast(old_wm->wm[3].ignore_lines), old_wm->wm[3].lines, 263042a0d256SVille Syrjälä enast(old_wm->wm[4].ignore_lines), old_wm->wm[4].lines, 263142a0d256SVille Syrjälä enast(old_wm->wm[5].ignore_lines), old_wm->wm[5].lines, 263242a0d256SVille Syrjälä enast(old_wm->wm[6].ignore_lines), old_wm->wm[6].lines, 263342a0d256SVille Syrjälä enast(old_wm->wm[7].ignore_lines), old_wm->wm[7].lines, 263442a0d256SVille Syrjälä enast(old_wm->trans_wm.ignore_lines), old_wm->trans_wm.lines, 263542a0d256SVille Syrjälä enast(old_wm->sagv.wm0.ignore_lines), old_wm->sagv.wm0.lines, 263642a0d256SVille Syrjälä enast(old_wm->sagv.trans_wm.ignore_lines), old_wm->sagv.trans_wm.lines, 263742a0d256SVille Syrjälä enast(new_wm->wm[0].ignore_lines), new_wm->wm[0].lines, 263842a0d256SVille Syrjälä enast(new_wm->wm[1].ignore_lines), new_wm->wm[1].lines, 263942a0d256SVille Syrjälä enast(new_wm->wm[2].ignore_lines), new_wm->wm[2].lines, 264042a0d256SVille Syrjälä enast(new_wm->wm[3].ignore_lines), new_wm->wm[3].lines, 264142a0d256SVille Syrjälä enast(new_wm->wm[4].ignore_lines), new_wm->wm[4].lines, 264242a0d256SVille Syrjälä enast(new_wm->wm[5].ignore_lines), new_wm->wm[5].lines, 264342a0d256SVille Syrjälä enast(new_wm->wm[6].ignore_lines), new_wm->wm[6].lines, 264442a0d256SVille Syrjälä enast(new_wm->wm[7].ignore_lines), new_wm->wm[7].lines, 264542a0d256SVille Syrjälä enast(new_wm->trans_wm.ignore_lines), new_wm->trans_wm.lines, 264642a0d256SVille Syrjälä enast(new_wm->sagv.wm0.ignore_lines), new_wm->sagv.wm0.lines, 264742a0d256SVille Syrjälä enast(new_wm->sagv.trans_wm.ignore_lines), new_wm->sagv.trans_wm.lines); 264842a0d256SVille Syrjälä 264942a0d256SVille Syrjälä drm_dbg_kms(&i915->drm, 265042a0d256SVille Syrjälä "[PLANE:%d:%s] blocks %4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%5d" 265142a0d256SVille Syrjälä " -> %4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%5d\n", 265242a0d256SVille Syrjälä plane->base.base.id, plane->base.name, 265342a0d256SVille Syrjälä old_wm->wm[0].blocks, old_wm->wm[1].blocks, 265442a0d256SVille Syrjälä old_wm->wm[2].blocks, old_wm->wm[3].blocks, 265542a0d256SVille Syrjälä old_wm->wm[4].blocks, old_wm->wm[5].blocks, 265642a0d256SVille Syrjälä old_wm->wm[6].blocks, old_wm->wm[7].blocks, 265742a0d256SVille Syrjälä old_wm->trans_wm.blocks, 265842a0d256SVille Syrjälä old_wm->sagv.wm0.blocks, 265942a0d256SVille Syrjälä old_wm->sagv.trans_wm.blocks, 266042a0d256SVille Syrjälä new_wm->wm[0].blocks, new_wm->wm[1].blocks, 266142a0d256SVille Syrjälä new_wm->wm[2].blocks, new_wm->wm[3].blocks, 266242a0d256SVille Syrjälä new_wm->wm[4].blocks, new_wm->wm[5].blocks, 266342a0d256SVille Syrjälä new_wm->wm[6].blocks, new_wm->wm[7].blocks, 266442a0d256SVille Syrjälä new_wm->trans_wm.blocks, 266542a0d256SVille Syrjälä new_wm->sagv.wm0.blocks, 266642a0d256SVille Syrjälä new_wm->sagv.trans_wm.blocks); 266742a0d256SVille Syrjälä 266842a0d256SVille Syrjälä drm_dbg_kms(&i915->drm, 266942a0d256SVille Syrjälä "[PLANE:%d:%s] min_ddb %4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%5d" 267042a0d256SVille Syrjälä " -> %4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%5d\n", 267142a0d256SVille Syrjälä plane->base.base.id, plane->base.name, 267242a0d256SVille Syrjälä old_wm->wm[0].min_ddb_alloc, old_wm->wm[1].min_ddb_alloc, 267342a0d256SVille Syrjälä old_wm->wm[2].min_ddb_alloc, old_wm->wm[3].min_ddb_alloc, 267442a0d256SVille Syrjälä old_wm->wm[4].min_ddb_alloc, old_wm->wm[5].min_ddb_alloc, 267542a0d256SVille Syrjälä old_wm->wm[6].min_ddb_alloc, old_wm->wm[7].min_ddb_alloc, 267642a0d256SVille Syrjälä old_wm->trans_wm.min_ddb_alloc, 267742a0d256SVille Syrjälä old_wm->sagv.wm0.min_ddb_alloc, 267842a0d256SVille Syrjälä old_wm->sagv.trans_wm.min_ddb_alloc, 267942a0d256SVille Syrjälä new_wm->wm[0].min_ddb_alloc, new_wm->wm[1].min_ddb_alloc, 268042a0d256SVille Syrjälä new_wm->wm[2].min_ddb_alloc, new_wm->wm[3].min_ddb_alloc, 268142a0d256SVille Syrjälä new_wm->wm[4].min_ddb_alloc, new_wm->wm[5].min_ddb_alloc, 268242a0d256SVille Syrjälä new_wm->wm[6].min_ddb_alloc, new_wm->wm[7].min_ddb_alloc, 268342a0d256SVille Syrjälä new_wm->trans_wm.min_ddb_alloc, 268442a0d256SVille Syrjälä new_wm->sagv.wm0.min_ddb_alloc, 268542a0d256SVille Syrjälä new_wm->sagv.trans_wm.min_ddb_alloc); 268642a0d256SVille Syrjälä } 268742a0d256SVille Syrjälä } 268842a0d256SVille Syrjälä } 268942a0d256SVille Syrjälä 269042a0d256SVille Syrjälä static bool skl_plane_selected_wm_equals(struct intel_plane *plane, 269142a0d256SVille Syrjälä const struct skl_pipe_wm *old_pipe_wm, 269242a0d256SVille Syrjälä const struct skl_pipe_wm *new_pipe_wm) 269342a0d256SVille Syrjälä { 269442a0d256SVille Syrjälä struct drm_i915_private *i915 = to_i915(plane->base.dev); 26957ee6f99dSVille Syrjälä int level; 269642a0d256SVille Syrjälä 26977ee6f99dSVille Syrjälä for (level = 0; level < i915->display.wm.num_levels; level++) { 269842a0d256SVille Syrjälä /* 269942a0d256SVille Syrjälä * We don't check uv_wm as the hardware doesn't actually 270042a0d256SVille Syrjälä * use it. It only gets used for calculating the required 270142a0d256SVille Syrjälä * ddb allocation. 270242a0d256SVille Syrjälä */ 270342a0d256SVille Syrjälä if (!skl_wm_level_equals(skl_plane_wm_level(old_pipe_wm, plane->id, level), 270442a0d256SVille Syrjälä skl_plane_wm_level(new_pipe_wm, plane->id, level))) 270542a0d256SVille Syrjälä return false; 270642a0d256SVille Syrjälä } 270742a0d256SVille Syrjälä 270842a0d256SVille Syrjälä if (HAS_HW_SAGV_WM(i915)) { 270942a0d256SVille Syrjälä const struct skl_plane_wm *old_wm = &old_pipe_wm->planes[plane->id]; 271042a0d256SVille Syrjälä const struct skl_plane_wm *new_wm = &new_pipe_wm->planes[plane->id]; 271142a0d256SVille Syrjälä 271242a0d256SVille Syrjälä if (!skl_wm_level_equals(&old_wm->sagv.wm0, &new_wm->sagv.wm0) || 271342a0d256SVille Syrjälä !skl_wm_level_equals(&old_wm->sagv.trans_wm, &new_wm->sagv.trans_wm)) 271442a0d256SVille Syrjälä return false; 271542a0d256SVille Syrjälä } 271642a0d256SVille Syrjälä 271742a0d256SVille Syrjälä return skl_wm_level_equals(skl_plane_trans_wm(old_pipe_wm, plane->id), 271842a0d256SVille Syrjälä skl_plane_trans_wm(new_pipe_wm, plane->id)); 271942a0d256SVille Syrjälä } 272042a0d256SVille Syrjälä 272142a0d256SVille Syrjälä /* 272242a0d256SVille Syrjälä * To make sure the cursor watermark registers are always consistent 272342a0d256SVille Syrjälä * with our computed state the following scenario needs special 272442a0d256SVille Syrjälä * treatment: 272542a0d256SVille Syrjälä * 272642a0d256SVille Syrjälä * 1. enable cursor 272742a0d256SVille Syrjälä * 2. move cursor entirely offscreen 272842a0d256SVille Syrjälä * 3. disable cursor 272942a0d256SVille Syrjälä * 273042a0d256SVille Syrjälä * Step 2. does call .disable_plane() but does not zero the watermarks 273142a0d256SVille Syrjälä * (since we consider an offscreen cursor still active for the purposes 273242a0d256SVille Syrjälä * of watermarks). Step 3. would not normally call .disable_plane() 273342a0d256SVille Syrjälä * because the actual plane visibility isn't changing, and we don't 273442a0d256SVille Syrjälä * deallocate the cursor ddb until the pipe gets disabled. So we must 273542a0d256SVille Syrjälä * force step 3. to call .disable_plane() to update the watermark 273642a0d256SVille Syrjälä * registers properly. 273742a0d256SVille Syrjälä * 273842a0d256SVille Syrjälä * Other planes do not suffer from this issues as their watermarks are 273942a0d256SVille Syrjälä * calculated based on the actual plane visibility. The only time this 274042a0d256SVille Syrjälä * can trigger for the other planes is during the initial readout as the 274142a0d256SVille Syrjälä * default value of the watermarks registers is not zero. 274242a0d256SVille Syrjälä */ 274342a0d256SVille Syrjälä static int skl_wm_add_affected_planes(struct intel_atomic_state *state, 274442a0d256SVille Syrjälä struct intel_crtc *crtc) 274542a0d256SVille Syrjälä { 274642a0d256SVille Syrjälä struct drm_i915_private *i915 = to_i915(crtc->base.dev); 274742a0d256SVille Syrjälä const struct intel_crtc_state *old_crtc_state = 274842a0d256SVille Syrjälä intel_atomic_get_old_crtc_state(state, crtc); 274942a0d256SVille Syrjälä struct intel_crtc_state *new_crtc_state = 275042a0d256SVille Syrjälä intel_atomic_get_new_crtc_state(state, crtc); 275142a0d256SVille Syrjälä struct intel_plane *plane; 275242a0d256SVille Syrjälä 275342a0d256SVille Syrjälä for_each_intel_plane_on_crtc(&i915->drm, crtc, plane) { 275442a0d256SVille Syrjälä struct intel_plane_state *plane_state; 275542a0d256SVille Syrjälä enum plane_id plane_id = plane->id; 275642a0d256SVille Syrjälä 275742a0d256SVille Syrjälä /* 275842a0d256SVille Syrjälä * Force a full wm update for every plane on modeset. 275942a0d256SVille Syrjälä * Required because the reset value of the wm registers 276042a0d256SVille Syrjälä * is non-zero, whereas we want all disabled planes to 276142a0d256SVille Syrjälä * have zero watermarks. So if we turn off the relevant 276242a0d256SVille Syrjälä * power well the hardware state will go out of sync 276342a0d256SVille Syrjälä * with the software state. 276442a0d256SVille Syrjälä */ 2765882ecff7SVille Syrjälä if (!intel_crtc_needs_modeset(new_crtc_state) && 276642a0d256SVille Syrjälä skl_plane_selected_wm_equals(plane, 276742a0d256SVille Syrjälä &old_crtc_state->wm.skl.optimal, 276842a0d256SVille Syrjälä &new_crtc_state->wm.skl.optimal)) 276942a0d256SVille Syrjälä continue; 277042a0d256SVille Syrjälä 277142a0d256SVille Syrjälä plane_state = intel_atomic_get_plane_state(state, plane); 277242a0d256SVille Syrjälä if (IS_ERR(plane_state)) 277342a0d256SVille Syrjälä return PTR_ERR(plane_state); 277442a0d256SVille Syrjälä 277542a0d256SVille Syrjälä new_crtc_state->update_planes |= BIT(plane_id); 27769d691c19SAndrzej Hajda new_crtc_state->async_flip_planes = 0; 27779d691c19SAndrzej Hajda new_crtc_state->do_async_flip = false; 277842a0d256SVille Syrjälä } 277942a0d256SVille Syrjälä 278042a0d256SVille Syrjälä return 0; 278142a0d256SVille Syrjälä } 278242a0d256SVille Syrjälä 278342a0d256SVille Syrjälä static int 278442a0d256SVille Syrjälä skl_compute_wm(struct intel_atomic_state *state) 278542a0d256SVille Syrjälä { 278642a0d256SVille Syrjälä struct intel_crtc *crtc; 278742a0d256SVille Syrjälä struct intel_crtc_state *new_crtc_state; 278842a0d256SVille Syrjälä int ret, i; 278942a0d256SVille Syrjälä 279042a0d256SVille Syrjälä for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) { 279142a0d256SVille Syrjälä ret = skl_build_pipe_wm(state, crtc); 279242a0d256SVille Syrjälä if (ret) 279342a0d256SVille Syrjälä return ret; 279442a0d256SVille Syrjälä } 279542a0d256SVille Syrjälä 279642a0d256SVille Syrjälä ret = skl_compute_ddb(state); 279742a0d256SVille Syrjälä if (ret) 279842a0d256SVille Syrjälä return ret; 279942a0d256SVille Syrjälä 280042a0d256SVille Syrjälä ret = intel_compute_sagv_mask(state); 280142a0d256SVille Syrjälä if (ret) 280242a0d256SVille Syrjälä return ret; 280342a0d256SVille Syrjälä 280442a0d256SVille Syrjälä /* 280542a0d256SVille Syrjälä * skl_compute_ddb() will have adjusted the final watermarks 280642a0d256SVille Syrjälä * based on how much ddb is available. Now we can actually 280742a0d256SVille Syrjälä * check if the final watermarks changed. 280842a0d256SVille Syrjälä */ 280942a0d256SVille Syrjälä for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) { 281042a0d256SVille Syrjälä ret = skl_wm_add_affected_planes(state, crtc); 281142a0d256SVille Syrjälä if (ret) 281242a0d256SVille Syrjälä return ret; 281342a0d256SVille Syrjälä } 281442a0d256SVille Syrjälä 281542a0d256SVille Syrjälä skl_print_wm_changes(state); 281642a0d256SVille Syrjälä 281742a0d256SVille Syrjälä return 0; 281842a0d256SVille Syrjälä } 281942a0d256SVille Syrjälä 282042a0d256SVille Syrjälä static void skl_wm_level_from_reg_val(u32 val, struct skl_wm_level *level) 282142a0d256SVille Syrjälä { 282242a0d256SVille Syrjälä level->enable = val & PLANE_WM_EN; 282342a0d256SVille Syrjälä level->ignore_lines = val & PLANE_WM_IGNORE_LINES; 282442a0d256SVille Syrjälä level->blocks = REG_FIELD_GET(PLANE_WM_BLOCKS_MASK, val); 282542a0d256SVille Syrjälä level->lines = REG_FIELD_GET(PLANE_WM_LINES_MASK, val); 282642a0d256SVille Syrjälä } 282742a0d256SVille Syrjälä 282842a0d256SVille Syrjälä static void skl_pipe_wm_get_hw_state(struct intel_crtc *crtc, 282942a0d256SVille Syrjälä struct skl_pipe_wm *out) 283042a0d256SVille Syrjälä { 283142a0d256SVille Syrjälä struct drm_i915_private *i915 = to_i915(crtc->base.dev); 283242a0d256SVille Syrjälä enum pipe pipe = crtc->pipe; 283342a0d256SVille Syrjälä enum plane_id plane_id; 28347ee6f99dSVille Syrjälä int level; 283542a0d256SVille Syrjälä u32 val; 283642a0d256SVille Syrjälä 283742a0d256SVille Syrjälä for_each_plane_id_on_crtc(crtc, plane_id) { 283842a0d256SVille Syrjälä struct skl_plane_wm *wm = &out->planes[plane_id]; 283942a0d256SVille Syrjälä 28407ee6f99dSVille Syrjälä for (level = 0; level < i915->display.wm.num_levels; level++) { 284142a0d256SVille Syrjälä if (plane_id != PLANE_CURSOR) 284200136429SJani Nikula val = intel_de_read(i915, PLANE_WM(pipe, plane_id, level)); 284342a0d256SVille Syrjälä else 284400136429SJani Nikula val = intel_de_read(i915, CUR_WM(pipe, level)); 284542a0d256SVille Syrjälä 284642a0d256SVille Syrjälä skl_wm_level_from_reg_val(val, &wm->wm[level]); 284742a0d256SVille Syrjälä } 284842a0d256SVille Syrjälä 284942a0d256SVille Syrjälä if (plane_id != PLANE_CURSOR) 285000136429SJani Nikula val = intel_de_read(i915, PLANE_WM_TRANS(pipe, plane_id)); 285142a0d256SVille Syrjälä else 285200136429SJani Nikula val = intel_de_read(i915, CUR_WM_TRANS(pipe)); 285342a0d256SVille Syrjälä 285442a0d256SVille Syrjälä skl_wm_level_from_reg_val(val, &wm->trans_wm); 285542a0d256SVille Syrjälä 285642a0d256SVille Syrjälä if (HAS_HW_SAGV_WM(i915)) { 285742a0d256SVille Syrjälä if (plane_id != PLANE_CURSOR) 285800136429SJani Nikula val = intel_de_read(i915, PLANE_WM_SAGV(pipe, plane_id)); 285942a0d256SVille Syrjälä else 286000136429SJani Nikula val = intel_de_read(i915, CUR_WM_SAGV(pipe)); 286142a0d256SVille Syrjälä 286242a0d256SVille Syrjälä skl_wm_level_from_reg_val(val, &wm->sagv.wm0); 286342a0d256SVille Syrjälä 286442a0d256SVille Syrjälä if (plane_id != PLANE_CURSOR) 286500136429SJani Nikula val = intel_de_read(i915, PLANE_WM_SAGV_TRANS(pipe, plane_id)); 286642a0d256SVille Syrjälä else 286700136429SJani Nikula val = intel_de_read(i915, CUR_WM_SAGV_TRANS(pipe)); 286842a0d256SVille Syrjälä 286942a0d256SVille Syrjälä skl_wm_level_from_reg_val(val, &wm->sagv.trans_wm); 287042a0d256SVille Syrjälä } else if (DISPLAY_VER(i915) >= 12) { 287142a0d256SVille Syrjälä wm->sagv.wm0 = wm->wm[0]; 287242a0d256SVille Syrjälä wm->sagv.trans_wm = wm->trans_wm; 287342a0d256SVille Syrjälä } 287442a0d256SVille Syrjälä } 287542a0d256SVille Syrjälä } 287642a0d256SVille Syrjälä 28770e7a16f9SJani Nikula static void skl_wm_get_hw_state(struct drm_i915_private *i915) 287842a0d256SVille Syrjälä { 287942a0d256SVille Syrjälä struct intel_dbuf_state *dbuf_state = 288042a0d256SVille Syrjälä to_intel_dbuf_state(i915->display.dbuf.obj.state); 288142a0d256SVille Syrjälä struct intel_crtc *crtc; 288242a0d256SVille Syrjälä 288342a0d256SVille Syrjälä if (HAS_MBUS_JOINING(i915)) 288442a0d256SVille Syrjälä dbuf_state->joined_mbus = intel_de_read(i915, MBUS_CTL) & MBUS_JOIN; 288542a0d256SVille Syrjälä 288642a0d256SVille Syrjälä for_each_intel_crtc(&i915->drm, crtc) { 288742a0d256SVille Syrjälä struct intel_crtc_state *crtc_state = 288842a0d256SVille Syrjälä to_intel_crtc_state(crtc->base.state); 288942a0d256SVille Syrjälä enum pipe pipe = crtc->pipe; 289042a0d256SVille Syrjälä unsigned int mbus_offset; 289142a0d256SVille Syrjälä enum plane_id plane_id; 289242a0d256SVille Syrjälä u8 slices; 289342a0d256SVille Syrjälä 289442a0d256SVille Syrjälä memset(&crtc_state->wm.skl.optimal, 0, 289542a0d256SVille Syrjälä sizeof(crtc_state->wm.skl.optimal)); 289642a0d256SVille Syrjälä if (crtc_state->hw.active) 289742a0d256SVille Syrjälä skl_pipe_wm_get_hw_state(crtc, &crtc_state->wm.skl.optimal); 289842a0d256SVille Syrjälä crtc_state->wm.skl.raw = crtc_state->wm.skl.optimal; 289942a0d256SVille Syrjälä 290042a0d256SVille Syrjälä memset(&dbuf_state->ddb[pipe], 0, sizeof(dbuf_state->ddb[pipe])); 290142a0d256SVille Syrjälä 290242a0d256SVille Syrjälä for_each_plane_id_on_crtc(crtc, plane_id) { 290342a0d256SVille Syrjälä struct skl_ddb_entry *ddb = 290442a0d256SVille Syrjälä &crtc_state->wm.skl.plane_ddb[plane_id]; 290542a0d256SVille Syrjälä struct skl_ddb_entry *ddb_y = 290642a0d256SVille Syrjälä &crtc_state->wm.skl.plane_ddb_y[plane_id]; 290742a0d256SVille Syrjälä 290842a0d256SVille Syrjälä if (!crtc_state->hw.active) 290942a0d256SVille Syrjälä continue; 291042a0d256SVille Syrjälä 291142a0d256SVille Syrjälä skl_ddb_get_hw_plane_state(i915, crtc->pipe, 291242a0d256SVille Syrjälä plane_id, ddb, ddb_y); 291342a0d256SVille Syrjälä 291442a0d256SVille Syrjälä skl_ddb_entry_union(&dbuf_state->ddb[pipe], ddb); 291542a0d256SVille Syrjälä skl_ddb_entry_union(&dbuf_state->ddb[pipe], ddb_y); 291642a0d256SVille Syrjälä } 291742a0d256SVille Syrjälä 291842a0d256SVille Syrjälä dbuf_state->weight[pipe] = intel_crtc_ddb_weight(crtc_state); 291942a0d256SVille Syrjälä 292042a0d256SVille Syrjälä /* 292142a0d256SVille Syrjälä * Used for checking overlaps, so we need absolute 292242a0d256SVille Syrjälä * offsets instead of MBUS relative offsets. 292342a0d256SVille Syrjälä */ 292442a0d256SVille Syrjälä slices = skl_compute_dbuf_slices(crtc, dbuf_state->active_pipes, 292542a0d256SVille Syrjälä dbuf_state->joined_mbus); 292642a0d256SVille Syrjälä mbus_offset = mbus_ddb_offset(i915, slices); 292742a0d256SVille Syrjälä crtc_state->wm.skl.ddb.start = mbus_offset + dbuf_state->ddb[pipe].start; 292842a0d256SVille Syrjälä crtc_state->wm.skl.ddb.end = mbus_offset + dbuf_state->ddb[pipe].end; 292942a0d256SVille Syrjälä 293042a0d256SVille Syrjälä /* The slices actually used by the planes on the pipe */ 293142a0d256SVille Syrjälä dbuf_state->slices[pipe] = 293242a0d256SVille Syrjälä skl_ddb_dbuf_slice_mask(i915, &crtc_state->wm.skl.ddb); 293342a0d256SVille Syrjälä 293442a0d256SVille Syrjälä drm_dbg_kms(&i915->drm, 293542a0d256SVille Syrjälä "[CRTC:%d:%s] dbuf slices 0x%x, ddb (%d - %d), active pipes 0x%x, mbus joined: %s\n", 293642a0d256SVille Syrjälä crtc->base.base.id, crtc->base.name, 293742a0d256SVille Syrjälä dbuf_state->slices[pipe], dbuf_state->ddb[pipe].start, 293842a0d256SVille Syrjälä dbuf_state->ddb[pipe].end, dbuf_state->active_pipes, 293942a0d256SVille Syrjälä str_yes_no(dbuf_state->joined_mbus)); 294042a0d256SVille Syrjälä } 294142a0d256SVille Syrjälä 294242a0d256SVille Syrjälä dbuf_state->enabled_slices = i915->display.dbuf.enabled_slices; 294342a0d256SVille Syrjälä } 294442a0d256SVille Syrjälä 294542a0d256SVille Syrjälä static bool skl_dbuf_is_misconfigured(struct drm_i915_private *i915) 294642a0d256SVille Syrjälä { 294742a0d256SVille Syrjälä const struct intel_dbuf_state *dbuf_state = 294842a0d256SVille Syrjälä to_intel_dbuf_state(i915->display.dbuf.obj.state); 294942a0d256SVille Syrjälä struct skl_ddb_entry entries[I915_MAX_PIPES] = {}; 295042a0d256SVille Syrjälä struct intel_crtc *crtc; 295142a0d256SVille Syrjälä 295242a0d256SVille Syrjälä for_each_intel_crtc(&i915->drm, crtc) { 295342a0d256SVille Syrjälä const struct intel_crtc_state *crtc_state = 295442a0d256SVille Syrjälä to_intel_crtc_state(crtc->base.state); 295542a0d256SVille Syrjälä 295642a0d256SVille Syrjälä entries[crtc->pipe] = crtc_state->wm.skl.ddb; 295742a0d256SVille Syrjälä } 295842a0d256SVille Syrjälä 295942a0d256SVille Syrjälä for_each_intel_crtc(&i915->drm, crtc) { 296042a0d256SVille Syrjälä const struct intel_crtc_state *crtc_state = 296142a0d256SVille Syrjälä to_intel_crtc_state(crtc->base.state); 296242a0d256SVille Syrjälä u8 slices; 296342a0d256SVille Syrjälä 296442a0d256SVille Syrjälä slices = skl_compute_dbuf_slices(crtc, dbuf_state->active_pipes, 296542a0d256SVille Syrjälä dbuf_state->joined_mbus); 296642a0d256SVille Syrjälä if (dbuf_state->slices[crtc->pipe] & ~slices) 296742a0d256SVille Syrjälä return true; 296842a0d256SVille Syrjälä 296942a0d256SVille Syrjälä if (skl_ddb_allocation_overlaps(&crtc_state->wm.skl.ddb, entries, 297042a0d256SVille Syrjälä I915_MAX_PIPES, crtc->pipe)) 297142a0d256SVille Syrjälä return true; 297242a0d256SVille Syrjälä } 297342a0d256SVille Syrjälä 297442a0d256SVille Syrjälä return false; 297542a0d256SVille Syrjälä } 297642a0d256SVille Syrjälä 29770e7a16f9SJani Nikula static void skl_wm_sanitize(struct drm_i915_private *i915) 297842a0d256SVille Syrjälä { 297942a0d256SVille Syrjälä struct intel_crtc *crtc; 298042a0d256SVille Syrjälä 298142a0d256SVille Syrjälä /* 298242a0d256SVille Syrjälä * On TGL/RKL (at least) the BIOS likes to assign the planes 298342a0d256SVille Syrjälä * to the wrong DBUF slices. This will cause an infinite loop 298442a0d256SVille Syrjälä * in skl_commit_modeset_enables() as it can't find a way to 298542a0d256SVille Syrjälä * transition between the old bogus DBUF layout to the new 298642a0d256SVille Syrjälä * proper DBUF layout without DBUF allocation overlaps between 298742a0d256SVille Syrjälä * the planes (which cannot be allowed or else the hardware 298842a0d256SVille Syrjälä * may hang). If we detect a bogus DBUF layout just turn off 298942a0d256SVille Syrjälä * all the planes so that skl_commit_modeset_enables() can 299042a0d256SVille Syrjälä * simply ignore them. 299142a0d256SVille Syrjälä */ 299242a0d256SVille Syrjälä if (!skl_dbuf_is_misconfigured(i915)) 299342a0d256SVille Syrjälä return; 299442a0d256SVille Syrjälä 299542a0d256SVille Syrjälä drm_dbg_kms(&i915->drm, "BIOS has misprogrammed the DBUF, disabling all planes\n"); 299642a0d256SVille Syrjälä 299742a0d256SVille Syrjälä for_each_intel_crtc(&i915->drm, crtc) { 299842a0d256SVille Syrjälä struct intel_plane *plane = to_intel_plane(crtc->base.primary); 299942a0d256SVille Syrjälä const struct intel_plane_state *plane_state = 300042a0d256SVille Syrjälä to_intel_plane_state(plane->base.state); 300142a0d256SVille Syrjälä struct intel_crtc_state *crtc_state = 300242a0d256SVille Syrjälä to_intel_crtc_state(crtc->base.state); 300342a0d256SVille Syrjälä 300442a0d256SVille Syrjälä if (plane_state->uapi.visible) 300542a0d256SVille Syrjälä intel_plane_disable_noatomic(crtc, plane); 300642a0d256SVille Syrjälä 300742a0d256SVille Syrjälä drm_WARN_ON(&i915->drm, crtc_state->active_planes != 0); 300842a0d256SVille Syrjälä 300942a0d256SVille Syrjälä memset(&crtc_state->wm.skl.ddb, 0, sizeof(crtc_state->wm.skl.ddb)); 301042a0d256SVille Syrjälä } 301142a0d256SVille Syrjälä } 301242a0d256SVille Syrjälä 30130e7a16f9SJani Nikula static void skl_wm_get_hw_state_and_sanitize(struct drm_i915_private *i915) 30140e7a16f9SJani Nikula { 30150e7a16f9SJani Nikula skl_wm_get_hw_state(i915); 30160e7a16f9SJani Nikula skl_wm_sanitize(i915); 30170e7a16f9SJani Nikula } 30180e7a16f9SJani Nikula 301942a0d256SVille Syrjälä void intel_wm_state_verify(struct intel_crtc *crtc, 302042a0d256SVille Syrjälä struct intel_crtc_state *new_crtc_state) 302142a0d256SVille Syrjälä { 302242a0d256SVille Syrjälä struct drm_i915_private *i915 = to_i915(crtc->base.dev); 302342a0d256SVille Syrjälä struct skl_hw_state { 302442a0d256SVille Syrjälä struct skl_ddb_entry ddb[I915_MAX_PLANES]; 302542a0d256SVille Syrjälä struct skl_ddb_entry ddb_y[I915_MAX_PLANES]; 302642a0d256SVille Syrjälä struct skl_pipe_wm wm; 302742a0d256SVille Syrjälä } *hw; 302842a0d256SVille Syrjälä const struct skl_pipe_wm *sw_wm = &new_crtc_state->wm.skl.optimal; 302942a0d256SVille Syrjälä struct intel_plane *plane; 303042a0d256SVille Syrjälä u8 hw_enabled_slices; 30317ee6f99dSVille Syrjälä int level; 303242a0d256SVille Syrjälä 303342a0d256SVille Syrjälä if (DISPLAY_VER(i915) < 9 || !new_crtc_state->hw.active) 303442a0d256SVille Syrjälä return; 303542a0d256SVille Syrjälä 303642a0d256SVille Syrjälä hw = kzalloc(sizeof(*hw), GFP_KERNEL); 303742a0d256SVille Syrjälä if (!hw) 303842a0d256SVille Syrjälä return; 303942a0d256SVille Syrjälä 304042a0d256SVille Syrjälä skl_pipe_wm_get_hw_state(crtc, &hw->wm); 304142a0d256SVille Syrjälä 304242a0d256SVille Syrjälä skl_pipe_ddb_get_hw_state(crtc, hw->ddb, hw->ddb_y); 304342a0d256SVille Syrjälä 304442a0d256SVille Syrjälä hw_enabled_slices = intel_enabled_dbuf_slices_mask(i915); 304542a0d256SVille Syrjälä 304642a0d256SVille Syrjälä if (DISPLAY_VER(i915) >= 11 && 304742a0d256SVille Syrjälä hw_enabled_slices != i915->display.dbuf.enabled_slices) 304842a0d256SVille Syrjälä drm_err(&i915->drm, 304942a0d256SVille Syrjälä "mismatch in DBUF Slices (expected 0x%x, got 0x%x)\n", 305042a0d256SVille Syrjälä i915->display.dbuf.enabled_slices, 305142a0d256SVille Syrjälä hw_enabled_slices); 305242a0d256SVille Syrjälä 305342a0d256SVille Syrjälä for_each_intel_plane_on_crtc(&i915->drm, crtc, plane) { 305442a0d256SVille Syrjälä const struct skl_ddb_entry *hw_ddb_entry, *sw_ddb_entry; 305542a0d256SVille Syrjälä const struct skl_wm_level *hw_wm_level, *sw_wm_level; 305642a0d256SVille Syrjälä 305742a0d256SVille Syrjälä /* Watermarks */ 30587ee6f99dSVille Syrjälä for (level = 0; level < i915->display.wm.num_levels; level++) { 305942a0d256SVille Syrjälä hw_wm_level = &hw->wm.planes[plane->id].wm[level]; 306042a0d256SVille Syrjälä sw_wm_level = skl_plane_wm_level(sw_wm, plane->id, level); 306142a0d256SVille Syrjälä 306242a0d256SVille Syrjälä if (skl_wm_level_equals(hw_wm_level, sw_wm_level)) 306342a0d256SVille Syrjälä continue; 306442a0d256SVille Syrjälä 306542a0d256SVille Syrjälä drm_err(&i915->drm, 306642a0d256SVille Syrjälä "[PLANE:%d:%s] mismatch in WM%d (expected e=%d b=%u l=%u, got e=%d b=%u l=%u)\n", 306742a0d256SVille Syrjälä plane->base.base.id, plane->base.name, level, 306842a0d256SVille Syrjälä sw_wm_level->enable, 306942a0d256SVille Syrjälä sw_wm_level->blocks, 307042a0d256SVille Syrjälä sw_wm_level->lines, 307142a0d256SVille Syrjälä hw_wm_level->enable, 307242a0d256SVille Syrjälä hw_wm_level->blocks, 307342a0d256SVille Syrjälä hw_wm_level->lines); 307442a0d256SVille Syrjälä } 307542a0d256SVille Syrjälä 307642a0d256SVille Syrjälä hw_wm_level = &hw->wm.planes[plane->id].trans_wm; 307742a0d256SVille Syrjälä sw_wm_level = skl_plane_trans_wm(sw_wm, plane->id); 307842a0d256SVille Syrjälä 307942a0d256SVille Syrjälä if (!skl_wm_level_equals(hw_wm_level, sw_wm_level)) { 308042a0d256SVille Syrjälä drm_err(&i915->drm, 308142a0d256SVille Syrjälä "[PLANE:%d:%s] mismatch in trans WM (expected e=%d b=%u l=%u, got e=%d b=%u l=%u)\n", 308242a0d256SVille Syrjälä plane->base.base.id, plane->base.name, 308342a0d256SVille Syrjälä sw_wm_level->enable, 308442a0d256SVille Syrjälä sw_wm_level->blocks, 308542a0d256SVille Syrjälä sw_wm_level->lines, 308642a0d256SVille Syrjälä hw_wm_level->enable, 308742a0d256SVille Syrjälä hw_wm_level->blocks, 308842a0d256SVille Syrjälä hw_wm_level->lines); 308942a0d256SVille Syrjälä } 309042a0d256SVille Syrjälä 309142a0d256SVille Syrjälä hw_wm_level = &hw->wm.planes[plane->id].sagv.wm0; 309242a0d256SVille Syrjälä sw_wm_level = &sw_wm->planes[plane->id].sagv.wm0; 309342a0d256SVille Syrjälä 309442a0d256SVille Syrjälä if (HAS_HW_SAGV_WM(i915) && 309542a0d256SVille Syrjälä !skl_wm_level_equals(hw_wm_level, sw_wm_level)) { 309642a0d256SVille Syrjälä drm_err(&i915->drm, 309742a0d256SVille Syrjälä "[PLANE:%d:%s] mismatch in SAGV WM (expected e=%d b=%u l=%u, got e=%d b=%u l=%u)\n", 309842a0d256SVille Syrjälä plane->base.base.id, plane->base.name, 309942a0d256SVille Syrjälä sw_wm_level->enable, 310042a0d256SVille Syrjälä sw_wm_level->blocks, 310142a0d256SVille Syrjälä sw_wm_level->lines, 310242a0d256SVille Syrjälä hw_wm_level->enable, 310342a0d256SVille Syrjälä hw_wm_level->blocks, 310442a0d256SVille Syrjälä hw_wm_level->lines); 310542a0d256SVille Syrjälä } 310642a0d256SVille Syrjälä 310742a0d256SVille Syrjälä hw_wm_level = &hw->wm.planes[plane->id].sagv.trans_wm; 310842a0d256SVille Syrjälä sw_wm_level = &sw_wm->planes[plane->id].sagv.trans_wm; 310942a0d256SVille Syrjälä 311042a0d256SVille Syrjälä if (HAS_HW_SAGV_WM(i915) && 311142a0d256SVille Syrjälä !skl_wm_level_equals(hw_wm_level, sw_wm_level)) { 311242a0d256SVille Syrjälä drm_err(&i915->drm, 311342a0d256SVille 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", 311442a0d256SVille Syrjälä plane->base.base.id, plane->base.name, 311542a0d256SVille Syrjälä sw_wm_level->enable, 311642a0d256SVille Syrjälä sw_wm_level->blocks, 311742a0d256SVille Syrjälä sw_wm_level->lines, 311842a0d256SVille Syrjälä hw_wm_level->enable, 311942a0d256SVille Syrjälä hw_wm_level->blocks, 312042a0d256SVille Syrjälä hw_wm_level->lines); 312142a0d256SVille Syrjälä } 312242a0d256SVille Syrjälä 312342a0d256SVille Syrjälä /* DDB */ 312442a0d256SVille Syrjälä hw_ddb_entry = &hw->ddb[PLANE_CURSOR]; 312542a0d256SVille Syrjälä sw_ddb_entry = &new_crtc_state->wm.skl.plane_ddb[PLANE_CURSOR]; 312642a0d256SVille Syrjälä 312742a0d256SVille Syrjälä if (!skl_ddb_entry_equal(hw_ddb_entry, sw_ddb_entry)) { 312842a0d256SVille Syrjälä drm_err(&i915->drm, 312942a0d256SVille Syrjälä "[PLANE:%d:%s] mismatch in DDB (expected (%u,%u), found (%u,%u))\n", 313042a0d256SVille Syrjälä plane->base.base.id, plane->base.name, 313142a0d256SVille Syrjälä sw_ddb_entry->start, sw_ddb_entry->end, 313242a0d256SVille Syrjälä hw_ddb_entry->start, hw_ddb_entry->end); 313342a0d256SVille Syrjälä } 313442a0d256SVille Syrjälä } 313542a0d256SVille Syrjälä 313642a0d256SVille Syrjälä kfree(hw); 313742a0d256SVille Syrjälä } 313842a0d256SVille Syrjälä 313923fbdb07SJani Nikula bool skl_watermark_ipc_enabled(struct drm_i915_private *i915) 314023fbdb07SJani Nikula { 314170296670SJani Nikula return i915->display.wm.ipc_enabled; 314223fbdb07SJani Nikula } 314323fbdb07SJani Nikula 314423fbdb07SJani Nikula void skl_watermark_ipc_update(struct drm_i915_private *i915) 314542a0d256SVille Syrjälä { 314642a0d256SVille Syrjälä if (!HAS_IPC(i915)) 314742a0d256SVille Syrjälä return; 314842a0d256SVille Syrjälä 314900136429SJani Nikula intel_de_rmw(i915, DISP_ARB_CTL2, DISP_IPC_ENABLE, 3150c73cdd12SJani Nikula skl_watermark_ipc_enabled(i915) ? DISP_IPC_ENABLE : 0); 315142a0d256SVille Syrjälä } 315242a0d256SVille Syrjälä 315323fbdb07SJani Nikula static bool skl_watermark_ipc_can_enable(struct drm_i915_private *i915) 315442a0d256SVille Syrjälä { 315542a0d256SVille Syrjälä /* Display WA #0477 WaDisableIPC: skl */ 315642a0d256SVille Syrjälä if (IS_SKYLAKE(i915)) 315742a0d256SVille Syrjälä return false; 315842a0d256SVille Syrjälä 315942a0d256SVille Syrjälä /* Display WA #1141: SKL:all KBL:all CFL */ 316042a0d256SVille Syrjälä if (IS_KABYLAKE(i915) || 316142a0d256SVille Syrjälä IS_COFFEELAKE(i915) || 316242a0d256SVille Syrjälä IS_COMETLAKE(i915)) 316342a0d256SVille Syrjälä return i915->dram_info.symmetric_memory; 316442a0d256SVille Syrjälä 316542a0d256SVille Syrjälä return true; 316642a0d256SVille Syrjälä } 316742a0d256SVille Syrjälä 316823fbdb07SJani Nikula void skl_watermark_ipc_init(struct drm_i915_private *i915) 316942a0d256SVille Syrjälä { 317042a0d256SVille Syrjälä if (!HAS_IPC(i915)) 317142a0d256SVille Syrjälä return; 317242a0d256SVille Syrjälä 317370296670SJani Nikula i915->display.wm.ipc_enabled = skl_watermark_ipc_can_enable(i915); 317442a0d256SVille Syrjälä 317523fbdb07SJani Nikula skl_watermark_ipc_update(i915); 317642a0d256SVille Syrjälä } 317742a0d256SVille Syrjälä 317842a0d256SVille Syrjälä static void 317942a0d256SVille Syrjälä adjust_wm_latency(struct drm_i915_private *i915, 31807ee6f99dSVille Syrjälä u16 wm[], int num_levels, int read_latency) 318142a0d256SVille Syrjälä { 318242a0d256SVille Syrjälä bool wm_lv_0_adjust_needed = i915->dram_info.wm_lv_0_adjust_needed; 318342a0d256SVille Syrjälä int i, level; 318442a0d256SVille Syrjälä 318542a0d256SVille Syrjälä /* 318642a0d256SVille Syrjälä * If a level n (n > 1) has a 0us latency, all levels m (m >= n) 318742a0d256SVille Syrjälä * need to be disabled. We make sure to sanitize the values out 318842a0d256SVille Syrjälä * of the punit to satisfy this requirement. 318942a0d256SVille Syrjälä */ 31907ee6f99dSVille Syrjälä for (level = 1; level < num_levels; level++) { 319142a0d256SVille Syrjälä if (wm[level] == 0) { 31927ee6f99dSVille Syrjälä for (i = level + 1; i < num_levels; i++) 319342a0d256SVille Syrjälä wm[i] = 0; 319442a0d256SVille Syrjälä 31957ee6f99dSVille Syrjälä num_levels = level; 319642a0d256SVille Syrjälä break; 319742a0d256SVille Syrjälä } 319842a0d256SVille Syrjälä } 319942a0d256SVille Syrjälä 320042a0d256SVille Syrjälä /* 320142a0d256SVille Syrjälä * WaWmMemoryReadLatency 320242a0d256SVille Syrjälä * 320342a0d256SVille Syrjälä * punit doesn't take into account the read latency so we need 320442a0d256SVille Syrjälä * to add proper adjustement to each valid level we retrieve 320542a0d256SVille Syrjälä * from the punit when level 0 response data is 0us. 320642a0d256SVille Syrjälä */ 320742a0d256SVille Syrjälä if (wm[0] == 0) { 32087ee6f99dSVille Syrjälä for (level = 0; level < num_levels; level++) 320942a0d256SVille Syrjälä wm[level] += read_latency; 321042a0d256SVille Syrjälä } 321142a0d256SVille Syrjälä 321242a0d256SVille Syrjälä /* 321342a0d256SVille Syrjälä * WA Level-0 adjustment for 16GB DIMMs: SKL+ 321442a0d256SVille Syrjälä * If we could not get dimm info enable this WA to prevent from 321542a0d256SVille Syrjälä * any underrun. If not able to get Dimm info assume 16GB dimm 321642a0d256SVille Syrjälä * to avoid any underrun. 321742a0d256SVille Syrjälä */ 321842a0d256SVille Syrjälä if (wm_lv_0_adjust_needed) 321942a0d256SVille Syrjälä wm[0] += 1; 322042a0d256SVille Syrjälä } 322142a0d256SVille Syrjälä 322242a0d256SVille Syrjälä static void mtl_read_wm_latency(struct drm_i915_private *i915, u16 wm[]) 322342a0d256SVille Syrjälä { 32247ee6f99dSVille Syrjälä int num_levels = i915->display.wm.num_levels; 322542a0d256SVille Syrjälä u32 val; 322642a0d256SVille Syrjälä 322700136429SJani Nikula val = intel_de_read(i915, MTL_LATENCY_LP0_LP1); 322842a0d256SVille Syrjälä wm[0] = REG_FIELD_GET(MTL_LATENCY_LEVEL_EVEN_MASK, val); 322942a0d256SVille Syrjälä wm[1] = REG_FIELD_GET(MTL_LATENCY_LEVEL_ODD_MASK, val); 323042a0d256SVille Syrjälä 323100136429SJani Nikula val = intel_de_read(i915, MTL_LATENCY_LP2_LP3); 323242a0d256SVille Syrjälä wm[2] = REG_FIELD_GET(MTL_LATENCY_LEVEL_EVEN_MASK, val); 323342a0d256SVille Syrjälä wm[3] = REG_FIELD_GET(MTL_LATENCY_LEVEL_ODD_MASK, val); 323442a0d256SVille Syrjälä 323500136429SJani Nikula val = intel_de_read(i915, MTL_LATENCY_LP4_LP5); 323642a0d256SVille Syrjälä wm[4] = REG_FIELD_GET(MTL_LATENCY_LEVEL_EVEN_MASK, val); 323742a0d256SVille Syrjälä wm[5] = REG_FIELD_GET(MTL_LATENCY_LEVEL_ODD_MASK, val); 323842a0d256SVille Syrjälä 32397ee6f99dSVille Syrjälä adjust_wm_latency(i915, wm, num_levels, 6); 324042a0d256SVille Syrjälä } 324142a0d256SVille Syrjälä 324242a0d256SVille Syrjälä static void skl_read_wm_latency(struct drm_i915_private *i915, u16 wm[]) 324342a0d256SVille Syrjälä { 32447ee6f99dSVille Syrjälä int num_levels = i915->display.wm.num_levels; 324542a0d256SVille Syrjälä int read_latency = DISPLAY_VER(i915) >= 12 ? 3 : 2; 324642a0d256SVille Syrjälä int mult = IS_DG2(i915) ? 2 : 1; 324742a0d256SVille Syrjälä u32 val; 324842a0d256SVille Syrjälä int ret; 324942a0d256SVille Syrjälä 325042a0d256SVille Syrjälä /* read the first set of memory latencies[0:3] */ 325142a0d256SVille Syrjälä val = 0; /* data0 to be programmed to 0 for first set */ 325242a0d256SVille Syrjälä ret = snb_pcode_read(&i915->uncore, GEN9_PCODE_READ_MEM_LATENCY, &val, NULL); 325342a0d256SVille Syrjälä if (ret) { 325442a0d256SVille Syrjälä drm_err(&i915->drm, "SKL Mailbox read error = %d\n", ret); 325542a0d256SVille Syrjälä return; 325642a0d256SVille Syrjälä } 325742a0d256SVille Syrjälä 32583fecf93cSVille Syrjälä wm[0] = REG_FIELD_GET(GEN9_MEM_LATENCY_LEVEL_0_4_MASK, val) * mult; 32593fecf93cSVille Syrjälä wm[1] = REG_FIELD_GET(GEN9_MEM_LATENCY_LEVEL_1_5_MASK, val) * mult; 32603fecf93cSVille Syrjälä wm[2] = REG_FIELD_GET(GEN9_MEM_LATENCY_LEVEL_2_6_MASK, val) * mult; 32613fecf93cSVille Syrjälä wm[3] = REG_FIELD_GET(GEN9_MEM_LATENCY_LEVEL_3_7_MASK, val) * mult; 326242a0d256SVille Syrjälä 326342a0d256SVille Syrjälä /* read the second set of memory latencies[4:7] */ 326442a0d256SVille Syrjälä val = 1; /* data0 to be programmed to 1 for second set */ 326542a0d256SVille Syrjälä ret = snb_pcode_read(&i915->uncore, GEN9_PCODE_READ_MEM_LATENCY, &val, NULL); 326642a0d256SVille Syrjälä if (ret) { 326742a0d256SVille Syrjälä drm_err(&i915->drm, "SKL Mailbox read error = %d\n", ret); 326842a0d256SVille Syrjälä return; 326942a0d256SVille Syrjälä } 327042a0d256SVille Syrjälä 32713fecf93cSVille Syrjälä wm[4] = REG_FIELD_GET(GEN9_MEM_LATENCY_LEVEL_0_4_MASK, val) * mult; 32723fecf93cSVille Syrjälä wm[5] = REG_FIELD_GET(GEN9_MEM_LATENCY_LEVEL_1_5_MASK, val) * mult; 32733fecf93cSVille Syrjälä wm[6] = REG_FIELD_GET(GEN9_MEM_LATENCY_LEVEL_2_6_MASK, val) * mult; 32743fecf93cSVille Syrjälä wm[7] = REG_FIELD_GET(GEN9_MEM_LATENCY_LEVEL_3_7_MASK, val) * mult; 327542a0d256SVille Syrjälä 32767ee6f99dSVille Syrjälä adjust_wm_latency(i915, wm, num_levels, read_latency); 327742a0d256SVille Syrjälä } 327842a0d256SVille Syrjälä 327942a0d256SVille Syrjälä static void skl_setup_wm_latency(struct drm_i915_private *i915) 328042a0d256SVille Syrjälä { 3281064b3eeeSVille Syrjälä if (HAS_HW_SAGV_WM(i915)) 32827ee6f99dSVille Syrjälä i915->display.wm.num_levels = 6; 3283064b3eeeSVille Syrjälä else 32847ee6f99dSVille Syrjälä i915->display.wm.num_levels = 8; 3285064b3eeeSVille Syrjälä 328642a0d256SVille Syrjälä if (DISPLAY_VER(i915) >= 14) 328742a0d256SVille Syrjälä mtl_read_wm_latency(i915, i915->display.wm.skl_latency); 328842a0d256SVille Syrjälä else 328942a0d256SVille Syrjälä skl_read_wm_latency(i915, i915->display.wm.skl_latency); 329042a0d256SVille Syrjälä 329142a0d256SVille Syrjälä intel_print_wm_latency(i915, "Gen9 Plane", i915->display.wm.skl_latency); 329242a0d256SVille Syrjälä } 329342a0d256SVille Syrjälä 329442a0d256SVille Syrjälä static const struct intel_wm_funcs skl_wm_funcs = { 329542a0d256SVille Syrjälä .compute_global_watermarks = skl_compute_wm, 32960e7a16f9SJani Nikula .get_hw_state = skl_wm_get_hw_state_and_sanitize, 329742a0d256SVille Syrjälä }; 329842a0d256SVille Syrjälä 329942a0d256SVille Syrjälä void skl_wm_init(struct drm_i915_private *i915) 330042a0d256SVille Syrjälä { 330142a0d256SVille Syrjälä intel_sagv_init(i915); 330242a0d256SVille Syrjälä 330342a0d256SVille Syrjälä skl_setup_wm_latency(i915); 330442a0d256SVille Syrjälä 330542a0d256SVille Syrjälä i915->display.funcs.wm = &skl_wm_funcs; 330642a0d256SVille Syrjälä } 330742a0d256SVille Syrjälä 330842a0d256SVille Syrjälä static struct intel_global_state *intel_dbuf_duplicate_state(struct intel_global_obj *obj) 330942a0d256SVille Syrjälä { 331042a0d256SVille Syrjälä struct intel_dbuf_state *dbuf_state; 331142a0d256SVille Syrjälä 331242a0d256SVille Syrjälä dbuf_state = kmemdup(obj->state, sizeof(*dbuf_state), GFP_KERNEL); 331342a0d256SVille Syrjälä if (!dbuf_state) 331442a0d256SVille Syrjälä return NULL; 331542a0d256SVille Syrjälä 331642a0d256SVille Syrjälä return &dbuf_state->base; 331742a0d256SVille Syrjälä } 331842a0d256SVille Syrjälä 331942a0d256SVille Syrjälä static void intel_dbuf_destroy_state(struct intel_global_obj *obj, 332042a0d256SVille Syrjälä struct intel_global_state *state) 332142a0d256SVille Syrjälä { 332242a0d256SVille Syrjälä kfree(state); 332342a0d256SVille Syrjälä } 332442a0d256SVille Syrjälä 332542a0d256SVille Syrjälä static const struct intel_global_state_funcs intel_dbuf_funcs = { 332642a0d256SVille Syrjälä .atomic_duplicate_state = intel_dbuf_duplicate_state, 332742a0d256SVille Syrjälä .atomic_destroy_state = intel_dbuf_destroy_state, 332842a0d256SVille Syrjälä }; 332942a0d256SVille Syrjälä 333042a0d256SVille Syrjälä struct intel_dbuf_state * 333142a0d256SVille Syrjälä intel_atomic_get_dbuf_state(struct intel_atomic_state *state) 333242a0d256SVille Syrjälä { 333342a0d256SVille Syrjälä struct drm_i915_private *i915 = to_i915(state->base.dev); 333442a0d256SVille Syrjälä struct intel_global_state *dbuf_state; 333542a0d256SVille Syrjälä 333642a0d256SVille Syrjälä dbuf_state = intel_atomic_get_global_obj_state(state, &i915->display.dbuf.obj); 333742a0d256SVille Syrjälä if (IS_ERR(dbuf_state)) 333842a0d256SVille Syrjälä return ERR_CAST(dbuf_state); 333942a0d256SVille Syrjälä 334042a0d256SVille Syrjälä return to_intel_dbuf_state(dbuf_state); 334142a0d256SVille Syrjälä } 334242a0d256SVille Syrjälä 334342a0d256SVille Syrjälä int intel_dbuf_init(struct drm_i915_private *i915) 334442a0d256SVille Syrjälä { 334542a0d256SVille Syrjälä struct intel_dbuf_state *dbuf_state; 334642a0d256SVille Syrjälä 334742a0d256SVille Syrjälä dbuf_state = kzalloc(sizeof(*dbuf_state), GFP_KERNEL); 334842a0d256SVille Syrjälä if (!dbuf_state) 334942a0d256SVille Syrjälä return -ENOMEM; 335042a0d256SVille Syrjälä 335142a0d256SVille Syrjälä intel_atomic_global_obj_init(i915, &i915->display.dbuf.obj, 335242a0d256SVille Syrjälä &dbuf_state->base, &intel_dbuf_funcs); 335342a0d256SVille Syrjälä 335442a0d256SVille Syrjälä return 0; 335542a0d256SVille Syrjälä } 335642a0d256SVille Syrjälä 335742a0d256SVille Syrjälä /* 335842a0d256SVille Syrjälä * Configure MBUS_CTL and all DBUF_CTL_S of each slice to join_mbus state before 335942a0d256SVille Syrjälä * update the request state of all DBUS slices. 336042a0d256SVille Syrjälä */ 336142a0d256SVille Syrjälä static void update_mbus_pre_enable(struct intel_atomic_state *state) 336242a0d256SVille Syrjälä { 336342a0d256SVille Syrjälä struct drm_i915_private *i915 = to_i915(state->base.dev); 336442a0d256SVille Syrjälä u32 mbus_ctl, dbuf_min_tracker_val; 336542a0d256SVille Syrjälä enum dbuf_slice slice; 336642a0d256SVille Syrjälä const struct intel_dbuf_state *dbuf_state = 336742a0d256SVille Syrjälä intel_atomic_get_new_dbuf_state(state); 336842a0d256SVille Syrjälä 336942a0d256SVille Syrjälä if (!HAS_MBUS_JOINING(i915)) 337042a0d256SVille Syrjälä return; 337142a0d256SVille Syrjälä 337242a0d256SVille Syrjälä /* 337342a0d256SVille Syrjälä * TODO: Implement vblank synchronized MBUS joining changes. 337442a0d256SVille Syrjälä * Must be properly coordinated with dbuf reprogramming. 337542a0d256SVille Syrjälä */ 337642a0d256SVille Syrjälä if (dbuf_state->joined_mbus) { 337742a0d256SVille Syrjälä mbus_ctl = MBUS_HASHING_MODE_1x4 | MBUS_JOIN | 337842a0d256SVille Syrjälä MBUS_JOIN_PIPE_SELECT_NONE; 337942a0d256SVille Syrjälä dbuf_min_tracker_val = DBUF_MIN_TRACKER_STATE_SERVICE(3); 338042a0d256SVille Syrjälä } else { 338142a0d256SVille Syrjälä mbus_ctl = MBUS_HASHING_MODE_2x2 | 338242a0d256SVille Syrjälä MBUS_JOIN_PIPE_SELECT_NONE; 338342a0d256SVille Syrjälä dbuf_min_tracker_val = DBUF_MIN_TRACKER_STATE_SERVICE(1); 338442a0d256SVille Syrjälä } 338542a0d256SVille Syrjälä 338642a0d256SVille Syrjälä intel_de_rmw(i915, MBUS_CTL, 338742a0d256SVille Syrjälä MBUS_HASHING_MODE_MASK | MBUS_JOIN | 338842a0d256SVille Syrjälä MBUS_JOIN_PIPE_SELECT_MASK, mbus_ctl); 338942a0d256SVille Syrjälä 339042a0d256SVille Syrjälä for_each_dbuf_slice(i915, slice) 339142a0d256SVille Syrjälä intel_de_rmw(i915, DBUF_CTL_S(slice), 339242a0d256SVille Syrjälä DBUF_MIN_TRACKER_STATE_SERVICE_MASK, 339342a0d256SVille Syrjälä dbuf_min_tracker_val); 339442a0d256SVille Syrjälä } 339542a0d256SVille Syrjälä 339642a0d256SVille Syrjälä void intel_dbuf_pre_plane_update(struct intel_atomic_state *state) 339742a0d256SVille Syrjälä { 339842a0d256SVille Syrjälä struct drm_i915_private *i915 = to_i915(state->base.dev); 339942a0d256SVille Syrjälä const struct intel_dbuf_state *new_dbuf_state = 340042a0d256SVille Syrjälä intel_atomic_get_new_dbuf_state(state); 340142a0d256SVille Syrjälä const struct intel_dbuf_state *old_dbuf_state = 340242a0d256SVille Syrjälä intel_atomic_get_old_dbuf_state(state); 340342a0d256SVille Syrjälä 340442a0d256SVille Syrjälä if (!new_dbuf_state || 340542a0d256SVille Syrjälä (new_dbuf_state->enabled_slices == old_dbuf_state->enabled_slices && 340642a0d256SVille Syrjälä new_dbuf_state->joined_mbus == old_dbuf_state->joined_mbus)) 340742a0d256SVille Syrjälä return; 340842a0d256SVille Syrjälä 340942a0d256SVille Syrjälä WARN_ON(!new_dbuf_state->base.changed); 341042a0d256SVille Syrjälä 341142a0d256SVille Syrjälä update_mbus_pre_enable(state); 341242a0d256SVille Syrjälä gen9_dbuf_slices_update(i915, 341342a0d256SVille Syrjälä old_dbuf_state->enabled_slices | 341442a0d256SVille Syrjälä new_dbuf_state->enabled_slices); 341542a0d256SVille Syrjälä } 341642a0d256SVille Syrjälä 341742a0d256SVille Syrjälä void intel_dbuf_post_plane_update(struct intel_atomic_state *state) 341842a0d256SVille Syrjälä { 341942a0d256SVille Syrjälä struct drm_i915_private *i915 = to_i915(state->base.dev); 342042a0d256SVille Syrjälä const struct intel_dbuf_state *new_dbuf_state = 342142a0d256SVille Syrjälä intel_atomic_get_new_dbuf_state(state); 342242a0d256SVille Syrjälä const struct intel_dbuf_state *old_dbuf_state = 342342a0d256SVille Syrjälä intel_atomic_get_old_dbuf_state(state); 342442a0d256SVille Syrjälä 342542a0d256SVille Syrjälä if (!new_dbuf_state || 342642a0d256SVille Syrjälä (new_dbuf_state->enabled_slices == old_dbuf_state->enabled_slices && 342742a0d256SVille Syrjälä new_dbuf_state->joined_mbus == old_dbuf_state->joined_mbus)) 342842a0d256SVille Syrjälä return; 342942a0d256SVille Syrjälä 343042a0d256SVille Syrjälä WARN_ON(!new_dbuf_state->base.changed); 343142a0d256SVille Syrjälä 343242a0d256SVille Syrjälä gen9_dbuf_slices_update(i915, 343342a0d256SVille Syrjälä new_dbuf_state->enabled_slices); 343442a0d256SVille Syrjälä } 343542a0d256SVille Syrjälä 3436851d635aSRadhakrishna Sripada static bool xelpdp_is_only_pipe_per_dbuf_bank(enum pipe pipe, u8 active_pipes) 3437851d635aSRadhakrishna Sripada { 3438851d635aSRadhakrishna Sripada switch (pipe) { 3439851d635aSRadhakrishna Sripada case PIPE_A: 3440851d635aSRadhakrishna Sripada return !(active_pipes & BIT(PIPE_D)); 3441851d635aSRadhakrishna Sripada case PIPE_D: 3442851d635aSRadhakrishna Sripada return !(active_pipes & BIT(PIPE_A)); 3443851d635aSRadhakrishna Sripada case PIPE_B: 3444851d635aSRadhakrishna Sripada return !(active_pipes & BIT(PIPE_C)); 3445851d635aSRadhakrishna Sripada case PIPE_C: 3446851d635aSRadhakrishna Sripada return !(active_pipes & BIT(PIPE_B)); 3447851d635aSRadhakrishna Sripada default: /* to suppress compiler warning */ 3448851d635aSRadhakrishna Sripada MISSING_CASE(pipe); 3449851d635aSRadhakrishna Sripada break; 3450851d635aSRadhakrishna Sripada } 3451851d635aSRadhakrishna Sripada 3452851d635aSRadhakrishna Sripada return false; 3453851d635aSRadhakrishna Sripada } 3454851d635aSRadhakrishna Sripada 345542a0d256SVille Syrjälä void intel_mbus_dbox_update(struct intel_atomic_state *state) 345642a0d256SVille Syrjälä { 345742a0d256SVille Syrjälä struct drm_i915_private *i915 = to_i915(state->base.dev); 345842a0d256SVille Syrjälä const struct intel_dbuf_state *new_dbuf_state, *old_dbuf_state; 345942a0d256SVille Syrjälä const struct intel_crtc_state *new_crtc_state; 346042a0d256SVille Syrjälä const struct intel_crtc *crtc; 346142a0d256SVille Syrjälä u32 val = 0; 346242a0d256SVille Syrjälä int i; 346342a0d256SVille Syrjälä 346442a0d256SVille Syrjälä if (DISPLAY_VER(i915) < 11) 346542a0d256SVille Syrjälä return; 346642a0d256SVille Syrjälä 346742a0d256SVille Syrjälä new_dbuf_state = intel_atomic_get_new_dbuf_state(state); 346842a0d256SVille Syrjälä old_dbuf_state = intel_atomic_get_old_dbuf_state(state); 346942a0d256SVille Syrjälä if (!new_dbuf_state || 347042a0d256SVille Syrjälä (new_dbuf_state->joined_mbus == old_dbuf_state->joined_mbus && 347142a0d256SVille Syrjälä new_dbuf_state->active_pipes == old_dbuf_state->active_pipes)) 347242a0d256SVille Syrjälä return; 347342a0d256SVille Syrjälä 3474851d635aSRadhakrishna Sripada if (DISPLAY_VER(i915) >= 14) 3475851d635aSRadhakrishna Sripada val |= MBUS_DBOX_I_CREDIT(2); 3476851d635aSRadhakrishna Sripada 347742a0d256SVille Syrjälä if (DISPLAY_VER(i915) >= 12) { 347842a0d256SVille Syrjälä val |= MBUS_DBOX_B2B_TRANSACTIONS_MAX(16); 347942a0d256SVille Syrjälä val |= MBUS_DBOX_B2B_TRANSACTIONS_DELAY(1); 348042a0d256SVille Syrjälä val |= MBUS_DBOX_REGULATE_B2B_TRANSACTIONS_EN; 348142a0d256SVille Syrjälä } 348242a0d256SVille Syrjälä 3483851d635aSRadhakrishna Sripada if (DISPLAY_VER(i915) >= 14) 3484851d635aSRadhakrishna Sripada val |= new_dbuf_state->joined_mbus ? MBUS_DBOX_A_CREDIT(12) : 3485851d635aSRadhakrishna Sripada MBUS_DBOX_A_CREDIT(8); 3486851d635aSRadhakrishna Sripada else if (IS_ALDERLAKE_P(i915)) 348742a0d256SVille Syrjälä /* Wa_22010947358:adl-p */ 348842a0d256SVille Syrjälä val |= new_dbuf_state->joined_mbus ? MBUS_DBOX_A_CREDIT(6) : 348942a0d256SVille Syrjälä MBUS_DBOX_A_CREDIT(4); 349042a0d256SVille Syrjälä else 349142a0d256SVille Syrjälä val |= MBUS_DBOX_A_CREDIT(2); 349242a0d256SVille Syrjälä 3493851d635aSRadhakrishna Sripada if (DISPLAY_VER(i915) >= 14) { 3494851d635aSRadhakrishna Sripada val |= MBUS_DBOX_B_CREDIT(0xA); 3495851d635aSRadhakrishna Sripada } else if (IS_ALDERLAKE_P(i915)) { 349642a0d256SVille Syrjälä val |= MBUS_DBOX_BW_CREDIT(2); 349742a0d256SVille Syrjälä val |= MBUS_DBOX_B_CREDIT(8); 349842a0d256SVille Syrjälä } else if (DISPLAY_VER(i915) >= 12) { 349942a0d256SVille Syrjälä val |= MBUS_DBOX_BW_CREDIT(2); 350042a0d256SVille Syrjälä val |= MBUS_DBOX_B_CREDIT(12); 350142a0d256SVille Syrjälä } else { 350242a0d256SVille Syrjälä val |= MBUS_DBOX_BW_CREDIT(1); 350342a0d256SVille Syrjälä val |= MBUS_DBOX_B_CREDIT(8); 350442a0d256SVille Syrjälä } 350542a0d256SVille Syrjälä 350642a0d256SVille Syrjälä for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) { 3507851d635aSRadhakrishna Sripada u32 pipe_val = val; 3508851d635aSRadhakrishna Sripada 3509851d635aSRadhakrishna Sripada if (!new_crtc_state->hw.active) 351042a0d256SVille Syrjälä continue; 351142a0d256SVille Syrjälä 3512851d635aSRadhakrishna Sripada if (DISPLAY_VER(i915) >= 14) { 3513851d635aSRadhakrishna Sripada if (xelpdp_is_only_pipe_per_dbuf_bank(crtc->pipe, 3514851d635aSRadhakrishna Sripada new_dbuf_state->active_pipes)) 3515851d635aSRadhakrishna Sripada pipe_val |= MBUS_DBOX_BW_8CREDITS_MTL; 3516851d635aSRadhakrishna Sripada else 3517851d635aSRadhakrishna Sripada pipe_val |= MBUS_DBOX_BW_4CREDITS_MTL; 3518851d635aSRadhakrishna Sripada } 3519851d635aSRadhakrishna Sripada 3520851d635aSRadhakrishna Sripada intel_de_write(i915, PIPE_MBUS_DBOX_CTL(crtc->pipe), pipe_val); 352142a0d256SVille Syrjälä } 352242a0d256SVille Syrjälä } 3523dde01ed5SJani Nikula 3524dde01ed5SJani Nikula static int skl_watermark_ipc_status_show(struct seq_file *m, void *data) 3525dde01ed5SJani Nikula { 3526dde01ed5SJani Nikula struct drm_i915_private *i915 = m->private; 3527dde01ed5SJani Nikula 3528dde01ed5SJani Nikula seq_printf(m, "Isochronous Priority Control: %s\n", 3529dde01ed5SJani Nikula str_yes_no(skl_watermark_ipc_enabled(i915))); 3530dde01ed5SJani Nikula return 0; 3531dde01ed5SJani Nikula } 3532dde01ed5SJani Nikula 3533dde01ed5SJani Nikula static int skl_watermark_ipc_status_open(struct inode *inode, struct file *file) 3534dde01ed5SJani Nikula { 3535dde01ed5SJani Nikula struct drm_i915_private *i915 = inode->i_private; 3536dde01ed5SJani Nikula 3537dde01ed5SJani Nikula return single_open(file, skl_watermark_ipc_status_show, i915); 3538dde01ed5SJani Nikula } 3539dde01ed5SJani Nikula 3540dde01ed5SJani Nikula static ssize_t skl_watermark_ipc_status_write(struct file *file, 3541dde01ed5SJani Nikula const char __user *ubuf, 3542dde01ed5SJani Nikula size_t len, loff_t *offp) 3543dde01ed5SJani Nikula { 3544dde01ed5SJani Nikula struct seq_file *m = file->private_data; 3545dde01ed5SJani Nikula struct drm_i915_private *i915 = m->private; 3546dde01ed5SJani Nikula intel_wakeref_t wakeref; 3547dde01ed5SJani Nikula bool enable; 3548dde01ed5SJani Nikula int ret; 3549dde01ed5SJani Nikula 3550dde01ed5SJani Nikula ret = kstrtobool_from_user(ubuf, len, &enable); 3551dde01ed5SJani Nikula if (ret < 0) 3552dde01ed5SJani Nikula return ret; 3553dde01ed5SJani Nikula 3554dde01ed5SJani Nikula with_intel_runtime_pm(&i915->runtime_pm, wakeref) { 3555dde01ed5SJani Nikula if (!skl_watermark_ipc_enabled(i915) && enable) 3556dde01ed5SJani Nikula drm_info(&i915->drm, 3557dde01ed5SJani Nikula "Enabling IPC: WM will be proper only after next commit\n"); 355870296670SJani Nikula i915->display.wm.ipc_enabled = enable; 3559dde01ed5SJani Nikula skl_watermark_ipc_update(i915); 3560dde01ed5SJani Nikula } 3561dde01ed5SJani Nikula 3562dde01ed5SJani Nikula return len; 3563dde01ed5SJani Nikula } 3564dde01ed5SJani Nikula 3565dde01ed5SJani Nikula static const struct file_operations skl_watermark_ipc_status_fops = { 3566dde01ed5SJani Nikula .owner = THIS_MODULE, 3567dde01ed5SJani Nikula .open = skl_watermark_ipc_status_open, 3568dde01ed5SJani Nikula .read = seq_read, 3569dde01ed5SJani Nikula .llseek = seq_lseek, 3570dde01ed5SJani Nikula .release = single_release, 3571dde01ed5SJani Nikula .write = skl_watermark_ipc_status_write 3572dde01ed5SJani Nikula }; 3573dde01ed5SJani Nikula 357414f25bd0SVille Syrjälä static int intel_sagv_status_show(struct seq_file *m, void *unused) 357514f25bd0SVille Syrjälä { 357614f25bd0SVille Syrjälä struct drm_i915_private *i915 = m->private; 357714f25bd0SVille Syrjälä static const char * const sagv_status[] = { 357814f25bd0SVille Syrjälä [I915_SAGV_UNKNOWN] = "unknown", 357914f25bd0SVille Syrjälä [I915_SAGV_DISABLED] = "disabled", 358014f25bd0SVille Syrjälä [I915_SAGV_ENABLED] = "enabled", 358114f25bd0SVille Syrjälä [I915_SAGV_NOT_CONTROLLED] = "not controlled", 358214f25bd0SVille Syrjälä }; 358314f25bd0SVille Syrjälä 358414f25bd0SVille Syrjälä seq_printf(m, "SAGV available: %s\n", str_yes_no(intel_has_sagv(i915))); 358514f25bd0SVille Syrjälä seq_printf(m, "SAGV status: %s\n", sagv_status[i915->display.sagv.status]); 358614f25bd0SVille Syrjälä seq_printf(m, "SAGV block time: %d usec\n", i915->display.sagv.block_time_us); 358714f25bd0SVille Syrjälä 358814f25bd0SVille Syrjälä return 0; 358914f25bd0SVille Syrjälä } 359014f25bd0SVille Syrjälä 359114f25bd0SVille Syrjälä DEFINE_SHOW_ATTRIBUTE(intel_sagv_status); 359214f25bd0SVille Syrjälä 359314f25bd0SVille Syrjälä void skl_watermark_debugfs_register(struct drm_i915_private *i915) 3594dde01ed5SJani Nikula { 3595dde01ed5SJani Nikula struct drm_minor *minor = i915->drm.primary; 3596dde01ed5SJani Nikula 359714f25bd0SVille Syrjälä if (HAS_IPC(i915)) 3598dde01ed5SJani Nikula debugfs_create_file("i915_ipc_status", 0644, minor->debugfs_root, i915, 3599dde01ed5SJani Nikula &skl_watermark_ipc_status_fops); 360014f25bd0SVille Syrjälä 360114f25bd0SVille Syrjälä if (HAS_SAGV(i915)) 360214f25bd0SVille Syrjälä debugfs_create_file("i915_sagv_status", 0444, minor->debugfs_root, i915, 360314f25bd0SVille Syrjälä &intel_sagv_status_fops); 3604dde01ed5SJani Nikula } 3605