- Enable PIPEDMC_ERROR interrupt (Dibin)

- Some general display fixes and cleanups (Ville, Nemesa,
    Suraj, Dibin, Arun, Desnes, Juha-Pekka, Vidya, Julian)
  - More refactor to split display code (Jani, Ville, Luca)
  - Panel Replay BW optimization (Animesh)
  - Integrate the sharpness filter properly into the scaler (Ville)
  - Watermark/SAGV fixes/cleanups/etc (Ville)
  - Restructure DP/HDMI sink format handling (Ville)
  - Eliminate FB usage from low level pinning code (Ville)
  - Some initial prep patches for always enable AS SDP (Ankit)
  - Many PSR related fixes (Jouni)
  - Fix MST VCPI lookup and modeset-lock splat (Suraj)
 -----BEGIN PGP SIGNATURE-----
 
 iQEzBAABCgAdFiEEbSBwaO7dZQkcLOKj+mJfZA7rE8oFAmn6LQcACgkQ+mJfZA7r
 E8oGkQf8DAAUKQr+GAzTS5hdXPM6gZ+6n+3rU3SC/3jk595DGEdar+roZ1G+DPRg
 xoYHHK0lq/0aE+ynaa2c4rEEYYD8rruc/56DQ9iT49ap+oNtAhqsvE8vcwZ5D7C2
 io/YxkVY6VSffbrUDnx/RUlD3PQFsT20N14BfxPUjF6jggxAT1kQFUqSqThWyWOB
 hvj/h54SdzjuaMwPNcbdcLq6b9zfuOD04s2D1b2o8kBy3cX4RJp6Wgal55QhkTTh
 u0GoYLqFqBrH4Cm4XzYgTFn4OYOwhNZKac3rx88YtdIOsnaHFZMnDVm5O/Ss83DT
 2yblgl5APkpQWEFmIyE/+m3ZKiaIqg==
 =oOAT
 -----END PGP SIGNATURE-----

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

 - Enable PIPEDMC_ERROR interrupt (Dibin)
 - Some general display fixes and cleanups (Ville, Nemesa,
   Suraj, Dibin, Arun, Desnes, Juha-Pekka, Vidya, Julian)
 - More refactor to split display code (Jani, Ville, Luca)
 - Panel Replay BW optimization (Animesh)
 - Integrate the sharpness filter properly into the scaler (Ville)
 - Watermark/SAGV fixes/cleanups/etc (Ville)
 - Restructure DP/HDMI sink format handling (Ville)
 - Eliminate FB usage from low level pinning code (Ville)
 - Some initial prep patches for always enable AS SDP (Ankit)
 - Many PSR related fixes (Jouni)
 - Fix MST VCPI lookup and modeset-lock splat (Suraj)

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

From: Rodrigo Vivi <rodrigo.vivi@intel.com>
Link: https://patch.msgid.link/afot1cjSpeAjYzg2@intel.com
This commit is contained in:
Dave Airlie 2026-05-06 10:54:51 +10:00
commit 7a777dccc2
139 changed files with 2755 additions and 2240 deletions

View File

@ -149,6 +149,7 @@ struct drm_dp_tunnel {
bool bw_alloc_enabled:1;
bool has_io_error:1;
bool destroyed:1;
bool pr_optimization_support:1;
};
struct drm_dp_tunnel_group_state;
@ -508,6 +509,8 @@ create_tunnel(struct drm_dp_tunnel_mgr *mgr,
tunnel->bw_alloc_supported = tunnel_reg_bw_alloc_supported(regs);
tunnel->bw_alloc_enabled = tunnel_reg_bw_alloc_enabled(regs);
tunnel->pr_optimization_support = tunnel_reg(regs, DP_TUNNELING_CAPABILITIES) &
DP_PANEL_REPLAY_OPTIMIZATION_SUPPORT;
if (!add_tunnel_to_group(mgr, drv_group_id, tunnel)) {
kfree(tunnel);
@ -1036,6 +1039,20 @@ bool drm_dp_tunnel_bw_alloc_is_enabled(const struct drm_dp_tunnel *tunnel)
}
EXPORT_SYMBOL(drm_dp_tunnel_bw_alloc_is_enabled);
/**
* drm_dp_tunnel_pr_optimization_supported - Query the PR BW optimization support
* @tunnel: Tunnel object
*
* Query if the PR BW optimization is supported for @tunnel.
*
* Returns %true if the PR BW optimiation is supported for @tunnel.
*/
bool drm_dp_tunnel_pr_optimization_supported(const struct drm_dp_tunnel *tunnel)
{
return tunnel && tunnel->pr_optimization_support;
}
EXPORT_SYMBOL(drm_dp_tunnel_pr_optimization_supported);
static int clear_bw_req_state(struct drm_dp_aux *aux)
{
u8 bw_req_mask = DP_BW_REQUEST_SUCCEEDED | DP_BW_REQUEST_FAILED;

View File

@ -153,7 +153,7 @@ config DRM_I915_TRACE_GTT
config DRM_I915_SW_FENCE_DEBUG_OBJECTS
bool "Enable additional driver debugging for fence objects"
depends on DRM_I915
select DEBUG_OBJECTS
depends on DEBUG_OBJECTS
default n
help
Choose this option to turn on extra driver debugging that may affect

View File

@ -80,6 +80,7 @@ i915-y += \
i915_display_pc8.o \
i915_dpt.o \
i915_dsb_buffer.o \
i915_fb_pin.o \
i915_hdcp_gsc.o \
i915_initial_plane.o \
i915_overlay.o \
@ -255,6 +256,7 @@ i915-y += \
display/intel_cursor.o \
display/intel_dbuf_bw.o \
display/intel_de.o \
display/intel_display_clock_gating.o \
display/intel_display.o \
display/intel_display_conversion.o \
display/intel_display_driver.o \
@ -279,7 +281,6 @@ i915-y += \
display/intel_drrs.o \
display/intel_dsb.o \
display/intel_fb.o \
display/intel_fb_pin.o \
display/intel_fbc.o \
display/intel_fdi.o \
display/intel_fifo_underrun.o \
@ -295,6 +296,7 @@ i915-y += \
display/intel_link_bw.o \
display/intel_load_detect.o \
display/intel_lpe_audio.o \
display/intel_mchbar.o \
display/intel_modeset_lock.o \
display/intel_modeset_setup.o \
display/intel_modeset_verify.o \
@ -325,8 +327,7 @@ i915-$(CONFIG_ACPI) += \
display/intel_acpi.o \
display/intel_opregion.o
i915-$(CONFIG_DRM_FBDEV_EMULATION) += \
display/intel_fbdev.o \
display/intel_fbdev_fb.o
display/intel_fbdev.o
i915-$(CONFIG_DEBUG_FS) += \
display/intel_display_debugfs.o \
display/intel_display_debugfs_params.o \

View File

@ -4,13 +4,13 @@
*/
#include <drm/drm_device.h>
#include <drm/intel/pci_config.h>
#include "i9xx_display_sr.h"
#include "i9xx_wm_regs.h"
#include "intel_de.h"
#include "intel_display_regs.h"
#include "intel_gmbus.h"
#include "intel_pci_config.h"
static void i9xx_display_save_swf(struct intel_display *display)
{

View File

@ -1240,7 +1240,7 @@ i9xx_get_initial_plane_config(struct intel_crtc *crtc,
fb->width, fb->height, fb->format->cpp[0] * 8,
base, fb->pitches[0], plane_config->size);
plane_config->fb = intel_fb;
plane_config->fb = &intel_fb->base;
}
bool i9xx_fixup_initial_plane_config(struct intel_crtc *crtc,

View File

@ -19,7 +19,7 @@
#include "intel_display_utils.h"
#include "intel_dram.h"
#include "intel_fb.h"
#include "intel_mchbar_regs.h"
#include "intel_mchbar.h"
#include "intel_wm.h"
#include "skl_watermark.h"
#include "vlv_sideband.h"
@ -118,41 +118,41 @@ static void chv_set_memory_dvfs(struct intel_display *display, bool enable)
u32 val;
int ret;
vlv_punit_get(display->drm);
vlv_punit_get(display);
val = vlv_punit_read(display->drm, PUNIT_REG_DDR_SETUP2);
val = vlv_punit_read(display, PUNIT_REG_DDR_SETUP2);
if (enable)
val &= ~FORCE_DDR_HIGH_FREQ;
else
val |= FORCE_DDR_HIGH_FREQ;
val &= ~FORCE_DDR_LOW_FREQ;
val |= FORCE_DDR_FREQ_REQ_ACK;
vlv_punit_write(display->drm, PUNIT_REG_DDR_SETUP2, val);
vlv_punit_write(display, PUNIT_REG_DDR_SETUP2, val);
ret = poll_timeout_us(val = vlv_punit_read(display->drm, PUNIT_REG_DDR_SETUP2),
ret = poll_timeout_us(val = vlv_punit_read(display, PUNIT_REG_DDR_SETUP2),
(val & FORCE_DDR_FREQ_REQ_ACK) == 0,
500, 3000, false);
if (ret)
drm_err(display->drm,
"timed out waiting for Punit DDR DVFS request\n");
vlv_punit_put(display->drm);
vlv_punit_put(display);
}
static void chv_set_memory_pm5(struct intel_display *display, bool enable)
{
u32 val;
vlv_punit_get(display->drm);
vlv_punit_get(display);
val = vlv_punit_read(display->drm, PUNIT_REG_DSPSSPM);
val = vlv_punit_read(display, PUNIT_REG_DSPSSPM);
if (enable)
val |= DSP_MAXFIFO_PM5_ENABLE;
else
val &= ~DSP_MAXFIFO_PM5_ENABLE;
vlv_punit_write(display->drm, PUNIT_REG_DSPSSPM, val);
vlv_punit_write(display, PUNIT_REG_DSPSSPM, val);
vlv_punit_put(display->drm);
vlv_punit_put(display);
}
#define FW_WM(value, plane) \
@ -2742,12 +2742,11 @@ static void ilk_compute_wm_level(struct intel_display *display,
static void hsw_read_wm_latency(struct intel_display *display, u16 wm[])
{
struct intel_uncore *uncore = to_intel_uncore(display->drm);
u64 sskpd;
display->wm.num_levels = 5;
sskpd = intel_uncore_read64(uncore, MCH_SSKPD);
sskpd = intel_mchbar_read64_2x32(display, MCH_SSKPD);
wm[0] = REG_FIELD_GET64(SSKPD_NEW_WM0_MASK_HSW, sskpd);
if (wm[0] == 0)
@ -2760,12 +2759,11 @@ static void hsw_read_wm_latency(struct intel_display *display, u16 wm[])
static void snb_read_wm_latency(struct intel_display *display, u16 wm[])
{
struct intel_uncore *uncore = to_intel_uncore(display->drm);
u32 sskpd;
display->wm.num_levels = 4;
sskpd = intel_uncore_read(uncore, MCH_SSKPD);
sskpd = intel_mchbar_read(display, MCH_SSKPD);
wm[0] = REG_FIELD_GET(SSKPD_WM0_MASK_SNB, sskpd);
wm[1] = REG_FIELD_GET(SSKPD_WM1_MASK_SNB, sskpd);
@ -2775,12 +2773,11 @@ static void snb_read_wm_latency(struct intel_display *display, u16 wm[])
static void ilk_read_wm_latency(struct intel_display *display, u16 wm[])
{
struct intel_uncore *uncore = to_intel_uncore(display->drm);
u32 mltr;
display->wm.num_levels = 3;
mltr = intel_uncore_read(uncore, MLTR_ILK);
mltr = intel_mchbar_read(display, MLTR_ILK);
/* ILK primary LP0 latency is 700 ns */
wm[0] = 7;
@ -3587,7 +3584,7 @@ void ilk_wm_sanitize(struct intel_display *display)
int i;
/* Only supported on platforms that use atomic watermark design */
if (!display->funcs.wm->optimize_watermarks)
if (!display->wm.funcs->optimize_watermarks)
return;
if (drm_WARN_ON(display->drm, DISPLAY_VER(display) >= 9))
@ -3918,9 +3915,9 @@ static void vlv_wm_get_hw_state(struct intel_display *display)
wm->level = VLV_WM_LEVEL_PM2;
if (display->platform.cherryview) {
vlv_punit_get(display->drm);
vlv_punit_get(display);
val = vlv_punit_read(display->drm, PUNIT_REG_DSPSSPM);
val = vlv_punit_read(display, PUNIT_REG_DSPSSPM);
if (val & DSP_MAXFIFO_PM5_ENABLE)
wm->level = VLV_WM_LEVEL_PM5;
@ -3933,11 +3930,11 @@ static void vlv_wm_get_hw_state(struct intel_display *display)
* HIGH/LOW bits so that we don't actually change
* the current state.
*/
val = vlv_punit_read(display->drm, PUNIT_REG_DDR_SETUP2);
val = vlv_punit_read(display, PUNIT_REG_DDR_SETUP2);
val |= FORCE_DDR_FREQ_REQ_ACK;
vlv_punit_write(display->drm, PUNIT_REG_DDR_SETUP2, val);
vlv_punit_write(display, PUNIT_REG_DDR_SETUP2, val);
ret = poll_timeout_us(val = vlv_punit_read(display->drm, PUNIT_REG_DDR_SETUP2),
ret = poll_timeout_us(val = vlv_punit_read(display, PUNIT_REG_DDR_SETUP2),
(val & FORCE_DDR_FREQ_REQ_ACK) == 0,
500, 3000, false);
if (ret) {
@ -3946,12 +3943,12 @@ static void vlv_wm_get_hw_state(struct intel_display *display)
"assuming DDR DVFS is disabled\n");
display->wm.num_levels = VLV_WM_LEVEL_PM5 + 1;
} else {
val = vlv_punit_read(display->drm, PUNIT_REG_DDR_SETUP2);
val = vlv_punit_read(display, PUNIT_REG_DDR_SETUP2);
if ((val & FORCE_DDR_HIGH_FREQ) == 0)
wm->level = VLV_WM_LEVEL_DDR_DVFS;
}
vlv_punit_put(display->drm);
vlv_punit_put(display);
}
for_each_intel_crtc(display->drm, crtc) {
@ -4155,34 +4152,34 @@ void i9xx_wm_init(struct intel_display *display)
/* For FIFO watermark updates */
if (HAS_PCH_SPLIT(display)) {
ilk_setup_wm_latency(display);
display->funcs.wm = &ilk_wm_funcs;
display->wm.funcs = &ilk_wm_funcs;
} else if (display->platform.valleyview || display->platform.cherryview) {
vlv_setup_wm_latency(display);
display->funcs.wm = &vlv_wm_funcs;
display->wm.funcs = &vlv_wm_funcs;
} else if (display->platform.g4x) {
g4x_setup_wm_latency(display);
display->funcs.wm = &g4x_wm_funcs;
display->wm.funcs = &g4x_wm_funcs;
} else if (display->platform.pineview) {
if (!pnv_get_cxsr_latency(display)) {
drm_info(display->drm, "Unknown FSB/MEM, disabling CxSR\n");
/* Disable CxSR and never update its watermark again */
intel_set_memory_cxsr(display, false);
display->funcs.wm = &nop_funcs;
display->wm.funcs = &nop_funcs;
} else {
display->funcs.wm = &pnv_wm_funcs;
display->wm.funcs = &pnv_wm_funcs;
}
} else if (DISPLAY_VER(display) == 4) {
display->funcs.wm = &i965_wm_funcs;
display->wm.funcs = &i965_wm_funcs;
} else if (DISPLAY_VER(display) == 3) {
display->funcs.wm = &i9xx_wm_funcs;
display->wm.funcs = &i9xx_wm_funcs;
} else if (DISPLAY_VER(display) == 2) {
if (INTEL_NUM_PIPES(display) == 1)
display->funcs.wm = &i845_wm_funcs;
display->wm.funcs = &i845_wm_funcs;
else
display->funcs.wm = &i9xx_wm_funcs;
display->wm.funcs = &i9xx_wm_funcs;
} else {
drm_err(display->drm,
"unexpected fall-through in %s\n", __func__);
display->funcs.wm = &nop_funcs;
display->wm.funcs = &nop_funcs;
}
}

View File

@ -754,10 +754,8 @@ void intel_audio_codec_enable(struct intel_encoder *encoder,
crtc->base.base.id, crtc->base.name,
drm_eld_size(crtc_state->eld));
if (display->funcs.audio)
display->funcs.audio->audio_codec_enable(encoder,
crtc_state,
conn_state);
if (display->audio.funcs)
display->audio.funcs->audio_codec_enable(encoder, crtc_state, conn_state);
mutex_lock(&display->audio.mutex);
@ -813,10 +811,8 @@ void intel_audio_codec_disable(struct intel_encoder *encoder,
encoder->base.base.id, encoder->base.name,
crtc->base.base.id, crtc->base.name);
if (display->funcs.audio)
display->funcs.audio->audio_codec_disable(encoder,
old_crtc_state,
old_conn_state);
if (display->audio.funcs)
display->audio.funcs->audio_codec_disable(encoder, old_crtc_state, old_conn_state);
mutex_lock(&display->audio.mutex);
@ -864,8 +860,8 @@ void intel_audio_codec_get_config(struct intel_encoder *encoder,
if (!crtc_state->has_audio)
return;
if (display->funcs.audio)
display->funcs.audio->audio_codec_get_config(encoder, crtc_state);
if (display->audio.funcs)
display->audio.funcs->audio_codec_get_config(encoder, crtc_state);
}
static const struct intel_audio_funcs g4x_audio_funcs = {
@ -893,12 +889,12 @@ static const struct intel_audio_funcs hsw_audio_funcs = {
void intel_audio_hooks_init(struct intel_display *display)
{
if (display->platform.g4x)
display->funcs.audio = &g4x_audio_funcs;
display->audio.funcs = &g4x_audio_funcs;
else if (display->platform.valleyview || display->platform.cherryview ||
HAS_PCH_CPT(display) || HAS_PCH_IBX(display))
display->funcs.audio = &ibx_audio_funcs;
display->audio.funcs = &ibx_audio_funcs;
else if (display->platform.haswell || DISPLAY_VER(display) >= 8)
display->funcs.audio = &hsw_audio_funcs;
display->audio.funcs = &hsw_audio_funcs;
}
struct aud_ts_cdclk_m_n {

View File

@ -11,6 +11,7 @@
#include <drm/drm_file.h>
#include <drm/drm_print.h>
#include <drm/intel/pci_config.h>
#include "intel_backlight.h"
#include "intel_backlight_regs.h"
@ -23,7 +24,6 @@
#include "intel_dp_aux_backlight.h"
#include "intel_dsi_dcs_backlight.h"
#include "intel_panel.h"
#include "intel_pci_config.h"
#include "intel_pps.h"
#include "intel_quirks.h"

View File

@ -85,3 +85,30 @@ struct drm_gem_object *intel_bo_framebuffer_lookup(struct intel_display *display
{
return display->parent->bo->framebuffer_lookup(display->drm, filp, user_mode_cmd);
}
#if IS_ENABLED(CONFIG_DRM_FBDEV_EMULATION)
u32 intel_bo_fbdev_pitch_align(struct intel_display *display, u32 stride)
{
return display->parent->bo->fbdev_pitch_align(stride);
}
struct drm_gem_object *intel_bo_fbdev_create(struct intel_display *display, int size)
{
return display->parent->bo->fbdev_create(display->drm, size);
}
void intel_bo_fbdev_destroy(struct drm_gem_object *obj)
{
struct intel_display *display = to_intel_display(obj->dev);
display->parent->bo->fbdev_destroy(obj);
}
int intel_bo_fbdev_fill_info(struct drm_gem_object *obj, struct fb_info *info,
struct i915_vma *vma)
{
struct intel_display *display = to_intel_display(obj->dev);
return display->parent->bo->fbdev_fill_info(obj, info, vma);
}
#endif

View File

@ -10,6 +10,8 @@ struct drm_file;
struct drm_gem_object;
struct drm_mode_fb_cmd2;
struct drm_scanout_buffer;
struct fb_info;
struct i915_vma;
struct intel_display;
struct intel_framebuffer;
struct seq_file;
@ -31,4 +33,10 @@ struct drm_gem_object *intel_bo_framebuffer_lookup(struct intel_display *display
struct drm_file *filp,
const struct drm_mode_fb_cmd2 *user_mode_cmd);
u32 intel_bo_fbdev_pitch_align(struct intel_display *display, u32 stride);
struct drm_gem_object *intel_bo_fbdev_create(struct intel_display *display, int size);
void intel_bo_fbdev_destroy(struct drm_gem_object *obj);
int intel_bo_fbdev_fill_info(struct drm_gem_object *obj, struct fb_info *info,
struct i915_vma *vma);
#endif /* __INTEL_BO__ */

View File

@ -9,14 +9,14 @@
#include "intel_bw.h"
#include "intel_crtc.h"
#include "intel_de.h"
#include "intel_display_core.h"
#include "intel_display_regs.h"
#include "intel_display_types.h"
#include "intel_display_utils.h"
#include "intel_dram.h"
#include "intel_mchbar_regs.h"
#include "intel_mchbar.h"
#include "intel_parent.h"
#include "intel_uncore.h"
#include "skl_watermark.h"
struct intel_bw_state {
@ -28,9 +28,6 @@ struct intel_bw_state {
*/
u8 pipe_sagv_reject;
/* bitmask of active pipes */
u8 active_pipes;
/*
* From MTL onwards, to lock a QGV point, punit expects the peak BW of
* the selected QGV point as the parameter in multiples of 100MB/s
@ -74,11 +71,10 @@ static int dg1_mchbar_read_qgv_point_info(struct intel_display *display,
struct intel_qgv_point *sp,
int point)
{
struct intel_uncore *uncore = to_intel_uncore(display->drm);
u32 dclk_ratio, dclk_reference;
u32 val;
val = intel_uncore_read(uncore, SA_PERF_STATUS_0_0_0_MCHBAR_PC);
val = intel_mchbar_read(display, SA_PERF_STATUS_0_0_0_MCHBAR_PC);
dclk_ratio = REG_FIELD_GET(DG1_QCLK_RATIO_MASK, val);
if (val & DG1_QCLK_REFERENCE)
dclk_reference = 6; /* 6 * 16.666 MHz = 100 MHz */
@ -86,18 +82,18 @@ static int dg1_mchbar_read_qgv_point_info(struct intel_display *display,
dclk_reference = 8; /* 8 * 16.666 MHz = 133 MHz */
sp->dclk = DIV_ROUND_UP((16667 * dclk_ratio * dclk_reference) + 500, 1000);
val = intel_uncore_read(uncore, SKL_MC_BIOS_DATA_0_0_0_MCHBAR_PCU);
val = intel_mchbar_read(display, SKL_MC_BIOS_DATA_0_0_0_MCHBAR_PCU);
if (val & DG1_GEAR_TYPE)
sp->dclk *= 2;
if (sp->dclk == 0)
return -EINVAL;
val = intel_uncore_read(uncore, MCHBAR_CH0_CR_TC_PRE_0_0_0_MCHBAR);
val = intel_mchbar_read(display, MCHBAR_CH0_CR_TC_PRE_0_0_0_MCHBAR);
sp->t_rp = REG_FIELD_GET(DG1_DRAM_T_RP_MASK, val);
sp->t_rdpre = REG_FIELD_GET(DG1_DRAM_T_RDPRE_MASK, val);
val = intel_uncore_read(uncore, MCHBAR_CH0_CR_TC_PRE_0_0_0_MCHBAR_HIGH);
val = intel_mchbar_read(display, MCHBAR_CH0_CR_TC_PRE_0_0_0_MCHBAR_HIGH);
sp->t_rcd = REG_FIELD_GET(DG1_DRAM_T_RCD_MASK, val);
sp->t_ras = REG_FIELD_GET(DG1_DRAM_T_RAS_MASK, val);
@ -211,12 +207,11 @@ static int icl_pcode_restrict_qgv_points(struct intel_display *display,
static int mtl_read_qgv_point_info(struct intel_display *display,
struct intel_qgv_point *sp, int point)
{
struct intel_uncore *uncore = to_intel_uncore(display->drm);
u32 val, val2;
u16 dclk;
val = intel_uncore_read(uncore, MTL_MEM_SS_INFO_QGV_POINT_LOW(point));
val2 = intel_uncore_read(uncore, MTL_MEM_SS_INFO_QGV_POINT_HIGH(point));
val = intel_de_read(display, MTL_MEM_SS_INFO_QGV_POINT_LOW(point));
val2 = intel_de_read(display, MTL_MEM_SS_INFO_QGV_POINT_HIGH(point));
dclk = REG_FIELD_GET(MTL_DCLK_MASK, val);
sp->dclk = DIV_ROUND_CLOSEST(16667 * dclk, 1000);
sp->t_rp = REG_FIELD_GET(MTL_TRP_MASK, val);
@ -1265,31 +1260,6 @@ static int intel_bw_check_data_rate(struct intel_atomic_state *state, bool *chan
return 0;
}
static int intel_bw_modeset_checks(struct intel_atomic_state *state)
{
const struct intel_bw_state *old_bw_state;
struct intel_bw_state *new_bw_state;
int ret;
if (!intel_any_crtc_active_changed(state))
return 0;
new_bw_state = intel_atomic_get_bw_state(state);
if (IS_ERR(new_bw_state))
return PTR_ERR(new_bw_state);
old_bw_state = intel_atomic_get_old_bw_state(state);
new_bw_state->active_pipes =
intel_calc_active_pipes(state, old_bw_state->active_pipes);
ret = intel_atomic_lock_global_state(&new_bw_state->base);
if (ret)
return ret;
return 0;
}
static int intel_bw_check_sagv_mask(struct intel_atomic_state *state)
{
struct intel_display *display = to_intel_display(state);
@ -1346,10 +1316,6 @@ int intel_bw_atomic_check(struct intel_atomic_state *state)
if (DISPLAY_VER(display) < 9)
return 0;
ret = intel_bw_modeset_checks(state);
if (ret)
return ret;
ret = intel_bw_check_sagv_mask(state);
if (ret)
return ret;
@ -1410,7 +1376,6 @@ void intel_bw_update_hw_state(struct intel_display *display)
if (DISPLAY_VER(display) < 9)
return;
bw_state->active_pipes = 0;
bw_state->pipe_sagv_reject = 0;
for_each_intel_crtc(display->drm, crtc) {
@ -1418,9 +1383,6 @@ void intel_bw_update_hw_state(struct intel_display *display)
to_intel_crtc_state(crtc->base.state);
enum pipe pipe = crtc->pipe;
if (crtc_state->hw.active)
bw_state->active_pipes |= BIT(pipe);
if (DISPLAY_VER(display) >= 11)
intel_bw_crtc_update(bw_state, crtc_state);
@ -1504,10 +1466,6 @@ bool intel_bw_pmdemand_needs_update(struct intel_atomic_state *state)
bool intel_bw_can_enable_sagv(struct intel_display *display,
const struct intel_bw_state *bw_state)
{
if (DISPLAY_VER(display) < 11 &&
bw_state->active_pipes && !is_power_of_2(bw_state->active_pipes))
return false;
return bw_state->pipe_sagv_reject == 0;
}

View File

@ -61,10 +61,10 @@ const u16 filtercoeff_3[] = {
FILTER_COEFF_0_125,
};
static void intel_casf_filter_lut_load(struct intel_crtc *crtc,
const struct intel_crtc_state *crtc_state)
static void intel_casf_filter_lut_load(const struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(crtc_state);
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
int i;
intel_de_write(display, SHRPLUT_INDEX(crtc->pipe),
@ -75,53 +75,35 @@ static void intel_casf_filter_lut_load(struct intel_crtc *crtc,
sharpness_lut[i]);
}
void intel_casf_update_strength(struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(crtc_state);
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
int win_size;
intel_de_rmw(display, SHARPNESS_CTL(crtc->pipe), FILTER_STRENGTH_MASK,
FILTER_STRENGTH(crtc_state->hw.casf_params.strength));
win_size = intel_de_read(display, SKL_PS_WIN_SZ(crtc->pipe, 1));
intel_de_write_fw(display, SKL_PS_WIN_SZ(crtc->pipe, 1), win_size);
}
static void intel_casf_compute_win_size(struct intel_crtc_state *crtc_state)
{
const struct drm_display_mode *mode = &crtc_state->hw.adjusted_mode;
u32 total_pixels = mode->hdisplay * mode->vdisplay;
if (total_pixels <= MAX_PIXELS_FOR_3_TAP_FILTER)
crtc_state->hw.casf_params.win_size = SHARPNESS_FILTER_SIZE_3X3;
crtc_state->pch_pfit.casf.win_size = SHARPNESS_FILTER_SIZE_3X3;
else if (total_pixels <= MAX_PIXELS_FOR_5_TAP_FILTER)
crtc_state->hw.casf_params.win_size = SHARPNESS_FILTER_SIZE_5X5;
crtc_state->pch_pfit.casf.win_size = SHARPNESS_FILTER_SIZE_5X5;
else
crtc_state->hw.casf_params.win_size = SHARPNESS_FILTER_SIZE_7X7;
crtc_state->pch_pfit.casf.win_size = SHARPNESS_FILTER_SIZE_7X7;
}
static void intel_casf_scaler_compute_coef(struct intel_crtc_state *crtc_state);
int intel_casf_compute_config(struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(crtc_state);
if (!HAS_CASF(display))
if (crtc_state->hw.sharpness_strength == 0)
return 0;
if (crtc_state->uapi.sharpness_strength == 0) {
crtc_state->hw.casf_params.casf_enable = false;
crtc_state->hw.casf_params.strength = 0;
return 0;
}
/* CASF with joiner not supported in hardware */
if (crtc_state->joiner_pipes) {
drm_dbg_kms(display->drm, "CASF not supported with joiner\n");
return -EINVAL;
}
crtc_state->hw.casf_params.casf_enable = true;
crtc_state->pch_pfit.casf.enable = true;
/*
* HW takes a value in form (1.0 + strength) in 4.4 fixed format.
@ -131,12 +113,12 @@ int intel_casf_compute_config(struct intel_crtc_state *crtc_state)
* 6.3125 in 4.4 format is b01100101 which is equal to 101.
* Also 85 + 16 = 101.
*/
crtc_state->hw.casf_params.strength =
min(crtc_state->uapi.sharpness_strength, 0xEF) + 0x10;
crtc_state->pch_pfit.casf.strength =
min(crtc_state->hw.sharpness_strength, 0xEF) + 0x10;
intel_casf_compute_win_size(crtc_state);
intel_casf_scaler_compute_config(crtc_state);
intel_casf_scaler_compute_coef(crtc_state);
return 0;
}
@ -151,35 +133,27 @@ void intel_casf_sharpness_get_config(struct intel_crtc_state *crtc_state)
if (sharp & FILTER_EN) {
if (drm_WARN_ON(display->drm,
REG_FIELD_GET(FILTER_STRENGTH_MASK, sharp) < 16))
crtc_state->hw.casf_params.strength = 0;
crtc_state->pch_pfit.casf.strength = 0;
else
crtc_state->hw.casf_params.strength =
crtc_state->pch_pfit.casf.strength =
REG_FIELD_GET(FILTER_STRENGTH_MASK, sharp);
crtc_state->hw.casf_params.casf_enable = true;
crtc_state->hw.casf_params.win_size =
crtc_state->pch_pfit.casf.enable = true;
crtc_state->pch_pfit.casf.win_size =
REG_FIELD_GET(FILTER_SIZE_MASK, sharp);
}
}
bool intel_casf_needs_scaler(const struct intel_crtc_state *crtc_state)
{
if (crtc_state->hw.casf_params.casf_enable)
return true;
return false;
}
static int casf_coeff_tap(int i)
{
return i % SCALER_FILTER_NUM_TAPS;
}
static u32 casf_coeff(struct intel_crtc_state *crtc_state, int t)
static u32 casf_coeff(const struct intel_crtc_state *crtc_state, int t)
{
struct scaler_filter_coeff value;
u32 coeff;
value = crtc_state->hw.casf_params.coeff[t];
value = crtc_state->pch_pfit.casf.coeff[t];
value.sign = 0;
coeff = value.sign << 15 | value.exp << 12 | value.mantissa << 3;
@ -189,10 +163,10 @@ static u32 casf_coeff(struct intel_crtc_state *crtc_state, int t)
/*
* 17 phase of 7 taps requires 119 coefficients in 60 dwords per set.
* To enable casf: program scaler coefficients with the coeffients
* that are calculated and stored in hw.casf_params.coeff as per
* that are calculated and stored in pch_pfit.casf.coeff as per
* SCALER_COEFFICIENT_FORMAT
*/
static void intel_casf_write_coeff(struct intel_crtc_state *crtc_state)
static void intel_casf_write_coeff(const struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(crtc_state);
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
@ -240,16 +214,16 @@ static void convert_sharpness_coef_binary(struct scaler_filter_coeff *coeff,
}
}
void intel_casf_scaler_compute_config(struct intel_crtc_state *crtc_state)
static void intel_casf_scaler_compute_coef(struct intel_crtc_state *crtc_state)
{
const u16 *filtercoeff;
u16 filter_coeff[SCALER_FILTER_NUM_TAPS];
u16 sumcoeff = 0;
int i;
if (crtc_state->hw.casf_params.win_size == 0)
if (crtc_state->pch_pfit.casf.win_size == 0)
filtercoeff = filtercoeff_1;
else if (crtc_state->hw.casf_params.win_size == 1)
else if (crtc_state->pch_pfit.casf.win_size == 1)
filtercoeff = filtercoeff_2;
else
filtercoeff = filtercoeff_3;
@ -259,37 +233,13 @@ void intel_casf_scaler_compute_config(struct intel_crtc_state *crtc_state)
for (i = 0; i < SCALER_FILTER_NUM_TAPS; i++) {
filter_coeff[i] = (*(filtercoeff + i) * 100 / sumcoeff);
convert_sharpness_coef_binary(&crtc_state->hw.casf_params.coeff[i],
convert_sharpness_coef_binary(&crtc_state->pch_pfit.casf.coeff[i],
filter_coeff[i]);
}
}
void intel_casf_enable(struct intel_crtc_state *crtc_state)
void intel_casf_setup(const struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(crtc_state);
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
u32 sharpness_ctl;
intel_casf_filter_lut_load(crtc, crtc_state);
intel_casf_filter_lut_load(crtc_state);
intel_casf_write_coeff(crtc_state);
sharpness_ctl = FILTER_EN | FILTER_STRENGTH(crtc_state->hw.casf_params.strength);
sharpness_ctl |= crtc_state->hw.casf_params.win_size;
intel_de_write(display, SHARPNESS_CTL(crtc->pipe), sharpness_ctl);
skl_scaler_setup_casf(crtc_state);
}
void intel_casf_disable(const struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(crtc_state);
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
intel_de_write(display, SKL_PS_CTRL(crtc->pipe, 1), 0);
intel_de_write(display, SKL_PS_WIN_POS(crtc->pipe, 1), 0);
intel_de_write(display, SHARPNESS_CTL(crtc->pipe), 0);
intel_de_write(display, SKL_PS_WIN_SZ(crtc->pipe, 1), 0);
}

View File

@ -11,11 +11,7 @@
struct intel_crtc_state;
int intel_casf_compute_config(struct intel_crtc_state *crtc_state);
void intel_casf_update_strength(struct intel_crtc_state *new_crtc_state);
void intel_casf_sharpness_get_config(struct intel_crtc_state *crtc_state);
void intel_casf_enable(struct intel_crtc_state *crtc_state);
void intel_casf_disable(const struct intel_crtc_state *crtc_state);
void intel_casf_scaler_compute_config(struct intel_crtc_state *crtc_state);
bool intel_casf_needs_scaler(const struct intel_crtc_state *crtc_state);
void intel_casf_setup(const struct intel_crtc_state *crtc_state);
#endif /* __INTEL_CASF_H__ */

View File

@ -28,6 +28,7 @@
#include <drm/drm_fixed.h>
#include <drm/drm_print.h>
#include <drm/intel/intel_pcode_regs.h>
#include <drm/intel/pci_config.h>
#include <drm/intel/step.h>
#include "hsw_ips.h"
@ -42,9 +43,8 @@
#include "intel_display_utils.h"
#include "intel_display_wa.h"
#include "intel_dram.h"
#include "intel_mchbar_regs.h"
#include "intel_mchbar.h"
#include "intel_parent.h"
#include "intel_pci_config.h"
#include "intel_plane.h"
#include "intel_psr.h"
#include "intel_vdsc.h"
@ -170,27 +170,27 @@ struct intel_cdclk_funcs {
void intel_cdclk_get_cdclk(struct intel_display *display,
struct intel_cdclk_config *cdclk_config)
{
display->funcs.cdclk->get_cdclk(display, cdclk_config);
display->cdclk.funcs->get_cdclk(display, cdclk_config);
}
static void intel_cdclk_set_cdclk(struct intel_display *display,
const struct intel_cdclk_config *cdclk_config,
enum pipe pipe)
{
display->funcs.cdclk->set_cdclk(display, cdclk_config, pipe);
display->cdclk.funcs->set_cdclk(display, cdclk_config, pipe);
}
static int intel_cdclk_modeset_calc_cdclk(struct intel_atomic_state *state)
{
struct intel_display *display = to_intel_display(state);
return display->funcs.cdclk->modeset_calc_cdclk(state);
return display->cdclk.funcs->modeset_calc_cdclk(state);
}
static u8 intel_cdclk_calc_voltage_level(struct intel_display *display,
int cdclk)
{
return display->funcs.cdclk->calc_voltage_level(cdclk);
return display->cdclk.funcs->calc_voltage_level(cdclk);
}
static void fixed_133mhz_get_cdclk(struct intel_display *display,
@ -376,8 +376,8 @@ static unsigned int intel_hpll_vco(struct intel_display *display)
else
return 0;
tmp = intel_de_read(display, display->platform.pineview ||
display->platform.mobile ? HPLLVCO_MOBILE : HPLLVCO);
tmp = intel_mchbar_read(display, display->platform.pineview ||
display->platform.mobile ? HPLLVCO_MOBILE : HPLLVCO);
vco = vco_table[tmp & 0x7];
if (vco == 0)
@ -613,9 +613,9 @@ static void vlv_get_cdclk(struct intel_display *display,
cdclk_config->vco = vlv_clock_get_hpll_vco(display->drm);
cdclk_config->cdclk = vlv_clock_get_cdclk(display->drm);
vlv_punit_get(display->drm);
val = vlv_punit_read(display->drm, PUNIT_REG_DSPSSPM);
vlv_punit_put(display->drm);
vlv_punit_get(display);
val = vlv_punit_read(display, PUNIT_REG_DSPSSPM);
vlv_punit_put(display);
if (display->platform.valleyview)
cdclk_config->voltage_level = (val & DSPFREQGUAR_MASK) >>
@ -691,17 +691,17 @@ static void vlv_set_cdclk(struct intel_display *display,
*/
wakeref = intel_display_power_get(display, POWER_DOMAIN_DISPLAY_CORE);
vlv_iosf_sb_get(display->drm,
BIT(VLV_IOSF_SB_CCK) |
BIT(VLV_IOSF_SB_BUNIT) |
BIT(VLV_IOSF_SB_PUNIT));
intel_parent_vlv_iosf_get(display,
BIT(VLV_IOSF_SB_CCK) |
BIT(VLV_IOSF_SB_BUNIT) |
BIT(VLV_IOSF_SB_PUNIT));
val = vlv_punit_read(display->drm, PUNIT_REG_DSPSSPM);
val = vlv_punit_read(display, PUNIT_REG_DSPSSPM);
val &= ~DSPFREQGUAR_MASK;
val |= (cmd << DSPFREQGUAR_SHIFT);
vlv_punit_write(display->drm, PUNIT_REG_DSPSSPM, val);
vlv_punit_write(display, PUNIT_REG_DSPSSPM, val);
ret = poll_timeout_us(val = vlv_punit_read(display->drm, PUNIT_REG_DSPSSPM),
ret = poll_timeout_us(val = vlv_punit_read(display, PUNIT_REG_DSPSSPM),
(val & DSPFREQSTAT_MASK) == (cmd << DSPFREQSTAT_SHIFT),
500, 50 * 1000, false);
if (ret)
@ -714,12 +714,12 @@ static void vlv_set_cdclk(struct intel_display *display,
cdclk) - 1;
/* adjust cdclk divider */
val = vlv_cck_read(display->drm, CCK_DISPLAY_CLOCK_CONTROL);
val = vlv_cck_read(display, CCK_DISPLAY_CLOCK_CONTROL);
val &= ~CCK_FREQUENCY_VALUES;
val |= divider;
vlv_cck_write(display->drm, CCK_DISPLAY_CLOCK_CONTROL, val);
vlv_cck_write(display, CCK_DISPLAY_CLOCK_CONTROL, val);
ret = poll_timeout_us(val = vlv_cck_read(display->drm, CCK_DISPLAY_CLOCK_CONTROL),
ret = poll_timeout_us(val = vlv_cck_read(display, CCK_DISPLAY_CLOCK_CONTROL),
(val & CCK_FREQUENCY_STATUS) == (divider << CCK_FREQUENCY_STATUS_SHIFT),
500, 50 * 1000, false);
if (ret)
@ -727,7 +727,7 @@ static void vlv_set_cdclk(struct intel_display *display,
}
/* adjust self-refresh exit latency value */
val = vlv_bunit_read(display->drm, BUNIT_REG_BISOC);
val = vlv_bunit_read(display, BUNIT_REG_BISOC);
val &= ~0x7f;
/*
@ -738,12 +738,12 @@ static void vlv_set_cdclk(struct intel_display *display,
val |= 4500 / 250; /* 4.5 usec */
else
val |= 3000 / 250; /* 3.0 usec */
vlv_bunit_write(display->drm, BUNIT_REG_BISOC, val);
vlv_bunit_write(display, BUNIT_REG_BISOC, val);
vlv_iosf_sb_put(display->drm,
BIT(VLV_IOSF_SB_CCK) |
BIT(VLV_IOSF_SB_BUNIT) |
BIT(VLV_IOSF_SB_PUNIT));
intel_parent_vlv_iosf_put(display,
BIT(VLV_IOSF_SB_CCK) |
BIT(VLV_IOSF_SB_BUNIT) |
BIT(VLV_IOSF_SB_PUNIT));
intel_update_cdclk(display);
@ -780,19 +780,19 @@ static void chv_set_cdclk(struct intel_display *display,
*/
wakeref = intel_display_power_get(display, POWER_DOMAIN_DISPLAY_CORE);
vlv_punit_get(display->drm);
val = vlv_punit_read(display->drm, PUNIT_REG_DSPSSPM);
vlv_punit_get(display);
val = vlv_punit_read(display, PUNIT_REG_DSPSSPM);
val &= ~DSPFREQGUAR_MASK_CHV;
val |= (cmd << DSPFREQGUAR_SHIFT_CHV);
vlv_punit_write(display->drm, PUNIT_REG_DSPSSPM, val);
vlv_punit_write(display, PUNIT_REG_DSPSSPM, val);
ret = poll_timeout_us(val = vlv_punit_read(display->drm, PUNIT_REG_DSPSSPM),
ret = poll_timeout_us(val = vlv_punit_read(display, PUNIT_REG_DSPSSPM),
(val & DSPFREQSTAT_MASK_CHV) == (cmd << DSPFREQSTAT_SHIFT_CHV),
500, 50 * 1000, false);
if (ret)
drm_err(display->drm, "timed out waiting for CDCLK change\n");
vlv_punit_put(display->drm);
vlv_punit_put(display);
intel_update_cdclk(display);
@ -2619,7 +2619,7 @@ static void intel_set_cdclk(struct intel_display *display,
if (!intel_cdclk_changed(&display->cdclk.hw, cdclk_config))
return;
if (drm_WARN_ON_ONCE(display->drm, !display->funcs.cdclk->set_cdclk))
if (drm_WARN_ON_ONCE(display->drm, !display->cdclk.funcs->set_cdclk))
return;
intel_cdclk_dump_config(display, cdclk_config, context);
@ -4042,100 +4042,100 @@ static const struct intel_cdclk_funcs i830_cdclk_funcs = {
void intel_init_cdclk_hooks(struct intel_display *display)
{
if (DISPLAY_VER(display) >= 35) {
display->funcs.cdclk = &xe3lpd_cdclk_funcs;
display->cdclk.funcs = &xe3lpd_cdclk_funcs;
display->cdclk.table = xe3p_lpd_cdclk_table;
} else if (DISPLAY_VER(display) >= 30) {
display->funcs.cdclk = &xe3lpd_cdclk_funcs;
display->cdclk.funcs = &xe3lpd_cdclk_funcs;
display->cdclk.table = xe3lpd_cdclk_table;
} else if (DISPLAY_VER(display) >= 20) {
display->funcs.cdclk = &rplu_cdclk_funcs;
display->cdclk.funcs = &rplu_cdclk_funcs;
display->cdclk.table = xe2lpd_cdclk_table;
} else if (DISPLAY_VERx100(display) >= 1401) {
display->funcs.cdclk = &rplu_cdclk_funcs;
display->cdclk.funcs = &rplu_cdclk_funcs;
display->cdclk.table = xe2hpd_cdclk_table;
} else if (DISPLAY_VER(display) >= 14) {
display->funcs.cdclk = &rplu_cdclk_funcs;
display->cdclk.funcs = &rplu_cdclk_funcs;
display->cdclk.table = mtl_cdclk_table;
} else if (display->platform.dg2) {
display->funcs.cdclk = &tgl_cdclk_funcs;
display->cdclk.funcs = &tgl_cdclk_funcs;
display->cdclk.table = dg2_cdclk_table;
} else if (display->platform.alderlake_p) {
/* Wa_22011320316:adl-p[a0] */
if (intel_display_wa(display, INTEL_DISPLAY_WA_22011320316)) {
display->cdclk.table = adlp_a_step_cdclk_table;
display->funcs.cdclk = &tgl_cdclk_funcs;
display->cdclk.funcs = &tgl_cdclk_funcs;
} else if (display->platform.alderlake_p_raptorlake_u) {
display->cdclk.table = rplu_cdclk_table;
display->funcs.cdclk = &rplu_cdclk_funcs;
display->cdclk.funcs = &rplu_cdclk_funcs;
} else {
display->cdclk.table = adlp_cdclk_table;
display->funcs.cdclk = &tgl_cdclk_funcs;
display->cdclk.funcs = &tgl_cdclk_funcs;
}
} else if (display->platform.rocketlake) {
display->funcs.cdclk = &tgl_cdclk_funcs;
display->cdclk.funcs = &tgl_cdclk_funcs;
display->cdclk.table = rkl_cdclk_table;
} else if (DISPLAY_VER(display) >= 12) {
display->funcs.cdclk = &tgl_cdclk_funcs;
display->cdclk.funcs = &tgl_cdclk_funcs;
display->cdclk.table = icl_cdclk_table;
} else if (display->platform.jasperlake || display->platform.elkhartlake) {
display->funcs.cdclk = &ehl_cdclk_funcs;
display->cdclk.funcs = &ehl_cdclk_funcs;
display->cdclk.table = icl_cdclk_table;
} else if (DISPLAY_VER(display) >= 11) {
display->funcs.cdclk = &icl_cdclk_funcs;
display->cdclk.funcs = &icl_cdclk_funcs;
display->cdclk.table = icl_cdclk_table;
} else if (display->platform.geminilake || display->platform.broxton) {
display->funcs.cdclk = &bxt_cdclk_funcs;
display->cdclk.funcs = &bxt_cdclk_funcs;
if (display->platform.geminilake)
display->cdclk.table = glk_cdclk_table;
else
display->cdclk.table = bxt_cdclk_table;
} else if (DISPLAY_VER(display) == 9) {
display->funcs.cdclk = &skl_cdclk_funcs;
display->cdclk.funcs = &skl_cdclk_funcs;
} else if (display->platform.broadwell) {
display->funcs.cdclk = &bdw_cdclk_funcs;
display->cdclk.funcs = &bdw_cdclk_funcs;
} else if (display->platform.haswell) {
display->funcs.cdclk = &hsw_cdclk_funcs;
display->cdclk.funcs = &hsw_cdclk_funcs;
} else if (display->platform.cherryview) {
display->funcs.cdclk = &chv_cdclk_funcs;
display->cdclk.funcs = &chv_cdclk_funcs;
} else if (display->platform.valleyview) {
display->funcs.cdclk = &vlv_cdclk_funcs;
display->cdclk.funcs = &vlv_cdclk_funcs;
} else if (display->platform.sandybridge || display->platform.ivybridge) {
display->funcs.cdclk = &fixed_400mhz_cdclk_funcs;
display->cdclk.funcs = &fixed_400mhz_cdclk_funcs;
} else if (display->platform.ironlake) {
display->funcs.cdclk = &ilk_cdclk_funcs;
display->cdclk.funcs = &ilk_cdclk_funcs;
} else if (display->platform.gm45) {
display->funcs.cdclk = &gm45_cdclk_funcs;
display->cdclk.funcs = &gm45_cdclk_funcs;
} else if (display->platform.g45) {
display->funcs.cdclk = &g33_cdclk_funcs;
display->cdclk.funcs = &g33_cdclk_funcs;
} else if (display->platform.i965gm) {
display->funcs.cdclk = &i965gm_cdclk_funcs;
display->cdclk.funcs = &i965gm_cdclk_funcs;
} else if (display->platform.i965g) {
display->funcs.cdclk = &fixed_400mhz_cdclk_funcs;
display->cdclk.funcs = &fixed_400mhz_cdclk_funcs;
} else if (display->platform.pineview) {
display->funcs.cdclk = &pnv_cdclk_funcs;
display->cdclk.funcs = &pnv_cdclk_funcs;
} else if (display->platform.g33) {
display->funcs.cdclk = &g33_cdclk_funcs;
display->cdclk.funcs = &g33_cdclk_funcs;
} else if (display->platform.i945gm) {
display->funcs.cdclk = &i945gm_cdclk_funcs;
display->cdclk.funcs = &i945gm_cdclk_funcs;
} else if (display->platform.i945g) {
display->funcs.cdclk = &fixed_400mhz_cdclk_funcs;
display->cdclk.funcs = &fixed_400mhz_cdclk_funcs;
} else if (display->platform.i915gm) {
display->funcs.cdclk = &i915gm_cdclk_funcs;
display->cdclk.funcs = &i915gm_cdclk_funcs;
} else if (display->platform.i915g) {
display->funcs.cdclk = &i915g_cdclk_funcs;
display->cdclk.funcs = &i915g_cdclk_funcs;
} else if (display->platform.i865g) {
display->funcs.cdclk = &i865g_cdclk_funcs;
display->cdclk.funcs = &i865g_cdclk_funcs;
} else if (display->platform.i85x) {
display->funcs.cdclk = &i85x_cdclk_funcs;
display->cdclk.funcs = &i85x_cdclk_funcs;
} else if (display->platform.i845g) {
display->funcs.cdclk = &i845g_cdclk_funcs;
display->cdclk.funcs = &i845g_cdclk_funcs;
} else if (display->platform.i830) {
display->funcs.cdclk = &i830_cdclk_funcs;
display->cdclk.funcs = &i830_cdclk_funcs;
}
if (drm_WARN(display->drm, !display->funcs.cdclk,
if (drm_WARN(display->drm, !display->cdclk.funcs,
"Unknown platform. Assuming i830\n"))
display->funcs.cdclk = &i830_cdclk_funcs;
display->cdclk.funcs = &i830_cdclk_funcs;
}
int intel_cdclk_logical(const struct intel_cdclk_state *cdclk_state)

View File

@ -1933,7 +1933,7 @@ void intel_color_load_luts(const struct intel_crtc_state *crtc_state)
if (crtc_state->dsb_color)
return;
display->funcs.color->load_luts(crtc_state);
display->color.funcs->load_luts(crtc_state);
}
void intel_color_commit_noarm(struct intel_dsb *dsb,
@ -1941,8 +1941,8 @@ void intel_color_commit_noarm(struct intel_dsb *dsb,
{
struct intel_display *display = to_intel_display(crtc_state);
if (display->funcs.color->color_commit_noarm)
display->funcs.color->color_commit_noarm(dsb, crtc_state);
if (display->color.funcs->color_commit_noarm)
display->color.funcs->color_commit_noarm(dsb, crtc_state);
}
void intel_color_commit_arm(struct intel_dsb *dsb,
@ -1950,15 +1950,15 @@ void intel_color_commit_arm(struct intel_dsb *dsb,
{
struct intel_display *display = to_intel_display(crtc_state);
display->funcs.color->color_commit_arm(dsb, crtc_state);
display->color.funcs->color_commit_arm(dsb, crtc_state);
}
void intel_color_post_update(const struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(crtc_state);
if (display->funcs.color->color_post_update)
display->funcs.color->color_post_update(crtc_state);
if (display->color.funcs->color_post_update)
display->color.funcs->color_post_update(crtc_state);
}
void intel_color_modeset(const struct intel_crtc_state *crtc_state)
@ -2022,7 +2022,7 @@ void intel_color_prepare_commit(struct intel_atomic_state *state,
if (!intel_color_uses_dsb(crtc_state))
return;
display->funcs.color->load_luts(crtc_state);
display->color.funcs->load_luts(crtc_state);
if (crtc_state->use_dsb && intel_color_uses_chained_dsb(crtc_state)) {
intel_vrr_send_push(crtc_state->dsb_color, crtc_state);
@ -2113,19 +2113,19 @@ int intel_color_check(struct intel_atomic_state *state,
if (!intel_crtc_needs_color_update(new_crtc_state))
return 0;
return display->funcs.color->color_check(state, crtc);
return display->color.funcs->color_check(state, crtc);
}
void intel_color_get_config(struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(crtc_state);
display->funcs.color->get_config(crtc_state);
display->color.funcs->get_config(crtc_state);
display->funcs.color->read_luts(crtc_state);
display->color.funcs->read_luts(crtc_state);
if (display->funcs.color->read_csc)
display->funcs.color->read_csc(crtc_state);
if (display->color.funcs->read_csc)
display->color.funcs->read_csc(crtc_state);
}
bool intel_color_lut_equal(const struct intel_crtc_state *crtc_state,
@ -2142,7 +2142,7 @@ bool intel_color_lut_equal(const struct intel_crtc_state *crtc_state,
if (!is_pre_csc_lut && crtc_state->c8_planes)
return true;
return display->funcs.color->lut_equal(crtc_state, blob1, blob2,
return display->color.funcs->lut_equal(crtc_state, blob1, blob2,
is_pre_csc_lut);
}
@ -4253,8 +4253,8 @@ intel_color_load_plane_csc_matrix(struct intel_dsb *dsb,
{
struct intel_display *display = to_intel_display(plane_state);
if (display->funcs.color->load_plane_csc_matrix)
display->funcs.color->load_plane_csc_matrix(dsb, plane_state);
if (display->color.funcs->load_plane_csc_matrix)
display->color.funcs->load_plane_csc_matrix(dsb, plane_state);
}
static void
@ -4263,8 +4263,8 @@ intel_color_load_plane_luts(struct intel_dsb *dsb,
{
struct intel_display *display = to_intel_display(plane_state);
if (display->funcs.color->load_plane_luts)
display->funcs.color->load_plane_luts(dsb, plane_state);
if (display->color.funcs->load_plane_luts)
display->color.funcs->load_plane_luts(dsb, plane_state);
}
bool
@ -4346,29 +4346,29 @@ void intel_color_init_hooks(struct intel_display *display)
{
if (HAS_GMCH(display)) {
if (display->platform.cherryview)
display->funcs.color = &chv_color_funcs;
display->color.funcs = &chv_color_funcs;
else if (display->platform.valleyview)
display->funcs.color = &vlv_color_funcs;
display->color.funcs = &vlv_color_funcs;
else if (DISPLAY_VER(display) >= 4)
display->funcs.color = &i965_color_funcs;
display->color.funcs = &i965_color_funcs;
else
display->funcs.color = &i9xx_color_funcs;
display->color.funcs = &i9xx_color_funcs;
} else {
if (DISPLAY_VER(display) >= 12)
display->funcs.color = &tgl_color_funcs;
display->color.funcs = &tgl_color_funcs;
else if (DISPLAY_VER(display) == 11)
display->funcs.color = &icl_color_funcs;
display->color.funcs = &icl_color_funcs;
else if (DISPLAY_VER(display) == 10)
display->funcs.color = &glk_color_funcs;
display->color.funcs = &glk_color_funcs;
else if (DISPLAY_VER(display) == 9)
display->funcs.color = &skl_color_funcs;
display->color.funcs = &skl_color_funcs;
else if (DISPLAY_VER(display) == 8)
display->funcs.color = &bdw_color_funcs;
display->color.funcs = &bdw_color_funcs;
else if (display->platform.haswell)
display->funcs.color = &hsw_color_funcs;
display->color.funcs = &hsw_color_funcs;
else if (DISPLAY_VER(display) == 7)
display->funcs.color = &ivb_color_funcs;
display->color.funcs = &ivb_color_funcs;
else
display->funcs.color = &ilk_color_funcs;
display->color.funcs = &ilk_color_funcs;
}
}

View File

@ -250,7 +250,7 @@ void intel_crtc_state_dump(const struct intel_crtc_state *pipe_config,
str_enabled_disabled(pipe_config->has_sel_update),
str_enabled_disabled(pipe_config->has_panel_replay),
str_enabled_disabled(pipe_config->enable_psr2_sel_fetch));
drm_printf(&p, "minimum HBlank: %d\n", pipe_config->min_hblank);
drm_printf(&p, "minimum hblank: %d\n", pipe_config->min_hblank);
}
drm_printf(&p, "audio: %i, infoframes: %i, infoframes enabled: 0x%x\n",
@ -320,19 +320,23 @@ void intel_crtc_state_dump(const struct intel_crtc_state *pipe_config,
drm_printf(&p, "pipe mode: " DRM_MODE_FMT "\n",
DRM_MODE_ARG(&pipe_config->hw.pipe_mode));
intel_dump_crtc_timings(&p, &pipe_config->hw.pipe_mode);
drm_printf(&p, "port clock: %d, pipe src: " DRM_RECT_FMT ", pixel rate %d, min cdclk %d\n",
pipe_config->port_clock, DRM_RECT_ARG(&pipe_config->pipe_src),
pipe_config->pixel_rate, pipe_config->min_cdclk);
drm_printf(&p, "port clock: %d, pixel rate %d, min cdclk %d, min voltage level %d\n",
pipe_config->port_clock, pipe_config->pixel_rate,
pipe_config->min_cdclk, pipe_config->min_voltage_level);
drm_printf(&p, "linetime: %d, ips linetime: %d\n",
pipe_config->linetime, pipe_config->ips_linetime);
if (DISPLAY_VER(display) >= 9)
drm_printf(&p, "num_scalers: %d, scaler_users: 0x%x, scaler_id: %d, scaling_filter: %d\n",
drm_printf(&p, "num_scalers: %d, scaler_users: 0x%x, scaler_id: %d, scaling_filter: %d, sharpness_strength: %d\n",
crtc->num_scalers,
pipe_config->scaler_state.scaler_users,
pipe_config->scaler_state.scaler_id,
pipe_config->hw.scaling_filter);
pipe_config->hw.scaling_filter,
pipe_config->hw.sharpness_strength);
drm_printf(&p, "pipe src: " DRM_RECT_FMT "\n",
DRM_RECT_ARG(&pipe_config->pipe_src));
if (HAS_GMCH(display))
drm_printf(&p, "gmch pfit: control: 0x%08x, ratios: 0x%08x, lvds border: 0x%08x\n",
@ -345,6 +349,11 @@ void intel_crtc_state_dump(const struct intel_crtc_state *pipe_config,
str_enabled_disabled(pipe_config->pch_pfit.enabled),
str_yes_no(pipe_config->pch_pfit.force_thru));
drm_printf(&p, "sharpness strength: %d, sharpness tap size: %d, sharpness enable: %d\n",
pipe_config->pch_pfit.casf.strength,
pipe_config->pch_pfit.casf.win_size,
pipe_config->pch_pfit.casf.enable);
drm_printf(&p, "ips: %i, double wide: %i, drrs: %i\n",
pipe_config->ips_enabled, pipe_config->double_wide,
pipe_config->has_drrs);
@ -380,11 +389,6 @@ void intel_crtc_state_dump(const struct intel_crtc_state *pipe_config,
intel_vdsc_state_dump(&p, 0, pipe_config);
drm_printf(&p, "sharpness strength: %d, sharpness tap size: %d, sharpness enable: %d\n",
pipe_config->hw.casf_params.strength,
pipe_config->hw.casf_params.win_size,
pipe_config->hw.casf_params.casf_enable);
dump_planes:
if (!state)
return;

View File

@ -492,7 +492,7 @@ void intel_cx0_phy_set_signal_levels(struct intel_encoder *encoder,
wakeref = intel_cx0_phy_transaction_begin(encoder);
trans = encoder->get_buf_trans(encoder, crtc_state, &n_entries);
trans = intel_ddi_buf_trans_get(encoder, crtc_state, &n_entries);
if (drm_WARN_ON_ONCE(display->drm, !trans)) {
intel_cx0_phy_transaction_end(encoder, wakeref);
return;

View File

@ -140,7 +140,7 @@ void hsw_prepare_dp_ddi_buffers(struct intel_encoder *encoder,
enum port port = encoder->port;
const struct intel_ddi_buf_trans *trans;
trans = encoder->get_buf_trans(encoder, crtc_state, &n_entries);
trans = intel_ddi_buf_trans_get(encoder, crtc_state, &n_entries);
if (drm_WARN_ON_ONCE(display->drm, !trans))
return;
@ -172,7 +172,7 @@ static void hsw_prepare_hdmi_ddi_buffers(struct intel_encoder *encoder,
enum port port = encoder->port;
const struct intel_ddi_buf_trans *trans;
trans = encoder->get_buf_trans(encoder, crtc_state, &n_entries);
trans = intel_ddi_buf_trans_get(encoder, crtc_state, &n_entries);
if (drm_WARN_ON_ONCE(display->drm, !trans))
return;
@ -1106,7 +1106,7 @@ static void skl_ddi_set_iboost(struct intel_encoder *encoder,
const struct intel_ddi_buf_trans *trans;
int n_entries;
trans = encoder->get_buf_trans(encoder, crtc_state, &n_entries);
trans = intel_ddi_buf_trans_get(encoder, crtc_state, &n_entries);
if (drm_WARN_ON_ONCE(display->drm, !trans))
return;
@ -1132,7 +1132,7 @@ static u8 intel_ddi_dp_voltage_max(struct intel_dp *intel_dp,
struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
int n_entries;
encoder->get_buf_trans(encoder, crtc_state, &n_entries);
intel_ddi_buf_trans_get(encoder, crtc_state, &n_entries);
if (drm_WARN_ON(display->drm, n_entries < 1))
n_entries = 1;
@ -1175,7 +1175,7 @@ static void icl_ddi_combo_vswing_program(struct intel_encoder *encoder,
int n_entries, ln;
u32 val;
trans = encoder->get_buf_trans(encoder, crtc_state, &n_entries);
trans = intel_ddi_buf_trans_get(encoder, crtc_state, &n_entries);
if (drm_WARN_ON_ONCE(display->drm, !trans))
return;
@ -1293,7 +1293,7 @@ static void icl_mg_phy_set_signal_levels(struct intel_encoder *encoder,
if (intel_tc_port_in_tbt_alt_mode(enc_to_dig_port(encoder)))
return;
trans = encoder->get_buf_trans(encoder, crtc_state, &n_entries);
trans = intel_ddi_buf_trans_get(encoder, crtc_state, &n_entries);
if (drm_WARN_ON_ONCE(display->drm, !trans))
return;
@ -1394,7 +1394,7 @@ static void tgl_dkl_phy_set_signal_levels(struct intel_encoder *encoder,
if (intel_tc_port_in_tbt_alt_mode(enc_to_dig_port(encoder)))
return;
trans = encoder->get_buf_trans(encoder, crtc_state, &n_entries);
trans = intel_ddi_buf_trans_get(encoder, crtc_state, &n_entries);
if (drm_WARN_ON_ONCE(display->drm, !trans))
return;
@ -1511,7 +1511,7 @@ int intel_ddi_level(struct intel_encoder *encoder,
const struct intel_ddi_buf_trans *trans;
int level, n_entries;
trans = encoder->get_buf_trans(encoder, crtc_state, &n_entries);
trans = intel_ddi_buf_trans_get(encoder, crtc_state, &n_entries);
if (drm_WARN_ON_ONCE(display->drm, !trans))
return 0;

View File

@ -1123,8 +1123,8 @@ static const union intel_ddi_buf_trans_entry _xe3plpd_lt_trans_dp14[] = {
{ .lt = { 1, 2, 0, 28, 7 } },
{ .lt = { 0, 3, 0, 35, 13 } },
{ .lt = { 1, 1, 0, 27, 0 } },
{ .lt = { 1, 2, 0, 31, 4 } },
{ .lt = { 0, 3, 0, 39, 9 } },
{ .lt = { 1, 2, 0, 31, 5 } },
{ .lt = { 0, 3, 0, 37, 11 } },
{ .lt = { 1, 2, 0, 35, 0 } },
{ .lt = { 0, 3, 0, 41, 7 } },
{ .lt = { 0, 3, 0, 48, 0 } },
@ -1852,3 +1852,10 @@ void intel_ddi_buf_trans_init(struct intel_encoder *encoder)
MISSING_CASE(pdev->device);
}
}
const struct intel_ddi_buf_trans *intel_ddi_buf_trans_get(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
int *n_entries)
{
return encoder->get_buf_trans(encoder, crtc_state, n_entries);
}

View File

@ -77,5 +77,8 @@ struct intel_ddi_buf_trans {
bool is_hobl_buf_trans(const struct intel_ddi_buf_trans *table);
void intel_ddi_buf_trans_init(struct intel_encoder *encoder);
const struct intel_ddi_buf_trans *
intel_ddi_buf_trans_get(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state, int *n_entries);
#endif

View File

@ -176,3 +176,11 @@ void intel_de_write8(struct intel_display *display, i915_reg_t reg, u8 val)
intel_uncore_write8(__to_uncore(display), reg, val);
}
u16 intel_de_read16(struct intel_display *display, i915_reg_t reg)
{
/* this is only used on MCHBAR registers on pre-SNB */
drm_WARN_ON(display->drm, DISPLAY_VER(display) >= 6);
return intel_uncore_read16(__to_uncore(display), reg);
}

View File

@ -19,6 +19,7 @@ static inline struct intel_uncore *__to_uncore(struct intel_display *display)
u8 intel_de_read8(struct intel_display *display, i915_reg_t reg);
void intel_de_write8(struct intel_display *display, i915_reg_t reg, u8 val);
u16 intel_de_read16(struct intel_display *display, i915_reg_t reg);
static inline u32
intel_de_read(struct intel_display *display, i915_reg_t reg)
@ -35,8 +36,8 @@ intel_de_read(struct intel_display *display, i915_reg_t reg)
}
static inline u64
intel_de_read64_2x32(struct intel_display *display,
i915_reg_t lower_reg, i915_reg_t upper_reg)
intel_de_read64_2x32_volatile(struct intel_display *display,
i915_reg_t lower_reg, i915_reg_t upper_reg)
{
u64 val;
@ -52,6 +53,18 @@ intel_de_read64_2x32(struct intel_display *display,
return val;
}
static inline u64
intel_de_read64_2x32(struct intel_display *display, i915_reg_t reg)
{
i915_reg_t upper_reg = _MMIO(i915_mmio_reg_offset(reg) + 4);
u32 lower, upper;
lower = intel_de_read(display, reg);
upper = intel_de_read(display, upper_reg);
return (u64)upper << 32 | lower;
}
static inline void
intel_de_posting_read(struct intel_display *display, i915_reg_t reg)
{

View File

@ -58,7 +58,6 @@
#include "intel_audio.h"
#include "intel_bo.h"
#include "intel_bw.h"
#include "intel_casf.h"
#include "intel_cdclk.h"
#include "intel_clock_gating.h"
#include "intel_color.h"
@ -988,24 +987,6 @@ static bool audio_disabling(const struct intel_crtc_state *old_crtc_state,
memcmp(old_crtc_state->eld, new_crtc_state->eld, MAX_ELD_BYTES) != 0);
}
static bool intel_casf_enabling(const struct intel_crtc_state *new_crtc_state,
const struct intel_crtc_state *old_crtc_state)
{
if (!new_crtc_state->hw.active)
return false;
return is_enabling(hw.casf_params.casf_enable, old_crtc_state, new_crtc_state);
}
static bool intel_casf_disabling(const struct intel_crtc_state *old_crtc_state,
const struct intel_crtc_state *new_crtc_state)
{
if (!new_crtc_state->hw.active)
return false;
return is_disabling(hw.casf_params.casf_enable, old_crtc_state, new_crtc_state);
}
static bool intel_crtc_lobf_enabling(const struct intel_crtc_state *old_crtc_state,
const struct intel_crtc_state *new_crtc_state)
{
@ -1187,9 +1168,6 @@ static void intel_pre_plane_update(struct intel_atomic_state *state,
if (audio_disabling(old_crtc_state, new_crtc_state))
intel_encoders_audio_disable(state, crtc);
if (intel_casf_disabling(old_crtc_state, new_crtc_state))
intel_casf_disable(new_crtc_state);
intel_drrs_deactivate(old_crtc_state);
if (hsw_ips_pre_update(state, crtc))
@ -2184,7 +2162,7 @@ static void i9xx_crtc_disable(struct intel_atomic_state *state,
if (DISPLAY_VER(display) != 2)
intel_set_cpu_fifo_underrun_reporting(display, pipe, false);
if (!display->funcs.wm->initial_watermarks)
if (!display->wm.funcs->initial_watermarks)
intel_update_watermarks(display);
/* clock the pipe down to 640x480@60 to potentially save power */
@ -4073,7 +4051,7 @@ bool intel_crtc_get_pipe_config(struct intel_crtc_state *crtc_state)
struct intel_display *display = to_intel_display(crtc_state);
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
if (!display->funcs.display->get_pipe_config(crtc, crtc_state))
if (!display->modeset.funcs->get_pipe_config(crtc, crtc_state))
return false;
crtc_state->hw.active = true;
@ -4308,14 +4286,9 @@ static int intel_crtc_atomic_check(struct intel_atomic_state *state,
return ret;
}
ret = intel_casf_compute_config(crtc_state);
if (ret)
return ret;
if (DISPLAY_VER(display) >= 9) {
if (intel_crtc_needs_modeset(crtc_state) ||
intel_crtc_needs_fastset(crtc_state) ||
intel_casf_needs_scaler(crtc_state)) {
intel_crtc_needs_fastset(crtc_state)) {
ret = skl_update_scaler_crtc(crtc_state);
if (ret)
return ret;
@ -4550,6 +4523,7 @@ intel_crtc_copy_uapi_to_hw_state_modeset(struct intel_atomic_state *state,
drm_mode_copy(&crtc_state->hw.adjusted_mode,
&crtc_state->uapi.adjusted_mode);
crtc_state->hw.scaling_filter = crtc_state->uapi.scaling_filter;
crtc_state->hw.sharpness_strength = crtc_state->uapi.sharpness_strength;
intel_crtc_copy_uapi_to_hw_state_nomodeset(state, crtc);
}
@ -4615,6 +4589,7 @@ copy_joiner_crtc_state_modeset(struct intel_atomic_state *state,
drm_mode_copy(&secondary_crtc_state->hw.adjusted_mode,
&primary_crtc_state->hw.adjusted_mode);
secondary_crtc_state->hw.scaling_filter = primary_crtc_state->hw.scaling_filter;
secondary_crtc_state->hw.sharpness_strength = primary_crtc_state->hw.sharpness_strength;
if (primary_crtc_state->dp_tunnel_ref.tunnel)
drm_dp_tunnel_ref_get(primary_crtc_state->dp_tunnel_ref.tunnel,
@ -5368,12 +5343,12 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
PIPE_CONF_CHECK_BOOL(pch_pfit.enabled);
PIPE_CONF_CHECK_RECT(pch_pfit.dst);
PIPE_CONF_CHECK_BOOL(pch_pfit.casf.enable);
PIPE_CONF_CHECK_I(pch_pfit.casf.win_size);
PIPE_CONF_CHECK_I(pch_pfit.casf.strength);
PIPE_CONF_CHECK_I(scaler_state.scaler_id);
PIPE_CONF_CHECK_I(pixel_rate);
PIPE_CONF_CHECK_BOOL(hw.casf_params.casf_enable);
PIPE_CONF_CHECK_I(hw.casf_params.win_size);
PIPE_CONF_CHECK_I(hw.casf_params.strength);
PIPE_CONF_CHECK_X(gamma_mode);
if (display->platform.cherryview)
@ -6428,6 +6403,10 @@ int intel_atomic_check(struct drm_device *dev,
if (new_crtc_state->uapi.scaling_filter !=
old_crtc_state->uapi.scaling_filter)
new_crtc_state->uapi.mode_changed = true;
if (new_crtc_state->uapi.sharpness_strength !=
old_crtc_state->uapi.sharpness_strength)
new_crtc_state->uapi.mode_changed = true;
}
intel_vrr_check_modeset(state);
@ -6760,7 +6739,9 @@ static void intel_enable_crtc(struct intel_atomic_state *state,
intel_psr_notify_pipe_change(state, crtc, true);
display->funcs.display->crtc_enable(state, crtc);
display->modeset.funcs->crtc_enable(state, crtc);
intel_crtc_wait_for_next_vblank(crtc);
/* vblanks work again, re-enable pipe CRC. */
intel_crtc_enable_pipe_crc(crtc);
@ -6801,11 +6782,6 @@ static void intel_pre_update_crtc(struct intel_atomic_state *state,
intel_vrr_set_transcoder_timings(new_crtc_state);
}
if (intel_casf_enabling(new_crtc_state, old_crtc_state))
intel_casf_enable(new_crtc_state);
else if (new_crtc_state->hw.casf_params.strength != old_crtc_state->hw.casf_params.strength)
intel_casf_update_strength(new_crtc_state);
intel_fbc_update(state, crtc);
drm_WARN_ON(display->drm, !intel_display_power_is_enabled(display, POWER_DOMAIN_DC_OFF));
@ -6896,7 +6872,7 @@ static void intel_old_crtc_state_disables(struct intel_atomic_state *state,
intel_psr_notify_pipe_change(state, crtc, false);
display->funcs.display->crtc_disable(state, crtc);
display->modeset.funcs->crtc_disable(state, crtc);
for_each_intel_crtc_in_pipe_mask(display->drm, pipe_crtc,
intel_crtc_joined_pipe_mask(old_crtc_state)) {
@ -7548,7 +7524,7 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
}
/* Now enable the clocks, plane, pipe, and connectors that we set up. */
display->funcs.display->commit_modeset_enables(state);
display->modeset.funcs->commit_modeset_enables(state);
/* FIXME probably need to sequence this properly */
intel_program_dpkgc_latency(state);
@ -8221,7 +8197,7 @@ intel_mode_valid_max_plane_size(struct intel_display *display,
return MODE_OK;
}
static const struct intel_display_funcs skl_display_funcs = {
static const struct intel_modeset_funcs skl_display_funcs = {
.get_pipe_config = hsw_get_pipe_config,
.crtc_enable = hsw_crtc_enable,
.crtc_disable = hsw_crtc_disable,
@ -8230,7 +8206,7 @@ static const struct intel_display_funcs skl_display_funcs = {
.fixup_initial_plane_config = skl_fixup_initial_plane_config,
};
static const struct intel_display_funcs ddi_display_funcs = {
static const struct intel_modeset_funcs ddi_display_funcs = {
.get_pipe_config = hsw_get_pipe_config,
.crtc_enable = hsw_crtc_enable,
.crtc_disable = hsw_crtc_disable,
@ -8239,7 +8215,7 @@ static const struct intel_display_funcs ddi_display_funcs = {
.fixup_initial_plane_config = i9xx_fixup_initial_plane_config,
};
static const struct intel_display_funcs pch_split_display_funcs = {
static const struct intel_modeset_funcs pch_split_display_funcs = {
.get_pipe_config = ilk_get_pipe_config,
.crtc_enable = ilk_crtc_enable,
.crtc_disable = ilk_crtc_disable,
@ -8248,7 +8224,7 @@ static const struct intel_display_funcs pch_split_display_funcs = {
.fixup_initial_plane_config = i9xx_fixup_initial_plane_config,
};
static const struct intel_display_funcs vlv_display_funcs = {
static const struct intel_modeset_funcs vlv_display_funcs = {
.get_pipe_config = i9xx_get_pipe_config,
.crtc_enable = valleyview_crtc_enable,
.crtc_disable = i9xx_crtc_disable,
@ -8257,7 +8233,7 @@ static const struct intel_display_funcs vlv_display_funcs = {
.fixup_initial_plane_config = i9xx_fixup_initial_plane_config,
};
static const struct intel_display_funcs i9xx_display_funcs = {
static const struct intel_modeset_funcs i9xx_display_funcs = {
.get_pipe_config = i9xx_get_pipe_config,
.crtc_enable = i9xx_crtc_enable,
.crtc_disable = i9xx_crtc_disable,
@ -8273,16 +8249,16 @@ static const struct intel_display_funcs i9xx_display_funcs = {
void intel_init_display_hooks(struct intel_display *display)
{
if (DISPLAY_VER(display) >= 9) {
display->funcs.display = &skl_display_funcs;
display->modeset.funcs = &skl_display_funcs;
} else if (HAS_DDI(display)) {
display->funcs.display = &ddi_display_funcs;
display->modeset.funcs = &ddi_display_funcs;
} else if (HAS_PCH_SPLIT(display)) {
display->funcs.display = &pch_split_display_funcs;
display->modeset.funcs = &pch_split_display_funcs;
} else if (display->platform.cherryview ||
display->platform.valleyview) {
display->funcs.display = &vlv_display_funcs;
display->modeset.funcs = &vlv_display_funcs;
} else {
display->funcs.display = &i9xx_display_funcs;
display->modeset.funcs = &i9xx_display_funcs;
}
}

View File

@ -0,0 +1,270 @@
// SPDX-License-Identifier: MIT
/*
* Copyright 2026 Intel Corporation
*/
#include <drm/intel/intel_gmd_misc_regs.h>
#include "intel_de.h"
#include "i9xx_plane_regs.h"
#include "intel_display.h"
#include "intel_display_clock_gating.h"
#include "intel_display_core.h"
#include "intel_display_regs.h"
static void intel_display_gen9_init_clock_gating(struct intel_display *display)
{
/* See Bspec note for PSR2_CTL bit 31, Wa#828:skl,bxt,kbl,cfl */
intel_de_rmw(display, CHICKEN_PAR1_1, 0, SKL_EDP_PSR_FIX_RDWRAP);
/* WaEnableChickenDCPR:skl,bxt,kbl,glk,cfl */
intel_de_rmw(display, GEN8_CHICKEN_DCPR_1, 0, MASK_WAKEMEM);
/*
* WaFbcWakeMemOn:skl,bxt,kbl,glk,cfl
* Display WA #0859: skl,bxt,kbl,glk,cfl
*/
intel_de_rmw(display, DISP_ARB_CTL, 0, DISP_FBC_MEMORY_WAKE);
}
void intel_display_skl_init_clock_gating(struct intel_display *display)
{
/*
* WaCompressedResourceDisplayNewHashMode:skl,kbl
* Display WA #0390: skl,kbl
*
* Must match Sampler, Pixel Back End, and Media. See
* WaCompressedResourceSamplerPbeMediaNewHashMode.
*/
intel_de_rmw(display, CHICKEN_PAR1_1, 0, SKL_DE_COMPRESSED_HASH_MODE);
intel_display_gen9_init_clock_gating(display);
/*
* WaFbcTurnOffFbcWatermark:skl
* Display WA #0562: skl
*/
intel_de_rmw(display, DISP_ARB_CTL, 0, DISP_FBC_WM_DIS);
}
void intel_display_kbl_init_clock_gating(struct intel_display *display)
{
/*
* WaCompressedResourceDisplayNewHashMode:skl,kbl
* Display WA #0390: skl,kbl
*
* Must match Sampler, Pixel Back End, and Media. See
* WaCompressedResourceSamplerPbeMediaNewHashMode.
*/
intel_de_rmw(display, CHICKEN_PAR1_1, 0, SKL_DE_COMPRESSED_HASH_MODE);
intel_display_gen9_init_clock_gating(display);
/*
* WaFbcTurnOffFbcWatermark:kbl
* Display WA #0562: kbl
*/
intel_de_rmw(display, DISP_ARB_CTL, 0, DISP_FBC_WM_DIS);
}
void intel_display_cfl_init_clock_gating(struct intel_display *display)
{
/*
* WaCompressedResourceDisplayNewHashMode:skl,kbl (and cfl, cml)
* Display WA #0390: skl,kbl (and cfl, cml)
*
* Must match Sampler, Pixel Back End, and Media. See
* WaCompressedResourceSamplerPbeMediaNewHashMode.
*
* NOTE: this is the same workaround used for skl and kbl,
* because the original implementation was checking HAS_LLC(),
* which cfl/cml have, even though the comment for the
* workaround doesn't mention it.
*
*/
intel_de_rmw(display, CHICKEN_PAR1_1, 0, SKL_DE_COMPRESSED_HASH_MODE);
intel_display_gen9_init_clock_gating(display);
/*
* WaFbcTurnOffFbcWatermark:cfl
* Display WA #0562: cfl
*/
intel_de_rmw(display, DISP_ARB_CTL, 0, DISP_FBC_WM_DIS);
}
void intel_display_bxt_init_clock_gating(struct intel_display *display)
{
intel_display_gen9_init_clock_gating(display);
/*
* Wa: Backlight PWM may stop in the asserted state, causing backlight
* to stay fully on.
*/
intel_de_write(display, GEN9_CLKGATE_DIS_0,
intel_de_read(display, GEN9_CLKGATE_DIS_0) |
PWM1_GATING_DIS | PWM2_GATING_DIS);
/*
* Lower the display internal timeout.
* This is needed to avoid any hard hangs when DSI port PLL
* is off and a MMIO access is attempted by any privilege
* application, using batch buffers or any other means.
*/
intel_de_write(display, RM_TIMEOUT, MMIO_TIMEOUT_US(950));
/*
* WaFbcTurnOffFbcWatermark:bxt
* Display WA #0562: bxt
*/
intel_de_rmw(display, DISP_ARB_CTL, 0, DISP_FBC_WM_DIS);
}
void intel_display_glk_init_clock_gating(struct intel_display *display)
{
intel_display_gen9_init_clock_gating(display);
/*
* WaDisablePWMClockGating:glk
* Backlight PWM may stop in the asserted state, causing backlight
* to stay fully on.
*/
intel_de_write(display, GEN9_CLKGATE_DIS_0,
intel_de_read(display, GEN9_CLKGATE_DIS_0) |
PWM1_GATING_DIS | PWM2_GATING_DIS);
}
void intel_display_bdw_clock_gating_disable_fbcq(struct intel_display *display)
{
/* WaFbcAsynchFlipDisableFbcQueue:hsw,bdw */
intel_de_rmw(display, CHICKEN_PIPESL_1(PIPE_A), 0, HSW_FBCQ_DIS);
}
void intel_display_bdw_clock_gating_vblank_in_srd(struct intel_display *display)
{
enum pipe pipe;
/* WaPsrDPAMaskVBlankInSRD:hsw */
intel_de_rmw(display, CHICKEN_PAR1_1, 0, HSW_MASK_VBL_TO_PIPE_IN_SRD);
for_each_pipe(display, pipe) {
/* WaPsrDPRSUnmaskVBlankInSRD:hsw,bdw */
intel_de_rmw(display, CHICKEN_PIPESL_1(pipe), 0,
BDW_UNMASK_VBL_TO_REGS_IN_SRD);
}
}
void intel_display_bdw_clock_gating_kvm_notif(struct intel_display *display)
{
/* WaKVMNotificationOnConfigChange:bdw */
intel_de_rmw(display, CHICKEN_PAR2_1, 0,
KVM_CONFIG_CHANGE_NOTIFICATION_SELECT);
}
void intel_display_hsw_init_clock_gating(struct intel_display *display)
{
enum pipe pipe;
/* WaFbcAsynchFlipDisableFbcQueue:hsw,bdw */
intel_de_rmw(display, CHICKEN_PIPESL_1(PIPE_A), 0, HSW_FBCQ_DIS);
/* WaPsrDPAMaskVBlankInSRD:hsw */
intel_de_rmw(display, CHICKEN_PAR1_1, 0, HSW_MASK_VBL_TO_PIPE_IN_SRD);
for_each_pipe(display, pipe) {
/* WaPsrDPRSUnmaskVBlankInSRD:hsw,bdw */
intel_de_rmw(display, CHICKEN_PIPESL_1(pipe), 0,
HSW_UNMASK_VBL_TO_REGS_IN_SRD);
}
}
void intel_display_disable_trickle_feed(struct intel_display *display)
{
enum pipe pipe;
for_each_pipe(display, pipe) {
intel_de_rmw(display, DSPCNTR(display, pipe), 0,
DISP_TRICKLE_FEED_DISABLE);
intel_de_rmw(display, DSPSURF(display, pipe), 0, 0);
intel_de_posting_read(display, DSPSURF(display, pipe));
}
}
void intel_display_ilk_init_clock_gating(struct intel_display *display)
{
u32 dspclk_gate = ILK_VRHUNIT_CLOCK_GATE_DISABLE;
/*
* Required for FBC
* WaFbcDisableDpfcClockGating:ilk
*/
dspclk_gate |= ILK_DPFCRUNIT_CLOCK_GATE_DISABLE |
ILK_DPFCUNIT_CLOCK_GATE_DISABLE |
ILK_DPFDUNIT_CLOCK_GATE_ENABLE;
intel_de_write(display, ILK_DISPLAY_CHICKEN2,
intel_de_read(display, ILK_DISPLAY_CHICKEN2) |
ILK_DPARB_GATE | ILK_VSDPFD_FULL);
dspclk_gate |= ILK_DPARBUNIT_CLOCK_GATE_ENABLE;
intel_de_write(display, DISP_ARB_CTL,
intel_de_read(display, DISP_ARB_CTL) |
DISP_FBC_WM_DIS);
if (display->platform.ironlake && display->platform.mobile) {
/* WaFbcAsynchFlipDisableFbcQueue:ilk */
intel_de_rmw(display, ILK_DISPLAY_CHICKEN1, 0, ILK_FBCQ_DIS);
intel_de_rmw(display, ILK_DISPLAY_CHICKEN2, 0, ILK_DPARB_GATE);
}
intel_de_write(display, ILK_DSPCLK_GATE_D, dspclk_gate);
intel_de_rmw(display, ILK_DISPLAY_CHICKEN2, 0, ILK_ELPIN_409_SELECT);
intel_display_disable_trickle_feed(display);
}
void intel_display_gen6_init_clock_gating(struct intel_display *display)
{
u32 dspclk_gate = ILK_VRHUNIT_CLOCK_GATE_DISABLE;
intel_de_write(display, ILK_DSPCLK_GATE_D, dspclk_gate);
intel_de_rmw(display, ILK_DISPLAY_CHICKEN2, 0, ILK_ELPIN_409_SELECT);
intel_de_write(display, ILK_DISPLAY_CHICKEN1,
intel_de_read(display, ILK_DISPLAY_CHICKEN1) |
ILK_FBCQ_DIS | ILK_PABSTRETCH_DIS);
intel_de_write(display, ILK_DISPLAY_CHICKEN2,
intel_de_read(display, ILK_DISPLAY_CHICKEN2) |
ILK_DPARB_GATE | ILK_VSDPFD_FULL);
intel_de_write(display, ILK_DSPCLK_GATE_D,
intel_de_read(display, ILK_DSPCLK_GATE_D) |
ILK_DPARBUNIT_CLOCK_GATE_ENABLE |
ILK_DPFDUNIT_CLOCK_GATE_ENABLE);
intel_display_disable_trickle_feed(display);
}
void intel_display_ivb_init_clock_gating(struct intel_display *display)
{
intel_de_write(display, ILK_DSPCLK_GATE_D, ILK_VRHUNIT_CLOCK_GATE_DISABLE);
intel_de_rmw(display, ILK_DISPLAY_CHICKEN1, 0, ILK_FBCQ_DIS);
}
void intel_display_g4x_init_clock_gating(struct intel_display *display)
{
u32 dspclk_gate = VRHUNIT_CLOCK_GATE_DISABLE |
OVRUNIT_CLOCK_GATE_DISABLE |
OVCUNIT_CLOCK_GATE_DISABLE;
if (display->platform.gm45)
dspclk_gate |= DSSUNIT_CLOCK_GATE_DISABLE;
intel_de_write(display, DSPCLK_GATE_D, dspclk_gate);
intel_display_disable_trickle_feed(display);
}
void intel_display_i965gm_init_clock_gating(struct intel_display *display)
{
intel_de_write(display, DSPCLK_GATE_D, 0);
}

View File

@ -0,0 +1,27 @@
/* SPDX-License-Identifier: MIT */
/*
* Copyright 2026 Intel Corporation
*/
#ifndef __INTEL_DISPLAY_CLOCK_GATING_H__
#define __INTEL_DISPLAY_CLOCK_GATING_H__
struct intel_display;
void intel_display_skl_init_clock_gating(struct intel_display *display);
void intel_display_kbl_init_clock_gating(struct intel_display *display);
void intel_display_cfl_init_clock_gating(struct intel_display *display);
void intel_display_bxt_init_clock_gating(struct intel_display *display);
void intel_display_glk_init_clock_gating(struct intel_display *display);
void intel_display_bdw_clock_gating_disable_fbcq(struct intel_display *display);
void intel_display_bdw_clock_gating_vblank_in_srd(struct intel_display *display);
void intel_display_bdw_clock_gating_kvm_notif(struct intel_display *display);
void intel_display_hsw_init_clock_gating(struct intel_display *display);
void intel_display_disable_trickle_feed(struct intel_display *display);
void intel_display_ilk_init_clock_gating(struct intel_display *display);
void intel_display_gen6_init_clock_gating(struct intel_display *display);
void intel_display_ivb_init_clock_gating(struct intel_display *display);
void intel_display_g4x_init_clock_gating(struct intel_display *display);
void intel_display_i965gm_init_clock_gating(struct intel_display *display);
#endif /* __INTEL_DISPLAY_CLOCK_GATING_H__ */

View File

@ -47,7 +47,7 @@ struct intel_dpll_global_funcs;
struct intel_dpll_mgr;
struct intel_fbdev;
struct intel_fdi_funcs;
struct intel_hotplug_funcs;
struct intel_hotplug_irq_funcs;
struct intel_initial_plane_config;
struct intel_opregion;
struct intel_overlay;
@ -59,7 +59,7 @@ struct task_struct;
/* Amount of PSF GV points, BSpec precisely defines this */
#define I915_NUM_PSF_GV_POINTS 3
struct intel_display_funcs {
struct intel_modeset_funcs {
/*
* Returns the active state of the crtc, and if the crtc is active,
* fills out the pipe-config with the hw state.
@ -100,6 +100,9 @@ struct intel_audio_state {
};
struct intel_audio {
/* internal display audio functions */
const struct intel_audio_funcs *funcs;
/* hda/i915 audio component */
struct i915_audio_component *component;
bool component_registered;
@ -124,6 +127,9 @@ struct intel_audio {
* dpll, because on some platforms plls share registers.
*/
struct intel_dpll_global {
/* internal dpll functions */
const struct intel_dpll_global_funcs *funcs;
struct mutex lock;
int num_dpll;
@ -152,6 +158,9 @@ struct intel_frontbuffer_tracking {
};
struct intel_hotplug {
/* internal hotplug irq functions */
const struct intel_hotplug_irq_funcs *funcs;
struct delayed_work hotplug_work;
const u32 *hpd, *pch_hpd;
@ -244,6 +253,9 @@ struct intel_vbt_data {
};
struct intel_wm {
/* internal watermark functions */
const struct intel_wm_funcs *funcs;
/*
* Raw watermark latency values:
* in 0.1us units for WM0,
@ -297,33 +309,6 @@ struct intel_display {
/* list of all intel_crtcs sorted by pipe */
struct list_head pipe_list;
/* Display functions */
struct {
/* Top level crtc-ish functions */
const struct intel_display_funcs *display;
/* Display CDCLK functions */
const struct intel_cdclk_funcs *cdclk;
/* Display pll funcs */
const struct intel_dpll_global_funcs *dpll;
/* irq display functions */
const struct intel_hotplug_funcs *hotplug;
/* pm display functions */
const struct intel_wm_funcs *wm;
/* fdi display functions */
const struct intel_fdi_funcs *fdi;
/* Display internal color functions */
const struct intel_color_funcs *color;
/* Display internal audio functions */
const struct intel_audio_funcs *audio;
} funcs;
struct {
bool any_task_allowed;
struct task_struct *allowed_task;
@ -351,6 +336,9 @@ struct intel_display {
} bw;
struct {
/* Internal CDCLK functions */
const struct intel_cdclk_funcs *funcs;
/* The current hardware cdclk configuration */
struct intel_cdclk_config hw;
@ -365,6 +353,9 @@ struct intel_display {
} cdclk;
struct {
/* internal color functions */
const struct intel_color_funcs *funcs;
struct drm_property_blob *glk_linear_degamma_lut;
} color;
@ -418,6 +409,9 @@ struct intel_display {
} fbdev;
struct {
/* internal fdi functions */
const struct intel_fdi_funcs *funcs;
unsigned int pll_freq;
u32 rx_config;
} fdi;
@ -518,6 +512,11 @@ struct intel_display {
u32 pipestat_irq_mask[I915_MAX_PIPES];
} irq;
struct {
/* Top level crtc-ish functions */
const struct intel_modeset_funcs *funcs;
} modeset;
struct {
/* protected by wm.wm_mutex */
u16 linetime[I915_MAX_PIPES];
@ -559,12 +558,15 @@ struct intel_display {
unsigned long mask;
} quirks;
struct {
u32 count;
} reset;
struct {
/* restore state for suspend/resume and display reset */
struct drm_atomic_commit *modeset_state;
struct drm_modeset_acquire_ctx reset_ctx;
/* modeset stuck tracking for reset */
atomic_t pending_fb_pin;
u32 saveDSPARB;
u32 saveSWF0[16];
u32 saveSWF1[16];

View File

@ -27,6 +27,7 @@
#include "intel_display_power.h"
#include "intel_display_power_well.h"
#include "intel_display_regs.h"
#include "intel_display_reset.h"
#include "intel_display_rpm.h"
#include "intel_display_types.h"
#include "intel_dmc.h"
@ -416,11 +417,12 @@ static void intel_scaler_info(struct seq_file *m, struct intel_crtc *crtc)
/* Not all platforms have a scaler */
if (num_scalers) {
seq_printf(m, "\tnum_scalers=%d, scaler_users=%x scaler_id=%d scaling_filter=%d",
seq_printf(m, "\tnum_scalers=%d, scaler_users=%x scaler_id=%d scaling_filter=%d sharpness_strength=%d",
num_scalers,
crtc_state->scaler_state.scaler_users,
crtc_state->scaler_state.scaler_id,
crtc_state->hw.scaling_filter);
crtc_state->hw.scaling_filter,
crtc_state->hw.sharpness_strength);
for (i = 0; i < num_scalers; i++) {
const struct intel_scaler *sc =
@ -837,6 +839,7 @@ void intel_display_debugfs_register(struct intel_display *display)
intel_bios_debugfs_register(display);
intel_cdclk_debugfs_register(display);
intel_display_reset_debugfs_register(display);
intel_dmc_debugfs_register(display);
intel_dp_test_debugfs_register(display);
intel_fbc_debugfs_register(display);

View File

@ -200,6 +200,7 @@ struct intel_display_platforms {
#define HAS_PSR_TRANS_PUSH_FRAME_CHANGE(__display) (DISPLAY_VER(__display) >= 20)
#define HAS_SAGV(__display) (DISPLAY_VER(__display) >= 9 && \
!(__display)->platform.broxton && !(__display)->platform.geminilake)
#define HAS_SAGV_WM(__display) (DISPLAY_VER(__display) >= 12 && !(__display)->platform.rocketlake)
#define HAS_TRANSCODER(__display, trans) ((DISPLAY_RUNTIME_INFO(__display)->cpu_transcoder_mask & \
BIT(trans)) != 0)
#define HAS_UNCOMPRESSED_JOINER(__display) (DISPLAY_VER(__display) >= 13)

View File

@ -2458,6 +2458,10 @@ void dg1_de_irq_postinstall(struct intel_display *display)
intel_de_write(display, GEN11_DISPLAY_INT_CTL, GEN11_DISPLAY_IRQ_ENABLE);
}
struct intel_display_irq_funcs {
void (*reset)(struct intel_display *display);
};
void intel_display_irq_init(struct intel_display *display)
{
spin_lock_init(&display->irq.lock);

View File

@ -25,7 +25,7 @@
#include "intel_display_wa.h"
#include "intel_dmc.h"
#include "intel_dram.h"
#include "intel_mchbar_regs.h"
#include "intel_mchbar.h"
#include "intel_parent.h"
#include "intel_pch_refclk.h"
#include "intel_pmdemand.h"
@ -1252,7 +1252,7 @@ static void assert_can_disable_lcpll(struct intel_display *display)
static u32 hsw_read_dcomp(struct intel_display *display)
{
if (display->platform.haswell)
return intel_de_read(display, D_COMP_HSW);
return intel_mchbar_read(display, D_COMP_HSW);
else
return intel_de_read(display, D_COMP_BDW);
}
@ -1420,9 +1420,7 @@ static void hsw_disable_pc8(struct intel_display *display)
intel_init_pch_refclk(display);
/* Many display registers don't survive PC8+ */
#ifdef I915 /* FIXME */
intel_clock_gating_init(display->drm);
#endif
}
static void intel_pch_reset_handshake(struct intel_display *display,
@ -1890,9 +1888,9 @@ static bool vlv_punit_is_power_gated(struct intel_display *display, u32 reg0)
{
bool ret;
vlv_punit_get(display->drm);
ret = (vlv_punit_read(display->drm, reg0) & SSPM0_SSC_MASK) == SSPM0_SSC_PWR_GATE;
vlv_punit_put(display->drm);
vlv_punit_get(display);
ret = (vlv_punit_read(display, reg0) & SSPM0_SSC_MASK) == SSPM0_SSC_PWR_GATE;
vlv_punit_put(display);
return ret;
}

View File

@ -4,13 +4,13 @@
*/
#include <drm/drm_print.h>
#include <drm/intel/vlv_iosf_sb_regs.h>
#include "intel_display_core.h"
#include "intel_display_power_map.h"
#include "intel_display_power_well.h"
#include "intel_display_regs.h"
#include "intel_display_types.h"
#include "vlv_iosf_sb_reg.h"
#define __LIST_INLINE_ELEMS(__elem_type, ...) \
((__elem_type[]) { __VA_ARGS__ })

View File

@ -34,7 +34,6 @@
#include "intel_vga.h"
#include "skl_watermark.h"
#include "vlv_dpio_phy_regs.h"
#include "vlv_iosf_sb_reg.h"
#include "vlv_sideband.h"
/*
@ -1189,28 +1188,28 @@ static void vlv_set_power_well(struct intel_display *display,
state = enable ? PUNIT_PWRGT_PWR_ON(pw_idx) :
PUNIT_PWRGT_PWR_GATE(pw_idx);
vlv_punit_get(display->drm);
vlv_punit_get(display);
val = vlv_punit_read(display->drm, PUNIT_REG_PWRGT_STATUS);
val = vlv_punit_read(display, PUNIT_REG_PWRGT_STATUS);
if ((val & mask) == state)
goto out;
ctrl = vlv_punit_read(display->drm, PUNIT_REG_PWRGT_CTRL);
ctrl = vlv_punit_read(display, PUNIT_REG_PWRGT_CTRL);
ctrl &= ~mask;
ctrl |= state;
vlv_punit_write(display->drm, PUNIT_REG_PWRGT_CTRL, ctrl);
vlv_punit_write(display, PUNIT_REG_PWRGT_CTRL, ctrl);
ret = poll_timeout_us(val = vlv_punit_read(display->drm, PUNIT_REG_PWRGT_STATUS),
ret = poll_timeout_us(val = vlv_punit_read(display, PUNIT_REG_PWRGT_STATUS),
(val & mask) == state,
500, 100 * 1000, false);
if (ret)
drm_err(display->drm,
"timeout setting power well state %08x (%08x)\n",
state,
vlv_punit_read(display->drm, PUNIT_REG_PWRGT_CTRL));
vlv_punit_read(display, PUNIT_REG_PWRGT_CTRL));
out:
vlv_punit_put(display->drm);
vlv_punit_put(display);
}
static void vlv_power_well_enable(struct intel_display *display,
@ -1237,9 +1236,9 @@ static bool vlv_power_well_enabled(struct intel_display *display,
mask = PUNIT_PWRGT_MASK(pw_idx);
ctrl = PUNIT_PWRGT_PWR_ON(pw_idx);
vlv_punit_get(display->drm);
vlv_punit_get(display);
state = vlv_punit_read(display->drm, PUNIT_REG_PWRGT_STATUS) & mask;
state = vlv_punit_read(display, PUNIT_REG_PWRGT_STATUS) & mask;
/*
* We only ever set the power-on and power-gate states, anything
* else is unexpected.
@ -1253,10 +1252,10 @@ static bool vlv_power_well_enabled(struct intel_display *display,
* A transient state at this point would mean some unexpected party
* is poking at the power controls too.
*/
ctrl = vlv_punit_read(display->drm, PUNIT_REG_PWRGT_CTRL) & mask;
ctrl = vlv_punit_read(display, PUNIT_REG_PWRGT_CTRL) & mask;
drm_WARN_ON(display->drm, ctrl != state);
vlv_punit_put(display->drm);
vlv_punit_put(display);
return enabled;
}
@ -1533,30 +1532,30 @@ static void chv_dpio_cmn_power_well_enable(struct intel_display *display,
drm_err(display->drm, "Display PHY %d is not power up\n",
phy);
vlv_dpio_get(display->drm);
vlv_dpio_get(display);
/* Enable dynamic power down */
tmp = vlv_dpio_read(display->drm, phy, CHV_CMN_DW28);
tmp = vlv_dpio_read(display, phy, CHV_CMN_DW28);
tmp |= DPIO_DYNPWRDOWNEN_CH0 | DPIO_CL1POWERDOWNEN |
DPIO_SUS_CLK_CONFIG_GATE_CLKREQ;
vlv_dpio_write(display->drm, phy, CHV_CMN_DW28, tmp);
vlv_dpio_write(display, phy, CHV_CMN_DW28, tmp);
if (id == VLV_DISP_PW_DPIO_CMN_BC) {
tmp = vlv_dpio_read(display->drm, phy, CHV_CMN_DW6_CH1);
tmp = vlv_dpio_read(display, phy, CHV_CMN_DW6_CH1);
tmp |= DPIO_DYNPWRDOWNEN_CH1;
vlv_dpio_write(display->drm, phy, CHV_CMN_DW6_CH1, tmp);
vlv_dpio_write(display, phy, CHV_CMN_DW6_CH1, tmp);
} else {
/*
* Force the non-existing CL2 off. BXT does this
* too, so maybe it saves some power even though
* CL2 doesn't exist?
*/
tmp = vlv_dpio_read(display->drm, phy, CHV_CMN_DW30);
tmp = vlv_dpio_read(display, phy, CHV_CMN_DW30);
tmp |= DPIO_CL2_LDOFUSE_PWRENB;
vlv_dpio_write(display->drm, phy, CHV_CMN_DW30, tmp);
vlv_dpio_write(display, phy, CHV_CMN_DW30, tmp);
}
vlv_dpio_put(display->drm);
vlv_dpio_put(display);
display->power.chv_phy_control |= PHY_COM_LANE_RESET_DEASSERT(phy);
intel_de_write(display, DISPLAY_PHY_CONTROL,
@ -1624,9 +1623,9 @@ static void assert_chv_phy_powergate(struct intel_display *display, enum dpio_ph
else
reg = CHV_CMN_DW6_CH1;
vlv_dpio_get(display->drm);
val = vlv_dpio_read(display->drm, phy, reg);
vlv_dpio_put(display->drm);
vlv_dpio_get(display);
val = vlv_dpio_read(display, phy, reg);
vlv_dpio_put(display);
/*
* This assumes !override is only used when the port is disabled.
@ -1740,9 +1739,9 @@ static bool chv_pipe_power_well_enabled(struct intel_display *display,
bool enabled;
u32 state, ctrl;
vlv_punit_get(display->drm);
vlv_punit_get(display);
state = vlv_punit_read(display->drm, PUNIT_REG_DSPSSPM) & DP_SSS_MASK(pipe);
state = vlv_punit_read(display, PUNIT_REG_DSPSSPM) & DP_SSS_MASK(pipe);
/*
* We only ever set the power-on and power-gate states, anything
* else is unexpected.
@ -1755,10 +1754,10 @@ static bool chv_pipe_power_well_enabled(struct intel_display *display,
* A transient state at this point would mean some unexpected party
* is poking at the power controls too.
*/
ctrl = vlv_punit_read(display->drm, PUNIT_REG_DSPSSPM) & DP_SSC_MASK(pipe);
ctrl = vlv_punit_read(display, PUNIT_REG_DSPSSPM) & DP_SSC_MASK(pipe);
drm_WARN_ON(display->drm, ctrl << 16 != state);
vlv_punit_put(display->drm);
vlv_punit_put(display);
return enabled;
}
@ -1774,29 +1773,29 @@ static void chv_set_pipe_power_well(struct intel_display *display,
state = enable ? DP_SSS_PWR_ON(pipe) : DP_SSS_PWR_GATE(pipe);
vlv_punit_get(display->drm);
vlv_punit_get(display);
ctrl = vlv_punit_read(display->drm, PUNIT_REG_DSPSSPM);
ctrl = vlv_punit_read(display, PUNIT_REG_DSPSSPM);
if ((ctrl & DP_SSS_MASK(pipe)) == state)
goto out;
ctrl &= ~DP_SSC_MASK(pipe);
ctrl |= enable ? DP_SSC_PWR_ON(pipe) : DP_SSC_PWR_GATE(pipe);
vlv_punit_write(display->drm, PUNIT_REG_DSPSSPM, ctrl);
vlv_punit_write(display, PUNIT_REG_DSPSSPM, ctrl);
ret = poll_timeout_us(ctrl = vlv_punit_read(display->drm, PUNIT_REG_DSPSSPM),
ret = poll_timeout_us(ctrl = vlv_punit_read(display, PUNIT_REG_DSPSSPM),
(ctrl & DP_SSS_MASK(pipe)) == state,
500, 100 * 1000, false);
if (ret)
drm_err(display->drm,
"timeout setting power well state %08x (%08x)\n",
state,
vlv_punit_read(display->drm, PUNIT_REG_DSPSSPM));
vlv_punit_read(display, PUNIT_REG_DSPSSPM));
#undef COND
out:
vlv_punit_put(display->drm);
vlv_punit_put(display);
}
static void chv_pipe_power_well_sync_hw(struct intel_display *display,

View File

@ -217,6 +217,34 @@
# define DPIOUNIT_CLOCK_GATE_DISABLE (1 << 6) /* 915-945 */
# define OVFUNIT_CLOCK_GATE_DISABLE (1 << 5)
# define OVBUNIT_CLOCK_GATE_DISABLE (1 << 4)
#define ILK_DISPLAY_CHICKEN1 _MMIO(0x42000)
#define ILK_FBCQ_DIS REG_BIT(22)
#define ILK_PABSTRETCH_DIS REG_BIT(21)
#define ILK_SABSTRETCH_DIS REG_BIT(20)
#define IVB_PRI_STRETCH_MAX_MASK REG_GENMASK(21, 20)
#define IVB_PRI_STRETCH_MAX_X8 REG_FIELD_PREP(IVB_PRI_STRETCH_MAX_MASK, 0)
#define IVB_PRI_STRETCH_MAX_X4 REG_FIELD_PREP(IVB_PRI_STRETCH_MAX_MASK, 1)
#define IVB_PRI_STRETCH_MAX_X2 REG_FIELD_PREP(IVB_PRI_STRETCH_MAX_MASK, 2)
#define IVB_PRI_STRETCH_MAX_X1 REG_FIELD_PREP(IVB_PRI_STRETCH_MAX_MASK, 3)
#define IVB_SPR_STRETCH_MAX_MASK REG_GENMASK(19, 18)
#define IVB_SPR_STRETCH_MAX_X8 REG_FIELD_PREP(IVB_SPR_STRETCH_MAX_MASK, 0)
#define IVB_SPR_STRETCH_MAX_X4 REG_FIELD_PREP(IVB_SPR_STRETCH_MAX_MASK, 1)
#define IVB_SPR_STRETCH_MAX_X2 REG_FIELD_PREP(IVB_SPR_STRETCH_MAX_MASK, 2)
#define IVB_SPR_STRETCH_MAX_X1 REG_FIELD_PREP(IVB_SPR_STRETCH_MAX_MASK, 3)
#define ILK_DISPLAY_CHICKEN2 _MMIO(0x42004)
/* Required on all Ironlake and Sandybridge according to the B-Spec. */
#define ILK_ELPIN_409_SELECT REG_BIT(25)
#define ILK_DPARB_GATE REG_BIT(22)
#define ILK_VSDPFD_FULL REG_BIT(21)
#define ILK_DSPCLK_GATE_D _MMIO(0x42020)
#define ILK_VRHUNIT_CLOCK_GATE_DISABLE REG_BIT(28)
#define ILK_DPFCUNIT_CLOCK_GATE_DISABLE REG_BIT(9)
#define ILK_DPFCRUNIT_CLOCK_GATE_DISABLE REG_BIT(8)
#define ILK_DPFDUNIT_CLOCK_GATE_ENABLE REG_BIT(7)
#define ILK_DPARBUNIT_CLOCK_GATE_ENABLE REG_BIT(5)
/*
* This bit must be set on the 830 to prevent hangs when turning off the
* overlay scaler.
@ -405,6 +433,9 @@
#define SKL_EDP_PSR_FIX_RDWRAP REG_BIT(3)
#define IGNORE_PSR2_HW_TRACKING REG_BIT(1)
#define CHICKEN_PAR2_1 _MMIO(0x42090)
#define KVM_CONFIG_CHANGE_NOTIFICATION_SELECT REG_BIT(14)
/*
* GEN9 clock gating regs
*/
@ -2263,6 +2294,7 @@
#define TRANS_DP2_CTL(trans) _MMIO_TRANS(trans, _TRANS_DP2_CTL_A, _TRANS_DP2_CTL_B)
#define TRANS_DP2_128B132B_CHANNEL_CODING REG_BIT(31)
#define TRANS_DP2_PANEL_REPLAY_ENABLE REG_BIT(30)
#define TRANS_DP2_PR_TUNNELING_ENABLE REG_BIT(26)
#define TRANS_DP2_DEBUG_ENABLE REG_BIT(23)
#define _TRANS_DP2_VFREQHIGH_A 0x600a4

View File

@ -3,6 +3,8 @@
* Copyright © 2023 Intel Corporation
*/
#include <linux/debugfs.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_print.h>
@ -16,28 +18,23 @@
#include "intel_hotplug.h"
#include "intel_pps.h"
bool intel_display_reset_test(struct intel_display *display)
bool intel_display_reset_supported(struct intel_display *display)
{
return display->params.force_reset_modeset_test;
return display && HAS_DISPLAY(display);
}
/* returns true if intel_display_reset_finish() needs to be called */
bool intel_display_reset_prepare(struct intel_display *display,
modeset_stuck_fn modeset_stuck, void *context)
bool intel_display_reset_test(struct intel_display *display)
{
return display && HAS_DISPLAY(display) &&
display->params.force_reset_modeset_test;
}
void intel_display_reset_prepare(struct intel_display *display)
{
struct drm_modeset_acquire_ctx *ctx = &display->restore.reset_ctx;
struct drm_atomic_commit *state;
int ret;
if (!HAS_DISPLAY(display))
return false;
if (atomic_read(&display->restore.pending_fb_pin)) {
drm_dbg_kms(display->drm,
"Modeset potentially stuck, unbreaking through wedging\n");
modeset_stuck(context);
}
/*
* Need mode_config.mutex so that we don't
* trample ongoing ->detect() and whatnot.
@ -60,7 +57,7 @@ bool intel_display_reset_prepare(struct intel_display *display,
ret = PTR_ERR(state);
drm_err(display->drm, "Duplicating state failed with %i\n",
ret);
return true;
return;
}
ret = drm_atomic_helper_disable_all(display->drm, ctx);
@ -68,13 +65,12 @@ bool intel_display_reset_prepare(struct intel_display *display,
drm_err(display->drm, "Suspending crtc's failed with %i\n",
ret);
drm_atomic_commit_put(state);
return true;
return;
}
display->reset.count++;
display->restore.modeset_state = state;
state->acquire_ctx = ctx;
return true;
}
void intel_display_reset_finish(struct intel_display *display, bool test_only)
@ -83,9 +79,6 @@ void intel_display_reset_finish(struct intel_display *display, bool test_only)
struct drm_atomic_commit *state;
int ret;
if (!HAS_DISPLAY(display))
return;
state = fetch_and_zero(&display->restore.modeset_state);
if (!state)
goto unlock;
@ -124,3 +117,10 @@ void intel_display_reset_finish(struct intel_display *display, bool test_only)
drm_modeset_acquire_fini(ctx);
mutex_unlock(&display->drm->mode_config.mutex);
}
void intel_display_reset_debugfs_register(struct intel_display *display)
{
debugfs_create_u32("intel_display_reset_count", 0400,
display->drm->debugfs_root,
&display->reset.count);
}

View File

@ -10,11 +10,11 @@
struct intel_display;
typedef void modeset_stuck_fn(void *context);
bool intel_display_reset_supported(struct intel_display *display);
bool intel_display_reset_test(struct intel_display *display);
bool intel_display_reset_prepare(struct intel_display *display,
modeset_stuck_fn modeset_stuck, void *context);
void intel_display_reset_prepare(struct intel_display *display);
void intel_display_reset_finish(struct intel_display *display, bool test_only);
void intel_display_reset_debugfs_register(struct intel_display *display);
#endif /* __INTEL_RESET_H__ */

View File

@ -683,14 +683,15 @@ struct intel_plane_state {
struct i915_vma *ggtt_vma;
struct i915_vma *dpt_vma;
unsigned long flags;
#define PLANE_HAS_FENCE BIT(0)
struct intel_fb_view view;
/* for legacy cursor fb unpin */
struct drm_vblank_work unpin_work;
/* fenced region ID (-1 if none) */
s8 fence_id;
/* Plane pxp decryption state */
bool decrypt;
@ -755,9 +756,7 @@ struct intel_plane_state {
};
struct intel_initial_plane_config {
struct intel_framebuffer *fb;
struct intel_memory_region *mem;
resource_size_t phys_base;
struct drm_framebuffer *fb;
struct i915_vma *vma;
int size;
u32 base;
@ -997,7 +996,7 @@ struct intel_casf {
struct scaler_filter_coeff coeff[SCALER_FILTER_NUM_TAPS];
u8 strength;
u8 win_size;
bool casf_enable;
bool enable;
};
struct intel_crtc_state {
@ -1036,7 +1035,7 @@ struct intel_crtc_state {
struct drm_property_blob *degamma_lut, *gamma_lut, *ctm;
struct drm_display_mode mode, pipe_mode, adjusted_mode;
enum drm_scaling_filter scaling_filter;
struct intel_casf casf_params;
u8 sharpness_strength;
} hw;
/* actual state of LUTs */
@ -1223,6 +1222,7 @@ struct intel_crtc_state {
/* Panel fitter placement and size for Ironlake+ */
struct {
struct intel_casf casf;
struct drm_rect dst;
bool enabled;
bool force_thru;

View File

@ -505,6 +505,14 @@ static void pipedmc_clock_gating_wa(struct intel_display *display, bool enable)
static u32 pipedmc_interrupt_mask(struct intel_display *display)
{
/*
* TODO: Check if PIPEDMC_ERROR bit enabling causes errors
* on PTL, enable it if validation passes
*/
if (DISPLAY_VER(display) >= 35)
return PIPEDMC_FLIPQ_PROG_DONE |
PIPEDMC_ERROR;
/*
* FIXME PIPEDMC_ERROR not enabled for now due to LNL pipe B
* triggering it during the first DC state transition. Figure
@ -1574,10 +1582,10 @@ void intel_dmc_update_dc6_allowed_count(struct intel_display *display,
struct intel_dmc *dmc = display_to_dmc(display);
u32 dc5_cur_count;
if (DISPLAY_VER(dmc->display) < 14)
if (DISPLAY_VER(display) < 14)
return;
dc5_cur_count = intel_de_read(dmc->display, DG1_DMC_DEBUG_DC5_COUNT);
dc5_cur_count = intel_de_read(display, DG1_DMC_DEBUG_DC5_COUNT);
if (!start_tracking)
dmc->dc6_allowed.count += dc5_cur_count - dmc->dc6_allowed.dc5_start;

View File

@ -46,7 +46,7 @@
* atomic variant of waiting MMIO.
*/
#define DMC_WAKELOCK_CTL_TIMEOUT_US 5000
#define DMC_WAKELOCK_HOLD_TIME 50
#define DMC_WAKELOCK_HOLD_TIME 5
/*
* Possible non-negative values for the enable_dmc_wl param.

View File

@ -1234,28 +1234,11 @@ int intel_dp_output_format_link_bpp_x16(enum intel_output_format output_format,
return fxp_q4_from_int(pipe_bpp);
}
static enum intel_output_format
intel_dp_sink_format(struct intel_connector *connector,
const struct drm_display_mode *mode)
{
const struct drm_display_info *info = &connector->base.display_info;
if (drm_mode_is_420_only(info, mode))
return INTEL_OUTPUT_FORMAT_YCBCR420;
return INTEL_OUTPUT_FORMAT_RGB;
}
static int
intel_dp_mode_min_link_bpp_x16(struct intel_connector *connector,
const struct drm_display_mode *mode)
const struct drm_display_mode *mode,
enum intel_output_format output_format)
{
enum intel_output_format output_format, sink_format;
sink_format = intel_dp_sink_format(connector, mode);
output_format = intel_dp_output_format(connector, sink_format);
return intel_dp_output_format_link_bpp_x16(output_format,
intel_dp_min_bpp(output_format));
}
@ -1317,23 +1300,29 @@ intel_dp_tmds_clock_valid(struct intel_dp *intel_dp,
return MODE_OK;
}
static int frl_required_bw(int clock, int bpc,
enum intel_output_format sink_format)
{
if (sink_format == INTEL_OUTPUT_FORMAT_YCBCR420)
clock /= 2;
return clock * bpc * 3;
}
static enum drm_mode_status
intel_dp_mode_valid_downstream(struct intel_connector *connector,
const struct drm_display_mode *mode,
int target_clock)
int target_clock,
enum intel_output_format sink_format)
{
struct intel_dp *intel_dp = intel_attached_dp(connector);
const struct drm_display_info *info = &connector->base.display_info;
enum drm_mode_status status;
enum intel_output_format sink_format;
/* If PCON supports FRL MODE, check FRL bandwidth constraints */
if (intel_dp->dfp.pcon_max_frl_bw) {
int link_bpp_x16 = intel_dp_mode_min_link_bpp_x16(connector, mode);
int target_bw;
int max_frl_bw;
int target_bw, max_frl_bw;
target_bw = fxp_q4_to_int_roundup(link_bpp_x16) * target_clock;
/* Assume 8bpc for the FRL bandwidth check */
target_bw = frl_required_bw(target_clock, 8, sink_format);
max_frl_bw = intel_dp->dfp.pcon_max_frl_bw;
@ -1350,25 +1339,36 @@ intel_dp_mode_valid_downstream(struct intel_connector *connector,
target_clock > intel_dp->dfp.max_dotclock)
return MODE_CLOCK_HIGH;
sink_format = intel_dp_sink_format(connector, mode);
/* Assume 8bpc for the DP++/HDMI/DVI TMDS clock check */
status = intel_dp_tmds_clock_valid(intel_dp, target_clock,
8, sink_format, true);
return intel_dp_tmds_clock_valid(intel_dp, target_clock,
8, sink_format, true);
}
if (status != MODE_OK) {
if (sink_format == INTEL_OUTPUT_FORMAT_YCBCR420 ||
!connector->base.ycbcr_420_allowed ||
!drm_mode_is_420_also(info, mode))
return status;
sink_format = INTEL_OUTPUT_FORMAT_YCBCR420;
status = intel_dp_tmds_clock_valid(intel_dp, target_clock,
8, sink_format, true);
if (status != MODE_OK)
return status;
static enum drm_mode_status
intel_dp_sink_format_valid(struct intel_connector *connector,
const struct drm_display_mode *mode,
enum intel_output_format sink_format)
{
struct intel_dp *intel_dp = intel_attached_dp(connector);
const struct drm_display_info *info = &connector->base.display_info;
switch (sink_format) {
case INTEL_OUTPUT_FORMAT_YCBCR420:
if (intel_dp->dfp.min_tmds_clock &&
!intel_dp_has_hdmi_sink(intel_dp))
return MODE_NO_420;
if (!connector->base.ycbcr_420_allowed ||
!drm_mode_is_420(info, mode))
return MODE_NO_420;
return MODE_OK;
case INTEL_OUTPUT_FORMAT_RGB:
return MODE_OK;
default:
MISSING_CASE(sink_format);
return MODE_BAD;
}
return MODE_OK;
}
int intel_dp_max_hdisplay_per_pipe(struct intel_display *display)
@ -1442,15 +1442,14 @@ bool intel_dp_dotclk_valid(struct intel_display *display,
}
static enum drm_mode_status
intel_dp_mode_valid(struct drm_connector *_connector,
const struct drm_display_mode *mode)
intel_dp_mode_valid_format(struct intel_connector *connector,
const struct drm_display_mode *mode,
int target_clock,
enum intel_output_format sink_format)
{
struct intel_display *display = to_intel_display(_connector->dev);
struct intel_connector *connector = to_intel_connector(_connector);
struct intel_display *display = to_intel_display(connector);
struct intel_dp *intel_dp = intel_attached_dp(connector);
enum intel_output_format sink_format, output_format;
const struct drm_display_mode *fixed_mode;
int target_clock = mode->clock;
enum intel_output_format output_format;
int max_rate, mode_rate, max_lanes, max_link_clock;
u16 dsc_max_compressed_bpp = 0;
enum drm_mode_status status;
@ -1458,29 +1457,10 @@ intel_dp_mode_valid(struct drm_connector *_connector,
int num_joined_pipes;
int link_bpp_x16;
status = intel_cpu_transcoder_mode_valid(display, mode);
status = intel_dp_sink_format_valid(connector, mode, sink_format);
if (status != MODE_OK)
return status;
if (mode->flags & DRM_MODE_FLAG_DBLCLK)
return MODE_H_ILLEGAL;
if (mode->clock < 10000)
return MODE_CLOCK_LOW;
if (intel_dp_hdisplay_bad(display, mode->hdisplay))
return MODE_H_ILLEGAL;
fixed_mode = intel_panel_fixed_mode(connector, mode);
if (intel_dp_is_edp(intel_dp) && fixed_mode) {
status = intel_panel_mode_valid(connector, mode);
if (status != MODE_OK)
return status;
target_clock = fixed_mode->clock;
}
sink_format = intel_dp_sink_format(connector, mode);
output_format = intel_dp_output_format(connector, sink_format);
max_link_clock = intel_dp_max_link_rate(intel_dp);
@ -1488,7 +1468,8 @@ intel_dp_mode_valid(struct drm_connector *_connector,
max_rate = intel_dp_max_link_data_rate(intel_dp, max_link_clock, max_lanes);
link_bpp_x16 = intel_dp_mode_min_link_bpp_x16(connector, mode);
link_bpp_x16 = intel_dp_mode_min_link_bpp_x16(connector, mode,
output_format);
mode_rate = intel_dp_link_required(max_link_clock, max_lanes,
target_clock, mode->hdisplay,
link_bpp_x16, 0);
@ -1578,7 +1559,70 @@ intel_dp_mode_valid(struct drm_connector *_connector,
if (status != MODE_OK)
return status;
return intel_dp_mode_valid_downstream(connector, mode, target_clock);
return intel_dp_mode_valid_downstream(connector, mode,
target_clock, sink_format);
}
static enum drm_mode_status
intel_dp_mode_valid(struct drm_connector *_connector,
const struct drm_display_mode *mode)
{
struct intel_display *display = to_intel_display(_connector->dev);
struct intel_connector *connector = to_intel_connector(_connector);
const struct drm_display_info *info = &connector->base.display_info;
struct intel_dp *intel_dp = intel_attached_dp(connector);
const struct drm_display_mode *fixed_mode;
int target_clock = mode->clock;
enum drm_mode_status status;
status = intel_cpu_transcoder_mode_valid(display, mode);
if (status != MODE_OK)
return status;
if (mode->flags & DRM_MODE_FLAG_DBLCLK)
return MODE_H_ILLEGAL;
if (mode->clock < 10000)
return MODE_CLOCK_LOW;
if (intel_dp_hdisplay_bad(display, mode->hdisplay))
return MODE_H_ILLEGAL;
fixed_mode = intel_panel_fixed_mode(connector, mode);
if (intel_dp_is_edp(intel_dp) && fixed_mode) {
status = intel_panel_mode_valid(connector, mode);
if (status != MODE_OK)
return status;
target_clock = fixed_mode->clock;
}
/*
* TODO: Even when using a 4:2:0 sink_format intel_dp_output_format()
* will always choose a 4:4:4 output_format if the DFP can do the
* 4:4:4->4:2:0 conversion for us. Thus a mode may still be rejected
* if we only have enough DP link bandwidth for 4:2:0 but not for
* 4:4:4. Another attempt with an explicit 4:2:0 output_format might
* be needed here. intel_dp_compute_config() would need the same
* logic, or else the actual modeset would still fail.
*
* Also a lot of the checks only depend on output_format but not
* sink_format, so we are potentially doing redundant work by
* testing the same output_format for two different sink_formats.
*/
if (drm_mode_is_420_only(info, mode)) {
status = intel_dp_mode_valid_format(connector, mode, target_clock,
INTEL_OUTPUT_FORMAT_YCBCR420);
} else {
status = intel_dp_mode_valid_format(connector, mode, target_clock,
INTEL_OUTPUT_FORMAT_RGB);
if (status != MODE_OK && drm_mode_is_420_also(info, mode))
status = intel_dp_mode_valid_format(connector, mode, target_clock,
INTEL_OUTPUT_FORMAT_YCBCR420);
}
return status;
}
bool intel_dp_source_supports_tps3(struct intel_display *display)
@ -3124,6 +3168,21 @@ static void intel_dp_compute_vsc_colorimetry(const struct intel_crtc_state *crtc
vsc->content_type = DP_CONTENT_TYPE_NOT_DEFINED;
}
static bool intel_dp_needs_as_sdp(struct intel_dp *intel_dp,
struct intel_crtc_state *crtc_state)
{
if (!intel_dp->as_sdp_supported)
return false;
/*
* #TODO Implement AS SDP for DP branch device.
*/
if (drm_dp_is_branch(intel_dp->dpcd))
return false;
return crtc_state->vrr.enable;
}
static void intel_dp_compute_as_sdp(struct intel_dp *intel_dp,
struct intel_crtc_state *crtc_state)
{
@ -3131,7 +3190,12 @@ static void intel_dp_compute_as_sdp(struct intel_dp *intel_dp,
const struct drm_display_mode *adjusted_mode =
&crtc_state->hw.adjusted_mode;
if (!crtc_state->vrr.enable || !intel_dp->as_sdp_supported)
/*
* #FIXME: SDP/infoframe updates arent truly atomic, and with the new
* cdclk->tc clock crossing we may transiently send a corrupted packet
* if the update lands midtransmission.
*/
if (!intel_dp_needs_as_sdp(intel_dp, crtc_state))
return;
crtc_state->infoframes.enable |= intel_hdmi_infoframe_enable(DP_SDP_ADAPTIVE_SYNC);
@ -3330,41 +3394,59 @@ static int
intel_dp_compute_output_format(struct intel_encoder *encoder,
struct intel_crtc_state *crtc_state,
struct drm_connector_state *conn_state,
bool respect_downstream_limits)
bool respect_downstream_limits,
enum intel_output_format sink_format)
{
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
struct intel_connector *connector = intel_dp->attached_connector;
const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
if (intel_dp_sink_format_valid(connector, adjusted_mode,
sink_format) != MODE_OK)
return -EINVAL;
crtc_state->sink_format = sink_format;
crtc_state->output_format = intel_dp_output_format(connector, crtc_state->sink_format);
return intel_dp_compute_link_config(encoder, crtc_state, conn_state,
respect_downstream_limits);
}
static int
intel_dp_compute_formats(struct intel_encoder *encoder,
struct intel_crtc_state *crtc_state,
struct drm_connector_state *conn_state,
bool respect_downstream_limits)
{
struct intel_display *display = to_intel_display(encoder);
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
struct intel_connector *connector = intel_dp->attached_connector;
const struct drm_display_info *info = &connector->base.display_info;
const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
bool ycbcr_420_only;
int ret;
ycbcr_420_only = drm_mode_is_420_only(info, adjusted_mode);
if (drm_mode_is_420_only(info, adjusted_mode)) {
ret = intel_dp_compute_output_format(encoder, crtc_state, conn_state,
respect_downstream_limits,
INTEL_OUTPUT_FORMAT_YCBCR420);
if (ycbcr_420_only && !connector->base.ycbcr_420_allowed) {
drm_dbg_kms(display->drm,
"YCbCr 4:2:0 mode but YCbCr 4:2:0 output not possible. Falling back to RGB.\n");
crtc_state->sink_format = INTEL_OUTPUT_FORMAT_RGB;
if (ret && !respect_downstream_limits) {
drm_dbg_kms(display->drm,
"YCbCr 4:2:0 mode but YCbCr 4:2:0 output not possible. Falling back to RGB.\n");
ret = intel_dp_compute_output_format(encoder, crtc_state, conn_state,
respect_downstream_limits,
INTEL_OUTPUT_FORMAT_RGB);
}
} else {
crtc_state->sink_format = intel_dp_sink_format(connector, adjusted_mode);
}
ret = intel_dp_compute_output_format(encoder, crtc_state, conn_state,
respect_downstream_limits,
INTEL_OUTPUT_FORMAT_RGB);
crtc_state->output_format = intel_dp_output_format(connector, crtc_state->sink_format);
ret = intel_dp_compute_link_config(encoder, crtc_state, conn_state,
respect_downstream_limits);
if (ret) {
if (crtc_state->sink_format == INTEL_OUTPUT_FORMAT_YCBCR420 ||
!connector->base.ycbcr_420_allowed ||
!drm_mode_is_420_also(info, adjusted_mode))
return ret;
crtc_state->sink_format = INTEL_OUTPUT_FORMAT_YCBCR420;
crtc_state->output_format = intel_dp_output_format(connector,
crtc_state->sink_format);
ret = intel_dp_compute_link_config(encoder, crtc_state, conn_state,
respect_downstream_limits);
if (ret && drm_mode_is_420_also(info, adjusted_mode))
ret = intel_dp_compute_output_format(encoder, crtc_state, conn_state,
respect_downstream_limits,
INTEL_OUTPUT_FORMAT_YCBCR420);
}
return ret;
@ -3539,18 +3621,15 @@ intel_dp_compute_config(struct intel_encoder *encoder,
* Try to respect downstream TMDS clock limits first, if
* that fails assume the user might know something we don't.
*/
ret = intel_dp_compute_output_format(encoder, pipe_config, conn_state, true);
ret = intel_dp_compute_formats(encoder, pipe_config, conn_state, true);
if (ret)
ret = intel_dp_compute_output_format(encoder, pipe_config, conn_state, false);
ret = intel_dp_compute_formats(encoder, pipe_config, conn_state, false);
if (ret)
return ret;
if ((intel_dp_is_edp(intel_dp) && fixed_mode) ||
pipe_config->output_format == INTEL_OUTPUT_FORMAT_YCBCR420) {
ret = intel_pfit_compute_config(pipe_config, conn_state);
if (ret)
return ret;
}
ret = intel_pfit_compute_config(pipe_config, conn_state);
if (ret)
return ret;
pipe_config->limited_color_range =
intel_dp_limited_color_range(pipe_config, conn_state);
@ -4505,7 +4584,7 @@ void intel_dp_get_dsc_sink_cap(u8 dpcd_rev,
if (drm_dp_dpcd_readb(connector->dp.dsc_decompression_aux, DP_FEC_CAPABILITY,
&connector->dp.fec_capability) < 0) {
drm_err(display->drm, "Failed to read FEC DPCD register\n");
drm_dbg_kms(display->drm, "Could not read FEC DPCD register\n");
return;
}

View File

@ -742,11 +742,14 @@ static void intel_dp_update_downspread_ctrl(struct intel_dp *intel_dp,
void intel_dp_link_training_set_bw(struct intel_dp *intel_dp,
int link_bw, int rate_select, int lane_count,
bool enhanced_framing)
bool enhanced_framing, bool post_lt_adj_req)
{
if (enhanced_framing)
lane_count |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
if (post_lt_adj_req)
lane_count |= DP_POST_LT_ADJ_REQ_GRANTED;
if (link_bw) {
/* DP and eDP v1.3 and earlier link bw set method. */
u8 link_config[] = { link_bw, lane_count };
@ -825,12 +828,21 @@ static u32 intel_dp_training_pattern(struct intel_dp *intel_dp,
return DP_TRAINING_PATTERN_2;
}
static bool intel_dp_use_post_lt_adj_req(struct intel_dp *intel_dp,
const struct intel_crtc_state *crtc_state)
{
return intel_dp->set_idle_link_train &&
drm_dp_post_lt_adj_req_supported(intel_dp->dpcd) &&
intel_dp_training_pattern(intel_dp, crtc_state, DP_PHY_DPRX) != DP_TRAINING_PATTERN_4;
}
static void intel_dp_update_link_bw_set(struct intel_dp *intel_dp,
const struct intel_crtc_state *crtc_state,
u8 link_bw, u8 rate_select)
{
intel_dp_link_training_set_bw(intel_dp, link_bw, rate_select, crtc_state->lane_count,
crtc_state->enhanced_framing);
crtc_state->enhanced_framing,
intel_dp_use_post_lt_adj_req(intel_dp, crtc_state));
}
/*
@ -1091,6 +1103,109 @@ intel_dp_link_training_channel_equalization(struct intel_dp *intel_dp,
return channel_eq;
}
static bool
intel_dp_post_lt_adj_req(struct intel_dp *intel_dp,
const struct intel_crtc_state *crtc_state)
{
u8 link_status[DP_LINK_STATUS_SIZE];
unsigned long deadline;
bool timeout = false;
bool success = false;
int changes = 0;
if (!intel_dp_use_post_lt_adj_req(intel_dp, crtc_state))
return true;
if (drm_dp_dpcd_read_phy_link_status(&intel_dp->aux, DP_PHY_DPRX,
link_status) < 0) {
lt_err(intel_dp, DP_PHY_DPRX, "Failed to get link status\n");
return false;
}
deadline = jiffies + msecs_to_jiffies_timeout(200);
for (;;) {
/* Make sure clock is still ok */
if (!drm_dp_clock_recovery_ok(link_status,
crtc_state->lane_count)) {
intel_dp_dump_link_status(intel_dp, DP_PHY_DPRX, link_status);
lt_dbg(intel_dp, DP_PHY_DPRX,
"Clock recovery check failed, cannot continue POST_LT_ADJ_REQ\n");
break;
}
if (!drm_dp_channel_eq_ok(link_status,
crtc_state->lane_count)) {
intel_dp_dump_link_status(intel_dp, DP_PHY_DPRX, link_status);
lt_dbg(intel_dp, DP_PHY_DPRX, "Channel EQ check failed. cannot continue POST_LT_ADJ_REQ\n");
break;
}
if (!drm_dp_post_lt_adj_req_in_progress(link_status)) {
success = true;
intel_dp_dump_link_status(intel_dp, DP_PHY_DPRX, link_status);
lt_dbg(intel_dp, DP_PHY_DPRX,
"POST_LT_ADJ_REQ done (%d changes). DP Training successful\n", changes);
break;
}
if (changes == 6) {
success = true;
intel_dp_dump_link_status(intel_dp, DP_PHY_DPRX, link_status);
lt_dbg(intel_dp, DP_PHY_DPRX,
"POST_LT_ADJ_REQ limit reached (%d changes). DP Training successful\n", changes);
break;
}
if (timeout) {
success = true;
intel_dp_dump_link_status(intel_dp, DP_PHY_DPRX, link_status);
lt_dbg(intel_dp, DP_PHY_DPRX,
"POST_LT_ADJ_REQ timeout reached (%d changes). DP Training successful\n", changes);
break;
}
fsleep(5000);
if (drm_dp_dpcd_read_phy_link_status(&intel_dp->aux, DP_PHY_DPRX,
link_status) < 0) {
lt_err(intel_dp, DP_PHY_DPRX, "Failed to get link status\n");
break;
}
/* Update training set as requested by target */
if (intel_dp_get_adjust_train(intel_dp, crtc_state, DP_PHY_DPRX, link_status)) {
deadline = jiffies + msecs_to_jiffies_timeout(200);
changes++;
if (!intel_dp_update_link_train(intel_dp, crtc_state, DP_PHY_DPRX)) {
lt_err(intel_dp, DP_PHY_DPRX, "Failed to update link training\n");
break;
}
} else if (time_after(jiffies, deadline)) {
timeout = true;
}
}
return success;
}
static void intel_dp_stop_post_lt_adj_req(struct intel_dp *intel_dp,
const struct intel_crtc_state *crtc_state)
{
u8 lane_count;
if (!intel_dp_use_post_lt_adj_req(intel_dp, crtc_state))
return;
/* clear DP_POST_LT_ADJ_REQ_GRANTED */
lane_count = crtc_state->lane_count;
if (crtc_state->enhanced_framing)
lane_count |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
drm_dp_dpcd_writeb(&intel_dp->aux, DP_LANE_COUNT_SET, lane_count);
}
static bool intel_dp_disable_dpcd_training_pattern(struct intel_dp *intel_dp,
enum drm_dp_phy dp_phy)
{
@ -1389,6 +1504,11 @@ intel_dp_link_train_all_phys(struct intel_dp *intel_dp,
intel_dp_disable_dpcd_training_pattern(intel_dp, DP_PHY_DPRX);
intel_dp->set_idle_link_train(intel_dp, crtc_state);
if (ret)
ret = intel_dp_post_lt_adj_req(intel_dp, crtc_state);
intel_dp_stop_post_lt_adj_req(intel_dp, crtc_state);
return ret;
}

View File

@ -21,7 +21,7 @@ void intel_dp_link_training_set_mode(struct intel_dp *intel_dp,
int link_rate, bool is_vrr);
void intel_dp_link_training_set_bw(struct intel_dp *intel_dp,
int link_bw, int rate_select, int lane_count,
bool enhanced_framing);
bool enhanced_framing, bool post_lt_adj_req);
bool intel_dp_get_adjust_train(struct intel_dp *intel_dp,
const struct intel_crtc_state *crtc_state,

View File

@ -721,7 +721,10 @@ static int mst_stream_compute_config(struct intel_encoder *encoder,
pipe_config->sink_format = INTEL_OUTPUT_FORMAT_RGB;
pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
pipe_config->has_pch_encoder = false;
ret = intel_pfit_compute_config(pipe_config, conn_state);
if (ret)
return ret;
for_each_joiner_candidate(connector, adjusted_mode, num_joined_pipes) {
if (num_joined_pipes > 1)
@ -2144,7 +2147,7 @@ void intel_dp_mst_prepare_probe(struct intel_dp *intel_dp)
intel_dp_link_training_set_mode(intel_dp, link_rate, false);
intel_dp_link_training_set_bw(intel_dp, link_bw, rate_select, lane_count,
drm_dp_enhanced_frame_cap(intel_dp->dpcd));
drm_dp_enhanced_frame_cap(intel_dp->dpcd), false);
intel_mst_set_probed_link_params(intel_dp, link_rate, lane_count);
}

View File

@ -296,6 +296,24 @@ bool intel_dp_tunnel_bw_alloc_is_enabled(struct intel_dp *intel_dp)
return drm_dp_tunnel_bw_alloc_is_enabled(intel_dp->tunnel);
}
/**
* intel_dp_tunnel_pr_optimization_supported - Query the PR BW optimization support
* @intel_dp: DP port object
*
* Query whether a DP tunnel supports the PR BW optimization.
*
* Returns %true if the BW allocation mode is supported on @intel_dp.
*/
bool intel_dp_tunnel_pr_optimization_supported(struct intel_dp *intel_dp)
{
struct intel_display *display = to_intel_display(intel_dp);
if (DISPLAY_VER(display) < 35)
return false;
return drm_dp_tunnel_pr_optimization_supported(intel_dp->tunnel);
}
/**
* intel_dp_tunnel_suspend - Suspend a DP tunnel connected on a port
* @intel_dp: DP port object

View File

@ -32,6 +32,7 @@ void intel_dp_tunnel_resume(struct intel_dp *intel_dp,
void intel_dp_tunnel_suspend(struct intel_dp *intel_dp);
bool intel_dp_tunnel_bw_alloc_is_enabled(struct intel_dp *intel_dp);
bool intel_dp_tunnel_pr_optimization_supported(struct intel_dp *intel_dp);
void
intel_dp_tunnel_atomic_cleanup_inherited_state(struct intel_atomic_state *state);
@ -76,6 +77,11 @@ static inline bool intel_dp_tunnel_bw_alloc_is_enabled(struct intel_dp *intel_dp
return false;
}
static inline bool intel_dp_tunnel_pr_optimization_supported(struct intel_dp *intel_dp)
{
return false;
}
static inline void
intel_dp_tunnel_atomic_cleanup_inherited_state(struct intel_atomic_state *state) {}

View File

@ -301,7 +301,7 @@ void bxt_dpio_phy_set_signal_levels(struct intel_encoder *encoder,
enum dpio_phy phy;
int lane, n_entries;
trans = encoder->get_buf_trans(encoder, crtc_state, &n_entries);
trans = intel_ddi_buf_trans_get(encoder, crtc_state, &n_entries);
if (drm_WARN_ON_ONCE(display->drm, !trans))
return;
@ -724,46 +724,46 @@ void chv_set_phy_signal_level(struct intel_encoder *encoder,
u32 val;
int i;
vlv_dpio_get(display->drm);
vlv_dpio_get(display);
/* Clear calc init */
val = vlv_dpio_read(display->drm, phy, VLV_PCS01_DW10(ch));
val = vlv_dpio_read(display, phy, VLV_PCS01_DW10(ch));
val &= ~(DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3);
val &= ~(DPIO_PCS_TX1DEEMP_MASK | DPIO_PCS_TX2DEEMP_MASK);
val |= DPIO_PCS_TX1DEEMP_9P5 | DPIO_PCS_TX2DEEMP_9P5;
vlv_dpio_write(display->drm, phy, VLV_PCS01_DW10(ch), val);
vlv_dpio_write(display, phy, VLV_PCS01_DW10(ch), val);
if (crtc_state->lane_count > 2) {
val = vlv_dpio_read(display->drm, phy, VLV_PCS23_DW10(ch));
val = vlv_dpio_read(display, phy, VLV_PCS23_DW10(ch));
val &= ~(DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3);
val &= ~(DPIO_PCS_TX1DEEMP_MASK | DPIO_PCS_TX2DEEMP_MASK);
val |= DPIO_PCS_TX1DEEMP_9P5 | DPIO_PCS_TX2DEEMP_9P5;
vlv_dpio_write(display->drm, phy, VLV_PCS23_DW10(ch), val);
vlv_dpio_write(display, phy, VLV_PCS23_DW10(ch), val);
}
val = vlv_dpio_read(display->drm, phy, VLV_PCS01_DW9(ch));
val = vlv_dpio_read(display, phy, VLV_PCS01_DW9(ch));
val &= ~(DPIO_PCS_TX1MARGIN_MASK | DPIO_PCS_TX2MARGIN_MASK);
val |= DPIO_PCS_TX1MARGIN_000 | DPIO_PCS_TX2MARGIN_000;
vlv_dpio_write(display->drm, phy, VLV_PCS01_DW9(ch), val);
vlv_dpio_write(display, phy, VLV_PCS01_DW9(ch), val);
if (crtc_state->lane_count > 2) {
val = vlv_dpio_read(display->drm, phy, VLV_PCS23_DW9(ch));
val = vlv_dpio_read(display, phy, VLV_PCS23_DW9(ch));
val &= ~(DPIO_PCS_TX1MARGIN_MASK | DPIO_PCS_TX2MARGIN_MASK);
val |= DPIO_PCS_TX1MARGIN_000 | DPIO_PCS_TX2MARGIN_000;
vlv_dpio_write(display->drm, phy, VLV_PCS23_DW9(ch), val);
vlv_dpio_write(display, phy, VLV_PCS23_DW9(ch), val);
}
/* Program swing deemph */
for (i = 0; i < crtc_state->lane_count; i++) {
val = vlv_dpio_read(display->drm, phy, CHV_TX_DW4(ch, i));
val = vlv_dpio_read(display, phy, CHV_TX_DW4(ch, i));
val &= ~DPIO_SWING_DEEMPH9P5_MASK;
val |= DPIO_SWING_DEEMPH9P5(deemph_reg_value);
vlv_dpio_write(display->drm, phy, CHV_TX_DW4(ch, i), val);
vlv_dpio_write(display, phy, CHV_TX_DW4(ch, i), val);
}
/* Program swing margin */
for (i = 0; i < crtc_state->lane_count; i++) {
val = vlv_dpio_read(display->drm, phy, CHV_TX_DW2(ch, i));
val = vlv_dpio_read(display, phy, CHV_TX_DW2(ch, i));
val &= ~DPIO_SWING_MARGIN000_MASK;
val |= DPIO_SWING_MARGIN000(margin_reg_value);
@ -776,7 +776,7 @@ void chv_set_phy_signal_level(struct intel_encoder *encoder,
val &= ~DPIO_UNIQ_TRANS_SCALE_MASK;
val |= DPIO_UNIQ_TRANS_SCALE(0x9a);
vlv_dpio_write(display->drm, phy, CHV_TX_DW2(ch, i), val);
vlv_dpio_write(display, phy, CHV_TX_DW2(ch, i), val);
}
/*
@ -786,26 +786,26 @@ void chv_set_phy_signal_level(struct intel_encoder *encoder,
* 27 for ch0 and ch1.
*/
for (i = 0; i < crtc_state->lane_count; i++) {
val = vlv_dpio_read(display->drm, phy, CHV_TX_DW3(ch, i));
val = vlv_dpio_read(display, phy, CHV_TX_DW3(ch, i));
if (uniq_trans_scale)
val |= DPIO_TX_UNIQ_TRANS_SCALE_EN;
else
val &= ~DPIO_TX_UNIQ_TRANS_SCALE_EN;
vlv_dpio_write(display->drm, phy, CHV_TX_DW3(ch, i), val);
vlv_dpio_write(display, phy, CHV_TX_DW3(ch, i), val);
}
/* Start swing calculation */
val = vlv_dpio_read(display->drm, phy, VLV_PCS01_DW10(ch));
val = vlv_dpio_read(display, phy, VLV_PCS01_DW10(ch));
val |= DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3;
vlv_dpio_write(display->drm, phy, VLV_PCS01_DW10(ch), val);
vlv_dpio_write(display, phy, VLV_PCS01_DW10(ch), val);
if (crtc_state->lane_count > 2) {
val = vlv_dpio_read(display->drm, phy, VLV_PCS23_DW10(ch));
val = vlv_dpio_read(display, phy, VLV_PCS23_DW10(ch));
val |= DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3;
vlv_dpio_write(display->drm, phy, VLV_PCS23_DW10(ch), val);
vlv_dpio_write(display, phy, VLV_PCS23_DW10(ch), val);
}
vlv_dpio_put(display->drm);
vlv_dpio_put(display);
}
static void __chv_data_lane_soft_reset(struct intel_encoder *encoder,
@ -818,38 +818,38 @@ static void __chv_data_lane_soft_reset(struct intel_encoder *encoder,
enum dpio_phy phy = vlv_dig_port_to_phy(dig_port);
u32 val;
val = vlv_dpio_read(display->drm, phy, VLV_PCS01_DW0(ch));
val = vlv_dpio_read(display, phy, VLV_PCS01_DW0(ch));
if (reset)
val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
else
val |= DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET;
vlv_dpio_write(display->drm, phy, VLV_PCS01_DW0(ch), val);
vlv_dpio_write(display, phy, VLV_PCS01_DW0(ch), val);
if (crtc_state->lane_count > 2) {
val = vlv_dpio_read(display->drm, phy, VLV_PCS23_DW0(ch));
val = vlv_dpio_read(display, phy, VLV_PCS23_DW0(ch));
if (reset)
val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
else
val |= DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET;
vlv_dpio_write(display->drm, phy, VLV_PCS23_DW0(ch), val);
vlv_dpio_write(display, phy, VLV_PCS23_DW0(ch), val);
}
val = vlv_dpio_read(display->drm, phy, VLV_PCS01_DW1(ch));
val = vlv_dpio_read(display, phy, VLV_PCS01_DW1(ch));
val |= CHV_PCS_REQ_SOFTRESET_EN;
if (reset)
val &= ~DPIO_PCS_CLK_SOFT_RESET;
else
val |= DPIO_PCS_CLK_SOFT_RESET;
vlv_dpio_write(display->drm, phy, VLV_PCS01_DW1(ch), val);
vlv_dpio_write(display, phy, VLV_PCS01_DW1(ch), val);
if (crtc_state->lane_count > 2) {
val = vlv_dpio_read(display->drm, phy, VLV_PCS23_DW1(ch));
val = vlv_dpio_read(display, phy, VLV_PCS23_DW1(ch));
val |= CHV_PCS_REQ_SOFTRESET_EN;
if (reset)
val &= ~DPIO_PCS_CLK_SOFT_RESET;
else
val |= DPIO_PCS_CLK_SOFT_RESET;
vlv_dpio_write(display->drm, phy, VLV_PCS23_DW1(ch), val);
vlv_dpio_write(display, phy, VLV_PCS23_DW1(ch), val);
}
}
@ -859,9 +859,9 @@ void chv_data_lane_soft_reset(struct intel_encoder *encoder,
{
struct intel_display *display = to_intel_display(encoder);
vlv_dpio_get(display->drm);
vlv_dpio_get(display);
__chv_data_lane_soft_reset(encoder, crtc_state, reset);
vlv_dpio_put(display->drm);
vlv_dpio_put(display);
}
void chv_phy_pre_pll_enable(struct intel_encoder *encoder,
@ -887,47 +887,47 @@ void chv_phy_pre_pll_enable(struct intel_encoder *encoder,
chv_phy_powergate_lanes(encoder, true, lane_mask);
vlv_dpio_get(display->drm);
vlv_dpio_get(display);
/* Assert data lane reset */
__chv_data_lane_soft_reset(encoder, crtc_state, true);
/* program left/right clock distribution */
if (pipe != PIPE_B) {
val = vlv_dpio_read(display->drm, phy, CHV_CMN_DW5_CH0);
val = vlv_dpio_read(display, phy, CHV_CMN_DW5_CH0);
val &= ~(CHV_BUFLEFTENA1_MASK | CHV_BUFRIGHTENA1_MASK);
if (ch == DPIO_CH0)
val |= CHV_BUFLEFTENA1_FORCE;
if (ch == DPIO_CH1)
val |= CHV_BUFRIGHTENA1_FORCE;
vlv_dpio_write(display->drm, phy, CHV_CMN_DW5_CH0, val);
vlv_dpio_write(display, phy, CHV_CMN_DW5_CH0, val);
} else {
val = vlv_dpio_read(display->drm, phy, CHV_CMN_DW1_CH1);
val = vlv_dpio_read(display, phy, CHV_CMN_DW1_CH1);
val &= ~(CHV_BUFLEFTENA2_MASK | CHV_BUFRIGHTENA2_MASK);
if (ch == DPIO_CH0)
val |= CHV_BUFLEFTENA2_FORCE;
if (ch == DPIO_CH1)
val |= CHV_BUFRIGHTENA2_FORCE;
vlv_dpio_write(display->drm, phy, CHV_CMN_DW1_CH1, val);
vlv_dpio_write(display, phy, CHV_CMN_DW1_CH1, val);
}
/* program clock channel usage */
val = vlv_dpio_read(display->drm, phy, VLV_PCS01_DW8(ch));
val = vlv_dpio_read(display, phy, VLV_PCS01_DW8(ch));
val |= DPIO_PCS_USEDCLKCHANNEL_OVRRIDE;
if (pipe == PIPE_B)
val |= DPIO_PCS_USEDCLKCHANNEL;
else
val &= ~DPIO_PCS_USEDCLKCHANNEL;
vlv_dpio_write(display->drm, phy, VLV_PCS01_DW8(ch), val);
vlv_dpio_write(display, phy, VLV_PCS01_DW8(ch), val);
if (crtc_state->lane_count > 2) {
val = vlv_dpio_read(display->drm, phy, VLV_PCS23_DW8(ch));
val = vlv_dpio_read(display, phy, VLV_PCS23_DW8(ch));
val |= DPIO_PCS_USEDCLKCHANNEL_OVRRIDE;
if (pipe == PIPE_B)
val |= DPIO_PCS_USEDCLKCHANNEL;
else
val &= ~DPIO_PCS_USEDCLKCHANNEL;
vlv_dpio_write(display->drm, phy, VLV_PCS23_DW8(ch), val);
vlv_dpio_write(display, phy, VLV_PCS23_DW8(ch), val);
}
/*
@ -935,14 +935,14 @@ void chv_phy_pre_pll_enable(struct intel_encoder *encoder,
* matches the pipe, but here we need to
* pick the CL based on the port.
*/
val = vlv_dpio_read(display->drm, phy, CHV_CMN_DW19(ch));
val = vlv_dpio_read(display, phy, CHV_CMN_DW19(ch));
if (pipe == PIPE_B)
val |= CHV_CMN_USEDCLKCHANNEL;
else
val &= ~CHV_CMN_USEDCLKCHANNEL;
vlv_dpio_write(display->drm, phy, CHV_CMN_DW19(ch), val);
vlv_dpio_write(display, phy, CHV_CMN_DW19(ch), val);
vlv_dpio_put(display->drm);
vlv_dpio_put(display);
}
void chv_phy_pre_encoder_enable(struct intel_encoder *encoder,
@ -956,17 +956,17 @@ void chv_phy_pre_encoder_enable(struct intel_encoder *encoder,
int data, i, stagger;
u32 val;
vlv_dpio_get(display->drm);
vlv_dpio_get(display);
/* allow hardware to manage TX FIFO reset source */
val = vlv_dpio_read(display->drm, phy, VLV_PCS01_DW11(ch));
val = vlv_dpio_read(display, phy, VLV_PCS01_DW11(ch));
val &= ~DPIO_LANEDESKEW_STRAP_OVRD;
vlv_dpio_write(display->drm, phy, VLV_PCS01_DW11(ch), val);
vlv_dpio_write(display, phy, VLV_PCS01_DW11(ch), val);
if (crtc_state->lane_count > 2) {
val = vlv_dpio_read(display->drm, phy, VLV_PCS23_DW11(ch));
val = vlv_dpio_read(display, phy, VLV_PCS23_DW11(ch));
val &= ~DPIO_LANEDESKEW_STRAP_OVRD;
vlv_dpio_write(display->drm, phy, VLV_PCS23_DW11(ch), val);
vlv_dpio_write(display, phy, VLV_PCS23_DW11(ch), val);
}
/* Program Tx lane latency optimal setting*/
@ -976,7 +976,7 @@ void chv_phy_pre_encoder_enable(struct intel_encoder *encoder,
data = 0;
else
data = (i == 1) ? 0 : DPIO_UPAR;
vlv_dpio_write(display->drm, phy, CHV_TX_DW14(ch, i), data);
vlv_dpio_write(display, phy, CHV_TX_DW14(ch, i), data);
}
/* Data lane stagger programming */
@ -991,17 +991,17 @@ void chv_phy_pre_encoder_enable(struct intel_encoder *encoder,
else
stagger = 0x2;
val = vlv_dpio_read(display->drm, phy, VLV_PCS01_DW11(ch));
val = vlv_dpio_read(display, phy, VLV_PCS01_DW11(ch));
val |= DPIO_TX2_STAGGER_MASK(0x1f);
vlv_dpio_write(display->drm, phy, VLV_PCS01_DW11(ch), val);
vlv_dpio_write(display, phy, VLV_PCS01_DW11(ch), val);
if (crtc_state->lane_count > 2) {
val = vlv_dpio_read(display->drm, phy, VLV_PCS23_DW11(ch));
val = vlv_dpio_read(display, phy, VLV_PCS23_DW11(ch));
val |= DPIO_TX2_STAGGER_MASK(0x1f);
vlv_dpio_write(display->drm, phy, VLV_PCS23_DW11(ch), val);
vlv_dpio_write(display, phy, VLV_PCS23_DW11(ch), val);
}
vlv_dpio_write(display->drm, phy, VLV_PCS01_DW12(ch),
vlv_dpio_write(display, phy, VLV_PCS01_DW12(ch),
DPIO_LANESTAGGER_STRAP(stagger) |
DPIO_LANESTAGGER_STRAP_OVRD |
DPIO_TX1_STAGGER_MASK(0x1f) |
@ -1009,7 +1009,7 @@ void chv_phy_pre_encoder_enable(struct intel_encoder *encoder,
DPIO_TX2_STAGGER_MULT(0));
if (crtc_state->lane_count > 2) {
vlv_dpio_write(display->drm, phy, VLV_PCS23_DW12(ch),
vlv_dpio_write(display, phy, VLV_PCS23_DW12(ch),
DPIO_LANESTAGGER_STRAP(stagger) |
DPIO_LANESTAGGER_STRAP_OVRD |
DPIO_TX1_STAGGER_MASK(0x1f) |
@ -1020,7 +1020,7 @@ void chv_phy_pre_encoder_enable(struct intel_encoder *encoder,
/* Deassert data lane reset */
__chv_data_lane_soft_reset(encoder, crtc_state, false);
vlv_dpio_put(display->drm);
vlv_dpio_put(display);
}
void chv_phy_release_cl2_override(struct intel_encoder *encoder)
@ -1042,20 +1042,20 @@ void chv_phy_post_pll_disable(struct intel_encoder *encoder,
enum pipe pipe = to_intel_crtc(old_crtc_state->uapi.crtc)->pipe;
u32 val;
vlv_dpio_get(display->drm);
vlv_dpio_get(display);
/* disable left/right clock distribution */
if (pipe != PIPE_B) {
val = vlv_dpio_read(display->drm, phy, CHV_CMN_DW5_CH0);
val = vlv_dpio_read(display, phy, CHV_CMN_DW5_CH0);
val &= ~(CHV_BUFLEFTENA1_MASK | CHV_BUFRIGHTENA1_MASK);
vlv_dpio_write(display->drm, phy, CHV_CMN_DW5_CH0, val);
vlv_dpio_write(display, phy, CHV_CMN_DW5_CH0, val);
} else {
val = vlv_dpio_read(display->drm, phy, CHV_CMN_DW1_CH1);
val = vlv_dpio_read(display, phy, CHV_CMN_DW1_CH1);
val &= ~(CHV_BUFLEFTENA2_MASK | CHV_BUFRIGHTENA2_MASK);
vlv_dpio_write(display->drm, phy, CHV_CMN_DW1_CH1, val);
vlv_dpio_write(display, phy, CHV_CMN_DW1_CH1, val);
}
vlv_dpio_put(display->drm);
vlv_dpio_put(display);
/*
* Leave the power down bit cleared for at least one
@ -1079,22 +1079,22 @@ void vlv_set_phy_signal_level(struct intel_encoder *encoder,
enum dpio_channel ch = vlv_dig_port_to_channel(dig_port);
enum dpio_phy phy = vlv_dig_port_to_phy(dig_port);
vlv_dpio_get(display->drm);
vlv_dpio_get(display);
vlv_dpio_write(display->drm, phy, VLV_TX_DW5_GRP(ch), 0x00000000);
vlv_dpio_write(display->drm, phy, VLV_TX_DW4_GRP(ch), demph_reg_value);
vlv_dpio_write(display->drm, phy, VLV_TX_DW2_GRP(ch),
vlv_dpio_write(display, phy, VLV_TX_DW5_GRP(ch), 0x00000000);
vlv_dpio_write(display, phy, VLV_TX_DW4_GRP(ch), demph_reg_value);
vlv_dpio_write(display, phy, VLV_TX_DW2_GRP(ch),
uniqtranscale_reg_value);
vlv_dpio_write(display->drm, phy, VLV_TX_DW3_GRP(ch), 0x0C782040);
vlv_dpio_write(display, phy, VLV_TX_DW3_GRP(ch), 0x0C782040);
if (tx3_demph)
vlv_dpio_write(display->drm, phy, VLV_TX_DW4(ch, 3), tx3_demph);
vlv_dpio_write(display, phy, VLV_TX_DW4(ch, 3), tx3_demph);
vlv_dpio_write(display->drm, phy, VLV_PCS_DW11_GRP(ch), 0x00030000);
vlv_dpio_write(display->drm, phy, VLV_PCS_DW9_GRP(ch), preemph_reg_value);
vlv_dpio_write(display->drm, phy, VLV_TX_DW5_GRP(ch), DPIO_TX_OCALINIT_EN);
vlv_dpio_write(display, phy, VLV_PCS_DW11_GRP(ch), 0x00030000);
vlv_dpio_write(display, phy, VLV_PCS_DW9_GRP(ch), preemph_reg_value);
vlv_dpio_write(display, phy, VLV_TX_DW5_GRP(ch), DPIO_TX_OCALINIT_EN);
vlv_dpio_put(display->drm);
vlv_dpio_put(display);
}
void vlv_phy_pre_pll_enable(struct intel_encoder *encoder,
@ -1106,23 +1106,23 @@ void vlv_phy_pre_pll_enable(struct intel_encoder *encoder,
enum dpio_phy phy = vlv_dig_port_to_phy(dig_port);
/* Program Tx lane resets to default */
vlv_dpio_get(display->drm);
vlv_dpio_get(display);
vlv_dpio_write(display->drm, phy, VLV_PCS_DW0_GRP(ch),
vlv_dpio_write(display, phy, VLV_PCS_DW0_GRP(ch),
DPIO_PCS_TX_LANE2_RESET |
DPIO_PCS_TX_LANE1_RESET);
vlv_dpio_write(display->drm, phy, VLV_PCS_DW1_GRP(ch),
vlv_dpio_write(display, phy, VLV_PCS_DW1_GRP(ch),
DPIO_PCS_CLK_CRI_RXEB_EIOS_EN |
DPIO_PCS_CLK_CRI_RXDIGFILTSG_EN |
DPIO_PCS_CLK_DATAWIDTH_8_10 |
DPIO_PCS_CLK_SOFT_RESET);
/* Fix up inter-pair skew failure */
vlv_dpio_write(display->drm, phy, VLV_PCS_DW12_GRP(ch), 0x00750f00);
vlv_dpio_write(display->drm, phy, VLV_TX_DW11_GRP(ch), 0x00001500);
vlv_dpio_write(display->drm, phy, VLV_TX_DW14_GRP(ch), 0x40400000);
vlv_dpio_write(display, phy, VLV_PCS_DW12_GRP(ch), 0x00750f00);
vlv_dpio_write(display, phy, VLV_TX_DW11_GRP(ch), 0x00001500);
vlv_dpio_write(display, phy, VLV_TX_DW14_GRP(ch), 0x40400000);
vlv_dpio_put(display->drm);
vlv_dpio_put(display);
}
void vlv_phy_pre_encoder_enable(struct intel_encoder *encoder,
@ -1137,20 +1137,20 @@ void vlv_phy_pre_encoder_enable(struct intel_encoder *encoder,
enum pipe pipe = crtc->pipe;
u32 val;
vlv_dpio_get(display->drm);
vlv_dpio_get(display);
/* Enable clock channels for this port */
val = DPIO_PCS_USEDCLKCHANNEL_OVRRIDE;
if (pipe == PIPE_B)
val |= DPIO_PCS_USEDCLKCHANNEL;
val |= 0xc4;
vlv_dpio_write(display->drm, phy, VLV_PCS_DW8_GRP(ch), val);
vlv_dpio_write(display, phy, VLV_PCS_DW8_GRP(ch), val);
/* Program lane clock */
vlv_dpio_write(display->drm, phy, VLV_PCS_DW14_GRP(ch), 0x00760018);
vlv_dpio_write(display->drm, phy, VLV_PCS_DW23_GRP(ch), 0x00400888);
vlv_dpio_write(display, phy, VLV_PCS_DW14_GRP(ch), 0x00760018);
vlv_dpio_write(display, phy, VLV_PCS_DW23_GRP(ch), 0x00400888);
vlv_dpio_put(display->drm);
vlv_dpio_put(display);
}
void vlv_phy_reset_lanes(struct intel_encoder *encoder,
@ -1161,10 +1161,10 @@ void vlv_phy_reset_lanes(struct intel_encoder *encoder,
enum dpio_channel ch = vlv_dig_port_to_channel(dig_port);
enum dpio_phy phy = vlv_dig_port_to_phy(dig_port);
vlv_dpio_get(display->drm);
vlv_dpio_write(display->drm, phy, VLV_PCS_DW0_GRP(ch), 0x00000000);
vlv_dpio_write(display->drm, phy, VLV_PCS_DW1_GRP(ch), 0x00e00060);
vlv_dpio_put(display->drm);
vlv_dpio_get(display);
vlv_dpio_write(display, phy, VLV_PCS_DW0_GRP(ch), 0x00000000);
vlv_dpio_write(display, phy, VLV_PCS_DW1_GRP(ch), 0x00e00060);
vlv_dpio_put(display);
}
void vlv_wait_port_ready(struct intel_encoder *encoder,

View File

@ -528,9 +528,9 @@ void vlv_crtc_clock_get(struct intel_crtc_state *crtc_state)
if ((hw_state->dpll & DPLL_VCO_ENABLE) == 0)
return;
vlv_dpio_get(display->drm);
tmp = vlv_dpio_read(display->drm, phy, VLV_PLL_DW3(ch));
vlv_dpio_put(display->drm);
vlv_dpio_get(display);
tmp = vlv_dpio_read(display, phy, VLV_PLL_DW3(ch));
vlv_dpio_put(display);
clock.m1 = REG_FIELD_GET(DPIO_M1_DIV_MASK, tmp);
clock.m2 = REG_FIELD_GET(DPIO_M2_DIV_MASK, tmp);
@ -556,13 +556,13 @@ void chv_crtc_clock_get(struct intel_crtc_state *crtc_state)
if ((hw_state->dpll & DPLL_VCO_ENABLE) == 0)
return;
vlv_dpio_get(display->drm);
cmn_dw13 = vlv_dpio_read(display->drm, phy, CHV_CMN_DW13(ch));
pll_dw0 = vlv_dpio_read(display->drm, phy, CHV_PLL_DW0(ch));
pll_dw1 = vlv_dpio_read(display->drm, phy, CHV_PLL_DW1(ch));
pll_dw2 = vlv_dpio_read(display->drm, phy, CHV_PLL_DW2(ch));
pll_dw3 = vlv_dpio_read(display->drm, phy, CHV_PLL_DW3(ch));
vlv_dpio_put(display->drm);
vlv_dpio_get(display);
cmn_dw13 = vlv_dpio_read(display, phy, CHV_CMN_DW13(ch));
pll_dw0 = vlv_dpio_read(display, phy, CHV_PLL_DW0(ch));
pll_dw1 = vlv_dpio_read(display, phy, CHV_PLL_DW1(ch));
pll_dw2 = vlv_dpio_read(display, phy, CHV_PLL_DW2(ch));
pll_dw3 = vlv_dpio_read(display, phy, CHV_PLL_DW3(ch));
vlv_dpio_put(display);
clock.m1 = REG_FIELD_GET(DPIO_CHV_M1_DIV_MASK, pll_dw1) == DPIO_CHV_M1_DIV_BY_2 ? 2 : 0;
clock.m2 = REG_FIELD_GET(DPIO_CHV_M2_DIV_MASK, pll_dw0) << 22;
@ -1735,7 +1735,7 @@ int intel_dpll_crtc_compute_clock(struct intel_atomic_state *state,
if (!crtc_state->hw.enable)
return 0;
ret = display->funcs.dpll->crtc_compute_clock(state, crtc);
ret = display->dpll.funcs->crtc_compute_clock(state, crtc);
if (ret) {
drm_dbg_kms(display->drm, "[CRTC:%d:%s] Couldn't calculate DPLL settings\n",
crtc->base.base.id, crtc->base.name);
@ -1759,10 +1759,10 @@ int intel_dpll_crtc_get_dpll(struct intel_atomic_state *state,
if (!crtc_state->hw.enable || crtc_state->intel_dpll)
return 0;
if (!display->funcs.dpll->crtc_get_dpll)
if (!display->dpll.funcs->crtc_get_dpll)
return 0;
ret = display->funcs.dpll->crtc_get_dpll(state, crtc);
ret = display->dpll.funcs->crtc_get_dpll(state, crtc);
if (ret) {
drm_dbg_kms(display->drm, "[CRTC:%d:%s] Couldn't get a shared DPLL\n",
crtc->base.base.id, crtc->base.name);
@ -1776,27 +1776,27 @@ void
intel_dpll_init_clock_hook(struct intel_display *display)
{
if (HAS_LT_PHY(display))
display->funcs.dpll = &xe3plpd_dpll_funcs;
display->dpll.funcs = &xe3plpd_dpll_funcs;
else if (DISPLAY_VER(display) >= 14)
display->funcs.dpll = &mtl_dpll_funcs;
display->dpll.funcs = &mtl_dpll_funcs;
else if (display->platform.dg2)
display->funcs.dpll = &dg2_dpll_funcs;
display->dpll.funcs = &dg2_dpll_funcs;
else if (DISPLAY_VER(display) >= 9 || HAS_DDI(display))
display->funcs.dpll = &hsw_dpll_funcs;
display->dpll.funcs = &hsw_dpll_funcs;
else if (HAS_PCH_SPLIT(display))
display->funcs.dpll = &ilk_dpll_funcs;
display->dpll.funcs = &ilk_dpll_funcs;
else if (display->platform.cherryview)
display->funcs.dpll = &chv_dpll_funcs;
display->dpll.funcs = &chv_dpll_funcs;
else if (display->platform.valleyview)
display->funcs.dpll = &vlv_dpll_funcs;
display->dpll.funcs = &vlv_dpll_funcs;
else if (display->platform.g4x)
display->funcs.dpll = &g4x_dpll_funcs;
display->dpll.funcs = &g4x_dpll_funcs;
else if (display->platform.pineview)
display->funcs.dpll = &pnv_dpll_funcs;
display->dpll.funcs = &pnv_dpll_funcs;
else if (DISPLAY_VER(display) != 2)
display->funcs.dpll = &i9xx_dpll_funcs;
display->dpll.funcs = &i9xx_dpll_funcs;
else
display->funcs.dpll = &i8xx_dpll_funcs;
display->dpll.funcs = &i8xx_dpll_funcs;
}
static bool i9xx_has_pps(struct intel_display *display)
@ -1866,24 +1866,24 @@ static void vlv_pllb_recal_opamp(struct intel_display *display,
* PLLB opamp always calibrates to max value of 0x3f, force enable it
* and set it to a reasonable value instead.
*/
tmp = vlv_dpio_read(display->drm, phy, VLV_PLL_DW17(ch));
tmp = vlv_dpio_read(display, phy, VLV_PLL_DW17(ch));
tmp &= 0xffffff00;
tmp |= 0x00000030;
vlv_dpio_write(display->drm, phy, VLV_PLL_DW17(ch), tmp);
vlv_dpio_write(display, phy, VLV_PLL_DW17(ch), tmp);
tmp = vlv_dpio_read(display->drm, phy, VLV_REF_DW11);
tmp = vlv_dpio_read(display, phy, VLV_REF_DW11);
tmp &= 0x00ffffff;
tmp |= 0x8c000000;
vlv_dpio_write(display->drm, phy, VLV_REF_DW11, tmp);
vlv_dpio_write(display, phy, VLV_REF_DW11, tmp);
tmp = vlv_dpio_read(display->drm, phy, VLV_PLL_DW17(ch));
tmp = vlv_dpio_read(display, phy, VLV_PLL_DW17(ch));
tmp &= 0xffffff00;
vlv_dpio_write(display->drm, phy, VLV_PLL_DW17(ch), tmp);
vlv_dpio_write(display, phy, VLV_PLL_DW17(ch), tmp);
tmp = vlv_dpio_read(display->drm, phy, VLV_REF_DW11);
tmp = vlv_dpio_read(display, phy, VLV_REF_DW11);
tmp &= 0x00ffffff;
tmp |= 0xb0000000;
vlv_dpio_write(display->drm, phy, VLV_REF_DW11, tmp);
vlv_dpio_write(display, phy, VLV_REF_DW11, tmp);
}
static void vlv_prepare_pll(const struct intel_crtc_state *crtc_state)
@ -1896,7 +1896,7 @@ static void vlv_prepare_pll(const struct intel_crtc_state *crtc_state)
enum pipe pipe = crtc->pipe;
u32 tmp, coreclk;
vlv_dpio_get(display->drm);
vlv_dpio_get(display);
/* See eDP HDMI DPIO driver vbios notes doc */
@ -1905,15 +1905,15 @@ static void vlv_prepare_pll(const struct intel_crtc_state *crtc_state)
vlv_pllb_recal_opamp(display, phy, ch);
/* Set up Tx target for periodic Rcomp update */
vlv_dpio_write(display->drm, phy, VLV_PCS_DW17_BCAST, 0x0100000f);
vlv_dpio_write(display, phy, VLV_PCS_DW17_BCAST, 0x0100000f);
/* Disable target IRef on PLL */
tmp = vlv_dpio_read(display->drm, phy, VLV_PLL_DW16(ch));
tmp = vlv_dpio_read(display, phy, VLV_PLL_DW16(ch));
tmp &= 0x00ffffff;
vlv_dpio_write(display->drm, phy, VLV_PLL_DW16(ch), tmp);
vlv_dpio_write(display, phy, VLV_PLL_DW16(ch), tmp);
/* Disable fast lock */
vlv_dpio_write(display->drm, phy, VLV_CMN_DW0, 0x610);
vlv_dpio_write(display, phy, VLV_CMN_DW0, 0x610);
/* Set idtafcrecal before PLL is enabled */
tmp = DPIO_M1_DIV(clock->m1) |
@ -1929,42 +1929,42 @@ static void vlv_prepare_pll(const struct intel_crtc_state *crtc_state)
* Note: don't use the DAC post divider as it seems unstable.
*/
tmp |= DPIO_S1_DIV(DPIO_S1_DIV_HDMIDP);
vlv_dpio_write(display->drm, phy, VLV_PLL_DW3(ch), tmp);
vlv_dpio_write(display, phy, VLV_PLL_DW3(ch), tmp);
tmp |= DPIO_ENABLE_CALIBRATION;
vlv_dpio_write(display->drm, phy, VLV_PLL_DW3(ch), tmp);
vlv_dpio_write(display, phy, VLV_PLL_DW3(ch), tmp);
/* Set HBR and RBR LPF coefficients */
if (crtc_state->port_clock == 162000 ||
intel_crtc_has_type(crtc_state, INTEL_OUTPUT_ANALOG) ||
intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
vlv_dpio_write(display->drm, phy, VLV_PLL_DW18(ch), 0x009f0003);
vlv_dpio_write(display, phy, VLV_PLL_DW18(ch), 0x009f0003);
else
vlv_dpio_write(display->drm, phy, VLV_PLL_DW18(ch), 0x00d0000f);
vlv_dpio_write(display, phy, VLV_PLL_DW18(ch), 0x00d0000f);
if (intel_crtc_has_dp_encoder(crtc_state)) {
/* Use SSC source */
if (pipe == PIPE_A)
vlv_dpio_write(display->drm, phy, VLV_PLL_DW5(ch), 0x0df40000);
vlv_dpio_write(display, phy, VLV_PLL_DW5(ch), 0x0df40000);
else
vlv_dpio_write(display->drm, phy, VLV_PLL_DW5(ch), 0x0df70000);
vlv_dpio_write(display, phy, VLV_PLL_DW5(ch), 0x0df70000);
} else { /* HDMI or VGA */
/* Use bend source */
if (pipe == PIPE_A)
vlv_dpio_write(display->drm, phy, VLV_PLL_DW5(ch), 0x0df70000);
vlv_dpio_write(display, phy, VLV_PLL_DW5(ch), 0x0df70000);
else
vlv_dpio_write(display->drm, phy, VLV_PLL_DW5(ch), 0x0df40000);
vlv_dpio_write(display, phy, VLV_PLL_DW5(ch), 0x0df40000);
}
coreclk = vlv_dpio_read(display->drm, phy, VLV_PLL_DW7(ch));
coreclk = vlv_dpio_read(display, phy, VLV_PLL_DW7(ch));
coreclk = (coreclk & 0x0000ff00) | 0x01c00000;
if (intel_crtc_has_dp_encoder(crtc_state))
coreclk |= 0x01000000;
vlv_dpio_write(display->drm, phy, VLV_PLL_DW7(ch), coreclk);
vlv_dpio_write(display, phy, VLV_PLL_DW7(ch), coreclk);
vlv_dpio_write(display->drm, phy, VLV_PLL_DW19(ch), 0x87871000);
vlv_dpio_write(display, phy, VLV_PLL_DW19(ch), 0x87871000);
vlv_dpio_put(display->drm);
vlv_dpio_put(display);
}
static void _vlv_enable_pll(const struct intel_crtc_state *crtc_state)
@ -2019,44 +2019,44 @@ static void chv_prepare_pll(const struct intel_crtc_state *crtc_state)
m2_frac = clock->m2 & 0x3fffff;
vlv_dpio_get(display->drm);
vlv_dpio_get(display);
/* p1 and p2 divider */
vlv_dpio_write(display->drm, phy, CHV_CMN_DW13(ch),
vlv_dpio_write(display, phy, CHV_CMN_DW13(ch),
DPIO_CHV_S1_DIV(5) |
DPIO_CHV_P1_DIV(clock->p1) |
DPIO_CHV_P2_DIV(clock->p2) |
DPIO_CHV_K_DIV(1));
/* Feedback post-divider - m2 */
vlv_dpio_write(display->drm, phy, CHV_PLL_DW0(ch),
vlv_dpio_write(display, phy, CHV_PLL_DW0(ch),
DPIO_CHV_M2_DIV(clock->m2 >> 22));
/* Feedback refclk divider - n and m1 */
vlv_dpio_write(display->drm, phy, CHV_PLL_DW1(ch),
vlv_dpio_write(display, phy, CHV_PLL_DW1(ch),
DPIO_CHV_M1_DIV(DPIO_CHV_M1_DIV_BY_2) |
DPIO_CHV_N_DIV(1));
/* M2 fraction division */
vlv_dpio_write(display->drm, phy, CHV_PLL_DW2(ch),
vlv_dpio_write(display, phy, CHV_PLL_DW2(ch),
DPIO_CHV_M2_FRAC_DIV(m2_frac));
/* M2 fraction division enable */
tmp = vlv_dpio_read(display->drm, phy, CHV_PLL_DW3(ch));
tmp = vlv_dpio_read(display, phy, CHV_PLL_DW3(ch));
tmp &= ~(DPIO_CHV_FEEDFWD_GAIN_MASK | DPIO_CHV_FRAC_DIV_EN);
tmp |= DPIO_CHV_FEEDFWD_GAIN(2);
if (m2_frac)
tmp |= DPIO_CHV_FRAC_DIV_EN;
vlv_dpio_write(display->drm, phy, CHV_PLL_DW3(ch), tmp);
vlv_dpio_write(display, phy, CHV_PLL_DW3(ch), tmp);
/* Program digital lock detect threshold */
tmp = vlv_dpio_read(display->drm, phy, CHV_PLL_DW9(ch));
tmp = vlv_dpio_read(display, phy, CHV_PLL_DW9(ch));
tmp &= ~(DPIO_CHV_INT_LOCK_THRESHOLD_MASK |
DPIO_CHV_INT_LOCK_THRESHOLD_SEL_COARSE);
tmp |= DPIO_CHV_INT_LOCK_THRESHOLD(0x5);
if (!m2_frac)
tmp |= DPIO_CHV_INT_LOCK_THRESHOLD_SEL_COARSE;
vlv_dpio_write(display->drm, phy, CHV_PLL_DW9(ch), tmp);
vlv_dpio_write(display, phy, CHV_PLL_DW9(ch), tmp);
/* Loop filter */
if (clock->vco == 5400000) {
@ -2081,19 +2081,19 @@ static void chv_prepare_pll(const struct intel_crtc_state *crtc_state)
DPIO_CHV_GAIN_CTRL(0x3);
tribuf_calcntr = 0;
}
vlv_dpio_write(display->drm, phy, CHV_PLL_DW6(ch), loopfilter);
vlv_dpio_write(display, phy, CHV_PLL_DW6(ch), loopfilter);
tmp = vlv_dpio_read(display->drm, phy, CHV_PLL_DW8(ch));
tmp = vlv_dpio_read(display, phy, CHV_PLL_DW8(ch));
tmp &= ~DPIO_CHV_TDC_TARGET_CNT_MASK;
tmp |= DPIO_CHV_TDC_TARGET_CNT(tribuf_calcntr);
vlv_dpio_write(display->drm, phy, CHV_PLL_DW8(ch), tmp);
vlv_dpio_write(display, phy, CHV_PLL_DW8(ch), tmp);
/* AFC Recal */
vlv_dpio_write(display->drm, phy, CHV_CMN_DW14(ch),
vlv_dpio_read(display->drm, phy, CHV_CMN_DW14(ch)) |
vlv_dpio_write(display, phy, CHV_CMN_DW14(ch),
vlv_dpio_read(display, phy, CHV_CMN_DW14(ch)) |
DPIO_AFC_RECAL);
vlv_dpio_put(display->drm);
vlv_dpio_put(display);
}
static void _chv_enable_pll(const struct intel_crtc_state *crtc_state)
@ -2106,14 +2106,14 @@ static void _chv_enable_pll(const struct intel_crtc_state *crtc_state)
enum pipe pipe = crtc->pipe;
u32 tmp;
vlv_dpio_get(display->drm);
vlv_dpio_get(display);
/* Enable back the 10bit clock to display controller */
tmp = vlv_dpio_read(display->drm, phy, CHV_CMN_DW14(ch));
tmp = vlv_dpio_read(display, phy, CHV_CMN_DW14(ch));
tmp |= DPIO_DCLKP_EN;
vlv_dpio_write(display->drm, phy, CHV_CMN_DW14(ch), tmp);
vlv_dpio_write(display, phy, CHV_CMN_DW14(ch), tmp);
vlv_dpio_put(display->drm);
vlv_dpio_put(display);
/*
* Need to wait > 100ns between dclkp clock enable bit and PLL enable.
@ -2247,14 +2247,14 @@ void chv_disable_pll(struct intel_display *display, enum pipe pipe)
intel_de_write(display, DPLL(display, pipe), val);
intel_de_posting_read(display, DPLL(display, pipe));
vlv_dpio_get(display->drm);
vlv_dpio_get(display);
/* Disable 10bit clock to display controller */
val = vlv_dpio_read(display->drm, phy, CHV_CMN_DW14(ch));
val = vlv_dpio_read(display, phy, CHV_CMN_DW14(ch));
val &= ~DPIO_DCLKP_EN;
vlv_dpio_write(display->drm, phy, CHV_CMN_DW14(ch), val);
vlv_dpio_write(display, phy, CHV_CMN_DW14(ch), val);
vlv_dpio_put(display->drm);
vlv_dpio_put(display);
}
void i9xx_disable_pll(const struct intel_crtc_state *crtc_state)

View File

@ -9,14 +9,14 @@
#include <drm/drm_print.h>
#include <drm/intel/intel_pcode_regs.h>
#include "intel_de.h"
#include "intel_display_core.h"
#include "intel_display_utils.h"
#include "intel_display_regs.h"
#include "intel_dram.h"
#include "intel_mchbar_regs.h"
#include "intel_mchbar.h"
#include "intel_parent.h"
#include "intel_uncore.h"
#include "vlv_iosf_sb.h"
#include "vlv_sideband.h"
struct dram_dimm_info {
u16 size;
@ -58,18 +58,15 @@ const char *intel_dram_type_str(enum intel_dram_type type)
static enum intel_dram_type pnv_dram_type(struct intel_display *display)
{
struct intel_uncore *uncore = to_intel_uncore(display->drm);
return intel_uncore_read(uncore, CSHRDDR3CTL) & CSHRDDR3CTL_DDR3 ?
return intel_mchbar_read(display, CSHRDDR3CTL) & CSHRDDR3CTL_DDR3 ?
INTEL_DRAM_DDR3 : INTEL_DRAM_DDR2;
}
static unsigned int pnv_mem_freq(struct intel_display *display)
{
struct intel_uncore *uncore = to_intel_uncore(display->drm);
u32 tmp;
tmp = intel_uncore_read(uncore, CLKCFG);
tmp = intel_mchbar_read(display, CLKCFG);
switch (tmp & CLKCFG_MEM_MASK) {
case CLKCFG_MEM_533:
@ -85,10 +82,9 @@ static unsigned int pnv_mem_freq(struct intel_display *display)
static unsigned int ilk_mem_freq(struct intel_display *display)
{
struct intel_uncore *uncore = to_intel_uncore(display->drm);
u16 ddrpll;
ddrpll = intel_uncore_read16(uncore, DDRMPLL1);
ddrpll = intel_mchbar_read16(display, DDRMPLL1);
switch (ddrpll & 0xff) {
case 0xc:
return 800000;
@ -109,9 +105,9 @@ static unsigned int chv_mem_freq(struct intel_display *display)
{
u32 val;
vlv_iosf_sb_get(display->drm, BIT(VLV_IOSF_SB_CCK));
val = vlv_iosf_sb_read(display->drm, VLV_IOSF_SB_CCK, CCK_FUSE_REG);
vlv_iosf_sb_put(display->drm, BIT(VLV_IOSF_SB_CCK));
vlv_cck_get(display);
val = vlv_cck_read(display, CCK_FUSE_REG);
vlv_cck_put(display);
switch ((val >> 2) & 0x7) {
case 3:
@ -125,9 +121,9 @@ static unsigned int vlv_mem_freq(struct intel_display *display)
{
u32 val;
vlv_iosf_sb_get(display->drm, BIT(VLV_IOSF_SB_PUNIT));
val = vlv_iosf_sb_read(display->drm, VLV_IOSF_SB_PUNIT, PUNIT_REG_GPU_FREQ_STS);
vlv_iosf_sb_put(display->drm, BIT(VLV_IOSF_SB_PUNIT));
vlv_punit_get(display);
val = vlv_punit_read(display, PUNIT_REG_GPU_FREQ_STS);
vlv_punit_put(display);
switch ((val >> 6) & 3) {
case 0:
@ -158,7 +154,6 @@ unsigned int intel_mem_freq(struct intel_display *display)
static unsigned int i9xx_fsb_freq(struct intel_display *display)
{
struct intel_uncore *uncore = to_intel_uncore(display->drm);
u32 fsb;
/*
@ -169,7 +164,7 @@ static unsigned int i9xx_fsb_freq(struct intel_display *display)
* don't know which registers have that information,
* and all the relevant docs have gone to bit heaven :(
*/
fsb = intel_uncore_read(uncore, CLKCFG) & CLKCFG_FSB_MASK;
fsb = intel_mchbar_read(display, CLKCFG) & CLKCFG_FSB_MASK;
if (display->platform.pineview || display->platform.mobile) {
switch (fsb) {
@ -214,10 +209,9 @@ static unsigned int i9xx_fsb_freq(struct intel_display *display)
static unsigned int ilk_fsb_freq(struct intel_display *display)
{
struct intel_uncore *uncore = to_intel_uncore(display->drm);
u16 fsb;
fsb = intel_uncore_read16(uncore, CSIPLL0) & 0x3ff;
fsb = intel_mchbar_read16(display, CSIPLL0) & 0x3ff;
switch (fsb) {
case 0x00c:
@ -484,7 +478,6 @@ intel_is_dram_symmetric(const struct dram_channel_info *ch0,
static int
skl_dram_get_channels_info(struct intel_display *display, struct dram_info *dram_info)
{
struct intel_uncore *uncore = to_intel_uncore(display->drm);
struct dram_channel_info ch0 = {}, ch1 = {};
u32 val;
int ret;
@ -492,12 +485,12 @@ skl_dram_get_channels_info(struct intel_display *display, struct dram_info *dram
/* Assume 16Gb+ DIMMs are present until proven otherwise */
dram_info->has_16gb_dimms = true;
val = intel_uncore_read(uncore, SKL_MAD_DIMM_CH0_0_0_0_MCHBAR_MCMAIN);
val = intel_mchbar_read(display, SKL_MAD_DIMM_CH0_0_0_0_MCHBAR_MCMAIN);
ret = skl_dram_get_channel_info(display, &ch0, 0, val);
if (ret == 0)
dram_info->num_channels++;
val = intel_uncore_read(uncore, SKL_MAD_DIMM_CH1_0_0_0_MCHBAR_MCMAIN);
val = intel_mchbar_read(display, SKL_MAD_DIMM_CH1_0_0_0_MCHBAR_MCMAIN);
ret = skl_dram_get_channel_info(display, &ch1, 1, val);
if (ret == 0)
dram_info->num_channels++;
@ -528,10 +521,9 @@ skl_dram_get_channels_info(struct intel_display *display, struct dram_info *dram
static enum intel_dram_type
skl_get_dram_type(struct intel_display *display)
{
struct intel_uncore *uncore = to_intel_uncore(display->drm);
u32 val;
val = intel_uncore_read(uncore, SKL_MAD_INTER_CHANNEL_0_0_0_MCHBAR_MCMAIN);
val = intel_mchbar_read(display, SKL_MAD_INTER_CHANNEL_0_0_0_MCHBAR_MCMAIN);
switch (val & SKL_DRAM_DDR_TYPE_MASK) {
case SKL_DRAM_DDR_TYPE_DDR3:
@ -642,7 +634,6 @@ static void bxt_get_dimm_info(struct dram_dimm_info *dimm, u32 val)
static int bxt_get_dram_info(struct intel_display *display, struct dram_info *dram_info)
{
struct intel_uncore *uncore = to_intel_uncore(display->drm);
u32 val;
u8 valid_ranks = 0;
int i;
@ -654,7 +645,7 @@ static int bxt_get_dram_info(struct intel_display *display, struct dram_info *dr
struct dram_dimm_info dimm;
enum intel_dram_type type;
val = intel_uncore_read(uncore, BXT_D_CR_DRP0_DUNIT(i));
val = intel_mchbar_read(display, BXT_D_CR_DRP0_DUNIT(i));
if (val == 0xFFFFFFFF)
continue;
@ -767,8 +758,7 @@ static int gen12_get_dram_info(struct intel_display *display, struct dram_info *
static int xelpdp_get_dram_info(struct intel_display *display, struct dram_info *dram_info)
{
struct intel_uncore *uncore = to_intel_uncore(display->drm);
u32 val = intel_uncore_read(uncore, MTL_MEM_SS_INFO_GLOBAL);
u32 val = intel_de_read(display, MTL_MEM_SS_INFO_GLOBAL);
switch (REG_FIELD_GET(MTL_DDR_TYPE_MASK, val)) {
case 0:

View File

@ -521,6 +521,11 @@ bool intel_fb_needs_64k_phys(u64 modifier)
INTEL_PLANE_CAP_NEED64K_PHYS);
}
bool intel_fb_needs_cpu_access(const struct drm_framebuffer *fb)
{
return intel_fb_rc_ccs_cc_plane(fb) >= 0;
}
/**
* intel_fb_is_tile4_modifier: Check if a modifier is a tile4 modifier type
* @modifier: Modifier to check
@ -876,15 +881,6 @@ static void intel_tile_block_dims(const struct drm_framebuffer *fb, int color_pl
*tile_height = 1;
}
unsigned int intel_tile_row_size(const struct drm_framebuffer *fb, int color_plane)
{
unsigned int tile_width, tile_height;
intel_tile_dims(fb, color_plane, &tile_width, &tile_height);
return fb->pitches[color_plane] * tile_height;
}
unsigned int
intel_fb_align_height(const struct drm_framebuffer *fb,
int color_plane, unsigned int height)
@ -1261,6 +1257,10 @@ static bool intel_plane_can_remap(const struct intel_plane_state *plane_state)
if (intel_fb_is_ccs_modifier(fb->modifier))
return false;
/* TODO implement remapping with DPT */
if (intel_fb_uses_dpt(fb))
return false;
/* Linear needs a page aligned stride for remapping */
if (fb->modifier == DRM_FORMAT_MOD_LINEAR) {
unsigned int alignment = intel_tile_size(display) - 1;
@ -1274,7 +1274,7 @@ static bool intel_plane_can_remap(const struct intel_plane_state *plane_state)
return true;
}
bool intel_fb_needs_pot_stride_remap(const struct intel_framebuffer *fb)
static bool intel_fb_needs_pot_stride_remap(const struct intel_framebuffer *fb)
{
struct intel_display *display = to_intel_display(fb->base.dev);
@ -1287,9 +1287,9 @@ bool intel_plane_uses_fence(const struct intel_plane_state *plane_state)
struct intel_display *display = to_intel_display(plane_state);
struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
return DISPLAY_VER(display) < 4 ||
return intel_plane_needs_fence(display) ||
(plane->fbc && !plane_state->no_fbc_reason &&
plane_state->view.gtt.type == I915_GTT_VIEW_NORMAL);
i915_gtt_view_is_normal(&plane_state->view.gtt));
}
static int intel_fb_pitch(const struct intel_framebuffer *fb, int color_plane, unsigned int rotation)
@ -1511,7 +1511,7 @@ static u32 calc_plane_remap_info(const struct intel_framebuffer *fb, int color_p
plane_view_height_tiles(fb, color_plane, dims, y));
}
if (view->gtt.type == I915_GTT_VIEW_ROTATED) {
if (i915_gtt_view_is_rotated(&view->gtt)) {
drm_WARN_ON(display->drm, remap_info->linear);
check_array_bounds(display, view->gtt.rotated.plane, color_plane);
@ -1536,7 +1536,7 @@ static u32 calc_plane_remap_info(const struct intel_framebuffer *fb, int color_p
/* rotate the tile dimensions to match the GTT view */
swap(tile_width, tile_height);
} else {
drm_WARN_ON(display->drm, view->gtt.type != I915_GTT_VIEW_REMAPPED);
drm_WARN_ON(display->drm, !i915_gtt_view_is_remapped(&view->gtt));
check_array_bounds(display, view->gtt.remapped.plane, color_plane);
@ -1632,13 +1632,14 @@ calc_plane_normal_size(const struct intel_framebuffer *fb, int color_plane,
static void intel_fb_view_init(struct intel_display *display,
struct intel_fb_view *view,
enum i915_gtt_view_type view_type)
enum i915_gtt_view_type view_type,
const struct intel_framebuffer *fb)
{
memset(view, 0, sizeof(*view));
view->gtt.type = view_type;
if (view_type == I915_GTT_VIEW_REMAPPED &&
(display->platform.alderlake_p || DISPLAY_VER(display) >= 14))
if (i915_gtt_view_is_remapped(&view->gtt) &&
intel_fb_needs_pot_stride_remap(fb))
view->gtt.remapped.plane_alignment = SZ_2M / PAGE_SIZE;
}
@ -1704,16 +1705,19 @@ int intel_fill_fb_info(struct intel_display *display, struct intel_framebuffer *
int i, num_planes = fb->base.format->num_planes;
unsigned int tile_size = intel_tile_size(display);
intel_fb_view_init(display, &fb->normal_view, I915_GTT_VIEW_NORMAL);
intel_fb_view_init(display, &fb->normal_view,
I915_GTT_VIEW_NORMAL, fb);
drm_WARN_ON(display->drm,
intel_fb_supports_90_270_rotation(fb) &&
intel_fb_needs_pot_stride_remap(fb));
if (intel_fb_supports_90_270_rotation(fb))
intel_fb_view_init(display, &fb->rotated_view, I915_GTT_VIEW_ROTATED);
intel_fb_view_init(display, &fb->rotated_view,
I915_GTT_VIEW_ROTATED, fb);
if (intel_fb_needs_pot_stride_remap(fb))
intel_fb_view_init(display, &fb->remapped_view, I915_GTT_VIEW_REMAPPED);
intel_fb_view_init(display, &fb->remapped_view,
I915_GTT_VIEW_REMAPPED, fb);
for (i = 0; i < num_planes; i++) {
struct fb_plane_view_dims view_dims;
@ -1840,8 +1844,9 @@ static void intel_plane_remap_gtt(struct intel_plane_state *plane_state)
u32 gtt_offset = 0;
intel_fb_view_init(display, &plane_state->view,
drm_rotation_90_or_270(rotation) ? I915_GTT_VIEW_ROTATED :
I915_GTT_VIEW_REMAPPED);
drm_rotation_90_or_270(rotation) ?
I915_GTT_VIEW_ROTATED : I915_GTT_VIEW_REMAPPED,
intel_fb);
src_x = plane_state->uapi.src.x1 >> 16;
src_y = plane_state->uapi.src.y1 >> 16;

View File

@ -38,6 +38,7 @@ bool intel_fb_is_rc_ccs_cc_modifier(u64 modifier);
bool intel_fb_is_mc_ccs_modifier(u64 modifier);
bool intel_fb_needs_64k_phys(u64 modifier);
bool intel_fb_is_tile4_modifier(u64 modifier);
bool intel_fb_needs_cpu_access(const struct drm_framebuffer *fb);
bool intel_fb_is_ccs_aux_plane(const struct drm_framebuffer *fb, int color_plane);
int intel_fb_rc_ccs_cc_plane(const struct drm_framebuffer *fb);
@ -62,7 +63,6 @@ int skl_main_to_aux_plane(const struct drm_framebuffer *fb, int main_plane);
unsigned int intel_tile_size(struct intel_display *display);
unsigned int intel_tile_width_bytes(const struct drm_framebuffer *fb, int color_plane);
unsigned int intel_tile_height(const struct drm_framebuffer *fb, int color_plane);
unsigned int intel_tile_row_size(const struct drm_framebuffer *fb, int color_plane);
unsigned int intel_fb_align_height(const struct drm_framebuffer *fb,
int color_plane, unsigned int height);
@ -78,7 +78,6 @@ u32 intel_plane_compute_aligned_offset(int *x, int *y,
const struct intel_plane_state *plane_state,
int color_plane);
bool intel_fb_needs_pot_stride_remap(const struct intel_framebuffer *fb);
bool intel_plane_uses_fence(const struct intel_plane_state *plane_state);
bool intel_fb_supports_90_270_rotation(const struct intel_framebuffer *fb);

View File

@ -8,22 +8,29 @@
#include <linux/types.h>
struct drm_framebuffer;
struct drm_gem_object;
struct i915_vma;
struct intel_plane_state;
struct i915_gtt_view;
struct iosys_map;
struct i915_vma *
intel_fb_pin_to_ggtt(const struct drm_framebuffer *fb,
const struct i915_gtt_view *view,
unsigned int alignment,
unsigned int phys_alignment,
unsigned int vtd_guard,
bool uses_fence,
unsigned long *out_flags);
struct intel_fb_pin_params {
const struct i915_gtt_view *view;
unsigned int alignment;
unsigned int phys_alignment;
unsigned int vtd_guard;
bool needs_cpu_lmem_access;
bool needs_low_address;
bool needs_physical;
bool needs_fence;
};
void intel_fb_unpin_vma(struct i915_vma *vma, unsigned long flags);
struct i915_vma *
intel_fb_pin_to_ggtt(struct drm_gem_object *obj,
const struct intel_fb_pin_params *pin_params,
int *out_fence_id);
void intel_fb_unpin_vma(struct i915_vma *vma, int fence_id);
int intel_plane_pin_fb(struct intel_plane_state *new_plane_state,
const struct intel_plane_state *old_plane_state);

View File

@ -1458,13 +1458,10 @@ static void intel_fbc_update_state(struct intel_atomic_state *state,
fbc_state->fence_y_offset = intel_plane_fence_y_offset(plane_state);
drm_WARN_ON(display->drm, plane_state->flags & PLANE_HAS_FENCE &&
drm_WARN_ON(display->drm, plane_state->fence_id >= 0 &&
!intel_fbc_has_fences(display));
if (plane_state->flags & PLANE_HAS_FENCE)
fbc_state->fence_id = intel_parent_vma_fence_id(display, plane_state->ggtt_vma);
else
fbc_state->fence_id = -1;
fbc_state->fence_id = plane_state->fence_id;
fbc_state->cfb_stride = intel_fbc_cfb_stride(plane_state);
fbc_state->cfb_size = intel_fbc_cfb_size(plane_state);
@ -1487,9 +1484,7 @@ static bool intel_fbc_is_fence_ok(const struct intel_plane_state *plane_state)
* so have no fence associated with it) due to aperture constraints
* at the time of pinning.
*/
return DISPLAY_VER(display) >= 9 ||
(plane_state->flags & PLANE_HAS_FENCE &&
intel_parent_vma_fence_id(display, plane_state->ggtt_vma) != -1);
return DISPLAY_VER(display) >= 9 || plane_state->fence_id >= 0;
}
static bool intel_fbc_is_cfb_ok(const struct intel_plane_state *plane_state)

View File

@ -54,13 +54,12 @@
#include "intel_fb.h"
#include "intel_fb_pin.h"
#include "intel_fbdev.h"
#include "intel_fbdev_fb.h"
#include "intel_frontbuffer.h"
#include "intel_plane.h"
struct intel_fbdev {
struct intel_framebuffer *fb;
struct i915_vma *vma;
unsigned long vma_flags;
};
static struct intel_fbdev *to_intel_fbdev(struct drm_fb_helper *fb_helper)
@ -141,7 +140,7 @@ static void intel_fbdev_fb_destroy(struct fb_info *info)
* the info->screen_base mmaping. Leaking the VMA is simpler than
* trying to rectify all the possible error paths leading here.
*/
intel_fb_unpin_vma(ifbdev->vma, ifbdev->vma_flags);
intel_fb_unpin_vma(ifbdev->vma, -1);
drm_framebuffer_remove(fb_helper->fb);
drm_client_release(&fb_helper->client);
@ -204,7 +203,8 @@ static const struct drm_fb_helper_funcs intel_fb_helper_funcs = {
.fb_set_suspend = intelfb_set_suspend,
};
static void intel_fbdev_fill_mode_cmd(struct drm_fb_helper_surface_size *sizes,
static void intel_fbdev_fill_mode_cmd(struct intel_display *display,
struct drm_fb_helper_surface_size *sizes,
struct drm_mode_fb_cmd2 *mode_cmd)
{
/* we don't do packed 24bpp */
@ -215,7 +215,7 @@ static void intel_fbdev_fill_mode_cmd(struct drm_fb_helper_surface_size *sizes,
mode_cmd->width = sizes->surface_width;
mode_cmd->height = sizes->surface_height;
mode_cmd->pitches[0] = intel_fbdev_fb_pitch_align(mode_cmd->width * DIV_ROUND_UP(sizes->surface_bpp, 8));
mode_cmd->pitches[0] = intel_bo_fbdev_pitch_align(display, mode_cmd->width * DIV_ROUND_UP(sizes->surface_bpp, 8));
mode_cmd->pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
sizes->surface_depth);
mode_cmd->modifier[0] = DRM_FORMAT_MOD_LINEAR;
@ -230,12 +230,12 @@ __intel_fbdev_fb_alloc(struct intel_display *display,
struct drm_gem_object *obj;
int size;
intel_fbdev_fill_mode_cmd(sizes, &mode_cmd);
intel_fbdev_fill_mode_cmd(display, sizes, &mode_cmd);
size = mode_cmd.pitches[0] * mode_cmd.height;
size = PAGE_ALIGN(size);
obj = intel_fbdev_fb_bo_create(display->drm, size);
obj = intel_bo_fbdev_create(display, size);
if (IS_ERR(obj)) {
fb = ERR_CAST(obj);
goto err;
@ -247,7 +247,7 @@ __intel_fbdev_fb_alloc(struct intel_display *display,
mode_cmd.modifier[0]),
&mode_cmd);
if (IS_ERR(fb)) {
intel_fbdev_fb_bo_destroy(obj);
intel_bo_fbdev_destroy(obj);
goto err;
}
@ -265,11 +265,11 @@ int intel_fbdev_driver_fbdev_probe(struct drm_fb_helper *helper,
{
struct intel_display *display = to_intel_display(helper->dev);
struct intel_fbdev *ifbdev = to_intel_fbdev(helper);
struct intel_fb_pin_params pin_params = {};
struct intel_framebuffer *fb = ifbdev->fb;
struct fb_info *info = helper->info;
struct ref_tracker *wakeref;
struct i915_vma *vma;
unsigned long flags = 0;
bool prealloc = false;
struct drm_gem_object *obj;
int ret;
@ -306,15 +306,20 @@ int intel_fbdev_driver_fbdev_probe(struct drm_fb_helper *helper,
sizes->fb_height = fb->base.height;
}
obj = intel_fb_bo(&fb->base);
/* Pin the GGTT vma for our access via info->screen_base.
* This also validates that any existing fb inherited from the
* BIOS is suitable for own access.
*/
vma = intel_fb_pin_to_ggtt(&fb->base, &fb->normal_view.gtt,
fb->min_alignment, 0,
intel_fb_view_vtd_guard(&fb->base, &fb->normal_view,
DRM_MODE_ROTATE_0),
false, &flags);
pin_params.view = &fb->normal_view.gtt;
pin_params.alignment = fb->min_alignment;
pin_params.vtd_guard = intel_fb_view_vtd_guard(&fb->base,
&fb->normal_view,
DRM_MODE_ROTATE_0);
pin_params.needs_low_address = intel_plane_needs_low_address(display);
vma = intel_fb_pin_to_ggtt(obj, &pin_params, NULL);
if (IS_ERR(vma)) {
ret = PTR_ERR(vma);
goto out_unlock;
@ -325,9 +330,7 @@ int intel_fbdev_driver_fbdev_probe(struct drm_fb_helper *helper,
info->fbops = &intelfb_ops;
obj = intel_fb_bo(&fb->base);
ret = intel_fbdev_fb_fill_info(display->drm, info, obj, vma);
ret = intel_bo_fbdev_fill_info(obj, info, vma);
if (ret)
goto out_unpin;
@ -345,14 +348,13 @@ int intel_fbdev_driver_fbdev_probe(struct drm_fb_helper *helper,
drm_dbg_kms(display->drm, "allocated %dx%d fb\n", fb->base.width, fb->base.height);
ifbdev->fb = fb;
ifbdev->vma = vma;
ifbdev->vma_flags = flags;
intel_display_rpm_put(display, wakeref);
return 0;
out_unpin:
intel_fb_unpin_vma(vma, flags);
intel_fb_unpin_vma(vma, -1);
out_unlock:
intel_display_rpm_put(display, wakeref);

View File

@ -1,118 +0,0 @@
/* SPDX-License-Identifier: MIT */
/*
* Copyright © 2023 Intel Corporation
*/
#include <linux/fb.h>
#include <drm/drm_print.h>
#include "gem/i915_gem_lmem.h"
#include "i915_drv.h"
#include "intel_fbdev_fb.h"
u32 intel_fbdev_fb_pitch_align(u32 stride)
{
return ALIGN(stride, 64);
}
bool intel_fbdev_fb_prefer_stolen(struct drm_device *drm, unsigned int size)
{
struct drm_i915_private *i915 = to_i915(drm);
/* Skip stolen on MTL as Wa_22018444074 mitigation. */
if (IS_METEORLAKE(i915))
return false;
/*
* If the FB is too big, just don't use it since fbdev is not very
* important and we should probably use that space with FBC or other
* features.
*/
return i915->dsm.usable_size >= size * 2;
}
struct drm_gem_object *intel_fbdev_fb_bo_create(struct drm_device *drm, int size)
{
struct drm_i915_private *i915 = to_i915(drm);
struct drm_i915_gem_object *obj;
obj = ERR_PTR(-ENODEV);
if (HAS_LMEM(i915)) {
obj = i915_gem_object_create_lmem(i915, size,
I915_BO_ALLOC_CONTIGUOUS |
I915_BO_ALLOC_USER);
} else {
if (intel_fbdev_fb_prefer_stolen(drm, size))
obj = i915_gem_object_create_stolen(i915, size);
else
drm_info(drm, "Allocating fbdev: Stolen memory not preferred.\n");
if (IS_ERR(obj))
obj = i915_gem_object_create_shmem(i915, size);
}
if (IS_ERR(obj)) {
drm_err(drm, "failed to allocate framebuffer (%pe)\n", obj);
return ERR_PTR(-ENOMEM);
}
return &obj->base;
}
void intel_fbdev_fb_bo_destroy(struct drm_gem_object *obj)
{
drm_gem_object_put(obj);
}
int intel_fbdev_fb_fill_info(struct drm_device *drm, struct fb_info *info,
struct drm_gem_object *_obj, struct i915_vma *vma)
{
struct drm_i915_private *i915 = to_i915(drm);
struct drm_i915_gem_object *obj = to_intel_bo(_obj);
struct i915_gem_ww_ctx ww;
void __iomem *vaddr;
int ret;
if (i915_gem_object_is_lmem(obj)) {
struct intel_memory_region *mem = obj->mm.region;
/* Use fbdev's framebuffer from lmem for discrete */
info->fix.smem_start =
(unsigned long)(mem->io.start +
i915_gem_object_get_dma_address(obj, 0) -
mem->region.start);
info->fix.smem_len = obj->base.size;
} else {
struct i915_ggtt *ggtt = to_gt(i915)->ggtt;
/* Our framebuffer is the entirety of fbdev's system memory */
info->fix.smem_start =
(unsigned long)(ggtt->gmadr.start + i915_ggtt_offset(vma));
info->fix.smem_len = vma->size;
}
for_i915_gem_ww(&ww, ret, false) {
ret = i915_gem_object_lock(vma->obj, &ww);
if (ret)
continue;
vaddr = i915_vma_pin_iomap(vma);
if (IS_ERR(vaddr)) {
drm_err(drm,
"Failed to remap framebuffer into virtual memory (%pe)\n", vaddr);
ret = PTR_ERR(vaddr);
continue;
}
}
if (ret)
return ret;
info->screen_base = vaddr;
info->screen_size = intel_bo_to_drm_bo(obj)->size;
return 0;
}

View File

@ -1,24 +0,0 @@
/* SPDX-License-Identifier: MIT */
/*
* Copyright © 2023 Intel Corporation
*/
#ifndef __INTEL_FBDEV_FB_H__
#define __INTEL_FBDEV_FB_H__
#include <linux/types.h>
struct drm_device;
struct drm_gem_object;
struct drm_mode_fb_cmd2;
struct fb_info;
struct i915_vma;
u32 intel_fbdev_fb_pitch_align(u32 stride);
struct drm_gem_object *intel_fbdev_fb_bo_create(struct drm_device *drm, int size);
void intel_fbdev_fb_bo_destroy(struct drm_gem_object *obj);
int intel_fbdev_fb_fill_info(struct drm_device *drm, struct fb_info *info,
struct drm_gem_object *obj, struct i915_vma *vma);
bool intel_fbdev_fb_prefer_stolen(struct drm_device *drm, unsigned int size);
#endif

View File

@ -11,6 +11,7 @@
#include "intel_atomic.h"
#include "intel_crtc.h"
#include "intel_ddi.h"
#include "intel_ddi_buf_trans.h"
#include "intel_de.h"
#include "intel_display_regs.h"
#include "intel_display_types.h"
@ -122,7 +123,7 @@ void intel_fdi_link_train(struct intel_crtc *crtc,
{
struct intel_display *display = to_intel_display(crtc);
display->funcs.fdi->fdi_link_train(crtc, crtc_state);
display->fdi.funcs->fdi_link_train(crtc, crtc_state);
}
/**
@ -852,7 +853,7 @@ void hsw_fdi_link_train(struct intel_encoder *encoder,
u32 temp, i, rx_ctl_val;
int n_entries;
encoder->get_buf_trans(encoder, crtc_state, &n_entries);
intel_ddi_buf_trans_get(encoder, crtc_state, &n_entries);
hsw_prepare_dp_ddi_buffers(encoder, crtc_state);
@ -1108,11 +1109,11 @@ void
intel_fdi_init_hook(struct intel_display *display)
{
if (display->platform.ironlake) {
display->funcs.fdi = &ilk_funcs;
display->fdi.funcs = &ilk_funcs;
} else if (display->platform.sandybridge) {
display->funcs.fdi = &gen6_funcs;
display->fdi.funcs = &gen6_funcs;
} else if (display->platform.ivybridge) {
/* FIXME: detect B0+ stepping and use auto training */
display->funcs.fdi = &ivb_funcs;
display->fdi.funcs = &ivb_funcs;
}
}

View File

@ -72,6 +72,7 @@ intel_hdcp_adjust_hdcp_line_rekeying(struct intel_encoder *encoder,
static int intel_conn_to_vcpi(struct intel_atomic_state *state,
struct intel_connector *connector)
{
struct intel_display *display = to_intel_display(state);
struct drm_dp_mst_topology_mgr *mgr;
struct drm_dp_mst_atomic_payload *payload;
struct drm_dp_mst_topology_state *mst_state;
@ -79,13 +80,19 @@ static int intel_conn_to_vcpi(struct intel_atomic_state *state,
/* For HDMI this is forced to be 0x0. For DP SST also this is 0x0. */
if (!connector->mst.port)
return 0;
mgr = connector->mst.port->mgr;
drm_modeset_lock(&mgr->base.lock, state->base.acquire_ctx);
mst_state = to_drm_dp_mst_topology_state(mgr->base.state);
payload = drm_atomic_get_mst_payload_state(mst_state, connector->mst.port);
if (drm_WARN_ON(mgr->dev, !payload))
mgr = connector->mst.port->mgr;
mst_state = drm_atomic_get_new_mst_topology_state(&state->base, mgr);
if (!mst_state) {
drm_dbg_kms(display->drm, "MST topology still not created\n");
return 0;
}
payload = drm_atomic_get_mst_payload_state(mst_state, connector->mst.port);
if (!payload) {
drm_dbg_kms(display->drm, "MST Payload not present\n");
return 0;
}
return payload->vcpi;
}

View File

@ -2021,6 +2021,51 @@ intel_hdmi_mode_clock_valid(struct drm_connector *_connector, int clock,
return status;
}
static enum drm_mode_status
intel_hdmi_sink_format_valid(struct intel_connector *connector,
const struct drm_display_mode *mode,
bool has_hdmi_sink,
enum intel_output_format sink_format)
{
const struct drm_display_info *info = &connector->base.display_info;
switch (sink_format) {
case INTEL_OUTPUT_FORMAT_YCBCR420:
if (!has_hdmi_sink ||
!connector->base.ycbcr_420_allowed ||
!drm_mode_is_420(info, mode))
return MODE_NO_420;
return MODE_OK;
case INTEL_OUTPUT_FORMAT_RGB:
return MODE_OK;
default:
MISSING_CASE(sink_format);
return MODE_BAD;
}
}
static enum drm_mode_status
intel_hdmi_mode_valid_format(struct intel_connector *connector,
const struct drm_display_mode *mode,
int clock, bool has_hdmi_sink,
enum intel_output_format sink_format)
{
struct intel_display *display = to_intel_display(connector);
enum drm_mode_status status;
status = intel_hdmi_sink_format_valid(connector, mode,
has_hdmi_sink, sink_format);
if (status != MODE_OK)
return status;
status = intel_pfit_mode_valid(display, mode, sink_format, 0);
if (status != MODE_OK)
return status;
return intel_hdmi_mode_clock_valid(&connector->base, clock, has_hdmi_sink, sink_format);
}
static enum drm_mode_status
intel_hdmi_mode_valid(struct drm_connector *_connector,
const struct drm_display_mode *mode)
@ -2028,12 +2073,11 @@ intel_hdmi_mode_valid(struct drm_connector *_connector,
struct intel_connector *connector = to_intel_connector(_connector);
struct intel_display *display = to_intel_display(connector);
struct intel_hdmi *hdmi = intel_attached_hdmi(connector);
const struct drm_display_info *info = &connector->base.display_info;
enum drm_mode_status status;
int clock = mode->clock;
int max_dotclk = display->cdclk.max_dotclk_freq;
bool has_hdmi_sink = intel_has_hdmi_sink(hdmi, connector->base.state);
bool ycbcr_420_only;
enum intel_output_format sink_format;
status = intel_cpu_transcoder_mode_valid(display, mode);
if (status != MODE_OK)
@ -2060,31 +2104,20 @@ intel_hdmi_mode_valid(struct drm_connector *_connector,
if (clock > 600000)
return MODE_CLOCK_HIGH;
ycbcr_420_only = drm_mode_is_420_only(&connector->base.display_info, mode);
if (drm_mode_is_420_only(info, mode)) {
status = intel_hdmi_mode_valid_format(connector, mode, clock, has_hdmi_sink,
INTEL_OUTPUT_FORMAT_YCBCR420);
} else {
status = intel_hdmi_mode_valid_format(connector, mode, clock, has_hdmi_sink,
INTEL_OUTPUT_FORMAT_RGB);
if (ycbcr_420_only)
sink_format = INTEL_OUTPUT_FORMAT_YCBCR420;
else
sink_format = INTEL_OUTPUT_FORMAT_RGB;
status = intel_pfit_mode_valid(display, mode, sink_format, 0);
if (status != MODE_OK && drm_mode_is_420_also(info, mode))
status = intel_hdmi_mode_valid_format(connector, mode, clock, has_hdmi_sink,
INTEL_OUTPUT_FORMAT_YCBCR420);
}
if (status != MODE_OK)
return status;
status = intel_hdmi_mode_clock_valid(&connector->base, clock, has_hdmi_sink, sink_format);
if (status != MODE_OK) {
if (ycbcr_420_only ||
!connector->base.ycbcr_420_allowed ||
!drm_mode_is_420_also(&connector->base.display_info, mode))
return status;
sink_format = INTEL_OUTPUT_FORMAT_YCBCR420;
status = intel_hdmi_mode_clock_valid(&connector->base, clock, has_hdmi_sink,
sink_format);
if (status != MODE_OK)
return status;
}
return intel_mode_valid_max_plane_size(display, mode, 1);
}
@ -2241,20 +2274,6 @@ static bool intel_hdmi_has_audio(struct intel_encoder *encoder,
return intel_conn_state->force_audio == HDMI_AUDIO_ON;
}
static enum intel_output_format
intel_hdmi_sink_format(const struct intel_crtc_state *crtc_state,
struct intel_connector *connector,
bool ycbcr_420_output)
{
if (!crtc_state->has_hdmi_sink)
return INTEL_OUTPUT_FORMAT_RGB;
if (connector->base.ycbcr_420_allowed && ycbcr_420_output)
return INTEL_OUTPUT_FORMAT_YCBCR420;
else
return INTEL_OUTPUT_FORMAT_RGB;
}
static enum intel_output_format
intel_hdmi_output_format(const struct intel_crtc_state *crtc_state)
{
@ -2263,37 +2282,55 @@ intel_hdmi_output_format(const struct intel_crtc_state *crtc_state)
static int intel_hdmi_compute_output_format(struct intel_encoder *encoder,
struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state,
bool respect_downstream_limits)
struct intel_connector *connector,
bool respect_downstream_limits,
enum intel_output_format sink_format)
{
const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
if (intel_hdmi_sink_format_valid(connector, adjusted_mode,
crtc_state->has_hdmi_sink, sink_format) != MODE_OK)
return -EINVAL;
crtc_state->sink_format = sink_format;
crtc_state->output_format = intel_hdmi_output_format(crtc_state);
return intel_hdmi_compute_clock(encoder, crtc_state, respect_downstream_limits);
}
static int intel_hdmi_compute_formats(struct intel_encoder *encoder,
struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state,
bool respect_downstream_limits)
{
struct intel_display *display = to_intel_display(encoder);
struct intel_connector *connector = to_intel_connector(conn_state->connector);
const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
const struct drm_display_info *info = &connector->base.display_info;
bool ycbcr_420_only = drm_mode_is_420_only(info, adjusted_mode);
int ret;
crtc_state->sink_format =
intel_hdmi_sink_format(crtc_state, connector, ycbcr_420_only);
if (drm_mode_is_420_only(info, adjusted_mode)) {
ret = intel_hdmi_compute_output_format(encoder, crtc_state, connector,
respect_downstream_limits,
INTEL_OUTPUT_FORMAT_YCBCR420);
if (ycbcr_420_only && crtc_state->sink_format != INTEL_OUTPUT_FORMAT_YCBCR420) {
drm_dbg_kms(display->drm,
"YCbCr 4:2:0 mode but YCbCr 4:2:0 output not possible. Falling back to RGB.\n");
crtc_state->sink_format = INTEL_OUTPUT_FORMAT_RGB;
}
if (ret && !respect_downstream_limits) {
drm_dbg_kms(display->drm,
"YCbCr 4:2:0 mode but YCbCr 4:2:0 output not possible. Falling back to RGB.\n");
crtc_state->output_format = intel_hdmi_output_format(crtc_state);
ret = intel_hdmi_compute_clock(encoder, crtc_state, respect_downstream_limits);
if (ret) {
if (crtc_state->sink_format == INTEL_OUTPUT_FORMAT_YCBCR420 ||
!crtc_state->has_hdmi_sink ||
!connector->base.ycbcr_420_allowed ||
!drm_mode_is_420_also(info, adjusted_mode))
return ret;
ret = intel_hdmi_compute_output_format(encoder, crtc_state, connector,
respect_downstream_limits,
INTEL_OUTPUT_FORMAT_RGB);
}
} else {
ret = intel_hdmi_compute_output_format(encoder, crtc_state, connector,
respect_downstream_limits,
INTEL_OUTPUT_FORMAT_RGB);
crtc_state->sink_format = INTEL_OUTPUT_FORMAT_YCBCR420;
crtc_state->output_format = intel_hdmi_output_format(crtc_state);
ret = intel_hdmi_compute_clock(encoder, crtc_state, respect_downstream_limits);
if (ret && drm_mode_is_420_also(info, adjusted_mode))
ret = intel_hdmi_compute_output_format(encoder, crtc_state, connector,
respect_downstream_limits,
INTEL_OUTPUT_FORMAT_YCBCR420);
}
return ret;
@ -2370,9 +2407,9 @@ int intel_hdmi_compute_config(struct intel_encoder *encoder,
* Try to respect downstream TMDS clock limits first, if
* that fails assume the user might know something we don't.
*/
ret = intel_hdmi_compute_output_format(encoder, pipe_config, conn_state, true);
ret = intel_hdmi_compute_formats(encoder, pipe_config, conn_state, true);
if (ret)
ret = intel_hdmi_compute_output_format(encoder, pipe_config, conn_state, false);
ret = intel_hdmi_compute_formats(encoder, pipe_config, conn_state, false);
if (ret) {
drm_dbg_kms(display->drm,
"unsupported HDMI clock (%d kHz), rejecting mode\n",
@ -2380,11 +2417,9 @@ int intel_hdmi_compute_config(struct intel_encoder *encoder,
return ret;
}
if (intel_hdmi_is_ycbcr420(pipe_config)) {
ret = intel_pfit_compute_config(pipe_config, conn_state);
if (ret)
return ret;
}
ret = intel_pfit_compute_config(pipe_config, conn_state);
if (ret)
return ret;
pipe_config->limited_color_range =
intel_hdmi_limited_color_range(pipe_config, conn_state);

View File

@ -1420,7 +1420,7 @@ static void i915_hpd_irq_setup(struct intel_display *display)
hotplug_en);
}
struct intel_hotplug_funcs {
struct intel_hotplug_irq_funcs {
/* Enable HPD sense and interrupts for all present encoders */
void (*hpd_irq_setup)(struct intel_display *display);
/* Enable HPD sense for a single encoder */
@ -1428,7 +1428,7 @@ struct intel_hotplug_funcs {
};
#define HPD_FUNCS(platform) \
static const struct intel_hotplug_funcs platform##_hpd_funcs = { \
static const struct intel_hotplug_irq_funcs platform##_hpd_funcs = { \
.hpd_irq_setup = platform##_hpd_irq_setup, \
.hpd_enable_detection = platform##_hpd_enable_detection, \
}
@ -1447,8 +1447,8 @@ void intel_hpd_enable_detection(struct intel_encoder *encoder)
{
struct intel_display *display = to_intel_display(encoder);
if (display->funcs.hotplug)
display->funcs.hotplug->hpd_enable_detection(encoder);
if (display->hotplug.funcs)
display->hotplug.funcs->hpd_enable_detection(encoder);
}
void intel_hpd_irq_setup(struct intel_display *display)
@ -1457,8 +1457,8 @@ void intel_hpd_irq_setup(struct intel_display *display)
!display->irq.vlv_display_irqs_enabled)
return;
if (display->funcs.hotplug)
display->funcs.hotplug->hpd_irq_setup(display);
if (display->hotplug.funcs)
display->hotplug.funcs->hpd_irq_setup(display);
}
void intel_hotplug_irq_init(struct intel_display *display)
@ -1469,23 +1469,23 @@ void intel_hotplug_irq_init(struct intel_display *display)
if (HAS_GMCH(display)) {
if (HAS_HOTPLUG(display))
display->funcs.hotplug = &i915_hpd_funcs;
display->hotplug.funcs = &i915_hpd_funcs;
} else {
if (HAS_PCH_DG2(display))
display->funcs.hotplug = &icp_hpd_funcs;
display->hotplug.funcs = &icp_hpd_funcs;
else if (HAS_PCH_DG1(display))
display->funcs.hotplug = &dg1_hpd_funcs;
display->hotplug.funcs = &dg1_hpd_funcs;
else if (DISPLAY_VER(display) >= 14)
display->funcs.hotplug = &xelpdp_hpd_funcs;
display->hotplug.funcs = &xelpdp_hpd_funcs;
else if (DISPLAY_VER(display) >= 11)
display->funcs.hotplug = &gen11_hpd_funcs;
display->hotplug.funcs = &gen11_hpd_funcs;
else if (display->platform.geminilake || display->platform.broxton)
display->funcs.hotplug = &bxt_hpd_funcs;
display->hotplug.funcs = &bxt_hpd_funcs;
else if (INTEL_PCH_TYPE(display) >= PCH_ICP)
display->funcs.hotplug = &icp_hpd_funcs;
display->hotplug.funcs = &icp_hpd_funcs;
else if (INTEL_PCH_TYPE(display) >= PCH_SPT)
display->funcs.hotplug = &spt_hpd_funcs;
display->hotplug.funcs = &spt_hpd_funcs;
else
display->funcs.hotplug = &ilk_hpd_funcs;
display->hotplug.funcs = &ilk_hpd_funcs;
}
}

View File

@ -1,26 +1,51 @@
// SPDX-License-Identifier: MIT
/* Copyright © 2025 Intel Corporation */
#include <linux/iopoll.h>
#include <drm/drm_blend.h>
#include <drm/drm_print.h>
#include <drm/intel/display_parent_interface.h>
#include "intel_crtc.h"
#include "intel_de.h"
#include "intel_display_core.h"
#include "intel_display_regs.h"
#include "intel_display_types.h"
#include "intel_fb.h"
#include "intel_frontbuffer.h"
#include "intel_initial_plane.h"
#include "intel_parent.h"
#include "intel_plane.h"
struct intel_initial_plane_configs {
struct intel_initial_plane_config config[I915_MAX_PIPES];
};
void intel_initial_plane_vblank_wait(struct intel_crtc *crtc)
{
struct intel_display *display = to_intel_display(crtc);
u32 start_ts, end_ts;
int ret;
display->parent->initial_plane->vblank_wait(&crtc->base);
/* xe doesn't have interrupts enabled this early */
if (intel_parent_irq_enabled(display)) {
intel_crtc_wait_for_next_vblank(crtc);
return;
}
start_ts = intel_de_read(display, PIPE_FRMTMSTMP(crtc->pipe));
ret = poll_timeout_us(end_ts = intel_de_read(display, PIPE_FRMTMSTMP(crtc->pipe)),
end_ts != start_ts, 1000, 1000 * 1000, false);
if (ret)
drm_warn(display->drm, "[CRTC:%d:%s] early vblank wait timed out\n",
crtc->base.base.id, crtc->base.name);
}
static const struct intel_plane_state *
intel_reuse_initial_plane_obj(struct intel_crtc *this,
const struct intel_initial_plane_config plane_configs[])
const struct intel_initial_plane_configs *all_plane_configs)
{
struct intel_display *display = to_intel_display(this);
struct intel_crtc *crtc;
@ -39,7 +64,8 @@ intel_reuse_initial_plane_obj(struct intel_crtc *this,
if (!plane_state->ggtt_vma)
continue;
if (plane_configs[this->pipe].base == plane_configs[crtc->pipe].base)
if (all_plane_configs->config[this->pipe].base ==
all_plane_configs->config[crtc->pipe].base)
return plane_state;
}
@ -50,17 +76,38 @@ static struct drm_gem_object *
intel_alloc_initial_plane_obj(struct intel_display *display,
struct intel_initial_plane_config *plane_config)
{
struct intel_framebuffer *fb = plane_config->fb;
struct drm_framebuffer *fb = plane_config->fb;
switch (fb->base.modifier) {
switch (fb->modifier) {
case DRM_FORMAT_MOD_LINEAR:
break;
case I915_FORMAT_MOD_X_TILED:
case I915_FORMAT_MOD_Y_TILED:
case I915_FORMAT_MOD_4_TILED:
break;
/* fenced region needed for linear CPU access to tiled FB */
if (intel_parent_has_fenced_regions(display))
break;
fallthrough;
default:
drm_dbg_kms(display->drm, "Unsupported modifier for initial FB: 0x%llx\n",
fb->base.modifier);
fb->modifier);
return NULL;
}
/*
* Would need to preserve the DPT, its GGTT
* mapping, and the actual FB memory.
*/
if (intel_fb_modifier_uses_dpt(display, fb->modifier)) {
drm_dbg_kms(display->drm, "DPT not supported for initial FB\n");
return NULL;
}
/*
* Would need to preserve the 270 degree rotated
* GGTT mapping used by the display hardware.
*/
if (drm_rotation_90_or_270(plane_config->rotation)) {
drm_dbg_kms(display->drm, "90/270 degree rotation not supported for initial FB\n");
return NULL;
}
@ -69,10 +116,10 @@ intel_alloc_initial_plane_obj(struct intel_display *display,
static void
intel_find_initial_plane_obj(struct intel_crtc *crtc,
struct intel_initial_plane_config plane_configs[])
struct intel_initial_plane_configs *all_plane_configs)
{
struct intel_display *display = to_intel_display(crtc);
struct intel_initial_plane_config *plane_config = &plane_configs[crtc->pipe];
struct intel_initial_plane_config *plane_config = &all_plane_configs->config[crtc->pipe];
struct intel_plane *plane = to_intel_plane(crtc->base.primary);
struct intel_plane_state *plane_state = to_intel_plane_state(plane->base.state);
struct drm_framebuffer *fb;
@ -88,12 +135,12 @@ intel_find_initial_plane_obj(struct intel_crtc *crtc,
return;
if (intel_alloc_initial_plane_obj(display, plane_config)) {
fb = &plane_config->fb->base;
fb = plane_config->fb;
vma = plane_config->vma;
} else {
const struct intel_plane_state *other_plane_state;
other_plane_state = intel_reuse_initial_plane_obj(crtc, plane_configs);
other_plane_state = intel_reuse_initial_plane_obj(crtc, all_plane_configs);
if (!other_plane_state)
goto nofb;
@ -144,7 +191,7 @@ static void plane_config_fini(struct intel_display *display,
struct intel_initial_plane_config *plane_config)
{
if (plane_config->fb) {
struct drm_framebuffer *fb = &plane_config->fb->base;
struct drm_framebuffer *fb = plane_config->fb;
/* We may only have the stub and not a full framebuffer */
if (drm_framebuffer_read_refcount(fb))
@ -158,14 +205,14 @@ static void plane_config_fini(struct intel_display *display,
void intel_initial_plane_config(struct intel_display *display)
{
struct intel_initial_plane_config plane_configs[I915_MAX_PIPES] = {};
struct intel_initial_plane_configs all_plane_configs = {};
struct intel_crtc *crtc;
for_each_intel_crtc(display->drm, crtc) {
const struct intel_crtc_state *crtc_state =
to_intel_crtc_state(crtc->base.state);
struct intel_initial_plane_config *plane_config =
&plane_configs[crtc->pipe];
&all_plane_configs.config[crtc->pipe];
if (!crtc_state->hw.active)
continue;
@ -177,15 +224,15 @@ void intel_initial_plane_config(struct intel_display *display)
* can even allow for smooth boot transitions if the BIOS
* fb is large enough for the active pipe configuration.
*/
display->funcs.display->get_initial_plane_config(crtc, plane_config);
display->modeset.funcs->get_initial_plane_config(crtc, plane_config);
/*
* If the fb is shared between multiple heads, we'll
* just get the first one.
*/
intel_find_initial_plane_obj(crtc, plane_configs);
intel_find_initial_plane_obj(crtc, &all_plane_configs);
if (display->funcs.display->fixup_initial_plane_config(crtc, plane_config))
if (display->modeset.funcs->fixup_initial_plane_config(crtc, plane_config))
intel_initial_plane_vblank_wait(crtc);
plane_config_fini(display, plane_config);

View File

@ -70,11 +70,11 @@
#include <drm/drm_print.h>
#include <drm/intel/intel_lpe_audio.h>
#include <drm/intel/pci_config.h>
#include "intel_audio_regs.h"
#include "intel_de.h"
#include "intel_lpe_audio.h"
#include "intel_pci_config.h"
#define HAS_LPE_AUDIO(display) ((display)->audio.lpe.platdev)

View File

@ -2135,7 +2135,7 @@ void intel_lt_phy_set_signal_levels(struct intel_encoder *encoder,
wakeref = intel_lt_phy_transaction_begin(encoder);
trans = encoder->get_buf_trans(encoder, crtc_state, &n_entries);
trans = intel_ddi_buf_trans_get(encoder, crtc_state, &n_entries);
if (drm_WARN_ON_ONCE(display->drm, !trans)) {
intel_lt_phy_transaction_end(encoder, wakeref);
return;

View File

@ -0,0 +1,78 @@
// SPDX-License-Identifier: MIT
/*
* Copyright © 2026 Intel Corporation
*/
#include <linux/minmax.h>
#include <drm/drm_print.h>
#include "intel_de.h"
#include "intel_display_core.h"
#include "intel_mchbar.h"
static bool has_mchbar_mirror(struct intel_display *display)
{
return DISPLAY_VER(display) < 14;
}
static u32 mchbar_mirror_base(struct intel_display *display)
{
if (DISPLAY_VER(display) >= 6)
return MCHBAR_MIRROR_BASE_SNB;
else
return MCHBAR_MIRROR_BASE;
}
static u32 mchbar_mirror_end(struct intel_display *display)
{
if (DISPLAY_VER(display) >= 12 && !display->platform.rocketlake)
return MCHBAR_MIRROR_END_TGL;
else if (DISPLAY_VER(display) >= 11)
return MCHBAR_MIRROR_END_ICL_RKL;
else if (DISPLAY_VER(display) >= 6)
return MCHBAR_MIRROR_END_SNB;
else
return MCHBAR_MIRROR_END;
}
static u32 mchbar_mirror_len(struct intel_display *display)
{
return mchbar_mirror_end(display) - mchbar_mirror_base(display) + 1;
}
static bool is_mchbar_reg(struct intel_display *display, i915_reg_t reg)
{
return has_mchbar_mirror(display) &&
in_range32(i915_mmio_reg_offset(reg),
mchbar_mirror_base(display),
mchbar_mirror_len(display));
}
static void assert_is_mchbar_reg(struct intel_display *display, i915_reg_t reg)
{
drm_WARN(display->drm, !is_mchbar_reg(display, reg),
"Reading non-MCHBAR register 0x%x\n",
i915_mmio_reg_offset(reg));
}
u16 intel_mchbar_read16(struct intel_display *display, i915_reg_t reg)
{
assert_is_mchbar_reg(display, reg);
return intel_de_read16(display, reg);
}
u32 intel_mchbar_read(struct intel_display *display, i915_reg_t reg)
{
assert_is_mchbar_reg(display, reg);
return intel_de_read(display, reg);
}
u64 intel_mchbar_read64_2x32(struct intel_display *display, i915_reg_t reg)
{
assert_is_mchbar_reg(display, reg);
return intel_de_read64_2x32(display, reg);
}

View File

@ -0,0 +1,21 @@
/* SPDX-License-Identifier: MIT */
/*
* Copyright © 2026 Intel Corporation
*/
#ifndef __INTEL_MCHBAR_H__
#define __INTEL_MCHBAR_H__
#include <linux/types.h>
#include <drm/intel/mchbar_regs.h>
#include "i915_reg_defs.h"
struct intel_display;
u16 intel_mchbar_read16(struct intel_display *display, i915_reg_t reg);
u32 intel_mchbar_read(struct intel_display *display, i915_reg_t reg);
u64 intel_mchbar_read64_2x32(struct intel_display *display, i915_reg_t reg);
#endif /* __INTEL_MCHBAR_H__ */

View File

@ -83,7 +83,7 @@ static void intel_crtc_disable_noatomic_begin(struct intel_crtc *crtc,
drm_WARN_ON(display->drm, IS_ERR(temp_crtc_state) || ret);
}
display->funcs.display->crtc_disable(to_intel_atomic_state(state), crtc);
display->modeset.funcs->crtc_disable(to_intel_atomic_state(state), crtc);
drm_atomic_commit_put(state);
@ -333,6 +333,7 @@ static void intel_crtc_copy_hw_to_uapi_state(struct intel_crtc_state *crtc_state
crtc_state->uapi.adjusted_mode = crtc_state->hw.adjusted_mode;
crtc_state->uapi.scaling_filter = crtc_state->hw.scaling_filter;
crtc_state->uapi.sharpness_strength = crtc_state->hw.sharpness_strength;
if (DISPLAY_INFO(display)->color.degamma_lut_size) {
/* assume 1:1 mapping */

View File

@ -34,13 +34,13 @@
#include <drm/drm_edid.h>
#include <drm/drm_file.h>
#include <drm/drm_print.h>
#include <drm/intel/pci_config.h>
#include "intel_acpi.h"
#include "intel_backlight.h"
#include "intel_display_core.h"
#include "intel_display_types.h"
#include "intel_opregion.h"
#include "intel_pci_config.h"
#define OPREGION_HEADER_OFFSET 0
#define OPREGION_ACPI_OFFSET 0x100

View File

@ -481,13 +481,9 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
if (ret != 0)
return ret;
atomic_inc(&display->restore.pending_fb_pin);
vma = intel_parent_overlay_pin_fb(display, obj, &offset);
if (IS_ERR(vma)) {
ret = PTR_ERR(vma);
goto out_pin_section;
}
if (IS_ERR(vma))
return PTR_ERR(vma);
if (!intel_parent_overlay_is_active(display)) {
const struct intel_crtc_state *crtc_state =
@ -571,8 +567,6 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
out_unpin:
intel_parent_overlay_unpin_fb(display, vma);
out_pin_section:
atomic_dec(&display->restore.pending_fb_pin);
return ret;
}

View File

@ -19,6 +19,7 @@
#include <drm/drm_print.h>
#include <drm/intel/display_parent_interface.h>
#include <drm/intel/vlv_iosf_sb_regs.h>
#include "intel_display_core.h"
#include "intel_parent.h"
@ -338,13 +339,37 @@ void intel_parent_stolen_node_free(struct intel_display *display, const struct i
display->parent->stolen->node_free(node);
}
/* vma */
int intel_parent_vma_fence_id(struct intel_display *display, const struct i915_vma *vma)
/* vlv iosf */
void intel_parent_vlv_iosf_get(struct intel_display *display, unsigned long unit_mask)
{
if (!display->parent->vma)
return -1;
if (drm_WARN_ON_ONCE(display->drm, !display->parent->vlv_iosf))
return;
return display->parent->vma->fence_id(vma);
display->parent->vlv_iosf->get(display->drm, unit_mask);
}
void intel_parent_vlv_iosf_put(struct intel_display *display, unsigned long unit_mask)
{
if (drm_WARN_ON_ONCE(display->drm, !display->parent->vlv_iosf))
return;
display->parent->vlv_iosf->put(display->drm, unit_mask);
}
u32 intel_parent_vlv_iosf_read(struct intel_display *display, enum vlv_iosf_sb_unit unit, u32 addr)
{
if (drm_WARN_ON_ONCE(display->drm, !display->parent->vlv_iosf))
return 0;
return display->parent->vlv_iosf->read(display->drm, unit, addr);
}
int intel_parent_vlv_iosf_write(struct intel_display *display, enum vlv_iosf_sb_unit unit, u32 addr, u32 val)
{
if (drm_WARN_ON_ONCE(display->drm, !display->parent->vlv_iosf))
return -EINVAL;
return display->parent->vlv_iosf->write(display->drm, unit, addr, val);
}
/* generic */

View File

@ -6,6 +6,7 @@
#include <linux/types.h>
enum vlv_iosf_sb_unit;
struct dma_fence;
struct drm_file;
struct drm_gem_object;
@ -109,8 +110,11 @@ u64 intel_parent_stolen_node_size(struct intel_display *display, const struct in
struct intel_stolen_node *intel_parent_stolen_node_alloc(struct intel_display *display);
void intel_parent_stolen_node_free(struct intel_display *display, const struct intel_stolen_node *node);
/* vma */
int intel_parent_vma_fence_id(struct intel_display *display, const struct i915_vma *vma);
/* vlv iosf */
void intel_parent_vlv_iosf_get(struct intel_display *display, unsigned long unit_mask);
void intel_parent_vlv_iosf_put(struct intel_display *display, unsigned long unit_mask);
u32 intel_parent_vlv_iosf_read(struct intel_display *display, enum vlv_iosf_sb_unit unit, u32 addr);
int intel_parent_vlv_iosf_write(struct intel_display *display, enum vlv_iosf_sb_unit unit, u32 addr, u32 val);
/* generic */
bool intel_parent_has_auxccs(struct intel_display *display);

View File

@ -186,6 +186,7 @@ static int pch_panel_fitting(struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state)
{
struct intel_display *display = to_intel_display(crtc_state);
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
const struct drm_display_mode *adjusted_mode =
&crtc_state->hw.adjusted_mode;
int pipe_src_w = drm_rect_width(&crtc_state->pipe_src);
@ -195,11 +196,22 @@ static int pch_panel_fitting(struct intel_crtc_state *crtc_state,
/* Native modes don't need fitting */
if (adjusted_mode->crtc_hdisplay == pipe_src_w &&
adjusted_mode->crtc_vdisplay == pipe_src_h &&
crtc_state->output_format != INTEL_OUTPUT_FORMAT_YCBCR420)
crtc_state->output_format != INTEL_OUTPUT_FORMAT_YCBCR420 &&
crtc_state->hw.sharpness_strength == 0)
return 0;
switch (conn_state->scaling_mode) {
case DRM_MODE_SCALE_CENTER:
if (adjusted_mode->crtc_hdisplay < pipe_src_w ||
adjusted_mode->crtc_vdisplay < pipe_src_h) {
drm_dbg_kms(display->drm,
"[CRTC:%d:%s] pfit center mode source (%dx%d) exceeds display (%dx%d)\n",
crtc->base.base.id, crtc->base.name,
pipe_src_w, pipe_src_h,
adjusted_mode->crtc_hdisplay,
adjusted_mode->crtc_vdisplay);
return -EINVAL;
}
width = pipe_src_w;
height = pipe_src_h;
x = (adjusted_mode->crtc_hdisplay - width + 1)/2;
@ -249,6 +261,16 @@ static int pch_panel_fitting(struct intel_crtc_state *crtc_state,
return -EINVAL;
}
if (crtc_state->hw.sharpness_strength &&
(width != pipe_src_w || height != pipe_src_h ||
crtc_state->hw.scaling_filter != DRM_SCALING_FILTER_DEFAULT ||
crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB)) {
drm_dbg_kms(display->drm,
"[CRTC:%d:%s] no scaling/YCbCr output with sharpness filter\n",
crtc->base.base.id, crtc->base.name);
return -EINVAL;
}
drm_rect_init(&crtc_state->pch_pfit.dst,
x, y, width, height);
crtc_state->pch_pfit.enabled = true;

View File

@ -70,6 +70,7 @@ static void intel_plane_state_reset(struct intel_plane_state *plane_state,
__drm_atomic_helper_plane_state_reset(&plane_state->uapi, &plane->base);
plane_state->scaler_id = -1;
plane_state->fence_id = -1;
}
struct intel_plane *intel_plane_alloc(void)
@ -137,7 +138,7 @@ intel_plane_duplicate_state(struct drm_plane *plane)
intel_state->ggtt_vma = NULL;
intel_state->dpt_vma = NULL;
intel_state->flags = 0;
intel_state->fence_id = -1;
intel_state->damage = DRM_RECT_INIT(0, 0, 0, 0);
/* add reference to fb */
@ -170,6 +171,19 @@ intel_plane_destroy_state(struct drm_plane *plane,
kfree(plane_state);
}
bool intel_plane_needs_low_address(struct intel_display *display)
{
/*
* Valleyview is definitely limited to scanning out the first
* 512MiB. Lets presume this behaviour was inherited from the
* g4x display engine and that all earlier gen are similarly
* limited. Testing suggests that it is a little more
* complicated than this. For example, Cherryview appears quite
* happy to scanout from anywhere within its global aperture.
*/
return HAS_GMCH(display);
}
bool intel_plane_needs_physical(struct intel_plane *plane)
{
struct intel_display *display = to_intel_display(plane);
@ -178,6 +192,15 @@ bool intel_plane_needs_physical(struct intel_plane *plane)
DISPLAY_INFO(display)->cursor_needs_physical;
}
bool intel_plane_needs_fence(struct intel_display *display)
{
/*
* pre-i965 planes use the fence for tiled scanout.
* i965+ planes have their own tiled scanout control bit.
*/
return DISPLAY_VER(display) < 4;
}
bool intel_plane_can_async_flip(struct intel_plane *plane,
const struct drm_format_info *info,
u64 modifier)

View File

@ -15,6 +15,7 @@ struct drm_rect;
struct intel_atomic_state;
struct intel_crtc;
struct intel_crtc_state;
struct intel_display;
struct intel_dsb;
struct intel_plane;
struct intel_plane_state;
@ -79,7 +80,9 @@ int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state);
void intel_plane_set_invisible(struct intel_crtc_state *crtc_state,
struct intel_plane_state *plane_state);
void intel_plane_helper_add(struct intel_plane *plane);
bool intel_plane_needs_low_address(struct intel_display *display);
bool intel_plane_needs_physical(struct intel_plane *plane);
bool intel_plane_needs_fence(struct intel_display *display);
void intel_plane_init_cursor_vblank_work(struct intel_plane_state *old_plane_state,
struct intel_plane_state *new_plane_state);
int intel_plane_add_affected(struct intel_atomic_state *state,

View File

@ -45,6 +45,7 @@
#include "intel_dmc.h"
#include "intel_dp.h"
#include "intel_dp_aux.h"
#include "intel_dp_tunnel.h"
#include "intel_dsb.h"
#include "intel_frontbuffer.h"
#include "intel_hdmi.h"
@ -694,6 +695,9 @@ static void _psr_init_dpcd(struct intel_dp *intel_dp, struct intel_connector *co
connector->dp.psr_caps.sync_latency = intel_dp_get_sink_sync_latency(intel_dp);
if (intel_has_quirk(display, QUIRK_DISABLE_PSR2))
return;
if (DISPLAY_VER(display) >= 9 &&
connector->dp.psr_caps.dpcd[0] >= DP_PSR2_WITH_Y_COORD_IS_SUPPORTED) {
bool y_req = connector->dp.psr_caps.dpcd[1] &
@ -1031,11 +1035,27 @@ static u8 frames_before_su_entry(struct intel_dp *intel_dp)
return frames_before_su_entry;
}
static bool intel_psr_allow_pr_bw_optimization(struct intel_dp *intel_dp)
{
if (intel_dp_is_edp(intel_dp))
return false;
if (!intel_dp_tunnel_bw_alloc_is_enabled(intel_dp))
return false;
if (!intel_dp_tunnel_pr_optimization_supported(intel_dp))
return false;
return true;
}
static void dg2_activate_panel_replay(struct intel_dp *intel_dp)
{
struct intel_display *display = to_intel_display(intel_dp);
struct intel_psr *psr = &intel_dp->psr;
enum transcoder cpu_transcoder = intel_dp->psr.transcoder;
u32 dp2_ctl_set = TRANS_DP2_PANEL_REPLAY_ENABLE;
u32 dp2_ctl_clear = 0;
if (intel_dp_is_edp(intel_dp) && psr->sel_update_enabled) {
u32 val = psr->su_region_et_enabled ?
@ -1048,12 +1068,16 @@ static void dg2_activate_panel_replay(struct intel_dp *intel_dp)
val);
}
if (intel_psr_allow_pr_bw_optimization(intel_dp))
dp2_ctl_set |= TRANS_DP2_PR_TUNNELING_ENABLE;
else
dp2_ctl_clear = TRANS_DP2_PR_TUNNELING_ENABLE;
intel_de_rmw(display,
PSR2_MAN_TRK_CTL(display, intel_dp->psr.transcoder),
0, ADLP_PSR2_MAN_TRK_CTL_SF_CONTINUOS_FULL_FRAME);
intel_de_rmw(display, TRANS_DP2_CTL(intel_dp->psr.transcoder), 0,
TRANS_DP2_PANEL_REPLAY_ENABLE);
intel_de_rmw(display, TRANS_DP2_CTL(intel_dp->psr.transcoder), dp2_ctl_clear, dp2_ctl_set);
}
static void hsw_activate_psr2(struct intel_dp *intel_dp)

View File

@ -94,6 +94,12 @@ static void quirk_disable_edp_panel_replay(struct intel_dp *intel_dp)
drm_info(display->drm, "Applying disable Panel Replay quirk\n");
}
static void quirk_disable_psr2(struct intel_display *display)
{
intel_set_quirk(display, QUIRK_DISABLE_PSR2);
drm_info(display->drm, "PSR2 support not currently available for this setup, applying disable PSR2 quirk\n");
}
struct intel_quirk {
int device;
int subsystem_vendor;
@ -250,6 +256,9 @@ static struct intel_quirk intel_quirks[] = {
/* Dell XPS 13 7390 2-in-1 */
{ 0x8a52, 0x1028, 0x08b0, quirk_edp_limit_rate_hbr2 },
/* Xiaomi Book Pro 14 2026 */
{ 0xb081, 0x1d72, 0x2424, quirk_disable_psr2 },
};
static const struct intel_dpcd_quirk intel_dpcd_quirks[] = {
@ -269,6 +278,14 @@ static const struct intel_dpcd_quirk intel_dpcd_quirks[] = {
.sink_oui = SINK_OUI(0x00, 0x22, 0xb9),
.hook = quirk_disable_edp_panel_replay,
},
/* Dell XPS 16 DA16260 */
{
.device = DEVICE_ID_ANY,
.subsystem_vendor = 0x1028,
.subsystem_device = 0x0dba,
.sink_oui = SINK_OUI(0x00, 0x22, 0xb9),
.hook = quirk_disable_edp_panel_replay,
},
};
void intel_init_quirks(struct intel_display *display)

View File

@ -22,6 +22,7 @@ enum intel_quirk_id {
QUIRK_FW_SYNC_LEN,
QUIRK_EDP_LIMIT_RATE_HBR2,
QUIRK_DISABLE_EDP_PANEL_REPLAY,
QUIRK_DISABLE_PSR2,
};
void intel_init_quirks(struct intel_display *display);

View File

@ -7,8 +7,9 @@
#include <drm/drm_device.h>
#include "intel_de.h"
#include "intel_display_types.h"
#include "intel_rom.h"
#include "intel_uncore.h"
#include "intel_oprom_regs.h"
struct intel_rom {
@ -17,7 +18,7 @@ struct intel_rom {
void __iomem *oprom;
/* for SPI */
struct intel_uncore *uncore;
struct intel_display *display;
loff_t offset;
size_t size;
@ -30,10 +31,10 @@ struct intel_rom {
static u32 spi_read32(struct intel_rom *rom, loff_t offset)
{
intel_uncore_write(rom->uncore, PRIMARY_SPI_ADDRESS,
rom->offset + offset);
intel_de_write(rom->display, PRIMARY_SPI_ADDRESS,
rom->offset + offset);
return intel_uncore_read(rom->uncore, PRIMARY_SPI_TRIGGER);
return intel_de_read(rom->display, PRIMARY_SPI_TRIGGER);
}
static u16 spi_read16(struct intel_rom *rom, loff_t offset)
@ -50,13 +51,13 @@ struct intel_rom *intel_rom_spi(struct drm_device *drm)
if (!rom)
return NULL;
rom->uncore = to_intel_uncore(drm);
rom->display = to_intel_display(drm);
static_region = intel_uncore_read(rom->uncore, SPI_STATIC_REGIONS);
static_region = intel_de_read(rom->display, SPI_STATIC_REGIONS);
static_region &= OPTIONROM_SPI_REGIONID_MASK;
intel_uncore_write(rom->uncore, PRIMARY_SPI_REGIONID, static_region);
intel_de_write(rom->display, PRIMARY_SPI_REGIONID, static_region);
rom->offset = intel_uncore_read(rom->uncore, OROM_OFFSET) & OROM_OFFSET_MASK;
rom->offset = intel_de_read(rom->display, OROM_OFFSET) & OROM_OFFSET_MASK;
rom->size = 0x200000;

View File

@ -72,7 +72,7 @@ void intel_snps_phy_set_signal_levels(struct intel_encoder *encoder,
enum phy phy = intel_encoder_to_phy(encoder);
int n_entries, ln;
trans = encoder->get_buf_trans(encoder, crtc_state, &n_entries);
trans = intel_ddi_buf_trans_get(encoder, crtc_state, &n_entries);
if (drm_WARN_ON_ONCE(display->drm, !trans))
return;

View File

@ -109,8 +109,8 @@ u32 i915_get_vblank_counter(struct drm_crtc *crtc)
* we get a low value that's stable across two reads of the high
* register.
*/
frame = intel_de_read64_2x32(display, PIPEFRAMEPIXEL(display, pipe),
PIPEFRAME(display, pipe));
frame = intel_de_read64_2x32_volatile(display, PIPEFRAMEPIXEL(display, pipe),
PIPEFRAME(display, pipe));
pixel = frame & PIPE_PIXEL_MASK;
frame = (frame >> PIPE_FRAME_LOW_SHIFT) & 0xffffff;

View File

@ -55,6 +55,16 @@ bool intel_vrr_is_capable(struct intel_connector *connector)
if (connector->mst.dp)
return false;
intel_dp = intel_attached_dp(connector);
/*
* Among non-MST DP branch devices, only an HDMI 2.1 sink connected
* via a PCON could support VRR. However, supporting VRR through a
* PCON requires non-trivial changes that are not implemented yet.
* Until that support exists, avoid VRR on all DP branch devices.
*
* TODO: Add support for VRR for DP->HDMI 2.1 PCON.
*/
if (drm_dp_is_branch(intel_dp->dpcd))
return false;
if (!drm_dp_sink_can_do_video_without_timing_msa(intel_dp->dpcd))
return false;
@ -1053,11 +1063,9 @@ void intel_vrr_get_config(struct intel_crtc_state *crtc_state)
if (crtc_state->cmrr.enable) {
crtc_state->cmrr.cmrr_n =
intel_de_read64_2x32(display, TRANS_CMRR_N_LO(display, cpu_transcoder),
TRANS_CMRR_N_HI(display, cpu_transcoder));
intel_de_read64_2x32(display, TRANS_CMRR_N_LO(display, cpu_transcoder));
crtc_state->cmrr.cmrr_m =
intel_de_read64_2x32(display, TRANS_CMRR_M_LO(display, cpu_transcoder),
TRANS_CMRR_M_HI(display, cpu_transcoder));
intel_de_read64_2x32(display, TRANS_CMRR_M_LO(display, cpu_transcoder));
}
if (DISPLAY_VER(display) >= 13) {

View File

@ -48,8 +48,8 @@
*/
void intel_update_watermarks(struct intel_display *display)
{
if (display->funcs.wm->update_wm)
display->funcs.wm->update_wm(display);
if (display->wm.funcs->update_wm)
display->wm.funcs->update_wm(display);
}
int intel_wm_compute(struct intel_atomic_state *state,
@ -57,10 +57,10 @@ int intel_wm_compute(struct intel_atomic_state *state,
{
struct intel_display *display = to_intel_display(state);
if (!display->funcs.wm->compute_watermarks)
if (!display->wm.funcs->compute_watermarks)
return 0;
return display->funcs.wm->compute_watermarks(state, crtc);
return display->wm.funcs->compute_watermarks(state, crtc);
}
bool intel_initial_watermarks(struct intel_atomic_state *state,
@ -68,8 +68,8 @@ bool intel_initial_watermarks(struct intel_atomic_state *state,
{
struct intel_display *display = to_intel_display(state);
if (display->funcs.wm->initial_watermarks) {
display->funcs.wm->initial_watermarks(state, crtc);
if (display->wm.funcs->initial_watermarks) {
display->wm.funcs->initial_watermarks(state, crtc);
return true;
}
@ -81,8 +81,8 @@ void intel_atomic_update_watermarks(struct intel_atomic_state *state,
{
struct intel_display *display = to_intel_display(state);
if (display->funcs.wm->atomic_update_watermarks)
display->funcs.wm->atomic_update_watermarks(state, crtc);
if (display->wm.funcs->atomic_update_watermarks)
display->wm.funcs->atomic_update_watermarks(state, crtc);
}
void intel_optimize_watermarks(struct intel_atomic_state *state,
@ -90,30 +90,30 @@ void intel_optimize_watermarks(struct intel_atomic_state *state,
{
struct intel_display *display = to_intel_display(state);
if (display->funcs.wm->optimize_watermarks)
display->funcs.wm->optimize_watermarks(state, crtc);
if (display->wm.funcs->optimize_watermarks)
display->wm.funcs->optimize_watermarks(state, crtc);
}
int intel_compute_global_watermarks(struct intel_atomic_state *state)
{
struct intel_display *display = to_intel_display(state);
if (display->funcs.wm->compute_global_watermarks)
return display->funcs.wm->compute_global_watermarks(state);
if (display->wm.funcs->compute_global_watermarks)
return display->wm.funcs->compute_global_watermarks(state);
return 0;
}
void intel_wm_get_hw_state(struct intel_display *display)
{
if (display->funcs.wm->get_hw_state)
return display->funcs.wm->get_hw_state(display);
if (display->wm.funcs->get_hw_state)
return display->wm.funcs->get_hw_state(display);
}
void intel_wm_sanitize(struct intel_display *display)
{
if (display->funcs.wm->sanitize)
return display->funcs.wm->sanitize(display);
if (display->wm.funcs->sanitize)
return display->wm.funcs->sanitize(display);
}
bool intel_wm_plane_visible(const struct intel_crtc_state *crtc_state,

View File

@ -270,6 +270,11 @@ int skl_update_scaler_crtc(struct intel_crtc_state *crtc_state)
{
const struct drm_display_mode *pipe_mode = &crtc_state->hw.pipe_mode;
int width, height;
int ret;
ret = intel_casf_compute_config(crtc_state);
if (ret)
return ret;
if (crtc_state->pch_pfit.enabled) {
width = drm_rect_width(&crtc_state->pch_pfit.dst);
@ -284,8 +289,7 @@ int skl_update_scaler_crtc(struct intel_crtc_state *crtc_state)
drm_rect_width(&crtc_state->pipe_src),
drm_rect_height(&crtc_state->pipe_src),
width, height, NULL, 0,
crtc_state->pch_pfit.enabled ||
intel_casf_needs_scaler(crtc_state));
crtc_state->pch_pfit.enabled);
}
/**
@ -323,19 +327,24 @@ int skl_update_scaler_plane(struct intel_crtc_state *crtc_state,
need_scaler);
}
static bool scaler_has_casf(struct intel_display *display, int scaler_id)
{
return HAS_CASF(display) && scaler_id == 1;
}
static int intel_allocate_scaler(struct intel_crtc_scaler_state *scaler_state,
struct intel_crtc *crtc,
struct intel_plane_state *plane_state,
bool casf_scaler)
{
struct intel_display *display = to_intel_display(crtc);
int i;
for (i = 0; i < crtc->num_scalers; i++) {
if (scaler_state->scalers[i].in_use)
continue;
/* CASF needs second scaler */
if (!plane_state && casf_scaler && i != 1)
if (casf_scaler && !scaler_has_casf(display, i))
continue;
scaler_state->scalers[i].in_use = true;
@ -529,14 +538,11 @@ static int setup_crtc_scaler(struct intel_atomic_state *state,
struct intel_crtc_scaler_state *scaler_state =
&crtc_state->scaler_state;
if (intel_casf_needs_scaler(crtc_state) && crtc_state->pch_pfit.enabled)
return -EINVAL;
return intel_atomic_setup_scaler(crtc_state,
hweight32(scaler_state->scaler_users),
crtc, "CRTC", crtc->base.base.id,
NULL, &scaler_state->scaler_id,
intel_casf_needs_scaler(crtc_state));
crtc_state->pch_pfit.casf.enable);
}
static int setup_plane_scaler(struct intel_atomic_state *state,
@ -725,9 +731,9 @@ static void glk_program_nearest_filter_coefs(struct intel_display *display,
GLK_PS_COEF_INDEX_SET(pipe, id, set), 0);
}
static u32 skl_scaler_get_filter_select(enum drm_scaling_filter filter)
static u32 skl_scaler_get_filter_select(enum drm_scaling_filter filter, bool casf)
{
if (filter == DRM_SCALING_FILTER_NEAREST_NEIGHBOR)
if (filter == DRM_SCALING_FILTER_NEAREST_NEIGHBOR || casf)
return (PS_FILTER_PROGRAMMED |
PS_Y_VERT_FILTER_SELECT(0) |
PS_Y_HORZ_FILTER_SELECT(0) |
@ -752,50 +758,14 @@ static void skl_scaler_setup_filter(struct intel_display *display,
}
}
#define CASF_SCALER_FILTER_SELECT \
(PS_FILTER_PROGRAMMED | \
PS_Y_VERT_FILTER_SELECT(0) | \
PS_Y_HORZ_FILTER_SELECT(0) | \
PS_UV_VERT_FILTER_SELECT(0) | \
PS_UV_HORZ_FILTER_SELECT(0))
void skl_scaler_setup_casf(struct intel_crtc_state *crtc_state)
static u32 casf_sharpness_ctl(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);
struct drm_display_mode *adjusted_mode =
&crtc_state->hw.adjusted_mode;
struct intel_crtc_scaler_state *scaler_state =
&crtc_state->scaler_state;
struct drm_rect src, dest;
int id, width, height;
int x = 0, y = 0;
enum pipe pipe = crtc->pipe;
u32 ps_ctrl;
if (!crtc_state->pch_pfit.casf.enable)
return 0;
width = adjusted_mode->crtc_hdisplay;
height = adjusted_mode->crtc_vdisplay;
drm_rect_init(&dest, x, y, width, height);
width = drm_rect_width(&dest);
height = drm_rect_height(&dest);
id = scaler_state->scaler_id;
drm_rect_init(&src, 0, 0,
drm_rect_width(&crtc_state->pipe_src) << 16,
drm_rect_height(&crtc_state->pipe_src) << 16);
trace_intel_pipe_scaler_update_arm(crtc, id, x, y, width, height);
ps_ctrl = PS_SCALER_EN | PS_BINDING_PIPE | scaler_state->scalers[id].mode |
CASF_SCALER_FILTER_SELECT;
intel_de_write_fw(display, SKL_PS_CTRL(pipe, id), ps_ctrl);
intel_de_write_fw(display, SKL_PS_WIN_POS(pipe, id),
PS_WIN_XPOS(x) | PS_WIN_YPOS(y));
intel_de_write_fw(display, SKL_PS_WIN_SZ(pipe, id),
PS_WIN_XSIZE(width) | PS_WIN_YSIZE(height));
return FILTER_EN |
FILTER_STRENGTH(crtc_state->pch_pfit.casf.strength) |
crtc_state->pch_pfit.casf.win_size;
}
void skl_pfit_enable(const struct intel_crtc_state *crtc_state)
@ -839,12 +809,20 @@ void skl_pfit_enable(const struct intel_crtc_state *crtc_state)
id = scaler_state->scaler_id;
ps_ctrl = PS_SCALER_EN | PS_BINDING_PIPE | scaler_state->scalers[id].mode |
skl_scaler_get_filter_select(crtc_state->hw.scaling_filter);
skl_scaler_get_filter_select(crtc_state->hw.scaling_filter,
crtc_state->pch_pfit.casf.enable);
trace_intel_pipe_scaler_update_arm(crtc, id, x, y, width, height);
skl_scaler_setup_filter(display, NULL, pipe, id, 0,
crtc_state->hw.scaling_filter);
if (crtc_state->pch_pfit.casf.enable)
intel_casf_setup(crtc_state);
else
skl_scaler_setup_filter(display, NULL, pipe, id, 0,
crtc_state->hw.scaling_filter);
if (scaler_has_casf(display, id))
intel_de_write_fw(display, SHARPNESS_CTL(crtc->pipe),
casf_sharpness_ctl(crtc_state));
intel_de_write_fw(display, SKL_PS_CTRL(pipe, id), ps_ctrl);
@ -905,7 +883,7 @@ skl_program_plane_scaler(struct intel_dsb *dsb,
}
ps_ctrl = PS_SCALER_EN | PS_BINDING_PLANE(plane->id) | scaler->mode |
skl_scaler_get_filter_select(plane_state->hw.scaling_filter);
skl_scaler_get_filter_select(plane_state->hw.scaling_filter, false);
trace_intel_plane_scaler_update_arm(plane, scaler_id,
crtc_x, crtc_y, crtc_w, crtc_h);
@ -932,6 +910,9 @@ static void skl_detach_scaler(struct intel_dsb *dsb,
trace_intel_scaler_disable_arm(crtc, id);
if (scaler_has_casf(display, id))
intel_de_write_dsb(display, dsb, SHARPNESS_CTL(crtc->pipe), 0);
intel_de_write_dsb(display, dsb, SKL_PS_CTRL(crtc->pipe, id), 0);
intel_de_write_dsb(display, dsb, SKL_PS_WIN_POS(crtc->pipe, id), 0);
intel_de_write_dsb(display, dsb, SKL_PS_WIN_SZ(crtc->pipe, id), 0);
@ -982,22 +963,19 @@ void skl_scaler_get_config(struct intel_crtc_state *crtc_state)
id = i;
/* Read CASF regs for second scaler */
if (HAS_CASF(display) && id == 1)
if (scaler_has_casf(display, i))
intel_casf_sharpness_get_config(crtc_state);
if (!crtc_state->hw.casf_params.casf_enable)
crtc_state->pch_pfit.enabled = true;
crtc_state->pch_pfit.enabled = true;
pos = intel_de_read(display, SKL_PS_WIN_POS(crtc->pipe, i));
size = intel_de_read(display, SKL_PS_WIN_SZ(crtc->pipe, i));
if (!crtc_state->hw.casf_params.casf_enable)
drm_rect_init(&crtc_state->pch_pfit.dst,
REG_FIELD_GET(PS_WIN_XPOS_MASK, pos),
REG_FIELD_GET(PS_WIN_YPOS_MASK, pos),
REG_FIELD_GET(PS_WIN_XSIZE_MASK, size),
REG_FIELD_GET(PS_WIN_YSIZE_MASK, size));
drm_rect_init(&crtc_state->pch_pfit.dst,
REG_FIELD_GET(PS_WIN_XPOS_MASK, pos),
REG_FIELD_GET(PS_WIN_YPOS_MASK, pos),
REG_FIELD_GET(PS_WIN_XSIZE_MASK, size),
REG_FIELD_GET(PS_WIN_YSIZE_MASK, size));
scaler_state->scalers[i].in_use = true;
break;

View File

@ -36,8 +36,6 @@ void skl_scaler_disable(const struct intel_crtc_state *old_crtc_state);
void skl_scaler_get_config(struct intel_crtc_state *crtc_state);
void skl_scaler_setup_casf(struct intel_crtc_state *crtc_state);
enum drm_mode_status
skl_scaler_mode_valid(struct intel_display *display,
const struct drm_display_mode *mode,

View File

@ -2126,6 +2126,19 @@ static int skl_check_main_surface(struct intel_plane_state *plane_state)
return 0;
}
/* Divide a U16.16 fixed-point value by 2, staying in fixed-point domain */
static inline u32 fp_16_16_div2(u32 fp)
{
return fp >> 1;
}
/* Convert a U16.16 fixed-point value to integer, rounding up */
static inline int fp_16_16_to_int_ceil(u32 fp)
{
return DIV_ROUND_UP(fp, 1 << 16);
}
static int skl_check_nv12_aux_surface(struct intel_plane_state *plane_state)
{
struct intel_display *display = to_intel_display(plane_state);
@ -2139,10 +2152,16 @@ static int skl_check_nv12_aux_surface(struct intel_plane_state *plane_state)
int min_height = intel_plane_min_height(plane, fb, uv_plane, rotation);
int max_width = intel_plane_max_width(plane, fb, uv_plane, rotation);
int max_height = intel_plane_max_height(plane, fb, uv_plane, rotation);
int x = plane_state->uapi.src.x1 >> 17;
int y = plane_state->uapi.src.y1 >> 17;
int w = drm_rect_width(&plane_state->uapi.src) >> 17;
int h = drm_rect_height(&plane_state->uapi.src) >> 17;
/*
* LNL+ UV surface start/size =
* ceiling(half of Y plane start/size). Use ceiling division
* unconditionally; it is a no-op for even values.
*/
int x = fp_16_16_to_int_ceil(fp_16_16_div2(plane_state->uapi.src.x1));
int y = fp_16_16_to_int_ceil(fp_16_16_div2(plane_state->uapi.src.y1));
int w = fp_16_16_to_int_ceil(fp_16_16_div2(drm_rect_width(&plane_state->uapi.src)));
int h = fp_16_16_to_int_ceil(fp_16_16_div2(drm_rect_height(&plane_state->uapi.src)));
u32 offset;
/* FIXME not quite sure how/if these apply to the chroma plane */
@ -3148,12 +3167,6 @@ skl_get_initial_plane_config(struct intel_crtc *crtc,
fb->format = drm_get_format_info(display->drm, fourcc, fb->modifier);
if (!display->params.enable_dpt &&
intel_fb_modifier_uses_dpt(display, fb->modifier)) {
drm_dbg_kms(display->drm, "DPT disabled, skipping initial FB\n");
goto error;
}
/*
* DRM_MODE_ROTATE_ is counter clockwise to stay compatible with Xrandr
* while i915 HW rotation is clockwise, that's why this swapping.
@ -3206,7 +3219,7 @@ skl_get_initial_plane_config(struct intel_crtc *crtc,
fb->width, fb->height, fb->format->cpp[0] * 8,
base, fb->pitches[0], plane_config->size);
plane_config->fb = intel_fb;
plane_config->fb = &intel_fb->base;
return;
error:

View File

@ -308,15 +308,6 @@ static bool skl_crtc_can_enable_sagv(const struct intel_crtc_state *crtc_state)
enum plane_id plane_id;
int max_level = INT_MAX;
if (!intel_has_sagv(display))
return false;
if (!crtc_state->hw.active)
return true;
if (crtc_state->hw.pipe_mode.flags & DRM_MODE_FLAG_INTERLACE)
return false;
for_each_plane_id_on_crtc(crtc, plane_id) {
const struct skl_plane_wm *wm =
&crtc_state->wm.skl.optimal.planes[plane_id];
@ -359,9 +350,6 @@ static bool tgl_crtc_can_enable_sagv(const struct intel_crtc_state *crtc_state)
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
enum plane_id plane_id;
if (!crtc_state->hw.active)
return true;
for_each_plane_id_on_crtc(crtc, plane_id) {
const struct skl_plane_wm *wm =
&crtc_state->wm.skl.optimal.planes[plane_id];
@ -377,6 +365,9 @@ bool intel_crtc_can_enable_sagv(const struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(crtc_state);
if (!display->sagv.block_time_us)
return false;
if (!display->params.enable_sagv)
return false;
@ -388,7 +379,13 @@ bool intel_crtc_can_enable_sagv(const struct intel_crtc_state *crtc_state)
if (crtc_state->inherited)
return false;
if (DISPLAY_VER(display) >= 12)
if (!crtc_state->hw.active)
return true;
if (crtc_state->hw.pipe_mode.flags & DRM_MODE_FLAG_INTERLACE)
return false;
if (HAS_SAGV_WM(display))
return tgl_crtc_can_enable_sagv(crtc_state);
else
return skl_crtc_can_enable_sagv(crtc_state);
@ -1939,7 +1936,7 @@ static void skl_compute_plane_wm(const struct intel_crtc_state *crtc_state,
result->enable = true;
result->auto_min_alloc_wm_enable = xe3_auto_min_alloc_capable(plane, level);
if (DISPLAY_VER(display) < 12 && display->sagv.block_time_us)
if (!HAS_SAGV_WM(display) && display->sagv.block_time_us)
result->can_sagv = latency >= display->sagv.block_time_us;
}
@ -2065,7 +2062,7 @@ static int skl_build_plane_wm_single(struct intel_crtc_state *crtc_state,
skl_compute_transition_wm(display, &wm->trans_wm,
&wm->wm[0], &wm_params);
if (DISPLAY_VER(display) >= 12) {
if (HAS_SAGV_WM(display)) {
tgl_compute_sagv_wm(crtc_state, plane, &wm_params, wm);
skl_compute_transition_wm(display, &wm->sagv.trans_wm,
@ -2324,7 +2321,7 @@ static int skl_wm_check_vblank(struct intel_crtc_state *crtc_state)
}
}
if (DISPLAY_VER(display) >= 12 &&
if (HAS_SAGV_WM(display) &&
display->sagv.block_time_us &&
skl_prefill_vblank_too_short(&ctx, crtc_state,
display->sagv.block_time_us)) {
@ -2616,6 +2613,26 @@ skl_print_plane_ddb_changes(struct intel_plane *plane,
skl_ddb_entry_size(old), skl_ddb_entry_size(new));
}
#define PLANE_WM_EN_FMT "%cwm0,%cwm1,%cwm2,%cwm3,%cwm4,%cwm5,%cwm6,%cwm7,%ctwm,%cswm,%cstwm"
#define PLANE_WM_EN_ARGS(__wm) \
enast((__wm)->wm[0].enable), enast((__wm)->wm[1].enable), \
enast((__wm)->wm[2].enable), enast((__wm)->wm[3].enable), \
enast((__wm)->wm[4].enable), enast((__wm)->wm[5].enable), \
enast((__wm)->wm[6].enable), enast((__wm)->wm[7].enable), \
enast((__wm)->trans_wm.enable), \
enast((__wm)->sagv.wm0.enable), \
enast((__wm)->sagv.trans_wm.enable)
#define PLANE_WM_FMT "%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%5d"
#define PLANE_WM_ARGS(__wm, __field) \
(__wm)->wm[0].__field, (__wm)->wm[1].__field, \
(__wm)->wm[2].__field, (__wm)->wm[3].__field, \
(__wm)->wm[4].__field, (__wm)->wm[5].__field, \
(__wm)->wm[6].__field, (__wm)->wm[7].__field, \
(__wm)->trans_wm.__field, \
(__wm)->sagv.wm0.__field, \
(__wm)->sagv.trans_wm.__field
static noinline_for_stack void
skl_print_plane_wm_changes(struct intel_plane *plane,
const struct skl_plane_wm *old_wm,
@ -2624,112 +2641,44 @@ skl_print_plane_wm_changes(struct intel_plane *plane,
struct intel_display *display = to_intel_display(plane);
drm_dbg_kms(display->drm,
"[PLANE:%d:%s] level %cwm0,%cwm1,%cwm2,%cwm3,%cwm4,%cwm5,%cwm6,%cwm7,%ctwm,%cswm,%cstwm"
" -> %cwm0,%cwm1,%cwm2,%cwm3,%cwm4,%cwm5,%cwm6,%cwm7,%ctwm,%cswm,%cstwm\n",
"[PLANE:%d:%s] level " PLANE_WM_EN_FMT " -> " PLANE_WM_EN_FMT "\n",
plane->base.base.id, plane->base.name,
enast(old_wm->wm[0].enable), enast(old_wm->wm[1].enable),
enast(old_wm->wm[2].enable), enast(old_wm->wm[3].enable),
enast(old_wm->wm[4].enable), enast(old_wm->wm[5].enable),
enast(old_wm->wm[6].enable), enast(old_wm->wm[7].enable),
enast(old_wm->trans_wm.enable),
enast(old_wm->sagv.wm0.enable),
enast(old_wm->sagv.trans_wm.enable),
enast(new_wm->wm[0].enable), enast(new_wm->wm[1].enable),
enast(new_wm->wm[2].enable), enast(new_wm->wm[3].enable),
enast(new_wm->wm[4].enable), enast(new_wm->wm[5].enable),
enast(new_wm->wm[6].enable), enast(new_wm->wm[7].enable),
enast(new_wm->trans_wm.enable),
enast(new_wm->sagv.wm0.enable),
enast(new_wm->sagv.trans_wm.enable));
PLANE_WM_EN_ARGS(old_wm),
PLANE_WM_EN_ARGS(new_wm));
drm_dbg_kms(display->drm,
"[PLANE:%d:%s] lines %c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%4d"
" -> %c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%3d,%c%4d\n",
"[PLANE:%d:%s] lines " PLANE_WM_FMT " -> " PLANE_WM_FMT "\n",
plane->base.base.id, plane->base.name,
enast(old_wm->wm[0].ignore_lines), old_wm->wm[0].lines,
enast(old_wm->wm[1].ignore_lines), old_wm->wm[1].lines,
enast(old_wm->wm[2].ignore_lines), old_wm->wm[2].lines,
enast(old_wm->wm[3].ignore_lines), old_wm->wm[3].lines,
enast(old_wm->wm[4].ignore_lines), old_wm->wm[4].lines,
enast(old_wm->wm[5].ignore_lines), old_wm->wm[5].lines,
enast(old_wm->wm[6].ignore_lines), old_wm->wm[6].lines,
enast(old_wm->wm[7].ignore_lines), old_wm->wm[7].lines,
enast(old_wm->trans_wm.ignore_lines), old_wm->trans_wm.lines,
enast(old_wm->sagv.wm0.ignore_lines), old_wm->sagv.wm0.lines,
enast(old_wm->sagv.trans_wm.ignore_lines), old_wm->sagv.trans_wm.lines,
enast(new_wm->wm[0].ignore_lines), new_wm->wm[0].lines,
enast(new_wm->wm[1].ignore_lines), new_wm->wm[1].lines,
enast(new_wm->wm[2].ignore_lines), new_wm->wm[2].lines,
enast(new_wm->wm[3].ignore_lines), new_wm->wm[3].lines,
enast(new_wm->wm[4].ignore_lines), new_wm->wm[4].lines,
enast(new_wm->wm[5].ignore_lines), new_wm->wm[5].lines,
enast(new_wm->wm[6].ignore_lines), new_wm->wm[6].lines,
enast(new_wm->wm[7].ignore_lines), new_wm->wm[7].lines,
enast(new_wm->trans_wm.ignore_lines), new_wm->trans_wm.lines,
enast(new_wm->sagv.wm0.ignore_lines), new_wm->sagv.wm0.lines,
enast(new_wm->sagv.trans_wm.ignore_lines), new_wm->sagv.trans_wm.lines);
PLANE_WM_ARGS(old_wm, lines),
PLANE_WM_ARGS(new_wm, lines));
drm_dbg_kms(display->drm,
"[PLANE:%d:%s] blocks %4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%5d"
" -> %4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%5d\n",
"[PLANE:%d:%s] blocks " PLANE_WM_FMT " -> " PLANE_WM_FMT "\n",
plane->base.base.id, plane->base.name,
old_wm->wm[0].blocks, old_wm->wm[1].blocks,
old_wm->wm[2].blocks, old_wm->wm[3].blocks,
old_wm->wm[4].blocks, old_wm->wm[5].blocks,
old_wm->wm[6].blocks, old_wm->wm[7].blocks,
old_wm->trans_wm.blocks,
old_wm->sagv.wm0.blocks,
old_wm->sagv.trans_wm.blocks,
new_wm->wm[0].blocks, new_wm->wm[1].blocks,
new_wm->wm[2].blocks, new_wm->wm[3].blocks,
new_wm->wm[4].blocks, new_wm->wm[5].blocks,
new_wm->wm[6].blocks, new_wm->wm[7].blocks,
new_wm->trans_wm.blocks,
new_wm->sagv.wm0.blocks,
new_wm->sagv.trans_wm.blocks);
PLANE_WM_ARGS(old_wm, blocks),
PLANE_WM_ARGS(new_wm, blocks));
drm_dbg_kms(display->drm,
"[PLANE:%d:%s] min_ddb %4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%5d"
" -> %4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%5d\n",
"[PLANE:%d:%s] min_ddb " PLANE_WM_FMT " -> " PLANE_WM_FMT "\n",
plane->base.base.id, plane->base.name,
old_wm->wm[0].min_ddb_alloc, old_wm->wm[1].min_ddb_alloc,
old_wm->wm[2].min_ddb_alloc, old_wm->wm[3].min_ddb_alloc,
old_wm->wm[4].min_ddb_alloc, old_wm->wm[5].min_ddb_alloc,
old_wm->wm[6].min_ddb_alloc, old_wm->wm[7].min_ddb_alloc,
old_wm->trans_wm.min_ddb_alloc,
old_wm->sagv.wm0.min_ddb_alloc,
old_wm->sagv.trans_wm.min_ddb_alloc,
new_wm->wm[0].min_ddb_alloc, new_wm->wm[1].min_ddb_alloc,
new_wm->wm[2].min_ddb_alloc, new_wm->wm[3].min_ddb_alloc,
new_wm->wm[4].min_ddb_alloc, new_wm->wm[5].min_ddb_alloc,
new_wm->wm[6].min_ddb_alloc, new_wm->wm[7].min_ddb_alloc,
new_wm->trans_wm.min_ddb_alloc,
new_wm->sagv.wm0.min_ddb_alloc,
new_wm->sagv.trans_wm.min_ddb_alloc);
PLANE_WM_ARGS(old_wm, min_ddb_alloc),
PLANE_WM_ARGS(new_wm, min_ddb_alloc));
if (DISPLAY_VER(display) >= 11)
return;
drm_dbg_kms(display->drm,
"[PLANE:%d:%s] min_ddb_uv %4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%5d"
" -> %4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%4d,%5d\n",
"[PLANE:%d:%s] min_ddb_uv " PLANE_WM_FMT " -> " PLANE_WM_FMT "\n",
plane->base.base.id, plane->base.name,
old_wm->wm[0].min_ddb_alloc_uv, old_wm->wm[1].min_ddb_alloc_uv,
old_wm->wm[2].min_ddb_alloc_uv, old_wm->wm[3].min_ddb_alloc_uv,
old_wm->wm[4].min_ddb_alloc_uv, old_wm->wm[5].min_ddb_alloc_uv,
old_wm->wm[6].min_ddb_alloc_uv, old_wm->wm[7].min_ddb_alloc_uv,
old_wm->trans_wm.min_ddb_alloc_uv,
old_wm->sagv.wm0.min_ddb_alloc_uv,
old_wm->sagv.trans_wm.min_ddb_alloc_uv,
new_wm->wm[0].min_ddb_alloc_uv, new_wm->wm[1].min_ddb_alloc_uv,
new_wm->wm[2].min_ddb_alloc_uv, new_wm->wm[3].min_ddb_alloc_uv,
new_wm->wm[4].min_ddb_alloc_uv, new_wm->wm[5].min_ddb_alloc_uv,
new_wm->wm[6].min_ddb_alloc_uv, new_wm->wm[7].min_ddb_alloc_uv,
new_wm->trans_wm.min_ddb_alloc_uv,
new_wm->sagv.wm0.min_ddb_alloc_uv,
new_wm->sagv.trans_wm.min_ddb_alloc_uv);
PLANE_WM_ARGS(old_wm, min_ddb_alloc_uv),
PLANE_WM_ARGS(new_wm, min_ddb_alloc_uv));
}
#undef PLANE_WM_EN_FMT
#undef PLANE_WM_EN_ARGS
#undef PLANE_WM_FMT
#undef PLANE_WM_ARGS
static void
skl_print_wm_changes(struct intel_atomic_state *state)
{
@ -2997,8 +2946,9 @@ skl_compute_wm(struct intel_atomic_state *state)
* other crtcs can't be allowed to use the more optimal
* normal (ie. non-SAGV) watermarks.
*/
pipe_wm->use_sagv_wm = !HAS_HW_SAGV_WM(display) &&
DISPLAY_VER(display) >= 12 &&
pipe_wm->use_sagv_wm =
HAS_SAGV_WM(display) &&
!HAS_HW_SAGV_WM(display) &&
intel_crtc_can_enable_sagv(new_crtc_state);
ret = skl_wm_add_affected_planes(state, crtc);
@ -3064,7 +3014,7 @@ static void skl_pipe_wm_get_hw_state(struct intel_crtc *crtc,
val = intel_de_read(display, CUR_WM_SAGV_TRANS(pipe));
skl_wm_level_from_reg_val(display, val, &wm->sagv.trans_wm);
} else if (DISPLAY_VER(display) >= 12) {
} else if (HAS_SAGV_WM(display)) {
wm->sagv.wm0 = wm->wm[0];
wm->sagv.trans_wm = wm->trans_wm;
}
@ -3919,6 +3869,40 @@ void skl_wm_plane_disable_noatomic(struct intel_crtc *crtc,
sizeof(crtc_state->wm.skl.optimal.planes[plane->id]));
}
static void skl_wm_level_verify(struct intel_plane *plane,
const char *wm_name,
const struct skl_wm_level *hw_wm_level,
const struct skl_wm_level *sw_wm_level)
{
struct intel_display *display = to_intel_display(plane);
if (skl_wm_level_equals(hw_wm_level, sw_wm_level))
return;
drm_err(display->drm,
"[PLANE:%d:%s] mismatch in %s (expected e=%d b=%u l=%u, got e=%d b=%u l=%u)\n",
plane->base.base.id, plane->base.name, wm_name,
sw_wm_level->enable, sw_wm_level->blocks, sw_wm_level->lines,
hw_wm_level->enable, hw_wm_level->blocks, hw_wm_level->lines);
}
static void skl_ddb_entry_verify(struct intel_plane *plane,
const char *ddb_name,
const struct skl_ddb_entry *hw_ddb_entry,
const struct skl_ddb_entry *sw_ddb_entry)
{
struct intel_display *display = to_intel_display(plane);
if (skl_ddb_entry_equal(hw_ddb_entry, sw_ddb_entry))
return;
drm_err(display->drm,
"[PLANE:%d:%s] mismatch in %s (expected (%u,%u), found (%u,%u))\n",
plane->base.base.id, plane->base.name, ddb_name,
sw_ddb_entry->start, sw_ddb_entry->end,
hw_ddb_entry->start, hw_ddb_entry->end);
}
void intel_wm_state_verify(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
@ -3958,86 +3942,42 @@ void intel_wm_state_verify(struct intel_atomic_state *state,
hw_enabled_slices);
for_each_intel_plane_on_crtc(display->drm, crtc, plane) {
const struct skl_ddb_entry *hw_ddb_entry, *sw_ddb_entry;
const struct skl_wm_level *hw_wm_level, *sw_wm_level;
const struct skl_plane_wm *hw_plane_wm =
&hw->wm.planes[plane->id];
const struct skl_plane_wm *sw_plane_wm =
&sw_wm->planes[plane->id];
/* Watermarks */
for (level = 0; level < display->wm.num_levels; level++) {
hw_wm_level = &hw->wm.planes[plane->id].wm[level];
sw_wm_level = skl_plane_wm_level(sw_wm, plane->id, level);
char wm_name[16];
if (skl_wm_level_equals(hw_wm_level, sw_wm_level))
continue;
snprintf(wm_name, sizeof(wm_name), "WM%d", level);
drm_err(display->drm,
"[PLANE:%d:%s] mismatch in WM%d (expected e=%d b=%u l=%u, got e=%d b=%u l=%u)\n",
plane->base.base.id, plane->base.name, level,
sw_wm_level->enable,
sw_wm_level->blocks,
sw_wm_level->lines,
hw_wm_level->enable,
hw_wm_level->blocks,
hw_wm_level->lines);
skl_wm_level_verify(plane, wm_name,
&hw_plane_wm->wm[level],
skl_plane_wm_level(sw_wm, plane->id, level));
}
hw_wm_level = &hw->wm.planes[plane->id].trans_wm;
sw_wm_level = skl_plane_trans_wm(sw_wm, plane->id);
skl_wm_level_verify(plane, "trans WM",
&hw_plane_wm->trans_wm,
skl_plane_trans_wm(sw_wm, plane->id));
if (!skl_wm_level_equals(hw_wm_level, sw_wm_level)) {
drm_err(display->drm,
"[PLANE:%d:%s] mismatch in trans WM (expected e=%d b=%u l=%u, got e=%d b=%u l=%u)\n",
plane->base.base.id, plane->base.name,
sw_wm_level->enable,
sw_wm_level->blocks,
sw_wm_level->lines,
hw_wm_level->enable,
hw_wm_level->blocks,
hw_wm_level->lines);
if (HAS_HW_SAGV_WM(display)) {
skl_wm_level_verify(plane, "SAGV WM",
&hw_plane_wm->sagv.wm0,
&sw_plane_wm->sagv.wm0);
skl_wm_level_verify(plane, "SAGV trans WM",
&hw_plane_wm->sagv.trans_wm,
&sw_plane_wm->sagv.trans_wm);
}
hw_wm_level = &hw->wm.planes[plane->id].sagv.wm0;
sw_wm_level = &sw_wm->planes[plane->id].sagv.wm0;
skl_ddb_entry_verify(plane, "DDB",
&hw->ddb[plane->id],
&new_crtc_state->wm.skl.plane_ddb[plane->id]);
if (HAS_HW_SAGV_WM(display) &&
!skl_wm_level_equals(hw_wm_level, sw_wm_level)) {
drm_err(display->drm,
"[PLANE:%d:%s] mismatch in SAGV WM (expected e=%d b=%u l=%u, got e=%d b=%u l=%u)\n",
plane->base.base.id, plane->base.name,
sw_wm_level->enable,
sw_wm_level->blocks,
sw_wm_level->lines,
hw_wm_level->enable,
hw_wm_level->blocks,
hw_wm_level->lines);
}
hw_wm_level = &hw->wm.planes[plane->id].sagv.trans_wm;
sw_wm_level = &sw_wm->planes[plane->id].sagv.trans_wm;
if (HAS_HW_SAGV_WM(display) &&
!skl_wm_level_equals(hw_wm_level, sw_wm_level)) {
drm_err(display->drm,
"[PLANE:%d:%s] mismatch in SAGV trans WM (expected e=%d b=%u l=%u, got e=%d b=%u l=%u)\n",
plane->base.base.id, plane->base.name,
sw_wm_level->enable,
sw_wm_level->blocks,
sw_wm_level->lines,
hw_wm_level->enable,
hw_wm_level->blocks,
hw_wm_level->lines);
}
/* DDB */
hw_ddb_entry = &hw->ddb[plane->id];
sw_ddb_entry = &new_crtc_state->wm.skl.plane_ddb[plane->id];
if (!skl_ddb_entry_equal(hw_ddb_entry, sw_ddb_entry)) {
drm_err(display->drm,
"[PLANE:%d:%s] mismatch in DDB (expected (%u,%u), found (%u,%u))\n",
plane->base.base.id, plane->base.name,
sw_ddb_entry->start, sw_ddb_entry->end,
hw_ddb_entry->start, hw_ddb_entry->end);
}
skl_ddb_entry_verify(plane, "DDB Y",
&hw->ddb_y[plane->id],
&new_crtc_state->wm.skl.plane_ddb_y[plane->id]);
}
kfree(hw);
@ -4055,7 +3995,7 @@ void skl_wm_init(struct intel_display *display)
skl_setup_wm_latency(display);
display->funcs.wm = &skl_wm_funcs;
display->wm.funcs = &skl_wm_funcs;
}
static int skl_watermark_ipc_status_show(struct seq_file *m, void *data)

View File

@ -22,11 +22,11 @@ int vlv_clock_get_hpll_vco(struct drm_device *drm)
int hpll_freq, vco_freq[] = { 800, 1600, 2000, 2400 };
if (!display->vlv_clock.hpll_freq) {
vlv_cck_get(drm);
vlv_cck_get(display);
/* Obtain SKU information */
hpll_freq = vlv_cck_read(drm, CCK_FUSE_REG) &
hpll_freq = vlv_cck_read(display, CCK_FUSE_REG) &
CCK_FUSE_HPLL_FREQ_MASK;
vlv_cck_put(drm);
vlv_cck_put(display);
display->vlv_clock.hpll_freq = vco_freq[hpll_freq] * 1000;
@ -39,12 +39,13 @@ int vlv_clock_get_hpll_vco(struct drm_device *drm)
static int vlv_clock_get_cck(struct drm_device *drm,
const char *name, u32 reg, int ref_freq)
{
struct intel_display *display = to_intel_display(drm);
u32 val;
int divider;
vlv_cck_get(drm);
val = vlv_cck_read(drm, reg);
vlv_cck_put(drm);
vlv_cck_get(display);
val = vlv_cck_read(display, reg);
vlv_cck_put(display);
divider = val & CCK_FREQUENCY_VALUES;

View File

@ -254,16 +254,16 @@ static int dpi_send_cmd(struct intel_dsi *intel_dsi, u32 cmd, bool hs,
static void band_gap_reset(struct intel_display *display)
{
vlv_flisdsi_get(display->drm);
vlv_flisdsi_get(display);
vlv_flisdsi_write(display->drm, 0x08, 0x0001);
vlv_flisdsi_write(display->drm, 0x0F, 0x0005);
vlv_flisdsi_write(display->drm, 0x0F, 0x0025);
vlv_flisdsi_write(display, 0x08, 0x0001);
vlv_flisdsi_write(display, 0x0F, 0x0005);
vlv_flisdsi_write(display, 0x0F, 0x0025);
udelay(150);
vlv_flisdsi_write(display->drm, 0x0F, 0x0000);
vlv_flisdsi_write(display->drm, 0x08, 0x0000);
vlv_flisdsi_write(display, 0x0F, 0x0000);
vlv_flisdsi_write(display, 0x08, 0x0000);
vlv_flisdsi_put(display->drm);
vlv_flisdsi_put(display);
}
static int intel_dsi_compute_config(struct intel_encoder *encoder,
@ -461,11 +461,11 @@ static void vlv_dsi_device_ready(struct intel_encoder *encoder)
drm_dbg_kms(display->drm, "\n");
vlv_flisdsi_get(display->drm);
vlv_flisdsi_get(display);
/* program rcomp for compliance, reduce from 50 ohms to 45 ohms
* needed everytime after power gate */
vlv_flisdsi_write(display->drm, 0x04, 0x0004);
vlv_flisdsi_put(display->drm);
vlv_flisdsi_write(display, 0x04, 0x0004);
vlv_flisdsi_put(display);
/* bandgap reset is needed after everytime we do power gate */
band_gap_reset(display);

View File

@ -219,11 +219,11 @@ void vlv_dsi_pll_enable(struct intel_encoder *encoder,
drm_dbg_kms(display->drm, "\n");
vlv_cck_get(display->drm);
vlv_cck_get(display);
vlv_cck_write(display->drm, CCK_REG_DSI_PLL_CONTROL, 0);
vlv_cck_write(display->drm, CCK_REG_DSI_PLL_DIVIDER, config->dsi_pll.div);
vlv_cck_write(display->drm, CCK_REG_DSI_PLL_CONTROL,
vlv_cck_write(display, CCK_REG_DSI_PLL_CONTROL, 0);
vlv_cck_write(display, CCK_REG_DSI_PLL_DIVIDER, config->dsi_pll.div);
vlv_cck_write(display, CCK_REG_DSI_PLL_CONTROL,
config->dsi_pll.ctrl & ~DSI_PLL_VCO_EN);
/* wait at least 0.5 us after ungating before enabling VCO,
@ -231,17 +231,17 @@ void vlv_dsi_pll_enable(struct intel_encoder *encoder,
*/
usleep_range(10, 50);
vlv_cck_write(display->drm, CCK_REG_DSI_PLL_CONTROL, config->dsi_pll.ctrl);
vlv_cck_write(display, CCK_REG_DSI_PLL_CONTROL, config->dsi_pll.ctrl);
ret = poll_timeout_us(val = vlv_cck_read(display->drm, CCK_REG_DSI_PLL_CONTROL),
ret = poll_timeout_us(val = vlv_cck_read(display, CCK_REG_DSI_PLL_CONTROL),
val & DSI_PLL_LOCK,
500, 20 * 1000, false);
if (ret) {
vlv_cck_put(display->drm);
vlv_cck_put(display);
drm_err(display->drm, "DSI PLL lock failed\n");
return;
}
vlv_cck_put(display->drm);
vlv_cck_put(display);
drm_dbg_kms(display->drm, "DSI PLL locked\n");
}
@ -253,14 +253,14 @@ void vlv_dsi_pll_disable(struct intel_encoder *encoder)
drm_dbg_kms(display->drm, "\n");
vlv_cck_get(display->drm);
vlv_cck_get(display);
tmp = vlv_cck_read(display->drm, CCK_REG_DSI_PLL_CONTROL);
tmp = vlv_cck_read(display, CCK_REG_DSI_PLL_CONTROL);
tmp &= ~DSI_PLL_VCO_EN;
tmp |= DSI_PLL_LDO_GATE;
vlv_cck_write(display->drm, CCK_REG_DSI_PLL_CONTROL, tmp);
vlv_cck_write(display, CCK_REG_DSI_PLL_CONTROL, tmp);
vlv_cck_put(display->drm);
vlv_cck_put(display);
}
static bool has_dsic_clock(struct intel_display *display)
@ -333,10 +333,10 @@ u32 vlv_dsi_get_pclk(struct intel_encoder *encoder,
drm_dbg_kms(display->drm, "\n");
vlv_cck_get(display->drm);
pll_ctl = vlv_cck_read(display->drm, CCK_REG_DSI_PLL_CONTROL);
pll_div = vlv_cck_read(display->drm, CCK_REG_DSI_PLL_DIVIDER);
vlv_cck_put(display->drm);
vlv_cck_get(display);
pll_ctl = vlv_cck_read(display, CCK_REG_DSI_PLL_CONTROL);
pll_div = vlv_cck_read(display, CCK_REG_DSI_PLL_DIVIDER);
vlv_cck_put(display);
config->dsi_pll.ctrl = pll_ctl & ~DSI_PLL_LOCK;
config->dsi_pll.div = pll_div;
@ -603,9 +603,9 @@ static void assert_dsi_pll(struct intel_display *display, bool state)
{
bool cur_state;
vlv_cck_get(display->drm);
cur_state = vlv_cck_read(display->drm, CCK_REG_DSI_PLL_CONTROL) & DSI_PLL_VCO_EN;
vlv_cck_put(display->drm);
vlv_cck_get(display);
cur_state = vlv_cck_read(display, CCK_REG_DSI_PLL_CONTROL) & DSI_PLL_VCO_EN;
vlv_cck_put(display);
INTEL_DISPLAY_STATE_WARN(display, cur_state != state,
"DSI PLL state assertion failure (expected %s, current %s)\n",

View File

@ -6,8 +6,74 @@
#include "intel_display_core.h"
#include "intel_display_types.h"
#include "intel_dpio_phy.h"
#include "intel_parent.h"
#include "vlv_sideband.h"
void vlv_bunit_get(struct intel_display *display)
{
intel_parent_vlv_iosf_get(display, BIT(VLV_IOSF_SB_BUNIT));
}
u32 vlv_bunit_read(struct intel_display *display, u32 reg)
{
return intel_parent_vlv_iosf_read(display, VLV_IOSF_SB_BUNIT, reg);
}
void vlv_bunit_write(struct intel_display *display, u32 reg, u32 val)
{
intel_parent_vlv_iosf_write(display, VLV_IOSF_SB_BUNIT, reg, val);
}
void vlv_bunit_put(struct intel_display *display)
{
intel_parent_vlv_iosf_put(display, BIT(VLV_IOSF_SB_BUNIT));
}
void vlv_cck_get(struct intel_display *display)
{
intel_parent_vlv_iosf_get(display, BIT(VLV_IOSF_SB_CCK));
}
u32 vlv_cck_read(struct intel_display *display, u32 reg)
{
return intel_parent_vlv_iosf_read(display, VLV_IOSF_SB_CCK, reg);
}
void vlv_cck_write(struct intel_display *display, u32 reg, u32 val)
{
intel_parent_vlv_iosf_write(display, VLV_IOSF_SB_CCK, reg, val);
}
void vlv_cck_put(struct intel_display *display)
{
intel_parent_vlv_iosf_put(display, BIT(VLV_IOSF_SB_CCK));
}
void vlv_ccu_get(struct intel_display *display)
{
intel_parent_vlv_iosf_get(display, BIT(VLV_IOSF_SB_CCU));
}
u32 vlv_ccu_read(struct intel_display *display, u32 reg)
{
return intel_parent_vlv_iosf_read(display, VLV_IOSF_SB_CCU, reg);
}
void vlv_ccu_write(struct intel_display *display, u32 reg, u32 val)
{
intel_parent_vlv_iosf_write(display, VLV_IOSF_SB_CCU, reg, val);
}
void vlv_ccu_put(struct intel_display *display)
{
intel_parent_vlv_iosf_put(display, BIT(VLV_IOSF_SB_CCU));
}
void vlv_dpio_get(struct intel_display *display)
{
intel_parent_vlv_iosf_get(display, BIT(VLV_IOSF_SB_DPIO) | BIT(VLV_IOSF_SB_DPIO_2));
}
static enum vlv_iosf_sb_unit vlv_dpio_phy_to_unit(struct intel_display *display,
enum dpio_phy phy)
{
@ -21,13 +87,12 @@ static enum vlv_iosf_sb_unit vlv_dpio_phy_to_unit(struct intel_display *display,
return VLV_IOSF_SB_DPIO;
}
u32 vlv_dpio_read(struct drm_device *drm, enum dpio_phy phy, int reg)
u32 vlv_dpio_read(struct intel_display *display, enum dpio_phy phy, int reg)
{
struct intel_display *display = to_intel_display(drm);
enum vlv_iosf_sb_unit unit = vlv_dpio_phy_to_unit(display, phy);
u32 val;
val = vlv_iosf_sb_read(drm, unit, reg);
val = intel_parent_vlv_iosf_read(display, unit, reg);
/*
* FIXME: There might be some registers where all 1's is a valid value,
@ -40,11 +105,70 @@ u32 vlv_dpio_read(struct drm_device *drm, enum dpio_phy phy, int reg)
return val;
}
void vlv_dpio_write(struct drm_device *drm,
void vlv_dpio_write(struct intel_display *display,
enum dpio_phy phy, int reg, u32 val)
{
struct intel_display *display = to_intel_display(drm);
enum vlv_iosf_sb_unit unit = vlv_dpio_phy_to_unit(display, phy);
vlv_iosf_sb_write(drm, unit, reg, val);
intel_parent_vlv_iosf_write(display, unit, reg, val);
}
void vlv_dpio_put(struct intel_display *display)
{
intel_parent_vlv_iosf_put(display, BIT(VLV_IOSF_SB_DPIO) | BIT(VLV_IOSF_SB_DPIO_2));
}
void vlv_flisdsi_get(struct intel_display *display)
{
intel_parent_vlv_iosf_get(display, BIT(VLV_IOSF_SB_FLISDSI));
}
u32 vlv_flisdsi_read(struct intel_display *display, u32 reg)
{
return intel_parent_vlv_iosf_read(display, VLV_IOSF_SB_FLISDSI, reg);
}
void vlv_flisdsi_write(struct intel_display *display, u32 reg, u32 val)
{
intel_parent_vlv_iosf_write(display, VLV_IOSF_SB_FLISDSI, reg, val);
}
void vlv_flisdsi_put(struct intel_display *display)
{
intel_parent_vlv_iosf_put(display, BIT(VLV_IOSF_SB_FLISDSI));
}
void vlv_nc_get(struct intel_display *display)
{
intel_parent_vlv_iosf_get(display, BIT(VLV_IOSF_SB_NC));
}
u32 vlv_nc_read(struct intel_display *display, u8 addr)
{
return intel_parent_vlv_iosf_read(display, VLV_IOSF_SB_NC, addr);
}
void vlv_nc_put(struct intel_display *display)
{
intel_parent_vlv_iosf_put(display, BIT(VLV_IOSF_SB_NC));
}
void vlv_punit_get(struct intel_display *display)
{
intel_parent_vlv_iosf_get(display, BIT(VLV_IOSF_SB_PUNIT));
}
u32 vlv_punit_read(struct intel_display *display, u32 addr)
{
return intel_parent_vlv_iosf_read(display, VLV_IOSF_SB_PUNIT, addr);
}
int vlv_punit_write(struct intel_display *display, u32 addr, u32 val)
{
return intel_parent_vlv_iosf_write(display, VLV_IOSF_SB_PUNIT, addr, val);
}
void vlv_punit_put(struct intel_display *display)
{
intel_parent_vlv_iosf_put(display, BIT(VLV_IOSF_SB_PUNIT));
}

View File

@ -4,153 +4,45 @@
#ifndef _VLV_SIDEBAND_H_
#define _VLV_SIDEBAND_H_
#include <linux/bitops.h>
#include <linux/types.h>
#include "vlv_iosf_sb.h"
#include "vlv_iosf_sb_reg.h"
#include <drm/intel/vlv_iosf_sb_regs.h>
enum dpio_phy;
struct drm_device;
struct intel_display;
static inline void vlv_bunit_get(struct drm_device *drm)
{
vlv_iosf_sb_get(drm, BIT(VLV_IOSF_SB_BUNIT));
}
void vlv_bunit_get(struct intel_display *display);
u32 vlv_bunit_read(struct intel_display *display, u32 reg);
void vlv_bunit_write(struct intel_display *display, u32 reg, u32 val);
void vlv_bunit_put(struct intel_display *display);
static inline u32 vlv_bunit_read(struct drm_device *drm, u32 reg)
{
return vlv_iosf_sb_read(drm, VLV_IOSF_SB_BUNIT, reg);
}
void vlv_cck_get(struct intel_display *display);
u32 vlv_cck_read(struct intel_display *display, u32 reg);
void vlv_cck_write(struct intel_display *display, u32 reg, u32 val);
void vlv_cck_put(struct intel_display *display);
static inline void vlv_bunit_write(struct drm_device *drm, u32 reg, u32 val)
{
vlv_iosf_sb_write(drm, VLV_IOSF_SB_BUNIT, reg, val);
}
void vlv_ccu_get(struct intel_display *display);
u32 vlv_ccu_read(struct intel_display *display, u32 reg);
void vlv_ccu_write(struct intel_display *display, u32 reg, u32 val);
void vlv_ccu_put(struct intel_display *display);
static inline void vlv_bunit_put(struct drm_device *drm)
{
vlv_iosf_sb_put(drm, BIT(VLV_IOSF_SB_BUNIT));
}
void vlv_dpio_get(struct intel_display *display);
u32 vlv_dpio_read(struct intel_display *display, enum dpio_phy phy, int reg);
void vlv_dpio_write(struct intel_display *display, enum dpio_phy phy, int reg, u32 val);
void vlv_dpio_put(struct intel_display *display);
static inline void vlv_cck_get(struct drm_device *drm)
{
vlv_iosf_sb_get(drm, BIT(VLV_IOSF_SB_CCK));
}
void vlv_flisdsi_get(struct intel_display *display);
u32 vlv_flisdsi_read(struct intel_display *display, u32 reg);
void vlv_flisdsi_write(struct intel_display *display, u32 reg, u32 val);
void vlv_flisdsi_put(struct intel_display *display);
static inline u32 vlv_cck_read(struct drm_device *drm, u32 reg)
{
return vlv_iosf_sb_read(drm, VLV_IOSF_SB_CCK, reg);
}
void vlv_nc_get(struct intel_display *display);
u32 vlv_nc_read(struct intel_display *display, u8 addr);
void vlv_nc_put(struct intel_display *display);
static inline void vlv_cck_write(struct drm_device *drm, u32 reg, u32 val)
{
vlv_iosf_sb_write(drm, VLV_IOSF_SB_CCK, reg, val);
}
static inline void vlv_cck_put(struct drm_device *drm)
{
vlv_iosf_sb_put(drm, BIT(VLV_IOSF_SB_CCK));
}
static inline void vlv_ccu_get(struct drm_device *drm)
{
vlv_iosf_sb_get(drm, BIT(VLV_IOSF_SB_CCU));
}
static inline u32 vlv_ccu_read(struct drm_device *drm, u32 reg)
{
return vlv_iosf_sb_read(drm, VLV_IOSF_SB_CCU, reg);
}
static inline void vlv_ccu_write(struct drm_device *drm, u32 reg, u32 val)
{
vlv_iosf_sb_write(drm, VLV_IOSF_SB_CCU, reg, val);
}
static inline void vlv_ccu_put(struct drm_device *drm)
{
vlv_iosf_sb_put(drm, BIT(VLV_IOSF_SB_CCU));
}
static inline void vlv_dpio_get(struct drm_device *drm)
{
vlv_iosf_sb_get(drm, BIT(VLV_IOSF_SB_DPIO) | BIT(VLV_IOSF_SB_DPIO_2));
}
#ifdef I915
u32 vlv_dpio_read(struct drm_device *drm, enum dpio_phy phy, int reg);
void vlv_dpio_write(struct drm_device *drm,
enum dpio_phy phy, int reg, u32 val);
#else
static inline u32 vlv_dpio_read(struct drm_device *drm, int phy, int reg)
{
return 0;
}
static inline void vlv_dpio_write(struct drm_device *drm,
int phy, int reg, u32 val)
{
}
#endif
static inline void vlv_dpio_put(struct drm_device *drm)
{
vlv_iosf_sb_put(drm, BIT(VLV_IOSF_SB_DPIO) | BIT(VLV_IOSF_SB_DPIO_2));
}
static inline void vlv_flisdsi_get(struct drm_device *drm)
{
vlv_iosf_sb_get(drm, BIT(VLV_IOSF_SB_FLISDSI));
}
static inline u32 vlv_flisdsi_read(struct drm_device *drm, u32 reg)
{
return vlv_iosf_sb_read(drm, VLV_IOSF_SB_FLISDSI, reg);
}
static inline void vlv_flisdsi_write(struct drm_device *drm, u32 reg, u32 val)
{
vlv_iosf_sb_write(drm, VLV_IOSF_SB_FLISDSI, reg, val);
}
static inline void vlv_flisdsi_put(struct drm_device *drm)
{
vlv_iosf_sb_put(drm, BIT(VLV_IOSF_SB_FLISDSI));
}
static inline void vlv_nc_get(struct drm_device *drm)
{
vlv_iosf_sb_get(drm, BIT(VLV_IOSF_SB_NC));
}
static inline u32 vlv_nc_read(struct drm_device *drm, u8 addr)
{
return vlv_iosf_sb_read(drm, VLV_IOSF_SB_NC, addr);
}
static inline void vlv_nc_put(struct drm_device *drm)
{
vlv_iosf_sb_put(drm, BIT(VLV_IOSF_SB_NC));
}
static inline void vlv_punit_get(struct drm_device *drm)
{
vlv_iosf_sb_get(drm, BIT(VLV_IOSF_SB_PUNIT));
}
static inline u32 vlv_punit_read(struct drm_device *drm, u32 addr)
{
return vlv_iosf_sb_read(drm, VLV_IOSF_SB_PUNIT, addr);
}
static inline int vlv_punit_write(struct drm_device *drm, u32 addr, u32 val)
{
return vlv_iosf_sb_write(drm, VLV_IOSF_SB_PUNIT, addr, val);
}
static inline void vlv_punit_put(struct drm_device *drm)
{
vlv_iosf_sb_put(drm, BIT(VLV_IOSF_SB_PUNIT));
}
void vlv_punit_get(struct intel_display *display);
u32 vlv_punit_read(struct intel_display *display, u32 addr);
int vlv_punit_write(struct intel_display *display, u32 addr, u32 val);
void vlv_punit_put(struct intel_display *display);
#endif /* _VLV_SIDEBAND_H_ */

View File

@ -10,6 +10,8 @@
#include <drm/drm_print.h>
#include <drm/intel/display_parent_interface.h>
#include <drm/intel/i915_drm.h>
#include <drm/intel/mchbar_regs.h>
#include <drm/intel/pci_config.h>
#include "gem/i915_gem_lmem.h"
#include "gem/i915_gem_region.h"
@ -23,8 +25,6 @@
#include "i915_reg.h"
#include "i915_utils.h"
#include "i915_vgpu.h"
#include "intel_mchbar_regs.h"
#include "intel_pci_config.h"
struct intel_stolen_node {
struct drm_i915_private *i915;

View File

@ -12,6 +12,7 @@
#include <drm/drm_print.h>
#include <drm/intel/i915_drm.h>
#include <drm/intel/intel-gtt.h>
#include <drm/intel/pci_config.h>
#include "gem/i915_gem_lmem.h"
@ -20,7 +21,6 @@
#include "intel_gpu_commands.h"
#include "intel_gt.h"
#include "intel_gt_regs.h"
#include "intel_pci_config.h"
#include "intel_ring.h"
#include "i915_drv.h"
#include "i915_pci.h"

View File

@ -7,6 +7,7 @@
#include <drm/drm_print.h>
#include <drm/intel/intel_gmd_misc_regs.h>
#include <drm/intel/mchbar_regs.h>
#include "display/intel_display.h"
#include "i915_drv.h"
@ -15,7 +16,6 @@
#include "i915_pvinfo.h"
#include "i915_vgpu.h"
#include "intel_gt_regs.h"
#include "intel_mchbar_regs.h"
/**
* DOC: fence register handling

View File

@ -6,6 +6,7 @@
#include <drm/drm_managed.h>
#include <drm/intel/intel-gtt.h>
#include <drm/intel/intel_gmd_interrupt_regs.h>
#include <drm/intel/pci_config.h>
#include "gem/i915_gem_internal.h"
#include "gem/i915_gem_lmem.h"
@ -28,7 +29,6 @@
#include "intel_gt_requests.h"
#include "intel_migrate.h"
#include "intel_mocs.h"
#include "intel_pci_config.h"
#include "intel_rc6.h"
#include "intel_renderstate.h"
#include "intel_rps.h"

View File

@ -19,7 +19,6 @@
#include "intel_gt_pm_debugfs.h"
#include "intel_gt_regs.h"
#include "intel_llc.h"
#include "intel_mchbar_regs.h"
#include "intel_pcode.h"
#include "intel_rc6.h"
#include "intel_rps.h"

View File

@ -7,12 +7,12 @@
#include <linux/cpufreq.h>
#include <drm/intel/intel_pcode_regs.h>
#include <drm/intel/mchbar_regs.h>
#include "i915_drv.h"
#include "i915_reg.h"
#include "intel_gt.h"
#include "intel_llc.h"
#include "intel_mchbar_regs.h"
#include "intel_pcode.h"
#include "intel_rps.h"

View File

@ -4,12 +4,12 @@
*/
#include <drm/drm_print.h>
#include <drm/intel/pci_config.h>
#include "i915_drv.h"
#include "i915_pci.h"
#include "i915_reg.h"
#include "intel_memory_region.h"
#include "intel_pci_config.h"
#include "intel_region_lmem.h"
#include "intel_region_ttm.h"
#include "gem/i915_gem_lmem.h"

View File

@ -7,6 +7,9 @@
#include <linux/stop_machine.h>
#include <linux/string_helpers.h>
#include <drm/intel/mchbar_regs.h>
#include <drm/intel/pci_config.h>
#include "display/intel_display_reset.h"
#include "display/intel_overlay.h"
#include "gem/i915_gem_context.h"
@ -27,8 +30,6 @@
#include "intel_gt_pm.h"
#include "intel_gt_print.h"
#include "intel_gt_requests.h"
#include "intel_mchbar_regs.h"
#include "intel_pci_config.h"
#include "intel_reset.h"
#define RESET_MAX_RETRIES 3
@ -966,6 +967,7 @@ static void nop_submit_request(struct i915_request *request)
static void __intel_gt_set_wedged(struct intel_gt *gt)
{
struct intel_display *display = gt->i915->display;
struct intel_engine_cs *engine;
intel_engine_mask_t awake;
enum intel_engine_id id;
@ -983,7 +985,8 @@ static void __intel_gt_set_wedged(struct intel_gt *gt)
awake = reset_prepare(gt);
/* Even if the GPU reset fails, it should still stop the engines */
if (!intel_gt_gpu_reset_clobbers_display(gt))
if (!intel_gt_gpu_reset_clobbers_display(gt) &&
!intel_display_reset_test(display))
intel_gt_reset_all_engines(gt);
for_each_engine(engine, gt, id)
@ -1397,11 +1400,6 @@ int intel_engine_reset(struct intel_engine_cs *engine, const char *msg)
return err;
}
static void display_reset_modeset_stuck(void *gt)
{
intel_gt_set_wedged(gt);
}
static void intel_gt_reset_global(struct intel_gt *gt,
u32 engine_mask,
const char *reason)
@ -1424,16 +1422,25 @@ static void intel_gt_reset_global(struct intel_gt *gt,
bool need_display_reset;
bool reset_display;
need_display_reset = intel_gt_gpu_reset_clobbers_display(gt) &&
need_display_reset =
intel_display_reset_supported(display) &&
intel_gt_gpu_reset_clobbers_display(gt) &&
intel_has_gpu_reset(gt);
reset_display = intel_display_reset_test(display) ||
reset_display =
intel_display_reset_test(display) ||
need_display_reset;
if (reset_display)
reset_display = intel_display_reset_prepare(display,
display_reset_modeset_stuck,
gt);
if (reset_display) {
if (atomic_read(&i915->pending_fb_pin)) {
drm_dbg_kms(&i915->drm,
"Modeset potentially stuck, unbreaking through wedging\n");
intel_gt_set_wedged(gt);
}
intel_display_reset_prepare(display);
}
intel_gt_reset(gt, engine_mask, reason);
@ -1501,9 +1508,10 @@ void intel_gt_handle_error(struct intel_gt *gt,
/*
* Try engine reset when available. We fall back to full reset if
* single reset fails.
* single reset fails. Display reset test needs a full reset.
*/
if (!intel_uc_uses_guc_submission(&gt->uc) &&
if (!intel_display_reset_test(gt->i915->display) &&
!intel_uc_uses_guc_submission(&gt->uc) &&
intel_has_reset_engine(gt) && !intel_gt_is_wedged(gt)) {
local_bh_disable();
for_each_engine_masked(engine, gt, engine_mask, tmp) {

View File

@ -5,9 +5,10 @@
#include <linux/string_helpers.h>
#include <drm/intel/i915_drm.h>
#include <drm/intel/display_parent_interface.h>
#include <drm/intel/i915_drm.h>
#include <drm/intel/intel_pcode_regs.h>
#include <drm/intel/mchbar_regs.h>
#include "display/intel_display_rps.h"
#include "display/vlv_clock.h"
@ -25,7 +26,6 @@
#include "intel_gt_pm_irq.h"
#include "intel_gt_print.h"
#include "intel_gt_regs.h"
#include "intel_mchbar_regs.h"
#include "intel_pcode.h"
#include "intel_rps.h"
#include "vlv_iosf_sb.h"

View File

@ -16,7 +16,6 @@
#include "i915_wait_util.h"
#include "intel_guc_print.h"
#include "intel_guc_slpc.h"
#include "intel_mchbar_regs.h"
/**
* DOC: SLPC - Dynamic Frequency management

View File

@ -32,10 +32,10 @@
*/
#include <drm/drm_print.h>
#include <drm/intel/pci_config.h>
#include "gvt.h"
#include "i915_drv.h"
#include "intel_pci_config.h"
enum {
INTEL_GVT_PCI_BAR_GTTMMIO = 0,

View File

@ -71,7 +71,6 @@
#include "i915_drv.h"
#include "i915_pvinfo.h"
#include "i915_reg.h"
#include "intel_mchbar_regs.h"
#include "sched_policy.h"
/* XXX FIXME i915 has changed PP_XXX definition */

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