Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

drm/i915/xe3: Use hw support for min/interim ddb allocations for async flip

Xe3 is capable of switching automatically to min ddb allocation
(not using any extra blocks) or interim SAGV-adjusted allocation
in case if async flip is used. Introduce the minimum and interim
ddb allocation configuration for that purpose. Also i915 is
replaced with intel_display within the patch's context

v2: update min/interim ddb declarations and handling (Ville)
update to register definitions styling
consolidation of minimal wm0 check with min DDB check

Bspec: 69880, 72053
Signed-off-by: Stanislav Lisovskiy <stanislav.lisovskiy@intel.com>
Signed-off-by: Vinod Govindapillai <vinod.govindapillai@intel.com>
Reviewed-by: Uma Shankar <uma.shankar@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20241121112726.510220-4-vinod.govindapillai@intel.com

authored by

Stanislav Lisovskiy and committed by
Vinod Govindapillai
a831920c aac49b86

+118 -18
+8
drivers/gpu/drm/i915/display/intel_display_types.h
··· 780 780 u8 lines; 781 781 bool enable; 782 782 bool ignore_lines; 783 + bool auto_min_alloc_wm_enable; 783 784 bool can_sagv; 784 785 }; 785 786 ··· 875 874 struct skl_ddb_entry plane_ddb[I915_MAX_PLANES]; 876 875 /* pre-icl: for planar Y */ 877 876 struct skl_ddb_entry plane_ddb_y[I915_MAX_PLANES]; 877 + 878 + /* 879 + * xe3: Minimum amount of display blocks and minimum 880 + * sagv allocation required for async flip 881 + */ 882 + u16 plane_min_ddb[I915_MAX_PLANES]; 883 + u16 plane_interim_ddb[I915_MAX_PLANES]; 878 884 } skl; 879 885 880 886 struct {
+26
drivers/gpu/drm/i915/display/skl_universal_plane.c
··· 717 717 PLANE_BUF_START(entry->start); 718 718 } 719 719 720 + static u32 xe3_plane_min_ddb_reg_val(const u16 *min_ddb, 721 + const u16 *interim_ddb) 722 + { 723 + u32 val = 0; 724 + 725 + if (*min_ddb) 726 + val |= PLANE_MIN_DBUF_BLOCKS(*min_ddb); 727 + 728 + if (*interim_ddb) 729 + val |= PLANE_INTERIM_DBUF_BLOCKS(*interim_ddb); 730 + 731 + val |= val ? PLANE_AUTO_MIN_DBUF_EN : 0; 732 + 733 + return val; 734 + } 735 + 720 736 static u32 skl_plane_wm_reg_val(const struct skl_wm_level *level) 721 737 { 722 738 u32 val = 0; ··· 741 725 val |= PLANE_WM_EN; 742 726 if (level->ignore_lines) 743 727 val |= PLANE_WM_IGNORE_LINES; 728 + if (level->auto_min_alloc_wm_enable) 729 + val |= PLANE_WM_AUTO_MIN_ALLOC_EN; 730 + 744 731 val |= REG_FIELD_PREP(PLANE_WM_BLOCKS_MASK, level->blocks); 745 732 val |= REG_FIELD_PREP(PLANE_WM_LINES_MASK, level->lines); 746 733 ··· 762 743 &crtc_state->wm.skl.plane_ddb[plane_id]; 763 744 const struct skl_ddb_entry *ddb_y = 764 745 &crtc_state->wm.skl.plane_ddb_y[plane_id]; 746 + const u16 *min_ddb = &crtc_state->wm.skl.plane_min_ddb[plane_id]; 747 + const u16 *interim_ddb = 748 + &crtc_state->wm.skl.plane_interim_ddb[plane_id]; 765 749 int level; 766 750 767 751 for (level = 0; level < display->wm.num_levels; level++) ··· 789 767 if (DISPLAY_VER(display) < 11) 790 768 intel_de_write_dsb(display, dsb, PLANE_NV12_BUF_CFG(pipe, plane_id), 791 769 skl_plane_ddb_reg_val(ddb_y)); 770 + 771 + if (DISPLAY_VER(display) >= 30) 772 + intel_de_write_dsb(display, dsb, PLANE_MIN_BUF_CFG(pipe, plane_id), 773 + xe3_plane_min_ddb_reg_val(min_ddb, interim_ddb)); 792 774 } 793 775 794 776 static void
+15
drivers/gpu/drm/i915/display/skl_universal_plane_regs.h
··· 322 322 _PLANE_WM_2_A_0, _PLANE_WM_2_B_0) 323 323 #define PLANE_WM_EN REG_BIT(31) 324 324 #define PLANE_WM_IGNORE_LINES REG_BIT(30) 325 + #define PLANE_WM_AUTO_MIN_ALLOC_EN REG_BIT(29) 325 326 #define PLANE_WM_LINES_MASK REG_GENMASK(26, 14) 326 327 #define PLANE_WM_BLOCKS_MASK REG_GENMASK(11, 0) 327 328 ··· 374 373 #define PLANE_BUF_CFG(pipe, plane) _MMIO_SKL_PLANE((pipe), (plane), \ 375 374 _PLANE_BUF_CFG_1_A, _PLANE_BUF_CFG_1_B, \ 376 375 _PLANE_BUF_CFG_2_A, _PLANE_BUF_CFG_2_B) 376 + 377 377 /* skl+: 10 bits, icl+ 11 bits, adlp+ 12 bits */ 378 378 #define PLANE_BUF_END_MASK REG_GENMASK(27, 16) 379 379 #define PLANE_BUF_END(end) REG_FIELD_PREP(PLANE_BUF_END_MASK, (end)) 380 380 #define PLANE_BUF_START_MASK REG_GENMASK(11, 0) 381 381 #define PLANE_BUF_START(start) REG_FIELD_PREP(PLANE_BUF_START_MASK, (start)) 382 + 383 + #define _PLANE_MIN_BUF_CFG_1_A 0x70274 384 + #define _PLANE_MIN_BUF_CFG_2_A 0x70374 385 + #define _PLANE_MIN_BUF_CFG_1_B 0x71274 386 + #define _PLANE_MIN_BUF_CFG_2_B 0x71374 387 + #define PLANE_MIN_BUF_CFG(pipe, plane) _MMIO_SKL_PLANE((pipe), (plane), \ 388 + _PLANE_MIN_BUF_CFG_1_A, _PLANE_MIN_BUF_CFG_1_B, \ 389 + _PLANE_MIN_BUF_CFG_2_A, _PLANE_MIN_BUF_CFG_2_B) 390 + #define PLANE_AUTO_MIN_DBUF_EN REG_BIT(31) 391 + #define PLANE_MIN_DBUF_BLOCKS_MASK REG_GENMASK(27, 16) 392 + #define PLANE_MIN_DBUF_BLOCKS(val) REG_FIELD_PREP(PLANE_MIN_DBUF_BLOCKS_MASK, (val)) 393 + #define PLANE_INTERIM_DBUF_BLOCKS_MASK REG_GENMASK(11, 0) 394 + #define PLANE_INTERIM_DBUF_BLOCKS(val) REG_FIELD_PREP(PLANE_INTERIM_DBUF_BLOCKS_MASK, (val)) 382 395 383 396 /* tgl+ */ 384 397 #define _SEL_FETCH_PLANE_CTL_1_A 0x70890
+69 -18
drivers/gpu/drm/i915/display/skl_watermark.c
··· 801 801 const enum pipe pipe, 802 802 const enum plane_id plane_id, 803 803 struct skl_ddb_entry *ddb, 804 - struct skl_ddb_entry *ddb_y) 804 + struct skl_ddb_entry *ddb_y, 805 + u16 *min_ddb, u16 *interim_ddb) 805 806 { 807 + struct intel_display *display = &i915->display; 806 808 u32 val; 807 809 808 810 /* Cursor doesn't support NV12/planar, so no extra calculation needed */ 809 811 if (plane_id == PLANE_CURSOR) { 810 - val = intel_de_read(i915, CUR_BUF_CFG(pipe)); 812 + val = intel_de_read(display, CUR_BUF_CFG(pipe)); 811 813 skl_ddb_entry_init_from_hw(ddb, val); 812 814 return; 813 815 } 814 816 815 - val = intel_de_read(i915, PLANE_BUF_CFG(pipe, plane_id)); 817 + val = intel_de_read(display, PLANE_BUF_CFG(pipe, plane_id)); 816 818 skl_ddb_entry_init_from_hw(ddb, val); 817 819 818 - if (DISPLAY_VER(i915) >= 11) 820 + if (DISPLAY_VER(display) >= 30) { 821 + val = intel_de_read(display, PLANE_MIN_BUF_CFG(pipe, plane_id)); 822 + 823 + *min_ddb = REG_FIELD_GET(PLANE_MIN_DBUF_BLOCKS_MASK, val); 824 + *interim_ddb = REG_FIELD_GET(PLANE_INTERIM_DBUF_BLOCKS_MASK, val); 825 + } 826 + 827 + if (DISPLAY_VER(display) >= 11) 819 828 return; 820 829 821 - val = intel_de_read(i915, PLANE_NV12_BUF_CFG(pipe, plane_id)); 830 + val = intel_de_read(display, PLANE_NV12_BUF_CFG(pipe, plane_id)); 822 831 skl_ddb_entry_init_from_hw(ddb_y, val); 823 832 } 824 833 825 834 static void skl_pipe_ddb_get_hw_state(struct intel_crtc *crtc, 826 835 struct skl_ddb_entry *ddb, 827 - struct skl_ddb_entry *ddb_y) 836 + struct skl_ddb_entry *ddb_y, 837 + u16 *min_ddb, u16 *interim_ddb) 828 838 { 829 839 struct drm_i915_private *i915 = to_i915(crtc->base.dev); 830 840 enum intel_display_power_domain power_domain; ··· 851 841 skl_ddb_get_hw_plane_state(i915, pipe, 852 842 plane_id, 853 843 &ddb[plane_id], 854 - &ddb_y[plane_id]); 844 + &ddb_y[plane_id], 845 + &min_ddb[plane_id], 846 + &interim_ddb[plane_id]); 855 847 856 848 intel_display_power_put(i915, power_domain, wakeref); 857 849 } ··· 1388 1376 use_minimal_wm0_only(const struct intel_crtc_state *crtc_state, 1389 1377 struct intel_plane *plane) 1390 1378 { 1391 - struct drm_i915_private *i915 = to_i915(plane->base.dev); 1379 + struct intel_display *display = to_intel_display(plane); 1392 1380 1393 - return DISPLAY_VER(i915) >= 13 && 1381 + /* Xe3+ are auto minimum DDB capble. So don't force minimal wm0 */ 1382 + return IS_DISPLAY_VER(display, 13, 20) && 1394 1383 crtc_state->uapi.async_flip && 1395 1384 plane->async_flip; 1396 1385 } ··· 1548 1535 const struct intel_dbuf_state *dbuf_state = 1549 1536 intel_atomic_get_new_dbuf_state(state); 1550 1537 const struct skl_ddb_entry *alloc = &dbuf_state->ddb[crtc->pipe]; 1538 + struct intel_display *display = to_intel_display(state); 1551 1539 int num_active = hweight8(dbuf_state->active_pipes); 1552 1540 struct skl_plane_ddb_iter iter; 1553 1541 enum plane_id plane_id; ··· 1559 1545 /* Clear the partitioning for disabled planes. */ 1560 1546 memset(crtc_state->wm.skl.plane_ddb, 0, sizeof(crtc_state->wm.skl.plane_ddb)); 1561 1547 memset(crtc_state->wm.skl.plane_ddb_y, 0, sizeof(crtc_state->wm.skl.plane_ddb_y)); 1548 + memset(crtc_state->wm.skl.plane_min_ddb, 0, 1549 + sizeof(crtc_state->wm.skl.plane_min_ddb)); 1550 + memset(crtc_state->wm.skl.plane_interim_ddb, 0, 1551 + sizeof(crtc_state->wm.skl.plane_interim_ddb)); 1562 1552 1563 1553 if (!crtc_state->hw.active) 1564 1554 return 0; ··· 1635 1617 &crtc_state->wm.skl.plane_ddb[plane_id]; 1636 1618 struct skl_ddb_entry *ddb_y = 1637 1619 &crtc_state->wm.skl.plane_ddb_y[plane_id]; 1620 + u16 *min_ddb = &crtc_state->wm.skl.plane_min_ddb[plane_id]; 1621 + u16 *interim_ddb = 1622 + &crtc_state->wm.skl.plane_interim_ddb[plane_id]; 1638 1623 const struct skl_plane_wm *wm = 1639 1624 &crtc_state->wm.skl.optimal.planes[plane_id]; 1640 1625 ··· 1653 1632 } else { 1654 1633 skl_allocate_plane_ddb(&iter, ddb, &wm->wm[level], 1655 1634 crtc_state->rel_data_rate[plane_id]); 1635 + } 1636 + 1637 + if (DISPLAY_VER(display) >= 30) { 1638 + *min_ddb = wm->wm[0].min_ddb_alloc; 1639 + *interim_ddb = wm->sagv.wm0.min_ddb_alloc; 1656 1640 } 1657 1641 } 1658 1642 drm_WARN_ON(&i915->drm, iter.size != 0 || iter.data_rate != 0); ··· 1702 1676 &crtc_state->wm.skl.plane_ddb[plane_id]; 1703 1677 const struct skl_ddb_entry *ddb_y = 1704 1678 &crtc_state->wm.skl.plane_ddb_y[plane_id]; 1679 + u16 *interim_ddb = 1680 + &crtc_state->wm.skl.plane_interim_ddb[plane_id]; 1705 1681 struct skl_plane_wm *wm = 1706 1682 &crtc_state->wm.skl.optimal.planes[plane_id]; 1707 1683 ··· 1717 1689 } 1718 1690 1719 1691 skl_check_wm_level(&wm->sagv.wm0, ddb); 1692 + if (DISPLAY_VER(display) >= 30) 1693 + *interim_ddb = wm->sagv.wm0.min_ddb_alloc; 1694 + 1720 1695 skl_check_wm_level(&wm->sagv.trans_wm, ddb); 1721 1696 } 1722 1697 ··· 1798 1767 int color_plane, unsigned int pan_x) 1799 1768 { 1800 1769 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 1770 + struct intel_display *display = to_intel_display(crtc_state); 1801 1771 struct drm_i915_private *i915 = to_i915(crtc->base.dev); 1802 1772 u32 interm_pbpl; 1803 1773 ··· 1857 1825 wp->y_min_scanlines, 1858 1826 wp->dbuf_block_size); 1859 1827 1860 - if (DISPLAY_VER(i915) >= 30) 1828 + if (DISPLAY_VER(display) >= 30) 1861 1829 interm_pbpl += (pan_x != 0); 1862 1830 else if (DISPLAY_VER(i915) >= 10) 1863 1831 interm_pbpl++; ··· 1922 1890 return 31; 1923 1891 } 1924 1892 1893 + static bool xe3_auto_min_alloc_capable(struct intel_display *display, 1894 + int level) 1895 + { 1896 + return DISPLAY_VER(display) >= 30 && level == 0; 1897 + } 1898 + 1925 1899 static void skl_compute_plane_wm(const struct intel_crtc_state *crtc_state, 1926 1900 struct intel_plane *plane, 1927 1901 int level, ··· 1937 1899 struct skl_wm_level *result /* out */) 1938 1900 { 1939 1901 struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); 1902 + struct intel_display *display = to_intel_display(crtc_state); 1940 1903 uint_fixed_16_16_t method1, method2; 1941 1904 uint_fixed_16_16_t selected_result; 1942 1905 u32 blocks, lines, min_ddb_alloc = 0; ··· 2061 2022 /* Bspec says: value >= plane ddb allocation -> invalid, hence the +1 here */ 2062 2023 result->min_ddb_alloc = max(min_ddb_alloc, blocks) + 1; 2063 2024 result->enable = true; 2025 + result->auto_min_alloc_wm_enable = xe3_auto_min_alloc_capable(display, level); 2064 2026 2065 2027 if (DISPLAY_VER(i915) < 12 && i915->display.sagv.block_time_us) 2066 2028 result->can_sagv = latency >= i915->display.sagv.block_time_us; ··· 2441 2401 return l1->enable == l2->enable && 2442 2402 l1->ignore_lines == l2->ignore_lines && 2443 2403 l1->lines == l2->lines && 2444 - l1->blocks == l2->blocks; 2404 + l1->blocks == l2->blocks && 2405 + l1->auto_min_alloc_wm_enable == l2->auto_min_alloc_wm_enable; 2445 2406 } 2446 2407 2447 2408 static bool skl_plane_wm_equals(struct drm_i915_private *i915, 2448 2409 const struct skl_plane_wm *wm1, 2449 2410 const struct skl_plane_wm *wm2) 2450 2411 { 2412 + struct intel_display *display = &i915->display; 2451 2413 int level; 2452 2414 2453 - for (level = 0; level < i915->display.wm.num_levels; level++) { 2415 + for (level = 0; level < display->wm.num_levels; level++) { 2454 2416 /* 2455 2417 * We don't check uv_wm as the hardware doesn't actually 2456 2418 * use it. It only gets used for calculating the required ··· 3003 2961 level->ignore_lines = val & PLANE_WM_IGNORE_LINES; 3004 2962 level->blocks = REG_FIELD_GET(PLANE_WM_BLOCKS_MASK, val); 3005 2963 level->lines = REG_FIELD_GET(PLANE_WM_LINES_MASK, val); 2964 + level->auto_min_alloc_wm_enable = DISPLAY_VER(display) >= 30 ? 2965 + val & PLANE_WM_AUTO_MIN_ALLOC_EN : 0; 3006 2966 } 3007 2967 3008 2968 static void skl_pipe_wm_get_hw_state(struct intel_crtc *crtc, ··· 3064 3020 struct intel_crtc *crtc; 3065 3021 3066 3022 if (HAS_MBUS_JOINING(display)) 3067 - dbuf_state->joined_mbus = intel_de_read(i915, MBUS_CTL) & MBUS_JOIN; 3023 + dbuf_state->joined_mbus = intel_de_read(display, MBUS_CTL) & MBUS_JOIN; 3068 3024 3069 3025 dbuf_state->mdclk_cdclk_ratio = intel_mdclk_cdclk_ratio(display, &display->cdclk.hw); 3070 3026 3071 - for_each_intel_crtc(&i915->drm, crtc) { 3027 + for_each_intel_crtc(display->drm, crtc) { 3072 3028 struct intel_crtc_state *crtc_state = 3073 3029 to_intel_crtc_state(crtc->base.state); 3074 3030 enum pipe pipe = crtc->pipe; ··· 3089 3045 &crtc_state->wm.skl.plane_ddb[plane_id]; 3090 3046 struct skl_ddb_entry *ddb_y = 3091 3047 &crtc_state->wm.skl.plane_ddb_y[plane_id]; 3048 + u16 *min_ddb = 3049 + &crtc_state->wm.skl.plane_min_ddb[plane_id]; 3050 + u16 *interim_ddb = 3051 + &crtc_state->wm.skl.plane_interim_ddb[plane_id]; 3092 3052 3093 3053 if (!crtc_state->hw.active) 3094 3054 continue; 3095 3055 3096 3056 skl_ddb_get_hw_plane_state(i915, crtc->pipe, 3097 - plane_id, ddb, ddb_y); 3057 + plane_id, ddb, ddb_y, 3058 + min_ddb, interim_ddb); 3098 3059 3099 3060 skl_ddb_entry_union(&dbuf_state->ddb[pipe], ddb); 3100 3061 skl_ddb_entry_union(&dbuf_state->ddb[pipe], ddb_y); ··· 3121 3072 dbuf_state->slices[pipe] = 3122 3073 skl_ddb_dbuf_slice_mask(i915, &crtc_state->wm.skl.ddb); 3123 3074 3124 - drm_dbg_kms(&i915->drm, 3075 + drm_dbg_kms(display->drm, 3125 3076 "[CRTC:%d:%s] dbuf slices 0x%x, ddb (%d - %d), active pipes 0x%x, mbus joined: %s\n", 3126 3077 crtc->base.base.id, crtc->base.name, 3127 3078 dbuf_state->slices[pipe], dbuf_state->ddb[pipe].start, ··· 3129 3080 str_yes_no(dbuf_state->joined_mbus)); 3130 3081 } 3131 3082 3132 - dbuf_state->enabled_slices = i915->display.dbuf.enabled_slices; 3083 + dbuf_state->enabled_slices = display->dbuf.enabled_slices; 3133 3084 } 3134 3085 3135 3086 bool skl_watermark_ipc_enabled(struct drm_i915_private *i915) ··· 3764 3715 struct skl_hw_state { 3765 3716 struct skl_ddb_entry ddb[I915_MAX_PLANES]; 3766 3717 struct skl_ddb_entry ddb_y[I915_MAX_PLANES]; 3718 + u16 min_ddb[I915_MAX_PLANES]; 3719 + u16 interim_ddb[I915_MAX_PLANES]; 3767 3720 struct skl_pipe_wm wm; 3768 3721 } *hw; 3769 3722 const struct skl_pipe_wm *sw_wm = &new_crtc_state->wm.skl.optimal; ··· 3782 3731 3783 3732 skl_pipe_wm_get_hw_state(crtc, &hw->wm); 3784 3733 3785 - skl_pipe_ddb_get_hw_state(crtc, hw->ddb, hw->ddb_y); 3734 + skl_pipe_ddb_get_hw_state(crtc, hw->ddb, hw->ddb_y, hw->min_ddb, hw->interim_ddb); 3786 3735 3787 3736 hw_enabled_slices = intel_enabled_dbuf_slices_mask(i915); 3788 3737