Core Changes:

- drm/print: add drm_print_hex_dump()
 
 Driver Changes:
  - HDCP fixes and updates for Xe3lpd and for HDCP 1.4 (Suraj)
  - Add dedicated lock for each sideband (Jani)
  - New GSC FW for ARL-H and ARL-U (Daniele)
  - Add support for 3 VDSC engines 12 slices (Ankit)
  - Sanitize MBUS joining (Ville)
  - Fixes in DP MST (Imre)
  - Stop using pixel_format_from_register_bits() to parse VBT (Ville)
  - Declutter CDCLK code (Ville)
  - PSR clean up and fixes (Jouni, Jani, Animesh)
  - DMC wakelock - Fixes and enablement for Xe3_LPD (Gustavo)
  - Demote source OUI read/write failure logging to debug (Jani)
  - Potential boot oops fix and some general cleanups (Ville)
  - Scaler code cleanups (Ville)
  - More conversion towards struct intel_display and general cleanups (Jani)
  - Limit max compressed bpp to 18 when forcing DSC (Ankit)
  - Start to reconcile i915's and xe's display power mgt sequences (Rodrigo)
  - Some correction in the DP Link Training sequence (Arun)
  - Avoid setting YUV420_MODE in PIPE_MISC on Xe3lpd (Ankit)
  - MST and DDI cleanups and refactoring (Jani)
  - Fixed an typo in i915_gem_gtt.c (Zhang)
  - Try to make DPT shrinkable again (Ville)
  - Try to fix CPU MMIO fails during legacy LUT updates (Ville)
  - Some PPS cleanups (Ville, Jani)
  - Use seq buf for printing rates (Jani)
  - Flush DMC wakelock release work at the end of runtime suspend (Gustavo)
  - Fix NULL pointer dereference in capture_engine (Eugene)
  - Fix memory leak by correcting cache object name in error handler (Jiasheng)
  - Small refactor in WM/DPKGC for modifying latency programmed into PKG_C_LATENCY (Suraj)
  - Add drm_printer based hex dumper and use it (Jani)
  - Move g4x code to specific g4x functions (Jani)
 -----BEGIN PGP SIGNATURE-----
 
 iQEzBAABCAAdFiEEbSBwaO7dZQkcLOKj+mJfZA7rE8oFAmdZ92YACgkQ+mJfZA7r
 E8pSlQf+O3NYEw4F0Y8FSTY0rlG0WO+0p5fjrVipfkj3DOe+Z8uYyghrYwGqyIX9
 GRcd4GLYiGNxToSfLY5B0+fQtF16S0L2dtAJ1sOFhG1HdVmV+1pzQs63ZRAyr4xc
 NrPMLKOef1GvtOUaSxqDUmvrK8yiJevmYosjopFgzQjkiFOkK0WAErZVwBZypLKz
 UYL1JOeStp9jG1ZEPNAfavIn/Ldquem1vjPZvLGwAfP/Sf/VxJDtabXHeXog+zf/
 9pfrYvLLHStAMUJUIenfJr86W22Y4b7mvQFVuz25a/fIacd+9NaRKUqkltHE0/2o
 aXPNMI31BiN++yJwoeQIY4HlMZMBgw==
 =rw4n
 -----END PGP SIGNATURE-----

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

Core Changes:
 - drm/print: add drm_print_hex_dump()

Driver Changes:
 - HDCP fixes and updates for Xe3lpd and for HDCP 1.4 (Suraj)
 - Add dedicated lock for each sideband (Jani)
 - New GSC FW for ARL-H and ARL-U (Daniele)
 - Add support for 3 VDSC engines 12 slices (Ankit)
 - Sanitize MBUS joining (Ville)
 - Fixes in DP MST (Imre)
 - Stop using pixel_format_from_register_bits() to parse VBT (Ville)
 - Declutter CDCLK code (Ville)
 - PSR clean up and fixes (Jouni, Jani, Animesh)
 - DMC wakelock - Fixes and enablement for Xe3_LPD (Gustavo)
 - Demote source OUI read/write failure logging to debug (Jani)
 - Potential boot oops fix and some general cleanups (Ville)
 - Scaler code cleanups (Ville)
 - More conversion towards struct intel_display and general cleanups (Jani)
 - Limit max compressed bpp to 18 when forcing DSC (Ankit)
 - Start to reconcile i915's and xe's display power mgt sequences (Rodrigo)
 - Some correction in the DP Link Training sequence (Arun)
 - Avoid setting YUV420_MODE in PIPE_MISC on Xe3lpd (Ankit)
 - MST and DDI cleanups and refactoring (Jani)
 - Fixed an typo in i915_gem_gtt.c (Zhang)
 - Try to make DPT shrinkable again (Ville)
 - Try to fix CPU MMIO fails during legacy LUT updates (Ville)
 - Some PPS cleanups (Ville, Jani)
 - Use seq buf for printing rates (Jani)
 - Flush DMC wakelock release work at the end of runtime suspend (Gustavo)
 - Fix NULL pointer dereference in capture_engine (Eugene)
 - Fix memory leak by correcting cache object name in error handler (Jiasheng)
 - Small refactor in WM/DPKGC for modifying latency programmed into PKG_C_LATENCY (Suraj)
 - Add drm_printer based hex dumper and use it (Jani)
 - Move g4x code to specific g4x functions (Jani)

Signed-off-by: Simona Vetter <simona.vetter@ffwll.ch>
From: Rodrigo Vivi <rodrigo.vivi@intel.com>
[sima: conflict in intel_dp_mst.c due to conversion to
drm_connector_dynamic_init that landed through drm-misc]
Link: https://patchwork.freedesktop.org/patch/msgid/Z1n4VhatZpvT5xKs@intel.com
This commit is contained in:
Simona Vetter 2025-01-07 16:51:19 +01:00
commit 9cc06dbaf4
112 changed files with 4158 additions and 3444 deletions

@ -390,3 +390,26 @@ void drm_print_regset32(struct drm_printer *p, struct debugfs_regset32 *regset)
}
}
EXPORT_SYMBOL(drm_print_regset32);
/**
* drm_print_hex_dump - print a hex dump to a &drm_printer stream
* @p: The &drm_printer
* @prefix: Prefix for each line, may be NULL for no prefix
* @buf: Buffer to dump
* @len: Length of buffer
*
* Print hex dump to &drm_printer, with 16 space-separated hex bytes per line,
* optionally with a prefix on each line. No separator is added after prefix.
*/
void drm_print_hex_dump(struct drm_printer *p, const char *prefix,
const u8 *buf, size_t len)
{
int i;
for (i = 0; i < len; i += 16) {
int bytes_per_line = min(16, len - i);
drm_printf(p, "%s%*ph\n", prefix ?: "", bytes_per_line, buf + i);
}
}
EXPORT_SYMBOL(drm_print_hex_dump);

@ -30,7 +30,6 @@ i915-y += \
i915_params.o \
i915_pci.o \
i915_scatterlist.o \
i915_suspend.o \
i915_switcheroo.o \
i915_sysfs.o \
i915_utils.o \
@ -220,6 +219,7 @@ i915-$(CONFIG_HWMON) += \
i915-y += \
display/hsw_ips.o \
display/i9xx_plane.o \
display/i9xx_display_sr.o \
display/i9xx_wm.o \
display/intel_alpm.o \
display/intel_atomic.o \

@ -55,8 +55,8 @@ const struct dpll *vlv_get_dpll(struct drm_i915_private *i915)
return IS_CHERRYVIEW(i915) ? &chv_dpll[0] : &vlv_dpll[0];
}
void g4x_dp_set_clock(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config)
static void g4x_dp_set_clock(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config)
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
const struct dpll *divisor = NULL;
@ -1223,6 +1223,25 @@ static bool ilk_digital_port_connected(struct intel_encoder *encoder)
return intel_de_read(display, DEISR) & bit;
}
static int g4x_dp_compute_config(struct intel_encoder *encoder,
struct intel_crtc_state *crtc_state,
struct drm_connector_state *conn_state)
{
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
int ret;
if (HAS_PCH_SPLIT(i915) && encoder->port != PORT_A)
crtc_state->has_pch_encoder = true;
ret = intel_dp_compute_config(encoder, crtc_state, conn_state);
if (ret)
return ret;
g4x_dp_set_clock(encoder, crtc_state);
return 0;
}
static void g4x_dp_suspend_complete(struct intel_encoder *encoder)
{
/*
@ -1307,7 +1326,7 @@ bool g4x_dp_init(struct drm_i915_private *dev_priv,
intel_encoder_link_check_init(intel_encoder, intel_dp_link_check);
intel_encoder->hotplug = intel_dp_hotplug;
intel_encoder->compute_config = intel_dp_compute_config;
intel_encoder->compute_config = g4x_dp_compute_config;
intel_encoder->get_hw_state = intel_dp_get_hw_state;
intel_encoder->get_config = intel_dp_get_config;
intel_encoder->sync_state = intel_dp_sync_state;

@ -19,8 +19,6 @@ struct intel_encoder;
#ifdef I915
const struct dpll *vlv_get_dpll(struct drm_i915_private *i915);
void g4x_dp_set_clock(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config);
bool g4x_dp_port_enabled(struct drm_i915_private *dev_priv,
i915_reg_t dp_reg, enum port port,
enum pipe *pipe);
@ -31,10 +29,6 @@ static inline const struct dpll *vlv_get_dpll(struct drm_i915_private *i915)
{
return NULL;
}
static inline void g4x_dp_set_clock(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config)
{
}
static inline bool g4x_dp_port_enabled(struct drm_i915_private *dev_priv,
i915_reg_t dp_reg, int port,
enum pipe *pipe)

@ -185,10 +185,12 @@ void hsw_ips_post_update(struct intel_atomic_state *state,
/* IPS only exists on ULT machines and is tied to pipe A. */
bool hsw_crtc_supports_ips(struct intel_crtc *crtc)
{
return HAS_IPS(to_i915(crtc->base.dev)) && crtc->pipe == PIPE_A;
struct intel_display *display = to_intel_display(crtc);
return HAS_IPS(display) && crtc->pipe == PIPE_A;
}
bool hsw_crtc_state_ips_capable(const struct intel_crtc_state *crtc_state)
static bool hsw_crtc_state_ips_capable(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);
@ -218,6 +220,20 @@ bool hsw_crtc_state_ips_capable(const struct intel_crtc_state *crtc_state)
return true;
}
int hsw_ips_min_cdclk(const struct intel_crtc_state *crtc_state)
{
struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
if (!IS_BROADWELL(i915))
return 0;
if (!hsw_crtc_state_ips_capable(crtc_state))
return 0;
/* pixel rate mustn't exceed 95% of cdclk with IPS on BDW */
return DIV_ROUND_UP(crtc_state->pixel_rate * 100, 95);
}
int hsw_ips_compute_config(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{

@ -19,7 +19,7 @@ bool hsw_ips_pre_update(struct intel_atomic_state *state,
void hsw_ips_post_update(struct intel_atomic_state *state,
struct intel_crtc *crtc);
bool hsw_crtc_supports_ips(struct intel_crtc *crtc);
bool hsw_crtc_state_ips_capable(const struct intel_crtc_state *crtc_state);
int hsw_ips_min_cdclk(const struct intel_crtc_state *crtc_state);
int hsw_ips_compute_config(struct intel_atomic_state *state,
struct intel_crtc *crtc);
void hsw_ips_get_config(struct intel_crtc_state *crtc_state);
@ -42,9 +42,9 @@ static inline bool hsw_crtc_supports_ips(struct intel_crtc *crtc)
{
return false;
}
static inline bool hsw_crtc_state_ips_capable(const struct intel_crtc_state *crtc_state)
static inline int hsw_ips_min_cdclk(const struct intel_crtc_state *crtc_state)
{
return false;
return 0;
}
static inline int hsw_ips_compute_config(struct intel_atomic_state *state,
struct intel_crtc *crtc)

@ -0,0 +1,95 @@
// SPDX-License-Identifier: MIT
/*
* Copyright © 2024 Intel Corporation
*/
#include "i915_drv.h"
#include "i915_reg.h"
#include "i9xx_display_sr.h"
#include "intel_de.h"
#include "intel_gmbus.h"
#include "intel_pci_config.h"
static void i9xx_display_save_swf(struct intel_display *display)
{
int i;
/* Scratch space */
if (DISPLAY_VER(display) == 2 && display->platform.mobile) {
for (i = 0; i < 7; i++) {
display->restore.saveSWF0[i] = intel_de_read(display, SWF0(display, i));
display->restore.saveSWF1[i] = intel_de_read(display, SWF1(display, i));
}
for (i = 0; i < 3; i++)
display->restore.saveSWF3[i] = intel_de_read(display, SWF3(display, i));
} else if (DISPLAY_VER(display) == 2) {
for (i = 0; i < 7; i++)
display->restore.saveSWF1[i] = intel_de_read(display, SWF1(display, i));
} else if (HAS_GMCH(display)) {
for (i = 0; i < 16; i++) {
display->restore.saveSWF0[i] = intel_de_read(display, SWF0(display, i));
display->restore.saveSWF1[i] = intel_de_read(display, SWF1(display, i));
}
for (i = 0; i < 3; i++)
display->restore.saveSWF3[i] = intel_de_read(display, SWF3(display, i));
}
}
static void i9xx_display_restore_swf(struct intel_display *display)
{
int i;
/* Scratch space */
if (DISPLAY_VER(display) == 2 && display->platform.mobile) {
for (i = 0; i < 7; i++) {
intel_de_write(display, SWF0(display, i), display->restore.saveSWF0[i]);
intel_de_write(display, SWF1(display, i), display->restore.saveSWF1[i]);
}
for (i = 0; i < 3; i++)
intel_de_write(display, SWF3(display, i), display->restore.saveSWF3[i]);
} else if (DISPLAY_VER(display) == 2) {
for (i = 0; i < 7; i++)
intel_de_write(display, SWF1(display, i), display->restore.saveSWF1[i]);
} else if (HAS_GMCH(display)) {
for (i = 0; i < 16; i++) {
intel_de_write(display, SWF0(display, i), display->restore.saveSWF0[i]);
intel_de_write(display, SWF1(display, i), display->restore.saveSWF1[i]);
}
for (i = 0; i < 3; i++)
intel_de_write(display, SWF3(display, i), display->restore.saveSWF3[i]);
}
}
void i9xx_display_sr_save(struct intel_display *display)
{
struct pci_dev *pdev = to_pci_dev(display->drm->dev);
if (!HAS_DISPLAY(display))
return;
/* Display arbitration control */
if (DISPLAY_VER(display) <= 4)
display->restore.saveDSPARB = intel_de_read(display, DSPARB(display));
if (DISPLAY_VER(display) == 4)
pci_read_config_word(pdev, GCDGMBUS, &display->restore.saveGCDGMBUS);
i9xx_display_save_swf(display);
}
void i9xx_display_sr_restore(struct intel_display *display)
{
struct pci_dev *pdev = to_pci_dev(display->drm->dev);
if (!HAS_DISPLAY(display))
return;
i9xx_display_restore_swf(display);
if (DISPLAY_VER(display) == 4)
pci_write_config_word(pdev, GCDGMBUS, display->restore.saveGCDGMBUS);
/* Display arbitration */
if (DISPLAY_VER(display) <= 4)
intel_de_write(display, DSPARB(display), display->restore.saveDSPARB);
}

@ -0,0 +1,14 @@
/* SPDX-License-Identifier: MIT */
/*
* Copyright © 2024 Intel Corporation
*/
#ifndef __I9XX_DISPLAY_SR_H__
#define __I9XX_DISPLAY_SR_H__
struct intel_display;
void i9xx_display_sr_save(struct intel_display *display);
void i9xx_display_sr_restore(struct intel_display *display);
#endif

@ -1602,7 +1602,9 @@ static int gen11_dsi_dsc_compute_config(struct intel_encoder *encoder,
/* FIXME: split only when necessary */
if (crtc_state->dsc.slice_count > 1)
crtc_state->dsc.dsc_split = true;
crtc_state->dsc.num_streams = 2;
else
crtc_state->dsc.num_streams = 1;
/* FIXME: initialize from VBT */
vdsc_cfg->rc_model_size = DSC_RC_MODEL_SIZE_CONST;

@ -681,12 +681,11 @@ static void ibx_audio_codec_enable(struct intel_encoder *encoder,
void intel_audio_sdp_split_update(const struct intel_crtc_state *crtc_state)
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
struct intel_display *display = to_intel_display(crtc_state);
enum transcoder trans = crtc_state->cpu_transcoder;
if (HAS_DP20(i915))
intel_de_rmw(i915, AUD_DP_2DOT0_CTRL(trans), AUD_ENABLE_SDP_SPLIT,
if (HAS_DP20(display))
intel_de_rmw(display, AUD_DP_2DOT0_CTRL(trans), AUD_ENABLE_SDP_SPLIT,
crtc_state->sdp_split_enable ? AUD_ENABLE_SDP_SPLIT : 0);
}
@ -981,6 +980,53 @@ static void glk_force_audio_cdclk(struct drm_i915_private *i915,
drm_modeset_acquire_fini(&ctx);
}
int intel_audio_min_cdclk(const struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(crtc_state);
struct drm_i915_private *dev_priv = to_i915(display->drm);
int min_cdclk = 0;
if (!crtc_state->has_audio)
return 0;
/* BSpec says "Do not use DisplayPort with CDCLK less than 432 MHz,
* audio enabled, port width x4, and link rate HBR2 (5.4 GHz), or else
* there may be audio corruption or screen corruption." This cdclk
* restriction for GLK is 316.8 MHz.
*/
if (intel_crtc_has_dp_encoder(crtc_state) &&
crtc_state->port_clock >= 540000 &&
crtc_state->lane_count == 4) {
if (DISPLAY_VER(display) == 10) {
/* Display WA #1145: glk */
min_cdclk = max(min_cdclk, 316800);
} else if (DISPLAY_VER(display) == 9 || IS_BROADWELL(dev_priv)) {
/* Display WA #1144: skl,bxt */
min_cdclk = max(min_cdclk, 432000);
}
}
/*
* According to BSpec, "The CD clock frequency must be at least twice
* the frequency of the Azalia BCLK." and BCLK is 96 MHz by default.
*/
if (DISPLAY_VER(display) >= 9)
min_cdclk = max(min_cdclk, 2 * 96000);
/*
* "For DP audio configuration, cdclk frequency shall be set to
* meet the following requirements:
* DP Link Frequency(MHz) | Cdclk frequency(MHz)
* 270 | 320 or higher
* 162 | 200 or higher"
*/
if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
intel_crtc_has_dp_encoder(crtc_state))
min_cdclk = max(min_cdclk, crtc_state->port_clock);
return min_cdclk;
}
static unsigned long i915_audio_component_get_power(struct device *kdev)
{
struct intel_display *display = to_intel_display(kdev);

@ -27,6 +27,7 @@ void intel_audio_codec_get_config(struct intel_encoder *encoder,
struct intel_crtc_state *crtc_state);
void intel_audio_cdclk_change_pre(struct drm_i915_private *dev_priv);
void intel_audio_cdclk_change_post(struct drm_i915_private *dev_priv);
int intel_audio_min_cdclk(const struct intel_crtc_state *crtc_state);
void intel_audio_init(struct drm_i915_private *dev_priv);
void intel_audio_register(struct drm_i915_private *i915);
void intel_audio_deinit(struct drm_i915_private *dev_priv);

@ -1402,12 +1402,21 @@ parse_power_conservation_features(struct intel_display *display,
panel_type);
}
static void vbt_edp_to_pps_delays(struct intel_pps_delays *pps,
const struct edp_power_seq *edp_pps)
{
pps->power_up = edp_pps->t1_t3;
pps->backlight_on = edp_pps->t8;
pps->backlight_off = edp_pps->t9;
pps->power_down = edp_pps->t10;
pps->power_cycle = edp_pps->t11_t12;
}
static void
parse_edp(struct intel_display *display,
struct intel_panel *panel)
{
const struct bdb_edp *edp;
const struct edp_power_seq *edp_pps;
const struct edp_fast_link_params *edp_link_params;
int panel_type = panel->vbt.panel_type;
@ -1428,10 +1437,10 @@ parse_edp(struct intel_display *display,
}
/* Get the eDP sequencing and link info */
edp_pps = &edp->power_seqs[panel_type];
edp_link_params = &edp->fast_link_params[panel_type];
panel->vbt.edp.pps = *edp_pps;
vbt_edp_to_pps_delays(&panel->vbt.edp.pps,
&edp->power_seqs[panel_type]);
if (display->vbt.version >= 224) {
panel->vbt.edp.rate =

@ -50,14 +50,6 @@ enum intel_backlight_type {
INTEL_BACKLIGHT_VESA_EDP_AUX_INTERFACE,
};
struct edp_power_seq {
u16 t1_t3;
u16 t8;
u16 t9;
u16 t10;
u16 t11_t12;
} __packed;
/*
* MIPI Sequence Block definitions
*

@ -1256,7 +1256,7 @@ int intel_bw_min_cdclk(struct drm_i915_private *i915,
min_cdclk = intel_bw_dbuf_min_cdclk(i915, bw_state);
for_each_pipe(i915, pipe)
min_cdclk = max(bw_state->min_cdclk[pipe], min_cdclk);
min_cdclk = max(min_cdclk, bw_state->min_cdclk[pipe]);
return min_cdclk;
}

@ -37,7 +37,6 @@
#include "intel_cdclk.h"
#include "intel_crtc.h"
#include "intel_de.h"
#include "intel_dp.h"
#include "intel_display_types.h"
#include "intel_mchbar_regs.h"
#include "intel_pci_config.h"
@ -46,6 +45,7 @@
#include "intel_vdsc.h"
#include "skl_watermark.h"
#include "skl_watermark_regs.h"
#include "vlv_dsi.h"
#include "vlv_sideband.h"
/**
@ -2761,23 +2761,34 @@ intel_set_cdclk_post_plane_update(struct intel_atomic_state *state)
"Post changing CDCLK to");
}
/* pixels per CDCLK */
static int intel_cdclk_ppc(struct intel_display *display, bool double_wide)
{
return DISPLAY_VER(display) >= 10 || double_wide ? 2 : 1;
}
/* max pixel rate as % of CDCLK (not accounting for PPC) */
static int intel_cdclk_guardband(struct intel_display *display)
{
struct drm_i915_private *dev_priv = to_i915(display->drm);
if (DISPLAY_VER(display) >= 9 ||
IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv))
return 100;
else if (IS_CHERRYVIEW(dev_priv))
return 95;
else
return 90;
}
static int intel_pixel_rate_to_cdclk(const struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(crtc_state);
struct drm_i915_private *dev_priv = to_i915(display->drm);
int ppc = intel_cdclk_ppc(display, crtc_state->double_wide);
int guardband = intel_cdclk_guardband(display);
int pixel_rate = crtc_state->pixel_rate;
if (DISPLAY_VER(display) >= 10)
return DIV_ROUND_UP(pixel_rate, 2);
else if (DISPLAY_VER(display) == 9 ||
IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv))
return pixel_rate;
else if (IS_CHERRYVIEW(dev_priv))
return DIV_ROUND_UP(pixel_rate * 100, 95);
else if (crtc_state->double_wide)
return DIV_ROUND_UP(pixel_rate * 100, 90 * 2);
else
return DIV_ROUND_UP(pixel_rate * 100, 90);
return DIV_ROUND_UP(pixel_rate * 100, guardband * ppc);
}
static int intel_planes_min_cdclk(const struct intel_crtc_state *crtc_state)
@ -2788,127 +2799,24 @@ static int intel_planes_min_cdclk(const struct intel_crtc_state *crtc_state)
int min_cdclk = 0;
for_each_intel_plane_on_crtc(display->drm, crtc, plane)
min_cdclk = max(crtc_state->min_cdclk[plane->id], min_cdclk);
return min_cdclk;
}
static int intel_vdsc_min_cdclk(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);
int num_vdsc_instances = intel_dsc_get_num_vdsc_instances(crtc_state);
int min_cdclk = 0;
/*
* When we decide to use only one VDSC engine, since
* each VDSC operates with 1 ppc throughput, pixel clock
* cannot be higher than the VDSC clock (cdclk)
* If there 2 VDSC engines, then pixel clock can't be higher than
* VDSC clock(cdclk) * 2 and so on.
*/
min_cdclk = max_t(int, min_cdclk,
DIV_ROUND_UP(crtc_state->pixel_rate, num_vdsc_instances));
if (crtc_state->joiner_pipes) {
int pixel_clock = intel_dp_mode_to_fec_clock(crtc_state->hw.adjusted_mode.clock);
/*
* According to Bigjoiner bw check:
* compressed_bpp <= PPC * CDCLK * Big joiner Interface bits / Pixel clock
*
* We have already computed compressed_bpp, so now compute the min CDCLK that
* is required to support this compressed_bpp.
*
* => CDCLK >= compressed_bpp * Pixel clock / (PPC * Bigjoiner Interface bits)
*
* Since PPC = 2 with bigjoiner
* => CDCLK >= compressed_bpp * Pixel clock / 2 * Bigjoiner Interface bits
*/
int bigjoiner_interface_bits = DISPLAY_VER(display) >= 14 ? 36 : 24;
int min_cdclk_bj =
(fxp_q4_to_int_roundup(crtc_state->dsc.compressed_bpp_x16) *
pixel_clock) / (2 * bigjoiner_interface_bits);
min_cdclk = max(min_cdclk, min_cdclk_bj);
}
min_cdclk = max(min_cdclk, crtc_state->min_cdclk[plane->id]);
return min_cdclk;
}
int intel_crtc_compute_min_cdclk(const struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(crtc_state);
struct drm_i915_private *dev_priv = to_i915(display->drm);
int min_cdclk;
if (!crtc_state->hw.enable)
return 0;
min_cdclk = intel_pixel_rate_to_cdclk(crtc_state);
/* pixel rate mustn't exceed 95% of cdclk with IPS on BDW */
if (IS_BROADWELL(dev_priv) && hsw_crtc_state_ips_capable(crtc_state))
min_cdclk = DIV_ROUND_UP(min_cdclk * 100, 95);
/* BSpec says "Do not use DisplayPort with CDCLK less than 432 MHz,
* audio enabled, port width x4, and link rate HBR2 (5.4 GHz), or else
* there may be audio corruption or screen corruption." This cdclk
* restriction for GLK is 316.8 MHz.
*/
if (intel_crtc_has_dp_encoder(crtc_state) &&
crtc_state->has_audio &&
crtc_state->port_clock >= 540000 &&
crtc_state->lane_count == 4) {
if (DISPLAY_VER(display) == 10) {
/* Display WA #1145: glk */
min_cdclk = max(316800, min_cdclk);
} else if (DISPLAY_VER(display) == 9 || IS_BROADWELL(dev_priv)) {
/* Display WA #1144: skl,bxt */
min_cdclk = max(432000, min_cdclk);
}
}
/*
* According to BSpec, "The CD clock frequency must be at least twice
* the frequency of the Azalia BCLK." and BCLK is 96 MHz by default.
*/
if (crtc_state->has_audio && DISPLAY_VER(display) >= 9)
min_cdclk = max(2 * 96000, min_cdclk);
/*
* "For DP audio configuration, cdclk frequency shall be set to
* meet the following requirements:
* DP Link Frequency(MHz) | Cdclk frequency(MHz)
* 270 | 320 or higher
* 162 | 200 or higher"
*/
if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
intel_crtc_has_dp_encoder(crtc_state) && crtc_state->has_audio)
min_cdclk = max(crtc_state->port_clock, min_cdclk);
/*
* On Valleyview some DSI panels lose (v|h)sync when the clock is lower
* than 320000KHz.
*/
if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI) &&
IS_VALLEYVIEW(dev_priv))
min_cdclk = max(320000, min_cdclk);
/*
* On Geminilake once the CDCLK gets as low as 79200
* picture gets unstable, despite that values are
* correct for DSI PLL and DE PLL.
*/
if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI) &&
IS_GEMINILAKE(dev_priv))
min_cdclk = max(158400, min_cdclk);
/* Account for additional needs from the planes */
min_cdclk = max(intel_planes_min_cdclk(crtc_state), min_cdclk);
if (crtc_state->dsc.compression_enable)
min_cdclk = max(min_cdclk, intel_vdsc_min_cdclk(crtc_state));
min_cdclk = max(min_cdclk, hsw_ips_min_cdclk(crtc_state));
min_cdclk = max(min_cdclk, intel_audio_min_cdclk(crtc_state));
min_cdclk = max(min_cdclk, vlv_dsi_min_cdclk(crtc_state));
min_cdclk = max(min_cdclk, intel_planes_min_cdclk(crtc_state));
min_cdclk = max(min_cdclk, intel_vdsc_min_cdclk(crtc_state));
return min_cdclk;
}
@ -2960,7 +2868,7 @@ static int intel_compute_min_cdclk(struct intel_atomic_state *state)
min_cdclk = max(cdclk_state->force_min_cdclk,
cdclk_state->bw_min_cdclk);
for_each_pipe(display, pipe)
min_cdclk = max(cdclk_state->min_cdclk[pipe], min_cdclk);
min_cdclk = max(min_cdclk, cdclk_state->min_cdclk[pipe]);
/*
* Avoid glk_force_audio_cdclk() causing excessive screen
@ -2972,7 +2880,7 @@ static int intel_compute_min_cdclk(struct intel_atomic_state *state)
*/
if (IS_GEMINILAKE(dev_priv) && cdclk_state->active_pipes &&
!is_power_of_2(cdclk_state->active_pipes))
min_cdclk = max(2 * 96000, min_cdclk);
min_cdclk = max(min_cdclk, 2 * 96000);
if (min_cdclk > display->cdclk.max_cdclk_freq) {
drm_dbg_kms(display->drm,
@ -3028,8 +2936,8 @@ static int bxt_compute_min_voltage_level(struct intel_atomic_state *state)
min_voltage_level = 0;
for_each_pipe(display, pipe)
min_voltage_level = max(cdclk_state->min_voltage_level[pipe],
min_voltage_level);
min_voltage_level = max(min_voltage_level,
cdclk_state->min_voltage_level[pipe]);
return min_voltage_level;
}
@ -3452,20 +3360,11 @@ int intel_modeset_calc_cdclk(struct intel_atomic_state *state)
static int intel_compute_max_dotclk(struct intel_display *display)
{
struct drm_i915_private *dev_priv = to_i915(display->drm);
int ppc = intel_cdclk_ppc(display, HAS_DOUBLE_WIDE(display));
int guardband = intel_cdclk_guardband(display);
int max_cdclk_freq = display->cdclk.max_cdclk_freq;
if (DISPLAY_VER(display) >= 10)
return 2 * max_cdclk_freq;
else if (DISPLAY_VER(display) == 9 ||
IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv))
return max_cdclk_freq;
else if (IS_CHERRYVIEW(dev_priv))
return max_cdclk_freq*95/100;
else if (DISPLAY_VER(display) < 4)
return 2*max_cdclk_freq*90/100;
else
return max_cdclk_freq*90/100;
return ppc * max_cdclk_freq * guardband / 100;
}
/**

@ -38,6 +38,7 @@
#include "i915_reg.h"
#include "intel_connector.h"
#include "intel_crt.h"
#include "intel_crt_regs.h"
#include "intel_crtc.h"
#include "intel_ddi.h"
#include "intel_ddi_buf_trans.h"
@ -55,18 +56,23 @@
#include "intel_pch_refclk.h"
/* Here's the desired hotplug mode */
#define ADPA_HOTPLUG_BITS (ADPA_CRT_HOTPLUG_PERIOD_128 | \
#define ADPA_HOTPLUG_BITS (ADPA_CRT_HOTPLUG_ENABLE | \
ADPA_CRT_HOTPLUG_PERIOD_128 | \
ADPA_CRT_HOTPLUG_WARMUP_10MS | \
ADPA_CRT_HOTPLUG_SAMPLE_4S | \
ADPA_CRT_HOTPLUG_VOLTAGE_50 | \
ADPA_CRT_HOTPLUG_VOLREF_325MV | \
ADPA_CRT_HOTPLUG_ENABLE)
ADPA_CRT_HOTPLUG_VOLREF_325MV)
#define ADPA_HOTPLUG_MASK (ADPA_CRT_HOTPLUG_MONITOR_MASK | \
ADPA_CRT_HOTPLUG_ENABLE | \
ADPA_CRT_HOTPLUG_PERIOD_MASK | \
ADPA_CRT_HOTPLUG_WARMUP_MASK | \
ADPA_CRT_HOTPLUG_SAMPLE_MASK | \
ADPA_CRT_HOTPLUG_VOLTAGE_MASK | \
ADPA_CRT_HOTPLUG_VOLREF_MASK | \
ADPA_CRT_HOTPLUG_FORCE_TRIGGER)
struct intel_crt {
struct intel_encoder base;
/* DPMS state is stored in the connector, which we need in the
* encoder's enable/disable callbacks */
struct intel_connector *connector;
bool force_hotplug_required;
i915_reg_t adpa_reg;
};
@ -91,9 +97,9 @@ bool intel_crt_port_enabled(struct intel_display *display,
/* asserts want to know the pipe even if the port is disabled */
if (HAS_PCH_CPT(dev_priv))
*pipe = (val & ADPA_PIPE_SEL_MASK_CPT) >> ADPA_PIPE_SEL_SHIFT_CPT;
*pipe = REG_FIELD_GET(ADPA_PIPE_SEL_MASK_CPT, val);
else
*pipe = (val & ADPA_PIPE_SEL_MASK) >> ADPA_PIPE_SEL_SHIFT;
*pipe = REG_FIELD_GET(ADPA_PIPE_SEL_MASK, val);
return val & ADPA_DAC_ENABLE;
}
@ -141,27 +147,27 @@ static unsigned int intel_crt_get_flags(struct intel_encoder *encoder)
}
static void intel_crt_get_config(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config)
struct intel_crtc_state *crtc_state)
{
pipe_config->output_types |= BIT(INTEL_OUTPUT_ANALOG);
crtc_state->output_types |= BIT(INTEL_OUTPUT_ANALOG);
pipe_config->hw.adjusted_mode.flags |= intel_crt_get_flags(encoder);
crtc_state->hw.adjusted_mode.flags |= intel_crt_get_flags(encoder);
pipe_config->hw.adjusted_mode.crtc_clock = pipe_config->port_clock;
crtc_state->hw.adjusted_mode.crtc_clock = crtc_state->port_clock;
}
static void hsw_crt_get_config(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config)
struct intel_crtc_state *crtc_state)
{
lpt_pch_get_config(pipe_config);
lpt_pch_get_config(crtc_state);
hsw_ddi_get_config(encoder, pipe_config);
hsw_ddi_get_config(encoder, crtc_state);
pipe_config->hw.adjusted_mode.flags &= ~(DRM_MODE_FLAG_PHSYNC |
DRM_MODE_FLAG_NHSYNC |
DRM_MODE_FLAG_PVSYNC |
DRM_MODE_FLAG_NVSYNC);
pipe_config->hw.adjusted_mode.flags |= intel_crt_get_flags(encoder);
crtc_state->hw.adjusted_mode.flags &= ~(DRM_MODE_FLAG_PHSYNC |
DRM_MODE_FLAG_NHSYNC |
DRM_MODE_FLAG_PVSYNC |
DRM_MODE_FLAG_NVSYNC);
crtc_state->hw.adjusted_mode.flags |= intel_crt_get_flags(encoder);
}
/* Note: The caller is required to filter out dpms modes not supported by the
@ -244,7 +250,7 @@ static void hsw_disable_crt(struct intel_atomic_state *state,
const struct intel_crtc_state *old_crtc_state,
const struct drm_connector_state *old_conn_state)
{
struct intel_display *display = to_intel_display(state);
struct intel_display *display = to_intel_display(encoder);
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
drm_WARN_ON(display->drm, !old_crtc_state->has_pch_encoder);
@ -257,7 +263,7 @@ static void hsw_post_disable_crt(struct intel_atomic_state *state,
const struct intel_crtc_state *old_crtc_state,
const struct drm_connector_state *old_conn_state)
{
struct intel_display *display = to_intel_display(state);
struct intel_display *display = to_intel_display(encoder);
struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc);
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
@ -287,7 +293,7 @@ static void hsw_pre_pll_enable_crt(struct intel_atomic_state *state,
const struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state)
{
struct intel_display *display = to_intel_display(state);
struct intel_display *display = to_intel_display(encoder);
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
drm_WARN_ON(display->drm, !crtc_state->has_pch_encoder);
@ -300,7 +306,7 @@ static void hsw_pre_enable_crt(struct intel_atomic_state *state,
const struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state)
{
struct intel_display *display = to_intel_display(state);
struct intel_display *display = to_intel_display(encoder);
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
enum pipe pipe = crtc->pipe;
@ -319,7 +325,7 @@ static void hsw_enable_crt(struct intel_atomic_state *state,
const struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state)
{
struct intel_display *display = to_intel_display(state);
struct intel_display *display = to_intel_display(encoder);
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
enum pipe pipe = crtc->pipe;
@ -355,8 +361,7 @@ intel_crt_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode)
{
struct intel_display *display = to_intel_display(connector->dev);
struct drm_device *dev = connector->dev;
struct drm_i915_private *dev_priv = to_i915(dev);
struct drm_i915_private *dev_priv = to_i915(connector->dev);
int max_dotclk = display->cdclk.max_dotclk_freq;
enum drm_mode_status status;
int max_clock;
@ -399,48 +404,48 @@ intel_crt_mode_valid(struct drm_connector *connector,
}
static int intel_crt_compute_config(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config,
struct intel_crtc_state *crtc_state,
struct drm_connector_state *conn_state)
{
struct drm_display_mode *adjusted_mode =
&pipe_config->hw.adjusted_mode;
&crtc_state->hw.adjusted_mode;
if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
return -EINVAL;
pipe_config->sink_format = INTEL_OUTPUT_FORMAT_RGB;
pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
crtc_state->sink_format = INTEL_OUTPUT_FORMAT_RGB;
crtc_state->output_format = INTEL_OUTPUT_FORMAT_RGB;
return 0;
}
static int pch_crt_compute_config(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config,
struct intel_crtc_state *crtc_state,
struct drm_connector_state *conn_state)
{
struct drm_display_mode *adjusted_mode =
&pipe_config->hw.adjusted_mode;
&crtc_state->hw.adjusted_mode;
if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
return -EINVAL;
pipe_config->has_pch_encoder = true;
if (!intel_fdi_compute_pipe_bpp(pipe_config))
crtc_state->has_pch_encoder = true;
if (!intel_fdi_compute_pipe_bpp(crtc_state))
return -EINVAL;
pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
crtc_state->output_format = INTEL_OUTPUT_FORMAT_RGB;
return 0;
}
static int hsw_crt_compute_config(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config,
struct intel_crtc_state *crtc_state,
struct drm_connector_state *conn_state)
{
struct intel_display *display = to_intel_display(encoder);
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct drm_display_mode *adjusted_mode =
&pipe_config->hw.adjusted_mode;
&crtc_state->hw.adjusted_mode;
if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
return -EINVAL;
@ -450,30 +455,30 @@ static int hsw_crt_compute_config(struct intel_encoder *encoder,
adjusted_mode->crtc_hblank_start > 4096)
return -EINVAL;
pipe_config->has_pch_encoder = true;
if (!intel_fdi_compute_pipe_bpp(pipe_config))
crtc_state->has_pch_encoder = true;
if (!intel_fdi_compute_pipe_bpp(crtc_state))
return -EINVAL;
pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
crtc_state->output_format = INTEL_OUTPUT_FORMAT_RGB;
/* LPT FDI RX only supports 8bpc. */
if (HAS_PCH_LPT(dev_priv)) {
/* TODO: Check crtc_state->max_link_bpp_x16 instead of bw_constrained */
if (pipe_config->bw_constrained && pipe_config->pipe_bpp < 24) {
if (crtc_state->bw_constrained && crtc_state->pipe_bpp < 24) {
drm_dbg_kms(display->drm,
"LPT only supports 24bpp\n");
return -EINVAL;
}
pipe_config->pipe_bpp = 24;
crtc_state->pipe_bpp = 24;
}
/* FDI must always be 2.7 GHz */
pipe_config->port_clock = 135000 * 2;
crtc_state->port_clock = 135000 * 2;
pipe_config->enhanced_framing = true;
crtc_state->enhanced_framing = true;
adjusted_mode->crtc_clock = lpt_iclkip(pipe_config);
adjusted_mode->crtc_clock = lpt_iclkip(crtc_state);
return 0;
}
@ -481,9 +486,8 @@ static int hsw_crt_compute_config(struct intel_encoder *encoder,
static bool ilk_crt_detect_hotplug(struct drm_connector *connector)
{
struct intel_display *display = to_intel_display(connector->dev);
struct drm_device *dev = connector->dev;
struct intel_crt *crt = intel_attached_crt(to_intel_connector(connector));
struct drm_i915_private *dev_priv = to_i915(dev);
struct drm_i915_private *dev_priv = to_i915(connector->dev);
u32 adpa;
bool ret;
@ -532,9 +536,8 @@ static bool ilk_crt_detect_hotplug(struct drm_connector *connector)
static bool valleyview_crt_detect_hotplug(struct drm_connector *connector)
{
struct intel_display *display = to_intel_display(connector->dev);
struct drm_device *dev = connector->dev;
struct intel_crt *crt = intel_attached_crt(to_intel_connector(connector));
struct drm_i915_private *dev_priv = to_i915(dev);
struct drm_i915_private *dev_priv = to_i915(connector->dev);
bool reenable_hpd;
u32 adpa;
bool ret;
@ -588,8 +591,7 @@ static bool valleyview_crt_detect_hotplug(struct drm_connector *connector)
static bool intel_crt_detect_hotplug(struct drm_connector *connector)
{
struct intel_display *display = to_intel_display(connector->dev);
struct drm_device *dev = connector->dev;
struct drm_i915_private *dev_priv = to_i915(dev);
struct drm_i915_private *dev_priv = to_i915(connector->dev);
u32 stat;
bool ret = false;
int i, tries = 0;
@ -856,7 +858,7 @@ intel_crt_detect(struct drm_connector *connector,
struct intel_display *display = to_intel_display(connector->dev);
struct drm_i915_private *dev_priv = to_i915(connector->dev);
struct intel_crt *crt = intel_attached_crt(to_intel_connector(connector));
struct intel_encoder *intel_encoder = &crt->base;
struct intel_encoder *encoder = &crt->base;
struct drm_atomic_state *state;
intel_wakeref_t wakeref;
int status;
@ -865,15 +867,14 @@ intel_crt_detect(struct drm_connector *connector,
connector->base.id, connector->name,
force);
if (!intel_display_device_enabled(dev_priv))
if (!intel_display_device_enabled(display))
return connector_status_disconnected;
if (!intel_display_driver_check_access(dev_priv))
if (!intel_display_driver_check_access(display))
return connector->status;
if (display->params.load_detect_test) {
wakeref = intel_display_power_get(dev_priv,
intel_encoder->power_domain);
wakeref = intel_display_power_get(dev_priv, encoder->power_domain);
goto load_detect;
}
@ -881,8 +882,7 @@ intel_crt_detect(struct drm_connector *connector,
if (dmi_check_system(intel_spurious_crt_detect))
return connector_status_disconnected;
wakeref = intel_display_power_get(dev_priv,
intel_encoder->power_domain);
wakeref = intel_display_power_get(dev_priv, encoder->power_domain);
if (I915_HAS_HOTPLUG(display)) {
/* We can not rely on the HPD pin always being correctly wired
@ -939,7 +939,7 @@ intel_crt_detect(struct drm_connector *connector,
}
out:
intel_display_power_put(dev_priv, intel_encoder->power_domain, wakeref);
intel_display_power_put(dev_priv, encoder->power_domain, wakeref);
return status;
}
@ -947,19 +947,17 @@ intel_crt_detect(struct drm_connector *connector,
static int intel_crt_get_modes(struct drm_connector *connector)
{
struct intel_display *display = to_intel_display(connector->dev);
struct drm_device *dev = connector->dev;
struct drm_i915_private *dev_priv = to_i915(dev);
struct drm_i915_private *dev_priv = to_i915(connector->dev);
struct intel_crt *crt = intel_attached_crt(to_intel_connector(connector));
struct intel_encoder *intel_encoder = &crt->base;
struct intel_encoder *encoder = &crt->base;
intel_wakeref_t wakeref;
struct i2c_adapter *ddc;
int ret;
if (!intel_display_driver_check_access(dev_priv))
if (!intel_display_driver_check_access(display))
return drm_edid_connector_add_modes(connector);
wakeref = intel_display_power_get(dev_priv,
intel_encoder->power_domain);
wakeref = intel_display_power_get(dev_priv, encoder->power_domain);
ret = intel_crt_ddc_get_modes(connector, connector->ddc);
if (ret || !IS_G4X(dev_priv))
@ -970,7 +968,7 @@ static int intel_crt_get_modes(struct drm_connector *connector)
ret = intel_crt_ddc_get_modes(connector, ddc);
out:
intel_display_power_put(dev_priv, intel_encoder->power_domain, wakeref);
intel_display_power_put(dev_priv, encoder->power_domain, wakeref);
return ret;
}
@ -984,7 +982,7 @@ void intel_crt_reset(struct drm_encoder *encoder)
u32 adpa;
adpa = intel_de_read(display, crt->adpa_reg);
adpa &= ~ADPA_CRT_HOTPLUG_MASK;
adpa &= ~ADPA_HOTPLUG_MASK;
adpa |= ADPA_HOTPLUG_BITS;
intel_de_write(display, crt->adpa_reg, adpa);
intel_de_posting_read(display, crt->adpa_reg);
@ -1022,9 +1020,8 @@ static const struct drm_encoder_funcs intel_crt_enc_funcs = {
void intel_crt_init(struct intel_display *display)
{
struct drm_i915_private *dev_priv = to_i915(display->drm);
struct drm_connector *connector;
struct intel_connector *connector;
struct intel_crt *crt;
struct intel_connector *intel_connector;
i915_reg_t adpa_reg;
u8 ddc_pin;
u32 adpa;
@ -1047,7 +1044,9 @@ void intel_crt_init(struct intel_display *display)
* it and see what happens.
*/
intel_de_write(display, adpa_reg,
adpa | ADPA_DAC_ENABLE | ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE);
adpa | ADPA_DAC_ENABLE |
ADPA_HSYNC_CNTL_DISABLE |
ADPA_VSYNC_CNTL_DISABLE);
if ((intel_de_read(display, adpa_reg) & ADPA_DAC_ENABLE) == 0)
return;
intel_de_write(display, adpa_reg, adpa);
@ -1057,17 +1056,15 @@ void intel_crt_init(struct intel_display *display)
if (!crt)
return;
intel_connector = intel_connector_alloc();
if (!intel_connector) {
connector = intel_connector_alloc();
if (!connector) {
kfree(crt);
return;
}
ddc_pin = display->vbt.crt_ddc_pin;
connector = &intel_connector->base;
crt->connector = intel_connector;
drm_connector_init_with_ddc(display->drm, connector,
drm_connector_init_with_ddc(display->drm, &connector->base,
&intel_crt_connector_funcs,
DRM_MODE_CONNECTOR_VGA,
intel_gmbus_get_adapter(display, ddc_pin));
@ -1075,7 +1072,7 @@ void intel_crt_init(struct intel_display *display)
drm_encoder_init(display->drm, &crt->base.base, &intel_crt_enc_funcs,
DRM_MODE_ENCODER_DAC, "CRT");
intel_connector_attach_encoder(intel_connector, &crt->base);
intel_connector_attach_encoder(connector, &crt->base);
crt->base.type = INTEL_OUTPUT_ANALOG;
crt->base.cloneable = BIT(INTEL_OUTPUT_DVO) | BIT(INTEL_OUTPUT_HDMI);
@ -1085,7 +1082,7 @@ void intel_crt_init(struct intel_display *display)
crt->base.pipe_mask = ~0;
if (DISPLAY_VER(display) != 2)
connector->interlace_allowed = true;
connector->base.interlace_allowed = true;
crt->adpa_reg = adpa_reg;
@ -1095,11 +1092,11 @@ void intel_crt_init(struct intel_display *display)
!dmi_check_system(intel_spurious_crt_detect)) {
crt->base.hpd_pin = HPD_CRT;
crt->base.hotplug = intel_encoder_hotplug;
intel_connector->polled = DRM_CONNECTOR_POLL_HPD;
connector->polled = DRM_CONNECTOR_POLL_HPD;
} else {
intel_connector->polled = DRM_CONNECTOR_POLL_CONNECT;
connector->polled = DRM_CONNECTOR_POLL_CONNECT;
}
intel_connector->base.polled = intel_connector->polled;
connector->base.polled = connector->polled;
if (HAS_DDI(display)) {
assert_port_valid(dev_priv, PORT_E);
@ -1132,9 +1129,9 @@ void intel_crt_init(struct intel_display *display)
crt->base.get_hw_state = intel_crt_get_hw_state;
crt->base.enable = intel_enable_crt;
}
intel_connector->get_hw_state = intel_connector_get_hw_state;
connector->get_hw_state = intel_connector_get_hw_state;
drm_connector_helper_add(connector, &intel_crt_connector_helper_funcs);
drm_connector_helper_add(&connector->base, &intel_crt_connector_helper_funcs);
/*
* TODO: find a proper way to discover whether we need to set the the

@ -0,0 +1,48 @@
/* SPDX-License-Identifier: MIT */
/*
* Copyright © 2024 Intel Corporation
*/
#ifndef __INTEL_CRT_REGS_H__
#define __INTEL_CRT_REGS_H__
#include "intel_display_reg_defs.h"
#define ADPA _MMIO(0x61100)
#define PCH_ADPA _MMIO(0xe1100)
#define VLV_ADPA _MMIO(VLV_DISPLAY_BASE + 0x61100)
#define ADPA_DAC_ENABLE REG_BIT(31)
#define ADPA_PIPE_SEL_MASK REG_BIT(30)
#define ADPA_PIPE_SEL(pipe) REG_FIELD_PREP(ADPA_PIPE_SEL_MASK, (pipe))
#define ADPA_PIPE_SEL_MASK_CPT REG_GENMASK(30, 29)
#define ADPA_PIPE_SEL_CPT(pipe) REG_FIELD_PREP(ADPA_PIPE_SEL_MASK_CPT, (pipe))
#define ADPA_CRT_HOTPLUG_MONITOR_MASK REG_GENMASK(25, 24)
#define ADPA_CRT_HOTPLUG_MONITOR_NONE REG_FIELD_PREP(ADPA_CRT_HOTPLUG_MONITOR_MASK, 0)
#define ADPA_CRT_HOTPLUG_MONITOR_COLOR REG_FIELD_PREP(ADPA_CRT_HOTPLUG_MONITOR_MASK, 3)
#define ADPA_CRT_HOTPLUG_MONITOR_MONO REG_FIELD_PREP(ADPA_CRT_HOTPLUG_MONITOR_MASK, 2)
#define ADPA_CRT_HOTPLUG_ENABLE REG_BIT(23)
#define ADPA_CRT_HOTPLUG_PERIOD_MASK REG_BIT(22)
#define ADPA_CRT_HOTPLUG_PERIOD_64 REG_FIELD_PREP(ADPA_CRT_HOTPLUG_PERIOD_MASK, 0)
#define ADPA_CRT_HOTPLUG_PERIOD_128 REG_FIELD_PREP(ADPA_CRT_HOTPLUG_PERIOD_MASK, 1)
#define ADPA_CRT_HOTPLUG_WARMUP_MASK REG_BIT(21)
#define ADPA_CRT_HOTPLUG_WARMUP_5MS REG_FIELD_PREP(ADPA_CRT_HOTPLUG_WARMUP_MASK, 0)
#define ADPA_CRT_HOTPLUG_WARMUP_10MS REG_FIELD_PREP(ADPA_CRT_HOTPLUG_WARMUP_MASK, 1)
#define ADPA_CRT_HOTPLUG_SAMPLE_MASK REG_BIT(20)
#define ADPA_CRT_HOTPLUG_SAMPLE_2S REG_FIELD_PREP(ADPA_CRT_HOTPLUG_SAMPLE_MASK, 0)
#define ADPA_CRT_HOTPLUG_SAMPLE_4S REG_FIELD_PREP(ADPA_CRT_HOTPLUG_SAMPLE_MASK, 1)
#define ADPA_CRT_HOTPLUG_VOLTAGE_MASK REG_GENMASK(19, 18)
#define ADPA_CRT_HOTPLUG_VOLTAGE_40 REG_FIELD_PREP(ADPA_CRT_HOTPLUG_VOLTAGE_MASK, 0)
#define ADPA_CRT_HOTPLUG_VOLTAGE_50 REG_FIELD_PREP(ADPA_CRT_HOTPLUG_VOLTAGE_MASK, 1)
#define ADPA_CRT_HOTPLUG_VOLTAGE_60 REG_FIELD_PREP(ADPA_CRT_HOTPLUG_VOLTAGE_MASK, 2)
#define ADPA_CRT_HOTPLUG_VOLTAGE_70 REG_FIELD_PREP(ADPA_CRT_HOTPLUG_VOLTAGE_MASK, 3)
#define ADPA_CRT_HOTPLUG_VOLREF_MASK REG_BIT(17)
#define ADPA_CRT_HOTPLUG_VOLREF_325MV REG_FIELD_PREP(ADPA_CRT_HOTPLUG_VOLREF_MASK, 0)
#define ADPA_CRT_HOTPLUG_VOLREF_475MV REG_FIELD_PREP(ADPA_CRT_HOTPLUG_VOLREF_MASK, 1)
#define ADPA_CRT_HOTPLUG_FORCE_TRIGGER REG_BIT(16)
#define ADPA_USE_VGA_HVPOLARITY REG_BIT(15)
#define ADPA_HSYNC_CNTL_DISABLE REG_BIT(11)
#define ADPA_VSYNC_CNTL_DISABLE REG_BIT(10)
#define ADPA_VSYNC_ACTIVE_HIGH REG_BIT(4)
#define ADPA_HSYNC_ACTIVE_HIGH REG_BIT(3)
#endif /* __INTEL_CRT_REGS_H__ */

@ -50,16 +50,6 @@ intel_dump_infoframe(struct drm_i915_private *i915,
hdmi_infoframe_log(KERN_DEBUG, i915->drm.dev, frame);
}
static void
intel_dump_buffer(const char *prefix, const u8 *buf, size_t len)
{
if (!drm_debug_enabled(DRM_UT_KMS))
return;
print_hex_dump(KERN_DEBUG, prefix, DUMP_PREFIX_NONE,
16, 0, buf, len, false);
}
#define OUTPUT_TYPE(x) [INTEL_OUTPUT_ ## x] = #x
static const char * const output_type_str[] = {
@ -293,8 +283,8 @@ void intel_crtc_state_dump(const struct intel_crtc_state *pipe_config,
drm_dp_as_sdp_log(&p, &pipe_config->infoframes.as_sdp);
if (pipe_config->has_audio)
intel_dump_buffer("ELD: ", pipe_config->eld,
drm_eld_size(pipe_config->eld));
drm_print_hex_dump(&p, "ELD: ", pipe_config->eld,
drm_eld_size(pipe_config->eld));
drm_printf(&p, "vrr: %s, vmin: %d, vmax: %d, pipeline full: %d, guardband: %d flipline: %d, vmin vblank: %d, vmax vblank: %d\n",
str_yes_no(pipe_config->vrr.enable),

@ -619,7 +619,6 @@ static void skl_write_cursor_wm(struct intel_dsb *dsb,
const struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(plane->base.dev);
struct drm_i915_private *i915 = to_i915(plane->base.dev);
enum plane_id plane_id = plane->id;
enum pipe pipe = plane->pipe;
const struct skl_pipe_wm *pipe_wm = &crtc_state->wm.skl.optimal;
@ -627,14 +626,14 @@ static void skl_write_cursor_wm(struct intel_dsb *dsb,
&crtc_state->wm.skl.plane_ddb[plane_id];
int level;
for (level = 0; level < i915->display.wm.num_levels; level++)
for (level = 0; level < display->wm.num_levels; level++)
intel_de_write_dsb(display, dsb, CUR_WM(pipe, level),
skl_cursor_wm_reg_val(skl_plane_wm_level(pipe_wm, plane_id, level)));
intel_de_write_dsb(display, dsb, CUR_WM_TRANS(pipe),
skl_cursor_wm_reg_val(skl_plane_trans_wm(pipe_wm, plane_id)));
if (HAS_HW_SAGV_WM(i915)) {
if (HAS_HW_SAGV_WM(display)) {
const struct skl_plane_wm *wm = &pipe_wm->planes[plane_id];
intel_de_write_dsb(display, dsb, CUR_WM_SAGV(pipe),

@ -2987,7 +2987,7 @@ static void intel_cx0pll_enable(struct intel_encoder *encoder,
struct intel_display *display = to_intel_display(encoder);
enum phy phy = intel_encoder_to_phy(encoder);
struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
bool lane_reversal = dig_port->saved_port_bits & DDI_BUF_PORT_REVERSAL;
bool lane_reversal = dig_port->lane_reversal;
u8 maxpclk_lane = lane_reversal ? INTEL_CX0_LANE1 :
INTEL_CX0_LANE0;
intel_wakeref_t wakeref = intel_cx0_phy_transaction_begin(encoder);

@ -335,10 +335,14 @@ static void intel_ddi_init_dp_buf_reg(struct intel_encoder *encoder,
struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
/* DDI_BUF_CTL_ENABLE will be set by intel_ddi_prepare_link_retrain() later */
intel_dp->DP = dig_port->saved_port_bits |
DDI_PORT_WIDTH(crtc_state->lane_count) |
intel_dp->DP = DDI_PORT_WIDTH(crtc_state->lane_count) |
DDI_BUF_TRANS_SELECT(0);
if (dig_port->lane_reversal)
intel_dp->DP |= DDI_BUF_PORT_REVERSAL;
if (dig_port->ddi_a_4_lanes)
intel_dp->DP |= DDI_A_4_LANES;
if (DISPLAY_VER(i915) >= 14) {
if (intel_dp_is_uhbr(crtc_state))
intel_dp->DP |= DDI_BUF_PORT_DATA_40BIT;
@ -455,17 +459,20 @@ static u32 bdw_trans_port_sync_master_select(enum transcoder master_transcoder)
}
static void
intel_ddi_config_transcoder_dp2(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
intel_ddi_config_transcoder_dp2(const struct intel_crtc_state *crtc_state,
bool enable)
{
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
struct intel_display *display = to_intel_display(crtc_state);
enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
u32 val = 0;
if (intel_dp_is_uhbr(crtc_state))
if (!HAS_DP20(display))
return;
if (enable && intel_dp_is_uhbr(crtc_state))
val = TRANS_DP2_128B132B_CHANNEL_CODING;
intel_de_write(i915, TRANS_DP2_CTL(cpu_transcoder), val);
intel_de_write(display, TRANS_DP2_CTL(cpu_transcoder), val);
}
/*
@ -617,9 +624,10 @@ void intel_ddi_enable_transcoder_func(struct intel_encoder *encoder,
/*
* Same as intel_ddi_enable_transcoder_func(), but it does not set the enable
* bit.
* bit for the DDI function and enables the DP2 configuration. Called for all
* transcoder types.
*/
static void
void
intel_ddi_config_transcoder_func(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
{
@ -628,12 +636,20 @@ intel_ddi_config_transcoder_func(struct intel_encoder *encoder,
enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
u32 ctl;
intel_ddi_config_transcoder_dp2(crtc_state, true);
ctl = intel_ddi_transcoder_func_reg_val_get(encoder, crtc_state);
ctl &= ~TRANS_DDI_FUNC_ENABLE;
intel_de_write(dev_priv, TRANS_DDI_FUNC_CTL(dev_priv, cpu_transcoder),
ctl);
}
/*
* Disable the DDI function and port syncing.
* For SST, pre-TGL MST, TGL+ MST-slave transcoders: deselect the DDI port,
* SST/MST mode and disable the DP2 configuration. For TGL+ MST-master
* transcoders these are done later in intel_ddi_post_disable_dp().
*/
void intel_ddi_disable_transcoder_func(const struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(crtc_state);
@ -670,6 +686,9 @@ void intel_ddi_disable_transcoder_func(const struct intel_crtc_state *crtc_state
intel_de_write(dev_priv, TRANS_DDI_FUNC_CTL(dev_priv, cpu_transcoder),
ctl);
if (intel_dp_mst_is_slave_trans(crtc_state))
intel_ddi_config_transcoder_dp2(crtc_state, false);
if (intel_has_quirk(display, QUIRK_INCREASE_DDI_DISABLED_TIME) &&
intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) {
drm_dbg_kms(display->drm, "Quirk Increase DDI disabled time\n");
@ -700,15 +719,15 @@ int intel_ddi_toggle_hdcp_bits(struct intel_encoder *intel_encoder,
bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector)
{
struct drm_device *dev = intel_connector->base.dev;
struct drm_i915_private *dev_priv = to_i915(dev);
struct intel_display *display = to_intel_display(intel_connector);
struct drm_i915_private *dev_priv = to_i915(display->drm);
struct intel_encoder *encoder = intel_attached_encoder(intel_connector);
int type = intel_connector->base.connector_type;
enum port port = encoder->port;
enum transcoder cpu_transcoder;
intel_wakeref_t wakeref;
enum pipe pipe = 0;
u32 tmp;
u32 ddi_mode;
bool ret;
wakeref = intel_display_power_get_if_enabled(dev_priv,
@ -716,6 +735,7 @@ bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector)
if (!wakeref)
return false;
/* Note: This returns false for DP MST primary encoders. */
if (!encoder->get_hw_state(encoder, &pipe)) {
ret = false;
goto out;
@ -726,38 +746,28 @@ bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector)
else
cpu_transcoder = (enum transcoder) pipe;
tmp = intel_de_read(dev_priv,
TRANS_DDI_FUNC_CTL(dev_priv, cpu_transcoder));
ddi_mode = intel_de_read(dev_priv, TRANS_DDI_FUNC_CTL(dev_priv, cpu_transcoder)) &
TRANS_DDI_MODE_SELECT_MASK;
switch (tmp & TRANS_DDI_MODE_SELECT_MASK) {
case TRANS_DDI_MODE_SELECT_HDMI:
case TRANS_DDI_MODE_SELECT_DVI:
if (ddi_mode == TRANS_DDI_MODE_SELECT_HDMI ||
ddi_mode == TRANS_DDI_MODE_SELECT_DVI) {
ret = type == DRM_MODE_CONNECTOR_HDMIA;
break;
case TRANS_DDI_MODE_SELECT_DP_SST:
} else if (ddi_mode == TRANS_DDI_MODE_SELECT_FDI_OR_128B132B && !HAS_DP20(display)) {
ret = type == DRM_MODE_CONNECTOR_VGA;
} else if (ddi_mode == TRANS_DDI_MODE_SELECT_DP_SST) {
ret = type == DRM_MODE_CONNECTOR_eDP ||
type == DRM_MODE_CONNECTOR_DisplayPort;
break;
case TRANS_DDI_MODE_SELECT_DP_MST:
/* if the transcoder is in MST state then
* connector isn't connected */
type == DRM_MODE_CONNECTOR_DisplayPort;
} else if (ddi_mode == TRANS_DDI_MODE_SELECT_FDI_OR_128B132B && HAS_DP20(display)) {
/*
* encoder->get_hw_state() should have bailed out on MST. This
* must be SST and non-eDP.
*/
ret = type == DRM_MODE_CONNECTOR_DisplayPort;
} else if (drm_WARN_ON(display->drm, ddi_mode == TRANS_DDI_MODE_SELECT_DP_MST)) {
/* encoder->get_hw_state() should have bailed out on MST. */
ret = false;
break;
case TRANS_DDI_MODE_SELECT_FDI_OR_128B132B:
if (HAS_DP20(dev_priv))
/* 128b/132b */
ret = false;
else
/* FDI */
ret = type == DRM_MODE_CONNECTOR_VGA;
break;
default:
} else {
ret = false;
break;
}
out:
@ -769,8 +779,8 @@ bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector)
static void intel_ddi_get_encoder_pipes(struct intel_encoder *encoder,
u8 *pipe_mask, bool *is_dp_mst)
{
struct drm_device *dev = encoder->base.dev;
struct drm_i915_private *dev_priv = to_i915(dev);
struct intel_display *display = to_intel_display(encoder);
struct drm_i915_private *dev_priv = to_i915(display->drm);
enum port port = encoder->port;
intel_wakeref_t wakeref;
enum pipe p;
@ -815,7 +825,7 @@ static void intel_ddi_get_encoder_pipes(struct intel_encoder *encoder,
mst_pipe_mask = 0;
for_each_pipe(dev_priv, p) {
enum transcoder cpu_transcoder = (enum transcoder)p;
unsigned int port_mask, ddi_select;
u32 port_mask, ddi_select, ddi_mode;
intel_wakeref_t trans_wakeref;
trans_wakeref = intel_display_power_get_if_enabled(dev_priv,
@ -839,9 +849,10 @@ static void intel_ddi_get_encoder_pipes(struct intel_encoder *encoder,
if ((tmp & port_mask) != ddi_select)
continue;
if ((tmp & TRANS_DDI_MODE_SELECT_MASK) == TRANS_DDI_MODE_SELECT_DP_MST ||
(HAS_DP20(dev_priv) &&
(tmp & TRANS_DDI_MODE_SELECT_MASK) == TRANS_DDI_MODE_SELECT_FDI_OR_128B132B))
ddi_mode = tmp & TRANS_DDI_MODE_SELECT_MASK;
if (ddi_mode == TRANS_DDI_MODE_SELECT_DP_MST ||
(ddi_mode == TRANS_DDI_MODE_SELECT_FDI_OR_128B132B && HAS_DP20(display)))
mst_pipe_mask |= BIT(p);
*pipe_mask |= BIT(p);
@ -2196,8 +2207,8 @@ i915_reg_t dp_tp_ctl_reg(struct intel_encoder *encoder,
return DP_TP_CTL(encoder->port);
}
i915_reg_t dp_tp_status_reg(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
static i915_reg_t dp_tp_status_reg(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
@ -2208,6 +2219,25 @@ i915_reg_t dp_tp_status_reg(struct intel_encoder *encoder,
return DP_TP_STATUS(encoder->port);
}
void intel_ddi_clear_act_sent(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(encoder);
intel_de_write(display, dp_tp_status_reg(encoder, crtc_state),
DP_TP_STATUS_ACT_SENT);
}
void intel_ddi_wait_for_act_sent(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(encoder);
if (intel_de_wait_for_set(display, dp_tp_status_reg(encoder, crtc_state),
DP_TP_STATUS_ACT_SENT, 1))
drm_err(display->drm, "Timed out waiting for ACT sent\n");
}
static void intel_dp_sink_set_msa_timing_par_ignore_state(struct intel_dp *intel_dp,
const struct intel_crtc_state *crtc_state,
bool enable)
@ -2376,12 +2406,10 @@ static void intel_ddi_power_up_lanes(struct intel_encoder *encoder,
if (intel_encoder_is_combo(encoder)) {
enum phy phy = intel_encoder_to_phy(encoder);
bool lane_reversal =
dig_port->saved_port_bits & DDI_BUF_PORT_REVERSAL;
intel_combo_phy_power_up_lanes(i915, phy, false,
crtc_state->lane_count,
lane_reversal);
dig_port->lane_reversal);
}
}
@ -2521,7 +2549,7 @@ static void mtl_port_buf_ctl_program(struct intel_encoder *encoder,
else
val |= XELPDP_PORT_BUF_PORT_DATA_10BIT;
if (dig_port->saved_port_bits & DDI_BUF_PORT_REVERSAL)
if (dig_port->lane_reversal)
val |= XELPDP_PORT_REVERSAL;
intel_de_write(i915, XELPDP_PORT_BUF_CTL1(i915, port), val);
@ -2583,10 +2611,6 @@ static void mtl_ddi_pre_enable_dp(struct intel_atomic_state *state,
/*
* 6.b If DP v2.0/128b mode - Configure TRANS_DP2_CTL register settings.
*/
intel_ddi_config_transcoder_dp2(encoder, crtc_state);
/*
* 6.c Configure TRANS_DDI_FUNC_CTL DDI Select, DDI Mode Select & MST
* Transport Select
*/
@ -2721,9 +2745,6 @@ static void tgl_ddi_pre_enable_dp(struct intel_atomic_state *state,
*/
intel_ddi_enable_transcoder_clock(encoder, crtc_state);
if (HAS_DP20(dev_priv))
intel_ddi_config_transcoder_dp2(encoder, crtc_state);
/*
* 7.b Configure TRANS_DDI_FUNC_CTL DDI Select, DDI Mode Select & MST
* Transport Select
@ -2862,9 +2883,9 @@ static void intel_ddi_pre_enable_dp(struct intel_atomic_state *state,
const struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state)
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct intel_display *display = to_intel_display(encoder);
if (HAS_DP20(dev_priv))
if (HAS_DP20(display))
intel_dp_128b132b_sdp_crc16(enc_to_intel_dp(encoder),
crtc_state);
@ -2872,9 +2893,9 @@ static void intel_ddi_pre_enable_dp(struct intel_atomic_state *state,
if (crtc_state->has_panel_replay)
intel_psr_enable_sink(enc_to_intel_dp(encoder), crtc_state);
if (DISPLAY_VER(dev_priv) >= 14)
if (DISPLAY_VER(display) >= 14)
mtl_ddi_pre_enable_dp(state, encoder, crtc_state, conn_state);
else if (DISPLAY_VER(dev_priv) >= 12)
else if (DISPLAY_VER(display) >= 12)
tgl_ddi_pre_enable_dp(state, encoder, crtc_state, conn_state);
else
hsw_ddi_pre_enable_dp(state, encoder, crtc_state, conn_state);
@ -2911,6 +2932,24 @@ static void intel_ddi_pre_enable_hdmi(struct intel_atomic_state *state,
crtc_state, conn_state);
}
/*
* Note: Also called from the ->pre_enable of the first active MST stream
* encoder on its primary encoder.
*
* When called from DP MST code:
*
* - conn_state will be NULL
*
* - encoder will be the primary encoder (i.e. mst->primary)
*
* - the main connector associated with this port won't be active or linked to a
* crtc
*
* - crtc_state will be the state of the first stream to be activated on this
* port, and it may not be the same stream that will be deactivated last, but
* each stream should have a state that is identical when it comes to the DP
* link parameteres
*/
static void intel_ddi_pre_enable(struct intel_atomic_state *state,
struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
@ -2920,19 +2959,6 @@ static void intel_ddi_pre_enable(struct intel_atomic_state *state,
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
enum pipe pipe = crtc->pipe;
/*
* When called from DP MST code:
* - conn_state will be NULL
* - encoder will be the main encoder (ie. mst->primary)
* - the main connector associated with this port
* won't be active or linked to a crtc
* - crtc_state will be the state of the first stream to
* be activated on this port, and it may not be the same
* stream that will be deactivated last, but each stream
* should have a state that is identical when it comes to
* the DP link parameteres
*/
drm_WARN_ON(&dev_priv->drm, crtc_state->has_pch_encoder);
intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
@ -3088,6 +3114,8 @@ static void intel_ddi_post_disable_dp(struct intel_atomic_state *state,
intel_dp_sink_set_fec_ready(intel_dp, old_crtc_state, false);
intel_ddi_config_transcoder_dp2(old_crtc_state, false);
/*
* From TGL spec: "If single stream or multi-stream master transcoder:
* Configure Transcoder Clock select to direct no clock to the
@ -3180,6 +3208,11 @@ static void intel_ddi_post_disable_hdmi_or_sst(struct intel_atomic_state *state,
}
}
/*
* Note: Also called from the ->post_disable of the last active MST stream
* encoder on its primary encoder. See also the comment for
* intel_ddi_pre_enable().
*/
static void intel_ddi_post_disable(struct intel_atomic_state *state,
struct intel_encoder *encoder,
const struct intel_crtc_state *old_crtc_state,
@ -3210,6 +3243,11 @@ static void intel_ddi_post_disable(struct intel_atomic_state *state,
old_conn_state);
}
/*
* Note: Also called from the ->post_pll_disable of the last active MST stream
* encoder on its primary encoder. See also the comment for
* intel_ddi_pre_enable().
*/
static void intel_ddi_post_pll_disable(struct intel_atomic_state *state,
struct intel_encoder *encoder,
const struct intel_crtc_state *old_crtc_state,
@ -3260,7 +3298,7 @@ static void trans_port_sync_stop_link_train(struct intel_atomic_state *state,
crtc_state);
}
static void intel_enable_ddi_dp(struct intel_atomic_state *state,
static void intel_ddi_enable_dp(struct intel_atomic_state *state,
struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state)
@ -3282,18 +3320,8 @@ static void intel_enable_ddi_dp(struct intel_atomic_state *state,
trans_port_sync_stop_link_train(state, encoder, crtc_state);
}
/* FIXME bad home for this function */
i915_reg_t hsw_chicken_trans_reg(struct drm_i915_private *i915,
enum transcoder cpu_transcoder)
{
return DISPLAY_VER(i915) >= 14 ?
MTL_CHICKEN_TRANS(cpu_transcoder) :
CHICKEN_TRANS(cpu_transcoder);
}
static i915_reg_t
gen9_chicken_trans_reg_by_port(struct drm_i915_private *dev_priv,
enum port port)
gen9_chicken_trans_reg_by_port(struct intel_display *display, enum port port)
{
static const enum transcoder trans[] = {
[PORT_A] = TRANSCODER_EDP,
@ -3303,19 +3331,20 @@ gen9_chicken_trans_reg_by_port(struct drm_i915_private *dev_priv,
[PORT_E] = TRANSCODER_A,
};
drm_WARN_ON(&dev_priv->drm, DISPLAY_VER(dev_priv) < 9);
drm_WARN_ON(display->drm, DISPLAY_VER(display) < 9);
if (drm_WARN_ON(&dev_priv->drm, port < PORT_A || port > PORT_E))
if (drm_WARN_ON(display->drm, port < PORT_A || port > PORT_E))
port = PORT_A;
return CHICKEN_TRANS(trans[port]);
return CHICKEN_TRANS(display, trans[port]);
}
static void intel_enable_ddi_hdmi(struct intel_atomic_state *state,
static void intel_ddi_enable_hdmi(struct intel_atomic_state *state,
struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state)
{
struct intel_display *display = to_intel_display(encoder);
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
struct drm_connector *connector = conn_state->connector;
@ -3346,7 +3375,7 @@ static void intel_enable_ddi_hdmi(struct intel_atomic_state *state,
* the bits affect a specific DDI port rather than
* a specific transcoder.
*/
i915_reg_t reg = gen9_chicken_trans_reg_by_port(dev_priv, port);
i915_reg_t reg = gen9_chicken_trans_reg_by_port(display, port);
u32 val;
val = intel_de_read(dev_priv, reg);
@ -3386,14 +3415,20 @@ static void intel_enable_ddi_hdmi(struct intel_atomic_state *state,
* is filled with lane count, already set in the crtc_state.
* The same is required to be filled in PORT_BUF_CTL for C10/20 Phy.
*/
buf_ctl = dig_port->saved_port_bits | DDI_BUF_CTL_ENABLE;
buf_ctl = DDI_BUF_CTL_ENABLE;
if (dig_port->lane_reversal)
buf_ctl |= DDI_BUF_PORT_REVERSAL;
if (dig_port->ddi_a_4_lanes)
buf_ctl |= DDI_A_4_LANES;
if (DISPLAY_VER(dev_priv) >= 14) {
u8 lane_count = mtl_get_port_width(crtc_state->lane_count);
u32 port_buf = 0;
port_buf |= XELPDP_PORT_WIDTH(lane_count);
if (dig_port->saved_port_bits & DDI_BUF_PORT_REVERSAL)
if (dig_port->lane_reversal)
port_buf |= XELPDP_PORT_REVERSAL;
intel_de_rmw(dev_priv, XELPDP_PORT_BUF_CTL1(dev_priv, port),
@ -3413,7 +3448,7 @@ static void intel_enable_ddi_hdmi(struct intel_atomic_state *state,
intel_wait_ddi_buf_active(encoder);
}
static void intel_enable_ddi(struct intel_atomic_state *state,
static void intel_ddi_enable(struct intel_atomic_state *state,
struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state)
@ -3439,15 +3474,15 @@ static void intel_enable_ddi(struct intel_atomic_state *state,
}
if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
intel_enable_ddi_hdmi(state, encoder, crtc_state, conn_state);
intel_ddi_enable_hdmi(state, encoder, crtc_state, conn_state);
else
intel_enable_ddi_dp(state, encoder, crtc_state, conn_state);
intel_ddi_enable_dp(state, encoder, crtc_state, conn_state);
intel_hdcp_enable(state, encoder, crtc_state, conn_state);
}
static void intel_disable_ddi_dp(struct intel_atomic_state *state,
static void intel_ddi_disable_dp(struct intel_atomic_state *state,
struct intel_encoder *encoder,
const struct intel_crtc_state *old_crtc_state,
const struct drm_connector_state *old_conn_state)
@ -3468,7 +3503,7 @@ static void intel_disable_ddi_dp(struct intel_atomic_state *state,
false);
}
static void intel_disable_ddi_hdmi(struct intel_atomic_state *state,
static void intel_ddi_disable_hdmi(struct intel_atomic_state *state,
struct intel_encoder *encoder,
const struct intel_crtc_state *old_crtc_state,
const struct drm_connector_state *old_conn_state)
@ -3483,7 +3518,7 @@ static void intel_disable_ddi_hdmi(struct intel_atomic_state *state,
connector->base.id, connector->name);
}
static void intel_disable_ddi(struct intel_atomic_state *state,
static void intel_ddi_disable(struct intel_atomic_state *state,
struct intel_encoder *encoder,
const struct intel_crtc_state *old_crtc_state,
const struct drm_connector_state *old_conn_state)
@ -3493,10 +3528,10 @@ static void intel_disable_ddi(struct intel_atomic_state *state,
intel_hdcp_disable(to_intel_connector(old_conn_state->connector));
if (intel_crtc_has_type(old_crtc_state, INTEL_OUTPUT_HDMI))
intel_disable_ddi_hdmi(state, encoder, old_crtc_state,
intel_ddi_disable_hdmi(state, encoder, old_crtc_state,
old_conn_state);
else
intel_disable_ddi_dp(state, encoder, old_crtc_state,
intel_ddi_disable_dp(state, encoder, old_crtc_state,
old_conn_state);
}
@ -3556,6 +3591,11 @@ void intel_ddi_update_active_dpll(struct intel_atomic_state *state,
intel_update_active_dpll(state, pipe_crtc, encoder);
}
/*
* Note: Also called from the ->pre_pll_enable of the first active MST stream
* encoder on its primary encoder. See also the comment for
* intel_ddi_pre_enable().
*/
static void
intel_ddi_pre_pll_enable(struct intel_atomic_state *state,
struct intel_encoder *encoder,
@ -3868,29 +3908,136 @@ static void bdw_get_trans_port_sync_config(struct intel_crtc_state *crtc_state)
crtc_state->sync_mode_slaves_mask);
}
static void intel_ddi_read_func_ctl_dvi(struct intel_encoder *encoder,
struct intel_crtc_state *crtc_state,
u32 ddi_func_ctl)
{
struct intel_display *display = to_intel_display(encoder);
crtc_state->output_types |= BIT(INTEL_OUTPUT_HDMI);
if (DISPLAY_VER(display) >= 14)
crtc_state->lane_count =
((ddi_func_ctl & DDI_PORT_WIDTH_MASK) >> DDI_PORT_WIDTH_SHIFT) + 1;
else
crtc_state->lane_count = 4;
}
static void intel_ddi_read_func_ctl_hdmi(struct intel_encoder *encoder,
struct intel_crtc_state *crtc_state,
u32 ddi_func_ctl)
{
crtc_state->has_hdmi_sink = true;
crtc_state->infoframes.enable |=
intel_hdmi_infoframes_enabled(encoder, crtc_state);
if (crtc_state->infoframes.enable)
crtc_state->has_infoframe = true;
if (ddi_func_ctl & TRANS_DDI_HDMI_SCRAMBLING)
crtc_state->hdmi_scrambling = true;
if (ddi_func_ctl & TRANS_DDI_HIGH_TMDS_CHAR_RATE)
crtc_state->hdmi_high_tmds_clock_ratio = true;
intel_ddi_read_func_ctl_dvi(encoder, crtc_state, ddi_func_ctl);
}
static void intel_ddi_read_func_ctl_fdi(struct intel_encoder *encoder,
struct intel_crtc_state *crtc_state,
u32 ddi_func_ctl)
{
struct intel_display *display = to_intel_display(encoder);
crtc_state->output_types |= BIT(INTEL_OUTPUT_ANALOG);
crtc_state->enhanced_framing =
intel_de_read(display, dp_tp_ctl_reg(encoder, crtc_state)) &
DP_TP_CTL_ENHANCED_FRAME_ENABLE;
}
static void intel_ddi_read_func_ctl_dp_sst(struct intel_encoder *encoder,
struct intel_crtc_state *crtc_state,
u32 ddi_func_ctl)
{
struct intel_display *display = to_intel_display(encoder);
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
if (encoder->type == INTEL_OUTPUT_EDP)
crtc_state->output_types |= BIT(INTEL_OUTPUT_EDP);
else
crtc_state->output_types |= BIT(INTEL_OUTPUT_DP);
crtc_state->lane_count =
((ddi_func_ctl & DDI_PORT_WIDTH_MASK) >> DDI_PORT_WIDTH_SHIFT) + 1;
intel_cpu_transcoder_get_m1_n1(crtc, cpu_transcoder, &crtc_state->dp_m_n);
intel_cpu_transcoder_get_m2_n2(crtc, cpu_transcoder, &crtc_state->dp_m2_n2);
crtc_state->enhanced_framing =
intel_de_read(display, dp_tp_ctl_reg(encoder, crtc_state)) &
DP_TP_CTL_ENHANCED_FRAME_ENABLE;
if (DISPLAY_VER(display) >= 11)
crtc_state->fec_enable =
intel_de_read(display,
dp_tp_ctl_reg(encoder, crtc_state)) & DP_TP_CTL_FEC_ENABLE;
if (dig_port->lspcon.active && intel_dp_has_hdmi_sink(&dig_port->dp))
crtc_state->infoframes.enable |=
intel_lspcon_infoframes_enabled(encoder, crtc_state);
else
crtc_state->infoframes.enable |=
intel_hdmi_infoframes_enabled(encoder, crtc_state);
}
static void intel_ddi_read_func_ctl_dp_mst(struct intel_encoder *encoder,
struct intel_crtc_state *crtc_state,
u32 ddi_func_ctl)
{
struct intel_display *display = to_intel_display(encoder);
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
crtc_state->output_types |= BIT(INTEL_OUTPUT_DP_MST);
crtc_state->lane_count =
((ddi_func_ctl & DDI_PORT_WIDTH_MASK) >> DDI_PORT_WIDTH_SHIFT) + 1;
if (DISPLAY_VER(display) >= 12)
crtc_state->mst_master_transcoder =
REG_FIELD_GET(TRANS_DDI_MST_TRANSPORT_SELECT_MASK, ddi_func_ctl);
intel_cpu_transcoder_get_m1_n1(crtc, cpu_transcoder, &crtc_state->dp_m_n);
if (DISPLAY_VER(display) >= 11)
crtc_state->fec_enable =
intel_de_read(display,
dp_tp_ctl_reg(encoder, crtc_state)) & DP_TP_CTL_FEC_ENABLE;
crtc_state->infoframes.enable |=
intel_hdmi_infoframes_enabled(encoder, crtc_state);
}
static void intel_ddi_read_func_ctl(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config)
{
struct intel_display *display = to_intel_display(encoder);
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);
enum transcoder cpu_transcoder = pipe_config->cpu_transcoder;
struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
u32 temp, flags = 0;
u32 ddi_func_ctl, ddi_mode, flags = 0;
temp = intel_de_read(dev_priv,
TRANS_DDI_FUNC_CTL(dev_priv, cpu_transcoder));
if (temp & TRANS_DDI_PHSYNC)
ddi_func_ctl = intel_de_read(dev_priv, TRANS_DDI_FUNC_CTL(dev_priv, cpu_transcoder));
if (ddi_func_ctl & TRANS_DDI_PHSYNC)
flags |= DRM_MODE_FLAG_PHSYNC;
else
flags |= DRM_MODE_FLAG_NHSYNC;
if (temp & TRANS_DDI_PVSYNC)
if (ddi_func_ctl & TRANS_DDI_PVSYNC)
flags |= DRM_MODE_FLAG_PVSYNC;
else
flags |= DRM_MODE_FLAG_NVSYNC;
pipe_config->hw.adjusted_mode.flags |= flags;
switch (temp & TRANS_DDI_BPC_MASK) {
switch (ddi_func_ctl & TRANS_DDI_BPC_MASK) {
case TRANS_DDI_BPC_6:
pipe_config->pipe_bpp = 18;
break;
@ -3907,93 +4054,27 @@ static void intel_ddi_read_func_ctl(struct intel_encoder *encoder,
break;
}
switch (temp & TRANS_DDI_MODE_SELECT_MASK) {
case TRANS_DDI_MODE_SELECT_HDMI:
pipe_config->has_hdmi_sink = true;
ddi_mode = ddi_func_ctl & TRANS_DDI_MODE_SELECT_MASK;
pipe_config->infoframes.enable |=
intel_hdmi_infoframes_enabled(encoder, pipe_config);
if (pipe_config->infoframes.enable)
pipe_config->has_infoframe = true;
if (temp & TRANS_DDI_HDMI_SCRAMBLING)
pipe_config->hdmi_scrambling = true;
if (temp & TRANS_DDI_HIGH_TMDS_CHAR_RATE)
pipe_config->hdmi_high_tmds_clock_ratio = true;
fallthrough;
case TRANS_DDI_MODE_SELECT_DVI:
pipe_config->output_types |= BIT(INTEL_OUTPUT_HDMI);
if (DISPLAY_VER(dev_priv) >= 14)
pipe_config->lane_count =
((temp & DDI_PORT_WIDTH_MASK) >> DDI_PORT_WIDTH_SHIFT) + 1;
else
pipe_config->lane_count = 4;
break;
case TRANS_DDI_MODE_SELECT_DP_SST:
if (encoder->type == INTEL_OUTPUT_EDP)
pipe_config->output_types |= BIT(INTEL_OUTPUT_EDP);
else
pipe_config->output_types |= BIT(INTEL_OUTPUT_DP);
pipe_config->lane_count =
((temp & DDI_PORT_WIDTH_MASK) >> DDI_PORT_WIDTH_SHIFT) + 1;
intel_cpu_transcoder_get_m1_n1(crtc, cpu_transcoder,
&pipe_config->dp_m_n);
intel_cpu_transcoder_get_m2_n2(crtc, cpu_transcoder,
&pipe_config->dp_m2_n2);
pipe_config->enhanced_framing =
intel_de_read(dev_priv, dp_tp_ctl_reg(encoder, pipe_config)) &
DP_TP_CTL_ENHANCED_FRAME_ENABLE;
if (DISPLAY_VER(dev_priv) >= 11)
pipe_config->fec_enable =
intel_de_read(dev_priv,
dp_tp_ctl_reg(encoder, pipe_config)) & DP_TP_CTL_FEC_ENABLE;
if (dig_port->lspcon.active && intel_dp_has_hdmi_sink(&dig_port->dp))
pipe_config->infoframes.enable |=
intel_lspcon_infoframes_enabled(encoder, pipe_config);
else
pipe_config->infoframes.enable |=
intel_hdmi_infoframes_enabled(encoder, pipe_config);
break;
case TRANS_DDI_MODE_SELECT_FDI_OR_128B132B:
if (!HAS_DP20(dev_priv)) {
/* FDI */
pipe_config->output_types |= BIT(INTEL_OUTPUT_ANALOG);
pipe_config->enhanced_framing =
intel_de_read(dev_priv, dp_tp_ctl_reg(encoder, pipe_config)) &
DP_TP_CTL_ENHANCED_FRAME_ENABLE;
break;
}
fallthrough; /* 128b/132b */
case TRANS_DDI_MODE_SELECT_DP_MST:
pipe_config->output_types |= BIT(INTEL_OUTPUT_DP_MST);
pipe_config->lane_count =
((temp & DDI_PORT_WIDTH_MASK) >> DDI_PORT_WIDTH_SHIFT) + 1;
if (DISPLAY_VER(dev_priv) >= 12)
pipe_config->mst_master_transcoder =
REG_FIELD_GET(TRANS_DDI_MST_TRANSPORT_SELECT_MASK, temp);
intel_cpu_transcoder_get_m1_n1(crtc, cpu_transcoder,
&pipe_config->dp_m_n);
if (DISPLAY_VER(dev_priv) >= 11)
pipe_config->fec_enable =
intel_de_read(dev_priv,
dp_tp_ctl_reg(encoder, pipe_config)) & DP_TP_CTL_FEC_ENABLE;
pipe_config->infoframes.enable |=
intel_hdmi_infoframes_enabled(encoder, pipe_config);
break;
default:
break;
if (ddi_mode == TRANS_DDI_MODE_SELECT_HDMI) {
intel_ddi_read_func_ctl_hdmi(encoder, pipe_config, ddi_func_ctl);
} else if (ddi_mode == TRANS_DDI_MODE_SELECT_DVI) {
intel_ddi_read_func_ctl_dvi(encoder, pipe_config, ddi_func_ctl);
} else if (ddi_mode == TRANS_DDI_MODE_SELECT_FDI_OR_128B132B && !HAS_DP20(display)) {
intel_ddi_read_func_ctl_fdi(encoder, pipe_config, ddi_func_ctl);
} else if (ddi_mode == TRANS_DDI_MODE_SELECT_DP_SST) {
intel_ddi_read_func_ctl_dp_sst(encoder, pipe_config, ddi_func_ctl);
} else if (ddi_mode == TRANS_DDI_MODE_SELECT_DP_MST ||
(ddi_mode == TRANS_DDI_MODE_SELECT_FDI_OR_128B132B && HAS_DP20(display))) {
intel_ddi_read_func_ctl_dp_mst(encoder, pipe_config, ddi_func_ctl);
}
}
/*
* Note: Also called from the ->get_config of the MST stream encoders on their
* primary encoder, via the platform specific hooks here. See also the comment
* for intel_ddi_pre_enable().
*/
static void intel_ddi_get_config(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config)
{
@ -4690,7 +4771,7 @@ static bool intel_ddi_a_force_4_lanes(struct intel_digital_port *dig_port)
if (dig_port->base.port != PORT_A)
return false;
if (dig_port->saved_port_bits & DDI_A_4_LANES)
if (dig_port->ddi_a_4_lanes)
return false;
/* Broxton/Geminilake: Bspec says that DDI_A_4_LANES is the only
@ -4728,7 +4809,7 @@ intel_ddi_max_lanes(struct intel_digital_port *dig_port)
if (intel_ddi_a_force_4_lanes(dig_port)) {
drm_dbg_kms(&dev_priv->drm,
"Forcing DDI_A_4_LANES for port A\n");
dig_port->saved_port_bits |= DDI_A_4_LANES;
dig_port->ddi_a_4_lanes = true;
max_lanes = 4;
}
@ -4907,6 +4988,7 @@ void intel_ddi_init(struct intel_display *display,
bool init_hdmi, init_dp;
enum port port;
enum phy phy;
u32 ddi_buf_ctl;
port = intel_bios_encoder_port(devdata);
if (port == PORT_NONE)
@ -5030,10 +5112,10 @@ void intel_ddi_init(struct intel_display *display,
encoder->compute_output_type = intel_ddi_compute_output_type;
encoder->compute_config = intel_ddi_compute_config;
encoder->compute_config_late = intel_ddi_compute_config_late;
encoder->enable = intel_enable_ddi;
encoder->enable = intel_ddi_enable;
encoder->pre_pll_enable = intel_ddi_pre_pll_enable;
encoder->pre_enable = intel_ddi_pre_enable;
encoder->disable = intel_disable_ddi;
encoder->disable = intel_ddi_disable;
encoder->post_pll_disable = intel_ddi_post_pll_disable;
encoder->post_disable = intel_ddi_post_disable;
encoder->update_pipe = intel_ddi_update_pipe;
@ -5156,17 +5238,12 @@ void intel_ddi_init(struct intel_display *display,
else
encoder->hpd_pin = intel_hpd_pin_default(dev_priv, port);
if (DISPLAY_VER(dev_priv) >= 11)
dig_port->saved_port_bits =
intel_de_read(dev_priv, DDI_BUF_CTL(port))
& DDI_BUF_PORT_REVERSAL;
else
dig_port->saved_port_bits =
intel_de_read(dev_priv, DDI_BUF_CTL(port))
& (DDI_BUF_PORT_REVERSAL | DDI_A_4_LANES);
ddi_buf_ctl = intel_de_read(dev_priv, DDI_BUF_CTL(port));
if (intel_bios_encoder_lane_reversal(devdata))
dig_port->saved_port_bits |= DDI_BUF_PORT_REVERSAL;
dig_port->lane_reversal = intel_bios_encoder_lane_reversal(devdata) ||
ddi_buf_ctl & DDI_BUF_PORT_REVERSAL;
dig_port->ddi_a_4_lanes = DISPLAY_VER(dev_priv) < 11 && ddi_buf_ctl & DDI_A_4_LANES;
dig_port->dp.output_reg = INVALID_MMIO_REG;
dig_port->max_lanes = intel_ddi_max_lanes(dig_port);

@ -26,10 +26,12 @@ enum transcoder;
i915_reg_t dp_tp_ctl_reg(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state);
i915_reg_t dp_tp_status_reg(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state);
i915_reg_t hsw_chicken_trans_reg(struct drm_i915_private *i915,
enum transcoder cpu_transcoder);
void intel_ddi_clear_act_sent(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state);
void intel_ddi_wait_for_act_sent(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state);
void intel_ddi_fdi_post_disable(struct intel_atomic_state *state,
struct intel_encoder *intel_encoder,
const struct intel_crtc_state *old_crtc_state,
@ -57,6 +59,8 @@ void intel_wait_ddi_buf_idle(struct drm_i915_private *dev_priv,
void intel_ddi_init(struct intel_display *display,
const struct intel_bios_encoder_data *devdata);
bool intel_ddi_get_hw_state(struct intel_encoder *encoder, enum pipe *pipe);
void intel_ddi_config_transcoder_func(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state);
void intel_ddi_enable_transcoder_func(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state);
void intel_ddi_disable_transcoder_func(const struct intel_crtc_state *crtc_state);

@ -1687,18 +1687,24 @@ dg2_get_snps_buf_trans(struct intel_encoder *encoder,
}
static const struct intel_ddi_buf_trans *
mtl_get_cx0_buf_trans(struct intel_encoder *encoder,
mtl_get_c10_buf_trans(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
int *n_entries)
{
if (intel_crtc_has_dp_encoder(crtc_state) && crtc_state->port_clock >= 1000000)
return intel_get_buf_trans(&mtl_c10_trans_dp14, n_entries);
}
static const struct intel_ddi_buf_trans *
mtl_get_c20_buf_trans(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
int *n_entries)
{
if (intel_crtc_has_dp_encoder(crtc_state) && intel_dp_is_uhbr(crtc_state))
return intel_get_buf_trans(&mtl_c20_trans_uhbr, n_entries);
else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI) && !(intel_encoder_is_c10phy(encoder)))
else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
return intel_get_buf_trans(&mtl_c20_trans_hdmi, n_entries);
else if (!intel_encoder_is_c10phy(encoder))
return intel_get_buf_trans(&mtl_c20_trans_dp14, n_entries);
else
return intel_get_buf_trans(&mtl_c10_trans_dp14, n_entries);
return intel_get_buf_trans(&mtl_c20_trans_dp14, n_entries);
}
void intel_ddi_buf_trans_init(struct intel_encoder *encoder)
@ -1706,7 +1712,10 @@ void intel_ddi_buf_trans_init(struct intel_encoder *encoder)
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
if (DISPLAY_VER(i915) >= 14) {
encoder->get_buf_trans = mtl_get_cx0_buf_trans;
if (intel_encoder_is_c10phy(encoder))
encoder->get_buf_trans = mtl_get_c10_buf_trans;
else
encoder->get_buf_trans = mtl_get_c20_buf_trans;
} else if (IS_DG2(i915)) {
encoder->get_buf_trans = dg2_get_snps_buf_trans;
} else if (IS_ALDERLAKE_P(i915)) {

@ -117,6 +117,16 @@ __intel_de_wait_for_register_nowl(struct intel_display *display,
value, timeout);
}
static inline int
__intel_de_wait_for_register_atomic_nowl(struct intel_display *display,
i915_reg_t reg,
u32 mask, u32 value,
unsigned int fast_timeout_us)
{
return __intel_wait_for_register(__to_uncore(display), reg, mask,
value, fast_timeout_us, 0, NULL);
}
static inline int
intel_de_wait(struct intel_display *display, i915_reg_t reg,
u32 mask, u32 value, unsigned int timeout)

@ -511,6 +511,7 @@ void vlv_wait_port_ready(struct intel_display *display,
void intel_enable_transcoder(const struct intel_crtc_state *new_crtc_state)
{
struct intel_display *display = to_intel_display(new_crtc_state);
struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc);
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
enum transcoder cpu_transcoder = new_crtc_state->cpu_transcoder;
@ -554,8 +555,7 @@ void intel_enable_transcoder(const struct intel_crtc_state *new_crtc_state)
if (DISPLAY_VER(dev_priv) == 14)
set |= DP_FEC_BS_JITTER_WA;
intel_de_rmw(dev_priv,
hsw_chicken_trans_reg(dev_priv, cpu_transcoder),
intel_de_rmw(display, CHICKEN_TRANS(display, cpu_transcoder),
clear, set);
}
@ -591,6 +591,7 @@ void intel_enable_transcoder(const struct intel_crtc_state *new_crtc_state)
void intel_disable_transcoder(const struct intel_crtc_state *old_crtc_state)
{
struct intel_display *display = to_intel_display(old_crtc_state);
struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc);
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
enum transcoder cpu_transcoder = old_crtc_state->cpu_transcoder;
@ -628,7 +629,7 @@ void intel_disable_transcoder(const struct intel_crtc_state *old_crtc_state)
intel_de_write(dev_priv, TRANSCONF(dev_priv, cpu_transcoder), val);
if (DISPLAY_VER(dev_priv) >= 12)
intel_de_rmw(dev_priv, hsw_chicken_trans_reg(dev_priv, cpu_transcoder),
intel_de_rmw(display, CHICKEN_TRANS(display, cpu_transcoder),
FECSTALL_DIS_DPTSTREAM_DPTTG, 0);
if ((val & TRANSCONF_ENABLE) == 0)
@ -1744,10 +1745,9 @@ static void hsw_set_linetime_wm(const struct intel_crtc_state *crtc_state)
static void hsw_set_frame_start_delay(const struct intel_crtc_state *crtc_state)
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
struct intel_display *display = to_intel_display(crtc_state);
intel_de_rmw(i915, hsw_chicken_trans_reg(i915, crtc_state->cpu_transcoder),
intel_de_rmw(display, CHICKEN_TRANS(display, crtc_state->cpu_transcoder),
HSW_FRAME_START_DELAY_MASK,
HSW_FRAME_START_DELAY(crtc_state->framestart_delay - 1));
}
@ -2371,7 +2371,7 @@ static bool intel_crtc_supports_double_wide(const struct intel_crtc *crtc)
const struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
/* GDG double wide on either pipe, otherwise pipe A only */
return DISPLAY_VER(dev_priv) < 4 &&
return HAS_DOUBLE_WIDE(dev_priv) &&
(crtc->pipe == PIPE_A || IS_I915G(dev_priv));
}
@ -3137,9 +3137,14 @@ bdw_get_pipe_misc_output_format(struct intel_crtc *crtc)
tmp = intel_de_read(dev_priv, PIPE_MISC(crtc->pipe));
if (tmp & PIPE_MISC_YUV420_ENABLE) {
/* We support 4:2:0 in full blend mode only */
drm_WARN_ON(&dev_priv->drm,
(tmp & PIPE_MISC_YUV420_MODE_FULL_BLEND) == 0);
/*
* We support 4:2:0 in full blend mode only.
* For xe3_lpd+ this is implied in YUV420 Enable bit.
* Ensure the same for prior platforms in YUV420 Mode bit.
*/
if (DISPLAY_VER(dev_priv) < 30)
drm_WARN_ON(&dev_priv->drm,
(tmp & PIPE_MISC_YUV420_MODE_FULL_BLEND) == 0);
return INTEL_OUTPUT_FORMAT_YCBCR420;
} else if (tmp & PIPE_MISC_OUTPUT_COLORSPACE_YUV) {
@ -3207,7 +3212,7 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
intel_color_get_config(pipe_config);
if (DISPLAY_VER(dev_priv) < 4)
if (HAS_DOUBLE_WIDE(dev_priv))
pipe_config->double_wide = tmp & TRANSCONF_DOUBLE_WIDE;
intel_get_transcoder_timings(crtc, pipe_config);
@ -3388,8 +3393,8 @@ static void bdw_set_pipe_misc(struct intel_dsb *dsb,
val |= PIPE_MISC_OUTPUT_COLORSPACE_YUV;
if (crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420)
val |= PIPE_MISC_YUV420_ENABLE |
PIPE_MISC_YUV420_MODE_FULL_BLEND;
val |= DISPLAY_VER(display) >= 30 ? PIPE_MISC_YUV420_ENABLE :
PIPE_MISC_YUV420_ENABLE | PIPE_MISC_YUV420_MODE_FULL_BLEND;
if (DISPLAY_VER(dev_priv) >= 11 && is_hdr_mode(crtc_state))
val |= PIPE_MISC_HDR_MODE_PRECISION;
@ -3746,12 +3751,13 @@ static u8 fixup_ultrajoiner_secondary_pipes(u8 ultrajoiner_primary_pipes,
static void enabled_ultrajoiner_pipes(struct drm_i915_private *i915,
u8 *primary_pipes, u8 *secondary_pipes)
{
struct intel_display *display = &i915->display;
struct intel_crtc *crtc;
*primary_pipes = 0;
*secondary_pipes = 0;
if (!HAS_ULTRAJOINER(i915))
if (!HAS_ULTRAJOINER(display))
return;
for_each_intel_crtc_in_pipe_mask(&i915->drm, crtc,
@ -4111,6 +4117,7 @@ static void intel_joiner_get_config(struct intel_crtc_state *crtc_state)
static bool hsw_get_pipe_config(struct intel_crtc *crtc,
struct intel_crtc_state *pipe_config)
{
struct intel_display *display = to_intel_display(crtc);
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
bool active;
u32 tmp;
@ -4187,7 +4194,7 @@ static bool hsw_get_pipe_config(struct intel_crtc *crtc,
}
if (!transcoder_is_dsi(pipe_config->cpu_transcoder)) {
tmp = intel_de_read(dev_priv, hsw_chicken_trans_reg(dev_priv, pipe_config->cpu_transcoder));
tmp = intel_de_read(display, CHICKEN_TRANS(display, pipe_config->cpu_transcoder));
pipe_config->framestart_delay = REG_FIELD_GET(HSW_FRAME_START_DELAY_MASK, tmp) + 1;
} else {
@ -4545,6 +4552,7 @@ static int hsw_compute_linetime_wm(struct intel_atomic_state *state,
static int intel_crtc_atomic_check(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
struct intel_display *display = to_intel_display(crtc);
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
struct intel_crtc_state *crtc_state =
intel_atomic_get_new_crtc_state(state, crtc);
@ -4581,12 +4589,12 @@ static int intel_crtc_atomic_check(struct intel_atomic_state *state,
return ret;
}
ret = intel_atomic_setup_scalers(dev_priv, crtc, crtc_state);
ret = intel_atomic_setup_scalers(state, crtc);
if (ret)
return ret;
}
if (HAS_IPS(dev_priv)) {
if (HAS_IPS(display)) {
ret = hsw_ips_compute_config(state, crtc);
if (ret)
return ret;
@ -5208,7 +5216,7 @@ pipe_config_dp_vsc_sdp_mismatch(struct drm_printer *p, bool fastset,
const struct drm_dp_vsc_sdp *a,
const struct drm_dp_vsc_sdp *b)
{
pipe_config_mismatch(p, fastset, crtc, name, "dp sdp");
pipe_config_mismatch(p, fastset, crtc, name, "dp vsc sdp");
drm_printf(p, "expected:\n");
drm_dp_vsc_sdp_log(p, a);
@ -5217,27 +5225,18 @@ pipe_config_dp_vsc_sdp_mismatch(struct drm_printer *p, bool fastset,
}
static void
pipe_config_dp_as_sdp_mismatch(struct drm_i915_private *i915,
bool fastset, const char *name,
pipe_config_dp_as_sdp_mismatch(struct drm_printer *p, bool fastset,
const struct intel_crtc *crtc,
const char *name,
const struct drm_dp_as_sdp *a,
const struct drm_dp_as_sdp *b)
{
struct drm_printer p;
pipe_config_mismatch(p, fastset, crtc, name, "dp as sdp");
if (fastset) {
p = drm_dbg_printer(&i915->drm, DRM_UT_KMS, NULL);
drm_printf(&p, "fastset requirement not met in %s dp sdp\n", name);
} else {
p = drm_err_printer(&i915->drm, NULL);
drm_printf(&p, "mismatch in %s dp sdp\n", name);
}
drm_printf(&p, "expected:\n");
drm_dp_as_sdp_log(&p, a);
drm_printf(&p, "found:\n");
drm_dp_as_sdp_log(&p, b);
drm_printf(p, "expected:\n");
drm_dp_as_sdp_log(p, a);
drm_printf(p, "found:\n");
drm_dp_as_sdp_log(p, b);
}
/* Returns the length up to and including the last differing byte */
@ -5260,26 +5259,13 @@ pipe_config_buffer_mismatch(struct drm_printer *p, bool fastset,
const char *name,
const u8 *a, const u8 *b, size_t len)
{
const char *loglevel;
if (fastset) {
if (!drm_debug_enabled(DRM_UT_KMS))
return;
loglevel = KERN_DEBUG;
} else {
loglevel = KERN_ERR;
}
pipe_config_mismatch(p, fastset, crtc, name, "buffer");
/* only dump up to the last difference */
len = memcmp_diff_len(a, b, len);
print_hex_dump(loglevel, "expected: ", DUMP_PREFIX_NONE,
16, 0, a, len, false);
print_hex_dump(loglevel, "found: ", DUMP_PREFIX_NONE,
16, 0, b, len, false);
drm_print_hex_dump(p, "expected: ", a, len);
drm_print_hex_dump(p, "found: ", b, len);
}
static void
@ -5322,6 +5308,7 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
const struct intel_crtc_state *pipe_config,
bool fastset)
{
struct intel_display *display = to_intel_display(current_config);
struct drm_i915_private *dev_priv = to_i915(current_config->uapi.crtc->dev);
struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);
struct drm_printer p;
@ -5498,7 +5485,7 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
#define PIPE_CONF_CHECK_DP_AS_SDP(name) do { \
if (!intel_compare_dp_as_sdp(&current_config->infoframes.name, \
&pipe_config->infoframes.name)) { \
pipe_config_dp_as_sdp_mismatch(dev_priv, fastset, __stringify(name), \
pipe_config_dp_as_sdp_mismatch(&p, fastset, crtc, __stringify(name), \
&current_config->infoframes.name, \
&pipe_config->infoframes.name); \
ret = false; \
@ -5562,7 +5549,7 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
PIPE_CONF_CHECK_I(lane_count);
PIPE_CONF_CHECK_X(lane_lat_optim_mask);
if (HAS_DOUBLE_BUFFERED_M_N(dev_priv)) {
if (HAS_DOUBLE_BUFFERED_M_N(display)) {
if (!fastset || !pipe_config->update_m_n)
PIPE_CONF_CHECK_M_N(dp_m_n);
} else {
@ -5743,7 +5730,7 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
PIPE_CONF_CHECK_I(dsc.config.nsl_bpg_offset);
PIPE_CONF_CHECK_BOOL(dsc.compression_enable);
PIPE_CONF_CHECK_BOOL(dsc.dsc_split);
PIPE_CONF_CHECK_I(dsc.num_streams);
PIPE_CONF_CHECK_I(dsc.compressed_bpp_x16);
PIPE_CONF_CHECK_BOOL(splitter.enable);
@ -6797,6 +6784,7 @@ static int intel_atomic_check_config_and_link(struct intel_atomic_state *state)
int intel_atomic_check(struct drm_device *dev,
struct drm_atomic_state *_state)
{
struct intel_display *display = to_intel_display(dev);
struct drm_i915_private *dev_priv = to_i915(dev);
struct intel_atomic_state *state = to_intel_atomic_state(_state);
struct intel_crtc_state *old_crtc_state, *new_crtc_state;
@ -6804,7 +6792,7 @@ int intel_atomic_check(struct drm_device *dev,
int ret, i;
bool any_ms = false;
if (!intel_display_driver_check_access(dev_priv))
if (!intel_display_driver_check_access(display))
return -ENODEV;
for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
@ -7572,7 +7560,7 @@ static void intel_atomic_dsb_cleanup(struct intel_crtc_state *crtc_state)
static void intel_atomic_cleanup_work(struct work_struct *work)
{
struct intel_atomic_state *state =
container_of(work, struct intel_atomic_state, base.commit_work);
container_of(work, struct intel_atomic_state, cleanup_work);
struct drm_i915_private *i915 = to_i915(state->base.dev);
struct intel_crtc_state *old_crtc_state;
struct intel_crtc *crtc;
@ -7822,6 +7810,8 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
/* Now enable the clocks, plane, pipe, and connectors that we set up. */
dev_priv->display.funcs.display->commit_modeset_enables(state);
intel_program_dpkgc_latency(state);
if (state->modeset)
intel_set_cdclk_post_plane_update(state);
@ -7927,8 +7917,8 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
* schedule point (cond_resched()) here anyway to keep latencies
* down.
*/
INIT_WORK(&state->base.commit_work, intel_atomic_cleanup_work);
queue_work(system_highpri_wq, &state->base.commit_work);
INIT_WORK(&state->cleanup_work, intel_atomic_cleanup_work);
queue_work(dev_priv->display.wq.cleanup, &state->cleanup_work);
}
static void intel_atomic_commit_work(struct work_struct *work)
@ -8308,11 +8298,12 @@ void intel_setup_outputs(struct drm_i915_private *dev_priv)
static int max_dotclock(struct drm_i915_private *i915)
{
int max_dotclock = i915->display.cdclk.max_dotclk_freq;
struct intel_display *display = &i915->display;
int max_dotclock = display->cdclk.max_dotclk_freq;
if (HAS_ULTRAJOINER(i915))
if (HAS_ULTRAJOINER(display))
max_dotclock *= 4;
else if (HAS_UNCOMPRESSED_JOINER(i915) || HAS_BIGJOINER(i915))
else if (HAS_UNCOMPRESSED_JOINER(display) || HAS_BIGJOINER(display))
max_dotclock *= 2;
return max_dotclock;

@ -238,9 +238,6 @@ enum phy_fia {
for ((__phy) = PHY_A; (__phy) < I915_MAX_PHYS; (__phy)++) \
for_each_if((__phys_mask) & BIT(__phy))
#define for_each_crtc(dev, crtc) \
list_for_each_entry(crtc, &(dev)->mode_config.crtc_list, head)
#define for_each_intel_plane(dev, intel_plane) \
list_for_each_entry(intel_plane, \
&(dev)->mode_config.plane_list, \

@ -453,7 +453,14 @@ struct intel_display {
} ips;
struct {
bool display_irqs_enabled;
/*
* Most platforms treat the display irq block as an always-on
* power domain. vlv/chv can disable it at runtime and need
* special care to avoid writing any of the display block
* registers outside of the power domain. We defer setting up
* the display irqs in this case to the runtime pm.
*/
bool vlv_display_irqs_enabled;
/* For i915gm/i945gm vblank irq workaround */
u8 vblank_enabled;
@ -505,6 +512,11 @@ struct intel_display {
/* restore state for suspend/resume and display reset */
struct drm_atomic_state *modeset_state;
struct drm_modeset_acquire_ctx reset_ctx;
u32 saveDSPARB;
u32 saveSWF0[16];
u32 saveSWF1[16];
u32 saveSWF3[3];
u16 saveGCDGMBUS;
} restore;
struct {
@ -542,6 +554,9 @@ struct intel_display {
/* unbound hipri wq for page flips/plane updates */
struct workqueue_struct *flip;
/* hipri wq for commit cleanups */
struct workqueue_struct *cleanup;
} wq;
/* Grouping using named structs. Keep sorted. */

@ -730,11 +730,12 @@ static bool
intel_lpsp_power_well_enabled(struct drm_i915_private *i915,
enum i915_power_well_id power_well_id)
{
struct intel_display *display = &i915->display;
intel_wakeref_t wakeref;
bool is_enabled;
wakeref = intel_runtime_pm_get(&i915->runtime_pm);
is_enabled = intel_display_power_well_is_enabled(i915,
is_enabled = intel_display_power_well_is_enabled(display,
power_well_id);
intel_runtime_pm_put(&i915->runtime_pm, wakeref);
@ -1331,7 +1332,7 @@ static ssize_t i915_joiner_write(struct file *file,
{
struct seq_file *m = file->private_data;
struct intel_connector *connector = m->private;
struct drm_i915_private *i915 = to_i915(connector->base.dev);
struct intel_display *display = to_intel_display(connector);
int force_joined_pipes = 0;
int ret;
@ -1349,7 +1350,7 @@ static ssize_t i915_joiner_write(struct file *file,
connector->force_joined_pipes = force_joined_pipes;
break;
case 4:
if (HAS_ULTRAJOINER(i915)) {
if (HAS_ULTRAJOINER(display)) {
connector->force_joined_pipes = force_joined_pipes;
break;
}

@ -16,6 +16,7 @@
#include "intel_display_params.h"
#include "intel_display_power.h"
#include "intel_display_reg_defs.h"
#include "intel_display_types.h"
#include "intel_fbc.h"
#include "intel_step.h"
@ -252,6 +253,7 @@ static const struct intel_display_device_info no_display = {};
static const struct platform_desc i830_desc = {
PLATFORM(i830),
PLATFORM_GROUP(mobile),
.info = &(const struct intel_display_device_info) {
I830_DISPLAY,
@ -270,6 +272,7 @@ static const struct platform_desc i845_desc = {
static const struct platform_desc i85x_desc = {
PLATFORM(i85x),
PLATFORM_GROUP(mobile),
.info = &(const struct intel_display_device_info) {
I830_DISPLAY,
@ -312,6 +315,7 @@ static const struct platform_desc i915g_desc = {
static const struct platform_desc i915gm_desc = {
PLATFORM(i915gm),
PLATFORM_GROUP(mobile),
.info = &(const struct intel_display_device_info) {
GEN3_DISPLAY,
I9XX_COLORS,
@ -336,6 +340,7 @@ static const struct platform_desc i945g_desc = {
static const struct platform_desc i945gm_desc = {
PLATFORM(i915gm),
PLATFORM_GROUP(mobile),
.info = &(const struct intel_display_device_info) {
GEN3_DISPLAY,
I9XX_COLORS,
@ -357,13 +362,21 @@ static const struct platform_desc g33_desc = {
},
};
static const struct platform_desc pnv_desc = {
static const struct intel_display_device_info pnv_display = {
GEN3_DISPLAY,
I9XX_COLORS,
.has_hotplug = 1,
};
static const struct platform_desc pnv_g_desc = {
PLATFORM(pineview),
.info = &(const struct intel_display_device_info) {
GEN3_DISPLAY,
I9XX_COLORS,
.has_hotplug = 1,
},
.info = &pnv_display,
};
static const struct platform_desc pnv_m_desc = {
PLATFORM(pineview),
PLATFORM_GROUP(mobile),
.info = &pnv_display,
};
#define GEN4_DISPLAY \
@ -390,6 +403,7 @@ static const struct platform_desc i965g_desc = {
static const struct platform_desc i965gm_desc = {
PLATFORM(i965gm),
PLATFORM_GROUP(mobile),
.info = &(const struct intel_display_device_info) {
GEN4_DISPLAY,
.has_overlay = 1,
@ -413,6 +427,7 @@ static const struct platform_desc g45_desc = {
static const struct platform_desc gm45_desc = {
PLATFORM(gm45),
PLATFORM_GROUP(g4x),
PLATFORM_GROUP(mobile),
.info = &(const struct intel_display_device_info) {
GEN4_DISPLAY,
.supports_tv = 1,
@ -443,6 +458,7 @@ static const struct platform_desc ilk_d_desc = {
static const struct platform_desc ilk_m_desc = {
PLATFORM(ironlake),
PLATFORM_GROUP(mobile),
.info = &(const struct intel_display_device_info) {
ILK_DISPLAY,
@ -450,38 +466,54 @@ static const struct platform_desc ilk_m_desc = {
},
};
static const struct platform_desc snb_desc = {
PLATFORM(sandybridge),
.info = &(const struct intel_display_device_info) {
.has_hotplug = 1,
I9XX_PIPE_OFFSETS,
I9XX_CURSOR_OFFSETS,
ILK_COLORS,
static const struct intel_display_device_info snb_display = {
.has_hotplug = 1,
I9XX_PIPE_OFFSETS,
I9XX_CURSOR_OFFSETS,
ILK_COLORS,
.__runtime_defaults.ip.ver = 6,
.__runtime_defaults.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B),
.__runtime_defaults.cpu_transcoder_mask =
BIT(TRANSCODER_A) | BIT(TRANSCODER_B),
.__runtime_defaults.port_mask = BIT(PORT_A) | BIT(PORT_B) | BIT(PORT_C) | BIT(PORT_D), /* DP A, SDVO/HDMI/DP B, HDMI/DP C/D */
.__runtime_defaults.fbc_mask = BIT(INTEL_FBC_A),
},
.__runtime_defaults.ip.ver = 6,
.__runtime_defaults.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B),
.__runtime_defaults.cpu_transcoder_mask =
BIT(TRANSCODER_A) | BIT(TRANSCODER_B),
.__runtime_defaults.port_mask = BIT(PORT_A) | BIT(PORT_B) | BIT(PORT_C) | BIT(PORT_D), /* DP A, SDVO/HDMI/DP B, HDMI/DP C/D */
.__runtime_defaults.fbc_mask = BIT(INTEL_FBC_A),
};
static const struct platform_desc ivb_desc = {
PLATFORM(ivybridge),
.info = &(const struct intel_display_device_info) {
.has_hotplug = 1,
IVB_PIPE_OFFSETS,
IVB_CURSOR_OFFSETS,
IVB_COLORS,
static const struct platform_desc snb_d_desc = {
PLATFORM(sandybridge),
.info = &snb_display,
};
.__runtime_defaults.ip.ver = 7,
.__runtime_defaults.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C),
.__runtime_defaults.cpu_transcoder_mask =
BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | BIT(TRANSCODER_C),
.__runtime_defaults.port_mask = BIT(PORT_A) | BIT(PORT_B) | BIT(PORT_C) | BIT(PORT_D), /* DP A, SDVO/HDMI/DP B, HDMI/DP C/D */
.__runtime_defaults.fbc_mask = BIT(INTEL_FBC_A),
},
static const struct platform_desc snb_m_desc = {
PLATFORM(sandybridge),
PLATFORM_GROUP(mobile),
.info = &snb_display,
};
static const struct intel_display_device_info ivb_display = {
.has_hotplug = 1,
IVB_PIPE_OFFSETS,
IVB_CURSOR_OFFSETS,
IVB_COLORS,
.__runtime_defaults.ip.ver = 7,
.__runtime_defaults.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C),
.__runtime_defaults.cpu_transcoder_mask =
BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | BIT(TRANSCODER_C),
.__runtime_defaults.port_mask = BIT(PORT_A) | BIT(PORT_B) | BIT(PORT_C) | BIT(PORT_D), /* DP A, SDVO/HDMI/DP B, HDMI/DP C/D */
.__runtime_defaults.fbc_mask = BIT(INTEL_FBC_A),
};
static const struct platform_desc ivb_d_desc = {
PLATFORM(ivybridge),
.info = &ivb_display,
};
static const struct platform_desc ivb_m_desc = {
PLATFORM(ivybridge),
PLATFORM_GROUP(mobile),
.info = &ivb_display,
};
static const struct platform_desc vlv_desc = {
@ -1011,6 +1043,7 @@ static const enum intel_step dg1_steppings[] = {
static const struct platform_desc dg1_desc = {
PLATFORM(dg1),
PLATFORM_GROUP(dgfx),
.info = &(const struct intel_display_device_info) {
XE_D_DISPLAY,
@ -1238,6 +1271,7 @@ static const enum intel_step dg2_g12_steppings[] = {
static const struct platform_desc dg2_desc = {
PLATFORM(dg2),
PLATFORM_GROUP(dgfx),
.subplatforms = (const struct subplatform_desc[]) {
{
SUBPLATFORM(dg2, g10),
@ -1338,6 +1372,7 @@ static const struct platform_desc lnl_desc = {
static const struct platform_desc bmg_desc = {
PLATFORM(battlemage),
PLATFORM_GROUP(dgfx),
};
static const struct platform_desc ptl_desc = {
@ -1381,11 +1416,14 @@ static const struct {
INTEL_I965GM_IDS(INTEL_DISPLAY_DEVICE, &i965gm_desc),
INTEL_GM45_IDS(INTEL_DISPLAY_DEVICE, &gm45_desc),
INTEL_G45_IDS(INTEL_DISPLAY_DEVICE, &g45_desc),
INTEL_PNV_IDS(INTEL_DISPLAY_DEVICE, &pnv_desc),
INTEL_PNV_G_IDS(INTEL_DISPLAY_DEVICE, &pnv_g_desc),
INTEL_PNV_M_IDS(INTEL_DISPLAY_DEVICE, &pnv_m_desc),
INTEL_ILK_D_IDS(INTEL_DISPLAY_DEVICE, &ilk_d_desc),
INTEL_ILK_M_IDS(INTEL_DISPLAY_DEVICE, &ilk_m_desc),
INTEL_SNB_IDS(INTEL_DISPLAY_DEVICE, &snb_desc),
INTEL_IVB_IDS(INTEL_DISPLAY_DEVICE, &ivb_desc),
INTEL_SNB_D_IDS(INTEL_DISPLAY_DEVICE, &snb_d_desc),
INTEL_SNB_M_IDS(INTEL_DISPLAY_DEVICE, &snb_m_desc),
INTEL_IVB_D_IDS(INTEL_DISPLAY_DEVICE, &ivb_d_desc),
INTEL_IVB_M_IDS(INTEL_DISPLAY_DEVICE, &ivb_m_desc),
INTEL_HSW_IDS(INTEL_DISPLAY_DEVICE, &hsw_desc),
INTEL_VLV_IDS(INTEL_DISPLAY_DEVICE, &vlv_desc),
INTEL_BDW_IDS(INTEL_DISPLAY_DEVICE, &bdw_desc),
@ -1429,9 +1467,9 @@ static const struct {
};
static const struct intel_display_device_info *
probe_gmdid_display(struct drm_i915_private *i915, struct intel_display_ip_ver *ip_ver)
probe_gmdid_display(struct intel_display *display, struct intel_display_ip_ver *ip_ver)
{
struct pci_dev *pdev = to_pci_dev(i915->drm.dev);
struct pci_dev *pdev = to_pci_dev(display->drm->dev);
struct intel_display_ip_ver gmd_id;
void __iomem *addr;
u32 val;
@ -1439,7 +1477,8 @@ probe_gmdid_display(struct drm_i915_private *i915, struct intel_display_ip_ver *
addr = pci_iomap_range(pdev, 0, i915_mmio_reg_offset(GMD_ID_DISPLAY), sizeof(u32));
if (!addr) {
drm_err(&i915->drm, "Cannot map MMIO BAR to read display GMD_ID\n");
drm_err(display->drm,
"Cannot map MMIO BAR to read display GMD_ID\n");
return NULL;
}
@ -1447,7 +1486,7 @@ probe_gmdid_display(struct drm_i915_private *i915, struct intel_display_ip_ver *
pci_iounmap(pdev, addr);
if (val == 0) {
drm_dbg_kms(&i915->drm, "Device doesn't have display\n");
drm_dbg_kms(display->drm, "Device doesn't have display\n");
return NULL;
}
@ -1463,7 +1502,8 @@ probe_gmdid_display(struct drm_i915_private *i915, struct intel_display_ip_ver *
}
}
drm_err(&i915->drm, "Unrecognized display IP version %d.%02d; disabling display.\n",
drm_err(display->drm,
"Unrecognized display IP version %d.%02d; disabling display.\n",
gmd_id.ver, gmd_id.rel);
return NULL;
}
@ -1564,10 +1604,9 @@ static void display_platforms_or(struct intel_display_platforms *dst,
bitmap_or(dst->bitmap, dst->bitmap, src->bitmap, display_platforms_num_bits());
}
void intel_display_device_probe(struct drm_i915_private *i915)
struct intel_display *intel_display_device_probe(struct pci_dev *pdev)
{
struct intel_display *display = &i915->display;
struct pci_dev *pdev = to_pci_dev(i915->drm.dev);
struct intel_display *display = to_intel_display(pdev);
const struct intel_display_device_info *info;
struct intel_display_ip_ver ip_ver = {};
const struct platform_desc *desc;
@ -1575,55 +1614,56 @@ void intel_display_device_probe(struct drm_i915_private *i915)
enum intel_step step;
/* Add drm device backpointer as early as possible. */
i915->display.drm = &i915->drm;
display->drm = pci_get_drvdata(pdev);
intel_display_params_copy(&i915->display.params);
intel_display_params_copy(&display->params);
if (has_no_display(pdev)) {
drm_dbg_kms(&i915->drm, "Device doesn't have display\n");
drm_dbg_kms(display->drm, "Device doesn't have display\n");
goto no_display;
}
desc = find_platform_desc(pdev);
if (!desc) {
drm_dbg_kms(&i915->drm, "Unknown device ID %04x; disabling display.\n",
drm_dbg_kms(display->drm,
"Unknown device ID %04x; disabling display.\n",
pdev->device);
goto no_display;
}
info = desc->info;
if (!info)
info = probe_gmdid_display(i915, &ip_ver);
info = probe_gmdid_display(display, &ip_ver);
if (!info)
goto no_display;
DISPLAY_INFO(i915) = info;
DISPLAY_INFO(display) = info;
memcpy(DISPLAY_RUNTIME_INFO(i915),
&DISPLAY_INFO(i915)->__runtime_defaults,
sizeof(*DISPLAY_RUNTIME_INFO(i915)));
memcpy(DISPLAY_RUNTIME_INFO(display),
&DISPLAY_INFO(display)->__runtime_defaults,
sizeof(*DISPLAY_RUNTIME_INFO(display)));
drm_WARN_ON(&i915->drm, !desc->name ||
drm_WARN_ON(display->drm, !desc->name ||
!display_platforms_weight(&desc->platforms));
display->platform = desc->platforms;
subdesc = find_subplatform_desc(pdev, desc);
if (subdesc) {
drm_WARN_ON(&i915->drm, !subdesc->name ||
drm_WARN_ON(display->drm, !subdesc->name ||
!display_platforms_weight(&subdesc->platforms));
display_platforms_or(&display->platform, &subdesc->platforms);
/* Ensure platform and subplatform are distinct */
drm_WARN_ON(&i915->drm,
drm_WARN_ON(display->drm,
display_platforms_weight(&display->platform) !=
display_platforms_weight(&desc->platforms) +
display_platforms_weight(&subdesc->platforms));
}
if (ip_ver.ver || ip_ver.rel || ip_ver.step) {
DISPLAY_RUNTIME_INFO(i915)->ip = ip_ver;
DISPLAY_RUNTIME_INFO(display)->ip = ip_ver;
step = STEP_A0 + ip_ver.step;
if (step > STEP_FUTURE) {
drm_dbg_kms(display->drm, "Using future display stepping\n");
@ -1634,29 +1674,32 @@ void intel_display_device_probe(struct drm_i915_private *i915)
subdesc ? &subdesc->step_info : NULL);
}
DISPLAY_RUNTIME_INFO(i915)->step = step;
DISPLAY_RUNTIME_INFO(display)->step = step;
drm_info(&i915->drm, "Found %s%s%s (device ID %04x) display version %u.%02u stepping %s\n",
drm_info(display->drm, "Found %s%s%s (device ID %04x) %s display version %u.%02u stepping %s\n",
desc->name, subdesc ? "/" : "", subdesc ? subdesc->name : "",
pdev->device, DISPLAY_RUNTIME_INFO(i915)->ip.ver,
DISPLAY_RUNTIME_INFO(i915)->ip.rel,
pdev->device, display->platform.dgfx ? "discrete" : "integrated",
DISPLAY_RUNTIME_INFO(display)->ip.ver,
DISPLAY_RUNTIME_INFO(display)->ip.rel,
step != STEP_NONE ? intel_step_name(step) : "N/A");
return;
return display;
no_display:
DISPLAY_INFO(i915) = &no_display;
DISPLAY_INFO(display) = &no_display;
return display;
}
void intel_display_device_remove(struct drm_i915_private *i915)
void intel_display_device_remove(struct intel_display *display)
{
intel_display_params_free(&i915->display.params);
intel_display_params_free(&display->params);
}
static void __intel_display_device_info_runtime_init(struct drm_i915_private *i915)
static void __intel_display_device_info_runtime_init(struct intel_display *display)
{
struct intel_display *display = &i915->display;
struct intel_display_runtime_info *display_runtime = DISPLAY_RUNTIME_INFO(i915);
struct drm_i915_private *i915 = to_i915(display->drm);
struct intel_display_runtime_info *display_runtime = DISPLAY_RUNTIME_INFO(display);
enum pipe pipe;
BUILD_BUG_ON(BITS_PER_TYPE(display_runtime->pipe_mask) < I915_MAX_PIPES);
@ -1664,35 +1707,35 @@ static void __intel_display_device_info_runtime_init(struct drm_i915_private *i9
BUILD_BUG_ON(BITS_PER_TYPE(display_runtime->port_mask) < I915_MAX_PORTS);
/* This covers both ULT and ULX */
if (IS_HASWELL_ULT(i915) || IS_BROADWELL_ULT(i915))
if (display->platform.haswell_ult || display->platform.broadwell_ult)
display_runtime->port_mask &= ~BIT(PORT_D);
if (IS_ICL_WITH_PORT_F(i915))
if (display->platform.icelake_port_f)
display_runtime->port_mask |= BIT(PORT_F);
/* Wa_14011765242: adl-s A0,A1 */
if (IS_ALDERLAKE_S(i915) && IS_DISPLAY_STEP(i915, STEP_A0, STEP_A2))
for_each_pipe(i915, pipe)
if (display->platform.alderlake_s && IS_DISPLAY_STEP(display, STEP_A0, STEP_A2))
for_each_pipe(display, pipe)
display_runtime->num_scalers[pipe] = 0;
else if (DISPLAY_VER(i915) >= 11) {
for_each_pipe(i915, pipe)
else if (DISPLAY_VER(display) >= 11) {
for_each_pipe(display, pipe)
display_runtime->num_scalers[pipe] = 2;
} else if (DISPLAY_VER(i915) >= 9) {
} else if (DISPLAY_VER(display) >= 9) {
display_runtime->num_scalers[PIPE_A] = 2;
display_runtime->num_scalers[PIPE_B] = 2;
display_runtime->num_scalers[PIPE_C] = 1;
}
if (DISPLAY_VER(i915) >= 13 || HAS_D12_PLANE_MINIMIZATION(i915))
for_each_pipe(i915, pipe)
if (DISPLAY_VER(display) >= 13 || HAS_D12_PLANE_MINIMIZATION(display))
for_each_pipe(display, pipe)
display_runtime->num_sprites[pipe] = 4;
else if (DISPLAY_VER(i915) >= 11)
for_each_pipe(i915, pipe)
else if (DISPLAY_VER(display) >= 11)
for_each_pipe(display, pipe)
display_runtime->num_sprites[pipe] = 6;
else if (DISPLAY_VER(i915) == 10)
for_each_pipe(i915, pipe)
else if (DISPLAY_VER(display) == 10)
for_each_pipe(display, pipe)
display_runtime->num_sprites[pipe] = 3;
else if (IS_BROXTON(i915)) {
else if (display->platform.broxton) {
/*
* Skylake and Broxton currently don't expose the topmost plane as its
* use is exclusive with the legacy cursor and we only want to expose
@ -1705,23 +1748,23 @@ static void __intel_display_device_info_runtime_init(struct drm_i915_private *i9
display_runtime->num_sprites[PIPE_A] = 2;
display_runtime->num_sprites[PIPE_B] = 2;
display_runtime->num_sprites[PIPE_C] = 1;
} else if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) {
for_each_pipe(i915, pipe)
} else if (display->platform.valleyview || display->platform.cherryview) {
for_each_pipe(display, pipe)
display_runtime->num_sprites[pipe] = 2;
} else if (DISPLAY_VER(i915) >= 5 || IS_G4X(i915)) {
for_each_pipe(i915, pipe)
} else if (DISPLAY_VER(display) >= 5 || display->platform.g4x) {
for_each_pipe(display, pipe)
display_runtime->num_sprites[pipe] = 1;
}
if ((IS_DGFX(i915) || DISPLAY_VER(i915) >= 14) &&
!(intel_de_read(i915, GU_CNTL_PROTECTED) & DEPRESENT)) {
drm_info(&i915->drm, "Display not present, disabling\n");
if ((display->platform.dgfx || DISPLAY_VER(display) >= 14) &&
!(intel_de_read(display, GU_CNTL_PROTECTED) & DEPRESENT)) {
drm_info(display->drm, "Display not present, disabling\n");
goto display_fused_off;
}
if (IS_DISPLAY_VER(i915, 7, 8) && HAS_PCH_SPLIT(i915)) {
u32 fuse_strap = intel_de_read(i915, FUSE_STRAP);
u32 sfuse_strap = intel_de_read(i915, SFUSE_STRAP);
if (IS_DISPLAY_VER(display, 7, 8) && HAS_PCH_SPLIT(i915)) {
u32 fuse_strap = intel_de_read(display, FUSE_STRAP);
u32 sfuse_strap = intel_de_read(display, SFUSE_STRAP);
/*
* SFUSE_STRAP is supposed to have a bit signalling the display
@ -1736,16 +1779,16 @@ static void __intel_display_device_info_runtime_init(struct drm_i915_private *i9
sfuse_strap & SFUSE_STRAP_DISPLAY_DISABLED ||
(HAS_PCH_CPT(i915) &&
!(sfuse_strap & SFUSE_STRAP_FUSE_LOCK))) {
drm_info(&i915->drm,
drm_info(display->drm,
"Display fused off, disabling\n");
goto display_fused_off;
} else if (fuse_strap & IVB_PIPE_C_DISABLE) {
drm_info(&i915->drm, "PipeC fused off\n");
drm_info(display->drm, "PipeC fused off\n");
display_runtime->pipe_mask &= ~BIT(PIPE_C);
display_runtime->cpu_transcoder_mask &= ~BIT(TRANSCODER_C);
}
} else if (DISPLAY_VER(i915) >= 9) {
u32 dfsm = intel_de_read(i915, SKL_DFSM);
} else if (DISPLAY_VER(display) >= 9) {
u32 dfsm = intel_de_read(display, SKL_DFSM);
if (dfsm & SKL_DFSM_PIPE_A_DISABLE) {
display_runtime->pipe_mask &= ~BIT(PIPE_A);
@ -1763,7 +1806,7 @@ static void __intel_display_device_info_runtime_init(struct drm_i915_private *i9
display_runtime->fbc_mask &= ~BIT(INTEL_FBC_C);
}
if (DISPLAY_VER(i915) >= 12 &&
if (DISPLAY_VER(display) >= 12 &&
(dfsm & TGL_DFSM_PIPE_D_DISABLE)) {
display_runtime->pipe_mask &= ~BIT(PIPE_D);
display_runtime->cpu_transcoder_mask &= ~BIT(TRANSCODER_D);
@ -1776,15 +1819,15 @@ static void __intel_display_device_info_runtime_init(struct drm_i915_private *i9
if (dfsm & SKL_DFSM_DISPLAY_HDCP_DISABLE)
display_runtime->has_hdcp = 0;
if (IS_DG2(i915) || DISPLAY_VER(i915) < 13) {
if (display->platform.dg2 || DISPLAY_VER(display) < 13) {
if (dfsm & SKL_DFSM_DISPLAY_PM_DISABLE)
display_runtime->fbc_mask = 0;
}
if (DISPLAY_VER(i915) >= 11 && (dfsm & ICL_DFSM_DMC_DISABLE))
if (DISPLAY_VER(display) >= 11 && (dfsm & ICL_DFSM_DMC_DISABLE))
display_runtime->has_dmc = 0;
if (IS_DISPLAY_VER(i915, 10, 12) &&
if (IS_DISPLAY_VER(display, 10, 12) &&
(dfsm & GLK_DFSM_DISPLAY_DSC_DISABLE))
display_runtime->has_dsc = 0;
@ -1793,8 +1836,8 @@ static void __intel_display_device_info_runtime_init(struct drm_i915_private *i9
display_runtime->has_dbuf_overlap_detection = false;
}
if (DISPLAY_VER(i915) >= 20) {
u32 cap = intel_de_read(i915, XE2LPD_DE_CAP);
if (DISPLAY_VER(display) >= 20) {
u32 cap = intel_de_read(display, XE2LPD_DE_CAP);
if (REG_FIELD_GET(XE2LPD_DE_CAP_DSC_MASK, cap) ==
XE2LPD_DE_CAP_DSC_REMOVED)
@ -1802,18 +1845,19 @@ static void __intel_display_device_info_runtime_init(struct drm_i915_private *i9
if (REG_FIELD_GET(XE2LPD_DE_CAP_SCALER_MASK, cap) ==
XE2LPD_DE_CAP_SCALER_SINGLE) {
for_each_pipe(i915, pipe)
for_each_pipe(display, pipe)
if (display_runtime->num_scalers[pipe])
display_runtime->num_scalers[pipe] = 1;
}
}
if (DISPLAY_VER(i915) >= 30)
if (DISPLAY_VER(display) >= 30)
display_runtime->edp_typec_support =
intel_de_read(display, PICA_PHY_CONFIG_CONTROL) & EDP_ON_TYPEC;
display_runtime->rawclk_freq = intel_read_rawclk(display);
drm_dbg_kms(&i915->drm, "rawclk rate: %d kHz\n", display_runtime->rawclk_freq);
drm_dbg_kms(display->drm, "rawclk rate: %d kHz\n",
display_runtime->rawclk_freq);
return;
@ -1821,21 +1865,21 @@ static void __intel_display_device_info_runtime_init(struct drm_i915_private *i9
memset(display_runtime, 0, sizeof(*display_runtime));
}
void intel_display_device_info_runtime_init(struct drm_i915_private *i915)
void intel_display_device_info_runtime_init(struct intel_display *display)
{
if (HAS_DISPLAY(i915))
__intel_display_device_info_runtime_init(i915);
if (HAS_DISPLAY(display))
__intel_display_device_info_runtime_init(display);
/* Display may have been disabled by runtime init */
if (!HAS_DISPLAY(i915)) {
i915->drm.driver_features &= ~(DRIVER_MODESET | DRIVER_ATOMIC);
i915->display.info.__device_info = &no_display;
if (!HAS_DISPLAY(display)) {
display->drm->driver_features &= ~(DRIVER_MODESET | DRIVER_ATOMIC);
display->info.__device_info = &no_display;
}
/* Disable nuclear pageflip by default on pre-g4x */
if (!i915->display.params.nuclear_pageflip &&
DISPLAY_VER(i915) < 5 && !IS_G4X(i915))
i915->drm.driver_features &= ~DRIVER_ATOMIC;
if (!display->params.nuclear_pageflip &&
DISPLAY_VER(display) < 5 && !display->platform.g4x)
display->drm->driver_features &= ~DRIVER_ATOMIC;
}
void intel_display_device_info_print(const struct intel_display_device_info *info,
@ -1872,10 +1916,8 @@ void intel_display_device_info_print(const struct intel_display_device_info *inf
* Disabling display means taking over the display hardware, putting it to
* sleep, and preventing connectors from being connected via any means.
*/
bool intel_display_device_enabled(struct drm_i915_private *i915)
bool intel_display_device_enabled(struct intel_display *display)
{
struct intel_display *display = &i915->display;
/* Only valid when HAS_DISPLAY() is true */
drm_WARN_ON(display->drm, !HAS_DISPLAY(display));

@ -12,8 +12,9 @@
#include "intel_display_conversion.h"
#include "intel_display_limits.h"
struct drm_i915_private;
struct drm_printer;
struct intel_display;
struct pci_dev;
/*
* Display platforms and subplatforms. Keep platforms in display version based
@ -21,6 +22,10 @@ struct drm_printer;
* platform.
*/
#define INTEL_DISPLAY_PLATFORMS(func) \
/* Platform group aliases */ \
func(g4x) /* g45 and gm45 */ \
func(mobile) /* mobile platforms */ \
func(dgfx) /* discrete graphics */ \
/* Display ver 2 */ \
func(i830) \
func(i845g) \
@ -38,7 +43,6 @@ struct drm_printer;
func(i965gm) \
func(g45) \
func(gm45) \
func(g4x) /* group alias for g45 and gm45 */ \
/* Display ver 5 */ \
func(ironlake) \
/* Display ver 6 */ \
@ -136,61 +140,64 @@ struct intel_display_platforms {
func(overlay_needs_physical); \
func(supports_tv);
#define HAS_4TILE(i915) (IS_DG2(i915) || DISPLAY_VER(i915) >= 14)
#define HAS_ASYNC_FLIPS(i915) (DISPLAY_VER(i915) >= 5)
#define HAS_BIGJOINER(i915) (DISPLAY_VER(i915) >= 11 && HAS_DSC(i915))
#define HAS_CDCLK_CRAWL(i915) (DISPLAY_INFO(i915)->has_cdclk_crawl)
#define HAS_CDCLK_SQUASH(i915) (DISPLAY_INFO(i915)->has_cdclk_squash)
#define HAS_CUR_FBC(i915) (!HAS_GMCH(i915) && IS_DISPLAY_VER(i915, 7, 13))
#define HAS_D12_PLANE_MINIMIZATION(i915) (IS_ROCKETLAKE(i915) || IS_ALDERLAKE_S(i915))
#define HAS_DBUF_OVERLAP_DETECTION(__i915) (DISPLAY_RUNTIME_INFO(__i915)->has_dbuf_overlap_detection)
#define HAS_DDI(i915) (DISPLAY_INFO(i915)->has_ddi)
#define HAS_DISPLAY(i915) (DISPLAY_RUNTIME_INFO(i915)->pipe_mask != 0)
#define HAS_DMC(i915) (DISPLAY_RUNTIME_INFO(i915)->has_dmc)
#define HAS_DOUBLE_BUFFERED_M_N(i915) (DISPLAY_VER(i915) >= 9 || IS_BROADWELL(i915))
#define HAS_DP_MST(i915) (DISPLAY_INFO(i915)->has_dp_mst)
#define HAS_DP20(i915) (IS_DG2(i915) || DISPLAY_VER(i915) >= 14)
#define HAS_DPT(i915) (DISPLAY_VER(i915) >= 13)
#define HAS_DSB(i915) (DISPLAY_INFO(i915)->has_dsb)
#define HAS_DSC(__i915) (DISPLAY_RUNTIME_INFO(__i915)->has_dsc)
#define HAS_DSC_MST(__i915) (DISPLAY_VER(__i915) >= 12 && HAS_DSC(__i915))
#define HAS_FBC(i915) (DISPLAY_RUNTIME_INFO(i915)->fbc_mask != 0)
#define HAS_FPGA_DBG_UNCLAIMED(i915) (DISPLAY_INFO(i915)->has_fpga_dbg)
#define HAS_FW_BLC(i915) (DISPLAY_VER(i915) >= 3)
#define HAS_GMBUS_IRQ(i915) (DISPLAY_VER(i915) >= 4)
#define HAS_GMBUS_BURST_READ(i915) (DISPLAY_VER(i915) >= 10 || IS_KABYLAKE(i915))
#define HAS_GMCH(i915) (DISPLAY_INFO(i915)->has_gmch)
#define HAS_HW_SAGV_WM(i915) (DISPLAY_VER(i915) >= 13 && !IS_DGFX(i915))
#define HAS_IPC(i915) (DISPLAY_INFO(i915)->has_ipc)
#define HAS_IPS(i915) (IS_HASWELL_ULT(i915) || IS_BROADWELL(i915))
#define HAS_LRR(i915) (DISPLAY_VER(i915) >= 12)
#define HAS_LSPCON(i915) (IS_DISPLAY_VER(i915, 9, 10))
#define HAS_MBUS_JOINING(i915) (IS_ALDERLAKE_P(i915) || DISPLAY_VER(i915) >= 14)
#define HAS_MSO(i915) (DISPLAY_VER(i915) >= 12)
#define HAS_OVERLAY(i915) (DISPLAY_INFO(i915)->has_overlay)
#define HAS_PSR(i915) (DISPLAY_INFO(i915)->has_psr)
#define HAS_PSR_HW_TRACKING(i915) (DISPLAY_INFO(i915)->has_psr_hw_tracking)
#define HAS_PSR2_SEL_FETCH(i915) (DISPLAY_VER(i915) >= 12)
#define HAS_SAGV(i915) (DISPLAY_VER(i915) >= 9 && !IS_BROXTON(i915) && !IS_GEMINILAKE(i915))
#define HAS_TRANSCODER(i915, trans) ((DISPLAY_RUNTIME_INFO(i915)->cpu_transcoder_mask & \
BIT(trans)) != 0)
#define HAS_UNCOMPRESSED_JOINER(i915) (DISPLAY_VER(i915) >= 13)
#define HAS_ULTRAJOINER(i915) ((DISPLAY_VER(i915) >= 20 || \
(IS_DGFX(i915) && DISPLAY_VER(i915) == 14)) && \
HAS_DSC(i915))
#define HAS_VRR(i915) (DISPLAY_VER(i915) >= 11)
#define HAS_AS_SDP(i915) (DISPLAY_VER(i915) >= 13)
#define HAS_CMRR(i915) (DISPLAY_VER(i915) >= 20)
#define INTEL_NUM_PIPES(i915) (hweight8(DISPLAY_RUNTIME_INFO(i915)->pipe_mask))
#define I915_HAS_HOTPLUG(i915) (DISPLAY_INFO(i915)->has_hotplug)
#define OVERLAY_NEEDS_PHYSICAL(i915) (DISPLAY_INFO(i915)->overlay_needs_physical)
#define SUPPORTS_TV(i915) (DISPLAY_INFO(i915)->supports_tv)
#define HAS_4TILE(__display) ((__display)->platform.dg2 || DISPLAY_VER(__display) >= 14)
#define HAS_ASYNC_FLIPS(__display) (DISPLAY_VER(__display) >= 5)
#define HAS_BIGJOINER(__display) (DISPLAY_VER(__display) >= 11 && HAS_DSC(__display))
#define HAS_CDCLK_CRAWL(__display) (DISPLAY_INFO(__display)->has_cdclk_crawl)
#define HAS_CDCLK_SQUASH(__display) (DISPLAY_INFO(__display)->has_cdclk_squash)
#define HAS_CUR_FBC(__display) (!HAS_GMCH(__display) && IS_DISPLAY_VER(__display, 7, 13))
#define HAS_D12_PLANE_MINIMIZATION(__display) ((__display)->platform.rocketlake || (__display)->platform.alderlake_s)
#define HAS_DBUF_OVERLAP_DETECTION(__display) (DISPLAY_RUNTIME_INFO(__display)->has_dbuf_overlap_detection)
#define HAS_DDI(__display) (DISPLAY_INFO(__display)->has_ddi)
#define HAS_DISPLAY(__display) (DISPLAY_RUNTIME_INFO(__display)->pipe_mask != 0)
#define HAS_DMC(__display) (DISPLAY_RUNTIME_INFO(__display)->has_dmc)
#define HAS_DMC_WAKELOCK(__display) (DISPLAY_VER(__display) >= 20)
#define HAS_DOUBLE_BUFFERED_M_N(__display) (DISPLAY_VER(__display) >= 9 || (__display)->platform.broadwell)
#define HAS_DOUBLE_WIDE(__display) (DISPLAY_VER(__display) < 4)
#define HAS_DP_MST(__display) (DISPLAY_INFO(__display)->has_dp_mst)
#define HAS_DP20(__display) ((__display)->platform.dg2 || DISPLAY_VER(__display) >= 14)
#define HAS_DPT(__display) (DISPLAY_VER(__display) >= 13)
#define HAS_DSB(__display) (DISPLAY_INFO(__display)->has_dsb)
#define HAS_DSC(__display) (DISPLAY_RUNTIME_INFO(__display)->has_dsc)
#define HAS_DSC_MST(__display) (DISPLAY_VER(__display) >= 12 && HAS_DSC(__display))
#define HAS_FBC(__display) (DISPLAY_RUNTIME_INFO(__display)->fbc_mask != 0)
#define HAS_FPGA_DBG_UNCLAIMED(__display) (DISPLAY_INFO(__display)->has_fpga_dbg)
#define HAS_FW_BLC(__display) (DISPLAY_VER(__display) >= 3)
#define HAS_GMBUS_IRQ(__display) (DISPLAY_VER(__display) >= 4)
#define HAS_GMBUS_BURST_READ(__display) (DISPLAY_VER(__display) >= 10 || (__display)->platform.kabylake)
#define HAS_GMCH(__display) (DISPLAY_INFO(__display)->has_gmch)
#define HAS_HW_SAGV_WM(__display) (DISPLAY_VER(__display) >= 13 && !(__display)->platform.dgfx)
#define HAS_IPC(__display) (DISPLAY_INFO(__display)->has_ipc)
#define HAS_IPS(__display) ((__display)->platform.haswell_ult || (__display)->platform.broadwell)
#define HAS_LRR(__display) (DISPLAY_VER(__display) >= 12)
#define HAS_LSPCON(__display) (IS_DISPLAY_VER(__display, 9, 10))
#define HAS_MBUS_JOINING(__display) ((__display)->platform.alderlake_p || DISPLAY_VER(__display) >= 14)
#define HAS_MSO(__display) (DISPLAY_VER(__display) >= 12)
#define HAS_OVERLAY(__display) (DISPLAY_INFO(__display)->has_overlay)
#define HAS_PSR(__display) (DISPLAY_INFO(__display)->has_psr)
#define HAS_PSR_HW_TRACKING(__display) (DISPLAY_INFO(__display)->has_psr_hw_tracking)
#define HAS_PSR2_SEL_FETCH(__display) (DISPLAY_VER(__display) >= 12)
#define HAS_SAGV(__display) (DISPLAY_VER(__display) >= 9 && \
!(__display)->platform.broxton && !(__display)->platform.geminilake)
#define HAS_TRANSCODER(__display, trans) ((DISPLAY_RUNTIME_INFO(__display)->cpu_transcoder_mask & \
BIT(trans)) != 0)
#define HAS_UNCOMPRESSED_JOINER(__display) (DISPLAY_VER(__display) >= 13)
#define HAS_ULTRAJOINER(__display) ((DISPLAY_VER(__display) >= 20 || \
((__display)->platform.dgfx && DISPLAY_VER(__display) == 14)) && \
HAS_DSC(__display))
#define HAS_VRR(__display) (DISPLAY_VER(__display) >= 11)
#define HAS_AS_SDP(__display) (DISPLAY_VER(__display) >= 13)
#define HAS_CMRR(__display) (DISPLAY_VER(__display) >= 20)
#define INTEL_NUM_PIPES(__display) (hweight8(DISPLAY_RUNTIME_INFO(__display)->pipe_mask))
#define I915_HAS_HOTPLUG(__display) (DISPLAY_INFO(__display)->has_hotplug)
#define OVERLAY_NEEDS_PHYSICAL(__display) (DISPLAY_INFO(__display)->overlay_needs_physical)
#define SUPPORTS_TV(__display) (DISPLAY_INFO(__display)->supports_tv)
/* Check that device has a display IP version within the specific range. */
#define IS_DISPLAY_VERx100(__i915, from, until) ( \
#define IS_DISPLAY_VERx100(__display, from, until) ( \
BUILD_BUG_ON_ZERO((from) < 200) + \
(DISPLAY_VERx100(__i915) >= (from) && \
DISPLAY_VERx100(__i915) <= (until)))
(DISPLAY_VERx100(__display) >= (from) && \
DISPLAY_VERx100(__display) <= (until)))
/*
* Check if a device has a specific IP version as well as a stepping within the
@ -201,30 +208,30 @@ struct intel_display_platforms {
* hardware fix is present and the software workaround is no longer necessary.
* E.g.,
*
* IS_DISPLAY_VERx100_STEP(i915, 1400, STEP_A0, STEP_B2)
* IS_DISPLAY_VERx100_STEP(i915, 1400, STEP_C0, STEP_FOREVER)
* IS_DISPLAY_VERx100_STEP(display, 1400, STEP_A0, STEP_B2)
* IS_DISPLAY_VERx100_STEP(display, 1400, STEP_C0, STEP_FOREVER)
*
* "STEP_FOREVER" can be passed as "until" for workarounds that have no upper
* stepping bound for the specified IP version.
*/
#define IS_DISPLAY_VERx100_STEP(__i915, ipver, from, until) \
(IS_DISPLAY_VERx100((__i915), (ipver), (ipver)) && \
IS_DISPLAY_STEP((__i915), (from), (until)))
#define IS_DISPLAY_VERx100_STEP(__display, ipver, from, until) \
(IS_DISPLAY_VERx100((__display), (ipver), (ipver)) && \
IS_DISPLAY_STEP((__display), (from), (until)))
#define DISPLAY_INFO(i915) (__to_intel_display(i915)->info.__device_info)
#define DISPLAY_RUNTIME_INFO(i915) (&__to_intel_display(i915)->info.__runtime_info)
#define DISPLAY_INFO(__display) (__to_intel_display(__display)->info.__device_info)
#define DISPLAY_RUNTIME_INFO(__display) (&__to_intel_display(__display)->info.__runtime_info)
#define DISPLAY_VER(i915) (DISPLAY_RUNTIME_INFO(i915)->ip.ver)
#define DISPLAY_VERx100(i915) (DISPLAY_RUNTIME_INFO(i915)->ip.ver * 100 + \
DISPLAY_RUNTIME_INFO(i915)->ip.rel)
#define IS_DISPLAY_VER(i915, from, until) \
(DISPLAY_VER(i915) >= (from) && DISPLAY_VER(i915) <= (until))
#define DISPLAY_VER(__display) (DISPLAY_RUNTIME_INFO(__display)->ip.ver)
#define DISPLAY_VERx100(__display) (DISPLAY_RUNTIME_INFO(__display)->ip.ver * 100 + \
DISPLAY_RUNTIME_INFO(__display)->ip.rel)
#define IS_DISPLAY_VER(__display, from, until) \
(DISPLAY_VER(__display) >= (from) && DISPLAY_VER(__display) <= (until))
#define INTEL_DISPLAY_STEP(__i915) (DISPLAY_RUNTIME_INFO(__i915)->step)
#define INTEL_DISPLAY_STEP(__display) (DISPLAY_RUNTIME_INFO(__display)->step)
#define IS_DISPLAY_STEP(__i915, since, until) \
(drm_WARN_ON(__to_intel_display(__i915)->drm, INTEL_DISPLAY_STEP(__i915) == STEP_NONE), \
INTEL_DISPLAY_STEP(__i915) >= (since) && INTEL_DISPLAY_STEP(__i915) < (until))
#define IS_DISPLAY_STEP(__display, since, until) \
(drm_WARN_ON(__to_intel_display(__display)->drm, INTEL_DISPLAY_STEP(__display) == STEP_NONE), \
INTEL_DISPLAY_STEP(__display) >= (since) && INTEL_DISPLAY_STEP(__display) < (until))
struct intel_display_runtime_info {
struct intel_display_ip_ver {
@ -283,10 +290,10 @@ struct intel_display_device_info {
} color;
};
bool intel_display_device_enabled(struct drm_i915_private *i915);
void intel_display_device_probe(struct drm_i915_private *i915);
void intel_display_device_remove(struct drm_i915_private *i915);
void intel_display_device_info_runtime_init(struct drm_i915_private *i915);
bool intel_display_device_enabled(struct intel_display *display);
struct intel_display *intel_display_device_probe(struct pci_dev *pdev);
void intel_display_device_remove(struct intel_display *display);
void intel_display_device_info_runtime_init(struct intel_display *display);
void intel_display_device_info_print(const struct intel_display_device_info *info,
const struct intel_display_runtime_info *runtime,

@ -80,12 +80,12 @@ bool intel_display_driver_probe_defer(struct pci_dev *pdev)
return false;
}
void intel_display_driver_init_hw(struct drm_i915_private *i915)
void intel_display_driver_init_hw(struct intel_display *display)
{
struct intel_display *display = &i915->display;
struct drm_i915_private *i915 = to_i915(display->drm);
struct intel_cdclk_state *cdclk_state;
if (!HAS_DISPLAY(i915))
if (!HAS_DISPLAY(display))
return;
cdclk_state = to_intel_cdclk_state(display->cdclk.obj.state);
@ -112,12 +112,12 @@ static const struct drm_mode_config_helper_funcs intel_mode_config_funcs = {
.atomic_commit_setup = drm_dp_mst_atomic_setup_commit,
};
static void intel_mode_config_init(struct drm_i915_private *i915)
static void intel_mode_config_init(struct intel_display *display)
{
struct drm_mode_config *mode_config = &i915->drm.mode_config;
struct drm_mode_config *mode_config = &display->drm->mode_config;
drm_mode_config_init(&i915->drm);
INIT_LIST_HEAD(&i915->display.global.obj_list);
drm_mode_config_init(display->drm);
INIT_LIST_HEAD(&display->global.obj_list);
mode_config->min_width = 0;
mode_config->min_height = 0;
@ -128,19 +128,19 @@ static void intel_mode_config_init(struct drm_i915_private *i915)
mode_config->funcs = &intel_mode_funcs;
mode_config->helper_private = &intel_mode_config_funcs;
mode_config->async_page_flip = HAS_ASYNC_FLIPS(i915);
mode_config->async_page_flip = HAS_ASYNC_FLIPS(display);
/*
* Maximum framebuffer dimensions, chosen to match
* the maximum render engine surface size on gen4+.
*/
if (DISPLAY_VER(i915) >= 7) {
if (DISPLAY_VER(display) >= 7) {
mode_config->max_width = 16384;
mode_config->max_height = 16384;
} else if (DISPLAY_VER(i915) >= 4) {
} else if (DISPLAY_VER(display) >= 4) {
mode_config->max_width = 8192;
mode_config->max_height = 8192;
} else if (DISPLAY_VER(i915) == 3) {
} else if (DISPLAY_VER(display) == 3) {
mode_config->max_width = 4096;
mode_config->max_height = 4096;
} else {
@ -148,11 +148,11 @@ static void intel_mode_config_init(struct drm_i915_private *i915)
mode_config->max_height = 2048;
}
if (IS_I845G(i915) || IS_I865G(i915)) {
mode_config->cursor_width = IS_I845G(i915) ? 64 : 512;
if (display->platform.i845g || display->platform.i865g) {
mode_config->cursor_width = display->platform.i845g ? 64 : 512;
mode_config->cursor_height = 1023;
} else if (IS_I830(i915) || IS_I85X(i915) ||
IS_I915G(i915) || IS_I915GM(i915)) {
} else if (display->platform.i830 || display->platform.i85x ||
display->platform.i915g || display->platform.i915gm) {
mode_config->cursor_width = 64;
mode_config->cursor_height = 64;
} else {
@ -161,18 +161,19 @@ static void intel_mode_config_init(struct drm_i915_private *i915)
}
}
static void intel_mode_config_cleanup(struct drm_i915_private *i915)
static void intel_mode_config_cleanup(struct intel_display *display)
{
struct drm_i915_private *i915 = to_i915(display->drm);
intel_atomic_global_obj_cleanup(i915);
drm_mode_config_cleanup(&i915->drm);
drm_mode_config_cleanup(display->drm);
}
static void intel_plane_possible_crtcs_init(struct drm_i915_private *dev_priv)
static void intel_plane_possible_crtcs_init(struct intel_display *display)
{
struct intel_display *display = &dev_priv->display;
struct intel_plane *plane;
for_each_intel_plane(&dev_priv->drm, plane) {
for_each_intel_plane(display->drm, plane) {
struct intel_crtc *crtc = intel_crtc_for_pipe(display,
plane->pipe);
@ -180,41 +181,43 @@ static void intel_plane_possible_crtcs_init(struct drm_i915_private *dev_priv)
}
}
void intel_display_driver_early_probe(struct drm_i915_private *i915)
void intel_display_driver_early_probe(struct intel_display *display)
{
if (!HAS_DISPLAY(i915))
struct drm_i915_private *i915 = to_i915(display->drm);
if (!HAS_DISPLAY(display))
return;
spin_lock_init(&i915->display.fb_tracking.lock);
mutex_init(&i915->display.backlight.lock);
mutex_init(&i915->display.audio.mutex);
mutex_init(&i915->display.wm.wm_mutex);
mutex_init(&i915->display.pps.mutex);
mutex_init(&i915->display.hdcp.hdcp_mutex);
spin_lock_init(&display->fb_tracking.lock);
mutex_init(&display->backlight.lock);
mutex_init(&display->audio.mutex);
mutex_init(&display->wm.wm_mutex);
mutex_init(&display->pps.mutex);
mutex_init(&display->hdcp.hdcp_mutex);
intel_display_irq_init(i915);
intel_dkl_phy_init(i915);
intel_color_init_hooks(&i915->display);
intel_init_cdclk_hooks(&i915->display);
intel_color_init_hooks(display);
intel_init_cdclk_hooks(display);
intel_audio_hooks_init(i915);
intel_dpll_init_clock_hook(i915);
intel_init_display_hooks(i915);
intel_fdi_init_hook(i915);
intel_dmc_wl_init(&i915->display);
intel_dmc_wl_init(display);
}
/* part #1: call before irq install */
int intel_display_driver_probe_noirq(struct drm_i915_private *i915)
int intel_display_driver_probe_noirq(struct intel_display *display)
{
struct intel_display *display = &i915->display;
struct drm_i915_private *i915 = to_i915(display->drm);
int ret;
if (i915_inject_probe_failure(i915))
return -ENODEV;
if (HAS_DISPLAY(i915)) {
ret = drm_vblank_init(&i915->drm,
INTEL_NUM_PIPES(i915));
if (HAS_DISPLAY(display)) {
ret = drm_vblank_init(display->drm,
INTEL_NUM_PIPES(display));
if (ret)
return ret;
}
@ -226,24 +229,25 @@ int intel_display_driver_probe_noirq(struct drm_i915_private *i915)
goto cleanup_bios;
/* FIXME: completely on the wrong abstraction layer */
ret = intel_power_domains_init(i915);
ret = intel_power_domains_init(display);
if (ret < 0)
goto cleanup_vga;
intel_pmdemand_init_early(i915);
intel_power_domains_init_hw(i915, false);
intel_power_domains_init_hw(display, false);
if (!HAS_DISPLAY(i915))
if (!HAS_DISPLAY(display))
return 0;
intel_dmc_init(display);
i915->display.wq.modeset = alloc_ordered_workqueue("i915_modeset", 0);
i915->display.wq.flip = alloc_workqueue("i915_flip", WQ_HIGHPRI |
display->wq.modeset = alloc_ordered_workqueue("i915_modeset", 0);
display->wq.flip = alloc_workqueue("i915_flip", WQ_HIGHPRI |
WQ_UNBOUND, WQ_UNBOUND_MAX_ACTIVE);
display->wq.cleanup = alloc_workqueue("i915_cleanup", WQ_HIGHPRI, 0);
intel_mode_config_init(i915);
intel_mode_config_init(display);
ret = intel_cdclk_init(display);
if (ret)
@ -273,7 +277,7 @@ int intel_display_driver_probe_noirq(struct drm_i915_private *i915)
cleanup_vga_client_pw_domain_dmc:
intel_dmc_fini(display);
intel_power_domains_driver_remove(i915);
intel_power_domains_driver_remove(display);
cleanup_vga:
intel_vga_unregister(display);
cleanup_bios:
@ -282,7 +286,7 @@ int intel_display_driver_probe_noirq(struct drm_i915_private *i915)
return ret;
}
static void set_display_access(struct drm_i915_private *i915,
static void set_display_access(struct intel_display *display,
bool any_task_allowed,
struct task_struct *allowed_task)
{
@ -290,20 +294,20 @@ static void set_display_access(struct drm_i915_private *i915,
int err;
intel_modeset_lock_ctx_retry(&ctx, NULL, 0, err) {
err = drm_modeset_lock_all_ctx(&i915->drm, &ctx);
err = drm_modeset_lock_all_ctx(display->drm, &ctx);
if (err)
continue;
i915->display.access.any_task_allowed = any_task_allowed;
i915->display.access.allowed_task = allowed_task;
display->access.any_task_allowed = any_task_allowed;
display->access.allowed_task = allowed_task;
}
drm_WARN_ON(&i915->drm, err);
drm_WARN_ON(display->drm, err);
}
/**
* intel_display_driver_enable_user_access - Enable display HW access for all threads
* @i915: i915 device instance
* @display: display device instance
*
* Enable the display HW access for all threads. Examples for such accesses
* are modeset commits and connector probing.
@ -311,16 +315,18 @@ static void set_display_access(struct drm_i915_private *i915,
* This function should be called during driver loading and system resume once
* all the HW initialization steps are done.
*/
void intel_display_driver_enable_user_access(struct drm_i915_private *i915)
void intel_display_driver_enable_user_access(struct intel_display *display)
{
set_display_access(i915, true, NULL);
struct drm_i915_private *i915 = to_i915(display->drm);
set_display_access(display, true, NULL);
intel_hpd_enable_detection_work(i915);
}
/**
* intel_display_driver_disable_user_access - Disable display HW access for user threads
* @i915: i915 device instance
* @display: display device instance
*
* Disable the display HW access for user threads. Examples for such accesses
* are modeset commits and connector probing. For the current thread the
@ -335,16 +341,18 @@ void intel_display_driver_enable_user_access(struct drm_i915_private *i915)
* This function should be called during driver loading/unloading and system
* suspend/shutdown before starting the HW init/deinit programming.
*/
void intel_display_driver_disable_user_access(struct drm_i915_private *i915)
void intel_display_driver_disable_user_access(struct intel_display *display)
{
struct drm_i915_private *i915 = to_i915(display->drm);
intel_hpd_disable_detection_work(i915);
set_display_access(i915, false, current);
set_display_access(display, false, current);
}
/**
* intel_display_driver_suspend_access - Suspend display HW access for all threads
* @i915: i915 device instance
* @display: display device instance
*
* Disable the display HW access for all threads. Examples for such accesses
* are modeset commits and connector probing. This call should be either
@ -354,14 +362,14 @@ void intel_display_driver_disable_user_access(struct drm_i915_private *i915)
* This function should be called during driver unloading and system
* suspend/shutdown after completing the HW deinit programming.
*/
void intel_display_driver_suspend_access(struct drm_i915_private *i915)
void intel_display_driver_suspend_access(struct intel_display *display)
{
set_display_access(i915, false, NULL);
set_display_access(display, false, NULL);
}
/**
* intel_display_driver_resume_access - Resume display HW access for the resume thread
* @i915: i915 device instance
* @display: display device instance
*
* Enable the display HW access for the current resume thread, keeping the
* access disabled for all other (user) threads. Examples for such accesses
@ -373,14 +381,14 @@ void intel_display_driver_suspend_access(struct drm_i915_private *i915)
* This function should be called during system resume before starting the HW
* init steps.
*/
void intel_display_driver_resume_access(struct drm_i915_private *i915)
void intel_display_driver_resume_access(struct intel_display *display)
{
set_display_access(i915, false, current);
set_display_access(display, false, current);
}
/**
* intel_display_driver_check_access - Check if the current thread has disaplay HW access
* @i915: i915 device instance
* @display: display device instance
*
* Check whether the current thread has display HW access, print a debug
* message if it doesn't. Such accesses are modeset commits and connector
@ -389,26 +397,26 @@ void intel_display_driver_resume_access(struct drm_i915_private *i915)
* Returns %true if the current thread has display HW access, %false
* otherwise.
*/
bool intel_display_driver_check_access(struct drm_i915_private *i915)
bool intel_display_driver_check_access(struct intel_display *display)
{
char comm[TASK_COMM_LEN];
char current_task[TASK_COMM_LEN + 16];
char allowed_task[TASK_COMM_LEN + 16] = "none";
if (i915->display.access.any_task_allowed ||
i915->display.access.allowed_task == current)
if (display->access.any_task_allowed ||
display->access.allowed_task == current)
return true;
snprintf(current_task, sizeof(current_task), "%s[%d]",
get_task_comm(comm, current),
task_pid_vnr(current));
if (i915->display.access.allowed_task)
if (display->access.allowed_task)
snprintf(allowed_task, sizeof(allowed_task), "%s[%d]",
get_task_comm(comm, i915->display.access.allowed_task),
task_pid_vnr(i915->display.access.allowed_task));
get_task_comm(comm, display->access.allowed_task),
task_pid_vnr(display->access.allowed_task));
drm_dbg_kms(&i915->drm,
drm_dbg_kms(display->drm,
"Reject display access from task %s (allowed to %s)\n",
current_task, allowed_task);
@ -416,14 +424,13 @@ bool intel_display_driver_check_access(struct drm_i915_private *i915)
}
/* part #2: call after irq install, but before gem init */
int intel_display_driver_probe_nogem(struct drm_i915_private *i915)
int intel_display_driver_probe_nogem(struct intel_display *display)
{
struct intel_display *display = &i915->display;
struct drm_device *dev = display->drm;
struct drm_i915_private *i915 = to_i915(display->drm);
enum pipe pipe;
int ret;
if (!HAS_DISPLAY(i915))
if (!HAS_DISPLAY(display))
return 0;
intel_wm_init(i915);
@ -434,22 +441,22 @@ int intel_display_driver_probe_nogem(struct drm_i915_private *i915)
intel_gmbus_setup(display);
drm_dbg_kms(&i915->drm, "%d display pipe%s available.\n",
INTEL_NUM_PIPES(i915),
INTEL_NUM_PIPES(i915) > 1 ? "s" : "");
drm_dbg_kms(display->drm, "%d display pipe%s available.\n",
INTEL_NUM_PIPES(display),
INTEL_NUM_PIPES(display) > 1 ? "s" : "");
for_each_pipe(i915, pipe) {
for_each_pipe(display, pipe) {
ret = intel_crtc_init(i915, pipe);
if (ret)
goto err_mode_config;
}
intel_plane_possible_crtcs_init(i915);
intel_plane_possible_crtcs_init(display);
intel_shared_dpll_init(i915);
intel_fdi_pll_freq_update(i915);
intel_update_czclk(i915);
intel_display_driver_init_hw(i915);
intel_display_driver_init_hw(display);
intel_dpll_update_ref_clks(i915);
if (display->cdclk.max_cdclk_freq == 0)
@ -465,21 +472,21 @@ int intel_display_driver_probe_nogem(struct drm_i915_private *i915)
if (ret)
goto err_hdcp;
intel_display_driver_disable_user_access(i915);
intel_display_driver_disable_user_access(display);
drm_modeset_lock_all(dev);
intel_modeset_setup_hw_state(i915, dev->mode_config.acquire_ctx);
drm_modeset_lock_all(display->drm);
intel_modeset_setup_hw_state(i915, display->drm->mode_config.acquire_ctx);
intel_acpi_assign_connector_fwnodes(display);
drm_modeset_unlock_all(dev);
drm_modeset_unlock_all(display->drm);
intel_initial_plane_config(i915);
intel_initial_plane_config(display);
/*
* Make sure hardware watermarks really match the state we read out.
* Note that we need to do this after reconstructing the BIOS fb's
* since the watermark calculation done here will use pstate->fb.
*/
if (!HAS_GMCH(i915))
if (!HAS_GMCH(display))
ilk_wm_sanitize(i915);
return 0;
@ -487,18 +494,18 @@ int intel_display_driver_probe_nogem(struct drm_i915_private *i915)
err_hdcp:
intel_hdcp_component_fini(display);
err_mode_config:
intel_mode_config_cleanup(i915);
intel_mode_config_cleanup(display);
return ret;
}
/* part #3: call after gem init */
int intel_display_driver_probe(struct drm_i915_private *i915)
int intel_display_driver_probe(struct intel_display *display)
{
struct intel_display *display = &i915->display;
struct drm_i915_private *i915 = to_i915(display->drm);
int ret;
if (!HAS_DISPLAY(i915))
if (!HAS_DISPLAY(display))
return 0;
/*
@ -514,11 +521,11 @@ int intel_display_driver_probe(struct drm_i915_private *i915)
* are already calculated and there is no assert_plane warnings
* during bootup.
*/
ret = intel_initial_commit(&i915->drm);
ret = intel_initial_commit(display->drm);
if (ret)
drm_dbg_kms(&i915->drm, "Initial modeset failed, %d\n", ret);
drm_dbg_kms(display->drm, "Initial modeset failed, %d\n", ret);
intel_overlay_setup(i915);
intel_overlay_setup(display);
/* Only enable hotplug handling once the fbdev is fully set up. */
intel_hpd_init(i915);
@ -528,13 +535,13 @@ int intel_display_driver_probe(struct drm_i915_private *i915)
return 0;
}
void intel_display_driver_register(struct drm_i915_private *i915)
void intel_display_driver_register(struct intel_display *display)
{
struct intel_display *display = &i915->display;
struct drm_printer p = drm_dbg_printer(&i915->drm, DRM_UT_KMS,
struct drm_i915_private *i915 = to_i915(display->drm);
struct drm_printer p = drm_dbg_printer(display->drm, DRM_UT_KMS,
"i915 display info:");
if (!HAS_DISPLAY(i915))
if (!HAS_DISPLAY(display))
return;
/* Must be done after probing outputs */
@ -543,7 +550,7 @@ void intel_display_driver_register(struct drm_i915_private *i915)
intel_audio_init(i915);
intel_display_driver_enable_user_access(i915);
intel_display_driver_enable_user_access(display);
intel_audio_register(i915);
@ -554,23 +561,26 @@ void intel_display_driver_register(struct drm_i915_private *i915)
* fbdev configuration, for which we use the
* fbdev->async_cookie.
*/
drm_kms_helper_poll_init(&i915->drm);
drm_kms_helper_poll_init(display->drm);
intel_hpd_poll_disable(i915);
intel_fbdev_setup(i915);
intel_display_device_info_print(DISPLAY_INFO(i915),
DISPLAY_RUNTIME_INFO(i915), &p);
intel_display_device_info_print(DISPLAY_INFO(display),
DISPLAY_RUNTIME_INFO(display), &p);
}
/* part #1: call before irq uninstall */
void intel_display_driver_remove(struct drm_i915_private *i915)
void intel_display_driver_remove(struct intel_display *display)
{
if (!HAS_DISPLAY(i915))
struct drm_i915_private *i915 = to_i915(display->drm);
if (!HAS_DISPLAY(display))
return;
flush_workqueue(i915->display.wq.flip);
flush_workqueue(i915->display.wq.modeset);
flush_workqueue(display->wq.flip);
flush_workqueue(display->wq.modeset);
flush_workqueue(display->wq.cleanup);
/*
* MST topology needs to be suspended so we don't have any calls to
@ -581,14 +591,14 @@ void intel_display_driver_remove(struct drm_i915_private *i915)
}
/* part #2: call after irq uninstall */
void intel_display_driver_remove_noirq(struct drm_i915_private *i915)
void intel_display_driver_remove_noirq(struct intel_display *display)
{
struct intel_display *display = &i915->display;
struct drm_i915_private *i915 = to_i915(display->drm);
if (!HAS_DISPLAY(i915))
if (!HAS_DISPLAY(display))
return;
intel_display_driver_suspend_access(i915);
intel_display_driver_suspend_access(display);
/*
* Due to the hpd irq storm handling the hotplug work can re-arm the
@ -603,55 +613,54 @@ void intel_display_driver_remove_noirq(struct drm_i915_private *i915)
intel_hdcp_component_fini(display);
intel_mode_config_cleanup(i915);
intel_mode_config_cleanup(display);
intel_dp_tunnel_mgr_cleanup(display);
intel_overlay_cleanup(i915);
intel_overlay_cleanup(display);
intel_gmbus_teardown(display);
destroy_workqueue(i915->display.wq.flip);
destroy_workqueue(i915->display.wq.modeset);
destroy_workqueue(display->wq.flip);
destroy_workqueue(display->wq.modeset);
destroy_workqueue(display->wq.cleanup);
intel_fbc_cleanup(&i915->display);
intel_fbc_cleanup(display);
}
/* part #3: call after gem init */
void intel_display_driver_remove_nogem(struct drm_i915_private *i915)
void intel_display_driver_remove_nogem(struct intel_display *display)
{
struct intel_display *display = &i915->display;
intel_dmc_fini(display);
intel_power_domains_driver_remove(i915);
intel_power_domains_driver_remove(display);
intel_vga_unregister(display);
intel_bios_driver_remove(display);
}
void intel_display_driver_unregister(struct drm_i915_private *i915)
void intel_display_driver_unregister(struct intel_display *display)
{
struct intel_display *display = &i915->display;
struct drm_i915_private *i915 = to_i915(display->drm);
if (!HAS_DISPLAY(i915))
if (!HAS_DISPLAY(display))
return;
drm_client_dev_unregister(&i915->drm);
drm_client_dev_unregister(display->drm);
/*
* After flushing the fbdev (incl. a late async config which
* will have delayed queuing of a hotplug event), then flush
* the hotplug events.
*/
drm_kms_helper_poll_fini(&i915->drm);
drm_kms_helper_poll_fini(display->drm);
intel_display_driver_disable_user_access(i915);
intel_display_driver_disable_user_access(display);
intel_audio_deinit(i915);
drm_atomic_helper_shutdown(&i915->drm);
drm_atomic_helper_shutdown(display->drm);
acpi_video_unregister();
intel_opregion_unregister(display);
@ -661,30 +670,37 @@ void intel_display_driver_unregister(struct drm_i915_private *i915)
* turn all crtc's off, but do not adjust state
* This has to be paired with a call to intel_modeset_setup_hw_state.
*/
int intel_display_driver_suspend(struct drm_i915_private *i915)
int intel_display_driver_suspend(struct intel_display *display)
{
struct drm_i915_private *i915 = to_i915(display->drm);
struct drm_atomic_state *state;
int ret;
if (!HAS_DISPLAY(i915))
if (!HAS_DISPLAY(display))
return 0;
state = drm_atomic_helper_suspend(&i915->drm);
state = drm_atomic_helper_suspend(display->drm);
ret = PTR_ERR_OR_ZERO(state);
if (ret)
drm_err(&i915->drm, "Suspending crtc's failed with %i\n",
drm_err(display->drm, "Suspending crtc's failed with %i\n",
ret);
else
i915->display.restore.modeset_state = state;
display->restore.modeset_state = state;
/* ensure all DPT VMAs have been unpinned for intel_dpt_suspend() */
flush_workqueue(display->wq.cleanup);
intel_dp_mst_suspend(i915);
return ret;
}
int
__intel_display_driver_resume(struct drm_i915_private *i915,
__intel_display_driver_resume(struct intel_display *display,
struct drm_atomic_state *state,
struct drm_modeset_acquire_ctx *ctx)
{
struct intel_display *display = &i915->display;
struct drm_i915_private *i915 = to_i915(display->drm);
struct drm_crtc_state *crtc_state;
struct drm_crtc *crtc;
int ret, i;
@ -710,33 +726,37 @@ __intel_display_driver_resume(struct drm_i915_private *i915,
}
/* ignore any reset values/BIOS leftovers in the WM registers */
if (!HAS_GMCH(i915))
if (!HAS_GMCH(display))
to_intel_atomic_state(state)->skip_intermediate_wm = true;
ret = drm_atomic_helper_commit_duplicated_state(state, ctx);
drm_WARN_ON(&i915->drm, ret == -EDEADLK);
drm_WARN_ON(display->drm, ret == -EDEADLK);
return ret;
}
void intel_display_driver_resume(struct drm_i915_private *i915)
void intel_display_driver_resume(struct intel_display *display)
{
struct drm_atomic_state *state = i915->display.restore.modeset_state;
struct drm_i915_private *i915 = to_i915(display->drm);
struct drm_atomic_state *state = display->restore.modeset_state;
struct drm_modeset_acquire_ctx ctx;
int ret;
if (!HAS_DISPLAY(i915))
if (!HAS_DISPLAY(display))
return;
i915->display.restore.modeset_state = NULL;
/* MST sideband requires HPD interrupts enabled */
intel_dp_mst_resume(i915);
display->restore.modeset_state = NULL;
if (state)
state->acquire_ctx = &ctx;
drm_modeset_acquire_init(&ctx, 0);
while (1) {
ret = drm_modeset_lock_all_ctx(&i915->drm, &ctx);
ret = drm_modeset_lock_all_ctx(display->drm, &ctx);
if (ret != -EDEADLK)
break;
@ -744,14 +764,14 @@ void intel_display_driver_resume(struct drm_i915_private *i915)
}
if (!ret)
ret = __intel_display_driver_resume(i915, state, &ctx);
ret = __intel_display_driver_resume(display, state, &ctx);
skl_watermark_ipc_update(i915);
drm_modeset_drop_locks(&ctx);
drm_modeset_acquire_fini(&ctx);
if (ret)
drm_err(&i915->drm,
drm_err(display->drm,
"Restoring old state failed with %i\n", ret);
if (state)
drm_atomic_state_put(state);

@ -9,34 +9,34 @@
#include <linux/types.h>
struct drm_atomic_state;
struct drm_i915_private;
struct drm_modeset_acquire_ctx;
struct intel_display;
struct pci_dev;
bool intel_display_driver_probe_defer(struct pci_dev *pdev);
void intel_display_driver_init_hw(struct drm_i915_private *i915);
void intel_display_driver_early_probe(struct drm_i915_private *i915);
int intel_display_driver_probe_noirq(struct drm_i915_private *i915);
int intel_display_driver_probe_nogem(struct drm_i915_private *i915);
int intel_display_driver_probe(struct drm_i915_private *i915);
void intel_display_driver_register(struct drm_i915_private *i915);
void intel_display_driver_remove(struct drm_i915_private *i915);
void intel_display_driver_remove_noirq(struct drm_i915_private *i915);
void intel_display_driver_remove_nogem(struct drm_i915_private *i915);
void intel_display_driver_unregister(struct drm_i915_private *i915);
int intel_display_driver_suspend(struct drm_i915_private *i915);
void intel_display_driver_resume(struct drm_i915_private *i915);
void intel_display_driver_init_hw(struct intel_display *display);
void intel_display_driver_early_probe(struct intel_display *display);
int intel_display_driver_probe_noirq(struct intel_display *display);
int intel_display_driver_probe_nogem(struct intel_display *display);
int intel_display_driver_probe(struct intel_display *display);
void intel_display_driver_register(struct intel_display *display);
void intel_display_driver_remove(struct intel_display *display);
void intel_display_driver_remove_noirq(struct intel_display *display);
void intel_display_driver_remove_nogem(struct intel_display *display);
void intel_display_driver_unregister(struct intel_display *display);
int intel_display_driver_suspend(struct intel_display *display);
void intel_display_driver_resume(struct intel_display *display);
/* interface for intel_display_reset.c */
int __intel_display_driver_resume(struct drm_i915_private *i915,
int __intel_display_driver_resume(struct intel_display *display,
struct drm_atomic_state *state,
struct drm_modeset_acquire_ctx *ctx);
void intel_display_driver_enable_user_access(struct drm_i915_private *i915);
void intel_display_driver_disable_user_access(struct drm_i915_private *i915);
void intel_display_driver_suspend_access(struct drm_i915_private *i915);
void intel_display_driver_resume_access(struct drm_i915_private *i915);
bool intel_display_driver_check_access(struct drm_i915_private *i915);
void intel_display_driver_enable_user_access(struct intel_display *display);
void intel_display_driver_disable_user_access(struct intel_display *display);
void intel_display_driver_suspend_access(struct intel_display *display);
void intel_display_driver_resume_access(struct intel_display *display);
bool intel_display_driver_check_access(struct intel_display *display);
#endif /* __INTEL_DISPLAY_DRIVER_H__ */

@ -434,7 +434,8 @@ void i9xx_pipestat_irq_ack(struct drm_i915_private *dev_priv,
spin_lock(&dev_priv->irq_lock);
if (!dev_priv->display.irq.display_irqs_enabled) {
if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
!dev_priv->display.irq.vlv_display_irqs_enabled) {
spin_unlock(&dev_priv->irq_lock);
return;
}
@ -843,7 +844,9 @@ static u32 gen8_de_port_aux_mask(struct drm_i915_private *dev_priv)
static u32 gen8_de_pipe_fault_mask(struct drm_i915_private *dev_priv)
{
if (DISPLAY_VER(dev_priv) >= 14)
struct intel_display *display = &dev_priv->display;
if (DISPLAY_VER(display) >= 14)
return MTL_PIPEDMC_ATS_FAULT |
MTL_PLANE_ATS_FAULT |
GEN12_PIPEDMC_FAULT |
@ -853,7 +856,7 @@ static u32 gen8_de_pipe_fault_mask(struct drm_i915_private *dev_priv)
GEN9_PIPE_PLANE3_FAULT |
GEN9_PIPE_PLANE2_FAULT |
GEN9_PIPE_PLANE1_FAULT;
if (DISPLAY_VER(dev_priv) >= 13 || HAS_D12_PLANE_MINIMIZATION(dev_priv))
if (DISPLAY_VER(display) >= 13 || HAS_D12_PLANE_MINIMIZATION(display))
return GEN12_PIPEDMC_FAULT |
GEN9_PIPE_CURSOR_FAULT |
GEN11_PIPE_PLANE5_FAULT |
@ -861,7 +864,7 @@ static u32 gen8_de_pipe_fault_mask(struct drm_i915_private *dev_priv)
GEN9_PIPE_PLANE3_FAULT |
GEN9_PIPE_PLANE2_FAULT |
GEN9_PIPE_PLANE1_FAULT;
else if (DISPLAY_VER(dev_priv) == 12)
else if (DISPLAY_VER(display) == 12)
return GEN12_PIPEDMC_FAULT |
GEN9_PIPE_CURSOR_FAULT |
GEN11_PIPE_PLANE7_FAULT |
@ -871,7 +874,7 @@ static u32 gen8_de_pipe_fault_mask(struct drm_i915_private *dev_priv)
GEN9_PIPE_PLANE3_FAULT |
GEN9_PIPE_PLANE2_FAULT |
GEN9_PIPE_PLANE1_FAULT;
else if (DISPLAY_VER(dev_priv) == 11)
else if (DISPLAY_VER(display) == 11)
return GEN9_PIPE_CURSOR_FAULT |
GEN11_PIPE_PLANE7_FAULT |
GEN11_PIPE_PLANE6_FAULT |
@ -880,7 +883,7 @@ static u32 gen8_de_pipe_fault_mask(struct drm_i915_private *dev_priv)
GEN9_PIPE_PLANE3_FAULT |
GEN9_PIPE_PLANE2_FAULT |
GEN9_PIPE_PLANE1_FAULT;
else if (DISPLAY_VER(dev_priv) >= 9)
else if (DISPLAY_VER(display) >= 9)
return GEN9_PIPE_CURSOR_FAULT |
GEN9_PIPE_PLANE4_FAULT |
GEN9_PIPE_PLANE3_FAULT |
@ -1420,7 +1423,6 @@ static void intel_display_vblank_dc_work(struct work_struct *work)
{
struct intel_display *display =
container_of(work, typeof(*display), irq.vblank_dc_work);
struct drm_i915_private *i915 = to_i915(display->drm);
int vblank_wa_num_pipes = READ_ONCE(display->irq.vblank_wa_num_pipes);
/*
@ -1429,7 +1431,7 @@ static void intel_display_vblank_dc_work(struct work_struct *work)
* PSR code. If DC3CO is taken into use we need take that into account
* here as well.
*/
intel_display_power_set_target_dc_state(i915, vblank_wa_num_pipes ? DC_STATE_DISABLE :
intel_display_power_set_target_dc_state(display, vblank_wa_num_pipes ? DC_STATE_DISABLE :
DC_STATE_EN_UPTO_DC6);
}
@ -1479,7 +1481,7 @@ void bdw_disable_vblank(struct drm_crtc *_crtc)
schedule_work(&display->irq.vblank_dc_work);
}
void vlv_display_irq_reset(struct drm_i915_private *dev_priv)
static void _vlv_display_irq_reset(struct drm_i915_private *dev_priv)
{
struct intel_uncore *uncore = &dev_priv->uncore;
@ -1497,6 +1499,12 @@ void vlv_display_irq_reset(struct drm_i915_private *dev_priv)
dev_priv->irq_mask = ~0u;
}
void vlv_display_irq_reset(struct drm_i915_private *dev_priv)
{
if (dev_priv->display.irq.vlv_display_irqs_enabled)
_vlv_display_irq_reset(dev_priv);
}
void i9xx_display_irq_reset(struct drm_i915_private *i915)
{
if (I915_HAS_HOTPLUG(i915)) {
@ -1516,6 +1524,9 @@ void vlv_display_irq_postinstall(struct drm_i915_private *dev_priv)
u32 enable_mask;
enum pipe pipe;
if (!dev_priv->display.irq.vlv_display_irqs_enabled)
return;
pipestat_mask = PIPE_CRC_DONE_INTERRUPT_STATUS;
i915_enable_pipestat(dev_priv, PIPE_A, PIPE_GMBUS_INTERRUPT_STATUS);
@ -1688,13 +1699,13 @@ void valleyview_enable_display_irqs(struct drm_i915_private *dev_priv)
{
lockdep_assert_held(&dev_priv->irq_lock);
if (dev_priv->display.irq.display_irqs_enabled)
if (dev_priv->display.irq.vlv_display_irqs_enabled)
return;
dev_priv->display.irq.display_irqs_enabled = true;
dev_priv->display.irq.vlv_display_irqs_enabled = true;
if (intel_irqs_enabled(dev_priv)) {
vlv_display_irq_reset(dev_priv);
_vlv_display_irq_reset(dev_priv);
vlv_display_irq_postinstall(dev_priv);
}
}
@ -1703,13 +1714,13 @@ void valleyview_disable_display_irqs(struct drm_i915_private *dev_priv)
{
lockdep_assert_held(&dev_priv->irq_lock);
if (!dev_priv->display.irq.display_irqs_enabled)
if (!dev_priv->display.irq.vlv_display_irqs_enabled)
return;
dev_priv->display.irq.display_irqs_enabled = false;
dev_priv->display.irq.vlv_display_irqs_enabled = false;
if (intel_irqs_enabled(dev_priv))
vlv_display_irq_reset(dev_priv);
_vlv_display_irq_reset(dev_priv);
}
void ilk_de_irq_postinstall(struct drm_i915_private *i915)
@ -1902,17 +1913,6 @@ void intel_display_irq_init(struct drm_i915_private *i915)
{
i915->drm.vblank_disable_immediate = true;
/*
* Most platforms treat the display irq block as an always-on power
* domain. vlv/chv can disable it at runtime and need special care to
* avoid writing any of the display block registers outside of the power
* domain. We defer setting up the display irqs in this case to the
* runtime pm.
*/
i915->display.irq.display_irqs_enabled = true;
if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915))
i915->display.irq.display_irqs_enabled = false;
intel_hotplug_irq_init(i915);
INIT_WORK(&i915->display.irq.vblank_dc_work,

@ -123,10 +123,10 @@ intel_display_param_named_unsafe(enable_psr2_sel_fetch, bool, 0400,
"(0=disabled, 1=enabled) "
"Default: 1");
intel_display_param_named_unsafe(enable_dmc_wl, bool, 0400,
intel_display_param_named_unsafe(enable_dmc_wl, int, 0400,
"Enable DMC wakelock "
"(0=disabled, 1=enabled) "
"Default: 0");
"(-1=use per-chip default, 0=disabled, 1=enabled) "
"Default: -1");
__maybe_unused
static void _param_print_bool(struct drm_printer *p, const char *driver_name,

@ -47,7 +47,7 @@ struct drm_printer;
param(int, enable_psr, -1, 0600) \
param(bool, psr_safest_params, false, 0400) \
param(bool, enable_psr2_sel_fetch, true, 0400) \
param(bool, enable_dmc_wl, false, 0400) \
param(int, enable_dmc_wl, -1, 0400) \
#define MEMBER(T, member, ...) T member;
struct intel_display_params {

File diff suppressed because it is too large Load Diff

@ -15,6 +15,7 @@ enum aux_ch;
enum port;
struct drm_i915_private;
struct i915_power_well;
struct intel_display;
struct intel_encoder;
struct seq_file;
@ -166,21 +167,21 @@ struct intel_display_power_domain_set {
for ((__domain) = 0; (__domain) < POWER_DOMAIN_NUM; (__domain)++) \
for_each_if(test_bit((__domain), (__mask)->bits))
int intel_power_domains_init(struct drm_i915_private *dev_priv);
void intel_power_domains_cleanup(struct drm_i915_private *dev_priv);
void intel_power_domains_init_hw(struct drm_i915_private *dev_priv, bool resume);
void intel_power_domains_driver_remove(struct drm_i915_private *dev_priv);
void intel_power_domains_enable(struct drm_i915_private *dev_priv);
void intel_power_domains_disable(struct drm_i915_private *dev_priv);
void intel_power_domains_suspend(struct drm_i915_private *dev_priv, bool s2idle);
void intel_power_domains_resume(struct drm_i915_private *dev_priv);
void intel_power_domains_sanitize_state(struct drm_i915_private *dev_priv);
int intel_power_domains_init(struct intel_display *display);
void intel_power_domains_cleanup(struct intel_display *display);
void intel_power_domains_init_hw(struct intel_display *display, bool resume);
void intel_power_domains_driver_remove(struct intel_display *display);
void intel_power_domains_enable(struct intel_display *display);
void intel_power_domains_disable(struct intel_display *display);
void intel_power_domains_suspend(struct intel_display *display, bool s2idle);
void intel_power_domains_resume(struct intel_display *display);
void intel_power_domains_sanitize_state(struct intel_display *display);
void intel_display_power_suspend_late(struct drm_i915_private *i915);
void intel_display_power_resume_early(struct drm_i915_private *i915);
void intel_display_power_suspend(struct drm_i915_private *i915);
void intel_display_power_resume(struct drm_i915_private *i915);
void intel_display_power_set_target_dc_state(struct drm_i915_private *dev_priv,
void intel_display_power_suspend_late(struct intel_display *display, bool s2idle);
void intel_display_power_resume_early(struct intel_display *display);
void intel_display_power_suspend(struct intel_display *display);
void intel_display_power_resume(struct intel_display *display);
void intel_display_power_set_target_dc_state(struct intel_display *display,
u32 state);
bool intel_display_power_is_enabled(struct drm_i915_private *dev_priv,

@ -1752,9 +1752,9 @@ __set_power_wells(struct i915_power_domains *power_domains,
const struct i915_power_well_desc_list *power_well_descs,
int power_well_descs_sz)
{
struct drm_i915_private *i915 = container_of(power_domains,
struct drm_i915_private,
display.power.domains);
struct intel_display *display = container_of(power_domains,
struct intel_display,
power.domains);
u64 power_well_ids = 0;
const struct i915_power_well_desc_list *desc_list;
const struct i915_power_well_desc *desc;
@ -1778,7 +1778,7 @@ __set_power_wells(struct i915_power_domains *power_domains,
enum i915_power_well_id id = inst->id;
pw->desc = desc;
drm_WARN_ON(&i915->drm,
drm_WARN_ON(display->drm,
overflows_type(inst - desc->instances->list, pw->instance_idx));
pw->instance_idx = inst - desc->instances->list;
@ -1789,8 +1789,8 @@ __set_power_wells(struct i915_power_domains *power_domains,
if (id == DISP_PW_ID_NONE)
continue;
drm_WARN_ON(&i915->drm, id >= sizeof(power_well_ids) * 8);
drm_WARN_ON(&i915->drm, power_well_ids & BIT_ULL(id));
drm_WARN_ON(display->drm, id >= sizeof(power_well_ids) * 8);
drm_WARN_ON(display->drm, power_well_ids & BIT_ULL(id));
power_well_ids |= BIT_ULL(id);
}
@ -1811,53 +1811,53 @@ __set_power_wells(struct i915_power_domains *power_domains,
*/
int intel_display_power_map_init(struct i915_power_domains *power_domains)
{
struct drm_i915_private *i915 = container_of(power_domains,
struct drm_i915_private,
display.power.domains);
struct intel_display *display = container_of(power_domains,
struct intel_display,
power.domains);
/*
* The enabling order will be from lower to higher indexed wells,
* the disabling order is reversed.
*/
if (!HAS_DISPLAY(i915)) {
if (!HAS_DISPLAY(display)) {
power_domains->power_well_count = 0;
return 0;
}
if (DISPLAY_VER(i915) >= 30)
if (DISPLAY_VER(display) >= 30)
return set_power_wells(power_domains, xe3lpd_power_wells);
else if (DISPLAY_VER(i915) >= 20)
else if (DISPLAY_VER(display) >= 20)
return set_power_wells(power_domains, xe2lpd_power_wells);
else if (DISPLAY_VER(i915) >= 14)
else if (DISPLAY_VER(display) >= 14)
return set_power_wells(power_domains, xelpdp_power_wells);
else if (IS_DG2(i915))
else if (display->platform.dg2)
return set_power_wells(power_domains, xehpd_power_wells);
else if (DISPLAY_VER(i915) >= 13)
else if (DISPLAY_VER(display) >= 13)
return set_power_wells(power_domains, xelpd_power_wells);
else if (IS_DG1(i915))
else if (display->platform.dg1)
return set_power_wells(power_domains, dg1_power_wells);
else if (IS_ALDERLAKE_S(i915))
else if (display->platform.alderlake_s)
return set_power_wells(power_domains, adls_power_wells);
else if (IS_ROCKETLAKE(i915))
else if (display->platform.rocketlake)
return set_power_wells(power_domains, rkl_power_wells);
else if (DISPLAY_VER(i915) == 12)
else if (DISPLAY_VER(display) == 12)
return set_power_wells(power_domains, tgl_power_wells);
else if (DISPLAY_VER(i915) == 11)
else if (DISPLAY_VER(display) == 11)
return set_power_wells(power_domains, icl_power_wells);
else if (IS_GEMINILAKE(i915))
else if (display->platform.geminilake)
return set_power_wells(power_domains, glk_power_wells);
else if (IS_BROXTON(i915))
else if (display->platform.broxton)
return set_power_wells(power_domains, bxt_power_wells);
else if (DISPLAY_VER(i915) == 9)
else if (DISPLAY_VER(display) == 9)
return set_power_wells(power_domains, skl_power_wells);
else if (IS_CHERRYVIEW(i915))
else if (display->platform.cherryview)
return set_power_wells(power_domains, chv_power_wells);
else if (IS_BROADWELL(i915))
else if (display->platform.broadwell)
return set_power_wells(power_domains, bdw_power_wells);
else if (IS_HASWELL(i915))
else if (display->platform.haswell)
return set_power_wells(power_domains, hsw_power_wells);
else if (IS_VALLEYVIEW(i915))
else if (display->platform.valleyview)
return set_power_wells(power_domains, vlv_power_wells);
else if (IS_I830(i915))
else if (display->platform.i830)
return set_power_wells(power_domains, i830_power_wells);
else
return set_power_wells(power_domains, i9xx_power_wells);

File diff suppressed because it is too large Load Diff

@ -10,21 +10,20 @@
#include "intel_display_power.h"
#include "intel_dpio_phy.h"
struct drm_i915_private;
struct i915_power_well_ops;
struct intel_display;
struct intel_encoder;
#define for_each_power_well(__dev_priv, __power_well) \
for ((__power_well) = (__dev_priv)->display.power.domains.power_wells; \
(__power_well) - (__dev_priv)->display.power.domains.power_wells < \
(__dev_priv)->display.power.domains.power_well_count; \
#define for_each_power_well(___display, __power_well) \
for ((__power_well) = (___display)->power.domains.power_wells; \
(__power_well) - (___display)->power.domains.power_wells < \
(___display)->power.domains.power_well_count; \
(__power_well)++)
#define for_each_power_well_reverse(__dev_priv, __power_well) \
for ((__power_well) = (__dev_priv)->display.power.domains.power_wells + \
(__dev_priv)->display.power.domains.power_well_count - 1; \
(__power_well) - (__dev_priv)->display.power.domains.power_wells >= 0; \
#define for_each_power_well_reverse(___display, __power_well) \
for ((__power_well) = (___display)->power.domains.power_wells + \
(___display)->power.domains.power_well_count - 1; \
(__power_well) - (___display)->power.domains.power_wells >= 0; \
(__power_well)--)
/*
@ -127,23 +126,23 @@ struct i915_power_well {
u8 instance_idx;
};
struct i915_power_well *lookup_power_well(struct drm_i915_private *i915,
struct i915_power_well *lookup_power_well(struct intel_display *display,
enum i915_power_well_id id);
void intel_power_well_enable(struct drm_i915_private *i915,
void intel_power_well_enable(struct intel_display *display,
struct i915_power_well *power_well);
void intel_power_well_disable(struct drm_i915_private *i915,
void intel_power_well_disable(struct intel_display *display,
struct i915_power_well *power_well);
void intel_power_well_sync_hw(struct drm_i915_private *i915,
void intel_power_well_sync_hw(struct intel_display *display,
struct i915_power_well *power_well);
void intel_power_well_get(struct drm_i915_private *i915,
void intel_power_well_get(struct intel_display *display,
struct i915_power_well *power_well);
void intel_power_well_put(struct drm_i915_private *i915,
void intel_power_well_put(struct intel_display *display,
struct i915_power_well *power_well);
bool intel_power_well_is_enabled(struct drm_i915_private *i915,
bool intel_power_well_is_enabled(struct intel_display *display,
struct i915_power_well *power_well);
bool intel_power_well_is_enabled_cached(struct i915_power_well *power_well);
bool intel_display_power_well_is_enabled(struct drm_i915_private *dev_priv,
bool intel_display_power_well_is_enabled(struct intel_display *display,
enum i915_power_well_id power_well_id);
bool intel_power_well_is_always_on(struct i915_power_well *power_well);
const char *intel_power_well_name(struct i915_power_well *power_well);
@ -152,7 +151,7 @@ int intel_power_well_refcount(struct i915_power_well *power_well);
void chv_phy_powergate_lanes(struct intel_encoder *encoder,
bool override, unsigned int mask);
bool chv_phy_powergate_ch(struct drm_i915_private *dev_priv, enum dpio_phy phy,
bool chv_phy_powergate_ch(struct intel_display *display, enum dpio_phy phy,
enum dpio_channel ch, bool override);
void gen9_enable_dc5(struct intel_display *display);

@ -114,11 +114,11 @@ void intel_display_reset_finish(struct drm_i915_private *i915)
* so need a full re-initialization.
*/
intel_pps_unlock_regs_wa(display);
intel_display_driver_init_hw(i915);
intel_display_driver_init_hw(display);
intel_clock_gating_init(i915);
intel_hpd_init(i915);
ret = __intel_display_driver_resume(i915, state, ctx);
ret = __intel_display_driver_resume(display, state, ctx);
if (ret)
drm_err(&i915->drm,
"Restoring old state failed with %i\n", ret);

@ -301,6 +301,15 @@ struct intel_panel_bl_funcs {
u32 (*hz_to_pwm)(struct intel_connector *connector, u32 hz);
};
/* in 100us units */
struct intel_pps_delays {
u16 power_up; /* eDP: T1+T3, LVDS: T1+T2 */
u16 backlight_on; /* eDP: T8, LVDS: T5 */
u16 backlight_off; /* eDP: T9, LVDS: T6/TX */
u16 power_down; /* eDP: T10, LVDS: T3 */
u16 power_cycle; /* eDP: T11+T12, LVDS: T7+T4 */
};
enum drrs_type {
DRRS_TYPE_NONE,
DRRS_TYPE_STATIC,
@ -328,7 +337,7 @@ struct intel_vbt_panel_data {
int preemphasis;
int vswing;
int bpp;
struct edp_power_seq pps;
struct intel_pps_delays pps;
u8 drrs_msa_timing_delay;
bool low_vswing;
bool hobl;
@ -587,6 +596,8 @@ struct intel_atomic_state {
bool skip_intermediate_wm;
bool rps_interactive;
struct work_struct cleanup_work;
};
struct intel_plane_state {
@ -697,8 +708,8 @@ struct intel_initial_plane_config {
};
struct intel_scaler {
int in_use;
u32 mode;
bool in_use;
};
struct intel_crtc_scaler_state {
@ -1235,7 +1246,7 @@ struct intel_crtc_state {
/* Display Stream compression state */
struct {
bool compression_enable;
bool dsc_split;
int num_streams;
/* Compressed Bpp in U6.4 format (first 4 bits for fractional part) */
u16 compressed_bpp_x16;
u8 slice_count;
@ -1568,8 +1579,8 @@ struct intel_pps {
* requiring a reinitialization. Only relevant on BXT+.
*/
bool bxt_pps_reset;
struct edp_power_seq pps_delays;
struct edp_power_seq bios_pps_delays;
struct intel_pps_delays pps_delays;
struct intel_pps_delays bios_pps_delays;
};
struct intel_psr {
@ -1803,11 +1814,13 @@ struct intel_lspcon {
struct intel_digital_port {
struct intel_encoder base;
u32 saved_port_bits;
struct intel_dp dp;
struct intel_hdmi hdmi;
struct intel_lspcon lspcon;
enum irqreturn (*hpd_pulse)(struct intel_digital_port *, bool);
bool lane_reversal;
bool ddi_a_4_lanes;
bool release_cl2_override;
u8 max_lanes;
/* Used for DP and ICL+ TypeC/DP and TypeC/HDMI ports. */

@ -638,8 +638,6 @@ void intel_dmc_disable_program(struct intel_display *display)
pipedmc_clock_gating_wa(display, true);
disable_all_event_handlers(display);
pipedmc_clock_gating_wa(display, false);
intel_dmc_wl_disable(display);
}
void assert_dmc_loaded(struct intel_display *display)
@ -1146,8 +1144,6 @@ void intel_dmc_suspend(struct intel_display *display)
if (dmc)
flush_work(&dmc->work);
intel_dmc_wl_disable(display);
/* Drop the reference held in case DMC isn't loaded. */
if (!intel_dmc_has_payload(display))
intel_dmc_runtime_pm_put(display);

@ -5,6 +5,9 @@
#include <linux/kernel.h>
#include <drm/drm_print.h>
#include "i915_reg.h"
#include "intel_de.h"
#include "intel_dmc.h"
#include "intel_dmc_regs.h"
@ -39,7 +42,11 @@
* potential future use.
*/
#define DMC_WAKELOCK_CTL_TIMEOUT 5
/*
* Define DMC_WAKELOCK_CTL_TIMEOUT_US in microseconds because we use the
* atomic variant of waiting MMIO.
*/
#define DMC_WAKELOCK_CTL_TIMEOUT_US 5000
#define DMC_WAKELOCK_HOLD_TIME 50
struct intel_dmc_wl_range {
@ -47,8 +54,90 @@ struct intel_dmc_wl_range {
u32 end;
};
static struct intel_dmc_wl_range lnl_wl_range[] = {
static struct intel_dmc_wl_range powered_off_ranges[] = {
{ .start = 0x60000, .end = 0x7ffff },
{},
};
static struct intel_dmc_wl_range xe3lpd_dc5_dc6_dmc_ranges[] = {
{ .start = 0x45500 }, /* DC_STATE_SEL */
{ .start = 0x457a0, .end = 0x457b0 }, /* DC*_RESIDENCY_COUNTER */
{ .start = 0x45504 }, /* DC_STATE_EN */
{ .start = 0x45400, .end = 0x4540c }, /* PWR_WELL_CTL_* */
{ .start = 0x454f0 }, /* RETENTION_CTRL */
/* DBUF_CTL_* */
{ .start = 0x44300 },
{ .start = 0x44304 },
{ .start = 0x44f00 },
{ .start = 0x44f04 },
{ .start = 0x44fe8 },
{ .start = 0x45008 },
{ .start = 0x46070 }, /* CDCLK_PLL_ENABLE */
{ .start = 0x46000 }, /* CDCLK_CTL */
{ .start = 0x46008 }, /* CDCLK_SQUASH_CTL */
/* TRANS_CMTG_CTL_* */
{ .start = 0x6fa88 },
{ .start = 0x6fb88 },
{ .start = 0x46430 }, /* CHICKEN_DCPR_1 */
{ .start = 0x46434 }, /* CHICKEN_DCPR_2 */
{ .start = 0x454a0 }, /* CHICKEN_DCPR_4 */
{ .start = 0x42084 }, /* CHICKEN_MISC_2 */
{ .start = 0x42088 }, /* CHICKEN_MISC_3 */
{ .start = 0x46160 }, /* CMTG_CLK_SEL */
{ .start = 0x8f000, .end = 0x8ffff }, /* Main DMC registers */
{},
};
static struct intel_dmc_wl_range xe3lpd_dc3co_dmc_ranges[] = {
{ .start = 0x454a0 }, /* CHICKEN_DCPR_4 */
{ .start = 0x45504 }, /* DC_STATE_EN */
/* DBUF_CTL_* */
{ .start = 0x44300 },
{ .start = 0x44304 },
{ .start = 0x44f00 },
{ .start = 0x44f04 },
{ .start = 0x44fe8 },
{ .start = 0x45008 },
{ .start = 0x46070 }, /* CDCLK_PLL_ENABLE */
{ .start = 0x46000 }, /* CDCLK_CTL */
{ .start = 0x46008 }, /* CDCLK_SQUASH_CTL */
{ .start = 0x8f000, .end = 0x8ffff }, /* Main DMC registers */
/* Scanline registers */
{ .start = 0x70000 },
{ .start = 0x70004 },
{ .start = 0x70014 },
{ .start = 0x70018 },
{ .start = 0x71000 },
{ .start = 0x71004 },
{ .start = 0x71014 },
{ .start = 0x71018 },
{ .start = 0x72000 },
{ .start = 0x72004 },
{ .start = 0x72014 },
{ .start = 0x72018 },
{ .start = 0x73000 },
{ .start = 0x73004 },
{ .start = 0x73014 },
{ .start = 0x73018 },
{ .start = 0x7b000 },
{ .start = 0x7b004 },
{ .start = 0x7b014 },
{ .start = 0x7b018 },
{ .start = 0x7c000 },
{ .start = 0x7c004 },
{ .start = 0x7c014 },
{ .start = 0x7c018 },
{},
};
static void __intel_dmc_wl_release(struct intel_display *display)
@ -72,15 +161,18 @@ static void intel_dmc_wl_work(struct work_struct *work)
spin_lock_irqsave(&wl->lock, flags);
/* Bail out if refcount reached zero while waiting for the spinlock */
if (!refcount_read(&wl->refcount))
/*
* Bail out if refcount became non-zero while waiting for the spinlock,
* meaning that the lock is now taken again.
*/
if (refcount_read(&wl->refcount))
goto out_unlock;
__intel_de_rmw_nowl(display, DMC_WAKELOCK1_CTL, DMC_WAKELOCK_CTL_REQ, 0);
if (__intel_de_wait_for_register_nowl(display, DMC_WAKELOCK1_CTL,
DMC_WAKELOCK_CTL_ACK, 0,
DMC_WAKELOCK_CTL_TIMEOUT)) {
if (__intel_de_wait_for_register_atomic_nowl(display, DMC_WAKELOCK1_CTL,
DMC_WAKELOCK_CTL_ACK, 0,
DMC_WAKELOCK_CTL_TIMEOUT_US)) {
WARN_RATELIMIT(1, "DMC wakelock release timed out");
goto out_unlock;
}
@ -91,38 +183,110 @@ static void intel_dmc_wl_work(struct work_struct *work)
spin_unlock_irqrestore(&wl->lock, flags);
}
static bool intel_dmc_wl_check_range(u32 address)
static void __intel_dmc_wl_take(struct intel_display *display)
{
int i;
bool wl_needed = false;
struct intel_dmc_wl *wl = &display->wl;
for (i = 0; i < ARRAY_SIZE(lnl_wl_range); i++) {
if (address >= lnl_wl_range[i].start &&
address <= lnl_wl_range[i].end) {
wl_needed = true;
break;
}
/*
* Only try to take the wakelock if it's not marked as taken
* yet. It may be already taken at this point if we have
* already released the last reference, but the work has not
* run yet.
*/
if (wl->taken)
return;
__intel_de_rmw_nowl(display, DMC_WAKELOCK1_CTL, 0,
DMC_WAKELOCK_CTL_REQ);
/*
* We need to use the atomic variant of the waiting routine
* because the DMC wakelock is also taken in atomic context.
*/
if (__intel_de_wait_for_register_atomic_nowl(display, DMC_WAKELOCK1_CTL,
DMC_WAKELOCK_CTL_ACK,
DMC_WAKELOCK_CTL_ACK,
DMC_WAKELOCK_CTL_TIMEOUT_US)) {
WARN_RATELIMIT(1, "DMC wakelock ack timed out");
return;
}
return wl_needed;
wl->taken = true;
}
static bool intel_dmc_wl_reg_in_range(i915_reg_t reg,
const struct intel_dmc_wl_range ranges[])
{
u32 offset = i915_mmio_reg_offset(reg);
for (int i = 0; ranges[i].start; i++) {
u32 end = ranges[i].end ?: ranges[i].start;
if (ranges[i].start <= offset && offset <= end)
return true;
}
return false;
}
static bool intel_dmc_wl_check_range(i915_reg_t reg, u32 dc_state)
{
const struct intel_dmc_wl_range *ranges;
/*
* Check that the offset is in one of the ranges for which
* registers are powered off during DC states.
*/
if (intel_dmc_wl_reg_in_range(reg, powered_off_ranges))
return true;
/*
* Check that the offset is for a register that is touched by
* the DMC and requires a DC exit for proper access.
*/
switch (dc_state) {
case DC_STATE_EN_DC3CO:
ranges = xe3lpd_dc3co_dmc_ranges;
break;
case DC_STATE_EN_UPTO_DC5:
case DC_STATE_EN_UPTO_DC6:
ranges = xe3lpd_dc5_dc6_dmc_ranges;
break;
default:
ranges = NULL;
}
if (ranges && intel_dmc_wl_reg_in_range(reg, ranges))
return true;
return false;
}
static bool __intel_dmc_wl_supported(struct intel_display *display)
{
if (DISPLAY_VER(display) < 20 ||
!intel_dmc_has_payload(display) ||
!display->params.enable_dmc_wl)
return false;
return display->params.enable_dmc_wl && intel_dmc_has_payload(display);
}
return true;
static void intel_dmc_wl_sanitize_param(struct intel_display *display)
{
if (!HAS_DMC_WAKELOCK(display))
display->params.enable_dmc_wl = 0;
else if (display->params.enable_dmc_wl >= 0)
display->params.enable_dmc_wl = !!display->params.enable_dmc_wl;
else
display->params.enable_dmc_wl = DISPLAY_VER(display) >= 30;
drm_dbg_kms(display->drm, "Sanitized enable_dmc_wl value: %d\n",
display->params.enable_dmc_wl);
}
void intel_dmc_wl_init(struct intel_display *display)
{
struct intel_dmc_wl *wl = &display->wl;
/* don't call __intel_dmc_wl_supported(), DMC is not loaded yet */
if (DISPLAY_VER(display) < 20 || !display->params.enable_dmc_wl)
intel_dmc_wl_sanitize_param(display);
if (!display->params.enable_dmc_wl)
return;
INIT_DELAYED_WORK(&wl->work, intel_dmc_wl_work);
@ -130,7 +294,8 @@ void intel_dmc_wl_init(struct intel_display *display)
refcount_set(&wl->refcount, 0);
}
void intel_dmc_wl_enable(struct intel_display *display)
/* Must only be called as part of enabling dynamic DC states. */
void intel_dmc_wl_enable(struct intel_display *display, u32 dc_state)
{
struct intel_dmc_wl *wl = &display->wl;
unsigned long flags;
@ -140,7 +305,9 @@ void intel_dmc_wl_enable(struct intel_display *display)
spin_lock_irqsave(&wl->lock, flags);
if (wl->enabled)
wl->dc_state = dc_state;
if (drm_WARN_ON(display->drm, wl->enabled))
goto out_unlock;
/*
@ -151,12 +318,29 @@ void intel_dmc_wl_enable(struct intel_display *display)
__intel_de_rmw_nowl(display, DMC_WAKELOCK_CFG, 0, DMC_WAKELOCK_CFG_ENABLE);
wl->enabled = true;
wl->taken = false;
/*
* This would be racy in the following scenario:
*
* 1. Function A calls intel_dmc_wl_get();
* 2. Some function calls intel_dmc_wl_disable();
* 3. Some function calls intel_dmc_wl_enable();
* 4. Concurrently with (3), function A performs the MMIO in between
* setting DMC_WAKELOCK_CFG_ENABLE and asserting the lock with
* __intel_dmc_wl_take().
*
* TODO: Check with the hardware team whether it is safe to assert the
* hardware lock before enabling to avoid such a scenario. Otherwise, we
* would need to deal with it via software synchronization.
*/
if (refcount_read(&wl->refcount))
__intel_dmc_wl_take(display);
out_unlock:
spin_unlock_irqrestore(&wl->lock, flags);
}
/* Must only be called as part of disabling dynamic DC states. */
void intel_dmc_wl_disable(struct intel_display *display)
{
struct intel_dmc_wl *wl = &display->wl;
@ -165,24 +349,44 @@ void intel_dmc_wl_disable(struct intel_display *display)
if (!__intel_dmc_wl_supported(display))
return;
flush_delayed_work(&wl->work);
intel_dmc_wl_flush_release_work(display);
spin_lock_irqsave(&wl->lock, flags);
if (!wl->enabled)
if (drm_WARN_ON(display->drm, !wl->enabled))
goto out_unlock;
/* Disable wakelock in DMC */
__intel_de_rmw_nowl(display, DMC_WAKELOCK_CFG, DMC_WAKELOCK_CFG_ENABLE, 0);
refcount_set(&wl->refcount, 0);
wl->enabled = false;
/*
* The spec is not explicit about the expectation of existing
* lock users at the moment of disabling, but it does say that we must
* clear DMC_WAKELOCK_CTL_REQ, which gives us a clue that it is okay to
* disable with existing lock users.
*
* TODO: Get the correct expectation from the hardware team.
*/
__intel_de_rmw_nowl(display, DMC_WAKELOCK1_CTL, DMC_WAKELOCK_CTL_REQ, 0);
wl->taken = false;
out_unlock:
spin_unlock_irqrestore(&wl->lock, flags);
}
void intel_dmc_wl_flush_release_work(struct intel_display *display)
{
struct intel_dmc_wl *wl = &display->wl;
if (!__intel_dmc_wl_supported(display))
return;
flush_delayed_work(&wl->work);
}
void intel_dmc_wl_get(struct intel_display *display, i915_reg_t reg)
{
struct intel_dmc_wl *wl = &display->wl;
@ -191,14 +395,17 @@ void intel_dmc_wl_get(struct intel_display *display, i915_reg_t reg)
if (!__intel_dmc_wl_supported(display))
return;
if (!intel_dmc_wl_check_range(reg.reg))
return;
spin_lock_irqsave(&wl->lock, flags);
if (!wl->enabled)
if (i915_mmio_reg_valid(reg) && !intel_dmc_wl_check_range(reg, wl->dc_state))
goto out_unlock;
if (!wl->enabled) {
if (!refcount_inc_not_zero(&wl->refcount))
refcount_set(&wl->refcount, 1);
goto out_unlock;
}
cancel_delayed_work(&wl->work);
if (refcount_inc_not_zero(&wl->refcount))
@ -206,26 +413,7 @@ void intel_dmc_wl_get(struct intel_display *display, i915_reg_t reg)
refcount_set(&wl->refcount, 1);
/*
* Only try to take the wakelock if it's not marked as taken
* yet. It may be already taken at this point if we have
* already released the last reference, but the work has not
* run yet.
*/
if (!wl->taken) {
__intel_de_rmw_nowl(display, DMC_WAKELOCK1_CTL, 0,
DMC_WAKELOCK_CTL_REQ);
if (__intel_de_wait_for_register_nowl(display, DMC_WAKELOCK1_CTL,
DMC_WAKELOCK_CTL_ACK,
DMC_WAKELOCK_CTL_ACK,
DMC_WAKELOCK_CTL_TIMEOUT)) {
WARN_RATELIMIT(1, "DMC wakelock ack timed out");
goto out_unlock;
}
wl->taken = true;
}
__intel_dmc_wl_take(display);
out_unlock:
spin_unlock_irqrestore(&wl->lock, flags);
@ -239,12 +427,9 @@ void intel_dmc_wl_put(struct intel_display *display, i915_reg_t reg)
if (!__intel_dmc_wl_supported(display))
return;
if (!intel_dmc_wl_check_range(reg.reg))
return;
spin_lock_irqsave(&wl->lock, flags);
if (!wl->enabled)
if (i915_mmio_reg_valid(reg) && !intel_dmc_wl_check_range(reg, wl->dc_state))
goto out_unlock;
if (WARN_RATELIMIT(!refcount_read(&wl->refcount),
@ -252,6 +437,9 @@ void intel_dmc_wl_put(struct intel_display *display, i915_reg_t reg)
goto out_unlock;
if (refcount_dec_and_test(&wl->refcount)) {
if (!wl->enabled)
goto out_unlock;
__intel_dmc_wl_release(display);
goto out_unlock;
@ -260,3 +448,13 @@ void intel_dmc_wl_put(struct intel_display *display, i915_reg_t reg)
out_unlock:
spin_unlock_irqrestore(&wl->lock, flags);
}
void intel_dmc_wl_get_noreg(struct intel_display *display)
{
intel_dmc_wl_get(display, INVALID_MMIO_REG);
}
void intel_dmc_wl_put_noreg(struct intel_display *display)
{
intel_dmc_wl_put(display, INVALID_MMIO_REG);
}

@ -15,17 +15,27 @@
struct intel_display;
struct intel_dmc_wl {
spinlock_t lock; /* protects enabled, taken and refcount */
spinlock_t lock; /* protects enabled, taken, dc_state and refcount */
bool enabled;
bool taken;
refcount_t refcount;
/*
* We are keeping a copy of the enabled DC state because
* intel_display.power.domains is protected by a mutex and we do
* not want call mutex_lock() in atomic context, where some of
* the tracked MMIO operations happen.
*/
u32 dc_state;
struct delayed_work work;
};
void intel_dmc_wl_init(struct intel_display *display);
void intel_dmc_wl_enable(struct intel_display *display);
void intel_dmc_wl_enable(struct intel_display *display, u32 dc_state);
void intel_dmc_wl_disable(struct intel_display *display);
void intel_dmc_wl_flush_release_work(struct intel_display *display);
void intel_dmc_wl_get(struct intel_display *display, i915_reg_t reg);
void intel_dmc_wl_put(struct intel_display *display, i915_reg_t reg);
void intel_dmc_wl_get_noreg(struct intel_display *display);
void intel_dmc_wl_put_noreg(struct intel_display *display);
#endif /* __INTEL_WAKELOCK_H__ */

@ -28,6 +28,7 @@
#include <linux/export.h>
#include <linux/i2c.h>
#include <linux/notifier.h>
#include <linux/seq_buf.h>
#include <linux/slab.h>
#include <linux/sort.h>
#include <linux/string_helpers.h>
@ -109,10 +110,19 @@
/* Constants for DP DSC configurations */
static const u8 valid_dsc_bpp[] = {6, 8, 10, 12, 15};
/* With Single pipe configuration, HW is capable of supporting maximum
* of 4 slices per line.
/*
* With Single pipe configuration, HW is capable of supporting maximum of:
* 2 slices per line for ICL, BMG
* 4 slices per line for other platforms.
* For now consider a max of 2 slices per line, which works for all platforms.
* With this we can have max of 4 DSC Slices per pipe.
*
* For higher resolutions where 12 slice support is required with
* ultrajoiner, only then each pipe can support 3 slices.
*
* #TODO Split this better to use 4 slices/dsc engine where supported.
*/
static const u8 valid_dsc_slicecount[] = {1, 2, 4};
static const u8 valid_dsc_slicecount[] = {1, 2, 3, 4};
/**
* intel_dp_is_edp - is the given port attached to an eDP panel (either CPU or PCH)
@ -1020,6 +1030,13 @@ u8 intel_dp_dsc_get_slice_count(const struct intel_connector *connector,
for (i = 0; i < ARRAY_SIZE(valid_dsc_slicecount); i++) {
u8 test_slice_count = valid_dsc_slicecount[i] * num_joined_pipes;
/*
* 3 DSC Slices per pipe need 3 DSC engines,
* which is supported only with Ultrajoiner.
*/
if (valid_dsc_slicecount[i] == 3 && num_joined_pipes != 4)
continue;
if (test_slice_count >
drm_dp_dsc_sink_max_slice_count(connector->dp.dsc_dpcd, false))
break;
@ -1032,6 +1049,9 @@ u8 intel_dp_dsc_get_slice_count(const struct intel_connector *connector,
if (num_joined_pipes > 1 && valid_dsc_slicecount[i] < 2)
continue;
if (mode_hdisplay % test_slice_count)
continue;
if (min_slice_count <= test_slice_count)
return test_slice_count;
}
@ -1333,16 +1353,15 @@ int intel_dp_num_joined_pipes(struct intel_dp *intel_dp,
int hdisplay, int clock)
{
struct intel_display *display = to_intel_display(intel_dp);
struct drm_i915_private *i915 = to_i915(display->drm);
if (connector->force_joined_pipes)
return connector->force_joined_pipes;
if (HAS_ULTRAJOINER(i915) &&
if (HAS_ULTRAJOINER(display) &&
intel_dp_needs_joiner(intel_dp, connector, hdisplay, clock, 4))
return 4;
if ((HAS_BIGJOINER(i915) || HAS_UNCOMPRESSED_JOINER(i915)) &&
if ((HAS_BIGJOINER(display) || HAS_UNCOMPRESSED_JOINER(display)) &&
intel_dp_needs_joiner(intel_dp, connector, hdisplay, clock, 2))
return 2;
@ -1488,41 +1507,32 @@ bool intel_dp_source_supports_tps4(struct drm_i915_private *i915)
return DISPLAY_VER(i915) >= 10;
}
static void snprintf_int_array(char *str, size_t len,
const int *array, int nelem)
static void seq_buf_print_array(struct seq_buf *s, const int *array, int nelem)
{
int i;
str[0] = '\0';
for (i = 0; i < nelem; i++) {
int r = snprintf(str, len, "%s%d", i ? ", " : "", array[i]);
if (r >= len)
return;
str += r;
len -= r;
}
for (i = 0; i < nelem; i++)
seq_buf_printf(s, "%s%d", i ? ", " : "", array[i]);
}
static void intel_dp_print_rates(struct intel_dp *intel_dp)
{
struct drm_i915_private *i915 = dp_to_i915(intel_dp);
char str[128]; /* FIXME: too big for stack? */
struct intel_display *display = to_intel_display(intel_dp);
DECLARE_SEQ_BUF(s, 128); /* FIXME: too big for stack? */
if (!drm_debug_enabled(DRM_UT_KMS))
return;
snprintf_int_array(str, sizeof(str),
intel_dp->source_rates, intel_dp->num_source_rates);
drm_dbg_kms(&i915->drm, "source rates: %s\n", str);
seq_buf_print_array(&s, intel_dp->source_rates, intel_dp->num_source_rates);
drm_dbg_kms(display->drm, "source rates: %s\n", seq_buf_str(&s));
snprintf_int_array(str, sizeof(str),
intel_dp->sink_rates, intel_dp->num_sink_rates);
drm_dbg_kms(&i915->drm, "sink rates: %s\n", str);
seq_buf_clear(&s);
seq_buf_print_array(&s, intel_dp->sink_rates, intel_dp->num_sink_rates);
drm_dbg_kms(display->drm, "sink rates: %s\n", seq_buf_str(&s));
snprintf_int_array(str, sizeof(str),
intel_dp->common_rates, intel_dp->num_common_rates);
drm_dbg_kms(&i915->drm, "common rates: %s\n", str);
seq_buf_clear(&s);
seq_buf_print_array(&s, intel_dp->common_rates, intel_dp->num_common_rates);
drm_dbg_kms(display->drm, "common rates: %s\n", seq_buf_str(&s));
}
static int forced_link_rate(struct intel_dp *intel_dp)
@ -1700,13 +1710,13 @@ static int intel_dp_max_bpp(struct intel_dp *intel_dp,
static bool has_seamless_m_n(struct intel_connector *connector)
{
struct drm_i915_private *i915 = to_i915(connector->base.dev);
struct intel_display *display = to_intel_display(connector);
/*
* Seamless M/N reprogramming only implemented
* for BDW+ double buffered M/N registers so far.
*/
return HAS_DOUBLE_BUFFERED_M_N(i915) &&
return HAS_DOUBLE_BUFFERED_M_N(display) &&
intel_panel_drrs_type(connector) == DRRS_TYPE_SEAMLESS;
}
@ -2021,6 +2031,15 @@ static int dsc_src_max_compressed_bpp(struct intel_dp *intel_dp)
{
struct drm_i915_private *i915 = dp_to_i915(intel_dp);
/*
* Forcing DSC and using the platform's max compressed bpp is seen to cause
* underruns. Since DSC isn't needed in these cases, limit the
* max compressed bpp to 18, which is a safe value across platforms with different
* pipe bpps.
*/
if (intel_dp->force_dsc_en)
return 18;
/*
* Max Compressed bpp for Gen 13+ is 27bpp.
* For earlier platform is 23bpp. (Bspec:49259).
@ -2405,9 +2424,16 @@ int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
* VDSC engine operates at 1 Pixel per clock, so if peak pixel rate
* is greater than the maximum Cdclock and if slice count is even
* then we need to use 2 VDSC instances.
* In case of Ultrajoiner along with 12 slices we need to use 3
* VDSC instances.
*/
if (pipe_config->joiner_pipes || pipe_config->dsc.slice_count > 1)
pipe_config->dsc.dsc_split = true;
if (pipe_config->joiner_pipes && num_joined_pipes == 4 &&
pipe_config->dsc.slice_count == 12)
pipe_config->dsc.num_streams = 3;
else if (pipe_config->joiner_pipes || pipe_config->dsc.slice_count > 1)
pipe_config->dsc.num_streams = 2;
else
pipe_config->dsc.num_streams = 1;
ret = intel_dp_dsc_compute_params(connector, pipe_config);
if (ret < 0) {
@ -3064,9 +3090,6 @@ intel_dp_compute_config(struct intel_encoder *encoder,
struct intel_connector *connector = intel_dp->attached_connector;
int ret = 0, link_bpp_x16;
if (HAS_PCH_SPLIT(dev_priv) && !HAS_DDI(dev_priv) && encoder->port != PORT_A)
pipe_config->has_pch_encoder = true;
fixed_mode = intel_panel_fixed_mode(connector, adjusted_mode);
if (intel_dp_is_edp(intel_dp) && fixed_mode) {
ret = intel_panel_compute_config(connector, adjusted_mode);
@ -3149,9 +3172,6 @@ intel_dp_compute_config(struct intel_encoder *encoder,
if (pipe_config->splitter.enable)
pipe_config->dp_m_n.data_m *= pipe_config->splitter.link_count;
if (!HAS_DDI(dev_priv))
g4x_dp_set_clock(encoder, pipe_config);
intel_vrr_compute_config(pipe_config, conn_state);
intel_dp_compute_as_sdp(intel_dp, pipe_config);
intel_psr_compute_config(intel_dp, pipe_config, conn_state);
@ -3406,7 +3426,7 @@ void intel_dp_sink_disable_decompression(struct intel_atomic_state *state,
static void
intel_dp_init_source_oui(struct intel_dp *intel_dp)
{
struct drm_i915_private *i915 = dp_to_i915(intel_dp);
struct intel_display *display = to_intel_display(intel_dp);
u8 oui[] = { 0x00, 0xaa, 0x01 };
u8 buf[3] = {};
@ -3420,7 +3440,7 @@ intel_dp_init_source_oui(struct intel_dp *intel_dp)
* already set to what we want, so as to avoid clearing any state by accident
*/
if (drm_dp_dpcd_read(&intel_dp->aux, DP_SOURCE_OUI, buf, sizeof(buf)) < 0)
drm_err(&i915->drm, "Failed to read source OUI\n");
drm_dbg_kms(display->drm, "Failed to read source OUI\n");
if (memcmp(oui, buf, sizeof(oui)) == 0) {
/* Assume the OUI was written now. */
@ -3429,7 +3449,7 @@ intel_dp_init_source_oui(struct intel_dp *intel_dp)
}
if (drm_dp_dpcd_write(&intel_dp->aux, DP_SOURCE_OUI, oui, sizeof(oui)) < 0) {
drm_info(&i915->drm, "Failed to write source OUI\n");
drm_dbg_kms(display->drm, "Failed to write source OUI\n");
WRITE_ONCE(intel_dp->oui_valid, false);
}
@ -5608,6 +5628,7 @@ intel_dp_detect(struct drm_connector *connector,
struct drm_modeset_acquire_ctx *ctx,
bool force)
{
struct intel_display *display = to_intel_display(connector->dev);
struct drm_i915_private *dev_priv = to_i915(connector->dev);
struct intel_connector *intel_connector =
to_intel_connector(connector);
@ -5622,10 +5643,10 @@ intel_dp_detect(struct drm_connector *connector,
drm_WARN_ON(&dev_priv->drm,
!drm_modeset_is_locked(&dev_priv->drm.mode_config.connection_mutex));
if (!intel_display_device_enabled(dev_priv))
if (!intel_display_device_enabled(display))
return connector_status_disconnected;
if (!intel_display_driver_check_access(dev_priv))
if (!intel_display_driver_check_access(display))
return connector->status;
intel_dp_flush_connector_commits(intel_connector);
@ -5747,6 +5768,7 @@ intel_dp_detect(struct drm_connector *connector,
static void
intel_dp_force(struct drm_connector *connector)
{
struct intel_display *display = to_intel_display(connector->dev);
struct intel_dp *intel_dp = intel_attached_dp(to_intel_connector(connector));
struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
struct intel_encoder *intel_encoder = &dig_port->base;
@ -5755,7 +5777,7 @@ intel_dp_force(struct drm_connector *connector)
drm_dbg_kms(&dev_priv->drm, "[CONNECTOR:%d:%s]\n",
connector->base.id, connector->name);
if (!intel_display_driver_check_access(dev_priv))
if (!intel_display_driver_check_access(display))
return;
intel_dp_unset_edid(intel_dp);

@ -6,7 +6,6 @@
#include "i915_drv.h"
#include "i915_reg.h"
#include "i915_trace.h"
#include "intel_bios.h"
#include "intel_de.h"
#include "intel_display_types.h"
#include "intel_dp.h"

@ -898,7 +898,7 @@ intel_dp_link_training_clock_recovery(struct intel_dp *intel_dp,
voltage_tries = 1;
for (cr_tries = 0; cr_tries < max_cr_tries; ++cr_tries) {
usleep_range(delay_us, 2 * delay_us);
fsleep(delay_us);
if (drm_dp_dpcd_read_phy_link_status(&intel_dp->aux, dp_phy,
link_status) < 0) {
@ -1040,7 +1040,7 @@ intel_dp_link_training_channel_equalization(struct intel_dp *intel_dp,
}
for (tries = 0; tries < 5; tries++) {
usleep_range(delay_us, 2 * delay_us);
fsleep(delay_us);
if (drm_dp_dpcd_read_phy_link_status(&intel_dp->aux, dp_phy,
link_status) < 0) {
@ -1414,16 +1414,10 @@ intel_dp_128b132b_lane_eq(struct intel_dp *intel_dp,
}
/* Time budget for the LANEx_EQ_DONE Sequence */
deadline = jiffies + msecs_to_jiffies_timeout(400);
deadline = jiffies + msecs_to_jiffies_timeout(450);
for (try = 0; try < max_tries; try++) {
usleep_range(delay_us, 2 * delay_us);
/*
* The delay may get updated. The transmitter shall read the
* delay before link status during link training.
*/
delay_us = drm_dp_128b132b_read_aux_rd_interval(&intel_dp->aux);
fsleep(delay_us);
if (drm_dp_dpcd_read_link_status(&intel_dp->aux, link_status) < 0) {
lt_err(intel_dp, DP_PHY_DPRX, "Failed to read link status\n");
@ -1451,8 +1445,15 @@ intel_dp_128b132b_lane_eq(struct intel_dp *intel_dp,
if (time_after(jiffies, deadline))
timeout = true; /* try one last time after deadline */
/* Update signal levels and training set as requested. */
/*
* During LT, Tx shall read AUX_RD_INTERVAL just before writing the new FFE
* presets.
*/
delay_us = drm_dp_128b132b_read_aux_rd_interval(&intel_dp->aux);
intel_dp_get_adjust_train(intel_dp, crtc_state, DP_PHY_DPRX, link_status);
/* Update signal levels and training set as requested. */
if (!intel_dp_update_link_train(intel_dp, crtc_state, DP_PHY_DPRX)) {
lt_err(intel_dp, DP_PHY_DPRX, "Failed to update TX FFE settings\n");
return false;

File diff suppressed because it is too large Load Diff

@ -855,6 +855,7 @@ void chv_data_lane_soft_reset(struct intel_encoder *encoder,
void chv_phy_pre_pll_enable(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(encoder);
struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
@ -871,7 +872,7 @@ void chv_phy_pre_pll_enable(struct intel_encoder *encoder,
*/
if (ch == DPIO_CH0 && pipe == PIPE_B)
dig_port->release_cl2_override =
!chv_phy_powergate_ch(dev_priv, DPIO_PHY0, DPIO_CH1, true);
!chv_phy_powergate_ch(display, DPIO_PHY0, DPIO_CH1, true);
chv_phy_powergate_lanes(encoder, true, lane_mask);
@ -1013,11 +1014,11 @@ void chv_phy_pre_encoder_enable(struct intel_encoder *encoder,
void chv_phy_release_cl2_override(struct intel_encoder *encoder)
{
struct intel_display *display = to_intel_display(encoder);
struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
if (dig_port->release_cl2_override) {
chv_phy_powergate_ch(dev_priv, DPIO_PHY0, DPIO_CH1, false);
chv_phy_powergate_ch(display, DPIO_PHY0, DPIO_CH1, false);
dig_port->release_cl2_override = false;
}
}

@ -205,7 +205,7 @@ void intel_dpt_resume(struct drm_i915_private *i915)
struct intel_framebuffer *fb = to_intel_framebuffer(drm_fb);
if (fb->dpt_vm)
i915_ggtt_resume_vm(fb->dpt_vm);
i915_ggtt_resume_vm(fb->dpt_vm, true);
}
mutex_unlock(&i915->drm.mode_config.fb_lock);
}
@ -233,7 +233,7 @@ void intel_dpt_suspend(struct drm_i915_private *i915)
struct intel_framebuffer *fb = to_intel_framebuffer(drm_fb);
if (fb->dpt_vm)
i915_ggtt_suspend_vm(fb->dpt_vm);
i915_ggtt_suspend_vm(fb->dpt_vm, true);
}
mutex_unlock(&i915->drm.mode_config.fb_lock);

@ -68,7 +68,9 @@ const char *intel_drrs_type_str(enum drrs_type drrs_type)
bool intel_cpu_transcoder_has_drrs(struct drm_i915_private *i915,
enum transcoder cpu_transcoder)
{
if (HAS_DOUBLE_BUFFERED_M_N(i915))
struct intel_display *display = &i915->display;
if (HAS_DOUBLE_BUFFERED_M_N(display))
return true;
return intel_cpu_transcoder_has_m2_n2(i915, cpu_transcoder);

@ -256,15 +256,6 @@ static bool intel_dsb_prev_ins_is_write(struct intel_dsb *dsb,
return prev_opcode == opcode && prev_reg == i915_mmio_reg_offset(reg);
}
static bool intel_dsb_prev_ins_is_mmio_write(struct intel_dsb *dsb, i915_reg_t reg)
{
/* only full byte-enables can be converted to indexed writes */
return intel_dsb_prev_ins_is_write(dsb,
DSB_OPCODE_MMIO_WRITE << DSB_OPCODE_SHIFT |
DSB_BYTE_EN << DSB_BYTE_EN_SHIFT,
reg);
}
static bool intel_dsb_prev_ins_is_indexed_write(struct intel_dsb *dsb, i915_reg_t reg)
{
return intel_dsb_prev_ins_is_write(dsb,
@ -273,7 +264,7 @@ static bool intel_dsb_prev_ins_is_indexed_write(struct intel_dsb *dsb, i915_reg_
}
/**
* intel_dsb_reg_write_indexed() - Emit register wriite to the DSB context
* intel_dsb_reg_write_indexed() - Emit indexed register write to the DSB context
* @dsb: DSB context
* @reg: register address.
* @val: value.
@ -304,44 +295,23 @@ void intel_dsb_reg_write_indexed(struct intel_dsb *dsb,
* we are writing odd no of dwords, Zeros will be added in the end for
* padding.
*/
if (!intel_dsb_prev_ins_is_mmio_write(dsb, reg) &&
!intel_dsb_prev_ins_is_indexed_write(dsb, reg)) {
intel_dsb_emit(dsb, val,
(DSB_OPCODE_MMIO_WRITE << DSB_OPCODE_SHIFT) |
(DSB_BYTE_EN << DSB_BYTE_EN_SHIFT) |
if (!intel_dsb_prev_ins_is_indexed_write(dsb, reg))
intel_dsb_emit(dsb, 0, /* count */
(DSB_OPCODE_INDEXED_WRITE << DSB_OPCODE_SHIFT) |
i915_mmio_reg_offset(reg));
} else {
if (!assert_dsb_has_room(dsb))
return;
/* convert to indexed write? */
if (intel_dsb_prev_ins_is_mmio_write(dsb, reg)) {
u32 prev_val = dsb->ins[0];
if (!assert_dsb_has_room(dsb))
return;
dsb->ins[0] = 1; /* count */
dsb->ins[1] = (DSB_OPCODE_INDEXED_WRITE << DSB_OPCODE_SHIFT) |
i915_mmio_reg_offset(reg);
/* Update the count */
dsb->ins[0]++;
intel_dsb_buffer_write(&dsb->dsb_buf, dsb->ins_start_offset + 0,
dsb->ins[0]);
intel_dsb_buffer_write(&dsb->dsb_buf, dsb->ins_start_offset + 0,
dsb->ins[0]);
intel_dsb_buffer_write(&dsb->dsb_buf, dsb->ins_start_offset + 1,
dsb->ins[1]);
intel_dsb_buffer_write(&dsb->dsb_buf, dsb->ins_start_offset + 2,
prev_val);
dsb->free_pos++;
}
intel_dsb_buffer_write(&dsb->dsb_buf, dsb->free_pos++, val);
/* Update the count */
dsb->ins[0]++;
intel_dsb_buffer_write(&dsb->dsb_buf, dsb->ins_start_offset + 0,
dsb->ins[0]);
/* if number of data words is odd, then the last dword should be 0.*/
if (dsb->free_pos & 0x1)
intel_dsb_buffer_write(&dsb->dsb_buf, dsb->free_pos, 0);
}
intel_dsb_buffer_write(&dsb->dsb_buf, dsb->free_pos++, val);
/* if number of data words is odd, then the last dword should be 0.*/
if (dsb->free_pos & 0x1)
intel_dsb_buffer_write(&dsb->dsb_buf, dsb->free_pos, 0);
}
void intel_dsb_reg_write(struct intel_dsb *dsb,

@ -745,6 +745,23 @@ void intel_dsi_log_params(struct intel_dsi *intel_dsi)
str_enabled_disabled(!(intel_dsi->video_frmt_cfg_bits & DISABLE_VIDEO_BTA)));
}
static enum mipi_dsi_pixel_format vbt_to_dsi_pixel_format(unsigned int format)
{
switch (format) {
case PIXEL_FORMAT_RGB888:
return MIPI_DSI_FMT_RGB888;
case PIXEL_FORMAT_RGB666_LOOSELY_PACKED:
return MIPI_DSI_FMT_RGB666;
case PIXEL_FORMAT_RGB666:
return MIPI_DSI_FMT_RGB666_PACKED;
case PIXEL_FORMAT_RGB565:
return MIPI_DSI_FMT_RGB565;
default:
MISSING_CASE(format);
return MIPI_DSI_FMT_RGB666;
}
}
bool intel_dsi_vbt_init(struct intel_dsi *intel_dsi, u16 panel_id)
{
struct drm_device *dev = intel_dsi->base.base.dev;
@ -762,8 +779,7 @@ bool intel_dsi_vbt_init(struct intel_dsi *intel_dsi, u16 panel_id)
intel_dsi->clock_stop = mipi_config->enable_clk_stop ? 1 : 0;
intel_dsi->lane_count = mipi_config->lane_cnt + 1;
intel_dsi->pixel_format =
pixel_format_from_register_bits(
mipi_config->videomode_color_format << 7);
vbt_to_dsi_pixel_format(mipi_config->videomode_color_format);
intel_dsi->dual_link = mipi_config->dual_link;
intel_dsi->pixel_overlap = mipi_config->pixel_overlap;

@ -318,6 +318,7 @@ static void intel_dvo_pre_enable(struct intel_atomic_state *state,
static enum drm_connector_status
intel_dvo_detect(struct drm_connector *_connector, bool force)
{
struct intel_display *display = to_intel_display(_connector->dev);
struct intel_connector *connector = to_intel_connector(_connector);
struct drm_i915_private *i915 = to_i915(connector->base.dev);
struct intel_dvo *intel_dvo = intel_attached_dvo(connector);
@ -325,10 +326,10 @@ intel_dvo_detect(struct drm_connector *_connector, bool force)
drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s]\n",
connector->base.base.id, connector->base.name);
if (!intel_display_device_enabled(i915))
if (!intel_display_device_enabled(display))
return connector_status_disconnected;
if (!intel_display_driver_check_access(i915))
if (!intel_display_driver_check_access(display))
return connector->base.status;
return intel_dvo->dev.dev_ops->detect(&intel_dvo->dev);
@ -336,11 +337,11 @@ intel_dvo_detect(struct drm_connector *_connector, bool force)
static int intel_dvo_get_modes(struct drm_connector *_connector)
{
struct intel_display *display = to_intel_display(_connector->dev);
struct intel_connector *connector = to_intel_connector(_connector);
struct drm_i915_private *i915 = to_i915(connector->base.dev);
int num_modes;
if (!intel_display_driver_check_access(i915))
if (!intel_display_driver_check_access(display))
return drm_edid_connector_add_modes(&connector->base);
/*

@ -496,14 +496,13 @@ static int
gmbus_xfer_read(struct intel_display *display, struct i2c_msg *msg,
u32 gmbus0_reg, u32 gmbus1_index)
{
struct drm_i915_private *i915 = to_i915(display->drm);
u8 *buf = msg->buf;
unsigned int rx_size = msg->len;
unsigned int len;
int ret;
do {
if (HAS_GMBUS_BURST_READ(i915))
if (HAS_GMBUS_BURST_READ(display))
len = min(rx_size, INTEL_GMBUS_BURST_READ_MAX_LEN);
else
len = min(rx_size, gmbus_max_xfer_size(display));

@ -31,27 +31,33 @@
#define KEY_LOAD_TRIES 5
#define HDCP2_LC_RETRY_CNT 3
/* WA: 16022217614 */
static void
intel_hdcp_disable_hdcp_line_rekeying(struct intel_encoder *encoder,
struct intel_hdcp *hdcp)
intel_hdcp_adjust_hdcp_line_rekeying(struct intel_encoder *encoder,
struct intel_hdcp *hdcp,
bool enable)
{
struct intel_display *display = to_intel_display(encoder);
i915_reg_t rekey_reg;
u32 rekey_bit = 0;
/* Here we assume HDMI is in TMDS mode of operation */
if (encoder->type != INTEL_OUTPUT_HDMI)
return;
if (DISPLAY_VER(display) >= 14) {
if (IS_DISPLAY_VERx100_STEP(display, 1400, STEP_D0, STEP_FOREVER))
intel_de_rmw(display, MTL_CHICKEN_TRANS(hdcp->cpu_transcoder),
0, HDCP_LINE_REKEY_DISABLE);
else if (IS_DISPLAY_VERx100_STEP(display, 1401, STEP_B0, STEP_FOREVER) ||
IS_DISPLAY_VERx100_STEP(display, 2000, STEP_B0, STEP_FOREVER))
intel_de_rmw(display,
TRANS_DDI_FUNC_CTL(display, hdcp->cpu_transcoder),
0, TRANS_DDI_HDCP_LINE_REKEY_DISABLE);
if (DISPLAY_VER(display) >= 30) {
rekey_reg = TRANS_DDI_FUNC_CTL(display, hdcp->cpu_transcoder);
rekey_bit = XE3_TRANS_DDI_HDCP_LINE_REKEY_DISABLE;
} else if (IS_DISPLAY_VERx100_STEP(display, 1401, STEP_B0, STEP_FOREVER) ||
IS_DISPLAY_VERx100_STEP(display, 2000, STEP_B0, STEP_FOREVER)) {
rekey_reg = TRANS_DDI_FUNC_CTL(display, hdcp->cpu_transcoder);
rekey_bit = TRANS_DDI_HDCP_LINE_REKEY_DISABLE;
} else if (IS_DISPLAY_VERx100_STEP(display, 1400, STEP_D0, STEP_FOREVER)) {
rekey_reg = CHICKEN_TRANS(display, hdcp->cpu_transcoder);
rekey_bit = HDCP_LINE_REKEY_DISABLE;
}
if (rekey_bit)
intel_de_rmw(display, rekey_reg, rekey_bit, enable ? 0 : rekey_bit);
}
static int intel_conn_to_vcpi(struct intel_atomic_state *state,
@ -343,7 +349,7 @@ static bool hdcp_key_loadable(struct intel_display *display)
/* PG1 (power well #1) needs to be enabled */
with_intel_runtime_pm(&i915->runtime_pm, wakeref)
enabled = intel_display_power_well_is_enabled(i915, id);
enabled = intel_display_power_well_is_enabled(display, id);
/*
* Another req for hdcp key loadability is enabled state of pll for
@ -1048,6 +1054,8 @@ static int intel_hdcp1_enable(struct intel_connector *connector)
return ret;
}
intel_hdcp_adjust_hdcp_line_rekeying(connector->encoder, hdcp, true);
/* Incase of authentication failures, HDCP spec expects reauth. */
for (i = 0; i < tries; i++) {
ret = intel_hdcp_auth(connector);
@ -2069,7 +2077,7 @@ static int _intel_hdcp2_enable(struct intel_atomic_state *state,
connector->base.base.id, connector->base.name,
hdcp->content_type);
intel_hdcp_disable_hdcp_line_rekeying(connector->encoder, hdcp);
intel_hdcp_adjust_hdcp_line_rekeying(connector->encoder, hdcp, false);
ret = hdcp2_authenticate_and_encrypt(state, connector);
if (ret) {

@ -1600,14 +1600,12 @@ static
bool intel_hdmi_hdcp_check_link(struct intel_digital_port *dig_port,
struct intel_connector *connector)
{
struct intel_display *display = to_intel_display(dig_port);
int retry;
for (retry = 0; retry < 3; retry++)
if (intel_hdmi_hdcp_check_link_once(dig_port, connector))
return true;
drm_err(display->drm, "Link check failed\n");
return false;
}
@ -2556,10 +2554,10 @@ intel_hdmi_detect(struct drm_connector *connector, bool force)
drm_dbg_kms(display->drm, "[CONNECTOR:%d:%s]\n",
connector->base.id, connector->name);
if (!intel_display_device_enabled(dev_priv))
if (!intel_display_device_enabled(display))
return connector_status_disconnected;
if (!intel_display_driver_check_access(dev_priv))
if (!intel_display_driver_check_access(display))
return connector->status;
wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS);
@ -2586,12 +2584,11 @@ static void
intel_hdmi_force(struct drm_connector *connector)
{
struct intel_display *display = to_intel_display(connector->dev);
struct drm_i915_private *i915 = to_i915(connector->dev);
drm_dbg_kms(display->drm, "[CONNECTOR:%d:%s]\n",
connector->base.id, connector->name);
if (!intel_display_driver_check_access(i915))
if (!intel_display_driver_check_access(display))
return;
intel_hdmi_unset_edid(connector);

@ -813,8 +813,10 @@ static void i915_hpd_poll_init_work(struct work_struct *work)
*/
void intel_hpd_poll_enable(struct drm_i915_private *dev_priv)
{
struct intel_display *display = &dev_priv->display;
if (!HAS_DISPLAY(dev_priv) ||
!intel_display_device_enabled(dev_priv))
!intel_display_device_enabled(display))
return;
WRITE_ONCE(dev_priv->display.hotplug.poll_enabled, true);

@ -1457,7 +1457,11 @@ void intel_hpd_enable_detection(struct intel_encoder *encoder)
void intel_hpd_irq_setup(struct drm_i915_private *i915)
{
if (i915->display.irq.display_irqs_enabled && i915->display.funcs.hotplug)
if ((IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) &&
!i915->display.irq.vlv_display_irqs_enabled)
return;
if (i915->display.funcs.hotplug)
i915->display.funcs.hotplug->hpd_irq_setup(i915);
}

@ -57,12 +57,7 @@
/* Private structure for the integrated LVDS support */
struct intel_lvds_pps {
/* 100us units */
int t1_t2;
int t3;
int t4;
int t5;
int tx;
struct intel_pps_delays delays;
int divider;
@ -168,12 +163,12 @@ static void intel_lvds_pps_get_hw_state(struct drm_i915_private *dev_priv,
val = intel_de_read(dev_priv, PP_ON_DELAYS(dev_priv, 0));
pps->port = REG_FIELD_GET(PANEL_PORT_SELECT_MASK, val);
pps->t1_t2 = REG_FIELD_GET(PANEL_POWER_UP_DELAY_MASK, val);
pps->t5 = REG_FIELD_GET(PANEL_LIGHT_ON_DELAY_MASK, val);
pps->delays.power_up = REG_FIELD_GET(PANEL_POWER_UP_DELAY_MASK, val);
pps->delays.backlight_on = REG_FIELD_GET(PANEL_LIGHT_ON_DELAY_MASK, val);
val = intel_de_read(dev_priv, PP_OFF_DELAYS(dev_priv, 0));
pps->t3 = REG_FIELD_GET(PANEL_POWER_DOWN_DELAY_MASK, val);
pps->tx = REG_FIELD_GET(PANEL_LIGHT_OFF_DELAY_MASK, val);
pps->delays.power_down = REG_FIELD_GET(PANEL_POWER_DOWN_DELAY_MASK, val);
pps->delays.backlight_off = REG_FIELD_GET(PANEL_LIGHT_OFF_DELAY_MASK, val);
val = intel_de_read(dev_priv, PP_DIVISOR(dev_priv, 0));
pps->divider = REG_FIELD_GET(PP_REFERENCE_DIVIDER_MASK, val);
@ -186,25 +181,30 @@ static void intel_lvds_pps_get_hw_state(struct drm_i915_private *dev_priv,
if (val)
val--;
/* Convert from 100ms to 100us units */
pps->t4 = val * 1000;
pps->delays.power_cycle = val * 1000;
if (DISPLAY_VER(dev_priv) < 5 &&
pps->t1_t2 == 0 && pps->t5 == 0 && pps->t3 == 0 && pps->tx == 0) {
pps->delays.power_up == 0 &&
pps->delays.backlight_on == 0 &&
pps->delays.power_down == 0 &&
pps->delays.backlight_off == 0) {
drm_dbg_kms(&dev_priv->drm,
"Panel power timings uninitialized, "
"setting defaults\n");
/* Set T2 to 40ms and T5 to 200ms in 100 usec units */
pps->t1_t2 = 40 * 10;
pps->t5 = 200 * 10;
pps->delays.power_up = 40 * 10;
pps->delays.backlight_on = 200 * 10;
/* Set T3 to 35ms and Tx to 200ms in 100 usec units */
pps->t3 = 35 * 10;
pps->tx = 200 * 10;
pps->delays.power_down = 35 * 10;
pps->delays.backlight_off = 200 * 10;
}
drm_dbg(&dev_priv->drm, "LVDS PPS:t1+t2 %d t3 %d t4 %d t5 %d tx %d "
drm_dbg(&dev_priv->drm, "LVDS PPS:power_up %d power_down %d power_cycle %d backlight_on %d backlight_off %d "
"divider %d port %d powerdown_on_reset %d\n",
pps->t1_t2, pps->t3, pps->t4, pps->t5, pps->tx,
pps->divider, pps->port, pps->powerdown_on_reset);
pps->delays.power_up, pps->delays.power_down,
pps->delays.power_cycle, pps->delays.backlight_on,
pps->delays.backlight_off, pps->divider,
pps->port, pps->powerdown_on_reset);
}
static void intel_lvds_pps_init_hw(struct drm_i915_private *dev_priv,
@ -221,16 +221,17 @@ static void intel_lvds_pps_init_hw(struct drm_i915_private *dev_priv,
intel_de_write(dev_priv, PP_ON_DELAYS(dev_priv, 0),
REG_FIELD_PREP(PANEL_PORT_SELECT_MASK, pps->port) |
REG_FIELD_PREP(PANEL_POWER_UP_DELAY_MASK, pps->t1_t2) |
REG_FIELD_PREP(PANEL_LIGHT_ON_DELAY_MASK, pps->t5));
REG_FIELD_PREP(PANEL_POWER_UP_DELAY_MASK, pps->delays.power_up) |
REG_FIELD_PREP(PANEL_LIGHT_ON_DELAY_MASK, pps->delays.backlight_on));
intel_de_write(dev_priv, PP_OFF_DELAYS(dev_priv, 0),
REG_FIELD_PREP(PANEL_POWER_DOWN_DELAY_MASK, pps->t3) |
REG_FIELD_PREP(PANEL_LIGHT_OFF_DELAY_MASK, pps->tx));
REG_FIELD_PREP(PANEL_POWER_DOWN_DELAY_MASK, pps->delays.power_down) |
REG_FIELD_PREP(PANEL_LIGHT_OFF_DELAY_MASK, pps->delays.backlight_off));
intel_de_write(dev_priv, PP_DIVISOR(dev_priv, 0),
REG_FIELD_PREP(PP_REFERENCE_DIVIDER_MASK, pps->divider) |
REG_FIELD_PREP(PANEL_POWER_CYCLE_DELAY_MASK, DIV_ROUND_UP(pps->t4, 1000) + 1));
REG_FIELD_PREP(PANEL_POWER_CYCLE_DELAY_MASK,
DIV_ROUND_UP(pps->delays.power_cycle, 1000) + 1));
}
static void intel_pre_enable_lvds(struct intel_atomic_state *state,

@ -1024,5 +1024,5 @@ void intel_modeset_setup_hw_state(struct drm_i915_private *i915,
intel_display_power_put(i915, POWER_DOMAIN_INIT, wakeref);
intel_power_domains_sanitize_state(i915);
intel_power_domains_sanitize_state(display);
}

@ -183,7 +183,7 @@ struct overlay_registers {
};
struct intel_overlay {
struct drm_i915_private *i915;
struct intel_display *display;
struct intel_context *context;
struct intel_crtc *crtc;
struct i915_vma *vma;
@ -205,17 +205,17 @@ struct intel_overlay {
void (*flip_complete)(struct intel_overlay *ovl);
};
static void i830_overlay_clock_gating(struct drm_i915_private *dev_priv,
static void i830_overlay_clock_gating(struct intel_display *display,
bool enable)
{
struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev);
struct pci_dev *pdev = to_pci_dev(display->drm->dev);
u8 val;
/* WA_OVERLAY_CLKGATE:alm */
if (enable)
intel_de_write(dev_priv, DSPCLK_GATE_D(dev_priv), 0);
intel_de_write(display, DSPCLK_GATE_D(display), 0);
else
intel_de_write(dev_priv, DSPCLK_GATE_D(dev_priv),
intel_de_write(display, DSPCLK_GATE_D(display),
OVRUNIT_CLOCK_GATE_DISABLE);
/* WA_DISABLE_L2CACHE_CLOCK_GATING:alm */
@ -253,11 +253,11 @@ alloc_request(struct intel_overlay *overlay, void (*fn)(struct intel_overlay *))
/* overlay needs to be disable in OCMD reg */
static int intel_overlay_on(struct intel_overlay *overlay)
{
struct drm_i915_private *dev_priv = overlay->i915;
struct intel_display *display = overlay->display;
struct i915_request *rq;
u32 *cs;
drm_WARN_ON(&dev_priv->drm, overlay->active);
drm_WARN_ON(display->drm, overlay->active);
rq = alloc_request(overlay, NULL);
if (IS_ERR(rq))
@ -271,8 +271,8 @@ static int intel_overlay_on(struct intel_overlay *overlay)
overlay->active = true;
if (IS_I830(dev_priv))
i830_overlay_clock_gating(dev_priv, false);
if (display->platform.i830)
i830_overlay_clock_gating(display, false);
*cs++ = MI_OVERLAY_FLIP | MI_OVERLAY_ON;
*cs++ = overlay->flip_addr | OFC_UPDATE;
@ -288,10 +288,12 @@ static int intel_overlay_on(struct intel_overlay *overlay)
static void intel_overlay_flip_prepare(struct intel_overlay *overlay,
struct i915_vma *vma)
{
struct intel_display *display = overlay->display;
struct drm_i915_private *i915 = to_i915(display->drm);
enum pipe pipe = overlay->crtc->pipe;
struct intel_frontbuffer *frontbuffer = NULL;
drm_WARN_ON(&overlay->i915->drm, overlay->old_vma);
drm_WARN_ON(display->drm, overlay->old_vma);
if (vma)
frontbuffer = intel_frontbuffer_get(intel_bo_to_drm_bo(vma->obj));
@ -303,8 +305,7 @@ static void intel_overlay_flip_prepare(struct intel_overlay *overlay,
intel_frontbuffer_put(overlay->frontbuffer);
overlay->frontbuffer = frontbuffer;
intel_frontbuffer_flip_prepare(overlay->i915,
INTEL_FRONTBUFFER_OVERLAY(pipe));
intel_frontbuffer_flip_prepare(i915, INTEL_FRONTBUFFER_OVERLAY(pipe));
overlay->old_vma = overlay->vma;
if (vma)
@ -318,20 +319,20 @@ static int intel_overlay_continue(struct intel_overlay *overlay,
struct i915_vma *vma,
bool load_polyphase_filter)
{
struct drm_i915_private *dev_priv = overlay->i915;
struct intel_display *display = overlay->display;
struct i915_request *rq;
u32 flip_addr = overlay->flip_addr;
u32 tmp, *cs;
drm_WARN_ON(&dev_priv->drm, !overlay->active);
drm_WARN_ON(display->drm, !overlay->active);
if (load_polyphase_filter)
flip_addr |= OFC_UPDATE;
/* check for underruns */
tmp = intel_de_read(dev_priv, DOVSTA);
tmp = intel_de_read(display, DOVSTA);
if (tmp & (1 << 17))
drm_dbg(&dev_priv->drm, "overlay underrun, DOVSTA: %x\n", tmp);
drm_dbg(display->drm, "overlay underrun, DOVSTA: %x\n", tmp);
rq = alloc_request(overlay, NULL);
if (IS_ERR(rq))
@ -355,14 +356,15 @@ static int intel_overlay_continue(struct intel_overlay *overlay,
static void intel_overlay_release_old_vma(struct intel_overlay *overlay)
{
struct intel_display *display = overlay->display;
struct drm_i915_private *i915 = to_i915(display->drm);
struct i915_vma *vma;
vma = fetch_and_zero(&overlay->old_vma);
if (drm_WARN_ON(&overlay->i915->drm, !vma))
if (drm_WARN_ON(display->drm, !vma))
return;
intel_frontbuffer_flip_complete(overlay->i915,
INTEL_FRONTBUFFER_OVERLAY(overlay->crtc->pipe));
intel_frontbuffer_flip_complete(i915, INTEL_FRONTBUFFER_OVERLAY(overlay->crtc->pipe));
i915_vma_unpin(vma);
i915_vma_put(vma);
@ -376,7 +378,7 @@ intel_overlay_release_old_vid_tail(struct intel_overlay *overlay)
static void intel_overlay_off_tail(struct intel_overlay *overlay)
{
struct drm_i915_private *dev_priv = overlay->i915;
struct intel_display *display = overlay->display;
intel_overlay_release_old_vma(overlay);
@ -384,8 +386,8 @@ static void intel_overlay_off_tail(struct intel_overlay *overlay)
overlay->crtc = NULL;
overlay->active = false;
if (IS_I830(dev_priv))
i830_overlay_clock_gating(dev_priv, true);
if (display->platform.i830)
i830_overlay_clock_gating(display, true);
}
static void intel_overlay_last_flip_retire(struct i915_active *active)
@ -400,10 +402,11 @@ static void intel_overlay_last_flip_retire(struct i915_active *active)
/* overlay needs to be disabled in OCMD reg */
static int intel_overlay_off(struct intel_overlay *overlay)
{
struct intel_display *display = overlay->display;
struct i915_request *rq;
u32 *cs, flip_addr = overlay->flip_addr;
drm_WARN_ON(&overlay->i915->drm, !overlay->active);
drm_WARN_ON(display->drm, !overlay->active);
/* According to intel docs the overlay hw may hang (when switching
* off) without loading the filter coeffs. It is however unclear whether
@ -452,7 +455,7 @@ static int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay)
*/
static int intel_overlay_release_old_vid(struct intel_overlay *overlay)
{
struct drm_i915_private *dev_priv = overlay->i915;
struct intel_display *display = overlay->display;
struct i915_request *rq;
u32 *cs;
@ -463,7 +466,7 @@ static int intel_overlay_release_old_vid(struct intel_overlay *overlay)
if (!overlay->old_vma)
return 0;
if (!(intel_de_read(dev_priv, GEN2_ISR) & I915_OVERLAY_PLANE_FLIP_PENDING_INTERRUPT)) {
if (!(intel_de_read(display, GEN2_ISR) & I915_OVERLAY_PLANE_FLIP_PENDING_INTERRUPT)) {
intel_overlay_release_old_vid_tail(overlay);
return 0;
}
@ -487,9 +490,9 @@ static int intel_overlay_release_old_vid(struct intel_overlay *overlay)
return i915_active_wait(&overlay->last_flip);
}
void intel_overlay_reset(struct drm_i915_private *dev_priv)
void intel_overlay_reset(struct intel_display *display)
{
struct intel_overlay *overlay = dev_priv->display.overlay;
struct intel_overlay *overlay = display->overlay;
if (!overlay)
return;
@ -550,11 +553,11 @@ static int uv_vsubsampling(u32 format)
}
}
static u32 calc_swidthsw(struct drm_i915_private *dev_priv, u32 offset, u32 width)
static u32 calc_swidthsw(struct intel_display *display, u32 offset, u32 width)
{
u32 sw;
if (DISPLAY_VER(dev_priv) == 2)
if (DISPLAY_VER(display) == 2)
sw = ALIGN((offset & 31) + width, 32);
else
sw = ALIGN((offset & 63) + width, 64);
@ -789,16 +792,17 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
struct drm_i915_gem_object *new_bo,
struct drm_intel_overlay_put_image *params)
{
struct intel_display *display = overlay->display;
struct drm_i915_private *dev_priv = to_i915(display->drm);
struct overlay_registers __iomem *regs = overlay->regs;
struct drm_i915_private *dev_priv = overlay->i915;
u32 swidth, swidthsw, sheight, ostride;
enum pipe pipe = overlay->crtc->pipe;
bool scale_changed = false;
struct i915_vma *vma;
int ret, tmp_width;
drm_WARN_ON(&dev_priv->drm,
!drm_modeset_is_locked(&dev_priv->drm.mode_config.connection_mutex));
drm_WARN_ON(display->drm,
!drm_modeset_is_locked(&display->drm->mode_config.connection_mutex));
ret = intel_overlay_release_old_vid(overlay);
if (ret != 0)
@ -824,7 +828,7 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
oconfig |= OCONF_CC_OUT_8BIT;
if (crtc_state->gamma_enable)
oconfig |= OCONF_GAMMA2_ENABLE;
if (DISPLAY_VER(dev_priv) == 4)
if (DISPLAY_VER(display) == 4)
oconfig |= OCONF_CSC_MODE_BT709;
oconfig |= pipe == 0 ?
OCONF_PIPE_A : OCONF_PIPE_B;
@ -845,7 +849,7 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
tmp_width = params->src_width;
swidth = params->src_width;
swidthsw = calc_swidthsw(dev_priv, params->offset_Y, tmp_width);
swidthsw = calc_swidthsw(display, params->offset_Y, tmp_width);
sheight = params->src_height;
iowrite32(i915_ggtt_offset(vma) + params->offset_Y, &regs->OBUF_0Y);
ostride = params->stride_Y;
@ -858,9 +862,9 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
swidth |= (params->src_width / uv_hscale) << 16;
sheight |= (params->src_height / uv_vscale) << 16;
tmp_U = calc_swidthsw(dev_priv, params->offset_U,
tmp_U = calc_swidthsw(display, params->offset_U,
params->src_width / uv_hscale);
tmp_V = calc_swidthsw(dev_priv, params->offset_V,
tmp_V = calc_swidthsw(display, params->offset_V,
params->src_width / uv_hscale);
swidthsw |= max(tmp_U, tmp_V) << 16;
@ -899,11 +903,11 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
int intel_overlay_switch_off(struct intel_overlay *overlay)
{
struct drm_i915_private *dev_priv = overlay->i915;
struct intel_display *display = overlay->display;
int ret;
drm_WARN_ON(&dev_priv->drm,
!drm_modeset_is_locked(&dev_priv->drm.mode_config.connection_mutex));
drm_WARN_ON(display->drm,
!drm_modeset_is_locked(&display->drm->mode_config.connection_mutex));
ret = intel_overlay_recover_from_interrupt(overlay);
if (ret != 0)
@ -936,26 +940,24 @@ static int check_overlay_possible_on_crtc(struct intel_overlay *overlay,
static void update_pfit_vscale_ratio(struct intel_overlay *overlay)
{
struct drm_i915_private *dev_priv = overlay->i915;
struct intel_display *display = overlay->display;
u32 ratio;
/* XXX: This is not the same logic as in the xorg driver, but more in
* line with the intel documentation for the i965
*/
if (DISPLAY_VER(dev_priv) >= 4) {
u32 tmp = intel_de_read(dev_priv, PFIT_PGM_RATIOS(dev_priv));
if (DISPLAY_VER(display) >= 4) {
u32 tmp = intel_de_read(display, PFIT_PGM_RATIOS(display));
/* on i965 use the PGM reg to read out the autoscaler values */
ratio = REG_FIELD_GET(PFIT_VERT_SCALE_MASK_965, tmp);
} else {
u32 tmp;
if (intel_de_read(dev_priv, PFIT_CONTROL(dev_priv)) & PFIT_VERT_AUTO_SCALE)
tmp = intel_de_read(dev_priv,
PFIT_AUTO_RATIOS(dev_priv));
if (intel_de_read(display, PFIT_CONTROL(display)) & PFIT_VERT_AUTO_SCALE)
tmp = intel_de_read(display, PFIT_AUTO_RATIOS(display));
else
tmp = intel_de_read(dev_priv,
PFIT_PGM_RATIOS(dev_priv));
tmp = intel_de_read(display, PFIT_PGM_RATIOS(display));
ratio = REG_FIELD_GET(PFIT_VERT_SCALE_MASK, tmp);
}
@ -1000,7 +1002,7 @@ static int check_overlay_scaling(struct drm_intel_overlay_put_image *rec)
return 0;
}
static int check_overlay_src(struct drm_i915_private *dev_priv,
static int check_overlay_src(struct intel_display *display,
struct drm_intel_overlay_put_image *rec,
struct drm_i915_gem_object *new_bo)
{
@ -1011,7 +1013,7 @@ static int check_overlay_src(struct drm_i915_private *dev_priv,
u32 tmp;
/* check src dimensions */
if (IS_I845G(dev_priv) || IS_I830(dev_priv)) {
if (display->platform.i845g || display->platform.i830) {
if (rec->src_height > IMAGE_MAX_HEIGHT_LEGACY ||
rec->src_width > IMAGE_MAX_WIDTH_LEGACY)
return -EINVAL;
@ -1063,14 +1065,14 @@ static int check_overlay_src(struct drm_i915_private *dev_priv,
return -EINVAL;
/* stride checking */
if (IS_I830(dev_priv) || IS_I845G(dev_priv))
if (display->platform.i830 || display->platform.i845g)
stride_mask = 255;
else
stride_mask = 63;
if (rec->stride_Y & stride_mask || rec->stride_UV & stride_mask)
return -EINVAL;
if (DISPLAY_VER(dev_priv) == 4 && rec->stride_Y < 512)
if (DISPLAY_VER(display) == 4 && rec->stride_Y < 512)
return -EINVAL;
tmp = (rec->flags & I915_OVERLAY_TYPE_MASK) == I915_OVERLAY_YUV_PLANAR ?
@ -1114,17 +1116,17 @@ static int check_overlay_src(struct drm_i915_private *dev_priv,
int intel_overlay_put_image_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
struct intel_display *display = to_intel_display(dev);
struct drm_intel_overlay_put_image *params = data;
struct drm_i915_private *dev_priv = to_i915(dev);
struct intel_overlay *overlay;
struct drm_crtc *drmmode_crtc;
struct intel_crtc *crtc;
struct drm_i915_gem_object *new_bo;
int ret;
overlay = dev_priv->display.overlay;
overlay = display->overlay;
if (!overlay) {
drm_dbg(&dev_priv->drm, "userspace bug: no overlay\n");
drm_dbg(display->drm, "userspace bug: no overlay\n");
return -ENODEV;
}
@ -1148,7 +1150,7 @@ int intel_overlay_put_image_ioctl(struct drm_device *dev, void *data,
drm_modeset_lock_all(dev);
if (i915_gem_object_is_tiled(new_bo)) {
drm_dbg_kms(&dev_priv->drm,
drm_dbg_kms(display->drm,
"buffer used for overlay image can not be tiled\n");
ret = -EINVAL;
goto out_unlock;
@ -1197,7 +1199,7 @@ int intel_overlay_put_image_ioctl(struct drm_device *dev, void *data,
goto out_unlock;
}
ret = check_overlay_src(dev_priv, params, new_bo);
ret = check_overlay_src(display, params, new_bo);
if (ret != 0)
goto out_unlock;
@ -1277,14 +1279,14 @@ static int check_gamma(struct drm_intel_overlay_attrs *attrs)
int intel_overlay_attrs_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
struct intel_display *display = to_intel_display(dev);
struct drm_intel_overlay_attrs *attrs = data;
struct drm_i915_private *dev_priv = to_i915(dev);
struct intel_overlay *overlay;
int ret;
overlay = dev_priv->display.overlay;
overlay = display->overlay;
if (!overlay) {
drm_dbg(&dev_priv->drm, "userspace bug: no overlay\n");
drm_dbg(display->drm, "userspace bug: no overlay\n");
return -ENODEV;
}
@ -1297,13 +1299,13 @@ int intel_overlay_attrs_ioctl(struct drm_device *dev, void *data,
attrs->contrast = overlay->contrast;
attrs->saturation = overlay->saturation;
if (DISPLAY_VER(dev_priv) != 2) {
attrs->gamma0 = intel_de_read(dev_priv, OGAMC0);
attrs->gamma1 = intel_de_read(dev_priv, OGAMC1);
attrs->gamma2 = intel_de_read(dev_priv, OGAMC2);
attrs->gamma3 = intel_de_read(dev_priv, OGAMC3);
attrs->gamma4 = intel_de_read(dev_priv, OGAMC4);
attrs->gamma5 = intel_de_read(dev_priv, OGAMC5);
if (DISPLAY_VER(display) != 2) {
attrs->gamma0 = intel_de_read(display, OGAMC0);
attrs->gamma1 = intel_de_read(display, OGAMC1);
attrs->gamma2 = intel_de_read(display, OGAMC2);
attrs->gamma3 = intel_de_read(display, OGAMC3);
attrs->gamma4 = intel_de_read(display, OGAMC4);
attrs->gamma5 = intel_de_read(display, OGAMC5);
}
} else {
if (attrs->brightness < -128 || attrs->brightness > 127)
@ -1321,7 +1323,7 @@ int intel_overlay_attrs_ioctl(struct drm_device *dev, void *data,
update_reg_attrs(overlay, overlay->regs);
if (attrs->flags & I915_OVERLAY_UPDATE_GAMMA) {
if (DISPLAY_VER(dev_priv) == 2)
if (DISPLAY_VER(display) == 2)
goto out_unlock;
if (overlay->active) {
@ -1333,12 +1335,12 @@ int intel_overlay_attrs_ioctl(struct drm_device *dev, void *data,
if (ret)
goto out_unlock;
intel_de_write(dev_priv, OGAMC0, attrs->gamma0);
intel_de_write(dev_priv, OGAMC1, attrs->gamma1);
intel_de_write(dev_priv, OGAMC2, attrs->gamma2);
intel_de_write(dev_priv, OGAMC3, attrs->gamma3);
intel_de_write(dev_priv, OGAMC4, attrs->gamma4);
intel_de_write(dev_priv, OGAMC5, attrs->gamma5);
intel_de_write(display, OGAMC0, attrs->gamma0);
intel_de_write(display, OGAMC1, attrs->gamma1);
intel_de_write(display, OGAMC2, attrs->gamma2);
intel_de_write(display, OGAMC3, attrs->gamma3);
intel_de_write(display, OGAMC4, attrs->gamma4);
intel_de_write(display, OGAMC5, attrs->gamma5);
}
}
overlay->color_key_enabled = (attrs->flags & I915_OVERLAY_DISABLE_DEST_COLORKEY) == 0;
@ -1352,12 +1354,13 @@ int intel_overlay_attrs_ioctl(struct drm_device *dev, void *data,
static int get_registers(struct intel_overlay *overlay, bool use_phys)
{
struct drm_i915_private *i915 = overlay->i915;
struct intel_display *display = overlay->display;
struct drm_i915_private *i915 = to_i915(display->drm);
struct drm_i915_gem_object *obj = ERR_PTR(-ENODEV);
struct i915_vma *vma;
int err;
if (!IS_METEORLAKE(i915)) /* Wa_22018444074 */
if (!display->platform.meteorlake) /* Wa_22018444074 */
obj = i915_gem_object_create_stolen(i915, PAGE_SIZE);
if (IS_ERR(obj))
obj = i915_gem_object_create_internal(i915, PAGE_SIZE);
@ -1390,13 +1393,14 @@ static int get_registers(struct intel_overlay *overlay, bool use_phys)
return err;
}
void intel_overlay_setup(struct drm_i915_private *dev_priv)
void intel_overlay_setup(struct intel_display *display)
{
struct drm_i915_private *dev_priv = to_i915(display->drm);
struct intel_overlay *overlay;
struct intel_engine_cs *engine;
int ret;
if (!HAS_OVERLAY(dev_priv))
if (!HAS_OVERLAY(display))
return;
engine = to_gt(dev_priv)->engine[RCS0];
@ -1407,7 +1411,7 @@ void intel_overlay_setup(struct drm_i915_private *dev_priv)
if (!overlay)
return;
overlay->i915 = dev_priv;
overlay->display = display;
overlay->context = engine->kernel_context;
overlay->color_key = 0x0101fe;
overlay->color_key_enabled = true;
@ -1418,7 +1422,7 @@ void intel_overlay_setup(struct drm_i915_private *dev_priv)
i915_active_init(&overlay->last_flip,
NULL, intel_overlay_last_flip_retire, 0);
ret = get_registers(overlay, OVERLAY_NEEDS_PHYSICAL(dev_priv));
ret = get_registers(overlay, OVERLAY_NEEDS_PHYSICAL(display));
if (ret)
goto out_free;
@ -1426,19 +1430,24 @@ void intel_overlay_setup(struct drm_i915_private *dev_priv)
update_polyphase_filter(overlay->regs);
update_reg_attrs(overlay, overlay->regs);
dev_priv->display.overlay = overlay;
drm_info(&dev_priv->drm, "Initialized overlay support.\n");
display->overlay = overlay;
drm_info(display->drm, "Initialized overlay support.\n");
return;
out_free:
kfree(overlay);
}
void intel_overlay_cleanup(struct drm_i915_private *dev_priv)
bool intel_overlay_available(struct intel_display *display)
{
return display->overlay;
}
void intel_overlay_cleanup(struct intel_display *display)
{
struct intel_overlay *overlay;
overlay = fetch_and_zero(&dev_priv->display.overlay);
overlay = fetch_and_zero(&display->overlay);
if (!overlay)
return;
@ -1447,7 +1456,7 @@ void intel_overlay_cleanup(struct drm_i915_private *dev_priv)
* Furthermore modesetting teardown happens beforehand so the
* hardware should be off already.
*/
drm_WARN_ON(&dev_priv->drm, overlay->active);
drm_WARN_ON(display->drm, overlay->active);
i915_gem_object_put(overlay->reg_bo);
i915_active_fini(&overlay->last_flip);
@ -1467,8 +1476,7 @@ struct intel_overlay_snapshot {
struct intel_overlay_snapshot *
intel_overlay_snapshot_capture(struct intel_display *display)
{
struct drm_i915_private *dev_priv = to_i915(display->drm);
struct intel_overlay *overlay = dev_priv->display.overlay;
struct intel_overlay *overlay = display->overlay;
struct intel_overlay_snapshot *error;
if (!overlay || !overlay->active)
@ -1478,8 +1486,8 @@ intel_overlay_snapshot_capture(struct intel_display *display)
if (error == NULL)
return NULL;
error->dovsta = intel_de_read(dev_priv, DOVSTA);
error->isr = intel_de_read(dev_priv, GEN2_ISR);
error->dovsta = intel_de_read(display, DOVSTA);
error->isr = intel_de_read(display, GEN2_ISR);
error->base = overlay->flip_addr;
memcpy_fromio(&error->regs, overlay->regs, sizeof(error->regs));

@ -17,19 +17,24 @@ struct intel_overlay;
struct intel_overlay_snapshot;
#ifdef I915
void intel_overlay_setup(struct drm_i915_private *dev_priv);
void intel_overlay_cleanup(struct drm_i915_private *dev_priv);
void intel_overlay_setup(struct intel_display *display);
bool intel_overlay_available(struct intel_display *display);
void intel_overlay_cleanup(struct intel_display *display);
int intel_overlay_switch_off(struct intel_overlay *overlay);
int intel_overlay_put_image_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
int intel_overlay_attrs_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
void intel_overlay_reset(struct drm_i915_private *dev_priv);
void intel_overlay_reset(struct intel_display *display);
#else
static inline void intel_overlay_setup(struct drm_i915_private *dev_priv)
static inline void intel_overlay_setup(struct intel_display *display)
{
}
static inline void intel_overlay_cleanup(struct drm_i915_private *dev_priv)
static inline bool intel_overlay_available(struct intel_display *display)
{
return false;
}
static inline void intel_overlay_cleanup(struct intel_display *display)
{
}
static inline int intel_overlay_switch_off(struct intel_overlay *overlay)
@ -37,7 +42,7 @@ static inline int intel_overlay_switch_off(struct intel_overlay *overlay)
return 0;
}
static inline int intel_overlay_put_image_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
struct drm_file *file_priv)
{
return 0;
}
@ -46,7 +51,7 @@ static inline int intel_overlay_attrs_ioctl(struct drm_device *dev, void *data,
{
return 0;
}
static inline void intel_overlay_reset(struct drm_i915_private *dev_priv)
static inline void intel_overlay_reset(struct intel_display *display)
{
}
#endif

@ -383,12 +383,12 @@ void intel_panel_add_encoder_fixed_mode(struct intel_connector *connector,
enum drm_connector_status
intel_panel_detect(struct drm_connector *connector, bool force)
{
struct drm_i915_private *i915 = to_i915(connector->dev);
struct intel_display *display = to_intel_display(connector->dev);
if (!intel_display_device_enabled(i915))
if (!intel_display_device_enabled(display))
return connector_status_disconnected;
if (!intel_display_driver_check_access(i915))
if (!intel_display_driver_check_access(display))
return connector->status;
return connector_status_connected;

@ -6,6 +6,7 @@
#include "g4x_dp.h"
#include "i915_reg.h"
#include "intel_crt.h"
#include "intel_crt_regs.h"
#include "intel_de.h"
#include "intel_display_types.h"
#include "intel_dpll.h"

@ -108,13 +108,13 @@ void lpt_disable_iclkip(struct drm_i915_private *dev_priv)
intel_de_write(dev_priv, PIXCLK_GATE, PIXCLK_GATE_GATE);
mutex_lock(&dev_priv->sb_lock);
intel_sbi_lock(dev_priv);
temp = intel_sbi_read(dev_priv, SBI_SSCCTL6, SBI_ICLK);
temp |= SBI_SSCCTL_DISABLE;
intel_sbi_write(dev_priv, SBI_SSCCTL6, temp, SBI_ICLK);
mutex_unlock(&dev_priv->sb_lock);
intel_sbi_unlock(dev_priv);
}
struct iclkip_params {
@ -195,7 +195,7 @@ void lpt_program_iclkip(const struct intel_crtc_state *crtc_state)
"iCLKIP clock: found settings for %dKHz refresh rate: auxdiv=%x, divsel=%x, phasedir=%x, phaseinc=%x\n",
clock, p.auxdiv, p.divsel, p.phasedir, p.phaseinc);
mutex_lock(&dev_priv->sb_lock);
intel_sbi_lock(dev_priv);
/* Program SSCDIVINTPHASE6 */
temp = intel_sbi_read(dev_priv, SBI_SSCDIVINTPHASE6, SBI_ICLK);
@ -218,7 +218,7 @@ void lpt_program_iclkip(const struct intel_crtc_state *crtc_state)
temp &= ~SBI_SSCCTL_DISABLE;
intel_sbi_write(dev_priv, SBI_SSCCTL6, temp, SBI_ICLK);
mutex_unlock(&dev_priv->sb_lock);
intel_sbi_unlock(dev_priv);
/* Wait for initialization time */
udelay(24);
@ -236,11 +236,11 @@ int lpt_get_iclkip(struct drm_i915_private *dev_priv)
iclkip_params_init(&p);
mutex_lock(&dev_priv->sb_lock);
intel_sbi_lock(dev_priv);
temp = intel_sbi_read(dev_priv, SBI_SSCCTL6, SBI_ICLK);
if (temp & SBI_SSCCTL_DISABLE) {
mutex_unlock(&dev_priv->sb_lock);
intel_sbi_unlock(dev_priv);
return 0;
}
@ -254,7 +254,7 @@ int lpt_get_iclkip(struct drm_i915_private *dev_priv)
p.auxdiv = (temp & SBI_SSCAUXDIV_FINALDIV2SEL_MASK) >>
SBI_SSCAUXDIV_FINALDIV2SEL_SHIFT;
mutex_unlock(&dev_priv->sb_lock);
intel_sbi_unlock(dev_priv);
p.desired_divisor = (p.divsel + 2) * p.iclk_pi_range + p.phaseinc;
@ -279,7 +279,7 @@ static void lpt_enable_clkout_dp(struct drm_i915_private *dev_priv,
with_fdi, "LP PCH doesn't have FDI\n"))
with_fdi = false;
mutex_lock(&dev_priv->sb_lock);
intel_sbi_lock(dev_priv);
tmp = intel_sbi_read(dev_priv, SBI_SSCCTL, SBI_ICLK);
tmp &= ~SBI_SSCCTL_DISABLE;
@ -302,7 +302,7 @@ static void lpt_enable_clkout_dp(struct drm_i915_private *dev_priv,
tmp |= SBI_GEN0_CFG_BUFFENABLE_DISABLE;
intel_sbi_write(dev_priv, reg, tmp, SBI_ICLK);
mutex_unlock(&dev_priv->sb_lock);
intel_sbi_unlock(dev_priv);
}
/* Sequence to disable CLKOUT_DP */
@ -310,7 +310,7 @@ void lpt_disable_clkout_dp(struct drm_i915_private *dev_priv)
{
u32 reg, tmp;
mutex_lock(&dev_priv->sb_lock);
intel_sbi_lock(dev_priv);
reg = HAS_PCH_LPT_LP(dev_priv) ? SBI_GEN0 : SBI_DBUFF0;
tmp = intel_sbi_read(dev_priv, reg, SBI_ICLK);
@ -328,7 +328,7 @@ void lpt_disable_clkout_dp(struct drm_i915_private *dev_priv)
intel_sbi_write(dev_priv, SBI_SSCCTL, tmp, SBI_ICLK);
}
mutex_unlock(&dev_priv->sb_lock);
intel_sbi_unlock(dev_priv);
}
#define BEND_IDX(steps) ((50 + (steps)) / 5)
@ -374,7 +374,7 @@ static void lpt_bend_clkout_dp(struct drm_i915_private *dev_priv, int steps)
if (drm_WARN_ON(&dev_priv->drm, idx >= ARRAY_SIZE(sscdivintphase)))
return;
mutex_lock(&dev_priv->sb_lock);
intel_sbi_lock(dev_priv);
if (steps % 10 != 0)
tmp = 0xAAAAAAAB;
@ -387,7 +387,7 @@ static void lpt_bend_clkout_dp(struct drm_i915_private *dev_priv, int steps)
tmp |= sscdivintphase[idx];
intel_sbi_write(dev_priv, SBI_SSCDIVINTPHASE, tmp, SBI_ICLK);
mutex_unlock(&dev_priv->sb_lock);
intel_sbi_unlock(dev_priv);
}
#undef BEND_IDX

@ -20,10 +20,10 @@ intel_reuse_initial_plane_obj(struct intel_crtc *this,
struct drm_framebuffer **fb,
struct i915_vma **vma)
{
struct drm_i915_private *i915 = to_i915(this->base.dev);
struct intel_display *display = to_intel_display(this);
struct intel_crtc *crtc;
for_each_intel_crtc(&i915->drm, crtc) {
for_each_intel_crtc(display->drm, crtc) {
struct intel_plane *plane =
to_intel_plane(crtc->base.primary);
const struct intel_plane_state *plane_state =
@ -48,9 +48,10 @@ intel_reuse_initial_plane_obj(struct intel_crtc *this,
}
static bool
initial_plane_phys_lmem(struct drm_i915_private *i915,
initial_plane_phys_lmem(struct intel_display *display,
struct intel_initial_plane_config *plane_config)
{
struct drm_i915_private *i915 = to_i915(display->drm);
gen8_pte_t __iomem *gte = to_gt(i915)->ggtt->gsm;
struct intel_memory_region *mem;
dma_addr_t dma_addr;
@ -63,7 +64,7 @@ initial_plane_phys_lmem(struct drm_i915_private *i915,
pte = ioread64(gte);
if (!(pte & GEN12_GGTT_PTE_LM)) {
drm_err(&i915->drm,
drm_err(display->drm,
"Initial plane programming missing PTE_LM bit\n");
return false;
}
@ -75,7 +76,7 @@ initial_plane_phys_lmem(struct drm_i915_private *i915,
else
mem = i915->mm.stolen_region;
if (!mem) {
drm_dbg_kms(&i915->drm,
drm_dbg_kms(display->drm,
"Initial plane memory region not initialized\n");
return false;
}
@ -85,13 +86,13 @@ initial_plane_phys_lmem(struct drm_i915_private *i915,
* ever be placed in the stolen portion.
*/
if (dma_addr < mem->region.start || dma_addr > mem->region.end) {
drm_err(&i915->drm,
drm_err(display->drm,
"Initial plane programming using invalid range, dma_addr=%pa (%s [%pa-%pa])\n",
&dma_addr, mem->region.name, &mem->region.start, &mem->region.end);
return false;
}
drm_dbg(&i915->drm,
drm_dbg(display->drm,
"Using dma_addr=%pa, based on initial plane programming\n",
&dma_addr);
@ -102,9 +103,10 @@ initial_plane_phys_lmem(struct drm_i915_private *i915,
}
static bool
initial_plane_phys_smem(struct drm_i915_private *i915,
initial_plane_phys_smem(struct intel_display *display,
struct intel_initial_plane_config *plane_config)
{
struct drm_i915_private *i915 = to_i915(display->drm);
struct intel_memory_region *mem;
u32 base;
@ -112,7 +114,7 @@ initial_plane_phys_smem(struct drm_i915_private *i915,
mem = i915->mm.stolen_region;
if (!mem) {
drm_dbg_kms(&i915->drm,
drm_dbg_kms(display->drm,
"Initial plane memory region not initialized\n");
return false;
}
@ -125,19 +127,22 @@ initial_plane_phys_smem(struct drm_i915_private *i915,
}
static bool
initial_plane_phys(struct drm_i915_private *i915,
initial_plane_phys(struct intel_display *display,
struct intel_initial_plane_config *plane_config)
{
struct drm_i915_private *i915 = to_i915(display->drm);
if (IS_DGFX(i915) || HAS_LMEMBAR_SMEM_STOLEN(i915))
return initial_plane_phys_lmem(i915, plane_config);
return initial_plane_phys_lmem(display, plane_config);
else
return initial_plane_phys_smem(i915, plane_config);
return initial_plane_phys_smem(display, plane_config);
}
static struct i915_vma *
initial_plane_vma(struct drm_i915_private *i915,
initial_plane_vma(struct intel_display *display,
struct intel_initial_plane_config *plane_config)
{
struct drm_i915_private *i915 = to_i915(display->drm);
struct intel_memory_region *mem;
struct drm_i915_gem_object *obj;
struct drm_mm_node orig_mm = {};
@ -149,7 +154,7 @@ initial_plane_vma(struct drm_i915_private *i915,
if (plane_config->size == 0)
return NULL;
if (!initial_plane_phys(i915, plane_config))
if (!initial_plane_phys(display, plane_config))
return NULL;
phys_base = plane_config->phys_base;
@ -168,7 +173,7 @@ initial_plane_vma(struct drm_i915_private *i915,
if (IS_ENABLED(CONFIG_FRAMEBUFFER_CONSOLE) &&
mem == i915->mm.stolen_region &&
size * 2 > i915->dsm.usable_size) {
drm_dbg_kms(&i915->drm, "Initial FB size exceeds half of stolen, discarding\n");
drm_dbg_kms(display->drm, "Initial FB size exceeds half of stolen, discarding\n");
return NULL;
}
@ -176,7 +181,7 @@ initial_plane_vma(struct drm_i915_private *i915,
I915_BO_ALLOC_USER |
I915_BO_PREALLOC);
if (IS_ERR(obj)) {
drm_dbg_kms(&i915->drm, "Failed to preallocate initial FB in %s\n",
drm_dbg_kms(display->drm, "Failed to preallocate initial FB in %s\n",
mem->region.name);
return NULL;
}
@ -254,7 +259,7 @@ initial_plane_vma(struct drm_i915_private *i915,
if (drm_mm_node_allocated(&orig_mm))
drm_mm_remove_node(&orig_mm);
drm_dbg_kms(&i915->drm,
drm_dbg_kms(display->drm,
"Initial plane fb bound to 0x%x in the ggtt (original 0x%x)\n",
i915_ggtt_offset(vma), plane_config->base);
@ -271,8 +276,7 @@ static bool
intel_alloc_initial_plane_obj(struct intel_crtc *crtc,
struct intel_initial_plane_config *plane_config)
{
struct drm_device *dev = crtc->base.dev;
struct drm_i915_private *dev_priv = to_i915(dev);
struct intel_display *display = to_intel_display(crtc);
struct drm_mode_fb_cmd2 mode_cmd = {};
struct drm_framebuffer *fb = &plane_config->fb->base;
struct i915_vma *vma;
@ -284,13 +288,13 @@ intel_alloc_initial_plane_obj(struct intel_crtc *crtc,
case I915_FORMAT_MOD_4_TILED:
break;
default:
drm_dbg(&dev_priv->drm,
drm_dbg(display->drm,
"Unsupported modifier for initial FB: 0x%llx\n",
fb->modifier);
return false;
}
vma = initial_plane_vma(dev_priv, plane_config);
vma = initial_plane_vma(display, plane_config);
if (!vma)
return false;
@ -303,7 +307,7 @@ intel_alloc_initial_plane_obj(struct intel_crtc *crtc,
if (intel_framebuffer_init(to_intel_framebuffer(fb),
intel_bo_to_drm_bo(vma->obj), &mode_cmd)) {
drm_dbg_kms(&dev_priv->drm, "intel fb init failed\n");
drm_dbg_kms(display->drm, "intel fb init failed\n");
goto err_vma;
}
@ -410,12 +414,12 @@ static void plane_config_fini(struct intel_initial_plane_config *plane_config)
i915_vma_put(plane_config->vma);
}
void intel_initial_plane_config(struct drm_i915_private *i915)
void intel_initial_plane_config(struct intel_display *display)
{
struct intel_initial_plane_config plane_configs[I915_MAX_PIPES] = {};
struct intel_crtc *crtc;
for_each_intel_crtc(&i915->drm, crtc) {
for_each_intel_crtc(display->drm, crtc) {
struct intel_initial_plane_config *plane_config =
&plane_configs[crtc->pipe];
@ -429,7 +433,7 @@ void intel_initial_plane_config(struct drm_i915_private *i915)
* can even allow for smooth boot transitions if the BIOS
* fb is large enough for the active pipe configuration.
*/
i915->display.funcs.display->get_initial_plane_config(crtc, plane_config);
display->funcs.display->get_initial_plane_config(crtc, plane_config);
/*
* If the fb is shared between multiple heads, we'll
@ -437,7 +441,7 @@ void intel_initial_plane_config(struct drm_i915_private *i915)
*/
intel_find_initial_plane_obj(crtc, plane_configs);
if (i915->display.funcs.display->fixup_initial_plane_config(crtc, plane_config))
if (display->funcs.display->fixup_initial_plane_config(crtc, plane_config))
intel_crtc_wait_for_next_vblank(crtc);
plane_config_fini(plane_config);

@ -6,8 +6,8 @@
#ifndef __INTEL_PLANE_INITIAL_H__
#define __INTEL_PLANE_INITIAL_H__
struct drm_i915_private;
struct intel_display;
void intel_initial_plane_config(struct drm_i915_private *i915);
void intel_initial_plane_config(struct intel_display *display);
#endif

@ -134,7 +134,7 @@ vlv_power_sequencer_kick(struct intel_dp *intel_dp)
*/
if (!pll_enabled) {
release_cl_override = display->platform.cherryview &&
!chv_phy_powergate_ch(dev_priv, phy, ch, true);
!chv_phy_powergate_ch(display, phy, ch, true);
if (vlv_force_pll_on(dev_priv, pipe, vlv_get_dpll(dev_priv))) {
drm_err(display->drm,
@ -163,7 +163,7 @@ vlv_power_sequencer_kick(struct intel_dp *intel_dp)
vlv_force_pll_off(dev_priv, pipe);
if (release_cl_override)
chv_phy_powergate_ch(dev_priv, phy, ch, false);
chv_phy_powergate_ch(display, phy, ch, false);
}
}
@ -668,23 +668,24 @@ static void wait_panel_power_cycle(struct intel_dp *intel_dp)
struct intel_display *display = to_intel_display(intel_dp);
struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
ktime_t panel_power_on_time;
s64 panel_power_off_duration;
drm_dbg_kms(display->drm,
"[ENCODER:%d:%s] %s wait for panel power cycle\n",
dig_port->base.base.base.id, dig_port->base.base.name,
pps_name(intel_dp));
s64 panel_power_off_duration, remaining;
/* take the difference of current time and panel power off time
* and then make panel wait for t11_t12 if needed. */
* and then make panel wait for power_cycle if needed. */
panel_power_on_time = ktime_get_boottime();
panel_power_off_duration = ktime_ms_delta(panel_power_on_time, intel_dp->pps.panel_power_off_time);
remaining = max(0, intel_dp->pps.panel_power_cycle_delay - panel_power_off_duration);
drm_dbg_kms(display->drm,
"[ENCODER:%d:%s] %s wait for panel power cycle (%lld ms remaining)\n",
dig_port->base.base.base.id, dig_port->base.base.name,
pps_name(intel_dp), remaining);
/* When we disable the VDD override bit last we have to do the manual
* wait. */
if (panel_power_off_duration < (s64)intel_dp->pps.panel_power_cycle_delay)
wait_remaining_ms_from_jiffies(jiffies,
intel_dp->pps.panel_power_cycle_delay - panel_power_off_duration);
if (remaining)
wait_remaining_ms_from_jiffies(jiffies, remaining);
wait_panel_status(intel_dp, IDLE_CYCLE_MASK, IDLE_CYCLE_VALUE);
}
@ -1387,10 +1388,10 @@ static void pps_init_timestamps(struct intel_dp *intel_dp)
}
static void
intel_pps_readout_hw_state(struct intel_dp *intel_dp, struct edp_power_seq *seq)
intel_pps_readout_hw_state(struct intel_dp *intel_dp, struct intel_pps_delays *seq)
{
struct intel_display *display = to_intel_display(intel_dp);
u32 pp_on, pp_off, pp_ctl;
u32 pp_on, pp_off, pp_ctl, power_cycle_delay;
struct pps_registers regs;
intel_pps_get_registers(intel_dp, &regs);
@ -1405,59 +1406,77 @@ intel_pps_readout_hw_state(struct intel_dp *intel_dp, struct edp_power_seq *seq)
pp_off = intel_de_read(display, regs.pp_off);
/* Pull timing values out of registers */
seq->t1_t3 = REG_FIELD_GET(PANEL_POWER_UP_DELAY_MASK, pp_on);
seq->t8 = REG_FIELD_GET(PANEL_LIGHT_ON_DELAY_MASK, pp_on);
seq->t9 = REG_FIELD_GET(PANEL_LIGHT_OFF_DELAY_MASK, pp_off);
seq->t10 = REG_FIELD_GET(PANEL_POWER_DOWN_DELAY_MASK, pp_off);
seq->power_up = REG_FIELD_GET(PANEL_POWER_UP_DELAY_MASK, pp_on);
seq->backlight_on = REG_FIELD_GET(PANEL_LIGHT_ON_DELAY_MASK, pp_on);
seq->backlight_off = REG_FIELD_GET(PANEL_LIGHT_OFF_DELAY_MASK, pp_off);
seq->power_down = REG_FIELD_GET(PANEL_POWER_DOWN_DELAY_MASK, pp_off);
if (i915_mmio_reg_valid(regs.pp_div)) {
u32 pp_div;
pp_div = intel_de_read(display, regs.pp_div);
seq->t11_t12 = REG_FIELD_GET(PANEL_POWER_CYCLE_DELAY_MASK, pp_div) * 1000;
power_cycle_delay = REG_FIELD_GET(PANEL_POWER_CYCLE_DELAY_MASK, pp_div);
} else {
seq->t11_t12 = REG_FIELD_GET(BXT_POWER_CYCLE_DELAY_MASK, pp_ctl) * 1000;
power_cycle_delay = REG_FIELD_GET(BXT_POWER_CYCLE_DELAY_MASK, pp_ctl);
}
/* hardware wants <delay>+1 in 100ms units */
seq->power_cycle = power_cycle_delay ? (power_cycle_delay - 1) * 1000 : 0;
}
static void
intel_pps_dump_state(struct intel_dp *intel_dp, const char *state_name,
const struct edp_power_seq *seq)
const struct intel_pps_delays *seq)
{
struct intel_display *display = to_intel_display(intel_dp);
drm_dbg_kms(display->drm,
"%s t1_t3 %d t8 %d t9 %d t10 %d t11_t12 %d\n",
state_name,
seq->t1_t3, seq->t8, seq->t9, seq->t10, seq->t11_t12);
"%s power_up %d backlight_on %d backlight_off %d power_down %d power_cycle %d\n",
state_name, seq->power_up, seq->backlight_on,
seq->backlight_off, seq->power_down, seq->power_cycle);
}
static void
intel_pps_verify_state(struct intel_dp *intel_dp)
{
struct intel_display *display = to_intel_display(intel_dp);
struct edp_power_seq hw;
struct edp_power_seq *sw = &intel_dp->pps.pps_delays;
struct intel_pps_delays hw;
struct intel_pps_delays *sw = &intel_dp->pps.pps_delays;
intel_pps_readout_hw_state(intel_dp, &hw);
if (hw.t1_t3 != sw->t1_t3 || hw.t8 != sw->t8 || hw.t9 != sw->t9 ||
hw.t10 != sw->t10 || hw.t11_t12 != sw->t11_t12) {
if (hw.power_up != sw->power_up ||
hw.backlight_on != sw->backlight_on ||
hw.backlight_off != sw->backlight_off ||
hw.power_down != sw->power_down ||
hw.power_cycle != sw->power_cycle) {
drm_err(display->drm, "PPS state mismatch\n");
intel_pps_dump_state(intel_dp, "sw", sw);
intel_pps_dump_state(intel_dp, "hw", &hw);
}
}
static bool pps_delays_valid(struct edp_power_seq *delays)
static bool pps_delays_valid(struct intel_pps_delays *delays)
{
return delays->t1_t3 || delays->t8 || delays->t9 ||
delays->t10 || delays->t11_t12;
return delays->power_up || delays->backlight_on || delays->backlight_off ||
delays->power_down || delays->power_cycle;
}
static int msecs_to_pps_units(int msecs)
{
/* PPS uses 100us units */
return msecs * 10;
}
static int pps_units_to_msecs(int val)
{
/* PPS uses 100us units */
return DIV_ROUND_UP(val, 10);
}
static void pps_init_delays_bios(struct intel_dp *intel_dp,
struct edp_power_seq *bios)
struct intel_pps_delays *bios)
{
struct intel_display *display = to_intel_display(intel_dp);
@ -1472,7 +1491,7 @@ static void pps_init_delays_bios(struct intel_dp *intel_dp,
}
static void pps_init_delays_vbt(struct intel_dp *intel_dp,
struct edp_power_seq *vbt)
struct intel_pps_delays *vbt)
{
struct intel_display *display = to_intel_display(intel_dp);
struct intel_connector *connector = intel_dp->attached_connector;
@ -1488,39 +1507,28 @@ static void pps_init_delays_vbt(struct intel_dp *intel_dp,
* seems sufficient to avoid this problem.
*/
if (intel_has_quirk(display, QUIRK_INCREASE_T12_DELAY)) {
vbt->t11_t12 = max_t(u16, vbt->t11_t12, 1300 * 10);
vbt->power_cycle = max_t(u16, vbt->power_cycle, msecs_to_pps_units(1300));
drm_dbg_kms(display->drm,
"Increasing T12 panel delay as per the quirk to %d\n",
vbt->t11_t12);
vbt->power_cycle);
}
/* T11_T12 delay is special and actually in units of 100ms, but zero
* based in the hw (so we need to add 100 ms). But the sw vbt
* table multiplies it with 1000 to make it in units of 100usec,
* too. */
vbt->t11_t12 += 100 * 10;
intel_pps_dump_state(intel_dp, "vbt", vbt);
}
static void pps_init_delays_spec(struct intel_dp *intel_dp,
struct edp_power_seq *spec)
struct intel_pps_delays *spec)
{
struct intel_display *display = to_intel_display(intel_dp);
lockdep_assert_held(&display->pps.mutex);
/* Upper limits from eDP 1.3 spec. Note that we use the clunky units of
* our hw here, which are all in 100usec. */
spec->t1_t3 = 210 * 10;
spec->t8 = 50 * 10; /* no limit for t8, use t7 instead */
spec->t9 = 50 * 10; /* no limit for t9, make it symmetric with t8 */
spec->t10 = 500 * 10;
/* This one is special and actually in units of 100ms, but zero
* based in the hw (so we need to add 100 ms). But the sw vbt
* table multiplies it with 1000 to make it in units of 100usec,
* too. */
spec->t11_t12 = (510 + 100) * 10;
/* Upper limits from eDP 1.3 spec */
spec->power_up = msecs_to_pps_units(10 + 200); /* T1+T3 */
spec->backlight_on = msecs_to_pps_units(50); /* no limit for T8, use T7 instead */
spec->backlight_off = msecs_to_pps_units(50); /* no limit for T9, make it symmetric with T8 */
spec->power_down = msecs_to_pps_units(500); /* T10 */
spec->power_cycle = msecs_to_pps_units(10 + 500); /* T11+T12 */
intel_pps_dump_state(intel_dp, "spec", spec);
}
@ -1528,7 +1536,7 @@ static void pps_init_delays_spec(struct intel_dp *intel_dp,
static void pps_init_delays(struct intel_dp *intel_dp)
{
struct intel_display *display = to_intel_display(intel_dp);
struct edp_power_seq cur, vbt, spec,
struct intel_pps_delays cur, vbt, spec,
*final = &intel_dp->pps.pps_delays;
lockdep_assert_held(&display->pps.mutex);
@ -1546,20 +1554,18 @@ static void pps_init_delays(struct intel_dp *intel_dp)
#define assign_final(field) final->field = (max(cur.field, vbt.field) == 0 ? \
spec.field : \
max(cur.field, vbt.field))
assign_final(t1_t3);
assign_final(t8);
assign_final(t9);
assign_final(t10);
assign_final(t11_t12);
assign_final(power_up);
assign_final(backlight_on);
assign_final(backlight_off);
assign_final(power_down);
assign_final(power_cycle);
#undef assign_final
#define get_delay(field) (DIV_ROUND_UP(final->field, 10))
intel_dp->pps.panel_power_up_delay = get_delay(t1_t3);
intel_dp->pps.backlight_on_delay = get_delay(t8);
intel_dp->pps.backlight_off_delay = get_delay(t9);
intel_dp->pps.panel_power_down_delay = get_delay(t10);
intel_dp->pps.panel_power_cycle_delay = get_delay(t11_t12);
#undef get_delay
intel_dp->pps.panel_power_up_delay = pps_units_to_msecs(final->power_up);
intel_dp->pps.backlight_on_delay = pps_units_to_msecs(final->backlight_on);
intel_dp->pps.backlight_off_delay = pps_units_to_msecs(final->backlight_off);
intel_dp->pps.panel_power_down_delay = pps_units_to_msecs(final->power_down);
intel_dp->pps.panel_power_cycle_delay = pps_units_to_msecs(final->power_cycle);
drm_dbg_kms(display->drm,
"panel power up delay %d, power down delay %d, power cycle delay %d\n",
@ -1573,19 +1579,20 @@ static void pps_init_delays(struct intel_dp *intel_dp)
/*
* We override the HW backlight delays to 1 because we do manual waits
* on them. For T8, even BSpec recommends doing it. For T9, if we
* don't do this, we'll end up waiting for the backlight off delay
* twice: once when we do the manual sleep, and once when we disable
* the panel and wait for the PP_STATUS bit to become zero.
* on them. For backlight_on, even BSpec recommends doing it. For
* backlight_off, if we don't do this, we'll end up waiting for the
* backlight off delay twice: once when we do the manual sleep, and
* once when we disable the panel and wait for the PP_STATUS bit to
* become zero.
*/
final->t8 = 1;
final->t9 = 1;
final->backlight_on = 1;
final->backlight_off = 1;
/*
* HW has only a 100msec granularity for t11_t12 so round it up
* HW has only a 100msec granularity for power_cycle so round it up
* accordingly.
*/
final->t11_t12 = roundup(final->t11_t12, 100 * 10);
final->power_cycle = roundup(final->power_cycle, msecs_to_pps_units(100));
}
static void pps_init_registers(struct intel_dp *intel_dp, bool force_disable_vdd)
@ -1596,7 +1603,7 @@ static void pps_init_registers(struct intel_dp *intel_dp, bool force_disable_vdd
int div = DISPLAY_RUNTIME_INFO(display)->rawclk_freq / 1000;
struct pps_registers regs;
enum port port = dp_to_dig_port(intel_dp)->base.port;
const struct edp_power_seq *seq = &intel_dp->pps.pps_delays;
const struct intel_pps_delays *seq = &intel_dp->pps.pps_delays;
lockdep_assert_held(&display->pps.mutex);
@ -1629,10 +1636,10 @@ static void pps_init_registers(struct intel_dp *intel_dp, bool force_disable_vdd
intel_de_write(display, regs.pp_ctrl, pp);
}
pp_on = REG_FIELD_PREP(PANEL_POWER_UP_DELAY_MASK, seq->t1_t3) |
REG_FIELD_PREP(PANEL_LIGHT_ON_DELAY_MASK, seq->t8);
pp_off = REG_FIELD_PREP(PANEL_LIGHT_OFF_DELAY_MASK, seq->t9) |
REG_FIELD_PREP(PANEL_POWER_DOWN_DELAY_MASK, seq->t10);
pp_on = REG_FIELD_PREP(PANEL_POWER_UP_DELAY_MASK, seq->power_up) |
REG_FIELD_PREP(PANEL_LIGHT_ON_DELAY_MASK, seq->backlight_on);
pp_off = REG_FIELD_PREP(PANEL_LIGHT_OFF_DELAY_MASK, seq->backlight_off) |
REG_FIELD_PREP(PANEL_POWER_DOWN_DELAY_MASK, seq->power_down);
/* Haswell doesn't have any port selection bits for the panel
* power sequencer any more. */
@ -1665,11 +1672,14 @@ static void pps_init_registers(struct intel_dp *intel_dp, bool force_disable_vdd
*/
if (i915_mmio_reg_valid(regs.pp_div))
intel_de_write(display, regs.pp_div,
REG_FIELD_PREP(PP_REFERENCE_DIVIDER_MASK, (100 * div) / 2 - 1) | REG_FIELD_PREP(PANEL_POWER_CYCLE_DELAY_MASK, DIV_ROUND_UP(seq->t11_t12, 1000)));
REG_FIELD_PREP(PP_REFERENCE_DIVIDER_MASK,
(100 * div) / 2 - 1) |
REG_FIELD_PREP(PANEL_POWER_CYCLE_DELAY_MASK,
DIV_ROUND_UP(seq->power_cycle, 1000) + 1));
else
intel_de_rmw(display, regs.pp_ctrl, BXT_POWER_CYCLE_DELAY_MASK,
REG_FIELD_PREP(BXT_POWER_CYCLE_DELAY_MASK,
DIV_ROUND_UP(seq->t11_t12, 1000)));
DIV_ROUND_UP(seq->power_cycle, 1000) + 1));
drm_dbg_kms(display->drm,
"panel power sequencer register settings: PP_ON %#x, PP_OFF %#x, PP_DIV %#x\n",
@ -1810,6 +1820,8 @@ static int intel_pps_show(struct seq_file *m, void *data)
intel_dp->pps.panel_power_up_delay);
seq_printf(m, "Panel power down delay: %d\n",
intel_dp->pps.panel_power_down_delay);
seq_printf(m, "Panel power cycle delay: %d\n",
intel_dp->pps.panel_power_cycle_delay);
seq_printf(m, "Backlight on delay: %d\n",
intel_dp->pps.backlight_on_delay);
seq_printf(m, "Backlight off delay: %d\n",

@ -1130,18 +1130,16 @@ static void psr2_program_idle_frames(struct intel_dp *intel_dp,
static void tgl_psr2_enable_dc3co(struct intel_dp *intel_dp)
{
struct intel_display *display = to_intel_display(intel_dp);
struct drm_i915_private *dev_priv = to_i915(display->drm);
psr2_program_idle_frames(intel_dp, 0);
intel_display_power_set_target_dc_state(dev_priv, DC_STATE_EN_DC3CO);
intel_display_power_set_target_dc_state(display, DC_STATE_EN_DC3CO);
}
static void tgl_psr2_disable_dc3co(struct intel_dp *intel_dp)
{
struct intel_display *display = to_intel_display(intel_dp);
struct drm_i915_private *dev_priv = to_i915(display->drm);
intel_display_power_set_target_dc_state(dev_priv, DC_STATE_EN_UPTO_DC6);
intel_display_power_set_target_dc_state(display, DC_STATE_EN_UPTO_DC6);
psr2_program_idle_frames(intel_dp, psr_compute_idle_frames(intel_dp));
}
@ -1564,13 +1562,6 @@ static bool _psr_compute_config(struct intel_dp *intel_dp,
const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
int entry_setup_frames;
/*
* Current PSR panels don't work reliably with VRR enabled
* So if VRR is enabled, do not enable PSR.
*/
if (crtc_state->vrr.enable)
return false;
if (!CAN_PSR(intel_dp))
return false;
@ -1644,6 +1635,15 @@ _panel_replay_compute_config(struct intel_dp *intel_dp,
return true;
}
static bool intel_psr_needs_wa_18037818876(struct intel_dp *intel_dp,
struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(intel_dp);
return (DISPLAY_VER(display) == 20 && intel_dp->psr.entry_setup_frames > 0 &&
!crtc_state->has_sel_update);
}
void intel_psr_compute_config(struct intel_dp *intel_dp,
struct intel_crtc_state *crtc_state,
struct drm_connector_state *conn_state)
@ -1679,6 +1679,12 @@ void intel_psr_compute_config(struct intel_dp *intel_dp,
return;
}
/*
* Currently PSR/PR doesn't work reliably with VRR enabled.
*/
if (crtc_state->vrr.enable)
return;
crtc_state->has_panel_replay = _panel_replay_compute_config(intel_dp,
crtc_state,
conn_state);
@ -1690,6 +1696,13 @@ void intel_psr_compute_config(struct intel_dp *intel_dp,
return;
crtc_state->has_sel_update = intel_sel_update_config_valid(intel_dp, crtc_state);
/* Wa_18037818876 */
if (intel_psr_needs_wa_18037818876(intel_dp, crtc_state)) {
crtc_state->has_psr = false;
drm_dbg_kms(display->drm,
"PSR disabled to workaround PSR FSM hang issue\n");
}
}
void intel_psr_get_config(struct intel_encoder *encoder,
@ -1773,23 +1786,6 @@ static void intel_psr_activate(struct intel_dp *intel_dp)
intel_dp->psr.active = true;
}
static u32 wa_16013835468_bit_get(struct intel_dp *intel_dp)
{
switch (intel_dp->psr.pipe) {
case PIPE_A:
return LATENCY_REPORTING_REMOVED_PIPE_A;
case PIPE_B:
return LATENCY_REPORTING_REMOVED_PIPE_B;
case PIPE_C:
return LATENCY_REPORTING_REMOVED_PIPE_C;
case PIPE_D:
return LATENCY_REPORTING_REMOVED_PIPE_D;
default:
MISSING_CASE(intel_dp->psr.pipe);
return 0;
}
}
/*
* Wa_16013835468
* Wa_14015648006
@ -1798,23 +1794,25 @@ static void wm_optimization_wa(struct intel_dp *intel_dp,
const struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(intel_dp);
bool set_wa_bit = false;
enum pipe pipe = intel_dp->psr.pipe;
bool activate = false;
/* Wa_14015648006 */
if (IS_DISPLAY_VER(display, 11, 14))
set_wa_bit |= crtc_state->wm_level_disabled;
if (IS_DISPLAY_VER(display, 11, 14) && crtc_state->wm_level_disabled)
activate = true;
/* Wa_16013835468 */
if (DISPLAY_VER(display) == 12)
set_wa_bit |= crtc_state->hw.adjusted_mode.crtc_vblank_start !=
crtc_state->hw.adjusted_mode.crtc_vdisplay;
if (DISPLAY_VER(display) == 12 &&
crtc_state->hw.adjusted_mode.crtc_vblank_start !=
crtc_state->hw.adjusted_mode.crtc_vdisplay)
activate = true;
if (set_wa_bit)
if (activate)
intel_de_rmw(display, GEN8_CHICKEN_DCPR_1,
0, wa_16013835468_bit_get(intel_dp));
0, LATENCY_REPORTING_REMOVED(pipe));
else
intel_de_rmw(display, GEN8_CHICKEN_DCPR_1,
wa_16013835468_bit_get(intel_dp), 0);
LATENCY_REPORTING_REMOVED(pipe), 0);
}
static void intel_psr_enable_source(struct intel_dp *intel_dp,
@ -1908,7 +1906,7 @@ static void intel_psr_enable_source(struct intel_dp *intel_dp,
if (intel_dp->psr.sel_update_enabled) {
if (DISPLAY_VER(display) == 9)
intel_de_rmw(display, CHICKEN_TRANS(cpu_transcoder), 0,
intel_de_rmw(display, CHICKEN_TRANS(display, cpu_transcoder), 0,
PSR2_VSC_ENABLE_PROG_HEADER |
PSR2_ADD_VERTICAL_LINE_COUNT);
@ -1920,7 +1918,7 @@ static void intel_psr_enable_source(struct intel_dp *intel_dp,
if (!intel_dp->psr.panel_replay_enabled &&
(IS_DISPLAY_VERx100_STEP(display, 1400, STEP_A0, STEP_B0) ||
IS_ALDERLAKE_P(dev_priv)))
intel_de_rmw(display, hsw_chicken_trans_reg(dev_priv, cpu_transcoder),
intel_de_rmw(display, CHICKEN_TRANS(display, cpu_transcoder),
0, ADLP_1_BASED_X_GRANULARITY);
/* Wa_16012604467:adlp,mtl[a0,b0] */
@ -2114,7 +2112,7 @@ static void intel_psr_disable_locked(struct intel_dp *intel_dp)
*/
if (DISPLAY_VER(display) >= 11)
intel_de_rmw(display, GEN8_CHICKEN_DCPR_1,
wa_16013835468_bit_get(intel_dp), 0);
LATENCY_REPORTING_REMOVED(intel_dp->psr.pipe), 0);
if (intel_dp->psr.sel_update_enabled) {
/* Wa_16012604467:adlp,mtl[a0,b0] */
@ -3335,11 +3333,10 @@ void intel_psr_flush(struct intel_display *display,
void intel_psr_init(struct intel_dp *intel_dp)
{
struct intel_display *display = to_intel_display(intel_dp);
struct drm_i915_private *dev_priv = to_i915(display->drm);
struct intel_connector *connector = intel_dp->attached_connector;
struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
if (!(HAS_PSR(display) || HAS_DP20(dev_priv)))
if (!(HAS_PSR(display) || HAS_DP20(display)))
return;
/*
@ -3357,7 +3354,7 @@ void intel_psr_init(struct intel_dp *intel_dp)
return;
}
if ((HAS_DP20(dev_priv) && !intel_dp_is_edp(intel_dp)) ||
if ((HAS_DP20(display) && !intel_dp_is_edp(intel_dp)) ||
DISPLAY_VER(display) >= 20)
intel_dp->psr.source_panel_replay_support = true;
@ -3974,7 +3971,6 @@ DEFINE_SHOW_ATTRIBUTE(i915_psr_status);
void intel_psr_connector_debugfs_add(struct intel_connector *connector)
{
struct intel_display *display = to_intel_display(connector);
struct drm_i915_private *i915 = to_i915(connector->base.dev);
struct dentry *root = connector->base.debugfs_entry;
if (connector->base.connector_type != DRM_MODE_CONNECTOR_eDP &&
@ -3984,7 +3980,7 @@ void intel_psr_connector_debugfs_add(struct intel_connector *connector)
debugfs_create_file("i915_psr_sink_status", 0444, root,
connector, &i915_psr_sink_status_fops);
if (HAS_PSR(display) || HAS_DP20(i915))
if (HAS_PSR(display) || HAS_DP20(display))
debugfs_create_file("i915_psr_status", 0444, root,
connector, &i915_psr_status_fops);
}

@ -2136,6 +2136,7 @@ intel_sdvo_connector_matches_edid(struct intel_sdvo_connector *sdvo,
static enum drm_connector_status
intel_sdvo_detect(struct drm_connector *connector, bool force)
{
struct intel_display *display = to_intel_display(connector->dev);
struct drm_i915_private *i915 = to_i915(connector->dev);
struct intel_sdvo *intel_sdvo = intel_attached_sdvo(to_intel_connector(connector));
struct intel_sdvo_connector *intel_sdvo_connector = to_intel_sdvo_connector(connector);
@ -2145,10 +2146,10 @@ intel_sdvo_detect(struct drm_connector *connector, bool force)
drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s]\n",
connector->base.id, connector->name);
if (!intel_display_device_enabled(i915))
if (!intel_display_device_enabled(display))
return connector_status_disconnected;
if (!intel_display_driver_check_access(i915))
if (!intel_display_driver_check_access(display))
return connector->status;
if (!intel_sdvo_set_target_output(intel_sdvo,
@ -2196,14 +2197,14 @@ intel_sdvo_detect(struct drm_connector *connector, bool force)
static int intel_sdvo_get_ddc_modes(struct drm_connector *connector)
{
struct drm_i915_private *i915 = to_i915(connector->dev);
struct intel_display *display = to_intel_display(connector->dev);
int num_modes = 0;
const struct drm_edid *drm_edid;
drm_dbg_kms(connector->dev, "[CONNECTOR:%d:%s]\n",
connector->base.id, connector->name);
if (!intel_display_driver_check_access(i915))
if (!intel_display_driver_check_access(display))
return drm_edid_connector_add_modes(connector);
/* set the bus switch and get the modes */
@ -2297,6 +2298,7 @@ static const struct drm_display_mode sdvo_tv_modes[] = {
static int intel_sdvo_get_tv_modes(struct drm_connector *connector)
{
struct intel_display *display = to_intel_display(connector->dev);
struct intel_sdvo *intel_sdvo = intel_attached_sdvo(to_intel_connector(connector));
struct drm_i915_private *i915 = to_i915(intel_sdvo->base.base.dev);
struct intel_sdvo_connector *intel_sdvo_connector =
@ -2310,7 +2312,7 @@ static int intel_sdvo_get_tv_modes(struct drm_connector *connector)
drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s]\n",
connector->base.id, connector->name);
if (!intel_display_driver_check_access(i915))
if (!intel_display_driver_check_access(display))
return 0;
/*

@ -390,7 +390,7 @@ void intel_tc_port_set_fia_lane_count(struct intel_digital_port *dig_port,
{
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
struct intel_tc_port *tc = to_tc_port(dig_port);
bool lane_reversal = dig_port->saved_port_bits & DDI_BUF_PORT_REVERSAL;
bool lane_reversal = dig_port->lane_reversal;
u32 val;
if (DISPLAY_VER(i915) >= 14)

@ -1714,7 +1714,6 @@ intel_tv_detect(struct drm_connector *connector,
bool force)
{
struct intel_display *display = to_intel_display(connector->dev);
struct drm_i915_private *i915 = to_i915(connector->dev);
struct intel_tv *intel_tv = intel_attached_tv(to_intel_connector(connector));
enum drm_connector_status status;
int type;
@ -1722,10 +1721,10 @@ intel_tv_detect(struct drm_connector *connector,
drm_dbg_kms(display->drm, "[CONNECTOR:%d:%s] force=%d\n",
connector->base.id, connector->name, force);
if (!intel_display_device_enabled(i915))
if (!intel_display_device_enabled(display))
return connector_status_disconnected;
if (!intel_display_driver_check_access(i915))
if (!intel_display_driver_check_access(display))
return connector->status;
if (force) {

@ -1014,6 +1014,14 @@ struct bdb_tv_options {
* Block 27 - eDP VBT Block
*/
struct edp_power_seq {
u16 t1_t3;
u16 t8;
u16 t9;
u16 t10;
u16 t11_t12;
} __packed;
#define EDP_18BPP 0
#define EDP_24BPP 1
#define EDP_30BPP 2

@ -14,6 +14,7 @@
#include "intel_crtc.h"
#include "intel_de.h"
#include "intel_display_types.h"
#include "intel_dp.h"
#include "intel_dsi.h"
#include "intel_qp_tables.h"
#include "intel_vdsc.h"
@ -379,7 +380,7 @@ intel_dsc_power_domain(struct intel_crtc *crtc, enum transcoder cpu_transcoder)
static int intel_dsc_get_vdsc_per_pipe(const struct intel_crtc_state *crtc_state)
{
return crtc_state->dsc.dsc_split ? 2 : 1;
return crtc_state->dsc.num_streams;
}
int intel_dsc_get_num_vdsc_instances(const struct intel_crtc_state *crtc_state)
@ -402,8 +403,10 @@ static void intel_dsc_get_pps_reg(const struct intel_crtc_state *crtc_state, int
pipe_dsc = is_pipe_dsc(crtc, cpu_transcoder);
if (dsc_reg_num >= 3)
if (dsc_reg_num >= 4)
MISSING_CASE(dsc_reg_num);
if (dsc_reg_num >= 3)
dsc_reg[2] = BMG_DSC2_PPS(pipe, pps);
if (dsc_reg_num >= 2)
dsc_reg[1] = pipe_dsc ? ICL_DSC1_PPS(pipe, pps) : DSCC_PPS(pps);
if (dsc_reg_num >= 1)
@ -415,7 +418,7 @@ static void intel_dsc_pps_write(const struct intel_crtc_state *crtc_state,
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
i915_reg_t dsc_reg[2];
i915_reg_t dsc_reg[3];
int i, vdsc_per_pipe, dsc_reg_num;
vdsc_per_pipe = intel_dsc_get_vdsc_per_pipe(crtc_state);
@ -770,11 +773,17 @@ void intel_dsc_enable(const struct intel_crtc_state *crtc_state)
intel_dsc_pps_configure(crtc_state);
dss_ctl2_val |= LEFT_BRANCH_VDSC_ENABLE;
dss_ctl2_val |= VDSC0_ENABLE;
if (vdsc_instances_per_pipe > 1) {
dss_ctl2_val |= RIGHT_BRANCH_VDSC_ENABLE;
dss_ctl2_val |= VDSC1_ENABLE;
dss_ctl1_val |= JOINER_ENABLE;
}
if (vdsc_instances_per_pipe > 2) {
dss_ctl2_val |= VDSC2_ENABLE;
dss_ctl2_val |= SMALL_JOINER_CONFIG_3_ENGINES;
}
if (crtc_state->joiner_pipes) {
if (intel_crtc_ultrajoiner_enable_needed(crtc_state))
dss_ctl1_val |= ULTRA_JOINER_ENABLE;
@ -809,7 +818,7 @@ static u32 intel_dsc_pps_read(struct intel_crtc_state *crtc_state, int pps,
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
i915_reg_t dsc_reg[2];
i915_reg_t dsc_reg[3];
int i, vdsc_per_pipe, dsc_reg_num;
u32 val;
@ -972,12 +981,16 @@ void intel_dsc_get_config(struct intel_crtc_state *crtc_state)
dss_ctl1 = intel_de_read(dev_priv, dss_ctl1_reg(crtc, cpu_transcoder));
dss_ctl2 = intel_de_read(dev_priv, dss_ctl2_reg(crtc, cpu_transcoder));
crtc_state->dsc.compression_enable = dss_ctl2 & LEFT_BRANCH_VDSC_ENABLE;
crtc_state->dsc.compression_enable = dss_ctl2 & VDSC0_ENABLE;
if (!crtc_state->dsc.compression_enable)
goto out;
crtc_state->dsc.dsc_split = (dss_ctl2 & RIGHT_BRANCH_VDSC_ENABLE) &&
(dss_ctl1 & JOINER_ENABLE);
if (dss_ctl1 & JOINER_ENABLE && dss_ctl2 & (VDSC2_ENABLE | SMALL_JOINER_CONFIG_3_ENGINES))
crtc_state->dsc.num_streams = 3;
else if (dss_ctl1 & JOINER_ENABLE && dss_ctl2 & VDSC1_ENABLE)
crtc_state->dsc.num_streams = 2;
else
crtc_state->dsc.num_streams = 1;
intel_dsc_get_pps_config(crtc_state);
out:
@ -988,10 +1001,10 @@ static void intel_vdsc_dump_state(struct drm_printer *p, int indent,
const struct intel_crtc_state *crtc_state)
{
drm_printf_indent(p, indent,
"dsc-dss: compressed-bpp:" FXP_Q4_FMT ", slice-count: %d, split: %s\n",
"dsc-dss: compressed-bpp:" FXP_Q4_FMT ", slice-count: %d, num_streams: %d\n",
FXP_Q4_ARGS(crtc_state->dsc.compressed_bpp_x16),
crtc_state->dsc.slice_count,
str_yes_no(crtc_state->dsc.dsc_split));
crtc_state->dsc.num_streams);
}
void intel_vdsc_state_dump(struct drm_printer *p, int indent,
@ -1003,3 +1016,48 @@ void intel_vdsc_state_dump(struct drm_printer *p, int indent,
intel_vdsc_dump_state(p, indent, crtc_state);
drm_dsc_dump_config(p, indent, &crtc_state->dsc.config);
}
int intel_vdsc_min_cdclk(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);
int num_vdsc_instances = intel_dsc_get_num_vdsc_instances(crtc_state);
int min_cdclk;
if (!crtc_state->dsc.compression_enable)
return 0;
/*
* When we decide to use only one VDSC engine, since
* each VDSC operates with 1 ppc throughput, pixel clock
* cannot be higher than the VDSC clock (cdclk)
* If there 2 VDSC engines, then pixel clock can't be higher than
* VDSC clock(cdclk) * 2 and so on.
*/
min_cdclk = DIV_ROUND_UP(crtc_state->pixel_rate, num_vdsc_instances);
if (crtc_state->joiner_pipes) {
int pixel_clock = intel_dp_mode_to_fec_clock(crtc_state->hw.adjusted_mode.clock);
/*
* According to Bigjoiner bw check:
* compressed_bpp <= PPC * CDCLK * Big joiner Interface bits / Pixel clock
*
* We have already computed compressed_bpp, so now compute the min CDCLK that
* is required to support this compressed_bpp.
*
* => CDCLK >= compressed_bpp * Pixel clock / (PPC * Bigjoiner Interface bits)
*
* Since PPC = 2 with bigjoiner
* => CDCLK >= compressed_bpp * Pixel clock / 2 * Bigjoiner Interface bits
*/
int bigjoiner_interface_bits = DISPLAY_VER(display) >= 14 ? 36 : 24;
int min_cdclk_bj =
(fxp_q4_to_int_roundup(crtc_state->dsc.compressed_bpp_x16) *
pixel_clock) / (2 * bigjoiner_interface_bits);
min_cdclk = max(min_cdclk, min_cdclk_bj);
}
return min_cdclk;
}

@ -31,5 +31,6 @@ void intel_dsc_dp_pps_write(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state);
void intel_vdsc_state_dump(struct drm_printer *p, int indent,
const struct intel_crtc_state *crtc_state);
int intel_vdsc_min_cdclk(const struct intel_crtc_state *crtc_state);
#endif /* __INTEL_VDSC_H__ */

@ -21,8 +21,10 @@
#define MAX_DL_BUFFER_TARGET_DEPTH 0x5a0
#define DSS_CTL2 _MMIO(0x67404)
#define LEFT_BRANCH_VDSC_ENABLE (1 << 31)
#define RIGHT_BRANCH_VDSC_ENABLE (1 << 15)
#define VDSC0_ENABLE REG_BIT(31)
#define VDSC2_ENABLE REG_BIT(30)
#define SMALL_JOINER_CONFIG_3_ENGINES REG_BIT(23)
#define VDSC1_ENABLE REG_BIT(15)
#define RIGHT_DL_BUF_TARGET_DEPTH_MASK (0xfff << 0)
#define RIGHT_DL_BUF_TARGET_DEPTH(pixels) ((pixels) << 0)
@ -57,8 +59,10 @@
#define DSCC_PPS(pps) _MMIO(_DSCC_PPS_0 + ((pps) < 12 ? (pps) : (pps) + 12) * 4)
#define _ICL_DSC0_PICTURE_PARAMETER_SET_0_PB 0x78270
#define _ICL_DSC1_PICTURE_PARAMETER_SET_0_PB 0x78370
#define _BMG_DSC2_PICTURE_PARAMETER_SET_0_PB 0x78970
#define _ICL_DSC0_PICTURE_PARAMETER_SET_0_PC 0x78470
#define _ICL_DSC1_PICTURE_PARAMETER_SET_0_PC 0x78570
#define _BMG_DSC2_PICTURE_PARAMETER_SET_0_PC 0x78A70
#define ICL_DSC0_PICTURE_PARAMETER_SET_0(pipe) _MMIO_PIPE((pipe) - PIPE_B, \
_ICL_DSC0_PICTURE_PARAMETER_SET_0_PB, \
_ICL_DSC0_PICTURE_PARAMETER_SET_0_PC)
@ -71,8 +75,12 @@
#define _ICL_DSC1_PPS_0(pipe) _PICK_EVEN((pipe) - PIPE_B, \
_ICL_DSC1_PICTURE_PARAMETER_SET_0_PB, \
_ICL_DSC1_PICTURE_PARAMETER_SET_0_PC)
#define _BMG_DSC2_PPS_0(pipe) _PICK_EVEN((pipe) - PIPE_B, \
_BMG_DSC2_PICTURE_PARAMETER_SET_0_PB, \
_BMG_DSC2_PICTURE_PARAMETER_SET_0_PC)
#define ICL_DSC0_PPS(pipe, pps) _MMIO(_ICL_DSC0_PPS_0(pipe) + ((pps) * 4))
#define ICL_DSC1_PPS(pipe, pps) _MMIO(_ICL_DSC1_PPS_0(pipe) + ((pps) * 4))
#define BMG_DSC2_PPS(pipe, pps) _MMIO(_BMG_DSC2_PPS_0(pipe) + ((pps) * 4))
/* PPS 0 */
#define DSC_PPS0_NATIVE_422_ENABLE REG_BIT(23)

@ -288,7 +288,7 @@ void intel_vrr_set_transcoder_timings(const struct intel_crtc_state *crtc_state)
* ADL/DG2: make TRANS_SET_CONTEXT_LATENCY effective with VRR
*/
if (IS_DISPLAY_VER(display, 12, 13))
intel_de_rmw(display, CHICKEN_TRANS(cpu_transcoder),
intel_de_rmw(display, CHICKEN_TRANS(display, cpu_transcoder),
0, PIPE_VBLANK_WITH_DELAY);
if (!intel_vrr_possible(crtc_state)) {

@ -105,10 +105,10 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach,
const struct drm_format_info *format,
u64 modifier, bool need_scaler)
{
struct intel_display *display = to_intel_display(crtc_state);
struct intel_crtc_scaler_state *scaler_state =
&crtc_state->scaler_state;
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
const struct drm_display_mode *adjusted_mode =
&crtc_state->hw.adjusted_mode;
int pipe_src_w = drm_rect_width(&crtc_state->pipe_src);
@ -130,9 +130,9 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach,
* Once NV12 is enabled, handle it here while allocating scaler
* for NV12.
*/
if (DISPLAY_VER(dev_priv) >= 9 && crtc_state->hw.enable &&
if (DISPLAY_VER(display) >= 9 && crtc_state->hw.enable &&
need_scaler && adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {
drm_dbg_kms(&dev_priv->drm,
drm_dbg_kms(display->drm,
"Pipe/Plane scaling not supported with IF-ID mode\n");
return -EINVAL;
}
@ -150,9 +150,9 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach,
if (force_detach || !need_scaler) {
if (*scaler_id >= 0) {
scaler_state->scaler_users &= ~(1 << scaler_user);
scaler_state->scalers[*scaler_id].in_use = 0;
scaler_state->scalers[*scaler_id].in_use = false;
drm_dbg_kms(&dev_priv->drm,
drm_dbg_kms(display->drm,
"scaler_user index %u.%u: "
"Staged freeing scaler id %d scaler_users = 0x%x\n",
crtc->pipe, scaler_user, *scaler_id,
@ -164,7 +164,7 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach,
if (format && intel_format_info_is_yuv_semiplanar(format, modifier) &&
(src_h < SKL_MIN_YUV_420_SRC_H || src_w < SKL_MIN_YUV_420_SRC_W)) {
drm_dbg_kms(&dev_priv->drm,
drm_dbg_kms(display->drm,
"Planar YUV: src dimensions not met\n");
return -EINVAL;
}
@ -174,17 +174,17 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach,
min_dst_w = SKL_MIN_DST_W;
min_dst_h = SKL_MIN_DST_H;
if (DISPLAY_VER(dev_priv) < 11) {
if (DISPLAY_VER(display) < 11) {
max_src_w = SKL_MAX_SRC_W;
max_src_h = SKL_MAX_SRC_H;
max_dst_w = SKL_MAX_DST_W;
max_dst_h = SKL_MAX_DST_H;
} else if (DISPLAY_VER(dev_priv) < 12) {
} else if (DISPLAY_VER(display) < 12) {
max_src_w = ICL_MAX_SRC_W;
max_src_h = ICL_MAX_SRC_H;
max_dst_w = ICL_MAX_DST_W;
max_dst_h = ICL_MAX_DST_H;
} else if (DISPLAY_VER(dev_priv) < 14) {
} else if (DISPLAY_VER(display) < 14) {
max_src_w = TGL_MAX_SRC_W;
max_src_h = TGL_MAX_SRC_H;
max_dst_w = TGL_MAX_DST_W;
@ -201,7 +201,7 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach,
dst_w < min_dst_w || dst_h < min_dst_h ||
src_w > max_src_w || src_h > max_src_h ||
dst_w > max_dst_w || dst_h > max_dst_h) {
drm_dbg_kms(&dev_priv->drm,
drm_dbg_kms(display->drm,
"scaler_user index %u.%u: src %ux%u dst %ux%u "
"size is out of scaler range\n",
crtc->pipe, scaler_user, src_w, src_h,
@ -218,7 +218,7 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach,
* now.
*/
if (pipe_src_w > max_dst_w || pipe_src_h > max_dst_h) {
drm_dbg_kms(&dev_priv->drm,
drm_dbg_kms(display->drm,
"scaler_user index %u.%u: pipe src size %ux%u "
"is out of scaler range\n",
crtc->pipe, scaler_user, pipe_src_w, pipe_src_h);
@ -227,7 +227,7 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach,
/* mark this plane as a scaler user in crtc_state */
scaler_state->scaler_users |= (1 << scaler_user);
drm_dbg_kms(&dev_priv->drm, "scaler_user index %u.%u: "
drm_dbg_kms(display->drm, "scaler_user index %u.%u: "
"staged scaling request for %ux%u->%ux%u scaler_users = 0x%x\n",
crtc->pipe, scaler_user, src_w, src_h, dst_w, dst_h,
scaler_state->scaler_users);
@ -268,20 +268,19 @@ int skl_update_scaler_crtc(struct intel_crtc_state *crtc_state)
int skl_update_scaler_plane(struct intel_crtc_state *crtc_state,
struct intel_plane_state *plane_state)
{
struct intel_plane *intel_plane =
to_intel_plane(plane_state->uapi.plane);
struct drm_i915_private *dev_priv = to_i915(intel_plane->base.dev);
struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
struct drm_framebuffer *fb = plane_state->hw.fb;
bool force_detach = !fb || !plane_state->uapi.visible;
bool need_scaler = false;
/* Pre-gen11 and SDR planes always need a scaler for planar formats. */
if (!icl_is_hdr_plane(dev_priv, intel_plane->id) &&
if (!icl_is_hdr_plane(dev_priv, plane->id) &&
fb && intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier))
need_scaler = true;
return skl_update_scaler(crtc_state, force_detach,
drm_plane_index(&intel_plane->base),
drm_plane_index(&plane->base),
&plane_state->scaler_id,
drm_rect_width(&plane_state->uapi.src) >> 16,
drm_rect_height(&plane_state->uapi.src) >> 16,
@ -292,29 +291,37 @@ int skl_update_scaler_plane(struct intel_crtc_state *crtc_state,
need_scaler);
}
static int intel_allocate_scaler(struct intel_crtc_scaler_state *scaler_state,
struct intel_crtc *crtc)
{
int i;
for (i = 0; i < crtc->num_scalers; i++) {
if (scaler_state->scalers[i].in_use)
continue;
scaler_state->scalers[i].in_use = true;
return i;
}
return -1;
}
static int intel_atomic_setup_scaler(struct intel_crtc_scaler_state *scaler_state,
int num_scalers_need, struct intel_crtc *intel_crtc,
int num_scalers_need, struct intel_crtc *crtc,
const char *name, int idx,
struct intel_plane_state *plane_state,
int *scaler_id)
{
struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev);
int j;
struct intel_display *display = to_intel_display(crtc);
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
u32 mode;
if (*scaler_id < 0) {
/* find a free scaler */
for (j = 0; j < intel_crtc->num_scalers; j++) {
if (scaler_state->scalers[j].in_use)
continue;
if (*scaler_id < 0)
*scaler_id = intel_allocate_scaler(scaler_state, crtc);
*scaler_id = j;
scaler_state->scalers[*scaler_id].in_use = 1;
break;
}
}
if (drm_WARN(&dev_priv->drm, *scaler_id < 0,
if (drm_WARN(display->drm, *scaler_id < 0,
"Cannot find scaler for %s:%d\n", name, idx))
return -EINVAL;
@ -324,7 +331,7 @@ static int intel_atomic_setup_scaler(struct intel_crtc_scaler_state *scaler_stat
plane_state->hw.fb->format->num_planes > 1) {
struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
if (DISPLAY_VER(dev_priv) == 9) {
if (DISPLAY_VER(display) == 9) {
mode = SKL_PS_SCALER_MODE_NV12;
} else if (icl_is_hdr_plane(dev_priv, plane->id)) {
/*
@ -342,17 +349,17 @@ static int intel_atomic_setup_scaler(struct intel_crtc_scaler_state *scaler_stat
if (linked)
mode |= PS_BINDING_Y_PLANE(linked->id);
}
} else if (DISPLAY_VER(dev_priv) >= 10) {
} else if (DISPLAY_VER(display) >= 10) {
mode = PS_SCALER_MODE_NORMAL;
} else if (num_scalers_need == 1 && intel_crtc->num_scalers > 1) {
} else if (num_scalers_need == 1 && crtc->num_scalers > 1) {
/*
* when only 1 scaler is in use on a pipe with 2 scalers
* scaler 0 operates in high quality (HQ) mode.
* In this case use scaler 0 to take advantage of HQ mode
*/
scaler_state->scalers[*scaler_id].in_use = 0;
scaler_state->scalers[*scaler_id].in_use = false;
*scaler_id = 0;
scaler_state->scalers[0].in_use = 1;
scaler_state->scalers[0].in_use = true;
mode = SKL_PS_SCALER_MODE_HQ;
} else {
mode = SKL_PS_SCALER_MODE_DYN;
@ -376,7 +383,7 @@ static int intel_atomic_setup_scaler(struct intel_crtc_scaler_state *scaler_stat
* unnecessarily.
*/
if (DISPLAY_VER(dev_priv) >= 14) {
if (DISPLAY_VER(display) >= 14) {
/*
* On versions 14 and up, only the first
* scaler supports a vertical scaling factor
@ -389,7 +396,7 @@ static int intel_atomic_setup_scaler(struct intel_crtc_scaler_state *scaler_stat
else
max_vscale = 0x10000;
} else if (DISPLAY_VER(dev_priv) >= 10 ||
} else if (DISPLAY_VER(display) >= 10 ||
!intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier)) {
max_hscale = 0x30000 - 1;
max_vscale = 0x30000 - 1;
@ -408,7 +415,7 @@ static int intel_atomic_setup_scaler(struct intel_crtc_scaler_state *scaler_stat
vscale = drm_rect_calc_vscale(src, dst, 1, max_vscale);
if (hscale < 0 || vscale < 0) {
drm_dbg_kms(&dev_priv->drm,
drm_dbg_kms(display->drm,
"Scaler %d doesn't support required plane scaling\n",
*scaler_id);
drm_rect_debug_print("src: ", src, true);
@ -418,18 +425,66 @@ static int intel_atomic_setup_scaler(struct intel_crtc_scaler_state *scaler_stat
}
}
drm_dbg_kms(&dev_priv->drm, "Attached scaler id %u.%u to %s:%d\n",
intel_crtc->pipe, *scaler_id, name, idx);
drm_dbg_kms(display->drm, "Attached scaler id %u.%u to %s:%d\n",
crtc->pipe, *scaler_id, name, idx);
scaler_state->scalers[*scaler_id].mode = mode;
return 0;
}
static int setup_crtc_scaler(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
struct intel_crtc_state *crtc_state =
intel_atomic_get_new_crtc_state(state, crtc);
struct intel_crtc_scaler_state *scaler_state =
&crtc_state->scaler_state;
return intel_atomic_setup_scaler(scaler_state,
hweight32(scaler_state->scaler_users),
crtc, "CRTC", crtc->base.base.id,
NULL, &scaler_state->scaler_id);
}
static int setup_plane_scaler(struct intel_atomic_state *state,
struct intel_crtc *crtc,
struct intel_plane *plane)
{
struct intel_display *display = to_intel_display(state);
struct intel_crtc_state *crtc_state =
intel_atomic_get_new_crtc_state(state, crtc);
struct intel_crtc_scaler_state *scaler_state =
&crtc_state->scaler_state;
struct intel_plane_state *plane_state;
/* plane on different crtc cannot be a scaler user of this crtc */
if (drm_WARN_ON(display->drm, plane->pipe != crtc->pipe))
return 0;
plane_state = intel_atomic_get_new_plane_state(state, plane);
/*
* GLK+ scalers don't have a HQ mode so it
* isn't necessary to change between HQ and dyn mode
* on those platforms.
*/
if (!plane_state && DISPLAY_VER(display) >= 10)
return 0;
plane_state = intel_atomic_get_plane_state(state, plane);
if (IS_ERR(plane_state))
return PTR_ERR(plane_state);
return intel_atomic_setup_scaler(scaler_state,
hweight32(scaler_state->scaler_users),
crtc, "PLANE", plane->base.base.id,
plane_state, &plane_state->scaler_id);
}
/**
* intel_atomic_setup_scalers() - setup scalers for crtc per staged requests
* @dev_priv: i915 device
* @intel_crtc: intel crtc
* @crtc_state: incoming crtc_state to validate and setup scalers
* @state: atomic state
* @crtc: crtc
*
* This function sets up scalers based on staged scaling requests for
* a @crtc and its planes. It is called from crtc level check path. If request
@ -442,16 +497,14 @@ static int intel_atomic_setup_scaler(struct intel_crtc_scaler_state *scaler_stat
* 0 - scalers were setup successfully
* error code - otherwise
*/
int intel_atomic_setup_scalers(struct drm_i915_private *dev_priv,
struct intel_crtc *intel_crtc,
struct intel_crtc_state *crtc_state)
int intel_atomic_setup_scalers(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
struct drm_plane *plane = NULL;
struct intel_plane *intel_plane;
struct intel_display *display = to_intel_display(crtc);
struct intel_crtc_state *crtc_state =
intel_atomic_get_new_crtc_state(state, crtc);
struct intel_crtc_scaler_state *scaler_state =
&crtc_state->scaler_state;
struct drm_atomic_state *drm_state = crtc_state->uapi.state;
struct intel_atomic_state *intel_state = to_intel_atomic_state(drm_state);
int num_scalers_need;
int i;
@ -470,80 +523,33 @@ int intel_atomic_setup_scalers(struct drm_i915_private *dev_priv,
*/
/* fail if required scalers > available scalers */
if (num_scalers_need > intel_crtc->num_scalers) {
drm_dbg_kms(&dev_priv->drm,
if (num_scalers_need > crtc->num_scalers) {
drm_dbg_kms(display->drm,
"Too many scaling requests %d > %d\n",
num_scalers_need, intel_crtc->num_scalers);
num_scalers_need, crtc->num_scalers);
return -EINVAL;
}
/* walkthrough scaler_users bits and start assigning scalers */
for (i = 0; i < sizeof(scaler_state->scaler_users) * 8; i++) {
struct intel_plane_state *plane_state = NULL;
int *scaler_id;
const char *name;
int idx, ret;
int ret;
/* skip if scaler not required */
if (!(scaler_state->scaler_users & (1 << i)))
continue;
if (i == SKL_CRTC_INDEX) {
name = "CRTC";
idx = intel_crtc->base.base.id;
/* panel fitter case: assign as a crtc scaler */
scaler_id = &scaler_state->scaler_id;
ret = setup_crtc_scaler(state, crtc);
if (ret)
return ret;
} else {
name = "PLANE";
struct intel_plane *plane =
to_intel_plane(drm_plane_from_index(display->drm, i));
/* plane scaler case: assign as a plane scaler */
/* find the plane that set the bit as scaler_user */
plane = drm_state->planes[i].ptr;
/*
* to enable/disable hq mode, add planes that are using scaler
* into this transaction
*/
if (!plane) {
struct drm_plane_state *state;
/*
* GLK+ scalers don't have a HQ mode so it
* isn't necessary to change between HQ and dyn mode
* on those platforms.
*/
if (DISPLAY_VER(dev_priv) >= 10)
continue;
plane = drm_plane_from_index(&dev_priv->drm, i);
state = drm_atomic_get_plane_state(drm_state, plane);
if (IS_ERR(state)) {
drm_dbg_kms(&dev_priv->drm,
"Failed to add [PLANE:%d] to drm_state\n",
plane->base.id);
return PTR_ERR(state);
}
}
intel_plane = to_intel_plane(plane);
idx = plane->base.id;
/* plane on different crtc cannot be a scaler user of this crtc */
if (drm_WARN_ON(&dev_priv->drm,
intel_plane->pipe != intel_crtc->pipe))
continue;
plane_state = intel_atomic_get_new_plane_state(intel_state,
intel_plane);
scaler_id = &plane_state->scaler_id;
ret = setup_plane_scaler(state, crtc, plane);
if (ret)
return ret;
}
ret = intel_atomic_setup_scaler(scaler_state, num_scalers_need,
intel_crtc, name, idx,
plane_state, scaler_id);
if (ret < 0)
return ret;
}
return 0;
@ -596,12 +602,12 @@ static u16 glk_nearest_filter_coef(int t)
*
*/
static void glk_program_nearest_filter_coefs(struct drm_i915_private *dev_priv,
static void glk_program_nearest_filter_coefs(struct intel_display *display,
enum pipe pipe, int id, int set)
{
int i;
intel_de_write_fw(dev_priv, GLK_PS_COEF_INDEX_SET(pipe, id, set),
intel_de_write_fw(display, GLK_PS_COEF_INDEX_SET(pipe, id, set),
PS_COEF_INDEX_AUTO_INC);
for (i = 0; i < 17 * 7; i += 2) {
@ -614,11 +620,11 @@ static void glk_program_nearest_filter_coefs(struct drm_i915_private *dev_priv,
t = glk_coef_tap(i + 1);
tmp |= glk_nearest_filter_coef(t) << 16;
intel_de_write_fw(dev_priv, GLK_PS_COEF_DATA_SET(pipe, id, set),
intel_de_write_fw(display, GLK_PS_COEF_DATA_SET(pipe, id, set),
tmp);
}
intel_de_write_fw(dev_priv, GLK_PS_COEF_INDEX_SET(pipe, id, set), 0);
intel_de_write_fw(display, GLK_PS_COEF_INDEX_SET(pipe, id, set), 0);
}
static u32 skl_scaler_get_filter_select(enum drm_scaling_filter filter, int set)
@ -634,14 +640,14 @@ static u32 skl_scaler_get_filter_select(enum drm_scaling_filter filter, int set)
return PS_FILTER_MEDIUM;
}
static void skl_scaler_setup_filter(struct drm_i915_private *dev_priv, enum pipe pipe,
static void skl_scaler_setup_filter(struct intel_display *display, enum pipe pipe,
int id, int set, enum drm_scaling_filter filter)
{
switch (filter) {
case DRM_SCALING_FILTER_DEFAULT:
break;
case DRM_SCALING_FILTER_NEAREST_NEIGHBOR:
glk_program_nearest_filter_coefs(dev_priv, pipe, id, set);
glk_program_nearest_filter_coefs(display, pipe, id, set);
break;
default:
MISSING_CASE(filter);
@ -650,8 +656,8 @@ static void skl_scaler_setup_filter(struct drm_i915_private *dev_priv, enum pipe
void skl_pfit_enable(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);
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
const struct intel_crtc_scaler_state *scaler_state =
&crtc_state->scaler_state;
const struct drm_rect *dst = &crtc_state->pch_pfit.dst;
@ -669,7 +675,7 @@ void skl_pfit_enable(const struct intel_crtc_state *crtc_state)
if (!crtc_state->pch_pfit.enabled)
return;
if (drm_WARN_ON(&dev_priv->drm,
if (drm_WARN_ON(display->drm,
crtc_state->scaler_state.scaler_id < 0))
return;
@ -688,18 +694,18 @@ void skl_pfit_enable(const struct intel_crtc_state *crtc_state)
ps_ctrl = PS_SCALER_EN | PS_BINDING_PIPE | scaler_state->scalers[id].mode |
skl_scaler_get_filter_select(crtc_state->hw.scaling_filter, 0);
skl_scaler_setup_filter(dev_priv, pipe, id, 0,
skl_scaler_setup_filter(display, pipe, id, 0,
crtc_state->hw.scaling_filter);
intel_de_write_fw(dev_priv, SKL_PS_CTRL(pipe, id), ps_ctrl);
intel_de_write_fw(display, SKL_PS_CTRL(pipe, id), ps_ctrl);
intel_de_write_fw(dev_priv, SKL_PS_VPHASE(pipe, id),
intel_de_write_fw(display, SKL_PS_VPHASE(pipe, id),
PS_Y_PHASE(0) | PS_UV_RGB_PHASE(uv_rgb_vphase));
intel_de_write_fw(dev_priv, SKL_PS_HPHASE(pipe, id),
intel_de_write_fw(display, SKL_PS_HPHASE(pipe, id),
PS_Y_PHASE(0) | PS_UV_RGB_PHASE(uv_rgb_hphase));
intel_de_write_fw(dev_priv, SKL_PS_WIN_POS(pipe, id),
intel_de_write_fw(display, SKL_PS_WIN_POS(pipe, id),
PS_WIN_XPOS(x) | PS_WIN_YPOS(y));
intel_de_write_fw(dev_priv, SKL_PS_WIN_SZ(pipe, id),
intel_de_write_fw(display, SKL_PS_WIN_SZ(pipe, id),
PS_WIN_XSIZE(width) | PS_WIN_YSIZE(height));
}
@ -708,6 +714,7 @@ skl_program_plane_scaler(struct intel_plane *plane,
const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state)
{
struct intel_display *display = to_intel_display(plane);
struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
const struct drm_framebuffer *fb = plane_state->hw.fb;
enum pipe pipe = plane->pipe;
@ -751,28 +758,27 @@ skl_program_plane_scaler(struct intel_plane *plane,
ps_ctrl = PS_SCALER_EN | PS_BINDING_PLANE(plane->id) | scaler->mode |
skl_scaler_get_filter_select(plane_state->hw.scaling_filter, 0);
skl_scaler_setup_filter(dev_priv, pipe, scaler_id, 0,
skl_scaler_setup_filter(display, pipe, scaler_id, 0,
plane_state->hw.scaling_filter);
intel_de_write_fw(dev_priv, SKL_PS_CTRL(pipe, scaler_id), ps_ctrl);
intel_de_write_fw(dev_priv, SKL_PS_VPHASE(pipe, scaler_id),
intel_de_write_fw(display, SKL_PS_CTRL(pipe, scaler_id), ps_ctrl);
intel_de_write_fw(display, SKL_PS_VPHASE(pipe, scaler_id),
PS_Y_PHASE(y_vphase) | PS_UV_RGB_PHASE(uv_rgb_vphase));
intel_de_write_fw(dev_priv, SKL_PS_HPHASE(pipe, scaler_id),
intel_de_write_fw(display, SKL_PS_HPHASE(pipe, scaler_id),
PS_Y_PHASE(y_hphase) | PS_UV_RGB_PHASE(uv_rgb_hphase));
intel_de_write_fw(dev_priv, SKL_PS_WIN_POS(pipe, scaler_id),
intel_de_write_fw(display, SKL_PS_WIN_POS(pipe, scaler_id),
PS_WIN_XPOS(crtc_x) | PS_WIN_YPOS(crtc_y));
intel_de_write_fw(dev_priv, SKL_PS_WIN_SZ(pipe, scaler_id),
intel_de_write_fw(display, SKL_PS_WIN_SZ(pipe, scaler_id),
PS_WIN_XSIZE(crtc_w) | PS_WIN_YSIZE(crtc_h));
}
static void skl_detach_scaler(struct intel_crtc *crtc, int id)
{
struct drm_device *dev = crtc->base.dev;
struct drm_i915_private *dev_priv = to_i915(dev);
struct intel_display *display = to_intel_display(crtc);
intel_de_write_fw(dev_priv, SKL_PS_CTRL(crtc->pipe, id), 0);
intel_de_write_fw(dev_priv, SKL_PS_WIN_POS(crtc->pipe, id), 0);
intel_de_write_fw(dev_priv, SKL_PS_WIN_SZ(crtc->pipe, id), 0);
intel_de_write_fw(display, SKL_PS_CTRL(crtc->pipe, id), 0);
intel_de_write_fw(display, SKL_PS_WIN_POS(crtc->pipe, id), 0);
intel_de_write_fw(display, SKL_PS_WIN_SZ(crtc->pipe, id), 0);
}
/*
@ -803,8 +809,8 @@ void skl_scaler_disable(const struct intel_crtc_state *old_crtc_state)
void skl_scaler_get_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);
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
struct intel_crtc_scaler_state *scaler_state = &crtc_state->scaler_state;
int id = -1;
int i;
@ -813,15 +819,15 @@ void skl_scaler_get_config(struct intel_crtc_state *crtc_state)
for (i = 0; i < crtc->num_scalers; i++) {
u32 ctl, pos, size;
ctl = intel_de_read(dev_priv, SKL_PS_CTRL(crtc->pipe, i));
ctl = intel_de_read(display, SKL_PS_CTRL(crtc->pipe, i));
if ((ctl & (PS_SCALER_EN | PS_BINDING_MASK)) != (PS_SCALER_EN | PS_BINDING_PIPE))
continue;
id = i;
crtc_state->pch_pfit.enabled = true;
pos = intel_de_read(dev_priv, SKL_PS_WIN_POS(crtc->pipe, i));
size = intel_de_read(dev_priv, SKL_PS_WIN_SZ(crtc->pipe, i));
pos = intel_de_read(display, SKL_PS_WIN_POS(crtc->pipe, i));
size = intel_de_read(display, SKL_PS_WIN_SZ(crtc->pipe, i));
drm_rect_init(&crtc_state->pch_pfit.dst,
REG_FIELD_GET(PS_WIN_XPOS_MASK, pos),

@ -5,11 +5,7 @@
#ifndef INTEL_SCALER_H
#define INTEL_SCALER_H
#include <linux/types.h>
enum drm_scaling_filter;
enum pipe;
struct drm_i915_private;
struct intel_atomic_state;
struct intel_crtc;
struct intel_crtc_state;
struct intel_plane;
@ -20,9 +16,8 @@ int skl_update_scaler_crtc(struct intel_crtc_state *crtc_state);
int skl_update_scaler_plane(struct intel_crtc_state *crtc_state,
struct intel_plane_state *plane_state);
int intel_atomic_setup_scalers(struct drm_i915_private *dev_priv,
struct intel_crtc *intel_crtc,
struct intel_crtc_state *crtc_state);
int intel_atomic_setup_scalers(struct intel_atomic_state *state,
struct intel_crtc *crtc);
void skl_pfit_enable(const struct intel_crtc_state *crtc_state);

@ -239,7 +239,9 @@ int skl_format_to_fourcc(int format, bool rgb_order, bool alpha)
static u8 icl_nv12_y_plane_mask(struct drm_i915_private *i915)
{
if (DISPLAY_VER(i915) >= 13 || HAS_D12_PLANE_MINIMIZATION(i915))
struct intel_display *display = &i915->display;
if (DISPLAY_VER(display) >= 13 || HAS_D12_PLANE_MINIMIZATION(display))
return BIT(PLANE_4) | BIT(PLANE_5);
else
return BIT(PLANE_6) | BIT(PLANE_7);
@ -734,7 +736,6 @@ static void skl_write_plane_wm(struct intel_dsb *dsb,
const struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(plane->base.dev);
struct drm_i915_private *i915 = to_i915(plane->base.dev);
enum plane_id plane_id = plane->id;
enum pipe pipe = plane->pipe;
const struct skl_pipe_wm *pipe_wm = &crtc_state->wm.skl.optimal;
@ -744,14 +745,14 @@ static void skl_write_plane_wm(struct intel_dsb *dsb,
&crtc_state->wm.skl.plane_ddb_y[plane_id];
int level;
for (level = 0; level < i915->display.wm.num_levels; level++)
for (level = 0; level < display->wm.num_levels; level++)
intel_de_write_dsb(display, dsb, PLANE_WM(pipe, plane_id, level),
skl_plane_wm_reg_val(skl_plane_wm_level(pipe_wm, plane_id, level)));
intel_de_write_dsb(display, dsb, PLANE_WM_TRANS(pipe, plane_id),
skl_plane_wm_reg_val(skl_plane_trans_wm(pipe_wm, plane_id)));
if (HAS_HW_SAGV_WM(i915)) {
if (HAS_HW_SAGV_WM(display)) {
const struct skl_plane_wm *wm = &pipe_wm->planes[plane_id];
intel_de_write_dsb(display, dsb, PLANE_WM_SAGV(pipe, plane_id),
@ -763,7 +764,7 @@ static void skl_write_plane_wm(struct intel_dsb *dsb,
intel_de_write_dsb(display, dsb, PLANE_BUF_CFG(pipe, plane_id),
skl_plane_ddb_reg_val(ddb));
if (DISPLAY_VER(i915) < 11)
if (DISPLAY_VER(display) < 11)
intel_de_write_dsb(display, dsb, PLANE_NV12_BUF_CFG(pipe, plane_id),
skl_plane_ddb_reg_val(ddb_y));
}
@ -2548,13 +2549,14 @@ static bool tgl_plane_has_mc_ccs(struct drm_i915_private *i915,
static u8 skl_get_plane_caps(struct drm_i915_private *i915,
enum pipe pipe, enum plane_id plane_id)
{
struct intel_display *display = &i915->display;
u8 caps = INTEL_PLANE_CAP_TILING_X;
if (DISPLAY_VER(i915) < 13 || IS_ALDERLAKE_P(i915))
if (DISPLAY_VER(display) < 13 || display->platform.alderlake_p)
caps |= INTEL_PLANE_CAP_TILING_Y;
if (DISPLAY_VER(i915) < 12)
if (DISPLAY_VER(display) < 12)
caps |= INTEL_PLANE_CAP_TILING_Yf;
if (HAS_4TILE(i915))
if (HAS_4TILE(display))
caps |= INTEL_PLANE_CAP_TILING_4;
if (!IS_ENABLED(I915) && !HAS_FLAT_CCS(i915))
@ -2562,14 +2564,14 @@ static u8 skl_get_plane_caps(struct drm_i915_private *i915,
if (skl_plane_has_rc_ccs(i915, pipe, plane_id)) {
caps |= INTEL_PLANE_CAP_CCS_RC;
if (DISPLAY_VER(i915) >= 12)
if (DISPLAY_VER(display) >= 12)
caps |= INTEL_PLANE_CAP_CCS_RC_CC;
}
if (tgl_plane_has_mc_ccs(i915, plane_id))
caps |= INTEL_PLANE_CAP_CCS_MC;
if (DISPLAY_VER(i915) >= 14 && IS_DGFX(i915))
if (DISPLAY_VER(display) >= 14 && display->platform.dgfx)
caps |= INTEL_PLANE_CAP_NEED64K_PHYS;
return caps;
@ -2743,6 +2745,7 @@ void
skl_get_initial_plane_config(struct intel_crtc *crtc,
struct intel_initial_plane_config *plane_config)
{
struct intel_display *display = to_intel_display(crtc);
struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state);
struct drm_device *dev = crtc->base.dev;
struct drm_i915_private *dev_priv = to_i915(dev);
@ -2824,7 +2827,7 @@ skl_get_initial_plane_config(struct intel_crtc *crtc,
fb->modifier = I915_FORMAT_MOD_Y_TILED;
break;
case PLANE_CTL_TILED_YF: /* aka PLANE_CTL_TILED_4 on XE_LPD+ */
if (HAS_4TILE(dev_priv)) {
if (HAS_4TILE(display)) {
u32 rc_mask = PLANE_CTL_RENDER_DECOMPRESSION_ENABLE |
PLANE_CTL_CLEAR_COLOR_DISABLE;

@ -77,20 +77,23 @@ static bool skl_needs_memory_bw_wa(struct drm_i915_private *i915)
bool
intel_has_sagv(struct drm_i915_private *i915)
{
return HAS_SAGV(i915) &&
i915->display.sagv.status != I915_SAGV_NOT_CONTROLLED;
struct intel_display *display = &i915->display;
return HAS_SAGV(display) && display->sagv.status != I915_SAGV_NOT_CONTROLLED;
}
static u32
intel_sagv_block_time(struct drm_i915_private *i915)
{
if (DISPLAY_VER(i915) >= 14) {
struct intel_display *display = &i915->display;
if (DISPLAY_VER(display) >= 14) {
u32 val;
val = intel_de_read(i915, MTL_LATENCY_SAGV);
val = intel_de_read(display, MTL_LATENCY_SAGV);
return REG_FIELD_GET(MTL_LATENCY_QCLK_SAGV, val);
} else if (DISPLAY_VER(i915) >= 12) {
} else if (DISPLAY_VER(display) >= 12) {
u32 val = 0;
int ret;
@ -98,14 +101,14 @@ intel_sagv_block_time(struct drm_i915_private *i915)
GEN12_PCODE_READ_SAGV_BLOCK_TIME_US,
&val, NULL);
if (ret) {
drm_dbg_kms(&i915->drm, "Couldn't read SAGV block time!\n");
drm_dbg_kms(display->drm, "Couldn't read SAGV block time!\n");
return 0;
}
return val;
} else if (DISPLAY_VER(i915) == 11) {
} else if (DISPLAY_VER(display) == 11) {
return 10;
} else if (HAS_SAGV(i915)) {
} else if (HAS_SAGV(display)) {
return 30;
} else {
return 0;
@ -114,31 +117,33 @@ intel_sagv_block_time(struct drm_i915_private *i915)
static void intel_sagv_init(struct drm_i915_private *i915)
{
if (!HAS_SAGV(i915))
i915->display.sagv.status = I915_SAGV_NOT_CONTROLLED;
struct intel_display *display = &i915->display;
if (!HAS_SAGV(display))
display->sagv.status = I915_SAGV_NOT_CONTROLLED;
/*
* Probe to see if we have working SAGV control.
* For icl+ this was already determined by intel_bw_init_hw().
*/
if (DISPLAY_VER(i915) < 11)
if (DISPLAY_VER(display) < 11)
skl_sagv_disable(i915);
drm_WARN_ON(&i915->drm, i915->display.sagv.status == I915_SAGV_UNKNOWN);
drm_WARN_ON(display->drm, display->sagv.status == I915_SAGV_UNKNOWN);
i915->display.sagv.block_time_us = intel_sagv_block_time(i915);
display->sagv.block_time_us = intel_sagv_block_time(i915);
drm_dbg_kms(&i915->drm, "SAGV supported: %s, original SAGV block time: %u us\n",
str_yes_no(intel_has_sagv(i915)), i915->display.sagv.block_time_us);
drm_dbg_kms(display->drm, "SAGV supported: %s, original SAGV block time: %u us\n",
str_yes_no(intel_has_sagv(i915)), display->sagv.block_time_us);
/* avoid overflow when adding with wm0 latency/etc. */
if (drm_WARN(&i915->drm, i915->display.sagv.block_time_us > U16_MAX,
if (drm_WARN(display->drm, display->sagv.block_time_us > U16_MAX,
"Excessive SAGV block time %u, ignoring\n",
i915->display.sagv.block_time_us))
i915->display.sagv.block_time_us = 0;
display->sagv.block_time_us))
display->sagv.block_time_us = 0;
if (!intel_has_sagv(i915))
i915->display.sagv.block_time_us = 0;
display->sagv.block_time_us = 0;
}
/*
@ -444,6 +449,7 @@ bool intel_can_enable_sagv(struct drm_i915_private *i915,
static int intel_compute_sagv_mask(struct intel_atomic_state *state)
{
struct intel_display *display = to_intel_display(state);
struct drm_i915_private *i915 = to_i915(state->base.dev);
int ret;
struct intel_crtc *crtc;
@ -479,7 +485,7 @@ static int intel_compute_sagv_mask(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(i915) &&
pipe_wm->use_sagv_wm = !HAS_HW_SAGV_WM(display) &&
DISPLAY_VER(i915) >= 12 &&
intel_crtc_can_enable_sagv(new_crtc_state);
@ -2496,6 +2502,7 @@ static u8 intel_dbuf_enabled_slices(const struct intel_dbuf_state *dbuf_state)
static int
skl_compute_ddb(struct intel_atomic_state *state)
{
struct intel_display *display = to_intel_display(state);
struct drm_i915_private *i915 = to_i915(state->base.dev);
const struct intel_dbuf_state *old_dbuf_state;
struct intel_dbuf_state *new_dbuf_state = NULL;
@ -2524,7 +2531,7 @@ skl_compute_ddb(struct intel_atomic_state *state)
return ret;
}
if (HAS_MBUS_JOINING(i915)) {
if (HAS_MBUS_JOINING(display)) {
new_dbuf_state->joined_mbus =
adlp_check_mbus_joined(new_dbuf_state->active_pipes);
@ -2742,10 +2749,10 @@ static bool skl_plane_selected_wm_equals(struct intel_plane *plane,
const struct skl_pipe_wm *old_pipe_wm,
const struct skl_pipe_wm *new_pipe_wm)
{
struct drm_i915_private *i915 = to_i915(plane->base.dev);
struct intel_display *display = to_intel_display(plane);
int level;
for (level = 0; level < i915->display.wm.num_levels; level++) {
for (level = 0; level < display->wm.num_levels; level++) {
/*
* We don't check uv_wm as the hardware doesn't actually
* use it. It only gets used for calculating the required
@ -2756,7 +2763,7 @@ static bool skl_plane_selected_wm_equals(struct intel_plane *plane,
return false;
}
if (HAS_HW_SAGV_WM(i915)) {
if (HAS_HW_SAGV_WM(display)) {
const struct skl_plane_wm *old_wm = &old_pipe_wm->planes[plane->id];
const struct skl_plane_wm *new_wm = &new_pipe_wm->planes[plane->id];
@ -2847,32 +2854,51 @@ static int skl_wm_add_affected_planes(struct intel_atomic_state *state,
* Program DEEP PKG_C_LATENCY Pkg C with all 1's.
* Program PKG_C_LATENCY Added Wake Time = 0
*/
static void
skl_program_dpkgc_latency(struct drm_i915_private *i915, bool enable_dpkgc)
void
intel_program_dpkgc_latency(struct intel_atomic_state *state)
{
u32 max_latency = 0;
u32 clear = 0, val = 0;
struct intel_display *display = to_intel_display(state);
struct drm_i915_private *i915 = to_i915(display->drm);
struct intel_crtc *crtc;
struct intel_crtc_state *new_crtc_state;
u32 latency = LNL_PKG_C_LATENCY_MASK;
u32 added_wake_time = 0;
u32 max_linetime = 0;
u32 clear, val;
bool fixed_refresh_rate = false;
int i;
if (DISPLAY_VER(i915) < 20)
if (DISPLAY_VER(display) < 20)
return;
if (enable_dpkgc) {
max_latency = skl_watermark_max_latency(i915, 1);
if (max_latency == 0)
max_latency = LNL_PKG_C_LATENCY_MASK;
added_wake_time = DSB_EXE_TIME +
i915->display.sagv.block_time_us;
} else {
max_latency = LNL_PKG_C_LATENCY_MASK;
added_wake_time = 0;
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
if (!new_crtc_state->vrr.enable ||
(new_crtc_state->vrr.vmin == new_crtc_state->vrr.vmax &&
new_crtc_state->vrr.vmin == new_crtc_state->vrr.flipline))
fixed_refresh_rate = true;
max_linetime = max(new_crtc_state->linetime, max_linetime);
}
clear |= LNL_ADDED_WAKE_TIME_MASK | LNL_PKG_C_LATENCY_MASK;
val |= REG_FIELD_PREP(LNL_PKG_C_LATENCY_MASK, max_latency);
val |= REG_FIELD_PREP(LNL_ADDED_WAKE_TIME_MASK, added_wake_time);
if (fixed_refresh_rate) {
latency = skl_watermark_max_latency(i915, 1);
/* Wa_22020299601 */
if ((latency && max_linetime) &&
(DISPLAY_VER(display) == 20 || DISPLAY_VER(display) == 30)) {
latency = max_linetime * DIV_ROUND_UP(latency, max_linetime);
} else if (!latency) {
latency = LNL_PKG_C_LATENCY_MASK;
}
intel_uncore_rmw(&i915->uncore, LNL_PKG_C_LATENCY, clear, val);
added_wake_time = DSB_EXE_TIME +
display->sagv.block_time_us;
}
clear = LNL_ADDED_WAKE_TIME_MASK | LNL_PKG_C_LATENCY_MASK;
val = REG_FIELD_PREP(LNL_PKG_C_LATENCY_MASK, latency) |
REG_FIELD_PREP(LNL_ADDED_WAKE_TIME_MASK, added_wake_time);
intel_de_rmw(display, LNL_PKG_C_LATENCY, clear, val);
}
static int
@ -2881,7 +2907,6 @@ skl_compute_wm(struct intel_atomic_state *state)
struct intel_crtc *crtc;
struct intel_crtc_state __maybe_unused *new_crtc_state;
int ret, i;
bool enable_dpkgc = false;
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
ret = skl_build_pipe_wm(state, crtc);
@ -2906,15 +2931,8 @@ skl_compute_wm(struct intel_atomic_state *state)
ret = skl_wm_add_affected_planes(state, crtc);
if (ret)
return ret;
if ((new_crtc_state->vrr.vmin == new_crtc_state->vrr.vmax &&
new_crtc_state->vrr.vmin == new_crtc_state->vrr.flipline) ||
!new_crtc_state->vrr.enable)
enable_dpkgc = true;
}
skl_program_dpkgc_latency(to_i915(state->base.dev), enable_dpkgc);
skl_print_wm_changes(state);
return 0;
@ -2931,6 +2949,7 @@ static void skl_wm_level_from_reg_val(u32 val, struct skl_wm_level *level)
static void skl_pipe_wm_get_hw_state(struct intel_crtc *crtc,
struct skl_pipe_wm *out)
{
struct intel_display *display = to_intel_display(crtc);
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
enum pipe pipe = crtc->pipe;
enum plane_id plane_id;
@ -2956,7 +2975,7 @@ static void skl_pipe_wm_get_hw_state(struct intel_crtc *crtc,
skl_wm_level_from_reg_val(val, &wm->trans_wm);
if (HAS_HW_SAGV_WM(i915)) {
if (HAS_HW_SAGV_WM(display)) {
if (plane_id != PLANE_CURSOR)
val = intel_de_read(i915, PLANE_WM_SAGV(pipe, plane_id));
else
@ -2984,7 +3003,7 @@ static void skl_wm_get_hw_state(struct drm_i915_private *i915)
to_intel_dbuf_state(i915->display.dbuf.obj.state);
struct intel_crtc *crtc;
if (HAS_MBUS_JOINING(i915))
if (HAS_MBUS_JOINING(display))
dbuf_state->joined_mbus = intel_de_read(i915, MBUS_CTL) & MBUS_JOIN;
dbuf_state->mdclk_cdclk_ratio = intel_mdclk_cdclk_ratio(display, &display->cdclk.hw);
@ -3048,202 +3067,6 @@ static void skl_wm_get_hw_state(struct drm_i915_private *i915)
dbuf_state->enabled_slices = i915->display.dbuf.enabled_slices;
}
static bool skl_dbuf_is_misconfigured(struct drm_i915_private *i915)
{
const struct intel_dbuf_state *dbuf_state =
to_intel_dbuf_state(i915->display.dbuf.obj.state);
struct skl_ddb_entry entries[I915_MAX_PIPES] = {};
struct intel_crtc *crtc;
for_each_intel_crtc(&i915->drm, crtc) {
const struct intel_crtc_state *crtc_state =
to_intel_crtc_state(crtc->base.state);
entries[crtc->pipe] = crtc_state->wm.skl.ddb;
}
for_each_intel_crtc(&i915->drm, crtc) {
const struct intel_crtc_state *crtc_state =
to_intel_crtc_state(crtc->base.state);
u8 slices;
slices = skl_compute_dbuf_slices(crtc, dbuf_state->active_pipes,
dbuf_state->joined_mbus);
if (dbuf_state->slices[crtc->pipe] & ~slices)
return true;
if (skl_ddb_allocation_overlaps(&crtc_state->wm.skl.ddb, entries,
I915_MAX_PIPES, crtc->pipe))
return true;
}
return false;
}
static void skl_wm_sanitize(struct drm_i915_private *i915)
{
struct intel_crtc *crtc;
/*
* On TGL/RKL (at least) the BIOS likes to assign the planes
* to the wrong DBUF slices. This will cause an infinite loop
* in skl_commit_modeset_enables() as it can't find a way to
* transition between the old bogus DBUF layout to the new
* proper DBUF layout without DBUF allocation overlaps between
* the planes (which cannot be allowed or else the hardware
* may hang). If we detect a bogus DBUF layout just turn off
* all the planes so that skl_commit_modeset_enables() can
* simply ignore them.
*/
if (!skl_dbuf_is_misconfigured(i915))
return;
drm_dbg_kms(&i915->drm, "BIOS has misprogrammed the DBUF, disabling all planes\n");
for_each_intel_crtc(&i915->drm, crtc) {
struct intel_plane *plane = to_intel_plane(crtc->base.primary);
const struct intel_plane_state *plane_state =
to_intel_plane_state(plane->base.state);
struct intel_crtc_state *crtc_state =
to_intel_crtc_state(crtc->base.state);
if (plane_state->uapi.visible)
intel_plane_disable_noatomic(crtc, plane);
drm_WARN_ON(&i915->drm, crtc_state->active_planes != 0);
memset(&crtc_state->wm.skl.ddb, 0, sizeof(crtc_state->wm.skl.ddb));
}
}
static void skl_wm_get_hw_state_and_sanitize(struct drm_i915_private *i915)
{
skl_wm_get_hw_state(i915);
skl_wm_sanitize(i915);
}
void intel_wm_state_verify(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
struct drm_i915_private *i915 = to_i915(state->base.dev);
const struct intel_crtc_state *new_crtc_state =
intel_atomic_get_new_crtc_state(state, crtc);
struct skl_hw_state {
struct skl_ddb_entry ddb[I915_MAX_PLANES];
struct skl_ddb_entry ddb_y[I915_MAX_PLANES];
struct skl_pipe_wm wm;
} *hw;
const struct skl_pipe_wm *sw_wm = &new_crtc_state->wm.skl.optimal;
struct intel_plane *plane;
u8 hw_enabled_slices;
int level;
if (DISPLAY_VER(i915) < 9 || !new_crtc_state->hw.active)
return;
hw = kzalloc(sizeof(*hw), GFP_KERNEL);
if (!hw)
return;
skl_pipe_wm_get_hw_state(crtc, &hw->wm);
skl_pipe_ddb_get_hw_state(crtc, hw->ddb, hw->ddb_y);
hw_enabled_slices = intel_enabled_dbuf_slices_mask(i915);
if (DISPLAY_VER(i915) >= 11 &&
hw_enabled_slices != i915->display.dbuf.enabled_slices)
drm_err(&i915->drm,
"mismatch in DBUF Slices (expected 0x%x, got 0x%x)\n",
i915->display.dbuf.enabled_slices,
hw_enabled_slices);
for_each_intel_plane_on_crtc(&i915->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;
/* Watermarks */
for (level = 0; level < i915->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);
if (skl_wm_level_equals(hw_wm_level, sw_wm_level))
continue;
drm_err(&i915->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);
}
hw_wm_level = &hw->wm.planes[plane->id].trans_wm;
sw_wm_level = skl_plane_trans_wm(sw_wm, plane->id);
if (!skl_wm_level_equals(hw_wm_level, sw_wm_level)) {
drm_err(&i915->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);
}
hw_wm_level = &hw->wm.planes[plane->id].sagv.wm0;
sw_wm_level = &sw_wm->planes[plane->id].sagv.wm0;
if (HAS_HW_SAGV_WM(i915) &&
!skl_wm_level_equals(hw_wm_level, sw_wm_level)) {
drm_err(&i915->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(i915) &&
!skl_wm_level_equals(hw_wm_level, sw_wm_level)) {
drm_err(&i915->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_CURSOR];
sw_ddb_entry = &new_crtc_state->wm.skl.plane_ddb[PLANE_CURSOR];
if (!skl_ddb_entry_equal(hw_ddb_entry, sw_ddb_entry)) {
drm_err(&i915->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);
}
}
kfree(hw);
}
bool skl_watermark_ipc_enabled(struct drm_i915_private *i915)
{
return i915->display.wm.ipc_enabled;
@ -3386,31 +3209,19 @@ static void skl_read_wm_latency(struct drm_i915_private *i915, u16 wm[])
static void skl_setup_wm_latency(struct drm_i915_private *i915)
{
if (HAS_HW_SAGV_WM(i915))
i915->display.wm.num_levels = 6;
struct intel_display *display = &i915->display;
if (HAS_HW_SAGV_WM(display))
display->wm.num_levels = 6;
else
i915->display.wm.num_levels = 8;
display->wm.num_levels = 8;
if (DISPLAY_VER(i915) >= 14)
mtl_read_wm_latency(i915, i915->display.wm.skl_latency);
if (DISPLAY_VER(display) >= 14)
mtl_read_wm_latency(i915, display->wm.skl_latency);
else
skl_read_wm_latency(i915, i915->display.wm.skl_latency);
skl_read_wm_latency(i915, display->wm.skl_latency);
intel_print_wm_latency(i915, "Gen9 Plane", i915->display.wm.skl_latency);
}
static const struct intel_wm_funcs skl_wm_funcs = {
.compute_global_watermarks = skl_compute_wm,
.get_hw_state = skl_wm_get_hw_state_and_sanitize,
};
void skl_wm_init(struct drm_i915_private *i915)
{
intel_sagv_init(i915);
skl_setup_wm_latency(i915);
i915->display.funcs.wm = &skl_wm_funcs;
intel_print_wm_latency(i915, "Gen9 Plane", display->wm.skl_latency);
}
static struct intel_global_state *intel_dbuf_duplicate_state(struct intel_global_obj *obj)
@ -3466,38 +3277,27 @@ static bool xelpdp_is_only_pipe_per_dbuf_bank(enum pipe pipe, u8 active_pipes)
{
switch (pipe) {
case PIPE_A:
return !(active_pipes & BIT(PIPE_D));
case PIPE_D:
return !(active_pipes & BIT(PIPE_A));
active_pipes &= BIT(PIPE_A) | BIT(PIPE_D);
break;
case PIPE_B:
return !(active_pipes & BIT(PIPE_C));
case PIPE_C:
return !(active_pipes & BIT(PIPE_B));
active_pipes &= BIT(PIPE_B) | BIT(PIPE_C);
break;
default: /* to suppress compiler warning */
MISSING_CASE(pipe);
break;
return false;
}
return false;
return is_power_of_2(active_pipes);
}
static void intel_mbus_dbox_update(struct intel_atomic_state *state)
static u32 pipe_mbus_dbox_ctl(const struct intel_crtc *crtc,
const struct intel_dbuf_state *dbuf_state)
{
struct drm_i915_private *i915 = to_i915(state->base.dev);
const struct intel_dbuf_state *new_dbuf_state, *old_dbuf_state;
const struct intel_crtc *crtc;
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
u32 val = 0;
if (DISPLAY_VER(i915) < 11)
return;
new_dbuf_state = intel_atomic_get_new_dbuf_state(state);
old_dbuf_state = intel_atomic_get_old_dbuf_state(state);
if (!new_dbuf_state ||
(new_dbuf_state->joined_mbus == old_dbuf_state->joined_mbus &&
new_dbuf_state->active_pipes == old_dbuf_state->active_pipes))
return;
if (DISPLAY_VER(i915) >= 14)
val |= MBUS_DBOX_I_CREDIT(2);
@ -3508,12 +3308,12 @@ static void intel_mbus_dbox_update(struct intel_atomic_state *state)
}
if (DISPLAY_VER(i915) >= 14)
val |= new_dbuf_state->joined_mbus ? MBUS_DBOX_A_CREDIT(12) :
MBUS_DBOX_A_CREDIT(8);
val |= dbuf_state->joined_mbus ?
MBUS_DBOX_A_CREDIT(12) : MBUS_DBOX_A_CREDIT(8);
else if (IS_ALDERLAKE_P(i915))
/* Wa_22010947358:adl-p */
val |= new_dbuf_state->joined_mbus ? MBUS_DBOX_A_CREDIT(6) :
MBUS_DBOX_A_CREDIT(4);
val |= dbuf_state->joined_mbus ?
MBUS_DBOX_A_CREDIT(6) : MBUS_DBOX_A_CREDIT(4);
else
val |= MBUS_DBOX_A_CREDIT(2);
@ -3530,19 +3330,42 @@ static void intel_mbus_dbox_update(struct intel_atomic_state *state)
val |= MBUS_DBOX_B_CREDIT(8);
}
for_each_intel_crtc_in_pipe_mask(&i915->drm, crtc, new_dbuf_state->active_pipes) {
u32 pipe_val = val;
if (DISPLAY_VERx100(i915) == 1400) {
if (xelpdp_is_only_pipe_per_dbuf_bank(crtc->pipe,
new_dbuf_state->active_pipes))
pipe_val |= MBUS_DBOX_BW_8CREDITS_MTL;
else
pipe_val |= MBUS_DBOX_BW_4CREDITS_MTL;
}
intel_de_write(i915, PIPE_MBUS_DBOX_CTL(crtc->pipe), pipe_val);
if (DISPLAY_VERx100(i915) == 1400) {
if (xelpdp_is_only_pipe_per_dbuf_bank(crtc->pipe, dbuf_state->active_pipes))
val |= MBUS_DBOX_BW_8CREDITS_MTL;
else
val |= MBUS_DBOX_BW_4CREDITS_MTL;
}
return val;
}
static void pipe_mbus_dbox_ctl_update(struct drm_i915_private *i915,
const struct intel_dbuf_state *dbuf_state)
{
struct intel_crtc *crtc;
for_each_intel_crtc_in_pipe_mask(&i915->drm, crtc, dbuf_state->active_pipes)
intel_de_write(i915, PIPE_MBUS_DBOX_CTL(crtc->pipe),
pipe_mbus_dbox_ctl(crtc, dbuf_state));
}
static void intel_mbus_dbox_update(struct intel_atomic_state *state)
{
struct drm_i915_private *i915 = to_i915(state->base.dev);
const struct intel_dbuf_state *new_dbuf_state, *old_dbuf_state;
if (DISPLAY_VER(i915) < 11)
return;
new_dbuf_state = intel_atomic_get_new_dbuf_state(state);
old_dbuf_state = intel_atomic_get_old_dbuf_state(state);
if (!new_dbuf_state ||
(new_dbuf_state->joined_mbus == old_dbuf_state->joined_mbus &&
new_dbuf_state->active_pipes == old_dbuf_state->active_pipes))
return;
pipe_mbus_dbox_ctl_update(i915, new_dbuf_state);
}
int intel_dbuf_state_set_mdclk_cdclk_ratio(struct intel_atomic_state *state,
@ -3562,23 +3385,24 @@ int intel_dbuf_state_set_mdclk_cdclk_ratio(struct intel_atomic_state *state,
void intel_dbuf_mdclk_cdclk_ratio_update(struct drm_i915_private *i915,
int ratio, bool joined_mbus)
{
struct intel_display *display = &i915->display;
enum dbuf_slice slice;
if (!HAS_MBUS_JOINING(i915))
if (!HAS_MBUS_JOINING(display))
return;
if (DISPLAY_VER(i915) >= 20)
intel_de_rmw(i915, MBUS_CTL, MBUS_TRANSLATION_THROTTLE_MIN_MASK,
if (DISPLAY_VER(display) >= 20)
intel_de_rmw(display, MBUS_CTL, MBUS_TRANSLATION_THROTTLE_MIN_MASK,
MBUS_TRANSLATION_THROTTLE_MIN(ratio - 1));
if (joined_mbus)
ratio *= 2;
drm_dbg_kms(&i915->drm, "Updating dbuf ratio to %d (mbus joined: %s)\n",
drm_dbg_kms(display->drm, "Updating dbuf ratio to %d (mbus joined: %s)\n",
ratio, str_yes_no(joined_mbus));
for_each_dbuf_slice(i915, slice)
intel_de_rmw(i915, DBUF_CTL_S(slice),
for_each_dbuf_slice(display, slice)
intel_de_rmw(display, DBUF_CTL_S(slice),
DBUF_MIN_TRACKER_STATE_SERVICE_MASK,
DBUF_MIN_TRACKER_STATE_SERVICE(ratio - 1));
}
@ -3625,22 +3449,13 @@ static enum pipe intel_mbus_joined_pipe(struct intel_atomic_state *state,
return INVALID_PIPE;
}
static void intel_dbuf_mbus_join_update(struct intel_atomic_state *state,
enum pipe pipe)
static void mbus_ctl_join_update(struct drm_i915_private *i915,
const struct intel_dbuf_state *dbuf_state,
enum pipe pipe)
{
struct drm_i915_private *i915 = to_i915(state->base.dev);
const struct intel_dbuf_state *old_dbuf_state =
intel_atomic_get_old_dbuf_state(state);
const struct intel_dbuf_state *new_dbuf_state =
intel_atomic_get_new_dbuf_state(state);
u32 mbus_ctl;
drm_dbg_kms(&i915->drm, "Changing mbus joined: %s -> %s (pipe: %c)\n",
str_yes_no(old_dbuf_state->joined_mbus),
str_yes_no(new_dbuf_state->joined_mbus),
pipe != INVALID_PIPE ? pipe_name(pipe) : '*');
if (new_dbuf_state->joined_mbus)
if (dbuf_state->joined_mbus)
mbus_ctl = MBUS_HASHING_MODE_1x4 | MBUS_JOIN;
else
mbus_ctl = MBUS_HASHING_MODE_2x2;
@ -3655,6 +3470,23 @@ static void intel_dbuf_mbus_join_update(struct intel_atomic_state *state,
MBUS_JOIN_PIPE_SELECT_MASK, mbus_ctl);
}
static void intel_dbuf_mbus_join_update(struct intel_atomic_state *state,
enum pipe pipe)
{
struct drm_i915_private *i915 = to_i915(state->base.dev);
const struct intel_dbuf_state *old_dbuf_state =
intel_atomic_get_old_dbuf_state(state);
const struct intel_dbuf_state *new_dbuf_state =
intel_atomic_get_new_dbuf_state(state);
drm_dbg_kms(&i915->drm, "Changing mbus joined: %s -> %s (pipe: %c)\n",
str_yes_no(old_dbuf_state->joined_mbus),
str_yes_no(new_dbuf_state->joined_mbus),
pipe != INVALID_PIPE ? pipe_name(pipe) : '*');
mbus_ctl_join_update(i915, new_dbuf_state, pipe);
}
void intel_dbuf_mbus_pre_ddb_update(struct intel_atomic_state *state)
{
const struct intel_dbuf_state *new_dbuf_state =
@ -3757,6 +3589,243 @@ void intel_dbuf_post_plane_update(struct intel_atomic_state *state)
gen9_dbuf_slices_update(i915, new_slices);
}
static void skl_mbus_sanitize(struct drm_i915_private *i915)
{
struct intel_display *display = &i915->display;
struct intel_dbuf_state *dbuf_state =
to_intel_dbuf_state(display->dbuf.obj.state);
if (!HAS_MBUS_JOINING(display))
return;
if (!dbuf_state->joined_mbus ||
adlp_check_mbus_joined(dbuf_state->active_pipes))
return;
drm_dbg_kms(display->drm, "Disabling redundant MBUS joining (active pipes 0x%x)\n",
dbuf_state->active_pipes);
dbuf_state->joined_mbus = false;
intel_dbuf_mdclk_cdclk_ratio_update(i915,
dbuf_state->mdclk_cdclk_ratio,
dbuf_state->joined_mbus);
pipe_mbus_dbox_ctl_update(i915, dbuf_state);
mbus_ctl_join_update(i915, dbuf_state, INVALID_PIPE);
}
static bool skl_dbuf_is_misconfigured(struct drm_i915_private *i915)
{
const struct intel_dbuf_state *dbuf_state =
to_intel_dbuf_state(i915->display.dbuf.obj.state);
struct skl_ddb_entry entries[I915_MAX_PIPES] = {};
struct intel_crtc *crtc;
for_each_intel_crtc(&i915->drm, crtc) {
const struct intel_crtc_state *crtc_state =
to_intel_crtc_state(crtc->base.state);
entries[crtc->pipe] = crtc_state->wm.skl.ddb;
}
for_each_intel_crtc(&i915->drm, crtc) {
const struct intel_crtc_state *crtc_state =
to_intel_crtc_state(crtc->base.state);
u8 slices;
slices = skl_compute_dbuf_slices(crtc, dbuf_state->active_pipes,
dbuf_state->joined_mbus);
if (dbuf_state->slices[crtc->pipe] & ~slices)
return true;
if (skl_ddb_allocation_overlaps(&crtc_state->wm.skl.ddb, entries,
I915_MAX_PIPES, crtc->pipe))
return true;
}
return false;
}
static void skl_dbuf_sanitize(struct drm_i915_private *i915)
{
struct intel_crtc *crtc;
/*
* On TGL/RKL (at least) the BIOS likes to assign the planes
* to the wrong DBUF slices. This will cause an infinite loop
* in skl_commit_modeset_enables() as it can't find a way to
* transition between the old bogus DBUF layout to the new
* proper DBUF layout without DBUF allocation overlaps between
* the planes (which cannot be allowed or else the hardware
* may hang). If we detect a bogus DBUF layout just turn off
* all the planes so that skl_commit_modeset_enables() can
* simply ignore them.
*/
if (!skl_dbuf_is_misconfigured(i915))
return;
drm_dbg_kms(&i915->drm, "BIOS has misprogrammed the DBUF, disabling all planes\n");
for_each_intel_crtc(&i915->drm, crtc) {
struct intel_plane *plane = to_intel_plane(crtc->base.primary);
const struct intel_plane_state *plane_state =
to_intel_plane_state(plane->base.state);
struct intel_crtc_state *crtc_state =
to_intel_crtc_state(crtc->base.state);
if (plane_state->uapi.visible)
intel_plane_disable_noatomic(crtc, plane);
drm_WARN_ON(&i915->drm, crtc_state->active_planes != 0);
memset(&crtc_state->wm.skl.ddb, 0, sizeof(crtc_state->wm.skl.ddb));
}
}
static void skl_wm_get_hw_state_and_sanitize(struct drm_i915_private *i915)
{
skl_wm_get_hw_state(i915);
skl_mbus_sanitize(i915);
skl_dbuf_sanitize(i915);
}
void intel_wm_state_verify(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
struct intel_display *display = to_intel_display(state);
struct drm_i915_private *i915 = to_i915(state->base.dev);
const struct intel_crtc_state *new_crtc_state =
intel_atomic_get_new_crtc_state(state, crtc);
struct skl_hw_state {
struct skl_ddb_entry ddb[I915_MAX_PLANES];
struct skl_ddb_entry ddb_y[I915_MAX_PLANES];
struct skl_pipe_wm wm;
} *hw;
const struct skl_pipe_wm *sw_wm = &new_crtc_state->wm.skl.optimal;
struct intel_plane *plane;
u8 hw_enabled_slices;
int level;
if (DISPLAY_VER(i915) < 9 || !new_crtc_state->hw.active)
return;
hw = kzalloc(sizeof(*hw), GFP_KERNEL);
if (!hw)
return;
skl_pipe_wm_get_hw_state(crtc, &hw->wm);
skl_pipe_ddb_get_hw_state(crtc, hw->ddb, hw->ddb_y);
hw_enabled_slices = intel_enabled_dbuf_slices_mask(i915);
if (DISPLAY_VER(i915) >= 11 &&
hw_enabled_slices != i915->display.dbuf.enabled_slices)
drm_err(&i915->drm,
"mismatch in DBUF Slices (expected 0x%x, got 0x%x)\n",
i915->display.dbuf.enabled_slices,
hw_enabled_slices);
for_each_intel_plane_on_crtc(&i915->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;
/* Watermarks */
for (level = 0; level < i915->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);
if (skl_wm_level_equals(hw_wm_level, sw_wm_level))
continue;
drm_err(&i915->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);
}
hw_wm_level = &hw->wm.planes[plane->id].trans_wm;
sw_wm_level = skl_plane_trans_wm(sw_wm, plane->id);
if (!skl_wm_level_equals(hw_wm_level, sw_wm_level)) {
drm_err(&i915->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);
}
hw_wm_level = &hw->wm.planes[plane->id].sagv.wm0;
sw_wm_level = &sw_wm->planes[plane->id].sagv.wm0;
if (HAS_HW_SAGV_WM(display) &&
!skl_wm_level_equals(hw_wm_level, sw_wm_level)) {
drm_err(&i915->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(&i915->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_CURSOR];
sw_ddb_entry = &new_crtc_state->wm.skl.plane_ddb[PLANE_CURSOR];
if (!skl_ddb_entry_equal(hw_ddb_entry, sw_ddb_entry)) {
drm_err(&i915->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);
}
}
kfree(hw);
}
static const struct intel_wm_funcs skl_wm_funcs = {
.compute_global_watermarks = skl_compute_wm,
.get_hw_state = skl_wm_get_hw_state_and_sanitize,
};
void skl_wm_init(struct drm_i915_private *i915)
{
intel_sagv_init(i915);
skl_setup_wm_latency(i915);
i915->display.funcs.wm = &skl_wm_funcs;
}
static int skl_watermark_ipc_status_show(struct seq_file *m, void *data)
{
struct drm_i915_private *i915 = m->private;
@ -3830,13 +3899,14 @@ DEFINE_SHOW_ATTRIBUTE(intel_sagv_status);
void skl_watermark_debugfs_register(struct drm_i915_private *i915)
{
struct drm_minor *minor = i915->drm.primary;
struct intel_display *display = &i915->display;
struct drm_minor *minor = display->drm->primary;
if (HAS_IPC(i915))
if (HAS_IPC(display))
debugfs_create_file("i915_ipc_status", 0644, minor->debugfs_root, i915,
&skl_watermark_ipc_status_fops);
if (HAS_SAGV(i915))
if (HAS_SAGV(display))
debugfs_create_file("i915_sagv_status", 0444, minor->debugfs_root, i915,
&intel_sagv_status_fops);
}

@ -87,6 +87,7 @@ void intel_dbuf_mdclk_cdclk_ratio_update(struct drm_i915_private *i915,
int ratio, bool joined_mbus);
void intel_dbuf_mbus_pre_ddb_update(struct intel_atomic_state *state);
void intel_dbuf_mbus_post_ddb_update(struct intel_atomic_state *state);
void intel_program_dpkgc_latency(struct intel_atomic_state *state);
#endif /* __SKL_WATERMARK_H__ */

@ -67,9 +67,8 @@ static u16 pixels_from_txbyteclkhs(u16 clk_hs, int bpp, int lane_count,
(bpp * burst_mode_ratio));
}
enum mipi_dsi_pixel_format pixel_format_from_register_bits(u32 fmt)
static enum mipi_dsi_pixel_format pixel_format_from_register_bits(u32 fmt)
{
/* It just so happens the VBT matches register contents. */
switch (fmt) {
case VID_MODE_FORMAT_RGB888:
return MIPI_DSI_FMT_RGB888;
@ -1760,6 +1759,31 @@ static void vlv_dphy_param_init(struct intel_dsi *intel_dsi)
intel_dsi_log_params(intel_dsi);
}
int vlv_dsi_min_cdclk(const struct intel_crtc_state *crtc_state)
{
struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI))
return 0;
/*
* On Valleyview some DSI panels lose (v|h)sync when the clock is lower
* than 320000KHz.
*/
if (IS_VALLEYVIEW(dev_priv))
return 320000;
/*
* On Geminilake once the CDCLK gets as low as 79200
* picture gets unstable, despite that values are
* correct for DSI PLL and DE PLL.
*/
if (IS_GEMINILAKE(dev_priv))
return 158400;
return 0;
}
typedef void (*vlv_dsi_dmi_quirk_func)(struct intel_dsi *intel_dsi);
/*

@ -6,21 +6,20 @@
#ifndef __VLV_DSI_H__
#define __VLV_DSI_H__
#include <linux/types.h>
enum port;
struct drm_i915_private;
struct intel_crtc_state;
struct intel_dsi;
#ifdef I915
void vlv_dsi_wait_for_fifo_empty(struct intel_dsi *intel_dsi, enum port port);
enum mipi_dsi_pixel_format pixel_format_from_register_bits(u32 fmt);
int vlv_dsi_min_cdclk(const struct intel_crtc_state *crtc_state);
void vlv_dsi_init(struct drm_i915_private *dev_priv);
#else
static inline void vlv_dsi_wait_for_fifo_empty(struct intel_dsi *intel_dsi, enum port port)
{
}
static inline enum mipi_dsi_pixel_format pixel_format_from_register_bits(u32 fmt)
static inline int vlv_dsi_min_cdclk(const struct intel_crtc_state *crtc_state)
{
return 0;
}

@ -283,9 +283,7 @@ bool i915_gem_object_has_iomem(const struct drm_i915_gem_object *obj);
static inline bool
i915_gem_object_is_shrinkable(const struct drm_i915_gem_object *obj)
{
/* TODO: make DPT shrinkable when it has no bound vmas */
return i915_gem_object_type_has(obj, I915_GEM_OBJECT_IS_SHRINKABLE) &&
!obj->is_dpt;
return i915_gem_object_type_has(obj, I915_GEM_OBJECT_IS_SHRINKABLE);
}
static inline bool

@ -107,11 +107,12 @@ int i915_ggtt_init_hw(struct drm_i915_private *i915)
/**
* i915_ggtt_suspend_vm - Suspend the memory mappings for a GGTT or DPT VM
* @vm: The VM to suspend the mappings for
* @evict_all: Evict all VMAs
*
* Suspend the memory mappings for all objects mapped to HW via the GGTT or a
* DPT page table.
*/
void i915_ggtt_suspend_vm(struct i915_address_space *vm)
void i915_ggtt_suspend_vm(struct i915_address_space *vm, bool evict_all)
{
struct i915_vma *vma, *vn;
int save_skip_rewrite;
@ -157,7 +158,7 @@ void i915_ggtt_suspend_vm(struct i915_address_space *vm)
goto retry;
}
if (!i915_vma_is_bound(vma, I915_VMA_GLOBAL_BIND)) {
if (evict_all || !i915_vma_is_bound(vma, I915_VMA_GLOBAL_BIND)) {
i915_vma_wait_for_bind(vma);
__i915_vma_evict(vma, false);
@ -172,13 +173,15 @@ void i915_ggtt_suspend_vm(struct i915_address_space *vm)
vm->skip_pte_rewrite = save_skip_rewrite;
mutex_unlock(&vm->mutex);
drm_WARN_ON(&vm->i915->drm, evict_all && !list_empty(&vm->bound_list));
}
void i915_ggtt_suspend(struct i915_ggtt *ggtt)
{
struct intel_gt *gt;
i915_ggtt_suspend_vm(&ggtt->vm);
i915_ggtt_suspend_vm(&ggtt->vm, false);
ggtt->invalidate(ggtt);
list_for_each_entry(gt, &ggtt->gt_list, ggtt_link)
@ -1545,6 +1548,7 @@ int i915_ggtt_enable_hw(struct drm_i915_private *i915)
/**
* i915_ggtt_resume_vm - Restore the memory mappings for a GGTT or DPT VM
* @vm: The VM to restore the mappings for
* @all_evicted: Were all VMAs expected to be evicted on suspend?
*
* Restore the memory mappings for all objects mapped to HW via the GGTT or a
* DPT page table.
@ -1552,13 +1556,18 @@ int i915_ggtt_enable_hw(struct drm_i915_private *i915)
* Returns %true if restoring the mapping for any object that was in a write
* domain before suspend.
*/
bool i915_ggtt_resume_vm(struct i915_address_space *vm)
bool i915_ggtt_resume_vm(struct i915_address_space *vm, bool all_evicted)
{
struct i915_vma *vma;
bool write_domain_objs = false;
drm_WARN_ON(&vm->i915->drm, !vm->is_ggtt && !vm->is_dpt);
if (all_evicted) {
drm_WARN_ON(&vm->i915->drm, !list_empty(&vm->bound_list));
return false;
}
/* First fill our portion of the GTT with scratch pages */
vm->clear_range(vm, 0, vm->total);
@ -1598,7 +1607,7 @@ void i915_ggtt_resume(struct i915_ggtt *ggtt)
list_for_each_entry(gt, &ggtt->gt_list, ggtt_link)
intel_gt_check_and_clear_faults(gt);
flush = i915_ggtt_resume_vm(&ggtt->vm);
flush = i915_ggtt_resume_vm(&ggtt->vm, false);
if (drm_mm_node_allocated(&ggtt->error_capture))
ggtt->vm.scratch_range(&ggtt->vm, ggtt->error_capture.start,

@ -608,8 +608,8 @@ int i915_ppgtt_init_hw(struct intel_gt *gt);
struct i915_ppgtt *i915_ppgtt_create(struct intel_gt *gt,
unsigned long lmem_pt_obj_flags);
void i915_ggtt_suspend_vm(struct i915_address_space *vm);
bool i915_ggtt_resume_vm(struct i915_address_space *vm);
void i915_ggtt_suspend_vm(struct i915_address_space *vm, bool evict_all);
bool i915_ggtt_resume_vm(struct i915_address_space *vm, bool all_evicted);
void i915_ggtt_suspend(struct i915_ggtt *gtt);
void i915_ggtt_resume(struct i915_ggtt *ggtt);

@ -1198,6 +1198,7 @@ void intel_gt_reset(struct intel_gt *gt,
intel_engine_mask_t stalled_mask,
const char *reason)
{
struct intel_display *display = &gt->i915->display;
intel_engine_mask_t awake;
int ret;
@ -1243,7 +1244,7 @@ void intel_gt_reset(struct intel_gt *gt,
if (INTEL_INFO(gt->i915)->gpu_reset_clobbers_display)
intel_irq_resume(gt->i915);
intel_overlay_reset(gt->i915);
intel_overlay_reset(display);
/* sanitize uC after engine reset */
if (!intel_uc_uses_guc_submission(&gt->uc))

@ -40,6 +40,7 @@
#include "display/bxt_dpio_phy_regs.h"
#include "display/i9xx_plane_regs.h"
#include "display/intel_crt_regs.h"
#include "display/intel_cursor_regs.h"
#include "display/intel_display.h"
#include "display/intel_dpio_phy.h"

@ -45,6 +45,7 @@
#include "intel_mchbar_regs.h"
#include "display/bxt_dpio_phy_regs.h"
#include "display/i9xx_plane_regs.h"
#include "display/intel_crt_regs.h"
#include "display/intel_cursor_regs.h"
#include "display/intel_display_types.h"
#include "display/intel_dmc_regs.h"

@ -45,6 +45,7 @@
#include <drm/drm_managed.h>
#include <drm/drm_probe_helper.h>
#include "display/i9xx_display_sr.h"
#include "display/intel_acpi.h"
#include "display/intel_bw.h"
#include "display/intel_cdclk.h"
@ -60,6 +61,7 @@
#include "display/intel_pch_refclk.h"
#include "display/intel_pps.h"
#include "display/intel_sprite_uapi.h"
#include "display/intel_vga.h"
#include "display/skl_watermark.h"
#include "gem/i915_gem_context.h"
@ -93,7 +95,6 @@
#include "i915_memcpy.h"
#include "i915_perf.h"
#include "i915_query.h"
#include "i915_suspend.h"
#include "i915_switcheroo.h"
#include "i915_sysfs.h"
#include "i915_utils.h"
@ -104,6 +105,8 @@
#include "intel_pci_config.h"
#include "intel_pcode.h"
#include "intel_region_ttm.h"
#include "intel_sbi.h"
#include "vlv_sideband.h"
#include "vlv_suspend.h"
static const struct drm_driver i915_drm_driver;
@ -217,6 +220,7 @@ static void sanitize_gpu(struct drm_i915_private *i915)
*/
static int i915_driver_early_probe(struct drm_i915_private *dev_priv)
{
struct intel_display *display = &dev_priv->display;
int ret = 0;
if (i915_inject_probe_failure(dev_priv))
@ -231,8 +235,9 @@ static int i915_driver_early_probe(struct drm_i915_private *dev_priv)
spin_lock_init(&dev_priv->irq_lock);
spin_lock_init(&dev_priv->gpu_error.lock);
intel_sbi_init(dev_priv);
vlv_iosf_sb_init(dev_priv);
mutex_init(&dev_priv->sb_lock);
cpu_latency_qos_add_request(&dev_priv->sb_qos, PM_QOS_DEFAULT_VALUE);
i915_memcpy_init_early(dev_priv);
intel_runtime_pm_init_early(&dev_priv->runtime_pm);
@ -259,7 +264,7 @@ static int i915_driver_early_probe(struct drm_i915_private *dev_priv)
intel_detect_pch(dev_priv);
intel_irq_init(dev_priv);
intel_display_driver_early_probe(dev_priv);
intel_display_driver_early_probe(display);
intel_clock_gating_hooks_init(dev_priv);
intel_detect_preproduction_hw(dev_priv);
@ -282,16 +287,19 @@ static int i915_driver_early_probe(struct drm_i915_private *dev_priv)
*/
static void i915_driver_late_release(struct drm_i915_private *dev_priv)
{
struct intel_display *display = &dev_priv->display;
intel_irq_fini(dev_priv);
intel_power_domains_cleanup(dev_priv);
intel_power_domains_cleanup(display);
i915_gem_cleanup_early(dev_priv);
intel_gt_driver_late_release_all(dev_priv);
intel_region_ttm_device_fini(dev_priv);
vlv_suspend_cleanup(dev_priv);
i915_workqueues_cleanup(dev_priv);
cpu_latency_qos_remove_request(&dev_priv->sb_qos);
mutex_destroy(&dev_priv->sb_lock);
vlv_iosf_sb_fini(dev_priv);
intel_sbi_fini(dev_priv);
i915_params_free(&dev_priv->params);
}
@ -307,6 +315,7 @@ static void i915_driver_late_release(struct drm_i915_private *dev_priv)
*/
static int i915_driver_mmio_probe(struct drm_i915_private *dev_priv)
{
struct intel_display *display = &dev_priv->display;
struct intel_gt *gt;
int ret, i;
@ -332,7 +341,7 @@ static int i915_driver_mmio_probe(struct drm_i915_private *dev_priv)
/* Try to make sure MCHBAR is enabled before poking at it */
intel_gmch_bar_setup(dev_priv);
intel_device_info_runtime_init(dev_priv);
intel_display_device_info_runtime_init(dev_priv);
intel_display_device_info_runtime_init(display);
for_each_gt(gt, dev_priv, i) {
ret = intel_gt_init_mmio(gt);
@ -599,6 +608,7 @@ static void i915_driver_hw_remove(struct drm_i915_private *dev_priv)
*/
static void i915_driver_register(struct drm_i915_private *dev_priv)
{
struct intel_display *display = &dev_priv->display;
struct intel_gt *gt;
unsigned int i;
@ -627,9 +637,9 @@ static void i915_driver_register(struct drm_i915_private *dev_priv)
i915_hwmon_register(dev_priv);
intel_display_driver_register(dev_priv);
intel_display_driver_register(display);
intel_power_domains_enable(dev_priv);
intel_power_domains_enable(display);
intel_runtime_pm_enable(&dev_priv->runtime_pm);
intel_register_dsm_handler();
@ -644,6 +654,7 @@ static void i915_driver_register(struct drm_i915_private *dev_priv)
*/
static void i915_driver_unregister(struct drm_i915_private *dev_priv)
{
struct intel_display *display = &dev_priv->display;
struct intel_gt *gt;
unsigned int i;
@ -652,9 +663,9 @@ static void i915_driver_unregister(struct drm_i915_private *dev_priv)
intel_unregister_dsm_handler();
intel_runtime_pm_disable(&dev_priv->runtime_pm);
intel_power_domains_disable(dev_priv);
intel_power_domains_disable(display);
intel_display_driver_unregister(dev_priv);
intel_display_driver_unregister(display);
intel_pxp_fini(dev_priv);
@ -731,7 +742,7 @@ i915_driver_create(struct pci_dev *pdev, const struct pci_device_id *ent)
/* Set up device info and initial runtime info. */
intel_device_info_driver_create(i915, pdev->device, match_info);
intel_display_device_probe(i915);
intel_display_device_probe(pdev);
return i915;
}
@ -750,6 +761,7 @@ i915_driver_create(struct pci_dev *pdev, const struct pci_device_id *ent)
int i915_driver_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct drm_i915_private *i915;
struct intel_display *display;
int ret;
ret = pci_enable_device(pdev);
@ -764,6 +776,8 @@ int i915_driver_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
return PTR_ERR(i915);
}
display = &i915->display;
ret = i915_driver_early_probe(i915);
if (ret < 0)
goto out_pci_disable;
@ -784,7 +798,7 @@ int i915_driver_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (ret < 0)
goto out_cleanup_mmio;
ret = intel_display_driver_probe_noirq(i915);
ret = intel_display_driver_probe_noirq(display);
if (ret < 0)
goto out_cleanup_hw;
@ -792,7 +806,7 @@ int i915_driver_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (ret)
goto out_cleanup_modeset;
ret = intel_display_driver_probe_nogem(i915);
ret = intel_display_driver_probe_nogem(display);
if (ret)
goto out_cleanup_irq;
@ -804,7 +818,7 @@ int i915_driver_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (ret && ret != -ENODEV)
drm_dbg(&i915->drm, "pxp init failed with %d\n", ret);
ret = intel_display_driver_probe(i915);
ret = intel_display_driver_probe(display);
if (ret)
goto out_cleanup_gem;
@ -824,14 +838,14 @@ int i915_driver_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
i915_gem_driver_release(i915);
out_cleanup_modeset2:
/* FIXME clean up the error path */
intel_display_driver_remove(i915);
intel_display_driver_remove(display);
intel_irq_uninstall(i915);
intel_display_driver_remove_noirq(i915);
intel_display_driver_remove_noirq(display);
goto out_cleanup_modeset;
out_cleanup_irq:
intel_irq_uninstall(i915);
out_cleanup_modeset:
intel_display_driver_remove_nogem(i915);
intel_display_driver_remove_nogem(display);
out_cleanup_hw:
i915_driver_hw_remove(i915);
intel_memory_regions_driver_release(i915);
@ -851,6 +865,7 @@ int i915_driver_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
void i915_driver_remove(struct drm_i915_private *i915)
{
struct intel_display *display = &i915->display;
intel_wakeref_t wakeref;
wakeref = intel_runtime_pm_get(&i915->runtime_pm);
@ -864,16 +879,16 @@ void i915_driver_remove(struct drm_i915_private *i915)
intel_gvt_driver_remove(i915);
intel_display_driver_remove(i915);
intel_display_driver_remove(display);
intel_irq_uninstall(i915);
intel_display_driver_remove_noirq(i915);
intel_display_driver_remove_noirq(display);
i915_reset_error_state(i915);
i915_gem_driver_remove(i915);
intel_display_driver_remove_nogem(i915);
intel_display_driver_remove_nogem(display);
i915_driver_hw_remove(i915);
@ -883,6 +898,7 @@ void i915_driver_remove(struct drm_i915_private *i915)
static void i915_driver_release(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = to_i915(dev);
struct intel_display *display = &dev_priv->display;
struct intel_runtime_pm *rpm = &dev_priv->runtime_pm;
intel_wakeref_t wakeref;
@ -906,7 +922,7 @@ static void i915_driver_release(struct drm_device *dev)
i915_driver_late_release(dev_priv);
intel_display_device_remove(dev_priv);
intel_display_device_remove(display);
}
static int i915_driver_open(struct drm_device *dev, struct drm_file *file)
@ -936,14 +952,16 @@ static void i915_driver_postclose(struct drm_device *dev, struct drm_file *file)
void i915_driver_shutdown(struct drm_i915_private *i915)
{
struct intel_display *display = &i915->display;
disable_rpm_wakeref_asserts(&i915->runtime_pm);
intel_runtime_pm_disable(&i915->runtime_pm);
intel_power_domains_disable(i915);
intel_power_domains_disable(display);
intel_fbdev_set_suspend(&i915->drm, FBINFO_STATE_SUSPENDED, true);
if (HAS_DISPLAY(i915)) {
drm_kms_helper_poll_disable(&i915->drm);
intel_display_driver_disable_user_access(i915);
intel_display_driver_disable_user_access(display);
drm_atomic_helper_shutdown(&i915->drm);
}
@ -954,7 +972,7 @@ void i915_driver_shutdown(struct drm_i915_private *i915)
intel_hpd_cancel_work(i915);
if (HAS_DISPLAY(i915))
intel_display_driver_suspend_access(i915);
intel_display_driver_suspend_access(display);
intel_encoder_suspend_all(&i915->display);
intel_encoder_shutdown_all(&i915->display);
@ -974,7 +992,7 @@ void i915_driver_shutdown(struct drm_i915_private *i915)
* - unify the driver remove and system/runtime suspend sequences with
* the above unified shutdown/poweroff sequence.
*/
intel_power_domains_driver_remove(i915);
intel_power_domains_driver_remove(display);
enable_rpm_wakeref_asserts(&i915->runtime_pm);
intel_runtime_pm_driver_last_release(&i915->runtime_pm);
@ -1022,24 +1040,22 @@ static int i915_drm_suspend(struct drm_device *dev)
/* We do a lot of poking in a lot of registers, make sure they work
* properly. */
intel_power_domains_disable(dev_priv);
intel_power_domains_disable(display);
intel_fbdev_set_suspend(dev, FBINFO_STATE_SUSPENDED, true);
if (HAS_DISPLAY(dev_priv)) {
drm_kms_helper_poll_disable(dev);
intel_display_driver_disable_user_access(dev_priv);
intel_display_driver_disable_user_access(display);
}
pci_save_state(pdev);
intel_display_driver_suspend(dev_priv);
intel_dp_mst_suspend(dev_priv);
intel_display_driver_suspend(display);
intel_irq_suspend(dev_priv);
intel_hpd_cancel_work(dev_priv);
if (HAS_DISPLAY(dev_priv))
intel_display_driver_suspend_access(dev_priv);
intel_display_driver_suspend_access(display);
intel_encoder_suspend_all(&dev_priv->display);
@ -1047,7 +1063,7 @@ static int i915_drm_suspend(struct drm_device *dev)
intel_dpt_suspend(dev_priv);
i915_ggtt_suspend(to_gt(dev_priv)->ggtt);
i915_save_display(dev_priv);
i9xx_display_sr_save(display);
opregion_target_state = suspend_to_idle(dev_priv) ? PCI_D1 : PCI_D3cold;
intel_opregion_suspend(display, opregion_target_state);
@ -1066,6 +1082,7 @@ static int i915_drm_suspend(struct drm_device *dev)
static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation)
{
struct drm_i915_private *dev_priv = to_i915(dev);
struct intel_display *display = &dev_priv->display;
struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev);
struct intel_runtime_pm *rpm = &dev_priv->runtime_pm;
struct intel_gt *gt;
@ -1081,14 +1098,12 @@ static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation)
for_each_gt(gt, dev_priv, i)
intel_uncore_suspend(gt->uncore);
intel_power_domains_suspend(dev_priv, s2idle);
intel_display_power_suspend_late(dev_priv);
intel_display_power_suspend_late(display, s2idle);
ret = vlv_suspend_complete(dev_priv);
if (ret) {
drm_err(&dev_priv->drm, "Suspend complete failed: %d\n", ret);
intel_power_domains_resume(dev_priv);
intel_display_power_resume_early(display);
goto out;
}
@ -1166,7 +1181,12 @@ static int i915_drm_resume(struct drm_device *dev)
intel_dmc_resume(display);
i915_restore_display(dev_priv);
i9xx_display_sr_restore(display);
intel_vga_redisable(display);
intel_gmbus_reset(display);
intel_pps_unlock_regs_wa(display);
intel_init_pch_refclk(dev_priv);
@ -1188,21 +1208,19 @@ static int i915_drm_resume(struct drm_device *dev)
i915_gem_resume(dev_priv);
intel_display_driver_init_hw(dev_priv);
intel_display_driver_init_hw(display);
intel_clock_gating_init(dev_priv);
if (HAS_DISPLAY(dev_priv))
intel_display_driver_resume_access(dev_priv);
intel_display_driver_resume_access(display);
intel_hpd_init(dev_priv);
/* MST sideband requires HPD interrupts enabled */
intel_dp_mst_resume(dev_priv);
intel_display_driver_resume(dev_priv);
intel_display_driver_resume(display);
if (HAS_DISPLAY(dev_priv)) {
intel_display_driver_enable_user_access(dev_priv);
intel_display_driver_enable_user_access(display);
drm_kms_helper_poll_enable(dev);
}
intel_hpd_poll_disable(dev_priv);
@ -1211,7 +1229,7 @@ static int i915_drm_resume(struct drm_device *dev)
intel_fbdev_set_suspend(dev, FBINFO_STATE_RUNNING, false);
intel_power_domains_enable(dev_priv);
intel_power_domains_enable(display);
intel_gvt_resume(dev_priv);
@ -1223,6 +1241,7 @@ static int i915_drm_resume(struct drm_device *dev)
static int i915_drm_resume_early(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = to_i915(dev);
struct intel_display *display = &dev_priv->display;
struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev);
struct intel_gt *gt;
int ret, i;
@ -1282,9 +1301,7 @@ static int i915_drm_resume_early(struct drm_device *dev)
for_each_gt(gt, dev_priv, i)
intel_gt_resume_early(gt);
intel_display_power_resume_early(dev_priv);
intel_power_domains_resume(dev_priv);
intel_display_power_resume_early(display);
enable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
@ -1486,7 +1503,7 @@ static int intel_runtime_suspend(struct device *kdev)
for_each_gt(gt, dev_priv, i)
intel_uncore_suspend(gt->uncore);
intel_display_power_suspend(dev_priv);
intel_display_power_suspend(display);
ret = vlv_suspend_complete(dev_priv);
if (ret) {
@ -1580,7 +1597,7 @@ static int intel_runtime_resume(struct device *kdev)
drm_dbg(&dev_priv->drm,
"Unclaimed access during suspend, bios?\n");
intel_display_power_resume(dev_priv);
intel_display_power_resume(display);
ret = vlv_resume_prepare(dev_priv, true);

@ -101,14 +101,6 @@ struct i915_dsm {
resource_size_t usable_size;
};
struct i915_suspend_saved_registers {
u32 saveDSPARB;
u32 saveSWF0[16];
u32 saveSWF1[16];
u32 saveSWF3[3];
u16 saveGCDGMBUS;
};
#define MAX_L3_SLICES 2
struct intel_l3_parity {
u32 *remap_info[MAX_L3_SLICES];
@ -236,9 +228,17 @@ struct drm_i915_private {
spinlock_t irq_lock;
bool irqs_enabled;
/* LPT/WPT IOSF sideband protection */
struct mutex sbi_lock;
/* VLV/CHV IOSF sideband */
struct {
struct mutex lock; /* protect sideband access */
struct pm_qos_request qos;
} vlv_iosf_sb;
/* Sideband mailbox protection */
struct mutex sb_lock;
struct pm_qos_request sb_qos;
/** Cached value of IMR to avoid reads in updating the bitfield */
u32 irq_mask;
@ -291,7 +291,6 @@ struct drm_i915_private {
struct i915_gpu_error gpu_error;
u32 suspend_count;
struct i915_suspend_saved_registers regfile;
struct vlv_s0ix_state *vlv_s0ix_state;
struct dram_info {

@ -71,7 +71,7 @@ void i915_gem_gtt_finish_pages(struct drm_i915_gem_object *obj,
* i915_gem_gtt_reserve - reserve a node in an address_space (GTT)
* @vm: the &struct i915_address_space
* @ww: An optional struct i915_gem_ww_ctx.
* @node: the &struct drm_mm_node (typically i915_vma.mode)
* @node: the &struct drm_mm_node (typically i915_vma.node)
* @size: how much space to allocate inside the GTT,
* must be #I915_GTT_PAGE_SIZE aligned
* @offset: where to insert inside the GTT,

@ -2,9 +2,9 @@
* SPDX-License-Identifier: MIT
*/
#include "display/intel_overlay.h"
#include "gem/i915_gem_mman.h"
#include "gt/intel_engine_user.h"
#include "pxp/intel_pxp.h"
#include "i915_cmd_parser.h"
@ -16,6 +16,7 @@ int i915_getparam_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
struct drm_i915_private *i915 = to_i915(dev);
struct intel_display *display = &i915->display;
struct pci_dev *pdev = to_pci_dev(dev->dev);
const struct sseu_dev_info *sseu = &to_gt(i915)->info.sseu;
drm_i915_getparam_t *param = data;
@ -38,7 +39,7 @@ int i915_getparam_ioctl(struct drm_device *dev, void *data,
value = to_gt(i915)->ggtt->num_fences;
break;
case I915_PARAM_HAS_OVERLAY:
value = !!i915->display.overlay;
value = intel_overlay_available(display);
break;
case I915_PARAM_HAS_BSD:
value = !!intel_engine_lookup_user(i915,

@ -658,8 +658,7 @@ static void valleyview_irq_reset(struct drm_i915_private *dev_priv)
gen5_gt_irq_reset(to_gt(dev_priv));
spin_lock_irq(&dev_priv->irq_lock);
if (dev_priv->display.irq.display_irqs_enabled)
vlv_display_irq_reset(dev_priv);
vlv_display_irq_reset(dev_priv);
spin_unlock_irq(&dev_priv->irq_lock);
}
@ -723,8 +722,7 @@ static void cherryview_irq_reset(struct drm_i915_private *dev_priv)
gen2_irq_reset(uncore, GEN8_PCU_IRQ_REGS);
spin_lock_irq(&dev_priv->irq_lock);
if (dev_priv->display.irq.display_irqs_enabled)
vlv_display_irq_reset(dev_priv);
vlv_display_irq_reset(dev_priv);
spin_unlock_irq(&dev_priv->irq_lock);
}
@ -740,8 +738,7 @@ static void valleyview_irq_postinstall(struct drm_i915_private *dev_priv)
gen5_gt_irq_postinstall(to_gt(dev_priv));
spin_lock_irq(&dev_priv->irq_lock);
if (dev_priv->display.irq.display_irqs_enabled)
vlv_display_irq_postinstall(dev_priv);
vlv_display_irq_postinstall(dev_priv);
spin_unlock_irq(&dev_priv->irq_lock);
intel_uncore_write(&dev_priv->uncore, VLV_MASTER_IER, MASTER_INTERRUPT_ENABLE);
@ -794,8 +791,7 @@ static void cherryview_irq_postinstall(struct drm_i915_private *dev_priv)
gen8_gt_irq_postinstall(to_gt(dev_priv));
spin_lock_irq(&dev_priv->irq_lock);
if (dev_priv->display.irq.display_irqs_enabled)
vlv_display_irq_postinstall(dev_priv);
vlv_display_irq_postinstall(dev_priv);
spin_unlock_irq(&dev_priv->irq_lock);
intel_uncore_write(&dev_priv->uncore, GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL);

@ -1147,53 +1147,6 @@
#define _TRANS_MULT_B 0x6102c
#define TRANS_MULT(dev_priv, trans) _MMIO_TRANS2(dev_priv, (trans), _TRANS_MULT_A)
/* VGA port control */
#define ADPA _MMIO(0x61100)
#define PCH_ADPA _MMIO(0xe1100)
#define VLV_ADPA _MMIO(VLV_DISPLAY_BASE + 0x61100)
#define ADPA_DAC_ENABLE (1 << 31)
#define ADPA_DAC_DISABLE 0
#define ADPA_PIPE_SEL_SHIFT 30
#define ADPA_PIPE_SEL_MASK (1 << 30)
#define ADPA_PIPE_SEL(pipe) ((pipe) << 30)
#define ADPA_PIPE_SEL_SHIFT_CPT 29
#define ADPA_PIPE_SEL_MASK_CPT (3 << 29)
#define ADPA_PIPE_SEL_CPT(pipe) ((pipe) << 29)
#define ADPA_CRT_HOTPLUG_MASK 0x03ff0000 /* bit 25-16 */
#define ADPA_CRT_HOTPLUG_MONITOR_NONE (0 << 24)
#define ADPA_CRT_HOTPLUG_MONITOR_MASK (3 << 24)
#define ADPA_CRT_HOTPLUG_MONITOR_COLOR (3 << 24)
#define ADPA_CRT_HOTPLUG_MONITOR_MONO (2 << 24)
#define ADPA_CRT_HOTPLUG_ENABLE (1 << 23)
#define ADPA_CRT_HOTPLUG_PERIOD_64 (0 << 22)
#define ADPA_CRT_HOTPLUG_PERIOD_128 (1 << 22)
#define ADPA_CRT_HOTPLUG_WARMUP_5MS (0 << 21)
#define ADPA_CRT_HOTPLUG_WARMUP_10MS (1 << 21)
#define ADPA_CRT_HOTPLUG_SAMPLE_2S (0 << 20)
#define ADPA_CRT_HOTPLUG_SAMPLE_4S (1 << 20)
#define ADPA_CRT_HOTPLUG_VOLTAGE_40 (0 << 18)
#define ADPA_CRT_HOTPLUG_VOLTAGE_50 (1 << 18)
#define ADPA_CRT_HOTPLUG_VOLTAGE_60 (2 << 18)
#define ADPA_CRT_HOTPLUG_VOLTAGE_70 (3 << 18)
#define ADPA_CRT_HOTPLUG_VOLREF_325MV (0 << 17)
#define ADPA_CRT_HOTPLUG_VOLREF_475MV (1 << 17)
#define ADPA_CRT_HOTPLUG_FORCE_TRIGGER (1 << 16)
#define ADPA_USE_VGA_HVPOLARITY (1 << 15)
#define ADPA_SETS_HVPOLARITY 0
#define ADPA_VSYNC_CNTL_DISABLE (1 << 10)
#define ADPA_VSYNC_CNTL_ENABLE 0
#define ADPA_HSYNC_CNTL_DISABLE (1 << 11)
#define ADPA_HSYNC_CNTL_ENABLE 0
#define ADPA_VSYNC_ACTIVE_HIGH (1 << 4)
#define ADPA_VSYNC_ACTIVE_LOW 0
#define ADPA_HSYNC_ACTIVE_HIGH (1 << 3)
#define ADPA_HSYNC_ACTIVE_LOW 0
#define ADPA_DPMS_MASK (~(3 << 10))
#define ADPA_DPMS_ON (0 << 10)
#define ADPA_DPMS_SUSPEND (1 << 10)
#define ADPA_DPMS_STANDBY (2 << 10)
#define ADPA_DPMS_OFF (3 << 10)
/* Hotplug control (945+ only) */
#define PORT_HOTPLUG_EN(dev_priv) _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x61110)
#define PORTB_HOTPLUG_INT_EN (1 << 29)
@ -2802,7 +2755,7 @@
#define _CHICKEN_TRANS_C 0x420c8
#define _CHICKEN_TRANS_EDP 0x420cc
#define _CHICKEN_TRANS_D 0x420d8
#define CHICKEN_TRANS(trans) _MMIO(_PICK((trans), \
#define _CHICKEN_TRANS(trans) _MMIO(_PICK((trans), \
[TRANSCODER_EDP] = _CHICKEN_TRANS_EDP, \
[TRANSCODER_A] = _CHICKEN_TRANS_A, \
[TRANSCODER_B] = _CHICKEN_TRANS_B, \
@ -2810,9 +2763,10 @@
[TRANSCODER_D] = _CHICKEN_TRANS_D))
#define _MTL_CHICKEN_TRANS_A 0x604e0
#define _MTL_CHICKEN_TRANS_B 0x614e0
#define MTL_CHICKEN_TRANS(trans) _MMIO_TRANS((trans), \
#define _MTL_CHICKEN_TRANS(trans) _MMIO_TRANS((trans), \
_MTL_CHICKEN_TRANS_A, \
_MTL_CHICKEN_TRANS_B)
#define CHICKEN_TRANS(display, trans) (DISPLAY_VER(display) >= 14 ? _MTL_CHICKEN_TRANS(trans) : _CHICKEN_TRANS(trans))
#define PIPE_VBLANK_WITH_DELAY REG_BIT(31) /* tgl+ */
#define SKL_UNMASK_VBL_TO_PIPE_IN_SRD REG_BIT(30) /* skl+ */
#define HSW_FRAME_START_DELAY_MASK REG_GENMASK(28, 27)
@ -2863,11 +2817,16 @@
#define RESET_PCH_HANDSHAKE_ENABLE REG_BIT(4)
#define GEN8_CHICKEN_DCPR_1 _MMIO(0x46430)
#define LATENCY_REPORTING_REMOVED_PIPE_D REG_BIT(31)
#define _LATENCY_REPORTING_REMOVED_PIPE_D REG_BIT(31)
#define SKL_SELECT_ALTERNATE_DC_EXIT REG_BIT(30)
#define LATENCY_REPORTING_REMOVED_PIPE_C REG_BIT(25)
#define LATENCY_REPORTING_REMOVED_PIPE_B REG_BIT(24)
#define LATENCY_REPORTING_REMOVED_PIPE_A REG_BIT(23)
#define _LATENCY_REPORTING_REMOVED_PIPE_C REG_BIT(25)
#define _LATENCY_REPORTING_REMOVED_PIPE_B REG_BIT(24)
#define _LATENCY_REPORTING_REMOVED_PIPE_A REG_BIT(23)
#define LATENCY_REPORTING_REMOVED(pipe) _PICK((pipe), \
_LATENCY_REPORTING_REMOVED_PIPE_A, \
_LATENCY_REPORTING_REMOVED_PIPE_B, \
_LATENCY_REPORTING_REMOVED_PIPE_C, \
_LATENCY_REPORTING_REMOVED_PIPE_D)
#define ICL_DELAY_PMRSP REG_BIT(22)
#define DISABLE_FLR_SRC REG_BIT(15)
#define MASK_WAKEMEM REG_BIT(13)
@ -3819,6 +3778,7 @@ enum skl_power_gate {
#define TRANS_DDI_PVSYNC (1 << 17)
#define TRANS_DDI_PHSYNC (1 << 16)
#define TRANS_DDI_PORT_SYNC_ENABLE REG_BIT(15)
#define XE3_TRANS_DDI_HDCP_LINE_REKEY_DISABLE REG_BIT(15)
#define TRANS_DDI_EDP_INPUT_MASK (7 << 12)
#define TRANS_DDI_EDP_INPUT_A_ON (0 << 12)
#define TRANS_DDI_EDP_INPUT_A_ONOFF (4 << 12)
@ -3863,25 +3823,26 @@ enum skl_power_gate {
#define _TGL_DP_TP_CTL_A 0x60540
#define DP_TP_CTL(port) _MMIO_PORT(port, _DP_TP_CTL_A, _DP_TP_CTL_B)
#define TGL_DP_TP_CTL(dev_priv, tran) _MMIO_TRANS2(dev_priv, (tran), _TGL_DP_TP_CTL_A)
#define DP_TP_CTL_ENABLE (1 << 31)
#define DP_TP_CTL_FEC_ENABLE (1 << 30)
#define DP_TP_CTL_MODE_SST (0 << 27)
#define DP_TP_CTL_MODE_MST (1 << 27)
#define DP_TP_CTL_FORCE_ACT (1 << 25)
#define DP_TP_CTL_TRAIN_PAT4_SEL_MASK (3 << 19)
#define DP_TP_CTL_TRAIN_PAT4_SEL_TP4A (0 << 19)
#define DP_TP_CTL_TRAIN_PAT4_SEL_TP4B (1 << 19)
#define DP_TP_CTL_TRAIN_PAT4_SEL_TP4C (2 << 19)
#define DP_TP_CTL_ENHANCED_FRAME_ENABLE (1 << 18)
#define DP_TP_CTL_FDI_AUTOTRAIN (1 << 15)
#define DP_TP_CTL_LINK_TRAIN_MASK (7 << 8)
#define DP_TP_CTL_LINK_TRAIN_PAT1 (0 << 8)
#define DP_TP_CTL_LINK_TRAIN_PAT2 (1 << 8)
#define DP_TP_CTL_LINK_TRAIN_PAT3 (4 << 8)
#define DP_TP_CTL_LINK_TRAIN_PAT4 (5 << 8)
#define DP_TP_CTL_LINK_TRAIN_IDLE (2 << 8)
#define DP_TP_CTL_LINK_TRAIN_NORMAL (3 << 8)
#define DP_TP_CTL_SCRAMBLE_DISABLE (1 << 7)
#define DP_TP_CTL_ENABLE REG_BIT(31)
#define DP_TP_CTL_FEC_ENABLE REG_BIT(30)
#define DP_TP_CTL_MODE_MASK REG_BIT(27)
#define DP_TP_CTL_MODE_SST REG_FIELD_PREP(DP_TP_CTL_MODE_MASK, 0)
#define DP_TP_CTL_MODE_MST REG_FIELD_PREP(DP_TP_CTL_MODE_MASK, 1)
#define DP_TP_CTL_FORCE_ACT REG_BIT(25)
#define DP_TP_CTL_TRAIN_PAT4_SEL_MASK REG_GENMASK(20, 19)
#define DP_TP_CTL_TRAIN_PAT4_SEL_TP4A REG_FIELD_PREP(DP_TP_CTL_TRAIN_PAT4_SEL_MASK, 0)
#define DP_TP_CTL_TRAIN_PAT4_SEL_TP4B REG_FIELD_PREP(DP_TP_CTL_TRAIN_PAT4_SEL_MASK, 1)
#define DP_TP_CTL_TRAIN_PAT4_SEL_TP4C REG_FIELD_PREP(DP_TP_CTL_TRAIN_PAT4_SEL_MASK, 2)
#define DP_TP_CTL_ENHANCED_FRAME_ENABLE REG_BIT(18)
#define DP_TP_CTL_FDI_AUTOTRAIN REG_BIT(15)
#define DP_TP_CTL_LINK_TRAIN_MASK REG_GENMASK(10, 8)
#define DP_TP_CTL_LINK_TRAIN_PAT1 REG_FIELD_PREP(DP_TP_CTL_LINK_TRAIN_MASK, 0)
#define DP_TP_CTL_LINK_TRAIN_PAT2 REG_FIELD_PREP(DP_TP_CTL_LINK_TRAIN_MASK, 1)
#define DP_TP_CTL_LINK_TRAIN_PAT3 REG_FIELD_PREP(DP_TP_CTL_LINK_TRAIN_MASK, 4)
#define DP_TP_CTL_LINK_TRAIN_PAT4 REG_FIELD_PREP(DP_TP_CTL_LINK_TRAIN_MASK, 5)
#define DP_TP_CTL_LINK_TRAIN_IDLE REG_FIELD_PREP(DP_TP_CTL_LINK_TRAIN_MASK, 2)
#define DP_TP_CTL_LINK_TRAIN_NORMAL REG_FIELD_PREP(DP_TP_CTL_LINK_TRAIN_MASK, 3)
#define DP_TP_CTL_SCRAMBLE_DISABLE REG_BIT(7)
/* DisplayPort Transport Status */
#define _DP_TP_STATUS_A 0x64044
@ -3889,14 +3850,15 @@ enum skl_power_gate {
#define _TGL_DP_TP_STATUS_A 0x60544
#define DP_TP_STATUS(port) _MMIO_PORT(port, _DP_TP_STATUS_A, _DP_TP_STATUS_B)
#define TGL_DP_TP_STATUS(dev_priv, tran) _MMIO_TRANS2(dev_priv, (tran), _TGL_DP_TP_STATUS_A)
#define DP_TP_STATUS_FEC_ENABLE_LIVE (1 << 28)
#define DP_TP_STATUS_IDLE_DONE (1 << 25)
#define DP_TP_STATUS_ACT_SENT (1 << 24)
#define DP_TP_STATUS_MODE_STATUS_MST (1 << 23)
#define DP_TP_STATUS_AUTOTRAIN_DONE (1 << 12)
#define DP_TP_STATUS_PAYLOAD_MAPPING_VC2 (3 << 8)
#define DP_TP_STATUS_PAYLOAD_MAPPING_VC1 (3 << 4)
#define DP_TP_STATUS_PAYLOAD_MAPPING_VC0 (3 << 0)
#define DP_TP_STATUS_FEC_ENABLE_LIVE REG_BIT(28)
#define DP_TP_STATUS_IDLE_DONE REG_BIT(25)
#define DP_TP_STATUS_ACT_SENT REG_BIT(24)
#define DP_TP_STATUS_MODE_STATUS_MST REG_BIT(23)
#define DP_TP_STATUS_STREAMS_ENABLED_MASK REG_GENMASK(18, 16) /* 17:16 on hsw but bit 18 mbz */
#define DP_TP_STATUS_AUTOTRAIN_DONE REG_BIT(12)
#define DP_TP_STATUS_PAYLOAD_MAPPING_VC2_MASK REG_GENMASK(9, 8)
#define DP_TP_STATUS_PAYLOAD_MAPPING_VC1_MASK REG_GENMASK(5, 4)
#define DP_TP_STATUS_PAYLOAD_MAPPING_VC0_MASK REG_GENMASK(1, 0)
/* DDI Buffer Control */
#define _DDI_BUF_CTL_A 0x64000

@ -1,141 +0,0 @@
/*
*
* Copyright 2008 (c) Intel Corporation
* Jesse Barnes <jbarnes@virtuousgeek.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "display/intel_de.h"
#include "display/intel_gmbus.h"
#include "display/intel_vga.h"
#include "i915_drv.h"
#include "i915_reg.h"
#include "i915_suspend.h"
#include "intel_pci_config.h"
static void intel_save_swf(struct drm_i915_private *dev_priv)
{
int i;
/* Scratch space */
if (GRAPHICS_VER(dev_priv) == 2 && IS_MOBILE(dev_priv)) {
for (i = 0; i < 7; i++) {
dev_priv->regfile.saveSWF0[i] = intel_de_read(dev_priv,
SWF0(dev_priv, i));
dev_priv->regfile.saveSWF1[i] = intel_de_read(dev_priv,
SWF1(dev_priv, i));
}
for (i = 0; i < 3; i++)
dev_priv->regfile.saveSWF3[i] = intel_de_read(dev_priv,
SWF3(dev_priv, i));
} else if (GRAPHICS_VER(dev_priv) == 2) {
for (i = 0; i < 7; i++)
dev_priv->regfile.saveSWF1[i] = intel_de_read(dev_priv,
SWF1(dev_priv, i));
} else if (HAS_GMCH(dev_priv)) {
for (i = 0; i < 16; i++) {
dev_priv->regfile.saveSWF0[i] = intel_de_read(dev_priv,
SWF0(dev_priv, i));
dev_priv->regfile.saveSWF1[i] = intel_de_read(dev_priv,
SWF1(dev_priv, i));
}
for (i = 0; i < 3; i++)
dev_priv->regfile.saveSWF3[i] = intel_de_read(dev_priv,
SWF3(dev_priv, i));
}
}
static void intel_restore_swf(struct drm_i915_private *dev_priv)
{
int i;
/* Scratch space */
if (GRAPHICS_VER(dev_priv) == 2 && IS_MOBILE(dev_priv)) {
for (i = 0; i < 7; i++) {
intel_de_write(dev_priv, SWF0(dev_priv, i),
dev_priv->regfile.saveSWF0[i]);
intel_de_write(dev_priv, SWF1(dev_priv, i),
dev_priv->regfile.saveSWF1[i]);
}
for (i = 0; i < 3; i++)
intel_de_write(dev_priv, SWF3(dev_priv, i),
dev_priv->regfile.saveSWF3[i]);
} else if (GRAPHICS_VER(dev_priv) == 2) {
for (i = 0; i < 7; i++)
intel_de_write(dev_priv, SWF1(dev_priv, i),
dev_priv->regfile.saveSWF1[i]);
} else if (HAS_GMCH(dev_priv)) {
for (i = 0; i < 16; i++) {
intel_de_write(dev_priv, SWF0(dev_priv, i),
dev_priv->regfile.saveSWF0[i]);
intel_de_write(dev_priv, SWF1(dev_priv, i),
dev_priv->regfile.saveSWF1[i]);
}
for (i = 0; i < 3; i++)
intel_de_write(dev_priv, SWF3(dev_priv, i),
dev_priv->regfile.saveSWF3[i]);
}
}
void i915_save_display(struct drm_i915_private *dev_priv)
{
struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev);
if (!HAS_DISPLAY(dev_priv))
return;
/* Display arbitration control */
if (GRAPHICS_VER(dev_priv) <= 4)
dev_priv->regfile.saveDSPARB = intel_de_read(dev_priv,
DSPARB(dev_priv));
if (GRAPHICS_VER(dev_priv) == 4)
pci_read_config_word(pdev, GCDGMBUS,
&dev_priv->regfile.saveGCDGMBUS);
intel_save_swf(dev_priv);
}
void i915_restore_display(struct drm_i915_private *dev_priv)
{
struct intel_display *display = &dev_priv->display;
struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev);
if (!HAS_DISPLAY(dev_priv))
return;
intel_restore_swf(dev_priv);
if (GRAPHICS_VER(dev_priv) == 4)
pci_write_config_word(pdev, GCDGMBUS,
dev_priv->regfile.saveGCDGMBUS);
/* Display arbitration */
if (GRAPHICS_VER(dev_priv) <= 4)
intel_de_write(dev_priv, DSPARB(dev_priv),
dev_priv->regfile.saveDSPARB);
intel_vga_redisable(display);
intel_gmbus_reset(display);
}

@ -1,14 +0,0 @@
/* SPDX-License-Identifier: MIT */
/*
* Copyright © 2019 Intel Corporation
*/
#ifndef __I915_SUSPEND_H__
#define __I915_SUSPEND_H__
struct drm_i915_private;
void i915_save_display(struct drm_i915_private *i915);
void i915_restore_display(struct drm_i915_private *i915);
#endif /* __I915_SUSPEND_H__ */

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