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

drm/i915 features for v6.13:

[airlied: fixed build problem xe->display]
Features and functionality:
- Enable BMG and LNL+ ultra joiner support to join 2+2 pipes (Ankit, Stan)
- Enable 10bpc+CCS scanout for ICL+ and fp16+CCS scanout for TGL+ (Ville)
- Use DSB for plane/color management commits (Ville)
- Expose package temperature in hwmon (Raag)
- Add more Arrow Lake (ARL) PCI IDs (Dnyaneshwar)
- Add intel_display_caps debugfs for display capabilities and params (Jani)
- Debug log detected LTTPR PHY descriptors (Imre)

Refactoring and cleanups:
- Add intel_bo abstraction to remove drm/xe -Ddrm_i915_gem_object=xe_bo hack (Jani)
- IRQ enable/disable/suspend/resume cleanups (Rodrigo)
- Pre-SKL watermark/CxSR cleanups (Ville)
- Joiner refactoring and cleanups (Ankit, Stan)
- Unify PCI ROM vs. SPI flash VBT read code paths (Ville)
- Use the common gen3+ irq code for gen2 (Ville)
- Display include cleanups (Jani)
- Conversions from drm_i915_private to struct intel_display (Jani, Ville, Suraj)
- Convert wakeref_t underlying type to struct ref_tracker * (Jani)
- Hide VLV/CHV/BXT/GLK specific PPS handling better (Jani)
- Split out DP test request handling to a separate file (Jani)
- Add display snapshot abstraction for error state (Jani)
- Register macro cleanups (Jani)
- Add irq IMR/IER/IIR register triplet abstraction (Jani)
- Remove IS_LP() (Jani)
- Remove xe compat raw reg read/write support (Jani)
- Remove unused macro parameter (He Lugang)
- Fix typos and spelling (Yan Zhen, Shen Lichuan, Colin Ian King)
- Minor code fixes (Yuesong Li, Chen Ni)
- Minor modeset refactoring (Ville)

Fixes:
- Fix a number of DP 2.1 Panel Replay issues (Jouni)
- Fix drm/xe display lockdep issues on runtime suspend/resume (Suraj)
- Fix MTL C20 PHY PLL values for UHBR20 (Dnyaneshwar)
- Fix DP FEC enabling for UHBR rates (Chaitanya)
- Fix BMG supported UHBR rates (10 and 13.5) (Arun)
- Fix BMG CCS modifiers (Juha-Pekka)
- Fix AUX IO power enabling for eDP PSR (Imre)
- Add PSR workarounds (Jouni)
- Check for too low DSC BPC (Suraj)
- Improve HDCP wakeup robustness after suspend/resume (Suraj)
- Reduce ICP+ hotplug filter to 250 us to match DP spec (Suraj)
- Fix PSR sink enable sequence (Ville)
- Fix DP colorimetry detection (Ville)
- Apply i915gm/i945gm irq C-state workaround to CRC interrupts (Ville)

Merges:
- Backmerge to fix cross-tree conflicts (Jani)
- Backmerge to get v6.12-rc1 (Jani)

Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Jani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/878quu6go9.fsf@intel.com
This commit is contained in:
Dave Airlie 2024-10-17 14:19:22 +10:00
commit f1864235dd
192 changed files with 6407 additions and 4731 deletions

View File

@ -83,3 +83,11 @@ Contact: intel-gfx@lists.freedesktop.org
Description: RO. Fan speed of device in RPM.
Only supported for particular Intel i915 graphics platforms.
What: /sys/bus/pci/drivers/i915/.../hwmon/hwmon<i>/temp1_input
Date: November 2024
KernelVersion: 6.12
Contact: intel-gfx@lists.freedesktop.org
Description: RO. GPU package temperature in millidegree Celsius.
Only supported for particular Intel i915 graphics platforms.

View File

@ -51,7 +51,8 @@ i915-y += \
i915-y += \
soc/intel_dram.o \
soc/intel_gmch.o \
soc/intel_pch.o
soc/intel_pch.o \
soc/intel_rom.o
# core library code
i915-y += \
@ -225,6 +226,7 @@ i915-y += \
display/intel_atomic_plane.o \
display/intel_audio.o \
display/intel_bios.o \
display/intel_bo.o \
display/intel_bw.o \
display/intel_cdclk.o \
display/intel_color.o \
@ -242,6 +244,7 @@ i915-y += \
display/intel_display_power_well.o \
display/intel_display_reset.o \
display/intel_display_rps.o \
display/intel_display_snapshot.o \
display/intel_display_wa.o \
display/intel_dmc.o \
display/intel_dmc_wl.o \
@ -325,6 +328,7 @@ i915-y += \
display/intel_dp_hdcp.o \
display/intel_dp_link_training.o \
display/intel_dp_mst.o \
display/intel_dp_test.o \
display/intel_dsi.o \
display/intel_dsi_dcs_backlight.o \
display/intel_dsi_vbt.o \

View File

@ -19,6 +19,7 @@
#include "intel_dp.h"
#include "intel_dp_aux.h"
#include "intel_dp_link_training.h"
#include "intel_dp_test.h"
#include "intel_dpio_phy.h"
#include "intel_encoder.h"
#include "intel_fifo_underrun.h"
@ -477,12 +478,8 @@ intel_dp_link_down(struct intel_encoder *encoder,
msleep(intel_dp->pps.panel_power_down_delay);
if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
intel_wakeref_t wakeref;
with_intel_pps_lock(intel_dp, wakeref)
intel_dp->pps.active_pipe = INVALID_PIPE;
}
if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
vlv_pps_port_disable(encoder, old_crtc_state);
}
static void g4x_dp_audio_enable(struct intel_encoder *encoder,
@ -694,7 +691,7 @@ static void intel_enable_dp(struct intel_atomic_state *state,
with_intel_pps_lock(intel_dp, wakeref) {
if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
vlv_pps_init(encoder, pipe_config);
vlv_pps_port_enable_unlocked(encoder, pipe_config);
intel_dp_enable_port(intel_dp, pipe_config);
@ -1172,12 +1169,8 @@ intel_dp_hotplug(struct intel_encoder *encoder,
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
enum intel_hotplug_state state;
if (intel_dp->compliance.test_active &&
intel_dp->compliance.test_type == DP_TEST_LINK_PHY_TEST_PATTERN) {
intel_dp_phy_test(encoder);
/* just do the PHY test and nothing else */
if (intel_dp_test_phy(intel_dp))
return INTEL_HOTPLUG_UNCHANGED;
}
state = intel_encoder_hotplug(encoder, connector);
@ -1249,20 +1242,6 @@ static void intel_dp_encoder_destroy(struct drm_encoder *encoder)
kfree(enc_to_dig_port(to_intel_encoder(encoder)));
}
enum pipe vlv_active_pipe(struct intel_dp *intel_dp)
{
struct intel_display *display = to_intel_display(intel_dp);
struct drm_i915_private *dev_priv = to_i915(display->drm);
struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
enum pipe pipe;
if (g4x_dp_port_enabled(dev_priv, intel_dp->output_reg,
encoder->port, &pipe))
return pipe;
return INVALID_PIPE;
}
static void intel_dp_encoder_reset(struct drm_encoder *encoder)
{
struct intel_display *display = to_intel_display(encoder->dev);
@ -1273,12 +1252,8 @@ static void intel_dp_encoder_reset(struct drm_encoder *encoder)
intel_dp->reset_link_params = true;
if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
intel_wakeref_t wakeref;
with_intel_pps_lock(intel_dp, wakeref)
intel_dp->pps.active_pipe = vlv_active_pipe(intel_dp);
}
if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
vlv_pps_pipe_reset(intel_dp);
intel_pps_encoder_reset(intel_dp);
}

View File

@ -19,7 +19,6 @@ struct intel_encoder;
#ifdef I915
const struct dpll *vlv_get_dpll(struct drm_i915_private *i915);
enum pipe vlv_active_pipe(struct intel_dp *intel_dp);
void g4x_dp_set_clock(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config);
bool g4x_dp_port_enabled(struct drm_i915_private *dev_priv,
@ -32,10 +31,6 @@ static inline const struct dpll *vlv_get_dpll(struct drm_i915_private *i915)
{
return NULL;
}
static inline int vlv_active_pipe(struct intel_dp *intel_dp)
{
return 0;
}
static inline void g4x_dp_set_clock(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config)
{

View File

@ -3,6 +3,8 @@
* Copyright © 2022 Intel Corporation
*/
#include <linux/debugfs.h>
#include "hsw_ips.h"
#include "i915_drv.h"
#include "i915_reg.h"

View File

@ -416,7 +416,8 @@ static int i9xx_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
return DIV_ROUND_UP(pixel_rate * num, den);
}
static void i9xx_plane_update_noarm(struct intel_plane *plane,
static void i9xx_plane_update_noarm(struct intel_dsb *dsb,
struct intel_plane *plane,
const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state)
{
@ -444,7 +445,8 @@ static void i9xx_plane_update_noarm(struct intel_plane *plane,
}
}
static void i9xx_plane_update_arm(struct intel_plane *plane,
static void i9xx_plane_update_arm(struct intel_dsb *dsb,
struct intel_plane *plane,
const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state)
{
@ -507,7 +509,8 @@ static void i9xx_plane_update_arm(struct intel_plane *plane,
intel_plane_ggtt_offset(plane_state) + dspaddr_offset);
}
static void i830_plane_update_arm(struct intel_plane *plane,
static void i830_plane_update_arm(struct intel_dsb *dsb,
struct intel_plane *plane,
const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state)
{
@ -517,11 +520,12 @@ static void i830_plane_update_arm(struct intel_plane *plane,
* Additional breakage on i830 causes register reads to return
* the last latched value instead of the last written value [ALM026].
*/
i9xx_plane_update_noarm(plane, crtc_state, plane_state);
i9xx_plane_update_arm(plane, crtc_state, plane_state);
i9xx_plane_update_noarm(dsb, plane, crtc_state, plane_state);
i9xx_plane_update_arm(dsb, plane, crtc_state, plane_state);
}
static void i9xx_plane_disable_arm(struct intel_plane *plane,
static void i9xx_plane_disable_arm(struct intel_dsb *dsb,
struct intel_plane *plane,
const struct intel_crtc_state *crtc_state)
{
struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
@ -549,7 +553,8 @@ static void i9xx_plane_disable_arm(struct intel_plane *plane,
}
static void
g4x_primary_async_flip(struct intel_plane *plane,
g4x_primary_async_flip(struct intel_dsb *dsb,
struct intel_plane *plane,
const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state,
bool async_flip)
@ -569,7 +574,8 @@ g4x_primary_async_flip(struct intel_plane *plane,
}
static void
vlv_primary_async_flip(struct intel_plane *plane,
vlv_primary_async_flip(struct intel_dsb *dsb,
struct intel_plane *plane,
const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state,
bool async_flip)

View File

@ -7,13 +7,23 @@
#include "i915_reg.h"
#include "i9xx_wm.h"
#include "intel_atomic.h"
#include "intel_bo.h"
#include "intel_display.h"
#include "intel_display_trace.h"
#include "intel_fb.h"
#include "intel_mchbar_regs.h"
#include "intel_wm.h"
#include "skl_watermark.h"
#include "vlv_sideband.h"
struct intel_watermark_params {
u16 fifo_size;
u16 max_wm;
u8 default_wm;
u8 guard_size;
u8 cacheline_size;
};
/* used in computing the new watermarks state */
struct intel_wm_config {
unsigned int num_pipes_active;
@ -136,6 +146,7 @@ static void chv_set_memory_pm5(struct drm_i915_private *dev_priv, bool enable)
static bool _intel_set_memory_cxsr(struct drm_i915_private *dev_priv, bool enable)
{
struct intel_display *display = &dev_priv->display;
bool was_enabled;
u32 val;
@ -177,7 +188,7 @@ static bool _intel_set_memory_cxsr(struct drm_i915_private *dev_priv, bool enabl
return false;
}
trace_intel_memory_cxsr(dev_priv, was_enabled, enable);
trace_intel_memory_cxsr(display, was_enabled, enable);
drm_dbg_kms(&dev_priv->drm, "memory self-refresh is %s (was %s)\n",
str_enabled_disabled(enable),
@ -695,6 +706,76 @@ static void pnv_update_wm(struct drm_i915_private *dev_priv)
}
}
static bool i9xx_wm_need_update(const struct intel_plane_state *old_plane_state,
const struct intel_plane_state *new_plane_state)
{
/* Update watermarks on tiling or size changes. */
if (old_plane_state->uapi.visible != new_plane_state->uapi.visible)
return true;
if (!old_plane_state->hw.fb || !new_plane_state->hw.fb)
return false;
if (old_plane_state->hw.fb->modifier != new_plane_state->hw.fb->modifier ||
old_plane_state->hw.rotation != new_plane_state->hw.rotation ||
drm_rect_width(&old_plane_state->uapi.src) != drm_rect_width(&new_plane_state->uapi.src) ||
drm_rect_height(&old_plane_state->uapi.src) != drm_rect_height(&new_plane_state->uapi.src) ||
drm_rect_width(&old_plane_state->uapi.dst) != drm_rect_width(&new_plane_state->uapi.dst) ||
drm_rect_height(&old_plane_state->uapi.dst) != drm_rect_height(&new_plane_state->uapi.dst))
return true;
return false;
}
static void i9xx_wm_compute(struct intel_crtc_state *new_crtc_state,
const struct intel_plane_state *old_plane_state,
const struct intel_plane_state *new_plane_state)
{
bool turn_off, turn_on, visible, was_visible, mode_changed;
mode_changed = intel_crtc_needs_modeset(new_crtc_state);
was_visible = old_plane_state->uapi.visible;
visible = new_plane_state->uapi.visible;
if (!was_visible && !visible)
return;
turn_off = was_visible && (!visible || mode_changed);
turn_on = visible && (!was_visible || mode_changed);
/* FIXME nuke when all wm code is atomic */
if (turn_on) {
new_crtc_state->update_wm_pre = true;
} else if (turn_off) {
new_crtc_state->update_wm_post = true;
} else if (i9xx_wm_need_update(old_plane_state, new_plane_state)) {
/* FIXME bollocks */
new_crtc_state->update_wm_pre = true;
new_crtc_state->update_wm_post = true;
}
}
static int i9xx_compute_watermarks(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
struct intel_crtc_state *new_crtc_state =
intel_atomic_get_new_crtc_state(state, crtc);
const struct intel_plane_state *old_plane_state;
const struct intel_plane_state *new_plane_state;
struct intel_plane *plane;
int i;
for_each_oldnew_intel_plane_in_state(state, plane, old_plane_state,
new_plane_state, i) {
if (plane->pipe != crtc->pipe)
continue;
i9xx_wm_compute(new_crtc_state, old_plane_state, new_plane_state);
}
return 0;
}
/*
* Documentation says:
* "If the line size is small, the TLB fetches can get in the way of the
@ -715,10 +796,11 @@ static unsigned int g4x_tlb_miss_wa(int fifo_size, int width, int cpp)
static void g4x_write_wm_values(struct drm_i915_private *dev_priv,
const struct g4x_wm_values *wm)
{
struct intel_display *display = &dev_priv->display;
enum pipe pipe;
for_each_pipe(dev_priv, pipe)
trace_g4x_wm(intel_crtc_for_pipe(dev_priv, pipe), wm);
trace_g4x_wm(intel_crtc_for_pipe(display, pipe), wm);
intel_uncore_write(&dev_priv->uncore, DSPFW1(dev_priv),
FW_WM(wm->sr.plane, SR) |
@ -747,10 +829,11 @@ static void g4x_write_wm_values(struct drm_i915_private *dev_priv,
static void vlv_write_wm_values(struct drm_i915_private *dev_priv,
const struct vlv_wm_values *wm)
{
struct intel_display *display = &dev_priv->display;
enum pipe pipe;
for_each_pipe(dev_priv, pipe) {
trace_vlv_wm(intel_crtc_for_pipe(dev_priv, pipe), wm);
trace_vlv_wm(intel_crtc_for_pipe(display, pipe), wm);
intel_uncore_write(&dev_priv->uncore, VLV_DDL(pipe),
(wm->ddl[pipe].plane[PLANE_CURSOR] << DDL_CURSOR_SHIFT) |
@ -1276,6 +1359,22 @@ static int g4x_compute_intermediate_wm(struct intel_atomic_state *state,
return 0;
}
static int g4x_compute_watermarks(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
int ret;
ret = g4x_compute_pipe_wm(state, crtc);
if (ret)
return ret;
ret = g4x_compute_intermediate_wm(state, crtc);
if (ret)
return ret;
return 0;
}
static void g4x_merge_wm(struct drm_i915_private *dev_priv,
struct g4x_wm_values *wm)
{
@ -1902,6 +2001,22 @@ static int vlv_compute_intermediate_wm(struct intel_atomic_state *state,
return 0;
}
static int vlv_compute_watermarks(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
int ret;
ret = vlv_compute_pipe_wm(state, crtc);
if (ret)
return ret;
ret = vlv_compute_intermediate_wm(state, crtc);
if (ret)
return ret;
return 0;
}
static void vlv_merge_wm(struct drm_i915_private *dev_priv,
struct vlv_wm_values *wm)
{
@ -2088,12 +2203,13 @@ static void i965_update_wm(struct drm_i915_private *dev_priv)
static struct intel_crtc *intel_crtc_for_plane(struct drm_i915_private *i915,
enum i9xx_plane_id i9xx_plane)
{
struct intel_display *display = &i915->display;
struct intel_plane *plane;
for_each_intel_plane(&i915->drm, plane) {
if (plane->id == PLANE_PRIMARY &&
plane->i9xx_plane == i9xx_plane)
return intel_crtc_for_pipe(i915, plane->pipe);
return intel_crtc_for_pipe(display, plane->pipe);
}
return NULL;
@ -2172,12 +2288,12 @@ static void i9xx_update_wm(struct drm_i915_private *dev_priv)
crtc = single_enabled_crtc(dev_priv);
if (IS_I915GM(dev_priv) && crtc) {
struct drm_i915_gem_object *obj;
struct drm_gem_object *obj;
obj = intel_fb_obj(crtc->base.primary->state->fb);
obj = intel_fb_bo(crtc->base.primary->state->fb);
/* self-refresh seems busted with untiled */
if (!i915_gem_object_is_tiled(obj))
if (!intel_bo_is_tiled(obj))
crtc = NULL;
}
@ -2878,8 +2994,9 @@ static int ilk_compute_intermediate_wm(struct intel_atomic_state *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_pipe_wm *a = &new_crtc_state->wm.ilk.intermediate;
const struct intel_pipe_wm *b = &old_crtc_state->wm.ilk.optimal;
struct intel_pipe_wm *intermediate = &new_crtc_state->wm.ilk.intermediate;
const struct intel_pipe_wm *optimal = &new_crtc_state->wm.ilk.optimal;
const struct intel_pipe_wm *active = &old_crtc_state->wm.ilk.optimal;
int level;
/*
@ -2887,25 +3004,29 @@ static int ilk_compute_intermediate_wm(struct intel_atomic_state *state,
* currently active watermarks to get values that are safe both before
* and after the vblank.
*/
*a = new_crtc_state->wm.ilk.optimal;
*intermediate = *optimal;
if (!new_crtc_state->hw.active ||
intel_crtc_needs_modeset(new_crtc_state) ||
state->skip_intermediate_wm)
return 0;
a->pipe_enabled |= b->pipe_enabled;
a->sprites_enabled |= b->sprites_enabled;
a->sprites_scaled |= b->sprites_scaled;
intermediate->pipe_enabled |= active->pipe_enabled;
intermediate->sprites_enabled |= active->sprites_enabled;
intermediate->sprites_scaled |= active->sprites_scaled;
for (level = 0; level < dev_priv->display.wm.num_levels; level++) {
struct intel_wm_level *a_wm = &a->wm[level];
const struct intel_wm_level *b_wm = &b->wm[level];
struct intel_wm_level *intermediate_wm = &intermediate->wm[level];
const struct intel_wm_level *active_wm = &active->wm[level];
a_wm->enable &= b_wm->enable;
a_wm->pri_val = max(a_wm->pri_val, b_wm->pri_val);
a_wm->spr_val = max(a_wm->spr_val, b_wm->spr_val);
a_wm->cur_val = max(a_wm->cur_val, b_wm->cur_val);
a_wm->fbc_val = max(a_wm->fbc_val, b_wm->fbc_val);
intermediate_wm->enable &= active_wm->enable;
intermediate_wm->pri_val = max(intermediate_wm->pri_val,
active_wm->pri_val);
intermediate_wm->spr_val = max(intermediate_wm->spr_val,
active_wm->spr_val);
intermediate_wm->cur_val = max(intermediate_wm->cur_val,
active_wm->cur_val);
intermediate_wm->fbc_val = max(intermediate_wm->fbc_val,
active_wm->fbc_val);
}
/*
@ -2914,19 +3035,35 @@ static int ilk_compute_intermediate_wm(struct intel_atomic_state *state,
* there's no safe way to transition from the old state to
* the new state, so we need to fail the atomic transaction.
*/
if (!ilk_validate_pipe_wm(dev_priv, a))
if (!ilk_validate_pipe_wm(dev_priv, intermediate))
return -EINVAL;
/*
* If our intermediate WM are identical to the final WM, then we can
* omit the post-vblank programming; only update if it's different.
*/
if (memcmp(a, &new_crtc_state->wm.ilk.optimal, sizeof(*a)) != 0)
if (memcmp(intermediate, optimal, sizeof(*intermediate)) != 0)
new_crtc_state->wm.need_postvbl_update = true;
return 0;
}
static int ilk_compute_watermarks(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
int ret;
ret = ilk_compute_pipe_wm(state, crtc);
if (ret)
return ret;
ret = ilk_compute_intermediate_wm(state, crtc);
if (ret)
return ret;
return 0;
}
/*
* Merge the watermarks from all active pipes for a specific level.
*/
@ -3265,7 +3402,7 @@ static void ilk_write_wm_values(struct drm_i915_private *dev_priv,
dev_priv->display.wm.hw = *results;
}
bool ilk_disable_lp_wm(struct drm_i915_private *dev_priv)
bool ilk_disable_cxsr(struct drm_i915_private *dev_priv)
{
return _ilk_disable_lp_wm(dev_priv, WM_DIRTY_LP_ALL);
}
@ -3716,6 +3853,7 @@ static void g4x_wm_get_hw_state(struct drm_i915_private *dev_priv)
static void g4x_wm_sanitize(struct drm_i915_private *dev_priv)
{
struct intel_display *display = &dev_priv->display;
struct intel_plane *plane;
struct intel_crtc *crtc;
@ -3723,7 +3861,7 @@ static void g4x_wm_sanitize(struct drm_i915_private *dev_priv)
for_each_intel_plane(&dev_priv->drm, plane) {
struct intel_crtc *crtc =
intel_crtc_for_pipe(dev_priv, plane->pipe);
intel_crtc_for_pipe(display, plane->pipe);
struct intel_crtc_state *crtc_state =
to_intel_crtc_state(crtc->base.state);
struct intel_plane_state *plane_state =
@ -3871,6 +4009,7 @@ static void vlv_wm_get_hw_state(struct drm_i915_private *dev_priv)
static void vlv_wm_sanitize(struct drm_i915_private *dev_priv)
{
struct intel_display *display = &dev_priv->display;
struct intel_plane *plane;
struct intel_crtc *crtc;
@ -3878,7 +4017,7 @@ static void vlv_wm_sanitize(struct drm_i915_private *dev_priv)
for_each_intel_plane(&dev_priv->drm, plane) {
struct intel_crtc *crtc =
intel_crtc_for_pipe(dev_priv, plane->pipe);
intel_crtc_for_pipe(display, plane->pipe);
struct intel_crtc_state *crtc_state =
to_intel_crtc_state(crtc->base.state);
struct intel_plane_state *plane_state =
@ -3971,16 +4110,14 @@ static void ilk_wm_get_hw_state(struct drm_i915_private *dev_priv)
}
static const struct intel_wm_funcs ilk_wm_funcs = {
.compute_pipe_wm = ilk_compute_pipe_wm,
.compute_intermediate_wm = ilk_compute_intermediate_wm,
.compute_watermarks = ilk_compute_watermarks,
.initial_watermarks = ilk_initial_watermarks,
.optimize_watermarks = ilk_optimize_watermarks,
.get_hw_state = ilk_wm_get_hw_state,
};
static const struct intel_wm_funcs vlv_wm_funcs = {
.compute_pipe_wm = vlv_compute_pipe_wm,
.compute_intermediate_wm = vlv_compute_intermediate_wm,
.compute_watermarks = vlv_compute_watermarks,
.initial_watermarks = vlv_initial_watermarks,
.optimize_watermarks = vlv_optimize_watermarks,
.atomic_update_watermarks = vlv_atomic_update_fifo,
@ -3988,26 +4125,29 @@ static const struct intel_wm_funcs vlv_wm_funcs = {
};
static const struct intel_wm_funcs g4x_wm_funcs = {
.compute_pipe_wm = g4x_compute_pipe_wm,
.compute_intermediate_wm = g4x_compute_intermediate_wm,
.compute_watermarks = g4x_compute_watermarks,
.initial_watermarks = g4x_initial_watermarks,
.optimize_watermarks = g4x_optimize_watermarks,
.get_hw_state = g4x_wm_get_hw_state_and_sanitize,
};
static const struct intel_wm_funcs pnv_wm_funcs = {
.compute_watermarks = i9xx_compute_watermarks,
.update_wm = pnv_update_wm,
};
static const struct intel_wm_funcs i965_wm_funcs = {
.compute_watermarks = i9xx_compute_watermarks,
.update_wm = i965_update_wm,
};
static const struct intel_wm_funcs i9xx_wm_funcs = {
.compute_watermarks = i9xx_compute_watermarks,
.update_wm = i9xx_update_wm,
};
static const struct intel_wm_funcs i845_wm_funcs = {
.compute_watermarks = i9xx_compute_watermarks,
.update_wm = i845_update_wm,
};

View File

@ -13,12 +13,12 @@ struct intel_crtc_state;
struct intel_plane_state;
#ifdef I915
bool ilk_disable_lp_wm(struct drm_i915_private *i915);
bool ilk_disable_cxsr(struct drm_i915_private *i915);
void ilk_wm_sanitize(struct drm_i915_private *i915);
bool intel_set_memory_cxsr(struct drm_i915_private *i915, bool enable);
void i9xx_wm_init(struct drm_i915_private *i915);
#else
static inline bool ilk_disable_lp_wm(struct drm_i915_private *i915)
static inline bool ilk_disable_cxsr(struct drm_i915_private *i915)
{
return false;
}

View File

@ -29,6 +29,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_fixed.h>
#include <drm/drm_mipi_dsi.h>
#include <drm/drm_probe_helper.h>
#include "i915_reg.h"
#include "icl_dsi.h"

View File

@ -3,6 +3,8 @@
* Copyright 2024, Intel Corporation.
*/
#include <linux/debugfs.h>
#include "intel_alpm.h"
#include "intel_crtc.h"
#include "intel_de.h"
@ -330,7 +332,7 @@ static void lnl_alpm_configure(struct intel_dp *intel_dp,
ALPM_CTL_AUX_LESS_WAKE_TIME(intel_dp->alpm_parameters.aux_less_wake_lines);
intel_de_write(display,
PORT_ALPM_CTL(display, port),
PORT_ALPM_CTL(port),
PORT_ALPM_CTL_ALPM_AUX_LESS_ENABLE |
PORT_ALPM_CTL_MAX_PHY_SWING_SETUP(15) |
PORT_ALPM_CTL_MAX_PHY_SWING_HOLD(0) |
@ -338,7 +340,7 @@ static void lnl_alpm_configure(struct intel_dp *intel_dp,
intel_dp->alpm_parameters.silence_period_sym_clocks));
intel_de_write(display,
PORT_ALPM_LFPS_CTL(display, port),
PORT_ALPM_LFPS_CTL(port),
PORT_ALPM_LFPS_CTL_LFPS_CYCLE_COUNT(10) |
PORT_ALPM_LFPS_CTL_LFPS_HALF_CYCLE_DURATION(
intel_dp->alpm_parameters.lfps_half_cycle_num_of_syms) |

View File

@ -266,7 +266,6 @@ intel_crtc_duplicate_state(struct drm_crtc *crtc)
crtc_state->update_pipe = false;
crtc_state->update_m_n = false;
crtc_state->update_lrr = false;
crtc_state->disable_lp_wm = false;
crtc_state->disable_cxsr = false;
crtc_state->update_wm_pre = false;
crtc_state->update_wm_post = false;
@ -277,7 +276,8 @@ intel_crtc_duplicate_state(struct drm_crtc *crtc)
crtc_state->fb_bits = 0;
crtc_state->update_planes = 0;
crtc_state->dsb_color_vblank = NULL;
crtc_state->dsb_color_commit = NULL;
crtc_state->dsb_commit = NULL;
crtc_state->use_dsb = false;
return &crtc_state->uapi;
}
@ -312,7 +312,7 @@ intel_crtc_destroy_state(struct drm_crtc *crtc,
struct intel_crtc_state *crtc_state = to_intel_crtc_state(state);
drm_WARN_ON(crtc->dev, crtc_state->dsb_color_vblank);
drm_WARN_ON(crtc->dev, crtc_state->dsb_color_commit);
drm_WARN_ON(crtc->dev, crtc_state->dsb_commit);
__drm_atomic_helper_crtc_destroy_state(&crtc_state->uapi);
intel_crtc_free_hw_state(crtc_state);

View File

@ -35,9 +35,10 @@
#include <linux/dma-resv.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_blend.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_gem.h>
#include <drm/drm_gem_atomic_helper.h>
#include "i915_config.h"
#include "i9xx_plane_regs.h"
@ -391,28 +392,6 @@ void intel_plane_set_invisible(struct intel_crtc_state *crtc_state,
plane_state->uapi.visible = false;
}
/* FIXME nuke when all wm code is atomic */
static bool intel_wm_need_update(const struct intel_plane_state *cur,
struct intel_plane_state *new)
{
/* Update watermarks on tiling or size changes. */
if (new->uapi.visible != cur->uapi.visible)
return true;
if (!cur->hw.fb || !new->hw.fb)
return false;
if (cur->hw.fb->modifier != new->hw.fb->modifier ||
cur->hw.rotation != new->hw.rotation ||
drm_rect_width(&new->uapi.src) != drm_rect_width(&cur->uapi.src) ||
drm_rect_height(&new->uapi.src) != drm_rect_height(&cur->uapi.src) ||
drm_rect_width(&new->uapi.dst) != drm_rect_width(&cur->uapi.dst) ||
drm_rect_height(&new->uapi.dst) != drm_rect_height(&cur->uapi.dst))
return true;
return false;
}
static bool intel_plane_is_scaled(const struct intel_plane_state *plane_state)
{
int src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
@ -492,6 +471,61 @@ static bool i9xx_must_disable_cxsr(const struct intel_crtc_state *new_crtc_state
return old_ctl != new_ctl;
}
static bool ilk_must_disable_cxsr(const struct intel_crtc_state *new_crtc_state,
const struct intel_plane_state *old_plane_state,
const struct intel_plane_state *new_plane_state)
{
struct intel_plane *plane = to_intel_plane(new_plane_state->uapi.plane);
bool old_visible = old_plane_state->uapi.visible;
bool new_visible = new_plane_state->uapi.visible;
bool modeset, turn_on;
if (plane->id == PLANE_CURSOR)
return false;
modeset = intel_crtc_needs_modeset(new_crtc_state);
turn_on = new_visible && (!old_visible || modeset);
/*
* ILK/SNB DVSACNTR/Sprite Enable
* IVB SPR_CTL/Sprite Enable
* "When in Self Refresh Big FIFO mode, a write to enable the
* plane will be internally buffered and delayed while Big FIFO
* mode is exiting."
*
* Which means that enabling the sprite can take an extra frame
* when we start in big FIFO mode (LP1+). Thus we need to drop
* down to LP0 and wait for vblank in order to make sure the
* sprite gets enabled on the next vblank after the register write.
* Doing otherwise would risk enabling the sprite one frame after
* we've already signalled flip completion. We can resume LP1+
* once the sprite has been enabled.
*
* With experimental results seems this is needed also for primary
* plane, not only sprite plane.
*/
if (turn_on)
return true;
/*
* WaCxSRDisabledForSpriteScaling:ivb
* IVB SPR_SCALE/Scaling Enable
* "Low Power watermarks must be disabled for at least one
* frame before enabling sprite scaling, and kept disabled
* until sprite scaling is disabled."
*
* ILK/SNB DVSASCALE/Scaling Enable
* "When in Self Refresh Big FIFO mode, scaling enable will be
* masked off while Big FIFO mode is exiting."
*
* Despite the w/a only being listed for IVB we assume that
* the ILK/SNB note has similar ramifications, hence we apply
* the w/a on all three platforms.
*/
return !intel_plane_is_scaled(old_plane_state) &&
intel_plane_is_scaled(new_plane_state);
}
static int intel_plane_atomic_calc_changes(const struct intel_crtc_state *old_crtc_state,
struct intel_crtc_state *new_crtc_state,
const struct intel_plane_state *old_plane_state,
@ -546,20 +580,6 @@ static int intel_plane_atomic_calc_changes(const struct intel_crtc_state *old_cr
was_visible, visible,
turn_off, turn_on, mode_changed);
if (turn_on) {
if (DISPLAY_VER(dev_priv) < 5 && !IS_G4X(dev_priv))
new_crtc_state->update_wm_pre = true;
} else if (turn_off) {
if (DISPLAY_VER(dev_priv) < 5 && !IS_G4X(dev_priv))
new_crtc_state->update_wm_post = true;
} else if (intel_wm_need_update(old_plane_state, new_plane_state)) {
if (DISPLAY_VER(dev_priv) < 5 && !IS_G4X(dev_priv)) {
/* FIXME bollocks */
new_crtc_state->update_wm_pre = true;
new_crtc_state->update_wm_post = true;
}
}
if (visible || was_visible)
new_crtc_state->fb_bits |= plane->frontbuffer_bit;
@ -567,45 +587,9 @@ static int intel_plane_atomic_calc_changes(const struct intel_crtc_state *old_cr
i9xx_must_disable_cxsr(new_crtc_state, old_plane_state, new_plane_state))
new_crtc_state->disable_cxsr = true;
/*
* ILK/SNB DVSACNTR/Sprite Enable
* IVB SPR_CTL/Sprite Enable
* "When in Self Refresh Big FIFO mode, a write to enable the
* plane will be internally buffered and delayed while Big FIFO
* mode is exiting."
*
* Which means that enabling the sprite can take an extra frame
* when we start in big FIFO mode (LP1+). Thus we need to drop
* down to LP0 and wait for vblank in order to make sure the
* sprite gets enabled on the next vblank after the register write.
* Doing otherwise would risk enabling the sprite one frame after
* we've already signalled flip completion. We can resume LP1+
* once the sprite has been enabled.
*
*
* WaCxSRDisabledForSpriteScaling:ivb
* IVB SPR_SCALE/Scaling Enable
* "Low Power watermarks must be disabled for at least one
* frame before enabling sprite scaling, and kept disabled
* until sprite scaling is disabled."
*
* ILK/SNB DVSASCALE/Scaling Enable
* "When in Self Refresh Big FIFO mode, scaling enable will be
* masked off while Big FIFO mode is exiting."
*
* Despite the w/a only being listed for IVB we assume that
* the ILK/SNB note has similar ramifications, hence we apply
* the w/a on all three platforms.
*
* With experimental results seems this is needed also for primary
* plane, not only sprite plane.
*/
if (plane->id != PLANE_CURSOR &&
(IS_IRONLAKE(dev_priv) || IS_SANDYBRIDGE(dev_priv) ||
IS_IVYBRIDGE(dev_priv)) &&
(turn_on || (!intel_plane_is_scaled(old_plane_state) &&
intel_plane_is_scaled(new_plane_state))))
new_crtc_state->disable_lp_wm = true;
if ((IS_IRONLAKE(dev_priv) || IS_SANDYBRIDGE(dev_priv) || IS_IVYBRIDGE(dev_priv)) &&
ilk_must_disable_cxsr(new_crtc_state, old_plane_state, new_plane_state))
new_crtc_state->disable_cxsr = true;
if (intel_plane_do_async_flip(plane, old_crtc_state, new_crtc_state)) {
new_crtc_state->do_async_flip = true;
@ -710,13 +694,13 @@ intel_crtc_get_plane(struct intel_crtc *crtc, enum plane_id plane_id)
int intel_plane_atomic_check(struct intel_atomic_state *state,
struct intel_plane *plane)
{
struct drm_i915_private *i915 = to_i915(state->base.dev);
struct intel_display *display = to_intel_display(state);
struct intel_plane_state *new_plane_state =
intel_atomic_get_new_plane_state(state, plane);
const struct intel_plane_state *old_plane_state =
intel_atomic_get_old_plane_state(state, plane);
const struct intel_plane_state *new_primary_crtc_plane_state;
struct intel_crtc *crtc = intel_crtc_for_pipe(i915, plane->pipe);
struct intel_crtc *crtc = intel_crtc_for_pipe(display, plane->pipe);
const struct intel_crtc_state *old_crtc_state =
intel_atomic_get_old_crtc_state(state, crtc);
struct intel_crtc_state *new_crtc_state =
@ -790,7 +774,8 @@ skl_next_plane_to_commit(struct intel_atomic_state *state,
return NULL;
}
void intel_plane_update_noarm(struct intel_plane *plane,
void intel_plane_update_noarm(struct intel_dsb *dsb,
struct intel_plane *plane,
const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state)
{
@ -799,10 +784,11 @@ void intel_plane_update_noarm(struct intel_plane *plane,
trace_intel_plane_update_noarm(plane, crtc);
if (plane->update_noarm)
plane->update_noarm(plane, crtc_state, plane_state);
plane->update_noarm(dsb, plane, crtc_state, plane_state);
}
void intel_plane_async_flip(struct intel_plane *plane,
void intel_plane_async_flip(struct intel_dsb *dsb,
struct intel_plane *plane,
const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state,
bool async_flip)
@ -810,34 +796,37 @@ void intel_plane_async_flip(struct intel_plane *plane,
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
trace_intel_plane_async_flip(plane, crtc, async_flip);
plane->async_flip(plane, crtc_state, plane_state, async_flip);
plane->async_flip(dsb, plane, crtc_state, plane_state, async_flip);
}
void intel_plane_update_arm(struct intel_plane *plane,
void intel_plane_update_arm(struct intel_dsb *dsb,
struct intel_plane *plane,
const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state)
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
if (crtc_state->do_async_flip && plane->async_flip) {
intel_plane_async_flip(plane, crtc_state, plane_state, true);
intel_plane_async_flip(dsb, plane, crtc_state, plane_state, true);
return;
}
trace_intel_plane_update_arm(plane, crtc);
plane->update_arm(plane, crtc_state, plane_state);
plane->update_arm(dsb, plane, crtc_state, plane_state);
}
void intel_plane_disable_arm(struct intel_plane *plane,
void intel_plane_disable_arm(struct intel_dsb *dsb,
struct intel_plane *plane,
const struct intel_crtc_state *crtc_state)
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
trace_intel_plane_disable_arm(plane, crtc);
plane->disable_arm(plane, crtc_state);
plane->disable_arm(dsb, plane, crtc_state);
}
void intel_crtc_planes_update_noarm(struct intel_atomic_state *state,
void intel_crtc_planes_update_noarm(struct intel_dsb *dsb,
struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
struct intel_crtc_state *new_crtc_state =
@ -862,11 +851,13 @@ void intel_crtc_planes_update_noarm(struct intel_atomic_state *state,
/* TODO: for mailbox updates this should be skipped */
if (new_plane_state->uapi.visible ||
new_plane_state->planar_slave)
intel_plane_update_noarm(plane, new_crtc_state, new_plane_state);
intel_plane_update_noarm(dsb, plane,
new_crtc_state, new_plane_state);
}
}
static void skl_crtc_planes_update_arm(struct intel_atomic_state *state,
static void skl_crtc_planes_update_arm(struct intel_dsb *dsb,
struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
struct intel_crtc_state *old_crtc_state =
@ -893,13 +884,14 @@ static void skl_crtc_planes_update_arm(struct intel_atomic_state *state,
*/
if (new_plane_state->uapi.visible ||
new_plane_state->planar_slave)
intel_plane_update_arm(plane, new_crtc_state, new_plane_state);
intel_plane_update_arm(dsb, plane, new_crtc_state, new_plane_state);
else
intel_plane_disable_arm(plane, new_crtc_state);
intel_plane_disable_arm(dsb, plane, new_crtc_state);
}
}
static void i9xx_crtc_planes_update_arm(struct intel_atomic_state *state,
static void i9xx_crtc_planes_update_arm(struct intel_dsb *dsb,
struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
struct intel_crtc_state *new_crtc_state =
@ -919,21 +911,22 @@ static void i9xx_crtc_planes_update_arm(struct intel_atomic_state *state,
* would have to be called here as well.
*/
if (new_plane_state->uapi.visible)
intel_plane_update_arm(plane, new_crtc_state, new_plane_state);
intel_plane_update_arm(dsb, plane, new_crtc_state, new_plane_state);
else
intel_plane_disable_arm(plane, new_crtc_state);
intel_plane_disable_arm(dsb, plane, new_crtc_state);
}
}
void intel_crtc_planes_update_arm(struct intel_atomic_state *state,
void intel_crtc_planes_update_arm(struct intel_dsb *dsb,
struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
struct drm_i915_private *i915 = to_i915(state->base.dev);
if (DISPLAY_VER(i915) >= 9)
skl_crtc_planes_update_arm(state, crtc);
skl_crtc_planes_update_arm(dsb, state, crtc);
else
i9xx_crtc_planes_update_arm(state, crtc);
i9xx_crtc_planes_update_arm(dsb, state, crtc);
}
int intel_atomic_plane_check_clipping(struct intel_plane_state *plane_state,
@ -1114,8 +1107,8 @@ intel_prepare_plane_fb(struct drm_plane *_plane,
struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
struct intel_plane_state *old_plane_state =
intel_atomic_get_old_plane_state(state, plane);
struct drm_i915_gem_object *obj = intel_fb_obj(new_plane_state->hw.fb);
struct drm_i915_gem_object *old_obj = intel_fb_obj(old_plane_state->hw.fb);
struct drm_gem_object *obj = intel_fb_bo(new_plane_state->hw.fb);
struct drm_gem_object *old_obj = intel_fb_bo(old_plane_state->hw.fb);
int ret;
if (old_obj) {
@ -1135,7 +1128,7 @@ intel_prepare_plane_fb(struct drm_plane *_plane,
* can safely continue.
*/
if (new_crtc_state && intel_crtc_needs_modeset(new_crtc_state)) {
ret = add_dma_resv_fences(intel_bo_to_drm_bo(old_obj)->resv,
ret = add_dma_resv_fences(old_obj->resv,
&new_plane_state->uapi);
if (ret < 0)
return ret;
@ -1195,7 +1188,7 @@ intel_cleanup_plane_fb(struct drm_plane *plane,
struct intel_atomic_state *state =
to_intel_atomic_state(old_plane_state->uapi.state);
struct drm_i915_private *dev_priv = to_i915(plane->dev);
struct drm_i915_gem_object *obj = intel_fb_obj(old_plane_state->hw.fb);
struct drm_gem_object *obj = intel_fb_bo(old_plane_state->hw.fb);
if (!obj)
return;

View File

@ -14,6 +14,7 @@ struct drm_rect;
struct intel_atomic_state;
struct intel_crtc;
struct intel_crtc_state;
struct intel_dsb;
struct intel_plane;
struct intel_plane_state;
enum plane_id;
@ -32,26 +33,32 @@ void intel_plane_copy_uapi_to_hw_state(struct intel_plane_state *plane_state,
struct intel_crtc *crtc);
void intel_plane_copy_hw_state(struct intel_plane_state *plane_state,
const struct intel_plane_state *from_plane_state);
void intel_plane_async_flip(struct intel_plane *plane,
void intel_plane_async_flip(struct intel_dsb *dsb,
struct intel_plane *plane,
const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state,
bool async_flip);
void intel_plane_update_noarm(struct intel_plane *plane,
void intel_plane_update_noarm(struct intel_dsb *dsb,
struct intel_plane *plane,
const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state);
void intel_plane_update_arm(struct intel_plane *plane,
void intel_plane_update_arm(struct intel_dsb *dsb,
struct intel_plane *plane,
const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state);
void intel_plane_disable_arm(struct intel_plane *plane,
void intel_plane_disable_arm(struct intel_dsb *dsb,
struct intel_plane *plane,
const struct intel_crtc_state *crtc_state);
struct intel_plane *intel_plane_alloc(void);
void intel_plane_free(struct intel_plane *plane);
struct drm_plane_state *intel_plane_duplicate_state(struct drm_plane *plane);
void intel_plane_destroy_state(struct drm_plane *plane,
struct drm_plane_state *state);
void intel_crtc_planes_update_noarm(struct intel_atomic_state *state,
void intel_crtc_planes_update_noarm(struct intel_dsb *dsb,
struct intel_atomic_state *state,
struct intel_crtc *crtc);
void intel_crtc_planes_update_arm(struct intel_atomic_state *state,
void intel_crtc_planes_update_arm(struct intel_dsb *dsbx,
struct intel_atomic_state *state,
struct intel_crtc *crtc);
int intel_plane_atomic_check_with_state(const struct intel_crtc_state *old_crtc_state,
struct intel_crtc_state *crtc_state,

View File

@ -982,12 +982,12 @@ static unsigned long i915_audio_component_get_power(struct device *kdev)
{
struct intel_display *display = to_intel_display(kdev);
struct drm_i915_private *i915 = to_i915(display->drm);
intel_wakeref_t ret;
intel_wakeref_t wakeref;
/* Catch potential impedance mismatches before they occur! */
BUILD_BUG_ON(sizeof(intel_wakeref_t) > sizeof(unsigned long));
ret = intel_display_power_get(i915, POWER_DOMAIN_AUDIO_PLAYBACK);
wakeref = intel_display_power_get(i915, POWER_DOMAIN_AUDIO_PLAYBACK);
if (i915->display.audio.power_refcount++ == 0) {
if (DISPLAY_VER(i915) >= 9) {
@ -1007,7 +1007,7 @@ static unsigned long i915_audio_component_get_power(struct device *kdev)
0, AUD_PIN_BUF_ENABLE);
}
return ret;
return (unsigned long)wakeref;
}
static void i915_audio_component_put_power(struct device *kdev,
@ -1015,13 +1015,14 @@ static void i915_audio_component_put_power(struct device *kdev,
{
struct intel_display *display = to_intel_display(kdev);
struct drm_i915_private *i915 = to_i915(display->drm);
intel_wakeref_t wakeref = (intel_wakeref_t)cookie;
/* Stop forcing CDCLK to 2*BCLK if no need for audio to be powered. */
if (--i915->display.audio.power_refcount == 0)
if (IS_GEMINILAKE(i915))
glk_force_audio_cdclk(i915, false);
intel_display_power_put(i915, POWER_DOMAIN_AUDIO_PLAYBACK, cookie);
intel_display_power_put(i915, POWER_DOMAIN_AUDIO_PLAYBACK, wakeref);
}
static void i915_audio_component_codec_wake_override(struct device *kdev,

View File

@ -25,6 +25,7 @@
*
*/
#include <linux/debugfs.h>
#include <linux/firmware.h>
#include <drm/display/drm_dp_helper.h>
@ -32,12 +33,12 @@
#include <drm/drm_edid.h>
#include <drm/drm_fixed.h>
#include "soc/intel_rom.h"
#include "i915_drv.h"
#include "i915_reg.h"
#include "intel_display.h"
#include "intel_display_types.h"
#include "intel_gmbus.h"
#include "intel_uncore.h"
#define _INTEL_BIOS_PRIVATE
#include "intel_vbt_defs.h"
@ -1705,8 +1706,8 @@ parse_mipi_config(struct intel_display *display,
return;
}
drm_dbg(display->drm, "Found MIPI Config block, panel index = %d\n",
panel_type);
drm_dbg_kms(display->drm, "Found MIPI Config block, panel index = %d\n",
panel_type);
/*
* get hold of the correct configuration block and pps data as per
@ -2066,8 +2067,8 @@ parse_mipi_sequence(struct intel_display *display,
return;
}
drm_dbg(display->drm, "Found MIPI sequence block v%u\n",
sequence->version);
drm_dbg_kms(display->drm, "Found MIPI sequence block v%u\n",
sequence->version);
seq_data = find_panel_sequence_block(display, sequence, panel_type, &seq_size);
if (!seq_data)
@ -2113,7 +2114,7 @@ parse_mipi_sequence(struct intel_display *display,
fixup_mipi_sequences(display, panel);
drm_dbg(display->drm, "MIPI related VBT parsing complete\n");
drm_dbg_kms(display->drm, "MIPI related VBT parsing complete\n");
return;
err:
@ -2770,9 +2771,9 @@ static bool child_device_size_valid(struct intel_display *display, int size)
expected_size = child_device_expected_size(display->vbt.version);
if (expected_size < 0) {
expected_size = sizeof(struct child_device_config);
drm_dbg(display->drm,
"Expected child device config size for VBT version %u not known; assuming %d\n",
display->vbt.version, expected_size);
drm_dbg_kms(display->drm,
"Expected child device config size for VBT version %u not known; assuming %d\n",
display->vbt.version, expected_size);
}
/* Flag an error for unexpected size, but continue anyway. */
@ -2963,6 +2964,9 @@ static const struct bdb_header *get_bdb_header(const struct vbt_header *vbt)
return _vbt + vbt->bdb_offset;
}
static const char vbt_signature[] = "$VBT";
static const int vbt_signature_len = 4;
/**
* intel_bios_is_valid_vbt - does the given buffer contain a valid VBT
* @display: display device
@ -2985,7 +2989,7 @@ bool intel_bios_is_valid_vbt(struct intel_display *display,
return false;
}
if (memcmp(vbt->signature, "$VBT", 4)) {
if (memcmp(vbt->signature, vbt_signature, vbt_signature_len)) {
drm_dbg_kms(display->drm, "VBT invalid signature\n");
return false;
}
@ -3052,131 +3056,59 @@ static struct vbt_header *firmware_get_vbt(struct intel_display *display,
return vbt;
}
static u32 intel_spi_read(struct intel_uncore *uncore, u32 offset)
static struct vbt_header *oprom_get_vbt(struct intel_display *display,
struct intel_rom *rom,
size_t *size, const char *type)
{
intel_uncore_write(uncore, PRIMARY_SPI_ADDRESS, offset);
struct vbt_header *vbt;
size_t vbt_size;
loff_t offset;
return intel_uncore_read(uncore, PRIMARY_SPI_TRIGGER);
}
if (!rom)
return NULL;
static struct vbt_header *spi_oprom_get_vbt(struct intel_display *display,
size_t *size)
{
struct drm_i915_private *i915 = to_i915(display->drm);
u32 count, data, found, store = 0;
u32 static_region, oprom_offset;
u32 oprom_size = 0x200000;
u16 vbt_size;
u32 *vbt;
BUILD_BUG_ON(vbt_signature_len != sizeof(vbt_signature) - 1);
BUILD_BUG_ON(vbt_signature_len != sizeof(u32));
static_region = intel_uncore_read(&i915->uncore, SPI_STATIC_REGIONS);
static_region &= OPTIONROM_SPI_REGIONID_MASK;
intel_uncore_write(&i915->uncore, PRIMARY_SPI_REGIONID, static_region);
offset = intel_rom_find(rom, *(const u32 *)vbt_signature);
if (offset < 0)
goto err_free_rom;
oprom_offset = intel_uncore_read(&i915->uncore, OROM_OFFSET);
oprom_offset &= OROM_OFFSET_MASK;
for (count = 0; count < oprom_size; count += 4) {
data = intel_spi_read(&i915->uncore, oprom_offset + count);
if (data == *((const u32 *)"$VBT")) {
found = oprom_offset + count;
break;
}
if (sizeof(struct vbt_header) > intel_rom_size(rom) - offset) {
drm_dbg_kms(display->drm, "VBT header incomplete\n");
goto err_free_rom;
}
if (count >= oprom_size)
goto err_not_found;
BUILD_BUG_ON(sizeof(vbt->vbt_size) != sizeof(u16));
/* Get VBT size and allocate space for the VBT */
vbt_size = intel_spi_read(&i915->uncore,
found + offsetof(struct vbt_header, vbt_size));
vbt_size &= 0xffff;
vbt_size = intel_rom_read16(rom, offset + offsetof(struct vbt_header, vbt_size));
if (vbt_size > intel_rom_size(rom) - offset) {
drm_dbg_kms(display->drm, "VBT incomplete (vbt_size overflows)\n");
goto err_free_rom;
}
vbt = kzalloc(round_up(vbt_size, 4), GFP_KERNEL);
if (!vbt)
goto err_not_found;
goto err_free_rom;
for (count = 0; count < vbt_size; count += 4)
*(vbt + store++) = intel_spi_read(&i915->uncore, found + count);
intel_rom_read_block(rom, vbt, offset, vbt_size);
if (!intel_bios_is_valid_vbt(display, vbt, vbt_size))
goto err_free_vbt;
drm_dbg_kms(display->drm, "Found valid VBT in SPI flash\n");
drm_dbg_kms(display->drm, "Found valid VBT in %s\n", type);
if (size)
*size = vbt_size;
return (struct vbt_header *)vbt;
err_free_vbt:
kfree(vbt);
err_not_found:
return NULL;
}
static struct vbt_header *oprom_get_vbt(struct intel_display *display,
size_t *sizep)
{
struct pci_dev *pdev = to_pci_dev(display->drm->dev);
void __iomem *p = NULL, *oprom;
struct vbt_header *vbt;
u16 vbt_size;
size_t i, size;
oprom = pci_map_rom(pdev, &size);
if (!oprom)
return NULL;
/* Scour memory looking for the VBT signature. */
for (i = 0; i + 4 < size; i += 4) {
if (ioread32(oprom + i) != *((const u32 *)"$VBT"))
continue;
p = oprom + i;
size -= i;
break;
}
if (!p)
goto err_unmap_oprom;
if (sizeof(struct vbt_header) > size) {
drm_dbg(display->drm, "VBT header incomplete\n");
goto err_unmap_oprom;
}
vbt_size = ioread16(p + offsetof(struct vbt_header, vbt_size));
if (vbt_size > size) {
drm_dbg(display->drm,
"VBT incomplete (vbt_size overflows)\n");
goto err_unmap_oprom;
}
/* The rest will be validated by intel_bios_is_valid_vbt() */
vbt = kmalloc(vbt_size, GFP_KERNEL);
if (!vbt)
goto err_unmap_oprom;
memcpy_fromio(vbt, p, vbt_size);
if (!intel_bios_is_valid_vbt(display, vbt, vbt_size))
goto err_free_vbt;
pci_unmap_rom(pdev, oprom);
if (sizep)
*sizep = vbt_size;
drm_dbg_kms(display->drm, "Found valid VBT in PCI ROM\n");
intel_rom_free(rom);
return vbt;
err_free_vbt:
kfree(vbt);
err_unmap_oprom:
pci_unmap_rom(pdev, oprom);
err_free_rom:
intel_rom_free(rom);
return NULL;
}
@ -3198,11 +3130,11 @@ static const struct vbt_header *intel_bios_get_vbt(struct intel_display *display
*/
if (!vbt && IS_DGFX(i915))
with_intel_runtime_pm(&i915->runtime_pm, wakeref)
vbt = spi_oprom_get_vbt(display, sizep);
vbt = oprom_get_vbt(display, intel_rom_spi(i915), sizep, "SPI flash");
if (!vbt)
with_intel_runtime_pm(&i915->runtime_pm, wakeref)
vbt = oprom_get_vbt(display, sizep);
vbt = oprom_get_vbt(display, intel_rom_pci(i915), sizep, "PCI ROM");
return vbt;
}

View File

@ -0,0 +1,59 @@
// SPDX-License-Identifier: MIT
/* Copyright © 2024 Intel Corporation */
#include "gem/i915_gem_mman.h"
#include "gem/i915_gem_object.h"
#include "gem/i915_gem_object_frontbuffer.h"
#include "i915_debugfs.h"
#include "intel_bo.h"
bool intel_bo_is_tiled(struct drm_gem_object *obj)
{
return i915_gem_object_is_tiled(to_intel_bo(obj));
}
bool intel_bo_is_userptr(struct drm_gem_object *obj)
{
return i915_gem_object_is_userptr(to_intel_bo(obj));
}
bool intel_bo_is_shmem(struct drm_gem_object *obj)
{
return i915_gem_object_is_shmem(to_intel_bo(obj));
}
bool intel_bo_is_protected(struct drm_gem_object *obj)
{
return i915_gem_object_is_protected(to_intel_bo(obj));
}
void intel_bo_flush_if_display(struct drm_gem_object *obj)
{
i915_gem_object_flush_if_display(to_intel_bo(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);
}
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_frontbuffer *intel_bo_get_frontbuffer(struct drm_gem_object *obj)
{
return i915_gem_object_get_frontbuffer(to_intel_bo(obj));
}
struct intel_frontbuffer *intel_bo_set_frontbuffer(struct drm_gem_object *obj,
struct intel_frontbuffer *front)
{
return i915_gem_object_set_frontbuffer(to_intel_bo(obj), front);
}
void intel_bo_describe(struct seq_file *m, struct drm_gem_object *obj)
{
i915_debugfs_describe_obj(m, to_intel_bo(obj));
}

View File

@ -0,0 +1,27 @@
/* SPDX-License-Identifier: MIT */
/* Copyright © 2024 Intel Corporation */
#ifndef __INTEL_BO__
#define __INTEL_BO__
#include <linux/types.h>
struct drm_gem_object;
struct seq_file;
struct vm_area_struct;
bool intel_bo_is_tiled(struct drm_gem_object *obj);
bool intel_bo_is_userptr(struct drm_gem_object *obj);
bool intel_bo_is_shmem(struct drm_gem_object *obj);
bool intel_bo_is_protected(struct drm_gem_object *obj);
void intel_bo_flush_if_display(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_get_frontbuffer(struct drm_gem_object *obj);
struct intel_frontbuffer *intel_bo_set_frontbuffer(struct drm_gem_object *obj,
struct intel_frontbuffer *front);
void intel_bo_describe(struct seq_file *m, struct drm_gem_object *obj);
#endif /* __INTEL_BO__ */

File diff suppressed because it is too large Load Diff

View File

@ -11,9 +11,9 @@
#include "intel_display_limits.h"
#include "intel_global_state.h"
struct drm_i915_private;
struct intel_atomic_state;
struct intel_crtc_state;
struct intel_display;
struct intel_cdclk_config {
unsigned int cdclk, vco, ref, bypass;
@ -59,24 +59,24 @@ struct intel_cdclk_state {
};
int intel_crtc_compute_min_cdclk(const struct intel_crtc_state *crtc_state);
void intel_cdclk_init_hw(struct drm_i915_private *i915);
void intel_cdclk_uninit_hw(struct drm_i915_private *i915);
void intel_init_cdclk_hooks(struct drm_i915_private *dev_priv);
void intel_update_max_cdclk(struct drm_i915_private *dev_priv);
void intel_update_cdclk(struct drm_i915_private *dev_priv);
u32 intel_read_rawclk(struct drm_i915_private *dev_priv);
void intel_cdclk_init_hw(struct intel_display *display);
void intel_cdclk_uninit_hw(struct intel_display *display);
void intel_init_cdclk_hooks(struct intel_display *display);
void intel_update_max_cdclk(struct intel_display *display);
void intel_update_cdclk(struct intel_display *display);
u32 intel_read_rawclk(struct intel_display *display);
bool intel_cdclk_clock_changed(const struct intel_cdclk_config *a,
const struct intel_cdclk_config *b);
int intel_mdclk_cdclk_ratio(struct drm_i915_private *i915,
int intel_mdclk_cdclk_ratio(struct intel_display *display,
const struct intel_cdclk_config *cdclk_config);
bool intel_cdclk_is_decreasing_later(struct intel_atomic_state *state);
void intel_set_cdclk_pre_plane_update(struct intel_atomic_state *state);
void intel_set_cdclk_post_plane_update(struct intel_atomic_state *state);
void intel_cdclk_dump_config(struct drm_i915_private *i915,
void intel_cdclk_dump_config(struct intel_display *display,
const struct intel_cdclk_config *cdclk_config,
const char *context);
int intel_modeset_calc_cdclk(struct intel_atomic_state *state);
void intel_cdclk_get_cdclk(struct drm_i915_private *dev_priv,
void intel_cdclk_get_cdclk(struct intel_display *display,
struct intel_cdclk_config *cdclk_config);
int intel_cdclk_atomic_check(struct intel_atomic_state *state,
bool *need_cdclk_calc);
@ -88,11 +88,11 @@ intel_atomic_get_cdclk_state(struct intel_atomic_state *state);
container_of_const((global_state), struct intel_cdclk_state, base)
#define intel_atomic_get_old_cdclk_state(state) \
to_intel_cdclk_state(intel_atomic_get_old_global_obj_state(state, &to_i915(state->base.dev)->display.cdclk.obj))
to_intel_cdclk_state(intel_atomic_get_old_global_obj_state(state, &to_intel_display(state)->cdclk.obj))
#define intel_atomic_get_new_cdclk_state(state) \
to_intel_cdclk_state(intel_atomic_get_new_global_obj_state(state, &to_i915(state->base.dev)->display.cdclk.obj))
to_intel_cdclk_state(intel_atomic_get_new_global_obj_state(state, &to_intel_display(state)->cdclk.obj))
int intel_cdclk_init(struct drm_i915_private *dev_priv);
void intel_cdclk_debugfs_register(struct drm_i915_private *i915);
int intel_cdclk_init(struct intel_display *display);
void intel_cdclk_debugfs_register(struct intel_display *display);
#endif /* __INTEL_CDCLK_H__ */

View File

@ -39,7 +39,8 @@ struct intel_color_funcs {
* the next vblank start, alongside any other double buffered
* registers involved with the same commit. This hook is optional.
*/
void (*color_commit_noarm)(const struct intel_crtc_state *crtc_state);
void (*color_commit_noarm)(struct intel_dsb *dsb,
const struct intel_crtc_state *crtc_state);
/*
* Program arming double buffered color management registers
* during vblank evasion. The registers (and whatever other registers
@ -47,7 +48,8 @@ struct intel_color_funcs {
* during the next vblank start, alongside any other double buffered
* registers involved with the same commit.
*/
void (*color_commit_arm)(const struct intel_crtc_state *crtc_state);
void (*color_commit_arm)(struct intel_dsb *dsb,
const struct intel_crtc_state *crtc_state);
/*
* Perform any extra tasks needed after all the
* double buffered registers have been latched.
@ -205,37 +207,44 @@ static u64 *ctm_mult_by_limited(u64 *result, const u64 *input)
return result;
}
static void ilk_update_pipe_csc(struct intel_crtc *crtc,
static void ilk_update_pipe_csc(struct intel_dsb *dsb,
struct intel_crtc *crtc,
const struct intel_csc_matrix *csc)
{
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
struct intel_display *display = to_intel_display(crtc->base.dev);
enum pipe pipe = crtc->pipe;
intel_de_write_fw(i915, PIPE_CSC_PREOFF_HI(pipe), csc->preoff[0]);
intel_de_write_fw(i915, PIPE_CSC_PREOFF_ME(pipe), csc->preoff[1]);
intel_de_write_fw(i915, PIPE_CSC_PREOFF_LO(pipe), csc->preoff[2]);
intel_de_write_dsb(display, dsb, PIPE_CSC_PREOFF_HI(pipe),
csc->preoff[0]);
intel_de_write_dsb(display, dsb, PIPE_CSC_PREOFF_ME(pipe),
csc->preoff[1]);
intel_de_write_dsb(display, dsb, PIPE_CSC_PREOFF_LO(pipe),
csc->preoff[2]);
intel_de_write_fw(i915, PIPE_CSC_COEFF_RY_GY(pipe),
csc->coeff[0] << 16 | csc->coeff[1]);
intel_de_write_fw(i915, PIPE_CSC_COEFF_BY(pipe),
csc->coeff[2] << 16);
intel_de_write_dsb(display, dsb, PIPE_CSC_COEFF_RY_GY(pipe),
csc->coeff[0] << 16 | csc->coeff[1]);
intel_de_write_dsb(display, dsb, PIPE_CSC_COEFF_BY(pipe),
csc->coeff[2] << 16);
intel_de_write_fw(i915, PIPE_CSC_COEFF_RU_GU(pipe),
csc->coeff[3] << 16 | csc->coeff[4]);
intel_de_write_fw(i915, PIPE_CSC_COEFF_BU(pipe),
csc->coeff[5] << 16);
intel_de_write_dsb(display, dsb, PIPE_CSC_COEFF_RU_GU(pipe),
csc->coeff[3] << 16 | csc->coeff[4]);
intel_de_write_dsb(display, dsb, PIPE_CSC_COEFF_BU(pipe),
csc->coeff[5] << 16);
intel_de_write_fw(i915, PIPE_CSC_COEFF_RV_GV(pipe),
csc->coeff[6] << 16 | csc->coeff[7]);
intel_de_write_fw(i915, PIPE_CSC_COEFF_BV(pipe),
csc->coeff[8] << 16);
intel_de_write_dsb(display, dsb, PIPE_CSC_COEFF_RV_GV(pipe),
csc->coeff[6] << 16 | csc->coeff[7]);
intel_de_write_dsb(display, dsb, PIPE_CSC_COEFF_BV(pipe),
csc->coeff[8] << 16);
if (DISPLAY_VER(i915) < 7)
if (DISPLAY_VER(display) < 7)
return;
intel_de_write_fw(i915, PIPE_CSC_POSTOFF_HI(pipe), csc->postoff[0]);
intel_de_write_fw(i915, PIPE_CSC_POSTOFF_ME(pipe), csc->postoff[1]);
intel_de_write_fw(i915, PIPE_CSC_POSTOFF_LO(pipe), csc->postoff[2]);
intel_de_write_dsb(display, dsb, PIPE_CSC_POSTOFF_HI(pipe),
csc->postoff[0]);
intel_de_write_dsb(display, dsb, PIPE_CSC_POSTOFF_ME(pipe),
csc->postoff[1]);
intel_de_write_dsb(display, dsb, PIPE_CSC_POSTOFF_LO(pipe),
csc->postoff[2]);
}
static void ilk_read_pipe_csc(struct intel_crtc *crtc,
@ -304,34 +313,41 @@ static void skl_read_csc(struct intel_crtc_state *crtc_state)
ilk_read_pipe_csc(crtc, &crtc_state->csc);
}
static void icl_update_output_csc(struct intel_crtc *crtc,
static void icl_update_output_csc(struct intel_dsb *dsb,
struct intel_crtc *crtc,
const struct intel_csc_matrix *csc)
{
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
struct intel_display *display = to_intel_display(crtc->base.dev);
enum pipe pipe = crtc->pipe;
intel_de_write_fw(i915, PIPE_CSC_OUTPUT_PREOFF_HI(pipe), csc->preoff[0]);
intel_de_write_fw(i915, PIPE_CSC_OUTPUT_PREOFF_ME(pipe), csc->preoff[1]);
intel_de_write_fw(i915, PIPE_CSC_OUTPUT_PREOFF_LO(pipe), csc->preoff[2]);
intel_de_write_dsb(display, dsb, PIPE_CSC_OUTPUT_PREOFF_HI(pipe),
csc->preoff[0]);
intel_de_write_dsb(display, dsb, PIPE_CSC_OUTPUT_PREOFF_ME(pipe),
csc->preoff[1]);
intel_de_write_dsb(display, dsb, PIPE_CSC_OUTPUT_PREOFF_LO(pipe),
csc->preoff[2]);
intel_de_write_fw(i915, PIPE_CSC_OUTPUT_COEFF_RY_GY(pipe),
csc->coeff[0] << 16 | csc->coeff[1]);
intel_de_write_fw(i915, PIPE_CSC_OUTPUT_COEFF_BY(pipe),
csc->coeff[2] << 16);
intel_de_write_dsb(display, dsb, PIPE_CSC_OUTPUT_COEFF_RY_GY(pipe),
csc->coeff[0] << 16 | csc->coeff[1]);
intel_de_write_dsb(display, dsb, PIPE_CSC_OUTPUT_COEFF_BY(pipe),
csc->coeff[2] << 16);
intel_de_write_fw(i915, PIPE_CSC_OUTPUT_COEFF_RU_GU(pipe),
csc->coeff[3] << 16 | csc->coeff[4]);
intel_de_write_fw(i915, PIPE_CSC_OUTPUT_COEFF_BU(pipe),
csc->coeff[5] << 16);
intel_de_write_dsb(display, dsb, PIPE_CSC_OUTPUT_COEFF_RU_GU(pipe),
csc->coeff[3] << 16 | csc->coeff[4]);
intel_de_write_dsb(display, dsb, PIPE_CSC_OUTPUT_COEFF_BU(pipe),
csc->coeff[5] << 16);
intel_de_write_fw(i915, PIPE_CSC_OUTPUT_COEFF_RV_GV(pipe),
csc->coeff[6] << 16 | csc->coeff[7]);
intel_de_write_fw(i915, PIPE_CSC_OUTPUT_COEFF_BV(pipe),
csc->coeff[8] << 16);
intel_de_write_dsb(display, dsb, PIPE_CSC_OUTPUT_COEFF_RV_GV(pipe),
csc->coeff[6] << 16 | csc->coeff[7]);
intel_de_write_dsb(display, dsb, PIPE_CSC_OUTPUT_COEFF_BV(pipe),
csc->coeff[8] << 16);
intel_de_write_fw(i915, PIPE_CSC_OUTPUT_POSTOFF_HI(pipe), csc->postoff[0]);
intel_de_write_fw(i915, PIPE_CSC_OUTPUT_POSTOFF_ME(pipe), csc->postoff[1]);
intel_de_write_fw(i915, PIPE_CSC_OUTPUT_POSTOFF_LO(pipe), csc->postoff[2]);
intel_de_write_dsb(display, dsb, PIPE_CSC_OUTPUT_POSTOFF_HI(pipe),
csc->postoff[0]);
intel_de_write_dsb(display, dsb, PIPE_CSC_OUTPUT_POSTOFF_ME(pipe),
csc->postoff[1]);
intel_de_write_dsb(display, dsb, PIPE_CSC_OUTPUT_POSTOFF_LO(pipe),
csc->postoff[2]);
}
static void icl_read_output_csc(struct intel_crtc *crtc,
@ -526,12 +542,13 @@ static void ilk_assign_csc(struct intel_crtc_state *crtc_state)
}
}
static void ilk_load_csc_matrix(const struct intel_crtc_state *crtc_state)
static void ilk_load_csc_matrix(struct intel_dsb *dsb,
const struct intel_crtc_state *crtc_state)
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
if (crtc_state->csc_enable)
ilk_update_pipe_csc(crtc, &crtc_state->csc);
ilk_update_pipe_csc(dsb, crtc, &crtc_state->csc);
}
static void icl_assign_csc(struct intel_crtc_state *crtc_state)
@ -563,15 +580,16 @@ static void icl_assign_csc(struct intel_crtc_state *crtc_state)
}
}
static void icl_load_csc_matrix(const struct intel_crtc_state *crtc_state)
static void icl_load_csc_matrix(struct intel_dsb *dsb,
const struct intel_crtc_state *crtc_state)
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
if (crtc_state->csc_mode & ICL_CSC_ENABLE)
ilk_update_pipe_csc(crtc, &crtc_state->csc);
ilk_update_pipe_csc(dsb, crtc, &crtc_state->csc);
if (crtc_state->csc_mode & ICL_OUTPUT_CSC_ENABLE)
icl_update_output_csc(crtc, &crtc_state->output_csc);
icl_update_output_csc(dsb, crtc, &crtc_state->output_csc);
}
static u16 ctm_to_twos_complement(u64 coeff, int int_bits, int frac_bits)
@ -953,7 +971,8 @@ static void ilk_lut_12p4_pack(struct drm_color_lut *entry, u32 ldw, u32 udw)
REG_FIELD_GET(PREC_PALETTE_12P4_BLUE_LDW_MASK, ldw);
}
static void icl_color_commit_noarm(const struct intel_crtc_state *crtc_state)
static void icl_color_commit_noarm(struct intel_dsb *dsb,
const struct intel_crtc_state *crtc_state)
{
/*
* Despite Wa_1406463849, ICL no longer suffers from the SKL
@ -963,10 +982,11 @@ static void icl_color_commit_noarm(const struct intel_crtc_state *crtc_state)
*
* On TGL+ all CSC arming issues have been properly fixed.
*/
icl_load_csc_matrix(crtc_state);
icl_load_csc_matrix(dsb, crtc_state);
}
static void skl_color_commit_noarm(const struct intel_crtc_state *crtc_state)
static void skl_color_commit_noarm(struct intel_dsb *dsb,
const struct intel_crtc_state *crtc_state)
{
/*
* Possibly related to display WA #1184, SKL CSC loses the latched
@ -979,21 +999,24 @@ static void skl_color_commit_noarm(const struct intel_crtc_state *crtc_state)
* which is called after PSR exit.
*/
if (!crtc_state->has_psr)
ilk_load_csc_matrix(crtc_state);
ilk_load_csc_matrix(dsb, crtc_state);
}
static void ilk_color_commit_noarm(const struct intel_crtc_state *crtc_state)
static void ilk_color_commit_noarm(struct intel_dsb *dsb,
const struct intel_crtc_state *crtc_state)
{
ilk_load_csc_matrix(crtc_state);
ilk_load_csc_matrix(dsb, crtc_state);
}
static void i9xx_color_commit_arm(const struct intel_crtc_state *crtc_state)
static void i9xx_color_commit_arm(struct intel_dsb *dsb,
const struct intel_crtc_state *crtc_state)
{
/* update TRANSCONF GAMMA_MODE */
i9xx_set_pipeconf(crtc_state);
}
static void ilk_color_commit_arm(const struct intel_crtc_state *crtc_state)
static void ilk_color_commit_arm(struct intel_dsb *dsb,
const struct intel_crtc_state *crtc_state)
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
@ -1005,7 +1028,8 @@ static void ilk_color_commit_arm(const struct intel_crtc_state *crtc_state)
crtc_state->csc_mode);
}
static void hsw_color_commit_arm(const struct intel_crtc_state *crtc_state)
static void hsw_color_commit_arm(struct intel_dsb *dsb,
const struct intel_crtc_state *crtc_state)
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
@ -1076,15 +1100,16 @@ static void skl_get_config(struct intel_crtc_state *crtc_state)
crtc_state->csc_enable = true;
}
static void skl_color_commit_arm(const struct intel_crtc_state *crtc_state)
static void skl_color_commit_arm(struct intel_dsb *dsb,
const struct intel_crtc_state *crtc_state)
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
struct intel_display *display = to_intel_display(crtc->base.dev);
enum pipe pipe = crtc->pipe;
u32 val = 0;
if (crtc_state->has_psr)
ilk_load_csc_matrix(crtc_state);
ilk_load_csc_matrix(dsb, crtc_state);
/*
* We don't (yet) allow userspace to control the pipe background color,
@ -1095,32 +1120,29 @@ static void skl_color_commit_arm(const struct intel_crtc_state *crtc_state)
val |= SKL_BOTTOM_COLOR_GAMMA_ENABLE;
if (crtc_state->csc_enable)
val |= SKL_BOTTOM_COLOR_CSC_ENABLE;
intel_de_write(i915, SKL_BOTTOM_COLOR(pipe), val);
intel_de_write_dsb(display, dsb, SKL_BOTTOM_COLOR(pipe), val);
intel_de_write(i915, GAMMA_MODE(crtc->pipe),
crtc_state->gamma_mode);
intel_de_write_dsb(display, dsb, GAMMA_MODE(crtc->pipe), crtc_state->gamma_mode);
intel_de_write_fw(i915, PIPE_CSC_MODE(crtc->pipe),
crtc_state->csc_mode);
intel_de_write_dsb(display, dsb, PIPE_CSC_MODE(crtc->pipe), crtc_state->csc_mode);
}
static void icl_color_commit_arm(const struct intel_crtc_state *crtc_state)
static void icl_color_commit_arm(struct intel_dsb *dsb,
const struct intel_crtc_state *crtc_state)
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
struct intel_display *display = to_intel_display(crtc->base.dev);
enum pipe pipe = crtc->pipe;
/*
* We don't (yet) allow userspace to control the pipe background color,
* so force it to black.
*/
intel_de_write(i915, SKL_BOTTOM_COLOR(pipe), 0);
intel_de_write_dsb(display, dsb, SKL_BOTTOM_COLOR(pipe), 0);
intel_de_write(i915, GAMMA_MODE(crtc->pipe),
crtc_state->gamma_mode);
intel_de_write_dsb(display, dsb, GAMMA_MODE(crtc->pipe), crtc_state->gamma_mode);
intel_de_write_fw(i915, PIPE_CSC_MODE(crtc->pipe),
crtc_state->csc_mode);
intel_de_write_dsb(display, dsb, PIPE_CSC_MODE(crtc->pipe), crtc_state->csc_mode);
}
static void icl_color_post_update(const struct intel_crtc_state *crtc_state)
@ -1876,22 +1898,21 @@ void intel_color_load_luts(const struct intel_crtc_state *crtc_state)
i915->display.funcs.color->load_luts(crtc_state);
}
void intel_color_commit_noarm(const struct intel_crtc_state *crtc_state)
void intel_color_commit_noarm(struct intel_dsb *dsb,
const struct intel_crtc_state *crtc_state)
{
struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
if (i915->display.funcs.color->color_commit_noarm)
i915->display.funcs.color->color_commit_noarm(crtc_state);
i915->display.funcs.color->color_commit_noarm(dsb, crtc_state);
}
void intel_color_commit_arm(const struct intel_crtc_state *crtc_state)
void intel_color_commit_arm(struct intel_dsb *dsb,
const struct intel_crtc_state *crtc_state)
{
struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
i915->display.funcs.color->color_commit_arm(crtc_state);
if (crtc_state->dsb_color_commit)
intel_dsb_commit(crtc_state->dsb_color_commit, false);
i915->display.funcs.color->color_commit_arm(dsb, crtc_state);
}
void intel_color_post_update(const struct intel_crtc_state *crtc_state)
@ -1902,6 +1923,23 @@ void intel_color_post_update(const struct intel_crtc_state *crtc_state)
i915->display.funcs.color->color_post_update(crtc_state);
}
void intel_color_modeset(const struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(crtc_state);
intel_color_load_luts(crtc_state);
intel_color_commit_noarm(NULL, crtc_state);
intel_color_commit_arm(NULL, crtc_state);
if (DISPLAY_VER(display) < 9) {
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct intel_plane *plane = to_intel_plane(crtc->base.primary);
/* update DSPCNTR to configure gamma/csc for pipe bottom color */
plane->disable_arm(NULL, plane, crtc_state);
}
}
void intel_color_prepare_commit(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
@ -1925,28 +1963,14 @@ void intel_color_prepare_commit(struct intel_atomic_state *state,
i915->display.funcs.color->load_luts(crtc_state);
intel_dsb_wait_vblank_delay(state, crtc_state->dsb_color_vblank);
intel_dsb_interrupt(crtc_state->dsb_color_vblank);
intel_dsb_finish(crtc_state->dsb_color_vblank);
crtc_state->dsb_color_commit = intel_dsb_prepare(state, crtc, INTEL_DSB_0, 16);
if (!crtc_state->dsb_color_commit) {
intel_dsb_cleanup(crtc_state->dsb_color_vblank);
crtc_state->dsb_color_vblank = NULL;
return;
}
intel_dsb_chain(state, crtc_state->dsb_color_commit,
crtc_state->dsb_color_vblank, true);
intel_dsb_finish(crtc_state->dsb_color_commit);
}
void intel_color_cleanup_commit(struct intel_crtc_state *crtc_state)
{
if (crtc_state->dsb_color_commit) {
intel_dsb_cleanup(crtc_state->dsb_color_commit);
crtc_state->dsb_color_commit = NULL;
}
if (crtc_state->dsb_color_vblank) {
intel_dsb_cleanup(crtc_state->dsb_color_vblank);
crtc_state->dsb_color_vblank = NULL;
@ -1955,8 +1979,6 @@ void intel_color_cleanup_commit(struct intel_crtc_state *crtc_state)
void intel_color_wait_commit(const struct intel_crtc_state *crtc_state)
{
if (crtc_state->dsb_color_commit)
intel_dsb_wait(crtc_state->dsb_color_commit);
if (crtc_state->dsb_color_vblank)
intel_dsb_wait(crtc_state->dsb_color_vblank);
}

View File

@ -11,6 +11,7 @@
struct intel_atomic_state;
struct intel_crtc_state;
struct intel_crtc;
struct intel_dsb;
struct drm_i915_private;
struct drm_property_blob;
@ -24,10 +25,13 @@ void intel_color_prepare_commit(struct intel_atomic_state *state,
void intel_color_cleanup_commit(struct intel_crtc_state *crtc_state);
bool intel_color_uses_dsb(const struct intel_crtc_state *crtc_state);
void intel_color_wait_commit(const struct intel_crtc_state *crtc_state);
void intel_color_commit_noarm(const struct intel_crtc_state *crtc_state);
void intel_color_commit_arm(const struct intel_crtc_state *crtc_state);
void intel_color_commit_noarm(struct intel_dsb *dsb,
const struct intel_crtc_state *crtc_state);
void intel_color_commit_arm(struct intel_dsb *dsb,
const struct intel_crtc_state *crtc_state);
void intel_color_post_update(const struct intel_crtc_state *crtc_state);
void intel_color_load_luts(const struct intel_crtc_state *crtc_state);
void intel_color_modeset(const struct intel_crtc_state *crtc_state);
void intel_color_get_config(struct intel_crtc_state *crtc_state);
bool intel_color_lut_equal(const struct intel_crtc_state *crtc_state,
const struct drm_property_blob *blob1,

View File

@ -694,6 +694,7 @@ static bool intel_crt_detect_ddc(struct drm_connector *connector)
static enum drm_connector_status
intel_crt_load_detect(struct intel_crt *crt, enum pipe pipe)
{
struct intel_display *display = to_intel_display(&crt->base);
struct drm_device *dev = crt->base.base.dev;
struct drm_i915_private *dev_priv = to_i915(dev);
enum transcoder cpu_transcoder = (enum transcoder)pipe;
@ -734,7 +735,7 @@ intel_crt_load_detect(struct intel_crt *crt, enum pipe pipe)
TRANSCONF(dev_priv, cpu_transcoder));
/* Wait for next Vblank to substitue
* border color for Color info */
intel_crtc_wait_for_next_vblank(intel_crtc_for_pipe(dev_priv, pipe));
intel_crtc_wait_for_next_vblank(intel_crtc_for_pipe(display, pipe));
st00 = intel_de_read8(dev_priv, _VGA_MSR_WRITE);
status = ((st00 & (1 << 4)) != 0) ?
connector_status_connected :

View File

@ -9,6 +9,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_plane.h>
#include <drm/drm_vblank.h>
#include <drm/drm_vblank_work.h>
#include "i915_vgpu.h"
@ -48,12 +49,12 @@ struct intel_crtc *intel_first_crtc(struct drm_i915_private *i915)
return to_intel_crtc(drm_crtc_from_index(&i915->drm, 0));
}
struct intel_crtc *intel_crtc_for_pipe(struct drm_i915_private *i915,
struct intel_crtc *intel_crtc_for_pipe(struct intel_display *display,
enum pipe pipe)
{
struct intel_crtc *crtc;
for_each_intel_crtc(&i915->drm, crtc) {
for_each_intel_crtc(display->drm, crtc) {
if (crtc->pipe == pipe)
return crtc;
}
@ -69,7 +70,8 @@ void intel_crtc_wait_for_next_vblank(struct intel_crtc *crtc)
void intel_wait_for_vblank_if_active(struct drm_i915_private *i915,
enum pipe pipe)
{
struct intel_crtc *crtc = intel_crtc_for_pipe(i915, pipe);
struct intel_display *display = &i915->display;
struct intel_crtc *crtc = intel_crtc_for_pipe(display, pipe);
if (crtc->active)
intel_crtc_wait_for_next_vblank(crtc);
@ -122,6 +124,8 @@ void intel_crtc_vblank_on(const struct intel_crtc_state *crtc_state)
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
crtc->block_dc_for_vblank = intel_psr_needs_block_dc_vblank(crtc_state);
assert_vblank_disabled(&crtc->base);
drm_crtc_set_max_vblank_count(&crtc->base,
intel_crtc_max_vblank_count(crtc_state));
@ -138,6 +142,7 @@ void intel_crtc_vblank_on(const struct intel_crtc_state *crtc_state)
void intel_crtc_vblank_off(const struct intel_crtc_state *crtc_state)
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct intel_display *display = to_intel_display(crtc);
/*
* Should really happen exactly when we disable the pipe
@ -148,6 +153,10 @@ void intel_crtc_vblank_off(const struct intel_crtc_state *crtc_state)
drm_crtc_vblank_off(&crtc->base);
assert_vblank_disabled(&crtc->base);
crtc->block_dc_for_vblank = false;
flush_work(&display->irq.vblank_dc_work);
}
struct intel_crtc_state *intel_crtc_state_alloc(struct intel_crtc *crtc)
@ -387,13 +396,31 @@ int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe)
return ret;
}
int intel_crtc_get_pipe_from_crtc_id_ioctl(struct drm_device *dev, void *data,
struct drm_file *file)
{
struct drm_i915_get_pipe_from_crtc_id *pipe_from_crtc_id = data;
struct drm_crtc *drm_crtc;
struct intel_crtc *crtc;
drm_crtc = drm_crtc_find(dev, file, pipe_from_crtc_id->crtc_id);
if (!drm_crtc)
return -ENOENT;
crtc = to_intel_crtc(drm_crtc);
pipe_from_crtc_id->pipe = crtc->pipe;
return 0;
}
static bool intel_crtc_needs_vblank_work(const struct intel_crtc_state *crtc_state)
{
return crtc_state->hw.active &&
!intel_crtc_needs_modeset(crtc_state) &&
!crtc_state->preload_luts &&
!intel_crtc_needs_modeset(crtc_state) &&
intel_crtc_needs_color_update(crtc_state) &&
!intel_color_uses_dsb(crtc_state);
!intel_color_uses_dsb(crtc_state) &&
!crtc_state->use_dsb;
}
static void intel_crtc_vblank_work(struct kthread_work *base)
@ -457,6 +484,17 @@ int intel_usecs_to_scanlines(const struct drm_display_mode *adjusted_mode,
1000 * adjusted_mode->crtc_htotal);
}
int intel_scanlines_to_usecs(const struct drm_display_mode *adjusted_mode,
int scanlines)
{
/* paranoia */
if (!adjusted_mode->crtc_clock)
return 1;
return DIV_ROUND_UP_ULL(mul_u32_u32(scanlines, adjusted_mode->crtc_htotal * 1000),
adjusted_mode->crtc_clock);
}
/**
* intel_pipe_update_start() - start update of a set of display registers
* @state: the atomic state
@ -484,12 +522,8 @@ void intel_pipe_update_start(struct intel_atomic_state *state,
intel_psr_lock(new_crtc_state);
if (new_crtc_state->do_async_flip) {
spin_lock_irq(&crtc->base.dev->event_lock);
/* arm the event for the flip done irq handler */
crtc->flip_done_event = new_crtc_state->uapi.event;
spin_unlock_irq(&crtc->base.dev->event_lock);
new_crtc_state->uapi.event = NULL;
intel_crtc_prepare_vblank_event(new_crtc_state,
&crtc->flip_done_event);
return;
}
@ -589,6 +623,19 @@ void intel_crtc_arm_vblank_event(struct intel_crtc_state *crtc_state)
crtc_state->uapi.event = NULL;
}
void intel_crtc_prepare_vblank_event(struct intel_crtc_state *crtc_state,
struct drm_pending_vblank_event **event)
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
unsigned long irqflags;
spin_lock_irqsave(&crtc->base.dev->event_lock, irqflags);
*event = crtc_state->uapi.event;
spin_unlock_irqrestore(&crtc->base.dev->event_lock, irqflags);
crtc_state->uapi.event = NULL;
}
/**
* intel_pipe_update_end() - end update of a set of display registers
* @state: the atomic state

View File

@ -10,11 +10,15 @@
enum i9xx_plane_id;
enum pipe;
struct drm_device;
struct drm_display_mode;
struct drm_file;
struct drm_i915_private;
struct drm_pending_vblank_event;
struct intel_atomic_state;
struct intel_crtc;
struct intel_crtc_state;
struct intel_display;
/*
* FIXME: We should instead only take spinlocks once for the entire update
@ -28,9 +32,15 @@ struct intel_crtc_state;
int intel_usecs_to_scanlines(const struct drm_display_mode *adjusted_mode,
int usecs);
int intel_scanlines_to_usecs(const struct drm_display_mode *adjusted_mode,
int scanlines);
void intel_crtc_arm_vblank_event(struct intel_crtc_state *crtc_state);
void intel_crtc_prepare_vblank_event(struct intel_crtc_state *crtc_state,
struct drm_pending_vblank_event **event);
u32 intel_crtc_max_vblank_count(const struct intel_crtc_state *crtc_state);
int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe);
int intel_crtc_get_pipe_from_crtc_id_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
struct intel_crtc_state *intel_crtc_state_alloc(struct intel_crtc *crtc);
void intel_crtc_state_reset(struct intel_crtc_state *crtc_state,
struct intel_crtc *crtc);
@ -43,7 +53,7 @@ void intel_pipe_update_end(struct intel_atomic_state *state,
struct intel_crtc *crtc);
void intel_wait_for_vblank_workers(struct intel_atomic_state *state);
struct intel_crtc *intel_first_crtc(struct drm_i915_private *i915);
struct intel_crtc *intel_crtc_for_pipe(struct drm_i915_private *i915,
struct intel_crtc *intel_crtc_for_pipe(struct intel_display *display,
enum pipe pipe);
void intel_wait_for_vblank_if_active(struct drm_i915_private *i915,
enum pipe pipe);

View File

@ -9,6 +9,7 @@
#include <drm/drm_blend.h>
#include <drm/drm_damage_helper.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_vblank.h>
#include "i915_reg.h"
#include "intel_atomic.h"
@ -26,8 +27,6 @@
#include "intel_vblank.h"
#include "skl_watermark.h"
#include "gem/i915_gem_object.h"
/* Cursor formats */
static const u32 intel_cursor_formats[] = {
DRM_FORMAT_ARGB8888,
@ -275,7 +274,8 @@ static int i845_check_cursor(struct intel_crtc_state *crtc_state,
}
/* TODO: split into noarm+arm pair */
static void i845_cursor_update_arm(struct intel_plane *plane,
static void i845_cursor_update_arm(struct intel_dsb *dsb,
struct intel_plane *plane,
const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state)
{
@ -315,10 +315,11 @@ static void i845_cursor_update_arm(struct intel_plane *plane,
}
}
static void i845_cursor_disable_arm(struct intel_plane *plane,
static void i845_cursor_disable_arm(struct intel_dsb *dsb,
struct intel_plane *plane,
const struct intel_crtc_state *crtc_state)
{
i845_cursor_update_arm(plane, crtc_state, NULL);
i845_cursor_update_arm(dsb, plane, crtc_state, NULL);
}
static bool i845_cursor_get_hw_state(struct intel_plane *plane,
@ -527,22 +528,25 @@ static int i9xx_check_cursor(struct intel_crtc_state *crtc_state,
return 0;
}
static void i9xx_cursor_disable_sel_fetch_arm(struct intel_plane *plane,
static void i9xx_cursor_disable_sel_fetch_arm(struct intel_dsb *dsb,
struct intel_plane *plane,
const struct intel_crtc_state *crtc_state)
{
struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
struct intel_display *display = to_intel_display(plane->base.dev);
enum pipe pipe = plane->pipe;
if (!crtc_state->enable_psr2_sel_fetch)
return;
intel_de_write_fw(dev_priv, SEL_FETCH_CUR_CTL(pipe), 0);
intel_de_write_dsb(display, dsb, SEL_FETCH_CUR_CTL(pipe), 0);
}
static void wa_16021440873(struct intel_plane *plane,
static void wa_16021440873(struct intel_dsb *dsb,
struct intel_plane *plane,
const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state)
{
struct intel_display *display = to_intel_display(plane->base.dev);
struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
u32 ctl = plane_state->ctl;
int et_y_position = drm_rect_height(&crtc_state->pipe_src) + 1;
@ -551,16 +555,18 @@ static void wa_16021440873(struct intel_plane *plane,
ctl &= ~MCURSOR_MODE_MASK;
ctl |= MCURSOR_MODE_64_2B;
intel_de_write_fw(dev_priv, SEL_FETCH_CUR_CTL(pipe), ctl);
intel_de_write_dsb(display, dsb, SEL_FETCH_CUR_CTL(pipe), ctl);
intel_de_write(dev_priv, CURPOS_ERLY_TPT(dev_priv, pipe),
CURSOR_POS_Y(et_y_position));
intel_de_write_dsb(display, dsb, CURPOS_ERLY_TPT(dev_priv, pipe),
CURSOR_POS_Y(et_y_position));
}
static void i9xx_cursor_update_sel_fetch_arm(struct intel_plane *plane,
static void i9xx_cursor_update_sel_fetch_arm(struct intel_dsb *dsb,
struct intel_plane *plane,
const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state)
{
struct intel_display *display = to_intel_display(plane->base.dev);
struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
enum pipe pipe = plane->pipe;
@ -571,19 +577,17 @@ static void i9xx_cursor_update_sel_fetch_arm(struct intel_plane *plane,
if (crtc_state->enable_psr2_su_region_et) {
u32 val = intel_cursor_position(crtc_state, plane_state,
true);
intel_de_write_fw(dev_priv,
CURPOS_ERLY_TPT(dev_priv, pipe),
val);
intel_de_write_dsb(display, dsb, CURPOS_ERLY_TPT(dev_priv, pipe), val);
}
intel_de_write_fw(dev_priv, SEL_FETCH_CUR_CTL(pipe),
plane_state->ctl);
intel_de_write_dsb(display, dsb, SEL_FETCH_CUR_CTL(pipe), plane_state->ctl);
} else {
/* Wa_16021440873 */
if (crtc_state->enable_psr2_su_region_et)
wa_16021440873(plane, crtc_state, plane_state);
wa_16021440873(dsb, plane, crtc_state, plane_state);
else
i9xx_cursor_disable_sel_fetch_arm(plane, crtc_state);
i9xx_cursor_disable_sel_fetch_arm(dsb, plane, crtc_state);
}
}
@ -610,9 +614,11 @@ static u32 skl_cursor_wm_reg_val(const struct skl_wm_level *level)
return val;
}
static void skl_write_cursor_wm(struct intel_plane *plane,
static void skl_write_cursor_wm(struct intel_dsb *dsb,
struct intel_plane *plane,
const struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(plane->base.dev);
struct drm_i915_private *i915 = to_i915(plane->base.dev);
enum plane_id plane_id = plane->id;
enum pipe pipe = plane->pipe;
@ -622,30 +628,32 @@ static void skl_write_cursor_wm(struct intel_plane *plane,
int level;
for (level = 0; level < i915->display.wm.num_levels; level++)
intel_de_write_fw(i915, CUR_WM(pipe, level),
skl_cursor_wm_reg_val(skl_plane_wm_level(pipe_wm, plane_id, level)));
intel_de_write_dsb(display, dsb, CUR_WM(pipe, level),
skl_cursor_wm_reg_val(skl_plane_wm_level(pipe_wm, plane_id, level)));
intel_de_write_fw(i915, CUR_WM_TRANS(pipe),
skl_cursor_wm_reg_val(skl_plane_trans_wm(pipe_wm, plane_id)));
intel_de_write_dsb(display, dsb, CUR_WM_TRANS(pipe),
skl_cursor_wm_reg_val(skl_plane_trans_wm(pipe_wm, plane_id)));
if (HAS_HW_SAGV_WM(i915)) {
const struct skl_plane_wm *wm = &pipe_wm->planes[plane_id];
intel_de_write_fw(i915, CUR_WM_SAGV(pipe),
skl_cursor_wm_reg_val(&wm->sagv.wm0));
intel_de_write_fw(i915, CUR_WM_SAGV_TRANS(pipe),
skl_cursor_wm_reg_val(&wm->sagv.trans_wm));
intel_de_write_dsb(display, dsb, CUR_WM_SAGV(pipe),
skl_cursor_wm_reg_val(&wm->sagv.wm0));
intel_de_write_dsb(display, dsb, CUR_WM_SAGV_TRANS(pipe),
skl_cursor_wm_reg_val(&wm->sagv.trans_wm));
}
intel_de_write_fw(i915, CUR_BUF_CFG(pipe),
skl_cursor_ddb_reg_val(ddb));
intel_de_write_dsb(display, dsb, CUR_BUF_CFG(pipe),
skl_cursor_ddb_reg_val(ddb));
}
/* TODO: split into noarm+arm pair */
static void i9xx_cursor_update_arm(struct intel_plane *plane,
static void i9xx_cursor_update_arm(struct intel_dsb *dsb,
struct intel_plane *plane,
const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state)
{
struct intel_display *display = to_intel_display(plane->base.dev);
struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
enum pipe pipe = plane->pipe;
u32 cntl = 0, base = 0, pos = 0, fbc_ctl = 0;
@ -685,38 +693,36 @@ static void i9xx_cursor_update_arm(struct intel_plane *plane,
*/
if (DISPLAY_VER(dev_priv) >= 9)
skl_write_cursor_wm(plane, crtc_state);
skl_write_cursor_wm(dsb, plane, crtc_state);
if (plane_state)
i9xx_cursor_update_sel_fetch_arm(plane, crtc_state,
plane_state);
i9xx_cursor_update_sel_fetch_arm(dsb, plane, crtc_state, plane_state);
else
i9xx_cursor_disable_sel_fetch_arm(plane, crtc_state);
i9xx_cursor_disable_sel_fetch_arm(dsb, plane, crtc_state);
if (plane->cursor.base != base ||
plane->cursor.size != fbc_ctl ||
plane->cursor.cntl != cntl) {
if (HAS_CUR_FBC(dev_priv))
intel_de_write_fw(dev_priv,
CUR_FBC_CTL(dev_priv, pipe),
fbc_ctl);
intel_de_write_fw(dev_priv, CURCNTR(dev_priv, pipe), cntl);
intel_de_write_fw(dev_priv, CURPOS(dev_priv, pipe), pos);
intel_de_write_fw(dev_priv, CURBASE(dev_priv, pipe), base);
intel_de_write_dsb(display, dsb, CUR_FBC_CTL(dev_priv, pipe), fbc_ctl);
intel_de_write_dsb(display, dsb, CURCNTR(dev_priv, pipe), cntl);
intel_de_write_dsb(display, dsb, CURPOS(dev_priv, pipe), pos);
intel_de_write_dsb(display, dsb, CURBASE(dev_priv, pipe), base);
plane->cursor.base = base;
plane->cursor.size = fbc_ctl;
plane->cursor.cntl = cntl;
} else {
intel_de_write_fw(dev_priv, CURPOS(dev_priv, pipe), pos);
intel_de_write_fw(dev_priv, CURBASE(dev_priv, pipe), base);
intel_de_write_dsb(display, dsb, CURPOS(dev_priv, pipe), pos);
intel_de_write_dsb(display, dsb, CURBASE(dev_priv, pipe), base);
}
}
static void i9xx_cursor_disable_arm(struct intel_plane *plane,
static void i9xx_cursor_disable_arm(struct intel_dsb *dsb,
struct intel_plane *plane,
const struct intel_crtc_state *crtc_state)
{
i9xx_cursor_update_arm(plane, crtc_state, NULL);
i9xx_cursor_update_arm(dsb, plane, crtc_state, NULL);
}
static bool i9xx_cursor_get_hw_state(struct intel_plane *plane,
@ -905,10 +911,10 @@ intel_legacy_cursor_update(struct drm_plane *_plane,
}
if (new_plane_state->uapi.visible) {
intel_plane_update_noarm(plane, crtc_state, new_plane_state);
intel_plane_update_arm(plane, crtc_state, new_plane_state);
intel_plane_update_noarm(NULL, plane, crtc_state, new_plane_state);
intel_plane_update_arm(NULL, plane, crtc_state, new_plane_state);
} else {
intel_plane_disable_arm(plane, crtc_state);
intel_plane_disable_arm(NULL, plane, crtc_state);
}
local_irq_enable();

View File

@ -923,10 +923,10 @@ static const struct intel_c20pll_state mtl_c20_dp_uhbr20 = {
},
.mplla = { 0x3104, /* mplla cfg0 */
0xd105, /* mplla cfg1 */
0xc025, /* mplla cfg2 */
0xc025, /* mplla cfg3 */
0xa6ab, /* mplla cfg4 */
0x8c00, /* mplla cfg5 */
0x9217, /* mplla cfg2 */
0x9217, /* mplla cfg3 */
0x8c00, /* mplla cfg4 */
0x759a, /* mplla cfg5 */
0x4000, /* mplla cfg6 */
0x0003, /* mplla cfg7 */
0x3555, /* mplla cfg8 */

View File

@ -54,6 +54,7 @@
#include "intel_dp_aux.h"
#include "intel_dp_link_training.h"
#include "intel_dp_mst.h"
#include "intel_dp_test.h"
#include "intel_dp_tunnel.h"
#include "intel_dpio_phy.h"
#include "intel_dsi.h"
@ -3115,11 +3116,12 @@ static void intel_ddi_post_disable_hdmi_or_sst(struct intel_atomic_state *state,
const struct intel_crtc_state *old_crtc_state,
const struct drm_connector_state *old_conn_state)
{
struct intel_display *display = to_intel_display(encoder);
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct intel_crtc *pipe_crtc;
int i;
for_each_intel_crtc_in_pipe_mask(&dev_priv->drm, pipe_crtc,
intel_crtc_joined_pipe_mask(old_crtc_state)) {
for_each_pipe_crtc_modeset_disable(display, pipe_crtc, old_crtc_state, i) {
const struct intel_crtc_state *old_pipe_crtc_state =
intel_atomic_get_old_crtc_state(state, pipe_crtc);
@ -3130,8 +3132,7 @@ static void intel_ddi_post_disable_hdmi_or_sst(struct intel_atomic_state *state,
intel_ddi_disable_transcoder_func(old_crtc_state);
for_each_intel_crtc_in_pipe_mask(&dev_priv->drm, pipe_crtc,
intel_crtc_joined_pipe_mask(old_crtc_state)) {
for_each_pipe_crtc_modeset_disable(display, pipe_crtc, old_crtc_state, i) {
const struct intel_crtc_state *old_pipe_crtc_state =
intel_atomic_get_old_crtc_state(state, pipe_crtc);
@ -3382,8 +3383,9 @@ static void intel_enable_ddi(struct intel_atomic_state *state,
const struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state)
{
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
struct intel_display *display = to_intel_display(encoder);
struct intel_crtc *pipe_crtc;
int i;
intel_ddi_enable_transcoder_func(encoder, crtc_state);
@ -3394,8 +3396,7 @@ static void intel_enable_ddi(struct intel_atomic_state *state,
intel_ddi_wait_for_fec_status(encoder, crtc_state, true);
for_each_intel_crtc_in_pipe_mask_reverse(&i915->drm, pipe_crtc,
intel_crtc_joined_pipe_mask(crtc_state)) {
for_each_pipe_crtc_modeset_enable(display, pipe_crtc, crtc_state, i) {
const struct intel_crtc_state *pipe_crtc_state =
intel_atomic_get_new_crtc_state(state, pipe_crtc);
@ -4550,12 +4551,8 @@ intel_ddi_hotplug(struct intel_encoder *encoder,
enum intel_hotplug_state state;
int ret;
if (intel_dp->compliance.test_active &&
intel_dp->compliance.test_type == DP_TEST_LINK_PHY_TEST_PATTERN) {
intel_dp_phy_test(encoder);
/* just do the PHY test and nothing else */
if (intel_dp_test_phy(intel_dp))
return INTEL_HOTPLUG_UNCHANGED;
}
state = intel_encoder_hotplug(encoder, connector);

View File

@ -8,6 +8,7 @@
#include "i915_drv.h"
#include "i915_trace.h"
#include "intel_dsb.h"
#include "intel_uncore.h"
static inline struct intel_uncore *__to_uncore(struct intel_display *display)
@ -233,4 +234,14 @@ __intel_de_write_notrace(struct intel_display *display, i915_reg_t reg,
}
#define intel_de_write_notrace(p,...) __intel_de_write_notrace(__to_intel_display(p), __VA_ARGS__)
static __always_inline void
intel_de_write_dsb(struct intel_display *display, struct intel_dsb *dsb,
i915_reg_t reg, u32 val)
{
if (dsb)
intel_dsb_reg_write(dsb, reg, val);
else
intel_de_write_fw(display, reg, val);
}
#endif /* __INTEL_DE_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -40,7 +40,6 @@ struct drm_encoder;
struct drm_file;
struct drm_format_info;
struct drm_framebuffer;
struct drm_i915_gem_object;
struct drm_i915_private;
struct drm_mode_fb_cmd2;
struct drm_modeset_acquire_ctx;
@ -52,6 +51,7 @@ struct intel_atomic_state;
struct intel_crtc;
struct intel_crtc_state;
struct intel_digital_port;
struct intel_display;
struct intel_dp;
struct intel_encoder;
struct intel_initial_plane_config;
@ -94,16 +94,6 @@ static inline bool transcoder_is_dsi(enum transcoder transcoder)
return transcoder == TRANSCODER_DSI_A || transcoder == TRANSCODER_DSI_C;
}
/*
* Global legacy plane identifier. Valid only for primary/sprite
* planes on pre-g4x, and only for primary planes on g4x-bdw.
*/
enum i9xx_plane_id {
PLANE_A,
PLANE_B,
PLANE_C,
};
#define plane_name(p) ((p) + 'A')
#define for_each_plane_id_on_crtc(__crtc, __p) \
@ -401,6 +391,30 @@ enum phy_fia {
((connector) = to_intel_connector((__state)->base.connectors[__i].ptr), \
(new_connector_state) = to_intel_digital_connector_state((__state)->base.connectors[__i].new_state), 1))
#define for_each_crtc_in_masks(display, crtc, first_pipes, second_pipes, i) \
for ((i) = 0; \
(i) < (I915_MAX_PIPES * 2) && ((crtc) = intel_crtc_for_pipe(display, (i) % I915_MAX_PIPES), 1); \
(i)++) \
for_each_if((crtc) && ((first_pipes) | ((second_pipes) << I915_MAX_PIPES)) & BIT(i))
#define for_each_crtc_in_masks_reverse(display, crtc, first_pipes, second_pipes, i) \
for ((i) = (I915_MAX_PIPES * 2 - 1); \
(i) >= 0 && ((crtc) = intel_crtc_for_pipe(display, (i) % I915_MAX_PIPES), 1); \
(i)--) \
for_each_if((crtc) && ((first_pipes) | ((second_pipes) << I915_MAX_PIPES)) & BIT(i))
#define for_each_pipe_crtc_modeset_disable(display, crtc, crtc_state, i) \
for_each_crtc_in_masks(display, crtc, \
_intel_modeset_primary_pipes(crtc_state), \
_intel_modeset_secondary_pipes(crtc_state), \
i)
#define for_each_pipe_crtc_modeset_enable(display, crtc, crtc_state, i) \
for_each_crtc_in_masks_reverse(display, crtc, \
_intel_modeset_primary_pipes(crtc_state), \
_intel_modeset_secondary_pipes(crtc_state), \
i)
int intel_atomic_check(struct drm_device *dev, struct drm_atomic_state *state);
int intel_atomic_add_affected_planes(struct intel_atomic_state *state,
struct intel_crtc *crtc);
@ -415,7 +429,7 @@ u32 intel_plane_fb_max_stride(struct drm_i915_private *dev_priv,
enum drm_mode_status
intel_mode_valid_max_plane_size(struct drm_i915_private *dev_priv,
const struct drm_display_mode *mode,
bool joiner);
int num_joined_pipes);
enum drm_mode_status
intel_cpu_transcoder_mode_valid(struct drm_i915_private *i915,
const struct drm_display_mode *mode);
@ -425,7 +439,14 @@ bool is_trans_port_sync_master(const struct intel_crtc_state *state);
u8 intel_crtc_joined_pipe_mask(const struct intel_crtc_state *crtc_state);
bool intel_crtc_is_joiner_secondary(const struct intel_crtc_state *crtc_state);
bool intel_crtc_is_joiner_primary(const struct intel_crtc_state *crtc_state);
bool intel_crtc_is_bigjoiner_primary(const struct intel_crtc_state *crtc_state);
bool intel_crtc_is_bigjoiner_secondary(const struct intel_crtc_state *crtc_state);
bool intel_crtc_is_ultrajoiner(const struct intel_crtc_state *crtc_state);
bool intel_crtc_is_ultrajoiner_primary(const struct intel_crtc_state *crtc_state);
bool intel_crtc_ultrajoiner_enable_needed(const struct intel_crtc_state *crtc_state);
u8 intel_crtc_joiner_secondary_pipes(const struct intel_crtc_state *crtc_state);
u8 _intel_modeset_primary_pipes(const struct intel_crtc_state *crtc_state);
u8 _intel_modeset_secondary_pipes(const struct intel_crtc_state *crtc_state);
struct intel_crtc *intel_primary_crtc(const struct intel_crtc_state *crtc_state);
bool intel_crtc_get_pipe_config(struct intel_crtc_state *crtc_state);
bool intel_pipe_config_compare(const struct intel_crtc_state *current_config,
@ -437,8 +458,8 @@ void i9xx_set_pipeconf(const struct intel_crtc_state *crtc_state);
void ilk_set_pipeconf(const struct intel_crtc_state *crtc_state);
void intel_enable_transcoder(const struct intel_crtc_state *new_crtc_state);
void intel_disable_transcoder(const struct intel_crtc_state *old_crtc_state);
void i830_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe);
void i830_disable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe);
void i830_enable_pipe(struct intel_display *display, enum pipe pipe);
void i830_disable_pipe(struct intel_display *display, enum pipe pipe);
int vlv_get_hpll_vco(struct drm_i915_private *dev_priv);
int vlv_get_cck_clock(struct drm_i915_private *dev_priv,
const char *name, u32 reg, int ref_freq);
@ -470,16 +491,10 @@ bool intel_encoder_is_snps(struct intel_encoder *encoder);
bool intel_encoder_is_tc(struct intel_encoder *encoder);
enum tc_port intel_encoder_to_tc(struct intel_encoder *encoder);
int intel_get_pipe_from_crtc_id_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
int ilk_get_lanes_required(int target_clock, int link_bw, int bpp);
void vlv_wait_port_ready(struct drm_i915_private *dev_priv,
struct intel_digital_port *dig_port,
unsigned int expected_mask);
struct drm_framebuffer *
intel_framebuffer_create(struct drm_i915_gem_object *obj,
struct drm_mode_fb_cmd2 *mode_cmd);
bool intel_fuzzy_clock_check(int clock1, int clock2);
@ -586,5 +601,6 @@ bool assert_port_valid(struct drm_i915_private *i915, enum port port);
})
bool intel_scanout_needs_vtd_wa(struct drm_i915_private *i915);
int intel_crtc_num_joined_pipes(const struct intel_crtc_state *crtc_state);
#endif

View File

@ -81,10 +81,8 @@ struct intel_display_funcs {
struct intel_wm_funcs {
/* update_wm is for legacy wm management */
void (*update_wm)(struct drm_i915_private *dev_priv);
int (*compute_pipe_wm)(struct intel_atomic_state *state,
struct intel_crtc *crtc);
int (*compute_intermediate_wm)(struct intel_atomic_state *state,
struct intel_crtc *crtc);
int (*compute_watermarks)(struct intel_atomic_state *state,
struct intel_crtc *crtc);
void (*initial_watermarks)(struct intel_atomic_state *state,
struct intel_crtc *crtc);
void (*atomic_update_watermarks)(struct intel_atomic_state *state,
@ -457,6 +455,8 @@ struct intel_display {
/* For i915gm/i945gm vblank irq workaround */
u8 vblank_enabled;
struct work_struct vblank_dc_work;
u32 de_irq_mask[I915_MAX_PIPES];
u32 pipestat_irq_mask[I915_MAX_PIPES];
} irq;

View File

@ -3,6 +3,7 @@
* Copyright © 2020 Intel Corporation
*/
#include <linux/debugfs.h>
#include <linux/string_helpers.h>
#include <drm/drm_debugfs.h>
@ -10,13 +11,13 @@
#include <drm/drm_fourcc.h>
#include "hsw_ips.h"
#include "i915_debugfs.h"
#include "i915_irq.h"
#include "i915_reg.h"
#include "intel_alpm.h"
#include "intel_bo.h"
#include "intel_crtc.h"
#include "intel_de.h"
#include "intel_crtc_state_dump.h"
#include "intel_de.h"
#include "intel_display_debugfs.h"
#include "intel_display_debugfs_params.h"
#include "intel_display_power.h"
@ -26,7 +27,9 @@
#include "intel_dp.h"
#include "intel_dp_link_training.h"
#include "intel_dp_mst.h"
#include "intel_dp_test.h"
#include "intel_drrs.h"
#include "intel_fb.h"
#include "intel_fbc.h"
#include "intel_fbdev.h"
#include "intel_hdcp.h"
@ -39,11 +42,28 @@
#include "intel_vdsc.h"
#include "intel_wm.h"
static struct intel_display *node_to_intel_display(struct drm_info_node *node)
{
return to_intel_display(node->minor->dev);
}
static inline struct drm_i915_private *node_to_i915(struct drm_info_node *node)
{
return to_i915(node->minor->dev);
}
static int intel_display_caps(struct seq_file *m, void *data)
{
struct intel_display *display = node_to_intel_display(m->private);
struct drm_printer p = drm_seq_file_printer(m);
intel_display_device_info_print(DISPLAY_INFO(display),
DISPLAY_RUNTIME_INFO(display), &p);
intel_display_params_dump(&display->params, display->drm->driver->name, &p);
return 0;
}
static int i915_frontbuffer_tracking(struct seq_file *m, void *unused)
{
struct drm_i915_private *dev_priv = node_to_i915(m->private);
@ -106,7 +126,7 @@ static int i915_gem_framebuffer_info(struct seq_file *m, void *data)
fbdev_fb->base.format->cpp[0] * 8,
fbdev_fb->base.modifier,
drm_framebuffer_read_refcount(&fbdev_fb->base));
i915_debugfs_describe_obj(m, intel_fb_obj(&fbdev_fb->base));
intel_bo_describe(m, intel_fb_bo(&fbdev_fb->base));
seq_putc(m, '\n');
}
#endif
@ -124,7 +144,7 @@ static int i915_gem_framebuffer_info(struct seq_file *m, void *data)
fb->base.format->cpp[0] * 8,
fb->base.modifier,
drm_framebuffer_read_refcount(&fb->base));
i915_debugfs_describe_obj(m, intel_fb_obj(&fb->base));
intel_bo_describe(m, intel_fb_bo(&fb->base));
seq_putc(m, '\n');
}
mutex_unlock(&dev_priv->drm.mode_config.fb_lock);
@ -424,7 +444,7 @@ static void intel_scaler_info(struct seq_file *m, struct intel_crtc *crtc)
int num_scalers = crtc->num_scalers;
int i;
/* Not all platformas have a scaler */
/* Not all platforms have a scaler */
if (num_scalers) {
seq_printf(m, "\tnum_scalers=%d, scaler_users=%x scaler_id=%d scaling_filter=%d",
num_scalers,
@ -773,198 +793,6 @@ static int i915_dp_mst_info(struct seq_file *m, void *unused)
return 0;
}
static ssize_t i915_displayport_test_active_write(struct file *file,
const char __user *ubuf,
size_t len, loff_t *offp)
{
char *input_buffer;
int status = 0;
struct drm_device *dev;
struct drm_connector *connector;
struct drm_connector_list_iter conn_iter;
struct intel_dp *intel_dp;
int val = 0;
dev = ((struct seq_file *)file->private_data)->private;
if (len == 0)
return 0;
input_buffer = memdup_user_nul(ubuf, len);
if (IS_ERR(input_buffer))
return PTR_ERR(input_buffer);
drm_dbg(dev, "Copied %d bytes from user\n", (unsigned int)len);
drm_connector_list_iter_begin(dev, &conn_iter);
drm_for_each_connector_iter(connector, &conn_iter) {
struct intel_encoder *encoder;
if (connector->connector_type !=
DRM_MODE_CONNECTOR_DisplayPort)
continue;
encoder = to_intel_encoder(connector->encoder);
if (encoder && encoder->type == INTEL_OUTPUT_DP_MST)
continue;
if (encoder && connector->status == connector_status_connected) {
intel_dp = enc_to_intel_dp(encoder);
status = kstrtoint(input_buffer, 10, &val);
if (status < 0)
break;
drm_dbg(dev, "Got %d for test active\n", val);
/* To prevent erroneous activation of the compliance
* testing code, only accept an actual value of 1 here
*/
if (val == 1)
intel_dp->compliance.test_active = true;
else
intel_dp->compliance.test_active = false;
}
}
drm_connector_list_iter_end(&conn_iter);
kfree(input_buffer);
if (status < 0)
return status;
*offp += len;
return len;
}
static int i915_displayport_test_active_show(struct seq_file *m, void *data)
{
struct drm_i915_private *dev_priv = m->private;
struct drm_connector *connector;
struct drm_connector_list_iter conn_iter;
struct intel_dp *intel_dp;
drm_connector_list_iter_begin(&dev_priv->drm, &conn_iter);
drm_for_each_connector_iter(connector, &conn_iter) {
struct intel_encoder *encoder;
if (connector->connector_type !=
DRM_MODE_CONNECTOR_DisplayPort)
continue;
encoder = to_intel_encoder(connector->encoder);
if (encoder && encoder->type == INTEL_OUTPUT_DP_MST)
continue;
if (encoder && connector->status == connector_status_connected) {
intel_dp = enc_to_intel_dp(encoder);
if (intel_dp->compliance.test_active)
seq_puts(m, "1");
else
seq_puts(m, "0");
} else
seq_puts(m, "0");
}
drm_connector_list_iter_end(&conn_iter);
return 0;
}
static int i915_displayport_test_active_open(struct inode *inode,
struct file *file)
{
return single_open(file, i915_displayport_test_active_show,
inode->i_private);
}
static const struct file_operations i915_displayport_test_active_fops = {
.owner = THIS_MODULE,
.open = i915_displayport_test_active_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
.write = i915_displayport_test_active_write
};
static int i915_displayport_test_data_show(struct seq_file *m, void *data)
{
struct drm_i915_private *dev_priv = m->private;
struct drm_connector *connector;
struct drm_connector_list_iter conn_iter;
struct intel_dp *intel_dp;
drm_connector_list_iter_begin(&dev_priv->drm, &conn_iter);
drm_for_each_connector_iter(connector, &conn_iter) {
struct intel_encoder *encoder;
if (connector->connector_type !=
DRM_MODE_CONNECTOR_DisplayPort)
continue;
encoder = to_intel_encoder(connector->encoder);
if (encoder && encoder->type == INTEL_OUTPUT_DP_MST)
continue;
if (encoder && connector->status == connector_status_connected) {
intel_dp = enc_to_intel_dp(encoder);
if (intel_dp->compliance.test_type ==
DP_TEST_LINK_EDID_READ)
seq_printf(m, "%lx",
intel_dp->compliance.test_data.edid);
else if (intel_dp->compliance.test_type ==
DP_TEST_LINK_VIDEO_PATTERN) {
seq_printf(m, "hdisplay: %d\n",
intel_dp->compliance.test_data.hdisplay);
seq_printf(m, "vdisplay: %d\n",
intel_dp->compliance.test_data.vdisplay);
seq_printf(m, "bpc: %u\n",
intel_dp->compliance.test_data.bpc);
} else if (intel_dp->compliance.test_type ==
DP_TEST_LINK_PHY_TEST_PATTERN) {
seq_printf(m, "pattern: %d\n",
intel_dp->compliance.test_data.phytest.phy_pattern);
seq_printf(m, "Number of lanes: %d\n",
intel_dp->compliance.test_data.phytest.num_lanes);
seq_printf(m, "Link Rate: %d\n",
intel_dp->compliance.test_data.phytest.link_rate);
seq_printf(m, "level: %02x\n",
intel_dp->train_set[0]);
}
} else
seq_puts(m, "0");
}
drm_connector_list_iter_end(&conn_iter);
return 0;
}
DEFINE_SHOW_ATTRIBUTE(i915_displayport_test_data);
static int i915_displayport_test_type_show(struct seq_file *m, void *data)
{
struct drm_i915_private *dev_priv = m->private;
struct drm_connector *connector;
struct drm_connector_list_iter conn_iter;
struct intel_dp *intel_dp;
drm_connector_list_iter_begin(&dev_priv->drm, &conn_iter);
drm_for_each_connector_iter(connector, &conn_iter) {
struct intel_encoder *encoder;
if (connector->connector_type !=
DRM_MODE_CONNECTOR_DisplayPort)
continue;
encoder = to_intel_encoder(connector->encoder);
if (encoder && encoder->type == INTEL_OUTPUT_DP_MST)
continue;
if (encoder && connector->status == connector_status_connected) {
intel_dp = enc_to_intel_dp(encoder);
seq_printf(m, "%02lx\n", intel_dp->compliance.test_type);
} else
seq_puts(m, "0");
}
drm_connector_list_iter_end(&conn_iter);
return 0;
}
DEFINE_SHOW_ATTRIBUTE(i915_displayport_test_type);
static ssize_t
i915_fifo_underrun_reset_write(struct file *filp,
const char __user *ubuf,
@ -1025,6 +853,7 @@ static const struct file_operations i915_fifo_underrun_reset_ops = {
};
static const struct drm_info_list intel_display_debugfs_list[] = {
{"intel_display_caps", intel_display_caps, 0},
{"i915_frontbuffer_tracking", i915_frontbuffer_tracking, 0},
{"i915_sr_status", i915_sr_status, 0},
{"i915_gem_framebuffer", i915_gem_framebuffer_info, 0},
@ -1037,37 +866,22 @@ static const struct drm_info_list intel_display_debugfs_list[] = {
{"i915_lpsp_status", i915_lpsp_status, 0},
};
static const struct {
const char *name;
const struct file_operations *fops;
} intel_display_debugfs_files[] = {
{"i915_fifo_underrun_reset", &i915_fifo_underrun_reset_ops},
{"i915_dp_test_data", &i915_displayport_test_data_fops},
{"i915_dp_test_type", &i915_displayport_test_type_fops},
{"i915_dp_test_active", &i915_displayport_test_active_fops},
};
void intel_display_debugfs_register(struct drm_i915_private *i915)
{
struct intel_display *display = &i915->display;
struct drm_minor *minor = i915->drm.primary;
int i;
for (i = 0; i < ARRAY_SIZE(intel_display_debugfs_files); i++) {
debugfs_create_file(intel_display_debugfs_files[i].name,
0644,
minor->debugfs_root,
to_i915(minor->dev),
intel_display_debugfs_files[i].fops);
}
debugfs_create_file("i915_fifo_underrun_reset", 0644, minor->debugfs_root,
to_i915(minor->dev), &i915_fifo_underrun_reset_ops);
drm_debugfs_create_files(intel_display_debugfs_list,
ARRAY_SIZE(intel_display_debugfs_list),
minor->debugfs_root, minor);
intel_bios_debugfs_register(display);
intel_cdclk_debugfs_register(i915);
intel_dmc_debugfs_register(i915);
intel_cdclk_debugfs_register(display);
intel_dmc_debugfs_register(display);
intel_dp_test_debugfs_register(display);
intel_fbc_debugfs_register(display);
intel_hpd_debugfs_register(i915);
intel_opregion_debugfs_register(display);
@ -1502,6 +1316,68 @@ static int intel_crtc_pipe_show(struct seq_file *m, void *unused)
}
DEFINE_SHOW_ATTRIBUTE(intel_crtc_pipe);
static int i915_joiner_show(struct seq_file *m, void *data)
{
struct intel_connector *connector = m->private;
seq_printf(m, "%d\n", connector->force_joined_pipes);
return 0;
}
static ssize_t i915_joiner_write(struct file *file,
const char __user *ubuf,
size_t len, loff_t *offp)
{
struct seq_file *m = file->private_data;
struct intel_connector *connector = m->private;
struct drm_i915_private *i915 = to_i915(connector->base.dev);
int force_joined_pipes = 0;
int ret;
if (len == 0)
return 0;
ret = kstrtoint_from_user(ubuf, len, 0, &force_joined_pipes);
if (ret < 0)
return ret;
switch (force_joined_pipes) {
case 0:
case 1:
case 2:
connector->force_joined_pipes = force_joined_pipes;
break;
case 4:
if (HAS_ULTRAJOINER(i915)) {
connector->force_joined_pipes = force_joined_pipes;
break;
}
fallthrough;
default:
return -EINVAL;
}
*offp += len;
return len;
}
static int i915_joiner_open(struct inode *inode, struct file *file)
{
return single_open(file, i915_joiner_show, inode->i_private);
}
static const struct file_operations i915_joiner_fops = {
.owner = THIS_MODULE,
.open = i915_joiner_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
.write = i915_joiner_write
};
/**
* intel_connector_debugfs_add - add i915 specific connector debugfs files
* @connector: pointer to a registered intel_connector
@ -1548,11 +1424,11 @@ void intel_connector_debugfs_add(struct intel_connector *connector)
connector, &i915_dsc_fractional_bpp_fops);
}
if (DISPLAY_VER(i915) >= 11 &&
(connector_type == DRM_MODE_CONNECTOR_DisplayPort ||
connector_type == DRM_MODE_CONNECTOR_eDP)) {
debugfs_create_bool("i915_bigjoiner_force_enable", 0644, root,
&connector->force_bigjoiner_enable);
if ((connector_type == DRM_MODE_CONNECTOR_DisplayPort ||
connector_type == DRM_MODE_CONNECTOR_eDP) &&
intel_dp_has_joiner(intel_attached_dp(connector))) {
debugfs_create_file("i915_joiner_force_enable", 0644, root,
connector, &i915_joiner_fops);
}
if (connector_type == DRM_MODE_CONNECTOR_DSI ||

View File

@ -1318,6 +1318,7 @@ static const struct {
INTEL_RPLU_IDS(INTEL_DISPLAY_DEVICE, &adl_p_desc),
INTEL_RPLP_IDS(INTEL_DISPLAY_DEVICE, &adl_p_desc),
INTEL_DG2_IDS(INTEL_DISPLAY_DEVICE, &dg2_desc),
INTEL_ARL_IDS(INTEL_DISPLAY_DEVICE, &mtl_desc),
INTEL_MTL_IDS(INTEL_DISPLAY_DEVICE, &mtl_desc),
INTEL_LNL_IDS(INTEL_DISPLAY_DEVICE, &lnl_desc),
INTEL_BMG_IDS(INTEL_DISPLAY_DEVICE, &bmg_desc),
@ -1531,6 +1532,7 @@ void intel_display_device_remove(struct drm_i915_private *i915)
static void __intel_display_device_info_runtime_init(struct drm_i915_private *i915)
{
struct intel_display *display = &i915->display;
struct intel_display_runtime_info *display_runtime = DISPLAY_RUNTIME_INFO(i915);
enum pipe pipe;
@ -1677,7 +1679,7 @@ static void __intel_display_device_info_runtime_init(struct drm_i915_private *i9
}
}
display_runtime->rawclk_freq = intel_read_rawclk(i915);
display_runtime->rawclk_freq = intel_read_rawclk(display);
drm_dbg_kms(&i915->drm, "rawclk rate: %d kHz\n", display_runtime->rawclk_freq);
return;

View File

@ -118,6 +118,7 @@ enum intel_display_subplatform {
#define HAS_4TILE(i915) (IS_DG2(i915) || DISPLAY_VER(i915) >= 14)
#define HAS_ASYNC_FLIPS(i915) (DISPLAY_VER(i915) >= 5)
#define HAS_BIGJOINER(i915) (DISPLAY_VER(i915) >= 11 && HAS_DSC(i915))
#define HAS_CDCLK_CRAWL(i915) (DISPLAY_INFO(i915)->has_cdclk_crawl)
#define HAS_CDCLK_SQUASH(i915) (DISPLAY_INFO(i915)->has_cdclk_squash)
#define HAS_CUR_FBC(i915) (!HAS_GMCH(i915) && IS_DISPLAY_VER(i915, 7, 13))
@ -149,9 +150,13 @@ enum intel_display_subplatform {
#define HAS_PSR(i915) (DISPLAY_INFO(i915)->has_psr)
#define HAS_PSR_HW_TRACKING(i915) (DISPLAY_INFO(i915)->has_psr_hw_tracking)
#define HAS_PSR2_SEL_FETCH(i915) (DISPLAY_VER(i915) >= 12)
#define HAS_SAGV(i915) (DISPLAY_VER(i915) >= 9 && !IS_LP(i915))
#define HAS_SAGV(i915) (DISPLAY_VER(i915) >= 9 && !IS_BROXTON(i915) && !IS_GEMINILAKE(i915))
#define HAS_TRANSCODER(i915, trans) ((DISPLAY_RUNTIME_INFO(i915)->cpu_transcoder_mask & \
BIT(trans)) != 0)
#define HAS_UNCOMPRESSED_JOINER(i915) (DISPLAY_VER(i915) >= 13)
#define HAS_ULTRAJOINER(i915) ((DISPLAY_VER(i915) >= 20 || \
(IS_DGFX(i915) && DISPLAY_VER(i915) == 14)) && \
HAS_DSC(i915))
#define HAS_VRR(i915) (DISPLAY_VER(i915) >= 11)
#define HAS_AS_SDP(i915) (DISPLAY_VER(i915) >= 13)
#define HAS_CMRR(i915) (DISPLAY_VER(i915) >= 20)

View File

@ -82,16 +82,17 @@ bool intel_display_driver_probe_defer(struct pci_dev *pdev)
void intel_display_driver_init_hw(struct drm_i915_private *i915)
{
struct intel_display *display = &i915->display;
struct intel_cdclk_state *cdclk_state;
if (!HAS_DISPLAY(i915))
return;
cdclk_state = to_intel_cdclk_state(i915->display.cdclk.obj.state);
cdclk_state = to_intel_cdclk_state(display->cdclk.obj.state);
intel_update_cdclk(i915);
intel_cdclk_dump_config(i915, &i915->display.cdclk.hw, "Current CDCLK");
cdclk_state->logical = cdclk_state->actual = i915->display.cdclk.hw;
intel_update_cdclk(display);
intel_cdclk_dump_config(display, &display->cdclk.hw, "Current CDCLK");
cdclk_state->logical = cdclk_state->actual = display->cdclk.hw;
intel_display_wa_apply(i915);
}
@ -168,10 +169,11 @@ static void intel_mode_config_cleanup(struct drm_i915_private *i915)
static void intel_plane_possible_crtcs_init(struct drm_i915_private *dev_priv)
{
struct intel_display *display = &dev_priv->display;
struct intel_plane *plane;
for_each_intel_plane(&dev_priv->drm, plane) {
struct intel_crtc *crtc = intel_crtc_for_pipe(dev_priv,
struct intel_crtc *crtc = intel_crtc_for_pipe(display,
plane->pipe);
plane->base.possible_crtcs = drm_crtc_mask(&crtc->base);
@ -193,7 +195,7 @@ void intel_display_driver_early_probe(struct drm_i915_private *i915)
intel_display_irq_init(i915);
intel_dkl_phy_init(i915);
intel_color_init_hooks(i915);
intel_init_cdclk_hooks(i915);
intel_init_cdclk_hooks(&i915->display);
intel_audio_hooks_init(i915);
intel_dpll_init_clock_hook(i915);
intel_init_display_hooks(i915);
@ -219,7 +221,7 @@ int intel_display_driver_probe_noirq(struct drm_i915_private *i915)
intel_bios_init(display);
ret = intel_vga_register(i915);
ret = intel_vga_register(display);
if (ret)
goto cleanup_bios;
@ -235,7 +237,7 @@ int intel_display_driver_probe_noirq(struct drm_i915_private *i915)
if (!HAS_DISPLAY(i915))
return 0;
intel_dmc_init(i915);
intel_dmc_init(display);
i915->display.wq.modeset = alloc_ordered_workqueue("i915_modeset", 0);
i915->display.wq.flip = alloc_workqueue("i915_flip", WQ_HIGHPRI |
@ -243,7 +245,7 @@ int intel_display_driver_probe_noirq(struct drm_i915_private *i915)
intel_mode_config_init(i915);
ret = intel_cdclk_init(i915);
ret = intel_cdclk_init(display);
if (ret)
goto cleanup_vga_client_pw_domain_dmc;
@ -270,10 +272,10 @@ int intel_display_driver_probe_noirq(struct drm_i915_private *i915)
return 0;
cleanup_vga_client_pw_domain_dmc:
intel_dmc_fini(i915);
intel_dmc_fini(display);
intel_power_domains_driver_remove(i915);
cleanup_vga:
intel_vga_unregister(i915);
intel_vga_unregister(display);
cleanup_bios:
intel_bios_driver_remove(display);
@ -450,13 +452,13 @@ int intel_display_driver_probe_nogem(struct drm_i915_private *i915)
intel_display_driver_init_hw(i915);
intel_dpll_update_ref_clks(i915);
if (i915->display.cdclk.max_cdclk_freq == 0)
intel_update_max_cdclk(i915);
if (display->cdclk.max_cdclk_freq == 0)
intel_update_max_cdclk(display);
intel_hti_init(display);
/* Just disable it once at startup */
intel_vga_disable(i915);
intel_vga_disable(display);
intel_setup_outputs(i915);
ret = intel_dp_tunnel_mgr_init(display);
@ -619,11 +621,11 @@ void intel_display_driver_remove_nogem(struct drm_i915_private *i915)
{
struct intel_display *display = &i915->display;
intel_dmc_fini(i915);
intel_dmc_fini(display);
intel_power_domains_driver_remove(i915);
intel_vga_unregister(i915);
intel_vga_unregister(display);
intel_bios_driver_remove(display);
}
@ -681,12 +683,13 @@ __intel_display_driver_resume(struct drm_i915_private *i915,
struct drm_atomic_state *state,
struct drm_modeset_acquire_ctx *ctx)
{
struct intel_display *display = &i915->display;
struct drm_crtc_state *crtc_state;
struct drm_crtc *crtc;
int ret, i;
intel_modeset_setup_hw_state(i915, ctx);
intel_vga_redisable(i915);
intel_vga_redisable(display);
if (!state)
return 0;

View File

@ -3,6 +3,8 @@
* Copyright © 2023 Intel Corporation
*/
#include <drm/drm_vblank.h>
#include "gt/intel_rps.h"
#include "i915_drv.h"
#include "i915_irq.h"
@ -27,7 +29,8 @@
static void
intel_handle_vblank(struct drm_i915_private *dev_priv, enum pipe pipe)
{
struct intel_crtc *crtc = intel_crtc_for_pipe(dev_priv, pipe);
struct intel_display *display = &dev_priv->display;
struct intel_crtc *crtc = intel_crtc_for_pipe(display, pipe);
drm_crtc_handle_vblank(&crtc->base);
}
@ -269,14 +272,17 @@ void i915_disable_pipestat(struct drm_i915_private *dev_priv,
intel_uncore_posting_read(&dev_priv->uncore, reg);
}
static bool i915_has_asle(struct drm_i915_private *i915)
static bool i915_has_legacy_blc_interrupt(struct intel_display *display)
{
struct intel_display *display = &i915->display;
struct drm_i915_private *i915 = to_i915(display->drm);
if (!IS_PINEVIEW(i915) && !IS_MOBILE(i915))
return false;
if (IS_I85X(i915))
return true;
return intel_opregion_asle_present(display);
if (IS_PINEVIEW(i915))
return true;
return IS_DISPLAY_VER(display, 3, 4) && IS_MOBILE(i915);
}
/**
@ -285,7 +291,12 @@ static bool i915_has_asle(struct drm_i915_private *i915)
*/
void i915_enable_asle_pipestat(struct drm_i915_private *dev_priv)
{
if (!i915_has_asle(dev_priv))
struct intel_display *display = &dev_priv->display;
if (!intel_opregion_asle_present(display))
return;
if (!i915_has_legacy_blc_interrupt(display))
return;
spin_lock_irq(&dev_priv->irq_lock);
@ -298,14 +309,15 @@ void i915_enable_asle_pipestat(struct drm_i915_private *dev_priv)
spin_unlock_irq(&dev_priv->irq_lock);
}
#if defined(CONFIG_DEBUG_FS)
#if IS_ENABLED(CONFIG_DEBUG_FS)
static void display_pipe_crc_irq_handler(struct drm_i915_private *dev_priv,
enum pipe pipe,
u32 crc0, u32 crc1,
u32 crc2, u32 crc3,
u32 crc4)
{
struct intel_crtc *crtc = intel_crtc_for_pipe(dev_priv, pipe);
struct intel_display *display = &dev_priv->display;
struct intel_crtc *crtc = intel_crtc_for_pipe(display, pipe);
struct intel_pipe_crc *pipe_crc = &crtc->pipe_crc;
u32 crcs[5] = { crc0, crc1, crc2, crc3, crc4 };
@ -344,7 +356,8 @@ display_pipe_crc_irq_handler(struct drm_i915_private *dev_priv,
static void flip_done_handler(struct drm_i915_private *i915,
enum pipe pipe)
{
struct intel_crtc *crtc = intel_crtc_for_pipe(i915, pipe);
struct intel_display *display = &i915->display;
struct intel_crtc *crtc = intel_crtc_for_pipe(display, pipe);
spin_lock(&i915->drm.event_lock);
@ -400,7 +413,7 @@ static void i9xx_pipe_crc_irq_handler(struct drm_i915_private *dev_priv,
res1, res2);
}
void i9xx_pipestat_irq_reset(struct drm_i915_private *dev_priv)
static void i9xx_pipestat_irq_reset(struct drm_i915_private *dev_priv)
{
enum pipe pipe;
@ -480,28 +493,10 @@ void i9xx_pipestat_irq_ack(struct drm_i915_private *dev_priv,
spin_unlock(&dev_priv->irq_lock);
}
void i8xx_pipestat_irq_handler(struct drm_i915_private *dev_priv,
u16 iir, u32 pipe_stats[I915_MAX_PIPES])
{
enum pipe pipe;
for_each_pipe(dev_priv, pipe) {
if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS)
intel_handle_vblank(dev_priv, pipe);
if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS)
i9xx_pipe_crc_irq_handler(dev_priv, pipe);
if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS)
intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe);
}
}
void i915_pipestat_irq_handler(struct drm_i915_private *dev_priv,
u32 iir, u32 pipe_stats[I915_MAX_PIPES])
{
struct intel_display *display = &dev_priv->display;
bool blc_event = false;
enum pipe pipe;
@ -1226,15 +1221,14 @@ void gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl)
u32 gen11_gu_misc_irq_ack(struct drm_i915_private *i915, const u32 master_ctl)
{
void __iomem * const regs = intel_uncore_regs(&i915->uncore);
u32 iir;
if (!(master_ctl & GEN11_GU_MISC_IRQ))
return 0;
iir = raw_reg_read(regs, GEN11_GU_MISC_IIR);
iir = intel_de_read(i915, GEN11_GU_MISC_IIR);
if (likely(iir))
raw_reg_write(regs, GEN11_GU_MISC_IIR, iir);
intel_de_write(i915, GEN11_GU_MISC_IIR, iir);
return iir;
}
@ -1249,25 +1243,56 @@ void gen11_gu_misc_irq_handler(struct drm_i915_private *i915, const u32 iir)
void gen11_display_irq_handler(struct drm_i915_private *i915)
{
void __iomem * const regs = intel_uncore_regs(&i915->uncore);
const u32 disp_ctl = raw_reg_read(regs, GEN11_DISPLAY_INT_CTL);
u32 disp_ctl;
disable_rpm_wakeref_asserts(&i915->runtime_pm);
/*
* GEN11_DISPLAY_INT_CTL has same format as GEN8_MASTER_IRQ
* for the display related bits.
*/
raw_reg_write(regs, GEN11_DISPLAY_INT_CTL, 0x0);
disp_ctl = intel_de_read(i915, GEN11_DISPLAY_INT_CTL);
intel_de_write(i915, GEN11_DISPLAY_INT_CTL, 0);
gen8_de_irq_handler(i915, disp_ctl);
raw_reg_write(regs, GEN11_DISPLAY_INT_CTL,
GEN11_DISPLAY_IRQ_ENABLE);
intel_de_write(i915, GEN11_DISPLAY_INT_CTL, GEN11_DISPLAY_IRQ_ENABLE);
enable_rpm_wakeref_asserts(&i915->runtime_pm);
}
/* Called from drm generic code, passed 'crtc' which
* we use as a pipe index
*/
static void i915gm_irq_cstate_wa_enable(struct drm_i915_private *i915)
{
lockdep_assert_held(&i915->drm.vblank_time_lock);
/*
* Vblank/CRC interrupts fail to wake the device up from C2+.
* Disabling render clock gating during C-states avoids
* the problem. There is a small power cost so we do this
* only when vblank/CRC interrupts are actually enabled.
*/
if (i915->display.irq.vblank_enabled++ == 0)
intel_uncore_write(&i915->uncore, SCPD0, _MASKED_BIT_ENABLE(CSTATE_RENDER_CLOCK_GATE_DISABLE));
}
static void i915gm_irq_cstate_wa_disable(struct drm_i915_private *i915)
{
lockdep_assert_held(&i915->drm.vblank_time_lock);
if (--i915->display.irq.vblank_enabled == 0)
intel_uncore_write(&i915->uncore, SCPD0, _MASKED_BIT_DISABLE(CSTATE_RENDER_CLOCK_GATE_DISABLE));
}
void i915gm_irq_cstate_wa(struct drm_i915_private *i915, bool enable)
{
spin_lock_irq(&i915->drm.vblank_time_lock);
if (enable)
i915gm_irq_cstate_wa_enable(i915);
else
i915gm_irq_cstate_wa_disable(i915);
spin_unlock_irq(&i915->drm.vblank_time_lock);
}
int i8xx_enable_vblank(struct drm_crtc *crtc)
{
struct drm_i915_private *dev_priv = to_i915(crtc->dev);
@ -1281,22 +1306,35 @@ int i8xx_enable_vblank(struct drm_crtc *crtc)
return 0;
}
void i8xx_disable_vblank(struct drm_crtc *crtc)
{
struct drm_i915_private *dev_priv = to_i915(crtc->dev);
enum pipe pipe = to_intel_crtc(crtc)->pipe;
unsigned long irqflags;
spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
i915_disable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_STATUS);
spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
}
int i915gm_enable_vblank(struct drm_crtc *crtc)
{
struct drm_i915_private *i915 = to_i915(crtc->dev);
/*
* Vblank interrupts fail to wake the device up from C2+.
* Disabling render clock gating during C-states avoids
* the problem. There is a small power cost so we do this
* only when vblank interrupts are actually enabled.
*/
if (i915->display.irq.vblank_enabled++ == 0)
intel_uncore_write(&i915->uncore, SCPD0, _MASKED_BIT_ENABLE(CSTATE_RENDER_CLOCK_GATE_DISABLE));
i915gm_irq_cstate_wa_enable(i915);
return i8xx_enable_vblank(crtc);
}
void i915gm_disable_vblank(struct drm_crtc *crtc)
{
struct drm_i915_private *i915 = to_i915(crtc->dev);
i8xx_disable_vblank(crtc);
i915gm_irq_cstate_wa_disable(i915);
}
int i965_enable_vblank(struct drm_crtc *crtc)
{
struct drm_i915_private *dev_priv = to_i915(crtc->dev);
@ -1311,6 +1349,18 @@ int i965_enable_vblank(struct drm_crtc *crtc)
return 0;
}
void i965_disable_vblank(struct drm_crtc *crtc)
{
struct drm_i915_private *dev_priv = to_i915(crtc->dev);
enum pipe pipe = to_intel_crtc(crtc)->pipe;
unsigned long irqflags;
spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
i915_disable_pipestat(dev_priv, pipe,
PIPE_START_VBLANK_INTERRUPT_STATUS);
spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
}
int ilk_enable_vblank(struct drm_crtc *crtc)
{
struct drm_i915_private *dev_priv = to_i915(crtc->dev);
@ -1332,6 +1382,19 @@ int ilk_enable_vblank(struct drm_crtc *crtc)
return 0;
}
void ilk_disable_vblank(struct drm_crtc *crtc)
{
struct drm_i915_private *dev_priv = to_i915(crtc->dev);
enum pipe pipe = to_intel_crtc(crtc)->pipe;
unsigned long irqflags;
u32 bit = DISPLAY_VER(dev_priv) >= 7 ?
DE_PIPE_VBLANK_IVB(pipe) : DE_PIPE_VBLANK(pipe);
spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
ilk_disable_display_irq(dev_priv, bit);
spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
}
static bool gen11_dsi_configure_te(struct intel_crtc *intel_crtc,
bool enable)
{
@ -1356,9 +1419,27 @@ static bool gen11_dsi_configure_te(struct intel_crtc *intel_crtc,
return true;
}
static void intel_display_vblank_dc_work(struct work_struct *work)
{
struct intel_display *display =
container_of(work, typeof(*display), irq.vblank_dc_work);
struct drm_i915_private *i915 = to_i915(display->drm);
u8 vblank_enabled = READ_ONCE(display->irq.vblank_enabled);
/*
* NOTE: intel_display_power_set_target_dc_state is used only by PSR
* code for DC3CO handling. DC3CO target state is currently disabled in
* PSR code. If DC3CO is taken into use we need take that into account
* here as well.
*/
intel_display_power_set_target_dc_state(i915, vblank_enabled ? DC_STATE_DISABLE :
DC_STATE_EN_UPTO_DC6);
}
int bdw_enable_vblank(struct drm_crtc *_crtc)
{
struct intel_crtc *crtc = to_intel_crtc(_crtc);
struct intel_display *display = to_intel_display(crtc);
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
enum pipe pipe = crtc->pipe;
unsigned long irqflags;
@ -1366,6 +1447,9 @@ int bdw_enable_vblank(struct drm_crtc *_crtc)
if (gen11_dsi_configure_te(crtc, true))
return 0;
if (display->irq.vblank_enabled++ == 0 && crtc->block_dc_for_vblank)
schedule_work(&display->irq.vblank_dc_work);
spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
bdw_enable_pipe_irq(dev_priv, pipe, GEN8_PIPE_VBLANK);
spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
@ -1379,58 +1463,10 @@ int bdw_enable_vblank(struct drm_crtc *_crtc)
return 0;
}
/* Called from drm generic code, passed 'crtc' which
* we use as a pipe index
*/
void i8xx_disable_vblank(struct drm_crtc *crtc)
{
struct drm_i915_private *dev_priv = to_i915(crtc->dev);
enum pipe pipe = to_intel_crtc(crtc)->pipe;
unsigned long irqflags;
spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
i915_disable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_STATUS);
spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
}
void i915gm_disable_vblank(struct drm_crtc *crtc)
{
struct drm_i915_private *i915 = to_i915(crtc->dev);
i8xx_disable_vblank(crtc);
if (--i915->display.irq.vblank_enabled == 0)
intel_uncore_write(&i915->uncore, SCPD0, _MASKED_BIT_DISABLE(CSTATE_RENDER_CLOCK_GATE_DISABLE));
}
void i965_disable_vblank(struct drm_crtc *crtc)
{
struct drm_i915_private *dev_priv = to_i915(crtc->dev);
enum pipe pipe = to_intel_crtc(crtc)->pipe;
unsigned long irqflags;
spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
i915_disable_pipestat(dev_priv, pipe,
PIPE_START_VBLANK_INTERRUPT_STATUS);
spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
}
void ilk_disable_vblank(struct drm_crtc *crtc)
{
struct drm_i915_private *dev_priv = to_i915(crtc->dev);
enum pipe pipe = to_intel_crtc(crtc)->pipe;
unsigned long irqflags;
u32 bit = DISPLAY_VER(dev_priv) >= 7 ?
DE_PIPE_VBLANK_IVB(pipe) : DE_PIPE_VBLANK(pipe);
spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
ilk_disable_display_irq(dev_priv, bit);
spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
}
void bdw_disable_vblank(struct drm_crtc *_crtc)
{
struct intel_crtc *crtc = to_intel_crtc(_crtc);
struct intel_display *display = to_intel_display(crtc);
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
enum pipe pipe = crtc->pipe;
unsigned long irqflags;
@ -1441,6 +1477,9 @@ void bdw_disable_vblank(struct drm_crtc *_crtc)
spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
bdw_disable_pipe_irq(dev_priv, pipe, GEN8_PIPE_VBLANK);
spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
if (--display->irq.vblank_enabled == 0 && crtc->block_dc_for_vblank)
schedule_work(&display->irq.vblank_dc_work);
}
void vlv_display_irq_reset(struct drm_i915_private *dev_priv)
@ -1457,10 +1496,21 @@ void vlv_display_irq_reset(struct drm_i915_private *dev_priv)
i9xx_pipestat_irq_reset(dev_priv);
GEN3_IRQ_RESET(uncore, VLV_);
gen3_irq_reset(uncore, VLV_IRQ_REGS);
dev_priv->irq_mask = ~0u;
}
void i9xx_display_irq_reset(struct drm_i915_private *i915)
{
if (I915_HAS_HOTPLUG(i915)) {
i915_hotplug_interrupt_update(i915, 0xffffffff, 0);
intel_uncore_rmw(&i915->uncore,
PORT_HOTPLUG_STAT(i915), 0, 0);
}
i9xx_pipestat_irq_reset(i915);
}
void vlv_display_irq_postinstall(struct drm_i915_private *dev_priv)
{
struct intel_uncore *uncore = &dev_priv->uncore;
@ -1489,7 +1539,7 @@ void vlv_display_irq_postinstall(struct drm_i915_private *dev_priv)
dev_priv->irq_mask = ~enable_mask;
GEN3_IRQ_INIT(uncore, VLV_, dev_priv->irq_mask, enable_mask);
gen3_irq_init(uncore, VLV_IRQ_REGS, dev_priv->irq_mask, enable_mask);
}
void gen8_display_irq_reset(struct drm_i915_private *dev_priv)
@ -1506,10 +1556,10 @@ void gen8_display_irq_reset(struct drm_i915_private *dev_priv)
for_each_pipe(dev_priv, pipe)
if (intel_display_power_is_enabled(dev_priv,
POWER_DOMAIN_PIPE(pipe)))
GEN8_IRQ_RESET_NDX(uncore, DE_PIPE, pipe);
gen3_irq_reset(uncore, GEN8_DE_PIPE_IRQ_REGS(pipe));
GEN3_IRQ_RESET(uncore, GEN8_DE_PORT_);
GEN3_IRQ_RESET(uncore, GEN8_DE_MISC_);
gen3_irq_reset(uncore, GEN8_DE_PORT_IRQ_REGS);
gen3_irq_reset(uncore, GEN8_DE_MISC_IRQ_REGS);
}
void gen11_display_irq_reset(struct drm_i915_private *dev_priv)
@ -1549,18 +1599,18 @@ void gen11_display_irq_reset(struct drm_i915_private *dev_priv)
for_each_pipe(dev_priv, pipe)
if (intel_display_power_is_enabled(dev_priv,
POWER_DOMAIN_PIPE(pipe)))
GEN8_IRQ_RESET_NDX(uncore, DE_PIPE, pipe);
gen3_irq_reset(uncore, GEN8_DE_PIPE_IRQ_REGS(pipe));
GEN3_IRQ_RESET(uncore, GEN8_DE_PORT_);
GEN3_IRQ_RESET(uncore, GEN8_DE_MISC_);
gen3_irq_reset(uncore, GEN8_DE_PORT_IRQ_REGS);
gen3_irq_reset(uncore, GEN8_DE_MISC_IRQ_REGS);
if (DISPLAY_VER(dev_priv) >= 14)
GEN3_IRQ_RESET(uncore, PICAINTERRUPT_);
gen3_irq_reset(uncore, PICAINTERRUPT_IRQ_REGS);
else
GEN3_IRQ_RESET(uncore, GEN11_DE_HPD_);
gen3_irq_reset(uncore, GEN11_DE_HPD_IRQ_REGS);
if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP)
GEN3_IRQ_RESET(uncore, SDE);
gen3_irq_reset(uncore, SDE_IRQ_REGS);
}
void gen8_irq_power_well_post_enable(struct drm_i915_private *dev_priv,
@ -1580,9 +1630,9 @@ void gen8_irq_power_well_post_enable(struct drm_i915_private *dev_priv,
}
for_each_pipe_masked(dev_priv, pipe, pipe_mask)
GEN8_IRQ_INIT_NDX(uncore, DE_PIPE, pipe,
dev_priv->display.irq.de_irq_mask[pipe],
~dev_priv->display.irq.de_irq_mask[pipe] | extra_ier);
gen3_irq_init(uncore, GEN8_DE_PIPE_IRQ_REGS(pipe),
dev_priv->display.irq.de_irq_mask[pipe],
~dev_priv->display.irq.de_irq_mask[pipe] | extra_ier);
spin_unlock_irq(&dev_priv->irq_lock);
}
@ -1601,7 +1651,7 @@ void gen8_irq_power_well_pre_disable(struct drm_i915_private *dev_priv,
}
for_each_pipe_masked(dev_priv, pipe, pipe_mask)
GEN8_IRQ_RESET_NDX(uncore, DE_PIPE, pipe);
gen3_irq_reset(uncore, GEN8_DE_PIPE_IRQ_REGS(pipe));
spin_unlock_irq(&dev_priv->irq_lock);
@ -1635,7 +1685,7 @@ static void ibx_irq_postinstall(struct drm_i915_private *dev_priv)
else
mask = SDE_GMBUS_CPT;
GEN3_IRQ_INIT(uncore, SDE, ~mask, 0xffffffff);
gen3_irq_init(uncore, SDE_IRQ_REGS, ~mask, 0xffffffff);
}
void valleyview_enable_display_irqs(struct drm_i915_private *dev_priv)
@ -1703,7 +1753,7 @@ void ilk_de_irq_postinstall(struct drm_i915_private *i915)
ibx_irq_postinstall(i915);
GEN3_IRQ_INIT(uncore, DE, i915->irq_mask,
gen3_irq_init(uncore, DE_IRQ_REGS, i915->irq_mask,
display_mask | extra_mask);
}
@ -1789,20 +1839,20 @@ void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv)
if (intel_display_power_is_enabled(dev_priv,
POWER_DOMAIN_PIPE(pipe)))
GEN8_IRQ_INIT_NDX(uncore, DE_PIPE, pipe,
dev_priv->display.irq.de_irq_mask[pipe],
de_pipe_enables);
gen3_irq_init(uncore, GEN8_DE_PIPE_IRQ_REGS(pipe),
dev_priv->display.irq.de_irq_mask[pipe],
de_pipe_enables);
}
GEN3_IRQ_INIT(uncore, GEN8_DE_PORT_, ~de_port_masked, de_port_enables);
GEN3_IRQ_INIT(uncore, GEN8_DE_MISC_, ~de_misc_masked, de_misc_masked);
gen3_irq_init(uncore, GEN8_DE_PORT_IRQ_REGS, ~de_port_masked, de_port_enables);
gen3_irq_init(uncore, GEN8_DE_MISC_IRQ_REGS, ~de_misc_masked, de_misc_masked);
if (IS_DISPLAY_VER(dev_priv, 11, 13)) {
u32 de_hpd_masked = 0;
u32 de_hpd_enables = GEN11_DE_TC_HOTPLUG_MASK |
GEN11_DE_TBT_HOTPLUG_MASK;
GEN3_IRQ_INIT(uncore, GEN11_DE_HPD_, ~de_hpd_masked,
gen3_irq_init(uncore, GEN11_DE_HPD_IRQ_REGS, ~de_hpd_masked,
de_hpd_enables);
}
}
@ -1815,10 +1865,10 @@ static void mtp_irq_postinstall(struct drm_i915_private *i915)
u32 de_hpd_enables = de_hpd_mask | XELPDP_DP_ALT_HOTPLUG_MASK |
XELPDP_TBT_HOTPLUG_MASK;
GEN3_IRQ_INIT(uncore, PICAINTERRUPT_, ~de_hpd_mask,
gen3_irq_init(uncore, PICAINTERRUPT_IRQ_REGS, ~de_hpd_mask,
de_hpd_enables);
GEN3_IRQ_INIT(uncore, SDE, ~sde_mask, 0xffffffff);
gen3_irq_init(uncore, SDE_IRQ_REGS, ~sde_mask, 0xffffffff);
}
static void icp_irq_postinstall(struct drm_i915_private *dev_priv)
@ -1826,7 +1876,7 @@ static void icp_irq_postinstall(struct drm_i915_private *dev_priv)
struct intel_uncore *uncore = &dev_priv->uncore;
u32 mask = SDE_GMBUS_ICP;
GEN3_IRQ_INIT(uncore, SDE, ~mask, 0xffffffff);
gen3_irq_init(uncore, SDE_IRQ_REGS, ~mask, 0xffffffff);
}
void gen11_de_irq_postinstall(struct drm_i915_private *dev_priv)
@ -1866,4 +1916,7 @@ void intel_display_irq_init(struct drm_i915_private *i915)
i915->display.irq.display_irqs_enabled = false;
intel_hotplug_irq_init(i915);
INIT_WORK(&i915->display.irq.vblank_dc_work,
intel_display_vblank_dc_work);
}

View File

@ -54,6 +54,7 @@ void gen11_display_irq_handler(struct drm_i915_private *i915);
u32 gen11_gu_misc_irq_ack(struct drm_i915_private *i915, const u32 master_ctl);
void gen11_gu_misc_irq_handler(struct drm_i915_private *i915, const u32 iir);
void i9xx_display_irq_reset(struct drm_i915_private *i915);
void vlv_display_irq_reset(struct drm_i915_private *i915);
void gen8_display_irq_reset(struct drm_i915_private *i915);
void gen11_display_irq_reset(struct drm_i915_private *i915);
@ -68,15 +69,15 @@ u32 i915_pipestat_enable_mask(struct drm_i915_private *i915, enum pipe pipe);
void i915_enable_pipestat(struct drm_i915_private *i915, enum pipe pipe, u32 status_mask);
void i915_disable_pipestat(struct drm_i915_private *i915, enum pipe pipe, u32 status_mask);
void i915_enable_asle_pipestat(struct drm_i915_private *i915);
void i9xx_pipestat_irq_reset(struct drm_i915_private *i915);
void i9xx_pipestat_irq_ack(struct drm_i915_private *i915, u32 iir, u32 pipe_stats[I915_MAX_PIPES]);
void i915_pipestat_irq_handler(struct drm_i915_private *i915, u32 iir, u32 pipe_stats[I915_MAX_PIPES]);
void i965_pipestat_irq_handler(struct drm_i915_private *i915, u32 iir, u32 pipe_stats[I915_MAX_PIPES]);
void valleyview_pipestat_irq_handler(struct drm_i915_private *i915, u32 pipe_stats[I915_MAX_PIPES]);
void i8xx_pipestat_irq_handler(struct drm_i915_private *i915, u16 iir, u32 pipe_stats[I915_MAX_PIPES]);
void intel_display_irq_init(struct drm_i915_private *i915);
void i915gm_irq_cstate_wa(struct drm_i915_private *i915, bool enable);
#endif /* __INTEL_DISPLAY_IRQ_H__ */

View File

@ -49,6 +49,16 @@ enum transcoder {
I915_MAX_TRANSCODERS
};
/*
* Global legacy plane identifier. Valid only for primary/sprite
* planes on pre-g4x, and only for primary planes on g4x-bdw.
*/
enum i9xx_plane_id {
PLANE_A,
PLANE_B,
PLANE_C,
};
/*
* Per-pipe plane identifier.
* I915_MAX_PLANES in the enum below is the maximum (across all platforms)

View File

@ -173,14 +173,16 @@ static void _param_print_charp(struct drm_printer *p, const char *driver_name,
/**
* intel_display_params_dump - dump intel display modparams
* @display: display device
* @params: display params
* @driver_name: driver name to use for printing
* @p: the &drm_printer
*
* Pretty printer for i915 modparams.
*/
void intel_display_params_dump(struct intel_display *display, struct drm_printer *p)
void intel_display_params_dump(const struct intel_display_params *params,
const char *driver_name, struct drm_printer *p)
{
#define PRINT(T, x, ...) _param_print(p, display->drm->driver->name, #x, display->params.x);
#define PRINT(T, x, ...) _param_print(p, driver_name, #x, params->x);
INTEL_DISPLAY_PARAMS_FOR_EACH(PRINT);
#undef PRINT
}

View File

@ -9,7 +9,6 @@
#include <linux/types.h>
struct drm_printer;
struct intel_display;
/*
* Invoke param, a function-like macro, for each intel display param, with
@ -56,8 +55,8 @@ struct intel_display_params {
};
#undef MEMBER
void intel_display_params_dump(struct intel_display *display,
struct drm_printer *p);
void intel_display_params_dump(const struct intel_display_params *params,
const char *driver_name, struct drm_printer *p);
void intel_display_params_copy(struct intel_display_params *dest);
void intel_display_params_free(struct intel_display_params *params);

View File

@ -545,7 +545,7 @@ intel_display_power_get_if_enabled(struct drm_i915_private *dev_priv,
wakeref = intel_runtime_pm_get_if_in_use(&dev_priv->runtime_pm);
if (!wakeref)
return false;
return NULL;
mutex_lock(&power_domains->lock);
@ -560,7 +560,7 @@ intel_display_power_get_if_enabled(struct drm_i915_private *dev_priv,
if (!is_enabled) {
intel_runtime_pm_put(&dev_priv->runtime_pm, wakeref);
wakeref = 0;
wakeref = NULL;
}
return wakeref;
@ -648,7 +648,7 @@ intel_display_power_put_async_work(struct work_struct *work)
struct i915_power_domains *power_domains = &dev_priv->display.power.domains;
struct intel_runtime_pm *rpm = &dev_priv->runtime_pm;
intel_wakeref_t new_work_wakeref = intel_runtime_pm_get_raw(rpm);
intel_wakeref_t old_work_wakeref = 0;
intel_wakeref_t old_work_wakeref = NULL;
mutex_lock(&power_domains->lock);
@ -895,7 +895,7 @@ intel_display_power_put_mask_in_set(struct drm_i915_private *i915,
!bitmap_subset(mask->bits, power_domain_set->mask.bits, POWER_DOMAIN_NUM));
for_each_power_domain(domain, mask) {
intel_wakeref_t __maybe_unused wf = -1;
intel_wakeref_t __maybe_unused wf = INTEL_WAKEREF_DEF;
#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)
wf = fetch_and_zero(&power_domain_set->wakerefs[domain]);
@ -1300,6 +1300,7 @@ static void hsw_disable_lcpll(struct drm_i915_private *dev_priv,
*/
static void hsw_restore_lcpll(struct drm_i915_private *dev_priv)
{
struct intel_display *display = &dev_priv->display;
u32 val;
val = intel_de_read(dev_priv, LCPLL_CTL);
@ -1343,8 +1344,8 @@ static void hsw_restore_lcpll(struct drm_i915_private *dev_priv)
intel_uncore_forcewake_put(&dev_priv->uncore, FORCEWAKE_ALL);
intel_update_cdclk(dev_priv);
intel_cdclk_dump_config(dev_priv, &dev_priv->display.cdclk.hw, "Current CDCLK");
intel_update_cdclk(display);
intel_cdclk_dump_config(display, &display->cdclk.hw, "Current CDCLK");
}
/*
@ -1416,10 +1417,11 @@ static void intel_pch_reset_handshake(struct drm_i915_private *dev_priv,
static void skl_display_core_init(struct drm_i915_private *dev_priv,
bool resume)
{
struct i915_power_domains *power_domains = &dev_priv->display.power.domains;
struct intel_display *display = &dev_priv->display;
struct i915_power_domains *power_domains = &display->power.domains;
struct i915_power_well *well;
gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);
gen9_set_dc_state(display, DC_STATE_DISABLE);
/* enable PCH reset handshake */
intel_pch_reset_handshake(dev_priv, !HAS_PCH_NOP(dev_priv));
@ -1438,28 +1440,29 @@ static void skl_display_core_init(struct drm_i915_private *dev_priv,
mutex_unlock(&power_domains->lock);
intel_cdclk_init_hw(dev_priv);
intel_cdclk_init_hw(display);
gen9_dbuf_enable(dev_priv);
if (resume)
intel_dmc_load_program(dev_priv);
intel_dmc_load_program(display);
}
static void skl_display_core_uninit(struct drm_i915_private *dev_priv)
{
struct i915_power_domains *power_domains = &dev_priv->display.power.domains;
struct intel_display *display = &dev_priv->display;
struct i915_power_domains *power_domains = &display->power.domains;
struct i915_power_well *well;
if (!HAS_DISPLAY(dev_priv))
return;
gen9_disable_dc_states(dev_priv);
gen9_disable_dc_states(display);
/* TODO: disable DMC program */
gen9_dbuf_disable(dev_priv);
intel_cdclk_uninit_hw(dev_priv);
intel_cdclk_uninit_hw(display);
/* The spec doesn't call for removing the reset handshake flag */
/* disable PG1 and Misc I/O */
@ -1482,10 +1485,11 @@ static void skl_display_core_uninit(struct drm_i915_private *dev_priv)
static void bxt_display_core_init(struct drm_i915_private *dev_priv, bool resume)
{
struct i915_power_domains *power_domains = &dev_priv->display.power.domains;
struct intel_display *display = &dev_priv->display;
struct i915_power_domains *power_domains = &display->power.domains;
struct i915_power_well *well;
gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);
gen9_set_dc_state(display, DC_STATE_DISABLE);
/*
* NDE_RSTWRN_OPT RST PCH Handshake En must always be 0b on BXT
@ -1506,28 +1510,29 @@ static void bxt_display_core_init(struct drm_i915_private *dev_priv, bool resume
mutex_unlock(&power_domains->lock);
intel_cdclk_init_hw(dev_priv);
intel_cdclk_init_hw(display);
gen9_dbuf_enable(dev_priv);
if (resume)
intel_dmc_load_program(dev_priv);
intel_dmc_load_program(display);
}
static void bxt_display_core_uninit(struct drm_i915_private *dev_priv)
{
struct i915_power_domains *power_domains = &dev_priv->display.power.domains;
struct intel_display *display = &dev_priv->display;
struct i915_power_domains *power_domains = &display->power.domains;
struct i915_power_well *well;
if (!HAS_DISPLAY(dev_priv))
return;
gen9_disable_dc_states(dev_priv);
gen9_disable_dc_states(display);
/* TODO: disable DMC program */
gen9_dbuf_disable(dev_priv);
intel_cdclk_uninit_hw(dev_priv);
intel_cdclk_uninit_hw(display);
/* The spec doesn't call for removing the reset handshake flag */
@ -1623,10 +1628,11 @@ static void tgl_bw_buddy_init(struct drm_i915_private *dev_priv)
static void icl_display_core_init(struct drm_i915_private *dev_priv,
bool resume)
{
struct i915_power_domains *power_domains = &dev_priv->display.power.domains;
struct intel_display *display = &dev_priv->display;
struct i915_power_domains *power_domains = &display->power.domains;
struct i915_power_well *well;
gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);
gen9_set_dc_state(display, DC_STATE_DISABLE);
/* Wa_14011294188:ehl,jsl,tgl,rkl,adl-s */
if (INTEL_PCH_TYPE(dev_priv) >= PCH_TGP &&
@ -1657,7 +1663,7 @@ static void icl_display_core_init(struct drm_i915_private *dev_priv,
HOLD_PHY_PG1_LATCH | HOLD_PHY_CLKREQ_PG1_LATCH, 0);
/* 4. Enable CDCLK. */
intel_cdclk_init_hw(dev_priv);
intel_cdclk_init_hw(display);
if (DISPLAY_VER(dev_priv) >= 12)
gen12_dbuf_slices_config(dev_priv);
@ -1681,7 +1687,7 @@ static void icl_display_core_init(struct drm_i915_private *dev_priv,
intel_de_rmw(dev_priv, CHICKEN_MISC_2, BMG_DARB_HALF_BLK_END_BURST, 1);
if (resume)
intel_dmc_load_program(dev_priv);
intel_dmc_load_program(display);
/* Wa_14011508470:tgl,dg1,rkl,adl-s,adl-p,dg2 */
if (IS_DISPLAY_VER_FULL(dev_priv, IP_VER(12, 0), IP_VER(13, 0)))
@ -1704,14 +1710,15 @@ static void icl_display_core_init(struct drm_i915_private *dev_priv,
static void icl_display_core_uninit(struct drm_i915_private *dev_priv)
{
struct i915_power_domains *power_domains = &dev_priv->display.power.domains;
struct intel_display *display = &dev_priv->display;
struct i915_power_domains *power_domains = &display->power.domains;
struct i915_power_well *well;
if (!HAS_DISPLAY(dev_priv))
return;
gen9_disable_dc_states(dev_priv);
intel_dmc_disable_program(dev_priv);
gen9_disable_dc_states(display);
intel_dmc_disable_program(display);
/* 1. Disable all display engine functions -> aready done */
@ -1719,7 +1726,7 @@ static void icl_display_core_uninit(struct drm_i915_private *dev_priv)
gen9_dbuf_disable(dev_priv);
/* 3. Disable CD clock */
intel_cdclk_uninit_hw(dev_priv);
intel_cdclk_uninit_hw(display);
if (DISPLAY_VER(dev_priv) == 14)
intel_de_rmw(dev_priv, DC_STATE_EN, 0,
@ -2066,7 +2073,8 @@ void intel_power_domains_disable(struct drm_i915_private *i915)
*/
void intel_power_domains_suspend(struct drm_i915_private *i915, bool s2idle)
{
struct i915_power_domains *power_domains = &i915->display.power.domains;
struct intel_display *display = &i915->display;
struct i915_power_domains *power_domains = &display->power.domains;
intel_wakeref_t wakeref __maybe_unused =
fetch_and_zero(&power_domains->init_wakeref);
@ -2080,7 +2088,7 @@ void intel_power_domains_suspend(struct drm_i915_private *i915, bool s2idle)
* that would be blocked if the firmware was inactive.
*/
if (!(power_domains->allowed_dc_mask & DC_STATE_EN_DC9) && s2idle &&
intel_dmc_has_payload(i915)) {
intel_dmc_has_payload(display)) {
intel_display_power_flush_work(i915);
intel_power_domains_verify_state(i915);
return;
@ -2225,9 +2233,11 @@ static void intel_power_domains_verify_state(struct drm_i915_private *i915)
void intel_display_power_suspend_late(struct drm_i915_private *i915)
{
struct intel_display *display = &i915->display;
if (DISPLAY_VER(i915) >= 11 || IS_GEMINILAKE(i915) ||
IS_BROXTON(i915)) {
bxt_enable_dc9(i915);
bxt_enable_dc9(display);
} else if (IS_HASWELL(i915) || IS_BROADWELL(i915)) {
hsw_enable_pc8(i915);
}
@ -2239,10 +2249,12 @@ void intel_display_power_suspend_late(struct drm_i915_private *i915)
void intel_display_power_resume_early(struct drm_i915_private *i915)
{
struct intel_display *display = &i915->display;
if (DISPLAY_VER(i915) >= 11 || IS_GEMINILAKE(i915) ||
IS_BROXTON(i915)) {
gen9_sanitize_dc_state(i915);
bxt_disable_dc9(i915);
gen9_sanitize_dc_state(display);
bxt_disable_dc9(display);
} else if (IS_HASWELL(i915) || IS_BROADWELL(i915)) {
hsw_disable_pc8(i915);
}
@ -2254,12 +2266,14 @@ void intel_display_power_resume_early(struct drm_i915_private *i915)
void intel_display_power_suspend(struct drm_i915_private *i915)
{
struct intel_display *display = &i915->display;
if (DISPLAY_VER(i915) >= 11) {
icl_display_core_uninit(i915);
bxt_enable_dc9(i915);
bxt_enable_dc9(display);
} else if (IS_GEMINILAKE(i915) || IS_BROXTON(i915)) {
bxt_display_core_uninit(i915);
bxt_enable_dc9(i915);
bxt_enable_dc9(display);
} else if (IS_HASWELL(i915) || IS_BROADWELL(i915)) {
hsw_enable_pc8(i915);
}
@ -2267,23 +2281,24 @@ void intel_display_power_suspend(struct drm_i915_private *i915)
void intel_display_power_resume(struct drm_i915_private *i915)
{
struct i915_power_domains *power_domains = &i915->display.power.domains;
struct intel_display *display = &i915->display;
struct i915_power_domains *power_domains = &display->power.domains;
if (DISPLAY_VER(i915) >= 11) {
bxt_disable_dc9(i915);
bxt_disable_dc9(display);
icl_display_core_init(i915, true);
if (intel_dmc_has_payload(i915)) {
if (intel_dmc_has_payload(display)) {
if (power_domains->allowed_dc_mask & DC_STATE_EN_UPTO_DC6)
skl_enable_dc6(i915);
skl_enable_dc6(display);
else if (power_domains->allowed_dc_mask & DC_STATE_EN_UPTO_DC5)
gen9_enable_dc5(i915);
gen9_enable_dc5(display);
}
} else if (IS_GEMINILAKE(i915) || IS_BROXTON(i915)) {
bxt_disable_dc9(i915);
bxt_disable_dc9(display);
bxt_display_core_init(i915, true);
if (intel_dmc_has_payload(i915) &&
if (intel_dmc_has_payload(display) &&
(power_domains->allowed_dc_mask & DC_STATE_EN_UPTO_DC5))
gen9_enable_dc5(i915);
gen9_enable_dc5(display);
} else if (IS_HASWELL(i915) || IS_BROADWELL(i915)) {
hsw_disable_pc8(i915);
}

View File

@ -232,7 +232,7 @@ intel_display_power_put_async(struct drm_i915_private *i915,
enum intel_display_power_domain domain,
intel_wakeref_t wakeref)
{
__intel_display_power_put_async(i915, domain, -1, -1);
__intel_display_power_put_async(i915, domain, INTEL_WAKEREF_DEF, -1);
}
static inline void
@ -241,7 +241,7 @@ intel_display_power_put_async_delay(struct drm_i915_private *i915,
intel_wakeref_t wakeref,
int delay_ms)
{
__intel_display_power_put_async(i915, domain, -1, delay_ms);
__intel_display_power_put_async(i915, domain, INTEL_WAKEREF_DEF, delay_ms);
}
#endif
@ -297,10 +297,10 @@ void gen9_dbuf_slices_update(struct drm_i915_private *dev_priv,
#define with_intel_display_power(i915, domain, wf) \
for ((wf) = intel_display_power_get((i915), (domain)); (wf); \
intel_display_power_put_async((i915), (domain), (wf)), (wf) = 0)
intel_display_power_put_async((i915), (domain), (wf)), (wf) = NULL)
#define with_intel_display_power_if_enabled(i915, domain, wf) \
for ((wf) = intel_display_power_get_if_enabled((i915), (domain)); (wf); \
intel_display_power_put_async((i915), (domain), (wf)), (wf) = 0)
intel_display_power_put_async((i915), (domain), (wf)), (wf) = NULL)
#endif /* __INTEL_DISPLAY_POWER_H__ */

View File

@ -187,8 +187,10 @@ int intel_power_well_refcount(struct i915_power_well *power_well)
static void hsw_power_well_post_enable(struct drm_i915_private *dev_priv,
u8 irq_pipe_mask, bool has_vga)
{
struct intel_display *display = &dev_priv->display;
if (has_vga)
intel_vga_reset_io_mem(dev_priv);
intel_vga_reset_io_mem(display);
if (irq_pipe_mask)
gen8_irq_power_well_post_enable(dev_priv, irq_pipe_mask);
@ -601,20 +603,22 @@ static bool hsw_power_well_enabled(struct drm_i915_private *dev_priv,
return (val & mask) == mask;
}
static void assert_can_enable_dc9(struct drm_i915_private *dev_priv)
static void assert_can_enable_dc9(struct intel_display *display)
{
drm_WARN_ONCE(&dev_priv->drm,
(intel_de_read(dev_priv, DC_STATE_EN) & DC_STATE_EN_DC9),
struct drm_i915_private *dev_priv = to_i915(display->drm);
drm_WARN_ONCE(display->drm,
(intel_de_read(display, DC_STATE_EN) & DC_STATE_EN_DC9),
"DC9 already programmed to be enabled.\n");
drm_WARN_ONCE(&dev_priv->drm,
intel_de_read(dev_priv, DC_STATE_EN) &
drm_WARN_ONCE(display->drm,
intel_de_read(display, DC_STATE_EN) &
DC_STATE_EN_UPTO_DC5,
"DC5 still not disabled to enable DC9.\n");
drm_WARN_ONCE(&dev_priv->drm,
intel_de_read(dev_priv, HSW_PWR_WELL_CTL2) &
drm_WARN_ONCE(display->drm,
intel_de_read(display, HSW_PWR_WELL_CTL2) &
HSW_PWR_WELL_CTL_REQ(SKL_PW_CTL_IDX_PW_2),
"Power well 2 on.\n");
drm_WARN_ONCE(&dev_priv->drm, intel_irqs_enabled(dev_priv),
drm_WARN_ONCE(display->drm, intel_irqs_enabled(dev_priv),
"Interrupts not disabled yet.\n");
/*
@ -626,12 +630,14 @@ static void assert_can_enable_dc9(struct drm_i915_private *dev_priv)
*/
}
static void assert_can_disable_dc9(struct drm_i915_private *dev_priv)
static void assert_can_disable_dc9(struct intel_display *display)
{
drm_WARN_ONCE(&dev_priv->drm, intel_irqs_enabled(dev_priv),
struct drm_i915_private *dev_priv = to_i915(display->drm);
drm_WARN_ONCE(display->drm, intel_irqs_enabled(dev_priv),
"Interrupts not disabled yet.\n");
drm_WARN_ONCE(&dev_priv->drm,
intel_de_read(dev_priv, DC_STATE_EN) &
drm_WARN_ONCE(display->drm,
intel_de_read(display, DC_STATE_EN) &
DC_STATE_EN_UPTO_DC5,
"DC5 still not disabled.\n");
@ -644,14 +650,14 @@ static void assert_can_disable_dc9(struct drm_i915_private *dev_priv)
*/
}
static void gen9_write_dc_state(struct drm_i915_private *dev_priv,
static void gen9_write_dc_state(struct intel_display *display,
u32 state)
{
int rewrites = 0;
int rereads = 0;
u32 v;
intel_de_write(dev_priv, DC_STATE_EN, state);
intel_de_write(display, DC_STATE_EN, state);
/* It has been observed that disabling the dc6 state sometimes
* doesn't stick and dmc keeps returning old value. Make sure
@ -659,10 +665,10 @@ static void gen9_write_dc_state(struct drm_i915_private *dev_priv,
* we are confident that state is exactly what we want.
*/
do {
v = intel_de_read(dev_priv, DC_STATE_EN);
v = intel_de_read(display, DC_STATE_EN);
if (v != state) {
intel_de_write(dev_priv, DC_STATE_EN, state);
intel_de_write(display, DC_STATE_EN, state);
rewrites++;
rereads = 0;
} else if (rereads++ > 5) {
@ -672,27 +678,28 @@ static void gen9_write_dc_state(struct drm_i915_private *dev_priv,
} while (rewrites < 100);
if (v != state)
drm_err(&dev_priv->drm,
drm_err(display->drm,
"Writing dc state to 0x%x failed, now 0x%x\n",
state, v);
/* Most of the times we need one retry, avoid spam */
if (rewrites > 1)
drm_dbg_kms(&dev_priv->drm,
drm_dbg_kms(display->drm,
"Rewrote dc state to 0x%x %d times\n",
state, rewrites);
}
static u32 gen9_dc_mask(struct drm_i915_private *dev_priv)
static u32 gen9_dc_mask(struct intel_display *display)
{
struct drm_i915_private *dev_priv = to_i915(display->drm);
u32 mask;
mask = DC_STATE_EN_UPTO_DC5;
if (DISPLAY_VER(dev_priv) >= 12)
if (DISPLAY_VER(display) >= 12)
mask |= DC_STATE_EN_DC3CO | DC_STATE_EN_UPTO_DC6
| DC_STATE_EN_DC9;
else if (DISPLAY_VER(dev_priv) == 11)
else if (DISPLAY_VER(display) == 11)
mask |= DC_STATE_EN_UPTO_DC6 | DC_STATE_EN_DC9;
else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
mask |= DC_STATE_EN_DC9;
@ -702,17 +709,17 @@ static u32 gen9_dc_mask(struct drm_i915_private *dev_priv)
return mask;
}
void gen9_sanitize_dc_state(struct drm_i915_private *i915)
void gen9_sanitize_dc_state(struct intel_display *display)
{
struct i915_power_domains *power_domains = &i915->display.power.domains;
struct i915_power_domains *power_domains = &display->power.domains;
u32 val;
if (!HAS_DISPLAY(i915))
if (!HAS_DISPLAY(display))
return;
val = intel_de_read(i915, DC_STATE_EN) & gen9_dc_mask(i915);
val = intel_de_read(display, DC_STATE_EN) & gen9_dc_mask(display);
drm_dbg_kms(&i915->drm,
drm_dbg_kms(display->drm,
"Resetting DC state tracking from %02x to %02x\n",
power_domains->dc_state, val);
power_domains->dc_state = val;
@ -720,7 +727,7 @@ void gen9_sanitize_dc_state(struct drm_i915_private *i915)
/**
* gen9_set_dc_state - set target display C power state
* @dev_priv: i915 device instance
* @display: display instance
* @state: target DC power state
* - DC_STATE_DISABLE
* - DC_STATE_EN_UPTO_DC5
@ -741,150 +748,152 @@ void gen9_sanitize_dc_state(struct drm_i915_private *i915)
* back on and register state is restored. This is guaranteed by the MMIO write
* to DC_STATE_EN blocking until the state is restored.
*/
void gen9_set_dc_state(struct drm_i915_private *dev_priv, u32 state)
void gen9_set_dc_state(struct intel_display *display, u32 state)
{
struct i915_power_domains *power_domains = &dev_priv->display.power.domains;
struct i915_power_domains *power_domains = &display->power.domains;
u32 val;
u32 mask;
if (!HAS_DISPLAY(dev_priv))
if (!HAS_DISPLAY(display))
return;
if (drm_WARN_ON_ONCE(&dev_priv->drm,
if (drm_WARN_ON_ONCE(display->drm,
state & ~power_domains->allowed_dc_mask))
state &= power_domains->allowed_dc_mask;
val = intel_de_read(dev_priv, DC_STATE_EN);
mask = gen9_dc_mask(dev_priv);
drm_dbg_kms(&dev_priv->drm, "Setting DC state from %02x to %02x\n",
val = intel_de_read(display, DC_STATE_EN);
mask = gen9_dc_mask(display);
drm_dbg_kms(display->drm, "Setting DC state from %02x to %02x\n",
val & mask, state);
/* Check if DMC is ignoring our DC state requests */
if ((val & mask) != power_domains->dc_state)
drm_err(&dev_priv->drm, "DC state mismatch (0x%x -> 0x%x)\n",
drm_err(display->drm, "DC state mismatch (0x%x -> 0x%x)\n",
power_domains->dc_state, val & mask);
val &= ~mask;
val |= state;
gen9_write_dc_state(dev_priv, val);
gen9_write_dc_state(display, val);
power_domains->dc_state = val & mask;
}
static void tgl_enable_dc3co(struct drm_i915_private *dev_priv)
static void tgl_enable_dc3co(struct intel_display *display)
{
drm_dbg_kms(&dev_priv->drm, "Enabling DC3CO\n");
gen9_set_dc_state(dev_priv, DC_STATE_EN_DC3CO);
drm_dbg_kms(display->drm, "Enabling DC3CO\n");
gen9_set_dc_state(display, DC_STATE_EN_DC3CO);
}
static void tgl_disable_dc3co(struct drm_i915_private *dev_priv)
static void tgl_disable_dc3co(struct intel_display *display)
{
drm_dbg_kms(&dev_priv->drm, "Disabling DC3CO\n");
intel_de_rmw(dev_priv, DC_STATE_EN, DC_STATE_DC3CO_STATUS, 0);
gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);
drm_dbg_kms(display->drm, "Disabling DC3CO\n");
intel_de_rmw(display, DC_STATE_EN, DC_STATE_DC3CO_STATUS, 0);
gen9_set_dc_state(display, DC_STATE_DISABLE);
/*
* Delay of 200us DC3CO Exit time B.Spec 49196
*/
usleep_range(200, 210);
}
static void assert_can_enable_dc5(struct drm_i915_private *dev_priv)
static void assert_can_enable_dc5(struct intel_display *display)
{
struct drm_i915_private *dev_priv = to_i915(display->drm);
enum i915_power_well_id high_pg;
/* Power wells at this level and above must be disabled for DC5 entry */
if (DISPLAY_VER(dev_priv) == 12)
if (DISPLAY_VER(display) == 12)
high_pg = ICL_DISP_PW_3;
else
high_pg = SKL_DISP_PW_2;
drm_WARN_ONCE(&dev_priv->drm,
drm_WARN_ONCE(display->drm,
intel_display_power_well_is_enabled(dev_priv, high_pg),
"Power wells above platform's DC5 limit still enabled.\n");
drm_WARN_ONCE(&dev_priv->drm,
(intel_de_read(dev_priv, DC_STATE_EN) &
drm_WARN_ONCE(display->drm,
(intel_de_read(display, DC_STATE_EN) &
DC_STATE_EN_UPTO_DC5),
"DC5 already programmed to be enabled.\n");
assert_rpm_wakelock_held(&dev_priv->runtime_pm);
assert_dmc_loaded(dev_priv);
assert_dmc_loaded(display);
}
void gen9_enable_dc5(struct drm_i915_private *dev_priv)
void gen9_enable_dc5(struct intel_display *display)
{
assert_can_enable_dc5(dev_priv);
struct drm_i915_private *dev_priv = to_i915(display->drm);
drm_dbg_kms(&dev_priv->drm, "Enabling DC5\n");
assert_can_enable_dc5(display);
drm_dbg_kms(display->drm, "Enabling DC5\n");
/* Wa Display #1183: skl,kbl,cfl */
if (DISPLAY_VER(dev_priv) == 9 && !IS_BROXTON(dev_priv))
intel_de_rmw(dev_priv, GEN8_CHICKEN_DCPR_1,
if (DISPLAY_VER(display) == 9 && !IS_BROXTON(dev_priv))
intel_de_rmw(display, GEN8_CHICKEN_DCPR_1,
0, SKL_SELECT_ALTERNATE_DC_EXIT);
intel_dmc_wl_enable(&dev_priv->display);
intel_dmc_wl_enable(display);
gen9_set_dc_state(dev_priv, DC_STATE_EN_UPTO_DC5);
gen9_set_dc_state(display, DC_STATE_EN_UPTO_DC5);
}
static void assert_can_enable_dc6(struct drm_i915_private *dev_priv)
static void assert_can_enable_dc6(struct intel_display *display)
{
drm_WARN_ONCE(&dev_priv->drm,
(intel_de_read(dev_priv, UTIL_PIN_CTL) &
drm_WARN_ONCE(display->drm,
(intel_de_read(display, UTIL_PIN_CTL) &
(UTIL_PIN_ENABLE | UTIL_PIN_MODE_MASK)) ==
(UTIL_PIN_ENABLE | UTIL_PIN_MODE_PWM),
"Utility pin enabled in PWM mode\n");
drm_WARN_ONCE(&dev_priv->drm,
(intel_de_read(dev_priv, DC_STATE_EN) &
drm_WARN_ONCE(display->drm,
(intel_de_read(display, DC_STATE_EN) &
DC_STATE_EN_UPTO_DC6),
"DC6 already programmed to be enabled.\n");
assert_dmc_loaded(dev_priv);
assert_dmc_loaded(display);
}
void skl_enable_dc6(struct drm_i915_private *dev_priv)
void skl_enable_dc6(struct intel_display *display)
{
assert_can_enable_dc6(dev_priv);
struct drm_i915_private *dev_priv = to_i915(display->drm);
drm_dbg_kms(&dev_priv->drm, "Enabling DC6\n");
assert_can_enable_dc6(display);
drm_dbg_kms(display->drm, "Enabling DC6\n");
/* Wa Display #1183: skl,kbl,cfl */
if (DISPLAY_VER(dev_priv) == 9 && !IS_BROXTON(dev_priv))
intel_de_rmw(dev_priv, GEN8_CHICKEN_DCPR_1,
if (DISPLAY_VER(display) == 9 && !IS_BROXTON(dev_priv))
intel_de_rmw(display, GEN8_CHICKEN_DCPR_1,
0, SKL_SELECT_ALTERNATE_DC_EXIT);
intel_dmc_wl_enable(&dev_priv->display);
intel_dmc_wl_enable(display);
gen9_set_dc_state(dev_priv, DC_STATE_EN_UPTO_DC6);
gen9_set_dc_state(display, DC_STATE_EN_UPTO_DC6);
}
void bxt_enable_dc9(struct drm_i915_private *dev_priv)
void bxt_enable_dc9(struct intel_display *display)
{
struct intel_display *display = &dev_priv->display;
struct drm_i915_private *dev_priv = to_i915(display->drm);
assert_can_enable_dc9(dev_priv);
assert_can_enable_dc9(display);
drm_dbg_kms(&dev_priv->drm, "Enabling DC9\n");
drm_dbg_kms(display->drm, "Enabling DC9\n");
/*
* Power sequencer reset is not needed on
* platforms with South Display Engine on PCH,
* because PPS registers are always on.
* Power sequencer reset is needed on BXT/GLK, because the PPS registers
* aren't always on, unlike with South Display Engine on PCH.
*/
if (!HAS_PCH_SPLIT(dev_priv))
intel_pps_reset_all(display);
gen9_set_dc_state(dev_priv, DC_STATE_EN_DC9);
if (IS_BROXTON(dev_priv) || IS_GEMINILAKE(dev_priv))
bxt_pps_reset_all(display);
gen9_set_dc_state(display, DC_STATE_EN_DC9);
}
void bxt_disable_dc9(struct drm_i915_private *dev_priv)
void bxt_disable_dc9(struct intel_display *display)
{
struct intel_display *display = &dev_priv->display;
assert_can_disable_dc9(display);
assert_can_disable_dc9(dev_priv);
drm_dbg_kms(display->drm, "Disabling DC9\n");
drm_dbg_kms(&dev_priv->drm, "Disabling DC9\n");
gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);
gen9_set_dc_state(display, DC_STATE_DISABLE);
intel_pps_unlock_regs_wa(display);
}
@ -949,8 +958,10 @@ static void bxt_verify_dpio_phy_power_wells(struct drm_i915_private *dev_priv)
static bool gen9_dc_off_power_well_enabled(struct drm_i915_private *dev_priv,
struct i915_power_well *power_well)
{
return ((intel_de_read(dev_priv, DC_STATE_EN) & DC_STATE_EN_DC3CO) == 0 &&
(intel_de_read(dev_priv, DC_STATE_EN) & DC_STATE_EN_UPTO_DC5_DC6_MASK) == 0);
struct intel_display *display = &dev_priv->display;
return ((intel_de_read(display, DC_STATE_EN) & DC_STATE_EN_DC3CO) == 0 &&
(intel_de_read(display, DC_STATE_EN) & DC_STATE_EN_UPTO_DC5_DC6_MASK) == 0);
}
static void gen9_assert_dbuf_enabled(struct drm_i915_private *dev_priv)
@ -965,27 +976,28 @@ static void gen9_assert_dbuf_enabled(struct drm_i915_private *dev_priv)
enabled_dbuf_slices);
}
void gen9_disable_dc_states(struct drm_i915_private *dev_priv)
void gen9_disable_dc_states(struct intel_display *display)
{
struct i915_power_domains *power_domains = &dev_priv->display.power.domains;
struct drm_i915_private *dev_priv = to_i915(display->drm);
struct i915_power_domains *power_domains = &display->power.domains;
struct intel_cdclk_config cdclk_config = {};
if (power_domains->target_dc_state == DC_STATE_EN_DC3CO) {
tgl_disable_dc3co(dev_priv);
tgl_disable_dc3co(display);
return;
}
gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);
gen9_set_dc_state(display, DC_STATE_DISABLE);
if (!HAS_DISPLAY(dev_priv))
if (!HAS_DISPLAY(display))
return;
intel_dmc_wl_disable(&dev_priv->display);
intel_dmc_wl_disable(display);
intel_cdclk_get_cdclk(dev_priv, &cdclk_config);
intel_cdclk_get_cdclk(display, &cdclk_config);
/* Can't read out voltage_level so can't use intel_cdclk_changed() */
drm_WARN_ON(&dev_priv->drm,
intel_cdclk_clock_changed(&dev_priv->display.cdclk.hw,
drm_WARN_ON(display->drm,
intel_cdclk_clock_changed(&display->cdclk.hw,
&cdclk_config));
gen9_assert_dbuf_enabled(dev_priv);
@ -993,7 +1005,7 @@ void gen9_disable_dc_states(struct drm_i915_private *dev_priv)
if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
bxt_verify_dpio_phy_power_wells(dev_priv);
if (DISPLAY_VER(dev_priv) >= 11)
if (DISPLAY_VER(display) >= 11)
/*
* DMC retains HW context only for port A, the other combo
* PHY's HW context for port B is lost after DC transitions,
@ -1005,26 +1017,29 @@ void gen9_disable_dc_states(struct drm_i915_private *dev_priv)
static void gen9_dc_off_power_well_enable(struct drm_i915_private *dev_priv,
struct i915_power_well *power_well)
{
gen9_disable_dc_states(dev_priv);
struct intel_display *display = &dev_priv->display;
gen9_disable_dc_states(display);
}
static void gen9_dc_off_power_well_disable(struct drm_i915_private *dev_priv,
struct i915_power_well *power_well)
{
struct i915_power_domains *power_domains = &dev_priv->display.power.domains;
struct intel_display *display = &dev_priv->display;
struct i915_power_domains *power_domains = &display->power.domains;
if (!intel_dmc_has_payload(dev_priv))
if (!intel_dmc_has_payload(display))
return;
switch (power_domains->target_dc_state) {
case DC_STATE_EN_DC3CO:
tgl_enable_dc3co(dev_priv);
tgl_enable_dc3co(display);
break;
case DC_STATE_EN_UPTO_DC6:
skl_enable_dc6(dev_priv);
skl_enable_dc6(display);
break;
case DC_STATE_EN_UPTO_DC5:
gen9_enable_dc5(dev_priv);
gen9_enable_dc5(display);
break;
}
}
@ -1048,24 +1063,30 @@ static bool i9xx_always_on_power_well_enabled(struct drm_i915_private *dev_priv,
static void i830_pipes_power_well_enable(struct drm_i915_private *dev_priv,
struct i915_power_well *power_well)
{
if ((intel_de_read(dev_priv, TRANSCONF(dev_priv, PIPE_A)) & TRANSCONF_ENABLE) == 0)
i830_enable_pipe(dev_priv, PIPE_A);
if ((intel_de_read(dev_priv, TRANSCONF(dev_priv, PIPE_B)) & TRANSCONF_ENABLE) == 0)
i830_enable_pipe(dev_priv, PIPE_B);
struct intel_display *display = &dev_priv->display;
if ((intel_de_read(display, TRANSCONF(dev_priv, PIPE_A)) & TRANSCONF_ENABLE) == 0)
i830_enable_pipe(display, PIPE_A);
if ((intel_de_read(display, TRANSCONF(dev_priv, PIPE_B)) & TRANSCONF_ENABLE) == 0)
i830_enable_pipe(display, PIPE_B);
}
static void i830_pipes_power_well_disable(struct drm_i915_private *dev_priv,
struct i915_power_well *power_well)
{
i830_disable_pipe(dev_priv, PIPE_B);
i830_disable_pipe(dev_priv, PIPE_A);
struct intel_display *display = &dev_priv->display;
i830_disable_pipe(display, PIPE_B);
i830_disable_pipe(display, PIPE_A);
}
static bool i830_pipes_power_well_enabled(struct drm_i915_private *dev_priv,
struct i915_power_well *power_well)
{
return intel_de_read(dev_priv, TRANSCONF(dev_priv, PIPE_A)) & TRANSCONF_ENABLE &&
intel_de_read(dev_priv, TRANSCONF(dev_priv, PIPE_B)) & TRANSCONF_ENABLE;
struct intel_display *display = &dev_priv->display;
return intel_de_read(display, TRANSCONF(dev_priv, PIPE_A)) & TRANSCONF_ENABLE &&
intel_de_read(display, TRANSCONF(dev_priv, PIPE_B)) & TRANSCONF_ENABLE;
}
static void i830_pipes_power_well_sync_hw(struct drm_i915_private *dev_priv,
@ -1232,7 +1253,7 @@ static void vlv_display_power_well_init(struct drm_i915_private *dev_priv)
intel_crt_reset(&encoder->base);
}
intel_vga_redisable_power_on(dev_priv);
intel_vga_redisable_power_on(display);
intel_pps_unlock_regs_wa(display);
}
@ -1248,7 +1269,7 @@ static void vlv_display_power_well_deinit(struct drm_i915_private *dev_priv)
/* make sure we're done processing display irqs */
intel_synchronize_irq(dev_priv);
intel_pps_reset_all(display);
vlv_pps_reset_all(display);
/* Prevent us from re-enabling polling on accident in late suspend */
if (!dev_priv->drm.dev->power.is_suspended)

View File

@ -12,6 +12,7 @@
struct drm_i915_private;
struct i915_power_well_ops;
struct intel_display;
struct intel_encoder;
#define for_each_power_well(__dev_priv, __power_well) \
@ -154,13 +155,13 @@ void chv_phy_powergate_lanes(struct intel_encoder *encoder,
bool chv_phy_powergate_ch(struct drm_i915_private *dev_priv, enum dpio_phy phy,
enum dpio_channel ch, bool override);
void gen9_enable_dc5(struct drm_i915_private *dev_priv);
void skl_enable_dc6(struct drm_i915_private *dev_priv);
void gen9_sanitize_dc_state(struct drm_i915_private *dev_priv);
void gen9_set_dc_state(struct drm_i915_private *dev_priv, u32 state);
void gen9_disable_dc_states(struct drm_i915_private *dev_priv);
void bxt_enable_dc9(struct drm_i915_private *dev_priv);
void bxt_disable_dc9(struct drm_i915_private *dev_priv);
void gen9_enable_dc5(struct intel_display *display);
void skl_enable_dc6(struct intel_display *display);
void gen9_sanitize_dc_state(struct intel_display *display);
void gen9_set_dc_state(struct intel_display *display, u32 state);
void gen9_disable_dc_states(struct intel_display *display);
void bxt_enable_dc9(struct intel_display *display);
void bxt_disable_dc9(struct intel_display *display);
extern const struct i915_power_well_ops i9xx_always_on_power_well_ops;
extern const struct i915_power_well_ops chv_pipe_power_well_ops;

View File

@ -0,0 +1,72 @@
// SPDX-License-Identifier: MIT
/* Copyright © 2024 Intel Corporation */
#include <linux/slab.h>
#include "i915_drv.h"
#include "intel_display_device.h"
#include "intel_display_params.h"
#include "intel_display_snapshot.h"
#include "intel_dmc.h"
#include "intel_overlay.h"
struct intel_display_snapshot {
struct intel_display *display;
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_snapshot *intel_display_snapshot_capture(struct intel_display *display)
{
struct intel_display_snapshot *snapshot;
snapshot = kzalloc(sizeof(*snapshot), GFP_ATOMIC);
if (!snapshot)
return NULL;
snapshot->display = display;
memcpy(&snapshot->info, DISPLAY_INFO(display), sizeof(snapshot->info));
memcpy(&snapshot->runtime_info, DISPLAY_RUNTIME_INFO(display),
sizeof(snapshot->runtime_info));
intel_display_params_copy(&snapshot->params);
snapshot->overlay = intel_overlay_snapshot_capture(display);
snapshot->dmc = intel_dmc_snapshot_capture(display);
return snapshot;
}
void intel_display_snapshot_print(const struct intel_display_snapshot *snapshot,
struct drm_printer *p)
{
struct intel_display *display;
if (!snapshot)
return;
display = snapshot->display;
intel_display_device_info_print(&snapshot->info, &snapshot->runtime_info, p);
intel_display_params_dump(&snapshot->params, display->drm->driver->name, p);
intel_overlay_snapshot_print(snapshot->overlay, p);
intel_dmc_snapshot_print(snapshot->dmc, p);
}
void intel_display_snapshot_free(struct intel_display_snapshot *snapshot)
{
if (!snapshot)
return;
intel_display_params_free(&snapshot->params);
kfree(snapshot->overlay);
kfree(snapshot->dmc);
kfree(snapshot);
}

View File

@ -0,0 +1,16 @@
/* SPDX-License-Identifier: MIT */
/* Copyright © 2024 Intel Corporation */
#ifndef __INTEL_DISPLAY_SNAPSHOT_H__
#define __INTEL_DISPLAY_SNAPSHOT_H__
struct drm_printer;
struct intel_display;
struct intel_display_snapshot;
struct intel_display_snapshot *intel_display_snapshot_capture(struct intel_display *display);
void intel_display_snapshot_print(const struct intel_display_snapshot *snapshot,
struct drm_printer *p);
void intel_display_snapshot_free(struct intel_display_snapshot *snapshot);
#endif /* __INTEL_DISPLAY_SNAPSHOT_H__ */

View File

@ -18,7 +18,7 @@
#include "intel_display_types.h"
#include "intel_vblank.h"
#define __dev_name_i915(i915) dev_name((i915)->drm.dev)
#define __dev_name_display(display) dev_name((display)->drm->dev)
#define __dev_name_kms(obj) dev_name((obj)->base.dev->dev)
TRACE_EVENT(intel_pipe_enable,
@ -32,10 +32,10 @@ TRACE_EVENT(intel_pipe_enable,
__field(enum pipe, pipe)
),
TP_fast_assign(
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
struct intel_display *display = to_intel_display(crtc);
struct intel_crtc *it__;
__assign_str(dev);
for_each_intel_crtc(&dev_priv->drm, it__) {
for_each_intel_crtc(display->drm, it__) {
__entry->frame[it__->pipe] = intel_crtc_get_vblank_counter(it__);
__entry->scanline[it__->pipe] = intel_get_crtc_scanline(it__);
}
@ -61,10 +61,10 @@ TRACE_EVENT(intel_pipe_disable,
),
TP_fast_assign(
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
struct intel_display *display = to_intel_display(crtc);
struct intel_crtc *it__;
__assign_str(dev);
for_each_intel_crtc(&dev_priv->drm, it__) {
for_each_intel_crtc(display->drm, it__) {
__entry->frame[it__->pipe] = intel_crtc_get_vblank_counter(it__);
__entry->scanline[it__->pipe] = intel_get_crtc_scanline(it__);
}
@ -130,18 +130,18 @@ TRACE_EVENT(intel_pipe_crc,
);
TRACE_EVENT(intel_cpu_fifo_underrun,
TP_PROTO(struct drm_i915_private *dev_priv, enum pipe pipe),
TP_ARGS(dev_priv, pipe),
TP_PROTO(struct intel_display *display, enum pipe pipe),
TP_ARGS(display, pipe),
TP_STRUCT__entry(
__string(dev, __dev_name_i915(dev_priv))
__string(dev, __dev_name_display(display))
__field(enum pipe, pipe)
__field(u32, frame)
__field(u32, scanline)
),
TP_fast_assign(
struct intel_crtc *crtc = intel_crtc_for_pipe(dev_priv, pipe);
struct intel_crtc *crtc = intel_crtc_for_pipe(display, pipe);
__assign_str(dev);
__entry->pipe = pipe;
__entry->frame = intel_crtc_get_vblank_counter(crtc);
@ -154,11 +154,11 @@ TRACE_EVENT(intel_cpu_fifo_underrun,
);
TRACE_EVENT(intel_pch_fifo_underrun,
TP_PROTO(struct drm_i915_private *dev_priv, enum pipe pch_transcoder),
TP_ARGS(dev_priv, pch_transcoder),
TP_PROTO(struct intel_display *display, enum pipe pch_transcoder),
TP_ARGS(display, pch_transcoder),
TP_STRUCT__entry(
__string(dev, __dev_name_i915(dev_priv))
__string(dev, __dev_name_display(display))
__field(enum pipe, pipe)
__field(u32, frame)
__field(u32, scanline)
@ -166,7 +166,7 @@ TRACE_EVENT(intel_pch_fifo_underrun,
TP_fast_assign(
enum pipe pipe = pch_transcoder;
struct intel_crtc *crtc = intel_crtc_for_pipe(dev_priv, pipe);
struct intel_crtc *crtc = intel_crtc_for_pipe(display, pipe);
__assign_str(dev);
__entry->pipe = pipe;
__entry->frame = intel_crtc_get_vblank_counter(crtc);
@ -179,11 +179,11 @@ TRACE_EVENT(intel_pch_fifo_underrun,
);
TRACE_EVENT(intel_memory_cxsr,
TP_PROTO(struct drm_i915_private *dev_priv, bool old, bool new),
TP_ARGS(dev_priv, old, new),
TP_PROTO(struct intel_display *display, bool old, bool new),
TP_ARGS(display, old, new),
TP_STRUCT__entry(
__string(dev, __dev_name_i915(dev_priv))
__string(dev, __dev_name_display(display))
__array(u32, frame, 3)
__array(u32, scanline, 3)
__field(bool, old)
@ -193,7 +193,7 @@ TRACE_EVENT(intel_memory_cxsr,
TP_fast_assign(
struct intel_crtc *crtc;
__assign_str(dev);
for_each_intel_crtc(&dev_priv->drm, crtc) {
for_each_intel_crtc(display->drm, crtc) {
__entry->frame[crtc->pipe] = intel_crtc_get_vblank_counter(crtc);
__entry->scanline[crtc->pipe] = intel_get_crtc_scanline(crtc);
}
@ -458,7 +458,8 @@ TRACE_EVENT(intel_fbc_activate,
),
TP_fast_assign(
struct intel_crtc *crtc = intel_crtc_for_pipe(to_i915(plane->base.dev),
struct intel_display *display = to_intel_display(plane->base.dev);
struct intel_crtc *crtc = intel_crtc_for_pipe(display,
plane->pipe);
__assign_str(dev);
__assign_str(name);
@ -485,7 +486,8 @@ TRACE_EVENT(intel_fbc_deactivate,
),
TP_fast_assign(
struct intel_crtc *crtc = intel_crtc_for_pipe(to_i915(plane->base.dev),
struct intel_display *display = to_intel_display(plane->base.dev);
struct intel_crtc *crtc = intel_crtc_for_pipe(display,
plane->pipe);
__assign_str(dev);
__assign_str(name);
@ -512,7 +514,8 @@ TRACE_EVENT(intel_fbc_nuke,
),
TP_fast_assign(
struct intel_crtc *crtc = intel_crtc_for_pipe(to_i915(plane->base.dev),
struct intel_display *display = to_intel_display(plane->base.dev);
struct intel_crtc *crtc = intel_crtc_for_pipe(display,
plane->pipe);
__assign_str(dev);
__assign_str(name);
@ -652,12 +655,12 @@ TRACE_EVENT(intel_pipe_update_end,
);
TRACE_EVENT(intel_frontbuffer_invalidate,
TP_PROTO(struct drm_i915_private *i915,
TP_PROTO(struct intel_display *display,
unsigned int frontbuffer_bits, unsigned int origin),
TP_ARGS(i915, frontbuffer_bits, origin),
TP_ARGS(display, frontbuffer_bits, origin),
TP_STRUCT__entry(
__string(dev, __dev_name_i915(i915))
__string(dev, __dev_name_display(display))
__field(unsigned int, frontbuffer_bits)
__field(unsigned int, origin)
),
@ -673,12 +676,12 @@ TRACE_EVENT(intel_frontbuffer_invalidate,
);
TRACE_EVENT(intel_frontbuffer_flush,
TP_PROTO(struct drm_i915_private *i915,
TP_PROTO(struct intel_display *display,
unsigned int frontbuffer_bits, unsigned int origin),
TP_ARGS(i915, frontbuffer_bits, origin),
TP_ARGS(display, frontbuffer_bits, origin),
TP_STRUCT__entry(
__string(dev, __dev_name_i915(i915))
__string(dev, __dev_name_display(display))
__field(unsigned int, frontbuffer_bits)
__field(unsigned int, origin)
),

View File

@ -26,10 +26,8 @@
#ifndef __INTEL_DISPLAY_TYPES_H__
#define __INTEL_DISPLAY_TYPES_H__
#include <linux/i2c.h>
#include <linux/pm_qos.h>
#include <linux/pwm.h>
#include <linux/sched/clock.h>
#include <drm/display/drm_dp_dual_mode_helper.h>
#include <drm/display/drm_dp_mst_helper.h>
@ -38,16 +36,11 @@
#include <drm/drm_atomic.h>
#include <drm/drm_crtc.h>
#include <drm/drm_encoder.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_probe_helper.h>
#include <drm/drm_rect.h>
#include <drm/drm_vblank.h>
#include <drm/drm_vblank_work.h>
#include <drm/intel/i915_hdcp_interface.h>
#include <media/cec-notifier.h>
#include "gem/i915_gem_object_types.h" /* for to_intel_bo() */
#include "i915_vma.h"
#include "i915_vma_types.h"
#include "intel_bios.h"
@ -57,11 +50,13 @@
#include "intel_dpll_mgr.h"
#include "intel_wm_types.h"
struct cec_notifier;
struct drm_printer;
struct __intel_global_objs_state;
struct intel_connector;
struct intel_ddi_buf_trans;
struct intel_fbc;
struct intel_connector;
struct intel_hdcp_shim;
struct intel_tc_port;
/*
@ -430,128 +425,6 @@ struct intel_panel {
struct intel_digital_port;
enum check_link_response {
HDCP_LINK_PROTECTED = 0,
HDCP_TOPOLOGY_CHANGE,
HDCP_LINK_INTEGRITY_FAILURE,
HDCP_REAUTH_REQUEST
};
/*
* This structure serves as a translation layer between the generic HDCP code
* and the bus-specific code. What that means is that HDCP over HDMI differs
* from HDCP over DP, so to account for these differences, we need to
* communicate with the receiver through this shim.
*
* For completeness, the 2 buses differ in the following ways:
* - DP AUX vs. DDC
* HDCP registers on the receiver are set via DP AUX for DP, and
* they are set via DDC for HDMI.
* - Receiver register offsets
* The offsets of the registers are different for DP vs. HDMI
* - Receiver register masks/offsets
* For instance, the ready bit for the KSV fifo is in a different
* place on DP vs HDMI
* - Receiver register names
* Seriously. In the DP spec, the 16-bit register containing
* downstream information is called BINFO, on HDMI it's called
* BSTATUS. To confuse matters further, DP has a BSTATUS register
* with a completely different definition.
* - KSV FIFO
* On HDMI, the ksv fifo is read all at once, whereas on DP it must
* be read 3 keys at a time
* - Aksv output
* Since Aksv is hidden in hardware, there's different procedures
* to send it over DP AUX vs DDC
*/
struct intel_hdcp_shim {
/* Outputs the transmitter's An and Aksv values to the receiver. */
int (*write_an_aksv)(struct intel_digital_port *dig_port, u8 *an);
/* Reads the receiver's key selection vector */
int (*read_bksv)(struct intel_digital_port *dig_port, u8 *bksv);
/*
* Reads BINFO from DP receivers and BSTATUS from HDMI receivers. The
* definitions are the same in the respective specs, but the names are
* different. Call it BSTATUS since that's the name the HDMI spec
* uses and it was there first.
*/
int (*read_bstatus)(struct intel_digital_port *dig_port,
u8 *bstatus);
/* Determines whether a repeater is present downstream */
int (*repeater_present)(struct intel_digital_port *dig_port,
bool *repeater_present);
/* Reads the receiver's Ri' value */
int (*read_ri_prime)(struct intel_digital_port *dig_port, u8 *ri);
/* Determines if the receiver's KSV FIFO is ready for consumption */
int (*read_ksv_ready)(struct intel_digital_port *dig_port,
bool *ksv_ready);
/* Reads the ksv fifo for num_downstream devices */
int (*read_ksv_fifo)(struct intel_digital_port *dig_port,
int num_downstream, u8 *ksv_fifo);
/* Reads a 32-bit part of V' from the receiver */
int (*read_v_prime_part)(struct intel_digital_port *dig_port,
int i, u32 *part);
/* Enables HDCP signalling on the port */
int (*toggle_signalling)(struct intel_digital_port *dig_port,
enum transcoder cpu_transcoder,
bool enable);
/* Enable/Disable stream encryption on DP MST Transport Link */
int (*stream_encryption)(struct intel_connector *connector,
bool enable);
/* Ensures the link is still protected */
bool (*check_link)(struct intel_digital_port *dig_port,
struct intel_connector *connector);
/* Detects panel's hdcp capability. This is optional for HDMI. */
int (*hdcp_get_capability)(struct intel_digital_port *dig_port,
bool *hdcp_capable);
/* HDCP adaptation(DP/HDMI) required on the port */
enum hdcp_wired_protocol protocol;
/* Detects whether sink is HDCP2.2 capable */
int (*hdcp_2_2_get_capability)(struct intel_connector *connector,
bool *capable);
/* Write HDCP2.2 messages */
int (*write_2_2_msg)(struct intel_connector *connector,
void *buf, size_t size);
/* Read HDCP2.2 messages */
int (*read_2_2_msg)(struct intel_connector *connector,
u8 msg_id, void *buf, size_t size);
/*
* Implementation of DP HDCP2.2 Errata for the communication of stream
* type to Receivers. In DP HDCP2.2 Stream type is one of the input to
* the HDCP2.2 Cipher for En/De-Cryption. Not applicable for HDMI.
*/
int (*config_stream_type)(struct intel_connector *connector,
bool is_repeater, u8 type);
/* Enable/Disable HDCP 2.2 stream encryption on DP MST Transport Link */
int (*stream_2_2_encryption)(struct intel_connector *connector,
bool enable);
/* HDCP2.2 Link Integrity Check */
int (*check_2_2_link)(struct intel_digital_port *dig_port,
struct intel_connector *connector);
/* HDCP remote sink cap */
int (*get_remote_hdcp_capability)(struct intel_connector *connector,
bool *hdcp_capable, bool *hdcp2_capable);
};
struct intel_hdcp {
const struct intel_hdcp_shim *shim;
/* Mutex for hdcp state of the connector */
@ -651,7 +524,7 @@ struct intel_connector {
struct intel_dp *mst_port;
bool force_bigjoiner_enable;
int force_joined_pipes;
struct {
struct drm_dp_aux *dsc_decompression_aux;
@ -1036,6 +909,10 @@ struct intel_csc_matrix {
u16 postoff[3];
};
void intel_io_mmio_fw_write(void *ctx, i915_reg_t reg, u32 val);
typedef void (*intel_io_reg_write)(void *ctx, i915_reg_t reg, u32 val);
struct intel_crtc_state {
/*
* uapi (drm) state. This is the software state shown to userspace.
@ -1270,9 +1147,6 @@ struct intel_crtc_state {
/* w/a for waiting 2 vblanks during crtc enable */
enum pipe hsw_workaround_pipe;
/* IVB sprite scaling w/a (WaCxSRDisabledForSpriteScaling:ivb) */
bool disable_lp_wm;
struct intel_crtc_wm_state wm;
int min_cdclk[I915_MAX_PLANES];
@ -1396,8 +1270,9 @@ struct intel_crtc_state {
/* Only valid on TGL+ */
enum transcoder mst_master_transcoder;
/* For DSB based color LUT updates */
struct intel_dsb *dsb_color_vblank, *dsb_color_commit;
/* For DSB based pipe updates */
struct intel_dsb *dsb_color_vblank, *dsb_commit;
bool use_dsb;
u32 psr2_man_track_ctl;
@ -1488,6 +1363,8 @@ struct intel_crtc {
/* armed event for async flip */
struct drm_pending_vblank_event *flip_done_event;
/* armed event for DSB based updates */
struct drm_pending_vblank_event *dsb_event;
/* Access to these should be protected by dev_priv->irq_lock. */
bool cpu_fifo_underrun_disabled;
@ -1540,6 +1417,8 @@ struct intel_crtc {
#ifdef CONFIG_DEBUG_FS
struct intel_pipe_crc pipe_crc;
#endif
bool block_dc_for_vblank;
};
struct intel_plane {
@ -1578,22 +1457,26 @@ struct intel_plane {
u32 pixel_format, u64 modifier,
unsigned int rotation);
/* Write all non-self arming plane registers */
void (*update_noarm)(struct intel_plane *plane,
void (*update_noarm)(struct intel_dsb *dsb,
struct intel_plane *plane,
const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state);
/* Write all self-arming plane registers */
void (*update_arm)(struct intel_plane *plane,
void (*update_arm)(struct intel_dsb *dsb,
struct intel_plane *plane,
const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state);
/* Disable the plane, must arm */
void (*disable_arm)(struct intel_plane *plane,
void (*disable_arm)(struct intel_dsb *dsb,
struct intel_plane *plane,
const struct intel_crtc_state *crtc_state);
bool (*get_hw_state)(struct intel_plane *plane, enum pipe *pipe);
int (*check_plane)(struct intel_crtc_state *crtc_state,
struct intel_plane_state *plane_state);
int (*min_cdclk)(const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state);
void (*async_flip)(struct intel_plane *plane,
void (*async_flip)(struct intel_dsb *dsb,
struct intel_plane *plane,
const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state,
bool async_flip);
@ -1601,14 +1484,6 @@ struct intel_plane {
void (*disable_flip_done)(struct intel_plane *plane);
};
struct intel_watermark_params {
u16 fifo_size;
u16 max_wm;
u8 default_wm;
u8 guard_size;
u8 cacheline_size;
};
#define to_intel_atomic_state(x) container_of(x, struct intel_atomic_state, base)
#define to_intel_crtc(x) container_of(x, struct intel_crtc, base)
#define to_intel_connector(x) container_of(x, struct intel_connector, base)
@ -1622,8 +1497,6 @@ struct intel_watermark_params {
#define to_intel_framebuffer(fb) \
container_of_const((fb), struct intel_framebuffer, base)
#define intel_fb_obj(x) ((x) ? to_intel_bo((x)->obj[0]) : NULL)
struct intel_hdmi {
i915_reg_t hdmi_reg;
struct {
@ -1676,7 +1549,7 @@ struct intel_pps {
* Pipe whose power sequencer is currently locked into
* this port. Only relevant on VLV/CHV.
*/
enum pipe pps_pipe;
enum pipe vlv_pps_pipe;
/*
* Power sequencer index. Only relevant on BXT+.
@ -1689,12 +1562,12 @@ struct intel_pps {
* the use of the PPS for any pipe currentrly driving
* external DP as that will mess things up on VLV.
*/
enum pipe active_pipe;
enum pipe vlv_active_pipe;
/*
* Set if the sequencer may be reset due to a power transition,
* requiring a reinitialization. Only relevant on BXT+.
*/
bool pps_reset;
bool bxt_pps_reset;
struct edp_power_seq pps_delays;
struct edp_power_seq bios_pps_delays;
};
@ -2050,7 +1923,10 @@ static inline struct intel_dp *enc_to_intel_dp(struct intel_encoder *encoder)
static inline struct intel_dp *intel_attached_dp(struct intel_connector *connector)
{
return enc_to_intel_dp(intel_attached_encoder(connector));
if (connector->mst_port)
return connector->mst_port;
else
return enc_to_intel_dp(intel_attached_encoder(connector));
}
static inline bool intel_encoder_is_dp(struct intel_encoder *encoder)

View File

@ -52,7 +52,7 @@ enum intel_dmc_id {
};
struct intel_dmc {
struct drm_i915_private *i915;
struct intel_display *display;
struct work_struct work;
const char *fw_path;
u32 max_fw_size; /* bytes */
@ -70,21 +70,21 @@ struct intel_dmc {
};
/* Note: This may be NULL. */
static struct intel_dmc *i915_to_dmc(struct drm_i915_private *i915)
static struct intel_dmc *display_to_dmc(struct intel_display *display)
{
return i915->display.dmc.dmc;
return display->dmc.dmc;
}
static const char *dmc_firmware_param(struct drm_i915_private *i915)
static const char *dmc_firmware_param(struct intel_display *display)
{
const char *p = i915->display.params.dmc_firmware_path;
const char *p = display->params.dmc_firmware_path;
return p && *p ? p : NULL;
}
static bool dmc_firmware_param_disabled(struct drm_i915_private *i915)
static bool dmc_firmware_param_disabled(struct intel_display *display)
{
const char *p = dmc_firmware_param(i915);
const char *p = dmc_firmware_param(display);
/* Magic path to indicate disabled */
return p && !strcmp(p, "/dev/null");
@ -162,18 +162,19 @@ MODULE_FIRMWARE(SKL_DMC_PATH);
#define BXT_DMC_MAX_FW_SIZE 0x3000
MODULE_FIRMWARE(BXT_DMC_PATH);
static const char *dmc_firmware_default(struct drm_i915_private *i915, u32 *size)
static const char *dmc_firmware_default(struct intel_display *display, u32 *size)
{
struct drm_i915_private *i915 = to_i915(display->drm);
const char *fw_path = NULL;
u32 max_fw_size = 0;
if (DISPLAY_VER_FULL(i915) == IP_VER(20, 0)) {
if (DISPLAY_VER_FULL(display) == IP_VER(20, 0)) {
fw_path = XE2LPD_DMC_PATH;
max_fw_size = XE2LPD_DMC_MAX_FW_SIZE;
} else if (DISPLAY_VER_FULL(i915) == IP_VER(14, 1)) {
} else if (DISPLAY_VER_FULL(display) == IP_VER(14, 1)) {
fw_path = BMG_DMC_PATH;
max_fw_size = XELPDP_DMC_MAX_FW_SIZE;
} else if (DISPLAY_VER_FULL(i915) == IP_VER(14, 0)) {
} else if (DISPLAY_VER_FULL(display) == IP_VER(14, 0)) {
fw_path = MTL_DMC_PATH;
max_fw_size = XELPDP_DMC_MAX_FW_SIZE;
} else if (IS_DG2(i915)) {
@ -194,7 +195,7 @@ static const char *dmc_firmware_default(struct drm_i915_private *i915, u32 *size
} else if (IS_TIGERLAKE(i915)) {
fw_path = TGL_DMC_PATH;
max_fw_size = DISPLAY_VER12_DMC_MAX_FW_SIZE;
} else if (DISPLAY_VER(i915) == 11) {
} else if (DISPLAY_VER(display) == 11) {
fw_path = ICL_DMC_PATH;
max_fw_size = ICL_DMC_MAX_FW_SIZE;
} else if (IS_GEMINILAKE(i915)) {
@ -375,70 +376,70 @@ static bool is_valid_dmc_id(enum intel_dmc_id dmc_id)
return dmc_id >= DMC_FW_MAIN && dmc_id < DMC_FW_MAX;
}
static bool has_dmc_id_fw(struct drm_i915_private *i915, enum intel_dmc_id dmc_id)
static bool has_dmc_id_fw(struct intel_display *display, enum intel_dmc_id dmc_id)
{
struct intel_dmc *dmc = i915_to_dmc(i915);
struct intel_dmc *dmc = display_to_dmc(display);
return dmc && dmc->dmc_info[dmc_id].payload;
}
bool intel_dmc_has_payload(struct drm_i915_private *i915)
bool intel_dmc_has_payload(struct intel_display *display)
{
return has_dmc_id_fw(i915, DMC_FW_MAIN);
return has_dmc_id_fw(display, DMC_FW_MAIN);
}
static const struct stepping_info *
intel_get_stepping_info(struct drm_i915_private *i915,
intel_get_stepping_info(struct intel_display *display,
struct stepping_info *si)
{
const char *step_name = intel_step_name(INTEL_DISPLAY_STEP(i915));
const char *step_name = intel_step_name(INTEL_DISPLAY_STEP(display));
si->stepping = step_name[0];
si->substepping = step_name[1];
return si;
}
static void gen9_set_dc_state_debugmask(struct drm_i915_private *i915)
static void gen9_set_dc_state_debugmask(struct intel_display *display)
{
/* The below bit doesn't need to be cleared ever afterwards */
intel_de_rmw(i915, DC_STATE_DEBUG, 0,
intel_de_rmw(display, DC_STATE_DEBUG, 0,
DC_STATE_DEBUG_MASK_CORES | DC_STATE_DEBUG_MASK_MEMORY_UP);
intel_de_posting_read(i915, DC_STATE_DEBUG);
intel_de_posting_read(display, DC_STATE_DEBUG);
}
static void disable_event_handler(struct drm_i915_private *i915,
static void disable_event_handler(struct intel_display *display,
i915_reg_t ctl_reg, i915_reg_t htp_reg)
{
intel_de_write(i915, ctl_reg,
intel_de_write(display, ctl_reg,
REG_FIELD_PREP(DMC_EVT_CTL_TYPE_MASK,
DMC_EVT_CTL_TYPE_EDGE_0_1) |
REG_FIELD_PREP(DMC_EVT_CTL_EVENT_ID_MASK,
DMC_EVT_CTL_EVENT_ID_FALSE));
intel_de_write(i915, htp_reg, 0);
intel_de_write(display, htp_reg, 0);
}
static void disable_all_event_handlers(struct drm_i915_private *i915)
static void disable_all_event_handlers(struct intel_display *display)
{
enum intel_dmc_id dmc_id;
/* TODO: disable the event handlers on pre-GEN12 platforms as well */
if (DISPLAY_VER(i915) < 12)
if (DISPLAY_VER(display) < 12)
return;
for_each_dmc_id(dmc_id) {
int handler;
if (!has_dmc_id_fw(i915, dmc_id))
if (!has_dmc_id_fw(display, dmc_id))
continue;
for (handler = 0; handler < DMC_EVENT_HANDLER_COUNT_GEN12; handler++)
disable_event_handler(i915,
DMC_EVT_CTL(i915, dmc_id, handler),
DMC_EVT_HTP(i915, dmc_id, handler));
disable_event_handler(display,
DMC_EVT_CTL(display, dmc_id, handler),
DMC_EVT_HTP(display, dmc_id, handler));
}
}
static void adlp_pipedmc_clock_gating_wa(struct drm_i915_private *i915, bool enable)
static void adlp_pipedmc_clock_gating_wa(struct intel_display *display, bool enable)
{
enum pipe pipe;
@ -451,84 +452,86 @@ static void adlp_pipedmc_clock_gating_wa(struct drm_i915_private *i915, bool ena
*/
if (enable)
for (pipe = PIPE_A; pipe <= PIPE_D; pipe++)
intel_de_rmw(i915, CLKGATE_DIS_PSL_EXT(pipe),
intel_de_rmw(display, CLKGATE_DIS_PSL_EXT(pipe),
0, PIPEDMC_GATING_DIS);
else
for (pipe = PIPE_C; pipe <= PIPE_D; pipe++)
intel_de_rmw(i915, CLKGATE_DIS_PSL_EXT(pipe),
intel_de_rmw(display, CLKGATE_DIS_PSL_EXT(pipe),
PIPEDMC_GATING_DIS, 0);
}
static void mtl_pipedmc_clock_gating_wa(struct drm_i915_private *i915)
static void mtl_pipedmc_clock_gating_wa(struct intel_display *display)
{
/*
* Wa_16015201720
* The WA requires clock gating to be disabled all the time
* for pipe A and B.
*/
intel_de_rmw(i915, GEN9_CLKGATE_DIS_0, 0,
intel_de_rmw(display, GEN9_CLKGATE_DIS_0, 0,
MTL_PIPEDMC_GATING_DIS_A | MTL_PIPEDMC_GATING_DIS_B);
}
static void pipedmc_clock_gating_wa(struct drm_i915_private *i915, bool enable)
static void pipedmc_clock_gating_wa(struct intel_display *display, bool enable)
{
if (DISPLAY_VER(i915) >= 14 && enable)
mtl_pipedmc_clock_gating_wa(i915);
else if (DISPLAY_VER(i915) == 13)
adlp_pipedmc_clock_gating_wa(i915, enable);
if (DISPLAY_VER(display) >= 14 && enable)
mtl_pipedmc_clock_gating_wa(display);
else if (DISPLAY_VER(display) == 13)
adlp_pipedmc_clock_gating_wa(display, enable);
}
void intel_dmc_enable_pipe(struct drm_i915_private *i915, enum pipe pipe)
void intel_dmc_enable_pipe(struct intel_display *display, enum pipe pipe)
{
enum intel_dmc_id dmc_id = PIPE_TO_DMC_ID(pipe);
if (!is_valid_dmc_id(dmc_id) || !has_dmc_id_fw(i915, dmc_id))
if (!is_valid_dmc_id(dmc_id) || !has_dmc_id_fw(display, dmc_id))
return;
if (DISPLAY_VER(i915) >= 14)
intel_de_rmw(i915, MTL_PIPEDMC_CONTROL, 0, PIPEDMC_ENABLE_MTL(pipe));
if (DISPLAY_VER(display) >= 14)
intel_de_rmw(display, MTL_PIPEDMC_CONTROL, 0, PIPEDMC_ENABLE_MTL(pipe));
else
intel_de_rmw(i915, PIPEDMC_CONTROL(pipe), 0, PIPEDMC_ENABLE);
intel_de_rmw(display, PIPEDMC_CONTROL(pipe), 0, PIPEDMC_ENABLE);
}
void intel_dmc_disable_pipe(struct drm_i915_private *i915, enum pipe pipe)
void intel_dmc_disable_pipe(struct intel_display *display, enum pipe pipe)
{
enum intel_dmc_id dmc_id = PIPE_TO_DMC_ID(pipe);
if (!is_valid_dmc_id(dmc_id) || !has_dmc_id_fw(i915, dmc_id))
if (!is_valid_dmc_id(dmc_id) || !has_dmc_id_fw(display, dmc_id))
return;
if (DISPLAY_VER(i915) >= 14)
intel_de_rmw(i915, MTL_PIPEDMC_CONTROL, PIPEDMC_ENABLE_MTL(pipe), 0);
if (DISPLAY_VER(display) >= 14)
intel_de_rmw(display, MTL_PIPEDMC_CONTROL, PIPEDMC_ENABLE_MTL(pipe), 0);
else
intel_de_rmw(i915, PIPEDMC_CONTROL(pipe), PIPEDMC_ENABLE, 0);
intel_de_rmw(display, PIPEDMC_CONTROL(pipe), PIPEDMC_ENABLE, 0);
}
static bool is_dmc_evt_ctl_reg(struct drm_i915_private *i915,
static bool is_dmc_evt_ctl_reg(struct intel_display *display,
enum intel_dmc_id dmc_id, i915_reg_t reg)
{
u32 offset = i915_mmio_reg_offset(reg);
u32 start = i915_mmio_reg_offset(DMC_EVT_CTL(i915, dmc_id, 0));
u32 end = i915_mmio_reg_offset(DMC_EVT_CTL(i915, dmc_id, DMC_EVENT_HANDLER_COUNT_GEN12));
u32 start = i915_mmio_reg_offset(DMC_EVT_CTL(display, dmc_id, 0));
u32 end = i915_mmio_reg_offset(DMC_EVT_CTL(display, dmc_id, DMC_EVENT_HANDLER_COUNT_GEN12));
return offset >= start && offset < end;
}
static bool is_dmc_evt_htp_reg(struct drm_i915_private *i915,
static bool is_dmc_evt_htp_reg(struct intel_display *display,
enum intel_dmc_id dmc_id, i915_reg_t reg)
{
u32 offset = i915_mmio_reg_offset(reg);
u32 start = i915_mmio_reg_offset(DMC_EVT_HTP(i915, dmc_id, 0));
u32 end = i915_mmio_reg_offset(DMC_EVT_HTP(i915, dmc_id, DMC_EVENT_HANDLER_COUNT_GEN12));
u32 start = i915_mmio_reg_offset(DMC_EVT_HTP(display, dmc_id, 0));
u32 end = i915_mmio_reg_offset(DMC_EVT_HTP(display, dmc_id, DMC_EVENT_HANDLER_COUNT_GEN12));
return offset >= start && offset < end;
}
static bool disable_dmc_evt(struct drm_i915_private *i915,
static bool disable_dmc_evt(struct intel_display *display,
enum intel_dmc_id dmc_id,
i915_reg_t reg, u32 data)
{
if (!is_dmc_evt_ctl_reg(i915, dmc_id, reg))
struct drm_i915_private *i915 = to_i915(display->drm);
if (!is_dmc_evt_ctl_reg(display, dmc_id, reg))
return false;
/* keep all pipe DMC events disabled by default */
@ -548,11 +551,11 @@ static bool disable_dmc_evt(struct drm_i915_private *i915,
return false;
}
static u32 dmc_mmiodata(struct drm_i915_private *i915,
static u32 dmc_mmiodata(struct intel_display *display,
struct intel_dmc *dmc,
enum intel_dmc_id dmc_id, int i)
{
if (disable_dmc_evt(i915, dmc_id,
if (disable_dmc_evt(display, dmc_id,
dmc->dmc_info[dmc_id].mmioaddr[i],
dmc->dmc_info[dmc_id].mmiodata[i]))
return REG_FIELD_PREP(DMC_EVT_CTL_TYPE_MASK,
@ -565,25 +568,26 @@ static u32 dmc_mmiodata(struct drm_i915_private *i915,
/**
* intel_dmc_load_program() - write the firmware from memory to register.
* @i915: i915 drm device.
* @display: display instance
*
* DMC firmware is read from a .bin file and kept in internal memory one time.
* Everytime display comes back from low power state this function is called to
* copy the firmware from internal memory to registers.
*/
void intel_dmc_load_program(struct drm_i915_private *i915)
void intel_dmc_load_program(struct intel_display *display)
{
struct i915_power_domains *power_domains = &i915->display.power.domains;
struct intel_dmc *dmc = i915_to_dmc(i915);
struct drm_i915_private *i915 __maybe_unused = to_i915(display->drm);
struct i915_power_domains *power_domains = &display->power.domains;
struct intel_dmc *dmc = display_to_dmc(display);
enum intel_dmc_id dmc_id;
u32 i;
if (!intel_dmc_has_payload(i915))
if (!intel_dmc_has_payload(display))
return;
pipedmc_clock_gating_wa(i915, true);
pipedmc_clock_gating_wa(display, true);
disable_all_event_handlers(i915);
disable_all_event_handlers(display);
assert_rpm_wakelock_held(&i915->runtime_pm);
@ -591,7 +595,7 @@ void intel_dmc_load_program(struct drm_i915_private *i915)
for_each_dmc_id(dmc_id) {
for (i = 0; i < dmc->dmc_info[dmc_id].dmc_fw_size; i++) {
intel_de_write_fw(i915,
intel_de_write_fw(display,
DMC_PROGRAM(dmc->dmc_info[dmc_id].start_mmioaddr, i),
dmc->dmc_info[dmc_id].payload[i]);
}
@ -601,48 +605,48 @@ void intel_dmc_load_program(struct drm_i915_private *i915)
for_each_dmc_id(dmc_id) {
for (i = 0; i < dmc->dmc_info[dmc_id].mmio_count; i++) {
intel_de_write(i915, dmc->dmc_info[dmc_id].mmioaddr[i],
dmc_mmiodata(i915, dmc, dmc_id, i));
intel_de_write(display, dmc->dmc_info[dmc_id].mmioaddr[i],
dmc_mmiodata(display, dmc, dmc_id, i));
}
}
power_domains->dc_state = 0;
gen9_set_dc_state_debugmask(i915);
gen9_set_dc_state_debugmask(display);
pipedmc_clock_gating_wa(i915, false);
pipedmc_clock_gating_wa(display, false);
}
/**
* intel_dmc_disable_program() - disable the firmware
* @i915: i915 drm device
* @display: display instance
*
* Disable all event handlers in the firmware, making sure the firmware is
* inactive after the display is uninitialized.
*/
void intel_dmc_disable_program(struct drm_i915_private *i915)
void intel_dmc_disable_program(struct intel_display *display)
{
if (!intel_dmc_has_payload(i915))
if (!intel_dmc_has_payload(display))
return;
pipedmc_clock_gating_wa(i915, true);
disable_all_event_handlers(i915);
pipedmc_clock_gating_wa(i915, false);
pipedmc_clock_gating_wa(display, true);
disable_all_event_handlers(display);
pipedmc_clock_gating_wa(display, false);
intel_dmc_wl_disable(&i915->display);
intel_dmc_wl_disable(display);
}
void assert_dmc_loaded(struct drm_i915_private *i915)
void assert_dmc_loaded(struct intel_display *display)
{
struct intel_dmc *dmc = i915_to_dmc(i915);
struct intel_dmc *dmc = display_to_dmc(display);
drm_WARN_ONCE(&i915->drm, !dmc, "DMC not initialized\n");
drm_WARN_ONCE(&i915->drm, dmc &&
!intel_de_read(i915, DMC_PROGRAM(dmc->dmc_info[DMC_FW_MAIN].start_mmioaddr, 0)),
drm_WARN_ONCE(display->drm, !dmc, "DMC not initialized\n");
drm_WARN_ONCE(display->drm, dmc &&
!intel_de_read(display, DMC_PROGRAM(dmc->dmc_info[DMC_FW_MAIN].start_mmioaddr, 0)),
"DMC program storage start is NULL\n");
drm_WARN_ONCE(&i915->drm, !intel_de_read(i915, DMC_SSP_BASE),
drm_WARN_ONCE(display->drm, !intel_de_read(display, DMC_SSP_BASE),
"DMC SSP Base Not fine\n");
drm_WARN_ONCE(&i915->drm, !intel_de_read(i915, DMC_HTP_SKL),
drm_WARN_ONCE(display->drm, !intel_de_read(display, DMC_HTP_SKL),
"DMC HTP Not fine\n");
}
@ -673,7 +677,7 @@ static void dmc_set_fw_offset(struct intel_dmc *dmc,
const struct stepping_info *si,
u8 package_ver)
{
struct drm_i915_private *i915 = dmc->i915;
struct intel_display *display = dmc->display;
enum intel_dmc_id dmc_id;
unsigned int i;
@ -681,7 +685,7 @@ static void dmc_set_fw_offset(struct intel_dmc *dmc,
dmc_id = package_ver <= 1 ? DMC_FW_MAIN : fw_info[i].dmc_id;
if (!is_valid_dmc_id(dmc_id)) {
drm_dbg(&i915->drm, "Unsupported firmware id: %u\n", dmc_id);
drm_dbg(display->drm, "Unsupported firmware id: %u\n", dmc_id);
continue;
}
@ -703,7 +707,7 @@ static bool dmc_mmio_addr_sanity_check(struct intel_dmc *dmc,
const u32 *mmioaddr, u32 mmio_count,
int header_ver, enum intel_dmc_id dmc_id)
{
struct drm_i915_private *i915 = dmc->i915;
struct intel_display *display = dmc->display;
u32 start_range, end_range;
int i;
@ -713,14 +717,14 @@ static bool dmc_mmio_addr_sanity_check(struct intel_dmc *dmc,
} else if (dmc_id == DMC_FW_MAIN) {
start_range = TGL_MAIN_MMIO_START;
end_range = TGL_MAIN_MMIO_END;
} else if (DISPLAY_VER(i915) >= 13) {
} else if (DISPLAY_VER(display) >= 13) {
start_range = ADLP_PIPE_MMIO_START;
end_range = ADLP_PIPE_MMIO_END;
} else if (DISPLAY_VER(i915) >= 12) {
} else if (DISPLAY_VER(display) >= 12) {
start_range = TGL_PIPE_MMIO_START(dmc_id);
end_range = TGL_PIPE_MMIO_END(dmc_id);
} else {
drm_warn(&i915->drm, "Unknown mmio range for sanity check");
drm_warn(display->drm, "Unknown mmio range for sanity check");
return false;
}
@ -736,7 +740,7 @@ static u32 parse_dmc_fw_header(struct intel_dmc *dmc,
const struct intel_dmc_header_base *dmc_header,
size_t rem_size, enum intel_dmc_id dmc_id)
{
struct drm_i915_private *i915 = dmc->i915;
struct intel_display *display = dmc->display;
struct dmc_fw_info *dmc_info = &dmc->dmc_info[dmc_id];
unsigned int header_len_bytes, dmc_header_size, payload_size, i;
const u32 *mmioaddr, *mmiodata;
@ -784,39 +788,39 @@ static u32 parse_dmc_fw_header(struct intel_dmc *dmc,
start_mmioaddr = DMC_V1_MMIO_START_RANGE;
dmc_header_size = sizeof(*v1);
} else {
drm_err(&i915->drm, "Unknown DMC fw header version: %u\n",
drm_err(display->drm, "Unknown DMC fw header version: %u\n",
dmc_header->header_ver);
return 0;
}
if (header_len_bytes != dmc_header_size) {
drm_err(&i915->drm, "DMC firmware has wrong dmc header length "
drm_err(display->drm, "DMC firmware has wrong dmc header length "
"(%u bytes)\n", header_len_bytes);
return 0;
}
/* Cache the dmc header info. */
if (mmio_count > mmio_count_max) {
drm_err(&i915->drm, "DMC firmware has wrong mmio count %u\n", mmio_count);
drm_err(display->drm, "DMC firmware has wrong mmio count %u\n", mmio_count);
return 0;
}
if (!dmc_mmio_addr_sanity_check(dmc, mmioaddr, mmio_count,
dmc_header->header_ver, dmc_id)) {
drm_err(&i915->drm, "DMC firmware has Wrong MMIO Addresses\n");
drm_err(display->drm, "DMC firmware has Wrong MMIO Addresses\n");
return 0;
}
drm_dbg_kms(&i915->drm, "DMC %d:\n", dmc_id);
drm_dbg_kms(display->drm, "DMC %d:\n", dmc_id);
for (i = 0; i < mmio_count; i++) {
dmc_info->mmioaddr[i] = _MMIO(mmioaddr[i]);
dmc_info->mmiodata[i] = mmiodata[i];
drm_dbg_kms(&i915->drm, " mmio[%d]: 0x%x = 0x%x%s%s\n",
drm_dbg_kms(display->drm, " mmio[%d]: 0x%x = 0x%x%s%s\n",
i, mmioaddr[i], mmiodata[i],
is_dmc_evt_ctl_reg(i915, dmc_id, dmc_info->mmioaddr[i]) ? " (EVT_CTL)" :
is_dmc_evt_htp_reg(i915, dmc_id, dmc_info->mmioaddr[i]) ? " (EVT_HTP)" : "",
disable_dmc_evt(i915, dmc_id, dmc_info->mmioaddr[i],
is_dmc_evt_ctl_reg(display, dmc_id, dmc_info->mmioaddr[i]) ? " (EVT_CTL)" :
is_dmc_evt_htp_reg(display, dmc_id, dmc_info->mmioaddr[i]) ? " (EVT_HTP)" : "",
disable_dmc_evt(display, dmc_id, dmc_info->mmioaddr[i],
dmc_info->mmiodata[i]) ? " (disabling)" : "");
}
dmc_info->mmio_count = mmio_count;
@ -830,7 +834,7 @@ static u32 parse_dmc_fw_header(struct intel_dmc *dmc,
goto error_truncated;
if (payload_size > dmc->max_fw_size) {
drm_err(&i915->drm, "DMC FW too big (%u bytes)\n", payload_size);
drm_err(display->drm, "DMC FW too big (%u bytes)\n", payload_size);
return 0;
}
dmc_info->dmc_fw_size = dmc_header->fw_size;
@ -845,7 +849,7 @@ static u32 parse_dmc_fw_header(struct intel_dmc *dmc,
return header_len_bytes + payload_size;
error_truncated:
drm_err(&i915->drm, "Truncated DMC firmware, refusing.\n");
drm_err(display->drm, "Truncated DMC firmware, refusing.\n");
return 0;
}
@ -855,7 +859,7 @@ parse_dmc_fw_package(struct intel_dmc *dmc,
const struct stepping_info *si,
size_t rem_size)
{
struct drm_i915_private *i915 = dmc->i915;
struct intel_display *display = dmc->display;
u32 package_size = sizeof(struct intel_package_header);
u32 num_entries, max_entries;
const struct intel_fw_info *fw_info;
@ -868,7 +872,7 @@ parse_dmc_fw_package(struct intel_dmc *dmc,
} else if (package_header->header_ver == 2) {
max_entries = PACKAGE_V2_MAX_FW_INFO_ENTRIES;
} else {
drm_err(&i915->drm, "DMC firmware has unknown header version %u\n",
drm_err(display->drm, "DMC firmware has unknown header version %u\n",
package_header->header_ver);
return 0;
}
@ -882,7 +886,7 @@ parse_dmc_fw_package(struct intel_dmc *dmc,
goto error_truncated;
if (package_header->header_len * 4 != package_size) {
drm_err(&i915->drm, "DMC firmware has wrong package header length "
drm_err(display->drm, "DMC firmware has wrong package header length "
"(%u bytes)\n", package_size);
return 0;
}
@ -900,7 +904,7 @@ parse_dmc_fw_package(struct intel_dmc *dmc,
return package_size;
error_truncated:
drm_err(&i915->drm, "Truncated DMC firmware, refusing.\n");
drm_err(display->drm, "Truncated DMC firmware, refusing.\n");
return 0;
}
@ -909,16 +913,16 @@ static u32 parse_dmc_fw_css(struct intel_dmc *dmc,
struct intel_css_header *css_header,
size_t rem_size)
{
struct drm_i915_private *i915 = dmc->i915;
struct intel_display *display = dmc->display;
if (rem_size < sizeof(struct intel_css_header)) {
drm_err(&i915->drm, "Truncated DMC firmware, refusing.\n");
drm_err(display->drm, "Truncated DMC firmware, refusing.\n");
return 0;
}
if (sizeof(struct intel_css_header) !=
(css_header->header_len * 4)) {
drm_err(&i915->drm, "DMC firmware has wrong CSS header length "
drm_err(display->drm, "DMC firmware has wrong CSS header length "
"(%u bytes)\n",
(css_header->header_len * 4));
return 0;
@ -931,12 +935,12 @@ static u32 parse_dmc_fw_css(struct intel_dmc *dmc,
static int parse_dmc_fw(struct intel_dmc *dmc, const struct firmware *fw)
{
struct drm_i915_private *i915 = dmc->i915;
struct intel_display *display = dmc->display;
struct intel_css_header *css_header;
struct intel_package_header *package_header;
struct intel_dmc_header_base *dmc_header;
struct stepping_info display_info = { '*', '*'};
const struct stepping_info *si = intel_get_stepping_info(i915, &display_info);
const struct stepping_info *si = intel_get_stepping_info(display, &display_info);
enum intel_dmc_id dmc_id;
u32 readcount = 0;
u32 r, offset;
@ -966,7 +970,7 @@ static int parse_dmc_fw(struct intel_dmc *dmc, const struct firmware *fw)
offset = readcount + dmc->dmc_info[dmc_id].dmc_offset * 4;
if (offset > fw->size) {
drm_err(&i915->drm, "Reading beyond the fw_size\n");
drm_err(display->drm, "Reading beyond the fw_size\n");
continue;
}
@ -974,30 +978,35 @@ static int parse_dmc_fw(struct intel_dmc *dmc, const struct firmware *fw)
parse_dmc_fw_header(dmc, dmc_header, fw->size - offset, dmc_id);
}
if (!intel_dmc_has_payload(i915)) {
drm_err(&i915->drm, "DMC firmware main program not found\n");
if (!intel_dmc_has_payload(display)) {
drm_err(display->drm, "DMC firmware main program not found\n");
return -ENOENT;
}
return 0;
}
static void intel_dmc_runtime_pm_get(struct drm_i915_private *i915)
static void intel_dmc_runtime_pm_get(struct intel_display *display)
{
drm_WARN_ON(&i915->drm, i915->display.dmc.wakeref);
i915->display.dmc.wakeref = intel_display_power_get(i915, POWER_DOMAIN_INIT);
struct drm_i915_private *i915 = to_i915(display->drm);
drm_WARN_ON(display->drm, display->dmc.wakeref);
display->dmc.wakeref = intel_display_power_get(i915, POWER_DOMAIN_INIT);
}
static void intel_dmc_runtime_pm_put(struct drm_i915_private *i915)
static void intel_dmc_runtime_pm_put(struct intel_display *display)
{
struct drm_i915_private *i915 = to_i915(display->drm);
intel_wakeref_t wakeref __maybe_unused =
fetch_and_zero(&i915->display.dmc.wakeref);
fetch_and_zero(&display->dmc.wakeref);
intel_display_power_put(i915, POWER_DOMAIN_INIT, wakeref);
}
static const char *dmc_fallback_path(struct drm_i915_private *i915)
static const char *dmc_fallback_path(struct intel_display *display)
{
struct drm_i915_private *i915 = to_i915(display->drm);
if (IS_ALDERLAKE_P(i915))
return ADLP_DMC_FALLBACK_PATH;
@ -1007,45 +1016,45 @@ static const char *dmc_fallback_path(struct drm_i915_private *i915)
static void dmc_load_work_fn(struct work_struct *work)
{
struct intel_dmc *dmc = container_of(work, typeof(*dmc), work);
struct drm_i915_private *i915 = dmc->i915;
struct intel_display *display = dmc->display;
const struct firmware *fw = NULL;
const char *fallback_path;
int err;
err = request_firmware(&fw, dmc->fw_path, i915->drm.dev);
err = request_firmware(&fw, dmc->fw_path, display->drm->dev);
if (err == -ENOENT && !dmc_firmware_param(i915)) {
fallback_path = dmc_fallback_path(i915);
if (err == -ENOENT && !dmc_firmware_param(display)) {
fallback_path = dmc_fallback_path(display);
if (fallback_path) {
drm_dbg_kms(&i915->drm, "%s not found, falling back to %s\n",
drm_dbg_kms(display->drm, "%s not found, falling back to %s\n",
dmc->fw_path, fallback_path);
err = request_firmware(&fw, fallback_path, i915->drm.dev);
err = request_firmware(&fw, fallback_path, display->drm->dev);
if (err == 0)
dmc->fw_path = fallback_path;
}
}
if (err) {
drm_notice(&i915->drm,
drm_notice(display->drm,
"Failed to load DMC firmware %s (%pe). Disabling runtime power management.\n",
dmc->fw_path, ERR_PTR(err));
drm_notice(&i915->drm, "DMC firmware homepage: %s",
drm_notice(display->drm, "DMC firmware homepage: %s",
INTEL_DMC_FIRMWARE_URL);
return;
}
err = parse_dmc_fw(dmc, fw);
if (err) {
drm_notice(&i915->drm,
drm_notice(display->drm,
"Failed to parse DMC firmware %s (%pe). Disabling runtime power management.\n",
dmc->fw_path, ERR_PTR(err));
goto out;
}
intel_dmc_load_program(i915);
intel_dmc_runtime_pm_put(i915);
intel_dmc_load_program(display);
intel_dmc_runtime_pm_put(display);
drm_info(&i915->drm, "Finished loading DMC firmware %s (v%u.%u)\n",
drm_info(display->drm, "Finished loading DMC firmware %s (v%u.%u)\n",
dmc->fw_path, DMC_VERSION_MAJOR(dmc->version),
DMC_VERSION_MINOR(dmc->version));
@ -1055,16 +1064,17 @@ static void dmc_load_work_fn(struct work_struct *work)
/**
* intel_dmc_init() - initialize the firmware loading.
* @i915: i915 drm device.
* @display: display instance
*
* This function is called at the time of loading the display driver to read
* firmware from a .bin file and copied into a internal memory.
*/
void intel_dmc_init(struct drm_i915_private *i915)
void intel_dmc_init(struct intel_display *display)
{
struct drm_i915_private *i915 = to_i915(display->drm);
struct intel_dmc *dmc;
if (!HAS_DMC(i915))
if (!HAS_DMC(display))
return;
/*
@ -1075,35 +1085,35 @@ void intel_dmc_init(struct drm_i915_private *i915)
* suspend as runtime suspend *requires* a working DMC for whatever
* reason.
*/
intel_dmc_runtime_pm_get(i915);
intel_dmc_runtime_pm_get(display);
dmc = kzalloc(sizeof(*dmc), GFP_KERNEL);
if (!dmc)
return;
dmc->i915 = i915;
dmc->display = display;
INIT_WORK(&dmc->work, dmc_load_work_fn);
dmc->fw_path = dmc_firmware_default(i915, &dmc->max_fw_size);
dmc->fw_path = dmc_firmware_default(display, &dmc->max_fw_size);
if (dmc_firmware_param_disabled(i915)) {
drm_info(&i915->drm, "Disabling DMC firmware and runtime PM\n");
if (dmc_firmware_param_disabled(display)) {
drm_info(display->drm, "Disabling DMC firmware and runtime PM\n");
goto out;
}
if (dmc_firmware_param(i915))
dmc->fw_path = dmc_firmware_param(i915);
if (dmc_firmware_param(display))
dmc->fw_path = dmc_firmware_param(display);
if (!dmc->fw_path) {
drm_dbg_kms(&i915->drm,
drm_dbg_kms(display->drm,
"No known DMC firmware for platform, disabling runtime PM\n");
goto out;
}
i915->display.dmc.dmc = dmc;
display->dmc.dmc = dmc;
drm_dbg_kms(&i915->drm, "Loading %s\n", dmc->fw_path);
drm_dbg_kms(display->drm, "Loading %s\n", dmc->fw_path);
queue_work(i915->unordered_wq, &dmc->work);
return;
@ -1114,129 +1124,152 @@ void intel_dmc_init(struct drm_i915_private *i915)
/**
* intel_dmc_suspend() - prepare DMC firmware before system suspend
* @i915: i915 drm device
* @display: display instance
*
* Prepare the DMC firmware before entering system suspend. This includes
* flushing pending work items and releasing any resources acquired during
* init.
*/
void intel_dmc_suspend(struct drm_i915_private *i915)
void intel_dmc_suspend(struct intel_display *display)
{
struct intel_dmc *dmc = i915_to_dmc(i915);
struct intel_dmc *dmc = display_to_dmc(display);
if (!HAS_DMC(i915))
if (!HAS_DMC(display))
return;
if (dmc)
flush_work(&dmc->work);
intel_dmc_wl_disable(&i915->display);
intel_dmc_wl_disable(display);
/* Drop the reference held in case DMC isn't loaded. */
if (!intel_dmc_has_payload(i915))
intel_dmc_runtime_pm_put(i915);
if (!intel_dmc_has_payload(display))
intel_dmc_runtime_pm_put(display);
}
/**
* intel_dmc_resume() - init DMC firmware during system resume
* @i915: i915 drm device
* @display: display instance
*
* Reinitialize the DMC firmware during system resume, reacquiring any
* resources released in intel_dmc_suspend().
*/
void intel_dmc_resume(struct drm_i915_private *i915)
void intel_dmc_resume(struct intel_display *display)
{
if (!HAS_DMC(i915))
if (!HAS_DMC(display))
return;
/*
* Reacquire the reference to keep RPM disabled in case DMC isn't
* loaded.
*/
if (!intel_dmc_has_payload(i915))
intel_dmc_runtime_pm_get(i915);
if (!intel_dmc_has_payload(display))
intel_dmc_runtime_pm_get(display);
}
/**
* intel_dmc_fini() - unload the DMC firmware.
* @i915: i915 drm device.
* @display: display instance
*
* Firmmware unloading includes freeing the internal memory and reset the
* firmware loading status.
*/
void intel_dmc_fini(struct drm_i915_private *i915)
void intel_dmc_fini(struct intel_display *display)
{
struct intel_dmc *dmc = i915_to_dmc(i915);
struct intel_dmc *dmc = display_to_dmc(display);
enum intel_dmc_id dmc_id;
if (!HAS_DMC(i915))
if (!HAS_DMC(display))
return;
intel_dmc_suspend(i915);
drm_WARN_ON(&i915->drm, i915->display.dmc.wakeref);
intel_dmc_suspend(display);
drm_WARN_ON(display->drm, display->dmc.wakeref);
if (dmc) {
for_each_dmc_id(dmc_id)
kfree(dmc->dmc_info[dmc_id].payload);
kfree(dmc);
i915->display.dmc.dmc = NULL;
display->dmc.dmc = NULL;
}
}
void intel_dmc_print_error_state(struct drm_printer *p,
struct drm_i915_private *i915)
{
struct intel_dmc *dmc = i915_to_dmc(i915);
struct intel_dmc_snapshot {
bool initialized;
bool loaded;
u32 version;
};
if (!HAS_DMC(i915))
struct intel_dmc_snapshot *intel_dmc_snapshot_capture(struct intel_display *display)
{
struct intel_dmc *dmc = display_to_dmc(display);
struct intel_dmc_snapshot *snapshot;
if (!HAS_DMC(display))
return NULL;
snapshot = kzalloc(sizeof(*snapshot), GFP_ATOMIC);
if (!snapshot)
return NULL;
snapshot->initialized = dmc;
snapshot->loaded = intel_dmc_has_payload(display);
if (dmc)
snapshot->version = dmc->version;
return snapshot;
}
void intel_dmc_snapshot_print(const struct intel_dmc_snapshot *snapshot, struct drm_printer *p)
{
if (!snapshot)
return;
drm_printf(p, "DMC initialized: %s\n", str_yes_no(dmc));
drm_printf(p, "DMC loaded: %s\n",
str_yes_no(intel_dmc_has_payload(i915)));
if (dmc)
drm_printf(p, "DMC initialized: %s\n", str_yes_no(snapshot->initialized));
drm_printf(p, "DMC loaded: %s\n", str_yes_no(snapshot->loaded));
if (snapshot->initialized)
drm_printf(p, "DMC fw version: %d.%d\n",
DMC_VERSION_MAJOR(dmc->version),
DMC_VERSION_MINOR(dmc->version));
DMC_VERSION_MAJOR(snapshot->version),
DMC_VERSION_MINOR(snapshot->version));
}
static int intel_dmc_debugfs_status_show(struct seq_file *m, void *unused)
{
struct drm_i915_private *i915 = m->private;
struct intel_dmc *dmc = i915_to_dmc(i915);
struct intel_display *display = m->private;
struct drm_i915_private *i915 = to_i915(display->drm);
struct intel_dmc *dmc = display_to_dmc(display);
intel_wakeref_t wakeref;
i915_reg_t dc5_reg, dc6_reg = INVALID_MMIO_REG;
if (!HAS_DMC(i915))
if (!HAS_DMC(display))
return -ENODEV;
wakeref = intel_runtime_pm_get(&i915->runtime_pm);
seq_printf(m, "DMC initialized: %s\n", str_yes_no(dmc));
seq_printf(m, "fw loaded: %s\n",
str_yes_no(intel_dmc_has_payload(i915)));
str_yes_no(intel_dmc_has_payload(display)));
seq_printf(m, "path: %s\n", dmc ? dmc->fw_path : "N/A");
seq_printf(m, "Pipe A fw needed: %s\n",
str_yes_no(DISPLAY_VER(i915) >= 12));
str_yes_no(DISPLAY_VER(display) >= 12));
seq_printf(m, "Pipe A fw loaded: %s\n",
str_yes_no(has_dmc_id_fw(i915, DMC_FW_PIPEA)));
str_yes_no(has_dmc_id_fw(display, DMC_FW_PIPEA)));
seq_printf(m, "Pipe B fw needed: %s\n",
str_yes_no(IS_ALDERLAKE_P(i915) ||
DISPLAY_VER(i915) >= 14));
DISPLAY_VER(display) >= 14));
seq_printf(m, "Pipe B fw loaded: %s\n",
str_yes_no(has_dmc_id_fw(i915, DMC_FW_PIPEB)));
str_yes_no(has_dmc_id_fw(display, DMC_FW_PIPEB)));
if (!intel_dmc_has_payload(i915))
if (!intel_dmc_has_payload(display))
goto out;
seq_printf(m, "version: %d.%d\n", DMC_VERSION_MAJOR(dmc->version),
DMC_VERSION_MINOR(dmc->version));
if (DISPLAY_VER(i915) >= 12) {
if (DISPLAY_VER(display) >= 12) {
i915_reg_t dc3co_reg;
if (IS_DGFX(i915) || DISPLAY_VER(i915) >= 14) {
if (IS_DGFX(i915) || DISPLAY_VER(display) >= 14) {
dc3co_reg = DG1_DMC_DEBUG3;
dc5_reg = DG1_DMC_DEBUG_DC5_COUNT;
} else {
@ -1246,7 +1279,7 @@ static int intel_dmc_debugfs_status_show(struct seq_file *m, void *unused)
}
seq_printf(m, "DC3CO count: %d\n",
intel_de_read(i915, dc3co_reg));
intel_de_read(display, dc3co_reg));
} else {
dc5_reg = IS_BROXTON(i915) ? BXT_DMC_DC3_DC5_COUNT :
SKL_DMC_DC3_DC5_COUNT;
@ -1254,18 +1287,18 @@ static int intel_dmc_debugfs_status_show(struct seq_file *m, void *unused)
dc6_reg = SKL_DMC_DC5_DC6_COUNT;
}
seq_printf(m, "DC3 -> DC5 count: %d\n", intel_de_read(i915, dc5_reg));
seq_printf(m, "DC3 -> DC5 count: %d\n", intel_de_read(display, dc5_reg));
if (i915_mmio_reg_valid(dc6_reg))
seq_printf(m, "DC5 -> DC6 count: %d\n",
intel_de_read(i915, dc6_reg));
intel_de_read(display, dc6_reg));
seq_printf(m, "program base: 0x%08x\n",
intel_de_read(i915, DMC_PROGRAM(dmc->dmc_info[DMC_FW_MAIN].start_mmioaddr, 0)));
intel_de_read(display, DMC_PROGRAM(dmc->dmc_info[DMC_FW_MAIN].start_mmioaddr, 0)));
out:
seq_printf(m, "ssp base: 0x%08x\n",
intel_de_read(i915, DMC_SSP_BASE));
seq_printf(m, "htp: 0x%08x\n", intel_de_read(i915, DMC_HTP_SKL));
intel_de_read(display, DMC_SSP_BASE));
seq_printf(m, "htp: 0x%08x\n", intel_de_read(display, DMC_HTP_SKL));
intel_runtime_pm_put(&i915->runtime_pm, wakeref);
@ -1274,10 +1307,10 @@ static int intel_dmc_debugfs_status_show(struct seq_file *m, void *unused)
DEFINE_SHOW_ATTRIBUTE(intel_dmc_debugfs_status);
void intel_dmc_debugfs_register(struct drm_i915_private *i915)
void intel_dmc_debugfs_register(struct intel_display *display)
{
struct drm_minor *minor = i915->drm.primary;
struct drm_minor *minor = display->drm->primary;
debugfs_create_file("i915_dmc_info", 0444, minor->debugfs_root,
i915, &intel_dmc_debugfs_status_fops);
display, &intel_dmc_debugfs_status_fops);
}

View File

@ -9,22 +9,24 @@
#include <linux/types.h>
enum pipe;
struct drm_i915_private;
struct drm_printer;
struct intel_display;
struct intel_dmc_snapshot;
void intel_dmc_init(struct drm_i915_private *i915);
void intel_dmc_load_program(struct drm_i915_private *i915);
void intel_dmc_disable_program(struct drm_i915_private *i915);
void intel_dmc_enable_pipe(struct drm_i915_private *i915, enum pipe pipe);
void intel_dmc_disable_pipe(struct drm_i915_private *i915, enum pipe pipe);
void intel_dmc_fini(struct drm_i915_private *i915);
void intel_dmc_suspend(struct drm_i915_private *i915);
void intel_dmc_resume(struct drm_i915_private *i915);
bool intel_dmc_has_payload(struct drm_i915_private *i915);
void intel_dmc_debugfs_register(struct drm_i915_private *i915);
void intel_dmc_print_error_state(struct drm_printer *p,
struct drm_i915_private *i915);
void intel_dmc_init(struct intel_display *display);
void intel_dmc_load_program(struct intel_display *display);
void intel_dmc_disable_program(struct intel_display *display);
void intel_dmc_enable_pipe(struct intel_display *display, enum pipe pipe);
void intel_dmc_disable_pipe(struct intel_display *display, enum pipe pipe);
void intel_dmc_fini(struct intel_display *display);
void intel_dmc_suspend(struct intel_display *display);
void intel_dmc_resume(struct intel_display *display);
bool intel_dmc_has_payload(struct intel_display *display);
void intel_dmc_debugfs_register(struct intel_display *display);
void assert_dmc_loaded(struct drm_i915_private *i915);
struct intel_dmc_snapshot *intel_dmc_snapshot_capture(struct intel_display *display);
void intel_dmc_snapshot_print(const struct intel_dmc_snapshot *snapshot, struct drm_printer *p);
void assert_dmc_loaded(struct intel_display *display);
#endif /* __INTEL_DMC_H__ */

View File

@ -109,10 +109,8 @@ static bool intel_dmc_wl_check_range(u32 address)
static bool __intel_dmc_wl_supported(struct intel_display *display)
{
struct drm_i915_private *i915 = to_i915(display->drm);
if (DISPLAY_VER(display) < 20 ||
!intel_dmc_has_payload(i915) ||
!intel_dmc_has_payload(display) ||
!display->params.enable_dmc_wl)
return false;

File diff suppressed because it is too large Load Diff

View File

@ -37,9 +37,6 @@ struct link_config_limits {
};
void intel_edp_fixup_vbt_bpp(struct intel_encoder *encoder, int pipe_bpp);
void intel_dp_adjust_compliance_config(struct intel_dp *intel_dp,
struct intel_crtc_state *pipe_config,
struct link_config_limits *limits);
bool intel_dp_limited_color_range(const struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state);
int intel_dp_min_bpp(enum intel_output_format output_format);
@ -117,13 +114,13 @@ void intel_dp_compute_rate(struct intel_dp *intel_dp, int port_clock,
bool intel_dp_source_supports_tps3(struct drm_i915_private *i915);
bool intel_dp_source_supports_tps4(struct drm_i915_private *i915);
bool intel_dp_get_colorimetry_status(struct intel_dp *intel_dp);
int intel_dp_link_required(int pixel_clock, int bpp);
int intel_dp_effective_data_rate(int pixel_clock, int bpp_x16,
int bw_overhead);
int intel_dp_max_link_data_rate(struct intel_dp *intel_dp,
int max_dprx_rate, int max_dprx_lanes);
bool intel_dp_joiner_needs_dsc(struct drm_i915_private *i915, bool use_joiner);
bool intel_dp_joiner_needs_dsc(struct drm_i915_private *i915,
int num_joined_pipes);
bool intel_dp_has_joiner(struct intel_dp *intel_dp);
bool intel_dp_needs_vsc_sdp(const struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state);
@ -142,7 +139,7 @@ int intel_dp_dsc_compute_max_bpp(const struct intel_connector *connector,
u16 intel_dp_dsc_get_max_compressed_bpp(struct drm_i915_private *i915,
u32 link_clock, u32 lane_count,
u32 mode_clock, u32 mode_hdisplay,
bool bigjoiner,
int num_joined_pipes,
enum intel_output_format output_format,
u32 pipe_bpp,
u32 timeslots);
@ -152,10 +149,10 @@ int intel_dp_dsc_sink_max_compressed_bpp(const struct intel_connector *connector
int bpc);
u8 intel_dp_dsc_get_slice_count(const struct intel_connector *connector,
int mode_clock, int mode_hdisplay,
bool bigjoiner);
bool intel_dp_need_joiner(struct intel_dp *intel_dp,
struct intel_connector *connector,
int hdisplay, int clock);
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)
{
@ -190,7 +187,6 @@ void intel_dp_sync_state(struct intel_encoder *encoder,
void intel_dp_check_frl_training(struct intel_dp *intel_dp);
void intel_dp_pcon_dsc_configure(struct intel_dp *intel_dp,
const struct intel_crtc_state *crtc_state);
void intel_dp_phy_test(struct intel_encoder *encoder);
void intel_dp_wait_source_oui(struct intel_dp *intel_dp);
int intel_dp_output_bpp(enum intel_output_format output_format, int bpp);
@ -204,4 +200,9 @@ intel_dp_compute_config_link_bpp_limits(struct intel_dp *intel_dp,
void intel_dp_get_dsc_sink_cap(u8 dpcd_rev, struct intel_connector *connector);
bool intel_dp_has_gamut_metadata_dip(struct intel_encoder *encoder);
bool intel_dp_link_params_valid(struct intel_dp *intel_dp, int link_rate,
u8 lane_count);
bool intel_dp_has_connector(struct intel_dp *intel_dp,
const struct drm_connector_state *conn_state);
#endif /* __INTEL_DP_H__ */

View File

@ -19,6 +19,7 @@
#include "intel_dp_hdcp.h"
#include "intel_hdcp.h"
#include "intel_hdcp_regs.h"
#include "intel_hdcp_shim.h"
static u32 transcoder_to_stream_enc_status(enum transcoder cpu_transcoder)
{

View File

@ -21,6 +21,8 @@
* IN THE SOFTWARE.
*/
#include <linux/debugfs.h>
#include <drm/display/drm_dp_helper.h>
#include "i915_drv.h"
@ -208,8 +210,10 @@ static int intel_dp_init_lttpr(struct intel_dp *intel_dp, const u8 dpcd[DP_RECEI
lttpr_count = intel_dp_init_lttpr_phys(intel_dp, dpcd);
for (i = 0; i < lttpr_count; i++)
for (i = 0; i < lttpr_count; i++) {
intel_dp_read_lttpr_phy_caps(intel_dp, dpcd, DP_PHY_LTTPR(i));
drm_dp_dump_lttpr_desc(&intel_dp->aux, DP_PHY_LTTPR(i));
}
return lttpr_count;
}
@ -1677,19 +1681,11 @@ void intel_dp_128b132b_sdp_crc16(struct intel_dp *intel_dp,
lt_dbg(intel_dp, DP_PHY_DPRX, "DP2.0 SDP CRC16 for 128b/132b enabled\n");
}
static struct intel_dp *intel_connector_to_intel_dp(struct intel_connector *connector)
{
if (connector->mst_port)
return connector->mst_port;
else
return enc_to_intel_dp(intel_attached_encoder(connector));
}
static int i915_dp_force_link_rate_show(struct seq_file *m, void *data)
{
struct intel_connector *connector = to_intel_connector(m->private);
struct intel_display *display = to_intel_display(connector);
struct intel_dp *intel_dp = intel_connector_to_intel_dp(connector);
struct intel_dp *intel_dp = intel_attached_dp(connector);
int current_rate = -1;
int force_rate;
int err;
@ -1760,7 +1756,7 @@ static ssize_t i915_dp_force_link_rate_write(struct file *file,
struct seq_file *m = file->private_data;
struct intel_connector *connector = to_intel_connector(m->private);
struct intel_display *display = to_intel_display(connector);
struct intel_dp *intel_dp = intel_connector_to_intel_dp(connector);
struct intel_dp *intel_dp = intel_attached_dp(connector);
int rate;
int err;
@ -1787,7 +1783,7 @@ static int i915_dp_force_lane_count_show(struct seq_file *m, void *data)
{
struct intel_connector *connector = to_intel_connector(m->private);
struct intel_display *display = to_intel_display(connector);
struct intel_dp *intel_dp = intel_connector_to_intel_dp(connector);
struct intel_dp *intel_dp = intel_attached_dp(connector);
int current_lane_count = -1;
int force_lane_count;
int err;
@ -1862,7 +1858,7 @@ static ssize_t i915_dp_force_lane_count_write(struct file *file,
struct seq_file *m = file->private_data;
struct intel_connector *connector = to_intel_connector(m->private);
struct intel_display *display = to_intel_display(connector);
struct intel_dp *intel_dp = intel_connector_to_intel_dp(connector);
struct intel_dp *intel_dp = intel_attached_dp(connector);
int lane_count;
int err;
@ -1889,7 +1885,7 @@ static int i915_dp_max_link_rate_show(void *data, u64 *val)
{
struct intel_connector *connector = to_intel_connector(data);
struct intel_display *display = to_intel_display(connector);
struct intel_dp *intel_dp = intel_connector_to_intel_dp(connector);
struct intel_dp *intel_dp = intel_attached_dp(connector);
int err;
err = drm_modeset_lock_single_interruptible(&display->drm->mode_config.connection_mutex);
@ -1908,7 +1904,7 @@ static int i915_dp_max_lane_count_show(void *data, u64 *val)
{
struct intel_connector *connector = to_intel_connector(data);
struct intel_display *display = to_intel_display(connector);
struct intel_dp *intel_dp = intel_connector_to_intel_dp(connector);
struct intel_dp *intel_dp = intel_attached_dp(connector);
int err;
err = drm_modeset_lock_single_interruptible(&display->drm->mode_config.connection_mutex);
@ -1927,7 +1923,7 @@ static int i915_dp_force_link_training_failure_show(void *data, u64 *val)
{
struct intel_connector *connector = to_intel_connector(data);
struct intel_display *display = to_intel_display(connector);
struct intel_dp *intel_dp = intel_connector_to_intel_dp(connector);
struct intel_dp *intel_dp = intel_attached_dp(connector);
int err;
err = drm_modeset_lock_single_interruptible(&display->drm->mode_config.connection_mutex);
@ -1945,7 +1941,7 @@ static int i915_dp_force_link_training_failure_write(void *data, u64 val)
{
struct intel_connector *connector = to_intel_connector(data);
struct intel_display *display = to_intel_display(connector);
struct intel_dp *intel_dp = intel_connector_to_intel_dp(connector);
struct intel_dp *intel_dp = intel_attached_dp(connector);
int err;
if (val > 2)
@ -1969,7 +1965,7 @@ static int i915_dp_force_link_retrain_show(void *data, u64 *val)
{
struct intel_connector *connector = to_intel_connector(data);
struct intel_display *display = to_intel_display(connector);
struct intel_dp *intel_dp = intel_connector_to_intel_dp(connector);
struct intel_dp *intel_dp = intel_attached_dp(connector);
int err;
err = drm_modeset_lock_single_interruptible(&display->drm->mode_config.connection_mutex);
@ -1987,7 +1983,7 @@ static int i915_dp_force_link_retrain_write(void *data, u64 val)
{
struct intel_connector *connector = to_intel_connector(data);
struct intel_display *display = to_intel_display(connector);
struct intel_dp *intel_dp = intel_connector_to_intel_dp(connector);
struct intel_dp *intel_dp = intel_attached_dp(connector);
int err;
err = drm_modeset_lock_single_interruptible(&display->drm->mode_config.connection_mutex);
@ -2010,7 +2006,7 @@ static int i915_dp_link_retrain_disabled_show(struct seq_file *m, void *data)
{
struct intel_connector *connector = to_intel_connector(m->private);
struct intel_display *display = to_intel_display(connector);
struct intel_dp *intel_dp = intel_connector_to_intel_dp(connector);
struct intel_dp *intel_dp = intel_attached_dp(connector);
int err;
err = drm_modeset_lock_single_interruptible(&display->drm->mode_config.connection_mutex);

View File

@ -41,9 +41,10 @@
#include "intel_display_types.h"
#include "intel_dp.h"
#include "intel_dp_hdcp.h"
#include "intel_dp_mst.h"
#include "intel_dp_tunnel.h"
#include "intel_dp_link_training.h"
#include "intel_dp_mst.h"
#include "intel_dp_test.h"
#include "intel_dp_tunnel.h"
#include "intel_dpio_phy.h"
#include "intel_hdcp.h"
#include "intel_hotplug.h"
@ -102,11 +103,13 @@ static int intel_dp_mst_bw_overhead(const struct intel_crtc_state *crtc_state,
flags |= crtc_state->fec_enable ? DRM_DP_BW_OVERHEAD_FEC : 0;
if (dsc) {
int num_joined_pipes = intel_crtc_num_joined_pipes(crtc_state);
flags |= DRM_DP_BW_OVERHEAD_DSC;
dsc_slice_count = intel_dp_dsc_get_slice_count(connector,
adjusted_mode->clock,
adjusted_mode->hdisplay,
crtc_state->joiner_pipes);
num_joined_pipes);
}
overhead = drm_dp_bw_overhead(crtc_state->lane_count,
@ -539,7 +542,7 @@ intel_dp_mst_compute_config_limits(struct intel_dp *intel_dp,
*/
limits->pipe.max_bpp = min(crtc_state->pipe_bpp, 24);
intel_dp_adjust_compliance_config(intel_dp, crtc_state, limits);
intel_dp_test_compute_config(intel_dp, crtc_state, limits);
if (!intel_dp_compute_config_link_bpp_limits(intel_dp,
crtc_state,
@ -568,6 +571,7 @@ static int intel_dp_mst_compute_config(struct intel_encoder *encoder,
&pipe_config->hw.adjusted_mode;
struct link_config_limits limits;
bool dsc_needed, joiner_needs_dsc;
int num_joined_pipes;
int ret = 0;
if (pipe_config->fec_enable &&
@ -577,16 +581,17 @@ static int intel_dp_mst_compute_config(struct intel_encoder *encoder,
if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
return -EINVAL;
if (intel_dp_need_joiner(intel_dp, connector,
adjusted_mode->crtc_hdisplay,
adjusted_mode->crtc_clock))
pipe_config->joiner_pipes = GENMASK(crtc->pipe + 1, crtc->pipe);
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;
joiner_needs_dsc = intel_dp_joiner_needs_dsc(dev_priv, pipe_config->joiner_pipes);
joiner_needs_dsc = intel_dp_joiner_needs_dsc(dev_priv, num_joined_pipes);
dsc_needed = joiner_needs_dsc || intel_dp->force_dsc_en ||
!intel_dp_mst_compute_config_limits(intel_dp,
@ -985,6 +990,7 @@ static void intel_mst_post_disable_dp(struct intel_atomic_state *state,
const struct intel_crtc_state *old_crtc_state,
const struct drm_connector_state *old_conn_state)
{
struct intel_display *display = to_intel_display(encoder);
struct intel_dp_mst_encoder *intel_mst = enc_to_mst(encoder);
struct intel_digital_port *dig_port = intel_mst->primary;
struct intel_dp *intel_dp = &dig_port->dp;
@ -1001,6 +1007,7 @@ static void intel_mst_post_disable_dp(struct intel_atomic_state *state,
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
struct intel_crtc *pipe_crtc;
bool last_mst_stream;
int i;
intel_dp->active_mst_links--;
last_mst_stream = intel_dp->active_mst_links == 0;
@ -1008,8 +1015,7 @@ static void intel_mst_post_disable_dp(struct intel_atomic_state *state,
DISPLAY_VER(dev_priv) >= 12 && last_mst_stream &&
!intel_dp_mst_is_master_trans(old_crtc_state));
for_each_intel_crtc_in_pipe_mask(&dev_priv->drm, pipe_crtc,
intel_crtc_joined_pipe_mask(old_crtc_state)) {
for_each_pipe_crtc_modeset_disable(display, pipe_crtc, old_crtc_state, i) {
const struct intel_crtc_state *old_pipe_crtc_state =
intel_atomic_get_old_crtc_state(state, pipe_crtc);
@ -1033,8 +1039,7 @@ static void intel_mst_post_disable_dp(struct intel_atomic_state *state,
intel_ddi_disable_transcoder_func(old_crtc_state);
for_each_intel_crtc_in_pipe_mask(&dev_priv->drm, pipe_crtc,
intel_crtc_joined_pipe_mask(old_crtc_state)) {
for_each_pipe_crtc_modeset_disable(display, pipe_crtc, old_crtc_state, i) {
const struct intel_crtc_state *old_pipe_crtc_state =
intel_atomic_get_old_crtc_state(state, pipe_crtc);
@ -1243,6 +1248,7 @@ static void intel_mst_enable_dp(struct intel_atomic_state *state,
const struct intel_crtc_state *pipe_config,
const struct drm_connector_state *conn_state)
{
struct intel_display *display = to_intel_display(encoder);
struct intel_dp_mst_encoder *intel_mst = enc_to_mst(encoder);
struct intel_digital_port *dig_port = intel_mst->primary;
struct intel_dp *intel_dp = &dig_port->dp;
@ -1253,7 +1259,7 @@ static void intel_mst_enable_dp(struct intel_atomic_state *state,
enum transcoder trans = pipe_config->cpu_transcoder;
bool first_mst_stream = intel_dp->active_mst_links == 1;
struct intel_crtc *pipe_crtc;
int ret;
int ret, i;
drm_WARN_ON(&dev_priv->drm, pipe_config->has_pch_encoder);
@ -1300,8 +1306,7 @@ static void intel_mst_enable_dp(struct intel_atomic_state *state,
intel_enable_transcoder(pipe_config);
for_each_intel_crtc_in_pipe_mask_reverse(&dev_priv->drm, pipe_crtc,
intel_crtc_joined_pipe_mask(pipe_config)) {
for_each_pipe_crtc_modeset_enable(display, pipe_crtc, pipe_config, i) {
const struct intel_crtc_state *pipe_crtc_state =
intel_atomic_get_new_crtc_state(state, pipe_crtc);
@ -1422,10 +1427,11 @@ intel_dp_mst_mode_valid_ctx(struct drm_connector *connector,
int max_dotclk = to_i915(connector->dev)->display.cdclk.max_dotclk_freq;
int max_rate, mode_rate, max_lanes, max_link_clock;
int ret;
bool dsc = false, joiner = false;
bool dsc = false;
u16 dsc_max_compressed_bpp = 0;
u8 dsc_slice_count = 0;
int target_clock = mode->clock;
int num_joined_pipes;
if (drm_connector_is_unregistered(connector)) {
*status = MODE_ERROR;
@ -1465,11 +1471,9 @@ intel_dp_mst_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.
*/
if (intel_dp_need_joiner(intel_dp, intel_connector,
mode->hdisplay, target_clock)) {
joiner = true;
max_dotclk *= 2;
}
num_joined_pipes = intel_dp_num_joined_pipes(intel_dp, intel_connector,
mode->hdisplay, target_clock);
max_dotclk *= num_joined_pipes;
ret = drm_modeset_lock(&mgr->base.lock, ctx);
if (ret)
@ -1495,20 +1499,20 @@ intel_dp_mst_mode_valid_ctx(struct drm_connector *connector,
max_lanes,
target_clock,
mode->hdisplay,
joiner,
num_joined_pipes,
INTEL_OUTPUT_FORMAT_RGB,
pipe_bpp, 64);
dsc_slice_count =
intel_dp_dsc_get_slice_count(intel_connector,
target_clock,
mode->hdisplay,
joiner);
num_joined_pipes);
}
dsc = dsc_max_compressed_bpp && dsc_slice_count;
}
if (intel_dp_joiner_needs_dsc(dev_priv, joiner) && !dsc) {
if (intel_dp_joiner_needs_dsc(dev_priv, num_joined_pipes) && !dsc) {
*status = MODE_CLOCK_HIGH;
return 0;
}
@ -1518,7 +1522,7 @@ intel_dp_mst_mode_valid_ctx(struct drm_connector *connector,
return 0;
}
*status = intel_mode_valid_max_plane_size(dev_priv, mode, joiner);
*status = intel_mode_valid_max_plane_size(dev_priv, mode, num_joined_pipes);
return 0;
}

View File

@ -0,0 +1,765 @@
// SPDX-License-Identifier: MIT
/* Copyright © 2024 Intel Corporation */
#include <linux/debugfs.h>
#include <drm/display/drm_dp.h>
#include <drm/display/drm_dp_helper.h>
#include <drm/drm_edid.h>
#include <drm/drm_probe_helper.h>
#include "i915_drv.h"
#include "i915_reg.h"
#include "intel_ddi.h"
#include "intel_de.h"
#include "intel_display_types.h"
#include "intel_dp.h"
#include "intel_dp_link_training.h"
#include "intel_dp_mst.h"
#include "intel_dp_test.h"
void intel_dp_test_reset(struct intel_dp *intel_dp)
{
/*
* Clearing compliance test variables to allow capturing
* of values for next automated test request.
*/
memset(&intel_dp->compliance, 0, sizeof(intel_dp->compliance));
}
/* Adjust link config limits based on compliance test requests. */
void intel_dp_test_compute_config(struct intel_dp *intel_dp,
struct intel_crtc_state *pipe_config,
struct link_config_limits *limits)
{
struct intel_display *display = to_intel_display(intel_dp);
/* For DP Compliance we override the computed bpp for the pipe */
if (intel_dp->compliance.test_data.bpc != 0) {
int bpp = 3 * intel_dp->compliance.test_data.bpc;
limits->pipe.min_bpp = bpp;
limits->pipe.max_bpp = bpp;
pipe_config->dither_force_disable = bpp == 6 * 3;
drm_dbg_kms(display->drm, "Setting pipe_bpp to %d\n", bpp);
}
/* Use values requested by Compliance Test Request */
if (intel_dp->compliance.test_type == DP_TEST_LINK_TRAINING) {
int index;
/* Validate the compliance test data since max values
* might have changed due to link train fallback.
*/
if (intel_dp_link_params_valid(intel_dp, intel_dp->compliance.test_link_rate,
intel_dp->compliance.test_lane_count)) {
index = intel_dp_rate_index(intel_dp->common_rates,
intel_dp->num_common_rates,
intel_dp->compliance.test_link_rate);
if (index >= 0) {
limits->min_rate = intel_dp->compliance.test_link_rate;
limits->max_rate = intel_dp->compliance.test_link_rate;
}
limits->min_lane_count = intel_dp->compliance.test_lane_count;
limits->max_lane_count = intel_dp->compliance.test_lane_count;
}
}
}
/* Compliance test status bits */
#define INTEL_DP_RESOLUTION_PREFERRED 1
#define INTEL_DP_RESOLUTION_STANDARD 2
#define INTEL_DP_RESOLUTION_FAILSAFE 3
static u8 intel_dp_autotest_link_training(struct intel_dp *intel_dp)
{
struct intel_display *display = to_intel_display(intel_dp);
int status = 0;
int test_link_rate;
u8 test_lane_count, test_link_bw;
/* (DP CTS 1.2)
* 4.3.1.11
*/
/* Read the TEST_LANE_COUNT and TEST_LINK_RTAE fields (DP CTS 3.1.4) */
status = drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_LANE_COUNT,
&test_lane_count);
if (status <= 0) {
drm_dbg_kms(display->drm, "Lane count read failed\n");
return DP_TEST_NAK;
}
test_lane_count &= DP_MAX_LANE_COUNT_MASK;
status = drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_LINK_RATE,
&test_link_bw);
if (status <= 0) {
drm_dbg_kms(display->drm, "Link Rate read failed\n");
return DP_TEST_NAK;
}
test_link_rate = drm_dp_bw_code_to_link_rate(test_link_bw);
/* Validate the requested link rate and lane count */
if (!intel_dp_link_params_valid(intel_dp, test_link_rate,
test_lane_count))
return DP_TEST_NAK;
intel_dp->compliance.test_lane_count = test_lane_count;
intel_dp->compliance.test_link_rate = test_link_rate;
return DP_TEST_ACK;
}
static u8 intel_dp_autotest_video_pattern(struct intel_dp *intel_dp)
{
struct intel_display *display = to_intel_display(intel_dp);
u8 test_pattern;
u8 test_misc;
__be16 h_width, v_height;
int status = 0;
/* Read the TEST_PATTERN (DP CTS 3.1.5) */
status = drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_PATTERN,
&test_pattern);
if (status <= 0) {
drm_dbg_kms(display->drm, "Test pattern read failed\n");
return DP_TEST_NAK;
}
if (test_pattern != DP_COLOR_RAMP)
return DP_TEST_NAK;
status = drm_dp_dpcd_read(&intel_dp->aux, DP_TEST_H_WIDTH_HI,
&h_width, 2);
if (status <= 0) {
drm_dbg_kms(display->drm, "H Width read failed\n");
return DP_TEST_NAK;
}
status = drm_dp_dpcd_read(&intel_dp->aux, DP_TEST_V_HEIGHT_HI,
&v_height, 2);
if (status <= 0) {
drm_dbg_kms(display->drm, "V Height read failed\n");
return DP_TEST_NAK;
}
status = drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_MISC0,
&test_misc);
if (status <= 0) {
drm_dbg_kms(display->drm, "TEST MISC read failed\n");
return DP_TEST_NAK;
}
if ((test_misc & DP_TEST_COLOR_FORMAT_MASK) != DP_COLOR_FORMAT_RGB)
return DP_TEST_NAK;
if (test_misc & DP_TEST_DYNAMIC_RANGE_CEA)
return DP_TEST_NAK;
switch (test_misc & DP_TEST_BIT_DEPTH_MASK) {
case DP_TEST_BIT_DEPTH_6:
intel_dp->compliance.test_data.bpc = 6;
break;
case DP_TEST_BIT_DEPTH_8:
intel_dp->compliance.test_data.bpc = 8;
break;
default:
return DP_TEST_NAK;
}
intel_dp->compliance.test_data.video_pattern = test_pattern;
intel_dp->compliance.test_data.hdisplay = be16_to_cpu(h_width);
intel_dp->compliance.test_data.vdisplay = be16_to_cpu(v_height);
/* Set test active flag here so userspace doesn't interrupt things */
intel_dp->compliance.test_active = true;
return DP_TEST_ACK;
}
static u8 intel_dp_autotest_edid(struct intel_dp *intel_dp)
{
struct intel_display *display = to_intel_display(intel_dp);
u8 test_result = DP_TEST_ACK;
struct intel_connector *intel_connector = intel_dp->attached_connector;
struct drm_connector *connector = &intel_connector->base;
if (!intel_connector->detect_edid || connector->edid_corrupt ||
intel_dp->aux.i2c_defer_count > 6) {
/* Check EDID read for NACKs, DEFERs and corruption
* (DP CTS 1.2 Core r1.1)
* 4.2.2.4 : Failed EDID read, I2C_NAK
* 4.2.2.5 : Failed EDID read, I2C_DEFER
* 4.2.2.6 : EDID corruption detected
* Use failsafe mode for all cases
*/
if (intel_dp->aux.i2c_nack_count > 0 ||
intel_dp->aux.i2c_defer_count > 0)
drm_dbg_kms(display->drm,
"EDID read had %d NACKs, %d DEFERs\n",
intel_dp->aux.i2c_nack_count,
intel_dp->aux.i2c_defer_count);
intel_dp->compliance.test_data.edid = INTEL_DP_RESOLUTION_FAILSAFE;
} else {
/* FIXME: Get rid of drm_edid_raw() */
const struct edid *block = drm_edid_raw(intel_connector->detect_edid);
/* We have to write the checksum of the last block read */
block += block->extensions;
if (drm_dp_dpcd_writeb(&intel_dp->aux, DP_TEST_EDID_CHECKSUM,
block->checksum) <= 0)
drm_dbg_kms(display->drm,
"Failed to write EDID checksum\n");
test_result = DP_TEST_ACK | DP_TEST_EDID_CHECKSUM_WRITE;
intel_dp->compliance.test_data.edid = INTEL_DP_RESOLUTION_PREFERRED;
}
/* Set test active flag here so userspace doesn't interrupt things */
intel_dp->compliance.test_active = true;
return test_result;
}
static void intel_dp_phy_pattern_update(struct intel_dp *intel_dp,
const struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(intel_dp);
struct drm_dp_phy_test_params *data =
&intel_dp->compliance.test_data.phytest;
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
enum pipe pipe = crtc->pipe;
u32 pattern_val;
switch (data->phy_pattern) {
case DP_LINK_QUAL_PATTERN_DISABLE:
drm_dbg_kms(display->drm, "Disable Phy Test Pattern\n");
intel_de_write(display, DDI_DP_COMP_CTL(pipe), 0x0);
if (DISPLAY_VER(display) >= 10)
intel_de_rmw(display, dp_tp_ctl_reg(encoder, crtc_state),
DP_TP_CTL_TRAIN_PAT4_SEL_MASK | DP_TP_CTL_LINK_TRAIN_MASK,
DP_TP_CTL_LINK_TRAIN_NORMAL);
break;
case DP_LINK_QUAL_PATTERN_D10_2:
drm_dbg_kms(display->drm, "Set D10.2 Phy Test Pattern\n");
intel_de_write(display, DDI_DP_COMP_CTL(pipe),
DDI_DP_COMP_CTL_ENABLE | DDI_DP_COMP_CTL_D10_2);
break;
case DP_LINK_QUAL_PATTERN_ERROR_RATE:
drm_dbg_kms(display->drm,
"Set Error Count Phy Test Pattern\n");
intel_de_write(display, DDI_DP_COMP_CTL(pipe),
DDI_DP_COMP_CTL_ENABLE |
DDI_DP_COMP_CTL_SCRAMBLED_0);
break;
case DP_LINK_QUAL_PATTERN_PRBS7:
drm_dbg_kms(display->drm, "Set PRBS7 Phy Test Pattern\n");
intel_de_write(display, DDI_DP_COMP_CTL(pipe),
DDI_DP_COMP_CTL_ENABLE | DDI_DP_COMP_CTL_PRBS7);
break;
case DP_LINK_QUAL_PATTERN_80BIT_CUSTOM:
/*
* FIXME: Ideally pattern should come from DPCD 0x250. As
* current firmware of DPR-100 could not set it, so hardcoding
* now for complaince test.
*/
drm_dbg_kms(display->drm,
"Set 80Bit Custom Phy Test Pattern 0x3e0f83e0 0x0f83e0f8 0x0000f83e\n");
pattern_val = 0x3e0f83e0;
intel_de_write(display, DDI_DP_COMP_PAT(pipe, 0), pattern_val);
pattern_val = 0x0f83e0f8;
intel_de_write(display, DDI_DP_COMP_PAT(pipe, 1), pattern_val);
pattern_val = 0x0000f83e;
intel_de_write(display, DDI_DP_COMP_PAT(pipe, 2), pattern_val);
intel_de_write(display, DDI_DP_COMP_CTL(pipe),
DDI_DP_COMP_CTL_ENABLE |
DDI_DP_COMP_CTL_CUSTOM80);
break;
case DP_LINK_QUAL_PATTERN_CP2520_PAT_1:
/*
* FIXME: Ideally pattern should come from DPCD 0x24A. As
* current firmware of DPR-100 could not set it, so hardcoding
* now for complaince test.
*/
drm_dbg_kms(display->drm,
"Set HBR2 compliance Phy Test Pattern\n");
pattern_val = 0xFB;
intel_de_write(display, DDI_DP_COMP_CTL(pipe),
DDI_DP_COMP_CTL_ENABLE | DDI_DP_COMP_CTL_HBR2 |
pattern_val);
break;
case DP_LINK_QUAL_PATTERN_CP2520_PAT_3:
if (DISPLAY_VER(display) < 10) {
drm_warn(display->drm,
"Platform does not support TPS4\n");
break;
}
drm_dbg_kms(display->drm,
"Set TPS4 compliance Phy Test Pattern\n");
intel_de_write(display, DDI_DP_COMP_CTL(pipe), 0x0);
intel_de_rmw(display, dp_tp_ctl_reg(encoder, crtc_state),
DP_TP_CTL_TRAIN_PAT4_SEL_MASK | DP_TP_CTL_LINK_TRAIN_MASK,
DP_TP_CTL_TRAIN_PAT4_SEL_TP4A | DP_TP_CTL_LINK_TRAIN_PAT4);
break;
default:
drm_warn(display->drm, "Invalid Phy Test Pattern\n");
}
}
static void intel_dp_process_phy_request(struct intel_dp *intel_dp,
const struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(intel_dp);
struct drm_dp_phy_test_params *data =
&intel_dp->compliance.test_data.phytest;
u8 link_status[DP_LINK_STATUS_SIZE];
if (drm_dp_dpcd_read_phy_link_status(&intel_dp->aux, DP_PHY_DPRX,
link_status) < 0) {
drm_dbg_kms(display->drm, "failed to get link status\n");
return;
}
/* retrieve vswing & pre-emphasis setting */
intel_dp_get_adjust_train(intel_dp, crtc_state, DP_PHY_DPRX,
link_status);
intel_dp_set_signal_levels(intel_dp, crtc_state, DP_PHY_DPRX);
intel_dp_phy_pattern_update(intel_dp, crtc_state);
drm_dp_dpcd_write(&intel_dp->aux, DP_TRAINING_LANE0_SET,
intel_dp->train_set, crtc_state->lane_count);
drm_dp_set_phy_test_pattern(&intel_dp->aux, data,
intel_dp->dpcd[DP_DPCD_REV]);
}
static u8 intel_dp_autotest_phy_pattern(struct intel_dp *intel_dp)
{
struct intel_display *display = to_intel_display(intel_dp);
struct drm_dp_phy_test_params *data =
&intel_dp->compliance.test_data.phytest;
if (drm_dp_get_phy_test_pattern(&intel_dp->aux, data)) {
drm_dbg_kms(display->drm,
"DP Phy Test pattern AUX read failure\n");
return DP_TEST_NAK;
}
/* Set test active flag here so userspace doesn't interrupt things */
intel_dp->compliance.test_active = true;
return DP_TEST_ACK;
}
void intel_dp_test_request(struct intel_dp *intel_dp)
{
struct intel_display *display = to_intel_display(intel_dp);
u8 response = DP_TEST_NAK;
u8 request = 0;
int status;
status = drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_REQUEST, &request);
if (status <= 0) {
drm_dbg_kms(display->drm,
"Could not read test request from sink\n");
goto update_status;
}
switch (request) {
case DP_TEST_LINK_TRAINING:
drm_dbg_kms(display->drm, "LINK_TRAINING test requested\n");
response = intel_dp_autotest_link_training(intel_dp);
break;
case DP_TEST_LINK_VIDEO_PATTERN:
drm_dbg_kms(display->drm, "TEST_PATTERN test requested\n");
response = intel_dp_autotest_video_pattern(intel_dp);
break;
case DP_TEST_LINK_EDID_READ:
drm_dbg_kms(display->drm, "EDID test requested\n");
response = intel_dp_autotest_edid(intel_dp);
break;
case DP_TEST_LINK_PHY_TEST_PATTERN:
drm_dbg_kms(display->drm, "PHY_PATTERN test requested\n");
response = intel_dp_autotest_phy_pattern(intel_dp);
break;
default:
drm_dbg_kms(display->drm, "Invalid test request '%02x'\n",
request);
break;
}
if (response & DP_TEST_ACK)
intel_dp->compliance.test_type = request;
update_status:
status = drm_dp_dpcd_writeb(&intel_dp->aux, DP_TEST_RESPONSE, response);
if (status <= 0)
drm_dbg_kms(display->drm,
"Could not write test response to sink\n");
}
/* phy test */
static int intel_dp_prep_phy_test(struct intel_dp *intel_dp,
struct drm_modeset_acquire_ctx *ctx,
u8 *pipe_mask)
{
struct intel_display *display = to_intel_display(intel_dp);
struct drm_connector_list_iter conn_iter;
struct intel_connector *connector;
int ret = 0;
*pipe_mask = 0;
drm_connector_list_iter_begin(display->drm, &conn_iter);
for_each_intel_connector_iter(connector, &conn_iter) {
struct drm_connector_state *conn_state =
connector->base.state;
struct intel_crtc_state *crtc_state;
struct intel_crtc *crtc;
if (!intel_dp_has_connector(intel_dp, conn_state))
continue;
crtc = to_intel_crtc(conn_state->crtc);
if (!crtc)
continue;
ret = drm_modeset_lock(&crtc->base.mutex, ctx);
if (ret)
break;
crtc_state = to_intel_crtc_state(crtc->base.state);
drm_WARN_ON(display->drm,
!intel_crtc_has_dp_encoder(crtc_state));
if (!crtc_state->hw.active)
continue;
if (conn_state->commit &&
!try_wait_for_completion(&conn_state->commit->hw_done))
continue;
*pipe_mask |= BIT(crtc->pipe);
}
drm_connector_list_iter_end(&conn_iter);
return ret;
}
static int intel_dp_do_phy_test(struct intel_encoder *encoder,
struct drm_modeset_acquire_ctx *ctx)
{
struct intel_display *display = to_intel_display(encoder);
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
struct intel_crtc *crtc;
u8 pipe_mask;
int ret;
ret = drm_modeset_lock(&display->drm->mode_config.connection_mutex,
ctx);
if (ret)
return ret;
ret = intel_dp_prep_phy_test(intel_dp, ctx, &pipe_mask);
if (ret)
return ret;
if (pipe_mask == 0)
return 0;
drm_dbg_kms(display->drm, "[ENCODER:%d:%s] PHY test\n",
encoder->base.base.id, encoder->base.name);
for_each_intel_crtc_in_pipe_mask(display->drm, crtc, pipe_mask) {
const struct intel_crtc_state *crtc_state =
to_intel_crtc_state(crtc->base.state);
/* test on the MST master transcoder */
if (DISPLAY_VER(display) >= 12 &&
intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST) &&
!intel_dp_mst_is_master_trans(crtc_state))
continue;
intel_dp_process_phy_request(intel_dp, crtc_state);
break;
}
return 0;
}
bool intel_dp_test_phy(struct intel_dp *intel_dp)
{
struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
struct intel_encoder *encoder = &dig_port->base;
struct drm_modeset_acquire_ctx ctx;
int ret;
if (!intel_dp->compliance.test_active ||
intel_dp->compliance.test_type != DP_TEST_LINK_PHY_TEST_PATTERN)
return false;
drm_modeset_acquire_init(&ctx, 0);
for (;;) {
ret = intel_dp_do_phy_test(encoder, &ctx);
if (ret == -EDEADLK) {
drm_modeset_backoff(&ctx);
continue;
}
break;
}
drm_modeset_drop_locks(&ctx);
drm_modeset_acquire_fini(&ctx);
drm_WARN(encoder->base.dev, ret,
"Acquiring modeset locks failed with %i\n", ret);
return true;
}
bool intel_dp_test_short_pulse(struct intel_dp *intel_dp)
{
struct intel_display *display = to_intel_display(intel_dp);
bool reprobe_needed = false;
switch (intel_dp->compliance.test_type) {
case DP_TEST_LINK_TRAINING:
drm_dbg_kms(display->drm,
"Link Training Compliance Test requested\n");
/* Send a Hotplug Uevent to userspace to start modeset */
drm_kms_helper_hotplug_event(display->drm);
break;
case DP_TEST_LINK_PHY_TEST_PATTERN:
drm_dbg_kms(display->drm,
"PHY test pattern Compliance Test requested\n");
/*
* Schedule long hpd to do the test
*
* FIXME get rid of the ad-hoc phy test modeset code
* and properly incorporate it into the normal modeset.
*/
reprobe_needed = true;
}
return reprobe_needed;
}
static ssize_t i915_displayport_test_active_write(struct file *file,
const char __user *ubuf,
size_t len, loff_t *offp)
{
struct seq_file *m = file->private_data;
struct intel_display *display = m->private;
char *input_buffer;
int status = 0;
struct drm_connector *connector;
struct drm_connector_list_iter conn_iter;
struct intel_dp *intel_dp;
int val = 0;
if (len == 0)
return 0;
input_buffer = memdup_user_nul(ubuf, len);
if (IS_ERR(input_buffer))
return PTR_ERR(input_buffer);
drm_dbg_kms(display->drm, "Copied %d bytes from user\n", (unsigned int)len);
drm_connector_list_iter_begin(display->drm, &conn_iter);
drm_for_each_connector_iter(connector, &conn_iter) {
struct intel_encoder *encoder;
if (connector->connector_type !=
DRM_MODE_CONNECTOR_DisplayPort)
continue;
encoder = to_intel_encoder(connector->encoder);
if (encoder && encoder->type == INTEL_OUTPUT_DP_MST)
continue;
if (encoder && connector->status == connector_status_connected) {
intel_dp = enc_to_intel_dp(encoder);
status = kstrtoint(input_buffer, 10, &val);
if (status < 0)
break;
drm_dbg_kms(display->drm, "Got %d for test active\n", val);
/* To prevent erroneous activation of the compliance
* testing code, only accept an actual value of 1 here
*/
if (val == 1)
intel_dp->compliance.test_active = true;
else
intel_dp->compliance.test_active = false;
}
}
drm_connector_list_iter_end(&conn_iter);
kfree(input_buffer);
if (status < 0)
return status;
*offp += len;
return len;
}
static int i915_displayport_test_active_show(struct seq_file *m, void *data)
{
struct intel_display *display = m->private;
struct drm_connector *connector;
struct drm_connector_list_iter conn_iter;
struct intel_dp *intel_dp;
drm_connector_list_iter_begin(display->drm, &conn_iter);
drm_for_each_connector_iter(connector, &conn_iter) {
struct intel_encoder *encoder;
if (connector->connector_type !=
DRM_MODE_CONNECTOR_DisplayPort)
continue;
encoder = to_intel_encoder(connector->encoder);
if (encoder && encoder->type == INTEL_OUTPUT_DP_MST)
continue;
if (encoder && connector->status == connector_status_connected) {
intel_dp = enc_to_intel_dp(encoder);
if (intel_dp->compliance.test_active)
seq_puts(m, "1");
else
seq_puts(m, "0");
} else {
seq_puts(m, "0");
}
}
drm_connector_list_iter_end(&conn_iter);
return 0;
}
static int i915_displayport_test_active_open(struct inode *inode,
struct file *file)
{
return single_open(file, i915_displayport_test_active_show,
inode->i_private);
}
static const struct file_operations i915_displayport_test_active_fops = {
.owner = THIS_MODULE,
.open = i915_displayport_test_active_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
.write = i915_displayport_test_active_write
};
static int i915_displayport_test_data_show(struct seq_file *m, void *data)
{
struct intel_display *display = m->private;
struct drm_connector *connector;
struct drm_connector_list_iter conn_iter;
struct intel_dp *intel_dp;
drm_connector_list_iter_begin(display->drm, &conn_iter);
drm_for_each_connector_iter(connector, &conn_iter) {
struct intel_encoder *encoder;
if (connector->connector_type !=
DRM_MODE_CONNECTOR_DisplayPort)
continue;
encoder = to_intel_encoder(connector->encoder);
if (encoder && encoder->type == INTEL_OUTPUT_DP_MST)
continue;
if (encoder && connector->status == connector_status_connected) {
intel_dp = enc_to_intel_dp(encoder);
if (intel_dp->compliance.test_type ==
DP_TEST_LINK_EDID_READ)
seq_printf(m, "%lx",
intel_dp->compliance.test_data.edid);
else if (intel_dp->compliance.test_type ==
DP_TEST_LINK_VIDEO_PATTERN) {
seq_printf(m, "hdisplay: %d\n",
intel_dp->compliance.test_data.hdisplay);
seq_printf(m, "vdisplay: %d\n",
intel_dp->compliance.test_data.vdisplay);
seq_printf(m, "bpc: %u\n",
intel_dp->compliance.test_data.bpc);
} else if (intel_dp->compliance.test_type ==
DP_TEST_LINK_PHY_TEST_PATTERN) {
seq_printf(m, "pattern: %d\n",
intel_dp->compliance.test_data.phytest.phy_pattern);
seq_printf(m, "Number of lanes: %d\n",
intel_dp->compliance.test_data.phytest.num_lanes);
seq_printf(m, "Link Rate: %d\n",
intel_dp->compliance.test_data.phytest.link_rate);
seq_printf(m, "level: %02x\n",
intel_dp->train_set[0]);
}
} else {
seq_puts(m, "0");
}
}
drm_connector_list_iter_end(&conn_iter);
return 0;
}
DEFINE_SHOW_ATTRIBUTE(i915_displayport_test_data);
static int i915_displayport_test_type_show(struct seq_file *m, void *data)
{
struct intel_display *display = m->private;
struct drm_connector *connector;
struct drm_connector_list_iter conn_iter;
struct intel_dp *intel_dp;
drm_connector_list_iter_begin(display->drm, &conn_iter);
drm_for_each_connector_iter(connector, &conn_iter) {
struct intel_encoder *encoder;
if (connector->connector_type !=
DRM_MODE_CONNECTOR_DisplayPort)
continue;
encoder = to_intel_encoder(connector->encoder);
if (encoder && encoder->type == INTEL_OUTPUT_DP_MST)
continue;
if (encoder && connector->status == connector_status_connected) {
intel_dp = enc_to_intel_dp(encoder);
seq_printf(m, "%02lx\n", intel_dp->compliance.test_type);
} else {
seq_puts(m, "0");
}
}
drm_connector_list_iter_end(&conn_iter);
return 0;
}
DEFINE_SHOW_ATTRIBUTE(i915_displayport_test_type);
static const struct {
const char *name;
const struct file_operations *fops;
} intel_display_debugfs_files[] = {
{"i915_dp_test_data", &i915_displayport_test_data_fops},
{"i915_dp_test_type", &i915_displayport_test_type_fops},
{"i915_dp_test_active", &i915_displayport_test_active_fops},
};
void intel_dp_test_debugfs_register(struct intel_display *display)
{
struct drm_minor *minor = display->drm->primary;
int i;
for (i = 0; i < ARRAY_SIZE(intel_display_debugfs_files); i++) {
debugfs_create_file(intel_display_debugfs_files[i].name,
0644,
minor->debugfs_root,
display,
intel_display_debugfs_files[i].fops);
}
}

View File

@ -0,0 +1,23 @@
/* SPDX-License-Identifier: MIT */
/* Copyright © 2024 Intel Corporation */
#ifndef __INTEL_DP_TEST_H__
#define __INTEL_DP_TEST_H__
#include <linux/types.h>
struct intel_crtc_state;
struct intel_display;
struct intel_dp;
struct link_config_limits;
void intel_dp_test_reset(struct intel_dp *intel_dp);
void intel_dp_test_request(struct intel_dp *intel_dp);
void intel_dp_test_compute_config(struct intel_dp *intel_dp,
struct intel_crtc_state *pipe_config,
struct link_config_limits *limits);
bool intel_dp_test_phy(struct intel_dp *intel_dp);
bool intel_dp_test_short_pulse(struct intel_dp *intel_dp);
void intel_dp_test_debugfs_register(struct intel_display *display);
#endif /* __INTEL_DP_TEST_H__ */

View File

@ -20,7 +20,7 @@ struct intel_dp;
struct intel_encoder;
struct intel_link_bw_limits;
#if defined(CONFIG_DRM_I915_DP_TUNNEL) && defined(I915)
#if IS_ENABLED(CONFIG_DRM_I915_DP_TUNNEL) && defined(I915)
int intel_dp_tunnel_detect(struct intel_dp *intel_dp, struct drm_modeset_acquire_ctx *ctx);
void intel_dp_tunnel_disconnect(struct intel_dp *intel_dp);

View File

@ -589,11 +589,14 @@ static bool intel_pll_is_valid(struct drm_i915_private *dev_priv,
if (clock->m1 < limit->m1.min || limit->m1.max < clock->m1)
return false;
if (!IS_PINEVIEW(dev_priv) && !IS_LP(dev_priv))
if (!IS_PINEVIEW(dev_priv) &&
!IS_VALLEYVIEW(dev_priv) && !IS_CHERRYVIEW(dev_priv) &&
!IS_BROXTON(dev_priv) && !IS_GEMINILAKE(dev_priv))
if (clock->m1 <= clock->m2)
return false;
if (!IS_LP(dev_priv)) {
if (!IS_VALLEYVIEW(dev_priv) && !IS_CHERRYVIEW(dev_priv) &&
!IS_BROXTON(dev_priv) && !IS_GEMINILAKE(dev_priv)) {
if (clock->p < limit->p.min || limit->p.max < clock->p)
return false;
if (clock->m < limit->m.min || limit->m.max < clock->m)
@ -780,7 +783,7 @@ g4x_find_best_dpll(const struct intel_limit *limit,
max_n = limit->n.max;
/* based on hardware requirement, prefer smaller n to precision */
for (clock.n = limit->n.min; clock.n <= max_n; clock.n++) {
/* based on hardware requirement, prefere larger m1,m2 */
/* based on hardware requirement, prefer larger m1,m2 */
for (clock.m1 = limit->m1.max;
clock.m1 >= limit->m1.min; clock.m1--) {
for (clock.m2 = limit->m2.max;
@ -2212,7 +2215,8 @@ void chv_enable_pll(const struct intel_crtc_state *crtc_state)
int vlv_force_pll_on(struct drm_i915_private *dev_priv, enum pipe pipe,
const struct dpll *dpll)
{
struct intel_crtc *crtc = intel_crtc_for_pipe(dev_priv, pipe);
struct intel_display *display = &dev_priv->display;
struct intel_crtc *crtc = intel_crtc_for_pipe(display, pipe);
struct intel_crtc_state *crtc_state;
crtc_state = intel_crtc_state_alloc(crtc);

View File

@ -242,7 +242,7 @@ void intel_dpt_suspend(struct drm_i915_private *i915)
struct i915_address_space *
intel_dpt_create(struct intel_framebuffer *fb)
{
struct drm_gem_object *obj = &intel_fb_obj(&fb->base)->base;
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;

View File

@ -3,6 +3,8 @@
* Copyright © 2021 Intel Corporation
*/
#include <linux/debugfs.h>
#include "i915_drv.h"
#include "i915_reg.h"
#include "intel_atomic.h"

View File

@ -4,6 +4,8 @@
*
*/
#include <drm/drm_vblank.h>
#include "i915_drv.h"
#include "i915_irq.h"
#include "i915_reg.h"
@ -37,9 +39,16 @@ struct intel_dsb {
unsigned int free_pos;
/*
* ins_start_offset will help to store start dword of the dsb
* instuction and help in identifying the batch of auto-increment
* register.
* Previously emitted DSB instruction. Used to
* identify/adjust the instruction for indexed
* register writes.
*/
u32 ins[2];
/*
* Start of the previously emitted DSB instruction.
* Used to adjust the instruction for indexed
* register writes.
*/
unsigned int ins_start_offset;
@ -119,6 +128,12 @@ pre_commit_crtc_state(struct intel_atomic_state *state,
return old_crtc_state;
}
static int dsb_vblank_delay(const struct intel_crtc_state *crtc_state)
{
return intel_mode_vblank_start(&crtc_state->hw.adjusted_mode) -
intel_mode_vdisplay(&crtc_state->hw.adjusted_mode);
}
static int dsb_vtotal(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
@ -215,9 +230,11 @@ static void intel_dsb_emit(struct intel_dsb *dsb, u32 ldw, u32 udw)
dsb->free_pos = ALIGN(dsb->free_pos, 2);
dsb->ins_start_offset = dsb->free_pos;
dsb->ins[0] = ldw;
dsb->ins[1] = udw;
intel_dsb_buffer_write(&dsb->dsb_buf, dsb->free_pos++, ldw);
intel_dsb_buffer_write(&dsb->dsb_buf, dsb->free_pos++, 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]);
}
static bool intel_dsb_prev_ins_is_write(struct intel_dsb *dsb,
@ -233,10 +250,8 @@ static bool intel_dsb_prev_ins_is_write(struct intel_dsb *dsb,
if (dsb->free_pos == 0)
return false;
prev_opcode = intel_dsb_buffer_read(&dsb->dsb_buf,
dsb->ins_start_offset + 1) & ~DSB_REG_VALUE_MASK;
prev_reg = intel_dsb_buffer_read(&dsb->dsb_buf,
dsb->ins_start_offset + 1) & DSB_REG_VALUE_MASK;
prev_opcode = dsb->ins[1] & ~DSB_REG_VALUE_MASK;
prev_reg = dsb->ins[1] & DSB_REG_VALUE_MASK;
return prev_opcode == opcode && prev_reg == i915_mmio_reg_offset(reg);
}
@ -269,8 +284,6 @@ static bool intel_dsb_prev_ins_is_indexed_write(struct intel_dsb *dsb, i915_reg_
void intel_dsb_reg_write(struct intel_dsb *dsb,
i915_reg_t reg, u32 val)
{
u32 old_val;
/*
* For example the buffer will look like below for 3 dwords for auto
* increment register:
@ -299,23 +312,27 @@ void intel_dsb_reg_write(struct intel_dsb *dsb,
/* convert to indexed write? */
if (intel_dsb_prev_ins_is_mmio_write(dsb, reg)) {
u32 prev_val = intel_dsb_buffer_read(&dsb->dsb_buf,
dsb->ins_start_offset + 0);
u32 prev_val = dsb->ins[0];
intel_dsb_buffer_write(&dsb->dsb_buf,
dsb->ins_start_offset + 0, 1); /* count */
dsb->ins[0] = 1; /* count */
dsb->ins[1] = (DSB_OPCODE_INDEXED_WRITE << DSB_OPCODE_SHIFT) |
i915_mmio_reg_offset(reg);
intel_dsb_buffer_write(&dsb->dsb_buf, dsb->ins_start_offset + 0,
dsb->ins[0]);
intel_dsb_buffer_write(&dsb->dsb_buf, dsb->ins_start_offset + 1,
(DSB_OPCODE_INDEXED_WRITE << DSB_OPCODE_SHIFT) |
i915_mmio_reg_offset(reg));
intel_dsb_buffer_write(&dsb->dsb_buf, dsb->ins_start_offset + 2, prev_val);
dsb->ins[1]);
intel_dsb_buffer_write(&dsb->dsb_buf, dsb->ins_start_offset + 2,
prev_val);
dsb->free_pos++;
}
intel_dsb_buffer_write(&dsb->dsb_buf, dsb->free_pos++, val);
/* Update the count */
old_val = intel_dsb_buffer_read(&dsb->dsb_buf, dsb->ins_start_offset);
intel_dsb_buffer_write(&dsb->dsb_buf, dsb->ins_start_offset, old_val + 1);
dsb->ins[0]++;
intel_dsb_buffer_write(&dsb->dsb_buf, dsb->ins_start_offset + 0,
dsb->ins[0]);
/* if number of data words is odd, then the last dword should be 0.*/
if (dsb->free_pos & 0x1)
@ -370,6 +387,24 @@ void intel_dsb_nonpost_end(struct intel_dsb *dsb)
intel_dsb_noop(dsb, 4);
}
void intel_dsb_interrupt(struct intel_dsb *dsb)
{
intel_dsb_emit(dsb, 0,
DSB_OPCODE_INTERRUPT << DSB_OPCODE_SHIFT);
}
void intel_dsb_wait_usec(struct intel_dsb *dsb, int count)
{
intel_dsb_emit(dsb, count,
DSB_OPCODE_WAIT_USEC << DSB_OPCODE_SHIFT);
}
void intel_dsb_wait_vblanks(struct intel_dsb *dsb, int count)
{
intel_dsb_emit(dsb, count,
DSB_OPCODE_WAIT_VBLANKS << DSB_OPCODE_SHIFT);
}
static void intel_dsb_emit_wait_dsl(struct intel_dsb *dsb,
u32 opcode, int lower, int upper)
{
@ -510,6 +545,31 @@ static u32 dsb_error_int_en(struct intel_display *display)
return errors;
}
void intel_dsb_vblank_evade(struct intel_atomic_state *state,
struct intel_dsb *dsb)
{
struct intel_crtc *crtc = dsb->crtc;
const struct intel_crtc_state *crtc_state = pre_commit_crtc_state(state, crtc);
/* FIXME calibrate sensibly */
int latency = intel_usecs_to_scanlines(&crtc_state->hw.adjusted_mode, 20);
int vblank_delay = dsb_vblank_delay(crtc_state);
int start, end;
if (pre_commit_is_vrr_active(state, crtc)) {
end = intel_vrr_vmin_vblank_start(crtc_state);
start = end - vblank_delay - latency;
intel_dsb_wait_scanline_out(state, dsb, start, end);
end = intel_vrr_vmax_vblank_start(crtc_state);
start = end - vblank_delay - latency;
intel_dsb_wait_scanline_out(state, dsb, start, end);
} else {
end = intel_mode_vblank_start(&crtc_state->hw.adjusted_mode);
start = end - vblank_delay - latency;
intel_dsb_wait_scanline_out(state, dsb, start, end);
}
}
static void _intel_dsb_chain(struct intel_atomic_state *state,
struct intel_dsb *dsb,
struct intel_dsb *chained_dsb,
@ -535,7 +595,7 @@ static void _intel_dsb_chain(struct intel_atomic_state *state,
intel_dsb_reg_write(dsb, DSB_INTERRUPT(pipe, chained_dsb->id),
dsb_error_int_status(display) | DSB_PROG_INT_STATUS |
dsb_error_int_en(display));
dsb_error_int_en(display) | DSB_PROG_INT_EN);
if (ctrl & DSB_WAIT_FOR_VBLANK) {
int dewake_scanline = dsb_dewake_scanline_start(state, crtc);
@ -577,6 +637,17 @@ void intel_dsb_chain(struct intel_atomic_state *state,
wait_for_vblank ? DSB_WAIT_FOR_VBLANK : 0);
}
void intel_dsb_wait_vblank_delay(struct intel_atomic_state *state,
struct intel_dsb *dsb)
{
struct intel_crtc *crtc = dsb->crtc;
const struct intel_crtc_state *crtc_state = pre_commit_crtc_state(state, crtc);
int usecs = intel_scanlines_to_usecs(&crtc_state->hw.adjusted_mode,
dsb_vblank_delay(crtc_state)) + 1;
intel_dsb_wait_usec(dsb, usecs);
}
static void _intel_dsb_commit(struct intel_dsb *dsb, u32 ctrl,
int hw_dewake_scanline)
{
@ -603,7 +674,7 @@ static void _intel_dsb_commit(struct intel_dsb *dsb, u32 ctrl,
intel_de_write_fw(display, DSB_INTERRUPT(pipe, dsb->id),
dsb_error_int_status(display) | DSB_PROG_INT_STATUS |
dsb_error_int_en(display));
dsb_error_int_en(display) | DSB_PROG_INT_EN);
intel_de_write_fw(display, DSB_HEAD(pipe, dsb->id),
intel_dsb_buffer_ggtt_offset(&dsb->dsb_buf));
@ -671,6 +742,9 @@ void intel_dsb_wait(struct intel_dsb *dsb)
/* Attempt to reset it */
dsb->free_pos = 0;
dsb->ins_start_offset = 0;
dsb->ins[0] = 0;
dsb->ins[1] = 0;
intel_de_write_fw(display, DSB_CTRL(pipe, dsb->id), 0);
intel_de_write_fw(display, DSB_INTERRUPT(pipe, dsb->id),
@ -723,8 +797,6 @@ struct intel_dsb *intel_dsb_prepare(struct intel_atomic_state *state,
dsb->id = dsb_id;
dsb->crtc = crtc;
dsb->size = size / 4; /* in dwords */
dsb->free_pos = 0;
dsb->ins_start_offset = 0;
dsb->chicken = dsb_chicken(state, crtc);
dsb->hw_dewake_scanline =
@ -759,12 +831,29 @@ void intel_dsb_cleanup(struct intel_dsb *dsb)
void intel_dsb_irq_handler(struct intel_display *display,
enum pipe pipe, enum intel_dsb_id dsb_id)
{
struct intel_crtc *crtc = intel_crtc_for_pipe(to_i915(display->drm), pipe);
struct intel_crtc *crtc = intel_crtc_for_pipe(display, pipe);
u32 tmp, errors;
tmp = intel_de_read_fw(display, DSB_INTERRUPT(pipe, dsb_id));
intel_de_write_fw(display, DSB_INTERRUPT(pipe, dsb_id), tmp);
if (tmp & DSB_PROG_INT_STATUS) {
spin_lock(&display->drm->event_lock);
if (crtc->dsb_event) {
/*
* Update vblank counter/timestmap in case it
* hasn't been done yet for this frame.
*/
drm_crtc_accurate_vblank_count(&crtc->base);
drm_crtc_send_vblank_event(&crtc->base, crtc->dsb_event);
crtc->dsb_event = NULL;
}
spin_unlock(&display->drm->event_lock);
}
errors = tmp & dsb_error_int_status(display);
if (errors)
drm_err(display->drm, "[CRTC:%d:%s] DSB %d error interrupt: 0x%x\n",

View File

@ -39,12 +39,19 @@ void intel_dsb_reg_write_masked(struct intel_dsb *dsb,
void intel_dsb_noop(struct intel_dsb *dsb, int count);
void intel_dsb_nonpost_start(struct intel_dsb *dsb);
void intel_dsb_nonpost_end(struct intel_dsb *dsb);
void intel_dsb_interrupt(struct intel_dsb *dsb);
void intel_dsb_wait_usec(struct intel_dsb *dsb, int count);
void intel_dsb_wait_vblanks(struct intel_dsb *dsb, int count);
void intel_dsb_wait_vblank_delay(struct intel_atomic_state *state,
struct intel_dsb *dsb);
void intel_dsb_wait_scanline_in(struct intel_atomic_state *state,
struct intel_dsb *dsb,
int lower, int upper);
void intel_dsb_wait_scanline_out(struct intel_atomic_state *state,
struct intel_dsb *dsb,
int lower, int upper);
void intel_dsb_vblank_evade(struct intel_atomic_state *state,
struct intel_dsb *dsb);
void intel_dsb_chain(struct intel_atomic_state *state,
struct intel_dsb *dsb,
struct intel_dsb *chained_dsb,

View File

@ -76,7 +76,7 @@ enum drm_mode_status intel_dsi_mode_valid(struct drm_connector *connector,
if (fixed_mode->clock > max_dotclk)
return MODE_CLOCK_HIGH;
return intel_mode_valid_max_plane_size(dev_priv, mode, false);
return intel_mode_valid_max_plane_size(dev_priv, mode, 1);
}
struct intel_dsi_host *intel_dsi_host_init(struct intel_dsi *intel_dsi,

View File

@ -31,6 +31,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_crtc.h>
#include <drm/drm_edid.h>
#include <drm/drm_probe_helper.h>
#include "i915_drv.h"
#include "i915_reg.h"

View File

@ -3,15 +3,16 @@
* Copyright © 2021 Intel Corporation
*/
#include <drm/drm_blend.h>
#include <drm/drm_modeset_helper.h>
#include <linux/dma-fence.h>
#include <linux/dma-resv.h>
#include "gem/i915_gem_object.h"
#include <drm/drm_blend.h>
#include <drm/drm_gem.h>
#include <drm/drm_modeset_helper.h>
#include "i915_drv.h"
#include "intel_atomic_plane.h"
#include "intel_bo.h"
#include "intel_display.h"
#include "intel_display_types.h"
#include "intel_dpt.h"
@ -44,6 +45,14 @@ static const struct drm_format_info skl_ccs_formats[] = {
.cpp = { 4, 1, }, .hsub = 8, .vsub = 16, .has_alpha = true, },
{ .format = DRM_FORMAT_ABGR8888, .depth = 32, .num_planes = 2,
.cpp = { 4, 1, }, .hsub = 8, .vsub = 16, .has_alpha = true, },
{ .format = DRM_FORMAT_XRGB2101010, .depth = 30, .num_planes = 2,
.cpp = { 4, 1, }, .hsub = 8, .vsub = 16, },
{ .format = DRM_FORMAT_XBGR2101010, .depth = 30, .num_planes = 2,
.cpp = { 4, 1, }, .hsub = 8, .vsub = 16, },
{ .format = DRM_FORMAT_ARGB2101010, .depth = 30, .num_planes = 2,
.cpp = { 4, 1, }, .hsub = 8, .vsub = 16, .has_alpha = true, },
{ .format = DRM_FORMAT_ABGR2101010, .depth = 30, .num_planes = 2,
.cpp = { 4, 1, }, .hsub = 8, .vsub = 16, .has_alpha = true, },
};
/*
@ -66,6 +75,30 @@ static const struct drm_format_info gen12_ccs_formats[] = {
{ .format = DRM_FORMAT_ABGR8888, .depth = 32, .num_planes = 2,
.char_per_block = { 4, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 },
.hsub = 1, .vsub = 1, .has_alpha = true },
{ .format = DRM_FORMAT_XRGB2101010, .depth = 30, .num_planes = 2,
.char_per_block = { 4, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 },
.hsub = 1, .vsub = 1, },
{ .format = DRM_FORMAT_XBGR2101010, .depth = 30, .num_planes = 2,
.char_per_block = { 4, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 },
.hsub = 1, .vsub = 1, },
{ .format = DRM_FORMAT_ARGB2101010, .depth = 30, .num_planes = 2,
.char_per_block = { 4, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 },
.hsub = 1, .vsub = 1, .has_alpha = true },
{ .format = DRM_FORMAT_ABGR2101010, .depth = 30, .num_planes = 2,
.char_per_block = { 4, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 },
.hsub = 1, .vsub = 1, .has_alpha = true },
{ .format = DRM_FORMAT_XRGB16161616F, .depth = 0, .num_planes = 2,
.char_per_block = { 8, 1 }, .block_w = { 1, 1 }, .block_h = { 1, 1 },
.hsub = 1, .vsub = 1, },
{ .format = DRM_FORMAT_XBGR16161616F, .depth = 0, .num_planes = 2,
.char_per_block = { 8, 1 }, .block_w = { 1, 1 }, .block_h = { 1, 1 },
.hsub = 1, .vsub = 1, },
{ .format = DRM_FORMAT_ARGB16161616F, .depth = 0, .num_planes = 2,
.char_per_block = { 8, 1 }, .block_w = { 1, 1 }, .block_h = { 1, 1 },
.hsub = 1, .vsub = 1, .has_alpha = true },
{ .format = DRM_FORMAT_ABGR16161616F, .depth = 0, .num_planes = 2,
.char_per_block = { 8, 1 }, .block_w = { 1, 1 }, .block_h = { 1, 1 },
.hsub = 1, .vsub = 1, .has_alpha = true },
{ .format = DRM_FORMAT_YUYV, .num_planes = 2,
.char_per_block = { 2, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 },
.hsub = 2, .vsub = 1, .is_yuv = true },
@ -101,31 +134,79 @@ static const struct drm_format_info gen12_ccs_formats[] = {
*/
static const struct drm_format_info gen12_ccs_cc_formats[] = {
{ .format = DRM_FORMAT_XRGB8888, .depth = 24, .num_planes = 3,
.char_per_block = { 4, 1, 0 }, .block_w = { 1, 2, 2 }, .block_h = { 1, 1, 1 },
.char_per_block = { 4, 1, 0 }, .block_w = { 1, 2, 0 }, .block_h = { 1, 1, 0 },
.hsub = 1, .vsub = 1, },
{ .format = DRM_FORMAT_XBGR8888, .depth = 24, .num_planes = 3,
.char_per_block = { 4, 1, 0 }, .block_w = { 1, 2, 2 }, .block_h = { 1, 1, 1 },
.char_per_block = { 4, 1, 0 }, .block_w = { 1, 2, 0 }, .block_h = { 1, 1, 0 },
.hsub = 1, .vsub = 1, },
{ .format = DRM_FORMAT_ARGB8888, .depth = 32, .num_planes = 3,
.char_per_block = { 4, 1, 0 }, .block_w = { 1, 2, 2 }, .block_h = { 1, 1, 1 },
.char_per_block = { 4, 1, 0 }, .block_w = { 1, 2, 0 }, .block_h = { 1, 1, 0 },
.hsub = 1, .vsub = 1, .has_alpha = true },
{ .format = DRM_FORMAT_ABGR8888, .depth = 32, .num_planes = 3,
.char_per_block = { 4, 1, 0 }, .block_w = { 1, 2, 2 }, .block_h = { 1, 1, 1 },
.char_per_block = { 4, 1, 0 }, .block_w = { 1, 2, 0 }, .block_h = { 1, 1, 0 },
.hsub = 1, .vsub = 1, .has_alpha = true },
{ .format = DRM_FORMAT_XRGB2101010, .depth = 30, .num_planes = 3,
.char_per_block = { 4, 1, 0 }, .block_w = { 1, 2, 0 }, .block_h = { 1, 1, 0 },
.hsub = 1, .vsub = 1, },
{ .format = DRM_FORMAT_XBGR2101010, .depth = 30, .num_planes = 3,
.char_per_block = { 4, 1, 0 }, .block_w = { 1, 2, 0 }, .block_h = { 1, 1, 0 },
.hsub = 1, .vsub = 1, },
{ .format = DRM_FORMAT_ARGB2101010, .depth = 30, .num_planes = 3,
.char_per_block = { 4, 1, 0 }, .block_w = { 1, 2, 0 }, .block_h = { 1, 1, 0 },
.hsub = 1, .vsub = 1, .has_alpha = true },
{ .format = DRM_FORMAT_ABGR2101010, .depth = 30, .num_planes = 3,
.char_per_block = { 4, 1, 0 }, .block_w = { 1, 2, 0 }, .block_h = { 1, 1, 0 },
.hsub = 1, .vsub = 1, .has_alpha = true },
{ .format = DRM_FORMAT_XRGB16161616F, .depth = 0, .num_planes = 3,
.char_per_block = { 8, 1, 0 }, .block_w = { 1, 1, 0 }, .block_h = { 1, 1, 0 },
.hsub = 1, .vsub = 1, },
{ .format = DRM_FORMAT_XBGR16161616F, .depth = 0, .num_planes = 3,
.char_per_block = { 8, 1, 0 }, .block_w = { 1, 1, 0 }, .block_h = { 1, 1, 0 },
.hsub = 1, .vsub = 1, },
{ .format = DRM_FORMAT_ARGB16161616F, .depth = 0, .num_planes = 3,
.char_per_block = { 8, 1, 0 }, .block_w = { 1, 1, 0 }, .block_h = { 1, 1, 0 },
.hsub = 1, .vsub = 1, .has_alpha = true },
{ .format = DRM_FORMAT_ABGR16161616F, .depth = 0, .num_planes = 3,
.char_per_block = { 8, 1, 0 }, .block_w = { 1, 1, 0 }, .block_h = { 1, 1, 0 },
.hsub = 1, .vsub = 1, .has_alpha = true },
};
static const struct drm_format_info gen12_flat_ccs_cc_formats[] = {
{ .format = DRM_FORMAT_XRGB8888, .depth = 24, .num_planes = 2,
.char_per_block = { 4, 0 }, .block_w = { 1, 2 }, .block_h = { 1, 1 },
.char_per_block = { 4, 0 }, .block_w = { 1, 0 }, .block_h = { 1, 0 },
.hsub = 1, .vsub = 1, },
{ .format = DRM_FORMAT_XBGR8888, .depth = 24, .num_planes = 2,
.char_per_block = { 4, 0 }, .block_w = { 1, 2 }, .block_h = { 1, 1 },
.char_per_block = { 4, 0 }, .block_w = { 1, 0 }, .block_h = { 1, 0 },
.hsub = 1, .vsub = 1, },
{ .format = DRM_FORMAT_ARGB8888, .depth = 32, .num_planes = 2,
.char_per_block = { 4, 0 }, .block_w = { 1, 2 }, .block_h = { 1, 1 },
.char_per_block = { 4, 0 }, .block_w = { 1, 0 }, .block_h = { 1, 0 },
.hsub = 1, .vsub = 1, .has_alpha = true },
{ .format = DRM_FORMAT_ABGR8888, .depth = 32, .num_planes = 2,
.char_per_block = { 4, 0 }, .block_w = { 1, 2 }, .block_h = { 1, 1 },
.char_per_block = { 4, 0 }, .block_w = { 1, 0 }, .block_h = { 1, 0 },
.hsub = 1, .vsub = 1, .has_alpha = true },
{ .format = DRM_FORMAT_XRGB2101010, .depth = 30, .num_planes = 2,
.char_per_block = { 4, 0 }, .block_w = { 1, 0 }, .block_h = { 1, 0 },
.hsub = 1, .vsub = 1, },
{ .format = DRM_FORMAT_XBGR2101010, .depth = 30, .num_planes = 2,
.char_per_block = { 4, 0 }, .block_w = { 1, 0 }, .block_h = { 1, 0 },
.hsub = 1, .vsub = 1, },
{ .format = DRM_FORMAT_ARGB2101010, .depth = 30, .num_planes = 2,
.char_per_block = { 4, 0 }, .block_w = { 1, 0 }, .block_h = { 1, 0 },
.hsub = 1, .vsub = 1, .has_alpha = true },
{ .format = DRM_FORMAT_ABGR2101010, .depth = 30, .num_planes = 2,
.char_per_block = { 4, 0 }, .block_w = { 1, 0 }, .block_h = { 1, 0 },
.hsub = 1, .vsub = 1, .has_alpha = true },
{ .format = DRM_FORMAT_XRGB16161616F, .depth = 0, .num_planes = 2,
.char_per_block = { 8, 0 }, .block_w = { 1, 0 }, .block_h = { 1, 0 },
.hsub = 1, .vsub = 1, },
{ .format = DRM_FORMAT_XBGR16161616F, .depth = 0, .num_planes = 2,
.char_per_block = { 8, 0 }, .block_w = { 1, 0 }, .block_h = { 1, 0 },
.hsub = 1, .vsub = 1, },
{ .format = DRM_FORMAT_ARGB16161616F, .depth = 0, .num_planes = 2,
.char_per_block = { 8, 0 }, .block_w = { 1, 0 }, .block_h = { 1, 0 },
.hsub = 1, .vsub = 1, .has_alpha = true },
{ .format = DRM_FORMAT_ABGR16161616F, .depth = 0, .num_planes = 2,
.char_per_block = { 8, 0 }, .block_w = { 1, 0 }, .block_h = { 1, 0 },
.hsub = 1, .vsub = 1, .has_alpha = true },
};
@ -1224,7 +1305,7 @@ static bool intel_plane_needs_remap(const struct intel_plane_state *plane_state)
static int convert_plane_offset_to_xy(const struct intel_framebuffer *fb, int color_plane,
int plane_width, int *x, int *y)
{
struct drm_i915_gem_object *obj = intel_fb_obj(&fb->base);
struct drm_gem_object *obj = intel_fb_bo(&fb->base);
int ret;
ret = intel_fb_offset_to_xy(x, y, &fb->base, color_plane);
@ -1248,7 +1329,7 @@ static int convert_plane_offset_to_xy(const struct intel_framebuffer *fb, int co
* fb layout agrees with the fence layout. We already check that the
* fb stride matches the fence stride elsewhere.
*/
if (color_plane == 0 && i915_gem_object_is_tiled(obj) &&
if (color_plane == 0 && intel_bo_is_tiled(obj) &&
(*x + plane_width) * fb->base.format->cpp[color_plane] > fb->base.pitches[color_plane]) {
drm_dbg_kms(fb->base.dev,
"bad fb plane %d offset: 0x%x\n",
@ -1568,7 +1649,7 @@ static unsigned int intel_fb_min_alignment(const struct drm_framebuffer *fb)
int intel_fill_fb_info(struct drm_i915_private *i915, struct intel_framebuffer *fb)
{
struct drm_i915_gem_object *obj = intel_fb_obj(&fb->base);
struct drm_gem_object *obj = intel_fb_bo(&fb->base);
u32 gtt_offset_rotated = 0;
u32 gtt_offset_remapped = 0;
unsigned int max_size = 0;
@ -1641,10 +1722,10 @@ int intel_fill_fb_info(struct drm_i915_private *i915, struct intel_framebuffer *
max_size = max(max_size, offset + size);
}
if (mul_u32_u32(max_size, tile_size) > intel_bo_to_drm_bo(obj)->size) {
if (mul_u32_u32(max_size, tile_size) > obj->size) {
drm_dbg_kms(&i915->drm,
"fb too big for bo (need %llu bytes, have %zu bytes)\n",
mul_u32_u32(max_size, tile_size), intel_bo_to_drm_bo(obj)->size);
mul_u32_u32(max_size, tile_size), obj->size);
return -EINVAL;
}
@ -1868,7 +1949,7 @@ static void intel_user_framebuffer_destroy(struct drm_framebuffer *fb)
intel_frontbuffer_put(intel_fb->frontbuffer);
intel_fb_bo_framebuffer_fini(intel_fb_obj(fb));
intel_fb_bo_framebuffer_fini(intel_fb_bo(fb));
kfree(intel_fb);
}
@ -1877,16 +1958,16 @@ static int intel_user_framebuffer_create_handle(struct drm_framebuffer *fb,
struct drm_file *file,
unsigned int *handle)
{
struct drm_i915_gem_object *obj = intel_fb_obj(fb);
struct drm_i915_private *i915 = to_i915(intel_bo_to_drm_bo(obj)->dev);
struct drm_gem_object *obj = intel_fb_bo(fb);
struct intel_display *display = to_intel_display(obj->dev);
if (i915_gem_object_is_userptr(obj)) {
drm_dbg(&i915->drm,
if (intel_bo_is_userptr(obj)) {
drm_dbg(display->drm,
"attempting to use a userptr for a framebuffer, denied\n");
return -EINVAL;
}
return drm_gem_handle_create(file, intel_bo_to_drm_bo(obj), handle);
return drm_gem_handle_create(file, obj, handle);
}
struct frontbuffer_fence_cb {
@ -1910,7 +1991,7 @@ static int intel_user_framebuffer_dirty(struct drm_framebuffer *fb,
struct drm_clip_rect *clips,
unsigned int num_clips)
{
struct drm_i915_gem_object *obj = intel_fb_obj(fb);
struct drm_gem_object *obj = intel_fb_bo(fb);
struct intel_frontbuffer *front = to_intel_frontbuffer(fb);
struct dma_fence *fence;
struct frontbuffer_fence_cb *cb;
@ -1919,10 +2000,10 @@ static int intel_user_framebuffer_dirty(struct drm_framebuffer *fb,
if (!atomic_read(&front->bits))
return 0;
if (dma_resv_test_signaled(intel_bo_to_drm_bo(obj)->resv, dma_resv_usage_rw(false)))
if (dma_resv_test_signaled(obj->resv, dma_resv_usage_rw(false)))
goto flush;
ret = dma_resv_get_singleton(intel_bo_to_drm_bo(obj)->resv, dma_resv_usage_rw(false),
ret = dma_resv_get_singleton(obj->resv, dma_resv_usage_rw(false),
&fence);
if (ret || !fence)
goto flush;
@ -1949,7 +2030,7 @@ static int intel_user_framebuffer_dirty(struct drm_framebuffer *fb,
return ret;
flush:
i915_gem_object_flush_if_display(obj);
intel_bo_flush_if_display(obj);
intel_frontbuffer_flush(front, ORIGIN_DIRTYFB);
return ret;
}
@ -1961,10 +2042,10 @@ static const struct drm_framebuffer_funcs intel_fb_funcs = {
};
int intel_framebuffer_init(struct intel_framebuffer *intel_fb,
struct drm_i915_gem_object *obj,
struct drm_gem_object *obj,
struct drm_mode_fb_cmd2 *mode_cmd)
{
struct drm_i915_private *dev_priv = to_i915(intel_bo_to_drm_bo(obj)->dev);
struct drm_i915_private *dev_priv = to_i915(obj->dev);
struct drm_framebuffer *fb = &intel_fb->base;
u32 max_stride;
int ret = -EINVAL;
@ -2040,7 +2121,7 @@ int intel_framebuffer_init(struct intel_framebuffer *intel_fb,
}
}
fb->obj[i] = intel_bo_to_drm_bo(obj);
fb->obj[i] = obj;
}
ret = intel_fill_fb_info(dev_priv, intel_fb);
@ -2084,7 +2165,7 @@ intel_user_framebuffer_create(struct drm_device *dev,
const struct drm_mode_fb_cmd2 *user_mode_cmd)
{
struct drm_framebuffer *fb;
struct drm_i915_gem_object *obj;
struct drm_gem_object *obj;
struct drm_mode_fb_cmd2 mode_cmd = *user_mode_cmd;
struct drm_i915_private *i915 = to_i915(dev);
@ -2093,13 +2174,13 @@ intel_user_framebuffer_create(struct drm_device *dev,
return ERR_CAST(obj);
fb = intel_framebuffer_create(obj, &mode_cmd);
drm_gem_object_put(intel_bo_to_drm_bo(obj));
drm_gem_object_put(obj);
return fb;
}
struct drm_framebuffer *
intel_framebuffer_create(struct drm_i915_gem_object *obj,
intel_framebuffer_create(struct drm_gem_object *obj,
struct drm_mode_fb_cmd2 *mode_cmd)
{
struct intel_framebuffer *intel_fb;
@ -2119,3 +2200,8 @@ intel_framebuffer_create(struct drm_i915_gem_object *obj,
kfree(intel_fb);
return ERR_PTR(ret);
}
struct drm_gem_object *intel_fb_bo(const struct drm_framebuffer *fb)
{
return fb ? fb->obj[0] : NULL;
}

View File

@ -12,6 +12,7 @@
struct drm_device;
struct drm_file;
struct drm_framebuffer;
struct drm_gem_object;
struct drm_i915_gem_object;
struct drm_i915_private;
struct drm_mode_fb_cmd2;
@ -84,9 +85,12 @@ void intel_fb_fill_view(const struct intel_framebuffer *fb, unsigned int rotatio
int intel_plane_compute_gtt(struct intel_plane_state *plane_state);
int intel_framebuffer_init(struct intel_framebuffer *ifb,
struct drm_i915_gem_object *obj,
struct drm_gem_object *obj,
struct drm_mode_fb_cmd2 *mode_cmd);
struct drm_framebuffer *
intel_framebuffer_create(struct drm_gem_object *obj,
struct drm_mode_fb_cmd2 *mode_cmd);
struct drm_framebuffer *
intel_user_framebuffer_create(struct drm_device *dev,
struct drm_file *filp,
const struct drm_mode_fb_cmd2 *user_mode_cmd);
@ -96,4 +100,6 @@ bool intel_fb_uses_dpt(const struct drm_framebuffer *fb);
unsigned int intel_fb_modifier_to_tiling(u64 fb_modifier);
struct drm_gem_object *intel_fb_bo(const struct drm_framebuffer *fb);
#endif /* __INTEL_FB_H__ */

View File

@ -11,15 +11,16 @@
#include "intel_fb.h"
#include "intel_fb_bo.h"
void intel_fb_bo_framebuffer_fini(struct drm_i915_gem_object *obj)
void intel_fb_bo_framebuffer_fini(struct drm_gem_object *obj)
{
/* Nothing to do for i915 */
}
int intel_fb_bo_framebuffer_init(struct intel_framebuffer *intel_fb,
struct drm_i915_gem_object *obj,
struct drm_gem_object *_obj,
struct drm_mode_fb_cmd2 *mode_cmd)
{
struct drm_i915_gem_object *obj = to_intel_bo(_obj);
struct drm_i915_private *i915 = to_i915(obj->base.dev);
unsigned int tiling, stride;
@ -74,7 +75,7 @@ int intel_fb_bo_framebuffer_init(struct intel_framebuffer *intel_fb,
return 0;
}
struct drm_i915_gem_object *
struct drm_gem_object *
intel_fb_bo_lookup_valid_bo(struct drm_i915_private *i915,
struct drm_file *filp,
const struct drm_mode_fb_cmd2 *mode_cmd)
@ -93,5 +94,5 @@ intel_fb_bo_lookup_valid_bo(struct drm_i915_private *i915,
return ERR_PTR(-EREMOTE);
}
return obj;
return intel_bo_to_drm_bo(obj);
}

View File

@ -7,18 +7,18 @@
#define __INTEL_FB_BO_H__
struct drm_file;
struct drm_mode_fb_cmd2;
struct drm_i915_gem_object;
struct drm_gem_object;
struct drm_i915_private;
struct drm_mode_fb_cmd2;
struct intel_framebuffer;
void intel_fb_bo_framebuffer_fini(struct drm_i915_gem_object *obj);
void intel_fb_bo_framebuffer_fini(struct drm_gem_object *obj);
int intel_fb_bo_framebuffer_init(struct intel_framebuffer *intel_fb,
struct drm_i915_gem_object *obj,
struct drm_gem_object *obj,
struct drm_mode_fb_cmd2 *mode_cmd);
struct drm_i915_gem_object *
struct drm_gem_object *
intel_fb_bo_lookup_valid_bo(struct drm_i915_private *i915,
struct drm_file *filp,
const struct drm_mode_fb_cmd2 *user_mode_cmd);

View File

@ -26,7 +26,8 @@ intel_fb_pin_to_dpt(const struct drm_framebuffer *fb,
{
struct drm_device *dev = fb->dev;
struct drm_i915_private *dev_priv = to_i915(dev);
struct drm_i915_gem_object *obj = intel_fb_obj(fb);
struct drm_gem_object *_obj = intel_fb_bo(fb);
struct drm_i915_gem_object *obj = to_intel_bo(_obj);
struct i915_gem_ww_ctx ww;
struct i915_vma *vma;
int ret;
@ -111,7 +112,8 @@ intel_fb_pin_to_ggtt(const struct drm_framebuffer *fb,
{
struct drm_device *dev = fb->dev;
struct drm_i915_private *dev_priv = to_i915(dev);
struct drm_i915_gem_object *obj = intel_fb_obj(fb);
struct drm_gem_object *_obj = intel_fb_bo(fb);
struct drm_i915_gem_object *obj = to_intel_bo(_obj);
intel_wakeref_t wakeref;
struct i915_gem_ww_ctx ww;
struct i915_vma *vma;
@ -274,9 +276,11 @@ int intel_plane_pin_fb(struct intel_plane_state *plane_state)
* will trigger might_sleep() even if it won't actually sleep,
* which is the case when the fb has already been pinned.
*/
if (intel_plane_needs_physical(plane))
plane_state->phys_dma_addr =
i915_gem_object_get_dma_address(intel_fb_obj(&fb->base), 0);
if (intel_plane_needs_physical(plane)) {
struct drm_i915_gem_object *obj = to_intel_bo(intel_fb_bo(&fb->base));
plane_state->phys_dma_addr = i915_gem_object_get_dma_address(obj, 0);
}
} else {
unsigned int alignment = intel_plane_fb_min_alignment(plane_state);

View File

@ -38,6 +38,7 @@
* forcibly disable it to allow proper screen updates.
*/
#include <linux/debugfs.h>
#include <linux/string_helpers.h>
#include <drm/drm_blend.h>
@ -1792,7 +1793,6 @@ static void intel_fbc_underrun_work_fn(struct work_struct *work)
{
struct intel_fbc *fbc = container_of(work, typeof(*fbc), underrun_work);
struct intel_display *display = fbc->display;
struct drm_i915_private *i915 = to_i915(display->drm);
mutex_lock(&fbc->lock);
@ -1805,7 +1805,7 @@ static void intel_fbc_underrun_work_fn(struct work_struct *work)
intel_fbc_deactivate(fbc, "FIFO underrun");
if (!fbc->flip_pending)
intel_crtc_wait_for_next_vblank(intel_crtc_for_pipe(i915, fbc->state.plane->pipe));
intel_crtc_wait_for_next_vblank(intel_crtc_for_pipe(display, fbc->state.plane->pipe));
__intel_fbc_disable(fbc);
out:
mutex_unlock(&fbc->lock);

View File

@ -41,12 +41,11 @@
#include <drm/drm_crtc_helper.h>
#include <drm/drm_fb_helper.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_gem.h>
#include <drm/drm_gem_framebuffer_helper.h>
#include "gem/i915_gem_mman.h"
#include "gem/i915_gem_object.h"
#include "i915_drv.h"
#include "intel_bo.h"
#include "intel_display_types.h"
#include "intel_fb.h"
#include "intel_fb_pin.h"
@ -129,10 +128,9 @@ static int intel_fbdev_pan_display(struct fb_var_screeninfo *var,
static int intel_fbdev_mmap(struct fb_info *info, struct vm_area_struct *vma)
{
struct intel_fbdev *fbdev = to_intel_fbdev(info->par);
struct drm_gem_object *bo = drm_gem_fb_get_obj(&fbdev->fb->base, 0);
struct drm_i915_gem_object *obj = to_intel_bo(bo);
struct drm_gem_object *obj = drm_gem_fb_get_obj(&fbdev->fb->base, 0);
return i915_gem_fb_mmap(obj, vma);
return intel_bo_fb_mmap(obj, vma);
}
static void intel_fbdev_fb_destroy(struct fb_info *info)
@ -187,7 +185,7 @@ static int intelfb_create(struct drm_fb_helper *helper,
struct i915_vma *vma;
unsigned long flags = 0;
bool prealloc = false;
struct drm_i915_gem_object *obj;
struct drm_gem_object *obj;
int ret;
mutex_lock(&ifbdev->hpd_lock);
@ -209,7 +207,7 @@ static int intelfb_create(struct drm_fb_helper *helper,
drm_framebuffer_put(&fb->base);
fb = NULL;
}
if (!fb || drm_WARN_ON(dev, !intel_fb_obj(&fb->base))) {
if (!fb || drm_WARN_ON(dev, !intel_fb_bo(&fb->base))) {
drm_dbg_kms(&dev_priv->drm,
"no BIOS fb, allocating a new one\n");
fb = intel_fbdev_fb_alloc(helper, sizes);
@ -247,7 +245,7 @@ static int intelfb_create(struct drm_fb_helper *helper,
info->fbops = &intelfb_ops;
obj = intel_fb_obj(&fb->base);
obj = intel_fb_bo(&fb->base);
ret = intel_fbdev_fb_fill_info(dev_priv, info, obj, vma);
if (ret)
@ -259,7 +257,7 @@ static int intelfb_create(struct drm_fb_helper *helper,
* If the object is stolen however, it will be full of whatever
* garbage was left in there.
*/
if (!i915_gem_object_is_shmem(obj) && !prealloc)
if (!intel_bo_is_shmem(obj) && !prealloc)
memset_io(info->screen_base, 0, info->screen_size);
/* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */
@ -323,8 +321,7 @@ static bool intel_fbdev_init_bios(struct drm_device *dev,
to_intel_plane(crtc->base.primary);
struct intel_plane_state *plane_state =
to_intel_plane_state(plane->base.state);
struct drm_i915_gem_object *obj =
intel_fb_obj(plane_state->uapi.fb);
struct drm_gem_object *obj = intel_fb_bo(plane_state->uapi.fb);
if (!crtc_state->uapi.active) {
drm_dbg_kms(&i915->drm,
@ -340,12 +337,12 @@ static bool intel_fbdev_init_bios(struct drm_device *dev,
continue;
}
if (intel_bo_to_drm_bo(obj)->size > max_size) {
if (obj->size > max_size) {
drm_dbg_kms(&i915->drm,
"found possible fb from [PLANE:%d:%s]\n",
plane->base.base.id, plane->base.name);
fb = to_intel_framebuffer(plane_state->uapi.fb);
max_size = intel_bo_to_drm_bo(obj)->size;
max_size = obj->size;
}
}
@ -533,7 +530,7 @@ void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous
* full of whatever garbage was left in there.
*/
if (state == FBINFO_STATE_RUNNING &&
!i915_gem_object_is_shmem(intel_fb_obj(&ifbdev->fb->base)))
!intel_bo_is_shmem(intel_fb_bo(&ifbdev->fb->base)))
memset_io(info->screen_base, 0, info->screen_size);
drm_fb_helper_set_suspend(&ifbdev->helper, state);

View File

@ -9,6 +9,7 @@
#include "i915_drv.h"
#include "intel_display_types.h"
#include "intel_fb.h"
#include "intel_fbdev_fb.h"
struct intel_framebuffer *intel_fbdev_fb_alloc(struct drm_fb_helper *helper,
@ -60,15 +61,16 @@ struct intel_framebuffer *intel_fbdev_fb_alloc(struct drm_fb_helper *helper,
return ERR_PTR(-ENOMEM);
}
fb = intel_framebuffer_create(obj, &mode_cmd);
fb = intel_framebuffer_create(intel_bo_to_drm_bo(obj), &mode_cmd);
i915_gem_object_put(obj);
return to_intel_framebuffer(fb);
}
int intel_fbdev_fb_fill_info(struct drm_i915_private *i915, struct fb_info *info,
struct drm_i915_gem_object *obj, struct i915_vma *vma)
struct drm_gem_object *_obj, struct i915_vma *vma)
{
struct drm_i915_gem_object *obj = to_intel_bo(_obj);
struct i915_gem_ww_ctx ww;
void __iomem *vaddr;
int ret;

View File

@ -8,7 +8,7 @@
struct drm_fb_helper;
struct drm_fb_helper_surface_size;
struct drm_i915_gem_object;
struct drm_gem_object;
struct drm_i915_private;
struct fb_info;
struct i915_vma;
@ -16,6 +16,6 @@ struct i915_vma;
struct intel_framebuffer *intel_fbdev_fb_alloc(struct drm_fb_helper *helper,
struct drm_fb_helper_surface_size *sizes);
int intel_fbdev_fb_fill_info(struct drm_i915_private *i915, struct fb_info *info,
struct drm_i915_gem_object *obj, struct i915_vma *vma);
struct drm_gem_object *obj, struct i915_vma *vma);
#endif

View File

@ -137,6 +137,7 @@ void intel_fdi_link_train(struct intel_crtc *crtc,
*/
int intel_fdi_add_affected_crtcs(struct intel_atomic_state *state)
{
struct intel_display *display = to_intel_display(state);
struct drm_i915_private *i915 = to_i915(state->base.dev);
const struct intel_crtc_state *old_crtc_state;
const struct intel_crtc_state *new_crtc_state;
@ -145,7 +146,7 @@ int intel_fdi_add_affected_crtcs(struct intel_atomic_state *state)
if (!IS_IVYBRIDGE(i915) || INTEL_NUM_PIPES(i915) != 3)
return 0;
crtc = intel_crtc_for_pipe(i915, PIPE_C);
crtc = intel_crtc_for_pipe(display, PIPE_C);
new_crtc_state = intel_atomic_get_new_crtc_state(state, crtc);
if (!new_crtc_state)
return 0;
@ -157,7 +158,7 @@ int intel_fdi_add_affected_crtcs(struct intel_atomic_state *state)
if (!old_crtc_state->fdi_lanes)
return 0;
crtc = intel_crtc_for_pipe(i915, PIPE_B);
crtc = intel_crtc_for_pipe(display, PIPE_B);
new_crtc_state = intel_atomic_get_crtc_state(&state->base, crtc);
if (IS_ERR(new_crtc_state))
return PTR_ERR(new_crtc_state);
@ -184,6 +185,7 @@ static int ilk_check_fdi_lanes(struct drm_device *dev, enum pipe pipe,
struct intel_crtc_state *pipe_config,
enum pipe *pipe_to_reduce)
{
struct intel_display *display = to_intel_display(dev);
struct drm_i915_private *dev_priv = to_i915(dev);
struct drm_atomic_state *state = pipe_config->uapi.state;
struct intel_crtc *other_crtc;
@ -223,7 +225,7 @@ static int ilk_check_fdi_lanes(struct drm_device *dev, enum pipe pipe,
if (pipe_config->fdi_lanes <= 2)
return 0;
other_crtc = intel_crtc_for_pipe(dev_priv, PIPE_C);
other_crtc = intel_crtc_for_pipe(display, PIPE_C);
other_crtc_state =
intel_atomic_get_crtc_state(state, other_crtc);
if (IS_ERR(other_crtc_state))
@ -244,7 +246,7 @@ static int ilk_check_fdi_lanes(struct drm_device *dev, enum pipe pipe,
return -EINVAL;
}
other_crtc = intel_crtc_for_pipe(dev_priv, PIPE_B);
other_crtc = intel_crtc_for_pipe(display, PIPE_B);
other_crtc_state =
intel_atomic_get_crtc_state(state, other_crtc);
if (IS_ERR(other_crtc_state))

View File

@ -57,6 +57,7 @@
static bool ivb_can_enable_err_int(struct drm_device *dev)
{
struct intel_display *display = to_intel_display(dev);
struct drm_i915_private *dev_priv = to_i915(dev);
struct intel_crtc *crtc;
enum pipe pipe;
@ -64,7 +65,7 @@ static bool ivb_can_enable_err_int(struct drm_device *dev)
lockdep_assert_held(&dev_priv->irq_lock);
for_each_pipe(dev_priv, pipe) {
crtc = intel_crtc_for_pipe(dev_priv, pipe);
crtc = intel_crtc_for_pipe(display, pipe);
if (crtc->cpu_fifo_underrun_disabled)
return false;
@ -75,6 +76,7 @@ static bool ivb_can_enable_err_int(struct drm_device *dev)
static bool cpt_can_enable_serr_int(struct drm_device *dev)
{
struct intel_display *display = to_intel_display(dev);
struct drm_i915_private *dev_priv = to_i915(dev);
enum pipe pipe;
struct intel_crtc *crtc;
@ -82,7 +84,7 @@ static bool cpt_can_enable_serr_int(struct drm_device *dev)
lockdep_assert_held(&dev_priv->irq_lock);
for_each_pipe(dev_priv, pipe) {
crtc = intel_crtc_for_pipe(dev_priv, pipe);
crtc = intel_crtc_for_pipe(display, pipe);
if (crtc->pch_fifo_underrun_disabled)
return false;
@ -93,6 +95,7 @@ static bool cpt_can_enable_serr_int(struct drm_device *dev)
static void i9xx_check_fifo_underruns(struct intel_crtc *crtc)
{
struct intel_display *display = to_intel_display(crtc);
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
i915_reg_t reg = PIPESTAT(dev_priv, crtc->pipe);
u32 enable_mask;
@ -106,7 +109,7 @@ static void i9xx_check_fifo_underruns(struct intel_crtc *crtc)
intel_de_write(dev_priv, reg, enable_mask | PIPE_FIFO_UNDERRUN_STATUS);
intel_de_posting_read(dev_priv, reg);
trace_intel_cpu_fifo_underrun(dev_priv, crtc->pipe);
trace_intel_cpu_fifo_underrun(display, crtc->pipe);
drm_err(&dev_priv->drm, "pipe %c underrun\n", pipe_name(crtc->pipe));
}
@ -147,6 +150,7 @@ static void ilk_set_fifo_underrun_reporting(struct drm_device *dev,
static void ivb_check_fifo_underruns(struct intel_crtc *crtc)
{
struct intel_display *display = to_intel_display(crtc);
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
enum pipe pipe = crtc->pipe;
u32 err_int = intel_de_read(dev_priv, GEN7_ERR_INT);
@ -159,7 +163,7 @@ static void ivb_check_fifo_underruns(struct intel_crtc *crtc)
intel_de_write(dev_priv, GEN7_ERR_INT, ERR_INT_FIFO_UNDERRUN(pipe));
intel_de_posting_read(dev_priv, GEN7_ERR_INT);
trace_intel_cpu_fifo_underrun(dev_priv, pipe);
trace_intel_cpu_fifo_underrun(display, pipe);
drm_err(&dev_priv->drm, "fifo underrun on pipe %c\n", pipe_name(pipe));
}
@ -235,6 +239,7 @@ static void ibx_set_fifo_underrun_reporting(struct drm_device *dev,
static void cpt_check_pch_fifo_underruns(struct intel_crtc *crtc)
{
struct intel_display *display = to_intel_display(crtc);
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
enum pipe pch_transcoder = crtc->pipe;
u32 serr_int = intel_de_read(dev_priv, SERR_INT);
@ -248,7 +253,7 @@ static void cpt_check_pch_fifo_underruns(struct intel_crtc *crtc)
SERR_INT_TRANS_FIFO_UNDERRUN(pch_transcoder));
intel_de_posting_read(dev_priv, SERR_INT);
trace_intel_pch_fifo_underrun(dev_priv, pch_transcoder);
trace_intel_pch_fifo_underrun(display, pch_transcoder);
drm_err(&dev_priv->drm, "pch fifo underrun on pch transcoder %c\n",
pipe_name(pch_transcoder));
}
@ -282,8 +287,9 @@ static void cpt_set_fifo_underrun_reporting(struct drm_device *dev,
static bool __intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev,
enum pipe pipe, bool enable)
{
struct intel_display *display = to_intel_display(dev);
struct drm_i915_private *dev_priv = to_i915(dev);
struct intel_crtc *crtc = intel_crtc_for_pipe(dev_priv, pipe);
struct intel_crtc *crtc = intel_crtc_for_pipe(display, pipe);
bool old;
lockdep_assert_held(&dev_priv->irq_lock);
@ -351,8 +357,9 @@ bool intel_set_pch_fifo_underrun_reporting(struct drm_i915_private *dev_priv,
enum pipe pch_transcoder,
bool enable)
{
struct intel_display *display = &dev_priv->display;
struct intel_crtc *crtc =
intel_crtc_for_pipe(dev_priv, pch_transcoder);
intel_crtc_for_pipe(display, pch_transcoder);
unsigned long flags;
bool old;
@ -395,7 +402,8 @@ bool intel_set_pch_fifo_underrun_reporting(struct drm_i915_private *dev_priv,
void intel_cpu_fifo_underrun_irq_handler(struct drm_i915_private *dev_priv,
enum pipe pipe)
{
struct intel_crtc *crtc = intel_crtc_for_pipe(dev_priv, pipe);
struct intel_display *display = &dev_priv->display;
struct intel_crtc *crtc = intel_crtc_for_pipe(display, pipe);
u32 underruns = 0;
/* We may be called too early in init, thanks BIOS! */
@ -427,7 +435,7 @@ void intel_cpu_fifo_underrun_irq_handler(struct drm_i915_private *dev_priv,
}
if (intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false)) {
trace_intel_cpu_fifo_underrun(dev_priv, pipe);
trace_intel_cpu_fifo_underrun(display, pipe);
if (DISPLAY_VER(dev_priv) >= 11)
drm_err(&dev_priv->drm, "CPU pipe %c FIFO underrun: %s%s%s%s\n",
@ -455,9 +463,11 @@ void intel_cpu_fifo_underrun_irq_handler(struct drm_i915_private *dev_priv,
void intel_pch_fifo_underrun_irq_handler(struct drm_i915_private *dev_priv,
enum pipe pch_transcoder)
{
struct intel_display *display = &dev_priv->display;
if (intel_set_pch_fifo_underrun_reporting(dev_priv, pch_transcoder,
false)) {
trace_intel_pch_fifo_underrun(dev_priv, pch_transcoder);
trace_intel_pch_fifo_underrun(display, pch_transcoder);
drm_err(&dev_priv->drm, "PCH transcoder %c FIFO underrun\n",
pipe_name(pch_transcoder));
}

View File

@ -55,9 +55,11 @@
* cancelled as soon as busyness is detected.
*/
#include "gem/i915_gem_object_frontbuffer.h"
#include <drm/drm_gem.h>
#include "i915_active.h"
#include "i915_drv.h"
#include "intel_bo.h"
#include "intel_display_trace.h"
#include "intel_display_types.h"
#include "intel_dp.h"
@ -93,7 +95,7 @@ static void frontbuffer_flush(struct drm_i915_private *i915,
if (!frontbuffer_bits)
return;
trace_intel_frontbuffer_flush(i915, frontbuffer_bits, origin);
trace_intel_frontbuffer_flush(display, frontbuffer_bits, origin);
might_sleep();
intel_td_flush(i915);
@ -173,17 +175,17 @@ void __intel_fb_invalidate(struct intel_frontbuffer *front,
enum fb_op_origin origin,
unsigned int frontbuffer_bits)
{
struct drm_i915_private *i915 = intel_bo_to_i915(front->obj);
struct intel_display *display = &i915->display;
struct intel_display *display = to_intel_display(front->obj->dev);
struct drm_i915_private *i915 = to_i915(display->drm);
if (origin == ORIGIN_CS) {
spin_lock(&i915->display.fb_tracking.lock);
i915->display.fb_tracking.busy_bits |= frontbuffer_bits;
i915->display.fb_tracking.flip_bits &= ~frontbuffer_bits;
spin_unlock(&i915->display.fb_tracking.lock);
spin_lock(&display->fb_tracking.lock);
display->fb_tracking.busy_bits |= frontbuffer_bits;
display->fb_tracking.flip_bits &= ~frontbuffer_bits;
spin_unlock(&display->fb_tracking.lock);
}
trace_intel_frontbuffer_invalidate(i915, frontbuffer_bits, origin);
trace_intel_frontbuffer_invalidate(display, frontbuffer_bits, origin);
might_sleep();
intel_psr_invalidate(display, frontbuffer_bits, origin);
@ -195,14 +197,15 @@ void __intel_fb_flush(struct intel_frontbuffer *front,
enum fb_op_origin origin,
unsigned int frontbuffer_bits)
{
struct drm_i915_private *i915 = intel_bo_to_i915(front->obj);
struct intel_display *display = to_intel_display(front->obj->dev);
struct drm_i915_private *i915 = to_i915(display->drm);
if (origin == ORIGIN_CS) {
spin_lock(&i915->display.fb_tracking.lock);
spin_lock(&display->fb_tracking.lock);
/* Filter out new bits since rendering started. */
frontbuffer_bits &= i915->display.fb_tracking.busy_bits;
i915->display.fb_tracking.busy_bits &= ~frontbuffer_bits;
spin_unlock(&i915->display.fb_tracking.lock);
frontbuffer_bits &= display->fb_tracking.busy_bits;
display->fb_tracking.busy_bits &= ~frontbuffer_bits;
spin_unlock(&display->fb_tracking.lock);
}
if (frontbuffer_bits)
@ -214,7 +217,7 @@ static void intel_frontbuffer_flush_work(struct work_struct *work)
struct intel_frontbuffer *front =
container_of(work, struct intel_frontbuffer, flush_work);
i915_gem_object_flush_if_display(front->obj);
intel_bo_flush_if_display(front->obj);
intel_frontbuffer_flush(front, ORIGIN_DIRTYFB);
intel_frontbuffer_put(front);
}
@ -255,31 +258,32 @@ static void frontbuffer_retire(struct i915_active *ref)
}
static void frontbuffer_release(struct kref *ref)
__releases(&intel_bo_to_i915(front->obj)->display.fb_tracking.lock)
__releases(&to_intel_display(front->obj->dev)->fb_tracking.lock)
{
struct intel_frontbuffer *ret, *front =
container_of(ref, typeof(*front), ref);
struct drm_i915_gem_object *obj = front->obj;
struct drm_gem_object *obj = front->obj;
struct intel_display *display = to_intel_display(obj->dev);
drm_WARN_ON(&intel_bo_to_i915(obj)->drm, atomic_read(&front->bits));
drm_WARN_ON(display->drm, atomic_read(&front->bits));
i915_ggtt_clear_scanout(obj);
i915_ggtt_clear_scanout(to_intel_bo(obj));
ret = i915_gem_object_set_frontbuffer(obj, NULL);
drm_WARN_ON(&intel_bo_to_i915(obj)->drm, ret);
spin_unlock(&intel_bo_to_i915(obj)->display.fb_tracking.lock);
ret = intel_bo_set_frontbuffer(obj, NULL);
drm_WARN_ON(display->drm, ret);
spin_unlock(&display->fb_tracking.lock);
i915_active_fini(&front->write);
kfree_rcu(front, rcu);
}
struct intel_frontbuffer *
intel_frontbuffer_get(struct drm_i915_gem_object *obj)
intel_frontbuffer_get(struct drm_gem_object *obj)
{
struct drm_i915_private *i915 = intel_bo_to_i915(obj);
struct drm_i915_private *i915 = to_i915(obj->dev);
struct intel_frontbuffer *front, *cur;
front = i915_gem_object_get_frontbuffer(obj);
front = intel_bo_get_frontbuffer(obj);
if (front)
return front;
@ -297,7 +301,7 @@ intel_frontbuffer_get(struct drm_i915_gem_object *obj)
INIT_WORK(&front->flush_work, intel_frontbuffer_flush_work);
spin_lock(&i915->display.fb_tracking.lock);
cur = i915_gem_object_set_frontbuffer(obj, front);
cur = intel_bo_set_frontbuffer(obj, front);
spin_unlock(&i915->display.fb_tracking.lock);
if (cur != front)
kfree(front);
@ -308,7 +312,7 @@ void intel_frontbuffer_put(struct intel_frontbuffer *front)
{
kref_put_lock(&front->ref,
frontbuffer_release,
&intel_bo_to_i915(front->obj)->display.fb_tracking.lock);
&to_intel_display(front->obj->dev)->fb_tracking.lock);
}
/**
@ -337,13 +341,17 @@ void intel_frontbuffer_track(struct intel_frontbuffer *old,
BUILD_BUG_ON(I915_MAX_PLANES > INTEL_FRONTBUFFER_BITS_PER_PIPE);
if (old) {
drm_WARN_ON(&intel_bo_to_i915(old->obj)->drm,
struct intel_display *display = to_intel_display(old->obj->dev);
drm_WARN_ON(display->drm,
!(atomic_read(&old->bits) & frontbuffer_bits));
atomic_andnot(frontbuffer_bits, &old->bits);
}
if (new) {
drm_WARN_ON(&intel_bo_to_i915(new->obj)->drm,
struct intel_display *display = to_intel_display(new->obj->dev);
drm_WARN_ON(display->drm,
atomic_read(&new->bits) & frontbuffer_bits);
atomic_or(frontbuffer_bits, &new->bits);
}

View File

@ -30,6 +30,7 @@
#include "i915_active_types.h"
struct drm_gem_object;
struct drm_i915_private;
enum fb_op_origin {
@ -44,7 +45,7 @@ struct intel_frontbuffer {
struct kref ref;
atomic_t bits;
struct i915_active write;
struct drm_i915_gem_object *obj;
struct drm_gem_object *obj;
struct rcu_head rcu;
struct work_struct flush_work;
@ -77,7 +78,7 @@ void intel_frontbuffer_flip(struct drm_i915_private *i915,
void intel_frontbuffer_put(struct intel_frontbuffer *front);
struct intel_frontbuffer *
intel_frontbuffer_get(struct drm_i915_gem_object *obj);
intel_frontbuffer_get(struct drm_gem_object *obj);
void __intel_fb_invalidate(struct intel_frontbuffer *front,
enum fb_op_origin origin,

File diff suppressed because it is too large Load Diff

View File

@ -19,18 +19,19 @@ struct intel_hdcp_gsc_message {
void *hdcp_cmd_out;
};
bool intel_hdcp_gsc_cs_required(struct drm_i915_private *i915)
bool intel_hdcp_gsc_cs_required(struct intel_display *display)
{
return DISPLAY_VER(i915) >= 14;
return DISPLAY_VER(display) >= 14;
}
bool intel_hdcp_gsc_check_status(struct drm_i915_private *i915)
bool intel_hdcp_gsc_check_status(struct intel_display *display)
{
struct drm_i915_private *i915 = to_i915(display->drm);
struct intel_gt *gt = i915->media_gt;
struct intel_gsc_uc *gsc = gt ? &gt->uc.gsc : NULL;
if (!gsc || !intel_uc_fw_is_running(&gsc->fw)) {
drm_dbg_kms(&i915->drm,
drm_dbg_kms(display->drm,
"GSC components required for HDCP2.2 are not ready\n");
return false;
}
@ -106,8 +107,9 @@ static const struct i915_hdcp_ops gsc_hdcp_ops = {
.close_hdcp_session = intel_hdcp_gsc_close_session,
};
static int intel_hdcp_gsc_hdcp2_init(struct drm_i915_private *i915)
static int intel_hdcp_gsc_hdcp2_init(struct intel_display *display)
{
struct drm_i915_private *i915 = to_i915(display->drm);
struct intel_hdcp_gsc_message *hdcp_message;
int ret;
@ -120,19 +122,19 @@ static int intel_hdcp_gsc_hdcp2_init(struct drm_i915_private *i915)
* NOTE: No need to lock the comp mutex here as it is already
* going to be taken before this function called
*/
i915->display.hdcp.hdcp_message = hdcp_message;
display->hdcp.hdcp_message = hdcp_message;
ret = intel_hdcp_gsc_initialize_message(i915, hdcp_message);
if (ret)
drm_err(&i915->drm, "Could not initialize hdcp_message\n");
drm_err(display->drm, "Could not initialize hdcp_message\n");
return ret;
}
static void intel_hdcp_gsc_free_message(struct drm_i915_private *i915)
static void intel_hdcp_gsc_free_message(struct intel_display *display)
{
struct intel_hdcp_gsc_message *hdcp_message =
i915->display.hdcp.hdcp_message;
display->hdcp.hdcp_message;
hdcp_message->hdcp_cmd_in = NULL;
hdcp_message->hdcp_cmd_out = NULL;
@ -140,7 +142,7 @@ static void intel_hdcp_gsc_free_message(struct drm_i915_private *i915)
kfree(hdcp_message);
}
int intel_hdcp_gsc_init(struct drm_i915_private *i915)
int intel_hdcp_gsc_init(struct intel_display *display)
{
struct i915_hdcp_arbiter *data;
int ret;
@ -149,20 +151,20 @@ int intel_hdcp_gsc_init(struct drm_i915_private *i915)
if (!data)
return -ENOMEM;
mutex_lock(&i915->display.hdcp.hdcp_mutex);
i915->display.hdcp.arbiter = data;
i915->display.hdcp.arbiter->hdcp_dev = i915->drm.dev;
i915->display.hdcp.arbiter->ops = &gsc_hdcp_ops;
ret = intel_hdcp_gsc_hdcp2_init(i915);
mutex_unlock(&i915->display.hdcp.hdcp_mutex);
mutex_lock(&display->hdcp.hdcp_mutex);
display->hdcp.arbiter = data;
display->hdcp.arbiter->hdcp_dev = display->drm->dev;
display->hdcp.arbiter->ops = &gsc_hdcp_ops;
ret = intel_hdcp_gsc_hdcp2_init(display);
mutex_unlock(&display->hdcp.hdcp_mutex);
return ret;
}
void intel_hdcp_gsc_fini(struct drm_i915_private *i915)
void intel_hdcp_gsc_fini(struct intel_display *display)
{
intel_hdcp_gsc_free_message(i915);
kfree(i915->display.hdcp.arbiter);
intel_hdcp_gsc_free_message(display);
kfree(display->hdcp.arbiter);
}
static int intel_gsc_send_sync(struct drm_i915_private *i915,

View File

@ -10,14 +10,15 @@
#include <linux/types.h>
struct drm_i915_private;
struct intel_display;
struct intel_hdcp_gsc_message;
bool intel_hdcp_gsc_cs_required(struct drm_i915_private *i915);
bool intel_hdcp_gsc_cs_required(struct intel_display *display);
ssize_t intel_hdcp_gsc_msg_send(struct drm_i915_private *i915, u8 *msg_in,
size_t msg_in_len, u8 *msg_out,
size_t msg_out_len);
int intel_hdcp_gsc_init(struct drm_i915_private *i915);
void intel_hdcp_gsc_fini(struct drm_i915_private *i915);
bool intel_hdcp_gsc_check_status(struct drm_i915_private *i915);
int intel_hdcp_gsc_init(struct intel_display *display);
void intel_hdcp_gsc_fini(struct intel_display *display);
bool intel_hdcp_gsc_check_status(struct intel_display *display);
#endif /* __INTEL_HDCP_GCS_H__ */

View File

@ -46,12 +46,12 @@ intel_hdcp_gsc_initiate_session(struct device *dev, struct hdcp_port_data *data,
(u8 *)&session_init_out,
sizeof(session_init_out));
if (byte < 0) {
drm_dbg_kms(&i915->drm, "intel_hdcp_gsc_msg_send failed. %zd\n", byte);
drm_dbg_kms(display->drm, "intel_hdcp_gsc_msg_send failed. %zd\n", byte);
return byte;
}
if (session_init_out.header.status != FW_HDCP_STATUS_SUCCESS) {
drm_dbg_kms(&i915->drm, "FW cmd 0x%08X Failed. Status: 0x%X\n",
drm_dbg_kms(display->drm, "FW cmd 0x%08X Failed. Status: 0x%X\n",
WIRED_INITIATE_HDCP2_SESSION,
session_init_out.header.status);
return -EIO;
@ -108,12 +108,12 @@ intel_hdcp_gsc_verify_receiver_cert_prepare_km(struct device *dev,
(u8 *)&verify_rxcert_out,
sizeof(verify_rxcert_out));
if (byte < 0) {
drm_dbg_kms(&i915->drm, "intel_hdcp_gsc_msg_send failed: %zd\n", byte);
drm_dbg_kms(display->drm, "intel_hdcp_gsc_msg_send failed: %zd\n", byte);
return byte;
}
if (verify_rxcert_out.header.status != FW_HDCP_STATUS_SUCCESS) {
drm_dbg_kms(&i915->drm, "FW cmd 0x%08X Failed. Status: 0x%X\n",
drm_dbg_kms(display->drm, "FW cmd 0x%08X Failed. Status: 0x%X\n",
WIRED_VERIFY_RECEIVER_CERT,
verify_rxcert_out.header.status);
return -EIO;
@ -171,12 +171,12 @@ intel_hdcp_gsc_verify_hprime(struct device *dev, struct hdcp_port_data *data,
(u8 *)&send_hprime_out,
sizeof(send_hprime_out));
if (byte < 0) {
drm_dbg_kms(&i915->drm, "intel_hdcp_gsc_msg_send failed. %zd\n", byte);
drm_dbg_kms(display->drm, "intel_hdcp_gsc_msg_send failed. %zd\n", byte);
return byte;
}
if (send_hprime_out.header.status != FW_HDCP_STATUS_SUCCESS) {
drm_dbg_kms(&i915->drm, "FW cmd 0x%08X Failed. Status: 0x%X\n",
drm_dbg_kms(display->drm, "FW cmd 0x%08X Failed. Status: 0x%X\n",
WIRED_AKE_SEND_HPRIME, send_hprime_out.header.status);
return -EIO;
}
@ -222,12 +222,12 @@ intel_hdcp_gsc_store_pairing_info(struct device *dev, struct hdcp_port_data *dat
(u8 *)&pairing_info_out,
sizeof(pairing_info_out));
if (byte < 0) {
drm_dbg_kms(&i915->drm, "intel_hdcp_gsc_msg_send failed. %zd\n", byte);
drm_dbg_kms(display->drm, "intel_hdcp_gsc_msg_send failed. %zd\n", byte);
return byte;
}
if (pairing_info_out.header.status != FW_HDCP_STATUS_SUCCESS) {
drm_dbg_kms(&i915->drm, "FW cmd 0x%08X failed. Status: 0x%X\n",
drm_dbg_kms(display->drm, "FW cmd 0x%08X failed. Status: 0x%X\n",
WIRED_AKE_SEND_PAIRING_INFO,
pairing_info_out.header.status);
return -EIO;
@ -269,12 +269,12 @@ intel_hdcp_gsc_initiate_locality_check(struct device *dev,
byte = intel_hdcp_gsc_msg_send(i915, (u8 *)&lc_init_in, sizeof(lc_init_in),
(u8 *)&lc_init_out, sizeof(lc_init_out));
if (byte < 0) {
drm_dbg_kms(&i915->drm, "intel_hdcp_gsc_msg_send failed. %zd\n", byte);
drm_dbg_kms(display->drm, "intel_hdcp_gsc_msg_send failed. %zd\n", byte);
return byte;
}
if (lc_init_out.header.status != FW_HDCP_STATUS_SUCCESS) {
drm_dbg_kms(&i915->drm, "FW cmd 0x%08X Failed. status: 0x%X\n",
drm_dbg_kms(display->drm, "FW cmd 0x%08X Failed. status: 0x%X\n",
WIRED_INIT_LOCALITY_CHECK, lc_init_out.header.status);
return -EIO;
}
@ -323,12 +323,12 @@ intel_hdcp_gsc_verify_lprime(struct device *dev, struct hdcp_port_data *data,
(u8 *)&verify_lprime_out,
sizeof(verify_lprime_out));
if (byte < 0) {
drm_dbg_kms(&i915->drm, "intel_hdcp_gsc_msg_send failed. %zd\n", byte);
drm_dbg_kms(display->drm, "intel_hdcp_gsc_msg_send failed. %zd\n", byte);
return byte;
}
if (verify_lprime_out.header.status != FW_HDCP_STATUS_SUCCESS) {
drm_dbg_kms(&i915->drm, "FW cmd 0x%08X failed. status: 0x%X\n",
drm_dbg_kms(display->drm, "FW cmd 0x%08X failed. status: 0x%X\n",
WIRED_VALIDATE_LOCALITY,
verify_lprime_out.header.status);
return -EIO;
@ -369,12 +369,12 @@ int intel_hdcp_gsc_get_session_key(struct device *dev,
byte = intel_hdcp_gsc_msg_send(i915, (u8 *)&get_skey_in, sizeof(get_skey_in),
(u8 *)&get_skey_out, sizeof(get_skey_out));
if (byte < 0) {
drm_dbg_kms(&i915->drm, "intel_hdcp_gsc_msg_send failed. %zd\n", byte);
drm_dbg_kms(display->drm, "intel_hdcp_gsc_msg_send failed. %zd\n", byte);
return byte;
}
if (get_skey_out.header.status != FW_HDCP_STATUS_SUCCESS) {
drm_dbg_kms(&i915->drm, "FW cmd 0x%08X failed. status: 0x%X\n",
drm_dbg_kms(display->drm, "FW cmd 0x%08X failed. status: 0x%X\n",
WIRED_GET_SESSION_KEY, get_skey_out.header.status);
return -EIO;
}
@ -435,12 +435,12 @@ intel_hdcp_gsc_repeater_check_flow_prepare_ack(struct device *dev,
(u8 *)&verify_repeater_out,
sizeof(verify_repeater_out));
if (byte < 0) {
drm_dbg_kms(&i915->drm, "intel_hdcp_gsc_msg_send failed. %zd\n", byte);
drm_dbg_kms(display->drm, "intel_hdcp_gsc_msg_send failed. %zd\n", byte);
return byte;
}
if (verify_repeater_out.header.status != FW_HDCP_STATUS_SUCCESS) {
drm_dbg_kms(&i915->drm, "FW cmd 0x%08X failed. status: 0x%X\n",
drm_dbg_kms(display->drm, "FW cmd 0x%08X failed. status: 0x%X\n",
WIRED_VERIFY_REPEATER,
verify_repeater_out.header.status);
return -EIO;
@ -504,12 +504,12 @@ int intel_hdcp_gsc_verify_mprime(struct device *dev,
sizeof(verify_mprime_out));
kfree(verify_mprime_in);
if (byte < 0) {
drm_dbg_kms(&i915->drm, "intel_hdcp_gsc_msg_send failed. %zd\n", byte);
drm_dbg_kms(display->drm, "intel_hdcp_gsc_msg_send failed. %zd\n", byte);
return byte;
}
if (verify_mprime_out.header.status != FW_HDCP_STATUS_SUCCESS) {
drm_dbg_kms(&i915->drm, "FW cmd 0x%08X failed. status: 0x%X\n",
drm_dbg_kms(display->drm, "FW cmd 0x%08X failed. status: 0x%X\n",
WIRED_REPEATER_AUTH_STREAM_REQ,
verify_mprime_out.header.status);
return -EIO;
@ -552,12 +552,12 @@ int intel_hdcp_gsc_enable_authentication(struct device *dev,
(u8 *)&enable_auth_out,
sizeof(enable_auth_out));
if (byte < 0) {
drm_dbg_kms(&i915->drm, "intel_hdcp_gsc_msg_send failed. %zd\n", byte);
drm_dbg_kms(display->drm, "intel_hdcp_gsc_msg_send failed. %zd\n", byte);
return byte;
}
if (enable_auth_out.header.status != FW_HDCP_STATUS_SUCCESS) {
drm_dbg_kms(&i915->drm, "FW cmd 0x%08X failed. status: 0x%X\n",
drm_dbg_kms(display->drm, "FW cmd 0x%08X failed. status: 0x%X\n",
WIRED_ENABLE_AUTH, enable_auth_out.header.status);
return -EIO;
}
@ -599,12 +599,12 @@ intel_hdcp_gsc_close_session(struct device *dev, struct hdcp_port_data *data)
(u8 *)&session_close_out,
sizeof(session_close_out));
if (byte < 0) {
drm_dbg_kms(&i915->drm, "intel_hdcp_gsc_msg_send failed. %zd\n", byte);
drm_dbg_kms(display->drm, "intel_hdcp_gsc_msg_send failed. %zd\n", byte);
return byte;
}
if (session_close_out.header.status != FW_HDCP_STATUS_SUCCESS) {
drm_dbg_kms(&i915->drm, "Session Close Failed. status: 0x%X\n",
drm_dbg_kms(display->drm, "Session Close Failed. status: 0x%X\n",
session_close_out.header.status);
return -EIO;
}

View File

@ -22,11 +22,12 @@ struct hdcp2_ske_send_eks;
struct hdcp2_rep_send_receiverid_list;
struct hdcp2_rep_send_ack;
struct hdcp2_rep_stream_ready;
struct intel_display;
ssize_t intel_hdcp_gsc_msg_send(struct drm_i915_private *i915, u8 *msg_in,
size_t msg_in_len, u8 *msg_out,
size_t msg_out_len);
bool intel_hdcp_gsc_check_status(struct drm_i915_private *i915);
bool intel_hdcp_gsc_check_status(struct intel_display *display);
int
intel_hdcp_gsc_initiate_session(struct device *dev, struct hdcp_port_data *data,
struct hdcp2_ake_init *ake_data);

View File

@ -0,0 +1,137 @@
/* SPDX-License-Identifier: MIT */
/* Copyright © 2024 Intel Corporation */
#ifndef __INTEL_HDCP_SHIM_H__
#define __INTEL_HDCP_SHIM_H__
#include <linux/types.h>
#include <drm/intel/i915_hdcp_interface.h>
enum transcoder;
struct intel_connector;
struct intel_digital_port;
enum check_link_response {
HDCP_LINK_PROTECTED = 0,
HDCP_TOPOLOGY_CHANGE,
HDCP_LINK_INTEGRITY_FAILURE,
HDCP_REAUTH_REQUEST
};
/*
* This structure serves as a translation layer between the generic HDCP code
* and the bus-specific code. What that means is that HDCP over HDMI differs
* from HDCP over DP, so to account for these differences, we need to
* communicate with the receiver through this shim.
*
* For completeness, the 2 buses differ in the following ways:
* - DP AUX vs. DDC
* HDCP registers on the receiver are set via DP AUX for DP, and
* they are set via DDC for HDMI.
* - Receiver register offsets
* The offsets of the registers are different for DP vs. HDMI
* - Receiver register masks/offsets
* For instance, the ready bit for the KSV fifo is in a different
* place on DP vs HDMI
* - Receiver register names
* Seriously. In the DP spec, the 16-bit register containing
* downstream information is called BINFO, on HDMI it's called
* BSTATUS. To confuse matters further, DP has a BSTATUS register
* with a completely different definition.
* - KSV FIFO
* On HDMI, the ksv fifo is read all at once, whereas on DP it must
* be read 3 keys at a time
* - Aksv output
* Since Aksv is hidden in hardware, there's different procedures
* to send it over DP AUX vs DDC
*/
struct intel_hdcp_shim {
/* Outputs the transmitter's An and Aksv values to the receiver. */
int (*write_an_aksv)(struct intel_digital_port *dig_port, u8 *an);
/* Reads the receiver's key selection vector */
int (*read_bksv)(struct intel_digital_port *dig_port, u8 *bksv);
/*
* Reads BINFO from DP receivers and BSTATUS from HDMI receivers. The
* definitions are the same in the respective specs, but the names are
* different. Call it BSTATUS since that's the name the HDMI spec
* uses and it was there first.
*/
int (*read_bstatus)(struct intel_digital_port *dig_port,
u8 *bstatus);
/* Determines whether a repeater is present downstream */
int (*repeater_present)(struct intel_digital_port *dig_port,
bool *repeater_present);
/* Reads the receiver's Ri' value */
int (*read_ri_prime)(struct intel_digital_port *dig_port, u8 *ri);
/* Determines if the receiver's KSV FIFO is ready for consumption */
int (*read_ksv_ready)(struct intel_digital_port *dig_port,
bool *ksv_ready);
/* Reads the ksv fifo for num_downstream devices */
int (*read_ksv_fifo)(struct intel_digital_port *dig_port,
int num_downstream, u8 *ksv_fifo);
/* Reads a 32-bit part of V' from the receiver */
int (*read_v_prime_part)(struct intel_digital_port *dig_port,
int i, u32 *part);
/* Enables HDCP signalling on the port */
int (*toggle_signalling)(struct intel_digital_port *dig_port,
enum transcoder cpu_transcoder,
bool enable);
/* Enable/Disable stream encryption on DP MST Transport Link */
int (*stream_encryption)(struct intel_connector *connector,
bool enable);
/* Ensures the link is still protected */
bool (*check_link)(struct intel_digital_port *dig_port,
struct intel_connector *connector);
/* Detects panel's hdcp capability. This is optional for HDMI. */
int (*hdcp_get_capability)(struct intel_digital_port *dig_port,
bool *hdcp_capable);
/* HDCP adaptation(DP/HDMI) required on the port */
enum hdcp_wired_protocol protocol;
/* Detects whether sink is HDCP2.2 capable */
int (*hdcp_2_2_get_capability)(struct intel_connector *connector,
bool *capable);
/* Write HDCP2.2 messages */
int (*write_2_2_msg)(struct intel_connector *connector,
void *buf, size_t size);
/* Read HDCP2.2 messages */
int (*read_2_2_msg)(struct intel_connector *connector,
u8 msg_id, void *buf, size_t size);
/*
* Implementation of DP HDCP2.2 Errata for the communication of stream
* type to Receivers. In DP HDCP2.2 Stream type is one of the input to
* the HDCP2.2 Cipher for En/De-Cryption. Not applicable for HDMI.
*/
int (*config_stream_type)(struct intel_connector *connector,
bool is_repeater, u8 type);
/* Enable/Disable HDCP 2.2 stream encryption on DP MST Transport Link */
int (*stream_2_2_encryption)(struct intel_connector *connector,
bool enable);
/* HDCP2.2 Link Integrity Check */
int (*check_2_2_link)(struct intel_digital_port *dig_port,
struct intel_connector *connector);
/* HDCP remote sink cap */
int (*get_remote_hdcp_capability)(struct intel_connector *connector,
bool *hdcp_capable, bool *hdcp2_capable);
};
#endif /* __INTEL_HDCP_SHIM_H__ */

View File

@ -38,8 +38,11 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_crtc.h>
#include <drm/drm_edid.h>
#include <drm/drm_probe_helper.h>
#include <drm/intel/intel_lpe_audio.h>
#include <media/cec-notifier.h>
#include "g4x_hdmi.h"
#include "i915_drv.h"
#include "i915_reg.h"
@ -55,6 +58,7 @@
#include "intel_gmbus.h"
#include "intel_hdcp.h"
#include "intel_hdcp_regs.h"
#include "intel_hdcp_shim.h"
#include "intel_hdmi.h"
#include "intel_lspcon.h"
#include "intel_panel.h"
@ -1310,8 +1314,8 @@ static int intel_hdmi_hdcp_write(struct intel_digital_port *dig_port,
memcpy(&write_buf[1], buffer, size);
msg.addr = DRM_HDCP_DDC_ADDR;
msg.flags = 0,
msg.len = size + 1,
msg.flags = 0;
msg.len = size + 1;
msg.buf = write_buf;
ret = i2c_transfer(ddc, &msg, 1);
@ -2053,7 +2057,7 @@ intel_hdmi_mode_valid(struct drm_connector *connector,
return status;
}
return intel_mode_valid_max_plane_size(dev_priv, mode, false);
return intel_mode_valid_max_plane_size(dev_priv, mode, 1);
}
bool intel_hdmi_bpc_possible(const struct intel_crtc_state *crtc_state,

View File

@ -21,8 +21,11 @@
* IN THE SOFTWARE.
*/
#include <linux/debugfs.h>
#include <linux/kernel.h>
#include <drm/drm_probe_helper.h>
#include "i915_drv.h"
#include "i915_irq.h"
#include "intel_display_power.h"

View File

@ -849,10 +849,11 @@ static void icp_hpd_irq_setup(struct drm_i915_private *dev_priv)
enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->display.hotplug.pch_hpd);
hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->display.hotplug.pch_hpd);
if (INTEL_PCH_TYPE(dev_priv) <= PCH_TGP)
intel_uncore_write(&dev_priv->uncore, SHPD_FILTER_CNT, SHPD_FILTER_CNT_500_ADJ);
else
intel_uncore_write(&dev_priv->uncore, SHPD_FILTER_CNT, SHPD_FILTER_CNT_250);
/*
* We reduce the value to 250us to be able to detect SHPD when an external display
* is connected. This is also expected of us as stated in DP1.4a Table 3-4.
*/
intel_uncore_write(&dev_priv->uncore, SHPD_FILTER_CNT, SHPD_FILTER_CNT_250);
ibx_display_interrupt_update(dev_priv, hotplug_irqs, enabled_irqs);
@ -1060,6 +1061,10 @@ static void mtp_hpd_irq_setup(struct drm_i915_private *i915)
enabled_irqs = intel_hpd_enabled_irqs(i915, i915->display.hotplug.pch_hpd);
hotplug_irqs = intel_hpd_hotplug_irqs(i915, i915->display.hotplug.pch_hpd);
/*
* Use 250us here to align with the DP1.4a(Table 3-4) spec as to what the
* SHPD_FILTER_CNT value should be.
*/
intel_de_write(i915, SHPD_FILTER_CNT, SHPD_FILTER_CNT_250);
mtp_hpd_invert(i915);

View File

@ -26,7 +26,6 @@ void intel_link_bw_init_limits(struct intel_atomic_state *state,
struct intel_link_bw_limits *limits)
{
struct intel_display *display = to_intel_display(state);
struct drm_i915_private *i915 = to_i915(state->base.dev);
enum pipe pipe;
limits->force_fec_pipes = 0;
@ -34,7 +33,7 @@ void intel_link_bw_init_limits(struct intel_atomic_state *state,
for_each_pipe(display, pipe) {
const struct intel_crtc_state *crtc_state =
intel_atomic_get_new_crtc_state(state,
intel_crtc_for_pipe(i915, pipe));
intel_crtc_for_pipe(display, pipe));
if (state->base.duplicated && crtc_state) {
limits->max_bpp_x16[pipe] = crtc_state->max_link_bpp_x16;

View File

@ -37,6 +37,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_crtc.h>
#include <drm/drm_edid.h>
#include <drm/drm_probe_helper.h>
#include "i915_drv.h"
#include "i915_reg.h"
@ -263,7 +264,7 @@ static void intel_pre_enable_lvds(struct intel_atomic_state *state,
temp |= LVDS_PIPE_SEL(pipe);
}
/* set the corresponsding LVDS_BORDER bit */
/* set the corresponding LVDS_BORDER bit */
temp &= ~LVDS_BORDER_ENABLE;
temp |= crtc_state->gmch_pfit.lvds_border_bits;

View File

@ -8,6 +8,7 @@
#include <drm/drm_atomic_uapi.h>
#include <drm/drm_atomic_state_helper.h>
#include <drm/drm_vblank.h>
#include "i915_drv.h"
#include "i915_reg.h"
@ -221,6 +222,7 @@ static u8 get_transcoder_pipes(struct drm_i915_private *i915,
static void get_portsync_pipes(struct intel_crtc *crtc,
u8 *master_pipe_mask, u8 *slave_pipes_mask)
{
struct intel_display *display = to_intel_display(crtc);
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
struct intel_crtc_state *crtc_state =
to_intel_crtc_state(crtc->base.state);
@ -243,7 +245,7 @@ static void get_portsync_pipes(struct intel_crtc *crtc,
*master_pipe_mask = get_transcoder_pipes(i915, BIT(master_transcoder));
drm_WARN_ON(&i915->drm, !is_power_of_2(*master_pipe_mask));
master_crtc = intel_crtc_for_pipe(i915, ffs(*master_pipe_mask) - 1);
master_crtc = intel_crtc_for_pipe(display, ffs(*master_pipe_mask) - 1);
master_crtc_state = to_intel_crtc_state(master_crtc->base.state);
*slave_pipes_mask = get_transcoder_pipes(i915, master_crtc_state->sync_mode_slaves_mask);
}
@ -375,6 +377,7 @@ static void intel_crtc_copy_hw_to_uapi_state(struct intel_crtc_state *crtc_state
static void
intel_sanitize_plane_mapping(struct drm_i915_private *i915)
{
struct intel_display *display = &i915->display;
struct intel_crtc *crtc;
if (DISPLAY_VER(i915) >= 4)
@ -396,7 +399,7 @@ intel_sanitize_plane_mapping(struct drm_i915_private *i915)
"[PLANE:%d:%s] attached to the wrong pipe, disabling plane\n",
plane->base.base.id, plane->base.name);
plane_crtc = intel_crtc_for_pipe(i915, pipe);
plane_crtc = intel_crtc_for_pipe(display, pipe);
intel_plane_disable_noatomic(plane_crtc, plane);
}
}
@ -490,8 +493,8 @@ static bool intel_sanitize_crtc(struct intel_crtc *crtc,
}
/* Disable any background color/etc. set by the BIOS */
intel_color_commit_noarm(crtc_state);
intel_color_commit_arm(crtc_state);
intel_color_commit_noarm(NULL, crtc_state);
intel_color_commit_arm(NULL, crtc_state);
}
if (!crtc_state->hw.active ||
@ -662,6 +665,7 @@ static void intel_sanitize_encoder(struct intel_encoder *encoder)
/* FIXME read out full plane state for all planes */
static void readout_plane_state(struct drm_i915_private *i915)
{
struct intel_display *display = &i915->display;
struct intel_plane *plane;
struct intel_crtc *crtc;
@ -674,7 +678,7 @@ static void readout_plane_state(struct drm_i915_private *i915)
visible = plane->get_hw_state(plane, &pipe);
crtc = intel_crtc_for_pipe(i915, pipe);
crtc = intel_crtc_for_pipe(display, pipe);
crtc_state = to_intel_crtc_state(crtc->base.state);
intel_set_plane_visible(crtc_state, plane_state, visible);
@ -695,6 +699,7 @@ static void readout_plane_state(struct drm_i915_private *i915)
static void intel_modeset_readout_hw_state(struct drm_i915_private *i915)
{
struct intel_display *display = &i915->display;
struct intel_cdclk_state *cdclk_state =
to_intel_cdclk_state(i915->display.cdclk.obj.state);
struct intel_dbuf_state *dbuf_state =
@ -743,7 +748,7 @@ static void intel_modeset_readout_hw_state(struct drm_i915_private *i915)
pipe = 0;
if (encoder->get_hw_state(encoder, &pipe)) {
crtc = intel_crtc_for_pipe(i915, pipe);
crtc = intel_crtc_for_pipe(display, pipe);
crtc_state = to_intel_crtc_state(crtc->base.state);
encoder->base.crtc = &crtc->base;
@ -955,6 +960,7 @@ static void intel_early_display_was(struct drm_i915_private *i915)
void intel_modeset_setup_hw_state(struct drm_i915_private *i915,
struct drm_modeset_acquire_ctx *ctx)
{
struct intel_display *display = &i915->display;
struct intel_encoder *encoder;
struct intel_crtc *crtc;
intel_wakeref_t wakeref;
@ -982,7 +988,7 @@ void intel_modeset_setup_hw_state(struct drm_i915_private *i915,
drm_crtc_vblank_reset(&crtc->base);
if (crtc_state->hw.active) {
intel_dmc_enable_pipe(i915, crtc->pipe);
intel_dmc_enable_pipe(display, crtc->pipe);
intel_crtc_vblank_on(crtc_state);
}
}

View File

@ -26,6 +26,7 @@
*/
#include <linux/acpi.h>
#include <linux/debugfs.h>
#include <linux/dmi.h>
#include <acpi/video.h>

View File

@ -294,7 +294,7 @@ static void intel_overlay_flip_prepare(struct intel_overlay *overlay,
drm_WARN_ON(&overlay->i915->drm, overlay->old_vma);
if (vma)
frontbuffer = intel_frontbuffer_get(vma->obj);
frontbuffer = intel_frontbuffer_get(intel_bo_to_drm_bo(vma->obj));
intel_frontbuffer_track(overlay->frontbuffer, frontbuffer,
INTEL_FRONTBUFFER_OVERLAY(pipe));
@ -1457,18 +1457,19 @@ void intel_overlay_cleanup(struct drm_i915_private *dev_priv)
#if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR)
struct intel_overlay_error_state {
struct intel_overlay_snapshot {
struct overlay_registers regs;
unsigned long base;
u32 dovsta;
u32 isr;
};
struct intel_overlay_error_state *
intel_overlay_capture_error_state(struct drm_i915_private *dev_priv)
struct intel_overlay_snapshot *
intel_overlay_snapshot_capture(struct intel_display *display)
{
struct drm_i915_private *dev_priv = to_i915(display->drm);
struct intel_overlay *overlay = dev_priv->display.overlay;
struct intel_overlay_error_state *error;
struct intel_overlay_snapshot *error;
if (!overlay || !overlay->active)
return NULL;
@ -1487,9 +1488,12 @@ intel_overlay_capture_error_state(struct drm_i915_private *dev_priv)
}
void
intel_overlay_print_error_state(struct drm_printer *p,
struct intel_overlay_error_state *error)
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);

View File

@ -6,12 +6,15 @@
#ifndef __INTEL_OVERLAY_H__
#define __INTEL_OVERLAY_H__
#include <linux/types.h>
struct drm_device;
struct drm_file;
struct drm_i915_private;
struct drm_printer;
struct intel_display;
struct intel_overlay;
struct intel_overlay_error_state;
struct intel_overlay_snapshot;
#ifdef I915
void intel_overlay_setup(struct drm_i915_private *dev_priv);
@ -22,10 +25,6 @@ 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 drm_i915_private *dev_priv);
struct intel_overlay_error_state *
intel_overlay_capture_error_state(struct drm_i915_private *dev_priv);
void intel_overlay_print_error_state(struct drm_printer *p,
struct intel_overlay_error_state *error);
#else
static inline void intel_overlay_setup(struct drm_i915_private *dev_priv)
{
@ -50,13 +49,21 @@ static inline int intel_overlay_attrs_ioctl(struct drm_device *dev, void *data,
static inline void intel_overlay_reset(struct drm_i915_private *dev_priv)
{
}
static inline struct intel_overlay_error_state *
intel_overlay_capture_error_state(struct drm_i915_private *dev_priv)
#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_print_error_state(struct drm_printer *p,
struct intel_overlay_error_state *error)
static inline void intel_overlay_snapshot_print(const struct intel_overlay_snapshot *error,
struct drm_printer *p)
{
}
#endif

View File

@ -32,6 +32,7 @@
#include "i915_reg.h"
#include "intel_atomic.h"
#include "intel_de.h"
#include "intel_display_irq.h"
#include "intel_display_types.h"
#include "intel_pipe_crc.h"
#include "intel_pipe_crc_regs.h"
@ -285,6 +286,9 @@ intel_crtc_crc_setup_workarounds(struct intel_crtc *crtc, bool enable)
struct drm_modeset_acquire_ctx ctx;
int ret;
if (IS_I945GM(dev_priv) || IS_I915GM(dev_priv))
i915gm_irq_cstate_wa(dev_priv, enable);
drm_modeset_acquire_init(&ctx, 0);
state = drm_atomic_state_alloc(&dev_priv->drm);

View File

@ -302,7 +302,7 @@ intel_alloc_initial_plane_obj(struct intel_crtc *crtc,
mode_cmd.flags = DRM_MODE_FB_MODIFIERS;
if (intel_framebuffer_init(to_intel_framebuffer(fb),
vma->obj, &mode_cmd)) {
intel_bo_to_drm_bo(vma->obj), &mode_cmd)) {
drm_dbg_kms(&dev_priv->drm, "intel fb init failed\n");
goto err_vma;
}

View File

@ -3,6 +3,8 @@
* Copyright © 2020 Intel Corporation
*/
#include <linux/debugfs.h>
#include "g4x_dp.h"
#include "i915_drv.h"
#include "i915_reg.h"
@ -31,7 +33,7 @@ static const char *pps_name(struct intel_dp *intel_dp)
struct intel_pps *pps = &intel_dp->pps;
if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) {
switch (pps->pps_pipe) {
switch (pps->vlv_pps_pipe) {
case INVALID_PIPE:
/*
* FIXME would be nice if we can guarantee
@ -43,7 +45,7 @@ static const char *pps_name(struct intel_dp *intel_dp)
case PIPE_B:
return "PPS B";
default:
MISSING_CASE(pps->pps_pipe);
MISSING_CASE(pps->vlv_pps_pipe);
break;
}
} else {
@ -68,7 +70,7 @@ intel_wakeref_t intel_pps_lock(struct intel_dp *intel_dp)
intel_wakeref_t wakeref;
/*
* See intel_pps_reset_all() why we need a power domain reference here.
* See vlv_pps_reset_all() why we need a power domain reference here.
*/
wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_DISPLAY_CORE);
mutex_lock(&display->pps.mutex);
@ -85,7 +87,7 @@ intel_wakeref_t intel_pps_unlock(struct intel_dp *intel_dp,
mutex_unlock(&display->pps.mutex);
intel_display_power_put(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref);
return 0;
return NULL;
}
static void
@ -94,7 +96,7 @@ vlv_power_sequencer_kick(struct intel_dp *intel_dp)
struct intel_display *display = to_intel_display(intel_dp);
struct drm_i915_private *dev_priv = to_i915(display->drm);
struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
enum pipe pipe = intel_dp->pps.pps_pipe;
enum pipe pipe = intel_dp->pps.vlv_pps_pipe;
bool pll_enabled, release_cl_override = false;
enum dpio_phy phy = vlv_pipe_to_phy(pipe);
enum dpio_channel ch = vlv_pipe_to_channel(pipe);
@ -180,18 +182,18 @@ static enum pipe vlv_find_free_pps(struct intel_display *display)
if (encoder->type == INTEL_OUTPUT_EDP) {
drm_WARN_ON(display->drm,
intel_dp->pps.active_pipe != INVALID_PIPE &&
intel_dp->pps.active_pipe !=
intel_dp->pps.pps_pipe);
intel_dp->pps.vlv_active_pipe != INVALID_PIPE &&
intel_dp->pps.vlv_active_pipe !=
intel_dp->pps.vlv_pps_pipe);
if (intel_dp->pps.pps_pipe != INVALID_PIPE)
pipes &= ~(1 << intel_dp->pps.pps_pipe);
if (intel_dp->pps.vlv_pps_pipe != INVALID_PIPE)
pipes &= ~(1 << intel_dp->pps.vlv_pps_pipe);
} else {
drm_WARN_ON(display->drm,
intel_dp->pps.pps_pipe != INVALID_PIPE);
intel_dp->pps.vlv_pps_pipe != INVALID_PIPE);
if (intel_dp->pps.active_pipe != INVALID_PIPE)
pipes &= ~(1 << intel_dp->pps.active_pipe);
if (intel_dp->pps.vlv_active_pipe != INVALID_PIPE)
pipes &= ~(1 << intel_dp->pps.vlv_active_pipe);
}
}
@ -213,11 +215,11 @@ vlv_power_sequencer_pipe(struct intel_dp *intel_dp)
/* We should never land here with regular DP ports */
drm_WARN_ON(display->drm, !intel_dp_is_edp(intel_dp));
drm_WARN_ON(display->drm, intel_dp->pps.active_pipe != INVALID_PIPE &&
intel_dp->pps.active_pipe != intel_dp->pps.pps_pipe);
drm_WARN_ON(display->drm, intel_dp->pps.vlv_active_pipe != INVALID_PIPE &&
intel_dp->pps.vlv_active_pipe != intel_dp->pps.vlv_pps_pipe);
if (intel_dp->pps.pps_pipe != INVALID_PIPE)
return intel_dp->pps.pps_pipe;
if (intel_dp->pps.vlv_pps_pipe != INVALID_PIPE)
return intel_dp->pps.vlv_pps_pipe;
pipe = vlv_find_free_pps(display);
@ -229,7 +231,7 @@ vlv_power_sequencer_pipe(struct intel_dp *intel_dp)
pipe = PIPE_A;
vlv_steal_power_sequencer(display, pipe);
intel_dp->pps.pps_pipe = pipe;
intel_dp->pps.vlv_pps_pipe = pipe;
drm_dbg_kms(display->drm,
"picked %s for [ENCODER:%d:%s]\n",
@ -246,7 +248,7 @@ vlv_power_sequencer_pipe(struct intel_dp *intel_dp)
*/
vlv_power_sequencer_kick(intel_dp);
return intel_dp->pps.pps_pipe;
return intel_dp->pps.vlv_pps_pipe;
}
static int
@ -260,10 +262,10 @@ bxt_power_sequencer_idx(struct intel_dp *intel_dp)
/* We should never land here with regular DP ports */
drm_WARN_ON(display->drm, !intel_dp_is_edp(intel_dp));
if (!intel_dp->pps.pps_reset)
if (!intel_dp->pps.bxt_pps_reset)
return pps_idx;
intel_dp->pps.pps_reset = false;
intel_dp->pps.bxt_pps_reset = false;
/*
* Only the HW needs to be reprogrammed, the SW state is fixed and
@ -325,19 +327,19 @@ vlv_initial_power_sequencer_setup(struct intel_dp *intel_dp)
/* try to find a pipe with this port selected */
/* first pick one where the panel is on */
intel_dp->pps.pps_pipe = vlv_initial_pps_pipe(display, port,
pps_has_pp_on);
intel_dp->pps.vlv_pps_pipe = vlv_initial_pps_pipe(display, port,
pps_has_pp_on);
/* didn't find one? pick one where vdd is on */
if (intel_dp->pps.pps_pipe == INVALID_PIPE)
intel_dp->pps.pps_pipe = vlv_initial_pps_pipe(display, port,
pps_has_vdd_on);
if (intel_dp->pps.vlv_pps_pipe == INVALID_PIPE)
intel_dp->pps.vlv_pps_pipe = vlv_initial_pps_pipe(display, port,
pps_has_vdd_on);
/* didn't find one? pick one with just the correct port */
if (intel_dp->pps.pps_pipe == INVALID_PIPE)
intel_dp->pps.pps_pipe = vlv_initial_pps_pipe(display, port,
pps_any);
if (intel_dp->pps.vlv_pps_pipe == INVALID_PIPE)
intel_dp->pps.vlv_pps_pipe = vlv_initial_pps_pipe(display, port,
pps_any);
/* didn't find one? just let vlv_power_sequencer_pipe() pick one when needed */
if (intel_dp->pps.pps_pipe == INVALID_PIPE) {
if (intel_dp->pps.vlv_pps_pipe == INVALID_PIPE) {
drm_dbg_kms(display->drm,
"[ENCODER:%d:%s] no initial power sequencer\n",
dig_port->base.base.base.id, dig_port->base.base.name);
@ -446,21 +448,17 @@ pps_initial_setup(struct intel_dp *intel_dp)
return intel_pps_is_valid(intel_dp);
}
void intel_pps_reset_all(struct intel_display *display)
void vlv_pps_reset_all(struct intel_display *display)
{
struct drm_i915_private *dev_priv = to_i915(display->drm);
struct intel_encoder *encoder;
if (drm_WARN_ON(display->drm, !IS_LP(dev_priv)))
return;
if (!HAS_DISPLAY(display))
return;
/*
* We can't grab pps_mutex here due to deadlock with power_domain
* mutex when power_domain functions are called while holding pps_mutex.
* That also means that in order to use pps_pipe the code needs to
* That also means that in order to use vlv_pps_pipe the code needs to
* hold both a power domain reference and pps_mutex, and the power domain
* reference get/put must be done while _not_ holding pps_mutex.
* pps_{lock,unlock}() do these steps in the correct order, so one
@ -470,16 +468,27 @@ void intel_pps_reset_all(struct intel_display *display)
for_each_intel_dp(display->drm, encoder) {
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
drm_WARN_ON(display->drm,
intel_dp->pps.active_pipe != INVALID_PIPE);
drm_WARN_ON(display->drm, intel_dp->pps.vlv_active_pipe != INVALID_PIPE);
if (encoder->type != INTEL_OUTPUT_EDP)
continue;
if (encoder->type == INTEL_OUTPUT_EDP)
intel_dp->pps.vlv_pps_pipe = INVALID_PIPE;
}
}
if (DISPLAY_VER(display) >= 9)
intel_dp->pps.pps_reset = true;
else
intel_dp->pps.pps_pipe = INVALID_PIPE;
void bxt_pps_reset_all(struct intel_display *display)
{
struct intel_encoder *encoder;
if (!HAS_DISPLAY(display))
return;
/* See vlv_pps_reset_all() for why we can't grab pps_mutex here. */
for_each_intel_dp(display->drm, encoder) {
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
if (encoder->type == INTEL_OUTPUT_EDP)
intel_dp->pps.bxt_pps_reset = true;
}
}
@ -548,7 +557,7 @@ static bool edp_have_panel_power(struct intel_dp *intel_dp)
lockdep_assert_held(&display->pps.mutex);
if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
intel_dp->pps.pps_pipe == INVALID_PIPE)
intel_dp->pps.vlv_pps_pipe == INVALID_PIPE)
return false;
return (intel_de_read(display, _pp_stat_reg(intel_dp)) & PP_ON) != 0;
@ -562,7 +571,7 @@ static bool edp_have_panel_vdd(struct intel_dp *intel_dp)
lockdep_assert_held(&display->pps.mutex);
if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
intel_dp->pps.pps_pipe == INVALID_PIPE)
intel_dp->pps.vlv_pps_pipe == INVALID_PIPE)
return false;
return intel_de_read(display, _pp_ctrl_reg(intel_dp)) & EDP_FORCE_VDD;
@ -1151,10 +1160,10 @@ static void vlv_detach_power_sequencer(struct intel_dp *intel_dp)
{
struct intel_display *display = to_intel_display(intel_dp);
struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
enum pipe pipe = intel_dp->pps.pps_pipe;
enum pipe pipe = intel_dp->pps.vlv_pps_pipe;
i915_reg_t pp_on_reg = PP_ON_DELAYS(display, pipe);
drm_WARN_ON(display->drm, intel_dp->pps.active_pipe != INVALID_PIPE);
drm_WARN_ON(display->drm, intel_dp->pps.vlv_active_pipe != INVALID_PIPE);
if (drm_WARN_ON(display->drm, pipe != PIPE_A && pipe != PIPE_B))
return;
@ -1177,7 +1186,7 @@ static void vlv_detach_power_sequencer(struct intel_dp *intel_dp)
intel_de_write(display, pp_on_reg, 0);
intel_de_posting_read(display, pp_on_reg);
intel_dp->pps.pps_pipe = INVALID_PIPE;
intel_dp->pps.vlv_pps_pipe = INVALID_PIPE;
}
static void vlv_steal_power_sequencer(struct intel_display *display,
@ -1190,12 +1199,12 @@ static void vlv_steal_power_sequencer(struct intel_display *display,
for_each_intel_dp(display->drm, encoder) {
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
drm_WARN(display->drm, intel_dp->pps.active_pipe == pipe,
drm_WARN(display->drm, intel_dp->pps.vlv_active_pipe == pipe,
"stealing PPS %c from active [ENCODER:%d:%s]\n",
pipe_name(pipe), encoder->base.base.id,
encoder->base.name);
if (intel_dp->pps.pps_pipe != pipe)
if (intel_dp->pps.vlv_pps_pipe != pipe)
continue;
drm_dbg_kms(display->drm,
@ -1208,8 +1217,59 @@ static void vlv_steal_power_sequencer(struct intel_display *display,
}
}
void vlv_pps_init(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
static enum pipe vlv_active_pipe(struct intel_dp *intel_dp)
{
struct intel_display *display = to_intel_display(intel_dp);
struct drm_i915_private *dev_priv = to_i915(display->drm);
struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
enum pipe pipe;
if (g4x_dp_port_enabled(dev_priv, intel_dp->output_reg,
encoder->port, &pipe))
return pipe;
return INVALID_PIPE;
}
/* Call on all DP, not just eDP */
void vlv_pps_pipe_init(struct intel_dp *intel_dp)
{
intel_dp->pps.vlv_pps_pipe = INVALID_PIPE;
intel_dp->pps.vlv_active_pipe = vlv_active_pipe(intel_dp);
}
/* Call on all DP, not just eDP */
void vlv_pps_pipe_reset(struct intel_dp *intel_dp)
{
intel_wakeref_t wakeref;
with_intel_pps_lock(intel_dp, wakeref)
intel_dp->pps.vlv_active_pipe = vlv_active_pipe(intel_dp);
}
enum pipe vlv_pps_backlight_initial_pipe(struct intel_dp *intel_dp)
{
enum pipe pipe;
/*
* Figure out the current pipe for the initial backlight setup. If the
* current pipe isn't valid, try the PPS pipe, and if that fails just
* assume pipe A.
*/
pipe = vlv_active_pipe(intel_dp);
if (pipe != PIPE_A && pipe != PIPE_B)
pipe = intel_dp->pps.vlv_pps_pipe;
if (pipe != PIPE_A && pipe != PIPE_B)
pipe = PIPE_A;
return pipe;
}
/* Call on all DP, not just eDP */
void vlv_pps_port_enable_unlocked(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(encoder);
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
@ -1217,10 +1277,10 @@ void vlv_pps_init(struct intel_encoder *encoder,
lockdep_assert_held(&display->pps.mutex);
drm_WARN_ON(display->drm, intel_dp->pps.active_pipe != INVALID_PIPE);
drm_WARN_ON(display->drm, intel_dp->pps.vlv_active_pipe != INVALID_PIPE);
if (intel_dp->pps.pps_pipe != INVALID_PIPE &&
intel_dp->pps.pps_pipe != crtc->pipe) {
if (intel_dp->pps.vlv_pps_pipe != INVALID_PIPE &&
intel_dp->pps.vlv_pps_pipe != crtc->pipe) {
/*
* If another power sequencer was being used on this
* port previously make sure to turn off vdd there while
@ -1235,13 +1295,13 @@ void vlv_pps_init(struct intel_encoder *encoder,
*/
vlv_steal_power_sequencer(display, crtc->pipe);
intel_dp->pps.active_pipe = crtc->pipe;
intel_dp->pps.vlv_active_pipe = crtc->pipe;
if (!intel_dp_is_edp(intel_dp))
return;
/* now it's all ours */
intel_dp->pps.pps_pipe = crtc->pipe;
intel_dp->pps.vlv_pps_pipe = crtc->pipe;
drm_dbg_kms(display->drm,
"initializing %s for [ENCODER:%d:%s]\n",
@ -1253,6 +1313,18 @@ void vlv_pps_init(struct intel_encoder *encoder,
pps_init_registers(intel_dp, true);
}
/* Call on all DP, not just eDP */
void vlv_pps_port_disable(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
{
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
intel_wakeref_t wakeref;
with_intel_pps_lock(intel_dp, wakeref)
intel_dp->pps.vlv_active_pipe = INVALID_PIPE;
}
static void pps_vdd_init(struct intel_dp *intel_dp)
{
struct intel_display *display = to_intel_display(intel_dp);

View File

@ -43,10 +43,16 @@ void intel_pps_wait_power_cycle(struct intel_dp *intel_dp);
bool intel_pps_init(struct intel_dp *intel_dp);
void intel_pps_init_late(struct intel_dp *intel_dp);
void intel_pps_encoder_reset(struct intel_dp *intel_dp);
void intel_pps_reset_all(struct intel_display *display);
void vlv_pps_init(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state);
void vlv_pps_pipe_init(struct intel_dp *intel_dp);
void vlv_pps_pipe_reset(struct intel_dp *intel_dp);
enum pipe vlv_pps_backlight_initial_pipe(struct intel_dp *intel_dp);
void vlv_pps_port_enable_unlocked(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state);
void vlv_pps_port_disable(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state);
void vlv_pps_reset_all(struct intel_display *display);
void bxt_pps_reset_all(struct intel_display *display);
void intel_pps_unlock_regs_wa(struct intel_display *display);
void intel_pps_setup(struct intel_display *display);

View File

@ -21,6 +21,8 @@
* DEALINGS IN THE SOFTWARE.
*/
#include <linux/debugfs.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_damage_helper.h>
#include <drm/drm_debugfs.h>
@ -33,6 +35,7 @@
#include "intel_cursor_regs.h"
#include "intel_ddi.h"
#include "intel_de.h"
#include "intel_display_irq.h"
#include "intel_display_types.h"
#include "intel_dp.h"
#include "intel_dp_aux.h"
@ -762,7 +765,7 @@ static void _psr_enable_sink(struct intel_dp *intel_dp,
const struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(intel_dp);
u8 val = DP_PSR_ENABLE;
u8 val = 0;
if (crtc_state->has_sel_update) {
val |= DP_PSR_ENABLE_PSR2 | DP_PSR_IRQ_HPD_WITH_CRC_ERRORS;
@ -782,7 +785,9 @@ static void _psr_enable_sink(struct intel_dp *intel_dp,
if (intel_dp->psr.entry_setup_frames > 0)
val |= DP_PSR_FRAME_CAPTURE;
drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, val);
val |= DP_PSR_ENABLE;
drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, val);
}
@ -1599,6 +1604,10 @@ _panel_replay_compute_config(struct intel_dp *intel_dp,
/* Remaining checks are for eDP only */
if (to_intel_crtc(crtc_state->uapi.crtc)->pipe != PIPE_A &&
to_intel_crtc(crtc_state->uapi.crtc)->pipe != PIPE_B)
return false;
/* 128b/132b Panel Replay is not supported on eDP */
if (intel_dp_is_uhbr(crtc_state)) {
drm_dbg_kms(display->drm,
@ -2114,7 +2123,7 @@ static void intel_psr_disable_locked(struct intel_dp *intel_dp)
ALPM_CTL_ALPM_AUX_LESS_ENABLE, 0);
intel_de_rmw(display,
PORT_ALPM_CTL(display, cpu_transcoder),
PORT_ALPM_CTL(cpu_transcoder),
PORT_ALPM_CTL_ALPM_AUX_LESS_ENABLE, 0);
}
@ -2221,6 +2230,36 @@ void intel_psr_resume(struct intel_dp *intel_dp)
mutex_unlock(&psr->lock);
}
/**
* intel_psr_needs_block_dc_vblank - Check if block dc entry is needed
* @crtc_state: CRTC status
*
* We need to block DC6 entry in case of Panel Replay as enabling VBI doesn't
* prevent it in case of Panel Replay. Panel Replay switches main link off on
* DC entry. This means vblank interrupts are not fired and is a problem if
* user-space is polling for vblank events.
*/
bool intel_psr_needs_block_dc_vblank(const struct intel_crtc_state *crtc_state)
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct intel_encoder *encoder;
for_each_encoder_on_crtc(crtc->base.dev, &crtc->base, encoder) {
struct intel_dp *intel_dp;
if (!intel_encoder_is_dp(encoder))
continue;
intel_dp = enc_to_intel_dp(encoder);
if (intel_dp_is_edp(intel_dp) &&
CAN_PANEL_REPLAY(intel_dp))
return true;
}
return false;
}
static u32 man_trk_ctl_enable_bit_get(struct intel_display *display)
{
struct drm_i915_private *dev_priv = to_i915(display->drm);
@ -2480,11 +2519,60 @@ static bool psr2_sel_fetch_pipe_state_supported(const struct intel_crtc_state *c
return true;
}
/* Wa 14019834836 */
static void intel_psr_apply_pr_link_on_su_wa(struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(crtc_state);
struct intel_encoder *encoder;
int hactive_limit;
if (crtc_state->psr2_su_area.y1 != 0 ||
crtc_state->psr2_su_area.y2 != 0)
return;
if (crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420)
hactive_limit = intel_dp_is_uhbr(crtc_state) ? 1230 : 546;
else
hactive_limit = intel_dp_is_uhbr(crtc_state) ? 615 : 273;
if (crtc_state->hw.adjusted_mode.hdisplay < hactive_limit)
return;
for_each_intel_encoder_mask_with_psr(display->drm, encoder,
crtc_state->uapi.encoder_mask) {
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
if (!intel_dp_is_edp(intel_dp) &&
intel_dp->psr.panel_replay_enabled &&
intel_dp->psr.sel_update_enabled) {
crtc_state->psr2_su_area.y2++;
return;
}
}
}
static void
intel_psr_apply_su_area_workarounds(struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(crtc_state);
struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
/* Wa_14014971492 */
if (!crtc_state->has_panel_replay &&
((IS_DISPLAY_VER_STEP(display, IP_VER(14, 0), STEP_A0, STEP_B0) ||
IS_ALDERLAKE_P(i915) || IS_TIGERLAKE(i915))) &&
crtc_state->splitter.enable)
crtc_state->psr2_su_area.y1 = 0;
/* Wa 14019834836 */
if (DISPLAY_VER(display) == 30)
intel_psr_apply_pr_link_on_su_wa(crtc_state);
}
int intel_psr2_sel_fetch_update(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
struct intel_display *display = to_intel_display(state);
struct drm_i915_private *dev_priv = to_i915(state->base.dev);
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;
@ -2589,12 +2677,7 @@ int intel_psr2_sel_fetch_update(struct intel_atomic_state *state,
if (full_update)
goto skip_sel_fetch_set_loop;
/* Wa_14014971492 */
if (!crtc_state->has_panel_replay &&
((IS_DISPLAY_VER_STEP(display, IP_VER(14, 0), STEP_A0, STEP_B0) ||
IS_ALDERLAKE_P(dev_priv) || IS_TIGERLAKE(dev_priv))) &&
crtc_state->splitter.enable)
crtc_state->psr2_su_area.y1 = 0;
intel_psr_apply_su_area_workarounds(crtc_state);
ret = drm_atomic_add_affected_planes(&state->base, &crtc->base);
if (ret)
@ -3848,10 +3931,8 @@ void intel_psr_connector_debugfs_add(struct intel_connector *connector)
struct drm_i915_private *i915 = to_i915(connector->base.dev);
struct dentry *root = connector->base.debugfs_entry;
/* TODO: Add support for MST connectors as well. */
if ((connector->base.connector_type != DRM_MODE_CONNECTOR_eDP &&
connector->base.connector_type != DRM_MODE_CONNECTOR_DisplayPort) ||
connector->mst_port)
if (connector->base.connector_type != DRM_MODE_CONNECTOR_eDP &&
connector->base.connector_type != DRM_MODE_CONNECTOR_DisplayPort)
return;
debugfs_create_file("i915_psr_sink_status", 0444, root,

View File

@ -58,6 +58,7 @@ int intel_psr2_sel_fetch_update(struct intel_atomic_state *state,
void intel_psr2_program_trans_man_trk_ctl(const struct intel_crtc_state *crtc_state);
void intel_psr_pause(struct intel_dp *intel_dp);
void intel_psr_resume(struct intel_dp *intel_dp);
bool intel_psr_needs_block_dc_vblank(const struct intel_crtc_state *crtc_state);
void intel_psr_lock(const struct intel_crtc_state *crtc_state);
void intel_psr_unlock(const struct intel_crtc_state *crtc_state);

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