mirror of
https://github.com/torvalds/linux.git
synced 2026-05-12 16:18:45 +02:00
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:
commit
d93f8ea0e5
|
|
@ -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 \
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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__ */
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
||||
|
|
|
|||
|
|
@ -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__ */
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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 & \
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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__ */
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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__ */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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__ */
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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__ */
|
||||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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__ */
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
/*
|
||||
|
|
|
|||
15
drivers/gpu/drm/i915/display/intel_oprom_regs.h
Normal file
15
drivers/gpu/drm/i915/display/intel_oprom_regs.h
Normal 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
|
||||
|
|
@ -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, ®s->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, ®s->OBUF_0Y);
|
||||
iowrite32(offset + params->offset_Y, ®s->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,
|
||||
®s->OBUF_0U);
|
||||
iowrite32(i915_ggtt_offset(vma) + params->offset_V,
|
||||
iowrite32(offset + params->offset_V,
|
||||
®s->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), ®s->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
|
||||
|
|
|
|||
|
|
@ -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__ */
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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__ */
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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) |
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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__ */
|
||||
|
|
|
|||
|
|
@ -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
Loading…
Reference in New Issue
Block a user