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.

Merge tag 'drm-intel-next-2025-11-04' of https://gitlab.freedesktop.org/drm/i915/kernel into drm-next

drm/i915 feature pull for v6.19:

Features and functionality:
- Enable LNL+ content adaptive sharpness filter (CASF) (Nemesa)
- Use optimized VRR guardband (Ankit, Ville)
- Enable Xe3p LT PHY (Suraj)
- Enable FBC support for Xe3p_LPD display (Sai Teja, Vinod)
- Specify DMC firmware for display version 30.02 (Dnyaneshwar)
- Report reason for disabling PSR to debugfs (Michał)
- Extend i915_display_info with Type-C port details (Khaled)
- Log DSI send packet sequence errors and contents

Refactoring and cleanups:
- Refactoring to prepare for VRR guardband optimization (Ankit)
- Abstract VRR live status wait (Ankit)
- Refactor VRR and DSB timing to handle Set Context Latency explicitly (Ankit)
- Helpers for prefill latency calculations (Ville)
- Refactor SKL+ watermark latency setup (Ville)
- VRR refactoring and cleanups (Ville)
- SKL+ universal plane cleanups (Ville)
- Decouple CDCLK from state->modeset refactor (Ville)
- Refactor VLV/CHV clock functions (Jani)
- Refactor fbdev handling (Jani)
- Call i915 and xe runtime PM from display via function pointers (Jouni)
- IRQ code refactoring (Jani)
- Drop display dependency on i915 feature check macros (Jani)
- Refactor and unify i915 and xe stolen memory interfaces towards display (Jani)
- Switch to driver agnostic drm to display pointer chase (Jani)
- Use display version over graphics version in display code (Matt A)
- GVT cleanups (Jonathan, Andi)
- Rename a VLV clock function to unify (Michał)
- Explicitly sanitize DMC package header num entries (Luca)
- Remove redundant port clock check from ALPM (Jouni)
- Use sysfs_emit() instead of sprintf() in PMU sysfs (Madhur Kumar)
- Clean up C20 PHY PLL register macros (Imre, Mika))
- Abstract "address in MMIO table" helper for general use (Matt A)
- Improve VRR platform abstractions (Ville)
- Move towards more standard PCI PM code usage (Ville)
- Framebuffer refactoring (Ville)
- Drop display dependency on i915_utils.h (Jani)
- Include cleanups (Jani)

Fixes:
- Workaround docking station DSC issues with high pixel clock and bpp (Imre)
- Fix Panel Replay in DSC mode (Imre)
- Disable tracepoints for PREEMPT_RT as a workaround (Maarten)
- Fix intel_crtc_get_vblank_counter() on PREEMPT_RT (Maarten)
- Fix C10 PHY identification on PTL/WCL (Dnyaneshwar)
- Take AS SDP into account with optimized guardband (Jouni)
- Fix panic structure allocation memory leak (Jani)
- Adjust an FBC workaround platforms (Vinod)
- Add fallback for CDCLK selection (Naladala)
- Avoid using invalid transcoder in MST transport select (Suraj)
- Don't use cursor size reduction on display version 14+ (Nemesa)
- Fix C20 PHY PLL register programming (Imre, Mika)
- Fix PSR frontbuffer flush handling (Jouni)
- Store ALPM parameters in crtc state (Jouni)
- Defeature DRRS on LNL+ (Ville)
- Fix the scope of the large DRAM DIMM workaround (Ville)
- Fix PICA vs. AUX power ordering issue (Gustavo)
- Fix pixel rate for computing watermark line time (Ville)
- Fix framebuffer set_tiling vs. addfb race (Ville)
- DMC event handler fixes (Ville)

DRM Core:
- CRTC sharpness strength property (Nemesa)
- DPCD DSC quirk for Synaptics Panamera devices (Imre)
- Helpers to query the branch DSC max throughput/line-width (Imre)

Merges:
- Backmerge drm-next for v6.18-rc and to sync with drm-xe-next (Jani)

Signed-off-by: Dave Airlie <airlied@redhat.com>

From: Jani Nikula <jani.nikula@intel.com>
Link: https://patch.msgid.link/ec5a05f2df6d597a62033ee2d57225cce707b320@intel.com

+7571 -2272
+156
drivers/gpu/drm/display/drm_dp_helper.c
··· 2552 2552 { OUI(0x00, 0x0C, 0xE7), DEVICE_ID_ANY, false, BIT(DP_DPCD_QUIRK_HBLANK_EXPANSION_REQUIRES_DSC) }, 2553 2553 /* Apple MacBookPro 2017 15 inch eDP Retina panel reports too low DP_MAX_LINK_RATE */ 2554 2554 { OUI(0x00, 0x10, 0xfa), DEVICE_ID(101, 68, 21, 101, 98, 97), false, BIT(DP_DPCD_QUIRK_CAN_DO_MAX_LINK_RATE_3_24_GBPS) }, 2555 + /* Synaptics Panamera supports only a compressed bpp of 12 above 50% of its max DSC pixel throughput */ 2556 + { OUI(0x90, 0xCC, 0x24), DEVICE_ID('S', 'Y', 'N', 'A', 0x53, 0x22), true, BIT(DP_DPCD_QUIRK_DSC_THROUGHPUT_BPP_LIMIT) }, 2557 + { OUI(0x90, 0xCC, 0x24), DEVICE_ID('S', 'Y', 'N', 'A', 0x53, 0x31), true, BIT(DP_DPCD_QUIRK_DSC_THROUGHPUT_BPP_LIMIT) }, 2558 + { OUI(0x90, 0xCC, 0x24), DEVICE_ID('S', 'Y', 'N', 'A', 0x53, 0x33), true, BIT(DP_DPCD_QUIRK_DSC_THROUGHPUT_BPP_LIMIT) }, 2555 2559 }; 2556 2560 2557 2561 #undef OUI ··· 2844 2840 return num_bpc; 2845 2841 } 2846 2842 EXPORT_SYMBOL(drm_dp_dsc_sink_supported_input_bpcs); 2843 + 2844 + /* 2845 + * See DP Standard v2.1a 2.8.4 Minimum Slices/Display, Table 2-159 and 2846 + * Appendix L.1 Derivation of Slice Count Requirements. 2847 + */ 2848 + static int dsc_sink_min_slice_throughput(int peak_pixel_rate) 2849 + { 2850 + if (peak_pixel_rate >= 4800000) 2851 + return 600000; 2852 + else if (peak_pixel_rate >= 2700000) 2853 + return 400000; 2854 + else 2855 + return 340000; 2856 + } 2857 + 2858 + /** 2859 + * drm_dp_dsc_sink_max_slice_throughput() - Get a DSC sink's maximum pixel throughput per slice 2860 + * @dsc_dpcd: DSC sink's capabilities from DPCD 2861 + * @peak_pixel_rate: Cumulative peak pixel rate in kHz 2862 + * @is_rgb_yuv444: The mode is either RGB or YUV444 2863 + * 2864 + * Return the DSC sink device's maximum pixel throughput per slice, based on 2865 + * the device's @dsc_dpcd capabilities, the @peak_pixel_rate of the transferred 2866 + * stream(s) and whether the output format @is_rgb_yuv444 or yuv422/yuv420. 2867 + * 2868 + * Note that @peak_pixel_rate is the total pixel rate transferred to the same 2869 + * DSC/display sink. For instance to calculate a tile's slice count of an MST 2870 + * multi-tiled display sink (not considering here the required 2871 + * rounding/alignment of slice count):: 2872 + * 2873 + * @peak_pixel_rate = tile_pixel_rate * tile_count 2874 + * total_slice_count = @peak_pixel_rate / drm_dp_dsc_sink_max_slice_throughput(@peak_pixel_rate) 2875 + * tile_slice_count = total_slice_count / tile_count 2876 + * 2877 + * Returns: 2878 + * The maximum pixel throughput per slice supported by the DSC sink device 2879 + * in kPixels/sec. 2880 + */ 2881 + int drm_dp_dsc_sink_max_slice_throughput(const u8 dsc_dpcd[DP_DSC_RECEIVER_CAP_SIZE], 2882 + int peak_pixel_rate, bool is_rgb_yuv444) 2883 + { 2884 + int throughput; 2885 + int delta = 0; 2886 + int base; 2887 + 2888 + throughput = dsc_dpcd[DP_DSC_PEAK_THROUGHPUT - DP_DSC_SUPPORT]; 2889 + 2890 + if (is_rgb_yuv444) { 2891 + throughput = (throughput & DP_DSC_THROUGHPUT_MODE_0_MASK) >> 2892 + DP_DSC_THROUGHPUT_MODE_0_SHIFT; 2893 + 2894 + delta = ((dsc_dpcd[DP_DSC_RC_BUF_BLK_SIZE - DP_DSC_SUPPORT]) & 2895 + DP_DSC_THROUGHPUT_MODE_0_DELTA_MASK) >> 2896 + DP_DSC_THROUGHPUT_MODE_0_DELTA_SHIFT; /* in units of 2 MPixels/sec */ 2897 + delta *= 2000; 2898 + } else { 2899 + throughput = (throughput & DP_DSC_THROUGHPUT_MODE_1_MASK) >> 2900 + DP_DSC_THROUGHPUT_MODE_1_SHIFT; 2901 + } 2902 + 2903 + switch (throughput) { 2904 + case 0: 2905 + return dsc_sink_min_slice_throughput(peak_pixel_rate); 2906 + case 1: 2907 + base = 340000; 2908 + break; 2909 + case 2 ... 14: 2910 + base = 400000 + 50000 * (throughput - 2); 2911 + break; 2912 + case 15: 2913 + base = 170000; 2914 + break; 2915 + } 2916 + 2917 + return base + delta; 2918 + } 2919 + EXPORT_SYMBOL(drm_dp_dsc_sink_max_slice_throughput); 2920 + 2921 + static u8 dsc_branch_dpcd_cap(const u8 dpcd[DP_DSC_BRANCH_CAP_SIZE], int reg) 2922 + { 2923 + return dpcd[reg - DP_DSC_BRANCH_OVERALL_THROUGHPUT_0]; 2924 + } 2925 + 2926 + /** 2927 + * drm_dp_dsc_branch_max_overall_throughput() - Branch device's max overall DSC pixel throughput 2928 + * @dsc_branch_dpcd: DSC branch capabilities from DPCD 2929 + * @is_rgb_yuv444: The mode is either RGB or YUV444 2930 + * 2931 + * Return the branch device's maximum overall DSC pixel throughput, based on 2932 + * the device's DPCD DSC branch capabilities, and whether the output 2933 + * format @is_rgb_yuv444 or yuv422/yuv420. 2934 + * 2935 + * Returns: 2936 + * - 0: The maximum overall throughput capability is not indicated by 2937 + * the device separately and it must be determined from the per-slice 2938 + * max throughput (see @drm_dp_dsc_branch_slice_max_throughput()) 2939 + * and the maximum slice count supported by the device. 2940 + * - > 0: The maximum overall DSC pixel throughput supported by the branch 2941 + * device in kPixels/sec. 2942 + */ 2943 + int drm_dp_dsc_branch_max_overall_throughput(const u8 dsc_branch_dpcd[DP_DSC_BRANCH_CAP_SIZE], 2944 + bool is_rgb_yuv444) 2945 + { 2946 + int throughput; 2947 + 2948 + if (is_rgb_yuv444) 2949 + throughput = dsc_branch_dpcd_cap(dsc_branch_dpcd, 2950 + DP_DSC_BRANCH_OVERALL_THROUGHPUT_0); 2951 + else 2952 + throughput = dsc_branch_dpcd_cap(dsc_branch_dpcd, 2953 + DP_DSC_BRANCH_OVERALL_THROUGHPUT_1); 2954 + 2955 + switch (throughput) { 2956 + case 0: 2957 + return 0; 2958 + case 1: 2959 + return 680000; 2960 + default: 2961 + return 600000 + 50000 * throughput; 2962 + } 2963 + } 2964 + EXPORT_SYMBOL(drm_dp_dsc_branch_max_overall_throughput); 2965 + 2966 + /** 2967 + * drm_dp_dsc_branch_max_line_width() - Branch device's max DSC line width 2968 + * @dsc_branch_dpcd: DSC branch capabilities from DPCD 2969 + * 2970 + * Return the branch device's maximum overall DSC line width, based on 2971 + * the device's @dsc_branch_dpcd capabilities. 2972 + * 2973 + * Returns: 2974 + * - 0: The maximum line width is not indicated by the device 2975 + * separately and it must be determined from the maximum 2976 + * slice count and slice-width supported by the device. 2977 + * - %-EINVAL: The device indicates an invalid maximum line width 2978 + * (< 5120 pixels). 2979 + * - >= 5120: The maximum line width in pixels. 2980 + */ 2981 + int drm_dp_dsc_branch_max_line_width(const u8 dsc_branch_dpcd[DP_DSC_BRANCH_CAP_SIZE]) 2982 + { 2983 + int line_width = dsc_branch_dpcd_cap(dsc_branch_dpcd, DP_DSC_BRANCH_MAX_LINE_WIDTH); 2984 + 2985 + switch (line_width) { 2986 + case 0: 2987 + return 0; 2988 + case 1 ... 15: 2989 + return -EINVAL; 2990 + default: 2991 + return line_width * 320; 2992 + } 2993 + } 2994 + EXPORT_SYMBOL(drm_dp_dsc_branch_max_line_width); 2847 2995 2848 2996 static int drm_dp_read_lttpr_regs(struct drm_dp_aux *aux, 2849 2997 const u8 dpcd[DP_RECEIVER_CAP_SIZE], int address,
+4
drivers/gpu/drm/drm_atomic_uapi.c
··· 419 419 set_out_fence_for_crtc(state->state, crtc, fence_ptr); 420 420 } else if (property == crtc->scaling_filter_property) { 421 421 state->scaling_filter = val; 422 + } else if (property == crtc->sharpness_strength_property) { 423 + state->sharpness_strength = val; 422 424 } else if (crtc->funcs->atomic_set_property) { 423 425 return crtc->funcs->atomic_set_property(crtc, state, property, val); 424 426 } else { ··· 458 456 *val = 0; 459 457 else if (property == crtc->scaling_filter_property) 460 458 *val = state->scaling_filter; 459 + else if (property == crtc->sharpness_strength_property) 460 + *val = state->sharpness_strength; 461 461 else if (crtc->funcs->atomic_get_property) 462 462 return crtc->funcs->atomic_get_property(crtc, state, property, val); 463 463 else {
+35
drivers/gpu/drm/drm_crtc.c
··· 229 229 * Driver's default scaling filter 230 230 * Nearest Neighbor: 231 231 * Nearest Neighbor scaling filter 232 + * SHARPNESS_STRENGTH: 233 + * Atomic property for setting the sharpness strength/intensity by userspace. 234 + * 235 + * The value of this property is set as an integer value ranging 236 + * from 0 - 255 where: 237 + * 238 + * 0: Sharpness feature is disabled(default value). 239 + * 240 + * 1: Minimum sharpness. 241 + * 242 + * 255: Maximum sharpness. 243 + * 244 + * User can gradually increase or decrease the sharpness level and can 245 + * set the optimum value depending on content. 246 + * This value will be passed to kernel through the UAPI. 247 + * The setting of this property does not require modeset. 248 + * The sharpness effect takes place post blending on the final composed output. 249 + * If the feature is disabled, the content remains same without any sharpening effect 250 + * and when this feature is applied, it enhances the clarity of the content. 232 251 */ 233 252 234 253 __printf(6, 0) ··· 958 939 return 0; 959 940 } 960 941 EXPORT_SYMBOL(drm_crtc_create_scaling_filter_property); 942 + 943 + int drm_crtc_create_sharpness_strength_property(struct drm_crtc *crtc) 944 + { 945 + struct drm_device *dev = crtc->dev; 946 + struct drm_property *prop = 947 + drm_property_create_range(dev, 0, "SHARPNESS_STRENGTH", 0, 255); 948 + 949 + if (!prop) 950 + return -ENOMEM; 951 + 952 + crtc->sharpness_strength_property = prop; 953 + drm_object_attach_property(&crtc->base, prop, 0); 954 + 955 + return 0; 956 + } 957 + EXPORT_SYMBOL(drm_crtc_create_sharpness_strength_property); 961 958 962 959 /** 963 960 * drm_crtc_in_clone_mode - check if the given CRTC state is in clone mode
+12
drivers/gpu/drm/i915/Makefile
··· 13 13 # drivers. Define I915 when building i915. 14 14 subdir-ccflags-y += -DI915 15 15 16 + # FIXME: Disable tracepoints on i915 for PREEMPT_RT, unfortunately 17 + # it's an all or nothing flag. You cannot selectively disable 18 + # only some tracepoints. 19 + subdir-ccflags-$(CONFIG_PREEMPT_RT) += -DNOTRACE 20 + 16 21 subdir-ccflags-y += -I$(src) 17 22 18 23 # Please keep these build lists sorted! ··· 31 26 i915_ioctl.o \ 32 27 i915_irq.o \ 33 28 i915_mitigations.o \ 29 + i915_mmio_range.o \ 34 30 i915_module.o \ 35 31 i915_params.o \ 36 32 i915_pci.o \ ··· 234 228 display/intel_bios.o \ 235 229 display/intel_bo.o \ 236 230 display/intel_bw.o \ 231 + display/intel_casf.o \ 237 232 display/intel_cdclk.o \ 238 233 display/intel_cmtg.o \ 239 234 display/intel_color.o \ ··· 243 236 display/intel_crtc.o \ 244 237 display/intel_crtc_state_dump.o \ 245 238 display/intel_cursor.o \ 239 + display/intel_dbuf_bw.o \ 246 240 display/intel_display.o \ 247 241 display/intel_display_conversion.o \ 248 242 display/intel_display_driver.o \ ··· 256 248 display/intel_display_rpm.o \ 257 249 display/intel_display_rps.o \ 258 250 display/intel_display_snapshot.o \ 251 + display/intel_display_utils.o \ 259 252 display/intel_display_wa.o \ 260 253 display/intel_dmc.o \ 261 254 display/intel_dmc_wl.o \ ··· 306 297 display/intel_vblank.o \ 307 298 display/intel_vga.o \ 308 299 display/intel_wm.o \ 300 + display/skl_prefill.o \ 309 301 display/skl_scaler.o \ 310 302 display/skl_universal_plane.o \ 311 303 display/skl_watermark.o \ 304 + display/vlv_clock.o \ 312 305 display/vlv_sideband.o 313 306 i915-$(CONFIG_ACPI) += \ 314 307 display/intel_acpi.o \ ··· 357 346 display/intel_gmbus.o \ 358 347 display/intel_hdmi.o \ 359 348 display/intel_lspcon.o \ 349 + display/intel_lt_phy.o \ 360 350 display/intel_lvds.o \ 361 351 display/intel_panel.o \ 362 352 display/intel_pfit.o \
+1 -1
drivers/gpu/drm/i915/display/g4x_dp.c
··· 11 11 12 12 #include "g4x_dp.h" 13 13 #include "i915_reg.h" 14 - #include "i915_utils.h" 15 14 #include "intel_audio.h" 16 15 #include "intel_backlight.h" 17 16 #include "intel_connector.h" ··· 19 20 #include "intel_display_power.h" 20 21 #include "intel_display_regs.h" 21 22 #include "intel_display_types.h" 23 + #include "intel_display_utils.h" 22 24 #include "intel_dp.h" 23 25 #include "intel_dp_aux.h" 24 26 #include "intel_dp_link_training.h"
+28 -33
drivers/gpu/drm/i915/display/hsw_ips.c
··· 191 191 192 192 static bool hsw_crtc_state_ips_capable(const struct intel_crtc_state *crtc_state) 193 193 { 194 - struct intel_display *display = to_intel_display(crtc_state); 195 194 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 196 195 197 - /* IPS only exists on ULT machines and is tied to pipe A. */ 198 196 if (!hsw_crtc_supports_ips(crtc)) 199 - return false; 200 - 201 - if (!display->params.enable_ips) 202 197 return false; 203 198 204 199 if (crtc_state->pipe_bpp > 24) 205 200 return false; 206 201 207 - /* 208 - * We compare against max which means we must take 209 - * the increased cdclk requirement into account when 210 - * calculating the new cdclk. 211 - * 212 - * Should measure whether using a lower cdclk w/o IPS 213 - */ 214 - if (display->platform.broadwell && 215 - crtc_state->pixel_rate > display->cdclk.max_cdclk_freq * 95 / 100) 216 - return false; 217 - 218 202 return true; 203 + } 204 + 205 + static int _hsw_ips_min_cdclk(const struct intel_crtc_state *crtc_state) 206 + { 207 + struct intel_display *display = to_intel_display(crtc_state); 208 + 209 + if (display->platform.broadwell) 210 + return DIV_ROUND_UP(crtc_state->pixel_rate * 100, 95); 211 + 212 + /* no IPS specific limits to worry about */ 213 + return 0; 219 214 } 220 215 221 216 int hsw_ips_min_cdclk(const struct intel_crtc_state *crtc_state) 222 217 { 223 218 struct intel_display *display = to_intel_display(crtc_state); 224 - 225 - if (!display->platform.broadwell) 226 - return 0; 219 + int min_cdclk; 227 220 228 221 if (!hsw_crtc_state_ips_capable(crtc_state)) 229 222 return 0; 230 223 231 - /* pixel rate mustn't exceed 95% of cdclk with IPS on BDW */ 232 - return DIV_ROUND_UP(crtc_state->pixel_rate * 100, 95); 224 + min_cdclk = _hsw_ips_min_cdclk(crtc_state); 225 + 226 + /* 227 + * Do not ask for more than the max CDCLK frequency, 228 + * if that is not enough IPS will simply not be used. 229 + */ 230 + if (min_cdclk > display->cdclk.max_cdclk_freq) 231 + return 0; 232 + 233 + return min_cdclk; 233 234 } 234 235 235 236 int hsw_ips_compute_config(struct intel_atomic_state *state, ··· 245 244 if (!hsw_crtc_state_ips_capable(crtc_state)) 246 245 return 0; 247 246 247 + if (_hsw_ips_min_cdclk(crtc_state) > display->cdclk.max_cdclk_freq) 248 + return 0; 249 + 250 + if (!display->params.enable_ips) 251 + return 0; 252 + 248 253 /* 249 254 * When IPS gets enabled, the pipe CRC changes. Since IPS gets 250 255 * enabled and disabled dynamically based on package C states, ··· 263 256 /* IPS should be fine as long as at least one plane is enabled. */ 264 257 if (!(crtc_state->active_planes & ~BIT(PLANE_CURSOR))) 265 258 return 0; 266 - 267 - if (display->platform.broadwell) { 268 - const struct intel_cdclk_state *cdclk_state; 269 - 270 - cdclk_state = intel_atomic_get_cdclk_state(state); 271 - if (IS_ERR(cdclk_state)) 272 - return PTR_ERR(cdclk_state); 273 - 274 - /* pixel rate mustn't exceed 95% of cdclk with IPS on BDW */ 275 - if (crtc_state->pixel_rate > intel_cdclk_logical(cdclk_state) * 95 / 100) 276 - return 0; 277 - } 278 259 279 260 crtc_state->ips_enabled = true; 280 261
+1 -1
drivers/gpu/drm/i915/display/i9xx_plane.c
··· 11 11 #include <drm/drm_print.h> 12 12 13 13 #include "i915_reg.h" 14 - #include "i915_utils.h" 15 14 #include "i9xx_plane.h" 16 15 #include "i9xx_plane_regs.h" 17 16 #include "intel_atomic.h" ··· 18 19 #include "intel_display_irq.h" 19 20 #include "intel_display_regs.h" 20 21 #include "intel_display_types.h" 22 + #include "intel_display_utils.h" 21 23 #include "intel_fb.h" 22 24 #include "intel_fbc.h" 23 25 #include "intel_frontbuffer.h"
+3 -4
drivers/gpu/drm/i915/display/i9xx_wm.c
··· 2295 2295 2296 2296 crtc = single_enabled_crtc(display); 2297 2297 if (display->platform.i915gm && crtc) { 2298 - struct drm_gem_object *obj; 2299 - 2300 - obj = intel_fb_bo(crtc->base.primary->state->fb); 2298 + const struct drm_framebuffer *fb = 2299 + crtc->base.primary->state->fb; 2301 2300 2302 2301 /* self-refresh seems busted with untiled */ 2303 - if (!intel_bo_is_tiled(obj)) 2302 + if (fb->modifier == DRM_FORMAT_MOD_LINEAR) 2304 2303 crtc = NULL; 2305 2304 } 2306 2305
+2 -2
drivers/gpu/drm/i915/display/icl_dsi.c
··· 35 35 #include <drm/drm_probe_helper.h> 36 36 37 37 #include "i915_reg.h" 38 - #include "i915_utils.h" 39 38 #include "icl_dsi.h" 40 39 #include "icl_dsi_regs.h" 41 40 #include "intel_atomic.h" ··· 47 48 #include "intel_ddi.h" 48 49 #include "intel_de.h" 49 50 #include "intel_display_regs.h" 51 + #include "intel_display_utils.h" 50 52 #include "intel_dsi.h" 51 53 #include "intel_dsi_vbt.h" 52 54 #include "intel_panel.h" ··· 1655 1655 if (ret) 1656 1656 return ret; 1657 1657 1658 - crtc_state->dsc.compression_enable = true; 1658 + intel_dsc_enable_on_crtc(crtc_state); 1659 1659 1660 1660 return 0; 1661 1661 }
+1 -1
drivers/gpu/drm/i915/display/intel_acpi.c
··· 11 11 12 12 #include <drm/drm_print.h> 13 13 14 - #include "i915_utils.h" 15 14 #include "intel_acpi.h" 16 15 #include "intel_display_core.h" 17 16 #include "intel_display_types.h" 17 + #include "intel_display_utils.h" 18 18 19 19 #define INTEL_DSM_REVISION_ID 1 /* For Calpella anyway... */ 20 20 #define INTEL_DSM_FN_PLATFORM_MUX_INFO 1 /* No args */
+39 -52
drivers/gpu/drm/i915/display/intel_alpm.c
··· 49 49 return; 50 50 51 51 intel_dp->alpm_dpcd = dpcd; 52 - mutex_init(&intel_dp->alpm_parameters.lock); 52 + mutex_init(&intel_dp->alpm.lock); 53 53 } 54 54 55 55 static int get_silence_period_symbols(const struct intel_crtc_state *crtc_state) ··· 58 58 1000 / 1000; 59 59 } 60 60 61 - static int get_lfps_cycle_min_max_time(const struct intel_crtc_state *crtc_state, 62 - int *min, int *max) 61 + static void get_lfps_cycle_min_max_time(const struct intel_crtc_state *crtc_state, 62 + int *min, int *max) 63 63 { 64 64 if (crtc_state->port_clock < 540000) { 65 65 *min = 65 * LFPS_CYCLE_COUNT; 66 66 *max = 75 * LFPS_CYCLE_COUNT; 67 - } else if (crtc_state->port_clock <= 810000) { 67 + } else { 68 68 *min = 140; 69 69 *max = 800; 70 - } else { 71 - *min = *max = -1; 72 - return -1; 73 70 } 74 - 75 - return 0; 76 71 } 77 72 78 73 static int get_lfps_cycle_time(const struct intel_crtc_state *crtc_state) 79 74 { 80 - int tlfps_cycle_min, tlfps_cycle_max, ret; 75 + int tlfps_cycle_min, tlfps_cycle_max; 81 76 82 - ret = get_lfps_cycle_min_max_time(crtc_state, &tlfps_cycle_min, 83 - &tlfps_cycle_max); 84 - if (ret) 85 - return ret; 77 + get_lfps_cycle_min_max_time(crtc_state, &tlfps_cycle_min, 78 + &tlfps_cycle_max); 86 79 87 80 return tlfps_cycle_min + (tlfps_cycle_max - tlfps_cycle_min) / 2; 88 81 } 89 82 90 83 static int get_lfps_half_cycle_clocks(const struct intel_crtc_state *crtc_state) 91 84 { 92 - int lfps_cycle_time = get_lfps_cycle_time(crtc_state); 93 - 94 - if (lfps_cycle_time < 0) 95 - return -1; 96 - 97 - return lfps_cycle_time * crtc_state->port_clock / 1000 / 1000 / (2 * LFPS_CYCLE_COUNT); 85 + return get_lfps_cycle_time(crtc_state) * crtc_state->port_clock / 1000 / 86 + 1000 / (2 * LFPS_CYCLE_COUNT); 98 87 } 99 88 100 89 /* ··· 122 133 123 134 static int 124 135 _lnl_compute_aux_less_alpm_params(struct intel_dp *intel_dp, 125 - const struct intel_crtc_state *crtc_state) 136 + struct intel_crtc_state *crtc_state) 126 137 { 127 138 struct intel_display *display = to_intel_display(intel_dp); 128 139 int aux_less_wake_time, aux_less_wake_lines, silence_period, ··· 135 146 silence_period = get_silence_period_symbols(crtc_state); 136 147 137 148 lfps_half_cycle = get_lfps_half_cycle_clocks(crtc_state); 138 - if (lfps_half_cycle < 0) 139 - return false; 140 149 141 150 if (aux_less_wake_lines > ALPM_CTL_AUX_LESS_WAKE_TIME_MASK || 142 151 silence_period > PORT_ALPM_CTL_SILENCE_PERIOD_MASK || ··· 144 157 if (display->params.psr_safest_params) 145 158 aux_less_wake_lines = ALPM_CTL_AUX_LESS_WAKE_TIME_MASK; 146 159 147 - intel_dp->alpm_parameters.aux_less_wake_lines = aux_less_wake_lines; 148 - intel_dp->alpm_parameters.silence_period_sym_clocks = silence_period; 149 - intel_dp->alpm_parameters.lfps_half_cycle_num_of_syms = lfps_half_cycle; 160 + crtc_state->alpm_state.aux_less_wake_lines = aux_less_wake_lines; 161 + crtc_state->alpm_state.silence_period_sym_clocks = silence_period; 162 + crtc_state->alpm_state.lfps_half_cycle_num_of_syms = lfps_half_cycle; 150 163 151 164 return true; 152 165 } 153 166 154 167 static bool _lnl_compute_alpm_params(struct intel_dp *intel_dp, 155 - const struct intel_crtc_state *crtc_state) 168 + struct intel_crtc_state *crtc_state) 156 169 { 157 170 struct intel_display *display = to_intel_display(intel_dp); 158 171 int check_entry_lines; ··· 173 186 if (display->params.psr_safest_params) 174 187 check_entry_lines = 15; 175 188 176 - intel_dp->alpm_parameters.check_entry_lines = check_entry_lines; 189 + crtc_state->alpm_state.check_entry_lines = check_entry_lines; 177 190 178 191 return true; 179 192 } ··· 204 217 } 205 218 206 219 bool intel_alpm_compute_params(struct intel_dp *intel_dp, 207 - const struct intel_crtc_state *crtc_state) 220 + struct intel_crtc_state *crtc_state) 208 221 { 209 222 struct intel_display *display = to_intel_display(intel_dp); 210 223 int io_wake_lines, io_wake_time, fast_wake_lines, fast_wake_time; ··· 242 255 io_wake_lines = fast_wake_lines = max_wake_lines; 243 256 244 257 /* According to Bspec lower limit should be set as 7 lines. */ 245 - intel_dp->alpm_parameters.io_wake_lines = max(io_wake_lines, 7); 246 - intel_dp->alpm_parameters.fast_wake_lines = max(fast_wake_lines, 7); 258 + crtc_state->alpm_state.io_wake_lines = max(io_wake_lines, 7); 259 + crtc_state->alpm_state.fast_wake_lines = max(fast_wake_lines, 7); 247 260 248 261 return true; 249 262 } ··· 257 270 int waketime_in_lines, first_sdp_position; 258 271 int context_latency, guardband; 259 272 260 - if (intel_dp->alpm_parameters.lobf_disable_debug) { 273 + if (intel_dp->alpm.lobf_disable_debug) { 261 274 drm_dbg_kms(display->drm, "LOBF is disabled by debug flag\n"); 262 275 return; 263 276 } 264 277 265 - if (intel_dp->alpm_parameters.sink_alpm_error) 278 + if (intel_dp->alpm.sink_alpm_error) 266 279 return; 267 280 268 281 if (!intel_dp_is_edp(intel_dp)) ··· 293 306 adjusted_mode->crtc_vdisplay - context_latency; 294 307 first_sdp_position = adjusted_mode->crtc_vtotal - adjusted_mode->crtc_vsync_start; 295 308 if (intel_alpm_aux_less_wake_supported(intel_dp)) 296 - waketime_in_lines = intel_dp->alpm_parameters.io_wake_lines; 309 + waketime_in_lines = crtc_state->alpm_state.io_wake_lines; 297 310 else 298 - waketime_in_lines = intel_dp->alpm_parameters.aux_less_wake_lines; 311 + waketime_in_lines = crtc_state->alpm_state.aux_less_wake_lines; 299 312 300 313 crtc_state->has_lobf = (context_latency + guardband) > 301 314 (first_sdp_position + waketime_in_lines); ··· 312 325 !crtc_state->has_lobf)) 313 326 return; 314 327 315 - mutex_lock(&intel_dp->alpm_parameters.lock); 328 + mutex_lock(&intel_dp->alpm.lock); 316 329 /* 317 330 * Panel Replay on eDP is always using ALPM aux less. I.e. no need to 318 331 * check panel support at this point. ··· 321 334 alpm_ctl = ALPM_CTL_ALPM_ENABLE | 322 335 ALPM_CTL_ALPM_AUX_LESS_ENABLE | 323 336 ALPM_CTL_AUX_LESS_SLEEP_HOLD_TIME_50_SYMBOLS | 324 - ALPM_CTL_AUX_LESS_WAKE_TIME(intel_dp->alpm_parameters.aux_less_wake_lines); 337 + ALPM_CTL_AUX_LESS_WAKE_TIME(crtc_state->alpm_state.aux_less_wake_lines); 325 338 326 339 if (intel_dp->as_sdp_supported) { 327 340 u32 pr_alpm_ctl = PR_ALPM_CTL_ADAPTIVE_SYNC_SDP_POSITION_T1; ··· 339 352 340 353 } else { 341 354 alpm_ctl = ALPM_CTL_EXTENDED_FAST_WAKE_ENABLE | 342 - ALPM_CTL_EXTENDED_FAST_WAKE_TIME(intel_dp->alpm_parameters.fast_wake_lines); 355 + ALPM_CTL_EXTENDED_FAST_WAKE_TIME(crtc_state->alpm_state.fast_wake_lines); 343 356 } 344 357 345 358 if (crtc_state->has_lobf) { ··· 347 360 drm_dbg_kms(display->drm, "Link off between frames (LOBF) enabled\n"); 348 361 } 349 362 350 - alpm_ctl |= ALPM_CTL_ALPM_ENTRY_CHECK(intel_dp->alpm_parameters.check_entry_lines); 363 + alpm_ctl |= ALPM_CTL_ALPM_ENTRY_CHECK(crtc_state->alpm_state.check_entry_lines); 351 364 352 365 intel_de_write(display, ALPM_CTL(display, cpu_transcoder), alpm_ctl); 353 - mutex_unlock(&intel_dp->alpm_parameters.lock); 366 + mutex_unlock(&intel_dp->alpm.lock); 354 367 } 355 368 356 369 void intel_alpm_configure(struct intel_dp *intel_dp, 357 370 const struct intel_crtc_state *crtc_state) 358 371 { 359 372 lnl_alpm_configure(intel_dp, crtc_state); 360 - intel_dp->alpm_parameters.transcoder = crtc_state->cpu_transcoder; 373 + intel_dp->alpm.transcoder = crtc_state->cpu_transcoder; 361 374 } 362 375 363 376 void intel_alpm_port_configure(struct intel_dp *intel_dp, ··· 375 388 PORT_ALPM_CTL_MAX_PHY_SWING_SETUP(15) | 376 389 PORT_ALPM_CTL_MAX_PHY_SWING_HOLD(0) | 377 390 PORT_ALPM_CTL_SILENCE_PERIOD( 378 - intel_dp->alpm_parameters.silence_period_sym_clocks); 391 + crtc_state->alpm_state.silence_period_sym_clocks); 379 392 lfps_ctl_val = PORT_ALPM_LFPS_CTL_LFPS_CYCLE_COUNT(LFPS_CYCLE_COUNT) | 380 393 PORT_ALPM_LFPS_CTL_LFPS_HALF_CYCLE_DURATION( 381 - intel_dp->alpm_parameters.lfps_half_cycle_num_of_syms) | 394 + crtc_state->alpm_state.lfps_half_cycle_num_of_syms) | 382 395 PORT_ALPM_LFPS_CTL_FIRST_LFPS_HALF_CYCLE_DURATION( 383 - intel_dp->alpm_parameters.lfps_half_cycle_num_of_syms) | 396 + crtc_state->alpm_state.lfps_half_cycle_num_of_syms) | 384 397 PORT_ALPM_LFPS_CTL_LAST_LFPS_HALF_CYCLE_DURATION( 385 - intel_dp->alpm_parameters.lfps_half_cycle_num_of_syms); 398 + crtc_state->alpm_state.lfps_half_cycle_num_of_syms); 386 399 } 387 400 388 401 intel_de_write(display, PORT_ALPM_CTL(port), alpm_ctl_val); ··· 420 433 continue; 421 434 422 435 if (old_crtc_state->has_lobf) { 423 - mutex_lock(&intel_dp->alpm_parameters.lock); 436 + mutex_lock(&intel_dp->alpm.lock); 424 437 intel_de_write(display, ALPM_CTL(display, cpu_transcoder), 0); 425 438 drm_dbg_kms(display->drm, "Link off between frames (LOBF) disabled\n"); 426 - mutex_unlock(&intel_dp->alpm_parameters.lock); 439 + mutex_unlock(&intel_dp->alpm.lock); 427 440 } 428 441 } 429 442 } ··· 517 530 struct intel_connector *connector = data; 518 531 struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder); 519 532 520 - *val = intel_dp->alpm_parameters.lobf_disable_debug; 533 + *val = intel_dp->alpm.lobf_disable_debug; 521 534 522 535 return 0; 523 536 } ··· 528 541 struct intel_connector *connector = data; 529 542 struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder); 530 543 531 - intel_dp->alpm_parameters.lobf_disable_debug = val; 544 + intel_dp->alpm.lobf_disable_debug = val; 532 545 533 546 return 0; 534 547 } ··· 556 569 void intel_alpm_disable(struct intel_dp *intel_dp) 557 570 { 558 571 struct intel_display *display = to_intel_display(intel_dp); 559 - enum transcoder cpu_transcoder = intel_dp->alpm_parameters.transcoder; 572 + enum transcoder cpu_transcoder = intel_dp->alpm.transcoder; 560 573 561 574 if (DISPLAY_VER(display) < 20 || !intel_dp->alpm_dpcd) 562 575 return; 563 576 564 - mutex_lock(&intel_dp->alpm_parameters.lock); 577 + mutex_lock(&intel_dp->alpm.lock); 565 578 566 579 intel_de_rmw(display, ALPM_CTL(display, cpu_transcoder), 567 580 ALPM_CTL_ALPM_ENABLE | ALPM_CTL_LOBF_ENABLE | ··· 572 585 PORT_ALPM_CTL_ALPM_AUX_LESS_ENABLE, 0); 573 586 574 587 drm_dbg_kms(display->drm, "Disabling ALPM\n"); 575 - mutex_unlock(&intel_dp->alpm_parameters.lock); 588 + mutex_unlock(&intel_dp->alpm.lock); 576 589 } 577 590 578 591 bool intel_alpm_get_error(struct intel_dp *intel_dp)
+1 -1
drivers/gpu/drm/i915/display/intel_alpm.h
··· 17 17 18 18 void intel_alpm_init(struct intel_dp *intel_dp); 19 19 bool intel_alpm_compute_params(struct intel_dp *intel_dp, 20 - const struct intel_crtc_state *crtc_state); 20 + struct intel_crtc_state *crtc_state); 21 21 void intel_alpm_lobf_compute_config(struct intel_dp *intel_dp, 22 22 struct intel_crtc_state *crtc_state, 23 23 struct drm_connector_state *conn_state);
+1 -1
drivers/gpu/drm/i915/display/intel_backlight.c
··· 13 13 #include <drm/drm_print.h> 14 14 15 15 #include "i915_reg.h" 16 - #include "i915_utils.h" 17 16 #include "intel_backlight.h" 18 17 #include "intel_backlight_regs.h" 19 18 #include "intel_connector.h" ··· 20 21 #include "intel_display_regs.h" 21 22 #include "intel_display_rpm.h" 22 23 #include "intel_display_types.h" 24 + #include "intel_display_utils.h" 23 25 #include "intel_dp_aux_backlight.h" 24 26 #include "intel_dsi_dcs_backlight.h" 25 27 #include "intel_panel.h"
+1 -1
drivers/gpu/drm/i915/display/intel_bios.c
··· 36 36 #include "soc/intel_rom.h" 37 37 38 38 #include "i915_drv.h" 39 - #include "i915_utils.h" 40 39 #include "intel_display.h" 41 40 #include "intel_display_core.h" 42 41 #include "intel_display_rpm.h" 43 42 #include "intel_display_types.h" 43 + #include "intel_display_utils.h" 44 44 #include "intel_gmbus.h" 45 45 46 46 #define _INTEL_BIOS_PRIVATE
+18 -297
drivers/gpu/drm/i915/display/intel_bw.c
··· 3 3 * Copyright © 2019 Intel Corporation 4 4 */ 5 5 6 - #include <drm/drm_atomic_state_helper.h> 7 - 8 6 #include "soc/intel_dram.h" 9 7 10 8 #include "i915_drv.h" 11 9 #include "i915_reg.h" 12 - #include "i915_utils.h" 13 - #include "intel_atomic.h" 14 10 #include "intel_bw.h" 15 - #include "intel_cdclk.h" 11 + #include "intel_crtc.h" 16 12 #include "intel_display_core.h" 17 13 #include "intel_display_regs.h" 18 14 #include "intel_display_types.h" 15 + #include "intel_display_utils.h" 19 16 #include "intel_mchbar_regs.h" 20 17 #include "intel_pcode.h" 21 18 #include "intel_uncore.h" 22 19 #include "skl_watermark.h" 23 20 24 - struct intel_dbuf_bw { 25 - unsigned int max_bw[I915_MAX_DBUF_SLICES]; 26 - u8 active_planes[I915_MAX_DBUF_SLICES]; 27 - }; 28 - 29 21 struct intel_bw_state { 30 22 struct intel_global_state base; 31 - struct intel_dbuf_bw dbuf_bw[I915_MAX_PIPES]; 32 23 33 24 /* 34 25 * Contains a bit mask, used to determine, whether correspondent ··· 827 836 icl_get_bw_info(display, dram_info, &icl_sa_info); 828 837 } 829 838 830 - static unsigned int intel_bw_crtc_num_active_planes(const struct intel_crtc_state *crtc_state) 831 - { 832 - /* 833 - * We assume cursors are small enough 834 - * to not not cause bandwidth problems. 835 - */ 836 - return hweight8(crtc_state->active_planes & ~BIT(PLANE_CURSOR)); 837 - } 838 - 839 - static unsigned int intel_bw_crtc_data_rate(const struct intel_crtc_state *crtc_state) 840 - { 841 - struct intel_display *display = to_intel_display(crtc_state); 842 - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 843 - unsigned int data_rate = 0; 844 - enum plane_id plane_id; 845 - 846 - for_each_plane_id_on_crtc(crtc, plane_id) { 847 - /* 848 - * We assume cursors are small enough 849 - * to not not cause bandwidth problems. 850 - */ 851 - if (plane_id == PLANE_CURSOR) 852 - continue; 853 - 854 - data_rate += crtc_state->data_rate[plane_id]; 855 - 856 - if (DISPLAY_VER(display) < 11) 857 - data_rate += crtc_state->data_rate_y[plane_id]; 858 - } 859 - 860 - return data_rate; 861 - } 862 - 863 - /* "Maximum Pipe Read Bandwidth" */ 864 - static int intel_bw_crtc_min_cdclk(struct intel_display *display, 865 - unsigned int data_rate) 866 - { 867 - if (DISPLAY_VER(display) < 12) 868 - return 0; 869 - 870 - return DIV_ROUND_UP_ULL(mul_u32_u32(data_rate, 10), 512); 871 - } 872 - 873 839 static unsigned int intel_bw_num_active_planes(struct intel_display *display, 874 840 const struct intel_bw_state *bw_state) 875 841 { ··· 842 894 static unsigned int intel_bw_data_rate(struct intel_display *display, 843 895 const struct intel_bw_state *bw_state) 844 896 { 845 - struct drm_i915_private *i915 = to_i915(display->drm); 846 897 unsigned int data_rate = 0; 847 898 enum pipe pipe; 848 899 849 900 for_each_pipe(display, pipe) 850 901 data_rate += bw_state->data_rate[pipe]; 851 902 852 - if (DISPLAY_VER(display) >= 13 && i915_vtd_active(i915)) 903 + if (DISPLAY_VER(display) >= 13 && intel_display_vtd_active(display)) 853 904 data_rate = DIV_ROUND_UP(data_rate * 105, 100); 854 905 855 906 return data_rate; ··· 1209 1262 old_bw_state, new_bw_state); 1210 1263 } 1211 1264 1212 - static bool intel_dbuf_bw_changed(struct intel_display *display, 1213 - const struct intel_dbuf_bw *old_dbuf_bw, 1214 - const struct intel_dbuf_bw *new_dbuf_bw) 1215 - { 1216 - enum dbuf_slice slice; 1217 - 1218 - for_each_dbuf_slice(display, slice) { 1219 - if (old_dbuf_bw->max_bw[slice] != new_dbuf_bw->max_bw[slice] || 1220 - old_dbuf_bw->active_planes[slice] != new_dbuf_bw->active_planes[slice]) 1221 - return true; 1222 - } 1223 - 1224 - return false; 1225 - } 1226 - 1227 - static bool intel_bw_state_changed(struct intel_display *display, 1228 - const struct intel_bw_state *old_bw_state, 1229 - const struct intel_bw_state *new_bw_state) 1230 - { 1231 - enum pipe pipe; 1232 - 1233 - for_each_pipe(display, pipe) { 1234 - const struct intel_dbuf_bw *old_dbuf_bw = 1235 - &old_bw_state->dbuf_bw[pipe]; 1236 - const struct intel_dbuf_bw *new_dbuf_bw = 1237 - &new_bw_state->dbuf_bw[pipe]; 1238 - 1239 - if (intel_dbuf_bw_changed(display, old_dbuf_bw, new_dbuf_bw)) 1240 - return true; 1241 - 1242 - if (intel_bw_crtc_min_cdclk(display, old_bw_state->data_rate[pipe]) != 1243 - intel_bw_crtc_min_cdclk(display, new_bw_state->data_rate[pipe])) 1244 - return true; 1245 - } 1246 - 1247 - return false; 1248 - } 1249 - 1250 - static void skl_plane_calc_dbuf_bw(struct intel_dbuf_bw *dbuf_bw, 1251 - struct intel_crtc *crtc, 1252 - enum plane_id plane_id, 1253 - const struct skl_ddb_entry *ddb, 1254 - unsigned int data_rate) 1255 - { 1256 - struct intel_display *display = to_intel_display(crtc); 1257 - unsigned int dbuf_mask = skl_ddb_dbuf_slice_mask(display, ddb); 1258 - enum dbuf_slice slice; 1259 - 1260 - /* 1261 - * The arbiter can only really guarantee an 1262 - * equal share of the total bw to each plane. 1263 - */ 1264 - for_each_dbuf_slice_in_mask(display, slice, dbuf_mask) { 1265 - dbuf_bw->max_bw[slice] = max(dbuf_bw->max_bw[slice], data_rate); 1266 - dbuf_bw->active_planes[slice] |= BIT(plane_id); 1267 - } 1268 - } 1269 - 1270 - static void skl_crtc_calc_dbuf_bw(struct intel_dbuf_bw *dbuf_bw, 1271 - const struct intel_crtc_state *crtc_state) 1272 - { 1273 - struct intel_display *display = to_intel_display(crtc_state); 1274 - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 1275 - enum plane_id plane_id; 1276 - 1277 - memset(dbuf_bw, 0, sizeof(*dbuf_bw)); 1278 - 1279 - if (!crtc_state->hw.active) 1280 - return; 1281 - 1282 - for_each_plane_id_on_crtc(crtc, plane_id) { 1283 - /* 1284 - * We assume cursors are small enough 1285 - * to not cause bandwidth problems. 1286 - */ 1287 - if (plane_id == PLANE_CURSOR) 1288 - continue; 1289 - 1290 - skl_plane_calc_dbuf_bw(dbuf_bw, crtc, plane_id, 1291 - &crtc_state->wm.skl.plane_ddb[plane_id], 1292 - crtc_state->data_rate[plane_id]); 1293 - 1294 - if (DISPLAY_VER(display) < 11) 1295 - skl_plane_calc_dbuf_bw(dbuf_bw, crtc, plane_id, 1296 - &crtc_state->wm.skl.plane_ddb_y[plane_id], 1297 - crtc_state->data_rate[plane_id]); 1298 - } 1299 - } 1300 - 1301 - /* "Maximum Data Buffer Bandwidth" */ 1302 - static int 1303 - intel_bw_dbuf_min_cdclk(struct intel_display *display, 1304 - const struct intel_bw_state *bw_state) 1305 - { 1306 - unsigned int total_max_bw = 0; 1307 - enum dbuf_slice slice; 1308 - 1309 - for_each_dbuf_slice(display, slice) { 1310 - int num_active_planes = 0; 1311 - unsigned int max_bw = 0; 1312 - enum pipe pipe; 1313 - 1314 - /* 1315 - * The arbiter can only really guarantee an 1316 - * equal share of the total bw to each plane. 1317 - */ 1318 - for_each_pipe(display, pipe) { 1319 - const struct intel_dbuf_bw *dbuf_bw = &bw_state->dbuf_bw[pipe]; 1320 - 1321 - max_bw = max(dbuf_bw->max_bw[slice], max_bw); 1322 - num_active_planes += hweight8(dbuf_bw->active_planes[slice]); 1323 - } 1324 - max_bw *= num_active_planes; 1325 - 1326 - total_max_bw = max(total_max_bw, max_bw); 1327 - } 1328 - 1329 - return DIV_ROUND_UP(total_max_bw, 64); 1330 - } 1331 - 1332 - int intel_bw_min_cdclk(struct intel_display *display, 1333 - const struct intel_bw_state *bw_state) 1334 - { 1335 - enum pipe pipe; 1336 - int min_cdclk; 1337 - 1338 - min_cdclk = intel_bw_dbuf_min_cdclk(display, bw_state); 1339 - 1340 - for_each_pipe(display, pipe) 1341 - min_cdclk = max(min_cdclk, 1342 - intel_bw_crtc_min_cdclk(display, 1343 - bw_state->data_rate[pipe])); 1344 - 1345 - return min_cdclk; 1346 - } 1347 - 1348 - int intel_bw_calc_min_cdclk(struct intel_atomic_state *state, 1349 - bool *need_cdclk_calc) 1350 - { 1351 - struct intel_display *display = to_intel_display(state); 1352 - struct intel_bw_state *new_bw_state = NULL; 1353 - const struct intel_bw_state *old_bw_state = NULL; 1354 - const struct intel_cdclk_state *cdclk_state; 1355 - const struct intel_crtc_state *old_crtc_state; 1356 - const struct intel_crtc_state *new_crtc_state; 1357 - int old_min_cdclk, new_min_cdclk; 1358 - struct intel_crtc *crtc; 1359 - int i; 1360 - 1361 - if (DISPLAY_VER(display) < 9) 1362 - return 0; 1363 - 1364 - for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, 1365 - new_crtc_state, i) { 1366 - struct intel_dbuf_bw old_dbuf_bw, new_dbuf_bw; 1367 - 1368 - skl_crtc_calc_dbuf_bw(&old_dbuf_bw, old_crtc_state); 1369 - skl_crtc_calc_dbuf_bw(&new_dbuf_bw, new_crtc_state); 1370 - 1371 - if (!intel_dbuf_bw_changed(display, &old_dbuf_bw, &new_dbuf_bw)) 1372 - continue; 1373 - 1374 - new_bw_state = intel_atomic_get_bw_state(state); 1375 - if (IS_ERR(new_bw_state)) 1376 - return PTR_ERR(new_bw_state); 1377 - 1378 - old_bw_state = intel_atomic_get_old_bw_state(state); 1379 - 1380 - new_bw_state->dbuf_bw[crtc->pipe] = new_dbuf_bw; 1381 - } 1382 - 1383 - if (!old_bw_state) 1384 - return 0; 1385 - 1386 - if (intel_bw_state_changed(display, old_bw_state, new_bw_state)) { 1387 - int ret = intel_atomic_lock_global_state(&new_bw_state->base); 1388 - if (ret) 1389 - return ret; 1390 - } 1391 - 1392 - old_min_cdclk = intel_bw_min_cdclk(display, old_bw_state); 1393 - new_min_cdclk = intel_bw_min_cdclk(display, new_bw_state); 1394 - 1395 - /* 1396 - * No need to check against the cdclk state if 1397 - * the min cdclk doesn't increase. 1398 - * 1399 - * Ie. we only ever increase the cdclk due to bandwidth 1400 - * requirements. This can reduce back and forth 1401 - * display blinking due to constant cdclk changes. 1402 - */ 1403 - if (new_min_cdclk <= old_min_cdclk) 1404 - return 0; 1405 - 1406 - cdclk_state = intel_atomic_get_cdclk_state(state); 1407 - if (IS_ERR(cdclk_state)) 1408 - return PTR_ERR(cdclk_state); 1409 - 1410 - /* 1411 - * No need to recalculate the cdclk state if 1412 - * the min cdclk doesn't increase. 1413 - * 1414 - * Ie. we only ever increase the cdclk due to bandwidth 1415 - * requirements. This can reduce back and forth 1416 - * display blinking due to constant cdclk changes. 1417 - */ 1418 - if (new_min_cdclk <= intel_cdclk_bw_min_cdclk(cdclk_state)) 1419 - return 0; 1420 - 1421 - drm_dbg_kms(display->drm, 1422 - "new bandwidth min cdclk (%d kHz) > old min cdclk (%d kHz)\n", 1423 - new_min_cdclk, intel_cdclk_bw_min_cdclk(cdclk_state)); 1424 - *need_cdclk_calc = true; 1425 - 1426 - return 0; 1427 - } 1428 - 1429 1265 static int intel_bw_check_data_rate(struct intel_atomic_state *state, bool *changed) 1430 1266 { 1431 1267 struct intel_display *display = to_intel_display(state); ··· 1219 1489 for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, 1220 1490 new_crtc_state, i) { 1221 1491 unsigned int old_data_rate = 1222 - intel_bw_crtc_data_rate(old_crtc_state); 1492 + intel_crtc_bw_data_rate(old_crtc_state); 1223 1493 unsigned int new_data_rate = 1224 - intel_bw_crtc_data_rate(new_crtc_state); 1494 + intel_crtc_bw_data_rate(new_crtc_state); 1225 1495 unsigned int old_active_planes = 1226 - intel_bw_crtc_num_active_planes(old_crtc_state); 1496 + intel_crtc_bw_num_active_planes(old_crtc_state); 1227 1497 unsigned int new_active_planes = 1228 - intel_bw_crtc_num_active_planes(new_crtc_state); 1498 + intel_crtc_bw_num_active_planes(new_crtc_state); 1229 1499 struct intel_bw_state *new_bw_state; 1230 1500 1231 1501 /* ··· 1257 1527 1258 1528 static int intel_bw_modeset_checks(struct intel_atomic_state *state) 1259 1529 { 1260 - struct intel_display *display = to_intel_display(state); 1261 1530 const struct intel_bw_state *old_bw_state; 1262 1531 struct intel_bw_state *new_bw_state; 1532 + int ret; 1263 1533 1264 - if (DISPLAY_VER(display) < 9) 1534 + if (!intel_any_crtc_active_changed(state)) 1265 1535 return 0; 1266 1536 1267 1537 new_bw_state = intel_atomic_get_bw_state(state); ··· 1273 1543 new_bw_state->active_pipes = 1274 1544 intel_calc_active_pipes(state, old_bw_state->active_pipes); 1275 1545 1276 - if (new_bw_state->active_pipes != old_bw_state->active_pipes) { 1277 - int ret; 1278 - 1279 - ret = intel_atomic_lock_global_state(&new_bw_state->base); 1280 - if (ret) 1281 - return ret; 1282 - } 1546 + ret = intel_atomic_lock_global_state(&new_bw_state->base); 1547 + if (ret) 1548 + return ret; 1283 1549 1284 1550 return 0; 1285 1551 } ··· 1325 1599 return 0; 1326 1600 } 1327 1601 1328 - int intel_bw_atomic_check(struct intel_atomic_state *state, bool any_ms) 1602 + int intel_bw_atomic_check(struct intel_atomic_state *state) 1329 1603 { 1330 1604 struct intel_display *display = to_intel_display(state); 1331 1605 bool changed = false; ··· 1336 1610 if (DISPLAY_VER(display) < 9) 1337 1611 return 0; 1338 1612 1339 - if (any_ms) { 1340 - ret = intel_bw_modeset_checks(state); 1341 - if (ret) 1342 - return ret; 1343 - } 1613 + ret = intel_bw_modeset_checks(state); 1614 + if (ret) 1615 + return ret; 1344 1616 1345 1617 ret = intel_bw_check_sagv_mask(state); 1346 1618 if (ret) ··· 1381 1657 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 1382 1658 1383 1659 bw_state->data_rate[crtc->pipe] = 1384 - intel_bw_crtc_data_rate(crtc_state); 1660 + intel_crtc_bw_data_rate(crtc_state); 1385 1661 bw_state->num_active_planes[crtc->pipe] = 1386 - intel_bw_crtc_num_active_planes(crtc_state); 1662 + intel_crtc_bw_num_active_planes(crtc_state); 1387 1663 1388 1664 drm_dbg_kms(display->drm, "pipe %c data rate %u num active planes %u\n", 1389 1665 pipe_name(crtc->pipe), ··· 1414 1690 if (DISPLAY_VER(display) >= 11) 1415 1691 intel_bw_crtc_update(bw_state, crtc_state); 1416 1692 1417 - skl_crtc_calc_dbuf_bw(&bw_state->dbuf_bw[pipe], crtc_state); 1418 - 1419 1693 /* initially SAGV has been forced off */ 1420 1694 bw_state->pipe_sagv_reject |= BIT(pipe); 1421 1695 } ··· 1431 1709 1432 1710 bw_state->data_rate[pipe] = 0; 1433 1711 bw_state->num_active_planes[pipe] = 0; 1434 - memset(&bw_state->dbuf_bw[pipe], 0, sizeof(bw_state->dbuf_bw[pipe])); 1435 1712 } 1436 1713 1437 1714 static struct intel_global_state *
+1 -5
drivers/gpu/drm/i915/display/intel_bw.h
··· 28 28 29 29 void intel_bw_init_hw(struct intel_display *display); 30 30 int intel_bw_init(struct intel_display *display); 31 - int intel_bw_atomic_check(struct intel_atomic_state *state, bool any_ms); 32 - int intel_bw_calc_min_cdclk(struct intel_atomic_state *state, 33 - bool *need_cdclk_calc); 34 - int intel_bw_min_cdclk(struct intel_display *display, 35 - const struct intel_bw_state *bw_state); 31 + int intel_bw_atomic_check(struct intel_atomic_state *state); 36 32 void intel_bw_update_hw_state(struct intel_display *display); 37 33 void intel_bw_crtc_disable_noatomic(struct intel_crtc *crtc); 38 34
+290
drivers/gpu/drm/i915/display/intel_casf.c
··· 1 + // SPDX-License-Identifier: MIT 2 + /* Copyright © 2025 Intel Corporation */ 3 + 4 + #include <drm/drm_print.h> 5 + 6 + #include "i915_reg.h" 7 + #include "intel_casf.h" 8 + #include "intel_casf_regs.h" 9 + #include "intel_de.h" 10 + #include "intel_display_regs.h" 11 + #include "intel_display_types.h" 12 + #include "skl_scaler.h" 13 + 14 + #define MAX_PIXELS_FOR_3_TAP_FILTER (1920 * 1080) 15 + #define MAX_PIXELS_FOR_5_TAP_FILTER (3840 * 2160) 16 + 17 + #define FILTER_COEFF_0_125 125 18 + #define FILTER_COEFF_0_25 250 19 + #define FILTER_COEFF_0_5 500 20 + #define FILTER_COEFF_1_0 1000 21 + #define FILTER_COEFF_0_0 0 22 + #define SET_POSITIVE_SIGN(x) ((x) & (~SIGN)) 23 + 24 + /** 25 + * DOC: Content Adaptive Sharpness Filter (CASF) 26 + * 27 + * Starting from LNL the display engine supports an 28 + * adaptive sharpening filter, enhancing the image 29 + * quality. The display hardware utilizes the second 30 + * pipe scaler for implementing CASF. 31 + * If sharpness is being enabled then pipe scaling 32 + * cannot be used. 33 + * This filter operates on a region of pixels based 34 + * on the tap size. Coefficients are used to generate 35 + * an alpha value which blends the sharpened image to 36 + * original image. 37 + */ 38 + 39 + /* Default LUT values to be loaded one time. */ 40 + static const u16 sharpness_lut[] = { 41 + 4095, 2047, 1364, 1022, 816, 678, 579, 42 + 504, 444, 397, 357, 323, 293, 268, 244, 224, 43 + 204, 187, 170, 154, 139, 125, 111, 98, 85, 44 + 73, 60, 48, 36, 24, 12, 0 45 + }; 46 + 47 + const u16 filtercoeff_1[] = { 48 + FILTER_COEFF_0_0, FILTER_COEFF_0_0, FILTER_COEFF_0_5, 49 + FILTER_COEFF_1_0, FILTER_COEFF_0_5, FILTER_COEFF_0_0, 50 + FILTER_COEFF_0_0, 51 + }; 52 + 53 + const u16 filtercoeff_2[] = { 54 + FILTER_COEFF_0_0, FILTER_COEFF_0_25, FILTER_COEFF_0_5, 55 + FILTER_COEFF_1_0, FILTER_COEFF_0_5, FILTER_COEFF_0_25, 56 + FILTER_COEFF_0_0, 57 + }; 58 + 59 + const u16 filtercoeff_3[] = { 60 + FILTER_COEFF_0_125, FILTER_COEFF_0_25, FILTER_COEFF_0_5, 61 + FILTER_COEFF_1_0, FILTER_COEFF_0_5, FILTER_COEFF_0_25, 62 + FILTER_COEFF_0_125, 63 + }; 64 + 65 + static void intel_casf_filter_lut_load(struct intel_crtc *crtc, 66 + const struct intel_crtc_state *crtc_state) 67 + { 68 + struct intel_display *display = to_intel_display(crtc_state); 69 + int i; 70 + 71 + intel_de_write(display, SHRPLUT_INDEX(crtc->pipe), 72 + INDEX_AUTO_INCR | INDEX_VALUE(0)); 73 + 74 + for (i = 0; i < ARRAY_SIZE(sharpness_lut); i++) 75 + intel_de_write(display, SHRPLUT_DATA(crtc->pipe), 76 + sharpness_lut[i]); 77 + } 78 + 79 + void intel_casf_update_strength(struct intel_crtc_state *crtc_state) 80 + { 81 + struct intel_display *display = to_intel_display(crtc_state); 82 + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 83 + int win_size; 84 + 85 + intel_de_rmw(display, SHARPNESS_CTL(crtc->pipe), FILTER_STRENGTH_MASK, 86 + FILTER_STRENGTH(crtc_state->hw.casf_params.strength)); 87 + 88 + win_size = intel_de_read(display, SKL_PS_WIN_SZ(crtc->pipe, 1)); 89 + 90 + intel_de_write_fw(display, SKL_PS_WIN_SZ(crtc->pipe, 1), win_size); 91 + } 92 + 93 + static void intel_casf_compute_win_size(struct intel_crtc_state *crtc_state) 94 + { 95 + const struct drm_display_mode *mode = &crtc_state->hw.adjusted_mode; 96 + u32 total_pixels = mode->hdisplay * mode->vdisplay; 97 + 98 + if (total_pixels <= MAX_PIXELS_FOR_3_TAP_FILTER) 99 + crtc_state->hw.casf_params.win_size = SHARPNESS_FILTER_SIZE_3X3; 100 + else if (total_pixels <= MAX_PIXELS_FOR_5_TAP_FILTER) 101 + crtc_state->hw.casf_params.win_size = SHARPNESS_FILTER_SIZE_5X5; 102 + else 103 + crtc_state->hw.casf_params.win_size = SHARPNESS_FILTER_SIZE_7X7; 104 + } 105 + 106 + int intel_casf_compute_config(struct intel_crtc_state *crtc_state) 107 + { 108 + struct intel_display *display = to_intel_display(crtc_state); 109 + 110 + if (!HAS_CASF(display)) 111 + return 0; 112 + 113 + if (crtc_state->uapi.sharpness_strength == 0) { 114 + crtc_state->hw.casf_params.casf_enable = false; 115 + crtc_state->hw.casf_params.strength = 0; 116 + return 0; 117 + } 118 + 119 + crtc_state->hw.casf_params.casf_enable = true; 120 + 121 + /* 122 + * HW takes a value in form (1.0 + strength) in 4.4 fixed format. 123 + * Strength is from 0.0-14.9375 ie from 0-239. 124 + * User can give value from 0-255 but is clamped to 239. 125 + * Ex. User gives 85 which is 5.3125 and adding 1.0 gives 6.3125. 126 + * 6.3125 in 4.4 format is b01100101 which is equal to 101. 127 + * Also 85 + 16 = 101. 128 + */ 129 + crtc_state->hw.casf_params.strength = 130 + min(crtc_state->uapi.sharpness_strength, 0xEF) + 0x10; 131 + 132 + intel_casf_compute_win_size(crtc_state); 133 + 134 + intel_casf_scaler_compute_config(crtc_state); 135 + 136 + return 0; 137 + } 138 + 139 + void intel_casf_sharpness_get_config(struct intel_crtc_state *crtc_state) 140 + { 141 + struct intel_display *display = to_intel_display(crtc_state); 142 + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 143 + u32 sharp; 144 + 145 + sharp = intel_de_read(display, SHARPNESS_CTL(crtc->pipe)); 146 + if (sharp & FILTER_EN) { 147 + if (drm_WARN_ON(display->drm, 148 + REG_FIELD_GET(FILTER_STRENGTH_MASK, sharp) < 16)) 149 + crtc_state->hw.casf_params.strength = 0; 150 + else 151 + crtc_state->hw.casf_params.strength = 152 + REG_FIELD_GET(FILTER_STRENGTH_MASK, sharp); 153 + crtc_state->hw.casf_params.casf_enable = true; 154 + crtc_state->hw.casf_params.win_size = 155 + REG_FIELD_GET(FILTER_SIZE_MASK, sharp); 156 + } 157 + } 158 + 159 + bool intel_casf_needs_scaler(const struct intel_crtc_state *crtc_state) 160 + { 161 + if (crtc_state->hw.casf_params.casf_enable) 162 + return true; 163 + 164 + return false; 165 + } 166 + 167 + static int casf_coeff_tap(int i) 168 + { 169 + return i % SCALER_FILTER_NUM_TAPS; 170 + } 171 + 172 + static u32 casf_coeff(struct intel_crtc_state *crtc_state, int t) 173 + { 174 + struct scaler_filter_coeff value; 175 + u32 coeff; 176 + 177 + value = crtc_state->hw.casf_params.coeff[t]; 178 + value.sign = 0; 179 + 180 + coeff = value.sign << 15 | value.exp << 12 | value.mantissa << 3; 181 + return coeff; 182 + } 183 + 184 + /* 185 + * 17 phase of 7 taps requires 119 coefficients in 60 dwords per set. 186 + * To enable casf: program scaler coefficients with the coeffients 187 + * that are calculated and stored in hw.casf_params.coeff as per 188 + * SCALER_COEFFICIENT_FORMAT 189 + */ 190 + static void intel_casf_write_coeff(struct intel_crtc_state *crtc_state) 191 + { 192 + struct intel_display *display = to_intel_display(crtc_state); 193 + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 194 + int id = crtc_state->scaler_state.scaler_id; 195 + int i; 196 + 197 + if (id != 1) { 198 + drm_WARN(display->drm, 0, "Second scaler not enabled\n"); 199 + return; 200 + } 201 + 202 + intel_de_write_fw(display, GLK_PS_COEF_INDEX_SET(crtc->pipe, id, 0), 203 + PS_COEF_INDEX_AUTO_INC); 204 + 205 + for (i = 0; i < 17 * SCALER_FILTER_NUM_TAPS; i += 2) { 206 + u32 tmp; 207 + int t; 208 + 209 + t = casf_coeff_tap(i); 210 + tmp = casf_coeff(crtc_state, t); 211 + 212 + t = casf_coeff_tap(i + 1); 213 + tmp |= casf_coeff(crtc_state, t) << 16; 214 + 215 + intel_de_write_fw(display, GLK_PS_COEF_DATA_SET(crtc->pipe, id, 0), 216 + tmp); 217 + } 218 + } 219 + 220 + static void convert_sharpness_coef_binary(struct scaler_filter_coeff *coeff, 221 + u16 coefficient) 222 + { 223 + if (coefficient < 25) { 224 + coeff->mantissa = (coefficient * 2048) / 100; 225 + coeff->exp = 3; 226 + } else if (coefficient < 50) { 227 + coeff->mantissa = (coefficient * 1024) / 100; 228 + coeff->exp = 2; 229 + } else if (coefficient < 100) { 230 + coeff->mantissa = (coefficient * 512) / 100; 231 + coeff->exp = 1; 232 + } else { 233 + coeff->mantissa = (coefficient * 256) / 100; 234 + coeff->exp = 0; 235 + } 236 + } 237 + 238 + void intel_casf_scaler_compute_config(struct intel_crtc_state *crtc_state) 239 + { 240 + const u16 *filtercoeff; 241 + u16 filter_coeff[SCALER_FILTER_NUM_TAPS]; 242 + u16 sumcoeff = 0; 243 + int i; 244 + 245 + if (crtc_state->hw.casf_params.win_size == 0) 246 + filtercoeff = filtercoeff_1; 247 + else if (crtc_state->hw.casf_params.win_size == 1) 248 + filtercoeff = filtercoeff_2; 249 + else 250 + filtercoeff = filtercoeff_3; 251 + 252 + for (i = 0; i < SCALER_FILTER_NUM_TAPS; i++) 253 + sumcoeff += *(filtercoeff + i); 254 + 255 + for (i = 0; i < SCALER_FILTER_NUM_TAPS; i++) { 256 + filter_coeff[i] = (*(filtercoeff + i) * 100 / sumcoeff); 257 + convert_sharpness_coef_binary(&crtc_state->hw.casf_params.coeff[i], 258 + filter_coeff[i]); 259 + } 260 + } 261 + 262 + void intel_casf_enable(struct intel_crtc_state *crtc_state) 263 + { 264 + struct intel_display *display = to_intel_display(crtc_state); 265 + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 266 + u32 sharpness_ctl; 267 + 268 + intel_casf_filter_lut_load(crtc, crtc_state); 269 + 270 + intel_casf_write_coeff(crtc_state); 271 + 272 + sharpness_ctl = FILTER_EN | FILTER_STRENGTH(crtc_state->hw.casf_params.strength); 273 + 274 + sharpness_ctl |= crtc_state->hw.casf_params.win_size; 275 + 276 + intel_de_write(display, SHARPNESS_CTL(crtc->pipe), sharpness_ctl); 277 + 278 + skl_scaler_setup_casf(crtc_state); 279 + } 280 + 281 + void intel_casf_disable(const struct intel_crtc_state *crtc_state) 282 + { 283 + struct intel_display *display = to_intel_display(crtc_state); 284 + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 285 + 286 + intel_de_write(display, SKL_PS_CTRL(crtc->pipe, 1), 0); 287 + intel_de_write(display, SKL_PS_WIN_POS(crtc->pipe, 1), 0); 288 + intel_de_write(display, SHARPNESS_CTL(crtc->pipe), 0); 289 + intel_de_write(display, SKL_PS_WIN_SZ(crtc->pipe, 1), 0); 290 + }
+21
drivers/gpu/drm/i915/display/intel_casf.h
··· 1 + /* SPDX-License-Identifier: MIT */ 2 + /* 3 + * Copyright © 2025 Intel Corporation 4 + */ 5 + 6 + #ifndef __INTEL_CASF_H__ 7 + #define __INTEL_CASF_H__ 8 + 9 + #include <linux/types.h> 10 + 11 + struct intel_crtc_state; 12 + 13 + int intel_casf_compute_config(struct intel_crtc_state *crtc_state); 14 + void intel_casf_update_strength(struct intel_crtc_state *new_crtc_state); 15 + void intel_casf_sharpness_get_config(struct intel_crtc_state *crtc_state); 16 + void intel_casf_enable(struct intel_crtc_state *crtc_state); 17 + void intel_casf_disable(const struct intel_crtc_state *crtc_state); 18 + void intel_casf_scaler_compute_config(struct intel_crtc_state *crtc_state); 19 + bool intel_casf_needs_scaler(const struct intel_crtc_state *crtc_state); 20 + 21 + #endif /* __INTEL_CASF_H__ */
+33
drivers/gpu/drm/i915/display/intel_casf_regs.h
··· 1 + /* SPDX-License-Identifier: MIT */ 2 + /* 3 + * Copyright © 2025 Intel Corporation 4 + */ 5 + 6 + #ifndef __INTEL_CASF_REGS_H__ 7 + #define __INTEL_CASF_REGS_H__ 8 + 9 + #include "intel_display_reg_defs.h" 10 + 11 + #define _SHARPNESS_CTL_A 0x682B0 12 + #define _SHARPNESS_CTL_B 0x68AB0 13 + #define SHARPNESS_CTL(pipe) _MMIO_PIPE(pipe, _SHARPNESS_CTL_A, _SHARPNESS_CTL_B) 14 + #define FILTER_EN REG_BIT(31) 15 + #define FILTER_STRENGTH_MASK REG_GENMASK(15, 8) 16 + #define FILTER_STRENGTH(x) REG_FIELD_PREP(FILTER_STRENGTH_MASK, (x)) 17 + #define FILTER_SIZE_MASK REG_GENMASK(1, 0) 18 + #define SHARPNESS_FILTER_SIZE_3X3 REG_FIELD_PREP(FILTER_SIZE_MASK, 0) 19 + #define SHARPNESS_FILTER_SIZE_5X5 REG_FIELD_PREP(FILTER_SIZE_MASK, 1) 20 + #define SHARPNESS_FILTER_SIZE_7X7 REG_FIELD_PREP(FILTER_SIZE_MASK, 2) 21 + 22 + #define _SHRPLUT_DATA_A 0x682B8 23 + #define _SHRPLUT_DATA_B 0x68AB8 24 + #define SHRPLUT_DATA(pipe) _MMIO_PIPE(pipe, _SHRPLUT_DATA_A, _SHRPLUT_DATA_B) 25 + 26 + #define _SHRPLUT_INDEX_A 0x682B4 27 + #define _SHRPLUT_INDEX_B 0x68AB4 28 + #define SHRPLUT_INDEX(pipe) _MMIO_PIPE(pipe, _SHRPLUT_INDEX_A, _SHRPLUT_INDEX_B) 29 + #define INDEX_AUTO_INCR REG_BIT(10) 30 + #define INDEX_VALUE_MASK REG_GENMASK(4, 0) 31 + #define INDEX_VALUE(x) REG_FIELD_PREP(INDEX_VALUE_MASK, (x)) 32 + 33 + #endif /* __INTEL_CASF_REGS__ */
+322 -127
drivers/gpu/drm/i915/display/intel_cdclk.c
··· 32 32 #include "hsw_ips.h" 33 33 #include "i915_drv.h" 34 34 #include "i915_reg.h" 35 - #include "i915_utils.h" 36 35 #include "intel_atomic.h" 37 36 #include "intel_audio.h" 38 - #include "intel_bw.h" 39 37 #include "intel_cdclk.h" 40 38 #include "intel_crtc.h" 39 + #include "intel_dbuf_bw.h" 41 40 #include "intel_de.h" 42 41 #include "intel_display_regs.h" 43 42 #include "intel_display_types.h" 43 + #include "intel_display_utils.h" 44 44 #include "intel_mchbar_regs.h" 45 45 #include "intel_pci_config.h" 46 46 #include "intel_pcode.h" ··· 49 49 #include "intel_vdsc.h" 50 50 #include "skl_watermark.h" 51 51 #include "skl_watermark_regs.h" 52 + #include "vlv_clock.h" 52 53 #include "vlv_dsi.h" 53 54 #include "vlv_sideband.h" 54 55 ··· 133 132 */ 134 133 struct intel_cdclk_config actual; 135 134 136 - /* minimum acceptable cdclk to satisfy bandwidth requirements */ 137 - int bw_min_cdclk; 135 + /* minimum acceptable cdclk to satisfy DBUF bandwidth requirements */ 136 + int dbuf_bw_min_cdclk; 138 137 /* minimum acceptable cdclk for each pipe */ 139 138 int min_cdclk[I915_MAX_PIPES]; 140 139 /* minimum acceptable voltage level for each pipe */ ··· 145 144 146 145 /* forced minimum cdclk for glk+ audio w/a */ 147 146 int force_min_cdclk; 147 + 148 + /* bitmask of enabled pipes */ 149 + u8 enabled_pipes; 148 150 149 151 /* bitmask of active pipes */ 150 152 u8 active_pipes; ··· 567 563 568 564 static int vlv_calc_cdclk(struct intel_display *display, int min_cdclk) 569 565 { 570 - struct drm_i915_private *dev_priv = to_i915(display->drm); 571 - int freq_320 = (dev_priv->hpll_freq << 1) % 320000 != 0 ? 566 + int freq_320 = (vlv_clock_get_hpll_vco(display->drm) << 1) % 320000 != 0 ? 572 567 333333 : 320000; 573 568 574 569 /* ··· 587 584 588 585 static u8 vlv_calc_voltage_level(struct intel_display *display, int cdclk) 589 586 { 590 - struct drm_i915_private *dev_priv = to_i915(display->drm); 591 - 592 587 if (display->platform.valleyview) { 593 588 if (cdclk >= 320000) /* jump to highest voltage for 400MHz too */ 594 589 return 2; ··· 600 599 * hardware has shown that we just need to write the desired 601 600 * CCK divider into the Punit register. 602 601 */ 603 - return DIV_ROUND_CLOSEST(dev_priv->hpll_freq << 1, cdclk) - 1; 602 + return DIV_ROUND_CLOSEST(vlv_clock_get_hpll_vco(display->drm) << 1, cdclk) - 1; 604 603 } 605 604 } 606 605 ··· 609 608 { 610 609 u32 val; 611 610 612 - vlv_iosf_sb_get(display->drm, BIT(VLV_IOSF_SB_CCK) | BIT(VLV_IOSF_SB_PUNIT)); 611 + cdclk_config->vco = vlv_clock_get_hpll_vco(display->drm); 612 + cdclk_config->cdclk = vlv_clock_get_cdclk(display->drm); 613 613 614 - cdclk_config->vco = vlv_get_hpll_vco(display->drm); 615 - cdclk_config->cdclk = vlv_get_cck_clock(display->drm, "cdclk", 616 - CCK_DISPLAY_CLOCK_CONTROL, 617 - cdclk_config->vco); 618 - 614 + vlv_punit_get(display->drm); 619 615 val = vlv_punit_read(display->drm, PUNIT_REG_DSPSSPM); 620 - 621 - vlv_iosf_sb_put(display->drm, 622 - BIT(VLV_IOSF_SB_CCK) | BIT(VLV_IOSF_SB_PUNIT)); 616 + vlv_punit_put(display->drm); 623 617 624 618 if (display->platform.valleyview) 625 619 cdclk_config->voltage_level = (val & DSPFREQGUAR_MASK) >> ··· 626 630 627 631 static void vlv_program_pfi_credits(struct intel_display *display) 628 632 { 629 - struct drm_i915_private *dev_priv = to_i915(display->drm); 630 633 unsigned int credits, default_credits; 631 634 632 635 if (display->platform.cherryview) ··· 633 638 else 634 639 default_credits = PFI_CREDIT(8); 635 640 636 - if (display->cdclk.hw.cdclk >= dev_priv->czclk_freq) { 641 + if (display->cdclk.hw.cdclk >= vlv_clock_get_czclk(display->drm)) { 637 642 /* CHV suggested value is 31 or 63 */ 638 643 if (display->platform.cherryview) 639 644 credits = PFI_CREDIT_63; ··· 665 670 const struct intel_cdclk_config *cdclk_config, 666 671 enum pipe pipe) 667 672 { 668 - struct drm_i915_private *dev_priv = to_i915(display->drm); 669 673 int cdclk = cdclk_config->cdclk; 670 674 u32 val, cmd = cdclk_config->voltage_level; 671 675 intel_wakeref_t wakeref; ··· 709 715 if (cdclk == 400000) { 710 716 u32 divider; 711 717 712 - divider = DIV_ROUND_CLOSEST(dev_priv->hpll_freq << 1, 718 + divider = DIV_ROUND_CLOSEST(vlv_clock_get_hpll_vco(display->drm) << 1, 713 719 cdclk) - 1; 714 720 715 721 /* adjust cdclk divider */ ··· 1561 1567 drm_WARN(display->drm, 1, 1562 1568 "Cannot satisfy minimum cdclk %d with refclk %u\n", 1563 1569 min_cdclk, display->cdclk.hw.ref); 1564 - return 0; 1570 + return display->cdclk.max_cdclk_freq; 1565 1571 } 1566 1572 1567 1573 static int bxt_calc_cdclk_pll_vco(struct intel_display *display, int cdclk) ··· 2594 2600 } 2595 2601 } 2596 2602 2603 + static bool dg2_power_well_count(struct intel_display *display, 2604 + const struct intel_cdclk_state *cdclk_state) 2605 + { 2606 + return display->platform.dg2 ? hweight8(cdclk_state->active_pipes) : 0; 2607 + } 2608 + 2597 2609 static void intel_cdclk_pcode_pre_notify(struct intel_atomic_state *state) 2598 2610 { 2599 2611 struct intel_display *display = to_intel_display(state); ··· 2612 2612 2613 2613 if (!intel_cdclk_changed(&old_cdclk_state->actual, 2614 2614 &new_cdclk_state->actual) && 2615 - new_cdclk_state->active_pipes == 2616 - old_cdclk_state->active_pipes) 2615 + dg2_power_well_count(display, old_cdclk_state) == 2616 + dg2_power_well_count(display, new_cdclk_state)) 2617 2617 return; 2618 2618 2619 2619 /* According to "Sequence Before Frequency Change", voltage level set to 0x3 */ 2620 2620 voltage_level = DISPLAY_TO_PCODE_VOLTAGE_MAX; 2621 2621 2622 2622 change_cdclk = new_cdclk_state->actual.cdclk != old_cdclk_state->actual.cdclk; 2623 - update_pipe_count = hweight8(new_cdclk_state->active_pipes) > 2624 - hweight8(old_cdclk_state->active_pipes); 2623 + update_pipe_count = dg2_power_well_count(display, new_cdclk_state) > 2624 + dg2_power_well_count(display, old_cdclk_state); 2625 2625 2626 2626 /* 2627 2627 * According to "Sequence Before Frequency Change", ··· 2639 2639 * no action if it is decreasing, before the change 2640 2640 */ 2641 2641 if (update_pipe_count) 2642 - num_active_pipes = hweight8(new_cdclk_state->active_pipes); 2642 + num_active_pipes = dg2_power_well_count(display, new_cdclk_state); 2643 2643 2644 2644 intel_pcode_notify(display, voltage_level, num_active_pipes, cdclk, 2645 2645 change_cdclk, update_pipe_count); ··· 2659 2659 voltage_level = new_cdclk_state->actual.voltage_level; 2660 2660 2661 2661 update_cdclk = new_cdclk_state->actual.cdclk != old_cdclk_state->actual.cdclk; 2662 - update_pipe_count = hweight8(new_cdclk_state->active_pipes) < 2663 - hweight8(old_cdclk_state->active_pipes); 2662 + update_pipe_count = dg2_power_well_count(display, new_cdclk_state) < 2663 + dg2_power_well_count(display, old_cdclk_state); 2664 2664 2665 2665 /* 2666 2666 * According to "Sequence After Frequency Change", ··· 2676 2676 * no action if it is increasing, after the change 2677 2677 */ 2678 2678 if (update_pipe_count) 2679 - num_active_pipes = hweight8(new_cdclk_state->active_pipes); 2679 + num_active_pipes = dg2_power_well_count(display, new_cdclk_state); 2680 2680 2681 2681 intel_pcode_notify(display, voltage_level, num_active_pipes, cdclk, 2682 2682 update_cdclk, update_pipe_count); ··· 2710 2710 intel_atomic_get_new_cdclk_state(state); 2711 2711 struct intel_cdclk_config cdclk_config; 2712 2712 enum pipe pipe; 2713 + 2714 + if (!new_cdclk_state) 2715 + return; 2713 2716 2714 2717 if (!intel_cdclk_changed(&old_cdclk_state->actual, 2715 2718 &new_cdclk_state->actual)) ··· 2766 2763 intel_atomic_get_new_cdclk_state(state); 2767 2764 enum pipe pipe; 2768 2765 2766 + if (!new_cdclk_state) 2767 + return; 2768 + 2769 2769 if (!intel_cdclk_changed(&old_cdclk_state->actual, 2770 2770 &new_cdclk_state->actual)) 2771 2771 return; ··· 2806 2800 return 90; 2807 2801 } 2808 2802 2809 - static int intel_pixel_rate_to_cdclk(const struct intel_crtc_state *crtc_state) 2803 + static int _intel_pixel_rate_to_cdclk(const struct intel_crtc_state *crtc_state, int pixel_rate) 2810 2804 { 2811 2805 struct intel_display *display = to_intel_display(crtc_state); 2812 2806 int ppc = intel_cdclk_ppc(display, crtc_state->double_wide); 2813 2807 int guardband = intel_cdclk_guardband(display); 2814 - int pixel_rate = crtc_state->pixel_rate; 2815 2808 2816 2809 return DIV_ROUND_UP(pixel_rate * 100, guardband * ppc); 2810 + } 2811 + 2812 + static int intel_pixel_rate_to_cdclk(const struct intel_crtc_state *crtc_state) 2813 + { 2814 + return _intel_pixel_rate_to_cdclk(crtc_state, crtc_state->pixel_rate); 2817 2815 } 2818 2816 2819 2817 static int intel_planes_min_cdclk(const struct intel_crtc_state *crtc_state) ··· 2828 2818 int min_cdclk = 0; 2829 2819 2830 2820 for_each_intel_plane_on_crtc(display->drm, crtc, plane) 2831 - min_cdclk = max(min_cdclk, crtc_state->min_cdclk[plane->id]); 2821 + min_cdclk = max(min_cdclk, crtc_state->plane_min_cdclk[plane->id]); 2832 2822 2833 2823 return min_cdclk; 2834 2824 } 2835 2825 2836 - static int intel_crtc_compute_min_cdclk(const struct intel_crtc_state *crtc_state) 2826 + int intel_crtc_min_cdclk(const struct intel_crtc_state *crtc_state) 2837 2827 { 2838 2828 int min_cdclk; 2839 2829 ··· 2841 2831 return 0; 2842 2832 2843 2833 min_cdclk = intel_pixel_rate_to_cdclk(crtc_state); 2834 + min_cdclk = max(min_cdclk, intel_crtc_bw_min_cdclk(crtc_state)); 2835 + min_cdclk = max(min_cdclk, intel_fbc_min_cdclk(crtc_state)); 2844 2836 min_cdclk = max(min_cdclk, hsw_ips_min_cdclk(crtc_state)); 2845 2837 min_cdclk = max(min_cdclk, intel_audio_min_cdclk(crtc_state)); 2846 2838 min_cdclk = max(min_cdclk, vlv_dsi_min_cdclk(crtc_state)); ··· 2852 2840 return min_cdclk; 2853 2841 } 2854 2842 2843 + static int intel_cdclk_update_crtc_min_cdclk(struct intel_atomic_state *state, 2844 + struct intel_crtc *crtc, 2845 + int old_min_cdclk, int new_min_cdclk, 2846 + bool *need_cdclk_calc) 2847 + { 2848 + struct intel_display *display = to_intel_display(state); 2849 + struct intel_cdclk_state *cdclk_state; 2850 + bool allow_cdclk_decrease = intel_any_crtc_needs_modeset(state); 2851 + int ret; 2852 + 2853 + if (new_min_cdclk == old_min_cdclk) 2854 + return 0; 2855 + 2856 + if (!allow_cdclk_decrease && new_min_cdclk < old_min_cdclk) 2857 + return 0; 2858 + 2859 + cdclk_state = intel_atomic_get_cdclk_state(state); 2860 + if (IS_ERR(cdclk_state)) 2861 + return PTR_ERR(cdclk_state); 2862 + 2863 + old_min_cdclk = cdclk_state->min_cdclk[crtc->pipe]; 2864 + 2865 + if (new_min_cdclk == old_min_cdclk) 2866 + return 0; 2867 + 2868 + if (!allow_cdclk_decrease && new_min_cdclk < old_min_cdclk) 2869 + return 0; 2870 + 2871 + cdclk_state->min_cdclk[crtc->pipe] = new_min_cdclk; 2872 + 2873 + ret = intel_atomic_lock_global_state(&cdclk_state->base); 2874 + if (ret) 2875 + return ret; 2876 + 2877 + *need_cdclk_calc = true; 2878 + 2879 + drm_dbg_kms(display->drm, 2880 + "[CRTC:%d:%s] min cdclk: %d kHz -> %d kHz\n", 2881 + crtc->base.base.id, crtc->base.name, 2882 + old_min_cdclk, new_min_cdclk); 2883 + 2884 + return 0; 2885 + } 2886 + 2887 + int intel_cdclk_update_dbuf_bw_min_cdclk(struct intel_atomic_state *state, 2888 + int old_min_cdclk, int new_min_cdclk, 2889 + bool *need_cdclk_calc) 2890 + { 2891 + struct intel_display *display = to_intel_display(state); 2892 + struct intel_cdclk_state *cdclk_state; 2893 + bool allow_cdclk_decrease = intel_any_crtc_needs_modeset(state); 2894 + int ret; 2895 + 2896 + if (new_min_cdclk == old_min_cdclk) 2897 + return 0; 2898 + 2899 + if (!allow_cdclk_decrease && new_min_cdclk < old_min_cdclk) 2900 + return 0; 2901 + 2902 + cdclk_state = intel_atomic_get_cdclk_state(state); 2903 + if (IS_ERR(cdclk_state)) 2904 + return PTR_ERR(cdclk_state); 2905 + 2906 + old_min_cdclk = cdclk_state->dbuf_bw_min_cdclk; 2907 + 2908 + if (new_min_cdclk == old_min_cdclk) 2909 + return 0; 2910 + 2911 + if (!allow_cdclk_decrease && new_min_cdclk < old_min_cdclk) 2912 + return 0; 2913 + 2914 + cdclk_state->dbuf_bw_min_cdclk = new_min_cdclk; 2915 + 2916 + ret = intel_atomic_lock_global_state(&cdclk_state->base); 2917 + if (ret) 2918 + return ret; 2919 + 2920 + *need_cdclk_calc = true; 2921 + 2922 + drm_dbg_kms(display->drm, 2923 + "dbuf bandwidth min cdclk: %d kHz -> %d kHz\n", 2924 + old_min_cdclk, new_min_cdclk); 2925 + 2926 + return 0; 2927 + } 2928 + 2929 + static bool glk_cdclk_audio_wa_needed(struct intel_display *display, 2930 + const struct intel_cdclk_state *cdclk_state) 2931 + { 2932 + return display->platform.geminilake && 2933 + cdclk_state->enabled_pipes && 2934 + !is_power_of_2(cdclk_state->enabled_pipes); 2935 + } 2936 + 2855 2937 static int intel_compute_min_cdclk(struct intel_atomic_state *state) 2856 2938 { 2857 2939 struct intel_display *display = to_intel_display(state); 2858 2940 struct intel_cdclk_state *cdclk_state = 2859 2941 intel_atomic_get_new_cdclk_state(state); 2860 - const struct intel_bw_state *bw_state; 2861 - struct intel_crtc *crtc; 2862 - struct intel_crtc_state *crtc_state; 2863 - int min_cdclk, i; 2864 2942 enum pipe pipe; 2943 + int min_cdclk; 2865 2944 2866 - for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) { 2867 - int ret; 2868 - 2869 - min_cdclk = intel_crtc_compute_min_cdclk(crtc_state); 2870 - if (min_cdclk < 0) 2871 - return min_cdclk; 2872 - 2873 - if (cdclk_state->min_cdclk[crtc->pipe] == min_cdclk) 2874 - continue; 2875 - 2876 - cdclk_state->min_cdclk[crtc->pipe] = min_cdclk; 2877 - 2878 - ret = intel_atomic_lock_global_state(&cdclk_state->base); 2879 - if (ret) 2880 - return ret; 2881 - } 2882 - 2883 - bw_state = intel_atomic_get_new_bw_state(state); 2884 - if (bw_state) { 2885 - min_cdclk = intel_bw_min_cdclk(display, bw_state); 2886 - 2887 - if (cdclk_state->bw_min_cdclk != min_cdclk) { 2888 - int ret; 2889 - 2890 - cdclk_state->bw_min_cdclk = min_cdclk; 2891 - 2892 - ret = intel_atomic_lock_global_state(&cdclk_state->base); 2893 - if (ret) 2894 - return ret; 2895 - } 2896 - } 2897 - 2898 - min_cdclk = max(cdclk_state->force_min_cdclk, 2899 - cdclk_state->bw_min_cdclk); 2945 + min_cdclk = cdclk_state->force_min_cdclk; 2946 + min_cdclk = max(min_cdclk, cdclk_state->dbuf_bw_min_cdclk); 2900 2947 for_each_pipe(display, pipe) 2901 2948 min_cdclk = max(min_cdclk, cdclk_state->min_cdclk[pipe]); 2902 2949 ··· 2967 2896 * by changing the cd2x divider (see glk_cdclk_table[]) and 2968 2897 * thus a full modeset won't be needed then. 2969 2898 */ 2970 - if (display->platform.geminilake && cdclk_state->active_pipes && 2971 - !is_power_of_2(cdclk_state->active_pipes)) 2899 + if (glk_cdclk_audio_wa_needed(display, cdclk_state)) 2972 2900 min_cdclk = max(min_cdclk, 2 * 96000); 2973 2901 2974 2902 if (min_cdclk > display->cdclk.max_cdclk_freq) { ··· 3253 3183 return to_intel_cdclk_state(cdclk_state); 3254 3184 } 3255 3185 3256 - int intel_cdclk_atomic_check(struct intel_atomic_state *state, 3257 - bool *need_cdclk_calc) 3186 + static int intel_cdclk_modeset_checks(struct intel_atomic_state *state, 3187 + bool *need_cdclk_calc) 3258 3188 { 3189 + struct intel_display *display = to_intel_display(state); 3259 3190 const struct intel_cdclk_state *old_cdclk_state; 3260 - const struct intel_cdclk_state *new_cdclk_state; 3261 - struct intel_plane_state __maybe_unused *plane_state; 3262 - struct intel_plane *plane; 3191 + struct intel_cdclk_state *new_cdclk_state; 3263 3192 int ret; 3264 - int i; 3265 3193 3266 - /* 3267 - * active_planes bitmask has been updated, and potentially affected 3268 - * planes are part of the state. We can now compute the minimum cdclk 3269 - * for each plane. 3270 - */ 3271 - for_each_new_intel_plane_in_state(state, plane, plane_state, i) { 3272 - ret = intel_plane_calc_min_cdclk(state, plane, need_cdclk_calc); 3273 - if (ret) 3274 - return ret; 3275 - } 3194 + if (!intel_any_crtc_enable_changed(state) && 3195 + !intel_any_crtc_active_changed(state)) 3196 + return 0; 3276 3197 3277 - ret = intel_bw_calc_min_cdclk(state, need_cdclk_calc); 3198 + new_cdclk_state = intel_atomic_get_cdclk_state(state); 3199 + if (IS_ERR(new_cdclk_state)) 3200 + return PTR_ERR(new_cdclk_state); 3201 + 3202 + old_cdclk_state = intel_atomic_get_old_cdclk_state(state); 3203 + 3204 + new_cdclk_state->enabled_pipes = 3205 + intel_calc_enabled_pipes(state, old_cdclk_state->enabled_pipes); 3206 + 3207 + new_cdclk_state->active_pipes = 3208 + intel_calc_active_pipes(state, old_cdclk_state->active_pipes); 3209 + 3210 + ret = intel_atomic_lock_global_state(&new_cdclk_state->base); 3278 3211 if (ret) 3279 3212 return ret; 3280 3213 3281 - old_cdclk_state = intel_atomic_get_old_cdclk_state(state); 3282 - new_cdclk_state = intel_atomic_get_new_cdclk_state(state); 3283 - 3284 - if (new_cdclk_state && 3285 - old_cdclk_state->force_min_cdclk != new_cdclk_state->force_min_cdclk) 3214 + if (!old_cdclk_state->active_pipes != !new_cdclk_state->active_pipes) 3286 3215 *need_cdclk_calc = true; 3216 + 3217 + if (glk_cdclk_audio_wa_needed(display, old_cdclk_state) != 3218 + glk_cdclk_audio_wa_needed(display, new_cdclk_state)) 3219 + *need_cdclk_calc = true; 3220 + 3221 + if (dg2_power_well_count(display, old_cdclk_state) != 3222 + dg2_power_well_count(display, new_cdclk_state)) 3223 + *need_cdclk_calc = true; 3224 + 3225 + return 0; 3226 + } 3227 + 3228 + static int intel_crtcs_calc_min_cdclk(struct intel_atomic_state *state, 3229 + bool *need_cdclk_calc) 3230 + { 3231 + const struct intel_crtc_state *old_crtc_state; 3232 + const struct intel_crtc_state *new_crtc_state; 3233 + struct intel_crtc *crtc; 3234 + int i, ret; 3235 + 3236 + for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, 3237 + new_crtc_state, i) { 3238 + ret = intel_cdclk_update_crtc_min_cdclk(state, crtc, 3239 + old_crtc_state->min_cdclk, 3240 + new_crtc_state->min_cdclk, 3241 + need_cdclk_calc); 3242 + if (ret) 3243 + return ret; 3244 + } 3287 3245 3288 3246 return 0; 3289 3247 } ··· 3348 3250 const struct intel_cdclk_state *old_cdclk_state, 3349 3251 const struct intel_cdclk_state *new_cdclk_state) 3350 3252 { 3351 - bool power_well_cnt_changed = hweight8(old_cdclk_state->active_pipes) != 3352 - hweight8(new_cdclk_state->active_pipes); 3353 - bool cdclk_changed = intel_cdclk_changed(&old_cdclk_state->actual, 3354 - &new_cdclk_state->actual); 3355 3253 /* 3356 - * We need to poke hw for gen >= 12, because we notify PCode if 3254 + * We need to poke hw for DG2, because we notify PCode if 3357 3255 * pipe power well count changes. 3358 3256 */ 3359 - return cdclk_changed || (display->platform.dg2 && power_well_cnt_changed); 3257 + return intel_cdclk_changed(&old_cdclk_state->actual, 3258 + &new_cdclk_state->actual) || 3259 + dg2_power_well_count(display, old_cdclk_state) != 3260 + dg2_power_well_count(display, new_cdclk_state); 3360 3261 } 3361 3262 3362 - int intel_modeset_calc_cdclk(struct intel_atomic_state *state) 3263 + static int intel_modeset_calc_cdclk(struct intel_atomic_state *state) 3363 3264 { 3364 3265 struct intel_display *display = to_intel_display(state); 3365 3266 const struct intel_cdclk_state *old_cdclk_state; ··· 3372 3275 3373 3276 old_cdclk_state = intel_atomic_get_old_cdclk_state(state); 3374 3277 3375 - new_cdclk_state->active_pipes = 3376 - intel_calc_active_pipes(state, old_cdclk_state->active_pipes); 3377 - 3378 3278 ret = intel_cdclk_modeset_calc_cdclk(state); 3379 3279 if (ret) 3380 3280 return ret; ··· 3384 3290 ret = intel_atomic_serialize_global_state(&new_cdclk_state->base); 3385 3291 if (ret) 3386 3292 return ret; 3387 - } else if (old_cdclk_state->active_pipes != new_cdclk_state->active_pipes || 3388 - old_cdclk_state->force_min_cdclk != new_cdclk_state->force_min_cdclk || 3389 - intel_cdclk_changed(&old_cdclk_state->logical, 3293 + } else if (intel_cdclk_changed(&old_cdclk_state->logical, 3390 3294 &new_cdclk_state->logical)) { 3391 3295 ret = intel_atomic_lock_global_state(&new_cdclk_state->base); 3392 3296 if (ret) ··· 3466 3374 return 0; 3467 3375 } 3468 3376 3377 + int intel_cdclk_atomic_check(struct intel_atomic_state *state) 3378 + { 3379 + const struct intel_cdclk_state *old_cdclk_state; 3380 + struct intel_cdclk_state *new_cdclk_state; 3381 + bool need_cdclk_calc = false; 3382 + int ret; 3383 + 3384 + ret = intel_cdclk_modeset_checks(state, &need_cdclk_calc); 3385 + if (ret) 3386 + return ret; 3387 + 3388 + ret = intel_crtcs_calc_min_cdclk(state, &need_cdclk_calc); 3389 + if (ret) 3390 + return ret; 3391 + 3392 + ret = intel_dbuf_bw_calc_min_cdclk(state, &need_cdclk_calc); 3393 + if (ret) 3394 + return ret; 3395 + 3396 + old_cdclk_state = intel_atomic_get_old_cdclk_state(state); 3397 + new_cdclk_state = intel_atomic_get_new_cdclk_state(state); 3398 + 3399 + if (new_cdclk_state && 3400 + old_cdclk_state->force_min_cdclk != new_cdclk_state->force_min_cdclk) { 3401 + ret = intel_atomic_lock_global_state(&new_cdclk_state->base); 3402 + if (ret) 3403 + return ret; 3404 + 3405 + need_cdclk_calc = true; 3406 + } 3407 + 3408 + if (need_cdclk_calc) { 3409 + ret = intel_modeset_calc_cdclk(state); 3410 + if (ret) 3411 + return ret; 3412 + } 3413 + 3414 + return 0; 3415 + } 3416 + 3469 3417 void intel_cdclk_update_hw_state(struct intel_display *display) 3470 3418 { 3471 - const struct intel_bw_state *bw_state = 3472 - to_intel_bw_state(display->bw.obj.state); 3419 + const struct intel_dbuf_bw_state *dbuf_bw_state = 3420 + to_intel_dbuf_bw_state(display->dbuf_bw.obj.state); 3473 3421 struct intel_cdclk_state *cdclk_state = 3474 3422 to_intel_cdclk_state(display->cdclk.obj.state); 3475 3423 struct intel_crtc *crtc; 3476 3424 3425 + cdclk_state->enabled_pipes = 0; 3477 3426 cdclk_state->active_pipes = 0; 3478 3427 3479 3428 for_each_intel_crtc(display->drm, crtc) { ··· 3522 3389 to_intel_crtc_state(crtc->base.state); 3523 3390 enum pipe pipe = crtc->pipe; 3524 3391 3392 + if (crtc_state->hw.enable) 3393 + cdclk_state->enabled_pipes |= BIT(pipe); 3525 3394 if (crtc_state->hw.active) 3526 3395 cdclk_state->active_pipes |= BIT(pipe); 3527 3396 3528 - cdclk_state->min_cdclk[pipe] = intel_crtc_compute_min_cdclk(crtc_state); 3397 + cdclk_state->min_cdclk[pipe] = crtc_state->min_cdclk; 3529 3398 cdclk_state->min_voltage_level[pipe] = crtc_state->min_voltage_level; 3530 3399 } 3531 3400 3532 - cdclk_state->bw_min_cdclk = intel_bw_min_cdclk(display, bw_state); 3401 + cdclk_state->dbuf_bw_min_cdclk = intel_dbuf_bw_min_cdclk(display, dbuf_bw_state); 3533 3402 } 3534 3403 3535 3404 void intel_cdclk_crtc_disable_noatomic(struct intel_crtc *crtc) ··· 3700 3565 return (intel_de_read(display, PCH_RAWCLK_FREQ) & RAWCLK_FREQ_MASK) * 1000; 3701 3566 } 3702 3567 3703 - static int vlv_hrawclk(struct intel_display *display) 3704 - { 3705 - /* RAWCLK_FREQ_VLV register updated from power well code */ 3706 - return vlv_get_cck_clock_hpll(display->drm, "hrawclk", 3707 - CCK_DISPLAY_REF_CLOCK_CONTROL); 3708 - } 3709 - 3710 3568 static int i9xx_hrawclk(struct intel_display *display) 3711 3569 { 3712 3570 struct drm_i915_private *i915 = to_i915(display->drm); ··· 3733 3605 else if (HAS_PCH_SPLIT(display)) 3734 3606 freq = pch_rawclk(display); 3735 3607 else if (display->platform.valleyview || display->platform.cherryview) 3736 - freq = vlv_hrawclk(display); 3608 + freq = vlv_clock_get_hrawclk(display->drm); 3737 3609 else if (DISPLAY_VER(display) >= 3) 3738 3610 freq = i9xx_hrawclk(display); 3739 3611 else ··· 4025 3897 return cdclk_state->min_cdclk[pipe]; 4026 3898 } 4027 3899 4028 - int intel_cdclk_bw_min_cdclk(const struct intel_cdclk_state *cdclk_state) 4029 - { 4030 - return cdclk_state->bw_min_cdclk; 4031 - } 4032 - 4033 3900 bool intel_cdclk_pmdemand_needs_update(struct intel_atomic_state *state) 4034 3901 { 4035 3902 const struct intel_cdclk_state *new_cdclk_state, *old_cdclk_state; ··· 4055 3932 intel_cdclk_dump_config(display, &display->cdclk.hw, "Current CDCLK"); 4056 3933 cdclk_state->actual = display->cdclk.hw; 4057 3934 cdclk_state->logical = display->cdclk.hw; 3935 + } 3936 + 3937 + static int calc_cdclk(const struct intel_crtc_state *crtc_state, int min_cdclk) 3938 + { 3939 + struct intel_display *display = to_intel_display(crtc_state); 3940 + 3941 + if (DISPLAY_VER(display) >= 10 || display->platform.broxton) { 3942 + return bxt_calc_cdclk(display, min_cdclk); 3943 + } else if (DISPLAY_VER(display) == 9) { 3944 + int vco; 3945 + 3946 + vco = display->cdclk.skl_preferred_vco_freq; 3947 + if (vco == 0) 3948 + vco = 8100000; 3949 + 3950 + return skl_calc_cdclk(min_cdclk, vco); 3951 + } else if (display->platform.broadwell) { 3952 + return bdw_calc_cdclk(min_cdclk); 3953 + } else if (display->platform.cherryview || display->platform.valleyview) { 3954 + return vlv_calc_cdclk(display, min_cdclk); 3955 + } else { 3956 + return display->cdclk.max_cdclk_freq; 3957 + } 3958 + } 3959 + 3960 + static unsigned int _intel_cdclk_prefill_adj(const struct intel_crtc_state *crtc_state, 3961 + int clock, int min_cdclk) 3962 + { 3963 + struct intel_display *display = to_intel_display(crtc_state); 3964 + int ppc = intel_cdclk_ppc(display, crtc_state->double_wide); 3965 + int cdclk = calc_cdclk(crtc_state, min_cdclk); 3966 + 3967 + return min(0x10000, DIV_ROUND_UP_ULL((u64)clock << 16, ppc * cdclk)); 3968 + } 3969 + 3970 + unsigned int intel_cdclk_prefill_adjustment(const struct intel_crtc_state *crtc_state) 3971 + { 3972 + /* FIXME use the actual min_cdclk for the pipe here */ 3973 + return intel_cdclk_prefill_adjustment_worst(crtc_state); 3974 + } 3975 + 3976 + unsigned int intel_cdclk_prefill_adjustment_worst(const struct intel_crtc_state *crtc_state) 3977 + { 3978 + int clock = crtc_state->hw.pipe_mode.crtc_clock; 3979 + int min_cdclk; 3980 + 3981 + /* 3982 + * FIXME could perhaps consider a few more of the factors 3983 + * that go the per-crtc min_cdclk. Namely anything that 3984 + * only changes during full modesets. 3985 + * 3986 + * FIXME this assumes 1:1 scaling, but the other _worst() stuff 3987 + * assumes max downscaling, so the final result will be 3988 + * unrealistically bad. Figure out where the actual maximum value 3989 + * lies and use that to compute a more realistic worst case 3990 + * estimate... 3991 + */ 3992 + min_cdclk = _intel_pixel_rate_to_cdclk(crtc_state, clock); 3993 + 3994 + return _intel_cdclk_prefill_adj(crtc_state, clock, min_cdclk); 3995 + } 3996 + 3997 + int intel_cdclk_min_cdclk_for_prefill(const struct intel_crtc_state *crtc_state, 3998 + unsigned int prefill_lines_unadjusted, 3999 + unsigned int prefill_lines_available) 4000 + { 4001 + struct intel_display *display = to_intel_display(crtc_state); 4002 + const struct drm_display_mode *pipe_mode = &crtc_state->hw.pipe_mode; 4003 + int ppc = intel_cdclk_ppc(display, crtc_state->double_wide); 4004 + 4005 + return DIV_ROUND_UP_ULL(mul_u32_u32(pipe_mode->crtc_clock, prefill_lines_unadjusted), 4006 + ppc * prefill_lines_available); 4058 4007 }
+12 -4
drivers/gpu/drm/i915/display/intel_cdclk.h
··· 38 38 void intel_cdclk_dump_config(struct intel_display *display, 39 39 const struct intel_cdclk_config *cdclk_config, 40 40 const char *context); 41 - int intel_modeset_calc_cdclk(struct intel_atomic_state *state); 42 41 void intel_cdclk_get_cdclk(struct intel_display *display, 43 42 struct intel_cdclk_config *cdclk_config); 44 - int intel_cdclk_atomic_check(struct intel_atomic_state *state, 45 - bool *need_cdclk_calc); 43 + int intel_cdclk_atomic_check(struct intel_atomic_state *state); 46 44 int intel_cdclk_state_set_joined_mbus(struct intel_atomic_state *state, bool joined_mbus); 47 45 struct intel_cdclk_state * 48 46 intel_atomic_get_cdclk_state(struct intel_atomic_state *state); 49 47 void intel_cdclk_update_hw_state(struct intel_display *display); 50 48 void intel_cdclk_crtc_disable_noatomic(struct intel_crtc *crtc); 49 + int intel_cdclk_update_dbuf_bw_min_cdclk(struct intel_atomic_state *state, 50 + int old_min_cdclk, int new_min_cdclk, 51 + bool *need_cdclk_calc); 51 52 52 53 #define to_intel_cdclk_state(global_state) \ 53 54 container_of_const((global_state), struct intel_cdclk_state, base) ··· 65 64 int intel_cdclk_actual(const struct intel_cdclk_state *cdclk_state); 66 65 int intel_cdclk_actual_voltage_level(const struct intel_cdclk_state *cdclk_state); 67 66 int intel_cdclk_min_cdclk(const struct intel_cdclk_state *cdclk_state, enum pipe pipe); 68 - int intel_cdclk_bw_min_cdclk(const struct intel_cdclk_state *cdclk_state); 69 67 bool intel_cdclk_pmdemand_needs_update(struct intel_atomic_state *state); 70 68 void intel_cdclk_force_min_cdclk(struct intel_cdclk_state *cdclk_state, int force_min_cdclk); 71 69 void intel_cdclk_read_hw(struct intel_display *display); 70 + 71 + unsigned int intel_cdclk_prefill_adjustment(const struct intel_crtc_state *crtc_state); 72 + unsigned int intel_cdclk_prefill_adjustment_worst(const struct intel_crtc_state *crtc_state); 73 + int intel_cdclk_min_cdclk_for_prefill(const struct intel_crtc_state *crtc_state, 74 + unsigned int prefill_lines_unadjusted, 75 + unsigned int prefill_lines_available); 76 + 77 + int intel_crtc_min_cdclk(const struct intel_crtc_state *crtc_state); 72 78 73 79 #endif /* __INTEL_CDCLK_H__ */
+2 -2
drivers/gpu/drm/i915/display/intel_color.c
··· 24 24 25 25 #include <drm/drm_print.h> 26 26 27 - #include "i915_utils.h" 28 27 #include "i9xx_plane_regs.h" 29 28 #include "intel_color.h" 30 29 #include "intel_color_regs.h" 31 30 #include "intel_de.h" 32 31 #include "intel_display_types.h" 32 + #include "intel_display_utils.h" 33 33 #include "intel_dsb.h" 34 34 #include "intel_vrr.h" 35 35 ··· 2013 2013 2014 2014 if (crtc_state->use_dsb && intel_color_uses_chained_dsb(crtc_state)) { 2015 2015 intel_vrr_send_push(crtc_state->dsb_color, crtc_state); 2016 - intel_dsb_wait_vblank_delay(state, crtc_state->dsb_color); 2016 + intel_dsb_wait_for_delayed_vblank(state, crtc_state->dsb_color); 2017 2017 intel_vrr_check_push_sent(crtc_state->dsb_color, crtc_state); 2018 2018 intel_dsb_interrupt(crtc_state->dsb_color); 2019 2019 }
+1 -1
drivers/gpu/drm/i915/display/intel_combo_phy.c
··· 5 5 6 6 #include <drm/drm_print.h> 7 7 8 - #include "i915_utils.h" 9 8 #include "intel_combo_phy.h" 10 9 #include "intel_combo_phy_regs.h" 11 10 #include "intel_de.h" 12 11 #include "intel_display_regs.h" 13 12 #include "intel_display_types.h" 13 + #include "intel_display_utils.h" 14 14 15 15 #define for_each_combo_phy(__display, __phy) \ 16 16 for ((__phy) = PHY_A; (__phy) < I915_MAX_PHYS; (__phy)++) \
+1 -1
drivers/gpu/drm/i915/display/intel_connector.c
··· 31 31 #include <drm/drm_probe_helper.h> 32 32 33 33 #include "i915_drv.h" 34 - #include "i915_utils.h" 34 + #include "i915_utils.h" /* for i915_inject_probe_failure() */ 35 35 #include "intel_connector.h" 36 36 #include "intel_display_core.h" 37 37 #include "intel_display_debugfs.h"
+96 -2
drivers/gpu/drm/i915/display/intel_crtc.c
··· 84 84 if (!crtc->active) 85 85 return 0; 86 86 87 - if (!vblank->max_vblank_count) 88 - return (u32)drm_crtc_accurate_vblank_count(&crtc->base); 87 + if (!vblank->max_vblank_count) { 88 + /* On preempt-rt we cannot take the vblank spinlock since this function is called from tracepoints */ 89 + if (IS_ENABLED(CONFIG_PREEMPT_RT)) 90 + return (u32)drm_crtc_vblank_count(&crtc->base); 91 + else 92 + return (u32)drm_crtc_accurate_vblank_count(&crtc->base); 93 + } 89 94 90 95 return crtc->base.funcs->get_vblank_counter(&crtc->base); 91 96 } ··· 394 389 cpu_latency_qos_add_request(&crtc->vblank_pm_qos, PM_QOS_DEFAULT_VALUE); 395 390 396 391 drm_WARN_ON(display->drm, drm_crtc_index(&crtc->base) != crtc->pipe); 392 + 393 + if (HAS_CASF(display)) 394 + drm_crtc_create_sharpness_strength_property(&crtc->base); 397 395 398 396 return 0; 399 397 ··· 755 747 756 748 out: 757 749 intel_psr_unlock(new_crtc_state); 750 + } 751 + 752 + bool intel_crtc_enable_changed(const struct intel_crtc_state *old_crtc_state, 753 + const struct intel_crtc_state *new_crtc_state) 754 + { 755 + return old_crtc_state->hw.enable != new_crtc_state->hw.enable; 756 + } 757 + 758 + bool intel_any_crtc_enable_changed(struct intel_atomic_state *state) 759 + { 760 + const struct intel_crtc_state *old_crtc_state, *new_crtc_state; 761 + struct intel_crtc *crtc; 762 + int i; 763 + 764 + for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, 765 + new_crtc_state, i) { 766 + if (intel_crtc_enable_changed(old_crtc_state, new_crtc_state)) 767 + return true; 768 + } 769 + 770 + return false; 771 + } 772 + 773 + bool intel_crtc_active_changed(const struct intel_crtc_state *old_crtc_state, 774 + const struct intel_crtc_state *new_crtc_state) 775 + { 776 + return old_crtc_state->hw.active != new_crtc_state->hw.active; 777 + } 778 + 779 + bool intel_any_crtc_active_changed(struct intel_atomic_state *state) 780 + { 781 + const struct intel_crtc_state *old_crtc_state, *new_crtc_state; 782 + struct intel_crtc *crtc; 783 + int i; 784 + 785 + for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, 786 + new_crtc_state, i) { 787 + if (intel_crtc_active_changed(old_crtc_state, new_crtc_state)) 788 + return true; 789 + } 790 + 791 + return false; 792 + } 793 + 794 + unsigned int intel_crtc_bw_num_active_planes(const struct intel_crtc_state *crtc_state) 795 + { 796 + /* 797 + * We assume cursors are small enough 798 + * to not cause bandwidth problems. 799 + */ 800 + return hweight8(crtc_state->active_planes & ~BIT(PLANE_CURSOR)); 801 + } 802 + 803 + unsigned int intel_crtc_bw_data_rate(const struct intel_crtc_state *crtc_state) 804 + { 805 + struct intel_display *display = to_intel_display(crtc_state); 806 + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 807 + unsigned int data_rate = 0; 808 + enum plane_id plane_id; 809 + 810 + for_each_plane_id_on_crtc(crtc, plane_id) { 811 + /* 812 + * We assume cursors are small enough 813 + * to not cause bandwidth problems. 814 + */ 815 + if (plane_id == PLANE_CURSOR) 816 + continue; 817 + 818 + data_rate += crtc_state->data_rate[plane_id]; 819 + 820 + if (DISPLAY_VER(display) < 11) 821 + data_rate += crtc_state->data_rate_y[plane_id]; 822 + } 823 + 824 + return data_rate; 825 + } 826 + 827 + /* "Maximum Pipe Read Bandwidth" */ 828 + int intel_crtc_bw_min_cdclk(const struct intel_crtc_state *crtc_state) 829 + { 830 + struct intel_display *display = to_intel_display(crtc_state); 831 + 832 + if (DISPLAY_VER(display) < 12) 833 + return 0; 834 + 835 + return DIV_ROUND_UP_ULL(mul_u32_u32(intel_crtc_bw_data_rate(crtc_state), 10), 512); 758 836 }
+11
drivers/gpu/drm/i915/display/intel_crtc.h
··· 58 58 enum pipe pipe); 59 59 void intel_crtc_wait_for_next_vblank(struct intel_crtc *crtc); 60 60 61 + bool intel_any_crtc_enable_changed(struct intel_atomic_state *state); 62 + bool intel_crtc_enable_changed(const struct intel_crtc_state *old_crtc_state, 63 + const struct intel_crtc_state *new_crtc_state); 64 + bool intel_any_crtc_active_changed(struct intel_atomic_state *state); 65 + bool intel_crtc_active_changed(const struct intel_crtc_state *old_crtc_state, 66 + const struct intel_crtc_state *new_crtc_state); 67 + 68 + unsigned int intel_crtc_bw_num_active_planes(const struct intel_crtc_state *crtc_state); 69 + unsigned int intel_crtc_bw_data_rate(const struct intel_crtc_state *crtc_state); 70 + int intel_crtc_bw_min_cdclk(const struct intel_crtc_state *crtc_state); 71 + 61 72 #endif
+10 -6
drivers/gpu/drm/i915/display/intel_crtc_state_dump.c
··· 289 289 drm_printf(&p, "scanline offset: %d\n", 290 290 intel_crtc_scanline_offset(pipe_config)); 291 291 292 - drm_printf(&p, "vblank delay: %d, framestart delay: %d, MSA timing delay: %d\n", 293 - pipe_config->hw.adjusted_mode.crtc_vblank_start - 294 - pipe_config->hw.adjusted_mode.crtc_vdisplay, 295 - pipe_config->framestart_delay, pipe_config->msa_timing_delay); 292 + drm_printf(&p, "framestart delay: %d, MSA timing delay: %d, set context latency: %d\n", 293 + pipe_config->framestart_delay, pipe_config->msa_timing_delay, 294 + pipe_config->set_context_latency); 296 295 297 296 drm_printf(&p, "vrr: %s, fixed rr: %s, vmin: %d, vmax: %d, flipline: %d, pipeline full: %d, guardband: %d vsync start: %d, vsync end: %d\n", 298 297 str_yes_no(pipe_config->vrr.enable), ··· 312 313 drm_printf(&p, "pipe mode: " DRM_MODE_FMT "\n", 313 314 DRM_MODE_ARG(&pipe_config->hw.pipe_mode)); 314 315 intel_dump_crtc_timings(&p, &pipe_config->hw.pipe_mode); 315 - drm_printf(&p, "port clock: %d, pipe src: " DRM_RECT_FMT ", pixel rate %d\n", 316 + drm_printf(&p, "port clock: %d, pipe src: " DRM_RECT_FMT ", pixel rate %d, min cdclk %d\n", 316 317 pipe_config->port_clock, DRM_RECT_ARG(&pipe_config->pipe_src), 317 - pipe_config->pixel_rate); 318 + pipe_config->pixel_rate, pipe_config->min_cdclk); 318 319 319 320 drm_printf(&p, "linetime: %d, ips linetime: %d\n", 320 321 pipe_config->linetime, pipe_config->ips_linetime); ··· 371 372 vlv_dump_csc(&p, "wgc csc", &pipe_config->csc); 372 373 373 374 intel_vdsc_state_dump(&p, 0, pipe_config); 375 + 376 + drm_printf(&p, "sharpness strength: %d, sharpness tap size: %d, sharpness enable: %d\n", 377 + pipe_config->hw.casf_params.strength, 378 + pipe_config->hw.casf_params.win_size, 379 + pipe_config->hw.casf_params.casf_enable); 374 380 375 381 dump_planes: 376 382 if (!state)
+2 -2
drivers/gpu/drm/i915/display/intel_cursor.c
··· 12 12 #include <drm/drm_print.h> 13 13 #include <drm/drm_vblank.h> 14 14 15 - #include "i915_utils.h" 16 15 #include "intel_atomic.h" 17 16 #include "intel_cursor.h" 18 17 #include "intel_cursor_regs.h" 19 18 #include "intel_de.h" 20 19 #include "intel_display.h" 21 20 #include "intel_display_types.h" 21 + #include "intel_display_utils.h" 22 22 #include "intel_fb.h" 23 23 #include "intel_fb_pin.h" 24 24 #include "intel_frontbuffer.h" ··· 662 662 cntl = plane_state->ctl | 663 663 i9xx_cursor_ctl_crtc(crtc_state); 664 664 665 - if (width != height) 665 + if (DISPLAY_VER(display) < 14 && width != height) 666 666 fbc_ctl = CUR_FBC_EN | CUR_FBC_HEIGHT(height - 1); 667 667 668 668 base = plane_state->surf;
+61 -70
drivers/gpu/drm/i915/display/intel_cx0_phy.c
··· 8 8 9 9 #include <drm/drm_print.h> 10 10 11 - #include "i915_utils.h" 12 11 #include "intel_alpm.h" 13 12 #include "intel_cx0_phy.h" 14 13 #include "intel_cx0_phy_regs.h" ··· 15 16 #include "intel_ddi_buf_trans.h" 16 17 #include "intel_de.h" 17 18 #include "intel_display_types.h" 19 + #include "intel_display_utils.h" 18 20 #include "intel_dp.h" 19 21 #include "intel_hdmi.h" 22 + #include "intel_lt_phy.h" 20 23 #include "intel_panel.h" 21 24 #include "intel_psr.h" 22 25 #include "intel_snps_hdmi_pll.h" 23 26 #include "intel_tc.h" 24 - 25 - #define MB_WRITE_COMMITTED true 26 - #define MB_WRITE_UNCOMMITTED false 27 27 28 28 #define for_each_cx0_lane_in_mask(__lane_mask, __lane) \ 29 29 for ((__lane) = 0; (__lane) < 2; (__lane)++) \ ··· 37 39 struct intel_display *display = to_intel_display(encoder); 38 40 enum phy phy = intel_encoder_to_phy(encoder); 39 41 40 - /* PTL doesn't have a PHY connected to PORT B; as such, 41 - * there will never be a case where PTL uses PHY B. 42 - * WCL uses PORT A and B with the C10 PHY. 43 - * Reusing the condition for WCL and extending it for PORT B 44 - * should not cause any issues for PTL. 45 - */ 46 - if (display->platform.pantherlake && phy < PHY_C) 47 - return true; 42 + if (display->platform.pantherlake) { 43 + if (display->platform.pantherlake_wildcatlake) 44 + return phy <= PHY_B; 45 + else 46 + return phy == PHY_A; 47 + } 48 48 49 49 if ((display->platform.lunarlake || display->platform.meteorlake) && phy < PHY_C) 50 50 return true; ··· 126 130 intel_display_power_put(display, POWER_DOMAIN_DC_OFF, wakeref); 127 131 } 128 132 129 - static void intel_clear_response_ready_flag(struct intel_encoder *encoder, 130 - int lane) 133 + void intel_clear_response_ready_flag(struct intel_encoder *encoder, 134 + int lane) 131 135 { 132 136 struct intel_display *display = to_intel_display(encoder); 133 137 ··· 136 140 0, XELPDP_PORT_P2M_RESPONSE_READY | XELPDP_PORT_P2M_ERROR_SET); 137 141 } 138 142 139 - static void intel_cx0_bus_reset(struct intel_encoder *encoder, int lane) 143 + void intel_cx0_bus_reset(struct intel_encoder *encoder, int lane) 140 144 { 141 145 struct intel_display *display = to_intel_display(encoder); 142 146 enum port port = encoder->port; ··· 157 161 intel_clear_response_ready_flag(encoder, lane); 158 162 } 159 163 160 - static int intel_cx0_wait_for_ack(struct intel_encoder *encoder, 161 - int command, int lane, u32 *val) 164 + int intel_cx0_wait_for_ack(struct intel_encoder *encoder, 165 + int command, int lane, u32 *val) 162 166 { 163 167 struct intel_display *display = to_intel_display(encoder); 164 168 enum port port = encoder->port; ··· 269 273 return 0; 270 274 } 271 275 272 - static u8 intel_cx0_read(struct intel_encoder *encoder, 273 - u8 lane_mask, u16 addr) 276 + u8 intel_cx0_read(struct intel_encoder *encoder, u8 lane_mask, u16 addr) 274 277 { 275 278 int lane = lane_mask_to_lane(lane_mask); 276 279 ··· 356 361 "PHY %c Write %04x failed after %d retries.\n", phy_name(phy), addr, i); 357 362 } 358 363 359 - static void intel_cx0_write(struct intel_encoder *encoder, 360 - u8 lane_mask, u16 addr, u8 data, bool committed) 364 + void intel_cx0_write(struct intel_encoder *encoder, 365 + u8 lane_mask, u16 addr, u8 data, bool committed) 361 366 { 362 367 int lane; 363 368 ··· 409 414 __intel_cx0_write(encoder, lane, addr, val, committed); 410 415 } 411 416 412 - static void intel_cx0_rmw(struct intel_encoder *encoder, 413 - u8 lane_mask, u16 addr, u8 clear, u8 set, bool committed) 417 + void intel_cx0_rmw(struct intel_encoder *encoder, 418 + u8 lane_mask, u16 addr, u8 clear, u8 set, bool committed) 414 419 { 415 420 u8 lane; 416 421 ··· 2100 2105 return 0; 2101 2106 } 2102 2107 2108 + static int intel_c10pll_calc_port_clock(struct intel_encoder *encoder, 2109 + const struct intel_c10pll_state *pll_state); 2110 + 2103 2111 static void intel_c10pll_readout_hw_state(struct intel_encoder *encoder, 2104 2112 struct intel_c10pll_state *pll_state) 2105 2113 { ··· 2127 2129 pll_state->tx = intel_cx0_read(encoder, lane, PHY_C10_VDR_TX(0)); 2128 2130 2129 2131 intel_cx0_phy_transaction_end(encoder, wakeref); 2132 + 2133 + pll_state->clock = intel_c10pll_calc_port_clock(encoder, pll_state); 2130 2134 } 2131 2135 2132 2136 static void intel_c10_pll_program(struct intel_display *display, ··· 2587 2587 return false; 2588 2588 } 2589 2589 2590 - static bool is_hdmi_frl(u32 clock) 2591 - { 2592 - switch (clock) { 2593 - case 300000: /* 3 Gbps */ 2594 - case 600000: /* 6 Gbps */ 2595 - case 800000: /* 8 Gbps */ 2596 - case 1000000: /* 10 Gbps */ 2597 - case 1200000: /* 12 Gbps */ 2598 - return true; 2599 - default: 2600 - return false; 2601 - } 2602 - } 2603 - 2604 2590 static bool intel_c20_protocol_switch_valid(struct intel_encoder *encoder) 2605 2591 { 2606 2592 struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder); ··· 2600 2614 { 2601 2615 if (dp && is_dp2(clock)) 2602 2616 return 2; 2603 - else if (is_hdmi_frl(clock)) 2617 + else if (intel_hdmi_is_frl(clock)) 2604 2618 return 1; 2605 2619 else 2606 2620 return 0; ··· 2612 2626 bool is_dp, int port_clock) 2613 2627 { 2614 2628 u8 owned_lane_mask = intel_cx0_get_owned_lane_mask(encoder); 2629 + u8 serdes; 2615 2630 bool cntx; 2616 2631 int i; 2617 2632 2618 2633 /* 1. Read current context selection */ 2619 - cntx = intel_cx0_read(encoder, INTEL_CX0_LANE0, PHY_C20_VDR_CUSTOM_SERDES_RATE) & BIT(0); 2634 + cntx = intel_cx0_read(encoder, INTEL_CX0_LANE0, PHY_C20_VDR_CUSTOM_SERDES_RATE) & 2635 + PHY_C20_CONTEXT_TOGGLE; 2620 2636 2621 2637 /* 2622 2638 * 2. If there is a protocol switch from HDMI to DP or vice versa, clear ··· 2688 2700 MB_WRITE_COMMITTED); 2689 2701 2690 2702 /* 5. For DP or 6. For HDMI */ 2691 - if (is_dp) { 2692 - intel_cx0_rmw(encoder, owned_lane_mask, PHY_C20_VDR_CUSTOM_SERDES_RATE, 2693 - BIT(6) | PHY_C20_CUSTOM_SERDES_MASK, 2694 - BIT(6) | PHY_C20_CUSTOM_SERDES(intel_c20_get_dp_rate(port_clock)), 2695 - MB_WRITE_COMMITTED); 2696 - } else { 2697 - intel_cx0_rmw(encoder, owned_lane_mask, PHY_C20_VDR_CUSTOM_SERDES_RATE, 2698 - BIT(7) | PHY_C20_CUSTOM_SERDES_MASK, 2699 - is_hdmi_frl(port_clock) ? BIT(7) : 0, 2700 - MB_WRITE_COMMITTED); 2703 + serdes = 0; 2704 + if (is_dp) 2705 + serdes = PHY_C20_IS_DP | 2706 + PHY_C20_DP_RATE(intel_c20_get_dp_rate(port_clock)); 2707 + else if (intel_hdmi_is_frl(port_clock)) 2708 + serdes = PHY_C20_IS_HDMI_FRL; 2701 2709 2702 - intel_cx0_write(encoder, INTEL_CX0_BOTH_LANES, PHY_C20_VDR_HDMI_RATE, 2703 - intel_c20_get_hdmi_rate(port_clock), 2704 - MB_WRITE_COMMITTED); 2705 - } 2710 + intel_cx0_rmw(encoder, owned_lane_mask, PHY_C20_VDR_CUSTOM_SERDES_RATE, 2711 + PHY_C20_IS_DP | PHY_C20_DP_RATE_MASK | PHY_C20_IS_HDMI_FRL, 2712 + serdes, 2713 + MB_WRITE_COMMITTED); 2714 + 2715 + if (!is_dp) 2716 + intel_cx0_rmw(encoder, INTEL_CX0_BOTH_LANES, PHY_C20_VDR_HDMI_RATE, 2717 + PHY_C20_HDMI_RATE_MASK, 2718 + intel_c20_get_hdmi_rate(port_clock), 2719 + MB_WRITE_COMMITTED); 2706 2720 2707 2721 /* 2708 2722 * 7. Write Vendor specific registers to toggle context setting to load 2709 2723 * the updated programming toggle context bit 2710 2724 */ 2711 2725 intel_cx0_rmw(encoder, owned_lane_mask, PHY_C20_VDR_CUSTOM_SERDES_RATE, 2712 - BIT(0), cntx ? 0 : 1, MB_WRITE_COMMITTED); 2726 + PHY_C20_CONTEXT_TOGGLE, cntx ? 0 : PHY_C20_CONTEXT_TOGGLE, 2727 + MB_WRITE_COMMITTED); 2713 2728 } 2714 2729 2715 2730 static int intel_c10pll_calc_port_clock(struct intel_encoder *encoder, ··· 2759 2768 2760 2769 val |= XELPDP_FORWARD_CLOCK_UNGATE; 2761 2770 2762 - if (!is_dp && is_hdmi_frl(port_clock)) 2771 + if (!is_dp && intel_hdmi_is_frl(port_clock)) 2763 2772 val |= XELPDP_DDI_CLOCK_SELECT_PREP(display, XELPDP_DDI_CLOCK_SELECT_DIV18CLK); 2764 2773 else 2765 2774 val |= XELPDP_DDI_CLOCK_SELECT_PREP(display, XELPDP_DDI_CLOCK_SELECT_MAXPCLK); ··· 2799 2808 return val; 2800 2809 } 2801 2810 2802 - static void intel_cx0_powerdown_change_sequence(struct intel_encoder *encoder, 2803 - u8 lane_mask, u8 state) 2811 + void intel_cx0_powerdown_change_sequence(struct intel_encoder *encoder, 2812 + u8 lane_mask, u8 state) 2804 2813 { 2805 2814 struct intel_display *display = to_intel_display(encoder); 2806 2815 enum port port = encoder->port; ··· 2830 2839 /* Update Timeout Value */ 2831 2840 if (intel_de_wait_custom(display, buf_ctl2_reg, 2832 2841 intel_cx0_get_powerdown_update(lane_mask), 0, 2833 - XELPDP_PORT_POWERDOWN_UPDATE_TIMEOUT_US, 0, NULL)) 2842 + XELPDP_PORT_POWERDOWN_UPDATE_TIMEOUT_US, 2, NULL)) 2834 2843 drm_warn(display->drm, 2835 2844 "PHY %c failed to bring out of Lane reset after %dus.\n", 2836 2845 phy_name(phy), XELPDP_PORT_RESET_START_TIMEOUT_US); 2837 2846 } 2838 2847 2839 - static void intel_cx0_setup_powerdown(struct intel_encoder *encoder) 2848 + void intel_cx0_setup_powerdown(struct intel_encoder *encoder) 2840 2849 { 2841 2850 struct intel_display *display = to_intel_display(encoder); 2842 2851 enum port port = encoder->port; 2843 2852 2844 2853 intel_de_rmw(display, XELPDP_PORT_BUF_CTL2(display, port), 2845 2854 XELPDP_POWER_STATE_READY_MASK, 2846 - XELPDP_POWER_STATE_READY(CX0_P2_STATE_READY)); 2855 + XELPDP_POWER_STATE_READY(XELPDP_P2_STATE_READY)); 2847 2856 intel_de_rmw(display, XELPDP_PORT_BUF_CTL3(display, port), 2848 2857 XELPDP_POWER_STATE_ACTIVE_MASK | 2849 2858 XELPDP_PLL_LANE_STAGGERING_DELAY_MASK, 2850 - XELPDP_POWER_STATE_ACTIVE(CX0_P0_STATE_ACTIVE) | 2859 + XELPDP_POWER_STATE_ACTIVE(XELPDP_P0_STATE_ACTIVE) | 2851 2860 XELPDP_PLL_LANE_STAGGERING_DELAY(0)); 2852 2861 } 2853 2862 ··· 2920 2929 phy_name(phy), XELPDP_REFCLK_ENABLE_TIMEOUT_US); 2921 2930 2922 2931 intel_cx0_powerdown_change_sequence(encoder, INTEL_CX0_BOTH_LANES, 2923 - CX0_P2_STATE_RESET); 2932 + XELPDP_P2_STATE_RESET); 2924 2933 intel_cx0_setup_powerdown(encoder); 2925 2934 2926 2935 intel_de_rmw(display, XELPDP_PORT_BUF_CTL2(display, port), lane_pipe_reset, 0); ··· 3025 3034 * TODO: For DP alt mode use only one lane. 3026 3035 */ 3027 3036 intel_cx0_powerdown_change_sequence(encoder, INTEL_CX0_BOTH_LANES, 3028 - CX0_P2_STATE_READY); 3037 + XELPDP_P2_STATE_READY); 3029 3038 3030 3039 /* 3031 3040 * 4. Program PORT_MSGBUS_TIMER register's Message Bus Timer field to 0xA000. ··· 3151 3160 } 3152 3161 } 3153 3162 3154 - static void intel_mtl_tbt_pll_enable(struct intel_encoder *encoder, 3155 - const struct intel_crtc_state *crtc_state) 3163 + void intel_mtl_tbt_pll_enable(struct intel_encoder *encoder, 3164 + const struct intel_crtc_state *crtc_state) 3156 3165 { 3157 3166 struct intel_display *display = to_intel_display(encoder); 3158 3167 enum phy phy = intel_encoder_to_phy(encoder); ··· 3266 3275 struct intel_display *display = to_intel_display(encoder); 3267 3276 3268 3277 if (intel_encoder_is_c10phy(encoder)) 3269 - return CX0_P2PG_STATE_DISABLE; 3278 + return XELPDP_P2PG_STATE_DISABLE; 3270 3279 3271 3280 if ((display->platform.battlemage && encoder->port == PORT_A) || 3272 3281 (DISPLAY_VER(display) >= 30 && encoder->type == INTEL_OUTPUT_EDP)) 3273 - return CX0_P2PG_STATE_DISABLE; 3282 + return XELPDP_P2PG_STATE_DISABLE; 3274 3283 3275 - return CX0_P4PG_STATE_DISABLE; 3284 + return XELPDP_P4PG_STATE_DISABLE; 3276 3285 } 3277 3286 3278 3287 static void intel_cx0pll_disable(struct intel_encoder *encoder) ··· 3336 3345 intel_cx0_get_pclk_pll_request(lane); 3337 3346 } 3338 3347 3339 - static void intel_mtl_tbt_pll_disable(struct intel_encoder *encoder) 3348 + void intel_mtl_tbt_pll_disable(struct intel_encoder *encoder) 3340 3349 { 3341 3350 struct intel_display *display = to_intel_display(encoder); 3342 3351 enum phy phy = intel_encoder_to_phy(encoder); ··· 3575 3584 struct intel_encoder *encoder; 3576 3585 struct intel_cx0pll_state mpll_hw_state = {}; 3577 3586 3578 - if (DISPLAY_VER(display) < 14) 3587 + if (!IS_DISPLAY_VER(display, 14, 30)) 3579 3588 return; 3580 3589 3581 3590 if (!new_crtc_state->hw.active)
+21
drivers/gpu/drm/i915/display/intel_cx0_phy.h
··· 8 8 9 9 #include <linux/types.h> 10 10 11 + #define MB_WRITE_COMMITTED true 12 + #define MB_WRITE_UNCOMMITTED false 13 + 11 14 enum icl_port_dpll_id; 12 15 struct intel_atomic_state; 13 16 struct intel_c10pll_state; ··· 22 19 struct intel_encoder; 23 20 struct intel_hdmi; 24 21 22 + void intel_clear_response_ready_flag(struct intel_encoder *encoder, 23 + int lane); 25 24 bool intel_encoder_is_c10phy(struct intel_encoder *encoder); 26 25 void intel_mtl_pll_enable(struct intel_encoder *encoder, 27 26 const struct intel_crtc_state *crtc_state); ··· 46 41 const struct intel_cx0pll_state *b); 47 42 void intel_cx0_phy_set_signal_levels(struct intel_encoder *encoder, 48 43 const struct intel_crtc_state *crtc_state); 44 + void intel_cx0_powerdown_change_sequence(struct intel_encoder *encoder, 45 + u8 lane_mask, u8 state); 46 + int intel_cx0_phy_check_hdmi_link_rate(struct intel_hdmi *hdmi, int clock); 47 + void intel_cx0_setup_powerdown(struct intel_encoder *encoder); 48 + bool intel_cx0_is_hdmi_frl(u32 clock); 49 + u8 intel_cx0_read(struct intel_encoder *encoder, u8 lane_mask, u16 addr); 50 + void intel_cx0_rmw(struct intel_encoder *encoder, 51 + u8 lane_mask, u16 addr, u8 clear, u8 set, bool committed); 52 + void intel_cx0_write(struct intel_encoder *encoder, 53 + u8 lane_mask, u16 addr, u8 data, bool committed); 54 + int intel_cx0_wait_for_ack(struct intel_encoder *encoder, 55 + int command, int lane, u32 *val); 56 + void intel_cx0_bus_reset(struct intel_encoder *encoder, int lane); 49 57 int intel_mtl_tbt_calc_port_clock(struct intel_encoder *encoder); 50 58 void intel_cx0_pll_power_save_wa(struct intel_display *display); 51 59 void intel_lnl_mac_transmit_lfps(struct intel_encoder *encoder, 52 60 const struct intel_crtc_state *crtc_state); 61 + void intel_mtl_tbt_pll_enable(struct intel_encoder *encoder, 62 + const struct intel_crtc_state *crtc_state); 63 + void intel_mtl_tbt_pll_disable(struct intel_encoder *encoder); 53 64 54 65 #endif /* __INTEL_CX0_PHY_H__ */
+17 -8
drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h
··· 50 50 #define XELPDP_PORT_M2P_COMMAND_WRITE_UNCOMMITTED REG_FIELD_PREP(XELPDP_PORT_M2P_COMMAND_TYPE_MASK, 0x1) 51 51 #define XELPDP_PORT_M2P_COMMAND_WRITE_COMMITTED REG_FIELD_PREP(XELPDP_PORT_M2P_COMMAND_TYPE_MASK, 0x2) 52 52 #define XELPDP_PORT_M2P_COMMAND_READ REG_FIELD_PREP(XELPDP_PORT_M2P_COMMAND_TYPE_MASK, 0x3) 53 + #define XELPDP_PORT_P2P_TRANSACTION_PENDING REG_BIT(24) 53 54 #define XELPDP_PORT_M2P_DATA_MASK REG_GENMASK(23, 16) 54 55 #define XELPDP_PORT_M2P_DATA(val) REG_FIELD_PREP(XELPDP_PORT_M2P_DATA_MASK, val) 55 56 #define XELPDP_PORT_M2P_TRANSACTION_RESET REG_BIT(15) ··· 105 104 #define XELPDP_PORT_BUF_PORT_DATA_20BIT REG_FIELD_PREP(XELPDP_PORT_BUF_PORT_DATA_WIDTH_MASK, 1) 106 105 #define XELPDP_PORT_BUF_PORT_DATA_40BIT REG_FIELD_PREP(XELPDP_PORT_BUF_PORT_DATA_WIDTH_MASK, 2) 107 106 #define XELPDP_PORT_REVERSAL REG_BIT(16) 107 + #define XE3PLPDP_PHY_MODE_MASK REG_GENMASK(15, 12) 108 + #define XE3PLPDP_PHY_MODE_DP REG_FIELD_PREP(XE3PLPDP_PHY_MODE_MASK, 0x3) 108 109 #define XELPDP_PORT_BUF_IO_SELECT_TBT REG_BIT(11) 109 110 #define XELPDP_PORT_BUF_PHY_IDLE REG_BIT(7) 110 111 #define XELPDP_TC_PHY_OWNERSHIP REG_BIT(6) ··· 127 124 _XELPDP_PORT_BUF_CTL2(port)) 128 125 #define XELPDP_LANE_PIPE_RESET(lane) _PICK(lane, REG_BIT(31), REG_BIT(30)) 129 126 #define XELPDP_LANE_PHY_CURRENT_STATUS(lane) _PICK(lane, REG_BIT(29), REG_BIT(28)) 127 + #define XE3PLPDP_LANE_PHY_PULSE_STATUS(lane) _PICK(lane, REG_BIT(27), REG_BIT(26)) 130 128 #define XELPDP_LANE_POWERDOWN_UPDATE(lane) _PICK(lane, REG_BIT(25), REG_BIT(24)) 131 129 #define _XELPDP_LANE0_POWERDOWN_NEW_STATE_MASK REG_GENMASK(23, 20) 132 130 #define _XELPDP_LANE0_POWERDOWN_NEW_STATE(val) REG_FIELD_PREP(_XELPDP_LANE0_POWERDOWN_NEW_STATE_MASK, val) ··· 153 149 #define XELPDP_PLL_LANE_STAGGERING_DELAY(val) REG_FIELD_PREP(XELPDP_PLL_LANE_STAGGERING_DELAY_MASK, val) 154 150 #define XELPDP_POWER_STATE_ACTIVE_MASK REG_GENMASK(3, 0) 155 151 #define XELPDP_POWER_STATE_ACTIVE(val) REG_FIELD_PREP(XELPDP_POWER_STATE_ACTIVE_MASK, val) 156 - #define CX0_P0_STATE_ACTIVE 0x0 157 - #define CX0_P2_STATE_READY 0x2 158 - #define CX0_P2PG_STATE_DISABLE 0x9 159 - #define CX0_P4PG_STATE_DISABLE 0xC 160 - #define CX0_P2_STATE_RESET 0x2 152 + #define XELPDP_P0_STATE_ACTIVE 0x0 153 + #define XELPDP_P2_STATE_READY 0x2 154 + #define XE3PLPD_P4_STATE_DISABLE 0x4 155 + #define XELPDP_P2PG_STATE_DISABLE 0x9 156 + #define XELPDP_P4PG_STATE_DISABLE 0xC 157 + #define XELPDP_P2_STATE_RESET 0x2 161 158 162 159 #define _XELPDP_PORT_MSGBUS_TIMER_LN0_A 0x640d8 163 160 #define _XELPDP_PORT_MSGBUS_TIMER_LN0_B 0x641d8 ··· 303 298 #define PHY_C20_RD_DATA_L 0xC08 304 299 #define PHY_C20_RD_DATA_H 0xC09 305 300 #define PHY_C20_VDR_CUSTOM_SERDES_RATE 0xD00 306 - #define PHY_C20_VDR_HDMI_RATE 0xD01 301 + #define PHY_C20_IS_HDMI_FRL REG_BIT8(7) 302 + #define PHY_C20_IS_DP REG_BIT8(6) 303 + #define PHY_C20_DP_RATE_MASK REG_GENMASK8(4, 1) 304 + #define PHY_C20_DP_RATE(val) REG_FIELD_PREP8(PHY_C20_DP_RATE_MASK, val) 307 305 #define PHY_C20_CONTEXT_TOGGLE REG_BIT8(0) 308 - #define PHY_C20_CUSTOM_SERDES_MASK REG_GENMASK8(4, 1) 309 - #define PHY_C20_CUSTOM_SERDES(val) REG_FIELD_PREP8(PHY_C20_CUSTOM_SERDES_MASK, val) 306 + #define PHY_C20_VDR_HDMI_RATE 0xD01 307 + #define PHY_C20_HDMI_RATE_MASK REG_GENMASK8(1, 0) 308 + #define PHY_C20_HDMI_RATE(val) REG_FIELD_PREP8(PHY_C20_HDMI_RATE_MASK, val) 310 309 #define PHY_C20_VDR_CUSTOM_WIDTH 0xD02 311 310 #define PHY_C20_CUSTOM_WIDTH_MASK REG_GENMASK(1, 0) 312 311 #define PHY_C20_CUSTOM_WIDTH(val) REG_FIELD_PREP8(PHY_C20_CUSTOM_WIDTH_MASK, val)
+295
drivers/gpu/drm/i915/display/intel_dbuf_bw.c
··· 1 + // SPDX-License-Identifier: MIT 2 + /* 3 + * Copyright © 2025 Intel Corporation 4 + */ 5 + 6 + #include <drm/drm_print.h> 7 + 8 + #include "intel_dbuf_bw.h" 9 + #include "intel_display_core.h" 10 + #include "intel_display_types.h" 11 + #include "skl_watermark.h" 12 + 13 + struct intel_dbuf_bw { 14 + unsigned int max_bw[I915_MAX_DBUF_SLICES]; 15 + u8 active_planes[I915_MAX_DBUF_SLICES]; 16 + }; 17 + 18 + struct intel_dbuf_bw_state { 19 + struct intel_global_state base; 20 + struct intel_dbuf_bw dbuf_bw[I915_MAX_PIPES]; 21 + }; 22 + 23 + struct intel_dbuf_bw_state *to_intel_dbuf_bw_state(struct intel_global_state *obj_state) 24 + { 25 + return container_of(obj_state, struct intel_dbuf_bw_state, base); 26 + } 27 + 28 + struct intel_dbuf_bw_state * 29 + intel_atomic_get_old_dbuf_bw_state(struct intel_atomic_state *state) 30 + { 31 + struct intel_display *display = to_intel_display(state); 32 + struct intel_global_state *dbuf_bw_state; 33 + 34 + dbuf_bw_state = intel_atomic_get_old_global_obj_state(state, &display->dbuf_bw.obj); 35 + 36 + return to_intel_dbuf_bw_state(dbuf_bw_state); 37 + } 38 + 39 + struct intel_dbuf_bw_state * 40 + intel_atomic_get_new_dbuf_bw_state(struct intel_atomic_state *state) 41 + { 42 + struct intel_display *display = to_intel_display(state); 43 + struct intel_global_state *dbuf_bw_state; 44 + 45 + dbuf_bw_state = intel_atomic_get_new_global_obj_state(state, &display->dbuf_bw.obj); 46 + 47 + return to_intel_dbuf_bw_state(dbuf_bw_state); 48 + } 49 + 50 + struct intel_dbuf_bw_state * 51 + intel_atomic_get_dbuf_bw_state(struct intel_atomic_state *state) 52 + { 53 + struct intel_display *display = to_intel_display(state); 54 + struct intel_global_state *dbuf_bw_state; 55 + 56 + dbuf_bw_state = intel_atomic_get_global_obj_state(state, &display->dbuf_bw.obj); 57 + if (IS_ERR(dbuf_bw_state)) 58 + return ERR_CAST(dbuf_bw_state); 59 + 60 + return to_intel_dbuf_bw_state(dbuf_bw_state); 61 + } 62 + 63 + static bool intel_dbuf_bw_changed(struct intel_display *display, 64 + const struct intel_dbuf_bw *old_dbuf_bw, 65 + const struct intel_dbuf_bw *new_dbuf_bw) 66 + { 67 + enum dbuf_slice slice; 68 + 69 + for_each_dbuf_slice(display, slice) { 70 + if (old_dbuf_bw->max_bw[slice] != new_dbuf_bw->max_bw[slice] || 71 + old_dbuf_bw->active_planes[slice] != new_dbuf_bw->active_planes[slice]) 72 + return true; 73 + } 74 + 75 + return false; 76 + } 77 + 78 + static bool intel_dbuf_bw_state_changed(struct intel_display *display, 79 + const struct intel_dbuf_bw_state *old_dbuf_bw_state, 80 + const struct intel_dbuf_bw_state *new_dbuf_bw_state) 81 + { 82 + enum pipe pipe; 83 + 84 + for_each_pipe(display, pipe) { 85 + const struct intel_dbuf_bw *old_dbuf_bw = 86 + &old_dbuf_bw_state->dbuf_bw[pipe]; 87 + const struct intel_dbuf_bw *new_dbuf_bw = 88 + &new_dbuf_bw_state->dbuf_bw[pipe]; 89 + 90 + if (intel_dbuf_bw_changed(display, old_dbuf_bw, new_dbuf_bw)) 91 + return true; 92 + } 93 + 94 + return false; 95 + } 96 + 97 + static void skl_plane_calc_dbuf_bw(struct intel_dbuf_bw *dbuf_bw, 98 + struct intel_crtc *crtc, 99 + enum plane_id plane_id, 100 + const struct skl_ddb_entry *ddb, 101 + unsigned int data_rate) 102 + { 103 + struct intel_display *display = to_intel_display(crtc); 104 + unsigned int dbuf_mask = skl_ddb_dbuf_slice_mask(display, ddb); 105 + enum dbuf_slice slice; 106 + 107 + /* 108 + * The arbiter can only really guarantee an 109 + * equal share of the total bw to each plane. 110 + */ 111 + for_each_dbuf_slice_in_mask(display, slice, dbuf_mask) { 112 + dbuf_bw->max_bw[slice] = max(dbuf_bw->max_bw[slice], data_rate); 113 + dbuf_bw->active_planes[slice] |= BIT(plane_id); 114 + } 115 + } 116 + 117 + static void skl_crtc_calc_dbuf_bw(struct intel_dbuf_bw *dbuf_bw, 118 + const struct intel_crtc_state *crtc_state) 119 + { 120 + struct intel_display *display = to_intel_display(crtc_state); 121 + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 122 + enum plane_id plane_id; 123 + 124 + memset(dbuf_bw, 0, sizeof(*dbuf_bw)); 125 + 126 + if (!crtc_state->hw.active) 127 + return; 128 + 129 + for_each_plane_id_on_crtc(crtc, plane_id) { 130 + /* 131 + * We assume cursors are small enough 132 + * to not cause bandwidth problems. 133 + */ 134 + if (plane_id == PLANE_CURSOR) 135 + continue; 136 + 137 + skl_plane_calc_dbuf_bw(dbuf_bw, crtc, plane_id, 138 + &crtc_state->wm.skl.plane_ddb[plane_id], 139 + crtc_state->data_rate[plane_id]); 140 + 141 + if (DISPLAY_VER(display) < 11) 142 + skl_plane_calc_dbuf_bw(dbuf_bw, crtc, plane_id, 143 + &crtc_state->wm.skl.plane_ddb_y[plane_id], 144 + crtc_state->data_rate[plane_id]); 145 + } 146 + } 147 + 148 + /* "Maximum Data Buffer Bandwidth" */ 149 + int intel_dbuf_bw_min_cdclk(struct intel_display *display, 150 + const struct intel_dbuf_bw_state *dbuf_bw_state) 151 + { 152 + unsigned int total_max_bw = 0; 153 + enum dbuf_slice slice; 154 + 155 + for_each_dbuf_slice(display, slice) { 156 + int num_active_planes = 0; 157 + unsigned int max_bw = 0; 158 + enum pipe pipe; 159 + 160 + /* 161 + * The arbiter can only really guarantee an 162 + * equal share of the total bw to each plane. 163 + */ 164 + for_each_pipe(display, pipe) { 165 + const struct intel_dbuf_bw *dbuf_bw = &dbuf_bw_state->dbuf_bw[pipe]; 166 + 167 + max_bw = max(dbuf_bw->max_bw[slice], max_bw); 168 + num_active_planes += hweight8(dbuf_bw->active_planes[slice]); 169 + } 170 + max_bw *= num_active_planes; 171 + 172 + total_max_bw = max(total_max_bw, max_bw); 173 + } 174 + 175 + return DIV_ROUND_UP(total_max_bw, 64); 176 + } 177 + 178 + int intel_dbuf_bw_calc_min_cdclk(struct intel_atomic_state *state, 179 + bool *need_cdclk_calc) 180 + { 181 + struct intel_display *display = to_intel_display(state); 182 + struct intel_dbuf_bw_state *new_dbuf_bw_state = NULL; 183 + const struct intel_dbuf_bw_state *old_dbuf_bw_state = NULL; 184 + const struct intel_crtc_state *old_crtc_state; 185 + const struct intel_crtc_state *new_crtc_state; 186 + struct intel_crtc *crtc; 187 + int ret, i; 188 + 189 + if (DISPLAY_VER(display) < 9) 190 + return 0; 191 + 192 + for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, 193 + new_crtc_state, i) { 194 + struct intel_dbuf_bw old_dbuf_bw, new_dbuf_bw; 195 + 196 + skl_crtc_calc_dbuf_bw(&old_dbuf_bw, old_crtc_state); 197 + skl_crtc_calc_dbuf_bw(&new_dbuf_bw, new_crtc_state); 198 + 199 + if (!intel_dbuf_bw_changed(display, &old_dbuf_bw, &new_dbuf_bw)) 200 + continue; 201 + 202 + new_dbuf_bw_state = intel_atomic_get_dbuf_bw_state(state); 203 + if (IS_ERR(new_dbuf_bw_state)) 204 + return PTR_ERR(new_dbuf_bw_state); 205 + 206 + old_dbuf_bw_state = intel_atomic_get_old_dbuf_bw_state(state); 207 + 208 + new_dbuf_bw_state->dbuf_bw[crtc->pipe] = new_dbuf_bw; 209 + } 210 + 211 + if (!old_dbuf_bw_state) 212 + return 0; 213 + 214 + if (intel_dbuf_bw_state_changed(display, old_dbuf_bw_state, new_dbuf_bw_state)) { 215 + ret = intel_atomic_lock_global_state(&new_dbuf_bw_state->base); 216 + if (ret) 217 + return ret; 218 + } 219 + 220 + ret = intel_cdclk_update_dbuf_bw_min_cdclk(state, 221 + intel_dbuf_bw_min_cdclk(display, old_dbuf_bw_state), 222 + intel_dbuf_bw_min_cdclk(display, new_dbuf_bw_state), 223 + need_cdclk_calc); 224 + if (ret) 225 + return ret; 226 + 227 + return 0; 228 + } 229 + 230 + void intel_dbuf_bw_update_hw_state(struct intel_display *display) 231 + { 232 + struct intel_dbuf_bw_state *dbuf_bw_state = 233 + to_intel_dbuf_bw_state(display->dbuf_bw.obj.state); 234 + struct intel_crtc *crtc; 235 + 236 + if (DISPLAY_VER(display) < 9) 237 + return; 238 + 239 + for_each_intel_crtc(display->drm, crtc) { 240 + const struct intel_crtc_state *crtc_state = 241 + to_intel_crtc_state(crtc->base.state); 242 + 243 + skl_crtc_calc_dbuf_bw(&dbuf_bw_state->dbuf_bw[crtc->pipe], crtc_state); 244 + } 245 + } 246 + 247 + void intel_dbuf_bw_crtc_disable_noatomic(struct intel_crtc *crtc) 248 + { 249 + struct intel_display *display = to_intel_display(crtc); 250 + struct intel_dbuf_bw_state *dbuf_bw_state = 251 + to_intel_dbuf_bw_state(display->dbuf_bw.obj.state); 252 + enum pipe pipe = crtc->pipe; 253 + 254 + if (DISPLAY_VER(display) < 9) 255 + return; 256 + 257 + memset(&dbuf_bw_state->dbuf_bw[pipe], 0, sizeof(dbuf_bw_state->dbuf_bw[pipe])); 258 + } 259 + 260 + static struct intel_global_state * 261 + intel_dbuf_bw_duplicate_state(struct intel_global_obj *obj) 262 + { 263 + struct intel_dbuf_bw_state *state; 264 + 265 + state = kmemdup(obj->state, sizeof(*state), GFP_KERNEL); 266 + if (!state) 267 + return NULL; 268 + 269 + return &state->base; 270 + } 271 + 272 + static void intel_dbuf_bw_destroy_state(struct intel_global_obj *obj, 273 + struct intel_global_state *state) 274 + { 275 + kfree(state); 276 + } 277 + 278 + static const struct intel_global_state_funcs intel_dbuf_bw_funcs = { 279 + .atomic_duplicate_state = intel_dbuf_bw_duplicate_state, 280 + .atomic_destroy_state = intel_dbuf_bw_destroy_state, 281 + }; 282 + 283 + int intel_dbuf_bw_init(struct intel_display *display) 284 + { 285 + struct intel_dbuf_bw_state *state; 286 + 287 + state = kzalloc(sizeof(*state), GFP_KERNEL); 288 + if (!state) 289 + return -ENOMEM; 290 + 291 + intel_atomic_global_obj_init(display, &display->dbuf_bw.obj, 292 + &state->base, &intel_dbuf_bw_funcs); 293 + 294 + return 0; 295 + }
+37
drivers/gpu/drm/i915/display/intel_dbuf_bw.h
··· 1 + /* SPDX-License-Identifier: MIT */ 2 + /* 3 + * Copyright © 2025 Intel Corporation 4 + */ 5 + 6 + #ifndef __INTEL_DBUF_BW_H__ 7 + #define __INTEL_DBUF_BW_H__ 8 + 9 + #include <drm/drm_atomic.h> 10 + 11 + struct intel_atomic_state; 12 + struct intel_dbuf_bw_state; 13 + struct intel_crtc; 14 + struct intel_display; 15 + struct intel_global_state; 16 + 17 + struct intel_dbuf_bw_state * 18 + to_intel_dbuf_bw_state(struct intel_global_state *obj_state); 19 + 20 + struct intel_dbuf_bw_state * 21 + intel_atomic_get_old_dbuf_bw_state(struct intel_atomic_state *state); 22 + 23 + struct intel_dbuf_bw_state * 24 + intel_atomic_get_new_dbuf_bw_state(struct intel_atomic_state *state); 25 + 26 + struct intel_dbuf_bw_state * 27 + intel_atomic_get_dbuf_bw_state(struct intel_atomic_state *state); 28 + 29 + int intel_dbuf_bw_init(struct intel_display *display); 30 + int intel_dbuf_bw_calc_min_cdclk(struct intel_atomic_state *state, 31 + bool *need_cdclk_calc); 32 + int intel_dbuf_bw_min_cdclk(struct intel_display *display, 33 + const struct intel_dbuf_bw_state *dbuf_bw_state); 34 + void intel_dbuf_bw_update_hw_state(struct intel_display *display); 35 + void intel_dbuf_bw_crtc_disable_noatomic(struct intel_crtc *crtc); 36 + 37 + #endif /* __INTEL_DBUF_BW_H__ */
+38 -5
drivers/gpu/drm/i915/display/intel_ddi.c
··· 35 35 #include <drm/drm_privacy_screen_consumer.h> 36 36 37 37 #include "i915_reg.h" 38 - #include "i915_utils.h" 39 38 #include "icl_dsi.h" 40 39 #include "intel_alpm.h" 41 40 #include "intel_audio.h" ··· 52 53 #include "intel_display_power.h" 53 54 #include "intel_display_regs.h" 54 55 #include "intel_display_types.h" 56 + #include "intel_display_utils.h" 55 57 #include "intel_dkl_phy.h" 56 58 #include "intel_dkl_phy_regs.h" 57 59 #include "intel_dp.h" ··· 72 72 #include "intel_hotplug.h" 73 73 #include "intel_hti.h" 74 74 #include "intel_lspcon.h" 75 + #include "intel_lt_phy.h" 75 76 #include "intel_mg_phy_regs.h" 76 77 #include "intel_modeset_lock.h" 77 78 #include "intel_panel.h" ··· 1467 1466 u8 signal_levels) 1468 1467 { 1469 1468 struct intel_display *display = to_intel_display(intel_dp); 1469 + const u8 *signal_array; 1470 + size_t array_size; 1470 1471 int i; 1471 1472 1472 - for (i = 0; i < ARRAY_SIZE(index_to_dp_signal_levels); i++) { 1473 - if (index_to_dp_signal_levels[i] == signal_levels) 1473 + signal_array = index_to_dp_signal_levels; 1474 + array_size = ARRAY_SIZE(index_to_dp_signal_levels); 1475 + 1476 + for (i = 0; i < array_size; i++) { 1477 + if (signal_array[i] == signal_levels) 1474 1478 return i; 1475 1479 } 1476 1480 ··· 4246 4240 &crtc_state->dpll_hw_state); 4247 4241 } 4248 4242 4243 + static void xe3plpd_ddi_get_config(struct intel_encoder *encoder, 4244 + struct intel_crtc_state *crtc_state) 4245 + { 4246 + intel_lt_phy_pll_readout_hw_state(encoder, crtc_state, &crtc_state->dpll_hw_state.ltpll); 4247 + 4248 + if (crtc_state->dpll_hw_state.ltpll.tbt_mode) 4249 + crtc_state->port_clock = intel_mtl_tbt_calc_port_clock(encoder); 4250 + else 4251 + crtc_state->port_clock = 4252 + intel_lt_phy_calc_port_clock(encoder, crtc_state); 4253 + intel_ddi_get_config(encoder, crtc_state); 4254 + } 4255 + 4249 4256 static void mtl_ddi_get_config(struct intel_encoder *encoder, 4250 4257 struct intel_crtc_state *crtc_state) 4251 4258 { ··· 4578 4559 struct intel_display *display = to_intel_display(encoder); 4579 4560 struct drm_connector *connector = conn_state->connector; 4580 4561 u8 port_sync_transcoders = 0; 4562 + int ret = 0; 4563 + 4564 + if (intel_crtc_has_dp_encoder(crtc_state)) 4565 + ret = intel_dp_compute_config_late(encoder, crtc_state, conn_state); 4566 + 4567 + if (ret) 4568 + return ret; 4581 4569 4582 4570 drm_dbg_kms(display->drm, "[ENCODER:%d:%s] [CRTC:%d:%s]\n", 4583 4571 encoder->base.base.id, encoder->base.name, ··· 5250 5224 encoder->cloneable = 0; 5251 5225 encoder->pipe_mask = ~0; 5252 5226 5253 - if (DISPLAY_VER(display) >= 14) { 5227 + if (HAS_LT_PHY(display)) { 5228 + encoder->enable_clock = intel_xe3plpd_pll_enable; 5229 + encoder->disable_clock = intel_xe3plpd_pll_disable; 5230 + encoder->port_pll_type = intel_mtl_port_pll_type; 5231 + encoder->get_config = xe3plpd_ddi_get_config; 5232 + } else if (DISPLAY_VER(display) >= 14) { 5254 5233 encoder->enable_clock = intel_mtl_pll_enable; 5255 5234 encoder->disable_clock = intel_mtl_pll_disable; 5256 5235 encoder->port_pll_type = intel_mtl_port_pll_type; ··· 5320 5289 encoder->get_config = hsw_ddi_get_config; 5321 5290 } 5322 5291 5323 - if (DISPLAY_VER(display) >= 14) { 5292 + if (HAS_LT_PHY(display)) { 5293 + encoder->set_signal_levels = intel_lt_phy_set_signal_levels; 5294 + } else if (DISPLAY_VER(display) >= 14) { 5324 5295 encoder->set_signal_levels = intel_cx0_phy_set_signal_levels; 5325 5296 } else if (display->platform.dg2) { 5326 5297 encoder->set_signal_levels = intel_snps_phy_set_signal_levels;
+81 -2
drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c
··· 3 3 * Copyright © 2020 Intel Corporation 4 4 */ 5 5 6 - #include "i915_utils.h" 7 6 #include "intel_cx0_phy.h" 8 7 #include "intel_ddi.h" 9 8 #include "intel_ddi_buf_trans.h" 10 9 #include "intel_de.h" 11 10 #include "intel_display_types.h" 11 + #include "intel_display_utils.h" 12 12 #include "intel_dp.h" 13 + #include "intel_lt_phy.h" 13 14 14 15 /* HDMI/DVI modes ignore everything but the last 2 items. So we share 15 16 * them for both DP and FDI transports, allowing those ports to ··· 1116 1115 .num_entries = ARRAY_SIZE(_mtl_c20_trans_uhbr), 1117 1116 }; 1118 1117 1118 + /* DP1.4 */ 1119 + static const union intel_ddi_buf_trans_entry _xe3plpd_lt_trans_dp14[] = { 1120 + { .lt = { 1, 0, 0, 21, 0 } }, 1121 + { .lt = { 1, 1, 0, 24, 3 } }, 1122 + { .lt = { 1, 2, 0, 28, 7 } }, 1123 + { .lt = { 0, 3, 0, 35, 13 } }, 1124 + { .lt = { 1, 1, 0, 27, 0 } }, 1125 + { .lt = { 1, 2, 0, 31, 4 } }, 1126 + { .lt = { 0, 3, 0, 39, 9 } }, 1127 + { .lt = { 1, 2, 0, 35, 0 } }, 1128 + { .lt = { 0, 3, 0, 41, 7 } }, 1129 + { .lt = { 0, 3, 0, 48, 0 } }, 1130 + }; 1131 + 1132 + /* DP2.1 */ 1133 + static const union intel_ddi_buf_trans_entry _xe3plpd_lt_trans_uhbr[] = { 1134 + { .lt = { 0, 0, 0, 48, 0 } }, 1135 + { .lt = { 0, 0, 0, 43, 5 } }, 1136 + { .lt = { 0, 0, 0, 40, 8 } }, 1137 + { .lt = { 0, 0, 0, 37, 11 } }, 1138 + { .lt = { 0, 0, 0, 33, 15 } }, 1139 + { .lt = { 0, 0, 2, 46, 0 } }, 1140 + { .lt = { 0, 0, 2, 42, 4 } }, 1141 + { .lt = { 0, 0, 2, 38, 8 } }, 1142 + { .lt = { 0, 0, 2, 35, 11 } }, 1143 + { .lt = { 0, 0, 2, 33, 13 } }, 1144 + { .lt = { 0, 0, 4, 44, 0 } }, 1145 + { .lt = { 0, 0, 4, 40, 4 } }, 1146 + { .lt = { 0, 0, 4, 37, 7 } }, 1147 + { .lt = { 0, 0, 4, 33, 11 } }, 1148 + { .lt = { 0, 0, 8, 40, 0 } }, 1149 + { .lt = { 1, 0, 2, 26, 2 } }, 1150 + }; 1151 + 1152 + /* eDp */ 1153 + static const union intel_ddi_buf_trans_entry _xe3plpd_lt_trans_edp[] = { 1154 + { .lt = { 1, 0, 0, 12, 0 } }, 1155 + { .lt = { 1, 1, 0, 13, 1 } }, 1156 + { .lt = { 1, 2, 0, 15, 3 } }, 1157 + { .lt = { 1, 3, 0, 19, 7 } }, 1158 + { .lt = { 1, 1, 0, 14, 0 } }, 1159 + { .lt = { 1, 2, 0, 16, 2 } }, 1160 + { .lt = { 1, 3, 0, 21, 5 } }, 1161 + { .lt = { 1, 2, 0, 18, 0 } }, 1162 + { .lt = { 1, 3, 0, 22, 4 } }, 1163 + { .lt = { 1, 3, 0, 26, 0 } }, 1164 + }; 1165 + 1166 + static const struct intel_ddi_buf_trans xe3plpd_lt_trans_dp14 = { 1167 + .entries = _xe3plpd_lt_trans_dp14, 1168 + .num_entries = ARRAY_SIZE(_xe3plpd_lt_trans_dp14), 1169 + }; 1170 + 1171 + static const struct intel_ddi_buf_trans xe3plpd_lt_trans_uhbr = { 1172 + .entries = _xe3plpd_lt_trans_uhbr, 1173 + .num_entries = ARRAY_SIZE(_xe3plpd_lt_trans_uhbr), 1174 + }; 1175 + 1176 + static const struct intel_ddi_buf_trans xe3plpd_lt_trans_edp = { 1177 + .entries = _xe3plpd_lt_trans_edp, 1178 + .num_entries = ARRAY_SIZE(_xe3plpd_lt_trans_edp), 1179 + }; 1180 + 1119 1181 bool is_hobl_buf_trans(const struct intel_ddi_buf_trans *table) 1120 1182 { 1121 1183 return table == &tgl_combo_phy_trans_edp_hbr2_hobl; ··· 1771 1707 return intel_get_buf_trans(&mtl_c20_trans_dp14, n_entries); 1772 1708 } 1773 1709 1710 + static const struct intel_ddi_buf_trans * 1711 + xe3plpd_get_lt_buf_trans(struct intel_encoder *encoder, 1712 + const struct intel_crtc_state *crtc_state, 1713 + int *n_entries) 1714 + { 1715 + if (intel_crtc_has_dp_encoder(crtc_state) && intel_dp_is_uhbr(crtc_state)) 1716 + return intel_get_buf_trans(&xe3plpd_lt_trans_uhbr, n_entries); 1717 + else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP)) 1718 + return intel_get_buf_trans(&xe3plpd_lt_trans_edp, n_entries); 1719 + else 1720 + return intel_get_buf_trans(&xe3plpd_lt_trans_dp14, n_entries); 1721 + } 1722 + 1774 1723 void intel_ddi_buf_trans_init(struct intel_encoder *encoder) 1775 1724 { 1776 1725 struct intel_display *display = to_intel_display(encoder); 1777 1726 1778 - if (DISPLAY_VER(display) >= 14) { 1727 + if (HAS_LT_PHY(display)) { 1728 + encoder->get_buf_trans = xe3plpd_get_lt_buf_trans; 1729 + } else if (DISPLAY_VER(display) >= 14) { 1779 1730 if (intel_encoder_is_c10phy(encoder)) 1780 1731 encoder->get_buf_trans = mtl_get_c10_buf_trans; 1781 1732 else
+9
drivers/gpu/drm/i915/display/intel_ddi_buf_trans.h
··· 50 50 u8 post_cursor; 51 51 }; 52 52 53 + struct xe3plpd_lt_phy_buf_trans { 54 + u8 txswing; 55 + u8 txswing_level; 56 + u8 pre_cursor; 57 + u8 main_cursor; 58 + u8 post_cursor; 59 + }; 60 + 53 61 union intel_ddi_buf_trans_entry { 54 62 struct hsw_ddi_buf_trans hsw; 55 63 struct bxt_ddi_buf_trans bxt; ··· 65 57 struct icl_mg_phy_ddi_buf_trans mg; 66 58 struct tgl_dkl_phy_ddi_buf_trans dkl; 67 59 struct dg2_snps_phy_buf_trans snps; 60 + struct xe3plpd_lt_phy_buf_trans lt; 68 61 }; 69 62 70 63 struct intel_ddi_buf_trans {
+188 -131
drivers/gpu/drm/i915/display/intel_display.c
··· 51 51 #include "i915_config.h" 52 52 #include "i915_drv.h" 53 53 #include "i915_reg.h" 54 - #include "i915_utils.h" 55 54 #include "i9xx_plane.h" 56 55 #include "i9xx_plane_regs.h" 57 56 #include "i9xx_wm.h" ··· 59 60 #include "intel_audio.h" 60 61 #include "intel_bo.h" 61 62 #include "intel_bw.h" 63 + #include "intel_casf.h" 62 64 #include "intel_cdclk.h" 63 65 #include "intel_clock_gating.h" 64 66 #include "intel_color.h" ··· 76 76 #include "intel_display_regs.h" 77 77 #include "intel_display_rpm.h" 78 78 #include "intel_display_types.h" 79 + #include "intel_display_utils.h" 79 80 #include "intel_display_wa.h" 80 81 #include "intel_dmc.h" 81 82 #include "intel_dp.h" ··· 100 99 #include "intel_hdmi.h" 101 100 #include "intel_hotplug.h" 102 101 #include "intel_link_bw.h" 102 + #include "intel_lt_phy.h" 103 103 #include "intel_lvds.h" 104 104 #include "intel_lvds_regs.h" 105 105 #include "intel_modeset_setup.h" ··· 131 129 #include "skl_scaler.h" 132 130 #include "skl_universal_plane.h" 133 131 #include "skl_watermark.h" 134 - #include "vlv_dpio_phy_regs.h" 135 132 #include "vlv_dsi.h" 136 133 #include "vlv_dsi_pll.h" 137 134 #include "vlv_dsi_regs.h" 138 - #include "vlv_sideband.h" 139 135 140 136 static void intel_set_transcoder_timings(const struct intel_crtc_state *crtc_state); 141 137 static void intel_set_pipe_src_size(const struct intel_crtc_state *crtc_state); 142 138 static void hsw_set_transconf(const struct intel_crtc_state *crtc_state); 143 139 static void bdw_set_pipe_misc(struct intel_dsb *dsb, 144 140 const struct intel_crtc_state *crtc_state); 145 - 146 - /* returns HPLL frequency in kHz */ 147 - int vlv_get_hpll_vco(struct drm_device *drm) 148 - { 149 - int hpll_freq, vco_freq[] = { 800, 1600, 2000, 2400 }; 150 - 151 - /* Obtain SKU information */ 152 - hpll_freq = vlv_cck_read(drm, CCK_FUSE_REG) & 153 - CCK_FUSE_HPLL_FREQ_MASK; 154 - 155 - return vco_freq[hpll_freq] * 1000; 156 - } 157 - 158 - int vlv_get_cck_clock(struct drm_device *drm, 159 - const char *name, u32 reg, int ref_freq) 160 - { 161 - u32 val; 162 - int divider; 163 - 164 - val = vlv_cck_read(drm, reg); 165 - divider = val & CCK_FREQUENCY_VALUES; 166 - 167 - drm_WARN(drm, (val & CCK_FREQUENCY_STATUS) != 168 - (divider << CCK_FREQUENCY_STATUS_SHIFT), 169 - "%s change in progress\n", name); 170 - 171 - return DIV_ROUND_CLOSEST(ref_freq << 1, divider + 1); 172 - } 173 - 174 - int vlv_get_cck_clock_hpll(struct drm_device *drm, 175 - const char *name, u32 reg) 176 - { 177 - struct drm_i915_private *dev_priv = to_i915(drm); 178 - int hpll; 179 - 180 - vlv_cck_get(drm); 181 - 182 - if (dev_priv->hpll_freq == 0) 183 - dev_priv->hpll_freq = vlv_get_hpll_vco(drm); 184 - 185 - hpll = vlv_get_cck_clock(drm, name, reg, dev_priv->hpll_freq); 186 - 187 - vlv_cck_put(drm); 188 - 189 - return hpll; 190 - } 191 - 192 - void intel_update_czclk(struct intel_display *display) 193 - { 194 - struct drm_i915_private *dev_priv = to_i915(display->drm); 195 - 196 - if (!display->platform.valleyview && !display->platform.cherryview) 197 - return; 198 - 199 - dev_priv->czclk_freq = vlv_get_cck_clock_hpll(display->drm, "czclk", 200 - CCK_CZ_CLOCK_CONTROL); 201 - 202 - drm_dbg_kms(display->drm, "CZ clock rate: %d kHz\n", dev_priv->czclk_freq); 203 - } 204 141 205 142 static bool is_hdr_mode(const struct intel_crtc_state *crtc_state) 206 143 { ··· 832 891 static bool needs_async_flip_vtd_wa(const struct intel_crtc_state *crtc_state) 833 892 { 834 893 struct intel_display *display = to_intel_display(crtc_state); 835 - struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); 836 894 837 - return crtc_state->uapi.async_flip && i915_vtd_active(i915) && 895 + return crtc_state->uapi.async_flip && intel_display_vtd_active(display) && 838 896 (DISPLAY_VER(display) == 9 || display->platform.broadwell || 839 897 display->platform.haswell); 840 898 } ··· 978 1038 return is_disabling(has_audio, old_crtc_state, new_crtc_state) || 979 1039 (old_crtc_state->has_audio && 980 1040 memcmp(old_crtc_state->eld, new_crtc_state->eld, MAX_ELD_BYTES) != 0); 1041 + } 1042 + 1043 + static bool intel_casf_enabling(const struct intel_crtc_state *new_crtc_state, 1044 + const struct intel_crtc_state *old_crtc_state) 1045 + { 1046 + if (!new_crtc_state->hw.active) 1047 + return false; 1048 + 1049 + return is_enabling(hw.casf_params.casf_enable, old_crtc_state, new_crtc_state); 1050 + } 1051 + 1052 + static bool intel_casf_disabling(const struct intel_crtc_state *old_crtc_state, 1053 + const struct intel_crtc_state *new_crtc_state) 1054 + { 1055 + if (!new_crtc_state->hw.active) 1056 + return false; 1057 + 1058 + return is_disabling(hw.casf_params.casf_enable, old_crtc_state, new_crtc_state); 981 1059 } 982 1060 983 1061 #undef is_disabling ··· 1152 1194 1153 1195 if (audio_disabling(old_crtc_state, new_crtc_state)) 1154 1196 intel_encoders_audio_disable(state, crtc); 1197 + 1198 + if (intel_casf_disabling(old_crtc_state, new_crtc_state)) 1199 + intel_casf_disable(new_crtc_state); 1155 1200 1156 1201 intel_drrs_deactivate(old_crtc_state); 1157 1202 ··· 1603 1642 } 1604 1643 1605 1644 intel_set_transcoder_timings(crtc_state); 1606 - if (HAS_VRR(display)) 1607 - intel_vrr_set_transcoder_timings(crtc_state); 1645 + intel_vrr_set_transcoder_timings(crtc_state); 1608 1646 1609 1647 if (cpu_transcoder != TRANSCODER_EDP) 1610 1648 intel_de_write(display, TRANS_MULT(display, cpu_transcoder), ··· 2382 2422 return 0; 2383 2423 } 2384 2424 2385 - static int intel_crtc_vblank_delay(const struct intel_crtc_state *crtc_state) 2425 + static int intel_crtc_set_context_latency(struct intel_crtc_state *crtc_state) 2386 2426 { 2387 2427 struct intel_display *display = to_intel_display(crtc_state); 2388 - int vblank_delay = 0; 2428 + int set_context_latency = 0; 2389 2429 2390 2430 if (!HAS_DSB(display)) 2391 2431 return 0; 2392 2432 2393 - vblank_delay = max(vblank_delay, intel_psr_min_vblank_delay(crtc_state)); 2433 + set_context_latency = max(set_context_latency, 2434 + intel_psr_min_set_context_latency(crtc_state)); 2394 2435 2395 - return vblank_delay; 2436 + return set_context_latency; 2396 2437 } 2397 2438 2398 - static int intel_crtc_compute_vblank_delay(struct intel_atomic_state *state, 2399 - struct intel_crtc *crtc) 2439 + static int intel_crtc_compute_set_context_latency(struct intel_atomic_state *state, 2440 + struct intel_crtc *crtc) 2400 2441 { 2401 2442 struct intel_display *display = to_intel_display(state); 2402 2443 struct intel_crtc_state *crtc_state = 2403 2444 intel_atomic_get_new_crtc_state(state, crtc); 2404 2445 struct drm_display_mode *adjusted_mode = 2405 2446 &crtc_state->hw.adjusted_mode; 2406 - int vblank_delay, max_vblank_delay; 2447 + int set_context_latency, max_vblank_delay; 2407 2448 2408 - vblank_delay = intel_crtc_vblank_delay(crtc_state); 2449 + set_context_latency = intel_crtc_set_context_latency(crtc_state); 2450 + 2409 2451 max_vblank_delay = adjusted_mode->crtc_vblank_end - adjusted_mode->crtc_vblank_start - 1; 2410 2452 2411 - if (vblank_delay > max_vblank_delay) { 2412 - drm_dbg_kms(display->drm, "[CRTC:%d:%s] vblank delay (%d) exceeds max (%d)\n", 2413 - crtc->base.base.id, crtc->base.name, vblank_delay, max_vblank_delay); 2453 + if (set_context_latency > max_vblank_delay) { 2454 + drm_dbg_kms(display->drm, "[CRTC:%d:%s] set context latency (%d) exceeds max (%d)\n", 2455 + crtc->base.base.id, crtc->base.name, 2456 + set_context_latency, 2457 + max_vblank_delay); 2414 2458 return -EINVAL; 2415 2459 } 2416 2460 2417 - adjusted_mode->crtc_vblank_start += vblank_delay; 2461 + crtc_state->set_context_latency = set_context_latency; 2462 + adjusted_mode->crtc_vblank_start += set_context_latency; 2418 2463 2419 2464 return 0; 2420 2465 } ··· 2431 2466 intel_atomic_get_new_crtc_state(state, crtc); 2432 2467 int ret; 2433 2468 2434 - ret = intel_crtc_compute_vblank_delay(state, crtc); 2469 + ret = intel_dpll_crtc_compute_clock(state, crtc); 2435 2470 if (ret) 2436 2471 return ret; 2437 2472 2438 - ret = intel_dpll_crtc_compute_clock(state, crtc); 2473 + ret = intel_crtc_compute_set_context_latency(state, crtc); 2439 2474 if (ret) 2440 2475 return ret; 2441 2476 ··· 2451 2486 2452 2487 if (crtc_state->has_pch_encoder) 2453 2488 return ilk_fdi_compute_config(crtc, crtc_state); 2489 + 2490 + intel_vrr_compute_guardband(crtc_state); 2454 2491 2455 2492 return 0; 2456 2493 } ··· 2645 2678 if (DISPLAY_VER(display) >= 13) { 2646 2679 intel_de_write(display, 2647 2680 TRANS_SET_CONTEXT_LATENCY(display, cpu_transcoder), 2648 - crtc_vblank_start - crtc_vdisplay); 2681 + crtc_state->set_context_latency); 2649 2682 2650 2683 /* 2651 2684 * VBLANK_START not used by hw, just clear it 2652 2685 * to make it stand out in register dumps. 2653 2686 */ 2654 2687 crtc_vblank_start = 1; 2688 + } else if (DISPLAY_VER(display) == 12) { 2689 + /* VBLANK_START - VACTIVE defines SCL on TGL */ 2690 + crtc_vblank_start = crtc_vdisplay + crtc_state->set_context_latency; 2655 2691 } 2656 2692 2657 2693 if (DISPLAY_VER(display) >= 4) ··· 2738 2768 if (DISPLAY_VER(display) >= 13) { 2739 2769 intel_de_write(display, 2740 2770 TRANS_SET_CONTEXT_LATENCY(display, cpu_transcoder), 2741 - crtc_vblank_start - crtc_vdisplay); 2771 + crtc_state->set_context_latency); 2742 2772 2743 2773 /* 2744 2774 * VBLANK_START not used by hw, just clear it 2745 2775 * to make it stand out in register dumps. 2746 2776 */ 2747 2777 crtc_vblank_start = 1; 2778 + } else if (DISPLAY_VER(display) == 12) { 2779 + /* VBLANK_START - VACTIVE defines SCL on TGL */ 2780 + crtc_vblank_start = crtc_vdisplay + crtc_state->set_context_latency; 2748 2781 } 2749 2782 2750 2783 /* ··· 2854 2881 adjusted_mode->crtc_vblank_end += 1; 2855 2882 } 2856 2883 2857 - if (DISPLAY_VER(display) >= 13 && !transcoder_is_dsi(cpu_transcoder)) 2858 - adjusted_mode->crtc_vblank_start = 2859 - adjusted_mode->crtc_vdisplay + 2884 + if (DISPLAY_VER(display) >= 13 && !transcoder_is_dsi(cpu_transcoder)) { 2885 + pipe_config->set_context_latency = 2860 2886 intel_de_read(display, 2861 2887 TRANS_SET_CONTEXT_LATENCY(display, cpu_transcoder)); 2888 + adjusted_mode->crtc_vblank_start = 2889 + adjusted_mode->crtc_vdisplay + 2890 + pipe_config->set_context_latency; 2891 + } else if (DISPLAY_VER(display) == 12) { 2892 + /* 2893 + * TGL doesn't have a dedicated register for SCL. 2894 + * Instead, the hardware derives SCL from the difference between 2895 + * TRANS_VBLANK.vblank_start and TRANS_VTOTAL.vactive. 2896 + * To reflect the HW behaviour, readout the value for SCL as 2897 + * Vblank start - Vactive. 2898 + */ 2899 + pipe_config->set_context_latency = 2900 + adjusted_mode->crtc_vblank_start - adjusted_mode->crtc_vdisplay; 2901 + } 2862 2902 2863 2903 if (DISPLAY_VER(display) >= 30) 2864 2904 pipe_config->min_hblank = intel_de_read(display, ··· 3938 3952 intel_joiner_get_config(pipe_config); 3939 3953 intel_dsc_get_config(pipe_config); 3940 3954 3955 + /* intel_vrr_get_config() depends on .framestart_delay */ 3956 + if (!transcoder_is_dsi(pipe_config->cpu_transcoder)) { 3957 + tmp = intel_de_read(display, CHICKEN_TRANS(display, pipe_config->cpu_transcoder)); 3958 + 3959 + pipe_config->framestart_delay = REG_FIELD_GET(HSW_FRAME_START_DELAY_MASK, tmp) + 1; 3960 + } else { 3961 + /* no idea if this is correct */ 3962 + pipe_config->framestart_delay = 1; 3963 + } 3964 + 3965 + /* 3966 + * intel_vrr_get_config() depends on TRANS_SET_CONTEXT_LATENCY 3967 + * readout done by intel_get_transcoder_timings(). 3968 + */ 3941 3969 if (!transcoder_is_dsi(pipe_config->cpu_transcoder) || 3942 3970 DISPLAY_VER(display) >= 11) 3943 3971 intel_get_transcoder_timings(crtc, pipe_config); ··· 4001 4001 TRANS_MULT(display, pipe_config->cpu_transcoder)) + 1; 4002 4002 } else { 4003 4003 pipe_config->pixel_multiplier = 1; 4004 - } 4005 - 4006 - if (!transcoder_is_dsi(pipe_config->cpu_transcoder)) { 4007 - tmp = intel_de_read(display, CHICKEN_TRANS(display, pipe_config->cpu_transcoder)); 4008 - 4009 - pipe_config->framestart_delay = REG_FIELD_GET(HSW_FRAME_START_DELAY_MASK, tmp) + 1; 4010 - } else { 4011 - /* no idea if this is correct */ 4012 - pipe_config->framestart_delay = 1; 4013 4004 } 4014 4005 4015 4006 out: ··· 4249 4258 return ret; 4250 4259 } 4251 4260 4261 + ret = intel_casf_compute_config(crtc_state); 4262 + if (ret) 4263 + return ret; 4264 + 4252 4265 if (DISPLAY_VER(display) >= 9) { 4253 4266 if (intel_crtc_needs_modeset(crtc_state) || 4254 - intel_crtc_needs_fastset(crtc_state)) { 4267 + intel_crtc_needs_fastset(crtc_state) || 4268 + intel_casf_needs_scaler(crtc_state)) { 4255 4269 ret = skl_update_scaler_crtc(crtc_state); 4256 4270 if (ret) 4257 4271 return ret; ··· 4635 4639 if (ret) 4636 4640 return ret; 4637 4641 4638 - crtc_state->fec_enable = limits->force_fec_pipes & BIT(crtc->pipe); 4642 + crtc_state->dsc.compression_enabled_on_link = limits->link_dsc_pipes & BIT(crtc->pipe); 4639 4643 crtc_state->max_link_bpp_x16 = limits->max_bpp_x16[crtc->pipe]; 4640 4644 4641 4645 if (crtc_state->pipe_bpp > fxp_q4_to_int(crtc_state->max_link_bpp_x16)) { ··· 4755 4759 struct drm_connector_state *conn_state; 4756 4760 struct drm_connector *connector; 4757 4761 int i; 4758 - 4759 - intel_vrr_compute_config_late(crtc_state); 4760 4762 4761 4763 for_each_new_connector_in_state(&state->base, connector, 4762 4764 conn_state, i) { ··· 4990 4996 * Allow fastboot to fix up vblank delay (handled via LRR 4991 4997 * codepaths), a bit dodgy as the registers aren't 4992 4998 * double buffered but seems to be working more or less... 4999 + * 5000 + * Also allow this when the VRR timing generator is always on, 5001 + * and optimized guardband is used. In such cases, 5002 + * vblank delay may vary even without inherited state, but it's 5003 + * still safe as VRR guardband is still same. 4993 5004 */ 4994 - return HAS_LRR(display) && old_crtc_state->inherited && 4995 - !intel_crtc_has_type(old_crtc_state, INTEL_OUTPUT_DSI); 5005 + return HAS_LRR(display) && 5006 + (old_crtc_state->inherited || intel_vrr_always_use_vrr_tg(display)) && 5007 + !intel_crtc_has_type(old_crtc_state, INTEL_OUTPUT_DSI); 5008 + } 5009 + 5010 + static void 5011 + pipe_config_lt_phy_pll_mismatch(struct drm_printer *p, bool fastset, 5012 + const struct intel_crtc *crtc, 5013 + const char *name, 5014 + const struct intel_lt_phy_pll_state *a, 5015 + const struct intel_lt_phy_pll_state *b) 5016 + { 5017 + struct intel_display *display = to_intel_display(crtc); 5018 + char *chipname = "LTPHY"; 5019 + 5020 + pipe_config_mismatch(p, fastset, crtc, name, chipname); 5021 + 5022 + drm_printf(p, "expected:\n"); 5023 + intel_lt_phy_dump_hw_state(display, a); 5024 + drm_printf(p, "found:\n"); 5025 + intel_lt_phy_dump_hw_state(display, b); 4996 5026 } 4997 5027 4998 5028 bool ··· 5139 5121 pipe_config_cx0pll_mismatch(&p, fastset, crtc, __stringify(name), \ 5140 5122 &current_config->name, \ 5141 5123 &pipe_config->name); \ 5124 + ret = false; \ 5125 + } \ 5126 + } while (0) 5127 + 5128 + #define PIPE_CONF_CHECK_PLL_LT(name) do { \ 5129 + if (!intel_lt_phy_pll_compare_hw_state(&current_config->name, \ 5130 + &pipe_config->name)) { \ 5131 + pipe_config_lt_phy_pll_mismatch(&p, fastset, crtc, __stringify(name), \ 5132 + &current_config->name, \ 5133 + &pipe_config->name); \ 5142 5134 ret = false; \ 5143 5135 } \ 5144 5136 } while (0) ··· 5347 5319 5348 5320 PIPE_CONF_CHECK_I(scaler_state.scaler_id); 5349 5321 PIPE_CONF_CHECK_I(pixel_rate); 5322 + PIPE_CONF_CHECK_BOOL(hw.casf_params.casf_enable); 5323 + PIPE_CONF_CHECK_I(hw.casf_params.win_size); 5324 + PIPE_CONF_CHECK_I(hw.casf_params.strength); 5350 5325 5351 5326 PIPE_CONF_CHECK_X(gamma_mode); 5352 5327 if (display->platform.cherryview) ··· 5380 5349 PIPE_CONF_CHECK_PLL(dpll_hw_state); 5381 5350 5382 5351 /* FIXME convert MTL+ platforms over to dpll_mgr */ 5383 - if (DISPLAY_VER(display) >= 14) 5352 + if (HAS_LT_PHY(display)) 5353 + PIPE_CONF_CHECK_PLL_LT(dpll_hw_state.ltpll); 5354 + else if (DISPLAY_VER(display) >= 14) 5384 5355 PIPE_CONF_CHECK_PLL_CX0(dpll_hw_state.cx0pll); 5385 5356 5386 5357 PIPE_CONF_CHECK_X(dsi_pll.ctrl); ··· 5475 5442 PIPE_CONF_CHECK_I(vrr.pipeline_full); 5476 5443 PIPE_CONF_CHECK_I(vrr.guardband); 5477 5444 } 5445 + 5446 + PIPE_CONF_CHECK_I(set_context_latency); 5478 5447 5479 5448 #undef PIPE_CONF_CHECK_X 5480 5449 #undef PIPE_CONF_CHECK_I ··· 5724 5689 return 0; 5725 5690 } 5726 5691 5692 + u8 intel_calc_enabled_pipes(struct intel_atomic_state *state, 5693 + u8 enabled_pipes) 5694 + { 5695 + const struct intel_crtc_state *crtc_state; 5696 + struct intel_crtc *crtc; 5697 + int i; 5698 + 5699 + for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) { 5700 + if (crtc_state->hw.enable) 5701 + enabled_pipes |= BIT(crtc->pipe); 5702 + else 5703 + enabled_pipes &= ~BIT(crtc->pipe); 5704 + } 5705 + 5706 + return enabled_pipes; 5707 + } 5708 + 5727 5709 u8 intel_calc_active_pipes(struct intel_atomic_state *state, 5728 5710 u8 active_pipes) 5729 5711 { ··· 5770 5718 return 0; 5771 5719 } 5772 5720 5773 - static bool lrr_params_changed(const struct drm_display_mode *old_adjusted_mode, 5774 - const struct drm_display_mode *new_adjusted_mode) 5721 + static bool lrr_params_changed(const struct intel_crtc_state *old_crtc_state, 5722 + const struct intel_crtc_state *new_crtc_state) 5775 5723 { 5724 + const struct drm_display_mode *old_adjusted_mode = &old_crtc_state->hw.adjusted_mode; 5725 + const struct drm_display_mode *new_adjusted_mode = &new_crtc_state->hw.adjusted_mode; 5726 + 5776 5727 return old_adjusted_mode->crtc_vblank_start != new_adjusted_mode->crtc_vblank_start || 5777 5728 old_adjusted_mode->crtc_vblank_end != new_adjusted_mode->crtc_vblank_end || 5778 - old_adjusted_mode->crtc_vtotal != new_adjusted_mode->crtc_vtotal; 5729 + old_adjusted_mode->crtc_vtotal != new_adjusted_mode->crtc_vtotal || 5730 + old_crtc_state->set_context_latency != new_crtc_state->set_context_latency; 5779 5731 } 5780 5732 5781 5733 static void intel_crtc_check_fastset(const struct intel_crtc_state *old_crtc_state, ··· 5805 5749 &new_crtc_state->dp_m_n)) 5806 5750 new_crtc_state->update_m_n = false; 5807 5751 5808 - if (!lrr_params_changed(&old_crtc_state->hw.adjusted_mode, 5809 - &new_crtc_state->hw.adjusted_mode)) 5752 + if (!lrr_params_changed(old_crtc_state, new_crtc_state)) 5810 5753 new_crtc_state->update_lrr = false; 5811 5754 5812 5755 if (intel_crtc_needs_modeset(new_crtc_state)) ··· 6397 6342 struct intel_crtc_state *old_crtc_state, *new_crtc_state; 6398 6343 struct intel_crtc *crtc; 6399 6344 int ret, i; 6400 - bool any_ms = false; 6401 6345 6402 6346 if (!intel_display_driver_check_access(display)) 6403 6347 return -ENODEV; ··· 6504 6450 if (!intel_crtc_needs_modeset(new_crtc_state)) 6505 6451 continue; 6506 6452 6507 - any_ms = true; 6508 - 6509 6453 intel_dpll_release(state, crtc); 6510 6454 } 6511 6455 6512 - if (any_ms && !check_digital_port_conflicts(state)) { 6513 - drm_dbg_kms(display->drm, 6514 - "rejecting conflicting digital port configuration\n"); 6456 + if (intel_any_crtc_needs_modeset(state) && !check_digital_port_conflicts(state)) { 6457 + drm_dbg_kms(display->drm, "rejecting conflicting digital port configuration\n"); 6515 6458 ret = -EINVAL; 6516 6459 goto fail; 6517 6460 } ··· 6517 6466 if (ret) 6518 6467 goto fail; 6519 6468 6469 + for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) 6470 + new_crtc_state->min_cdclk = intel_crtc_min_cdclk(new_crtc_state); 6471 + 6520 6472 ret = intel_compute_global_watermarks(state); 6521 6473 if (ret) 6522 6474 goto fail; 6523 6475 6524 - ret = intel_bw_atomic_check(state, any_ms); 6476 + ret = intel_bw_atomic_check(state); 6525 6477 if (ret) 6526 6478 goto fail; 6527 6479 6528 - ret = intel_cdclk_atomic_check(state, &any_ms); 6480 + ret = intel_cdclk_atomic_check(state); 6529 6481 if (ret) 6530 6482 goto fail; 6531 6483 6532 - if (intel_any_crtc_needs_modeset(state)) 6533 - any_ms = true; 6534 - 6535 - if (any_ms) { 6484 + if (intel_any_crtc_needs_modeset(state)) { 6536 6485 ret = intel_modeset_checks(state); 6537 6486 if (ret) 6538 6487 goto fail; 6539 - 6540 - ret = intel_modeset_calc_cdclk(state); 6541 - if (ret) 6542 - return ret; 6543 6488 } 6544 6489 6545 6490 ret = intel_pmdemand_atomic_check(state); ··· 6785 6738 cmrr_params_changed(old_crtc_state, new_crtc_state)) 6786 6739 intel_vrr_set_transcoder_timings(new_crtc_state); 6787 6740 } 6741 + 6742 + if (intel_casf_enabling(new_crtc_state, old_crtc_state)) 6743 + intel_casf_enable(new_crtc_state); 6744 + else if (new_crtc_state->hw.casf_params.strength != old_crtc_state->hw.casf_params.strength) 6745 + intel_casf_update_strength(new_crtc_state); 6788 6746 6789 6747 intel_fbc_update(state, crtc); 6790 6748 ··· 7359 7307 intel_dsb_wait_vblanks(new_crtc_state->dsb_commit, 1); 7360 7308 7361 7309 intel_vrr_send_push(new_crtc_state->dsb_commit, new_crtc_state); 7362 - intel_dsb_wait_vblank_delay(state, new_crtc_state->dsb_commit); 7310 + intel_dsb_wait_for_delayed_vblank(state, new_crtc_state->dsb_commit); 7363 7311 intel_vrr_check_push_sent(new_crtc_state->dsb_commit, 7364 7312 new_crtc_state); 7365 7313 intel_dsb_interrupt(new_crtc_state->dsb_commit); ··· 7449 7397 */ 7450 7398 intel_pmdemand_pre_plane_update(state); 7451 7399 7452 - if (state->modeset) { 7400 + if (state->modeset) 7453 7401 drm_atomic_helper_update_legacy_modeset_state(display->drm, &state->base); 7454 7402 7455 - intel_set_cdclk_pre_plane_update(state); 7403 + intel_set_cdclk_pre_plane_update(state); 7456 7404 7405 + if (state->modeset) 7457 7406 intel_modeset_verify_disabled(state); 7458 - } 7459 7407 7460 7408 intel_sagv_pre_plane_update(state); 7461 7409 ··· 7568 7516 intel_verify_planes(state); 7569 7517 7570 7518 intel_sagv_post_plane_update(state); 7571 - if (state->modeset) 7572 - intel_set_cdclk_post_plane_update(state); 7519 + intel_set_cdclk_post_plane_update(state); 7573 7520 intel_pmdemand_post_plane_update(state); 7574 7521 7575 7522 drm_atomic_helper_commit_hw_done(&state->base); ··· 8054 8003 mode->vtotal > vtotal_max) 8055 8004 return MODE_V_ILLEGAL; 8056 8005 8006 + /* 8007 + * WM_LINETIME only goes up to (almost) 64 usec, and also 8008 + * knowing that the linetime is always bounded will ease the 8009 + * mind during various calculations. 8010 + */ 8011 + if (DIV_ROUND_UP(mode->htotal * 1000, mode->clock) > 64) 8012 + return MODE_H_ILLEGAL; 8013 + 8057 8014 return MODE_OK; 8058 8015 } 8059 8016 ··· 8386 8327 8387 8328 bool intel_scanout_needs_vtd_wa(struct intel_display *display) 8388 8329 { 8389 - struct drm_i915_private *i915 = to_i915(display->drm); 8390 - 8391 - return IS_DISPLAY_VER(display, 6, 11) && i915_vtd_active(i915); 8330 + return IS_DISPLAY_VER(display, 6, 11) && intel_display_vtd_active(display); 8392 8331 }
+2 -6
drivers/gpu/drm/i915/display/intel_display.h
··· 394 394 i) 395 395 396 396 int intel_atomic_check(struct drm_device *dev, struct drm_atomic_state *state); 397 + u8 intel_calc_enabled_pipes(struct intel_atomic_state *state, 398 + u8 enabled_pipes); 397 399 u8 intel_calc_active_pipes(struct intel_atomic_state *state, 398 400 u8 active_pipes); 399 401 void intel_link_compute_m_n(u16 bpp, int nlanes, ··· 437 435 void intel_disable_transcoder(const struct intel_crtc_state *old_crtc_state); 438 436 void i830_enable_pipe(struct intel_display *display, enum pipe pipe); 439 437 void i830_disable_pipe(struct intel_display *display, enum pipe pipe); 440 - int vlv_get_hpll_vco(struct drm_device *drm); 441 - int vlv_get_cck_clock(struct drm_device *drm, 442 - const char *name, u32 reg, int ref_freq); 443 - int vlv_get_cck_clock_hpll(struct drm_device *drm, 444 - const char *name, u32 reg); 445 438 bool intel_has_pending_fb_unpin(struct intel_display *display); 446 439 void intel_encoder_destroy(struct drm_encoder *encoder); 447 440 struct drm_display_mode * ··· 525 528 void intel_setup_outputs(struct intel_display *display); 526 529 int intel_initial_commit(struct intel_display *display); 527 530 void intel_panel_sanitize_ssc(struct intel_display *display); 528 - void intel_update_czclk(struct intel_display *display); 529 531 enum drm_mode_status intel_mode_valid(struct drm_device *dev, 530 532 const struct drm_display_mode *mode); 531 533 int intel_atomic_commit(struct drm_device *dev, struct drm_atomic_state *_state,
+13 -7
drivers/gpu/drm/i915/display/intel_display_conversion.c
··· 1 1 // SPDX-License-Identifier: MIT 2 2 /* Copyright © 2024 Intel Corporation */ 3 3 4 - #include "i915_drv.h" 5 - #include "intel_display_conversion.h" 4 + #include <drm/intel/display_member.h> 6 5 7 - static struct intel_display *__i915_to_display(struct drm_i915_private *i915) 8 - { 9 - return i915->display; 10 - } 6 + #include "intel_display_conversion.h" 11 7 12 8 struct intel_display *__drm_to_display(struct drm_device *drm) 13 9 { 14 - return __i915_to_display(to_i915(drm)); 10 + /* 11 + * Note: This relies on both struct drm_i915_private and struct 12 + * xe_device having the struct drm_device and struct intel_display * 13 + * members at the same relative offsets, as defined by struct 14 + * __intel_generic_device. 15 + * 16 + * See also INTEL_DISPLAY_MEMBER_STATIC_ASSERT(). 17 + */ 18 + struct __intel_generic_device *d = container_of(drm, struct __intel_generic_device, drm); 19 + 20 + return d->display; 15 21 }
+28 -1
drivers/gpu/drm/i915/display/intel_display_core.h
··· 41 41 struct intel_color_funcs; 42 42 struct intel_crtc; 43 43 struct intel_crtc_state; 44 + struct intel_display_parent_interface; 44 45 struct intel_dmc; 45 46 struct intel_dpll_global_funcs; 46 47 struct intel_dpll_mgr; ··· 292 291 /* Intel PCH: where the south display engine lives */ 293 292 enum intel_pch pch_type; 294 293 294 + /* Parent, or core, driver functions exposed to display */ 295 + const struct intel_display_parent_interface *parent; 296 + 295 297 /* Display functions */ 296 298 struct { 297 299 /* Top level crtc-ish functions */ ··· 372 368 373 369 struct intel_global_obj obj; 374 370 } dbuf; 371 + 372 + struct { 373 + struct intel_global_obj obj; 374 + } dbuf_bw; 375 375 376 376 struct { 377 377 /* ··· 483 475 484 476 struct work_struct vblank_notify_work; 485 477 486 - u32 de_irq_mask[I915_MAX_PIPES]; 478 + /* 479 + * Cached value of VLV/CHV IMR to avoid reads in updating the 480 + * bitfield. 481 + */ 482 + u32 vlv_imr_mask; 483 + /* 484 + * Cached value of gen 5-7 DE IMR to avoid reads in updating the 485 + * bitfield. 486 + */ 487 + u32 ilk_de_imr_mask; 488 + /* 489 + * Cached value of BDW+ DE pipe IMR to avoid reads in updating 490 + * the bitfield. 491 + */ 492 + u32 de_pipe_imr_mask[I915_MAX_PIPES]; 487 493 u32 pipestat_irq_mask[I915_MAX_PIPES]; 488 494 } irq; 489 495 ··· 588 566 u32 chv_dpll_md[I915_MAX_PIPES]; 589 567 u32 bxt_phy_grc; 590 568 } state; 569 + 570 + struct { 571 + unsigned int hpll_freq; 572 + unsigned int czclk_freq; 573 + } vlv_clock; 591 574 592 575 struct { 593 576 /* ordered wq for modesets */
+8
drivers/gpu/drm/i915/display/intel_display_debugfs.c
··· 47 47 #include "intel_psr_regs.h" 48 48 #include "intel_vdsc.h" 49 49 #include "intel_wm.h" 50 + #include "intel_tc.h" 50 51 51 52 static struct intel_display *node_to_intel_display(struct drm_info_node *node) 52 53 { ··· 247 246 { 248 247 struct intel_connector *intel_connector = to_intel_connector(connector); 249 248 const struct drm_display_mode *mode; 249 + struct drm_printer p = drm_seq_file_printer(m); 250 + struct intel_digital_port *dig_port = NULL; 250 251 251 252 seq_printf(m, "[CONNECTOR:%d:%s]: status: %s\n", 252 253 connector->base.id, connector->name, ··· 271 268 intel_dp_mst_info(m, intel_connector); 272 269 else 273 270 intel_dp_info(m, intel_connector); 271 + dig_port = dp_to_dig_port(intel_attached_dp(intel_connector)); 274 272 break; 275 273 case DRM_MODE_CONNECTOR_HDMIA: 276 274 intel_hdmi_info(m, intel_connector); 275 + dig_port = hdmi_to_dig_port(intel_attached_hdmi(intel_connector)); 277 276 break; 278 277 default: 279 278 break; 280 279 } 280 + 281 + if (dig_port != NULL && intel_encoder_is_tc(&dig_port->base)) 282 + intel_tc_info(&p, dig_port); 281 283 282 284 intel_hdcp_info(m, intel_connector); 283 285
+17 -1
drivers/gpu/drm/i915/display/intel_display_device.c
··· 1404 1404 PLATFORM_GROUP(dgfx), 1405 1405 }; 1406 1406 1407 + static const u16 wcl_ids[] = { 1408 + INTEL_WCL_IDS(ID), 1409 + 0 1410 + }; 1411 + 1407 1412 static const struct platform_desc ptl_desc = { 1408 1413 PLATFORM(pantherlake), 1414 + .subplatforms = (const struct subplatform_desc[]) { 1415 + { 1416 + SUBPLATFORM(pantherlake, wildcatlake), 1417 + .pciidlist = wcl_ids, 1418 + }, 1419 + {}, 1420 + } 1409 1421 }; 1410 1422 1411 1423 __diag_pop(); ··· 1494 1482 INTEL_LNL_IDS(INTEL_DISPLAY_DEVICE, &lnl_desc), 1495 1483 INTEL_BMG_IDS(INTEL_DISPLAY_DEVICE, &bmg_desc), 1496 1484 INTEL_PTL_IDS(INTEL_DISPLAY_DEVICE, &ptl_desc), 1485 + INTEL_WCL_IDS(INTEL_DISPLAY_DEVICE, &ptl_desc), 1497 1486 }; 1498 1487 1499 1488 static const struct { ··· 1647 1634 bitmap_or(dst->bitmap, dst->bitmap, src->bitmap, display_platforms_num_bits()); 1648 1635 } 1649 1636 1650 - struct intel_display *intel_display_device_probe(struct pci_dev *pdev) 1637 + struct intel_display *intel_display_device_probe(struct pci_dev *pdev, 1638 + const struct intel_display_parent_interface *parent) 1651 1639 { 1652 1640 struct intel_display *display; 1653 1641 const struct intel_display_device_info *info; ··· 1663 1649 1664 1650 /* Add drm device backpointer as early as possible. */ 1665 1651 display->drm = pci_get_drvdata(pdev); 1652 + 1653 + display->parent = parent; 1666 1654 1667 1655 intel_display_params_copy(&display->params); 1668 1656
+10 -3
drivers/gpu/drm/i915/display/intel_display_device.h
··· 13 13 14 14 struct drm_printer; 15 15 struct intel_display; 16 + struct intel_display_parent_interface; 16 17 struct pci_dev; 17 18 18 19 /* ··· 102 101 /* Display ver 14.1 (based on GMD ID) */ \ 103 102 func(battlemage) \ 104 103 /* Display ver 30 (based on GMD ID) */ \ 105 - func(pantherlake) 104 + func(pantherlake) \ 105 + func(pantherlake_wildcatlake) 106 + 106 107 107 108 #define __MEMBER(name) unsigned long name:1; 108 109 #define __COUNT(x) 1 + ··· 143 140 func(overlay_needs_physical); \ 144 141 func(supports_tv); 145 142 143 + #define HAS_128B_Y_TILING(__display) (!(__display)->platform.i915g && !(__display)->platform.i915gm) 146 144 #define HAS_4TILE(__display) ((__display)->platform.dg2 || DISPLAY_VER(__display) >= 14) 147 145 #define HAS_ASYNC_FLIPS(__display) (DISPLAY_VER(__display) >= 5) 148 146 #define HAS_AS_SDP(__display) (DISPLAY_VER(__display) >= 13) 147 + #define HAS_AUX_CCS(__display) (IS_DISPLAY_VER(__display, 9, 12) || (__display)->platform.alderlake_p || (__display)->platform.meteorlake) 149 148 #define HAS_BIGJOINER(__display) (DISPLAY_VER(__display) >= 11 && HAS_DSC(__display)) 149 + #define HAS_CASF(__display) (DISPLAY_VER(__display) >= 20) 150 150 #define HAS_CDCLK_CRAWL(__display) (DISPLAY_INFO(__display)->has_cdclk_crawl) 151 151 #define HAS_CDCLK_SQUASH(__display) (DISPLAY_INFO(__display)->has_cdclk_squash) 152 152 #define HAS_CMRR(__display) (DISPLAY_VER(__display) >= 20) ··· 161 155 #define HAS_DISPLAY(__display) (DISPLAY_RUNTIME_INFO(__display)->pipe_mask != 0) 162 156 #define HAS_DMC(__display) (DISPLAY_RUNTIME_INFO(__display)->has_dmc) 163 157 #define HAS_DMC_WAKELOCK(__display) (DISPLAY_VER(__display) >= 20) 164 - #define HAS_DOUBLE_BUFFERED_M_N(__display) (DISPLAY_VER(__display) >= 9 || (__display)->platform.broadwell) 158 + #define HAS_DOUBLE_BUFFERED_M_N(__display) (IS_DISPLAY_VER((__display), 9, 14) || (__display)->platform.broadwell) 165 159 #define HAS_DOUBLE_BUFFERED_LUT(__display) (DISPLAY_VER(__display) >= 30) 166 160 #define HAS_DOUBLE_WIDE(__display) (DISPLAY_VER(__display) < 4) 167 161 #define HAS_DP20(__display) ((__display)->platform.dg2 || DISPLAY_VER(__display) >= 14) ··· 314 308 315 309 bool intel_display_device_present(struct intel_display *display); 316 310 bool intel_display_device_enabled(struct intel_display *display); 317 - struct intel_display *intel_display_device_probe(struct pci_dev *pdev); 311 + struct intel_display *intel_display_device_probe(struct pci_dev *pdev, 312 + const struct intel_display_parent_interface *parent); 318 313 void intel_display_device_remove(struct intel_display *display); 319 314 void intel_display_device_info_runtime_init(struct intel_display *display); 320 315
+7 -2
drivers/gpu/drm/i915/display/intel_display_driver.c
··· 18 18 #include <drm/drm_vblank.h> 19 19 20 20 #include "i915_drv.h" 21 - #include "i915_utils.h" 21 + #include "i915_utils.h" /* for i915_inject_probe_failure() */ 22 22 #include "i9xx_wm.h" 23 23 #include "intel_acpi.h" 24 24 #include "intel_atomic.h" ··· 28 28 #include "intel_cdclk.h" 29 29 #include "intel_color.h" 30 30 #include "intel_crtc.h" 31 + #include "intel_dbuf_bw.h" 31 32 #include "intel_display_core.h" 32 33 #include "intel_display_debugfs.h" 33 34 #include "intel_display_driver.h" 34 35 #include "intel_display_irq.h" 35 36 #include "intel_display_power.h" 36 37 #include "intel_display_types.h" 38 + #include "intel_display_utils.h" 37 39 #include "intel_display_wa.h" 38 40 #include "intel_dkl_phy.h" 39 41 #include "intel_dmc.h" ··· 287 285 if (ret) 288 286 goto cleanup_wq_unordered; 289 287 288 + ret = intel_dbuf_bw_init(display); 289 + if (ret) 290 + goto cleanup_wq_unordered; 291 + 290 292 ret = intel_bw_init(display); 291 293 if (ret) 292 294 goto cleanup_wq_unordered; ··· 488 482 intel_dpll_init(display); 489 483 intel_fdi_pll_freq_update(display); 490 484 491 - intel_update_czclk(display); 492 485 intel_display_driver_init_hw(display); 493 486 intel_dpll_update_ref_clks(display); 494 487
+102 -26
drivers/gpu/drm/i915/display/intel_display_irq.c
··· 140 140 lockdep_assert_held(&display->irq.lock); 141 141 drm_WARN_ON(display->drm, enabled_irq_mask & ~interrupt_mask); 142 142 143 - new_val = dev_priv->irq_mask; 143 + new_val = display->irq.ilk_de_imr_mask; 144 144 new_val &= ~interrupt_mask; 145 145 new_val |= (~enabled_irq_mask & interrupt_mask); 146 146 147 - if (new_val != dev_priv->irq_mask && 147 + if (new_val != display->irq.ilk_de_imr_mask && 148 148 !drm_WARN_ON(display->drm, !intel_irqs_enabled(dev_priv))) { 149 - dev_priv->irq_mask = new_val; 150 - intel_de_write(display, DEIMR, dev_priv->irq_mask); 149 + display->irq.ilk_de_imr_mask = new_val; 150 + intel_de_write(display, DEIMR, display->irq.ilk_de_imr_mask); 151 151 intel_de_posting_read(display, DEIMR); 152 152 } 153 153 } ··· 215 215 if (drm_WARN_ON(display->drm, !intel_irqs_enabled(dev_priv))) 216 216 return; 217 217 218 - new_val = display->irq.de_irq_mask[pipe]; 218 + new_val = display->irq.de_pipe_imr_mask[pipe]; 219 219 new_val &= ~interrupt_mask; 220 220 new_val |= (~enabled_irq_mask & interrupt_mask); 221 221 222 - if (new_val != display->irq.de_irq_mask[pipe]) { 223 - display->irq.de_irq_mask[pipe] = new_val; 224 - intel_de_write(display, GEN8_DE_PIPE_IMR(pipe), display->irq.de_irq_mask[pipe]); 222 + if (new_val != display->irq.de_pipe_imr_mask[pipe]) { 223 + display->irq.de_pipe_imr_mask[pipe] = new_val; 224 + intel_de_write(display, GEN8_DE_PIPE_IMR(pipe), display->irq.de_pipe_imr_mask[pipe]); 225 225 intel_de_posting_read(display, GEN8_DE_PIPE_IMR(pipe)); 226 226 } 227 227 } ··· 872 872 } 873 873 } 874 874 875 - void ilk_display_irq_handler(struct intel_display *display, u32 de_iir) 875 + static void _ilk_display_irq_handler(struct intel_display *display, u32 de_iir) 876 876 { 877 877 enum pipe pipe; 878 878 u32 hotplug_trigger = de_iir & DE_DP_A_HOTPLUG; ··· 923 923 ilk_display_rps_irq_handler(display); 924 924 } 925 925 926 - void ivb_display_irq_handler(struct intel_display *display, u32 de_iir) 926 + static void _ivb_display_irq_handler(struct intel_display *display, u32 de_iir) 927 927 { 928 928 enum pipe pipe; 929 929 u32 hotplug_trigger = de_iir & DE_DP_A_HOTPLUG_IVB; ··· 970 970 /* clear PCH hotplug event before clear CPU irq */ 971 971 intel_de_write(display, SDEIIR, pch_iir); 972 972 } 973 + } 974 + 975 + void ilk_display_irq_master_disable(struct intel_display *display, u32 *de_ier, u32 *sde_ier) 976 + { 977 + /* disable master interrupt before clearing iir */ 978 + *de_ier = intel_de_read_fw(display, DEIER); 979 + intel_de_write_fw(display, DEIER, *de_ier & ~DE_MASTER_IRQ_CONTROL); 980 + 981 + /* 982 + * Disable south interrupts. We'll only write to SDEIIR once, so further 983 + * interrupts will be stored on its back queue, and then we'll be able 984 + * to process them after we restore SDEIER (as soon as we restore it, 985 + * we'll get an interrupt if SDEIIR still has something to process due 986 + * to its back queue). 987 + */ 988 + if (!HAS_PCH_NOP(display)) { 989 + *sde_ier = intel_de_read_fw(display, SDEIER); 990 + intel_de_write_fw(display, SDEIER, 0); 991 + } else { 992 + *sde_ier = 0; 993 + } 994 + } 995 + 996 + void ilk_display_irq_master_enable(struct intel_display *display, u32 de_ier, u32 sde_ier) 997 + { 998 + intel_de_write_fw(display, DEIER, de_ier); 999 + 1000 + if (sde_ier) 1001 + intel_de_write_fw(display, SDEIER, sde_ier); 1002 + } 1003 + 1004 + bool ilk_display_irq_handler(struct intel_display *display) 1005 + { 1006 + u32 de_iir; 1007 + bool handled = false; 1008 + 1009 + de_iir = intel_de_read_fw(display, DEIIR); 1010 + if (de_iir) { 1011 + intel_de_write_fw(display, DEIIR, de_iir); 1012 + if (DISPLAY_VER(display) >= 7) 1013 + _ivb_display_irq_handler(display, de_iir); 1014 + else 1015 + _ilk_display_irq_handler(display, de_iir); 1016 + handled = true; 1017 + } 1018 + 1019 + return handled; 973 1020 } 974 1021 975 1022 static u32 gen8_de_port_aux_mask(struct intel_display *display) ··· 1912 1865 1913 1866 static void _vlv_display_irq_reset(struct intel_display *display) 1914 1867 { 1915 - struct drm_i915_private *dev_priv = to_i915(display->drm); 1916 - 1917 1868 if (display->platform.cherryview) 1918 1869 intel_de_write(display, DPINVGTT, DPINVGTT_STATUS_MASK_CHV); 1919 1870 else ··· 1926 1881 i9xx_pipestat_irq_reset(display); 1927 1882 1928 1883 intel_display_irq_regs_reset(display, VLV_IRQ_REGS); 1929 - dev_priv->irq_mask = ~0u; 1884 + display->irq.vlv_imr_mask = ~0u; 1930 1885 } 1931 1886 1932 1887 void vlv_display_irq_reset(struct intel_display *display) ··· 1945 1900 } 1946 1901 1947 1902 i9xx_pipestat_irq_reset(display); 1903 + } 1904 + 1905 + u32 i9xx_display_irq_enable_mask(struct intel_display *display) 1906 + { 1907 + u32 enable_mask; 1908 + 1909 + enable_mask = I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | 1910 + I915_DISPLAY_PIPE_B_EVENT_INTERRUPT; 1911 + 1912 + if (DISPLAY_VER(display) >= 3) 1913 + enable_mask |= I915_ASLE_INTERRUPT; 1914 + 1915 + if (HAS_HOTPLUG(display)) 1916 + enable_mask |= I915_DISPLAY_PORT_INTERRUPT; 1917 + 1918 + return enable_mask; 1948 1919 } 1949 1920 1950 1921 void i915_display_irq_postinstall(struct intel_display *display) ··· 2000 1939 2001 1940 static void _vlv_display_irq_postinstall(struct intel_display *display) 2002 1941 { 2003 - struct drm_i915_private *dev_priv = to_i915(display->drm); 2004 1942 u32 pipestat_mask; 2005 1943 u32 enable_mask; 2006 1944 enum pipe pipe; ··· 2033 1973 enable_mask |= I915_DISPLAY_PIPE_C_EVENT_INTERRUPT | 2034 1974 I915_LPE_PIPE_C_INTERRUPT; 2035 1975 2036 - drm_WARN_ON(display->drm, dev_priv->irq_mask != ~0u); 1976 + drm_WARN_ON(display->drm, display->irq.vlv_imr_mask != ~0u); 2037 1977 2038 - dev_priv->irq_mask = ~enable_mask; 1978 + display->irq.vlv_imr_mask = ~enable_mask; 2039 1979 2040 - intel_display_irq_regs_init(display, VLV_IRQ_REGS, dev_priv->irq_mask, enable_mask); 1980 + intel_display_irq_regs_init(display, VLV_IRQ_REGS, display->irq.vlv_imr_mask, enable_mask); 2041 1981 } 2042 1982 2043 1983 void vlv_display_irq_postinstall(struct intel_display *display) ··· 2048 1988 spin_unlock_irq(&display->irq.lock); 2049 1989 } 2050 1990 2051 - void ibx_display_irq_reset(struct intel_display *display) 1991 + static void ibx_display_irq_reset(struct intel_display *display) 2052 1992 { 2053 1993 if (HAS_PCH_NOP(display)) 2054 1994 return; ··· 2057 1997 2058 1998 if (HAS_PCH_CPT(display) || HAS_PCH_LPT(display)) 2059 1999 intel_de_write(display, SERR_INT, 0xffffffff); 2000 + } 2001 + 2002 + void ilk_display_irq_reset(struct intel_display *display) 2003 + { 2004 + struct intel_uncore *uncore = to_intel_uncore(display->drm); 2005 + 2006 + gen2_irq_reset(uncore, DE_IRQ_REGS); 2007 + display->irq.ilk_de_imr_mask = ~0u; 2008 + 2009 + if (DISPLAY_VER(display) == 7) 2010 + intel_de_write(display, GEN7_ERR_INT, 0xffffffff); 2011 + 2012 + if (display->platform.haswell) { 2013 + intel_de_write(display, EDP_PSR_IMR, 0xffffffff); 2014 + intel_de_write(display, EDP_PSR_IIR, 0xffffffff); 2015 + } 2016 + 2017 + ibx_display_irq_reset(display); 2060 2018 } 2061 2019 2062 2020 void gen8_display_irq_reset(struct intel_display *display) ··· 2166 2088 2167 2089 for_each_pipe_masked(display, pipe, pipe_mask) 2168 2090 intel_display_irq_regs_init(display, GEN8_DE_PIPE_IRQ_REGS(pipe), 2169 - display->irq.de_irq_mask[pipe], 2170 - ~display->irq.de_irq_mask[pipe] | extra_ier); 2091 + display->irq.de_pipe_imr_mask[pipe], 2092 + ~display->irq.de_pipe_imr_mask[pipe] | extra_ier); 2171 2093 2172 2094 spin_unlock_irq(&display->irq.lock); 2173 2095 } ··· 2261 2183 2262 2184 void ilk_de_irq_postinstall(struct intel_display *display) 2263 2185 { 2264 - struct drm_i915_private *i915 = to_i915(display->drm); 2265 - 2266 2186 u32 display_mask, extra_mask; 2267 2187 2268 2188 if (DISPLAY_VER(display) >= 7) { ··· 2292 2216 if (display->platform.ironlake && display->platform.mobile) 2293 2217 extra_mask |= DE_PCU_EVENT; 2294 2218 2295 - i915->irq_mask = ~display_mask; 2219 + display->irq.ilk_de_imr_mask = ~display_mask; 2296 2220 2297 2221 ibx_irq_postinstall(display); 2298 2222 2299 - intel_display_irq_regs_init(display, DE_IRQ_REGS, i915->irq_mask, 2223 + intel_display_irq_regs_init(display, DE_IRQ_REGS, display->irq.ilk_de_imr_mask, 2300 2224 display_mask | extra_mask); 2301 2225 } 2302 2226 ··· 2381 2305 } 2382 2306 2383 2307 for_each_pipe(display, pipe) { 2384 - display->irq.de_irq_mask[pipe] = ~de_pipe_masked; 2308 + display->irq.de_pipe_imr_mask[pipe] = ~de_pipe_masked; 2385 2309 2386 2310 if (intel_display_power_is_enabled(display, 2387 2311 POWER_DOMAIN_PIPE(pipe))) 2388 2312 intel_display_irq_regs_init(display, GEN8_DE_PIPE_IRQ_REGS(pipe), 2389 - display->irq.de_irq_mask[pipe], 2313 + display->irq.de_pipe_imr_mask[pipe], 2390 2314 de_pipe_enables); 2391 2315 } 2392 2316
+5 -3
drivers/gpu/drm/i915/display/intel_display_irq.h
··· 47 47 void ilk_disable_vblank(struct drm_crtc *crtc); 48 48 void bdw_disable_vblank(struct drm_crtc *crtc); 49 49 50 - void ivb_display_irq_handler(struct intel_display *display, u32 de_iir); 51 - void ilk_display_irq_handler(struct intel_display *display, u32 de_iir); 50 + void ilk_display_irq_master_disable(struct intel_display *display, u32 *de_ier, u32 *sde_ier); 51 + void ilk_display_irq_master_enable(struct intel_display *display, u32 de_ier, u32 sde_ier); 52 + bool ilk_display_irq_handler(struct intel_display *display); 52 53 void gen8_de_irq_handler(struct intel_display *display, u32 master_ctl); 53 54 void gen11_display_irq_handler(struct intel_display *display); 54 55 ··· 57 56 void gen11_gu_misc_irq_handler(struct intel_display *display, const u32 iir); 58 57 59 58 void i9xx_display_irq_reset(struct intel_display *display); 60 - void ibx_display_irq_reset(struct intel_display *display); 59 + void ilk_display_irq_reset(struct intel_display *display); 61 60 void vlv_display_irq_reset(struct intel_display *display); 62 61 void gen8_display_irq_reset(struct intel_display *display); 63 62 void gen11_display_irq_reset(struct intel_display *display); 64 63 64 + u32 i9xx_display_irq_enable_mask(struct intel_display *display); 65 65 void i915_display_irq_postinstall(struct intel_display *display); 66 66 void i965_display_irq_postinstall(struct intel_display *display); 67 67 void vlv_display_irq_postinstall(struct intel_display *display);
+43
drivers/gpu/drm/i915/display/intel_display_jiffies.h
··· 1 + /* SPDX-License-Identifier: MIT */ 2 + /* Copyright © 2025 Intel Corporation */ 3 + 4 + #ifndef __INTEL_DISPLAY_JIFFIES_H__ 5 + #define __INTEL_DISPLAY_JIFFIES_H__ 6 + 7 + #include <linux/jiffies.h> 8 + 9 + static inline unsigned long msecs_to_jiffies_timeout(const unsigned int m) 10 + { 11 + unsigned long j = msecs_to_jiffies(m); 12 + 13 + return min_t(unsigned long, MAX_JIFFY_OFFSET, j + 1); 14 + } 15 + 16 + /* 17 + * If you need to wait X milliseconds between events A and B, but event B 18 + * doesn't happen exactly after event A, you record the timestamp (jiffies) of 19 + * when event A happened, then just before event B you call this function and 20 + * pass the timestamp as the first argument, and X as the second argument. 21 + */ 22 + static inline void 23 + wait_remaining_ms_from_jiffies(unsigned long timestamp_jiffies, int to_wait_ms) 24 + { 25 + unsigned long target_jiffies, tmp_jiffies, remaining_jiffies; 26 + 27 + /* 28 + * Don't re-read the value of "jiffies" every time since it may change 29 + * behind our back and break the math. 30 + */ 31 + tmp_jiffies = jiffies; 32 + target_jiffies = timestamp_jiffies + 33 + msecs_to_jiffies_timeout(to_wait_ms); 34 + 35 + if (time_after(target_jiffies, tmp_jiffies)) { 36 + remaining_jiffies = target_jiffies - tmp_jiffies; 37 + while (remaining_jiffies) 38 + remaining_jiffies = 39 + schedule_timeout_uninterruptible(remaining_jiffies); 40 + } 41 + } 42 + 43 + #endif /* __INTEL_DISPLAY_JIFFIES_H__ */
+1 -1
drivers/gpu/drm/i915/display/intel_display_power.c
··· 11 11 #include "i915_drv.h" 12 12 #include "i915_irq.h" 13 13 #include "i915_reg.h" 14 - #include "i915_utils.h" 15 14 #include "intel_backlight_regs.h" 16 15 #include "intel_cdclk.h" 17 16 #include "intel_clock_gating.h" ··· 22 23 #include "intel_display_regs.h" 23 24 #include "intel_display_rpm.h" 24 25 #include "intel_display_types.h" 26 + #include "intel_display_utils.h" 25 27 #include "intel_dmc.h" 26 28 #include "intel_mchbar_regs.h" 27 29 #include "intel_pch_refclk.h"
+14 -12
drivers/gpu/drm/i915/display/intel_display_power_map.c
··· 1516 1516 .ops = &hsw_power_well_ops, 1517 1517 .irq_pipe_mask = BIT(PIPE_D), 1518 1518 .has_fuses = true, 1519 - }, { 1519 + }, 1520 + }; 1521 + 1522 + static const struct i915_power_well_desc xelpdp_power_wells_aux[] = { 1523 + { 1520 1524 .instances = &I915_PW_INSTANCES( 1521 1525 I915_PW("AUX_A", &icl_pwdoms_aux_a, .xelpdp.aux_ch = AUX_CH_A), 1522 1526 I915_PW("AUX_B", &icl_pwdoms_aux_b, .xelpdp.aux_ch = AUX_CH_B), ··· 1538 1534 I915_PW_DESCRIPTORS(icl_power_wells_pw_1), 1539 1535 I915_PW_DESCRIPTORS(xelpd_power_wells_dc_off), 1540 1536 I915_PW_DESCRIPTORS(xelpdp_power_wells_main), 1537 + I915_PW_DESCRIPTORS(xelpdp_power_wells_aux), 1541 1538 }; 1542 1539 1543 1540 I915_DECL_PW_DOMAINS(xe2lpd_pwdoms_pica_tc, ··· 1589 1584 I915_PW_DESCRIPTORS(xe2lpd_power_wells_dcoff), 1590 1585 I915_PW_DESCRIPTORS(xelpdp_power_wells_main), 1591 1586 I915_PW_DESCRIPTORS(xe2lpd_power_wells_pica), 1587 + I915_PW_DESCRIPTORS(xelpdp_power_wells_aux), 1592 1588 }; 1593 1589 1594 1590 /* ··· 1683 1677 .ops = &hsw_power_well_ops, 1684 1678 .irq_pipe_mask = BIT(PIPE_D), 1685 1679 .has_fuses = true, 1686 - }, { 1687 - .instances = &I915_PW_INSTANCES( 1688 - I915_PW("AUX_A", &icl_pwdoms_aux_a, .xelpdp.aux_ch = AUX_CH_A), 1689 - I915_PW("AUX_B", &icl_pwdoms_aux_b, .xelpdp.aux_ch = AUX_CH_B), 1690 - I915_PW("AUX_TC1", &xelpdp_pwdoms_aux_tc1, .xelpdp.aux_ch = AUX_CH_USBC1), 1691 - I915_PW("AUX_TC2", &xelpdp_pwdoms_aux_tc2, .xelpdp.aux_ch = AUX_CH_USBC2), 1692 - I915_PW("AUX_TC3", &xelpdp_pwdoms_aux_tc3, .xelpdp.aux_ch = AUX_CH_USBC3), 1693 - I915_PW("AUX_TC4", &xelpdp_pwdoms_aux_tc4, .xelpdp.aux_ch = AUX_CH_USBC4), 1694 - ), 1695 - .ops = &xelpdp_aux_power_well_ops, 1696 1680 }, 1697 1681 }; 1698 1682 ··· 1711 1715 I915_PW_DESCRIPTORS(xe3lpd_power_wells_dcoff), 1712 1716 I915_PW_DESCRIPTORS(xe3lpd_power_wells_main), 1713 1717 I915_PW_DESCRIPTORS(xe2lpd_power_wells_pica), 1718 + I915_PW_DESCRIPTORS(xelpdp_power_wells_aux), 1714 1719 }; 1715 1720 1716 1721 static const struct i915_power_well_desc wcl_power_wells_main[] = { ··· 1748 1751 .ops = &hsw_power_well_ops, 1749 1752 .irq_pipe_mask = BIT(PIPE_C), 1750 1753 .has_fuses = true, 1751 - }, { 1754 + }, 1755 + }; 1756 + 1757 + static const struct i915_power_well_desc wcl_power_wells_aux[] = { 1758 + { 1752 1759 .instances = &I915_PW_INSTANCES( 1753 1760 I915_PW("AUX_A", &icl_pwdoms_aux_a, .xelpdp.aux_ch = AUX_CH_A), 1754 1761 I915_PW("AUX_B", &icl_pwdoms_aux_b, .xelpdp.aux_ch = AUX_CH_B), ··· 1769 1768 I915_PW_DESCRIPTORS(xe3lpd_power_wells_dcoff), 1770 1769 I915_PW_DESCRIPTORS(wcl_power_wells_main), 1771 1770 I915_PW_DESCRIPTORS(xe2lpd_power_wells_pica), 1771 + I915_PW_DESCRIPTORS(wcl_power_wells_aux), 1772 1772 }; 1773 1773 1774 1774 static void init_power_well_domains(const struct i915_power_well_instance *inst,
+20 -2
drivers/gpu/drm/i915/display/intel_display_power_well.c
··· 1864 1864 * expected to just wait a fixed 600us after raising the request 1865 1865 * bit. 1866 1866 */ 1867 - usleep_range(600, 1200); 1867 + if (DISPLAY_VER(display) >= 35) { 1868 + if (intel_de_wait_for_set(display, XELPDP_DP_AUX_CH_CTL(display, aux_ch), 1869 + XELPDP_DP_AUX_CH_CTL_POWER_STATUS, 2)) 1870 + drm_warn(display->drm, 1871 + "Timeout waiting for PHY %c AUX channel power to be up\n", 1872 + phy_name(phy)); 1873 + } else { 1874 + usleep_range(600, 1200); 1875 + } 1868 1876 } 1869 1877 1870 1878 static void xelpdp_aux_power_well_disable(struct intel_display *display, 1871 1879 struct i915_power_well *power_well) 1872 1880 { 1873 1881 enum aux_ch aux_ch = i915_power_well_instance(power_well)->xelpdp.aux_ch; 1882 + enum phy phy = icl_aux_pw_to_phy(display, power_well); 1874 1883 1875 1884 intel_de_rmw(display, XELPDP_DP_AUX_CH_CTL(display, aux_ch), 1876 1885 XELPDP_DP_AUX_CH_CTL_POWER_REQUEST, 1877 1886 0); 1878 - usleep_range(10, 30); 1887 + 1888 + if (DISPLAY_VER(display) >= 35) { 1889 + if (intel_de_wait_for_clear(display, XELPDP_DP_AUX_CH_CTL(display, aux_ch), 1890 + XELPDP_DP_AUX_CH_CTL_POWER_STATUS, 1)) 1891 + drm_warn(display->drm, 1892 + "Timeout waiting for PHY %c AUX channel to powerdown\n", 1893 + phy_name(phy)); 1894 + } else { 1895 + usleep_range(10, 30); 1896 + } 1879 1897 } 1880 1898 1881 1899 static bool xelpdp_aux_power_well_enabled(struct intel_display *display,
+13 -20
drivers/gpu/drm/i915/display/intel_display_rpm.c
··· 1 1 // SPDX-License-Identifier: MIT 2 2 /* Copyright © 2025 Intel Corporation */ 3 3 4 - #include "i915_drv.h" 4 + #include <drm/intel/display_parent_interface.h> 5 + 5 6 #include "intel_display_core.h" 6 7 #include "intel_display_rpm.h" 7 - #include "intel_runtime_pm.h" 8 - 9 - static struct intel_runtime_pm *display_to_rpm(struct intel_display *display) 10 - { 11 - struct drm_i915_private *i915 = to_i915(display->drm); 12 - 13 - return &i915->runtime_pm; 14 - } 15 8 16 9 struct ref_tracker *intel_display_rpm_get_raw(struct intel_display *display) 17 10 { 18 - return intel_runtime_pm_get_raw(display_to_rpm(display)); 11 + return display->parent->rpm->get_raw(display->drm); 19 12 } 20 13 21 14 void intel_display_rpm_put_raw(struct intel_display *display, struct ref_tracker *wakeref) 22 15 { 23 - intel_runtime_pm_put_raw(display_to_rpm(display), wakeref); 16 + display->parent->rpm->put_raw(display->drm, wakeref); 24 17 } 25 18 26 19 struct ref_tracker *intel_display_rpm_get(struct intel_display *display) 27 20 { 28 - return intel_runtime_pm_get(display_to_rpm(display)); 21 + return display->parent->rpm->get(display->drm); 29 22 } 30 23 31 24 struct ref_tracker *intel_display_rpm_get_if_in_use(struct intel_display *display) 32 25 { 33 - return intel_runtime_pm_get_if_in_use(display_to_rpm(display)); 26 + return display->parent->rpm->get_if_in_use(display->drm); 34 27 } 35 28 36 29 struct ref_tracker *intel_display_rpm_get_noresume(struct intel_display *display) 37 30 { 38 - return intel_runtime_pm_get_noresume(display_to_rpm(display)); 31 + return display->parent->rpm->get_noresume(display->drm); 39 32 } 40 33 41 34 void intel_display_rpm_put(struct intel_display *display, struct ref_tracker *wakeref) 42 35 { 43 - intel_runtime_pm_put(display_to_rpm(display), wakeref); 36 + display->parent->rpm->put(display->drm, wakeref); 44 37 } 45 38 46 39 void intel_display_rpm_put_unchecked(struct intel_display *display) 47 40 { 48 - intel_runtime_pm_put_unchecked(display_to_rpm(display)); 41 + display->parent->rpm->put_unchecked(display->drm); 49 42 } 50 43 51 44 bool intel_display_rpm_suspended(struct intel_display *display) 52 45 { 53 - return intel_runtime_pm_suspended(display_to_rpm(display)); 46 + return display->parent->rpm->suspended(display->drm); 54 47 } 55 48 56 49 void assert_display_rpm_held(struct intel_display *display) 57 50 { 58 - assert_rpm_wakelock_held(display_to_rpm(display)); 51 + display->parent->rpm->assert_held(display->drm); 59 52 } 60 53 61 54 void intel_display_rpm_assert_block(struct intel_display *display) 62 55 { 63 - disable_rpm_wakeref_asserts(display_to_rpm(display)); 56 + display->parent->rpm->assert_block(display->drm); 64 57 } 65 58 66 59 void intel_display_rpm_assert_unblock(struct intel_display *display) 67 60 { 68 - enable_rpm_wakeref_asserts(display_to_rpm(display)); 61 + display->parent->rpm->assert_unblock(display->drm); 69 62 }
+59 -9
drivers/gpu/drm/i915/display/intel_display_types.h
··· 551 551 u8 fec_capability; 552 552 553 553 u8 dsc_hblank_expansion_quirk:1; 554 + u8 dsc_throughput_quirk:1; 554 555 u8 dsc_decompression_enabled:1; 556 + 557 + struct { 558 + struct { 559 + int rgb_yuv444; 560 + int yuv422_420; 561 + } overall_throughput; 562 + int max_line_width; 563 + } dsc_branch_caps; 555 564 } dp; 556 565 557 566 struct { ··· 955 946 u16 postoff[3]; 956 947 }; 957 948 949 + enum intel_panel_replay_dsc_support { 950 + INTEL_DP_PANEL_REPLAY_DSC_NOT_SUPPORTED, 951 + INTEL_DP_PANEL_REPLAY_DSC_FULL_FRAME_ONLY, 952 + INTEL_DP_PANEL_REPLAY_DSC_SELECTIVE_UPDATE, 953 + }; 954 + 955 + struct scaler_filter_coeff { 956 + u16 sign; 957 + u16 exp; 958 + u16 mantissa; 959 + }; 960 + 961 + struct intel_casf { 962 + #define SCALER_FILTER_NUM_TAPS 7 963 + struct scaler_filter_coeff coeff[SCALER_FILTER_NUM_TAPS]; 964 + u8 strength; 965 + u8 win_size; 966 + bool casf_enable; 967 + }; 968 + 958 969 struct intel_crtc_state { 959 970 /* 960 971 * uapi (drm) state. This is the software state shown to userspace. ··· 1011 982 struct drm_property_blob *degamma_lut, *gamma_lut, *ctm; 1012 983 struct drm_display_mode mode, pipe_mode, adjusted_mode; 1013 984 enum drm_scaling_filter scaling_filter; 985 + struct intel_casf casf_params; 1014 986 } hw; 1015 987 1016 988 /* actual state of LUTs */ ··· 1154 1124 bool has_panel_replay; 1155 1125 bool wm_level_disabled; 1156 1126 bool pkg_c_latency_used; 1127 + /* Only used for state verification. */ 1128 + enum intel_panel_replay_dsc_support panel_replay_dsc_support; 1157 1129 u32 dc3co_exitline; 1158 1130 u16 su_y_granularity; 1159 1131 u8 active_non_psr_pipes; 1132 + const char *no_psr_reason; 1160 1133 1161 1134 /* 1162 1135 * Frequency the dpll for the port should run at. Differs from the ··· 1216 1183 1217 1184 struct intel_crtc_wm_state wm; 1218 1185 1219 - int min_cdclk[I915_MAX_PLANES]; 1186 + int min_cdclk; 1187 + 1188 + int plane_min_cdclk[I915_MAX_PLANES]; 1220 1189 1221 1190 /* for packed/planar CbCr */ 1222 1191 u32 data_rate[I915_MAX_PLANES]; ··· 1303 1268 1304 1269 /* Display Stream compression state */ 1305 1270 struct { 1271 + /* Only used for state computation, not read out from the HW. */ 1272 + bool compression_enabled_on_link; 1306 1273 bool compression_enable; 1307 1274 int num_streams; 1308 1275 /* Compressed Bpp in U6.4 format (first 4 bits for fractional part) */ ··· 1378 1341 1379 1342 /* LOBF flag */ 1380 1343 bool has_lobf; 1344 + 1345 + /* W2 window or 'set context latency' lines */ 1346 + u16 set_context_latency; 1347 + 1348 + struct { 1349 + u8 io_wake_lines; 1350 + u8 fast_wake_lines; 1351 + 1352 + /* LNL and beyond */ 1353 + u8 check_entry_lines; 1354 + u8 aux_less_wake_lines; 1355 + u8 silence_period_sym_clocks; 1356 + u8 lfps_half_cycle_num_of_syms; 1357 + } alpm_state; 1381 1358 }; 1382 1359 1383 1360 enum intel_pipe_crc_source { ··· 1730 1679 bool source_panel_replay_support; 1731 1680 bool sink_panel_replay_support; 1732 1681 bool sink_panel_replay_su_support; 1682 + enum intel_panel_replay_dsc_support sink_panel_replay_dsc_support; 1733 1683 bool panel_replay_enabled; 1734 1684 u32 dc3co_exitline; 1735 1685 u32 dc3co_exit_delay; 1736 1686 struct delayed_work dc3co_work; 1737 1687 u8 entry_setup_frames; 1738 1688 1689 + u8 io_wake_lines; 1690 + u8 fast_wake_lines; 1691 + 1739 1692 bool link_ok; 1740 1693 bool pkg_c_latency_used; 1741 1694 1742 1695 u8 active_non_psr_pipes; 1696 + 1697 + const char *no_psr_reason; 1743 1698 }; 1744 1699 1745 1700 struct intel_dp { ··· 1901 1844 bool colorimetry_support; 1902 1845 1903 1846 struct { 1904 - u8 io_wake_lines; 1905 - u8 fast_wake_lines; 1906 1847 enum transcoder transcoder; 1907 1848 struct mutex lock; 1908 1849 1909 - /* LNL and beyond */ 1910 - u8 check_entry_lines; 1911 - u8 aux_less_wake_lines; 1912 - u8 silence_period_sym_clocks; 1913 - u8 lfps_half_cycle_num_of_syms; 1914 1850 bool lobf_disable_debug; 1915 1851 bool sink_alpm_error; 1916 - } alpm_parameters; 1852 + } alpm; 1917 1853 1918 1854 u8 alpm_dpcd; 1919 1855
+32
drivers/gpu/drm/i915/display/intel_display_utils.c
··· 1 + // SPDX-License-Identifier: MIT 2 + /* Copyright © 2025 Intel Corporation */ 3 + 4 + #include <linux/device.h> 5 + 6 + #include <drm/drm_device.h> 7 + 8 + #ifdef CONFIG_X86 9 + #include <asm/hypervisor.h> 10 + #endif 11 + 12 + #include "intel_display_core.h" 13 + #include "intel_display_utils.h" 14 + 15 + bool intel_display_run_as_guest(struct intel_display *display) 16 + { 17 + #if IS_ENABLED(CONFIG_X86) 18 + return !hypervisor_is_type(X86_HYPER_NATIVE); 19 + #else 20 + /* Not supported yet */ 21 + return false; 22 + #endif 23 + } 24 + 25 + bool intel_display_vtd_active(struct intel_display *display) 26 + { 27 + if (device_iommu_mapped(display->drm->dev)) 28 + return true; 29 + 30 + /* Running as a guest, we assume the host is enforcing VT'd */ 31 + return intel_display_run_as_guest(display); 32 + }
+31
drivers/gpu/drm/i915/display/intel_display_utils.h
··· 1 + /* SPDX-License-Identifier: MIT */ 2 + /* Copyright © 2025 Intel Corporation */ 3 + 4 + #ifndef __INTEL_DISPLAY_UTILS__ 5 + #define __INTEL_DISPLAY_UTILS__ 6 + 7 + #include <linux/bug.h> 8 + #include <linux/types.h> 9 + 10 + struct intel_display; 11 + 12 + #ifndef MISSING_CASE 13 + #define MISSING_CASE(x) WARN(1, "Missing case (%s == %ld)\n", \ 14 + __stringify(x), (long)(x)) 15 + #endif 16 + 17 + #ifndef fetch_and_zero 18 + #define fetch_and_zero(ptr) ({ \ 19 + typeof(*ptr) __T = *(ptr); \ 20 + *(ptr) = (typeof(*ptr))0; \ 21 + __T; \ 22 + }) 23 + #endif 24 + 25 + #define KHz(x) (1000 * (x)) 26 + #define MHz(x) KHz(1000 * (x)) 27 + 28 + bool intel_display_run_as_guest(struct intel_display *display); 29 + bool intel_display_vtd_active(struct intel_display *display); 30 + 31 + #endif /* __INTEL_DISPLAY_UTILS__ */
+2
drivers/gpu/drm/i915/display/intel_display_wa.c
··· 67 67 return intel_display_needs_wa_16025573575(display); 68 68 case INTEL_DISPLAY_WA_14011503117: 69 69 return DISPLAY_VER(display) == 13; 70 + case INTEL_DISPLAY_WA_22014263786: 71 + return IS_DISPLAY_VERx100(display, 1100, 1400); 70 72 default: 71 73 drm_WARN(display->drm, 1, "Missing Wa number: %s\n", name); 72 74 break;
+1
drivers/gpu/drm/i915/display/intel_display_wa.h
··· 25 25 INTEL_DISPLAY_WA_16023588340, 26 26 INTEL_DISPLAY_WA_16025573575, 27 27 INTEL_DISPLAY_WA_14011503117, 28 + INTEL_DISPLAY_WA_22014263786, 28 29 }; 29 30 30 31 bool __intel_display_wa(struct intel_display *display, enum intel_display_wa wa, const char *name);
+90 -18
drivers/gpu/drm/i915/display/intel_dmc.c
··· 30 30 #include <drm/drm_print.h> 31 31 32 32 #include "i915_reg.h" 33 - #include "i915_utils.h" 34 33 #include "intel_crtc.h" 35 34 #include "intel_de.h" 36 35 #include "intel_display_power_well.h" 37 36 #include "intel_display_regs.h" 38 37 #include "intel_display_rpm.h" 39 38 #include "intel_display_types.h" 39 + #include "intel_display_utils.h" 40 40 #include "intel_dmc.h" 41 41 #include "intel_dmc_regs.h" 42 42 #include "intel_flipq.h" ··· 127 127 #define DISPLAY_VER13_DMC_MAX_FW_SIZE 0x20000 128 128 #define DISPLAY_VER12_DMC_MAX_FW_SIZE ICL_DMC_MAX_FW_SIZE 129 129 130 + #define XE3LPD_3002_DMC_PATH DMC_PATH(xe3lpd_3002) 131 + MODULE_FIRMWARE(XE3LPD_3002_DMC_PATH); 132 + 130 133 #define XE3LPD_DMC_PATH DMC_PATH(xe3lpd) 131 134 MODULE_FIRMWARE(XE3LPD_DMC_PATH); 132 135 ··· 186 183 { 187 184 const char *fw_path = NULL; 188 185 u32 max_fw_size = 0; 189 - 190 - if (DISPLAY_VERx100(display) == 3002 || 191 - DISPLAY_VERx100(display) == 3000) { 186 + if (DISPLAY_VERx100(display) == 3002) { 187 + fw_path = XE3LPD_3002_DMC_PATH; 188 + max_fw_size = XE2LPD_DMC_MAX_FW_SIZE; 189 + } else if (DISPLAY_VERx100(display) == 3000) { 192 190 fw_path = XE3LPD_DMC_PATH; 193 191 max_fw_size = XE2LPD_DMC_MAX_FW_SIZE; 194 192 } else if (DISPLAY_VERx100(display) == 2000) { ··· 513 509 PIPEDMC_ATS_FAULT; 514 510 } 515 511 516 - static u32 dmc_evt_ctl_disable(void) 512 + static u32 dmc_evt_ctl_disable(u32 dmc_evt_ctl) 517 513 { 518 - return REG_FIELD_PREP(DMC_EVT_CTL_TYPE_MASK, 519 - DMC_EVT_CTL_TYPE_EDGE_0_1) | 514 + /* 515 + * DMC_EVT_CTL_ENABLE cannot be cleared once set. Always 516 + * configure it based on the original event definition to 517 + * avoid mismatches in assert_dmc_loaded(). 518 + */ 519 + return (dmc_evt_ctl & DMC_EVT_CTL_ENABLE) | 520 + REG_FIELD_PREP(DMC_EVT_CTL_TYPE_MASK, 521 + DMC_EVT_CTL_TYPE_EDGE_0_1) | 520 522 REG_FIELD_PREP(DMC_EVT_CTL_EVENT_ID_MASK, 521 523 DMC_EVENT_FALSE); 522 524 } ··· 556 546 REG_FIELD_GET(DMC_EVT_CTL_EVENT_ID_MASK, data) == event_id; 557 547 } 558 548 549 + static bool fixup_dmc_evt(struct intel_display *display, 550 + enum intel_dmc_id dmc_id, 551 + i915_reg_t reg_ctl, u32 *data_ctl, 552 + i915_reg_t reg_htp, u32 *data_htp) 553 + { 554 + if (!is_dmc_evt_ctl_reg(display, dmc_id, reg_ctl)) 555 + return false; 556 + 557 + if (!is_dmc_evt_htp_reg(display, dmc_id, reg_htp)) 558 + return false; 559 + 560 + /* make sure reg_ctl and reg_htp are for the same event */ 561 + if (i915_mmio_reg_offset(reg_ctl) - i915_mmio_reg_offset(DMC_EVT_CTL(display, dmc_id, 0)) != 562 + i915_mmio_reg_offset(reg_htp) - i915_mmio_reg_offset(DMC_EVT_HTP(display, dmc_id, 0))) 563 + return false; 564 + 565 + /* 566 + * On ADL-S the HRR event handler is not restored after DC6. 567 + * Clear it to zero from the beginning to avoid mismatches later. 568 + */ 569 + if (display->platform.alderlake_s && dmc_id == DMC_FW_MAIN && 570 + is_event_handler(display, dmc_id, MAINDMC_EVENT_VBLANK_A, reg_ctl, *data_ctl)) { 571 + *data_ctl = 0; 572 + *data_htp = 0; 573 + return true; 574 + } 575 + 576 + /* 577 + * TGL/ADL-S DMC firmware incorrectly uses the undelayed vblank 578 + * event for the HRR handler, when it should be using the delayed 579 + * vblank event instead. Fixed firmware was never released 580 + * so the Windows driver just hacks around it by overriding 581 + * the event ID. Do the same. 582 + */ 583 + if ((display->platform.tigerlake || display->platform.alderlake_s) && 584 + is_event_handler(display, dmc_id, MAINDMC_EVENT_VBLANK_A, reg_ctl, *data_ctl)) { 585 + *data_ctl &= ~DMC_EVT_CTL_EVENT_ID_MASK; 586 + *data_ctl |= REG_FIELD_PREP(DMC_EVT_CTL_EVENT_ID_MASK, 587 + MAINDMC_EVENT_VBLANK_DELAYED_A); 588 + return true; 589 + } 590 + 591 + return false; 592 + } 593 + 559 594 static bool disable_dmc_evt(struct intel_display *display, 560 595 enum intel_dmc_id dmc_id, 561 596 i915_reg_t reg, u32 data) ··· 619 564 620 565 /* also disable the HRR event on the main DMC on TGL/ADLS */ 621 566 if ((display->platform.tigerlake || display->platform.alderlake_s) && 622 - is_event_handler(display, dmc_id, MAINDMC_EVENT_VBLANK_A, reg, data)) 567 + is_event_handler(display, dmc_id, MAINDMC_EVENT_VBLANK_DELAYED_A, reg, data)) 623 568 return true; 624 569 625 570 return false; ··· 632 577 if (disable_dmc_evt(display, dmc_id, 633 578 dmc->dmc_info[dmc_id].mmioaddr[i], 634 579 dmc->dmc_info[dmc_id].mmiodata[i])) 635 - return dmc_evt_ctl_disable(); 580 + return dmc_evt_ctl_disable(dmc->dmc_info[dmc_id].mmiodata[i]); 636 581 else 637 582 return dmc->dmc_info[dmc_id].mmiodata[i]; 638 583 } ··· 690 635 691 636 found = intel_de_read(display, reg); 692 637 expected = dmc_mmiodata(display, dmc, dmc_id, i); 693 - 694 - /* once set DMC_EVT_CTL_ENABLE can't be cleared :/ */ 695 - if (is_dmc_evt_ctl_reg(display, dmc_id, reg)) { 696 - found &= ~DMC_EVT_CTL_ENABLE; 697 - expected &= ~DMC_EVT_CTL_ENABLE; 698 - } 699 638 700 639 drm_WARN(display->drm, found != expected, 701 640 "DMC %d mmio[%d]/0x%x incorrect (expected 0x%x, current 0x%x)\n", ··· 843 794 if (!is_event_handler(display, dmc_id, event_id, reg, data)) 844 795 continue; 845 796 846 - intel_de_write(display, reg, enable ? data : dmc_evt_ctl_disable()); 797 + intel_de_write(display, reg, enable ? data : dmc_evt_ctl_disable(data)); 847 798 num_handlers++; 848 799 } 849 800 ··· 1113 1064 for (i = 0; i < mmio_count; i++) { 1114 1065 dmc_info->mmioaddr[i] = _MMIO(mmioaddr[i]); 1115 1066 dmc_info->mmiodata[i] = mmiodata[i]; 1067 + } 1116 1068 1069 + for (i = 0; i < mmio_count - 1; i++) { 1070 + u32 orig_mmiodata[2] = { 1071 + dmc_info->mmiodata[i], 1072 + dmc_info->mmiodata[i+1], 1073 + }; 1074 + 1075 + if (!fixup_dmc_evt(display, dmc_id, 1076 + dmc_info->mmioaddr[i], &dmc_info->mmiodata[i], 1077 + dmc_info->mmioaddr[i+1], &dmc_info->mmiodata[i+1])) 1078 + continue; 1079 + 1080 + drm_dbg_kms(display->drm, 1081 + " mmio[%d]: 0x%x = 0x%x->0x%x (EVT_CTL)\n", 1082 + i, i915_mmio_reg_offset(dmc_info->mmioaddr[i]), 1083 + orig_mmiodata[0], dmc_info->mmiodata[i]); 1084 + drm_dbg_kms(display->drm, 1085 + " mmio[%d]: 0x%x = 0x%x->0x%x (EVT_HTP)\n", 1086 + i+1, i915_mmio_reg_offset(dmc_info->mmioaddr[i+1]), 1087 + orig_mmiodata[1], dmc_info->mmiodata[i+1]); 1088 + } 1089 + 1090 + for (i = 0; i < mmio_count; i++) { 1117 1091 drm_dbg_kms(display->drm, " mmio[%d]: 0x%x = 0x%x%s%s\n", 1118 - i, mmioaddr[i], mmiodata[i], 1092 + i, i915_mmio_reg_offset(dmc_info->mmioaddr[i]), dmc_info->mmiodata[i], 1119 1093 is_dmc_evt_ctl_reg(display, dmc_id, dmc_info->mmioaddr[i]) ? " (EVT_CTL)" : 1120 1094 is_dmc_evt_htp_reg(display, dmc_id, dmc_info->mmioaddr[i]) ? " (EVT_HTP)" : "", 1121 1095 disable_dmc_evt(display, dmc_id, dmc_info->mmioaddr[i], ··· 1213 1141 } 1214 1142 1215 1143 num_entries = package_header->num_entries; 1216 - if (WARN_ON(package_header->num_entries > max_entries)) 1144 + if (WARN_ON(num_entries > max_entries)) 1217 1145 num_entries = max_entries; 1218 1146 1219 1147 fw_info = (const struct intel_fw_info *)
+237 -26
drivers/gpu/drm/i915/display/intel_dp.c
··· 51 51 #include <drm/drm_probe_helper.h> 52 52 53 53 #include "g4x_dp.h" 54 - #include "i915_utils.h" 55 54 #include "intel_alpm.h" 56 55 #include "intel_atomic.h" 57 56 #include "intel_audio.h" ··· 63 64 #include "intel_ddi.h" 64 65 #include "intel_de.h" 65 66 #include "intel_display_driver.h" 67 + #include "intel_display_jiffies.h" 68 + #include "intel_display_utils.h" 66 69 #include "intel_display_regs.h" 67 70 #include "intel_display_rpm.h" 68 71 #include "intel_display_types.h" ··· 94 93 #include "intel_psr.h" 95 94 #include "intel_quirks.h" 96 95 #include "intel_tc.h" 96 + #include "intel_vblank.h" 97 97 #include "intel_vdsc.h" 98 98 #include "intel_vrr.h" 99 - 100 - /* DP DSC throughput values used for slice count calculations KPixels/s */ 101 - #define DP_DSC_PEAK_PIXEL_RATE 2720000 102 - #define DP_DSC_MAX_ENC_THROUGHPUT_0 340000 103 - #define DP_DSC_MAX_ENC_THROUGHPUT_1 400000 104 99 105 100 /* Max DSC line buffer depth supported by HW. */ 106 101 #define INTEL_DP_DSC_MAX_LINE_BUF_DEPTH 13 ··· 1015 1018 struct intel_display *display = to_intel_display(connector); 1016 1019 u8 min_slice_count, i; 1017 1020 int max_slice_width; 1021 + int tp_rgb_yuv444; 1022 + int tp_yuv422_420; 1018 1023 1019 - if (mode_clock <= DP_DSC_PEAK_PIXEL_RATE) 1020 - min_slice_count = DIV_ROUND_UP(mode_clock, 1021 - DP_DSC_MAX_ENC_THROUGHPUT_0); 1022 - else 1023 - min_slice_count = DIV_ROUND_UP(mode_clock, 1024 - DP_DSC_MAX_ENC_THROUGHPUT_1); 1024 + /* 1025 + * TODO: Use the throughput value specific to the actual RGB/YUV 1026 + * format of the output. 1027 + * The RGB/YUV444 throughput value should be always either equal 1028 + * or smaller than the YUV422/420 value, but let's not depend on 1029 + * this assumption. 1030 + */ 1031 + if (mode_clock > max(connector->dp.dsc_branch_caps.overall_throughput.rgb_yuv444, 1032 + connector->dp.dsc_branch_caps.overall_throughput.yuv422_420)) 1033 + return 0; 1034 + 1035 + if (mode_hdisplay > connector->dp.dsc_branch_caps.max_line_width) 1036 + return 0; 1037 + 1038 + /* 1039 + * TODO: Pass the total pixel rate of all the streams transferred to 1040 + * an MST tiled display, calculate the total slice count for all tiles 1041 + * from this and the per-tile slice count from the total slice count. 1042 + */ 1043 + tp_rgb_yuv444 = drm_dp_dsc_sink_max_slice_throughput(connector->dp.dsc_dpcd, 1044 + mode_clock, true); 1045 + tp_yuv422_420 = drm_dp_dsc_sink_max_slice_throughput(connector->dp.dsc_dpcd, 1046 + mode_clock, false); 1047 + 1048 + /* 1049 + * TODO: Use the throughput value specific to the actual RGB/YUV 1050 + * format of the output. 1051 + * For now use the smaller of these, which is ok, potentially 1052 + * resulting in a higher than required minimum slice count. 1053 + * The RGB/YUV444 throughput value should be always either equal 1054 + * or smaller than the YUV422/420 value, but let's not depend on 1055 + * this assumption. 1056 + */ 1057 + min_slice_count = DIV_ROUND_UP(mode_clock, min(tp_rgb_yuv444, tp_yuv422_420)); 1025 1058 1026 1059 /* 1027 1060 * Due to some DSC engine BW limitations, we need to enable second ··· 2367 2340 return 0; 2368 2341 } 2369 2342 2370 - static void intel_dp_fec_compute_config(struct intel_dp *intel_dp, 2371 - struct intel_crtc_state *crtc_state) 2343 + /* 2344 + * Return whether FEC must be enabled for 8b10b SST or MST links. On 128b132b 2345 + * links FEC is always enabled implicitly by the HW, so this function returns 2346 + * false for that case. 2347 + */ 2348 + bool intel_dp_needs_8b10b_fec(const struct intel_crtc_state *crtc_state, 2349 + bool dsc_enabled_on_crtc) 2372 2350 { 2373 - if (crtc_state->fec_enable) 2374 - return; 2351 + if (intel_dp_is_uhbr(crtc_state)) 2352 + return false; 2375 2353 2376 2354 /* 2377 2355 * Though eDP v1.5 supports FEC with DSC, unlike DP, it is optional. 2378 2356 * Since, FEC is a bandwidth overhead, continue to not enable it for 2379 2357 * eDP. Until, there is a good reason to do so. 2380 2358 */ 2381 - if (intel_dp_is_edp(intel_dp)) 2382 - return; 2359 + if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP)) 2360 + return false; 2383 2361 2384 - if (intel_dp_is_uhbr(crtc_state)) 2385 - return; 2386 - 2387 - crtc_state->fec_enable = true; 2362 + return dsc_enabled_on_crtc || intel_dsc_enabled_on_link(crtc_state); 2388 2363 } 2389 2364 2390 2365 int intel_dp_dsc_compute_config(struct intel_dp *intel_dp, ··· 2404 2375 bool is_mst = intel_crtc_has_type(pipe_config, INTEL_OUTPUT_DP_MST); 2405 2376 int ret; 2406 2377 2407 - intel_dp_fec_compute_config(intel_dp, pipe_config); 2378 + /* 2379 + * FIXME: set the FEC enabled state once pipe_config->port_clock is 2380 + * already known, so the UHBR/non-UHBR mode can be determined. 2381 + */ 2382 + pipe_config->fec_enable = intel_dp_needs_8b10b_fec(pipe_config, true); 2408 2383 2409 2384 if (!intel_dp_dsc_supports_format(connector, pipe_config->output_format)) 2410 2385 return -EINVAL; ··· 2483 2450 return ret; 2484 2451 } 2485 2452 2486 - pipe_config->dsc.compression_enable = true; 2453 + intel_dsc_enable_on_crtc(pipe_config); 2454 + 2487 2455 drm_dbg_kms(display->drm, "DP DSC computed with Input Bpp = %d " 2488 2456 "Compressed Bpp = " FXP_Q4_FMT " Slice Count = %d\n", 2489 2457 pipe_config->pipe_bpp, ··· 2492 2458 pipe_config->dsc.slice_count); 2493 2459 2494 2460 return 0; 2461 + } 2462 + 2463 + static int 2464 + dsc_throughput_quirk_max_bpp_x16(const struct intel_connector *connector, 2465 + const struct intel_crtc_state *crtc_state) 2466 + { 2467 + const struct drm_display_mode *adjusted_mode = 2468 + &crtc_state->hw.adjusted_mode; 2469 + 2470 + if (!connector->dp.dsc_throughput_quirk) 2471 + return INT_MAX; 2472 + 2473 + /* 2474 + * Synaptics Panamera branch devices have a problem decompressing a 2475 + * stream with a compressed link-bpp higher than 12, if the pixel 2476 + * clock is higher than ~50 % of the maximum overall throughput 2477 + * reported by the branch device. Work around this by limiting the 2478 + * maximum link bpp for such pixel clocks. 2479 + * 2480 + * TODO: Use the throughput value specific to the actual RGB/YUV 2481 + * format of the output, after determining the pixel clock limit for 2482 + * YUV modes. For now use the smaller of the throughput values, which 2483 + * may result in limiting the link-bpp value already at a lower than 2484 + * required mode clock in case of native YUV422/420 output formats. 2485 + * The RGB/YUV444 throughput value should be always either equal or 2486 + * smaller than the YUV422/420 value, but let's not depend on this 2487 + * assumption. 2488 + */ 2489 + if (adjusted_mode->crtc_clock < 2490 + min(connector->dp.dsc_branch_caps.overall_throughput.rgb_yuv444, 2491 + connector->dp.dsc_branch_caps.overall_throughput.yuv422_420) / 2) 2492 + return INT_MAX; 2493 + 2494 + return fxp_q4_from_int(12); 2495 2495 } 2496 2496 2497 2497 /* ··· 2559 2491 } else { 2560 2492 int dsc_src_min_bpp, dsc_sink_min_bpp, dsc_min_bpp; 2561 2493 int dsc_src_max_bpp, dsc_sink_max_bpp, dsc_max_bpp; 2494 + int throughput_max_bpp_x16; 2562 2495 2563 2496 dsc_src_min_bpp = intel_dp_dsc_min_src_compressed_bpp(); 2564 2497 dsc_sink_min_bpp = intel_dp_dsc_sink_min_compressed_bpp(crtc_state); ··· 2574 2505 min(dsc_sink_max_bpp, dsc_src_max_bpp) : dsc_src_max_bpp; 2575 2506 2576 2507 max_link_bpp_x16 = min(max_link_bpp_x16, fxp_q4_from_int(dsc_max_bpp)); 2508 + 2509 + throughput_max_bpp_x16 = dsc_throughput_quirk_max_bpp_x16(connector, crtc_state); 2510 + throughput_max_bpp_x16 = clamp(throughput_max_bpp_x16, 2511 + limits->link.min_bpp_x16, max_link_bpp_x16); 2512 + if (throughput_max_bpp_x16 < max_link_bpp_x16) { 2513 + max_link_bpp_x16 = throughput_max_bpp_x16; 2514 + 2515 + drm_dbg_kms(display->drm, 2516 + "[CRTC:%d:%s][CONNECTOR:%d:%s] Decreasing link max bpp to " FXP_Q4_FMT " due to DSC throughput quirk\n", 2517 + crtc->base.base.id, crtc->base.name, 2518 + connector->base.base.id, connector->base.name, 2519 + FXP_Q4_ARGS(max_link_bpp_x16)); 2520 + } 2577 2521 } 2578 2522 2579 2523 limits->link.max_bpp_x16 = max_link_bpp_x16; ··· 4251 4169 dsc_dpcd); 4252 4170 } 4253 4171 4254 - void intel_dp_get_dsc_sink_cap(u8 dpcd_rev, struct intel_connector *connector) 4172 + static void init_dsc_overall_throughput_limits(struct intel_connector *connector, bool is_branch) 4173 + { 4174 + u8 branch_caps[DP_DSC_BRANCH_CAP_SIZE]; 4175 + int line_width; 4176 + 4177 + connector->dp.dsc_branch_caps.overall_throughput.rgb_yuv444 = INT_MAX; 4178 + connector->dp.dsc_branch_caps.overall_throughput.yuv422_420 = INT_MAX; 4179 + connector->dp.dsc_branch_caps.max_line_width = INT_MAX; 4180 + 4181 + if (!is_branch) 4182 + return; 4183 + 4184 + if (drm_dp_dpcd_read_data(connector->dp.dsc_decompression_aux, 4185 + DP_DSC_BRANCH_OVERALL_THROUGHPUT_0, branch_caps, 4186 + sizeof(branch_caps)) != 0) 4187 + return; 4188 + 4189 + connector->dp.dsc_branch_caps.overall_throughput.rgb_yuv444 = 4190 + drm_dp_dsc_branch_max_overall_throughput(branch_caps, true) ? : INT_MAX; 4191 + 4192 + connector->dp.dsc_branch_caps.overall_throughput.yuv422_420 = 4193 + drm_dp_dsc_branch_max_overall_throughput(branch_caps, false) ? : INT_MAX; 4194 + 4195 + line_width = drm_dp_dsc_branch_max_line_width(branch_caps); 4196 + connector->dp.dsc_branch_caps.max_line_width = line_width > 0 ? line_width : INT_MAX; 4197 + } 4198 + 4199 + void intel_dp_get_dsc_sink_cap(u8 dpcd_rev, 4200 + const struct drm_dp_desc *desc, bool is_branch, 4201 + struct intel_connector *connector) 4255 4202 { 4256 4203 struct intel_display *display = to_intel_display(connector); 4257 4204 ··· 4292 4181 4293 4182 /* Clear fec_capable to avoid using stale values */ 4294 4183 connector->dp.fec_capability = 0; 4184 + 4185 + memset(&connector->dp.dsc_branch_caps, 0, sizeof(connector->dp.dsc_branch_caps)); 4186 + connector->dp.dsc_throughput_quirk = false; 4295 4187 4296 4188 if (dpcd_rev < DP_DPCD_REV_14) 4297 4189 return; ··· 4310 4196 4311 4197 drm_dbg_kms(display->drm, "FEC CAPABILITY: %x\n", 4312 4198 connector->dp.fec_capability); 4199 + 4200 + if (!(connector->dp.dsc_dpcd[0] & DP_DSC_DECOMPRESSION_IS_SUPPORTED)) 4201 + return; 4202 + 4203 + init_dsc_overall_throughput_limits(connector, is_branch); 4204 + 4205 + /* 4206 + * TODO: Move the HW rev check as well to the DRM core quirk table if 4207 + * that's required after clarifying the list of affected devices. 4208 + */ 4209 + if (drm_dp_has_quirk(desc, DP_DPCD_QUIRK_DSC_THROUGHPUT_BPP_LIMIT) && 4210 + desc->ident.hw_rev == 0x10) 4211 + connector->dp.dsc_throughput_quirk = true; 4313 4212 } 4314 4213 4315 4214 static void intel_edp_get_dsc_sink_cap(u8 edp_dpcd_rev, struct intel_connector *connector) ··· 4331 4204 return; 4332 4205 4333 4206 intel_dp_read_dsc_dpcd(connector->dp.dsc_decompression_aux, connector->dp.dsc_dpcd); 4207 + 4208 + if (connector->dp.dsc_dpcd[0] & DP_DSC_DECOMPRESSION_IS_SUPPORTED) 4209 + init_dsc_overall_throughput_limits(connector, false); 4334 4210 } 4335 4211 4336 4212 static void ··· 4350 4220 connector); 4351 4221 else 4352 4222 intel_dp_get_dsc_sink_cap(intel_dp->dpcd[DP_DPCD_REV], 4223 + &intel_dp->desc, drm_dp_is_branch(intel_dp->dpcd), 4353 4224 connector); 4354 4225 } 4355 4226 ··· 5684 5553 5685 5554 if (intel_alpm_get_error(intel_dp)) { 5686 5555 intel_alpm_disable(intel_dp); 5687 - intel_dp->alpm_parameters.sink_alpm_error = true; 5556 + intel_dp->alpm.sink_alpm_error = true; 5688 5557 } 5689 5558 5690 5559 if (intel_dp_test_short_pulse(intel_dp)) ··· 6052 5921 memset(connector->dp.dsc_dpcd, 0, sizeof(connector->dp.dsc_dpcd)); 6053 5922 intel_dp->psr.sink_panel_replay_support = false; 6054 5923 intel_dp->psr.sink_panel_replay_su_support = false; 5924 + intel_dp->psr.sink_panel_replay_dsc_support = 5925 + INTEL_DP_PANEL_REPLAY_DSC_NOT_SUPPORTED; 6055 5926 6056 5927 intel_dp_mst_disconnect(intel_dp); 6057 5928 ··· 6989 6856 drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst.mgr, false); 6990 6857 } 6991 6858 } 6859 + } 6860 + 6861 + static 6862 + int intel_dp_sdp_compute_config_late(struct intel_crtc_state *crtc_state) 6863 + { 6864 + struct intel_display *display = to_intel_display(crtc_state); 6865 + int guardband = intel_crtc_vblank_length(crtc_state); 6866 + int min_sdp_guardband = intel_dp_sdp_min_guardband(crtc_state, false); 6867 + 6868 + if (guardband < min_sdp_guardband) { 6869 + drm_dbg_kms(display->drm, "guardband %d < min sdp guardband %d\n", 6870 + guardband, min_sdp_guardband); 6871 + return -EINVAL; 6872 + } 6873 + 6874 + return 0; 6875 + } 6876 + 6877 + int intel_dp_compute_config_late(struct intel_encoder *encoder, 6878 + struct intel_crtc_state *crtc_state, 6879 + struct drm_connector_state *conn_state) 6880 + { 6881 + struct intel_dp *intel_dp = enc_to_intel_dp(encoder); 6882 + int ret; 6883 + 6884 + intel_psr_compute_config_late(intel_dp, crtc_state); 6885 + 6886 + ret = intel_dp_sdp_compute_config_late(crtc_state); 6887 + if (ret) 6888 + return ret; 6889 + 6890 + return 0; 6891 + } 6892 + 6893 + static 6894 + int intel_dp_get_lines_for_sdp(const struct intel_crtc_state *crtc_state, u32 type) 6895 + { 6896 + switch (type) { 6897 + case DP_SDP_VSC_EXT_VESA: 6898 + case DP_SDP_VSC_EXT_CEA: 6899 + return 10; 6900 + case HDMI_PACKET_TYPE_GAMUT_METADATA: 6901 + return 8; 6902 + case DP_SDP_PPS: 6903 + return 7; 6904 + case DP_SDP_ADAPTIVE_SYNC: 6905 + return crtc_state->vrr.vsync_start + 1; 6906 + default: 6907 + break; 6908 + } 6909 + 6910 + return 0; 6911 + } 6912 + 6913 + int intel_dp_sdp_min_guardband(const struct intel_crtc_state *crtc_state, 6914 + bool assume_all_enabled) 6915 + { 6916 + struct intel_display *display = to_intel_display(crtc_state); 6917 + int sdp_guardband = 0; 6918 + 6919 + if (assume_all_enabled || 6920 + crtc_state->infoframes.enable & 6921 + intel_hdmi_infoframe_enable(HDMI_PACKET_TYPE_GAMUT_METADATA)) 6922 + sdp_guardband = max(sdp_guardband, 6923 + intel_dp_get_lines_for_sdp(crtc_state, 6924 + HDMI_PACKET_TYPE_GAMUT_METADATA)); 6925 + 6926 + if (assume_all_enabled || 6927 + crtc_state->dsc.compression_enable) 6928 + sdp_guardband = max(sdp_guardband, 6929 + intel_dp_get_lines_for_sdp(crtc_state, DP_SDP_PPS)); 6930 + 6931 + if ((assume_all_enabled && HAS_AS_SDP(display)) || 6932 + crtc_state->infoframes.enable & intel_hdmi_infoframe_enable(DP_SDP_ADAPTIVE_SYNC)) 6933 + sdp_guardband = max(sdp_guardband, 6934 + intel_dp_get_lines_for_sdp(crtc_state, DP_SDP_ADAPTIVE_SYNC)); 6935 + 6936 + return sdp_guardband; 6992 6937 }
+11 -1
drivers/gpu/drm/i915/display/intel_dp.h
··· 12 12 enum pipe; 13 13 enum port; 14 14 struct drm_connector_state; 15 + struct drm_dp_desc; 15 16 struct drm_dp_vsc_sdp; 16 17 struct drm_encoder; 17 18 struct drm_modeset_acquire_ctx; ··· 73 72 int intel_dp_compute_config(struct intel_encoder *encoder, 74 73 struct intel_crtc_state *pipe_config, 75 74 struct drm_connector_state *conn_state); 75 + bool intel_dp_needs_8b10b_fec(const struct intel_crtc_state *crtc_state, 76 + bool dsc_enabled_on_crtc); 76 77 int intel_dp_dsc_compute_config(struct intel_dp *intel_dp, 77 78 struct intel_crtc_state *pipe_config, 78 79 struct drm_connector_state *conn_state, ··· 202 199 bool dsc, 203 200 struct link_config_limits *limits); 204 201 205 - void intel_dp_get_dsc_sink_cap(u8 dpcd_rev, struct intel_connector *connector); 202 + void intel_dp_get_dsc_sink_cap(u8 dpcd_rev, 203 + const struct drm_dp_desc *desc, bool is_branch, 204 + struct intel_connector *connector); 206 205 bool intel_dp_has_gamut_metadata_dip(struct intel_encoder *encoder); 207 206 208 207 bool intel_dp_link_params_valid(struct intel_dp *intel_dp, int link_rate, ··· 220 215 int intel_dp_dsc_bpp_step_x16(const struct intel_connector *connector); 221 216 void intel_dp_dpcd_set_probe(struct intel_dp *intel_dp, bool force_on_external); 222 217 bool intel_dp_in_hdr_mode(const struct drm_connector_state *conn_state); 218 + int intel_dp_compute_config_late(struct intel_encoder *encoder, 219 + struct intel_crtc_state *crtc_state, 220 + struct drm_connector_state *conn_state); 221 + int intel_dp_sdp_min_guardband(const struct intel_crtc_state *crtc_state, 222 + bool assume_all_enabled); 223 223 224 224 #endif /* __INTEL_DP_H__ */
+1 -1
drivers/gpu/drm/i915/display/intel_dp_aux.c
··· 5 5 6 6 #include <drm/drm_print.h> 7 7 8 - #include "i915_utils.h" 9 8 #include "intel_de.h" 10 9 #include "intel_display_types.h" 10 + #include "intel_display_utils.h" 11 11 #include "intel_dp.h" 12 12 #include "intel_dp_aux.h" 13 13 #include "intel_dp_aux_regs.h"
+33 -16
drivers/gpu/drm/i915/display/intel_dp_mst.c
··· 33 33 #include <drm/drm_print.h> 34 34 #include <drm/drm_probe_helper.h> 35 35 36 - #include "i915_utils.h" 37 36 #include "intel_atomic.h" 38 37 #include "intel_audio.h" 39 38 #include "intel_connector.h" ··· 42 43 #include "intel_display_driver.h" 43 44 #include "intel_display_regs.h" 44 45 #include "intel_display_types.h" 46 + #include "intel_display_utils.h" 45 47 #include "intel_dp.h" 46 48 #include "intel_dp_hdcp.h" 47 49 #include "intel_dp_link_training.h" ··· 293 293 mst_stream_update_slots(crtc_state, mst_state); 294 294 } 295 295 296 - if (dsc) { 297 - if (!intel_dp_supports_fec(intel_dp, connector, crtc_state)) 298 - return -EINVAL; 299 - 300 - crtc_state->fec_enable = !intel_dp_is_uhbr(crtc_state); 301 - } 296 + /* 297 + * NOTE: The following must reset crtc_state->fec_enable for UHBR/DSC 298 + * after it was set by intel_dp_dsc_compute_config() -> 299 + * intel_dp_needs_8b10b_fec(). 300 + */ 301 + crtc_state->fec_enable = intel_dp_needs_8b10b_fec(crtc_state, dsc); 302 + /* 303 + * If FEC gets enabled only because of another compressed stream, FEC 304 + * may not be supported for this uncompressed stream on the whole link 305 + * path until the sink DPRX. In this case a downstream branch device 306 + * will disable FEC for the uncompressed stream as expected and so the 307 + * FEC support doesn't need to be checked for this uncompressed stream. 308 + */ 309 + if (crtc_state->fec_enable && dsc && 310 + !intel_dp_supports_fec(intel_dp, connector, crtc_state)) 311 + return -EINVAL; 302 312 303 313 max_dpt_bpp_x16 = fxp_q4_from_int(intel_dp_mst_max_dpt_bpp(crtc_state, dsc)); 304 314 if (max_dpt_bpp_x16 && max_bpp_x16 > max_dpt_bpp_x16) { ··· 821 811 return mask; 822 812 } 823 813 824 - static int intel_dp_mst_check_fec_change(struct intel_atomic_state *state, 814 + static int intel_dp_mst_check_dsc_change(struct intel_atomic_state *state, 825 815 struct drm_dp_mst_topology_mgr *mst_mgr, 826 816 struct intel_link_bw_limits *limits) 827 817 { 828 818 struct intel_display *display = to_intel_display(state); 829 819 struct intel_crtc *crtc; 830 820 u8 mst_pipe_mask; 831 - u8 fec_pipe_mask = 0; 821 + u8 dsc_pipe_mask = 0; 832 822 int ret; 833 823 834 824 mst_pipe_mask = get_pipes_downstream_of_mst_port(state, mst_mgr, NULL); ··· 841 831 if (drm_WARN_ON(display->drm, !crtc_state)) 842 832 return -EINVAL; 843 833 844 - if (crtc_state->fec_enable) 845 - fec_pipe_mask |= BIT(crtc->pipe); 834 + if (intel_dsc_enabled_on_link(crtc_state)) 835 + dsc_pipe_mask |= BIT(crtc->pipe); 846 836 } 847 837 848 - if (!fec_pipe_mask || mst_pipe_mask == fec_pipe_mask) 838 + if (!dsc_pipe_mask || mst_pipe_mask == dsc_pipe_mask) 849 839 return 0; 850 840 851 - limits->force_fec_pipes |= mst_pipe_mask; 841 + limits->link_dsc_pipes |= mst_pipe_mask; 852 842 853 - ret = intel_modeset_pipes_in_mask_early(state, "MST FEC", 843 + ret = intel_modeset_pipes_in_mask_early(state, "MST DSC", 854 844 mst_pipe_mask); 855 845 856 846 return ret ? : -EAGAIN; ··· 904 894 int i; 905 895 906 896 for_each_new_mst_mgr_in_state(&state->base, mgr, mst_state, i) { 907 - ret = intel_dp_mst_check_fec_change(state, mgr, limits); 897 + ret = intel_dp_mst_check_dsc_change(state, mgr, limits); 908 898 if (ret) 909 899 return ret; 910 900 ··· 1668 1658 struct intel_connector *connector) 1669 1659 { 1670 1660 u8 dpcd_caps[DP_RECEIVER_CAP_SIZE]; 1661 + struct drm_dp_desc desc; 1671 1662 1672 1663 if (!connector->dp.dsc_decompression_aux) 1673 1664 return; ··· 1676 1665 if (drm_dp_read_dpcd_caps(connector->dp.dsc_decompression_aux, dpcd_caps) < 0) 1677 1666 return; 1678 1667 1679 - intel_dp_get_dsc_sink_cap(dpcd_caps[DP_DPCD_REV], connector); 1668 + if (drm_dp_read_desc(connector->dp.dsc_decompression_aux, &desc, 1669 + drm_dp_is_branch(dpcd_caps)) < 0) 1670 + return; 1671 + 1672 + intel_dp_get_dsc_sink_cap(dpcd_caps[DP_DPCD_REV], 1673 + &desc, drm_dp_is_branch(dpcd_caps), 1674 + connector); 1680 1675 } 1681 1676 1682 1677 static bool detect_dsc_hblank_expansion_quirk(const struct intel_connector *connector)
+1 -1
drivers/gpu/drm/i915/display/intel_dpio_phy.c
··· 24 24 #include <drm/drm_print.h> 25 25 26 26 #include "bxt_dpio_phy_regs.h" 27 - #include "i915_utils.h" 28 27 #include "intel_ddi.h" 29 28 #include "intel_ddi_buf_trans.h" 30 29 #include "intel_de.h" 31 30 #include "intel_display_power_well.h" 32 31 #include "intel_display_regs.h" 33 32 #include "intel_display_types.h" 33 + #include "intel_display_utils.h" 34 34 #include "intel_dp.h" 35 35 #include "intel_dpio_phy.h" 36 36 #include "vlv_dpio_phy_regs.h"
+30 -1
drivers/gpu/drm/i915/display/intel_dpll.c
··· 17 17 #include "intel_display_types.h" 18 18 #include "intel_dpio_phy.h" 19 19 #include "intel_dpll.h" 20 + #include "intel_lt_phy.h" 20 21 #include "intel_lvds.h" 21 22 #include "intel_lvds_regs.h" 22 23 #include "intel_panel.h" ··· 1233 1232 return 0; 1234 1233 } 1235 1234 1235 + static int xe3plpd_crtc_compute_clock(struct intel_atomic_state *state, 1236 + struct intel_crtc *crtc) 1237 + { 1238 + struct intel_crtc_state *crtc_state = 1239 + intel_atomic_get_new_crtc_state(state, crtc); 1240 + struct intel_encoder *encoder = 1241 + intel_get_crtc_new_encoder(state, crtc_state); 1242 + int ret; 1243 + 1244 + ret = intel_lt_phy_pll_calc_state(crtc_state, encoder); 1245 + if (ret) 1246 + return ret; 1247 + 1248 + /* TODO: Do the readback via intel_compute_shared_dplls() */ 1249 + crtc_state->port_clock = 1250 + intel_lt_phy_calc_port_clock(encoder, crtc_state); 1251 + 1252 + crtc_state->hw.adjusted_mode.crtc_clock = intel_crtc_dotclock(crtc_state); 1253 + 1254 + return 0; 1255 + } 1256 + 1236 1257 static int ilk_fb_cb_factor(const struct intel_crtc_state *crtc_state) 1237 1258 { 1238 1259 struct intel_display *display = to_intel_display(crtc_state); ··· 1714 1691 return 0; 1715 1692 } 1716 1693 1694 + static const struct intel_dpll_global_funcs xe3plpd_dpll_funcs = { 1695 + .crtc_compute_clock = xe3plpd_crtc_compute_clock, 1696 + }; 1697 + 1717 1698 static const struct intel_dpll_global_funcs mtl_dpll_funcs = { 1718 1699 .crtc_compute_clock = mtl_crtc_compute_clock, 1719 1700 }; ··· 1816 1789 void 1817 1790 intel_dpll_init_clock_hook(struct intel_display *display) 1818 1791 { 1819 - if (DISPLAY_VER(display) >= 14) 1792 + if (HAS_LT_PHY(display)) 1793 + display->funcs.dpll = &xe3plpd_dpll_funcs; 1794 + else if (DISPLAY_VER(display) >= 14) 1820 1795 display->funcs.dpll = &mtl_dpll_funcs; 1821 1796 else if (display->platform.dg2) 1822 1797 display->funcs.dpll = &dg2_dpll_funcs;
+1 -1
drivers/gpu/drm/i915/display/intel_dpll_mgr.c
··· 27 27 #include <drm/drm_print.h> 28 28 29 29 #include "bxt_dpio_phy_regs.h" 30 - #include "i915_utils.h" 31 30 #include "intel_cx0_phy.h" 32 31 #include "intel_de.h" 33 32 #include "intel_display_regs.h" 34 33 #include "intel_display_types.h" 34 + #include "intel_display_utils.h" 35 35 #include "intel_dkl_phy.h" 36 36 #include "intel_dkl_phy_regs.h" 37 37 #include "intel_dpio_phy.h"
+11
drivers/gpu/drm/i915/display/intel_dpll_mgr.h
··· 267 267 bool tbt_mode; 268 268 }; 269 269 270 + struct intel_lt_phy_pll_state { 271 + u32 clock; /* in kHz */ 272 + u8 addr_msb[13]; 273 + u8 addr_lsb[13]; 274 + u8 data[13][4]; 275 + u8 config[3]; 276 + bool ssc_enabled; 277 + bool tbt_mode; 278 + }; 279 + 270 280 struct intel_dpll_hw_state { 271 281 union { 272 282 struct i9xx_dpll_hw_state i9xx; ··· 286 276 struct icl_dpll_hw_state icl; 287 277 struct intel_mpllb_state mpllb; 288 278 struct intel_cx0pll_state cx0pll; 279 + struct intel_lt_phy_pll_state ltpll; 289 280 }; 290 281 }; 291 282
+33 -24
drivers/gpu/drm/i915/display/intel_dsb.c
··· 115 115 return old_crtc_state->vrr.enable && !intel_crtc_vrr_disabling(state, crtc); 116 116 } 117 117 118 - static int dsb_vblank_delay(struct intel_atomic_state *state, 119 - struct intel_crtc *crtc) 120 - { 121 - const struct intel_crtc_state *crtc_state = 122 - intel_pre_commit_crtc_state(state, crtc); 123 - 124 - if (pre_commit_is_vrr_active(state, crtc)) 125 - /* 126 - * When the push is sent during vblank it will trigger 127 - * on the next scanline, hence we have up to one extra 128 - * scanline until the delayed vblank occurs after 129 - * TRANS_PUSH has been written. 130 - */ 131 - return intel_vrr_vblank_delay(crtc_state) + 1; 132 - else 133 - return intel_mode_vblank_delay(&crtc_state->hw.adjusted_mode); 134 - } 135 - 136 118 static int dsb_vtotal(struct intel_atomic_state *state, 137 119 struct intel_crtc *crtc) 138 120 { ··· 705 723 intel_dsb_emit_wait_dsl(dsb, DSB_OPCODE_WAIT_DSL_OUT, 0, 0); 706 724 707 725 if (pre_commit_is_vrr_active(state, crtc)) { 708 - int vblank_delay = intel_vrr_vblank_delay(crtc_state); 726 + int vblank_delay = crtc_state->set_context_latency; 709 727 710 728 end = intel_vrr_vmin_vblank_start(crtc_state); 711 729 start = end - vblank_delay - latency; ··· 797 815 wait_for_vblank ? DSB_WAIT_FOR_VBLANK : 0); 798 816 } 799 817 800 - void intel_dsb_wait_vblank_delay(struct intel_atomic_state *state, 801 - struct intel_dsb *dsb) 818 + void intel_dsb_wait_for_delayed_vblank(struct intel_atomic_state *state, 819 + struct intel_dsb *dsb) 802 820 { 803 821 struct intel_crtc *crtc = dsb->crtc; 804 822 const struct intel_crtc_state *crtc_state = 805 823 intel_pre_commit_crtc_state(state, crtc); 806 - int usecs = intel_scanlines_to_usecs(&crtc_state->hw.adjusted_mode, 807 - dsb_vblank_delay(state, crtc)); 824 + const struct drm_display_mode *adjusted_mode = 825 + &crtc_state->hw.adjusted_mode; 826 + int wait_scanlines; 808 827 809 - intel_dsb_wait_usec(dsb, usecs); 828 + if (pre_commit_is_vrr_active(state, crtc)) { 829 + /* 830 + * If the push happened before the vmin decision boundary 831 + * we don't know how far we are from the undelayed vblank. 832 + * Wait until we're past the vmin safe window, at which 833 + * point we're SCL lines away from the delayed vblank. 834 + * 835 + * If the push happened after the vmin decision boundary 836 + * the hardware itself guarantees that we're SCL lines 837 + * away from the delayed vblank, and we won't be inside 838 + * the vmin safe window so this extra wait does nothing. 839 + */ 840 + intel_dsb_wait_scanline_out(state, dsb, 841 + intel_vrr_safe_window_start(crtc_state), 842 + intel_vrr_vmin_safe_window_end(crtc_state)); 843 + /* 844 + * When the push is sent during vblank it will trigger 845 + * on the next scanline, hence we have up to one extra 846 + * scanline until the delayed vblank occurs after 847 + * TRANS_PUSH has been written. 848 + */ 849 + wait_scanlines = crtc_state->set_context_latency + 1; 850 + } else { 851 + wait_scanlines = intel_mode_vblank_delay(adjusted_mode); 852 + } 853 + 854 + intel_dsb_wait_usec(dsb, intel_scanlines_to_usecs(adjusted_mode, wait_scanlines)); 810 855 } 811 856 812 857 /**
+2 -2
drivers/gpu/drm/i915/display/intel_dsb.h
··· 48 48 void intel_dsb_interrupt(struct intel_dsb *dsb); 49 49 void intel_dsb_wait_usec(struct intel_dsb *dsb, int count); 50 50 void intel_dsb_wait_vblanks(struct intel_dsb *dsb, int count); 51 - void intel_dsb_wait_vblank_delay(struct intel_atomic_state *state, 52 - struct intel_dsb *dsb); 51 + void intel_dsb_wait_for_delayed_vblank(struct intel_atomic_state *state, 52 + struct intel_dsb *dsb); 53 53 void intel_dsb_wait_scanline_in(struct intel_atomic_state *state, 54 54 struct intel_dsb *dsb, 55 55 int lower, int upper);
+21 -13
drivers/gpu/drm/i915/display/intel_dsi_vbt.c
··· 38 38 #include <drm/drm_print.h> 39 39 #include <video/mipi_display.h> 40 40 41 - #include "i915_utils.h" 42 41 #include "intel_de.h" 43 42 #include "intel_display_regs.h" 44 43 #include "intel_display_types.h" 44 + #include "intel_display_utils.h" 45 45 #include "intel_dsi.h" 46 46 #include "intel_dsi_vbt.h" 47 47 #include "intel_gmbus_regs.h" ··· 106 106 u8 type, flags, seq_port; 107 107 u16 len; 108 108 enum port port; 109 - 110 - drm_dbg_kms(display->drm, "\n"); 109 + ssize_t ret; 110 + bool hs_mode; 111 111 112 112 flags = *data++; 113 113 type = *data++; ··· 129 129 goto out; 130 130 } 131 131 132 - if ((flags >> MIPI_TRANSFER_MODE_SHIFT) & 1) 132 + hs_mode = (flags >> MIPI_TRANSFER_MODE_SHIFT) & 1; 133 + if (hs_mode) 133 134 dsi_device->mode_flags &= ~MIPI_DSI_MODE_LPM; 134 135 else 135 136 dsi_device->mode_flags |= MIPI_DSI_MODE_LPM; 136 137 137 138 dsi_device->channel = (flags >> MIPI_VIRTUAL_CHANNEL_SHIFT) & 3; 138 139 140 + drm_dbg_kms(display->drm, "DSI packet: Port %c (seq %u), Flags 0x%02x, VC %u, %s, Type 0x%02x, Length %u, Data %*ph\n", 141 + port_name(port), seq_port, flags, dsi_device->channel, 142 + hs_mode ? "HS" : "LP", type, len, (int)len, data); 143 + 139 144 switch (type) { 140 145 case MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM: 141 - mipi_dsi_generic_write(dsi_device, NULL, 0); 146 + ret = mipi_dsi_generic_write(dsi_device, NULL, 0); 142 147 break; 143 148 case MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM: 144 - mipi_dsi_generic_write(dsi_device, data, 1); 149 + ret = mipi_dsi_generic_write(dsi_device, data, 1); 145 150 break; 146 151 case MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM: 147 - mipi_dsi_generic_write(dsi_device, data, 2); 152 + ret = mipi_dsi_generic_write(dsi_device, data, 2); 148 153 break; 149 154 case MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM: 150 155 case MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM: 151 156 case MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM: 152 - drm_dbg_kms(display->drm, "Generic Read not yet implemented or used\n"); 157 + ret = -EOPNOTSUPP; 153 158 break; 154 159 case MIPI_DSI_GENERIC_LONG_WRITE: 155 - mipi_dsi_generic_write(dsi_device, data, len); 160 + ret = mipi_dsi_generic_write(dsi_device, data, len); 156 161 break; 157 162 case MIPI_DSI_DCS_SHORT_WRITE: 158 - mipi_dsi_dcs_write_buffer(dsi_device, data, 1); 163 + ret = mipi_dsi_dcs_write_buffer(dsi_device, data, 1); 159 164 break; 160 165 case MIPI_DSI_DCS_SHORT_WRITE_PARAM: 161 - mipi_dsi_dcs_write_buffer(dsi_device, data, 2); 166 + ret = mipi_dsi_dcs_write_buffer(dsi_device, data, 2); 162 167 break; 163 168 case MIPI_DSI_DCS_READ: 164 - drm_dbg_kms(display->drm, "DCS Read not yet implemented or used\n"); 169 + ret = -EOPNOTSUPP; 165 170 break; 166 171 case MIPI_DSI_DCS_LONG_WRITE: 167 - mipi_dsi_dcs_write_buffer(dsi_device, data, len); 172 + ret = mipi_dsi_dcs_write_buffer(dsi_device, data, len); 168 173 break; 169 174 } 175 + 176 + if (ret < 0) 177 + drm_err(display->drm, "DSI send packet failed with %pe\n", ERR_PTR(ret)); 170 178 171 179 if (DISPLAY_VER(display) < 11) 172 180 vlv_dsi_wait_for_fifo_empty(intel_dsi, port);
+1 -1
drivers/gpu/drm/i915/display/intel_dvo.c
··· 34 34 #include <drm/drm_print.h> 35 35 #include <drm/drm_probe_helper.h> 36 36 37 - #include "i915_utils.h" 38 37 #include "intel_connector.h" 39 38 #include "intel_de.h" 40 39 #include "intel_display_driver.h" 41 40 #include "intel_display_regs.h" 42 41 #include "intel_display_types.h" 42 + #include "intel_display_utils.h" 43 43 #include "intel_dvo.h" 44 44 #include "intel_dvo_dev.h" 45 45 #include "intel_dvo_regs.h"
+19 -22
drivers/gpu/drm/i915/display/intel_fb.c
··· 10 10 #include <drm/drm_gem.h> 11 11 #include <drm/drm_modeset_helper.h> 12 12 13 - #include "i915_drv.h" 14 - #include "i915_utils.h" 15 13 #include "intel_bo.h" 16 14 #include "intel_display.h" 17 15 #include "intel_display_core.h" 18 16 #include "intel_display_types.h" 17 + #include "intel_display_utils.h" 19 18 #include "intel_dpt.h" 20 19 #include "intel_fb.h" 21 20 #include "intel_fb_bo.h" ··· 546 547 u8 plane_caps, 547 548 const struct intel_modifier_desc *md) 548 549 { 549 - struct drm_i915_private *i915 = to_i915(display->drm); 550 - 551 550 if (!IS_DISPLAY_VER(display, md->display_ver.from, md->display_ver.until)) 552 551 return false; 553 552 ··· 557 560 * where supported. 558 561 */ 559 562 if (intel_fb_is_ccs_modifier(md->modifier) && 560 - HAS_FLAT_CCS(i915) != !md->ccs.packed_aux_planes) 563 + HAS_AUX_CCS(display) != !!md->ccs.packed_aux_planes) 561 564 return false; 562 565 563 566 if (md->modifier == I915_FORMAT_MOD_4_TILED_BMG_CCS && 564 - (GRAPHICS_VER(i915) < 20 || !display->platform.dgfx)) 567 + (DISPLAY_VER(display) < 14 || !display->platform.dgfx)) 565 568 return false; 566 569 567 570 if (md->modifier == I915_FORMAT_MOD_4_TILED_LNL_CCS && 568 - (GRAPHICS_VER(i915) < 20 || display->platform.dgfx)) 571 + (DISPLAY_VER(display) < 20 || display->platform.dgfx)) 569 572 return false; 570 573 571 574 return true; ··· 774 777 intel_tile_width_bytes(const struct drm_framebuffer *fb, int color_plane) 775 778 { 776 779 struct intel_display *display = to_intel_display(fb->dev); 777 - struct drm_i915_private *i915 = to_i915(display->drm); 778 780 unsigned int cpp = fb->format->cpp[color_plane]; 779 781 780 782 switch (fb->modifier) { ··· 810 814 return 64; 811 815 fallthrough; 812 816 case I915_FORMAT_MOD_Y_TILED: 813 - if (DISPLAY_VER(display) == 2 || HAS_128_BYTE_Y_TILING(i915)) 817 + if (HAS_128B_Y_TILING(display)) 814 818 return 128; 815 819 else 816 820 return 512; ··· 2113 2117 2114 2118 intel_frontbuffer_put(intel_fb->frontbuffer); 2115 2119 2120 + kfree(intel_fb->panic); 2116 2121 kfree(intel_fb); 2117 2122 } 2118 2123 ··· 2212 2215 struct intel_display *display = to_intel_display(obj->dev); 2213 2216 struct drm_framebuffer *fb = &intel_fb->base; 2214 2217 u32 max_stride; 2215 - int ret = -EINVAL; 2218 + int ret; 2216 2219 int i; 2220 + 2221 + intel_fb->panic = intel_panic_alloc(); 2222 + if (!intel_fb->panic) 2223 + return -ENOMEM; 2217 2224 2218 2225 /* 2219 2226 * intel_frontbuffer_get() must be done before 2220 2227 * intel_fb_bo_framebuffer_init() to avoid set_tiling vs. addfb race. 2221 2228 */ 2222 2229 intel_fb->frontbuffer = intel_frontbuffer_get(obj); 2223 - if (!intel_fb->frontbuffer) 2224 - return -ENOMEM; 2230 + if (!intel_fb->frontbuffer) { 2231 + ret = -ENOMEM; 2232 + goto err_free_panic; 2233 + } 2225 2234 2226 - ret = intel_fb_bo_framebuffer_init(fb, obj, mode_cmd); 2235 + ret = intel_fb_bo_framebuffer_init(obj, mode_cmd); 2227 2236 if (ret) 2228 2237 goto err_frontbuffer_put; 2229 2238 ··· 2326 2323 intel_fb_bo_framebuffer_fini(obj); 2327 2324 err_frontbuffer_put: 2328 2325 intel_frontbuffer_put(intel_fb->frontbuffer); 2326 + err_free_panic: 2327 + kfree(intel_fb->panic); 2328 + 2329 2329 return ret; 2330 2330 } 2331 2331 ··· 2355 2349 struct intel_framebuffer *intel_framebuffer_alloc(void) 2356 2350 { 2357 2351 struct intel_framebuffer *intel_fb; 2358 - struct intel_panic *panic; 2359 2352 2360 2353 intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL); 2361 2354 if (!intel_fb) 2362 2355 return NULL; 2363 - 2364 - panic = intel_panic_alloc(); 2365 - if (!panic) { 2366 - kfree(intel_fb); 2367 - return NULL; 2368 - } 2369 - 2370 - intel_fb->panic = panic; 2371 2356 2372 2357 return intel_fb; 2373 2358 }
+1 -2
drivers/gpu/drm/i915/display/intel_fb_bo.c
··· 18 18 /* Nothing to do for i915 */ 19 19 } 20 20 21 - int intel_fb_bo_framebuffer_init(struct drm_framebuffer *fb, 22 - struct drm_gem_object *_obj, 21 + int intel_fb_bo_framebuffer_init(struct drm_gem_object *_obj, 23 22 struct drm_mode_fb_cmd2 *mode_cmd) 24 23 { 25 24 struct drm_i915_gem_object *obj = to_intel_bo(_obj);
+1 -2
drivers/gpu/drm/i915/display/intel_fb_bo.h
··· 14 14 15 15 void intel_fb_bo_framebuffer_fini(struct drm_gem_object *obj); 16 16 17 - int intel_fb_bo_framebuffer_init(struct drm_framebuffer *fb, 18 - struct drm_gem_object *obj, 17 + int intel_fb_bo_framebuffer_init(struct drm_gem_object *obj, 19 18 struct drm_mode_fb_cmd2 *mode_cmd); 20 19 21 20 struct drm_gem_object *
+142 -56
drivers/gpu/drm/i915/display/intel_fbc.c
··· 49 49 #include "gt/intel_gt_types.h" 50 50 51 51 #include "i915_drv.h" 52 - #include "i915_utils.h" 53 52 #include "i915_vgpu.h" 54 53 #include "i915_vma.h" 55 54 #include "i9xx_plane_regs.h" 56 - #include "intel_cdclk.h" 57 55 #include "intel_de.h" 58 56 #include "intel_display_device.h" 59 57 #include "intel_display_regs.h" 60 58 #include "intel_display_rpm.h" 61 59 #include "intel_display_trace.h" 62 60 #include "intel_display_types.h" 61 + #include "intel_display_utils.h" 63 62 #include "intel_display_wa.h" 64 63 #include "intel_fbc.h" 65 64 #include "intel_fbc_regs.h" ··· 101 102 struct mutex lock; 102 103 unsigned int busy_bits; 103 104 104 - struct i915_stolen_fb compressed_fb, compressed_llb; 105 + struct intel_stolen_node *compressed_fb; 106 + struct intel_stolen_node *compressed_llb; 105 107 106 108 enum intel_fbc_id id; 107 109 ··· 141 141 return stride; 142 142 } 143 143 144 - static unsigned int intel_fbc_cfb_cpp(void) 144 + static unsigned int intel_fbc_cfb_cpp(const struct intel_plane_state *plane_state) 145 145 { 146 - return 4; /* FBC always 4 bytes per pixel */ 146 + const struct drm_framebuffer *fb = plane_state->hw.fb; 147 + unsigned int cpp = fb->format->cpp[0]; 148 + 149 + return max(cpp, 4); 147 150 } 148 151 149 152 /* plane stride based cfb stride in bytes, assuming 1:1 compression limit */ 150 153 static unsigned int intel_fbc_plane_cfb_stride(const struct intel_plane_state *plane_state) 151 154 { 152 - unsigned int cpp = intel_fbc_cfb_cpp(); 155 + unsigned int cpp = intel_fbc_cfb_cpp(plane_state); 153 156 154 157 return intel_fbc_plane_stride(plane_state) * cpp; 155 158 } ··· 206 203 struct intel_display *display = to_intel_display(plane_state->uapi.plane->dev); 207 204 unsigned int stride = intel_fbc_plane_cfb_stride(plane_state); 208 205 unsigned int width = drm_rect_width(&plane_state->uapi.src) >> 16; 209 - unsigned int cpp = intel_fbc_cfb_cpp(); 206 + unsigned int cpp = intel_fbc_cfb_cpp(plane_state); 210 207 211 208 return _intel_fbc_cfb_stride(display, cpp, width, stride); 212 209 } ··· 379 376 static void i8xx_fbc_program_cfb(struct intel_fbc *fbc) 380 377 { 381 378 struct intel_display *display = fbc->display; 382 - struct drm_i915_private *i915 = to_i915(display->drm); 383 379 384 380 drm_WARN_ON(display->drm, 385 - range_end_overflows_t(u64, i915_gem_stolen_area_address(i915), 386 - i915_gem_stolen_node_offset(&fbc->compressed_fb), 381 + range_end_overflows_t(u64, i915_gem_stolen_area_address(display->drm), 382 + i915_gem_stolen_node_offset(fbc->compressed_fb), 387 383 U32_MAX)); 388 384 drm_WARN_ON(display->drm, 389 - range_end_overflows_t(u64, i915_gem_stolen_area_address(i915), 390 - i915_gem_stolen_node_offset(&fbc->compressed_llb), 385 + range_end_overflows_t(u64, i915_gem_stolen_area_address(display->drm), 386 + i915_gem_stolen_node_offset(fbc->compressed_llb), 391 387 U32_MAX)); 392 388 intel_de_write(display, FBC_CFB_BASE, 393 - i915_gem_stolen_node_address(i915, &fbc->compressed_fb)); 389 + i915_gem_stolen_node_address(fbc->compressed_fb)); 394 390 intel_de_write(display, FBC_LL_BASE, 395 - i915_gem_stolen_node_address(i915, &fbc->compressed_llb)); 391 + i915_gem_stolen_node_address(fbc->compressed_llb)); 396 392 } 397 393 398 394 static const struct intel_fbc_funcs i8xx_fbc_funcs = { ··· 499 497 struct intel_display *display = fbc->display; 500 498 501 499 intel_de_write(display, DPFC_CB_BASE, 502 - i915_gem_stolen_node_offset(&fbc->compressed_fb)); 500 + i915_gem_stolen_node_offset(fbc->compressed_fb)); 503 501 } 504 502 505 503 static const struct intel_fbc_funcs g4x_fbc_funcs = { ··· 568 566 struct intel_display *display = fbc->display; 569 567 570 568 intel_de_write(display, ILK_DPFC_CB_BASE(fbc->id), 571 - i915_gem_stolen_node_offset(&fbc->compressed_fb)); 569 + i915_gem_stolen_node_offset(fbc->compressed_fb)); 572 570 } 573 571 574 572 static const struct intel_fbc_funcs ilk_fbc_funcs = { ··· 799 797 800 798 static u64 intel_fbc_stolen_end(struct intel_display *display) 801 799 { 802 - struct drm_i915_private __maybe_unused *i915 = to_i915(display->drm); 803 800 u64 end; 804 801 805 802 /* The FBC hardware for BDW/SKL doesn't have access to the stolen ··· 807 806 * underruns, even if that range is not reserved by the BIOS. */ 808 807 if (display->platform.broadwell || 809 808 (DISPLAY_VER(display) == 9 && !display->platform.broxton)) 810 - end = i915_gem_stolen_area_size(i915) - 8 * 1024 * 1024; 809 + end = i915_gem_stolen_area_size(display->drm) - 8 * 1024 * 1024; 811 810 else 812 811 end = U64_MAX; 813 812 ··· 836 835 unsigned int size, int min_limit) 837 836 { 838 837 struct intel_display *display = fbc->display; 839 - struct drm_i915_private *i915 = to_i915(display->drm); 840 838 u64 end = intel_fbc_stolen_end(display); 841 839 int ret, limit = min_limit; 842 840 843 841 size /= limit; 844 842 845 843 /* Try to over-allocate to reduce reallocations and fragmentation. */ 846 - ret = i915_gem_stolen_insert_node_in_range(i915, &fbc->compressed_fb, 844 + ret = i915_gem_stolen_insert_node_in_range(fbc->compressed_fb, 847 845 size <<= 1, 4096, 0, end); 848 846 if (ret == 0) 849 847 return limit; 850 848 851 849 for (; limit <= intel_fbc_max_limit(display); limit <<= 1) { 852 - ret = i915_gem_stolen_insert_node_in_range(i915, &fbc->compressed_fb, 850 + ret = i915_gem_stolen_insert_node_in_range(fbc->compressed_fb, 853 851 size >>= 1, 4096, 0, end); 854 852 if (ret == 0) 855 853 return limit; ··· 861 861 unsigned int size, int min_limit) 862 862 { 863 863 struct intel_display *display = fbc->display; 864 - struct drm_i915_private *i915 = to_i915(display->drm); 865 864 int ret; 866 865 867 866 drm_WARN_ON(display->drm, 868 - i915_gem_stolen_node_allocated(&fbc->compressed_fb)); 867 + i915_gem_stolen_node_allocated(fbc->compressed_fb)); 869 868 drm_WARN_ON(display->drm, 870 - i915_gem_stolen_node_allocated(&fbc->compressed_llb)); 869 + i915_gem_stolen_node_allocated(fbc->compressed_llb)); 871 870 872 871 if (DISPLAY_VER(display) < 5 && !display->platform.g4x) { 873 - ret = i915_gem_stolen_insert_node(i915, &fbc->compressed_llb, 874 - 4096, 4096); 872 + ret = i915_gem_stolen_insert_node(fbc->compressed_llb, 4096, 4096); 875 873 if (ret) 876 874 goto err; 877 875 } ··· 885 887 886 888 drm_dbg_kms(display->drm, 887 889 "reserved %llu bytes of contiguous stolen space for FBC, limit: %d\n", 888 - i915_gem_stolen_node_size(&fbc->compressed_fb), fbc->limit); 890 + i915_gem_stolen_node_size(fbc->compressed_fb), fbc->limit); 889 891 return 0; 890 892 891 893 err_llb: 892 - if (i915_gem_stolen_node_allocated(&fbc->compressed_llb)) 893 - i915_gem_stolen_remove_node(i915, &fbc->compressed_llb); 894 + if (i915_gem_stolen_node_allocated(fbc->compressed_llb)) 895 + i915_gem_stolen_remove_node(fbc->compressed_llb); 894 896 err: 895 - if (i915_gem_stolen_initialized(i915)) 897 + if (i915_gem_stolen_initialized(display->drm)) 896 898 drm_info_once(display->drm, 897 899 "not enough stolen space for compressed buffer (need %d more bytes), disabling. Hint: you may be able to increase stolen memory size in the BIOS to avoid this.\n", size); 898 900 return -ENOSPC; ··· 930 932 if (IS_DISPLAY_VER(display, 11, 12)) 931 933 intel_de_rmw(display, ILK_DPFC_CHICKEN(fbc->id), 932 934 0, DPFC_CHICKEN_COMP_DUMMY_PIXEL); 933 - 934 - /* Wa_22014263786:icl,jsl,tgl,dg1,rkl,adls,adlp,mtl */ 935 - if (DISPLAY_VER(display) >= 11 && !display->platform.dg2) 935 + /* 936 + * Wa_22014263786 937 + * Fixes: Screen flicker with FBC and Package C state enabled 938 + * Workaround: Forced SLB invalidation before start of new frame. 939 + */ 940 + if (intel_display_wa(display, 22014263786)) 936 941 intel_de_rmw(display, ILK_DPFC_CHICKEN(fbc->id), 937 942 0, DPFC_CHICKEN_FORCE_SLB_INVALIDATION); 938 943 ··· 946 945 947 946 static void __intel_fbc_cleanup_cfb(struct intel_fbc *fbc) 948 947 { 949 - struct intel_display *display = fbc->display; 950 - struct drm_i915_private *i915 = to_i915(display->drm); 951 - 952 948 if (WARN_ON(intel_fbc_hw_is_active(fbc))) 953 949 return; 954 950 955 - if (i915_gem_stolen_node_allocated(&fbc->compressed_llb)) 956 - i915_gem_stolen_remove_node(i915, &fbc->compressed_llb); 957 - if (i915_gem_stolen_node_allocated(&fbc->compressed_fb)) 958 - i915_gem_stolen_remove_node(i915, &fbc->compressed_fb); 951 + if (i915_gem_stolen_node_allocated(fbc->compressed_llb)) 952 + i915_gem_stolen_remove_node(fbc->compressed_llb); 953 + if (i915_gem_stolen_node_allocated(fbc->compressed_fb)) 954 + i915_gem_stolen_remove_node(fbc->compressed_fb); 959 955 } 960 956 961 957 void intel_fbc_cleanup(struct intel_display *display) ··· 964 966 mutex_lock(&fbc->lock); 965 967 __intel_fbc_cleanup_cfb(fbc); 966 968 mutex_unlock(&fbc->lock); 969 + 970 + i915_gem_stolen_node_free(fbc->compressed_fb); 971 + i915_gem_stolen_node_free(fbc->compressed_llb); 967 972 968 973 kfree(fbc); 969 974 } ··· 1084 1083 } 1085 1084 } 1086 1085 1086 + static bool 1087 + xe3p_lpd_fbc_fp16_format_is_valid(const struct intel_plane_state *plane_state) 1088 + { 1089 + const struct drm_framebuffer *fb = plane_state->hw.fb; 1090 + 1091 + switch (fb->format->format) { 1092 + case DRM_FORMAT_ARGB16161616F: 1093 + case DRM_FORMAT_ABGR16161616F: 1094 + return true; 1095 + default: 1096 + return false; 1097 + } 1098 + } 1099 + 1100 + static bool xe3p_lpd_fbc_pixel_format_is_valid(const struct intel_plane_state *plane_state) 1101 + { 1102 + const struct drm_framebuffer *fb = plane_state->hw.fb; 1103 + 1104 + if (lnl_fbc_pixel_format_is_valid(plane_state)) 1105 + return true; 1106 + 1107 + if (xe3p_lpd_fbc_fp16_format_is_valid(plane_state)) 1108 + return true; 1109 + 1110 + switch (fb->format->format) { 1111 + case DRM_FORMAT_XRGB16161616: 1112 + case DRM_FORMAT_XBGR16161616: 1113 + case DRM_FORMAT_ARGB16161616: 1114 + case DRM_FORMAT_ABGR16161616: 1115 + return true; 1116 + default: 1117 + return false; 1118 + } 1119 + } 1120 + 1121 + bool 1122 + intel_fbc_is_enable_pixel_normalizer(const struct intel_plane_state *plane_state) 1123 + { 1124 + struct intel_display *display = to_intel_display(plane_state); 1125 + 1126 + return DISPLAY_VER(display) >= 35 && 1127 + xe3p_lpd_fbc_fp16_format_is_valid(plane_state); 1128 + } 1129 + 1087 1130 static bool pixel_format_is_valid(const struct intel_plane_state *plane_state) 1088 1131 { 1089 1132 struct intel_display *display = to_intel_display(plane_state->uapi.plane->dev); 1090 1133 1091 - if (DISPLAY_VER(display) >= 20) 1134 + if (DISPLAY_VER(display) >= 35) 1135 + return xe3p_lpd_fbc_pixel_format_is_valid(plane_state); 1136 + else if (DISPLAY_VER(display) >= 20) 1092 1137 return lnl_fbc_pixel_format_is_valid(plane_state); 1093 1138 else if (DISPLAY_VER(display) >= 5 || display->platform.g4x) 1094 1139 return g4x_fbc_pixel_format_is_valid(plane_state); ··· 1402 1355 1403 1356 return intel_fbc_min_limit(plane_state) <= fbc->limit && 1404 1357 intel_fbc_cfb_size(plane_state) <= fbc->limit * 1405 - i915_gem_stolen_node_size(&fbc->compressed_fb); 1358 + i915_gem_stolen_node_size(fbc->compressed_fb); 1406 1359 } 1407 1360 1408 1361 static bool intel_fbc_is_ok(const struct intel_plane_state *plane_state) ··· 1468 1421 } 1469 1422 } 1470 1423 1424 + static int _intel_fbc_min_cdclk(const struct intel_crtc_state *crtc_state) 1425 + { 1426 + struct intel_display *display = to_intel_display(crtc_state); 1427 + 1428 + /* WaFbcExceedCdClockThreshold:hsw,bdw */ 1429 + if (display->platform.haswell || display->platform.broadwell) 1430 + return DIV_ROUND_UP(crtc_state->pixel_rate * 100, 95); 1431 + 1432 + /* no FBC specific limits to worry about */ 1433 + return 0; 1434 + } 1435 + 1471 1436 static int intel_fbc_check_plane(struct intel_atomic_state *state, 1472 1437 struct intel_plane *plane) 1473 1438 { ··· 1495 1436 if (!fbc) 1496 1437 return 0; 1497 1438 1498 - if (!i915_gem_stolen_initialized(i915)) { 1439 + if (!i915_gem_stolen_initialized(display->drm)) { 1499 1440 plane_state->no_fbc_reason = "stolen memory not initialised"; 1500 1441 return 0; 1501 1442 } ··· 1521 1462 } 1522 1463 1523 1464 /* WaFbcTurnOffFbcWhenHyperVisorIsUsed:skl,bxt */ 1524 - if (i915_vtd_active(i915) && (display->platform.skylake || display->platform.broxton)) { 1465 + if (intel_display_vtd_active(display) && 1466 + (display->platform.skylake || display->platform.broxton)) { 1525 1467 plane_state->no_fbc_reason = "VT-d enabled"; 1526 1468 return 0; 1527 1469 } ··· 1620 1560 return 0; 1621 1561 } 1622 1562 1623 - /* WaFbcExceedCdClockThreshold:hsw,bdw */ 1624 - if (display->platform.haswell || display->platform.broadwell) { 1625 - const struct intel_cdclk_state *cdclk_state; 1626 - 1627 - cdclk_state = intel_atomic_get_cdclk_state(state); 1628 - if (IS_ERR(cdclk_state)) 1629 - return PTR_ERR(cdclk_state); 1630 - 1631 - if (crtc_state->pixel_rate >= intel_cdclk_logical(cdclk_state) * 95 / 100) { 1632 - plane_state->no_fbc_reason = "pixel rate too high"; 1633 - return 0; 1634 - } 1563 + if (_intel_fbc_min_cdclk(crtc_state) > display->cdclk.max_cdclk_freq) { 1564 + plane_state->no_fbc_reason = "pixel rate too high"; 1565 + return 0; 1635 1566 } 1636 1567 1637 1568 plane_state->no_fbc_reason = NULL; ··· 1630 1579 return 0; 1631 1580 } 1632 1581 1582 + int intel_fbc_min_cdclk(const struct intel_crtc_state *crtc_state) 1583 + { 1584 + struct intel_display *display = to_intel_display(crtc_state); 1585 + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 1586 + struct intel_plane *plane = to_intel_plane(crtc->base.primary); 1587 + int min_cdclk; 1588 + 1589 + if (!plane->fbc) 1590 + return 0; 1591 + 1592 + min_cdclk = _intel_fbc_min_cdclk(crtc_state); 1593 + 1594 + /* 1595 + * Do not ask for more than the max CDCLK frequency, 1596 + * if that is not enough FBC will simply not be used. 1597 + */ 1598 + if (min_cdclk > display->cdclk.max_cdclk_freq) 1599 + return 0; 1600 + 1601 + return min_cdclk; 1602 + } 1633 1603 1634 1604 static bool intel_fbc_can_flip_nuke(struct intel_atomic_state *state, 1635 1605 struct intel_crtc *crtc, ··· 2155 2083 if (!fbc) 2156 2084 return NULL; 2157 2085 2086 + fbc->compressed_fb = i915_gem_stolen_node_alloc(display->drm); 2087 + if (!fbc->compressed_fb) 2088 + goto err; 2089 + fbc->compressed_llb = i915_gem_stolen_node_alloc(display->drm); 2090 + if (!fbc->compressed_llb) 2091 + goto err; 2092 + 2158 2093 fbc->id = fbc_id; 2159 2094 fbc->display = display; 2160 2095 INIT_WORK(&fbc->underrun_work, intel_fbc_underrun_work_fn); ··· 2181 2102 fbc->funcs = &i8xx_fbc_funcs; 2182 2103 2183 2104 return fbc; 2105 + 2106 + err: 2107 + i915_gem_stolen_node_free(fbc->compressed_llb); 2108 + i915_gem_stolen_node_free(fbc->compressed_fb); 2109 + kfree(fbc); 2110 + 2111 + return NULL; 2184 2112 } 2185 2113 2186 2114 /**
+3
drivers/gpu/drm/i915/display/intel_fbc.h
··· 28 28 }; 29 29 30 30 int intel_fbc_atomic_check(struct intel_atomic_state *state); 31 + int intel_fbc_min_cdclk(const struct intel_crtc_state *crtc_state); 31 32 bool intel_fbc_pre_update(struct intel_atomic_state *state, 32 33 struct intel_crtc *crtc); 33 34 void intel_fbc_post_update(struct intel_atomic_state *state, ··· 53 52 struct intel_crtc *crtc); 54 53 void intel_fbc_dirty_rect_update_noarm(struct intel_dsb *dsb, 55 54 struct intel_plane *plane); 55 + bool 56 + intel_fbc_is_enable_pixel_normalizer(const struct intel_plane_state *plane_state); 56 57 57 58 #endif /* __INTEL_FBC_H__ */
+59 -2
drivers/gpu/drm/i915/display/intel_fbdev.c
··· 205 205 .fb_set_suspend = intelfb_set_suspend, 206 206 }; 207 207 208 + static void intel_fbdev_fill_mode_cmd(struct drm_fb_helper_surface_size *sizes, 209 + struct drm_mode_fb_cmd2 *mode_cmd) 210 + { 211 + /* we don't do packed 24bpp */ 212 + if (sizes->surface_bpp == 24) 213 + sizes->surface_bpp = 32; 214 + 215 + mode_cmd->flags = DRM_MODE_FB_MODIFIERS; 216 + mode_cmd->width = sizes->surface_width; 217 + mode_cmd->height = sizes->surface_height; 218 + 219 + mode_cmd->pitches[0] = intel_fbdev_fb_pitch_align(mode_cmd->width * DIV_ROUND_UP(sizes->surface_bpp, 8)); 220 + mode_cmd->pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, 221 + sizes->surface_depth); 222 + mode_cmd->modifier[0] = DRM_FORMAT_MOD_LINEAR; 223 + } 224 + 225 + static struct intel_framebuffer * 226 + __intel_fbdev_fb_alloc(struct intel_display *display, 227 + struct drm_fb_helper_surface_size *sizes) 228 + { 229 + struct drm_mode_fb_cmd2 mode_cmd = {}; 230 + struct drm_framebuffer *fb; 231 + struct drm_gem_object *obj; 232 + int size; 233 + 234 + intel_fbdev_fill_mode_cmd(sizes, &mode_cmd); 235 + 236 + size = mode_cmd.pitches[0] * mode_cmd.height; 237 + size = PAGE_ALIGN(size); 238 + 239 + obj = intel_fbdev_fb_bo_create(display->drm, size); 240 + if (IS_ERR(obj)) { 241 + fb = ERR_CAST(obj); 242 + goto err; 243 + } 244 + 245 + fb = intel_framebuffer_create(obj, 246 + drm_get_format_info(display->drm, 247 + mode_cmd.pixel_format, 248 + mode_cmd.modifier[0]), 249 + &mode_cmd); 250 + if (IS_ERR(fb)) { 251 + intel_fbdev_fb_bo_destroy(obj); 252 + goto err; 253 + } 254 + 255 + drm_gem_object_put(obj); 256 + 257 + return to_intel_framebuffer(fb); 258 + 259 + err: 260 + return ERR_CAST(fb); 261 + 262 + } 263 + 208 264 int intel_fbdev_driver_fbdev_probe(struct drm_fb_helper *helper, 209 265 struct drm_fb_helper_surface_size *sizes) 210 266 { ··· 291 235 if (!fb || drm_WARN_ON(display->drm, !intel_fb_bo(&fb->base))) { 292 236 drm_dbg_kms(display->drm, 293 237 "no BIOS fb, allocating a new one\n"); 294 - fb = intel_fbdev_fb_alloc(helper, sizes); 238 + 239 + fb = __intel_fbdev_fb_alloc(display, sizes); 295 240 if (IS_ERR(fb)) 296 241 return PTR_ERR(fb); 297 242 } else { ··· 332 275 333 276 obj = intel_fb_bo(&fb->base); 334 277 335 - ret = intel_fbdev_fb_fill_info(display, info, obj, vma); 278 + ret = intel_fbdev_fb_fill_info(display->drm, info, obj, vma); 336 279 if (ret) 337 280 goto out_unpin; 338 281
+19 -39
drivers/gpu/drm/i915/display/intel_fbdev_fb.c
··· 3 3 * Copyright © 2023 Intel Corporation 4 4 */ 5 5 6 - #include <drm/drm_fb_helper.h> 6 + #include <linux/fb.h> 7 7 8 8 #include "gem/i915_gem_lmem.h" 9 9 10 10 #include "i915_drv.h" 11 - #include "intel_display_core.h" 12 - #include "intel_display_types.h" 13 - #include "intel_fb.h" 14 11 #include "intel_fbdev_fb.h" 15 12 16 - struct intel_framebuffer *intel_fbdev_fb_alloc(struct drm_fb_helper *helper, 17 - struct drm_fb_helper_surface_size *sizes) 13 + u32 intel_fbdev_fb_pitch_align(u32 stride) 18 14 { 19 - struct intel_display *display = to_intel_display(helper->dev); 20 - struct drm_i915_private *dev_priv = to_i915(display->drm); 21 - struct drm_framebuffer *fb; 22 - struct drm_mode_fb_cmd2 mode_cmd = {}; 15 + return ALIGN(stride, 64); 16 + } 17 + 18 + struct drm_gem_object *intel_fbdev_fb_bo_create(struct drm_device *drm, int size) 19 + { 20 + struct drm_i915_private *dev_priv = to_i915(drm); 23 21 struct drm_i915_gem_object *obj; 24 - int size; 25 - 26 - /* we don't do packed 24bpp */ 27 - if (sizes->surface_bpp == 24) 28 - sizes->surface_bpp = 32; 29 - 30 - mode_cmd.width = sizes->surface_width; 31 - mode_cmd.height = sizes->surface_height; 32 - 33 - mode_cmd.pitches[0] = ALIGN(mode_cmd.width * 34 - DIV_ROUND_UP(sizes->surface_bpp, 8), 64); 35 - mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, 36 - sizes->surface_depth); 37 - 38 - size = mode_cmd.pitches[0] * mode_cmd.height; 39 - size = PAGE_ALIGN(size); 40 22 41 23 obj = ERR_PTR(-ENODEV); 42 24 if (HAS_LMEM(dev_priv)) { ··· 33 51 * 34 52 * Also skip stolen on MTL as Wa_22018444074 mitigation. 35 53 */ 36 - if (!display->platform.meteorlake && size * 2 < dev_priv->dsm.usable_size) 54 + if (!IS_METEORLAKE(dev_priv) && size * 2 < dev_priv->dsm.usable_size) 37 55 obj = i915_gem_object_create_stolen(dev_priv, size); 38 56 if (IS_ERR(obj)) 39 57 obj = i915_gem_object_create_shmem(dev_priv, size); 40 58 } 41 59 42 60 if (IS_ERR(obj)) { 43 - drm_err(display->drm, "failed to allocate framebuffer (%pe)\n", obj); 61 + drm_err(drm, "failed to allocate framebuffer (%pe)\n", obj); 44 62 return ERR_PTR(-ENOMEM); 45 63 } 46 64 47 - fb = intel_framebuffer_create(intel_bo_to_drm_bo(obj), 48 - drm_get_format_info(display->drm, 49 - mode_cmd.pixel_format, 50 - mode_cmd.modifier[0]), 51 - &mode_cmd); 52 - i915_gem_object_put(obj); 53 - 54 - return to_intel_framebuffer(fb); 65 + return &obj->base; 55 66 } 56 67 57 - int intel_fbdev_fb_fill_info(struct intel_display *display, struct fb_info *info, 68 + void intel_fbdev_fb_bo_destroy(struct drm_gem_object *obj) 69 + { 70 + drm_gem_object_put(obj); 71 + } 72 + 73 + int intel_fbdev_fb_fill_info(struct drm_device *drm, struct fb_info *info, 58 74 struct drm_gem_object *_obj, struct i915_vma *vma) 59 75 { 60 - struct drm_i915_private *i915 = to_i915(display->drm); 76 + struct drm_i915_private *i915 = to_i915(drm); 61 77 struct drm_i915_gem_object *obj = to_intel_bo(_obj); 62 78 struct i915_gem_ww_ctx ww; 63 79 void __iomem *vaddr; ··· 87 107 88 108 vaddr = i915_vma_pin_iomap(vma); 89 109 if (IS_ERR(vaddr)) { 90 - drm_err(display->drm, 110 + drm_err(drm, 91 111 "Failed to remap framebuffer into virtual memory (%pe)\n", vaddr); 92 112 ret = PTR_ERR(vaddr); 93 113 continue;
+8 -6
drivers/gpu/drm/i915/display/intel_fbdev_fb.h
··· 6 6 #ifndef __INTEL_FBDEV_FB_H__ 7 7 #define __INTEL_FBDEV_FB_H__ 8 8 9 - struct drm_fb_helper; 10 - struct drm_fb_helper_surface_size; 9 + #include <linux/types.h> 10 + 11 + struct drm_device; 11 12 struct drm_gem_object; 13 + struct drm_mode_fb_cmd2; 12 14 struct fb_info; 13 15 struct i915_vma; 14 - struct intel_display; 15 16 16 - struct intel_framebuffer *intel_fbdev_fb_alloc(struct drm_fb_helper *helper, 17 - struct drm_fb_helper_surface_size *sizes); 18 - int intel_fbdev_fb_fill_info(struct intel_display *display, struct fb_info *info, 17 + u32 intel_fbdev_fb_pitch_align(u32 stride); 18 + struct drm_gem_object *intel_fbdev_fb_bo_create(struct drm_device *drm, int size); 19 + void intel_fbdev_fb_bo_destroy(struct drm_gem_object *obj); 20 + int intel_fbdev_fb_fill_info(struct drm_device *drm, struct fb_info *info, 19 21 struct drm_gem_object *obj, struct i915_vma *vma); 20 22 21 23 #endif
+1 -1
drivers/gpu/drm/i915/display/intel_fdi.c
··· 9 9 #include <drm/drm_print.h> 10 10 11 11 #include "i915_reg.h" 12 - #include "i915_utils.h" 13 12 #include "intel_atomic.h" 14 13 #include "intel_crtc.h" 15 14 #include "intel_ddi.h" 16 15 #include "intel_de.h" 17 16 #include "intel_display_regs.h" 18 17 #include "intel_display_types.h" 18 + #include "intel_display_utils.h" 19 19 #include "intel_dp.h" 20 20 #include "intel_fdi.h" 21 21 #include "intel_fdi_regs.h"
+3 -3
drivers/gpu/drm/i915/display/intel_flipq.c
··· 7 7 8 8 #include <drm/drm_print.h> 9 9 10 - #include "i915_utils.h" 11 - #include "intel_step.h" 12 10 #include "intel_crtc.h" 13 11 #include "intel_de.h" 14 12 #include "intel_display_core.h" 15 13 #include "intel_display_types.h" 16 - #include "intel_flipq.h" 14 + #include "intel_display_utils.h" 17 15 #include "intel_dmc.h" 18 16 #include "intel_dmc_regs.h" 19 17 #include "intel_dsb.h" 18 + #include "intel_flipq.h" 19 + #include "intel_step.h" 20 20 #include "intel_vblank.h" 21 21 #include "intel_vrr.h" 22 22
+1 -1
drivers/gpu/drm/i915/display/intel_hdcp.c
··· 19 19 #include <drm/intel/i915_component.h> 20 20 21 21 #include "i915_reg.h" 22 - #include "i915_utils.h" 23 22 #include "intel_connector.h" 24 23 #include "intel_de.h" 24 + #include "intel_display_jiffies.h" 25 25 #include "intel_display_power.h" 26 26 #include "intel_display_power_well.h" 27 27 #include "intel_display_regs.h"
-1
drivers/gpu/drm/i915/display/intel_hdcp_gsc.c
··· 9 9 #include "gt/intel_gt.h" 10 10 #include "gt/uc/intel_gsc_uc_heci_cmd_submit.h" 11 11 #include "i915_drv.h" 12 - #include "i915_utils.h" 13 12 #include "intel_hdcp_gsc.h" 14 13 15 14 struct intel_hdcp_gsc_context {
+15 -1
drivers/gpu/drm/i915/display/intel_hdmi.c
··· 45 45 #include <media/cec-notifier.h> 46 46 47 47 #include "g4x_hdmi.h" 48 - #include "i915_utils.h" 49 48 #include "intel_atomic.h" 50 49 #include "intel_audio.h" 51 50 #include "intel_connector.h" ··· 54 55 #include "intel_display_driver.h" 55 56 #include "intel_display_regs.h" 56 57 #include "intel_display_types.h" 58 + #include "intel_display_utils.h" 57 59 #include "intel_dp.h" 58 60 #include "intel_gmbus.h" 59 61 #include "intel_hdcp.h" ··· 67 67 #include "intel_pfit.h" 68 68 #include "intel_snps_phy.h" 69 69 #include "intel_vrr.h" 70 + 71 + bool intel_hdmi_is_frl(u32 clock) 72 + { 73 + switch (clock) { 74 + case 300000: /* 3 Gbps */ 75 + case 600000: /* 6 Gbps */ 76 + case 800000: /* 8 Gbps */ 77 + case 1000000: /* 10 Gbps */ 78 + case 1200000: /* 12 Gbps */ 79 + return true; 80 + default: 81 + return false; 82 + } 83 + } 70 84 71 85 static void 72 86 assert_hdmi_port_disabled(struct intel_hdmi *intel_hdmi)
+1
drivers/gpu/drm/i915/display/intel_hdmi.h
··· 60 60 int src_max_slices, int src_max_slice_width, 61 61 int hdmi_max_slices, int hdmi_throughput); 62 62 int intel_hdmi_dsc_get_slice_height(int vactive); 63 + bool intel_hdmi_is_frl(u32 clock); 63 64 64 65 void hsw_write_infoframe(struct intel_encoder *encoder, 65 66 const struct intel_crtc_state *crtc_state,
+2 -2
drivers/gpu/drm/i915/display/intel_hotplug.c
··· 28 28 29 29 #include "i915_drv.h" 30 30 #include "i915_irq.h" 31 - #include "i915_utils.h" 32 31 #include "intel_connector.h" 33 - #include "intel_display_power.h" 34 32 #include "intel_display_core.h" 33 + #include "intel_display_power.h" 35 34 #include "intel_display_rpm.h" 36 35 #include "intel_display_types.h" 36 + #include "intel_display_utils.h" 37 37 #include "intel_dp.h" 38 38 #include "intel_hdcp.h" 39 39 #include "intel_hotplug.h"
+4 -1
drivers/gpu/drm/i915/display/intel_hotplug_irq.c
··· 6 6 #include <drm/drm_print.h> 7 7 8 8 #include "i915_reg.h" 9 - #include "i915_utils.h" 10 9 #include "intel_de.h" 11 10 #include "intel_display_irq.h" 12 11 #include "intel_display_regs.h" 13 12 #include "intel_display_types.h" 13 + #include "intel_display_utils.h" 14 14 #include "intel_dp_aux.h" 15 15 #include "intel_gmbus.h" 16 16 #include "intel_hotplug.h" ··· 419 419 { 420 420 u32 hotplug_status = 0, hotplug_status_mask; 421 421 int i; 422 + 423 + if (!HAS_HOTPLUG(display)) 424 + return 0; 422 425 423 426 if (display->platform.g4x || 424 427 display->platform.valleyview || display->platform.cherryview)
+1 -1
drivers/gpu/drm/i915/display/intel_lspcon.c
··· 31 31 #include <drm/drm_edid.h> 32 32 #include <drm/drm_print.h> 33 33 34 - #include "i915_utils.h" 35 34 #include "intel_de.h" 36 35 #include "intel_display_regs.h" 37 36 #include "intel_display_types.h" 37 + #include "intel_display_utils.h" 38 38 #include "intel_dp.h" 39 39 #include "intel_hdmi.h" 40 40 #include "intel_lspcon.h"
+2000
drivers/gpu/drm/i915/display/intel_lt_phy.c
··· 1 + // SPDX-License-Identifier: MIT 2 + /* 3 + * Copyright © 2025 Intel Corporation 4 + */ 5 + 6 + #include <drm/drm_print.h> 7 + 8 + #include "i915_reg.h" 9 + #include "i915_utils.h" 10 + #include "intel_cx0_phy.h" 11 + #include "intel_cx0_phy_regs.h" 12 + #include "intel_ddi.h" 13 + #include "intel_ddi_buf_trans.h" 14 + #include "intel_de.h" 15 + #include "intel_display.h" 16 + #include "intel_display_types.h" 17 + #include "intel_dpll_mgr.h" 18 + #include "intel_hdmi.h" 19 + #include "intel_lt_phy.h" 20 + #include "intel_lt_phy_regs.h" 21 + #include "intel_panel.h" 22 + #include "intel_psr.h" 23 + #include "intel_tc.h" 24 + 25 + #define for_each_lt_phy_lane_in_mask(__lane_mask, __lane) \ 26 + for ((__lane) = 0; (__lane) < 2; (__lane)++) \ 27 + for_each_if((__lane_mask) & BIT(__lane)) 28 + 29 + #define INTEL_LT_PHY_LANE0 BIT(0) 30 + #define INTEL_LT_PHY_LANE1 BIT(1) 31 + #define INTEL_LT_PHY_BOTH_LANES (INTEL_LT_PHY_LANE1 |\ 32 + INTEL_LT_PHY_LANE0) 33 + #define MODE_DP 3 34 + 35 + static const struct intel_lt_phy_pll_state xe3plpd_lt_dp_rbr = { 36 + .clock = 162000, 37 + .config = { 38 + 0x83, 39 + 0x2d, 40 + 0x0, 41 + }, 42 + .addr_msb = { 43 + 0x87, 44 + 0x87, 45 + 0x87, 46 + 0x87, 47 + 0x88, 48 + 0x88, 49 + 0x88, 50 + 0x88, 51 + 0x88, 52 + 0x88, 53 + 0x88, 54 + 0x88, 55 + 0x88, 56 + }, 57 + .addr_lsb = { 58 + 0x10, 59 + 0x0c, 60 + 0x14, 61 + 0xe4, 62 + 0x0c, 63 + 0x10, 64 + 0x14, 65 + 0x18, 66 + 0x48, 67 + 0x40, 68 + 0x4c, 69 + 0x24, 70 + 0x44, 71 + }, 72 + .data = { 73 + { 0x0, 0x4c, 0x2, 0x0 }, 74 + { 0x5, 0xa, 0x2a, 0x20 }, 75 + { 0x80, 0x0, 0x0, 0x0 }, 76 + { 0x4, 0x4, 0x82, 0x28 }, 77 + { 0xfa, 0x16, 0x83, 0x11 }, 78 + { 0x80, 0x0f, 0xf9, 0x53 }, 79 + { 0x84, 0x26, 0x5, 0x4 }, 80 + { 0x0, 0xe0, 0x1, 0x0 }, 81 + { 0x4b, 0x48, 0x0, 0x0 }, 82 + { 0x27, 0x8, 0x0, 0x0 }, 83 + { 0x5a, 0x13, 0x29, 0x13 }, 84 + { 0x0, 0x5b, 0xe0, 0x0a }, 85 + { 0x0, 0x0, 0x0, 0x0 }, 86 + }, 87 + }; 88 + 89 + static const struct intel_lt_phy_pll_state xe3plpd_lt_dp_hbr1 = { 90 + .clock = 270000, 91 + .config = { 92 + 0x8b, 93 + 0x2d, 94 + 0x0, 95 + }, 96 + .addr_msb = { 97 + 0x87, 98 + 0x87, 99 + 0x87, 100 + 0x87, 101 + 0x88, 102 + 0x88, 103 + 0x88, 104 + 0x88, 105 + 0x88, 106 + 0x88, 107 + 0x88, 108 + 0x88, 109 + 0x88, 110 + }, 111 + .addr_lsb = { 112 + 0x10, 113 + 0x0c, 114 + 0x14, 115 + 0xe4, 116 + 0x0c, 117 + 0x10, 118 + 0x14, 119 + 0x18, 120 + 0x48, 121 + 0x40, 122 + 0x4c, 123 + 0x24, 124 + 0x44, 125 + }, 126 + .data = { 127 + { 0x0, 0x4c, 0x2, 0x0 }, 128 + { 0x3, 0xca, 0x34, 0xa0 }, 129 + { 0xe0, 0x0, 0x0, 0x0 }, 130 + { 0x5, 0x4, 0x81, 0xad }, 131 + { 0xfa, 0x11, 0x83, 0x11 }, 132 + { 0x80, 0x0f, 0xf9, 0x53 }, 133 + { 0x84, 0x26, 0x7, 0x4 }, 134 + { 0x0, 0xe0, 0x1, 0x0 }, 135 + { 0x43, 0x48, 0x0, 0x0 }, 136 + { 0x27, 0x8, 0x0, 0x0 }, 137 + { 0x5a, 0x13, 0x29, 0x13 }, 138 + { 0x0, 0x5b, 0xe0, 0x0d }, 139 + { 0x0, 0x0, 0x0, 0x0 }, 140 + }, 141 + }; 142 + 143 + static const struct intel_lt_phy_pll_state xe3plpd_lt_dp_hbr2 = { 144 + .clock = 540000, 145 + .config = { 146 + 0x93, 147 + 0x2d, 148 + 0x0, 149 + }, 150 + .addr_msb = { 151 + 0x87, 152 + 0x87, 153 + 0x87, 154 + 0x87, 155 + 0x88, 156 + 0x88, 157 + 0x88, 158 + 0x88, 159 + 0x88, 160 + 0x88, 161 + 0x88, 162 + 0x88, 163 + 0x88, 164 + }, 165 + .addr_lsb = { 166 + 0x10, 167 + 0x0c, 168 + 0x14, 169 + 0xe4, 170 + 0x0c, 171 + 0x10, 172 + 0x14, 173 + 0x18, 174 + 0x48, 175 + 0x40, 176 + 0x4c, 177 + 0x24, 178 + 0x44, 179 + }, 180 + .data = { 181 + { 0x0, 0x4c, 0x2, 0x0 }, 182 + { 0x1, 0x4d, 0x34, 0xa0 }, 183 + { 0xe0, 0x0, 0x0, 0x0 }, 184 + { 0xa, 0x4, 0x81, 0xda }, 185 + { 0xfa, 0x11, 0x83, 0x11 }, 186 + { 0x80, 0x0f, 0xf9, 0x53 }, 187 + { 0x84, 0x26, 0x7, 0x4 }, 188 + { 0x0, 0xe0, 0x1, 0x0 }, 189 + { 0x43, 0x48, 0x0, 0x0 }, 190 + { 0x27, 0x8, 0x0, 0x0 }, 191 + { 0x5a, 0x13, 0x29, 0x13 }, 192 + { 0x0, 0x5b, 0xe0, 0x0d }, 193 + { 0x0, 0x0, 0x0, 0x0 }, 194 + }, 195 + }; 196 + 197 + static const struct intel_lt_phy_pll_state xe3plpd_lt_dp_hbr3 = { 198 + .clock = 810000, 199 + .config = { 200 + 0x9b, 201 + 0x2d, 202 + 0x0, 203 + }, 204 + .addr_msb = { 205 + 0x87, 206 + 0x87, 207 + 0x87, 208 + 0x87, 209 + 0x88, 210 + 0x88, 211 + 0x88, 212 + 0x88, 213 + 0x88, 214 + 0x88, 215 + 0x88, 216 + 0x88, 217 + 0x88, 218 + }, 219 + .addr_lsb = { 220 + 0x10, 221 + 0x0c, 222 + 0x14, 223 + 0xe4, 224 + 0x0c, 225 + 0x10, 226 + 0x14, 227 + 0x18, 228 + 0x48, 229 + 0x40, 230 + 0x4c, 231 + 0x24, 232 + 0x44, 233 + }, 234 + .data = { 235 + { 0x0, 0x4c, 0x2, 0x0 }, 236 + { 0x1, 0x4a, 0x34, 0xa0 }, 237 + { 0xe0, 0x0, 0x0, 0x0 }, 238 + { 0x5, 0x4, 0x80, 0xa8 }, 239 + { 0xfa, 0x11, 0x83, 0x11 }, 240 + { 0x80, 0x0f, 0xf9, 0x53 }, 241 + { 0x84, 0x26, 0x7, 0x4 }, 242 + { 0x0, 0xe0, 0x1, 0x0 }, 243 + { 0x43, 0x48, 0x0, 0x0 }, 244 + { 0x27, 0x8, 0x0, 0x0 }, 245 + { 0x5a, 0x13, 0x29, 0x13 }, 246 + { 0x0, 0x5b, 0xe0, 0x0d }, 247 + { 0x0, 0x0, 0x0, 0x0 }, 248 + }, 249 + }; 250 + 251 + static const struct intel_lt_phy_pll_state xe3plpd_lt_dp_uhbr10 = { 252 + .clock = 1000000, 253 + .config = { 254 + 0x43, 255 + 0x2d, 256 + 0x0, 257 + }, 258 + .addr_msb = { 259 + 0x85, 260 + 0x85, 261 + 0x85, 262 + 0x85, 263 + 0x86, 264 + 0x86, 265 + 0x86, 266 + 0x86, 267 + 0x86, 268 + 0x86, 269 + 0x86, 270 + 0x86, 271 + 0x86, 272 + }, 273 + .addr_lsb = { 274 + 0x10, 275 + 0x0c, 276 + 0x14, 277 + 0xe4, 278 + 0x0c, 279 + 0x10, 280 + 0x14, 281 + 0x18, 282 + 0x48, 283 + 0x40, 284 + 0x4c, 285 + 0x24, 286 + 0x44, 287 + }, 288 + .data = { 289 + { 0x0, 0x4c, 0x2, 0x0 }, 290 + { 0x1, 0xa, 0x20, 0x80 }, 291 + { 0x6a, 0xaa, 0xaa, 0xab }, 292 + { 0x0, 0x3, 0x4, 0x94 }, 293 + { 0xfa, 0x1c, 0x83, 0x11 }, 294 + { 0x80, 0x0f, 0xf9, 0x53 }, 295 + { 0x84, 0x26, 0x4, 0x4 }, 296 + { 0x0, 0xe0, 0x1, 0x0 }, 297 + { 0x45, 0x48, 0x0, 0x0 }, 298 + { 0x27, 0x8, 0x0, 0x0 }, 299 + { 0x5a, 0x14, 0x2a, 0x14 }, 300 + { 0x0, 0x5b, 0xe0, 0x8 }, 301 + { 0x0, 0x0, 0x0, 0x0 }, 302 + }, 303 + }; 304 + 305 + static const struct intel_lt_phy_pll_state xe3plpd_lt_dp_uhbr13_5 = { 306 + .clock = 1350000, 307 + .config = { 308 + 0xcb, 309 + 0x2d, 310 + 0x0, 311 + }, 312 + .addr_msb = { 313 + 0x87, 314 + 0x87, 315 + 0x87, 316 + 0x87, 317 + 0x88, 318 + 0x88, 319 + 0x88, 320 + 0x88, 321 + 0x88, 322 + 0x88, 323 + 0x88, 324 + 0x88, 325 + 0x88, 326 + }, 327 + .addr_lsb = { 328 + 0x10, 329 + 0x0c, 330 + 0x14, 331 + 0xe4, 332 + 0x0c, 333 + 0x10, 334 + 0x14, 335 + 0x18, 336 + 0x48, 337 + 0x40, 338 + 0x4c, 339 + 0x24, 340 + 0x44, 341 + }, 342 + .data = { 343 + { 0x0, 0x4c, 0x2, 0x0 }, 344 + { 0x2, 0x9, 0x2b, 0xe0 }, 345 + { 0x90, 0x0, 0x0, 0x0 }, 346 + { 0x8, 0x4, 0x80, 0xe0 }, 347 + { 0xfa, 0x15, 0x83, 0x11 }, 348 + { 0x80, 0x0f, 0xf9, 0x53 }, 349 + { 0x84, 0x26, 0x6, 0x4 }, 350 + { 0x0, 0xe0, 0x1, 0x0 }, 351 + { 0x49, 0x48, 0x0, 0x0 }, 352 + { 0x27, 0x8, 0x0, 0x0 }, 353 + { 0x5a, 0x13, 0x29, 0x13 }, 354 + { 0x0, 0x57, 0xe0, 0x0c }, 355 + { 0x0, 0x0, 0x0, 0x0 }, 356 + }, 357 + }; 358 + 359 + static const struct intel_lt_phy_pll_state xe3plpd_lt_dp_uhbr20 = { 360 + .clock = 2000000, 361 + .config = { 362 + 0x53, 363 + 0x2d, 364 + 0x0, 365 + }, 366 + .addr_msb = { 367 + 0x85, 368 + 0x85, 369 + 0x85, 370 + 0x85, 371 + 0x86, 372 + 0x86, 373 + 0x86, 374 + 0x86, 375 + 0x86, 376 + 0x86, 377 + 0x86, 378 + 0x86, 379 + 0x86, 380 + }, 381 + .addr_lsb = { 382 + 0x10, 383 + 0x0c, 384 + 0x14, 385 + 0xe4, 386 + 0x0c, 387 + 0x10, 388 + 0x14, 389 + 0x18, 390 + 0x48, 391 + 0x40, 392 + 0x4c, 393 + 0x24, 394 + 0x44, 395 + }, 396 + .data = { 397 + { 0x0, 0x4c, 0x2, 0x0 }, 398 + { 0x1, 0xa, 0x20, 0x80 }, 399 + { 0x6a, 0xaa, 0xaa, 0xab }, 400 + { 0x0, 0x3, 0x4, 0x94 }, 401 + { 0xfa, 0x1c, 0x83, 0x11 }, 402 + { 0x80, 0x0f, 0xf9, 0x53 }, 403 + { 0x84, 0x26, 0x4, 0x4 }, 404 + { 0x0, 0xe0, 0x1, 0x0 }, 405 + { 0x45, 0x48, 0x0, 0x0 }, 406 + { 0x27, 0x8, 0x0, 0x0 }, 407 + { 0x5a, 0x14, 0x2a, 0x14 }, 408 + { 0x0, 0x5b, 0xe0, 0x8 }, 409 + { 0x0, 0x0, 0x0, 0x0 }, 410 + }, 411 + }; 412 + 413 + static const struct intel_lt_phy_pll_state * const xe3plpd_lt_dp_tables[] = { 414 + &xe3plpd_lt_dp_rbr, 415 + &xe3plpd_lt_dp_hbr1, 416 + &xe3plpd_lt_dp_hbr2, 417 + &xe3plpd_lt_dp_hbr3, 418 + &xe3plpd_lt_dp_uhbr10, 419 + &xe3plpd_lt_dp_uhbr13_5, 420 + &xe3plpd_lt_dp_uhbr20, 421 + NULL, 422 + }; 423 + 424 + static const struct intel_lt_phy_pll_state xe3plpd_lt_edp_2_16 = { 425 + .clock = 216000, 426 + .config = { 427 + 0xa3, 428 + 0x2d, 429 + 0x1, 430 + }, 431 + .addr_msb = { 432 + 0x87, 433 + 0x87, 434 + 0x87, 435 + 0x87, 436 + 0x88, 437 + 0x88, 438 + 0x88, 439 + 0x88, 440 + 0x88, 441 + 0x88, 442 + 0x88, 443 + 0x88, 444 + 0x88, 445 + }, 446 + .addr_lsb = { 447 + 0x10, 448 + 0x0c, 449 + 0x14, 450 + 0xe4, 451 + 0x0c, 452 + 0x10, 453 + 0x14, 454 + 0x18, 455 + 0x48, 456 + 0x40, 457 + 0x4c, 458 + 0x24, 459 + 0x44, 460 + }, 461 + .data = { 462 + { 0x0, 0x4c, 0x2, 0x0 }, 463 + { 0x3, 0xca, 0x2a, 0x20 }, 464 + { 0x80, 0x0, 0x0, 0x0 }, 465 + { 0x6, 0x4, 0x81, 0xbc }, 466 + { 0xfa, 0x16, 0x83, 0x11 }, 467 + { 0x80, 0x0f, 0xf9, 0x53 }, 468 + { 0x84, 0x26, 0x5, 0x4 }, 469 + { 0x0, 0xe0, 0x1, 0x0 }, 470 + { 0x4b, 0x48, 0x0, 0x0 }, 471 + { 0x27, 0x8, 0x0, 0x0 }, 472 + { 0x5a, 0x13, 0x29, 0x13 }, 473 + { 0x0, 0x5b, 0xe0, 0x0a }, 474 + { 0x0, 0x0, 0x0, 0x0 }, 475 + }, 476 + }; 477 + 478 + static const struct intel_lt_phy_pll_state xe3plpd_lt_edp_2_43 = { 479 + .clock = 243000, 480 + .config = { 481 + 0xab, 482 + 0x2d, 483 + 0x1, 484 + }, 485 + .addr_msb = { 486 + 0x87, 487 + 0x87, 488 + 0x87, 489 + 0x87, 490 + 0x88, 491 + 0x88, 492 + 0x88, 493 + 0x88, 494 + 0x88, 495 + 0x88, 496 + 0x88, 497 + 0x88, 498 + 0x88, 499 + }, 500 + .addr_lsb = { 501 + 0x10, 502 + 0x0c, 503 + 0x14, 504 + 0xe4, 505 + 0x0c, 506 + 0x10, 507 + 0x14, 508 + 0x18, 509 + 0x48, 510 + 0x40, 511 + 0x4c, 512 + 0x24, 513 + 0x44, 514 + }, 515 + .data = { 516 + { 0x0, 0x4c, 0x2, 0x0 }, 517 + { 0x3, 0xca, 0x2f, 0x60 }, 518 + { 0xb0, 0x0, 0x0, 0x0 }, 519 + { 0x6, 0x4, 0x81, 0xbc }, 520 + { 0xfa, 0x13, 0x83, 0x11 }, 521 + { 0x80, 0x0f, 0xf9, 0x53 }, 522 + { 0x84, 0x26, 0x6, 0x4 }, 523 + { 0x0, 0xe0, 0x1, 0x0 }, 524 + { 0x47, 0x48, 0x0, 0x0 }, 525 + { 0x0, 0x0, 0x0, 0x0 }, 526 + { 0x5a, 0x13, 0x29, 0x13 }, 527 + { 0x0, 0x5b, 0xe0, 0x0c }, 528 + { 0x0, 0x0, 0x0, 0x0 }, 529 + }, 530 + }; 531 + 532 + static const struct intel_lt_phy_pll_state xe3plpd_lt_edp_3_24 = { 533 + .clock = 324000, 534 + .config = { 535 + 0xb3, 536 + 0x2d, 537 + 0x1, 538 + }, 539 + .addr_msb = { 540 + 0x87, 541 + 0x87, 542 + 0x87, 543 + 0x87, 544 + 0x88, 545 + 0x88, 546 + 0x88, 547 + 0x88, 548 + 0x88, 549 + 0x88, 550 + 0x88, 551 + 0x88, 552 + 0x88, 553 + }, 554 + .addr_lsb = { 555 + 0x10, 556 + 0x0c, 557 + 0x14, 558 + 0xe4, 559 + 0x0c, 560 + 0x10, 561 + 0x14, 562 + 0x18, 563 + 0x48, 564 + 0x40, 565 + 0x4c, 566 + 0x24, 567 + 0x44, 568 + }, 569 + .data = { 570 + { 0x0, 0x4c, 0x2, 0x0 }, 571 + { 0x2, 0x8a, 0x2a, 0x20 }, 572 + { 0x80, 0x0, 0x0, 0x0 }, 573 + { 0x6, 0x4, 0x81, 0x28 }, 574 + { 0xfa, 0x16, 0x83, 0x11 }, 575 + { 0x80, 0x0f, 0xf9, 0x53 }, 576 + { 0x84, 0x26, 0x5, 0x4 }, 577 + { 0x0, 0xe0, 0x1, 0x0 }, 578 + { 0x4b, 0x48, 0x0, 0x0 }, 579 + { 0x27, 0x8, 0x0, 0x0 }, 580 + { 0x5a, 0x13, 0x29, 0x13 }, 581 + { 0x0, 0x5b, 0xe0, 0x0a }, 582 + { 0x0, 0x0, 0x0, 0x0 }, 583 + }, 584 + }; 585 + 586 + static const struct intel_lt_phy_pll_state xe3plpd_lt_edp_4_32 = { 587 + .clock = 432000, 588 + .config = { 589 + 0xbb, 590 + 0x2d, 591 + 0x1, 592 + }, 593 + .addr_msb = { 594 + 0x87, 595 + 0x87, 596 + 0x87, 597 + 0x87, 598 + 0x88, 599 + 0x88, 600 + 0x88, 601 + 0x88, 602 + 0x88, 603 + 0x88, 604 + 0x88, 605 + 0x88, 606 + 0x88, 607 + }, 608 + .addr_lsb = { 609 + 0x10, 610 + 0x0c, 611 + 0x14, 612 + 0xe4, 613 + 0x0c, 614 + 0x10, 615 + 0x14, 616 + 0x18, 617 + 0x48, 618 + 0x40, 619 + 0x4c, 620 + 0x24, 621 + 0x44, 622 + }, 623 + .data = { 624 + { 0x0, 0x4c, 0x2, 0x0 }, 625 + { 0x1, 0x4d, 0x2a, 0x20 }, 626 + { 0x80, 0x0, 0x0, 0x0 }, 627 + { 0xc, 0x4, 0x81, 0xbc }, 628 + { 0xfa, 0x16, 0x83, 0x11 }, 629 + { 0x80, 0x0f, 0xf9, 0x53 }, 630 + { 0x84, 0x26, 0x5, 0x4 }, 631 + { 0x0, 0xe0, 0x1, 0x0 }, 632 + { 0x4b, 0x48, 0x0, 0x0 }, 633 + { 0x27, 0x8, 0x0, 0x0 }, 634 + { 0x5a, 0x13, 0x29, 0x13 }, 635 + { 0x0, 0x5b, 0xe0, 0x0a }, 636 + { 0x0, 0x0, 0x0, 0x0 }, 637 + }, 638 + }; 639 + 640 + static const struct intel_lt_phy_pll_state xe3plpd_lt_edp_6_75 = { 641 + .clock = 675000, 642 + .config = { 643 + 0xdb, 644 + 0x2d, 645 + 0x1, 646 + }, 647 + .addr_msb = { 648 + 0x87, 649 + 0x87, 650 + 0x87, 651 + 0x87, 652 + 0x88, 653 + 0x88, 654 + 0x88, 655 + 0x88, 656 + 0x88, 657 + 0x88, 658 + 0x88, 659 + 0x88, 660 + 0x88, 661 + }, 662 + .addr_lsb = { 663 + 0x10, 664 + 0x0c, 665 + 0x14, 666 + 0xe4, 667 + 0x0c, 668 + 0x10, 669 + 0x14, 670 + 0x18, 671 + 0x48, 672 + 0x40, 673 + 0x4c, 674 + 0x24, 675 + 0x44, 676 + }, 677 + .data = { 678 + { 0x0, 0x4c, 0x2, 0x0 }, 679 + { 0x1, 0x4a, 0x2b, 0xe0 }, 680 + { 0x90, 0x0, 0x0, 0x0 }, 681 + { 0x6, 0x4, 0x80, 0xa8 }, 682 + { 0xfa, 0x15, 0x83, 0x11 }, 683 + { 0x80, 0x0f, 0xf9, 0x53 }, 684 + { 0x84, 0x26, 0x6, 0x4 }, 685 + { 0x0, 0xe0, 0x1, 0x0 }, 686 + { 0x49, 0x48, 0x0, 0x0 }, 687 + { 0x27, 0x8, 0x0, 0x0 }, 688 + { 0x5a, 0x13, 0x29, 0x13 }, 689 + { 0x0, 0x57, 0xe0, 0x0c }, 690 + { 0x0, 0x0, 0x0, 0x0 }, 691 + }, 692 + }; 693 + 694 + static const struct intel_lt_phy_pll_state * const xe3plpd_lt_edp_tables[] = { 695 + &xe3plpd_lt_dp_rbr, 696 + &xe3plpd_lt_edp_2_16, 697 + &xe3plpd_lt_edp_2_43, 698 + &xe3plpd_lt_dp_hbr1, 699 + &xe3plpd_lt_edp_3_24, 700 + &xe3plpd_lt_edp_4_32, 701 + &xe3plpd_lt_dp_hbr2, 702 + &xe3plpd_lt_edp_6_75, 703 + &xe3plpd_lt_dp_hbr3, 704 + NULL, 705 + }; 706 + 707 + static const struct intel_lt_phy_pll_state xe3plpd_lt_hdmi_252 = { 708 + .clock = 25200, 709 + .config = { 710 + 0x84, 711 + 0x2d, 712 + 0x0, 713 + }, 714 + .addr_msb = { 715 + 0x87, 716 + 0x87, 717 + 0x87, 718 + 0x87, 719 + 0x88, 720 + 0x88, 721 + 0x88, 722 + 0x88, 723 + 0x88, 724 + 0x88, 725 + 0x88, 726 + 0x88, 727 + 0x88, 728 + }, 729 + .addr_lsb = { 730 + 0x10, 731 + 0x0c, 732 + 0x14, 733 + 0xe4, 734 + 0x0c, 735 + 0x10, 736 + 0x14, 737 + 0x18, 738 + 0x48, 739 + 0x40, 740 + 0x4c, 741 + 0x24, 742 + 0x44, 743 + }, 744 + .data = { 745 + { 0x0, 0x4c, 0x2, 0x0 }, 746 + { 0x0c, 0x15, 0x27, 0x60 }, 747 + { 0x0, 0x0, 0x0, 0x0 }, 748 + { 0x8, 0x4, 0x98, 0x28 }, 749 + { 0x42, 0x0, 0x84, 0x10 }, 750 + { 0x80, 0x0f, 0xd9, 0xb5 }, 751 + { 0x86, 0x0, 0x0, 0x0 }, 752 + { 0x1, 0xa0, 0x1, 0x0 }, 753 + { 0x4b, 0x0, 0x0, 0x0 }, 754 + { 0x28, 0x0, 0x0, 0x0 }, 755 + { 0x0, 0x14, 0x2a, 0x14 }, 756 + { 0x0, 0x0, 0x0, 0x0 }, 757 + { 0x0, 0x0, 0x0, 0x0 }, 758 + }, 759 + }; 760 + 761 + static const struct intel_lt_phy_pll_state xe3plpd_lt_hdmi_272 = { 762 + .clock = 27200, 763 + .config = { 764 + 0x84, 765 + 0x2d, 766 + 0x0, 767 + }, 768 + .addr_msb = { 769 + 0x87, 770 + 0x87, 771 + 0x87, 772 + 0x87, 773 + 0x88, 774 + 0x88, 775 + 0x88, 776 + 0x88, 777 + 0x88, 778 + 0x88, 779 + 0x88, 780 + 0x88, 781 + 0x88, 782 + }, 783 + .addr_lsb = { 784 + 0x10, 785 + 0x0c, 786 + 0x14, 787 + 0xe4, 788 + 0x0c, 789 + 0x10, 790 + 0x14, 791 + 0x18, 792 + 0x48, 793 + 0x40, 794 + 0x4c, 795 + 0x24, 796 + 0x44, 797 + }, 798 + .data = { 799 + { 0x0, 0x4c, 0x2, 0x0 }, 800 + { 0x0b, 0x15, 0x26, 0xa0 }, 801 + { 0x60, 0x0, 0x0, 0x0 }, 802 + { 0x8, 0x4, 0x96, 0x28 }, 803 + { 0xfa, 0x0c, 0x84, 0x11 }, 804 + { 0x80, 0x0f, 0xd9, 0x53 }, 805 + { 0x86, 0x0, 0x0, 0x0 }, 806 + { 0x1, 0xa0, 0x1, 0x0 }, 807 + { 0x4b, 0x0, 0x0, 0x0 }, 808 + { 0x28, 0x0, 0x0, 0x0 }, 809 + { 0x0, 0x14, 0x2a, 0x14 }, 810 + { 0x0, 0x0, 0x0, 0x0 }, 811 + { 0x0, 0x0, 0x0, 0x0 }, 812 + }, 813 + }; 814 + 815 + static const struct intel_lt_phy_pll_state xe3plpd_lt_hdmi_742p5 = { 816 + .clock = 74250, 817 + .config = { 818 + 0x84, 819 + 0x2d, 820 + 0x0, 821 + }, 822 + .addr_msb = { 823 + 0x87, 824 + 0x87, 825 + 0x87, 826 + 0x87, 827 + 0x88, 828 + 0x88, 829 + 0x88, 830 + 0x88, 831 + 0x88, 832 + 0x88, 833 + 0x88, 834 + 0x88, 835 + 0x88, 836 + }, 837 + .addr_lsb = { 838 + 0x10, 839 + 0x0c, 840 + 0x14, 841 + 0xe4, 842 + 0x0c, 843 + 0x10, 844 + 0x14, 845 + 0x18, 846 + 0x48, 847 + 0x40, 848 + 0x4c, 849 + 0x24, 850 + 0x44, 851 + }, 852 + .data = { 853 + { 0x0, 0x4c, 0x2, 0x0 }, 854 + { 0x4, 0x15, 0x26, 0xa0 }, 855 + { 0x60, 0x0, 0x0, 0x0 }, 856 + { 0x8, 0x4, 0x88, 0x28 }, 857 + { 0xfa, 0x0c, 0x84, 0x11 }, 858 + { 0x80, 0x0f, 0xd9, 0x53 }, 859 + { 0x86, 0x0, 0x0, 0x0 }, 860 + { 0x1, 0xa0, 0x1, 0x0 }, 861 + { 0x4b, 0x0, 0x0, 0x0 }, 862 + { 0x28, 0x0, 0x0, 0x0 }, 863 + { 0x0, 0x14, 0x2a, 0x14 }, 864 + { 0x0, 0x0, 0x0, 0x0 }, 865 + { 0x0, 0x0, 0x0, 0x0 }, 866 + }, 867 + }; 868 + 869 + static const struct intel_lt_phy_pll_state xe3plpd_lt_hdmi_1p485 = { 870 + .clock = 148500, 871 + .config = { 872 + 0x84, 873 + 0x2d, 874 + 0x0, 875 + }, 876 + .addr_msb = { 877 + 0x87, 878 + 0x87, 879 + 0x87, 880 + 0x87, 881 + 0x88, 882 + 0x88, 883 + 0x88, 884 + 0x88, 885 + 0x88, 886 + 0x88, 887 + 0x88, 888 + 0x88, 889 + 0x88, 890 + }, 891 + .addr_lsb = { 892 + 0x10, 893 + 0x0c, 894 + 0x14, 895 + 0xe4, 896 + 0x0c, 897 + 0x10, 898 + 0x14, 899 + 0x18, 900 + 0x48, 901 + 0x40, 902 + 0x4c, 903 + 0x24, 904 + 0x44, 905 + }, 906 + .data = { 907 + { 0x0, 0x4c, 0x2, 0x0 }, 908 + { 0x2, 0x15, 0x26, 0xa0 }, 909 + { 0x60, 0x0, 0x0, 0x0 }, 910 + { 0x8, 0x4, 0x84, 0x28 }, 911 + { 0xfa, 0x0c, 0x84, 0x11 }, 912 + { 0x80, 0x0f, 0xd9, 0x53 }, 913 + { 0x86, 0x0, 0x0, 0x0 }, 914 + { 0x1, 0xa0, 0x1, 0x0 }, 915 + { 0x4b, 0x0, 0x0, 0x0 }, 916 + { 0x28, 0x0, 0x0, 0x0 }, 917 + { 0x0, 0x14, 0x2a, 0x14 }, 918 + { 0x0, 0x0, 0x0, 0x0 }, 919 + { 0x0, 0x0, 0x0, 0x0 }, 920 + }, 921 + }; 922 + 923 + static const struct intel_lt_phy_pll_state xe3plpd_lt_hdmi_5p94 = { 924 + .clock = 594000, 925 + .config = { 926 + 0x84, 927 + 0x2d, 928 + 0x0, 929 + }, 930 + .addr_msb = { 931 + 0x87, 932 + 0x87, 933 + 0x87, 934 + 0x87, 935 + 0x88, 936 + 0x88, 937 + 0x88, 938 + 0x88, 939 + 0x88, 940 + 0x88, 941 + 0x88, 942 + 0x88, 943 + 0x88, 944 + }, 945 + .addr_lsb = { 946 + 0x10, 947 + 0x0c, 948 + 0x14, 949 + 0xe4, 950 + 0x0c, 951 + 0x10, 952 + 0x14, 953 + 0x18, 954 + 0x48, 955 + 0x40, 956 + 0x4c, 957 + 0x24, 958 + 0x44, 959 + }, 960 + .data = { 961 + { 0x0, 0x4c, 0x2, 0x0 }, 962 + { 0x0, 0x95, 0x26, 0xa0 }, 963 + { 0x60, 0x0, 0x0, 0x0 }, 964 + { 0x8, 0x4, 0x81, 0x28 }, 965 + { 0xfa, 0x0c, 0x84, 0x11 }, 966 + { 0x80, 0x0f, 0xd9, 0x53 }, 967 + { 0x86, 0x0, 0x0, 0x0 }, 968 + { 0x1, 0xa0, 0x1, 0x0 }, 969 + { 0x4b, 0x0, 0x0, 0x0 }, 970 + { 0x28, 0x0, 0x0, 0x0 }, 971 + { 0x0, 0x14, 0x2a, 0x14 }, 972 + { 0x0, 0x0, 0x0, 0x0 }, 973 + { 0x0, 0x0, 0x0, 0x0 }, 974 + }, 975 + }; 976 + 977 + static const struct intel_lt_phy_pll_state * const xe3plpd_lt_hdmi_tables[] = { 978 + &xe3plpd_lt_hdmi_252, 979 + &xe3plpd_lt_hdmi_272, 980 + &xe3plpd_lt_hdmi_742p5, 981 + &xe3plpd_lt_hdmi_1p485, 982 + &xe3plpd_lt_hdmi_5p94, 983 + NULL, 984 + }; 985 + 986 + static u8 intel_lt_phy_get_owned_lane_mask(struct intel_encoder *encoder) 987 + { 988 + struct intel_digital_port *dig_port = enc_to_dig_port(encoder); 989 + 990 + if (!intel_tc_port_in_dp_alt_mode(dig_port)) 991 + return INTEL_LT_PHY_BOTH_LANES; 992 + 993 + return intel_tc_port_max_lane_count(dig_port) > 2 994 + ? INTEL_LT_PHY_BOTH_LANES : INTEL_LT_PHY_LANE0; 995 + } 996 + 997 + static u8 intel_lt_phy_read(struct intel_encoder *encoder, u8 lane_mask, u16 addr) 998 + { 999 + return intel_cx0_read(encoder, lane_mask, addr); 1000 + } 1001 + 1002 + static void intel_lt_phy_write(struct intel_encoder *encoder, 1003 + u8 lane_mask, u16 addr, u8 data, bool committed) 1004 + { 1005 + intel_cx0_write(encoder, lane_mask, addr, data, committed); 1006 + } 1007 + 1008 + static void intel_lt_phy_rmw(struct intel_encoder *encoder, 1009 + u8 lane_mask, u16 addr, u8 clear, u8 set, bool committed) 1010 + { 1011 + intel_cx0_rmw(encoder, lane_mask, addr, clear, set, committed); 1012 + } 1013 + 1014 + static void intel_lt_phy_clear_status_p2p(struct intel_encoder *encoder, 1015 + int lane) 1016 + { 1017 + struct intel_display *display = to_intel_display(encoder); 1018 + 1019 + intel_de_rmw(display, 1020 + XE3PLPD_PORT_P2M_MSGBUS_STATUS_P2P(encoder->port, lane), 1021 + XELPDP_PORT_P2M_RESPONSE_READY, 0); 1022 + } 1023 + 1024 + static void 1025 + assert_dc_off(struct intel_display *display) 1026 + { 1027 + bool enabled; 1028 + 1029 + enabled = intel_display_power_is_enabled(display, POWER_DOMAIN_DC_OFF); 1030 + drm_WARN_ON(display->drm, !enabled); 1031 + } 1032 + 1033 + static int __intel_lt_phy_p2p_write_once(struct intel_encoder *encoder, 1034 + int lane, u16 addr, u8 data, 1035 + i915_reg_t mac_reg_addr, 1036 + u8 expected_mac_val) 1037 + { 1038 + struct intel_display *display = to_intel_display(encoder); 1039 + enum port port = encoder->port; 1040 + enum phy phy = intel_encoder_to_phy(encoder); 1041 + int ack; 1042 + u32 val; 1043 + 1044 + if (intel_de_wait_for_clear(display, XELPDP_PORT_M2P_MSGBUS_CTL(display, port, lane), 1045 + XELPDP_PORT_P2P_TRANSACTION_PENDING, 1046 + XELPDP_MSGBUS_TIMEOUT_SLOW)) { 1047 + drm_dbg_kms(display->drm, 1048 + "PHY %c Timeout waiting for previous transaction to complete. Resetting bus.\n", 1049 + phy_name(phy)); 1050 + intel_cx0_bus_reset(encoder, lane); 1051 + return -ETIMEDOUT; 1052 + } 1053 + 1054 + intel_de_rmw(display, XELPDP_PORT_P2M_MSGBUS_STATUS(display, port, lane), 0, 0); 1055 + 1056 + intel_de_write(display, XELPDP_PORT_M2P_MSGBUS_CTL(display, port, lane), 1057 + XELPDP_PORT_P2P_TRANSACTION_PENDING | 1058 + XELPDP_PORT_M2P_COMMAND_WRITE_COMMITTED | 1059 + XELPDP_PORT_M2P_DATA(data) | 1060 + XELPDP_PORT_M2P_ADDRESS(addr)); 1061 + 1062 + ack = intel_cx0_wait_for_ack(encoder, XELPDP_PORT_P2M_COMMAND_WRITE_ACK, lane, &val); 1063 + if (ack < 0) 1064 + return ack; 1065 + 1066 + if (val & XELPDP_PORT_P2M_ERROR_SET) { 1067 + drm_dbg_kms(display->drm, 1068 + "PHY %c Error occurred during P2P write command. Status: 0x%x\n", 1069 + phy_name(phy), val); 1070 + intel_lt_phy_clear_status_p2p(encoder, lane); 1071 + intel_cx0_bus_reset(encoder, lane); 1072 + return -EINVAL; 1073 + } 1074 + 1075 + /* 1076 + * RE-VISIT: 1077 + * This needs to be added to give PHY time to set everything up this was a requirement 1078 + * to get the display up and running 1079 + * This is the time PHY takes to settle down after programming the PHY. 1080 + */ 1081 + udelay(150); 1082 + intel_clear_response_ready_flag(encoder, lane); 1083 + intel_lt_phy_clear_status_p2p(encoder, lane); 1084 + 1085 + return 0; 1086 + } 1087 + 1088 + static void __intel_lt_phy_p2p_write(struct intel_encoder *encoder, 1089 + int lane, u16 addr, u8 data, 1090 + i915_reg_t mac_reg_addr, 1091 + u8 expected_mac_val) 1092 + { 1093 + struct intel_display *display = to_intel_display(encoder); 1094 + enum phy phy = intel_encoder_to_phy(encoder); 1095 + int i, status; 1096 + 1097 + assert_dc_off(display); 1098 + 1099 + /* 3 tries is assumed to be enough to write successfully */ 1100 + for (i = 0; i < 3; i++) { 1101 + status = __intel_lt_phy_p2p_write_once(encoder, lane, addr, data, mac_reg_addr, 1102 + expected_mac_val); 1103 + 1104 + if (status == 0) 1105 + return; 1106 + } 1107 + 1108 + drm_err_once(display->drm, 1109 + "PHY %c P2P Write %04x failed after %d retries.\n", phy_name(phy), addr, i); 1110 + } 1111 + 1112 + static void intel_lt_phy_p2p_write(struct intel_encoder *encoder, 1113 + u8 lane_mask, u16 addr, u8 data, 1114 + i915_reg_t mac_reg_addr, 1115 + u8 expected_mac_val) 1116 + { 1117 + int lane; 1118 + 1119 + for_each_lt_phy_lane_in_mask(lane_mask, lane) 1120 + __intel_lt_phy_p2p_write(encoder, lane, addr, data, mac_reg_addr, expected_mac_val); 1121 + } 1122 + 1123 + static void 1124 + intel_lt_phy_setup_powerdown(struct intel_encoder *encoder, u8 lane_count) 1125 + { 1126 + /* 1127 + * The new PORT_BUF_CTL6 stuff for dc5 entry and exit needs to be handled 1128 + * by dmc firmware not explicitly mentioned in Bspec. This leaves this 1129 + * function as a wrapper only but keeping it expecting future changes. 1130 + */ 1131 + intel_cx0_setup_powerdown(encoder); 1132 + } 1133 + 1134 + static void 1135 + intel_lt_phy_powerdown_change_sequence(struct intel_encoder *encoder, 1136 + u8 lane_mask, u8 state) 1137 + { 1138 + intel_cx0_powerdown_change_sequence(encoder, lane_mask, state); 1139 + } 1140 + 1141 + static void 1142 + intel_lt_phy_lane_reset(struct intel_encoder *encoder, 1143 + u8 lane_count) 1144 + { 1145 + struct intel_display *display = to_intel_display(encoder); 1146 + enum port port = encoder->port; 1147 + enum phy phy = intel_encoder_to_phy(encoder); 1148 + u8 owned_lane_mask = intel_lt_phy_get_owned_lane_mask(encoder); 1149 + u32 lane_pipe_reset = owned_lane_mask == INTEL_LT_PHY_BOTH_LANES 1150 + ? XELPDP_LANE_PIPE_RESET(0) | XELPDP_LANE_PIPE_RESET(1) 1151 + : XELPDP_LANE_PIPE_RESET(0); 1152 + u32 lane_phy_current_status = owned_lane_mask == INTEL_LT_PHY_BOTH_LANES 1153 + ? (XELPDP_LANE_PHY_CURRENT_STATUS(0) | 1154 + XELPDP_LANE_PHY_CURRENT_STATUS(1)) 1155 + : XELPDP_LANE_PHY_CURRENT_STATUS(0); 1156 + u32 lane_phy_pulse_status = owned_lane_mask == INTEL_LT_PHY_BOTH_LANES 1157 + ? (XE3PLPDP_LANE_PHY_PULSE_STATUS(0) | 1158 + XE3PLPDP_LANE_PHY_PULSE_STATUS(1)) 1159 + : XE3PLPDP_LANE_PHY_PULSE_STATUS(0); 1160 + 1161 + intel_de_rmw(display, XE3PLPD_PORT_BUF_CTL5(port), 1162 + XE3PLPD_MACCLK_RATE_MASK, XE3PLPD_MACCLK_RATE_DEF); 1163 + 1164 + intel_de_rmw(display, XELPDP_PORT_BUF_CTL1(display, port), 1165 + XE3PLPDP_PHY_MODE_MASK, XE3PLPDP_PHY_MODE_DP); 1166 + 1167 + intel_lt_phy_setup_powerdown(encoder, lane_count); 1168 + intel_lt_phy_powerdown_change_sequence(encoder, owned_lane_mask, 1169 + XELPDP_P2_STATE_RESET); 1170 + 1171 + intel_de_rmw(display, XE3PLPD_PORT_BUF_CTL5(port), 1172 + XE3PLPD_MACCLK_RESET_0, 0); 1173 + 1174 + intel_de_rmw(display, XELPDP_PORT_CLOCK_CTL(display, port), 1175 + XELPDP_LANE_PCLK_PLL_REQUEST(0), 1176 + XELPDP_LANE_PCLK_PLL_REQUEST(0)); 1177 + 1178 + if (intel_de_wait_custom(display, XELPDP_PORT_CLOCK_CTL(display, port), 1179 + XELPDP_LANE_PCLK_PLL_ACK(0), 1180 + XELPDP_LANE_PCLK_PLL_ACK(0), 1181 + XE3PLPD_MACCLK_TURNON_LATENCY_US, 1182 + XE3PLPD_MACCLK_TURNON_LATENCY_MS, NULL)) 1183 + drm_warn(display->drm, "PHY %c PLL MacCLK assertion Ack not done after %dus.\n", 1184 + phy_name(phy), XE3PLPD_MACCLK_TURNON_LATENCY_MS * 1000); 1185 + 1186 + intel_de_rmw(display, XELPDP_PORT_CLOCK_CTL(display, port), 1187 + XELPDP_FORWARD_CLOCK_UNGATE, 1188 + XELPDP_FORWARD_CLOCK_UNGATE); 1189 + 1190 + intel_de_rmw(display, XELPDP_PORT_BUF_CTL2(display, port), 1191 + lane_pipe_reset | lane_phy_pulse_status, 0); 1192 + 1193 + if (intel_de_wait_custom(display, XELPDP_PORT_BUF_CTL2(display, port), 1194 + lane_phy_current_status, 0, 1195 + XE3PLPD_RESET_END_LATENCY_US, 2, NULL)) 1196 + drm_warn(display->drm, 1197 + "PHY %c failed to bring out of Lane reset after %dus.\n", 1198 + phy_name(phy), XE3PLPD_RESET_END_LATENCY_US); 1199 + 1200 + if (intel_de_wait_custom(display, XELPDP_PORT_BUF_CTL2(display, port), 1201 + lane_phy_pulse_status, lane_phy_pulse_status, 1202 + XE3PLPD_RATE_CALIB_DONE_LATENCY_US, 0, NULL)) 1203 + drm_warn(display->drm, "PHY %c PLL rate not changed after %dus.\n", 1204 + phy_name(phy), XE3PLPD_RATE_CALIB_DONE_LATENCY_US); 1205 + 1206 + intel_de_rmw(display, XELPDP_PORT_BUF_CTL2(display, port), lane_phy_pulse_status, 0); 1207 + } 1208 + 1209 + static void 1210 + intel_lt_phy_program_port_clock_ctl(struct intel_encoder *encoder, 1211 + const struct intel_crtc_state *crtc_state, 1212 + bool lane_reversal) 1213 + { 1214 + struct intel_display *display = to_intel_display(encoder); 1215 + u32 val = 0; 1216 + 1217 + intel_de_rmw(display, XELPDP_PORT_BUF_CTL1(display, encoder->port), 1218 + XELPDP_PORT_REVERSAL, 1219 + lane_reversal ? XELPDP_PORT_REVERSAL : 0); 1220 + 1221 + val |= XELPDP_FORWARD_CLOCK_UNGATE; 1222 + 1223 + /* 1224 + * We actually mean MACCLK here and not MAXPCLK when using LT Phy 1225 + * but since the register bits still remain the same we use 1226 + * the same definition 1227 + */ 1228 + if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI) && 1229 + intel_hdmi_is_frl(crtc_state->port_clock)) 1230 + val |= XELPDP_DDI_CLOCK_SELECT_PREP(display, XELPDP_DDI_CLOCK_SELECT_DIV18CLK); 1231 + else 1232 + val |= XELPDP_DDI_CLOCK_SELECT_PREP(display, XELPDP_DDI_CLOCK_SELECT_MAXPCLK); 1233 + 1234 + /* DP2.0 10G and 20G rates enable MPLLA*/ 1235 + if (crtc_state->port_clock == 1000000 || crtc_state->port_clock == 2000000) 1236 + val |= XELPDP_SSC_ENABLE_PLLA; 1237 + else 1238 + val |= crtc_state->dpll_hw_state.ltpll.ssc_enabled ? XELPDP_SSC_ENABLE_PLLB : 0; 1239 + 1240 + intel_de_rmw(display, XELPDP_PORT_CLOCK_CTL(display, encoder->port), 1241 + XELPDP_LANE1_PHY_CLOCK_SELECT | XELPDP_FORWARD_CLOCK_UNGATE | 1242 + XELPDP_DDI_CLOCK_SELECT_MASK(display) | XELPDP_SSC_ENABLE_PLLA | 1243 + XELPDP_SSC_ENABLE_PLLB, val); 1244 + } 1245 + 1246 + static u32 intel_lt_phy_get_dp_clock(u8 rate) 1247 + { 1248 + switch (rate) { 1249 + case 0: 1250 + return 162000; 1251 + case 1: 1252 + return 270000; 1253 + case 2: 1254 + return 540000; 1255 + case 3: 1256 + return 810000; 1257 + case 4: 1258 + return 216000; 1259 + case 5: 1260 + return 243000; 1261 + case 6: 1262 + return 324000; 1263 + case 7: 1264 + return 432000; 1265 + case 8: 1266 + return 1000000; 1267 + case 9: 1268 + return 1350000; 1269 + case 10: 1270 + return 2000000; 1271 + case 11: 1272 + return 675000; 1273 + default: 1274 + MISSING_CASE(rate); 1275 + return 0; 1276 + } 1277 + } 1278 + 1279 + static bool 1280 + intel_lt_phy_config_changed(struct intel_encoder *encoder, 1281 + const struct intel_crtc_state *crtc_state) 1282 + { 1283 + u8 val, rate; 1284 + u32 clock; 1285 + 1286 + val = intel_lt_phy_read(encoder, INTEL_LT_PHY_LANE0, 1287 + LT_PHY_VDR_0_CONFIG); 1288 + rate = REG_FIELD_GET8(LT_PHY_VDR_RATE_ENCODING_MASK, val); 1289 + 1290 + /* 1291 + * The only time we do not reconfigure the PLL is when we are 1292 + * using 1.62 Gbps clock since PHY PLL defaults to that 1293 + * otherwise we always need to reconfigure it. 1294 + */ 1295 + if (intel_crtc_has_dp_encoder(crtc_state)) { 1296 + clock = intel_lt_phy_get_dp_clock(rate); 1297 + if (crtc_state->port_clock == 1620000 && crtc_state->port_clock == clock) 1298 + return false; 1299 + } 1300 + 1301 + return true; 1302 + } 1303 + 1304 + static intel_wakeref_t intel_lt_phy_transaction_begin(struct intel_encoder *encoder) 1305 + { 1306 + struct intel_display *display = to_intel_display(encoder); 1307 + struct intel_dp *intel_dp = enc_to_intel_dp(encoder); 1308 + intel_wakeref_t wakeref; 1309 + 1310 + intel_psr_pause(intel_dp); 1311 + wakeref = intel_display_power_get(display, POWER_DOMAIN_DC_OFF); 1312 + 1313 + return wakeref; 1314 + } 1315 + 1316 + static void intel_lt_phy_transaction_end(struct intel_encoder *encoder, intel_wakeref_t wakeref) 1317 + { 1318 + struct intel_display *display = to_intel_display(encoder); 1319 + struct intel_dp *intel_dp = enc_to_intel_dp(encoder); 1320 + 1321 + intel_psr_resume(intel_dp); 1322 + intel_display_power_put(display, POWER_DOMAIN_DC_OFF, wakeref); 1323 + } 1324 + 1325 + static const struct intel_lt_phy_pll_state * const * 1326 + intel_lt_phy_pll_tables_get(struct intel_crtc_state *crtc_state, 1327 + struct intel_encoder *encoder) 1328 + { 1329 + if (intel_crtc_has_dp_encoder(crtc_state)) { 1330 + if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP)) 1331 + return xe3plpd_lt_edp_tables; 1332 + 1333 + return xe3plpd_lt_dp_tables; 1334 + } else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) { 1335 + return xe3plpd_lt_hdmi_tables; 1336 + } 1337 + 1338 + MISSING_CASE(encoder->type); 1339 + return NULL; 1340 + } 1341 + 1342 + static bool 1343 + intel_lt_phy_pll_is_ssc_enabled(struct intel_crtc_state *crtc_state, 1344 + struct intel_encoder *encoder) 1345 + { 1346 + struct intel_display *display = to_intel_display(encoder); 1347 + 1348 + if (intel_crtc_has_dp_encoder(crtc_state)) { 1349 + if (intel_panel_use_ssc(display)) { 1350 + struct intel_dp *intel_dp = enc_to_intel_dp(encoder); 1351 + 1352 + return (intel_dp->dpcd[DP_MAX_DOWNSPREAD] & DP_MAX_DOWNSPREAD_0_5); 1353 + } 1354 + } 1355 + 1356 + return false; 1357 + } 1358 + 1359 + static int 1360 + intel_lt_phy_calc_hdmi_port_clock(const struct intel_lt_phy_pll_state *lt_state) 1361 + { 1362 + #define REF_CLK_KHZ 38400 1363 + #define REGVAL(i) ( \ 1364 + (lt_state->data[i][3]) | \ 1365 + (lt_state->data[i][2] << 8) | \ 1366 + (lt_state->data[i][1] << 16) | \ 1367 + (lt_state->data[i][0] << 24) \ 1368 + ) 1369 + 1370 + int clk = 0; 1371 + u32 d8, pll_reg_5, pll_reg_3, pll_reg_57, m2div_frac, m2div_int; 1372 + u64 temp0, temp1; 1373 + /* 1374 + * The algorithm uses '+' to combine bitfields when 1375 + * constructing PLL_reg3 and PLL_reg57: 1376 + * PLL_reg57 = (D7 << 24) + (postdiv << 15) + (D8 << 7) + D6_new; 1377 + * PLL_reg3 = (D4 << 21) + (D3 << 18) + (D1 << 15) + (m2div_int << 5); 1378 + * 1379 + * However, this is likely intended to be a bitwise OR operation, 1380 + * as each field occupies distinct, non-overlapping bits in the register. 1381 + * 1382 + * PLL_reg57 is composed of following fields packed into a 32-bit value: 1383 + * - D7: max value 10 -> fits in 4 bits -> placed at bits 24-27 1384 + * - postdiv: max value 9 -> fits in 4 bits -> placed at bits 15-18 1385 + * - D8: derived from loop_cnt / 2, max 127 -> fits in 7 bits 1386 + * (though 8 bits are given to it) -> placed at bits 7-14 1387 + * - D6_new: fits in lower 7 bits -> placed at bits 0-6 1388 + * PLL_reg57 = (D7 << 24) | (postdiv << 15) | (D8 << 7) | D6_new; 1389 + * 1390 + * Similarly, PLL_reg3 is packed as: 1391 + * - D4: max value 256 -> fits in 9 bits -> placed at bits 21-29 1392 + * - D3: max value 9 -> fits in 4 bits -> placed at bits 18-21 1393 + * - D1: max value 2 -> fits in 2 bits -> placed at bits 15-16 1394 + * - m2div_int: max value 511 -> fits in 9 bits (10 bits allocated) 1395 + * -> placed at bits 5-14 1396 + * PLL_reg3 = (D4 << 21) | (D3 << 18) | (D1 << 15) | (m2div_int << 5); 1397 + */ 1398 + pll_reg_5 = REGVAL(2); 1399 + pll_reg_3 = REGVAL(1); 1400 + pll_reg_57 = REGVAL(3); 1401 + m2div_frac = pll_reg_5; 1402 + 1403 + /* 1404 + * From forward algorithm we know 1405 + * m2div = 2 * m2 1406 + * val = y * frequency * 5 1407 + * So now, 1408 + * frequency = (m2 * 2 * refclk_khz / (d8 * 10)) 1409 + * frequency = (m2div * refclk_khz / (d8 * 10)) 1410 + */ 1411 + d8 = (pll_reg_57 & REG_GENMASK(14, 7)) >> 7; 1412 + m2div_int = (pll_reg_3 & REG_GENMASK(14, 5)) >> 5; 1413 + temp0 = ((u64)m2div_frac * REF_CLK_KHZ) >> 32; 1414 + temp1 = (u64)m2div_int * REF_CLK_KHZ; 1415 + if (d8 == 0) 1416 + return 0; 1417 + 1418 + clk = div_u64((temp1 + temp0), d8 * 10); 1419 + 1420 + return clk; 1421 + } 1422 + 1423 + int 1424 + intel_lt_phy_calc_port_clock(struct intel_encoder *encoder, 1425 + const struct intel_crtc_state *crtc_state) 1426 + { 1427 + int clk; 1428 + const struct intel_lt_phy_pll_state *lt_state = 1429 + &crtc_state->dpll_hw_state.ltpll; 1430 + u8 mode, rate; 1431 + 1432 + mode = REG_FIELD_GET8(LT_PHY_VDR_MODE_ENCODING_MASK, 1433 + lt_state->config[0]); 1434 + /* 1435 + * For edp/dp read the clock value from the tables 1436 + * and return the clock as the algorithm used for 1437 + * calculating the port clock does not exactly matches 1438 + * with edp/dp clock. 1439 + */ 1440 + if (mode == MODE_DP) { 1441 + rate = REG_FIELD_GET8(LT_PHY_VDR_RATE_ENCODING_MASK, 1442 + lt_state->config[0]); 1443 + clk = intel_lt_phy_get_dp_clock(rate); 1444 + } else { 1445 + clk = intel_lt_phy_calc_hdmi_port_clock(lt_state); 1446 + } 1447 + 1448 + return clk; 1449 + } 1450 + 1451 + int 1452 + intel_lt_phy_pll_calc_state(struct intel_crtc_state *crtc_state, 1453 + struct intel_encoder *encoder) 1454 + { 1455 + const struct intel_lt_phy_pll_state * const *tables; 1456 + int i; 1457 + 1458 + tables = intel_lt_phy_pll_tables_get(crtc_state, encoder); 1459 + if (!tables) 1460 + return -EINVAL; 1461 + 1462 + for (i = 0; tables[i]; i++) { 1463 + if (crtc_state->port_clock == tables[i]->clock) { 1464 + crtc_state->dpll_hw_state.ltpll = *tables[i]; 1465 + if (intel_crtc_has_dp_encoder(crtc_state)) { 1466 + if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP)) 1467 + crtc_state->dpll_hw_state.ltpll.config[2] = 1; 1468 + } 1469 + crtc_state->dpll_hw_state.ltpll.ssc_enabled = 1470 + intel_lt_phy_pll_is_ssc_enabled(crtc_state, encoder); 1471 + return 0; 1472 + } 1473 + } 1474 + 1475 + /* TODO: Add a function to compute the data for HDMI TMDS*/ 1476 + 1477 + return -EINVAL; 1478 + } 1479 + 1480 + static void 1481 + intel_lt_phy_program_pll(struct intel_encoder *encoder, 1482 + const struct intel_crtc_state *crtc_state) 1483 + { 1484 + u8 owned_lane_mask = intel_lt_phy_get_owned_lane_mask(encoder); 1485 + int i, j, k; 1486 + 1487 + intel_lt_phy_write(encoder, owned_lane_mask, LT_PHY_VDR_0_CONFIG, 1488 + crtc_state->dpll_hw_state.ltpll.config[0], MB_WRITE_COMMITTED); 1489 + intel_lt_phy_write(encoder, INTEL_LT_PHY_LANE0, LT_PHY_VDR_1_CONFIG, 1490 + crtc_state->dpll_hw_state.ltpll.config[1], MB_WRITE_COMMITTED); 1491 + intel_lt_phy_write(encoder, owned_lane_mask, LT_PHY_VDR_2_CONFIG, 1492 + crtc_state->dpll_hw_state.ltpll.config[2], MB_WRITE_COMMITTED); 1493 + 1494 + for (i = 0; i <= 12; i++) { 1495 + intel_lt_phy_write(encoder, INTEL_LT_PHY_LANE0, LT_PHY_VDR_X_ADDR_MSB(i), 1496 + crtc_state->dpll_hw_state.ltpll.addr_msb[i], 1497 + MB_WRITE_COMMITTED); 1498 + intel_lt_phy_write(encoder, INTEL_LT_PHY_LANE0, LT_PHY_VDR_X_ADDR_LSB(i), 1499 + crtc_state->dpll_hw_state.ltpll.addr_lsb[i], 1500 + MB_WRITE_COMMITTED); 1501 + 1502 + for (j = 3, k = 0; j >= 0; j--, k++) 1503 + intel_lt_phy_write(encoder, INTEL_LT_PHY_LANE0, 1504 + LT_PHY_VDR_X_DATAY(i, j), 1505 + crtc_state->dpll_hw_state.ltpll.data[i][k], 1506 + MB_WRITE_COMMITTED); 1507 + } 1508 + } 1509 + 1510 + static void 1511 + intel_lt_phy_enable_disable_tx(struct intel_encoder *encoder, 1512 + const struct intel_crtc_state *crtc_state) 1513 + { 1514 + struct intel_digital_port *dig_port = enc_to_dig_port(encoder); 1515 + bool lane_reversal = dig_port->lane_reversal; 1516 + u8 lane_count = crtc_state->lane_count; 1517 + bool is_dp_alt = 1518 + intel_tc_port_in_dp_alt_mode(dig_port); 1519 + enum intel_tc_pin_assignment tc_pin = 1520 + intel_tc_port_get_pin_assignment(dig_port); 1521 + u8 transmitter_mask = 0; 1522 + 1523 + /* 1524 + * We have a two transmitters per lane and total of 2 PHY lanes so a total 1525 + * of 4 transmitters. We prepare a mask of the lanes that need to be activated 1526 + * and the transmitter which need to be activated for each lane. TX 0,1 correspond 1527 + * to LANE0 and TX 2, 3 correspond to LANE1. 1528 + */ 1529 + 1530 + switch (lane_count) { 1531 + case 1: 1532 + transmitter_mask = lane_reversal ? REG_BIT8(3) : REG_BIT8(0); 1533 + if (is_dp_alt) { 1534 + if (tc_pin == INTEL_TC_PIN_ASSIGNMENT_D) 1535 + transmitter_mask = REG_BIT8(0); 1536 + else 1537 + transmitter_mask = REG_BIT8(1); 1538 + } 1539 + break; 1540 + case 2: 1541 + transmitter_mask = lane_reversal ? REG_GENMASK8(3, 2) : REG_GENMASK8(1, 0); 1542 + if (is_dp_alt) 1543 + transmitter_mask = REG_GENMASK8(1, 0); 1544 + break; 1545 + case 3: 1546 + transmitter_mask = lane_reversal ? REG_GENMASK8(3, 1) : REG_GENMASK8(2, 0); 1547 + if (is_dp_alt) 1548 + transmitter_mask = REG_GENMASK8(2, 0); 1549 + break; 1550 + case 4: 1551 + transmitter_mask = REG_GENMASK8(3, 0); 1552 + break; 1553 + default: 1554 + MISSING_CASE(lane_count); 1555 + transmitter_mask = REG_GENMASK8(3, 0); 1556 + break; 1557 + } 1558 + 1559 + if (transmitter_mask & BIT(0)) { 1560 + intel_lt_phy_p2p_write(encoder, INTEL_LT_PHY_LANE0, LT_PHY_TXY_CTL10(0), 1561 + LT_PHY_TX_LANE_ENABLE, LT_PHY_TXY_CTL10_MAC(0), 1562 + LT_PHY_TX_LANE_ENABLE); 1563 + } else { 1564 + intel_lt_phy_p2p_write(encoder, INTEL_LT_PHY_LANE0, LT_PHY_TXY_CTL10(0), 1565 + 0, LT_PHY_TXY_CTL10_MAC(0), 0); 1566 + } 1567 + 1568 + if (transmitter_mask & BIT(1)) { 1569 + intel_lt_phy_p2p_write(encoder, INTEL_LT_PHY_LANE0, LT_PHY_TXY_CTL10(1), 1570 + LT_PHY_TX_LANE_ENABLE, LT_PHY_TXY_CTL10_MAC(1), 1571 + LT_PHY_TX_LANE_ENABLE); 1572 + } else { 1573 + intel_lt_phy_p2p_write(encoder, INTEL_LT_PHY_LANE0, LT_PHY_TXY_CTL10(1), 1574 + 0, LT_PHY_TXY_CTL10_MAC(1), 0); 1575 + } 1576 + 1577 + if (transmitter_mask & BIT(2)) { 1578 + intel_lt_phy_p2p_write(encoder, INTEL_LT_PHY_LANE1, LT_PHY_TXY_CTL10(0), 1579 + LT_PHY_TX_LANE_ENABLE, LT_PHY_TXY_CTL10_MAC(0), 1580 + LT_PHY_TX_LANE_ENABLE); 1581 + } else { 1582 + intel_lt_phy_p2p_write(encoder, INTEL_LT_PHY_LANE1, LT_PHY_TXY_CTL10(0), 1583 + 0, LT_PHY_TXY_CTL10_MAC(0), 0); 1584 + } 1585 + 1586 + if (transmitter_mask & BIT(3)) { 1587 + intel_lt_phy_p2p_write(encoder, INTEL_LT_PHY_LANE1, LT_PHY_TXY_CTL10(1), 1588 + LT_PHY_TX_LANE_ENABLE, LT_PHY_TXY_CTL10_MAC(1), 1589 + LT_PHY_TX_LANE_ENABLE); 1590 + } else { 1591 + intel_lt_phy_p2p_write(encoder, INTEL_LT_PHY_LANE1, LT_PHY_TXY_CTL10(1), 1592 + 0, LT_PHY_TXY_CTL10_MAC(1), 0); 1593 + } 1594 + } 1595 + 1596 + void intel_lt_phy_pll_enable(struct intel_encoder *encoder, 1597 + const struct intel_crtc_state *crtc_state) 1598 + { 1599 + struct intel_display *display = to_intel_display(encoder); 1600 + struct intel_digital_port *dig_port = enc_to_dig_port(encoder); 1601 + bool lane_reversal = dig_port->lane_reversal; 1602 + u8 owned_lane_mask = intel_lt_phy_get_owned_lane_mask(encoder); 1603 + enum phy phy = intel_encoder_to_phy(encoder); 1604 + enum port port = encoder->port; 1605 + intel_wakeref_t wakeref = 0; 1606 + u32 lane_phy_pulse_status = owned_lane_mask == INTEL_LT_PHY_BOTH_LANES 1607 + ? (XE3PLPDP_LANE_PHY_PULSE_STATUS(0) | 1608 + XE3PLPDP_LANE_PHY_PULSE_STATUS(1)) 1609 + : XE3PLPDP_LANE_PHY_PULSE_STATUS(0); 1610 + u8 rate_update; 1611 + 1612 + wakeref = intel_lt_phy_transaction_begin(encoder); 1613 + 1614 + /* 1. Enable MacCLK at default 162 MHz frequency. */ 1615 + intel_lt_phy_lane_reset(encoder, crtc_state->lane_count); 1616 + 1617 + /* 2. Program PORT_CLOCK_CTL register to configure clock muxes, gating, and SSC. */ 1618 + intel_lt_phy_program_port_clock_ctl(encoder, crtc_state, lane_reversal); 1619 + 1620 + /* 3. Change owned PHY lanes power to Ready state. */ 1621 + intel_lt_phy_powerdown_change_sequence(encoder, owned_lane_mask, 1622 + XELPDP_P2_STATE_READY); 1623 + 1624 + /* 1625 + * 4. Read the PHY message bus VDR register PHY_VDR_0_Config check enabled PLL type, 1626 + * encoded rate and encoded mode. 1627 + */ 1628 + if (intel_lt_phy_config_changed(encoder, crtc_state)) { 1629 + /* 1630 + * 5. Program the PHY internal PLL registers over PHY message bus for the desired 1631 + * frequency and protocol type 1632 + */ 1633 + intel_lt_phy_program_pll(encoder, crtc_state); 1634 + 1635 + /* 6. Use the P2P transaction flow */ 1636 + /* 1637 + * 6.1. Set the PHY VDR register 0xCC4[Rate Control VDR Update] = 1 over PHY message 1638 + * bus for Owned PHY Lanes. 1639 + */ 1640 + /* 1641 + * 6.2. Poll for P2P Transaction Ready = "1" and read the MAC message bus VDR 1642 + * register at offset 0xC00 for Owned PHY Lanes*. 1643 + */ 1644 + /* 6.3. Clear P2P transaction Ready bit. */ 1645 + intel_lt_phy_p2p_write(encoder, owned_lane_mask, LT_PHY_RATE_UPDATE, 1646 + LT_PHY_RATE_CONTROL_VDR_UPDATE, LT_PHY_MAC_VDR, 1647 + LT_PHY_PCLKIN_GATE); 1648 + 1649 + /* 7. Program PORT_CLOCK_CTL[PCLK PLL Request LN0] = 0. */ 1650 + intel_de_rmw(display, XELPDP_PORT_CLOCK_CTL(display, port), 1651 + XELPDP_LANE_PCLK_PLL_REQUEST(0), 0); 1652 + 1653 + /* 8. Poll for PORT_CLOCK_CTL[PCLK PLL Ack LN0]= 0. */ 1654 + if (intel_de_wait_custom(display, XELPDP_PORT_CLOCK_CTL(display, port), 1655 + XELPDP_LANE_PCLK_PLL_ACK(0), 0, 1656 + XE3PLPD_MACCLK_TURNOFF_LATENCY_US, 0, NULL)) 1657 + drm_warn(display->drm, "PHY %c PLL MacCLK Ack deassertion Timeout after %dus.\n", 1658 + phy_name(phy), XE3PLPD_MACCLK_TURNOFF_LATENCY_US); 1659 + 1660 + /* 1661 + * 9. Follow the Display Voltage Frequency Switching - Sequence Before Frequency 1662 + * Change. We handle this step in bxt_set_cdclk(). 1663 + */ 1664 + /* 10. Program DDI_CLK_VALFREQ to match intended DDI clock frequency. */ 1665 + intel_de_write(display, DDI_CLK_VALFREQ(encoder->port), 1666 + crtc_state->port_clock); 1667 + 1668 + /* 11. Program PORT_CLOCK_CTL[PCLK PLL Request LN0] = 1. */ 1669 + intel_de_rmw(display, XELPDP_PORT_CLOCK_CTL(display, port), 1670 + XELPDP_LANE_PCLK_PLL_REQUEST(0), 1671 + XELPDP_LANE_PCLK_PLL_REQUEST(0)); 1672 + 1673 + /* 12. Poll for PORT_CLOCK_CTL[PCLK PLL Ack LN0]= 1. */ 1674 + if (intel_de_wait_custom(display, XELPDP_PORT_CLOCK_CTL(display, port), 1675 + XELPDP_LANE_PCLK_PLL_ACK(0), 1676 + XELPDP_LANE_PCLK_PLL_ACK(0), 1677 + XE3PLPD_MACCLK_TURNON_LATENCY_US, 2, NULL)) 1678 + drm_warn(display->drm, "PHY %c PLL MacCLK Ack assertion Timeout after %dus.\n", 1679 + phy_name(phy), XE3PLPD_MACCLK_TURNON_LATENCY_US); 1680 + 1681 + /* 1682 + * 13. Ungate the forward clock by setting 1683 + * PORT_CLOCK_CTL[Forward Clock Ungate] = 1. 1684 + */ 1685 + intel_de_rmw(display, XELPDP_PORT_CLOCK_CTL(display, port), 1686 + XELPDP_FORWARD_CLOCK_UNGATE, 1687 + XELPDP_FORWARD_CLOCK_UNGATE); 1688 + 1689 + /* 14. SW clears PORT_BUF_CTL2 [PHY Pulse Status]. */ 1690 + intel_de_rmw(display, XELPDP_PORT_BUF_CTL2(display, port), 1691 + lane_phy_pulse_status, 1692 + lane_phy_pulse_status); 1693 + /* 1694 + * 15. Clear the PHY VDR register 0xCC4[Rate Control VDR Update] over 1695 + * PHY message bus for Owned PHY Lanes. 1696 + */ 1697 + rate_update = intel_lt_phy_read(encoder, INTEL_LT_PHY_LANE0, LT_PHY_RATE_UPDATE); 1698 + rate_update &= ~LT_PHY_RATE_CONTROL_VDR_UPDATE; 1699 + intel_lt_phy_write(encoder, owned_lane_mask, LT_PHY_RATE_UPDATE, 1700 + rate_update, MB_WRITE_COMMITTED); 1701 + 1702 + /* 16. Poll for PORT_BUF_CTL2 register PHY Pulse Status = 1 for Owned PHY Lanes. */ 1703 + if (intel_de_wait_custom(display, XELPDP_PORT_BUF_CTL2(display, port), 1704 + lane_phy_pulse_status, lane_phy_pulse_status, 1705 + XE3PLPD_RATE_CALIB_DONE_LATENCY_US, 2, NULL)) 1706 + drm_warn(display->drm, "PHY %c PLL rate not changed after %dus.\n", 1707 + phy_name(phy), XE3PLPD_RATE_CALIB_DONE_LATENCY_US); 1708 + 1709 + /* 17. SW clears PORT_BUF_CTL2 [PHY Pulse Status]. */ 1710 + intel_de_rmw(display, XELPDP_PORT_BUF_CTL2(display, port), 1711 + lane_phy_pulse_status, 1712 + lane_phy_pulse_status); 1713 + } else { 1714 + intel_de_write(display, DDI_CLK_VALFREQ(encoder->port), crtc_state->port_clock); 1715 + } 1716 + 1717 + /* 1718 + * 18. Follow the Display Voltage Frequency Switching - Sequence After Frequency Change. 1719 + * We handle this step in bxt_set_cdclk() 1720 + */ 1721 + /* 19. Move the PHY powerdown state to Active and program to enable/disable transmitters */ 1722 + intel_lt_phy_powerdown_change_sequence(encoder, owned_lane_mask, 1723 + XELPDP_P0_STATE_ACTIVE); 1724 + 1725 + intel_lt_phy_enable_disable_tx(encoder, crtc_state); 1726 + intel_lt_phy_transaction_end(encoder, wakeref); 1727 + } 1728 + 1729 + void intel_lt_phy_pll_disable(struct intel_encoder *encoder) 1730 + { 1731 + struct intel_display *display = to_intel_display(encoder); 1732 + enum phy phy = intel_encoder_to_phy(encoder); 1733 + enum port port = encoder->port; 1734 + intel_wakeref_t wakeref; 1735 + u8 owned_lane_mask = intel_lt_phy_get_owned_lane_mask(encoder); 1736 + u32 lane_pipe_reset = owned_lane_mask == INTEL_LT_PHY_BOTH_LANES 1737 + ? (XELPDP_LANE_PIPE_RESET(0) | 1738 + XELPDP_LANE_PIPE_RESET(1)) 1739 + : XELPDP_LANE_PIPE_RESET(0); 1740 + u32 lane_phy_current_status = owned_lane_mask == INTEL_LT_PHY_BOTH_LANES 1741 + ? (XELPDP_LANE_PHY_CURRENT_STATUS(0) | 1742 + XELPDP_LANE_PHY_CURRENT_STATUS(1)) 1743 + : XELPDP_LANE_PHY_CURRENT_STATUS(0); 1744 + u32 lane_phy_pulse_status = owned_lane_mask == INTEL_LT_PHY_BOTH_LANES 1745 + ? (XE3PLPDP_LANE_PHY_PULSE_STATUS(0) | 1746 + XE3PLPDP_LANE_PHY_PULSE_STATUS(1)) 1747 + : XE3PLPDP_LANE_PHY_PULSE_STATUS(0); 1748 + 1749 + wakeref = intel_lt_phy_transaction_begin(encoder); 1750 + 1751 + /* 1. Clear PORT_BUF_CTL2 [PHY Pulse Status]. */ 1752 + intel_de_rmw(display, XELPDP_PORT_BUF_CTL2(display, port), 1753 + lane_phy_pulse_status, 1754 + lane_phy_pulse_status); 1755 + 1756 + /* 2. Set PORT_BUF_CTL2<port> Lane<PHY Lanes Owned> Pipe Reset to 1. */ 1757 + intel_de_rmw(display, XELPDP_PORT_BUF_CTL2(display, port), lane_pipe_reset, 1758 + lane_pipe_reset); 1759 + 1760 + /* 3. Poll for PORT_BUF_CTL2<port> Lane<PHY Lanes Owned> PHY Current Status == 1. */ 1761 + if (intel_de_wait_custom(display, XELPDP_PORT_BUF_CTL2(display, port), 1762 + lane_phy_current_status, 1763 + lane_phy_current_status, 1764 + XE3PLPD_RESET_START_LATENCY_US, 0, NULL)) 1765 + drm_warn(display->drm, 1766 + "PHY %c failed to reset Lane after %dms.\n", 1767 + phy_name(phy), XE3PLPD_RESET_START_LATENCY_US); 1768 + 1769 + /* 4. Clear for PHY pulse status on owned PHY lanes. */ 1770 + intel_de_rmw(display, XELPDP_PORT_BUF_CTL2(display, port), 1771 + lane_phy_pulse_status, 1772 + lane_phy_pulse_status); 1773 + 1774 + /* 1775 + * 5. Follow the Display Voltage Frequency Switching - 1776 + * Sequence Before Frequency Change. We handle this step in bxt_set_cdclk(). 1777 + */ 1778 + /* 6. Program PORT_CLOCK_CTL[PCLK PLL Request LN0] = 0. */ 1779 + intel_de_rmw(display, XELPDP_PORT_CLOCK_CTL(display, port), 1780 + XELPDP_LANE_PCLK_PLL_REQUEST(0), 0); 1781 + 1782 + /* 7. Program DDI_CLK_VALFREQ to 0. */ 1783 + intel_de_write(display, DDI_CLK_VALFREQ(encoder->port), 0); 1784 + 1785 + /* 8. Poll for PORT_CLOCK_CTL[PCLK PLL Ack LN0]= 0. */ 1786 + if (intel_de_wait_custom(display, XELPDP_PORT_CLOCK_CTL(display, port), 1787 + XELPDP_LANE_PCLK_PLL_ACK(0), 0, 1788 + XE3PLPD_MACCLK_TURNOFF_LATENCY_US, 0, NULL)) 1789 + drm_warn(display->drm, "PHY %c PLL MacCLK Ack deassertion Timeout after %dus.\n", 1790 + phy_name(phy), XE3PLPD_MACCLK_TURNOFF_LATENCY_US); 1791 + 1792 + /* 1793 + * 9. Follow the Display Voltage Frequency Switching - 1794 + * Sequence After Frequency Change. We handle this step in bxt_set_cdclk(). 1795 + */ 1796 + /* 10. Program PORT_CLOCK_CTL register to disable and gate clocks. */ 1797 + intel_de_rmw(display, XELPDP_PORT_CLOCK_CTL(display, port), 1798 + XELPDP_DDI_CLOCK_SELECT_MASK(display) | XELPDP_FORWARD_CLOCK_UNGATE, 0); 1799 + 1800 + /* 11. Program PORT_BUF_CTL5[MacCLK Reset_0] = 1 to assert MacCLK reset. */ 1801 + intel_de_rmw(display, XE3PLPD_PORT_BUF_CTL5(port), 1802 + XE3PLPD_MACCLK_RESET_0, XE3PLPD_MACCLK_RESET_0); 1803 + 1804 + intel_lt_phy_transaction_end(encoder, wakeref); 1805 + } 1806 + 1807 + void intel_lt_phy_set_signal_levels(struct intel_encoder *encoder, 1808 + const struct intel_crtc_state *crtc_state) 1809 + { 1810 + struct intel_display *display = to_intel_display(encoder); 1811 + const struct intel_ddi_buf_trans *trans; 1812 + u8 owned_lane_mask; 1813 + intel_wakeref_t wakeref; 1814 + int n_entries, ln; 1815 + struct intel_digital_port *dig_port = enc_to_dig_port(encoder); 1816 + 1817 + if (intel_tc_port_in_tbt_alt_mode(dig_port)) 1818 + return; 1819 + 1820 + owned_lane_mask = intel_lt_phy_get_owned_lane_mask(encoder); 1821 + 1822 + wakeref = intel_lt_phy_transaction_begin(encoder); 1823 + 1824 + trans = encoder->get_buf_trans(encoder, crtc_state, &n_entries); 1825 + if (drm_WARN_ON_ONCE(display->drm, !trans)) { 1826 + intel_lt_phy_transaction_end(encoder, wakeref); 1827 + return; 1828 + } 1829 + 1830 + for (ln = 0; ln < crtc_state->lane_count; ln++) { 1831 + int level = intel_ddi_level(encoder, crtc_state, ln); 1832 + int lane = ln / 2; 1833 + int tx = ln % 2; 1834 + u8 lane_mask = lane == 0 ? INTEL_LT_PHY_LANE0 : INTEL_LT_PHY_LANE1; 1835 + 1836 + if (!(lane_mask & owned_lane_mask)) 1837 + continue; 1838 + 1839 + intel_lt_phy_rmw(encoder, lane_mask, LT_PHY_TXY_CTL8(tx), 1840 + LT_PHY_TX_SWING_LEVEL_MASK | LT_PHY_TX_SWING_MASK, 1841 + LT_PHY_TX_SWING_LEVEL(trans->entries[level].lt.txswing_level) | 1842 + LT_PHY_TX_SWING(trans->entries[level].lt.txswing), 1843 + MB_WRITE_COMMITTED); 1844 + 1845 + intel_lt_phy_rmw(encoder, lane_mask, LT_PHY_TXY_CTL2(tx), 1846 + LT_PHY_TX_CURSOR_MASK, 1847 + LT_PHY_TX_CURSOR(trans->entries[level].lt.pre_cursor), 1848 + MB_WRITE_COMMITTED); 1849 + intel_lt_phy_rmw(encoder, lane_mask, LT_PHY_TXY_CTL3(tx), 1850 + LT_PHY_TX_CURSOR_MASK, 1851 + LT_PHY_TX_CURSOR(trans->entries[level].lt.main_cursor), 1852 + MB_WRITE_COMMITTED); 1853 + intel_lt_phy_rmw(encoder, lane_mask, LT_PHY_TXY_CTL4(tx), 1854 + LT_PHY_TX_CURSOR_MASK, 1855 + LT_PHY_TX_CURSOR(trans->entries[level].lt.post_cursor), 1856 + MB_WRITE_COMMITTED); 1857 + } 1858 + 1859 + intel_lt_phy_transaction_end(encoder, wakeref); 1860 + } 1861 + 1862 + void intel_lt_phy_dump_hw_state(struct intel_display *display, 1863 + const struct intel_lt_phy_pll_state *hw_state) 1864 + { 1865 + int i, j; 1866 + 1867 + drm_dbg_kms(display->drm, "lt_phy_pll_hw_state:\n"); 1868 + for (i = 0; i < 3; i++) { 1869 + drm_dbg_kms(display->drm, "config[%d] = 0x%.4x,\n", 1870 + i, hw_state->config[i]); 1871 + } 1872 + 1873 + for (i = 0; i <= 12; i++) 1874 + for (j = 3; j >= 0; j--) 1875 + drm_dbg_kms(display->drm, "vdr_data[%d][%d] = 0x%.4x,\n", 1876 + i, j, hw_state->data[i][j]); 1877 + } 1878 + 1879 + bool 1880 + intel_lt_phy_pll_compare_hw_state(const struct intel_lt_phy_pll_state *a, 1881 + const struct intel_lt_phy_pll_state *b) 1882 + { 1883 + if (memcmp(&a->config, &b->config, sizeof(a->config)) != 0) 1884 + return false; 1885 + 1886 + if (memcmp(&a->data, &b->data, sizeof(a->data)) != 0) 1887 + return false; 1888 + 1889 + return true; 1890 + } 1891 + 1892 + void intel_lt_phy_pll_readout_hw_state(struct intel_encoder *encoder, 1893 + const struct intel_crtc_state *crtc_state, 1894 + struct intel_lt_phy_pll_state *pll_state) 1895 + { 1896 + u8 owned_lane_mask; 1897 + u8 lane; 1898 + intel_wakeref_t wakeref; 1899 + int i, j, k; 1900 + 1901 + pll_state->tbt_mode = intel_tc_port_in_tbt_alt_mode(enc_to_dig_port(encoder)); 1902 + if (pll_state->tbt_mode) 1903 + return; 1904 + 1905 + owned_lane_mask = intel_lt_phy_get_owned_lane_mask(encoder); 1906 + lane = owned_lane_mask & INTEL_LT_PHY_LANE0 ? : INTEL_LT_PHY_LANE1; 1907 + wakeref = intel_lt_phy_transaction_begin(encoder); 1908 + 1909 + pll_state->config[0] = intel_lt_phy_read(encoder, lane, LT_PHY_VDR_0_CONFIG); 1910 + pll_state->config[1] = intel_lt_phy_read(encoder, INTEL_LT_PHY_LANE0, LT_PHY_VDR_1_CONFIG); 1911 + pll_state->config[2] = intel_lt_phy_read(encoder, lane, LT_PHY_VDR_2_CONFIG); 1912 + 1913 + for (i = 0; i <= 12; i++) { 1914 + for (j = 3, k = 0; j >= 0; j--, k++) 1915 + pll_state->data[i][k] = 1916 + intel_lt_phy_read(encoder, INTEL_LT_PHY_LANE0, 1917 + LT_PHY_VDR_X_DATAY(i, j)); 1918 + } 1919 + 1920 + pll_state->clock = 1921 + intel_lt_phy_calc_port_clock(encoder, crtc_state); 1922 + intel_lt_phy_transaction_end(encoder, wakeref); 1923 + } 1924 + 1925 + void intel_lt_phy_pll_state_verify(struct intel_atomic_state *state, 1926 + struct intel_crtc *crtc) 1927 + { 1928 + struct intel_display *display = to_intel_display(state); 1929 + struct intel_digital_port *dig_port; 1930 + const struct intel_crtc_state *new_crtc_state = 1931 + intel_atomic_get_new_crtc_state(state, crtc); 1932 + struct intel_encoder *encoder; 1933 + struct intel_lt_phy_pll_state pll_hw_state = {}; 1934 + const struct intel_lt_phy_pll_state *pll_sw_state = &new_crtc_state->dpll_hw_state.ltpll; 1935 + int clock; 1936 + int i, j; 1937 + 1938 + if (DISPLAY_VER(display) < 35) 1939 + return; 1940 + 1941 + if (!new_crtc_state->hw.active) 1942 + return; 1943 + 1944 + /* intel_get_crtc_new_encoder() only works for modeset/fastset commits */ 1945 + if (!intel_crtc_needs_modeset(new_crtc_state) && 1946 + !intel_crtc_needs_fastset(new_crtc_state)) 1947 + return; 1948 + 1949 + encoder = intel_get_crtc_new_encoder(state, new_crtc_state); 1950 + intel_lt_phy_pll_readout_hw_state(encoder, new_crtc_state, &pll_hw_state); 1951 + clock = intel_lt_phy_calc_port_clock(encoder, new_crtc_state); 1952 + 1953 + dig_port = enc_to_dig_port(encoder); 1954 + if (intel_tc_port_in_tbt_alt_mode(dig_port)) 1955 + return; 1956 + 1957 + INTEL_DISPLAY_STATE_WARN(display, pll_hw_state.clock != clock, 1958 + "[CRTC:%d:%s] mismatch in LT PHY: Register CLOCK (expected %d, found %d)", 1959 + crtc->base.base.id, crtc->base.name, 1960 + pll_sw_state->clock, pll_hw_state.clock); 1961 + 1962 + for (i = 0; i < 3; i++) { 1963 + INTEL_DISPLAY_STATE_WARN(display, pll_hw_state.config[i] != pll_sw_state->config[i], 1964 + "[CRTC:%d:%s] mismatch in LT PHY PLL CONFIG%d: (expected 0x%04x, found 0x%04x)", 1965 + crtc->base.base.id, crtc->base.name, i, 1966 + pll_sw_state->config[i], pll_hw_state.config[i]); 1967 + } 1968 + 1969 + for (i = 0; i <= 12; i++) { 1970 + for (j = 3; j >= 0; j--) 1971 + INTEL_DISPLAY_STATE_WARN(display, 1972 + pll_hw_state.data[i][j] != 1973 + pll_sw_state->data[i][j], 1974 + "[CRTC:%d:%s] mismatch in LT PHY PLL DATA[%d][%d]: (expected 0x%04x, found 0x%04x)", 1975 + crtc->base.base.id, crtc->base.name, i, j, 1976 + pll_sw_state->data[i][j], pll_hw_state.data[i][j]); 1977 + } 1978 + } 1979 + 1980 + void intel_xe3plpd_pll_enable(struct intel_encoder *encoder, 1981 + const struct intel_crtc_state *crtc_state) 1982 + { 1983 + struct intel_digital_port *dig_port = enc_to_dig_port(encoder); 1984 + 1985 + if (intel_tc_port_in_tbt_alt_mode(dig_port)) 1986 + intel_mtl_tbt_pll_enable(encoder, crtc_state); 1987 + else 1988 + intel_lt_phy_pll_enable(encoder, crtc_state); 1989 + } 1990 + 1991 + void intel_xe3plpd_pll_disable(struct intel_encoder *encoder) 1992 + { 1993 + struct intel_digital_port *dig_port = enc_to_dig_port(encoder); 1994 + 1995 + if (intel_tc_port_in_tbt_alt_mode(dig_port)) 1996 + intel_mtl_tbt_pll_disable(encoder); 1997 + else 1998 + intel_lt_phy_pll_disable(encoder); 1999 + 2000 + }
+44
drivers/gpu/drm/i915/display/intel_lt_phy.h
··· 1 + /* SPDX-License-Identifier: MIT 2 + * 3 + * Copyright © 2025 Intel Corporation 4 + */ 5 + 6 + #ifndef __INTEL_LT_PHY_H__ 7 + #define __INTEL_LT_PHY_H__ 8 + 9 + #include <linux/types.h> 10 + 11 + struct intel_atomic_state; 12 + struct intel_display; 13 + struct intel_encoder; 14 + struct intel_crtc_state; 15 + struct intel_crtc; 16 + struct intel_lt_phy_pll_state; 17 + 18 + void intel_lt_phy_pll_enable(struct intel_encoder *encoder, 19 + const struct intel_crtc_state *crtc_state); 20 + void intel_lt_phy_pll_disable(struct intel_encoder *encoder); 21 + int 22 + intel_lt_phy_pll_calc_state(struct intel_crtc_state *crtc_state, 23 + struct intel_encoder *encoder); 24 + int intel_lt_phy_calc_port_clock(struct intel_encoder *encoder, 25 + const struct intel_crtc_state *crtc_state); 26 + void intel_lt_phy_set_signal_levels(struct intel_encoder *encoder, 27 + const struct intel_crtc_state *crtc_state); 28 + void intel_lt_phy_dump_hw_state(struct intel_display *display, 29 + const struct intel_lt_phy_pll_state *hw_state); 30 + bool 31 + intel_lt_phy_pll_compare_hw_state(const struct intel_lt_phy_pll_state *a, 32 + const struct intel_lt_phy_pll_state *b); 33 + void intel_lt_phy_pll_readout_hw_state(struct intel_encoder *encoder, 34 + const struct intel_crtc_state *crtc_state, 35 + struct intel_lt_phy_pll_state *pll_state); 36 + void intel_lt_phy_pll_state_verify(struct intel_atomic_state *state, 37 + struct intel_crtc *crtc); 38 + void intel_xe3plpd_pll_enable(struct intel_encoder *encoder, 39 + const struct intel_crtc_state *crtc_state); 40 + void intel_xe3plpd_pll_disable(struct intel_encoder *encoder); 41 + 42 + #define HAS_LT_PHY(display) (DISPLAY_VER(display) >= 35) 43 + 44 + #endif /* __INTEL_LT_PHY_H__ */
+75
drivers/gpu/drm/i915/display/intel_lt_phy_regs.h
··· 1 + /* SPDX-License-Identifier: MIT 2 + * 3 + * Copyright © 2025 Intel Corporation 4 + */ 5 + 6 + #ifndef __INTEL_LT_PHY_REGS_H__ 7 + #define __INTEL_LT_PHY_REGS_H__ 8 + 9 + #define XE3PLPD_MSGBUS_TIMEOUT_FAST_US 500 10 + #define XE3PLPD_MACCLK_TURNON_LATENCY_MS 1 11 + #define XE3PLPD_MACCLK_TURNON_LATENCY_US 21 12 + #define XE3PLPD_MACCLK_TURNOFF_LATENCY_US 1 13 + #define XE3PLPD_RATE_CALIB_DONE_LATENCY_US 50 14 + #define XE3PLPD_RESET_START_LATENCY_US 10 15 + #define XE3PLPD_PWRDN_TO_RDY_LATENCY_US 4 16 + #define XE3PLPD_RESET_END_LATENCY_US 200 17 + 18 + /* LT Phy MAC Register */ 19 + #define LT_PHY_MAC_VDR _MMIO(0xC00) 20 + #define LT_PHY_PCLKIN_GATE REG_BIT8(0) 21 + 22 + /* LT Phy Pipe Spec Registers */ 23 + #define LT_PHY_TXY_CTL8(idx) (0x408 + (0x200 * (idx))) 24 + #define LT_PHY_TX_SWING_LEVEL_MASK REG_GENMASK8(7, 4) 25 + #define LT_PHY_TX_SWING_LEVEL(val) REG_FIELD_PREP8(LT_PHY_TX_SWING_LEVEL_MASK, val) 26 + #define LT_PHY_TX_SWING_MASK REG_BIT8(3) 27 + #define LT_PHY_TX_SWING(val) REG_FIELD_PREP8(LT_PHY_TX_SWING_MASK, val) 28 + 29 + #define LT_PHY_TXY_CTL2(idx) (0x402 + (0x200 * (idx))) 30 + #define LT_PHY_TXY_CTL3(idx) (0x403 + (0x200 * (idx))) 31 + #define LT_PHY_TXY_CTL4(idx) (0x404 + (0x200 * (idx))) 32 + #define LT_PHY_TX_CURSOR_MASK REG_GENMASK8(5, 0) 33 + #define LT_PHY_TX_CURSOR(val) REG_FIELD_PREP8(LT_PHY_TX_CURSOR_MASK, val) 34 + 35 + #define LT_PHY_TXY_CTL10(idx) (0x40A + (0x200 * (idx))) 36 + #define LT_PHY_TXY_CTL10_MAC(idx) _MMIO(LT_PHY_TXY_CTL10(idx)) 37 + #define LT_PHY_TX_LANE_ENABLE REG_BIT8(0) 38 + 39 + /* LT Phy Vendor Register */ 40 + #define LT_PHY_VDR_0_CONFIG 0xC02 41 + #define LT_PHY_VDR_DP_PLL_ENABLE REG_BIT(7) 42 + #define LT_PHY_VDR_1_CONFIG 0xC03 43 + #define LT_PHY_VDR_RATE_ENCODING_MASK REG_GENMASK8(6, 3) 44 + #define LT_PHY_VDR_MODE_ENCODING_MASK REG_GENMASK8(2, 0) 45 + #define LT_PHY_VDR_2_CONFIG 0xCC3 46 + 47 + #define LT_PHY_VDR_X_ADDR_MSB(idx) (0xC04 + 0x6 * (idx)) 48 + #define LT_PHY_VDR_X_ADDR_LSB(idx) (0xC05 + 0x6 * (idx)) 49 + 50 + #define LT_PHY_VDR_X_DATAY(idx, y) ((0xC06 + (3 - (y))) + 0x6 * (idx)) 51 + 52 + #define LT_PHY_RATE_UPDATE 0xCC4 53 + #define LT_PHY_RATE_CONTROL_VDR_UPDATE REG_BIT8(0) 54 + 55 + #define _XE3PLPD_PORT_BUF_CTL5(idx) _MMIO(_PICK_EVEN_2RANGES(idx, PORT_TC1, \ 56 + _XELPDP_PORT_BUF_CTL1_LN0_A, \ 57 + _XELPDP_PORT_BUF_CTL1_LN0_B, \ 58 + _XELPDP_PORT_BUF_CTL1_LN0_USBC1, \ 59 + _XELPDP_PORT_BUF_CTL1_LN0_USBC2) \ 60 + + 0x34) 61 + #define XE3PLPD_PORT_BUF_CTL5(port) _XE3PLPD_PORT_BUF_CTL5(__xe2lpd_port_idx(port)) 62 + #define XE3PLPD_MACCLK_RESET_0 REG_BIT(11) 63 + #define XE3PLPD_MACCLK_RATE_MASK REG_GENMASK(4, 0) 64 + #define XE3PLPD_MACCLK_RATE_DEF REG_FIELD_PREP(XE3PLPD_MACCLK_RATE_MASK, 0x1F) 65 + 66 + #define _XE3PLPD_PORT_P2M_MSGBUS_STATUS_P2P(idx, lane) _MMIO(_PICK_EVEN_2RANGES(idx, PORT_TC1, \ 67 + _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_A, \ 68 + _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_B, \ 69 + _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_USBC1, \ 70 + _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_USBC2) \ 71 + + 0x60 + (lane) * 0x4) 72 + #define XE3PLPD_PORT_P2M_MSGBUS_STATUS_P2P(port, lane) _XE3PLPD_PORT_P2M_MSGBUS_STATUS_P2P(__xe2lpd_port_idx(port), \ 73 + lane) 74 + #define XE3LPD_PORT_P2M_ADDR_MASK REG_GENMASK(11, 0) 75 + #endif /* __INTEL_LT_PHY_REGS_H__ */
+11 -3
drivers/gpu/drm/i915/display/intel_modeset_setup.c
··· 19 19 #include "intel_color.h" 20 20 #include "intel_crtc.h" 21 21 #include "intel_crtc_state_dump.h" 22 + #include "intel_dbuf_bw.h" 22 23 #include "intel_ddi.h" 23 24 #include "intel_de.h" 24 25 #include "intel_display.h" ··· 177 176 intel_cdclk_crtc_disable_noatomic(crtc); 178 177 skl_wm_crtc_disable_noatomic(crtc); 179 178 intel_bw_crtc_disable_noatomic(crtc); 179 + intel_dbuf_bw_crtc_disable_noatomic(crtc); 180 180 181 181 intel_pmdemand_update_port_clock(display, pmdemand_state, pipe, 0); 182 182 } ··· 853 851 */ 854 852 if (plane_state->uapi.visible && plane->min_cdclk) { 855 853 if (crtc_state->double_wide || DISPLAY_VER(display) >= 10) 856 - crtc_state->min_cdclk[plane->id] = 854 + crtc_state->plane_min_cdclk[plane->id] = 857 855 DIV_ROUND_UP(crtc_state->pixel_rate, 2); 858 856 else 859 - crtc_state->min_cdclk[plane->id] = 857 + crtc_state->plane_min_cdclk[plane->id] = 860 858 crtc_state->pixel_rate; 861 859 } 862 860 drm_dbg_kms(display->drm, 863 861 "[PLANE:%d:%s] min_cdclk %d kHz\n", 864 862 plane->base.base.id, plane->base.name, 865 - crtc_state->min_cdclk[plane->id]); 863 + crtc_state->plane_min_cdclk[plane->id]); 866 864 } 865 + 866 + crtc_state->min_cdclk = intel_crtc_min_cdclk(crtc_state); 867 + 868 + drm_dbg_kms(display->drm, "[CRTC:%d:%s] min_cdclk %d kHz\n", 869 + crtc->base.base.id, crtc->base.name, crtc_state->min_cdclk); 867 870 868 871 intel_pmdemand_update_port_clock(display, pmdemand_state, pipe, 869 872 crtc_state->port_clock); ··· 879 872 intel_wm_get_hw_state(display); 880 873 881 874 intel_bw_update_hw_state(display); 875 + intel_dbuf_bw_update_hw_state(display); 882 876 intel_cdclk_update_hw_state(display); 883 877 884 878 intel_pmdemand_init_pmdemand_params(display, pmdemand_state);
+2
drivers/gpu/drm/i915/display/intel_modeset_verify.c
··· 16 16 #include "intel_display_core.h" 17 17 #include "intel_display_types.h" 18 18 #include "intel_fdi.h" 19 + #include "intel_lt_phy.h" 19 20 #include "intel_modeset_verify.h" 20 21 #include "intel_snps_phy.h" 21 22 #include "skl_watermark.h" ··· 247 246 intel_dpll_state_verify(state, crtc); 248 247 intel_mpllb_state_verify(state, crtc); 249 248 intel_cx0pll_state_verify(state, crtc); 249 + intel_lt_phy_pll_state_verify(state, crtc); 250 250 } 251 251 252 252 void intel_modeset_verify_disabled(struct intel_atomic_state *state)
+2 -2
drivers/gpu/drm/i915/display/intel_pch.c
··· 5 5 6 6 #include <drm/drm_print.h> 7 7 8 - #include "i915_utils.h" 9 8 #include "intel_display_core.h" 9 + #include "intel_display_utils.h" 10 10 #include "intel_pch.h" 11 11 12 12 #define INTEL_PCH_DEVICE_ID_MASK 0xff80 ··· 328 328 "Display disabled, reverting to NOP PCH\n"); 329 329 display->pch_type = PCH_NOP; 330 330 } else if (!pch) { 331 - if (i915_run_as_guest() && HAS_DISPLAY(display)) { 331 + if (intel_display_run_as_guest(display) && HAS_DISPLAY(display)) { 332 332 intel_virt_detect_pch(display, &id, &pch_type); 333 333 display->pch_type = pch_type; 334 334 } else {
+1 -1
drivers/gpu/drm/i915/display/intel_pch_refclk.c
··· 6 6 #include <drm/drm_print.h> 7 7 8 8 #include "i915_reg.h" 9 - #include "i915_utils.h" 10 9 #include "intel_de.h" 11 10 #include "intel_display_regs.h" 12 11 #include "intel_display_types.h" 12 + #include "intel_display_utils.h" 13 13 #include "intel_panel.h" 14 14 #include "intel_pch_refclk.h" 15 15 #include "intel_sbi.h"
+1 -1
drivers/gpu/drm/i915/display/intel_pfit.c
··· 5 5 6 6 #include <drm/drm_print.h> 7 7 8 - #include "i915_utils.h" 9 8 #include "intel_de.h" 10 9 #include "intel_display_core.h" 11 10 #include "intel_display_driver.h" 12 11 #include "intel_display_regs.h" 13 12 #include "intel_display_types.h" 13 + #include "intel_display_utils.h" 14 14 #include "intel_lvds_regs.h" 15 15 #include "intel_pfit.h" 16 16 #include "intel_pfit_regs.h"
+9 -52
drivers/gpu/drm/i915/display/intel_plane.c
··· 45 45 #include <drm/drm_panic.h> 46 46 47 47 #include "gem/i915_gem_object.h" 48 - #include "i915_scheduler_types.h" 49 48 #include "i9xx_plane_regs.h" 50 49 #include "intel_cdclk.h" 51 50 #include "intel_cursor.h" ··· 291 292 rel_data_rate); 292 293 } 293 294 294 - int intel_plane_calc_min_cdclk(struct intel_atomic_state *state, 295 - struct intel_plane *plane, 296 - bool *need_cdclk_calc) 295 + static void intel_plane_calc_min_cdclk(struct intel_atomic_state *state, 296 + struct intel_plane *plane) 297 297 { 298 - struct intel_display *display = to_intel_display(plane); 299 298 const struct intel_plane_state *plane_state = 300 299 intel_atomic_get_new_plane_state(state, plane); 301 300 struct intel_crtc *crtc = to_intel_crtc(plane_state->hw.crtc); 302 - const struct intel_cdclk_state *cdclk_state; 303 - const struct intel_crtc_state *old_crtc_state; 304 301 struct intel_crtc_state *new_crtc_state; 305 302 306 303 if (!plane_state->uapi.visible || !plane->min_cdclk) 307 - return 0; 304 + return; 308 305 309 - old_crtc_state = intel_atomic_get_old_crtc_state(state, crtc); 310 306 new_crtc_state = intel_atomic_get_new_crtc_state(state, crtc); 311 307 312 - new_crtc_state->min_cdclk[plane->id] = 308 + new_crtc_state->plane_min_cdclk[plane->id] = 313 309 plane->min_cdclk(new_crtc_state, plane_state); 314 - 315 - /* 316 - * No need to check against the cdclk state if 317 - * the min cdclk for the plane doesn't increase. 318 - * 319 - * Ie. we only ever increase the cdclk due to plane 320 - * requirements. This can reduce back and forth 321 - * display blinking due to constant cdclk changes. 322 - */ 323 - if (new_crtc_state->min_cdclk[plane->id] <= 324 - old_crtc_state->min_cdclk[plane->id]) 325 - return 0; 326 - 327 - cdclk_state = intel_atomic_get_cdclk_state(state); 328 - if (IS_ERR(cdclk_state)) 329 - return PTR_ERR(cdclk_state); 330 - 331 - /* 332 - * No need to recalculate the cdclk state if 333 - * the min cdclk for the pipe doesn't increase. 334 - * 335 - * Ie. we only ever increase the cdclk due to plane 336 - * requirements. This can reduce back and forth 337 - * display blinking due to constant cdclk changes. 338 - */ 339 - if (new_crtc_state->min_cdclk[plane->id] <= 340 - intel_cdclk_min_cdclk(cdclk_state, crtc->pipe)) 341 - return 0; 342 - 343 - drm_dbg_kms(display->drm, 344 - "[PLANE:%d:%s] min cdclk (%d kHz) > [CRTC:%d:%s] min cdclk (%d kHz)\n", 345 - plane->base.base.id, plane->base.name, 346 - new_crtc_state->min_cdclk[plane->id], 347 - crtc->base.base.id, crtc->base.name, 348 - intel_cdclk_min_cdclk(cdclk_state, crtc->pipe)); 349 - *need_cdclk_calc = true; 350 - 351 - return 0; 352 310 } 353 311 354 312 static void intel_plane_clear_hw_state(struct intel_plane_state *plane_state) ··· 391 435 crtc_state->data_rate_y[plane->id] = 0; 392 436 crtc_state->rel_data_rate[plane->id] = 0; 393 437 crtc_state->rel_data_rate_y[plane->id] = 0; 394 - crtc_state->min_cdclk[plane->id] = 0; 438 + crtc_state->plane_min_cdclk[plane->id] = 0; 395 439 396 440 plane_state->uapi.visible = false; 397 441 } ··· 1128 1172 intel_prepare_plane_fb(struct drm_plane *_plane, 1129 1173 struct drm_plane_state *_new_plane_state) 1130 1174 { 1131 - struct i915_sched_attr attr = { .priority = I915_PRIORITY_DISPLAY }; 1132 1175 struct intel_plane *plane = to_intel_plane(_plane); 1133 1176 struct intel_display *display = to_intel_display(plane); 1134 1177 struct intel_plane_state *new_plane_state = ··· 1176 1221 goto unpin_fb; 1177 1222 1178 1223 if (new_plane_state->uapi.fence) { 1179 - i915_gem_fence_wait_priority(new_plane_state->uapi.fence, 1180 - &attr); 1224 + i915_gem_fence_wait_priority_display(new_plane_state->uapi.fence); 1181 1225 1182 1226 intel_display_rps_boost_after_vblank(new_plane_state->hw.crtc, 1183 1227 new_plane_state->uapi.fence); ··· 1699 1745 if (ret) 1700 1746 return ret; 1701 1747 } 1748 + 1749 + for_each_new_intel_plane_in_state(state, plane, plane_state, i) 1750 + intel_plane_calc_min_cdclk(state, plane); 1702 1751 1703 1752 return 0; 1704 1753 }
-3
drivers/gpu/drm/i915/display/intel_plane.h
··· 69 69 struct intel_crtc_state *crtc_state, 70 70 const struct intel_plane_state *old_plane_state, 71 71 struct intel_plane_state *intel_state); 72 - int intel_plane_calc_min_cdclk(struct intel_atomic_state *state, 73 - struct intel_plane *plane, 74 - bool *need_cdclk_calc); 75 72 int intel_plane_check_clipping(struct intel_plane_state *plane_state, 76 73 struct intel_crtc_state *crtc_state, 77 74 int min_scale, int max_scale,
+2 -1
drivers/gpu/drm/i915/display/intel_pmdemand.c
··· 7 7 8 8 #include <drm/drm_print.h> 9 9 10 - #include "i915_utils.h" 11 10 #include "intel_atomic.h" 12 11 #include "intel_bw.h" 13 12 #include "intel_cdclk.h" 14 13 #include "intel_de.h" 14 + #include "intel_display_jiffies.h" 15 15 #include "intel_display_regs.h" 16 16 #include "intel_display_trace.h" 17 + #include "intel_display_utils.h" 17 18 #include "intel_pmdemand.h" 18 19 #include "intel_step.h" 19 20 #include "skl_watermark.h"
+2 -1
drivers/gpu/drm/i915/display/intel_pps.c
··· 10 10 11 11 #include "g4x_dp.h" 12 12 #include "i915_reg.h" 13 - #include "i915_utils.h" 14 13 #include "intel_de.h" 14 + #include "intel_display_jiffies.h" 15 15 #include "intel_display_power_well.h" 16 16 #include "intel_display_regs.h" 17 17 #include "intel_display_types.h" 18 + #include "intel_display_utils.h" 18 19 #include "intel_dp.h" 19 20 #include "intel_dpio_phy.h" 20 21 #include "intel_dpll.h"
+323 -105
drivers/gpu/drm/i915/display/intel_psr.c
··· 39 39 #include "intel_display_regs.h" 40 40 #include "intel_display_rpm.h" 41 41 #include "intel_display_types.h" 42 + #include "intel_display_utils.h" 42 43 #include "intel_dmc.h" 43 44 #include "intel_dp.h" 44 45 #include "intel_dp_aux.h" ··· 51 50 #include "intel_snps_phy.h" 52 51 #include "intel_step.h" 53 52 #include "intel_vblank.h" 53 + #include "intel_vdsc.h" 54 54 #include "intel_vrr.h" 55 55 #include "skl_universal_plane.h" 56 56 ··· 582 580 intel_dp->psr.su_y_granularity = y; 583 581 } 584 582 583 + static enum intel_panel_replay_dsc_support 584 + compute_pr_dsc_support(struct intel_dp *intel_dp) 585 + { 586 + u8 pr_dsc_mode; 587 + u8 val; 588 + 589 + val = intel_dp->pr_dpcd[INTEL_PR_DPCD_INDEX(DP_PANEL_REPLAY_CAP_CAPABILITY)]; 590 + pr_dsc_mode = REG_FIELD_GET8(DP_PANEL_REPLAY_DSC_DECODE_CAPABILITY_IN_PR_MASK, val); 591 + 592 + switch (pr_dsc_mode) { 593 + case DP_DSC_DECODE_CAPABILITY_IN_PR_FULL_FRAME_ONLY: 594 + return INTEL_DP_PANEL_REPLAY_DSC_FULL_FRAME_ONLY; 595 + case DP_DSC_DECODE_CAPABILITY_IN_PR_SUPPORTED: 596 + return INTEL_DP_PANEL_REPLAY_DSC_SELECTIVE_UPDATE; 597 + default: 598 + MISSING_CASE(pr_dsc_mode); 599 + fallthrough; 600 + case DP_DSC_DECODE_CAPABILITY_IN_PR_NOT_SUPPORTED: 601 + case DP_DSC_DECODE_CAPABILITY_IN_PR_RESERVED: 602 + return INTEL_DP_PANEL_REPLAY_DSC_NOT_SUPPORTED; 603 + } 604 + } 605 + 606 + static const char *panel_replay_dsc_support_str(enum intel_panel_replay_dsc_support dsc_support) 607 + { 608 + switch (dsc_support) { 609 + case INTEL_DP_PANEL_REPLAY_DSC_NOT_SUPPORTED: 610 + return "not supported"; 611 + case INTEL_DP_PANEL_REPLAY_DSC_FULL_FRAME_ONLY: 612 + return "full frame only"; 613 + case INTEL_DP_PANEL_REPLAY_DSC_SELECTIVE_UPDATE: 614 + return "selective update"; 615 + default: 616 + MISSING_CASE(dsc_support); 617 + return "n/a"; 618 + }; 619 + } 620 + 585 621 static void _panel_replay_init_dpcd(struct intel_dp *intel_dp) 586 622 { 587 623 struct intel_display *display = to_intel_display(intel_dp); ··· 655 615 DP_PANEL_REPLAY_SU_SUPPORT) 656 616 intel_dp->psr.sink_panel_replay_su_support = true; 657 617 618 + intel_dp->psr.sink_panel_replay_dsc_support = compute_pr_dsc_support(intel_dp); 619 + 658 620 drm_dbg_kms(display->drm, 659 - "Panel replay %sis supported by panel\n", 621 + "Panel replay %sis supported by panel (in DSC mode: %s)\n", 660 622 intel_dp->psr.sink_panel_replay_su_support ? 661 - "selective_update " : ""); 623 + "selective_update " : "", 624 + panel_replay_dsc_support_str(intel_dp->psr.sink_panel_replay_dsc_support)); 662 625 } 663 626 664 627 static void _psr_init_dpcd(struct intel_dp *intel_dp) ··· 999 956 return val; 1000 957 } 1001 958 1002 - static int psr2_block_count_lines(struct intel_dp *intel_dp) 959 + static int 960 + psr2_block_count_lines(u8 io_wake_lines, u8 fast_wake_lines) 1003 961 { 1004 - return intel_dp->alpm_parameters.io_wake_lines < 9 && 1005 - intel_dp->alpm_parameters.fast_wake_lines < 9 ? 8 : 12; 962 + return io_wake_lines < 9 && fast_wake_lines < 9 ? 8 : 12; 1006 963 } 1007 964 1008 965 static int psr2_block_count(struct intel_dp *intel_dp) 1009 966 { 1010 - return psr2_block_count_lines(intel_dp) / 4; 967 + return psr2_block_count_lines(intel_dp->psr.io_wake_lines, 968 + intel_dp->psr.fast_wake_lines) / 4; 1011 969 } 1012 970 1013 971 static u8 frames_before_su_entry(struct intel_dp *intel_dp) ··· 1103 1059 */ 1104 1060 int tmp; 1105 1061 1106 - tmp = map[intel_dp->alpm_parameters.io_wake_lines - 1062 + tmp = map[intel_dp->psr.io_wake_lines - 1107 1063 TGL_EDP_PSR2_IO_BUFFER_WAKE_MIN_LINES]; 1108 1064 val |= TGL_EDP_PSR2_IO_BUFFER_WAKE(tmp + TGL_EDP_PSR2_IO_BUFFER_WAKE_MIN_LINES); 1109 1065 1110 - tmp = map[intel_dp->alpm_parameters.fast_wake_lines - TGL_EDP_PSR2_FAST_WAKE_MIN_LINES]; 1066 + tmp = map[intel_dp->psr.fast_wake_lines - TGL_EDP_PSR2_FAST_WAKE_MIN_LINES]; 1111 1067 val |= TGL_EDP_PSR2_FAST_WAKE(tmp + TGL_EDP_PSR2_FAST_WAKE_MIN_LINES); 1112 1068 } else if (DISPLAY_VER(display) >= 20) { 1113 - val |= LNL_EDP_PSR2_IO_BUFFER_WAKE(intel_dp->alpm_parameters.io_wake_lines); 1069 + val |= LNL_EDP_PSR2_IO_BUFFER_WAKE(intel_dp->psr.io_wake_lines); 1114 1070 } else if (DISPLAY_VER(display) >= 12) { 1115 - val |= TGL_EDP_PSR2_IO_BUFFER_WAKE(intel_dp->alpm_parameters.io_wake_lines); 1116 - val |= TGL_EDP_PSR2_FAST_WAKE(intel_dp->alpm_parameters.fast_wake_lines); 1071 + val |= TGL_EDP_PSR2_IO_BUFFER_WAKE(intel_dp->psr.io_wake_lines); 1072 + val |= TGL_EDP_PSR2_FAST_WAKE(intel_dp->psr.fast_wake_lines); 1117 1073 } else if (DISPLAY_VER(display) >= 9) { 1118 - val |= EDP_PSR2_IO_BUFFER_WAKE(intel_dp->alpm_parameters.io_wake_lines); 1119 - val |= EDP_PSR2_FAST_WAKE(intel_dp->alpm_parameters.fast_wake_lines); 1074 + val |= EDP_PSR2_IO_BUFFER_WAKE(intel_dp->psr.io_wake_lines); 1075 + val |= EDP_PSR2_FAST_WAKE(intel_dp->psr.fast_wake_lines); 1120 1076 } 1121 1077 1122 1078 if (intel_dp->psr.req_psr2_sdp_prior_scanline) ··· 1404 1360 return entry_setup_frames; 1405 1361 } 1406 1362 1407 - static bool wake_lines_fit_into_vblank(struct intel_dp *intel_dp, 1408 - const struct intel_crtc_state *crtc_state, 1409 - bool aux_less) 1363 + static 1364 + int _intel_psr_min_set_context_latency(const struct intel_crtc_state *crtc_state, 1365 + bool needs_panel_replay, 1366 + bool needs_sel_update) 1410 1367 { 1411 - struct intel_display *display = to_intel_display(intel_dp); 1412 - int vblank = crtc_state->hw.adjusted_mode.crtc_vblank_end - 1413 - crtc_state->hw.adjusted_mode.crtc_vblank_start; 1414 - int wake_lines; 1368 + struct intel_display *display = to_intel_display(crtc_state); 1415 1369 1416 - if (aux_less) 1417 - wake_lines = intel_dp->alpm_parameters.aux_less_wake_lines; 1370 + if (!crtc_state->has_psr) 1371 + return 0; 1372 + 1373 + /* Wa_14015401596 */ 1374 + if (intel_vrr_possible(crtc_state) && IS_DISPLAY_VER(display, 13, 14)) 1375 + return 1; 1376 + 1377 + /* Rest is for SRD_STATUS needed on LunarLake and onwards */ 1378 + if (DISPLAY_VER(display) < 20) 1379 + return 0; 1380 + 1381 + /* 1382 + * Comment on SRD_STATUS register in Bspec for LunarLake and onwards: 1383 + * 1384 + * To deterministically capture the transition of the state machine 1385 + * going from SRDOFFACK to IDLE, the delayed V. Blank should be at least 1386 + * one line after the non-delayed V. Blank. 1387 + * 1388 + * Legacy TG: TRANS_SET_CONTEXT_LATENCY > 0 1389 + * VRR TG: TRANS_VRR_CTL[ VRR Guardband ] < (TRANS_VRR_VMAX[ VRR Vmax ] 1390 + * - TRANS_VTOTAL[ Vertical Active ]) 1391 + * 1392 + * SRD_STATUS is used only by PSR1 on PantherLake. 1393 + * SRD_STATUS is used by PSR1 and Panel Replay DP on LunarLake. 1394 + */ 1395 + 1396 + if (DISPLAY_VER(display) >= 30 && (needs_panel_replay || 1397 + needs_sel_update)) 1398 + return 0; 1399 + else if (DISPLAY_VER(display) < 30 && (needs_sel_update || 1400 + intel_crtc_has_type(crtc_state, 1401 + INTEL_OUTPUT_EDP))) 1402 + return 0; 1418 1403 else 1419 - wake_lines = DISPLAY_VER(display) < 20 ? 1420 - psr2_block_count_lines(intel_dp) : 1421 - intel_dp->alpm_parameters.io_wake_lines; 1404 + return 1; 1405 + } 1422 1406 1407 + static bool _wake_lines_fit_into_vblank(const struct intel_crtc_state *crtc_state, 1408 + int vblank, 1409 + int wake_lines) 1410 + { 1423 1411 if (crtc_state->req_psr2_sdp_prior_scanline) 1424 1412 vblank -= 1; 1425 1413 ··· 1462 1386 return true; 1463 1387 } 1464 1388 1389 + static bool wake_lines_fit_into_vblank(struct intel_dp *intel_dp, 1390 + const struct intel_crtc_state *crtc_state, 1391 + bool aux_less, 1392 + bool needs_panel_replay, 1393 + bool needs_sel_update) 1394 + { 1395 + struct intel_display *display = to_intel_display(intel_dp); 1396 + int vblank = crtc_state->hw.adjusted_mode.crtc_vblank_end - 1397 + crtc_state->hw.adjusted_mode.crtc_vblank_start; 1398 + int wake_lines; 1399 + int scl = _intel_psr_min_set_context_latency(crtc_state, 1400 + needs_panel_replay, 1401 + needs_sel_update); 1402 + vblank -= scl; 1403 + 1404 + if (aux_less) 1405 + wake_lines = crtc_state->alpm_state.aux_less_wake_lines; 1406 + else 1407 + wake_lines = DISPLAY_VER(display) < 20 ? 1408 + psr2_block_count_lines(crtc_state->alpm_state.io_wake_lines, 1409 + crtc_state->alpm_state.fast_wake_lines) : 1410 + crtc_state->alpm_state.io_wake_lines; 1411 + 1412 + /* 1413 + * Guardband has not been computed yet, so we conservatively check if the 1414 + * full vblank duration is sufficient to accommodate wake line requirements 1415 + * for PSR features like Panel Replay and Selective Update. 1416 + * 1417 + * Once the actual guardband is available, a more accurate validation is 1418 + * performed in intel_psr_compute_config_late(), and PSR features are 1419 + * disabled if wake lines exceed the available guardband. 1420 + */ 1421 + return _wake_lines_fit_into_vblank(crtc_state, vblank, wake_lines); 1422 + } 1423 + 1465 1424 static bool alpm_config_valid(struct intel_dp *intel_dp, 1466 - const struct intel_crtc_state *crtc_state, 1467 - bool aux_less) 1425 + struct intel_crtc_state *crtc_state, 1426 + bool aux_less, 1427 + bool needs_panel_replay, 1428 + bool needs_sel_update) 1468 1429 { 1469 1430 struct intel_display *display = to_intel_display(intel_dp); 1470 1431 ··· 1511 1398 return false; 1512 1399 } 1513 1400 1514 - if (!wake_lines_fit_into_vblank(intel_dp, crtc_state, aux_less)) { 1401 + if (!wake_lines_fit_into_vblank(intel_dp, crtc_state, aux_less, 1402 + needs_panel_replay, needs_sel_update)) { 1515 1403 drm_dbg_kms(display->drm, 1516 1404 "PSR2/Panel Replay not enabled, too short vblank time\n"); 1517 1405 return false; ··· 1604 1490 return false; 1605 1491 } 1606 1492 1607 - if (!alpm_config_valid(intel_dp, crtc_state, false)) 1493 + if (!alpm_config_valid(intel_dp, crtc_state, false, false, true)) 1608 1494 return false; 1609 1495 1610 1496 if (!crtc_state->enable_psr2_sel_fetch && ··· 1649 1535 goto unsupported; 1650 1536 } 1651 1537 1652 - if (crtc_state->has_panel_replay && (DISPLAY_VER(display) < 14 || 1653 - !intel_dp->psr.sink_panel_replay_su_support)) 1654 - goto unsupported; 1538 + if (crtc_state->has_panel_replay) { 1539 + if (DISPLAY_VER(display) < 14) 1540 + goto unsupported; 1541 + 1542 + if (!intel_dp->psr.sink_panel_replay_su_support) 1543 + goto unsupported; 1544 + 1545 + if (intel_dsc_enabled_on_link(crtc_state) && 1546 + intel_dp->psr.sink_panel_replay_dsc_support != 1547 + INTEL_DP_PANEL_REPLAY_DSC_SELECTIVE_UPDATE) { 1548 + drm_dbg_kms(display->drm, 1549 + "Selective update with Panel Replay not enabled because it's not supported with DSC\n"); 1550 + goto unsupported; 1551 + } 1552 + } 1655 1553 1656 1554 if (crtc_state->crc_enabled) { 1657 1555 drm_dbg_kms(display->drm, ··· 1708 1582 if (entry_setup_frames >= 0) { 1709 1583 intel_dp->psr.entry_setup_frames = entry_setup_frames; 1710 1584 } else { 1585 + crtc_state->no_psr_reason = "PSR setup timing not met"; 1711 1586 drm_dbg_kms(display->drm, 1712 1587 "PSR condition failed: PSR setup timing not met\n"); 1713 1588 return false; ··· 1719 1592 1720 1593 static bool 1721 1594 _panel_replay_compute_config(struct intel_dp *intel_dp, 1722 - const struct intel_crtc_state *crtc_state, 1595 + struct intel_crtc_state *crtc_state, 1723 1596 const struct drm_connector_state *conn_state) 1724 1597 { 1725 1598 struct intel_display *display = to_intel_display(intel_dp); ··· 1738 1611 if (crtc_state->crc_enabled) { 1739 1612 drm_dbg_kms(display->drm, 1740 1613 "Panel Replay not enabled because it would inhibit pipe CRC calculation\n"); 1614 + return false; 1615 + } 1616 + 1617 + if (intel_dsc_enabled_on_link(crtc_state) && 1618 + intel_dp->psr.sink_panel_replay_dsc_support == 1619 + INTEL_DP_PANEL_REPLAY_DSC_NOT_SUPPORTED) { 1620 + drm_dbg_kms(display->drm, 1621 + "Panel Replay not enabled because it's not supported with DSC\n"); 1741 1622 return false; 1742 1623 } 1743 1624 ··· 1776 1641 return false; 1777 1642 } 1778 1643 1779 - if (!alpm_config_valid(intel_dp, crtc_state, true)) 1644 + if (!alpm_config_valid(intel_dp, crtc_state, true, true, false)) 1780 1645 return false; 1781 1646 1782 1647 return true; ··· 1791 1656 !crtc_state->has_sel_update); 1792 1657 } 1793 1658 1659 + static 1660 + void intel_psr_set_non_psr_pipes(struct intel_dp *intel_dp, 1661 + struct intel_crtc_state *crtc_state) 1662 + { 1663 + struct intel_display *display = to_intel_display(intel_dp); 1664 + struct intel_atomic_state *state = to_intel_atomic_state(crtc_state->uapi.state); 1665 + struct intel_crtc *crtc; 1666 + u8 active_pipes = 0; 1667 + 1668 + /* Wa_16025596647 */ 1669 + if (DISPLAY_VER(display) != 20 && 1670 + !IS_DISPLAY_VERx100_STEP(display, 3000, STEP_A0, STEP_B0)) 1671 + return; 1672 + 1673 + /* Not needed by Panel Replay */ 1674 + if (crtc_state->has_panel_replay) 1675 + return; 1676 + 1677 + /* We ignore possible secondary PSR/Panel Replay capable eDP */ 1678 + for_each_intel_crtc(display->drm, crtc) 1679 + active_pipes |= crtc->active ? BIT(crtc->pipe) : 0; 1680 + 1681 + active_pipes = intel_calc_active_pipes(state, active_pipes); 1682 + 1683 + crtc_state->active_non_psr_pipes = active_pipes & 1684 + ~BIT(to_intel_crtc(crtc_state->uapi.crtc)->pipe); 1685 + } 1686 + 1794 1687 void intel_psr_compute_config(struct intel_dp *intel_dp, 1795 1688 struct intel_crtc_state *crtc_state, 1796 1689 struct drm_connector_state *conn_state) 1797 1690 { 1798 1691 struct intel_display *display = to_intel_display(intel_dp); 1799 1692 const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; 1800 - struct intel_atomic_state *state = to_intel_atomic_state(crtc_state->uapi.state); 1801 - struct intel_crtc *crtc; 1802 - u8 active_pipes = 0; 1803 1693 1804 1694 if (!psr_global_enabled(intel_dp)) { 1805 1695 drm_dbg_kms(display->drm, "PSR disabled by flag\n"); ··· 1854 1694 return; 1855 1695 } 1856 1696 1697 + /* Only used for state verification. */ 1698 + crtc_state->panel_replay_dsc_support = intel_dp->psr.sink_panel_replay_dsc_support; 1857 1699 crtc_state->has_panel_replay = _panel_replay_compute_config(intel_dp, 1858 1700 crtc_state, 1859 1701 conn_state); ··· 1867 1705 return; 1868 1706 1869 1707 crtc_state->has_sel_update = intel_sel_update_config_valid(intel_dp, crtc_state); 1870 - 1871 - /* Wa_18037818876 */ 1872 - if (intel_psr_needs_wa_18037818876(intel_dp, crtc_state)) { 1873 - crtc_state->has_psr = false; 1874 - drm_dbg_kms(display->drm, 1875 - "PSR disabled to workaround PSR FSM hang issue\n"); 1876 - } 1877 - 1878 - /* Rest is for Wa_16025596647 */ 1879 - if (DISPLAY_VER(display) != 20 && 1880 - !IS_DISPLAY_VERx100_STEP(display, 3000, STEP_A0, STEP_B0)) 1881 - return; 1882 - 1883 - /* Not needed by Panel Replay */ 1884 - if (crtc_state->has_panel_replay) 1885 - return; 1886 - 1887 - /* We ignore possible secondary PSR/Panel Replay capable eDP */ 1888 - for_each_intel_crtc(display->drm, crtc) 1889 - active_pipes |= crtc->active ? BIT(crtc->pipe) : 0; 1890 - 1891 - active_pipes = intel_calc_active_pipes(state, active_pipes); 1892 - 1893 - crtc_state->active_non_psr_pipes = active_pipes & 1894 - ~BIT(to_intel_crtc(crtc_state->uapi.crtc)->pipe); 1895 1708 } 1896 1709 1897 1710 void intel_psr_get_config(struct intel_encoder *encoder, ··· 1950 1813 hsw_activate_psr1(intel_dp); 1951 1814 1952 1815 intel_dp->psr.active = true; 1816 + intel_dp->psr.no_psr_reason = NULL; 1953 1817 } 1954 1818 1955 1819 /* ··· 2160 2022 crtc_state->req_psr2_sdp_prior_scanline; 2161 2023 intel_dp->psr.active_non_psr_pipes = crtc_state->active_non_psr_pipes; 2162 2024 intel_dp->psr.pkg_c_latency_used = crtc_state->pkg_c_latency_used; 2025 + intel_dp->psr.io_wake_lines = crtc_state->alpm_state.io_wake_lines; 2026 + intel_dp->psr.fast_wake_lines = crtc_state->alpm_state.fast_wake_lines; 2163 2027 2164 2028 if (!psr_interrupt_error_check(intel_dp)) 2165 2029 return; ··· 2500 2360 } 2501 2361 2502 2362 /** 2503 - * intel_psr_min_vblank_delay - Minimum vblank delay needed by PSR 2363 + * intel_psr_min_set_context_latency - Minimum 'set context latency' lines needed by PSR 2504 2364 * @crtc_state: the crtc state 2505 2365 * 2506 - * Return minimum vblank delay needed by PSR. 2366 + * Return minimum SCL lines/delay needed by PSR. 2507 2367 */ 2508 - int intel_psr_min_vblank_delay(const struct intel_crtc_state *crtc_state) 2368 + int intel_psr_min_set_context_latency(const struct intel_crtc_state *crtc_state) 2509 2369 { 2510 - struct intel_display *display = to_intel_display(crtc_state); 2511 2370 2512 - if (!crtc_state->has_psr) 2513 - return 0; 2514 - 2515 - /* Wa_14015401596 */ 2516 - if (intel_vrr_possible(crtc_state) && IS_DISPLAY_VER(display, 13, 14)) 2517 - return 1; 2518 - 2519 - /* Rest is for SRD_STATUS needed on LunarLake and onwards */ 2520 - if (DISPLAY_VER(display) < 20) 2521 - return 0; 2522 - 2523 - /* 2524 - * Comment on SRD_STATUS register in Bspec for LunarLake and onwards: 2525 - * 2526 - * To deterministically capture the transition of the state machine 2527 - * going from SRDOFFACK to IDLE, the delayed V. Blank should be at least 2528 - * one line after the non-delayed V. Blank. 2529 - * 2530 - * Legacy TG: TRANS_SET_CONTEXT_LATENCY > 0 2531 - * VRR TG: TRANS_VRR_CTL[ VRR Guardband ] < (TRANS_VRR_VMAX[ VRR Vmax ] 2532 - * - TRANS_VTOTAL[ Vertical Active ]) 2533 - * 2534 - * SRD_STATUS is used only by PSR1 on PantherLake. 2535 - * SRD_STATUS is used by PSR1 and Panel Replay DP on LunarLake. 2536 - */ 2537 - 2538 - if (DISPLAY_VER(display) >= 30 && (crtc_state->has_panel_replay || 2539 - crtc_state->has_sel_update)) 2540 - return 0; 2541 - else if (DISPLAY_VER(display) < 30 && (crtc_state->has_sel_update || 2542 - intel_crtc_has_type(crtc_state, 2543 - INTEL_OUTPUT_EDP))) 2544 - return 0; 2545 - else 2546 - return 1; 2371 + return _intel_psr_min_set_context_latency(crtc_state, 2372 + crtc_state->has_panel_replay, 2373 + crtc_state->has_sel_update); 2547 2374 } 2548 2375 2549 2376 static u32 man_trk_ctl_enable_bit_get(struct intel_display *display) ··· 3032 2925 3033 2926 mutex_lock(&psr->lock); 3034 2927 2928 + if (!new_crtc_state->has_psr) 2929 + psr->no_psr_reason = new_crtc_state->no_psr_reason; 2930 + 3035 2931 if (psr->enabled) { 3036 2932 /* 3037 2933 * Reasons to disable: ··· 3061 2951 } 3062 2952 } 3063 2953 2954 + static void 2955 + verify_panel_replay_dsc_state(const struct intel_crtc_state *crtc_state) 2956 + { 2957 + struct intel_display *display = to_intel_display(crtc_state); 2958 + 2959 + if (!crtc_state->has_panel_replay) 2960 + return; 2961 + 2962 + drm_WARN_ON(display->drm, 2963 + intel_dsc_enabled_on_link(crtc_state) && 2964 + crtc_state->panel_replay_dsc_support == 2965 + INTEL_DP_PANEL_REPLAY_DSC_NOT_SUPPORTED); 2966 + } 2967 + 3064 2968 void intel_psr_post_plane_update(struct intel_atomic_state *state, 3065 2969 struct intel_crtc *crtc) 3066 2970 { ··· 3085 2961 3086 2962 if (!crtc_state->has_psr) 3087 2963 return; 2964 + 2965 + verify_panel_replay_dsc_state(crtc_state); 3088 2966 3089 2967 for_each_intel_encoder_mask_with_psr(state->base.dev, encoder, 3090 2968 crtc_state->uapi.encoder_mask) { ··· 3099 2973 drm_WARN_ON(display->drm, 3100 2974 psr->enabled && !crtc_state->active_planes); 3101 2975 3102 - keep_disabled |= psr->sink_not_reliable; 3103 - keep_disabled |= !crtc_state->active_planes; 2976 + if (psr->sink_not_reliable) 2977 + keep_disabled = true; 2978 + 2979 + if (!crtc_state->active_planes) { 2980 + psr->no_psr_reason = "All planes inactive"; 2981 + keep_disabled = true; 2982 + } 3104 2983 3105 2984 /* Display WA #1136: skl, bxt */ 3106 - keep_disabled |= DISPLAY_VER(display) < 11 && 3107 - crtc_state->wm_level_disabled; 2985 + if (DISPLAY_VER(display) < 11 && crtc_state->wm_level_disabled) { 2986 + psr->no_psr_reason = "Workaround #1136 for skl, bxt"; 2987 + keep_disabled = true; 2988 + } 3108 2989 3109 2990 if (!psr->enabled && !keep_disabled) 3110 2991 intel_psr_enable_locked(intel_dp, crtc_state); ··· 4124 3991 seq_printf(m, ", Panel Replay = %s", str_yes_no(psr->sink_panel_replay_support)); 4125 3992 seq_printf(m, ", Panel Replay Selective Update = %s", 4126 3993 str_yes_no(psr->sink_panel_replay_su_support)); 3994 + seq_printf(m, ", Panel Replay DSC support = %s", 3995 + panel_replay_dsc_support_str(psr->sink_panel_replay_dsc_support)); 4127 3996 if (intel_dp->pr_dpcd[INTEL_PR_DPCD_INDEX(DP_PANEL_REPLAY_CAP_SUPPORT)] & 4128 3997 DP_PANEL_REPLAY_EARLY_TRANSPORT_SUPPORT) 4129 3998 seq_printf(m, " (Early Transport)"); ··· 4160 4025 region_et = ""; 4161 4026 4162 4027 seq_printf(m, "PSR mode: %s%s%s\n", mode, status, region_et); 4028 + if (psr->no_psr_reason) 4029 + seq_printf(m, " %s\n", psr->no_psr_reason); 4163 4030 } 4164 4031 4165 4032 static int intel_psr_status(struct seq_file *m, struct intel_dp *intel_dp) ··· 4458 4321 const struct intel_crtc_state *crtc_state) 4459 4322 { 4460 4323 return intel_dp_is_edp(intel_dp) && crtc_state->has_panel_replay; 4324 + } 4325 + 4326 + void intel_psr_compute_config_late(struct intel_dp *intel_dp, 4327 + struct intel_crtc_state *crtc_state) 4328 + { 4329 + struct intel_display *display = to_intel_display(intel_dp); 4330 + int vblank = intel_crtc_vblank_length(crtc_state); 4331 + int wake_lines; 4332 + 4333 + if (intel_psr_needs_alpm_aux_less(intel_dp, crtc_state)) 4334 + wake_lines = crtc_state->alpm_state.aux_less_wake_lines; 4335 + else if (intel_psr_needs_alpm(intel_dp, crtc_state)) 4336 + wake_lines = DISPLAY_VER(display) < 20 ? 4337 + psr2_block_count_lines(crtc_state->alpm_state.io_wake_lines, 4338 + crtc_state->alpm_state.fast_wake_lines) : 4339 + crtc_state->alpm_state.io_wake_lines; 4340 + else 4341 + wake_lines = 0; 4342 + 4343 + /* 4344 + * Disable the PSR features if wake lines exceed the available vblank. 4345 + * Though SCL is computed based on these PSR features, it is not reset 4346 + * even if the PSR features are disabled to avoid changing vblank start 4347 + * at this stage. 4348 + */ 4349 + if (wake_lines && !_wake_lines_fit_into_vblank(crtc_state, vblank, wake_lines)) { 4350 + drm_dbg_kms(display->drm, 4351 + "Adjusting PSR/PR mode: vblank too short for wake lines = %d\n", 4352 + wake_lines); 4353 + 4354 + if (crtc_state->has_panel_replay) { 4355 + crtc_state->has_panel_replay = false; 4356 + /* 4357 + * #TODO : Add fall back to PSR/PSR2 4358 + * Since panel replay cannot be supported, we can fall back to PSR/PSR2. 4359 + * This will require calling compute_config for psr and psr2 with check for 4360 + * actual guardband instead of vblank_length. 4361 + */ 4362 + crtc_state->has_psr = false; 4363 + } 4364 + 4365 + crtc_state->has_sel_update = false; 4366 + crtc_state->enable_psr2_su_region_et = false; 4367 + crtc_state->enable_psr2_sel_fetch = false; 4368 + } 4369 + 4370 + /* Wa_18037818876 */ 4371 + if (intel_psr_needs_wa_18037818876(intel_dp, crtc_state)) { 4372 + crtc_state->has_psr = false; 4373 + drm_dbg_kms(display->drm, 4374 + "PSR disabled to workaround PSR FSM hang issue\n"); 4375 + } 4376 + 4377 + intel_psr_set_non_psr_pipes(intel_dp, crtc_state); 4378 + } 4379 + 4380 + int intel_psr_min_guardband(struct intel_crtc_state *crtc_state) 4381 + { 4382 + struct intel_display *display = to_intel_display(crtc_state); 4383 + int psr_min_guardband; 4384 + int wake_lines; 4385 + 4386 + if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP)) 4387 + return 0; 4388 + 4389 + if (crtc_state->has_panel_replay) 4390 + wake_lines = crtc_state->alpm_state.aux_less_wake_lines; 4391 + else if (crtc_state->has_sel_update) 4392 + wake_lines = DISPLAY_VER(display) < 20 ? 4393 + psr2_block_count_lines(crtc_state->alpm_state.io_wake_lines, 4394 + crtc_state->alpm_state.fast_wake_lines) : 4395 + crtc_state->alpm_state.io_wake_lines; 4396 + else 4397 + return 0; 4398 + 4399 + psr_min_guardband = wake_lines + crtc_state->set_context_latency; 4400 + 4401 + if (crtc_state->req_psr2_sdp_prior_scanline) 4402 + psr_min_guardband++; 4403 + 4404 + return psr_min_guardband; 4461 4405 }
+4 -1
drivers/gpu/drm/i915/display/intel_psr.h
··· 77 77 void intel_psr_trigger_frame_change_event(struct intel_dsb *dsb, 78 78 struct intel_atomic_state *state, 79 79 struct intel_crtc *crtc); 80 - int intel_psr_min_vblank_delay(const struct intel_crtc_state *crtc_state); 80 + int intel_psr_min_set_context_latency(const struct intel_crtc_state *crtc_state); 81 81 void intel_psr_connector_debugfs_add(struct intel_connector *connector); 82 82 void intel_psr_debugfs_register(struct intel_display *display); 83 83 bool intel_psr_needs_alpm(struct intel_dp *intel_dp, const struct intel_crtc_state *crtc_state); 84 84 bool intel_psr_needs_alpm_aux_less(struct intel_dp *intel_dp, 85 85 const struct intel_crtc_state *crtc_state); 86 + void intel_psr_compute_config_late(struct intel_dp *intel_dp, 87 + struct intel_crtc_state *crtc_state); 88 + int intel_psr_min_guardband(struct intel_crtc_state *crtc_state); 86 89 87 90 #endif /* __INTEL_PSR_H__ */
+1 -1
drivers/gpu/drm/i915/display/intel_qp_tables.c
··· 5 5 6 6 #include <drm/display/drm_dsc.h> 7 7 8 - #include "i915_utils.h" 8 + #include "intel_display_utils.h" 9 9 #include "intel_qp_tables.h" 10 10 11 11 /* from BPP 6 to 24 in steps of 0.5 */
+2
drivers/gpu/drm/i915/display/intel_snps_hdmi_pll.c
··· 332 332 c10_curve_1, c10_curve_2, prescaler_divider, 333 333 &pll_params); 334 334 335 + pll_state->clock = pixel_clock; 336 + 335 337 pll_state->tx = 0x10; 336 338 pll_state->cmn = 0x1; 337 339 pll_state->pll[0] = REG_FIELD_PREP(C10_PLL0_DIV5CLK_EN, pll_params.mpll_div5_en) |
+1 -1
drivers/gpu/drm/i915/display/intel_snps_phy.c
··· 7 7 8 8 #include <drm/drm_print.h> 9 9 10 - #include "i915_utils.h" 11 10 #include "intel_ddi.h" 12 11 #include "intel_ddi_buf_trans.h" 13 12 #include "intel_de.h" 14 13 #include "intel_display_regs.h" 15 14 #include "intel_display_types.h" 15 + #include "intel_display_utils.h" 16 16 #include "intel_snps_hdmi_pll.h" 17 17 #include "intel_snps_phy.h" 18 18 #include "intel_snps_phy_regs.h"
+1 -1
drivers/gpu/drm/i915/display/intel_sprite.c
··· 39 39 #include <drm/drm_print.h> 40 40 #include <drm/drm_rect.h> 41 41 42 - #include "i915_utils.h" 43 42 #include "i9xx_plane.h" 44 43 #include "intel_de.h" 45 44 #include "intel_display_types.h" 45 + #include "intel_display_utils.h" 46 46 #include "intel_fb.h" 47 47 #include "intel_frontbuffer.h" 48 48 #include "intel_plane.h"
+14 -1
drivers/gpu/drm/i915/display/intel_tc.c
··· 8 8 #include <drm/drm_print.h> 9 9 10 10 #include "i915_reg.h" 11 - #include "i915_utils.h" 12 11 #include "intel_atomic.h" 13 12 #include "intel_cx0_phy_regs.h" 14 13 #include "intel_ddi.h" ··· 17 18 #include "intel_display_power_map.h" 18 19 #include "intel_display_regs.h" 19 20 #include "intel_display_types.h" 21 + #include "intel_display_utils.h" 20 22 #include "intel_dkl_phy_regs.h" 21 23 #include "intel_dp.h" 22 24 #include "intel_dp_mst.h" ··· 1701 1701 tc->max_lane_count); 1702 1702 1703 1703 mutex_unlock(&tc->lock); 1704 + } 1705 + 1706 + void intel_tc_info(struct drm_printer *p, struct intel_digital_port *dig_port) 1707 + { 1708 + struct intel_tc_port *tc = to_tc_port(dig_port); 1709 + 1710 + intel_tc_port_lock(dig_port); 1711 + drm_printf(p, "\tTC Port %s: mode: %s, pin assignment: %c, max lanes: %d\n", 1712 + tc->port_name, 1713 + tc_port_mode_name(tc->mode), 1714 + pin_assignment_name(tc->pin_assignment), 1715 + tc->max_lane_count); 1716 + intel_tc_port_unlock(dig_port); 1704 1717 } 1705 1718 1706 1719 /*
+3
drivers/gpu/drm/i915/display/intel_tc.h
··· 8 8 9 9 #include <linux/types.h> 10 10 11 + struct drm_printer; 11 12 struct intel_crtc_state; 12 13 struct intel_digital_port; 13 14 struct intel_encoder; ··· 113 112 void intel_tc_port_cleanup(struct intel_digital_port *dig_port); 114 113 115 114 bool intel_tc_cold_requires_aux_pw(struct intel_digital_port *dig_port); 115 + 116 + void intel_tc_info(struct drm_printer *p, struct intel_digital_port *dig_port); 116 117 117 118 #endif /* __INTEL_TC_H__ */
+13 -2
drivers/gpu/drm/i915/display/intel_vblank.c
··· 8 8 #include <drm/drm_vblank.h> 9 9 10 10 #include "i915_drv.h" 11 - #include "i915_utils.h" 12 11 #include "intel_color.h" 13 12 #include "intel_crtc.h" 14 13 #include "intel_de.h" 14 + #include "intel_display_jiffies.h" 15 15 #include "intel_display_regs.h" 16 16 #include "intel_display_types.h" 17 + #include "intel_display_utils.h" 17 18 #include "intel_vblank.h" 18 19 #include "intel_vrr.h" 19 20 ··· 682 681 else 683 682 evade->vblank_start = intel_vrr_vmax_vblank_start(crtc_state); 684 683 685 - vblank_delay = intel_vrr_vblank_delay(crtc_state); 684 + vblank_delay = crtc_state->set_context_latency; 686 685 } else { 687 686 evade->vblank_start = intel_mode_vblank_start(adjusted_mode); 688 687 ··· 767 766 scanline = intel_get_crtc_scanline(crtc); 768 767 769 768 return scanline; 769 + } 770 + 771 + int intel_crtc_vblank_length(const struct intel_crtc_state *crtc_state) 772 + { 773 + const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; 774 + 775 + if (crtc_state->vrr.enable) 776 + return crtc_state->vrr.guardband; 777 + else 778 + return adjusted_mode->crtc_vtotal - adjusted_mode->crtc_vblank_start; 770 779 }
+2
drivers/gpu/drm/i915/display/intel_vblank.h
··· 48 48 intel_pre_commit_crtc_state(struct intel_atomic_state *state, 49 49 struct intel_crtc *crtc); 50 50 51 + int intel_crtc_vblank_length(const struct intel_crtc_state *crtc_state); 52 + 51 53 #endif /* __INTEL_VBLANK_H__ */
+25 -1
drivers/gpu/drm/i915/display/intel_vdsc.c
··· 11 11 #include <drm/drm_fixed.h> 12 12 #include <drm/drm_print.h> 13 13 14 - #include "i915_utils.h" 15 14 #include "intel_crtc.h" 16 15 #include "intel_de.h" 17 16 #include "intel_display_types.h" 17 + #include "intel_display_utils.h" 18 18 #include "intel_dp.h" 19 19 #include "intel_dsi.h" 20 20 #include "intel_qp_tables.h" ··· 370 370 (vdsc_cfg->rc_model_size - vdsc_cfg->initial_offset); 371 371 372 372 return 0; 373 + } 374 + 375 + void intel_dsc_enable_on_crtc(struct intel_crtc_state *crtc_state) 376 + { 377 + crtc_state->dsc.compression_enabled_on_link = true; 378 + crtc_state->dsc.compression_enable = true; 379 + } 380 + 381 + bool intel_dsc_enabled_on_link(const struct intel_crtc_state *crtc_state) 382 + { 383 + struct intel_display *display = to_intel_display(crtc_state); 384 + 385 + drm_WARN_ON(display->drm, crtc_state->dsc.compression_enable && 386 + !crtc_state->dsc.compression_enabled_on_link); 387 + 388 + return crtc_state->dsc.compression_enabled_on_link; 373 389 } 374 390 375 391 enum intel_display_power_domain ··· 1092 1076 } 1093 1077 1094 1078 return min_cdclk; 1079 + } 1080 + 1081 + unsigned int intel_vdsc_prefill_lines(const struct intel_crtc_state *crtc_state) 1082 + { 1083 + if (!crtc_state->dsc.compression_enable) 1084 + return 0; 1085 + 1086 + return 0x18000; /* 1.5 */ 1095 1087 }
+3
drivers/gpu/drm/i915/display/intel_vdsc.h
··· 20 20 void intel_dsc_enable(const struct intel_crtc_state *crtc_state); 21 21 void intel_dsc_disable(const struct intel_crtc_state *crtc_state); 22 22 int intel_dsc_compute_params(struct intel_crtc_state *pipe_config); 23 + void intel_dsc_enable_on_crtc(struct intel_crtc_state *crtc_state); 24 + bool intel_dsc_enabled_on_link(const struct intel_crtc_state *crtc_state); 23 25 void intel_dsc_get_config(struct intel_crtc_state *crtc_state); 24 26 enum intel_display_power_domain 25 27 intel_dsc_power_domain(struct intel_crtc *crtc, enum transcoder cpu_transcoder); ··· 34 32 void intel_vdsc_state_dump(struct drm_printer *p, int indent, 35 33 const struct intel_crtc_state *crtc_state); 36 34 int intel_vdsc_min_cdclk(const struct intel_crtc_state *crtc_state); 35 + unsigned int intel_vdsc_prefill_lines(const struct intel_crtc_state *crtc_state); 37 36 38 37 #endif /* __INTEL_VDSC_H__ */
+314 -188
drivers/gpu/drm/i915/display/intel_vrr.c
··· 10 10 #include "intel_display_regs.h" 11 11 #include "intel_display_types.h" 12 12 #include "intel_dp.h" 13 + #include "intel_psr.h" 13 14 #include "intel_vrr.h" 14 15 #include "intel_vrr_regs.h" 16 + #include "skl_prefill.h" 17 + #include "skl_watermark.h" 15 18 16 19 #define FIXED_POINT_PRECISION 100 17 20 #define CMRR_PRECISION_TOLERANCE 10 ··· 24 21 struct intel_display *display = to_intel_display(connector); 25 22 const struct drm_display_info *info = &connector->base.display_info; 26 23 struct intel_dp *intel_dp; 24 + 25 + if (!HAS_VRR(display)) 26 + return false; 27 27 28 28 /* 29 29 * DP Sink is capable of VRR video timings if ··· 52 46 return false; 53 47 } 54 48 55 - return HAS_VRR(display) && 56 - info->monitor_range.max_vfreq - info->monitor_range.min_vfreq > 10; 49 + return info->monitor_range.max_vfreq - info->monitor_range.min_vfreq > 10; 57 50 } 58 51 59 52 bool intel_vrr_is_in_range(struct intel_connector *connector, int vrefresh) ··· 84 79 } 85 80 } 86 81 87 - static int intel_vrr_real_vblank_delay(const struct intel_crtc_state *crtc_state) 88 - { 89 - return crtc_state->hw.adjusted_mode.crtc_vblank_start - 90 - crtc_state->hw.adjusted_mode.crtc_vdisplay; 91 - } 92 - 93 82 static int intel_vrr_extra_vblank_delay(struct intel_display *display) 94 83 { 95 84 /* 96 85 * On ICL/TGL VRR hardware inserts one extra scanline 97 86 * just after vactive, which pushes the vmin decision 98 - * boundary ahead accordingly. We'll include the extra 99 - * scanline in our vblank delay estimates to make sure 100 - * that we never underestimate how long we have until 101 - * the delayed vblank has passed. 87 + * boundary ahead accordingly, and thus reduces the 88 + * max guardband length by one scanline. 102 89 */ 103 90 return DISPLAY_VER(display) < 13 ? 1 : 0; 104 91 } 105 92 106 - int intel_vrr_vblank_delay(const struct intel_crtc_state *crtc_state) 93 + static int intel_vrr_vmin_flipline_offset(struct intel_display *display) 107 94 { 108 - struct intel_display *display = to_intel_display(crtc_state); 109 - 110 - return intel_vrr_real_vblank_delay(crtc_state) + 111 - intel_vrr_extra_vblank_delay(display); 112 - } 113 - 114 - static int intel_vrr_flipline_offset(struct intel_display *display) 115 - { 116 - /* ICL/TGL hardware imposes flipline>=vmin+1 */ 95 + /* 96 + * ICL/TGL hardware imposes flipline>=vmin+1 97 + * 98 + * We reduce the vmin value to compensate when programming the 99 + * hardware. This approach allows flipline to remain set at the 100 + * original value, and thus the frame will have the desired 101 + * minimum vtotal. 102 + */ 117 103 return DISPLAY_VER(display) < 13 ? 1 : 0; 118 104 } 119 105 120 - static int intel_vrr_vmin_flipline(const struct intel_crtc_state *crtc_state) 106 + static int intel_vrr_guardband_to_pipeline_full(const struct intel_crtc_state *crtc_state, 107 + int guardband) 121 108 { 122 - struct intel_display *display = to_intel_display(crtc_state); 109 + /* hardware imposes one extra scanline somewhere */ 110 + return guardband - crtc_state->framestart_delay - 1; 111 + } 123 112 124 - return crtc_state->vrr.vmin + intel_vrr_flipline_offset(display); 113 + static int intel_vrr_pipeline_full_to_guardband(const struct intel_crtc_state *crtc_state, 114 + int pipeline_full) 115 + { 116 + /* hardware imposes one extra scanline somewhere */ 117 + return pipeline_full + crtc_state->framestart_delay + 1; 125 118 } 126 119 127 120 /* ··· 138 135 * 139 136 * framestart_delay is programmable 1-4. 140 137 */ 141 - static int intel_vrr_vblank_exit_length(const struct intel_crtc_state *crtc_state) 142 - { 143 - struct intel_display *display = to_intel_display(crtc_state); 144 - 145 - if (DISPLAY_VER(display) >= 13) 146 - return crtc_state->vrr.guardband; 147 - else 148 - /* hardware imposes one extra scanline somewhere */ 149 - return crtc_state->vrr.pipeline_full + crtc_state->framestart_delay + 1; 150 - } 151 138 152 139 int intel_vrr_vmin_vtotal(const struct intel_crtc_state *crtc_state) 153 140 { 154 - struct intel_display *display = to_intel_display(crtc_state); 155 - 156 141 /* Min vblank actually determined by flipline */ 157 - if (DISPLAY_VER(display) >= 13) 158 - return intel_vrr_vmin_flipline(crtc_state); 159 - else 160 - return intel_vrr_vmin_flipline(crtc_state) + 161 - intel_vrr_real_vblank_delay(crtc_state); 142 + return crtc_state->vrr.vmin; 162 143 } 163 144 164 145 int intel_vrr_vmax_vtotal(const struct intel_crtc_state *crtc_state) 165 146 { 166 - struct intel_display *display = to_intel_display(crtc_state); 167 - 168 - if (DISPLAY_VER(display) >= 13) 169 - return crtc_state->vrr.vmax; 170 - else 171 - return crtc_state->vrr.vmax + 172 - intel_vrr_real_vblank_delay(crtc_state); 147 + return crtc_state->vrr.vmax; 173 148 } 174 149 175 150 int intel_vrr_vmin_vblank_start(const struct intel_crtc_state *crtc_state) 176 151 { 177 - return intel_vrr_vmin_vtotal(crtc_state) - intel_vrr_vblank_exit_length(crtc_state); 152 + return intel_vrr_vmin_vtotal(crtc_state) - crtc_state->vrr.guardband; 178 153 } 179 154 180 155 int intel_vrr_vmax_vblank_start(const struct intel_crtc_state *crtc_state) 181 156 { 182 - return intel_vrr_vmax_vtotal(crtc_state) - intel_vrr_vblank_exit_length(crtc_state); 157 + return intel_vrr_vmax_vtotal(crtc_state) - crtc_state->vrr.guardband; 183 158 } 184 159 185 160 static bool ··· 211 230 static 212 231 void intel_vrr_compute_cmrr_timings(struct intel_crtc_state *crtc_state) 213 232 { 214 - crtc_state->cmrr.enable = true; 215 233 /* 216 234 * TODO: Compute precise target refresh rate to determine 217 235 * if video_mode_required should be true. Currently set to ··· 220 240 crtc_state->vrr.vmax = cmrr_get_vtotal(crtc_state, false); 221 241 crtc_state->vrr.vmin = crtc_state->vrr.vmax; 222 242 crtc_state->vrr.flipline = crtc_state->vrr.vmin; 243 + 244 + crtc_state->cmrr.enable = true; 223 245 crtc_state->mode_flags |= I915_MODE_FLAG_VRR; 224 246 } 225 247 226 248 static 227 - void intel_vrr_compute_vrr_timings(struct intel_crtc_state *crtc_state) 249 + void intel_vrr_compute_vrr_timings(struct intel_crtc_state *crtc_state, 250 + int vmin, int vmax) 228 251 { 252 + crtc_state->vrr.vmax = vmax; 253 + crtc_state->vrr.vmin = vmin; 254 + crtc_state->vrr.flipline = crtc_state->vrr.vmin; 255 + 229 256 crtc_state->vrr.enable = true; 230 257 crtc_state->mode_flags |= I915_MODE_FLAG_VRR; 258 + } 259 + 260 + static 261 + void intel_vrr_compute_fixed_rr_timings(struct intel_crtc_state *crtc_state) 262 + { 263 + /* For fixed rr, vmin = vmax = flipline */ 264 + crtc_state->vrr.vmax = crtc_state->hw.adjusted_mode.crtc_vtotal; 265 + crtc_state->vrr.vmin = crtc_state->vrr.vmax; 266 + crtc_state->vrr.flipline = crtc_state->vrr.vmin; 267 + } 268 + 269 + static int intel_vrr_hw_value(const struct intel_crtc_state *crtc_state, 270 + int value) 271 + { 272 + struct intel_display *display = to_intel_display(crtc_state); 273 + 274 + /* 275 + * On TGL vmin/vmax/flipline also need to be 276 + * adjusted by the SCL to maintain correct vtotals. 277 + */ 278 + if (DISPLAY_VER(display) >= 13) 279 + return value; 280 + else 281 + return value - crtc_state->set_context_latency; 231 282 } 232 283 233 284 /* ··· 266 255 * Vtotal value. 267 256 */ 268 257 static 269 - int intel_vrr_fixed_rr_vtotal(const struct intel_crtc_state *crtc_state) 258 + int intel_vrr_fixed_rr_hw_vtotal(const struct intel_crtc_state *crtc_state) 270 259 { 271 - struct intel_display *display = to_intel_display(crtc_state); 272 - int crtc_vtotal = crtc_state->hw.adjusted_mode.crtc_vtotal; 273 - 274 - if (DISPLAY_VER(display) >= 13) 275 - return crtc_vtotal; 276 - else 277 - return crtc_vtotal - 278 - intel_vrr_real_vblank_delay(crtc_state); 260 + return intel_vrr_hw_value(crtc_state, crtc_state->hw.adjusted_mode.crtc_vtotal); 279 261 } 280 262 281 263 static 282 - int intel_vrr_fixed_rr_vmax(const struct intel_crtc_state *crtc_state) 264 + int intel_vrr_fixed_rr_hw_vmax(const struct intel_crtc_state *crtc_state) 283 265 { 284 - return intel_vrr_fixed_rr_vtotal(crtc_state); 266 + return intel_vrr_fixed_rr_hw_vtotal(crtc_state); 285 267 } 286 268 287 269 static 288 - int intel_vrr_fixed_rr_vmin(const struct intel_crtc_state *crtc_state) 270 + int intel_vrr_fixed_rr_hw_vmin(const struct intel_crtc_state *crtc_state) 289 271 { 290 272 struct intel_display *display = to_intel_display(crtc_state); 291 273 292 - return intel_vrr_fixed_rr_vtotal(crtc_state) - 293 - intel_vrr_flipline_offset(display); 274 + return intel_vrr_fixed_rr_hw_vtotal(crtc_state) - 275 + intel_vrr_vmin_flipline_offset(display); 294 276 } 295 277 296 278 static 297 - int intel_vrr_fixed_rr_flipline(const struct intel_crtc_state *crtc_state) 279 + int intel_vrr_fixed_rr_hw_flipline(const struct intel_crtc_state *crtc_state) 298 280 { 299 - return intel_vrr_fixed_rr_vtotal(crtc_state); 281 + return intel_vrr_fixed_rr_hw_vtotal(crtc_state); 300 282 } 301 283 302 284 void intel_vrr_set_fixed_rr_timings(const struct intel_crtc_state *crtc_state) ··· 301 297 return; 302 298 303 299 intel_de_write(display, TRANS_VRR_VMIN(display, cpu_transcoder), 304 - intel_vrr_fixed_rr_vmin(crtc_state) - 1); 300 + intel_vrr_fixed_rr_hw_vmin(crtc_state) - 1); 305 301 intel_de_write(display, TRANS_VRR_VMAX(display, cpu_transcoder), 306 - intel_vrr_fixed_rr_vmax(crtc_state) - 1); 302 + intel_vrr_fixed_rr_hw_vmax(crtc_state) - 1); 307 303 intel_de_write(display, TRANS_VRR_FLIPLINE(display, cpu_transcoder), 308 - intel_vrr_fixed_rr_flipline(crtc_state) - 1); 309 - } 310 - 311 - static 312 - void intel_vrr_compute_fixed_rr_timings(struct intel_crtc_state *crtc_state) 313 - { 314 - /* 315 - * For fixed rr, vmin = vmax = flipline. 316 - * vmin is already set to crtc_vtotal set vmax and flipline the same. 317 - */ 318 - crtc_state->vrr.vmax = crtc_state->hw.adjusted_mode.crtc_vtotal; 319 - crtc_state->vrr.flipline = crtc_state->hw.adjusted_mode.crtc_vtotal; 304 + intel_vrr_fixed_rr_hw_flipline(crtc_state) - 1); 320 305 } 321 306 322 307 static ··· 377 384 vmax = vmin; 378 385 } 379 386 380 - crtc_state->vrr.vmin = vmin; 381 - crtc_state->vrr.vmax = vmax; 382 - 383 - crtc_state->vrr.flipline = crtc_state->vrr.vmin; 384 - 385 387 if (crtc_state->uapi.vrr_enabled && vmin < vmax) 386 - intel_vrr_compute_vrr_timings(crtc_state); 388 + intel_vrr_compute_vrr_timings(crtc_state, vmin, vmax); 387 389 else if (is_cmrr_frac_required(crtc_state) && is_edp) 388 390 intel_vrr_compute_cmrr_timings(crtc_state); 389 391 else 390 392 intel_vrr_compute_fixed_rr_timings(crtc_state); 391 393 392 - /* 393 - * flipline determines the min vblank length the hardware will 394 - * generate, and on ICL/TGL flipline>=vmin+1, hence we reduce 395 - * vmin by one to make sure we can get the actual min vblank length. 396 - */ 397 - crtc_state->vrr.vmin -= intel_vrr_flipline_offset(display); 398 - 399 394 if (HAS_AS_SDP(display)) { 400 395 crtc_state->vrr.vsync_start = 401 396 (crtc_state->hw.adjusted_mode.crtc_vtotal - 402 - crtc_state->hw.adjusted_mode.vsync_start); 397 + crtc_state->hw.adjusted_mode.crtc_vsync_start); 403 398 crtc_state->vrr.vsync_end = 404 399 (crtc_state->hw.adjusted_mode.crtc_vtotal - 405 - crtc_state->hw.adjusted_mode.vsync_end); 400 + crtc_state->hw.adjusted_mode.crtc_vsync_end); 406 401 } 407 402 } 408 403 409 - void intel_vrr_compute_config_late(struct intel_crtc_state *crtc_state) 404 + static int 405 + intel_vrr_max_hw_guardband(const struct intel_crtc_state *crtc_state) 406 + { 407 + struct intel_display *display = to_intel_display(crtc_state); 408 + int max_pipeline_full = REG_FIELD_MAX(VRR_CTL_PIPELINE_FULL_MASK); 409 + 410 + if (DISPLAY_VER(display) >= 13) 411 + return REG_FIELD_MAX(XELPD_VRR_CTL_VRR_GUARDBAND_MASK); 412 + else 413 + return intel_vrr_pipeline_full_to_guardband(crtc_state, 414 + max_pipeline_full); 415 + } 416 + 417 + static int 418 + intel_vrr_max_vblank_guardband(const struct intel_crtc_state *crtc_state) 410 419 { 411 420 struct intel_display *display = to_intel_display(crtc_state); 412 421 const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; 413 422 423 + return crtc_state->vrr.vmin - 424 + adjusted_mode->crtc_vdisplay - 425 + crtc_state->set_context_latency - 426 + intel_vrr_extra_vblank_delay(display); 427 + } 428 + 429 + static int 430 + intel_vrr_max_guardband(struct intel_crtc_state *crtc_state) 431 + { 432 + return min(intel_vrr_max_hw_guardband(crtc_state), 433 + intel_vrr_max_vblank_guardband(crtc_state)); 434 + } 435 + 436 + static 437 + int intel_vrr_compute_optimized_guardband(struct intel_crtc_state *crtc_state) 438 + { 439 + struct intel_display *display = to_intel_display(crtc_state); 440 + struct skl_prefill_ctx prefill_ctx; 441 + int prefill_latency_us; 442 + int guardband = 0; 443 + 444 + skl_prefill_init_worst(&prefill_ctx, crtc_state); 445 + 446 + /* 447 + * The SoC power controller runs SAGV mutually exclusive with package C states, 448 + * so the max of package C and SAGV latencies is used to compute the min prefill guardband. 449 + * PM delay = max(sagv_latency, pkgc_max_latency (highest enabled wm level 1 and up)) 450 + */ 451 + prefill_latency_us = max(display->sagv.block_time_us, 452 + skl_watermark_max_latency(display, 1)); 453 + 454 + guardband = skl_prefill_min_guardband(&prefill_ctx, 455 + crtc_state, 456 + prefill_latency_us); 457 + 458 + if (intel_crtc_has_dp_encoder(crtc_state)) { 459 + guardband = max(guardband, intel_psr_min_guardband(crtc_state)); 460 + guardband = max(guardband, intel_dp_sdp_min_guardband(crtc_state, true)); 461 + } 462 + 463 + return guardband; 464 + } 465 + 466 + static bool intel_vrr_use_optimized_guardband(const struct intel_crtc_state *crtc_state) 467 + { 468 + /* 469 + * #TODO: Enable optimized guardband for HDMI 470 + * For HDMI lot of infoframes are transmitted a line or two after vsync. 471 + * Since with optimized guardband the double bufferring point is at delayed vblank, 472 + * we need to ensure that vsync happens after delayed vblank for the HDMI case. 473 + */ 474 + if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) 475 + return false; 476 + 477 + return true; 478 + } 479 + 480 + void intel_vrr_compute_guardband(struct intel_crtc_state *crtc_state) 481 + { 482 + struct intel_display *display = to_intel_display(crtc_state); 483 + struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; 484 + struct drm_display_mode *pipe_mode = &crtc_state->hw.pipe_mode; 485 + int guardband; 486 + 414 487 if (!intel_vrr_possible(crtc_state)) 415 488 return; 416 489 417 - if (DISPLAY_VER(display) >= 13) { 418 - crtc_state->vrr.guardband = 419 - crtc_state->vrr.vmin - adjusted_mode->crtc_vblank_start; 420 - } else { 421 - /* hardware imposes one extra scanline somewhere */ 422 - crtc_state->vrr.pipeline_full = 423 - min(255, crtc_state->vrr.vmin - adjusted_mode->crtc_vblank_start - 424 - crtc_state->framestart_delay - 1); 490 + if (intel_vrr_use_optimized_guardband(crtc_state)) 491 + guardband = intel_vrr_compute_optimized_guardband(crtc_state); 492 + else 493 + guardband = crtc_state->vrr.vmin - adjusted_mode->crtc_vdisplay; 425 494 495 + crtc_state->vrr.guardband = min(guardband, intel_vrr_max_guardband(crtc_state)); 496 + 497 + if (intel_vrr_always_use_vrr_tg(display)) { 498 + adjusted_mode->crtc_vblank_start = 499 + adjusted_mode->crtc_vtotal - crtc_state->vrr.guardband; 426 500 /* 427 - * vmin/vmax/flipline also need to be adjusted by 428 - * the vblank delay to maintain correct vtotals. 501 + * pipe_mode has already been derived from the 502 + * original adjusted_mode, keep the two in sync. 429 503 */ 430 - crtc_state->vrr.vmin -= intel_vrr_real_vblank_delay(crtc_state); 431 - crtc_state->vrr.vmax -= intel_vrr_real_vblank_delay(crtc_state); 432 - crtc_state->vrr.flipline -= intel_vrr_real_vblank_delay(crtc_state); 504 + pipe_mode->crtc_vblank_start = 505 + adjusted_mode->crtc_vblank_start; 433 506 } 507 + 508 + if (DISPLAY_VER(display) < 13) 509 + crtc_state->vrr.pipeline_full = 510 + intel_vrr_guardband_to_pipeline_full(crtc_state, 511 + crtc_state->vrr.guardband); 434 512 } 435 513 436 514 static u32 trans_vrr_ctl(const struct intel_crtc_state *crtc_state) ··· 524 460 { 525 461 struct intel_display *display = to_intel_display(crtc_state); 526 462 enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; 463 + 464 + if (!HAS_VRR(display)) 465 + return; 527 466 528 467 /* 529 468 * This bit seems to have two meanings depending on the platform: ··· 556 489 557 490 intel_vrr_set_fixed_rr_timings(crtc_state); 558 491 559 - if (!intel_vrr_always_use_vrr_tg(display) && !crtc_state->vrr.enable) 492 + if (!intel_vrr_always_use_vrr_tg(display)) 560 493 intel_de_write(display, TRANS_VRR_CTL(display, cpu_transcoder), 561 494 trans_vrr_ctl(crtc_state)); 562 495 ··· 565 498 TRANS_VRR_VSYNC(display, cpu_transcoder), 566 499 VRR_VSYNC_END(crtc_state->vrr.vsync_end) | 567 500 VRR_VSYNC_START(crtc_state->vrr.vsync_start)); 501 + 502 + /* 503 + * For BMG and LNL+ onwards the EMP_AS_SDP_TL is used for programming 504 + * double buffering point and transmission line for VRR packets for 505 + * HDMI2.1/DP/eDP/DP->HDMI2.1 PCON. 506 + * Since currently we support VRR only for DP/eDP, so this is programmed 507 + * to for Adaptive Sync SDP to Vsync start. 508 + */ 509 + if (DISPLAY_VERx100(display) == 1401 || DISPLAY_VER(display) >= 20) 510 + intel_de_write(display, 511 + EMP_AS_SDP_TL(display, cpu_transcoder), 512 + EMP_AS_SDP_DB_TL(crtc_state->vrr.vsync_start)); 568 513 } 569 514 570 515 void intel_vrr_send_push(struct intel_dsb *dsb, ··· 655 576 return false; 656 577 } 657 578 658 - static 659 - void intel_vrr_set_db_point_and_transmission_line(const struct intel_crtc_state *crtc_state) 579 + static int intel_vrr_hw_vmin(const struct intel_crtc_state *crtc_state) 580 + { 581 + struct intel_display *display = to_intel_display(crtc_state); 582 + 583 + return intel_vrr_hw_value(crtc_state, crtc_state->vrr.vmin) - 584 + intel_vrr_vmin_flipline_offset(display); 585 + } 586 + 587 + static int intel_vrr_hw_vmax(const struct intel_crtc_state *crtc_state) 588 + { 589 + return intel_vrr_hw_value(crtc_state, crtc_state->vrr.vmax); 590 + } 591 + 592 + static int intel_vrr_hw_flipline(const struct intel_crtc_state *crtc_state) 593 + { 594 + return intel_vrr_hw_value(crtc_state, crtc_state->vrr.flipline); 595 + } 596 + 597 + static void intel_vrr_set_vrr_timings(const struct intel_crtc_state *crtc_state) 660 598 { 661 599 struct intel_display *display = to_intel_display(crtc_state); 662 600 enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; 663 601 602 + intel_de_write(display, TRANS_VRR_VMIN(display, cpu_transcoder), 603 + intel_vrr_hw_vmin(crtc_state) - 1); 604 + intel_de_write(display, TRANS_VRR_VMAX(display, cpu_transcoder), 605 + intel_vrr_hw_vmax(crtc_state) - 1); 606 + intel_de_write(display, TRANS_VRR_FLIPLINE(display, cpu_transcoder), 607 + intel_vrr_hw_flipline(crtc_state) - 1); 608 + } 609 + 610 + static void intel_vrr_tg_enable(const struct intel_crtc_state *crtc_state, 611 + bool cmrr_enable) 612 + { 613 + struct intel_display *display = to_intel_display(crtc_state); 614 + enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; 615 + u32 vrr_ctl; 616 + 617 + intel_de_write(display, TRANS_PUSH(display, cpu_transcoder), TRANS_PUSH_EN); 618 + 619 + vrr_ctl = VRR_CTL_VRR_ENABLE | trans_vrr_ctl(crtc_state); 620 + 664 621 /* 665 - * For BMG and LNL+ onwards the EMP_AS_SDP_TL is used for programming 666 - * double buffering point and transmission line for VRR packets for 667 - * HDMI2.1/DP/eDP/DP->HDMI2.1 PCON. 668 - * Since currently we support VRR only for DP/eDP, so this is programmed 669 - * to for Adaptive Sync SDP to Vsync start. 622 + * FIXME this might be broken as bspec seems to imply that 623 + * even VRR_CTL_CMRR_ENABLE is armed by TRANS_CMRR_N_HI 624 + * when enabling CMRR (but not when disabling CMRR?). 670 625 */ 671 - if (DISPLAY_VERx100(display) == 1401 || DISPLAY_VER(display) >= 20) 672 - intel_de_write(display, 673 - EMP_AS_SDP_TL(display, cpu_transcoder), 674 - EMP_AS_SDP_DB_TL(crtc_state->vrr.vsync_start)); 626 + if (cmrr_enable) 627 + vrr_ctl |= VRR_CTL_CMRR_ENABLE; 628 + 629 + intel_de_write(display, TRANS_VRR_CTL(display, cpu_transcoder), vrr_ctl); 630 + } 631 + 632 + static void intel_vrr_tg_disable(const struct intel_crtc_state *old_crtc_state) 633 + { 634 + struct intel_display *display = to_intel_display(old_crtc_state); 635 + enum transcoder cpu_transcoder = old_crtc_state->cpu_transcoder; 636 + 637 + intel_de_write(display, TRANS_VRR_CTL(display, cpu_transcoder), 638 + trans_vrr_ctl(old_crtc_state)); 639 + 640 + if (intel_de_wait_for_clear(display, 641 + TRANS_VRR_STATUS(display, cpu_transcoder), 642 + VRR_STATUS_VRR_EN_LIVE, 1000)) 643 + drm_err(display->drm, "Timed out waiting for VRR live status to clear\n"); 644 + 645 + intel_de_write(display, TRANS_PUSH(display, cpu_transcoder), 0); 675 646 } 676 647 677 648 void intel_vrr_enable(const struct intel_crtc_state *crtc_state) 678 649 { 679 650 struct intel_display *display = to_intel_display(crtc_state); 680 - enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; 681 651 682 652 if (!crtc_state->vrr.enable) 683 653 return; 684 654 685 - intel_de_write(display, TRANS_VRR_VMIN(display, cpu_transcoder), 686 - crtc_state->vrr.vmin - 1); 687 - intel_de_write(display, TRANS_VRR_VMAX(display, cpu_transcoder), 688 - crtc_state->vrr.vmax - 1); 689 - intel_de_write(display, TRANS_VRR_FLIPLINE(display, cpu_transcoder), 690 - crtc_state->vrr.flipline - 1); 655 + intel_vrr_set_vrr_timings(crtc_state); 691 656 692 - intel_de_write(display, TRANS_PUSH(display, cpu_transcoder), 693 - TRANS_PUSH_EN); 694 - 695 - if (!intel_vrr_always_use_vrr_tg(display)) { 696 - intel_vrr_set_db_point_and_transmission_line(crtc_state); 697 - 698 - if (crtc_state->cmrr.enable) { 699 - intel_de_write(display, TRANS_VRR_CTL(display, cpu_transcoder), 700 - VRR_CTL_VRR_ENABLE | VRR_CTL_CMRR_ENABLE | 701 - trans_vrr_ctl(crtc_state)); 702 - } else { 703 - intel_de_write(display, TRANS_VRR_CTL(display, cpu_transcoder), 704 - VRR_CTL_VRR_ENABLE | trans_vrr_ctl(crtc_state)); 705 - } 706 - } 657 + if (!intel_vrr_always_use_vrr_tg(display)) 658 + intel_vrr_tg_enable(crtc_state, crtc_state->cmrr.enable); 707 659 } 708 660 709 661 void intel_vrr_disable(const struct intel_crtc_state *old_crtc_state) 710 662 { 711 663 struct intel_display *display = to_intel_display(old_crtc_state); 712 - enum transcoder cpu_transcoder = old_crtc_state->cpu_transcoder; 713 664 714 665 if (!old_crtc_state->vrr.enable) 715 666 return; 716 667 717 - if (!intel_vrr_always_use_vrr_tg(display)) { 718 - intel_de_write(display, TRANS_VRR_CTL(display, cpu_transcoder), 719 - trans_vrr_ctl(old_crtc_state)); 720 - intel_de_wait_for_clear(display, 721 - TRANS_VRR_STATUS(display, cpu_transcoder), 722 - VRR_STATUS_VRR_EN_LIVE, 1000); 723 - intel_de_write(display, TRANS_PUSH(display, cpu_transcoder), 0); 724 - } 668 + if (!intel_vrr_always_use_vrr_tg(display)) 669 + intel_vrr_tg_disable(old_crtc_state); 725 670 726 671 intel_vrr_set_fixed_rr_timings(old_crtc_state); 727 672 } ··· 753 650 void intel_vrr_transcoder_enable(const struct intel_crtc_state *crtc_state) 754 651 { 755 652 struct intel_display *display = to_intel_display(crtc_state); 756 - enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; 757 - 758 - if (!HAS_VRR(display)) 759 - return; 760 653 761 654 if (!intel_vrr_possible(crtc_state)) 762 655 return; 763 656 764 - if (!intel_vrr_always_use_vrr_tg(display)) { 765 - intel_de_write(display, TRANS_VRR_CTL(display, cpu_transcoder), 766 - trans_vrr_ctl(crtc_state)); 767 - return; 768 - } 769 - 770 - intel_de_write(display, TRANS_PUSH(display, cpu_transcoder), 771 - TRANS_PUSH_EN); 772 - 773 - intel_vrr_set_db_point_and_transmission_line(crtc_state); 774 - 775 - intel_de_write(display, TRANS_VRR_CTL(display, cpu_transcoder), 776 - VRR_CTL_VRR_ENABLE | trans_vrr_ctl(crtc_state)); 657 + if (intel_vrr_always_use_vrr_tg(display)) 658 + intel_vrr_tg_enable(crtc_state, false); 777 659 } 778 660 779 - void intel_vrr_transcoder_disable(const struct intel_crtc_state *crtc_state) 661 + void intel_vrr_transcoder_disable(const struct intel_crtc_state *old_crtc_state) 780 662 { 781 - struct intel_display *display = to_intel_display(crtc_state); 782 - enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; 663 + struct intel_display *display = to_intel_display(old_crtc_state); 783 664 784 - if (!HAS_VRR(display)) 665 + if (!intel_vrr_possible(old_crtc_state)) 785 666 return; 786 667 787 - if (!intel_vrr_possible(crtc_state)) 788 - return; 789 - 790 - intel_de_write(display, TRANS_VRR_CTL(display, cpu_transcoder), 0); 791 - 792 - intel_de_wait_for_clear(display, TRANS_VRR_STATUS(display, cpu_transcoder), 793 - VRR_STATUS_VRR_EN_LIVE, 1000); 794 - intel_de_write(display, TRANS_PUSH(display, cpu_transcoder), 0); 668 + if (intel_vrr_always_use_vrr_tg(display)) 669 + intel_vrr_tg_disable(old_crtc_state); 795 670 } 796 671 797 672 bool intel_vrr_is_fixed_rr(const struct intel_crtc_state *crtc_state) 798 673 { 799 674 return crtc_state->vrr.flipline && 800 675 crtc_state->vrr.flipline == crtc_state->vrr.vmax && 801 - crtc_state->vrr.flipline == intel_vrr_vmin_flipline(crtc_state); 676 + crtc_state->vrr.flipline == crtc_state->vrr.vmin; 802 677 } 803 678 804 679 void intel_vrr_get_config(struct intel_crtc_state *crtc_state) ··· 801 720 TRANS_CMRR_M_HI(display, cpu_transcoder)); 802 721 } 803 722 804 - if (DISPLAY_VER(display) >= 13) 723 + if (DISPLAY_VER(display) >= 13) { 805 724 crtc_state->vrr.guardband = 806 725 REG_FIELD_GET(XELPD_VRR_CTL_VRR_GUARDBAND_MASK, trans_vrr_ctl); 807 - else 808 - if (trans_vrr_ctl & VRR_CTL_PIPELINE_FULL_OVERRIDE) 726 + } else { 727 + if (trans_vrr_ctl & VRR_CTL_PIPELINE_FULL_OVERRIDE) { 809 728 crtc_state->vrr.pipeline_full = 810 729 REG_FIELD_GET(VRR_CTL_PIPELINE_FULL_MASK, trans_vrr_ctl); 730 + 731 + crtc_state->vrr.guardband = 732 + intel_vrr_pipeline_full_to_guardband(crtc_state, 733 + crtc_state->vrr.pipeline_full); 734 + } 735 + } 811 736 812 737 if (trans_vrr_ctl & VRR_CTL_FLIP_LINE_EN) { 813 738 crtc_state->vrr.flipline = intel_de_read(display, ··· 822 735 TRANS_VRR_VMAX(display, cpu_transcoder)) + 1; 823 736 crtc_state->vrr.vmin = intel_de_read(display, 824 737 TRANS_VRR_VMIN(display, cpu_transcoder)) + 1; 738 + 739 + if (DISPLAY_VER(display) < 13) { 740 + /* undo what intel_vrr_hw_value() does when writing the values */ 741 + crtc_state->vrr.flipline += crtc_state->set_context_latency; 742 + crtc_state->vrr.vmax += crtc_state->set_context_latency; 743 + crtc_state->vrr.vmin += crtc_state->set_context_latency; 744 + 745 + crtc_state->vrr.vmin += intel_vrr_vmin_flipline_offset(display); 746 + } 825 747 826 748 /* 827 749 * For platforms that always use VRR Timing Generator, the VTOTAL.Vtotal ··· 867 771 */ 868 772 if (crtc_state->vrr.enable) 869 773 crtc_state->mode_flags |= I915_MODE_FLAG_VRR; 774 + 775 + /* 776 + * For platforms that always use the VRR timing generator, we overwrite 777 + * crtc_vblank_start with vtotal - guardband to reflect the delayed 778 + * vblank start. This works for both default and optimized guardband values. 779 + * On other platforms, we keep the original value from 780 + * intel_get_transcoder_timings() and apply adjustments only in VRR-specific 781 + * paths as needed. 782 + */ 783 + if (intel_vrr_always_use_vrr_tg(display)) 784 + crtc_state->hw.adjusted_mode.crtc_vblank_start = 785 + crtc_state->hw.adjusted_mode.crtc_vtotal - 786 + crtc_state->vrr.guardband; 787 + } 788 + 789 + int intel_vrr_safe_window_start(const struct intel_crtc_state *crtc_state) 790 + { 791 + struct intel_display *display = to_intel_display(crtc_state); 792 + 793 + if (DISPLAY_VER(display) >= 30) 794 + return crtc_state->hw.adjusted_mode.crtc_vdisplay - 795 + crtc_state->set_context_latency; 796 + else 797 + return crtc_state->hw.adjusted_mode.crtc_vdisplay; 798 + } 799 + 800 + int intel_vrr_vmin_safe_window_end(const struct intel_crtc_state *crtc_state) 801 + { 802 + return intel_vrr_vmin_vblank_start(crtc_state) - 803 + crtc_state->set_context_latency; 870 804 }
+3 -2
drivers/gpu/drm/i915/display/intel_vrr.h
··· 21 21 void intel_vrr_check_modeset(struct intel_atomic_state *state); 22 22 void intel_vrr_compute_config(struct intel_crtc_state *crtc_state, 23 23 struct drm_connector_state *conn_state); 24 - void intel_vrr_compute_config_late(struct intel_crtc_state *crtc_state); 24 + void intel_vrr_compute_guardband(struct intel_crtc_state *crtc_state); 25 25 void intel_vrr_set_transcoder_timings(const struct intel_crtc_state *crtc_state); 26 26 void intel_vrr_enable(const struct intel_crtc_state *crtc_state); 27 27 void intel_vrr_send_push(struct intel_dsb *dsb, ··· 35 35 int intel_vrr_vmin_vtotal(const struct intel_crtc_state *crtc_state); 36 36 int intel_vrr_vmax_vblank_start(const struct intel_crtc_state *crtc_state); 37 37 int intel_vrr_vmin_vblank_start(const struct intel_crtc_state *crtc_state); 38 - int intel_vrr_vblank_delay(const struct intel_crtc_state *crtc_state); 39 38 bool intel_vrr_is_fixed_rr(const struct intel_crtc_state *crtc_state); 40 39 void intel_vrr_transcoder_enable(const struct intel_crtc_state *crtc_state); 41 40 void intel_vrr_transcoder_disable(const struct intel_crtc_state *crtc_state); 42 41 void intel_vrr_set_fixed_rr_timings(const struct intel_crtc_state *crtc_state); 43 42 bool intel_vrr_always_use_vrr_tg(struct intel_display *display); 43 + int intel_vrr_safe_window_start(const struct intel_crtc_state *crtc_state); 44 + int intel_vrr_vmin_safe_window_end(const struct intel_crtc_state *crtc_state); 44 45 45 46 #endif /* __INTEL_VRR_H__ */
+157
drivers/gpu/drm/i915/display/skl_prefill.c
··· 1 + // SPDX-License-Identifier: MIT 2 + /* 3 + * Copyright © 2025 Intel Corporation 4 + */ 5 + 6 + #include <linux/debugfs.h> 7 + 8 + #include <drm/drm_print.h> 9 + 10 + #include "intel_cdclk.h" 11 + #include "intel_display_core.h" 12 + #include "intel_display_types.h" 13 + #include "intel_vblank.h" 14 + #include "intel_vdsc.h" 15 + #include "skl_prefill.h" 16 + #include "skl_scaler.h" 17 + #include "skl_watermark.h" 18 + 19 + static unsigned int prefill_usecs_to_lines(const struct intel_crtc_state *crtc_state, 20 + unsigned int usecs) 21 + { 22 + const struct drm_display_mode *pipe_mode = &crtc_state->hw.pipe_mode; 23 + 24 + return DIV_ROUND_UP_ULL(mul_u32_u32(pipe_mode->crtc_clock, usecs << 16), 25 + pipe_mode->crtc_htotal * 1000); 26 + } 27 + 28 + static void prefill_init(struct skl_prefill_ctx *ctx, 29 + const struct intel_crtc_state *crtc_state) 30 + { 31 + memset(ctx, 0, sizeof(*ctx)); 32 + 33 + ctx->prefill.fixed = crtc_state->framestart_delay << 16; 34 + 35 + /* 20 usec for translation walks/etc. */ 36 + ctx->prefill.fixed += prefill_usecs_to_lines(crtc_state, 20); 37 + 38 + ctx->prefill.dsc = intel_vdsc_prefill_lines(crtc_state); 39 + } 40 + 41 + static void prefill_init_nocdclk_worst(struct skl_prefill_ctx *ctx, 42 + const struct intel_crtc_state *crtc_state) 43 + { 44 + prefill_init(ctx, crtc_state); 45 + 46 + ctx->prefill.wm0 = skl_wm0_prefill_lines_worst(crtc_state); 47 + ctx->prefill.scaler_1st = skl_scaler_1st_prefill_lines_worst(crtc_state); 48 + ctx->prefill.scaler_2nd = skl_scaler_2nd_prefill_lines_worst(crtc_state); 49 + 50 + ctx->adj.scaler_1st = skl_scaler_1st_prefill_adjustment_worst(crtc_state); 51 + ctx->adj.scaler_2nd = skl_scaler_2nd_prefill_adjustment_worst(crtc_state); 52 + } 53 + 54 + static void prefill_init_nocdclk(struct skl_prefill_ctx *ctx, 55 + const struct intel_crtc_state *crtc_state) 56 + { 57 + prefill_init(ctx, crtc_state); 58 + 59 + ctx->prefill.wm0 = skl_wm0_prefill_lines(crtc_state); 60 + ctx->prefill.scaler_1st = skl_scaler_1st_prefill_lines(crtc_state); 61 + ctx->prefill.scaler_2nd = skl_scaler_2nd_prefill_lines(crtc_state); 62 + 63 + ctx->adj.scaler_1st = skl_scaler_1st_prefill_adjustment(crtc_state); 64 + ctx->adj.scaler_2nd = skl_scaler_2nd_prefill_adjustment(crtc_state); 65 + } 66 + 67 + static unsigned int prefill_adjust(unsigned int value, unsigned int factor) 68 + { 69 + return DIV_ROUND_UP_ULL(mul_u32_u32(value, factor), 0x10000); 70 + } 71 + 72 + static unsigned int prefill_lines_nocdclk(const struct skl_prefill_ctx *ctx) 73 + { 74 + unsigned int prefill = 0; 75 + 76 + prefill += ctx->prefill.dsc; 77 + prefill = prefill_adjust(prefill, ctx->adj.scaler_2nd); 78 + 79 + prefill += ctx->prefill.scaler_2nd; 80 + prefill = prefill_adjust(prefill, ctx->adj.scaler_1st); 81 + 82 + prefill += ctx->prefill.scaler_1st; 83 + prefill += ctx->prefill.wm0; 84 + 85 + return prefill; 86 + } 87 + 88 + static unsigned int prefill_lines_cdclk(const struct skl_prefill_ctx *ctx) 89 + { 90 + return prefill_adjust(prefill_lines_nocdclk(ctx), ctx->adj.cdclk); 91 + } 92 + 93 + static unsigned int prefill_lines_full(const struct skl_prefill_ctx *ctx) 94 + { 95 + return ctx->prefill.fixed + prefill_lines_cdclk(ctx); 96 + } 97 + 98 + void skl_prefill_init_worst(struct skl_prefill_ctx *ctx, 99 + const struct intel_crtc_state *crtc_state) 100 + { 101 + prefill_init_nocdclk_worst(ctx, crtc_state); 102 + 103 + ctx->adj.cdclk = intel_cdclk_prefill_adjustment_worst(crtc_state); 104 + 105 + ctx->prefill.full = prefill_lines_full(ctx); 106 + } 107 + 108 + void skl_prefill_init(struct skl_prefill_ctx *ctx, 109 + const struct intel_crtc_state *crtc_state) 110 + { 111 + prefill_init_nocdclk(ctx, crtc_state); 112 + 113 + ctx->adj.cdclk = intel_cdclk_prefill_adjustment(crtc_state); 114 + 115 + ctx->prefill.full = prefill_lines_full(ctx); 116 + } 117 + 118 + static unsigned int prefill_lines_with_latency(const struct skl_prefill_ctx *ctx, 119 + const struct intel_crtc_state *crtc_state, 120 + unsigned int latency_us) 121 + { 122 + return ctx->prefill.full + prefill_usecs_to_lines(crtc_state, latency_us); 123 + } 124 + 125 + int skl_prefill_min_guardband(const struct skl_prefill_ctx *ctx, 126 + const struct intel_crtc_state *crtc_state, 127 + unsigned int latency_us) 128 + { 129 + unsigned int prefill = prefill_lines_with_latency(ctx, crtc_state, latency_us); 130 + 131 + return DIV_ROUND_UP(prefill, 0x10000); 132 + } 133 + 134 + static unsigned int prefill_guardband(const struct intel_crtc_state *crtc_state) 135 + { 136 + return intel_crtc_vblank_length(crtc_state) << 16; 137 + } 138 + 139 + bool skl_prefill_vblank_too_short(const struct skl_prefill_ctx *ctx, 140 + const struct intel_crtc_state *crtc_state, 141 + unsigned int latency_us) 142 + { 143 + unsigned int guardband = prefill_guardband(crtc_state); 144 + unsigned int prefill = prefill_lines_with_latency(ctx, crtc_state, latency_us); 145 + 146 + return guardband < prefill; 147 + } 148 + 149 + int skl_prefill_min_cdclk(const struct skl_prefill_ctx *ctx, 150 + const struct intel_crtc_state *crtc_state) 151 + { 152 + unsigned int prefill_unadjusted = prefill_lines_nocdclk(ctx); 153 + unsigned int prefill_available = prefill_guardband(crtc_state) - ctx->prefill.fixed; 154 + 155 + return intel_cdclk_min_cdclk_for_prefill(crtc_state, prefill_unadjusted, 156 + prefill_available); 157 + }
+46
drivers/gpu/drm/i915/display/skl_prefill.h
··· 1 + /* SPDX-License-Identifier: MIT */ 2 + /* 3 + * Copyright © 2025 Intel Corporation 4 + */ 5 + 6 + #ifndef __SKL_PREFILL_H__ 7 + #define __SKL_PREFILL_H__ 8 + 9 + #include <linux/types.h> 10 + 11 + struct intel_crtc_state; 12 + 13 + struct skl_prefill_ctx { 14 + /* .16 scanlines */ 15 + struct { 16 + unsigned int fixed; 17 + unsigned int wm0; 18 + unsigned int scaler_1st; 19 + unsigned int scaler_2nd; 20 + unsigned int dsc; 21 + unsigned int full; 22 + } prefill; 23 + 24 + /* .16 adjustment factors */ 25 + struct { 26 + unsigned int cdclk; 27 + unsigned int scaler_1st; 28 + unsigned int scaler_2nd; 29 + } adj; 30 + }; 31 + 32 + void skl_prefill_init_worst(struct skl_prefill_ctx *ctx, 33 + const struct intel_crtc_state *crtc_state); 34 + void skl_prefill_init(struct skl_prefill_ctx *ctx, 35 + const struct intel_crtc_state *crtc_state); 36 + 37 + bool skl_prefill_vblank_too_short(const struct skl_prefill_ctx *ctx, 38 + const struct intel_crtc_state *crtc_state, 39 + unsigned int latency_us); 40 + int skl_prefill_min_guardband(const struct skl_prefill_ctx *ctx, 41 + const struct intel_crtc_state *crtc_state, 42 + unsigned int latency_us); 43 + int skl_prefill_min_cdclk(const struct skl_prefill_ctx *ctx, 44 + const struct intel_crtc_state *crtc_state); 45 + 46 + #endif /* __SKL_PREFILL_H__ */
+221 -13
drivers/gpu/drm/i915/display/skl_scaler.c
··· 5 5 6 6 #include <drm/drm_print.h> 7 7 8 - #include "i915_utils.h" 8 + #include "intel_casf.h" 9 + #include "intel_casf_regs.h" 9 10 #include "intel_de.h" 10 11 #include "intel_display_regs.h" 11 12 #include "intel_display_trace.h" 12 13 #include "intel_display_types.h" 14 + #include "intel_display_utils.h" 13 15 #include "intel_display_wa.h" 14 16 #include "intel_fb.h" 15 17 #include "skl_scaler.h" ··· 284 282 drm_rect_width(&crtc_state->pipe_src), 285 283 drm_rect_height(&crtc_state->pipe_src), 286 284 width, height, NULL, 0, 287 - crtc_state->pch_pfit.enabled); 285 + crtc_state->pch_pfit.enabled || 286 + intel_casf_needs_scaler(crtc_state)); 288 287 } 289 288 290 289 /** ··· 324 321 } 325 322 326 323 static int intel_allocate_scaler(struct intel_crtc_scaler_state *scaler_state, 327 - struct intel_crtc *crtc) 324 + struct intel_crtc *crtc, 325 + struct intel_plane_state *plane_state, 326 + bool casf_scaler) 328 327 { 329 328 int i; 330 329 331 330 for (i = 0; i < crtc->num_scalers; i++) { 332 331 if (scaler_state->scalers[i].in_use) 332 + continue; 333 + 334 + /* CASF needs second scaler */ 335 + if (!plane_state && casf_scaler && i != 1) 333 336 continue; 334 337 335 338 scaler_state->scalers[i].in_use = true; ··· 388 379 int num_scalers_need, struct intel_crtc *crtc, 389 380 const char *name, int idx, 390 381 struct intel_plane_state *plane_state, 391 - int *scaler_id) 382 + int *scaler_id, bool casf_scaler) 392 383 { 393 384 struct intel_display *display = to_intel_display(crtc); 394 385 struct intel_crtc_scaler_state *scaler_state = &crtc_state->scaler_state; ··· 397 388 int vscale = 0; 398 389 399 390 if (*scaler_id < 0) 400 - *scaler_id = intel_allocate_scaler(scaler_state, crtc); 391 + *scaler_id = intel_allocate_scaler(scaler_state, crtc, plane_state, casf_scaler); 401 392 402 393 if (drm_WARN(display->drm, *scaler_id < 0, 403 394 "Cannot find scaler for %s:%d\n", name, idx)) ··· 529 520 struct intel_crtc_scaler_state *scaler_state = 530 521 &crtc_state->scaler_state; 531 522 523 + if (intel_casf_needs_scaler(crtc_state) && crtc_state->pch_pfit.enabled) 524 + return -EINVAL; 525 + 532 526 return intel_atomic_setup_scaler(crtc_state, 533 527 hweight32(scaler_state->scaler_users), 534 528 crtc, "CRTC", crtc->base.base.id, 535 - NULL, &scaler_state->scaler_id); 529 + NULL, &scaler_state->scaler_id, 530 + intel_casf_needs_scaler(crtc_state)); 536 531 } 537 532 538 533 static int setup_plane_scaler(struct intel_atomic_state *state, ··· 571 558 return intel_atomic_setup_scaler(crtc_state, 572 559 hweight32(scaler_state->scaler_users), 573 560 crtc, "PLANE", plane->base.base.id, 574 - plane_state, &plane_state->scaler_id); 561 + plane_state, &plane_state->scaler_id, 562 + false); 575 563 } 576 564 577 565 /** ··· 750 736 default: 751 737 MISSING_CASE(filter); 752 738 } 739 + } 740 + 741 + #define CASF_SCALER_FILTER_SELECT \ 742 + (PS_FILTER_PROGRAMMED | \ 743 + PS_Y_VERT_FILTER_SELECT(0) | \ 744 + PS_Y_HORZ_FILTER_SELECT(0) | \ 745 + PS_UV_VERT_FILTER_SELECT(0) | \ 746 + PS_UV_HORZ_FILTER_SELECT(0)) 747 + 748 + void skl_scaler_setup_casf(struct intel_crtc_state *crtc_state) 749 + { 750 + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 751 + struct intel_display *display = to_intel_display(crtc); 752 + struct drm_display_mode *adjusted_mode = 753 + &crtc_state->hw.adjusted_mode; 754 + struct intel_crtc_scaler_state *scaler_state = 755 + &crtc_state->scaler_state; 756 + struct drm_rect src, dest; 757 + int id, width, height; 758 + int x = 0, y = 0; 759 + enum pipe pipe = crtc->pipe; 760 + u32 ps_ctrl; 761 + 762 + width = adjusted_mode->crtc_hdisplay; 763 + height = adjusted_mode->crtc_vdisplay; 764 + 765 + drm_rect_init(&dest, x, y, width, height); 766 + 767 + width = drm_rect_width(&dest); 768 + height = drm_rect_height(&dest); 769 + id = scaler_state->scaler_id; 770 + 771 + drm_rect_init(&src, 0, 0, 772 + drm_rect_width(&crtc_state->pipe_src) << 16, 773 + drm_rect_height(&crtc_state->pipe_src) << 16); 774 + 775 + trace_intel_pipe_scaler_update_arm(crtc, id, x, y, width, height); 776 + 777 + ps_ctrl = PS_SCALER_EN | PS_BINDING_PIPE | scaler_state->scalers[id].mode | 778 + CASF_SCALER_FILTER_SELECT; 779 + 780 + intel_de_write_fw(display, SKL_PS_CTRL(pipe, id), ps_ctrl); 781 + intel_de_write_fw(display, SKL_PS_WIN_POS(pipe, id), 782 + PS_WIN_XPOS(x) | PS_WIN_YPOS(y)); 783 + intel_de_write_fw(display, SKL_PS_WIN_SZ(pipe, id), 784 + PS_WIN_XSIZE(width) | PS_WIN_YSIZE(height)); 753 785 } 754 786 755 787 void skl_pfit_enable(const struct intel_crtc_state *crtc_state) ··· 981 921 continue; 982 922 983 923 id = i; 984 - crtc_state->pch_pfit.enabled = true; 924 + 925 + /* Read CASF regs for second scaler */ 926 + if (HAS_CASF(display) && id == 1) 927 + intel_casf_sharpness_get_config(crtc_state); 928 + 929 + if (!crtc_state->hw.casf_params.casf_enable) 930 + crtc_state->pch_pfit.enabled = true; 985 931 986 932 pos = intel_de_read(display, SKL_PS_WIN_POS(crtc->pipe, i)); 987 933 size = intel_de_read(display, SKL_PS_WIN_SZ(crtc->pipe, i)); 988 934 989 - drm_rect_init(&crtc_state->pch_pfit.dst, 990 - REG_FIELD_GET(PS_WIN_XPOS_MASK, pos), 991 - REG_FIELD_GET(PS_WIN_YPOS_MASK, pos), 992 - REG_FIELD_GET(PS_WIN_XSIZE_MASK, size), 993 - REG_FIELD_GET(PS_WIN_YSIZE_MASK, size)); 935 + if (!crtc_state->hw.casf_params.casf_enable) 936 + drm_rect_init(&crtc_state->pch_pfit.dst, 937 + REG_FIELD_GET(PS_WIN_XPOS_MASK, pos), 938 + REG_FIELD_GET(PS_WIN_YPOS_MASK, pos), 939 + REG_FIELD_GET(PS_WIN_XSIZE_MASK, size), 940 + REG_FIELD_GET(PS_WIN_YSIZE_MASK, size)); 994 941 995 942 scaler_state->scalers[i].in_use = true; 996 943 break; ··· 1034 967 SKL_PS_ECC_STAT(crtc->pipe, scaler_state->scaler_id), 1035 968 1); 1036 969 intel_de_write(display, XELPD_DISPLAY_ERR_FATAL_MASK, 0); 970 + } 971 + 972 + unsigned int skl_scaler_1st_prefill_adjustment(const struct intel_crtc_state *crtc_state) 973 + { 974 + /* 975 + * FIXME don't have scalers assigned yet 976 + * so can't look up the scale factors 977 + */ 978 + return 0x10000; 979 + } 980 + 981 + unsigned int skl_scaler_2nd_prefill_adjustment(const struct intel_crtc_state *crtc_state) 982 + { 983 + /* 984 + * FIXME don't have scalers assigned yet 985 + * so can't look up the scale factors 986 + */ 987 + return 0x10000; 988 + } 989 + 990 + unsigned int skl_scaler_1st_prefill_lines(const struct intel_crtc_state *crtc_state) 991 + { 992 + const struct intel_crtc_scaler_state *scaler_state = 993 + &crtc_state->scaler_state; 994 + int num_scalers = hweight32(scaler_state->scaler_users); 995 + 996 + if (num_scalers > 0) 997 + return 4 << 16; 998 + 999 + return 0; 1000 + } 1001 + 1002 + unsigned int skl_scaler_2nd_prefill_lines(const struct intel_crtc_state *crtc_state) 1003 + { 1004 + const struct intel_crtc_scaler_state *scaler_state = 1005 + &crtc_state->scaler_state; 1006 + int num_scalers = hweight32(scaler_state->scaler_users); 1007 + 1008 + if (num_scalers > 1 && crtc_state->pch_pfit.enabled) 1009 + return 4 << 16; 1010 + 1011 + return 0; 1012 + } 1013 + 1014 + static unsigned int _skl_scaler_max_scale(const struct intel_crtc_state *crtc_state, 1015 + unsigned int max_scale) 1016 + { 1017 + struct intel_display *display = to_intel_display(crtc_state); 1018 + 1019 + /* 1020 + * Downscaling requires increasing cdclk, so max scale 1021 + * factor is limited to the max_dotclock/dotclock ratio. 1022 + * 1023 + * FIXME find out the max downscale factors properly 1024 + */ 1025 + return min(max_scale, DIV_ROUND_UP_ULL((u64)display->cdclk.max_dotclk_freq << 16, 1026 + crtc_state->hw.pipe_mode.crtc_clock)); 1027 + } 1028 + 1029 + unsigned int skl_scaler_max_total_scale(const struct intel_crtc_state *crtc_state) 1030 + { 1031 + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 1032 + unsigned int max_scale; 1033 + 1034 + if (crtc->num_scalers < 1) 1035 + return 0x10000; 1036 + 1037 + /* FIXME find out the max downscale factors properly */ 1038 + max_scale = 9 << 16; 1039 + if (crtc->num_scalers > 1) 1040 + max_scale *= 9; 1041 + 1042 + return _skl_scaler_max_scale(crtc_state, max_scale); 1043 + } 1044 + 1045 + unsigned int skl_scaler_max_hscale(const struct intel_crtc_state *crtc_state) 1046 + { 1047 + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 1048 + unsigned int max_scale; 1049 + 1050 + if (crtc->num_scalers < 1) 1051 + return 0x10000; 1052 + 1053 + /* FIXME find out the max downscale factors properly */ 1054 + max_scale = 3 << 16; 1055 + 1056 + return _skl_scaler_max_scale(crtc_state, max_scale); 1057 + } 1058 + 1059 + unsigned int skl_scaler_max_scale(const struct intel_crtc_state *crtc_state) 1060 + { 1061 + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 1062 + unsigned int max_scale; 1063 + 1064 + if (crtc->num_scalers < 1) 1065 + return 0x10000; 1066 + 1067 + /* FIXME find out the max downscale factors properly */ 1068 + max_scale = 9 << 16; 1069 + 1070 + return _skl_scaler_max_scale(crtc_state, max_scale); 1071 + } 1072 + 1073 + unsigned int skl_scaler_1st_prefill_adjustment_worst(const struct intel_crtc_state *crtc_state) 1074 + { 1075 + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 1076 + 1077 + if (crtc->num_scalers > 0) 1078 + return skl_scaler_max_scale(crtc_state); 1079 + else 1080 + return 0x10000; 1081 + } 1082 + 1083 + unsigned int skl_scaler_2nd_prefill_adjustment_worst(const struct intel_crtc_state *crtc_state) 1084 + { 1085 + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 1086 + 1087 + if (crtc->num_scalers > 1) 1088 + return skl_scaler_max_scale(crtc_state); 1089 + else 1090 + return 0x10000; 1091 + } 1092 + 1093 + unsigned int skl_scaler_1st_prefill_lines_worst(const struct intel_crtc_state *crtc_state) 1094 + { 1095 + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 1096 + 1097 + if (crtc->num_scalers > 0) 1098 + return 4 << 16; 1099 + else 1100 + return 0; 1101 + } 1102 + 1103 + unsigned int skl_scaler_2nd_prefill_lines_worst(const struct intel_crtc_state *crtc_state) 1104 + { 1105 + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 1106 + 1107 + if (crtc->num_scalers > 1) 1108 + return 4 << 16; 1109 + else 1110 + return 0; 1037 1111 }
+17
drivers/gpu/drm/i915/display/skl_scaler.h
··· 36 36 37 37 void skl_scaler_get_config(struct intel_crtc_state *crtc_state); 38 38 39 + void skl_scaler_setup_casf(struct intel_crtc_state *crtc_state); 40 + 39 41 enum drm_mode_status 40 42 skl_scaler_mode_valid(struct intel_display *display, 41 43 const struct drm_display_mode *mode, ··· 47 45 void adl_scaler_ecc_mask(const struct intel_crtc_state *crtc_state); 48 46 49 47 void adl_scaler_ecc_unmask(const struct intel_crtc_state *crtc_state); 48 + 49 + unsigned int skl_scaler_max_total_scale(const struct intel_crtc_state *crtc_state); 50 + unsigned int skl_scaler_max_scale(const struct intel_crtc_state *crtc_state); 51 + unsigned int skl_scaler_max_hscale(const struct intel_crtc_state *crtc_state); 52 + 53 + unsigned int skl_scaler_1st_prefill_adjustment_worst(const struct intel_crtc_state *crtc_state); 54 + unsigned int skl_scaler_2nd_prefill_adjustment_worst(const struct intel_crtc_state *crtc_state); 55 + unsigned int skl_scaler_1st_prefill_lines_worst(const struct intel_crtc_state *crtc_state); 56 + unsigned int skl_scaler_2nd_prefill_lines_worst(const struct intel_crtc_state *crtc_state); 57 + 58 + unsigned int skl_scaler_1st_prefill_adjustment(const struct intel_crtc_state *crtc_state); 59 + unsigned int skl_scaler_2nd_prefill_adjustment(const struct intel_crtc_state *crtc_state); 60 + unsigned int skl_scaler_1st_prefill_lines(const struct intel_crtc_state *crtc_state); 61 + unsigned int skl_scaler_2nd_prefill_lines(const struct intel_crtc_state *crtc_state); 62 + 50 63 #endif
+97 -71
drivers/gpu/drm/i915/display/skl_universal_plane.c
··· 7 7 #include <drm/drm_blend.h> 8 8 #include <drm/drm_damage_helper.h> 9 9 #include <drm/drm_fourcc.h> 10 + #include <drm/drm_print.h> 10 11 11 12 #include "pxp/intel_pxp.h" 12 - #include "i915_drv.h" 13 - #include "i915_utils.h" 14 13 #include "intel_bo.h" 15 14 #include "intel_de.h" 16 15 #include "intel_display_irq.h" 17 16 #include "intel_display_regs.h" 18 17 #include "intel_display_types.h" 18 + #include "intel_display_utils.h" 19 19 #include "intel_dpt.h" 20 20 #include "intel_fb.h" 21 21 #include "intel_fbc.h" ··· 24 24 #include "intel_plane.h" 25 25 #include "intel_psr.h" 26 26 #include "intel_psr_regs.h" 27 + #include "intel_step.h" 27 28 #include "skl_scaler.h" 28 29 #include "skl_universal_plane.h" 29 30 #include "skl_universal_plane_regs.h" ··· 390 389 } 391 390 } 392 391 392 + static int adl_plane_min_width(const struct drm_framebuffer *fb, 393 + int color_plane, 394 + unsigned int rotation) 395 + { 396 + return 16 / fb->format->cpp[color_plane]; 397 + } 398 + 393 399 static int icl_plane_min_width(const struct drm_framebuffer *fb, 394 400 int color_plane, 395 401 unsigned int rotation) 396 402 { 397 403 /* Wa_14011264657, Wa_14011050563: gen11+ */ 398 - switch (fb->format->format) { 399 - case DRM_FORMAT_C8: 400 - return 18; 401 - case DRM_FORMAT_RGB565: 402 - return 10; 403 - case DRM_FORMAT_XRGB8888: 404 - case DRM_FORMAT_XBGR8888: 405 - case DRM_FORMAT_ARGB8888: 406 - case DRM_FORMAT_ABGR8888: 407 - case DRM_FORMAT_XRGB2101010: 408 - case DRM_FORMAT_XBGR2101010: 409 - case DRM_FORMAT_ARGB2101010: 410 - case DRM_FORMAT_ABGR2101010: 411 - case DRM_FORMAT_XVYU2101010: 412 - case DRM_FORMAT_Y212: 413 - case DRM_FORMAT_Y216: 414 - return 6; 415 - case DRM_FORMAT_NV12: 416 - return 20; 417 - case DRM_FORMAT_P010: 418 - case DRM_FORMAT_P012: 419 - case DRM_FORMAT_P016: 420 - return 12; 421 - case DRM_FORMAT_XRGB16161616F: 422 - case DRM_FORMAT_XBGR16161616F: 423 - case DRM_FORMAT_ARGB16161616F: 424 - case DRM_FORMAT_ABGR16161616F: 425 - case DRM_FORMAT_XVYU12_16161616: 426 - case DRM_FORMAT_XVYU16161616: 427 - return 4; 428 - default: 429 - return 1; 430 - } 404 + return 16 / fb->format->cpp[color_plane] + 2; 431 405 } 432 406 433 407 static int xe3_plane_max_width(const struct drm_framebuffer *fb, ··· 437 461 unsigned int rotation) 438 462 { 439 463 return 4096; 464 + } 465 + 466 + static enum intel_fbc_id skl_fbc_id_for_pipe(enum pipe pipe) 467 + { 468 + return pipe - PIPE_A + INTEL_FBC_A; 469 + } 470 + 471 + static bool skl_plane_has_fbc(struct intel_display *display, 472 + enum intel_fbc_id fbc_id, enum plane_id plane_id) 473 + { 474 + if ((DISPLAY_RUNTIME_INFO(display)->fbc_mask & BIT(fbc_id)) == 0) 475 + return false; 476 + 477 + if (DISPLAY_VER(display) >= 20) 478 + return icl_is_hdr_plane(display, plane_id); 479 + else 480 + return plane_id == PLANE_1; 440 481 } 441 482 442 483 static int icl_plane_max_height(const struct drm_framebuffer *fb, ··· 891 898 intel_de_write_dsb(display, dsb, SEL_FETCH_PLANE_CTL(pipe, plane->id), 0); 892 899 } 893 900 901 + static void x3p_lpd_plane_update_pixel_normalizer(struct intel_dsb *dsb, 902 + struct intel_plane *plane, 903 + bool enable) 904 + { 905 + struct intel_display *display = to_intel_display(plane); 906 + enum intel_fbc_id fbc_id = skl_fbc_id_for_pipe(plane->pipe); 907 + u32 val; 908 + 909 + /* Only HDR planes have pixel normalizer and don't matter if no FBC */ 910 + if (!skl_plane_has_fbc(display, fbc_id, plane->id)) 911 + return; 912 + 913 + val = enable ? PLANE_PIXEL_NORMALIZE_NORM_FACTOR(PLANE_PIXEL_NORMALIZE_NORM_FACTOR_1_0) | 914 + PLANE_PIXEL_NORMALIZE_ENABLE : 0; 915 + 916 + intel_de_write_dsb(display, dsb, 917 + PLANE_PIXEL_NORMALIZE(plane->pipe, plane->id), val); 918 + } 919 + 894 920 static void 895 921 icl_plane_disable_arm(struct intel_dsb *dsb, 896 922 struct intel_plane *plane, ··· 925 913 skl_write_plane_wm(dsb, plane, crtc_state); 926 914 927 915 icl_plane_disable_sel_fetch_arm(dsb, plane, crtc_state); 916 + 917 + if (DISPLAY_VER(display) >= 35) 918 + x3p_lpd_plane_update_pixel_normalizer(dsb, plane, false); 919 + 928 920 intel_de_write_dsb(display, dsb, PLANE_CTL(pipe, plane_id), 0); 929 921 intel_de_write_dsb(display, dsb, PLANE_SURF(pipe, plane_id), 0); 930 922 } ··· 1588 1572 } 1589 1573 1590 1574 /* FLAT CCS doesn't need to program AUX_DIST */ 1591 - if (!HAS_FLAT_CCS(to_i915(display->drm)) && DISPLAY_VER(display) < 20) 1575 + if (HAS_AUX_CCS(display)) 1592 1576 intel_de_write_dsb(display, dsb, PLANE_AUX_DIST(pipe, plane_id), 1593 1577 skl_plane_aux_dist(plane_state, color_plane)); 1594 1578 ··· 1657 1641 skl_program_plane_scaler(dsb, plane, crtc_state, plane_state); 1658 1642 1659 1643 icl_plane_update_sel_fetch_arm(dsb, plane, crtc_state, plane_state); 1644 + 1645 + /* 1646 + * In order to have FBC for fp16 formats pixel normalizer block must be 1647 + * active. Check if pixel normalizer block need to be enabled for FBC. 1648 + * If needed, use normalization factor as 1.0 and enable the block. 1649 + */ 1650 + if (intel_fbc_is_enable_pixel_normalizer(plane_state)) 1651 + x3p_lpd_plane_update_pixel_normalizer(dsb, plane, true); 1660 1652 1661 1653 /* 1662 1654 * The control register self-arms if the plane was previously ··· 1804 1780 } 1805 1781 1806 1782 /* Y-tiling is not supported in IF-ID Interlace mode */ 1807 - if (crtc_state->hw.enable && 1808 - crtc_state->hw.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE && 1783 + if (crtc_state->hw.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE && 1809 1784 fb->modifier != DRM_FORMAT_MOD_LINEAR && 1810 1785 fb->modifier != I915_FORMAT_MOD_X_TILED) { 1811 1786 drm_dbg_kms(display->drm, ··· 1905 1882 return plane->min_width(fb, color_plane, rotation); 1906 1883 else 1907 1884 return 1; 1885 + } 1886 + 1887 + static int intel_plane_min_height(struct intel_plane *plane, 1888 + const struct drm_framebuffer *fb, 1889 + int color_plane, 1890 + unsigned int rotation) 1891 + { 1892 + return 1; 1908 1893 } 1909 1894 1910 1895 static int intel_plane_max_width(struct intel_plane *plane, ··· 2046 2015 int w = drm_rect_width(&plane_state->uapi.src) >> 16; 2047 2016 int h = drm_rect_height(&plane_state->uapi.src) >> 16; 2048 2017 int min_width = intel_plane_min_width(plane, fb, 0, rotation); 2018 + int min_height = intel_plane_min_height(plane, fb, 0, rotation); 2049 2019 int max_width = intel_plane_max_width(plane, fb, 0, rotation); 2050 2020 int max_height = intel_plane_max_height(plane, fb, 0, rotation); 2051 2021 unsigned int alignment = plane->min_alignment(plane, fb, 0); ··· 2054 2022 u32 offset; 2055 2023 int ret; 2056 2024 2057 - if (w > max_width || w < min_width || h > max_height || h < 1) { 2025 + if (w > max_width || w < min_width || h > max_height || h < min_height) { 2058 2026 drm_dbg_kms(display->drm, 2059 - "[PLANE:%d:%s] requested Y/RGB source size %dx%d outside limits (min: %dx1 max: %dx%d)\n", 2027 + "[PLANE:%d:%s] requested Y/RGB source size %dx%d outside limits (min: %dx%d max: %dx%d)\n", 2060 2028 plane->base.base.id, plane->base.name, 2061 - w, h, min_width, max_width, max_height); 2029 + w, h, min_width, min_height, max_width, max_height); 2062 2030 return -EINVAL; 2063 2031 } 2064 2032 ··· 2118 2086 int uv_plane = 1; 2119 2087 int ccs_plane = intel_fb_is_ccs_modifier(fb->modifier) ? 2120 2088 skl_main_to_aux_plane(fb, uv_plane) : 0; 2089 + int min_width = intel_plane_min_width(plane, fb, uv_plane, rotation); 2090 + int min_height = intel_plane_min_height(plane, fb, uv_plane, rotation); 2121 2091 int max_width = intel_plane_max_width(plane, fb, uv_plane, rotation); 2122 2092 int max_height = intel_plane_max_height(plane, fb, uv_plane, rotation); 2123 2093 int x = plane_state->uapi.src.x1 >> 17; ··· 2129 2095 u32 offset; 2130 2096 2131 2097 /* FIXME not quite sure how/if these apply to the chroma plane */ 2132 - if (w > max_width || h > max_height) { 2098 + if (w > max_width || w < min_width || h > max_height || h < min_height) { 2133 2099 drm_dbg_kms(display->drm, 2134 - "[PLANE:%d:%s] CbCr source size %dx%d too big (limit %dx%d)\n", 2100 + "[PLANE:%d:%s] requested CbCr source size %dx%d outside limits (min: %dx%d max: %dx%d)\n", 2135 2101 plane->base.base.id, plane->base.name, 2136 - w, h, max_width, max_height); 2102 + w, h, min_width, min_height, max_width, max_height); 2137 2103 return -EINVAL; 2138 2104 } 2139 2105 ··· 2438 2404 } 2439 2405 } 2440 2406 2441 - static enum intel_fbc_id skl_fbc_id_for_pipe(enum pipe pipe) 2442 - { 2443 - return pipe - PIPE_A + INTEL_FBC_A; 2444 - } 2445 - 2446 - static bool skl_plane_has_fbc(struct intel_display *display, 2447 - enum intel_fbc_id fbc_id, enum plane_id plane_id) 2448 - { 2449 - if ((DISPLAY_RUNTIME_INFO(display)->fbc_mask & BIT(fbc_id)) == 0) 2450 - return false; 2451 - 2452 - if (DISPLAY_VER(display) >= 20) 2453 - return icl_is_hdr_plane(display, plane_id); 2454 - else 2455 - return plane_id == PLANE_1; 2456 - } 2457 - 2458 2407 static struct intel_fbc *skl_plane_fbc(struct intel_display *display, 2459 2408 enum pipe pipe, enum plane_id plane_id) 2460 2409 { ··· 2456 2439 if (display->platform.skylake || display->platform.broxton) 2457 2440 return false; 2458 2441 2459 - if (DISPLAY_VER(display) == 9 && pipe == PIPE_C) 2442 + if (pipe == PIPE_C) 2460 2443 return false; 2461 2444 2462 - if (plane_id != PLANE_1 && plane_id != PLANE_2) 2463 - return false; 2464 - 2465 - return true; 2445 + return plane_id == PLANE_1 || plane_id == PLANE_2; 2466 2446 } 2467 2447 2468 2448 static const u32 *skl_get_plane_formats(struct intel_display *display, ··· 2475 2461 } 2476 2462 } 2477 2463 2464 + static bool glk_plane_has_planar(struct intel_display *display, 2465 + enum pipe pipe, enum plane_id plane_id) 2466 + { 2467 + return plane_id == PLANE_1 || plane_id == PLANE_2; 2468 + } 2469 + 2478 2470 static const u32 *glk_get_plane_formats(struct intel_display *display, 2479 2471 enum pipe pipe, enum plane_id plane_id, 2480 2472 int *num_formats) 2481 2473 { 2482 - if (skl_plane_has_planar(display, pipe, plane_id)) { 2474 + if (glk_plane_has_planar(display, pipe, plane_id)) { 2483 2475 *num_formats = ARRAY_SIZE(glk_planar_formats); 2484 2476 return glk_planar_formats; 2485 2477 } else { ··· 2725 2705 static bool skl_plane_has_rc_ccs(struct intel_display *display, 2726 2706 enum pipe pipe, enum plane_id plane_id) 2727 2707 { 2728 - return pipe != PIPE_C && 2729 - (plane_id == PLANE_1 || plane_id == PLANE_2); 2708 + if (pipe == PIPE_C) 2709 + return false; 2710 + 2711 + return plane_id == PLANE_1 || plane_id == PLANE_2; 2730 2712 } 2731 2713 2732 2714 static u8 skl_plane_caps(struct intel_display *display, ··· 2856 2834 intel_fbc_add_plane(skl_plane_fbc(display, pipe, plane_id), plane); 2857 2835 2858 2836 if (DISPLAY_VER(display) >= 30) { 2837 + plane->min_width = adl_plane_min_width; 2859 2838 plane->max_width = xe3_plane_max_width; 2860 2839 plane->max_height = icl_plane_max_height; 2861 2840 plane->min_cdclk = icl_plane_min_cdclk; 2862 2841 } else if (DISPLAY_VER(display) >= 11) { 2863 - plane->min_width = icl_plane_min_width; 2842 + if (DISPLAY_VER(display) >= 14 || display->platform.alderlake_p) 2843 + plane->min_width = adl_plane_min_width; 2844 + else 2845 + plane->min_width = icl_plane_min_width; 2864 2846 if (icl_is_hdr_plane(display, plane_id)) 2865 2847 plane->max_width = icl_hdr_plane_max_width; 2866 2848 else ··· 2956 2930 caps = skl_plane_caps(display, pipe, plane_id); 2957 2931 2958 2932 /* FIXME: xe has problems with AUX */ 2959 - if (!IS_ENABLED(I915) && !HAS_FLAT_CCS(to_i915(display->drm))) 2933 + if (!IS_ENABLED(I915) && HAS_AUX_CCS(display)) 2960 2934 caps &= ~(INTEL_PLANE_CAP_CCS_RC | 2961 2935 INTEL_PLANE_CAP_CCS_RC_CC | 2962 2936 INTEL_PLANE_CAP_CCS_MC);
+12
drivers/gpu/drm/i915/display/skl_universal_plane_regs.h
··· 455 455 _SEL_FETCH_PLANE_OFFSET_5_A, _SEL_FETCH_PLANE_OFFSET_5_B, \ 456 456 _SEL_FETCH_PLANE_OFFSET_6_A, _SEL_FETCH_PLANE_OFFSET_6_B) 457 457 458 + #define _PLANE_PIXEL_NORMALIZE_1_A 0x701a8 459 + #define _PLANE_PIXEL_NORMALIZE_2_A 0x702a8 460 + #define _PLANE_PIXEL_NORMALIZE_1_B 0x711a8 461 + #define _PLANE_PIXEL_NORMALIZE_2_B 0x712a8 462 + #define PLANE_PIXEL_NORMALIZE(pipe, plane) _MMIO_SKL_PLANE((pipe), (plane), \ 463 + _PLANE_PIXEL_NORMALIZE_1_A, _PLANE_PIXEL_NORMALIZE_1_B, \ 464 + _PLANE_PIXEL_NORMALIZE_2_A, _PLANE_PIXEL_NORMALIZE_2_B) 465 + #define PLANE_PIXEL_NORMALIZE_ENABLE REG_BIT(31) 466 + #define PLANE_PIXEL_NORMALIZE_NORM_FACTOR_MASK REG_GENMASK(15, 0) 467 + #define PLANE_PIXEL_NORMALIZE_NORM_FACTOR(val) REG_FIELD_PREP(PLANE_PIXEL_NORMALIZE_NORM_FACTOR_MASK, (val)) 468 + #define PLANE_PIXEL_NORMALIZE_NORM_FACTOR_1_0 0x3c00 469 + 458 470 #endif /* __SKL_UNIVERSAL_PLANE_REGS_H__ */
+182 -161
drivers/gpu/drm/i915/display/skl_watermark.c
··· 10 10 11 11 #include "soc/intel_dram.h" 12 12 #include "i915_reg.h" 13 - #include "i915_utils.h" 14 13 #include "i9xx_wm.h" 15 14 #include "intel_atomic.h" 16 15 #include "intel_bw.h" ··· 22 23 #include "intel_display_regs.h" 23 24 #include "intel_display_rpm.h" 24 25 #include "intel_display_types.h" 26 + #include "intel_display_utils.h" 25 27 #include "intel_fb.h" 26 28 #include "intel_fixed.h" 27 29 #include "intel_flipq.h" 28 30 #include "intel_pcode.h" 29 31 #include "intel_plane.h" 32 + #include "intel_vblank.h" 30 33 #include "intel_wm.h" 34 + #include "skl_prefill.h" 35 + #include "skl_scaler.h" 31 36 #include "skl_universal_plane_regs.h" 32 37 #include "skl_watermark.h" 33 38 #include "skl_watermark_regs.h" ··· 1639 1636 return ret; 1640 1637 } 1641 1638 1642 - static uint_fixed_16_16_t 1643 - intel_get_linetime_us(const struct intel_crtc_state *crtc_state) 1639 + static int skl_wm_linetime_us(const struct intel_crtc_state *crtc_state, 1640 + int pixel_rate) 1644 1641 { 1645 - struct intel_display *display = to_intel_display(crtc_state); 1646 - u32 pixel_rate; 1647 - u32 crtc_htotal; 1648 - uint_fixed_16_16_t linetime_us; 1649 - 1650 - if (!crtc_state->hw.active) 1651 - return u32_to_fixed16(0); 1652 - 1653 - pixel_rate = crtc_state->pixel_rate; 1654 - 1655 - if (drm_WARN_ON(display->drm, pixel_rate == 0)) 1656 - return u32_to_fixed16(0); 1657 - 1658 - crtc_htotal = crtc_state->hw.pipe_mode.crtc_htotal; 1659 - linetime_us = div_fixed16(crtc_htotal * 1000, pixel_rate); 1660 - 1661 - return linetime_us; 1642 + return DIV_ROUND_UP(crtc_state->hw.pipe_mode.crtc_htotal * 1000, 1643 + pixel_rate); 1662 1644 } 1663 1645 1664 1646 static int ··· 1731 1743 wp->y_tile_minimum = mul_u32_fixed16(wp->y_min_scanlines, 1732 1744 wp->plane_blocks_per_line); 1733 1745 1734 - wp->linetime_us = fixed16_to_u32_round_up(intel_get_linetime_us(crtc_state)); 1746 + wp->linetime_us = skl_wm_linetime_us(crtc_state, plane_pixel_rate); 1735 1747 1736 1748 return 0; 1737 1749 } ··· 1866 1878 } else { 1867 1879 blocks++; 1868 1880 } 1869 - 1870 - /* 1871 - * Make sure result blocks for higher latency levels are 1872 - * at least as high as level below the current level. 1873 - * Assumption in DDB algorithm optimization for special 1874 - * cases. Also covers Display WA #1125 for RC. 1875 - */ 1876 - if (result_prev->blocks > blocks) 1877 - blocks = result_prev->blocks; 1878 1881 } 1879 1882 } 1883 + 1884 + /* 1885 + * Make sure result blocks for higher latency levels are 1886 + * at least as high as level below the current level. 1887 + * Assumption in DDB algorithm optimization for special 1888 + * cases. Also covers Display WA #1125 for RC. 1889 + * 1890 + * Let's always do this as the algorithm can give non 1891 + * monotonic results on any platform. 1892 + */ 1893 + blocks = max_t(u32, blocks, result_prev->blocks); 1894 + lines = max_t(u32, lines, result_prev->lines); 1880 1895 1881 1896 if (DISPLAY_VER(display) >= 11) { 1882 1897 if (wp->y_tiled) { ··· 2148 2157 return 0; 2149 2158 } 2150 2159 2151 - static int 2152 - cdclk_prefill_adjustment(const struct intel_crtc_state *crtc_state) 2160 + unsigned int skl_wm0_prefill_lines_worst(const struct intel_crtc_state *crtc_state) 2153 2161 { 2154 2162 struct intel_display *display = to_intel_display(crtc_state); 2155 - struct intel_atomic_state *state = 2156 - to_intel_atomic_state(crtc_state->uapi.state); 2157 - const struct intel_cdclk_state *cdclk_state; 2163 + struct intel_plane *plane = to_intel_plane(crtc_state->uapi.crtc->primary); 2164 + const struct drm_display_mode *pipe_mode = &crtc_state->hw.pipe_mode; 2165 + int ret, pixel_rate, width, level = 0; 2166 + const struct drm_format_info *info; 2167 + struct skl_wm_level wm = {}; 2168 + struct skl_wm_params wp; 2169 + unsigned int latency; 2170 + u64 modifier; 2171 + u32 format; 2158 2172 2159 - cdclk_state = intel_atomic_get_cdclk_state(state); 2160 - if (IS_ERR(cdclk_state)) { 2161 - drm_WARN_ON(display->drm, PTR_ERR(cdclk_state)); 2162 - return 1; 2163 - } 2173 + /* only expected to be used for VRR guardband calculation */ 2174 + drm_WARN_ON(display->drm, !HAS_VRR(display)); 2164 2175 2165 - return min(1, DIV_ROUND_UP(crtc_state->pixel_rate, 2166 - 2 * intel_cdclk_logical(cdclk_state))); 2167 - } 2176 + /* FIXME rather ugly to pick this by hand but maybe no better way? */ 2177 + format = DRM_FORMAT_XBGR16161616F; 2178 + if (HAS_4TILE(display)) 2179 + modifier = I915_FORMAT_MOD_4_TILED; 2180 + else 2181 + modifier = I915_FORMAT_MOD_Y_TILED; 2168 2182 2169 - static int 2170 - dsc_prefill_latency(const struct intel_crtc_state *crtc_state) 2171 - { 2172 - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 2173 - const struct intel_crtc_scaler_state *scaler_state = 2174 - &crtc_state->scaler_state; 2175 - int linetime = DIV_ROUND_UP(1000 * crtc_state->hw.adjusted_mode.htotal, 2176 - crtc_state->hw.adjusted_mode.clock); 2177 - int num_scaler_users = hweight32(scaler_state->scaler_users); 2178 - int chroma_downscaling_factor = 2179 - crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420 ? 2 : 1; 2180 - u32 dsc_prefill_latency = 0; 2183 + info = drm_get_format_info(display->drm, format, modifier); 2181 2184 2182 - if (!crtc_state->dsc.compression_enable || 2183 - !num_scaler_users || 2184 - num_scaler_users > crtc->num_scalers) 2185 - return dsc_prefill_latency; 2185 + pixel_rate = DIV_ROUND_UP_ULL(mul_u32_u32(skl_scaler_max_total_scale(crtc_state), 2186 + pipe_mode->crtc_clock), 2187 + 0x10000); 2186 2188 2187 - dsc_prefill_latency = DIV_ROUND_UP(15 * linetime * chroma_downscaling_factor, 10); 2189 + /* FIXME limit to max plane width? */ 2190 + width = DIV_ROUND_UP_ULL(mul_u32_u32(skl_scaler_max_hscale(crtc_state), 2191 + pipe_mode->crtc_hdisplay), 2192 + 0x10000); 2188 2193 2189 - for (int i = 0; i < num_scaler_users; i++) { 2190 - u64 hscale_k, vscale_k; 2194 + /* FIXME is 90/270 rotation worse than 0/180? */ 2195 + ret = skl_compute_wm_params(crtc_state, width, info, 2196 + modifier, DRM_MODE_ROTATE_0, 2197 + pixel_rate, &wp, 0, 1); 2198 + drm_WARN_ON(display->drm, ret); 2191 2199 2192 - hscale_k = max(1000, mul_u32_u32(scaler_state->scalers[i].hscale, 1000) >> 16); 2193 - vscale_k = max(1000, mul_u32_u32(scaler_state->scalers[i].vscale, 1000) >> 16); 2194 - dsc_prefill_latency = DIV_ROUND_UP_ULL(dsc_prefill_latency * hscale_k * vscale_k, 2195 - 1000000); 2196 - } 2200 + latency = skl_wm_latency(display, level, &wp); 2197 2201 2198 - dsc_prefill_latency *= cdclk_prefill_adjustment(crtc_state); 2202 + skl_compute_plane_wm(crtc_state, plane, level, latency, &wp, &wm, &wm); 2199 2203 2200 - return intel_usecs_to_scanlines(&crtc_state->hw.adjusted_mode, dsc_prefill_latency); 2201 - } 2204 + /* FIXME is this sane? */ 2205 + if (wm.min_ddb_alloc == U16_MAX) 2206 + wm.lines = skl_wm_max_lines(display); 2202 2207 2203 - static int 2204 - scaler_prefill_latency(const struct intel_crtc_state *crtc_state) 2205 - { 2206 - const struct intel_crtc_scaler_state *scaler_state = 2207 - &crtc_state->scaler_state; 2208 - int num_scaler_users = hweight32(scaler_state->scaler_users); 2209 - int scaler_prefill_latency = 0; 2210 - int linetime = DIV_ROUND_UP(1000 * crtc_state->hw.adjusted_mode.htotal, 2211 - crtc_state->hw.adjusted_mode.clock); 2212 - 2213 - if (!num_scaler_users) 2214 - return scaler_prefill_latency; 2215 - 2216 - scaler_prefill_latency = 4 * linetime; 2217 - 2218 - if (num_scaler_users > 1) { 2219 - u64 hscale_k = max(1000, mul_u32_u32(scaler_state->scalers[0].hscale, 1000) >> 16); 2220 - u64 vscale_k = max(1000, mul_u32_u32(scaler_state->scalers[0].vscale, 1000) >> 16); 2221 - int chroma_downscaling_factor = 2222 - crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420 ? 2 : 1; 2223 - int latency; 2224 - 2225 - latency = DIV_ROUND_UP_ULL((4 * linetime * hscale_k * vscale_k * 2226 - chroma_downscaling_factor), 1000000); 2227 - scaler_prefill_latency += latency; 2228 - } 2229 - 2230 - scaler_prefill_latency *= cdclk_prefill_adjustment(crtc_state); 2231 - 2232 - return intel_usecs_to_scanlines(&crtc_state->hw.adjusted_mode, scaler_prefill_latency); 2233 - } 2234 - 2235 - static bool 2236 - skl_is_vblank_too_short(const struct intel_crtc_state *crtc_state, 2237 - int wm0_lines, int latency) 2238 - { 2239 - const struct drm_display_mode *adjusted_mode = 2240 - &crtc_state->hw.adjusted_mode; 2241 - 2242 - return crtc_state->framestart_delay + 2243 - intel_usecs_to_scanlines(adjusted_mode, latency) + 2244 - scaler_prefill_latency(crtc_state) + 2245 - dsc_prefill_latency(crtc_state) + 2246 - wm0_lines > 2247 - adjusted_mode->crtc_vtotal - adjusted_mode->crtc_vblank_start; 2208 + return wm.lines << 16; 2248 2209 } 2249 2210 2250 2211 static int skl_max_wm0_lines(const struct intel_crtc_state *crtc_state) ··· 2215 2272 return wm0_lines; 2216 2273 } 2217 2274 2275 + unsigned int skl_wm0_prefill_lines(const struct intel_crtc_state *crtc_state) 2276 + { 2277 + return skl_max_wm0_lines(crtc_state) << 16; 2278 + } 2279 + 2218 2280 /* 2219 2281 * TODO: In case we use PKG_C_LATENCY to allow C-states when the delayed vblank 2220 2282 * size is too small for the package C exit latency we need to notify PSR about 2221 2283 * the scenario to apply Wa_16025596647. 2222 2284 */ 2223 2285 static int skl_max_wm_level_for_vblank(struct intel_crtc_state *crtc_state, 2224 - int wm0_lines) 2286 + const struct skl_prefill_ctx *ctx) 2225 2287 { 2226 2288 struct intel_display *display = to_intel_display(crtc_state); 2289 + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 2227 2290 int level; 2228 2291 2229 2292 for (level = display->wm.num_levels - 1; level >= 0; level--) { ··· 2244 2295 if (level == 0) 2245 2296 latency = 0; 2246 2297 2247 - if (!skl_is_vblank_too_short(crtc_state, wm0_lines, latency)) 2298 + if (!skl_prefill_vblank_too_short(ctx, crtc_state, latency)) 2248 2299 return level; 2249 2300 } 2301 + 2302 + drm_dbg_kms(display->drm, "[CRTC:%d:%s] Not enough time in vblank for prefill\n", 2303 + crtc->base.base.id, crtc->base.name); 2250 2304 2251 2305 return -EINVAL; 2252 2306 } ··· 2258 2306 { 2259 2307 struct intel_display *display = to_intel_display(crtc_state); 2260 2308 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 2261 - int wm0_lines, level; 2309 + struct skl_prefill_ctx ctx; 2310 + int level; 2262 2311 2263 2312 if (!crtc_state->hw.active) 2264 2313 return 0; 2265 2314 2266 - wm0_lines = skl_max_wm0_lines(crtc_state); 2315 + skl_prefill_init(&ctx, crtc_state); 2267 2316 2268 - level = skl_max_wm_level_for_vblank(crtc_state, wm0_lines); 2317 + level = skl_max_wm_level_for_vblank(crtc_state, &ctx); 2269 2318 if (level < 0) 2270 2319 return level; 2271 2320 ··· 2275 2322 * based on whether we're limited by the vblank duration. 2276 2323 */ 2277 2324 crtc_state->wm_level_disabled = level < display->wm.num_levels - 1; 2325 + 2326 + /* 2327 + * TODO: assert that we are in fact using the maximum guardband 2328 + * if we end up disabling any WM levels here. Otherwise we clearly 2329 + * failed in using a realistic worst case prefill estimate when 2330 + * determining the guardband size. 2331 + */ 2278 2332 2279 2333 for (level++; level < display->wm.num_levels; level++) { 2280 2334 enum plane_id plane_id; ··· 2301 2341 2302 2342 if (DISPLAY_VER(display) >= 12 && 2303 2343 display->sagv.block_time_us && 2304 - skl_is_vblank_too_short(crtc_state, wm0_lines, 2305 - display->sagv.block_time_us)) { 2344 + skl_prefill_vblank_too_short(&ctx, crtc_state, 2345 + display->sagv.block_time_us)) { 2306 2346 enum plane_id plane_id; 2307 2347 2308 2348 for_each_plane_id_on_crtc(crtc, plane_id) { ··· 3134 3174 skl_watermark_ipc_update(display); 3135 3175 } 3136 3176 3137 - static void 3138 - adjust_wm_latency(struct intel_display *display, 3139 - u16 wm[], int num_levels, int read_latency) 3177 + static void multiply_wm_latency(struct intel_display *display, int mult) 3178 + { 3179 + u16 *wm = display->wm.skl_latency; 3180 + int level, num_levels = display->wm.num_levels; 3181 + 3182 + for (level = 0; level < num_levels; level++) 3183 + wm[level] *= mult; 3184 + } 3185 + 3186 + static void increase_wm_latency(struct intel_display *display, int inc) 3187 + { 3188 + u16 *wm = display->wm.skl_latency; 3189 + int level, num_levels = display->wm.num_levels; 3190 + 3191 + wm[0] += inc; 3192 + 3193 + for (level = 1; level < num_levels; level++) { 3194 + if (wm[level] == 0) 3195 + break; 3196 + 3197 + wm[level] += inc; 3198 + } 3199 + } 3200 + 3201 + static bool need_16gb_dimm_wa(struct intel_display *display) 3140 3202 { 3141 3203 const struct dram_info *dram_info = intel_dram_info(display->drm); 3142 - int i, level; 3204 + 3205 + return (display->platform.skylake || display->platform.kabylake || 3206 + display->platform.coffeelake || display->platform.cometlake || 3207 + DISPLAY_VER(display) == 11) && dram_info->has_16gb_dimms; 3208 + } 3209 + 3210 + static int wm_read_latency(struct intel_display *display) 3211 + { 3212 + if (DISPLAY_VER(display) >= 14) 3213 + return 6; 3214 + else if (DISPLAY_VER(display) >= 12) 3215 + return 3; 3216 + else 3217 + return 2; 3218 + } 3219 + 3220 + static void sanitize_wm_latency(struct intel_display *display) 3221 + { 3222 + u16 *wm = display->wm.skl_latency; 3223 + int level, num_levels = display->wm.num_levels; 3143 3224 3144 3225 /* 3145 3226 * If a level n (n > 1) has a 0us latency, all levels m (m >= n) ··· 3188 3187 * of the punit to satisfy this requirement. 3189 3188 */ 3190 3189 for (level = 1; level < num_levels; level++) { 3191 - if (wm[level] == 0) { 3192 - for (i = level + 1; i < num_levels; i++) 3193 - wm[i] = 0; 3194 - 3195 - num_levels = level; 3190 + if (wm[level] == 0) 3196 3191 break; 3197 - } 3198 3192 } 3193 + 3194 + for (level = level + 1; level < num_levels; level++) 3195 + wm[level] = 0; 3196 + } 3197 + 3198 + static void make_wm_latency_monotonic(struct intel_display *display) 3199 + { 3200 + u16 *wm = display->wm.skl_latency; 3201 + int level, num_levels = display->wm.num_levels; 3202 + 3203 + for (level = 1; level < num_levels; level++) { 3204 + if (wm[level] == 0) 3205 + break; 3206 + 3207 + wm[level] = max(wm[level], wm[level-1]); 3208 + } 3209 + } 3210 + 3211 + static void 3212 + adjust_wm_latency(struct intel_display *display) 3213 + { 3214 + u16 *wm = display->wm.skl_latency; 3215 + 3216 + if (display->platform.dg2) 3217 + multiply_wm_latency(display, 2); 3218 + 3219 + sanitize_wm_latency(display); 3220 + 3221 + make_wm_latency_monotonic(display); 3199 3222 3200 3223 /* 3201 3224 * WaWmMemoryReadLatency ··· 3228 3203 * to add proper adjustment to each valid level we retrieve 3229 3204 * from the punit when level 0 response data is 0us. 3230 3205 */ 3231 - if (wm[0] == 0) { 3232 - for (level = 0; level < num_levels; level++) 3233 - wm[level] += read_latency; 3234 - } 3206 + if (wm[0] == 0) 3207 + increase_wm_latency(display, wm_read_latency(display)); 3235 3208 3236 3209 /* 3237 - * WA Level-0 adjustment for 16Gb DIMMs: SKL+ 3210 + * WA Level-0 adjustment for 16Gb+ DIMMs: SKL+ 3238 3211 * If we could not get dimm info enable this WA to prevent from 3239 - * any underrun. If not able to get DIMM info assume 16Gb DIMM 3212 + * any underrun. If not able to get DIMM info assume 16Gb+ DIMM 3240 3213 * to avoid any underrun. 3241 3214 */ 3242 - if (!display->platform.dg2 && dram_info->has_16gb_dimms) 3243 - wm[0] += 1; 3215 + if (need_16gb_dimm_wa(display)) 3216 + increase_wm_latency(display, 1); 3244 3217 } 3245 3218 3246 - static void mtl_read_wm_latency(struct intel_display *display, u16 wm[]) 3219 + static void mtl_read_wm_latency(struct intel_display *display) 3247 3220 { 3248 - int num_levels = display->wm.num_levels; 3221 + u16 *wm = display->wm.skl_latency; 3249 3222 u32 val; 3250 3223 3251 3224 val = intel_de_read(display, MTL_LATENCY_LP0_LP1); ··· 3257 3234 val = intel_de_read(display, MTL_LATENCY_LP4_LP5); 3258 3235 wm[4] = REG_FIELD_GET(MTL_LATENCY_LEVEL_EVEN_MASK, val); 3259 3236 wm[5] = REG_FIELD_GET(MTL_LATENCY_LEVEL_ODD_MASK, val); 3260 - 3261 - adjust_wm_latency(display, wm, num_levels, 6); 3262 3237 } 3263 3238 3264 - static void skl_read_wm_latency(struct intel_display *display, u16 wm[]) 3239 + static void skl_read_wm_latency(struct intel_display *display) 3265 3240 { 3266 - int num_levels = display->wm.num_levels; 3267 - int read_latency = DISPLAY_VER(display) >= 12 ? 3 : 2; 3268 - int mult = display->platform.dg2 ? 2 : 1; 3241 + u16 *wm = display->wm.skl_latency; 3269 3242 u32 val; 3270 3243 int ret; 3271 3244 ··· 3273 3254 return; 3274 3255 } 3275 3256 3276 - wm[0] = REG_FIELD_GET(GEN9_MEM_LATENCY_LEVEL_0_4_MASK, val) * mult; 3277 - wm[1] = REG_FIELD_GET(GEN9_MEM_LATENCY_LEVEL_1_5_MASK, val) * mult; 3278 - wm[2] = REG_FIELD_GET(GEN9_MEM_LATENCY_LEVEL_2_6_MASK, val) * mult; 3279 - wm[3] = REG_FIELD_GET(GEN9_MEM_LATENCY_LEVEL_3_7_MASK, val) * mult; 3257 + wm[0] = REG_FIELD_GET(GEN9_MEM_LATENCY_LEVEL_0_4_MASK, val); 3258 + wm[1] = REG_FIELD_GET(GEN9_MEM_LATENCY_LEVEL_1_5_MASK, val); 3259 + wm[2] = REG_FIELD_GET(GEN9_MEM_LATENCY_LEVEL_2_6_MASK, val); 3260 + wm[3] = REG_FIELD_GET(GEN9_MEM_LATENCY_LEVEL_3_7_MASK, val); 3280 3261 3281 3262 /* read the second set of memory latencies[4:7] */ 3282 3263 val = 1; /* data0 to be programmed to 1 for second set */ ··· 3286 3267 return; 3287 3268 } 3288 3269 3289 - wm[4] = REG_FIELD_GET(GEN9_MEM_LATENCY_LEVEL_0_4_MASK, val) * mult; 3290 - wm[5] = REG_FIELD_GET(GEN9_MEM_LATENCY_LEVEL_1_5_MASK, val) * mult; 3291 - wm[6] = REG_FIELD_GET(GEN9_MEM_LATENCY_LEVEL_2_6_MASK, val) * mult; 3292 - wm[7] = REG_FIELD_GET(GEN9_MEM_LATENCY_LEVEL_3_7_MASK, val) * mult; 3293 - 3294 - adjust_wm_latency(display, wm, num_levels, read_latency); 3270 + wm[4] = REG_FIELD_GET(GEN9_MEM_LATENCY_LEVEL_0_4_MASK, val); 3271 + wm[5] = REG_FIELD_GET(GEN9_MEM_LATENCY_LEVEL_1_5_MASK, val); 3272 + wm[6] = REG_FIELD_GET(GEN9_MEM_LATENCY_LEVEL_2_6_MASK, val); 3273 + wm[7] = REG_FIELD_GET(GEN9_MEM_LATENCY_LEVEL_3_7_MASK, val); 3295 3274 } 3296 3275 3297 3276 static void skl_setup_wm_latency(struct intel_display *display) ··· 3300 3283 display->wm.num_levels = 8; 3301 3284 3302 3285 if (DISPLAY_VER(display) >= 14) 3303 - mtl_read_wm_latency(display, display->wm.skl_latency); 3286 + mtl_read_wm_latency(display); 3304 3287 else 3305 - skl_read_wm_latency(display, display->wm.skl_latency); 3288 + skl_read_wm_latency(display); 3306 3289 3307 - intel_print_wm_latency(display, "Gen9 Plane", display->wm.skl_latency); 3290 + intel_print_wm_latency(display, "original", display->wm.skl_latency); 3291 + 3292 + adjust_wm_latency(display); 3293 + 3294 + intel_print_wm_latency(display, "adjusted", display->wm.skl_latency); 3308 3295 } 3309 3296 3310 3297 static struct intel_global_state *intel_dbuf_duplicate_state(struct intel_global_obj *obj)
+3
drivers/gpu/drm/i915/display/skl_watermark.h
··· 79 79 80 80 bool intel_dbuf_pmdemand_needs_update(struct intel_atomic_state *state); 81 81 82 + unsigned int skl_wm0_prefill_lines_worst(const struct intel_crtc_state *crtc_state); 83 + unsigned int skl_wm0_prefill_lines(const struct intel_crtc_state *crtc_state); 84 + 82 85 #endif /* __SKL_WATERMARK_H__ */ 83 86
+88
drivers/gpu/drm/i915/display/vlv_clock.c
··· 1 + // SPDX-License-Identifier: MIT 2 + /* Copyright © 2025 Intel Corporation */ 3 + 4 + #include <drm/drm_print.h> 5 + 6 + #include "intel_display_core.h" 7 + #include "intel_display_types.h" 8 + #include "vlv_clock.h" 9 + #include "vlv_sideband.h" 10 + 11 + /* 12 + * FIXME: The caching of hpll_freq and czclk_freq relies on the first calls 13 + * occurring at a time when they can actually be read. This appears to be the 14 + * case, but is somewhat fragile. Make the initialization explicit at a point 15 + * where they can be reliably read. 16 + */ 17 + 18 + /* returns HPLL frequency in kHz */ 19 + int vlv_clock_get_hpll_vco(struct drm_device *drm) 20 + { 21 + struct intel_display *display = to_intel_display(drm); 22 + int hpll_freq, vco_freq[] = { 800, 1600, 2000, 2400 }; 23 + 24 + if (!display->vlv_clock.hpll_freq) { 25 + vlv_cck_get(drm); 26 + /* Obtain SKU information */ 27 + hpll_freq = vlv_cck_read(drm, CCK_FUSE_REG) & 28 + CCK_FUSE_HPLL_FREQ_MASK; 29 + vlv_cck_put(drm); 30 + 31 + display->vlv_clock.hpll_freq = vco_freq[hpll_freq] * 1000; 32 + 33 + drm_dbg_kms(drm, "HPLL frequency: %d kHz\n", display->vlv_clock.hpll_freq); 34 + } 35 + 36 + return display->vlv_clock.hpll_freq; 37 + } 38 + 39 + static int vlv_clock_get_cck(struct drm_device *drm, 40 + const char *name, u32 reg, int ref_freq) 41 + { 42 + u32 val; 43 + int divider; 44 + 45 + vlv_cck_get(drm); 46 + val = vlv_cck_read(drm, reg); 47 + vlv_cck_put(drm); 48 + 49 + divider = val & CCK_FREQUENCY_VALUES; 50 + 51 + drm_WARN(drm, (val & CCK_FREQUENCY_STATUS) != 52 + (divider << CCK_FREQUENCY_STATUS_SHIFT), 53 + "%s change in progress\n", name); 54 + 55 + return DIV_ROUND_CLOSEST(ref_freq << 1, divider + 1); 56 + } 57 + 58 + int vlv_clock_get_hrawclk(struct drm_device *drm) 59 + { 60 + /* RAWCLK_FREQ_VLV register updated from power well code */ 61 + return vlv_clock_get_cck(drm, "hrawclk", CCK_DISPLAY_REF_CLOCK_CONTROL, 62 + vlv_clock_get_hpll_vco(drm)); 63 + } 64 + 65 + int vlv_clock_get_czclk(struct drm_device *drm) 66 + { 67 + struct intel_display *display = to_intel_display(drm); 68 + 69 + if (!display->vlv_clock.czclk_freq) { 70 + display->vlv_clock.czclk_freq = vlv_clock_get_cck(drm, "czclk", CCK_CZ_CLOCK_CONTROL, 71 + vlv_clock_get_hpll_vco(drm)); 72 + drm_dbg_kms(drm, "CZ clock rate: %d kHz\n", display->vlv_clock.czclk_freq); 73 + } 74 + 75 + return display->vlv_clock.czclk_freq; 76 + } 77 + 78 + int vlv_clock_get_cdclk(struct drm_device *drm) 79 + { 80 + return vlv_clock_get_cck(drm, "cdclk", CCK_DISPLAY_CLOCK_CONTROL, 81 + vlv_clock_get_hpll_vco(drm)); 82 + } 83 + 84 + int vlv_clock_get_gpll(struct drm_device *drm) 85 + { 86 + return vlv_clock_get_cck(drm, "GPLL ref", CCK_GPLL_CLOCK_CONTROL, 87 + vlv_clock_get_czclk(drm)); 88 + }
+38
drivers/gpu/drm/i915/display/vlv_clock.h
··· 1 + /* SPDX-License-Identifier: MIT */ 2 + /* Copyright © 2025 Intel Corporation */ 3 + 4 + #ifndef __VLV_CLOCK_H__ 5 + #define __VLV_CLOCK_H__ 6 + 7 + struct drm_device; 8 + 9 + #ifdef I915 10 + int vlv_clock_get_hpll_vco(struct drm_device *drm); 11 + int vlv_clock_get_hrawclk(struct drm_device *drm); 12 + int vlv_clock_get_czclk(struct drm_device *drm); 13 + int vlv_clock_get_cdclk(struct drm_device *drm); 14 + int vlv_clock_get_gpll(struct drm_device *drm); 15 + #else 16 + static inline int vlv_clock_get_hpll_vco(struct drm_device *drm) 17 + { 18 + return 0; 19 + } 20 + static inline int vlv_clock_get_hrawclk(struct drm_device *drm) 21 + { 22 + return 0; 23 + } 24 + static inline int vlv_clock_get_czclk(struct drm_device *drm) 25 + { 26 + return 0; 27 + } 28 + static inline int vlv_clock_get_cdclk(struct drm_device *drm) 29 + { 30 + return 0; 31 + } 32 + static inline int vlv_clock_get_gpll(struct drm_device *drm) 33 + { 34 + return 0; 35 + } 36 + #endif 37 + 38 + #endif /* __VLV_CLOCK_H__ */
+1 -1
drivers/gpu/drm/i915/display/vlv_dsi.c
··· 34 34 #include <drm/drm_probe_helper.h> 35 35 36 36 #include "i915_reg.h" 37 - #include "i915_utils.h" 38 37 #include "intel_atomic.h" 39 38 #include "intel_backlight.h" 40 39 #include "intel_connector.h" ··· 41 42 #include "intel_de.h" 42 43 #include "intel_display_regs.h" 43 44 #include "intel_display_types.h" 45 + #include "intel_display_utils.h" 44 46 #include "intel_dsi.h" 45 47 #include "intel_dsi_vbt.h" 46 48 #include "intel_fifo_underrun.h"
+3 -2
drivers/gpu/drm/i915/gem/i915_gem_mman.c
··· 16 16 #include "i915_gem_evict.h" 17 17 #include "i915_gem_gtt.h" 18 18 #include "i915_gem_ioctls.h" 19 - #include "i915_gem_object.h" 20 19 #include "i915_gem_mman.h" 20 + #include "i915_gem_object.h" 21 + #include "i915_gem_ttm.h" 22 + #include "i915_jiffies.h" 21 23 #include "i915_mm.h" 22 24 #include "i915_trace.h" 23 25 #include "i915_user_extensions.h" 24 - #include "i915_gem_ttm.h" 25 26 #include "i915_vma.h" 26 27 27 28 static inline bool
+1
drivers/gpu/drm/i915/gem/i915_gem_object.h
··· 802 802 803 803 void i915_gem_fence_wait_priority(struct dma_fence *fence, 804 804 const struct i915_sched_attr *attr); 805 + void i915_gem_fence_wait_priority_display(struct dma_fence *fence); 805 806 806 807 int i915_gem_object_wait(struct drm_i915_gem_object *obj, 807 808 unsigned int flags,
+77 -27
drivers/gpu/drm/i915/gem/i915_gem_stolen.c
··· 24 24 #include "intel_mchbar_regs.h" 25 25 #include "intel_pci_config.h" 26 26 27 + struct intel_stolen_node { 28 + struct drm_i915_private *i915; 29 + struct drm_mm_node node; 30 + }; 31 + 27 32 /* 28 33 * The BIOS typically reserves some of the system's memory for the exclusive 29 34 * use of the integrated graphics. This memory is no longer available for ··· 41 36 * for is a boon. 42 37 */ 43 38 44 - int i915_gem_stolen_insert_node_in_range(struct drm_i915_private *i915, 45 - struct drm_mm_node *node, u64 size, 46 - unsigned alignment, u64 start, u64 end) 39 + static int __i915_gem_stolen_insert_node_in_range(struct drm_i915_private *i915, 40 + struct drm_mm_node *node, u64 size, 41 + unsigned int alignment, u64 start, u64 end) 47 42 { 48 43 int ret; 49 44 ··· 63 58 return ret; 64 59 } 65 60 66 - int i915_gem_stolen_insert_node(struct drm_i915_private *i915, 67 - struct drm_mm_node *node, u64 size, 68 - unsigned alignment) 61 + int i915_gem_stolen_insert_node_in_range(struct intel_stolen_node *node, u64 size, 62 + unsigned int alignment, u64 start, u64 end) 69 63 { 70 - return i915_gem_stolen_insert_node_in_range(i915, node, 71 - size, alignment, 72 - I915_GEM_STOLEN_BIAS, 73 - U64_MAX); 64 + return __i915_gem_stolen_insert_node_in_range(node->i915, &node->node, 65 + size, alignment, 66 + start, end); 74 67 } 75 68 76 - void i915_gem_stolen_remove_node(struct drm_i915_private *i915, 77 - struct drm_mm_node *node) 69 + static int __i915_gem_stolen_insert_node(struct drm_i915_private *i915, 70 + struct drm_mm_node *node, u64 size, 71 + unsigned int alignment) 72 + { 73 + return __i915_gem_stolen_insert_node_in_range(i915, node, 74 + size, alignment, 75 + I915_GEM_STOLEN_BIAS, 76 + U64_MAX); 77 + } 78 + 79 + int i915_gem_stolen_insert_node(struct intel_stolen_node *node, u64 size, 80 + unsigned int alignment) 81 + { 82 + return __i915_gem_stolen_insert_node(node->i915, &node->node, size, alignment); 83 + } 84 + 85 + static void __i915_gem_stolen_remove_node(struct drm_i915_private *i915, 86 + struct drm_mm_node *node) 78 87 { 79 88 mutex_lock(&i915->mm.stolen_lock); 80 89 drm_mm_remove_node(node); 81 90 mutex_unlock(&i915->mm.stolen_lock); 91 + } 92 + 93 + void i915_gem_stolen_remove_node(struct intel_stolen_node *node) 94 + { 95 + __i915_gem_stolen_remove_node(node->i915, &node->node); 82 96 } 83 97 84 98 static bool valid_stolen_size(struct drm_i915_private *i915, struct resource *dsm) ··· 707 683 struct drm_mm_node *stolen = fetch_and_zero(&obj->stolen); 708 684 709 685 GEM_BUG_ON(!stolen); 710 - i915_gem_stolen_remove_node(i915, stolen); 686 + __i915_gem_stolen_remove_node(i915, stolen); 711 687 kfree(stolen); 712 688 713 689 i915_gem_object_release_memory_region(obj); ··· 796 772 ret = drm_mm_reserve_node(&i915->mm.stolen, stolen); 797 773 mutex_unlock(&i915->mm.stolen_lock); 798 774 } else { 799 - ret = i915_gem_stolen_insert_node(i915, stolen, size, 800 - mem->min_page_size); 775 + ret = __i915_gem_stolen_insert_node(i915, stolen, size, 776 + mem->min_page_size); 801 777 } 802 778 if (ret) 803 779 goto err_free; ··· 809 785 return 0; 810 786 811 787 err_remove: 812 - i915_gem_stolen_remove_node(i915, stolen); 788 + __i915_gem_stolen_remove_node(i915, stolen); 813 789 err_free: 814 790 kfree(stolen); 815 791 return ret; ··· 1024 1000 return obj->ops == &i915_gem_object_stolen_ops; 1025 1001 } 1026 1002 1027 - bool i915_gem_stolen_initialized(const struct drm_i915_private *i915) 1003 + bool i915_gem_stolen_initialized(struct drm_device *drm) 1028 1004 { 1005 + struct drm_i915_private *i915 = to_i915(drm); 1006 + 1029 1007 return drm_mm_initialized(&i915->mm.stolen); 1030 1008 } 1031 1009 1032 - u64 i915_gem_stolen_area_address(const struct drm_i915_private *i915) 1010 + u64 i915_gem_stolen_area_address(struct drm_device *drm) 1033 1011 { 1012 + struct drm_i915_private *i915 = to_i915(drm); 1013 + 1034 1014 return i915->dsm.stolen.start; 1035 1015 } 1036 1016 1037 - u64 i915_gem_stolen_area_size(const struct drm_i915_private *i915) 1017 + u64 i915_gem_stolen_area_size(struct drm_device *drm) 1038 1018 { 1019 + struct drm_i915_private *i915 = to_i915(drm); 1020 + 1039 1021 return resource_size(&i915->dsm.stolen); 1040 1022 } 1041 1023 1042 - u64 i915_gem_stolen_node_address(const struct drm_i915_private *i915, 1043 - const struct drm_mm_node *node) 1024 + u64 i915_gem_stolen_node_address(const struct intel_stolen_node *node) 1044 1025 { 1026 + struct drm_i915_private *i915 = node->i915; 1027 + 1045 1028 return i915->dsm.stolen.start + i915_gem_stolen_node_offset(node); 1046 1029 } 1047 1030 1048 - bool i915_gem_stolen_node_allocated(const struct drm_mm_node *node) 1031 + bool i915_gem_stolen_node_allocated(const struct intel_stolen_node *node) 1049 1032 { 1050 - return drm_mm_node_allocated(node); 1033 + return drm_mm_node_allocated(&node->node); 1051 1034 } 1052 1035 1053 - u64 i915_gem_stolen_node_offset(const struct drm_mm_node *node) 1036 + u64 i915_gem_stolen_node_offset(const struct intel_stolen_node *node) 1054 1037 { 1055 - return node->start; 1038 + return node->node.start; 1056 1039 } 1057 1040 1058 - u64 i915_gem_stolen_node_size(const struct drm_mm_node *node) 1041 + u64 i915_gem_stolen_node_size(const struct intel_stolen_node *node) 1059 1042 { 1060 - return node->size; 1043 + return node->node.size; 1044 + } 1045 + 1046 + struct intel_stolen_node *i915_gem_stolen_node_alloc(struct drm_device *drm) 1047 + { 1048 + struct drm_i915_private *i915 = to_i915(drm); 1049 + struct intel_stolen_node *node; 1050 + 1051 + node = kzalloc(sizeof(*node), GFP_KERNEL); 1052 + if (!node) 1053 + return NULL; 1054 + 1055 + node->i915 = i915; 1056 + 1057 + return node; 1058 + } 1059 + 1060 + void i915_gem_stolen_node_free(const struct intel_stolen_node *node) 1061 + { 1062 + kfree(node); 1061 1063 }
+16 -18
drivers/gpu/drm/i915/gem/i915_gem_stolen.h
··· 8 8 9 9 #include <linux/types.h> 10 10 11 - struct drm_i915_private; 12 - struct drm_mm_node; 11 + struct drm_device; 13 12 struct drm_i915_gem_object; 13 + struct drm_i915_private; 14 + struct intel_stolen_node; 14 15 15 - #define i915_stolen_fb drm_mm_node 16 - 17 - int i915_gem_stolen_insert_node(struct drm_i915_private *i915, 18 - struct drm_mm_node *node, u64 size, 16 + int i915_gem_stolen_insert_node(struct intel_stolen_node *node, u64 size, 19 17 unsigned alignment); 20 - int i915_gem_stolen_insert_node_in_range(struct drm_i915_private *i915, 21 - struct drm_mm_node *node, u64 size, 18 + int i915_gem_stolen_insert_node_in_range(struct intel_stolen_node *node, u64 size, 22 19 unsigned alignment, u64 start, 23 20 u64 end); 24 - void i915_gem_stolen_remove_node(struct drm_i915_private *i915, 25 - struct drm_mm_node *node); 21 + void i915_gem_stolen_remove_node(struct intel_stolen_node *node); 26 22 struct intel_memory_region * 27 23 i915_gem_stolen_smem_setup(struct drm_i915_private *i915, u16 type, 28 24 u16 instance); ··· 34 38 35 39 #define I915_GEM_STOLEN_BIAS SZ_128K 36 40 37 - bool i915_gem_stolen_initialized(const struct drm_i915_private *i915); 38 - u64 i915_gem_stolen_area_address(const struct drm_i915_private *i915); 39 - u64 i915_gem_stolen_area_size(const struct drm_i915_private *i915); 41 + bool i915_gem_stolen_initialized(struct drm_device *drm); 42 + u64 i915_gem_stolen_area_address(struct drm_device *drm); 43 + u64 i915_gem_stolen_area_size(struct drm_device *drm); 40 44 41 - u64 i915_gem_stolen_node_address(const struct drm_i915_private *i915, 42 - const struct drm_mm_node *node); 45 + u64 i915_gem_stolen_node_address(const struct intel_stolen_node *node); 43 46 44 - bool i915_gem_stolen_node_allocated(const struct drm_mm_node *node); 45 - u64 i915_gem_stolen_node_offset(const struct drm_mm_node *node); 46 - u64 i915_gem_stolen_node_size(const struct drm_mm_node *node); 47 + bool i915_gem_stolen_node_allocated(const struct intel_stolen_node *node); 48 + u64 i915_gem_stolen_node_offset(const struct intel_stolen_node *node); 49 + u64 i915_gem_stolen_node_size(const struct intel_stolen_node *node); 50 + 51 + struct intel_stolen_node *i915_gem_stolen_node_alloc(struct drm_device *drm); 52 + void i915_gem_stolen_node_free(const struct intel_stolen_node *node); 47 53 48 54 #endif /* __I915_GEM_STOLEN_H__ */
+3 -2
drivers/gpu/drm/i915/gem/i915_gem_tiling.c
··· 145 145 return false; 146 146 } 147 147 148 - if (GRAPHICS_VER(i915) == 2 || 149 - (tiling == I915_TILING_Y && HAS_128_BYTE_Y_TILING(i915))) 148 + if (tiling == I915_TILING_Y && HAS_128_BYTE_Y_TILING(i915)) 149 + tile_width = 128; 150 + else if (GRAPHICS_VER(i915) == 2) 150 151 tile_width = 128; 151 152 else 152 153 tile_width = 512;
+1
drivers/gpu/drm/i915/gem/i915_gem_ttm.c
··· 10 10 #include <drm/drm_buddy.h> 11 11 12 12 #include "i915_drv.h" 13 + #include "i915_jiffies.h" 13 14 #include "i915_ttm_buddy_manager.h" 14 15 #include "intel_memory_region.h" 15 16 #include "intel_region_ttm.h"
+7
drivers/gpu/drm/i915/gem/i915_gem_wait.c
··· 138 138 local_bh_enable(); /* kick the tasklets if queues were reprioritised */ 139 139 } 140 140 141 + void i915_gem_fence_wait_priority_display(struct dma_fence *fence) 142 + { 143 + struct i915_sched_attr attr = { .priority = I915_PRIORITY_DISPLAY }; 144 + 145 + i915_gem_fence_wait_priority(fence, &attr); 146 + } 147 + 141 148 int 142 149 i915_gem_object_wait_priority(struct drm_i915_gem_object *obj, 143 150 unsigned int flags,
+4 -4
drivers/gpu/drm/i915/gt/gen2_engine_cs.c
··· 292 292 293 293 void gen2_irq_enable(struct intel_engine_cs *engine) 294 294 { 295 - engine->i915->irq_mask &= ~engine->irq_enable_mask; 296 - intel_uncore_write(engine->uncore, GEN2_IMR, engine->i915->irq_mask); 295 + engine->i915->gen2_imr_mask &= ~engine->irq_enable_mask; 296 + intel_uncore_write(engine->uncore, GEN2_IMR, engine->i915->gen2_imr_mask); 297 297 intel_uncore_posting_read_fw(engine->uncore, GEN2_IMR); 298 298 } 299 299 300 300 void gen2_irq_disable(struct intel_engine_cs *engine) 301 301 { 302 - engine->i915->irq_mask |= engine->irq_enable_mask; 303 - intel_uncore_write(engine->uncore, GEN2_IMR, engine->i915->irq_mask); 302 + engine->i915->gen2_imr_mask |= engine->irq_enable_mask; 303 + intel_uncore_write(engine->uncore, GEN2_IMR, engine->i915->gen2_imr_mask); 304 304 } 305 305 306 306 void gen5_irq_enable(struct intel_engine_cs *engine)
+1
drivers/gpu/drm/i915/gt/intel_engine_heartbeat.c
··· 4 4 */ 5 5 6 6 #include "i915_drv.h" 7 + #include "i915_jiffies.h" 7 8 #include "i915_request.h" 8 9 9 10 #include "intel_context.h"
+2 -1
drivers/gpu/drm/i915/gt/intel_rc6.c
··· 6 6 #include <linux/pm_runtime.h> 7 7 #include <linux/string_helpers.h> 8 8 9 + #include "display/vlv_clock.h" 9 10 #include "gem/i915_gem_region.h" 10 11 #include "i915_drv.h" 11 12 #include "i915_reg.h" ··· 803 802 /* On VLV and CHV, residency time is in CZ units rather than 1.28us */ 804 803 if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) { 805 804 mul = 1000000; 806 - div = i915->czclk_freq; 805 + div = vlv_clock_get_czclk(&i915->drm); 807 806 overflow_hw = BIT_ULL(40); 808 807 time_hw = vlv_residency_raw(uncore, reg); 809 808 } else {
+8 -10
drivers/gpu/drm/i915/gt/intel_rps.c
··· 7 7 8 8 #include <drm/intel/i915_drm.h> 9 9 10 - #include "display/intel_display.h" 11 10 #include "display/intel_display_rps.h" 11 + #include "display/vlv_clock.h" 12 12 #include "soc/intel_dram.h" 13 13 14 14 #include "i915_drv.h" ··· 1690 1690 { 1691 1691 struct drm_i915_private *i915 = rps_to_i915(rps); 1692 1692 1693 - rps->gpll_ref_freq = 1694 - vlv_get_cck_clock(&i915->drm, "GPLL ref", 1695 - CCK_GPLL_CLOCK_CONTROL, 1696 - i915->czclk_freq); 1693 + rps->gpll_ref_freq = vlv_clock_get_gpll(&i915->drm); 1697 1694 1698 1695 drm_dbg(&i915->drm, "GPLL reference freq: %d kHz\n", 1699 1696 rps->gpll_ref_freq); ··· 1700 1703 { 1701 1704 struct drm_i915_private *i915 = rps_to_i915(rps); 1702 1705 1706 + vlv_init_gpll_ref_freq(rps); 1707 + 1703 1708 vlv_iosf_sb_get(&i915->drm, 1704 1709 BIT(VLV_IOSF_SB_PUNIT) | 1705 1710 BIT(VLV_IOSF_SB_NC) | 1706 1711 BIT(VLV_IOSF_SB_CCK)); 1707 - 1708 - vlv_init_gpll_ref_freq(rps); 1709 1712 1710 1713 rps->max_freq = vlv_rps_max_freq(rps); 1711 1714 rps->rp0_freq = rps->max_freq; ··· 1734 1737 { 1735 1738 struct drm_i915_private *i915 = rps_to_i915(rps); 1736 1739 1740 + vlv_init_gpll_ref_freq(rps); 1741 + 1737 1742 vlv_iosf_sb_get(&i915->drm, 1738 1743 BIT(VLV_IOSF_SB_PUNIT) | 1739 1744 BIT(VLV_IOSF_SB_NC) | 1740 1745 BIT(VLV_IOSF_SB_CCK)); 1741 - 1742 - vlv_init_gpll_ref_freq(rps); 1743 1746 1744 1747 rps->max_freq = chv_rps_max_freq(rps); 1745 1748 rps->rp0_freq = rps->max_freq; ··· 1777 1780 1778 1781 static u32 vlv_wa_c0_ei(struct intel_rps *rps, u32 pm_iir) 1779 1782 { 1783 + struct drm_i915_private *i915 = rps_to_i915(rps); 1780 1784 struct intel_uncore *uncore = rps_to_uncore(rps); 1781 1785 const struct intel_rps_ei *prev = &rps->ei; 1782 1786 struct intel_rps_ei now; ··· 1794 1796 1795 1797 time = ktime_us_delta(now.ktime, prev->ktime); 1796 1798 1797 - time *= rps_to_i915(rps)->czclk_freq; 1799 + time *= vlv_clock_get_czclk(&i915->drm); 1798 1800 1799 1801 /* Workload can be split between render + media, 1800 1802 * e.g. SwapBuffers being blitted in X after being rendered in
+5 -4
drivers/gpu/drm/i915/gt/intel_workarounds.c
··· 5 5 6 6 #include "i915_drv.h" 7 7 #include "i915_reg.h" 8 + #include "i915_mmio_range.h" 8 9 #include "intel_context.h" 9 10 #include "intel_engine_pm.h" 10 11 #include "intel_engine_regs.h" ··· 2924 2923 wa_list_apply(&engine->wa_list); 2925 2924 } 2926 2925 2927 - static const struct i915_range mcr_ranges_gen8[] = { 2926 + static const struct i915_mmio_range mcr_ranges_gen8[] = { 2928 2927 { .start = 0x5500, .end = 0x55ff }, 2929 2928 { .start = 0x7000, .end = 0x7fff }, 2930 2929 { .start = 0x9400, .end = 0x97ff }, ··· 2933 2932 {}, 2934 2933 }; 2935 2934 2936 - static const struct i915_range mcr_ranges_gen12[] = { 2935 + static const struct i915_mmio_range mcr_ranges_gen12[] = { 2937 2936 { .start = 0x8150, .end = 0x815f }, 2938 2937 { .start = 0x9520, .end = 0x955f }, 2939 2938 { .start = 0xb100, .end = 0xb3ff }, ··· 2942 2941 {}, 2943 2942 }; 2944 2943 2945 - static const struct i915_range mcr_ranges_xehp[] = { 2944 + static const struct i915_mmio_range mcr_ranges_xehp[] = { 2946 2945 { .start = 0x4000, .end = 0x4aff }, 2947 2946 { .start = 0x5200, .end = 0x52ff }, 2948 2947 { .start = 0x5400, .end = 0x7fff }, ··· 2961 2960 2962 2961 static bool mcr_range(struct drm_i915_private *i915, u32 offset) 2963 2962 { 2964 - const struct i915_range *mcr_ranges; 2963 + const struct i915_mmio_range *mcr_ranges; 2965 2964 int i; 2966 2965 2967 2966 if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 55))
+1
drivers/gpu/drm/i915/gt/selftest_execlists.c
··· 11 11 #include "gt/intel_reset.h" 12 12 #include "gt/selftest_engine_heartbeat.h" 13 13 14 + #include "i915_jiffies.h" 14 15 #include "i915_selftest.h" 15 16 #include "selftests/i915_random.h" 16 17 #include "selftests/igt_flush_test.h"
+18 -17
drivers/gpu/drm/i915/gvt/kvmgt.c
··· 1279 1279 } 1280 1280 1281 1281 if ((info.flags & VFIO_REGION_INFO_FLAG_CAPS) && sparse) { 1282 - switch (cap_type_id) { 1283 - case VFIO_REGION_INFO_CAP_SPARSE_MMAP: 1282 + ret = -EINVAL; 1283 + if (cap_type_id == VFIO_REGION_INFO_CAP_SPARSE_MMAP) 1284 1284 ret = vfio_info_add_capability(&caps, 1285 1285 &sparse->header, 1286 1286 struct_size(sparse, areas, 1287 1287 sparse->nr_areas)); 1288 - if (ret) { 1289 - kfree(sparse); 1290 - return ret; 1291 - } 1292 - break; 1293 - default: 1288 + if (ret) { 1294 1289 kfree(sparse); 1295 - return -EINVAL; 1290 + return ret; 1296 1291 } 1297 1292 } 1298 1293 ··· 1356 1361 if (copy_from_user(&hdr, (void __user *)arg, minsz)) 1357 1362 return -EFAULT; 1358 1363 1364 + if (!is_power_of_2(hdr.flags & VFIO_IRQ_SET_DATA_TYPE_MASK) || 1365 + !is_power_of_2(hdr.flags & VFIO_IRQ_SET_ACTION_TYPE_MASK)) 1366 + return -EINVAL; 1367 + 1359 1368 if (!(hdr.flags & VFIO_IRQ_SET_DATA_NONE)) { 1360 1369 int max = intel_vgpu_get_irq_count(vgpu, hdr.index); 1370 + 1371 + if (!hdr.count) 1372 + return -EINVAL; 1361 1373 1362 1374 ret = vfio_set_irqs_validate_and_prepare(&hdr, max, 1363 1375 VFIO_PCI_NUM_IRQS, &data_size); 1364 1376 if (ret) { 1365 - gvt_vgpu_err("intel:vfio_set_irqs_validate_and_prepare failed\n"); 1366 - return -EINVAL; 1377 + gvt_vgpu_err("vfio_set_irqs_validate_and_prepare failed\n"); 1378 + return ret; 1367 1379 } 1368 - if (data_size) { 1369 - data = memdup_user((void __user *)(arg + minsz), 1370 - data_size); 1371 - if (IS_ERR(data)) 1372 - return PTR_ERR(data); 1373 - } 1380 + 1381 + data = memdup_user((void __user *)(arg + minsz), 1382 + data_size); 1383 + if (IS_ERR(data)) 1384 + return PTR_ERR(data); 1374 1385 } 1375 1386 1376 1387 ret = intel_vgpu_set_irqs(vgpu, hdr.flags, hdr.index,
+2 -2
drivers/gpu/drm/i915/gvt/mmio.c
··· 49 49 * @gpa: guest physical address 50 50 * 51 51 * Returns: 52 - * Zero on success, negative error code if failed 52 + * The MMIO offset of the given GPA 53 53 */ 54 54 int intel_vgpu_gpa_to_mmio_offset(struct intel_vgpu *vgpu, u64 gpa) 55 55 { ··· 58 58 } 59 59 60 60 #define reg_is_mmio(gvt, reg) \ 61 - (reg >= 0 && reg < gvt->device_info.mmio_size) 61 + (reg < gvt->device_info.mmio_size) 62 62 63 63 #define reg_is_gtt(gvt, reg) \ 64 64 (reg >= gvt->device_info.gtt_start_offset \
+1 -1
drivers/gpu/drm/i915/i915_config.c
··· 6 6 #include <linux/kernel.h> 7 7 8 8 #include "i915_config.h" 9 - #include "i915_utils.h" 9 + #include "i915_jiffies.h" 10 10 11 11 unsigned long 12 12 i915_fence_context_timeout(const struct drm_i915_private *i915, u64 context)
+84 -65
drivers/gpu/drm/i915/i915_driver.c
··· 46 46 #include <drm/drm_ioctl.h> 47 47 #include <drm/drm_managed.h> 48 48 #include <drm/drm_probe_helper.h> 49 + #include <drm/intel/display_member.h> 50 + #include <drm/intel/display_parent_interface.h> 49 51 50 52 #include "display/i9xx_display_sr.h" 51 53 #include "display/intel_bw.h" ··· 739 737 "DRM_I915_DEBUG_RUNTIME_PM enabled\n"); 740 738 } 741 739 740 + static const struct intel_display_parent_interface parent = { 741 + .rpm = &i915_display_rpm_interface, 742 + }; 743 + 744 + const struct intel_display_parent_interface *i915_driver_parent_interface(void) 745 + { 746 + return &parent; 747 + } 748 + 749 + /* Ensure drm and display members are placed properly. */ 750 + INTEL_DISPLAY_MEMBER_STATIC_ASSERT(struct drm_i915_private, drm, display); 751 + 742 752 static struct drm_i915_private * 743 753 i915_driver_create(struct pci_dev *pdev, const struct pci_device_id *ent) 744 754 { ··· 772 758 /* Set up device info and initial runtime info. */ 773 759 intel_device_info_driver_create(i915, pdev->device, match_info); 774 760 775 - display = intel_display_device_probe(pdev); 761 + display = intel_display_device_probe(pdev, &parent); 776 762 if (IS_ERR(display)) 777 763 return ERR_CAST(display); 778 764 ··· 1067 1053 { 1068 1054 struct drm_i915_private *dev_priv = to_i915(dev); 1069 1055 struct intel_display *display = dev_priv->display; 1070 - struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev); 1071 1056 pci_power_t opregion_target_state; 1072 1057 1073 1058 disable_rpm_wakeref_asserts(&dev_priv->runtime_pm); ··· 1079 1066 drm_kms_helper_poll_disable(dev); 1080 1067 intel_display_driver_disable_user_access(display); 1081 1068 } 1082 - 1083 - pci_save_state(pdev); 1084 1069 1085 1070 intel_display_driver_suspend(display); 1086 1071 ··· 1114 1103 { 1115 1104 struct drm_i915_private *dev_priv = to_i915(dev); 1116 1105 struct intel_display *display = dev_priv->display; 1117 - struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev); 1118 1106 struct intel_runtime_pm *rpm = &dev_priv->runtime_pm; 1119 1107 struct intel_gt *gt; 1120 1108 int ret, i; ··· 1134 1124 if (ret) { 1135 1125 drm_err(&dev_priv->drm, "Suspend complete failed: %d\n", ret); 1136 1126 intel_display_power_resume_early(display); 1137 - 1138 - goto out; 1139 1127 } 1140 1128 1141 - pci_disable_device(pdev); 1129 + enable_rpm_wakeref_asserts(rpm); 1130 + 1131 + if (!dev_priv->uncore.user_forcewake_count) 1132 + intel_runtime_pm_driver_release(rpm); 1133 + 1134 + return ret; 1135 + } 1136 + 1137 + static int i915_drm_suspend_noirq(struct drm_device *dev, bool hibernation) 1138 + { 1139 + struct drm_i915_private *dev_priv = to_i915(dev); 1140 + struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev); 1141 + 1142 1142 /* 1143 1143 * During hibernation on some platforms the BIOS may try to access 1144 1144 * the device even though it's already in D3 and hang the machine. So ··· 1160 1140 * Lenovo Thinkpad X301, X61s, X60, T60, X41 1161 1141 * Fujitsu FSC S7110 1162 1142 * Acer Aspire 1830T 1143 + * 1144 + * pci_save_state() prevents drivers/pci from 1145 + * automagically putting the device into D3. 1163 1146 */ 1164 - if (!(hibernation && GRAPHICS_VER(dev_priv) < 6)) 1165 - pci_set_power_state(pdev, PCI_D3hot); 1147 + if (hibernation && GRAPHICS_VER(dev_priv) < 6) 1148 + pci_save_state(pdev); 1166 1149 1167 - out: 1168 - enable_rpm_wakeref_asserts(rpm); 1169 - if (!dev_priv->uncore.user_forcewake_count) 1170 - intel_runtime_pm_driver_release(rpm); 1171 - 1172 - return ret; 1150 + return 0; 1173 1151 } 1174 1152 1175 1153 int i915_driver_suspend_switcheroo(struct drm_i915_private *i915, 1176 1154 pm_message_t state) 1177 1155 { 1156 + struct pci_dev *pdev = to_pci_dev(i915->drm.dev); 1178 1157 int error; 1179 1158 1180 1159 if (drm_WARN_ON_ONCE(&i915->drm, state.event != PM_EVENT_SUSPEND && ··· 1187 1168 if (error) 1188 1169 return error; 1189 1170 1190 - return i915_drm_suspend_late(&i915->drm, false); 1171 + error = i915_drm_suspend_late(&i915->drm, false); 1172 + if (error) 1173 + return error; 1174 + 1175 + pci_save_state(pdev); 1176 + pci_set_power_state(pdev, PCI_D3hot); 1177 + 1178 + return 0; 1191 1179 } 1192 1180 1193 1181 static int i915_drm_resume(struct drm_device *dev) ··· 1286 1260 { 1287 1261 struct drm_i915_private *dev_priv = to_i915(dev); 1288 1262 struct intel_display *display = dev_priv->display; 1289 - struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev); 1290 1263 struct intel_gt *gt; 1291 1264 int ret, i; 1292 1265 ··· 1298 1273 * FIXME: This should be solved with a special hdmi sink device or 1299 1274 * similar so that power domains can be employed. 1300 1275 */ 1301 - 1302 - /* 1303 - * Note that we need to set the power state explicitly, since we 1304 - * powered off the device during freeze and the PCI core won't power 1305 - * it back up for us during thaw. Powering off the device during 1306 - * freeze is not a hard requirement though, and during the 1307 - * suspend/resume phases the PCI core makes sure we get here with the 1308 - * device powered on. So in case we change our freeze logic and keep 1309 - * the device powered we can also remove the following set power state 1310 - * call. 1311 - */ 1312 - ret = pci_set_power_state(pdev, PCI_D0); 1313 - if (ret) { 1314 - drm_err(&dev_priv->drm, 1315 - "failed to set PCI D0 power state (%d)\n", ret); 1316 - return ret; 1317 - } 1318 - 1319 - /* 1320 - * Note that pci_enable_device() first enables any parent bridge 1321 - * device and only then sets the power state for this device. The 1322 - * bridge enabling is a nop though, since bridge devices are resumed 1323 - * first. The order of enabling power and enabling the device is 1324 - * imposed by the PCI core as described above, so here we preserve the 1325 - * same order for the freeze/thaw phases. 1326 - * 1327 - * TODO: eventually we should remove pci_disable_device() / 1328 - * pci_enable_enable_device() from suspend/resume. Due to how they 1329 - * depend on the device enable refcount we can't anyway depend on them 1330 - * disabling/enabling the device. 1331 - */ 1332 - if (pci_enable_device(pdev)) 1333 - return -EIO; 1334 - 1335 - pci_set_master(pdev); 1336 1276 1337 1277 disable_rpm_wakeref_asserts(&dev_priv->runtime_pm); 1338 1278 ··· 1318 1328 1319 1329 int i915_driver_resume_switcheroo(struct drm_i915_private *i915) 1320 1330 { 1331 + struct pci_dev *pdev = to_pci_dev(i915->drm.dev); 1321 1332 int ret; 1322 1333 1323 1334 if (i915->drm.switch_power_state == DRM_SWITCH_POWER_OFF) 1324 1335 return 0; 1336 + 1337 + ret = pci_set_power_state(pdev, PCI_D0); 1338 + if (ret) 1339 + return ret; 1340 + 1341 + pci_restore_state(pdev); 1325 1342 1326 1343 ret = i915_drm_resume_early(&i915->drm); 1327 1344 if (ret) ··· 1386 1389 return i915_drm_suspend_late(&i915->drm, false); 1387 1390 } 1388 1391 1392 + static int i915_pm_suspend_noirq(struct device *kdev) 1393 + { 1394 + struct drm_i915_private *i915 = kdev_to_i915(kdev); 1395 + 1396 + if (i915->drm.switch_power_state == DRM_SWITCH_POWER_OFF) 1397 + return 0; 1398 + 1399 + return i915_drm_suspend_noirq(&i915->drm, false); 1400 + } 1401 + 1389 1402 static int i915_pm_poweroff_late(struct device *kdev) 1390 1403 { 1391 1404 struct drm_i915_private *i915 = kdev_to_i915(kdev); ··· 1404 1397 return 0; 1405 1398 1406 1399 return i915_drm_suspend_late(&i915->drm, true); 1400 + } 1401 + 1402 + static int i915_pm_poweroff_noirq(struct device *kdev) 1403 + { 1404 + struct drm_i915_private *i915 = kdev_to_i915(kdev); 1405 + 1406 + if (i915->drm.switch_power_state == DRM_SWITCH_POWER_OFF) 1407 + return 0; 1408 + 1409 + return i915_drm_suspend_noirq(&i915->drm, true); 1407 1410 } 1408 1411 1409 1412 static int i915_pm_resume_early(struct device *kdev) ··· 1681 1664 .prepare = i915_pm_prepare, 1682 1665 .suspend = i915_pm_suspend, 1683 1666 .suspend_late = i915_pm_suspend_late, 1667 + .suspend_noirq = i915_pm_suspend_noirq, 1684 1668 .resume_early = i915_pm_resume_early, 1685 1669 .resume = i915_pm_resume, 1686 1670 .complete = i915_pm_complete, 1687 1671 1688 1672 /* 1689 1673 * S4 event handlers 1690 - * @freeze, @freeze_late : called (1) before creating the 1691 - * hibernation image [PMSG_FREEZE] and 1692 - * (2) after rebooting, before restoring 1693 - * the image [PMSG_QUIESCE] 1694 - * @thaw, @thaw_early : called (1) after creating the hibernation 1695 - * image, before writing it [PMSG_THAW] 1696 - * and (2) after failing to create or 1697 - * restore the image [PMSG_RECOVER] 1698 - * @poweroff, @poweroff_late: called after writing the hibernation 1699 - * image, before rebooting [PMSG_HIBERNATE] 1700 - * @restore, @restore_early : called after rebooting and restoring the 1701 - * hibernation image [PMSG_RESTORE] 1674 + * @freeze* : called (1) before creating the 1675 + * hibernation image [PMSG_FREEZE] and 1676 + * (2) after rebooting, before restoring 1677 + * the image [PMSG_QUIESCE] 1678 + * @thaw* : called (1) after creating the hibernation 1679 + * image, before writing it [PMSG_THAW] 1680 + * and (2) after failing to create or 1681 + * restore the image [PMSG_RECOVER] 1682 + * @poweroff* : called after writing the hibernation 1683 + * image, before rebooting [PMSG_HIBERNATE] 1684 + * @restore* : called after rebooting and restoring the 1685 + * hibernation image [PMSG_RESTORE] 1702 1686 */ 1703 1687 .freeze = i915_pm_freeze, 1704 1688 .freeze_late = i915_pm_freeze_late, ··· 1707 1689 .thaw = i915_pm_thaw, 1708 1690 .poweroff = i915_pm_suspend, 1709 1691 .poweroff_late = i915_pm_poweroff_late, 1692 + .poweroff_noirq = i915_pm_poweroff_noirq, 1710 1693 .restore_early = i915_pm_restore_early, 1711 1694 .restore = i915_pm_restore, 1712 1695
+2
drivers/gpu/drm/i915/i915_driver.h
··· 12 12 struct pci_device_id; 13 13 struct drm_i915_private; 14 14 struct drm_printer; 15 + struct intel_display_parent_interface; 15 16 16 17 #define DRIVER_NAME "i915" 17 18 #define DRIVER_DESC "Intel Graphics" ··· 25 24 26 25 int i915_driver_resume_switcheroo(struct drm_i915_private *i915); 27 26 int i915_driver_suspend_switcheroo(struct drm_i915_private *i915, pm_message_t state); 27 + const struct intel_display_parent_interface *i915_driver_parent_interface(void); 28 28 29 29 void 30 30 i915_print_iommu_status(struct drm_i915_private *i915, struct drm_printer *p);
+4 -17
drivers/gpu/drm/i915/i915_drv.h
··· 174 174 struct drm_i915_private { 175 175 struct drm_device drm; 176 176 177 + /* display device data, must be placed after drm device member */ 177 178 struct intel_display *display; 178 179 179 180 /* FIXME: Device release actions should all be moved to drmm_ */ ··· 235 234 /* Sideband mailbox protection */ 236 235 struct mutex sb_lock; 237 236 238 - /** Cached value of IMR to avoid reads in updating the bitfield */ 239 - u32 irq_mask; 237 + /* Cached value of gen 2-4 IMR to avoid reads in updating the bitfield */ 238 + u32 gen2_imr_mask; 240 239 241 240 bool preserve_bios_swizzle; 242 - 243 - unsigned int hpll_freq; 244 - unsigned int czclk_freq; 245 241 246 242 /** 247 243 * wq - Driver workqueue for GEM. ··· 488 490 #define IS_ALDERLAKE_P(i915) IS_PLATFORM(i915, INTEL_ALDERLAKE_P) 489 491 #define IS_DG2(i915) IS_PLATFORM(i915, INTEL_DG2) 490 492 #define IS_METEORLAKE(i915) IS_PLATFORM(i915, INTEL_METEORLAKE) 491 - /* 492 - * Display code shared by i915 and Xe relies on macros like IS_LUNARLAKE, 493 - * so we need to define these even on platforms that the i915 base driver 494 - * doesn't support. Ensure the parameter is used in the definition to 495 - * avoid 'unused variable' warnings when compiling the shared display code 496 - * for i915. 497 - */ 498 - #define IS_LUNARLAKE(i915) (0 && i915) 499 - #define IS_BATTLEMAGE(i915) (0 && i915) 500 - #define IS_PANTHERLAKE(i915) (0 && i915) 501 493 502 494 #define IS_ARROWLAKE_H(i915) \ 503 495 IS_SUBPLATFORM(i915, INTEL_METEORLAKE, INTEL_SUBPLATFORM_ARL_H) ··· 592 604 /* With the 945 and later, Y tiling got adjusted so that it was 32 128-byte 593 605 * rows, which changed the alignment requirements and fence programming. 594 606 */ 595 - #define HAS_128_BYTE_Y_TILING(i915) (GRAPHICS_VER(i915) != 2 && \ 596 - !(IS_I915G(i915) || IS_I915GM(i915))) 607 + #define HAS_128_BYTE_Y_TILING(i915) (!IS_I915G(i915) && !IS_I915GM(i915)) 597 608 598 609 #define HAS_RC6(i915) (INTEL_INFO(i915)->has_rc6) 599 610 #define HAS_RC6p(i915) (INTEL_INFO(i915)->has_rc6p)
+25 -80
drivers/gpu/drm/i915/i915_irq.c
··· 33 33 34 34 #include <drm/drm_drv.h> 35 35 36 - #include "display/intel_display_core.h" 37 36 #include "display/intel_display_irq.h" 38 37 #include "display/intel_hotplug.h" 39 38 #include "display/intel_hotplug_irq.h" 40 39 #include "display/intel_lpe_audio.h" 41 - #include "display/intel_psr_regs.h" 42 40 43 41 #include "gt/intel_breadcrumbs.h" 44 42 #include "gt/intel_gt.h" ··· 413 415 struct drm_i915_private *i915 = arg; 414 416 struct intel_display *display = i915->display; 415 417 void __iomem * const regs = intel_uncore_regs(&i915->uncore); 416 - u32 de_iir, gt_iir, de_ier, sde_ier = 0; 418 + u32 gt_iir, de_ier = 0, sde_ier = 0; 417 419 irqreturn_t ret = IRQ_NONE; 418 420 419 421 if (unlikely(!intel_irqs_enabled(i915))) ··· 422 424 /* IRQs are synced during runtime_suspend, we don't require a wakeref */ 423 425 disable_rpm_wakeref_asserts(&i915->runtime_pm); 424 426 425 - /* disable master interrupt before clearing iir */ 426 - de_ier = raw_reg_read(regs, DEIER); 427 - raw_reg_write(regs, DEIER, de_ier & ~DE_MASTER_IRQ_CONTROL); 428 - 429 - /* Disable south interrupts. We'll only write to SDEIIR once, so further 430 - * interrupts will will be stored on its back queue, and then we'll be 431 - * able to process them after we restore SDEIER (as soon as we restore 432 - * it, we'll get an interrupt if SDEIIR still has something to process 433 - * due to its back queue). */ 434 - if (!HAS_PCH_NOP(display)) { 435 - sde_ier = raw_reg_read(regs, SDEIER); 436 - raw_reg_write(regs, SDEIER, 0); 437 - } 427 + /* Disable master and south interrupts */ 428 + ilk_display_irq_master_disable(display, &de_ier, &sde_ier); 438 429 439 430 /* Find, clear, then process each source of interrupt */ 440 431 ··· 437 450 ret = IRQ_HANDLED; 438 451 } 439 452 440 - de_iir = raw_reg_read(regs, DEIIR); 441 - if (de_iir) { 442 - raw_reg_write(regs, DEIIR, de_iir); 443 - if (DISPLAY_VER(display) >= 7) 444 - ivb_display_irq_handler(display, de_iir); 445 - else 446 - ilk_display_irq_handler(display, de_iir); 453 + if (ilk_display_irq_handler(display)) 447 454 ret = IRQ_HANDLED; 448 - } 449 455 450 456 if (GRAPHICS_VER(i915) >= 6) { 451 457 u32 pm_iir = raw_reg_read(regs, GEN6_PMIIR); ··· 449 469 } 450 470 } 451 471 452 - raw_reg_write(regs, DEIER, de_ier); 453 - if (sde_ier) 454 - raw_reg_write(regs, SDEIER, sde_ier); 472 + /* Re-enable master and south interrupts */ 473 + ilk_display_irq_master_enable(display, de_ier, sde_ier); 455 474 456 475 pmu_irq_stats(i915, ret); 457 476 ··· 635 656 static void ilk_irq_reset(struct drm_i915_private *dev_priv) 636 657 { 637 658 struct intel_display *display = dev_priv->display; 638 - struct intel_uncore *uncore = &dev_priv->uncore; 639 659 640 - gen2_irq_reset(uncore, DE_IRQ_REGS); 641 - dev_priv->irq_mask = ~0u; 642 - 643 - if (GRAPHICS_VER(dev_priv) == 7) 644 - intel_uncore_write(uncore, GEN7_ERR_INT, 0xffffffff); 645 - 646 - if (IS_HASWELL(dev_priv)) { 647 - intel_uncore_write(uncore, EDP_PSR_IMR, 0xffffffff); 648 - intel_uncore_write(uncore, EDP_PSR_IIR, 0xffffffff); 649 - } 650 - 660 + /* The master interrupt enable is in DEIER, reset display irq first */ 661 + ilk_display_irq_reset(display); 651 662 gen5_gt_irq_reset(to_gt(dev_priv)); 652 - 653 - ibx_display_irq_reset(display); 654 663 } 655 664 656 665 static void valleyview_irq_reset(struct drm_i915_private *dev_priv) ··· 793 826 intel_uncore_posting_read(&dev_priv->uncore, GEN8_MASTER_IRQ); 794 827 } 795 828 829 + #define I9XX_HAS_FBC(i915) (IS_I85X(i915) || IS_I865G(i915) || IS_I915GM(i915) || IS_I945GM(i915)) 830 + 796 831 static u32 i9xx_error_mask(struct drm_i915_private *i915) 797 832 { 798 - struct intel_display *display = i915->display; 799 833 /* 800 834 * On gen2/3 FBC generates (seemingly spurious) 801 835 * display INVALID_GTT/INVALID_GTT_PTE table errors. ··· 809 841 * Unfortunately we can't mask off individual PGTBL_ER bits, 810 842 * so we just have to mask off all page table errors via EMR. 811 843 */ 812 - if (HAS_FBC(display)) 844 + if (I9XX_HAS_FBC(i915)) 813 845 return I915_ERROR_MEMORY_REFRESH; 814 846 else 815 847 return I915_ERROR_PAGE_TABLE | ··· 865 897 866 898 gen2_error_reset(uncore, GEN2_ERROR_REGS); 867 899 gen2_irq_reset(uncore, GEN2_IRQ_REGS); 868 - dev_priv->irq_mask = ~0u; 900 + dev_priv->gen2_imr_mask = ~0u; 869 901 } 870 902 871 903 static void i915_irq_postinstall(struct drm_i915_private *dev_priv) ··· 876 908 877 909 gen2_error_init(uncore, GEN2_ERROR_REGS, ~i9xx_error_mask(dev_priv)); 878 910 879 - dev_priv->irq_mask = 880 - ~(I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | 881 - I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | 882 - I915_MASTER_ERROR_INTERRUPT); 911 + enable_mask = i9xx_display_irq_enable_mask(display) | 912 + I915_MASTER_ERROR_INTERRUPT; 883 913 884 - enable_mask = 885 - I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | 886 - I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | 887 - I915_MASTER_ERROR_INTERRUPT | 888 - I915_USER_INTERRUPT; 914 + dev_priv->gen2_imr_mask = ~enable_mask; 889 915 890 - if (DISPLAY_VER(display) >= 3) { 891 - dev_priv->irq_mask &= ~I915_ASLE_INTERRUPT; 892 - enable_mask |= I915_ASLE_INTERRUPT; 893 - } 916 + enable_mask |= I915_USER_INTERRUPT; 894 917 895 - if (HAS_HOTPLUG(display)) { 896 - dev_priv->irq_mask &= ~I915_DISPLAY_PORT_INTERRUPT; 897 - enable_mask |= I915_DISPLAY_PORT_INTERRUPT; 898 - } 899 - 900 - gen2_irq_init(uncore, GEN2_IRQ_REGS, dev_priv->irq_mask, enable_mask); 918 + gen2_irq_init(uncore, GEN2_IRQ_REGS, dev_priv->gen2_imr_mask, enable_mask); 901 919 902 920 i915_display_irq_postinstall(display); 903 921 } ··· 912 958 913 959 ret = IRQ_HANDLED; 914 960 915 - if (HAS_HOTPLUG(display) && 916 - iir & I915_DISPLAY_PORT_INTERRUPT) 961 + if (iir & I915_DISPLAY_PORT_INTERRUPT) 917 962 hotplug_status = i9xx_hpd_irq_ack(display); 918 963 919 964 /* Call regardless, as some status bits might not be ··· 952 999 953 1000 gen2_error_reset(uncore, GEN2_ERROR_REGS); 954 1001 gen2_irq_reset(uncore, GEN2_IRQ_REGS); 955 - dev_priv->irq_mask = ~0u; 1002 + dev_priv->gen2_imr_mask = ~0u; 956 1003 } 957 1004 958 1005 static u32 i965_error_mask(struct drm_i915_private *i915) ··· 982 1029 983 1030 gen2_error_init(uncore, GEN2_ERROR_REGS, ~i965_error_mask(dev_priv)); 984 1031 985 - dev_priv->irq_mask = 986 - ~(I915_ASLE_INTERRUPT | 987 - I915_DISPLAY_PORT_INTERRUPT | 988 - I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | 989 - I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | 990 - I915_MASTER_ERROR_INTERRUPT); 1032 + enable_mask = i9xx_display_irq_enable_mask(display) | 1033 + I915_MASTER_ERROR_INTERRUPT; 991 1034 992 - enable_mask = 993 - I915_ASLE_INTERRUPT | 994 - I915_DISPLAY_PORT_INTERRUPT | 995 - I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | 996 - I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | 997 - I915_MASTER_ERROR_INTERRUPT | 998 - I915_USER_INTERRUPT; 1035 + dev_priv->gen2_imr_mask = ~enable_mask; 1036 + 1037 + enable_mask |= I915_USER_INTERRUPT; 999 1038 1000 1039 if (IS_G4X(dev_priv)) 1001 1040 enable_mask |= I915_BSD_USER_INTERRUPT; 1002 1041 1003 - gen2_irq_init(uncore, GEN2_IRQ_REGS, dev_priv->irq_mask, enable_mask); 1042 + gen2_irq_init(uncore, GEN2_IRQ_REGS, dev_priv->gen2_imr_mask, enable_mask); 1004 1043 1005 1044 i965_display_irq_postinstall(display); 1006 1045 }
+16
drivers/gpu/drm/i915/i915_jiffies.h
··· 1 + /* SPDX-License-Identifier: MIT */ 2 + /* Copyright © 2025 Intel Corporation */ 3 + 4 + #ifndef __I915_JIFFIES_H__ 5 + #define __I915_JIFFIES_H__ 6 + 7 + #include <linux/jiffies.h> 8 + 9 + static inline unsigned long msecs_to_jiffies_timeout(const unsigned int m) 10 + { 11 + unsigned long j = msecs_to_jiffies(m); 12 + 13 + return min_t(unsigned long, MAX_JIFFY_OFFSET, j + 1); 14 + } 15 + 16 + #endif /* __I915_JIFFIES_H__ */
+18
drivers/gpu/drm/i915/i915_mmio_range.c
··· 1 + // SPDX-License-Identifier: MIT 2 + /* 3 + * Copyright © 2025 Intel Corporation 4 + */ 5 + 6 + #include "i915_mmio_range.h" 7 + 8 + bool i915_mmio_range_table_contains(u32 addr, const struct i915_mmio_range *table) 9 + { 10 + while (table->start || table->end) { 11 + if (addr >= table->start && addr <= table->end) 12 + return true; 13 + 14 + table++; 15 + } 16 + 17 + return false; 18 + }
+19
drivers/gpu/drm/i915/i915_mmio_range.h
··· 1 + /* SPDX-License-Identifier: MIT */ 2 + /* 3 + * Copyright © 2025 Intel Corporation 4 + */ 5 + 6 + #ifndef __I915_MMIO_RANGE_H__ 7 + #define __I915_MMIO_RANGE_H__ 8 + 9 + #include <linux/types.h> 10 + 11 + /* Other register ranges (e.g., shadow tables, MCR tables, etc.) */ 12 + struct i915_mmio_range { 13 + u32 start; 14 + u32 end; 15 + }; 16 + 17 + bool i915_mmio_range_table_contains(u32 addr, const struct i915_mmio_range *table); 18 + 19 + #endif /* __I915_MMIO_RANGE_H__ */
+28 -39
drivers/gpu/drm/i915/i915_perf.c
··· 219 219 #include "i915_perf.h" 220 220 #include "i915_perf_oa_regs.h" 221 221 #include "i915_reg.h" 222 + #include "i915_mmio_range.h" 222 223 223 224 /* HW requires this to be a power of two, between 128k and 16M, though driver 224 225 * is currently generally designed assuming the largest 16M size is used such ··· 4321 4320 return false; 4322 4321 } 4323 4322 4324 - static bool reg_in_range_table(u32 addr, const struct i915_range *table) 4325 - { 4326 - while (table->start || table->end) { 4327 - if (addr >= table->start && addr <= table->end) 4328 - return true; 4329 - 4330 - table++; 4331 - } 4332 - 4333 - return false; 4334 - } 4335 - 4336 4323 #define REG_EQUAL(addr, mmio) \ 4337 4324 ((addr) == i915_mmio_reg_offset(mmio)) 4338 4325 4339 - static const struct i915_range gen7_oa_b_counters[] = { 4326 + static const struct i915_mmio_range gen7_oa_b_counters[] = { 4340 4327 { .start = 0x2710, .end = 0x272c }, /* OASTARTTRIG[1-8] */ 4341 4328 { .start = 0x2740, .end = 0x275c }, /* OAREPORTTRIG[1-8] */ 4342 4329 { .start = 0x2770, .end = 0x27ac }, /* OACEC[0-7][0-1] */ 4343 4330 {} 4344 4331 }; 4345 4332 4346 - static const struct i915_range gen12_oa_b_counters[] = { 4333 + static const struct i915_mmio_range gen12_oa_b_counters[] = { 4347 4334 { .start = 0x2b2c, .end = 0x2b2c }, /* GEN12_OAG_OA_PESS */ 4348 4335 { .start = 0xd900, .end = 0xd91c }, /* GEN12_OAG_OASTARTTRIG[1-8] */ 4349 4336 { .start = 0xd920, .end = 0xd93c }, /* GEN12_OAG_OAREPORTTRIG1[1-8] */ ··· 4342 4353 {} 4343 4354 }; 4344 4355 4345 - static const struct i915_range mtl_oam_b_counters[] = { 4356 + static const struct i915_mmio_range mtl_oam_b_counters[] = { 4346 4357 { .start = 0x393000, .end = 0x39301c }, /* GEN12_OAM_STARTTRIG1[1-8] */ 4347 4358 { .start = 0x393020, .end = 0x39303c }, /* GEN12_OAM_REPORTTRIG1[1-8] */ 4348 4359 { .start = 0x393040, .end = 0x39307c }, /* GEN12_OAM_CEC[0-7][0-1] */ ··· 4350 4361 {} 4351 4362 }; 4352 4363 4353 - static const struct i915_range xehp_oa_b_counters[] = { 4364 + static const struct i915_mmio_range xehp_oa_b_counters[] = { 4354 4365 { .start = 0xdc48, .end = 0xdc48 }, /* OAA_ENABLE_REG */ 4355 4366 { .start = 0xdd00, .end = 0xdd48 }, /* OAG_LCE0_0 - OAA_LENABLE_REG */ 4356 4367 {} 4357 4368 }; 4358 4369 4359 - static const struct i915_range gen7_oa_mux_regs[] = { 4370 + static const struct i915_mmio_range gen7_oa_mux_regs[] = { 4360 4371 { .start = 0x91b8, .end = 0x91cc }, /* OA_PERFCNT[1-2], OA_PERFMATRIX */ 4361 4372 { .start = 0x9800, .end = 0x9888 }, /* MICRO_BP0_0 - NOA_WRITE */ 4362 4373 { .start = 0xe180, .end = 0xe180 }, /* HALF_SLICE_CHICKEN2 */ 4363 4374 {} 4364 4375 }; 4365 4376 4366 - static const struct i915_range hsw_oa_mux_regs[] = { 4377 + static const struct i915_mmio_range hsw_oa_mux_regs[] = { 4367 4378 { .start = 0x09e80, .end = 0x09ea4 }, /* HSW_MBVID2_NOA[0-9] */ 4368 4379 { .start = 0x09ec0, .end = 0x09ec0 }, /* HSW_MBVID2_MISR0 */ 4369 4380 { .start = 0x25100, .end = 0x2ff90 }, 4370 4381 {} 4371 4382 }; 4372 4383 4373 - static const struct i915_range chv_oa_mux_regs[] = { 4384 + static const struct i915_mmio_range chv_oa_mux_regs[] = { 4374 4385 { .start = 0x182300, .end = 0x1823a4 }, 4375 4386 {} 4376 4387 }; 4377 4388 4378 - static const struct i915_range gen8_oa_mux_regs[] = { 4389 + static const struct i915_mmio_range gen8_oa_mux_regs[] = { 4379 4390 { .start = 0x0d00, .end = 0x0d2c }, /* RPM_CONFIG[0-1], NOA_CONFIG[0-8] */ 4380 4391 { .start = 0x20cc, .end = 0x20cc }, /* WAIT_FOR_RC6_EXIT */ 4381 4392 {} 4382 4393 }; 4383 4394 4384 - static const struct i915_range gen11_oa_mux_regs[] = { 4395 + static const struct i915_mmio_range gen11_oa_mux_regs[] = { 4385 4396 { .start = 0x91c8, .end = 0x91dc }, /* OA_PERFCNT[3-4] */ 4386 4397 {} 4387 4398 }; 4388 4399 4389 - static const struct i915_range gen12_oa_mux_regs[] = { 4400 + static const struct i915_mmio_range gen12_oa_mux_regs[] = { 4390 4401 { .start = 0x0d00, .end = 0x0d04 }, /* RPM_CONFIG[0-1] */ 4391 4402 { .start = 0x0d0c, .end = 0x0d2c }, /* NOA_CONFIG[0-8] */ 4392 4403 { .start = 0x9840, .end = 0x9840 }, /* GDT_CHICKEN_BITS */ ··· 4399 4410 * Ref: 14010536224: 4400 4411 * 0x20cc is repurposed on MTL, so use a separate array for MTL. 4401 4412 */ 4402 - static const struct i915_range mtl_oa_mux_regs[] = { 4413 + static const struct i915_mmio_range mtl_oa_mux_regs[] = { 4403 4414 { .start = 0x0d00, .end = 0x0d04 }, /* RPM_CONFIG[0-1] */ 4404 4415 { .start = 0x0d0c, .end = 0x0d2c }, /* NOA_CONFIG[0-8] */ 4405 4416 { .start = 0x9840, .end = 0x9840 }, /* GDT_CHICKEN_BITS */ ··· 4410 4421 4411 4422 static bool gen7_is_valid_b_counter_addr(struct i915_perf *perf, u32 addr) 4412 4423 { 4413 - return reg_in_range_table(addr, gen7_oa_b_counters); 4424 + return i915_mmio_range_table_contains(addr, gen7_oa_b_counters); 4414 4425 } 4415 4426 4416 4427 static bool gen8_is_valid_mux_addr(struct i915_perf *perf, u32 addr) 4417 4428 { 4418 - return reg_in_range_table(addr, gen7_oa_mux_regs) || 4419 - reg_in_range_table(addr, gen8_oa_mux_regs); 4429 + return i915_mmio_range_table_contains(addr, gen7_oa_mux_regs) || 4430 + i915_mmio_range_table_contains(addr, gen8_oa_mux_regs); 4420 4431 } 4421 4432 4422 4433 static bool gen11_is_valid_mux_addr(struct i915_perf *perf, u32 addr) 4423 4434 { 4424 - return reg_in_range_table(addr, gen7_oa_mux_regs) || 4425 - reg_in_range_table(addr, gen8_oa_mux_regs) || 4426 - reg_in_range_table(addr, gen11_oa_mux_regs); 4435 + return i915_mmio_range_table_contains(addr, gen7_oa_mux_regs) || 4436 + i915_mmio_range_table_contains(addr, gen8_oa_mux_regs) || 4437 + i915_mmio_range_table_contains(addr, gen11_oa_mux_regs); 4427 4438 } 4428 4439 4429 4440 static bool hsw_is_valid_mux_addr(struct i915_perf *perf, u32 addr) 4430 4441 { 4431 - return reg_in_range_table(addr, gen7_oa_mux_regs) || 4432 - reg_in_range_table(addr, hsw_oa_mux_regs); 4442 + return i915_mmio_range_table_contains(addr, gen7_oa_mux_regs) || 4443 + i915_mmio_range_table_contains(addr, hsw_oa_mux_regs); 4433 4444 } 4434 4445 4435 4446 static bool chv_is_valid_mux_addr(struct i915_perf *perf, u32 addr) 4436 4447 { 4437 - return reg_in_range_table(addr, gen7_oa_mux_regs) || 4438 - reg_in_range_table(addr, chv_oa_mux_regs); 4448 + return i915_mmio_range_table_contains(addr, gen7_oa_mux_regs) || 4449 + i915_mmio_range_table_contains(addr, chv_oa_mux_regs); 4439 4450 } 4440 4451 4441 4452 static bool gen12_is_valid_b_counter_addr(struct i915_perf *perf, u32 addr) 4442 4453 { 4443 - return reg_in_range_table(addr, gen12_oa_b_counters); 4454 + return i915_mmio_range_table_contains(addr, gen12_oa_b_counters); 4444 4455 } 4445 4456 4446 4457 static bool mtl_is_valid_oam_b_counter_addr(struct i915_perf *perf, u32 addr) 4447 4458 { 4448 4459 if (HAS_OAM(perf->i915) && 4449 4460 GRAPHICS_VER_FULL(perf->i915) >= IP_VER(12, 70)) 4450 - return reg_in_range_table(addr, mtl_oam_b_counters); 4461 + return i915_mmio_range_table_contains(addr, mtl_oam_b_counters); 4451 4462 4452 4463 return false; 4453 4464 } 4454 4465 4455 4466 static bool xehp_is_valid_b_counter_addr(struct i915_perf *perf, u32 addr) 4456 4467 { 4457 - return reg_in_range_table(addr, xehp_oa_b_counters) || 4458 - reg_in_range_table(addr, gen12_oa_b_counters) || 4468 + return i915_mmio_range_table_contains(addr, xehp_oa_b_counters) || 4469 + i915_mmio_range_table_contains(addr, gen12_oa_b_counters) || 4459 4470 mtl_is_valid_oam_b_counter_addr(perf, addr); 4460 4471 } 4461 4472 4462 4473 static bool gen12_is_valid_mux_addr(struct i915_perf *perf, u32 addr) 4463 4474 { 4464 4475 if (GRAPHICS_VER_FULL(perf->i915) >= IP_VER(12, 70)) 4465 - return reg_in_range_table(addr, mtl_oa_mux_regs); 4476 + return i915_mmio_range_table_contains(addr, mtl_oa_mux_regs); 4466 4477 else 4467 - return reg_in_range_table(addr, gen12_oa_mux_regs); 4478 + return i915_mmio_range_table_contains(addr, gen12_oa_mux_regs); 4468 4479 } 4469 4480 4470 4481 static u32 mask_reg_value(u32 reg, u32 val)
+2 -2
drivers/gpu/drm/i915/i915_pmu.c
··· 895 895 struct i915_str_attribute *eattr; 896 896 897 897 eattr = container_of(attr, struct i915_str_attribute, attr); 898 - return sprintf(buf, "%s\n", eattr->str); 898 + return sysfs_emit(buf, "%s\n", eattr->str); 899 899 } 900 900 901 901 #define I915_PMU_FORMAT_ATTR(_name, _config) \ ··· 925 925 struct i915_ext_attribute *eattr; 926 926 927 927 eattr = container_of(attr, struct i915_ext_attribute, attr); 928 - return sprintf(buf, "config=0x%lx\n", eattr->val); 928 + return sysfs_emit(buf, "config=0x%lx\n", eattr->val); 929 929 } 930 930 931 931 #define __event(__counter, __name, __unit) \
+10
drivers/gpu/drm/i915/i915_reg_defs.h
··· 174 174 */ 175 175 #define REG_FIELD_GET8(__mask, __val) ((u8)FIELD_GET(__mask, __val)) 176 176 177 + /** 178 + * REG_FIELD_MAX() - produce the maximum value representable by a field 179 + * @__mask: shifted mask defining the field's length and position 180 + * 181 + * Local wrapper for FIELD_MAX() to return the maximum bit value that can 182 + * be held in the field specified by @_mask, cast to u32 for consistency 183 + * with other macros. 184 + */ 185 + #define REG_FIELD_MAX(__mask) ((u32)FIELD_MAX(__mask)) 186 + 177 187 typedef struct { 178 188 u32 reg; 179 189 } i915_reg_t;
+4 -37
drivers/gpu/drm/i915/i915_utils.h
··· 38 38 39 39 struct drm_i915_private; 40 40 41 + #ifndef MISSING_CASE 41 42 #define MISSING_CASE(x) WARN(1, "Missing case (%s == %ld)\n", \ 42 43 __stringify(x), (long)(x)) 44 + #endif 43 45 44 46 #if IS_ENABLED(CONFIG_DRM_I915_DEBUG) 45 47 ··· 67 65 drm_err(&(i915)->drm, fmt, ##__VA_ARGS__); \ 68 66 }) 69 67 68 + #ifndef fetch_and_zero 70 69 #define fetch_and_zero(ptr) ({ \ 71 70 typeof(*ptr) __T = *(ptr); \ 72 71 *(ptr) = (typeof(*ptr))0; \ 73 72 __T; \ 74 73 }) 74 + #endif 75 75 76 76 /* 77 77 * check_user_mbz: Check that a user value exists and is zero ··· 103 99 { 104 100 return (n != 0 && ((n & (n - 1)) == 0)); 105 101 } 106 - 107 - static inline unsigned long msecs_to_jiffies_timeout(const unsigned int m) 108 - { 109 - unsigned long j = msecs_to_jiffies(m); 110 - 111 - return min_t(unsigned long, MAX_JIFFY_OFFSET, j + 1); 112 - } 113 - 114 - /* 115 - * If you need to wait X milliseconds between events A and B, but event B 116 - * doesn't happen exactly after event A, you record the timestamp (jiffies) of 117 - * when event A happened, then just before event B you call this function and 118 - * pass the timestamp as the first argument, and X as the second argument. 119 - */ 120 - static inline void 121 - wait_remaining_ms_from_jiffies(unsigned long timestamp_jiffies, int to_wait_ms) 122 - { 123 - unsigned long target_jiffies, tmp_jiffies, remaining_jiffies; 124 - 125 - /* 126 - * Don't re-read the value of "jiffies" every time since it may change 127 - * behind our back and break the math. 128 - */ 129 - tmp_jiffies = jiffies; 130 - target_jiffies = timestamp_jiffies + 131 - msecs_to_jiffies_timeout(to_wait_ms); 132 - 133 - if (time_after(target_jiffies, tmp_jiffies)) { 134 - remaining_jiffies = target_jiffies - tmp_jiffies; 135 - while (remaining_jiffies) 136 - remaining_jiffies = 137 - schedule_timeout_uninterruptible(remaining_jiffies); 138 - } 139 - } 140 - 141 - #define KHz(x) (1000 * (x)) 142 - #define MHz(x) KHz(1000 * (x)) 143 102 144 103 void add_taint_for_CI(struct drm_i915_private *i915, unsigned int taint); 145 104 static inline void __add_taint_for_CI(unsigned int taint)
+77
drivers/gpu/drm/i915/intel_runtime_pm.c
··· 29 29 #include <linux/pm_runtime.h> 30 30 31 31 #include <drm/drm_print.h> 32 + #include <drm/intel/display_parent_interface.h> 32 33 33 34 #include "i915_drv.h" 34 35 #include "i915_trace.h" ··· 177 176 178 177 return track_intel_runtime_pm_wakeref(rpm); 179 178 } 179 + 180 + static struct intel_runtime_pm *drm_to_rpm(const struct drm_device *drm) 181 + { 182 + struct drm_i915_private *i915 = to_i915(drm); 183 + 184 + return &i915->runtime_pm; 185 + } 186 + 187 + static struct ref_tracker *i915_display_rpm_get(const struct drm_device *drm) 188 + { 189 + return intel_runtime_pm_get(drm_to_rpm(drm)); 190 + } 191 + 192 + static struct ref_tracker *i915_display_rpm_get_raw(const struct drm_device *drm) 193 + { 194 + return intel_runtime_pm_get_raw(drm_to_rpm(drm)); 195 + } 196 + 197 + static struct ref_tracker *i915_display_rpm_get_if_in_use(const struct drm_device *drm) 198 + { 199 + return intel_runtime_pm_get_if_in_use(drm_to_rpm(drm)); 200 + } 201 + 202 + static struct ref_tracker *i915_display_rpm_get_noresume(const struct drm_device *drm) 203 + { 204 + return intel_runtime_pm_get_noresume(drm_to_rpm(drm)); 205 + } 206 + 207 + static void i915_display_rpm_put(const struct drm_device *drm, struct ref_tracker *wakeref) 208 + { 209 + intel_runtime_pm_put(drm_to_rpm(drm), wakeref); 210 + } 211 + 212 + static void i915_display_rpm_put_raw(const struct drm_device *drm, struct ref_tracker *wakeref) 213 + { 214 + intel_runtime_pm_put_raw(drm_to_rpm(drm), wakeref); 215 + } 216 + 217 + static void i915_display_rpm_put_unchecked(const struct drm_device *drm) 218 + { 219 + intel_runtime_pm_put_unchecked(drm_to_rpm(drm)); 220 + } 221 + 222 + static bool i915_display_rpm_suspended(const struct drm_device *drm) 223 + { 224 + return intel_runtime_pm_suspended(drm_to_rpm(drm)); 225 + } 226 + 227 + static void i915_display_rpm_assert_held(const struct drm_device *drm) 228 + { 229 + assert_rpm_wakelock_held(drm_to_rpm(drm)); 230 + } 231 + 232 + static void i915_display_rpm_assert_block(const struct drm_device *drm) 233 + { 234 + disable_rpm_wakeref_asserts(drm_to_rpm(drm)); 235 + } 236 + 237 + static void i915_display_rpm_assert_unblock(const struct drm_device *drm) 238 + { 239 + enable_rpm_wakeref_asserts(drm_to_rpm(drm)); 240 + } 241 + 242 + const struct intel_display_rpm_interface i915_display_rpm_interface = { 243 + .get = i915_display_rpm_get, 244 + .get_raw = i915_display_rpm_get_raw, 245 + .get_if_in_use = i915_display_rpm_get_if_in_use, 246 + .get_noresume = i915_display_rpm_get_noresume, 247 + .put = i915_display_rpm_put, 248 + .put_raw = i915_display_rpm_put_raw, 249 + .put_unchecked = i915_display_rpm_put_unchecked, 250 + .suspended = i915_display_rpm_suspended, 251 + .assert_held = i915_display_rpm_assert_held, 252 + .assert_block = i915_display_rpm_assert_block, 253 + .assert_unblock = i915_display_rpm_assert_unblock 254 + }; 180 255 181 256 /** 182 257 * intel_runtime_pm_get_raw - grab a raw runtime pm reference
+3
drivers/gpu/drm/i915/intel_runtime_pm.h
··· 14 14 struct device; 15 15 struct drm_i915_private; 16 16 struct drm_printer; 17 + struct intel_display_rpm_interface; 17 18 18 19 /* 19 20 * This struct helps tracking the state needed for runtime PM, which puts the ··· 226 225 { 227 226 } 228 227 #endif 228 + 229 + extern const struct intel_display_rpm_interface i915_display_rpm_interface; 229 230 230 231 #endif /* __INTEL_RUNTIME_PM_H__ */
+8 -7
drivers/gpu/drm/i915/intel_uncore.c
··· 35 35 #include "i915_reg.h" 36 36 #include "i915_vgpu.h" 37 37 #include "i915_wait_util.h" 38 + #include "i915_mmio_range.h" 38 39 #include "intel_uncore_trace.h" 39 40 40 41 #define FORCEWAKE_ACK_TIMEOUT_MS 50 ··· 1000 999 * scanned for obvious mistakes or typos by the selftests. 1001 1000 */ 1002 1001 1003 - static const struct i915_range gen8_shadowed_regs[] = { 1002 + static const struct i915_mmio_range gen8_shadowed_regs[] = { 1004 1003 { .start = 0x2030, .end = 0x2030 }, 1005 1004 { .start = 0xA008, .end = 0xA00C }, 1006 1005 { .start = 0x12030, .end = 0x12030 }, ··· 1008 1007 { .start = 0x22030, .end = 0x22030 }, 1009 1008 }; 1010 1009 1011 - static const struct i915_range gen11_shadowed_regs[] = { 1010 + static const struct i915_mmio_range gen11_shadowed_regs[] = { 1012 1011 { .start = 0x2030, .end = 0x2030 }, 1013 1012 { .start = 0x2550, .end = 0x2550 }, 1014 1013 { .start = 0xA008, .end = 0xA00C }, ··· 1035 1034 { .start = 0x1D8510, .end = 0x1D8550 }, 1036 1035 }; 1037 1036 1038 - static const struct i915_range gen12_shadowed_regs[] = { 1037 + static const struct i915_mmio_range gen12_shadowed_regs[] = { 1039 1038 { .start = 0x2030, .end = 0x2030 }, 1040 1039 { .start = 0x2510, .end = 0x2550 }, 1041 1040 { .start = 0xA008, .end = 0xA00C }, ··· 1079 1078 { .start = 0x1F8510, .end = 0x1F8550 }, 1080 1079 }; 1081 1080 1082 - static const struct i915_range dg2_shadowed_regs[] = { 1081 + static const struct i915_mmio_range dg2_shadowed_regs[] = { 1083 1082 { .start = 0x2030, .end = 0x2030 }, 1084 1083 { .start = 0x2510, .end = 0x2550 }, 1085 1084 { .start = 0xA008, .end = 0xA00C }, ··· 1118 1117 { .start = 0x1F8510, .end = 0x1F8550 }, 1119 1118 }; 1120 1119 1121 - static const struct i915_range mtl_shadowed_regs[] = { 1120 + static const struct i915_mmio_range mtl_shadowed_regs[] = { 1122 1121 { .start = 0x2030, .end = 0x2030 }, 1123 1122 { .start = 0x2510, .end = 0x2550 }, 1124 1123 { .start = 0xA008, .end = 0xA00C }, ··· 1136 1135 { .start = 0x22510, .end = 0x22550 }, 1137 1136 }; 1138 1137 1139 - static const struct i915_range xelpmp_shadowed_regs[] = { 1138 + static const struct i915_mmio_range xelpmp_shadowed_regs[] = { 1140 1139 { .start = 0x1C0030, .end = 0x1C0030 }, 1141 1140 { .start = 0x1C0510, .end = 0x1C0550 }, 1142 1141 { .start = 0x1C8030, .end = 0x1C8030 }, ··· 1157 1156 { .start = 0x38CFD4, .end = 0x38CFDC }, 1158 1157 }; 1159 1158 1160 - static int mmio_range_cmp(u32 key, const struct i915_range *range) 1159 + static int mmio_range_cmp(u32 key, const struct i915_mmio_range *range) 1161 1160 { 1162 1161 if (key < range->start) 1163 1162 return -1;
+1 -7
drivers/gpu/drm/i915/intel_uncore.h
··· 123 123 enum forcewake_domains domains; 124 124 }; 125 125 126 - /* Other register ranges (e.g., shadow tables, MCR tables, etc.) */ 127 - struct i915_range { 128 - u32 start; 129 - u32 end; 130 - }; 131 - 132 126 struct intel_uncore { 133 127 void __iomem *regs; 134 128 ··· 156 162 * Shadowed registers are special cases where we can safely write 157 163 * to the register *without* grabbing forcewake. 158 164 */ 159 - const struct i915_range *shadowed_reg_table; 165 + const struct i915_mmio_range *shadowed_reg_table; 160 166 unsigned int shadowed_reg_table_entries; 161 167 162 168 struct notifier_block pmic_bus_access_nb;
+1
drivers/gpu/drm/i915/selftests/i915_selftest.c
··· 30 30 31 31 #include "i915_driver.h" 32 32 #include "i915_drv.h" 33 + #include "i915_jiffies.h" 33 34 #include "i915_selftest.h" 34 35 #include "i915_wait_util.h" 35 36 #include "igt_flush_test.h"
+2 -2
drivers/gpu/drm/i915/selftests/intel_uncore.c
··· 64 64 static int intel_shadow_table_check(void) 65 65 { 66 66 struct { 67 - const struct i915_range *regs; 67 + const struct i915_mmio_range *regs; 68 68 unsigned int size; 69 69 } range_lists[] = { 70 70 { gen8_shadowed_regs, ARRAY_SIZE(gen8_shadowed_regs) }, ··· 74 74 { mtl_shadowed_regs, ARRAY_SIZE(mtl_shadowed_regs) }, 75 75 { xelpmp_shadowed_regs, ARRAY_SIZE(xelpmp_shadowed_regs) }, 76 76 }; 77 - const struct i915_range *range; 77 + const struct i915_mmio_range *range; 78 78 unsigned int i, j; 79 79 s32 prev; 80 80
+3 -1
drivers/gpu/drm/i915/selftests/mock_gem_device.c
··· 33 33 #include "gt/intel_gt.h" 34 34 #include "gt/intel_gt_requests.h" 35 35 #include "gt/mock_engine.h" 36 + #include "i915_driver.h" 36 37 #include "intel_memory_region.h" 37 38 #include "intel_region_ttm.h" 38 39 ··· 184 183 /* Set up device info and initial runtime info. */ 185 184 intel_device_info_driver_create(i915, pdev->device, &mock_info); 186 185 187 - display = intel_display_device_probe(pdev); 186 + /* FIXME: Can we run selftests using a mock device without display? */ 187 + display = intel_display_device_probe(pdev, i915_driver_parent_interface()); 188 188 if (IS_ERR(display)) 189 189 goto err_device; 190 190
+5 -5
drivers/gpu/drm/i915/soc/intel_dram.c
··· 335 335 skl_is_16gb_dimm(const struct dram_dimm_info *dimm) 336 336 { 337 337 /* Convert total Gb to Gb per DRAM device */ 338 - return dimm->size / (intel_dimm_num_devices(dimm) ?: 1) == 16; 338 + return dimm->size / (intel_dimm_num_devices(dimm) ?: 1) >= 16; 339 339 } 340 340 341 341 static void ··· 354 354 } 355 355 356 356 drm_dbg_kms(&i915->drm, 357 - "CH%u DIMM %c size: %u Gb, width: X%u, ranks: %u, 16Gb DIMMs: %s\n", 357 + "CH%u DIMM %c size: %u Gb, width: X%u, ranks: %u, 16Gb+ DIMMs: %s\n", 358 358 channel, dimm_name, dimm->size, dimm->width, dimm->ranks, 359 359 str_yes_no(skl_is_16gb_dimm(dimm))); 360 360 } ··· 384 384 ch->is_16gb_dimm = skl_is_16gb_dimm(&ch->dimm_l) || 385 385 skl_is_16gb_dimm(&ch->dimm_s); 386 386 387 - drm_dbg_kms(&i915->drm, "CH%u ranks: %u, 16Gb DIMMs: %s\n", 387 + drm_dbg_kms(&i915->drm, "CH%u ranks: %u, 16Gb+ DIMMs: %s\n", 388 388 channel, ch->ranks, str_yes_no(ch->is_16gb_dimm)); 389 389 390 390 return 0; ··· 406 406 u32 val; 407 407 int ret; 408 408 409 - /* Assume 16Gb DIMMs are present until proven otherwise */ 409 + /* Assume 16Gb+ DIMMs are present until proven otherwise */ 410 410 dram_info->has_16gb_dimms = true; 411 411 412 412 val = intel_uncore_read(&i915->uncore, ··· 438 438 drm_dbg_kms(&i915->drm, "Memory configuration is symmetric? %s\n", 439 439 str_yes_no(dram_info->symmetric_memory)); 440 440 441 - drm_dbg_kms(&i915->drm, "16Gb DIMMs: %s\n", 441 + drm_dbg_kms(&i915->drm, "16Gb+ DIMMs: %s\n", 442 442 str_yes_no(dram_info->has_16gb_dimms)); 443 443 444 444 return 0;
+7 -1
drivers/gpu/drm/xe/Makefile
··· 205 205 # Display code specific to xe 206 206 xe-$(CONFIG_DRM_XE_DISPLAY) += \ 207 207 display/ext/i915_irq.o \ 208 - display/ext/i915_utils.o \ 209 208 display/intel_bo.o \ 210 209 display/intel_fb_bo.o \ 211 210 display/intel_fbdev_fb.o \ ··· 217 218 display/xe_hdcp_gsc.o \ 218 219 display/xe_panic.o \ 219 220 display/xe_plane_initial.o \ 221 + display/xe_stolen.o \ 220 222 display/xe_tdf.o 221 223 222 224 # SOC code shared with i915 ··· 234 234 i915-display/intel_backlight.o \ 235 235 i915-display/intel_bios.o \ 236 236 i915-display/intel_bw.o \ 237 + i915-display/intel_casf.o \ 237 238 i915-display/intel_cdclk.o \ 238 239 i915-display/intel_cmtg.o \ 239 240 i915-display/intel_color.o \ ··· 244 243 i915-display/intel_crtc_state_dump.o \ 245 244 i915-display/intel_cursor.o \ 246 245 i915-display/intel_cx0_phy.o \ 246 + i915-display/intel_dbuf_bw.o \ 247 247 i915-display/intel_ddi.o \ 248 248 i915-display/intel_ddi_buf_trans.o \ 249 249 i915-display/intel_display.o \ ··· 256 254 i915-display/intel_display_power.o \ 257 255 i915-display/intel_display_power_map.o \ 258 256 i915-display/intel_display_power_well.o \ 257 + i915-display/intel_display_rpm.o \ 259 258 i915-display/intel_display_trace.o \ 259 + i915-display/intel_display_utils.o \ 260 260 i915-display/intel_display_wa.o \ 261 261 i915-display/intel_dkl_phy.o \ 262 262 i915-display/intel_dmc.o \ ··· 295 291 i915-display/intel_hti.o \ 296 292 i915-display/intel_link_bw.o \ 297 293 i915-display/intel_lspcon.o \ 294 + i915-display/intel_lt_phy.o \ 298 295 i915-display/intel_modeset_lock.o \ 299 296 i915-display/intel_modeset_setup.o \ 300 297 i915-display/intel_modeset_verify.o \ ··· 316 311 i915-display/intel_vga.o \ 317 312 i915-display/intel_vrr.o \ 318 313 i915-display/intel_wm.o \ 314 + i915-display/skl_prefill.o \ 319 315 i915-display/skl_scaler.o \ 320 316 i915-display/skl_universal_plane.o \ 321 317 i915-display/skl_watermark.o
+1 -3
drivers/gpu/drm/xe/compat-i915-headers/gem/i915_gem_object.h
··· 5 5 #define __I915_GEM_OBJECT_H__ 6 6 7 7 struct dma_fence; 8 - struct i915_sched_attr; 9 8 10 - static inline void i915_gem_fence_wait_priority(struct dma_fence *fence, 11 - const struct i915_sched_attr *attr) 9 + static inline void i915_gem_fence_wait_priority_display(struct dma_fence *fence) 12 10 { 13 11 } 14 12
+17 -62
drivers/gpu/drm/xe/compat-i915-headers/gem/i915_gem_stolen.h
··· 6 6 #ifndef _I915_GEM_STOLEN_H_ 7 7 #define _I915_GEM_STOLEN_H_ 8 8 9 - #include "xe_ttm_stolen_mgr.h" 10 - #include "xe_res_cursor.h" 11 - #include "xe_validation.h" 9 + #include <linux/types.h> 12 10 13 - struct xe_bo; 11 + struct drm_device; 12 + struct intel_stolen_node; 14 13 15 - struct i915_stolen_fb { 16 - struct xe_bo *bo; 17 - }; 14 + int i915_gem_stolen_insert_node_in_range(struct intel_stolen_node *node, u64 size, 15 + unsigned int align, u64 start, u64 end); 18 16 19 - static inline int i915_gem_stolen_insert_node_in_range(struct xe_device *xe, 20 - struct i915_stolen_fb *fb, 21 - u32 size, u32 align, 22 - u32 start, u32 end) 23 - { 24 - struct xe_bo *bo; 25 - int err = 0; 26 - u32 flags = XE_BO_FLAG_PINNED | XE_BO_FLAG_STOLEN; 17 + int i915_gem_stolen_insert_node(struct intel_stolen_node *node, u64 size, 18 + unsigned int align); 27 19 28 - if (start < SZ_4K) 29 - start = SZ_4K; 20 + void i915_gem_stolen_remove_node(struct intel_stolen_node *node); 30 21 31 - if (align) { 32 - size = ALIGN(size, align); 33 - start = ALIGN(start, align); 34 - } 22 + bool i915_gem_stolen_initialized(struct drm_device *drm); 35 23 36 - bo = xe_bo_create_pin_range_novm(xe, xe_device_get_root_tile(xe), 37 - size, start, end, ttm_bo_type_kernel, flags); 38 - if (IS_ERR(bo)) { 39 - err = PTR_ERR(bo); 40 - bo = NULL; 41 - return err; 42 - } 24 + bool i915_gem_stolen_node_allocated(const struct intel_stolen_node *node); 43 25 44 - fb->bo = bo; 26 + u32 i915_gem_stolen_node_offset(struct intel_stolen_node *node); 45 27 46 - return err; 47 - } 28 + u64 i915_gem_stolen_area_address(struct drm_device *drm); 48 29 49 - static inline int i915_gem_stolen_insert_node(struct xe_device *xe, 50 - struct i915_stolen_fb *fb, 51 - u32 size, u32 align) 52 - { 53 - /* Not used on xe */ 54 - BUG_ON(1); 55 - return -ENODEV; 56 - } 30 + u64 i915_gem_stolen_area_size(struct drm_device *drm); 57 31 58 - static inline void i915_gem_stolen_remove_node(struct xe_device *xe, 59 - struct i915_stolen_fb *fb) 60 - { 61 - xe_bo_unpin_map_no_vm(fb->bo); 62 - fb->bo = NULL; 63 - } 32 + u64 i915_gem_stolen_node_address(struct intel_stolen_node *node); 64 33 65 - #define i915_gem_stolen_initialized(xe) (!!ttm_manager_type(&(xe)->ttm, XE_PL_STOLEN)) 66 - #define i915_gem_stolen_node_allocated(fb) (!!((fb)->bo)) 34 + u64 i915_gem_stolen_node_size(const struct intel_stolen_node *node); 67 35 68 - static inline u32 i915_gem_stolen_node_offset(struct i915_stolen_fb *fb) 69 - { 70 - struct xe_res_cursor res; 36 + struct intel_stolen_node *i915_gem_stolen_node_alloc(struct drm_device *drm); 71 37 72 - xe_res_first(fb->bo->ttm.resource, 0, 4096, &res); 73 - return res.start; 74 - } 75 - 76 - /* Used for < gen4. These are not supported by Xe */ 77 - #define i915_gem_stolen_area_address(xe) (!WARN_ON(1)) 78 - /* Used for gen9 specific WA. Gen9 is not supported by Xe */ 79 - #define i915_gem_stolen_area_size(xe) (!WARN_ON(1)) 80 - 81 - #define i915_gem_stolen_node_address(xe, fb) (xe_ttm_stolen_gpu_offset(xe) + \ 82 - i915_gem_stolen_node_offset(fb)) 83 - #define i915_gem_stolen_node_size(fb) ((u64)((fb)->bo->ttm.base.size)) 38 + void i915_gem_stolen_node_free(const struct intel_stolen_node *node); 84 39 85 40 #endif
-4
drivers/gpu/drm/xe/compat-i915-headers/i915_drv.h
··· 12 12 13 13 #include <drm/drm_drv.h> 14 14 15 - #include "xe_device.h" /* for xe_device_has_flat_ccs() */ 16 15 #include "xe_device_types.h" 17 16 18 17 static inline struct drm_i915_private *to_i915(const struct drm_device *dev) ··· 33 34 #define IS_DG2(dev_priv) IS_PLATFORM(dev_priv, XE_DG2) 34 35 35 36 #define IS_MOBILE(xe) (xe && 0) 36 - 37 - #define HAS_FLAT_CCS(xe) (xe_device_has_flat_ccs(xe)) 38 - #define HAS_128_BYTE_Y_TILING(xe) (xe || 1) 39 37 40 38 #endif
-13
drivers/gpu/drm/xe/compat-i915-headers/i915_scheduler_types.h
··· 1 - /* SPDX-License-Identifier: MIT */ 2 - /* Copyright © 2025 Intel Corporation */ 3 - 4 - #ifndef __I915_SCHEDULER_TYPES_H__ 5 - #define __I915_SCHEDULER_TYPES_H__ 6 - 7 - #define I915_PRIORITY_DISPLAY 0 8 - 9 - struct i915_sched_attr { 10 - int priority; 11 - }; 12 - 13 - #endif
+8 -1
drivers/gpu/drm/xe/compat-i915-headers/i915_utils.h
··· 3 3 * Copyright © 2023 Intel Corporation 4 4 */ 5 5 6 - #include "../../i915/i915_utils.h" 6 + /* for soc/ */ 7 + #ifndef MISSING_CASE 8 + #define MISSING_CASE(x) WARN(1, "Missing case (%s == %ld)\n", \ 9 + __stringify(x), (long)(x)) 10 + #endif 11 + 12 + /* for a couple of users under i915/display */ 13 + #define i915_inject_probe_failure(unused) ((unused) && 0)
-27
drivers/gpu/drm/xe/display/ext/i915_utils.c
··· 1 - // SPDX-License-Identifier: MIT 2 - /* 3 - * Copyright © 2023 Intel Corporation 4 - */ 5 - 6 - #include "i915_drv.h" 7 - #include "i915_utils.h" 8 - 9 - bool i915_vtd_active(struct drm_i915_private *i915) 10 - { 11 - if (device_iommu_mapped(i915->drm.dev)) 12 - return true; 13 - 14 - /* Running as a guest, we assume the host is enforcing VT'd */ 15 - return i915_run_as_guest(); 16 - } 17 - 18 - #if IS_ENABLED(CONFIG_DRM_I915_DEBUG) 19 - 20 - /* i915 specific, just put here for shutting it up */ 21 - int __i915_inject_probe_error(struct drm_i915_private *i915, int err, 22 - const char *func, int line) 23 - { 24 - return 0; 25 - } 26 - 27 - #endif
+1 -2
drivers/gpu/drm/xe/display/intel_fb_bo.c
··· 24 24 xe_bo_put(bo); 25 25 } 26 26 27 - int intel_fb_bo_framebuffer_init(struct drm_framebuffer *fb, 28 - struct drm_gem_object *obj, 27 + int intel_fb_bo_framebuffer_init(struct drm_gem_object *obj, 29 28 struct drm_mode_fb_cmd2 *mode_cmd) 30 29 { 31 30 struct xe_bo *bo = gem_to_xe_bo(obj);
+23 -45
drivers/gpu/drm/xe/display/intel_fbdev_fb.c
··· 3 3 * Copyright © 2023 Intel Corporation 4 4 */ 5 5 6 - #include <drm/drm_fb_helper.h> 6 + #include <linux/fb.h> 7 7 8 - #include "intel_display_core.h" 9 - #include "intel_display_types.h" 10 - #include "intel_fb.h" 11 8 #include "intel_fbdev_fb.h" 12 9 #include "xe_bo.h" 13 10 #include "xe_ttm_stolen_mgr.h" ··· 12 15 13 16 #include <generated/xe_device_wa_oob.h> 14 17 15 - struct intel_framebuffer *intel_fbdev_fb_alloc(struct drm_fb_helper *helper, 16 - struct drm_fb_helper_surface_size *sizes) 18 + /* 19 + * FIXME: There shouldn't be any reason to have XE_PAGE_SIZE stride 20 + * alignment. The same 64 as i915 uses should be fine, and we shouldn't need to 21 + * have driver specific values. However, dropping the stride alignment to 64 22 + * leads to underflowing the bo pin count in the atomic cleanup work. 23 + */ 24 + u32 intel_fbdev_fb_pitch_align(u32 stride) 17 25 { 18 - struct drm_framebuffer *fb; 19 - struct drm_device *dev = helper->dev; 20 - struct xe_device *xe = to_xe_device(dev); 21 - struct drm_mode_fb_cmd2 mode_cmd = {}; 26 + return ALIGN(stride, XE_PAGE_SIZE); 27 + } 28 + 29 + struct drm_gem_object *intel_fbdev_fb_bo_create(struct drm_device *drm, int size) 30 + { 31 + struct xe_device *xe = to_xe_device(drm); 22 32 struct xe_bo *obj; 23 - int size; 24 33 25 - /* we don't do packed 24bpp */ 26 - if (sizes->surface_bpp == 24) 27 - sizes->surface_bpp = 32; 28 - 29 - mode_cmd.width = sizes->surface_width; 30 - mode_cmd.height = sizes->surface_height; 31 - 32 - mode_cmd.pitches[0] = ALIGN(mode_cmd.width * 33 - DIV_ROUND_UP(sizes->surface_bpp, 8), XE_PAGE_SIZE); 34 - mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, 35 - sizes->surface_depth); 36 - 37 - size = mode_cmd.pitches[0] * mode_cmd.height; 38 - size = PAGE_ALIGN(size); 39 34 obj = ERR_PTR(-ENODEV); 40 35 41 36 if (!IS_DGFX(xe) && !XE_DEVICE_WA(xe, 22019338487_display)) { ··· 51 62 52 63 if (IS_ERR(obj)) { 53 64 drm_err(&xe->drm, "failed to allocate framebuffer (%pe)\n", obj); 54 - fb = ERR_PTR(-ENOMEM); 55 - goto err; 65 + return ERR_PTR(-ENOMEM); 56 66 } 57 67 58 - fb = intel_framebuffer_create(&obj->ttm.base, 59 - drm_get_format_info(dev, 60 - mode_cmd.pixel_format, 61 - mode_cmd.modifier[0]), 62 - &mode_cmd); 63 - if (IS_ERR(fb)) { 64 - xe_bo_unpin_map_no_vm(obj); 65 - goto err; 66 - } 67 - 68 - drm_gem_object_put(&obj->ttm.base); 69 - 70 - return to_intel_framebuffer(fb); 71 - 72 - err: 73 - return ERR_CAST(fb); 68 + return &obj->ttm.base; 74 69 } 75 70 76 - int intel_fbdev_fb_fill_info(struct intel_display *display, struct fb_info *info, 71 + void intel_fbdev_fb_bo_destroy(struct drm_gem_object *obj) 72 + { 73 + xe_bo_unpin_map_no_vm(gem_to_xe_bo(obj)); 74 + } 75 + 76 + int intel_fbdev_fb_fill_info(struct drm_device *drm, struct fb_info *info, 77 77 struct drm_gem_object *_obj, struct i915_vma *vma) 78 78 { 79 79 struct xe_bo *obj = gem_to_xe_bo(_obj); 80 - struct pci_dev *pdev = to_pci_dev(display->drm->dev); 80 + struct pci_dev *pdev = to_pci_dev(drm->dev); 81 81 82 82 if (!(obj->flags & XE_BO_FLAG_SYSTEM)) { 83 83 if (obj->flags & XE_BO_FLAG_STOLEN)
+11 -1
drivers/gpu/drm/xe/display/xe_display.c
··· 13 13 #include <drm/drm_drv.h> 14 14 #include <drm/drm_managed.h> 15 15 #include <drm/drm_probe_helper.h> 16 + #include <drm/intel/display_member.h> 17 + #include <drm/intel/display_parent_interface.h> 16 18 #include <uapi/drm/xe_drm.h> 17 19 18 20 #include "soc/intel_dram.h" ··· 35 33 #include "intel_hotplug.h" 36 34 #include "intel_opregion.h" 37 35 #include "skl_watermark.h" 36 + #include "xe_display_rpm.h" 38 37 #include "xe_module.h" 38 + 39 + /* Ensure drm and display members are placed properly. */ 40 + INTEL_DISPLAY_MEMBER_STATIC_ASSERT(struct xe_device, drm, display); 39 41 40 42 /* Xe device functions */ 41 43 ··· 516 510 intel_display_device_remove(display); 517 511 } 518 512 513 + static const struct intel_display_parent_interface parent = { 514 + .rpm = &xe_display_rpm_interface, 515 + }; 516 + 519 517 /** 520 518 * xe_display_probe - probe display and create display struct 521 519 * @xe: XE device instance ··· 540 530 if (!xe->info.probe_display) 541 531 goto no_display; 542 532 543 - display = intel_display_device_probe(pdev); 533 + display = intel_display_device_probe(pdev, &parent); 544 534 if (IS_ERR(display)) 545 535 return PTR_ERR(display); 546 536
+31 -30
drivers/gpu/drm/xe/display/xe_display_rpm.c
··· 1 1 // SPDX-License-Identifier: MIT 2 2 /* Copyright © 2025 Intel Corporation */ 3 3 4 + #include <drm/intel/display_parent_interface.h> 5 + 4 6 #include "intel_display_core.h" 5 7 #include "intel_display_rpm.h" 6 8 #include "xe_device.h" 7 9 #include "xe_device_types.h" 8 10 #include "xe_pm.h" 9 11 10 - static struct xe_device *display_to_xe(struct intel_display *display) 12 + static struct ref_tracker *xe_display_rpm_get(const struct drm_device *drm) 11 13 { 12 - return to_xe_device(display->drm); 14 + return xe_pm_runtime_resume_and_get(to_xe_device(drm)) ? INTEL_WAKEREF_DEF : NULL; 13 15 } 14 16 15 - struct ref_tracker *intel_display_rpm_get_raw(struct intel_display *display) 17 + static struct ref_tracker *xe_display_rpm_get_if_in_use(const struct drm_device *drm) 16 18 { 17 - return intel_display_rpm_get(display); 19 + return xe_pm_runtime_get_if_in_use(to_xe_device(drm)) ? INTEL_WAKEREF_DEF : NULL; 18 20 } 19 21 20 - void intel_display_rpm_put_raw(struct intel_display *display, struct ref_tracker *wakeref) 22 + static struct ref_tracker *xe_display_rpm_get_noresume(const struct drm_device *drm) 21 23 { 22 - intel_display_rpm_put(display, wakeref); 23 - } 24 - 25 - struct ref_tracker *intel_display_rpm_get(struct intel_display *display) 26 - { 27 - return xe_pm_runtime_resume_and_get(display_to_xe(display)) ? INTEL_WAKEREF_DEF : NULL; 28 - } 29 - 30 - struct ref_tracker *intel_display_rpm_get_if_in_use(struct intel_display *display) 31 - { 32 - return xe_pm_runtime_get_if_in_use(display_to_xe(display)) ? INTEL_WAKEREF_DEF : NULL; 33 - } 34 - 35 - struct ref_tracker *intel_display_rpm_get_noresume(struct intel_display *display) 36 - { 37 - xe_pm_runtime_get_noresume(display_to_xe(display)); 24 + xe_pm_runtime_get_noresume(to_xe_device(drm)); 38 25 39 26 return INTEL_WAKEREF_DEF; 40 27 } 41 28 42 - void intel_display_rpm_put(struct intel_display *display, struct ref_tracker *wakeref) 29 + static void xe_display_rpm_put(const struct drm_device *drm, struct ref_tracker *wakeref) 43 30 { 44 31 if (wakeref) 45 - xe_pm_runtime_put(display_to_xe(display)); 32 + xe_pm_runtime_put(to_xe_device(drm)); 46 33 } 47 34 48 - void intel_display_rpm_put_unchecked(struct intel_display *display) 35 + static void xe_display_rpm_put_unchecked(const struct drm_device *drm) 49 36 { 50 - xe_pm_runtime_put(display_to_xe(display)); 37 + xe_pm_runtime_put(to_xe_device(drm)); 51 38 } 52 39 53 - bool intel_display_rpm_suspended(struct intel_display *display) 40 + static bool xe_display_rpm_suspended(const struct drm_device *drm) 54 41 { 55 - struct xe_device *xe = display_to_xe(display); 42 + struct xe_device *xe = to_xe_device(drm); 56 43 57 44 return pm_runtime_suspended(xe->drm.dev); 58 45 } 59 46 60 - void assert_display_rpm_held(struct intel_display *display) 47 + static void xe_display_rpm_assert_held(const struct drm_device *drm) 61 48 { 62 49 /* FIXME */ 63 50 } 64 51 65 - void intel_display_rpm_assert_block(struct intel_display *display) 52 + static void xe_display_rpm_assert_block(const struct drm_device *drm) 66 53 { 67 54 /* FIXME */ 68 55 } 69 56 70 - void intel_display_rpm_assert_unblock(struct intel_display *display) 57 + static void xe_display_rpm_assert_unblock(const struct drm_device *drm) 71 58 { 72 59 /* FIXME */ 73 60 } 61 + 62 + const struct intel_display_rpm_interface xe_display_rpm_interface = { 63 + .get = xe_display_rpm_get, 64 + .get_raw = xe_display_rpm_get, 65 + .get_if_in_use = xe_display_rpm_get_if_in_use, 66 + .get_noresume = xe_display_rpm_get_noresume, 67 + .put = xe_display_rpm_put, 68 + .put_raw = xe_display_rpm_put, 69 + .put_unchecked = xe_display_rpm_put_unchecked, 70 + .suspended = xe_display_rpm_suspended, 71 + .assert_held = xe_display_rpm_assert_held, 72 + .assert_block = xe_display_rpm_assert_block, 73 + .assert_unblock = xe_display_rpm_assert_unblock 74 + };
+11
drivers/gpu/drm/xe/display/xe_display_rpm.h
··· 1 + /* SPDX-License-Identifier: MIT */ 2 + /* 3 + * Copyright © 2025 Intel Corporation 4 + */ 5 + 6 + #ifndef _XE_DISPLAY_RPM_H_ 7 + #define _XE_DISPLAY_RPM_H_ 8 + 9 + extern const struct intel_display_rpm_interface xe_display_rpm_interface; 10 + 11 + #endif /* _XE_DISPLAY_RPM_H_ */
+123
drivers/gpu/drm/xe/display/xe_stolen.c
··· 1 + // SPDX-License-Identifier: MIT 2 + /* Copyright © 2025 Intel Corporation */ 3 + 4 + #include "gem/i915_gem_stolen.h" 5 + #include "xe_res_cursor.h" 6 + #include "xe_ttm_stolen_mgr.h" 7 + #include "xe_validation.h" 8 + 9 + struct intel_stolen_node { 10 + struct xe_device *xe; 11 + struct xe_bo *bo; 12 + }; 13 + 14 + int i915_gem_stolen_insert_node_in_range(struct intel_stolen_node *node, u64 size, 15 + unsigned int align, u64 start, u64 end) 16 + { 17 + struct xe_device *xe = node->xe; 18 + 19 + struct xe_bo *bo; 20 + int err = 0; 21 + u32 flags = XE_BO_FLAG_PINNED | XE_BO_FLAG_STOLEN; 22 + 23 + if (start < SZ_4K) 24 + start = SZ_4K; 25 + 26 + if (align) { 27 + size = ALIGN(size, align); 28 + start = ALIGN(start, align); 29 + } 30 + 31 + bo = xe_bo_create_pin_range_novm(xe, xe_device_get_root_tile(xe), 32 + size, start, end, ttm_bo_type_kernel, flags); 33 + if (IS_ERR(bo)) { 34 + err = PTR_ERR(bo); 35 + bo = NULL; 36 + return err; 37 + } 38 + 39 + node->bo = bo; 40 + 41 + return err; 42 + } 43 + 44 + int i915_gem_stolen_insert_node(struct intel_stolen_node *node, u64 size, unsigned int align) 45 + { 46 + /* Not used on xe */ 47 + WARN_ON(1); 48 + 49 + return -ENODEV; 50 + } 51 + 52 + void i915_gem_stolen_remove_node(struct intel_stolen_node *node) 53 + { 54 + xe_bo_unpin_map_no_vm(node->bo); 55 + node->bo = NULL; 56 + } 57 + 58 + bool i915_gem_stolen_initialized(struct drm_device *drm) 59 + { 60 + struct xe_device *xe = to_xe_device(drm); 61 + 62 + return ttm_manager_type(&xe->ttm, XE_PL_STOLEN); 63 + } 64 + 65 + bool i915_gem_stolen_node_allocated(const struct intel_stolen_node *node) 66 + { 67 + return node->bo; 68 + } 69 + 70 + u32 i915_gem_stolen_node_offset(struct intel_stolen_node *node) 71 + { 72 + struct xe_res_cursor res; 73 + 74 + xe_res_first(node->bo->ttm.resource, 0, 4096, &res); 75 + return res.start; 76 + } 77 + 78 + /* Used for < gen4. These are not supported by Xe */ 79 + u64 i915_gem_stolen_area_address(struct drm_device *drm) 80 + { 81 + WARN_ON(1); 82 + 83 + return 0; 84 + } 85 + 86 + /* Used for gen9 specific WA. Gen9 is not supported by Xe */ 87 + u64 i915_gem_stolen_area_size(struct drm_device *drm) 88 + { 89 + WARN_ON(1); 90 + 91 + return 0; 92 + } 93 + 94 + u64 i915_gem_stolen_node_address(struct intel_stolen_node *node) 95 + { 96 + struct xe_device *xe = node->xe; 97 + 98 + return xe_ttm_stolen_gpu_offset(xe) + i915_gem_stolen_node_offset(node); 99 + } 100 + 101 + u64 i915_gem_stolen_node_size(const struct intel_stolen_node *node) 102 + { 103 + return node->bo->ttm.base.size; 104 + } 105 + 106 + struct intel_stolen_node *i915_gem_stolen_node_alloc(struct drm_device *drm) 107 + { 108 + struct xe_device *xe = to_xe_device(drm); 109 + struct intel_stolen_node *node; 110 + 111 + node = kzalloc(sizeof(*node), GFP_KERNEL); 112 + if (!node) 113 + return NULL; 114 + 115 + node->xe = xe; 116 + 117 + return node; 118 + } 119 + 120 + void i915_gem_stolen_node_free(const struct intel_stolen_node *node) 121 + { 122 + kfree(node); 123 + }
+5 -11
drivers/gpu/drm/xe/xe_device_types.h
··· 228 228 /** @drm: drm device */ 229 229 struct drm_device drm; 230 230 231 + #if IS_ENABLED(CONFIG_DRM_XE_DISPLAY) 232 + /** @display: display device data, must be placed after drm device member */ 233 + struct intel_display *display; 234 + #endif 235 + 231 236 /** @devcoredump: device coredump */ 232 237 struct xe_devcoredump devcoredump; 233 238 ··· 637 632 * drm_i915_private during build. After cleanup these should go away, 638 633 * migrating to the right sub-structs 639 634 */ 640 - struct intel_display *display; 641 - 642 635 const struct dram_info *dram_info; 643 636 644 637 /* ··· 648 645 /* To shut up runtime pm macros.. */ 649 646 struct xe_runtime_pm {} runtime_pm; 650 647 651 - /* only to allow build, not used functionally */ 652 - u32 irq_mask; 653 - 654 648 struct intel_uncore { 655 649 spinlock_t lock; 656 650 } uncore; 657 - 658 - /* only to allow build, not used functionally */ 659 - struct { 660 - unsigned int hpll_freq; 661 - unsigned int czclk_freq; 662 - }; 663 651 #endif 664 652 }; 665 653
+1
drivers/gpu/drm/xe/xe_pci.c
··· 442 442 INTEL_PTL_IDS(INTEL_VGA_DEVICE, &ptl_desc), 443 443 INTEL_NVLS_IDS(INTEL_VGA_DEVICE, &nvls_desc), 444 444 INTEL_CRI_IDS(INTEL_PCI_DEVICE, &cri_desc), 445 + INTEL_WCL_IDS(INTEL_VGA_DEVICE, &ptl_desc), 445 446 { } 446 447 }; 447 448 MODULE_DEVICE_TABLE(pci, pciidlist);
+3
include/drm/display/drm_dp.h
··· 258 258 # define DP_DSC_RC_BUF_BLK_SIZE_4 0x1 259 259 # define DP_DSC_RC_BUF_BLK_SIZE_16 0x2 260 260 # define DP_DSC_RC_BUF_BLK_SIZE_64 0x3 261 + # define DP_DSC_THROUGHPUT_MODE_0_DELTA_SHIFT 3 /* DP 2.1a, in units of 2 MPixels/sec */ 262 + # define DP_DSC_THROUGHPUT_MODE_0_DELTA_MASK (0x1f << DP_DSC_THROUGHPUT_MODE_0_DELTA_SHIFT) 261 263 262 264 #define DP_DSC_RC_BUF_SIZE 0x063 263 265 ··· 1688 1686 #define DP_BRANCH_OUI_HEADER_SIZE 0xc 1689 1687 #define DP_RECEIVER_CAP_SIZE 0xf 1690 1688 #define DP_DSC_RECEIVER_CAP_SIZE 0x10 /* DSC Capabilities 0x60 through 0x6F */ 1689 + #define DP_DSC_BRANCH_CAP_SIZE 3 1691 1690 #define EDP_PSR_RECEIVER_CAP_SIZE 2 1692 1691 #define EDP_DISPLAY_CTL_CAP_SIZE 5 1693 1692 #define DP_LTTPR_COMMON_CAP_SIZE 8
+14
include/drm/display/drm_dp_helper.h
··· 211 211 u8 drm_dp_dsc_sink_line_buf_depth(const u8 dsc_dpcd[DP_DSC_RECEIVER_CAP_SIZE]); 212 212 int drm_dp_dsc_sink_supported_input_bpcs(const u8 dsc_dpc[DP_DSC_RECEIVER_CAP_SIZE], 213 213 u8 dsc_bpc[3]); 214 + int drm_dp_dsc_sink_max_slice_throughput(const u8 dsc_dpcd[DP_DSC_RECEIVER_CAP_SIZE], 215 + int peak_pixel_rate, bool is_rgb_yuv444); 216 + int drm_dp_dsc_branch_max_overall_throughput(const u8 dsc_branch_dpcd[DP_DSC_BRANCH_CAP_SIZE], 217 + bool is_rgb_yuv444); 218 + int drm_dp_dsc_branch_max_line_width(const u8 dsc_branch_dpcd[DP_DSC_BRANCH_CAP_SIZE]); 214 219 215 220 static inline bool 216 221 drm_dp_sink_supports_dsc(const u8 dsc_dpcd[DP_DSC_RECEIVER_CAP_SIZE]) ··· 833 828 * requires enabling DSC. 834 829 */ 835 830 DP_DPCD_QUIRK_HBLANK_EXPANSION_REQUIRES_DSC, 831 + /** 832 + * @DP_DPCD_QUIRK_DSC_THROUGHPUT_BPP_LIMIT: 833 + * 834 + * The device doesn't support DSC decompression at the maximum DSC 835 + * pixel throughput and compressed bpp it indicates via its DPCD DSC 836 + * capabilities. The compressed bpp must be limited above a device 837 + * specific DSC pixel throughput. 838 + */ 839 + DP_DPCD_QUIRK_DSC_THROUGHPUT_BPP_LIMIT, 836 840 }; 837 841 838 842 /**
+18
include/drm/drm_crtc.h
··· 318 318 enum drm_scaling_filter scaling_filter; 319 319 320 320 /** 321 + * @sharpness_strength: 322 + * 323 + * Used by the user to set the sharpness intensity. 324 + * The value ranges from 0-255. 325 + * Default value is 0 which disable the sharpness feature. 326 + * Any value greater than 0 enables sharpening with the 327 + * specified strength. 328 + */ 329 + u8 sharpness_strength; 330 + 331 + /** 321 332 * @event: 322 333 * 323 334 * Optional pointer to a DRM event to signal upon completion of the ··· 1100 1089 struct drm_property *scaling_filter_property; 1101 1090 1102 1091 /** 1092 + * @sharpness_strength_property: property to apply 1093 + * the intensity of the sharpness requested. 1094 + */ 1095 + struct drm_property *sharpness_strength_property; 1096 + 1097 + /** 1103 1098 * @state: 1104 1099 * 1105 1100 * Current atomic state for this CRTC. ··· 1341 1324 int drm_crtc_create_scaling_filter_property(struct drm_crtc *crtc, 1342 1325 unsigned int supported_filters); 1343 1326 bool drm_crtc_in_clone_mode(struct drm_crtc_state *crtc_state); 1327 + int drm_crtc_create_sharpness_strength_property(struct drm_crtc *crtc); 1344 1328 #endif /* __DRM_CRTC_H__ */
+42
include/drm/intel/display_member.h
··· 1 + /* SPDX-License-Identifier: MIT */ 2 + /* Copyright © 2025 Intel Corporation */ 3 + 4 + #ifndef __DRM_INTEL_DISPLAY_H__ 5 + #define __DRM_INTEL_DISPLAY_H__ 6 + 7 + #include <linux/build_bug.h> 8 + #include <linux/stddef.h> 9 + #include <linux/stringify.h> 10 + 11 + #include <drm/drm_device.h> 12 + 13 + struct intel_display; 14 + 15 + /* 16 + * A dummy device struct to define the relative offsets of drm and display 17 + * members. With the members identically placed in struct drm_i915_private and 18 + * struct xe_device, this allows figuring out the struct intel_display pointer 19 + * without the definition of either driver specific structure. 20 + */ 21 + struct __intel_generic_device { 22 + struct drm_device drm; 23 + struct intel_display *display; 24 + }; 25 + 26 + /** 27 + * INTEL_DISPLAY_MEMBER_STATIC_ASSERT() - ensure correct placing of drm and display members 28 + * @type: The struct to check 29 + * @drm_member: Name of the struct drm_device member 30 + * @display_member: Name of the struct intel_display * member. 31 + * 32 + * Use this static assert macro to ensure the struct drm_i915_private and struct 33 + * xe_device struct drm_device and struct intel_display * members are at the 34 + * same relative offsets. 35 + */ 36 + #define INTEL_DISPLAY_MEMBER_STATIC_ASSERT(type, drm_member, display_member) \ 37 + static_assert( \ 38 + offsetof(struct __intel_generic_device, display) - offsetof(struct __intel_generic_device, drm) == \ 39 + offsetof(type, display_member) - offsetof(type, drm_member), \ 40 + __stringify(type) " " __stringify(drm_member) " and " __stringify(display_member) " members at invalid offsets") 41 + 42 + #endif
+45
include/drm/intel/display_parent_interface.h
··· 1 + /* SPDX-License-Identifier: MIT */ 2 + /* Copyright © 2025 Intel Corporation x*/ 3 + 4 + #ifndef __DISPLAY_PARENT_INTERFACE_H__ 5 + #define __DISPLAY_PARENT_INTERFACE_H__ 6 + 7 + #include <linux/types.h> 8 + 9 + struct drm_device; 10 + struct ref_tracker; 11 + 12 + struct intel_display_rpm_interface { 13 + struct ref_tracker *(*get)(const struct drm_device *drm); 14 + struct ref_tracker *(*get_raw)(const struct drm_device *drm); 15 + struct ref_tracker *(*get_if_in_use)(const struct drm_device *drm); 16 + struct ref_tracker *(*get_noresume)(const struct drm_device *drm); 17 + 18 + void (*put)(const struct drm_device *drm, struct ref_tracker *wakeref); 19 + void (*put_raw)(const struct drm_device *drm, struct ref_tracker *wakeref); 20 + void (*put_unchecked)(const struct drm_device *drm); 21 + 22 + bool (*suspended)(const struct drm_device *drm); 23 + void (*assert_held)(const struct drm_device *drm); 24 + void (*assert_block)(const struct drm_device *drm); 25 + void (*assert_unblock)(const struct drm_device *drm); 26 + }; 27 + 28 + /** 29 + * struct intel_display_parent_interface - services parent driver provides to display 30 + * 31 + * The parent, or core, driver provides a pointer to this structure to display 32 + * driver when calling intel_display_device_probe(). The display driver uses it 33 + * to access services provided by the parent driver. The structure may contain 34 + * sub-struct pointers to group function pointers by functionality. 35 + * 36 + * All function and sub-struct pointers must be initialized and callable unless 37 + * explicitly marked as "optional" below. The display driver will only NULL 38 + * check the optional pointers. 39 + */ 40 + struct intel_display_parent_interface { 41 + /** @rpm: Runtime PM functions */ 42 + const struct intel_display_rpm_interface *rpm; 43 + }; 44 + 45 + #endif
+4 -1
include/drm/intel/pciids.h
··· 880 880 MACRO__(0xB08F, ## __VA_ARGS__), \ 881 881 MACRO__(0xB090, ## __VA_ARGS__), \ 882 882 MACRO__(0xB0A0, ## __VA_ARGS__), \ 883 - MACRO__(0xB0B0, ## __VA_ARGS__), \ 883 + MACRO__(0xB0B0, ## __VA_ARGS__) 884 + 885 + /* WCL */ 886 + #define INTEL_WCL_IDS(MACRO__, ...) \ 884 887 MACRO__(0xFD80, ## __VA_ARGS__), \ 885 888 MACRO__(0xFD81, ## __VA_ARGS__) 886 889