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