Merge tag 'drm-intel-next-2026-03-16' of https://gitlab.freedesktop.org/drm/i915/kernel into drm-next

[airlied: fixed conflict with xe tree]
drm/i915 feature pull for v7.1:

Features and functionality:
- C10/C20/LT PHY PLL divider verification (Mika)
- Use trans push mechanism to generate PSR frame change event on LNL+ (Jouni)
- Account for DSC bubble overhead for horizontal slices (Ankit, Chaitanya)

Refactoring and cleanups:
- Refactor DP DSC slice config computation (Imre)
- Use GVT versions of register helper macros for GVT MMIO table (Ankit)
- C10/C20/LT PHY PLL computation refactoring (Mika)
- VGA decode refactoring and related fixes/cleanups (Ville)
- Move DSB buffer buffer implementation to display parent interface (Jani)
- Move error interrupt capture to display irq snapshot (Jani)
- Move pcode calls to display parent interface (Jani)
- Reduce GVT dependency on display headers (Jani)
- Compute config and mode valid refactoring for DSC (Ankit)
- Stop using i915 core register headers in display (Uma)
- Refactor DPT, move i915 parts to display parent interface (Jani)
- Refactor gen2-4 overlay, move to display parent interface (Ville)
- Refactor masked field register macro helpers, move to shared headers (Jani)
- Convert a number of workaround checks to the new workaround framework (Luca)
- Refactor and move frontbuffer calls to display parent interface (Jani)
- Add VMA calls to display parent interface (Jani)
- Refactor stolen memory allocation decisions (Vinod, Ville)
- Clean up and unify workqueue usage (Marco Crivellari)
- Preparation for UHBR DP tunnels (Imre)
- Allow DSC passthrough modes during DP MST mode validation (Imre)
- Move framebuffer bo interface to display parent interface (Jani)

Fixes:
- Plenty of DP SST HPD IRQ handling fixes (Imre)
- DP AUX backlight and luminance control fixes (Suraj)
- Respect VBT pipe joiner disable for eDP (Ankit)
- Do not use CASF with joiner (Nemesa)
- Clear C10/C20 PHY response read and error bit to avoid PHY hangs (Suraj)
- Xe3p_LPD DMG clock gating, CDCLK, port sync workarounds (Suraj, Gustavo, Mitul)
- Fix GVT error path (Michał)
- Handle errors on DP DSC receiver cap reads (Suraj)
- DSS clock gating workaround on MTL+ to avoid DSC corruption (Mika)
- Skip state verification for LT PHY in TBT mode (Suraj)
- Fix NULL pointer dereference on suspend when uc firmware not loaded (Rahul Bukte)
- Fix an unlikely DMC state related NULL pointer dereference at probe (Imre)
- Handle error returns from vga_get_uninterruptible() (Simon Richter)
- Increase C10/C20/LT PHY timeouts to include SOC/OS turnaround (Arun)
- Fix BIOS FB vs. stolen memory size check (Ville)
- Fix LOBF to use computed guardband and set context latency (Ankit)
- Handle modeset WW mutex lock failures due to contention properly (Imre)
- Fix pipe BPP clamping due to HDR (Imre)
- Fix stale state usage in DSC state computation (Imre)
- Take HDCP 1.4 vs 2.x into account during link check (Suraj)
- Fix forced link retrain handling in MST HPD IRQ handler (Imre)
- Remove redundant warning on vcpi < 0 (Jonathan)

Core changes:
- iopoll: fix function parameter names in read_poll_timeout_atomic() (Randy Dunlap)

Merges:
- Backmerge drm-next for v7.0-rc1 (Jani)

Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Jani Nikula <jani.nikula@intel.com>
Link: https://patch.msgid.link/b14bb0f297b1750816cf5f342bde608e435655fa@intel.com
This commit is contained in:
Dave Airlie 2026-03-17 11:27:01 +10:00
commit d93f8ea0e5
218 changed files with 5636 additions and 3896 deletions

View File

@ -76,9 +76,13 @@ i915-$(CONFIG_PERF_EVENTS) += \
# core display adaptation
i915-y += \
i915_bo.o \
i915_display_pc8.o \
i915_dpt.o \
i915_dsb_buffer.o \
i915_hdcp_gsc.o \
i915_initial_plane.o \
i915_overlay.o \
i915_panic.o
# "Graphics Technology" (aka we talk to the gpu)
@ -270,13 +274,10 @@ i915-y += \
display/intel_dpll.o \
display/intel_dpll_mgr.o \
display/intel_dpt.o \
display/intel_dpt_common.o \
display/intel_dram.o \
display/intel_drrs.o \
display/intel_dsb.o \
display/intel_dsb_buffer.o \
display/intel_fb.o \
display/intel_fb_bo.o \
display/intel_fb_pin.o \
display/intel_fbc.o \
display/intel_fdi.o \

View File

@ -10,7 +10,6 @@
#include <drm/drm_print.h>
#include "g4x_dp.h"
#include "i915_reg.h"
#include "intel_audio.h"
#include "intel_backlight.h"
#include "intel_connector.h"

View File

@ -8,7 +8,6 @@
#include <drm/drm_print.h>
#include "g4x_hdmi.h"
#include "i915_reg.h"
#include "intel_atomic.h"
#include "intel_audio.h"
#include "intel_connector.h"

View File

