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:
commit
9cc06dbaf4
@ -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)
|
||||
|
||||
95
drivers/gpu/drm/i915/display/i9xx_display_sr.c
Normal file
95
drivers/gpu/drm/i915/display/i9xx_display_sr.c
Normal file
@ -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);
|
||||
}
|
||||
14
drivers/gpu/drm/i915/display/i9xx_display_sr.h
Normal file
14
drivers/gpu/drm/i915/display/i9xx_display_sr.h
Normal file
@ -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
|
||||
|
||||
48
drivers/gpu/drm/i915/display/intel_crt_regs.h
Normal file
48
drivers/gpu/drm/i915/display/intel_crt_regs.h
Normal file
@ -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(¤t_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), \
|
||||
¤t_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, ®s->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, ®s);
|
||||
@ -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 = >->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(>->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
Loading…
Reference in New Issue
Block a user