mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-12-29 09:16:33 +00:00
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:
commit
f1864235dd
@ -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.
|
||||
|
@ -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 \
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -3,6 +3,8 @@
|
||||
* Copyright © 2022 Intel Corporation
|
||||
*/
|
||||
|
||||
#include <linux/debugfs.h>
|
||||
|
||||
#include "hsw_ips.h"
|
||||
#include "i915_drv.h"
|
||||
#include "i915_reg.h"
|
||||
|
@ -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)
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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"
|
||||
|
@ -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) |
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
59
drivers/gpu/drm/i915/display/intel_bo.c
Normal file
59
drivers/gpu/drm/i915/display/intel_bo.c
Normal 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));
|
||||
}
|
27
drivers/gpu/drm/i915/display/intel_bo.h
Normal file
27
drivers/gpu/drm/i915/display/intel_bo.h
Normal 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
@ -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__ */
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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 :
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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 ||
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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__ */
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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__ */
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
72
drivers/gpu/drm/i915/display/intel_display_snapshot.c
Normal file
72
drivers/gpu/drm/i915/display/intel_display_snapshot.c
Normal 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);
|
||||
}
|
16
drivers/gpu/drm/i915/display/intel_display_snapshot.h
Normal file
16
drivers/gpu/drm/i915/display/intel_display_snapshot.h
Normal 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__ */
|
@ -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)
|
||||
),
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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__ */
|
||||
|
@ -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
@ -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__ */
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
765
drivers/gpu/drm/i915/display/intel_dp_test.c
Normal file
765
drivers/gpu/drm/i915/display/intel_dp_test.c
Normal 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);
|
||||
}
|
||||
}
|
23
drivers/gpu/drm/i915/display/intel_dp_test.h
Normal file
23
drivers/gpu/drm/i915/display/intel_dp_test.h
Normal 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__ */
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -3,6 +3,8 @@
|
||||
* Copyright © 2021 Intel Corporation
|
||||
*/
|
||||
|
||||
#include <linux/debugfs.h>
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "i915_reg.h"
|
||||
#include "intel_atomic.h"
|
||||
|
@ -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",
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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"
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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__ */
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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))
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
@ -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 ? >->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,
|
||||
|
@ -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__ */
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
137
drivers/gpu/drm/i915/display/intel_hdcp_shim.h
Normal file
137
drivers/gpu/drm/i915/display/intel_hdcp_shim.h
Normal 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__ */
|
@ -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,
|
||||
|
@ -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"
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -26,6 +26,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <acpi/video.h>
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user