@ -6,15 +6,15 @@
#include <linux/debugfs.h>
#include <drm/drm_print.h>
#include <drm/intel/intel_pcode_regs.h>
#include "hsw_ips.h"
#include "i915_reg.h"
#include "intel_color_regs.h"
#include "intel_de.h"
#include "intel_display_regs.h"
#include "intel_display_rpm.h"
#include "intel_display_types.h"
#include "intel_pcode.h"
#include "intel_parent.h"
static void hsw_ips_enable(const struct intel_crtc_state *crtc_state)
{
@ -39,8 +39,8 @@ static void hsw_ips_enable(const struct intel_crtc_state *crtc_state)
if (display->platform.broadwell) {
drm_WARN_ON(display->drm,
intel_pcode_write(display->drm, DISPLAY_IPS_CONTROL,
val | IPS_PCODE_CONTROL));
intel_parent_pcode_write(display, DISPLAY_IPS_CONTROL,
val | IPS_PCODE_CONTROL));
/*
* Quoting Art Runyan: "its not safe to expect any particular
* value in IPS_CTL bit 31 after enabling IPS through the
@ -72,7 +72,7 @@ bool hsw_ips_disable(const struct intel_crtc_state *crtc_state)
if (display->platform.broadwell) {
drm_WARN_ON(display->drm,
intel_pcode_write(display->drm, DISPLAY_IPS_CONTROL, 0));
intel_parent_pcode_write(display, DISPLAY_IPS_CONTROL, 0));
/*
* Wait for PCODE to finish disabling IPS. The BSpec specified
* 42ms timeout value leads to occasional timeouts so use 100ms

View File

@ -10,7 +10,6 @@
#include <drm/drm_fourcc.h>
#include <drm/drm_print.h>
#include "i915_reg.h"
#include "i9xx_plane.h"
#include "i9xx_plane_regs.h"
#include "intel_atomic.h"

View File

@ -6,8 +6,8 @@
#include <linux/iopoll.h>
#include <drm/drm_print.h>
#include <drm/intel/intel_gmd_misc_regs.h>
#include "i915_reg.h"
#include "i9xx_wm.h"
#include "i9xx_wm_regs.h"
#include "intel_atomic.h"
@ -182,8 +182,8 @@ static bool _intel_set_memory_cxsr(struct intel_display *display, bool enable)
intel_de_posting_read(display, DSPFW3(display));
} else if (display->platform.i945g || display->platform.i945gm) {
was_enabled = intel_de_read(display, FW_BLC_SELF) & FW_BLC_SELF_EN;
val = enable ? _MASKED_BIT_ENABLE(FW_BLC_SELF_EN) :
_MASKED_BIT_DISABLE(FW_BLC_SELF_EN);
val = enable ? REG_MASKED_FIELD_ENABLE(FW_BLC_SELF_EN) :
REG_MASKED_FIELD_DISABLE(FW_BLC_SELF_EN);
intel_de_write(display, FW_BLC_SELF, val);
intel_de_posting_read(display, FW_BLC_SELF);
} else if (display->platform.i915gm) {
@ -193,8 +193,8 @@ static bool _intel_set_memory_cxsr(struct intel_display *display, bool enable)
* FW_BLC_SELF. What's going on?
*/
was_enabled = intel_de_read(display, INSTPM) & INSTPM_SELF_EN;
val = enable ? _MASKED_BIT_ENABLE(INSTPM_SELF_EN) :
_MASKED_BIT_DISABLE(INSTPM_SELF_EN);
val = enable ? REG_MASKED_FIELD_ENABLE(INSTPM_SELF_EN) :
REG_MASKED_FIELD_DISABLE(INSTPM_SELF_EN);
intel_de_write(display, INSTPM, val);
intel_de_posting_read(display, INSTPM);
} else {

View File

@ -34,7 +34,6 @@
#include <drm/drm_print.h>
#include <drm/drm_probe_helper.h>
#include "i915_reg.h"
#include "icl_dsi.h"
#include "icl_dsi_regs.h"
#include "intel_atomic.h"
@ -1624,12 +1623,6 @@ static int gen11_dsi_dsc_compute_config(struct intel_encoder *encoder,
if (crtc_state->pipe_bpp < 8 * 3)
return -EINVAL;
/* FIXME: split only when necessary */
if (crtc_state->dsc.slice_count > 1)
crtc_state->dsc.num_streams = 2;
else
crtc_state->dsc.num_streams = 1;
/* FIXME: initialize from VBT */
vdsc_cfg->rc_model_size = DSC_RC_MODEL_SIZE_CONST;

View File

@ -15,6 +15,7 @@
#include "intel_dp_aux.h"
#include "intel_psr.h"
#include "intel_psr_regs.h"
#include "intel_vrr.h"
#define SILENCE_PERIOD_MIN_TIME 80
#define SILENCE_PERIOD_MAX_TIME 180
@ -43,12 +44,6 @@ bool intel_alpm_is_alpm_aux_less(struct intel_dp *intel_dp,
void intel_alpm_init(struct intel_dp *intel_dp)
{
u8 dpcd;
if (drm_dp_dpcd_readb(&intel_dp->aux, DP_RECEIVER_ALPM_CAP, &dpcd) < 0)
return;
intel_dp->alpm_dpcd = dpcd;
mutex_init(&intel_dp->alpm.lock);
}
@ -248,14 +243,87 @@ bool intel_alpm_compute_params(struct intel_dp *intel_dp,
return true;
}
int intel_alpm_lobf_min_guardband(struct intel_crtc_state *crtc_state)
{
struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
int first_sdp_position = adjusted_mode->crtc_vtotal -
adjusted_mode->crtc_vsync_start;
int waketime_in_lines;
/*
* #FIXME: Need to check if io_wake_lines or aux_less_wake_lines
* is applicable. Currently this information is not readily
* available in crtc_state, so max will suffice for now.
*/
waketime_in_lines = max(crtc_state->alpm_state.io_wake_lines,
crtc_state->alpm_state.aux_less_wake_lines);
if (!crtc_state->has_lobf)
return 0;
return first_sdp_position + waketime_in_lines + crtc_state->set_context_latency;
}
static bool intel_alpm_lobf_is_window1_sufficient(struct intel_crtc_state *crtc_state)
{
struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
int vblank = adjusted_mode->crtc_vtotal - adjusted_mode->crtc_vdisplay;
int window1;
/*
* LOBF must be disabled if the number of lines within Window 1 is not
* greater than ALPM_CTL[ALPM Entry Check]
*/
window1 = vblank - min(vblank,
crtc_state->vrr.guardband +
crtc_state->set_context_latency);
return window1 > crtc_state->alpm_state.check_entry_lines;
}
void intel_alpm_lobf_compute_config_late(struct intel_dp *intel_dp,
struct intel_crtc_state *crtc_state)
{
struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
int waketime_in_lines, first_sdp_position;
if (!crtc_state->has_lobf)
return;
if (!intel_alpm_lobf_is_window1_sufficient(crtc_state)) {
crtc_state->has_lobf = false;
return;
}
/*
* LOBF can only be enabled if the time from the start of the SCL+Guardband
* window to the position of the first SDP is greater than the time it takes
* to wake the main link.
*
* Position of first sdp : vsync_start
* start of scl + guardband : vtotal - (scl + guardband)
* time in lines to wake main link : waketime_in_lines
*
* Position of first sdp - start of (scl + guardband) > time in lines to wake main link
* vsync_start - (vtotal - (scl + guardband)) > waketime_in_lines
* vsync_start - vtotal + scl + guardband > waketime_in_lines
* scl + guardband > waketime_in_lines + (vtotal - vsync_start)
*/
first_sdp_position = adjusted_mode->crtc_vtotal - adjusted_mode->crtc_vsync_start;
if (intel_alpm_aux_less_wake_supported(intel_dp))
waketime_in_lines = crtc_state->alpm_state.io_wake_lines;
else
waketime_in_lines = crtc_state->alpm_state.aux_less_wake_lines;
crtc_state->has_lobf = (crtc_state->set_context_latency + crtc_state->vrr.guardband) >
(first_sdp_position + waketime_in_lines);
}
void intel_alpm_lobf_compute_config(struct intel_dp *intel_dp,
struct intel_crtc_state *crtc_state,
struct drm_connector_state *conn_state)
{
struct intel_display *display = to_intel_display(intel_dp);
struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
int waketime_in_lines, first_sdp_position;
int context_latency, guardband;
if (intel_dp->alpm.lobf_disable_debug) {
drm_dbg_kms(display->drm, "LOBF is disabled by debug flag\n");
@ -277,8 +345,8 @@ void intel_alpm_lobf_compute_config(struct intel_dp *intel_dp,
if (crtc_state->has_psr)
return;
if (crtc_state->vrr.vmin != crtc_state->vrr.vmax ||
crtc_state->vrr.vmin != crtc_state->vrr.flipline)
if (!intel_vrr_always_use_vrr_tg(display) ||
!intel_vrr_is_fixed_rr(crtc_state))
return;
if (!(intel_alpm_aux_wake_supported(intel_dp) ||
@ -288,17 +356,7 @@ void intel_alpm_lobf_compute_config(struct intel_dp *intel_dp,
if (!intel_alpm_compute_params(intel_dp, crtc_state))
return;
context_latency = adjusted_mode->crtc_vblank_start - adjusted_mode->crtc_vdisplay;
guardband = adjusted_mode->crtc_vtotal -
adjusted_mode->crtc_vdisplay - context_latency;
first_sdp_position = adjusted_mode->crtc_vtotal - adjusted_mode->crtc_vsync_start;
if (intel_alpm_aux_less_wake_supported(intel_dp))
waketime_in_lines = crtc_state->alpm_state.io_wake_lines;
else
waketime_in_lines = crtc_state->alpm_state.aux_less_wake_lines;
crtc_state->has_lobf = (context_latency + guardband) >
(first_sdp_position + waketime_in_lines);
crtc_state->has_lobf = true;
}
static void lnl_alpm_configure(struct intel_dp *intel_dp,
@ -388,25 +446,14 @@ void intel_alpm_port_configure(struct intel_dp *intel_dp,
intel_de_write(display, PORT_ALPM_LFPS_CTL(port), lfps_ctl_val);
}
void intel_alpm_pre_plane_update(struct intel_atomic_state *state,
struct intel_crtc *crtc)
void intel_alpm_lobf_disable(const struct intel_crtc_state *new_crtc_state)
{
struct intel_display *display = to_intel_display(state);
const struct intel_crtc_state *crtc_state =
intel_atomic_get_new_crtc_state(state, crtc);
const struct intel_crtc_state *old_crtc_state =
intel_atomic_get_old_crtc_state(state, crtc);
enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
struct intel_display *display = to_intel_display(new_crtc_state);
enum transcoder cpu_transcoder = new_crtc_state->cpu_transcoder;
struct intel_encoder *encoder;
if (DISPLAY_VER(display) < 20)
return;
if (crtc_state->has_lobf || crtc_state->has_lobf == old_crtc_state->has_lobf)
return;
for_each_intel_encoder_mask(display->drm, encoder,
crtc_state->uapi.encoder_mask) {
new_crtc_state->uapi.encoder_mask) {
struct intel_dp *intel_dp;
if (!intel_encoder_is_dp(encoder))
@ -417,12 +464,10 @@ void intel_alpm_pre_plane_update(struct intel_atomic_state *state,
if (!intel_dp_is_edp(intel_dp))
continue;
if (old_crtc_state->has_lobf) {
mutex_lock(&intel_dp->alpm.lock);
intel_de_write(display, ALPM_CTL(display, cpu_transcoder), 0);
drm_dbg_kms(display->drm, "Link off between frames (LOBF) disabled\n");
mutex_unlock(&intel_dp->alpm.lock);
}
mutex_lock(&intel_dp->alpm.lock);
intel_de_write(display, ALPM_CTL(display, cpu_transcoder), 0);
drm_dbg_kms(display->drm, "Link off between frames (LOBF) disabled\n");
mutex_unlock(&intel_dp->alpm.lock);
}
}
@ -443,22 +488,13 @@ void intel_alpm_enable_sink(struct intel_dp *intel_dp,
drm_dp_dpcd_writeb(&intel_dp->aux, DP_RECEIVER_ALPM_CONFIG, val);
}
void intel_alpm_post_plane_update(struct intel_atomic_state *state,
struct intel_crtc *crtc)
void intel_alpm_lobf_enable(const struct intel_crtc_state *new_crtc_state)
{
struct intel_display *display = to_intel_display(state);
const struct intel_crtc_state *crtc_state =
intel_atomic_get_new_crtc_state(state, crtc);
const struct intel_crtc_state *old_crtc_state =
intel_atomic_get_old_crtc_state(state, crtc);
struct intel_display *display = to_intel_display(new_crtc_state);
struct intel_encoder *encoder;
if (crtc_state->has_psr || !crtc_state->has_lobf ||
crtc_state->has_lobf == old_crtc_state->has_lobf)
return;
for_each_intel_encoder_mask(display->drm, encoder,
crtc_state->uapi.encoder_mask) {
new_crtc_state->uapi.encoder_mask) {
struct intel_dp *intel_dp;
if (!intel_encoder_is_dp(encoder))
@ -467,8 +503,8 @@ void intel_alpm_post_plane_update(struct intel_atomic_state *state,
intel_dp = enc_to_intel_dp(encoder);
if (intel_dp_is_edp(intel_dp)) {
intel_alpm_enable_sink(intel_dp, crtc_state);
intel_alpm_configure(intel_dp, crtc_state);
intel_alpm_enable_sink(intel_dp, new_crtc_state);
intel_alpm_configure(intel_dp, new_crtc_state);
}
}
}

View File

@ -25,12 +25,10 @@ void intel_alpm_configure(struct intel_dp *intel_dp,
const struct intel_crtc_state *crtc_state);
void intel_alpm_enable_sink(struct intel_dp *intel_dp,
const struct intel_crtc_state *crtc_state);
void intel_alpm_pre_plane_update(struct intel_atomic_state *state,
struct intel_crtc *crtc);
void intel_alpm_lobf_disable(const struct intel_crtc_state *new_crtc_state);
void intel_alpm_port_configure(struct intel_dp *intel_dp,
const struct intel_crtc_state *crtc_state);
void intel_alpm_post_plane_update(struct intel_atomic_state *state,
struct intel_crtc *crtc);
void intel_alpm_lobf_enable(const struct intel_crtc_state *new_crtc_state);
void intel_alpm_lobf_debugfs_add(struct intel_connector *connector);
bool intel_alpm_aux_wake_supported(struct intel_dp *intel_dp);
bool intel_alpm_aux_less_wake_supported(struct intel_dp *intel_dp);
@ -38,4 +36,7 @@ bool intel_alpm_is_alpm_aux_less(struct intel_dp *intel_dp,
const struct intel_crtc_state *crtc_state);
void intel_alpm_disable(struct intel_dp *intel_dp);
bool intel_alpm_get_error(struct intel_dp *intel_dp);
void intel_alpm_lobf_compute_config_late(struct intel_dp *intel_dp,
struct intel_crtc_state *crtc_state);
int intel_alpm_lobf_min_guardband(struct intel_crtc_state *crtc_state);
#endif

View File

@ -37,6 +37,7 @@
#include "intel_crtc.h"
#include "intel_de.h"
#include "intel_display_types.h"
#include "intel_display_wa.h"
#include "intel_lpe_audio.h"
/**
@ -184,17 +185,6 @@ static const struct hdmi_aud_ncts hdmi_aud_ncts_36bpp[] = {
{ 192000, TMDS_445_5M, 20480, 371250 },
};
/*
* WA_14020863754: Implement Audio Workaround
* Corner case with Min Hblank Fix can cause audio hang
*/
static bool needs_wa_14020863754(struct intel_display *display)
{
return DISPLAY_VERx100(display) == 3000 ||
DISPLAY_VERx100(display) == 2000 ||
DISPLAY_VERx100(display) == 1401;
}
/* get AUD_CONFIG_PIXEL_CLOCK_HDMI_* value for mode */
static u32 audio_config_hdmi_pixel_clock(const struct intel_crtc_state *crtc_state)
{
@ -440,7 +430,11 @@ static void hsw_audio_codec_disable(struct intel_encoder *encoder,
intel_de_rmw(display, HSW_AUD_PIN_ELD_CP_VLD,
AUDIO_OUTPUT_ENABLE(cpu_transcoder), 0);
if (needs_wa_14020863754(display))
/*
* WA_14020863754: Implement Audio Workaround
* Corner case with Min Hblank Fix can cause audio hang
*/
if (intel_display_wa(display, INTEL_DISPLAY_WA_14020863754))
intel_de_rmw(display, AUD_CHICKENBIT_REG3, DACBE_DISABLE_MIN_HBLANK_FIX, 0);
intel_audio_sdp_split_update(old_crtc_state, false);
@ -572,7 +566,11 @@ static void hsw_audio_codec_enable(struct intel_encoder *encoder,
intel_audio_sdp_split_update(crtc_state, true);
if (needs_wa_14020863754(display))
/*
* WA_14020863754: Implement Audio Workaround
* Corner case with Min Hblank Fix can cause audio hang
*/
if (intel_display_wa(display, INTEL_DISPLAY_WA_14020863754))
intel_de_rmw(display, AUD_CHICKENBIT_REG3, 0, DACBE_DISABLE_MIN_HBLANK_FIX);
/* Enable audio presence detect */

View File

@ -12,7 +12,6 @@
#include <drm/drm_file.h>
#include <drm/drm_print.h>
#include "i915_reg.h"
#include "intel_backlight.h"
#include "intel_backlight_regs.h"
#include "intel_connector.h"

View File

@ -41,6 +41,7 @@
#include "intel_display_utils.h"
#include "intel_gmbus.h"
#include "intel_rom.h"
#include "intel_vdsc.h"
#define _INTEL_BIOS_PRIVATE
#include "intel_vbt_defs.h"
@ -1545,6 +1546,10 @@ parse_edp(struct intel_display *display,
if (display->vbt.version >= 251)
panel->vbt.edp.dsc_disable =
panel_bool(edp->edp_dsc_disable, panel_type);
if (display->vbt.version >= 261)
panel->vbt.edp.pipe_joiner_enable =
panel_bool(edp->pipe_joiner_enable, panel_type);
}
static void
@ -3543,12 +3548,13 @@ bool intel_bios_is_dsi_present(struct intel_display *display,
return false;
}
static void fill_dsc(struct intel_crtc_state *crtc_state,
static bool fill_dsc(struct intel_crtc_state *crtc_state,
struct dsc_compression_parameters_entry *dsc,
int dsc_max_bpc)
{
struct intel_display *display = to_intel_display(crtc_state);
struct drm_dsc_config *vdsc_cfg = &crtc_state->dsc.config;
int slices_per_line;
int bpc = 8;
vdsc_cfg->dsc_version_major = dsc->version_major;
@ -3574,26 +3580,33 @@ static void fill_dsc(struct intel_crtc_state *crtc_state,
* throughput etc. into account.
*
* Also, per spec DSI supports 1, 2, 3 or 4 horizontal slices.
*
* FIXME: split only when necessary
*/
if (dsc->slices_per_line & BIT(2)) {
crtc_state->dsc.slice_count = 4;
slices_per_line = 4;
} else if (dsc->slices_per_line & BIT(1)) {
crtc_state->dsc.slice_count = 2;
slices_per_line = 2;
} else {
/* FIXME */
if (!(dsc->slices_per_line & BIT(0)))
drm_dbg_kms(display->drm,
"VBT: Unsupported DSC slice count for DSI\n");
crtc_state->dsc.slice_count = 1;
slices_per_line = 1;
}
if (drm_WARN_ON(display->drm,
!intel_dsc_get_slice_config(display, 1, slices_per_line,
&crtc_state->dsc.slice_config)))
return false;
if (crtc_state->hw.adjusted_mode.crtc_hdisplay %
crtc_state->dsc.slice_count != 0)
intel_dsc_line_slice_count(&crtc_state->dsc.slice_config) != 0)
drm_dbg_kms(display->drm,
"VBT: DSC hdisplay %d not divisible by slice count %d\n",
crtc_state->hw.adjusted_mode.crtc_hdisplay,
crtc_state->dsc.slice_count);
intel_dsc_line_slice_count(&crtc_state->dsc.slice_config));
/*
* The VBT rc_buffer_block_size and rc_buffer_size definitions
@ -3608,6 +3621,8 @@ static void fill_dsc(struct intel_crtc_state *crtc_state,
vdsc_cfg->block_pred_enable = dsc->block_prediction_enable;
vdsc_cfg->slice_height = dsc->slice_height;
return true;
}
/* FIXME: initially DSI specific */
@ -3628,9 +3643,7 @@ bool intel_bios_get_dsc_params(struct intel_encoder *encoder,
if (!devdata->dsc)
return false;
fill_dsc(crtc_state, devdata->dsc, dsc_max_bpc);
return true;
return fill_dsc(crtc_state, devdata->dsc, dsc_max_bpc);
}
}

View File

@ -1,87 +1,87 @@
// SPDX-License-Identifier: MIT
/* Copyright © 2024 Intel Corporation */
/* Copyright © 2026 Intel Corporation */
#include <drm/drm_panic.h>
#include <drm/drm_gem.h>
#include <drm/intel/display_parent_interface.h>
#include "gem/i915_gem_mman.h"
#include "gem/i915_gem_object.h"
#include "gem/i915_gem_object_frontbuffer.h"
#include "pxp/intel_pxp.h"
#include "i915_debugfs.h"
#include "intel_bo.h"
#include "intel_display_core.h"
#include "intel_display_types.h"
bool intel_bo_is_tiled(struct drm_gem_object *obj)
{
return i915_gem_object_is_tiled(to_intel_bo(obj));
struct intel_display *display = to_intel_display(obj->dev);
return display->parent->bo->is_tiled && display->parent->bo->is_tiled(obj);
}
bool intel_bo_is_userptr(struct drm_gem_object *obj)
{
return i915_gem_object_is_userptr(to_intel_bo(obj));
struct intel_display *display = to_intel_display(obj->dev);
return display->parent->bo->is_userptr && display->parent->bo->is_userptr(obj);
}
bool intel_bo_is_shmem(struct drm_gem_object *obj)
{
return i915_gem_object_is_shmem(to_intel_bo(obj));
struct intel_display *display = to_intel_display(obj->dev);
return display->parent->bo->is_shmem && display->parent->bo->is_shmem(obj);
}
bool intel_bo_is_protected(struct drm_gem_object *obj)
{
return i915_gem_object_is_protected(to_intel_bo(obj));
struct intel_display *display = to_intel_display(obj->dev);
return display->parent->bo->is_protected(obj);
}
int intel_bo_key_check(struct drm_gem_object *obj)
{
return intel_pxp_key_check(obj, false);
struct intel_display *display = to_intel_display(obj->dev);
return display->parent->bo->key_check(obj);
}
int intel_bo_fb_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma)
{
return i915_gem_fb_mmap(to_intel_bo(obj), vma);
struct intel_display *display = to_intel_display(obj->dev);
return display->parent->bo->fb_mmap(obj, vma);
}
int intel_bo_read_from_page(struct drm_gem_object *obj, u64 offset, void *dst, int size)
{
return i915_gem_object_read_from_page(to_intel_bo(obj), offset, dst, size);
}
struct intel_display *display = to_intel_display(obj->dev);
struct intel_frontbuffer *intel_bo_frontbuffer_get(struct drm_gem_object *_obj)
{
struct drm_i915_gem_object *obj = to_intel_bo(_obj);
struct i915_frontbuffer *front;
front = i915_gem_object_frontbuffer_get(obj);
if (!front)
return NULL;
return &front->base;
}
void intel_bo_frontbuffer_ref(struct intel_frontbuffer *_front)
{
struct i915_frontbuffer *front =
container_of(_front, typeof(*front), base);
i915_gem_object_frontbuffer_ref(front);
}
void intel_bo_frontbuffer_put(struct intel_frontbuffer *_front)
{
struct i915_frontbuffer *front =
container_of(_front, typeof(*front), base);
return i915_gem_object_frontbuffer_put(front);
}
void intel_bo_frontbuffer_flush_for_display(struct intel_frontbuffer *_front)
{
struct i915_frontbuffer *front =
container_of(_front, typeof(*front), base);
i915_gem_object_flush_if_display(front->obj);
return display->parent->bo->read_from_page(obj, offset, dst, size);
}
void intel_bo_describe(struct seq_file *m, struct drm_gem_object *obj)
{
i915_debugfs_describe_obj(m, to_intel_bo(obj));
struct intel_display *display = to_intel_display(obj->dev);
if (display->parent->bo->describe)
display->parent->bo->describe(m, obj);
}
int intel_bo_framebuffer_init(struct drm_gem_object *obj, struct drm_mode_fb_cmd2 *mode_cmd)
{
struct intel_display *display = to_intel_display(obj->dev);
return display->parent->bo->framebuffer_init(obj, mode_cmd);
}
void intel_bo_framebuffer_fini(struct drm_gem_object *obj)
{
struct intel_display *display = to_intel_display(obj->dev);
display->parent->bo->framebuffer_fini(obj);
}
struct drm_gem_object *intel_bo_framebuffer_lookup(struct intel_display *display,
struct drm_file *filp,
const struct drm_mode_fb_cmd2 *user_mode_cmd)
{
return display->parent->bo->framebuffer_lookup(display->drm, filp, user_mode_cmd);
}

View File

@ -6,8 +6,11 @@
#include <linux/types.h>
struct drm_file;
struct drm_gem_object;
struct drm_mode_fb_cmd2;
struct drm_scanout_buffer;
struct intel_display;
struct intel_framebuffer;
struct seq_file;
struct vm_area_struct;
@ -20,11 +23,12 @@ int intel_bo_key_check(struct drm_gem_object *obj);
int intel_bo_fb_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma);
int intel_bo_read_from_page(struct drm_gem_object *obj, u64 offset, void *dst, int size);
struct intel_frontbuffer *intel_bo_frontbuffer_get(struct drm_gem_object *obj);
void intel_bo_frontbuffer_ref(struct intel_frontbuffer *front);
void intel_bo_frontbuffer_put(struct intel_frontbuffer *front);
void intel_bo_frontbuffer_flush_for_display(struct intel_frontbuffer *front);
void intel_bo_describe(struct seq_file *m, struct drm_gem_object *obj);
void intel_bo_framebuffer_fini(struct drm_gem_object *obj);
int intel_bo_framebuffer_init(struct drm_gem_object *obj, struct drm_mode_fb_cmd2 *mode_cmd);
struct drm_gem_object *intel_bo_framebuffer_lookup(struct intel_display *display,
struct drm_file *filp,
const struct drm_mode_fb_cmd2 *user_mode_cmd);
#endif /* __INTEL_BO__ */

View File

@ -5,8 +5,8 @@
#include <drm/drm_atomic_state_helper.h>
#include <drm/drm_print.h>
#include <drm/intel/intel_pcode_regs.h>
#include "i915_reg.h"
#include "intel_bw.h"
#include "intel_crtc.h"
#include "intel_display_core.h"
@ -15,7 +15,7 @@
#include "intel_display_utils.h"
#include "intel_dram.h"
#include "intel_mchbar_regs.h"
#include "intel_pcode.h"
#include "intel_parent.h"
#include "intel_uncore.h"
#include "skl_watermark.h"
@ -114,9 +114,9 @@ static int icl_pcode_read_qgv_point_info(struct intel_display *display,
u16 dclk;
int ret;
ret = intel_pcode_read(display->drm, ICL_PCODE_MEM_SUBSYSYSTEM_INFO |
ICL_PCODE_MEM_SS_READ_QGV_POINT_INFO(point),
&val, &val2);
ret = intel_parent_pcode_read(display, ICL_PCODE_MEM_SUBSYSYSTEM_INFO |
ICL_PCODE_MEM_SS_READ_QGV_POINT_INFO(point),
&val, &val2);
if (ret)
return ret;
@ -141,8 +141,8 @@ static int adls_pcode_read_psf_gv_point_info(struct intel_display *display,
int ret;
int i;
ret = intel_pcode_read(display->drm, ICL_PCODE_MEM_SUBSYSYSTEM_INFO |
ADL_PCODE_MEM_SS_READ_PSF_GV_INFO, &val, NULL);
ret = intel_parent_pcode_read(display, ICL_PCODE_MEM_SUBSYSYSTEM_INFO |
ADL_PCODE_MEM_SS_READ_PSF_GV_INFO, &val, NULL);
if (ret)
return ret;
@ -189,11 +189,11 @@ static int icl_pcode_restrict_qgv_points(struct intel_display *display,
return 0;
/* bspec says to keep retrying for at least 1 ms */
ret = intel_pcode_request(display->drm, ICL_PCODE_SAGV_DE_MEM_SS_CONFIG,
points_mask,
ICL_PCODE_REP_QGV_MASK | ADLS_PCODE_REP_PSF_MASK,
ICL_PCODE_REP_QGV_SAFE | ADLS_PCODE_REP_PSF_SAFE,
1);
ret = intel_parent_pcode_request(display, ICL_PCODE_SAGV_DE_MEM_SS_CONFIG,
points_mask,
ICL_PCODE_REP_QGV_MASK | ADLS_PCODE_REP_PSF_MASK,
ICL_PCODE_REP_QGV_SAFE | ADLS_PCODE_REP_PSF_SAFE,
1);
if (ret < 0) {
drm_err(display->drm,

View File

@ -3,7 +3,6 @@
#include <drm/drm_print.h>
#include "i915_reg.h"
#include "intel_casf.h"
#include "intel_casf_regs.h"
#include "intel_de.h"
@ -116,6 +115,12 @@ int intel_casf_compute_config(struct intel_crtc_state *crtc_state)
return 0;
}
/* CASF with joiner not supported in hardware */
if (crtc_state->joiner_pipes) {
drm_dbg_kms(display->drm, "CASF not supported with joiner\n");
return -EINVAL;
}
crtc_state->hw.casf_params.casf_enable = true;
/*

View File

@ -27,9 +27,9 @@
#include <drm/drm_fixed.h>
#include <drm/drm_print.h>
#include <drm/intel/intel_pcode_regs.h>
#include "hsw_ips.h"
#include "i915_reg.h"
#include "intel_atomic.h"
#include "intel_audio.h"
#include "intel_cdclk.h"
@ -42,8 +42,8 @@
#include "intel_display_wa.h"
#include "intel_dram.h"
#include "intel_mchbar_regs.h"
#include "intel_parent.h"
#include "intel_pci_config.h"
#include "intel_pcode.h"
#include "intel_plane.h"
#include "intel_psr.h"
#include "intel_step.h"
@ -888,7 +888,7 @@ static void bdw_set_cdclk(struct intel_display *display,
"trying to change cdclk frequency with cdclk not enabled\n"))
return;
ret = intel_pcode_write(display->drm, BDW_PCODE_DISPLAY_FREQ_CHANGE_REQ, 0x0);
ret = intel_parent_pcode_write(display, BDW_PCODE_DISPLAY_FREQ_CHANGE_REQ, 0x0);
if (ret) {
drm_err(display->drm,
"failed to inform pcode about cdclk change\n");
@ -918,8 +918,8 @@ static void bdw_set_cdclk(struct intel_display *display,
if (ret)
drm_err(display->drm, "Switching back to LCPLL failed\n");
intel_pcode_write(display->drm, HSW_PCODE_DE_WRITE_FREQ_REQ,
cdclk_config->voltage_level);
intel_parent_pcode_write(display, HSW_PCODE_DE_WRITE_FREQ_REQ,
cdclk_config->voltage_level);
intel_de_write(display, CDCLK_FREQ,
DIV_ROUND_CLOSEST(cdclk, 1000) - 1);
@ -1175,10 +1175,10 @@ static void skl_set_cdclk(struct intel_display *display,
drm_WARN_ON_ONCE(display->drm,
display->platform.skylake && vco == 8640000);
ret = intel_pcode_request(display->drm, SKL_PCODE_CDCLK_CONTROL,
SKL_CDCLK_PREPARE_FOR_CHANGE,
SKL_CDCLK_READY_FOR_CHANGE,
SKL_CDCLK_READY_FOR_CHANGE, 3);
ret = intel_parent_pcode_request(display, SKL_PCODE_CDCLK_CONTROL,
SKL_CDCLK_PREPARE_FOR_CHANGE,
SKL_CDCLK_READY_FOR_CHANGE,
SKL_CDCLK_READY_FOR_CHANGE, 3);
if (ret) {
drm_err(display->drm,
"Failed to inform PCU about cdclk change (%d)\n", ret);
@ -1221,8 +1221,8 @@ static void skl_set_cdclk(struct intel_display *display,
intel_de_posting_read(display, CDCLK_CTL);
/* inform PCU of the change */
intel_pcode_write(display->drm, SKL_PCODE_CDCLK_CONTROL,
cdclk_config->voltage_level);
intel_parent_pcode_write(display, SKL_PCODE_CDCLK_CONTROL,
cdclk_config->voltage_level);
intel_update_cdclk(display);
}
@ -1870,7 +1870,7 @@ static void icl_cdclk_pll_disable(struct intel_display *display)
* after the PLL is enabled (which is already done as part of the
* normal flow of _bxt_set_cdclk()).
*/
if (intel_display_wa(display, 13012396614))
if (intel_display_wa(display, INTEL_DISPLAY_WA_13012396614))
intel_de_rmw(display, CDCLK_CTL, MDCLK_SOURCE_SEL_MASK, MDCLK_SOURCE_SEL_CD2XCLK);
intel_de_rmw(display, BXT_DE_PLL_ENABLE,
@ -2186,7 +2186,8 @@ static u32 bxt_cdclk_ctl(struct intel_display *display,
* icl_cdclk_pll_disable(). Here we are just making sure
* we keep the expected value.
*/
if (intel_display_wa(display, 13012396614) && vco == 0)
if (intel_display_wa(display, INTEL_DISPLAY_WA_13012396614) &&
vco == 0)
val |= MDCLK_SOURCE_SEL_CD2XCLK;
else
val |= xe2lpd_mdclk_source_sel(display);
@ -2247,18 +2248,18 @@ static void bxt_set_cdclk(struct intel_display *display,
if (DISPLAY_VER(display) >= 14 || display->platform.dg2)
; /* NOOP */
else if (DISPLAY_VER(display) >= 11)
ret = intel_pcode_request(display->drm, SKL_PCODE_CDCLK_CONTROL,
SKL_CDCLK_PREPARE_FOR_CHANGE,
SKL_CDCLK_READY_FOR_CHANGE,
SKL_CDCLK_READY_FOR_CHANGE, 3);
ret = intel_parent_pcode_request(display, SKL_PCODE_CDCLK_CONTROL,
SKL_CDCLK_PREPARE_FOR_CHANGE,
SKL_CDCLK_READY_FOR_CHANGE,
SKL_CDCLK_READY_FOR_CHANGE, 3);
else
/*
* BSpec requires us to wait up to 150usec, but that leads to
* timeouts; the 2ms used here is based on experiment.
*/
ret = intel_pcode_write_timeout(display->drm,
HSW_PCODE_DE_WRITE_FREQ_REQ,
0x80000000, 2);
ret = intel_parent_pcode_write_timeout(display,
HSW_PCODE_DE_WRITE_FREQ_REQ,
0x80000000, 2);
if (ret) {
drm_err(display->drm,
@ -2287,8 +2288,8 @@ static void bxt_set_cdclk(struct intel_display *display,
* Display versions 14 and beyond
*/;
else if (DISPLAY_VER(display) >= 11 && !display->platform.dg2)
ret = intel_pcode_write(display->drm, SKL_PCODE_CDCLK_CONTROL,
cdclk_config->voltage_level);
ret = intel_parent_pcode_write(display, SKL_PCODE_CDCLK_CONTROL,
cdclk_config->voltage_level);
if (DISPLAY_VER(display) < 11) {
/*
* The timeout isn't specified, the 2ms used here is based on
@ -2296,9 +2297,9 @@ static void bxt_set_cdclk(struct intel_display *display,
* FIXME: Waiting for the request completion could be delayed
* until the next PCODE request based on BSpec.
*/
ret = intel_pcode_write_timeout(display->drm,
HSW_PCODE_DE_WRITE_FREQ_REQ,
cdclk_config->voltage_level, 2);
ret = intel_parent_pcode_write_timeout(display,
HSW_PCODE_DE_WRITE_FREQ_REQ,
cdclk_config->voltage_level, 2);
}
if (ret) {
drm_err(display->drm,
@ -2598,11 +2599,11 @@ static void intel_pcode_notify(struct intel_display *display,
if (pipe_count_update_valid)
update_mask |= DISPLAY_TO_PCODE_PIPE_COUNT_VALID;
ret = intel_pcode_request(display->drm, SKL_PCODE_CDCLK_CONTROL,
SKL_CDCLK_PREPARE_FOR_CHANGE |
update_mask,
SKL_CDCLK_READY_FOR_CHANGE,
SKL_CDCLK_READY_FOR_CHANGE, 3);
ret = intel_parent_pcode_request(display, SKL_PCODE_CDCLK_CONTROL,
SKL_CDCLK_PREPARE_FOR_CHANGE |
update_mask,
SKL_CDCLK_READY_FOR_CHANGE,
SKL_CDCLK_READY_FOR_CHANGE, 3);
if (ret)
drm_err(display->drm,
"Failed to inform PCU about display config (err %d)\n",
@ -4006,7 +4007,7 @@ void intel_init_cdclk_hooks(struct intel_display *display)
display->cdclk.table = dg2_cdclk_table;
} else if (display->platform.alderlake_p) {
/* Wa_22011320316:adl-p[a0] */
if (display->platform.alderlake_p && IS_DISPLAY_STEP(display, STEP_A0, STEP_B0)) {
if (intel_display_wa(display, INTEL_DISPLAY_WA_22011320316)) {
display->cdclk.table = adlp_a_step_cdclk_table;
display->funcs.cdclk = &tgl_cdclk_funcs;
} else if (display->platform.alderlake_p_raptorlake_u) {

View File

@ -33,6 +33,7 @@
#include <drm/drm_edid.h>
#include <drm/drm_print.h>
#include <drm/drm_probe_helper.h>
#include <video/vga.h>
#include "intel_connector.h"
#include "intel_crt.h"
@ -55,6 +56,7 @@
#include "intel_pch_display.h"
#include "intel_pch_refclk.h"
#include "intel_pfit.h"
#include "intel_vga.h"
/* Here's the desired hotplug mode */
#define ADPA_HOTPLUG_BITS (ADPA_CRT_HOTPLUG_ENABLE | \
@ -691,6 +693,11 @@ static bool intel_crt_detect_ddc(struct drm_connector *connector)
return ret;
}
static bool intel_crt_sense_above_threshold(struct intel_display *display)
{
return intel_vga_read(display, VGA_IS0_R, true) & (1 << 4);
}
static enum drm_connector_status
intel_crt_load_detect(struct intel_crt *crt, enum pipe pipe)
{
@ -702,7 +709,6 @@ intel_crt_load_detect(struct intel_crt *crt, enum pipe pipe)
u32 vsample;
u32 vblank, vblank_start, vblank_end;
u32 dsl;
u8 st00;
enum drm_connector_status status;
drm_dbg_kms(display->drm, "starting load-detect on CRT\n");
@ -736,8 +742,8 @@ intel_crt_load_detect(struct intel_crt *crt, enum pipe pipe)
* border color for Color info.
*/
intel_crtc_wait_for_next_vblank(intel_crtc_for_pipe(display, pipe));
st00 = intel_de_read8(display, _VGA_MSR_WRITE);
status = ((st00 & (1 << 4)) != 0) ?
status = intel_crt_sense_above_threshold(display) ?
connector_status_connected :
connector_status_disconnected;
@ -777,15 +783,13 @@ intel_crt_load_detect(struct intel_crt *crt, enum pipe pipe)
while ((dsl = intel_de_read(display, PIPEDSL(display, pipe))) <= vsample)
;
/*
* Watch ST00 for an entire scanline
* Watch sense for an entire scanline
*/
detect = 0;
count = 0;
do {
count++;
/* Read the ST00 VGA status register */
st00 = intel_de_read8(display, _VGA_MSR_WRITE);
if (st00 & (1 << 4))
if (intel_crt_sense_above_threshold(display))
detect++;
} while ((intel_de_read(display, PIPEDSL(display, pipe)) == dsl));

View File

@ -45,6 +45,4 @@
#define ADPA_VSYNC_ACTIVE_HIGH REG_BIT(4)
#define ADPA_HSYNC_ACTIVE_HIGH REG_BIT(3)
#define _VGA_MSR_WRITE _MMIO(0x3c2)
#endif /* __INTEL_CRT_REGS_H__ */

View File

@ -747,7 +747,9 @@ void intel_pipe_update_end(struct intel_atomic_state *state,
* which would cause the next frame to terminate already at vmin
* vblank start instead of vmax vblank start.
*/
if (!state->base.legacy_cursor_update)
if (!state->base.legacy_cursor_update ||
(intel_psr_use_trans_push(new_crtc_state) &&
!new_crtc_state->vrr.enable))
intel_vrr_send_push(NULL, new_crtc_state);
local_irq_enable();

View File

@ -19,6 +19,7 @@
#include "intel_display.h"
#include "intel_display_types.h"
#include "intel_display_utils.h"
#include "intel_display_wa.h"
#include "intel_fb.h"
#include "intel_fb_pin.h"
#include "intel_frontbuffer.h"
@ -424,7 +425,7 @@ static u32 i9xx_cursor_ctl(const struct intel_plane_state *plane_state)
cntl |= MCURSOR_ROTATE_180;
/* Wa_22012358565:adl-p */
if (DISPLAY_VER(display) == 13)
if (intel_display_wa(display, INTEL_DISPLAY_WA_22012358565))
cntl |= MCURSOR_ARB_SLOTS(1);
return cntl;

File diff suppressed because it is too large Load Diff

View File

@ -25,8 +25,8 @@ struct intel_dpll_hw_state;
struct intel_encoder;
struct intel_hdmi;
void intel_clear_response_ready_flag(struct intel_encoder *encoder,
int lane);
void intel_cx0_clear_response_ready_flag(struct intel_encoder *encoder,
int lane);
bool intel_encoder_is_c10phy(struct intel_encoder *encoder);
void intel_mtl_pll_enable(struct intel_encoder *encoder,
struct intel_dpll *pll,
@ -77,6 +77,7 @@ bool intel_mtl_tbt_pll_readout_hw_state(struct intel_display *display,
struct intel_dpll_hw_state *hw_state);
int intel_mtl_tbt_calc_port_clock(struct intel_encoder *encoder);
void intel_cx0pll_verify_plls(struct intel_display *display);
void intel_cx0_pll_power_save_wa(struct intel_display *display);
void intel_lnl_mac_transmit_lfps(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state);

View File

@ -78,10 +78,10 @@
#define XELPDP_PCLK_PLL_ENABLE_TIMEOUT_US 3200
#define XELPDP_PCLK_PLL_DISABLE_TIMEOUT_US 20
#define XELPDP_PORT_BUF_SOC_READY_TIMEOUT_US 100
#define XELPDP_PORT_RESET_START_TIMEOUT_US 5
#define XELPDP_PORT_RESET_START_TIMEOUT_US 10
#define XELPDP_PORT_POWERDOWN_UPDATE_TIMEOUT_MS 2
#define XELPDP_PORT_RESET_END_TIMEOUT_MS 15
#define XELPDP_REFCLK_ENABLE_TIMEOUT_US 1
#define XELPDP_REFCLK_ENABLE_TIMEOUT_US 10
#define _XELPDP_PORT_BUF_CTL1_LN0_A 0x64004
#define _XELPDP_PORT_BUF_CTL1_LN0_B 0x64104

View File

@ -34,7 +34,6 @@
#include <drm/drm_print.h>
#include <drm/drm_privacy_screen_consumer.h>
#include "i915_reg.h"
#include "icl_dsi.h"
#include "intel_alpm.h"
#include "intel_audio.h"
@ -53,6 +52,7 @@
#include "intel_display_regs.h"
#include "intel_display_types.h"
#include "intel_display_utils.h"
#include "intel_display_wa.h"
#include "intel_dkl_phy.h"
#include "intel_dkl_phy_regs.h"
#include "intel_dp.h"
@ -1402,8 +1402,7 @@ static void tgl_dkl_phy_set_signal_levels(struct intel_encoder *encoder,
int level;
/* Wa_16011342517:adl-p */
if (display->platform.alderlake_p &&
IS_DISPLAY_STEP(display, STEP_A0, STEP_D0)) {
if (intel_display_wa(display, INTEL_DISPLAY_WA_16011342517)) {
if ((intel_encoder_is_hdmi(encoder) &&
crtc_state->port_clock == 594000) ||
(intel_encoder_is_dp(encoder) &&
@ -4247,13 +4246,15 @@ void intel_ddi_get_clock(struct intel_encoder *encoder,
static void xe3plpd_ddi_get_config(struct intel_encoder *encoder,
struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(encoder);
intel_lt_phy_pll_readout_hw_state(encoder, crtc_state, &crtc_state->dpll_hw_state.ltpll);
if (crtc_state->dpll_hw_state.ltpll.tbt_mode)
crtc_state->port_clock = intel_mtl_tbt_calc_port_clock(encoder);
else
crtc_state->port_clock =
intel_lt_phy_calc_port_clock(encoder, crtc_state);
intel_lt_phy_calc_port_clock(display, &crtc_state->dpll_hw_state.ltpll);
intel_ddi_get_config(encoder, crtc_state);
}
@ -4586,8 +4587,10 @@ intel_ddi_port_sync_transcoders(const struct intel_crtc_state *ref_crtc_state,
/*
* We don't enable port sync on BDW due to missing w/as and
* due to not having adjusted the modeset sequence appropriately.
* From, xe3lpd onwards we have defeatured this with reference to
* Wa_16024710867
*/
if (DISPLAY_VER(display) < 9)
if (!IS_DISPLAY_VER(display, 9, 20))
return 0;
if (!intel_crtc_has_type(ref_crtc_state, INTEL_OUTPUT_DP))

View File

@ -6,6 +6,8 @@
#ifndef __INTEL_DE_H__
#define __INTEL_DE_H__
#include <drm/drm_print.h>
#include "intel_display_core.h"
#include "intel_dmc_wl.h"
#include "intel_dsb.h"
@ -34,15 +36,18 @@ intel_de_read(struct intel_display *display, i915_reg_t reg)
static inline u8
intel_de_read8(struct intel_display *display, i915_reg_t reg)
{
u8 val;
/* this is only used on VGA registers (possible on pre-g4x) */
drm_WARN_ON(display->drm, DISPLAY_VER(display) >= 5 || display->platform.g4x);
intel_dmc_wl_get(display, reg);
return intel_uncore_read8(__to_uncore(display), reg);
}
val = intel_uncore_read8(__to_uncore(display), reg);
static inline void
intel_de_write8(struct intel_display *display, i915_reg_t reg, u8 val)
{
drm_WARN_ON(display->drm, DISPLAY_VER(display) >= 5 || display->platform.g4x);
intel_dmc_wl_put(display, reg);
return val;
intel_uncore_write8(__to_uncore(display), reg, val);
}
static inline u64

View File

@ -50,7 +50,6 @@
#include "g4x_hdmi.h"
#include "hsw_ips.h"
#include "i915_config.h"
#include "i915_reg.h"
#include "i9xx_plane.h"
#include "i9xx_plane_regs.h"
#include "i9xx_wm.h"
@ -86,7 +85,6 @@
#include "intel_dpll.h"
#include "intel_dpll_mgr.h"
#include "intel_dpt.h"
#include "intel_dpt_common.h"
#include "intel_drrs.h"
#include "intel_dsb.h"
#include "intel_dsi.h"
@ -455,7 +453,7 @@ void intel_enable_transcoder(const struct intel_crtc_state *new_crtc_state)
}
/* Wa_22012358565:adl-p */
if (DISPLAY_VER(display) == 13)
if (intel_display_wa(display, INTEL_DISPLAY_WA_22012358565))
intel_de_rmw(display, PIPE_ARB_CTL(display, pipe),
0, PIPE_ARB_USE_PROG_SLOTS);
@ -709,7 +707,7 @@ static void icl_set_pipe_chicken(const struct intel_crtc_state *crtc_state)
tmp |= UNDERRUN_RECOVERY_DISABLE_ADLP;
/* Wa_14010547955:dg2 */
if (display->platform.dg2)
if (intel_display_wa(display, INTEL_DISPLAY_WA_14010547955))
tmp |= DG2_RENDER_CCSTAG_4_3_EN;
intel_de_write(display, PIPE_CHICKEN(pipe), tmp);
@ -1008,6 +1006,28 @@ static bool intel_casf_disabling(const struct intel_crtc_state *old_crtc_state,
return is_disabling(hw.casf_params.casf_enable, old_crtc_state, new_crtc_state);
}
static bool intel_crtc_lobf_enabling(const struct intel_crtc_state *old_crtc_state,
const struct intel_crtc_state *new_crtc_state)
{
if (!new_crtc_state->hw.active)
return false;
return is_enabling(has_lobf, old_crtc_state, new_crtc_state) ||
(new_crtc_state->has_lobf &&
(new_crtc_state->update_lrr || new_crtc_state->update_m_n));
}
static bool intel_crtc_lobf_disabling(const struct intel_crtc_state *old_crtc_state,
const struct intel_crtc_state *new_crtc_state)
{
if (!old_crtc_state->hw.active)
return false;
return is_disabling(has_lobf, old_crtc_state, new_crtc_state) ||
(old_crtc_state->has_lobf &&
(new_crtc_state->update_lrr || new_crtc_state->update_m_n));
}
#undef is_disabling
#undef is_enabling
@ -1050,12 +1070,13 @@ static void intel_post_plane_update(struct intel_atomic_state *state,
if (audio_enabling(old_crtc_state, new_crtc_state))
intel_encoders_audio_enable(state, crtc);
if (intel_display_wa(display, 14011503117)) {
if (intel_display_wa(display, INTEL_DISPLAY_WA_14011503117)) {
if (old_crtc_state->pch_pfit.enabled != new_crtc_state->pch_pfit.enabled)
adl_scaler_ecc_unmask(new_crtc_state);
}
intel_alpm_post_plane_update(state, crtc);
if (intel_crtc_lobf_enabling(old_crtc_state, new_crtc_state))
intel_alpm_lobf_enable(new_crtc_state);
intel_psr_post_plane_update(state, crtc);
}
@ -1152,7 +1173,9 @@ static void intel_pre_plane_update(struct intel_atomic_state *state,
intel_atomic_get_new_crtc_state(state, crtc);
enum pipe pipe = crtc->pipe;
intel_alpm_pre_plane_update(state, crtc);
if (intel_crtc_lobf_disabling(old_crtc_state, new_crtc_state))
intel_alpm_lobf_disable(new_crtc_state);
intel_psr_pre_plane_update(state, crtc);
if (intel_crtc_vrr_disabling(state, crtc)) {
@ -1614,7 +1637,6 @@ static void hsw_configure_cpu_transcoder(const struct intel_crtc_state *crtc_sta
}
intel_set_transcoder_timings(crtc_state);
intel_vrr_set_transcoder_timings(crtc_state);
if (cpu_transcoder != TRANSCODER_EDP)
intel_de_write(display, TRANS_MULT(display, cpu_transcoder),
@ -4325,6 +4347,23 @@ static int intel_crtc_atomic_check(struct intel_atomic_state *state,
return 0;
}
static int bpc_to_bpp(int bpc)
{
switch (bpc) {
case 6 ... 7:
return 6 * 3;
case 8 ... 9:
return 8 * 3;
case 10 ... 11:
return 10 * 3;
case 12 ... 16:
return 12 * 3;
default:
MISSING_CASE(bpc);
return -EINVAL;
}
}
static int
compute_sink_pipe_bpp(const struct drm_connector_state *conn_state,
struct intel_crtc_state *crtc_state)
@ -4332,36 +4371,34 @@ compute_sink_pipe_bpp(const struct drm_connector_state *conn_state,
struct intel_display *display = to_intel_display(crtc_state);
struct drm_connector *connector = conn_state->connector;
const struct drm_display_info *info = &connector->display_info;
int bpp;
int edid_bpc = info->bpc ? : 8;
int target_pipe_bpp;
int max_edid_bpp;
switch (conn_state->max_bpc) {
case 6 ... 7:
bpp = 6 * 3;
break;
case 8 ... 9:
bpp = 8 * 3;
break;
case 10 ... 11:
bpp = 10 * 3;
break;
case 12 ... 16:
bpp = 12 * 3;
break;
default:
MISSING_CASE(conn_state->max_bpc);
return -EINVAL;
}
max_edid_bpp = bpc_to_bpp(edid_bpc);
if (max_edid_bpp < 0)
return max_edid_bpp;
if (bpp < crtc_state->pipe_bpp) {
target_pipe_bpp = bpc_to_bpp(conn_state->max_bpc);
if (target_pipe_bpp < 0)
return target_pipe_bpp;
/*
* The maximum pipe BPP is the minimum of the max platform BPP and
* the max EDID BPP.
*/
crtc_state->max_pipe_bpp = min(crtc_state->pipe_bpp, max_edid_bpp);
if (target_pipe_bpp < crtc_state->pipe_bpp) {
drm_dbg_kms(display->drm,
"[CONNECTOR:%d:%s] Limiting display bpp to %d "
"[CONNECTOR:%d:%s] Limiting target display pipe bpp to %d "
"(EDID bpp %d, max requested bpp %d, max platform bpp %d)\n",
connector->base.id, connector->name,
bpp, 3 * info->bpc,
target_pipe_bpp, 3 * info->bpc,
3 * conn_state->max_requested_bpc,
crtc_state->pipe_bpp);
crtc_state->pipe_bpp = bpp;
crtc_state->pipe_bpp = target_pipe_bpp;
}
return 0;
@ -5459,7 +5496,7 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
PIPE_CONF_CHECK_I(dsc.config.nsl_bpg_offset);
PIPE_CONF_CHECK_BOOL(dsc.compression_enable);
PIPE_CONF_CHECK_I(dsc.num_streams);
PIPE_CONF_CHECK_I(dsc.slice_config.streams_per_pipe);
PIPE_CONF_CHECK_I(dsc.compressed_bpp_x16);
PIPE_CONF_CHECK_BOOL(splitter.enable);
@ -7357,9 +7394,6 @@ static void intel_atomic_dsb_finish(struct intel_atomic_state *state,
intel_psr_trigger_frame_change_event(new_crtc_state->dsb_commit,
state, crtc);
intel_psr_wait_for_idle_dsb(new_crtc_state->dsb_commit,
new_crtc_state);
if (new_crtc_state->use_dsb)
intel_dsb_vblank_evade(state, new_crtc_state->dsb_commit);
@ -7390,9 +7424,37 @@ static void intel_atomic_dsb_finish(struct intel_atomic_state *state,
new_crtc_state->dsb_color);
if (new_crtc_state->use_dsb && !intel_color_uses_chained_dsb(new_crtc_state)) {
intel_dsb_wait_vblanks(new_crtc_state->dsb_commit, 1);
/*
* Dsb wait vblank may or may not skip. Let's remove it for PSR
* trans push case to ensure we are not waiting two vblanks
*/
if (!intel_psr_use_trans_push(new_crtc_state))
intel_dsb_wait_vblanks(new_crtc_state->dsb_commit, 1);
intel_vrr_send_push(new_crtc_state->dsb_commit, new_crtc_state);
/*
* Wait for idle is needed for corner case where PSR HW
* is transitioning into DEEP_SLEEP/SRDENT_OFF when
* new Frame Change event comes in. It is ok to do it
* here for both Frame Change mechanism (trans push
* and register write).
*/
intel_psr_wait_for_idle_dsb(new_crtc_state->dsb_commit,
new_crtc_state);
/*
* In case PSR uses trans push as a "frame change" event and
* VRR is not in use we need to wait vblank. Otherwise we may
* miss selective updates. DSB skips all waits while PSR is
* active. Check push send is skipped as well because trans push
* send bit is not reset by the HW if VRR is not
* enabled -> we may start configuring new selective
* update while previous is not complete.
*/
if (intel_psr_use_trans_push(new_crtc_state))
intel_dsb_wait_vblanks(new_crtc_state->dsb_commit, 1);
intel_dsb_wait_for_delayed_vblank(state, new_crtc_state->dsb_commit);
intel_vrr_check_push_sent(new_crtc_state->dsb_commit,
new_crtc_state);
@ -8001,6 +8063,25 @@ void intel_setup_outputs(struct intel_display *display)
drm_helper_move_panel_connectors_to_head(display->drm);
}
int intel_max_uncompressed_dotclock(struct intel_display *display)
{
int max_dotclock = display->cdclk.max_dotclk_freq;
int limit = max_dotclock;
if (DISPLAY_VERx100(display) == 3002)
limit = 937500;
else if (DISPLAY_VER(display) >= 30)
limit = 1350000;
/*
* Note: For other platforms though there are limits given
* in the Bspec, however the limit is intentionally not
* enforced to avoid regressions, unless real issues are
* observed.
*/
return min(max_dotclock, limit);
}
static int max_dotclock(struct intel_display *display)
{
int max_dotclock = display->cdclk.max_dotclk_freq;

View File

@ -135,32 +135,6 @@ enum tc_port {
I915_MAX_TC_PORTS
};
enum aux_ch {
AUX_CH_NONE = -1,
AUX_CH_A,
AUX_CH_B,
AUX_CH_C,
AUX_CH_D,
AUX_CH_E, /* ICL+ */
AUX_CH_F,
AUX_CH_G,
AUX_CH_H,
AUX_CH_I,
/* tgl+ */
AUX_CH_USBC1 = AUX_CH_D,
AUX_CH_USBC2,
AUX_CH_USBC3,
AUX_CH_USBC4,
AUX_CH_USBC5,
AUX_CH_USBC6,
/* XE_LPD repositions D/E offsets and bitfields */
AUX_CH_D_XELPD = AUX_CH_USBC5,
AUX_CH_E_XELPD,
};
enum phy {
PHY_NONE = -1,
@ -488,6 +462,7 @@ void intel_cpu_transcoder_get_m2_n2(struct intel_crtc *crtc,
struct intel_link_m_n *m_n);
int intel_dotclock_calculate(int link_freq, const struct intel_link_m_n *m_n);
int intel_crtc_dotclock(const struct intel_crtc_state *pipe_config);
int intel_max_uncompressed_dotclock(struct intel_display *display);
enum intel_display_power_domain intel_port_to_power_domain(struct intel_digital_port *dig_port);
enum intel_display_power_domain
intel_aux_power_domain(struct intel_digital_port *dig_port);

View File

@ -13,9 +13,9 @@
#include <drm/drm_file.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_print.h>
#include <drm/intel/intel_gmd_misc_regs.h>
#include "hsw_ips.h"
#include "i915_reg.h"
#include "i9xx_wm_regs.h"
#include "intel_alpm.h"
#include "intel_bo.h"

View File

@ -10,7 +10,6 @@
#include <drm/drm_print.h>
#include <drm/intel/pciids.h>
#include "i915_reg.h"
#include "intel_cx0_phy_regs.h"
#include "intel_de.h"
#include "intel_display.h"
@ -20,6 +19,7 @@
#include "intel_display_reg_defs.h"
#include "intel_display_regs.h"
#include "intel_display_types.h"
#include "intel_display_wa.h"
#include "intel_fbc.h"
#include "intel_step.h"
@ -1540,9 +1540,9 @@ probe_gmdid_display(struct intel_display *display, struct intel_display_ip_ver *
return NULL;
}
gmd_id.ver = REG_FIELD_GET(GMD_ID_ARCH_MASK, val);
gmd_id.rel = REG_FIELD_GET(GMD_ID_RELEASE_MASK, val);
gmd_id.step = REG_FIELD_GET(GMD_ID_STEP, val);
gmd_id.ver = REG_FIELD_GET(GMD_ID_DISPLAY_ARCH_MASK, val);
gmd_id.rel = REG_FIELD_GET(GMD_ID_DISPLAY_RELEASE_MASK, val);
gmd_id.step = REG_FIELD_GET(GMD_ID_DISPLAY_STEP, val);
for (i = 0; i < ARRAY_SIZE(gmdid_display_map); i++) {
if (gmd_id.ver == gmdid_display_map[i].ver &&
@ -1774,7 +1774,7 @@ static void __intel_display_device_info_runtime_init(struct intel_display *displ
display_runtime->port_mask |= BIT(PORT_F);
/* Wa_14011765242: adl-s A0,A1 */
if (display->platform.alderlake_s && IS_DISPLAY_STEP(display, STEP_A0, STEP_A2))
if (intel_display_wa(display, INTEL_DISPLAY_WA_14011765242))
for_each_pipe(display, pipe)
display_runtime->num_scalers[pipe] = 0;
else if (DISPLAY_VER(display) >= 11) {

View File

@ -197,6 +197,7 @@ struct intel_display_platforms {
#define HAS_PSR(__display) (DISPLAY_INFO(__display)->has_psr)
#define HAS_PSR_HW_TRACKING(__display) (DISPLAY_INFO(__display)->has_psr_hw_tracking)
#define HAS_PSR2_SEL_FETCH(__display) (DISPLAY_VER(__display) >= 12)
#define HAS_PSR_TRANS_PUSH_FRAME_CHANGE(__display) (DISPLAY_VER(__display) >= 20)
#define HAS_SAGV(__display) (DISPLAY_VER(__display) >= 9 && \
!(__display)->platform.broxton && !(__display)->platform.geminilake)
#define HAS_TRANSCODER(__display, trans) ((DISPLAY_RUNTIME_INFO(__display)->cpu_transcoder_mask & \

View File

@ -208,16 +208,12 @@ int intel_display_driver_probe_noirq(struct intel_display *display)
intel_bios_init(display);
ret = intel_vga_register(display);
if (ret)
goto cleanup_bios;
intel_psr_dc5_dc6_wa_init(display);
/* FIXME: completely on the wrong abstraction layer */
ret = intel_power_domains_init(display);
if (ret < 0)
goto cleanup_vga;
goto cleanup_bios;
intel_pmdemand_init_early(display);
@ -229,7 +225,7 @@ int intel_display_driver_probe_noirq(struct intel_display *display)
display->hotplug.dp_wq = alloc_ordered_workqueue("intel-dp", 0);
if (!display->hotplug.dp_wq) {
ret = -ENOMEM;
goto cleanup_vga_client_pw_domain_dmc;
goto cleanup_pw_domain_dmc;
}
display->wq.modeset = alloc_ordered_workqueue("i915_modeset", 0);
@ -245,13 +241,13 @@ int intel_display_driver_probe_noirq(struct intel_display *display)
goto cleanup_wq_modeset;
}
display->wq.cleanup = alloc_workqueue("i915_cleanup", WQ_HIGHPRI, 0);
display->wq.cleanup = alloc_workqueue("i915_cleanup", WQ_HIGHPRI | WQ_PERCPU, 0);
if (!display->wq.cleanup) {
ret = -ENOMEM;
goto cleanup_wq_flip;
}
display->wq.unordered = alloc_workqueue("display_unordered", 0, 0);
display->wq.unordered = alloc_workqueue("display_unordered", WQ_PERCPU, 0);
if (!display->wq.unordered) {
ret = -ENOMEM;
goto cleanup_wq_cleanup;
@ -301,11 +297,9 @@ int intel_display_driver_probe_noirq(struct intel_display *display)
destroy_workqueue(display->wq.modeset);
cleanup_wq_dp:
destroy_workqueue(display->hotplug.dp_wq);
cleanup_vga_client_pw_domain_dmc:
cleanup_pw_domain_dmc:
intel_dmc_fini(display);
intel_power_domains_driver_remove(display);
cleanup_vga:
intel_vga_unregister(display);
cleanup_bios:
intel_bios_driver_remove(display);
@ -554,6 +548,8 @@ void intel_display_driver_register(struct intel_display *display)
if (!HAS_DISPLAY(display))
return;
intel_vga_register(display);
/* Must be done after probing outputs */
intel_opregion_register(display);
intel_acpi_video_register(display);
@ -646,8 +642,6 @@ void intel_display_driver_remove_nogem(struct intel_display *display)
intel_power_domains_driver_remove(display);
intel_vga_unregister(display);
intel_bios_driver_remove(display);
}
@ -675,6 +669,8 @@ void intel_display_driver_unregister(struct intel_display *display)
acpi_video_unregister();
intel_opregion_unregister(display);
intel_vga_unregister(display);
}
/*

View File

@ -5,8 +5,8 @@
#include <drm/drm_print.h>
#include <drm/drm_vblank.h>
#include <drm/intel/intel_gmd_interrupt_regs.h>
#include "i915_reg.h"
#include "icl_dsi_regs.h"
#include "intel_crtc.h"
#include "intel_de.h"
@ -1619,7 +1619,7 @@ static void i915gm_irq_cstate_wa_enable(struct intel_display *display)
*/
if (display->irq.vblank_enabled++ == 0)
intel_de_write(display, SCPD0,
_MASKED_BIT_ENABLE(CSTATE_RENDER_CLOCK_GATE_DISABLE));
REG_MASKED_FIELD_ENABLE(CSTATE_RENDER_CLOCK_GATE_DISABLE));
}
static void i915gm_irq_cstate_wa_disable(struct intel_display *display)
@ -1628,7 +1628,7 @@ static void i915gm_irq_cstate_wa_disable(struct intel_display *display)
if (--display->irq.vblank_enabled == 0)
intel_de_write(display, SCPD0,
_MASKED_BIT_DISABLE(CSTATE_RENDER_CLOCK_GATE_DISABLE));
REG_MASKED_FIELD_DISABLE(CSTATE_RENDER_CLOCK_GATE_DISABLE));
}
void i915gm_irq_cstate_wa(struct intel_display *display, bool enable)
@ -2472,6 +2472,7 @@ void intel_display_irq_init(struct intel_display *display)
struct intel_display_irq_snapshot {
u32 derrmr;
u32 err_int;
};
struct intel_display_irq_snapshot *
@ -2486,6 +2487,9 @@ intel_display_irq_snapshot_capture(struct intel_display *display)
if (DISPLAY_VER(display) >= 6 && DISPLAY_VER(display) < 20 && !HAS_GMCH(display))
snapshot->derrmr = intel_de_read(display, DERRMR);
if (DISPLAY_VER(display) == 7)
snapshot->err_int = intel_de_read(display, GEN7_ERR_INT);
return snapshot;
}
@ -2496,4 +2500,5 @@ void intel_display_irq_snapshot_print(const struct intel_display_irq_snapshot *s
return;
drm_printf(p, "DERRMR: 0x%08x\n", snapshot->derrmr);
drm_printf(p, "ERR_INT: 0x%08x\n", snapshot->err_int);
}

View File

@ -138,6 +138,32 @@ enum hpd_pin {
HPD_NUM_PINS
};
enum aux_ch {
AUX_CH_NONE = -1,
AUX_CH_A,
AUX_CH_B,
AUX_CH_C,
AUX_CH_D,
AUX_CH_E, /* ICL+ */
AUX_CH_F,
AUX_CH_G,
AUX_CH_H,
AUX_CH_I,
/* tgl+ */
AUX_CH_USBC1 = AUX_CH_D,
AUX_CH_USBC2,
AUX_CH_USBC3,
AUX_CH_USBC4,
AUX_CH_USBC5,
AUX_CH_USBC6,
/* XE_LPD repositions D/E offsets and bitfields */
AUX_CH_D_XELPD = AUX_CH_USBC5,
AUX_CH_E_XELPD,
};
enum intel_color_block {
INTEL_PLANE_CB_PRE_CSC_LUT,
INTEL_PLANE_CB_CSC,

View File

@ -7,8 +7,8 @@
#include <linux/string_helpers.h>
#include <drm/drm_print.h>
#include <drm/intel/intel_pcode_regs.h>
#include "i915_reg.h"
#include "intel_backlight_regs.h"
#include "intel_cdclk.h"
#include "intel_clock_gating.h"
@ -21,12 +21,12 @@
#include "intel_display_rpm.h"
#include "intel_display_types.h"
#include "intel_display_utils.h"
#include "intel_display_wa.h"
#include "intel_dmc.h"
#include "intel_dram.h"
#include "intel_mchbar_regs.h"
#include "intel_parent.h"
#include "intel_pch_refclk.h"
#include "intel_pcode.h"
#include "intel_pmdemand.h"
#include "intel_pps_regs.h"
#include "intel_snps_phy.h"
@ -646,7 +646,7 @@ queue_async_put_domains_work(struct i915_power_domains *power_domains,
power.domains);
drm_WARN_ON(display->drm, power_domains->async_put_wakeref);
power_domains->async_put_wakeref = wakeref;
drm_WARN_ON(display->drm, !queue_delayed_work(system_unbound_wq,
drm_WARN_ON(display->drm, !queue_delayed_work(system_dfl_wq,
&power_domains->async_put_work,
msecs_to_jiffies(delay_ms)));
}
@ -1260,7 +1260,7 @@ static u32 hsw_read_dcomp(struct intel_display *display)
static void hsw_write_dcomp(struct intel_display *display, u32 val)
{
if (display->platform.haswell) {
if (intel_pcode_write(display->drm, GEN6_PCODE_WRITE_D_COMP, val))
if (intel_parent_pcode_write(display, GEN6_PCODE_WRITE_D_COMP, val))
drm_dbg_kms(display->drm, "Failed to write to D_COMP\n");
} else {
intel_de_write(display, D_COMP_BDW, val);
@ -1622,8 +1622,7 @@ static void tgl_bw_buddy_init(struct intel_display *display)
if (display->platform.dgfx && !display->platform.dg1)
return;
if (display->platform.alderlake_s ||
(display->platform.rocketlake && IS_DISPLAY_STEP(display, STEP_A0, STEP_B0)))
if (intel_display_wa(display, INTEL_DISPLAY_WA_1409767108))
/* Wa_1409767108 */
table = wa_1409767108_buddy_page_masks;
else
@ -1646,7 +1645,7 @@ static void tgl_bw_buddy_init(struct intel_display *display)
table[config].page_mask);
/* Wa_22010178259:tgl,dg1,rkl,adl-s */
if (DISPLAY_VER(display) == 12)
if (intel_display_wa(display, INTEL_DISPLAY_WA_22010178259))
intel_de_rmw(display, BW_BUDDY_CTL(i),
BW_BUDDY_TLB_REQ_TIMER_MASK,
BW_BUDDY_TLB_REQ_TIMER(0x8));
@ -1663,8 +1662,7 @@ static void icl_display_core_init(struct intel_display *display,
gen9_set_dc_state(display, DC_STATE_DISABLE);
/* Wa_14011294188:ehl,jsl,tgl,rkl,adl-s */
if (INTEL_PCH_TYPE(display) >= PCH_TGP &&
INTEL_PCH_TYPE(display) < PCH_DG1)
if (intel_display_wa(display, INTEL_DISPLAY_WA_14011294188))
intel_de_rmw(display, SOUTH_DSPCLK_GATE_D, 0,
PCH_DPMGUNIT_CLOCK_GATE_DISABLE);
@ -1718,17 +1716,17 @@ static void icl_display_core_init(struct intel_display *display,
intel_dmc_load_program(display);
/* Wa_14011508470:tgl,dg1,rkl,adl-s,adl-p,dg2 */
if (IS_DISPLAY_VERx100(display, 1200, 1300))
if (intel_display_wa(display, INTEL_DISPLAY_WA_14011508470))
intel_de_rmw(display, GEN11_CHICKEN_DCPR_2, 0,
DCPR_CLEAR_MEMSTAT_DIS | DCPR_SEND_RESP_IMM |
DCPR_MASK_LPMODE | DCPR_MASK_MAXLATENCY_MEMUP_CLR);
/* Wa_14011503030:xelpd */
if (DISPLAY_VER(display) == 13)
if (intel_display_wa(display, INTEL_DISPLAY_WA_14011503030))
intel_de_write(display, XELPD_DISPLAY_ERR_FATAL_MASK, ~0);
/* Wa_15013987218 */
if (DISPLAY_VER(display) == 20) {
if (intel_display_wa(display, INTEL_DISPLAY_WA_15013987218)) {
intel_de_rmw(display, SOUTH_DSPCLK_GATE_D,
0, PCH_GMBUSUNIT_CLOCK_GATE_DISABLE);
intel_de_rmw(display, SOUTH_DSPCLK_GATE_D,
@ -2267,8 +2265,9 @@ void intel_display_power_suspend_late(struct intel_display *display, bool s2idle
}
/* Tweaked Wa_14010685332:cnp,icp,jsp,mcc,tgp,adp */
if (INTEL_PCH_TYPE(display) >= PCH_CNP && INTEL_PCH_TYPE(display) < PCH_DG1)
intel_de_rmw(display, SOUTH_CHICKEN1, SBCLK_RUN_REFCLK_DIS, SBCLK_RUN_REFCLK_DIS);
if (intel_display_wa(display, INTEL_DISPLAY_WA_14010685332))
intel_de_rmw(display, SOUTH_CHICKEN1,
SBCLK_RUN_REFCLK_DIS, SBCLK_RUN_REFCLK_DIS);
}
void intel_display_power_resume_early(struct intel_display *display)
@ -2282,7 +2281,7 @@ void intel_display_power_resume_early(struct intel_display *display)
}
/* Tweaked Wa_14010685332:cnp,icp,jsp,mcc,tgp,adp */
if (INTEL_PCH_TYPE(display) >= PCH_CNP && INTEL_PCH_TYPE(display) < PCH_DG1)
if (intel_display_wa(display, INTEL_DISPLAY_WA_14010685332))
intel_de_rmw(display, SOUTH_CHICKEN1, SBCLK_RUN_REFCLK_DIS, 0);
intel_power_domains_resume(display);

View File

@ -112,7 +112,6 @@ static const struct i915_power_well_desc hsw_power_wells_main[] = {
.id = HSW_DISP_PW_GLOBAL),
),
.ops = &hsw_power_well_ops,
.has_vga = true,
},
};
@ -146,7 +145,6 @@ static const struct i915_power_well_desc bdw_power_wells_main[] = {
.id = HSW_DISP_PW_GLOBAL),
),
.ops = &hsw_power_well_ops,
.has_vga = true,
.irq_pipe_mask = BIT(PIPE_B) | BIT(PIPE_C),
},
};
@ -390,7 +388,6 @@ static const struct i915_power_well_desc skl_power_wells_main[] = {
.id = SKL_DISP_PW_2),
),
.ops = &hsw_power_well_ops,
.has_vga = true,
.irq_pipe_mask = BIT(PIPE_B) | BIT(PIPE_C),
.has_fuses = true,
}, {
@ -469,7 +466,6 @@ static const struct i915_power_well_desc bxt_power_wells_main[] = {
.id = SKL_DISP_PW_2),
),
.ops = &hsw_power_well_ops,
.has_vga = true,
.irq_pipe_mask = BIT(PIPE_B) | BIT(PIPE_C),
.has_fuses = true,
}, {
@ -572,7 +568,6 @@ static const struct i915_power_well_desc glk_power_wells_main[] = {
.id = SKL_DISP_PW_2),
),
.ops = &hsw_power_well_ops,
.has_vga = true,
.irq_pipe_mask = BIT(PIPE_B) | BIT(PIPE_C),
.has_fuses = true,
}, {
@ -748,7 +743,6 @@ static const struct i915_power_well_desc icl_power_wells_main[] = {
.id = ICL_DISP_PW_3),
),
.ops = &hsw_power_well_ops,
.has_vga = true,
.irq_pipe_mask = BIT(PIPE_B),
.has_fuses = true,
}, {
@ -914,7 +908,6 @@ static const struct i915_power_well_desc tgl_power_wells_main[] = {
.id = ICL_DISP_PW_3),
),
.ops = &hsw_power_well_ops,
.has_vga = true,
.irq_pipe_mask = BIT(PIPE_B),
.has_fuses = true,
}, {
@ -1071,7 +1064,6 @@ static const struct i915_power_well_desc rkl_power_wells_main[] = {
),
.ops = &hsw_power_well_ops,
.irq_pipe_mask = BIT(PIPE_B),
.has_vga = true,
.has_fuses = true,
}, {
.instances = &I915_PW_INSTANCES(
@ -1166,7 +1158,6 @@ static const struct i915_power_well_desc dg1_power_wells_main[] = {
),
.ops = &hsw_power_well_ops,
.irq_pipe_mask = BIT(PIPE_B),
.has_vga = true,
.has_fuses = true,
}, {
.instances = &I915_PW_INSTANCES(
@ -1325,7 +1316,6 @@ static const struct i915_power_well_desc xelpd_power_wells_main[] = {
.id = SKL_DISP_PW_2),
),
.ops = &hsw_power_well_ops,
.has_vga = true,
.has_fuses = true,
}, {
.instances = &I915_PW_INSTANCES(
@ -1482,7 +1472,6 @@ static const struct i915_power_well_desc xelpdp_power_wells_main[] = {
.id = SKL_DISP_PW_2),
),
.ops = &hsw_power_well_ops,
.has_vga = true,
.has_fuses = true,
}, {
.instances = &I915_PW_INSTANCES(
@ -1649,7 +1638,6 @@ static const struct i915_power_well_desc xe3lpd_power_wells_main[] = {
.id = SKL_DISP_PW_2),
),
.ops = &hsw_power_well_ops,
.has_vga = true,
.has_fuses = true,
}, {
.instances = &I915_PW_INSTANCES(
@ -1722,7 +1710,6 @@ static const struct i915_power_well_desc wcl_power_wells_main[] = {
.id = SKL_DISP_PW_2),
),
.ops = &hsw_power_well_ops,
.has_vga = true,
.has_fuses = true,
}, {
.instances = &I915_PW_INSTANCES(

View File

@ -6,8 +6,8 @@
#include <linux/iopoll.h>
#include <drm/drm_print.h>
#include <drm/intel/intel_pcode_regs.h>
#include "i915_reg.h"
#include "intel_backlight_regs.h"
#include "intel_combo_phy.h"
#include "intel_combo_phy_regs.h"
@ -18,6 +18,7 @@
#include "intel_display_regs.h"
#include "intel_display_rpm.h"
#include "intel_display_types.h"
#include "intel_display_wa.h"
#include "intel_dkl_phy.h"
#include "intel_dkl_phy_regs.h"
#include "intel_dmc.h"
@ -27,7 +28,6 @@
#include "intel_dpll.h"
#include "intel_hotplug.h"
#include "intel_parent.h"
#include "intel_pcode.h"
#include "intel_pps.h"
#include "intel_psr.h"
#include "intel_tc.h"
@ -195,6 +195,48 @@ int intel_power_well_refcount(struct i915_power_well *power_well)
return power_well->count;
}
static u32 dss_pipe_gating_bits(u8 irq_pipe_mask)
{
u32 bits = 0;
if (irq_pipe_mask & BIT(PIPE_A))
bits |= DSS_PIPE_A_GATING_DISABLED;
if (irq_pipe_mask & BIT(PIPE_B))
bits |= DSS_PIPE_B_GATING_DISABLED;
if (irq_pipe_mask & BIT(PIPE_C))
bits |= DSS_PIPE_C_GATING_DISABLED;
if (irq_pipe_mask & BIT(PIPE_D))
bits |= DSS_PIPE_D_GATING_DISABLED;
return bits;
}
static void dss_pipe_gating_enable_disable(struct intel_display *display,
u8 irq_pipe_mask,
bool disable)
{
u32 bits = dss_pipe_gating_bits(irq_pipe_mask);
u32 clear, set;
if (!bits)
return;
/*
* Single intel_de_rmw() for both enable/disable:
* - disable == true, set bits (disable clock gating)
* - disable == false, clear bits (re-enable clock gating)
*/
set = disable ? bits : 0;
clear = disable ? 0 : bits;
intel_de_rmw(display, CLKGATE_DIS_DSSDSC, clear, set);
drm_dbg_kms(display->drm,
"DSS clock gating %sd for pipe_mask=0x%x (CLKGATE_DIS_DSSDSC=0x%08x)\n",
str_enable_disable(!disable), irq_pipe_mask,
intel_de_read(display, CLKGATE_DIS_DSSDSC));
}
/*
* Starting with Haswell, we have a "Power Down Well" that can be turned off
* when not needed anymore. We have 4 registers that can request the power well
@ -202,20 +244,25 @@ int intel_power_well_refcount(struct i915_power_well *power_well)
* requesting it to be enabled.
*/
static void hsw_power_well_post_enable(struct intel_display *display,
u8 irq_pipe_mask, bool has_vga)
u8 irq_pipe_mask)
{
if (has_vga)
intel_vga_reset_io_mem(display);
if (irq_pipe_mask)
if (irq_pipe_mask) {
gen8_irq_power_well_post_enable(display, irq_pipe_mask);
if (intel_display_wa(display, INTEL_DISPLAY_WA_22021048059))
dss_pipe_gating_enable_disable(display, irq_pipe_mask, false);
}
}
static void hsw_power_well_pre_disable(struct intel_display *display,
u8 irq_pipe_mask)
{
if (irq_pipe_mask)
if (irq_pipe_mask) {
if (intel_display_wa(display, INTEL_DISPLAY_WA_22021048059))
dss_pipe_gating_enable_disable(display, irq_pipe_mask, true);
gen8_irq_power_well_pre_disable(display, irq_pipe_mask);
}
}
#define ICL_AUX_PW_TO_PHY(pw_idx) \
@ -418,8 +465,7 @@ static void hsw_power_well_enable(struct intel_display *display,
}
hsw_power_well_post_enable(display,
power_well->desc->irq_pipe_mask,
power_well->desc->has_vga);
power_well->desc->irq_pipe_mask);
}
static void hsw_power_well_disable(struct intel_display *display,
@ -522,7 +568,7 @@ static void icl_tc_cold_exit(struct intel_display *display)
int ret, tries = 0;
while (1) {
ret = intel_pcode_write(display->drm, ICL_PCODE_EXIT_TCCOLD, 0);
ret = intel_parent_pcode_write(display, ICL_PCODE_EXIT_TCCOLD, 0);
if (ret != -EAGAIN || ++tries == 3)
break;
msleep(1);
@ -806,7 +852,7 @@ void gen9_set_dc_state(struct intel_display *display, u32 state)
power_domains->dc_state, val & mask);
enable_dc6 = state & DC_STATE_EN_UPTO_DC6;
dc6_was_enabled = val & DC_STATE_EN_UPTO_DC6;
dc6_was_enabled = power_domains->dc_state & DC_STATE_EN_UPTO_DC6;
if (!dc6_was_enabled && enable_dc6)
intel_dmc_update_dc6_allowed_count(display, true);
@ -1230,7 +1276,7 @@ static void vlv_init_display_clock_gating(struct intel_display *display)
* Disable trickle feed and enable pnd deadline calculation
*/
intel_de_write(display, MI_ARB_VLV,
MI_ARB_DISPLAY_TRICKLE_FEED_DISABLE);
MI_ARB_DISPLAY_TRICKLE_FEED_DISABLE_VLV);
intel_de_write(display, CBR1_VLV, 0);
drm_WARN_ON(display->drm, DISPLAY_RUNTIME_INFO(display)->rawclk_freq == 0);
@ -1795,7 +1841,7 @@ tgl_tc_cold_request(struct intel_display *display, bool block)
* Spec states that we should timeout the request after 200us
* but the function below will timeout after 500us
*/
ret = intel_pcode_read(display->drm, TGL_PCODE_TCCOLD, &low_val, &high_val);
ret = intel_parent_pcode_read(display, TGL_PCODE_TCCOLD, &low_val, &high_val);
if (ret == 0) {
if (block &&
(low_val & TGL_PCODE_EXIT_TCCOLD_DATA_L_EXIT_FAILED))

View File

@ -103,8 +103,6 @@ struct i915_power_well_desc {
* the well enabled.
*/
u16 fixed_enable_delay:1;
/* The pw is backing the VGA functionality */
u16 has_vga:1;
u16 has_fuses:1;
/*
* The pw is for an ICL+ TypeC PHY port in

View File

@ -6,6 +6,9 @@
#include "intel_display_reg_defs.h"
#define GU_CNTL_PROTECTED _MMIO(0x10100C)
#define DEPRESENT REG_BIT(9)
#define _GEN7_PIPEA_DE_LOAD_SL 0x70068
#define _GEN7_PIPEB_DE_LOAD_SL 0x71068
#define GEN7_PIPE_DE_LOAD_SL(pipe) _MMIO_PIPE(pipe, _GEN7_PIPEA_DE_LOAD_SL, _GEN7_PIPEB_DE_LOAD_SL)
@ -79,6 +82,29 @@
#define DERRMR_PIPEC_VBLANK (1 << 21)
#define DERRMR_PIPEC_HBLANK (1 << 22)
#define GEN7_ERR_INT _MMIO(0x44040)
#define ERR_INT_POISON (1 << 31)
#define ERR_INT_INVALID_GTT_PTE (1 << 29)
#define ERR_INT_INVALID_PTE_DATA (1 << 28)
#define ERR_INT_SPRITE_C_FAULT (1 << 23)
#define ERR_INT_PRIMARY_C_FAULT (1 << 22)
#define ERR_INT_CURSOR_C_FAULT (1 << 21)
#define ERR_INT_SPRITE_B_FAULT (1 << 20)
#define ERR_INT_PRIMARY_B_FAULT (1 << 19)
#define ERR_INT_CURSOR_B_FAULT (1 << 18)
#define ERR_INT_SPRITE_A_FAULT (1 << 17)
#define ERR_INT_PRIMARY_A_FAULT (1 << 16)
#define ERR_INT_CURSOR_A_FAULT (1 << 15)
#define ERR_INT_MMIO_UNCLAIMED (1 << 13)
#define ERR_INT_PIPE_CRC_DONE_C (1 << 8)
#define ERR_INT_FIFO_UNDERRUN_C (1 << 6)
#define ERR_INT_PIPE_CRC_DONE_B (1 << 5)
#define ERR_INT_FIFO_UNDERRUN_B (1 << 3)
#define ERR_INT_PIPE_CRC_DONE_A (1 << 2)
#define ERR_INT_PIPE_CRC_DONE(pipe) (1 << (2 + (pipe) * 3))
#define ERR_INT_FIFO_UNDERRUN_A (1 << 0)
#define ERR_INT_FIFO_UNDERRUN(pipe) (1 << ((pipe) * 3))
#define VLV_IRQ_REGS I915_IRQ_REGS(VLV_IMR, \
VLV_IER, \
VLV_IIR)
@ -160,6 +186,47 @@
#define DPLL_FPA01_P1_POST_DIV_MASK_I830 0x001f0000
#define DSPCLK_GATE_D _MMIO(0x6200)
#define VLV_DSPCLK_GATE_D _MMIO(VLV_DISPLAY_BASE + 0x6200)
# define DPUNIT_B_CLOCK_GATE_DISABLE (1 << 30) /* 965 */
# define VSUNIT_CLOCK_GATE_DISABLE (1 << 29) /* 965 */
# define VRHUNIT_CLOCK_GATE_DISABLE (1 << 28) /* 965 */
# define VRDUNIT_CLOCK_GATE_DISABLE (1 << 27) /* 965 */
# define AUDUNIT_CLOCK_GATE_DISABLE (1 << 26) /* 965 */
# define DPUNIT_A_CLOCK_GATE_DISABLE (1 << 25) /* 965 */
# define DPCUNIT_CLOCK_GATE_DISABLE (1 << 24) /* 965 */
# define PNV_GMBUSUNIT_CLOCK_GATE_DISABLE (1 << 24) /* pnv */
# define TVRUNIT_CLOCK_GATE_DISABLE (1 << 23) /* 915-945 */
# define TVCUNIT_CLOCK_GATE_DISABLE (1 << 22) /* 915-945 */
# define TVFUNIT_CLOCK_GATE_DISABLE (1 << 21) /* 915-945 */
# define TVEUNIT_CLOCK_GATE_DISABLE (1 << 20) /* 915-945 */
# define DVSUNIT_CLOCK_GATE_DISABLE (1 << 19) /* 915-945 */
# define DSSUNIT_CLOCK_GATE_DISABLE (1 << 18) /* 915-945 */
# define DDBUNIT_CLOCK_GATE_DISABLE (1 << 17) /* 915-945 */
# define DPRUNIT_CLOCK_GATE_DISABLE (1 << 16) /* 915-945 */
# define DPFUNIT_CLOCK_GATE_DISABLE (1 << 15) /* 915-945 */
# define DPBMUNIT_CLOCK_GATE_DISABLE (1 << 14) /* 915-945 */
# define DPLSUNIT_CLOCK_GATE_DISABLE (1 << 13) /* 915-945 */
# define DPLUNIT_CLOCK_GATE_DISABLE (1 << 12) /* 915-945 */
# define DPOUNIT_CLOCK_GATE_DISABLE (1 << 11)
# define DPBUNIT_CLOCK_GATE_DISABLE (1 << 10)
# define DCUNIT_CLOCK_GATE_DISABLE (1 << 9)
# define DPUNIT_CLOCK_GATE_DISABLE (1 << 8)
# define VRUNIT_CLOCK_GATE_DISABLE (1 << 7) /* 915+: reserved */
# define OVHUNIT_CLOCK_GATE_DISABLE (1 << 6) /* 830-865 */
# define DPIOUNIT_CLOCK_GATE_DISABLE (1 << 6) /* 915-945 */
# define OVFUNIT_CLOCK_GATE_DISABLE (1 << 5)
# define OVBUNIT_CLOCK_GATE_DISABLE (1 << 4)
/*
* This bit must be set on the 830 to prevent hangs when turning off the
* overlay scaler.
*/
# define OVRUNIT_CLOCK_GATE_DISABLE (1 << 3)
# define OVCUNIT_CLOCK_GATE_DISABLE (1 << 2)
# define OVUUNIT_CLOCK_GATE_DISABLE (1 << 1)
# define ZVUNIT_CLOCK_GATE_DISABLE (1 << 0) /* 830 */
# define OVLUNIT_CLOCK_GATE_DISABLE (1 << 0) /* 845,865 */
/* Additional CHV pll/phy registers */
#define DPIO_PHY_STATUS _MMIO(VLV_DISPLAY_BASE + 0x6240)
#define DPLL_PORTD_READY_MASK (0xf)
@ -281,6 +348,7 @@
#define FW_CSPWRDWNEN (1 << 15)
#define MI_ARB_VLV _MMIO(VLV_DISPLAY_BASE + 0x6504)
#define MI_ARB_DISPLAY_TRICKLE_FEED_DISABLE_VLV (1 << 2)
#define CZCLK_CDCLK_FREQ_RATIO _MMIO(VLV_DISPLAY_BASE + 0x6508)
#define CDCLK_FREQ_SHIFT 4
@ -311,6 +379,46 @@
#define OGAMC1 _MMIO(0x30020)
#define OGAMC0 _MMIO(0x30024)
#define GEN8_CHICKEN_DCPR_1 _MMIO(0x46430)
#define _LATENCY_REPORTING_REMOVED_PIPE_D REG_BIT(31)
#define SKL_SELECT_ALTERNATE_DC_EXIT REG_BIT(30)
#define _LATENCY_REPORTING_REMOVED_PIPE_C REG_BIT(25)
#define _LATENCY_REPORTING_REMOVED_PIPE_B REG_BIT(24)
#define _LATENCY_REPORTING_REMOVED_PIPE_A REG_BIT(23)
#define LATENCY_REPORTING_REMOVED(pipe) _PICK((pipe), \
_LATENCY_REPORTING_REMOVED_PIPE_A, \
_LATENCY_REPORTING_REMOVED_PIPE_B, \
_LATENCY_REPORTING_REMOVED_PIPE_C, \
_LATENCY_REPORTING_REMOVED_PIPE_D)
#define ICL_DELAY_PMRSP REG_BIT(22)
#define DISABLE_FLR_SRC REG_BIT(15)
#define MASK_WAKEMEM REG_BIT(13)
#define DDI_CLOCK_REG_ACCESS REG_BIT(7)
#define CHICKEN_PAR1_1 _MMIO(0x42080)
#define IGNORE_KVMR_PIPE_A REG_BIT(23)
#define KBL_ARB_FILL_SPARE_22 REG_BIT(22)
#define DIS_RAM_BYPASS_PSR2_MAN_TRACK REG_BIT(16)
#define SKL_DE_COMPRESSED_HASH_MODE REG_BIT(15)
#define HSW_MASK_VBL_TO_PIPE_IN_SRD REG_BIT(15) /* hsw/bdw */
#define FORCE_ARB_IDLE_PLANES REG_BIT(14)
#define SKL_EDP_PSR_FIX_RDWRAP REG_BIT(3)
#define IGNORE_PSR2_HW_TRACKING REG_BIT(1)
/*
* GEN9 clock gating regs
*/
#define GEN9_CLKGATE_DIS_0 _MMIO(0x46530)
#define DARBF_GATING_DIS REG_BIT(27)
#define DMG_GATING_DIS REG_BIT(21)
#define MTL_PIPEDMC_GATING_DIS(pipe) REG_BIT(15 - (pipe))
#define PWM2_GATING_DIS REG_BIT(14)
#define PWM1_GATING_DIS REG_BIT(13)
#define GEN9_CLKGATE_DIS_3 _MMIO(0x46538)
#define TGL_VRH_GATING_DIS REG_BIT(31)
#define DPT_GATING_DIS REG_BIT(22)
#define GEN9_CLKGATE_DIS_4 _MMIO(0x4653C)
#define BXT_GMBUS_GATING_DIS (1 << 14)
#define DG2_DPFC_GATING_DIS REG_BIT(31)
@ -1003,6 +1111,15 @@
#define SWF3(dev_priv, i) _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x72414 + (i) * 4)
#define SWF_ILK(i) _MMIO(0x4F000 + (i) * 4)
#define DEISR _MMIO(0x44000)
#define DEIMR _MMIO(0x44004)
#define DEIIR _MMIO(0x44008)
#define DEIER _MMIO(0x4400c)
#define DE_IRQ_REGS I915_IRQ_REGS(DEIMR, \
DEIER, \
DEIIR)
#define DIGITAL_PORT_HOTPLUG_CNTRL _MMIO(0x44030)
#define DIGITAL_PORTA_HOTPLUG_ENABLE (1 << 4)
#define DIGITAL_PORTA_PULSE_DURATION_2ms (0 << 2) /* pre-HSW */
@ -1333,6 +1450,44 @@
GEN8_DE_PORT_IER, \
GEN8_DE_PORT_IIR)
/* interrupts */
#define DE_MASTER_IRQ_CONTROL (1 << 31)
#define DE_SPRITEB_FLIP_DONE (1 << 29)
#define DE_SPRITEA_FLIP_DONE (1 << 28)
#define DE_PLANEB_FLIP_DONE (1 << 27)
#define DE_PLANEA_FLIP_DONE (1 << 26)
#define DE_PLANE_FLIP_DONE(plane) (1 << (26 + (plane)))
#define DE_PCU_EVENT (1 << 25)
#define DE_GTT_FAULT (1 << 24)
#define DE_POISON (1 << 23)
#define DE_PERFORM_COUNTER (1 << 22)
#define DE_PCH_EVENT (1 << 21)
#define DE_AUX_CHANNEL_A (1 << 20)
#define DE_DP_A_HOTPLUG (1 << 19)
#define DE_GSE (1 << 18)
#define DE_PIPEB_VBLANK (1 << 15)
#define DE_PIPEB_EVEN_FIELD (1 << 14)
#define DE_PIPEB_ODD_FIELD (1 << 13)
#define DE_PIPEB_LINE_COMPARE (1 << 12)
#define DE_PIPEB_VSYNC (1 << 11)
#define DE_PIPEB_CRC_DONE (1 << 10)
#define DE_PIPEB_FIFO_UNDERRUN (1 << 8)
#define DE_PIPEA_VBLANK (1 << 7)
#define DE_PIPE_VBLANK(pipe) (1 << (7 + 8 * (pipe)))
#define DE_PIPEA_EVEN_FIELD (1 << 6)
#define DE_PIPEA_ODD_FIELD (1 << 5)
#define DE_PIPEA_LINE_COMPARE (1 << 4)
#define DE_PIPEA_VSYNC (1 << 3)
#define DE_PIPEA_CRC_DONE (1 << 2)
#define DE_PIPE_CRC_DONE(pipe) (1 << (2 + 8 * (pipe)))
#define DE_PIPEA_FIFO_UNDERRUN (1 << 0)
#define DE_PIPE_FIFO_UNDERRUN(pipe) (1 << (8 * (pipe)))
/* Display Internal Timeout Register */
#define RM_TIMEOUT _MMIO(0x42060)
#define RM_TIMEOUT_REG_CAPTURE _MMIO(0x420E0)
#define MMIO_TIMEOUT_US(us) ((us) << 0)
#define GEN8_DE_MISC_ISR _MMIO(0x44460)
#define GEN8_DE_MISC_IMR _MMIO(0x44464)
#define GEN8_DE_MISC_IIR _MMIO(0x44468)
@ -1466,6 +1621,29 @@
#define CHICKEN_FBC_STRIDE_MASK REG_GENMASK(12, 0)
#define CHICKEN_FBC_STRIDE(x) REG_FIELD_PREP(CHICKEN_FBC_STRIDE_MASK, (x))
#define _CHICKEN_PIPESL_1_A 0x420b0
#define _CHICKEN_PIPESL_1_B 0x420b4
#define CHICKEN_PIPESL_1(pipe) _MMIO_PIPE(pipe, _CHICKEN_PIPESL_1_A, _CHICKEN_PIPESL_1_B)
#define HSW_PRI_STRETCH_MAX_MASK REG_GENMASK(28, 27)
#define HSW_PRI_STRETCH_MAX_X8 REG_FIELD_PREP(HSW_PRI_STRETCH_MAX_MASK, 0)
#define HSW_PRI_STRETCH_MAX_X4 REG_FIELD_PREP(HSW_PRI_STRETCH_MAX_MASK, 1)
#define HSW_PRI_STRETCH_MAX_X2 REG_FIELD_PREP(HSW_PRI_STRETCH_MAX_MASK, 2)
#define HSW_PRI_STRETCH_MAX_X1 REG_FIELD_PREP(HSW_PRI_STRETCH_MAX_MASK, 3)
#define HSW_SPR_STRETCH_MAX_MASK REG_GENMASK(26, 25)
#define HSW_SPR_STRETCH_MAX_X8 REG_FIELD_PREP(HSW_SPR_STRETCH_MAX_MASK, 0)
#define HSW_SPR_STRETCH_MAX_X4 REG_FIELD_PREP(HSW_SPR_STRETCH_MAX_MASK, 1)
#define HSW_SPR_STRETCH_MAX_X2 REG_FIELD_PREP(HSW_SPR_STRETCH_MAX_MASK, 2)
#define HSW_SPR_STRETCH_MAX_X1 REG_FIELD_PREP(HSW_SPR_STRETCH_MAX_MASK, 3)
#define HSW_FBCQ_DIS REG_BIT(22)
#define HSW_UNMASK_VBL_TO_REGS_IN_SRD REG_BIT(15) /* hsw */
#define SKL_PSR_MASK_PLANE_FLIP REG_BIT(11) /* skl+ */
#define SKL_PLANE1_STRETCH_MAX_MASK REG_GENMASK(1, 0)
#define SKL_PLANE1_STRETCH_MAX_X8 REG_FIELD_PREP(SKL_PLANE1_STRETCH_MAX_MASK, 0)
#define SKL_PLANE1_STRETCH_MAX_X4 REG_FIELD_PREP(SKL_PLANE1_STRETCH_MAX_MASK, 1)
#define SKL_PLANE1_STRETCH_MAX_X2 REG_FIELD_PREP(SKL_PLANE1_STRETCH_MAX_MASK, 2)
#define SKL_PLANE1_STRETCH_MAX_X1 REG_FIELD_PREP(SKL_PLANE1_STRETCH_MAX_MASK, 3)
#define BDW_UNMASK_VBL_TO_REGS_IN_SRD REG_BIT(0) /* bdw */
#define _CHICKEN_TRANS_A 0x420c0
#define _CHICKEN_TRANS_B 0x420c4
#define _CHICKEN_TRANS_C 0x420c8
@ -1552,6 +1730,11 @@
#define GLK_DFSM_DISPLAY_DSC_DISABLE (1 << 7)
#define XE2LPD_DFSM_DBUF_OVERLAP_DISABLE (1 << 3)
#define GMD_ID_DISPLAY _MMIO(0x510a0)
#define GMD_ID_DISPLAY_ARCH_MASK REG_GENMASK(31, 22)
#define GMD_ID_DISPLAY_RELEASE_MASK REG_GENMASK(21, 14)
#define GMD_ID_DISPLAY_STEP REG_GENMASK(5, 0)
#define XE2LPD_DE_CAP _MMIO(0x41100)
#define XE2LPD_DE_CAP_3DLUT_MASK REG_GENMASK(31, 30)
#define XE2LPD_DE_CAP_DSC_MASK REG_GENMASK(29, 28)
@ -1685,6 +1868,13 @@
SDE_TC_HOTPLUG_ICP(HPD_PORT_TC2) | \
SDE_TC_HOTPLUG_ICP(HPD_PORT_TC1))
/* PCH */
#define SDEISR _MMIO(0xc4000)
#define SDEIMR _MMIO(0xc4004)
#define SDEIIR _MMIO(0xc4008)
#define SDEIER _MMIO(0xc400c)
#define SDE_IRQ_REGS I915_IRQ_REGS(SDEIMR, \
SDEIER, \
SDEIIR)
@ -2021,6 +2211,28 @@
#define TRANS_BPC_6 REG_FIELD_PREP(TRANS_BPC_MASK, 2)
#define TRANS_BPC_12 REG_FIELD_PREP(TRANS_BPC_MASK, 3)
/* Icelake PPS_DATA and _ECC DIP Registers.
* These are available for transcoders B,C and eDP.
* Adding the _A so as to reuse the _MMIO_TRANS2
* definition, with which it offsets to the right location.
*/
#define _TRANSA_CHICKEN1 0xf0060
#define _TRANSB_CHICKEN1 0xf1060
#define TRANS_CHICKEN1(pipe) _MMIO_PIPE(pipe, _TRANSA_CHICKEN1, _TRANSB_CHICKEN1)
#define TRANS_CHICKEN1_HDMIUNIT_GC_DISABLE REG_BIT(10)
#define TRANS_CHICKEN1_DP0UNIT_GC_DISABLE REG_BIT(4)
#define _TRANSA_CHICKEN2 0xf0064
#define _TRANSB_CHICKEN2 0xf1064
#define TRANS_CHICKEN2(pipe) _MMIO_PIPE(pipe, _TRANSA_CHICKEN2, _TRANSB_CHICKEN2)
#define TRANS_CHICKEN2_TIMING_OVERRIDE REG_BIT(31)
#define TRANS_CHICKEN2_FDI_POLARITY_REVERSED REG_BIT(29)
#define TRANS_CHICKEN2_FRAME_START_DELAY_MASK REG_GENMASK(28, 27)
#define TRANS_CHICKEN2_FRAME_START_DELAY(x) REG_FIELD_PREP(TRANS_CHICKEN2_FRAME_START_DELAY_MASK, (x)) /* 0-3 */
#define TRANS_CHICKEN2_DISABLE_DEEP_COLOR_COUNTER REG_BIT(26)
#define TRANS_CHICKEN2_DISABLE_DEEP_COLOR_MODESWITCH REG_BIT(25)
#define PCH_DP_B _MMIO(0xe4100)
#define PCH_DP_C _MMIO(0xe4200)
#define PCH_DP_D _MMIO(0xe4300)
@ -2211,6 +2423,13 @@
#define HSW_PWR_WELL_FORCE_ON (1 << 19)
#define HSW_PWR_WELL_CTL6 _MMIO(0x45414)
/* clock gating DSS DSC disable register */
#define CLKGATE_DIS_DSSDSC _MMIO(0x46548)
#define DSS_PIPE_D_GATING_DISABLED REG_BIT(31)
#define DSS_PIPE_C_GATING_DISABLED REG_BIT(29)
#define DSS_PIPE_B_GATING_DISABLED REG_BIT(27)
#define DSS_PIPE_A_GATING_DISABLED REG_BIT(25)
/* SKL Fuse Status */
enum skl_power_gate {
SKL_PG0,
@ -2854,6 +3073,42 @@ enum skl_power_gate {
#define SFUSE_STRAP_DDIC_DETECTED (1 << 1)
#define SFUSE_STRAP_DDID_DETECTED (1 << 0)
#define SOUTH_CHICKEN1 _MMIO(0xc2000)
#define FDIA_PHASE_SYNC_SHIFT_OVR 19
#define FDIA_PHASE_SYNC_SHIFT_EN 18
#define INVERT_DDIE_HPD REG_BIT(28)
#define INVERT_DDID_HPD_MTP REG_BIT(27)
#define INVERT_TC4_HPD REG_BIT(26)
#define INVERT_TC3_HPD REG_BIT(25)
#define INVERT_TC2_HPD REG_BIT(24)
#define INVERT_TC1_HPD REG_BIT(23)
#define INVERT_DDID_HPD (1 << 18)
#define INVERT_DDIC_HPD (1 << 17)
#define INVERT_DDIB_HPD (1 << 16)
#define INVERT_DDIA_HPD (1 << 15)
#define FDI_PHASE_SYNC_OVR(pipe) (1 << (FDIA_PHASE_SYNC_SHIFT_OVR - ((pipe) * 2)))
#define FDI_PHASE_SYNC_EN(pipe) (1 << (FDIA_PHASE_SYNC_SHIFT_EN - ((pipe) * 2)))
#define FDI_BC_BIFURCATION_SELECT (1 << 12)
#define CHASSIS_CLK_REQ_DURATION_MASK (0xf << 8)
#define CHASSIS_CLK_REQ_DURATION(x) ((x) << 8)
#define SBCLK_RUN_REFCLK_DIS (1 << 7)
#define ICP_SECOND_PPS_IO_SELECT REG_BIT(2)
#define SPT_PWM_GRANULARITY (1 << 0)
#define SOUTH_CHICKEN2 _MMIO(0xc2004)
#define FDI_MPHY_IOSFSB_RESET_STATUS (1 << 13)
#define FDI_MPHY_IOSFSB_RESET_CTL (1 << 12)
#define LPT_PWM_GRANULARITY (1 << 5)
#define DPLS_EDP_PPS_FIX_DIS (1 << 0)
#define SOUTH_DSPCLK_GATE_D _MMIO(0xc2020)
#define PCH_GMBUSUNIT_CLOCK_GATE_DISABLE (1 << 31)
#define PCH_DPLUNIT_CLOCK_GATE_DISABLE (1 << 30)
#define PCH_DPLSUNIT_CLOCK_GATE_DISABLE (1 << 29)
#define PCH_DPMGUNIT_CLOCK_GATE_DISABLE (1 << 15)
#define PCH_CPUNIT_CLOCK_GATE_DISABLE (1 << 14)
#define CNP_PWM_CGE_GATING_DISABLE (1 << 13)
#define PCH_LP_PARTITION_LEVEL_DISABLE (1 << 12)
/* Gen4+ Timestamp and Pipe Frame time stamp registers */
#define GEN4_TIMESTAMP _MMIO(0x2358)
#define ILK_TIMESTAMP_HI _MMIO(0x70070)
@ -2940,6 +3195,12 @@ enum skl_power_gate {
#define MTL_PIPE_CLKGATE_DIS2(pipe) _MMIO_PIPE(pipe, _MTL_PIPE_CLKGATE_DIS2_A, _MTL_PIPE_CLKGATE_DIS2_B)
#define MTL_DPFC_GATING_DIS REG_BIT(6)
#define MTL_MEM_SS_INFO_GLOBAL _MMIO(0x45700)
#define XE3P_ECC_IMPACTING_DE REG_BIT(12)
#define MTL_N_OF_ENABLED_QGV_POINTS_MASK REG_GENMASK(11, 8)
#define MTL_N_OF_POPULATED_CH_MASK REG_GENMASK(7, 4)
#define MTL_DDR_TYPE_MASK REG_GENMASK(3, 0)
#define MTL_MEM_SS_INFO_QGV_POINT_OFFSET 0x45710
#define MTL_MEM_SS_INFO_QGV_POINT_LOW(point) _MMIO(MTL_MEM_SS_INFO_QGV_POINT_OFFSET + (point) * 8)
#define MTL_TRCD_MASK REG_GENMASK(31, 24)
@ -2950,6 +3211,11 @@ enum skl_power_gate {
#define MTL_TRAS_MASK REG_GENMASK(16, 8)
#define MTL_TRDPRE_MASK REG_GENMASK(7, 0)
#define FW_BLC _MMIO(0x20d8)
#define FW_BLC2 _MMIO(0x20dc)
#define FW_BLC_SELF _MMIO(0x20e0) /* 915+ only */
#define FW_BLC_SELF_EN_MASK REG_BIT(31)
#define FW_BLC_SELF_FIFO_MASK REG_BIT(16) /* 945 only */
#define FW_BLC_SELF_EN REG_BIT(15) /* 945 only */
#endif /* __INTEL_DISPLAY_REGS_H__ */

View File

@ -8,8 +8,8 @@
#include <drm/drm_crtc.h>
#include <drm/drm_vblank.h>
#include "i915_reg.h"
#include "intel_display_core.h"
#include "intel_display_regs.h"
#include "intel_display_irq.h"
#include "intel_display_rps.h"
#include "intel_display_types.h"

View File

@ -19,7 +19,6 @@ struct intel_display_snapshot {
struct intel_display_device_info info;
struct intel_display_runtime_info runtime_info;
struct intel_display_params params;
struct intel_overlay_snapshot *overlay;
struct intel_dmc_snapshot *dmc;
struct intel_display_irq_snapshot *irq;
};
@ -41,7 +40,6 @@ struct intel_display_snapshot *intel_display_snapshot_capture(struct intel_displ
intel_display_params_copy(&snapshot->params);
snapshot->irq = intel_display_irq_snapshot_capture(display);
snapshot->overlay = intel_overlay_snapshot_capture(display);
snapshot->dmc = intel_dmc_snapshot_capture(display);
return snapshot;
@ -61,7 +59,6 @@ void intel_display_snapshot_print(const struct intel_display_snapshot *snapshot,
intel_display_params_dump(&snapshot->params, display->drm->driver->name, p);
intel_display_irq_snapshot_print(snapshot->irq, p);
intel_overlay_snapshot_print(snapshot->overlay, p);
intel_dmc_snapshot_print(snapshot->dmc, p);
}
@ -73,7 +70,6 @@ void intel_display_snapshot_free(struct intel_display_snapshot *snapshot)
intel_display_params_free(&snapshot->params);
kfree(snapshot->irq);
kfree(snapshot->overlay);
kfree(snapshot->dmc);
kfree(snapshot);
}

View File

@ -145,7 +145,7 @@ struct intel_framebuffer {
struct intel_fb_view remapped_view;
};
struct i915_address_space *dpt_vm;
struct intel_dpt *dpt;
unsigned int min_alignment;
unsigned int vtd_guard;
@ -351,6 +351,7 @@ struct intel_vbt_panel_data {
bool low_vswing;
bool hobl;
bool dsc_disable;
bool pipe_joiner_enable;
} edp;
struct {
@ -1162,6 +1163,7 @@ struct intel_crtc_state {
} dsi_pll;
int max_link_bpp_x16; /* in 1/16 bpp units */
int max_pipe_bpp; /* in 1 bpp units */
int pipe_bpp; /* in 1 bpp units */
int min_hblank;
struct intel_link_m_n dp_m_n;
@ -1333,10 +1335,13 @@ struct intel_crtc_state {
/* Only used for state computation, not read out from the HW. */
bool compression_enabled_on_link;
bool compression_enable;
int num_streams;
struct intel_dsc_slice_config {
int pipes_per_line;
int streams_per_pipe;
int slices_per_stream;
} slice_config;
/* Compressed Bpp in U6.4 format (first 4 bits for fractional part) */
u16 compressed_bpp_x16;
u8 slice_count;
struct drm_dsc_config config;
} dsc;
@ -1791,6 +1796,7 @@ struct intel_dp {
int link_rate;
u8 lane_count;
u8 sink_count;
bool downstream_port_changed;
bool needs_modeset_retry;
bool use_max_params;
u8 dpcd[DP_RECEIVER_CAP_SIZE];

View File

@ -5,11 +5,11 @@
#include <drm/drm_print.h>
#include "i915_reg.h"
#include "intel_de.h"
#include "intel_display_core.h"
#include "intel_display_regs.h"
#include "intel_display_wa.h"
#include "intel_step.h"
static void gen11_display_wa_apply(struct intel_display *display)
{
@ -32,9 +32,17 @@ static void adlp_display_wa_apply(struct intel_display *display)
intel_de_rmw(display, GEN8_CHICKEN_DCPR_1, DDI_CLOCK_REG_ACCESS, 0);
}
static void xe3plpd_display_wa_apply(struct intel_display *display)
{
/* Wa_22021451799 */
intel_de_rmw(display, GEN9_CLKGATE_DIS_0, 0, DMG_GATING_DIS);
}
void intel_display_wa_apply(struct intel_display *display)
{
if (display->platform.alderlake_p)
if (DISPLAY_VER(display) == 35)
xe3plpd_display_wa_apply(display);
else if (display->platform.alderlake_p)
adlp_display_wa_apply(display);
else if (DISPLAY_VER(display) == 12)
xe_d_display_wa_apply(display);
@ -62,22 +70,89 @@ static bool intel_display_needs_wa_16025573575(struct intel_display *display)
bool __intel_display_wa(struct intel_display *display, enum intel_display_wa wa, const char *name)
{
switch (wa) {
case INTEL_DISPLAY_WA_1409120013:
return IS_DISPLAY_VER(display, 11, 12);
case INTEL_DISPLAY_WA_1409767108:
return (display->platform.alderlake_s ||
(display->platform.rocketlake &&
IS_DISPLAY_STEP(display, STEP_A0, STEP_B0)));
case INTEL_DISPLAY_WA_13012396614:
return DISPLAY_VERx100(display) == 3000;
return DISPLAY_VERx100(display) == 3000 ||
DISPLAY_VERx100(display) == 3500;
case INTEL_DISPLAY_WA_14010477008:
return display->platform.dg1 || display->platform.rocketlake ||
(display->platform.tigerlake &&
IS_DISPLAY_STEP(display, STEP_A0, STEP_D0));
case INTEL_DISPLAY_WA_14010480278:
return (IS_DISPLAY_VER(display, 10, 12));
case INTEL_DISPLAY_WA_14010547955:
return display->platform.dg2;
case INTEL_DISPLAY_WA_14010685332:
return INTEL_PCH_TYPE(display) >= PCH_CNP &&
INTEL_PCH_TYPE(display) < PCH_DG1;
case INTEL_DISPLAY_WA_14011294188:
return INTEL_PCH_TYPE(display) >= PCH_TGP &&
INTEL_PCH_TYPE(display) < PCH_DG1;
case INTEL_DISPLAY_WA_14011503030:
case INTEL_DISPLAY_WA_14011503117:
case INTEL_DISPLAY_WA_22012358565:
return DISPLAY_VER(display) == 13;
case INTEL_DISPLAY_WA_14011508470:
return (IS_DISPLAY_VERx100(display, 1200, 1300));
case INTEL_DISPLAY_WA_14011765242:
return display->platform.alderlake_s &&
IS_DISPLAY_STEP(display, STEP_A0, STEP_A2);
case INTEL_DISPLAY_WA_14014143976:
return IS_DISPLAY_STEP(display, STEP_E0, STEP_FOREVER);
case INTEL_DISPLAY_WA_14016740474:
return IS_DISPLAY_VERx100_STEP(display, 1400, STEP_A0, STEP_C0);
case INTEL_DISPLAY_WA_14020863754:
return DISPLAY_VERx100(display) == 3000 ||
DISPLAY_VERx100(display) == 2000 ||
DISPLAY_VERx100(display) == 1401;
case INTEL_DISPLAY_WA_14025769978:
return DISPLAY_VER(display) == 35;
case INTEL_DISPLAY_WA_15013987218:
return DISPLAY_VER(display) == 20;
case INTEL_DISPLAY_WA_15018326506:
return display->platform.battlemage;
case INTEL_DISPLAY_WA_16011303918:
case INTEL_DISPLAY_WA_22011320316:
return display->platform.alderlake_p &&
IS_DISPLAY_STEP(display, STEP_A0, STEP_B0);
case INTEL_DISPLAY_WA_16011181250:
return display->platform.rocketlake || display->platform.alderlake_s ||
display->platform.dg2;
case INTEL_DISPLAY_WA_16011342517:
return display->platform.alderlake_p &&
IS_DISPLAY_STEP(display, STEP_A0, STEP_D0);
case INTEL_DISPLAY_WA_16011863758:
return DISPLAY_VER(display) >= 11;
case INTEL_DISPLAY_WA_16023588340:
return intel_display_needs_wa_16023588340(display);
case INTEL_DISPLAY_WA_16025573575:
return intel_display_needs_wa_16025573575(display);
case INTEL_DISPLAY_WA_16025596647:
return DISPLAY_VER(display) == 20 &&
IS_DISPLAY_VERx100_STEP(display, 3000,
STEP_A0, STEP_B0);
case INTEL_DISPLAY_WA_18034343758:
return DISPLAY_VER(display) == 20 ||
(display->platform.pantherlake &&
IS_DISPLAY_STEP(display, STEP_A0, STEP_B0));
case INTEL_DISPLAY_WA_22010178259:
return DISPLAY_VER(display) == 12;
case INTEL_DISPLAY_WA_22010947358:
return display->platform.alderlake_p;
case INTEL_DISPLAY_WA_22012278275:
return display->platform.alderlake_p &&
IS_DISPLAY_STEP(display, STEP_A0, STEP_E0);
case INTEL_DISPLAY_WA_22014263786:
return IS_DISPLAY_VERx100(display, 1100, 1400);
case INTEL_DISPLAY_WA_22021048059:
return IS_DISPLAY_VER(display, 14, 35);
default:
drm_WARN(display->drm, 1, "Missing Wa number: %s\n", name);
drm_WARN(display->drm, 1, "Missing Wa: %s\n", name);
break;
}

View File

@ -27,18 +27,44 @@ bool intel_display_needs_wa_16023588340(struct intel_display *display);
* number.
*/
enum intel_display_wa {
INTEL_DISPLAY_WA_1409120013,
INTEL_DISPLAY_WA_1409767108,
INTEL_DISPLAY_WA_13012396614,
INTEL_DISPLAY_WA_14010477008,
INTEL_DISPLAY_WA_14010480278,
INTEL_DISPLAY_WA_14010547955,
INTEL_DISPLAY_WA_14010685332,
INTEL_DISPLAY_WA_14011294188,
INTEL_DISPLAY_WA_14011503030,
INTEL_DISPLAY_WA_14011503117,
INTEL_DISPLAY_WA_14011508470,
INTEL_DISPLAY_WA_14011765242,
INTEL_DISPLAY_WA_14014143976,
INTEL_DISPLAY_WA_14016740474,
INTEL_DISPLAY_WA_14020863754,
INTEL_DISPLAY_WA_14025769978,
INTEL_DISPLAY_WA_15013987218,
INTEL_DISPLAY_WA_15018326506,
INTEL_DISPLAY_WA_16011181250,
INTEL_DISPLAY_WA_16011303918,
INTEL_DISPLAY_WA_16011342517,
INTEL_DISPLAY_WA_16011863758,
INTEL_DISPLAY_WA_16023588340,
INTEL_DISPLAY_WA_16025573575,
INTEL_DISPLAY_WA_16025596647,
INTEL_DISPLAY_WA_18034343758,
INTEL_DISPLAY_WA_22010178259,
INTEL_DISPLAY_WA_22010947358,
INTEL_DISPLAY_WA_22011320316,
INTEL_DISPLAY_WA_22012278275,
INTEL_DISPLAY_WA_22012358565,
INTEL_DISPLAY_WA_22014263786,
INTEL_DISPLAY_WA_22021048059,
};
bool __intel_display_wa(struct intel_display *display, enum intel_display_wa wa, const char *name);
#define intel_display_wa(__display, __wa) \
__intel_display_wa((__display), INTEL_DISPLAY_WA_##__wa, __stringify(__wa))
__intel_display_wa((__display), __wa, __stringify(__wa))
#endif

View File

@ -29,7 +29,6 @@
#include <drm/drm_file.h>
#include <drm/drm_print.h>
#include "i915_reg.h"
#include "intel_crtc.h"
#include "intel_de.h"
#include "intel_display_power_well.h"
@ -1599,8 +1598,7 @@ static bool intel_dmc_get_dc6_allowed_count(struct intel_display *display, u32 *
return false;
mutex_lock(&power_domains->lock);
dc6_enabled = intel_de_read(display, DC_STATE_EN) &
DC_STATE_EN_UPTO_DC6;
dc6_enabled = power_domains->dc_state & DC_STATE_EN_UPTO_DC6;
if (dc6_enabled)
intel_dmc_update_dc6_allowed_count(display, false);

File diff suppressed because it is too large Load Diff

View File

@ -75,6 +75,7 @@ int intel_dp_compute_config(struct intel_encoder *encoder,
struct drm_connector_state *conn_state);
bool intel_dp_needs_8b10b_fec(const struct intel_crtc_state *crtc_state,
bool dsc_enabled_on_crtc);
void intel_dp_dsc_reset_config(struct intel_crtc_state *crtc_state);
int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
struct intel_crtc_state *pipe_config,
struct drm_connector_state *conn_state,
@ -143,6 +144,8 @@ bool intel_digital_port_connected(struct intel_encoder *encoder);
bool intel_digital_port_connected_locked(struct intel_encoder *encoder);
int intel_dp_dsc_compute_max_bpp(const struct intel_connector *connector,
u8 dsc_max_bpc);
int intel_dp_compute_min_compressed_bpp_x16(struct intel_connector *connector,
enum intel_output_format output_format);
bool intel_dp_mode_valid_with_dsc(struct intel_connector *connector,
int link_clock, int lane_count,
int mode_clock, int mode_hdisplay,
@ -153,10 +156,6 @@ bool intel_dp_dsc_valid_compressed_bpp(struct intel_dp *intel_dp, int bpp_x16);
u8 intel_dp_dsc_get_slice_count(const struct intel_connector *connector,
int mode_clock, int mode_hdisplay,
int num_joined_pipes);
int intel_dp_num_joined_pipes(struct intel_dp *intel_dp,
struct intel_connector *connector,
int hdisplay, int clock);
static inline unsigned int intel_dp_unused_lane_mask(int lane_count)
{
return ~((1 << lane_count) - 1) & 0xf;
@ -225,5 +224,18 @@ int intel_dp_compute_config_late(struct intel_encoder *encoder,
struct drm_connector_state *conn_state);
int intel_dp_sdp_min_guardband(const struct intel_crtc_state *crtc_state,
bool assume_all_enabled);
int intel_dp_max_hdisplay_per_pipe(struct intel_display *display);
bool intel_dp_dotclk_valid(struct intel_display *display,
int target_clock,
int htotal,
int dsc_slice_count,
int num_joined_pipes);
bool intel_dp_joiner_candidate_valid(struct intel_connector *connector,
int hdisplay,
int num_joined_pipes);
#define for_each_joiner_candidate(__connector, __mode, __num_joined_pipes) \
for ((__num_joined_pipes) = 1; (__num_joined_pipes) <= (I915_MAX_PIPES); (__num_joined_pipes)++) \
for_each_if(intel_dp_joiner_candidate_valid(__connector, (__mode)->hdisplay, __num_joined_pipes))
#endif /* __INTEL_DP_H__ */

View File

@ -368,6 +368,16 @@ static const char *dpcd_vs_pwm_str(bool aux)
return aux ? "DPCD" : "PWM";
}
static const char *backlight_unit_str(struct intel_panel *panel)
{
if (panel->backlight.edp.vesa.info.luminance_set)
return "NITS";
else if (panel->backlight.edp.vesa.info.aux_set)
return "Brightness %";
else
return "PWM";
}
static void
intel_dp_aux_write_panel_luminance_override(struct intel_connector *connector)
{
@ -459,7 +469,7 @@ static u32 intel_dp_aux_vesa_get_backlight(struct intel_connector *connector, en
return val / 1000;
}
return connector->panel.backlight.level;
return panel->backlight.level;
}
static void
@ -486,7 +496,8 @@ intel_dp_aux_vesa_enable_backlight(const struct intel_crtc_state *crtc_state,
struct intel_panel *panel = &connector->panel;
struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder);
if (!panel->backlight.edp.vesa.info.aux_enable) {
if (!(panel->backlight.edp.vesa.info.aux_enable ||
panel->backlight.edp.vesa.info.luminance_set)) {
u32 pwm_level;
if (!panel->backlight.edp.vesa.info.aux_set)
@ -510,7 +521,8 @@ static void intel_dp_aux_vesa_disable_backlight(const struct drm_connector_state
drm_edp_backlight_disable(&intel_dp->aux, &panel->backlight.edp.vesa.info);
if (!panel->backlight.edp.vesa.info.aux_enable)
if (!(panel->backlight.edp.vesa.info.aux_enable ||
panel->backlight.edp.vesa.info.luminance_set))
panel->backlight.pwm_funcs->disable(old_conn_state,
intel_backlight_invert_pwm_level(connector, 0));
}
@ -537,11 +549,14 @@ static int intel_dp_aux_vesa_setup_backlight(struct intel_connector *connector,
drm_dbg_kms(display->drm,
"[CONNECTOR:%d:%s] AUX VESA backlight enable is controlled through %s\n",
connector->base.base.id, connector->base.name,
dpcd_vs_pwm_str(panel->backlight.edp.vesa.info.aux_enable));
dpcd_vs_pwm_str(panel->backlight.edp.vesa.info.aux_enable ||
panel->backlight.edp.vesa.info.luminance_set));
drm_dbg_kms(display->drm,
"[CONNECTOR:%d:%s] AUX VESA backlight level is controlled through %s\n",
"[CONNECTOR:%d:%s] AUX VESA backlight level is controlled through %s using %s values\n",
connector->base.base.id, connector->base.name,
dpcd_vs_pwm_str(panel->backlight.edp.vesa.info.aux_set));
dpcd_vs_pwm_str(panel->backlight.edp.vesa.info.aux_set ||
panel->backlight.edp.vesa.info.luminance_set),
backlight_unit_str(panel));
if (!panel->backlight.edp.vesa.info.aux_set ||
!panel->backlight.edp.vesa.info.aux_enable) {
@ -564,9 +579,6 @@ static int intel_dp_aux_vesa_setup_backlight(struct intel_connector *connector,
}
panel->backlight.level = intel_dp_aux_vesa_get_backlight(connector, 0);
panel->backlight.enabled = panel->backlight.level != 0;
drm_dbg_kms(display->drm,
"[CONNECTOR:%d:%s] AUX VESA Nits backlight level is controlled through DPCD\n",
connector->base.base.id, connector->base.name);
} else if (panel->backlight.edp.vesa.info.aux_set) {
panel->backlight.max = panel->backlight.edp.vesa.info.max;
panel->backlight.min = 0;
@ -644,9 +656,10 @@ int intel_dp_aux_init_backlight_funcs(struct intel_connector *connector)
struct intel_dp *intel_dp = intel_attached_dp(connector);
struct drm_device *dev = connector->base.dev;
struct intel_panel *panel = &connector->panel;
bool try_intel_interface = false, try_vesa_interface = false;
bool try_intel_interface = false;
/* Check the VBT and user's module parameters to figure out which
/*
* Check the VBT and user's module parameters to figure out which
* interfaces to probe
*/
switch (display->params.enable_dpcd_backlight) {
@ -655,7 +668,6 @@ int intel_dp_aux_init_backlight_funcs(struct intel_connector *connector)
case INTEL_DP_AUX_BACKLIGHT_AUTO:
switch (panel->vbt.backlight.type) {
case INTEL_BACKLIGHT_VESA_EDP_AUX_INTERFACE:
try_vesa_interface = true;
break;
case INTEL_BACKLIGHT_DISPLAY_DDI:
try_intel_interface = true;
@ -668,20 +680,12 @@ int intel_dp_aux_init_backlight_funcs(struct intel_connector *connector)
if (panel->vbt.backlight.type != INTEL_BACKLIGHT_VESA_EDP_AUX_INTERFACE)
try_intel_interface = true;
try_vesa_interface = true;
break;
case INTEL_DP_AUX_BACKLIGHT_FORCE_VESA:
try_vesa_interface = true;
break;
case INTEL_DP_AUX_BACKLIGHT_FORCE_INTEL:
try_intel_interface = true;
break;
}
/* For eDP 1.5 and above we are supposed to use VESA interface for brightness control */
if (intel_dp->edp_dpcd[0] >= DP_EDP_15)
try_vesa_interface = true;
/*
* Since Intel has their own backlight control interface, the majority of machines out there
* using DPCD backlight controls with Intel GPUs will be using this interface as opposed to
@ -694,16 +698,19 @@ int intel_dp_aux_init_backlight_funcs(struct intel_connector *connector)
* panel with Intel's OUI - which is also required for us to be able to detect Intel's
* backlight interface at all. This means that the only sensible way for us to detect both
* interfaces is to probe for Intel's first, and VESA's second.
*
* Also there is a chance some VBTs may advertise false Intel backlight support even if the
* TCON DPCD says otherwise. This means we keep VESA interface as fallback in that case.
*/
if (try_intel_interface && intel_dp_aux_supports_hdr_backlight(connector) &&
intel_dp->edp_dpcd[0] <= DP_EDP_14b) {
if (try_intel_interface && intel_dp->edp_dpcd[0] <= DP_EDP_14b &&
intel_dp_aux_supports_hdr_backlight(connector)) {
drm_dbg_kms(dev, "[CONNECTOR:%d:%s] Using Intel proprietary eDP backlight controls\n",
connector->base.base.id, connector->base.name);
panel->backlight.funcs = &intel_dp_hdr_bl_funcs;
return 0;
}
if (try_vesa_interface && intel_dp_aux_supports_vesa_backlight(connector)) {
if (intel_dp_aux_supports_vesa_backlight(connector)) {
drm_dbg_kms(dev, "[CONNECTOR:%d:%s] Using VESA eDP backlight controls\n",
connector->base.base.id, connector->base.name);
panel->backlight.funcs = &intel_dp_vesa_bl_funcs;

View File

@ -43,6 +43,7 @@
#include "intel_display_regs.h"
#include "intel_display_types.h"
#include "intel_display_utils.h"
#include "intel_display_wa.h"
#include "intel_dp.h"
#include "intel_dp_hdcp.h"
#include "intel_dp_link_training.h"
@ -595,39 +596,22 @@ mst_stream_compute_config_limits(struct intel_dp *intel_dp,
dsc);
}
static int mst_stream_compute_config(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config,
struct drm_connector_state *conn_state)
static int mst_stream_compute_link_for_joined_pipes(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config,
struct drm_connector_state *conn_state,
int num_joined_pipes)
{
struct intel_display *display = to_intel_display(encoder);
struct intel_atomic_state *state = to_intel_atomic_state(conn_state->state);
struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);
struct intel_dp *intel_dp = to_primary_dp(encoder);
struct intel_connector *connector =
to_intel_connector(conn_state->connector);
const struct drm_display_mode *adjusted_mode =
&pipe_config->hw.adjusted_mode;
struct intel_connector *connector =
to_intel_connector(conn_state->connector);
struct link_config_limits limits;
bool dsc_needed, joiner_needs_dsc;
int num_joined_pipes;
int ret = 0;
if (pipe_config->fec_enable &&
!intel_dp_supports_fec(intel_dp, connector, pipe_config))
return -EINVAL;
if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
return -EINVAL;
num_joined_pipes = intel_dp_num_joined_pipes(intel_dp, connector,
adjusted_mode->crtc_hdisplay,
adjusted_mode->crtc_clock);
if (num_joined_pipes > 1)
pipe_config->joiner_pipes = GENMASK(crtc->pipe + num_joined_pipes - 1, crtc->pipe);
pipe_config->sink_format = INTEL_OUTPUT_FORMAT_RGB;
pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
pipe_config->has_pch_encoder = false;
intel_dp_dsc_reset_config(pipe_config);
joiner_needs_dsc = intel_dp_joiner_needs_dsc(display, num_joined_pipes);
@ -642,7 +626,12 @@ static int mst_stream_compute_config(struct intel_encoder *encoder,
if (ret == -EDEADLK)
return ret;
if (ret)
if (ret ||
!intel_dp_dotclk_valid(display,
adjusted_mode->clock,
adjusted_mode->htotal,
0,
num_joined_pipes))
dsc_needed = true;
}
@ -653,6 +642,8 @@ static int mst_stream_compute_config(struct intel_encoder *encoder,
/* enable compression if the mode doesn't fit available BW */
if (dsc_needed) {
int dsc_slice_count;
drm_dbg_kms(display->drm, "Try DSC (fallback=%s, joiner=%s, force=%s)\n",
str_yes_no(ret), str_yes_no(joiner_needs_dsc),
str_yes_no(intel_dp->force_dsc_en));
@ -683,6 +674,66 @@ static int mst_stream_compute_config(struct intel_encoder *encoder,
ret = intel_dp_dsc_compute_config(intel_dp, pipe_config,
conn_state, &limits,
pipe_config->dp_m_n.tu);
if (ret)
return ret;
dsc_slice_count = intel_dp_mst_dsc_get_slice_count(connector, pipe_config);
if (!intel_dp_dotclk_valid(display,
adjusted_mode->clock,
adjusted_mode->htotal,
dsc_slice_count,
num_joined_pipes))
return -EINVAL;
}
if (ret)
return ret;
ret = intel_dp_compute_min_hblank(pipe_config, conn_state);
if (ret)
return ret;
return 0;
}
static int mst_stream_compute_config(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config,
struct drm_connector_state *conn_state)
{
struct intel_display *display = to_intel_display(encoder);
struct intel_atomic_state *state = to_intel_atomic_state(conn_state->state);
struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);
struct intel_dp *intel_dp = to_primary_dp(encoder);
struct intel_connector *connector =
to_intel_connector(conn_state->connector);
const struct drm_display_mode *adjusted_mode =
&pipe_config->hw.adjusted_mode;
int num_joined_pipes;
int ret = -EINVAL;
if (pipe_config->fec_enable &&
!intel_dp_supports_fec(intel_dp, connector, pipe_config))
return -EINVAL;
if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
return -EINVAL;
pipe_config->sink_format = INTEL_OUTPUT_FORMAT_RGB;
pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
pipe_config->has_pch_encoder = false;
for_each_joiner_candidate(connector, adjusted_mode, num_joined_pipes) {
if (num_joined_pipes > 1)
pipe_config->joiner_pipes = GENMASK(crtc->pipe + num_joined_pipes - 1,
crtc->pipe);
ret = mst_stream_compute_link_for_joined_pipes(encoder,
pipe_config,
conn_state,
num_joined_pipes);
if (ret == 0 || ret == -EDEADLK)
break;
}
if (ret)
@ -695,10 +746,6 @@ static int mst_stream_compute_config(struct intel_encoder *encoder,
pipe_config->lane_lat_optim_mask =
bxt_dpio_phy_calc_lane_lat_optim_mask(pipe_config->lane_count);
ret = intel_dp_compute_min_hblank(pipe_config, conn_state);
if (ret)
return ret;
intel_vrr_compute_config(pipe_config, conn_state);
intel_dp_audio_compute_config(encoder, pipe_config, conn_state);
@ -1230,7 +1277,7 @@ static void enable_bs_jitter_was(const struct intel_crtc_state *crtc_state)
set |= DP_MST_FEC_BS_JITTER_WA(crtc_state->cpu_transcoder);
/* Wa_14014143976:adlp */
if (IS_DISPLAY_STEP(display, STEP_E0, STEP_FOREVER)) {
if (intel_display_wa(display, INTEL_DISPLAY_WA_14014143976)) {
if (intel_dp_is_uhbr(crtc_state))
set |= DP_MST_SHORT_HBLANK_WA(crtc_state->cpu_transcoder);
else if (crtc_state->fec_enable)
@ -1419,11 +1466,11 @@ mst_connector_mode_valid_ctx(struct drm_connector *_connector,
struct intel_dp *intel_dp = connector->mst.dp;
struct drm_dp_mst_topology_mgr *mgr = &intel_dp->mst.mgr;
struct drm_dp_mst_port *port = connector->mst.port;
const int min_bpp = 18;
int max_dotclk = display->cdclk.max_dotclk_freq;
int max_rate, mode_rate, max_lanes, max_link_clock;
unsigned long bw_overhead_flags =
DRM_DP_BW_OVERHEAD_MST | DRM_DP_BW_OVERHEAD_SSC_REF_CLK;
int min_link_bpp_x16 = fxp_q4_from_int(18);
static bool supports_dsc;
int ret;
bool dsc = false;
int target_clock = mode->clock;
@ -1448,6 +1495,13 @@ mst_connector_mode_valid_ctx(struct drm_connector *_connector,
return 0;
}
supports_dsc = intel_dp_has_dsc(connector) &&
drm_dp_sink_supports_fec(connector->dp.fec_capability);
if (supports_dsc && connector->mst.port->passthrough_aux)
min_link_bpp_x16 = intel_dp_compute_min_compressed_bpp_x16(connector,
INTEL_OUTPUT_FORMAT_RGB);
max_link_clock = intel_dp_max_link_rate(intel_dp);
max_lanes = intel_dp_max_lane_count(intel_dp);
@ -1455,12 +1509,19 @@ mst_connector_mode_valid_ctx(struct drm_connector *_connector,
max_link_clock, max_lanes);
mode_rate = intel_dp_link_required(max_link_clock, max_lanes,
mode->clock, mode->hdisplay,
fxp_q4_from_int(min_bpp),
min_link_bpp_x16,
bw_overhead_flags);
/*
* TODO:
* - Also check if compression would allow for the mode
* in non-passthrough mode, i.e. the last branch device
* decompressing the stream. This makes a difference only if
* the BW on the link between the last branch device and the
* sink is higher than the BW on the whole MST path from the
* source to the last branch device. Relying on the extra BW
* this provides also requires the
* DFP_Link_Available_Payload_Bandwidth_Number described below.
* - Calculate the overhead using drm_dp_bw_overhead() /
* drm_dp_bw_channel_coding_efficiency(), similarly to the
* compute config code, as drm_dp_calc_pbn_mode() doesn't
@ -1470,49 +1531,73 @@ mst_connector_mode_valid_ctx(struct drm_connector *_connector,
* corresponding link capabilities of the sink) in case the
* stream is uncompressed for it by the last branch device.
*/
num_joined_pipes = intel_dp_num_joined_pipes(intel_dp, connector,
mode->hdisplay, target_clock);
max_dotclk *= num_joined_pipes;
ret = drm_modeset_lock(&mgr->base.lock, ctx);
if (ret)
return ret;
if (mode_rate > max_rate || mode->clock > max_dotclk ||
drm_dp_calc_pbn_mode(mode->clock, min_bpp << 4) > port->full_pbn) {
if (mode_rate > max_rate ||
drm_dp_calc_pbn_mode(mode->clock, min_link_bpp_x16) > port->full_pbn) {
*status = MODE_CLOCK_HIGH;
return 0;
}
if (intel_dp_has_dsc(connector) && drm_dp_sink_supports_fec(connector->dp.fec_capability)) {
/*
* TBD pass the connector BPC,
* for now U8_MAX so that max BPC on that platform would be picked
*/
int pipe_bpp = intel_dp_dsc_compute_max_bpp(connector, U8_MAX);
*status = MODE_CLOCK_HIGH;
for_each_joiner_candidate(connector, mode, num_joined_pipes) {
int dsc_slice_count = 0;
if (!drm_dp_is_uhbr_rate(max_link_clock))
bw_overhead_flags |= DRM_DP_BW_OVERHEAD_FEC;
if (supports_dsc) {
/*
* TBD pass the connector BPC,
* for now U8_MAX so that max BPC on that platform would be picked
*/
int pipe_bpp = intel_dp_dsc_compute_max_bpp(connector, U8_MAX);
dsc = intel_dp_mode_valid_with_dsc(connector,
max_link_clock, max_lanes,
target_clock, mode->hdisplay,
num_joined_pipes,
INTEL_OUTPUT_FORMAT_RGB, pipe_bpp,
bw_overhead_flags);
dsc_slice_count = intel_dp_dsc_get_slice_count(connector,
mode->clock,
mode->hdisplay,
num_joined_pipes);
if (!drm_dp_is_uhbr_rate(max_link_clock))
bw_overhead_flags |= DRM_DP_BW_OVERHEAD_FEC;
dsc = intel_dp_mode_valid_with_dsc(connector,
max_link_clock, max_lanes,
target_clock, mode->hdisplay,
num_joined_pipes,
INTEL_OUTPUT_FORMAT_RGB, pipe_bpp,
bw_overhead_flags);
}
if (intel_dp_joiner_needs_dsc(display, num_joined_pipes) && !dsc) {
*status = MODE_CLOCK_HIGH;
continue;
}
if (mode_rate > max_rate && !dsc) {
*status = MODE_CLOCK_HIGH;
continue;
}
*status = intel_mode_valid_max_plane_size(display, mode, num_joined_pipes);
if (*status != MODE_OK)
continue;
if (!dsc)
dsc_slice_count = 0;
if (!intel_dp_dotclk_valid(display,
mode->clock,
mode->htotal,
dsc_slice_count,
num_joined_pipes)) {
*status = MODE_CLOCK_HIGH;
continue;
}
break;
}
if (intel_dp_joiner_needs_dsc(display, num_joined_pipes) && !dsc) {
*status = MODE_CLOCK_HIGH;
return 0;
}
if (mode_rate > max_rate && !dsc) {
*status = MODE_CLOCK_HIGH;
return 0;
}
*status = intel_mode_valid_max_plane_size(display, mode, num_joined_pipes);
return 0;
}

View File

@ -54,31 +54,20 @@ static int kbytes_to_mbits(int kbytes)
return DIV_ROUND_UP(kbytes * 8, 1000);
}
static int get_current_link_bw(struct intel_dp *intel_dp,
bool *below_dprx_bw)
static int get_current_link_bw(struct intel_dp *intel_dp)
{
int rate = intel_dp_max_common_rate(intel_dp);
int lane_count = intel_dp_max_common_lane_count(intel_dp);
int bw;
bw = intel_dp_max_link_data_rate(intel_dp, rate, lane_count);
*below_dprx_bw = bw < drm_dp_max_dprx_data_rate(rate, lane_count);
return bw;
return intel_dp_max_link_data_rate(intel_dp, rate, lane_count);
}
static int update_tunnel_state(struct intel_dp *intel_dp)
static int __update_tunnel_state(struct intel_dp *intel_dp, bool force_sink_update)
{
struct intel_display *display = to_intel_display(intel_dp);
struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
bool old_bw_below_dprx;
bool new_bw_below_dprx;
int old_bw;
int new_bw;
int ret;
old_bw = get_current_link_bw(intel_dp, &old_bw_below_dprx);
ret = drm_dp_tunnel_update_state(intel_dp->tunnel);
if (ret < 0) {
drm_dbg_kms(display->drm,
@ -90,18 +79,26 @@ static int update_tunnel_state(struct intel_dp *intel_dp)
return ret;
}
if (ret == 0 ||
!drm_dp_tunnel_bw_alloc_is_enabled(intel_dp->tunnel))
if (!force_sink_update &&
(ret == 0 || !drm_dp_tunnel_bw_alloc_is_enabled(intel_dp->tunnel)))
return 0;
intel_dp_update_sink_caps(intel_dp);
new_bw = get_current_link_bw(intel_dp, &new_bw_below_dprx);
return 0;
}
static bool has_tunnel_bw_changed(struct intel_dp *intel_dp, int old_bw)
{
struct intel_display *display = to_intel_display(intel_dp);
struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
int new_bw;
new_bw = get_current_link_bw(intel_dp);
/* Suppress the notification if the mode list can't change due to bw. */
if (old_bw_below_dprx == new_bw_below_dprx &&
!new_bw_below_dprx)
return 0;
if (old_bw == new_bw)
return false;
drm_dbg_kms(display->drm,
"[DPTUN %s][ENCODER:%d:%s] Notify users about BW change: %d -> %d\n",
@ -109,7 +106,29 @@ static int update_tunnel_state(struct intel_dp *intel_dp)
encoder->base.base.id, encoder->base.name,
kbytes_to_mbits(old_bw), kbytes_to_mbits(new_bw));
return 1;
return true;
}
/*
* Returns:
* - 0 in case of success - if there wasn't any change in the tunnel state
* requiring a user notification
* - 1 in case of success - if there was a change in the tunnel state
* requiring a user notification
* - Negative error code if updating the tunnel state failed
*/
static int update_tunnel_state(struct intel_dp *intel_dp)
{
int old_bw;
int err;
old_bw = get_current_link_bw(intel_dp);
err = __update_tunnel_state(intel_dp, false);
if (err)
return err;
return has_tunnel_bw_changed(intel_dp, old_bw) ? 1 : 0;
}
/*
@ -150,11 +169,9 @@ static int allocate_initial_tunnel_bw_for_pipes(struct intel_dp *intel_dp, u8 pi
drm_dp_tunnel_name(intel_dp->tunnel),
encoder->base.base.id, encoder->base.name,
ERR_PTR(err));
return err;
}
return update_tunnel_state(intel_dp);
return err;
}
static int allocate_initial_tunnel_bw(struct intel_dp *intel_dp,
@ -170,13 +187,24 @@ static int allocate_initial_tunnel_bw(struct intel_dp *intel_dp,
return allocate_initial_tunnel_bw_for_pipes(intel_dp, pipe_mask);
}
/*
* Returns:
* - 0 in case of success - after any tunnel detected and added to @intel_dp
* - 1 in case of success - after a tunnel detected and added to @intel_dp,
* where the link BW via the tunnel changed in a way requiring a user
* notification
* - Negative error code if the tunnel detection failed
*/
static int detect_new_tunnel(struct intel_dp *intel_dp, struct drm_modeset_acquire_ctx *ctx)
{
struct intel_display *display = to_intel_display(intel_dp);
struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
struct drm_dp_tunnel *tunnel;
int old_bw;
int ret;
old_bw = get_current_link_bw(intel_dp);
tunnel = drm_dp_tunnel_detect(display->dp_tunnel_mgr,
&intel_dp->aux);
if (IS_ERR(tunnel))
@ -200,10 +228,17 @@ static int detect_new_tunnel(struct intel_dp *intel_dp, struct drm_modeset_acqui
}
ret = allocate_initial_tunnel_bw(intel_dp, ctx);
if (ret < 0)
if (ret < 0) {
intel_dp_tunnel_destroy(intel_dp);
return ret;
return ret;
}
ret = __update_tunnel_state(intel_dp, true);
if (ret)
return ret;
return has_tunnel_bw_changed(intel_dp, old_bw) ? 1 : 0;
}
/**
@ -221,9 +256,12 @@ static int detect_new_tunnel(struct intel_dp *intel_dp, struct drm_modeset_acqui
* tunnel. If the tunnel's state change requires this - for instance the
* tunnel's group ID has changed - the tunnel will be dropped and recreated.
*
* Return 0 in case of success - after any tunnel detected and added to
* @intel_dp - 1 in case the BW on an already existing tunnel has changed in a
* way that requires notifying user space.
* Returns:
* - 0 in case of success - after any tunnel detected and added to @intel_dp
* - 1 in case the link BW via the new or an already existing tunnel has changed
* in a way that requires notifying user space
* - Negative error code, if creating a new tunnel or updating the tunnel
* state failed
*/
int intel_dp_tunnel_detect(struct intel_dp *intel_dp, struct drm_modeset_acquire_ctx *ctx)
{

View File

@ -1219,6 +1219,7 @@ static int xe3plpd_crtc_compute_clock(struct intel_atomic_state *state,
intel_atomic_get_new_crtc_state(state, crtc);
struct intel_encoder *encoder =
intel_get_crtc_new_encoder(state, crtc_state);
struct intel_display *display = to_intel_display(encoder);
int ret;
ret = intel_lt_phy_pll_calc_state(crtc_state, encoder);
@ -1227,7 +1228,7 @@ static int xe3plpd_crtc_compute_clock(struct intel_atomic_state *state,
/* TODO: Do the readback via intel_compute_shared_dplls() */
crtc_state->port_clock =
intel_lt_phy_calc_port_clock(encoder, crtc_state);
intel_lt_phy_calc_port_clock(display, &crtc_state->dpll_hw_state.ltpll);
crtc_state->hw.adjusted_mode.crtc_clock = intel_crtc_dotclock(crtc_state);
@ -2333,3 +2334,8 @@ void assert_pll_disabled(struct intel_display *display, enum pipe pipe)
{
assert_pll(display, pipe, false);
}
bool intel_dpll_clock_matches(int clock1, int clock2)
{
return abs(clock1 - clock2) <= 1;
}

View File

@ -48,5 +48,6 @@ void chv_crtc_clock_get(struct intel_crtc_state *crtc_state);
void assert_pll_enabled(struct intel_display *display, enum pipe pipe);
void assert_pll_disabled(struct intel_display *display, enum pipe pipe);
bool intel_dpll_clock_matches(int clock1, int clock2);
#endif

View File

@ -38,6 +38,7 @@
#include "intel_dpll.h"
#include "intel_dpll_mgr.h"
#include "intel_hti.h"
#include "intel_lt_phy.h"
#include "intel_mg_phy_regs.h"
#include "intel_pch_refclk.h"
#include "intel_step.h"
@ -4613,7 +4614,7 @@ void intel_dpll_init(struct intel_display *display)
dpll_mgr = &pch_pll_mgr;
if (!dpll_mgr)
return;
goto out_verify;
dpll_info = dpll_mgr->dpll_info;
@ -4632,6 +4633,14 @@ void intel_dpll_init(struct intel_display *display)
display->dpll.mgr = dpll_mgr;
display->dpll.num_dpll = i;
out_verify:
/*
* TODO: Convert these to a KUnit test or dependent on a kconfig
* debug option.
*/
intel_cx0pll_verify_plls(display);
intel_lt_phy_verify_plls(display);
}
/**

View File

@ -241,14 +241,12 @@ struct intel_mpllb_state {
};
struct intel_c10pll_state {
u32 clock; /* in KHz */
u8 tx;
u8 cmn;
u8 pll[20];
};
struct intel_c20pll_state {
u32 clock; /* in kHz */
u16 tx[3];
u16 cmn[4];
union {
@ -274,7 +272,6 @@ struct intel_cx0pll_state {
};
struct intel_lt_phy_pll_state {
u32 clock; /* in kHz */
u8 addr_msb[13];
u8 addr_lsb[13];
u8 data[13][4];

View File

@ -1,187 +1,67 @@
// SPDX-License-Identifier: MIT
/*
* Copyright © 2021 Intel Corporation
* Copyright © 2023 Intel Corporation
*/
#include <drm/drm_print.h>
#include "gem/i915_gem_domain.h"
#include "gem/i915_gem_internal.h"
#include "gem/i915_gem_lmem.h"
#include "gt/gen8_ppgtt.h"
#include "i915_drv.h"
#include "intel_display_core.h"
#include "intel_display_rpm.h"
#include "intel_de.h"
#include "intel_display_regs.h"
#include "intel_display_types.h"
#include "intel_dpt.h"
#include "intel_fb.h"
#include "intel_parent.h"
#include "skl_universal_plane_regs.h"
struct i915_dpt {
struct i915_address_space vm;
struct drm_i915_gem_object *obj;
struct i915_vma *vma;
void __iomem *iomem;
};
#define i915_is_dpt(vm) ((vm)->is_dpt)
static inline struct i915_dpt *
i915_vm_to_dpt(struct i915_address_space *vm)
void intel_dpt_configure(struct intel_crtc *crtc)
{
BUILD_BUG_ON(offsetof(struct i915_dpt, vm));
drm_WARN_ON(&vm->i915->drm, !i915_is_dpt(vm));
return container_of(vm, struct i915_dpt, vm);
struct intel_display *display = to_intel_display(crtc);
if (DISPLAY_VER(display) == 14) {
enum pipe pipe = crtc->pipe;
enum plane_id plane_id;
for_each_plane_id_on_crtc(crtc, plane_id) {
if (plane_id == PLANE_CURSOR)
continue;
intel_de_rmw(display, PLANE_CHICKEN(pipe, plane_id),
PLANE_CHICKEN_DISABLE_DPT,
display->params.enable_dpt ? 0 :
PLANE_CHICKEN_DISABLE_DPT);
}
} else if (DISPLAY_VER(display) == 13) {
intel_de_rmw(display, CHICKEN_MISC_2,
CHICKEN_MISC_DISABLE_DPT,
display->params.enable_dpt ? 0 :
CHICKEN_MISC_DISABLE_DPT);
}
}
static void gen8_set_pte(void __iomem *addr, gen8_pte_t pte)
/**
* intel_dpt_suspend - suspend the memory mapping for all DPT FBs during system suspend
* @display: display device instance
*
* Suspend the memory mapping during system suspend for all framebuffers which
* are mapped to HW via a GGTT->DPT page table.
*
* This function must be called before the mappings in GGTT are suspended calling
* i915_ggtt_suspend().
*/
void intel_dpt_suspend(struct intel_display *display)
{
writeq(pte, addr);
}
struct drm_framebuffer *drm_fb;
static void dpt_insert_page(struct i915_address_space *vm,
dma_addr_t addr,
u64 offset,
unsigned int pat_index,
u32 flags)
{
struct i915_dpt *dpt = i915_vm_to_dpt(vm);
gen8_pte_t __iomem *base = dpt->iomem;
gen8_set_pte(base + offset / I915_GTT_PAGE_SIZE,
vm->pte_encode(addr, pat_index, flags));
}
static void dpt_insert_entries(struct i915_address_space *vm,
struct i915_vma_resource *vma_res,
unsigned int pat_index,
u32 flags)
{
struct i915_dpt *dpt = i915_vm_to_dpt(vm);
gen8_pte_t __iomem *base = dpt->iomem;
const gen8_pte_t pte_encode = vm->pte_encode(0, pat_index, flags);
struct sgt_iter sgt_iter;
dma_addr_t addr;
int i;
/*
* Note that we ignore PTE_READ_ONLY here. The caller must be careful
* not to allow the user to override access to a read only page.
*/
i = vma_res->start / I915_GTT_PAGE_SIZE;
for_each_sgt_daddr(addr, sgt_iter, vma_res->bi.pages)
gen8_set_pte(&base[i++], pte_encode | addr);
}
static void dpt_clear_range(struct i915_address_space *vm,
u64 start, u64 length)
{
}
static void dpt_bind_vma(struct i915_address_space *vm,
struct i915_vm_pt_stash *stash,
struct i915_vma_resource *vma_res,
unsigned int pat_index,
u32 flags)
{
u32 pte_flags;
if (vma_res->bound_flags)
if (!HAS_DISPLAY(display))
return;
/* Applicable to VLV (gen8+ do not support RO in the GGTT) */
pte_flags = 0;
if (vm->has_read_only && vma_res->bi.readonly)
pte_flags |= PTE_READ_ONLY;
if (vma_res->bi.lmem)
pte_flags |= PTE_LM;
mutex_lock(&display->drm->mode_config.fb_lock);
vm->insert_entries(vm, vma_res, pat_index, pte_flags);
drm_for_each_fb(drm_fb, display->drm) {
struct intel_framebuffer *fb = to_intel_framebuffer(drm_fb);
vma_res->page_sizes_gtt = I915_GTT_PAGE_SIZE;
/*
* Without aliasing PPGTT there's no difference between
* GLOBAL/LOCAL_BIND, it's all the same ptes. Hence unconditionally
* upgrade to both bound if we bind either to avoid double-binding.
*/
vma_res->bound_flags = I915_VMA_GLOBAL_BIND | I915_VMA_LOCAL_BIND;
}
static void dpt_unbind_vma(struct i915_address_space *vm,
struct i915_vma_resource *vma_res)
{
vm->clear_range(vm, vma_res->start, vma_res->vma_size);
}
static void dpt_cleanup(struct i915_address_space *vm)
{
struct i915_dpt *dpt = i915_vm_to_dpt(vm);
i915_gem_object_put(dpt->obj);
}
struct i915_vma *intel_dpt_pin_to_ggtt(struct i915_address_space *vm,
unsigned int alignment)
{
struct drm_i915_private *i915 = vm->i915;
struct intel_display *display = i915->display;
struct i915_dpt *dpt = i915_vm_to_dpt(vm);
struct ref_tracker *wakeref;
struct i915_vma *vma;
void __iomem *iomem;
struct i915_gem_ww_ctx ww;
u64 pin_flags = 0;
int err;
if (i915_gem_object_is_stolen(dpt->obj))
pin_flags |= PIN_MAPPABLE;
wakeref = intel_display_rpm_get(display);
atomic_inc(&display->restore.pending_fb_pin);
for_i915_gem_ww(&ww, err, true) {
err = i915_gem_object_lock(dpt->obj, &ww);
if (err)
continue;
vma = i915_gem_object_ggtt_pin_ww(dpt->obj, &ww, NULL, 0,
alignment, pin_flags);
if (IS_ERR(vma)) {
err = PTR_ERR(vma);
continue;
}
iomem = i915_vma_pin_iomap(vma);
i915_vma_unpin(vma);
if (IS_ERR(iomem)) {
err = PTR_ERR(iomem);
continue;
}
dpt->vma = vma;
dpt->iomem = iomem;
i915_vma_get(vma);
if (fb->dpt)
intel_parent_dpt_suspend(display, fb->dpt);
}
dpt->obj->mm.dirty = true;
atomic_dec(&display->restore.pending_fb_pin);
intel_display_rpm_put(display, wakeref);
return err ? ERR_PTR(err) : vma;
}
void intel_dpt_unpin_from_ggtt(struct i915_address_space *vm)
{
struct i915_dpt *dpt = i915_vm_to_dpt(vm);
i915_vma_unpin_iomap(dpt->vma);
i915_vma_put(dpt->vma);
mutex_unlock(&display->drm->mode_config.fb_lock);
}
/**
@ -207,120 +87,8 @@ void intel_dpt_resume(struct intel_display *display)
drm_for_each_fb(drm_fb, display->drm) {
struct intel_framebuffer *fb = to_intel_framebuffer(drm_fb);
if (fb->dpt_vm)
i915_ggtt_resume_vm(fb->dpt_vm, true);
if (fb->dpt)
intel_parent_dpt_resume(display, fb->dpt);
}
mutex_unlock(&display->drm->mode_config.fb_lock);
}
/**
* intel_dpt_suspend - suspend the memory mapping for all DPT FBs during system suspend
* @display: display device instance
*
* Suspend the memory mapping during system suspend for all framebuffers which
* are mapped to HW via a GGTT->DPT page table.
*
* This function must be called before the mappings in GGTT are suspended calling
* i915_ggtt_suspend().
*/
void intel_dpt_suspend(struct intel_display *display)
{
struct drm_framebuffer *drm_fb;
if (!HAS_DISPLAY(display))
return;
mutex_lock(&display->drm->mode_config.fb_lock);
drm_for_each_fb(drm_fb, display->drm) {
struct intel_framebuffer *fb = to_intel_framebuffer(drm_fb);
if (fb->dpt_vm)
i915_ggtt_suspend_vm(fb->dpt_vm, true);
}
mutex_unlock(&display->drm->mode_config.fb_lock);
}
struct i915_address_space *
intel_dpt_create(struct intel_framebuffer *fb)
{
struct drm_gem_object *obj = intel_fb_bo(&fb->base);
struct drm_i915_private *i915 = to_i915(obj->dev);
struct drm_i915_gem_object *dpt_obj;
struct i915_address_space *vm;
struct i915_dpt *dpt;
size_t size;
int ret;
if (intel_fb_needs_pot_stride_remap(fb))
size = intel_remapped_info_size(&fb->remapped_view.gtt.remapped);
else
size = DIV_ROUND_UP_ULL(obj->size, I915_GTT_PAGE_SIZE);
size = round_up(size * sizeof(gen8_pte_t), I915_GTT_PAGE_SIZE);
dpt_obj = i915_gem_object_create_lmem(i915, size, I915_BO_ALLOC_CONTIGUOUS);
if (IS_ERR(dpt_obj) && i915_ggtt_has_aperture(to_gt(i915)->ggtt))
dpt_obj = i915_gem_object_create_stolen(i915, size);
if (IS_ERR(dpt_obj) && !HAS_LMEM(i915)) {
drm_dbg_kms(&i915->drm, "Allocating dpt from smem\n");
dpt_obj = i915_gem_object_create_shmem(i915, size);
}
if (IS_ERR(dpt_obj))
return ERR_CAST(dpt_obj);
ret = i915_gem_object_lock_interruptible(dpt_obj, NULL);
if (!ret) {
ret = i915_gem_object_set_cache_level(dpt_obj, I915_CACHE_NONE);
i915_gem_object_unlock(dpt_obj);
}
if (ret) {
i915_gem_object_put(dpt_obj);
return ERR_PTR(ret);
}
dpt = kzalloc_obj(*dpt);
if (!dpt) {
i915_gem_object_put(dpt_obj);
return ERR_PTR(-ENOMEM);
}
vm = &dpt->vm;
vm->gt = to_gt(i915);
vm->i915 = i915;
vm->dma = i915->drm.dev;
vm->total = (size / sizeof(gen8_pte_t)) * I915_GTT_PAGE_SIZE;
vm->is_dpt = true;
i915_address_space_init(vm, VM_CLASS_DPT);
vm->insert_page = dpt_insert_page;
vm->clear_range = dpt_clear_range;
vm->insert_entries = dpt_insert_entries;
vm->cleanup = dpt_cleanup;
vm->vma_ops.bind_vma = dpt_bind_vma;
vm->vma_ops.unbind_vma = dpt_unbind_vma;
vm->pte_encode = vm->gt->ggtt->vm.pte_encode;
dpt->obj = dpt_obj;
dpt->obj->is_dpt = true;
return &dpt->vm;
}
void intel_dpt_destroy(struct i915_address_space *vm)
{
struct i915_dpt *dpt = i915_vm_to_dpt(vm);
dpt->obj->is_dpt = false;
i915_vm_put(&dpt->vm);
}
u64 intel_dpt_offset(struct i915_vma *dpt_vma)
{
return i915_vma_offset(dpt_vma);
}

View File

@ -1,26 +1,16 @@
/* SPDX-License-Identifier: MIT */
/*
* Copyright © 2021 Intel Corporation
* Copyright © 2023 Intel Corporation
*/
#ifndef __INTEL_DPT_H__
#define __INTEL_DPT_H__
#ifndef __INTEL_DPT_COMMON_H__
#define __INTEL_DPT_COMMON_H__
#include <linux/types.h>
struct i915_address_space;
struct i915_vma;
struct intel_crtc;
struct intel_display;
struct intel_framebuffer;
void intel_dpt_destroy(struct i915_address_space *vm);
struct i915_vma *intel_dpt_pin_to_ggtt(struct i915_address_space *vm,
unsigned int alignment);
void intel_dpt_unpin_from_ggtt(struct i915_address_space *vm);
void intel_dpt_configure(struct intel_crtc *crtc);
void intel_dpt_suspend(struct intel_display *display);
void intel_dpt_resume(struct intel_display *display);
struct i915_address_space *
intel_dpt_create(struct intel_framebuffer *fb);
u64 intel_dpt_offset(struct i915_vma *dpt_vma);
#endif /* __INTEL_DPT_H__ */
#endif /* __INTEL_DPT_COMMON_H__ */

View File

@ -1,35 +0,0 @@
// SPDX-License-Identifier: MIT
/*
* Copyright © 2023 Intel Corporation
*/
#include "intel_de.h"
#include "intel_display_regs.h"
#include "intel_display_types.h"
#include "intel_dpt_common.h"
#include "skl_universal_plane_regs.h"
void intel_dpt_configure(struct intel_crtc *crtc)
{
struct intel_display *display = to_intel_display(crtc);
if (DISPLAY_VER(display) == 14) {
enum pipe pipe = crtc->pipe;
enum plane_id plane_id;
for_each_plane_id_on_crtc(crtc, plane_id) {
if (plane_id == PLANE_CURSOR)
continue;
intel_de_rmw(display, PLANE_CHICKEN(pipe, plane_id),
PLANE_CHICKEN_DISABLE_DPT,
display->params.enable_dpt ? 0 :
PLANE_CHICKEN_DISABLE_DPT);
}
} else if (DISPLAY_VER(display) == 13) {
intel_de_rmw(display, CHICKEN_MISC_2,
CHICKEN_MISC_DISABLE_DPT,
display->params.enable_dpt ? 0 :
CHICKEN_MISC_DISABLE_DPT);
}
}

View File

@ -1,13 +0,0 @@
/* SPDX-License-Identifier: MIT */
/*
* Copyright © 2023 Intel Corporation
*/
#ifndef __INTEL_DPT_COMMON_H__
#define __INTEL_DPT_COMMON_H__
struct intel_crtc;
void intel_dpt_configure(struct intel_crtc *crtc);
#endif /* __INTEL_DPT_COMMON_H__ */

View File

@ -7,13 +7,14 @@
#include <drm/drm_managed.h>
#include <drm/drm_print.h>
#include <drm/intel/intel_pcode_regs.h>
#include "i915_reg.h"
#include "intel_display_core.h"
#include "intel_display_utils.h"
#include "intel_display_regs.h"
#include "intel_dram.h"
#include "intel_mchbar_regs.h"
#include "intel_pcode.h"
#include "intel_parent.h"
#include "intel_uncore.h"
#include "vlv_iosf_sb.h"
@ -692,8 +693,8 @@ static int icl_pcode_read_mem_global_info(struct intel_display *display,
u32 val = 0;
int ret;
ret = intel_pcode_read(display->drm, ICL_PCODE_MEM_SUBSYSYSTEM_INFO |
ICL_PCODE_MEM_SS_READ_GLOBAL_INFO, &val, NULL);
ret = intel_parent_pcode_read(display, ICL_PCODE_MEM_SUBSYSYSTEM_INFO |
ICL_PCODE_MEM_SS_READ_GLOBAL_INFO, &val, NULL);
if (ret)
return ret;

View File

@ -8,6 +8,7 @@
#include <drm/drm_print.h>
#include <drm/drm_vblank.h>
#include <drm/intel/display_parent_interface.h>
#include "intel_crtc.h"
#include "intel_de.h"
@ -15,8 +16,8 @@
#include "intel_display_rpm.h"
#include "intel_display_types.h"
#include "intel_dsb.h"
#include "intel_dsb_buffer.h"
#include "intel_dsb_regs.h"
#include "intel_psr.h"
#include "intel_vblank.h"
#include "intel_vrr.h"
#include "skl_watermark.h"
@ -75,6 +76,57 @@ struct intel_dsb {
* writes). There are no registers reads possible with DSB HW engine.
*/
/*
* DSB buffer parent interface calls are here instead of intel_parent.[ch]
* because they're not used outside of intel_dsb.c.
*/
static u32 dsb_buffer_ggtt_offset(struct intel_dsb *dsb)
{
struct intel_display *display = to_intel_display(dsb->crtc);
return display->parent->dsb->ggtt_offset(dsb->dsb_buf);
}
static void dsb_buffer_write(struct intel_dsb *dsb, u32 idx, u32 val)
{
struct intel_display *display = to_intel_display(dsb->crtc);
display->parent->dsb->write(dsb->dsb_buf, idx, val);
}
static u32 dsb_buffer_read(struct intel_dsb *dsb, u32 idx)
{
struct intel_display *display = to_intel_display(dsb->crtc);
return display->parent->dsb->read(dsb->dsb_buf, idx);
}
static void dsb_buffer_fill(struct intel_dsb *dsb, u32 idx, u32 val, size_t size)
{
struct intel_display *display = to_intel_display(dsb->crtc);
display->parent->dsb->fill(dsb->dsb_buf, idx, val, size);
}
static struct intel_dsb_buffer *dsb_buffer_create(struct intel_display *display, size_t size)
{
return display->parent->dsb->create(display->drm, size);
}
static void dsb_buffer_cleanup(struct intel_dsb *dsb)
{
struct intel_display *display = to_intel_display(dsb->crtc);
display->parent->dsb->cleanup(dsb->dsb_buf);
}
static void dsb_buffer_flush_map(struct intel_dsb *dsb)
{
struct intel_display *display = to_intel_display(dsb->crtc);
display->parent->dsb->flush_map(dsb->dsb_buf);
}
/* DSB opcodes. */
#define DSB_OPCODE_SHIFT 24
#define DSB_OPCODE_NOOP 0x0
@ -166,18 +218,24 @@ static int dsb_scanline_to_hw(struct intel_atomic_state *state,
* definitely do not want to skip vblank wait. We also have concern what comes
* to skipping vblank evasion. I.e. arming registers are latched before we have
* managed writing them. Due to these reasons we are not setting
* DSB_SKIP_WAITS_EN.
* DSB_SKIP_WAITS_EN except when using TRANS_PUSH mechanism to trigger
* "frame change" event.
*/
static u32 dsb_chicken(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
const struct intel_crtc_state *new_crtc_state =
intel_atomic_get_new_crtc_state(state, crtc);
u32 chicken = intel_psr_use_trans_push(new_crtc_state) ?
DSB_SKIP_WAITS_EN : 0;
if (pre_commit_is_vrr_active(state, crtc))
return DSB_CTRL_WAIT_SAFE_WINDOW |
chicken |= DSB_CTRL_WAIT_SAFE_WINDOW |
DSB_CTRL_NO_WAIT_VBLANK |
DSB_INST_WAIT_SAFE_WINDOW |
DSB_INST_NO_WAIT_VBLANK;
else
return 0;
return chicken;
}
static bool assert_dsb_has_room(struct intel_dsb *dsb)
@ -211,10 +269,10 @@ static void intel_dsb_dump(struct intel_dsb *dsb)
for (i = 0; i < ALIGN(dsb->free_pos, 64 / 4); i += 4)
drm_dbg_kms(display->drm,
" 0x%08x: 0x%08x 0x%08x 0x%08x 0x%08x\n", i * 4,
intel_dsb_buffer_read(dsb->dsb_buf, i),
intel_dsb_buffer_read(dsb->dsb_buf, i + 1),
intel_dsb_buffer_read(dsb->dsb_buf, i + 2),
intel_dsb_buffer_read(dsb->dsb_buf, i + 3));
dsb_buffer_read(dsb, i),
dsb_buffer_read(dsb, i + 1),
dsb_buffer_read(dsb, i + 2),
dsb_buffer_read(dsb, i + 3));
drm_dbg_kms(display->drm, "}\n");
}
@ -231,12 +289,12 @@ unsigned int intel_dsb_size(struct intel_dsb *dsb)
unsigned int intel_dsb_head(struct intel_dsb *dsb)
{
return intel_dsb_buffer_ggtt_offset(dsb->dsb_buf);
return dsb_buffer_ggtt_offset(dsb);
}
static unsigned int intel_dsb_tail(struct intel_dsb *dsb)
{
return intel_dsb_buffer_ggtt_offset(dsb->dsb_buf) + intel_dsb_size(dsb);
return dsb_buffer_ggtt_offset(dsb) + intel_dsb_size(dsb);
}
static void intel_dsb_ins_align(struct intel_dsb *dsb)
@ -263,8 +321,8 @@ static void intel_dsb_emit(struct intel_dsb *dsb, u32 ldw, u32 udw)
dsb->ins[0] = ldw;
dsb->ins[1] = udw;
intel_dsb_buffer_write(dsb->dsb_buf, dsb->free_pos++, dsb->ins[0]);
intel_dsb_buffer_write(dsb->dsb_buf, dsb->free_pos++, dsb->ins[1]);
dsb_buffer_write(dsb, dsb->free_pos++, dsb->ins[0]);
dsb_buffer_write(dsb, dsb->free_pos++, dsb->ins[1]);
}
static bool intel_dsb_prev_ins_is_write(struct intel_dsb *dsb,
@ -335,13 +393,12 @@ void intel_dsb_reg_write_indexed(struct intel_dsb *dsb,
/* Update the count */
dsb->ins[0]++;
intel_dsb_buffer_write(dsb->dsb_buf, dsb->ins_start_offset + 0,
dsb->ins[0]);
dsb_buffer_write(dsb, dsb->ins_start_offset + 0, dsb->ins[0]);
intel_dsb_buffer_write(dsb->dsb_buf, dsb->free_pos++, val);
dsb_buffer_write(dsb, dsb->free_pos++, val);
/* if number of data words is odd, then the last dword should be 0.*/
if (dsb->free_pos & 0x1)
intel_dsb_buffer_write(dsb->dsb_buf, dsb->free_pos, 0);
dsb_buffer_write(dsb, dsb->free_pos, 0);
}
void intel_dsb_reg_write(struct intel_dsb *dsb,
@ -521,8 +578,7 @@ static void intel_dsb_align_tail(struct intel_dsb *dsb)
aligned_tail = ALIGN(tail, CACHELINE_BYTES);
if (aligned_tail > tail)
intel_dsb_buffer_memset(dsb->dsb_buf, dsb->free_pos, 0,
aligned_tail - tail);
dsb_buffer_fill(dsb, dsb->free_pos, 0, aligned_tail - tail);
dsb->free_pos = aligned_tail / 4;
}
@ -541,8 +597,7 @@ static void intel_dsb_gosub_align(struct intel_dsb *dsb)
* "Ensure GOSUB is not placed in cacheline QW slot 6 or 7 (numbered 0-7)"
*/
if (aligned_tail - tail <= 2 * 8)
intel_dsb_buffer_memset(dsb->dsb_buf, dsb->free_pos, 0,
aligned_tail - tail);
dsb_buffer_fill(dsb, dsb->free_pos, 0, aligned_tail - tail);
dsb->free_pos = aligned_tail / 4;
}
@ -606,14 +661,14 @@ void intel_dsb_gosub_finish(struct intel_dsb *dsb)
*/
intel_dsb_noop(dsb, 8);
intel_dsb_buffer_flush_map(dsb->dsb_buf);
dsb_buffer_flush_map(dsb);
}
void intel_dsb_finish(struct intel_dsb *dsb)
{
intel_dsb_align_tail(dsb);
intel_dsb_buffer_flush_map(dsb->dsb_buf);
dsb_buffer_flush_map(dsb);
}
static u32 dsb_error_int_status(struct intel_display *display)
@ -917,7 +972,7 @@ void intel_dsb_wait(struct intel_dsb *dsb)
!is_busy,
100, 1000, false);
if (ret) {
u32 offset = intel_dsb_buffer_ggtt_offset(dsb->dsb_buf);
u32 offset = dsb_buffer_ggtt_offset(dsb);
intel_de_write_fw(display, DSB_CTRL(pipe, dsb->id),
DSB_ENABLE | DSB_HALT);
@ -983,7 +1038,7 @@ struct intel_dsb *intel_dsb_prepare(struct intel_atomic_state *state,
/* ~1 qword per instruction, full cachelines */
size = ALIGN(max_cmds * 8, CACHELINE_BYTES);
dsb_buf = intel_dsb_buffer_create(display->drm, size);
dsb_buf = dsb_buffer_create(display, size);
if (IS_ERR(dsb_buf))
goto out_put_rpm;
@ -1021,7 +1076,7 @@ struct intel_dsb *intel_dsb_prepare(struct intel_atomic_state *state,
*/
void intel_dsb_cleanup(struct intel_dsb *dsb)
{
intel_dsb_buffer_cleanup(dsb->dsb_buf);
dsb_buffer_cleanup(dsb);
kfree(dsb);
}

View File

@ -1,22 +0,0 @@
/* SPDX-License-Identifier: MIT */
/*
* Copyright © 2023 Intel Corporation
*/
#ifndef _INTEL_DSB_BUFFER_H
#define _INTEL_DSB_BUFFER_H
#include <linux/types.h>
struct drm_device;
struct intel_dsb_buffer;
u32 intel_dsb_buffer_ggtt_offset(struct intel_dsb_buffer *dsb_buf);
void intel_dsb_buffer_write(struct intel_dsb_buffer *dsb_buf, u32 idx, u32 val);
u32 intel_dsb_buffer_read(struct intel_dsb_buffer *dsb_buf, u32 idx);
void intel_dsb_buffer_memset(struct intel_dsb_buffer *dsb_buf, u32 idx, u32 val, size_t size);
struct intel_dsb_buffer *intel_dsb_buffer_create(struct drm_device *drm, size_t size);
void intel_dsb_buffer_cleanup(struct intel_dsb_buffer *dsb_buf);
void intel_dsb_buffer_flush_map(struct intel_dsb_buffer *dsb_buf);
#endif

View File

@ -16,9 +16,7 @@
#include "intel_display_core.h"
#include "intel_display_types.h"
#include "intel_display_utils.h"
#include "intel_dpt.h"
#include "intel_fb.h"
#include "intel_fb_bo.h"
#include "intel_frontbuffer.h"
#include "intel_parent.h"
#include "intel_plane.h"
@ -2104,16 +2102,17 @@ int intel_plane_compute_gtt(struct intel_plane_state *plane_state)
static void intel_user_framebuffer_destroy(struct drm_framebuffer *fb)
{
struct intel_display *display = to_intel_display(fb->dev);
struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
drm_framebuffer_cleanup(fb);
if (intel_fb_uses_dpt(fb))
intel_dpt_destroy(intel_fb->dpt_vm);
intel_parent_dpt_destroy(display, intel_fb->dpt);
intel_fb_bo_framebuffer_fini(intel_fb_bo(fb));
intel_bo_framebuffer_fini(intel_fb_bo(fb));
intel_frontbuffer_put(intel_fb->frontbuffer);
intel_parent_frontbuffer_put(display, intel_fb->frontbuffer);
kfree(intel_fb->panic);
kfree(intel_fb);
@ -2221,16 +2220,16 @@ int intel_framebuffer_init(struct intel_framebuffer *intel_fb,
return -ENOMEM;
/*
* intel_frontbuffer_get() must be done before
* intel_fb_bo_framebuffer_init() to avoid set_tiling vs. addfb race.
* intel_parent_frontbuffer_get() must be done before
* intel_bo_framebuffer_init() to avoid set_tiling vs. addfb race.
*/
intel_fb->frontbuffer = intel_frontbuffer_get(obj);
intel_fb->frontbuffer = intel_parent_frontbuffer_get(display, obj);
if (!intel_fb->frontbuffer) {
ret = -ENOMEM;
goto err_free_panic;
}
ret = intel_fb_bo_framebuffer_init(obj, mode_cmd);
ret = intel_bo_framebuffer_init(obj, mode_cmd);
if (ret)
goto err_frontbuffer_put;
@ -2304,16 +2303,21 @@ int intel_framebuffer_init(struct intel_framebuffer *intel_fb,
goto err_bo_framebuffer_fini;
if (intel_fb_uses_dpt(fb)) {
struct i915_address_space *vm;
struct drm_gem_object *obj = intel_fb_bo(&intel_fb->base);
struct intel_dpt *dpt;
size_t size = 0;
vm = intel_dpt_create(intel_fb);
if (IS_ERR(vm)) {
if (intel_fb_needs_pot_stride_remap(intel_fb))
size = intel_remapped_info_size(&intel_fb->remapped_view.gtt.remapped);
dpt = intel_parent_dpt_create(display, obj, size);
if (IS_ERR(dpt)) {
drm_dbg_kms(display->drm, "failed to create DPT\n");
ret = PTR_ERR(vm);
ret = PTR_ERR(dpt);
goto err_frontbuffer_put;
}
intel_fb->dpt_vm = vm;
intel_fb->dpt = dpt;
}
ret = drm_framebuffer_init(display->drm, fb, &intel_fb_funcs);
@ -2326,11 +2330,11 @@ int intel_framebuffer_init(struct intel_framebuffer *intel_fb,
err_free_dpt:
if (intel_fb_uses_dpt(fb))
intel_dpt_destroy(intel_fb->dpt_vm);
intel_parent_dpt_destroy(display, intel_fb->dpt);
err_bo_framebuffer_fini:
intel_fb_bo_framebuffer_fini(obj);
intel_bo_framebuffer_fini(obj);
err_frontbuffer_put:
intel_frontbuffer_put(intel_fb->frontbuffer);
intel_parent_frontbuffer_put(display, intel_fb->frontbuffer);
err_free_panic:
kfree(intel_fb->panic);
@ -2343,11 +2347,12 @@ intel_user_framebuffer_create(struct drm_device *dev,
const struct drm_format_info *info,
const struct drm_mode_fb_cmd2 *user_mode_cmd)
{
struct intel_display *display = to_intel_display(dev);
struct drm_framebuffer *fb;
struct drm_gem_object *obj;
struct drm_mode_fb_cmd2 mode_cmd = *user_mode_cmd;
obj = intel_fb_bo_lookup_valid_bo(dev, filp, &mode_cmd);
obj = intel_bo_framebuffer_lookup(display, filp, &mode_cmd);
if (IS_ERR(obj))
return ERR_CAST(obj);

View File

@ -1,101 +0,0 @@
/* SPDX-License-Identifier: MIT */
/*
* Copyright © 2021 Intel Corporation
*/
#include <drm/drm_framebuffer.h>
#include <drm/drm_print.h>
#include "gem/i915_gem_object.h"
#include "i915_drv.h"
#include "intel_display_core.h"
#include "intel_display_types.h"
#include "intel_fb.h"
#include "intel_fb_bo.h"
void intel_fb_bo_framebuffer_fini(struct drm_gem_object *obj)
{
/* Nothing to do for i915 */
}
int intel_fb_bo_framebuffer_init(struct drm_gem_object *_obj,
struct drm_mode_fb_cmd2 *mode_cmd)
{
struct drm_i915_gem_object *obj = to_intel_bo(_obj);
struct intel_display *display = to_intel_display(obj->base.dev);
unsigned int tiling, stride;
i915_gem_object_lock(obj, NULL);
tiling = i915_gem_object_get_tiling(obj);
stride = i915_gem_object_get_stride(obj);
i915_gem_object_unlock(obj);
if (mode_cmd->flags & DRM_MODE_FB_MODIFIERS) {
/*
* If there's a fence, enforce that
* the fb modifier and tiling mode match.
*/
if (tiling != I915_TILING_NONE &&
tiling != intel_fb_modifier_to_tiling(mode_cmd->modifier[0])) {
drm_dbg_kms(display->drm,
"tiling_mode doesn't match fb modifier\n");
return -EINVAL;
}
} else {
if (tiling == I915_TILING_X) {
mode_cmd->modifier[0] = I915_FORMAT_MOD_X_TILED;
} else if (tiling == I915_TILING_Y) {
drm_dbg_kms(display->drm,
"No Y tiling for legacy addfb\n");
return -EINVAL;
}
}
/*
* gen2/3 display engine uses the fence if present,
* so the tiling mode must match the fb modifier exactly.
*/
if (DISPLAY_VER(display) < 4 &&
tiling != intel_fb_modifier_to_tiling(mode_cmd->modifier[0])) {
drm_dbg_kms(display->drm,
"tiling_mode must match fb modifier exactly on gen2/3\n");
return -EINVAL;
}
/*
* If there's a fence, enforce that
* the fb pitch and fence stride match.
*/
if (tiling != I915_TILING_NONE && mode_cmd->pitches[0] != stride) {
drm_dbg_kms(display->drm,
"pitch (%d) must match tiling stride (%d)\n",
mode_cmd->pitches[0], stride);
return -EINVAL;
}
return 0;
}
struct drm_gem_object *
intel_fb_bo_lookup_valid_bo(struct drm_device *drm,
struct drm_file *filp,
const struct drm_mode_fb_cmd2 *mode_cmd)
{
struct drm_i915_private *i915 = to_i915(drm);
struct drm_i915_gem_object *obj;
obj = i915_gem_object_lookup(filp, mode_cmd->handles[0]);
if (!obj)
return ERR_PTR(-ENOENT);
/* object is backed with LMEM for discrete */
if (HAS_LMEM(i915) && !i915_gem_object_can_migrate(obj, INTEL_REGION_LMEM_0)) {
/* object is "remote", not in local memory */
i915_gem_object_put(obj);
drm_dbg_kms(&i915->drm, "framebuffer must reside in local memory\n");
return ERR_PTR(-EREMOTE);
}
return intel_bo_to_drm_bo(obj);
}

View File

@ -1,25 +0,0 @@
/* SPDX-License-Identifier: MIT */
/*
* Copyright © 2021 Intel Corporation
*/
#ifndef __INTEL_FB_BO_H__
#define __INTEL_FB_BO_H__
struct drm_device;
struct drm_file;
struct drm_framebuffer;
struct drm_gem_object;
struct drm_mode_fb_cmd2;
void intel_fb_bo_framebuffer_fini(struct drm_gem_object *obj);
int intel_fb_bo_framebuffer_init(struct drm_gem_object *obj,
struct drm_mode_fb_cmd2 *mode_cmd);
struct drm_gem_object *
intel_fb_bo_lookup_valid_bo(struct drm_device *drm,
struct drm_file *filp,
const struct drm_mode_fb_cmd2 *user_mode_cmd);
#endif

View File

@ -17,7 +17,7 @@
#include "intel_display_core.h"
#include "intel_display_rpm.h"
#include "intel_display_types.h"
#include "intel_dpt.h"
#include "i915_dpt.h"
#include "intel_fb.h"
#include "intel_fb_pin.h"
#include "intel_plane.h"
@ -27,13 +27,14 @@ intel_fb_pin_to_dpt(const struct drm_framebuffer *fb,
const struct i915_gtt_view *view,
unsigned int alignment,
unsigned long *out_flags,
struct i915_address_space *vm)
struct intel_dpt *dpt)
{
struct drm_device *dev = fb->dev;
struct intel_display *display = to_intel_display(dev);
struct drm_i915_private *dev_priv = to_i915(dev);
struct drm_gem_object *_obj = intel_fb_bo(fb);
struct drm_i915_gem_object *obj = to_intel_bo(_obj);
struct i915_address_space *vm = i915_dpt_to_vm(dpt);
struct i915_gem_ww_ctx ww;
struct i915_vma *vma;
int ret;
@ -284,7 +285,7 @@ int intel_plane_pin_fb(struct intel_plane_state *plane_state,
} else {
unsigned int alignment = intel_plane_fb_min_alignment(plane_state);
vma = intel_dpt_pin_to_ggtt(fb->dpt_vm, alignment / 512);
vma = i915_dpt_pin_to_ggtt(fb->dpt, alignment / 512);
if (IS_ERR(vma))
return PTR_ERR(vma);
@ -292,9 +293,9 @@ int intel_plane_pin_fb(struct intel_plane_state *plane_state,
vma = intel_fb_pin_to_dpt(&fb->base, &plane_state->view.gtt,
alignment, &plane_state->flags,
fb->dpt_vm);
fb->dpt);
if (IS_ERR(vma)) {
intel_dpt_unpin_from_ggtt(fb->dpt_vm);
i915_dpt_unpin_from_ggtt(fb->dpt);
plane_state->ggtt_vma = NULL;
return PTR_ERR(vma);
}
@ -307,7 +308,7 @@ int intel_plane_pin_fb(struct intel_plane_state *plane_state,
* The DPT object contains only one vma, and there is no VT-d
* guard, so the VMA's offset within the DPT is always 0.
*/
drm_WARN_ON(display->drm, intel_dpt_offset(plane_state->dpt_vma));
drm_WARN_ON(display->drm, i915_dpt_offset(plane_state->dpt_vma));
}
/*
@ -346,7 +347,7 @@ void intel_plane_unpin_fb(struct intel_plane_state *old_plane_state)
vma = fetch_and_zero(&old_plane_state->ggtt_vma);
if (vma)
intel_dpt_unpin_from_ggtt(fb->dpt_vm);
i915_dpt_unpin_from_ggtt(fb->dpt);
}
}

View File

@ -45,7 +45,6 @@
#include <drm/drm_fourcc.h>
#include <drm/drm_print.h>
#include "i915_vma.h"
#include "i9xx_plane_regs.h"
#include "intel_de.h"
#include "intel_display_device.h"
@ -184,7 +183,7 @@ static unsigned int skl_fbc_min_cfb_stride(struct intel_display *display,
* Wa_16011863758: icl+
* Avoid some hardware segment address miscalculation.
*/
if (DISPLAY_VER(display) >= 11)
if (intel_display_wa(display, INTEL_DISPLAY_WA_16011863758))
stride += 64;
/*
@ -950,7 +949,7 @@ static void intel_fbc_program_workarounds(struct intel_fbc *fbc)
}
/* Wa_1409120013:icl,jsl,tgl,dg1 */
if (IS_DISPLAY_VER(display, 11, 12))
if (intel_display_wa(display, INTEL_DISPLAY_WA_1409120013))
intel_de_rmw(display, ILK_DPFC_CHICKEN(fbc->id),
0, DPFC_CHICKEN_COMP_DUMMY_PIXEL);
/*
@ -958,7 +957,7 @@ static void intel_fbc_program_workarounds(struct intel_fbc *fbc)
* Fixes: Screen flicker with FBC and Package C state enabled
* Workaround: Forced SLB invalidation before start of new frame.
*/
if (intel_display_wa(display, 22014263786))
if (intel_display_wa(display, INTEL_DISPLAY_WA_22014263786))
intel_de_rmw(display, ILK_DPFC_CHICKEN(fbc->id),
0, DPFC_CHICKEN_FORCE_SLB_INVALIDATION);
@ -980,7 +979,7 @@ static void fbc_sys_cache_update_config(struct intel_display *display, u32 reg,
* Fixes: SoC hardware issue in read caching
* Workaround: disable cache read setting which is enabled by default.
*/
if (!intel_display_wa(display, 14025769978))
if (!intel_display_wa(display, INTEL_DISPLAY_WA_14025769978))
/* Cache read enable is set by default */
reg |= FBC_SYS_CACHE_READ_ENABLE;
@ -1463,7 +1462,7 @@ static void intel_fbc_update_state(struct intel_atomic_state *state,
!intel_fbc_has_fences(display));
if (plane_state->flags & PLANE_HAS_FENCE)
fbc_state->fence_id = i915_vma_fence_id(plane_state->ggtt_vma);
fbc_state->fence_id = intel_parent_vma_fence_id(display, plane_state->ggtt_vma);
else
fbc_state->fence_id = -1;
@ -1490,7 +1489,7 @@ static bool intel_fbc_is_fence_ok(const struct intel_plane_state *plane_state)
*/
return DISPLAY_VER(display) >= 9 ||
(plane_state->flags & PLANE_HAS_FENCE &&
i915_vma_fence_id(plane_state->ggtt_vma) != -1);
intel_parent_vma_fence_id(display, plane_state->ggtt_vma) != -1);
}
static bool intel_fbc_is_cfb_ok(const struct intel_plane_state *plane_state)
@ -1613,7 +1612,7 @@ static int intel_fbc_check_plane(struct intel_atomic_state *state,
return 0;
}
if (intel_display_wa(display, 16023588340)) {
if (intel_display_wa(display, INTEL_DISPLAY_WA_16023588340)) {
plane_state->no_fbc_reason = "Wa_16023588340";
return 0;
}
@ -1623,7 +1622,7 @@ static int intel_fbc_check_plane(struct intel_atomic_state *state,
* Fixes: Underrun during media decode
* Workaround: Do not enable FBC
*/
if (intel_display_wa(display, 15018326506)) {
if (intel_display_wa(display, INTEL_DISPLAY_WA_15018326506)) {
plane_state->no_fbc_reason = "Wa_15018326506";
return 0;
}

View File

@ -47,7 +47,6 @@
#include <drm/drm_managed.h>
#include <drm/drm_print.h>
#include "i915_vma.h"
#include "intel_bo.h"
#include "intel_display_core.h"
#include "intel_display_rpm.h"
@ -343,9 +342,7 @@ int intel_fbdev_driver_fbdev_probe(struct drm_fb_helper *helper,
/* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */
drm_dbg_kms(display->drm, "allocated %dx%d fb: 0x%08x\n",
fb->base.width, fb->base.height,
i915_ggtt_offset(vma));
drm_dbg_kms(display->drm, "allocated %dx%d fb\n", fb->base.width, fb->base.height);
ifbdev->fb = fb;
ifbdev->vma = vma;
ifbdev->vma_flags = flags;

View File

@ -17,28 +17,40 @@ u32 intel_fbdev_fb_pitch_align(u32 stride)
return ALIGN(stride, 64);
}
bool intel_fbdev_fb_prefer_stolen(struct drm_device *drm, unsigned int size)
{
struct drm_i915_private *i915 = to_i915(drm);
/* Skip stolen on MTL as Wa_22018444074 mitigation. */
if (IS_METEORLAKE(i915))
return false;
/*
* If the FB is too big, just don't use it since fbdev is not very
* important and we should probably use that space with FBC or other
* features.
*/
return i915->dsm.usable_size >= size * 2;
}
struct drm_gem_object *intel_fbdev_fb_bo_create(struct drm_device *drm, int size)
{
struct drm_i915_private *dev_priv = to_i915(drm);
struct drm_i915_private *i915 = to_i915(drm);
struct drm_i915_gem_object *obj;
obj = ERR_PTR(-ENODEV);
if (HAS_LMEM(dev_priv)) {
obj = i915_gem_object_create_lmem(dev_priv, size,
if (HAS_LMEM(i915)) {
obj = i915_gem_object_create_lmem(i915, size,
I915_BO_ALLOC_CONTIGUOUS |
I915_BO_ALLOC_USER);
} else {
/*
* If the FB is too big, just don't use it since fbdev is not very
* important and we should probably use that space with FBC or other
* features.
*
* Also skip stolen on MTL as Wa_22018444074 mitigation.
*/
if (!IS_METEORLAKE(dev_priv) && size * 2 < dev_priv->dsm.usable_size)
obj = i915_gem_object_create_stolen(dev_priv, size);
if (intel_fbdev_fb_prefer_stolen(drm, size))
obj = i915_gem_object_create_stolen(i915, size);
else
drm_info(drm, "Allocating fbdev: Stolen memory not preferred.\n");
if (IS_ERR(obj))
obj = i915_gem_object_create_shmem(dev_priv, size);
obj = i915_gem_object_create_shmem(i915, size);
}
if (IS_ERR(obj)) {

View File

@ -19,5 +19,6 @@ struct drm_gem_object *intel_fbdev_fb_bo_create(struct drm_device *drm, int size
void intel_fbdev_fb_bo_destroy(struct drm_gem_object *obj);
int intel_fbdev_fb_fill_info(struct drm_device *drm, struct fb_info *info,
struct drm_gem_object *obj, struct i915_vma *vma);
bool intel_fbdev_fb_prefer_stolen(struct drm_device *drm, unsigned int size);
#endif

View File

@ -8,7 +8,6 @@
#include <drm/drm_fixed.h>
#include <drm/drm_print.h>
#include "i915_reg.h"
#include "intel_atomic.h"
#include "intel_crtc.h"
#include "intel_ddi.h"

View File

@ -29,7 +29,6 @@
#include <drm/drm_print.h>
#include "i915_reg.h"
#include "intel_de.h"
#include "intel_display_irq.h"
#include "intel_display_regs.h"

View File

@ -12,6 +12,7 @@
#include "intel_display_core.h"
#include "intel_display_types.h"
#include "intel_display_utils.h"
#include "intel_display_wa.h"
#include "intel_dmc.h"
#include "intel_dmc_regs.h"
#include "intel_dsb.h"
@ -447,19 +448,11 @@ void intel_flipq_add(struct intel_crtc *crtc,
intel_flipq_sw_dmc_wake(crtc);
}
/* Wa_18034343758 */
static bool need_dmc_halt_wa(struct intel_display *display)
{
return DISPLAY_VER(display) == 20 ||
(display->platform.pantherlake &&
IS_DISPLAY_STEP(display, STEP_A0, STEP_B0));
}
void intel_flipq_wait_dmc_halt(struct intel_dsb *dsb, struct intel_crtc *crtc)
{
struct intel_display *display = to_intel_display(crtc);
if (need_dmc_halt_wa(display))
if (intel_display_wa(display, INTEL_DISPLAY_WA_18034343758))
intel_dsb_wait_usec(dsb, 2);
}
@ -467,6 +460,6 @@ void intel_flipq_unhalt_dmc(struct intel_dsb *dsb, struct intel_crtc *crtc)
{
struct intel_display *display = to_intel_display(crtc);
if (need_dmc_halt_wa(display))
if (intel_display_wa(display, INTEL_DISPLAY_WA_18034343758))
intel_dsb_reg_write(dsb, PIPEDMC_CTL(crtc->pipe), 0);
}

View File

@ -58,13 +58,13 @@
#include <drm/drm_gem.h>
#include <drm/drm_print.h>
#include "intel_bo.h"
#include "intel_display_trace.h"
#include "intel_display_types.h"
#include "intel_dp.h"
#include "intel_drrs.h"
#include "intel_fbc.h"
#include "intel_frontbuffer.h"
#include "intel_parent.h"
#include "intel_psr.h"
#include "intel_tdf.h"
@ -123,9 +123,9 @@ void intel_frontbuffer_flip(struct intel_display *display,
frontbuffer_flush(display, frontbuffer_bits, ORIGIN_FLIP);
}
void __intel_fb_invalidate(struct intel_frontbuffer *front,
enum fb_op_origin origin,
unsigned int frontbuffer_bits)
void __intel_frontbuffer_invalidate(struct intel_frontbuffer *front,
enum fb_op_origin origin,
unsigned int frontbuffer_bits)
{
struct intel_display *display = front->display;
@ -143,14 +143,14 @@ void __intel_fb_invalidate(struct intel_frontbuffer *front,
intel_fbc_invalidate(display, frontbuffer_bits, origin);
}
void __intel_fb_flush(struct intel_frontbuffer *front,
enum fb_op_origin origin,
unsigned int frontbuffer_bits)
void __intel_frontbuffer_flush(struct intel_frontbuffer *front,
enum fb_op_origin origin,
unsigned int frontbuffer_bits)
{
struct intel_display *display = front->display;
if (origin == ORIGIN_DIRTYFB)
intel_bo_frontbuffer_flush_for_display(front);
intel_parent_frontbuffer_flush_for_display(display, front);
if (origin == ORIGIN_CS) {
spin_lock(&display->fb_tracking.lock);
@ -164,18 +164,13 @@ void __intel_fb_flush(struct intel_frontbuffer *front,
frontbuffer_flush(display, frontbuffer_bits, origin);
}
static void intel_frontbuffer_ref(struct intel_frontbuffer *front)
{
intel_bo_frontbuffer_ref(front);
}
static void intel_frontbuffer_flush_work(struct work_struct *work)
{
struct intel_frontbuffer *front =
container_of(work, struct intel_frontbuffer, flush_work);
intel_frontbuffer_flush(front, ORIGIN_DIRTYFB);
intel_frontbuffer_put(front);
intel_parent_frontbuffer_put(front->display, front);
}
/**
@ -190,9 +185,9 @@ void intel_frontbuffer_queue_flush(struct intel_frontbuffer *front)
if (!front)
return;
intel_frontbuffer_ref(front);
intel_parent_frontbuffer_ref(front->display, front);
if (!schedule_work(&front->flush_work))
intel_frontbuffer_put(front);
intel_parent_frontbuffer_put(front->display, front);
}
void intel_frontbuffer_init(struct intel_frontbuffer *front, struct drm_device *drm)
@ -207,16 +202,6 @@ void intel_frontbuffer_fini(struct intel_frontbuffer *front)
drm_WARN_ON(front->display->drm, atomic_read(&front->bits));
}
struct intel_frontbuffer *intel_frontbuffer_get(struct drm_gem_object *obj)
{
return intel_bo_frontbuffer_get(obj);
}
void intel_frontbuffer_put(struct intel_frontbuffer *front)
{
intel_bo_frontbuffer_put(front);
}
/**
* intel_frontbuffer_track - update frontbuffer tracking
* @old: current buffer for the frontbuffer slots

View File

@ -66,14 +66,9 @@ struct intel_frontbuffer {
void intel_frontbuffer_flip(struct intel_display *display,
unsigned frontbuffer_bits);
void intel_frontbuffer_put(struct intel_frontbuffer *front);
struct intel_frontbuffer *
intel_frontbuffer_get(struct drm_gem_object *obj);
void __intel_fb_invalidate(struct intel_frontbuffer *front,
enum fb_op_origin origin,
unsigned int frontbuffer_bits);
void __intel_frontbuffer_invalidate(struct intel_frontbuffer *front,
enum fb_op_origin origin,
unsigned int frontbuffer_bits);
/**
* intel_frontbuffer_invalidate - invalidate frontbuffer object
@ -98,13 +93,13 @@ static inline bool intel_frontbuffer_invalidate(struct intel_frontbuffer *front,
if (!frontbuffer_bits)
return false;
__intel_fb_invalidate(front, origin, frontbuffer_bits);
__intel_frontbuffer_invalidate(front, origin, frontbuffer_bits);
return true;
}
void __intel_fb_flush(struct intel_frontbuffer *front,
enum fb_op_origin origin,
unsigned int frontbuffer_bits);
void __intel_frontbuffer_flush(struct intel_frontbuffer *front,
enum fb_op_origin origin,
unsigned int frontbuffer_bits);
/**
* intel_frontbuffer_flush - flush frontbuffer object
@ -126,7 +121,7 @@ static inline void intel_frontbuffer_flush(struct intel_frontbuffer *front,
if (!frontbuffer_bits)
return;
__intel_fb_flush(front, origin, frontbuffer_bits);
__intel_frontbuffer_flush(front, origin, frontbuffer_bits);
}
void intel_frontbuffer_queue_flush(struct intel_frontbuffer *front);

View File

@ -35,7 +35,6 @@
#include <drm/drm_print.h>
#include <drm/display/drm_hdcp_helper.h>
#include "i915_reg.h"
#include "intel_de.h"
#include "intel_display_regs.h"
#include "intel_display_types.h"
@ -251,7 +250,7 @@ static u32 get_reserved(struct intel_gmbus *bus)
preserve_bits |= GPIO_DATA_PULLUP_DISABLE | GPIO_CLOCK_PULLUP_DISABLE;
/* Wa_16025573575: the masks bits need to be preserved through out */
if (intel_display_wa(display, 16025573575))
if (intel_display_wa(display, INTEL_DISPLAY_WA_16025573575))
preserve_bits |= GPIO_CLOCK_DIR_MASK | GPIO_CLOCK_VAL_MASK |
GPIO_DATA_DIR_MASK | GPIO_DATA_VAL_MASK;
@ -343,7 +342,7 @@ intel_gpio_pre_xfer(struct i2c_adapter *adapter)
if (display->platform.pineview)
pnv_gmbus_clock_gating(display, false);
if (intel_display_wa(display, 16025573575))
if (intel_display_wa(display, INTEL_DISPLAY_WA_16025573575))
ptl_handle_mask_bits(bus, true);
set_data(bus, 1);
@ -364,7 +363,7 @@ intel_gpio_post_xfer(struct i2c_adapter *adapter)
if (display->platform.pineview)
pnv_gmbus_clock_gating(display, true);
if (intel_display_wa(display, 16025573575))
if (intel_display_wa(display, INTEL_DISPLAY_WA_16025573575))
ptl_handle_mask_bits(bus, false);
}

View File

@ -17,8 +17,8 @@
#include <drm/display/drm_hdcp_helper.h>
#include <drm/drm_print.h>
#include <drm/intel/i915_component.h>
#include <drm/intel/intel_pcode_regs.h>
#include "i915_reg.h"
#include "intel_connector.h"
#include "intel_de.h"
#include "intel_display_jiffies.h"
@ -33,7 +33,6 @@
#include "intel_hdcp_regs.h"
#include "intel_hdcp_shim.h"
#include "intel_parent.h"
#include "intel_pcode.h"
#include "intel_step.h"
#define USE_HDCP_GSC(__display) (DISPLAY_VER(__display) >= 14)
@ -76,7 +75,6 @@ static int intel_conn_to_vcpi(struct intel_atomic_state *state,
struct drm_dp_mst_topology_mgr *mgr;
struct drm_dp_mst_atomic_payload *payload;
struct drm_dp_mst_topology_state *mst_state;
int vcpi = 0;
/* For HDMI this is forced to be 0x0. For DP SST also this is 0x0. */
if (!connector->mst.port)
@ -87,15 +85,9 @@ static int intel_conn_to_vcpi(struct intel_atomic_state *state,
mst_state = to_drm_dp_mst_topology_state(mgr->base.state);
payload = drm_atomic_get_mst_payload_state(mst_state, connector->mst.port);
if (drm_WARN_ON(mgr->dev, !payload))
goto out;
return 0;
vcpi = payload->vcpi;
if (drm_WARN_ON(mgr->dev, vcpi < 0)) {
vcpi = 0;
goto out;
}
out:
return vcpi;
return payload->vcpi;
}
/*
@ -398,7 +390,7 @@ static int intel_hdcp_load_keys(struct intel_display *display)
* Mailbox interface.
*/
if (DISPLAY_VER(display) == 9 && !display->platform.broxton) {
ret = intel_pcode_write(display->drm, SKL_PCODE_LOAD_HDCP_KEYS, 1);
ret = intel_parent_pcode_write(display, SKL_PCODE_LOAD_HDCP_KEYS, 1);
if (ret) {
drm_err(display->drm,
"Failed to initiate HDCP key load (%d)\n",
@ -2239,7 +2231,7 @@ static void intel_hdcp_check_work(struct work_struct *work)
if (drm_connector_is_unregistered(&connector->base))
return;
if (!intel_hdcp2_check_link(connector))
if (!hdcp->force_hdcp14 && !intel_hdcp2_check_link(connector))
queue_delayed_work(display->wq.unordered, &hdcp->check_work,
DRM_HDCP2_CHECK_PERIOD_MS);
else if (!intel_hdcp_check_link(connector))

View File

@ -56,6 +56,7 @@
#include "intel_display_types.h"
#include "intel_display_utils.h"
#include "intel_dp.h"
#include "intel_dpll.h"
#include "intel_gmbus.h"
#include "intel_hdcp.h"
#include "intel_hdcp_regs.h"
@ -70,16 +71,14 @@
bool intel_hdmi_is_frl(u32 clock)
{
switch (clock) {
case 300000: /* 3 Gbps */
case 600000: /* 6 Gbps */
case 800000: /* 8 Gbps */
case 1000000: /* 10 Gbps */
case 1200000: /* 12 Gbps */
return true;
default:
return false;
}
u32 rates[] = { 300000, 600000, 800000, 1000000, 1200000 };
int i;
for (i = 0; i < ARRAY_SIZE(rates); i++)
if (intel_dpll_clock_matches(clock, rates[i]))
return true;
return false;
}
static void

View File

@ -5,7 +5,6 @@
#include <drm/drm_print.h>
#include "i915_reg.h"
#include "intel_de.h"
#include "intel_display_irq.h"
#include "intel_display_regs.h"

View File

@ -5,7 +5,6 @@
#include <drm/drm_print.h>
#include "i915_reg.h"
#include "intel_cx0_phy.h"
#include "intel_cx0_phy_regs.h"
#include "intel_ddi.h"
@ -14,6 +13,7 @@
#include "intel_display.h"
#include "intel_display_types.h"
#include "intel_display_utils.h"
#include "intel_dpll.h"
#include "intel_dpll_mgr.h"
#include "intel_hdmi.h"
#include "intel_lt_phy.h"
@ -60,7 +60,6 @@ struct lt_phy_params {
};
static const struct intel_lt_phy_pll_state xe3plpd_lt_dp_rbr = {
.clock = 162000,
.config = {
0x83,
0x2d,
@ -114,7 +113,6 @@ static const struct intel_lt_phy_pll_state xe3plpd_lt_dp_rbr = {
};
static const struct intel_lt_phy_pll_state xe3plpd_lt_dp_hbr1 = {
.clock = 270000,
.config = {
0x8b,
0x2d,
@ -168,7 +166,6 @@ static const struct intel_lt_phy_pll_state xe3plpd_lt_dp_hbr1 = {
};
static const struct intel_lt_phy_pll_state xe3plpd_lt_dp_hbr2 = {
.clock = 540000,
.config = {
0x93,
0x2d,
@ -222,7 +219,6 @@ static const struct intel_lt_phy_pll_state xe3plpd_lt_dp_hbr2 = {
};
static const struct intel_lt_phy_pll_state xe3plpd_lt_dp_hbr3 = {
.clock = 810000,
.config = {
0x9b,
0x2d,
@ -276,7 +272,6 @@ static const struct intel_lt_phy_pll_state xe3plpd_lt_dp_hbr3 = {
};
static const struct intel_lt_phy_pll_state xe3plpd_lt_dp_uhbr10 = {
.clock = 1000000,
.config = {
0x43,
0x2d,
@ -330,7 +325,6 @@ static const struct intel_lt_phy_pll_state xe3plpd_lt_dp_uhbr10 = {
};
static const struct intel_lt_phy_pll_state xe3plpd_lt_dp_uhbr13_5 = {
.clock = 1350000,
.config = {
0xcb,
0x2d,
@ -384,7 +378,6 @@ static const struct intel_lt_phy_pll_state xe3plpd_lt_dp_uhbr13_5 = {
};
static const struct intel_lt_phy_pll_state xe3plpd_lt_dp_uhbr20 = {
.clock = 2000000,
.config = {
0x53,
0x2d,
@ -437,19 +430,35 @@ static const struct intel_lt_phy_pll_state xe3plpd_lt_dp_uhbr20 = {
},
};
static const struct intel_lt_phy_pll_state * const xe3plpd_lt_dp_tables[] = {
&xe3plpd_lt_dp_rbr,
&xe3plpd_lt_dp_hbr1,
&xe3plpd_lt_dp_hbr2,
&xe3plpd_lt_dp_hbr3,
&xe3plpd_lt_dp_uhbr10,
&xe3plpd_lt_dp_uhbr13_5,
&xe3plpd_lt_dp_uhbr20,
NULL,
struct intel_lt_phy_pll_params {
const char *name;
bool is_hdmi;
int clock_rate;
const struct intel_lt_phy_pll_state *state;
};
#define __LT_PHY_PLL_PARAMS(__is_hdmi, __clock_rate, __state) { \
.name = __stringify(__state), \
.is_hdmi = __is_hdmi, \
.clock_rate = __clock_rate, \
.state = &__state, \
}
#define LT_PHY_PLL_HDMI_PARAMS(__clock_rate, __state) __LT_PHY_PLL_PARAMS(true, __clock_rate, __state)
#define LT_PHY_PLL_DP_PARAMS(__clock_rate, __state) __LT_PHY_PLL_PARAMS(false, __clock_rate, __state)
static const struct intel_lt_phy_pll_params xe3plpd_lt_dp_tables[] = {
LT_PHY_PLL_DP_PARAMS(162000, xe3plpd_lt_dp_rbr),
LT_PHY_PLL_DP_PARAMS(270000, xe3plpd_lt_dp_hbr1),
LT_PHY_PLL_DP_PARAMS(540000, xe3plpd_lt_dp_hbr2),
LT_PHY_PLL_DP_PARAMS(810000, xe3plpd_lt_dp_hbr3),
LT_PHY_PLL_DP_PARAMS(1000000, xe3plpd_lt_dp_uhbr10),
LT_PHY_PLL_DP_PARAMS(1350000, xe3plpd_lt_dp_uhbr13_5),
LT_PHY_PLL_DP_PARAMS(2000000, xe3plpd_lt_dp_uhbr20),
{}
};
static const struct intel_lt_phy_pll_state xe3plpd_lt_edp_2_16 = {
.clock = 216000,
.config = {
0xa3,
0x2d,
@ -503,7 +512,6 @@ static const struct intel_lt_phy_pll_state xe3plpd_lt_edp_2_16 = {
};
static const struct intel_lt_phy_pll_state xe3plpd_lt_edp_2_43 = {
.clock = 243000,
.config = {
0xab,
0x2d,
@ -557,7 +565,6 @@ static const struct intel_lt_phy_pll_state xe3plpd_lt_edp_2_43 = {
};
static const struct intel_lt_phy_pll_state xe3plpd_lt_edp_3_24 = {
.clock = 324000,
.config = {
0xb3,
0x2d,
@ -611,7 +618,6 @@ static const struct intel_lt_phy_pll_state xe3plpd_lt_edp_3_24 = {
};
static const struct intel_lt_phy_pll_state xe3plpd_lt_edp_4_32 = {
.clock = 432000,
.config = {
0xbb,
0x2d,
@ -665,7 +671,6 @@ static const struct intel_lt_phy_pll_state xe3plpd_lt_edp_4_32 = {
};
static const struct intel_lt_phy_pll_state xe3plpd_lt_edp_6_75 = {
.clock = 675000,
.config = {
0xdb,
0x2d,
@ -718,21 +723,20 @@ static const struct intel_lt_phy_pll_state xe3plpd_lt_edp_6_75 = {
},
};
static const struct intel_lt_phy_pll_state * const xe3plpd_lt_edp_tables[] = {
&xe3plpd_lt_dp_rbr,
&xe3plpd_lt_edp_2_16,
&xe3plpd_lt_edp_2_43,
&xe3plpd_lt_dp_hbr1,
&xe3plpd_lt_edp_3_24,
&xe3plpd_lt_edp_4_32,
&xe3plpd_lt_dp_hbr2,
&xe3plpd_lt_edp_6_75,
&xe3plpd_lt_dp_hbr3,
NULL,
static const struct intel_lt_phy_pll_params xe3plpd_lt_edp_tables[] = {
LT_PHY_PLL_DP_PARAMS(162000, xe3plpd_lt_dp_rbr),
LT_PHY_PLL_DP_PARAMS(216000, xe3plpd_lt_edp_2_16),
LT_PHY_PLL_DP_PARAMS(243000, xe3plpd_lt_edp_2_43),
LT_PHY_PLL_DP_PARAMS(270000, xe3plpd_lt_dp_hbr1),
LT_PHY_PLL_DP_PARAMS(324000, xe3plpd_lt_edp_3_24),
LT_PHY_PLL_DP_PARAMS(432000, xe3plpd_lt_edp_4_32),
LT_PHY_PLL_DP_PARAMS(540000, xe3plpd_lt_dp_hbr2),
LT_PHY_PLL_DP_PARAMS(675000, xe3plpd_lt_edp_6_75),
LT_PHY_PLL_DP_PARAMS(810000, xe3plpd_lt_dp_hbr3),
{}
};
static const struct intel_lt_phy_pll_state xe3plpd_lt_hdmi_252 = {
.clock = 25200,
.config = {
0x84,
0x2d,
@ -785,62 +789,7 @@ static const struct intel_lt_phy_pll_state xe3plpd_lt_hdmi_252 = {
},
};
static const struct intel_lt_phy_pll_state xe3plpd_lt_hdmi_272 = {
.clock = 27200,
.config = {
0x84,
0x2d,
0x0,
},
.addr_msb = {
0x87,
0x87,
0x87,
0x87,
0x88,
0x88,
0x88,
0x88,
0x88,
0x88,
0x88,
0x88,
0x88,
},
.addr_lsb = {
0x10,
0x0c,
0x14,
0xe4,
0x0c,
0x10,
0x14,
0x18,
0x48,
0x40,
0x4c,
0x24,
0x44,
},
.data = {
{ 0x0, 0x4c, 0x2, 0x0 },
{ 0x0b, 0x15, 0x26, 0xa0 },
{ 0x60, 0x0, 0x0, 0x0 },
{ 0x8, 0x4, 0x96, 0x28 },
{ 0xfa, 0x0c, 0x84, 0x11 },
{ 0x80, 0x0f, 0xd9, 0x53 },
{ 0x86, 0x0, 0x0, 0x0 },
{ 0x1, 0xa0, 0x1, 0x0 },
{ 0x4b, 0x0, 0x0, 0x0 },
{ 0x28, 0x0, 0x0, 0x0 },
{ 0x0, 0x14, 0x2a, 0x14 },
{ 0x0, 0x0, 0x0, 0x0 },
{ 0x0, 0x0, 0x0, 0x0 },
},
};
static const struct intel_lt_phy_pll_state xe3plpd_lt_hdmi_742p5 = {
.clock = 74250,
.config = {
0x84,
0x2d,
@ -894,7 +843,6 @@ static const struct intel_lt_phy_pll_state xe3plpd_lt_hdmi_742p5 = {
};
static const struct intel_lt_phy_pll_state xe3plpd_lt_hdmi_1p485 = {
.clock = 148500,
.config = {
0x84,
0x2d,
@ -948,7 +896,6 @@ static const struct intel_lt_phy_pll_state xe3plpd_lt_hdmi_1p485 = {
};
static const struct intel_lt_phy_pll_state xe3plpd_lt_hdmi_5p94 = {
.clock = 594000,
.config = {
0x84,
0x2d,
@ -1001,13 +948,12 @@ static const struct intel_lt_phy_pll_state xe3plpd_lt_hdmi_5p94 = {
},
};
static const struct intel_lt_phy_pll_state * const xe3plpd_lt_hdmi_tables[] = {
&xe3plpd_lt_hdmi_252,
&xe3plpd_lt_hdmi_272,
&xe3plpd_lt_hdmi_742p5,
&xe3plpd_lt_hdmi_1p485,
&xe3plpd_lt_hdmi_5p94,
NULL,
static const struct intel_lt_phy_pll_params xe3plpd_lt_hdmi_tables[] = {
LT_PHY_PLL_HDMI_PARAMS(25200, xe3plpd_lt_hdmi_252),
LT_PHY_PLL_HDMI_PARAMS(74250, xe3plpd_lt_hdmi_742p5),
LT_PHY_PLL_HDMI_PARAMS(148500, xe3plpd_lt_hdmi_1p485),
LT_PHY_PLL_HDMI_PARAMS(594000, xe3plpd_lt_hdmi_5p94),
{}
};
static u8 intel_lt_phy_get_owned_lane_mask(struct intel_encoder *encoder)
@ -1106,7 +1052,7 @@ static int __intel_lt_phy_p2p_write_once(struct intel_encoder *encoder,
* This is the time PHY takes to settle down after programming the PHY.
*/
udelay(150);
intel_clear_response_ready_flag(encoder, lane);
intel_cx0_clear_response_ready_flag(encoder, lane);
intel_lt_phy_clear_status_p2p(encoder, lane);
return 0;
@ -1346,7 +1292,7 @@ static void intel_lt_phy_transaction_end(struct intel_encoder *encoder, struct r
intel_display_power_put(display, POWER_DOMAIN_DC_OFF, wakeref);
}
static const struct intel_lt_phy_pll_state * const *
static const struct intel_lt_phy_pll_params *
intel_lt_phy_pll_tables_get(struct intel_crtc_state *crtc_state,
struct intel_encoder *encoder)
{
@ -1680,7 +1626,8 @@ intel_lt_phy_calculate_hdmi_state(struct intel_lt_phy_pll_state *lt_state,
}
static int
intel_lt_phy_calc_hdmi_port_clock(const struct intel_crtc_state *crtc_state)
intel_lt_phy_calc_hdmi_port_clock(struct intel_display *display,
const struct intel_lt_phy_pll_state *lt_state)
{
#define REGVAL(i) ( \
(lt_state->data[i][3]) | \
@ -1689,9 +1636,6 @@ intel_lt_phy_calc_hdmi_port_clock(const struct intel_crtc_state *crtc_state)
(lt_state->data[i][0] << 24) \
)
struct intel_display *display = to_intel_display(crtc_state);
const struct intel_lt_phy_pll_state *lt_state =
&crtc_state->dpll_hw_state.ltpll;
int clk = 0;
u32 d8, pll_reg_5, pll_reg_3, pll_reg_57, m2div_frac, m2div_int;
u64 temp0, temp1;
@ -1737,7 +1681,7 @@ intel_lt_phy_calc_hdmi_port_clock(const struct intel_crtc_state *crtc_state)
if (d8 == 0) {
drm_WARN_ON(display->drm,
"Invalid port clock using lowest HDMI portclock\n");
return xe3plpd_lt_hdmi_252.clock;
return xe3plpd_lt_hdmi_tables[0].clock_rate;
}
m2div_int = (pll_reg_3 & REG_GENMASK(14, 5)) >> 5;
temp0 = ((u64)m2div_frac * REF_CLK_KHZ) >> 32;
@ -1749,13 +1693,10 @@ intel_lt_phy_calc_hdmi_port_clock(const struct intel_crtc_state *crtc_state)
}
int
intel_lt_phy_calc_port_clock(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
intel_lt_phy_calc_port_clock(struct intel_display *display,
const struct intel_lt_phy_pll_state *lt_state)
{
struct intel_display *display = to_intel_display(encoder);
int clk;
const struct intel_lt_phy_pll_state *lt_state =
&crtc_state->dpll_hw_state.ltpll;
u8 mode, rate;
mode = REG_FIELD_GET8(LT_PHY_VDR_MODE_ENCODING_MASK,
@ -1771,10 +1712,10 @@ intel_lt_phy_calc_port_clock(struct intel_encoder *encoder,
lt_state->config[0]);
clk = intel_lt_phy_get_dp_clock(rate);
} else if (mode == MODE_HDMI_20) {
clk = intel_lt_phy_calc_hdmi_port_clock(crtc_state);
clk = intel_lt_phy_calc_hdmi_port_clock(display, lt_state);
} else {
drm_WARN_ON(display->drm, "Unsupported LT PHY Mode!\n");
clk = xe3plpd_lt_hdmi_252.clock;
clk = 25200;
}
return clk;
@ -1784,16 +1725,20 @@ int
intel_lt_phy_pll_calc_state(struct intel_crtc_state *crtc_state,
struct intel_encoder *encoder)
{
const struct intel_lt_phy_pll_state * const *tables;
struct intel_display *display = to_intel_display(crtc_state);
const struct intel_lt_phy_pll_params *tables;
int i;
tables = intel_lt_phy_pll_tables_get(crtc_state, encoder);
if (!tables)
return -EINVAL;
for (i = 0; tables[i]; i++) {
if (crtc_state->port_clock == tables[i]->clock) {
crtc_state->dpll_hw_state.ltpll = *tables[i];
for (i = 0; tables[i].name; i++) {
int clock = intel_lt_phy_calc_port_clock(display, tables[i].state);
drm_WARN_ON(display->drm, !intel_dpll_clock_matches(clock, tables[i].clock_rate));
if (intel_dpll_clock_matches(crtc_state->port_clock, clock)) {
crtc_state->dpll_hw_state.ltpll = *tables[i].state;
if (intel_crtc_has_dp_encoder(crtc_state)) {
if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP))
crtc_state->dpll_hw_state.ltpll.config[2] = 1;
@ -2212,6 +2157,9 @@ bool
intel_lt_phy_pll_compare_hw_state(const struct intel_lt_phy_pll_state *a,
const struct intel_lt_phy_pll_state *b)
{
if (a->tbt_mode || b->tbt_mode)
return true;
/*
* With LT PHY values other than VDR0_CONFIG and VDR2_CONFIG are
* unreliable. They cannot always be read back since internally
@ -2254,8 +2202,6 @@ void intel_lt_phy_pll_readout_hw_state(struct intel_encoder *encoder,
LT_PHY_VDR_X_DATAY(i, j));
}
pll_state->clock =
intel_lt_phy_calc_port_clock(encoder, crtc_state);
intel_lt_phy_transaction_end(encoder, wakeref);
}
@ -2319,3 +2265,66 @@ void intel_xe3plpd_pll_disable(struct intel_encoder *encoder)
intel_lt_phy_pll_disable(encoder);
}
static void intel_lt_phy_pll_verify_clock(struct intel_display *display,
int precomputed_clock,
const char *pll_state_name,
const struct intel_lt_phy_pll_state *pll_state,
bool is_precomputed_state)
{
struct drm_printer p;
int clock;
clock = intel_lt_phy_calc_port_clock(display, pll_state);
if (intel_dpll_clock_matches(clock, precomputed_clock))
return;
drm_warn(display->drm,
"PLL state %s (%s): clock difference too high: computed %d, pre-computed %d\n",
pll_state_name,
is_precomputed_state ? "precomputed" : "computed",
clock, precomputed_clock);
if (!drm_debug_enabled(DRM_UT_KMS))
return;
p = drm_dbg_printer(display->drm, DRM_UT_KMS, NULL);
drm_printf(&p, "PLL state %s (%s):\n",
pll_state_name,
is_precomputed_state ? "precomputed" : "computed");
intel_lt_phy_dump_hw_state(display, pll_state);
}
static void intel_lt_phy_pll_verify_params(struct intel_display *display,
const struct intel_lt_phy_pll_params *pll_params)
{
struct intel_lt_phy_pll_state pll_state;
intel_lt_phy_pll_verify_clock(display, pll_params->clock_rate, pll_params->name, pll_params->state, true);
if (!pll_params->is_hdmi)
return;
if (intel_lt_phy_calculate_hdmi_state(&pll_state, pll_params->clock_rate) != 0)
return;
intel_lt_phy_pll_verify_clock(display, pll_params->clock_rate, pll_params->name, &pll_state, false);
}
static void intel_lt_phy_pll_verify_tables(struct intel_display *display,
const struct intel_lt_phy_pll_params *tables)
{
int i;
for (i = 0; tables[i].name; i++)
intel_lt_phy_pll_verify_params(display, &tables[i]);
}
void intel_lt_phy_verify_plls(struct intel_display *display)
{
intel_lt_phy_pll_verify_tables(display, xe3plpd_lt_dp_tables);
intel_lt_phy_pll_verify_tables(display, xe3plpd_lt_edp_tables);
intel_lt_phy_pll_verify_tables(display, xe3plpd_lt_hdmi_tables);
}

View File

@ -21,8 +21,8 @@ void intel_lt_phy_pll_disable(struct intel_encoder *encoder);
int
intel_lt_phy_pll_calc_state(struct intel_crtc_state *crtc_state,
struct intel_encoder *encoder);
int intel_lt_phy_calc_port_clock(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state);
int intel_lt_phy_calc_port_clock(struct intel_display *display,
const struct intel_lt_phy_pll_state *lt_state);
void intel_lt_phy_set_signal_levels(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state);
void intel_lt_phy_dump_hw_state(struct intel_display *display,
@ -41,5 +41,6 @@ intel_lt_phy_calculate_hdmi_state(struct intel_lt_phy_pll_state *lt_state,
void intel_xe3plpd_pll_enable(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state);
void intel_xe3plpd_pll_disable(struct intel_encoder *encoder);
void intel_lt_phy_verify_plls(struct intel_display *display);
#endif /* __INTEL_LT_PHY_H__ */

View File

@ -6,12 +6,12 @@
#ifndef __INTEL_LT_PHY_REGS_H__
#define __INTEL_LT_PHY_REGS_H__
#define XE3PLPD_MSGBUS_TIMEOUT_FAST_US 500
#define XE3PLPD_MSGBUS_TIMEOUT_FAST_US 500
#define XE3PLPD_MACCLK_TURNON_LATENCY_MS 2
#define XE3PLPD_MACCLK_TURNOFF_LATENCY_US 1
#define XE3PLPD_MACCLK_TURNOFF_LATENCY_US 10
#define XE3PLPD_RATE_CALIB_DONE_LATENCY_MS 1
#define XE3PLPD_RESET_START_LATENCY_US 10
#define XE3PLPD_PWRDN_TO_RDY_LATENCY_US 4
#define XE3PLPD_RESET_START_LATENCY_US 10
#define XE3PLPD_PWRDN_TO_RDY_LATENCY_US 10
#define XE3PLPD_RESET_END_LATENCY_MS 2
/* LT Phy MAC Register */

View File

@ -11,7 +11,6 @@
#include <drm/drm_print.h>
#include <drm/drm_vblank.h>
#include "i915_reg.h"
#include "i9xx_wm.h"
#include "intel_atomic.h"
#include "intel_bw.h"
@ -26,6 +25,7 @@
#include "intel_display_power.h"
#include "intel_display_regs.h"
#include "intel_display_types.h"
#include "intel_display_wa.h"
#include "intel_dmc.h"
#include "intel_fifo_underrun.h"
#include "intel_modeset_setup.h"
@ -914,7 +914,7 @@ static void intel_early_display_was(struct intel_display *display)
* Display WA #1185 WaDisableDARBFClkGating:glk,icl,ehl,tgl
* Also known as Wa_14010480278.
*/
if (IS_DISPLAY_VER(display, 10, 12))
if (intel_display_wa(display, INTEL_DISPLAY_WA_14010480278))
intel_de_rmw(display, GEN9_CLKGATE_DIS_0, 0, DARBF_GATING_DIS);
/*

View File

@ -0,0 +1,15 @@
/* SPDX-License-Identifier: MIT */
/* Copyright © 2026 Intel Corporation */
#ifndef _INTEL_OPROM_REGS_H_
#define _INTEL_OPROM_REGS_H_
#define PRIMARY_SPI_TRIGGER _MMIO(0x102040)
#define PRIMARY_SPI_ADDRESS _MMIO(0x102080)
#define PRIMARY_SPI_REGIONID _MMIO(0x102084)
#define SPI_STATIC_REGIONS _MMIO(0x102090)
#define OPTIONROM_SPI_REGIONID_MASK REG_GENMASK(7, 0)
#define OROM_OFFSET _MMIO(0x1020c0)
#define OROM_OFFSET_MASK REG_GENMASK(20, 16)
#endif

View File

@ -27,24 +27,16 @@
*/
#include <drm/drm_fourcc.h>
#include <drm/drm_gem.h>
#include <drm/drm_print.h>
#include "gem/i915_gem_internal.h"
#include "gem/i915_gem_object_frontbuffer.h"
#include "gem/i915_gem_pm.h"
#include "gt/intel_gpu_commands.h"
#include "gt/intel_ring.h"
#include "i915_drv.h"
#include "i915_reg.h"
#include "intel_color_regs.h"
#include "intel_de.h"
#include "intel_display_regs.h"
#include "intel_display_types.h"
#include "intel_frontbuffer.h"
#include "intel_overlay.h"
#include "intel_pci_config.h"
#include "intel_parent.h"
#include "intel_pfit_regs.h"
/* Limits for overlay size. According to intel doc, the real limits are:
@ -121,9 +113,6 @@
#define RGB8I_TO_COLORKEY(c) \
((((c) & 0xff) << 16) | (((c) & 0xff) << 8) | (((c) & 0xff) << 0))
/* overlay flip addr flag */
#define OFC_UPDATE 0x1
/* polyphase filter coefficients */
#define N_HORIZ_Y_TAPS 5
#define N_VERT_Y_TAPS 3
@ -189,312 +178,16 @@ struct overlay_registers {
struct intel_overlay {
struct intel_display *display;
struct intel_context *context;
struct intel_crtc *crtc;
struct i915_vma *vma;
struct i915_vma *old_vma;
struct intel_frontbuffer *frontbuffer;
bool active;
bool pfit_active;
u32 pfit_vscale_ratio; /* shifted-point number, (1<<12) == 1.0 */
u32 color_key:24;
u32 color_key_enabled:1;
u32 brightness, contrast, saturation;
u32 old_xscale, old_yscale;
/* register access */
struct drm_i915_gem_object *reg_bo;
struct overlay_registers __iomem *regs;
u32 flip_addr;
/* flip handling */
struct i915_active last_flip;
void (*flip_complete)(struct intel_overlay *ovl);
};
static void i830_overlay_clock_gating(struct intel_display *display,
bool enable)
{
struct pci_dev *pdev = to_pci_dev(display->drm->dev);
u8 val;
/* WA_OVERLAY_CLKGATE:alm */
if (enable)
intel_de_write(display, DSPCLK_GATE_D, 0);
else
intel_de_write(display, DSPCLK_GATE_D, OVRUNIT_CLOCK_GATE_DISABLE);
/* WA_DISABLE_L2CACHE_CLOCK_GATING:alm */
pci_bus_read_config_byte(pdev->bus,
PCI_DEVFN(0, 0), I830_CLOCK_GATE, &val);
if (enable)
val &= ~I830_L2_CACHE_CLOCK_GATE_DISABLE;
else
val |= I830_L2_CACHE_CLOCK_GATE_DISABLE;
pci_bus_write_config_byte(pdev->bus,
PCI_DEVFN(0, 0), I830_CLOCK_GATE, val);
}
static struct i915_request *
alloc_request(struct intel_overlay *overlay, void (*fn)(struct intel_overlay *))
{
struct i915_request *rq;
int err;
overlay->flip_complete = fn;
rq = i915_request_create(overlay->context);
if (IS_ERR(rq))
return rq;
err = i915_active_add_request(&overlay->last_flip, rq);
if (err) {
i915_request_add(rq);
return ERR_PTR(err);
}
return rq;
}
/* overlay needs to be disable in OCMD reg */
static int intel_overlay_on(struct intel_overlay *overlay)
{
struct intel_display *display = overlay->display;
struct i915_request *rq;
u32 *cs;
drm_WARN_ON(display->drm, overlay->active);
rq = alloc_request(overlay, NULL);
if (IS_ERR(rq))
return PTR_ERR(rq);
cs = intel_ring_begin(rq, 4);
if (IS_ERR(cs)) {
i915_request_add(rq);
return PTR_ERR(cs);
}
overlay->active = true;
if (display->platform.i830)
i830_overlay_clock_gating(display, false);
*cs++ = MI_OVERLAY_FLIP | MI_OVERLAY_ON;
*cs++ = overlay->flip_addr | OFC_UPDATE;
*cs++ = MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP;
*cs++ = MI_NOOP;
intel_ring_advance(rq, cs);
i915_request_add(rq);
return i915_active_wait(&overlay->last_flip);
}
static void intel_overlay_flip_prepare(struct intel_overlay *overlay,
struct i915_vma *vma)
{
struct intel_display *display = overlay->display;
enum pipe pipe = overlay->crtc->pipe;
struct intel_frontbuffer *frontbuffer = NULL;
drm_WARN_ON(display->drm, overlay->old_vma);
if (vma)
frontbuffer = intel_frontbuffer_get(intel_bo_to_drm_bo(vma->obj));
intel_frontbuffer_track(overlay->frontbuffer, frontbuffer,
INTEL_FRONTBUFFER_OVERLAY(pipe));
if (overlay->frontbuffer)
intel_frontbuffer_put(overlay->frontbuffer);
overlay->frontbuffer = frontbuffer;
overlay->old_vma = overlay->vma;
if (vma)
overlay->vma = i915_vma_get(vma);
else
overlay->vma = NULL;
}
/* overlay needs to be enabled in OCMD reg */
static int intel_overlay_continue(struct intel_overlay *overlay,
struct i915_vma *vma,
bool load_polyphase_filter)
{
struct intel_display *display = overlay->display;
struct i915_request *rq;
u32 flip_addr = overlay->flip_addr;
u32 tmp, *cs;
drm_WARN_ON(display->drm, !overlay->active);
if (load_polyphase_filter)
flip_addr |= OFC_UPDATE;
/* check for underruns */
tmp = intel_de_read(display, DOVSTA);
if (tmp & (1 << 17))
drm_dbg(display->drm, "overlay underrun, DOVSTA: %x\n", tmp);
rq = alloc_request(overlay, NULL);
if (IS_ERR(rq))
return PTR_ERR(rq);
cs = intel_ring_begin(rq, 2);
if (IS_ERR(cs)) {
i915_request_add(rq);
return PTR_ERR(cs);
}
*cs++ = MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE;
*cs++ = flip_addr;
intel_ring_advance(rq, cs);
intel_overlay_flip_prepare(overlay, vma);
i915_request_add(rq);
return 0;
}
static void intel_overlay_release_old_vma(struct intel_overlay *overlay)
{
struct intel_display *display = overlay->display;
struct i915_vma *vma;
vma = fetch_and_zero(&overlay->old_vma);
if (drm_WARN_ON(display->drm, !vma))
return;
intel_frontbuffer_flip(display, INTEL_FRONTBUFFER_OVERLAY(overlay->crtc->pipe));
i915_vma_unpin(vma);
i915_vma_put(vma);
}
static void
intel_overlay_release_old_vid_tail(struct intel_overlay *overlay)
{
intel_overlay_release_old_vma(overlay);
}
static void intel_overlay_off_tail(struct intel_overlay *overlay)
{
struct intel_display *display = overlay->display;
intel_overlay_release_old_vma(overlay);
overlay->crtc->overlay = NULL;
overlay->crtc = NULL;
overlay->active = false;
if (display->platform.i830)
i830_overlay_clock_gating(display, true);
}
static void intel_overlay_last_flip_retire(struct i915_active *active)
{
struct intel_overlay *overlay =
container_of(active, typeof(*overlay), last_flip);
if (overlay->flip_complete)
overlay->flip_complete(overlay);
}
/* overlay needs to be disabled in OCMD reg */
static int intel_overlay_off(struct intel_overlay *overlay)
{
struct intel_display *display = overlay->display;
struct i915_request *rq;
u32 *cs, flip_addr = overlay->flip_addr;
drm_WARN_ON(display->drm, !overlay->active);
/*
* According to intel docs the overlay hw may hang (when switching
* off) without loading the filter coeffs. It is however unclear whether
* this applies to the disabling of the overlay or to the switching off
* of the hw. Do it in both cases.
*/
flip_addr |= OFC_UPDATE;
rq = alloc_request(overlay, intel_overlay_off_tail);
if (IS_ERR(rq))
return PTR_ERR(rq);
cs = intel_ring_begin(rq, 6);
if (IS_ERR(cs)) {
i915_request_add(rq);
return PTR_ERR(cs);
}
/* wait for overlay to go idle */
*cs++ = MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE;
*cs++ = flip_addr;
*cs++ = MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP;
/* turn overlay off */
*cs++ = MI_OVERLAY_FLIP | MI_OVERLAY_OFF;
*cs++ = flip_addr;
*cs++ = MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP;
intel_ring_advance(rq, cs);
intel_overlay_flip_prepare(overlay, NULL);
i915_request_add(rq);
return i915_active_wait(&overlay->last_flip);
}
/*
* Recover from an interruption due to a signal.
* We have to be careful not to repeat work forever an make forward progress.
*/
static int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay)
{
return i915_active_wait(&overlay->last_flip);
}
/*
* Wait for pending overlay flip and release old frame.
* Needs to be called before the overlay register are changed
* via intel_overlay_(un)map_regs.
*/
static int intel_overlay_release_old_vid(struct intel_overlay *overlay)
{
struct intel_display *display = overlay->display;
struct i915_request *rq;
u32 *cs;
/*
* Only wait if there is actually an old frame to release to
* guarantee forward progress.
*/
if (!overlay->old_vma)
return 0;
if (!(intel_de_read(display, GEN2_ISR) & I915_OVERLAY_PLANE_FLIP_PENDING_INTERRUPT)) {
intel_overlay_release_old_vid_tail(overlay);
return 0;
}
rq = alloc_request(overlay, intel_overlay_release_old_vid_tail);
if (IS_ERR(rq))
return PTR_ERR(rq);
cs = intel_ring_begin(rq, 2);
if (IS_ERR(cs)) {
i915_request_add(rq);
return PTR_ERR(cs);
}
*cs++ = MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP;
*cs++ = MI_NOOP;
intel_ring_advance(rq, cs);
i915_request_add(rq);
return i915_active_wait(&overlay->last_flip);
}
void intel_overlay_reset(struct intel_display *display)
{
struct intel_overlay *overlay = display->overlay;
@ -505,7 +198,8 @@ void intel_overlay_reset(struct intel_display *display)
overlay->old_xscale = 0;
overlay->old_yscale = 0;
overlay->crtc = NULL;
overlay->active = false;
intel_parent_overlay_reset(display);
}
static int packed_depth_bytes(u32 format)
@ -767,34 +461,8 @@ static u32 overlay_cmd_reg(struct drm_intel_overlay_put_image *params)
return cmd;
}
static struct i915_vma *intel_overlay_pin_fb(struct drm_i915_gem_object *new_bo)
{
struct i915_gem_ww_ctx ww;
struct i915_vma *vma;
int ret;
i915_gem_ww_ctx_init(&ww, true);
retry:
ret = i915_gem_object_lock(new_bo, &ww);
if (!ret) {
vma = i915_gem_object_pin_to_display_plane(new_bo, &ww, 0, 0,
NULL, PIN_MAPPABLE);
ret = PTR_ERR_OR_ZERO(vma);
}
if (ret == -EDEADLK) {
ret = i915_gem_ww_ctx_backoff(&ww);
if (!ret)
goto retry;
}
i915_gem_ww_ctx_fini(&ww);
if (ret)
return ERR_PTR(ret);
return vma;
}
static int intel_overlay_do_put_image(struct intel_overlay *overlay,
struct drm_i915_gem_object *new_bo,
struct drm_gem_object *obj,
struct drm_intel_overlay_put_image *params)
{
struct intel_display *display = overlay->display;
@ -804,23 +472,24 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
bool scale_changed = false;
struct i915_vma *vma;
int ret, tmp_width;
u32 tmp, offset;
drm_WARN_ON(display->drm,
!drm_modeset_is_locked(&display->drm->mode_config.connection_mutex));
ret = intel_overlay_release_old_vid(overlay);
ret = intel_parent_overlay_release_old_vid(display);
if (ret != 0)
return ret;
atomic_inc(&display->restore.pending_fb_pin);
vma = intel_overlay_pin_fb(new_bo);
vma = intel_parent_overlay_pin_fb(display, obj, &offset);
if (IS_ERR(vma)) {
ret = PTR_ERR(vma);
goto out_pin_section;
}
if (!overlay->active) {
if (!intel_parent_overlay_is_active(display)) {
const struct intel_crtc_state *crtc_state =
overlay->crtc->config;
u32 oconfig = 0;
@ -836,7 +505,7 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
OCONF_PIPE_A : OCONF_PIPE_B;
iowrite32(oconfig, &regs->OCONFIG);
ret = intel_overlay_on(overlay);
ret = intel_parent_overlay_on(display, INTEL_FRONTBUFFER_OVERLAY(pipe));
if (ret != 0)
goto out_unpin;
}
@ -853,7 +522,7 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
swidth = params->src_width;
swidthsw = calc_swidthsw(display, params->offset_Y, tmp_width);
sheight = params->src_height;
iowrite32(i915_ggtt_offset(vma) + params->offset_Y, &regs->OBUF_0Y);
iowrite32(offset + params->offset_Y, &regs->OBUF_0Y);
ostride = params->stride_Y;
if (params->flags & I915_OVERLAY_YUV_PLANAR) {
@ -870,9 +539,9 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
params->src_width / uv_hscale);
swidthsw |= max(tmp_U, tmp_V) << 16;
iowrite32(i915_ggtt_offset(vma) + params->offset_U,
iowrite32(offset + params->offset_U,
&regs->OBUF_0U);
iowrite32(i915_ggtt_offset(vma) + params->offset_V,
iowrite32(offset + params->offset_V,
&regs->OBUF_0V);
ostride |= params->stride_UV << 16;
@ -889,14 +558,19 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
iowrite32(overlay_cmd_reg(params), &regs->OCMD);
ret = intel_overlay_continue(overlay, vma, scale_changed);
/* check for underruns */
tmp = intel_de_read(display, DOVSTA);
if (tmp & (1 << 17))
drm_dbg(display->drm, "overlay underrun, DOVSTA: %x\n", tmp);
ret = intel_parent_overlay_continue(display, vma, scale_changed);
if (ret)
goto out_unpin;
return 0;
out_unpin:
i915_vma_unpin(vma);
intel_parent_overlay_unpin_fb(display, vma);
out_pin_section:
atomic_dec(&display->restore.pending_fb_pin);
@ -911,20 +585,23 @@ int intel_overlay_switch_off(struct intel_overlay *overlay)
drm_WARN_ON(display->drm,
!drm_modeset_is_locked(&display->drm->mode_config.connection_mutex));
ret = intel_overlay_recover_from_interrupt(overlay);
ret = intel_parent_overlay_recover_from_interrupt(display);
if (ret != 0)
return ret;
if (!overlay->active)
if (!intel_parent_overlay_is_active(display))
return 0;
ret = intel_overlay_release_old_vid(overlay);
ret = intel_parent_overlay_release_old_vid(display);
if (ret != 0)
return ret;
iowrite32(0, &overlay->regs->OCMD);
return intel_overlay_off(overlay);
overlay->crtc->overlay = NULL;
overlay->crtc = NULL;
return intel_parent_overlay_off(display);
}
static int check_overlay_possible_on_crtc(struct intel_overlay *overlay,
@ -1006,7 +683,7 @@ static int check_overlay_scaling(struct drm_intel_overlay_put_image *rec)
static int check_overlay_src(struct intel_display *display,
struct drm_intel_overlay_put_image *rec,
struct drm_i915_gem_object *new_bo)
struct drm_gem_object *obj)
{
int uv_hscale = uv_hsubsampling(rec->flags);
int uv_vscale = uv_vsubsampling(rec->flags);
@ -1091,7 +768,7 @@ static int check_overlay_src(struct intel_display *display,
return -EINVAL;
tmp = rec->stride_Y*rec->src_height;
if (rec->offset_Y + tmp > new_bo->base.size)
if (rec->offset_Y + tmp > obj->size)
return -EINVAL;
break;
@ -1102,12 +779,12 @@ static int check_overlay_src(struct intel_display *display,
return -EINVAL;
tmp = rec->stride_Y * rec->src_height;
if (rec->offset_Y + tmp > new_bo->base.size)
if (rec->offset_Y + tmp > obj->size)
return -EINVAL;
tmp = rec->stride_UV * (rec->src_height / uv_vscale);
if (rec->offset_U + tmp > new_bo->base.size ||
rec->offset_V + tmp > new_bo->base.size)
if (rec->offset_U + tmp > obj->size ||
rec->offset_V + tmp > obj->size)
return -EINVAL;
break;
}
@ -1122,8 +799,8 @@ int intel_overlay_put_image_ioctl(struct drm_device *dev, void *data,
struct drm_intel_overlay_put_image *params = data;
struct intel_overlay *overlay;
struct drm_crtc *drmmode_crtc;
struct drm_gem_object *obj;
struct intel_crtc *crtc;
struct drm_i915_gem_object *new_bo;
int ret;
overlay = display->overlay;
@ -1145,20 +822,13 @@ int intel_overlay_put_image_ioctl(struct drm_device *dev, void *data,
return -ENOENT;
crtc = to_intel_crtc(drmmode_crtc);
new_bo = i915_gem_object_lookup(file_priv, params->bo_handle);
if (!new_bo)
return -ENOENT;
obj = intel_parent_overlay_obj_lookup(display, file_priv, params->bo_handle);
if (IS_ERR(obj))
return PTR_ERR(obj);
drm_modeset_lock_all(dev);
if (i915_gem_object_is_tiled(new_bo)) {
drm_dbg_kms(display->drm,
"buffer used for overlay image can not be tiled\n");
ret = -EINVAL;
goto out_unlock;
}
ret = intel_overlay_recover_from_interrupt(overlay);
ret = intel_parent_overlay_recover_from_interrupt(display);
if (ret != 0)
goto out_unlock;
@ -1201,7 +871,7 @@ int intel_overlay_put_image_ioctl(struct drm_device *dev, void *data,
goto out_unlock;
}
ret = check_overlay_src(display, params, new_bo);
ret = check_overlay_src(display, params, obj);
if (ret != 0)
goto out_unlock;
@ -1210,18 +880,18 @@ int intel_overlay_put_image_ioctl(struct drm_device *dev, void *data,
if (ret != 0)
goto out_unlock;
ret = intel_overlay_do_put_image(overlay, new_bo, params);
ret = intel_overlay_do_put_image(overlay, obj, params);
if (ret != 0)
goto out_unlock;
drm_modeset_unlock_all(dev);
i915_gem_object_put(new_bo);
drm_gem_object_put(obj);
return 0;
out_unlock:
drm_modeset_unlock_all(dev);
i915_gem_object_put(new_bo);
drm_gem_object_put(obj);
return ret;
}
@ -1328,7 +998,7 @@ int intel_overlay_attrs_ioctl(struct drm_device *dev, void *data,
if (DISPLAY_VER(display) == 2)
goto out_unlock;
if (overlay->active) {
if (intel_parent_overlay_is_active(display)) {
ret = -EBUSY;
goto out_unlock;
}
@ -1354,80 +1024,31 @@ int intel_overlay_attrs_ioctl(struct drm_device *dev, void *data,
return ret;
}
static int get_registers(struct intel_overlay *overlay, bool use_phys)
{
struct intel_display *display = overlay->display;
struct drm_i915_private *i915 = to_i915(display->drm);
struct drm_i915_gem_object *obj = ERR_PTR(-ENODEV);
struct i915_vma *vma;
int err;
if (!display->platform.meteorlake) /* Wa_22018444074 */
obj = i915_gem_object_create_stolen(i915, PAGE_SIZE);
if (IS_ERR(obj))
obj = i915_gem_object_create_internal(i915, PAGE_SIZE);
if (IS_ERR(obj))
return PTR_ERR(obj);
vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0, PIN_MAPPABLE);
if (IS_ERR(vma)) {
err = PTR_ERR(vma);
goto err_put_bo;
}
if (use_phys)
overlay->flip_addr = sg_dma_address(obj->mm.pages->sgl);
else
overlay->flip_addr = i915_ggtt_offset(vma);
overlay->regs = i915_vma_pin_iomap(vma);
i915_vma_unpin(vma);
if (IS_ERR(overlay->regs)) {
err = PTR_ERR(overlay->regs);
goto err_put_bo;
}
overlay->reg_bo = obj;
return 0;
err_put_bo:
i915_gem_object_put(obj);
return err;
}
void intel_overlay_setup(struct intel_display *display)
{
struct drm_i915_private *dev_priv = to_i915(display->drm);
struct intel_overlay *overlay;
struct intel_engine_cs *engine;
int ret;
void __iomem *regs;
if (!HAS_OVERLAY(display))
return;
engine = to_gt(dev_priv)->engine[RCS0];
if (!engine || !engine->kernel_context)
return;
overlay = kzalloc_obj(*overlay);
if (!overlay)
return;
regs = intel_parent_overlay_setup(display,
OVERLAY_NEEDS_PHYSICAL(display));
if (IS_ERR(regs))
goto out_free;
overlay->display = display;
overlay->context = engine->kernel_context;
overlay->regs = regs;
overlay->color_key = 0x0101fe;
overlay->color_key_enabled = true;
overlay->brightness = -19;
overlay->contrast = 75;
overlay->saturation = 146;
i915_active_init(&overlay->last_flip,
NULL, intel_overlay_last_flip_retire, 0);
ret = get_registers(overlay, OVERLAY_NEEDS_PHYSICAL(display));
if (ret)
goto out_free;
memset_io(overlay->regs, 0, sizeof(struct overlay_registers));
update_polyphase_filter(overlay->regs);
update_reg_attrs(overlay, overlay->regs);
@ -1447,110 +1068,11 @@ bool intel_overlay_available(struct intel_display *display)
void intel_overlay_cleanup(struct intel_display *display)
{
struct intel_overlay *overlay;
overlay = fetch_and_zero(&display->overlay);
if (!overlay)
if (!display->overlay)
return;
/*
* The bo's should be free'd by the generic code already.
* Furthermore modesetting teardown happens beforehand so the
* hardware should be off already.
*/
drm_WARN_ON(display->drm, overlay->active);
intel_parent_overlay_cleanup(display);
i915_gem_object_put(overlay->reg_bo);
i915_active_fini(&overlay->last_flip);
kfree(overlay);
kfree(display->overlay);
display->overlay = NULL;
}
#if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR)
struct intel_overlay_snapshot {
struct overlay_registers regs;
unsigned long base;
u32 dovsta;
u32 isr;
};
struct intel_overlay_snapshot *
intel_overlay_snapshot_capture(struct intel_display *display)
{
struct intel_overlay *overlay = display->overlay;
struct intel_overlay_snapshot *error;
if (!overlay || !overlay->active)
return NULL;
error = kmalloc_obj(*error, GFP_ATOMIC);
if (error == NULL)
return NULL;
error->dovsta = intel_de_read(display, DOVSTA);
error->isr = intel_de_read(display, GEN2_ISR);
error->base = overlay->flip_addr;
memcpy_fromio(&error->regs, overlay->regs, sizeof(error->regs));
return error;
}
void
intel_overlay_snapshot_print(const struct intel_overlay_snapshot *error,
struct drm_printer *p)
{
if (!error)
return;
drm_printf(p, "Overlay, status: 0x%08x, interrupt: 0x%08x\n",
error->dovsta, error->isr);
drm_printf(p, " Register file at 0x%08lx:\n", error->base);
#define P(x) drm_printf(p, " " #x ": 0x%08x\n", error->regs.x)
P(OBUF_0Y);
P(OBUF_1Y);
P(OBUF_0U);
P(OBUF_0V);
P(OBUF_1U);
P(OBUF_1V);
P(OSTRIDE);
P(YRGB_VPH);
P(UV_VPH);
P(HORZ_PH);
P(INIT_PHS);
P(DWINPOS);
P(DWINSZ);
P(SWIDTH);
P(SWIDTHSW);
P(SHEIGHT);
P(YRGBSCALE);
P(UVSCALE);
P(OCLRC0);
P(OCLRC1);
P(DCLRKV);
P(DCLRKM);
P(SCLRKVH);
P(SCLRKVL);
P(SCLRKEN);
P(OCONFIG);
P(OCMD);
P(OSTART_0Y);
P(OSTART_1Y);
P(OSTART_0U);
P(OSTART_0V);
P(OSTART_1U);
P(OSTART_1V);
P(OTILEOFF_0Y);
P(OTILEOFF_1Y);
P(OTILEOFF_0U);
P(OTILEOFF_0V);
P(OTILEOFF_1U);
P(OTILEOFF_1V);
P(FASTHSCALE);
P(UVSCALEV);
#undef P
}
#endif

View File

@ -13,9 +13,7 @@ struct drm_file;
struct drm_printer;
struct intel_display;
struct intel_overlay;
struct intel_overlay_snapshot;
#ifdef I915
void intel_overlay_setup(struct intel_display *display);
bool intel_overlay_available(struct intel_display *display);
void intel_overlay_cleanup(struct intel_display *display);
@ -25,51 +23,5 @@ int intel_overlay_put_image_ioctl(struct drm_device *dev, void *data,
int intel_overlay_attrs_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
void intel_overlay_reset(struct intel_display *display);
#else
static inline void intel_overlay_setup(struct intel_display *display)
{
}
static inline bool intel_overlay_available(struct intel_display *display)
{
return false;
}
static inline void intel_overlay_cleanup(struct intel_display *display)
{
}
static inline int intel_overlay_switch_off(struct intel_overlay *overlay)
{
return 0;
}
static inline int intel_overlay_put_image_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
return 0;
}
static inline int intel_overlay_attrs_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
return 0;
}
static inline void intel_overlay_reset(struct intel_display *display)
{
}
#endif
#if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR) && defined(I915)
struct intel_overlay_snapshot *
intel_overlay_snapshot_capture(struct intel_display *display);
void intel_overlay_snapshot_print(const struct intel_overlay_snapshot *error,
struct drm_printer *p);
#else
static inline struct intel_overlay_snapshot *
intel_overlay_snapshot_capture(struct intel_display *display)
{
return NULL;
}
static inline void intel_overlay_snapshot_print(const struct intel_overlay_snapshot *error,
struct drm_printer *p)
{
}
#endif
#endif /* __INTEL_OVERLAY_H__ */

View File

@ -23,6 +23,55 @@
#include "intel_display_core.h"
#include "intel_parent.h"
/* dpt */
struct intel_dpt *intel_parent_dpt_create(struct intel_display *display,
struct drm_gem_object *obj, size_t size)
{
if (display->parent->dpt)
return display->parent->dpt->create(obj, size);
return NULL;
}
void intel_parent_dpt_destroy(struct intel_display *display, struct intel_dpt *dpt)
{
if (display->parent->dpt)
display->parent->dpt->destroy(dpt);
}
void intel_parent_dpt_suspend(struct intel_display *display, struct intel_dpt *dpt)
{
if (display->parent->dpt)
display->parent->dpt->suspend(dpt);
}
void intel_parent_dpt_resume(struct intel_display *display, struct intel_dpt *dpt)
{
if (display->parent->dpt)
display->parent->dpt->resume(dpt);
}
/* frontbuffer */
struct intel_frontbuffer *intel_parent_frontbuffer_get(struct intel_display *display, struct drm_gem_object *obj)
{
return display->parent->frontbuffer->get(obj);
}
void intel_parent_frontbuffer_ref(struct intel_display *display, struct intel_frontbuffer *front)
{
display->parent->frontbuffer->ref(front);
}
void intel_parent_frontbuffer_put(struct intel_display *display, struct intel_frontbuffer *front)
{
display->parent->frontbuffer->put(front);
}
void intel_parent_frontbuffer_flush_for_display(struct intel_display *display, struct intel_frontbuffer *front)
{
display->parent->frontbuffer->flush_for_display(front);
}
/* hdcp */
ssize_t intel_parent_hdcp_gsc_msg_send(struct intel_display *display,
struct intel_hdcp_gsc_context *gsc_context,
@ -59,6 +108,82 @@ void intel_parent_irq_synchronize(struct intel_display *display)
display->parent->irq->synchronize(display->drm);
}
/* overlay */
bool intel_parent_overlay_is_active(struct intel_display *display)
{
return display->parent->overlay->is_active(display->drm);
}
int intel_parent_overlay_on(struct intel_display *display,
u32 frontbuffer_bits)
{
return display->parent->overlay->overlay_on(display->drm,
frontbuffer_bits);
}
int intel_parent_overlay_continue(struct intel_display *display,
struct i915_vma *vma,
bool load_polyphase_filter)
{
return display->parent->overlay->overlay_continue(display->drm, vma,
load_polyphase_filter);
}
int intel_parent_overlay_off(struct intel_display *display)
{
return display->parent->overlay->overlay_off(display->drm);
}
int intel_parent_overlay_recover_from_interrupt(struct intel_display *display)
{
return display->parent->overlay->recover_from_interrupt(display->drm);
}
int intel_parent_overlay_release_old_vid(struct intel_display *display)
{
return display->parent->overlay->release_old_vid(display->drm);
}
void intel_parent_overlay_reset(struct intel_display *display)
{
display->parent->overlay->reset(display->drm);
}
struct i915_vma *intel_parent_overlay_pin_fb(struct intel_display *display,
struct drm_gem_object *obj,
u32 *offset)
{
return display->parent->overlay->pin_fb(display->drm, obj, offset);
}
void intel_parent_overlay_unpin_fb(struct intel_display *display,
struct i915_vma *vma)
{
return display->parent->overlay->unpin_fb(display->drm, vma);
}
struct drm_gem_object *intel_parent_overlay_obj_lookup(struct intel_display *display,
struct drm_file *filp,
u32 handle)
{
return display->parent->overlay->obj_lookup(display->drm,
filp, handle);
}
void __iomem *intel_parent_overlay_setup(struct intel_display *display,
bool needs_physical)
{
if (drm_WARN_ON_ONCE(display->drm, !display->parent->overlay))
return ERR_PTR(-ENODEV);
return display->parent->overlay->setup(display->drm, needs_physical);
}
void intel_parent_overlay_cleanup(struct intel_display *display)
{
display->parent->overlay->cleanup(display->drm);
}
/* panic */
struct intel_panic *intel_parent_panic_alloc(struct intel_display *display)
{
@ -92,6 +217,28 @@ void intel_parent_pc8_unblock(struct intel_display *display)
display->parent->pc8->unblock(display->drm);
}
/* pcode */
int intel_parent_pcode_read(struct intel_display *display, u32 mbox, u32 *val, u32 *val1)
{
return display->parent->pcode->read(display->drm, mbox, val, val1);
}
int intel_parent_pcode_write_timeout(struct intel_display *display, u32 mbox, u32 val, int timeout_ms)
{
return display->parent->pcode->write(display->drm, mbox, val, timeout_ms);
}
int intel_parent_pcode_write(struct intel_display *display, u32 mbox, u32 val)
{
return intel_parent_pcode_write_timeout(display, mbox, val, 1);
}
int intel_parent_pcode_request(struct intel_display *display, u32 mbox, u32 request,
u32 reply_mask, u32 reply, int timeout_base_ms)
{
return display->parent->pcode->request(display->drm, mbox, request, reply_mask, reply, timeout_base_ms);
}
/* rps */
bool intel_parent_rps_available(struct intel_display *display)
{
@ -191,6 +338,15 @@ void intel_parent_stolen_node_free(struct intel_display *display, const struct i
display->parent->stolen->node_free(node);
}
/* vma */
int intel_parent_vma_fence_id(struct intel_display *display, const struct i915_vma *vma)
{
if (!display->parent->vma)
return -1;
return display->parent->vma->fence_id(vma);
}
/* generic */
void intel_parent_fence_priority_display(struct intel_display *display, struct dma_fence *fence)
{

View File

@ -7,12 +7,30 @@
#include <linux/types.h>
struct dma_fence;
struct drm_file;
struct drm_gem_object;
struct drm_scanout_buffer;
struct i915_vma;
struct intel_display;
struct intel_dpt;
struct intel_frontbuffer;
struct intel_hdcp_gsc_context;
struct intel_panic;
struct intel_stolen_node;
/* dpt */
struct intel_dpt *intel_parent_dpt_create(struct intel_display *display,
struct drm_gem_object *obj, size_t size);
void intel_parent_dpt_destroy(struct intel_display *display, struct intel_dpt *dpt);
void intel_parent_dpt_suspend(struct intel_display *display, struct intel_dpt *dpt);
void intel_parent_dpt_resume(struct intel_display *display, struct intel_dpt *dpt);
/* frontbuffer */
struct intel_frontbuffer *intel_parent_frontbuffer_get(struct intel_display *display, struct drm_gem_object *obj);
void intel_parent_frontbuffer_ref(struct intel_display *display, struct intel_frontbuffer *front);
void intel_parent_frontbuffer_put(struct intel_display *display, struct intel_frontbuffer *front);
void intel_parent_frontbuffer_flush_for_display(struct intel_display *display, struct intel_frontbuffer *front);
/* hdcp */
ssize_t intel_parent_hdcp_gsc_msg_send(struct intel_display *display,
struct intel_hdcp_gsc_context *gsc_context,
@ -27,6 +45,29 @@ void intel_parent_hdcp_gsc_context_free(struct intel_display *display,
bool intel_parent_irq_enabled(struct intel_display *display);
void intel_parent_irq_synchronize(struct intel_display *display);
/* overlay */
bool intel_parent_overlay_is_active(struct intel_display *display);
int intel_parent_overlay_on(struct intel_display *display,
u32 frontbuffer_bits);
int intel_parent_overlay_continue(struct intel_display *display,
struct i915_vma *vma,
bool load_polyphase_filter);
int intel_parent_overlay_off(struct intel_display *display);
int intel_parent_overlay_recover_from_interrupt(struct intel_display *display);
int intel_parent_overlay_release_old_vid(struct intel_display *display);
void intel_parent_overlay_reset(struct intel_display *display);
struct i915_vma *intel_parent_overlay_pin_fb(struct intel_display *display,
struct drm_gem_object *obj,
u32 *offset);
void intel_parent_overlay_unpin_fb(struct intel_display *display,
struct i915_vma *vma);
struct drm_gem_object *intel_parent_overlay_obj_lookup(struct intel_display *display,
struct drm_file *filp,
u32 handle);
void __iomem *intel_parent_overlay_setup(struct intel_display *display,
bool needs_physical);
void intel_parent_overlay_cleanup(struct intel_display *display);
/* panic */
struct intel_panic *intel_parent_panic_alloc(struct intel_display *display);
int intel_parent_panic_setup(struct intel_display *display, struct intel_panic *panic, struct drm_scanout_buffer *sb);
@ -36,6 +77,13 @@ void intel_parent_panic_finish(struct intel_display *display, struct intel_panic
void intel_parent_pc8_block(struct intel_display *display);
void intel_parent_pc8_unblock(struct intel_display *display);
/* pcode */
int intel_parent_pcode_read(struct intel_display *display, u32 mbox, u32 *val, u32 *val1);
int intel_parent_pcode_write_timeout(struct intel_display *display, u32 mbox, u32 val, int timeout_ms);
int intel_parent_pcode_write(struct intel_display *display, u32 mbox, u32 val);
int intel_parent_pcode_request(struct intel_display *display, u32 mbox, u32 request,
u32 reply_mask, u32 reply, int timeout_base_ms);
/* rps */
bool intel_parent_rps_available(struct intel_display *display);
void intel_parent_rps_boost_if_not_started(struct intel_display *display, struct dma_fence *fence);
@ -61,6 +109,9 @@ u64 intel_parent_stolen_node_size(struct intel_display *display, const struct in
struct intel_stolen_node *intel_parent_stolen_node_alloc(struct intel_display *display);
void intel_parent_stolen_node_free(struct intel_display *display, const struct intel_stolen_node *node);
/* vma */
int intel_parent_vma_fence_id(struct intel_display *display, const struct i915_vma *vma);
/* generic */
bool intel_parent_has_auxccs(struct intel_display *display);
bool intel_parent_has_fenced_regions(struct intel_display *display);

View File

@ -6,7 +6,6 @@
#include <drm/drm_print.h>
#include "g4x_dp.h"
#include "i915_reg.h"
#include "intel_crt.h"
#include "intel_crt_regs.h"
#include "intel_de.h"

View File

@ -5,7 +5,6 @@
#include <drm/drm_print.h>
#include "i915_reg.h"
#include "intel_de.h"
#include "intel_display_regs.h"
#include "intel_display_types.h"

View File

@ -15,6 +15,7 @@
#include "intel_display_regs.h"
#include "intel_display_trace.h"
#include "intel_display_utils.h"
#include "intel_display_wa.h"
#include "intel_pmdemand.h"
#include "intel_step.h"
#include "skl_watermark.h"
@ -129,9 +130,10 @@ int intel_pmdemand_init(struct intel_display *display)
&pmdemand_state->base,
&intel_pmdemand_funcs);
if (IS_DISPLAY_VERx100_STEP(display, 1400, STEP_A0, STEP_C0))
/* Wa_14016740474 */
intel_de_rmw(display, XELPD_CHICKEN_DCPR_3, 0, DMD_RSP_TIMEOUT_DISABLE);
/* Wa_14016740474 */
if (intel_display_wa(display, INTEL_DISPLAY_WA_14016740474))
intel_de_rmw(display, XELPD_CHICKEN_DCPR_3, 0,
DMD_RSP_TIMEOUT_DISABLE);
return 0;
}

View File

@ -9,7 +9,6 @@
#include <drm/drm_print.h>
#include "g4x_dp.h"
#include "i915_reg.h"
#include "intel_de.h"
#include "intel_display_jiffies.h"
#include "intel_display_power_well.h"

View File

@ -29,7 +29,6 @@
#include <drm/drm_print.h>
#include <drm/drm_vblank.h>
#include "i915_reg.h"
#include "intel_alpm.h"
#include "intel_atomic.h"
#include "intel_crtc.h"
@ -41,6 +40,7 @@
#include "intel_display_rpm.h"
#include "intel_display_types.h"
#include "intel_display_utils.h"
#include "intel_display_wa.h"
#include "intel_dmc.h"
#include "intel_dp.h"
#include "intel_dp_aux.h"
@ -1083,7 +1083,7 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp)
}
/* Wa_22012278275:adl-p */
if (display->platform.alderlake_p && IS_DISPLAY_STEP(display, STEP_A0, STEP_E0)) {
if (intel_display_wa(display, INTEL_DISPLAY_WA_22012278275)) {
static const u8 map[] = {
2, /* 5 lines */
1, /* 6 lines */
@ -1264,7 +1264,7 @@ tgl_dc3co_exitline_compute_config(struct intel_dp *intel_dp,
return;
/* Wa_16011303918:adl-p */
if (display->platform.alderlake_p && IS_DISPLAY_STEP(display, STEP_A0, STEP_B0))
if (intel_display_wa(display, INTEL_DISPLAY_WA_16011303918))
return;
/*
@ -1546,8 +1546,7 @@ static bool intel_psr2_config_valid(struct intel_dp *intel_dp,
}
/* Wa_16011181250 */
if (display->platform.rocketlake || display->platform.alderlake_s ||
display->platform.dg2) {
if (intel_display_wa(display, INTEL_DISPLAY_WA_16011181250)) {
drm_dbg_kms(display->drm,
"PSR2 is defeatured for this platform\n");
return false;
@ -1829,8 +1828,7 @@ void intel_psr_set_non_psr_pipes(struct intel_dp *intel_dp,
u8 active_pipes = 0;
/* Wa_16025596647 */
if (DISPLAY_VER(display) != 20 &&
!IS_DISPLAY_VERx100_STEP(display, 3000, STEP_A0, STEP_B0))
if (!intel_display_wa(display, INTEL_DISPLAY_WA_16025596647))
return;
/* Not needed by Panel Replay */
@ -2130,6 +2128,9 @@ static void intel_psr_enable_source(struct intel_dp *intel_dp,
intel_dmc_block_pkgc(display, intel_dp->psr.pipe, true);
intel_alpm_configure(intel_dp, crtc_state);
if (HAS_PSR_TRANS_PUSH_FRAME_CHANGE(display))
intel_vrr_psr_frame_change_enable(crtc_state);
}
static bool psr_interrupt_error_check(struct intel_dp *intel_dp)
@ -2521,9 +2522,11 @@ void intel_psr_trigger_frame_change_event(struct intel_dsb *dsb,
intel_pre_commit_crtc_state(state, crtc);
struct intel_display *display = to_intel_display(crtc);
if (crtc_state->has_psr)
intel_de_write_dsb(display, dsb,
CURSURFLIVE(display, crtc->pipe), 0);
if (!crtc_state->has_psr || intel_psr_use_trans_push(crtc_state))
return;
intel_de_write_dsb(display, dsb,
CURSURFLIVE(display, crtc->pipe), 0);
}
/**
@ -2619,6 +2622,12 @@ void intel_psr2_program_trans_man_trk_ctl(struct intel_dsb *dsb,
intel_de_write_dsb(display, dsb, PIPE_SRCSZ_ERLY_TPT(crtc->pipe),
crtc_state->pipe_srcsz_early_tpt);
if (!crtc_state->dsc.compression_enable)
return;
intel_dsc_su_et_parameters_configure(dsb, encoder, crtc_state,
drm_rect_height(&crtc_state->psr2_su_area));
}
static void psr2_man_trk_ctl_calc(struct intel_crtc_state *crtc_state,
@ -2689,11 +2698,12 @@ static void clip_area_update(struct drm_rect *overlap_damage_area,
overlap_damage_area->y2 = damage_area->y2;
}
static void intel_psr2_sel_fetch_pipe_alignment(struct intel_crtc_state *crtc_state)
static bool intel_psr2_sel_fetch_pipe_alignment(struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(crtc_state);
const struct drm_dsc_config *vdsc_cfg = &crtc_state->dsc.config;
u16 y_alignment;
bool su_area_changed = false;
/* ADLP aligns the SU region to vdsc slice height in case dsc is enabled */
if (crtc_state->dsc.compression_enable &&
@ -2702,10 +2712,18 @@ static void intel_psr2_sel_fetch_pipe_alignment(struct intel_crtc_state *crtc_st
else
y_alignment = crtc_state->su_y_granularity;
crtc_state->psr2_su_area.y1 -= crtc_state->psr2_su_area.y1 % y_alignment;
if (crtc_state->psr2_su_area.y2 % y_alignment)
if (crtc_state->psr2_su_area.y1 % y_alignment) {
crtc_state->psr2_su_area.y1 -= crtc_state->psr2_su_area.y1 % y_alignment;
su_area_changed = true;
}
if (crtc_state->psr2_su_area.y2 % y_alignment) {
crtc_state->psr2_su_area.y2 = ((crtc_state->psr2_su_area.y2 /
y_alignment) + 1) * y_alignment;
su_area_changed = true;
}
return su_area_changed;
}
/*
@ -2839,7 +2857,7 @@ int intel_psr2_sel_fetch_update(struct intel_atomic_state *state,
struct intel_crtc_state *crtc_state = intel_atomic_get_new_crtc_state(state, crtc);
struct intel_plane_state *new_plane_state, *old_plane_state;
struct intel_plane *plane;
bool full_update = false, cursor_in_su_area = false;
bool full_update = false, su_area_changed;
int i, ret;
if (!crtc_state->enable_psr2_sel_fetch)
@ -2946,15 +2964,32 @@ int intel_psr2_sel_fetch_update(struct intel_atomic_state *state,
if (ret)
return ret;
/*
* Adjust su area to cover cursor fully as necessary (early
* transport). This needs to be done after
* drm_atomic_add_affected_planes to ensure visible cursor is added into
* affected planes even when cursor is not updated by itself.
*/
intel_psr2_sel_fetch_et_alignment(state, crtc, &cursor_in_su_area);
do {
bool cursor_in_su_area;
intel_psr2_sel_fetch_pipe_alignment(crtc_state);
/*
* Adjust su area to cover cursor fully as necessary
* (early transport). This needs to be done after
* drm_atomic_add_affected_planes to ensure visible
* cursor is added into affected planes even when
* cursor is not updated by itself.
*/
intel_psr2_sel_fetch_et_alignment(state, crtc, &cursor_in_su_area);
su_area_changed = intel_psr2_sel_fetch_pipe_alignment(crtc_state);
/*
* If the cursor was outside the SU area before
* alignment, the alignment step (which only expands
* SU) may pull the cursor partially inside, so we
* must run ET alignment again to fully cover it. But
* if the cursor was already fully inside before
* alignment, expanding the SU area won't change that,
* so no further work is needed.
*/
if (cursor_in_su_area)
break;
} while (su_area_changed);
/*
* Now that we have the pipe damaged area check if it intersect with
@ -3014,6 +3049,10 @@ int intel_psr2_sel_fetch_update(struct intel_atomic_state *state,
}
skip_sel_fetch_set_loop:
if (full_update)
clip_area_update(&crtc_state->psr2_su_area, &crtc_state->pipe_src,
&crtc_state->pipe_src);
psr2_man_trk_ctl_calc(crtc_state, full_update);
crtc_state->pipe_srcsz_early_tpt =
psr2_pipe_srcsz_early_tpt_calc(crtc_state, full_update);
@ -3562,7 +3601,14 @@ static void _psr_flush_handle(struct intel_dp *intel_dp)
{
struct intel_display *display = to_intel_display(intel_dp);
if (DISPLAY_VER(display) < 20 && intel_dp->psr.psr2_sel_fetch_enabled) {
if (DISPLAY_VER(display) >= 20) {
/*
* We can use PSR exit on LunarLake onwards. Also
* using trans push mechanism to trigger Frame Change
* event requires using PSR exit.
*/
intel_psr_exit(intel_dp);
} else if (intel_dp->psr.psr2_sel_fetch_enabled) {
/* Selective fetch prior LNL */
if (intel_dp->psr.psr2_sel_fetch_cff_enabled) {
/* can we turn CFF off? */
@ -3582,16 +3628,11 @@ static void _psr_flush_handle(struct intel_dp *intel_dp)
intel_psr_configure_full_frame_update(intel_dp);
intel_psr_force_update(intel_dp);
} else if (!intel_dp->psr.psr2_sel_fetch_enabled) {
} else {
/*
* PSR1 on all platforms
* PSR2 HW tracking
* Panel Replay Full frame update
* On older platforms using PSR exit was seen causing problems
*/
intel_psr_force_update(intel_dp);
} else {
/* Selective update LNL onwards */
intel_psr_exit(intel_dp);
}
if (!intel_dp->psr.active && !intel_dp->psr.busy_frontbuffer_bits)
@ -3972,8 +4013,7 @@ static void psr_dc5_dc6_wa_work(struct work_struct *work)
*/
void intel_psr_notify_dc5_dc6(struct intel_display *display)
{
if (DISPLAY_VER(display) != 20 &&
!IS_DISPLAY_VERx100_STEP(display, 3000, STEP_A0, STEP_B0))
if (!intel_display_wa(display, INTEL_DISPLAY_WA_16025596647))
return;
schedule_work(&display->psr_dc5_dc6_wa_work);
@ -3988,8 +4028,7 @@ void intel_psr_notify_dc5_dc6(struct intel_display *display)
*/
void intel_psr_dc5_dc6_wa_init(struct intel_display *display)
{
if (DISPLAY_VER(display) != 20 &&
!IS_DISPLAY_VERx100_STEP(display, 3000, STEP_A0, STEP_B0))
if (!intel_display_wa(display, INTEL_DISPLAY_WA_16025596647))
return;
INIT_WORK(&display->psr_dc5_dc6_wa_work, psr_dc5_dc6_wa_work);
@ -4010,8 +4049,7 @@ void intel_psr_notify_pipe_change(struct intel_atomic_state *state,
struct intel_display *display = to_intel_display(state);
struct intel_encoder *encoder;
if (DISPLAY_VER(display) != 20 &&
!IS_DISPLAY_VERx100_STEP(display, 3000, STEP_A0, STEP_B0))
if (!intel_display_wa(display, INTEL_DISPLAY_WA_16025596647))
return;
for_each_intel_encoder_with_psr(display->drm, encoder) {
@ -4567,3 +4605,10 @@ int intel_psr_min_guardband(struct intel_crtc_state *crtc_state)
return psr_min_guardband;
}
bool intel_psr_use_trans_push(const struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(crtc_state);
return HAS_PSR_TRANS_PUSH_FRAME_CHANGE(display) && crtc_state->has_psr;
}

View File

@ -85,5 +85,6 @@ bool intel_psr_needs_alpm_aux_less(struct intel_dp *intel_dp,
void intel_psr_compute_config_late(struct intel_dp *intel_dp,
struct intel_crtc_state *crtc_state);
int intel_psr_min_guardband(struct intel_crtc_state *crtc_state);
bool intel_psr_use_trans_push(const struct intel_crtc_state *crtc_state);
#endif /* __INTEL_PSR_H__ */

View File

@ -7,10 +7,9 @@
#include <drm/drm_device.h>
#include "i915_reg.h"
#include "intel_rom.h"
#include "intel_uncore.h"
#include "intel_oprom_regs.h"
struct intel_rom {
/* for PCI ROM */

View File

@ -332,8 +332,6 @@ void intel_snps_hdmi_pll_compute_c10pll(struct intel_c10pll_state *pll_state, u6
c10_curve_1, c10_curve_2, prescaler_divider,
&pll_params);
pll_state->clock = pixel_clock;
pll_state->tx = 0x10;
pll_state->cmn = 0x1;
pll_state->pll[0] = REG_FIELD_PREP(C10_PLL0_DIV5CLK_EN, pll_params.mpll_div5_en) |

View File

@ -7,7 +7,6 @@
#include <drm/drm_print.h>
#include "i915_reg.h"
#include "intel_atomic.h"
#include "intel_cx0_phy_regs.h"
#include "intel_ddi.h"
@ -1845,7 +1844,7 @@ bool intel_tc_port_link_reset(struct intel_digital_port *dig_port)
if (!intel_tc_port_link_needs_reset(dig_port))
return false;
queue_delayed_work(system_unbound_wq,
queue_delayed_work(system_dfl_wq,
&to_tc_port(dig_port)->link_reset_work,
msecs_to_jiffies(2000));
@ -1926,7 +1925,7 @@ void intel_tc_port_unlock(struct intel_digital_port *dig_port)
struct intel_tc_port *tc = to_tc_port(dig_port);
if (!tc->link_refcount && tc->mode != TC_PORT_DISCONNECTED)
queue_delayed_work(system_unbound_wq, &tc->disconnect_phy_work,
queue_delayed_work(system_dfl_wq, &tc->disconnect_phy_work,
msecs_to_jiffies(1000));
mutex_unlock(&tc->lock);

View File

@ -1109,6 +1109,7 @@ struct bdb_edp {
u16 edp_dsc_disable; /* 251+ */
u16 t6_delay_support; /* 260+ */
u16 link_idle_time[16]; /* 260+ */
u16 pipe_joiner_enable; /* 261+ */
} __packed;
/*

View File

@ -35,6 +35,58 @@ bool intel_dsc_source_support(const struct intel_crtc_state *crtc_state)
return true;
}
int intel_dsc_line_slice_count(const struct intel_dsc_slice_config *config)
{
return config->pipes_per_line * config->streams_per_pipe * config->slices_per_stream;
}
bool intel_dsc_get_slice_config(struct intel_display *display,
int pipes_per_line, int slices_per_pipe,
struct intel_dsc_slice_config *config)
{
int streams_per_pipe;
/* TODO: Add support for 8 slices per pipe on TGL+. */
switch (slices_per_pipe) {
case 3:
/*
* 3 DSC Slices per pipe need 3 DSC engines, which is supported only
* with Ultrajoiner only for some platforms.
*/
if (!HAS_DSC_3ENGINES(display) || pipes_per_line != 4)
return false;
streams_per_pipe = 3;
break;
case 4:
/* TODO: Consider using 1 DSC engine stream x 4 slices instead. */
case 2:
/* TODO: Consider using 1 DSC engine stream x 2 slices instead. */
streams_per_pipe = 2;
break;
case 1:
/*
* Bigjoiner needs small joiner to be enabled.
* So there should be at least 2 dsc slices per pipe,
* whenever bigjoiner is enabled.
*/
if (pipes_per_line > 1)
return false;
streams_per_pipe = 1;
break;
default:
MISSING_CASE(slices_per_pipe);
return false;
}
config->pipes_per_line = pipes_per_line;
config->streams_per_pipe = streams_per_pipe;
config->slices_per_stream = slices_per_pipe / streams_per_pipe;
return true;
}
static bool is_pipe_dsc(struct intel_crtc *crtc, enum transcoder cpu_transcoder)
{
struct intel_display *display = to_intel_display(crtc);
@ -278,8 +330,9 @@ int intel_dsc_compute_params(struct intel_crtc_state *pipe_config)
int ret;
vdsc_cfg->pic_width = pipe_config->hw.adjusted_mode.crtc_hdisplay;
vdsc_cfg->slice_width = DIV_ROUND_UP(vdsc_cfg->pic_width,
pipe_config->dsc.slice_count);
vdsc_cfg->slice_width =
DIV_ROUND_UP(vdsc_cfg->pic_width,
intel_dsc_line_slice_count(&pipe_config->dsc.slice_config));
err = intel_dsc_slice_dimensions_valid(pipe_config, vdsc_cfg);
@ -416,7 +469,7 @@ intel_dsc_power_domain(struct intel_crtc *crtc, enum transcoder cpu_transcoder)
static int intel_dsc_get_vdsc_per_pipe(const struct intel_crtc_state *crtc_state)
{
return crtc_state->dsc.num_streams;
return crtc_state->dsc.slice_config.streams_per_pipe;
}
int intel_dsc_get_num_vdsc_instances(const struct intel_crtc_state *crtc_state)
@ -767,6 +820,29 @@ void intel_dsc_dp_pps_write(struct intel_encoder *encoder,
sizeof(dp_dsc_pps_sdp));
}
void intel_dsc_su_et_parameters_configure(struct intel_dsb *dsb, struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state, int su_lines)
{
struct intel_display *display = to_intel_display(crtc_state);
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
const struct drm_dsc_config *vdsc_cfg = &crtc_state->dsc.config;
enum pipe pipe = crtc->pipe;
int vdsc_instances_per_pipe = intel_dsc_get_vdsc_per_pipe(crtc_state);
int slice_row_per_frame = su_lines / vdsc_cfg->slice_height;
u32 val;
drm_WARN_ON_ONCE(display->drm, su_lines % vdsc_cfg->slice_height);
drm_WARN_ON_ONCE(display->drm, vdsc_instances_per_pipe > 2);
val = DSC_SUPS0_SU_SLICE_ROW_PER_FRAME(slice_row_per_frame);
val |= DSC_SUPS0_SU_PIC_HEIGHT(su_lines);
intel_de_write_dsb(display, dsb, LNL_DSC0_SU_PARAMETER_SET_0(pipe), val);
if (vdsc_instances_per_pipe == 2)
intel_de_write_dsb(display, dsb, LNL_DSC1_SU_PARAMETER_SET_0(pipe), val);
}
static i915_reg_t dss_ctl1_reg(struct intel_crtc *crtc, enum transcoder cpu_transcoder)
{
return is_pipe_dsc(crtc, cpu_transcoder) ?
@ -1018,12 +1094,13 @@ void intel_dsc_get_config(struct intel_crtc_state *crtc_state)
if (!crtc_state->dsc.compression_enable)
goto out;
/* TODO: Read out slice_config.pipes_per_line/slices_per_stream as well */
if (dss_ctl1 & JOINER_ENABLE && dss_ctl2 & (VDSC2_ENABLE | SMALL_JOINER_CONFIG_3_ENGINES))
crtc_state->dsc.num_streams = 3;
crtc_state->dsc.slice_config.streams_per_pipe = 3;
else if (dss_ctl1 & JOINER_ENABLE && dss_ctl2 & VDSC1_ENABLE)
crtc_state->dsc.num_streams = 2;
crtc_state->dsc.slice_config.streams_per_pipe = 2;
else
crtc_state->dsc.num_streams = 1;
crtc_state->dsc.slice_config.streams_per_pipe = 1;
intel_dsc_get_pps_config(crtc_state);
out:
@ -1036,8 +1113,8 @@ static void intel_vdsc_dump_state(struct drm_printer *p, int indent,
drm_printf_indent(p, indent,
"dsc-dss: compressed-bpp:" FXP_Q4_FMT ", slice-count: %d, num_streams: %d\n",
FXP_Q4_ARGS(crtc_state->dsc.compressed_bpp_x16),
crtc_state->dsc.slice_count,
crtc_state->dsc.num_streams);
intel_dsc_line_slice_count(&crtc_state->dsc.slice_config),
crtc_state->dsc.slice_config.streams_per_pipe);
}
void intel_vdsc_state_dump(struct drm_printer *p, int indent,
@ -1050,7 +1127,6 @@ void intel_vdsc_state_dump(struct drm_printer *p, int indent,
drm_dsc_dump_config(p, indent, &crtc_state->dsc.config);
}
static
int intel_dsc_get_pixel_rate_with_dsc_bubbles(struct intel_display *display,
int pixel_rate, int htotal,
int dsc_horizontal_slices)
@ -1072,7 +1148,7 @@ int intel_vdsc_min_cdclk(const struct intel_crtc_state *crtc_state)
struct intel_display *display = to_intel_display(crtc_state);
int num_vdsc_instances = intel_dsc_get_num_vdsc_instances(crtc_state);
int htotal = crtc_state->hw.adjusted_mode.crtc_htotal;
int dsc_slices = crtc_state->dsc.slice_count;
int dsc_slices = intel_dsc_line_slice_count(&crtc_state->dsc.slice_config);
int pixel_rate;
int min_cdclk;

View File

@ -13,9 +13,16 @@ struct drm_printer;
enum transcoder;
struct intel_crtc;
struct intel_crtc_state;
struct intel_display;
struct intel_dsb;
struct intel_dsc_slice_config;
struct intel_encoder;
bool intel_dsc_source_support(const struct intel_crtc_state *crtc_state);
int intel_dsc_line_slice_count(const struct intel_dsc_slice_config *config);
bool intel_dsc_get_slice_config(struct intel_display *display,
int num_joined_pipes, int slice_per_pipe,
struct intel_dsc_slice_config *config);
void intel_uncompressed_joiner_enable(const struct intel_crtc_state *crtc_state);
void intel_dsc_enable(const struct intel_crtc_state *crtc_state);
void intel_dsc_disable(const struct intel_crtc_state *crtc_state);
@ -31,9 +38,14 @@ void intel_dsc_dsi_pps_write(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state);
void intel_dsc_dp_pps_write(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state);
void intel_dsc_su_et_parameters_configure(struct intel_dsb *dsb, struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state, int su_lines);
void intel_vdsc_state_dump(struct drm_printer *p, int indent,
const struct intel_crtc_state *crtc_state);
int intel_vdsc_min_cdclk(const struct intel_crtc_state *crtc_state);
unsigned int intel_vdsc_prefill_lines(const struct intel_crtc_state *crtc_state);
int intel_dsc_get_pixel_rate_with_dsc_bubbles(struct intel_display *display,
int pixel_rate, int htotal,
int dsc_horizontal_slices);
#endif /* __INTEL_VDSC_H__ */

View File

@ -196,6 +196,18 @@
#define DSC_PPS18_NSL_BPG_OFFSET(offset) REG_FIELD_PREP(DSC_PPS18_NSL_BPG_OFFSET_MASK, offset)
#define DSC_PPS18_SL_OFFSET_ADJ(offset) REG_FIELD_PREP(DSC_PPS18_SL_OFFSET_ADJ_MASK, offset)
#define _LNL_DSC0_SU_PARAMETER_SET_0_PA 0x78064
#define _LNL_DSC1_SU_PARAMETER_SET_0_PA 0x78164
#define _LNL_DSC0_SU_PARAMETER_SET_0_PB 0x78264
#define _LNL_DSC1_SU_PARAMETER_SET_0_PB 0x78364
#define LNL_DSC0_SU_PARAMETER_SET_0(pipe) _MMIO_PIPE((pipe), _LNL_DSC0_SU_PARAMETER_SET_0_PA, _LNL_DSC0_SU_PARAMETER_SET_0_PB)
#define LNL_DSC1_SU_PARAMETER_SET_0(pipe) _MMIO_PIPE((pipe), _LNL_DSC1_SU_PARAMETER_SET_0_PA, _LNL_DSC1_SU_PARAMETER_SET_0_PB)
#define DSC_SUPS0_SU_SLICE_ROW_PER_FRAME_MASK REG_GENMASK(31, 20)
#define DSC_SUPS0_SU_SLICE_ROW_PER_FRAME(rows) REG_FIELD_PREP(DSC_SUPS0_SU_SLICE_ROW_PER_FRAME_MASK, (rows))
#define DSC_SUPS0_SU_PIC_HEIGHT_MASK REG_GENMASK(15, 0)
#define DSC_SUPS0_SU_PIC_HEIGHT(h) REG_FIELD_PREP(DSC_SUPS0_SU_PIC_HEIGHT_MASK, (h))
/* Icelake Rate Control Buffer Threshold Registers */
#define DSCA_RC_BUF_THRESH_0 _MMIO(0x6B230)
#define DSCA_RC_BUF_THRESH_0_UDW _MMIO(0x6B230 + 4)

Some files were not shown because too many files have changed in this diff Show More